diff --git a/App.jsx b/App.jsx index 9073102..dcc9a7f 100644 --- a/App.jsx +++ b/App.jsx @@ -837,19 +837,21 @@ const Styles = () => ( .cert-card-brand input { text-align: center; font-weight: 700; } /* ---------- catalog docs (PDF gallery: upload progress, actions, dnd reorder) ---------- */ + .catalog-card-grid { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); } .catalog-doc-actions { position: absolute; top: 6px; right: 6px; display: flex; gap: 4px; } .catalog-doc-actions .btn { padding: 5px 6px; background: rgba(255,255,255,0.92); border-color: var(--line); } + .catalog-doc-img-wrap { aspect-ratio: unset; height: 92px; } .catalog-doc-link { - display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; - width: 100%; height: 100%; padding: 18px; text-align: center; color: inherit; text-decoration: none; + display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; + width: 100%; height: 100%; padding: 10px; text-align: center; color: inherit; text-decoration: none; } - .catalog-doc-filename { font-size: 11px; color: var(--ink-soft); word-break: break-word; } + .catalog-doc-filename { font-size: 10.5px; color: var(--ink-soft); word-break: break-word; line-height: 1.3; } .catalog-doc-uploading { - display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; - width: 100%; height: 100%; color: var(--ink-soft); font-size: 12px; padding: 18px; text-align: center; + display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px; + width: 100%; height: 100%; color: var(--ink-soft); font-size: 11px; padding: 10px; text-align: center; } .catalog-doc-spinner { - width: 26px; height: 26px; border-radius: 50%; border: 3px solid var(--line); border-top-color: var(--copper); + width: 20px; height: 20px; border-radius: 50%; border: 3px solid var(--line); border-top-color: var(--copper); animation: catalog-doc-spin 0.8s linear infinite; } @keyframes catalog-doc-spin { to { transform: rotate(360deg); } } @@ -859,6 +861,11 @@ const Styles = () => ( .catalog-dropzone.drag-active { outline: 2px dashed var(--blue); outline-offset: 6px; background: #F0F6FA; } .catalog-doc-card { cursor: grab; } .catalog-doc-card.dragging { opacity: 0.5; } + .catalog-doc-meta { font-size: 10.5px; color: var(--ink-soft); margin-top: 3px; text-align: center; word-break: break-word; } + .catalog-doc-edit-fields { display: flex; flex-direction: column; gap: 6px; } + .catalog-doc-edit-fields select { font-size: 11.5px; padding: 5px 8px; } + .catalog-filter-row { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; } + .catalog-filter-row .select { width: auto; min-width: 160px; } .field-label-row { display: flex; align-items: center; justify-content: space-between; } .field-manage-link { font-size: 11.5px; font-weight: 600; color: var(--blue); cursor: pointer; @@ -895,6 +902,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); } + .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 { width: 36px; height: 36px; border-radius: 50%; padding: 0; @@ -1188,7 +1196,8 @@ function MainApp({ username, onLogout }) { const [catalogDragActive, setCatalogDragActive] = useState(false); const [dragCatalogDocIdx, setDragCatalogDocIdx] = useState(null); const [editingCatalogId, setEditingCatalogId] = useState(null); - const [catalogTitleDraft, setCatalogTitleDraft] = useState(''); + const [catalogEditDraft, setCatalogEditDraft] = useState({ title: '', category: '', brand: '', type: '' }); + const [catalogCategoryFilter, setCatalogCategoryFilter] = useState('all'); useEffect(() => { getAiConfig().then((res) => setAiConfigHasKey(!!res.hasKey)).catch(() => {}); @@ -1276,6 +1285,11 @@ function MainApp({ username, onLogout }) { const priceHistory = useMemo(() => buildPriceHistory(quotes), [quotes]); + const filteredCatalogDocs = useMemo(() => { + if (catalogCategoryFilter === 'all') return catalogDocs; + return catalogDocs.filter(d => d.uploading || d.category === catalogCategoryFilter); + }, [catalogDocs, catalogCategoryFilter]); + function handleCustomerDrop(dropIdx) { if (dragCustomerIdx === null || dragCustomerIdx === dropIdx) { setDragCustomerIdx(null); return; } setCustomers(prev => reorderArray(prev, dragCustomerIdx, dropIdx)); @@ -1285,12 +1299,12 @@ function MainApp({ username, onLogout }) { if (!file) return; const tempId = 'catdoc_' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6); // 先插入一张"上传中"的占位卡片,让用户能实时看到这个文件正在传,传完再替换成真实数据 - setCatalogDocs(prev => [{ id: tempId, title: '', fileName: '', originalName: file.name, uploading: true }, ...prev]); + setCatalogDocs(prev => [{ id: tempId, title: '', fileName: '', originalName: file.name, category: '', brand: '', type: '', uploading: true }, ...prev]); try { const res = await uploadFile(tempId, file); setCatalogDocs(prev => prev.map(d => (d.id === tempId ? { ...d, fileName: res.fileName, originalName: res.originalName, uploading: false } : d))); setEditingCatalogId(tempId); - setCatalogTitleDraft(''); + setCatalogEditDraft({ title: '', category: '', brand: '', type: '' }); } catch (e) { notify(`《${file.name}》上传失败,请重试`); setCatalogDocs(prev => prev.filter(d => d.id !== tempId)); @@ -1311,14 +1325,19 @@ function MainApp({ username, onLogout }) { if (files.length === 0) { notify('只能上传PDF文件'); return; } handleCatalogFilesSelected(files); } - function startEditCatalogTitle(doc) { + function startEditCatalogDoc(doc) { setEditingCatalogId(doc.id); - setCatalogTitleDraft(doc.title || ''); + setCatalogEditDraft({ title: doc.title || '', category: doc.category || '', brand: doc.brand || '', type: doc.type || '' }); } - function saveCatalogTitle() { - setCatalogDocs(prev => prev.map(d => (d.id === editingCatalogId ? { ...d, title: catalogTitleDraft.trim() } : d))); + function updateCatalogEditDraft(patch) { + setCatalogEditDraft(d => ({ ...d, ...patch })); + } + function saveCatalogEdit() { + setCatalogDocs(prev => prev.map(d => (d.id === editingCatalogId + ? { ...d, title: catalogEditDraft.title.trim(), category: catalogEditDraft.category, brand: catalogEditDraft.brand, type: catalogEditDraft.type } + : d))); setEditingCatalogId(null); - setCatalogTitleDraft(''); + setCatalogEditDraft({ title: '', category: '', brand: '', type: '' }); } async function deleteCatalogDoc(doc) { if (!window.confirm('确定删除这份产品目录PDF?此操作不可恢复。')) return; @@ -2173,7 +2192,13 @@ function MainApp({ username, onLogout }) { className={`catalog-dropzone ${catalogDragActive ? 'drag-active' : ''}`} onDragOver={handleCatalogDragOver} onDragLeave={handleCatalogDragLeave} onDrop={handleCatalogDrop} > -
+
+
+ +