提交
This commit is contained in:
1 parent
c3be9d1dce
commit
299609706c
328 files changed
+144899
-13873
No files matched your search
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-06-10
|
||||
@@ -0,0 +1,257 @@
|
||||
# 运输计划管理系统 - 技术设计
|
||||
|
||||
## Context
|
||||
|
||||
### 项目背景
|
||||
|
||||
安庆山峡化工有限公司已建设 CRM 系统(线索/客户/商机/报价单/合同/产品管理)和地磅系统。现需建设**统一的运输计划管理系统**,将 CRM 合同与后续的运输、地磅、库存等环节串联,形成从合同→计划→运输→地磅→结算→归档的完整业务闭环。
|
||||
|
||||
### 技术栈
|
||||
|
||||
- **后端**:Python FastAPI + SQLAlchemy + MySQL
|
||||
- **前端**:Vue 3 + Element Plus + TypeScript
|
||||
- **对象存储**:MinIO(附件上传)
|
||||
- **数据库**:MySQL 5.7+
|
||||
|
||||
### 约束条件
|
||||
|
||||
1. 按需求文档要求,所有计划相关表统一使用 `pl_` 前缀
|
||||
2. 遵循 shanxia2.0 工程规范(见 `openspec/changes/zkxw-engineering-standards/`)
|
||||
3. 遵循 UI 规范(Fresh Mint 风格)
|
||||
4. 数据暂不按归属公司隔离
|
||||
5. 地磅数据由现场人员手动填写,不对接硬件设备
|
||||
|
||||
### 利益相关者
|
||||
|
||||
- 计划专员A:发起计划
|
||||
- 计划专员B:核对订单
|
||||
- 计划专员C:运费结算确认
|
||||
- 司机:扫码回传
|
||||
- 现场工作人员:地磅确认
|
||||
|
||||
---
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
1. 实现完整的计划管理流程:从合同发起→运输安排→状态流转→归档
|
||||
2. 支持运输审批流程(会签审批)
|
||||
3. 实现运费结算功能
|
||||
4. 实现车辆和司机管理
|
||||
5. 实现盘存统计和库存预警
|
||||
6. 遵循工程规范和 UI 规范
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
1. 不对接地磅硬件设备(手动填写数据)
|
||||
2. 不实现复杂的移动端功能(司机端仅扫码回传)
|
||||
3. 不实现电子签名
|
||||
4. 不实现多语言支持
|
||||
5. 不实现操作日志(暂不考虑)
|
||||
|
||||
---
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: 数据库表命名规范
|
||||
|
||||
**选择**:统一使用 `pl_` 前缀
|
||||
|
||||
**理由**:
|
||||
- 与现有 `sys_*`、`biz_*`、`wf_*` 命名体系保持一致
|
||||
- 便于识别和管理计划相关的表
|
||||
- 需求文档明确要求
|
||||
|
||||
**备选方案**:
|
||||
- `plan_*` - 与业务语义更贴近,但不符合统一前缀规范
|
||||
- `transport_*` - 过于局限,无法覆盖库存等其他功能
|
||||
|
||||
---
|
||||
|
||||
### Decision 2: 审批流程实现方式
|
||||
|
||||
**选择**:自定义审批流程(不使用工作流引擎)
|
||||
|
||||
**理由**:
|
||||
- 需求简单:仅支持会签审批(1-2级)
|
||||
- 不走复杂的工作流引擎
|
||||
- 审批规则灵活(用户选择审批人)
|
||||
- 减少系统复杂度
|
||||
|
||||
**备选方案**:
|
||||
- 使用 Warm-Flow 工作流引擎 - 过于复杂,不适合简单审批场景
|
||||
- 使用独立审批服务 - 增加系统复杂度,当前阶段不必要
|
||||
|
||||
---
|
||||
|
||||
### Decision 3: 计划与运输的关系设计
|
||||
|
||||
**选择**:采用中间关联表实现 N:N 关系
|
||||
|
||||
**理由**:
|
||||
- 需求明确支持:1:1、1:N、N:1 三种场景
|
||||
- 中间表 `pl_plan_transport` 清晰表达关联关系
|
||||
- 便于后续扩展和维护
|
||||
|
||||
**表结构**:
|
||||
```
|
||||
pl_plan_transport
|
||||
├── plan_id (FK)
|
||||
├── transport_id (FK)
|
||||
├── create_time
|
||||
└── del_flag
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Decision 4: 库存金额计算方式
|
||||
|
||||
**选择**:每批入库单独计算,不使用加权平均
|
||||
|
||||
**理由**:
|
||||
- 需求明确要求:使用入库时的实际价格,每批单独计算
|
||||
- 财务合规性:每批货物成本清晰可追溯
|
||||
- 简化计算逻辑
|
||||
|
||||
---
|
||||
|
||||
### Decision 5: 二维码实现方式
|
||||
|
||||
**选择**:URL Scheme + 参数编码
|
||||
|
||||
**理由**:
|
||||
- 简单可靠:二维码包含运输单ID和基本信息
|
||||
- 无需复杂加密:运输单ID已足够定位
|
||||
- 便于调试:可通过URL直接访问
|
||||
|
||||
**二维码内容**:
|
||||
```
|
||||
{base_url}/transport/scan/{transport_id}?code={verify_code}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Decision 6: 证件过期提醒实现
|
||||
|
||||
**选择**:定时任务每日检查
|
||||
|
||||
**理由**:
|
||||
- 需求明确:过期前30天提醒
|
||||
- 定时任务简单可靠
|
||||
- 避免实时检查性能开销
|
||||
|
||||
---
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
### Risk 1: 多系统数据同步
|
||||
|
||||
**风险**:CRM 合同变更可能导致已发起计划的数据不一致
|
||||
|
||||
**缓解措施**:
|
||||
- 计划发起时冗余存储合同关键信息
|
||||
- 明确告知用户:合同变更后需手动同步
|
||||
- 在计划详情页显示合同信息快照
|
||||
|
||||
---
|
||||
|
||||
### Risk 2: 并发状态流转冲突
|
||||
|
||||
**风险**:多人同时操作同一计划可能导致状态不一致
|
||||
|
||||
**缓解措施**:
|
||||
- 使用乐观锁(version_no 字段)
|
||||
- 状态变更前检查当前状态
|
||||
- 前端操作后及时刷新状态
|
||||
|
||||
---
|
||||
|
||||
### Risk 3: 大量数据统计性能
|
||||
|
||||
**风险**:盘存统计涉及大量数据汇总,可能影响性能
|
||||
|
||||
**缓解措施**:
|
||||
- 归档后的数据不会频繁变更,考虑使用物化视图或定时统计表
|
||||
- 限制查询时间范围
|
||||
- 大数据量场景考虑分库分表(未来扩展)
|
||||
|
||||
---
|
||||
|
||||
## Migration Plan
|
||||
|
||||
### Phase 1: 数据库变更
|
||||
|
||||
1. 创建新表(按依赖顺序):
|
||||
- `pl_vehicle`、`pl_driver`、`pl_carrier`(基础数据)
|
||||
- `pl_plan`、`pl_plan_product`(计划主表)
|
||||
- `pl_transport`、`pl_transport_approval`(运输相关)
|
||||
- `pl_freight_settlement`(运费结算)
|
||||
- `pl_inventory`、`pl_inventory_warning`(库存相关)
|
||||
|
||||
2. 初始化基础数据(车辆类型、承运商等)
|
||||
|
||||
### Phase 2: 后端 API 开发
|
||||
|
||||
1. 基础 CRUD API(车辆、司机、承运商)
|
||||
2. 计划管理 API
|
||||
3. 运输管理 API
|
||||
4. 审批流程 API
|
||||
5. 运费结算 API
|
||||
6. 盘存统计 API
|
||||
|
||||
### Phase 3: 前端页面开发
|
||||
|
||||
1. 车辆管理页面
|
||||
2. 司机管理页面
|
||||
3. 计划管理页面
|
||||
4. 运输管理页面
|
||||
5. 运费结算页面
|
||||
6. 盘存统计页面
|
||||
7. 工作台(待办、预警)
|
||||
|
||||
### Phase 4: 定时任务
|
||||
|
||||
1. 证件过期提醒任务
|
||||
2. 库存统计定时更新(如采用统计表方案)
|
||||
|
||||
### Rollback Strategy
|
||||
|
||||
- Phase 1:回滚数据库变更(DROP TABLE)
|
||||
- Phase 2:删除新增的 API 路由
|
||||
- Phase 3:删除新增的前端页面和组件
|
||||
- Phase 4:禁用定时任务
|
||||
|
||||
---
|
||||
|
||||
## Open Questions
|
||||
|
||||
### Q1: 审批人权限控制
|
||||
|
||||
**问题**:审批人选择时是否需要过滤有审批权限的用户?
|
||||
|
||||
**建议**:暂不限制,所有用户都可被选择;后续按需细化权限
|
||||
|
||||
---
|
||||
|
||||
### Q2: 通知发送方式
|
||||
|
||||
**问题**:系统消息之外是否需要邮件/短信通知?
|
||||
|
||||
**建议**:暂仅使用系统消息;后续按需扩展
|
||||
|
||||
---
|
||||
|
||||
### Q3: 统计报表导出
|
||||
|
||||
**问题**:盘存统计报表是否需要导出功能?
|
||||
|
||||
**建议**:暂不实现;后续按需补充(见需求文档)
|
||||
|
||||
---
|
||||
|
||||
### Q4: 框架合同调价函关联
|
||||
|
||||
**问题**:框架合同调价后,已发起计划的价格是否需要同步更新?
|
||||
|
||||
**建议**:保持计划创建时的价格不变(价格快照);调价仅影响后续新建的计划
|
||||
@@ -0,0 +1,97 @@
|
||||
## Why
|
||||
|
||||
安庆山峡化工有限公司已建设 CRM 系统(线索/客户/商机/报价单/合同/产品管理)和地磅系统。现需建设**统一的运输计划管理系统**,将 CRM 合同与后续的运输、地磅、库存等环节串联,形成从合同→计划→运输→地磅→结算→归档的完整业务闭环。
|
||||
|
||||
## What Changes
|
||||
|
||||
### 新增功能模块
|
||||
|
||||
1. **计划管理(Plan Management)**
|
||||
- 支持从 CRM 合同发起计划,自动带入合同基本信息、商品明细、结算方式等
|
||||
- 支持三种单据类型:直销单、入库单、出库单(根据供应商/目的地自动判断)
|
||||
- 支持产品属性检查(易制毒/易制爆需上传购买证、运输证)
|
||||
- 支持跟进状态流转(等客户确认→待采购→待发货/待出库→待收货/待入库→已收货/已入库→待归档→归档完成)
|
||||
- 支持任意状态下取消计划
|
||||
|
||||
2. **运输管理(Transport Management)**
|
||||
- 支持选择车辆类型(自有/承运商)和具体车辆
|
||||
- 支持生成二维码供司机/现场人员扫码
|
||||
- 支持司机扫码回传运输单据和数量
|
||||
- 支持运输安排状态管理(待安排/已安排)
|
||||
|
||||
3. **运输审批(Transport Approval)**
|
||||
- 支持简单审批流程(会签)
|
||||
- 提交审批时用户选择审批人,按选择顺序依次审批
|
||||
- 状态流转:草稿→待执行→执行中→已完成→已取消
|
||||
- **不允许状态回退**
|
||||
|
||||
4. **运费结算(Freight Settlement)**
|
||||
- 支持按重量或按趟次计算运费
|
||||
- 支持多选运输单合并生成结算单
|
||||
- 结算流程:待提交→已提交→审核通过→已确认
|
||||
- 支持发票信息记录(发票号、开票日期、发票金额)
|
||||
- 支持汇款凭证上传
|
||||
|
||||
5. **车辆与司机管理(Vehicle & Driver Management)**
|
||||
- 车辆归属唯一性管理(自有 或 承运商)
|
||||
- 司机档案管理(姓名、联系方式、驾驶证、行驶证、危化品证)
|
||||
- 证件过期提醒(30天)
|
||||
|
||||
6. **盘存统计(Inventory Statistics)**
|
||||
- 库存台账(按产品汇总库存量和库存金额)
|
||||
- 出入库明细与汇总报表
|
||||
- 运输统计(按运输公司/车辆统计趟次和运费)
|
||||
- 库存预警(按产品设置阈值)
|
||||
|
||||
### 数据库变更
|
||||
|
||||
- 新增 `pl_plan`(计划主表)
|
||||
- 新增 `pl_plan_product`(计划产品明细表)
|
||||
- 新增 `pl_transport`(运输信息表)
|
||||
- 新增 `pl_transport_approval`(运输审批记录表)
|
||||
- 新增 `pl_vehicle`(车辆表)
|
||||
- 新增 `pl_driver`(司机表)
|
||||
- 新增 `pl_freight_settlement`(运费结算表)
|
||||
- 新增 `pl_inventory`(库存表)
|
||||
|
||||
### API 变更
|
||||
|
||||
- 新增 `/api/plan/*`(计划管理相关接口)
|
||||
- 新增 `/api/transport/*`(运输管理相关接口)
|
||||
- 新增 `/api/vehicle/*`(车辆管理相关接口)
|
||||
- 新增 `/api/driver/*`(司机管理相关接口)
|
||||
- 新增 `/api/freight/*`(运费结算相关接口)
|
||||
- 新增 `/api/inventory/*`(库存统计相关接口)
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `transport-plan`: 运输计划管理 — 计划创建、编辑、取消、状态流转
|
||||
- `transport-order`: 运输单管理 — 运输安排、二维码生成、扫码回传
|
||||
- `transport-approval`: 运输审批 — 审批流程、会签审批、审批记录
|
||||
- `freight-settlement`: 运费结算 — 结算单生成、发票管理、汇款凭证
|
||||
- `vehicle-driver`: 车辆司机管理 — 车辆档案、司机档案、证件提醒
|
||||
- `inventory-statistics`: 盘存统计 — 库存台账、出入库报表、运输统计、库存预警
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- 无(暂无对现有 capability 的需求变更)
|
||||
|
||||
## Impact
|
||||
|
||||
### 受影响系统
|
||||
|
||||
- **后端**:`backend/app/` — 新增计划、运输、车辆、司机、运费、库存相关模块
|
||||
- **前端**:`web-admin/src/` — 新增计划管理、运输管理、车辆管理等页面
|
||||
- **数据库**:新增 `pl_*` 系列表
|
||||
|
||||
### 外部依赖
|
||||
|
||||
- CRM 合同系统(`crm_contract`, `crm_contract_product`)— 读取合同信息
|
||||
- 地磅系统(`dibang_*`)— 接收出入库数据
|
||||
- MinIO 对象存储 — 附件上传
|
||||
|
||||
### 表前缀规范
|
||||
|
||||
按需求文档要求,所有计划相关表统一使用 `pl_` 前缀
|
||||
@@ -0,0 +1,82 @@
|
||||
# Freight Settlement (运费结算)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 运费计算
|
||||
|
||||
系统 SHALL 支持两种运费计算方式:按重量(默认)和按趟次。
|
||||
|
||||
#### Scenario: 按重量计算(默认)
|
||||
- **WHEN** 用户选择"按重量"计算方式
|
||||
- **THEN** 系统 SHALL 默认使用此方式
|
||||
- **AND** 运费 SHALL 自动计算为:运输数量 × 运输单价
|
||||
- **AND** 计算结果 SHALL 允许用户手动调整
|
||||
|
||||
#### Scenario: 按趟次计算
|
||||
- **WHEN** 用户选择"按趟次"计算方式
|
||||
- **THEN** 系统 SHALL 要求用户手动填写运费金额
|
||||
- **AND** 系统 SHALL NOT 进行自动计算
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 结算单生成
|
||||
|
||||
系统 SHALL 支持多选运输单合并生成结算单。
|
||||
|
||||
#### Scenario: 生成结算单
|
||||
- **WHEN** 用户选择多个运输单
|
||||
- **AND** 用户点击"生成结算单"
|
||||
- **THEN** 系统 SHALL 合并选中运输单的运费
|
||||
- **AND** 系统 SHALL 生成结算单编号
|
||||
- **AND** 系统 SHALL 显示结算明细供用户确认
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 结算流程
|
||||
|
||||
系统 SHALL 支持运费结算的完整流程。
|
||||
|
||||
#### Scenario: 结算流程
|
||||
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
| 待提交 | 结算单创建后初始状态 |
|
||||
| 已提交 | 用户提交结算单 |
|
||||
| 审核通过 | 计划专员C审核通过 |
|
||||
| 已确认 | 结算完成 |
|
||||
|
||||
#### Scenario: 审核确认
|
||||
- **WHEN** 结算单状态为"已提交"
|
||||
- **AND** 计划专员C点击"审核通过"
|
||||
- **THEN** 系统 SHALL 将状态更新为"审核通过"
|
||||
- **AND** 系统 SHALL 将状态更新为"已确认"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 发票管理
|
||||
|
||||
系统 SHALL 支持发票信息记录。
|
||||
|
||||
#### Scenario: 发票信息记录
|
||||
- **WHEN** 用户填写发票信息
|
||||
- **THEN** 系统 SHALL 记录发票号
|
||||
- **AND** 系统 SHALL 记录开票日期
|
||||
- **AND** 系统 SHALL 记录发票金额
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 汇款凭证
|
||||
|
||||
系统 SHALL 支持汇款凭证上传,且需精确对应到结算单。
|
||||
|
||||
#### Scenario: 汇款凭证上传
|
||||
- **WHEN** 用户上传汇款凭证
|
||||
- **THEN** 系统 SHALL 支持多个文件上传
|
||||
- **AND** 系统 SHALL 不限制文件类型
|
||||
- **AND** 系统 SHALL 允许选择对应的结算单
|
||||
|
||||
#### Scenario: 汇款凭证关联
|
||||
- **WHEN** 用户上传汇款凭证
|
||||
- **THEN** 系统 SHALL 要求选择对应的结算单
|
||||
- **AND** 系统 SHALL 记录关联关系
|
||||
- **AND** 系统 SHALL 支持查看关联的结算单详情
|
||||
@@ -0,0 +1,127 @@
|
||||
# Inventory Statistics (盘存统计)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 库存统计口径
|
||||
|
||||
系统 SHALL 以归档完成的单据为准进行库存统计。
|
||||
|
||||
#### Scenario: 统计范围
|
||||
- **WHEN** 系统计算库存数据
|
||||
- **THEN** 系统 SHALL 仅统计归档完成的入库单和出库单
|
||||
- **AND** 系统 SHALL 排除草稿、审批中、执行中的单据
|
||||
- **AND** 系统 SHALL 排除已取消的单据
|
||||
|
||||
#### Scenario: 直销单排除
|
||||
- **WHEN** 系统计算库存
|
||||
- **THEN** 系统 SHALL 排除直销单类型
|
||||
- **AND** 直销单 SHALL NOT 影响库存数量
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 库存台账
|
||||
|
||||
系统 SHALL 支持按产品汇总当前库存量和库存金额。
|
||||
|
||||
#### Scenario: 库存台账展示
|
||||
- **WHEN** 用户访问库存台账
|
||||
- **THEN** 系统 SHALL 按产品显示:
|
||||
- 产品名称
|
||||
- 产品编号
|
||||
- 当前库存数量
|
||||
- 库存单位
|
||||
- 库存金额(使用入库时的实际价格,每批单独计算)
|
||||
|
||||
#### Scenario: 库存金额计算
|
||||
- **WHEN** 系统计算库存金额
|
||||
- **THEN** 系统 SHALL 使用入库时的实际价格
|
||||
- **AND** 系统 SHALL NOT 使用加权平均
|
||||
- **AND** 每批入库 SHALL 单独计算金额
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 出入库明细
|
||||
|
||||
系统 SHALL 支持按时间范围列出所有入库/出库记录。
|
||||
|
||||
#### Scenario: 出入库明细查询
|
||||
- **WHEN** 用户设置时间范围
|
||||
- **THEN** 系统 SHALL 显示该范围内的所有入库记录
|
||||
- **AND** 系统 SHALL 显示该范围内的所有出库记录
|
||||
- **AND** 每条记录 SHALL 包含:
|
||||
- 单据编号
|
||||
- 单据类型(入库/出库)
|
||||
- 产品信息
|
||||
- 数量
|
||||
- 单价
|
||||
- 金额
|
||||
- 时间
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 出入库汇总
|
||||
|
||||
系统 SHALL 支持按月/周汇总各产品的入库量、出库量、净变化。
|
||||
|
||||
#### Scenario: 按月汇总
|
||||
- **WHEN** 用户选择"按月"汇总
|
||||
- **THEN** 系统 SHALL 按月分组显示
|
||||
- **AND** 系统 SHALL 显示每个产品的:
|
||||
- 月度入库总量
|
||||
- 月度出库总量
|
||||
- 月度净变化
|
||||
|
||||
#### Scenario: 按周汇总
|
||||
- **WHEN** 用户选择"按周"汇总
|
||||
- **THEN** 系统 SHALL 按周分组显示
|
||||
- **AND** 系统 SHALL 显示每个产品的:
|
||||
- 周度入库总量
|
||||
- 周度出库总量
|
||||
- 周度净变化
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 运输统计
|
||||
|
||||
系统 SHALL 支持按运输公司/车辆统计运输趟次和运费。
|
||||
|
||||
#### Scenario: 按运输公司统计
|
||||
- **WHEN** 用户选择"按运输公司"统计
|
||||
- **THEN** 系统 SHALL 显示每个运输公司的:
|
||||
- 运输趟次
|
||||
- 总运费
|
||||
- 平均运费
|
||||
|
||||
#### Scenario: 按车辆统计
|
||||
- **WHEN** 用户选择"按车辆"统计
|
||||
- **THEN** 系统 SHALL 显示每辆车的:
|
||||
- 运输趟次
|
||||
- 总运费
|
||||
- 运输里程
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 库存预警
|
||||
|
||||
系统 SHALL 支持按产品设置预警阈值并提供预警通知。
|
||||
|
||||
#### Scenario: 预警阈值设置
|
||||
- **WHEN** 管理员为产品设置预警阈值
|
||||
- **THEN** 系统 SHALL 支持设置:
|
||||
- 最低库存预警
|
||||
- 最高库存预警(如适用)
|
||||
|
||||
#### Scenario: 预警触发
|
||||
- **WHEN** 产品库存 ≤ 最低库存预警值
|
||||
- **THEN** 系统 SHALL 生成库存预警
|
||||
- **AND** 系统 SHALL 在工作台显示预警列表
|
||||
- **AND** 预警 SHALL 包含:
|
||||
- 产品名称
|
||||
- 当前库存
|
||||
- 预警阈值
|
||||
- 预警类型(低于最低/高于最高)
|
||||
|
||||
#### Scenario: 预警通知
|
||||
- **WHEN** 库存预警触发
|
||||
- **THEN** 系统 SHALL 通过系统消息通知相关人员
|
||||
- **AND** 通知 SHALL 包含产品信息和当前库存状态
|
||||
@@ -0,0 +1,59 @@
|
||||
# PL API JSON 命名(运输计划模块)
|
||||
|
||||
本能力补充 `openspec/changes/zkxw-engineering-standards/specs/api-conventions/spec.md` 中「JSON 字段命名」要求,**专用于** `app/api/pl/**` 与 `web-admin/src/api/pl/**`、`web-admin/src/views/pl/**`。
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 运输计划 API JSON 字段 camelCase 对齐
|
||||
|
||||
运输计划模块(路由前缀 `/api/transport/**`)的请求体、响应体及 Query 参数中,凡前端 TypeScript 使用 camelCase 的多词字段,后端 Pydantic Schema SHALL 通过 `Field(..., alias="camelCase")` 声明 JSON 别名,并设置 `model_config = {"populate_by_name": True}`(或 `ConfigDict(populate_by_name=True)`)。
|
||||
|
||||
路由层访问请求体 SHALL 使用 **Python snake_case 属性名**(如 `payload.carrier_name`),SHALL NOT 使用 `payload.carrierName`。
|
||||
|
||||
读接口(`response_model=...Read`)SHALL 为 ORM 列对应的 snake_case 字段配置 alias,使 FastAPI 默认 `response_model_by_alias=True` 输出 camelCase,与 `web-admin/src/api/pl/index.ts` 类型定义一致。
|
||||
|
||||
#### Scenario: 承运商新增
|
||||
|
||||
- **WHEN** 前端 `POST /api/transport/carrier` 请求体为 `{ "carrierName": "某某物流", "contactName": "张三", "status": "1" }`
|
||||
- **THEN** `CarrierCreate` SHALL 校验通过(HTTP 非 422)
|
||||
- **AND** 路由 SHALL 通过 `payload.carrier_name` 写入 `pl_carrier.carrier_name`
|
||||
|
||||
#### Scenario: 计划新增含产品明细
|
||||
|
||||
- **WHEN** 前端 `POST /api/transport/plan/` 请求体含 `belongsCompany`、`planType`、`planDate` 及 `products[].productId`
|
||||
- **THEN** `PlanCreate` / `PlanProductCreate` SHALL 校验通过
|
||||
- **AND** 响应 `PlanRead` / `PlanProductRead` 的 JSON 键 SHALL 为 `planNo`、`createTime` 等 camelCase
|
||||
|
||||
#### Scenario: 运输安排
|
||||
|
||||
- **WHEN** 前端 `POST /api/transport/order/arrange/{planId}` 请求体为 `{ "vehicleId": "...", "driverId": "...", "freightType": "by_weight" }`
|
||||
- **THEN** `TransportArrange` SHALL 校验通过
|
||||
- **AND** 路由 SHALL 使用 `payload.vehicle_id`、`payload.driver_id` 访问字段
|
||||
|
||||
#### Scenario: 列表分页 Query
|
||||
|
||||
- **WHEN** 前端 GET 列表接口 Query 为 `page=1&pageSize=20&planType=direct`
|
||||
- **THEN** 路由参数 SHALL 通过 `Query(..., alias="pageSize")` 或 Schema alias 正确解析
|
||||
- **AND** SHALL NOT 静默忽略 `pageSize` 导致始终使用默认每页 20 条
|
||||
|
||||
#### Scenario: 仅 snake_case 无 alias 视为缺陷
|
||||
|
||||
- **WHEN** `app/schemas/pl/**` 中 Write/Read Schema 的多词字段仅有 `snake_case` 属性名、无 `alias`
|
||||
- **THEN** 属于本变更范围内的规范违反;前端发送 camelCase 时将返回 **422 Unprocessable Entity**
|
||||
- **AND** 修复 SHALL 为后端补 alias,SHALL NOT 要求 web-admin 改为 snake_case
|
||||
|
||||
### Requirement: 运输计划 Schema 变更门禁
|
||||
|
||||
修改 `app/schemas/pl/**` 或新增 PL 写接口时,提交前 SHALL 运行 `python backend/scripts/check_pl_json_aliases.py`;脚本失败 SHALL 阻塞合并。
|
||||
|
||||
Schema 覆盖范围 SHALL 至少包括:
|
||||
|
||||
| 路径 | 说明 |
|
||||
|------|------|
|
||||
| `app/schemas/pl/__init__.py` | 承运商、车辆、司机 |
|
||||
| `app/schemas/pl/plan.py` | 计划与产品明细 |
|
||||
| `app/schemas/pl/transport.py` | 运输、安排、审批 |
|
||||
| `app/schemas/pl/freight.py` | 运费结算 |
|
||||
| `app/schemas/pl/inventory.py` | 库存、证件提醒 |
|
||||
|
||||
参考实现:`app/schemas/db/weighing.py`(地磅模块 alias 模式)。
|
||||
@@ -0,0 +1,75 @@
|
||||
# Transport Approval (运输审批)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 简单审批流程
|
||||
|
||||
系统 SHALL 支持简单审批流程(会签),允许用户选择审批人并按顺序审批。
|
||||
|
||||
#### Scenario: 提交审批
|
||||
- **WHEN** 用户点击"提交审批"
|
||||
- **THEN** 系统 SHALL 显示审批人选择界面
|
||||
- **AND** 用户 SHALL 选择审批人(可选择多人)
|
||||
- **AND** 审批顺序 SHALL 按照用户选择时的排序
|
||||
|
||||
#### Scenario: 审批规则
|
||||
- **WHEN** 用户提交审批
|
||||
- **THEN** 系统 SHALL 使用会签方式审批(所有人审批通过才算通过)
|
||||
- **AND** 系统 SHALL 按选择顺序依次审批
|
||||
- **AND** 每一级审批完成后才能进入下一级
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 运输计划状态流转
|
||||
|
||||
系统 SHALL 支持运输计划的完整状态流转,且不允许状态回退。
|
||||
|
||||
#### Scenario: 状态流转(不允许回退)
|
||||
- **WHEN** 运输计划处于某状态
|
||||
- **THEN** 系统 SHALL 仅允许向前流转至下一状态
|
||||
- **AND** 系统 SHALL 禁止回退至已过的状态
|
||||
- **WHEN** 运输计划状态流转至"已完成"或"已取消"
|
||||
- **THEN** 系统 SHALL 禁止任何状态变更
|
||||
|
||||
#### Scenario: 状态流转详情
|
||||
|
||||
| 当前状态 | 下一状态 | 说明 |
|
||||
|---------|---------|------|
|
||||
| 草稿 | 待执行/已取消 | 提交审批后进入待执行 |
|
||||
| 待执行 | 执行中/已取消 | 开始执行后进入执行中 |
|
||||
| 执行中 | 已完成/已取消 | 执行完成后进入已完成 |
|
||||
| 已完成 | - | 终态,不可变更 |
|
||||
| 已取消 | - | 终态,不可变更 |
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 审批记录
|
||||
|
||||
系统 SHALL 记录完整的审批历史。
|
||||
|
||||
#### Scenario: 审批记录内容
|
||||
- **WHEN** 审批人完成审批
|
||||
- **THEN** 系统 SHALL 记录审批人信息(id, name)
|
||||
- **AND** 系统 SHALL 记录审批结果(approved/rejected)
|
||||
- **AND** 系统 SHALL 记录审批意见
|
||||
- **AND** 系统 SHALL 记录审批时间
|
||||
- **AND** 系统 SHALL 记录审批耗时
|
||||
|
||||
#### Scenario: 审批拒绝处理
|
||||
- **WHEN** 审批人拒绝审批
|
||||
- **THEN** 系统 SHALL 将计划状态回退至"草稿"
|
||||
- **AND** 系统 SHALL 通知申请人审批被拒绝
|
||||
- **AND** 系统 SHALL 保留审批拒绝记录
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 审批人选择
|
||||
|
||||
系统 SHALL 支持从组织架构或用户列表中选择审批人。
|
||||
|
||||
#### Scenario: 选择审批人
|
||||
- **WHEN** 用户点击"选择审批人"
|
||||
- **THEN** 系统 SHALL 显示用户选择器
|
||||
- **AND** 用户 SHALL 能搜索和选择多个用户
|
||||
- **AND** 用户 SHALL 能调整审批顺序
|
||||
- **AND** 系统 SHALL 记住用户的选择顺序
|
||||
@@ -0,0 +1,109 @@
|
||||
# Transport Order (运输单管理)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 运输安排
|
||||
|
||||
系统 SHALL 支持运输安排,包括选择车辆类型、车辆、司机,填写运输信息。
|
||||
|
||||
#### Scenario: 选择自有车辆
|
||||
- **WHEN** 用户选择车辆类型为"自有"
|
||||
- **THEN** 系统 SHALL 仅显示自有车辆列表
|
||||
- **AND** 用户选择具体车辆后
|
||||
- **THEN** 系统 SHALL 自动带出该车辆的默认司机
|
||||
|
||||
#### Scenario: 选择承运商车辆
|
||||
- **WHEN** 用户选择车辆类型为"承运商"
|
||||
- **THEN** 系统 SHALL 仅显示承运商车辆列表
|
||||
- **AND** 用户选择承运商后
|
||||
- **THEN** 系统 SHALL 仅显示该承运商名下的车辆
|
||||
- **AND** 用户选择具体车辆后
|
||||
- **THEN** 系统 SHALL 自动带出该车辆的默认司机
|
||||
|
||||
#### Scenario: 运输信息填写
|
||||
- **WHEN** 用户完成运输安排
|
||||
- **THEN** 系统 SHALL 生成运输编号(格式:`SXYS######`,每月重置)
|
||||
- **AND** 系统 SHALL 将运输安排状态从"待安排"更新为"已安排"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 车辆归属唯一性
|
||||
|
||||
系统 SHALL 确保同一辆车只能属于一种类型(自有 或 承运商)。
|
||||
|
||||
#### Scenario: 车辆归属约束
|
||||
- **WHEN** 管理员新增或编辑车辆
|
||||
- **THEN** 系统 SHALL 要求选择车辆归属类型(自有/承运商)
|
||||
- **AND** 系统 SHALL 确保同一辆车只能选择一个归属类型
|
||||
- **AND** 系统 SHALL 禁止同一车牌号同时属于自有和承运商
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 二维码生成与分发
|
||||
|
||||
系统 SHALL 支持生成二维码供司机/现场人员扫码。
|
||||
|
||||
#### Scenario: 二维码生成
|
||||
- **WHEN** 用户点击"生成二维码"
|
||||
- **THEN** 系统 SHALL 生成包含运输单信息的二维码
|
||||
- **AND** 系统 SHALL 显示有效期设置(默认不设期限,用户可手动填写)
|
||||
- **AND** 系统 SHALL 提供下载二维码图片功能
|
||||
|
||||
#### Scenario: 二维码分发
|
||||
- **WHEN** 用户下载二维码图片
|
||||
- **THEN** 系统 SHALL 提示用户截图发送给司机/现场人员
|
||||
- **AND** 二维码 SHALL 包含运输单号、产品信息、目的地等关键信息
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 司机扫码回传
|
||||
|
||||
系统 SHALL 支持司机扫描二维码回传运输信息,无需登录。
|
||||
|
||||
#### Scenario: 司机扫码
|
||||
- **WHEN** 司机扫描运输单二维码
|
||||
- **THEN** 系统 SHALL 允许无需登录即可访问回传页面
|
||||
- **AND** 系统 SHALL 允许回传以下信息:
|
||||
- 运输单据照片
|
||||
- 运输数量
|
||||
- 其他信息(备注等)
|
||||
|
||||
#### Scenario: 现场人员扫码
|
||||
- **WHEN** 现场人员扫描二维码
|
||||
- **THEN** 系统 SHALL 要求登录验证权限
|
||||
- **AND** 系统 SHALL 显示完整的单据详情供查看
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 运输与计划关系
|
||||
|
||||
系统 SHALL 支持计划与运输的 N:N 关系。
|
||||
|
||||
#### Scenario: 1:1 关系
|
||||
- **WHEN** 一个计划对应一趟运输
|
||||
- **THEN** 系统 SHALL 允许直接关联
|
||||
|
||||
#### Scenario: 1:N 关系(分车装运)
|
||||
- **WHEN** 一个计划需要多趟运输(分车装运)
|
||||
- **THEN** 系统 SHALL 允许创建多个运输单关联同一计划
|
||||
|
||||
#### Scenario: N:1 关系(拼车)
|
||||
- **WHEN** 多个计划合并一趟运输(拼车)
|
||||
- **THEN** 系统 SHALL 允许一个运输单关联多个计划
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 待入库/待出库单据同步
|
||||
|
||||
系统 SHALL 支持待入库/待出库单据的自动同步。
|
||||
|
||||
#### Scenario: 单据自动生成
|
||||
- **WHEN** 计划状态流转至"待入库"或"待出库"
|
||||
- **THEN** 系统 SHALL 自动生成地磅单
|
||||
- **AND** 系统 SHALL 通过系统消息通知现场工作人员
|
||||
- **AND** 系统 SHALL 支持复制文本通过微信发送
|
||||
|
||||
#### Scenario: 地磅数据录入
|
||||
- **WHEN** 现场工作人员确认地磅数据
|
||||
- **THEN** 系统 SHALL 允许手动填写地磅数据(不对接硬件)
|
||||
- **AND** 系统 SHALL 允许上传单据和附件
|
||||
@@ -0,0 +1,190 @@
|
||||
# Transport Plan (运输计划管理)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 计划可从 CRM 合同发起
|
||||
|
||||
系统 SHALL 支持从 CRM 合同发起运输计划,自动带入合同基本信息、商品明细、结算方式等数据。
|
||||
|
||||
#### Scenario: 从合同发起计划
|
||||
- **WHEN** 用户选择 CRM 合同并点击"发起计划"
|
||||
- **THEN** 系统 SHALL 自动带入客户信息(customer_id, customer_name)
|
||||
- **AND** 系统 SHALL 自动带入联系人信息(contact_name, contact_mobile)
|
||||
- **AND** 系统 SHALL 自动带入甲方/乙方信息(party_a*, party_b*)
|
||||
- **AND** 系统 SHALL 自动带入合同有效期(start_date, end_date)
|
||||
- **AND** 系统 SHALL 自动带入结算方式(settlement_method)
|
||||
- **AND** 系统 SHALL 自动带入商品明细(从 crm_contract_product 读取 product_id, product_name, model, unit, price)
|
||||
- **AND** 系统 SHALL 自动带入送货方式(delivery_method)
|
||||
|
||||
#### Scenario: 合同关联字段映射
|
||||
|
||||
| CRM 合同字段 | 计划字段 |
|
||||
|-------------|---------|
|
||||
| customer_id | customer_id |
|
||||
| customer_name | customer_name |
|
||||
| contact_name | contact_name |
|
||||
| contact_mobile | contact_mobile |
|
||||
| party_a* | party_a* |
|
||||
| party_b* | party_b* |
|
||||
| start_date | plan_start_date |
|
||||
| end_date | plan_end_date |
|
||||
| settlement_method | settlement_method |
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 单据类型自动判断
|
||||
|
||||
系统 SHALL 根据供应商和目的地自动判断单据类型(直销单/入库单/出库单)。
|
||||
|
||||
#### Scenario: 判断为入库单
|
||||
- **WHEN** 目的地 = "安庆山峡" OR 目的地 = "安徽云栋"
|
||||
- **THEN** 系统 SHALL 将单据类型设置为"入库单"
|
||||
|
||||
#### Scenario: 判断为出库单
|
||||
- **WHEN** 供应商 = "安庆山峡" OR 供应商 = "安徽云栋"
|
||||
- **THEN** 系统 SHALL 将单据类型设置为"出库单"
|
||||
|
||||
#### Scenario: 判断为直销单
|
||||
- **WHEN** 供应商 ≠ "安庆山峡" AND 供应商 ≠ "安徽云栋" AND 目的地 ≠ "安庆山峡" AND 目的地 ≠ "安徽云栋"
|
||||
- **THEN** 系统 SHALL 将单据类型设置为"直销单"
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 产品属性检查
|
||||
|
||||
系统 SHALL 在安排运输前检查产品属性,易制毒/易制爆产品必须上传购买证和运输证。
|
||||
|
||||
#### Scenario: 易制毒产品需上传证件
|
||||
- **WHEN** 产品属性包含"易制毒"且用户点击"安排运输"
|
||||
- **THEN** 系统 SHALL 检查是否已上传购买证
|
||||
- **AND** 系统 SHALL 检查是否已上传运输证
|
||||
- **IF** 任一证件缺失
|
||||
- **THEN** 系统 SHALL 阻止安排运输并提示用户上传缺失证件
|
||||
|
||||
#### Scenario: 易制爆产品需上传证件
|
||||
- **WHEN** 产品属性包含"易制爆"且用户点击"安排运输"
|
||||
- **THEN** 系统 SHALL 检查是否已上传购买证
|
||||
- **AND** 系统 SHALL 检查是否已上传运输证
|
||||
- **IF** 任一证件缺失
|
||||
- **THEN** 系统 SHALL 阻止安排运输并提示用户上传缺失证件
|
||||
|
||||
#### Scenario: 普通产品无需证件
|
||||
- **WHEN** 产品不包含"易制毒"和"易制爆"属性
|
||||
- **THEN** 系统 SHALL 允许直接安排运输,无需上传证件
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 跟进状态流转
|
||||
|
||||
系统 SHALL 支持跟进状态的完整流转,并支持任意状态下取消。
|
||||
|
||||
#### Scenario: 直销单状态流转
|
||||
- **WHEN** 直销单状态为"等客户确认"且用户确认要货
|
||||
- **THEN** 系统 SHALL 将状态流转至"待采购"
|
||||
- **WHEN** 直销单状态为"待采购"且采购完成
|
||||
- **THEN** 系统 SHALL 将状态流转至"待发货"
|
||||
- **WHEN** 直销单状态为"待发货"且货物发出
|
||||
- **THEN** 系统 SHALL 将状态流转至"待收货"
|
||||
- **WHEN** 直销单状态为"待收货"且客户确认收货
|
||||
- **THEN** 系统 SHALL 将状态流转至"待归档"
|
||||
- **WHEN** 直销单状态为"待归档"且用户点击归档
|
||||
- **THEN** 系统 SHALL 将状态流转至"归档完成"
|
||||
|
||||
#### Scenario: 入库单状态流转
|
||||
- **WHEN** 入库单状态为"待采购"且采购完成
|
||||
- **THEN** 系统 SHALL 将状态流转至"待发货"
|
||||
- **WHEN** 入库单状态为"待发货"且货物到达
|
||||
- **THEN** 系统 SHALL 将状态流转至"待入库"
|
||||
- **WHEN** 入库单状态为"待入库"且地磅确认入库
|
||||
- **THEN** 系统 SHALL 将状态流转至"已入库"
|
||||
- **WHEN** 入库单状态为"已入库"且用户点击归档
|
||||
- **THEN** 系统 SHALL 将状态流转至"归档完成"
|
||||
|
||||
#### Scenario: 出库单状态流转
|
||||
- **WHEN** 出库单状态为"等客户确认"且客户确认要货
|
||||
- **THEN** 系统 SHALL 将状态流转至"待出库"
|
||||
- **WHEN** 出库单状态为"待出库"且货物出库
|
||||
- **THEN** 系统 SHALL 将状态流转至"已出库"
|
||||
- **WHEN** 出库单状态为"已出库"且客户确认收货
|
||||
- **THEN** 系统 SHALL 将状态流转至"已收货"
|
||||
- **WHEN** 出库单状态为"已收货"且用户点击归档
|
||||
- **THEN** 系统 SHALL 将状态流转至"归档完成"
|
||||
|
||||
#### Scenario: 任意状态下取消计划
|
||||
- **WHEN** 用户在任意跟进状态下点击"取消计划"
|
||||
- **THEN** 系统 SHALL 将计划状态设置为"已取消"
|
||||
- **AND** 系统 SHALL 保留运输信息并标记为"已取消"
|
||||
- **AND** 系统 SHALL 禁止该计划继续流转
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 归档操作
|
||||
|
||||
系统 SHALL 支持归档操作,归档后自动更新归档状态和完成状态。
|
||||
|
||||
#### Scenario: 归档操作
|
||||
- **WHEN** 计划处于"待归档"状态且用户点击"归档"
|
||||
- **THEN** 系统 SHALL 将归档状态从"未归档"更新为"已归档"
|
||||
- **AND** 系统 SHALL 将完成状态从"否"更新为"是"
|
||||
- **AND** 系统 SHALL 禁止该计划继续修改
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 计划编号规则
|
||||
|
||||
系统 SHALL 按照规则自动生成计划订单编号。
|
||||
|
||||
#### Scenario: 计划编号生成
|
||||
- **WHEN** 用户新建计划
|
||||
- **THEN** 系统 SHALL 生成编号格式为 `SXDDHYYYYMMDD######`
|
||||
- **WHEREIN** `YYYYMMDD` 为当前日期
|
||||
- **AND** `######` 为当日6位序号(从000001开始,每日重置)
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 金额计算规则
|
||||
|
||||
系统 SHALL 支持入库金额和出库金额的自动计算。
|
||||
|
||||
#### Scenario: 入库金额计算
|
||||
- **WHEN** 用户填写入库数量或修改入库价
|
||||
- **THEN** 系统 SHALL 自动计算入库金额 = 入库数 × 入库价
|
||||
- **AND** 入库价默认值为合同价格,支持后续修改
|
||||
|
||||
#### Scenario: 出库金额计算
|
||||
- **WHEN** 用户填写出库数量或修改出库价
|
||||
- **THEN** 系统 SHALL 自动计算出库金额 = 出库数 × 出库价
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 通知信息生成
|
||||
|
||||
系统 SHALL 按模板生成通知信息,通知信息不可编辑。
|
||||
|
||||
#### Scenario: 通知信息模板
|
||||
- **WHEN** 系统生成通知信息
|
||||
- **THEN** 系统 SHALL 使用以下模板格式:
|
||||
|
||||
```
|
||||
计划号:{plan_no}
|
||||
企业名称:{customer_name}
|
||||
提货单位:{destination}
|
||||
到货时间:{delivery_date}
|
||||
药品名称:{product_name}
|
||||
到货吨位:{quantity}吨
|
||||
备注:{remark}
|
||||
```
|
||||
|
||||
- **AND** 用户 SHALL NOT 直接编辑通知信息内容
|
||||
|
||||
---
|
||||
|
||||
### Requirement: Web 管理端按钮须携带图标
|
||||
|
||||
运输计划模块 `web-admin/src/views/pl/**`(承运商管理、车辆管理、司机管理、运输计划、运输管理、运费结算、库存台账、证件提醒及 form/detail/arrange 子页)SHALL 遵循 OpenSpec `ui-conventions` 中 **「按钮须携带图标」** Requirement:凡带可见文案的 `el-button` 须在文字前方包含 `<el-icon>`,图标从 `@element-plus/icons-vue` 显式导入。
|
||||
|
||||
#### Scenario: 运输计划菜单页面按钮展示
|
||||
|
||||
- **WHEN** 用户打开运输计划菜单下任一列表、表单或详情页
|
||||
- **THEN** 筛选区「搜索」「重置」、工具栏「新增」、操作列「查看/编辑/删除/安排运输/提交/审核/处理」、弹窗与页脚「取消/确定/返回」等带文案按钮 SHALL 均携带语义图标
|
||||
- **THEN** SHALL NOT 出现仅有文字、无 `<el-icon>` 的按钮
|
||||
@@ -0,0 +1,74 @@
|
||||
# Vehicle, Personnel & Certificate(车辆/人员/证书管理)
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: 车辆档案管理
|
||||
|
||||
系统 SHALL 支持车辆档案的完整管理,含关联人员子表与车辆证书子表。
|
||||
|
||||
#### Scenario: 车辆信息维护
|
||||
- **WHEN** 管理员新增或编辑车辆
|
||||
- **THEN** 系统 SHALL 记录车牌号(唯一)、车辆类型(自有/承运商)、承运商(类型为承运商时)、载重、车辆状态(可用/维修中/报废)、备注
|
||||
- **AND** 系统 SHALL 在车辆弹窗内以子表维护关联人员(姓名、手机号非必填、年龄、人员类型、关联备注、默认司机)
|
||||
- **AND** 系统 SHALL 在车辆弹窗内以子表维护车辆证书(证书名称、证号、有效期、提前提醒天数,默认 30)
|
||||
|
||||
#### Scenario: 车辆归属管理
|
||||
- **WHEN** 管理员编辑车辆归属类型
|
||||
- **THEN** 系统 SHALL 确保同一辆车只能属于一种类型(自有或承运商)
|
||||
- **AND** 系统 SHALL 禁止同一车牌号重复
|
||||
|
||||
#### Scenario: 车辆关联人员
|
||||
- **WHEN** 管理员在车辆弹窗维护关联人员子表
|
||||
- **THEN** 系统 SHALL 支持每车多人,人员类型为司机或押运员
|
||||
- **AND** 系统 SHALL 确保每辆车最多一名默认司机(仅 role=driver 的行可设为默认)
|
||||
- **AND** 系统 SHALL 在保存时 upsert 人员主数据(有手机号时按手机号去重,无手机号时按姓名弱匹配)
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 人员档案管理
|
||||
|
||||
系统 SHALL 支持人员(司机、押运员等)档案的独立管理。
|
||||
|
||||
#### Scenario: 人员信息维护
|
||||
- **WHEN** 管理员新增或编辑人员
|
||||
- **THEN** 系统 SHALL 记录姓名(必填)、手机号(非必填)、年龄、身份证号、在职状态、备注
|
||||
- **AND** 系统 SHALL 以子表维护人员证书(证书名称、证号、有效期、提前提醒天数,默认 30)
|
||||
- **AND** 系统 SHALL NOT 在人员表写死驾驶证/行驶证/危化品证等字段
|
||||
|
||||
#### Scenario: 人员与车辆绑定
|
||||
- **WHEN** 管理员在车辆弹窗或人员管理中维护绑定关系
|
||||
- **THEN** 系统 SHALL 允许同一人员关联多辆车、同一车辆关联多人
|
||||
- **AND** 系统 SHALL 在运输安排选择车辆后自动带出该车的默认司机
|
||||
- **AND** 系统 SHALL 在安排运输时司机下拉仅展示该车 role=driver 的关联人员
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 动态证书管理
|
||||
|
||||
系统 SHALL 使用独立证书表管理车辆与人员的各类证书。
|
||||
|
||||
#### Scenario: 证书实例维护
|
||||
- **WHEN** 管理员为车辆或人员添加证书
|
||||
- **THEN** 系统 SHALL 记录 owner_type(vehicle/personnel)、证书名称、证号、有效期、remind_days(默认 30)、附件
|
||||
- **AND** 系统 SHALL 允许同一主体持有多个证书,证种可动态增删
|
||||
- **AND** 证书附件 SHALL 使用 OpenSpec「附件上传卡片化布局」:`AttachmentUploadField` 组件,多附件以逗号分隔 URL 存入 `attachment_urls`;支持上传、下载、图片预览
|
||||
|
||||
#### Scenario: 证书到期提醒
|
||||
- **WHEN** 证书 expire_date 非空且剩余天数 ≤ remind_days
|
||||
- **THEN** 系统 SHALL 通过定时任务扫描 pl_cert 生成 pl_document_reminder
|
||||
- **AND** 提醒 SHALL 覆盖车辆与人员证书
|
||||
- **AND** 提醒列表 SHALL 展示主体类型、主体名称(车牌/姓名)、证书名称、到期日期、剩余天数
|
||||
|
||||
---
|
||||
|
||||
### Requirement: 承运商管理
|
||||
|
||||
系统 SHALL 支持承运商档案管理(不变)。
|
||||
|
||||
#### Scenario: 承运商信息维护
|
||||
- **WHEN** 管理员新增承运商
|
||||
- **THEN** 系统 SHALL 记录承运商名称、联系人、联系电话、合作状态(合作中/已终止)
|
||||
|
||||
#### Scenario: 承运商车辆筛选
|
||||
- **WHEN** 用户选择承运商后安排运输
|
||||
- **THEN** 系统 SHALL 仅显示该承运商名下的车辆
|
||||
@@ -0,0 +1,200 @@
|
||||
# 运输计划管理系统 - 实施任务清单
|
||||
|
||||
## 1. 数据库设计与创建
|
||||
|
||||
### 1.1 基础数据表
|
||||
|
||||
- [x] 1.1.1 创建承运商表 `pl_carrier`
|
||||
- [x] 1.1.2 创建车辆表 `pl_vehicle`
|
||||
- [x] 1.1.3 创建司机表 `pl_driver`
|
||||
- [x] 1.1.4 创建证件提醒表 `pl_document_reminder`
|
||||
|
||||
### 1.2 计划管理表
|
||||
|
||||
- [x] 1.2.1 创建计划主表 `pl_plan`
|
||||
- [x] 1.2.2 创建计划产品明细表 `pl_plan_product`
|
||||
- [ ] 1.2.3 创建计划变更记录表 `pl_plan_change`
|
||||
|
||||
### 1.3 运输管理表
|
||||
|
||||
- [x] 1.3.1 创建运输表 `pl_transport`
|
||||
- [x] 1.3.2 创建计划-运输关联表 `pl_plan_transport`
|
||||
- [x] 1.3.3 创建运输审批记录表 `pl_transport_approval`
|
||||
|
||||
### 1.4 运费结算表
|
||||
|
||||
- [x] 1.4.1 创建运费结算表 `pl_freight_settlement`
|
||||
- [ ] 1.4.2 创建汇款凭证表 `pl_remittance_voucher`
|
||||
|
||||
### 1.5 库存管理表
|
||||
|
||||
- [x] 1.5.1 创建库存表 `pl_inventory`
|
||||
- [x] 1.5.2 创建库存预警表 `pl_inventory_warning`
|
||||
|
||||
---
|
||||
|
||||
## 2. 后端 API 开发
|
||||
|
||||
### 2.1 基础数据 API
|
||||
|
||||
- [x] 2.1.1 实现承运商 CRUD API (`/api/carrier/*`)
|
||||
- [x] 2.1.2 实现车辆 CRUD API (`/api/vehicle/*`)
|
||||
- [x] 2.1.3 实现司机 CRUD API (`/api/driver/*`)
|
||||
- [x] 2.1.4 实现车辆列表 API(含承运商筛选)
|
||||
- [x] 2.1.5 实现司机列表 API(含车辆绑定信息)
|
||||
|
||||
### 2.2 计划管理 API
|
||||
|
||||
- [x] 2.2.1 实现计划列表 API (`/api/plan/list`)
|
||||
- [x] 2.2.2 实现计划详情 API (`/api/plan/{id}`)
|
||||
- [x] 2.2.3 实现从合同发起计划 API (`/api/plan/create-from-contract`)
|
||||
- [x] 2.2.4 实现计划编辑 API (`/api/plan/{id}`, PUT)
|
||||
- [x] 2.2.5 实现计划取消 API (`/api/plan/{id}/cancel`)
|
||||
- [x] 2.2.6 实现计划归档 API (`/api/plan/{id}/archive`)
|
||||
- [x] 2.2.7 实现跟进状态流转 API (`/api/plan/{id}/status`)
|
||||
- [x] 2.2.8 实现单据类型自动判断逻辑
|
||||
- [x] 2.2.9 实现产品属性检查逻辑(易制毒/易制爆)
|
||||
- [x] 2.2.10 实现金额自动计算逻辑(入库/出库金额)
|
||||
|
||||
### 2.3 运输管理 API
|
||||
|
||||
- [x] 2.3.1 实现运输安排 API (`/api/transport/arrange`)
|
||||
- [x] 2.3.2 实现运输列表 API (`/api/transport/list`)
|
||||
- [x] 2.3.3 实现运输详情 API (`/api/transport/{id}`)
|
||||
- [x] 2.3.4 实现二维码生成 API (`/api/transport/{id}/qrcode`)
|
||||
- [x] 2.3.5 实现司机扫码回传 API (`/api/transport/scan/feedback`)
|
||||
- [x] 2.3.6 实现计划-运输关联管理 API (`/api/plan-transport/*`)
|
||||
|
||||
### 2.4 审批流程 API
|
||||
|
||||
- [x] 2.4.1 实现提交审批 API (`/api/transport/{id}/submit-approval`)
|
||||
- [x] 2.4.2 实现审批 API (`/api/approval/{id}`)
|
||||
- [x] 2.4.3 实现审批列表 API (`/api/approval/list`)
|
||||
- [x] 2.4.4 实现审批详情 API (`/api/approval/{id}/detail`)
|
||||
|
||||
### 2.5 运费结算 API
|
||||
|
||||
- [x] 2.5.1 实现结算单生成 API (`/api/freight/generate`)
|
||||
- [x] 2.5.2 实现结算单列表 API (`/api/freight/list`)
|
||||
- [x] 2.5.3 实现结算单详情 API (`/api/freight/{id}`)
|
||||
- [x] 2.5.4 实现结算单提交 API (`/api/freight/{id}/submit`)
|
||||
- [x] 2.5.5 实现结算单审核 API (`/api/freight/{id}/approve`)
|
||||
- [x] 2.5.6 实现发票信息记录 API (`/api/freight/{id}/invoice`)
|
||||
- [x] 2.5.7 实现汇款凭证上传 API (`/api/freight/{id}/voucher`)
|
||||
|
||||
### 2.6 盘存统计 API
|
||||
|
||||
- [x] 2.6.1 实现库存台账 API (`/api/inventory/ledger`)
|
||||
- [x] 2.6.2 实现出入库明细 API (`/api/inventory/details`)
|
||||
- [x] 2.6.3 实现出入库汇总 API (`/api/inventory/summary`)
|
||||
- [x] 2.6.4 实现运输统计 API (`/api/inventory/transport-stats`)
|
||||
- [x] 2.6.5 实现库存预警列表 API (`/api/inventory/warnings`)
|
||||
- [x] 2.6.6 实现预警阈值设置 API (`/api/inventory/warning-threshold`)
|
||||
|
||||
---
|
||||
|
||||
## 3. 前端页面开发
|
||||
|
||||
### 3.1 基础数据管理页面
|
||||
|
||||
- [x] 3.1.1 实现承运商管理页面 (`/views/transport/carrier/index.vue`)
|
||||
- [x] 3.1.2 实现车辆管理页面 (`/views/transport/vehicle/index.vue`)
|
||||
- [x] 3.1.3 实现司机管理页面 (`/views/transport/driver/index.vue`)
|
||||
- [x] 3.1.4 实现证件到期提醒页面 (`/views/transport/document-reminder/index.vue`)
|
||||
|
||||
### 3.2 计划管理页面
|
||||
|
||||
- [x] 3.2.1 实现计划列表页面 (`/views/pl/plan/index.vue`)
|
||||
- [x] 3.2.2 实现计划新增/编辑页面 (`/views/pl/plan/form.vue`)
|
||||
- [x] 3.2.3 实现计划详情页面 (`/views/pl/plan/detail.vue`)
|
||||
- [x] 3.2.4 实现运输安排页面 (`/views/pl/plan/arrange.vue`)
|
||||
|
||||
### 3.3 运输管理页面
|
||||
|
||||
- [x] 3.3.1 实现运输列表页面 (`/views/pl/transport/index.vue`)
|
||||
|
||||
### 3.4 运费结算页面
|
||||
|
||||
- [x] 3.4.1 实现结算单列表页面 (`/views/pl/freight/index.vue`)
|
||||
|
||||
### 3.5 盘存统计页面
|
||||
|
||||
- [x] 3.5.1 实现库存台账页面 (`/views/pl/inventory/ledger.vue`)
|
||||
- [x] 3.5.2 实现证件提醒页面 (`/views/pl/inventory/document-reminder.vue`)
|
||||
- [x] 3.6 车辆/人员/证书重构(`docs/superpowers/specs/2026-06-19-pl-vehicle-personnel-cert-design.md`)
|
||||
|
||||
### 3.7 工作台集成
|
||||
|
||||
- [ ] 3.7.1 实现待办任务列表组件 (`PendingTasks.vue`)
|
||||
- [ ] 3.7.2 实现证件到期提醒组件 (`DocumentReminder.vue`)
|
||||
- [ ] 3.7.3 实现库存预警提醒组件 (`InventoryWarning.vue`)
|
||||
|
||||
---
|
||||
|
||||
## 4. 定时任务开发
|
||||
|
||||
- [ ] 4.1 实现证件过期提醒定时任务(每日检查)
|
||||
- [ ] 4.2 实现库存预警检查定时任务(每日检查)
|
||||
- [ ] 4.3 实现库存统计更新定时任务(可选,如有统计表)
|
||||
|
||||
---
|
||||
|
||||
## 5. 菜单与权限配置
|
||||
|
||||
- [ ] 5.1 配置计划管理菜单
|
||||
- [ ] 5.2 配置运输管理菜单
|
||||
- [ ] 5.3 配置审批管理菜单
|
||||
- [ ] 5.4 配置运费结算菜单
|
||||
- [ ] 5.5 配置盘存统计菜单
|
||||
- [ ] 5.6 配置基础数据管理菜单(车辆、司机、承运商)
|
||||
- [ ] 5.7 配置权限标识(`transport:plan:*`, `transport:vehicle:*` 等)
|
||||
|
||||
---
|
||||
|
||||
## 6. 路由配置
|
||||
|
||||
- [x] 6.1 配置后端 API 路由注册(`app/api/__init__.py`, `app/main.py`)
|
||||
- [x] 6.2 配置前端路由(`web-admin/src/router/modules/pl.ts`)
|
||||
|
||||
---
|
||||
|
||||
## 7. 测试与验证
|
||||
|
||||
### 7.1 单元测试
|
||||
|
||||
- [ ] 7.1.1 编写单据类型判断逻辑测试
|
||||
- [ ] 7.1.2 编写金额计算逻辑测试
|
||||
- [ ] 7.1.3 编写审批流程逻辑测试
|
||||
- [ ] 7.1.4 编写运费计算逻辑测试
|
||||
|
||||
### 7.2 API 测试
|
||||
|
||||
- [ ] 7.2.1 验证计划 CRUD API
|
||||
- [ ] 7.2.2 验证运输安排 API
|
||||
- [ ] 7.2.3 验证审批流程 API
|
||||
- [ ] 7.2.4 验证运费结算 API
|
||||
|
||||
### 7.3 集成测试
|
||||
|
||||
- [ ] 7.3.1 验证从合同发起计划完整流程
|
||||
- [ ] 7.3.2 验证审批流程完整流转
|
||||
- [ ] 7.3.3 验证运费结算完整流程
|
||||
- [ ] 7.3.4 验证盘存统计准确性
|
||||
|
||||
---
|
||||
|
||||
## 8. 文档与培训
|
||||
|
||||
- [ ] 8.1 编写用户操作手册
|
||||
- [ ] 8.2 更新 API 文档
|
||||
- [ ] 8.3 编写技术设计文档(如有更新)
|
||||
|
||||
---
|
||||
|
||||
## 9. 部署与上线
|
||||
|
||||
- [ ] 9.1 执行数据库变更脚本
|
||||
- [ ] 9.2 部署后端服务
|
||||
- [ ] 9.3 部署前端服务
|
||||
- [ ] 9.4 配置生产环境参数
|
||||
- [ ] 9.5 验证生产环境功能
|
||||
@@ -161,7 +161,21 @@ Web 管理端(`web-admin`)与对外 JSON 接口中,**请求体与响应 `d
|
||||
|
||||
列表/详情等读接口的 `_row_to_dict`(或等价转换)SHALL 将 ORM 列名转为 camelCase 键名再返回前端。
|
||||
|
||||
参考实现:`app/api/admin.py` 中 `TenantCreateBody`;CRM:`app/schemas/crm/customer.py`、`app/schemas/crm/product.py`;路由:`app/api/crm.py`(客户列表/公海池)。
|
||||
参考实现:`app/api/admin.py` 中 `TenantCreateBody`;CRM:`app/schemas/crm/customer.py`、`app/schemas/crm/product.py`;路由:`app/api/crm.py`(客户列表/公海池);**运输计划**:`app/schemas/pl/**`(`openspec/changes/transport-plan-management/specs/pl-api-json/spec.md`);地磅:`app/schemas/db/weighing.py`。
|
||||
|
||||
FastAPI 路由 Query 参数若 Python 参数名为 `page_size`,SHALL 声明 `Query(..., alias="pageSize")`,与前端列表分页一致。
|
||||
|
||||
#### Scenario: 运输计划承运商新增 422 回归
|
||||
|
||||
- **WHEN** 前端 `POST /api/transport/carrier` 发送 `{ "carrierName": "测试" }`
|
||||
- **THEN** `CarrierCreate` SHALL 含 `carrier_name = Field(..., alias="carrierName")` 且校验通过
|
||||
- **AND** SHALL NOT 因缺少 alias 返回 422 `carrier_name Field required`
|
||||
|
||||
#### Scenario: 运输计划列表 pageSize Query
|
||||
|
||||
- **WHEN** 前端 `GET /api/transport/plan/?page=2&pageSize=50`
|
||||
- **THEN** 路由 SHALL 使用 `page_size: int = Query(..., alias="pageSize")` 解析为 50
|
||||
- **AND** SHALL NOT 忽略 `pageSize` 而始终使用默认 20
|
||||
|
||||
#### Scenario: 前端提交新增分类
|
||||
|
||||
|
||||
@@ -264,9 +264,9 @@ Web 管理端弹窗 SHALL 遵循规范:表单 `label-position="top"`;遮罩
|
||||
1. **操作列「查看」按钮**:操作列 SHALL 在首位包含一个「查看」按钮(`<el-icon><View /></el-icon>查看`),点击后弹出只读查看弹窗。
|
||||
2. **行双击触发**:`el-table` SHALL 监听 `@row-dblclick` 事件,双击任意行时触发与「查看」按钮相同的弹窗(即调用同一 `handleView(row)` 函数)。
|
||||
3. **条件按钮场景**:当操作列按钮随状态/Tab 变化(如待确认 Tab 显示「确认收款」,已确认 Tab 显示「查看确认信息」),`@row-dblclick` handler SHALL 仅在「查看」类按钮可见时触发对应查看函数,其余状态下可忽略或调用对应主操作函数。
|
||||
3. **弹窗样式**:查看弹窗 SHALL 使用 `SystemViewDialog` 共享组件(`src/components/business/system-view-dialog/index.vue`),样式对齐待办中心「查看详情」弹窗(无标题栏、hero 渐变头图 + 图标、KV grid 字段展示、关闭按钮)。
|
||||
4. **字段内容**:查看弹窗 SHALL 展示该行记录的所有业务字段(含状态映射、字典翻译),不展示 `id`、`del_flag` 等技术字段。长文本/备注字段 SHALL 使用 `span: true` 跨两列展示。
|
||||
5. **区块标题样式**:查看弹窗中各区块标题(`SystemViewDialog` 的 section title,渲染为 `h3`)SHALL 与字段标签(`dt`)形成明显视觉区分。区块标题 SHALL 使用深色文字(`#1e293b`)配合左侧主色竖条装饰(`border-left: 3px solid #10b981`),字号 14px、`font-weight: 600`;字段标签 SHALL 保持为辅助灰色(`#64748b`)、`font-weight: 500`。区块标题样式 SHALL NOT 与字段标签使用相同颜色或相近字重。
|
||||
4. **弹窗组件**:查看弹窗 SHALL 优先使用 `SystemViewDialog`(`web-admin/src/components/business/system-view-dialog/index.vue`);样式对齐 Hero 渐变头图 + 分区 KV 信息区 + 底部「关闭」按钮(详见下文「查看弹窗 KV 布局与组件选型」)。KV 信息区 SHALL 使用 `ViewKvGrid`(上下堆叠栅格)或 `ViewKvTable`(多组多列表格);**SHALL NOT** 使用 `el-descriptions` 或历史 `.dlg-kv` 布局承载列表行查看详情。
|
||||
5. **字段内容**:查看弹窗 SHALL 展示该行记录的所有业务字段(含状态映射、字典翻译),不展示 `id`、`del_flag` 等技术字段;KV 跨列/换行规则见「查看弹窗 KV 布局与组件选型」。
|
||||
6. **区块标题样式**:查看弹窗中各区块标题(如 `SystemViewDialog` 的 section title、`bx` 模块 `.dlg-view-section-title`,渲染为 `h3`/`h4`)SHALL 与字段标签形成明显视觉区分。区块标题 SHALL 使用深色文字(`#1e293b`)配合左侧主色竖条装饰(`border-left: 3px solid #10b981`),字号 14px、`font-weight: 600`;字段标签 SHALL 为 11px、`#64748b`、`font-weight: 400`(由 `ViewKvGrid` 的 `dt` 或 `ViewKvTable` 的 `th` 统一渲染)。区块标题样式 SHALL NOT 与字段标签使用相同颜色或相近字重。
|
||||
|
||||
#### Scenario: 新增系统管理列表页
|
||||
|
||||
@@ -284,6 +284,169 @@ Web 管理端弹窗 SHALL 遵循规范:表单 `label-position="top"`;遮罩
|
||||
- **WHEN** PR 修改列表页面且页面包含 `el-table`
|
||||
- **THEN** 审查者 SHALL 确认 `el-table` 绑定了 `@row-dblclick` 事件,且操作列包含「查看」按钮
|
||||
|
||||
### Requirement: 查看弹窗 KV 布局与组件选型
|
||||
|
||||
`web-admin` 列表行【查看】弹窗及同类只读详情弹窗的键值(KV)信息区 SHALL 采用下列两种**规范布局之一**,**SHALL NOT** 使用 Element Plus `el-descriptions`,**SHALL NOT** 使用已废弃的 `.dlg-kv` 四列「label|value|label|value」横向布局,**SHALL NOT** 在业务页手写无统一样式的 `<table>` 承载主体 KV。
|
||||
|
||||
| 布局 | 说明 | 默认场景 |
|
||||
|------|------|----------|
|
||||
| **上下堆叠栅格** | label 在上、value 在下,多列 grid | 字段较多、需 3~4 列密度;`SystemViewDialog` 默认 |
|
||||
| **多组多列表格** | 每行左 label(`th`)、右 value(`td`);短字段一行可排多组 | 字段较少(通常 ≤10)、需表格对齐感;如报销备用金申请「基础信息」 |
|
||||
|
||||
权威视觉细节见 `docs/web-admin-ui-spec-fresh-mint.md` §9.5 / §9.8;交互 Demo 见 `docs/fresh-mint-view-wide-dialog-demos.html`(上下堆叠见主区;**多组多列表格**见 `#table-section`,模式 M~R)。
|
||||
|
||||
#### 1. 组件选型
|
||||
|
||||
| 场景 | 组件 | 路径 |
|
||||
|------|------|------|
|
||||
| 门户 / CRM / 系统管理等(默认) | `SystemViewDialog` | `web-admin/src/components/business/system-view-dialog/index.vue` |
|
||||
| KV 栅格渲染(上下堆叠,被上述组件复用) | `ViewKvGrid` | `web-admin/src/components/business/system-view-dialog/ViewKvGrid.vue` |
|
||||
| KV 表格渲染(多组多列,被上述组件复用) | `ViewKvTable` | `web-admin/src/components/business/system-view-dialog/ViewKvTable.vue` |
|
||||
| 报销管理(`bx` 模块,Hero 自定义壳) | `BxViewKvGrid` / `BxViewKvTable` | `web-admin/src/components/bx/base/BxViewKvGrid.vue`、`BxViewKvTable.vue`(内部分别复用 `ViewKvGrid` / `ViewKvTable`) |
|
||||
|
||||
- 新增业务查看弹窗 **SHALL** 优先 `SystemViewDialog` + `ViewField[]` / `ViewSection[]`。
|
||||
- 字段极多、需 Tab / KPI / 分栏的复杂查看 **SHALL** 采用界面模式 **P10**(独立 `*ViewDialog`,内部仍复用 `ViewKvGrid` / `ViewKvTable` 或 `SystemViewDialog` 的 section 结构)。
|
||||
- `bx` 模块保留 `.dlg-view-hero` 等既有 Hero 壳时,KV 区 **SHALL** 使用 `BxViewKvGrid` 或 `BxViewKvTable`,**SHALL NOT** 继续手写 `.dlg-kv` 或裸 `<table>`。
|
||||
|
||||
#### 2. 弹窗宽度与默认列数
|
||||
|
||||
- `SystemViewDialog` 默认宽度 **SHALL** 为 **`1040px`**(`width` prop 可覆盖;合同/报价等宽表场景可用 `calc(100vw - Npx)` 或更大固定宽)。
|
||||
- 上下堆叠栅格默认列数 **SHALL** 为 **4 列**(`gridColumns: 4`);紧凑模式(`compact`)降为 **2 列**。
|
||||
- 多组多列表格 **SHALL** 在 **`1040px`** 弹窗内使用;少字段(≤8)可选用 **`720px`~`920px`**(见 Demo Q/R)。
|
||||
- `bx` 模块 `.dialog-view-xl` 宽度 **SHALL** 与上述一致(`min(1040px, calc(100vw - 32px))`)。
|
||||
|
||||
#### 3. KV 单元格结构(上下堆叠栅格)
|
||||
|
||||
每个字段渲染为 `<dl>` 内的 `.view-kv` 单元:
|
||||
|
||||
- **dt(label)**:上,11px,`#64748b`,`font-weight: 400`
|
||||
- **dd(value)**:下,13px,`font-weight: 600`,`word-break: break-word`
|
||||
- **SHALL NOT** 在同一 grid cell 内使用左右并排的 label|value(历史 `el-descriptions` / `.dlg-kv .k/.v` 模式)
|
||||
|
||||
#### 4. 四列栅格跨列规则
|
||||
|
||||
栅格容器为 `.view-kv-grid.view-kv-grid--cols-4`,`gap: 12px 18px`。跨列逻辑 **SHALL** 由 `web-admin/src/utils/view-field-layout.ts` 与 `ViewField` 属性共同决定:
|
||||
|
||||
| 类型 | 每行个数 | 触发条件 | CSS class |
|
||||
|------|----------|----------|-----------|
|
||||
| 短值 | **4 个/行** | 默认;显示文本 < 17 字且非长 label 启发式 | (无 span) |
|
||||
| 长值 | **2 个/行** | `long: true` 或 `span: true`;或自动:文本 ≥17 字、含 ` / ` 路径、label 匹配备注/地址/说明等 | `view-kv-span-2` |
|
||||
| 整行 | **1 个/行** | `fullSpan: true` 或 `span: 'full'`;或自动:文本 ≥80 字 | `view-kv-span-full` |
|
||||
|
||||
常量:`VIEW_KV_LONG_MIN_LEN = 17`,`VIEW_KV_FULL_MIN_LEN = 80`(见 `view-field-layout.ts`)。
|
||||
|
||||
响应式:**SHALL** 在 ≤1100px 降为 3 列、≤900px 降为 2 列、≤640px 降为 1 列(`ViewKvGrid.vue` 内 media query);长值在单列下 **SHALL** 占满整行。
|
||||
|
||||
#### 5. ViewField 定义约定
|
||||
|
||||
类型定义见 `web-admin/src/components/business/system-view-dialog/types.ts`。
|
||||
|
||||
```typescript
|
||||
interface ViewField {
|
||||
label: string
|
||||
value?: string | number | boolean | null
|
||||
items?: string[] // 无编号列表,与 value 二选一
|
||||
span?: boolean | 'full' // true=长值(2列);'full'=整行
|
||||
long?: boolean // 显式长值,等同 span:true
|
||||
fullSpan?: boolean // 显式整行
|
||||
tagType?: TagType // 状态/类型 → el-tag
|
||||
money?: boolean // 金额红色 .money-display
|
||||
}
|
||||
```
|
||||
|
||||
- 空值 **SHALL** 展示为 `—`(`formatViewValue`)。
|
||||
- 字典/状态 **SHALL** 预先翻译为 label 并视情况设 `tagType`(见「查看弹窗中编码字段展示为可读标签」「状态、结论与类型字段使用 Tag 标签展示」)。
|
||||
- 金额 **SHALL** 设 `money: true` 并使用 `¥` 前缀(见「价格字段展示规范」)。
|
||||
|
||||
#### 6. 弹窗骨架(SystemViewDialog)
|
||||
|
||||
标准只读查看弹窗 **SHALL** 按以下顺序组织:
|
||||
|
||||
1. **Hero**(`.view-hero`):图标 + 主标题 + 可选 `meta` / `code` + 状态 Tag(hero-actions 插槽可选)
|
||||
2. **分区**(`.view-section`):区块标题 + `ViewKvGrid` / `ViewKvTable` 或具名插槽(子表、附件、审批流等)
|
||||
3. **Footer**:仅「关闭」类按钮(带 `Close` 图标),**SHALL NOT** 在查看态混入提交语义
|
||||
|
||||
子表、附件、审批历史等 **SHALL** 作为独立 section 或 slot 置于 KV 区之后,**SHALL NOT** 嵌入 KV 栅格 cell 或 KV 表格 `<td>`。
|
||||
|
||||
#### 7. 模块辅助工具(推荐)
|
||||
|
||||
| 模块 | 工具 | 用途 |
|
||||
|------|------|------|
|
||||
| CRM | `web-admin/src/utils/crm/view-fields.ts` | `crmField` / `crmLongField` / `crmDictField` / `crmTagField` 构建 `ViewField` |
|
||||
| 报销 bx | `web-admin/src/utils/bx/view-kv.ts` | `bxViewKv` / `bxViewKvLong` / `bxViewKvMoney` |
|
||||
|
||||
#### 8. KV 表格模式(多组多列)
|
||||
|
||||
当业务选用**多组多列表格**展示 KV 时,**SHALL** 使用 `ViewKvTable`(或 `BxViewKvTable`),数据源仍为 `ViewField[]`;跨行/长值逻辑 **SHALL** 复用 `web-admin/src/utils/view-field-layout.ts`(`isViewFieldLong` / `isViewFieldFullSpan` / `buildViewKvTableDualRows` / `buildViewKvTableTripleRows`)。
|
||||
|
||||
**模式(`mode` prop)**
|
||||
|
||||
| mode | 每行组数 | 列结构 | 典型场景 |
|
||||
|------|----------|--------|----------|
|
||||
| `pair` | **1 组** | `th` + `td`(两列) | 少字段、需逐行阅读;Demo **Q** |
|
||||
| `dual` | **2 组** | `th` + `td` × 2(四列) | 中等字段量;Demo **N** / **R** |
|
||||
| `triple` | **3 组** | `th` + `td` × 3(六列) | 少字段高密度;Demo 扩展;参考 `bx/advance/apply` 基础信息 |
|
||||
|
||||
**行分组规则**
|
||||
|
||||
- 短字段 **SHALL** 按 mode 尽可能填满一行(`dual` 最多 2 组、`triple` 最多 3 组);末行不足时 **SHALL** 留空 `th`/`td` 占位,**SHALL NOT** 强行与长字段同组。
|
||||
- 长值 / 整行字段(`long` / `fullSpan` 或 `view-field-layout.ts` 自动检测)**SHALL** 独占整行:`pair` 为单行 `th`+`td`;`dual` 为 `td colspan="3"`;`triple` 为 `td colspan="5"`。
|
||||
- 字段顺序 **SHOULD** 将长文本(申请原因、备注等)置于数组末尾,以便短字段先组成完整多组行。
|
||||
|
||||
**表格样式(Fresh Mint)**
|
||||
|
||||
- 外层 **SHALL** 使用 `.view-kv-table-wrap`(圆角 8px、边框 `#d9e8e2`)。
|
||||
- 表头单元格 **`th`(label)**:背景 `var(--table-head)`,11px、`#64748b`;**SHALL** 支持换行(`white-space: normal`、`word-break: break-word`、`overflow-wrap: anywhere`),**SHALL NOT** 使用 `white-space: nowrap` 导致长 label(如「实际发放金额(元)」)溢出。
|
||||
- 数据单元格 **`td`(value)**:13px、`font-weight: 600`;金额 **SHALL** 使用 `.money-display`;状态/类型 **SHALL** 使用 `el-tag`(`ViewKvTableCell`)。
|
||||
- `triple` 模式 label 列宽约 **10%**、value 列宽约 **23.33%**(三组合计六列);具体比例以 `ViewKvTable.vue` 为准。
|
||||
|
||||
**选型建议**
|
||||
|
||||
- 字段 **≤8** 且弹窗显空 → 优先 **`pair`** 或 **`triple`** + 适当缩窄弹窗宽度。
|
||||
- 字段 **9~18** 且需表格感 → 优先 **`dual`**(1040px)。
|
||||
- 同一弹窗内 **SHALL NOT** 混用 `ViewKvGrid` 与 `ViewKvTable` 于**同一 section**;不同 section 可按需分别选用(如「基础信息」用表格、「扩展信息」用栅格)。
|
||||
|
||||
#### 9. 禁止与废弃
|
||||
|
||||
- **SHALL NOT** 在新代码中使用 `el-descriptions` 实现列表行【查看】弹窗主体 KV。
|
||||
- **SHALL NOT** 使用 `.dlg-kv`、`.dlg-kv--triple` 横向 KV(`web-admin/src/styles/bx/index.scss` 内已标记 deprecated,仅兼容旧页)。
|
||||
- **SHALL NOT** 手写 `<table class="...">` 实现 KV 主体区;**SHALL** 使用 `ViewKvTable` / `BxViewKvTable`。
|
||||
- 迁移存量页时 **SHALL** 保留 Hero / 子表 / 附件 / 审批流结构,**仅替换** KV 区为 `ViewKvGrid` / `ViewKvTable` / `BxViewKvGrid` / `BxViewKvTable` / `SystemViewDialog`。
|
||||
|
||||
#### Scenario: 新增 CRM 列表查看弹窗
|
||||
|
||||
- **WHEN** 在 CRM 模块新增带【查看】按钮的列表页
|
||||
- **THEN** SHALL 使用 `SystemViewDialog`(或独立 `*DetailDialog` 封装该组件)
|
||||
- **THEN** KV 字段 SHALL 通过 `ViewSection[]` + `ViewField[]` 定义,默认 4 列上下堆叠
|
||||
- **THEN** SHALL NOT 使用 `el-descriptions`
|
||||
|
||||
#### Scenario: 报销模块查看弹窗(上下堆叠)
|
||||
|
||||
- **WHEN** 在 `web-admin/src/views/bx/**` 实现或改造查看弹窗,且 KV 区采用上下堆叠栅格
|
||||
- **THEN** KV 区 SHALL 使用 `BxViewKvGrid`(columns 默认 4)
|
||||
- **THEN** 弹窗宽度 SHALL 为 1040px 级(`.dialog-view-xl`)
|
||||
|
||||
#### Scenario: 报销模块查看弹窗(多组多列表格)
|
||||
|
||||
- **WHEN** 在 `web-admin/src/views/bx/**` 的查看弹窗中,某 section(如「基础信息」)采用多组多列表格
|
||||
- **THEN** SHALL 使用 `BxViewKvTable` + `ViewField[]`,并显式声明 `mode`(`pair` / `dual` / `triple`)
|
||||
- **THEN** 长 label SHALL 在 `th` 内换行展示,**SHALL NOT** 溢出列宽
|
||||
- **THEN** 参考实现:`web-admin/src/views/bx/advance/apply/index.vue`(`mode="triple"`)
|
||||
|
||||
#### Scenario: 长文本与备注字段
|
||||
|
||||
- **WHEN** 查看弹窗包含申请原因、备注、条款等长文本
|
||||
- **THEN** SHALL 为对应 `ViewField` 设置 `long: true` 或 `fullSpan: true`(或依赖 `view-field-layout.ts` 自动检测)
|
||||
- **THEN** 4 列栅格下 SHALL 占 2 列或整行,**SHALL NOT** 与短字段同一行挤 4 个
|
||||
|
||||
#### Scenario: Code review KV 布局
|
||||
|
||||
- **WHEN** PR 新增或修改查看弹窗
|
||||
- **THEN** 审查者 SHALL 确认 KV 区为 `ViewKvGrid`(上下堆叠 + 声明的 `gridColumns`)或 `ViewKvTable`(多组多列 + 声明的 `mode`)
|
||||
- **THEN** SHALL 确认未使用 `el-descriptions` / `.dlg-kv` / 手写 KV `<table>` 作为主体字段区
|
||||
- **THEN** 状态/金额/字典字段 SHALL 符合 Tag、`money`、字典翻译等关联 Requirement
|
||||
- **THEN** 若使用 `ViewKvTable`,SHALL 确认长 label 可换行、长 value 独占整行
|
||||
|
||||
### Requirement: 查看弹窗中编码字段展示为可读标签
|
||||
|
||||
`web-admin` 中所有只读查看弹窗(`SystemViewDialog` 及类似组件)中,存储为编码(code / value)的字段 SHALL 展示为对应的人类可读标签(label),SHALL NOT 直接展示原始编码值。这包括但不限于:字典编码→字典标签、状态编码→状态文本、站点类型编码→类型名称等。
|
||||
@@ -716,6 +879,14 @@ watchDebounced(
|
||||
| 退订 | `Remove` | 退订、减少持有类操作 |
|
||||
| 作废 | `Delete` | 作废流水/订单(与删除同图标,可用 `op-warn` 样式区分) |
|
||||
| 操作流水 / 记录列表 | `List` | 「操作流水」等子列表入口 |
|
||||
| 返回 | `Close` | 详情页、表单页「返回」按钮(与取消同图标) |
|
||||
| 选择 / 挑选 | `Select` | 输入框 append「选择」、挑选合同/客户等 |
|
||||
| 安排运输 | `Van` | 运输计划「安排运输」操作 |
|
||||
| 归档 / 批量归档 | `FolderChecked` | 计划归档、批量归档 |
|
||||
| 取消计划 | `CircleClose` | 取消运输计划等业务取消 |
|
||||
| 二维码 | `Share` | 生成/查看运输二维码 |
|
||||
| 提交结算 | `Promotion` | 运费结算「提交」 |
|
||||
| 审核通过 | `CircleCheck` | 运费结算「审核」、证件「处理」等确认类操作 |
|
||||
|
||||
#### Scenario: 新增列表页工具栏按钮
|
||||
|
||||
@@ -742,6 +913,13 @@ watchDebounced(
|
||||
- **WHEN** PR 包含新增或修改的 `el-button`
|
||||
- **THEN** 审查者 SHALL 确认该按钮包含 `<el-icon>` 子元素,且图标组件已从 `@element-plus/icons-vue` 显式导入
|
||||
|
||||
#### Scenario: 运输计划模块(web-admin/src/views/pl)
|
||||
|
||||
- **WHEN** 实现或修改 `web-admin/src/views/pl/**` 下运输计划菜单页面(承运商管理、车辆管理、司机管理、运输计划、运输管理、运费结算、库存台账、证件提醒及其子页 form/detail/arrange)
|
||||
- **THEN** 每个带可见文案的 `el-button` SHALL 在文字前方包含 `<el-icon>`,并按上表选用语义图标(如搜索 `Search`、重置 `RefreshLeft`、新增 `Plus`、查看 `View`、安排运输 `Van`、归档 `FolderChecked`、提交 `Promotion`、审核/处理 `CircleCheck`、选择 `Select` 等)
|
||||
- **THEN** 图标组件 SHALL 在 `<script setup>` 中从 `@element-plus/icons-vue` 显式 `import`,SHALL NOT 依赖隐式全局注册
|
||||
- **THEN** Code review SHALL 拒绝仅有文字、无 `<el-icon>` 的按钮
|
||||
|
||||
#### Scenario: 渠道服务订单与财务确认页
|
||||
|
||||
- **WHEN** 实现或修改 `web-admin/src/views/pilot-service/channel-service-order/**` 或 `channel-service-order-finance/**` 中的按钮(含弹窗底栏、表格操作列、行内 link 删除)
|
||||
|
||||
Reference in new issue
Block a user