cloud-web-corejs 1.0.54-dev.712 → 1.0.54-dev.714

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 (18) hide show
  1. package/package.json +1 -1
  2. package/src/components/xform/docs/autocomplete /350/207/252/345/212/250/345/256/214/346/210/220/347/273/204/344/273/266/350/257/264/346/230/216.md" +11 -13
  3. package/src/components/xform/form-designer/form-widget/field-widget/autocomplete-widget.vue +47 -5
  4. package/src/components/xform/form-designer/form-widget/field-widget/baseAttachment-widget.vue +4 -10
  5. package/src/components/xform/form-designer/form-widget/field-widget/census-widget.vue +3 -9
  6. package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +16 -16
  7. package/src/components/xform/form-designer/form-widget/field-widget/form-item-wrapper.vue +1 -1
  8. package/src/components/xform/form-designer/form-widget/field-widget/mixins/autocomplete-mixin.js +123 -54
  9. package/src/components/xform/form-designer/form-widget/field-widget/mixins/echart-bar-mixin.js +3 -9
  10. package/src/components/xform/form-designer/form-widget/field-widget/mixins/echart-category-mixin.js +3 -9
  11. package/src/components/xform/form-designer/form-widget/field-widget/mixins/echart-pie-mixin.js +3 -9
  12. package/src/components/xform/form-designer/form-widget/field-widget/project-tag-widget.vue +4 -9
  13. package/src/components/xform/form-designer/form-widget/field-widget/vabUpload-widget.vue +4 -10
  14. package/src/components/xform/form-designer/setting-panel/property-editor/field-autocomplete/autocomplete-vabSearchName-editor.vue +54 -56
  15. package/src/components/xform/form-designer/setting-panel/property-editor/formScriptEnabled-editor.vue +7 -0
  16. package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +27 -19
  17. package/src/components/xform/form-render/container-item/list-h5-item.vue +20 -18
  18. package/src/components/xform/form-render/container-item/table2-item.vue +18 -10
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cloud-web-corejs",
3
3
  "private": false,
4
- "version": "1.0.54-dev.712",
4
+ "version": "1.0.54-dev.714",
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
7
7
  "lint": "eslint --ext .js,.vue src",
@@ -27,21 +27,19 @@
27
27
  在表单设计器左侧「高级字段」分组中拖入「自动完成」组件,右侧属性面板可配置:
28
28
 
29
29
  ### 自动完成设置(`autocomplete-vabSearchName-editor`)
30
- - **存储ID字段**(`valueField`):候选项数据中 ID 对应的字段名,留空则使用字段本身 `keyName`
31
- - **存储名称字段**(`vabSearchName`):选中后名称持久化到的表单字段名
32
- - **输入提示**(`placeholder`)
33
- - **可清空**(`clearable`)
34
- - **聚焦即查询**(`triggerOnFocus`):聚焦空输入框时是否触发一次查询
35
- - **防抖(ms)**(`debounce`):输入防抖毫秒数
36
- - **ID反查脚本编码**(`getByIdScriptCode`):选填,编辑态根据 ID 反查名称
37
- - **清空回调**(`onSearchClear`)
38
- - **下拉项模板**(`autocompleteItemTemplate`):脚本,入参 `item`,返回 HTML 字符串
30
+
31
+ 面板精简为核心配置(参考「搜索框」组件的精简风格):
32
+ - **来源ID字段**(`valueField`):候选项数据中 ID 对应的字段名,留空则使用字段本身 `keyName`;ID 始终存入字段本身
33
+ - **来源名称字段**(`vabSearchName`):候选项数据中名称对应的字段名,同时作为名称持久化的展示字段
39
34
  - **选中回填**(`autocompleteFillConfig`):数组,每项 `{ targetField, targetFormField, sourceField }`
40
35
 
41
- ### 请求访问设置(复用 `formScriptEnabled-editor`)
42
- - **表单脚本编码**(`formScriptCode`):远程搜索的后台逻辑脚本编码(必填)
43
- - **查询参数**(`formScriptParam`):脚本,返回额外请求参数对象
44
- - **查询回调**(`formScriptSuccess`):脚本,入参 `res`、`rows`,可返回处理后的数组
36
+ 其余通用项由标准编辑器提供:**输入提示**(`placeholder`)、**可清空**(`clearable`)在「常用设置」中配置;**清空回调**(`onSearchClear`)在「事件设置」中配置;**查询脚本编码**等在下方「请求访问设置」区块维护。
37
+
38
+ > 以下选项仍保留在 `autocompleteConfig` schema 中(保证旧表单兼容与运行时行为),但已从设计器面板移除,如需使用可直接写入组件 `options` JSON:
39
+ > - `triggerOnFocus`(默认 `true`):聚焦空输入框时是否触发一次查询
40
+ > - `debounce`(默认 `300`):输入防抖毫秒数
41
+ > - `getByIdScriptCode`:编辑态根据 ID 反查名称的脚本编码
42
+ > - `autocompleteItemTemplate`:自定义下拉项模板脚本(入参 `item`,返回 HTML 字符串)
45
43
 
46
44
  ## 远程搜索请求约定
47
45
 
@@ -14,16 +14,19 @@
14
14
  :placeholder="getI18nLabel(field.options.placeholder || '请输入关键词搜索')"
15
15
  :clearable="field.options.clearable"
16
16
  :fetch-suggestions="querySearchAsync"
17
- :trigger-on-focus="field.options.triggerOnFocus !== false"
17
+ :trigger-on-focus="false"
18
18
  :debounce="field.options.debounce || 300"
19
19
  :value-key="valueKey"
20
20
  :prefix-icon="field.options.prefixIcon"
