|
@@ -59,6 +59,28 @@ $(document).ready(() => {
|
|
|
for (const b of this.bases) {
|
|
|
b.reg = new RegExp(b.code, 'igm');
|
|
|
}
|
|
|
+ this.orderReg = /f\d+/ig;
|
|
|
+ }
|
|
|
+
|
|
|
+ getLeafOrder(data) {
|
|
|
+ if (!data) return [];
|
|
|
+ if (!data.expr) return [`f${data.order}`];
|
|
|
+ const orderParam = data.expr.match(this.orderReg);
|
|
|
+ if (!orderParam || orderParam.length === 0) return [`f${data.order}`];
|
|
|
+
|
|
|
+ const result = [], payData = paySheet.zh_data || [];
|
|
|
+ for (const op of orderParam) {
|
|
|
+ const order = op.substring(1, op.length);
|
|
|
+ result.push(...this.getLeafOrder(payData[parseInt(order) -1]));
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ checkCircularExpr(expr, selfOrder) {
|
|
|
+ const leafOrder = this.getLeafOrder({expr});
|
|
|
+
|
|
|
+ if (leafOrder.indexOf(`f${selfOrder}`) >= 0 || leafOrder.indexOf(`F${selfOrder}`) >= 0) return true;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
calculateExpr(expr) {
|
|
@@ -85,6 +107,7 @@ $(document).ready(() => {
|
|
|
return new PayCalc(b);
|
|
|
})(calcBase);
|
|
|
const paySpread = SpreadJsObj.createNewSpread($('#pay-spread')[0]);
|
|
|
+ const paySheet = paySpread.getActiveSheet();
|
|
|
const wcPay = dealPay.find(function (x) {return x.ptype === 4});
|
|
|
|
|
|
$.subMenu({
|
|
@@ -230,7 +253,6 @@ $(document).ready(() => {
|
|
|
},
|
|
|
isLock: function (data) {
|
|
|
const result = !!lockPayExpr && payBase.isStarted(data) && payBase.hasBase(data);
|
|
|
- console.log(data.name, result);
|
|
|
return result;
|
|
|
}
|
|
|
};
|
|
@@ -309,17 +331,31 @@ $(document).ready(() => {
|
|
|
SpreadJsObj.loadSheetData(paySpread.getActiveSheet(), SpreadJsObj.DataType.Data, dealPay);
|
|
|
|
|
|
const paySpreadObj = {
|
|
|
- _checkExprValid(expr, invalidParam) {
|
|
|
+ _checkExprValid(expr, invalidParam, selfOrder) {
|
|
|
if (!expr) return [true, null];
|
|
|
const param = [];
|
|
|
+ const orderReg = /^f\d+/i;
|
|
|
let num = '', base = '';
|
|
|
for (let i = 0, iLen = expr.length; i < iLen; i++) {
|
|
|
+ const subExpr = expr.substring(i, expr.length);
|
|
|
if (/^[\d\.%]+/.test(expr[i])) {
|
|
|
if (base !== '') {
|
|
|
param.push({type: 'base', value: base});
|
|
|
base = '';
|
|
|
}
|
|
|
num = num + expr[i];
|
|
|
+ } else if (orderReg.test(subExpr)) {
|
|
|
+ if (num !== '') {
|
|
|
+ param.push({type: 'num', value: num});
|
|
|
+ num = '';
|
|
|
+ }
|
|
|
+ if (base !== '') {
|
|
|
+ param.push({type: 'base', value: base});
|
|
|
+ base = '';
|
|
|
+ }
|
|
|
+ const order = orderReg.exec(subExpr);
|
|
|
+ param.push({type: 'order', value: order[0]});
|
|
|
+ i = i + order[0].length - 1;
|
|
|
} else if (/^[a-z]/.test(expr[i])) {
|
|
|
if (num !== '') {
|
|
|
param.push({type: 'num', value: num});
|
|
@@ -406,6 +442,12 @@ $(document).ready(() => {
|
|
|
if (i > 0 && (param[i - 1].type === 'num' || param[i - 1].type === 'right'))
|
|
|
return [false, '输入的表达式非法:' + p.value + '前应有运算符'];
|
|
|
}
|
|
|
+ if (p.type === 'order') {
|
|
|
+ if (selfOrder === undefined) return [false, '输入的表达式错误:不支持行号引用'];
|
|
|
+
|
|
|
+ if ([`f${selfOrder}`, `F${selfOrder}`].indexOf(p.value) >= 0) return [false, '输入的表达式非法:请勿引用自己'];
|
|
|
+ if (['f1', 'f2', 'f3', 'F1', 'F2', 'F3'].indexOf(p.value) >= 0) return [false, '输入的表达式非法:请勿引用前三行'];
|
|
|
+ }
|
|
|
if (p.type === 'left') {
|
|
|
iLeftCount += 1;
|
|
|
if (i !== 0 && param[i-1].type !== 'calc')
|
|
@@ -421,6 +463,11 @@ $(document).ready(() => {
|
|
|
}
|
|
|
if (iLeftCount > iRightCount)
|
|
|
return [false, '输入的表达式非法:"("后无对应的")"'];
|
|
|
+
|
|
|
+ if (selfOrder !== undefined) {
|
|
|
+ const circular = payCalc.checkCircularExpr(expr);
|
|
|
+ if (circular) return [false, '输入的表达式非法:循环引用'];
|
|
|
+ }
|
|
|
return [true, ''];
|
|
|
},
|
|
|
_checkSExpr: function (payNode, text, data) {
|
|
@@ -479,7 +526,7 @@ $(document).ready(() => {
|
|
|
return [true, ''];
|
|
|
}
|
|
|
},
|
|
|
- _checkExpr: function (text, data) {
|
|
|
+ _checkExpr: function (text, data, order) {
|
|
|
if (text) {
|
|
|
const num = _.toNumber(text);
|
|
|
if (num) {
|
|
@@ -487,7 +534,7 @@ $(document).ready(() => {
|
|
|
data.expr = null;
|
|
|
} else {
|
|
|
const expr = $.trim(text).replace('\t', '').replace('=', '').toLowerCase();
|
|
|
- const [valid, msg] = this._checkExprValid(expr, ['bqyf']);
|
|
|
+ const [valid, msg] = this._checkExprValid(expr, ['bqyf'], order);
|
|
|
if (!valid) return [valid, msg];
|
|
|
data.expr = expr;
|
|
|
data.tp = null;
|
|
@@ -675,7 +722,7 @@ $(document).ready(() => {
|
|
|
case 'tp':
|
|
|
const [tpValid, tpMsg] = payBase.isSF(select)
|
|
|
? paySpreadObj._checkSfExpr(validText, data.updateData)
|
|
|
- : paySpreadObj._checkExpr(validText, data.updateData);
|
|
|
+ : paySpreadObj._checkExpr(validText, data.updateData, select.order);
|
|
|
if (!tpValid) {
|
|
|
toastr.warning(tpMsg);
|
|
|
SpreadJsObj.reLoadRowData(info.sheet, info.row);
|
|
@@ -848,7 +895,7 @@ $(document).ready(() => {
|
|
|
case 'tp':
|
|
|
const [tpValid, tpMsg] = payBase.isSF(node)
|
|
|
? paySpreadObj._checkSfExpr(validText, updateData)
|
|
|
- : paySpreadObj._checkExpr(validText, updateData);
|
|
|
+ : paySpreadObj._checkExpr(validText, updateData, select.order);
|
|
|
if (!tpValid) {
|
|
|
toastr.warning(tpMsg);
|
|
|
SpreadJsObj.reLoadSheetData(paySpread.getActiveSheet());
|
|
@@ -923,7 +970,7 @@ $(document).ready(() => {
|
|
|
data.updateData = { pid: select.pid, tp: null, expr: newValue };
|
|
|
const [valid, msg] = payBase.isSF(select)
|
|
|
? paySpreadObj._checkSfExpr(newValue, data.updateData)
|
|
|
- : paySpreadObj._checkExpr(newValue, data.updateData);
|
|
|
+ : paySpreadObj._checkExpr(newValue, data.updateData, select.order);
|
|
|
if (!valid) {
|
|
|
toastr.warning(msg);
|
|
|
this.value = select.expr;
|