WEB/src/pages/Product/List/index.tsx

395 lines
11 KiB
TypeScript

import {
productcontrollerCreateproduct,
productcontrollerDeleteproduct,
productcontrollerGetbrandall,
productcontrollerGetflavorsall,
productcontrollerGetproductlist,
productcontrollerGetstrengthall,
productcontrollerUpdateproductnamecn,
} from '@/servers/api/product';
import { templatecontrollerRendertemplate } from '@/servers/api/template';
import { PlusOutlined } from '@ant-design/icons';
import {
ActionType,
DrawerForm,
PageContainer,
ProColumns,
ProForm,
ProFormInstance,
ProFormSelect,
ProFormText,
ProFormTextArea,
ProTable,
} from '@ant-design/pro-components';
import { App, Button, Popconfirm } from 'antd';
import React, { useRef, useState } from 'react';
// TODO
interface DictItem {
id: number;
name: string;
title: string;
}
const NameCn: React.FC<{
id: number;
value: string | undefined;
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ value, tableRef, id }) => {
const { message } = App.useApp();
const [editable, setEditable] = React.useState<boolean>(false);
if (!editable)
return <div onClick={() => setEditable(true)}>{value || '-'}</div>;
return (
<ProFormText
initialValue={value}
fieldProps={{
autoFocus: true,
onBlur: async (e: React.FocusEvent<HTMLInputElement>) => {
if (!e.target.value) return setEditable(false);
const { success, message: errMsg } =
await productcontrollerUpdateproductnamecn({
id,
nameCn: e.target.value,
});
setEditable(false);
if (!success) {
return message.error(errMsg);
}
tableRef?.current?.reload();
},
}}
/>
);
};
const List: React.FC = () => {
const actionRef = useRef<ActionType>();
// 状态:存储当前选中的行
const [selectedRows, setSelectedRows] = React.useState<API.Product[]>([]);
const { message } = App.useApp();
const columns: ProColumns<API.Product>[] = [
{
title: '名称',
dataIndex: 'name',
},
{
title: '中文名',
dataIndex: 'nameCn',
render: (_, record) => {
return (
<NameCn value={record.nameCn} id={record.id} tableRef={actionRef} />
);
},
},
{
title: '产品描述',
dataIndex: 'description',
hideInSearch: true,
},
{
title: '产品品牌',
dataIndex: 'brandName',
},
{
title: '强度',
dataIndex: 'strengthName',
},
{
title: '口味',
dataIndex: 'flavorsName',
},
{
title: '湿度',
dataIndex: 'humidity',
},
{
title: 'sku',
dataIndex: 'sku',
},
{
title: '更新时间',
dataIndex: 'updatedAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '创建时间',
dataIndex: 'createdAt',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
dataIndex: 'option',
valueType: 'option',
render: (_, record) => (
<>
<Popconfirm
title="删除"
description="确认删除?"
onConfirm={async () => {
try {
const { success, message: errMsg } =
await productcontrollerDeleteproduct({ id: record.id });
if (!success) {
throw new Error(errMsg);
}
actionRef.current?.reload();
} catch (error: any) {
message.error(error.message);
}
}}
>
<Button type="primary" danger>
</Button>
</Popconfirm>
</>
),
},
];
return (
<PageContainer header={{ title: '产品列表' }}>
<ProTable<API.Product>
headerTitle="查询表格"
actionRef={actionRef}
rowKey="id"
toolBarRender={() => [<CreateForm tableRef={actionRef} />]}
request={async (params) => {
const { data, success } = await productcontrollerGetproductlist(
params,
);
return {
total: data?.total || 0,
data: data?.items || [],
success,
};
}}
columns={columns}
editable={{
type: 'single',
onSave: async (key, record, originRow) => {
console.log('保存数据:', record);
},
}}
rowSelection={{
onChange: (_, selectedRows) => setSelectedRows(selectedRows),
}}
/>
</PageContainer>
);
};
const CreateForm: React.FC<{
tableRef: React.MutableRefObject<ActionType | undefined>;
}> = ({ tableRef }) => {
// antd 的消息提醒
const { message } = App.useApp();
// 表单引用
const formRef = useRef<ProFormInstance>();
// 状态:存储品牌、强度和口味的选项
const [brandOptions, setBrandOptions] = useState<DictItem[]>([]);
const [strengthOptions, setStrengthOptions] = useState<DictItem[]>([]);
const [flavorOptions, setFlavorOptions] = useState<DictItem[]>([]);
/**
* @description 生成 SKU
*/
const handleGenerateSku = async () => {
try {
// 从表单引用中获取当前表单的值
const formValues = formRef.current?.getFieldsValue();
const { humidity, brandId, strengthId, flavorsId } = formValues;
// 检查是否所有必需的字段都已选择
if (!brandId || !strengthId || !flavorsId || !humidity) {
message.warning('请先选择品牌、强度、口味和干湿');
return;
}
// 从选项中查找所选品牌、强度和口味的完整对象
const brand = brandOptions.find((item) => item.id === brandId);
const strength = strengthOptions.find((item) => item.id === strengthId);
const flavor = flavorOptions.find((item) => item.id === flavorsId);
// 调用模板渲染API来生成SKU
const { data: rendered, message: msg, success } = await templatecontrollerRendertemplate(
{ name: 'product.sku' },
{
brand: brand ? brand.name : "",
strength: strength ? strength.name : '',
flavor: flavor ? flavor.name : '',
humidity: humidity === 'dry' ? 'Dry' : 'Moisture',
},
);
if (!success) {
throw new Error(msg);
}
// 将生成的SKU设置到表单字段中
formRef.current?.setFieldsValue({ sku: rendered });
} catch (error: any) {
message.error(`生成失败: ${error.message}`);
}
};
/**
* @description 生成产品名称
*/
const handleGenerateName = async () => {
try {
// 从表单引用中获取当前表单的值
const formValues = formRef.current?.getFieldsValue();
const { humidity, brandId, strengthId, flavorsId } = formValues;
// 检查是否所有必需的字段都已选择
if (!brandId || !strengthId || !flavorsId || !humidity) {
message.warning('请先选择品牌、强度、口味和干湿');
return;
}
// 从选项中查找所选品牌、强度和口味的完整对象
const brand = brandOptions.find((item) => item.id === brandId);
const strength = strengthOptions.find((item) => item.id === strengthId);
const flavor = flavorOptions.find((item) => item.id === flavorsId);
// 调用模板渲染API来生成产品名称
const { message: msg, data: rendered, success } = await templatecontrollerRendertemplate(
{ name: 'product.title' },
{
brand: brand ? brand.title : "",
strength: strength ? strength.title : '',
flavor: flavor ? flavor.title : '',
model: '',
humidity: humidity === 'dry' ? 'Dry' : 'Moisture',
},
);
if (!success) {
throw new Error(msg);
}
// 将生成的名称设置到表单字段中
formRef.current?.setFieldsValue({ name: rendered });
} catch (error: any) {
message.error(`生成失败: ${error.message}`);
}
};
// TODO 可以输入brand等
return (
<DrawerForm<API.CreateProductDTO>
title="新建"
formRef={formRef} // Pass formRef
trigger={
<Button type="primary">
<PlusOutlined />
</Button>
}
autoFocusFirstInput
drawerProps={{
destroyOnHidden: true,
}}
onFinish={async (values) => {
try {
const { success, message: errMsg } =
await productcontrollerCreateproduct(values);
if (!success) {
throw new Error(errMsg);
}
tableRef.current?.reload();
message.success('提交成功');
return true;
} catch (error: any) {
message.error(error.message);
}
}}
>
<ProFormSelect
name="brandId"
width="lg"
label="产品品牌"
placeholder="请选择产品品牌"
request={async () => {
const { data = [] } = await productcontrollerGetbrandall();
setBrandOptions(data);
return data.map((item: DictItem) => ({
label: item.name,
value: item.id,
}));
}}
rules={[{ required: true, message: '请选择产品品牌' }]}
/>
<ProFormSelect
name="strengthId"
width="lg"
label="强度"
placeholder="请选择强度"
request={async () => {
const { data = [] } = await productcontrollerGetstrengthall();
setStrengthOptions(data);
return data.map((item: DictItem) => ({
label: item.name,
value: item.id,
}));
}}
rules={[{ required: true, message: '请选择强度' }]}
/>
<ProFormSelect
name="flavorsId"
width="lg"
label="口味"
placeholder="请选择口味"
request={async () => {
const { data = [] } = await productcontrollerGetflavorsall();
setFlavorOptions(data);
return data.map((item: DictItem) => ({
label: item.name,
value: item.id,
}));
}}
rules={[{ required: true, message: '请选择口味' }]}
/>
<ProFormSelect
name="humidity"
width="lg"
label="干湿"
placeholder="请选择干湿"
valueEnum={{
dry: 'dry',
wet: 'wet',
}}
rules={[{ required: true, message: '请选择干湿' }]}
/>
<ProForm.Group>
<ProFormText
name="sku"
label="SKU"
width="md"
placeholder="请输入SKU"
rules={[{ required: true, message: '请输入SKU' }]}
/>
<Button style={{ marginTop: '32px' }} onClick={handleGenerateSku}>
</Button>
</ProForm.Group>
<ProForm.Group>
<ProFormText
name="name"
label="名称"
width="md"
placeholder="请输入名称"
rules={[{ required: true, message: '请输入名称' }]}
/>
<Button style={{ marginTop: '32px' }} onClick={handleGenerateName}>
</Button>
</ProForm.Group>
<ProFormTextArea
name="description"
width="lg"
label="产品描述"
placeholder="请输入产品描述"
/>
</DrawerForm>
);
};
export default List;