| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970 |
- import { roundForObj } from '@sc/util';
- import evaluate from 'evaluator.js';
- // 关键字组
- export interface IKeywordItem {
- optionCode: string; // 选项号
- coe: string; // 系数 *1.29
- keyword: string;
- unit: string;
- }
- export interface IInfoPriceMain {
- classCode: string; // 别名编码 0749B01D01
- expString: string; // 表达式 :X*(1+(A-1)+(B-1)+(C-1))
- basePrice: string; // 基价
- }
- /* eslint-disable import/prefer-default-export */
- const replaceAll = (FindText: RegExp | string, RepText: string, str: string): string => {
- const regExp = new RegExp(FindText, 'g');
- return str.replace(regExp, RepText);
- };
- /**
- * 计算材料价
- * infoPrice:主表的数据
- * keywordItems : 关键字列表
- */
- export const calcMaterialExp = (infoPrice: IInfoPriceMain, keywordItems: IKeywordItem[]) => {
- const preCodeLength = 5; // 别名编码位数,可能要改成5位或6位
- const decimal = 2; // 小数位数
- const groupStr = infoPrice.classCode.substr(preCodeLength);
- let { expString } = infoPrice; // 计算式
- const matchKeywords: IKeywordItem[] = [];
- try {
- if (groupStr.length > 0) {
- let startIndex = 0;
- while (groupStr.length > startIndex) {
- const option = groupStr.substr(startIndex, 3); // 获取A01这样的编号
- const group = keywordItems.find(item => item.optionCode === option);
- if (group) {
- // 运距=15km 这种类型的要特殊处理 暂时没有办法处理~ 没法从编号中获取具体要加减多少
- const operator = group.coe.charAt(0); // 加 减 乘的操作
- const coeNumber = parseFloat(group.coe.substr(1)); // 要代入计算的系数
- let replaceStr = '';
- if (operator === '*') {
- // 乘法时,自减1
- replaceStr = `${coeNumber - 1}`;
- } else {
- // + 或者 - 操作符时,使用 (+10) 或者 (-10)来替换,
- replaceStr = `(${group.coe})`;
- }
- expString = replaceAll(option.charAt(0), replaceStr, expString);
- matchKeywords.push(group);
- }
- startIndex += 3;
- }
- // 替换基价
- expString = replaceAll('X', infoPrice.basePrice, expString);
- // 没找到的按0处理
- expString = replaceAll(/[a-zA-Z]/, '0', expString);
- return { price: roundForObj(evaluate(expString), decimal), matchKeywords };
- }
- } catch (error) {
- throw new Error('计算失败,表达式有误');
- }
- return { price: roundForObj(infoPrice.basePrice, decimal), matchKeywords };
- };
|