Commit Graph

186 Commits

Author SHA1 Message Date
7e4d796ce3 perf(app): OTA下载进度节流 — 20%步进轻提示根治卡顿
问题: plus.nativeUI.showWaiting 每次下载回调都触发原生等待框更新,
      高频调用导致主线程阻塞产生无响应/掉帧。

修复:
1. 废除 plus.nativeUI.showWaiting 全系列调用
2. 改用 uni.showToast + position:'top' 顶部轻提示
3. 核心: 节流阀 lastProgress — 每跨越20%才触发一次UI更新
   整个下载过程最多5次toast (20/40/60/80/100%),根治跨端卡顿
4. 初始toast '已转入后台下载...' 给用户明确反馈
5. 安装/重启逻辑保持不变(静默安装+2s自动重启)
2026-08-11 18:01:17 +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
b97dfaa95d fix(backend): 宏观状态权限校验 — 根除 current_user 空值绕过漏洞
Bug: if current_user: 在 Python 中 None/空dict均为falsy,
      一旦 current_user 为空则整个权限块被跳过直接放行。

修复:
1. if not current_user → 直接 raise 401
2. 反转 SUPER_ADMIN 判断: if user_role != 'SUPER_ADMIN' 进入校验
   (避免 if/else/pass 空分支带来的逻辑歧义)
3. main_task is not None 显式判断 (替代隐式 truthy)
2026-08-11 17:39:30 +08:00
9064973a3f fix(app): onShow 中增加更新检查 — 用户无需杀后台即可感知新版本
问题: checkUpdate 仅在 onLaunch 执行,App 常驻内存时永不复用。
      用户部署更新后,不杀后台就永远感知不到新版本。

修复:
1. onShow 中追加 checkUpdate(),每次回到前台自动检测
2. checkUpdate 顶部加 5分钟节流,避免频繁切后台时重复弹窗
2026-08-11 16:56:22 +08:00
01b8601dcd fix(app): OTA更新体验重构 — 废除闪烁弹窗 + 自动重启
问题:
1. uni.showLoading 每次调用都是关→开,进度回调中连续调用导致疯狂闪烁
2. 安装完成后弹窗询问重启,用户选「稍后」则必须手动杀后台

修复:
1. 替换 uni.showLoading → plus.nativeUI.showWaiting
   原生等待框支持原地更新文字,下载进度平滑过渡,零闪烁
2. 安装成功后移除重启询问弹窗,改为:
   plus.nativeUI.toast('新版本已就绪,即将重启...')
   → 2秒后 setTimeout → plus.runtime.restart()
   用户无需任何操作,2秒后自动生效
2026-08-11 16:53:35 +08:00
5b5f4a6b0e fix(frontend): TreeCanvas 坐标+连线三重修复 — 根治箭头悬空
1. calcSubtreeHeight: Math.max(CARD_H+GAP, totalChildrenHeight)
   → 首子与父平齐,父级高度取 max 而非无脑叠加

2. placeChildren: startY = parentNode.y (水平对齐)
   → 移除初始化 GAP,累加改为 startY += subtreeH

3. lines(): 动态追踪 Y 坐标
   → y1 = isLeft? n.y+40 : parent.y+40
   → y2 = isLeft? parent.y+40 : n.y+40
   → lineStyle 的 Math.atan2 自动画出完美对角线
2026-08-11 16:42:14 +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
0e3eb6a35a fix(frontend): 根治双重渲染 — 侧翼过滤主线,主轴归主轴
回滚此前错误的 allMains 根级过滤,恢复所有 TRANSFER/RECOVERY
任务进入中央垂直主轴。

真正修复:directChildren 加 .filter(c => !isMain(c))
→ 左右翼严格排除主线任务,仅保留 SPAWN 协助分支

原理: 主线→中央垂直时间线, 分支→左右翼, 各行其道不再重复
2026-08-11 15:40:43 +08:00
974f4b9d01 fix(frontend): TaskFlowView 根治双重渲染 — allMains 仅含根级节点
生产数据问题:16个任务中15个TRANSFER子节点全部挂在同一个root下,
isMain() 将它们同时放入 allMains 和 childMap,导致每个子节点渲染2次。

修复:
1. allMains 改为仅收集 parent_task_id IS NULL 的根级主干
   - TRANSFER 子节点仅通过 childMap → renderBranch 递归渲染
   - 彻底杜绝同一任务在时间线 + 分支中双重出现
2. 统一焦点/全景为同一套垂直时间线 JSX 布局
   - 删除旧焦点模式的独立 flex-row 排版
   - visibleMains useMemo 负责数据过滤 (active() 过滤)
3. 清理死代码: getRootMainId() / rootMainMap / srm / flatMap
2026-08-11 15:37:04 +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
88dc7381f6 fix(backend): 权限漏洞修复 + 业务逻辑审查修复
1. 宏观状态越权修复 (products.py + product_service.py):
   - update_overall_status 增加权限校验:仅 SUPER_ADMIN 或当前操作该产品主线任务的人可修改,否则 403

