Files
track/PROJECT_ANALYSIS_REPORT.md
duxingchen d32a3dce49 chore: UniApp OTA静默更新 + 项目分析报告
1. UniApp OTA更新优化
   - 移除进度条和下载中Toast(静默后台下载)
   - 安装成功后3秒自动重启,无用户感知
   - 失败时仅console.error,不弹窗打扰用户

2. 项目分析报告
   - 新增PROJECT_ANALYSIS_REPORT.md
   - 涵盖技术栈、数据模型、核心业务流程、潜在痛点和架构建议
2026-08-12 12:04:51 +08:00

19 KiB
Raw Blame History

Track Production — 项目现状与业务逻辑分析报告

受众: 高级开发工程师 / 系统架构师
日期: 2026-08-12
版本: v0.1.0


一、技术栈与架构

1.1 项目整体拓扑

track/
├── backend/           # Python FastAPI 后端服务
├── frontend/          # React SPATauri 桌面壳 + Web 管理端)
└── track-uniapp/      # UniApp 移动端iOS/Android/H5

1.2 后端技术栈

层面 技术 版本
框架 FastAPI (ASGI) 0.141
ASGI 服务器 Uvicorn 0.52
ORM SQLAlchemy 2.0(异步) 2.0.51
数据库 PostgreSQL通过 asyncpg pg 15+
迁移工具 Alembic 1.18
认证 python-jose (JWT) + Werkzeug scrypt HS256
密码验证 passlib bcrypt + Werkzeug scryptMOM 对接)
二维码 qrcode[pil] + Pillow 8.2 / 12.3
标签打印 PIL 图像合成 + Socket TSPL 协议
序列化 Pydantic v2 2.13

架构模式:分层架构 (Layered Architecture)

  • api/v1/endpoints/ — 路由/控制器层
  • services/ — 业务逻辑服务层
  • models/ — SQLAlchemy ORM 数据模型
  • schemas/ — Pydantic 请求/响应 DTO
  • core/ — 横切关注点(配置、数据库连接池、安全、时间工具)

1.3 前端技术栈

层面 技术 版本
UI 框架 React 19 + TypeScript 6.0 19.2
桌面壳 Tauri 2.xRust 原生窗口) 2.11
构建工具 Vite 8.2
UI 库 Ant Design 6 + Tailwind CSS 4 6.5 / 4.3
状态管理 Zustand 5 5.0
路由 React Router v7 7.18
HTTP 客户端 Axios 1.19
扫码 html5-qrcode懒加载 2.3

架构模式SPA + 路由级代码分割React.lazy

1.4 移动端 (track-uniapp)

基于 UniApp (Vue) 构建,目前包含 5 个页面:

  • 扫码干活 (pages/scan/index) — 核心工作入口
  • 我的任务 (pages/tasks/index) — 个人任务看板
  • 消息通知 (pages/notify/index)
  • 个人中心 (pages/profile/index)
  • 登录页 (pages/login/login)

底部 TabBar 4 个入口,与 PC 端 AppLayout 页面结构对应。


二、数据模型与实体关系

2.1 核心 E-R 图

┌──────────────────┐       ┌──────────────────┐
│ production_orders│ 1──N  │    products      │
│  - id (UUID PK)  │       │  - id (UUID PK)   │
│  - order_no[UQ]  │       │  - serial_number  │
│  - customer_info │       │    [16位HEX, UQ]  │
│  - status        │       │  - order_id (FK)  │←──── FK (nullable in latest)
│  - created_at    │       │  - material_id*   │      * = 逻辑外键→MOM
└──────────────────┘       │  - material_name  │        (material_base)
                           │  - spec_model     │
                           │  - category       │
                           │  - material_type  │
                           │  - overall_status │  宏观: 备货/生产/测试/维修/在库
                           │  - parent_product │──┐ 自引用 FK
                           │  - current_location│  │ (持有者/仓库)
                           │  - status         │  │
                           │  - created_at     │  │
                           └────────┬─────────┘  │
                                    │ 1           │
                                    │             │
                                    │ N           │
                           ┌────────▼─────────┐  │
                           │     tasks         │◄─┘
                           │  - id (UUID PK)   │
                           │  - product_id(FK) │
                           │  - parent_task_id │──┐ 自引用 FK无限嵌套
                           │  - task_name      │  │
                           │  - assignee_id*   │  │ * = 逻辑外键→MOM sys_user
                           │  - status         │  │
                           │  - task_type      │  │ TRANSFER/SPAWN/RECOVERY
                           │  - is_rework      │  │
                           │  - reject_reason  │  │
                           │  - remark         │  │
                           │  - received_at    │  │
                           │  - completed_at   │  │
                           │  - created_at     │  │
                           └──┬──────┬─────────┘  │
                              │ N    │ N            │
                     ┌────────▼─┐ ┌──▼──────────┐  │
                     │task_records│ │  task_logs │  │
                     │- remark   │ │ - action_type│  │
                     │- images   │ │ - operator_id│  │
                     │- created  │ │ - remark    │  │
                     └───────────┘ │ - created   │  │
                                   └─────────────┘  │
                           ┌────────────────────────┐
                           │    notifications        │
                           │  - user_id (目标用户)    │
                           │  - type (TRANSFER/REJECT│
                           │          /COMMENT)      │
                           │  - task_id (FK→tasks)   │
                           │  - is_read              │
                           └────────────────────────┘
                           ┌────────────────────────┐
                           │   product_messages      │
                           │  - product_id (FK)      │
                           │  - operator_id          │
                           │  - content              │
                           └────────────────────────┘

