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 +1 -1
- package/src/components/xform/form-designer/form-widget/dialog/baseFormulaDialog.vue +962 -0
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +18 -5
- package/src/components/xform/form-render/index.vue +5 -0
- package/src/components/xform/form-render/indexMixin.js +10 -2
- package/src/components/xform/mixins/defaultHandle.js +5 -1
- package/src/components/xform/utils/formula-util.js +116 -1
package/package.json
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
317
|
+
this.initValue(defaultValue);
|
|
318
318
|
}
|
|
319
319
|
} else {
|
|
320
320
|
//明细
|
|
321
321
|
if (!this.tableParam.row.id && this.isNotNullVal(defaultValue)) {
|
|
322
|
-
this.
|
|
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.
|
|
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) {
|