Commit Graph

40 Commits

Author SHA1 Message Date
dcc92b223e feat: 生产看板多维度重构(全量在制品、时间维度联动、口径提示)
本次只含后端看板接口与 PC 端页面。移动端的体验优化已在之前的 12 个提交中
入库,不在本提交范围内。

后端 · 服务层 dashboard_service.py
- 在制品列表不再按 20 条静默截断:此前 `.limit(limit*2)` 预取再排序切片,
  前端又拿数组长度当总数,表现为「卡片 23、列表却写共 20 个」的数据被吞。
  现默认返回全量,limit 降级为防御性上限
- 产品流转「已完结」接入右上角时间筛选(since/until),废弃硬编码「本月」。
  此前选「今天」也会看到整月产出,业务语义分裂;待流转/流转中仍为实时快照。
  Product 表无 completed_at,以名下工序的完成时间锚定「完结时刻」
- 返工任务可见性:未完结卡点永远展示,已了结的仅限本月,且与卡片数字共用
  同一份条件,避免「按钮显示 2、点开共 0 条」
- 驳回明细的「返工给」改为真实溯源:直接查派生出的返工任务当前 assignee_id,
  不再复刻 reject_task 的推算逻辑(返工任务事后被转交时会显示旧名字)

后端 · 接口层 dashboard.py
- /wip-tasks 的 limit 默认 20→500、上限 100→1000
- /my-stats 支持 since/until,新增接收/转交/上传备注口径(与 PC 人员操作统计
  逐字段交叉验证一致)

PC 端
- AdminDashboard: 在制品计数绑定真实总数并加截断提示、列表改为容器内滚动;
  驳回明细只展示「已驳回」行(返工行不再独立成行,其信息已由「返工给」承载);
  「待流转」「待接收」图例新增口径 Tooltip,消除「产品数 > 任务数」的误解;
  移除已失真的时间筛选提示条
- App.tsx: dayjs 中文 locale 上提到应用根。此前散落在 AdminPeoplePage /
  AnalyticsDashboard 两个页面里,而路由是 lazy 分割的 —— 直接打开概览页时
  那两个模块未加载,日期面板就露出 Sep/Su/Mo
- AdminPeoplePage / AnalyticsDashboard: 移除重复的页面级 locale 设置
- dashboardApi.ts: fetchWipTasks 默认值同步为 500
2026-09-16 14:29:56 +08:00
44ca09ae22 feat: 新增个人效能统计接口 /dashboard/my-stats(支持自选时段)
移动端「个人中心 → 工作统计」的数据源。现有接口拿不到这份数据:
/dashboard/people-history 支持 assignee_id 但只返回 WIP/PENDING/COMPLETED,
不含 REJECTED;/dashboard/rejected-tasks 则根本没有 assignee_id 参数 ——
「今日被驳回数」按现有接口无论如何都过滤不到个人。故补一个薄桥接端点。

服务端 get_my_stats(db, assignee_id, since, until) 返回两组指标:

生产战绩(按 Task.assignee_id 归因)
- tasks_completed / tasks_rejected:status 判定 + completed_at 落在区间,
  与 get_dashboard_stats 的 t_done_q 同一口径,只多了 assignee_id 过滤
- products_touched:按 product_id 去重,同一台设备做多道工序只算一台

操作统计(与 PC /dashboard/user-operations 严格同口径)
- receive/transfer:task_logs 的 receive / complete,按 operator_id 归因
- record:task_records 按 Task.assignee_id 归因,排除 '[' 开头的系统自动备注
- 前两项归因 operator_id、第三项归因 assignee_id 是 PC 端既有口径,
  此处刻意保持一致,便于工人自查的数与主管看到的面板对得上

端点侧新增 _parse_bound():裸时间字符串(无时区偏移)按北京时间解释,
否则会被当作服务器本地时间,边界整体偏 8 小时,出现「选了今日却统计到
昨天下午」。since/until 缺省为「本月 1 日 ~ 此刻」。
2026-09-15 15:51:34 +08:00
f22eae315f fix: 售后回流口径统一 — 状态双字段同步、工序名归一、标签配色
产品存在 overall_status 与 status 两个状态字段,此前各写入点各写一份映射、
甚至只改 overall_status 不改 status,导致回流设备(product.status 停留在
OUTBOUND)污染看板统计口径。

