cloud-web-corejs 1.0.54-dev.727 → 1.0.54-dev.729

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cloud-web-corejs",
3
3
  "private": false,
4
- "version": "1.0.54-dev.727",
4
+ "version": "1.0.54-dev.729",
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
7
7
  "lint": "eslint --ext .js,.vue src",
@@ -12,9 +12,10 @@
12
12
  | 字段 | 类型 | 默认 | 含义 |
13
13
  |------|------|------|------|
14
14
  | `addTabEnabled` | Boolean | `false` | 新增打开独立页签总开关。开启后新增走动态可关闭页签,不走「常规」 |
15
- | `addTabLabel` | String | `"新增"` | 新增页签初始标题 |
16
15
  | `submitBehavior` | String | `"closeToList"` | 提交后行为:`closeToList`(关页签回列表刷新)/ `refreshCurrent`(刷新本页出流程信息) |
17
16
 
17
+ > 新增页签初始标题**固定为「新增」**,不提供配置项(保存后升级为名称字段值)。
18
+
18
19
  复用既有字段(未新造):`hideNormalTab`(隐藏常规页签)、`multiTabLabelField`(页签标题字段,新增/编辑共用)、`multiTabEnabled`(编辑页签多开,语义不变)。
19
20
 
20
21
  > **配置位置统一在「列表表单」**,与 `multiTabEnabled` 同处。`submitBehavior` 运行时优先读列表表单配置。
@@ -46,15 +47,14 @@
46
47
  ## 三、改动清单(实际代码)
47
48
 
48
49
  ### 1. `components/xform/utils/util.js` — `getDefaultFormConfig()`
49
- 新增 3 个默认字段(**真正生效的默认值源**,非 designer.js 内联对象):
50
+ 新增 2 个默认字段(**真正生效的默认值源**,非 designer.js 内联对象):
50
51
  ```js
51
52
  addTabEnabled: false,
52
- addTabLabel: "新增",
53
53
  submitBehavior: "closeToList",
54
54
  ```
55
55
 
56
56
  ### 2. `components/xform/form-designer/setting-panel/form-setting.vue`
57
- 「列表标签页信息」分组新增:`addTabEnabled` 开关、`addTabLabel` 输入、`submitBehavior` 单选。
57
+ 「列表标签页信息」分组新增:`addTabEnabled` 开关、`submitBehavior` 单选(新增页签标题固定「新增」,无输入项)。
58
58
 
59
59
  ### 3. `components/vb-tabs/x-tabs.vue` — `removeTab` 既有 bug 修复
60
60
  `tabNameEnable=true` 且关闭非首个页签时引用了未定义的 `tab`,修为 `this.tabs[tabIndex-1]`:
@@ -71,7 +71,7 @@ let isAdd = !dataId;
71
71
  let addTab = formConfig.addTabEnabled && isAdd && tabLabelField;
