diff --git a/App.jsx b/App.jsx index 0320461..4423f10 100644 --- a/App.jsx +++ b/App.jsx @@ -592,6 +592,11 @@ function productExportRows(p, categories) { if (p.powerOrCapacity) rows.push({ labelKey: '功率 / 容量', value: p.powerOrCapacity }); if (p.voltage) rows.push({ labelKey: '电压', value: p.voltage }); } + // 通用兜底:不属于上面任何固定字段的"其他参数"(AI识别原文时发现的、schema里没有对应字段的 + // 参数),不管品类都追加在最后,保证原文规格表里的信息不会因为不在预定义字段列表里而丢失 + (p.extraSpecs || []).forEach(item => { + if (item && item.label && item.value) rows.push({ labelKey: item.label, value: item.value }); + }); return rows; } @@ -773,6 +778,9 @@ const blankProduct = () => ({ netWeight: '', // 净重(kg)(迷你UPS/离线式/在线互动式UPS共用) productImageFileName: '', productImageOriginalName: '', // 产品主图,导出多语言PDF时展示 sellingPoints: '', // 对客卖点/主要特点,每行一条,专门给客户看的(和下面的costPrice/notes内部信息彻底分开,不会一起导出) + extraSpecs: [], // 不在上面固定字段列表里的"其他参数",如 [{label:'防雷等级', value:'Type II'}]; + // AI批量导入时用来兜底承接原文规格表里有、但当前schema没有对应字段的参数, + // 保证不会因为字段没预定义就丢信息;也支持手动在产品详情页里增删 costPrice: '', notes: '', }); @@ -833,6 +841,9 @@ function powerInfoItems(p, categories) { if (p.safetyStandard) items.push({ key: 'safetystd', label: '安规/EMC标准', value: p.safetyStandard }); if (p.gridStandard) items.push({ key: 'gridstd', label: '并网标准', value: p.gridStandard }); if (p.otherStandard) items.push({ key: 'otherstd', label: '其他标准', value: p.otherStandard }); + (p.extraSpecs || []).forEach((item, idx) => { + if (item && item.label && item.value) items.push({ key: 'extraspec' + idx, label: item.label, value: item.value }); + }); return items; } if (isBatteryCategory(cat) && p.type === 'UPS配套锂电池系统') { @@ -859,6 +870,9 @@ function powerInfoItems(p, categories) { if (p.cabinetWeight) items.push({ key: 'cabinetweight', label: '系统柜重量(kg)', value: p.cabinetWeight }); if (p.altitude) items.push({ key: 'altitude', label: '海拔(m)', value: p.altitude }); if (p.selfDischargeRate) items.push({ key: 'selfdischarge', label: '自放电率', value: p.selfDischargeRate }); + (p.extraSpecs || []).forEach((item, idx) => { + if (item && item.label && item.value) items.push({ key: 'extraspec' + idx, label: item.label, value: item.value }); + }); return items; } if (isUpsCategory(cat) && (p.type === '离线式UPS' || p.type === '在线互动式UPS')) { @@ -885,6 +899,9 @@ function powerInfoItems(p, categories) { if (p.noiseLevel) items.push({ key: 'noiselevel', label: '噪音', value: p.noiseLevel }); if (p.dimensions) items.push({ key: 'dim', label: '尺寸(mm)', value: p.dimensions }); if (p.netWeight) items.push({ key: 'weight', label: '净重(kg)', value: p.netWeight }); + (p.extraSpecs || []).forEach((item, idx) => { + if (item && item.label && item.value) items.push({ key: 'extraspec' + idx, label: item.label, value: item.value }); + }); return items; } if (isUpsCategory(cat) && (p.type === '机架式UPS' || p.type === '在线式高频UPS')) { @@ -920,6 +937,9 @@ function powerInfoItems(p, categories) { if (p.noiseLevel) items.push({ key: 'noiselevel', label: '噪音', value: p.noiseLevel }); if (p.interfacePort) items.push({ key: 'interfaceport', label: '控制管理', value: p.interfacePort }); if (p.optionalSnmp) items.push({ key: 'snmp', label: '可选SNMP', value: p.optionalSnmp }); + (p.extraSpecs || []).forEach((item, idx) => { + if (item && item.label && item.value) items.push({ key: 'extraspec' + idx, label: item.label, value: item.value }); + }); return items; } if (isUpsCategory(cat) && p.type !== '迷你UPS') { @@ -943,6 +963,9 @@ function powerInfoItems(p, categories) { if (p.batterySpec) items.push({ key: 'battery', label: '电池数量和容量', value: p.batterySpec }); if (p.dimensions) items.push({ key: 'dim', label: '尺寸(mm)', value: p.dimensions }); if (p.netWeight) items.push({ key: 'weight', label: '净重(kg)', value: p.netWeight }); + (p.extraSpecs || []).forEach((item, idx) => { + if (item && item.label && item.value) items.push({ key: 'extraspec' + idx, label: item.label, value: item.value }); + }); return items; } return [{ key: 'power', label: '功率 / 容量', value: p.powerOrCapacity || '—' }]; @@ -2532,6 +2555,9 @@ function MainApp({ username, onLogout }) { otherStandard: p.otherStandard || '', sellingPoints: p.sellingPoints || '', // AI如果在原文里认出了营销卖点/主要特点,会自动填这里 batterySpec: p.batterySpec || '', dimensions: p.dimensions || '', netWeight: p.netWeight || '', notes: p.notes || '', + extraSpecs: Array.isArray(p.extraSpecs) + ? p.extraSpecs.filter(it => it && (it.label || it.value)).map(it => ({ label: it.label || '', value: it.value || '' })) + : [], // 不在固定schema里的"其他参数",原文有什么就带什么,型号之间可以完全不一样 })); setAiImportDrafts(drafts); } catch (e) { @@ -2609,6 +2635,7 @@ function MainApp({ username, onLogout }) { otherStandard: d.otherStandard || '', sellingPoints: d.sellingPoints || '', batterySpec: d.batterySpec || '', dimensions: d.dimensions || '', netWeight: d.netWeight || '', notes: d.notes || '', + extraSpecs: Array.isArray(d.extraSpecs) ? d.extraSpecs.filter(it => it && (it.label || it.value)) : [], }; } function confirmAiImport() { @@ -3926,6 +3953,7 @@ function MainApp({ username, onLogout }) { d.netWeight && `净重:${d.netWeight}`, (d.outputPortTypes && d.outputPortTypes.length) ? `输出口:${d.outputPortTypes.join('/')}` : '', d.sellingPoints ? `✓已识别对客卖点(${d.sellingPoints.split('\n').filter(Boolean).length}条)` : '', + (d.extraSpecs && d.extraSpecs.length) ? `✓其他参数(${d.extraSpecs.length}项:${d.extraSpecs.map(it => it.label).filter(Boolean).join('、')})` : '', ].filter(Boolean).join(' · ') || '(无更多规格信息)'} @@ -4629,6 +4657,10 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage, function addExtraName() { set({ extraNames: [...extraNames, ''] }); } function updateExtraName(idx, val) { const arr = [...extraNames]; arr[idx] = val; set({ extraNames: arr }); } function removeExtraName(idx) { set({ extraNames: extraNames.filter((_, i) => i !== idx) }); } + const extraSpecs = draft.extraSpecs || []; + function addExtraSpec() { set({ extraSpecs: [...extraSpecs, { label: '', value: '' }] }); } + function updateExtraSpec(idx, patch) { set({ extraSpecs: extraSpecs.map((it, i) => (i === idx ? { ...it, ...patch } : it)) }); } + function removeExtraSpec(idx) { set({ extraSpecs: extraSpecs.filter((_, i) => i !== idx) }); } function toggleOutputPortType(t) { const list = draft.outputPortTypes || []; if (list.includes(t)) { @@ -5069,6 +5101,18 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage, /> +
+ 其他参数(可选——原文规格表里有、但上面没有专属字段的参数,AI批量导入时会自动补充在这里,也可以手动增删;会一起显示在产品详情和多语言PDF导出里) + {extraSpecs.map((item, idx) => ( +
+ updateExtraSpec(idx, { label: e.target.value })} placeholder="参数名,如:防雷等级" /> + updateExtraSpec(idx, { value: e.target.value })} placeholder="参数值,如:Type II" /> + +
+ ))} + +
+
正本价格(元) set({ costPrice: e.target.value })} placeholder="采购/成本价,人民币" />
内部备注(仅自己可见,不会出现在任何导出的文档里)