cloud-web-corejs 1.0.54-dev.786 → 1.0.54-dev.787

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 (121) hide show
  1. package/package.json +2 -1
  2. package/src/components/VabUpload/index.vue +1 -1
  3. package/src/components/excelImport/index.js +69 -7
  4. package/src/components/excelImport/mixins.js +841 -9
  5. package/src/components/fileLibrary/fileHistoryDialog.vue +1 -1
  6. package/src/components/fileLibrary/fileObjAuthEdit.vue +1 -1
  7. package/src/components/fileLibrary/filterDialog.vue +1 -1
  8. package/src/components/formDialog/README.md +324 -241
  9. package/src/components/formDialog/actionButtons.js +90 -0
  10. package/src/components/formDialog/index.js +48 -35
  11. package/src/components/formDialog/index.vue +802 -724
  12. package/src/components/formDrawer/drawer.vue +719 -0
  13. package/src/components/formDrawer/index.js +50 -0
  14. package/src/components/onlineTalk/talkUserDialog.vue +1 -1
  15. package/src/components/tempStorage/tempStorageDialog.vue +1 -1
  16. package/src/components/wf/addTaskUserdialog.vue +1 -1
  17. package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +1 -1
  18. package/src/components/xform/form-designer/form-widget/dialog/formDialog.vue +115 -4
  19. package/src/components/xform/form-designer/form-widget/dialog/formDrawer.vue +102 -5
  20. package/src/components/xform/form-designer/form-widget/dialog/formFieldDialog.vue +1 -1
  21. package/src/components/xform/form-designer/form-widget/dialog/vabSearchDialog.vue +1 -1
  22. package/src/components/xform/form-designer/setting-panel/action-button-config-dialog.vue +241 -0
  23. package/src/components/xform/form-designer/setting-panel/form-setting.vue +116 -0
  24. package/src/components/xform/form-designer/setting-panel/property-editor/container-detail/detail-editor.vue +6 -0
  25. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +1 -0
  26. package/src/components/xform/form-render/container-item/data-table-mixin.js +1460 -1460
  27. package/src/components/xform/form-render/container-item/detail-item.vue +11 -2
  28. package/src/components/xform/form-render/indexMixin.js +5 -0
  29. package/src/index.js +506 -472
  30. package/src/utils/lazyPlugin.js +66 -0
  31. package/src/views/bd/setting/bd_attach_setting/dialog.vue +1 -1
  32. package/src/views/bd/setting/bd_attach_setting/list.vue +1 -1
  33. package/src/views/bd/setting/bd_company_env/dialog.vue +1 -1
  34. package/src/views/bd/setting/bd_company_env/list.vue +1 -1
  35. package/src/views/bd/setting/formVersion/ftHistoryDialog.vue +1 -1
  36. package/src/views/bd/setting/form_import_log/list.vue +1 -1
  37. package/src/views/bd/setting/form_script/dialog.vue +1 -1
  38. package/src/views/bd/setting/form_script/form_list.vue +1 -1
  39. package/src/views/bd/setting/form_script/list.vue +1 -1
  40. package/src/views/bd/setting/form_script/list1.vue +1 -1
  41. package/src/views/bd/setting/form_template/dialog.vue +1 -1
  42. package/src/views/bd/setting/form_template/ftHistoryDialog.vue +1 -1
  43. package/src/views/bd/setting/form_template/itemList.vue +1 -1
  44. package/src/views/bd/setting/form_template/list.vue +1 -1
  45. package/src/views/bd/setting/form_template/wf_list.vue +1 -1
  46. package/src/views/bd/setting/logic_param/list.vue +1 -1
  47. package/src/views/bd/setting/menu_kind/dialog.vue +1 -1
  48. package/src/views/bd/setting/menu_kind/list.vue +1 -1
  49. package/src/views/bd/setting/push_data/list.vue +1 -1
  50. package/src/views/bd/setting/push_data_h/list.vue +1 -1
  51. package/src/views/bd/setting/request_async_setting/list.vue +1 -1
  52. package/src/views/bd/setting/request_setting/list.vue +1 -1
  53. package/src/views/bd/setting/table_model/dialog.vue +1 -1
  54. package/src/views/bd/setting/table_model/list.vue +1 -1
  55. package/src/views/bd/setting/table_model/zdDialog.vue +1 -1
  56. package/src/views/support/export_template/list.vue +1 -1
  57. package/src/views/user/access_log/list.vue +1 -1
  58. package/src/views/user/access_log/list2.vue +1 -1
  59. package/src/views/user/api_request/list.vue +1 -1
  60. package/src/views/user/area/dialog.vue +1 -1
  61. package/src/views/user/area/list.vue +1 -1
  62. package/src/views/user/bill_setting/list.vue +1 -1
  63. package/src/views/user/bill_setting/userDialog.vue +1 -1
  64. package/src/views/user/code_rules/list.vue +1 -1
  65. package/src/views/user/common_attribute/list.vue +1 -1
  66. package/src/views/user/common_script/list.vue +1 -1
  67. package/src/views/user/company_info/dialog.vue +1 -1
  68. package/src/views/user/country/dialog.vue +1 -1
  69. package/src/views/user/country/list.vue +1 -1
  70. package/src/views/user/data_type_setting/dialog.vue +1 -1
  71. package/src/views/user/extend_datasource/dialog.vue +1 -1
  72. package/src/views/user/extend_datasource/list.vue +1 -1
  73. package/src/views/user/fieldTranslation/list.vue +1 -1
  74. package/src/views/user/field_values_invisible/list.vue +1 -1
  75. package/src/views/user/file_type/list.vue +1 -1
  76. package/src/views/user/file_view_area/list.vue +1 -1
  77. package/src/views/user/form/form_template/dialog.vue +1 -1
  78. package/src/views/user/form/form_template/itemList.vue +1 -1
  79. package/src/views/user/form/form_template/list.vue +1 -1
  80. package/src/views/user/form/form_template_field/dialog.vue +1 -1
  81. package/src/views/user/form/form_type/dialog.vue +1 -1
  82. package/src/views/user/form/form_type/list.vue +1 -1
  83. package/src/views/user/form/report_requestaccess/dialog.vue +1 -1
  84. package/src/views/user/form/report_requestaccess/list.vue +1 -1
  85. package/src/views/user/groups/dialog.vue +1 -1
  86. package/src/views/user/groups/list.vue +1 -1
  87. package/src/views/user/lang_tag/dialog.vue +1 -1
  88. package/src/views/user/lang_tag/list.vue +1 -1
  89. package/src/views/user/language_setting/list.vue +1 -1
  90. package/src/views/user/menu/list.vue +1 -1
  91. package/src/views/user/mobile_menu/list.vue +1 -1
  92. package/src/views/user/notify_message/list.vue +1 -1
  93. package/src/views/user/notify_template/list.vue +1 -1
  94. package/src/views/user/notify_template/list2.vue +1 -1
  95. package/src/views/user/oplog/list.vue +1 -1
  96. package/src/views/user/position/dialog.vue +1 -1
  97. package/src/views/user/position/list.vue +1 -1
  98. package/src/views/user/project_tag/dialog.vue +1 -1
  99. package/src/views/user/project_tag/list.vue +1 -1
  100. package/src/views/user/push_setting/list.vue +1 -1
  101. package/src/views/user/request_setting/list.vue +1 -1
  102. package/src/views/user/role/dialog.vue +1 -1
  103. package/src/views/user/role/list.vue +1 -1
  104. package/src/views/user/sale_org/dialog.vue +1 -1
  105. package/src/views/user/sale_org/list.vue +1 -1
  106. package/src/views/user/system_notice/list.vue +1 -1
  107. package/src/views/user/system_parameter/list.vue +1 -1
  108. package/src/views/user/user/dialog.vue +1 -1
  109. package/src/views/user/user/form_dialog.vue +1 -1
  110. package/src/views/user/user/form_list.vue +1 -1
  111. package/src/views/user/user/list.vue +2 -2
  112. package/src/views/user/user_log_classify/list.vue +1 -1
  113. package/src/views/user/wf/wfReport/index.vue +2 -2
  114. package/src/views/user/wf/wf_auto_submit_data/list.vue +2 -2
  115. package/src/views/user/wf/wf_manage/list.vue +2 -2
  116. package/src/views/user/wf/wf_manage/list2.vue +2 -2
  117. package/src/views/user/wf/wf_obj_config/dialog.vue +1 -1
  118. package/src/views/user/wf/wf_obj_config/list.vue +1 -1
  119. package/src/views/user/wf/wf_obj_config/list_form.vue +1 -1
  120. package/src/views/user/wf/wf_transfer_setting/list.vue +1 -1
  121. package/src/views/user/workbench_menu/list.vue +1 -1
