cloud-web-corejs 1.1.0-dev.22 → 1.1.0-dev.23
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/bizTab/BizTabListPage.vue +66 -33
- package/src/components/bizTab/README.md +3 -1
- package/src/components/mobile/wf/content.vue +27 -3
- package/src/components/table/index.js +5 -2
- package/src/components/table/plugins/cell-area/index.js +10 -3
- package/src/components/wf/wfStartDialog.vue +1 -0
- package/src/components/wf/wfUtil.js +47 -29
- package/src/components/wf/wfVisibility.js +6 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-mixin.js +7 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +3 -1
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +25 -1
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +14 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +318 -12
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +23 -7
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +48 -0
- package/src/components/xform/form-render/container-item/data-table-item.vue +8 -6
- package/src/components/xform/form-render/container-item/data-table-mixin.js +584 -24
- package/src/components/xform/form-render/container-item/detail-h5-item.vue +26 -16
- package/src/components/xform/form-render/container-item/detail-item.vue +350 -446
- package/src/components/xform/form-render/fieldControlMixin.js +2 -0
- package/src/components/xform/form-render/indexMixin.js +25 -15
- package/src/components/xform/mixins/businessLock.js +59 -0
- package/src/components/xform/mixins/wfStart.js +103 -0
- package/src/components/xform/mixins/wfVisibility.js +33 -0
- package/src/components/xform/styles/h5.scss +6 -1
- package/src/components/xform/utils/util.js +2 -0
- package/src/views/user/home/index.vue +1 -1
- package/src/views/user/home/net/distributor.vue +1015 -0
- package/src/views/user/home/net/index.vue +61 -0
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import cloneDeep from "lodash/cloneDeep";
|
|
2
|
+
import { applyBusinessLock } from '@base/components/xform/mixins/businessLock';
|
|
2
3
|
import {
|
|
3
4
|
collectFieldControlTargets, readFieldState, writeStateOptions, computeFieldStates,
|
|
4
5
|
resolveScriptStates, resolveRunMode, applyFieldState, isEntryVisible, sameValue,
|
|
@@ -410,6 +411,7 @@ export default {
|
|
|
410
411
|
this.handleWidgetShowRule(projected);
|
|
411
412
|
if (entry && states?.[entry.key]) writeStateOptions(projected.options, states[entry.key]);
|
|
412
413
|
this.applyWorkflowFieldControl(projected);
|
|
414
|
+
applyBusinessLock(projected, this);
|
|
413
415
|
if (widget.formItemFlag && this.disabledMode) projected.options.disabled = true;
|
|
414
416
|
const effective = readFieldState(projected);
|
|
415
417
|
// 非输入按钮不在动态目标范围,但仍应用流程自身的 disabled。
|
|
@@ -45,6 +45,8 @@ import {
|
|
|
45
45
|
} from "../../../components/xform/form-designer/widget-panel/widgetsConfig.js";
|
|
46
46
|
import { isUrlValueColumn } from "../../../components/xform/utils/attachmentValueUtil";
|
|
47
47
|
import scriptHttpMixin from "../../../components/xform/mixins/scriptHttp";
|
|
48
|
+
import wfVisibilityMixin from "@base/components/xform/mixins/wfVisibility";
|
|
49
|
+
import businessLockMixin from "@base/components/xform/mixins/businessLock";
|
|
48
50
|
import defaultHandleMixin from "../../../components/xform/mixins/defaultHandle";
|
|
49
51
|
import xeUtils from "xe-utils";
|
|
50
52
|
import { extendDeeply } from "@base/utils/index.js";
|
|
@@ -103,6 +105,8 @@ modules = {
|
|
|
103
105
|
baseFormulaDialog,
|
|
104
106
|
},
|
|
105
107
|
mixins: [
|
|
108
|
+
wfVisibilityMixin,
|
|
109
|
+
businessLockMixin,
|
|
106
110
|
baseRefUtil.emitter,
|
|
107
111
|
baseRefUtil.i18n,
|
|
108
112
|
scriptHttpMixin,
|
|
@@ -234,6 +238,9 @@ modules = {
|
|
|
234
238
|
currentFormData: {},
|
|
235
239
|
timerMap: {},
|
|
236
240
|
hasWf: false,
|
|
241
|
+
// 未启动流程时 hasWf 仍为 false,启动参数必须自身可响应,才能让详情按钮及时出现。
|
|
242
|
+
wfStartOption: null,
|
|
243
|
+
wfStartCtx: null,
|
|
237
244
|
showFormContent: false,
|
|
238
245
|
|
|
239
246
|
showFormDialog: false,
|
|
@@ -765,7 +772,7 @@ modules = {
|
|
|
765
772
|
let widgetEditOnWf = this.hanldeWfWidgetNew0(); //是否有流程时,当前用户特定流程节点是否可全局可编辑
|
|
766
773
|
this.widgetEditOnWf = widgetEditOnWf;
|
|
767
774
|
|
|
768
|
-
traverseAllWidgetsNew(this.formJson.widgetList, (widget) => {
|
|
775
|
+
traverseAllWidgetsNew(this.formJson.widgetList, (widget) => this.withBusinessLock(widget, () => {
|
|
769
776
|
//修复data-table旧数据表格列widget与editWidget为空的问题
|
|
770
777
|
this.handleTableColumnWidget(widget);
|
|
771
778
|
|
|
@@ -800,9 +807,9 @@ modules = {
|
|
|
800
807
|
}
|
|
801
808
|
}
|
|
802
809
|
}
|
|
803
|
-
});
|
|
810
|
+
}));
|
|
804
811
|
|
|
805
|
-
this.wfModifyEnabled = hasModifyItem;
|
|
812
|
+
this.wfModifyEnabled = hasModifyItem && !this.businessLocked;
|
|
806
813
|
},
|
|
807
814
|
getFieldControlWidgets() {
|
|
808
815
|
const widgets = [];
|
|
@@ -841,18 +848,20 @@ modules = {
|
|
|
841
848
|
|
|
842
849
|
const processWidget = (widget) => {
|
|
843
850
|
if (!widget) return;
|
|
844
|
-
this.
|
|
845
|
-
|
|
846
|
-
widget
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
851
|
+
return this.withBusinessLock(widget, () => {
|
|
852
|
+
this.handleWidgetShowRule(widget);
|
|
853
|
+
if (wfParam.hasWf && widget?.options?.saveSubmitWfButton) {
|
|
854
|
+
widget.options.hidden = true;
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
857
|
+
if (!wfParam.hasWf || widgetEditOnWf) return;
|
|
858
|
+
this.hanldeWfWidgetNew1(widget);
|
|
859
|
+
if (wfInfo.taskStep === "9999") {
|
|
860
|
+
this.hanldeWfWidgetItemNew(widget);
|
|
861
|
+
} else if (toModify && taskDefinitionKey) {
|
|
862
|
+
this.hanldeWfWidgetItemNew(widget);
|
|
863
|
+
}
|
|
864
|
+
});
|
|
856
865
|
};
|
|
857
866
|
|
|
858
867
|
const columnLoopDo = (column) => {
|
|
@@ -1463,6 +1472,7 @@ modules = {
|
|
|
1463
1472
|
showStartBtn: true, //需要启动按钮(语义不变)
|
|
1464
1473
|
injectStartBtn: false, //但不走 wfUtil 的 DOM 强制注入,改由 detail-item 模板声明式渲染
|
|
1465
1474
|
showWfFold: true,
|
|
1475
|
+
layoutType: formConfig.layoutType,
|
|
1466
1476
|
formCode: formCode,
|
|
1467
1477
|
startConfirmText: () => this.getWfStartConfirmText(),
|
|
1468
1478
|
callback: (wfParam) => {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { applyFieldState } from '@base/components/xform/form-render/fieldControlEngine';
|
|
2
|
+
|
|
3
|
+
// 最后叠加业务限制,不改变真实流程状态,也不放宽既有字段规则。
|
|
4
|
+
export function applyBusinessLock(widget, host) {
|
|
5
|
+
if (!host.businessLocked || !widget?.options) return;
|
|
6
|
+
const deleteColumn = ['editDelete', 'removeTreeRow'].includes(widget.columnType);
|
|
7
|
+
if (widget.options.saveSubmitWfButton || deleteColumn) {
|
|
8
|
+
widget.options.hidden = true;
|
|
9
|
+
} else if (!host.getIsfreeWidgetTypesOfWf(widget)) {
|
|
10
|
+
if (host.getIsHiddenWidgetTypesOfWf(widget)) widget.options.hidden = true;
|
|
11
|
+
else if (widget.formItemFlag) widget.options.disabled = true;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
data() {
|
|
17
|
+
return { businessLocked: false };
|
|
18
|
+
},
|
|
19
|
+
methods: {
|
|
20
|
+
// 可在表单事件脚本中调用;返回的 Promise 在本次视图更新后完成。
|
|
21
|
+
setBusinessLocked(locked = true) {
|
|
22
|
+
this.businessLocked = locked === true;
|
|
23
|
+
if (this.isFieldControlEnabled()) {
|
|
24
|
+
// 初始化前仅记录锁定意图,避免将锁定结果当成模板基线。
|
|
25
|
+
if (this.fieldControlInitialized) {
|
|
26
|
+
this.prepareFieldControlTargets();
|
|
27
|
+
this.applyFieldControlStates(this.getFieldControlRuntime().dynamicStates);
|
|
28
|
+
}
|
|
29
|
+
} else {
|
|
30
|
+
this.hanldeCommonWidget2();
|
|
31
|
+
}
|
|
32
|
+
return this.$nextTick();
|
|
33
|
+
},
|
|
34
|
+
withBusinessLock(widget, evaluate) {
|
|
35
|
+
if (!widget?.options) return evaluate();
|
|
36
|
+
if (!this._businessLockBaseline) this._businessLockBaseline = new WeakMap();
|
|
37
|
+
const previous = this._businessLockBaseline.get(widget);
|
|
38
|
+
if (previous) {
|
|
39
|
+
Object.keys(previous).forEach(key => {
|
|
40
|
+
if (previous[key] === undefined) this.$delete(widget.options, key);
|
|
41
|
+
else this.$set(widget.options, key, previous[key]);
|
|
42
|
+
});
|
|
43
|
+
this._businessLockBaseline.delete(widget);
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
return evaluate();
|
|
47
|
+
} finally {
|
|
48
|
+
const baseline = { hidden: widget.options.hidden, disabled: widget.options.disabled };
|
|
49
|
+
applyBusinessLock(widget, this);
|
|
50
|
+
if (this.businessLocked) this._businessLockBaseline.set(widget, baseline);
|
|
51
|
+
if (this.businessLocked || previous) {
|
|
52
|
+
applyFieldState({ widget, refKey: widget.options.name, isContainer: widget.category === 'container' },
|
|
53
|
+
{ visible: !widget.options.hidden, disabled: !!widget.options.disabled },
|
|
54
|
+
name => this.getWidgetRef(name));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { openStartWfDialog } from "@base/components/wf/wfUtil";
|
|
2
|
+
import { getWfButtonNames, loadWfButtonNames, DEFAULT_SUBMIT_BTN } from "@base/components/wf/wfButtonName";
|
|
3
|
+
import { loadWfAutoConfirm } from "@base/components/wf/wfAutoConfirm";
|
|
4
|
+
import { loadWfUserRange } from "@base/components/wf/wfUserRange";
|
|
5
|
+
import settingConfig from "@base/settings";
|
|
6
|
+
|
|
7
|
+
// PC 与 H5 共用启动规则、校验和回调;容器提供 wfStart() 获取各自的流程状态。
|
|
8
|
+
export default {
|
|
9
|
+
computed: {
|
|
10
|
+
wfStartButtonName() {
|
|
11
|
+
return getWfButtonNames().submitBtn || settingConfig.wfStartButtonName || this.$t1(DEFAULT_SUBMIT_BTN);
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
methods: {
|
|
15
|
+
initWfStartSettings() {
|
|
16
|
+
if (this.getFormRef()?.formConfig?.wfEnabled) {
|
|
17
|
+
loadWfButtonNames(this);
|
|
18
|
+
loadWfAutoConfirm(this);
|
|
19
|
+
loadWfUserRange(this);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
// 流程启动按钮:有启动信息、需要按钮(showStartBtn 未显式关闭)、未启动、非预览态才显示。
|
|
23
|
+
// 声明式渲染,替代 wfUtil 的 DOM 强制注入。
|
|
24
|
+
showWfStartBtn() {
|
|
25
|
+
if (this.getFormRef()?.businessLocked) return false;
|
|
26
|
+
let ws = this.wfStart();
|
|
27
|
+
if (!ws || this.previewState) return false;
|
|
28
|
+
let opt = ws.option || {};
|
|
29
|
+
if (opt.showStartBtn === false || ws.hasWf) return false;
|
|
30
|
+
return this.evalWfStartBtnShow();
|
|
31
|
+
},
|
|
32
|
+
/**
|
|
33
|
+
* 「提交流程」按钮显隐脚本(formConfig.wfStartBtnShow):return false 隐藏,不配则显示。
|
|
34
|
+
* 在渲染期求值,好处是随表单数据自动更新,代价是脚本会被反复执行——所以:
|
|
35
|
+
* 1) 编译结果按脚本原文缓存,避免每次渲染都 new Function;
|
|
36
|
+
* 2) 编译/执行异常一律放行(返回 true),不能因为脚本写错就把提交入口挡死;
|
|
37
|
+
* 3) formData 取轻量的 formRef.formData,不走 getSysFormData/getRealFormData 那套重加工。
|
|
38
|
+
* 脚本里务必只读数据、返回布尔,改数据会引发渲染循环。
|
|
39
|
+
*/
|
|
40
|
+
evalWfStartBtnShow() {
|
|
41
|
+
let formRef = this.getFormRef && this.getFormRef();
|
|
42
|
+
let src = formRef && formRef.formConfig && formRef.formConfig.wfStartBtnShow;
|
|
43
|
+
if (!src) return true;
|
|
44
|
+
let cache = this._wfStartShowFn; //挂实例属性即可,不需要响应式
|
|
45
|
+
if (!cache || cache.src !== src) {
|
|
46
|
+
try {
|
|
47
|
+
cache = {
|
|
48
|
+
src,
|
|
49
|
+
fn: new Function("dataId", "formCode", "formData", src),
|
|
50
|
+
};
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error("wfStartBtnShow 脚本编译失败", error);
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
this._wfStartShowFn = cache;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
let ret = cache.fn.call(
|
|
59
|
+
formRef,
|
|
60
|
+
formRef.dataId,
|
|
61
|
+
formRef.reportTemplate && formRef.reportTemplate.formCode,
|
|
62
|
+
formRef.formData
|
|
63
|
+
);
|
|
64
|
+
return ret !== false;
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error("wfStartBtnShow 脚本执行异常", error);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
// 声明式触发流程启动(替代原注入按钮的点击),复用 wfUtil 的 openStartWfDialog
|
|
71
|
+
startWf() {
|
|
72
|
+
if (this.getFormRef()?.businessLocked) return;
|
|
73
|
+
let ws = this.wfStart();
|
|
74
|
+
if (!ws || !ws.option || !ws.ctx) return;
|
|
75
|
+
// startConfirmText 原样透传:它只承载模板脚本 wfStartConfirmText 的文案(见 indexMixin
|
|
76
|
+
// 的 option 构造)。按钮名拼接与「后台 param19 自动确认」都由 wf.js 统一处理——
|
|
77
|
+
// 在这里替它拼默认文案的话,wf.js 会把它当成脚本自定义的告警,自动确认就失效了。
|
|
78
|
+
let innerOnStart = ws.option.onStart;
|
|
79
|
+
let formRef = this.getFormRef && this.getFormRef();
|
|
80
|
+
openStartWfDialog(ws.ctx, {
|
|
81
|
+
...ws.option, //浅拷贝:wfStartOption 是 formRef 上的共享对象,不可原地改
|
|
82
|
+
// 提交前置处理:确认框在 wfStartDialog 内部,这里(打开弹框前)是唯一能拦的位置。
|
|
83
|
+
// 既有的 onStart 是表单校验(仅 wfStartBindSave 开启时注入),把它的 done 换成
|
|
84
|
+
// 「跑前置脚本」,即得到「先校验、后脚本、再确认框」;没开自动保存时直接跑脚本。
|
|
85
|
+
onStart: (done) => {
|
|
86
|
+
let runBefore = () => {
|
|
87
|
+
if (!formRef || typeof formRef.runBeforeSubmitWf !== "function") {
|
|
88
|
+
return done();
|
|
89
|
+
}
|
|
90
|
+
formRef.runBeforeSubmitWf("wfStart").then((pass) => {
|
|
91
|
+
if (pass) done();
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
if (typeof innerOnStart === "function") {
|
|
95
|
+
innerOnStart(runBefore);
|
|
96
|
+
} else {
|
|
97
|
+
runBefore();
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// 与组件显隐规则一致:只匹配当前公司的角色,命中任意角色即隐藏。
|
|
2
|
+
export default {
|
|
3
|
+
data() {
|
|
4
|
+
return {
|
|
5
|
+
// 脚本态与角色配置分开保存;脚本取消隐藏时不会越过角色限制。
|
|
6
|
+
wfInfoHiddenByScript: false,
|
|
7
|
+
};
|
|
8
|
+
},
|
|
9
|
+
computed: {
|
|
10
|
+
_hideWf() {
|
|
11
|
+
const inherited = this.$attrs && this.$attrs._hideWf;
|
|
12
|
+
if (inherited === true || inherited === "true") return true;
|
|
13
|
+
if (this.wfInfoHiddenByScript) return true;
|
|
14
|
+
const configured = this.formConfig && this.formConfig.wfInfoHiddenRoleCodes;
|
|
15
|
+
const codes = (Array.isArray(configured) ? configured : String(configured || "").split(","))
|
|
16
|
+
.map(code => String(code).trim()).filter(Boolean);
|
|
17
|
+
return (this.userRoleDTO2s || []).some(role => codes.includes(role.roleCode));
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
methods: {
|
|
21
|
+
/**
|
|
22
|
+
* 给表单事件脚本调用:this.setWfInfoHidden(true/false)。
|
|
23
|
+
* 只控制流程信息、导航和依赖面板的审批入口,不影响流程初始化及启动按钮。
|
|
24
|
+
*/
|
|
25
|
+
setWfInfoHidden(hidden = true) {
|
|
26
|
+
this.wfInfoHiddenByScript = hidden === true || hidden === "true";
|
|
27
|
+
if (typeof this._refreshWfInfoVisibility === "function") {
|
|
28
|
+
this._refreshWfInfoVisibility();
|
|
29
|
+
}
|
|
30
|
+
return this.$nextTick();
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
};
|
|
@@ -180,7 +180,8 @@ $xformH5Size:14px;
|
|
|
180
180
|
那条正是块 C1 依赖的前提。 */
|
|
181
181
|
.el-form-item {
|
|
182
182
|
display: flex;
|
|
183
|
-
|
|
183
|
+
/* 单行字段与移动端基本信息表格保持一致:标签和值都落在字段行中线。 */
|
|
184
|
+
align-items: center;
|
|
184
185
|
position: relative;
|
|
185
186
|
min-height: $xformH5RowHeight;
|
|
186
187
|
margin-bottom: 0;
|
|
@@ -189,6 +190,8 @@ $xformH5Size:14px;
|
|
|
189
190
|
/* 对手:style.scss:13854 `.h5-detail-wrap .h5-item .el-form-item__label` (0,3,0)
|
|
190
191
|
带 text-align:left !important,且把 &:after 设成 display:none;本方 (0,5,0)。 */
|
|
191
192
|
.el-form-item > .el-form-item__label {
|
|
193
|
+
display: flex !important;
|
|
194
|
+
align-items: center;
|
|
192
195
|
width: $xformH5LabelWidth;
|
|
193
196
|
padding: 0 5px 0 0;
|
|
194
197
|
margin: 0;
|
|
@@ -1750,6 +1753,8 @@ $xformH5Size:14px;
|
|
|
1750
1753
|
border-radius: 0;
|
|
1751
1754
|
|
|
1752
1755
|
> .el-dialog__body {
|
|
1756
|
+
display: flex;
|
|
1757
|
+
flex-direction: column;
|
|
1753
1758
|
flex: 1;
|
|
1754
1759
|
min-height: 0;
|
|
1755
1760
|
overflow-y: auto;
|
|
@@ -1116,6 +1116,8 @@ export function getDefaultFormConfig() {
|
|
|
1116
1116
|
onBeforeSubmitWf: null,
|
|
1117
1117
|
// 「提交流程」按钮显隐脚本:return false 隐藏,不配则显示
|
|
1118
1118
|
wfStartBtnShow: null,
|
|
1119
|
+
// 当前公司角色编码,逗号分隔;命中任意角色只隐藏流程信息,保留启动入口。
|
|
1120
|
+
wfInfoHiddenRoleCodes: "",
|
|
1119
1121
|
wfAgreenBindSave: false,
|
|
1120
1122
|
wfAgreeConfigData: [],
|
|
1121
1123
|
wfConfigDataEnabled: false,
|
|
@@ -90,7 +90,7 @@ export default {
|
|
|
90
90
|
url = defaultHomePage || settingConfig.defaultHomePage || '@base/views/user/home/default.vue'
|
|
91
91
|
}
|
|
92
92
|
// 首页菜单不会归属别的子应用,无需 remote 兜底;归属解析见 @base/utils/resolveViewComponent
|
|
93
|
-
this.homeContent = (await loadViewComponentAsync(url)).component;
|
|
93
|
+
this.homeContent = (await loadViewComponentAsync(url)).component;
|
|
94
94
|
|
|
95
95
|
this.showHomeContent = true;
|
|
96
96
|
this.flag = 1;
|