2.2 关键设计决策

  1. 逻辑外键 vs 物理外键material_idassignee_id 均使用逻辑外键(只存 ID无 DB 级约束),指向外部 MOM 老系统——允许老系统数据独立演进,避免跨库约束。

  2. 物料快照机制Product 表存储 material_name/spec_model/category/material_type 完整快照,创建时一次性写入。这意味着即使老系统后续修改物料数据,已经流转的产品标签不会受影响。

  3. 任务树自引用Task 通过 parent_task_id 自引用实现无限层级嵌套。三种任务类型定义了分支行为:

    • TRANSFER:主线转交(主分支)
    • SPAWN:协助分支(不改变父任务状态)
    • RECOVERY:撤回后接力节点
  4. 16 位 HEX 产品身份证:通过 PostgreSQL SEQUENCE 单调递增生成,格式 %016X,理论上限 2^64实际序列值


三、核心业务流程

3.1 任务生命周期状态机

                  ┌──────────┐
                  │  PENDING  │  待接收
                  └────┬─────┘
                       │ receive
                       ▼
                  ┌──────────┐
         ┌────────│   WIP    │◄───────────────┐
         │        └────┬─────┘                │
         │ spawn       │  transfer/complete   │ recall
         │ (协助分支)    │  (完工裂变转交)        │ (撤回转交→CANCELED)
         ▼             ▼                      │
   ┌──────────┐  ┌───────────┐               │
   │PENDING   │  │ COMPLETED │               │
   │(SPAWN)   │  │(终态)      │               │
   └──┬───────┘  └───────────┘               │
      │ reject                               │
      ▼                                      │
┌──────────┐  ┌──────────────────────────────┘
│ REJECTED │  │
│ (终态)    │  │
└────┬─────┘  │
     │ 自动创建返工│
     ▼         │
┌──────────┐  │
│ PENDING  │  │
│(REWORK)  │──┘ 返工任务回到 WIP 循环
└──────────┘

3.2 核心业务接口说明

接口 作用 关键逻辑
POST /tasks/{id}/receive 工人确认接收 PENDING→WIP同步产品位置+宏观状态
POST /tasks/{id}/transfer 完工裂变转交 WIP→COMPLETED支持多分支 next_tasks,裂变子任务挂在当前任务下
POST /tasks/{id}/complete 旧版单步完结 保留兼容,内部委托到 transfer 逻辑
POST /tasks/{id}/end 结束协助分支 仅 SPAWN 类型可用,不创建下游
POST /tasks/{id}/reject 品质驳回 →REJECTED自动创建返工任务给上游
POST /tasks/{id}/recall 撤回未接收的转交 PENDING→CANCELED创建 RECOVERY 接力
POST /tasks/{id}/spawn 派发并行协助 父任务保持 WIP创建 PENDING SPAWN 子任务
GET /products/scan/{sn} 扫码查询 返回产品信息+完整递归任务树+人员姓名映射
PATCH /products/scan/{sn}/status 更新宏观状态 权限校验SUPER_ADMIN 或当前主线负责人
POST /print/execute 物理标签打印 480×360 工业排版→二值化→TSPL→Socket 9100

3.3 权限模型

