cloud-web-corejs 1.0.54-dev.795 → 1.0.54-dev.796
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/formDialog/README.md +32 -6
- package/src/components/luckysheet/dialog.vue +1 -1
- package/src/components/wf/wfButtonName.js +60 -0
- package/src/components/xform/form-designer/designer.js +2 -1
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +65 -29
- package/src/components/xform/form-designer/form-widget/field-widget/save_submit_wf_button-widget.vue +3 -0
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +103 -8
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/addTableData-event-editor.vue +0 -1
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/clickBindActions.js +253 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/clickBindEvent-editor.vue +49 -40
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/form-host-event-editor.vue +175 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-button/search-dialog-event-editor.vue +20 -5
- package/src/components/xform/form-designer/widget-panel/indexMixin.js +2 -1
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +3 -0
- package/src/components/xform/form-render/container-item/detail-item.vue +116 -3
- package/src/components/xform/form-render/index.vue +0 -7
- package/src/components/xform/form-render/indexMixin.js +60 -8
- package/src/components/xform/mixins/defaultHandle.js +21 -1
- package/src/components/xform/utils/util.js +7 -0
- package/src/views/bd/setting/formVersion/ftHistoryDialog.vue +2 -0
- package/src/components/xform/form-designer/form-widget/dialog/formDrawer.vue +0 -307
|
@@ -44,6 +44,14 @@
|
|
|
44
44
|
>下一单<i class="el-icon-arrow-right el-icon--right"></i
|
|
45
45
|
></el-button>
|
|
46
46
|
</template>
|
|
47
|
+
<el-button
|
|
48
|
+
v-if="showSaveSubmitBtn()"
|
|
49
|
+
class="button-sty"
|
|
50
|
+
type="success"
|
|
51
|
+
icon="el-icon-video-play"
|
|
52
|
+
@click="saveAndSubmitWfHandle()"
|
|
53
|
+
>{{ saveSubmitButtonName }}</el-button
|
|
54
|
+
>
|
|
47
55
|
<el-button
|
|
48
56
|
v-if="showWfStartBtn()"
|
|
49
57
|
class="button-sty yyy"
|
|
@@ -120,6 +128,12 @@ import detailPaneWidget from "../../../../components/xform/form-render/container
|
|
|
120
128
|
import FieldComponents from "../../../../components/xform/form-designer/form-widget/field-widget/index";
|
|
121
129
|
|
|
122
130
|
import { initWf, openStartWfDialog } from "../../../../components/wf/wfUtil";
|
|
131
|
+
import {
|
|
132
|
+
getWfButtonNames,
|
|
133
|
+
loadWfButtonNames,
|
|
134
|
+
DEFAULT_SUBMIT_BTN,
|
|
135
|
+
DEFAULT_SAVE_SUBMIT_BTN,
|
|
136
|
+
} from "../../../../components/wf/wfButtonName";
|
|
123
137
|
import settingConfig from "@/settings.js";
|
|
124
138
|
|
|
125
139
|
export default {
|
|
@@ -138,6 +152,10 @@ export default {
|
|
|
138
152
|
created() {
|
|
139
153
|
this.initRefList();
|
|
140
154
|
this.handleOnCreated();
|
|
155
|
+
//只有流程表单才需要按钮名,避免给普通详情页平白多一次请求(模块内全局只发一次)
|
|
156
|
+
if (this.getFormRef()?.formConfig?.wfEnabled) {
|
|
157
|
+
loadWfButtonNames(this);
|
|
158
|
+
}
|
|
141
159
|
},
|
|
142
160
|
mounted() {
|
|
143
161
|
this.handleOnMounted();
|
|
@@ -167,10 +185,18 @@ export default {
|
|
|
167
185
|
showHeader() {
|
|
168
186
|
return !this.plainMode && !this.widget.options.hideHeader;
|
|
169
187
|
},
|
|
188
|
+
// 按钮名取值链:后台 param18 → 全局 settings(老部署兼容) → 默认。
|
|
189
|
+
// 只能用 $t1(找不到 key 原样返回):$t2 的第二参在 i18n 命中 key 时会把自定义名整个覆盖掉。
|
|
170
190
|
wfStartButtonName() {
|
|
171
191
|
return (
|
|
192
|
+
getWfButtonNames().submitBtn ||
|
|
172
193
|
settingConfig.wfStartButtonName ||
|
|
173
|
-
this.$
|
|
194
|
+
this.$t1(DEFAULT_SUBMIT_BTN)
|
|
195
|
+
);
|
|
196
|
+
},
|
|
197
|
+
saveSubmitButtonName() {
|
|
198
|
+
return (
|
|
199
|
+
getWfButtonNames().saveSubmitBtn || this.$t1(DEFAULT_SAVE_SUBMIT_BTN)
|
|
174
200
|
);
|
|
175
201
|
},
|
|
176
202
|
// 「上一单/下一单」翻单按钮状态:详情表单开启 billNavEnabled 且宿主列表有翻单快照时才显示。
|
|
@@ -222,13 +248,100 @@ export default {
|
|
|
222
248
|
let ws = this.wfStart();
|
|
223
249
|
if (!ws || this.previewState) return false;
|
|
224
250
|
let opt = ws.option || {};
|
|
225
|
-
|
|
251
|
+
if (opt.showStartBtn === false || ws.hasWf) return false;
|
|
252
|
+
return this.evalWfStartBtnShow();
|
|
253
|
+
},
|
|
254
|
+
/**
|
|
255
|
+
* 「提交流程」按钮显隐脚本(formConfig.wfStartBtnShow):return false 隐藏,不配则显示。
|
|
256
|
+
* 在渲染期求值,好处是随表单数据自动更新,代价是脚本会被反复执行——所以:
|
|
257
|
+
* 1) 编译结果按脚本原文缓存,避免每次渲染都 new Function;
|
|
258
|
+
* 2) 编译/执行异常一律放行(返回 true),不能因为脚本写错就把提交入口挡死;
|
|
259
|
+
* 3) formData 取轻量的 formRef.formData,不走 getSysFormData/getRealFormData 那套重加工。
|
|
260
|
+
* 脚本里务必只读数据、返回布尔,改数据会引发渲染循环。
|
|
261
|
+
*/
|
|
262
|
+
evalWfStartBtnShow() {
|
|
263
|
+
let formRef = this.getFormRef && this.getFormRef();
|
|
264
|
+
let src = formRef && formRef.formConfig && formRef.formConfig.wfStartBtnShow;
|
|
265
|
+
if (!src) return true;
|
|
266
|
+
let cache = this._wfStartShowFn; //挂实例属性即可,不需要响应式
|
|
267
|
+
if (!cache || cache.src !== src) {
|
|
268
|
+
try {
|
|
269
|
+
cache = {
|
|
270
|
+
src,
|
|
271
|
+
fn: new Function("dataId", "formCode", "formData", src),
|
|
272
|
+
};
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.error("wfStartBtnShow 脚本编译失败", error);
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
this._wfStartShowFn = cache;
|
|
278
|
+
}
|
|
279
|
+
try {
|
|
280
|
+
let ret = cache.fn.call(
|
|
281
|
+
formRef,
|
|
282
|
+
formRef.dataId,
|
|
283
|
+
formRef.reportTemplate && formRef.reportTemplate.formCode,
|
|
284
|
+
formRef.formData
|
|
285
|
+
);
|
|
286
|
+
return ret !== false;
|
|
287
|
+
} catch (error) {
|
|
288
|
+
console.error("wfStartBtnShow 脚本执行异常", error);
|
|
289
|
+
return true;
|
|
290
|
+
}
|
|
291
|
+
},
|
|
292
|
+
// 「保存并提交流程」内建按钮:表单设置里 saveSubmitEnabled 开启后渲染,只在新增页显示。
|
|
293
|
+
// 与 showWfStartBtn 一样用方法而非 computed:流程状态是异步就绪的,computed 缓存会漏更新。
|
|
294
|
+
showSaveSubmitBtn() {
|
|
295
|
+
if (this.previewState) return false;
|
|
296
|
+
let formRef = this.getFormRef && this.getFormRef();
|
|
297
|
+
let formConfig = formRef && formRef.formConfig;
|
|
298
|
+
if (!formConfig || !formConfig.wfEnabled || !formConfig.saveSubmitEnabled)
|
|
299
|
+
return false;
|
|
300
|
+
if (formRef.dataId) return false; //只有新增页(编辑态一律不显示)
|
|
301
|
+
let wfParam = formRef.wfParam || {};
|
|
302
|
+
//流程已启动不显示(与 save_submit_wf_button-widget 的 isWfStarted 同口径)
|
|
303
|
+
if (formRef.hasWf || wfParam.hasWf || wfParam.wfInfo?.procInstId)
|
|
304
|
+
return false;
|
|
305
|
+
return true;
|
|
226
306
|
},
|
|
227
307
|
// 声明式触发流程启动(替代原注入按钮的点击),复用 wfUtil 的 openStartWfDialog
|
|
228
308
|
startWf() {
|
|
229
309
|
let ws = this.wfStart();
|
|
230
310
|
if (!ws || !ws.option || !ws.ctx) return;
|
|
231
|
-
|
|
311
|
+
// 启动确认提示语跟随「提交流程按钮名」:包一层现成的 startConfirmText 钩子,
|
|
312
|
+
// 既保住模板脚本 wfStartConfirmText 的最高优先级,又不必改公共的 wf.js
|
|
313
|
+
// (wf.js 默认分支走 $t2(文案, key),i18n 命中 key 会把自定义按钮名吞掉)。
|
|
314
|
+
let inner = ws.option.startConfirmText;
|
|
315
|
+
//只有后台真配了按钮名才改提示语;没配就返空,让 wf.js 走它自己的默认链
|
|
316
|
+
let btnName = getWfButtonNames().submitBtn;
|
|
317
|
+
let innerOnStart = ws.option.onStart;
|
|
318
|
+
let formRef = this.getFormRef && this.getFormRef();
|
|
319
|
+
openStartWfDialog(ws.ctx, {
|
|
320
|
+
...ws.option, //浅拷贝:wfStartOption 是 formRef 上的共享对象,不可原地改
|
|
321
|
+
// 提交前置处理:确认框在 wfStartDialog 内部,这里(打开弹框前)是唯一能拦的位置。
|
|
322
|
+
// 既有的 onStart 是表单校验(仅 wfStartBindSave 开启时注入),把它的 done 换成
|
|
323
|
+
// 「跑前置脚本」,即得到「先校验、后脚本、再确认框」;没开自动保存时直接跑脚本。
|
|
324
|
+
onStart: (done) => {
|
|
325
|
+
let runBefore = () => {
|
|
326
|
+
if (!formRef || typeof formRef.runBeforeSubmitWf !== "function") {
|
|
327
|
+
return done();
|
|
328
|
+
}
|
|
329
|
+
formRef.runBeforeSubmitWf("wfStart").then((pass) => {
|
|
330
|
+
if (pass) done();
|
|
331
|
+
});
|
|
332
|
+
};
|
|
333
|
+
if (typeof innerOnStart === "function") {
|
|
334
|
+
innerOnStart(runBefore);
|
|
335
|
+
} else {
|
|
336
|
+
runBefore();
|
|
337
|
+
}
|
|
338
|
+
},
|
|
339
|
+
startConfirmText: async (ctx) => {
|
|
340
|
+
let text = typeof inner === "function" ? await inner.call(this, ctx) : inner;
|
|
341
|
+
if (typeof text === "string" && text.trim()) return text; //模板脚本优先
|
|
342
|
+
return btnName ? `您确定要${btnName}吗?` : ""; //返空 → wf.js 走自身默认
|
|
343
|
+
},
|
|
344
|
+
});
|
|
232
345
|
},
|
|
233
346
|
// 触发宿主翻单:step = -1 上一单 / +1 下一单
|
|
234
347
|
navBill(step) {
|
|
@@ -77,11 +77,6 @@
|
|
|
77
77
|
:param="importDialogOption"
|
|
78
78
|
:parentTarget="_self"
|
|
79
79
|
></importDialog>
|
|
80
|
-
<formDrawer
|
|
81
|
-
v-if="showFormDrawer"
|
|
82
|
-
:visiable.sync="showFormDrawer"
|
|
83
|
-
:option="formDrawerOption"
|
|
84
|
-
></formDrawer>
|
|
85
80
|
<fileReferenceDialog
|
|
86
81
|
v-if="showFileReferenceDialog"
|
|
87
82
|
:visiable.sync="showFileReferenceDialog"
|
|
@@ -134,8 +129,6 @@ export default {
|
|
|
134
129
|
import(
|
|
135
130
|
"../../../components/xform/form-designer/form-widget/dialog/importDialog.vue"
|
|
136
131
|
),
|
|
137
|
-
formDrawer: () =>
|
|
138
|
-
import("../../../components/xform/form-designer/form-widget/dialog/formDrawer.vue"),
|
|
139
132
|
fileReferenceDialog: () =>
|
|
140
133
|
import(
|
|
141
134
|
"../../../components/xform/form-designer/form-widget/dialog/fileReferenceDialog.vue"
|
|
@@ -234,8 +234,6 @@ modules = {
|
|
|
234
234
|
formDialogOption: {},
|
|
235
235
|
showImportDialog: false,
|
|
236
236
|
importDialogOption: {},
|
|
237
|
-
formDrawerOption: {},
|
|
238
|
-
showFormDrawer: false,
|
|
239
237
|
userInfo: null,
|
|
240
238
|
userSaleOrgDTOs: [],
|
|
241
239
|
userRoleDTOs: [],
|
|
@@ -1822,6 +1820,46 @@ modules = {
|
|
|
1822
1820
|
);
|
|
1823
1821
|
},
|
|
1824
1822
|
|
|
1823
|
+
/**
|
|
1824
|
+
* 「提交流程」「保存并提交流程」共用的提交前置处理。
|
|
1825
|
+
* 执行时机:表单校验通过之后、确认框弹出之前。两条链路都调这里,业务规则只写一遍。
|
|
1826
|
+
*
|
|
1827
|
+
* 脚本契约(只认返回值,不用 done 回调):
|
|
1828
|
+
* return false → 中止提交
|
|
1829
|
+
* return Promise → 等它 settle;resolve(false) 或 reject 都算中止
|
|
1830
|
+
* 其他(含不写 return) → 放行
|
|
1831
|
+
* 之所以不做成 done 风格:本方法的调用方要 await 它,脚本一旦忘了调 done 就会永久挂起,
|
|
1832
|
+
* 「保存并提交」那条链路还会把 formSavePending 锁死,之后再也保存不了。
|
|
1833
|
+
*
|
|
1834
|
+
* @param {String} source "saveSubmit"(保存并提交流程) | "wfStart"(提交流程)
|
|
1835
|
+
* @returns {Promise<Boolean>} true 继续,false 中止
|
|
1836
|
+
*/
|
|
1837
|
+
runBeforeSubmitWf(source) {
|
|
1838
|
+
let script = this.formConfig?.onBeforeSubmitWf;
|
|
1839
|
+
if (!script) return Promise.resolve(true);
|
|
1840
|
+
let currentFormData = this.getSysFormData(this.getRealFormData());
|
|
1841
|
+
let ret;
|
|
1842
|
+
try {
|
|
1843
|
+
ret = this.handleCustomEvent(
|
|
1844
|
+
script,
|
|
1845
|
+
["formData", "source"],
|
|
1846
|
+
[currentFormData, source]
|
|
1847
|
+
);
|
|
1848
|
+
} catch (error) {
|
|
1849
|
+
//脚本自身报错不放行,避免带着未知状态继续提交
|
|
1850
|
+
console.error("onBeforeSubmitWf 执行异常", error);
|
|
1851
|
+
return Promise.resolve(false);
|
|
1852
|
+
}
|
|
1853
|
+
if (ret === false) return Promise.resolve(false);
|
|
1854
|
+
if (ret && typeof ret.then === "function") {
|
|
1855
|
+
return ret.then(
|
|
1856
|
+
(result) => result !== false,
|
|
1857
|
+
() => false
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
return Promise.resolve(true);
|
|
1861
|
+
},
|
|
1862
|
+
|
|
1825
1863
|
handleOnCreated: function () {
|
|
1826
1864
|
this.handleCustomEvent(this.formConfig?.onFormCreated);
|
|
1827
1865
|
/*if (this.formConfig && this.formConfig.onFormCreated) {
|
|
@@ -4869,12 +4907,26 @@ modules = {
|
|
|
4869
4907
|
this.showImportDialog = true;
|
|
4870
4908
|
this.importDialogOption = option;
|
|
4871
4909
|
},
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4910
|
+
/**
|
|
4911
|
+
* 表单抽屉:委托给全局 $formDrawer(components/formDrawer)。
|
|
4912
|
+
* 原 xform 内部抽屉壳(dialog/formDrawer.vue)已删除——它零调用方,且 scoped 样式写的是
|
|
4913
|
+
* .el-dialog__body,在 el-drawer 下根本不匹配,内容区没有高度、列表型模板会塌。
|
|
4914
|
+
* 这里保留方法名与回调式签名,存量脚本按内部形态调用也不会断。
|
|
4915
|
+
*/
|
|
4916
|
+
openFormDrawer(option = {}) {
|
|
4917
|
+
let dialogConfig = option.dialogConfig || {};
|
|
4918
|
+
let drawerOption = Object.assign({}, option, option.formConfig, {
|
|
4919
|
+
title: option.title || dialogConfig.title,
|
|
4920
|
+
size: option.size || dialogConfig.size,
|
|
4921
|
+
direction: option.direction || dialogConfig.direction,
|
|
4922
|
+
});
|
|
4923
|
+
delete drawerOption.formConfig;
|
|
4924
|
+
delete drawerOption.dialogConfig;
|
|
4925
|
+
return this.$formDrawer(drawerOption).then((result) => {
|
|
4926
|
+
if (result != null) option.confirm && option.confirm(result);
|
|
4927
|
+
option.close && option.close(null, this);
|
|
4928
|
+
return result;
|
|
4929
|
+
});
|
|
4878
4930
|
},
|
|
4879
4931
|
|
|
4880
4932
|
openFileReferenceDialog(option) {
|
|
@@ -2,6 +2,7 @@ import moment from "moment";
|
|
|
2
2
|
import { saveUserLog } from "@base/api/user";
|
|
3
3
|
import settingConfig from "@/settings";
|
|
4
4
|
import { openStartWfDialog } from "../../../components/wf/wfUtil";
|
|
5
|
+
import { getWfButtonNames } from "../../../components/wf/wfButtonName";
|
|
5
6
|
|
|
6
7
|
let modules = {};
|
|
7
8
|
modules = {
|
|
@@ -148,10 +149,15 @@ modules = {
|
|
|
148
149
|
return;
|
|
149
150
|
}
|
|
150
151
|
|
|
152
|
+
// 提示语跟随后台 param18 下发的按钮名;没配就保持原文案不变。
|
|
153
|
+
// 只能用 $t1(找不到 key 原样返回),$t2 在 i18n 命中 key 时会把拼进去的名字吞掉。
|
|
154
|
+
let btnName = getWfButtonNames().saveSubmitBtn;
|
|
151
155
|
let confirmText =
|
|
152
156
|
option?.confirmText ||
|
|
153
157
|
option?.config?.confirmText ||
|
|
154
|
-
|
|
158
|
+
(btnName
|
|
159
|
+
? this.$t1(`您确定要${btnName}吗?`)
|
|
160
|
+
: this.$t1("您确定要保存并提交流程吗?"));
|
|
155
161
|
|
|
156
162
|
return this.saveDefaultHandle({
|
|
157
163
|
...option,
|
|
@@ -161,6 +167,11 @@ modules = {
|
|
|
161
167
|
isConfirm: option?.config?.isConfirm ?? true,
|
|
162
168
|
confirmText: option?.config?.confirmText || confirmText,
|
|
163
169
|
skipHostReloadAfterSave: true,
|
|
170
|
+
//提交前置处理(与「提交流程」按钮共用同一个表单脚本)
|
|
171
|
+
beforeConfirm: () =>
|
|
172
|
+
formRef.runBeforeSubmitWf
|
|
173
|
+
? formRef.runBeforeSubmitWf("saveSubmit")
|
|
174
|
+
: true,
|
|
164
175
|
success: (res) => {
|
|
165
176
|
// ★ 保存成功后,只升级新增页签的「元数据」为编辑态(设 dataId/isAdd/formCode/标题),
|
|
166
177
|
// 不重渲染详情内容。这样即便随后提交失败/取消候选人弹框,页签也已是编辑态,
|
|
@@ -220,6 +231,15 @@ modules = {
|
|
|
220
231
|
});
|
|
221
232
|
if (!valid) return false;
|
|
222
233
|
|
|
234
|
+
// 提交前置处理:校验通过后、确认框之前拦截。只有「保存并提交流程」入口会传,
|
|
235
|
+
// 普通保存不受影响。返回 false 即中止(finally 里会释放 formSavePending)。
|
|
236
|
+
let beforeConfirm = config.beforeConfirm;
|
|
237
|
+
delete config.beforeConfirm; //不能透传给 formHttp
|
|
238
|
+
if (typeof beforeConfirm === "function") {
|
|
239
|
+
let pass = await beforeConfirm();
|
|
240
|
+
if (pass === false) return false;
|
|
241
|
+
}
|
|
242
|
+
|
|
223
243
|
let submitFormData
|
|
224
244
|
= typeof formRef.buildSubmitPayload === "function"
|
|
225
245
|
? await formRef.buildSubmitPayload()
|
|
@@ -1045,6 +1045,13 @@ export function getDefaultFormConfig() {
|
|
|
1045
1045
|
wfConfig: null,
|
|
1046
1046
|
wfStartBindSave: false,
|
|
1047
1047
|
wfStartConfirmText: null,
|
|
1048
|
+
// 「保存并提交流程」内建按钮:由 detail-item 渲染,只在新增页(dataId 为空)显示。
|
|
1049
|
+
// 按钮名不在此处配,统一由后台 wf_diy_attribute(param18) 下发,见 components/wf/wfButtonName.js
|
|
1050
|
+
saveSubmitEnabled: false,
|
|
1051
|
+
// 「提交流程」「保存并提交流程」共用的提交前置处理脚本:校验通过后、确认框之前执行
|
|
1052
|
+
onBeforeSubmitWf: null,
|
|
1053
|
+
// 「提交流程」按钮显隐脚本:return false 隐藏,不配则显示
|
|
1054
|
+
wfStartBtnShow: null,
|
|
1048
1055
|
wfAgreenBindSave: false,
|
|
1049
1056
|
wfAgreeConfigData: [],
|
|
1050
1057
|
wfConfigDataEnabled: false,
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<el-drawer v-bind="dialogConfig" @close="close" :visible.sync="showDialog">
|
|
3
|
-
<!-- host:"list" —— 承载列表宿主页(自带「常规(详情)/列表」页签),行点击进详情等行为与整页一致。
|
|
4
|
-
list.vue 根节点自带 #containt,本分支不再套 id,避免嵌套重复。 -->
|
|
5
|
-
<div class="cont fd-list-host" v-bind="bodyConfig" v-if="listHost">
|
|
6
|
-
<list-view-host :formCode="listFormCode" :param="dialogParam"/>
|
|
7
|
-
</div>
|
|
8
|
-
<div class="cont" v-bind="bodyConfig" id="containt" v-else>
|
|
9
|
-
<v-form-render :form-json.sync="formJson" :form-data="formData" :option-data="optionData" ref="vFormRef"
|
|
10
|
-
:reportTemplate.sync="formTemplate" :conditionParam.sync="conditionParam"
|
|
11
|
-
:formInsData.sync="formInsData" v-if="showRender" visible-key="showRender" :parent-target="_self"
|
|
12
|
-
@reload="reload" :param="dialogParam"
|
|
13
|
-
class="data-table_height" @hook:mounted="handleFormMounted"/>
|
|
14
|
-
</div>
|
|
15
|
-
<span class="dialog-footer" v-if="option.showFooter!==false" v-bind="option.footerConfig">
|
|
16
|
-
<el-button type="primary" plain class="button-sty" @click="close">
|
|
17
|
-
<i class="el-icon-close el-icon"></i>
|
|
18
|
-
{{ $t2('取 消', 'system.button.cancel2') }}
|
|
19
|
-
</el-button>
|
|
20
|
-
<!-- 模板配了 formConfig.actionButtons 时,用配置按钮替代「确定」(取消保持不变) -->
|
|
21
|
-
<template v-if="visibleFooterButtons">
|
|
22
|
-
<el-button v-for="btn in visibleFooterButtons" :key="btn.code" :type="btn.type || 'primary'"
|
|
23
|
-
:plain="btn.plain === true" class="button-sty" :loading="!!btnLoadingMap[btn.code]"
|
|
24
|
-
@click="handleActionButton(btn)">
|
|
25
|
-
<i v-if="btn.icon" :class="[btn.icon, 'el-icon']"></i>
|
|
26
|
-
{{ btnLabel(btn) }}
|
|
27
|
-
</el-button>
|
|
28
|
-
</template>
|
|
29
|
-
<el-button v-else type="primary" @click="dialogSubmit" class="button-sty">
|
|
30
|
-
<i class="el-icon-check el-icon"></i>
|
|
31
|
-
{{ $t2('确 定', 'system.button.confirm2') }}
|
|
32
|
-
</el-button>
|
|
33
|
-
</span>
|
|
34
|
-
</el-drawer>
|
|
35
|
-
</template>
|
|
36
|
-
|
|
37
|
-
<script>
|
|
38
|
-
import VFormRender from "../../../../../components/xform/form-render/index.vue";
|
|
39
|
-
import {
|
|
40
|
-
resolveActionButtons,
|
|
41
|
-
hasButtonPermission,
|
|
42
|
-
isButtonVisible,
|
|
43
|
-
runActionButton,
|
|
44
|
-
} from "@base/components/formDialog/actionButtons";
|
|
45
|
-
|
|
46
|
-
export default {
|
|
47
|
-
components: {
|
|
48
|
-
VFormRender,
|
|
49
|
-
// 列表宿主页(x-tabs:常规/列表/其他页签/多标签编辑),仅 host:"list" 时加载
|
|
50
|
-
ListViewHost: () =>
|
|
51
|
-
import(
|
|
52
|
-
/* webpackChunkName: "form-list-host" */ "@base/views/user/form/view/list.vue"
|
|
53
|
-
),
|
|
54
|
-
},
|
|
55
|
-
props: {
|
|
56
|
-
visiable: Boolean,
|
|
57
|
-
option: Object
|
|
58
|
-
},
|
|
59
|
-
mixins: [],
|
|
60
|
-
inject: ["getFormConfig"],
|
|
61
|
-
mounted() {
|
|
62
|
-
|
|
63
|
-
},
|
|
64
|
-
data() {
|
|
65
|
-
var that = this;
|
|
66
|
-
return {
|
|
67
|
-
showFormField: "_tt",
|
|
68
|
-
showDialog: true,
|
|
69
|
-
falseValue: false,
|
|
70
|
-
selectMulti: true,
|
|
71
|
-
|
|
72
|
-
formJson: {},
|
|
73
|
-
formData: {},
|
|
74
|
-
optionData: {},
|
|
75
|
-
showRender: false,
|
|
76
|
-
formTemplate: {},
|
|
77
|
-
/* formCode: null,*/
|
|
78
|
-
layoutType: null,
|
|
79
|
-
conditionParam: null,
|
|
80
|
-
formInsData: null,
|
|
81
|
-
$grid: null,
|
|
82
|
-
currentLayoutType: null,
|
|
83
|
-
// 模板 formConfig.actionButtons(权限过滤后);为空则底部保持默认「确定」
|
|
84
|
-
customButtons: null,
|
|
85
|
-
btnLoadingMap: {},
|
|
86
|
-
formRefMounted: false
|
|
87
|
-
};
|
|
88
|
-
},
|
|
89
|
-
computed: {
|
|
90
|
-
formCode() {
|
|
91
|
-
return this.option.formCode;
|
|
92
|
-
},
|
|
93
|
-
dialogParam() {
|
|
94
|
-
return this.option?.param;
|
|
95
|
-
},
|
|
96
|
-
// host:"list" —— 用列表宿主页承载(带「常规/列表」页签),而非直接渲染单个表单
|
|
97
|
-
listHost() {
|
|
98
|
-
return this.option?.host === "list";
|
|
99
|
-
},
|
|
100
|
-
listFormCode() {
|
|
101
|
-
return this.option?.formCode;
|
|
102
|
-
},
|
|
103
|
-
dialogConfig() {
|
|
104
|
-
let customClass = "dialog-style list-dialog dialog-checkbox pd_0";
|
|
105
|
-
if (this.option.dialogConfig?.customClass) {
|
|
106
|
-
customClass = customClass + " " + this.option.dialogConfig.customClass
|
|
107
|
-
}
|
|
108
|
-
let config = {
|
|
109
|
-
title: this.formTemplate.formName,
|
|
110
|
-
appendToBody: false,
|
|
111
|
-
// modalAppendToBody: true,
|
|
112
|
-
// closeOnClickModal: false,
|
|
113
|
-
modal: false,
|
|
114
|
-
destroyOnClose:true,
|
|
115
|
-
// width: "1200px",
|
|
116
|
-
// fullscreen: this.option.fullscreen,
|
|
117
|
-
size:"80%",
|
|
118
|
-
direction:"btt"
|
|
119
|
-
};
|
|
120
|
-
config = Object.assign({}, config, this.option.dialogConfig, {customClass});
|
|
121
|
-
config.title = this.$t1(config.title);
|
|
122
|
-
return config;
|
|
123
|
-
},
|
|
124
|
-
// 自定义按钮渲染列表:权限已在 initCustomButtons 过滤,此处按 visible 脚本过滤
|
|
125
|
-
visibleFooterButtons() {
|
|
126
|
-
if (!this.customButtons || !this.customButtons.length) return null;
|
|
127
|
-
this.formRefMounted; // eslint-disable-line no-unused-expressions
|
|
128
|
-
let buttons = this.customButtons.filter((btn) =>
|
|
129
|
-
isButtonVisible(btn, this.$refs.vFormRef)
|
|
130
|
-
);
|
|
131
|
-
return buttons.length ? buttons : null;
|
|
132
|
-
},
|
|
133
|
-
bodyConfig() {
|
|
134
|
-
let config = {};
|
|
135
|
-
let classStr = this.currentLayoutType
|
|
136
|
-
if (this.option.bodyConfig?.class) {
|
|
137
|
-
classStr = classStr + " " + this.option.bodyConfig.class;
|
|
138
|
-
}
|
|
139
|
-
if (this.option.showFooter == false) {
|
|
140
|
-
classStr = classStr + " nfootBtn";
|
|
141
|
-
}
|
|
142
|
-
config = Object.assign({}, config, this.option.bodyConfig, {class: classStr});
|
|
143
|
-
return config;
|
|
144
|
-
}
|
|
145
|
-
},
|
|
146
|
-
created() {
|
|
147
|
-
let currentFormConfig = this.getFormConfig();
|
|
148
|
-
this.currentLayoutType = currentFormConfig.layoutType
|
|
149
|
-
|
|
150
|
-
this.selectMulti = this.option.multiple ?? true;
|
|
151
|
-
// 列表宿主页自己会加载模板;仅在未指定标题时补取一次模板名做抽屉标题
|
|
152
|
-
if (this.listHost && this.option.dialogConfig?.title) return;
|
|
153
|
-
this.getReportTemplate();
|
|
154
|
-
},
|
|
155
|
-
methods: {
|
|
156
|
-
reload(){
|
|
157
|
-
this.showRender = false;
|
|
158
|
-
return this.getReportTemplate();
|
|
159
|
-
},
|
|
160
|
-
async getReportTemplate() {
|
|
161
|
-
let param = {
|
|
162
|
-
objTypeCode: this.$attrs.objTypeCode,
|
|
163
|
-
objId: this.$attrs.objId,
|
|
164
|
-
taskId: this.$attrs.taskId
|
|
165
|
-
};
|
|
166
|
-
this.conditionParam = param;
|
|
167
|
-
let url, data;
|
|
168
|
-
url = USER_PREFIX + `/formTemplate/getByFormCode`;
|
|
169
|
-
data = {stringOne: this.formCode}
|
|
170
|
-
|
|
171
|
-
let that = this;
|
|
172
|
-
return this.$http({
|
|
173
|
-
url: url,
|
|
174
|
-
method: `post`,
|
|
175
|
-
data: data,
|
|
176
|
-
isLoading: true,
|
|
177
|
-
loadingTarget: document.body,
|
|
178
|
-
modalStrictly: true,
|
|
179
|
-
success: res => {
|
|
180
|
-
let formTemplate = res.objx || {};
|
|
181
|
-
this.formTemplate = formTemplate;
|
|
182
|
-
// 列表宿主模式:只借模板名做标题,渲染与按钮均由宿主页自己负责
|
|
183
|
-
if (this.listHost) return;
|
|
184
|
-
this.formJson = formTemplate.formViewContent ? JSON.parse(formTemplate.formViewContent) : {};
|
|
185
|
-
this.layoutType = this.formJson.formConfig.layoutType
|
|
186
|
-
let formConfig = this.formJson.formConfig;
|
|
187
|
-
if (formConfig.searchDialogUniqueField) {
|
|
188
|
-
this.fieldKey = formConfig.searchDialogUniqueField;
|
|
189
|
-
}
|
|
190
|
-
this.initCustomButtons(formConfig);
|
|
191
|
-
|
|
192
|
-
this.showRender = true;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
},
|
|
198
|
-
// 模板 actionButtons:option.buttons 可覆盖;权限 formCode:authName 在此一次性过滤
|
|
199
|
-
initCustomButtons(formConfig) {
|
|
200
|
-
let buttons = resolveActionButtons(this.option?.buttons, formConfig);
|
|
201
|
-
this.customButtons = buttons
|
|
202
|
-
? buttons.filter((btn) => hasButtonPermission(btn, this.formCode, this))
|
|
203
|
-
: null;
|
|
204
|
-
},
|
|
205
|
-
handleFormMounted() {
|
|
206
|
-
this.formRefMounted = true;
|
|
207
|
-
},
|
|
208
|
-
btnLabel(btn) {
|
|
209
|
-
return this.$t1 ? this.$t1(btn.label) : btn.label;
|
|
210
|
-
},
|
|
211
|
-
/**
|
|
212
|
-
* 自定义按钮点击:校验 → onClick 脚本 → done/closeAfter 收口。
|
|
213
|
-
* 收口时优先回调 option.onAction(payload, formRef, vm);
|
|
214
|
-
* 未提供则仅按 closeAfter 关闭(按钮自身脚本即业务处理,不再走 option.confirm)。
|
|
215
|
-
*/
|
|
216
|
-
handleActionButton(btn) {
|
|
217
|
-
let formRef = this.$refs.vFormRef;
|
|
218
|
-
if (!formRef || this.btnLoadingMap[btn.code]) return;
|
|
219
|
-
this.$set(this.btnLoadingMap, btn.code, true);
|
|
220
|
-
let clearLoading = () => this.$set(this.btnLoadingMap, btn.code, false);
|
|
221
|
-
runActionButton(btn, {
|
|
222
|
-
formRef,
|
|
223
|
-
host: this,
|
|
224
|
-
getSelection: () => [],
|
|
225
|
-
onSettle: (payload, close) => {
|
|
226
|
-
if (typeof this.option.onAction === "function") {
|
|
227
|
-
this.option.onAction(payload, formRef, this);
|
|
228
|
-
}
|
|
229
|
-
if (close) this.close();
|
|
230
|
-
},
|
|
231
|
-
}).then(clearLoading, clearLoading);
|
|
232
|
-
},
|
|
233
|
-
close() {
|
|
234
|
-
let formRef = this.$refs.vFormRef;
|
|
235
|
-
this.showDialog = false;
|
|
236
|
-
this.$emit('update:visiable', false);
|
|
237
|
-
this.option.close && this.option.close(formRef, this);
|
|
238
|
-
},
|
|
239
|
-
dialogSubmit() {
|
|
240
|
-
let formRef = this.$refs.vFormRef;
|
|
241
|
-
if (this.option.confirm) {
|
|
242
|
-
if (this.option.confirm(formRef, this) !== false) {
|
|
243
|
-
this.close();
|
|
244
|
-
}
|
|
245
|
-
} else {
|
|
246
|
-
this.close();
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
</script>
|
|
252
|
-
|
|
253
|
-
<style lang="scss" scoped>
|
|
254
|
-
::v-deep .H5 .h5-fixed-bottom-btns {
|
|
255
|
-
bottom: 95px;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
.list-dialog {
|
|
259
|
-
.el-dialog__body {
|
|
260
|
-
height: calc(100% - 42px);
|
|
261
|
-
|
|
262
|
-
// host:"list":.cont 已有确定高度,把它传给 list.vue 根节点 #containt,
|
|
263
|
-
// .tab-box 自身是 height:100%,父链没高度页签内容区会塌成一条
|
|
264
|
-
.cont.fd-list-host {
|
|
265
|
-
padding: 0;
|
|
266
|
-
|
|
267
|
-
::v-deep > #containt {
|
|
268
|
-
height: 100%;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
.cont {
|
|
273
|
-
height: calc(100vh - 210px);
|
|
274
|
-
|
|
275
|
-
&.nfootBtn {
|
|
276
|
-
height: calc(100vh - 158px)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
&#containt {
|
|
280
|
-
padding: 0;
|
|
281
|
-
|
|
282
|
-
::v-deep .grid-container {
|
|
283
|
-
outline: none;
|
|
284
|
-
|
|
285
|
-
&.detail-wrap .d-cont {
|
|
286
|
-
//height: calc(100vh - 150px);
|
|
287
|
-
|
|
288
|
-
.title .field-wrapper {
|
|
289
|
-
display: inline-block !important
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
&.is-fullscreen .el-dialog__body {
|
|
298
|
-
.cont {
|
|
299
|
-
height: calc(100vh - 110px);
|
|
300
|
-
|
|
301
|
-
&.nfootBtn {
|
|
302
|
-
height: calc(100vh - var(--xform-dialog-body-offset, 58px))
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
</style>
|