metric-check-examples.md 12 KB

指标公式检查 - 使用示例

基础示例

示例1: 简单的加法公式

输入:

{
  "formula": "销售总额 = 单价 + 数量"
}

输出:

{
  "code": 200,
  "message": "success",
  "data": [
    {
      "variable": "单价",
      "name_zh": "单价",
      "name_en": "unit_price",
      "id": 101,
      "create_time": "2024-01-15 10:00:00",
      "findit": 1
    },
    {
      "variable": "数量",
      "name_zh": "数量",
      "name_en": "quantity",
      "id": 102,
      "create_time": "2024-01-15 10:01:00",
      "findit": 1
    }
  ]
}

示例2: 包含乘法的公式

输入:

{
  "formula": "销售额 = 单价 * 数量"
}

说明: 系统会提取 "单价" 和 "数量" 两个变量并在数据库中查找。

示例3: 复杂的计算公式

输入:

{
  "formula": "利润率 = (销售收入 - 成本) / 销售收入 * 100"
}

输出:

{
  "code": 200,
  "message": "success",
  "data": [
    {
      "variable": "销售收入",
      "name_zh": "销售收入",
      "name_en": "sales_revenue",
      "id": 201,
      "create_time": "2024-02-01 14:30:00",
      "findit": 1
    },
    {
      "variable": "成本",
      "name_zh": "成本",
      "name_en": "cost",
      "id": 202,
      "create_time": "2024-02-01 14:31:00",
      "findit": 1
    }
  ]
}

说明: 数字 "100" 会被自动过滤,不会出现在结果中。

特殊情况示例

示例4: 变量未找到

输入:

{
  "formula": "总成本 = 原材料成本 + 人工成本 + 其他费用"
}

输出:

{
  "code": 200,
  "message": "success",
  "data": [
    {
      "variable": "原材料成本",
      "name_zh": "原材料成本",
      "name_en": "material_cost",
      "id": 301,
      "create_time": "2024-03-01 09:00:00",
      "findit": 1
    },
    {
      "variable": "人工成本",
      "name_zh": "人工成本",
      "name_en": "labor_cost",
      "id": 302,
      "create_time": "2024-03-01 09:01:00",
      "findit": 1
    },
    {
      "variable": "其他费用",
      "name_zh": "",
      "name_en": "",
      "id": null,
      "create_time": "",
      "findit": 0
    }
  ]
}

前端处理建议:

data.data.forEach(item => {
  if (item.findit === 0) {
    // 提示用户该变量未找到
    alert(`变量 "${item.variable}" 未在元数据库中找到,是否需要创建?`);
  }
});

示例5: 中文括号

输入:

{
  "formula": "总额 = (收入 + 支出)* 汇率"
}

说明: 支持中文括号(),会正确提取 "收入"、"支出" 和 "汇率" 三个变量。

示例6: 混合括号

输入:

{
  "formula": "结果 = [收入 + (支出 * 税率)] / 总数"
}

说明: 支持方括号 [] 和圆括号 () 混用。

示例7: 纯数字公式

输入:

{
  "formula": "常量 = 100 + 200 * 3"
}

输出:

{
  "code": 200,
  "message": "success",
  "data": []
}

说明: 没有中文变量,返回空数组。

示例8: 重复变量

输入:

{
  "formula": "总计 = 单价 + 单价 * 0.1"
}

输出:

{
  "code": 200,
  "message": "success",
  "data": [
    {
      "variable": "单价",
      "name_zh": "单价",
      "name_en": "unit_price",
      "id": 101,
      "create_time": "2024-01-15 10:00:00",
      "findit": 1
    }
  ]
}

说明: 重复的变量会自动去重,只返回一次。

错误处理示例

示例9: 缺少等号

输入:

{
  "formula": "销售额"
}

输出:

{
  "code": 200,
  "message": "success",
  "data": []
}

说明: 缺少等号会返回空数组,不会报错。

示例10: 空公式

输入:

{
  "formula": ""
}

输出:

{
  "code": 400,
  "message": "failed",
  "data": {},
  "error": {
    "error": "公式文本不能为空"
  }
}

示例11: 缺少参数

输入:

{}

输出:

{
  "code": 400,
  "message": "failed",
  "data": {},
  "error": {
    "error": "公式文本不能为空"
  }
}

实际应用场景

场景1: 指标创建时的验证

// 前端代码示例
function validateMetricFormula(formula) {
  fetch('/api/data/metric/check', {
    method: 'POST',
    headers: {'Content-Type': 'application/json'},
    body: JSON.stringify({formula})
  })
  .then(res => res.json())
  .then(result => {
    if (result.code === 200) {
      const notFound = result.data.filter(item => item.findit === 0);
      
      if (notFound.length > 0) {
        // 显示警告
        const variables = notFound.map(item => item.variable).join(', ');
        showWarning(`以下变量未找到:${variables}`);
        
        // 询问用户是否继续
        if (confirm('是否继续创建指标?')) {
          createMetric(formula);
        }
      } else {
        // 所有变量都找到,直接创建
        createMetric(formula);
      }
    }
  });
}

场景2: 实时检查和提示

// 前端代码示例 - 输入时实时检查
let checkTimeout;
document.getElementById('formulaInput').addEventListener('input', (e) => {
  clearTimeout(checkTimeout);
  
  checkTimeout = setTimeout(() => {
    const formula = e.target.value;
    
    if (formula.includes('=')) {
      fetch('/api/data/metric/check', {
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify({formula})
      })
      .then(res => res.json())
      .then(result => {
        if (result.code === 200) {
          displayCheckResults(result.data);
        }
      });
    }
  }, 500); // 500ms防抖
});

