From df5e53fd062f61a7c4cfe362f1078d6c8d188b19 Mon Sep 17 00:00:00 2001 From: mairuiming Date: Wed, 2 Jul 2025 11:46:27 +0800 Subject: [PATCH] 1 1 --- src/App.tsx | 743 ++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 553 insertions(+), 190 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index f713a95..f244e25 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,188 +3,455 @@ import { bitable, CurrencyCode, FieldType, ICurrencyField, ICurrencyFieldMeta } import { Card, Modal, Checkbox, message } from 'antd'; import './App.css'; -// 选项类型定义 -interface OptionGroupDef { - title: string; - options: string[]; - required: boolean; - level?: number; - parentOption?: string; - condition?: (checkedList: string[]) => boolean; - resetOn?: string[]; - multiple?: boolean; // 新增:是否支持多选,默认为 false(单选) +// 客户配置类型定义 +interface CustomerOptionGroup { + title: string; // 客户名称 + options: CustomerTagGroup[]; // 客户专属标签组 + isDefault?: boolean; // 是否为默认客户 } -// 选项分组配置 -const OPTION_GROUPS: OptionGroupDef[] = [ - // 第一层:品牌选择 +// 客户标签组类型定义 +interface CustomerTagGroup { + title: string; // 标签组标题 + options: string[]; // 标签选项 + required: boolean; // 是否必填 + level?: number; // 层级 + parentOption?: string; // 父选项 + condition?: (checkedList: string[]) => boolean; // 显示条件 + resetOn?: string[]; // 重置条件 + multiple?: boolean; // 是否支持多选 +} + +// 客户配置 - 按客户分组管理标签 +const CUSTOMER_CONFIG: CustomerOptionGroup[] = [ + // PDS 客户配置 { - title: '品牌', - options: ['PDS', 'LWH', 'PLT', 'RBE'], - required: true, - level: 1 + title: 'PDS', + options: [ + { + title: '单据类型', + options: ['首单', '翻单'], + required: true, + level: 2 + }, + { + title: '是否要打板', + options: ['需要打板', '不需要打板'], + required: false, + level: 3, + parentOption: '首单', + condition: (checkedList) => checkedList.includes('首单'), + resetOn: ['翻单'] + }, + { + title: '批色样', + options: ['寄成衣','寄色样'], + required: true, + level: 5, + parentOption: '加色', + condition: (checkedList) => checkedList.includes('加色'), + resetOn: ['首单', '无变动不需要修改', '需要打板', '不需要打板'] + }, + { + title: '批色样', + options: ['要批色样', '不要批色样'], + required: true, + level: 4, + parentOption: '不需要打板', + condition: (checkedList) => checkedList.includes('首单') && checkedList.includes('不需要打板'), + resetOn: ['翻单', '有变动需要修改', '无变动不需要修改'] + }, + { + title: '品类', + options: ['牛仔', '时装'], + required: true + }, + { + title: '复杂度', + options: ['简单款', '基础款', '复杂款'], + required: true + }, + { + title: '二次工艺', + options: ['绣花', '印花'], + required: false + }, + { + title: '是否需要批船样', + options: ['不需要批船样', '需要批船样'], + required: true + }, + { + title: '运输方式', + options: ['美国', '澳大利亚', '英国'], + required: false, + resetOn: ['PLT', 'RBE'] + }, + { + title: '英国运输方式', + options: [ + '英国-海运', + '英国-空运 (直飞)', + '英国-空运 (转机)', + '英国-铁路(中欧班列)', + '英国-卡航', + '英国-卡空', + '英国-卡车联运', + '英国-海空联运' + ], + required: false, + level: 2, + parentOption: '英国', + condition: (checkedList) => checkedList.includes('英国'), + resetOn: ['美国', '澳大利亚', 'PLT', 'RBE'] + }, + { + title: '美国运输方式', + options: [ + '美国-海运慢船', + '美国-海运快船', + '美国-空运(直飞)' + ], + required: true, + level: 2, + parentOption: '美国', + condition: (checkedList) => checkedList.includes('美国'), + resetOn: ['英国', '澳大利亚', 'PLT', 'RBE'] + }, + { + title: '澳大利亚运输方式', + options: [ + '澳大利亚-海运', + '澳大利亚-空运(直飞)' + ], + required: true, + level: 2, + parentOption: '澳大利亚', + condition: (checkedList) => checkedList.includes('澳大利亚'), + resetOn: ['美国', '英国', 'PLT', 'RBE'] + }, + { + title: '面料特性', + options: [ + '普通面料(纯棉、常规化纤)', + '特殊面料(真丝、皮革、功能性面料)', + '易损面料(薄纱、蕾丝)' + ], + required: false + } + ] }, - // PDS和LWH共用的标签树 + // LWH 客户配置 { - title: '单据类型', - options: ['首单', '翻单'], - required: true, - level: 2, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH'), - resetOn: ['PLT', 'RBE'] - }, - { - title: '是否要打板', - options: ['需要打板', '不需要打板'], - required: false, - level: 3, - parentOption: '首单', - condition: (checkedList) => (checkedList.includes('PDS')) && checkedList.includes('首单'), - resetOn: ['翻单', 'PLT', 'RBE'] - }, - { - title: '打板类型(多选)', - options: ['复版', 'PP版','不用打版'], - required: false, - level: 3, - parentOption: '首单', - multiple: true, - condition: (checkedList) => (checkedList.includes('LWH')) && checkedList.includes('首单'), - resetOn: ['翻单', 'PLT', 'RBE'] - }, - { - title: '翻单变动', - options: ['无变动不需要修改', '有变动需要修改'], - required: false, - level: 3, - parentOption: '翻单', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('翻单'), - resetOn: ['首单', 'PLT', 'RBE'] - }, - { - title: '特殊订单', - options: ['换料寄面料样', '换料重新打板', '加色', '改尺寸重新打板'], - required: false, - level: 4, - parentOption: '有变动需要修改', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('有变动需要修改'), - resetOn: ['首单', '无变动不需要修改', 'PLT', 'RBE'] - }, - { - title: '特殊订单', - options: ['批大货布'], - required: false, - level: 4, - parentOption: '无变动不需要修改', - condition: (checkedList) => (checkedList.includes('LWH')) && checkedList.includes('无变动不需要修改'), - resetOn: ['首单', '有变动需要修改', 'PLT', 'RBE'] - }, - { - title: '批色样', - options: ['寄成衣','寄色样'], - required: true, - level: 5, - parentOption: '加色', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('加色'), - resetOn: ['首单', '无变动不需要修改', '需要打板', '不需要打板', 'PLT', 'RBE'] - }, - { - title: '批色样', - options: ['要批色样', '不要批色样'], - required: true, - level: 4, - parentOption: '不需要打板', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('首单') && checkedList.includes('不需要打板'), - resetOn: ['翻单', '有变动需要修改', '无变动不需要修改', 'PLT', 'RBE'] - }, - { - title: '品类', - options: ['牛仔', '时装'], - required: true, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH') - }, - { - title: '复杂度', - options: ['简单款', '基础款', '复杂款'], - required: true, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH') - }, - { - title: '二次工艺', - options: ['绣花', '印花'], - required: false, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH') - }, - { - title: '是否需要批船样', - options: ['不需要批船样', '需要批船样'], - required: true, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH') - }, - { - title: '运输方式', - options: ['美国', '澳大利亚', '英国'], - required: false, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH'), - resetOn: ['PLT', 'RBE'] - }, - { - title: '英国运输方式', + title: 'LWH', options: [ - '英国-海运', - '英国-空运 (直飞)', - '英国-空运 (转机)', - '英国-铁路(中欧班列)', - '英国-卡航', - '英国-卡空', - '英国-卡车联运', - '英国-海空联运' - ], - required: false, - level: 2, - parentOption: '英国', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('英国'), - resetOn: ['美国', '澳大利亚', 'PLT', 'RBE'] + { + title: '单据类型', + options: ['首单', '翻单'], + required: true, + level: 2 + }, + { + title: '打板类型(多选)', + options: ['复版', 'PP版','不用打版'], + required: false, + level: 3, + parentOption: '首单', + multiple: true, + condition: (checkedList) => checkedList.includes('首单'), + resetOn: ['翻单'] + }, + { + title: '翻单变动', + options: ['无变动不需要修改', '有变动需要修改'], + required: false, + level: 3, + parentOption: '翻单', + condition: (checkedList) => checkedList.includes('翻单'), + resetOn: ['首单'] + }, + { + title: '特殊订单', + options: ['换料寄面料样', '换料重新打板', '加色', '改尺寸重新打板','改尺寸不打版'], + required: false, + level: 4, + parentOption: '有变动需要修改', + condition: (checkedList) => checkedList.includes('有变动需要修改'), + resetOn: ['首单', '无变动不需要修改'] + }, + { + title: '特殊订单', + options: ['批大货布'], + required: false, + level: 4, + parentOption: '无变动不需要修改', + condition: (checkedList) => checkedList.includes('无变动不需要修改'), + resetOn: ['首单', '有变动需要修改'] + }, + { + title: '批色样', + options: ['寄成衣','寄色样'], + required: true, + level: 5, + parentOption: '加色', + condition: (checkedList) => checkedList.includes('加色'), + resetOn: ['首单', '无变动不需要修改', '需要打板', '不需要打板'] + }, + { + title: '品类', + options: ['牛仔', '时装'], + required: true + }, + { + title: '复杂度', + options: ['简单款', '基础款', '复杂款'], + required: true + }, + { + title: '二次工艺', + options: ['绣花', '印花'], + required: false + }, + { + title: '是否需要批船样', + options: ['不需要批船样', '需要批船样'], + required: true + }, + { + title: '运输方式', + options: ['美国', '澳大利亚', '英国'], + required: false, + resetOn: ['PLT', 'RBE'] + }, + { + title: '英国运输方式', + options: [ + '英国-海运', + '英国-空运 (直飞)', + '英国-空运 (转机)', + '英国-铁路(中欧班列)', + '英国-卡航', + '英国-卡空', + '英国-卡车联运', + '英国-海空联运' + ], + required: false, + level: 2, + parentOption: '英国', + condition: (checkedList) => checkedList.includes('英国'), + resetOn: ['美国', '澳大利亚', 'PLT', 'RBE'] + }, + { + title: '美国运输方式', + options: [ + '美国-海运慢船', + '美国-海运快船', + '美国-空运(直飞)' + ], + required: true, + level: 2, + parentOption: '美国', + condition: (checkedList) => checkedList.includes('美国'), + resetOn: ['英国', '澳大利亚', 'PLT', 'RBE'] + }, + { + title: '澳大利亚运输方式', + options: [ + '澳大利亚-海运', + '澳大利亚-空运(直飞)' + ], + required: true, + level: 2, + parentOption: '澳大利亚', + condition: (checkedList) => checkedList.includes('澳大利亚'), + resetOn: ['美国', '英国', 'PLT', 'RBE'] + }, + { + title: '面料特性', + options: [ + '普通面料(纯棉、常规化纤)', + '特殊面料(真丝、皮革、功能性面料)', + '易损面料(薄纱、蕾丝)' + ], + required: false + } + ] }, + + // PLT 客户配置 { - title: '美国运输方式', + title: 'PLT', options: [ - '美国-海运慢船', - '美国-海运快船', - '美国-空运(直飞)' - ], - required: true, - level: 2, - parentOption: '美国', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('美国'), - resetOn: ['英国', '澳大利亚', 'PLT', 'RBE'] + { + title: '单据类型', + options: ['首单', '翻单'], + required: true, + level: 2 + }, + { + title: '打板类型(多选)', + options: ['复版', '拍照版','不用打版'], + required: false, + level: 3, + parentOption: '首单', + multiple: true, + condition: (checkedList) => checkedList.includes('首单'), + resetOn: ['翻单'] + }, + { + title: '寄样方式', + options: ['寄裤筒', '寄成衣'], + required: false, + level: 4, + parentOption: '不用打版', + condition: (checkedList) => checkedList.includes('首单') && checkedList.includes('不用打版'), + resetOn: ['翻单'] + }, + { + title: '翻单变动', + options: ['无变动不需要修改', '有变动需要修改'], + required: false, + level: 3, + parentOption: '翻单', + condition: (checkedList) => checkedList.includes('翻单'), + resetOn: ['首单'] + }, + { + title: '特殊订单', + options: ['换料寄面料样', '换料重新打板', '改尺寸重新打板','改尺寸不打版'], + required: false, + level: 4, + parentOption: '有变动需要修改', + condition: (checkedList) => checkedList.includes('有变动需要修改'), + resetOn: ['首单', '无变动不需要修改'] + }, + { + title: '打版类型', + options: ['复版','拍照版'], + required: false, + level: 5, + parentOption: '换料重新打板', + condition: (checkedList) => checkedList.includes('换料重新打板'), + resetOn: ['首单', '无变动不需要修改','换料重新打板'] + }, + { + title: '打版类型', + options: ['复版','拍照版'], + required: false, + level: 5, + parentOption: '改尺寸重新打板', + condition: (checkedList) => checkedList.includes('改尺寸重新打板'), + resetOn: ['首单', '无变动不需要修改','换料重新打板'] + }, + { + title: '特殊订单', + options: ['批大货布'], + required: false, + level: 4, + parentOption: '无变动不需要修改', + condition: (checkedList) => checkedList.includes('无变动不需要修改'), + resetOn: ['首单', '有变动需要修改'] + }, + { + title: '品类', + options: ['牛仔', '时装'], + required: true + }, + { + title: '复杂度', + options: ['简单款', '基础款', '复杂款'], + required: true + }, + { + title: '二次工艺', + options: ['绣花', '印花'], + required: false + }, + { + title: '是否需要批船样', + options: ['不需要批船样', '需要批船样'], + required: true + }, + { + title: '运输方式', + options: ['美国', '澳大利亚', '英国'], + required: false, + resetOn: ['RBE'] + }, + { + title: '英国运输方式', + options: [ + '英国-海运', + '英国-空运 (直飞)', + '英国-空运 (转机)', + '英国-铁路(中欧班列)', + '英国-卡航', + '英国-卡空', + '英国-卡车联运', + '英国-海空联运' + ], + required: false, + level: 2, + parentOption: '英国', + condition: (checkedList) => checkedList.includes('英国'), + resetOn: ['美国', '澳大利亚', 'RBE'] + }, + { + title: '美国运输方式', + options: [ + '美国-海运慢船', + '美国-海运快船', + '美国-空运(直飞)' + ], + required: true, + level: 2, + parentOption: '美国', + condition: (checkedList) => checkedList.includes('美国'), + resetOn: ['英国', '澳大利亚', 'RBE'] + }, + { + title: '澳大利亚运输方式', + options: [ + '澳大利亚-海运', + '澳大利亚-空运(直飞)' + ], + required: true, + level: 2, + parentOption: '澳大利亚', + condition: (checkedList) => checkedList.includes('澳大利亚'), + resetOn: ['美国', '英国', 'RBE'] + }, + { + title: '面料特性', + options: [ + '普通面料(纯棉、常规化纤)', + '特殊面料(真丝、皮革、功能性面料)', + '易损面料(薄纱、蕾丝)' + ], + required: false + } + ] }, + + // RBE 客户配置 - 简化示例 { - title: '澳大利亚运输方式', + title: 'RBE', options: [ - '澳大利亚-海运', - '澳大利亚-空运(直飞)' - ], - required: true, - level: 2, - parentOption: '澳大利亚', - condition: (checkedList) => (checkedList.includes('PDS') || checkedList.includes('LWH')) && checkedList.includes('澳大利亚'), - resetOn: ['美国', '英国', 'PLT', 'RBE'] - }, - { - title: '面料特性', - options: [ - '普通面料(纯棉、常规化纤)', - '特殊面料(真丝、皮革、功能性面料)', - '易损面料(薄纱、蕾丝)' - ], - required: false, - condition: (checkedList) => checkedList.includes('PDS') || checkedList.includes('LWH') + { + title: '特殊订单类型', + options: ['紧急订单', '常规订单'], + required: true, + level: 2 + }, + { + title: '运输优先级', + options: ['标准运输', '加急运输', '特快运输'], + required: true, + level: 3 + } + ] } - - // HELLOMOLLY和RBE品牌的标签树仍然为空 - // 后续可根据需要添加专用标签 ]; const FABRIC_TEST_OPTIONS = ['需要面料测试', '不需要面料测试']; @@ -205,8 +472,9 @@ const createOptionSets = (checkedList: string[]) => { // 优化:使用memo包装OptionGroup组件 interface OptionGroupProps { - group: OptionGroupDef; + group: CustomerTagGroup; checkedList: string[]; + customer: string; onChange: (newList: string[]) => void; lockedOptions?: string[]; level?: number; @@ -215,6 +483,7 @@ interface OptionGroupProps { const OptionGroup = memo(({ group, checkedList, + customer, onChange, lockedOptions = [], level = 1 @@ -281,11 +550,45 @@ const OptionGroup = memo(({ ); }); +// 客户选择器组件 - 添加变更时清空选项的功能 +const CustomerSelector = memo(({ customers, selectedCustomer, onChange, onCustomerChange }) => { + return ( +
+
选择客户:
+
+ {customers.map(customer => ( + + ))} +
+
+ ); +}); + // 优化:使用memo包装OrderConfigSelector组件 interface OrderConfigSelectorProps { selectedRecordId: string | null; checkedList: string[]; setCheckedList: (list: string[]) => void; + selectedCustomer: string; + setSelectedCustomer: (customer: string) => void; onSubmit: (options: string[]) => void; onCancel: () => void; loading: boolean; @@ -295,32 +598,54 @@ const OrderConfigSelector = memo(({ selectedRecordId, checkedList, setCheckedList, + selectedCustomer, + setSelectedCustomer, onSubmit, onCancel, loading }) => { + // 查找当前选中客户的配置 + const customerConfig = useMemo(() => + CUSTOMER_CONFIG.find(c => c.title === selectedCustomer) || CUSTOMER_CONFIG[0], + [selectedCustomer] + ); + // 优化:使用useMemo缓存可见的选项组 const visibleGroups = useMemo(() => { - return OPTION_GROUPS.filter(group => { - if (!group.condition) return true; + if (!customerConfig) return []; + + // 筛选出可见的选项组 + return customerConfig.options.filter(group => { + // 如果没有定义显示条件,默认为可见 + if (!group.condition) { + return true; + } + + // 有显示条件的,检查条件是否满足 return group.condition(checkedList); }); - }, [checkedList]); + }, [checkedList, customerConfig]); + + // 当客户变更时清空选项 + const handleCustomerChange = useCallback((newCustomer: string) => { + console.log(`客户变更为: ${newCustomer},清空当前选项`); + setCheckedList([]); + }, [setCheckedList]); // 优化:使用useCallback缓存事件处理函数 const handleCheckedListChange = useCallback((newList: string[]) => { const addedOptions = newList.filter(opt => !checkedList.includes(opt)); if (addedOptions.length > 0) { - const resetGroups = OPTION_GROUPS.filter(group => + const resetGroups = customerConfig?.options.filter(group => group.resetOn?.some(resetOpt => addedOptions.includes(resetOpt)) - ); + ) || []; if (resetGroups.length > 0) { const resetGroupsSet = new Set(resetGroups); const filteredOptions = newList.filter(opt => { - const group = OPTION_GROUPS.find(g => g.options.includes(opt)); - return !resetGroupsSet.has(group as OptionGroupDef); + const group = customerConfig?.options.find(g => g.options.includes(opt)); + return !(group && resetGroupsSet.has(group)); }); setCheckedList(filteredOptions); return; @@ -328,12 +653,18 @@ const OrderConfigSelector = memo(({ } setCheckedList(newList); - }, [checkedList, setCheckedList]); + }, [checkedList, setCheckedList, customerConfig]); // 优化:使用useCallback缓存验证函数 const validateRequired = useCallback(() => { - for (const group of OPTION_GROUPS) { - if (group.required && group.condition?.(checkedList) !== false) { + if (!customerConfig) { + message.error('请选择客户'); + return false; + } + + // 验证可见的必填项 + for (const group of visibleGroups) { + if (group.required) { const has = checkedList.some(v => group.options.includes(v)); if (!has) { message.error(`请至少选择一项【${group.title}】`); @@ -352,7 +683,7 @@ const OrderConfigSelector = memo(({ } return true; - }, [checkedList]); + }, [checkedList, customerConfig, visibleGroups]); const needFabricTestDialog = useCallback(() => { return !(checkedList.includes('翻单') && checkedList.includes('无变动不需要修改')); @@ -416,16 +747,30 @@ const OrderConfigSelector = memo(({ okText="确定" cancelText="取消" confirmLoading={loading} + width={768} > - {visibleGroups.map(group => ( - - ))} + + + {/* 只有选择了客户才显示标签组 */} + {selectedCustomer && customerConfig && ( +
+ {visibleGroups.map(group => ( + + ))} +
+ )} { recordId: string | null; }>({ tableId: null, recordId: null }); + // 新增:当前选中的客户 + const [selectedCustomer, setSelectedCustomer] = useState(null); + // 优化:缓存字段选项映射,避免重复查找 const [fieldOptionsMap, setFieldOptionsMap] = useState>(new Map()); @@ -467,6 +815,7 @@ const App: React.FC = () => { const resetOptions = useCallback(() => { setSelectedRecordId(null); setCheckedList([]); + setSelectedCustomer(null); // 重置时也重置客户选择 }, []); const saveOptions = useCallback(async () => { @@ -475,6 +824,11 @@ const App: React.FC = () => { return; } + if (!selectedCustomer) { + message.error('请选择客户'); + return; + } + setLoading(true); const FIELD_ID_TO_SAVE = 'fldTtRHwlo'; @@ -551,7 +905,7 @@ const App: React.FC = () => { resetOptions(); setCurrentSelection({ tableId: null, recordId: null }); } - }, [selectedRecordId, currentSelection.tableId, checkedList, fieldOptionsMap, resetOptions]); + }, [selectedRecordId, currentSelection.tableId, checkedList, fieldOptionsMap, resetOptions, selectedCustomer]); useEffect(() => { const unsubscribe = bitable.base.onSelectionChange(async (event: any) => { @@ -584,6 +938,13 @@ const App: React.FC = () => { } else { setCheckedList([]); } + + // 尝试从选中的选项中推断客户 + const firstOption = checkedList[0]; + const customer = CUSTOMER_CONFIG.find(c => c.options.some(g => g.options.includes(firstOption))); + if (customer) { + setSelectedCustomer(customer.title); + } } } catch (e: any) { message.error('获取选中记录失败: ' + (e.message || e)); @@ -602,6 +963,8 @@ const App: React.FC = () => { selectedRecordId={selectedRecordId} checkedList={checkedList} setCheckedList={setCheckedList} + selectedCustomer={selectedCustomer || ''} + setSelectedCustomer={setSelectedCustomer} onSubmit={saveOptions} onCancel={resetOptions} loading={loading}