from fastapi import APIRouter, Request, Depends, Form from fastapi.responses import HTMLResponse from sqlalchemy.orm import Session from sqlalchemy import text from database import SessionLocal, redis_client from services.template_service import build_template from services.price_service import apply_adjust import json import uuid router = APIRouter(prefix="/estimate", tags=["estimate"]) # ================= DB ================= def get_db(): db = SessionLocal() try: yield db finally: db.close() # ================= 页面 ================= @router.get("/simulate", response_class=HTMLResponse) def simulate(machine_id: int, db: Session = Depends(get_db)): row = db.execute(text(""" SELECT estimate_packet FROM machine_temp WHERE machine_id=:mid """), {"mid": machine_id}).fetchone() tpl = json.loads(row.estimate_packet) html = "

估价模拟

" html += '
' for step in tpl["template"]: html += f"

{step['stepName']}

" for p in step["properties"]: html += f"{p['name']}
" for v in p["values"]: html += f"""
""" html += f"""
""" return html # ================= 提交估价 ================= @router.post("/simulate", response_class=HTMLResponse) def simulate_calc( machine_id: int = Form(...), option_ids: list[str] = Form([]), db: Session = Depends(get_db) ): base_price = 1000.0 factors = db.execute(text(""" SELECT option_id,factor,absolute_deduct FROM price_option_factor WHERE option_id IN :ids """), {"ids": tuple(option_ids)}).fetchall() price = base_price for f in factors: if f.factor: price *= float(f.factor) if f.absolute_deduct: price -= float(f.absolute_deduct) # 机型调节 adjust = db.execute(text(""" SELECT factor FROM price_adjust_factor WHERE level='machine' AND ref_id=:mid """), {"mid": machine_id}).fetchone() if adjust: price *= float(adjust.factor) html = f"""

估价结果

选择项:{",".join(option_ids)}
估价:{round(price,2)} 元
返回 """ return html @router.post("/estimate2", response_class=HTMLResponse) def estimate_submit( request: Request, machine_id: int = Form(...), capacity: str = Form(...), option_ids: list[int] = Form([]), db: Session = Depends(get_db) ): # ---------- 基础价格 ---------- base_price = db.execute( text(""" SELECT base_price FROM machine_base_price WHERE machine_id=:mid AND capacity=:cap """), {"mid": machine_id, "cap": capacity} ).scalar() or 0 price = float(base_price) # ---------- 扣减项 ---------- for oid in option_ids: r = db.execute( text(""" SELECT factor, absolute_deduct FROM price_option_factor WHERE option_id=:oid """), {"oid": oid} ).fetchone() if r: price = price * float(r.factor) - float(r.absolute_deduct) # ---------- 调节系数 ---------- brand_id = db.execute( text(""" SELECT brand_id FROM t_machine WHERE machine_id=:mid """), {"mid": machine_id} ).scalar() price = apply_adjust(db, machine_id, brand_id, price) price = round(max(price, 0), 2) # ---------- 估价版本 ---------- version_no = str(uuid.uuid4())[:8] db.execute( text(""" INSERT INTO estimate_record (machine_id, capacity, option_ids, final_price, version_no) VALUES (:m, :c, :o, :p, :v) """), { "m": machine_id, "c": capacity, "o": ",".join(map(str, option_ids)), "p": price, "v": version_no } ) db.commit() # ---------- 模板(Redis 缓存) ---------- cache_key = f"template:{machine_id}" cached = redis_client.get(cache_key) if redis_client else None if cached: template = json.loads(cached) else: rows = db.execute(text("SELECT * FROM release_option")).fetchall() template = build_template(rows) if redis_client: redis_client.set(cache_key, json.dumps(template), ex=3600) # ---------- 重新加载页面 ---------- machines = db.execute( text(""" SELECT machine_id, name FROM t_machine ORDER BY brand_name, name """) ).fetchall() capacities = db.execute( text(""" SELECT capacity FROM machine_base_price WHERE machine_id=:mid """), {"mid": machine_id} ).fetchall() return request.app.state.templates.TemplateResponse( "estimate.html", { "request": request, "machines": machines, "capacities": capacities, "template": template, "price": price, "version": version_no, "selected_machine": machine_id, "selected_capacity": capacity } )