feat: 订单模块 v0.1 实现与样板二维平面图全量采集

- 后端分层架构: api(Controller)/services(业务)/repositories(数据)/models(ORM)
- 订单模块: 创建(契约对齐目标站{contract_id,drawing_data,pic_url})、搜索、
  详情、更新、删除、状态机(意向单→正式单→生产中→完工/取消,非法迁移拒绝)、
  7节点生产进度、审计日志
- 认证模块: JWT签发(HS256/24h)、PBKDF2密码、注册登录
- 样板库API: 分类树/模板搜索/模板详情, drawing_data 与采集样本同构
- 254张样板二维平面图全部采集并静态挂载 /static/windoor-images/
- 种子脚本: 管理员+分类树+254套样板入库
- 统一响应envelope与付费墙(code=10086)/权限(code=210)语义
- 端到端冒烟测试7/7通过, 更新API.md §12自研接口规范
This commit is contained in:
HHY
2026-09-20 08:16:03 -07:00
parent 7554f2e3c7
commit d3e6de585c
288 changed files with 1835 additions and 9 deletions
+59
View File
@@ -182,3 +182,62 @@
- 付费墙模块(code=10086):订单全流程、报价(offer-price)、产品库、订单打印模板、AI 产品
- 到期语义:`pay-page-list` 返回 code=0 "您的账号已经到期,请联系销售人员!";`try_render` 返回 "体验版无法体验实景渲染"
- 角色权限:`contract-stat` 返回 code=210 "该账号没有该权限"
## 12. 自研系统接口规范(已实现 v0.1)
> 自研基址 `http://localhost:8000/api/`,envelope 与分页结构完全对齐 §0。认证:`Authorization: Bearer <JWT>`(HS256/24h)。
> 分层:`api/`(Controller) → `services/`(业务) → `repositories/`(数据) → `models/`(ORM)。
### 12.1 认证模块 `/api/auth`
| 接口名称 | 方式 | URL 路径 | 请求参数 | 响应示例 |
|---|---|---|---|---|
| 登录 | POST | `/api/auth/login` | `{"phone_number":"13800000000","password":"123456"}` | `{"code":1,"data":{"token":"...","expires_hours":24,"user":{...}}}` |
| 注册 | POST | `/api/auth/register` | `{"phone_number","password"}` | `{"code":1,"data":{"token","user_id"}}` |
| 当前用户 | GET | `/api/auth/current-user` | Bearer token | `{"code":1,"data":{"id,nickname,phone_number,company_id,language,try_expiration_time}}` |
### 12.2 订单模块 `/api/orders`(本节核心,自研设计)
**订单状态机**:`0意向单 → 1正式单 → 2生产中 → 3已完工`;任意未完工状态可 `4已取消`(终态)。非法迁移返回 code=0。
**单号规则**:`DO + YYYYMMDD + 4位流水`(同企业同日递增),例如 `DO202609200001`。
**创建订单后自动初始化生产进度节点**:下料/组装/玻璃/打胶/五金/质检/完工(7 节点,与目标站 get_order_process 语义对齐)。
| 接口名称 | 方式 | URL 路径 | 请求参数 | 响应示例 |
|---|---|---|---|---|
| **创建订单** | POST | `/api/orders` | `{"contract_id":1,"drawing_data":"{画布JSON}","pic_url":"/static/windoor-images/1.png","customer_id":1,"money":0,"count":0,"area":0,"note":"","status":0}` | `{"code":1,"message":"创建成功","data":{"id":1,"order_no":"DO202609200001","status":"意向单",...}}` |
| 订单搜索 | POST | `/api/orders/search` | `{"page":1,"page_size":15,"keyword":"","status":null,"contract_id":null,"start_date":"","end_date":"","order_by":"created_desc"}` | `{"code":1,"data":{"current_page":1,"data":[...],"total":0,"per_page":15}}` |
| 订单列表 | GET | `/api/orders?page=1&page_size=15` | query | 同上分页结构 |
| **订单详情** | GET | `/api/orders/{id}` | 路径 | `data` 含 `drawing_data`(画布 openFile 直接渲染)与 `processes[7]` |
| 更新订单 | PUT | `/api/orders/{id}` | 基础字段任意子集;`{"action":"change_status","target_status":1}` 执行状态迁移 | `{"code":1,"data":{...}}`;非法迁移 `{"code":0,"message":"不允许的状态迁移: 意向单→已完工"}` |
| 删除订单 | DELETE | `/api/orders/{id}` | 路径 | `{"code":1,"message":"删除成功"}` |
| **更新生产进度** | POST | `/api/orders/{id}/process` | `{"name":"下料","status":2}` (status: 0未开始/1进行中/2完成,自动记 finish_time) | `{"code":1,"data":{"id,"name","status","finish_time"}}` |
| 订单操作日志 | GET | `/api/orders/{id}/logs` | 路径 | `{"code":1,"data":[{"action":"create","detail":"创建订单 DO202609200001","created_at":...}]}` |
### 12.3 样板库模块 `/api/windoor`
| 接口名称 | 方式 | URL 路径 | 请求参数 | 响应示例 |
|---|---|---|---|---|
| 分类树 | GET | `/api/windoor/catelogs` | Bearer | 树结构同目标站 `default_windoor_catelog` |
| 模板搜索 | GET | `/api/windoor/templates?name=&catelog_id=&page=1&page_size=50` | query | 列表含 `pic_url`(本地平面图 `/static/windoor-images/{id}.png`),不含大字段 |
| 模板详情 | GET | `/api/windoor/templates/{id}` | 路径 | `data.drawing_data` — 与采集的 254 套样本同构,画布可直接渲染 |
### 12.4 系统模块
| 接口名称 | 方式 | URL 路径 | 说明 |
|---|---|---|---|
| 健康检查 | GET | `/api/health` | `{"code":1,"data":{"status":"up"}}` |
| 接口文档 | GET | `/docs` | FastAPI 自动生成 OpenAPI |
| 平面图静态 | GET | `/static/windoor-images/{id}.png` | 254 张采集平面图(开发参照,上线前须替换为自绘素材) |
### 12.5 种子数据
```bash
uv sync # 安装依赖
uv run python -m huamenchuang.scripts.seed # 管理员 + 分类树 + 254 套样板入库
uv run uvicorn huamenchuang.main:app --reload # 启动,http://localhost:8000/docs
```
管理员账号:`13800000000 / 123456`(开发用,生产必须修改)。
默认 SQLite(`HMC_DATABASE_URL` 可切 MySQL),JWT 密钥 `HMC_JWT_SECRET` 生产必须设置。