- lifecycle.py: 把映射表收敛为单一来源 overall_to_product_status /
  sync_product_status;新增 normalize_after_sales_step,将售后设备沿用生产
  阶段写法的历史工序名(测试/维修)折算到售后区独立工序名
- product_service.py: 删除本地 _OVERALL_TO_STATUS 副本,改用共享函数
- dashboard_service.py: WIP 矩阵补出 lifecycle_phase 列,活跃任务判定
  (is_active) 提前到所有终结态判定之前,避免残留 OUTBOUND 被误判为完结
- scripts/fix_product_status.py: 历史数据修复脚本(一次性)
- constants/task.ts: 售后工序标签由红色改紫色 —— 红色在本系统是「驳回/危险」
  语义色,售后只是另一条流转支线,用红色会让操作员误以为设备报错
2026-09-15 10:57:29 +08:00
b40340ea55 feat: 产品接口暴露lifecycle_phase并做阶段感知状态校验 2026-09-14 14:49:34 +08:00
7b7dbbb0d8 fix: WIP矩阵-左外连接纳入无任务新品归待接收,PENDING并入待接收,空负责人显式计数为未分配; 表头去待确认列并做TOP N折叠 2026-09-09 17:29:36 +08:00
d757c7985b fix: WIP矩阵口径重构-在制无条件计入,终结态按完工时间锚点(completed_at兜底created_at)过滤,多维终结归类(含扫码入库/出库节点),下钻同步 2026-09-07 14:46:58 +08:00
3019653dfa refactor: 宏观状态统一(待仓库收货/已入库)废弃"在库"; WIP矩阵返回product_name并新增下钻明细 2026-09-02 10:38:49 +08:00
e194b97649 fix: 全状态对齐 - 已出库(OUTBOUND)覆盖所有看板
- 看板产品流转 finished_cond 加'已出库',已出库归入已完结
- WIP 矩阵区分'已出库'维度
- MyTasksPage tab 加'已出库'
- 移动端 detail/WorkspaceArea STATUS_MAP 补 OUTBOUND
2026-09-02 09:07:37 +08:00
73faa1fd93 feat: Track 打通已完成/已入库/已出库状态闭环与外部联动
- 完工转交入库同步 status=COMPLETED;MOM 入库/出库回调同步 status
- 新增 mom-outbound webhook(发货出库标记已出库),lookup 返回 material_id
- VALID_OVERALL_STATUS 新增已出库;update_overall_status 同步 status 字段
- WIP 矩阵区分已入库/待仓库收货;虚拟节点正确处理已出库/转入在库人
2026-09-01 13:53:24 +08:00
0fc061728c fix(透视表): 在库按设备实际位置判断,修复数量不匹配
- 之前按最新主任务 task_name='在库' 判断,漏掉实际在库但无在库任务的历史设备
- 改为 current_location_id='virtual_warehouse' → 在库(生产完成)
- 其他设备按最新主任务工序归属(活跃/完成态都归该工序)
- 在库数量与实际在库设备一致
2026-08-31 17:24:38 +08:00
c3e03bb177 fix(透视表): 不再把任意已完成工序强制归在库
- 设备当前工序 = 最新主任务的工序名(task_name),不区分状态
- 「在库」只在该设备最新主任务真为在库工序时出现
- 完成的测试/生产等工序按原工序显示,不再误归在库
2026-08-28 16:57:02 +08:00
b57ae19b44 fix(透视表): 每台设备只按当前工序统计一次,修复待确认重复计数
- 取每台设备最新主任务作为当前状态
- 活跃任务(WIP/PENDING)→归属对应工序(待确认=转交未接收)
- 完成态任务→归属「在库」(生产完成)
- 上一步已完成+下一步待确认时只算一次,不再重复
- 时间筛选按设备最新主任务创建时间
2026-08-28 16:54:43 +08:00
0dcdb5dad7 fix(透视表): WIP 分布矩阵只统计主分支
- get_wip_matrix 过滤 parent_task_id IS NULL 或 TRANSFER/RECOVERY 的主线任务
- 排除 SPAWN 协助分支与返工任务,避免同一设备/工序重复计数
2026-08-28 16:51:46 +08:00
41dd257260 feat(透视表): 工序分布包含在库/完成 + 增加时间筛选
- wip-matrix 去掉状态过滤,全量分布,工序包含「在库」(生产完成)
- 后端加 since/until 按任务接手/创建时间过滤
- 前端 MatrixBoard 加 RangePicker 日期筛选 + 全部清除
2026-08-28 16:32:01 +08:00
7547a886cc feat(backend): 新增 /dashboard/wip-matrix 在制品交叉聚合接口
- 规格型号×人员/工序 的设备数量聚合(WIP/PENDING任务)
- dimension 参数: assignee(中文姓名)/task_name(工序名)
- 返回扁平数组含 count + assignees(该交叉点主负责人列表)
2026-08-28 16:25:20 +08:00
451e24c34c fix(workload): get_people_workload 内嵌 _to_bj 改用 to_beijing,修复 BEIJING_TZ 未定义
- 移除 import 后内嵌 _to_bj 仍引用 BEIJING_TZ 导致 NameError
2026-08-28 15:13:18 +08:00
bad0941d67 fix(时长): 所有时长计算排除非工作日 + 修复两处时区多算8小时
- get_wip_tasks/get_people_workload/get_people_history/product active_duration_hours/analytics 均改用 working_duration_hours
- 修复 get_wip_tasks 与 active_duration_hours 的 naive 时间误标北京时间 bug(DB实存UTC,原多算8小时)
- 每处读取 holidays 表排除配置的放假日期
2026-08-28 15:08:10 +08:00
7205de369a feat(backend): 新增 /dashboard/user-operations/detail 操作明细下钻接口
- 按人+操作类型(receive/transfer/record)查询明细:任务/产品/备注/时间
- record 明细与该人统计口径一致(名下任务手动备注,排除系统自动)
2026-08-28 13:36:23 +08:00
477a187fc1 fix(操作统计): 上传备注改为按任务负责人归因,历史数据可回溯
- 备注统计不用 task_logs(历史无record日志),改为 task_records 按任务 assignee 归因
- 排除系统自动生成的备注(以'['开头的接收/转交/撤回等),只计手动上传
- 移除 add_task_record 冗余的 record 日志(不再用于统计)
- 不改数据库,历史182条备注也能正确归属到人
2026-08-28 13:26:26 +08:00
41c19242cf fix(操作统计): 返回全部人员而非仅有操作的人
- get_user_operations 先取全部 IRIS 人员清单,再合并各自操作次数
- 无操作的显示 0,避免只看得到当前有操作记录的人(如只看自己)
2026-08-28 13:22:56 +08:00
b85188e625 feat(backend): 新增 /dashboard/user-operations 人员操作统计接口
- add_task_record 补 action_type=record 日志,使上传备注可统计到人
- get_user_operations 按人聚合 接收(receive)/转交(complete)/上传备注(record) 次数,时间筛选,中文名映射
- 复用 get_display_names,不新增数据库字段
2026-08-28 13:14:09 +08:00
90f5718e68 fix(驳回/返工): 抽屉与卡片数字口径一致,同时展示已驳回+返工任务
- 根因:卡片数字含返工任务(tasks_rework 实时快照),但抽屉只列已驳回 → 点开为空
- get_rejected_tasks 扩展返回两类(kind=rejected 按时间过滤 / kind=rework 实时不过滤)
- 前端抽屉按「已驳回」「返工任务」分组展示,数字与明细一一对应
2026-08-28 11:33:54 +08:00
7e00683a21 feat(backend): 新增 /dashboard/rejected-tasks 驳回/返工下钻接口
- RejectedTask schema: 设备/工序/驳回人/返工负责人/原因/时间
- get_rejected_tasks 批量窗口取驳回人(reject log) + 复刻 reject_task 的返工负责人追溯逻辑(create log→父任务→自身)
- 复用 get_display_names 中文名映射、BEIJING_TZ 时间转换
2026-08-28 11:18:58 +08:00
91b1426ccb feat(dashboard): 人员工时台账——平铺明细+多维筛选+时间交集+动态工时+备注+CSV导出 2026-08-13 16:04:23 +08:00
c2e6ed240b feat(dashboard): 看板增强——流转完成率下钻明细 + 人员看板(按人聚合在制品设备) 2026-08-13 12:00:12 +08:00
729de138cd feat: 在制品附加信息补全 — 设备名称|规格型号|序列号|身份证
后端: WipTask 新增 spec_model, 查询关联 Product.spec_model
前端: 第二行格式改为 物料|规格|序列号:xxx|身份证:xxx
2026-08-12 14:43:20 +08:00
9460a8492a feat: 在制品列表信息层级重构 + SLA预警色 + 点击跳转
1. 信息层级重构:
   主信息: [状态Tag] 任务名 | 负责人: 张三  ⏰3h
   附加信息: 物料名 SN:25022 ...A1B2C3  08-12 10:00
   新增后端 material_name 字段, 前端卡片式布局