角色层级:
  SUPER_ADMIN / SUPERVISOR  →  上帝视角(所有任务可操作)
  operator (普通工人)        →  仅操作分配给自己的任务

校验点:
  - 任务接收/驳回/转交/撤回_check_permission(assignee_id, operator_id, role)
  - 宏观状态修改:需 SUPER_ADMIN 或当前主线任务(WIP/PENDING)的 assignee
  - 留言板operator_id 由 Token 强制覆写,防止越权伪造

四、数据样本 (Data Shape)

4.1 扫码查询响应 (ProductScanResponse)

{
  "id": "550e8400-e29b-41d4-a716-446655440001",
  "serial_number": "000000000000001A",
  "external_serial": "CUST-SN-2024-0001",
  "order_id": "660e8400-e29b-41d4-a716-446655440002",
  "order_no": "ORD-2024-0881",
  "material_id": "MAT-32001",
  "material_name": "样品升降台V1J",
  "spec_model": "PH-B4V1J/类A",
  "category": "成品",
  "material_type": "装配件",
  "parent_product_id": null,
  "current_location_id": "zhangsan01",
  "overall_status": "生产",
  "status": "in_progress",
  "created_at": "2026-08-10T09:30:00+08:00",
  "assignee_names": {
    "zhangsan01": "张三",
    "lisi02": "李四",
    "wangwu03": "王五"
  },
  "task_tree": [
    {
      "id": "770e8400-...",
      "task_name": "装配",
      "assignee_id": "zhangsan01",
      "status": "WIP",
      "task_type": "TRANSFER",
      "is_rework": false,
      "received_at": "2026-08-10T09:45:00+08:00",
      "child_tasks": [
        {
          "id": "880e8400-...",
          "task_name": "接线",
          "assignee_id": "lisi02",
          "status": "PENDING",
          "task_type": "TRANSFER",
          "child_tasks": [],
          "records": []
        }
      ],
      "records": [
        {
          "id": 1,
          "task_id": "770e8400-...",
          "remark": "已完成底座固定",
          "images": ["https://cdn.example.com/img/2024/photo1.jpg"],
          "created_at": "2026-08-10T10:15:00+08:00"
        }
      ]
    }
  ]
}

4.2 任务完成请求 (transfer)

{
  "next_tasks": [
    {
      "task_name": "接线",
      "assignees": ["lisi02", "wangwu03"]
    },
    {
      "task_name": "质检",
      "assignees": ["virtual_warehouse"]
    }
  ],
  "note": "装配工序完工,转接线双人并行 + 质检入库"
}

4.3 标签打印数据

{
  "serial_number": "000000000000001A",
  "material_name": "样品升降台V1J",
  "spec_model": "PH-B4V1J/类A",
  "order_no": "ORD-2024-0881",
  "copies": 2,
  "printer_ip": "192.168.9.221",
  "printer_port": 9100
}

标签格式480×360 px 工业标签 → 二值化 → TSPL BITMAP 指令


五、系统双库架构

┌────────────────────────────────────────────────┐
│              Track 系统(本库)                   │
│  PostgreSQL :5433 / track_production           │
│  表: production_orders, products, tasks,       │
│       task_logs, task_records, notifications,  │
│       app_versions, product_messages           │
│  ORM: SQLAlchemy 2.0 Async                    │
├────────────────────────────────────────────────┤
│              MOM 老系统(只读)                   │
│  PostgreSQL :5435 / inventory_system           │
│  表: sys_user (用户), material_base (物料)      │
│  连接: SQLAlchemy Sync + NullPool              │
│  用途: 登录验证 + 物料手风琴选择器 + 姓名映射     │
└────────────────────────────────────────────────┘

六、观察到的潜在架构问题与优化方向

6.1 数据一致性与可靠性

问题 严重度 说明
Dashboard 统计值陈旧 get_dashboard_stats 使用硬编码字符串 "pending"/"in_progress" 过滤,但任务模型实际使用 PENDING/WIP 等大写常量。当前实际查的是全量/0值。
产品 status 字段语义模糊 Product 有 status(产品自身状态)和 overall_status(宏观流转状态)两个状态字段,前者使用小写 pending/in_progress/completed,后者使用中文 备货/生产/测试/维修/在库,存在概念重叠和命名不一致。
缺失数据库事务跨表保护 transfer_task 涉及多条 INSERT子任务+日志+通知+位置更新),使用多次 flush() + 最终 commit(),无显式 BEGIN/SAVEPOINT但 SQLAlchemy autocommit 模式下能保证原子性。
无软删除机制 任务仅状态流转CANCELED产品删除是硬删除级联清理关联无回收站/审计日志。

