@zhenliang/sheet 0.2.4 → 0.2.5-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/editor/InputOptionsEditor/index.d.ts +14 -0
- package/dist/core/editor/InputOptionsEditor/index.js +645 -0
- package/dist/core/editor/InputOptionsEditor/index.less +57 -0
- package/dist/core/editor/InputOptionsEditor/utils.d.ts +59 -0
- package/dist/core/editor/InputOptionsEditor/utils.js +335 -0
- package/dist/core/editor/InputOptionsEditor/vaildFormula.js +333 -0
- package/dist/core/editor/index.d.ts +1 -0
- package/dist/core/editor/index.js +2 -1
- package/dist/example/basic.d.ts +1 -0
- package/dist/example/basic.js +52 -5
- package/dist/example/index.less +7 -4
- package/package.json +1 -1
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
|
|
2
|
+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
|
3
|
+
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
|
|
4
|
+
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
5
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
|
+
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
|
+
/**
|
|
8
|
+
* 词法分析器:分词
|
|
9
|
+
*/
|
|
10
|
+
var Lexer = /*#__PURE__*/function () {
|
|
11
|
+
function Lexer(input) {
|
|
12
|
+
_classCallCheck(this, Lexer);
|
|
13
|
+
this.input = input;
|
|
14
|
+
this.pos = 0;
|
|
15
|
+
this.tokens = [];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// 词法规则:NUMBER
|
|
19
|
+
_createClass(Lexer, [{
|
|
20
|
+
key: "isNumberStart",
|
|
21
|
+
value: function isNumberStart(char) {
|
|
22
|
+
return char >= '0' && char <= '9';
|
|
23
|
+
}
|
|
24
|
+
}, {
|
|
25
|
+
key: "isDigit",
|
|
26
|
+
value: function isDigit(char) {
|
|
27
|
+
return char >= '0' && char <= '9';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// 词法规则:REFVAR
|
|
31
|
+
}, {
|
|
32
|
+
key: "isIdentifierStart",
|
|
33
|
+
value: function isIdentifierStart(char) {
|
|
34
|
+
return char >= 'a' && char <= 'z' || char >= 'A' && char <= 'Z' || char === '_';
|
|
35
|
+
}
|
|
36
|
+
}, {
|
|
37
|
+
key: "isIdentifierChar",
|
|
38
|
+
value: function isIdentifierChar(char) {
|
|
39
|
+
return this.isIdentifierStart(char) || this.isDigit(char);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// 词法规则:PERCENT
|
|
43
|
+
}, {
|
|
44
|
+
key: "isPercent",
|
|
45
|
+
value: function isPercent(char) {
|
|
46
|
+
return char === '%';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 执行词法分析
|
|
50
|
+
}, {
|
|
51
|
+
key: "tokenize",
|
|
52
|
+
value: function tokenize() {
|
|
53
|
+
while (this.pos < this.input.length) {
|
|
54
|
+
var char = this.input[this.pos];
|
|
55
|
+
|
|
56
|
+
// 跳过空白字符
|
|
57
|
+
if (char === ' ' || char === '\t' || char === '\r' || char === '\n') {
|
|
58
|
+
this.pos++;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// 尝试解析 NUMBER 或 PERCENT
|
|
63
|
+
if (this.isNumberStart(char)) {
|
|
64
|
+
var start = this.pos;
|
|
65
|
+
var hasDecimal = false;
|
|
66
|
+
|
|
67
|
+
// 匹配整数部分
|
|
68
|
+
if (char === '0') {
|
|
69
|
+
this.pos++;
|
|
70
|
+
} else {
|
|
71
|
+
while (this.pos < this.input.length && this.isDigit(this.input[this.pos])) {
|
|
72
|
+
this.pos++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// 匹配小数部分
|
|
77
|
+
if (this.pos < this.input.length && this.input[this.pos] === '.') {
|
|
78
|
+
hasDecimal = true;
|
|
79
|
+
this.pos++;
|
|
80
|
+
if (this.pos < this.input.length && this.isDigit(this.input[this.pos])) {
|
|
81
|
+
while (this.pos < this.input.length && this.isDigit(this.input[this.pos])) {
|
|
82
|
+
this.pos++;
|
|
83
|
+
}
|
|
84
|
+
} else {
|
|
85
|
+
// 小数点后没有数字,语法错误
|
|
86
|
+
this.pos = start + 1; // 回退到起始位置之后
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 检查是否是 PERCENT
|
|
92
|
+
if (this.pos < this.input.length && this.input[this.pos] === '%') {
|
|
93
|
+
this.tokens.push({
|
|
94
|
+
type: 'PERCENT',
|
|
95
|
+
value: this.input.substring(start, this.pos + 1)
|
|
96
|
+
});
|
|
97
|
+
this.pos++;
|
|
98
|
+
} else {
|
|
99
|
+
this.tokens.push({
|
|
100
|
+
type: 'NUMBER',
|
|
101
|
+
value: this.input.substring(start, this.pos)
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// 尝试解析 REFVAR
|
|
108
|
+
if (this.isIdentifierStart(char)) {
|
|
109
|
+
var _start = this.pos;
|
|
110
|
+
while (this.pos < this.input.length && this.isIdentifierChar(this.input[this.pos])) {
|
|
111
|
+
this.pos++;
|
|
112
|
+
}
|
|
113
|
+
this.tokens.push({
|
|
114
|
+
type: 'REFVAR',
|
|
115
|
+
value: this.input.substring(_start, this.pos)
|
|
116
|
+
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 解析运算符
|
|
121
|
+
if (char === '(') {
|
|
122
|
+
this.tokens.push({
|
|
123
|
+
type: 'LPAREN',
|
|
124
|
+
value: '('
|
|
125
|
+
});
|
|
126
|
+
this.pos++;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
if (char === ')') {
|
|
130
|
+
this.tokens.push({
|
|
131
|
+
type: 'RPAREN',
|
|
132
|
+
value: ')'
|
|
133
|
+
});
|
|
134
|
+
this.pos++;
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
if (char === '*') {
|
|
138
|
+
this.tokens.push({
|
|
139
|
+
type: 'MUL',
|
|
140
|
+
value: '*'
|
|
141
|
+
});
|
|
142
|
+
this.pos++;
|
|
143
|
+
continue;
|
|
144
|
+
}
|
|
145
|
+
if (char === '/') {
|
|
146
|
+
this.tokens.push({
|
|
147
|
+
type: 'DIV',
|
|
148
|
+
value: '/'
|
|
149
|
+
});
|
|
150
|
+
this.pos++;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (char === '+') {
|
|
154
|
+
this.tokens.push({
|
|
155
|
+
type: 'ADD',
|
|
156
|
+
value: '+'
|
|
157
|
+
});
|
|
158
|
+
this.pos++;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (char === '-') {
|
|
162
|
+
this.tokens.push({
|
|
163
|
+
type: 'SUB',
|
|
164
|
+
value: '-'
|
|
165
|
+
});
|
|
166
|
+
this.pos++;
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 无法识别的字符
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
}, {
|
|
176
|
+
key: "getTokens",
|
|
177
|
+
value: function getTokens() {
|
|
178
|
+
return this.tokens;
|
|
179
|
+
}
|
|
180
|
+
}]);
|
|
181
|
+
return Lexer;
|
|
182
|
+
}();
|
|
183
|
+
/**
|
|
184
|
+
* 语法分析器:递归下降解析器
|
|
185
|
+
* 实现标准优先级爬山算法处理运算符优先级
|
|
186
|
+
*/
|
|
187
|
+
var Parser = /*#__PURE__*/function () {
|
|
188
|
+
function Parser(tokens) {
|
|
189
|
+
_classCallCheck(this, Parser);
|
|
190
|
+
this.tokens = tokens;
|
|
191
|
+
this.pos = 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// prog: expr EOF
|
|
195
|
+
_createClass(Parser, [{
|
|
196
|
+
key: "parseProg",
|
|
197
|
+
value: function parseProg() {
|
|
198
|
+
var result = this.parseExpr();
|
|
199
|
+
if (!result) return false;
|
|
200
|
+
|
|
201
|
+
// 检查是否解析完所有 token
|
|
202
|
+
return this.pos >= this.tokens.length;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 入口表达式解析(处理最低优先级的加减运算)
|
|
206
|
+
}, {
|
|
207
|
+
key: "parseExpr",
|
|
208
|
+
value: function parseExpr() {
|
|
209
|
+
return this.parseAddSub();
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// 解析加减表达式(优先级低于乘除)
|
|
213
|
+
// expr: expr ('+' | '-') expr | term
|
|
214
|
+
}, {
|
|
215
|
+
key: "parseAddSub",
|
|
216
|
+
value: function parseAddSub() {
|
|
217
|
+
// 先解析左操作数
|
|
218
|
+
var left = this.parseMulDiv();
|
|
219
|
+
if (!left) return false;
|
|
220
|
+
|
|
221
|
+
// 用循环处理多个连续的加减运算符
|
|
222
|
+
while (true) {
|
|
223
|
+
var token = this.currentToken();
|
|
224
|
+
if (token && (token.type === 'ADD' || token.type === 'SUB')) {
|
|
225
|
+
this.pos++;
|
|
226
|
+
// 解析右操作数(使用更高优先级的规则)
|
|
227
|
+
var right = this.parseMulDiv();
|
|
228
|
+
if (!right) return false;
|
|
229
|
+
} else {
|
|
230
|
+
break;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 解析乘除表达式(优先级高于加减)
|
|
237
|
+
// term: term ('*' | '/') factor | factor
|
|
238
|
+
}, {
|
|
239
|
+
key: "parseMulDiv",
|
|
240
|
+
value: function parseMulDiv() {
|
|
241
|
+
// 先解析左操作数
|
|
242
|
+
var left = this.parseFactor();
|
|
243
|
+
if (!left) return false;
|
|
244
|
+
|
|
245
|
+
// 用循环处理多个连续的乘除运算符
|
|
246
|
+
while (true) {
|
|
247
|
+
var token = this.currentToken();
|
|
248
|
+
if (token && (token.type === 'MUL' || token.type === 'DIV')) {
|
|
249
|
+
this.pos++;
|
|
250
|
+
// 解析右操作数
|
|
251
|
+
var right = this.parseFactor();
|
|
252
|
+
if (!right) return false;
|
|
253
|
+
} else {
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return true;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// 解析基本表达式(括号、数字、百分比、变量)
|
|
261
|
+
// factor: '(' expr ')' | NUMBER | PERCENT | REFVAR
|
|
262
|
+
}, {
|
|
263
|
+
key: "parseFactor",
|
|
264
|
+
value: function parseFactor() {
|
|
265
|
+
var token = this.currentToken();
|
|
266
|
+
if (!token) return false;
|
|
267
|
+
|
|
268
|
+
// 处理括号表达式
|
|
269
|
+
if (token.type === 'LPAREN') {
|
|
270
|
+
this.pos++;
|
|
271
|
+
var exprResult = this.parseExpr();
|
|
272
|
+
if (!exprResult) return false;
|
|
273
|
+
var closeToken = this.currentToken();
|
|
274
|
+
if (!closeToken || closeToken.type !== 'RPAREN') return false;
|
|
275
|
+
this.pos++;
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// 处理数字
|
|
280
|
+
if (token.type === 'NUMBER') {
|
|
281
|
+
this.pos++;
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// 处理百分比数字
|
|
286
|
+
if (token.type === 'PERCENT') {
|
|
287
|
+
this.pos++;
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// 处理引用变量
|
|
292
|
+
if (token.type === 'REFVAR') {
|
|
293
|
+
this.pos++;
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
}, {
|
|
299
|
+
key: "currentToken",
|
|
300
|
+
value: function currentToken() {
|
|
301
|
+
return this.tokens[this.pos];
|
|
302
|
+
}
|
|
303
|
+
}]);
|
|
304
|
+
return Parser;
|
|
305
|
+
}();
|
|
306
|
+
/**
|
|
307
|
+
* 校验主函数
|
|
308
|
+
* @param {string} input - 要校验的表达式字符串
|
|
309
|
+
* @returns {boolean} - 校验通过返回 true,失败返回 false
|
|
310
|
+
*/
|
|
311
|
+
function validateCalculationExpr(input) {
|
|
312
|
+
// 输入验证
|
|
313
|
+
if (!input || typeof input !== 'string') {
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// 词法分析
|
|
318
|
+
var lexer = new Lexer(input);
|
|
319
|
+
if (!lexer.tokenize()) {
|
|
320
|
+
return false;
|
|
321
|
+
}
|
|
322
|
+
var tokens = lexer.getTokens();
|
|
323
|
+
|
|
324
|
+
// 检查是否有有效 token
|
|
325
|
+
if (tokens.length === 0) {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// 语法分析
|
|
330
|
+
var parser = new Parser(tokens);
|
|
331
|
+
return parser.parseProg();
|
|
332
|
+
}
|
|
333
|
+
export default validateCalculationExpr;
|
|
@@ -3,3 +3,4 @@ export { getDateEditor } from './dateEditor';
|
|
|
3
3
|
export { getNumberEditor, NumberEditor } from './numberEditor';
|
|
4
4
|
export { default as getSelectEditor } from './selectEditor';
|
|
5
5
|
export { default as getInputSelectEditor } from './inputSelectEditor/inputSelect';
|
|
6
|
+
export { default as getFormulaInputEditor } from './InputOptionsEditor';
|
|
@@ -2,4 +2,5 @@ export { default as getCascaderEditor } from "./cascaderEditor";
|
|
|
2
2
|
export { getDateEditor } from "./dateEditor";
|
|
3
3
|
export { getNumberEditor, NumberEditor } from "./numberEditor";
|
|
4
4
|
export { default as getSelectEditor } from "./selectEditor";
|
|
5
|
-
export { default as getInputSelectEditor } from "./inputSelectEditor/inputSelect";
|
|
5
|
+
export { default as getInputSelectEditor } from "./inputSelectEditor/inputSelect";
|
|
6
|
+
export { default as getFormulaInputEditor } from "./InputOptionsEditor";
|
package/dist/example/basic.d.ts
CHANGED
package/dist/example/basic.js
CHANGED
|
@@ -14,10 +14,11 @@ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o =
|
|
|
14
14
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
15
15
|
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
16
16
|
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
17
|
-
import { Table,
|
|
18
|
-
import { Space, Tag
|
|
17
|
+
import { Table, getFormulaInputEditor, getInputSelectEditor, getNumberEditor } from "./..";
|
|
18
|
+
import { Select, Space, Tag } from 'antd';
|
|
19
19
|
import 'antd/dist/antd.css';
|
|
20
20
|
import React, { useCallback, useState } from 'react';
|
|
21
|
+
import "./index.less";
|
|
21
22
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
23
|
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
23
24
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -64,6 +65,35 @@ var columns = [{
|
|
|
64
65
|
min: 0,
|
|
65
66
|
precision: 2
|
|
66
67
|
})
|
|
68
|
+
}, {
|
|
69
|
+
title: 'Formula',
|
|
70
|
+
dataIndex: 'formula',
|
|
71
|
+
key: 'formula',
|
|
72
|
+
width: 200,
|
|
73
|
+
cellConfig: {
|
|
74
|
+
className: 'testCell'
|
|
75
|
+
},
|
|
76
|
+
editor: getFormulaInputEditor([{
|
|
77
|
+
label: '单价',
|
|
78
|
+
value: 'price'
|
|
79
|
+
}, {
|
|
80
|
+
label: '数量',
|
|
81
|
+
value: 'qty'
|
|
82
|
+
}, {
|
|
83
|
+
label: '折扣',
|
|
84
|
+
value: 'discount',
|
|
85
|
+
info: '注意这个有点皮'
|
|
86
|
+
}, {
|
|
87
|
+
label: '价格相关',
|
|
88
|
+
value: 'priceGroup',
|
|
89
|
+
children: [{
|
|
90
|
+
label: '成本价',
|
|
91
|
+
value: 'cost'
|
|
92
|
+
}, {
|
|
93
|
+
label: '批发价',
|
|
94
|
+
value: 'wholesale'
|
|
95
|
+
}]
|
|
96
|
+
}])
|
|
67
97
|
}, {
|
|
68
98
|
title: 'Address',
|
|
69
99
|
editable: false,
|
|
@@ -111,19 +141,36 @@ var data = [{
|
|
|
111
141
|
name: 'John Brown',
|
|
112
142
|
age: 32,
|
|
113
143
|
address: 'New York No. 1 Lake Park',
|
|
114
|
-
tags: ['nice', 'developer']
|
|
144
|
+
tags: ['nice', 'developer'],
|
|
145
|
+
formula: '=price*qty'
|
|
115
146
|
}, {
|
|
116
147
|
key: '2',
|
|
117
148
|
name: 'Jim Green',
|
|
118
149
|
age: 42,
|
|
119
150
|
address: 'London No. 1 Lake Park',
|
|
120
|
-
tags: ['loser']
|
|
151
|
+
tags: ['loser'],
|
|
152
|
+
formula: '=price+discount'
|
|
121
153
|
}, {
|
|
122
154
|
key: '3',
|
|
123
155
|
name: 'Joe Black',
|
|
124
156
|
age: 32,
|
|
125
157
|
address: 'Sidney No. 1 Lake Park',
|
|
126
|
-
tags: ['cool', 'teacher']
|
|
158
|
+
tags: ['cool', 'teacher'],
|
|
159
|
+
formula: '=123* 4569797 * discount*123* 4569797 * discount*123* 4569797 * discount*123* 4569797 * discount*123* 4569797 * discount*123* 4569797 * discount*123* 4569797 * discount'
|
|
160
|
+
}, {
|
|
161
|
+
key: '4',
|
|
162
|
+
name: 'Joe ll',
|
|
163
|
+
age: 92,
|
|
164
|
+
address: 'Sidney No. 1 Lake Park',
|
|
165
|
+
tags: ['cool', 'teacher'],
|
|
166
|
+
formula: '=(123 + 456) * price'
|
|
167
|
+
}, {
|
|
168
|
+
key: '5',
|
|
169
|
+
name: 'Joe ll',
|
|
170
|
+
age: 37,
|
|
171
|
+
address: 'Sidney No. 1 Lake Park',
|
|
172
|
+
tags: ['cool', 'teacher'],
|
|
173
|
+
formula: '=(123 + 456) * price + 888'
|
|
127
174
|
}];
|
|
128
175
|
var App = function App() {
|
|
129
176
|
var _useState = useState(data),
|
package/dist/example/index.less
CHANGED