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

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 (26) hide show
  1. package/package.json +1 -1
  2. package/src/components/vb-tabs/x-tabs.vue +3 -2
  3. package/src/components/wf/content.vue +1 -1
  4. package/src/components/wf/wf.js +16 -1
  5. package/src/components/wf/wfUtil.js +1 -1
  6. package/src/components/xform/XFormTabContainer//346/226/260/345/242/236/351/241/265/347/255/276/346/250/241/345/274/217-/346/234/200/347/273/210/345/256/236/347/216/260.md +195 -0
  7. package/src/components/xform/form-designer/designer.js +4 -0
  8. package/src/components/xform/form-designer/form-widget/field-widget/button-widget.vue +76 -66
  9. package/src/components/xform/form-designer/form-widget/field-widget/download-button-widget.vue +0 -1
  10. package/src/components/xform/form-designer/form-widget/field-widget/import-button-widget.vue +1 -1
  11. package/src/components/xform/form-designer/form-widget/field-widget/import2-button-widget.vue +1 -1
  12. package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue +1 -1
  13. package/src/components/xform/form-designer/setting-panel/form-setting.vue +31 -0
  14. package/src/components/xform/form-render/container-item/data-table-mixin.js +18 -0
  15. package/src/components/xform/form-render/container-item/detail-item.vue +107 -3
  16. package/src/components/xform/form-render/indexMixin.js +95 -1
  17. package/src/components/xform/mixins/defaultHandle.js +16 -0
  18. package/src/components/xform/mixins/scriptHttp.js +3 -0
  19. package/src/components/xform/utils/util.js +4 -0
  20. package/src/layout/components/AppMain.vue +2 -1
  21. package/src/views/user/form/view/list.vue +164 -11
  22. package/src/views/user/position/list.vue +68 -108
  23. package/src/components/xform/XFormTabContainer/IMPLEMENTATION_PLAN.md +0 -1079
  24. package/src/components/xform/XFormTabContainer//346/226/260/345/242/236/351/241/265/347/255/276/346/250/241/345/274/217-/350/220/275/345/234/260/345/256/236/346/226/275/346/226/207/346/241/243.md +0 -232
  25. package/src/components/xform/XFormTabContainer//346/226/260/345/242/236/351/241/265/347/255/276/346/250/241/345/274/217/345/256/236/347/216/260/346/226/271/346/241/210.md +0 -511
  26. package/src/components/xform/form-designer/form-widget/field-widget/tableexportbuttonwidget.vue +0 -99
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.724",
4
+ "version": "1.0.54-dev.727",
5
5
  "scripts": {
6
6
  "dev": "vue-cli-service serve",
7
7
  "lint": "eslint --ext .js,.vue src",
@@ -91,9 +91,10 @@ export default {
91
91
  });
92
92
  if (this.activeName === targetName) {
93
93
  if (tabIndex > 0) {
94
+ let prev = this.tabs[tabIndex - 1];
94
95
  this.activeName = tabNameEnable
95
- ? tab.tabName
96
- : this.tabs[tabIndex - 1].data[paneKeyName] + "";
96
+ ? prev.tabName
97
+ : prev.data[paneKeyName] + "";
97
98
  } else {
98
99
  this.activeName = "second";
99
100
  }
@@ -7,7 +7,7 @@
7
7
  >
8
8
  <template #default>
9
9
  <div
10
- style="margin: -49px 0 16px 124px; position: relative; z-index: 2; height: 28px"
10
+ style="margin: -36px 0 8px 124px; position: relative; z-index: 2; height: 28px"
11
11
  v-if="!wfConfig.hiddenAllButton"
12
12
  >
13
13
  <el-button
@@ -1659,7 +1659,8 @@ wfStartMixin = {
1659
1659
  startFormData:{},
1660
1660
  wfUserRangeEnabled: false,
1661
1661
  preStartResult:[],
1662
- showSetCandidateDialog2:false
1662
+ showSetCandidateDialog2:false,
1663
+ wfSubmitted: false
1663
1664
  };
1664
1665
  },
