"""种子数据脚本: 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: import huamenchuang.models # noqa: F401 确保全部模型注册到 metadata 后再建表 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(): from sqlalchemy import select as _sel cats = json.load(open(cat_file, encoding="utf-8"))["data"] existing = set((await db.execute(_sel(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("种子数据完成") # 4) 帮助文章(幂等:按标题去重) async with SessionLocal() as db: from huamenchuang.models.extend import Article from huamenchuang.scripts.article_seed_data import ARTICLES existing = {t for (t,) in (await db.execute(select(Article.title))).all()} for i, (cat, title, content) in enumerate(ARTICLES): if title not in existing: db.add(Article(title=title, category=cat, content=content, sort=i)) await db.commit() print("帮助文章就绪") # 5) 平台公告(幂等:按名称去重) async with SessionLocal() as db: from huamenchuang.models.announcement import Announcement ANNOUNCEMENTS = [ ("AI 炫图功能上线", "选择样板一键生成多风格效果图,支持日景/黄昏/夜景与四种装修风格", 1), ("样板组合工场发布", "拖拽组合多个窗型样板,自由摆放、等高对齐、边缘吸附,支持 3D 预览", 2), ("3D 门窗开合演示", "3D 展示支持平开扇旋转、推拉扇滑动动画,可调节开合度", 3), ("优化下料引擎", "合同级汇总算料需求,一维优化切割提升型材利用率", 4), ] existing = {n for (n,) in (await db.execute(select(Announcement.name))).all()} for name, desc, sort in ANNOUNCEMENTS: if name not in existing: db.add(Announcement(name=name, desc=desc, sort=sort)) await db.commit() print("平台公告就绪") # 6) 价格脚本示例(幂等:按名称去重) async with SessionLocal() as db: from huamenchuang.models.business import PriceScript SAMPLE_SCRIPTS = [ ("断桥铝-55系列", "frame", "(w+h)*2/1000*52"), ("断桥铝-55系列", "mullion", "length*46"), ("断桥铝-55系列", "sash", "length*58"), ("双层中空玻璃", "glass", "max(110, area*135)"), ("标准五金", "hardware", "sashes*195"), ] existing = {n for (n,) in (await db.execute(select(PriceScript.name))).all()} for name, target, formula in SAMPLE_SCRIPTS: if name not in existing: db.add(PriceScript(name=name, target=target, formula=formula, note="种子示例脚本,可在产品管理中修改")) await db.commit() print("价格脚本就绪") # 7) 打印模板(幂等:按名称去重) async with SessionLocal() as db: from huamenchuang.models.extend import OrderFormat FORMATS = [ ("标准生产订单", [ {"type": "title", "text": "生产订单"}, {"type": "info", "fields": ["order_no", "customer_name", "phone", "address", "count", "money"]}, {"type": "image"}, {"type": "table", "kind": "process"}, {"type": "sign"}, ], 1), ("生产订单+BOM下料单", [ {"type": "title", "text": "生产订单"}, {"type": "info", "fields": ["order_no", "customer_name", "phone", "address", "count", "area", "money", "created_at"]}, {"type": "image"}, {"type": "table", "kind": "bom"}, {"type": "table", "kind": "process"}, {"type": "sign"}, ], 0), ] existing = {n for (n,) in (await db.execute(select(OrderFormat.name))).all()} for i, (name, blocks, is_default) in enumerate(FORMATS): if name not in existing: db.add(OrderFormat(name=name, order_type=0, sort=i, is_default=is_default, blocks=__import__("json").dumps(blocks, ensure_ascii=False))) await db.commit() print("打印模板就绪") if __name__ == "__main__": asyncio.run(seed())