数据定价计算方式更新
Showing
1 changed file
with
41 additions
and
14 deletions
| ... | @@ -848,36 +848,63 @@ const reporting = (formInfo) => { | ... | @@ -848,36 +848,63 @@ const reporting = (formInfo) => { |
| 848 | const calculatePrice = (pData) => { | 848 | const calculatePrice = (pData) => { |
| 849 | let modelFormula = modelData.value.modelFormula; | 849 | let modelFormula = modelData.value.modelFormula; |
| 850 | // 1. 移除所有干扰的引号(确保是数学表达式) | 850 | // 1. 移除所有干扰的引号(确保是数学表达式) |
| 851 | modelFormula = modelFormula.replace(/["']/g, ""); | 851 | modelFormula = modelFormula.replace(/["']/g, "").trim(); |
| 852 | 852 | ||
| 853 | // 1. 提取变量名(中文、英文、数字、下划线) | 853 | // 2. 定义允许的数学运算符和函数 |
| 854 | const allowedOperators = /[+\-*/%^() .\d]/; | ||
| 855 | const mathFunctions = ['sin', 'cos', 'tan', 'log', 'sqrt', 'abs', 'pow']; | ||
| 856 | |||
| 857 | // 3. 提取变量名 | ||
| 854 | const variableRegex = /[\u4e00-\u9fa5a-zA-Z_][\u4e00-\u9fa5a-zA-Z0-9_]*/g; | 858 | const variableRegex = /[\u4e00-\u9fa5a-zA-Z_][\u4e00-\u9fa5a-zA-Z0-9_]*/g; |
| 855 | const variableNames = modelFormula.match(variableRegex) || []; | 859 | const variableNames = modelFormula.match(variableRegex) || []; |
| 856 | |||
| 857 | // 2. 去重 | ||
| 858 | const uniqueVariables = [...new Set(variableNames)]; | 860 | const uniqueVariables = [...new Set(variableNames)]; |
| 859 | 861 | ||
| 860 | // 3. 构建变量映射 { 销售额: 2000, 成本: 500.5, ... } | 862 | // 4. 构建变量映射 |
| 861 | const variables = {}; | 863 | const variables = {}; |
| 862 | uniqueVariables.forEach(name => { | 864 | uniqueVariables.forEach(name => { |
| 863 | const dim = pData.find(d => d.dimensionalityName === name); | 865 | // 过滤数学函数 |
| 864 | variables[name] = dim ? parseFloat(dim.sNum) : 0; // 找不到则默认为 0 | 866 | if (!mathFunctions.includes(name)) { |
| 867 | const dim = pData.find(d => d.dimensionalityName === name); | ||
| 868 | variables[name] = dim ? parseFloat(dim.sNum) || 0 : 0; | ||
| 869 | } | ||
| 865 | }); | 870 | }); |
| 866 | 871 | ||
| 867 | // 4. 替换变量为数值(不加引号,确保是数字运算) | 872 | // 5. 替换变量为数值(考虑边界情况) |
| 868 | let expression = modelFormula; | 873 | let expression = modelFormula; |
| 869 | uniqueVariables.forEach(name => { | 874 | Object.keys(variables).forEach(name => { |
| 870 | expression = expression.replace(new RegExp(name, 'g'), variables[name]); | 875 | expression = expression.replace(new RegExp(name, 'g'), variables[name]); |
| 871 | }); | 876 | }); |
| 872 | 877 | ||
| 873 | // 5. 安全计算(推荐 math.js,或 new Function) | 878 | // 7. 表达式安全检查 |
| 879 | // 7.1 检查是否只包含允许的字符 | ||
| 880 | const sanitizedExpr = expression.replace(allowedOperators, ''); | ||
| 881 | if (sanitizedExpr.length > 0) { | ||
| 882 | console.error('公式包含非法字符:', sanitizedExpr); | ||
| 883 | return NaN; | ||
| 884 | } | ||
| 885 | // 8. 执行计算 | ||
| 874 | try { | 886 | try { |
| 875 | //如果用 eval,确保表达式格式正确 | 887 | // 8.1 转换运算符 |
| 876 | const resultNum = eval(expression); | 888 | expression = expression |
| 889 | .replace(/\s+/g, '') // 去除空格 | ||
| 890 | .replace(/\^/g, '**') // 转换幂运算 | ||
| 891 | .replace(/÷/g, '/') // 转换除法符号 | ||
| 892 | .replace(/×/g, '*') // 转换乘法符号 | ||
| 893 | .replace(/(\d+)\(/g, '$1*(') // 处理隐式乘法 | ||
| 894 | .replace(/\)\(/g, ')*('); // 处理括号间乘法 | ||
| 877 | 895 | ||
| 878 | dataTransactionPrice.value = (Math.round(parseFloat(resultNum) * 100) / 100).toFixed(2); | 896 | // 8.2 安全计算 |
| 897 | const result = new Function('return ' + expression)(); | ||
| 898 | const roundedResult = Math.round(parseFloat(result) * 100) / 100; | ||
| 899 | |||
| 900 | dataTransactionPrice.value = roundedResult.toFixed(2); | ||
| 901 | return roundedResult; | ||
| 879 | } catch (error) { | 902 | } catch (error) { |
| 880 | console.error('公式计算错误:', error); | 903 | console.error('公式计算错误:', { |
| 904 | error, | ||
| 905 | originalFormula: modelFormula, | ||
| 906 | processedFormula: expression | ||
| 907 | }); | ||
| 881 | return NaN; | 908 | return NaN; |
| 882 | } | 909 | } |
| 883 | }; | 910 | }; | ... | ... |
-
Please register or sign in to post a comment