bl-common-vue3 3.8.111 → 3.8.113
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
|
@@ -5,6 +5,54 @@ const DEFAULT_COLUMN_WIDTH = 16;
|
|
|
5
5
|
const MAX_COLUMN_WIDTH = 36;
|
|
6
6
|
const HEADER_ROW_HEIGHT = 30;
|
|
7
7
|
const DATA_ROW_HEIGHT = 24;
|
|
8
|
+
const XLSX_MIME_TYPE =
|
|
9
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8";
|
|
10
|
+
const INVALID_FILE_NAME_REG = /[\\/:*?"<>|]/g;
|
|
11
|
+
|
|
12
|
+
const getSafeXlsxFileName = (filename) => {
|
|
13
|
+
const safeName =
|
|
14
|
+
String(filename || "excel")
|
|
15
|
+
.replace(INVALID_FILE_NAME_REG, "_")
|
|
16
|
+
.trim() || "excel";
|
|
17
|
+
return /\.xlsx$/i.test(safeName) ? safeName : `${safeName}.xlsx`;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const isWeComBrowser = () => {
|
|
21
|
+
const ua = typeof navigator === "undefined" ? "" : navigator.userAgent || "";
|
|
22
|
+
return /wxwork|MicroMessenger/i.test(ua);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const saveByLink = (blob, fileName) => {
|
|
26
|
+
const objectUrl = window.URL.createObjectURL(blob);
|
|
27
|
+
const link = document.createElement("a");
|
|
28
|
+
link.style.display = "none";
|
|
29
|
+
link.href = objectUrl;
|
|
30
|
+
link.download = fileName;
|
|
31
|
+
document.body.appendChild(link);
|
|
32
|
+
link.click();
|
|
33
|
+
link.remove();
|
|
34
|
+
window.setTimeout(() => window.URL.revokeObjectURL(objectUrl), 0);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const saveXlsxBlob = (blob, filename) => {
|
|
38
|
+
const fileName = getSafeXlsxFileName(filename);
|
|
39
|
+
const file =
|
|
40
|
+
typeof File === "function"
|
|
41
|
+
? new File([blob], fileName, { type: XLSX_MIME_TYPE })
|
|
42
|
+
: blob;
|
|
43
|
+
|
|
44
|
+
if (window.navigator?.msSaveOrOpenBlob) {
|
|
45
|
+
window.navigator.msSaveOrOpenBlob(file, fileName);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (isWeComBrowser()) {
|
|
50
|
+
saveByLink(file, fileName);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
fs.saveAs(file, fileName);
|
|
55
|
+
};
|
|
8
56
|
|
|
9
57
|
const createBorder = (color) => ({
|
|
10
58
|
top: { style: "thin", color: { rgb: color } },
|
|
@@ -33,56 +81,56 @@ const getStyledExportOptions = (options = {}) => {
|
|
|
33
81
|
columnWidths && typeof columnWidths === "object" ? columnWidths : {},
|
|
34
82
|
};
|
|
35
83
|
};
|
|
36
|
-
|
|
84
|
+
|
|
37
85
|
export function getVerticalMergeCells(json, fields, options = {}) {
|
|
38
|
-
const { groupField, mergeFields = [] } = options;
|
|
39
|
-
if (!groupField || !Array.isArray(mergeFields) || !mergeFields.length) {
|
|
40
|
-
return [];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const fieldKeys = Object.keys(fields);
|
|
44
|
-
const mergeColumnIndexes = mergeFields
|
|
45
|
-
.map((field) => fieldKeys.indexOf(field))
|
|
46
|
-
.filter((columnIndex) => columnIndex >= 0);
|
|
47
|
-
if (!mergeColumnIndexes.length) {
|
|
48
|
-
return [];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const merges = [];
|
|
52
|
-
let groupStartIndex = 0;
|
|
53
|
-
|
|
54
|
-
const appendGroupMerges = (groupEndIndex) => {
|
|
55
|
-
const groupValue = json[groupStartIndex]?.[groupField];
|
|
56
|
-
if (
|
|
57
|
-
groupEndIndex <= groupStartIndex ||
|
|
58
|
-
groupValue === undefined ||
|
|
59
|
-
groupValue === null ||
|
|
60
|
-
groupValue === ""
|
|
61
|
-
) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
mergeColumnIndexes.forEach((columnIndex) => {
|
|
66
|
-
merges.push({
|
|
67
|
-
// 工作表第 0 行是表头,数据行需要整体向下偏移一行。
|
|
68
|
-
s: { r: groupStartIndex + 1, c: columnIndex },
|
|
69
|
-
e: { r: groupEndIndex + 1, c: columnIndex },
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
for (let rowIndex = 1; rowIndex <= json.length; rowIndex++) {
|
|
75
|
-
const groupChanged =
|
|
76
|
-
rowIndex === json.length ||
|
|
77
|
-
json[rowIndex]?.[groupField] !== json[groupStartIndex]?.[groupField];
|
|
78
|
-
if (!groupChanged) {
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
appendGroupMerges(rowIndex - 1);
|
|
83
|
-
groupStartIndex = rowIndex;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
+
const { groupField, mergeFields = [] } = options;
|
|
87
|
+
if (!groupField || !Array.isArray(mergeFields) || !mergeFields.length) {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const fieldKeys = Object.keys(fields);
|
|
92
|
+
const mergeColumnIndexes = mergeFields
|
|
93
|
+
.map((field) => fieldKeys.indexOf(field))
|
|
94
|
+
.filter((columnIndex) => columnIndex >= 0);
|
|
95
|
+
if (!mergeColumnIndexes.length) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const merges = [];
|
|
100
|
+
let groupStartIndex = 0;
|
|
101
|
+
|
|
102
|
+
const appendGroupMerges = (groupEndIndex) => {
|
|
103
|
+
const groupValue = json[groupStartIndex]?.[groupField];
|
|
104
|
+
if (
|
|
105
|
+
groupEndIndex <= groupStartIndex ||
|
|
106
|
+
groupValue === undefined ||
|
|
107
|
+
groupValue === null ||
|
|
108
|
+
groupValue === ""
|
|
109
|
+
) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
mergeColumnIndexes.forEach((columnIndex) => {
|
|
114
|
+
merges.push({
|
|
115
|
+
// 工作表第 0 行是表头,数据行需要整体向下偏移一行。
|
|
116
|
+
s: { r: groupStartIndex + 1, c: columnIndex },
|
|
117
|
+
e: { r: groupEndIndex + 1, c: columnIndex },
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
for (let rowIndex = 1; rowIndex <= json.length; rowIndex++) {
|
|
123
|
+
const groupChanged =
|
|
124
|
+
rowIndex === json.length ||
|
|
125
|
+
json[rowIndex]?.[groupField] !== json[groupStartIndex]?.[groupField];
|
|
126
|
+
if (!groupChanged) {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
appendGroupMerges(rowIndex - 1);
|
|
131
|
+
groupStartIndex = rowIndex;
|
|
132
|
+
}
|
|
133
|
+
|
|
86
134
|
return merges;
|
|
87
135
|
}
|
|
88
136
|
|
|
@@ -188,14 +236,14 @@ export async function createWorkbook(
|
|
|
188
236
|
: null;
|
|
189
237
|
//导出xlsx
|
|
190
238
|
json.forEach((item) => {
|
|
191
|
-
for (let i in item) {
|
|
192
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
193
|
-
if (fields.hasOwnProperty(i)) {
|
|
194
|
-
item[fields[i]] = item[i];
|
|
195
|
-
}
|
|
196
|
-
delete item[i]; //删除原先的对象属性
|
|
197
|
-
}
|
|
198
|
-
});
|
|
239
|
+
for (let i in item) {
|
|
240
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
241
|
+
if (fields.hasOwnProperty(i)) {
|
|
242
|
+
item[fields[i]] = item[i];
|
|
243
|
+
}
|
|
244
|
+
delete item[i]; //删除原先的对象属性
|
|
245
|
+
}
|
|
246
|
+
});
|
|
199
247
|
let wb = XLSX.utils.book_new(); //工作簿对象包含一SheetNames数组,以及一个表对象映射表名称到表对象。XLSX.utils.book_new实用函数创建一个新的工作簿对象。
|
|
200
248
|
let ws = XLSX.utils.json_to_sheet(json, { header: Object.values(fields) }); //将JS对象数组转换为工作表。
|
|
201
249
|
if (merges.length) {
|
|
@@ -223,32 +271,32 @@ export async function xlsx(
|
|
|
223
271
|
const sheetName = filename.replace(/[\\/?*[\]:]/g, "").slice(0, 31) || "Sheet1"; //excel的文件名称
|
|
224
272
|
wb.SheetNames.push(sheetName);
|
|
225
273
|
wb.Sheets[sheetName] = ws;
|
|
226
|
-
const defaultCellStyle = {
|
|
227
|
-
font: { name: "Verdana", sz: 13, color: "FF00FF88" },
|
|
228
|
-
fill: { fgColor: { rgb: "FFFFAA00" } },
|
|
229
|
-
}; //设置表格的样式
|
|
230
|
-
let wopts = {
|
|
231
|
-
bookType: "xlsx",
|
|
232
|
-
bookSST: false,
|
|
233
|
-
type: "binary",
|
|
234
|
-
cellStyles: true,
|
|
235
|
-
defaultCellStyle: defaultCellStyle,
|
|
236
|
-
showGridLines: false,
|
|
237
|
-
}; //写入的样式
|
|
238
|
-
let wbout = XLSX.write(wb, wopts);
|
|
239
|
-
let blob = new Blob([s2ab(wbout)], { type:
|
|
240
|
-
|
|
241
|
-
}
|
|
242
|
-
const s2ab = (s) => {
|
|
243
|
-
var buf;
|
|
244
|
-
if (typeof ArrayBuffer !== "undefined") {
|
|
245
|
-
buf = new ArrayBuffer(s.length);
|
|
246
|
-
var view = new Uint8Array(buf);
|
|
247
|
-
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
|
|
248
|
-
return buf;
|
|
249
|
-
} else {
|
|
250
|
-
buf = new Array(s.length);
|
|
251
|
-
for (var n = 0; n != s.length; ++n) buf[n] = s.charCodeAt(n) & 0xff;
|
|
252
|
-
return buf;
|
|
253
|
-
}
|
|
254
|
-
};
|
|
274
|
+
const defaultCellStyle = {
|
|
275
|
+
font: { name: "Verdana", sz: 13, color: "FF00FF88" },
|
|
276
|
+
fill: { fgColor: { rgb: "FFFFAA00" } },
|
|
277
|
+
}; //设置表格的样式
|
|
278
|
+
let wopts = {
|
|
279
|
+
bookType: "xlsx",
|
|
280
|
+
bookSST: false,
|
|
281
|
+
type: "binary",
|
|
282
|
+
cellStyles: true,
|
|
283
|
+
defaultCellStyle: defaultCellStyle,
|
|
284
|
+
showGridLines: false,
|
|
285
|
+
}; //写入的样式
|
|
286
|
+
let wbout = XLSX.write(wb, wopts);
|
|
287
|
+
let blob = new Blob([s2ab(wbout)], { type: XLSX_MIME_TYPE });
|
|
288
|
+
saveXlsxBlob(blob, filename);
|
|
289
|
+
}
|
|
290
|
+
const s2ab = (s) => {
|
|
291
|
+
var buf;
|
|
292
|
+
if (typeof ArrayBuffer !== "undefined") {
|
|
293
|
+
buf = new ArrayBuffer(s.length);
|
|
294
|
+
var view = new Uint8Array(buf);
|
|
295
|
+
for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
|
|
296
|
+
return buf;
|
|
297
|
+
} else {
|
|
298
|
+
buf = new Array(s.length);
|
|
299
|
+
for (var n = 0; n != s.length; ++n) buf[n] = s.charCodeAt(n) & 0xff;
|
|
300
|
+
return buf;
|
|
301
|
+
}
|
|
302
|
+
};
|
|
@@ -111,6 +111,15 @@
|
|
|
111
111
|
:config="item"
|
|
112
112
|
:validateInfo="validateInfos[item.key]"
|
|
113
113
|
/>
|
|
114
|
+
<a-col :span="8" v-if="displayStatus">
|
|
115
|
+
<a-form-item :label="t('common.table.status')">
|
|
116
|
+
<a-switch
|
|
117
|
+
v-model:checked="formState.status"
|
|
118
|
+
:checkedValue="1"
|
|
119
|
+
:unCheckedValue="0"
|
|
120
|
+
/>
|
|
121
|
+
</a-form-item>
|
|
122
|
+
</a-col>
|
|
114
123
|
<a-col :span="24">
|
|
115
124
|
<div class="text-title">{{t('components.extraManageEdit.enterSetting')}}</div>
|
|
116
125
|
</a-col>
|
|
@@ -272,6 +281,10 @@ export default defineComponent({
|
|
|
272
281
|
type: Array,
|
|
273
282
|
default: () => [],
|
|
274
283
|
},
|
|
284
|
+
displayStatus:{
|
|
285
|
+
type: Boolean,
|
|
286
|
+
default: true,
|
|
287
|
+
},
|
|
275
288
|
},
|
|
276
289
|
components: {
|
|
277
290
|
BlModal,
|
|
@@ -575,6 +588,9 @@ export default defineComponent({
|
|
|
575
588
|
const init = () => {
|
|
576
589
|
gettypelist('extra_field_type')
|
|
577
590
|
getCompanyList();
|
|
591
|
+
if (props.displayStatus){
|
|
592
|
+
state.formState.status = 1
|
|
593
|
+
}
|
|
578
594
|
if (props.id) {
|
|
579
595
|
// 编辑
|
|
580
596
|
let detailInfo = props.requestAllInfo.detail;
|
|
@@ -28,6 +28,14 @@
|
|
|
28
28
|
@change="handleCustomConfigChange($event, record, item)"
|
|
29
29
|
/>
|
|
30
30
|
</template>
|
|
31
|
+
<template #column-status="{record}">
|
|
32
|
+
<a-switch
|
|
33
|
+
:checked="getStatusValue(record)"
|
|
34
|
+
:checkedValue="1"
|
|
35
|
+
:unCheckedValue="0"
|
|
36
|
+
@change="statusChange(record, $event)"
|
|
37
|
+
/>
|
|
38
|
+
</template>
|
|
31
39
|
<template #column-action="{ record }">
|
|
32
40
|
<div v-if="record.is_system == 1">
|
|
33
41
|
<a-button @click="handleEdit(record)" type="link" v-if="record?.can_edit">{{t('common.button.edit')}}</a-button>
|
|
@@ -52,6 +60,7 @@
|
|
|
52
60
|
:requestAllInfo="requestAllInfo"
|
|
53
61
|
:requestAllParams="requestAllParams"
|
|
54
62
|
:displayCompany="displayCompany"
|
|
63
|
+
:display-status="displayStatus"
|
|
55
64
|
:expandFieldsExtraParams="expandFieldsExtraParams"
|
|
56
65
|
:id="editId"
|
|
57
66
|
:hasVillageSelect="hasVillageSelect"
|
|
@@ -135,6 +144,11 @@ export default defineComponent({
|
|
|
135
144
|
type: Array,
|
|
136
145
|
default: () => [],
|
|
137
146
|
},
|
|
147
|
+
// 是否展示状态
|
|
148
|
+
displayStatus:{
|
|
149
|
+
type: Boolean,
|
|
150
|
+
default: false,
|
|
151
|
+
},
|
|
138
152
|
},
|
|
139
153
|
components: {
|
|
140
154
|
BlDrawer,
|
|
@@ -147,6 +161,7 @@ export default defineComponent({
|
|
|
147
161
|
editVisible: false,
|
|
148
162
|
editId: 0,
|
|
149
163
|
customTable: null,
|
|
164
|
+
statusMap: {},
|
|
150
165
|
});
|
|
151
166
|
|
|
152
167
|
// 处理后的自定义配置项
|
|
@@ -298,6 +313,15 @@ export default defineComponent({
|
|
|
298
313
|
const fillColumnIndex = _deepColumns.findIndex((column) => column.key === 'fill');
|
|
299
314
|
const customColumns = getColumnsVisibleCustomConfigItems(normalizedCustomConfigItems.value);
|
|
300
315
|
_deepColumns.splice(fillColumnIndex, 0, ...customColumns);
|
|
316
|
+
if (props.displayStatus){
|
|
317
|
+
let index = _deepColumns.length - 3
|
|
318
|
+
_deepColumns.splice(index, 0, {
|
|
319
|
+
title: t('common.table.status'),
|
|
320
|
+
dataIndex: "status" ,
|
|
321
|
+
key: 'status',
|
|
322
|
+
width: 120,
|
|
323
|
+
})
|
|
324
|
+
}
|
|
301
325
|
return _deepColumns;
|
|
302
326
|
});
|
|
303
327
|
|
|
@@ -346,6 +370,40 @@ export default defineComponent({
|
|
|
346
370
|
});
|
|
347
371
|
};
|
|
348
372
|
|
|
373
|
+
const getStatusValue = (record) => {
|
|
374
|
+
const key = record?.id;
|
|
375
|
+
if (Object.prototype.hasOwnProperty.call(state.statusMap, key)) {
|
|
376
|
+
return state.statusMap[key];
|
|
377
|
+
}
|
|
378
|
+
return Number(record?.status) === 1 ? 1 : 0;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const statusChange = (record, checked) => {
|
|
382
|
+
const status = checked ? 1 : 0;
|
|
383
|
+
const oldStatus = getStatusValue(record);
|
|
384
|
+
state.statusMap[record.id] = status;
|
|
385
|
+
record.status = status;
|
|
386
|
+
const params = { ...record, status };
|
|
387
|
+
// 编辑
|
|
388
|
+
emit("request", {
|
|
389
|
+
params: {
|
|
390
|
+
method: 'put',
|
|
391
|
+
server: props.requestAllInfo.edit.service,
|
|
392
|
+
url: props.requestAllInfo.edit.serviceUrl.replace(/\${id}/g, record.id),
|
|
393
|
+
extra: {
|
|
394
|
+
...params,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
success: (res) => {
|
|
398
|
+
message.success(res?.msg || t('common.save.success'));
|
|
399
|
+
},
|
|
400
|
+
fail: () => {
|
|
401
|
+
state.statusMap[record.id] = oldStatus;
|
|
402
|
+
record.status = oldStatus;
|
|
403
|
+
},
|
|
404
|
+
})
|
|
405
|
+
}
|
|
406
|
+
|
|
349
407
|
return {
|
|
350
408
|
t,
|
|
351
409
|
...toRefs(state),
|
|
@@ -361,6 +419,8 @@ export default defineComponent({
|
|
|
361
419
|
getCustomConfigEditorProps,
|
|
362
420
|
handleCustomConfigChange,
|
|
363
421
|
editableCustomConfigItems,
|
|
422
|
+
getStatusValue,
|
|
423
|
+
statusChange,
|
|
364
424
|
};
|
|
365
425
|
},
|
|
366
426
|
});
|