From 2d22bd47d52d575f0b62e8bb348381a854ff8868 Mon Sep 17 00:00:00 2001 From: mike Date: Fri, 7 Aug 2026 17:04:38 +0800 Subject: [PATCH] Update App.jsx via upload script - 2026-08-07 17:04:16 --- App.jsx | 48 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/App.jsx b/App.jsx index 446f01d..f93463e 100644 --- a/App.jsx +++ b/App.jsx @@ -458,6 +458,25 @@ async function resolveExportTranslations(terms, lang) { // 把某个产品需要展示的规格行整理出来(和ProductDetail的powerInfoItems逻辑对齐,但拆分出 // 独立的label/value结构,方便多语言渲染时分别处理"字段名要翻译"和"数值一般不用翻译") +// 把AI识别到但没有具名字段的参数(extraSpecs)插入到已经组装好的规格行列表里——如果这一条 +// 标注了afterLabel(应该跟在哪个已知字段后面显示),就插到那个字段紧后面;找不到匹配的就 +// 兜底追加到列表最后,不会丢数据,只是位置不够准确。labelProp传'labelKey'(productExportRows +// 用)或'label'(powerInfoItems用),因为两边字段名不一样。 +function insertExtraSpecs(list, extraSpecs, labelProp) { + (extraSpecs || []).forEach((item, i) => { + if (!item || !item.label || !item.value) return; + const entry = labelProp === 'labelKey' + ? { labelKey: item.label, value: item.value } + : { key: 'extra_' + i + '_' + item.label, label: item.label, value: item.value }; + if (item.afterLabel) { + const idx = list.findIndex(r => r[labelProp] === item.afterLabel); + if (idx !== -1) { list.splice(idx + 1, 0, entry); return; } + } + list.push(entry); + }); + return list; +} + function productExportRows(p, categories) { const cat = (categories || []).find(c => c.id === p.category); const rows = []; @@ -600,9 +619,7 @@ function productExportRows(p, categories) { if (p.container20ft) rows.push({ labelKey: '20尺柜装箱数量', value: p.container20ft }); if (p.container40ft) rows.push({ labelKey: '40尺柜装箱数量', value: p.container40ft }); if (p.container40hq) rows.push({ labelKey: '40高柜装箱数量', value: p.container40hq }); - (p.extraSpecs || []).forEach(item => { - if (item && item.label && item.value) rows.push({ labelKey: item.label, value: item.value }); - }); + insertExtraSpecs(rows, p.extraSpecs, 'labelKey'); return rows; } @@ -847,7 +864,7 @@ 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, i) => { if (item && item.label && item.value) items.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(items, p.extraSpecs, 'label'); return items; } if (isBatteryCategory(cat) && p.type === 'UPS配套锂电池系统') { @@ -874,7 +891,7 @@ 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, i) => { if (item && item.label && item.value) items.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(items, p.extraSpecs, 'label'); return items; } if (isUpsCategory(cat) && (p.type === '离线式UPS' || p.type === '在线互动式UPS')) { @@ -905,7 +922,7 @@ function powerInfoItems(p, categories) { if (p.container20ft) items.push({ key: 'container20', label: '20尺柜装箱数量', value: p.container20ft }); if (p.container40ft) items.push({ key: 'container40', label: '40尺柜装箱数量', value: p.container40ft }); if (p.container40hq) items.push({ key: 'container40hq', label: '40高柜装箱数量', value: p.container40hq }); - (p.extraSpecs || []).forEach((item, i) => { if (item && item.label && item.value) items.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(items, p.extraSpecs, 'label'); return items; } if (isUpsCategory(cat) && (p.type === '机架式UPS' || p.type === '在线式高频UPS')) { @@ -945,7 +962,7 @@ function powerInfoItems(p, categories) { if (p.container20ft) items.push({ key: 'container20', label: '20尺柜装箱数量', value: p.container20ft }); if (p.container40ft) items.push({ key: 'container40', label: '40尺柜装箱数量', value: p.container40ft }); if (p.container40hq) items.push({ key: 'container40hq', label: '40高柜装箱数量', value: p.container40hq }); - (p.extraSpecs || []).forEach((item, i) => { if (item && item.label && item.value) items.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(items, p.extraSpecs, 'label'); return items; } if (isUpsCategory(cat) && p.type !== '迷你UPS') { @@ -955,7 +972,7 @@ function powerInfoItems(p, categories) { { key: 'pf', label: '功率因数', value: p.powerFactor || '—' }, { key: 'maxkw', label: '最大功率', value: maxKW !== null ? `${maxKW} kW` : '—' }, ]; - (p.extraSpecs || []).forEach((item, i) => { if (item && item.label && item.value) rackFallbackItems.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(rackFallbackItems, p.extraSpecs, 'label'); return rackFallbackItems; } if (isUpsCategory(cat) && p.type === '迷你UPS') { @@ -975,11 +992,11 @@ function powerInfoItems(p, categories) { if (p.container20ft) items.push({ key: 'container20', label: '20尺柜装箱数量', value: p.container20ft }); if (p.container40ft) items.push({ key: 'container40', label: '40尺柜装箱数量', value: p.container40ft }); if (p.container40hq) items.push({ key: 'container40hq', label: '40高柜装箱数量', value: p.container40hq }); - (p.extraSpecs || []).forEach((item, i) => { if (item && item.label && item.value) items.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(items, p.extraSpecs, 'label'); return items; } const fallbackItems = [{ key: 'power', label: '功率 / 容量', value: p.powerOrCapacity || '—' }]; - (p.extraSpecs || []).forEach((item, i) => { if (item && item.label && item.value) fallbackItems.push({ key: 'extra_' + i, label: item.label, value: item.value }); }); + insertExtraSpecs(fallbackItems, p.extraSpecs, 'label'); return fallbackItems; } @@ -5098,6 +5115,15 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage, set({ extraSpecs: next }); }} /> + { + const next = (draft.extraSpecs || []).slice(); + next[idx] = { ...next[idx], afterLabel: e.target.value }; + set({ extraSpecs: next }); + }} + />