21
- :suffix-icon="field.options.suffixIcon"
22
- :popper-class="field.options.customClass ? field.options.customClass.join(' ') : ''"
21
+ :suffix-icon="field.options.suffixIcon || 'el-icon-tickets'"
22
+ :popper-class="
23
+ 'autocomplete-popper' +
24
+ (field.options.customClass ? ' ' + field.options.customClass.join(' ') : '')
25
+ "
23
26
  @select="handleSelect"
24
27
  @clear="handleClear"
25
28
  @focus="handleFocusCustomEvent"
26
- @blur="handleBlurCustomEvent"
29
+ @blur="handleBlur"
27
30
  @input="handleInputChange"
28
31
  :style="'width:' + field.options.widgetWidth + ' !important;'"
29
32
  :class="{'custom-width': field.options.widgetWidth != null}">
@@ -33,7 +36,7 @@
33
36
  <span v-html="renderItemTemplate(item)"></span>
34
37
  </template>
35
38
  <template v-else>
36
- <span>{{ item[valueKey] }}</span>
39
+ <span v-html="highlightKeyword(item[valueKey])"></span>
37
40
  </template>
38
41
  </template>
39
42
  </el-autocomplete>
@@ -64,6 +67,30 @@ export default {
64
67
  return "";
65
68
  }
66
69
  },
70
+ /** HTML 转义,防止下拉项内容注入 */
71
+ escapeHtml(str) {
72
+ let map = {
73
+ "&": "&amp;",
74
+ "<": "&lt;",
75
+ ">": "&gt;",
76
+ '"': "&quot;",
77
+ "'": "&#39;",
78
+ };
79
+ return String(str == null ? "" : str).replace(/[&<>"']/g, (c) => map[c]);
80
+ },
81
+ /** 高亮下拉项中与当前搜索关键词匹配的部分 */
82
+ highlightKeyword(text) {
83
+ let escaped = this.escapeHtml(text);
84
+ let keyword = this.lastQueryKeyword;
85
+ if (!keyword) return escaped;
86
+ let kw = this.escapeHtml(keyword).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
87
+ if (!kw) return escaped;
88
+ let re = new RegExp("(" + kw + ")", "gi");
89
+ return escaped.replace(
90
+ re,
91
+ '<span class="autocomplete-highlight">$1</span>'
92
+ );
93
+ },
67
94
  },
68
95
  }
69
96
  </script>
@@ -75,3 +102,18 @@ export default {
75
102
  width: 100% !important;
76
103
  }
77
104
  </style>