1665
1666
  computed: {
@@ -1815,6 +1816,7 @@ wfStartMixin = {
1815
1816
 
1816
1817
  },
1817
1818
  startSubmitHanlde(formData){
1819
+ this.wfSubmitted = true; // 标记已进入提交,避免随后关闭弹框误判为「取消」
1818
1820
  this.showDialog = false;
1819
1821
  let that = getTarget(this);
1820
1822
  let option = this.option;
@@ -1850,10 +1852,23 @@ wfStartMixin = {
1850
1852
  }
1851
1853
  });
1852
1854
  },
1855
+ handleWfCancel() {
1856
+ // 未进入提交就关闭 = 取消启动,回调通用 onCancel(一次性,避免多个弹框关闭重复触发)
1857
+ if (this.wfSubmitted) return;
1858
+ this.wfSubmitted = true;
1859
+ this.option && this.option.onCancel && this.option.onCancel();
1860
+ },
1853
1861
  close() {
1862
+ this.handleWfCancel();
1854
1863
  this.$emit("update:visible", false);
1855
1864
  },
1856
1865
  },
1866
+ watch: {
1867
+ showSetCandidateDialog2(val, oldVal) {
1868
+ // 候选人弹框未提交就关闭 = 取消启动
1869
+ if (oldVal && !val) this.handleWfCancel();
1870
+ },
1871
+ },
1857
1872
  };
1858
1873
 
