cloud-web-corejs 1.0.54-dev.389 → 1.0.54-dev.390

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cloud-web-corejs",
3
3
  "private": false,
4
- "version": "1.0.54-dev.389",
4
+ "version": "1.0.54-dev.390",
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
7
7
  "lint": "eslint --ext .js,.vue src",
@@ -0,0 +1,962 @@
1
+ <template>
2
+ <el-dialog
3
+ :visible.sync="formulaDialogVisible"
4
+ :title="i18nt('designer.hint.formulaSetting')"
5
+ custom-class="dialog-style list-dialog"
6
+ :close-on-click-modal="false"
7
+ :close-on-press-escape="false"
8
+ :destroy-on-close="true"
9
+ :append-to-body="true"
10
+ width="70%"
11
+ top="0px"
12
+ ref="colFormulaDialog"
13
+ @close="dialogClose"
14
+ >
15
+ <div class="cont">
16
+ <el-row>
17
+ <el-col :span="24">
18
+ <div class="editor">
19
+ <div class="editor-top">
20
+ <el-row>
21
+ <el-col :span="22">
22
+ <div style="font-weight: bold">value =</div>
23
+ </el-col>
24
+ <!-- el-tag 模式 按钮 end -->
25
+ <el-col :span="2">
26
+ <el-button size="small" @click="clearFormula" type="danger" plain>
27
+ {{ i18nt("designer.hint.formulaClear") }}
28
+ </el-button>
29
+ </el-col>
30
+ </el-row>
31
+ <div ref="cmRef" style="height: 83px; width: 100%"></div>
32
+ </div>
33
+ <!-- -->
34
+ <div class="editor-bottom">
35
+ <el-button
36
+ v-on:click="insertSymbol(item)"
37
+ size="default"
38
+ v-for="(item, idx) in operate"
39
+ :key="idx"
40
+ >
41
+ {{ item }}
42
+ </el-button>
43
+ </div>
44
+ <!-- -->
45
+ </div>
46
+ </el-col>
47
+ </el-row>
48
+ <el-row style="margin: 10px">
49
+ <el-col :span="6">
50
+ <div class="group-item-left">
51
+ <div class="item-header">
52
+ {{ i18nt("designer.hint.formulaWidgetList") }}
53
+ </div>
54
+ <el-input
55
+ :placeholder="i18nt('designer.hint.formulaSearch')"
56
+ v-model="filterText"
57
+ clearable
58
+ ></el-input>
59
+ <div class="item-body-left">
60
+ <el-tree
61
+ ref="fieldTree"
62
+ :data="fieldTreeData"
63
+ :filter-node-method="filterNode"
64
+ @node-click="insertField"
65
+ >
66
+ <template #default="{ node, data }">
67
+ <span class="custom-tree-node">
68
+ <el-tooltip effect="dark" :content="node.label" placement="right">
69
+ <span>{{ node.label }}</span>
70
+ </el-tooltip>
71
+ </span>
72
+ </template>
73
+ </el-tree>
74
+ </div>
75
+ </div>
76
+ </el-col>
77
+ <el-col :span="6">
78
+ <el-row>
79
+ <el-col :span="24">
80
+ <div class="group-item-right-top">
81
+ <div class="item-header">
82
+ {{ i18nt("designer.hint.formulaFunctionList") }}
83
+ </div>
84
+ <div class="function-list">
85
+ <el-collapse v-model="funcActiveCollapseNames">
86
+ <template v-for="(item, index) in funcList">
87
+ <el-collapse-item
88
+ :key="index"
89
+ :title="i18nt(item.fClass)"
90
+ :name="index"
91
+ v-if="index < 2"
92
+ >
93
+ <div
94
+ v-for="(info, i) in item.flist"
95
+ :key="i"
96
+ class="field-item"
97
+ @click="insertFunction(info.fName + '(')"
98
+ @mouseenter="
99
+ showIntro(
100
+ i18nt(info.fName),
101
+ i18nt(item.fClass),
102
+ i18nt(info.fIntro)
103
+ )
104
+ "
105
+ v-on:mouseleave="resetIntro"
106
+ >
107
+ <span>{{ info.fName }}</span>
108
+ <el-tag :type="getClass(info.fType)"
109
+ >{{ i18nt(info.fType) }}
110
+ </el-tag>
111
+ </div>
112
+ </el-collapse-item>
113
+ </template>
114
+ </el-collapse>
115
+ </div>
116
+ </div>
117
+ </el-col>
118
+ </el-row>
119
+ </el-col>
120
+ <el-col :span="12">
121
+ <div class="group-item-right-bottom">
122
+ <div class="item-header">{{ introTitle }}</div>
123
+ <div class="item-body-right-bottom">
124
+ <ul>
125
+ <li
126
+ v-if="introduction.title !== ''"
127
+ style="font-size: 16px; color: #0a5d7c"
128
+ >
129
+ {{ introduction.title }}
130
+ </li>
131
+ <li>
132
+ <div class="intro-content" v-html="introduction.content"></div>
133
+ </li>
134
+ </ul>
135
+ </div>
136
+ </div>
137
+ </el-col>
138
+ </el-row>
139
+ </div>
140
+ <div class="dialog-footer" slot="footer">
141
+ <el-button
142
+ @click="formulaDialogVisible = false"
143
+ class="button-sty"
144
+ icon="el-icon-close"
145
+ >
146
+ {{ i18nt("designer.hint.cancel") }}
147
+ </el-button>
148
+ <el-button
149
+ type="primary"
150
+ @click="saveFormula"
151
+ class="button-sty"
152
+ icon="el-icon-check"
153
+ >
154
+ {{ i18nt("designer.hint.confirm") }}
155
+ </el-button>
156
+ </div>
157
+ </el-dialog>
158
+ </template>
159
+
160
+ <script>
161
+ import { basicSetup, EditorView } from "codemirror";
162
+ import { javascript } from "@codemirror/lang-javascript";
163
+ import { EditorState } from "@codemirror/state";
164
+ import i18n from "@base/components/xform/utils/i18n";
165
+ import {
166
+ deepClone,
167
+ getAllContainerWidgets,
168
+ getAllFieldWidgets,
169
+ getFieldWidgetById,
170
+ traverseFieldWidgetsOfContainer,
171
+ loopHandleWidget,
172
+ traverseAllWidgetsNew,
173
+ } from "@base/components/xform/utils/util";
174
+ import {
175
+ placeholders,
176
+ baseTheme,
177
+ formulas,
178
+ FORMULA_REG_EXP,
179
+ } from "@base/components/xform/utils/formula-util";
180
+
181
+ export default {
182
+ name: "formula-editor",
183
+ mixins: [i18n],
184
+ components: {},
185
+ props: {
186
+ option: Object,
187
+ },
188
+ computed: {
189
+ formulaForView() {
190
+ const matchResult = this.formula.match(FORMULA_REG_EXP);
191
+ if (!matchResult) {
192
+ return this.formula;
193
+ }
194
+
195
+ let resultFormula = this.formula;
196
+ matchResult.forEach((mi) => {
197
+ const secondPart = mi.split(".")[1];
198
+ resultFormula = resultFormula.replaceAll(mi, secondPart);
199
+ });
200
+
201
+ return resultFormula;
202
+ },
203
+ },
204
+ watch: {
205
+ filterText(val) {
206
+ this.$refs.fieldTree.filter(val);
207
+ },
208
+ },
209
+ data() {
210
+ return {
211
+ codeMirror: null,
212
+ formula: "",
213
+ tags: [], // 公式页签集合
214
+ fieldTreeData: [], // 设计器字段树
215
+ filterText: "",
216
+ formulaDialogVisible: true,
217
+ operate: ["+", "-", "*", "/", "!=", "==", "<", ">", "<=", ">=", "(", ")", ","],
218
+ insertNum: 0,
219
+ insertStr: "",
220
+ activeNames: ["1"],
221
+ widgetSizes: [
222
+ {
223
+ label: this.i18nt("designer.hint.formulaSizeLarge"),
224
+ value: "large",
225
+ },
226
+ {
227
+ label: this.i18nt("designer.hint.formulaSizeMedium"),
228
+ value: "default",
229
+ },
230
+ {
231
+ label: this.i18nt("designer.hint.formulaSizeSmall"),
232
+ value: "small",
233
+ },
234
+ {
235
+ label: this.i18nt("designer.hint.formulaSizeMini"),
236
+ value: "small",
237
+ },
238
+ ],
239
+ introTitle: this.i18nt("designer.hint.formulaFunctionExplain"),
240
+ introduction: {
241
+ title: this.i18nt("designer.hint.formulaPleaseSelect"),
242
+ content:
243
+ '<span class="cg">' +
244
+ this.i18nt("designer.hint.formulaSample") +
245
+ ':</span><span class="fname">SUM</span><span class="cg">(</span><span class="cs">' +
246
+ this.i18nt("designer.hint.formulaPara") +
247
+ '1</span><span class="cg">,</span><span class="cs">' +
248
+ this.i18nt("designer.hint.formulaPara") +
249
+ '2</span><span class="cg">)</span>',
250
+ },
251
+ funcList: formulas,
252
+ funcActiveCollapseNames: [0],
253
+
254
+ targetFormTemplate: null,
255
+ targetFormJson: null,
256
+ };
257
+ },
258
+ created() {
259
+ this.editFormula();
260
+ },
261
+ mounted() {},
262
+ methods: {
263
+ dialogClose() {
264
+ this.formulaDialogVisible = false;
265
+ this.$emit("update:visiable", false);
266
+ },
267
+ clearFormula(event) {
268
+ this.formula = ""; //CodeMirror 模式
269
+ this.tags = []; //el-tag模式
270
+ this.codeMirror.dispatch({
271
+ changes: { from: 0, to: this.codeMirror.state.doc.length, insert: "" },
272
+ });
273
+ },
274
+
275
+ /** 删除字符串str中的第n个subStr
276
+ * @param {Object} str
277
+ * @param {Object} subStr
278
+ * @param {Object} n
279
+ */
280
+ deleteChar(str, subStr, n) {
281
+ let num = -1;
282
+ return str.replace(/a/g, (item) => {
283
+ num++;
284
+ return num === n ? "" : item;
285
+ });
286
+ },
287
+
288
+ filterNode(value, data) {
289
+ if (!value) return true;
290
+ return data.label.indexOf(value) !== -1;
291
+ },
292
+ handleTableConfigData(widget, callback) {
293
+ callback(widget);
294
+ },
295
+ initFields() {
296
+ let option = this.option;
297
+ let formCode = option.formCode;
298
+ if (formCode) {
299
+ this.getReportTemplate(formCode, () => {
300
+ this.loadFieldListToTree();
301
+ });
302
+ }
303
+ },
304
+ initHandleFields() {
305
+ let option = this.option;
306
+ let formWidgetNames = option.formWidgetNames || [];
307
+ let itemWidgets = option.itemWidgets || [];
308
+ let tableWidgetNames = itemWidgets.map((item) => item.widgetName);
309
+
310
+ let tableWidgetMap0 = itemWidgets.map((item) => {
311
+ return {
312
+ [item.widgetName]: item.columnWidgetNames,
313
+ };
314
+ });
315
+
316
+ let formWidgetMap = {};
317
+ let tableWidgetMap = itemWidgets.map((item) => {
318
+ let columnWidgetMap = {};
319
+ item.columnWidgetNames.forEach((columnWidgetName) => {
320
+ return (columnWidgetMap[columnWidgetName] = null);
321
+ });
322
+ return {
323
+ [item.widgetName]: {
324
+ tableWidget: null,
325
+ columnWidgetMap,
326
+ },
327
+ };
328
+ });
329
+
330
+ traverseAllWidgetsNew(this.targetFormJson.widgetList, (widget, pWidget) => {
331
+ if (pWidget && pWidget.type === "data-table") {
332
+ if (tableWidgetNames.includes(pWidget.options.name)) {
333
+ let tableItems = tableWidgetMap0[pWidget.options.name];
334
+ if (
335
+ widget.formItemFlag &&
336
+ widget.options.label &&
337
+ tableItems.includes(widget.options.label)
338
+ ) {
339
+ tableWidgetMap[pWidget.options.name].columnWidgetMap[
340
+ widget.options.label
341
+ ] = widget;
342
+ }
343
+ tableWidgetMap[pWidget.options.name].tableWidget = widget;
344
+ }
345
+ formWidgetNames.push(widget.widgetName);
346
+ itemWidgets.push(widget);
347
+ } else if (
348
+ widget.formItemFlag &&
349
+ widget.options.label &&
350
+ formWidgetNames.includes(widget.options.label)
351
+ ) {
352
+ formWidgetMap[widget.options.label] = widget;
353
+ }
354
+ });
355
+ },
356
+ async getReportTemplate(formCode, callback) {
357
+ let url, data;
358
+ url = USER_PREFIX + `/formTemplate/getByFormCode`;
359
+ data = { stringOne: formCode };
360
+ await this.$http({
361
+ // aes: true,
362
+ url: url,
363
+ method: `post`,
364
+ data: data,
365
+ isLoading: true,
366
+ // loadingTarget: document.body,
367
+ // modalStrictly: true,
368
+ success: async (res) => {
369
+ let formTemplate = res.objx || {};
370
+ this.targetFormTemplate = formTemplate;
371
+ this.targetFormJson = formTemplate.formViewContent
372
+ ? JSON.parse(formTemplate.formViewContent)
373
+ : {};
374
+ callback && callback();
375
+ },
376
+ });
377
+ },
378
+ getTargetWidgetList() {
379
+ let widgetList = this.targetFormJson.widgetList;
380
+ return widgetList;
381
+ },
382
+ loadFieldListToTree() {
383
+ let option = this.option;
384
+ let formWidgetNames = option.formWidgetNames || [];
385
+ let itemWidgets = option.itemWidgets || [];
386
+ let tableWidgetNames = itemWidgets.map((item) => item.widgetName);
387
+ let tableWidgetMap = {};
388
+ itemWidgets.forEach((item) => {
389
+ tableWidgetMap[item.widgetName] = item.columnWidgetNames;
390
+ });
391
+
392
+ this.fieldTreeData.length = 0; //先清空
393
+
394
+ let widgetList = this.getTargetWidgetList();
395
+
396
+ const allFields = getAllFieldWidgets(widgetList);
397
+ const allContainers = getAllContainerWidgets(widgetList);
398
+
399
+ const subFormArray = [];
400
+ let sfFieldArray = [];
401
+ const subFormFieldMap = {};
402
+
403
+ //获取子表单容器内部的字段
404
+ allContainers.forEach((con) => {
405
+ if (con.type === "data-table") {
406
+ if (tableWidgetNames.includes(con.container.options.name)) {
407
+ subFormArray.push(con.container);
408
+ const tmpFieldArray = [];
409
+ const fwHandler = (fw) => {
410
+ /* if (!!fw.formItemFlag && fw.type === "number") {
411
+ tmpFieldArray.push(fw);
412
+ } */
413
+ if (tableWidgetMap[con.container.options.name]?.includes(fw.options.name)) {
414
+ tmpFieldArray.push(fw);
415
+ }
416
+ };
417
+
418
+ // this.traverseFieldWidgetsOfTableDataWidget(con.container, fwHandler);
419
+ traverseFieldWidgetsOfContainer(con.container, fwHandler);
420
+ subFormFieldMap[con.container.options.name] = tmpFieldArray;
421
+ sfFieldArray = sfFieldArray.concat(tmpFieldArray);
422
+ }
423
+ }
424
+ });
425
+
426
+ //加载到树形组件数据对象
427
+ allFields.forEach((fld) => {
428
+ let flag1 = !sfFieldArray.find((item) => item.id === fld.field.id);
429
+ let flag2 =
430
+ fld.field.options.label && formWidgetNames.includes(fld.field.options.name);
431
+ let flag = flag2;
432
+ if (flag) {
433
+ //排除子表单字段
434
+ const fieldNode = {
435
+ id: fld.field.id,
436
+ name: fld.field.options.name,
437
+ label: fld.field.options.label,
438
+ type: fld.field.type,
439
+ formItemFlag: true,
440
+ };
441
+ this.fieldTreeData.push(fieldNode);
442
+ }
443
+ });
444
+
445
+ subFormArray.forEach((sf) => {
446
+ const subFormNode = {
447
+ id: sf.id,
448
+ name: sf.options.name,
449
+ label: sf.options.label || sf.options.name,
450
+ type: sf.type,
451
+ formItemFlag: false,
452
+ children: [],
453
+ };
454
+
455
+ subFormFieldMap[sf.options.name].forEach((fld) => {
456
+ const fieldNode = {
457
+ id: fld.id,
458
+ name: fld.options.name,
459
+ label: fld.options.label,
460
+ type: fld.type,
461
+ formItemFlag: true,
462
+ };
463
+ subFormNode.children.push(fieldNode);
464
+ });
465
+
466
+ this.fieldTreeData.push(subFormNode);
467
+ });
468
+ },
469
+
470
+ // 插入字段
471
+ insertField(obj, node, self) {
472
+ if (!!obj.formItemFlag) {
473
+ let fieldId = obj.id + "";
474
+ let fieldLabel = "[" + obj.label + "]";
475
+ this.updateCodeMirror(fieldId, fieldLabel, "field");
476
+ }
477
+ },
478
+
479
+ // 插入符号
480
+ insertSymbol(opt) {
481
+ this.updateCodeMirror(opt, opt, null);
482
+ },
483
+
484
+ // 插入函数
485
+ insertFunction(opt) {
486
+ const val = opt.substring(0, opt.length - 1);
487
+ this.updateCodeMirror(val, val, "func");
488
+ },
489
+
490
+ updateCodeMirror(field, text, type = null) {
491
+ if (type) {
492
+ let obj = {
493
+ field: field,
494
+ text: text,
495
+ type: type,
496
+ };
497
+ let selectionLet = obj.field.length + obj.text.length + obj.type.length; //光标位置;
498
+ let code = `{{${obj.field}.${obj.text}.${obj.type}}}`;
499
+ if (type === "func") {
500
+ code += "()";
501
+ selectionLet = selectionLet + 7;
502
+ } else {
503
+ selectionLet = selectionLet + 6;
504
+ }
505
+
506
+ if (code) {
507
+ this.codeMirror.dispatch({
508
+ changes: {
509
+ from: this.codeMirror.state.selection.main.head,
510
+ to: this.codeMirror.state.selection.main.head,
511
+ insert: code,
512
+ },
513
+ selection: {
514
+ anchor: this.codeMirror.state.selection.main.head + selectionLet,
515
+ },
516
+ });
517
+ }
518
+ } else {
519
+ this.codeMirror.dispatch({
520
+ changes: {
521
+ from: this.codeMirror.state.selection.main.head,
522
+ to: this.codeMirror.state.selection.main.head,
523
+ insert: text,
524
+ },
525
+ selection: {
526
+ anchor: this.codeMirror.state.selection.main.head + text.length,
527
+ },
528
+ });
529
+ }
530
+ },
531
+
532
+ // 在字符串中查找[开始]结尾的字符串,并删除
533
+ removeStr(str) {
534
+ let a = str.indexOf("[");
535
+ if (a === -1) {
536
+ return str;
537
+ }
538
+ let b = str.indexOf("]", a) + 1;
539
+ let c = str.substring(a, b);
540
+ let strArr = str.split(c);
541
+ let newStr = "";
542
+ for (let i = 0; i < strArr.length; i++) {
543
+ newStr += strArr[i];
544
+ }
545
+ return this.removeStr(newStr);
546
+ },
547
+ extractFieldNames(formula) {
548
+ if (!formula) return [];
549
+ const fieldArray = [];
550
+ let tempFormula = formula;
551
+
552
+ // 循环查找所有 [字段名] 格式的引用
553
+ while (true) {
554
+ const startIndex = tempFormula.indexOf("[");
555
+ if (startIndex === -1) {
556
+ break; // 没有更多字段引用了
557
+ }
558
+
559
+ const endIndex = tempFormula.indexOf("]", startIndex);
560
+ if (endIndex === -1) {
561
+ break; // 格式不正确,没有匹配的右括号
562
+ }
563
+
564
+ // 提取字段名(不包含方括号)
565
+ const fieldName = tempFormula.substring(startIndex + 1, endIndex);
566
+
567
+ // 避免重复添加相同的字段名
568
+ if (!fieldArray.includes(fieldName)) {
569
+ fieldArray.push(fieldName);
570
+ }
571
+
572
+ // 从剩余部分继续查找
573
+ tempFormula = tempFormula.substring(endIndex + 1);
574
+ }
575
+
576
+ return fieldArray;
577
+ },
578
+ /**
579
+ * 字段label可能在公式保存后再次被修改,当编辑公式时需要再次刷新公式中的字段label(不刷新也不会影响公式计算结果)
580
+ */
581
+ refreshFormula() {
582
+ const matchResult = this.option.formula?.match(FORMULA_REG_EXP);
583
+ if (!matchResult) {
584
+ return this.option.formula;
585
+ }
586
+
587
+ matchResult.forEach((mi) => {
588
+ const firstPart = mi.split(".")[0];
589
+ const secondPart = mi.split(".")[1];
590
+ const thirdPart = mi.split(".")[2];
591
+ const nodeType = thirdPart.substring(0, thirdPart.length - 2);
592
+ if (nodeType === "func") {
593
+ return;
594
+ }
595
+
596
+ const fieldId = firstPart.substring(2, firstPart.length);
597
+ const fieldSchema = getFieldWidgetById(
598
+ // this.designer.widgetList,
599
+ this.getTargetWidgetList(),
600
+ fieldId,
601
+ false
602
+ );
603
+ if (!!fieldSchema) {
604
+ const newLabel = fieldSchema.options.label || fieldSchema.options.name;
605
+ this.option.formula = this.option.formula.replace(
606
+ mi,
607
+ firstPart + ".[" + newLabel + "]." + thirdPart
608
+ );
609
+ } else {
610
+ this.$message.error(
611
+ this.i18nt("designer.hint.deletedFieldInFormula") + secondPart
612
+ );
613
+ }
614
+ });
615
+ },
616
+
617
+ // 打开编辑公式弹窗
618
+ editFormula() {
619
+ this.fieldTreeData.length = 0;
620
+ // 初始化字段树
621
+
622
+ // this.loadFieldListToTree();
623
+ this.initFields();
624
+
625
+ console.log("设计器字段===>", this.fieldTreeData);
626
+
627
+ // 加载当前字段计算公式tags
628
+ this.refreshFormula();
629
+ const code = this.formula;
630
+ this.formulaDialogVisible = true;
631
+
632
+ //==== codeMirror 挂载视图 ====
633
+ this.$nextTick(() => {
634
+ this.codeMirror = new EditorView({
635
+ state: EditorState.create({
636
+ doc: code,
637
+ extensions: [basicSetup, javascript(), [baseTheme, [], placeholders]],
638
+ }),
639
+ parent: this.$refs.cmRef,
640
+ });
641
+ console.log("编辑器实例==>", this.codeMirror);
642
+ });
643
+ },
644
+
645
+ // 保存计算公式
646
+ getFormulaForView(formula) {
647
+ const matchResult = formula?.match(FORMULA_REG_EXP);
648
+ if (!matchResult) {
649
+ return {
650
+ formula: formula,
651
+ showFormula: formula,
652
+ };
653
+ }
654
+
655
+ return {
656
+ showFormula: this.formulaForView,
657
+ formula: formula,
658
+ };
659
+ },
660
+ saveFormula() {
661
+ this.formula = this.codeMirror.state.doc.text.join("");
662
+ let resultObj = this.getFormulaForView(this.formula);
663
+ this.option.confirm && this.option.confirm(resultObj);
664
+ this.dialogClose();
665
+ },
666
+ getClass(type) {
667
+ if (type === this.i18nt("designer.hint.formulaNumber")) {
668
+ return "warning";
669
+ }
670
+ if (type === this.i18nt("designer.hint.formulaChar")) {
671
+ return "";
672
+ }
673
+ if (type === this.i18nt("designer.hint.formulaObject")) {
674
+ return "danger";
675
+ }
676
+ },
677
+
678
+ resetIntro() {
679
+ this.introTitle = this.i18nt("designer.hint.formulaFunctionExplain");
680
+ this.introduction = {
681
+ title: this.i18nt("designer.hint.formulaPleaseSelect"),
682
+ content:
683
+ '<span class="cg">' +
684
+ this.i18nt("designer.hint.formulaSample") +
685
+ ':</span><span class="fname">SUM</span><span class="cg">(</span><span class="cs">参数1</span><span class="cg">,</span><span class="cs">参数2</span><span class="cg">)</span>',
686
+ };
687
+ },
688
+
689
+ showIntro(name, title, content) {
690
+ content = '<span class="cg">' + content + "</span>";
691
+ this.introduction = {
692
+ title: title,
693
+ content: content,
694
+ };
695
+ this.introTitle = name;
696
+ },
697
+
698
+ /**
699
+ * 校验计算公式是否正确
700
+ * @param s
701
+ * @returns {boolean}
702
+ */
703
+ isValid(s) {
704
+ let a = []; //存储左括号出现的地方
705
+ let l = s.length;
706
+ let k = 0;
707
+ let flag = 1;
708
+ let j;
709
+ for (let i = 0; i < l && flag; i++) {
710
+ switch (s[i]) {
711
+ case "(":
712
+ a[k] = i;
713
+ k++;
714
+ break;
715
+ case ")":
716
+ j = a[k - 1];
717
+ if (s[j] === "(") {
718
+ a[k] = 0;
719
+ k--;
720
+ } else {
721
+ flag = 0;
722
+ }
723
+ break;
724
+ case "{":
725
+ a[k] = i;
726
+ k++;
727
+ break;
728
+ case "}":
729
+ j = a[k - 1];
730
+ if (s[j] === "{") {
731
+ a[k] = 0;
732
+ k--;
733
+ } else {
734
+ flag = 0;
735
+ }
736
+ break;
737
+ case "[":
738
+ a[k] = i;
739
+ k++;
740
+ break;
741
+ case "]":
742
+ j = a[k - 1];
743
+ if (s[j] === "[") {
744
+ a[k] = 0;
745
+ k--;
746
+ } else {
747
+ flag = 0;
748
+ }
749
+ break;
750
+ }
751
+ }
752
+ if (k !== 0) {
753
+ flag = 0;
754
+ }
755
+ return flag !== 0;
756
+ },
757
+ },
758
+ };
759
+ </script>
760
+
761
+ <style lang="scss" scoped>
762
+ :deep(.cm-editor) {
763
+ height: 100%;
764
+ }
765
+
766
+ li {
767
+ list-style: none;
768
+ }
769
+
770
+ /*去掉li前面的点*/
771
+ .el-input-group {
772
+ cursor: pointer;
773
+ }
774
+
775
+ .header {
776
+ width: 97%;
777
+ border: 1px solid #ccc;
778
+ border-top-left-radius: 10px;
779
+ border-top-right-radius: 10px;
780
+ height: 31px;
781
+ line-height: 31px;
782
+ padding-left: 15px;
783
+ }
784
+
785
+ .editor {
786
+ margin-left: 10px;
787
+ margin-right: 10px;
788
+ height: 200px;
789
+ border: 1px solid #ccc;
790
+ border-radius: 6px;
791
+ }
792
+
793
+ .editor-top {
794
+ //margin-left: 10px;
795
+ height: 130px;
796
+ width: 100%;
797
+ padding: 8px;
798
+ position: relative;
799
+ overflow-x: hidden;
800
+ overflow-y: scroll;
801
+ }
802
+
803
+ .editor-bottom {
804
+ border-left: 1px solid #ccc;
805
+ display: flex;
806
+ flex-wrap: wrap;
807
+ padding: 5px;
808
+ align-content: flex-start;
809
+ }
810
+
811
+ .body-right-button {
812
+ width: 60px;
813
+ height: 40px;
814
+ }
815
+
816
+ .group-form {
817
+ margin-top: 15px;
818
+ display: flex;
819
+ justify-content: space-between;
820
+ height: 350px;
821
+ }
822
+
823
+ .group-item-left {
824
+ height: 350px;
825
+ border: 1px solid #ccc;
826
+ border-top-left-radius: 6px;
827
+ border-bottom-left-radius: 6px;
828
+ margin-bottom: 5px;
829
+ padding: 0;
830
+ width: 100%;
831
+ }
832
+
833
+ .group-item-right-top {
834
+ height: 350px;
835
+ border: 1px solid #ccc;
836
+ border-radius: 0;
837
+ margin-bottom: 5px;
838
+ width: 100%;
839
+ }
840
+
841
+ .group-item-right-bottom {
842
+ height: 350px;
843
+ border: 1px solid #ccc;
844
+ border-top-right-radius: 6px;
845
+ border-bottom-right-radius: 6px;
846
+ margin-bottom: 5px;
847
+ width: 100%;
848
+ }
849
+
850
+ .item-header {
851
+ border-bottom: 1px solid #ccc;
852
+ height: 29px;
853
+ line-height: 29px;
854
+ padding-left: 15px;
855
+ font-weight: bold;
856
+ }
857
+
858
+ .item-body-left {
859
+ height: 320px;
860
+ overflow-y: auto;
861
+ }
862
+
863
+ .function-list {
864
+ height: 320px;
865
+ overflow-y: auto;
866
+
867
+ :deep(.el-collapse-item__header) {
868
+ font-weight: normal !important;
869
+ }
870
+ }
871
+
872
+ .item-body-right-bottom {
873
+ height: 152px;
874
+ overflow-y: auto;
875
+ }
876
+
877
+ .el-collapse {
878
+ border: none;
879
+ }
880
+
881
+ :deep(.el-dialog) {
882
+ margin-top: 10px !important;
883
+ }
884
+
885
+ :deep(.el-collapse-item__header) {
886
+ padding-left: 10px;
887
+ border: none;
888
+ }
889
+
890
+ :deep(.el-collapse-item__wrap) {
891
+ border: none;
892
+ }
893
+
894
+ :deep(.el-collapse-item__arrow) {
895
+ margin-left: 8px;
896
+ }
897
+
898
+ .field-item {
899
+ display: flex;
900
+ justify-content: space-between;
901
+ align-items: center;
902
+ height: 32px;
903
+ padding-left: 30px;
904
+ padding-right: 15px;
905
+ cursor: pointer;
906
+ }
907
+
908
+ .field-item:hover {
909
+ background-color: #f8f8f8;
910
+ }
911
+
912
+ p::before {
913
+ content: "● ";
914
+ color: #0a5d7c;
915
+ }
916
+
917
+ p {
918
+ height: 24px;
919
+ line-height: 24px;
920
+ padding: 0 15px;
921
+ font-size: 16px;
922
+ color: #0a5d7c;
923
+ }
924
+
925
+ .intro-content {
926
+ padding-left: 30px;
927
+ }
928
+
929
+ .cg {
930
+ color: #0a5d7c;
931
+ }
932
+
933
+ .fname {
934
+ display: inline-block;
935
+ border-radius: 2px;
936
+ padding: 0 5px;
937
+ margin: 1px;
938
+ font-size: 12px;
939
+ line-height: 20px;
940
+ color: #708;
941
+ background: #fff;
942
+ }
943
+
944
+ .cs {
945
+ display: inline-block;
946
+ border-radius: 2px;
947
+ padding: 0 5px;
948
+ margin: 1px;
949
+ color: #fff;
950
+ font-size: 12px;
951
+ line-height: 20px;
952
+ background: #178cdf;
953
+ }
954
+
955
+ :deep(.el-dialog__body) {
956
+ padding: 0;
957
+ }
958
+
959
+ .small-padding-dialog {
960
+ /* margin-top: 0px; */
961
+ }
962
+ </style>
@@ -295,7 +295,7 @@ modules = {
295
295
  if (searchDialogConfig.valueSourceField) valueSourceField = searchDialogConfig.valueSourceField
296
296
  if (searchDialogConfig.labelSourceField) labelSourceField = searchDialogConfig.labelSourceField
297
297
  }