2. SLA滞留预警色:
   <12h → 绿色(正常) | 12-24h → 橙色(警告) | >24h → 红色加粗(危险)

3. 交互: 点击卡片新窗口打开对应产品扫码详情页
2026-08-12 14:33:56 +08:00
42544d7485 fix: get_wip_tasks 解包错误 — 新增 external_serial 后 rows 变3列但解包仍是2变量 2026-08-12 14:28:00 +08:00
079b65e761 feat: 在制品加业务序列号 + 追溯码改名为身份证
1. 在制品行: 显示 external_serial(业务序列号)
   优先 external_serial → 兜底 product_sn
   旧: 装配 A1B2C3D4  张三
   新: 装配 25022  张三

2. 留言板: 追溯码 → 身份证
   旧: 追溯码: 000000000000000D
   新: 身份证: 000000000000000D

3. 后端: WipTask 新增 external_serial 字段
   关联查询 Product.external_serial
2026-08-12 14:23:23 +08:00
ff7c791d49 fix: 留言板区分业务序列号与系统追溯码
语义修正:
  Product.serial_number  = 16位HEX系统追溯码(如000000000000000D)
  Product.external_serial = 业务产品序列号(如25022)

后端:
  - ProductMessageItem 新增 external_serial 字段
  - search_product_messages 关联查询 Product.external_serial
  - 关键词搜索也支持按 external_serial 匹配