@@ -0,0 +1,719 @@
1
+ <template>
2
+ <el-drawer
3
+ v-bind="drawerConfig"
4
+ :visible.sync="showWrap"
5
+ @close="handleClose"
6
+ @closed="handleClosed"
7
+ >
8
+ <div class="fd-wrap">
9
+ <div
10
+ class="fd-cont"
11
+ v-loading="xformLoading"
12
+ :class="{ 'fd-cont--plain': plain, 'fd-cont--fill': fillHeight }"
13
+ >
14
+ <!--
15
+ designer-view + #containt 是全站渲染态样式挂载的两个钩子
16
+ (style.scss 的 `#containt .detail-wrap{...}` 与 `.preview-dialog,.designer-view{...}` 两大块),
17
+ render.vue / xform formDialog 都套了这层。抽屉不套就会丢:
18
+ 详情头右侧按钮的 inline-block(会竖排换行)、.d-item 右侧 112px 的导航占位
19
+ (导航会盖住数据表格)、.detail-wrap 的 position:relative(导航挂到 el-drawer 上被裁掉)、
20
+ 模块边框内边距。
21
+ -->
22
+ <!-- host:"list" —— 承载列表宿主页(自带「常规(详情)/列表」页签),行点击进详情、
23
+ 多标签编辑等行为与整页一致。list.vue 根节点自带 #containt,此处只补 designer-view,
24
+ 避免与下面的包裹层撞 id。抽屉只作视口,不接管其按钮。 -->
25
+ <div class="designer-view fd-list-host" v-if="listHost">
26
+ <list-view-host
27
+ ref="listHostRef"
28
+ :formCode="listFormCode"
29
+ :param="drawerParam"
30
+ />
31
+ </div>
32
+ <div id="containt" class="designer-view" v-else>
33
+ <v-form-render
34
+ v-if="showRender"
35
+ ref="vFormRef"
36
+ :class="fillHeight ? 'data-table_height' : ''"
37
+ :form-json="formJson"
38
+ :form-data="formData"
39
+ :option-data="optionData"
40
+ :global-dsv="globalDsv"
41
+ :report-template="formTemplate"
42
+ :data-id="dataId"
43
+ :conditionParam.sync="conditionParam"
44
+ :param="drawerParam"
45
+ :dataTableOption="selectMode ? dataTableOption : undefined"
46
+ :plain-detail-mode="plain"
47
+ :parent-target="_self"
48
+ visible-key="showRender"
49
+ @reload="reload"
50
+ @hook:mounted="handleXformMounted"
51
+ />
52
+ </div>
53
+ </div>
54
+ <!-- select 多选:已选清单条 -->
55
+ <div class="fd-checked" v-if="selectMode && selectMulti && showRender">
56
+ <el-tooltip
57
+ :enterable="false"
58
+ effect="dark"
59
+ :content="$t1('全部删除')"
60
+ placement="top"
61
+ >
62
+ <a class="allDel icon-quanbushanchu" @click="clearChecked()"></a>
63
+ </el-tooltip>
64
+ <div class="list">
65
+ <div
66
+ class="item"
67
+ v-for="(checkRow, index) in checkRows"
68
+ :key="'c' + index"
69
+ >
70
+ <p>{{ checkRow[showFormField] }}</p>
71
+ <a class="el-icon-close" @click="clearTable1Select(index)"></a>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ <div class="fd-footer dialog-footer" v-if="showFooter">
76
+ <span class="fl tips" v-if="selectMode && !selectMulti">{{
77
+ $t1("注:双击确认选择(单选)")
78
+ }}</span>
79
+ <template v-if="readonly">
80
+ <el-button type="primary" class="button-sty" @click="showWrap = false"
81
+ ><i class="el-icon-close el-icon"></i
82
+ >{{ $t2("关 闭", "system.button.close2") }}</el-button
83
+ >
84
+ </template>
85
+ <!-- 自定义按钮(formConfig.actionButtons / options.buttons):固定取消 + 配置按钮 -->
86
+ <template v-else-if="visibleFooterButtons">
87
+ <el-button
88
+ type="primary"
89
+ plain
90
+ class="button-sty"
91
+ @click="showWrap = false"
92
+ ><i class="el-icon-close el-icon"></i
93
+ >{{ $t2("取 消", "system.button.cancel2") }}</el-button
94
+ >
95
+ <el-button
96
+ v-for="btn in visibleFooterButtons"
97
+ :key="btn.code"
98
+ :type="btn.type || 'primary'"
99
+ :plain="btn.plain === true"
100
+ class="button-sty"
101
+ :loading="!!btnLoadingMap[btn.code]"
102
+ @click="handleActionButton(btn)"
103
+ ><i v-if="btn.icon" :class="[btn.icon, 'el-icon']"></i
104
+ >{{ btnLabel(btn) }}</el-button
105
+ >
106
+ </template>
107
+ <template v-else>
108
+ <el-button
109
+ type="primary"
110
+ plain
111
+ class="button-sty"
112
+ @click="showWrap = false"
113
+ ><i class="el-icon-close el-icon"></i
114
+ >{{ $t2("取 消", "system.button.cancel2") }}</el-button
115
+ >
116
+ <el-button
117
+ type="primary"
118
+ class="button-sty"
119
+ :loading="confirmLoading"
120
+ @click="handleConfirm"
121
+ ><i class="el-icon-check el-icon"></i
122
+ >{{ $t2("确 定", "system.button.confirm2") }}</el-button
123
+ >
124
+ </template>
125
+ </div>
126
+ </div>
127
+ </el-drawer>
128
+ </template>
129
+
130
+ <script>
131
+ import {
132
+ resolveActionButtons,
133
+ hasButtonPermission,
134
+ isButtonVisible,
135
+ runActionButton,
136
+ } from "../formDialog/actionButtons";
137
+ import { traverseAllWidgetsNew } from "../xform/utils/util";
138
+
139
+ export default {
140
+ name: "formCodeDrawer",
141
+ components: {
142
+ // 列表宿主页(x-tabs:常规/列表/其他页签/多标签编辑),仅 host:"list" 时加载
143
+ ListViewHost: () =>
144
+ import(
145
+ /* webpackChunkName: "form-list-host" */ "@base/views/user/form/view/list.vue"
146
+ ),
147
+ // xform 渲染器按需加载(与 formDialog 共享同一 chunk),加载前先注册 xform 扩展控件
148
+ VFormRender: () =>
149
+ import("@base/components/xform/extension/extension-loader").then(
150
+ (ext) => {
151
+ ext.loadExtension();
152
+ return import("@base/components/xform/form-render/index.vue");
153
+ }
154
+ ),
155
+ },
156
+ data() {
157
+ return {
158
+ // open() 传入的完整 options(响应式,drawerConfig 等依赖它)
159
+ openOptions: {},
160
+ title: "",
161
+ showWrap: false,
162
+ showRender: false,
163
+ xformLoading: false,
164
+ confirmLoading: false,
165
+ readonly: false,
166
+ plain: false,
167
+ showFooter: true,
168
+ formJson: {},
169
+ formData: {},
170
+ optionData: {},
171
+ globalDsv: {},
172
+ formTemplate: {},
173
+ // 详情单据 id:xform 的 loadDefaultEntityData 依赖它(entity && dataId && scriptCode 才加载)
174
+ dataId: null,
175
+ conditionParam: null,
176
+ // select 模式(查询表格选择)
177
+ selectMode: false,
178
+ selectMulti: true,
179
+ checkRows: [],
180
+ fieldKey: "id",
181
+ showFormField: "_tt",
182
+ // 自定义按钮
183
+ customButtons: null,
184
+ btnLoadingMap: {},
185
+ formRefMounted: false,
186
+ // PC 专用(不支持 H5):选择行为注入 data-table
187
+ dataTableOption: null,
188
+ $grid: null,
189
+ };
190
+ },
191
+ computed: {
192
+ drawerConfig() {
193
+ let customClass = "drawer-style list-drawer form-code-drawer";
194
+ const opt = this.openOptions || {};
195
+ if (this.plain) customClass += " form-code-drawer--plain";
196
+ if (opt.customClass) customClass += " " + opt.customClass;
197
+ const config = {
198
+ title: this.$t1 ? this.$t1(this.title) : this.title,
199
+ // 列表宿主页里还要能进详情,默认给宽一点
200
+ size: opt.size || (this.listHost ? "85%" : "62%"),
201
+ direction: opt.direction || "rtl",
202
+ appendToBody: true,
203
+ wrapperClosable: false,
204
+ ...opt.drawerConfig,
205
+ customClass,
206
+ };
207
+ return config;
208
+ },
209
+ drawerParam() {
210
+ return (this.openOptions && this.openOptions.param) || undefined;
211
+ },
212
+ // host:"list" —— 用列表宿主页承载(带「常规/列表」页签),而非直接渲染单个表单
213
+ listHost() {
214
+ return (this.openOptions || {}).host === "list";
215
+ },
216
+ listFormCode() {
217
+ return (this.openOptions || {}).formCode;
218
+ },
219
+ /**
220
+ * 列表型模板(顶层唯一控件是查询表格)时撑满抽屉高度。
221
+ * 查询表格的 vxe-grid 用 height="auto",是按父元素实测高度算的,
222
+ * 父链(渲染器根 div → el-form)没有确定高度就会塌成一小块。
223
+ * 弹框里靠全局 .dialog-style .el-dialog__body .data-table_height 兜住,
224
+ * 抽屉不在该选择器下,需要本组件自己给这条链补高度。
225
+ * options.fillHeight 可强制开/关。
226
+ */
227
+ fillHeight() {
228
+ const opt = this.openOptions || {};
229
+ if (typeof opt.fillHeight === "boolean") return opt.fillHeight;
230
+ // 列表宿主页(页签 + 内部表格)必须撑满,否则页签内容区塌陷
231
+ if (this.listHost) return true;
232
+ const list = (this.formJson && this.formJson.widgetList) || [];
233
+ return (
234
+ list.length === 1
235
+ && list[0].type === "data-table"
236
+ && (list[0].options || {}).isQueryTable === true
237
+ );
238
+ },
239
+ // 自定义按钮渲染列表:权限已在 initCustomButtons 过滤,此处按 visible 脚本过滤
240
+ visibleFooterButtons() {
241
+ if (!this.customButtons || !this.customButtons.length) return null;
242
+ this.formRefMounted; // eslint-disable-line no-unused-expressions
243
+ const buttons = this.customButtons.filter((btn) =>
244
+ isButtonVisible(btn, this.$refs.vFormRef)
245
+ );
246
+ return buttons.length ? buttons : null;
247
+ },
248
+ },
249
+ methods: {
250
+ /**
251
+ * 打开抽屉。options 见 formDialog/README.md「$formDrawer」一节。
252
+ * resolve:默认按钮下 select 模式返回选中行数组、表单模式返回表单数据;
253
+ * 自定义按钮返回 {action, data};取消/关闭返回 null。
254
+ */
255
+ open(options = {}) {
256
+ this.openOptions = options;
257
+ this.title = options.title || "";
258
+ this.readonly = options.readonly === true;
259
+ this.plain = options.plain === true;
260
+ // 列表宿主页自带按钮区,抽屉底部默认不占地方(显式传 showFooter:true 才出)
261
+ this.showFooter = this.listHost
262
+ ? options.showFooter === true
263
+ : options.showFooter !== false;
264
+ this.formData = options.model || options.formData || {};
265
+ this.dataId = options.dataId != null ? options.dataId : null;
266
+ this.optionData = options.optionData || {};
267
+ this.globalDsv = options.globalDsv || {};
268
+ this.conditionParam = options.conditionParam || {};
269
+ this._beforeConfirm = options.beforeConfirm;
270
+ this._onReady = options.onReady;
271
+ this._callerButtons = Array.isArray(options.buttons)
272
+ ? options.buttons
273
+ : null;
274
+ this._settled = false;
275
+
276
+ const select = options.select;
277
+ this.selectMode = !!select;
278
+ if (select) {
279
+ this.selectMulti = select.multiple !== false;
280
+ this.checkRows = this.$baseLodash.cloneDeep(select.rows || []);
281
+ if (select.fieldKey) this.fieldKey = select.fieldKey;
282
+ this._selectOption = select;
283
+ this.initDataTableOption(select);
284
+ }
285
+
286
+ this.showWrap = true;
287
+ if (this.listHost) {
288
+ // 列表宿主页自己会加载模板;这里只在未指定标题时补取一次模板名,避免重复请求
289
+ if (!this.title) this.loadTemplate(options.formCode, true);
290
+ } else {
291
+ this.loadTemplate(options.formCode);
292
+ }
293
+ return new Promise((resolve) => {
294
+ this._resolve = resolve;
295
+ });
296
+ },
297
+ // 选择行为注入 data-table(搬自 searchFormDialog,仅 PC 分支)
298
+ initDataTableOption(select) {
299
+ this.dataTableOption = {
300
+ class: "is-pointer",
301
+ queryFormDialog: true,
302
+ queryParam: select.queryParam || undefined,
303
+ onCheckboxChange: (param) => this.addDataTable(param),
304
+ onCheckboxAll: (param) => this.checkAll(param),
305
+ onCellDblclick: (param) => this.checkWithSubmit(param),
306
+ // 数据刷新后回勾已选行
307
+ callback: () => {
308
+ if (this.checkRows.length) {
309
+ const $grid = this.getGrid();
310
+ const datas = $grid.getTableData().tableData;
311
+ const fieldKey = this.fieldKey;
312
+ this.checkRows.forEach((checkRow) => {
313
+ const row = datas.find(
314
+ (item) => item[fieldKey] == checkRow[fieldKey]
315
+ );
316
+ if (row) $grid.setCheckboxRow(row, true);
317
+ });
318
+ }
319
+ },
320
+ otherConfig: {
321
+ onFilter: () => {
322
+ this.checkRows = [];
323
+ },
324
+ },
325
+ config: {
326
+ checkboxConfig: {
327
+ checkStrictly: true,
328
+ showHeader: this.selectMulti,
329
+ trigger: "row",
330
+ },
331
+ },
332
+ };
333
+ },
334
+ reload() {
335
+ this.showRender = false;
336
+ return this.loadTemplate(this.openOptions && this.openOptions.formCode);
337
+ },
338
+ /**
339
+ * 与 formDialog xform 模式同链路:formTemplate/getByFormCode 取模板 JSON。
340
+ * @param {Boolean} titleOnly host:"list" 时只借模板名做抽屉标题,
341
+ * 渲染与按钮都由列表宿主页自己负责,不在此处初始化。
342
+ */
343
+ loadTemplate(formCode, titleOnly) {
344
+ if (!formCode) {
345
+ this.$message.error("formCode 不能为空");
346
+ return;
347
+ }
348
+ this.xformLoading = true;
349
+ this.$http({
350
+ aes: true,
351
+ url: USER_PREFIX + "/formTemplate/getByFormCode",
352
+ method: "post",
353
+ data: { stringOne: formCode },
354
+ isLoading: false,
355
+ success: (res) => {
356
+ this.xformLoading = false;
357
+ const template = res.objx || {};
358
+ const formJson = template.formViewContent
359
+ ? JSON.parse(template.formViewContent)
360
+ : {};
361
+ if (!formJson || !formJson.formConfig) {
362
+ this.$message.error(
363
+ `${this.$t2(
364
+ "表单模板不存在或内容为空",
365
+ "system.message.formTemplateEmpty"
366
+ )}: ${formCode || ""}`
367
+ );
368
+ return;
369
+ }
370
+ this.formTemplate = template;
371
+ if (!this.title) {
372
+ this.title = template.formName || template.name || "";
373
+ }
374
+ if (titleOnly) return;
375
+ this.formJson = formJson;
376
+ const formConfig = formJson.formConfig;
377
+ if (this.selectMode && !this._selectOption.fieldKey) {
378
+ this.fieldKey = formConfig.searchDialogUniqueField || this.fieldKey;
379
+ }
380
+ if (this.selectMode) {
381
+ this.initShowFormField();
382
+ }
383
+ this.initCustomButtons(formConfig, formCode);
384
+ this.showRender = true;
385
+ },
386
+ });
387
+ },
388
+ // 自定义按钮:调用方 buttons 覆盖模板 actionButtons;权限(formCode:authName)一次性过滤
389
+ initCustomButtons(formConfig, formCode) {
390
+ const buttons = resolveActionButtons(this._callerButtons, formConfig);
391
+ this.customButtons = buttons
392
+ ? buttons.filter((btn) => hasButtonPermission(btn, formCode, this))
393
+ : null;
394
+ },
395
+ handleXformMounted() {
396
+ const formRef = this.$refs.vFormRef;
397
+ if (!formRef) return;
398
+ if (this.readonly) {
399
+ formRef.setReadMode(true);
400
+ }
401
+ this.formRefMounted = true;
402
+ if (typeof this._onReady === "function") {
403
+ this._onReady(formRef, this);
404
+ }
405
+ },
406
+ btnLabel(btn) {
407
+ return this.$t1 ? this.$t1(btn.label) : btn.label;
408
+ },
409
+ handleActionButton(btn) {
410
+ const formRef = this.$refs.vFormRef;
411
+ if (!formRef || this.btnLoadingMap[btn.code]) return;
412
+ this.$set(this.btnLoadingMap, btn.code, true);
413
+ const clearLoading = () => this.$set(this.btnLoadingMap, btn.code, false);
414
+ runActionButton(btn, {
415
+ formRef,
416
+ host: this,
417
+ getSelection: () => this.checkRows,
418
+ onSettle: (payload, close) => {
419
+ this.settle(payload);
420
+ if (close) this.showWrap = false;
421
+ },
422
+ }).then(clearLoading, clearLoading);
423
+ },
424
+ // 默认确定:select 模式返回选中行;表单模式走 xform 校验返回表单数据
425
+ handleConfirm() {
426
+ if (this.selectMode) {
427
+ const rows = this.checkRows;
428
+ const select = this._selectOption || {};
429
+ if (typeof select.onConfirm === "function") {
430
+ if (select.onConfirm(rows, this.$refs.vFormRef, this) === false) {
431
+ return;
432
+ }
433
+ }
434
+ this.settle(rows);
435
+ this.showWrap = false;
436
+ return;
437
+ }
438
+ const formRef = this.$refs.vFormRef;
439
+ if (!formRef) return;
440
+ formRef.validateForm((valid) => {
441
+ if (!valid) return;
442
+ this.confirmWithData(
443
+ this.$baseLodash.cloneDeep(formRef.getFormData(false))
444
+ );
445
+ });
446
+ },
447
+ confirmWithData(data) {
448
+ if (typeof this._beforeConfirm === "function") {
449
+ this.confirmLoading = true;
450
+ Promise.resolve()
451
+ .then(() => this._beforeConfirm(data))
452
+ .then(() => {
453
+ this.confirmLoading = false;
454
+ this.settle(data);
455
+ this.showWrap = false;
456
+ })
457
+ .catch(() => {
458
+ // beforeConfirm 失败时不关闭,由调用方自行提示错误
459
+ this.confirmLoading = false;
460
+ });
461
+ } else {
462
+ this.settle(data);
463
+ this.showWrap = false;
464
+ }
465
+ },
466
+ /* ------- select 模式表格操作(搬自 searchFormDialog,仅 PC) ------- */
467
+ getDataTableWidget() {
468
+ let result = null;
469
+ traverseAllWidgetsNew(this.formJson.widgetList, (widget) => {
470
+ if (!result && widget.type == "data-table") {
471
+ result = widget;
472
+ }
473
+ });
474
+ return result;
475
+ },
476
+ getGrid() {
477
+ if (!this.$grid) {
478
+ const dataTableWidget = this.getDataTableWidget();
479
+ this.$grid = this.$refs.vFormRef
480
+ .getWidgetRef(dataTableWidget.options.name)
481
+ .getGridTable();
482
+ }
483
+ return this.$grid;
484
+ },
485
+ initShowFormField() {
486
+ const showFormField
487
+ = this.formJson.formConfig.searchDialogNameField || null;
488
+ if (!showFormField) {
489
+ const dataTableWidget = this.getDataTableWidget();
490
+ if (dataTableWidget) {
491
+ const column = (dataTableWidget.options.tableColumns || []).find(
492
+ (col) => !!col.prop
493
+ );
494
+ if (column) this.showFormField = column.prop;
495
+ }
496
+ } else {
497
+ this.showFormField = showFormField;
498
+ }
499
+ },
500
+ addDataTable(obj) {
501
+ const fieldKey = this.fieldKey;
502
+ const row = obj.row;
503
+ const $table1 = obj.$table;
504
+ if (this.selectMulti) {
505
+ const rows = this.checkRows;
506
+ if (obj.checked) {
507
+ const flag = rows.some((item) => row[fieldKey] == item[fieldKey]);
508
+ if (!flag) rows.push(obj.row);
509
+ } else {
510
+ const rowid = obj.row[fieldKey];
511
+ const delIndex = rows.findIndex(
512
+ (item) => item[fieldKey] == rowid
513
+ );
514
+ if (delIndex > -1) rows.splice(delIndex, 1);
515
+ }
516
+ } else {
517
+ $table1.clearCheckboxRow();
518
+ $table1.setCheckboxRow(obj.row, true);
519
+ this.checkRows = [obj.row];
520
+ }
521
+ if (obj.checked) {
522
+ const aRows = $table1.getTableData().visibleData;
523
+ const cRows = $table1.getCheckboxRecords();
524
+ $table1.setAllCheckboxRow(aRows.length == cRows.length);
525
+ } else {
526
+ $table1.setAllCheckboxRow(false);
527
+ }
528
+ },
529
+ checkAll(res) {
530
+ const fieldKey = this.fieldKey;
531
+ const $grid = res.$grid;
532
+ const allRows = $grid.getTableData().visibleData;
533
+ $grid.setCheckboxRow(allRows, res.checked);
534
+ allRows.forEach((lineData) => {
535
+ const rowid = lineData[fieldKey];
536
+ const exist = this.checkRows.find((item) => item[fieldKey] == rowid);
537
+ if (res.checked) {
538
+ if (!exist) this.checkRows.push(lineData);
539
+ } else if (exist) {
540
+ const delIndex = this.checkRows.findIndex(
541
+ (item) => item[fieldKey] == rowid
542
+ );
543
+ if (delIndex > -1) this.checkRows.splice(delIndex, 1);
544
+ }
545
+ });
546
+ },
547
+ clearTable1Select(index) {
548
+ const fieldKey = this.fieldKey;
549
+ const row = this.checkRows[index];
550
+ const rowid = row[fieldKey];
551
+ const $grid1 = this.getGrid();
552
+ const rows = $grid1.getTableData().visibleData;
553
+ const row2 = this.findTreeRowById(rows, rowid);
554
+ if (this.selectMulti) {
555
+ if (row2) $grid1.setCheckboxRow(row2, false);
556
+ } else {
557
+ $grid1.clearCheckboxRow();
558
+ }
559
+ this.checkRows.splice(index, 1);
560
+ if (row2) $grid1.setAllCheckboxRow(false);
561
+ },
562
+ clearChecked() {
563
+ const $grid1 = this.getGrid();
564
+ $grid1.clearCheckboxRow();
565
+ this.checkRows = [];
566
+ },
567
+ findTreeRowById(rows, rowid) {
568
+ const fieldKey = this.fieldKey;
569
+ for (let i = 0; i < rows.length; i++) {
570
+ const row = rows[i];
571
+ if (row[fieldKey] == rowid) return row;
572
+ if (row.children) {
573
+ const mRow = this.findTreeRowById(row.children, rowid);
574
+ if (mRow) return mRow;
575
+ }
576
+ }
577
+ return null;
578
+ },
579
+ // 单选双击直接确认
580
+ checkWithSubmit(obj) {
581
+ if (this.selectMode && !this.selectMulti) {
582
+ const $grid1 = obj.$table || this.getGrid();
583
+ const rows = $grid1.getCheckboxRecords(true);
584
+ if (rows && rows.length) {
585
+ this.handleConfirm();
586
+ }
587
+ }
588
+ },
589
+ /* ------- 生命周期收口(同 formDialog) ------- */
590
+ settle(value) {
591
+ if (this._settled) return;
592
+ this._settled = true;
593
+ if (this._resolve) {
594
+ this._resolve(value);
595
+ }
596
+ },
597
+ handleClose() {
598
+ // 取消/右上角关闭:resolve(null);确认路径已先 settle,此处不生效
599
+ this.settle(null);
600
+ },
601
+ handleClosed() {
602
+ this.$destroy();
603
+ if (this.$el && this.$el.parentNode) {
604
+ this.$el.parentNode.removeChild(this.$el);
605
+ }
606
+ },
607
+ },
608
+ };
609
+ </script>
610
+
611
+ <style lang="scss" scoped>
612
+ .fd-wrap {
613
+ height: 100%;
614
+ display: flex;
615
+ flex-direction: column;
616
+ overflow: hidden;
617
+
618
+ .fd-cont {
619
+ flex: 1;
620
+ min-height: 0;
621
+ overflow: auto;
622
+ padding: 0 12px;
623
+
624
+ ::v-deep .grid-height {
625
+ height: 100% !important;
626
+ }
627
+
628
+ // 页面里靠 `#app #containt.designer-view` 抹掉这层白底投影,
629
+ // 抽屉是 appendToBody 挂在 #app 外面的,得自己抹
630
+ #containt.designer-view {
631
+ background: none;
632
+ box-shadow: none;
633
+ }
634
+
635
+ // 容器(detail-wrap/栅格/h5-card)的 1px dashed 是设计器里的辅助线,
636
+ // 渲染态不该出现。全局只在 .dialog-style 弹框体和 tabs 内容区里清掉了
637
+ // (style.scss 的两处 .designer-view .grid-container{outline:none}),
638
+ // 抽屉不在这两个上下文下,需要自己清。
639
+ ::v-deep .grid-container {
640
+ outline: none;
641
+ }
642
+
643
+ // 列表宿主页(host:"list"):把高度沿 designer-view → #containt(list.vue 根) 传下去。
644
+ // .tab-box 自身已是 height:100%,但父链没高度时页签内容区会塌成一条。
645
+ .fd-list-host {
646
+ height: 100%;
647
+
648
+ ::v-deep #containt {
649
+ height: 100%;
650
+ }
651
+ }
652
+
653
+ // 列表型模板:把确定高度一路传到 vxe-grid 的父元素,表格才能铺满抽屉
654
+ &.fd-cont--fill {
655
+ overflow: hidden;
656
+
657
+ ::v-deep .data-table_height {
658
+ height: 100%;
659
+
660
+ > .render-form {
661
+ height: 100%;
662
+ }
663
+ }
664
+ }
665
+ }
666
+
667
+ .fd-checked {
668
+ flex-shrink: 0;
669
+ display: flex;
670
+ align-items: center;
671
+ padding: 4px 12px;
672
+ border-top: 1px solid #ebeef5;
673
+ overflow: hidden;
674
+
675
+ .allDel {
676
+ flex-shrink: 0;
677
+ margin-right: 8px;
678
+ cursor: pointer;
679
+ }
680
+
681
+ .list {
682
+ flex: 1;
683
+ display: flex;
684
+ overflow-x: auto;
685
+ white-space: nowrap;
686
+
687
+ .item {
688
+ display: inline-flex;
689
+ align-items: center;
690
+ margin-right: 8px;
691
+ padding: 0 6px;
692
+ background: #f4f6fa;
693
+ border-radius: 2px;
694
+
695
+ p {
696
+ margin: 0 4px 0 0;
697
+ }
698
+
699
+ a {
700
+ cursor: pointer;
701
+ }
702
+ }
703
+ }
704
+ }
705
+
706
+ .fd-footer {
707
+ flex-shrink: 0;
708
+ text-align: right;
709
+ padding: 10px 16px;
710
+ border-top: 1px solid #ebeef5;
711
+
712
+ .tips {
713
+ line-height: 28px;
714
+ color: #909399;
715
+ font-size: 12px;
716
+ }
717
+ }
718
+ }
719
+ </style>