from fastapi import APIRouter, Request, Depends, Form from fastapi.responses import HTMLResponse, RedirectResponse from sqlalchemy import text # 新增这一行 from sqlalchemy.orm import Session from database import SessionLocal import json import time from datetime import datetime from datetime import datetime from services.template_builder import build_estimate_template router = APIRouter(prefix="/admin", tags=["admin"]) # ---------- DB ---------- def get_db(): db = SessionLocal() try: yield db finally: db.close() # ---------- 机型管理 ---------- @router.get("/machines", response_class=HTMLResponse) def machine_page(db: Session = Depends(get_db)): categories = db.execute(text(""" SELECT category_id, name FROM t_chx_category """)).fetchall() machines = db.execute(text(""" SELECT brand_name, name, type_name FROM t_machine ORDER BY id DESC LIMIT 50 """)).fetchall() html = """

机型管理

分类:

品牌名称:

机型名称:


" return html @router.post("/machines/add") def add_machine( type_id: int = Form(...), brand_name: str = Form(...), machine_name: str = Form(...), db: Session = Depends(get_db) ): category = db.execute( text("SELECT name FROM t_chx_category WHERE category_id=:id"), {"id": type_id} ).fetchone() machine_id = int(time.time() * 1000) brand_id = int(time.time() * 1000) db.execute(text(""" INSERT INTO t_machine ( code, type_id, type_name, brand_id, brand_name, machine_id, name, create_time ) VALUES ( 'mobile', :type_id, :type_name, :brand_id, :brand_name, :machine_id, :name, :time ) """), { "type_id": type_id, "type_name": category.name, "brand_id": brand_id, "brand_name": brand_name, "machine_id": machine_id, "name": machine_name, "time": datetime.now() }) db.commit() return RedirectResponse("/admin/machines", status_code=302) # ---------- release_option 管理 ---------- @router.get("/options", response_class=HTMLResponse) def option_page(db: Session = Depends(get_db)): rows = db.execute(text(""" SELECT step_name, option_key_name, option_name FROM release_option ORDER BY step_name, option_key_name """)).fetchall() # 组装树 tree = {} for r in rows: step = r.step_name key = r.option_key_name opt = r.option_name tree.setdefault(step, {}) if key: tree[step].setdefault(key, []) if opt: tree[step][key].append(opt) # 渲染 HTML html = "

检测项管理

" for step, keys in tree.items(): html += f"

📂 {step}

" # 表单 html += """

➕ 新增父级

父级名称:

➕ 新增子级

父级名称: 子级名称:

➕ 新增选项

