Update App.jsx via upload script - 2026-07-24 10:34:44

This commit is contained in:
mike 2026-07-24 10:35:10 +08:00
parent 9580d3f8ac
commit 22b4033253
1 changed files with 115 additions and 14 deletions

129
App.jsx
View File

@ -259,13 +259,23 @@ const blankCustomer = () => ({
attachments: [], attachments: [],
}); });
const OUTPUT_PORT_TYPES = ['USB', 'DC', 'DC1', 'DC2', 'DC3', 'POE', 'Type-C', 'DC interface', 'POE interface'];
const DEFAULT_MINI_UPS_OUTPUT_TYPES = ['USB', 'DC1', 'DC2', 'DC3', 'POE'];
const blankProduct = () => ({ const blankProduct = () => ({
id: 'p_' + Date.now() + '_' + Math.random().toString(36).slice(2, 7), id: 'p_' + Date.now() + '_' + Math.random().toString(36).slice(2, 7),
name: '', extraNames: [], brand: '', category: '', type: '', name: '', extraNames: [], brand: '', category: '', type: '',
machineVariant: '', // / UPS machineVariant: '', // / UPSUPS
powerOrCapacity: '', // UPS/UPS"UPS" powerOrCapacity: '', // UPS/UPS"UPS"
ratedPower: '', ratedPowerUnit: 'VA', powerFactor: '', // UPS"UPS" ratedPower: '', ratedPowerUnit: 'VA', powerFactor: '', // UPS"UPS"
voltage: '', costPrice: '', notes: '', voltage: '', // UPSUPS 100~240Vac/50-60Hz
outputPortCount: '', // UPS 1-6
outputPortTypes: [], // UPS
outputPorts: [], // UPS/ [{type:'USB', voltage:'5Vdc', current:'3.0A'}]
batterySpec: '', // UPS "5000mAh*4"
dimensions: '', // UPS(mm) "210*130*40"
netWeight: '', // UPS(kg)
costPrice: '', notes: '',
}); });
function isUpsCategory(cat) { function isUpsCategory(cat) {
@ -290,7 +300,19 @@ function powerInfoItems(p, categories) {
]; ];
} }
if (isUpsCategory(cat) && p.type === '迷你UPS') { if (isUpsCategory(cat) && p.type === '迷你UPS') {
return [{ key: 'maxout', label: '最大输出功率', value: p.powerOrCapacity || '—' }]; const items = [{ key: 'maxout', label: '输出功率', value: p.powerOrCapacity || '—' }];
items.push({ key: 'inputvoltage', label: '输入电压', value: p.voltage || '—' });
if (p.outputPortCount) items.push({ key: 'portcount', label: '输出口数量', value: p.outputPortCount });
if (p.outputPortTypes && p.outputPortTypes.length) items.push({ key: 'porttypes', label: '输出口类型', value: p.outputPortTypes.join(' / ') });
(p.outputPorts || []).forEach(port => {
if (port.voltage || port.current) {
items.push({ key: 'port_' + port.type, label: `${port.type} 输出`, value: [port.voltage, port.current].filter(Boolean).join(' ') });
}
});
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 });
return items;
} }
return [{ key: 'power', label: '功率 / 容量', value: p.powerOrCapacity || '—' }]; return [{ key: 'power', label: '功率 / 容量', value: p.powerOrCapacity || '—' }];
} }
@ -2995,6 +3017,23 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage }
function addExtraName() { set({ extraNames: [...extraNames, ''] }); } function addExtraName() { set({ extraNames: [...extraNames, ''] }); }
function updateExtraName(idx, val) { const arr = [...extraNames]; arr[idx] = val; set({ extraNames: arr }); } function updateExtraName(idx, val) { const arr = [...extraNames]; arr[idx] = val; set({ extraNames: arr }); }
function removeExtraName(idx) { set({ extraNames: extraNames.filter((_, i) => i !== idx) }); } function removeExtraName(idx) { set({ extraNames: extraNames.filter((_, i) => i !== idx) }); }
function toggleOutputPortType(t) {
const list = draft.outputPortTypes || [];
if (list.includes(t)) {
set({
outputPortTypes: list.filter(x => x !== t),
outputPorts: (draft.outputPorts || []).filter(p => p.type !== t),
});
} else {
set({
outputPortTypes: [...list, t],
outputPorts: [...(draft.outputPorts || []), { type: t, voltage: '', current: '' }],
});
}
}
function updateOutputPort(t, patch) {
set({ outputPorts: (draft.outputPorts || []).map(p => (p.type === t ? { ...p, ...patch } : p)) });
}
return ( return (
<div className="panel"> <div className="panel">
<div className="panel-header"><div className="panel-title"><Edit2 size={14} />{draft.name ? '编辑产品' : '新建产品'}</div></div> <div className="panel-header"><div className="panel-title"><Edit2 size={14} />{draft.name ? '编辑产品' : '新建产品'}</div></div>
@ -3044,7 +3083,24 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage }
<span className="field-label">细分品类</span> <span className="field-label">细分品类</span>
<span className="field-manage-link" onClick={() => onManage('type')}><Settings2 size={11} />品类管理</span> <span className="field-manage-link" onClick={() => onManage('type')}><Settings2 size={11} />品类管理</span>
</div> </div>
<select className="select" value={draft.type} disabled={!cat} onChange={e => set({ type: e.target.value })}> <select
className="select" value={draft.type} disabled={!cat}
onChange={e => {
const newType = e.target.value;
if (newType === '迷你UPS') {
set({
type: newType,
machineVariant: '标机',
voltage: draft.voltage || '100~240Vac/50-60Hz',
outputPortCount: draft.outputPortCount || '5',
outputPortTypes: (draft.outputPortTypes && draft.outputPortTypes.length) ? draft.outputPortTypes : [...DEFAULT_MINI_UPS_OUTPUT_TYPES],
outputPorts: (draft.outputPorts && draft.outputPorts.length) ? draft.outputPorts : DEFAULT_MINI_UPS_OUTPUT_TYPES.map(t => ({ type: t, voltage: '', current: '' })),
});
} else {
set({ type: newType });
}
}}
>
<option value="">{!cat ? '请先选择产品大类' : typeOptions.length === 0 ? '该类目暂无品类,点右上角管理添加' : '请选择'}</option> <option value="">{!cat ? '请先选择产品大类' : typeOptions.length === 0 ? '该类目暂无品类,点右上角管理添加' : '请选择'}</option>
{typeOptions.map(t => <option key={t} value={t}>{t}</option>)} {typeOptions.map(t => <option key={t} value={t}>{t}</option>)}
</select> </select>
@ -3054,11 +3110,15 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage }
{isUps && ( {isUps && (
<div className="field"> <div className="field">
<span className="field-label">机型</span> <span className="field-label">机型</span>
<select className="select" value={draft.machineVariant} onChange={e => set({ machineVariant: e.target.value })}> {isMiniUps ? (
<option value="">请选择</option> <input className="input" value="标机" disabled readOnly />
<option value="标机">标机</option> ) : (
<option value="长机">长机</option> <select className="select" value={draft.machineVariant} onChange={e => set({ machineVariant: e.target.value })}>
</select> <option value="">请选择</option>
<option value="标机">标机</option>
<option value="长机">长机</option>
</select>
)}
</div> </div>
)} )}
@ -3079,10 +3139,51 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage }
<div className="field"><span className="field-label">电压</span><input className="input" value={draft.voltage} onChange={e => set({ voltage: e.target.value })} placeholder="如48V / 192V / 220V" /></div> <div className="field"><span className="field-label">电压</span><input className="input" value={draft.voltage} onChange={e => set({ voltage: e.target.value })} placeholder="如48V / 192V / 220V" /></div>
</div> </div>
) : isUps && isMiniUps ? ( ) : isUps && isMiniUps ? (
<div className="grid-2"> <>
<div className="field"><span className="field-label">最大输出功率</span><input className="input" value={draft.powerOrCapacity} onChange={e => set({ powerOrCapacity: e.target.value })} placeholder="如600W" /></div> <div className="grid-2">
<div className="field"><span className="field-label">电压</span><input className="input" value={draft.voltage} onChange={e => set({ voltage: e.target.value })} placeholder="如48V / 192V / 220V" /></div> <div className="field"><span className="field-label">输出功率</span><input className="input" value={draft.powerOrCapacity} onChange={e => set({ powerOrCapacity: e.target.value })} placeholder="如36W" /></div>
</div> <div className="field"><span className="field-label">输入电压</span><input className="input" value={draft.voltage} onChange={e => set({ voltage: e.target.value })} placeholder="如100~240Vac/50-60Hz" /></div>
</div>
<div className="grid-2">
<div className="field">
<span className="field-label">输出口数量</span>
<select className="select" value={draft.outputPortCount} onChange={e => set({ outputPortCount: e.target.value })}>
<option value="">请选择</option>
{[1, 2, 3, 4, 5, 6].map(n => <option key={n} value={String(n)}>{n}</option>)}
</select>
</div>
<div className="field">
<span className="field-label">电池数量和容量</span>
<input className="input" value={draft.batterySpec} onChange={e => set({ batterySpec: e.target.value })} placeholder="如5000mAh*4" />
</div>
</div>
<div className="field">
<span className="field-label">输出口类型</span>
<div className="checkbox-row">
{OUTPUT_PORT_TYPES.map(t => (
<div key={t} className={`checkbox-pill ${(draft.outputPortTypes || []).includes(t) ? 'checked' : ''}`} onClick={() => toggleOutputPortType(t)}>
{(draft.outputPortTypes || []).includes(t) && <Check size={11} />} {t}
</div>
))}
</div>
</div>
{(draft.outputPorts || []).length > 0 && (
<div className="field">
<span className="field-label">各输出口的输出电压 / 电流</span>
{draft.outputPorts.map(p => (
<div key={p.type} style={{ display: 'flex', gap: 8, alignItems: 'center', marginBottom: 6 }}>
<div style={{ width: 90, fontSize: 12.5, fontWeight: 700, flexShrink: 0 }}>{p.type}</div>
<input className="input" style={{ flex: 1 }} placeholder="输出电压,如 5Vdc" value={p.voltage} onChange={e => updateOutputPort(p.type, { voltage: e.target.value })} />
<input className="input" style={{ flex: 1 }} placeholder="电流,如 3.0A" value={p.current} onChange={e => updateOutputPort(p.type, { current: e.target.value })} />
</div>
))}
</div>
)}
<div className="grid-2">
<div className="field"><span className="field-label">尺寸mm</span><input className="input" value={draft.dimensions} onChange={e => set({ dimensions: e.target.value })} placeholder="如210*130*40" /></div>
<div className="field"><span className="field-label">净重kg</span><input className="input" value={draft.netWeight} onChange={e => set({ netWeight: e.target.value })} placeholder="如0.73" /></div>
</div>
</>
) : ( ) : (
<div className="grid-2"> <div className="grid-2">
<div className="field"><span className="field-label">功率 / 容量</span><input className="input" value={draft.powerOrCapacity} onChange={e => set({ powerOrCapacity: e.target.value })} placeholder="如10kVA / 100Ah / 5kWh" /></div> <div className="field"><span className="field-label">功率 / 容量</span><input className="input" value={draft.powerOrCapacity} onChange={e => set({ powerOrCapacity: e.target.value })} placeholder="如10kVA / 100Ah / 5kWh" /></div>