2. 任务撤回越权修复 (task_service.py + tasks.py):
   - recall_task 增加校验:操作人必须等于上游任务负责人(谁发出的谁撤回),否则 403
   - 管理员 (SUPER_ADMIN/SUPERVISOR) 直接放行

3. 驳回上游溯源修复 (task_service.py - reject_task):
   - 将 TaskLog (action_type=create) 提升为优先溯源方式,解决协助分支转交后驳回找不到正确发起人的 Bug
   - 保留 parent_task.assignee_id + task.assignee_id 两级兜底

4. complete_task 父节点继承修复:
   - 修复 task_type == 'MAIN' 永不匹配的 Bug(模型无此值)
   - 改为 not parent_task_id or task_type in (TRANSFER, RECOVERY)
2026-08-11 15:05:30 +08:00
d40a8d480e fix(backend): end_task 和 complete_task 补齐权限校验
- end_task 新增 operator_role 参数 + _check_permission 调用
- complete_task 新增 operator_role 参数 + _check_permission 调用
- 两个端点均注入 current_user Depends(get_current_user)
- 非任务负责人且非管理员/主管调用时返回 403
2026-08-11 10:13:40 +08:00
de47d27cfb fix(backend): _recalc_product_location 修复 func.or_() → or_()
func 是 SQL 函数调用(如 func.now()),不能替代 WHERE 条件中的 or_ 运算符。
这会导致结束协助分支时 SQL 抛错 500。
2026-08-11 10:05:13 +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
d3def15bb3 feat(web): TaskFlowView 递归渲染重构
- 废弃拍平算法,构建全局childMap保留真实树结构
- 新增renderBranch递归渲染函数,子子孙孙向外延伸
- 焦点/全景模式统一应用递归算法,连线从真实父节点引出
2026-08-11 10:02:06 +08:00
718e205f53 feat(backend): 完工转交智能父节点继承算法
- complete_task: MAIN转交保持平级(parent_task_id),SPAWN转交认当前为父(task.id)
- 基因严格继承: task_type不会篡位成MAIN
2026-08-11 10:02:01 +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
6373dca4f6 refactor: Web 端十字星流转树 — 3层嵌套协助降维渲染
- isMain() 移除危险的 parent.status 兜底判定,仅凭基因字段
- 新增 getRootMainId() 寻根算法,向上攀爬找视觉主干
- subsByRootMain 虚拟扁平化:孙子协助挂在顶级主干下
- 层级排序:直接子节点 → 孙子按父链收集
- SlimCard 新增嵌套协助标识:协助: {真实parent.assignee_id}
2026-08-10 17:37:30 +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
05003d3053 feat: 全局人名映射工具 — 拼音 ID → 中文姓名转换
- formatUserName(userId): 查全局字典翻译为中文名,降级返回原 ID
- formatUserAvatar(userId): 中文名取末字作为头像文字
- setUserNameMap(users): 批量注册用户字典
2026-08-10 17:37:16 +08:00
1fe9c3d59d feat: 留言板 API + 零信任安全:后端 Token 鉴权强制覆写 operator_id
- 新增 GET/POST /products/{id}/messages 端点
- POST 创建留言时注入 current_user = Depends(get_current_user)
- operator_id 优先取 Token 中的 username,防止前端越权伪造发言身份
- 同时将 product.current_location_id 显示改为 formatUserName 映射
2026-08-10 17:37:10 +08:00
b14773f81b feat: 产品协同留言板 — ProductMessage 模型 + API + 迁移
- 新增 ProductMessage 模型,挂载在 products.id(ON DELETE CASCADE)
- GET/POST /products/{id}/messages 接口
- 注册到 Alembic 自动发现
2026-08-10 17:37:01 +08:00
e326f8d311 fix: 修复任务完工/结束 500 + 后端基因继承
- 移除 task.child_tasks 的 ORM 属性直接赋值(导致 SQLAlchemy 状态机崩溃)
- complete_task 创建 next_task 时补上 task_type=task.task_type 基因继承
2026-08-10 17:36:54 +08:00
2440e9bdaa fix: 修复产品删除 500 — ImportError + FK 自引用约束
- 修正 TaskLog 导入路径:app.models.task → app.models.task_log
- 删除任务前先切断 parent_task_id 自引用外键
- 删除产品前先切断 parent_product_id 自引用外键
- 真正执行 delete(TaskRecord) 和 delete(TaskLog) 替代空 select
2026-08-10 17:36:48 +08:00
ba060cbb5e refactor(mobile): 流转树固定100%比例,移除双指缩放功能
- 移除 movable-view 的 :scale/:scale-min/:scale-max/:scale-value 属性
- 移除 onScale/zoomIn/zoomOut 方法及工具栏缩放按钮
- 移除顶部双指缩放·单指拖拽提示文字
- fitAll 简化为纯居中定位 (mvX/mvY),不再调整缩放比
- 工具栏仅保留: 返回 | 流转蓝图 | 卡片切换 | 全览
2026-08-10 15:25:56 +08:00
a07e43ec3a fix(mobile): 修复画布空白区域无法响应拖拽缩放手势
canvas-inner 使用 position:absolute 但未设置 width/height,
导致只缩到子元素大小(几乎为0)。在卡片之外的空白区域触摸时,
事件无法穿透到 movable-view 原生组件。