298
- this.setValue(userInfo[valueSourceField] ?? null);
298
+ this.initValue(userInfo[valueSourceField] ?? null);
299
299
  this.setShowValue(userInfo[labelSourceField] ?? null);
300
300
  } else if (this.field.options.saleOrgDefaultVabSearch) {
301
301
  let saleOrgDTO = this.getFormRef().getDefaultSaleOrgDTO();
@@ -306,7 +306,7 @@ modules = {
306
306
  if (searchDialogConfig.valueSourceField) valueSourceField = searchDialogConfig.valueSourceField
307
307
  if (searchDialogConfig.labelSourceField) labelSourceField = searchDialogConfig.labelSourceField
308
308
  }
309
- this.setValue(saleOrgDTO[valueSourceField] ?? null);
309
+ this.initValue(saleOrgDTO[valueSourceField] ?? null);
310
310
  this.setShowValue(saleOrgDTO[labelSourceField] ?? null);
311
311
  }
312
312
  }
@@ -314,12 +314,12 @@ modules = {
314
314
  if (!this.tableParam) {
315
315
  //主表
316
316
  if (this.isNotNullVal(defaultValue)) {
317
- this.setValue(defaultValue);
317
+ this.initValue(defaultValue);
318
318
  }
319
319
  } else {
320
320
  //明细
321
321
  if (!this.tableParam.row.id && this.isNotNullVal(defaultValue)) {
322
- this.setValue(defaultValue);
322
+ this.initValue(defaultValue);
323
323
  }
324
324
  }
325
325
  } else {
@@ -329,7 +329,7 @@ modules = {
329
329
  } else {
330
330
  //明细
331
331
  if (!this.tableParam.row.id && this.isNotNullVal(defaultValue)) {
332
- this.setValue(defaultValue);
332
+ this.initValue(defaultValue);
333
333
  }
334
334
  }
335
335
  }
