diff --git a/App.jsx b/App.jsx index dafa293..c4123d9 100644 --- a/App.jsx +++ b/App.jsx @@ -318,6 +318,10 @@ const TRANSLATION_DICTIONARY = { '控制管理': { en: 'Interface', fr: 'Interface', ru: 'Интерфейс', es: 'Interfaz', ar: 'الواجهة' }, '湿度': { en: 'Humidity', fr: 'Humidité', ru: 'Влажность', es: 'Humedad', ar: 'الرطوبة' }, '噪音': { en: 'Noise Level', fr: 'Niveau sonore', ru: 'Уровень шума', es: 'Nivel de ruido', ar: 'مستوى الضوضاء' }, + '应用场景': { en: 'Application', fr: 'Application', ru: 'Применение', es: 'Aplicación', ar: 'التطبيق' }, + '20尺柜装箱数量': { en: '20ft Container Qty', fr: 'Qté conteneur 20 pieds', ru: 'Кол-во в 20-фут контейнере', es: 'Cant. contenedor 20 pies', ar: 'الكمية في حاوية 20 قدم' }, + '40尺柜装箱数量': { en: '40ft Container Qty', fr: 'Qté conteneur 40 pieds', ru: 'Кол-во в 40-фут контейнере', es: 'Cant. contenedor 40 pies', ar: 'الكمية في حاوية 40 قدم' }, + '40高柜装箱数量': { en: '40HQ Container Qty', fr: 'Qté conteneur 40HQ', ru: 'Кол-во в контейнере 40HQ', es: 'Cant. contenedor 40HQ', ar: 'الكمية في حاوية 40HQ' }, '主要特点': { en: 'Main Features', fr: 'Caractéristiques principales', ru: 'Основные характеристики', es: 'Características principales', ar: 'الميزات الرئيسية' }, '相数': { en: 'Phase', fr: 'Phase', ru: 'Фаза', es: 'Fase', ar: 'الطور' }, '输入功率因数': { en: 'Input Power Factor', fr: "Facteur de puissance d'entrée", ru: 'Входной коэффициент мощности', es: 'Factor de potencia de entrada', ar: 'معامل قدرة الدخل' }, @@ -592,11 +596,10 @@ 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 }); - }); + if (p.applicationScenarios) rows.push({ labelKey: '应用场景', value: p.applicationScenarios }); + 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 }); return rows; } @@ -776,11 +779,10 @@ const blankProduct = () => ({ batterySpec: '', // 电池型号和数量,如 "12V4.5AH*1"(迷你UPS/离线式/在线互动式UPS共用) dimensions: '', // 尺寸(mm)(迷你UPS/离线式/在线互动式UPS共用) netWeight: '', // 净重(kg)(迷你UPS/离线式/在线互动式UPS共用) + applicationScenarios: '', // 应用场景文本,如 "电脑、投影仪、打印机、摄像机、收银机" + container20ft: '', container40ft: '', container40hq: '', // 装箱数量(20尺柜/40尺柜/40高柜,无栈板台数) productImageFileName: '', productImageOriginalName: '', // 产品主图,导出多语言PDF时展示 sellingPoints: '', // 对客卖点/主要特点,每行一条,专门给客户看的(和下面的costPrice/notes内部信息彻底分开,不会一起导出) - extraSpecs: [], // 不在上面固定字段列表里的"其他参数",如 [{label:'防雷等级', value:'Type II'}]; - // AI批量导入时用来兜底承接原文规格表里有、但当前schema没有对应字段的参数, - // 保证不会因为字段没预定义就丢信息;也支持手动在产品详情页里增删 costPrice: '', notes: '', }); @@ -841,9 +843,6 @@ 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配套锂电池系统') { @@ -870,9 +869,6 @@ 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')) { @@ -899,9 +895,10 @@ 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 }); - }); + if (p.applicationScenarios) items.push({ key: 'appscenario', label: '应用场景', value: p.applicationScenarios }); + 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 }); return items; } if (isUpsCategory(cat) && (p.type === '机架式UPS' || p.type === '在线式高频UPS')) { @@ -937,9 +934,10 @@ 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 }); - }); + if (p.applicationScenarios) items.push({ key: 'appscenario', label: '应用场景', value: p.applicationScenarios }); + 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 }); return items; } if (isUpsCategory(cat) && p.type !== '迷你UPS') { @@ -963,9 +961,10 @@ 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 }); - }); + if (p.applicationScenarios) items.push({ key: 'appscenario', label: '应用场景', value: p.applicationScenarios }); + 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 }); return items; } return [{ key: 'power', label: '功率 / 容量', value: p.powerOrCapacity || '—' }]; @@ -1925,7 +1924,6 @@ function MainApp({ username, onLogout }) { const [dragCustomerIdx, setDragCustomerIdx] = useState(null); const [dragGroupState, setDragGroupState] = useState(null); // { category, index } - const [dragJmsIdx, setDragJmsIdx] = useState(null); const [pwCurrent, setPwCurrent] = useState(''); const [pwNew, setPwNew] = useState(''); @@ -2091,11 +2089,6 @@ function MainApp({ username, onLogout }) { setCustomers(prev => reorderArray(prev, dragCustomerIdx, dropIdx)); setDragCustomerIdx(null); } - function handleJmsDrop(dropIdx) { - if (dragJmsIdx === null || dragJmsIdx === dropIdx) { setDragJmsIdx(null); return; } - setJmsLines(prev => reorderArray(prev, dragJmsIdx, dropIdx)); - setDragJmsIdx(null); - } async function handleAddCatalogFile(file) { if (!file) return; const tempId = 'catdoc_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6); @@ -2420,7 +2413,7 @@ function MainApp({ username, onLogout }) { try { const res = await checkJmsLine(line); setJmsLines(prev => prev.map(l => (l.id === id ? { ...l, monitorStatus: res.status, lastChecked: res.checkedAt } : l))); - if (res.status === 'abnormal') notify(`⚠ ${line.name || line.addr} 检测异常${res.detail ? ':' + res.detail : ''}`); + if (res.status === 'abnormal') notify(`⚠ ${line.name || line.addr} 检测异常`); else notify(`${line.name || line.addr} 检测正常`); } catch (e) { setJmsLines(prev => prev.map(l => (l.id === id ? { ...l, monitorStatus: line.monitorStatus } : l))); @@ -2555,9 +2548,6 @@ 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) { @@ -2635,7 +2625,6 @@ 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() { @@ -3175,10 +3164,6 @@ function MainApp({ username, onLogout }) { onDelete={deleteJmsLine} onCheck={checkJmsLineNow} onNotify={notify} - dragIdx={dragJmsIdx} - onDragStart={setDragJmsIdx} - onDrop={handleJmsDrop} - onDragEnd={() => setDragJmsIdx(null)} /> )} @@ -3853,11 +3838,9 @@ function MainApp({ username, onLogout }) { {!aiImportDrafts ? ( <>