1859
1874
  wfModifyMixin = {
@@ -141,7 +141,7 @@ f = async function (option) {
141
141
  appendPrevChildDom(wfBtnRegion, dom);
142
142
  }
143
143
 
144
- if (wfBtnRegion && showStartBtn && !hasWf && !option.hiddenAllButton) {
144
+ if (wfBtnRegion && showStartBtn && option.injectStartBtn !== false && !hasWf && !option.hiddenAllButton) {
145
145
  let wfStartButtonName = configUtil.settingConfig.wfStartButtonName || this.$t2('流程启动', 'components.wf.wfStart');
146
146
  let dom = new configUtil.Vue({
147
147
  render: function (h) {
@@ -0,0 +1,195 @@
1
+ # xform 表单「新增页签模式」——最终实现(已落地)
2
+
3
+ > 本文记录**实际已落地**的实现,替代前几版方案文档(`新增页签模式实现方案.md` / `新增页签模式-落地实施文档.md` / `新增页签模式-归一落地方案.md` / 弃用的 `IMPLEMENTATION_PLAN.md`)。
4
+ > 需求:去掉固定「常规」页签承载新增 → 新增打开独立可关闭页签(标题"新增")→ 保存后本页变编辑态(标题变名称字段)→ 提交(启动流程)后可配置「关闭页签回列表刷新」或「刷新本页」,并正确处理保存成功/提交失败/取消等边界。
5
+
6
+ ---
7
+
8
+ ## 一、最终交互与配置
9
+
10
+ ### 配置项(列表表单 formConfig,设计器「列表标签页信息」分组)
11
+
12
+ | 字段 | 类型 | 默认 | 含义 |
13
+ |------|------|------|------|
14
+ | `addTabEnabled` | Boolean | `false` | 新增打开独立页签总开关。开启后新增走动态可关闭页签,不走「常规」 |
15
+ | `addTabLabel` | String | `"新增"` | 新增页签初始标题 |
16
+ | `submitBehavior` | String | `"closeToList"` | 提交后行为:`closeToList`(关页签回列表刷新)/ `refreshCurrent`(刷新本页出流程信息) |
17
+
18
+ 复用既有字段(未新造):`hideNormalTab`(隐藏常规页签)、`multiTabLabelField`(页签标题字段,新增/编辑共用)、`multiTabEnabled`(编辑页签多开,语义不变)。
19
+
20
+ > **配置位置统一在「列表表单」**,与 `multiTabEnabled` 同处。`submitBehavior` 运行时优先读列表表单配置。
21
+
22
+ ### 端到端行为(详情内容恰好刷新一次)
23
+
24
+ | 分支 | 行为 | 详情刷新 |
25
+ |------|------|:---:|
26
+ | 新增保存(纯保存) | 页签升级编辑态、标题变名称字段、`dataId`=单号 | 1(编辑态重载) |
27
+ | 保存并提交 → 提交成功 + `refreshCurrent` | 刷新本页,出流程信息 | 1 |
28
+ | 保存并提交 → 提交成功 + `closeToList` | 关当前页签 → 切列表 → 刷新列表 | 0(详情) |
29
+ | 保存并提交 → 提交失败 / 取消候选人弹框 | 刷新当前详情到编辑态(不重复入库) | 1 |
30
+ | 直接启动流程(`wfStartBindSave` 开)→ 失败/取消 | 刷新到编辑态 | 1 |
31
+ | **直接启动流程(`wfStartBindSave` 关)→ 失败/取消** | **不刷新表单** | 0 |
32
+ | 直接启动流程 → 成功 | 按 `submitBehavior` 关页签/刷新 | 0 或 1 |
33
+
34
+ ---
35
+
36
+ ## 二、设计要点
37
+
38
+ 1. **归一**:新增 = 一个「还没有单号的编辑页签」,复用现有 `x-tabs` + `editTab` 插槽机制,不另写容器/分支体系。
39
+ 2. **合成唯一 id**:新增时给虚拟 row 合成 `id = tabName = "add_<时间戳>_<随机>"`,使 `x-tabs` 去重(按 `data.id`)/`tabName`/`paneName` 三者对齐;`dataId` 显式置 `null`,避免被当真实单号去 `getOne`。
40
+ 3. **元数据升级与内容重载解耦**:表单不 `watch` `dataId`,故改 `tab.dataId` 不触发重载。保存成功先只升级页签元数据(`dataId`/`isAdd`/`formCode`/标题),内容的那一次刷新交给流程结束后的分支,保证详情不刷两次。
41
+ 4. **wf 组件零业务耦合**:`wf.js` 只认通用钩子 `option.onStartSuccess` / `onStartFail` / `onCancel`,页签相关逻辑全部收在 xform 侧(`indexMixin`)。
42
+ 5. **两个入口统一**:「保存并提交」(`defaultHandle`)与「直接启动流程」(`indexMixin` 构造的 wf option)都通过同一批 xform 方法处理。
43
+
44
+ ---
45
+
46
+ ## 三、改动清单(实际代码)
47
+
48
+ ### 1. `components/xform/utils/util.js` — `getDefaultFormConfig()`
49
+ 新增 3 个默认字段(**真正生效的默认值源**,非 designer.js 内联对象):
50
+ ```js
51
+ addTabEnabled: false,
52
+ addTabLabel: "新增",
53
+ submitBehavior: "closeToList",
54
+ ```
55
+
56
+ ### 2. `components/xform/form-designer/setting-panel/form-setting.vue`
57
+ 「列表标签页信息」分组新增:`addTabEnabled` 开关、`addTabLabel` 输入、`submitBehavior` 单选。
58
+
59
+ ### 3. `components/vb-tabs/x-tabs.vue` — `removeTab` 既有 bug 修复
60
+ `tabNameEnable=true` 且关闭非首个页签时引用了未定义的 `tab`,修为 `this.tabs[tabIndex-1]`:
61
+ ```js
62
+ let prev = this.tabs[tabIndex - 1];
63
+ this.activeName = tabNameEnable ? prev.tabName : prev.data[paneKeyName] + "";
64
+ ```
65
+
66
+ ### 4. `views/user/form/view/list.vue`
67
+
68
+ **`openEditDialog`** — 归一分支,新增合成唯一 id、`dataId:null`、`isAdd`:
69
+ ```js
70
+ let isAdd = !dataId;
71
+ let addTab = formConfig.addTabEnabled && isAdd && tabLabelField;
72
+ if ((multiTabEnabled && dataId) || addTab) {
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;
75
+ this.$refs.xTabs.openEditTab(openRow, param, {
76
+ tabParam: { formCode, tabLabelField, tabName: key, isAdd, ...(isAdd ? { dataId: null } : {}) },
77
+ });
78
+ } else { /* 原「常规」分支不变 */ }
79
+ ```
80
+
81
+ **新增方法**(`editTab` 插槽 `@reload` 改为 `(...args) => onEditTabReload(tab, ...args)`):
82
+ - `resolveFormModel(target)`:逐级解析真实表单 `formDataModel`(`target` → `target.$refs.vFormRef` → `target.getFormRef()`)。
83
+ - `applyTabSaveResult(tab, dataId, formCode, formModel)`:升级编辑态 + 同步标题(标题取名称字段值,无值不回退单号)。**不含内容重渲染**。
84
+ - `onEditTabReload(tab, target, param)`:纯保存路径 → `applyTabSaveResult` + `reloadTabContent`(重渲染)。
85
+ - `promoteActiveAddTab(dataId, formCode, target)`:保存并提交路径 → 只对当前活动页签 `applyTabSaveResult`,**不重渲染**。
86
+
87
+ ### 5. `components/xform/mixins/defaultHandle.js` — `saveAndSubmitWfHandle`
88
+ 保存成功回调里:**先只升级页签元数据**(不刷详情),再开流程弹框,注入统一钩子:
89
+ ```js
90
+ success: (res) => {
91
+ let editFormCode = formConfig.editFormCode;
92
+ let listPageRef = formRef.getListPageRef && formRef.getListPageRef();
93
+ if (listPageRef && listPageRef.promoteActiveAddTab) {
94
+ listPageRef.promoteActiveAddTab(res.objx, editFormCode, formRef); // 元数据升级,防重复入库,不刷详情
95
+ }
96
+ openStartWfDialog(formRef, {
97
+ objId: res.objx, wfCode: ..., formCode: ..., serviceId: ..., skipStartConfirm: true,
98
+ onStartSuccess: () => formRef.onWfStartSuccess && formRef.onWfStartSuccess(),
99
+ onStartFail: () => formRef.onWfStartAbort && formRef.onWfStartAbort(), // 有保存 → 失败刷编辑态
100
+ onCancel: () => formRef.onWfStartAbort && formRef.onWfStartAbort(), // 有保存 → 取消刷编辑态
101
+ });
102
+ option?.config?.success && option.config.success(res);
103
+ },
104
+ ```
105
+
106
+ ### 6. `components/xform/form-render/indexMixin.js`
107
+
108
+ **wf option 构造处**(直接启动按钮入口,约 L1379):
109
+ ```js
110
+ onStartSuccess: () => this.onWfStartSuccess(), // 成功始终处理
111
+ // ...
112
+ if (formConfig.wfStartBindSave) { // 仅当伴随自动保存时,失败/取消才刷新
113
+ option.onStartFail = () => this.onWfStartAbort();
114
+ option.onCancel = () => this.onWfStartAbort();
115
+ option.onStart = ...; option.onBeforeStartSubmit = ...; // 既有自动保存逻辑
116
+ }
117
+ ```
118
+
119
+ **新增方法**(`switchToListTab` 附近):
120
+ ```js
121
+ getAddTabContext() {
122
+ // 返回 {xTabs, currentName, submitBehavior},仅当处于开启 addTabEnabled 的动态页签内;否则 null
123
+ }
124
+ onWfStartSuccess() {
125
+ let ctx = this.getAddTabContext();
126
+ if (ctx) {
127
+ if (ctx.submitBehavior === "refreshCurrent") this.$baseReload();
128
+ else { this.switchToListTab({ handleType: "reload" }); ctx.xTabs.removeTab(ctx.currentName); }
129
+ return;
130
+ }
131
+ this.$baseReload(); // 非本模式:原默认行为
132
+ }
133
+ onWfStartAbort() {
134
+ // 失败/取消:本模式下刷新当前详情到编辑态(dataId 已升级为单号);非本模式不处理
135
+ if (this.getAddTabContext()) this.$baseReload();
136
+ }
137
+ ```
138
+ > `getAddTabContext` 判定:当前页签名非 `first`/`second`/`otherTab*`,且列表表单 `addTabEnabled` 为真。
139
+
140
+ ### 7. `components/wf/wf.js` — `wfStartMixin`(仅通用钩子,无业务逻辑)
141
+ - `data` 增 `wfSubmitted: false`。
142
+ - `startSubmitHanlde` 首行 `this.wfSubmitted = true;`(进入提交后关闭弹框不算取消)。
143
+ - 新增 `handleWfCancel()`:未提交则一次性回调 `option.onCancel`(防多弹框重复触发)。
144
+ - `close()` 调 `handleWfCancel()`;新增 `watch.showSetCandidateDialog2`:候选人弹框未提交就关闭 → `handleWfCancel()`。
145
+ - 失败分支沿用既有 `option.onStartFail && option.onStartFail()`。
146
+
147
+ ---
148
+
149
+ ## 四、关键边界与结论
150
+
151
+ - **多次新增不覆盖**:合成唯一 id 保证每次新增各开一页签。
152
+ - **新增不误触发 getOne**:`tabParam.dataId = null` 覆盖 x-tabs 默认取 `row.id`。
153
+ - **标题**:取名称字段(`multiTabLabelField`)真实值,编辑态改名再保存会同步;无值保持原标题不回退单号。
154
+ - **防重复入库**:保存成功即升级 `tab.dataId`=单号,提交失败/取消后再保存走更新。
155
+ - **详情最多刷一次**:元数据升级不重渲染,内容刷新集中在流程结束分支。
156
+ - **wf 解耦**:`wf.js` 仅新增通用 `onCancel` 钩子;页签逻辑全在 xform。
157
+ - **`wfStartBindSave` 关 + 直接启动 + 失败/取消**:无保存,不注入 abort 钩子 → 不刷新表单。
158
+ - **向后兼容**:`addTabEnabled` 默认 false,存量表单(含 `multiTabEnabled=true`)行为不变;非 xform 的 wf 表单不受影响。
159
+
160
+ ---
161
+
162
+ ## 五、测试清单
163
+
164
+ | # | 场景 | 预期 |
165
+ |---|------|------|
166
+ | 1 | 旧表单未开 `addTabEnabled` 点新增 | 走「常规」,不变 |
167
+ | 2 | 存量 `multiTabEnabled=true` 未开 `addTabEnabled` | 编辑开页签,新增仍走常规 |
168
+ | 3 | 连续点新增 | 各开一页签,不覆盖 |
169
+ | 4 | 新增点开 | 空白新增表单,不调 getOne |
170
+ | 5 | 新增保存 | 标题变名称字段、转编辑态、`dataId` 正确、不新开页签、详情刷一次 |
171
+ | 6 | 编辑态改名再保存 | 页签标题同步为新名称 |
172
+ | 7 | 保存并提交成功 + `refreshCurrent` | 详情刷一次,出流程信息 |
173
+ | 8 | 保存并提交成功 + `closeToList` | 关页签、切列表、列表刷新 |
174
+ | 9 | 保存并提交 → 提交失败 | 详情刷到编辑态,不重复入库 |
175
+ | 10 | 保存并提交 → 关候选人弹框取消 | 详情刷到编辑态,不重复入库 |
176
+ | 11 | 保存并提交后重复提交 | 走更新,不产生重复单据 |
177
+ | 12 | `wfStartBindSave` 关 + 直接启动 + 失败/取消 | 表单不刷新 |
178
+ | 13 | `wfStartBindSave` 开 + 直接启动 + 失败/取消 | 刷到编辑态 |
179
+ | 14 | 关闭非首个动态页签 | 不报错(x-tabs 修复) |
180
+ | 15 | 非 xform 表单用流程 | 失败/取消不刷新,成功行为不变 |
181
+
182
+ ---
183
+
184
+ ## 六、涉及文件
185
+
186
+ | 文件 | 改动 |
187
+ |------|------|
188
+ | `components/xform/utils/util.js` | `getDefaultFormConfig` 加 3 字段 |
189
+ | `components/xform/form-designer/setting-panel/form-setting.vue` | 配置 UI |
190
+ | `components/vb-tabs/x-tabs.vue` | `removeTab` bug 修复 |
191
+ | `views/user/form/view/list.vue` | `openEditDialog` 归一分支 + `resolveFormModel`/`applyTabSaveResult`/`onEditTabReload`/`promoteActiveAddTab` |
192
+ | `components/xform/mixins/defaultHandle.js` | `saveAndSubmitWfHandle` 元数据升级 + 注入钩子 |
193
+ | `components/xform/form-render/indexMixin.js` | wf option 注入 + `getAddTabContext`/`onWfStartSuccess`/`onWfStartAbort` |
194
+ | `components/wf/wf.js` | `wfStartMixin` 通用 `onCancel` 钩子 + `wfSubmitted` 标志 |
195
+ </content>
@@ -91,6 +91,10 @@ let chartContainers = [],
91
91
  wfConfigData: [],
92
92
  multiTabEnabled: false,
93
93
  multiTabLabelField: null,
94
+ addTabEnabled: false, // 新增打开独立页签(不走「常规」页签)
95
+ addTabLabel: "新增", // 新增页签初始标题
96
+ submitBehavior: "refreshCurrent", // 提交后行为: refreshCurrent(默认,留在详情页) | closeToList
97
+ billNavEnabled: false, // 详情页签显示「上一单/下一单」翻单按钮
94
98
  addFormCode: null,
95
99
  addFormName: null,
96
100
  wfTheme: null,
@@ -1,87 +1,97 @@
1
1
  <template>
2
- <static-content-wrapper :designer="designer" :field="field" :design-state="designState" :display-style="field.options.displayStyle"
3
- :parent-widget="parentWidget" :parent-list="parentList" :index-of-parent-list="indexOfParentList"
4
- :sub-form-row-index="subFormRowIndex" :sub-form-col-index="subFormColIndex" :sub-form-row-id="subFormRowId">
5
- <el-button ref="fieldEditor" :type="field.options.type" :size="field.options.size" class="button-sty"
6
- :plain="field.options.plain" :round="field.options.round"
7
- :circle="field.options.circle" :icon="field.options.icon"
8
- :disabled="!designState &&field.options.disabled" style="margin-right:12px"
9
- @click.native="handleButtonWidgetClick">
10
- {{ getI18nLabel(field.options.label)}}</el-button>
2
+ <static-content-wrapper
3
+ :designer="designer"
4
+ :field="field"
5
+ :design-state="designState"
6
+ :display-style="field.options.displayStyle"
7
+ :parent-widget="parentWidget"
8
+ :parent-list="parentList"
9
+ :index-of-parent-list="indexOfParentList"
10
+ :sub-form-row-index="subFormRowIndex"
11
+ :sub-form-col-index="subFormColIndex"
12
+ :sub-form-row-id="subFormRowId"
13
+ >
14
+ <el-button
15
+ ref="fieldEditor"
16
+ :type="field.options.type"
17
+ :size="field.options.size"
18
+ class="button-sty"
19
+ :plain="field.options.plain"
20
+ :round="field.options.round"
21
+ :circle="field.options.circle"
22
+ :icon="field.options.icon"
23
+ :disabled="!designState && field.options.disabled"
24
+ @click.native="handleButtonWidgetClick"
25
+ >
26
+ {{ getI18nLabel(field.options.label) }}</el-button
27
+ >
11
28
  </static-content-wrapper>
12
29
  </template>
13
30
 
14
31
  <script>
15
- import StaticContentWrapper from './static-content-wrapper'
16
- import emitter from '../../../../../components/xform/utils/emitter'
17
- import i18n from "../../../../../components/xform/utils/i18n";
18
- import fieldMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/fieldMixin";
32
+ import StaticContentWrapper from "./static-content-wrapper";
33
+ import emitter from "../../../../../components/xform/utils/emitter";
34
+ import i18n from "../../../../../components/xform/utils/i18n";
35
+ import fieldMixin from "../../../../../components/xform/form-designer/form-widget/field-widget/fieldMixin";
19
36
 
20
- export default {
21
- name: "button-widget",
22
- componentName: 'FieldWidget', //必须固定为FieldWidget,用于接收父级组件的broadcast事件
23
- mixins: [emitter, fieldMixin, i18n],
24
- props: {
25
- field: Object,
26
- parentWidget: Object,
27
- parentList: Array,
28
- indexOfParentList: Number,
29
- designer: Object,
37
+ export default {
38
+ name: "button-widget",
39
+ componentName: "FieldWidget", //必须固定为FieldWidget,用于接收父级组件的broadcast事件
40
+ mixins: [emitter, fieldMixin, i18n],
41
+ props: {
42
+ field: Object,
43
+ parentWidget: Object,
44
+ parentList: Array,
45
+ indexOfParentList: Number,
46
+ designer: Object,
30
47
 
31
- designState: {
32
- type: Boolean,
33
- default: false
34
- },
35
-
36
- subFormRowIndex: { /* 子表单组件行索引,从0开始计数 */
37
- type: Number,
38
- default: -1
39
- },
40
- subFormColIndex: { /* 子表单组件列索引,从0开始计数 */
41
- type: Number,
42
- default: -1
43
- },
44
- subFormRowId: { /* 子表单组件行Id,唯一id且不可变 */
45
- type: String,
46
- default: ''
47
- },
48
-
49
- },
50
- components: {
51
- StaticContentWrapper,
48
+ designState: {
49
+ type: Boolean,
50
+ default: false,
52
51
  },
53
- computed: {
54
52
 
53
+ subFormRowIndex: {
54
+ /* 子表单组件行索引,从0开始计数 */ type: Number,
55
+ default: -1,
55
56
  },
56
- beforeCreate() {
57
- /* 这里不能访问方法和属性!! */
57
+ subFormColIndex: {
58
+ /* 子表单组件列索引,从0开始计数 */ type: Number,
59
+ default: -1,
58
60
  },
59
-
60
- created() {
61
- /* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
62
- 需要在父组件created中初始化!! */
63
- this.registerToRefList()
64
- this.initEventHandler()
65
-
66
- this.handleOnCreated()
61
+ subFormRowId: {
62
+ /* 子表单组件行Id,唯一id且不可变 */ type: String,
63
+ default: "",
67
64
  },
65
+ },
66
+ components: {
67
+ StaticContentWrapper,
68
+ },
69
+ computed: {},
70
+ beforeCreate() {
71
+ /* 这里不能访问方法和属性!! */
72
+ },
68
73
 
69
- mounted() {
70
- this.handleOnMounted()
71
- },
74
+ created() {
75
+ /* 注意:子组件mounted在父组件created之后、父组件mounted之前触发,故子组件mounted需要用到的prop
76
+ 需要在父组件created中初始化!! */
77
+ this.registerToRefList();
78
+ this.initEventHandler();
72
79
 
73
- beforeDestroy() {
74
- this.unregisterFromRefList()
75
- },
80
+ this.handleOnCreated();
81
+ },
76
82
 
77
- methods: {
83
+ mounted() {
84
+ this.handleOnMounted();
85
+ },
78
86
 
79
- }
87
+ beforeDestroy() {
88
+ this.unregisterFromRefList();
89
+ },
80
90
 
81
- }
91
+ methods: {},
92
+ };
82
93
  </script>
83
94
 
84
95
  <style lang="scss" scoped>
85
- @import "~@/styles/global.scss"; //* static-content-wrapper已引入,还需要重复引入吗? *//
86
-
96
+ @import "~@/styles/global.scss"; //* static-content-wrapper已引入,还需要重复引入吗? *//
87
97
  </style>
@@ -15,7 +15,6 @@
15
15
  class="button-sty"
16
16
  @click="clickHandle"
17
17
  icon="el-icon-download"
18
- plain
19
18
  :disabled="!designState && field.options.disabled"
20
19
  >
21
20
  {{ getI18nLabel(field.options.label) }}
@@ -4,7 +4,7 @@
4
4
  :display-style="field.options.displayStyle"
5
5
  :parent-widget="parentWidget" :parent-list="parentList"
6
6
  :index-of-parent-list="indexOfParentList">
7
- <el-button :type="field.options.type" class="button-sty" size="mini" icon="el-icon-download" plain @click="importHandle"
7
+ <el-button :type="field.options.type" class="button-sty" size="mini" icon="el-icon-download" @click="importHandle"
8
8
  :disabled="field.options.disabled">{{ getI18nLabel(field.options.label)}}
9
9
  </el-button>
10
10
  </static-content-wrapper>
@@ -4,7 +4,7 @@
4
4
  :display-style="field.options.displayStyle"
5
5
  :parent-widget="parentWidget" :parent-list="parentList"
6
6
  :index-of-parent-list="indexOfParentList">
7
- <el-button :type="field.options.type" class="button-sty" size="mini" icon="el-icon-download" plain @click="importHandle"
7
+ <el-button :type="field.options.type" class="button-sty" size="mini" icon="el-icon-download" @click="importHandle"
8
8
  :disabled="field.options.disabled">{{ getI18nLabel(field.options.label)}}
9
9
  </el-button>
10
10
  </static-content-wrapper>
@@ -9,7 +9,7 @@
9
9
  :index-of-parent-list="indexOfParentList"
10
10
  >
11
11
  <el-dropdown trigger="hover" :disabled="field.options.disabled">
12
- <el-button type="primary" class="button-sty" size="mini" plain>
12
+ <el-button type="primary" class="button-sty" size="mini">
13
13
  <span>{{ getI18nLabel("列表导出") }}</span
14
14
  ><span class="line"></span> <i class="el-icon-arrow-down el-icon--right"></i>
15
15
  </el-button>
@@ -123,6 +123,12 @@
123
123
  <el-form-item :label="i18nt('新增页面表单名称')">
124
124
  {{ formConfig.addFormName }}
125
125
  </el-form-item>
126
+ <el-form-item :label="i18nt('详情翻单按钮')">
127
+ <el-switch v-model="formConfig.billNavEnabled"></el-switch>
128
+ <span style="margin-left: 8px; color: #999; font-size: 12px">
129
+ 编辑态页签显示「上一单/下一单」
130
+ </span>
131
+ </el-form-item>
126
132
  </el-collapse-item>
127
133
  <el-collapse-item name="3" title="流程信息">
128
134
  <el-form-item :label="i18nt('启用流程')">
@@ -215,6 +221,31 @@
215
221
  <el-form-item :label="i18nt('标签名称字段')">
216
222
  <el-input type="text" v-model="formConfig.multiTabLabelField"></el-input>
217
223
  </el-form-item>
224
+ <el-form-item
225
+ v-if="formConfig.multiTabEnabled"
226
+ :label="i18nt('新增打开页签')"
227
+ >
228
+ <el-switch v-model="formConfig.addTabEnabled"></el-switch>
229
+ <span style="margin-left: 8px; color: #999; font-size: 12px">
230
+ 开启后新增打开独立可关闭页签,需配置「标签名称字段」
231
+ </span>
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
+ <el-form-item :label="i18nt('提交后行为')">
244
+ <el-radio-group v-model="formConfig.submitBehavior">
245
+ <el-radio label="closeToList">关闭页签并回列表刷新</el-radio>
246
+ <el-radio label="refreshCurrent">刷新当前页签</el-radio>
247
+ </el-radio-group>
248
+ </el-form-item>
218
249
  </el-collapse-item>
219
250
  <el-collapse-item name="5" title="其他标签页信息">
220
251
  <el-form-item :label="i18nt('自定义列表标签名称')">
@@ -1526,11 +1526,29 @@ modules = {
1526
1526
  } else {
1527
1527
  formCode = formConfig.addFormCode || formConfig.editFormCode;
1528
1528
  }
1529
+ // 上一单/下一单:打开详情时,按当前列表(排序/筛选后)有序行做快照,供详情页翻单使用
1530
+ let navRows = null;
1531
+ let navIndex = -1;
1532
+ // 快照:当前页有序行引用 + 当前行下标(仅存引用,开销小)。
1533
+ // 新增无当前行 → navIndex 置 -1,保存后由宿主把新单插入序列首位。
1534
+ try {
1535
+ let $grid = this.getGridTable && this.getGridTable();
1536
+ let fullData = $grid && $grid.getTableData()?.fullData;
1537
+ if (Array.isArray(fullData) && fullData.length) {
1538
+ navRows = fullData;
1539
+ navIndex = row?.id ? fullData.findIndex((r) => r.id === row.id) : -1;
1540
+ }
1541
+ } catch (e) {
1542
+ navRows = null;
1543
+ navIndex = -1;
1544
+ }
1529
1545
  let parentTarget = formRef.$attrs["parent-target"];
1530
1546
  parentTarget &&
1531
1547
  parentTarget.$attrs.openEditDialog &&
1532
1548
  parentTarget.$attrs.openEditDialog(row, param, {
1533
1549
  formCode,
1550
+ navRows,
1551
+ navIndex,
1534
1552
  ...option,
1535
1553
  });
1536
1554
  },