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
@@ -28,7 +28,7 @@
28
28
  <div class="clearfix screen-btns">
29
29
  <div class="fr">
30
30
  <vxe-button icon="el-icon-brush" class="button-sty" @click="resetEvent" type="text" status="primary"
31
- plain>{{ $t2('重置', 'system.button.reset') }}
31
+ plain>{{ $t1('刷新') }}
32
32
  </vxe-button>
33
33
  <vxe-button status="warning" icon="el-icon-search" class="button-sty" @click="searchEvent">
34
34
  {{ $t2('搜索', 'system.button.search') }}
@@ -10,7 +10,7 @@
10
10
  </div>
11
11
  <div class="fr">
12
12
  <el-button type="primary" plain class="button-sty" @click="$baseReload()" icon="el-icon-refresh-right">
13
- {{ $t2('重置', 'system.button.reset') }}
13
+ {{ $t1('刷新') }}
14
14
  </el-button>
15
15
  <el-button type="primary" class="button-sty" icon="el-icon-check" @click="saveData">
16
16
  {{ $t2('保存', 'system.button.save') }}
@@ -79,7 +79,7 @@
79
79
  @click="resetEvent"
80
80
  type="primary"
81
81
  plain
82
- >{{ $t1("重置") }}
82
+ >{{ $t1("刷新") }}
83
83
  </el-button>
84
84
  <el-button
85
85
  type="warning"