前端显示:
  样品升降台V1J · 序列号: 25022          ← 醒目
  追溯码: 000000000000000D               ← 10px浅灰小字
2026-08-12 14:20:38 +08:00
c14bbeb891 fix: 3个逻辑/UI Bug修复
Bug1 — 任务总数与进度条不匹配:
  tasks_total 从全库历史总数改为 PENDING+WIP+COMPLETED(时段)+REJECTED(时段)
  确保进度条4段之和 = 显示的总数, 不再出现11≠9的缺口

Bug2 — 在制品排序混乱:
  移除DB层order_by, 改为Python统一按duration_hours降序
  无视status, 纯数值排序, 滞留最久排最前
  取limit*2条后在Python中排序再截断

Bug3 — 留言板产品显示割裂:
  [Tag:SN] 物料名 → 物料名 (SN: A1B2C3D4...)
  物料名加粗, SN等宽灰色, 阅读更顺畅
2026-08-12 14:13:26 +08:00
32c234fea1 fix: 在制品按滞留时间降序 + 留言抽屉UI美化
1. 在制品排序: nulls_first → nulls_last
   已接收任务按receipt_at升序(最早=滞留最久)排最前
   未接收任务(null)排最后

2. 留言抽屉UI重设计:
   - 卡片式布局: 彩色头像圆+边框阴影+hover效果
   - 头像颜色按姓名首字自动分配7色
   - Input.Search替代普通Input+Search图标
   - 灰色背景区分卡片, 时间格式改为YYYY-MM-DD HH:mm
   - 手动分页按钮替代Antd分页器
2026-08-12 13:59:39 +08:00
ca195192b6 fix: 协同留言时间改为北京时间
根因: ProductMessage.created_at 使用 datetime.utcnow (UTC),
      与其他所有模型使用的 get_beijing_time 不一致。
      看板留言抽屉显示的时间比实际晚8小时。

修复:
  1. message.py: DateTime → DateTime(timezone=True)
     default 从 datetime.utcnow → get_beijing_time
  2. dashboard_service.py: 兜底转换已有数据
     naive UTC → replace(tzinfo=UTC) → astimezone(Beijing)
2026-08-12 13:55:33 +08:00
3b53db03c1 feat: 看板全局时间筛选 + 协同留言抽屉
任务1 — 后端时间快照逻辑:
  get_dashboard_stats 新增 since/until 参数
  PENDING/WIP/总数 → 永远实时快照(忽略时间筛选)
  COMPLETED/REJECTED → 严格按时段过滤
  完成率基于过滤后的COMPLETED计算

