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.
Files changed (22) hide show
  1. package/package.json +1 -1
  2. package/src/components/formDialog/README.md +32 -6
  3. package/src/components/luckysheet/dialog.vue +1 -1
  4. package/src/components/wf/wfButtonName.js +60 -0
  5. package/src/components/xform/form-designer/designer.js +2 -1
  6. package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +65 -29
  7. package/src/components/xform/form-designer/form-widget/field-widget/save_submit_wf_button-widget.vue +3 -0
  8. package/src/components/xform/form-designer/setting-panel/form-setting.vue +103 -8
  9. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/addTableData-event-editor.vue +0 -1
  10. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/clickBindActions.js +253 -0
  11. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/clickBindEvent-editor.vue +49 -40
  12. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/form-host-event-editor.vue +175 -0
  13. package/src/components/xform/form-designer/setting-panel/property-editor/field-button/search-dialog-event-editor.vue +20 -5
  14. package/src/components/xform/form-designer/widget-panel/indexMixin.js +2 -1
  15. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +3 -0
  16. package/src/components/xform/form-render/container-item/detail-item.vue +116 -3
  17. package/src/components/xform/form-render/index.vue +0 -7
  18. package/src/components/xform/form-render/indexMixin.js +60 -8
  19. package/src/components/xform/mixins/defaultHandle.js +21 -1
  20. package/src/components/xform/utils/util.js +7 -0
  21. package/src/views/bd/setting/formVersion/ftHistoryDialog.vue +2 -0
  22. 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.$t2("流程启动", "components.wf.wfStart")
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
- return opt.showStartBtn !== false && !ws.hasWf;
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
- openStartWfDialog(ws.ctx, ws.option);
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
- openFormDrawer(option) {
4873
- this.formDrawerOption = option;
4874
- this.showFormDrawer = true;
4875
- },
4876
- confirmFormDrawer() {
4877
- this.formDrawerOption.confirm && this.formDrawerOption.confirm();
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
- this.$t1("您确定要保存并提交流程吗?");
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,
@@ -326,6 +326,8 @@ export default {
326
326
  return {
327
327
  ...this.formData,
328
328
  objType: this.objType,
329
+ objCode: this.objCode,
330
+ relationCode: this.relationCode,
329
331
  sid: this.sid,
330
332
  };
331
333
  },
@@ -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>