@@ -1,241 +1,324 @@
1
- # $formDialog 表单弹框
2
-
3
- JS 调用式表单弹框:传入字段配置即可打开一个可编辑表单,确认后以 Promise 返回表单数据,无需为每个小表单单独编写 `.vue` 弹框组件。
4
-
5
- - 组件位置:`src/components/formDialog/`
6
- - 全局注册:`src/index.js` 中 `Vue.use(FormDialog)`,挂载为 `Vue.prototype.$formDialog`
7
- - 示例页面:`src/views/support/form-dialog-demo/index.vue`(路由 `/support/form-dialog-demo`,11 个可运行示例)
8
-
9
- 两种模式:
10
-
11
- 1. **字段配置模式**(默认)——传 `fields` 数组,由本组件渲染 element 控件;
12
- 2. **xform 整表模式**——传 `formCode`(或 `formJson`),弹框内渲染设计器里配置好的完整 xform 表单,见「xform 整表模式」一节。
13
-
14
- ## 快速上手
15
-
16
- ```js
17
- const data = await this.$formDialog({
18
- title: "新增分类",
19
- fields: [
20
- { prop: "name", label: "名称", required: true },
21
- {
22
- prop: "type",
23
- label: "类型",
24
- type: "select",
25
- options: [
26
- { label: "普通", value: 1 },
27
- { label: "重要", value: 2 },
28
- ],
29
- },
30
- { prop: "enabled", label: "启用", type: "switch" },
31
- { prop: "remark", label: "备注", type: "textarea" },
32
- ],
33
- });
34
- // 点确定且校验通过 => data 为表单数据对象
35
- // 取消 / 右上角关闭 => data 为 null(不使用 reject,无需 catch)
36
- if (data !== null) {
37
- // ...
38
- }
39
- ```
40
-
41
- ## 顶层 options
42
-
43
- | 参数 | 类型 | 默认值 | 说明 |
44
- |---|---|---|---|
45
- | `title` | String | `""` | 弹框标题 |
46
- | `width` | String | `"600px"` | 弹框宽度 |
47
- | `labelWidth` | String | `"100px"` | 表单 label 宽度 |
48
- | `model` | Object | `{}` | 初始值(编辑回显)。未提供的字段按类型补默认值 |
49
- | `fields` | Array | `[]` | 字段配置,见下 |
50
- | `rules` | Object | `{}` | 额外的 el-form 校验规则,与字段级 `required`/`rules` 合并 |
51
- | `readonly` | Boolean | `false` | 只读查看模式:整表单禁用,底部只有"关闭"按钮 |
52
- | `beforeConfirm` | Function | - | `(data) => Promise`。确认前钩子(常用于调保存接口),reject 则弹框不关闭;执行期间确定按钮 loading 防重复提交 |
53
- | `formCode` / `formJson` | String / Object | - | 传入即切换为 **xform 整表模式**(`fields` 不再生效),见「xform 整表模式」一节 |
54
-
55
- 返回值:`Promise`。确认(校验通过、beforeConfirm 成功)resolve 表单数据浅拷贝;取消/关闭 resolve `null`。
56
-
57
- ## 字段配置(field)
58
-
59
- ### 通用属性
60
-
61
- | 属性 | 类型 | 说明 |
62
- |---|---|---|
63
- | `prop` | String | 字段名(必填,作为 model 的 key) |
64
- | `label` | String | 标签文字 |
65
- | `type` | String | 控件类型,缺省为 `input`,见下表 |
66
- | `span` | Number | 栅格宽度(24 为一行一个,默认 24) |
67
- | `required` | Boolean | 必填(自动生成"XX不能为空"规则) |
68
- | `rules` | Array/Object | 字段级校验规则 |
69
- | `placeholder` | String | 占位文案 |
70
- | `disabled` | Boolean / `(model) => Boolean` | 禁用(支持函数联动) |
71
- | `visible` | Boolean / `(model) => Boolean` | 显隐(支持函数联动;隐藏时不渲染、不参与校验) |
72
- | `props` | Object | 透传给底层 element 控件的 props(如 `min`/`max`/`multiple`/`valueFormat` 等,可覆盖默认值) |
73
- | `render` | `(h, model, field) => VNode` | 自定义渲染逃生口,内置类型覆盖不了时使用(配置了 render 则忽略 type) |
74
- | `onChange` | `(value, model, field, dialog) => void` | 值变化回调,见「联动」 |
75
- | `dependsOn` | Array\<String\> | 依赖字段列表,见「联动」 |
76
-
77
- ### 控件类型(type)
78
-
79
- | type | 控件 | 值类型 | 说明 |
80
- |---|---|---|---|
81
- | `input`(默认) | el-input | String | |
82
- | `textarea` | el-input type=textarea | String | 默认 3 行 |
83
- | `number` | baseInputNumber | Number | 字段级 `scale`(小数位,默认 2,0=整数)、`negative`(允许负数);`min`/`max` 走 `props` |
84
- | `select` | el-select | 任意 | 三种数据源见下节 |
85
- | `date` | el-date-picker | String | value-format 默认 `yyyy-MM-dd` |
86
- | `datetime` | el-date-picker | String | value-format 默认 `yyyy-MM-dd HH:mm:ss` |
87
- | `daterange` | el-date-picker | Array | value-format 默认 `yyyy-MM-dd` |
88
- | `switch` | el-switch | Boolean | |
89
- | `radio` | el-radio-group | 任意 | 用 `options` |
90
- | `checkbox` | el-checkbox-group | Array | 用 `options` |
91
- | `search` | el-input + 搜索图标 | String | 通用搜索框样式(同 xform vabsearch),见「搜索框」 |
92
-
93
- ## 下拉数据源(select / radio / checkbox 通用)
94
-
95
- 三选一:
96
-
97
- ```js
98
- // 1. 静态值:数组(或函数,见「联动」)
99
- { prop: "type", type: "select", options: [{ label: "普通", value: 1 }, "直接字符串也可以"] }
100
-
101
- // 2. 词汇:/user/common_attribute/listItems,显示 value、取值 sn(与 xform 约定一致)
102
- { prop: "sex", type: "select", dictCode: "SEX", dictData: { ... } }
103
-
104
- // 3. 脚本编码:"formCode/scriptCode",先取服务名再请求 /{serviceName}/bd_api/{formCode}/{scriptCode}
105
- {
106
- prop: "org", type: "select",
107
- scriptCode: "demoForm/getOptions",
108
- scriptData: { ... }, // 请求参数,也支持 (model) => ({...})
109
- labelField: "name", // 默认 "label"
110
- valueField: "id", // 默认 "value"
111
- // 或完全自定义解析:
112
- // parseOptions: (res) => [{ label, value }],
113
- }
114
- ```
115
-
116
- 远程选项加载中 select 显示 loading。脚本模式选项对象上带 `row`(原始行数据)。
117
-
118
- ## 搜索框(type: "search")
119
-
120
- 样式与 xform vabsearch 控件一致:输入框内右侧 `el-icon-search` 图标 + 悬停清除图标。输入框默认禁止手输(值由选择回填),传 `props: { editable: true }` 放开。
121
-
122
- 点击搜索图标的行为,三选一(优先级从上到下):
123
-
124
- ```js
125
- // 方式1:onSearch 完全自定义(自己开弹框、自己回写 model;model 是响应式的)
126
- {
127
- prop: "customerName", label: "客户", type: "search",
128
- onSearch: async (model, field) => { /* ... */ },
129
- onClear: (model, field) => { model.customerId = null; model.customerName = null; },
130
- }
131
-
132
- // 方式2:searchComponent —— 打开自定义 Vue 弹框组件(走 utils/componentDialog)
133
- {
134
- prop: "supplierName", label: "供应商", type: "search",
135
- searchComponent: {
136
- // 路径加载只收集 dialog/ 目录、*Dialog.vue、*Dialog/index.vue
137
- componentPath: "views/xx/pickerDialog.vue",
138
- // 也可直接传 component,或传 componentLoader: () => import("@/views/xx/picker.vue")
139
- fieldMap: { supplierId: "id", supplierName: "name" },
140
- },
141
- }
142
- // 组件契约:自带弹框(wrapper 默认 false)、确认时 $emit("confirm", rows)、
143
- // 关闭时 $emit("update:visiable", false)。参考 demo 的 demoPickerDialog.vue
144
-
145
- // 方式3:searchDialog —— 打开 xform 搜索弹框(searchFormDialog,按 formCode 渲染数据表格)
146
- {
147
- prop: "billName", label: "单据", type: "search",
148
- searchDialog: {
149
- formCode: "xxx", // 目标表单编码(需已配置搜索弹框)
150
- multiple: false,
151
- queryParam: { ... }, // 可选查询参数
152
- rows: (model) => [...], // 可选回显已选行,支持函数
153
- fieldMap: { billId: "id", billName: "_tt" },
154
- // layoutType: "PC", // 默认 PC
155
- },
156
- }
157
- ```
158
-
159
- 选中回写规则(方式2/3 共用,优先级从上到下):
160
-
161
- 1. `onConfirm(model, rows, field)` —— 完全自定义
162
- 2. `fieldMap: { model字段: 行字段名 | (row, rows) => value }` —— 逐字段映射(函数形式可处理多选拼接)
163
- 3. 默认把首行中与 `prop` 同名(或 `showField` 指定)的字段写回本字段
164
-
165
- 清除图标触发 `onClear(model, field)`,不传则默认清空本字段;`clearable: false` 隐藏清除。
166
-
167
- ## 联动
168
-
169
- 四种机制可组合:
170
-
171
- ```js
172
- fields: [
173
- {
174
- prop: "province", label: "省份", type: "select", options: [...],
175
- // 1. onChange:任意字段值变化时触发(含搜索框 fieldMap 回写、render 控件改 model)
176
- // dialog 上可用:dialog.setFieldOptions(prop, options) 手动设选项
177
- // dialog.reloadFieldOptions(prop) 按最新 model 重拉词汇/脚本选项
178
- onChange: (val, model, field, dialog) => { ... },
179
- },
180
- {
181
- prop: "city", label: "城市", type: "select",
182
- // 2. dependsOn:依赖字段变化时自动清空自身值;
183
- // 若选项来自 dictCode/scriptCode,会按最新 model 自动重新拉取
184
- dependsOn: ["province"],
185
- // 静态级联:options 支持函数,渲染时实时按 model 求值
186
- options: (model) => cityMap[model.province] || [],
187
- // 远程级联传参:dictData / scriptData 支持 (model) => ({...})
188
- },
189
- // 3. 显隐联动:隐藏时不渲染、不参与必填校验
190
- { prop: "taxNo", label: "税号", required: true, visible: (model) => model.needInvoice },
191
- // 4. 禁用联动
192
- { prop: "reason", label: "原因", disabled: (model) => model.level !== 2 },
193
- ]
194
- ```
195
-
196
- 实现方式为深度监听 model + 快照 diff,链式联动(A 变 → B 清 → B 的 onChange)可用;避免在 onChange 里循环写值。
197
-
198
- ## xform 整表模式
199
-
200
- 传 `formCode`(或直接传 `formJson`)即进入整表模式:不再走 `fields` 渲染,而是按 `USER_PREFIX + /formTemplate/getByFormCode` 加载表单模板(与 `views/user/form/vform/render.vue` 同链路),弹框内用 `VFormRender` 渲染完整 xform 表单——业务控件、明细表、脚本事件等设计器能力全部可用。
201
-
202
- ```js
203
- const data = await this.$formDialog({
204
- formCode: "xxx", // 表单模板编码(与 formJson 二选一,formJson 直接传模板 JSON 对象)
205
- // title: "自定义标题", // 缺省取表单模板名称
206
- // width: "1000px", // 整表模式默认 1000px
207
- model: { name: "初始值" }, // 初始数据,结构与 getFormData 一致(也可用 formData 字段名)
208
- // readonly: true, // 只读:走 xform setReadMode,底部只有"关闭"
209
- // optionData: {}, // 透传 VFormRender 的 option-data
210
- // globalDsv: {}, // 透传 VFormRender 的 global-dsv
211
- onReady: (formRef, dialog) => {
212
- // 表单挂载后回调,formRef 即 VFormRender 实例:
213
- // formRef.setFieldValue / getWidgetRef / disableForm(...) 等 API 均可用
214
- },
215
- beforeConfirm: (formData) => this.$http({ ... }), // 同字段模式,reject 不关闭
216
- });
217
- // data 为 xform getFormData 的完整表单数据(含明细表);取消/关闭仍为 null
218
- ```
219
-
220
- 说明:
221
-
222
- - 确认时走 xform 自身的 `validateForm`(失败自动提示"必填项不能为空"并滚动定位到出错字段),通过后 resolve `getFormData` 的深拷贝。
223
- - `VFormRender` 为异步组件(独立 chunk),只在首次打开整表模式时加载,不增加主包体积;加载前会自动执行 `loadExtension()` 注册 xform 扩展控件。
224
- - 弹框规格与 xform 自己的 `dynamicDialogRender` 一致(`dialog-style list-dialog` + `.cont` 容器)。
225
- - 整表模式下 `fields`/`rules`/联动等字段配置模式的参数不生效——表单结构、校验、联动都在设计器里配置。
226
-
227
- ## 其他说明
228
-
229
- - 每次调用创建独立实例,支持叠开多层弹框(如在 `onSearch` 里再开一层 `$formDialog`,见 demo 示例 7/8)。
230
- - 弹框规格与项目一致:`append-to-body`、禁点遮罩关闭、可拖拽(`v-el-drag-dialog`)、`dialog-style` 样式类。
231
- - 实例挂在 `window.$vueRoot` 之下,弹框内可正常使用 `$t2`、`$http`、`$getBaseDicts` 等原型能力。
232
- - 也可不经 Vue 实例调用:`import FormDialog from "@base/components/formDialog/index.js"; FormDialog.open({...})`。
233
- - 数字框底层为 `baseInputNumber`(`v-limit-number` 指令限制小数位/负号,支持按键、选区替换与粘贴校验)。
234
-
235
- ## 与既有设施的分工
236
-
237
- | 场景 | 用什么 |
238
- |---|---|
239
- | 轻量配置化表单(增改查小弹框) | `$formDialog`(本组件) |
240
- | 复杂业务表单弹框(已有/需要专用 .vue) | `openComponentDialog`(`src/utils/componentDialog.js`) |
241
- | 按 xform 表单模板渲染的完整表单 | xform(`VFormRender` / `searchFormDialog`) |
1
+ # $formDialog 表单弹框
2
+
3
+ JS 调用式表单弹框:传入字段配置即可打开一个可编辑表单,确认后以 Promise 返回表单数据,无需为每个小表单单独编写 `.vue` 弹框组件。
4
+
5
+ - 组件位置:`src/components/formDialog/`
6
+ - 全局注册:`src/index.js` 中 `Vue.use(FormDialog)`,挂载为 `Vue.prototype.$formDialog`
7
+ - 示例页面:`src/views/support/form-dialog-demo/index.vue`(路由 `/support/form-dialog-demo`,11 个可运行示例)
8
+
9
+ 两种模式:
10
+
11
+ 1. **字段配置模式**(默认)——传 `fields` 数组,由本组件渲染 element 控件;
12
+ 2. **xform 整表模式**——传 `formCode`(或 `formJson`),弹框内渲染设计器里配置好的完整 xform 表单,见「xform 整表模式」一节。
13
+
14
+ ## 快速上手
15
+
16
+ ```js
17
+ const data = await this.$formDialog({
18
+ title: "新增分类",
19
+ fields: [
20
+ { prop: "name", label: "名称", required: true },
21
+ {
22
+ prop: "type",
23
+ label: "类型",
24
+ type: "select",
25
+ options: [
26
+ { label: "普通", value: 1 },
27
+ { label: "重要", value: 2 },
28
+ ],
29
+ },
30
+ { prop: "enabled", label: "启用", type: "switch" },
31
+ { prop: "remark", label: "备注", type: "textarea" },
32
+ ],
33
+ });
34
+ // 点确定且校验通过 => data 为表单数据对象
35
+ // 取消 / 右上角关闭 => data 为 null(不使用 reject,无需 catch)
36
+ if (data !== null) {
37
+ // ...
38
+ }
39
+ ```
40
+
41
+ ## 顶层 options
42
+
43
+ | 参数 | 类型 | 默认值 | 说明 |
44
+ |---|---|---|---|
45
+ | `title` | String | `""` | 弹框标题 |
46
+ | `width` | String | `"600px"` | 弹框宽度 |
47
+ | `labelWidth` | String | `"100px"` | 表单 label 宽度 |
48
+ | `model` | Object | `{}` | 初始值(编辑回显)。未提供的字段按类型补默认值 |
49
+ | `fields` | Array | `[]` | 字段配置,见下 |
50
+ | `rules` | Object | `{}` | 额外的 el-form 校验规则,与字段级 `required`/`rules` 合并 |
51
+ | `readonly` | Boolean | `false` | 只读查看模式:整表单禁用,底部只有"关闭"按钮 |
52
+ | `beforeConfirm` | Function | - | `(data) => Promise`。确认前钩子(常用于调保存接口),reject 则弹框不关闭;执行期间确定按钮 loading 防重复提交 |
53
+ | `formCode` / `formJson` | String / Object | - | 传入即切换为 **xform 整表模式**(`fields` 不再生效),见「xform 整表模式」一节 |
54
+
55
+ 返回值:`Promise`。确认(校验通过、beforeConfirm 成功)resolve 表单数据浅拷贝;取消/关闭 resolve `null`。
56
+
57
+ ## 字段配置(field)
58
+
59
+ ### 通用属性
60
+
61
+ | 属性 | 类型 | 说明 |
62
+ |---|---|---|
63
+ | `prop` | String | 字段名(必填,作为 model 的 key) |
64
+ | `label` | String | 标签文字 |
65
+ | `type` | String | 控件类型,缺省为 `input`,见下表 |
66
+ | `span` | Number | 栅格宽度(24 为一行一个,默认 24) |
67
+ | `required` | Boolean | 必填(自动生成"XX不能为空"规则) |
68
+ | `rules` | Array/Object | 字段级校验规则 |
69
+ | `placeholder` | String | 占位文案 |
70
+ | `disabled` | Boolean / `(model) => Boolean` | 禁用(支持函数联动) |
71
+ | `visible` | Boolean / `(model) => Boolean` | 显隐(支持函数联动;隐藏时不渲染、不参与校验) |
72
+ | `props` | Object | 透传给底层 element 控件的 props(如 `min`/`max`/`multiple`/`valueFormat` 等,可覆盖默认值) |
73
+ | `render` | `(h, model, field) => VNode` | 自定义渲染逃生口,内置类型覆盖不了时使用(配置了 render 则忽略 type) |
74
+ | `onChange` | `(value, model, field, dialog) => void` | 值变化回调,见「联动」 |
75
+ | `dependsOn` | Array\<String\> | 依赖字段列表,见「联动」 |
76
+
77
+ ### 控件类型(type)
78
+
79
+ | type | 控件 | 值类型 | 说明 |
80
+ |---|---|---|---|
81
+ | `input`(默认) | el-input | String | |
82
+ | `textarea` | el-input type=textarea | String | 默认 3 行 |
83
+ | `number` | baseInputNumber | Number | 字段级 `scale`(小数位,默认 2,0=整数)、`negative`(允许负数);`min`/`max` 走 `props` |
84
+ | `select` | el-select | 任意 | 三种数据源见下节 |
85
+ | `date` | el-date-picker | String | value-format 默认 `yyyy-MM-dd` |
86
+ | `datetime` | el-date-picker | String | value-format 默认 `yyyy-MM-dd HH:mm:ss` |
87
+ | `daterange` | el-date-picker | Array | value-format 默认 `yyyy-MM-dd` |
88
+ | `switch` | el-switch | Boolean | |
89
+ | `radio` | el-radio-group | 任意 | 用 `options` |
90
+ | `checkbox` | el-checkbox-group | Array | 用 `options` |
91
+ | `search` | el-input + 搜索图标 | String | 通用搜索框样式(同 xform vabsearch),见「搜索框」 |
92
+
93
+ ## 下拉数据源(select / radio / checkbox 通用)
94
+
95
+ 三选一:
96
+
97
+ ```js
98
+ // 1. 静态值:数组(或函数,见「联动」)
99
+ { prop: "type", type: "select", options: [{ label: "普通", value: 1 }, "直接字符串也可以"] }
100
+
101
+ // 2. 词汇:/user/common_attribute/listItems,显示 value、取值 sn(与 xform 约定一致)
102
+ { prop: "sex", type: "select", dictCode: "SEX", dictData: { ... } }
103
+
104
+ // 3. 脚本编码:"formCode/scriptCode",先取服务名再请求 /{serviceName}/bd_api/{formCode}/{scriptCode}
105
+ {
106
+ prop: "org", type: "select",
107
+ scriptCode: "demoForm/getOptions",
108
+ scriptData: { ... }, // 请求参数,也支持 (model) => ({...})
109
+ labelField: "name", // 默认 "label"
110
+ valueField: "id", // 默认 "value"
111
+ // 或完全自定义解析:
112
+ // parseOptions: (res) => [{ label, value }],
113
+ }
114
+ ```
115
+
116
+ 远程选项加载中 select 显示 loading。脚本模式选项对象上带 `row`(原始行数据)。
117
+
118
+ ## 搜索框(type: "search")
119
+
120
+ 样式与 xform vabsearch 控件一致:输入框内右侧 `el-icon-search` 图标 + 悬停清除图标。输入框默认禁止手输(值由选择回填),传 `props: { editable: true }` 放开。
121
+
122
+ 点击搜索图标的行为,三选一(优先级从上到下):
123
+
124
+ ```js
125
+ // 方式1:onSearch 完全自定义(自己开弹框、自己回写 model;model 是响应式的)
126
+ {
127
+ prop: "customerName", label: "客户", type: "search",
128
+ onSearch: async (model, field) => { /* ... */ },
129
+ onClear: (model, field) => { model.customerId = null; model.customerName = null; },
130
+ }
131
+
132
+ // 方式2:searchComponent —— 打开自定义 Vue 弹框组件(走 utils/componentDialog)
133
+ {
134
+ prop: "supplierName", label: "供应商", type: "search",
135
+ searchComponent: {
136
+ // 路径加载只收集 dialog/ 目录、*Dialog.vue、*Dialog/index.vue
137
+ componentPath: "views/xx/pickerDialog.vue",
138
+ // 也可直接传 component,或传 componentLoader: () => import("@/views/xx/picker.vue")
139
+ fieldMap: { supplierId: "id", supplierName: "name" },
140
+ },
141
+ }
142
+ // 组件契约:自带弹框(wrapper 默认 false)、确认时 $emit("confirm", rows)、
143
+ // 关闭时 $emit("update:visiable", false)。参考 demo 的 demoPickerDialog.vue
144
+
145
+ // 方式3:searchDialog —— 打开 xform 搜索弹框(searchFormDialog,按 formCode 渲染数据表格)
146
+ {
147
+ prop: "billName", label: "单据", type: "search",
148
+ searchDialog: {
149
+ formCode: "xxx", // 目标表单编码(需已配置搜索弹框)
150
+ multiple: false,
151
+ queryParam: { ... }, // 可选查询参数
152
+ rows: (model) => [...], // 可选回显已选行,支持函数
153
+ fieldMap: { billId: "id", billName: "_tt" },
154
+ // layoutType: "PC", // 默认 PC
155
+ },
156
+ }
157
+ ```
158
+
159
+ 选中回写规则(方式2/3 共用,优先级从上到下):
160
+
161
+ 1. `onConfirm(model, rows, field)` —— 完全自定义
162
+ 2. `fieldMap: { model字段: 行字段名 | (row, rows) => value }` —— 逐字段映射(函数形式可处理多选拼接)
163
+ 3. 默认把首行中与 `prop` 同名(或 `showField` 指定)的字段写回本字段
164
+
165
+ 清除图标触发 `onClear(model, field)`,不传则默认清空本字段;`clearable: false` 隐藏清除。
166
+
167
+ ## 联动
168
+
169
+ 四种机制可组合:
170
+
171
+ ```js
172
+ fields: [
173
+ {
174
+ prop: "province", label: "省份", type: "select", options: [...],
175
+ // 1. onChange:任意字段值变化时触发(含搜索框 fieldMap 回写、render 控件改 model)
176
+ // dialog 上可用:dialog.setFieldOptions(prop, options) 手动设选项
177
+ // dialog.reloadFieldOptions(prop) 按最新 model 重拉词汇/脚本选项
178
+ onChange: (val, model, field, dialog) => { ... },
179
+ },
180
+ {
181
+ prop: "city", label: "城市", type: "select",
182
+ // 2. dependsOn:依赖字段变化时自动清空自身值;
183
+ // 若选项来自 dictCode/scriptCode,会按最新 model 自动重新拉取
184
+ dependsOn: ["province"],
185
+ // 静态级联:options 支持函数,渲染时实时按 model 求值
186
+ options: (model) => cityMap[model.province] || [],
187
+ // 远程级联传参:dictData / scriptData 支持 (model) => ({...})
188
+ },
189
+ // 3. 显隐联动:隐藏时不渲染、不参与必填校验
190
+ { prop: "taxNo", label: "税号", required: true, visible: (model) => model.needInvoice },
191
+ // 4. 禁用联动
192
+ { prop: "reason", label: "原因", disabled: (model) => model.level !== 2 },
193
+ ]
194
+ ```
195
+
196
+ 实现方式为深度监听 model + 快照 diff,链式联动(A 变 → B 清 → B 的 onChange)可用;避免在 onChange 里循环写值。
197
+
198
+ ## xform 整表模式
199
+
200
+ 传 `formCode`(或直接传 `formJson`)即进入整表模式:不再走 `fields` 渲染,而是按 `USER_PREFIX + /formTemplate/getByFormCode` 加载表单模板(与 `views/user/form/vform/render.vue` 同链路),弹框内用 `VFormRender` 渲染完整 xform 表单——业务控件、明细表、脚本事件等设计器能力全部可用。
201
+
202
+ ```js
203
+ const data = await this.$formDialog({
204
+ formCode: "xxx", // 表单模板编码(与 formJson 二选一,formJson 直接传模板 JSON 对象)
205
+ // title: "自定义标题", // 缺省取表单模板名称
206
+ // width: "1000px", // 整表模式默认 1000px
207
+ model: { name: "初始值" }, // 初始数据,结构与 getFormData 一致(也可用 formData 字段名)
208
+ // readonly: true, // 只读:走 xform setReadMode,底部只有"关闭"
209
+ // optionData: {}, // 透传 VFormRender 的 option-data
210
+ // globalDsv: {}, // 透传 VFormRender 的 global-dsv
211
+ onReady: (formRef, dialog) => {
212
+ // 表单挂载后回调,formRef 即 VFormRender 实例:
213
+ // formRef.setFieldValue / getWidgetRef / disableForm(...) 等 API 均可用
214
+ },
215
+ beforeConfirm: (formData) => this.$http({ ... }), // 同字段模式,reject 不关闭
216
+ });
217
+ // data 为 xform getFormData 的完整表单数据(含明细表);取消/关闭仍为 null
218
+ ```
219
+
220
+ 说明:
221
+
222
+ - 确认时走 xform 自身的 `validateForm`(失败自动提示"必填项不能为空"并滚动定位到出错字段),通过后 resolve `getFormData` 的深拷贝。
223
+ - `VFormRender` 为异步组件(独立 chunk),只在首次打开整表模式时加载,不增加主包体积;加载前会自动执行 `loadExtension()` 注册 xform 扩展控件。
224
+ - 弹框规格与 xform 自己的 `dynamicDialogRender` 一致(`dialog-style list-dialog` + `.cont` 容器)。
225
+ - 整表模式下 `fields`/`rules`/联动等字段配置模式的参数不生效——表单结构、校验、联动都在设计器里配置。
226
+
227
+ ## 其他说明
228
+
229
+ - 每次调用创建独立实例,支持叠开多层弹框(如在 `onSearch` 里再开一层 `$formDialog`,见 demo 示例 7/8)。
230
+ - 弹框规格与项目一致:`append-to-body`、禁点遮罩关闭、可拖拽(`v-el-drag-dialog`)、`dialog-style` 样式类。
231
+ - 实例挂在 `window.$vueRoot` 之下,弹框内可正常使用 `$t2`、`$http`、`$getBaseDicts` 等原型能力。
232
+ - 也可不经 Vue 实例调用:`import FormDialog from "@base/components/formDialog/index.js"; FormDialog.open({...})`。
233
+ - 数字框底层为 `baseInputNumber`(`v-limit-number` 指令限制小数位/负号,支持按键、选区替换与粘贴校验)。
234
+
235
+ ## 自定义按钮(formConfig.actionButtons)
236
+
237
+ xform 整表模式下,底部按钮可在**表单设计器 表单设置 → 操作按钮**里配置(存模板 `formConfig.actionButtons`,随模板保存)。未配置则保持默认"取消/确定"。
238
+
239
+ ```js
240
+ // 设计器里每个按钮的配置项
241
+ {
242
+ code: "submit", // 按钮标识(必填),resolve 时区分是哪个按钮
243
+ label: "提 交",
244
+ type: "primary", plain: false, icon: "el-icon-check",
245
+ authName: "", // 权限唯一名称,完整权限编码 = formCode:authName
246
+ needValidate: true, // 点击前先 validateForm
247
+ closeAfter: true, // 脚本成功后自动收口并关闭
248
+ visible: "...", // 显隐脚本:visible(button),返回 false 隐藏
249
+ onClick: "...", // 点击脚本:onClick(formData, dialog, done, selection)
250
+ }
251
+ ```
252
+
253
+ 规则:
254
+
255
+ - **权限**:禁用清单机制(`dispermissions`)——配了 `authName` 且 `formCode:authName` 被禁用则不渲染;未配 `authName` 默认放行。与 visible 脚本是 AND 关系。
256
+ - **onClick 脚本**:`this` = VFormRender 实例(`getFormData`/`getWidgetRef`/`$http` 等可用);`done(data)` 结算 Promise(缺省 data 取表单数据);返回 `false` 或 reject 的 Promise 不关闭;未显式调 `done` 且 `closeAfter` 时自动以表单数据收口。执行期间按钮 loading 防重复提交。
257
+ - **resolve 语义**:配置了自定义按钮后 resolve `{ action: code, data }`;默认按钮仍是 `data`;取消/关闭仍是 `null`(存量调用不受影响)。
258
+ - 调用方可传 `buttons: [...]`(同结构)覆盖模板配置;readonly 模式只显示"关闭"。
259
+ - 弹框/抽屉共用同一套配置与语义(见下节 $formDrawer)。
260
+ - **四个壳都吃这份配置**:全局 `$formDialog` / `$formDrawer`,以及表单脚本内部通道
261
+ `openFormDialog` / `openFormDrawer`(`xform/form-designer/form-widget/dialog/` 下那两个)。
262
+ 一份模板配置,四处生效。内部通道收口时回调 `option.onAction(payload, formRef, vm)`
263
+ (不传则仅按 `closeAfter` 关闭,不再走 `option.confirm`——按钮自身的 onClick 脚本即业务处理)。
264
+
265
+ ## $formDrawer 表单抽屉
266
+
267
+ el-drawer 形态的 formCode 承载壳,全局方法 `this.$formDrawer(options)`(`src/components/formDrawer/`,`Vue.use(FormDrawer)` 注册)。仅支持 xform 整表模式(必传 `formCode`),**不支持 H5**。
268
+
269
+ ```js
270
+ const result = await this.$formDrawer({
271
+ formCode: "xxx", // 必填
272
+ // title: "自定义标题", // 缺省取模板名称
273
+ // size: "62%", direction: "rtl", // el-drawer 外观,drawerConfig 可整体透传
274
+ // dataId: row.id, // 详情单据 id —— 详情场景必传,xform 靠它加载单据数据
275
+ // model: {...}, // 初始表单数据(新增态/自定义数据时用)
276
+ // param: {...}, // 透传 VFormRender 的 param
277
+ // conditionParam: { objId, objTypeCode, taskId }, // 流程/权限上下文
278
+ // fillHeight: true, // 强制内容区撑满(列表型模板默认自动开启)
279
+ // host: "list", // 用列表宿主页承载,带「常规(详情)/列表」页签,见下
280
+ // plain: true, // 详情素身模式:去标题栏、去模块导航,只留模块
281
+ // select: { // 查询表格选择模式(列表型模板)
282
+ // multiple: true, rows: [...], fieldKey: "id",
283
+ // queryParam: {...}, onConfirm: (rows, formRef, drawer) => {},
284
+ // },
285
+ // buttons: [...], // 覆盖模板 actionButtons
286
+ // showFooter: false, readonly: true, onReady, beforeConfirm,
287
+ });
288
+ // 默认按钮:select 模式 resolve 选中行数组,表单模式 resolve 表单数据;
289
+ // 自定义按钮 resolve {action, data};取消/关闭 resolve null
290
+ ```
291
+
292
+ 说明:
293
+
294
+ - **select 模式**:行为对齐 xform 的 searchFormDialog——行点选/全选、单选双击直接确认、多选底部已选清单;`fieldKey` 缺省取模板 `searchDialogUniqueField`。自定义按钮脚本的 `selection` 参数即当前选中行。
295
+ - **plain 模式**:详情模板"只有一个个模块"——不渲染单据标题栏与模块导航(走 VFormRender 的 `plainDetailMode`,是渲染时覆盖,不改模板配置)。约定:抽屉不服务流程表单(wfEnabled)。
296
+ 详情容器另有两个**模板级**开关(设计器选中详情容器后的属性面板),与 plain 是"任一命中即隐藏"的叠加关系:`hideHeader` 整条标题栏不渲染、`hideNav` 隐藏模块导航。详情页本身也要素身时用模板开关,只在抽屉里素身时用 `plain`。
297
+ - **`host: "list"` 列表宿主模式**:抽屉里要"从列表点进详情"时用。此模式不再直接渲染单个表单,
298
+ 而是承载列表宿主页 `views/user/form/view/list.vue`,于是「常规(详情)」「列表」两个页签、其他自动页签、
299
+ 多标签编辑、翻单等行为与整页完全一致——点行进详情走的是模板自己的 `editFormCode`,无需额外接线。
300
+
301
+ ```js
302
+ this.$formDrawer({ formCode: "purchaseOrderList", host: "list", param: { status: 1 } });
303
+ ```
304
+
305
+ 与普通模式的差别:默认 `size` 为 85%(要容纳详情);底部 footer 默认**不显示**(列表页自带按钮区),
306
+ 显式传 `showFooter: true` 才出;`plain` / `select` / `actionButtons` 在此模式下不生效——
307
+ 抽屉只作视口,页内行为全部由宿主页负责。抽屉本身仍可 `await`,取消/关闭 resolve `null`。
308
+
309
+ 表单脚本内部通道 `openFormDialog` / `openFormDrawer` 同样支持 `host: "list"`:
310
+ `this.openFormDrawer({ formCode: "xxx", host: "list", param: {...} })`。
311
+ 弹框形态嵌套层级更深(表单 → 弹框 → 列表页 → 详情),建议配 `dialogConfig: { fullscreen: true }`
312
+ 或足够大的 width。若无历史包袱,表单脚本里直接调全局 `this.$formDrawer({ host: "list" })` 更轻。
313
+ - **详情必传 `dataId`**:xform 的 `loadDefaultEntityData` 要 `formConfig.entity && dataId && 脚本编码` 三者齐全才发请求加载单据数据;只传 `conditionParam` 不会加载,表单会是空的。
314
+ - **样式上下文**:抽屉内容区套了 `<div id="containt" class="designer-view">`,与 `views/user/form/vform/render.vue`、xform formDialog 一致。全站渲染态样式都挂在这两个钩子上(`style.scss` 的 `#containt .detail-wrap{...}` 与 `.preview-dialog,.designer-view{...}`),不套这层,详情场景会丢:头部右侧按钮的 inline-block(竖排换行)、`.d-item` 右侧 112px 的导航占位(模块导航压住数据表格)、`.detail-wrap` 的 `position:relative`(导航跑去锚 `.el-drawer`,被裁在抽屉外)、模块边框与内边距。
315
+ - **表格铺满高度**:查询表格的 vxe-grid 用 `height="auto"`,按父元素实测高度计算,父链没有确定高度就会塌成一小块。抽屉不在全局 `.dialog-style .el-dialog__body .data-table_height` 选择器下,故由抽屉自己补高度链:模板顶层只有一个查询表格(`data-table` + `isQueryTable`)时自动开启;模板结构特殊(表格嵌在 tab/栅格里,或表单+表格混排)时用 `fillHeight: true/false` 手工指定,`true` 时被撑满的是渲染器根节点与 `.render-form`,表格外层容器仍需自身有高度。
316
+ - 壳与 xform 渲染器均为懒加载(首次调用才加载),xform chunk 与 $formDialog 共享。
317
+
318
+ ## 与既有设施的分工
319
+
320
+ | 场景 | 用什么 |
321
+ |---|---|
322
+ | 轻量配置化表单(增改查小弹框) | `$formDialog`(本组件) |
323
+ | 复杂业务表单弹框(已有/需要专用 .vue) | `openComponentDialog`(`src/utils/componentDialog.js`) |
324
+ | 按 xform 表单模板渲染的完整表单 | xform(`VFormRender` / `searchFormDialog`) |