function displayCheckResults(data) {
  const container = document.getElementById('checkResults');
  container.innerHTML = '';
  
  data.forEach(item => {
    const div = document.createElement('div');
    div.className = item.findit ? 'found' : 'not-found';
    div.innerHTML = `
      <span>${item.variable}</span>
      ${item.findit ? 
        `<span class="success">✓ ${item.name_zh} (${item.name_en})</span>` :
        `<span class="error">✗ 未找到</span>`
      }
    `;
    container.appendChild(div);
  });
}

场景3: 批量检查多个指标

# Python批量检查示例
import requests

formulas = [
    "销售额 = 单价 * 数量",
    "利润 = 收入 - 成本",
    "利润率 = 利润 / 收入 * 100"
]

results = []
for formula in formulas:
    response = requests.post(
        'http://localhost:5000/api/data/metric/check',
        json={'formula': formula}
    )
    result = response.json()
    
    if result['code'] == 200:
        not_found = [item for item in result['data'] if item['findit'] == 0]
        results.append({
            'formula': formula,
            'status': 'ok' if len(not_found) == 0 else 'warning',
            'missing_variables': [item['variable'] for item in not_found]
        })

# 生成报告
for item in results:
    print(f"公式: {item['formula']}")
    print(f"状态: {item['status']}")
    if item['missing_variables']:
        print(f"缺失变量: {', '.join(item['missing_variables'])}")
    print('---')

场景4: 与其他功能集成

// 指标编辑器示例
class MetricEditor {
  constructor() {
    this.formula = '';
    this.checkResults = [];
  }
  
  // 设置公式
  setFormula(formula) {
    this.formula = formula;
    this.checkFormula();
  }
  
  // 检查公式
  async checkFormula() {
    if (!this.formula.includes('=')) return;
    
    const response = await fetch('/api/data/metric/check', {
      method: 'POST',
      headers: {'Content-Type': 'application/json'},
      body: JSON.stringify({formula: this.formula})
    });
    
    const result = await response.json();
    this.checkResults = result.data || [];
    this.updateUI();
  }
  
  // 更新界面
  updateUI() {
    // 高亮显示未找到的变量
    const notFound = this.checkResults.filter(item => item.findit === 0);
    notFound.forEach(item => {
      this.highlightVariable(item.variable, 'error');
    });
    
    // 显示统计
    const total = this.checkResults.length;
    const found = this.checkResults.filter(item => item.findit === 1).length;
    this.showStats(`${found}/${total} 个变量已找到`);
  }
  
  // 是否可以保存
  canSave() {
    const notFound = this.checkResults.filter(item => item.findit === 0);
    return notFound.length === 0;
  }
  
  // 获取缺失的变量
  getMissingVariables() {
    return this.checkResults
      .filter(item => item.findit === 0)
      .map(item => item.variable);
  }
}

Python客户端完整示例

import requests
import json

class MetricChecker:
    def __init__(self, base_url):
        self.base_url = base_url
        self.api_url = f"{base_url}/api/data/metric/check"
    
    def check(self, formula):
        """检查单个公式"""
        try:
            response = requests.post(
                self.api_url,
                json={'formula': formula},
                headers={'Content-Type': 'application/json'}
            )
            return response.json()
        except Exception as e:
            return {'error': str(e)}
    
    def check_batch(self, formulas):
        """批量检查多个公式"""
        results = []
        for formula in formulas:
            result = self.check(formula)
            results.append({
                'formula': formula,
                'result': result
            })
        return results
    
    def get_missing_variables(self, formula):
        """获取缺失的变量列表"""
        result = self.check(formula)
        if result.get('code') == 200:
            return [
                item['variable'] 
                for item in result.get('data', []) 
                if item['findit'] == 0
            ]
        return []
    
    def validate(self, formula):
        """验证公式是否完全可用"""
        missing = self.get_missing_variables(formula)
        return len(missing) == 0, missing
    
    def format_report(self, formula):
        """生成格式化的报告"""
        result = self.check(formula)
        
        if result.get('code') != 200:
            return f"错误: {result.get('error', '未知错误')}"
        
        report = [f"公式: {formula}", "=" * 50]
        
        data = result.get('data', [])
        if not data:
            report.append("未找到任何变量")
        else:
            for item in data:
                status = "✓" if item['findit'] == 1 else "✗"
                name = item['name_zh'] if item['findit'] == 1 else "未找到"
                report.append(f"{status} {item['variable']}: {name}")
        
        return "\n".join(report)

# 使用示例
if __name__ == '__main__':
    checker = MetricChecker('http://localhost:5000')
    
    # 示例1: 检查单个公式
    print("示例1: 检查单个公式")
    print(checker.format_report("销售额 = 单价 * 数量"))
    print()
    
    # 示例2: 验证公式
    print("示例2: 验证公式")
    formula = "利润 = 收入 - 成本"
    is_valid, missing = checker.validate(formula)
    if is_valid:
        print(f"✓ 公式有效: {formula}")
    else:
        print(f"✗ 公式无效,缺少变量: {', '.join(missing)}")
    print()
    
    # 示例3: 批量检查
    print("示例3: 批量检查")
    formulas = [
        "销售额 = 单价 * 数量",
        "成本 = 原材料 + 人工",
        "利润率 = 利润 / 销售额"
    ]
    results = checker.check_batch(formulas)
    for item in results:
        print(f"公式: {item['formula']}")
        data = item['result'].get('data', [])
        found = sum(1 for x in data if x['findit'] == 1)
        total = len(data)
        print(f"  变量匹配: {found}/{total}")
        print()

总结

这些示例展示了:

  1. 基础用法和各种公式格式
  2. 特殊情况和边界条件处理
  3. 错误处理机制
  4. 实际应用场景的集成方式
  5. 前后端完整的使用示例

根据实际需求,可以灵活调整和扩展这些示例代码。