105
+
106
+ <!-- 非 scoped:el-autocomplete 下拉浮层挂在 body 下,scoped 样式无法命中 -->
107
+ <style lang="scss">
108
+ .autocomplete-popper {
109
+ .el-autocomplete-suggestion__list li {
110
+ font-size: 13px;
111
+ line-height: 1.6;
112
+ }
113
+ }
114
+
115
+ .autocomplete-highlight {
116
+ color: #409eff;
117
+ font-weight: bold;
118
+ }
119
+ </style>
@@ -160,20 +160,14 @@ export default {
160
160
  let dataId = this.formDataId;
161
161
  if (!dataId) return;
162
162
  let reportTemplate = this.getFormRef().reportTemplate;
163
- let formCode = reportTemplate.formCode;
164
163
  if (dataId) {
165
164
  let accessParam = this.handleCustomEvent(this.field.options.formScriptParam)
166
165
  return this.formHttp({
167
166
  url: "/" + reportTemplate.serviceName + "/form_ins/getList",
168
- data: {
169
- formCode: formCode,
170
- formVersion: reportTemplate.formVersion,
171
- taBm: this.fieldKeyName,
172
- data: {
173
- ...accessParam,
174
- id: dataId
175
- }
176
- },
167
+ data: this.buildFormScriptData(reportTemplate, {
168
+ ...accessParam,
169
+ id: dataId
170
+ }),
177
171
  callback: res => {
178
172
  let rows = res.objx || [];
179
173
  this.setValue(rows)
@@ -137,18 +137,12 @@ export default {
137
137
  let scriptCode = this.field.options.formScriptCode;
138
138
  if (!scriptCode) return;
139
139
  let reportTemplate = this.getFormRef().reportTemplate;
140
- let formCode = reportTemplate.formCode;
141
140
  let accessParam = this.handleCustomEvent(this.field.options.formScriptParam);
142
141
  return this.formHttp({
143
142
  scriptCode: scriptCode,
144
- data: {
145
- formCode: formCode,
146
- formVersion: reportTemplate.formVersion,
147
- taBm: this.fieldKeyName,
148
- data: {
149
- ...accessParam,
150
- },
151
- },
143
+ data: this.buildFormScriptData(reportTemplate, {
144
+ ...accessParam,
145
+ }),
152
146
  callback: (res) => {
153
147
  let data = res.objx || {};
154
148
  this.fieldModel = data;
@@ -717,14 +717,7 @@ modules = {
717
717
  );
718
718
  return this.formHttp({
719
719
  scriptCode: scriptCode,
720
- data: {
721
- formCode: formCode,
722
- formVersion: reportTemplate.formVersion,
723
- taBm: this.fieldKeyName,
724
- data: {
725
- ...accessParam,
726
- },
727
- },
720
+ data: this.buildFormScriptData(reportTemplate, { ...accessParam }),
728
721
  callback: (res) => {
729
722
  let rows = res.objx?.records || res.objx || [];
730
723
  this.loadGloatOptions(rows, initFlag);
@@ -767,6 +760,20 @@ modules = {
767
760
  return;
768
761
  }
769
762
  },
763
+ /**
764
+ * 构造表单脚本请求的 data 参数(通用)。
765
+ * 勾选"请求去掉data层"(removeDataLevel)时,内层参数平铺到外层,不再包一层 data。
766
+ */
767
+ buildFormScriptData: function (reportTemplate, innerData, taBm) {
768
+ let base = {
769
+ formCode: reportTemplate.formCode,
770
+ formVersion: reportTemplate.formVersion,
771
+ taBm: taBm || this.fieldKeyName,
772
+ };
773
+ return this.field.options.removeDataLevel
774
+ ? { ...base, ...(innerData || {}) }
775
+ : { ...base, data: innerData || {} };
776
+ },
770
777
  loadGloatOptions: function (e, initFlag) {
771
778
  let optionItems = baseRefUtil.translateOptionItems(
772
779
  e,
@@ -859,14 +866,7 @@ modules = {
859
866
  );
860
867
  return this.formHttp({
861
868
  scriptCode: scriptCode,
862
- data: {
863
- formCode: formCode,
864
- formVersion: reportTemplate.formVersion,
865
- taBm: this.fieldKeyName,
866
- data: {
867
- ...accessParam,
868
- },
869
- },
869
+ data: this.buildFormScriptData(reportTemplate, { ...accessParam }),
870
870
  callback: (res) => {
871
871
  let rows = res.objx || [];
872
872
  this.loadOptions(rows);
@@ -288,7 +288,7 @@ export default {
288
288
 
289
289
  if (!!this.designer) {
290
290
  return this.designer.formConfig.labelWidth + "px";
291
- } else {
291
+ } else {
292
292
  return this.formConfig.labelWidth + "px";
293
293
  }
294
294
  },
@@ -59,28 +59,51 @@ export default {
59
59
  currentData[fieldKeyName] = val;
60
60
  },
61
61
  showValue(val) {
62
- //外部回显:当 currentData[labelField] 变化时,同步到输入框
62
+ //外部回显:当 currentData[displayField] 变化时,同步到输入框
63
63
  this.displayValue = val;
64
64
  },
65
65
  },
66
66
  computed: {
67
67
  /**
68
- * 选项数据中"ID/值"对应的字段名
68
+ * 关联来源字段:候选数据中"ID/值"对应的字段名
69
69
  */
70
70
  valueField() {
71
71
  return trim(this.field.options.valueField) || this.fieldKeyName;
72
72
  },
73
73
  /**
74
- * 选项数据中"名称"对应的字段名(同时作为持久化到表单数据的展示字段)
74
+ * 展示来源字段:候选数据中"名称"对应的字段名
75
+ * (为空时回退展示字段 vabSearchName,再回退字段本身,保证旧表单兼容)
75
76
  */
76
- labelField() {
77
+ sourceLabelField() {
78
+ return (
79
+ trim(this.field.options.labelSourceField) ||
80
+ trim(this.field.options.vabSearchName) ||
81
+ this.fieldKeyName
82
+ );
83
+ },
84
+ /**
85
+ * 展示字段:表单数据中持久化"名称"的字段(用于存储与回显)
86
+ */
87
+ displayField() {
77
88
  return trim(this.field.options.vabSearchName) || this.fieldKeyName;
78
89
  },
79
90
  /**
80
- * el-autocomplete 下拉项展示用的 value-key
91
+ * el-autocomplete 下拉项展示用的 value-key(取自候选数据的展示来源字段)
81
92
  */
82
93
  valueKey() {
83
- return this.labelField;
94
+ return this.sourceLabelField;
95
+ },
96
+ /**
97
+ * 查询字段:远程搜索时关键词传给后台的参数名(默认 keyword)
98
+ */
99
+ queryField() {
100
+ return trim(this.field.options.queryField) || "keyword";
101
+ },
102
+ /**
103
+ * condition格式下查询的数据表 taBm(留空取字段本身 keyName)
104
+ */
105
+ conditionTaBm() {
106
+ return trim(this.field.options.conditionTaBm) || this.fieldKeyName;
84
107
  },
85
108
  tableRow() {
86
109
  let tableParam = this.tableParam;
@@ -95,8 +118,8 @@ export default {
95
118
  */
96
119
  showValue() {
97
120
  let currentData = this.currentData;
98
- let labelField = this.labelField;
99
- let value = currentData[labelField] ?? null;
121
+ let displayField = this.displayField;
122
+ let value = currentData[displayField] ?? null;
100
123
  this.displayValue = value;
101
124
  return value;
102
125
  },
@@ -122,7 +145,7 @@ export default {
122
145
  this.$nextTick(() => {
123
146
  if (this.designState) return;
124
147
  let id = this.fieldModel;
125
- let label = this.currentData[this.labelField];
148
+ let label = this.currentData[this.displayField];
126
149
  if (this.isNotNullVal(id) && !this.isNotNullVal(label)) {
127
150
  this.fetchLabelById(id);
128
151
  }
@@ -138,8 +161,8 @@ export default {
138
161
  * 设置展示名称到当前数据行/表单模型,并同步到输入框
139
162
  */
140
163
  setShowValue(val = null) {
141
- let labelField = this.labelField;
142
- this.currentData[labelField] = val;
164
+ let displayField = this.displayField;
165
+ this.currentData[displayField] = val;
143
166
  this.displayValue = val;
144
167
  },
145
168
  setValue: function (e) {
@@ -174,8 +197,15 @@ export default {
174
197
  cb([]);
175
198
  return;
176
199
  }
177
- //避免对相同关键词重复查询(el-autocomplete focus/input 都会触发)
200
+ //需要有内容才执行搜索:关键词为空(含聚焦触发的空串)时不查询
178
201
  let keyword = queryString == null ? "" : String(queryString);
202
+ if (!trim(keyword)) {
203
+ this.lastQueryKeyword = null;
204
+ this._lastSuggestions = null;
205
+ cb([]);
206
+ return;
207
+ }
208
+ //避免对相同关键词重复查询(el-autocomplete focus/input 都会触发)
179
209
  if (
180
210
  keyword === this.lastQueryKeyword
181
211
  && this._lastSuggestions
@@ -187,20 +217,38 @@ export default {
187
217
  this.lastQueryKeyword = keyword;
188
218
 
189
219
  let reportTemplate = this.getFormRef().reportTemplate;
190
- let formCode = reportTemplate.formCode;
191
220
  let accessParam = this.handleCustomEvent(
192
221
  this.field.options.formScriptParam
193
222
  );
194
- let taBm = this.fieldKeyName;
195
- let data = {
196
- formCode: formCode,
197
- formVersion: reportTemplate.formVersion,
198
- taBm: taBm,
199
- data: {
223
+ let innerData;
224
+ if (this.field.options.conditionFormat) {
225
+ //condition 传值格式:关键词以 { field, value, filter:'like' } 追加到 condition 数组
226
+ let extra = accessParam || {};
227
+ let conditions = Array.isArray(extra.condition)
228
+ ? extra.condition.slice()
229
+ : [];
230
+ conditions.push({
231
+ value: keyword,
232
+ field: this.queryField,
233
+ filter: "like",
234
+ });
235
+ innerData = {
236
+ current: 1,
237
+ size: this.field.options.conditionSize || 100,
238
+ searchCount: true,
239
+ ...extra,
240
+ condition: conditions,
241
+ };
242
+ } else {
243
+ innerData = {
200
244
  ...accessParam,
201
- keyword: keyword,
202
- },
203
- };
245
+ [this.queryField]: keyword,
246
+ };
247
+ }
248
+ let taBm = this.field.options.conditionFormat
249
+ ? this.conditionTaBm
250
+ : undefined;
251
+ let data = this.buildFormScriptData(reportTemplate, innerData, taBm);
204
252
  return this.formHttp({
205
253
  scriptCode: scriptCode,
206
254
  isLoading: false,
@@ -234,9 +282,9 @@ export default {
234
282
  this.isSelecting = true;
235
283
  try {
236
284
  let valueField = this.valueField;
237
- let labelField = this.labelField;
285
+ let sourceLabelField = this.sourceLabelField;
238
286
  let id = item[valueField] ?? null;
239
- let label = item[labelField] ?? null;
287
+ let label = item[sourceLabelField] ?? null;
240
288
 
241
289
  //存储 ID(提交字段)
242
290
  this.setValue(id);
@@ -286,33 +334,34 @@ export default {
286
334
  }
287
335
  },
288
336
  /**
289
- * 输入框内容变化:若非"选中"触发,且与已存储名称不一致,则清空 ID(用户正在重新搜索)
337
+ * 输入框内容变化:仅派发校验与自定义 onInput,不清除已存储的 ID/名称。
338
+ * 用户输入但未选择、直接失焦时,由 handleBlur 还原为已存储的展示名称。
290
339
  */
291
340
  handleInputChange(text) {
292
341
  if (this.isSelecting) return;
293
- if (!this.designState) {
294
- if (!text) {
295
- //输入框被清空(非通过 clear 按钮)
296
- this.setValue(null);
297
- this.setShowValue(null);
298
- return;
299
- }
300
- let storedLabel = this.currentData[this.labelField];
301
- if (text !== storedLabel) {
302
- //用户手动输入了与已选中名称不同的内容,清空已存储的 ID 与名称
303
- this.fieldModel = null;
304
- this.currentData[this.fieldKeyName] = null;
305
- this.currentData[this.labelField] = null;
306
- this.oldFieldValue = null;
307
- }
308
- }
309
- //同步到表单模型并派发校验
310
342
  this.dispatch("VFormRender", "fieldValidation", [this.getPropName()]);
311
343
  if (this.field.options.onInput) {
312
344
  let fn = new Function("value", this.field.options.onInput);
313
345
  fn.call(this, text);
314
346
  }
315
347
  },
348
+ /**
349
+ * 失焦:若未通过"选择"确认新值,则把输入框内容还原为已存储的展示名称
350
+ * (已存储 ID 保持不变;从未选择过则清空输入框)。
351
+ */
352
+ handleBlur(e) {
353
+ if (!this.designState) {
354
+ //延迟到"选择"事件之后再还原,避免点击下拉项时被误还原
355
+ setTimeout(() => {
356
+ if (this.isSelecting) return;
357
+ let storedLabel = this.currentData[this.displayField] ?? null;
358
+ if (this.displayValue !== storedLabel) {
359
+ this.displayValue = storedLabel;
360
+ }
361
+ }, 150);
362
+ }
363
+ this.handleBlurCustomEvent(e);
364
+ },
316
365
  /**
317
366
  * 根据回填配置把选中项的其他字段值写入表单
318
367
  */
@@ -337,7 +386,7 @@ export default {
337
386
  },
338
387
  /**
339
388
  * 通过 ID 反查名称(编辑态回显场景)。
340
- * 当 fieldModel 有值但 currentData[labelField] 为空时调用。
389
+ * 当 fieldModel 有值但 currentData[displayField] 为空时调用。
341
390
  */
342
391
  fetchLabelById(id) {
343
392
  let formScriptEnabled = this.field.options.formScriptEnabled || false;
@@ -347,27 +396,47 @@ export default {
347
396
  //优先使用专用的 getById 脚本;否则不自动反查
348
397
  if (!getByIdScriptCode) return;
349
398
  let reportTemplate = this.getFormRef().reportTemplate;
350
- let formCode = reportTemplate.formCode;
351
399
  let accessParam = this.handleCustomEvent(
352
400
  this.field.options.formScriptParam
353
401
  );
402
+ let innerData;
403
+ if (this.field.options.conditionFormat) {
404
+ //condition 传值格式:按 关联来源字段 eq id 反查
405
+ let extra = accessParam || {};
406
+ let conditions = Array.isArray(extra.condition)
407
+ ? extra.condition.slice()
408
+ : [];
409
+ conditions.push({
410
+ value: id,
411
+ field: this.valueField,
412
+ filter: "eq",
413
+ });
414
+ innerData = {
415
+ current: 1,
416
+ size: this.field.options.conditionSize || 100,
417
+ searchCount: true,
418
+ ...extra,
419
+ condition: conditions,
420
+ };
421
+ } else {
422
+ innerData = {
423
+ ...accessParam,
424
+ id: id,
425
+ };
426
+ }
427
+ let taBm = this.field.options.conditionFormat
428
+ ? this.conditionTaBm
429
+ : undefined;
430
+ let data = this.buildFormScriptData(reportTemplate, innerData, taBm);
354
431
  return this.formHttp({
355
432
  scriptCode: getByIdScriptCode,
356
433
  isLoading: false,
357
- data: {
358
- formCode: formCode,
359
- formVersion: reportTemplate.formVersion,
360
- taBm: this.fieldKeyName,
361
- data: {
362
- ...accessParam,
363
- id: id,
364
- },
365
- },
434
+ data: data,
366
435
  callback: (res) => {
367
436
  let rows = res.objx?.records || res.objx || [];
368
437
  let row = Array.isArray(rows) ? rows[0] : rows;
369
438
  if (row) {
370
- let label = row[this.labelField] ?? null;
439
+ let label = row[this.sourceLabelField] ?? null;
371
440
  this.setShowValue(label);
372
441
  }
373
442
  },
@@ -376,21 +376,15 @@ modules = {
376
376
  },*/
377
377
  loadDataDefaultHandle() {
378
378
  let reportTemplate = this.getFormRef().reportTemplate;
379
- let formCode = reportTemplate.formCode;
380
379
  let formScriptEnabled = this.field.options.formScriptEnabled || false;
381
380
  let scriptCode = this.field.options.formScriptCode
382
381
  if (!scriptCode) return;
383
382
  let accessParam = this.handleCustomEvent(this.field.options.formScriptParam)
384
383
  return this.formHttp({
385
384
  scriptCode: scriptCode,
386
- data: {
387
- formCode: formCode,
388
- formVersion: reportTemplate.formVersion,
389
- taBm: this.fieldKeyName,
390
- data: {
391
- ...accessParam
392
- }
393
- },
385
+ data: this.buildFormScriptData(reportTemplate, {
386
+ ...accessParam
387
+ }),
394
388
  callback: res => {
395
389
  let rows = res.objx || [];
396
390
  this.setValue(rows)
@@ -248,21 +248,15 @@ modules = {
248
248
  },*/
249
249
  loadDataDefaultHandle() {
250
250
  let reportTemplate = this.getFormRef().reportTemplate;
251
- let formCode = reportTemplate.formCode;
252
251
  let formScriptEnabled = this.field.options.formScriptEnabled || false;
253
252
  let scriptCode = this.field.options.formScriptCode
254
253
  if (!scriptCode) return;
255
254
  let accessParam = this.handleCustomEvent(this.field.options.formScriptParam)
256
255
  return this.formHttp({
257
256
  scriptCode: scriptCode,
258
- data: {
259
- formCode: formCode,
260
- formVersion: reportTemplate.formVersion,
261
- taBm: this.fieldKeyName,
262
- data: {
263
- ...accessParam
264
- }
265
- },
257
+ data: this.buildFormScriptData(reportTemplate, {
258
+ ...accessParam
259
+ }),
266
260
  callback: res => {
267
261
  let rows = res.objx || [];
268
262
  this.setValue(rows)
@@ -171,21 +171,15 @@ modules = {
171
171
  },*/
172
172
  loadDataDefaultHandle() {
173
173
  let reportTemplate = this.getFormRef().reportTemplate;
174
- let formCode = reportTemplate.formCode;
175
174
  let formScriptEnabled = this.field.options.formScriptEnabled || false;
176
175
  let scriptCode = this.field.options.formScriptCode
177
176
  if (!scriptCode) return;
178
177
  let accessParam = this.handleCustomEvent(this.field.options.formScriptParam)
179
178
  return this.formHttp({
180
179
  scriptCode: scriptCode,
181
- data: {
182
- formCode: formCode,
183
- formVersion: reportTemplate.formVersion,
184
- taBm: this.fieldKeyName,
185
- data: {
186
- ...accessParam
187
- }
188
- },
180
+ data: this.buildFormScriptData(reportTemplate, {
181
+ ...accessParam
182
+ }),
189
183
  callback: res => {
190
184
  let rows = res.objx || [];
191
185
  this.setValue(rows)
@@ -154,15 +154,10 @@ export default {
154
154
  let accessParam = this.handleCustomEvent(this.field.options.formScriptParam);
155
155
  return this.formHttp({
156
156
  scriptCode: scriptCode,
157
- data: {
158
- formCode: formCode,
159
- formVersion: reportTemplate.formVersion,
160
- taBm: this.fieldKeyName,
161
- data: {
162
- ...accessParam,
163
- id: dataId,
164
- },
165
- },
157
+ data: this.buildFormScriptData(reportTemplate, {
158
+ ...accessParam,
159
+ id: dataId,
160
+ }),
166
161
  callback: (res) => {
167
162
  let rows = res.objx || [];
168
163
  this.setValue(rows);
@@ -137,7 +137,6 @@ export default {
137
137
  let dataId = this.formDataId;
138
138
  if (!dataId) return;
139
139
  let reportTemplate = this.getFormRef().reportTemplate;
140
- let formCode = reportTemplate.formCode;
141
140
  let formScriptEnabled = this.field.options.formScriptEnabled || false;
142
141
  let scriptCode = this.field.options.formScriptCode || "getList";
143
142
  if (!scriptCode) return;
@@ -148,15 +147,10 @@ export default {
148
147
  return this.formHttp({
149
148
  // url: "/" + reportTemplate.serviceName + "/form_ins/getList",
150
149
  scriptCode: scriptCode,
151
- data: {
152
- formCode: formCode,
153
- formVersion: reportTemplate.formVersion,
154
- taBm: this.fieldKeyName,
155
- data: {
156
- ...accessParam,
157
- id: dataId,
158
- },
159
- },
150
+ data: this.buildFormScriptData(reportTemplate, {
151
+ ...accessParam,
152
+ id: dataId,
153
+ }),
160
154
  callback: (res) => {
161
155
  let rows = res.objx || [];
162
156
  this.setValue(rows);
@@ -4,76 +4,56 @@
4
4
  <el-divider class="custom-divider-margin-top">自动完成设置</el-divider>
5
5
  </el-form-item>
6
6
 
7
- <el-form-item label="存储ID字段">
7
+ <el-form-item label="展示字段">
8
+ <el-input
9
+ type="text"
10
+ v-model="optionModel.vabSearchName"
11
+ placeholder="表单中存储名称的字段"
12
+ ></el-input>
13
+ </el-form-item>
14
+ <el-form-item label="关联来源字段">
8
15
  <el-input
9
16
  type="text"
10
17
  v-model="optionModel.valueField"
11
- placeholder="留空则使用字段本身"
18
+ placeholder="候选数据中作为值/ID的字段(默认字段本身),值存入字段本身"
12
19
  ></el-input>
13
20
  </el-form-item>
14
- <el-form-item label="存储名称字段">
21
+ <el-form-item label="展示来源字段">
15
22
  <el-input
16
23
  type="text"
17
- v-model="optionModel.vabSearchName"
18
- placeholder="存储展示名称的字段名"
24
+ v-model="optionModel.labelSourceField"
25
+ placeholder="候选数据中作为名称的字段(默认取展示字段)"
19
26
  ></el-input>
20
27
  </el-form-item>
21
- <el-form-item label="输入提示">
28
+ <el-form-item label="查询字段">
22
29
  <el-input
23
30
  type="text"
24
- v-model="optionModel.placeholder"
31
+ v-model="optionModel.queryField"
32
+ placeholder="condition格式时为字段名,否则为参数名(默认 keyword)"
25
33
  ></el-input>
26
34
  </el-form-item>
27
- <el-form-item label="可清空">
28
- <el-switch v-model="optionModel.clearable"></el-switch>
35
+ <el-form-item label="condition传值格式">
36
+ <el-switch v-model="optionModel.conditionFormat"></el-switch>
29
37
  </el-form-item>
30
- <el-form-item label="聚焦即查询">
31
- <el-switch v-model="optionModel.triggerOnFocus"></el-switch>
38
+ <el-form-item label="查询数据表">
39
+ <el-input
40
+ type="text"
41
+ v-model="optionModel.conditionTaBm"
42
+ placeholder="condition查询的数据表taBm(留空取字段本身)"
43
+ ></el-input>
32
44
  </el-form-item>
33
- <el-form-item label="防抖(ms)">
45
+ <el-form-item label="查询条数">
34
46
  <el-input-number
35
- v-model="optionModel.debounce"
36
- :min="0"
37
- :max="2000"
38
- :step="100"
47
+ v-model="optionModel.conditionSize"
48
+ :min="1"
39
49
  controls-position="right"
40
50
  style="width: 100%"
41
51
  ></el-input-number>
42
52
  </el-form-item>
43
53
 
44
- <el-form-item label="ID反查脚本编码">
45
- <el-input
46
- type="text"
47
- v-model="optionModel.getByIdScriptCode"
48
- placeholder="选填,编辑态根据ID反查名称"
49
- ></el-input>
50
- </el-form-item>
51
-
52
- <el-form-item label="清空回调">
53
- <a
54
- href="javascript:void(0);"
55
- class="a-link link-oneLind"
56
- @click="editEventHandler('onSearchClear', ['rowData', 'rowIndex'])"
57
- >
58
- <span>{{ optionModel.onSearchClear }}</span>
59
- <i class="el-icon-edit"></i>
60
- </a>
61
- </el-form-item>
62
-
63
- <el-form-item label="下拉项模板">
64
- <a
65
- href="javascript:void(0);"
66
- class="a-link link-oneLind"
67
- @click="editEventHandler('autocompleteItemTemplate', ['item'])"
68
- >
69
- <span>{{ optionModel.autocompleteItemTemplate }}</span>
70
- <i class="el-icon-edit"></i>
71
- </a>
72
- </el-form-item>
73
-
74
54
  <el-form-item label="选中回填">
75
55
  <el-button type="primary" plain round @click="showFillDialog = true">
76
- {{ i18nt('designer.setting.editAction') }}
56
+ {{ i18nt("designer.setting.editAction") }}
77
57
  </el-button>
78
58
  </el-form-item>
79
59
 
@@ -99,12 +79,20 @@
99
79
  border
100
80
  stripe
101
81
  >
102
- <el-table-column label="目标字段(组件名)" width="180" prop="targetField">
82
+ <el-table-column
83
+ label="目标字段(组件名)"
84
+ width="180"
85
+ prop="targetField"
86
+ >
103
87
  <template slot-scope="scope">
104
88
  <el-input v-model="scope.row.targetField"></el-input>
105
89
  </template>
106
90
  </el-table-column>
107
- <el-table-column label="目标数据属性" width="180" prop="targetFormField">
91
+ <el-table-column
92
+ label="目标数据属性"
93
+ width="180"
94
+ prop="targetFormField"
95
+ >
108
96
  <template slot-scope="scope">
109
97
  <el-input v-model="scope.row.targetFormField"></el-input>
110
98
  </template>
@@ -147,12 +135,23 @@
147
135
  </el-table>
148
136
  </div>
149
137
  <div class="dialog-footer" slot="footer">
150
- <span class="fl tips">注:'目标字段'与'目标数据属性'只需维护一个即可。</span>
151
- <el-button @click="showFillDialog = false" class="button-sty" icon="el-icon-close">
152
- {{ i18nt('designer.hint.cancel') }}
138
+ <span class="fl tips"
139
+ >注:'目标字段'与'目标数据属性'只需维护一个即可。</span
140
+ >
141
+ <el-button
142
+ @click="showFillDialog = false"
143
+ class="button-sty"
144
+ icon="el-icon-close"
145
+ >
146
+ {{ i18nt("designer.hint.cancel") }}
153
147
  </el-button>
154
- <el-button type="primary" @click="confirmFillDialog" class="button-sty" icon="el-icon-check">
155
- {{ i18nt('designer.hint.confirm') }}
148
+ <el-button
149
+ type="primary"
150
+ @click="confirmFillDialog"
151
+ class="button-sty"
152
+ icon="el-icon-check"
153
+ >
154
+ {{ i18nt("designer.hint.confirm") }}
156
155
  </el-button>
157
156
  </div>
158
157
  </el-dialog>
@@ -161,12 +160,11 @@
161
160
 
162
161
  <script>
163
162
  import i18n from "../../../../../../components/xform/utils/i18n";
164
- import eventMixin from "../../../../../../components/xform/form-designer/setting-panel/property-editor/event-handler/eventMixin";
165
163
  import propertyMixin from "../../../../../../components/xform/form-designer/setting-panel/property-editor/propertyMixin";
166
164
 
167
165
  export default {
168
166
  name: "autocomplete-vabSearchName-editor",
169
- mixins: [i18n, eventMixin, propertyMixin],
167
+ mixins: [i18n, propertyMixin],
170
168
  props: {
171
169
  designer: Object,
172
170
  selectedWidget: Object,
@@ -58,6 +58,12 @@
58
58
  <el-input type="text" v-model="optionModel.valueKey" :disabled="optionModel.commonAttributeEnabled"></el-input>
59
59
  </el-form-item> -->
60
60
  </template>
61
+ <el-form-item
62
+ label="请求去掉data层"
63
+ v-if="optionModel.formScriptEnabled"
64
+ >
65
+ <el-switch v-model="optionModel.removeDataLevel"></el-switch>
66
+ </el-form-item>
61
67
  <el-form-item
62
68
  label="查询回调"
63
69
  v-if="optionModel.formScriptEnabled || optionModel.commonAttributeEnabled"
@@ -98,6 +104,7 @@ export default {
98
104
  "status",
99
105
  "gantt",
100
106
  "cascader",
107
+ "autocomplete",
101
108
  ],
102
109
  };
103
110
  },
@@ -1,3 +1,18 @@
1
+ // 注意:httpConfig 需在 containers / autocompleteConfig 等使用处之前声明,
2
+ // 否则经 Babel 转译(const→var 提升,丢失 TDZ)后 ...httpConfig 会展开 undefined(为空),
3
+ // 导致相关组件丢失 formScriptEnabled 等「请求访问设置」字段。
4
+ const httpConfig = {
5
+ httpFormCode: null,
6
+ formScriptEnabled: true,
7
+ commonAttributeEnabled: false,
8
+ formScriptCode: null,
9
+ formScriptParam: null,
10
+ formScriptSuccess: null,
11
+ formScriptCallback: null,
12
+ //请求去掉data层:勾选后请求参数不再包一层 data
13
+ removeDataLevel: false,
14
+ };
15
+
1
16
  export const containers = [
2
17
  {
3
18
  type: "grid",
@@ -908,22 +923,25 @@ const autocompleteConfig = {
908
923
  customClass: [],
909
924
  placeholder: "请输入关键词搜索",
910
925
  clearable: true,
911
- //el-autocomplete 相关
912
- triggerOnFocus: true,
913
- debounce: 300,
926
+ //查询字段:远程搜索时关键词传给后台的参数名(默认 keyword)
927
+ queryField: "keyword",
928
+ //condition传值格式:勾选后关键词以 { condition:[{field,value,filter:'like'}], current,size,searchCount } 结构传递
929
+ conditionFormat: true,
930
+ //condition格式下的分页条数
931
+ conditionSize: 200,
932
+ //condition格式下查询的数据表(taBm),留空则取字段本身 keyName
933
+ conditionTaBm: null,
914
934
  prefixIcon: null,
915
935
  suffixIcon: null,
916
- //选项数据中"值/ID"对应的字段名(为空时取字段本身 keyName)
936
+ //关联来源字段:候选数据中"值/ID"对应的字段名(为空时取字段本身 keyName),值存入字段本身
917
937
  valueField: null,
938
+ //展示来源字段:候选数据中"名称"对应的字段名(为空时回退 vabSearchName,再回退字段本身 keyName)
939
+ labelSourceField: null,
918
940
  //远程搜索后台逻辑脚本配置(复用 httpConfig)
919
941
  ...httpConfig,
920
- formScriptCode: null,
921
- //通过 ID 反查名称的脚本编码(可选,用于编辑态回显)
922
- getByIdScriptCode: null,
942
+ formScriptCode: "getPage",
923
943
  //选中后回填其他表单字段的配置
924
944
  autocompleteFillConfig: [],
925
- //自定义下拉项模板脚本(可选,入参 item,返回 HTML 字符串)
926
- autocompleteItemTemplate: null,
927
945
  //事件
928
946
  onCreated: "",
929
947
  onMounted: "",
@@ -980,16 +998,6 @@ const projectTagConfig = {
980
998
  tagWidth: "",
981
999
  };
982
1000
 
983
- const httpConfig = {
984
- httpFormCode: null,
985
- formScriptEnabled: true,
986
- commonAttributeEnabled: false,
987
- formScriptCode: null,
988
- formScriptParam: null,
989
- formScriptSuccess: null,
990
- formScriptCallback: null,
991
- };
992
-
993
1001
  export const hiddenWidgetTypesOfWf = [
994
1002
  "button",
995
1003
  "search_button",
@@ -1431,9 +1431,22 @@ export default {
1431
1431
  queryCreateInfo: window.$vueRoot.$store.getters.queryCreateInfo || "0",
1432
1432
  };
1433
1433
  },
1434
+ /**
1435
+ * 构造表单脚本请求的 data 参数(通用)。
1436
+ * 勾选"请求去掉data层"(removeDataLevel)时,内层参数平铺到外层,不再包一层 data。
1437
+ */
1438
+ buildFormScriptData(reportTemplate, innerData, taBm) {
1439
+ let base = {
1440
+ formCode: reportTemplate.formCode,
1441
+ formVersion: reportTemplate.formVersion,
1442
+ taBm: taBm || this.fieldKeyName,
1443
+ };
1444
+ return this.widget.options.removeDataLevel
1445
+ ? { ...base, ...(innerData || {}) }
1446
+ : { ...base, data: innerData || {} };
1447
+ },
1434
1448
  loadDefaultQueryList(reqData, done) {
1435
1449
  let reportTemplate = this.getFormRef().reportTemplate;
1436
- let formCode = reportTemplate.formCode;
1437
1450
  let scriptCode = this.getScriptCode();
1438
1451
  let accessParam = this.getAccessParam() || {};
1439
1452
  let otherParam = {};
@@ -1449,12 +1462,7 @@ export default {
1449
1462
  requestData = extendDeeply(requestData, accessParam);
1450
1463
  return this.formHttp({
1451
1464
  scriptCode: scriptCode,
1452
- data: {
1453
- formCode: formCode,
1454
- formVersion: reportTemplate.formVersion,
1455
- taBm: this.fieldKeyName,
1456
- data: requestData,
1457
- },
1465
+ data: this.buildFormScriptData(reportTemplate, requestData),
1458
1466
  isLoading: false,
1459
1467
  ...defaultOption,
1460
1468
  callback: (res) => {
@@ -1465,7 +1473,6 @@ export default {
1465
1473
  loadDefaultViewList() {
1466
1474
  let dataId = this.formDataId;
1467
1475
  let reportTemplate = this.getFormRef().reportTemplate;
1468
- let formCode = reportTemplate.formCode;
1469
1476
  let accessParam = this.getAccessParam() || {};
1470
1477
  let otherParam = {};
1471
1478
  let attachmentType = this.getAttachmentType();
@@ -1475,16 +1482,11 @@ export default {
1475
1482
  let scriptCode = this.getScriptCode();
1476
1483
  return this.formHttp({
1477
1484
  scriptCode: scriptCode,
1478
- data: {
1479
- formCode: formCode,
1480
- formVersion: reportTemplate.formVersion,
1481
- taBm: this.fieldKeyName,
1482
- data: {
1483
- id: dataId,
1484
- ...otherParam,
1485
- ...accessParam,
1486
- },
1487
- },
1485
+ data: this.buildFormScriptData(reportTemplate, {
1486
+ id: dataId,
1487
+ ...otherParam,
1488
+ ...accessParam,
1489
+ }),
1488
1490
  callback: (res) => {
1489
1491
  let rows = res.objx ? res.objx.records || res.objx || [] : [];
1490
1492
  this.setValue(rows);
@@ -207,13 +207,26 @@ export default {
207
207
  this.widget.rows.length = 0;
208
208
  this.widget.rows.push(...widgetRows);
209
209
  },
210
+ /**
211
+ * 构造表单脚本请求的 data 参数(通用)。
212
+ * 勾选"请求去掉data层"(removeDataLevel)时,内层参数平铺到外层,不再包一层 data。
213
+ */
214
+ buildFormScriptData(reportTemplate, innerData, taBm) {
215
+ let base = {
216
+ formCode: reportTemplate.formCode,
217
+ formVersion: reportTemplate.formVersion,
218
+ taBm: taBm || this.fieldKeyName,
219
+ };
220
+ return this.widget.options.removeDataLevel
221
+ ? { ...base, ...(innerData || {}) }
222
+ : { ...base, data: innerData || {} };
223
+ },
210
224
  loadDataDefaultHandle(flag) {
211
225
  // this.init();
212
226
  // return
213
227
  let dataId = this.formDataId;
214
228
  if (flag !== true && !dataId) return;
215
229
  let reportTemplate = this.getFormRef().reportTemplate;
216
- let formCode = reportTemplate.formCode;
217
230
  let formScriptEnabled = this.widget.options.formScriptEnabled || false;
218
231
  let scriptCode = this.widget.options.formScriptCode;
219
232
  if (!scriptCode) return;
@@ -222,15 +235,10 @@ export default {
222
235
  );
223
236
  return this.formHttp({
224
237
  scriptCode: scriptCode,
225
- data: {
226
- formCode: formCode,
227
- formVersion: reportTemplate.formVersion,
228
- taBm: this.fieldKeyName,
229
- data: {
230
- id: dataId,
231
- ...accessParam,
232
- },
233
- },
238
+ data: this.buildFormScriptData(reportTemplate, {
239
+ id: dataId,
240
+ ...accessParam,
241
+ }),
234
242
  success: (res) => {
235
243
  let rows = res.objx || [];
236
244
  this.handleCustomEvent(