@@ -1341,6 +1341,19 @@ modules = {
1341
1341
  getFieldEditor: function () {
1342
1342
  return this.$refs["fieldEditor"];
1343
1343
  },
1344
+ initValue: function (e) {
1345
+ let value = e ?? null;
1346
+ let currentData =
1347
+ this.tableParam && this.tableParam.row
1348
+ ? this.tableParam.row
1349
+ : this.formModel;
1350
+ if (void 0 === currentData[this.fieldKeyName]) {
1351
+ this.$set(currentData, this.fieldKeyName, null);
1352
+ }
1353
+ this.fieldModel = value;
1354
+ this.initFileList();
1355
+ this.syncUpdateFormModel(value);
1356
+ },
1344
1357
  setValue: function (e) {
1345
1358
  if (this.field.formItemFlag) {
1346
1359
  let value = e ?? null;
@@ -90,6 +90,11 @@
90
90
  :visiable.sync="formulaDialogVisible"
91
91
  :option="formulaDialogOption"
92
92
  ></formulaDialog>
93
+ <baseFormulaDialog
94
+ v-if="baseFormulaDialogVisible"
95
+ :visiable.sync="baseFormulaDialogVisible"
96
+ :option="baseFormulaDialogOption"
97
+ ></baseFormulaDialog>
93
98
  </div>
94
99
  </template>
95
100
 
@@ -41,6 +41,7 @@ import '@base/components/xform/utils/directive'
41
41
  import html2Canvas from 'html2canvas'
42
42
  import JsPDF from 'jspdf'
43
43
  import formulaDialog from '@base/components/xform/form-designer/form-widget/dialog/formulaDialog.vue'
44
+ import baseFormulaDialog from '@base/components/xform/form-designer/form-widget/dialog/baseFormulaDialog.vue'
44
45
 
45
46
  let modules = {};
46
47
  const baseRefUtil = {
@@ -69,7 +70,8 @@ const baseRefUtil = {
69
70
  modules = {
70
71
  componentName: 'VFormRender',
71
72
  components: {
72
- formulaDialog
73
+ formulaDialog,
74
+ baseFormulaDialog
73
75
  },
74
76
  mixins: [baseRefUtil.emitter, baseRefUtil.i18n, scriptHttpMixin, defaultHandleMixin],
75
77
  props: {
@@ -203,7 +205,9 @@ modules = {
203
205
  showFileReferenceDialog:false,
204
206
 
205
207
  formulaDialogOption:null,
206
- formulaDialogVisible:false
208
+ formulaDialogVisible:false,
209
+ baseFormulaDialogOption:null,
210
+ baseFormulaDialogVisible:false
207
211
  };
208
212
  },
209
213
  computed: {
@@ -3186,6 +3190,10 @@ let dom4 = clonedElement.querySelector(".designer-view")
3186
3190
  openFormulaDialog(option) {
3187
3191
  this.formulaDialogOption = option
3188
3192
  this.formulaDialogVisible = true;
3193
+ },
3194
+ openBaseFormulaDialog(option) {
3195
+ this.baseFormulaDialogOption = option
3196
+ this.baseFormulaDialogVisible = true;
3189
3197
  }
3190
3198
  }
3191
3199
  };
@@ -1,6 +1,7 @@
1
1
  import dayjs from "dayjs";
2
2
  import {
3
- calculateFormula2
3
+ calculateFormula2,
4
+ baseCalculateFormula
4
5
  } from '@base/components/xform/utils/formula-util'
5
6
 
6
7
  let modules = {};
@@ -333,6 +334,9 @@ modules = {
333
334
  //2个数组的行号处理 end
334
335
  calculateFormula(formula,data){
335
336
  return calculateFormula2(formula, data, this)
337
+ },
338
+ baseCalculateFormula(formula){
339
+ return baseCalculateFormula(formula, this)
336
340
  }
337
341
 
338
342
  }
@@ -121,7 +121,122 @@ export function calculateFormula(VFR, DSV, formulaJs, formulaFieldRef, changedFi
121
121
  }
122
122
 
123
123
  const formulaValue = evalFn(formula, DSV, VFR, formulaJs)
124
- formulaFieldRef.setValue(formulaValue)
124
+ if(formulaFieldRef)formulaFieldRef.setValue(formulaValue)
125
+ return formulaValue
126
+ }
127
+
128
+ export function baseCalculateFormula(formulaStr, data, that /* VFR, DSV, formulaJs, formulaFieldRef, changedFieldRef */) {
129
+
130
+ if(!formulaStr)return
131
+ let formula = formulaStr;
132
+ let VFR = that.getFormRef();
133
+ let DSV = that.getGlobalDsv()
134
+ let formulaJs = formulajs
135
+ let formulaFieldRef = that;
136
+ if (formulaFieldRef.tableParam) {
137
+ } else if (!!formulaFieldRef.subFormItemFlag && !!changedFieldRef.subFormItemFlag) {
138
+ /* 子表单字段变化,只能触发子表单同一行字段的计算公式重新计算!! */
139
+ /* if (changedFieldRef.subFormRowId !== formulaFieldRef.subFormRowId) {
140
+ return
141
+ } */
142
+ }
143
+
144
+ formula = baseReplaceFieldsAndFunctionsOfFormula(VFR, formulaFieldRef,formula) //替换字段值
145
+ if (!formula) {
146
+ return
147
+ }
148
+
149
+ //替换formula-js函数
150
+ const matchResult = formula.match(/[A-Za-z]*/g)
151
+ let matchedList = []
152
+ if (!!matchResult) {
153
+ matchResult.forEach(mi => {
154
+ if (!!mi && (findCalFunStartIndex(mi) !== -1) && !matchedList.includes(mi)) {
155
+ const funcName = mi.toUpperCase()
156
+ formula = formula.replaceAll(mi, 'formulaJs.' + funcName)
157
+ matchedList.push(mi)
158
+ }
159
+ })
160
+ }
161
+
162
+ const formulaValue = evalFn(formula, DSV, VFR, formulaJs)
163
+ return formulaValue
164
+ }
165
+
166
+ /**
167
+ * 替换计算公式中的字段值
168
+ * @param VFR
169
+ * @param formulaFieldRef
170
+ * @returns {*}
171
+ */
172
+ export function baseReplaceFieldsAndFunctionsOfFormula(VFR, formulaFieldRef, formula) {
173
+ // let formula = formulaFieldRef.field.options.formula
174
+ const matchResult = formula.match(FORMULA_REG_EXP)
175
+ if (!matchResult) {
176
+ return formula
177
+ }
178
+
179
+ let resultFormula = formula
180
+ let quitFlag = false
181
+ matchResult.forEach(mi => {
182
+ const thirdPart = mi.split('.')[2]
183
+ const nodeType = thirdPart.substring(0, thirdPart.length - 2)
184
+ if (nodeType === 'func') {
185
+ const funcName = mi.split('.')[1]
186
+ resultFormula = resultFormula.replace(mi, funcName)
187
+ return
188
+ }
189
+
190
+ const firstPart = mi.split('.')[0]
191
+ const fieldId = firstPart.substring(2, firstPart.length)
192
+ const fieldSchema = getFieldWidgetById(VFR.formJsonObj.widgetList, fieldId, false)
193
+ if (!!fieldSchema) {
194
+ let fieldRef = VFR.getWidgetRef(fieldSchema.options.name)
195
+ if (!!fieldRef) {
196
+ //是否要考虑字符串值的替换??
197
+ resultFormula = resultFormula.replace(mi, fieldRef.getValue())
198
+ } else { //getWidgetRef找不到,则可能是子表单字段
199
+ const subFormNameOfField = VFR.getSubFormNameOfWidget(fieldSchema.options.name)
200
+ if (!!formulaFieldRef.subFormItemFlag || formulaFieldRef.tableParam) {
201
+ /* 如果当前计算字段是子表单字段,要判断公式中的子表单字段是否和当前计算字段是否属于同一子表单!! */
202
+
203
+
204
+ if (subFormNameOfField === formulaFieldRef?.parentWidget?.options?.name) {
205
+ let subFormRowId = formulaFieldRef.tableParam.row._X_ROW_KEY
206
+ fieldRef = VFR.getWidgetRef(fieldSchema.options.name + '_' + subFormRowId)
207
+ if (!!fieldRef) {
208
+ resultFormula = resultFormula.replaceAll(mi, fieldRef.getValue())
209
+ } else {
210
+ quitFlag = true
211
+ console.error('Field not found: ' + fieldSchema.options.label)
212
+ }
213
+ } else if (subFormNameOfField === formulaFieldRef.subFormName) {
214
+ fieldRef = VFR.getWidgetRef(fieldSchema.options.name + '@row' + formulaFieldRef.subFormRowId)
215
+ if (!!fieldRef) {
216
+ resultFormula = resultFormula.replaceAll(mi, fieldRef.getValue())
217
+ } else {
218
+ quitFlag = true
219
+ console.error('Field not found: ' + fieldSchema.options.label)
220
+ }
221
+ } else {
222
+ console.error('Invalid formula!')
223
+ }
224
+ } else {
225
+ /* 在主表单字段的计算公式中使用子表单字段,应将子表单所有记录同字段的值代入!! */
226
+ const subFormValue = VFR.formDataModel[subFormNameOfField]
227
+ let allSubFieldValues = ''
228
+ // const subFieldName = fieldSchema.options.name
229
+ const subFieldName = fieldKeyName(fieldSchema)
230
+ subFormValue.forEach((vi, idx) => {
231
+ allSubFieldValues = (idx === 0) ? vi[subFieldName] : allSubFieldValues + ', ' + vi[subFieldName]
232
+ })
233
+ resultFormula = resultFormula.replaceAll(mi, allSubFieldValues)
234
+ }
235
+ }
236
+ }
237
+ })
238
+
239
+ return quitFlag ? null : resultFormula
125
240
  }
126
241
 
127
242
  export function calculateFormula2(formulaStr, data, that) {