main.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. from __future__ import annotations
  2. from pathlib import Path
  3. from fastapi import FastAPI
  4. from fastapi.middleware.cors import CORSMiddleware
  5. from .schemas import (
  6. TemplateCreate,
  7. MachineConfigCreate,
  8. MachineConfigUpdate,
  9. TemplatePreviewRequest,
  10. TemplateRenderRequest,
  11. TemplateRenderResponse,
  12. TemplateUpdate,
  13. )
  14. from .services.renderer import renderer
  15. from .services.template_store import TemplateStore, load_store
  16. from .services.machine_store import MachineStore, load_machine_store
  17. def create_app() -> FastAPI:
  18. base_dir = Path(__file__).resolve().parents[1]
  19. store: TemplateStore = load_store(base_dir)
  20. machine_store: MachineStore = load_machine_store(base_dir / "data")
  21. app = FastAPI(title="洗衣机语音播报模板运营系统", version="1.0.0")
  22. app.add_middleware(
  23. CORSMiddleware,
  24. allow_origins=["*"],
  25. allow_methods=["*"],
  26. allow_headers=["*"],
  27. )
  28. @app.get("/api/health")
  29. async def health():
  30. return {"status": "ok"}
  31. @app.get("/api/machine-configs")
  32. async def list_machine_configs():
  33. """获取所有机型配置"""
  34. return {
  35. "configs": machine_store.configs,
  36. "reuse_map": machine_store.reuse_map,
  37. }
  38. @app.post("/api/machine-configs", status_code=201)
  39. async def create_machine_config(payload: MachineConfigCreate):
  40. """创建新机型"""
  41. try:
  42. config = {
  43. "label": payload.label,
  44. "type_ids": payload.type_ids,
  45. "zone_ids": payload.zone_ids,
  46. "card_type": payload.card_type,
  47. }
  48. result = machine_store.create(payload.model_key, config)
  49. if payload.reuse_from:
  50. machine_store.set_reuse(payload.model_key, {"all": payload.reuse_from})
  51. return result
  52. except ValueError as e:
  53. from fastapi import HTTPException
  54. raise HTTPException(status_code=400, detail=str(e))
  55. @app.put("/api/machine-configs/{model_key}")
  56. async def update_machine_config(model_key: str, payload: MachineConfigUpdate):
  57. """更新机型配置"""
  58. try:
  59. existing = machine_store.get(model_key)
  60. if not existing:
  61. from fastapi import HTTPException
  62. raise HTTPException(status_code=404, detail=f"机型 '{model_key}' 不存在")
  63. config = {
  64. "label": payload.label if payload.label is not None else existing["label"],
  65. "type_ids": payload.type_ids if payload.type_ids is not None else existing["type_ids"],
  66. "zone_ids": payload.zone_ids if payload.zone_ids is not None else existing["zone_ids"],
  67. "card_type": payload.card_type if payload.card_type is not None else existing["card_type"],
  68. }
  69. result = machine_store.update(model_key, config)
  70. if payload.reuse_from is not None:
  71. if payload.reuse_from:
  72. machine_store.set_reuse(model_key, {"all": payload.reuse_from})
  73. elif model_key in machine_store.reuse_map:
  74. del machine_store.reuse_map[model_key]
  75. machine_store._save_reuse()
  76. return result
  77. except ValueError as e:
  78. from fastapi import HTTPException
  79. raise HTTPException(status_code=404, detail=str(e))
  80. @app.delete("/api/machine-configs/{model_key}", status_code=204)
  81. async def delete_machine_config(model_key: str):
  82. """删除机型"""
  83. try:
  84. machine_store.delete(model_key)
  85. return {"status": "deleted"}
  86. except ValueError as e:
  87. from fastapi import HTTPException
  88. raise HTTPException(status_code=404, detail=str(e))
  89. @app.get("/api/templates")
  90. async def list_templates(
  91. machine_model: str = None,
  92. device_type: str = None,
  93. template_type: str = None
  94. ):
  95. return store.list_templates(machine_model, device_type, template_type)
  96. @app.get("/api/templates/categories")
  97. async def list_categories(machine_model: str = None):
  98. return {"categories": store.list_categories(machine_model)}
  99. @app.get("/api/templates/machine-models")
  100. async def list_machine_models():
  101. return {"machine_models": store.list_machine_models()}
  102. @app.get("/api/templates/device-types")
  103. async def list_device_types(machine_model: str = None):
  104. return {"device_types": store.list_device_types(machine_model)}
  105. @app.get("/api/templates/template-types")
  106. async def list_template_types(machine_model: str = None, device_type: str = None):
  107. return {"template_types": store.list_template_types(machine_model, device_type)}
  108. @app.get("/api/templates/{template_id}")
  109. async def get_template(template_id: str):
  110. return store.get_template(template_id)
  111. @app.post("/api/templates", status_code=201)
  112. async def create_template(payload: TemplateCreate):
  113. return store.create_template(payload)
  114. @app.put("/api/templates/{template_id}")
  115. async def update_template(template_id: str, payload: TemplateUpdate):
  116. return store.update_template(template_id, payload)
  117. @app.delete("/api/templates/{template_id}", status_code=204)
  118. async def delete_template(template_id: str):
  119. store.delete_template(template_id)
  120. return {"status": "deleted"}
  121. @app.get("/api/templates/{template_id}/redis-keys")
  122. async def get_template_redis_keys(template_id: str):
  123. record = store.get_template(template_id)
  124. return store.generate_redis_keys(record)
  125. @app.post("/api/templates/render", response_model=TemplateRenderResponse)
  126. async def render_template(payload: TemplateRenderRequest):
  127. record = store.get_template(payload.template_id)
  128. rendered = renderer.render_from_record(record, payload.parameters)
  129. return {"rendered_text": rendered}
  130. @app.post("/api/templates/preview")
  131. async def preview_template(payload: TemplatePreviewRequest):
  132. """预览模板 - 自动识别变量"""
  133. return renderer.preview(payload)
  134. return app
  135. app = create_app()