提交 2649e5ad 作者: 龚洪江

Merge branch 'master' into develop

...@@ -30,7 +30,7 @@ pnpm-debug.log* ...@@ -30,7 +30,7 @@ pnpm-debug.log*
pnpm-lock.yaml* pnpm-lock.yaml*
yarn-lock.yaml* yarn-lock.yaml*
package-lock.yaml* package-lock.yaml*
#package-lock.json #package-lock.json*
#yarn.lock #yarn.lock*
tsconfig.tsbuildinfo* tsconfig.tsbuildinfo*
...@@ -32,11 +32,11 @@ ...@@ -32,11 +32,11 @@
"query-string": "^8.1.0", "query-string": "^8.1.0",
"react": "^18.1.0", "react": "^18.1.0",
"react-dom": "^18.1.0", "react-dom": "^18.1.0",
"react-quill": "^2.0.0",
"react-redux": "^8.0.5", "react-redux": "^8.0.5",
"react-router-dom": "^6.10.0", "react-router-dom": "^6.10.0",
"react-viewer": "^3.2.2", "react-viewer": "^3.2.2",
"sort-by": "^1.2.0", "sort-by": "^1.2.0",
"wangeditor": "^4.7.15",
"xlsx": "^0.18.5" "xlsx": "^0.18.5"
}, },
"devDependencies": { "devDependencies": {
......
...@@ -9,6 +9,7 @@ import { MakeManageAPI } from './modules/makeManage'; ...@@ -9,6 +9,7 @@ import { MakeManageAPI } from './modules/makeManage';
import { CategoryManageAPI } from './modules/categoryManage'; import { CategoryManageAPI } from './modules/categoryManage';
import { SystemManageAPI } from './modules/systemManage'; import { SystemManageAPI } from './modules/systemManage';
import { CustomManageAPI } from './modules/customManage'; import { CustomManageAPI } from './modules/customManage';
import { MallManageAPI } from './modules/mallManage';
export { export {
CommonAPI, CommonAPI,
...@@ -22,4 +23,5 @@ export { ...@@ -22,4 +23,5 @@ export {
CategoryManageAPI, CategoryManageAPI,
SystemManageAPI, SystemManageAPI,
CustomManageAPI, CustomManageAPI,
MallManageAPI,
}; };
...@@ -48,6 +48,15 @@ export type categoryListType = InterItemFunction< ...@@ -48,6 +48,15 @@ export type categoryListType = InterItemFunction<
{ directoryId?: number; type?: number }, { directoryId?: number; type?: number },
categoryReposeType[] categoryReposeType[]
>; >;
//目录列表类型-分页
export type directoryPageListType = InterItemFunction<
{ type?: number },
{
id: number;
directoryName: string;
type: number;
}[]
>;
//目录列表类型-不分页 //目录列表类型-不分页
export type directoryListType = InterFunction< export type directoryListType = InterFunction<
{ type: number }, { type: number },
......
...@@ -14,4 +14,4 @@ export type BackEndLoginType = InterFunction< ...@@ -14,4 +14,4 @@ export type BackEndLoginType = InterFunction<
} }
>; >;
// 上传图片 // 上传图片
export type uploadOssType = InterFunction<any, NonNullable<unknown>>; export type uploadOssType = InterFunction<any, { filePath: string }>;
import { InterListFunction } from '~/api/interface'; import { InterFunction, InterListFunction } from '~/api/interface';
// 客户列表 // 客户列表
export type listAppUserType = InterListFunction< export type listAppUserType = InterListFunction<
...@@ -26,8 +26,52 @@ export type listAppUserType = InterListFunction< ...@@ -26,8 +26,52 @@ export type listAppUserType = InterListFunction<
portType: number; portType: number;
createTime: string; createTime: string;
companyAuthStatus: number; companyAuthStatus: number;
cooperationTagId: null; cooperationTagId: number;
companyName: null; companyName: null;
tagName: null; tagName: null;
} }
>; >;
// 加盟标签列表
export type CompanyListTag = InterFunction<
NonNullable<unknown>,
{
id: number;
tagName: string;
tagImg: null;
tagDescription: string;
createTime: string;
}[]
>;
// 修改用户信息
export type userAccountUpdateType = InterFunction<
{
accountNo?: string;
accountStatus?: number;
accountType?: number;
companyAuthStatus?: number;
companyName?: string;
cooperationTagId?: number;
createTime?: string;
email?: string;
id: number;
nickName?: string;
phoneNum?: string;
portType?: number;
remark?: string;
source?: number;
tagName?: string;
uid?: string;
userImg?: string;
userName?: string;
userSex?: number;
},
NonNullable<unknown>
>;
// 后台设置小程序用户标签
export type changeUserTagType = InterFunction<
{
cooperationTagId: number;
userAccountId: number;
},
NonNullable<unknown>
>;
import { UploadFile } from 'antd/es/upload/interface';
// 商城-新增商品
import { InterFunction, InterItemFunction } from '~/api/interface';
//商品列表
export type listGoodsType = InterItemFunction<
{
directoryId?: number;
goodsName?: string;
goodsType: number;
status?: number;
startTime?: string;
endTime?: string;
},
{
createTime: string;
directoryId: number;
directoryName: string;
goodsDesc: string;
goodsName: string;
imgUrl: string;
isCoupons: number;
status: number;
}[]
>;
//商品-新增
export type BaseInfoType = {
goodsName: string;
goodsDesc: string;
directoryId: number;
tag: string;
shelfStatus: number;
categoryByOne: number;
categoryByTwo: number;
images: { id: number; imgType: number; imgUrl: string }[];
goodsVideo: string;
};
// 库存规格
export interface specEntity {
id: number;
categoryId: number | string;
goodsSpecName: string;
skuId: number;
specIds: any;
chooseType: number;
must: number;
skuUnitId: number;
customizeInfo?: customizeEntity[];
productSpecList?: customizeEntity[];
industrySpecList?: any;
isCustomProd: boolean;
skuName?: string;
flag: number;
productName?: string;
}
// 自定义规格
export interface customizeEntity {
id: number;
partNo: string;
specName: string;
specImage?: string;
fileList?: UploadFile[];
productSpecCPQVO?: any;
productSpec?: number;
}
export type addGoodsType = InterFunction<
BaseInfoType & {
productSpec: specEntity[];
goodsDetailVO: { goodsDesc: string; productDesc?: string };
otherService: number[];
},
any
>;
//商品-编辑
export type editGoodsType = InterFunction<
BaseInfoType & {
productSpec: specEntity[];
goodsDetailVO: { goodsDesc: string; productDesc?: string };
otherService: number[];
id: number;
},
any
>;
//商品-详情
export type detailGoodsType = InterFunction<
{ goodsInfoId: number; type: number; leaseTerm?: number },
BaseInfoType & {
goodsSpec: specEntity[];
goodsDetail: { goodsDesc: string; productDesc: string; content: string };
otherService: { id: number; saleServiceName: string; saleServiceId: number }[];
goodsVideoId: number;
id: number;
}
>;
//商品-其它服务列表
export type otherServiceType = InterFunction<any, { id: number; saleServiceName: string }[]>;
//商品-规格单位
export type skuUnitType = InterFunction<any, { id: number; unitName: string }[]>;
//商品-批量上下架
export type batchOnShelfOrTakeDownType = InterFunction<{ goodsIds: number[]; status: number }, any>;
//商品批量删除
export type batchRemoveWareInfoType = InterFunction<number[], any>;
import { InterFunction, InterListFunction } from '~/api/interface';
// V1.0.1课程视频列表
export type queryCurriculumInfoListType = InterListFunction<
{
curriculumName?: string;
flightSkillsId?: number;
licenseId?: number;
regionId?: number;
},
{
curriculumDesc: string;
curriculumName: string;
detailContent: null;
flightSkills: number;
flightSkillsName1: string;
flightSkillsName2: string;
free: number;
id: number;
price: null;
supplierName: string;
surfaceUrl: null;
videoUrl: string;
}
>;
// V1.0.1新增课程
export type addCurriculumType = InterFunction<
{
curriculumDesc?: string;
curriculumName?: string;
detailContent?: string;
flightSkills?: number;
flightSkillsName1?: string;
flightSkillsName2?: string;
free?: number;
id?: number | null;
price?: number;
supplierName?: string;
surfaceUrl?: string;
videoUrl?: string;
},
NonNullable<unknown>
>;
// V1.0.1修改课程
export type updateCurriculumType = InterFunction<
{
curriculumDesc?: string;
curriculumName?: string;
detailContent?: string;
flightSkills?: number;
flightSkillsName1?: string;
flightSkillsName2?: string;
free?: number;
id: number | null;
price?: number;
supplierName?: string;
surfaceUrl?: string;
videoUrl?: string;
},
NonNullable<unknown>
>;
// V1.0.1课程技能列表
export type treeCurriculumSkillType = InterFunction<
NonNullable<unknown>,
{
id: number;
skillsName: string;
flightSkills: Array<{
id: number;
skillsName: string;
flightSkills: null;
}>;
}[]
>;
// V1.0.1删除课程
export type removeCurriculumType = InterFunction<{ id: number }, NonNullable<unknown>>;
...@@ -361,19 +361,19 @@ export type renterTakeOrderType = InterFunction< ...@@ -361,19 +361,19 @@ export type renterTakeOrderType = InterFunction<
// 后台管理——平台确认归还 // 后台管理——平台确认归还
export type pfConfirmOrderWareType = InterFunction< export type pfConfirmOrderWareType = InterFunction<
{ {
authPwd: string; authPwd?: string;
imgs: Array<string>; imgs?: Array<string>;
orderInfoId: number; orderInfoId?: number;
orderRefundId: number; orderRefundId?: number;
remark: string; remark?: string;
renAddress: string; renAddress?: string;
renName: string; renName?: string;
renPhone: string; renPhone?: string;
sendAddress: string; sendAddress?: string;
sendExCode: string; sendExCode?: string;
sendExNo: string; sendExNo?: string;
vcuSatus: number; vcuSatus?: number;
videoUrl: string; videoUrl?: string;
}, },
NonNullable<unknown> NonNullable<unknown>
>; >;
......
import axios from '../request'; import axios from '../request';
import { categoryListType, directoryListType, GoodsInfo } from '~/api/interface/categoryManage'; import {
categoryListType,
directoryListType,
directoryPageListType,
GoodsInfo,
} from '~/api/interface/categoryManage';
export class CategoryManageAPI { export class CategoryManageAPI {
// 分类目录 // 分类目录
...@@ -9,17 +14,15 @@ export class CategoryManageAPI { ...@@ -9,17 +14,15 @@ export class CategoryManageAPI {
}); });
}; };
// 分类目录(类型) // 分类目录(类型)
static getDirectoryListClone: directoryListType = (params) => { static directoryListClone: directoryPageListType = (params) => {
return axios.get('/pms/classify/getDirectoryList', { params }); return axios.get('pms/classify/directoryList', {
};
//目录列表不含分页
static getDirectoryList = (params: { type: number }) => {
return axios.get('pms/classify/getDirectoryList', {
params, params,
}); });
}; };
// 分类目录-不分页(类型)
static getDirectoryListClone: directoryListType = (params) => {
return axios.get('/pms/classify/getDirectoryList', { params });
};
// 新增或编辑目录 // 新增或编辑目录
static addOrEditDirectory = ( static addOrEditDirectory = (
data: { id?: number; directoryName: string; type: number; relevance: number }[], data: { id?: number; directoryName: string; type: number; relevance: number }[],
......
import axios from '../request'; import axios from '../request';
import { listAppUserType } from '~/api/interface/customManageType'; import {
changeUserTagType,
CompanyListTag,
listAppUserType,
userAccountUpdateType,
} from '~/api/interface/customManageType';
export class CustomManageAPI { export class CustomManageAPI {
// 客户列表 // 客户列表
static listAppUser: listAppUserType = (params) => static listAppUser: listAppUserType = (params) =>
axios.post('/userapp/user-account/listAppUser', params); axios.post('/userapp/user-account/listAppUser', params);
// 加盟列表
static CompanyListTag: CompanyListTag = (params) =>
axios.get('/userapp/cooperation/listTag', { params });
// 客户列表
static userAccountUpdate: userAccountUpdateType = (params) =>
axios.post('/userapp/user-account/update', params);
// 后台设置小程序用户标签
static changeUserTag: changeUserTagType = (params) =>
axios.get('/userapp/cooperation/changeUserTag', { params });
} }
import {
addGoodsType,
batchOnShelfOrTakeDownType,
batchRemoveWareInfoType,
detailGoodsType,
editGoodsType,
listGoodsType,
otherServiceType,
skuUnitType,
} from '~/api/interface/goodsType';
import axios from '../request';
class GoodsAPI {
//商品-列表
static getGoodsList: listGoodsType = (data) => {
return axios.post('/pms/goods/listPageGoodsInfo', data);
};
//商品-新增
static addGoods: addGoodsType = (data) => {
return axios.post('/pms/goods/addGoodsInfo', data);
};
//商品-编辑
static editGoods: editGoodsType = (data) => {
return axios.post('/pms/goods/editGoodsInfo', data);
};
//商品-详情
static getGoodsDetail: detailGoodsType = (params) => {
return axios.get('/pms/goods/getGoodsInfoDetail', { params });
};
// 商品-单位
static getSkuUnit: skuUnitType = () => {
return axios.get('/pms/goods/getSkuUnit');
};
// 商品-其它服务列表
static getOtherServiceList: otherServiceType = () => {
return axios.get('/pms/goods/listOtherService');
};
// 商品-批量上下架
static batchOnShelfOrTakeDown: batchOnShelfOrTakeDownType = (data) => {
return axios.post('/pms/goods/batchOnShelfOrTakeDown', data);
};
// 商品-批量删除
static batchRemoveWareInfo: batchRemoveWareInfoType = (data) => {
return axios.post('/pms/goods/batchRemoveWareInfo', data);
};
}
export default GoodsAPI;
import axios from '~/api/request';
import {
addCurriculumType,
queryCurriculumInfoListType,
removeCurriculumType,
treeCurriculumSkillType,
updateCurriculumType,
} from '~/api/interface/mallManageType';
export class MallManageAPI {
// V1.0.1课程视频列表
static queryCurriculumInfoList: queryCurriculumInfoListType = (params) =>
axios.post('/release/curriculum/queryCurriculumInfoList', params);
// V1.0.1新增课程
static addCurriculum: addCurriculumType = (params) =>
axios.post('/release/curriculum/addCurriculum', params);
// V1.0.1修改课程
static updateCurriculum: updateCurriculumType = (params) =>
axios.post('/release/curriculum/updateCurriculum', params);
// V1.0.1课程技能列表
static treeCurriculumSkill: treeCurriculumSkillType = (params) =>
axios.get('/release/curriculum/treeCurriculumSkill', { params });
// V1.0.1删除课程
static removeCurriculum: removeCurriculumType = (params) =>
axios.get('/release/curriculum/removeCurriculum', { params });
}
...@@ -14,7 +14,6 @@ import { ...@@ -14,7 +14,6 @@ import {
ProductSpecListType, ProductSpecListType,
productSpecPriceType, productSpecPriceType,
} from '~/api/interface/produceManageType'; } from '~/api/interface/produceManageType';
import dayjs from 'dayjs';
export class ProduceManageAPI { export class ProduceManageAPI {
// 产品管理-分页列表 // 产品管理-分页列表
......
...@@ -18,7 +18,7 @@ export class SystemManageAPI { ...@@ -18,7 +18,7 @@ export class SystemManageAPI {
// 账号-删除 // 账号-删除
static removeBAccount: removeBAccountType = (params) => static removeBAccount: removeBAccountType = (params) =>
axios.post('/userapp/back-user/removeBAccount', params); axios.get('/userapp/back-user/removeBAccount', { params });
// 账号-修改 // 账号-修改
static updateBAccount: updateBAccountType = (params) => static updateBAccount: updateBAccountType = (params) =>
......
...@@ -35,7 +35,7 @@ service.interceptors.response.use( ...@@ -35,7 +35,7 @@ service.interceptors.response.use(
return Promise.resolve(data); return Promise.resolve(data);
} }
// 重新登录? // 重新登录?
if (['605', '603', '602', '4004', '607', '2014', '2013'].includes(data.code)) { if (['605', '603', '602', '4004', '607', '2014', '2013', '5008'].includes(data.code)) {
message.error(data.message).then(); message.error(data.message).then();
Cookies.remove('SHAREFLY-TOKEN'); Cookies.remove('SHAREFLY-TOKEN');
setTimeout(() => { setTimeout(() => {
......
import { Form, InputNumber, Input } from 'antd';
import React from 'react';
// 表格可编辑单元格
interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
editing: boolean;
dataIndex: string;
title: any;
inputType: 'number' | 'text';
record: any;
index: number;
children: React.ReactNode;
}
const EditableCell: React.FC<EditableCellProps> = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode =
inputType === 'number' ? <InputNumber /> : <Input placeholder={`请输入${title}`} />;
return (
<td {...restProps}>
{editing ? (
<Form.Item
name={dataIndex + record.id}
style={{ margin: 0 }}
rules={[
{
required: true,
message: `请输入${title}`,
},
]}
>
{inputNode}
</Form.Item>
) : (
children
)}
</td>
);
};
export default EditableCell;
...@@ -8,4 +8,14 @@ ...@@ -8,4 +8,14 @@
color: red; color: red;
} }
} }
.goods-video-wrap{
position: relative;
width: 200px;
img{
position: absolute;
right: 0;
top: 0;
transform: translate(50%,-25%);
}
}
} }
import React, { useEffect, useState } from 'react';
import { Modal, Form, Select, Input, message, Button, ModalProps } from 'antd';
import { InterDataType } from '~/api/interface';
import { cooperationTagType } from '~/api/interface/produceManageType';
import { customizeEntity } from '~/api/interface/goodsType';
import { filterObjAttr } from '~/utils';
//加盟标签返回类型
type cooperationTagResponseType = InterDataType<cooperationTagType>;
interface selfProps {
handleOk: (specPrice: any, leaseTerm: number) => void;
handleCancel: () => void;
customRowData: Partial<customizeEntity>;
tagInfoList: cooperationTagResponseType;
goodsType: number;
}
const ConfigurePriceModal: React.FC<ModalProps & selfProps> = ({
open,
handleOk,
handleCancel,
customRowData,
tagInfoList,
goodsType,
}) => {
// 选择的列表
const [selectList, setSelectList] = useState<number[]>([]);
// 配置价格Form
const [cfgPriceForm] = Form.useForm<any>();
const deselectEvent = (id: number) => {
const obj: any = {};
obj[id] = undefined;
cfgPriceForm.setFieldsValue(obj);
const numArr: number[] = selectList.filter((i: number) => i !== id);
setSelectList([...numArr]);
};
const levelSelectEvent = (id: number) => {
selectList.push(id);
setSelectList([...selectList]);
};
// 将val转换为label
const transValtoLabel = (id: number) => {
const item = tagInfoList.find((i) => i.id === id);
return item ? item.tagName : id;
};
// 表单验证
const handleSubmit = async () => {
cfgPriceForm
.validateFields()
.then(async (values) => {
const specPrice = Object.keys(filterObjAttr(values, ['leaseTerm'])).reduce(
(pre: any, cur: string) => {
if (Object.keys(customRowData.productSpecCPQVO).length != 0) {
const priceItem: any = customRowData.productSpecCPQVO.specPrice.find(
(i: any) => i.cooperationTag === Number(cur),
);
pre.push({
id: priceItem?.id,
price: values[cur],
cooperationTag: cur,
});
} else {
pre.push({ price: values[cur], cooperationTag: cur });
}
return pre;
},
[],
);
handleOk([...specPrice], values.leaseTerm);
})
.catch((err) => {
message.warning(err.errorFields[0].errors[0]).then();
});
};
const handleCancelEvent = () => {
cfgPriceForm.resetFields();
handleCancel();
};
// 价格正则
const priceValidator = (_rule: any, value: any) => {
const regExp = /^[1-9]\d{0,7}(\.\d{1,2})?$|^0(\.\d{1,2})?$/;
const bol: boolean = regExp.test(value);
if (!value) {
return Promise.reject(new Error('请输入定价金额'));
}
if (!bol) {
return Promise.reject(
new Error('金额应为数字,小数最多两位,整数最多八位,不能输入0开头的整数'),
);
}
return Promise.resolve();
};
useEffect(() => {
// 新增规格则清空表单数据
if (Object.keys(customRowData.productSpecCPQVO).length === 0) {
cfgPriceForm.resetFields();
setSelectList([]);
} else {
cfgPriceForm.setFieldValue('leaseTerm', customRowData.productSpecCPQVO.leaseTerm);
const ids: number[] = [];
customRowData.productSpecCPQVO.specPrice.map((item: any) => {
cfgPriceForm.setFieldValue(Number(item.cooperationTag), item.price);
if (item.cooperationTag != '0') {
ids.push(Number(item.cooperationTag));
}
setSelectList(ids);
});
}
}, [customRowData]);
return (
<Modal
title='配置价格'
open={open}
onCancel={handleCancelEvent}
zIndex={1009}
footer={[
<Button key={1} type='default' onClick={handleCancelEvent}>
取消
</Button>,
<Button key={2} type='primary' onClick={handleSubmit}>
确认
</Button>,
]}
>
<Form
labelCol={{ span: 7 }}
wrapperCol={{ span: 14 }}
form={cfgPriceForm}
initialValues={{ leaseTerm: 0 }}
>
{goodsType && (
<Form.Item
label='租期'
name='leaseTerm'
rules={[{ required: true, message: '请选择租期' }]}
>
<Select>
<Select.Option value={0}>1-7天</Select.Option>
<Select.Option value={1}>8-15天</Select.Option>
<Select.Option value={2}>16-30天</Select.Option>
<Select.Option value={3}>31天以上</Select.Option>
</Select>
</Form.Item>
)}
<Form.Item label='渠道等级'>
<Select
placeholder='请选择渠道等级'
mode='multiple'
filterOption={(input, option) =>
(option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
}
onDeselect={deselectEvent}
onSelect={levelSelectEvent}
value={selectList}
>
{tagInfoList.map((item) => (
<Select.Option key={item.id} value={item.id}>
{item.tagName}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label='市场单价'
name={0}
rules={[{ required: true, validator: priceValidator }]}
>
<Input placeholder='请输入市场单价' maxLength={11} />
</Form.Item>
{selectList.map((item: number) => (
<Form.Item
label={transValtoLabel(item)}
key={item}
name={item}
rules={[{ required: true, validator: priceValidator }]}
>
<Input placeholder='请输入定价金额' maxLength={11} />
</Form.Item>
))}
</Form>
</Modal>
);
};
export default ConfigurePriceModal;
import './index.scss'; import './index.scss';
import RichText from '~/components/richText'; import RichText from '~/components/richText';
const GoodsIntroduce = () => { import { FC } from 'react';
import { InterDataType } from '~/api/interface';
import { detailGoodsType } from '~/api/interface/goodsType';
//商品返回类型
type goodsDetailType = InterDataType<detailGoodsType>;
interface selfProps {
getRichText: (html?: string) => void;
goodsDetail: goodsDetailType | undefined;
isDetail: boolean;
}
const GoodsIntroduce: FC<selfProps> = ({ getRichText, goodsDetail, isDetail }) => {
const richTextChange = (html?: string) => {
getRichText(html);
};
return ( return (
<div className='goods-introduce'> <div className='goods-introduce'>
<div className='goods-introduce-title'>产品介绍图</div> <div className='goods-introduce-title'>产品介绍图</div>
<div className='goods-introduce-content'> <div className='goods-introduce-content'>
<RichText richTextHeight={300} /> <RichText
value={goodsDetail?.goodsDetail.content}
onChange={richTextChange}
isDetail={isDetail}
/>
</div> </div>
</div> </div>
); );
......
import React, { useEffect, useState } from 'react';
import { Checkbox, Form } from 'antd';
import './index.scss';
import GoodsAPI from '~/api/modules/goodsAPI';
import { detailGoodsType, otherServiceType } from '~/api/interface/goodsType';
import { InterDataType } from '~/api/interface';
//商品返回类型
type goodsDetailType = InterDataType<detailGoodsType>;
interface selfProps {
otherServiceSelect: (id: number[]) => void;
goodsDetail: goodsDetailType | undefined;
isDetail: boolean;
}
//其它服务返回类型
type otherServiceListType = InterDataType<otherServiceType>;
const OtherInfo: React.FC<selfProps> = ({ otherServiceSelect, goodsDetail, isDetail }) => {
const [otherInfoForm] = Form.useForm();
//其它服务
const [otherServiceList, setOtherServiceList] = useState<otherServiceListType>([]);
const otherServiceRadioChange = (e: any) => {
otherServiceSelect(e);
};
//获取其它服务
const getOtherServiceList = () => {
GoodsAPI.getOtherServiceList().then(({ result }) => {
setOtherServiceList(result);
});
};
useEffect(() => {
getOtherServiceList();
}, []);
useEffect(() => {
if (goodsDetail) {
otherInfoForm.setFieldsValue({
otherService: goodsDetail.otherService.map((v) => v.saleServiceId),
});
}
}, [goodsDetail]);
return (
<div className='other-info'>
<div className='other-info-title'>其它信息</div>
<div className='other-info-form'>
<Form form={otherInfoForm} disabled={isDetail}>
<Form.Item label='搭配服务' name='otherService'>
<Checkbox.Group onChange={otherServiceRadioChange}>
{otherServiceList.map((item: any, index: number) => (
<Checkbox value={item.id} key={index}>
{item.saleServiceName}
</Checkbox>
))}
</Checkbox.Group>
</Form.Item>
</Form>
</div>
</div>
);
};
export default OtherInfo;
...@@ -3,81 +3,159 @@ import { Table, Button } from 'antd'; ...@@ -3,81 +3,159 @@ import { Table, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import './index.scss'; import './index.scss';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
const columns: ColumnsType<any> = [ import { customizeEntity, skuUnitType, specEntity } from '~/api/interface/goodsType';
{ import { InterDataType } from '~/api/interface';
title: '序号', import { categoryListType } from '~/api/interface/categoryManage';
align: 'center',
render: () => <div>--</div>, //分类返回类型
}, type categoryType = InterDataType<categoryListType>['list'];
{
title: `产品类型`, //产品-规格单位返回类型
align: 'center', type unitType = InterDataType<skuUnitType>;
// dataIndex: "goodsTypeId",
render: () => <div>--</div>, interface selfProps {
}, addOrEditSku: (record?: specEntity) => void;
{ specData: specEntity[];
title: '规格名称', categoryList: categoryType;
align: 'center', skuUnitList: unitType;
dataIndex: 'goodsSpecName', deleteSku: (record: specEntity) => void;
}, isDetail: boolean;
{ }
title: `方案`,
align: 'center', const StockSku: React.FC<selfProps> = ({
dataIndex: 'skuName', addOrEditSku,
}, specData,
{ categoryList,
title: '选项来源', skuUnitList,
align: 'center', deleteSku,
dataIndex: 'specIds', isDetail,
render: () => <div>--</div>, }) => {
}, const columns: ColumnsType<specEntity> = [
{ {
title: '选择方式', title: '序号',
align: 'center', align: 'center',
dataIndex: 'chooseType', render: (_text: string, _record: specEntity, index: number) => index + 1,
render: () => <div>--</div>,
},
{
title: '是否必选',
align: 'center',
dataIndex: 'must',
render: () => <div>--</div>,
},
{
title: '规格单位',
align: 'center',
dataIndex: 'skuUnitId',
render: () => {
return <div>--</div>;
}, },
}, {
{ title: `产品类型`,
title: '操作', align: 'center',
align: 'center', dataIndex: 'categoryId',
width: '20%', render: (text: string) => <div>{getGoodsTypeName(text)}</div>,
render: () => { },
return ( {
title: '规格名称',
align: 'center',
dataIndex: 'goodsSpecName',
},
{
title: `方案`,
align: 'center',
dataIndex: 'skuName',
},
{
title: '选项来源',
align: 'center',
dataIndex: 'specIds',
render: (_text: string, record) => (
<div> <div>
<Button type='link' style={{ marginRight: '10px' }}> {record.flag !== 1
编辑 ? record.specIds.map((i: any, j: number) => (
</Button> <div key={j}>
<Button type='link'>删除</Button> {i.specName}
{i.partNo && `(${i.partNo})`}
</div>
))
: record.customizeInfo &&
record.customizeInfo.map((i, index: number) => (
<div key={index}>{getSelfSpecName(i)}</div>
))}
</div> </div>
); ),
},
{
title: '选择方式',
align: 'center',
dataIndex: 'chooseType',
render: (text: number) => <div>{text === 0 ? '单选' : '多选'}</div>,
}, },
}, {
]; title: '是否必选',
const StockSku: React.FC<any> = () => { align: 'center',
dataIndex: 'must',
render: (text: number) => <div>{text ? '必选' : '非必选'}</div>,
},
{
title: '规格单位',
align: 'center',
dataIndex: 'skuUnitId',
render: (text: number) => {
return <div>{getSkuUnitName(text)}</div>;
},
},
{
title: '操作',
align: 'center',
width: '20%',
render: (_text: any, record) => {
return (
<div>
<Button
type='link'
style={{ marginRight: '10px' }}
onClick={() => addOrEditSkuClick(record)}
>
编辑
</Button>
<Button type='link' onClick={() => deleteSkuClick(record)}>
删除
</Button>
</div>
);
},
},
];
//添加、编辑规格操作
const addOrEditSkuClick = (record?: specEntity) => {
addOrEditSku(record);
};
//删除规格操作
const deleteSkuClick = (record: specEntity) => {
deleteSku(record);
};
// 自定义选项来源名称
const getSelfSpecName = (obj: customizeEntity) => {
return `${obj.specName}(${obj.partNo || ''})`;
};
// 行业或产品名称
const getGoodsTypeName = (id: number | string) => {
const obj = categoryList.find((i) => i.id === id);
return obj?.classifyName;
};
// 单位名称
const getSkuUnitName = (id: number) => {
const unitObj = skuUnitList.find((i) => i.id === id);
return unitObj?.unitName;
};
return ( return (
<div className='stock-sku'> <div className='stock-sku'>
<div className='stock-sku-title'>库存规格</div> <div className='stock-sku-title'>库存规格</div>
<div className='stock-sku-content'> <div className='stock-sku-content'>
<div className='stock-sku-operate'> {!isDetail && (
<Button icon={<PlusOutlined />} type='primary'> <div className='stock-sku-operate'>
添加规格 <Button icon={<PlusOutlined />} type='primary' onClick={() => addOrEditSkuClick()}>
</Button> 添加规格
</div> </Button>
<Table size='small' bordered rowKey='id' pagination={false} columns={columns} /> </div>
)}
<Table
size='small'
bordered
dataSource={specData}
rowKey='id'
pagination={false}
columns={isDetail ? columns.filter((v) => v.title !== '操作') : columns}
/>
</div> </div>
</div> </div>
); );
......
...@@ -46,7 +46,7 @@ $page-background: #f3f6ff; ...@@ -46,7 +46,7 @@ $page-background: #f3f6ff;
} }
.ant-layout-sider-children { .ant-layout-sider-children {
border-radius: 10px; border-radius: 10px;
overflow: hidden; //overflow: hidden;
} }
.ant-menu-item { .ant-menu-item {
......
import ReactQuill from 'react-quill'; import React, { useEffect } from 'react';
import 'react-quill/dist/quill.snow.css'; import E from 'wangeditor';
import { FC, useEffect, useRef } from 'react'; import { message } from 'antd';
// import events from '@/events';
import { CommonAPI } from '~/api';
interface selfProps { let editor: any = null;
richTextHeight: number;
interface PropsType {
onChange: (html?: string) => void;
value: string | undefined;
// eslint-disable-next-line react/require-default-props
isDetail?: boolean;
height?: number;
} }
const RichText: FC<selfProps> = ({ richTextHeight }) => { const RichText: React.FC<PropsType> = ({ onChange, value, isDetail, height }) => {
const quillRef = useRef<any>(); useEffect(() => {
const modules = { // 注:class写法需要在componentDidMount 创建编辑器
toolbar: { editor = new E('.edit');
container: [ editor.config.uploadImgShowBase64 = false;
[{ size: ['small', false, 'large', 'huge'] }], //字体设置 editor.config.zIndex = 1;
// [{ 'header': [1, 2, 3, 4, 5, 6, false] }], //标题字号,不能设置单个字大小 editor.config.height = height ? height : 550;
['bold', 'italic', 'underline', 'strike'], editor.config.uploadImgMaxLength = 5;
[{ list: 'ordered' }, { list: 'bullet' }, { indent: '-1' }, { indent: '+1' }], editor.config.uploadImgMaxSize = 1024 * 1024 * 3; // 2M
['link', 'image'], // a链接和图片的显示 editor.config.customUploadImg = async (resultFiles: any, insertImgFn: any) => {
[{ align: [] }], // resultFiles 是 input 中选中的文件列表
[ // insertImgFn 是获取图片 url 后,插入到编辑器的方法
{ const formData = new FormData();
background: [ resultFiles.map(async (item: any) => {
'rgb( 0, 0, 0)', formData.append('uploadFile', item);
'rgb(230, 0, 0)', });
'rgb(255, 153, 0)', const { code, result } = await CommonAPI.uploadOss(formData);
'rgb(255, 255, 0)', if (code === '200') {
'rgb( 0, 138, 0)', insertImgFn(result.filePath);
'rgb( 0, 102, 204)', message.success('上传成功');
'rgb(153, 51, 255)', } else {
'rgb(255, 255, 255)', message.error('上传失败');
'rgb(250, 204, 204)', }
'rgb(255, 235, 204)', };
'rgb(255, 255, 204)', editor.config.onchange = (newHtml: string) => {
'rgb(204, 232, 204)', if (newHtml) {
'rgb(204, 224, 245)', onChange(newHtml);
'rgb(235, 214, 255)', } else {
'rgb(187, 187, 187)', onChange(undefined);
'rgb(240, 102, 102)', }
'rgb(255, 194, 102)', };
'rgb(255, 255, 102)',
'rgb(102, 185, 102)', // 需要展示的菜单
'rgb(102, 163, 224)', editor.config.menus = [
'rgb(194, 133, 255)', 'head',
'rgb(136, 136, 136)', 'bold',
'rgb(161, 0, 0)', 'fontSize',
'rgb(178, 107, 0)', 'fontName',
'rgb(178, 178, 0)', 'italic',
'rgb( 0, 97, 0)', 'underline',
'rgb( 0, 71, 178)', 'strikeThrough',
'rgb(107, 36, 178)', 'indent',
'rgb( 68, 68, 68)', 'lineHeight',
'rgb( 92, 0, 0)', 'foreColor',
'rgb(102, 61, 0)', 'backColor',
'rgb(102, 102, 0)', 'link',
'rgb( 0, 55, 0)', 'list',
'rgb( 0, 41, 102)', 'todo',
'rgb( 61, 20, 10)', 'justify',
], 'quote',
}, 'table',
], 'splitLine',
[ 'undo',
{ 'redo',
color: [ 'image',
'rgb( 0, 0, 0)', ];
'rgb(230, 0, 0)',
'rgb(255, 153, 0)', /** 一定要创建 */
'rgb(255, 255, 0)', editor.create();
'rgb( 0, 138, 0)', // events.addListener('clearEdit', () => {
'rgb( 0, 102, 204)', // editor.txt.html('');
'rgb(153, 51, 255)', // });
'rgb(255, 255, 255)', return () => {
'rgb(250, 204, 204)', // 组件销毁时销毁编辑器 注:class写法需要在componentWillUnmount中调用
'rgb(255, 235, 204)', editor.destroy();
'rgb(255, 255, 204)', };
'rgb(204, 232, 204)',
'rgb(204, 224, 245)', // 这里一定要加上下面的这个注释
'rgb(235, 214, 255)', // eslint-disable-next-line react-hooks/exhaustive-deps
'rgb(187, 187, 187)', }, []);
'rgb(240, 102, 102)',
'rgb(255, 194, 102)',
'rgb(255, 255, 102)',
'rgb(102, 185, 102)',
'rgb(102, 163, 224)',
'rgb(194, 133, 255)',
'rgb(136, 136, 136)',
'rgb(161, 0, 0)',
'rgb(178, 107, 0)',
'rgb(178, 178, 0)',
'rgb( 0, 97, 0)',
'rgb( 0, 71, 178)',
'rgb(107, 36, 178)',
'rgb( 68, 68, 68)',
'rgb( 92, 0, 0)',
'rgb(102, 61, 0)',
'rgb(102, 102, 0)',
'rgb( 0, 55, 0)',
'rgb( 0, 41, 102)',
'rgb( 61, 20, 10)',
],
},
],
['clean'], //清空
['emoji'], //emoji表情,设置了才能显示
['video2'], //我自定义的视频图标,和插件提供的不一样,所以设置为video2
],
// handlers: {
// image: this.imageHandler.bind(this), //点击图片标志会调用的方法
// video2: this.showVideoModal.bind(this),
// },
},
// ImageExtend: {
// loading: true,
// name: 'img',
// action: RES_URL + "connector?isRelativePath=true",
// response: res => FILE_URL + res.info.url
// },
// ImageDrop: true,
// 'emoji-toolbar': true, //是否展示出来
// 'emoji-textarea': false, //我不需要emoji展示在文本框所以设置为false
// 'emoji-shortname': true,
};
useEffect(() => { useEffect(() => {
quillRef.current.editor.container.style.height = richTextHeight + 'px'; if (editor) {
}); editor.txt.html(value || '');
return <ReactQuill modules={modules} ref={quillRef} />; }
if (isDetail) {
editor.disable();
}
}, [value]);
return <div className='edit' />;
}; };
export default RichText; export default RichText;
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
// min-width: 200px; // min-width: 200px;
//} //}
.ant-form-item { .ant-form-item {
margin-inline-end: 20px; margin-inline-end: 15px;
} }
.ant-row { .ant-row {
......
import { Form, Input, Button, Select, DatePicker } from 'antd'; import { Form, Input, Button, Select, DatePicker, TreeSelect, Cascader } from 'antd';
import moment from 'dayjs'; import moment from 'dayjs';
import { SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons'; import { SearchOutlined, ReloadOutlined, ExportOutlined } from '@ant-design/icons';
import React, { useImperativeHandle } from 'react'; import React, { useImperativeHandle } from 'react';
...@@ -8,7 +8,7 @@ const { RangePicker } = DatePicker; ...@@ -8,7 +8,7 @@ const { RangePicker } = DatePicker;
// 搜索列表的类型 // 搜索列表的类型
export interface searchColumns { export interface searchColumns {
type: 'input' | 'select' | 'rangePicker' | 'DatePicker' | 'Select'; type: 'input' | 'select' | 'rangePicker' | 'DatePicker' | 'Select' | 'TreeSelect' | 'Cascader';
label?: string; label?: string;
name: string; name: string;
placeholder: string; placeholder: string;
...@@ -155,6 +155,33 @@ const Index: React.FC<propsType> = (props) => { ...@@ -155,6 +155,33 @@ const Index: React.FC<propsType> = (props) => {
showTime={item.showTime} showTime={item.showTime}
style={{ width: item.width ? `${item.width}px` : '180px' }} style={{ width: item.width ? `${item.width}px` : '180px' }}
/> />
) : item.type === 'TreeSelect' ? (
<TreeSelect
allowClear
treeDefaultExpandAll
placeholder={item.placeholder}
treeData={item.options}
fieldNames={{
label: 'name',
value: 'id',
children: 'childNodes',
}}
popupClassName='head-search-treeSelect'
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : item.type === 'Cascader' ? (
<Cascader
allowClear
changeOnSelect
placeholder={item.placeholder}
options={item.options}
fieldNames={{
label: 'name',
value: 'id',
children: 'childNodes',
}}
style={{ width: item.width ? `${item.width}px` : '180px' }}
/>
) : ( ) : (
'' ''
)} )}
......
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { message, Upload, UploadProps } from 'antd'; import { message, Upload, UploadProps } from 'antd';
// import { UploadFile } from "antd/es/upload/interface";
import { CommonAPI } from '~/api'; import { CommonAPI } from '~/api';
import './index.scss'; import './index.scss';
...@@ -23,10 +22,20 @@ interface PropsType { ...@@ -23,10 +22,20 @@ interface PropsType {
} }
export const Uploader: React.FC<PropsType> = (props) => { export const Uploader: React.FC<PropsType> = (props) => {
Uploader.defaultProps = { Uploader.defaultProps = {
listType: 'text', listType: 'picture-card',
fileSize: 2, fileSize: 2,
fileLength: 1, fileLength: 1,
fileType: ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/bmp'], fileType: [
'image/png',
'image/jpeg',
'image/jpg',
'image/gif',
'image/bmp',
'video/mp4',
'video/avi',
'video/mov',
'video/mkv',
],
// eslint-disable-next-line @typescript-eslint/no-empty-function // eslint-disable-next-line @typescript-eslint/no-empty-function
onChange: () => {}, onChange: () => {},
defaultFileList: [], defaultFileList: [],
...@@ -104,6 +113,7 @@ export const Uploader: React.FC<PropsType> = (props) => { ...@@ -104,6 +113,7 @@ export const Uploader: React.FC<PropsType> = (props) => {
onRemove: (res) => { onRemove: (res) => {
const newFileList = fileList.filter((item) => item.uid !== res.uid); const newFileList = fileList.filter((item) => item.uid !== res.uid);
setFileList(newFileList); setFileList(newFileList);
onChange?.(newFileList);
}, },
// onPreview: { onPreview }, // onPreview: { onPreview },
}; };
......
...@@ -123,7 +123,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({ ...@@ -123,7 +123,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
<Form.Item label='分类模块' name='type' rules={[{ required: true }]}> <Form.Item label='分类模块' name='type' rules={[{ required: true }]}>
<Select options={typeOptions} allowClear={true} onChange={onChangeType}></Select> <Select options={typeOptions} allowClear={true} onChange={onChangeType}></Select>
</Form.Item> </Form.Item>
<Form.Item label='目录类型'> {/* <Form.Item label='目录类型'>
<Radio.Group onChange={(e: RadioChangeEvent) => setHasPid(e.target.value)} value={hasPid}> <Radio.Group onChange={(e: RadioChangeEvent) => setHasPid(e.target.value)} value={hasPid}>
<Radio value={false}>无关联目录</Radio> <Radio value={false}>无关联目录</Radio>
<Radio value={true}>有关联目录</Radio> <Radio value={true}>有关联目录</Radio>
...@@ -137,7 +137,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({ ...@@ -137,7 +137,7 @@ const AddOrEditDec: React.FC<PropsType & selfPropsType> = ({
allowClear={true} allowClear={true}
></Select> ></Select>
</Form.Item> </Form.Item>
)} )} */}
<Form.Item label='目录名称' name='directoryName' rules={[{ required: true }]}> <Form.Item label='目录名称' name='directoryName' rules={[{ required: true }]}>
<Input placeholder='请输入目录名称' allowClear={true}></Input> <Input placeholder='请输入目录名称' allowClear={true}></Input>
......
...@@ -71,7 +71,7 @@ const DirectoryManage: FC = (props: any) => { ...@@ -71,7 +71,7 @@ const DirectoryManage: FC = (props: any) => {
}); });
return <div>{find?.label}</div>; return <div>{find?.label}</div>;
}, },
}, } /*
{ {
title: '目录类型', title: '目录类型',
dataIndex: 'directoryType', dataIndex: 'directoryType',
...@@ -83,7 +83,7 @@ const DirectoryManage: FC = (props: any) => { ...@@ -83,7 +83,7 @@ const DirectoryManage: FC = (props: any) => {
dataIndex: 'relevanceName', dataIndex: 'relevanceName',
key: 'relevanceName', key: 'relevanceName',
align: 'center', align: 'center',
}, }, */,
{ {
title: '操作', title: '操作',
key: 'action', key: 'action',
......
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import { Form, Modal, Select } from 'antd'; import { Form, Modal, Select } from 'antd';
// import { tagLevelEntity } from "@/api/modules/user"; import { InterListType } from '~/api/interface';
// import { UserAPI } from "@/api"; import { listAppUserType } from '~/api/interface/customManageType';
import { CustomManageAPI } from '~/api';
// 表格数据类型
type TableType = InterListType<listAppUserType>;
// 数据的类型
interface PropsType { interface PropsType {
visible: boolean; open: boolean;
closed: any; closed: any;
data: any; data?: TableType[0];
state: any;
} }
// 修改等级标签 // 修改等级标签
interface tagLevelForm { interface tagLevelForm {
channelLevelId: number; cooperationTagId: number;
mallOperator: number;
mallSaleManager: number;
} }
export const ChangeModal: FC<PropsType> = (props) => { export const ChangeModal: FC<PropsType> = (props) => {
ChangeModal.defaultProps = {
data: undefined,
};
// 父组件传参 // 父组件传参
const { visible, closed, data, state } = props; const { open, closed, data } = props;
// 个人等级标签 // 个人等级标签
const [tagLevelForm] = Form.useForm<tagLevelForm>(); const [form] = Form.useForm<tagLevelForm>();
// 相关运营列表 // 相关运营列表
const [operationList] = useState([]); const [operationList] = useState<{ value: number; label: string }[]>([]);
// 等级标签列表
const [cooperationTagIdList, setCooperationTagIdList] = useState<
{ value: number; label: string }[]
>([]);
// 关闭事件 // 关闭事件
const handleClosed = () => { const handleClosed = () => {
tagLevelForm.resetFields(); form.resetFields();
closed(); closed();
}; };
// 提交数据 // 提交数据
const handleSubmit = () => { const handleSubmit = () => {
tagLevelForm.validateFields().then(async (value: tagLevelForm) => { form.validateFields().then(async (value) => {
// 提交表单数据 const res = await CustomManageAPI.changeUserTag({
const SubmitFuc = async () => { userAccountId: Number(data?.id),
// const res: any = await UserAPI.mallUserChangeInfo({ cooperationTagId: value.cooperationTagId,
// ...value, });
// userAccountId: data.id, if (res && res.code === '200') {
// }); handleClosed();
// if (res.code === '200') {
// message.success('修改成功');
// handleClosed();
// } else {
// message.warning(res.message);
// }
};
// 如果之前填过等级标签,现在又删除了的话,调用删除等级标签的接口
if (data.channelClass && !value.channelLevelId) {
// 删除等级标签
// const res: any = await UserAPI.mallUserDeleteInfo({
// userAccountId: data.id,
// });
// if (res && res.code === '200') {
// await SubmitFuc();
// } else {
// message.warning(res.message);
// }
} else {
await SubmitFuc();
} }
}); });
}; };
// 获取运营人员列表 // 获取加盟列表
const getListOperate = () => { const getCompanyListTag = async () => {
// UserAPI.getKbtUserList({ keyword: '' }).then(({ result }) => { const res = await CustomManageAPI.CompanyListTag({});
// if (result) { if (res && res.code === '200') {
// setOperationList( setCooperationTagIdList(res.result.map((i) => ({ value: i.id, label: i.tagName })));
// result.map((i: any) => { // console.log(res.result);
// return { }
// label: `${i.userName || i.nickName}(${i.uid})`,
// value: i.id,
// };
// }),
// );
// }
// });
}; };
// 组件启动 // 组件启动
useEffect(() => { useEffect(() => {
if (data) { if (!data) return;
getListOperate(); getCompanyListTag().then();
tagLevelForm.setFieldsValue({ form.setFieldsValue({
channelLevelId: data.channelClass || undefined, cooperationTagId: data.cooperationTagId,
mallOperator: data.mallOperator || undefined, });
mallSaleManager: data.mallSaleManager || undefined, }, [open]);
});
}
}, [data]);
return ( return (
<Modal open={visible} title='变更' onCancel={handleClosed} destroyOnClose onOk={handleSubmit}> <Modal open={open} title='变更' onCancel={handleClosed} destroyOnClose onOk={handleSubmit}>
<Form form={tagLevelForm} labelCol={{ span: 5 }} wrapperCol={{ span: 16 }}> <Form form={form} labelCol={{ span: 5 }} wrapperCol={{ span: 16 }}>
<Form.Item label='等级标签' name='channelLevelId'> <Form.Item label='等级标签' name='cooperationTagId'>
<Select <Select
placeholder='请选择等级标签' placeholder='请选择等级标签'
disabled={!data?.realAuthStatus && !data?.entAuthStatus} disabled={!data?.userName && !data?.companyName}
allowClear allowClear
> options={cooperationTagIdList}
{state.levelTags.map((item: any, index: number) => ( />
<Select.Option value={item.id} key={index}>
{item.tagName}
</Select.Option>
))}
</Select>
</Form.Item> </Form.Item>
<Form.Item label='相关运营' name='mallOperator'> <Form.Item label='相关运营' name='mallOperator'>
<Select placeholder='请选择相关运营' allowClear> <Select placeholder='请选择相关运营' allowClear disabled>
{operationList.map((item: any, index: number) => ( {operationList.map((item: any, index: number) => (
<Select.Option value={item.value} key={index}> <Select.Option value={item.value} key={index}>
{item.label} {item.label}
...@@ -113,7 +86,7 @@ export const ChangeModal: FC<PropsType> = (props) => { ...@@ -113,7 +86,7 @@ export const ChangeModal: FC<PropsType> = (props) => {
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item label='相关销售' name='mallSaleManager'> <Form.Item label='相关销售' name='mallSaleManager'>
<Select placeholder='请选择相关销售' allowClear> <Select placeholder='请选择相关销售' allowClear disabled>
{operationList.map((item: any, index: number) => ( {operationList.map((item: any, index: number) => (
<Select.Option value={item.value} key={index}> <Select.Option value={item.value} key={index}>
{item.label} {item.label}
......
...@@ -24,6 +24,10 @@ const portTypeList = [ ...@@ -24,6 +24,10 @@ const portTypeList = [
]; ];
function CustomListView() { function CustomListView() {
// 等级标签列表
const [cooperationTagIdList, setCooperationTagIdList] = useState<
{ value: number; label: string }[]
>([]);
// 是否打开变更弹窗 // 是否打开变更弹窗
const [isChangeVisModal, setIsChangeVisModal] = useState<boolean>(false); const [isChangeVisModal, setIsChangeVisModal] = useState<boolean>(false);
// 表格分页配置 // 表格分页配置
...@@ -36,7 +40,7 @@ function CustomListView() { ...@@ -36,7 +40,7 @@ function CustomListView() {
// 表格数据 // 表格数据
const [tableData, setTableData] = useState<TableType>([]); const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据 // 需要编辑的数据
const [editData] = useState<TableType[0]>(); const [editData, setEditData] = useState<TableType[0]>();
// 加载列表 // 加载列表
const getTableList = async (value = {}) => { const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可 // 只需要修改这个地方的接口即可
...@@ -68,10 +72,21 @@ function CustomListView() { ...@@ -68,10 +72,21 @@ function CustomListView() {
query = data; query = data;
getTableList(data).then(); getTableList(data).then();
}; };
// 获取加盟列表
const getCompanyListTag = async () => {
const res = await CustomManageAPI.CompanyListTag({});
if (res && res.code === '200') {
setCooperationTagIdList(res.result.map((i) => ({ value: i.id, label: i.tagName })));
// console.log(res.result);
}
};
// componentDidMount // componentDidMount
useEffect(() => { useEffect(() => {
query = {}; query = {};
getTableList().then(); (async () => {
await getCompanyListTag();
await getTableList();
})();
}, []); }, []);
// 表格结构 // 表格结构
const columns: ColumnsType<TableType[0]> = [ const columns: ColumnsType<TableType[0]> = [
...@@ -80,7 +95,6 @@ function CustomListView() { ...@@ -80,7 +95,6 @@ function CustomListView() {
dataIndex: 'uid', dataIndex: 'uid',
align: 'center', align: 'center',
width: '100px', width: '100px',
render: (text) => `UID${text}`,
}, },
{ {
title: '用户名称', title: '用户名称',
...@@ -131,7 +145,7 @@ function CustomListView() { ...@@ -131,7 +145,7 @@ function CustomListView() {
title: '渠道等级', title: '渠道等级',
dataIndex: 'cooperationTagId', dataIndex: 'cooperationTagId',
align: 'center', align: 'center',
render: (text) => text, render: (text) => cooperationTagIdList.find((i) => i.value === text)?.label || text,
}, },
{ {
title: '上级推荐人', title: '上级推荐人',
...@@ -162,12 +176,13 @@ function CustomListView() { ...@@ -162,12 +176,13 @@ function CustomListView() {
dataIndex: 'action', dataIndex: 'action',
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
width: '150px', width: '100px',
render: (_text) => ( render: (_text, record) => (
<> <>
<Button <Button
type={'link'} type={'link'}
onClick={() => { onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setIsChangeVisModal(true); setIsChangeVisModal(true);
}} }}
> >
...@@ -198,37 +213,37 @@ function CustomListView() { ...@@ -198,37 +213,37 @@ function CustomListView() {
}, },
{ {
label: '来源', label: '来源',
name: 'form', name: 'portType',
type: 'Select', type: 'Select',
placeholder: '请选择相关来源', placeholder: '请选择相关来源',
options: portTypeList, options: portTypeList,
}, },
{ {
label: '创建时间', label: '创建时间',
name: 'time', name: 'rangeTime',
type: 'rangePicker', type: 'rangePicker',
placeholder: '请选择创建时间', placeholder: '请选择创建时间',
}, },
{ {
label: '企业认证', label: '企业认证',
name: 'enterprise', name: 'companyAuthStatus',
type: 'Select',
placeholder: '请选择是否认证',
options: [
{ value: 1, label: '未认证' },
{ value: 2, label: '已认证' },
],
},
{
label: '电子签约认证',
name: 'contract',
type: 'Select', type: 'Select',
placeholder: '请选择是否认证', placeholder: '请选择是否认证',
options: [ options: [
{ value: 1, label: '未认证' }, { value: 0, label: '未认证' },
{ value: 2, label: '已认证' }, { value: 1, label: '已认证' },
], ],
}, },
// {
// label: '电子签约认证',
// name: 'contract',
// type: 'Select',
// placeholder: '请选择是否认证',
// options: [
// { value: 1, label: '未认证' },
// { value: 2, label: '已认证' },
// ],
// },
]} ]}
searchData={onFinish} searchData={onFinish}
/> />
...@@ -250,12 +265,12 @@ function CustomListView() { ...@@ -250,12 +265,12 @@ function CustomListView() {
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }} // rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/> />
<ChangeModal <ChangeModal
visible={isChangeVisModal} open={isChangeVisModal}
closed={() => { closed={() => {
setIsChangeVisModal(false); setIsChangeVisModal(false);
paginationChange(pagination.current, pagination.pageSize);
}} }}
data={editData} data={editData}
state={{ levelTags: [] }}
/> />
</> </>
); );
......
import { InterListType, InterReqType } from '~/api/interface';
import React, { useEffect } from 'react';
import { Cascader, Form, Input, message, Modal } from 'antd';
import { Uploader } from '~/components/uploader';
import { PlusOutlined } from '@ant-design/icons';
import { MallManageAPI } from '~/api';
import { addCurriculumType, queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import RichText from '~/components/richText';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型
type ReqType = InterReqType<addCurriculumType>;
// 传参类型
interface propType {
title: string;
open: boolean;
closed: any;
data?: TableType[0];
}
const AddEditModal: React.FC<propType> = (props) => {
AddEditModal.defaultProps = {
data: undefined,
};
// 参数
const { title, open, closed, data } = props;
// 课程类型列表
const [curriculumSkillList, setCurriculumSkillList] = React.useState<
{
value: number;
label: string;
children?: Array<{
value: number;
label: string;
}>;
}[]
>([]);
// 表单钩子
const [form] = Form.useForm<ReqType>();
// 关闭弹窗
const handleCancel = () => {
form.resetFields();
closed();
};
// 确认事件
const handleOk = () => {
form
.validateFields()
.then(async (values) => {
// console.log('确认事件 --->', values);
await handleSubmit(values);
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then();
});
};
// 提交事件
const handleSubmit = async (values: ReqType) => {
const res = await MallManageAPI[data?.id ? 'updateCurriculum' : 'addCurriculum']({
...values,
flightSkills: Number((values?.flightSkills as unknown as number[])?.at(-1)),
id: data?.id ? data?.id : null,
});
if (res && res.code === '200') {
message.success('操作成功');
handleCancel();
}
};
// 获取课程类型
const getCurriculumSkillList = async () => {
const res = await MallManageAPI.treeCurriculumSkill({});
if (res && res.code === '200') {
setCurriculumSkillList(
res.result?.map((i) => ({
label: i.skillsName,
value: i.id,
children: i.flightSkills?.map((j) => ({ label: j.skillsName, value: j.id })),
})),
);
// console.log(res);
}
};
// componentDidMount
useEffect(() => {
if (!open) return;
// 获取课程类型
getCurriculumSkillList().then(() => {
// 加载出数据再操作
if (!data) return;
// 反向找数据回显
const flightSkillsName1 = curriculumSkillList.find(
(i) => i.label === data?.flightSkillsName1,
);
const flightSkillsName2 = flightSkillsName1?.children?.find(
(i) => i.label === data?.flightSkillsName2,
);
// 回显数据
form.setFieldsValue({
...data,
flightSkills: [flightSkillsName1?.value, flightSkillsName2?.value],
});
});
}, [open]);
return (
<Modal
open={open}
title={title}
onCancel={handleCancel}
onOk={handleOk}
destroyOnClose
width={600}
>
<Form
name='addForm'
form={form}
labelAlign='right'
autoComplete='new-password'
labelCol={{ span: 3 }}
wrapperCol={{ span: 10 }}
>
<Form.Item
label='课程类型'
name='flightSkills'
rules={[{ required: true, message: '请选择课程类型' }]}
>
<Cascader placeholder={'请选择课程类型'} options={curriculumSkillList} allowClear />
</Form.Item>
<Form.Item
label='课程名称'
name='curriculumName'
rules={[{ required: true, message: '请输入课程名称' }]}
>
<Input placeholder={'请输入课程名称'} maxLength={20} allowClear />
</Form.Item>
<Form.Item
label='课程描述'
name='curriculumDesc'
rules={[{ required: true, message: '请输入课程描述' }]}
>
<Input.TextArea placeholder={'请输入课程描述'} maxLength={20} allowClear showCount />
</Form.Item>
<Form.Item
label='课程封面'
name='surfaceUrl'
rules={[{ required: true, message: '请上传质检照片' }]}
style={{ marginBottom: '-40px' }}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
onChange={(e) => form.setFieldValue('surfaceUrl', e[0].url)}
defaultFileList={data?.surfaceUrl ? [{ url: data?.surfaceUrl }] : []}
>
<PlusOutlined />
</Uploader>
<div style={{ opacity: '0.68', transform: 'scale(0.86) translate(60px, -68px)' }}>
添加图片
<br />
建议尺寸750*420或比例16:9,小于5M的 JPG、PNG格式图片
</div>
</Form.Item>
<Form.Item
label='课程上传'
name='videoUrl'
rules={[{ required: true, message: '请上传质检视频' }]}
style={{ marginBottom: '-40px' }}
>
<Uploader
listType={'picture-card'}
fileUpload
fileLength={1}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
fileSize={10}
onChange={(e) => form.setFieldValue('videoUrl', e[0].url)}
defaultFileList={data?.videoUrl ? [{ url: data?.videoUrl }] : []}
>
<PlusOutlined />
</Uploader>
<div style={{ opacity: '0.68', transform: 'scale(0.86) translate(60px, -68px)' }}>
从本地上传视频
<br />
支持mp4,avi,wmv,mov,flv, rmvb,3gp,m4v,mkv格式; 文件最大不超过1G。
</div>
</Form.Item>
<Form.Item
label='课程详情'
name='detailContent'
rules={[{ required: false, message: '请填写详情' }]}
wrapperCol={{ span: 20 }}
>
<RichText
value={form.getFieldValue('detailContent')}
onChange={(e) => form.setFieldValue('detailContent', e)}
height={250}
/>
</Form.Item>
</Form>
</Modal>
);
};
export default AddEditModal;
import { useEffect, useState } from 'react';
import SearchBox from '~/components/search-box';
import { Button, Table, Image, message, Modal } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { queryCurriculumInfoListType } from '~/api/interface/mallManageType';
import { InterListType, InterReqType } from '~/api/interface';
import { MallManageAPI } from '~/api';
import { ColumnsType } from 'antd/es/table';
import AddEditModal from './comp/addEditModal';
// 表格数据类型
type TableType = InterListType<queryCurriculumInfoListType>;
// 请求数据的类型
type ReqType = InterReqType<queryCurriculumInfoListType>;
// 搜索表单的数据
let query: ReqType = {};
const CourseManageView = () => {
const { confirm } = Modal;
// 是否打开变更弹窗
const [isAddEditVisModal, setIsAddEditVisModal] = useState<boolean>(false);
// 表格分页配置
const [pagination, setPagination] = useState({
total: 0,
pageSize: 10,
current: 1,
totalPage: 0,
});
// 表格数据
const [tableData, setTableData] = useState<TableType>([]);
// 需要编辑的数据
const [editData, setEditData] = useState<TableType[0]>();
// 加载列表
const getTableList = async (value = {}) => {
// 只需要修改这个地方的接口即可
const res = await MallManageAPI.queryCurriculumInfoList({
pageNo: pagination.current,
pageSize: pagination.pageSize,
...value,
...query,
});
if (res && res.code === '200') {
const { list, pageNo, totalCount, pageSize, totalPage } = res.result; // 解构
setPagination({
total: totalCount,
current: pageNo,
pageSize,
totalPage,
});
setTableData(list);
// console.log('加载列表 --->', list);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
getTableList({ pageNo, pageSize }).then();
};
// 表单提交
const onFinish = (data: ReqType) => {
pagination.current = 1;
query = data;
getTableList(data).then();
};
// 删除数据
const handleDelete = (value: TableType[0]) => {
confirm({
title: '提示',
content: '是否删除该课程?',
onOk: async () => {
const res = await MallManageAPI.removeCurriculum({ id: value.id });
if (res && res.code === '200') {
message.success('删除成功');
paginationChange(
tableData.length === 1 ? pagination.current - 1 : pagination.current,
pagination.pageSize,
);
}
},
});
};
// 表格结构
const columns: ColumnsType<TableType[0]> = [
{
title: '课程名称',
dataIndex: 'curriculumName',
align: 'center',
width: '150px',
},
{
title: '课程类型',
dataIndex: 'flightSkillsName1',
align: 'center',
width: '150px',
render: (text, record) => `${text}/${record.flightSkillsName2}`,
},
{
title: '课程类型',
dataIndex: 'curriculumDesc',
align: 'center',
width: '150px',
ellipsis: true,
},
{
title: '封面图',
dataIndex: 'surfaceUrl',
align: 'center',
width: '150px',
render: (text, record) => (
<>
<Image
src={text ? text : `${record.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`}
alt={'封面图'}
style={{ width: '35px', height: '35px' }}
/>
</>
),
},
{
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right',
width: '100px',
render: (_text, record) => (
<>
<Button
type={'link'}
onClick={() => {
setEditData(JSON.parse(JSON.stringify(record)));
setIsAddEditVisModal(true);
}}
>
编辑
</Button>
<Button type={'link'} danger onClick={() => handleDelete(record)}>
删除
</Button>
</>
),
},
];
// componentDidMount
useEffect(() => {
query = {};
(async () => {
await getTableList();
})();
}, []);
return (
<>
<SearchBox
search={[
{
label: '课程名称',
name: 'keyword',
type: 'input',
placeholder: '请输入课程名称',
},
{
label: '课程类型',
name: 'companyAuthStatus',
type: 'Select',
placeholder: '请选择是否认证',
options: [
{ value: 0, label: '未认证' },
{ value: 1, label: '已认证' },
],
},
]}
searchData={onFinish}
child={
<>
<Button
type={'primary'}
icon={<PlusOutlined />}
onClick={() => {
setIsAddEditVisModal(true);
}}
>
新建课程
</Button>
</>
}
/>
<Table
size='small'
dataSource={tableData}
columns={columns}
rowKey='id'
// scroll={{ x: 1200 }}
pagination={{
total: pagination.total,
pageSize: pagination.pageSize,
current: pagination.current,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/>
<AddEditModal
open={isAddEditVisModal}
closed={() => {
setEditData(undefined);
setIsAddEditVisModal(false);
paginationChange(pagination.current, pagination.pageSize);
}}
data={editData}
title={editData?.id ? '编辑' : '新增'}
/>
</>
);
};
export default CourseManageView;
import React, { forwardRef } from 'react';
import { Button, Form, Upload, Input, Radio, Select, Cascader } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import './index.scss';
const BaseInfo: React.FC<any> = forwardRef(() => {
return (
<div className='base-info'>
<div className='base-info-title'>基本信息</div>
<div className='base-info-form'>
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 16 }} initialValues={{ shelfStatus: 1 }}>
<Form.Item
name='mainFileList'
label='商品主图'
rules={[{ required: true, message: '请上传商品主图' }]}
>
<Uploader listType='picture-card'>
<div>上传</div>
</Uploader>
</Form.Item>
<Form.Item label='商品副图' name='subFileList'>
<Uploader listType='picture-card'>
<div>上传</div>
</Uploader>
</Form.Item>
<Form.Item label='商品视频'>
<Upload>
<Button icon={<UploadOutlined />}>上传视频</Button>
</Upload>
</Form.Item>
<Form.Item
name='goodsName'
label='商品名称'
rules={[{ required: true, message: '请输入商品名称' }]}
>
<Input placeholder='请输入商品名称' maxLength={50} style={{ width: '400px' }} />
</Form.Item>
<Form.Item
name='goodsDesc'
label='商品描述'
rules={[{ required: true, message: '请输入商品描述' }]}
>
<Input.TextArea
placeholder='请输入商品描述'
maxLength={70}
style={{ width: '400px' }}
rows={4}
showCount
/>
</Form.Item>
<Form.Item
name='sortTypeId'
label='所属目录'
rules={[{ required: true, message: '请选择所属目录' }]}
>
<Select placeholder='请选择所属目录' style={{ width: '400px' }}>
<Select.Option>1</Select.Option>
</Select>
</Form.Item>
<Form.Item
name='masterTypeId'
label='商品分类'
rules={[{ required: true, message: '请选择商品分类' }]}
>
<Cascader
style={{ width: '400px' }}
fieldNames={{
label: 'goodsMasterType',
value: 'goodsMasterTypeId',
children: 'goodsSlaveTypeDTO',
}}
placeholder='请选择商品分类'
allowClear
/>
</Form.Item>
<Form.Item label='商品标签'>
<Radio.Group>
<Radio value={false}>不加</Radio>
<Radio value></Radio>
</Radio.Group>
</Form.Item>
<Form.Item
name='tag'
label='标签名称'
rules={[{ required: true, message: '请输入标签名称' }]}
>
<Input placeholder='请输入标签名称' style={{ width: '400px' }} maxLength={5} />
</Form.Item>
<Form.Item
label='商品状态'
name='shelfStatus'
rules={[{ required: true, message: '请选择商品状态' }]}
>
<Select placeholder='请选择商品状态' style={{ width: '400px' }}>
<Select.Option value={1}>上架</Select.Option>
<Select.Option value={0}>下架</Select.Option>
</Select>
</Form.Item>
</Form>
</div>
</div>
);
});
export default BaseInfo;
import React, { forwardRef } from 'react';
import { Checkbox, Form, Select, Row, Col } from 'antd';
import './index.scss';
const OtherInfo: React.FC<any> = forwardRef(() => {
return (
<div className='other-info'>
<div className='other-info-title'>其它信息</div>
<div className='other-info-form'>
<Form>
<Form.Item label='搭配服务' name='otherService'>
<Checkbox.Group>
<Checkbox>1</Checkbox>
</Checkbox.Group>
</Form.Item>
<Row>
<Col>
<span>用服务&gt;云享飞:</span>
</Col>
<Col span={8}>
<Form.Item name='shareFlyServiceId'>
<Select
allowClear
placeholder='请选择服务'
showSearch
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
>
<Select.Option>1</Select.Option>
</Select>
</Form.Item>
</Col>
</Row>
<Row>
<Col>
<span>&nbsp;&nbsp;&nbsp;&nbsp;我要租&gt;云仓:</span>
</Col>
<Col span={8}>
<Form.Item name='repoId'>
<Select
allowClear
placeholder='请选择商品'
showSearch
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
>
<Select.Option>1</Select.Option>
</Select>
</Form.Item>
</Col>
</Row>
</Form>
</div>
</div>
);
});
export default OtherInfo;
import SearchBox, { searchColumns } from '~/components/search-box'; import SearchBox, { searchColumns } from '~/components/search-box';
import { useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { Button, Card, Table } from 'antd'; import { Button, Card, Image, message, Table } from 'antd';
import { import {
ArrowDownOutlined, ArrowDownOutlined,
ArrowUpOutlined, ArrowUpOutlined,
...@@ -9,6 +9,17 @@ import { ...@@ -9,6 +9,17 @@ import {
PlusOutlined, PlusOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
import GoodsAPI from '~/api/modules/goodsAPI';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface';
import { listGoodsType } from '~/api/interface/goodsType';
import { CategoryManageAPI } from '~/api';
import { filterObjAttr } from '~/utils';
//商品返回类型
type goodsType = InterDataType<listGoodsType>['list'];
//商品列表筛选类型
type goodsSearchParameters = Omit<InterReqType<listGoodsType>, 'pageNo' | 'pageSize' | 'goodsType'>;
const GoodsList = () => { const GoodsList = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const tabList = [ const tabList = [
...@@ -26,54 +37,173 @@ const GoodsList = () => { ...@@ -26,54 +37,173 @@ const GoodsList = () => {
}, },
]; ];
const [activeTabKey, setActiveTabKey] = useState<string>('1'); const [activeTabKey, setActiveTabKey] = useState<string>('1');
const [searchColumns] = useState<searchColumns[]>([ const [searchColumns, setSearchColumns] = useState<searchColumns[]>([
{ {
label: '商品名称', label: '商品名称',
placeholder: '请输入商品名称', placeholder: '请输入商品名称',
name: '', name: 'goodsName',
type: 'input', type: 'input',
}, },
{ {
label: '所属目录', label: '所属目录',
placeholder: '请选择所属目录', placeholder: '请选择所属目录',
name: '', name: 'directoryId',
type: 'select', type: 'select',
options: [], options: [],
}, },
{ {
label: '创建时间', label: '创建时间',
placeholder: '请输入选择创建时间', placeholder: '请输入选择创建时间',
name: '', name: 'time',
type: 'rangePicker', type: 'rangePicker',
}, },
]); ]);
const tableColumns: ColumnsType<any> = [ const tableColumns: ColumnsType<goodsType[0]> = [
{ title: '序号', align: 'center' }, {
{ title: '图片', align: 'center' }, title: '序号',
{ title: '商品名称', align: 'center' }, align: 'center',
{ title: '所属目录', align: 'center' }, render: (_text: any, _record, index: number) =>
{ title: '创建时间', align: 'center' }, (pagination.pageNo - 1) * pagination.pageSize + index + 1,
{ title: '状态', align: 'center' }, },
{
title: '图片',
align: 'center',
dataIndex: 'imgUrl',
render: (text: string) => <Image src={text} width={50} height={50} />,
},
{ title: '商品名称', align: 'center', dataIndex: 'goodsName' },
{ title: '所属目录', align: 'center', dataIndex: 'directoryName' },
{ title: '创建时间', align: 'center', dataIndex: 'createTime' },
{
title: '状态',
align: 'center',
dataIndex: 'status',
render: (text: number) => (text ? '上架' : '下架'),
},
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
render: () => ( dataIndex: 'id',
render: (id: number) => (
<> <>
<Button type='link'>编辑</Button> <Button type='link' onClick={() => toEditGoods(id)}>
<Button type='link'>详情</Button> 编辑
</Button>
<Button type='link' onClick={() => toGoodsDetail(id)}>
详情
</Button>
</> </>
), ),
}, },
]; ];
const [tableData] = useState<{ id: number }[]>([{ id: 1 }]); const [tableData, setTableData] = useState<goodsType>([]);
//分页
const [pagination, setPagination] = useState<PaginationProps & { totalCount: number }>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
});
//筛选
const [query, setQuery] = useState<goodsSearchParameters>({ status: undefined });
// 表格多选
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onTabChange = (key: string) => { const onTabChange = (key: string) => {
pagination.pageNo = 1;
query.status = key === '1' ? undefined : key === '2' ? 1 : 0;
getGoodsList(query);
setQuery(query);
setActiveTabKey(key); setActiveTabKey(key);
}; };
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageSize = pageSize;
pagination.pageNo = pageNo;
getGoodsList(query);
};
//筛选
const searchSuccess = (data: any) => {
pagination.pageNo = 1;
setQuery(filterObjAttr(data, ['time']));
getGoodsList(filterObjAttr(data, ['time']));
};
//商品列表
const getGoodsList = (query?: goodsSearchParameters) => {
GoodsAPI.getGoodsList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
goodsType: 0,
...query,
}).then(({ result }) => {
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
setPagination(pagination);
});
};
//新增商品 //新增商品
const toAddMallGoods = () => { const toAddMallGoods = () => {
navigate({ pathname: '/mallManage/mallGoods/add' }); navigate({ pathname: '/mallManage/mallGoods/add' });
}; };
//编辑商品
const toEditGoods = (id: number) => {
navigate({
pathname: '/mallManage/mallGoods/add',
search: `id=${id}`,
});
};
//商品详情
const toGoodsDetail = (id: number) => {
navigate({
pathname: '/mallManage/mallGoods/detail',
search: `id=${id}&isDetail=1`,
});
};
// 表格多选事件
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys);
};
//获取目录列表
const getDirectoryList = () => {
CategoryManageAPI.getDirectoryListClone({ type: 4 }).then(({ result }) => {
if (result) {
const options = result.map((v) => ({ id: v.id, name: v.directoryName }));
searchColumns[1].options = options;
setSearchColumns(searchColumns);
}
});
};
//商品-批量上下架
const batchOnShelfOrTakeDown = (status: number) => {
if (selectedRowKeys.length === 0) {
return message.warning('请先选择商品');
}
GoodsAPI.batchOnShelfOrTakeDown({ goodsIds: selectedRowKeys as number[], status }).then(
({ code }) => {
if (code === '200') {
message.success(status ? '上架成功' : '下架成功');
getGoodsList(query);
}
},
);
};
//商品-删除
const deleteGoods = () => {
if (selectedRowKeys.length === 0) {
return message.warning('请先选择商品');
}
GoodsAPI.batchRemoveWareInfo(selectedRowKeys as number[]).then(({ code }) => {
if (code === '200') {
if (pagination.pageNo !== 1 && tableData.length == 1) {
pagination.pageNo -= 1;
}
message.success('删除成功');
getGoodsList(query);
}
});
};
useEffect(() => {
getGoodsList();
getDirectoryList();
}, []);
return ( return (
<div className='goods-list'> <div className='goods-list'>
<SearchBox <SearchBox
...@@ -83,20 +213,54 @@ const GoodsList = () => { ...@@ -83,20 +213,54 @@ const GoodsList = () => {
新增商品 新增商品
</Button> </Button>
} }
searchData={searchSuccess}
/> />
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}> <Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}> <div className='header-operate' style={{ marginBottom: '10px' }}>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowUpOutlined />}> {activeTabKey !== '2' && (
上架 <Button
</Button> type='primary'
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowDownOutlined />}> style={{ marginRight: '10px' }}
下架 icon={<ArrowUpOutlined />}
</Button> onClick={() => batchOnShelfOrTakeDown(1)}
<Button danger icon={<DeleteOutlined />}> >
上架
</Button>
)}
{activeTabKey !== '3' && (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={() => batchOnShelfOrTakeDown(0)}
>
下架
</Button>
)}
<Button danger icon={<DeleteOutlined />} onClick={deleteGoods}>
删除 删除
</Button> </Button>
</div> </div>
<Table columns={tableColumns} bordered dataSource={tableData} /> <Table
columns={tableColumns}
bordered
dataSource={tableData}
rowKey='id'
rowSelection={{
selectedRowKeys,
onChange: onSelectChange,
}}
pagination={{
total: pagination.totalCount,
pageSize: pagination.pageSize,
current: pagination.pageNo,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
</Card> </Card>
</div> </div>
); );
......
...@@ -51,11 +51,25 @@ const SetProduceSpecPriceModal: FC<ModalProps & PropsType> = ({ open, onCancel, ...@@ -51,11 +51,25 @@ const SetProduceSpecPriceModal: FC<ModalProps & PropsType> = ({ open, onCancel,
return { ...pre }; return { ...pre };
}, {}); }, {});
if (result.length) { if (result.length) {
form.setFieldsValue({ ...Obj, level: levelNumber }); //没有设置价格的清空
const setDefaultObj = tagInfoList.reduce((pre: any, cur) => {
if (!Object.keys(Obj).includes(cur.id.toString())) {
pre[cur.id] = undefined;
}
return pre;
}, {});
console.log('数据-->', setDefaultObj);
form.setFieldsValue({ ...Obj, level: levelNumber, ...setDefaultObj });
} else { } else {
//如果没有返回价格,清楚上一次选择的租期价格
const defaultObj = tagInfoList.reduce((pre: any, cur) => {
pre[cur.id] = undefined;
return pre;
}, {});
form.setFieldsValue({ form.setFieldsValue({
0: undefined, 0: undefined,
level: undefined, level: undefined,
...defaultObj,
}); });
} }
const arr = result const arr = result
......
...@@ -157,6 +157,7 @@ function ProduceManage() { ...@@ -157,6 +157,7 @@ function ProduceManage() {
}).then(({ result }) => { }).then(({ result }) => {
setLoading(false); setLoading(false);
setTableData(result.list || []); setTableData(result.list || []);
pagination.totalCount = result.totalCount;
setPagination(pagination); setPagination(pagination);
}); });
}; };
......
.base-info {
&-title {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
&::before {
content: '*';
color: red;
}
}
}
import React, { forwardRef } from 'react';
import { Button, Form, Upload, Input, Radio, Select, Cascader } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import './index.scss';
const BaseInfo: React.FC<any> = forwardRef(() => {
return (
<div className='base-info'>
<div className='base-info-title'>基本信息</div>
<div className='base-info-form'>
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 16 }} initialValues={{ shelfStatus: 1 }}>
<Form.Item
name='mainFileList'
label='商品主图'
rules={[{ required: true, message: '请上传商品主图' }]}
>
<Uploader listType='picture-card'>
<div>上传</div>
</Uploader>
</Form.Item>
<Form.Item label='商品副图' name='subFileList'>
<Uploader listType='picture-card'>
<div>上传</div>
</Uploader>
</Form.Item>
<Form.Item label='商品视频'>
<Upload>
<Button icon={<UploadOutlined />}>上传视频</Button>
</Upload>
</Form.Item>
<Form.Item
name='goodsName'
label='商品名称'
rules={[{ required: true, message: '请输入商品名称' }]}
>
<Input placeholder='请输入商品名称' maxLength={50} style={{ width: '400px' }} />
</Form.Item>
<Form.Item
name='goodsDesc'
label='商品描述'
rules={[{ required: true, message: '请输入商品描述' }]}
>
<Input.TextArea
placeholder='请输入商品描述'
maxLength={70}
style={{ width: '400px' }}
rows={4}
showCount
/>
</Form.Item>
<Form.Item
name='sortTypeId'
label='所属目录'
rules={[{ required: true, message: '请选择所属目录' }]}
>
<Select placeholder='请选择所属目录' style={{ width: '400px' }}>
<Select.Option>1</Select.Option>
</Select>
</Form.Item>
<Form.Item
name='masterTypeId'
label='商品分类'
rules={[{ required: true, message: '请选择商品分类' }]}
>
<Cascader
style={{ width: '400px' }}
fieldNames={{
label: 'goodsMasterType',
value: 'goodsMasterTypeId',
children: 'goodsSlaveTypeDTO',
}}
placeholder='请选择商品分类'
allowClear
/>
</Form.Item>
<Form.Item label='商品标签'>
<Radio.Group>
<Radio value={false}>不加</Radio>
<Radio value></Radio>
</Radio.Group>
</Form.Item>
<Form.Item
name='tag'
label='标签名称'
rules={[{ required: true, message: '请输入标签名称' }]}
>
<Input placeholder='请输入标签名称' style={{ width: '400px' }} maxLength={5} />
</Form.Item>
<Form.Item
label='商品状态'
name='shelfStatus'
rules={[{ required: true, message: '请选择商品状态' }]}
>
<Select placeholder='请选择商品状态' style={{ width: '400px' }}>
<Select.Option value={1}>上架</Select.Option>
<Select.Option value={0}>下架</Select.Option>
</Select>
</Form.Item>
</Form>
</div>
</div>
);
});
export default BaseInfo;
.goods-introduce {
&-title {
font-size: 15px;
font-weight: bold;
margin: 20px 0;
}
&-content {
margin-left: 50px;
}
}
import './index.scss';
import RichText from '~/components/richText';
const GoodsIntroduce = () => {
return (
<div className='goods-introduce'>
<div className='goods-introduce-title'>产品介绍图</div>
<div className='goods-introduce-content'>
<RichText richTextHeight={300} />
</div>
</div>
);
};
export default GoodsIntroduce;
.other-info {
&-title {
font-size: 15px;
font-weight: bold;
margin: 20px 0;
}
&-form {
margin-left: 50px;
}
}
import React, { forwardRef } from 'react';
import { Checkbox, Form, Select, Row, Col } from 'antd';
import './index.scss';
const OtherInfo: React.FC<any> = forwardRef(() => {
return (
<div className='other-info'>
<div className='other-info-title'>其它信息</div>
<div className='other-info-form'>
<Form>
<Form.Item label='搭配服务' name='otherService'>
<Checkbox.Group>
<Checkbox>1</Checkbox>
</Checkbox.Group>
</Form.Item>
<Row>
<Col>
<span>用服务&gt;云享飞:</span>
</Col>
<Col span={8}>
<Form.Item name='shareFlyServiceId'>
<Select
allowClear
placeholder='请选择服务'
showSearch
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
>
<Select.Option>1</Select.Option>
</Select>
</Form.Item>
</Col>
</Row>
<Row>
<Col>
<span>&nbsp;&nbsp;&nbsp;&nbsp;我要租&gt;云仓:</span>
</Col>
<Col span={8}>
<Form.Item name='repoId'>
<Select
allowClear
placeholder='请选择商品'
showSearch
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
>
<Select.Option>1</Select.Option>
</Select>
</Form.Item>
</Col>
</Row>
</Form>
</div>
</div>
);
});
export default OtherInfo;
.stock-sku {
&-title {
font-size: 15px;
font-weight: bold;
margin: 20px 0;
}
&-content {
margin-left: 50px;
}
&-operate {
margin-bottom: 10px;
}
}
import React from 'react';
import { Table, Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import './index.scss';
import { ColumnsType } from 'antd/es/table';
const StockSku: React.FC<any> = () => {
const columns: ColumnsType<any> = [
{
title: '序号',
align: 'center',
render: () => <div>--</div>,
},
{
title: `产品类型`,
align: 'center',
// dataIndex: "goodsTypeId",
render: () => <div>--</div>,
},
{
title: '规格名称',
align: 'center',
dataIndex: 'goodsSpecName',
},
{
title: `方案`,
align: 'center',
dataIndex: 'skuName',
},
{
title: '选项来源',
align: 'center',
dataIndex: 'specIds',
render: () => <div>--</div>,
},
{
title: '选择方式',
align: 'center',
dataIndex: 'chooseType',
render: () => <div>--</div>,
},
{
title: '是否必选',
align: 'center',
dataIndex: 'must',
render: () => <div>--</div>,
},
{
title: '规格单位',
align: 'center',
dataIndex: 'skuUnitId',
render: () => {
return <div>--</div>;
},
},
{
title: '操作',
align: 'center',
width: '20%',
render: () => {
return (
<div>
<Button type='link' style={{ marginRight: '10px' }}>
编辑
</Button>
<Button type='link'>删除</Button>
</div>
);
},
},
];
return (
<div className='stock-sku'>
<div className='stock-sku-title'>库存规格</div>
<div className='stock-sku-content'>
<div className='stock-sku-operate'>
<Button icon={<PlusOutlined />} type='primary'>
添加规格
</Button>
</div>
<Table size='small' bordered rowKey='id' pagination={false} columns={columns} />
</div>
</div>
);
};
export default StockSku;
.rent-info { .goods-info {
&-operate { &-operate {
margin-top: 50px; margin-top: 50px;
display: flex; display: flex;
......
import SearchBox, { searchColumns } from '~/components/search-box'; import SearchBox, { searchColumns } from '~/components/search-box';
import React, { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useState } from 'react'; import { Button, Card, Image, message, Table } from 'antd';
import { Button, Card, Table } from 'antd';
import { import {
ArrowDownOutlined, ArrowDownOutlined,
ArrowUpOutlined, ArrowUpOutlined,
...@@ -9,6 +9,16 @@ import { ...@@ -9,6 +9,16 @@ import {
PlusOutlined, PlusOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
import GoodsAPI from '~/api/modules/goodsAPI';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface';
import { listGoodsType } from '~/api/interface/goodsType';
import { CategoryManageAPI } from '~/api';
import { filterObjAttr } from '~/utils';
//商品返回类型
type goodsType = InterDataType<listGoodsType>['list'];
//商品列表筛选类型
type goodsSearchParameters = Omit<InterReqType<listGoodsType>, 'pageNo' | 'pageSize' | 'goodsType'>;
const RentList = () => { const RentList = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const tabList = [ const tabList = [
...@@ -26,56 +36,175 @@ const RentList = () => { ...@@ -26,56 +36,175 @@ const RentList = () => {
}, },
]; ];
const [activeTabKey, setActiveTabKey] = useState<string>('1'); const [activeTabKey, setActiveTabKey] = useState<string>('1');
const [searchColumns] = useState<searchColumns[]>([ const [searchColumns, setSearchColumns] = useState<searchColumns[]>([
{ {
label: '商品名称', label: '商品名称',
placeholder: '请输入商品名称', placeholder: '请输入商品名称',
name: '', name: 'goodsName',
type: 'input', type: 'input',
}, },
{ {
label: '所属目录', label: '所属目录',
placeholder: '请选择所属目录', placeholder: '请选择所属目录',
name: '', name: 'directoryId',
type: 'select', type: 'select',
options: [], options: [],
}, },
{ {
label: '创建时间', label: '创建时间',
placeholder: '请输入选择创建时间', placeholder: '请输入选择创建时间',
name: '', name: 'time',
type: 'rangePicker', type: 'rangePicker',
}, },
]); ]);
const tableColumns: ColumnsType<any> = [ const tableColumns: ColumnsType<goodsType[0]> = [
{ title: '序号', align: 'center' }, {
{ title: '图片', align: 'center' }, title: '序号',
{ title: '商品名称', align: 'center' }, align: 'center',
{ title: '所属目录', align: 'center' }, render: (_text: any, _record, index: number) =>
{ title: '创建时间', align: 'center' }, (pagination.pageNo - 1) * pagination.pageSize + index + 1,
{ title: '状态', align: 'center' }, },
{
title: '图片',
align: 'center',
dataIndex: 'imgUrl',
render: (text: string) => <Image src={text} width={50} height={50} />,
},
{ title: '商品名称', align: 'center', dataIndex: 'goodsName' },
{ title: '所属目录', align: 'center', dataIndex: 'directoryName' },
{ title: '创建时间', align: 'center', dataIndex: 'createTime' },
{
title: '状态',
align: 'center',
dataIndex: 'status',
render: (text: number) => (text ? '上架' : '下架'),
},
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
render: () => ( dataIndex: 'id',
render: (id: number) => (
<> <>
<Button type='link'>编辑</Button> <Button type='link' onClick={() => toEditGoods(id)}>
<Button type='link'>详情</Button> 编辑
</Button>
<Button type='link' onClick={() => toRentGoodsDetail(id)}>
详情
</Button>
</> </>
), ),
}, },
]; ];
const [tableData] = useState<{ id: number }[]>([{ id: 1 }]); const [tableData, setTableData] = useState<goodsType>([]);
//分页
const [pagination, setPagination] = useState<PaginationProps & { totalCount: number }>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
});
//筛选
const [query, setQuery] = useState<goodsSearchParameters>({ status: undefined });
// 表格多选
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onTabChange = (key: string) => { const onTabChange = (key: string) => {
pagination.pageNo = 1;
query.status = key === '1' ? undefined : key === '2' ? 1 : 0;
getGoodsList(query);
setQuery(query);
setActiveTabKey(key); setActiveTabKey(key);
}; };
//新增租赁商品 const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageSize = pageSize;
pagination.pageNo = pageNo;
getGoodsList(query);
};
//筛选
const searchSuccess = (data: any) => {
pagination.pageNo = 1;
setQuery(filterObjAttr(data, ['time']));
getGoodsList(filterObjAttr(data, ['time']));
};
//商品列表
const getGoodsList = (query?: goodsSearchParameters) => {
GoodsAPI.getGoodsList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
goodsType: 1,
...query,
}).then(({ result }) => {
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
setPagination(pagination);
});
};
//新增商品
const toAddRentGoods = () => { const toAddRentGoods = () => {
navigate({ pathname: '/mallManage/rentGoods/add' }); navigate({ pathname: '/mallManage/rentGoods/add' });
}; };
//编辑商品
const toEditGoods = (id: number) => {
navigate({
pathname: '/mallManage/rentGoods/edit',
search: `id=${id}`,
});
};
//商品详情
const toRentGoodsDetail = (id: number) => {
navigate({
pathname: '/mallManage/rentGoods/detail',
search: `id=${id}&isDetail=1`,
});
};
// 表格多选事件
const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys);
};
//获取目录列表
const getDirectoryList = () => {
CategoryManageAPI.getDirectoryListClone({ type: 4 }).then(({ result }) => {
if (result) {
const options = result.map((v) => ({ id: v.id, name: v.directoryName }));
searchColumns[1].options = options;
setSearchColumns(searchColumns);
}
});
};
//商品-批量上下架
const batchOnShelfOrTakeDown = (status: number) => {
if (selectedRowKeys.length === 0) {
return message.warning('请先选择商品');
}
GoodsAPI.batchOnShelfOrTakeDown({ goodsIds: selectedRowKeys as number[], status }).then(
({ code }) => {
if (code === '200') {
message.success(status ? '上架成功' : '下架成功');
getGoodsList(query);
}
},
);
};
//商品-删除
const deleteGoods = () => {
if (selectedRowKeys.length === 0) {
return message.warning('请先选择商品');
}
GoodsAPI.batchRemoveWareInfo(selectedRowKeys as number[]).then(({ code }) => {
if (code === '200') {
if (pagination.pageNo !== 1 && tableData.length == 1) {
pagination.pageNo -= 1;
}
message.success('删除成功');
getGoodsList(query);
}
});
};
useEffect(() => {
getGoodsList();
getDirectoryList();
}, []);
return ( return (
<div className='rent-list'> <div className='goods-list'>
<SearchBox <SearchBox
search={searchColumns} search={searchColumns}
child={ child={
...@@ -83,20 +212,54 @@ const RentList = () => { ...@@ -83,20 +212,54 @@ const RentList = () => {
新增商品 新增商品
</Button> </Button>
} }
searchData={searchSuccess}
/> />
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}> <Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}> <div className='header-operate' style={{ marginBottom: '10px' }}>
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowUpOutlined />}> {activeTabKey !== '2' && (
上架 <Button
</Button> type='primary'
<Button type='primary' style={{ marginRight: '10px' }} icon={<ArrowDownOutlined />}> style={{ marginRight: '10px' }}
下架 icon={<ArrowUpOutlined />}
</Button> onClick={() => batchOnShelfOrTakeDown(1)}
<Button danger icon={<DeleteOutlined />}> >
上架
</Button>
)}
{activeTabKey !== '3' && (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={() => batchOnShelfOrTakeDown(0)}
>
下架
</Button>
)}
<Button danger icon={<DeleteOutlined />} onClick={deleteGoods}>
删除 删除
</Button> </Button>
</div> </div>
<Table columns={tableColumns} bordered dataSource={tableData} /> <Table
columns={tableColumns}
bordered
dataSource={tableData}
rowKey='id'
rowSelection={{
selectedRowKeys,
onChange: onSelectChange,
}}
pagination={{
total: pagination.totalCount,
pageSize: pagination.pageSize,
current: pagination.pageNo,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) => paginationChange(page, pageSize),
showTotal: (total, range) => `当前 ${range[0]}-${range[1]} 条记录 / 共 ${total} 条数据`,
}}
/>
</Card> </Card>
</div> </div>
); );
......
import { Button } from 'antd'; import { Button } from 'antd';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import './index.scss'; import './index.scss';
import RichText from '~/components/richText';
const ServiceIntroduce = () => { const ServiceIntroduce = () => {
const navigate = useNavigate(); const navigate = useNavigate();
...@@ -19,9 +18,7 @@ const ServiceIntroduce = () => { ...@@ -19,9 +18,7 @@ const ServiceIntroduce = () => {
</Button> </Button>
</div> </div>
<div className='service-introduce-title'></div> <div className='service-introduce-title'></div>
<div className='service-introduce-rich-text'> <div className='service-introduce-rich-text'></div>
<RichText richTextHeight={500} />
</div>
</div> </div>
); );
}; };
......
...@@ -24,6 +24,7 @@ import { ...@@ -24,6 +24,7 @@ import {
AppstoreOutlined, AppstoreOutlined,
CoffeeOutlined, CoffeeOutlined,
UnorderedListOutlined, UnorderedListOutlined,
BookOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
...@@ -44,6 +45,7 @@ import CustomListView from '~/pages/customManage/customList'; ...@@ -44,6 +45,7 @@ import CustomListView from '~/pages/customManage/customList';
import CustomMoneyView from '~/pages/customManage/customMoney'; import CustomMoneyView from '~/pages/customManage/customMoney';
import CustomMoneyDetail from '~/pages/customManage/customMoney/detail'; import CustomMoneyDetail from '~/pages/customManage/customMoney/detail';
import AccountManageView from '~/pages/systemManage/accountManage'; import AccountManageView from '~/pages/systemManage/accountManage';
import CourseManageView from '~/pages/mallManage/courseManage';
// 活动 // 活动
const ActivityList = React.lazy(() => import('src/pages/activityManage/activityList')); //活动管理 const ActivityList = React.lazy(() => import('src/pages/activityManage/activityList')); //活动管理
...@@ -226,6 +228,15 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -226,6 +228,15 @@ export const routerList: Array<RouteObjectType> = [
}, },
children: [ children: [
{ {
path: '/mallManage/courseManage',
element: withLoadingComponent(<CourseManageView />),
meta: {
id: 10190,
icon: <BookOutlined />,
title: '课程管理',
},
},
{
path: '/mallManage/serviceList', path: '/mallManage/serviceList',
element: withLoadingComponent(<ServiceListView />), element: withLoadingComponent(<ServiceListView />),
meta: { meta: {
...@@ -274,6 +285,26 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -274,6 +285,26 @@ export const routerList: Array<RouteObjectType> = [
}, },
}, },
{ {
path: '/mallManage/rentGoods/edit',
element: withLoadingComponent(<RentAddOrEditOrDetailView />),
meta: {
id: 10136,
icon: <SmileOutlined />,
title: '租赁商品编辑',
hidden: true,
},
},
{
path: '/mallManage/rentGoods/detail',
element: withLoadingComponent(<RentAddOrEditOrDetailView />),
meta: {
id: 10136,
icon: <SmileOutlined />,
title: '租赁商品详情',
hidden: true,
},
},
{
path: '/mallManage/mallGoods', path: '/mallManage/mallGoods',
element: withLoadingComponent(<MallGoodsView />), element: withLoadingComponent(<MallGoodsView />),
meta: { meta: {
...@@ -293,6 +324,26 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -293,6 +324,26 @@ export const routerList: Array<RouteObjectType> = [
}, },
}, },
{ {
path: '/mallManage/mallGoods/edit',
element: withLoadingComponent(<MallAddOrEditOrDetailView />),
meta: {
id: 10146,
icon: <SmileOutlined />,
title: '商城商品编辑',
hidden: true,
},
},
{
path: '/mallManage/mallGoods/detail',
element: withLoadingComponent(<MallAddOrEditOrDetailView />),
meta: {
id: 10146,
icon: <SmileOutlined />,
title: '商城商品详情',
hidden: true,
},
},
{
path: '/mallManage/produceList', path: '/mallManage/produceList',
element: withLoadingComponent(<ProduceListView />), element: withLoadingComponent(<ProduceListView />),
meta: { meta: {
...@@ -443,6 +494,7 @@ export const routerList: Array<RouteObjectType> = [ ...@@ -443,6 +494,7 @@ export const routerList: Array<RouteObjectType> = [
id: 26200, id: 26200,
title: '现金管理', title: '现金管理',
icon: <RedEnvelopeOutlined />, icon: <RedEnvelopeOutlined />,
hidden: true,
}, },
}, },
{ {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论