6.2 性能与查询优化

问题 严重度 说明
递归任务树 N+1 查询 _load_task_tree_load_children 递归执行单条 SELECT深度为 N 的任务树执行 N+1 次数据库查询。建议使用 PostgreSQL Recursive CTE 一次性加载整棵树。
姓名映射逐次查询 _lookup_display_names 每次用 OR 拼接 LIKE 查询 MOM 老系统,高频场景(产品列表每页 50 条)下调用多次。建议加 Redis 缓存或本地映射表。
任务列表无总数 get_all_tasks 返回的 totallen(flat_tasks)(即当前页条数),而非数据库真实总数,前端无法正确分页。
产品列表复杂 JOIN get_all_products 为每个产品列表做了 3 次聚合子查询macro_status、overall_names、main_assignees数据量大时需关注性能。

6.3 安全性

问题 严重度 说明
SECRET_KEY 硬编码 config.py 默认值 "change-me-in-production",虽然 .env 可覆盖,但缺少生产环境强校验。
Material API 无鉴权 /materials/groups/materials/itemsDepends(get_current_user),任何人均可查询老系统物料库。
通知查询无鉴权 /notifications/ 通过 Query 参数 user_id 过滤,可被任意篡改查看他人通知。应改为从 Token 解析当前用户。
MOM 数据库密码明文 mom_database.py 中连接字符串硬编码数据库密码。

6.4 代码质量

问题 严重度 说明
print.py endpoint 为同步函数 标签预览/打印端点为同步 def,若耗时长会阻塞 event loop。建议改为 async def + run_in_executor
materials.py SQL 注入风险 TYPE_FILTER = "1=1" 是 Python 常量注入到 SQL 字符串拼接,虽当前安全,但此模式不够防御性。
重复的 _task_to_response 实现 product_service.pytask_service.py 各自维护一套任务树序列化逻辑,不共享。
app_version 模块独立但未接入 CI/CD AppVersion 表 + /app_version 端点支持 OTA WGT 升级,但目前无关联的打包/上传脚本。

6.5 架构演进建议

  1. 引入消息队列:当裂变转交产生多个子任务时,通知创建在同一个事务内——若通知发送失败会回滚整个转交。建议将通知发送解耦到消息队列。

  2. 位置追踪精度:当前 current_location_id 仅存储一个持有者,多路裂变后只能追踪第一个分支的负责人。建议引入专门的 product_locations 轨迹表。

  3. 任务状态机形式化:当前状态转换逻辑分散在 task_service.py 各方法中(多处 if task.status != ... 检查)。建议使用状态机模式(如 transitions 库)集中管理。

  4. API 版本化健全性:当前 /api/v1 前缀已预留版本号,但部分接口响应模型在迭代中已发生变化(如 task_tree 替代 top_level_tasks),建议通过 /api/v2 或 Deprecation Header 管理 API 演进。

  5. 前端测试覆盖:当前 frontend/ 无任何测试文件(.test.ts/.spec.ts),后端也无 pytest 目录,建议补充核心业务流程的集成测试。


七、项目亮点总结

  1. 精巧的任务裂变模型TRANSFER/SPAWN/RECOVERY 三种任务基因 + 智能父节点继承算法,支持单线转交、并行协助、裂变分支、撤回接力等复杂工厂场景。

  2. 双库隔离架构Track 本库存储流转数据MOM 老系统只读对接——物理隔离保护老系统,同时通过物料快照机制避免数据漂移。

  3. 工业级标签打印PIL 精确坐标排版 → 二值化 → TSPL 指令 → Socket 直连打标机,全程离线化,不依赖第三方打印服务。

  4. 三端覆盖PC 管理端 (React+Tauri) + 移动端 (UniApp) + 扫码端 (html5-qrcode 懒加载)UI 架构通过路由级代码分割优化首屏加载。

  5. 双 Token 认证Access Token (2h) + Refresh Token (7d),对接 MOM sys_user 的 scrypt 密码存储,不重复造用户系统。


报告由 Claude Code 自动生成,基于对代码库的静态分析。建议结合实际运行数据进一步验证上述发现。