提交 b26c4e6b 作者: 龚洪江

功能:租赁联调(60%)

上级 14d147dd
...@@ -40,3 +40,43 @@ export type rentModeListType = InterItemFunction< ...@@ -40,3 +40,43 @@ export type rentModeListType = InterItemFunction<
{ brandInfoId?: number; productTypeId?: number }, { brandInfoId?: number; productTypeId?: number },
{ modeName: string; id: number; brandInfoId: number; productTypeId: number; tag: string }[] { modeName: string; id: number; brandInfoId: number; productTypeId: number; tag: string }[]
>; >;
//租赁-商品-新增
export type addRentGoodsType = InterFunction<
{
brandInfoId: number;
deviceModeId: number;
leasePartsList: { name: string; number: number; price: number }[];
level: number;
logisticsCompany: number;
maxLeaseTerm: number;
minLeaseTerm: number;
modeOfDelivery: number;
priceStock: {
cashPledge: number;
maxDaysRental: number;
ninetyDaysRental: number;
productSpec: string;
sevenDaysRental: number;
showPrice: number;
skuImage: string;
stock: number;
stockOut: number;
thirtyDaysRental: number;
threeDaysRental: number;
}[];
productDetails: string;
productParam: string;
productTypeId: number;
resourcesList: { type: number; url: string }[];
returnAddress: number;
sellingPoint: string;
shelfStatus: number;
shipAddress: number;
tradeName: string;
specAttrList: { specName: string; specValuesList: { specName: string }[] }[];
},
any
>;
//租赁-商品-租期信息
export type leaseTermInfoType = InterFunction<any, { id: number; leaseDate: string }[]>;
import { import {
addRentGoodsType,
addRentModeType, addRentModeType,
addType, addType,
editBrandInfoType, editBrandInfoType,
getTypeListType, getTypeListType,
leaseTermInfoType,
listBrandInfoType, listBrandInfoType,
rentMakeAddType, rentMakeAddType,
rentModeListType, rentModeListType,
...@@ -37,4 +39,11 @@ export class RentManageAPI { ...@@ -37,4 +39,11 @@ export class RentManageAPI {
static addRentMode: addRentModeType = (data) => axios.post('/pms/brand/addMode', data); static addRentMode: addRentModeType = (data) => axios.post('/pms/brand/addMode', data);
// 租赁-型号-列表 // 租赁-型号-列表
static getRentModeList: rentModeListType = (data) => axios.post('/pms/brand/modeList', data); static getRentModeList: rentModeListType = (data) => axios.post('/pms/brand/modeList', data);
// 租赁-商品-新增
static addRentGoods: addRentGoodsType = (data) =>
axios.post('/pms/lease/goods/addLeaseGoods', data);
// 租赁-商品-租期信息
static getLeaseTermInfo: leaseTermInfoType = () =>
axios.post('/pms/lease/goods/getLeaseTermInfo');
} }
import React, { useState, useEffect } from 'react';
import { Modal, Form, Input, Select, Radio, Button, Table, message, ModalProps } from 'antd';
import { PlusOutlined, UploadOutlined } from '@ant-design/icons';
import type { RadioChangeEvent } from 'antd';
import EditableCell from '~/components/EditableCell';
import { InterDataType } from '~/api/interface';
import { ProduceManageAPI } from '~/api';
import {
cooperationTagType,
productListType,
ProductSpecListType,
} from '~/api/interface/produceManageType';
import { customizeEntity, skuUnitType, specEntity } from '~/api/interface/goodsType';
import { Uploader } from '~/components/uploader';
import ConfigurePriceModal from '../configurePriceModal';
//产品返回类型
type productType = InterDataType<productListType>['list'];
//产品-规格返回类型
type productSpecType = InterDataType<ProductSpecListType>['list'];
//产品-规格单位返回类型
type unitType = InterDataType<skuUnitType>;
//加盟标签返回类型
type cooperationTagResponseType = InterDataType<cooperationTagType>;
interface selfProps {
handleCancel: () => void;
handleOk: (data: specEntity) => void;
currentDesc: number;
curtRowData: Partial<specEntity>;
skuUnitList: unitType;
goodsType: number;
}
// interface tableRowEntity {
// goodsTypeId: number;
// prodOrScheme: any;
// selectSource: any;
// skuUnit: any;
// }
const AddOrEditSkuModal: React.FC<ModalProps & selfProps> = ({
open,
handleCancel,
handleOk,
currentDesc,
curtRowData,
skuUnitList,
goodsType,
}) => {
// 弹窗标题
const [dialogTitle, setDialogTitle] = useState<string>('添加');
// 规格表单
const [skuForm] = Form.useForm<any>();
// 自定义产品表单
const [selfProduct] = Form.useForm<any>();
// 是否自定义产品类型
const [isCustomProd, setIsCustomProd] = useState<boolean>(false);
//产品列表
const [productList, setProductList] = useState<productType>([]);
//产品规格列表
const [productSpecList, setProductSpecList] = useState<productSpecType>([]);
// 配置价格弹窗
const [configurePriceModalShow, setConfigurePriceModalShow] = useState<boolean>(false);
const [customRowData, setCustomRowData] = useState<Partial<customizeEntity>>({
id: -1,
productSpecCPQVO: {},
});
const [selfProductData, setSelfProductData] = useState<customizeEntity[]>([
{
id: 1,
specName: '',
partNo: '',
specImage: '',
fileList: [],
productSpecCPQVO: {},
},
]);
// 等级标签列表
const [tagInfoList, setTagInfoList] = useState<cooperationTagResponseType>([]);
// 自定义id数组
const [selfIds, setSelfIds] = useState<number[]>([]);
// 自定义选项表格
const selfSelectColumns = [
{
title: '选项名称',
align: 'center',
dataIndex: 'specName',
editable: true,
rules: [{ required: true, message: '请输入选项名称' }],
},
{
title: '料号',
align: 'center',
dataIndex: 'partNo',
editable: true,
rules: [{ required: true, message: '请输入料号' }],
},
{
title: '操作',
align: 'center',
width: '220px',
ellipsis: true,
render: (_text: string, record: any, i: number) => {
return (
<div style={{ display: 'flex', alignItems: 'center' }}>
<Uploader
fileUpload
listType='picture-card'
onChange={(fileList) => selfUploadSuccess(fileList, record, i)}
defaultFileList={record.fileList}
>
<UploadOutlined />
</Uploader>
<Button size='small' type='link' onClick={() => configurePriceEvent(record)}>
配置价格
</Button>
{i != 0 ? (
<Button
className='delete'
size='small'
type='link'
onClick={() => deleteSelfProduct(record)}
>
删除
</Button>
) : (
''
)}
</div>
);
},
},
];
const mergedColumns = selfSelectColumns.map((col: any) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record: any) => ({
record,
inputType: col.dataIndex === 'age' ? 'number' : 'text',
dataIndex: col.dataIndex,
title: col.title,
editing: true,
rules: col.rules,
}),
};
});
//
// // 根据所属行业获取方案列表
// const handleIndeTypeSelect = async (id: number) => {
// getIndustrySku(id);
// skuForm.setFieldsValue({
// skuId: undefined,
// specIds: undefined,
// });
// };
//
// 根据选择产品或行业获取选项来源列表
const handleProdOrInduSelected = (id: number) => {
getProductSpecList(id);
};
// // 选项来源选中
const handleSourceSelect = (id: number | string) => {
const values: any[] = skuForm.getFieldValue('specIds');
const obj = productSpecList.find((v) => v.id === id);
if (!obj?.priceList) {
message.warning('所选规格来源未配置好价格,请配置好SKU价格后重新选择!');
const index: number = values.findIndex((i: number) => i === id);
values.splice(index, 1);
}
skuForm.setFieldValue('specIds', values);
};
// // 规格来源切换
const skuSourceRadioChange = (e: RadioChangeEvent) => {
setIsCustomProd(e.target.value === 1);
};
// // 清除表单
const clearEvent = () => {
skuForm.resetFields();
selfProduct.resetFields();
setSelfProductData([
{
id: 1,
specName: '',
partNo: '',
specImage: '',
fileList: [],
productSpecCPQVO: {},
},
]);
setCustomRowData({
id: -1,
productSpecCPQVO: {},
});
setIsCustomProd(false);
};
const onCancel = () => {
// 关闭前恢复初始值
clearEvent();
handleCancel();
};
//获取产品列表
const getProductList = () => {
ProduceManageAPI.listPageProductSku({ pageNo: 1, pageSize: 9999, type: goodsType }).then(
({ result }) => {
setProductList(result.list || []);
},
);
};
//产品-规格
const getProductSpecList = (productSkuId: number, isDetail?: boolean) => {
ProduceManageAPI.listPageProductSpec({ pageNo: 1, pageSize: 9999, productSkuId }).then(
({ result }) => {
setProductSpecList(result.list || []);
if (result.list && !isDetail) {
const ids: number[] = result.list.reduce((pre: number[], cur) => {
return cur.priceList || goodsType === 1 ? [...pre, cur.id] : pre;
}, []);
skuForm.setFieldValue('specIds', ids.length ? ids : undefined);
}
},
);
};
// 添加自定义产品项
const addSelfSelectItem = () => {
setSelfProductData([
...selfProductData,
{
id: selfProductData.length + 1,
specName: '',
partNo: '',
specImage: '',
fileList: [],
productSpecCPQVO: {},
},
]);
};
// 删除自定义产品
const deleteSelfProduct = (record: customizeEntity) => {
const cusObj: customizeEntity | undefined =
curtRowData.customizeInfo &&
curtRowData.customizeInfo.find((i: customizeEntity) => i.id === record.id);
if (cusObj) {
setSelfIds([...selfIds, cusObj.id]);
}
const index: number = selfProductData.findIndex((item: any) => item.id === record.id);
selfProductData.splice(index, 1);
setSelfProductData([...selfProductData]);
};
//自定义商品上传成功
const selfUploadSuccess = (
fileList: {
id: number;
name: string;
uid: number;
url: string;
}[],
record: any,
index: number,
) => {
record.fileList = [
{
uid: `${Math.random()}`,
status: 'done',
url: fileList[0].url,
name: fileList[0].name,
},
];
record.specImage = fileList[0].url;
selfProductData.splice(index, 1, record);
setSelfProductData([...selfProductData]);
};
// 配置价格操作
const configurePriceEvent = (record: customizeEntity) => {
getTagNameList();
setConfigurePriceModalShow(true);
setCustomRowData({ ...record });
};
const configurePriceHandleOk = (specPrice: any, leaseTerm?: number) => {
setConfigurePriceModalShow(false);
const index: number = selfProductData.findIndex(
(i: customizeEntity) => i.id === customRowData.id,
);
selfProductData[index].productSpecCPQVO = {
productSpecId: selfProductData[index].productSpecCPQVO.productSpecId || undefined,
specPrice,
type: goodsType,
leaseTerm,
};
selfProductData.splice(index, 1, selfProductData[index]);
setSelfProductData([...selfProductData]);
};
const configurePriceHandleCancel = () => {
setConfigurePriceModalShow(false);
};
// 获取等级标签
const getTagNameList = () => {
ProduceManageAPI.getCooperationListTag().then(({ result }) => {
setTagInfoList(result || []);
});
};
// 点击确定,触发表单验证
const submitSku = () => {
skuForm.validateFields().then(async (values) => {
if (!isCustomProd) {
let productObj: productType[0] | undefined = undefined;
switch (currentDesc) {
case 2:
// const schemeObj = schemeList.find((i) => i.id === values.skuId);
// values.skuName = schemeObj?.solutionName;
break;
default:
productObj = productList.find((i) => i.id === values.skuId);
values.skuName = productObj?.productName;
}
values.specIds = values.specIds.reduce((pre: any, cur: number | string) => {
const sourceObj = productSpecList.find((i) => i.id === cur);
const specObj: any =
curtRowData?.specIds && curtRowData?.specIds.find((i: any) => i.mallSpecId === cur);
pre.push({
mallSpecId: cur,
specName: sourceObj?.specName,
partNo: sourceObj?.partNo,
id: specObj ? specObj.id : undefined,
});
return pre;
}, []);
handleOk({ ...values, id: curtRowData?.id || Math.random() });
} else {
const res: any = await Promise.all([validateCustomForm()]);
handleOk({
...values,
customizeInfo: res[0],
id: curtRowData?.id || Math.random(),
skuId: curtRowData?.skuId,
skuName: values.productName,
delProductSpecId: selfIds,
});
}
clearEvent();
});
// 验证自定义表单
const validateCustomForm: any = () => {
return new Promise((resolve, reject) => {
selfProduct
.validateFields()
.then(async (values) => {
for (let i = 0; i < selfProductData.length; i++) {
const v = selfProductData[i];
if (!v.specImage) {
return message.warning(`自定义选项第${i + 1}行未上传图片`);
}
}
for (let i = 0; i < selfProductData.length; i++) {
const v = selfProductData[i];
if (!(Object.keys(v.productSpecCPQVO).length != 0 && v.productSpecCPQVO.specPrice)) {
return message.warning(`自定义选项第${i + 1}行未配置价格`);
}
}
const arr: customizeEntity[] = selfProductData.map((i: customizeEntity) => {
return {
specName: values[`specName${i.id}`],
partNo: values[`partNo${i.id}`],
specImage: i.specImage,
productSpecCPQVO: i.productSpecCPQVO,
fileList: i.fileList,
id: i.id,
productSkuId: curtRowData && curtRowData.skuId,
};
});
resolve([...arr]);
})
.catch((err) => {
message.warning(err.errorFields[0].errors[0]).then();
reject([]);
});
});
};
};
useEffect(() => {
if (Object.keys(curtRowData).length !== 0) {
setDialogTitle('编辑');
if (!curtRowData.flag) {
getProductSpecList(curtRowData.skuId as number, true);
}
const specIds: number[] =
curtRowData.specIds && curtRowData.specIds.map((i: any) => i.mallSpecId);
skuForm.setFieldsValue({
goodsSpecName: curtRowData.goodsSpecName,
chooseType: curtRowData.chooseType,
skuUnitId: curtRowData.skuUnitId,
categoryId: curtRowData.categoryId, // 产品类型或所属行业ID
skuId: curtRowData.skuId, // 产品或方案ID
must: curtRowData.must,
specIds, // 选项来源ID数组
productName: curtRowData.flag === 1 ? curtRowData.skuName : undefined,
flag: curtRowData.flag,
});
setIsCustomProd(curtRowData.flag === 1);
if (curtRowData.flag === 1) {
setSelfProductData([...(curtRowData.customizeInfo as customizeEntity[])]);
const objForm: any = curtRowData.customizeInfo?.reduce((pre: any, cur: customizeEntity) => {
pre[`partNo${cur.id}`] = cur.partNo;
pre[`specName${cur.id}`] = cur.specName;
return pre;
}, {});
selfProduct.setFieldsValue(objForm);
}
} else {
setDialogTitle('添加');
}
}, [curtRowData]);
useEffect(() => {
getProductList();
}, []);
return (
<div>
<Modal
open={open}
title={`${dialogTitle}规格`}
onOk={() => submitSku()}
onCancel={onCancel}
width={820}
destroyOnClose
>
<Form
preserve={false}
labelCol={{ span: 5 }}
wrapperCol={{ span: 16 }}
form={skuForm}
initialValues={{ chooseType: 0, skuUnitId: 1, must: 0, flag: 0 }}
>
<Form.Item
label='规格名称'
name='goodsSpecName'
rules={[{ required: true, message: '请输入规格名称' }]}
>
<Input placeholder='请输入规格名称' maxLength={30} />
</Form.Item>
{currentDesc != 2 && (
<Form.Item label='规格来源' name='flag'>
<Radio.Group onChange={skuSourceRadioChange}>
<Radio value={0}>获取</Radio>
<Radio value={1} disabled={goodsType === 1}>
自定义
</Radio>
</Radio.Group>
</Form.Item>
)}
{currentDesc != 2 ? (
<>
{/*<Form.Item*/}
{/* name='categoryId'*/}
{/* label='产品类型'*/}
{/* rules={[{ required: true, message: '请选择产品类型' }]}*/}
{/*>*/}
{/* <Select*/}
{/* placeholder='请选择产品类型'*/}
{/* onSelect={handleProdTypeSelect}*/}
{/* showSearch*/}
{/* filterOption={(input, option: any) =>*/}
{/* (option?.label ?? '').toLowerCase().includes(input.toLowerCase())*/}
{/* }*/}
{/* >*/}
{/* {categoryList.map((item) => (*/}
{/* <Select.Option value={item.id} key={item.id}>*/}
{/* {item.classifyName}*/}
{/* </Select.Option>*/}
{/* ))}*/}
{/* </Select>*/}
{/*</Form.Item>*/}
{!isCustomProd ? (
<Form.Item
name='skuId'
label='产品'
rules={[{ required: true, message: '请选择产品' }]}
>
<Select
placeholder='请选择产品'
onSelect={handleProdOrInduSelected}
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
showSearch
>
{productList.map((item: any) => (
<Select.Option value={item.id} key={item.id}>
{item.productName}
</Select.Option>
))}
</Select>
</Form.Item>
) : (
<Form.Item
name='productName'
label='产品'
rules={[{ required: true, message: '请选择产品' }]}
>
<Input placeholder='请输入产品名称' maxLength={50} />
</Form.Item>
)}
</>
) : (
<>
<Form.Item
label='所属行业'
name='goodsTypeId'
rules={[{ required: true, message: '请选择所属行业' }]}
>
<Select
placeholder='请选择所属行业'
// onSelect={handleIndeTypeSelect}
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
showSearch
>
{/*{categoryList.map((item: categoryEntity) => (*/}
{/* <Select.Option value={item.goodsMasterTypeId} key={item.goodsMasterTypeId}>*/}
{/* {item.goodsMasterType}*/}
{/* </Select.Option>*/}
{/*))}*/}
</Select>
</Form.Item>
<Form.Item
label='方案'
name='skuId'
rules={[{ required: true, message: '请选择方案' }]}
>
<Select
showSearch
placeholder='请选择方案'
// onSelect={handleProdOrInduSelected}
filterOption={(input, option) =>
(option!.children as unknown as string)
.toLowerCase()
.includes(input.toLowerCase())
}
>
{/*{schemeList.map((item: any) => (*/}
{/* <Select.Option value={item.id} key={item.id}>*/}
{/* {item.solutionName}*/}
{/* </Select.Option>*/}
{/*))}*/}
</Select>
</Form.Item>
</>
)}
{isCustomProd ? (
<Form.Item label='自定义选项'>
<div style={{ marginBottom: '10px' }}>
<Button icon={<PlusOutlined />} type='primary' onClick={addSelfSelectItem} />
</div>
<Form form={selfProduct} component={false}>
<Table
size='small'
rowKey='id'
bordered
columns={mergedColumns}
dataSource={selfProductData}
pagination={false}
components={{
body: {
cell: EditableCell,
},
}}
/>
</Form>
</Form.Item>
) : (
<Form.Item
name='specIds'
label='选项来源'
rules={[{ required: true, message: '请选择选项来源' }]}
>
<Select
placeholder='请选择选项来源'
allowClear
mode='multiple'
onSelect={handleSourceSelect}
>
{productSpecList.map((item: any) => (
<Select.Option value={item.id} key={item.id} disabled={item.disabled}>
{item.specName}&nbsp;{item.partNo && `(${item.partNo})`}
</Select.Option>
))}
</Select>
</Form.Item>
)}
<Form.Item label='选择方式' name='chooseType'>
<Radio.Group>
<Radio value={0}>单选</Radio>
<Radio value={1} disabled={goodsType === 1}>
多选
</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label='是否必选' name='must'>
<Radio.Group>
<Radio value={0}>非必选</Radio>
<Radio value={1}>必选</Radio>
</Radio.Group>
</Form.Item>
<Form.Item
label='规格单位'
name='skuUnitId'
rules={[{ required: true, message: '请选择规格单位' }]}
>
<Select placeholder='请选择规格单位'>
{skuUnitList.map((item: any) => {
return (
<Select.Option value={item.id} key={item.id}>
{item.unitName}
</Select.Option>
);
})}
</Select>
</Form.Item>
</Form>
</Modal>
{/*配置价格*/}
<ConfigurePriceModal
open={configurePriceModalShow}
handleOk={configurePriceHandleOk}
handleCancel={configurePriceHandleCancel}
customRowData={customRowData}
tagInfoList={tagInfoList}
goodsType={goodsType}
/>
</div>
);
};
export default AddOrEditSkuModal;
.base-info {
&-title {
font-size: 15px;
font-weight: bold;
margin-bottom: 20px;
&::before {
content: '*';
color: red;
}
}
.goods-video-wrap{
position: relative;
width: 200px;
img{
position: absolute;
right: 0;
top: 0;
transform: translate(50%,-25%);
}
}
}
import React, { forwardRef, useEffect, useState, useImperativeHandle } from 'react';
import { Button, Form, Input, Radio, Select, Cascader } from 'antd';
import { UploadOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader';
import './index.scss';
import { BaseInfoType, detailGoodsType } from '~/api/interface/goodsType';
import { CategoryManageAPI } from '~/api';
import { InterDataType } from '~/api/interface';
import { categoryListType, directoryPageListType } from '~/api/interface/categoryManage';
import deletePng from '~/assets/image/delete.png';
//目录返回类型
type directoryType = InterDataType<directoryPageListType>['list'];
//分类返回类型
type categoryType = InterDataType<categoryListType>['list'];
//商品返回类型
type goodsDetailType = InterDataType<detailGoodsType>;
interface selfProps {
getCategoryList: (id: number) => void;
categoryList: categoryType;
ref: any;
goodsDetail: goodsDetailType | undefined;
isDetail: boolean; //是否详情
goodsType: number; //0:销售,1:租赁
}
const BaseInfo: React.FC<selfProps> = forwardRef(
({ getCategoryList, categoryList, goodsDetail, isDetail, goodsType }: selfProps, ref) => {
const [form] = Form.useForm<
BaseInfoType & {
mainImg: {
id: number;
name: string;
uid: number;
url: string;
}[];
subImg: {
id: number;
name: string;
uid: number;
url: string;
}[];
masterTypeId: number[];
}
>();
//目录
const [directoryList, setDirectoryList] = useState<directoryType>([]);
//是否添加标签
const [isAddTag, setIsAddTag] = useState<boolean>(false);
//主图文件列表
const [mainImgList, setMainImgList] = useState<
{
id: number;
name: string;
uid: number;
url: string;
}[]
>([]);
//副图文件列表
const [subImgList, setSubImgList] = useState<
{
id: number;
name: string;
uid: number;
url: string;
}[]
>([]);
//视频文件列表
const [videoList, setVideoList] = useState<
{
id: number;
name: string;
uid: number;
url: string;
}[]
>([]);
useImperativeHandle(ref, () => ({
baseInform: form,
}));
//获取目录列表
const getDirectoryList = () => {
CategoryManageAPI.getDirectoryListClone({ type: goodsType ? 2 : 4 }).then(({ result }) => {
setDirectoryList(result || []);
});
};
const directorySelectChange = (value: number) => {
form.setFieldsValue({
masterTypeId: undefined,
});
getCategoryList(value);
};
//商品标签
const radioChangeEvent = (e: any) => {
setIsAddTag(e.target.value);
};
//主图上传
const mainImgUploadSuccess = (
fileList: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => {
setMainImgList(fileList);
form.setFieldsValue({
mainImg: fileList,
});
};
//副图上传
const subImgUploadSuccess = (
fileList: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => {
setSubImgList(fileList);
form.setFieldsValue({
subImg: fileList,
});
};
//视频上传
const videoUploadSuccess = (
fileList: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => {
setVideoList(fileList);
form.setFieldsValue({
goodsVideo: fileList[0].url,
});
};
//视频移除
const deleteVideo = () => {
setVideoList([]);
form.setFieldsValue({
goodsVideo: undefined,
});
};
useEffect(() => {
getDirectoryList();
}, []);
useEffect(() => {
if (goodsDetail) {
const goodsMainImg = goodsDetail.images
.filter((v) => v.imgType === 0)
.map((v) => ({
id: v.id,
name: 'mainImg',
uid: v.id,
url: v.imgUrl,
}));
setMainImgList(goodsMainImg);
const goodsSubImg = goodsDetail.images
.filter((v) => v.imgType === 1)
.map((v) => ({
id: v.id,
name: 'sunImg',
uid: v.id,
url: v.imgUrl,
}));
setSubImgList(goodsSubImg);
if (goodsDetail.goodsVideo) {
setVideoList([
{
id: goodsDetail.goodsVideoId || Math.random(),
name: 'video',
uid: goodsDetail.goodsVideoId || Math.random(),
url: goodsDetail.goodsVideo,
},
]);
}
form.setFieldsValue({
mainImg: goodsMainImg,
subImg: goodsSubImg.length ? goodsSubImg : undefined,
goodsVideo: goodsDetail.goodsVideo || undefined,
goodsName: goodsDetail.goodsName,
goodsDesc: goodsDetail.goodsDetail.goodsDesc,
masterTypeId: [goodsDetail.categoryByOne, goodsDetail.categoryByTwo],
directoryId: goodsDetail.directoryId,
shelfStatus: goodsDetail.shelfStatus,
tag: goodsDetail.tag || undefined,
});
setIsAddTag(!!goodsDetail.tag);
}
}, [goodsDetail]);
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={form}
disabled={isDetail}
>
<Form.Item
name='mainImg'
label='商品主图'
rules={[{ required: true, message: '请上传商品主图' }]}
>
<Uploader
listType='picture-card'
fileUpload
onChange={mainImgUploadSuccess}
defaultFileList={mainImgList}
>
<UploadOutlined />
</Uploader>
</Form.Item>
<Form.Item label='商品副图' name='subImg'>
<Uploader
listType={isDetail && subImgList.length === 0 ? 'text' : 'picture-card'}
fileUpload
onChange={subImgUploadSuccess}
fileLength={3}
defaultFileList={subImgList}
>
{isDetail ? subImgList.length ? '' : '暂无' : <UploadOutlined />}
</Uploader>
</Form.Item>
<Form.Item label='商品视频' name='goodsVideo'>
{videoList.length ? (
<div className='goods-video-wrap'>
<video
src={videoList[0].url}
style={{ width: '200px', height: '200px' }}
controls
/>
{!isDetail && <img src={deletePng} alt='删除' onClick={deleteVideo} />}
</div>
) : (
<Uploader
listType='text'
fileUpload
onChange={videoUploadSuccess}
defaultFileList={videoList}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
fileSize={50}
>
{isDetail ? (
videoList.length ? (
''
) : (
'暂无'
)
) : (
<Button icon={<UploadOutlined />}>上传视频</Button>
)}
</Uploader>
)}
</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='directoryId'
label='所属目录'
rules={[{ required: true, message: '请选择所属目录' }]}
>
<Select
placeholder='请选择所属目录'
style={{ width: '400px' }}
onChange={directorySelectChange}
>
{directoryList.map((v) => (
<Select.Option value={v.id} key={v.id}>
{v.directoryName}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
name='masterTypeId'
label='商品分类'
rules={[{ required: true, message: '请选择商品分类' }]}
>
<Cascader
style={{ width: '400px' }}
options={categoryList}
fieldNames={{
label: 'classifyName',
value: 'id',
children: 'children',
}}
placeholder='请选择商品分类'
allowClear
/>
</Form.Item>
<Form.Item label='商品标签'>
<Radio.Group onChange={radioChangeEvent} value={isAddTag}>
<Radio value={false}>不加</Radio>
<Radio value={true}></Radio>
</Radio.Group>
</Form.Item>
{isAddTag && (
<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, { 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 === 1 && (
<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;
.goods-introduce {
&-title {
font-size: 15px;
font-weight: bold;
margin: 20px 0;
}
&-content {
margin-left: 50px;
}
}
.ql-container {
height: 400px;
}
import './index.scss';
import RichText from '~/components/richText';
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 (
<div className='goods-introduce'>
<div className='goods-introduce-title'>产品介绍图</div>
<div className='goods-introduce-content'>
<RichText
richTextContent={goodsDetail?.goodsDetail.content}
onChange={richTextChange}
isDetail={isDetail}
/>
</div>
</div>
);
};
export default GoodsIntroduce;
.other-info {
&-title {
font-size: 15px;
font-weight: bold;
margin: 20px 0;
}
&-form {
margin-left: 50px;
}
}
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;
.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';
import { customizeEntity, skuUnitType, specEntity } from '~/api/interface/goodsType';
import { InterDataType } from '~/api/interface';
//产品-规格单位返回类型
type unitType = InterDataType<skuUnitType>;
interface selfProps {
addOrEditSku: (record?: specEntity) => void;
specData: specEntity[];
skuUnitList: unitType;
deleteSku: (record: specEntity) => void;
isDetail: boolean;
}
//机构列表
const StockSku: React.FC<selfProps> = ({
addOrEditSku,
specData,
skuUnitList,
deleteSku,
isDetail,
}) => {
const columns: ColumnsType<specEntity> = [
{
title: '序号',
align: 'center',
render: (_text: string, _record: specEntity, index: number) => index + 1,
},
{
title: '规格名称',
align: 'center',
dataIndex: 'goodsSpecName',
},
{
title: `方案`,
align: 'center',
dataIndex: 'skuName',
},
{
title: '选项来源',
align: 'center',
dataIndex: 'specIds',
render: (_text: string, record) => (
<div>
{record.flag !== 1
? record.specIds.map((i: any, j: number) => (
<div key={j}>
{i.specName}
{i.partNo && `(${i.partNo})`}
</div>
))
: record.customizeInfo &&
record.customizeInfo.map((i, index: number) => (
<div key={index}>{getSelfSpecName(i)}</div>
))}
</div>
),
},
{
title: '选择方式',
align: 'center',
dataIndex: 'chooseType',
render: (text: number) => <div>{text === 0 ? '单选' : '多选'}</div>,
},
{
title: '是否必选',
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 getSkuUnitName = (id: number) => {
const unitObj = skuUnitList.find((i) => i.id === id);
return unitObj?.unitName;
};
return (
<div className='stock-sku'>
<div className='stock-sku-title'>库存规格</div>
<div className='stock-sku-content'>
{!isDetail && (
<div className='stock-sku-operate'>
<Button icon={<PlusOutlined />} type='primary' onClick={() => addOrEditSkuClick()}>
添加规格
</Button>
</div>
)}
<Table
size='small'
bordered
dataSource={specData}
rowKey='id'
pagination={false}
columns={isDetail ? columns.filter((v) => v.title !== '操作') : columns}
/>
</div>
</div>
);
};
export default StockSku;
import { Button, Col, Form, Input, message, Row, Select, Table, Tag } from 'antd';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
import { forwardRef, useImperativeHandle, useState } from 'react';
import { filterObjAttr } from '~/utils';
import EditableCell from '~/components/EditableCell';
type EditableTableProps = Parameters<typeof Table>[0];
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
interface selfProps {
tableData: any;
updateTableData: (tableData: any) => void;
defaultColumns: (ColumnTypes[number] & {
editable?: boolean;
dataIndex?: string;
inputType?: string;
radioOption?: { name: string; id: number }[];
rules?: any;
maxLength?: number;
children?: any;
placeholder?: string;
})[];
updateDefaultColumns: (
columns: (ColumnTypes[number] & {
editable?: boolean;
dataIndex?: string;
inputType?: string;
radioOption?: { name: string; id: number }[];
rules?: any;
maxLength?: number;
children?: any;
placeholder?: string;
})[],
) => void;
uploadSuccess?: (record: any, fileList: any) => void; //可编辑表单存在上传图片的时候
ref: any;
}
//规格表单数据类型
type specificationFormListType = {
optionList: { label: string; value: string }[];
id: number;
name: string;
addSpecificationValueShow: boolean;
specificationValueList: { name: string; id: number; specificationName: string }[];
};
const CommonSkuInfo = forwardRef<any, selfProps>(
({ tableData, updateTableData, defaultColumns, updateDefaultColumns, uploadSuccess }, ref) => {
//规格项表单
const [form] = Form.useForm<{ [x: string]: string }>();
//可编辑表格表单
const [skuValueForm] = Form.useForm<{ [x: string]: string }>();
//规格表单数组
const [specificationFormList, setSpecificationFormList] = useState<specificationFormListType[]>(
[
{
id: Math.random(),
name: `specName`,
optionList: [],
specificationValueList: [],
addSpecificationValueShow: false,
},
],
);
useImperativeHandle(ref, () => ({
getSpecificationForm: () => form,
getSpecificationValueForm: () => skuValueForm,
getSpecificationFormList: () => specificationFormList,
updateSpecificationFormList: (value: specificationFormListType[]) =>
setSpecificationFormList(value),
}));
//新增规格项目
const addSpecificationClick = () => {
setSpecificationFormList([
...specificationFormList,
{
id: Math.random(),
name: `specName${specificationFormList.length + 1}`,
optionList: [],
specificationValueList: [],
addSpecificationValueShow: false,
},
]);
};
// 删除规格项目
const deleteSpecificationClick = (index: number) => {
form.setFieldValue(specificationFormList[index].name, undefined);
specificationFormList.splice(index, 1);
combineSpecificationValue();
setSpecificationFormList([...specificationFormList]);
};
//规格项名称输入完成
const specificationPressEnter = (e: any, index: number) => {
specificationFormList[index].optionList = e.target.value
? [{ label: e.target.value, value: e.target.value }]
: [];
form.setFieldValue(specificationFormList[index].name, e.target.value);
setSpecificationFormList([...specificationFormList]);
};
//规格值添加
const addSpecificationValueClick = (index: number) => {
specificationFormList[index].addSpecificationValueShow = true;
setSpecificationFormList([...specificationFormList]);
};
//存在
const specificationValuePressEnter = (e: any, index: number) => {
const isExist = specificationFormList[index].specificationValueList.some(
(v) => v.name === e.target.value,
);
if (isExist) {
return message.warning('该规格值已存在');
}
specificationFormList[index].specificationValueList.push({
id: Math.random(),
name: e.target.value,
specificationName: specificationFormList[index].optionList[0].value,
});
combineSpecificationValue();
setSpecificationFormList(specificationFormList);
specificationValueCancel(index);
};
//规格值添加-取消
const specificationValueCancel = (index: number) => {
specificationFormList[index].addSpecificationValueShow = false;
setSpecificationFormList([...specificationFormList]);
};
//规格值-删除
const specificationValueDelete = (i: number, j: number) => {
specificationFormList[i].specificationValueList.splice(j, 1);
combineSpecificationValue();
setSpecificationFormList([...specificationFormList]);
};
//组合数据
const combineSpecificationValue = () => {
let combineSpecificationList: any = [];
let tableDataList: any = [];
//过滤规格值为空的
const filterSpecificationFormList = specificationFormList.filter(
(v) => v.specificationValueList.length,
);
if (filterSpecificationFormList.length > 1) {
const combineList = filterSpecificationFormList.reduce((pre: any, cur, currentIndex) => {
// 首次组合两个数据
if (currentIndex === 0 && filterSpecificationFormList.length > 1) {
combineSpecificationList = combineEvent(
cur.specificationValueList,
filterSpecificationFormList[currentIndex + 1].specificationValueList,
);
//二维数组拆分为对象
combineSpecificationList = getCombineObj(combineSpecificationList);
// 两个数据以上的组合
} else if (
currentIndex < filterSpecificationFormList.length - 1 &&
filterSpecificationFormList[currentIndex + 1].specificationValueList.length
) {
// 上一次的组合作为下一次组合的参数
combineSpecificationList = combineEvent(
combineSpecificationList,
filterSpecificationFormList[currentIndex + 1].specificationValueList,
);
//二维数组拆分为对象
combineSpecificationList = getCombineObj(combineSpecificationList);
}
pre = combineSpecificationList;
return pre;
}, []);
tableDataList = combineList.reduce((pre: any, cur: any) => {
const tabCovertObj = cur.reduce((a: any, b: any, currentIndex: number) => {
a['name' + (currentIndex + 1)] = b.name;
a['specificationName' + (currentIndex + 1)] = b.specificationName;
return a;
}, {});
//判断表格中是否已存在该条(缓存)
const tableItemObj = tableData.find((i: any) =>
Object.getOwnPropertyNames(tabCovertObj).every((key) => i[key] === tabCovertObj[key]),
);
pre.push({
...tabCovertObj,
id: tableItemObj ? tableItemObj.id : Math.random(), //存在则用之前的id,不存在新建id
fileList: tableItemObj ? tableItemObj.fileList : [],
});
return pre;
}, []);
} else if (filterSpecificationFormList.length === 1) {
//当存在一个规格项时
tableDataList = filterSpecificationFormList[0].specificationValueList.map((v) => {
const obj = Object.create(null);
obj['name1'] = v.name;
obj['specificationName1'] = v.specificationName;
//判断表格中是否已存在该条(缓存)
const tableItemObj = tableData.find((i: any) =>
Object.getOwnPropertyNames(obj).every((key) => i[key] === obj[key]),
);
obj['id'] = Math.random();
return tableItemObj ? tableItemObj : obj; //存在则用之前的一条,不存在新建一条
});
}
if (tableDataList.length) {
setTableFormDefault(tableDataList);
mergeTableRow(filterSpecificationFormList);
}
updateTableData([...tableDataList]);
};
//组合数据拆分为对象
const getCombineObj = (combineSpecificationList: any) => {
return combineSpecificationList.reduce((pre: any, cur: any) => {
pre.push(
cur.reduce((a: any, b: any) => {
if (Array.isArray(b)) {
a.push(...b);
} else {
a.push({ ...b });
}
return a;
}, []),
);
return pre;
}, []);
};
//两数组排列组合(通用)
const combineEvent = (list1: any, list2: any) => {
return list1.reduce((pre: any, cur: any) => pre.concat(list2.map((v: any) => [cur, v])), []);
};
//表头拆分及合并列
const mergeTableRow = (filterSpecificationFormList: specificationFormListType[]) => {
const columns = filterSpecificationFormList.map((v, index) => ({
title: v.optionList[0].value,
dataIndex: 'name' + (index + 1),
align: 'center',
onCell: (_: any, i: number) => {
//合并列
if (index < filterSpecificationFormList.length - 1) {
const count: number = filterSpecificationFormList
.slice(index + 1, filterSpecificationFormList.length)
.reduce((pre: number, cur) => {
return pre * cur.specificationValueList.length;
}, 1);
return {
rowSpan: count !== 1 ? ((i + 1) % count === 1 ? count : 0) : 1,
};
} else {
return {
rowSpan: 1,
};
}
},
}));
defaultColumns[0].children = columns;
updateDefaultColumns([...defaultColumns]);
};
//排列组合规格值表单默认数据
const setTableFormDefault = (tableDataList: any) => {
const tableFormDefault = tableDataList.reduce((pre: any, cur: any) => {
return {
...pre,
...Object.getOwnPropertyNames(filterObjAttr(cur, ['id'])).reduce((a: any, b) => {
a[b + cur.id] = cur[b];
return a;
}, {}),
};
}, {});
skuValueForm.setFieldsValue(tableFormDefault);
};
const covertColumns = () => {
return defaultColumns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record: any) => ({
record,
dataIndex: col.dataIndex,
title: col.title,
editing: col.editable,
radioOption: col.radioOption,
inputType: col.inputType,
uploadSuccess: col.inputType === 'uploader' ? uploadSuccess : undefined,
rules: col.rules,
placeholder: col.placeholder,
}),
};
});
};
return (
<div className='common-sku-info'>
<Form wrapperCol={{ span: 5 }} labelCol={{ span: 1 }} form={form}>
{specificationFormList.map((v, index) => (
<>
{/* 规格项*/}
<Row key={v.id}>
<Col span={7}>
<Form.Item
label={'规格项' + (index + 1)}
wrapperCol={{ span: 18 }}
labelCol={{ span: 5 }}
name={v.name}
rules={[{ required: true, message: `请输入规格项${index + 1}` }]}
>
<Select
placeholder='请输入规格项,按回车键完成'
dropdownRender={(menu) => (
<>
{v.optionList.length ? menu : ''}
<Input
onPressEnter={(e) => specificationPressEnter(e, index)}
maxLength={30}
/>
</>
)}
options={v.optionList}
/>
</Form.Item>
</Col>
{index ? (
<Col span={2}>
<Button
danger
icon={<DeleteOutlined />}
onClick={() => deleteSpecificationClick(index)}
>
删除
</Button>
</Col>
) : (
''
)}
</Row>
{/*规格值显示*/}
{v.specificationValueList.length ? (
<Row style={{ marginBottom: '10px' }}>
<Col span={2}></Col>
<Col span={4}>
<div>
{v.specificationValueList.map((v, i) => (
<Tag key={v.id} closable onClose={() => specificationValueDelete(index, i)}>
{v.name}
</Tag>
))}
</div>
</Col>
</Row>
) : (
''
)}
{/*规格值操作*/}
{v.optionList.length ? (
<Row>
<Col span={2}></Col>
<Col span={4} style={{ marginBottom: '10px' }}>
{v.addSpecificationValueShow ? (
<Input
placeholder='请输入规格值,按回车键完成'
onPressEnter={(e) => specificationValuePressEnter(e, index)}
maxLength={30}
/>
) : (
<Button
type='link'
danger
icon={<PlusOutlined />}
onClick={() => addSpecificationValueClick(index)}
>
添加规格值
</Button>
)}
</Col>
{v.addSpecificationValueShow ? (
<Col>
<Button
type='primary'
style={{ marginLeft: '10px' }}
onClick={() => specificationValueCancel(index)}
>
取消
</Button>
</Col>
) : (
''
)}
</Row>
) : (
''
)}
</>
))}
<Row>
<Col span={2}></Col>
<Col>
<Button type='primary' icon={<PlusOutlined />} onClick={addSpecificationClick}>
添加规格
</Button>
</Col>
</Row>
</Form>
{tableData.length ? (
<Form form={skuValueForm}>
<Table
style={{ marginTop: '10px' }}
rowKey='id'
columns={covertColumns() as ColumnTypes}
components={{
body: {
cell: EditableCell,
},
}}
bordered
dataSource={tableData}
pagination={false}
size='small'
/>
</Form>
) : (
''
)}
</div>
);
},
);
export default CommonSkuInfo;
...@@ -54,7 +54,6 @@ export const Uploader: React.FC<PropsType> = (props) => { ...@@ -54,7 +54,6 @@ export const Uploader: React.FC<PropsType> = (props) => {
listType, listType,
fileList, fileList,
beforeUpload: (res) => { beforeUpload: (res) => {
console.log('文件类型-->', res);
const isType = fileType?.includes(res.type); const isType = fileType?.includes(res.type);
const isSize = res.size / 1024 / 1024 < (fileSize || 2); const isSize = res.size / 1024 / 1024 < (fileSize || 2);
if (!isType) { if (!isType) {
......
import { Button, Col, Form, Input, message, Row, Select, Table, Tag } from 'antd'; import { Table } from 'antd';
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons'; import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { isEmptyBol, regPriceNumber } from '~/utils/validateUtils'; import { isEmptyBol, regPriceNumber } from '~/utils/validateUtils';
import EditableCell from '~/components/EditableCell';
import { InterDataType, InterReqType } from '~/api/interface'; import { InterDataType, InterReqType } from '~/api/interface';
import { addMallGoodsType, mallGoodsDetailsType } from '~/api/interface/goodsType'; import { addMallGoodsType, mallGoodsDetailsType } from '~/api/interface/goodsType';
import { filterObjAttr } from '~/utils'; import { filterObjAttr } from '~/utils';
import CommonSkuInfo from '~/components/goods/commonSkuInfo';
type EditableTableProps = Parameters<typeof Table>[0]; type EditableTableProps = Parameters<typeof Table>[0];
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>; type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
...@@ -36,10 +35,7 @@ interface selfProps { ...@@ -36,10 +35,7 @@ interface selfProps {
} }
const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
//规格项表单 const commonSkuInfoRef = useRef<any>();
const [form] = Form.useForm<{ [x: string]: string }>();
//可编辑表格表单
const [skuValueForm] = Form.useForm<{ [x: string]: string }>();
//表格数据 //表格数据
const [tableData, setTableData] = useState<(skuTableType & { [key: string]: string })[]>([]); const [tableData, setTableData] = useState<(skuTableType & { [key: string]: string })[]>([]);
...@@ -153,200 +149,12 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -153,200 +149,12 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
inputType: 'number', inputType: 'number',
}, },
]); ]);
const covertColumns = () => {
return defaultColumns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record: any) => ({
record,
dataIndex: col.dataIndex,
title: col.title,
editing: col.editable,
radioOption: col.radioOption,
inputType: col.inputType,
uploadSuccess: col.inputType === 'uploader' ? uploadSuccess : undefined,
rules: col.rules,
placeholder: col.placeholder,
}),
};
});
};
//规格表单数组
const [specificationFormList, setSpecificationFormList] = useState<specificationFormListType[]>([
{
id: Math.random(),
name: `specName`,
optionList: [],
specificationValueList: [],
addSpecificationValueShow: false,
},
]);
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
submitSku, submitSku,
getForm: () => skuValueForm, getForm: () => commonSkuInfoRef.current.getSpecificationValueForm(),
})); }));
//新增规格项目
const addSpecificationClick = () => {
setSpecificationFormList([
...specificationFormList,
{
id: Math.random(),
name: `specName${specificationFormList.length + 1}`,
optionList: [],
specificationValueList: [],
addSpecificationValueShow: false,
},
]);
};
// 删除规格项目
const deleteSpecificationClick = (index: number) => {
console.log('数据-->', specificationFormList[index]);
form.setFieldValue(specificationFormList[index].name, undefined);
specificationFormList.splice(index, 1);
combineSpecificationValue();
setSpecificationFormList([...specificationFormList]);
};
//规格项名称输入完成
const specificationPressEnter = (e: any, index: number) => {
specificationFormList[index].optionList = e.target.value
? [{ label: e.target.value, value: e.target.value }]
: [];
form.setFieldValue(specificationFormList[index].name, e.target.value);
setSpecificationFormList([...specificationFormList]);
};
//规格值添加
const addSpecificationValueClick = (index: number) => {
specificationFormList[index].addSpecificationValueShow = true;
setSpecificationFormList([...specificationFormList]);
};
//存在
const specificationValuePressEnter = (e: any, index: number) => {
const isExist = specificationFormList[index].specificationValueList.some(
(v) => v.name === e.target.value,
);
if (isExist) {
return message.warning('该规格值已存在');
}
specificationFormList[index].specificationValueList.push({
id: Math.random(),
name: e.target.value,
specificationName: specificationFormList[index].optionList[0].value,
});
combineSpecificationValue();
setSpecificationFormList(specificationFormList);
specificationValueCancel(index);
};
//规格值添加-取消
const specificationValueCancel = (index: number) => {
specificationFormList[index].addSpecificationValueShow = false;
setSpecificationFormList([...specificationFormList]);
};
//规格值-删除
const specificationValueDelete = (i: number, j: number) => {
specificationFormList[i].specificationValueList.splice(j, 1);
combineSpecificationValue();
setSpecificationFormList([...specificationFormList]);
};
//组合数据
const combineSpecificationValue = () => {
let combineSpecificationList: any = [];
let tableDataList: any = [];
//过滤规格值为空的
const filterSpecificationFormList = specificationFormList.filter(
(v) => v.specificationValueList.length,
);
if (filterSpecificationFormList.length > 1) {
const combineList = filterSpecificationFormList.reduce((pre: any, cur, currentIndex) => {
// 首次组合两个数据
if (currentIndex === 0 && filterSpecificationFormList.length > 1) {
combineSpecificationList = combineEvent(
cur.specificationValueList,
filterSpecificationFormList[currentIndex + 1].specificationValueList,
);
//二维数组拆分为对象
combineSpecificationList = getCombineObj(combineSpecificationList);
// 两个数据以上的组合
} else if (
currentIndex < filterSpecificationFormList.length - 1 &&
filterSpecificationFormList[currentIndex + 1].specificationValueList.length
) {
// 上一次的组合作为下一次组合的参数
combineSpecificationList = combineEvent(
combineSpecificationList,
filterSpecificationFormList[currentIndex + 1].specificationValueList,
);
//二维数组拆分为对象
combineSpecificationList = getCombineObj(combineSpecificationList);
}
pre = combineSpecificationList;
return pre;
}, []);
tableDataList = combineList.reduce((pre: any, cur: any) => {
const tabCovertObj = cur.reduce((a: any, b: any, currentIndex: number) => {
a['name' + (currentIndex + 1)] = b.name;
a['specificationName' + (currentIndex + 1)] = b.specificationName;
return a;
}, {});
//判断表格中是否已存在该条(缓存)
const tableItemObj = tableData.find((i) =>
Object.getOwnPropertyNames(tabCovertObj).every((key) => i[key] === tabCovertObj[key]),
);
pre.push({
...tabCovertObj,
id: tableItemObj ? tableItemObj.id : Math.random(), //存在则用之前的id,不存在新建id
fileList: tableItemObj ? tableItemObj.fileList : [],
});
return pre;
}, []);
} else if (filterSpecificationFormList.length === 1) {
//当存在一个规格项时
tableDataList = filterSpecificationFormList[0].specificationValueList.map((v) => {
const obj = Object.create(null);
obj['name1'] = v.name;
obj['specificationName1'] = v.specificationName;
//判断表格中是否已存在该条(缓存)
const tableItemObj = tableData.find((i) =>
Object.getOwnPropertyNames(obj).every((key) => i[key] === obj[key]),
);
obj['id'] = Math.random();
return tableItemObj ? tableItemObj : obj; //存在则用之前的一条,不存在新建一条
});
}
if (tableDataList.length) {
setTableFormDefault(tableDataList);
mergeTableRow(filterSpecificationFormList);
}
setTableData([...tableDataList]);
};
//组合数据拆分为对象
const getCombineObj = (combineSpecificationList: any) => {
return combineSpecificationList.reduce((pre: any, cur: any) => {
pre.push(
cur.reduce((a: any, b: any) => {
if (Array.isArray(b)) {
a.push(...b);
} else {
a.push({ ...b });
}
return a;
}, []),
);
return pre;
}, []);
};
//两数组排列组合(通用)
const combineEvent = (list1: any, list2: any) => {
return list1.reduce((pre: any, cur: any) => pre.concat(list2.map((v: any) => [cur, v])), []);
};
//表头拆分及合并列 //表头拆分及合并列
const mergeTableRow = (filterSpecificationFormList: specificationFormListType[]) => { const mergeTableRow = (filterSpecificationFormList: specificationFormListType[]) => {
const columns = filterSpecificationFormList.map((v, index) => ({ const columns = filterSpecificationFormList.map((v, index) => ({
...@@ -390,7 +198,7 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -390,7 +198,7 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
tableData[tableIndex].fileList = fileList; tableData[tableIndex].fileList = fileList;
const obj = Object.create(null); const obj = Object.create(null);
obj['skuImage' + record.id] = fileList.length ? fileList[0].url : undefined; obj['skuImage' + record.id] = fileList.length ? fileList[0].url : undefined;
skuValueForm.setFieldsValue(obj); commonSkuInfoRef.current.getSpecificationValueForm().setFieldsValue(obj);
setTableData([...tableData]); setTableData([...tableData]);
} }
}; };
...@@ -398,9 +206,12 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -398,9 +206,12 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
//提交验证 //提交验证
const submitSku = () => { const submitSku = () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
form commonSkuInfoRef.current
.getSpecificationForm()
.validateFields() .validateFields()
.then(() => { .then(() => {
const specificationFormList: specificationFormListType[] =
commonSkuInfoRef.current.getSpecificationFormList();
const specificationFormItem = specificationFormList.find( const specificationFormItem = specificationFormList.find(
(v) => !v.specificationValueList.length, (v) => !v.specificationValueList.length,
); );
...@@ -422,9 +233,10 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -422,9 +233,10 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
: undefined, : undefined,
})), })),
})); }));
skuValueForm commonSkuInfoRef.current
.getSpecificationValueForm()
.validateFields() .validateFields()
.then((value) => { .then((value: any) => {
//规格值数据转化 //规格值数据转化
const priceStock = tableData.reduce((pre: any, cur: any) => { const priceStock = tableData.reduce((pre: any, cur: any) => {
//规格名,规格值组合类型 //规格名,规格值组合类型
...@@ -448,12 +260,12 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -448,12 +260,12 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
}, []); }, []);
resolve({ priceStock, specAttrList }); resolve({ priceStock, specAttrList });
}) })
.catch((err) => { .catch((err: any) => {
reject(err); reject(err);
}); });
} }
}) })
.catch((err) => { .catch((err: any) => {
reject(err); reject(err);
}); });
}); });
...@@ -469,7 +281,15 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -469,7 +281,15 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
}, {}), }, {}),
}; };
}, {}); }, {});
skuValueForm.setFieldsValue(tableFormDefault); commonSkuInfoRef.current.getSpecificationValueForm().setFieldsValue(tableFormDefault);
};
//更新表单
const updateTableData = (tableData: any) => {
setTableData([...tableData]);
};
//更新表单列
const updateDefaultColumns = (columns: any) => {
setDefaultColumns([...columns]);
}; };
useEffect(() => { useEffect(() => {
...@@ -494,8 +314,8 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -494,8 +314,8 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
}, },
{}, {},
); );
form.setFieldsValue(specFormDefault); commonSkuInfoRef.current.getSpecificationForm().setFieldsValue(specFormDefault);
setSpecificationFormList([...covertSpecAttrList]); commonSkuInfoRef.current.updateSpecificationFormList([...covertSpecAttrList]);
mergeTableRow(covertSpecAttrList); mergeTableRow(covertSpecAttrList);
const tableDataList: (skuTableType & { [key: string]: string })[] = const tableDataList: (skuTableType & { [key: string]: string })[] =
goodsDetailsInfo.priceStock.map((v) => ({ goodsDetailsInfo.priceStock.map((v) => ({
...@@ -524,136 +344,14 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => { ...@@ -524,136 +344,14 @@ const SkuInfo = forwardRef<any, selfProps>(({ goodsDetailsInfo }, ref) => {
return ( return (
<div className='sku-info'> <div className='sku-info'>
<Form wrapperCol={{ span: 5 }} labelCol={{ span: 1 }} form={form}> <CommonSkuInfo
{specificationFormList.map((v, index) => ( tableData={tableData}
<> updateTableData={updateTableData}
{/* 规格项*/} defaultColumns={defaultColumns}
<Row key={v.id}> updateDefaultColumns={updateDefaultColumns}
<Col span={7}> uploadSuccess={uploadSuccess}
<Form.Item ref={commonSkuInfoRef}
label={'规格项' + (index + 1)}
wrapperCol={{ span: 18 }}
labelCol={{ span: 5 }}
name={v.name}
rules={[{ required: true, message: `请输入规格项${index + 1}` }]}
>
<Select
placeholder='请输入规格项,按回车键完成'
dropdownRender={(menu) => (
<>
{v.optionList.length ? menu : ''}
<Input
onPressEnter={(e) => specificationPressEnter(e, index)}
maxLength={30}
/>
</>
)}
options={v.optionList}
/>
</Form.Item>
</Col>
{index ? (
<Col span={2}>
<Button
danger
icon={<DeleteOutlined />}
onClick={() => deleteSpecificationClick(index)}
>
删除
</Button>
</Col>
) : (
''
)}
</Row>
{/*规格值显示*/}
{v.specificationValueList.length ? (
<Row style={{ marginBottom: '10px' }}>
<Col span={2}></Col>
<Col span={4}>
<div>
{v.specificationValueList.map((v, i) => (
<Tag key={v.id} closable onClose={() => specificationValueDelete(index, i)}>
{v.name}
</Tag>
))}
</div>
</Col>
</Row>
) : (
''
)}
{/*规格值操作*/}
{v.optionList.length ? (
<Row>
<Col span={2}></Col>
<Col span={4} style={{ marginBottom: '10px' }}>
{v.addSpecificationValueShow ? (
<Input
placeholder='请输入规格值,按回车键完成'
onPressEnter={(e) => specificationValuePressEnter(e, index)}
maxLength={30}
/>
) : (
<Button
type='link'
danger
icon={<PlusOutlined />}
onClick={() => addSpecificationValueClick(index)}
>
添加规格值
</Button>
)}
</Col>
{v.addSpecificationValueShow ? (
<Col>
<Button
type='primary'
style={{ marginLeft: '10px' }}
onClick={() => specificationValueCancel(index)}
>
取消
</Button>
</Col>
) : (
''
)}
</Row>
) : (
''
)}
</>
))}
<Row>
<Col span={2}></Col>
<Col>
<Button type='primary' icon={<PlusOutlined />} onClick={addSpecificationClick}>
添加规格
</Button>
</Col>
</Row>
</Form>
{tableData.length ? (
<Form form={skuValueForm}>
<Table
style={{ marginTop: '10px' }}
rowKey='id'
columns={covertColumns() as ColumnTypes}
components={{
body: {
cell: EditableCell,
},
}}
bordered
dataSource={tableData}
pagination={false}
size='small'
/> />
</Form>
) : (
''
)}
</div> </div>
); );
}); });
......
import SearchBox, { searchColumns } from '~/components/search-box';
import React, { useEffect, useRef, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { Button, Card, Image, message, Modal, Table } from 'antd';
import {
ArrowDownOutlined,
ArrowUpOutlined,
DeleteOutlined,
PlusOutlined,
} from '@ant-design/icons';
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';
import qs from 'query-string';
//商品返回类型
type goodsType = InterDataType<listGoodsType>['list'];
//商品列表筛选类型
type goodsSearchParameters = Omit<InterReqType<listGoodsType>, 'goodsType'>;
const RentList = () => {
//筛选ref
const searchRef = useRef();
const navigate = useNavigate();
const [searchParams, setSearchParams] = useSearchParams();
const tabList = [
{
key: '1',
tab: '全部',
},
{
key: '2',
tab: '上架中',
},
{
key: '3',
tab: '仓库中',
},
];
const [activeTabKey, setActiveTabKey] = useState<string>('1');
const [searchColumns, setSearchColumns] = useState<searchColumns[]>([
{
label: '商品名称',
placeholder: '请输入商品名称',
name: 'goodsName',
type: 'input',
},
{
label: '所属目录',
placeholder: '请选择所属目录',
name: 'directoryId',
type: 'select',
options: [],
},
{
label: '创建时间',
placeholder: '请输入选择创建时间',
name: 'time',
type: 'rangePicker',
},
]);
const tableColumns: ColumnsType<goodsType[0]> = [
{
title: '序号',
align: 'center',
render: (_text: any, _record, index: number) =>
(pagination.pageNo - 1) * pagination.pageSize + index + 1,
},
{
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: '操作',
align: 'center',
dataIndex: 'id',
render: (id: number) => (
<>
<Button type='link' onClick={() => toEditGoods(id)}>
编辑
</Button>
<Button type='link' onClick={() => toRentGoodsDetail(id)}>
详情
</Button>
</>
),
},
];
const [tableData, setTableData] = useState<goodsType>([]);
const [allRentGoods, setAllRentGoods] = useState<goodsType>([]);
const [loading, setLoading] = useState<boolean>(false);
//分页
const [pagination, setPagination] = useState<
PaginationProps & { totalCount: number; totalPage: number }
>({
pageNo: 1,
pageSize: 10,
totalCount: 0,
totalPage: 1,
});
//筛选
const [query, setQuery] = useState<goodsSearchParameters>({ status: undefined });
// 表格多选
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onTabChange = (key: string) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
query.status = key === '1' ? undefined : key === '2' ? 1 : 0;
setSearchParams(
qs.stringify({
pageNo: 1,
pageSize: 10,
...query,
status: query.status === undefined ? 'all' : query.status,
}),
);
getGoodsList(query);
getGoodsList({ ...query, pageNo: 1, pageSize: 9999 }, true);
setQuery(query);
setActiveTabKey(key);
};
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageSize = pageSize;
pagination.pageNo = pageNo;
setSearchParams(
qs.stringify({
pageNo: pageNo,
pageSize: pageSize,
...query,
status: query.status === undefined ? 'all' : query.status,
}),
);
getGoodsList(query);
getGoodsList({ ...query, pageNo: 1, pageSize: 9999 }, true);
};
//筛选
const searchSuccess = (data: any) => {
pagination.pageNo = 1;
pagination.pageSize = 10;
setQuery({ ...filterObjAttr(data, ['time']), status: query.status });
getGoodsList({ ...filterObjAttr(data, ['time']), status: query.status });
getGoodsList(
{ ...filterObjAttr(data, ['time']), status: query.status, pageNo: 1, pageSize: 9999 },
true,
);
setSearchParams(
qs.stringify({
pageNo: 1,
pageSize: 10,
...filterObjAttr(data, ['time']),
status: query.status === undefined ? 'all' : query.status,
}),
);
};
//商品列表
const getGoodsList = (query?: goodsSearchParameters, isAll?: boolean) => {
setLoading(true);
GoodsAPI.getGoodsList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
goodsType: 1,
...query,
}).then(({ result }) => {
setLoading(false);
if (isAll) {
setAllRentGoods(result.list || []);
} else {
setTableData(result.list || []);
pagination.totalCount = result.totalCount;
pagination.totalPage = result.totalPage;
setPagination(pagination);
}
});
};
//新增商品
const toAddRentGoods = () => {
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: 2 }).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('请先选择商品');
}
Modal.confirm({
title: '提示',
content: '删除后数据将会丢失,确定删除吗?',
onOk() {
GoodsAPI.batchRemoveWareInfo(selectedRowKeys as number[]).then(({ code }) => {
if (code === '200') {
if (pagination.pageNo !== 1 && tableData.length == 1) {
pagination.pageNo -= 1;
}
message.success('删除成功');
getGoodsList(query);
}
});
},
});
};
//上移
const upGoodsRentClick = () => {
if (selectedRowKeys.length === 0) {
message.warning('请选择商品');
} else if (selectedRowKeys.length > 1) {
message.warning('最多选择一个商品');
} else {
const index = tableData.findIndex((v) => v.id === selectedRowKeys[0]);
const allIndex = allRentGoods.findIndex((v) => v.id === selectedRowKeys[0]);
if (index === 0 && pagination.pageNo === 1) {
message.warning('位置已到最前列,无法上移');
} else {
const exReqData =
index === 0
? allRentGoods
.filter((_v, index) => index === allIndex - 1 || index === allIndex)
.map((v) => ({ id: v.id }))
: tableData
.filter((_v, i) => index - 1 === i || index === i)
.map((v) => ({ id: v.id }));
GoodsAPI.exchangeGoodsInfo({ firstId: exReqData[0].id, secondId: exReqData[1].id }).then(
({ code }) => {
if (code === '200') {
message.success('上移成功');
if (index === 0 && pagination.pageNo !== 1) {
pagination.pageNo -= 1;
setSearchParams(
qs.stringify({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...query,
status: query.status === undefined ? 'all' : query.status,
}),
);
}
getGoodsList(query);
getGoodsList({ ...query, pageNo: 1, pageSize: 9999 }, true);
}
},
);
}
}
};
//下移
const downRentGoodsClick = () => {
if (selectedRowKeys.length === 0) {
message.warning('请选择商品');
} else if (selectedRowKeys.length > 1) {
message.warning('最多选择一个商品');
} else {
const index = tableData.findIndex((v) => v.id === selectedRowKeys[0]);
const allIndex = allRentGoods.findIndex((v) => v.id === selectedRowKeys[0]);
if (index === tableData.length - 1 && pagination.pageNo === pagination.totalPage) {
message.warning('位置已到最后,无法下移');
} else {
const exReqData =
index === tableData.length - 1
? allRentGoods
.filter((_v, index) => index === allIndex + 1 || index === allIndex)
.map((v) => ({ id: v.id }))
: tableData
.filter((_v, i) => index + 1 === i || index === i)
.map((v) => ({ id: v.id }));
GoodsAPI.exchangeGoodsInfo({ firstId: exReqData[0].id, secondId: exReqData[1].id }).then(
({ code }) => {
if (code === '200') {
message.success('下移成功');
if (index === tableData.length - 1 && pagination.pageNo !== pagination.totalPage) {
pagination.pageNo += 1;
setSearchParams(
qs.stringify({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...query,
status: query.status === undefined ? 'all' : query.status,
}),
);
}
getGoodsList(query);
getGoodsList({ ...query, pageNo: 1, pageSize: 9999 }, true);
}
},
);
}
}
};
useEffect(() => {
getDirectoryList();
pagination.pageNo = Number(searchParams.get('pageNo') || 1);
pagination.pageSize = Number(searchParams.get('pageSize') || 10);
const queryObj = {
goodsName: searchParams.get('goodsName') || undefined,
directoryId: searchParams.get('directoryId')
? Number(searchParams.get('directoryId'))
: undefined,
startTime: searchParams.get('startTime') || undefined,
endTime: searchParams.get('endTime') || undefined,
status:
searchParams.get('status') === 'all' || searchParams.get('status') === null
? undefined
: Number(searchParams.get('status')),
};
getGoodsList(queryObj);
getGoodsList({ ...queryObj, pageSize: 9999, pageNo: 1 }, true);
setActiveTabKey(
searchParams.get('status') === 'all' || searchParams.get('status') === null
? '1'
: Number(searchParams.get('status')) === 1
? '2'
: '3',
);
(searchRef.current as any).getForm().setFieldsValue({
goodsName: searchParams.get('goodsName') || undefined,
directoryId: searchParams.get('directoryId')
? Number(searchParams.get('directoryId'))
: undefined,
time: searchParams.get('startTime')
? [searchParams.get('startTime'), searchParams.get('endTime')]
: undefined,
});
}, []);
return (
<div className='goods-list'>
<SearchBox
search={searchColumns}
child={
<Button type='primary' icon={<PlusOutlined />} onClick={toAddRentGoods}>
新增商品
</Button>
}
searchData={searchSuccess}
baseRef={searchRef}
/>
<Card tabList={tabList} activeTabKey={activeTabKey} onTabChange={onTabChange}>
<div className='header-operate' style={{ marginBottom: '10px' }}>
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowUpOutlined />}
onClick={upGoodsRentClick}
>
上移
</Button>
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={downRentGoodsClick}
>
下移
</Button>
{activeTabKey !== '2' && (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowUpOutlined />}
onClick={() => batchOnShelfOrTakeDown(1)}
>
上架
</Button>
)}
{activeTabKey !== '3' && (
<Button
type='primary'
style={{ marginRight: '10px' }}
icon={<ArrowDownOutlined />}
onClick={() => batchOnShelfOrTakeDown(0)}
>
下架
</Button>
)}
<Button danger icon={<DeleteOutlined />} onClick={deleteGoods}>
删除
</Button>
</div>
<Table
columns={tableColumns}
bordered
dataSource={tableData}
rowKey='id'
rowSelection={{
selectedRowKeys,
onChange: onSelectChange,
}}
loading={loading}
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>
</div>
);
};
export default RentList;
import { Form, Input, Radio } from 'antd'; import { Form, Input, Radio } from 'antd';
import './index.scss'; import './index.scss';
type goodsInfoForm = {
tradeName: string;
sellingPoint: string;
level: number;
shelfStatus: number;
};
const GoodsInfo = () => { const GoodsInfo = () => {
const qualityList = [ const qualityList = [
{ {
...@@ -24,18 +31,32 @@ const GoodsInfo = () => { ...@@ -24,18 +31,32 @@ const GoodsInfo = () => {
value: 4, value: 4,
}, },
]; ];
const [form] = Form.useForm<goodsInfoForm>();
return ( return (
<div className='goods-info'> <div className='goods-info'>
<div className='goods-info-title'>商品信息</div> <div className='goods-info-title'>商品信息</div>
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 10 }}> <Form
<Form.Item label='商品标题'> labelCol={{ span: 2 }}
<Input placeholder='请输入商品标题' /> wrapperCol={{ span: 10 }}
initialValues={{ level: 0 }}
form={form}
>
<Form.Item
label='商品标题'
name='tradeName'
rules={[{ required: true, message: '请输入商品标题' }]}
>
<Input placeholder='请输入商品标题' maxLength={30} />
</Form.Item> </Form.Item>
<Form.Item label='商品卖点'> <Form.Item
<Input placeholder='请输入商品卖点' /> label='商品卖点'
name='sellingPoint'
rules={[{ required: true, message: '请输入商品卖点' }]}
>
<Input placeholder='请输入商品卖点' maxLength={30} />
</Form.Item> </Form.Item>
<Form.Item label='商品成新'> <Form.Item label='商品成新' name='level'>
<Radio.Group> <Radio.Group>
{qualityList.map((v, index) => ( {qualityList.map((v, index) => (
<Radio value={v.value} key={index}> <Radio value={v.value} key={index}>
...@@ -44,7 +65,7 @@ const GoodsInfo = () => { ...@@ -44,7 +65,7 @@ const GoodsInfo = () => {
))} ))}
</Radio.Group> </Radio.Group>
</Form.Item> </Form.Item>
<Form.Item label='商品状态'> <Form.Item label='商品状态' name='shelfStatus'>
<Radio.Group> <Radio.Group>
<Radio value={1}>上架</Radio> <Radio value={1}>上架</Radio>
<Radio value={0}>下架</Radio> <Radio value={0}>下架</Radio>
......
import './index.scss'; import './index.scss';
import { Button, Cascader, Form, Radio, Table } from 'antd'; import { Button, Form, Select, Table } from 'antd';
import EditableCell from '~/components/EditableCell'; import EditableCell from '~/components/EditableCell';
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { MinusOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons'; import { MinusOutlined, PlusOutlined, UploadOutlined } from '@ant-design/icons';
import { Uploader } from '~/components/uploader'; import { Uploader } from '~/components/uploader';
import RichText from '~/components/richText'; import RichText from '~/components/richText';
import { RentManageAPI } from '../../../../../../api';
type EditableTableProps = Parameters<typeof Table>[0]; type EditableTableProps = Parameters<typeof Table>[0];
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>; type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
type RentAttrFormType = {
productTypeId: number;
brandInfoId: number;
deviceModeId: number;
goodsImage: string[];
goodsVideo: string;
productDetails: string;
};
//商品参数表格类型
type productParamType = {
id: number;
productParamName: string;
productParamValue: string;
};
const RentAttr = () => { const RentAttr = () => {
const typeList = [ //商品属性表单
{ const [rentAttrForm] = Form.useForm<RentAttrFormType>();
label: '航拍无人机', //商品参数表单
value: 1, const [productParamForm] = Form.useForm<{ [key: string]: string }>();
},
{
label: '行业无人机',
value: 2,
},
{
label: '挂载',
value: 3,
},
{
label: '配件',
value: 4,
},
];
const attrTableColumns: (ColumnTypes[number] & { const attrTableColumns: (ColumnTypes[number] & {
editable?: boolean; editable?: boolean;
...@@ -37,13 +39,13 @@ const RentAttr = () => { ...@@ -37,13 +39,13 @@ const RentAttr = () => {
})[] = [ })[] = [
{ {
title: '参数名称', title: '参数名称',
dataIndex: '', dataIndex: 'productParamName',
editable: true, editable: true,
align: 'center', align: 'center',
}, },
{ {
title: '参数值', title: '参数值',
dataIndex: '', dataIndex: 'productParamValue',
editable: true, editable: true,
align: 'center', align: 'center',
}, },
...@@ -66,7 +68,7 @@ const RentAttr = () => { ...@@ -66,7 +68,7 @@ const RentAttr = () => {
<Button <Button
type='primary' type='primary'
icon={<MinusOutlined />} icon={<MinusOutlined />}
onClick={deleteParameterDataEvent} onClick={() => deleteParameterDataEvent(index)}
></Button> ></Button>
) : ( ) : (
'' ''
...@@ -91,33 +93,176 @@ const RentAttr = () => { ...@@ -91,33 +93,176 @@ const RentAttr = () => {
}), }),
}; };
}); });
const [parameterTableData, setParameterTableData] = useState<any>([{ id: 1 }]); const [parameterTableData, setParameterTableData] = useState<productParamType[]>([
{ id: Math.random(), productParamName: '', productParamValue: '' },
]);
//类型下拉列表
const [rentTypeList, setTypeList] = useState<{ label: string; value: number }[]>([]);
//品牌下拉列表
const [brandInfoList, setBrandInfoList] = useState<{ label: string; value: number }[]>([]);
//型号下拉列表
const [modeTypeList, setModeTypeList] = useState<{ label: string; value: number }[]>([]);
//商品图片文件列表
const [imgFileList, setImgFileList] = useState<
{
id: number;
name: string;
uid: number;
url: string;
}[]
>([]);
//商品视频文件列表
const [videoFileList, setVideoFileList] = useState<
{
id: number;
name: string;
uid: number;
url: string;
}[]
>([]);
//商品参数新增 //商品参数新增
const addParameterDataEvent = () => { const addParameterDataEvent = () => {
setParameterTableData([...parameterTableData, { id: parameterTableData.length + 1 }]); setParameterTableData([
...parameterTableData,
{ id: Math.random(), productParamName: '', productParamValue: '' },
]);
}; };
//商品参数删除 //商品参数删除
const deleteParameterDataEvent = () => {}; const deleteParameterDataEvent = (index: number) => {
parameterTableData.splice(index, 1);
setParameterTableData(parameterTableData);
};
//类型列表
const getRentTypeList = () => {
RentManageAPI.getTypeList({ pageNo: 1, pageSize: 99999 }).then(({ result }) => {
if (result.list) {
const optionList = result.list.map((v) => ({ label: v.name, value: v.id }));
setTypeList(optionList);
}
});
};
//品牌列表
const getRentMakeList = () => {
RentManageAPI.getListBrandInfo({ pageNo: 1, pageSize: 99999 }).then(({ result }) => {
if (result.list) {
const optionList = result.list.map((v) => ({ label: v.brandName, value: v.id }));
setBrandInfoList(optionList);
}
});
};
//型号列表
const getRentModelList = (brandInfoId?: number, productTypeId?: number) => {
RentManageAPI.getRentModeList({ pageNo: 1, pageSize: 99999, brandInfoId, productTypeId }).then(
({ result }) => {
if (result.list) {
const optionList = result.list.map((v) => ({ label: v.modeName, value: v.id }));
setModeTypeList(optionList);
}
},
);
};
//类型选中
const rentTypeOnSelect = (value: number) => {
getRentModelList(rentAttrForm.getFieldValue('brandInfoId') || undefined, value);
};
//品牌选中
const brandInfoOnSelect = (value: number) => {
getRentModelList(value, rentAttrForm.getFieldValue('productTypeId') || undefined);
};
//商品图片上传成功
const imgUploadSuccess = (
value: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => {
rentAttrForm.setFieldValue(
'goodsImage',
value.map((v) => v.url),
);
setImgFileList(value);
};
//商品视频上传成功
const videoUploadSuccess = (
value: {
id: number;
name: string;
uid: number;
url: string;
}[],
) => {
rentAttrForm.setFieldValue('goodsVideo', value[0].url);
setVideoFileList(value);
};
//商品参数表单验证
const productParamFormSubmit = () => {
return new Promise((resolve, reject) => {
productParamForm
.validateFields()
.then((values) => {
const productParamList = parameterTableData.reduce(
(pre: { [key: string]: string }[], cur) => {
const Obj = Object.create(null);
Obj[values['productParamName' + cur.id]] = values['productParamValue' + cur.id];
pre.push(Obj);
return pre;
},
[],
);
resolve(productParamList);
})
.catch((err) => {
reject(err);
});
});
};
useEffect(() => {
getRentTypeList();
getRentMakeList();
}, []);
return ( return (
<div className='rent-attr'> <div className='rent-attr'>
<div className='rent-attr-title'>商品属性</div> <div className='rent-attr-title'>商品属性</div>
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 10 }}> <Form labelCol={{ span: 2 }} wrapperCol={{ span: 10 }} form={rentAttrForm}>
<Form.Item label='商品类型'> <Form.Item
<Radio.Group> label='商品类型'
{typeList.map((v) => ( name='productTypeId'
<Radio key={v.value} value={v.value}> rules={[{ required: true, message: '请选择商品类型' }]}
{v.label} >
</Radio> <Select
))} placeholder='请选择商品类型'
</Radio.Group> options={rentTypeList}
onSelect={rentTypeOnSelect}
></Select>
</Form.Item>
<Form.Item
label='商品品牌'
name='brandInfoId'
rules={[{ required: true, message: '请选择商品品牌' }]}
>
<Select
placeholder='请选择商品品牌'
options={brandInfoList}
onSelect={brandInfoOnSelect}
></Select>
</Form.Item> </Form.Item>
<Form.Item label='商品型号'> <Form.Item
<Cascader placeholder='请选择商品型号' /> label='商品型号'
name='deviceModeId'
rules={[{ required: true, message: '请选择商品型号' }]}
>
<Select placeholder='请选择商品型号' options={modeTypeList}></Select>
</Form.Item> </Form.Item>
<Form.Item label='商品参数'> <Form.Item label='商品参数'>
<Form> <Form form={productParamForm}>
<Table <Table
columns={columns as ColumnTypes} columns={columns as ColumnTypes}
components={{ components={{
...@@ -132,17 +277,39 @@ const RentAttr = () => { ...@@ -132,17 +277,39 @@ const RentAttr = () => {
></Table> ></Table>
</Form> </Form>
</Form.Item> </Form.Item>
<Form.Item label='商品图片'> <Form.Item
<Uploader fileUpload listType='picture-card'> label='商品图片'
name='goodsImage'
rules={[{ required: true, message: '请选择商品图片' }]}
>
<Uploader
fileUpload
listType='picture-card'
onChange={imgUploadSuccess}
defaultFileList={imgFileList}
fileSize={3}
fileLength={5}
>
<UploadOutlined /> <UploadOutlined />
</Uploader> </Uploader>
</Form.Item> </Form.Item>
<Form.Item label='商品视频'> <Form.Item label='商品视频' name='goodsVideo'>
<Uploader fileUpload listType='picture-card'> <Uploader
fileUpload
listType='picture-card'
onChange={videoUploadSuccess}
defaultFileList={videoFileList}
fileSize={30}
fileLength={1}
>
<UploadOutlined /> <UploadOutlined />
</Uploader> </Uploader>
</Form.Item> </Form.Item>
<Form.Item label='商品详情页'> <Form.Item
label='商品详情页'
name='productDetails'
rules={[{ required: true, message: '请输入商品详情页' }]}
>
<RichText richTextContent='' /> <RichText richTextContent='' />
</Form.Item> </Form.Item>
</Form> </Form>
......
.rent-info{
&-title{
font-size: 15px;
font-weight: bold;
line-height: 40px;
}
}
import { Form, Select } from 'antd';
import './index.scss';
const RentInfo = () => {
return (
<div className='rent-info'>
<div className='rent-info-title'>租赁信息</div>
<Form labelCol={{ span: 2 }} wrapperCol={{ span: 10 }}>
<Form.Item label='最低租期'>
<Select placeholder='请选择租期'>
<Select.Option>11</Select.Option>
</Select>
</Form.Item>
<Form.Item label='最高租期'>
<Select placeholder='请选择租期'>
<Select.Option>11</Select.Option>
</Select>
</Form.Item>
</Form>
</div>
);
};
export default RentInfo;
import './index.scss'; import './index.scss';
import { Button, Col, Row, Table } from 'antd'; import { Col, Form, Row, Select, Table } from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import CommonSkuInfo from '~/components/goods/commonSkuInfo';
import { ColumnsType } from 'antd/es/table/InternalTable'; import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
const SkuInfo = () => { import { RentManageAPI } from '~/api';
const skuTableColumns: ColumnsType<any> = [
type EditableTableProps = Parameters<typeof Table>[0];
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
interface selfProps {
ref: any;
}
const SkuInfo = forwardRef<any, selfProps>((_props, ref) => {
const [form] = Form.useForm<{ minLeaseTerm: number; maxLeaseTerm: number }>();
const commonSkuInfoRef = useRef<any>();
const [defaultColumns, setDefaultColumns] = useState<
(ColumnTypes[number] & {
editable?: boolean;
dataIndex?: string;
inputType?: string;
radioOption?: { name: string; id: number }[];
rules?: any;
maxLength?: number;
children?: any;
placeholder?: string;
})[]
>([
{ {
title: '版本', title: '商品规格',
align: 'center', align: 'center',
children: [],
}, },
{ {
title: '是否缺货', title: '押金',
align: 'center', align: 'center',
editable: true,
dataIndex: 'skuImage',
}, },
]);
const [tableData, setTableData] = useState<any>([]);
//全部租期下拉
const [allLeaseTermInfoList, setAllLeaseTermInfoList] = useState<
{ {
title: '押金', label: string;
value: number;
}[]
>([]);
// 低租期下拉
const [lowLeaseTermInfoList, setLowLeaseTermInfoList] = useState<
{
label: string;
value: number;
}[]
>([]);
//高租期下拉
const [upLeaseTermInfoList, setUpLeaseTermInfoList] = useState<
{
label: string;
value: number;
}[]
>([]);
useImperativeHandle(ref, () => ({
getForm: () => form,
}));
const updateTableData = (tableData: any) => {
setTableData([...tableData]);
};
const updateDefaultColumns = (columns: any) => {
setDefaultColumns([...columns]);
};
//租赁-商品-租期信息
const getLeaseTermInfo = () => {
RentManageAPI.getLeaseTermInfo().then(({ result }) => {
if (result) {
const optionList = result.map((v) => ({ label: v.leaseDate, value: v.id }));
setLowLeaseTermInfoList(optionList);
setUpLeaseTermInfoList(optionList);
setAllLeaseTermInfoList(optionList);
}
});
};
//最低租期选择
const lowLeaseTermInfoOnSelect = (value: number) => {
const upLeaseTermInfoIndex = allLeaseTermInfoList.findIndex((v) => v.value === value);
if (upLeaseTermInfoIndex !== -1) {
setUpLeaseTermInfoList(
allLeaseTermInfoList.slice(upLeaseTermInfoIndex, allLeaseTermInfoList.length),
);
}
if (form.getFieldValue('maxLeaseTerm')) {
const index = allLeaseTermInfoList.findIndex(
(v) => v.value === form.getFieldValue('maxLeaseTerm'),
);
if (index !== -1) {
const filterLeaseTermInfo = allLeaseTermInfoList.slice(upLeaseTermInfoIndex, index + 1);
setDefaultColumns(
defaultColumns.concat(
filterLeaseTermInfo.map((v) => ({
title: v.label,
align: 'center', align: 'center',
}, editable: true,
]; dataIndex: v.label,
})),
),
);
}
}
};
// 最高租期选择
const upLeaseTermInfoOnSelect = (value: number) => {
const lowLeaseTermInfoIndex = allLeaseTermInfoList.findIndex((v) => v.value === value);
if (lowLeaseTermInfoIndex !== -1) {
setLowLeaseTermInfoList(allLeaseTermInfoList.slice(0, lowLeaseTermInfoIndex + 1));
}
if (form.getFieldValue('minLeaseTerm')) {
const index = allLeaseTermInfoList.findIndex(
(v) => v.value === form.getFieldValue('minLeaseTerm'),
);
if (index !== -1) {
const filterLeaseTermInfo = allLeaseTermInfoList.slice(index, lowLeaseTermInfoIndex + 1);
setDefaultColumns(
defaultColumns.concat(
filterLeaseTermInfo.map((v) => ({
title: v.label,
align: 'center',
editable: true,
dataIndex: v.label,
})),
),
);
}
}
};
useEffect(() => {
getLeaseTermInfo();
}, []);
return ( return (
<div className='sku-info'> <div className='sku-info'>
<div className='sku-info-title'>价格库存信息</div> <div className='sku-info-title'>价格库存信息</div>
<Row> <Row>
<Col span={1}></Col> <Col span={1}></Col>
<Col span={7}>
<Form wrapperCol={{ span: 18 }} labelCol={{ span: 5 }} form={form}>
<Form.Item
label='最低租期'
name='minLeaseTerm'
rules={[{ required: true, message: '请选择最低租期' }]}
>
<Select
placeholder='请选择最低租期'
options={lowLeaseTermInfoList}
onSelect={lowLeaseTermInfoOnSelect}
></Select>
</Form.Item>
<Form.Item
label='最高租期'
name='maxLeaseTerm'
rules={[{ required: true, message: '请选择最高租期' }]}
>
<Select
placeholder='请选择最高租期'
options={upLeaseTermInfoList}
onSelect={upLeaseTermInfoOnSelect}
></Select>
</Form.Item>
</Form>
</Col>
</Row>
<Row>
<Col span={1}></Col>
<Col span={22}> <Col span={22}>
<div> <CommonSkuInfo
<Button type='primary' icon={<PlusOutlined />} style={{ marginBottom: '10px' }}> tableData={tableData}
新增规格 updateTableData={updateTableData}
</Button> defaultColumns={defaultColumns}
<Table bordered columns={skuTableColumns} /> updateDefaultColumns={updateDefaultColumns}
</div> ref={commonSkuInfoRef}
/>
</Col> </Col>
</Row> </Row>
</div> </div>
); );
}; });
export default SkuInfo; export default SkuInfo;
import GoodsInfo from './components/goodsInfo'; import GoodsInfo from './components/goodsInfo';
import RentAttr from './components/rentAttr'; import RentAttr from './components/rentAttr';
import RentInfo from './components/rentInfo';
import SkuInfo from './components/skuInfo'; import SkuInfo from './components/skuInfo';
import AddressInfo from './components/addressInfo'; import AddressInfo from './components/addressInfo';
const RentAddOrEdit = () => { const RentAddOrEdit = () => {
...@@ -10,8 +9,6 @@ const RentAddOrEdit = () => { ...@@ -10,8 +9,6 @@ const RentAddOrEdit = () => {
<GoodsInfo /> <GoodsInfo />
{/*商品属性*/} {/*商品属性*/}
<RentAttr /> <RentAttr />
<RentInfo />
{/*价格库存信息*/} {/*价格库存信息*/}
<SkuInfo /> <SkuInfo />
{/*物流信息*/} {/*物流信息*/}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论