72
72
  if ((multiTabEnabled && dataId) || addTab) {
73
73
  let key = isAdd ? "add_" + Date.now() + "_" + Math.random().toString(36).slice(2,6) : dataId;
74
- let openRow = isAdd ? { ...row, id: key, [tabLabelField]: formConfig.addTabLabel || "新增" } : row;
74
+ let openRow = isAdd ? { ...row, id: key, [tabLabelField]: "新增" } : row;
75
75
  this.$refs.xTabs.openEditTab(openRow, param, {
76
76
  tabParam: { formCode, tabLabelField, tabName: key, isAdd, ...(isAdd ? { dataId: null } : {}) },
77
77
  });
@@ -92,7 +92,6 @@ let chartContainers = [],
92
92
  multiTabEnabled: false,
93
93
  multiTabLabelField: null,
94
94
  addTabEnabled: false, // 新增打开独立页签(不走「常规」页签)
95
- addTabLabel: "新增", // 新增页签初始标题
96
95
  submitBehavior: "refreshCurrent", // 提交后行为: refreshCurrent(默认,留在详情页) | closeToList
97
96
  billNavEnabled: false, // 详情页签显示「上一单/下一单」翻单按钮
98
97
  addFormCode: null,
@@ -153,8 +153,20 @@ export default {
153
153
  },
154
154
  setValue(val) {
155
155
  let data = val || []
156
+ // 按 tableParam 决定落点:行内附件写回当前行对象,主表写回表单模型。
157
+ // 旧实现固定写 getFormRef().formDataModel(顶层),行内附件会写错位置并丢失联动,
158
+ // 且多行会互相覆盖同一个顶层字段。
159
+ let currentData = this.tableParam && this.tableParam.row
160
+ ? this.tableParam.row
161
+ : this.formModel;
162
+ if (currentData[this.fieldKeyName] === undefined) {
163
+ this.$set(currentData, this.fieldKeyName, [])
164
+ }
165
+ // 赋值 fieldModel 会触发 watch.fieldModel -> handleChangeEvent(内部再走
166
+ // syncUpdateFormModel + emitFieldDataChange,异步一次)。这里再同步写一次模型,
167
+ // 保证 setValue 返回后立即可读到最新值,且落点与 watcher 一致,不会重复触发变更事件。
156
168
  this.fieldModel = data;
157
- this.getFormRef().formDataModel[this.fieldKeyName] = data;
169
+ this.syncUpdateFormModel(data);
158
170
  },
159
171
  loadDataDefaultHandle() {
160
172
  let dataId = this.formDataId;
@@ -726,9 +726,17 @@ modules = {
726
726
  unregisterFromRefList: function () {
727
727
  if (null !== this.refList && this.field.options.name) {
728
728
  let e = this.field.options.name;
729
- this.tableParam && !this.designState
730
- ? delete this.refList[e + "@row" + this.tableParam.rowIndex]
731
- : delete this.refList[e];
729
+ // 注销 key 必须与 registerToRefList 对齐:行内组件用 name + "_" + row._X_ROW_KEY,
730
+ // 否则行组件销毁时删不掉引用,widgetRefList 里会残留指向旧行的“幽灵”组件,
731
+ // 导致数组必填等校验读到旧空行而误报。
732
+ let key =
733
+ this.tableParam && !this.designState
734
+ ? e + "_" + this.tableParam.row._X_ROW_KEY
735
+ : e;
736
+ // 仅当该 key 仍指向当前实例时才删除,避免同 key 重建时误删新注册的实例。
737
+ if (this.refList[key] === this) {
738
+ delete this.refList[key];
739
+ }
732
740
  }
733
741
  },
734
742
  initOptionItemsHandle() {
@@ -230,16 +230,6 @@
230
230
  开启后新增打开独立可关闭页签,需配置「标签名称字段」
231
231
  </span>
232
232
  </el-form-item>
233
- <el-form-item
234
- v-if="formConfig.multiTabEnabled && formConfig.addTabEnabled"
235
- :label="i18nt('新增页签标题')"
236
- >
237
- <el-input
238
- type="text"
239
- v-model="formConfig.addTabLabel"
240
- placeholder="默认`新增`"
241
- ></el-input>
242
- </el-form-item>
243
233
  <el-form-item :label="i18nt('提交后行为')">
244
234
  <el-radio-group v-model="formConfig.submitBehavior">
245
235
  <el-radio label="closeToList">关闭页签并回列表刷新</el-radio>
@@ -3116,6 +3116,28 @@ modules = {
3116
3116
  });
3117
3117
  return error;
3118
3118
  },
3119
+ /**
3120
+ * 判断某个组件引用是否为“幽灵”行组件:其 tableParam.row 已不在任何表格数据数组中。
3121
+ * 依据当前渲染的行组件持有的 row 一定与 formModel 中的行对象同引用;行被重建替换后,
3122
+ * 旧组件持有的 row 在所有数组里都找不到。非行内组件恒返回 false(走正常校验)。
3123
+ * @param {Object} ref 组件引用。@returns {Boolean}
3124
+ */
3125
+ isDetachedRowWidget(ref) {
3126
+ const tableParam = ref && ref.tableParam;
3127
+ if (!tableParam || !tableParam.row) {
3128
+ return false;
3129
+ }
3130
+ const row = tableParam.row;
3131
+ const model = this.formModel || {};
3132
+ const keys = Object.keys(model);
3133
+ for (let i = 0; i < keys.length; i++) {
3134
+ const arr = model[keys[i]];
3135
+ if (Array.isArray(arr) && arr.indexOf(row) !== -1) {
3136
+ return false;
3137
+ }
3138
+ }
3139
+ return true;
3140
+ },
3119
3141
  validateArrayValueFieldsRequired() {
3120
3142
  let error = null;
3121
3143
  const refList = this.widgetRefList || {};
@@ -3139,6 +3161,11 @@ modules = {
3139
3161
  if (!isArrayValueWidgetType(field.type, field.options)) {
3140
3162
  return;
3141
3163
  }
3164
+ // 兜底:跳过已从表格数据中移除的“幽灵”行组件引用(正常情况下已由
3165
+ // fieldMixin.unregisterFromRefList 的 key 对齐修复摘除,这里防残留误伤校验)。
3166
+ if (this.isDetachedRowWidget(ref)) {
3167
+ return;
3168
+ }
3142
3169
  const actualValue =
3143
3170
  typeof ref.getCurrentValue === "function"
3144
3171
  ? ref.getCurrentValue()
@@ -3618,7 +3645,12 @@ modules = {
3618
3645
  currentName !== "first" &&
3619
3646
  currentName !== "second" &&
3620
3647
  !/^otherTab/.test(currentName);
3621
- if (listFormConfig && listFormConfig.multiTabEnabled && xTabs && isDynamicTab) {
3648
+ if (
3649
+ listFormConfig &&
3650
+ listFormConfig.multiTabEnabled &&
3651
+ xTabs &&
3652
+ isDynamicTab
3653
+ ) {
3622
3654
  return {
3623
3655
  xTabs,
3624
3656
  currentName,
@@ -1000,7 +1000,6 @@ export function getDefaultFormConfig() {
1000
1000
  multiTabEnabled: false,
1001
1001
  multiTabLabelField: null,
1002
1002
  addTabEnabled: false, // 新增打开独立页签(不走「常规」页签)
1003
- addTabLabel: "新增", // 新增页签初始标题
1004
1003
  submitBehavior: "refreshCurrent", // 提交后行为: refreshCurrent(默认,留在详情页) | closeToList
1005
1004
  billNavEnabled: false, // 详情页签显示「上一单/下一单」翻单按钮
1006
1005
  addFormCode: null,
@@ -312,7 +312,7 @@ export default {
312
312
  ? "add_" + Date.now() + "_" + Math.random().toString(36).slice(2, 6)
313
313
  : dataId;
314
314
  let openRow = isAdd
315
- ? { ...row, id: key, [tabLabelField]: formConfig.addTabLabel || "新增" }
315
+ ? { ...row, id: key, [tabLabelField]: "新增" }
316
316
  : row;
317
317
  this.$refs.xTabs.openEditTab(openRow, param, {
318
318
  tabParam: {