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
+76
View File
@@ -0,0 +1,76 @@
"""种子数据脚本:
1. 创建默认企业/管理员(admin/123456)
2. 导入采集到的 254 套官方样板(drawing_data + 分类树 + 平面图)
用法: uv run python -m huamenchuang.scripts.seed
"""
import asyncio
import json
from pathlib import Path
DATA = Path(__file__).resolve().parents[3] / "data"
async def seed() -> None:
from huamenchuang.core.database import SessionLocal, init_db
from huamenchuang.models.user import User
from huamenchuang.models.windoor_template import WindoorCatelog, WindoorTemplate
from huamenchuang.services.auth_service import hash_password
await init_db()
async with SessionLocal() as db:
# 1) 管理员
if await db.get(User, 1) is None:
db.add(User(id=1, nickname="管理员", phone_number="13800000000",
password_hash=hash_password("123456"), company_id=1))
print("已创建管理员: 13800000000 / 123456")
# 2) 分类树(来自 default_windoor_catelog.json,取目标站原始 id 便于对照)
cat_file = DATA / "api-samples" / "default_windoor_catelog.json"
if cat_file.exists():
cats = json.load(open(cat_file, encoding="utf-8"))["data"]
existing = {c.id for c in (await db.execute(
__import__("sqlalchemy").select(WindoorCatelog.id))).scalars()}
for top in cats:
if top["id"] not in existing:
db.add(WindoorCatelog(id=top["id"], name=top["name"], fid=0, company_id=1))
for ch in top.get("children", []):
if ch["id"] not in existing:
db.add(WindoorCatelog(id=ch["id"], name=ch["name"], fid=top["id"], company_id=1))
print("分类树导入完成")
# 3) 官方样板 254 套
templates = json.load(open(DATA / "api-samples" / "windoor-templates-clean.json", encoding="utf-8"))
drawings_dir = DATA / "windoor-drawings"
img_dir = DATA / "windoor-images"
from sqlalchemy import func, select
count = (await db.execute(select(func.count()).select_from(WindoorTemplate))).scalar_one()
if count == 0:
for t in templates:
dd_file = drawings_dir / f"{t['id']}.json"
if not dd_file.exists():
continue
detail = json.load(open(dd_file, encoding="utf-8"))
img = img_dir / f"{t['id']}.png"
img2 = img_dir / f"{t['id']}.jpg"
pic = "/static/windoor-images/" + (img.name if img.exists() else img2.name)
db.add(WindoorTemplate(
name=detail.get("name") or t.get("name") or f"样板{t['id']}",
drawing_data=detail["drawing_data"],
pic_url=pic,
catelog_id=t["catelog_id"],
note=detail.get("note") or "",
times=detail.get("times") or 0,
low_width=detail.get("low_width") or 0,
high_width=detail.get("high_width") or 0,
low_height=detail.get("low_height") or 0,
high_height=detail.get("high_height") or 0,
))
print(f"已导入样板 {len(templates)} 套")
else:
print(f"样板表已有 {count} 条, 跳过导入")
await db.commit()
print("种子数据完成")
if __name__ == "__main__":
asyncio.run(seed())