From 290d9eccf6c9cf3e0d7c7b9c03b16ad89af17815 Mon Sep 17 00:00:00 2001 From: zzh Date: Sat, 22 Nov 2025 09:53:18 +0800 Subject: [PATCH] =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E7=BB=86=E8=8A=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FPY_FEATURE.md | 116 ---------------------- MEMORY_OPTIMIZATION.md | 160 ------------------------------- NOTIFICATION_DEBUG.md | 130 ------------------------- NOTIFICATION_SYSTEM.md | 94 ------------------ frontend/js/components/upload.js | 32 ++++++- server/app.py | 8 +- shipments_merge_cells_guide.md | 139 --------------------------- shipments_redis_structure.md | 100 ------------------- shipments_template_example.md | 62 ------------ 9 files changed, 34 insertions(+), 807 deletions(-) delete mode 100644 FPY_FEATURE.md delete mode 100644 MEMORY_OPTIMIZATION.md delete mode 100644 NOTIFICATION_DEBUG.md delete mode 100644 NOTIFICATION_SYSTEM.md delete mode 100644 shipments_merge_cells_guide.md delete mode 100644 shipments_redis_structure.md delete mode 100644 shipments_template_example.md diff --git a/FPY_FEATURE.md b/FPY_FEATURE.md deleted file mode 100644 index a6b92e5..0000000 --- a/FPY_FEATURE.md +++ /dev/null @@ -1,116 +0,0 @@ -# 直通良品率(FPY)功能说明 - -## 功能概述 - -新增了直通良品率(First Pass Yield, FPY)统计功能,用于追踪首次通过测试的产品数量。 - -## 什么是直通良品率? - -**直通良品率(FPY)** = 首次通过测试的产品数量 / 总生产数量 × 100% - -- **直通良品**:首次测试就通过的产品 -- **良品**:包括首次通过和返修后通过的所有合格产品 -- **不良品**:测试未通过的产品 - -### 示例 -假设生产了100个产品: -- 80个首次测试通过(直通良品) -- 15个首次测试失败,返修后通过 -- 5个无法修复 - -则: -- **直通良品率** = 80/100 = 80% -- **总良品率** = (80+15)/100 = 95% -- **不良率** = 5/100 = 5% - -## 功能实现 - -### 1. 数据库变更 -在 `stats` 表中新增 `fpy_good` 字段: -```sql -ALTER TABLE stats ADD COLUMN fpy_good INTEGER DEFAULT 0 -``` - -### 2. 仪表盘显示 -在仪表盘顶部新增"直通良品率"卡片,显示在"良品率"之前: -- 直通良品率 -- 良品率 -- 发货数量 -- 不良数量 - -### 3. 上传页面 -在"良/不良统计"上传页面新增"直通良品数量"输入框: -- 直通良品数量(新增) -- 良品数量 -- 不良数量 -- 不良明细(可选) - -### 4. API变更 - -#### 后端API -- `GET /api/dashboard` - 返回 `fpyRate` 字段 -- `POST /api/upload/stats` - 接受 `fpy_good` 参数 -- `GET /api/overview` - 返回 `fpyGoodTotal` 字段 -- `GET /api/list/stats` - 返回 `fpy_good` 字段 - -#### 前端API -- `API.uploadStats({fpy_good, good, bad, details})` - 上传时包含直通良品数 - -## 使用方法 - -### 1. 上传统计数据 -1. 进入"数据上传" -> "良/不良统计" -2. 填写: - - 直通良品数量:首次测试通过的数量 - - 良品数量:所有合格产品数量(包括返修后合格的) - - 不良数量:测试失败的数量 -3. 点击"上传" - -### 2. 查看统计 -在仪表盘可以看到: -- **直通良品率**:反映生产质量的稳定性 -- **良品率**:反映最终产品的合格率 - -## 计算公式 - -```javascript -// 直通良品率 -fpyRate = (fpy_good / (good + bad)) × 100% - -// 总良品率 -goodRate = (good / (good + bad)) × 100% -``` - -## 数据关系 - -``` -总生产数 = 良品数 + 不良数 -良品数 = 直通良品数 + 返修后合格数 -直通良品数 ≤ 良品数 ≤ 总生产数 -``` - -## 注意事项 - -1. **直通良品数不能大于良品数**:系统不会强制校验,请确保数据准确 -2. **历史数据兼容**:旧数据的 `fpy_good` 默认为 0 -3. **显示逻辑**:如果没有数据,显示为"—" -4. **通知功能**:上传时会通知超级管理员,包含直通良品数 - -## 业务价值 - -1. **质量监控**:直通良品率越高,说明生产过程越稳定 -2. **成本控制**:减少返修可以降低成本 -3. **流程优化**:通过对比直通良品率和总良品率,识别返修环节的效率 -4. **趋势分析**:长期追踪直通良品率变化,发现质量问题 - -## 示例数据 - -| 日期 | 直通良品 | 良品 | 不良 | 直通良品率 | 总良品率 | -|------|---------|------|------|-----------|---------| -| 2025-01-01 | 80 | 95 | 5 | 80% | 95% | -| 2025-01-02 | 85 | 92 | 8 | 85% | 92% | -| 2025-01-03 | 90 | 96 | 4 | 90% | 96% | - -从上表可以看出: -- 直通良品率在提升(80% → 85% → 90%),说明生产质量在改善 -- 总良品率保持在高位(95%左右),说明返修环节有效 diff --git a/MEMORY_OPTIMIZATION.md b/MEMORY_OPTIMIZATION.md deleted file mode 100644 index 1865bd8..0000000 --- a/MEMORY_OPTIMIZATION.md +++ /dev/null @@ -1,160 +0,0 @@ -# 内存优化说明 - -## 优化内容 - -### 1. Dashboard 组件资源清理 - -**清理策略(三重保护):** -- **策略1**: 每5次更新清理一次(约50秒) -- **策略2**: 数据量超过500条时自动清理 -- **策略3**: 超过1分钟强制清理 - -**清理内容:** -- 拼多多和圆通审计数据缓存 -- Canvas 画布内容 -- 趋势图数据对象 -- 触发浏览器垃圾回收(如果支持) - -**数据过滤:** -- 只缓存最近30天的数据 -- 自动过滤超过30天的旧数据 -- 减少内存占用 - -**日志输出:** -```javascript -console.log('[资源清理] 清理缓存数据,更新次数:', count, '数据量:', pddLength, ytLength); -``` - -### 2. Upload 组件事件监听器管理 - -**问题:** -- 每次渲染页面都添加新的事件监听器 -- 旧的监听器没有被移除 -- 导致内存泄漏 - -**解决方案:** -- 创建统一的事件监听器管理系统 -- 使用 `addListener()` 替代 `addEventListener()` -- 页面切换时自动清理所有监听器 - -**实现:** -```javascript -const eventListeners = []; -const addListener = (element, event, handler) => { - if(element){ - element.addEventListener(event, handler); - eventListeners.push({element, event, handler}); - } -}; -const cleanupListeners = () => { - eventListeners.forEach(({element, event, handler}) => { - element.removeEventListener(event, handler); - }); - eventListeners.length = 0; -}; -``` - -### 3. 内存监控工具 - -**功能:** -- 实时监控 JavaScript 堆内存使用情况 -- 每10秒输出一次内存状态 -- 内存使用超过70%时发出警告 - -**使用方法:** -```javascript -// 开发环境自动启动 -// 生产环境手动启动 -MemoryMonitor.start(10000); // 每10秒监控 - -// 查看当前内存状态 -MemoryMonitor.logCurrent(); - -// 停止监控 -MemoryMonitor.stop(); -``` - -**输出示例:** -``` -[内存监控] 使用: 45.23 MB / 2048.00 MB (2.21%) -[内存警告] 内存使用率超过70%,建议清理资源 -``` - -## 监控方法 - -### 浏览器开发者工具 - -1. **打开控制台**:F12 → Console -2. **查看内存日志**: - - `[资源清理]` - 缓存清理日志 - - `[内存监控]` - 内存使用情况 - - `[内存警告]` - 内存使用过高警告 - -3. **性能监控**:F12 → Performance - - 点击 Record 开始录制 - - 使用应用一段时间 - - 停止录制查看内存曲线 - -4. **内存快照**:F12 → Memory - - 选择 Heap snapshot - - 拍摄快照对比内存变化 - -### 手动测试 - -```javascript -// 在控制台执行 -MemoryMonitor.logCurrent(); - -// 查看缓存状态 -console.log('Dashboard缓存:', window.__auditCache); - -// 查看定时器 -console.log('定时器ID:', window.__auditTimer); -``` - -## 预期效果 - -### 优化前 -- 内存持续增长 -- 30秒清理无明显效果 -- 长时间使用后内存占用过高 - -### 优化后 -- 内存使用稳定在合理范围 -- 每50秒或数据量达到500条时自动清理 -- 超过1分钟强制清理 -- 只保留最近30天数据 -- 事件监听器正确清理 - -## 注意事项 - -1. **浏览器支持**: - - `performance.memory` API 仅在 Chrome/Edge 中可用 - - Firefox/Safari 不支持此 API - -2. **垃圾回收**: - - `window.gc()` 需要浏览器启动时添加 `--js-flags="--expose-gc"` 参数 - - 正常情况下浏览器会自动进行垃圾回收 - -3. **开发环境**: - - 内存监控工具在 localhost 自动启动 - - 生产环境需要手动启动 - -## 调整参数 - -如需调整清理策略,修改 `frontend/js/components/dashboard.js`: - -```javascript -// 修改清理条件 -const shouldClean = cache.updateCount >= 5 || // 改为10次 - (cache.pdd && cache.pdd.length > 500) || // 改为1000条 - (now - cache.lastClean > 60000); // 改为120000(2分钟) -``` - -## 测试建议 - -1. 打开浏览器控制台 -2. 进入 Dashboard 页面 -3. 观察内存监控日志 -4. 等待约1分钟查看清理日志 -5. 切换到其他页面,确认定时器已停止 diff --git a/NOTIFICATION_DEBUG.md b/NOTIFICATION_DEBUG.md deleted file mode 100644 index a548526..0000000 --- a/NOTIFICATION_DEBUG.md +++ /dev/null @@ -1,130 +0,0 @@ -# 通知系统调试指南 - -## 已修复的问题 - -### 1. 铃铛无法点击问题 -**原因:** -- 仪表盘页面有复杂的Canvas元素和图表,可能遮挡铃铛按钮 -- z-index层级设置不够高 -- 事件可能被其他元素捕获 - -**解决方案:** -- 提高铃铛按钮的z-index到999 -- 提高通知面板的z-index到1000 -- 给content-header添加z-index:10 -- 给#actions容器添加z-index:999 -- 徽章设置pointer-events:none,避免阻挡点击 -- 铃铛按钮设置pointer-events:auto,确保可点击 - -### 2. 点击铃铛没有弹出面板 -**原因:** -- 通知系统可能被多次初始化,导致事件监听器混乱 -- 事件监听器可能被重复绑定 - -**解决方案:** -- 添加isInitialized标志,防止重复初始化 -- 使用cloneNode()方法移除旧的事件监听器 -- 添加详细的console.log调试信息 -- 在togglePanel中添加元素存在性检查 - -### 3. 时间显示问题 -**原因:** -- 后端使用UTC时间,前端显示时差8小时 - -**解决方案:** -- 后端notify_superadmin()使用北京时间(UTC+8) -- 前端正确解析ISO格式的时间字符串 - -## 调试方法 - -### 1. 检查铃铛是否显示 -打开浏览器控制台,查看是否有以下日志: -``` -[Notifications] 铃铛已显示 -[Notifications] 初始化完成 -``` - -### 2. 检查点击事件 -点击铃铛时,应该看到: -``` -[Notifications] 铃铛被点击 -[Notifications] 面板状态: 打开 -``` - -### 3. 检查元素层级 -在浏览器开发者工具中: -1. 检查#notification-bell的z-index是否为999 -2. 检查#notification-panel的z-index是否为1000 -3. 检查.content-header的z-index是否为10 -4. 检查#actions的z-index是否为999 - -### 4. 检查CSS样式 -确认以下样式已应用: -```css -.notification-bell { - z-index: 999; - pointer-events: auto; -} - -.notification-badge { - z-index: 1000; - pointer-events: none; -} - -.notification-panel { - z-index: 1000; -} - -.content-header { - z-index: 10; -} - -#actions { - z-index: 999; -} -``` - -### 5. 手动测试 -在浏览器控制台执行: -```javascript -// 检查铃铛元素 -const bell = document.getElementById('notification-bell'); -console.log('铃铛元素:', bell); -console.log('铃铛样式:', window.getComputedStyle(bell)); - -// 检查面板元素 -const panel = document.getElementById('notification-panel'); -console.log('面板元素:', panel); -console.log('面板显示:', panel.style.display); - -// 手动触发点击 -bell.click(); -``` - -## 常见问题 - -### Q: 铃铛显示了但点击没反应 -A: 检查浏览器控制台是否有错误信息,确认事件监听器已绑定 - -### Q: 面板打开了但看不到 -A: 检查z-index是否被其他元素覆盖,或者面板位置是否在屏幕外 - -### Q: 时间显示还是不对 -A: 确认服务器时区设置,检查后端是否使用了北京时间 - -### Q: 在某些页面可以点击,某些页面不行 -A: 检查该页面是否有特殊的z-index或overflow设置 - -## 性能优化 - -1. **防止重复初始化**:使用isInitialized标志 -2. **移除旧事件监听器**:使用cloneNode()方法 -3. **定时器管理**:在cleanup时清理定时器 -4. **避免内存泄漏**:在页面切换时调用cleanup - -## 代码改进点 - -1. 添加了详细的日志输出,方便调试 -2. 添加了元素存在性检查,避免空指针错误 -3. 使用e.preventDefault()和e.stopPropagation()防止事件冒泡 -4. 提高了z-index层级,确保在所有页面都能正常显示 diff --git a/NOTIFICATION_SYSTEM.md b/NOTIFICATION_SYSTEM.md deleted file mode 100644 index c115bcd..0000000 --- a/NOTIFICATION_SYSTEM.md +++ /dev/null @@ -1,94 +0,0 @@ -# 消息通知系统使用说明 - -## 功能概述 - -为超级管理员账号添加了消息通知系统,可以实时查看其他用户的操作记录。 - -## 主要特性 - -### 1. 消息铃铛 -- 位置:页面右上角(仅超级管理员可见) -- 红色圆点徽章:显示未读消息数量 -- 点击铃铛:打开/关闭消息面板 - -### 2. 消息面板 -- 显示最近100条操作通知 -- 未读消息有蓝色圆点标记和高亮背景 -- 点击单条消息:标记为已读 -- "全部已读"按钮:一键标记所有消息为已读 -- "删除已读"按钮:删除所有已读消息(需确认) - -### 3. 自动更新 -- 每30秒自动刷新未读消息数量 -- 实时显示最新的用户操作 - -### 4. 时间显示 -- 使用北京时间(UTC+8) -- 智能显示:刚刚、X分钟前、X小时前、X天前 -- 超过7天显示完整日期时间 - -## 会触发通知的操作 - -以下操作会为超级管理员创建通知: - -1. **批量上传MAC文件** - 显示上传类型(pdd/yt/tx) -2. **批量上传发货记录文件** - 显示箱数和总数量 -3. **添加人员信息** - 显示姓名和角色 -4. **上传发货记录** - 显示日期和数量 -5. **上传MAC与批次** - 显示记录数量 -6. **批量上传不良明细文件** - 显示记录数量 -7. **上传返修记录** - 显示数量 -8. **上传良/不良统计** - 显示良品和不良品数量 -9. **上传不良明细** - 显示记录数量 - -## 通知内容 - -每条通知包含: -- **用户名**:执行操作的用户 -- **操作类型**:执行的具体操作 -- **详细信息**:操作的详细数据(如数量、日期等) -- **时间**:操作时间(智能显示:刚刚、X分钟前、X小时前等) - -## 技术实现 - -### 后端 -- 新增 `notifications` 数据表 -- 新增 `notify_superadmin()` 函数,在关键操作点调用,使用北京时间 -- 新增 5 个 API 端点: - - `GET /api/notifications` - 获取通知列表 - - `GET /api/notifications/unread-count` - 获取未读数量 - - `POST /api/notifications/mark-read` - 标记单条已读 - - `POST /api/notifications/mark-all-read` - 标记全部已读 - - `POST /api/notifications/delete-read` - 删除所有已读消息 - -### 前端 -- 新增 `notifications.js` 组件 -- 在 `index.html` 添加铃铛和通知面板 -- 在 `styles.css` 添加通知相关样式 -- 在 `app.js` 集成通知系统初始化 - -## 使用方法 - -1. 使用超级管理员账号登录系统 -2. 在页面右上角可以看到消息铃铛图标 🔔 -3. 当有新消息时,铃铛上会显示红色数字徽章 -4. 点击铃铛查看消息列表 -5. 点击单条消息标记为已读 -6. 点击"全部已读"按钮标记所有消息为已读 -7. 点击"删除已读"按钮清理已读消息(需确认) - -## 注意事项 - -- 只有超级管理员(role='superadmin')才能看到消息铃铛 -- 超级管理员自己的操作不会创建通知 -- 通知数据存储在 SQLite 数据库中 -- 消息列表最多显示最近100条记录 -- 所有时间使用北京时间(UTC+8) -- 删除已读消息操作不可恢复,请谨慎操作 - -## 修复的问题 - -### v1.1 更新 -1. **修复时间显示问题**:后端使用北京时间(UTC+8)存储,前端正确解析显示 -2. **修复铃铛无法点击问题**:调整z-index层级,确保铃铛和面板在最上层 -3. **新增删除已读功能**:可以清理已读消息,保持消息列表整洁 diff --git a/frontend/js/components/upload.js b/frontend/js/components/upload.js index 0f9f5f8..b52af7f 100644 --- a/frontend/js/components/upload.js +++ b/frontend/js/components/upload.js @@ -63,8 +63,9 @@ const Upload = (() => { async function renderMac(){ return section('MAC与批次(MAC与批次对应关系表)',`
- +