提交 26a95c46 作者: 龚洪江

功能:商品新增,商品编辑(联调完成)

上级 679b10ca
...@@ -99,8 +99,12 @@ export type otherServiceType = InterFunction<any, { id: number; saleServiceName: ...@@ -99,8 +99,12 @@ export type otherServiceType = InterFunction<any, { id: number; saleServiceName:
export type skuUnitType = InterFunction<any, { id: number; unitName: string }[]>; export type skuUnitType = InterFunction<any, { id: number; unitName: string }[]>;
//商品-批量上下架 //商品-批量上下架
export type batchOnShelfOrTakeDownType = InterFunction<{ goodsIds: number[]; status: number }, any>; export type batchOnShelfOrTakeDownType = InterFunction<{ goodsIds: number[]; status: number }, any>;
//商品-单个上下架(新)
export type upOrDownShelfType = InterFunction<{ id: number; status: number }, any>;
//商品批量删除 //商品批量删除
export type batchRemoveWareInfoType = InterFunction<number[], any>; export type batchRemoveWareInfoType = InterFunction<number[], any>;
//商品-单个删除
export type removeMallGoodsType = InterFunction<{ id: number }, any>;
//商品-上下移动 //商品-上下移动
export type exchangeGoodsInfoType = InterFunction<{ firstId: number; secondId: number }, any>; export type exchangeGoodsInfoType = InterFunction<{ firstId: number; secondId: number }, any>;
...@@ -116,7 +120,7 @@ export type addMallGoodsType = InterFunction< ...@@ -116,7 +120,7 @@ export type addMallGoodsType = InterFunction<
chooseType: number; chooseType: number;
goodsSpecValuesList: { goodsSpecValuesList: {
channelPrice?: number; channelPrice?: number;
id: number; id: any;
partNo: string; partNo: string;
salePrice: number; salePrice: number;
showPrice: number; showPrice: number;
...@@ -124,7 +128,44 @@ export type addMallGoodsType = InterFunction< ...@@ -124,7 +128,44 @@ export type addMallGoodsType = InterFunction<
specValueName: string; specValueName: string;
stock?: number; stock?: number;
}[]; }[];
id: any;
mallGoodsId: number;
must: number;
skuUnitId: number;
specName: string;
}[];
labelShow: number;
resourcesList: {
id: number; id: number;
type: number;
url: string;
}[];
shelfStatus: number;
tradeName: string;
},
any
>;
//商品-编辑(新)
export type editMallGoodsType = InterFunction<
{
categoryPrimaryId: number;
categorySubId: number;
description: string;
goodsDetails: string;
goodsLabel: string;
goodsSpecList: {
chooseType: number;
goodsSpecValuesList: {
channelPrice?: number;
id: any;
partNo: string;
salePrice: number;
showPrice: number;
specValueImage: string;
specValueName: string;
stock?: number;
}[];
id: any;
mallGoodsId: number; mallGoodsId: number;
must: number; must: number;
skuUnitId: number; skuUnitId: number;
...@@ -142,3 +183,85 @@ export type addMallGoodsType = InterFunction< ...@@ -142,3 +183,85 @@ export type addMallGoodsType = InterFunction<
}, },
any any
>; >;
//商品-列表(新)
export type listPageGoodsInfoType = InterItemFunction<
{ categoryPrimaryId?: number; tradeName?: string; shelfStatus?: number },
{
categoryPrimaryId: number;
categorySubId: number;
createTime: string;
description: string;
goodsDetails: string;
goodsLabel: string;
goodsSpecList: {
chooseType: number;
goodsSpecValuesList: {
channelPrice: number;
goodsSpecId: number;
id: number;
partNo: string;
salePrice: number;
showPrice: number;
specValueImage: string;
specValueName: string;
stock: number;
}[];
id: number;
mallGoodsId: number;
must: number;
skuUnitId: number;
specName: string;
}[];
id: number;
labelShow: number;
resourcesList: {
id: number;
type: number;
url: string;
}[];
shelfStatus: number;
tradeName: string;
userAccountId: number;
}[]
>;
//商城-详情(新)
export type mallGoodsDetailsType = InterFunction<
{ id: number },
{
categoryPrimaryId: number;
categorySubId: number;
createTime: string;
description: string;
goodsDetails: string;
goodsLabel: string;
goodsSpecList: {
chooseType: number;
goodsSpecValuesList: {
channelPrice: number;
goodsSpecId: number;
id: number;
partNo: string;
salePrice: number;
showPrice: number;
specValueImage: string;
specValueName: string;
stock: number;
}[];
id: number;
mallGoodsId: number;
must: number;
skuUnitId: number;
specName: string;
}[];
id: number;
labelShow: number;
resourcesList: {
id: number;
type: number;
url: string;
}[];
shelfStatus: number;
tradeName: string;
userAccountId: number;
}
>;
...@@ -5,10 +5,15 @@ import { ...@@ -5,10 +5,15 @@ import {
batchRemoveWareInfoType, batchRemoveWareInfoType,
detailGoodsType, detailGoodsType,
editGoodsType, editGoodsType,
editMallGoodsType,
exchangeGoodsInfoType, exchangeGoodsInfoType,
listGoodsType, listGoodsType,
listPageGoodsInfoType,
mallGoodsDetailsType,
otherServiceType, otherServiceType,
removeMallGoodsType,
skuUnitType, skuUnitType,
upOrDownShelfType,
} from '~/api/interface/goodsType'; } from '~/api/interface/goodsType';
import axios from '../request'; import axios from '../request';
...@@ -41,16 +46,35 @@ class GoodsAPI { ...@@ -41,16 +46,35 @@ class GoodsAPI {
static batchOnShelfOrTakeDown: batchOnShelfOrTakeDownType = (data) => { static batchOnShelfOrTakeDown: batchOnShelfOrTakeDownType = (data) => {
return axios.post('/pms/goods/batchOnShelfOrTakeDown', data); return axios.post('/pms/goods/batchOnShelfOrTakeDown', data);
}; };
//商品-单个上下架(新)
static upOrDownShelf: upOrDownShelfType = (params) =>
axios.get('/pms/mall/goods/upOrDownShelf', { params });
// 商品-批量删除 // 商品-批量删除
static batchRemoveWareInfo: batchRemoveWareInfoType = (data) => { static batchRemoveWareInfo: batchRemoveWareInfoType = (data) => {
return axios.post('/pms/goods/batchRemoveWareInfo', data); return axios.post('/pms/goods/batchRemoveWareInfo', data);
}; };
//商品-单个删除
static removeMallGoods: removeMallGoodsType = (params) =>
axios.get('/pms/mall/goods/removeMallGoods', { params });
// 商品-上下移动 // 商品-上下移动
static exchangeGoodsInfo: exchangeGoodsInfoType = (params) => { static exchangeGoodsInfo: exchangeGoodsInfoType = (params) => {
return axios.get('/pms/goods/exchangeGoodsInfo', { params }); return axios.get('/pms/goods/exchangeGoodsInfo', { params });
}; };
//商品-上下移动
static exchange: exchangeGoodsInfoType = (params) =>
axios.get('/pms/mall/goods/exchange', { params });
// 商品-新增(新) // 商品-新增(新)
static addMallGoods: addMallGoodsType = (data) => static addMallGoods: addMallGoodsType = (data) =>
axios.post('/pms/mall/goods/addMallGoods', data); axios.post('/pms/mall/goods/addMallGoods', data);
//商品-编辑(新)
static editMallGoods: editMallGoodsType = (data) =>
axios.post('/pms/mall/goods/editMallGoods', data);
// 商品-列表(新)
static getListPageGoodsInfo: listPageGoodsInfoType = (data) =>
axios.post('/pms/mall/goods/listPageGoodsInfo', data);
// 商品-详情(新)
static getMallGoodsDetails: mallGoodsDetailsType = (params) =>
axios.get('/pms/mall/goods/mallGoodsDetails', { params });
} }
export default GoodsAPI; export default GoodsAPI;
...@@ -39,7 +39,7 @@ const EditableCell: React.FC< ...@@ -39,7 +39,7 @@ const EditableCell: React.FC<
const inputNode = () => { const inputNode = () => {
switch (inputType) { switch (inputType) {
case 'number': case 'number':
return <InputNumber />; return <InputNumber placeholder={`请输入${title}`} maxLength={maxLength} />;
case 'select': case 'select':
return ( return (
<Select placeholder={`请选择${title}`} style={{ textAlign: 'start' }}> <Select placeholder={`请选择${title}`} style={{ textAlign: 'start' }}>
......
...@@ -118,7 +118,6 @@ const CategoryList = () => { ...@@ -118,7 +118,6 @@ const CategoryList = () => {
) : ( ) : (
'' ''
)} )}
<Button type='link'>详情</Button>
<Button type='link' onClick={() => addOrEditCategoryModalShowClick(record)}> <Button type='link' onClick={() => addOrEditCategoryModalShowClick(record)}>
编辑 编辑
</Button> </Button>
......
.goods-video-wrap{
position: relative;
width: 200px;
img{
position: absolute;
right: 0;
top: 0;
transform: translate(50%,-25%);
}
}
...@@ -2,10 +2,12 @@ import { Button, Cascader, Form, Input, Radio, Select } from 'antd'; ...@@ -2,10 +2,12 @@ import { Button, Cascader, Form, Input, Radio, Select } from 'antd';
import { Uploader } from '~/components/uploader'; import { Uploader } from '~/components/uploader';
import type { RadioChangeEvent } from 'antd'; import type { RadioChangeEvent } from 'antd';
import { UploadOutlined } from '@ant-design/icons'; import { UploadOutlined } from '@ant-design/icons';
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { InterDataType } from '~/api/interface'; import { InterDataType } from '~/api/interface';
import { categoryListRespType } from '~/api/interface/categoryManage'; import { categoryListRespType } from '~/api/interface/categoryManage';
import { CategoryManageAPI } from '~/api'; import { CategoryManageAPI } from '~/api';
import deletePng from '~/assets/image/delete.png';
import './index.scss';
//分类返回类型 //分类返回类型
type categoryType = InterDataType<categoryListRespType>['list']; type categoryType = InterDataType<categoryListRespType>['list'];
...@@ -76,6 +78,12 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => { ...@@ -76,6 +78,12 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => {
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
getForm: () => baseInfoForm, getForm: () => baseInfoForm,
setLabelShow: (value: boolean) => setLabelShow(value),
mediaData: {
setMainFileList,
setSubFileList,
setVideoFileList,
},
})); }));
//标签选中监听 //标签选中监听
...@@ -115,6 +123,11 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => { ...@@ -115,6 +123,11 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => {
setCategoryList(result.list || []); setCategoryList(result.list || []);
}); });
}; };
//视频删除
const deleteVideo = () => {
setVideoFileList([]);
baseInfoForm.setFieldValue('videoList', undefined);
};
useEffect(() => { useEffect(() => {
getCategoryList(); getCategoryList();
...@@ -133,10 +146,14 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => { ...@@ -133,10 +146,14 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => {
name='tradeName' name='tradeName'
rules={[{ required: true, message: '请输入商品名称' }]} rules={[{ required: true, message: '请输入商品名称' }]}
> >
<Input placeholder='请输入商品名称' /> <Input placeholder='请输入商品名称' maxLength={50} />
</Form.Item> </Form.Item>
<Form.Item label='商品描述' name='description'> <Form.Item
<Input.TextArea rows={4} placeholder='请输入商品描述' /> label='商品描述'
name='description'
rules={[{ required: true, message: '请输入商品描述' }]}
>
<Input.TextArea rows={4} placeholder='请输入商品描述' maxLength={70} showCount />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label='商品主图' label='商品主图'
...@@ -163,14 +180,27 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => { ...@@ -163,14 +180,27 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => {
</Uploader> </Uploader>
</Form.Item> </Form.Item>
<Form.Item label='商品视频' name='videoList'> <Form.Item label='商品视频' name='videoList'>
<Uploader {videoFileList.length ? (
fileUpload <div className='goods-video-wrap'>
listType='text' <video
onChange={(fileList) => uploadSuccess(fileList, 'videoList')} src={videoFileList[0].url}
defaultFileList={videoFileList} style={{ width: '200px', height: '200px' }}
> controls
<Button icon={<UploadOutlined />}>上传视频</Button> />
</Uploader> <img src={deletePng} alt='删除' onClick={deleteVideo} />
</div>
) : (
<Uploader
fileUpload
listType='text'
onChange={(fileList) => uploadSuccess(fileList, 'videoList')}
defaultFileList={videoFileList}
fileType={['video/mp4', 'video/avi', 'video/wmv', 'video/rmvb']}
fileSize={50}
>
<Button icon={<UploadOutlined />}>上传视频</Button>
</Uploader>
)}
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label='商品分类' label='商品分类'
...@@ -205,7 +235,7 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => { ...@@ -205,7 +235,7 @@ const BaseInfo = forwardRef<any, selfProps>((_props, ref) => {
name='goodsLabel' name='goodsLabel'
rules={[{ required: true, message: '请输入商品标签' }]} rules={[{ required: true, message: '请输入商品标签' }]}
> >
<Input placeholder='请输入商品标签' /> <Input placeholder='请输入商品标签' maxLength={10} />
</Form.Item> </Form.Item>
) : ( ) : (
'' ''
......
import RichText from '~/components/richText'; import RichText from '~/components/richText';
import { FC } from 'react';
interface selfProps {
onChange: (html: string) => void;
introduceInfo: string;
}
const IntroduceInfo: FC<selfProps> = ({ onChange, introduceInfo }) => {
//富文本修改
const richTextOnChange = (html?: string) => {
onChange(html || '');
};
const IntroduceInfo = () => {
return ( return (
<div className='introduce-info'> <div className='introduce-info'>
<RichText richTextContent='' height={400} /> <RichText richTextContent={introduceInfo} height={400} onChange={richTextOnChange} />
</div> </div>
); );
}; };
......
import { Button, Form, Input, message, Modal, ModalProps, Radio, Select, Table } from 'antd'; import { Button, Form, Input, Modal, ModalProps, Radio, Select, Table } from 'antd';
import { FC, useEffect, useState } from 'react'; import { FC, useEffect, useState } from 'react';
import EditableCell from '~/components/EditableCell'; import EditableCell from '~/components/EditableCell';
import { MinusOutlined, PlusOutlined } from '@ant-design/icons'; import { MinusOutlined, PlusOutlined } from '@ant-design/icons';
import { InterDataType, InterReqType } from '~/api/interface'; import { InterDataType, InterReqType } from '~/api/interface';
import { addMallGoodsType, skuUnitType } from '~/api/interface/goodsType'; import { addMallGoodsType, skuUnitType } from '~/api/interface/goodsType';
import { filterObjAttr } from '~/utils'; import { filterObjAttr } from '~/utils';
import { isEmptyBol, regPriceNumber } from '~/utils/validateUtils';
import _ from 'lodash';
type EditableTableProps = Parameters<typeof Table>[0]; type EditableTableProps = Parameters<typeof Table>[0];
type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>; type ColumnTypes = Exclude<EditableTableProps['columns'], undefined>;
//商品sku规格类型 //商品sku规格类型
type goodsSpecType = InterReqType<addMallGoodsType>['goodsSpecList'][0]; type goodsSpecType = Exclude<InterReqType<addMallGoodsType>, undefined>['goodsSpecList'][0];
//商品sku规格值类型 //商品sku规格值类型
type goodsSpecValuesType = type goodsSpecValuesType = Exclude<
InterReqType<addMallGoodsType>['goodsSpecList'][0]['goodsSpecValuesList'] & { fileList: any }; InterReqType<addMallGoodsType>,
undefined
>['goodsSpecList'][0]['goodsSpecValuesList'][0] & { fileList: any };
//单位返回类型 //单位返回类型
type unitType = InterDataType<skuUnitType>; type unitType = InterDataType<skuUnitType>;
interface selfProps { interface selfProps {
onCancel: () => void; onCancel: () => void;
onOk: (value: goodsSpecType) => void; onHandleOk: (value: goodsSpecType) => void;
skuUnitList: unitType; skuUnitList: unitType;
currentSku: goodsSpecType | undefined; currentSku: goodsSpecType | undefined;
} }
...@@ -27,12 +31,49 @@ interface selfProps { ...@@ -27,12 +31,49 @@ interface selfProps {
const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
open, open,
onCancel, onCancel,
onOk, onHandleOk,
skuUnitList, skuUnitList,
currentSku, currentSku,
}) => { }) => {
const [goodsSpecForm] = Form.useForm<Omit<goodsSpecType, 'goodsSpecValuesList'>>(); const [goodsSpecForm] = Form.useForm<Omit<goodsSpecType, 'goodsSpecValuesList'>>();
const [goodsSpecValuesForm] = Form.useForm<goodsSpecValuesType[0]>(); const [goodsSpecValuesForm] = Form.useForm<goodsSpecValuesType>();
//销售正则价格校验
const salePriceValidator = (_rules: any, value: number) => {
if (!isEmptyBol(value)) {
if (regPriceNumber(value.toString())) {
return Promise.resolve();
} else {
return Promise.reject(new Error('为整数且最多保留两位小数'));
}
} else {
return Promise.reject(new Error('请输入销售价'));
}
};
//渠道正则价格校验
const channelPriceValidator = (_rules: any, value: number) => {
if (!isEmptyBol(value)) {
if (regPriceNumber(value.toString())) {
return Promise.resolve();
} else {
return Promise.reject(new Error('为整数且最多保留两位小数'));
}
} else {
return Promise.resolve();
}
};
//库存正则校验
const stockPriceValidator = (_rules: any, value: number) => {
if (!isEmptyBol(value)) {
if (/^[+]{0,1}(\d+)$/.test(value.toString())) {
return Promise.resolve();
} else {
return Promise.reject(new Error('请输入正整数'));
}
} else {
return Promise.resolve();
}
};
const [tableData, setTableData] = useState<goodsSpecValuesType[]>([ const [tableData, setTableData] = useState<goodsSpecValuesType[]>([
{ {
...@@ -53,6 +94,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -53,6 +94,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
inputType?: string; inputType?: string;
radioOption?: { name: string; id: number }[]; radioOption?: { name: string; id: number }[];
rules?: any; rules?: any;
maxLength?: number;
})[] = [ })[] = [
{ {
title: '序号', title: '序号',
...@@ -74,6 +116,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -74,6 +116,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
editable: true, editable: true,
dataIndex: 'specValueName', dataIndex: 'specValueName',
rules: [{ required: true, message: '请输入选项名称' }], rules: [{ required: true, message: '请输入选项名称' }],
maxLength: 30,
}, },
{ {
title: '料号', title: '料号',
...@@ -81,25 +124,31 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -81,25 +124,31 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
editable: true, editable: true,
dataIndex: 'partNo', dataIndex: 'partNo',
rules: [{ required: true, message: '请输入料号' }], rules: [{ required: true, message: '请输入料号' }],
maxLength: 30,
}, },
{ {
title: '销售价', title: '销售价',
align: 'center', align: 'center',
editable: true, editable: true,
dataIndex: 'salePrice', dataIndex: 'salePrice',
rules: [{ required: true, message: '请输入销售号' }], rules: [{ required: true, validator: salePriceValidator }],
inputType: 'number',
}, },
{ {
title: '渠道价', title: '渠道价',
editable: true, editable: true,
align: 'center', align: 'center',
dataIndex: 'channelPrice', dataIndex: 'channelPrice',
rules: [{ required: false, validator: channelPriceValidator }],
inputType: 'number',
}, },
{ {
title: '库存', title: '库存',
editable: true, editable: true,
align: 'center', align: 'center',
dataIndex: 'stock', dataIndex: 'stock',
rules: [{ required: false, validator: stockPriceValidator }],
inputType: 'number',
}, },
{ {
title: '是否显示', title: '是否显示',
...@@ -107,7 +156,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -107,7 +156,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
align: 'center', align: 'center',
dataIndex: 'showPrice', dataIndex: 'showPrice',
inputType: 'radio', inputType: 'radio',
width: '20%', width: '18%',
radioOption: [ radioOption: [
{ id: 1, name: '显示' }, { id: 1, name: '显示' },
{ id: 0, name: '不显示' }, { id: 0, name: '不显示' },
...@@ -237,7 +286,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -237,7 +286,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
//提交 //提交
const handleOk = () => { const handleOk = () => {
Promise.all([goodsSpecForm.validateFields(), goodsSpecValuesForm.validateFields()]).then( Promise.all([goodsSpecForm.validateFields(), goodsSpecValuesForm.validateFields()]).then(
(values) => { (values: any) => {
const goodsSpecValuesList: goodsSpecValuesType[] = tableData.map((v) => { const goodsSpecValuesList: goodsSpecValuesType[] = tableData.map((v) => {
return Object.getOwnPropertyNames(v).reduce((pre: any, cur: string) => { return Object.getOwnPropertyNames(v).reduce((pre: any, cur: string) => {
if (Object.getOwnPropertyNames(values[1]).includes(cur + v.id)) { if (Object.getOwnPropertyNames(values[1]).includes(cur + v.id)) {
...@@ -247,7 +296,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -247,7 +296,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
return pre; return pre;
}, {}); }, {});
}); });
onOk({ ...values[0], goodsSpecValuesList, id: currentSku?.id || Math.random() }); onHandleOk({ ...values[0], goodsSpecValuesList, id: currentSku?.id || Math.random() });
clearForm(); clearForm();
}, },
); );
...@@ -294,7 +343,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -294,7 +343,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
<Modal <Modal
open={open} open={open}
title={currentSku ? '编辑规格' : '添加规格'} title={currentSku ? '编辑规格' : '添加规格'}
width={1000} width={1100}
onCancel={handleCancel} onCancel={handleCancel}
onOk={handleOk} onOk={handleOk}
> >
...@@ -309,7 +358,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({ ...@@ -309,7 +358,7 @@ const SkuAddOrEditModal: FC<ModalProps & selfProps> = ({
name='specName' name='specName'
rules={[{ required: true, message: '请输入规格名称' }]} rules={[{ required: true, message: '请输入规格名称' }]}
> >
<Input placeholder='请输入规格名称' /> <Input placeholder='请输入规格名称' maxLength={30} />
</Form.Item> </Form.Item>
<Form.Item label='规格值'> <Form.Item label='规格值'>
<Form component={false} form={goodsSpecValuesForm}> <Form component={false} form={goodsSpecValuesForm}>
......
...@@ -6,7 +6,7 @@ import { InterDataType, InterReqType } from '~/api/interface'; ...@@ -6,7 +6,7 @@ import { InterDataType, InterReqType } from '~/api/interface';
import { addMallGoodsType, skuUnitType } from '~/api/interface/goodsType'; import { addMallGoodsType, skuUnitType } from '~/api/interface/goodsType';
//商品sku规格类型 //商品sku规格类型
type goodsSpecType = InterReqType<addMallGoodsType>['goodsSpecList'][0]; type goodsSpecType = Exclude<InterReqType<addMallGoodsType>, undefined>['goodsSpecList'][0];
//单位返回类型 //单位返回类型
type unitType = InterDataType<skuUnitType>; type unitType = InterDataType<skuUnitType>;
interface selfProps { interface selfProps {
......
...@@ -5,20 +5,24 @@ import SkuInfo from './components/skuInfo'; ...@@ -5,20 +5,24 @@ import SkuInfo from './components/skuInfo';
import IntroduceInfo from './components/introduceInfo'; import IntroduceInfo from './components/introduceInfo';
import SkuAddOrEditModal from './components/skuAddOrEditModal'; import SkuAddOrEditModal from './components/skuAddOrEditModal';
import './index.scss'; import './index.scss';
import { useNavigate } from 'react-router-dom'; import { useNavigate, useSearchParams } from 'react-router-dom';
import { baseInfoType } from './components/baseInfo'; import { baseInfoType } from './components/baseInfo';
import { InterDataType, InterReqType } from '~/api/interface'; import { InterDataType, InterReqType } from '~/api/interface';
import { addMallGoodsType, skuUnitType } from '~/api/interface/goodsType'; import { addMallGoodsType, mallGoodsDetailsType, skuUnitType } from '~/api/interface/goodsType';
import GoodsAPI from '~/api/modules/goodsAPI'; import GoodsAPI from '~/api/modules/goodsAPI';
import { filterObjAttr } from '~/utils';
//商品sku规格类型 //商品sku规格类型
type goodsSpecType = InterReqType<addMallGoodsType>['goodsSpecList'][0]; type goodsSpecType = Exclude<InterReqType<addMallGoodsType>, undefined>['goodsSpecList'][0];
//单位返回类型 //单位返回类型
type unitType = InterDataType<skuUnitType>; type unitType = InterDataType<skuUnitType>;
//商品详情-返回类型
type goodsDetailType = InterDataType<mallGoodsDetailsType>;
const GoodsAddOrEditOrDetail = () => { const GoodsAddOrEditOrDetail = () => {
const baseInfoRef = useRef<any>(); const baseInfoRef = useRef<any>();
const navigate = useNavigate(); const navigate = useNavigate();
const [searchParams] = useSearchParams();
//单位列表 //单位列表
const [skuUnitList, setSkuUnitList] = useState<unitType>([]); const [skuUnitList, setSkuUnitList] = useState<unitType>([]);
...@@ -27,10 +31,14 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -27,10 +31,14 @@ const GoodsAddOrEditOrDetail = () => {
const [addOrEditSkuModalShow, setAddOrEditSkuModalShow] = useState<boolean>(false); const [addOrEditSkuModalShow, setAddOrEditSkuModalShow] = useState<boolean>(false);
//当前编辑sku //当前编辑sku
const [currentSku, setCurrentSku] = useState<goodsSpecType>(); const [currentSku, setCurrentSku] = useState<goodsSpecType>();
//基本信息暂存
const [baseInfo, setBaseInfo] = useState<baseInfoType>();
//skuTable数据 //skuTable数据
const [skuTable, setSkuTable] = useState<goodsSpecType[]>([]); const [skuTable, setSkuTable] = useState<goodsSpecType[]>([]);
//商品介绍详情
const [goodsDetails, setGoodsDetails] = useState<string>('');
//商品id
const [goodsId, setGoodsId] = useState<number>(0);
//商品详情
const [goodsDetailsInfo, setGoodsDetailsInfo] = useState<goodsDetailType>();
//新增、编辑sku弹窗显示 //新增、编辑sku弹窗显示
const addOrEditSkuClick = (record?: goodsSpecType) => { const addOrEditSkuClick = (record?: goodsSpecType) => {
...@@ -56,6 +64,10 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -56,6 +64,10 @@ const GoodsAddOrEditOrDetail = () => {
skuTable.splice(skuIndex, 1); skuTable.splice(skuIndex, 1);
setSkuTable([...skuTable]); setSkuTable([...skuTable]);
}; };
//商品详情获取
const getIntroduceInfo = (richText: string) => {
setGoodsDetails(richText);
};
const tabItems: TabsProps['items'] = [ const tabItems: TabsProps['items'] = [
{ {
...@@ -79,7 +91,7 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -79,7 +91,7 @@ const GoodsAddOrEditOrDetail = () => {
{ {
key: '3', key: '3',
label: `商品详情`, label: `商品详情`,
children: <IntroduceInfo />, children: <IntroduceInfo onChange={getIntroduceInfo} introduceInfo={goodsDetails} />,
}, },
]; ];
...@@ -94,8 +106,7 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -94,8 +106,7 @@ const GoodsAddOrEditOrDetail = () => {
baseInfoRef.current baseInfoRef.current
.getForm() .getForm()
.validateFields() .validateFields()
.then((value: baseInfoType) => { .then(() => {
setBaseInfo(value);
setTabSelectKeys((Number(tabSelectKeys) + 1).toString()); setTabSelectKeys((Number(tabSelectKeys) + 1).toString());
}) })
.catch((error: any) => { .catch((error: any) => {
...@@ -129,8 +140,95 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -129,8 +140,95 @@ const GoodsAddOrEditOrDetail = () => {
}); });
}; };
//商品保存
const saveGoods = () => {
baseInfoRef.current
.getForm()
.validateFields()
.then((values: baseInfoType) => {
if (skuTable.length) {
const skuList = skuTable.map((v) => ({
...v,
id: goodsDetailsInfo
? goodsDetailsInfo.goodsSpecList.find((i) => i.id === v.id)?.id
: undefined,
goodsSpecValuesList: v.goodsSpecValuesList.map((i) => ({
...i,
id: goodsDetailsInfo
? goodsDetailsInfo.goodsSpecList
.find((j) => j.id === v.id)
?.goodsSpecValuesList.find((k) => k.id === i.id)?.id
: undefined,
})),
}));
const addGoodsEditReq = {
...filterObjAttr(values, ['mainImgList', 'subImgList', 'videoList', 'categoryId']),
resourcesList: [
...values.mainImgList.map((v) => ({ type: 0, url: v.url })),
...(values.subImgList?.map((v) => ({ type: 1, url: v.url })) || []),
...(values.videoList?.map((v) => ({ type: 2, url: v.url })) || []),
],
categoryPrimaryId: values.categoryId[0],
categorySubId: values.categoryId.length === 2 ? values.categoryId[1] : undefined,
goodsDetails,
goodsSpecList: skuList,
id: goodsId || undefined,
};
GoodsAPI[goodsId ? 'editMallGoods' : 'addMallGoods'](addGoodsEditReq).then(({ code }) => {
if (code === '200') {
message.success(goodsId ? '编辑商城成功' : '新增商品成功');
navigate(-1);
}
});
} else {
message.warning('商品规格未添加');
}
})
.catch((error: any) => {
message.error(error.errorFields[0].errors[0]);
});
};
//商品详情
const getMallGoodsDetails = (id: number) => {
GoodsAPI.getMallGoodsDetails({ id }).then(({ result }) => {
const mainImgList = result.resourcesList
.filter((v) => v.type === 0)
.map((v) => ({ id: v.id, name: 'mainImg', uid: v.id, url: v.url }));
const subImgList = result.resourcesList
.filter((v) => v.type === 1)
.map((v) => ({ id: v.id, name: 'subImg', uid: v.id, url: v.url }));
const videoList = result.resourcesList
.filter((v) => v.type === 2)
.map((v) => ({ id: v.id, name: 'video', uid: v.id, url: v.url }));
setGoodsDetailsInfo(result);
setSkuTable(result.goodsSpecList);
setGoodsDetails(result.goodsDetails || '');
baseInfoRef.current.getForm().setFieldsValue({
tradeName: result.tradeName,
description: result.description || undefined,
mainImgList,
subImgList: subImgList.length ? subImgList : undefined,
videoList: videoList.length ? videoList : undefined,
categoryId: result.categorySubId
? [result.categoryPrimaryId, result.categorySubId]
: [result.categoryPrimaryId],
shelfStatus: result.shelfStatus,
labelShow: result.labelShow,
goodsLabel: result.goodsLabel || undefined,
});
baseInfoRef.current.setLabelShow(!!result.labelShow);
baseInfoRef.current.mediaData.setMainFileList(mainImgList);
baseInfoRef.current.mediaData.setSubFileList(subImgList);
baseInfoRef.current.mediaData.setVideoFileList(videoList);
});
};
useEffect(() => { useEffect(() => {
getSkuUnit(); getSkuUnit();
if (searchParams.get('id')) {
setGoodsId(Number(searchParams.get('id')));
getMallGoodsDetails(Number(searchParams.get('id')));
}
}, []); }, []);
return ( return (
...@@ -143,7 +241,9 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -143,7 +241,9 @@ const GoodsAddOrEditOrDetail = () => {
下一步 下一步
</Button> </Button>
) : ( ) : (
<Button type='primary'>保存</Button> <Button type='primary' onClick={saveGoods}>
保存
</Button>
)} )}
</div> </div>
<div className='back-btn'> <div className='back-btn'>
...@@ -155,7 +255,7 @@ const GoodsAddOrEditOrDetail = () => { ...@@ -155,7 +255,7 @@ const GoodsAddOrEditOrDetail = () => {
<SkuAddOrEditModal <SkuAddOrEditModal
open={addOrEditSkuModalShow} open={addOrEditSkuModalShow}
onCancel={addOrEditSkuModalCancel} onCancel={addOrEditSkuModalCancel}
onOk={addOrEditSkuModalOk} onHandleOk={addOrEditSkuModalOk}
skuUnitList={skuUnitList} skuUnitList={skuUnitList}
currentSku={currentSku} currentSku={currentSku}
/> />
......
const GoodsDetails = () => {
return <div className='goods-detail'></div>;
};
export default GoodsDetails;
...@@ -2,24 +2,22 @@ import SearchBox, { searchColumns } from '~/components/search-box'; ...@@ -2,24 +2,22 @@ import SearchBox, { searchColumns } from '~/components/search-box';
import React, { useEffect, useRef, useState } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom'; import { useNavigate, useSearchParams } from 'react-router-dom';
import { Button, Card, Image, message, Modal, Table } from 'antd'; import { Button, Card, Image, message, Modal, Table } from 'antd';
import { import { ArrowDownOutlined, ArrowUpOutlined, PlusOutlined } from '@ant-design/icons';
ArrowDownOutlined,
ArrowUpOutlined,
DeleteOutlined,
PlusOutlined,
} from '@ant-design/icons';
import { ColumnsType } from 'antd/es/table'; import { ColumnsType } from 'antd/es/table';
import GoodsAPI from '~/api/modules/goodsAPI'; import GoodsAPI from '~/api/modules/goodsAPI';
import { InterDataType, InterReqType, PaginationProps } from '~/api/interface'; import { InterDataType, InterReqType, PaginationProps } from '~/api/interface';
import { listGoodsType } from '~/api/interface/goodsType'; import { listPageGoodsInfoType } from '~/api/interface/goodsType';
import { CategoryManageAPI } from '~/api';
import { filterObjAttr } from '~/utils'; import { filterObjAttr } from '~/utils';
import qs from 'query-string'; import qs from 'query-string';
import { CategoryManageAPI } from '~/api';
import { categoryListRespType } from '~/api/interface/categoryManage';
//商品返回类型 //商品返回类型
type goodsType = InterDataType<listGoodsType>['list']; type goodsType = InterDataType<listPageGoodsInfoType>['list'];
//商品列表筛选类型 //商品列表筛选类型
type goodsSearchParameters = Omit<InterReqType<listGoodsType>, 'goodsType'>; type goodsSearchParameters = InterReqType<listPageGoodsInfoType>;
//分类返回类型
type categoryType = InterDataType<categoryListRespType>['list'];
const GoodsList = () => { const GoodsList = () => {
//筛选ref //筛选ref
...@@ -41,6 +39,8 @@ const GoodsList = () => { ...@@ -41,6 +39,8 @@ const GoodsList = () => {
}, },
]; ];
const [activeTabKey, setActiveTabKey] = useState<string>('1'); const [activeTabKey, setActiveTabKey] = useState<string>('1');
//分类列表
const [categoryList, setCategoryList] = useState<categoryType>([]);
const [searchColumns, setSearchColumns] = useState<searchColumns[]>([ const [searchColumns, setSearchColumns] = useState<searchColumns[]>([
{ {
label: '商品名称', label: '商品名称',
...@@ -49,18 +49,12 @@ const GoodsList = () => { ...@@ -49,18 +49,12 @@ const GoodsList = () => {
type: 'input', type: 'input',
}, },
{ {
label: '所属目录', label: '商品类型',
placeholder: '请选择所属目录', placeholder: '请选择商品类别',
name: 'directoryId', name: 'categoryPrimaryId',
type: 'select', type: 'select',
options: [], options: [],
}, },
{
label: '创建时间',
placeholder: '请输入选择创建时间',
name: 'time',
type: 'rangePicker',
},
]); ]);
const tableColumns: ColumnsType<goodsType[0]> = [ const tableColumns: ColumnsType<goodsType[0]> = [
{ {
...@@ -72,23 +66,29 @@ const GoodsList = () => { ...@@ -72,23 +66,29 @@ const GoodsList = () => {
{ {
title: '图片', title: '图片',
align: 'center', align: 'center',
dataIndex: 'imgUrl', dataIndex: 'resourcesList',
render: (text: string) => <Image src={text} width={50} height={50} />, render: (text: goodsType[0]['resourcesList']) => (
<Image src={text.find((v) => v.type === 0)?.url || ''} width={50} height={50} />
),
},
{ title: '商品名称', align: 'center', dataIndex: 'tradeName' },
{
title: '商品类别',
align: 'center',
render: (_text: string, record: goodsType[0]) => getCategoryStr(record),
}, },
{ title: '商品名称', align: 'center', dataIndex: 'goodsName' },
{ title: '所属目录', align: 'center', dataIndex: 'directoryName' },
{ title: '创建时间', align: 'center', dataIndex: 'createTime' }, { title: '创建时间', align: 'center', dataIndex: 'createTime' },
{ {
title: '状态', title: '状态',
align: 'center', align: 'center',
dataIndex: 'status', dataIndex: 'shelfStatus',
render: (text: number) => (text ? '上架' : '下架'), render: (text: number) => (text ? '上架' : '下架'),
}, },
{ {
title: '操作', title: '操作',
align: 'center', align: 'center',
dataIndex: 'id', dataIndex: 'id',
render: (id: number) => ( render: (id: number, record: goodsType[0]) => (
<> <>
<Button type='link' onClick={() => toEditGoods(id)}> <Button type='link' onClick={() => toEditGoods(id)}>
编辑 编辑
...@@ -96,6 +96,15 @@ const GoodsList = () => { ...@@ -96,6 +96,15 @@ const GoodsList = () => {
<Button type='link' onClick={() => toGoodsDetail(id)}> <Button type='link' onClick={() => toGoodsDetail(id)}>
详情 详情
</Button> </Button>
<Button type='link' onClick={() => upOrDownShelf(1, id)} disabled={!!record.shelfStatus}>
上架
</Button>
<Button type='link' onClick={() => upOrDownShelf(0, id)} disabled={!record.shelfStatus}>
下架
</Button>
<Button type='link' danger onClick={() => removeMallGoods(id)}>
删除
</Button>
</> </>
), ),
}, },
...@@ -113,20 +122,20 @@ const GoodsList = () => { ...@@ -113,20 +122,20 @@ const GoodsList = () => {
totalPage: 1, totalPage: 1,
}); });
//筛选 //筛选
const [query, setQuery] = useState<goodsSearchParameters>({ status: undefined }); const [query, setQuery] = useState<goodsSearchParameters>({ shelfStatus: undefined });
// 表格多选 // 表格多选
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onTabChange = (key: string) => { const onTabChange = (key: string) => {
pagination.pageNo = 1; pagination.pageNo = 1;
pagination.pageSize = 10; pagination.pageSize = 10;
query.status = key === '1' ? undefined : key === '2' ? 1 : 0; query.shelfStatus = key === '1' ? undefined : key === '2' ? 1 : 0;
setSearchParams( setSearchParams(
qs.stringify({ qs.stringify({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
...query, ...query,
status: query.status === undefined ? 'all' : query.status, shelfStatus: query.shelfStatus === undefined ? 'all' : query.shelfStatus,
}), }),
); );
getGoodsList(query); getGoodsList(query);
...@@ -142,7 +151,7 @@ const GoodsList = () => { ...@@ -142,7 +151,7 @@ const GoodsList = () => {
pageNo: pageNo, pageNo: pageNo,
pageSize: pageSize, pageSize: pageSize,
...query, ...query,
status: query.status === undefined ? 'all' : query.status, shelfStatus: query.shelfStatus === undefined ? 'all' : query.shelfStatus,
}), }),
); );
getGoodsList(query); getGoodsList(query);
...@@ -152,28 +161,24 @@ const GoodsList = () => { ...@@ -152,28 +161,24 @@ const GoodsList = () => {
const searchSuccess = (data: any) => { const searchSuccess = (data: any) => {
pagination.pageNo = 1; pagination.pageNo = 1;
pagination.pageSize = 10; pagination.pageSize = 10;
setQuery({ ...filterObjAttr(data, ['time']), status: query.status }); setQuery({ ...data, shelfStatus: query.shelfStatus });
getGoodsList({ ...filterObjAttr(data, ['time']), status: query.status }); getGoodsList({ ...data, shelfStatus: query.shelfStatus });
getGoodsList( getGoodsList({ ...data, shelfStatus: query.shelfStatus, pageSize: 9999, pageNo: 1 }, true);
{ ...filterObjAttr(data, ['time']), status: query.status, pageSize: 9999, pageNo: 1 },
true,
);
setSearchParams( setSearchParams(
qs.stringify({ qs.stringify({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
...filterObjAttr(data, ['time']), ...filterObjAttr(data, ['time']),
status: query.status === undefined ? 'all' : query.status, shelfStatus: query.shelfStatus === undefined ? 'all' : query.shelfStatus,
}), }),
); );
}; };
//商品列表 //商品列表
const getGoodsList = (query?: goodsSearchParameters, isAll?: boolean) => { const getGoodsList = (query?: goodsSearchParameters, isAll?: boolean) => {
setLoading(true); setLoading(true);
GoodsAPI.getGoodsList({ GoodsAPI.getListPageGoodsInfo({
pageNo: pagination.pageNo, pageNo: pagination.pageNo,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
goodsType: 0,
...query, ...query,
}).then(({ result }) => { }).then(({ result }) => {
setLoading(false); setLoading(false);
...@@ -200,50 +205,38 @@ const GoodsList = () => { ...@@ -200,50 +205,38 @@ const GoodsList = () => {
}; };
//商品详情 //商品详情
const toGoodsDetail = (id: number) => { const toGoodsDetail = (id: number) => {
navigate({ // navigate({
pathname: '/mallManage/mallGoods/detail', // pathname: '/mallManage/mallGoods/detail',
search: `id=${id}&isDetail=1`, // search: `id=${id}&isDetail=1`,
}); // });
}; };
// 表格多选事件 // 表格多选事件
const onSelectChange = (newSelectedRowKeys: React.Key[]) => { const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys); setSelectedRowKeys(newSelectedRowKeys);
}; };
//获取目录列表 //商品-单个上下架
const getDirectoryList = () => { const upOrDownShelf = (status: number, id: number) => {
CategoryManageAPI.getDirectoryListClone({ type: 4 }).then(({ result }) => { Modal.confirm({
if (result) { title: '提示',
const options = result.map((v) => ({ id: v.id, name: v.directoryName })); content: `确认${status ? '上架' : '下架'}该商品?`,
searchColumns[1].options = options; onOk: () => {
setSearchColumns([...searchColumns]); GoodsAPI.upOrDownShelf({ id, status }).then(({ code }) => {
} if (code === '200') {
}); message.success(status ? '上架成功' : '下架成功');
}; getGoodsList(query);
//商品-批量上下架 setSelectedRowKeys([]);
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);
setSelectedRowKeys([]);
}
}, },
); });
}; };
//商品-删除 //商品-删除
const deleteGoods = () => { const removeMallGoods = (id: number) => {
if (selectedRowKeys.length === 0) {
return message.warning('请先选择商品');
}
Modal.confirm({ Modal.confirm({
title: '提示', title: '提示',
content: '删除后数据将会丢失,确定删除吗?', content: '删除后数据将会丢失,确定删除吗?',
onOk() { onOk() {
GoodsAPI.batchRemoveWareInfo(selectedRowKeys as number[]).then(({ code }) => { GoodsAPI.removeMallGoods({ id }).then(({ code }) => {
if (code === '200') { if (code === '200') {
if (pagination.pageNo !== 1 && tableData.length == 1) { if (pagination.pageNo !== 1 && tableData.length == 1) {
pagination.pageNo -= 1; pagination.pageNo -= 1;
...@@ -276,7 +269,7 @@ const GoodsList = () => { ...@@ -276,7 +269,7 @@ const GoodsList = () => {
: tableData : tableData
.filter((_v, i) => index - 1 === i || index === i) .filter((_v, i) => index - 1 === i || index === i)
.map((v) => ({ id: v.id })); .map((v) => ({ id: v.id }));
GoodsAPI.exchangeGoodsInfo({ firstId: exReqData[0].id, secondId: exReqData[1].id }).then( GoodsAPI.exchange({ firstId: exReqData[0].id, secondId: exReqData[1].id }).then(
({ code }) => { ({ code }) => {
if (code === '200') { if (code === '200') {
message.success('上移成功'); message.success('上移成功');
...@@ -287,7 +280,7 @@ const GoodsList = () => { ...@@ -287,7 +280,7 @@ const GoodsList = () => {
pageNo: pagination.pageNo, pageNo: pagination.pageNo,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
...query, ...query,
status: query.status === undefined ? 'all' : query.status, shelfStatus: query.shelfStatus === undefined ? 'all' : query.shelfStatus,
}), }),
); );
} }
...@@ -319,7 +312,7 @@ const GoodsList = () => { ...@@ -319,7 +312,7 @@ const GoodsList = () => {
: tableData : tableData
.filter((_v, i) => index + 1 === i || index === i) .filter((_v, i) => index + 1 === i || index === i)
.map((v) => ({ id: v.id })); .map((v) => ({ id: v.id }));
GoodsAPI.exchangeGoodsInfo({ firstId: exReqData[0].id, secondId: exReqData[1].id }).then( GoodsAPI.exchange({ firstId: exReqData[0].id, secondId: exReqData[1].id }).then(
({ code }) => { ({ code }) => {
if (code === '200') { if (code === '200') {
message.success('下移成功'); message.success('下移成功');
...@@ -330,7 +323,7 @@ const GoodsList = () => { ...@@ -330,7 +323,7 @@ const GoodsList = () => {
pageNo: pagination.pageNo, pageNo: pagination.pageNo,
pageSize: pagination.pageSize, pageSize: pagination.pageSize,
...query, ...query,
status: query.status === undefined ? 'all' : query.status, shelfStatus: query.shelfStatus === undefined ? 'all' : query.shelfStatus,
}), }),
); );
} }
...@@ -342,41 +335,55 @@ const GoodsList = () => { ...@@ -342,41 +335,55 @@ const GoodsList = () => {
} }
} }
}; };
//分类列表
const getCategoryList = () => {
CategoryManageAPI.getCategoryRespList({ pageNo: 1, pageSize: 99999 }).then(({ result }) => {
searchColumns[1].options = (result.list || []).map((v) => ({ id: v.id, name: v.name }));
setSearchColumns([...searchColumns]);
setCategoryList(result.list || []);
});
};
//商品列表,分类组合
const getCategoryStr = (record: goodsType[0]) => {
return categoryList
.reduce((pre: string[], cur) => {
if (cur.id === record.categoryPrimaryId) {
pre.push(cur.name);
if (record.categorySubId) {
pre.push(cur.subDTOList.find((v) => v.id === record.categorySubId)?.name || '');
}
}
return pre;
}, [])
.join('/');
};
useEffect(() => { useEffect(() => {
getDirectoryList(); getCategoryList();
pagination.pageNo = Number(searchParams.get('pageNo') || 1); pagination.pageNo = Number(searchParams.get('pageNo') || 1);
pagination.pageSize = Number(searchParams.get('pageSize') || 10); pagination.pageSize = Number(searchParams.get('pageSize') || 10);
const queryObj = { const queryObj = {
goodsName: searchParams.get('goodsName') || undefined, tradeName: searchParams.get('goodsName') || undefined,
directoryId: searchParams.get('directoryId') shelfStatus:
? Number(searchParams.get('directoryId')) searchParams.get('shelfStatus') === 'all' || searchParams.get('shelfStatus') === null
: undefined,
startTime: searchParams.get('startTime') || undefined,
endTime: searchParams.get('endTime') || undefined,
status:
searchParams.get('status') === 'all' || searchParams.get('status') === null
? undefined ? undefined
: Number(searchParams.get('status')), : Number(searchParams.get('shelfStatus')),
}; };
getGoodsList(queryObj); getGoodsList(queryObj);
getGoodsList({ ...queryObj, pageNo: 1, pageSize: 9999 }, true); getGoodsList({ ...queryObj, pageNo: 1, pageSize: 9999 }, true);
setActiveTabKey( setActiveTabKey(
searchParams.get('status') === 'all' || searchParams.get('status') === null searchParams.get('shelfStatus') === 'all' || searchParams.get('shelfStatus') === null
? '1' ? '1'
: Number(searchParams.get('status')) === 1 : Number(searchParams.get('shelfStatus')) === 1
? '2' ? '2'
: '3', : '3',
); );
(searchRef.current as any).getForm().setFieldsValue({ (searchRef.current as any).getForm().setFieldsValue({
goodsName: searchParams.get('goodsName') || undefined, tradeName: 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 ( return (
<div className='goods-list'> <div className='goods-list'>
<SearchBox <SearchBox
...@@ -407,30 +414,6 @@ const GoodsList = () => { ...@@ -407,30 +414,6 @@ const GoodsList = () => {
> >
下移 下移
</Button> </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> </div>
<Table <Table
columns={tableColumns} columns={tableColumns}
...@@ -440,6 +423,8 @@ const GoodsList = () => { ...@@ -440,6 +423,8 @@ const GoodsList = () => {
rowSelection={{ rowSelection={{
selectedRowKeys, selectedRowKeys,
onChange: onSelectChange, onChange: onSelectChange,
type: 'radio',
hideSelectAll: true,
}} }}
loading={loading} loading={loading}
pagination={{ pagination={{
......
import _ from 'lodash';
// 不能输入数字,其他可以输入 // 不能输入数字,其他可以输入
export const exceptNumber = (val: any) => { export const exceptNumber = (val: any) => {
val.target.value = val.target.value.replace(/1?(\d|([1-9]\d+))(.\d+)?$/g, '').replace(/\s/g, ''); val.target.value = val.target.value.replace(/1?(\d|([1-9]\d+))(.\d+)?$/g, '').replace(/\s/g, '');
...@@ -105,3 +107,13 @@ export const maxLength6 = (val: any) => { ...@@ -105,3 +107,13 @@ export const maxLength6 = (val: any) => {
val.target.value = val.target.value.replace(/\D/g, ''); val.target.value = val.target.value.replace(/\D/g, '');
} }
}; };
//通用价格,且保留两位小数正则
export const regPriceNumber = (value: string): boolean => {
const reg = /^\d+(\.\d{1,2})?$/;
return reg.test(value);
};
//判断空值
export const isEmptyBol = (value: any): boolean => {
return _.isNull(value) || _.isNaN(value) || _.isNull(value) || _.isUndefined(value);
};
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论