Commit Graph

56 Commits

Author SHA1 Message Date
0b982d192c feat(mobile): 移动端补齐出库单据页(领料 / 报废 / 删除)
PC 端早就能挂出库物料,但移动端一直没有入口 —— 只能看,一线的人(生产领料、
测试补料)反而够不着。

- 产品详情页的产品信息卡底部加「出库单据 N 张单 / M 条料」入口,常显不隐藏:
  以前没内容时整块消失,用户根本不知道有这功能。
- 新增「出库单据」页与「选择 MOM 出库物料」页,与 PC 端同一套数据源、
  同一套接口、同一形态(按出库单号分组 + 点开展开明细)。
- 挂载不需要先选任务:任务只是溯源(记 added_by),展示/报废/删除一律按设备走。
- 代挂确认:勾了不是自己领的单时先拦一道。★ 这是**提示**不是权限 ——
  料的归属是设备不是人,代挂是合理操作(测试替生产补挂、库管代录)。
  ⚠️ 判据是 MOM 的 consumer_name 与登录人姓名比对,比错也只是多让用户勾一下。
- navigateTo / navigateBack 失败在 uni 里是**静默**的(只留一行 warning),
  用户看到的就是「点了没反应」。全部补 fail 回调弹窗。
2026-09-23 15:18:06 +08:00
42c883fe7d feat: 移动端直接完结入口、权限与派发解绑
【直接完结入口(双重门槛)】
- 转交弹窗新增「🏁 直接完结」选项,与「入库」互斥
- 角色门槛:仅超管 / 主管可见可操作(与后端 ADMIN_ROLES 对齐,两个角色都判 ——
  本文件既有的 canEditOverallStatus 只判了 SUPER_ADMIN 漏了 SUPERVISOR)
- 场景门槛:新增 showFinishDirect,要求产品确实是「已出库」。普通生产设备若被
  直接完结,既无下游任务、又不在仓库池,会变成卡在工人名下的孤儿数据
- transferMode 的 direct 分支同步校验双门槛,防残留选中态把 finish_directly 发出去

【修复售后"鸡生蛋"死锁】
- 已出库设备的下拉工序改走售后词表:taskOptionsFor 增加 overall_status 入参,
  已出库与 AFTER_SALES 同等待遇。此前只认 lifecycle_phase,而上一轮已禁止后端
  因"正常已出库做质检"翻转该阶段 → 工人选不到工序 → 进不了售后 → 更选不到

【派发入口与仓库位置解绑】
- 原条件硬性要求 current_location_id === 'virtual_warehouse',直接完结后的设备
  位置停在最后经手人名下,派发入口彻底消失,产品再也无法流转
- 新增豁免:产品空闲(无活跃主线任务)+ 超管/主管即可派发;新增 hasActiveMainTask
  只算主干,协助分支(SPAWN)不阻塞派发
- 文案与图标按场景动态化(在仓库 / 任务已完结)

【顺带修复】
- isWarehouseTransfer 死标志位:openWarehouseTransfer 先置 true,紧接着调用的
  openCreateFirstTask 又立刻重置为 false,导致弹窗标题永远显示「发起首道工序」,
  仓库转出文案从未生效。改为在 openCreateFirstTask 内按产品实际位置推导
2026-09-17 17:06:00 +08:00
1e6c006360 feat: MES/MOM 出入库状态解绑与直接完结通道(后端契约 + 移动端)
- TaskTransferRequest 新增 finish_directly 开关:闭环当前任务但不产生任何下游任务,
  产品 overall_status 保持原样,工人无需再借道「入库(virtual_warehouse)」来关闭任务,
  从根源上避免产品被误标「待仓库收货」而卡住 MOM 对账
- 空 assignees 分支加防呆校验:想直接完结必须显式传 finish_directly=true,
  杜绝漏填导致「转交」静默退化成「直接完结」的丢件级隐患
- 直接完结跳过 _mark_after_sales_if_reactivated:不产生新任务即不构成「回流返厂」信号,
  否则已出库设备的正常收官会把产品误翻成售后机(该标志单向不可回退)