任务2 — 前端时间筛选器:
  Radio.Button: 今天 | 近7天 | 近30天 | 自定义
  DatePicker.RangePicker 自定义区间
  切换时重新拉取 /dashboard/stats

任务3 — 协同留言抽屉:
  后端: GET /dashboard/messages(上帝视角全厂数据)
    JOIN Product → serial_number + material_name
    支持 keyword 搜: SN/物料名/留言人/内容
    按 created_at 倒序
  前端: Drawer + Input.Search + List
    点击"留言"数字打开抽屉
    分页展示: 留言人/内容/SN标签/物料名/时间
2026-08-12 13:50:56 +08:00
39377ae5e4 feat: 看板重构 — 在制品看板 + 留言未读数
核心理念转变:
  旧: 最近操作历史(谁做了什么)
  新: 当前在制品状态(谁的活卡了多久)

后端:
  - DashboardStats 新增 unread_messages(协同留言总数)
  - 新增 GET /dashboard/wip-tasks(在制品端点)
  - 按滞留时间升序排列,PENDING/WIP 任务倒计时
  - 自动计算 duration_hours(已滞留小时数)

前端:
  - 品质卡片: 新增留言未读数(紫色)
  - 在制品看板: 替换原最近动态
    每行显示: 状态徽标 | 任务名+负责人+身份证 | 滞留时长
  - 滞留颜色: 48h+红 | 24h+橙 | 8h+黄 | <8h灰
  - 系统通知可点击跳转
2026-08-12 13:40:08 +08:00
00fae01eed fix: 看板4项体验修复 — 时间/身份证/日期筛选/通知跳转
1. 完整16位产品身份证号显示(不再截断)
2. 日期筛选栏: 今天 | 近7天 | 近30天 | 全部
   - 后端 recent-activity 支持 since/until ISO参数
   - 默认展示今天动态,可按时间范围切换
3. 操作人兜底: TaskLog无operator_id时用任务assignee_id
4. 未读通知可点击跳转通知页面 + 快捷入口增加通知中心
2026-08-12 13:35:23 +08:00
c3f3a5e291 fix: 看板动态时间改为北京时间 + 操作人显示中文姓名
1. 时区修复:
   - database.py: PG连接池会话级设置 TimeZone=Asia/Shanghai
   - dashboard_service.py: 格式化时间显式 astimezone(BEIJING_TZ)
   - 兜底: tzinfo为None时默认当作北京时间处理

2. 操作人中文姓名:
   - 收集所有operator_id → 调用mom_cache批量翻译
   - 优先中文姓名 → 英文用户名兜底
   - operator_id为None时不再显示"系统",留空
2026-08-12 13:28:38 +08:00
658fc28b9b feat: 管理看板全面改版 — 增强可读性 + 填充空白区域
后端增强:
  - DashboardStats 新增 tasks_rejected, tasks_rework, unread_notifications
  - 新增 GET /dashboard/recent-activity 最近动态端点
  - 关联 Task + Product 表返回完整动态信息

前端改版 (AdminDashboard.tsx):
  - 4 张概览卡片: 产品流转 | 任务状态 | 品质通知 | 完成率
  - 每张卡片含进度条(百分比标注) + 中文说明
  - SVG 环形图展示任务完成率
  - 最近流转动态时间线 (8条)
  - 快捷入口: 创建产品/任务管理/打印配置/扫码干活
  - 底部说明卡片解释"产品 vs 任务"的区别
  - 响应式网格填满全屏, 无空白区域
2026-08-12 13:25:49 +08:00
69f3e35d14 fix: Dashboard统计数据修复 + 生产环境SECRET_KEY强制校验
1. Dashboard统计Bug修复
   - Task统计改用TASK_STATUS_PENDING/WIP/COMPLETED大写常量
   - 旧代码使用小写"pending"/"in_progress"永远匹配不到数据
   - 修复后tasks_pending/tasks_in_progress/tasks_completed返回真实值

2. 生产环境SECRET_KEY强制校验
   - 新增model_validator:DEBUG=False且SECRET_KEY为默认值时抛出ValueError
   - 阻止使用默认密钥部署到生产环境
2026-08-12 12:03:07 +08:00
b22de514a1 feat: 实现后端核心业务逻辑 (Auth鉴权、二维码服务、看板与产品端点) 2026-08-04 17:09:47 +08:00