Files
menchuang/doc/克隆实施方案.md
T
HHY 7554f2e3c7 feat: 整站全量采集与订单写入接口契约补全
- GET 全量扫描 279 个接口并留档(HTTP200=90, 业务成功=76)
- POST 安全探测 24 个只读/计算接口(白名单制, 支付/短信/删除类零触碰)
- 订单写入接口契约经 chunk 源码静态分析补全:
  orders CRUD / 创建订单{contract_id,drawing_data,pic_url} / windoor_default 保存
- 确认付费墙语义 code=10086 及到期/角色权限响应
- doc/API.md 新增整站采集结果章节, 更新订单模块契约表
2026-09-20 07:19:10 -07:00

208 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 门窗 Saunders 云平台(windoorcraft.com 同功能系统)克隆实施方案
> 版本:v0.1 | 日期:2026-09-20 | 编制:HHY
> 目标站:https://www.windoorcraft.com/home (代号 zzc,出品方 thinkerx.com)
> 本文档基于对目标站的**只读接口采集**(用户自有账户)与前端结构分析编写,所有代码实现均为自研原创。
---
## 1. 目标产品画像
windoorcraft.com 是一套面向门窗行业的 SaaS 工具集,核心价值链:
```
画窗(拖拽布置分格) → 自动算料报价 → 客户确认(合同/订单) → 生产(优化下料/打印) → 财务(收付款) → 库存
```
已探明的子系统:
| 子系统 | 说明 | 证据(路由/接口) |
|---|---|---|
| 2D 画窗编辑器 | 拖拽布置外框、中梃、扇、玻璃、横竖撑,参数化尺寸 | `/draw`、`drawing_data`、`shapeManager` |
| 报价引擎 | 自动报价 + 手动报价,型材/玻璃/五金附件计价 | `/manual-quote`、`automatic_quote`、`base_price`、`offer-price` |
| 订单/合同 | 意向单→合同→订单流转,电子签名确认 | `/orders`、`contracts`、`convert-contract/`、`up-contract-confirmed/` |
| 客户管理 CRM | 客户档案、业务员、客户分级 | `/customers_list`、`salesmen`、`ywy-*` |
| 生产管理 | 订单进度、车间派工、条码打印 | `get_order_process`、`printer`、`order_format` |
| 优化下料 | 一维型材优化切割(BIN 问题) | `optimize1d`、`cut_solution`、`contract_bars` |
| 库存/仓库 | 型材/玻璃/配件库存、出入库 | `warehouse_list`、`product_move_in/`、`materials_config` |
| 3D/渲染 | BabylonJS 3D 展示、DXF 出图、AI 炫图 | `/threed`、`renderV2`、`sketch-to-window-info` |
| 样板库 | 254 套官方窗型模板(6 大分类) | `search_default_windoor`、`default_windoor_info/{id}` |
| 商城/会员 | 软件订阅购买、试用、邀请返利 | `/purchase`、`company-module-info`、`invited_user_list` |
| 多端生态 | 微信小程序/公众号/APP、Apple/Google 登录 | `wechat-login-with-phone`、`wx/getwxurllink`、`apple_login` |
| 多语言 | 中/英/韩/俄/越 5 语言包 | `lang-en-us` 等独立 chunk |
| 子账户/权限 | 主子账户、业务员/经销商角色 | `son_user_update`、`up_son_user_permission`、`dls-*` |
## 2. 已采集数据资产(本次交付)
全部存于 `data/` 目录:
| 文件 | 内容 | 规模 |
|---|---|---|
| `api-endpoint-inventory.txt` | 从前端提取的全部接口名清单 | ≈300 条 |
| `api-samples/*.json` | 16 个核心接口的真实响应样本 | — |
| `api-samples/windoor-templates-clean.json` | **样板库全量清单**(含分类名映射) | 254 条 |
| `windoor-drawings/{id}.json` | **每套模板的完整绘制数据 `drawing_data`** | 254 个文件 / 5.4MB |
| `full-site/get/` + `get-manifest.json` | **整站 GET 扫描**:279 个接口逐一探测留档(200→90,业务成功 76) | 全量 |
| `full-site/post/` + `post-manifest.json` | **POST 安全探测**:24 个只读/计算语义接口(付费墙/参数契约确认) | 全量 |
| `full-site/sweep_get.py` / `sweep_post.py` | 可复用的限速采集脚本(白名单制,危险接口永不触碰) | — |
> 订单模块受目标站付费墙保护(`code=10086`),列表/详情数据无法以试用水印账户获取;但订单写入接口的**完整请求契约**已通过源码静态分析拿到:创建订单 `POST orders/{contract_id, drawing_data, pic_url}`、详情 `GET orders/{id}`、排序 `PUT orders/{id}`、删除 `DELETE orders/{id}`。自研实现不依赖对方付费墙数据。
### 2.1 样板库统计
| 分类 | 数量 |
|---|---|
| 平开 | 99 |
| 转角窗 | 54 |
| 推拉 | 35 |
| 复古门 | 31 |
| 肯德基门 | 27 |
| 中式门窗 | 8 |
| **合计** | **254** |
> 说明:`search_default_windoor` 接口无分页(前端仅传 `name` 关键字参数),一次返回全量;经验证 `page` 参数被忽略、三页内容完全一致,故 **254 条即官方样板库全量**,本次已 100% 采集成功(254/254)。
### 2.2 drawing_data 数据模型(拖拽编辑器核心,已破解)
`default_windoor_info/{id}` 返回的 `drawing_data` 是编辑器画布的完整序列化状态,直接喂给 `canvas.shapeManager.openFile()`。结构:
```
drawing_data
├── s 全局设置 { cs: 外框默认料宽60, cjs: 100 }
├── cp 预设参数
├── sm[] 形状集合(多形状 = 转角窗/连体窗)
│ └── 每个形状:
│ ├── cm 颜色映射 { g: 玻璃填充色, bn: 边框色, hd: 高光, ben: }
│ ├── dm 尺寸标注 { dims: [{at, ds, eidx, midx, name, type: line|mullion}] }
│ ├── fm 外框模型 { ew: [左,上,右,下]料宽, vs: 顶点, ejw, pew, ast }
│ ├── mm 中梃模型 { sp: [分割线 {line:{pt,norm}, alignType, equalSplit,
│ │ kw(竖撑), ws(窗撑), reinforced, polyId}] }
│ ├── sashes[] 扇:开向 openToward、开启状态 opened、带转框 withTurningFrame
│ ├── bars / bds 格条(防盗格/装饰格)
│ ├── gg / gcs 玻璃配置
│ ├── ut / tcs 推拉窗轨道(emptyTrackAppended)
│ ├── rt / ep 圆弧半径(复古门弧顶)
│ └── polygon 多边形轮廓(非矩形窗)
├── epi / sbf / wlc 编辑器状态(点吸附/选中框/墙线)
├── wall 附墙信息
└── scale 缩放比例
```
关键结论:**编辑器 = "多边形外框 + 中梃分割线树 + 区域→扇/玻璃分配" 的三层模型**。分割线(sp)带单位向量 norm 与对齐策略,渲染时递归切割多边形得到玻璃区域。这就是拖拽布置搭建的实现基础。
## 3. 目标技术架构(自研实现)
### 3.1 技术选型
结合本仓库已有的 Python 骨架(`pyproject.toml`,Python ≥3.14):
| 层 | 选型 | 说明 |
|---|---|---|
| 后端 | **FastAPI + SQLAlchemy 2.0 + MySQL 8** | 异步、类型安全(符合类型安全原则)、自带 OpenAPI 文档 |
| 前端 | **Vue 3 + TypeScript + Element Plus + Pinia** | 与原站 Vue 系心智一致;画布层自研 |
| 画布引擎 | **原生 Canvas 2D + 自研 shapeManager**(复刻数据模型 §2.2) | 备选 Konva.js 减少底层工作量 |
| 3D | Three.js + DXF 导出库 | 原站用 BabylonJS,功能等效替换 |
| 缓存/队列 | Redis + Celery(优化下料、渲染走异步任务) | optimize1d 计算密集 |
| 文件存储 | 阿里云 OSS / MinIO(自托管备选) | 原站用阿里云 OSS + 华为云 OBS |
| 认证 | JWT (HS256, 24h) + 手机验证码 + 微信 OAuth | 对齐原站鉴权方式 |
### 3.2 模块划分(严格分层)
```
src/huamenchuang/
├── main.py # FastAPI 入口、前端静态挂载
├── core/ # 配置、安全(JWT)、依赖注入、统一响应封装
│ ├── config.py security.py response.py # {code,message,data} envelope
├── models/ # SQLAlchemy ORM(见 §4 领域模型)
├── schemas/ # Pydantic 请求/响应模型
├── repositories/ # 数据访问层
├── services/ # 业务逻辑层
│ ├── auth_service.py customer_service.py contract_service.py
│ ├── order_service.py product_service.py warehouse_service.py
│ ├── quote_service.py optimize_service.py template_service.py
├── api/ # Controller 路由层(按模块拆分 router)
└── utils/ # 一维优化算法、公式引擎、单位换算
frontend/
├── src/
│ ├── api/ # axios 封装 + 接口定义
│ ├── stores/ # Pinia
│ ├── views/ # 与原站 42 条路由对应的页面
│ └── components/canvas/ # shapeManager / Frame / Mullion / Sash / Glass / Dimension
└── dist -> 后端静态挂载 # 构建产物挂载(符合前后端规范)
```
### 3.3 拖拽布置编辑器(核心难点)复刻方案
1. **数据层**:直接采用 §2.2 解析出的模型(`drawing_data` 已有 254 个真实样本作为测试集,兼容读入即等于拥有 254 个回归用例)。
2. **交互层**:
- 左侧样板库面板(`search_default_windoor` 数据 + 分类树 `default_windoor_catelog`),**拖拽模板进画布即实例化一个 sm 形状**;
- 画布上选中形状后,从边缘拖出**中梃分割线**(norm 决定水平/垂直,`alignType`/`equalSplit` 决定等分策略);
- 分割递归产生子区域,点击区域可指定 `sashes`(开扇,含开向箭头)、`bars`(格条)、玻璃类型;
- 边缘料宽 `ew[4]` 可视化拖拽调节;尺寸标注 `dims` 绑定边/中梃(`eidx`/`midx`)自动跟随。
3. **渲染层**:多边形裁剪 + 玻璃填充色 `cm.g` + 开向线条;打印视图走 SVG 输出。
4. **算料层**:遍历形状树输出型材清单(外框 4 段 + 中梃/横撑按 `sp` 长度),套用产品价格脚本(`script_bar/script_glass/script_addon`,服务端执行)。
## 4. 领域模型(依据真实响应样本归纳)
| 实体 | 关键字段(来自采集样本) |
|---|---|
| users | id, nickname, phone_number, wechat_id, union_id, apple_id, company_id, money, bounty, try_expiration_time, son_account_type, language, is_lose |
| companies | id, name, 参数集(find/update_company_param_value) |
| customers | id, name, phone, address, note, sort, type, salesmen, discount, balance, level, join_date |
| contracts | id, contract_no(如 FG20260818009), customer_id, area, count, money, status(意向单…), cut_status, sign_status, sign_picture_url, contract_type, confirmed, discount, agency_money, oids[] |
| orders | (POST 接口,结构待浏览器抓包补全) order_no, contract_id, products[], process |
| windoor_templates | id, name, pic_url, catelog_id, note, times, low/high_width/height, drawing_data |
| default_windoor_catelogs | 树:推拉门{平开,推拉,复古门,肯德基门,中式门窗,转角窗} |
| product_catelogs | 树,is_reference, lang |
| warehouses(材料) | bom_code, name, material(profile/glass/...), cost, price, color, pricing_method, length, count, warning, unit, meter_weight, thick, agency_price |
| receipt_accounts | type, name, number, bank, pic_url, is_default, balance |
| announcements | name, desc, pic_url, content(富文本) |
| company_modules | name, type, icon, description, price, try_days, label, info |
| operation_logs / invited_users | 分页日志/邀请返利 |
**接口响应统一 envelope**:`{code: 1=成功, message, data, other_data, other_data2}`;分页为 Laravel 风格 `current_page/data[]/total/per_page`。自研系统沿用此规范以保持前端迁移成本最低。
## 5. 接口清单(详见 doc/API.md)
按模块归组(GET 已验证 ✅ / POST 待抓包 ⏳):
- 认证:`login` `wechat-login` `wechat-login-with-phone` `code-login` `register-and-login` `verification-code-new` `captcha` `forget-password`
- 用户:`current-user`✅ `users`✅ `current-user/password` `current-user/phone` `son_user_update/` `up_son_user_permission`
- 客户:`customers_list`✅ `customers` `customer_record(s)` `customers_excel_in`
- 合同/订单:`contracts`✅ `convert-contract/` `orders/`(POST)⏳ `order-by-pid` `get_order_process` `up_order_no/` `contract_receipt*`
- 样板库:`search_default_windoor`✅ `default_windoor_catelog`✅ `default_windoor_info/{id}`✅ `default_windoor/` `windoor/`(用户自存窗型) `windoor_template_sort`
- 产品:`product-catelog`✅ `all-product`✅ `product/` `search-product` `dls-price-config` `team-discount`
- 仓库:`warehouse_list`✅ `warehouse_info` `receipt_accounts`✅ `product_move_in//out/` `materials_config`
- 下料:`optimize1d` `cut_solution(_new)` `contract_bars(_with_stock)` `up-cut-status`
- 渲染/3D:`rendering-info` `three-d-data`(POST)⏳ `drawing_data_by_oid/` `sketch-to-window-info`
- 财务:`contract_receipt_list`✅样 `contract_receipt_statistics(_tb)` `withdraw-money` `pay-order-list`
- 平台:`announcements`✅ `company-module-info`✅ `get-showdoc-menu`✅ `feedback` `ip_to_region`
> ⏳ 项:写入类接口(POST/PUT)为避免对生产系统产生副作用未做探测,需要在自研时按功能自行定义,或后续用浏览器 DevTools Network 面板在实际操作时抓包补全。
## 6. 里程碑计划
| 里程碑 | 内容 | 验收 |
|---|---|---|
| M1 基础框架 | FastAPI 骨架/统一响应/JWT 认证/Vue3 骨架/部署脚本 | 登录+用户中心跑通 |
| M2 业务 CRUD | 客户/合同/订单/产品/仓库 + Excel 导入导出 + 权限 | 全部 ✅ 接口对等实现 |
| M3 样板库+画图编辑器 | 拖拽布置、中梃分割、扇/玻璃指定、尺寸标注 | **加载全部 254 个采集样本渲染一致** |
| M4 报价+算料 | 价格脚本引擎、自动报价、手动报价 | 与原站同窗型报价误差为 0 |
| M5 生产+下料+打印 | 订单进度、optimize1d、打印模板 | 优化利用率 ≥ 原站 |
| M6 生态 | 微信登录/支付、商城、邀请返利、多语言 | 对齐原站 |
## 7. 风险与合规
1. **只仿功能,不搬代码/素材**:功能逻辑与数据模型不受版权保护,但对方源码、图标、宣传图文受保护。本项目全部自研,采集数据仅作开发参照;官方样板库图片存于对方 OSS(`webcc-pro.oss-cn-hangzhou...`),上线前需替换为自绘素材或取得授权。
2. **采集凭据时效**:本次使用的 Bearer token 有效期至 2026-09-21 06:05;账户试用期至 2026-09-23。后续采集需重新登录获取 token。
3. **生产 API 礼貌访问**:所有采集均为只读且 0.3s 限速;不触碰写入接口、不触发异常路径(其报错响应会暴露框架堆栈,属对方运维问题,勿利用)。
4. **待补全项**:订单/报价写入接口的请求体结构(需浏览器抓包);价格脚本语言文法(需实际配置产品后观察)。
## 8. 下一步(按优先级)
1. M1 搭建 FastAPI + Vue3 骨架,落统一响应与 JWT
2. 导入采集数据:`windoor_templates`、`default_windoor_catelogs` 建表入库(数据已就绪)
3. 画布 shapeManager 原型:先实现"读取 254 个样本→静态渲染",再补交互
4. 用户在真实环境抓包补全 ⏳ 接口后,更新 `doc/API.md`