Update App.jsx via upload script - 2026-08-21 10:01:57

This commit is contained in:
mike 2026-08-21 10:02:16 +08:00
parent 5489ea44b8
commit d493486b76
1 changed files with 61 additions and 0 deletions

61
App.jsx
View File

@ -766,6 +766,8 @@ function upsertProductByName(list, product) {
id: existing.id,
productImageFileName: existing.productImageFileName,
productImageOriginalName: existing.productImageOriginalName,
brochureFileName: existing.brochureFileName,
brochureOriginalName: existing.brochureOriginalName,
sellingPoints: existing.sellingPoints,
costPrice: existing.costPrice,
notes: existing.notes,
@ -931,6 +933,7 @@ const blankProduct = () => ({
extraSpecs: [], // AI {label, value} [{label:'', value:'13.7VDC/'}]
backPanelTemplateId: '', // idUPS
productImageFileName: '', productImageOriginalName: '', // PDF
brochureFileName: '', brochureOriginalName: '', // PDF/PDF
sellingPoints: '', // /costPrice/notes
costPrice: '', notes: '',
});
@ -1748,6 +1751,7 @@ const Styles = () => (
color: var(--ink-soft); font-size: 13px; cursor: pointer; transition: border-color 0.15s, color 0.15s;
}
.tax-add-category:hover { border-color: var(--blue); color: var(--blue); }
.brochure-file-chip { width: 40px; height: 40px; border-radius: 8px; background: var(--copper-soft); color: var(--copper); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.catalog-view-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; flex-wrap: wrap; gap: 10px; }
.cert-view-head { display: flex; align-items: center; justify-content: flex-end; margin-bottom: 14px; }
.cert-add-btn {
@ -4924,6 +4928,25 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage,
try { await deleteFile(draft.id, draft.productImageFileName); } catch (e) {}
set({ productImageFileName: '', productImageOriginalName: '' });
}
const [brochureUploading, setBrochureUploading] = useState(false);
async function handleBrochurePick(file) {
if (!file) return;
setBrochureUploading(true);
try {
const res = await uploadFile(draft.id, file);
set({ brochureFileName: res.fileName, brochureOriginalName: res.originalName });
} catch (e) {
if (onNotify) onNotify('彩页上传失败,请重试');
} finally {
setBrochureUploading(false);
}
}
async function handleBrochureRemove() {
if (!draft.brochureFileName) return;
if (!window.confirm('确定删除已上传的原版彩页?')) return;
try { await deleteFile(draft.id, draft.brochureFileName); } catch (e) {}
set({ brochureFileName: '', brochureOriginalName: '' });
}
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) }); }
@ -5380,6 +5403,33 @@ function ProductForm({ draft, setDraft, onSave, onCancel, categories, onManage,
)}
</div>
<div className="field">
<div className="field-label-row">
<span className="field-label">原版彩页可选保存厂家原始彩页文件支持PDF/图片仅用于保存和下载</span>
</div>
{draft.brochureFileName ? (
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<div className="brochure-file-chip">
<FileText size={16} />
</div>
<a
href={`/uploads/${draft.id}/${draft.brochureFileName}`} target="_blank" rel="noreferrer" download={draft.brochureOriginalName}
style={{ fontSize: 12.5, color: 'var(--blue)', flex: 1, wordBreak: 'break-word' }}
>{draft.brochureOriginalName}</a>
<label className="btn btn-sm" style={{ cursor: brochureUploading ? 'default' : 'pointer' }}>
{brochureUploading ? '上传中…' : '替换'}
<input type="file" style={{ display: 'none' }} disabled={brochureUploading} onChange={e => handleBrochurePick(e.target.files && e.target.files[0])} />
</label>
<button className="btn btn-sm btn-ghost btn-danger" onClick={handleBrochureRemove}><Trash2 size={12} /></button>
</div>
) : (
<label className="tax-add-category" style={{ display: 'block', cursor: brochureUploading ? 'default' : 'pointer' }}>
<input type="file" style={{ display: 'none' }} disabled={brochureUploading} onChange={e => handleBrochurePick(e.target.files && e.target.files[0])} />
<FileText size={16} style={{ verticalAlign: -3, marginRight: 4 }} />{brochureUploading ? '上传中…' : '点击上传原版彩页'}
</label>
)}
</div>
<div className="field">
<span className="field-label">其他参数AI识别到但暂未收录成正式字段的参数原样保留也会显示在详情页和多语言PDF导出里</span>
{(draft.extraSpecs || []).map((item, idx) => (
@ -5478,6 +5528,17 @@ function ProductDetail({ product: p, onEdit, onDelete, categories, exportLang, o
<BackPanelReadOnly template={backPanelTemplate} />
</div>
)}
{p.brochureFileName && (
<div className="field">
<span className="field-label">原版彩页</span>
<a
href={`/uploads/${p.id}/${p.brochureFileName}`} target="_blank" rel="noreferrer" download={p.brochureOriginalName}
className="btn btn-sm" style={{ display: 'inline-flex' }}
>
<FileText size={12} />{p.brochureOriginalName || '下载原版彩页'}
</a>
</div>
)}
{p.notes && <div className="field"><span className="field-label">备注</span><div style={{ fontSize: 12.5, whiteSpace: 'pre-wrap' }}>{p.notes}</div></div>}
</div>
</div>