bl-common-vue3 3.8.122 → 3.8.124
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
package/src/common/utils/xlsx.js
CHANGED
|
@@ -155,16 +155,23 @@ const getFieldStyle = (field, isDetailField, fieldStyles) => {
|
|
|
155
155
|
};
|
|
156
156
|
|
|
157
157
|
export function getVerticalMergeCells(json, fields, options = {}) {
|
|
158
|
-
const { groupField, mergeFields = [] } = options;
|
|
159
|
-
if (
|
|
158
|
+
const { groupField, mergeFields = [], mergeSameValueFields = [] } = options;
|
|
159
|
+
if (
|
|
160
|
+
!groupField ||
|
|
161
|
+
!Array.isArray(mergeFields) ||
|
|
162
|
+
!Array.isArray(mergeSameValueFields)
|
|
163
|
+
) {
|
|
160
164
|
return [];
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
const fieldKeys = Object.keys(fields);
|
|
164
|
-
const
|
|
168
|
+
const sameValueFields = [...new Set(mergeSameValueFields)]
|
|
169
|
+
.filter((field) => fieldKeys.includes(field));
|
|
170
|
+
const mergeColumnIndexes = [...new Set(mergeFields)]
|
|
171
|
+
.filter((field) => !sameValueFields.includes(field))
|
|
165
172
|
.map((field) => fieldKeys.indexOf(field))
|
|
166
173
|
.filter((columnIndex) => columnIndex >= 0);
|
|
167
|
-
if (!mergeColumnIndexes.length) {
|
|
174
|
+
if (!mergeColumnIndexes.length && !sameValueFields.length) {
|
|
168
175
|
return [];
|
|
169
176
|
}
|
|
170
177
|
|
|
@@ -189,6 +196,23 @@ export function getVerticalMergeCells(json, fields, options = {}) {
|
|
|
189
196
|
e: { r: groupEndIndex + 1, c: columnIndex },
|
|
190
197
|
});
|
|
191
198
|
});
|
|
199
|
+
|
|
200
|
+
// 相同值只在当前主分组内继续分段合并,避免相邻账单的相同所属期被合并到一起。
|
|
201
|
+
if (sameValueFields.length) {
|
|
202
|
+
const groupRows = json.slice(groupStartIndex, groupEndIndex + 1);
|
|
203
|
+
sameValueFields.forEach((field) => {
|
|
204
|
+
const fieldMerges = getVerticalMergeCells(groupRows, fields, {
|
|
205
|
+
groupField: field,
|
|
206
|
+
mergeFields: [field],
|
|
207
|
+
});
|
|
208
|
+
fieldMerges.forEach(({ s, e }) => {
|
|
209
|
+
merges.push({
|
|
210
|
+
s: { r: s.r + groupStartIndex, c: s.c },
|
|
211
|
+
e: { r: e.r + groupStartIndex, c: e.c },
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
}
|
|
192
216
|
};
|
|
193
217
|
|
|
194
218
|
for (let rowIndex = 1; rowIndex <= json.length; rowIndex++) {
|
|
@@ -39,10 +39,11 @@
|
|
|
39
39
|
<script>
|
|
40
40
|
import {
|
|
41
41
|
computed,
|
|
42
|
-
defineComponent, reactive, toRefs, watch,
|
|
42
|
+
defineComponent, getCurrentInstance, reactive, toRefs, watch,
|
|
43
43
|
} from "vue";
|
|
44
44
|
import {Modal, Table} from "ant-design-vue";
|
|
45
45
|
import { SyncOutlined } from "@ant-design/icons-vue";
|
|
46
|
+
import { EventCenterForMicroApp } from "kj-micro-app";
|
|
46
47
|
import {t, loadLanguageAsync} from "../../locale";
|
|
47
48
|
import utils from "../../common/utils/util";
|
|
48
49
|
import BlModal from "../BlModal/index.vue";
|
|
@@ -84,6 +85,7 @@ export default defineComponent({
|
|
|
84
85
|
},
|
|
85
86
|
},
|
|
86
87
|
setup(props, { emit }) {
|
|
88
|
+
const instance = getCurrentInstance();
|
|
87
89
|
|
|
88
90
|
const state = reactive({
|
|
89
91
|
dataList: [], // 数据源
|
|
@@ -157,11 +159,17 @@ export default defineComponent({
|
|
|
157
159
|
// context.emit("addProperty");
|
|
158
160
|
state.addLoading = true;
|
|
159
161
|
if (props.microMessageInfo.appName && props.microMessageInfo.routeName) {
|
|
160
|
-
//
|
|
162
|
+
// 共享依赖运行在主应用作用域,通过组件所属容器定位发起操作的子应用。
|
|
163
|
+
const rootElement = instance?.proxy?.$root?.$el;
|
|
164
|
+
const appElement = rootElement?.closest?.("micro-app") ||
|
|
165
|
+
rootElement?.parentElement?.closest("micro-app");
|
|
166
|
+
const appName = appElement?.getAttribute("name");
|
|
167
|
+
const microApp = typeof window.microApp?.forceDispatch === "function"
|
|
168
|
+
? window.microApp
|
|
169
|
+
: appName ? new EventCenterForMicroApp(appName) : null;
|
|
161
170
|
|
|
162
|
-
if (
|
|
163
|
-
|
|
164
|
-
window.microApp.forceDispatch({
|
|
171
|
+
if (microApp) {
|
|
172
|
+
microApp.forceDispatch({
|
|
165
173
|
type: "SetChildDrawerList",
|
|
166
174
|
info: {
|
|
167
175
|
props: {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
const assert = require("node:assert/strict");
|
|
2
|
+
const { test } = require("node:test");
|
|
3
|
+
|
|
4
|
+
const loadXlsx = () => import("../src/common/utils/xlsx.js");
|
|
5
|
+
const fields = {
|
|
6
|
+
bill_number: "Bill number",
|
|
7
|
+
receipt_amount: "Receipt",
|
|
8
|
+
vat_period: "VAT period",
|
|
9
|
+
invoice_amount: "Invoice",
|
|
10
|
+
tax_amount: "Tax",
|
|
11
|
+
};
|
|
12
|
+
const rows = [
|
|
13
|
+
{ bill_id: 1, bill_number: "B1", vat_period: "202608", receipt_amount: 100, invoice_amount: 200, tax_amount: 60 },
|
|
14
|
+
{ bill_id: 1, bill_number: "B1", vat_period: "202608", receipt_amount: 150, invoice_amount: "", tax_amount: "" },
|
|
15
|
+
{ bill_id: 1, bill_number: "B1", vat_period: "202609", receipt_amount: 300, invoice_amount: 100, tax_amount: 40 },
|
|
16
|
+
{ bill_id: 1, bill_number: "B1", vat_period: "202609", receipt_amount: "", invoice_amount: 110, tax_amount: "" },
|
|
17
|
+
{ bill_id: 1, bill_number: "B1", vat_period: "202609", receipt_amount: "", invoice_amount: 120, tax_amount: "" },
|
|
18
|
+
{ bill_id: 2, bill_number: "B2", vat_period: "202609", receipt_amount: 400, invoice_amount: 500, tax_amount: 50 },
|
|
19
|
+
{ bill_id: 2, bill_number: "B2", vat_period: "202609", receipt_amount: 450, invoice_amount: "", tax_amount: "" },
|
|
20
|
+
];
|
|
21
|
+
const mergeOptions = {
|
|
22
|
+
groupField: "bill_id",
|
|
23
|
+
mergeFields: ["bill_number"],
|
|
24
|
+
mergeSameValueFields: ["vat_period"],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
test("existing whole-bill merges remain compatible", async () => {
|
|
28
|
+
const { getVerticalMergeCells } = await loadXlsx();
|
|
29
|
+
assert.deepEqual(getVerticalMergeCells(rows, fields, {
|
|
30
|
+
groupField: "bill_id",
|
|
31
|
+
mergeFields: ["bill_number"],
|
|
32
|
+
}), [
|
|
33
|
+
{ s: { r: 1, c: 0 }, e: { r: 5, c: 0 } },
|
|
34
|
+
{ s: { r: 6, c: 0 }, e: { r: 7, c: 0 } },
|
|
35
|
+
]);
|
|
36
|
+
assert.deepEqual(getVerticalMergeCells(rows, fields), []);
|
|
37
|
+
assert.deepEqual(getVerticalMergeCells([], fields, mergeOptions), []);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
for (const enabled of [true, false]) {
|
|
41
|
+
test(`xlsx round trip preserves bill boundaries and detail values (styles: ${enabled})`, async () => {
|
|
42
|
+
const { createWorkbook } = await loadXlsx();
|
|
43
|
+
const { XLSX, wb, ws } = await createWorkbook(rows, fields, mergeOptions, {
|
|
44
|
+
enabled,
|
|
45
|
+
detailFields: ["vat_period", "receipt_amount", "invoice_amount", "tax_amount"],
|
|
46
|
+
});
|
|
47
|
+
XLSX.utils.book_append_sheet(wb, ws, "Bills");
|
|
48
|
+
const buffer = XLSX.write(wb, { bookType: "xlsx", type: "buffer" });
|
|
49
|
+
const restored = XLSX.read(buffer, { type: "buffer" }).Sheets.Bills;
|
|
50
|
+
assert.deepEqual(restored["!merges"].map(XLSX.utils.encode_range).sort(), [
|
|
51
|
+
"A2:A6", "A7:A8", "C2:C3", "C4:C6", "C7:C8",
|
|
52
|
+
]);
|
|
53
|
+
assert.equal(restored.C2.v, "202608");
|
|
54
|
+
assert.equal(restored.C4.v, "202609");
|
|
55
|
+
assert.equal(restored.C7.v, "202609");
|
|
56
|
+
rows.forEach((row, index) => {
|
|
57
|
+
const rowNumber = index + 2;
|
|
58
|
+
assert.equal(restored[`B${rowNumber}`]?.v ?? "", row.receipt_amount);
|
|
59
|
+
assert.equal(restored[`D${rowNumber}`]?.v ?? "", row.invoice_amount);
|
|
60
|
+
assert.equal(restored[`E${rowNumber}`]?.v ?? "", row.tax_amount);
|
|
61
|
+
});
|
|
62
|
+
if (enabled) {
|
|
63
|
+
assert.equal(ws.C2.s.alignment.vertical, "center");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
test("same-value merges support custom columns even without whole-bill fields", async () => {
|
|
69
|
+
const { getVerticalMergeCells } = await loadXlsx();
|
|
70
|
+
const customFields = Object.fromEntries(Array.from({ length: 30 }, (_, index) => [`field_${index}`, `Column ${index}`]));
|
|
71
|
+
customFields.vat_period = "VAT period";
|
|
72
|
+
assert.deepEqual(getVerticalMergeCells(rows, customFields, {
|
|
73
|
+
groupField: "bill_id",
|
|
74
|
+
mergeSameValueFields: ["vat_period"],
|
|
75
|
+
}), [
|
|
76
|
+
{ s: { r: 1, c: 30 }, e: { r: 2, c: 30 } },
|
|
77
|
+
{ s: { r: 3, c: 30 }, e: { r: 5, c: 30 } },
|
|
78
|
+
{ s: { r: 6, c: 30 }, e: { r: 7, c: 30 } },
|
|
79
|
+
]);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("blank values and isolated periods break merges", async () => {
|
|
83
|
+
const { getVerticalMergeCells } = await loadXlsx();
|
|
84
|
+
const periods = ["202608", "202608", "", "", null, null, undefined, undefined, "202609", "202608", "202608"];
|
|
85
|
+
const details = periods.map((vat_period) => ({ bill_id: 1, vat_period }));
|
|
86
|
+
assert.deepEqual(getVerticalMergeCells(details, fields, {
|
|
87
|
+
groupField: "bill_id",
|
|
88
|
+
mergeSameValueFields: ["vat_period"],
|
|
89
|
+
}), [
|
|
90
|
+
{ s: { r: 1, c: 2 }, e: { r: 2, c: 2 } },
|
|
91
|
+
{ s: { r: 10, c: 2 }, e: { r: 11, c: 2 } },
|
|
92
|
+
]);
|
|
93
|
+
assert.deepEqual(getVerticalMergeCells(details, { bill_number: "Bill" }, {
|
|
94
|
+
groupField: "bill_id",
|
|
95
|
+
mergeSameValueFields: ["vat_period"],
|
|
96
|
+
}), []);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("same-value rules take precedence without creating overlapping ranges", async () => {
|
|
100
|
+
const { getVerticalMergeCells } = await loadXlsx();
|
|
101
|
+
assert.deepEqual(getVerticalMergeCells(rows, fields, {
|
|
102
|
+
groupField: "bill_id",
|
|
103
|
+
mergeFields: ["vat_period", "vat_period"],
|
|
104
|
+
mergeSameValueFields: ["vat_period", "vat_period"],
|
|
105
|
+
}), [
|
|
106
|
+
{ s: { r: 1, c: 2 }, e: { r: 2, c: 2 } },
|
|
107
|
+
{ s: { r: 3, c: 2 }, e: { r: 5, c: 2 } },
|
|
108
|
+
{ s: { r: 6, c: 2 }, e: { r: 7, c: 2 } },
|
|
109
|
+
]);
|
|
110
|
+
});
|