父级名称: 子级名称: 选项名称:
""" return html @router.post("/options/add") def add_option( step_name: str = Form(...), option_key_name: str = Form(""), option_name: str = Form(""), db: Session = Depends(get_db) ): db.execute(text(""" INSERT INTO release_option (step_id, step_name, option_key_id, option_key_name, option_id, option_name) VALUES ( 2, :step, UNIX_TIMESTAMP(), :key, UNIX_TIMESTAMP(), :opt ) """), { "step": step_name, "key": option_key_name, "opt": option_name }) db.commit() return RedirectResponse("/admin/options", status_code=302) # ---------- API ---------- @router.get("/capacities/{machine_id}") def capacities(machine_id: int, db: Session = Depends(get_db)): return db.execute( "SELECT capacity FROM machine_base_price WHERE machine_id=:id", {"id": machine_id} ).fetchall() @router.post("/release_option/add") def add_option( step_id: int = Form(...), step_name: str = Form(...), option_key_name: str = Form(...), option_name: str = Form(...), db: Session = Depends(get_db) ): db.execute(""" INSERT INTO release_option(step_id,step_name,option_key_id,option_key_name,option_id,option_name) VALUES (:sid,:sname, UNIX_TIMESTAMP(), :kname, UNIX_TIMESTAMP(), :oname) """, { "sid": step_id, "sname": step_name, "kname": option_key_name, "oname": option_name }) db.commit() return {"ok": True} @router.get("/capacities/{machine_id}") def capacities(machine_id: int, db: Session = Depends(get_db)): return db.execute( "SELECT capacity FROM machine_base_price WHERE machine_id=:id", {"id": machine_id} ).fetchall() @router.get("/factors", response_class=HTMLResponse) def factors(request: Request, db: Session = Depends(get_db)): rows = db.execute(text(""" SELECT ro.option_name, pf.option_id, pf.factor, pf.absolute_deduct FROM price_option_factor pf LEFT JOIN release_option ro ON pf.option_id = ro.option_id """)).fetchall() options = db.execute(text(""" SELECT DISTINCT option_id, option_name FROM release_option """)).fetchall() return request.app.templates.TemplateResponse( "factors.html", { "request": request, "rows": rows, "options": options } ) @router.post("/factors/save") def save_factor( option_id: int = Form(...), factor: float = Form(1.0), absolute_deduct: float = Form(0), db: Session = Depends(get_db) ): db.execute(text(""" INSERT INTO price_option_factor(option_id,factor,absolute_deduct) VALUES (:oid,:f,:d) ON DUPLICATE KEY UPDATE factor=:f, absolute_deduct=:d """), { "oid": option_id, "f": factor, "d": absolute_deduct }) db.commit() return RedirectResponse("/admin/factors", status_code=302) @router.get("/adjust", response_class=HTMLResponse) def adjust_page(request: Request, db: Session = Depends(get_db)): rows = db.execute(text("SELECT * FROM price_adjust_factor")).fetchall() return request.app.templates.TemplateResponse( "adjust.html", {"request": request, "rows": rows} ) @router.post("/adjust/save") def save_adjust( level: str = Form(...), ref_id: int = Form(0), factor: float = Form(...), db: Session = Depends(get_db) ): db.execute(text(""" INSERT INTO price_adjust_factor(level,ref_id,factor) VALUES (:l,:r,:f) """), { "l": level, "r": ref_id, "f": factor }) db.commit() return RedirectResponse("/admin/adjust", status_code=302) @router.post("/machine-template/generate") def generate_machine_template( machine_id: int = Form(...), db: Session = Depends(get_db) ): # 1. release_option options = db.execute(text(""" SELECT step_name, option_key_name, option_id, option_name FROM release_option ORDER BY step_id, option_key_id, option_id """)).fetchall() if not options: return {"error": "release_option 为空"} template = build_estimate_template(options) # 2. 写入 machine_temp db.execute(text(""" INSERT INTO machine_temp (machine_id, temp_type, estimate_packet, create_time, update_time) VALUES (:mid, '00', :json, :now, :now) ON DUPLICATE KEY UPDATE estimate_packet = :json, update_time = :now """), { "mid": machine_id, "json": json.dumps(template, ensure_ascii=False), "now": datetime.now() }) db.commit() return RedirectResponse("/admin/machine-templates", status_code=302) @router.get("/machine-templates", response_class=HTMLResponse) def machine_templates(db: Session = Depends(get_db)): rows = db.execute(text(""" SELECT m.machine_id, m.name, m.brand_name, mt.id AS temp_id FROM t_machine m LEFT JOIN machine_temp mt ON m.machine_id = mt.machine_id AND mt.temp_type = '00' ORDER BY m.brand_name, m.name LIMIT 100 """)).fetchall() html = "

机型模板管理

" html += "" for r in rows: status = "已生成" if r.temp_id else "未生成" btn = "重新生成" if r.temp_id else "生成" html += f""" """ html += "
品牌机型模板操作
{r.brand_name} {r.name} {status}
" return html @router.get("/categories", response_class=HTMLResponse) def category_page(db: Session = Depends(get_db)): rows = db.execute(text("SELECT * FROM t_chx_category")).fetchall() html = "

分类管理

" html += """

新增分类

名称:
""" return html @router.post("/categories") def add_category(name: str = Form(...), db: Session = Depends(get_db)): db.execute( text("INSERT INTO t_chx_category(category_id,name) VALUES (UNIX_TIMESTAMP(),:n)"), {"n": name} ) db.commit() return RedirectResponse("/admin/categories", 302)