- 补齐直接完结的独立响应文案,不再拼出「已创建 0 个下一道工序任务「None」」
- 移动端转交弹窗改为「转交个人 / 入库 / 直接完结」三选一互斥
2026-09-17 14:07:02 +08:00
7fca315ff4 feat: 图片上传抽离公共模块,统一成功角标并修复记录拍照无法删除
上传模块 utils/upload.js(新增)
此前 detail.vue 与 records.vue 各写一份 uni.uploadFile 封装,超时与并发策略
容易漂移,且都是串行上传 —— 9 张图排队一张张传完,弱网下工人要干等半分钟。
- uploadImage:单张上传,UPLOAD_TIMEOUT 防弱网永久挂起;非 2xx 时后端返回的
  是 {detail:...} 而非 {url},必须当失败处理,否则图片被静默丢弃
- uploadImages:有界并发池(并发 3),onEachDone 对每张图恰好回调一次,
  成功与失败都精确回收一个 ⏳ 占位符
- isUploadedUrl:判定「是否已真正上传成功」。成功 resolve 的是后端 URL
  (/api/v1/upload/files/… 或 http(s)://),未完成的拿到的是本地临时地址
  (blob: / file:// / _doc/ / wxfile://)

上传成功绿勾角标
- 应用到 detail.vue(记录表单 + 驳回表单)与 records.vue(编辑记录弹窗)
- 角标仅在 isUploadedUrl 判定为真时渲染;⏳ 占位与失败项结构上不可能出现
  角标,因为角标只存在于「已上传」的那个循环里
- 圆角与裁剪改由 .success-badge-wrapper 负责,图片只负责填满

修复:记录/拍照里已选图片无法删除
删除按钮原为 v-if="canDeleteImage",而该项在「任务已定稿
(COMPLETED/REJECTED/ARCHIVED/CANCELED)」或「非本人任务」时返回 false。
但 handleTaskAction 里 type === "record" 是无条件打开弹窗的,工人完全可能
在已完成任务上打开「记录/拍照」,于是刚选、尚未提交的图也被一并锁死 ——
那些图只存在于内存里,删掉不产生任何服务端影响。

- 新增 recordForm.savedCount(打开弹窗时已落库的张数),
  新增 canDeleteRecordImage(i) = canDeleteImage || i >= savedCount:
  本次新选的图永远可删,已落库的才受「任务已定稿」约束
- 未落库的图免去 5 秒倒计时 —— 该机制本是为不可逆的服务器删除设计的,
  刚选错的图重拍一张即可,没必要卡 5 秒
- openEditRecord 由 images: record.images || [] 改为 saved.slice():
  原先按引用赋值,删图会直接改动底层记录对象,此时点「取消」被删的图
  在本地列表里也已经没了
2026-09-15 15:51:44 +08:00
6b3f14e8fd fix: 移动端驳回支持传图、422 报错可读化、修复详情页图片破图
车间的驳回操作不再强制拍照(编号错误等场景无需照片),移动端同步放开。

- utils/request.js: 新增 extractErrorDetail 统一解析后端 detail 的三种形态
  (字符串 / FastAPI 校验错误数组 / 对象),新增 422 拦截分支,并把
  400/403/409 及兜底分支的 `res.data?.detail || x` 全部换掉 —— 原写法在
  detail 是数组时会把整个数组丢给 showToast,弹出 [object Object]
- pages/scan/detail.vue: 驳回弹窗新增与「追加记录」一致的选图/传图 UI,
  doReject 携带 { reason, images }(允许空数组);选图上传流程抽成通用的
  pickAndUploadImages,与追加记录共用
- pages/scan/detail.vue: 新增 imageUrl() 补全后端返回的相对路径
  (/api/v1/upload/files/xxx.jpg 直接给 <image> 会破图),缩略图渲染与
  previewImage 预览均已接入;逻辑与 records.vue / TaskTreeNode.vue 对齐
2026-09-15 10:57:49 +08:00
31d085881b feat: 移动端工序选项隔离与售后标签 2026-09-14 14:49:38 +08:00
e194b97649 fix: 全状态对齐 - 已出库(OUTBOUND)覆盖所有看板
- 看板产品流转 finished_cond 加'已出库',已出库归入已完结
- WIP 矩阵区分'已出库'维度
- MyTasksPage tab 加'已出库'
- 移动端 detail/WorkspaceArea STATUS_MAP 补 OUTBOUND
2026-09-02 09:07:37 +08:00
cf2609d87a feat: Track 移动端状态展示与流转树全览改造
- 宏观状态栏补已入库/已出库语义色;OVERALL_OPTIONS 补已入库/已出库
- 在库任务'转入在库'显示实际操作人(assignee);补 OUTBOUND 状态色
- 流转树全览(TreeCanvas)由可移动 canvas 改为纵向递归树,复用 TaskTreeNode
2026-09-01 13:53:35 +08:00
d5315cb9a1 fix(APP): 撤回转交也加入5秒倒计时确认
- 撤回转交与其他破坏性操作(删除/结束分支/驳回)一致,确认前需5秒等待防误触
2026-08-28 12:12:27 +08:00
8537bce30c fix(APP): 倒计时期间确认按钮禁用虚化 + 收窄倒计时范围
- 5秒倒计时期间确认按钮虚化禁用(点不了),只有取消可用,倒计时结束按钮解锁再点击才执行
- 收窄范围:仅 删除记录/删除图片/结束分支/驳回 保留5秒等待;接收/转交/派发/保存/创建/撤回转交 恢复直接确认
2026-08-28 12:05:13 +08:00
5f8eeda818 fix(APP): 操作确认改为5秒倒计时双重确认,杜绝误触
- 接收/驳回/转交/派发/保存记录/创建首道工序 确认按钮:首次点击进入5秒倒计时,期间再点=取消反悔,倒计时结束再点才执行
- 结束分支/撤回转交/删除记录/删除图片:改为自定义倒计时确认弹窗,替换 uni.showModal(APP端原生弹窗取消行为异常)
- 修复 canDeleteImage 权限误判(严格===只比username→宽松双向比较),负责人不再看不到删图按钮
- 页面卸载清理定时器;操作失败增加错误提示消除静默
2026-08-28 11:49:43 +08:00
3288223a92 refactor(mobile): 移动端上传/展示去 IP 化,统一公网域名并支持 NODE_ENV 环境感知 2026-08-13 10:34:56 +08:00
1fdc607c07 feat: 管理员代工模式 — 前端权限放开 + 后端审计留痕
前端:
  - WorkspaceArea 新增 currentUserRole prop
  - isAssignee/canRecall: SUPER_ADMIN/SUPERVISOR 上帝视角直接放行
  - 管理员代操作时显示黄色提示条: 正在以管理员身份代[原负责人]操作
  - detail.vue: loadCurrentUser 提取并保存 user.role

后端:
  - _create_task_log 新增 task_assignee_id 参数
  - operator_id!=task_assignee_id 时自动拼接 [管理员xx代办操作]
  - 12处调用点全部传入 task_assignee_id
  - receive_task 位置赋值确认为 task.assignee_id(非 operator_id)
2026-08-12 15:24:50 +08:00
8e8d23010f fix: 留言板未读数退出重进后重置 — lastMsgSeenAt持久化到storage 2026-08-12 13:16:11 +08:00
3cb85f28b4 fix(frontend): 宏观状态前端UX重构 — 非权限人员隐藏箭头+拦截点击
1. 新增 canEditOverallStatus computed:
   - SUPER_ADMIN 直接放行
   - 递归遍历 task_tree,仅 WIP/PENDING 主线任务负责人有权
   - 严格对齐后端 update_overall_status 的 main_task 判断

2. handleOverallBarClick 增加权限拦截:
   无权限点击 → Toast '仅超级管理员或当前主线负责人可修改状态'

3. overall-arrow 增加 canEditOverallStatus 条件:
   无权限用户不显示 ▾ 箭头,视觉上明确不可操作
2026-08-11 17:48:51 +08:00
0a1c2f4dcf fix(frontend): 打印按钮被挤出画面 — card-header 防溢出
根因: card-header 一行塞入 4 个元素(标题+3按钮),
      card-header-right 无 flex-wrap/无 flex-shrink,
      窄屏上打印标签按钮溢出视口不可见。

修复:
- card-header-right: gap 8→4, 加 flex-wrap, flex-shrink:0
- 所有子元素: flex-shrink:0 + white-space:nowrap
- mode-toggle/print-label-btn: 缩小字号+padding节省空间
2026-08-11 16:07:19 +08:00
40a2d87345 fix: 消息通知页不能点进详情 — 补全 product_serial_number
问题: 点击通知卡片跳转 detail?taskId=xxx,但 detail.vue onLoad 只认 serial 参数导致空白页

修复:
1. 后端 NotificationResponse 新增 product_serial_number 字段
2. 后端 notifications API 联表 tasks+products 批量填充 serial
3. 前端 notify/index.vue handleCardTap 优先用 product_serial_number 跳转,兜底从 content 正则解析
4. 前端 detail.vue onLoad 新增 taskId 兜底 → doQueryByTask 反查 product_sn
2026-08-11 15:56:25 +08:00
30a48d90fc fix(frontend): 流转蓝图 + 聊天室 + 卡片布局 + 打印功能修复
1. TreeCanvas.vue - Y轴坐标算法重构:
   - calcSubtreeHeight 改为兄弟累加 (reduce) 替代 Math.max,彻底杜绝垂直重叠
   - childNode.y = parentNode.y + CARD_H + VERTICAL_GAP 严格向下延伸
   - 同级子节点按子树高度累加 startY,各占独立 Y 区域
   - 加宽画布默认尺寸 (400→800, padding +300/+400)

2. detail.vue - onShow 生命周期修复:
   - 新增 onShow() 钩子调用 fetchMessages(),解决聊天室退回不刷新问题

3. TaskSwipeCards.vue + detail.vue - CSS 防跳动:
   - .ss-swiper-h / .ss-card-wrapper 添加 min-height: 220px
   - .card 添加 min-height: 120px

4. detail.vue - 移动端打印标签:
   - 新增「🖨️ 打印标签」按钮
   - 双方案 ActionSheet: 网络打印机(后端API) / 蓝牙打印机(ESC/POS)
   - 对接现有 /print/execute 端点
2026-08-11 15:05:39 +08:00
6755dfeae3 feat(mobile): 登录修复 + 人名字典 + 留言板FAB + 流转算法重构
- login: catch补齐toast,修复密码错误静默失败
- detail: formatUserName渲染当前位置,dictVersion驱动响应式重绘
- detail: 留言板改为悬浮按钮+底部抽屉,未读徽标逻辑
- TaskSwipeCards: lanes终极递归算法,SPAWN不限层级开辟新Tab,先序push修复Tab顺序
- TreeCanvas: 父子相对坐标延伸算法,替代旧版奇偶距离递增
2026-08-11 10:02:12 +08:00
567f7175da fix: :key 强制子组件重建 + 拆除嵌套滚动锁
- detail.vue: 新增 dictVersion,loadUsers 后自增驱动子组件 :key 重建
- WorkspaceArea/TaskSwipeCards/TreeCanvas 绑定 :key='...-'+dictVersion
- .page-container: flex → block,让页面自然流式撑开
- .workspace-area: flex:1+overflow:hidden → height:auto
- .is-locked: 仅锁定任务模式下才 height:100vh+overflow:hidden
- .task-list: flex:1+overflow-y:auto → height:auto
2026-08-10 18:08:13 +08:00
051a075e9d fix: 留言板层级修复 + 人名映射防降级
- 留言板移除 currentMode 限制,产品级功能所有模式可见
- .page-container: min-height + overflow-y:auto 替代 height:100vh + overflow:hidden
- loadUsers 加 console.error 日志 + $forceUpdate 防字典空窗期
2026-08-10 17:56:47 +08:00
f9451b104b feat: 移动端全局人名映射 + 协同留言板 UI
- detail.vue: 留言板聊天室 UI + 乐观更新 + loadUsers 填充全局字典
- WorkspaceArea.vue: 任务列表/上游/下游负责人全部走 formatUserName
- TreeCanvas.vue: 节点负责人 + 嵌套协助提示走 formatUserName
- TaskSwipeCards.vue: 卡片负责人走 formatUserName
- 留言板头像取中文名末字(formatUserAvatar)
2026-08-10 17:37:25 +08:00
b834b24c24 fix: 已完成/已驳回/已入库/已撤回任务禁止编辑删除记录 2026-08-07 16:48:12 +08:00
0df7215134 feat: 移动端双Token队列拦截器 + 通知列表 + 登录页 + TabBar红点 + v1.0.1 2026-08-07 11:44:20 +08:00
616638a6c8 撤回改为CANCELED状态标记+TaskRecord留痕+TreeCanvas灰度渲染+全部状态映射更新 2026-08-06 12:51:40 +08:00
57884d7baa 撤回转交: recall接口删除子任务恢复父WIP + 前端canRecall判断 + 红色撤回按钮 2026-08-06 11:39:22 +08:00
e5bcde667b 转交弹窗互斥+备注必填: 选人清入库/选库清人 + textarea必填校验 2026-08-06 11:23:31 +08:00
ff3de80c96 派发协助备注改为必填(textarea+disabled校验) 2026-08-06 10:08:56 +08:00
999f8c2f3e IRIS过滤容错: 后端SQL失败时降级全量+前端严格过滤department===IRIS 2026-08-06 10:08:18 +08:00
eccf79b8d1 IRIS部门过滤: 后端users接口按department=IRIS过滤 + 前端双重兜底 2026-08-06 10:07:47 +08:00
e183ea5583 工业级重构: 用户Grid选择+工序由接收人定+隐藏结束按钮(次分支卡片内结束)+蓝图网格背景 2026-08-06 09:52:21 +08:00
34347dafb0 清理autoReceive: 删除立即接收开关+新任务强制PENDING等工人自行接收 2026-08-06 09:34:12 +08:00
a0bdce0359 首次扫码防呆: 删除statusPicker强弹+白板产品直接弹发起工序+宏观状态提示未激活 2026-08-06 09:27:15 +08:00
c0feab6be4 UX防呆: 仓库横幅有活跃任务时隐藏 + 宏观状态栏无任务时引导创建 + 创建任务自动切workspace 2026-08-06 09:22:31 +08:00
b00ebd892f 修正: 序列号→身份证, 外部序列号→产品序列号 2026-08-06 09:02:35 +08:00
ae720656b1 全局重命名: 序列号→身份证 (product.serial_number) 2026-08-06 09:00:15 +08:00
3b29bb0bd1 编辑产品加Label + 仓库横幅改为warehouse-transfer-banner + 弹窗标题联动isWarehouseTransfer 2026-08-06 08:42:32 +08:00
c836944f92 新增: 仓库转出功能 — 产品在库时显示📤转出按钮+复用创建任务+更新location 2026-08-06 08:39:06 +08:00
b547844dca 并发模型: spawn派发协助分支 + 转交简化为单线 + 子分支未完成拦截(409) 2026-08-05 18:01:14 +08:00
99eab80a1c 组件化拆分: TreeCanvas(2D画布) + WorkspaceArea(任务列表+锁定工作区) + detail瘦身(仅弹窗) 2026-08-05 17:25:15 +08:00
4c4ed7234d 终极重构: getTaskRemark兜底(record挖掘) + movable-area 2D画布(拖拽+缩放) 2026-08-05 17:22:36 +08:00
16762a8628 修复: remark强制渲染(醒目黄框内联样式) + 画布高度坍塌修复(100%撑满) 2026-08-05 17:02:48 +08:00
1d759f3e8c 流转树2D画布: scroll-view无限拖拽 + 水平分支并排 + 垂直时间轴 + 连线 2026-08-05 16:58:12 +08:00
9aa0687d8c 防呆重构: 废除swiper→任务列表+锁定工作区 + remark醒目显示 + 树视图减少缩进+分支闭环标记 2026-08-05 16:56:52 +08:00
78559db1fa 双模态详情页: workspace(swiper+footer) / tree(只读流转树) 智能分流+一键切换 2026-08-05 16:43:32 +08:00
21aa608db3 工艺节点树: 新增结束分支(终止)接口 + 前端🏁结束分支按钮 + WIP可无下游完结 2026-08-05 16:37:05 +08:00
e2d9590c48 修复remark丢失(_to_response漏字段) + UI重构swiper专注卡片看板 2026-08-05 16:35:14 +08:00
71e8eeb7e8 权限: receive/reject校验assignee_id匹配 + 前端myActiveTask只显示本人任务 + 403处理 2026-08-05 16:21:27 +08:00
62422e7558 全栈: 接收任务写入remark — 后端receive接口+Body参数+前端接收弹窗备注输入 2026-08-05 16:16:35 +08:00
7810097b39 全栈修复: remark字段全链路打通 — TaskCreate+TransferRequest+transfer_task+前端Payload 2026-08-05 15:59:20 +08:00