refactor: 统一将 productSku 字段重命名为 sku

简化产品 SKU 字段命名,将 productSku 统一改为 sku,保持代码一致性
This commit is contained in:
tikkhun 2025-12-01 10:59:35 +08:00
parent 0f264c15a5
commit 52e982ba42
8 changed files with 153 additions and 154 deletions

View File

@ -1,5 +1,4 @@
import {
productcontrollerAutobindcomponents,
productcontrollerCreateproduct,
productcontrollerDeleteproduct,
productcontrollerGetproductcomponents,
@ -32,12 +31,7 @@ import AttributeFormItem from '@/pages/Product/Attribute/components/AttributeFor
import React, { useMemo, useRef, useState } from 'react';
const capitalize = (s: string) => s.charAt(0).toLocaleUpperCase() + s.slice(1);
// TODO
interface DictItem {
id: number;
name: string;
title: string;
}
const NameCn: React.FC<{
id: number;
value: string | undefined;
@ -97,7 +91,7 @@ const ComponentsCell: React.FC<{ productId: number }> = ({ productId }) => {
{components && components.length ? (
components.map((component: any) => (
<Tag key={component.id} color="blue" style={{ marginBottom: 4 }}>
{component.productSku || `#${component.id}`} × {component.quantity}
{component.sku || `#${component.id}`} × {component.quantity}
{component.stock
?.map((s: any) => `${s.name}:${s.quantity}`)
@ -160,6 +154,27 @@ const List: React.FC = () => {
);
},
},
{
title: '产品类型',
dataIndex: 'type',
valueType: 'select',
valueEnum: {
single: { text: '单品' },
bundle: { text: '套装' },
},
render: (_, record) => {
// 如果类型不存在,则返回-
if (!record.type) return '-';
// 判断是否为单品
const isSingle = record.type === 'single';
// 根据类型显示不同颜色的标签
return (
<Tag color={isSingle ? 'green' : 'orange'}>
{isSingle ? '单品' : '套装'}
</Tag>
);
},
},
{
title: '价格',
dataIndex: 'price',
@ -429,24 +444,24 @@ const CreateForm: React.FC<{
if (sku) {
// 获取库存信息
const { data } = await stockcontrollerGetstocks({
productSku: sku,
sku: sku,
} as any);
// 如果库存信息存在且不为空
if (data && data.items && data.items.length > 0) {
// 设置在库状态
setStockStatus('in-stock');
// 设置产品类型为单品
formRef.current?.setFieldsValue({ productType: 'single' });
formRef.current?.setFieldsValue({ type: 'single' });
} else {
// 设置未在库状态
setStockStatus('out-of-stock');
// 设置产品类型为套装
formRef.current?.setFieldsValue({ productType: 'bundle' });
formRef.current?.setFieldsValue({ type: 'bundle' });
}
} else {
// 如果 sku 不存在,则重置状态
setStockStatus(null);
formRef.current?.setFieldsValue({ productType: null });
formRef.current?.setFieldsValue({ type: null });
}
}
}}
@ -485,8 +500,8 @@ const CreateForm: React.FC<{
price: (values as any).price,
promotionPrice: (values as any).promotionPrice,
attributes,
components:
values.productType === 'bundle' ? values.components : undefined,
type: values.type, // 直接使用 type
components: values.components,
};
const { success, message: errMsg } =
await productcontrollerCreateproduct(payload);
@ -507,9 +522,6 @@ const CreateForm: React.FC<{
placeholder="请输入SKU"
rules={[{ required: true, message: '请输入SKU' }]}
/>
<Button style={{ marginTop: '32px' }} onClick={handleGenerateSku}>
</Button>
{stockStatus && (
<Tag
style={{ marginTop: '32px' }}
@ -532,7 +544,7 @@ const CreateForm: React.FC<{
</Button>
</ProForm.Group>
<ProFormSelect
name="productType"
name="type"
label="产品类型"
options={[
{ value: 'single', label: '单品' },
@ -542,12 +554,12 @@ const CreateForm: React.FC<{
/>
<ProForm.Item
shouldUpdate={(prevValues: any, curValues: any) =>
prevValues.productType !== curValues.productType
prevValues.type !== curValues.type
}
noStyle
>
{({ getFieldValue }: { getFieldValue: (name: string) => any }) =>
getFieldValue('productType') === 'bundle' ? (
getFieldValue('type') === 'bundle' ? (
<ProFormList
name="components"
label="产品组成"
@ -641,23 +653,28 @@ const EditForm: React.FC<{
const { message } = App.useApp();
const formRef = useRef<ProFormInstance>();
const [components, setComponents] = useState<
{ productSku: string; quantity: number }[]
{ sku: string; quantity: number }[]
>([]);
const [productType, setProductType] = useState<'single' | 'bundle' | null>(
null,
);
const [type, setType] = useState<'single' | 'bundle' | null>(null);
const [stockStatus, setStockStatus] = useState<
'in-stock' | 'out-of-stock' | null
>(null);
React.useEffect(() => {
(async () => {
const { data: stockData } = await stockcontrollerGetstocks({
productSku: record.sku,
sku: record.sku,
} as any);
if (stockData && stockData.items && stockData.items.length > 0) {
setProductType('single');
formRef.current?.setFieldsValue({ productType: 'single' });
// 如果有库存,则为单品
setType('single');
setStockStatus('in-stock');
formRef.current?.setFieldsValue({ type: 'single' });
} else {
setProductType('bundle');
formRef.current?.setFieldsValue({ productType: 'bundle' });
// 如果没有库存,则为套装
setType('bundle');
setStockStatus('out-of-stock');
formRef.current?.setFieldsValue({ type: 'bundle' });
}
const { data: componentsData } =
await productcontrollerGetproductcomponents({ id: record.id });
@ -680,9 +697,9 @@ const EditForm: React.FC<{
return acc;
}, {} as any),
components: components,
productType: productType,
type: type,
};
}, [record, components, productType]);
}, [record, components, type]);
return (
<DrawerForm<any>
@ -702,19 +719,19 @@ const EditForm: React.FC<{
if (sku) {
// 获取库存信息
const { data } = await stockcontrollerGetstocks({
productSku: sku,
sku: sku,
} as any);
// 如果库存信息存在且不为空
if (data && data.items && data.items.length > 0) {
// 设置产品类型为单品
formRef.current?.setFieldsValue({ productType: 'single' });
formRef.current?.setFieldsValue({ type: 'single' });
} else {
// 设置产品类型为套装
formRef.current?.setFieldsValue({ productType: 'bundle' });
formRef.current?.setFieldsValue({ type: 'bundle' });
}
} else {
// 如果 sku 不存在,则重置状态
formRef.current?.setFieldsValue({ productType: null });
formRef.current?.setFieldsValue({ type: null });
}
}
}}
@ -752,12 +769,13 @@ const EditForm: React.FC<{
price: (values as any).price,
promotionPrice: (values as any).promotionPrice,
attributes,
type: values.type, // 直接使用 type
};
const { success, message: errMsg } =
await productcontrollerUpdateproduct({ id: record.id }, payload);
if (values.productType === 'bundle') {
if (values.type === 'bundle') {
const { success: success2, message: errMsg2 } =
await productcontrollerSetproductcomponents(
{ id: record.id },
@ -791,21 +809,14 @@ const EditForm: React.FC<{
placeholder="请输入SKU"
rules={[{ required: true, message: '请输入SKU' }]}
/>
<ProForm.Item noStyle shouldUpdate>
{() => {
const productType = formRef.current?.getFieldValue('productType');
return (
productType && (
<Tag
style={{ marginTop: '32px' }}
color={productType === 'single' ? 'green' : 'orange'}
>
{productType === 'single' ? '单品' : '套装'}
</Tag>
)
);
}}
</ProForm.Item>
{stockStatus && (
<Tag
style={{ marginTop: '32px' }}
color={stockStatus === 'in-stock' ? 'green' : 'orange'}
>
{stockStatus === 'in-stock' ? '在库' : '未在库'}
</Tag>
)}
</ProForm.Group>
<ProForm.Group>
<ProFormText
@ -817,7 +828,7 @@ const EditForm: React.FC<{
/>
</ProForm.Group>
<ProFormSelect
name="productType"
name="type"
label="产品类型"
options={[
{ value: 'single', label: '单品' },
@ -825,6 +836,55 @@ const EditForm: React.FC<{
]}
rules={[{ required: true, message: '请选择产品类型' }]}
/>
<ProForm.Item
shouldUpdate={(prevValues: any, curValues: any) =>
prevValues.type !== curValues.type
}
noStyle
>
{({ getFieldValue }: { getFieldValue: (name: string) => any }) =>
getFieldValue('type') === 'bundle' ? (
<ProFormList
name="components"
label="组成项"
creatorButtonProps={{
position: 'bottom',
creatorButtonText: '新增组成项',
}}
itemRender={({ listDom, action }) => (
<div
style={{
marginBottom: 8,
display: 'flex',
flexDirection: 'row',
alignItems: 'end',
}}
>
{listDom}
{action}
</div>
)}
>
<ProForm.Group>
<ProFormText
name="sku"
label="库存SKU"
width="md"
placeholder="请输入库存SKU"
rules={[{ required: true, message: '请输入库存SKU' }]}
/>
<ProFormText
name="quantity"
label="数量"
width="md"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
/>
</ProForm.Group>
</ProFormList>
) : null
}
</ProForm.Item>
<ProFormTextArea
name="description"
label="描述"
@ -871,67 +931,6 @@ const EditForm: React.FC<{
/>
<AttributeFormItem dictName="size" name="sizeValues" label="尺寸" isTag />
<AttributeFormItem dictName="category" name="category" label="分类" />
<ProForm.Group title="自动绑定">
<Button
onClick={async () => {
await productcontrollerAutobindcomponents({ id: record.id });
const { data: componentsData } =
await productcontrollerGetproductcomponents({ id: record.id });
formRef.current?.setFieldsValue({ components: componentsData });
}}
>
Run
</Button>
</ProForm.Group>
<ProForm.Item
shouldUpdate={(prevValues: any, curValues: any) =>
prevValues.productType !== curValues.productType
}
noStyle
>
{({ getFieldValue }: { getFieldValue: (name: string) => any }) =>
getFieldValue('productType') === 'bundle' ? (
<ProFormList
name="components"
label="组成项"
creatorButtonProps={{
position: 'bottom',
creatorButtonText: '新增组成项',
}}
itemRender={({ listDom, action }) => (
<div
style={{
marginBottom: 8,
display: 'flex',
flexDirection: 'row',
alignItems: 'end',
}}
>
{listDom}
{action}
</div>
)}
>
<ProForm.Group>
<ProFormText
name="sku"
label="库存SKU"
width="md"
placeholder="请输入库存SKU"
rules={[{ required: true, message: '请输入库存SKU' }]}
/>
<ProFormText
name="quantity"
label="数量"
width="md"
placeholder="请输入数量"
rules={[{ required: true, message: '请输入数量' }]}
/>
</ProForm.Group>
</ProFormList>
) : null
}
</ProForm.Item>
</DrawerForm>
);
};

View File

@ -29,7 +29,7 @@ const ListPage: React.FC = () => {
},
{
title: 'SKU',
dataIndex: 'productSku',
dataIndex: 'sku',
hideInSearch: true,
},
...points
@ -88,13 +88,13 @@ const ListPage: React.FC = () => {
render(_, record) {
return (
<ProFormDigit
key={record.productSku}
key={record.sku}
initialValue={0}
fieldProps={{
onChange(value) {
setReal({
...real,
[record.productSku]: value,
[record.sku]: value,
});
},
}}
@ -107,7 +107,7 @@ const ListPage: React.FC = () => {
dataIndex: 'restockQuantityReal',
hideInSearch: true,
render(_, record) {
return <ProFormDigit key={'b_' + record.productSku} />;
return <ProFormDigit key={'b_' + record.sku} />;
},
},
{
@ -138,7 +138,7 @@ const ListPage: React.FC = () => {
render(_, record) {
if (!record.availableDays) return '-';
const availableDays = Number(record.availableDays);
const quantity = real?.[record.productSku] || 0;
const quantity = real?.[record.sku] || 0;
const day =
availableDays +
Math.floor(
@ -154,7 +154,7 @@ const ListPage: React.FC = () => {
render(_, record) {
if (!record.availableDays) return '-';
const availableDays = Number(record.availableDays);
const quantity = real?.[record.productSku] || 0;
const quantity = real?.[record.sku] || 0;
const day =
availableDays +
Math.floor(

View File

@ -96,14 +96,14 @@ const ListPage: React.FC = () => {
render(_, record) {
return (
<ProFormDigit
key={record.productSku}
key={record.sku}
width={100}
fieldProps={{
defaultValue: 0,
onChange(value) {
setSavety({
...savety,
[record.productSku]: value,
[record.sku]: value,
});
},
}}
@ -129,7 +129,7 @@ const ListPage: React.FC = () => {
hideInSearch: true,
render(_, record) {
const base = record.lastMonthSales;
return 3 * count * base + (savety[record.productSku] || 0);
return 3 * count * base + (savety[record.sku] || 0);
},
},
{
@ -139,10 +139,10 @@ const ListPage: React.FC = () => {
const base = record.lastMonthSales;
return (
<ProFormDigit
key={'fix' + record.productSku + (savety[record.productSku] || 0)}
key={'fix' + record.sku + (savety[record.sku] || 0)}
width={100}
fieldProps={{
defaultValue: 3 * count * base + (savety[record.productSku] || 0),
defaultValue: 3 * count * base + (savety[record.sku] || 0),
}}
/>
);

View File

@ -25,7 +25,7 @@ const ListPage: React.FC = () => {
const columns: ProColumns<API.StockDTO>[] = [
{
title: 'SKU',
dataIndex: 'productSku',
dataIndex: 'sku',
hideInSearch: true,
sorter: true,
},
@ -130,7 +130,7 @@ const ListPage: React.FC = () => {
);
return [
item.productName || '',
item.productSku || '',
item.sku || '',
...stockRow,
];
});

View File

@ -285,7 +285,7 @@ const CreateForm: React.FC<{
return [];
}
}}
name="productSku"
name="sku"
label={'产品' + (idx + 1)}
width="lg"
placeholder="请选择产品"
@ -347,9 +347,9 @@ const UpdateForm: React.FC<{
...values,
items: values?.items?.map((item: API.PurchaseOrderItem) => ({
...item,
productSku: {
sku: {
label: item.productName,
value: item.productSku,
value: item.sku,
},
})),
};
@ -466,7 +466,7 @@ const UpdateForm: React.FC<{
return [];
}
}}
name="productSku"
name="sku"
label="产品"
width="lg"
placeholder="请选择产品"
@ -530,9 +530,9 @@ const DetailForm: React.FC<{
...values,
items: values?.items?.map((item: API.PurchaseOrderItem) => ({
...item,
productSku: {
sku: {
label: item.productName,
value: item.productSku,
value: item.sku,
},
})),
};
@ -631,7 +631,7 @@ const DetailForm: React.FC<{
return [];
}
}}
name="productSku"
name="sku"
label="产品"
width="lg"
placeholder="请选择产品"

View File

@ -23,7 +23,7 @@ const ListPage: React.FC = () => {
},
{
title: 'SKU',
dataIndex: 'productSku',
dataIndex: 'sku',
hideInSearch: true,
},
{

View File

@ -283,11 +283,11 @@ const CreateForm: React.FC<{
});
form.setFieldsValue({
items: data?.map(
(item: { productName: string; productSku: string }) => ({
(item: { productName: string; sku: string }) => ({
...item,
productSku: {
sku: {
label: item.productName,
value: item.productSku,
value: item.sku,
},
}),
),
@ -343,7 +343,7 @@ const CreateForm: React.FC<{
return [];
}
}}
name="productSku"
name="sku"
label={'产品' + (idx + 1)}
width="lg"
placeholder="请选择产品"
@ -392,9 +392,9 @@ const UpdateForm: React.FC<{
...values,
items: values?.items?.map((item: API.PurchaseOrderItem) => ({
...item,
productSku: {
sku: {
label: item.productName,
value: item.productSku,
value: item.sku,
},
})),
};
@ -519,7 +519,7 @@ const UpdateForm: React.FC<{
return [];
}
}}
name="productSku"
name="sku"
label={'产品' + (idx + 1)}
width="lg"
placeholder="请选择产品"
@ -565,11 +565,11 @@ const DetailForm: React.FC<{
const initialValues = {
...values,
items: values?.items?.map(
(item: { productName: string; productSku: string }) => ({
(item: { productName: string; sku: string }) => ({
...item,
productSku: {
sku: {
label: item.productName,
value: item.productSku,
value: item.sku,
},
}),
),
@ -676,7 +676,7 @@ const DetailForm: React.FC<{
return [];
}
}}
name="productSku"
name="sku"
label="产品"
width="lg"
placeholder="请选择产品"

View File

@ -898,7 +898,7 @@ declare namespace API {
id?: number;
productId?: number;
/** 组件所关联的 SKU */
productSku?: string;
sku?: string;
/** 组成数量 */
quantity?: number;
/** 创建时间 */
@ -924,7 +924,7 @@ declare namespace API {
type PurchaseOrderItem = {
id?: number;
productSku?: string;
sku?: string;
productName?: string;
quantity?: number;
price?: number;
@ -1076,7 +1076,7 @@ declare namespace API {
productName?: string;
/** 按库存点ID排序 */
sortPointId?: number;
/** 排序对象,格式如 { productName: "asc", productSku: "desc" } */
/** 排序对象,格式如 { productName: "asc", sku: "desc" } */
order?: Record<string, any>;
};
@ -1086,7 +1086,7 @@ declare namespace API {
/** 每页大小 */
pageSize?: number;
stockPointId?: number;
productSku?: string;
sku?: string;
productName?: string;
operationType?: string;
startDate?: string;
@ -1328,7 +1328,7 @@ declare namespace API {
/** 每页大小 */
pageSize?: number;
stockPointId?: number;
productSku?: string;
sku?: string;
productName?: string;
operationType?: string;
startDate?: string;
@ -1343,7 +1343,7 @@ declare namespace API {
productName?: string;
/** 按库存点ID排序 */
sortPointId?: number;
/** 排序对象,格式如 { productName: "asc", productSku: "desc" } */
/** 排序对象,格式如 { productName: "asc", sku: "desc" } */
order?: Record<string, any>;
};
@ -1378,7 +1378,7 @@ declare namespace API {
type StockDTO = {
id?: number;
stockPointId?: number;
productSku?: string;
sku?: string;
quantity?: number;
/** 创建时间 */
createdAt: string;
@ -1461,7 +1461,7 @@ declare namespace API {
type StockRecordDTO = {
id?: number;
stockPointId?: number;
productSku?: string;
sku?: string;
operationType?: any;
quantityChange?: number;
operatorId?: number;
@ -1650,7 +1650,7 @@ declare namespace API {
type UpdateStockDTO = {
stockPointId?: number;
productSku?: string;
sku?: string;
quantityChange?: number;
operationType?: 'in' | 'out';
operatorId?: number;