修复:
- canvas-inner: 添加 width:100%; height:100% 铺满 movable-view
- tree-movable-view: 添加 width:100%; height:100% 确保触摸覆盖
2026-08-10 15:19:34 +08:00
f2403dd1e6 fix(mobile): 流转树全览居中 + 拖拽缩放性能优化
1. fitAll() 居中修复: 内容坐标系整体对齐视口中心
   旧: mvX=0, mvY=0 (内容偏右下角)
   新: mvX = (viewportW - canvasW * scale) / 2, mvY同理

2. movable-area 显式像素高度: 替代 flex:1
   避免触摸区域计算不准确导致拖拽延迟

3. onScale 节流: rAF/setTimeout 限频 16ms
   避免 @scale 每帧触发 Vue 响应式更新

4. 新增 onChange 同步手势结束后的位置
   惯性动画结束后记录位置,下次 fitAll 参考使用

5. 添加 inertia+friction+damping 惯性动画参数
2026-08-10 15:09:06 +08:00
5271177d7a fix(mobile): 修复全览按钮点击后页面卡死的响应式循环bug
treeNodes 计算属性中直接修改了 product.task_tree 原始响应式对象
(设置 x/y/_isMain/_blabel),触发 Vue 2 深度响应式的无限渲染循环。

修复方案:对所有 task 对象进行浅拷贝 { ...t },在副本上设置坐标
和标签属性,切断响应式依赖循环。
2026-08-10 15:00:37 +08:00
3ec244bf2d feat: 全览节点无记录时Toast友好提示替代静默短路 2026-08-10 14:40:18 +08:00
5f12adfe2f fix: 连线层加pointer-events:none防止吞掉卡片点击事件 2026-08-10 14:37:37 +08:00
51ca05d737 fix: 全览按钮z-index修复+产品ID点击弹二维码 2026-08-10 14:30:50 +08:00
016a988962 fix: parseVersionCode修复—major*100+lastNum, T1.0.10→110匹配服务器 2026-08-10 14:22:36 +08:00
0b6c4a7f8b fix: OTA版本对比改用plus.runtime.versionCode直接对比,修复T1.0.10误判为旧版 2026-08-10 14:12:05 +08:00
f80da36d65 fix: 连线边缘到边缘防穿模+箭头像素级贴合分支卡片边缘 2026-08-10 13:59:22 +08:00
6d534960a7 refactor: 移动端TreeCanvas十字星拓扑—主干居中+分支左右发散+连线箭头+极简卡片160x80 2026-08-10 13:52:46 +08:00
38263291d1 perf: 流转树排他展开(手风琴模式)-同时只展开一个产品 2026-08-10 13:40:46 +08:00
4d93844637 fix: 箭头语义方向修正—永远背离主干指向分支(左翼◀+右翼▶) 2026-08-10 13:29:35 +08:00
fba3589d0d feat: 焦点/全景模式双翼flex-col纵向堆叠+SVG箭头+实线虚线区分 2026-08-10 13:26:31 +08:00
87296af139 refactor: 水平对称双翼布局—左翼(偶索引)+中央主干+右翼(奇索引),实线/虚线区分 2026-08-10 13:21:30 +08:00
ae520e49d7 refactor: 双模式流转树—焦点模式(活跃+遗留分支) + 全景模式(完整历史时间轴) + 极简卡片 2026-08-10 13:12:23 +08:00
5d6e2135c0 feat: 任务全景默认按设备分组+全展开+全部展开/折叠按钮(与产品管理一致) 2026-08-10 11:47:03 +08:00
34724e478c fix: SQL语法错误—func.and_()/or_()改为sqlalchemy.and_()/or_() 2026-08-10 11:41:10 +08:00
e447de6cfa feat: 当前位置100%动态主干化—与宏观状态同源,只跟主分支,静态字段仅兜底 2026-08-10 11:32:07 +08:00
b43bded0ef feat: 宏观状态动态从主干任务获取+任务树assignee中文姓名映射(后端+前端) 2026-08-10 11:25:44 +08:00
c0fe7c94bb feat: 产品管理默认按设备分组+自动全部展开+全部展开/折叠按钮 2026-08-10 11:18:01 +08:00
2eed7db82d refactor: 产品管理页全面升级—分组折叠面板+搜索/状态过滤+序列号列+与任务全景体验一致 2026-08-10 11:07:53 +08:00
60af3b9998 feat: 物料选择全量展示(移除成品/半成品限制) 2026-08-10 11:02:22 +08:00
2880ea6df7 fix: Grid回退grid-cols-12精确对齐+分组标题按device/order切换+宏观状态receive/transfer只主线 2026-08-10 10:58:33 +08:00