cloud-web-corejs 1.1.0-dev.21 → 1.1.0-dev.23
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 +1 -1
- package/src/components/bizTab/BizTabListPage.vue +66 -33
- package/src/components/bizTab/README.md +3 -1
- package/src/components/excelExport/conditionExportConfig.js +112 -0
- package/src/components/excelExport/exportType.js +8 -0
- package/src/components/excelExport/index.vue +7 -1
- package/src/components/excelExport/mixins.js +410 -259
- package/src/components/mobile/wf/content.vue +27 -3
- package/src/components/table/index.js +5 -2
- package/src/components/table/plugins/cell-area/index.js +10 -3
- package/src/components/wf/wfStartDialog.vue +1 -0
- package/src/components/wf/wfUtil.js +47 -29
- package/src/components/wf/wfVisibility.js +6 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-mixin.js +7 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +3 -1
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +25 -1
- package/src/components/xform/form-designer/form-widget/field-widget/select-export-item-button-widget.vue +2 -1
- package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue +2 -1
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +14 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +318 -12
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +23 -7
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/empty-number-input.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +27 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/table-export-button-editor.vue +33 -3
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +54 -0
- package/src/components/xform/form-render/container-item/data-table-item.vue +8 -6
- package/src/components/xform/form-render/container-item/data-table-mixin.js +587 -25
- package/src/components/xform/form-render/container-item/detail-h5-item.vue +26 -16
- package/src/components/xform/form-render/container-item/detail-item.vue +350 -446
- package/src/components/xform/form-render/fieldControlMixin.js +2 -0
- package/src/components/xform/form-render/indexMixin.js +25 -15
- package/src/components/xform/mixins/businessLock.js +59 -0
- package/src/components/xform/mixins/wfStart.js +103 -0
- package/src/components/xform/mixins/wfVisibility.js +33 -0
- package/src/components/xform/styles/h5.scss +6 -1
- package/src/components/xform/utils/util.js +2 -0
- package/src/views/user/home/index.vue +1 -1
- package/src/views/user/home/net/distributor.vue +1015 -0
- package/src/views/user/home/net/index.vue +61 -0
package/package.json
CHANGED
|
@@ -163,33 +163,34 @@ export default {
|
|
|
163
163
|
return key;
|
|
164
164
|
},
|
|
165
165
|
/**
|
|
166
|
-
*
|
|
166
|
+
* 打开「详情/编辑」页签。同一单据已开则复用并重新加载,不检查未保存修改。
|
|
167
167
|
* option.navRows / option.navIndex 传了就能用「上一单/下一单」翻单,
|
|
168
168
|
* 一般直接把列表的 fullData 和当前行下标丢进来。
|
|
169
169
|
*/
|
|
170
170
|
openDetail(row, param, option) {
|
|
171
171
|
let dataId = row ? row.id : null;
|
|
172
172
|
if (dataId == null || dataId === "") return this.openAdd(param, option);
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
173
|
+
let tab = this.getTabByDataId(dataId);
|
|
174
|
+
if (!tab && !this.checkTabLimit()) return null;
|
|
175
|
+
let key = tab ? tab.tabName : this.getAvailableTabName(option?.tabParam?.tabName || dataId);
|
|
176
|
+
let tabParam = {
|
|
177
|
+
tabLabelField: this.titleField,
|
|
178
|
+
navRows: (option && option.navRows) || null,
|
|
179
|
+
navIndex: (option && option.navIndex != null) ? option.navIndex : -1,
|
|
180
|
+
...((option && option.tabParam) || {}),
|
|
181
|
+
tabName: key,
|
|
182
|
+
isAdd: false,
|
|
183
|
+
dataId,
|
|
184
|
+
};
|
|
185
|
+
if (tab) {
|
|
186
|
+
// 已按当前单据定位,直接更新原页签,避免 x-tabs 按 row.id 严格比较时
|
|
187
|
+
// 把数字/字符串 ID 当成两张单据;tabName 始终保留,详情登记关系不变。
|
|
188
|
+
Object.assign(tab, { data: row, param: param || null }, tabParam);
|
|
189
|
+
this.activeName = key;
|
|
190
|
+
this.refreshTab(tab);
|
|
191
|
+
} else {
|
|
192
|
+
this.$refs.xTabs.openEditTab(row, param || null, { tabParam });
|
|
193
|
+
}
|
|
193
194
|
return key;
|
|
194
195
|
},
|
|
195
196
|
|
|
@@ -215,7 +216,7 @@ export default {
|
|
|
215
216
|
tab.navIndex = 0;
|
|
216
217
|
}
|
|
217
218
|
// 页签 key(tabName) 仍是当初的合成 id:换掉会连带 el-tab-pane 重建、详情被迫重挂载,
|
|
218
|
-
//
|
|
219
|
+
// 正好破坏「保存后不刷详情」的设计。重复打开按当前 dataId 去重。
|
|
219
220
|
}
|
|
220
221
|
this.syncTabTitle(tab, info ? info.title : null);
|
|
221
222
|
},
|
|
@@ -288,14 +289,28 @@ export default {
|
|
|
288
289
|
* 翻单会丢掉未保存的修改,所以先过一遍脏数据确认(与关页签同一判据)。
|
|
289
290
|
* @returns {Promise<Boolean>} 是否真的翻了
|
|
290
291
|
*/
|
|
291
|
-
navigateTab(tab, step) {
|
|
292
|
-
let idx = this.canNavigate(tab, step);
|
|
293
|
-
if (idx < 0) return Promise.resolve(false);
|
|
294
|
-
|
|
292
|
+
navigateTab(tab, step) {
|
|
293
|
+
let idx = this.canNavigate(tab, step);
|
|
294
|
+
if (idx < 0) return Promise.resolve(false);
|
|
295
|
+
let existing = this.getTabByDataId(tab.navRows[idx].id);
|
|
296
|
+
if (existing && existing !== tab) {
|
|
297
|
+
// 与重复打开一致:直接重新加载目标详情,不检查其未保存修改。
|
|
298
|
+
this.activeName = existing.tabName;
|
|
299
|
+
this.refreshTab(existing);
|
|
300
|
+
return Promise.resolve(true);
|
|
301
|
+
}
|
|
302
|
+
return this.confirmLeaveDetail(tab).then((pass) => {
|
|
295
303
|
if (!pass) return false;
|
|
296
304
|
// 确认期间可能已经被关掉或翻走了,重新校一次
|
|
297
|
-
let target = this.canNavigate(tab, step);
|
|
298
|
-
if (target < 0 || !this.isLiveTab(tab)) return false;
|
|
305
|
+
let target = this.canNavigate(tab, step);
|
|
306
|
+
if (target < 0 || !this.isLiveTab(tab)) return false;
|
|
307
|
+
// 确认期间目标单据可能已从其他入口打开。
|
|
308
|
+
let existing = this.getTabByDataId(tab.navRows[target].id);
|
|
309
|
+
if (existing && existing !== tab) {
|
|
310
|
+
this.activeName = existing.tabName;
|
|
311
|
+
this.refreshTab(existing);
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
299
314
|
tab.navIndex = target;
|
|
300
315
|
tab.data = tab.navRows[target];
|
|
301
316
|
tab.dataId = tab.data.id; // 详情不 watch dataId,靠下面的重挂载按新单号取数
|
|
@@ -338,14 +353,32 @@ export default {
|
|
|
338
353
|
getTabs() {
|
|
339
354
|
return this.$refs.xTabs ? this.$refs.xTabs.tabs : [];
|
|
340
355
|
},
|
|
341
|
-
getTab(tabName) {
|
|
342
|
-
return this.getTabs().find((tab) => tab.tabName === tabName) || null;
|
|
343
|
-
},
|
|
356
|
+
getTab(tabName) {
|
|
357
|
+
return this.getTabs().find((tab) => tab.tabName === tabName) || null;
|
|
358
|
+
},
|
|
359
|
+
getTabByDataId(dataId) {
|
|
360
|
+
if (dataId == null || dataId === "") return null;
|
|
361
|
+
return this.getTabs().find((tab) => {
|
|
362
|
+
if (tab.isAdd) return false;
|
|
363
|
+
const currentId = tab.dataId ?? tab.data?.id;
|
|
364
|
+
return currentId != null && String(currentId) === String(dataId);
|
|
365
|
+
}) || null;
|
|
366
|
+
},
|
|
367
|
+
getAvailableTabName(preferredName) {
|
|
368
|
+
const baseName = String(preferredName);
|
|
369
|
+
let name = baseName;
|
|
370
|
+
let suffix = 1;
|
|
371
|
+
// 翻单后旧页签仍占用原名称;列表页签名称也不可复用。
|
|
372
|
+
while (name === LIST_TAB_NAME || this.getTab(name)) {
|
|
373
|
+
name = baseName + "_" + suffix++;
|
|
374
|
+
}
|
|
375
|
+
return name;
|
|
376
|
+
},
|
|
344
377
|
isLiveTab(tab) {
|
|
345
378
|
return this.getTabs().indexOf(tab) >= 0;
|
|
346
379
|
},
|
|
347
|
-
hasTab(dataId) {
|
|
348
|
-
return this.
|
|
380
|
+
hasTab(dataId) {
|
|
381
|
+
return !!this.getTabByDataId(dataId);
|
|
349
382
|
},
|
|
350
383
|
getTabLabel(tab) {
|
|
351
384
|
let label = tab.data ? tab.data[this.titleField] : null;
|
|
@@ -94,7 +94,9 @@ this.$refs.bizTab.openAdd(null, { navRows: rows });
|
|
|
94
94
|
|
|
95
95
|
内置关闭确认的判定顺序:详情实现了 `isBillDirty()` → 问它;否则只拦「还没保存过的新增页签」。
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
**重复打开单据时直接重新加载**:按当前 `dataId` 复用页签,不检查 `isBillDirty()`、不弹确认,未保存的修改会被重新加载的数据覆盖。翻单目标已在其他页签打开时,同样激活并重新加载目标页签,源页签内容保留。关闭页签、在原页签内翻到未打开的单据时,仍按 `isBillDirty()` 判断是否需要放弃修改确认;详情没实现该方法时不拦。
|
|
98
|
+
|
|
99
|
+
单据查找按当前 `dataId` 匹配(数字与字符串 ID 等价);`tabName` 是稳定的页签标识,翻单和新增保存时保持不变。`getTab(tabName)` 用于按页签名称查找,`getTabByDataId(dataId)` / `hasTab(dataId)` 用于按当前单据查找。`openDetail()` 返回实际页签名称,可能与单据 ID 不同,应使用返回值激活页签。重新打开翻单前的单据时,会为新页签分配未占用的名称。
|
|
98
100
|
|
|
99
101
|
#### behavior
|
|
100
102
|
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { getLogicParamValue } from "@base/api/user";
|
|
2
|
+
|
|
3
|
+
export const CONDITION_EXPORT_PARAM_CODE = "conditionExportParams";
|
|
4
|
+
export const CONDITION_EXPORT_SEARCH_COUNT_CODE
|
|
5
|
+
= "conditionExportSearchCount";
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_CONDITION_EXPORT_CONFIG = Object.freeze({
|
|
8
|
+
maxQueryTotal: 300000,
|
|
9
|
+
pageSize: 1000,
|
|
10
|
+
limitFileSize: 100000,
|
|
11
|
+
searchCount: true,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
function parsePositiveInteger(value, fallback) {
|
|
15
|
+
let text = String(value == null ? "" : value).trim();
|
|
16
|
+
if (!/^\d+$/.test(text)) return fallback;
|
|
17
|
+
let result = Number(text);
|
|
18
|
+
if (!Number.isSafeInteger(result) || result <= 0) return fallback;
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* 解析「最大查询总数;每页查询数量;单文件最大数据量」。每一项独立回落默认值,
|
|
24
|
+
* 避免一项填错导致另外两项已生效的配置也被丢弃。
|
|
25
|
+
*/
|
|
26
|
+
export function parseConditionExportParams(rawValue) {
|
|
27
|
+
let values = typeof rawValue === "string" ? rawValue.split(";") : [];
|
|
28
|
+
return {
|
|
29
|
+
maxQueryTotal: parsePositiveInteger(
|
|
30
|
+
values[0],
|
|
31
|
+
DEFAULT_CONDITION_EXPORT_CONFIG.maxQueryTotal
|
|
32
|
+
),
|
|
33
|
+
pageSize: parsePositiveInteger(
|
|
34
|
+
values[1],
|
|
35
|
+
DEFAULT_CONDITION_EXPORT_CONFIG.pageSize
|
|
36
|
+
),
|
|
37
|
+
limitFileSize: parsePositiveInteger(
|
|
38
|
+
values[2],
|
|
39
|
+
DEFAULT_CONDITION_EXPORT_CONFIG.limitFileSize
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function parseConditionExportSearchCount(rawValue, fallback = true) {
|
|
45
|
+
if (typeof rawValue === "boolean") return rawValue;
|
|
46
|
+
if (typeof rawValue !== "string") return fallback;
|
|
47
|
+
let value = rawValue.trim().toLowerCase();
|
|
48
|
+
if (value === "true") return true;
|
|
49
|
+
if (value === "false") return false;
|
|
50
|
+
return fallback;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function readLogicParam(paramCode) {
|
|
54
|
+
return getLogicParamValue({
|
|
55
|
+
data: { paramCode },
|
|
56
|
+
modal: false,
|
|
57
|
+
failMsg: false,
|
|
58
|
+
errorMsg: false,
|
|
59
|
+
})
|
|
60
|
+
.then((res) => (res && res.type === "success" ? res.objx : ""))
|
|
61
|
+
.catch(() => "");
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 读取两条全局逻辑参数;接口异常时静默使用内置默认值。 */
|
|
65
|
+
export function loadConditionExportConfig() {
|
|
66
|
+
return Promise.all([
|
|
67
|
+
readLogicParam(CONDITION_EXPORT_PARAM_CODE),
|
|
68
|
+
readLogicParam(CONDITION_EXPORT_SEARCH_COUNT_CODE),
|
|
69
|
+
]).then(([paramsRaw, searchCountRaw]) => ({
|
|
70
|
+
...parseConditionExportParams(paramsRaw),
|
|
71
|
+
searchCount: parseConditionExportSearchCount(searchCountRaw, true),
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* 从导出按钮 options 取出条件导出的三项覆盖值。空值转成 null,交给
|
|
77
|
+
* resolveConditionExportConfig 回落到全局逻辑参数。
|
|
78
|
+
*/
|
|
79
|
+
export function pickConditionExportOverrides(fieldOptions = {}) {
|
|
80
|
+
return {
|
|
81
|
+
pageSize: fieldOptions.exportPageSize || null,
|
|
82
|
+
maxQueryTotal: fieldOptions.maxQueryTotal || null,
|
|
83
|
+
limitFileSize: fieldOptions.limitFileSize || null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 单次导出参数优先于全局逻辑参数。按钮参数与脚本参数在进入导出器前已经合并,且脚本
|
|
89
|
+
* 位于展开表达式右侧,所以这里读取到的 option 天然满足「脚本 > 按钮 > 全局」。
|
|
90
|
+
*/
|
|
91
|
+
export function resolveConditionExportConfig(globalConfig, option = {}) {
|
|
92
|
+
let base = globalConfig || DEFAULT_CONDITION_EXPORT_CONFIG;
|
|
93
|
+
let searchCountOverride
|
|
94
|
+
= option.conditionExportSearchCount !== undefined
|
|
95
|
+
? option.conditionExportSearchCount
|
|
96
|
+
: option.searchCount;
|
|
97
|
+
return {
|
|
98
|
+
maxQueryTotal: parsePositiveInteger(
|
|
99
|
+
option.maxQueryTotal,
|
|
100
|
+
base.maxQueryTotal
|
|
101
|
+
),
|
|
102
|
+
pageSize: parsePositiveInteger(option.pageSize, base.pageSize),
|
|
103
|
+
limitFileSize: parsePositiveInteger(
|
|
104
|
+
option.limitFileSize,
|
|
105
|
+
base.limitFileSize
|
|
106
|
+
),
|
|
107
|
+
searchCount: parseConditionExportSearchCount(
|
|
108
|
+
searchCountOverride,
|
|
109
|
+
base.searchCount
|
|
110
|
+
),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
@@ -39,6 +39,14 @@ export function isRowExport(type) {
|
|
|
39
39
|
return type === EXPORT_TYPE.SELECTED || type === EXPORT_TYPE.CURRENT;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* 是否条件导出。主表条件导出的历史 type 是 null/undefined;明细条件导出有独立类型。
|
|
44
|
+
* 明细选择导出虽然也走后端分页,但不受条件导出全局上限与查总数开关影响。
|
|
45
|
+
*/
|
|
46
|
+
export function isConditionExport(type) {
|
|
47
|
+
return type == null || type === EXPORT_TYPE.ITEM_CONDITION;
|
|
48
|
+
}
|
|
49
|
+
|
|
42
50
|
/**
|
|
43
51
|
* 是否必须先勾选行:空勾选要拦截,且以勾选行 id 作为查询条件。
|
|
44
52
|
* @param {String|null} type 导出模式。
|
|
@@ -41,6 +41,12 @@
|
|
|
41
41
|
<div class="export-box">
|
|
42
42
|
<div class="tips">
|
|
43
43
|
{{ $t2("导出中,请勿关闭当前窗口", "components.excelExport.tip") }}
|
|
44
|
+
<template v-if="conditionExportMode">
|
|
45
|
+
,{{
|
|
46
|
+
$t2("导出最大数据量", "components.excelExport.maxDataSize")
|
|
47
|
+
}}:{{ conditionExportConfig.maxQueryTotal
|
|
48
|
+
}}{{ $t2("条", "components.excelExport.rowUnit") }}
|
|
49
|
+
</template>
|
|
44
50
|
</div>
|
|
45
51
|
<el-progress
|
|
46
52
|
:text-inside="true"
|
|
@@ -62,7 +68,7 @@
|
|
|
62
68
|
<div class="fl import-count">
|
|
63
69
|
<span class="f-red doneNum">{{ doneSize }}</span>
|
|
64
70
|
/
|
|
65
|
-
<span class="dataSize">{{
|
|
71
|
+
<span class="dataSize">{{ exportTotalText }}</span>
|
|
66
72
|
</div>
|
|
67
73
|
<el-button type="primary" plain class="button-sty" @click="dialogClose2">
|
|
68
74
|
<i class="el-icon-close el-icon"></i>
|