Files
tick-stock-panel/backend/app/api/definitions.py
T
shy3130 5d06af60b2 feat(definitions): 统一定义选择器前端 + 冒烟 API 按 id 复检 + 备份导入冒烟展示
- POST /api/definitions/smoke 支持 id 直查已存定义 (smoke_stored),
  统一选择器逐条冒烟无需回传原始定义; 不存在 fail-closed 404
- DefinitionPicker 可复用组件: 跨 kind 目录 (21 内置信号实测) +
  kind 筛选/搜索/依赖 chips/预热/坏定义隔离展示 + 逐条冒烟
- 设置页新增「定义目录」页签; Backup 导入结果新增「导入冒烟」小节
  (apply 响应 smoke 逐条渲染, 失败条目带 issue 编码)
- 验收: pnpm build 过; 浏览器 E2E 导出→覆盖导入 275 项→
  冒烟 21/21 通过零 issue; 后端 36 契约测试过

Signed-off-by: shy3130 <shy3130@qq.com>
2026-10-26 15:54:03 +08:00

46 lines
1.5 KiB
Python

"""统一定义目录与导入冒烟 API (P4) — 一切皆扩展的消费面。
GET /api/definitions → 跨 kind 目录 (统一选择器的数据半边)
POST /api/definitions/smoke → 导入冒烟 (校验 + 编译 + 依赖可解析)
"""
from __future__ import annotations
from fastapi import APIRouter, Request
from pydantic import BaseModel, Field
from app import definitions as defs
router = APIRouter(prefix="/api/definitions", tags=["definitions"])
class SmokeRequest(BaseModel):
kind: str = Field(pattern="^(signal|factor)$")
definition: dict | None = None
# 二选一: 传 id 时按存储重查该定义复检 (统一选择器的"逐条冒烟"),
# 不必先把原始定义回传服务端。
id: str | None = None
@router.get("")
def list_definitions(request: Request) -> dict:
return {"items": defs.catalog(_data_dir(request))}
@router.post("/smoke")
def smoke_definition(req: SmokeRequest) -> dict:
"""导入冒烟: 返回 ok/issues/dependencies/warmup_bars, 不落盘。"""
if req.id is not None:
return defs.smoke_stored(req.kind, req.id, _data_dir(None))
if req.definition is None:
from fastapi import HTTPException
raise HTTPException(status_code=422, detail="definition 与 id 必须提供其一")
return defs.smoke_definition(req.kind, req.definition)
def _data_dir(request: Request):
from app.config import settings
_ = request # 预留 request 级覆写口; 当前与各 API 一致用全局 settings
return settings.data_dir