From 0d682a826a312926cf4e0dad8d5f6008e19a044f Mon Sep 17 00:00:00 2001 From: zzh Date: Thu, 26 Mar 2026 10:16:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=89=8D=E7=AB=AF=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=92=8C=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/assets/styles.css | 26 + frontend/index.html | 11 + frontend/js/components/shipment-audit.js | 124 +++- frontend/js/components/shipment-query.js | 109 ++- frontend/js/components/shipment-summary.js | 96 ++- frontend/js/components/shipments.js | 196 +++-- frontend/js/components/upload.js | 794 +++++++++++++-------- 7 files changed, 897 insertions(+), 459 deletions(-) mode change 100644 => 100755 frontend/assets/styles.css mode change 100644 => 100755 frontend/index.html mode change 100644 => 100755 frontend/js/components/shipment-audit.js mode change 100644 => 100755 frontend/js/components/shipment-query.js mode change 100644 => 100755 frontend/js/components/shipment-summary.js mode change 100644 => 100755 frontend/js/components/shipments.js mode change 100644 => 100755 frontend/js/components/upload.js diff --git a/frontend/assets/styles.css b/frontend/assets/styles.css old mode 100644 new mode 100755 index 8a203c8..ff60995 --- a/frontend/assets/styles.css +++ b/frontend/assets/styles.css @@ -2747,6 +2747,32 @@ input[type="date"]::-webkit-calendar-picker-indicator:hover{ .spec-value{font-size:14px;color:var(--text);font-weight:500} @media(max-width:768px){.product-card{flex-direction:column}.product-image-wrapper{flex:none;width:100%}.product-features{grid-template-columns:1fr}} +/* 历史记录弹窗响应式优化 */ +@media (max-width: 480px) { + .notification-modal-content { + width: 95%; + max-width: none; + } + + #mac-history-modal .notification-modal-content { + max-width: 95%; + } + + #mac-history-modal-list { + max-height: 50vh; + } + + #mac-history-modal-list li { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + + #mac-history-modal-list .badge { + align-self: flex-start; + } +} + [data-theme="light"] body{background:#f1f5f9} #app.trackit-layout{margin:0;height:100vh;border-radius:0;overflow:hidden;background:#ffffff;border:none;box-shadow:none;display:flex;flex-direction:row} #app.trackit-layout .content{background:rgba(248,250,252,.6);height:100%} diff --git a/frontend/index.html b/frontend/index.html old mode 100644 new mode 100755 index 887ed3a..366646b --- a/frontend/index.html +++ b/frontend/index.html @@ -470,6 +470,17 @@ + + diff --git a/frontend/js/components/shipment-audit.js b/frontend/js/components/shipment-audit.js old mode 100644 new mode 100755 index c428f6e..6d66398 --- a/frontend/js/components/shipment-audit.js +++ b/frontend/js/components/shipment-audit.js @@ -124,44 +124,94 @@ Router.register('/shipments/audit', async () => { }); }, 0); - return `
-
审计查询
+ return ` + -
-
- 说明:查询 Redis 中存储的审计时间记录,支持通过 MAC 地址或批次号查询。 +
+ + +
+
+
+ 说明:查询 Redis 中存储的审计时间记录,支持通过 MAC 地址或批次号查询。 +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+
+
- -
-
- - -
-
- - -
-
- - -
- -
- -
-
`; + `; }); diff --git a/frontend/js/components/shipment-query.js b/frontend/js/components/shipment-query.js old mode 100644 new mode 100755 index e05dbc9..bfd4dbd --- a/frontend/js/components/shipment-query.js +++ b/frontend/js/components/shipment-query.js @@ -187,38 +187,85 @@ Router.register('/shipments/query', async () => { // 根据用户角色决定是否显示清空按钮 const showClearButton = userRole === 'superadmin'; - return `
-
发货详细记录查询
+ return ` + -
-
-
加载中...
+
+ + +
+
+
+
+
加载中...
+
+
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+ +
+
+
- -
-
- - -
-
- - -
-
- - ${showClearButton ? '' : ''} -
-
- -
-
`; + `; }); diff --git a/frontend/js/components/shipment-summary.js b/frontend/js/components/shipment-summary.js old mode 100644 new mode 100755 index 3b6934a..a936712 --- a/frontend/js/components/shipment-summary.js +++ b/frontend/js/components/shipment-summary.js @@ -95,31 +95,83 @@ Router.register('/shipments/summary', async () => { performQuery(); }, 0); - return `
-
发货汇总信息查询
+ return ` + -
-
-
- - +
+ + +
+
+
+
+ + +
+
+ + +
+
+ +
+ +
-
- - + +
+
-
- -
-
`; + `; }); diff --git a/frontend/js/components/shipments.js b/frontend/js/components/shipments.js old mode 100644 new mode 100755 index 88bfeaf..f47c02c --- a/frontend/js/components/shipments.js +++ b/frontend/js/components/shipments.js @@ -170,25 +170,133 @@ Router.register('/upload/shipments', async () => { } }); }, 0); - return `
-
发货记录
+ return ` + -
-
手动录入
-
- 用于快速录入发货汇总信息(不含详细SN) +
+ -
-
-
- - + +
+
+
手动录入
+
用于快速录入发货汇总信息(不含详细SN)
+ +
+
+ + +
+
+ + +
+
+ +
+
+ + +
+
+ + +
+
+ +
+ + +
+ +
+
+
-
-
+ +
+
详细记录批量导入
+ +
+
📋 文件格式要求
+
+
• 必需列:出货日期、箱号、SN1、SN2、...、SN20
+
• 出货日期列支持合并单元格
+
• 支持格式:Excel (.xlsx, .xls) 或 CSV
+
+
+ +
- @@ -198,59 +306,19 @@ Router.register('/upload/shipments', async () => {
-
-
-
-
-
- - + +
+ +
-
-
-
- - + +
+
+ +
-
- - -
-
-
- -
-
详细记录批量导入
-
-
文件格式要求:
-
• 必需列:出货日期、箱号、SN1、SN2、...、SN20
-
• 出货日期列支持合并单元格
-
• 支持格式:Excel (.xlsx, .xls) 或 CSV
-
-
- - -
-
- - -
-
-
- - -
-
-
`; + `; }); \ No newline at end of file diff --git a/frontend/js/components/upload.js b/frontend/js/components/upload.js old mode 100644 new mode 100755 index 9091a61..5506e0a --- a/frontend/js/components/upload.js +++ b/frontend/js/components/upload.js @@ -68,100 +68,289 @@ const Upload = (() => { function textarea(id,label,placeholder=''){return `
`} async function renderMac(){ - return section('MAC与批次(MAC与批次对应关系表)',` -
-
📋 Excel文件格式要求
-
-
• Excel文件必须包含以下列头(按顺序):
-
- 拼多多/圆通:
- 第1列: MAC(格式:90A9F7300000)
- 第2列: 批次号

- 兔喜:
- 第1列: SN_MAC(格式:TJ251639510533:90A9F73007D0)
- 第2列: 批次号 + return ` + + +
+ -
- - -
- ${filePicker('mac-file','批量导入(Excel)','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel')} -
- -
-
- 历史记录 -
- - -
-
-
    -
    - `); + `; } async function renderStats(){ - return section('良/不良统计',` -
    -
    📊 数据说明
    -
    -
    直通良品数:一次检测就通过的产品数量
    -
    良品数:最终通过检测的产品总数(包含直通良品 + 返修后通过的产品)
    -
    不良品数:最终未通过检测的产品数量(报废或待返修)
    -
    - 💡 计算公式:
    - 直通良品率 = 直通良品数 / (良品数 + 不良品数) × 100%
    - 总良品率 = 良品数 / (良品数 + 不良品数) × 100% + return ` + + +
    + + +
    +
    +
    +
    📊 数据说明
    +
    +
    直通良品数:一次检测就通过的产品数量
    +
    良品数:最终通过检测的产品总数(包含直通良品 + 返修后通过的产品)
    +
    不良品数:最终未通过检测的产品数量(报废或待返修)
    +
    + 💡 计算公式:
    + 直通良品率 = 直通良品数 / (良品数 + 不良品数) × 100%
    + 总良品率 = 良品数 / (良品数 + 不良品数) × 100% +
    +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    +
    + + +
    +
    + + +
    +
    + +
    + + +
    + +
    + +
    -
    - - -
    - ${numberInput('fpy-good-count','直通良品数量(一次检测通过)')} - ${numberInput('good-count','良品数量(最终通过检测的总数)')} - ${numberInput('bad-count','不良品数量(最终未通过)')} -
    - - -
    -
    -
    -
    - 最新记录 -
    - - -
    -
    -
      -
      - `); + `; } // 不良原因选项 @@ -187,11 +376,46 @@ const Upload = (() => { ]; async function renderRepairs(){ - return section('返修记录上传',` - -
      + return ` + + +
      + + +
      +
      - +
      +
      - `); + `; } async function renderRepairsHistory(){ @@ -395,39 +612,98 @@ const Upload = (() => { }); async function renderSop(){ - return section('SOP 文件管理',` -
      -
      📄 SOP 说明
      -
      -
      • 所有用户均可在线查看和下载 SOP 文件
      -
      • 管理员可以上传新的 SOP 文件(支持 Excel 和 Word 格式)
      -
      • 建议为每个 SOP 文件添加清晰的描述说明
      + return ` + + +
      + + +
      +
      +
      +
      📄 SOP 说明
      +
      +
      • 所有用户均可在线查看和下载 SOP 文件
      +
      • 管理员可以上传新的 SOP 文件(支持 Excel 和 Word 格式)
      +
      • 建议为每个 SOP 文件添加清晰的描述说明
      +
      +
      + +
      + + +
      + +
      + + +
      + +
      + +
      + + +
      + +
      +
      SOP 文件列表
      +
        +
        - ${filePicker('sop-file','上传 SOP 文件 (Excel/Word)','application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,text/csv,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/msword')} -
        - - -
        -
        - -
        -
        SOP 文件列表
        -
          -
          - `); + `; } Router.register('/upload/sop', async () => { @@ -590,70 +866,98 @@ const Upload = (() => { async function bindMacEvents(){ const fileEl=document.getElementById('mac-file'); const btn = document.getElementById('mac-upload'); - const showHistoryBtn = document.getElementById('mac-show-history'); - const clearDisplayBtn = document.getElementById('mac-clear-display'); + const viewHistoryBtn = document.getElementById('mac-view-history'); + const toggleHelpBtn = document.getElementById('mac-toggle-help'); + const helpContent = document.getElementById('mac-help-content'); + const helpIcon = document.getElementById('mac-help-icon'); - // 显示历史记录的通用函数 - const displayHistory = async (showAll = false) => { - const listEl = document.getElementById('mac-list'); + // 格式说明折叠/展开功能 + addListener(toggleHelpBtn, 'click', () => { + const isHidden = helpContent.style.display === 'none'; + helpContent.style.display = isHidden ? 'block' : 'none'; + helpIcon.style.transform = isHidden ? 'rotate(180deg)' : 'rotate(0deg)'; + }); + + // 历史记录弹窗功能 + const showHistoryModal = async () => { + const modal = document.getElementById('mac-history-modal'); + const listEl = document.getElementById('mac-history-modal-list'); + + if(!modal || !listEl) return; + + // 显示弹窗 + modal.style.display = 'block'; + listEl.innerHTML = '
          加载中...
          '; + try { const data = await API.listMac(); - if(listEl){ - if(data.list && data.list.length > 0){ - const platformNames = {pdd: '拼多多', yt: '圆通', tx: '兔喜'}; + if(data.list && data.list.length > 0){ + const platformNames = {pdd: '拼多多', yt: '圆通', tx: '兔喜'}; + + // 按时间和机种分组统计 + const uploadGroups = {}; + data.list.forEach(r => { + const date = new Date(r.ts).toLocaleDateString('zh-CN'); + const platform = platformNames[r.platform] || r.platform || '未知'; + const key = `${date}_${platform}`; - // 按时间和机种分组统计 - const uploadGroups = {}; - data.list.forEach(r => { - const date = new Date(r.ts).toLocaleDateString('zh-CN'); - const platform = platformNames[r.platform] || r.platform || '未知'; - const key = `${date}_${platform}`; - - if (!uploadGroups[key]) { - uploadGroups[key] = { - date: date, - platform: platform, - count: 0, - firstTime: r.ts - }; - } - uploadGroups[key].count++; - }); - - // 转换为数组并按时间排序 - const groupArray = Object.values(uploadGroups) - .sort((a, b) => new Date(b.firstTime) - new Date(a.firstTime)); - - listEl.innerHTML = groupArray.map(g => { - return `
        • -
          -
          ${g.date}
          -
          上传 ${g.count} 条记录
          -
          -
          - ${g.platform} -
          -
        • `; - }).join(''); - - if(showAll) { - const totalGroups = groupArray.length; - const totalRecords = data.list.length; - API.toast(`显示 ${totalGroups} 次上传记录,共 ${totalRecords} 条数据`); + if (!uploadGroups[key]) { + uploadGroups[key] = { + date: date, + platform: platform, + count: 0, + firstTime: r.ts + }; } - } else { - listEl.innerHTML = '
        • 暂无历史记录
        • '; - } + uploadGroups[key].count++; + }); + + // 转换为数组并按时间排序 + const groupArray = Object.values(uploadGroups) + .sort((a, b) => new Date(b.firstTime) - new Date(a.firstTime)); + + listEl.innerHTML = ` +
          +
          ${groupArray.length} 次上传,总计 ${data.list.length} 条记录
          +
          +
            + ${groupArray.map(g => { + return `
          • +
            +
            ${g.date}
            +
            上传 ${g.count} 条记录
            +
            +
            + ${g.platform} +
            +
          • `; + }).join('')} +
          + `; + } else { + listEl.innerHTML = '
          暂无历史记录
          '; } } catch(e) { + listEl.innerHTML = '
          加载失败,请重试
          '; API.toast('加载历史记录失败'); - if(listEl) listEl.innerHTML = '
        • 加载失败
        • '; } }; - // 查看历史按钮 - 从服务器获取所有用户的上传记录 - addListener(showHistoryBtn, 'click', async ()=>{ - await displayHistory(true); + // 查看历史记录按钮 + addListener(viewHistoryBtn, 'click', showHistoryModal); + + // 关闭弹窗 + const closeBtn = document.getElementById('mac-history-modal-close'); + const backdrop = document.querySelector('#mac-history-modal .notification-modal-backdrop'); + + addListener(closeBtn, 'click', () => { + const modal = document.getElementById('mac-history-modal'); + if(modal) modal.style.display = 'none'; + }); + + addListener(backdrop, 'click', () => { + const modal = document.getElementById('mac-history-modal'); + if(modal) modal.style.display = 'none'; }); // 文件选择后立即验证 @@ -683,77 +987,6 @@ const Upload = (() => { } }); - // 查看历史按钮 - 从服务器获取所有用户的上传记录 - addListener(showHistoryBtn, 'click', async ()=>{ - const listEl = document.getElementById('mac-list'); - try { - const data = await API.listMac(); - if(listEl){ - if(data.list && data.list.length > 0){ - const platformNames = {pdd: '拼多多', yt: '圆通', tx: '兔喜'}; - - // 按时间和机种分组统计 - const uploadGroups = {}; - data.list.forEach(r => { - const date = new Date(r.ts).toLocaleDateString('zh-CN'); - const platform = platformNames[r.platform] || r.platform || '未知'; - const key = `${date}_${platform}`; - - if (!uploadGroups[key]) { - uploadGroups[key] = { - date: date, - platform: platform, - count: 0, - firstTime: r.ts - }; - } - uploadGroups[key].count++; - }); - - // 转换为数组并按时间排序 - const groupArray = Object.values(uploadGroups) - .sort((a, b) => new Date(b.firstTime) - new Date(a.firstTime)); - - listEl.innerHTML = groupArray.map(g => { - const time = new Date(g.firstTime).toLocaleString('zh-CN', { - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit' - }); - return `
        • -
          -
          ${g.date}
          -
          上传 ${g.count} 条记录
          -
          -
          - ${g.platform} -
          -
        • `; - }).join(''); - - const totalGroups = groupArray.length; - const totalRecords = data.list.length; - API.toast(`显示 ${totalGroups} 次上传记录,共 ${totalRecords} 条数据`); - } else { - listEl.innerHTML = '
        • 暂无历史记录
        • '; - } - } - } catch(e) { - API.toast('加载历史记录失败'); - if(listEl) listEl.innerHTML = '
        • 加载失败
        • '; - } - }); - - // 清空显示按钮 - addListener(clearDisplayBtn, 'click', ()=>{ - const listEl = document.getElementById('mac-list'); - if(listEl){ - listEl.innerHTML = '
        • 已清空显示
        • '; - API.toast('已清空显示(历史记录仍保留)'); - } - }); - addListener(btn, 'click', async ()=>{ const file = fileEl.files[0]; if(!file){ @@ -804,64 +1037,15 @@ const Upload = (() => { if(result.ok){ API.toast('上传成功'); - // 解析并显示成功上传的记录 + // 解析成功上传的记录 const output = result.output || ''; const jsonMatch = output.match(/=== 成功导入的数据 ===\n([\s\S]*?)\n=== 数据输出结束 ===/); if(jsonMatch && jsonMatch[1]){ try{ const records = JSON.parse(jsonMatch[1].trim()); if(records.length > 0){ - // 保存到本地历史记录(仅用于本地显示) saveToHistory(records); - - // 重新从服务器加载数据并显示 - const listEl = document.getElementById('mac-list'); - if(listEl){ - try { - const serverData = await API.listMac(); - if(serverData.list && serverData.list.length > 0){ - const platformNames = {pdd: '拼多多', yt: '圆通', tx: '兔喜'}; - - // 按时间和机种分组统计 - const uploadGroups = {}; - serverData.list.forEach(r => { - const date = new Date(r.ts).toLocaleDateString('zh-CN'); - const platform = platformNames[r.platform] || r.platform || '未知'; - const key = `${date}_${platform}`; - - if (!uploadGroups[key]) { - uploadGroups[key] = { - date: date, - platform: platform, - count: 0, - firstTime: r.ts - }; - } - uploadGroups[key].count++; - }); - - // 转换为数组并按时间排序 - const groupArray = Object.values(uploadGroups) - .sort((a, b) => new Date(b.firstTime) - new Date(a.firstTime)); - - listEl.innerHTML = groupArray.map(g => { - return `
        • -
          -
          ${g.date}
          -
          上传 ${g.count} 条记录
          -
          -
          - ${g.platform} -
          -
        • `; - }).join(''); - - API.toast(`成功上传 ${records.length} 条记录`); - } - } catch(e) { - console.error('刷新列表失败:', e); - } - } + API.toast(`成功上传 ${records.length} 条记录`); } }catch(e){ console.error('解析上传记录失败:', e);