forked from yoone/WEB
541 lines
14 KiB
TypeScript
541 lines
14 KiB
TypeScript
import { PRODUCT_STATUS_ENUM } from '@/constants';
|
||
import {
|
||
productcontrollerProductbysku,
|
||
productcontrollerSearchproducts,
|
||
} from '@/servers/api/product';
|
||
import { sitecontrollerAll } from '@/servers/api/site';
|
||
import {
|
||
wpproductcontrollerGetwpproducts,
|
||
wpproductcontrollerSetconstitution,
|
||
wpproductcontrollerSyncproducts,
|
||
wpproductcontrollerUpdateproduct,
|
||
wpproductcontrollerUpdatevariation,
|
||
} from '@/servers/api/wpProduct';
|
||
import { EditOutlined } from '@ant-design/icons';
|
||
import {
|
||
ActionType,
|
||
DrawerForm,
|
||
PageContainer,
|
||
ProColumns,
|
||
ProForm,
|
||
ProFormDigit,
|
||
ProFormList,
|
||
ProFormSelect,
|
||
ProFormText,
|
||
ProTable,
|
||
} from '@ant-design/pro-components';
|
||
import { App, Button, Divider, Form } from 'antd';
|
||
import { useRef } from 'react';
|
||
|
||
const List: React.FC = () => {
|
||
const actionRef = useRef<ActionType>();
|
||
const columns: ProColumns<API.WpProductDTO>[] = [
|
||
{
|
||
title: '名称',
|
||
dataIndex: 'name',
|
||
},
|
||
{
|
||
title: '站点',
|
||
dataIndex: 'siteId',
|
||
valueType: 'select',
|
||
request: async () => {
|
||
const { data = [] } = await sitecontrollerAll();
|
||
return data.map((item) => ({
|
||
label: item.siteName,
|
||
value: item.id,
|
||
}));
|
||
},
|
||
},
|
||
{
|
||
title: 'sku',
|
||
dataIndex: 'sku',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '产品状态',
|
||
dataIndex: 'status',
|
||
valueType: 'select',
|
||
valueEnum: PRODUCT_STATUS_ENUM,
|
||
},
|
||
{
|
||
title: '常规价格',
|
||
dataIndex: 'regular_price',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '销售价格',
|
||
dataIndex: 'sale_price',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '更新时间',
|
||
dataIndex: 'updatedAt',
|
||
valueType: 'dateTime',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '创建时间',
|
||
dataIndex: 'createdAt',
|
||
valueType: 'dateTime',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '操作',
|
||
dataIndex: 'option',
|
||
valueType: 'option',
|
||
render: (_, record) => (
|
||
<>
|
||
<UpdateForm tableRef={actionRef} values={record} />
|
||
{record.type === 'simple' && record.sku ? (
|
||
<>
|
||
<Divider type="vertical" />
|
||
<SetComponent
|
||
tableRef={actionRef}
|
||
values={record}
|
||
isProduct={true}
|
||
/>
|
||
</>
|
||
) : (
|
||
<></>
|
||
)}
|
||
</>
|
||
),
|
||
},
|
||
];
|
||
const varColumns: ProColumns<API.VariationDTO>[] = [
|
||
{
|
||
title: '变体名',
|
||
dataIndex: 'name',
|
||
},
|
||
{
|
||
title: 'sku',
|
||
dataIndex: 'sku',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '常规价格',
|
||
dataIndex: 'regular_price',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '销售价格',
|
||
dataIndex: 'sale_price',
|
||
hideInSearch: true,
|
||
},
|
||
{
|
||
title: '操作',
|
||
dataIndex: 'option',
|
||
valueType: 'option',
|
||
render: (_, record) => (
|
||
<>
|
||
<UpdateVaritation tableRef={actionRef} values={record} />
|
||
{record.sku ? (
|
||
<>
|
||
<Divider type="vertical" />
|
||
<SetComponent
|
||
tableRef={actionRef}
|
||
values={record}
|
||
isProduct={false}
|
||
/>
|
||
</>
|
||
) : (
|
||
<></>
|
||
)}
|
||
</>
|
||
),
|
||
},
|
||
];
|
||
|
||
return (
|
||
<PageContainer header={{ title: 'WP产品列表' }}>
|
||
<ProTable<API.WpProductDTO>
|
||
headerTitle="查询表格"
|
||
actionRef={actionRef}
|
||
rowKey="id"
|
||
request={async (params) => {
|
||
const { data, success } = await wpproductcontrollerGetwpproducts(
|
||
params,
|
||
);
|
||
return {
|
||
total: data?.total || 0,
|
||
data: data?.items || [],
|
||
success,
|
||
};
|
||
}}
|
||
columns={columns}
|
||
toolBarRender={() => [<SyncForm tableRef={actionRef} />]}
|
||
expandable={{
|
||
rowExpandable: (record) => record.type === 'variable',
|
||
expandedRowRender: (record) => (
|
||
<ProTable<API.VariationDTO>
|
||
rowKey="id"
|
||
dataSource={record.variations}
|
||
pagination={false}
|
||
search={false}
|
||
options={false}
|
||
columns={varColumns}
|
||
/>
|
||
),
|
||
}}
|
||
/>
|
||
</PageContainer>
|
||
);
|
||
};
|
||
|
||
const SyncForm: React.FC<{
|
||
tableRef: React.MutableRefObject<ActionType | undefined>;
|
||
}> = ({ tableRef }) => {
|
||
const { message } = App.useApp();
|
||
return (
|
||
<DrawerForm<API.wpproductcontrollerSyncproductsParams>
|
||
title="同步产品"
|
||
trigger={
|
||
<Button key="syncSite" type="primary">
|
||
同步产品
|
||
</Button>
|
||
}
|
||
autoFocusFirstInput
|
||
drawerProps={{
|
||
destroyOnClose: true,
|
||
}}
|
||
onFinish={async (values) => {
|
||
try {
|
||
const { success, message: errMsg } =
|
||
await wpproductcontrollerSyncproducts(values);
|
||
if (!success) {
|
||
throw new Error(errMsg);
|
||
}
|
||
message.success('同步成功');
|
||
tableRef.current?.reload();
|
||
return true;
|
||
} catch (error: any) {
|
||
message.error(error.message);
|
||
}
|
||
}}
|
||
>
|
||
<ProForm.Group>
|
||
<ProFormSelect
|
||
name="siteId"
|
||
width="lg"
|
||
label="站点"
|
||
placeholder="请选择站点"
|
||
request={async () => {
|
||
const { data = [] } = await sitecontrollerAll();
|
||
return data.map((item) => ({
|
||
label: item.siteName,
|
||
value: item.id,
|
||
}));
|
||
}}
|
||
/>
|
||
</ProForm.Group>
|
||
</DrawerForm>
|
||
);
|
||
};
|
||
|
||
const UpdateForm: React.FC<{
|
||
tableRef: React.MutableRefObject<ActionType | undefined>;
|
||
values: API.WpProductDTO;
|
||
}> = ({ tableRef, values: initialValues }) => {
|
||
const { message } = App.useApp();
|
||
return (
|
||
<DrawerForm<API.UpdateProductDTO>
|
||
title="编辑产品"
|
||
initialValues={initialValues}
|
||
trigger={
|
||
<Button type="primary">
|
||
<EditOutlined />
|
||
编辑
|
||
</Button>
|
||
}
|
||
autoFocusFirstInput
|
||
drawerProps={{
|
||
destroyOnClose: true,
|
||
}}
|
||
onFinish={async (values) => {
|
||
const { siteId, ...params } = values;
|
||
try {
|
||
const { success, message: errMsg } =
|
||
await wpproductcontrollerUpdateproduct(
|
||
{
|
||
productId: initialValues.externalProductId,
|
||
siteId,
|
||
},
|
||
params,
|
||
);
|
||
if (!success) {
|
||
throw new Error(errMsg);
|
||
}
|
||
message.success('提交成功');
|
||
tableRef.current?.reload();
|
||
return true;
|
||
} catch (error: any) {
|
||
message.error(error.message);
|
||
}
|
||
}}
|
||
>
|
||
<ProForm.Group>
|
||
<ProFormText label="名称" width="lg" name="name" />
|
||
<ProFormSelect
|
||
width="lg"
|
||
label="站点"
|
||
request={async () => {
|
||
const { data = [] } = await sitecontrollerAll();
|
||
return data.map((item) => ({
|
||
label: item.siteName,
|
||
value: item.id,
|
||
}));
|
||
}}
|
||
name="siteId"
|
||
disabled
|
||
/>
|
||
<ProFormText
|
||
name="sku"
|
||
width="lg"
|
||
label="sku"
|
||
tooltip="Example: TO-ZY-06MG-WG-S-0001"
|
||
placeholder="请输入SKU"
|
||
/>
|
||
{initialValues.type === 'simple' ? (
|
||
<>
|
||
<ProFormDigit
|
||
name="regular_price"
|
||
width="lg"
|
||
label="常规价格"
|
||
fieldProps={{
|
||
precision: 2,
|
||
}}
|
||
/>
|
||
<ProFormDigit
|
||
name="sale_price"
|
||
width="lg"
|
||
label="促销价格"
|
||
fieldProps={{
|
||
precision: 2,
|
||
}}
|
||
/>
|
||
</>
|
||
) : (
|
||
<></>
|
||
)}
|
||
</ProForm.Group>
|
||
</DrawerForm>
|
||
);
|
||
};
|
||
|
||
const UpdateVaritation: React.FC<{
|
||
tableRef: React.MutableRefObject<ActionType | undefined>;
|
||
values: API.VariationDTO;
|
||
}> = ({ tableRef, values: initialValues }) => {
|
||
const { message } = App.useApp();
|
||
return (
|
||
<DrawerForm<API.UpdateProductDTO>
|
||
title="编辑变体"
|
||
initialValues={initialValues}
|
||
trigger={
|
||
<Button type="primary">
|
||
<EditOutlined />
|
||
编辑
|
||
</Button>
|
||
}
|
||
autoFocusFirstInput
|
||
drawerProps={{
|
||
destroyOnClose: true,
|
||
}}
|
||
onFinish={async (values) => {
|
||
const { ...params } = values;
|
||
try {
|
||
const { success, message: errMsg } =
|
||
await wpproductcontrollerUpdatevariation(
|
||
{
|
||
siteId: initialValues.siteId,
|
||
productId: initialValues.externalProductId,
|
||
variationId: initialValues.externalVariationId,
|
||
},
|
||
params,
|
||
);
|
||
if (!success) {
|
||
throw new Error(errMsg);
|
||
}
|
||
message.success('提交成功');
|
||
tableRef.current?.reload();
|
||
return true;
|
||
} catch (error: any) {
|
||
message.error(error.message);
|
||
}
|
||
}}
|
||
>
|
||
<ProForm.Group>
|
||
<ProFormText label="变体名称" width="lg" name="name" />
|
||
<ProFormText
|
||
name="sku"
|
||
width="lg"
|
||
label="sku"
|
||
tooltip="Example: TO-ZY-06MG-WG-S-0001"
|
||
placeholder="请输入SKU"
|
||
/>
|
||
<ProFormDigit
|
||
name="regular_price"
|
||
width="lg"
|
||
label="常规价格"
|
||
fieldProps={{
|
||
precision: 2,
|
||
}}
|
||
/>
|
||
<ProFormDigit
|
||
name="sale_price"
|
||
width="lg"
|
||
label="促销价格"
|
||
fieldProps={{
|
||
precision: 2,
|
||
}}
|
||
/>
|
||
</ProForm.Group>
|
||
</DrawerForm>
|
||
);
|
||
};
|
||
|
||
const SetComponent: React.FC<{
|
||
tableRef: React.MutableRefObject<ActionType | undefined>;
|
||
values: API.VariationDTO | API.WpProductDTO;
|
||
isProduct: boolean;
|
||
}> = ({ tableRef, values: { id, constitution, name }, isProduct = false }) => {
|
||
const { message } = App.useApp();
|
||
const [form] = Form.useForm();
|
||
|
||
const fetchInitialValues = async () => {
|
||
const initData = await Promise.all(
|
||
constitution?.map?.(async (item) => {
|
||
const { data } = await productcontrollerProductbysku({
|
||
sku: item.sku as string,
|
||
});
|
||
return {
|
||
quantity: item.quantity,
|
||
sku: {
|
||
label: data?.name,
|
||
value: item.sku,
|
||
},
|
||
};
|
||
}) || [],
|
||
);
|
||
form.setFieldsValue({
|
||
constitution: initData,
|
||
});
|
||
};
|
||
|
||
return (
|
||
<DrawerForm<API.SetConstitutionDTO>
|
||
title={name}
|
||
form={form}
|
||
trigger={
|
||
<Button type="primary" danger={constitution?.length === 0}>
|
||
<EditOutlined />
|
||
构成
|
||
</Button>
|
||
}
|
||
autoFocusFirstInput
|
||
drawerProps={{
|
||
destroyOnClose: true,
|
||
}}
|
||
onFinish={async ({ constitution }) => {
|
||
try {
|
||
const { success, message: errMsg } =
|
||
await wpproductcontrollerSetconstitution(
|
||
{
|
||
id,
|
||
},
|
||
{
|
||
isProduct,
|
||
constitution,
|
||
},
|
||
);
|
||
if (!success) {
|
||
throw new Error(errMsg);
|
||
}
|
||
message.success('提交成功');
|
||
tableRef.current?.reload();
|
||
return true;
|
||
} catch (error: any) {
|
||
message.error(error.message);
|
||
}
|
||
}}
|
||
onOpenChange={(visiable) => {
|
||
if (visiable) fetchInitialValues();
|
||
}}
|
||
>
|
||
<ProForm.Group>
|
||
<ProFormList<{
|
||
sku: string;
|
||
quantity: number;
|
||
}>
|
||
name="constitution"
|
||
rules={[
|
||
{
|
||
required: true,
|
||
message: '至少需要一个商品',
|
||
validator: (_, value) =>
|
||
value && value.length > 0
|
||
? Promise.resolve()
|
||
: Promise.reject('至少需要一个商品'),
|
||
},
|
||
]}
|
||
creatorButtonProps={{ children: '新增' }}
|
||
>
|
||
{(fields, idx, { remove }) => (
|
||
<div key={idx}>
|
||
<ProFormSelect
|
||
request={async ({ keyWords }) => {
|
||
if (keyWords.length < 3) return [];
|
||
try {
|
||
const { data } = await productcontrollerSearchproducts({
|
||
name: keyWords,
|
||
});
|
||
const arr =
|
||
data?.map((item) => {
|
||
return {
|
||
label: item.name,
|
||
value: item.sku,
|
||
};
|
||
}) || [];
|
||
return arr;
|
||
} catch (error) {
|
||
console.log(error);
|
||
return [];
|
||
}
|
||
}}
|
||
name="sku"
|
||
label="产品"
|
||
width="lg"
|
||
placeholder="请选择产品"
|
||
tooltip="至少输入3个字符"
|
||
fieldProps={{
|
||
showSearch: true,
|
||
filterOption: false,
|
||
}}
|
||
transform={(value) => {
|
||
return value?.value || value;
|
||
}}
|
||
debounceTime={300} // 防抖,减少请求频率
|
||
rules={[{ required: true, message: '请选择产品' }]}
|
||
/>
|
||
<ProFormDigit
|
||
name="quantity"
|
||
label="数量"
|
||
placeholder="请输入数量"
|
||
rules={[{ required: true, message: '请输入数量' }]}
|
||
fieldProps={{
|
||
precision: 0,
|
||
}}
|
||
/>
|
||
<Button type="link" danger onClick={() => remove(fields.key)}>
|
||
删除
|
||
</Button>
|
||
</div>
|
||
)}
|
||
</ProFormList>
|
||
</ProForm.Group>
|
||
</DrawerForm>
|
||
);
|
||
};
|
||
|
||
export default List;
|