# 指标公式检查流程图 ## 整体架构 ``` ┌─────────────┐ │ 前端界面 │ │ (Browser) │ └──────┬──────┘ │ POST /api/data/metric/check │ {"formula": "销售额 = 单价 * 数量"} ↓ ┌──────────────────────────────────────┐ │ API Layer (Flask Routes) │ │ app/api/data_metric/routes.py │ │ │ │ @bp.route('/data/metric/check') │ │ def data_metric_check(): │ │ - 接收请求参数 │ │ - 参数验证 │ │ - 调用核心函数 │ │ - 返回JSON响应 │ └──────────────┬───────────────────────┘ │ │ metric_check(formula_text) ↓ ┌──────────────────────────────────────┐ │ Business Logic Layer (Core) │ │ app/core/data_metric/ │ │ metric_interface.py │ │ │ │ def metric_check(formula_text): │ │ 1. 解析公式 │ │ 2. 提取变量 │ │ 3. 查询数据库 │ │ 4. 返回结果 │ └──────────────┬───────────────────────┘ │ │ Cypher Query ↓ ┌──────────────────────────────────────┐ │ Data Layer (Neo4j) │ │ │ │ MATCH (n:DataMeta) │ │ WHERE n.name CONTAINS $variable │ │ RETURN n, id(n) as node_id │ │ LIMIT 1 │ └──────────────────────────────────────┘ ``` ## 详细流程 ### 1. 公式解析流程 ``` 输入公式: "销售额 = (单价 * 数量) + 运费 - 10" │ ↓ 按等号分割 │ ↓ ┌─────────────────────────┐ │ 左侧: "销售额" │ → 指标名称(暂不使用) │ 右侧: "(单价*数量)+运费-10"│ → 计算表达式 └─────────┬───────────────┘ │ ↓ 正则分割运算符 [+\-*/()()\[\]{}] │ ↓ ┌─────────────────────────┐ │ Tokens: │ │ ["单价", "数量", │ │ "运费", "10"] │ └─────────┬───────────────┘ │ ↓ 过滤中文变量 │ ↓ ┌─────────────────────────┐ │ Variables: │ │ ["单价", "数量", "运费"]│ └─────────┬───────────────┘ │ ↓ 变量去重 │ ↓ ┌─────────────────────────┐ │ Unique Variables: │ │ ["单价", "数量", "运费"]│ └─────────────────────────┘ ``` ### 2. 数据库查询流程 ``` 变量列表: ["单价", "数量", "运费"] │ ↓ ┌────────────────────────┐ │ for variable in list │ └────┬───────────────────┘ │ ↓ 查询Neo4j ┌──────────────────────────────┐ │ MATCH (n:DataMeta) │ │ WHERE n.name CONTAINS "单价" │ │ RETURN n, id(n) │ └────┬─────────────────────────┘ │ ↓ 是否找到? │ ├─ 是 ─→ ┌────────────────────┐ │ │ { │ │ │ variable: "单价" │ │ │ name_zh: "单价" │ │ │ name_en: "price" │ │ │ id: 101 │ │ │ findit: 1 │ │ │ } │ │ └────────────────────┘ │ └─ 否 ─→ ┌────────────────────┐ │ { │ │ variable: "运费" │ │ name_zh: "" │ │ name_en: "" │ │ id: null │ │ findit: 0 │ │ } │ └────────────────────┘ ``` ### 3. 响应构建流程 ``` 查询结果列表 │ ↓ ┌──────────────────────────┐ │ [ │ │ {variable:"单价", │ │ findit:1, id:101}, │ │ {variable:"数量", │ │ findit:1, id:102}, │ │ {variable:"运费", │ │ findit:0, id:null} │ │ ] │ └────┬─────────────────────┘ │ ↓ 包装成API响应 ┌──────────────────────────┐ │ { │ │ code: 200, │ │ message: "success", │ │ data: [...] │ │ } │ └────┬─────────────────────┘ │ ↓ JSON序列化 │ ↓ 返回给前端 ┌──────────────────────────┐ │ 前端显示结果 │ │ ✓ 单价: 已找到 │ │ ✓ 数量: 已找到 │ │ ✗ 运费: 未找到 │ └──────────────────────────┘ ``` ## 错误处理流程 ``` 请求到达 │ ↓ ┌───────────────┐ │ 参数验证 │ ─┬─→ formula为空 ──→ 返回错误 └───────┬───────┘ │ │ └─→ 无formula字段 ─→ 返回错误 ↓ ┌───────────────┐ │ 公式验证 │ ──→ 无等号 ──→ 返回空数组 └───────┬───────┘ │ ↓ ┌───────────────┐ │ 变量提取 │ ──→ 无中文变量 ──→ 返回空数组 └───────┬───────┘ │ ↓ ┌───────────────┐ │ 数据库查询 │ ─┬─→ 连接失败 ──→ 返回空数组 └───────┬───────┘ │ │ └─→ 查询异常 ──→ 记录日志,返回错误 │ ↓ 正常返回 ``` ## 数据流图 ``` ┌─────────┐ │ 前端 │ └────┬────┘ │ │ 1. 用户输入公式 │ "销售额 = 单价 * 数量" │ ↓ ┌─────────────┐ │ API接口 │ └──────┬──────┘ │ │ 2. 解析并验证 │ formula_text = "销售额 = 单价 * 数量" │ ↓ ┌──────────────────┐ │ 核心业务逻辑 │ └───────┬──────────┘ │ │ 3. 提取变量 │ variables = ["单价", "数量"] │ ↓ ┌──────────────┐ │ Neo4j │ ←─ 4. 查询元数据 └──────┬───────┘ "MATCH (n:DataMeta) WHERE..." │ │ 5. 返回节点数据 │ [{name:"单价", en_name:"price", id:101}, ...] │ ↓ ┌──────────────────┐ │ 核心业务逻辑 │ └───────┬──────────┘ │ │ 6. 格式化结果 │ [{variable:"单价", findit:1, id:101}, ...] │ ↓ ┌─────────────┐ │ API接口 │ └──────┬──────┘ │ │ 7. JSON响应 │ {code:200, message:"success", data:[...]} │ ↓ ┌─────────┐ │ 前端 │ └─────────┘ 显示结果 ``` ## 时序图 ``` 前端 API接口 核心函数 Neo4j │ │ │ │ │─POST────────→│ │ │ │ formula │ │ │ │ │ │ │ │ │─调用─────────→│ │ │ │ metric_check │ │ │ │ │ │ │ │ │─解析公式────→│ │ │ │ │ │ │ │←提取变量─────│ │ │ │ ["单价","数量"]│ │ │ │ │ │ │ │─查询: 单价──→│ │ │ │ │ │ │ │←返回节点────│ │ │ │ {id:101,...} │ │ │ │ │ │ │ │─查询: 数量──→│ │ │ │ │ │ │ │←返回节点────│ │ │ │ {id:102,...} │ │ │ │ │ │ │←返回结果─────│ │ │ │ [findit:1,...]│ │ │ │ │ │ │←JSON响应────│ │ │ │ {code:200} │ │ │ │ │ │ │ ``` ## 状态转换图 ``` [开始] │ ↓ [接收请求] ─错误─→ [返回错误响应] │ │ 成功 ↓ [解析公式] ─无等号─→ [返回空数组] │ │ 有等号 ↓ [提取变量] ─无变量─→ [返回空数组] │ │ 有变量 ↓ [查询数据库] ─连接失败─→ [返回空数组] │ │ 连接成功 ↓ [处理每个变量] │ ├─找到匹配─→ [findit=1] │ │ └─未找到───→ [findit=0] │ ↓ [收集结果] │ ↓ [返回成功响应] │ ↓ [结束] ``` ## 关键决策点 ``` 1. 公式是否有效? ├─ 是: 继续 └─ 否: 返回错误 2. 是否提取到变量? ├─ 是: 查询数据库 └─ 否: 返回空数组 3. 数据库连接是否正常? ├─ 是: 执行查询 └─ 否: 返回空数组 4. 是否找到匹配? ├─ 是: findit=1 └─ 否: findit=0 5. 是否还有更多变量? ├─ 是: 继续查询 └─ 否: 返回结果 ``` --- **说明**: - 实线箭头 (→): 正常流程 - 虚线箭头 (⇢): 数据流 - 分支 (├─): 决策点 - 单向箭头 (↓): 顺序执行