@lambo-design/shared 1.0.0-beta.243 → 1.0.0-beta.246

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 (201) hide show
  1. package/config/config.js +51 -51
  2. package/config/env.js +4 -4
  3. package/config/index.js +7 -7
  4. package/config/themes/atrovirens/atrovirens.css +576 -575
  5. package/config/themes/atrovirens/atrovirens.css.map +1 -1
  6. package/config/themes/atrovirens/atrovirens.less +668 -667
  7. package/config/themes/atrovirens/var.less +675 -674
  8. package/config/themes/blue/blue.css +576 -575
  9. package/config/themes/blue/blue.css.map +1 -1
  10. package/config/themes/blue/blue.less +670 -669
  11. package/config/themes/blue/var.less +678 -677
  12. package/config/themes/blue-white/blue-white.css +576 -575
  13. package/config/themes/blue-white/blue-white.css.map +1 -1
  14. package/config/themes/blue-white/blue-white.less +670 -669
  15. package/config/themes/blue-white/var.less +677 -676
  16. package/config/themes/blue-white-tight/blue-white-tight.css +577 -576
  17. package/config/themes/blue-white-tight/blue-white-tight.css.map +1 -1
  18. package/config/themes/blue-white-tight/blue-white-tight.less +672 -672
  19. package/config/themes/blue-white-tight/var.less +678 -677
  20. package/config/themes/danqing/danqing.css +576 -575
  21. package/config/themes/danqing/danqing.css.map +1 -1
  22. package/config/themes/danqing/danqing.less +669 -668
  23. package/config/themes/danqing/danqing.wxss +576 -572
  24. package/config/themes/danqing/var.less +680 -679
  25. package/config/themes/deep/deep.css +576 -575
  26. package/config/themes/deep/deep.css.map +1 -1
  27. package/config/themes/deep/deep.less +670 -669
  28. package/config/themes/deep/var.less +678 -677
  29. package/config/themes/default/default.css +576 -575
  30. package/config/themes/default/default.css.map +1 -1
  31. package/config/themes/default/default.less +672 -671
  32. package/config/themes/default/var.less +678 -677
  33. package/config/themes/eap/eap.css +576 -575
  34. package/config/themes/eap/eap.css.map +1 -1
  35. package/config/themes/eap/eap.less +672 -671
  36. package/config/themes/eap/var.less +678 -677
  37. package/config/themes/gold/gold.css +576 -575
  38. package/config/themes/gold/gold.css.map +1 -1
  39. package/config/themes/gold/gold.less +672 -671
  40. package/config/themes/gold/var.less +678 -677
  41. package/config/themes/index.js +28 -28
  42. package/config/themes/lime/lime.css +576 -575
  43. package/config/themes/lime/lime.css.map +1 -1
  44. package/config/themes/lime/lime.less +672 -671
  45. package/config/themes/lime/var.less +679 -678
  46. package/config/themes/orange/orange.css +576 -575
  47. package/config/themes/orange/orange.css.map +1 -1
  48. package/config/themes/orange/orange.less +672 -671
  49. package/config/themes/orange/var.less +679 -678
  50. package/config/themes/red/red.css +576 -575
  51. package/config/themes/red/red.css.map +1 -1
  52. package/config/themes/red/red.less +672 -671
  53. package/config/themes/red/var.less +678 -677
  54. package/config/themes/theme-atrovirens.js +559 -558
  55. package/config/themes/theme-blue.js +559 -558
  56. package/config/themes/theme-bw.js +559 -558
  57. package/config/themes/theme-bwt.js +561 -559
  58. package/config/themes/theme-danqing.js +559 -558
  59. package/config/themes/theme-deep.js +559 -558
  60. package/config/themes/theme-default.js +559 -558
  61. package/config/themes/theme-eap.js +559 -558
  62. package/config/themes/theme-gold.js +559 -558
  63. package/config/themes/theme-lime.js +559 -558
  64. package/config/themes/theme-orange.js +560 -559
  65. package/config/themes/theme-red.js +559 -558
  66. package/config/themes/theme-white.js +558 -557
  67. package/config/themes/white/var.less +676 -675
  68. package/config/themes/white/white.css +576 -575
  69. package/config/themes/white/white.css.map +1 -1
  70. package/config/themes/white/white.less +669 -668
  71. package/directives/index.js +23 -23
  72. package/directives/module/draggable.js +56 -56
  73. package/directives/module/permission.js +49 -49
  74. package/directives/module/print.js +1 -1
  75. package/directives/module/vue-print-nb/README.md +63 -63
  76. package/directives/module/vue-print-nb/print.js +94 -94
  77. package/directives/module/vue-print-nb/printarea.js +532 -532
  78. package/index.js +10 -10
  79. package/nstyles/common.less +197 -197
  80. package/nstyles/components/404.less +46 -46
  81. package/nstyles/components/button.less +34 -34
  82. package/nstyles/components/date-picker.less +37 -37
  83. package/nstyles/components/drawer.less +20 -20
  84. package/nstyles/components/dropdown.less +18 -18
  85. package/nstyles/components/excel-flow.less +72 -72
  86. package/nstyles/components/form.less +313 -313
  87. package/nstyles/components/index.less +23 -23
  88. package/nstyles/components/layout/collect.less +10 -10
  89. package/nstyles/components/layout/detail-view.less +107 -107
  90. package/nstyles/components/layout/full-screen.less +7 -7
  91. package/nstyles/components/layout/index.less +7 -7
  92. package/nstyles/components/layout/other-menu.less +142 -142
  93. package/nstyles/components/layout/page-view.less +101 -101
  94. package/nstyles/components/layout/sider-trigger.less +41 -41
  95. package/nstyles/components/layout/tags-nav.less +113 -113
  96. package/nstyles/components/modal.less +85 -85
  97. package/nstyles/components/n-button.less +131 -131
  98. package/nstyles/components/n-image-preview.less +131 -131
  99. package/nstyles/components/n-model/index.less +19 -19
  100. package/nstyles/components/n-model/report-index.less +43 -43
  101. package/nstyles/components/n-panel.less +40 -40
  102. package/nstyles/components/n-picker.less +37 -37
  103. package/nstyles/components/n-sign.less +17 -17
  104. package/nstyles/components/n-tooltip.less +10 -10
  105. package/nstyles/components/panel.less +31 -31
  106. package/nstyles/components/select.less +3 -3
  107. package/nstyles/components/sign.less +27 -27
  108. package/nstyles/components/table.less +315 -315
  109. package/nstyles/components/tree.less +158 -158
  110. package/nstyles/components/upload.less +164 -164
  111. package/nstyles/index.less +5 -5
  112. package/nstyles/reset.less +65 -65
  113. package/nstyles/third/ag.less +174 -174
  114. package/nstyles/third/index.less +11 -11
  115. package/nstyles/third/view-design.less +366 -366
  116. package/nstyles/variables/base.less +143 -143
  117. package/nstyles/variables/index.less +4 -4
  118. package/nstyles/variables/theme/default/button.less +7 -7
  119. package/nstyles/variables/theme/default/common.less +57 -57
  120. package/nstyles/variables/theme/default/index.less +7 -7
  121. package/nstyles/variables/theme/default/layout.less +40 -40
  122. package/nstyles/variables/theme/default/table.less +37 -37
  123. package/nstyles/variables/theme/default/tag.less +3 -3
  124. package/nstyles/variables/theme/default/upload.less +3 -3
  125. package/nstyles/variables/theme/index.less +13 -13
  126. package/nstyles/variables/theme/lsv/button.less +7 -0
  127. package/nstyles/variables/theme/lsv/common.less +39 -0
  128. package/nstyles/variables/theme/lsv/index.less +5 -0
  129. package/nstyles/variables/theme/lsv/layout.less +21 -0
  130. package/nstyles/variables/theme/lsv/table.less +20 -0
  131. package/nstyles/variables/theme/lsv/tag.less +3 -0
  132. package/nstyles/variables/theme/small/button.less +7 -7
  133. package/nstyles/variables/theme/small/common.less +39 -39
  134. package/nstyles/variables/theme/small/index.less +5 -5
  135. package/nstyles/variables/theme/small/layout.less +21 -21
  136. package/nstyles/variables/theme/small/table.less +17 -17
  137. package/nstyles/variables/theme/small/tag.less +3 -3
  138. package/package.json +1 -1
  139. package/plugin/index.js +12 -12
  140. package/plugin/module/date-format.js +30 -30
  141. package/plugin/module/loading.js +26 -26
  142. package/plugin/module/warn-handler.js +11 -11
  143. package/styles/variables.less +21 -21
  144. package/utils/ajax/cacheconf.js +19 -19
  145. package/utils/ajax/content-type.js +30 -30
  146. package/utils/ajax/index.js +12 -12
  147. package/utils/ajax/interceptors.js +97 -97
  148. package/utils/ajax/sseFetchUtil.js +71 -71
  149. package/utils/assist.js +147 -147
  150. package/utils/base64.js +126 -126
  151. package/utils/blob.js +47 -47
  152. package/utils/bus.js +3 -3
  153. package/utils/crypto/index.js +48 -48
  154. package/utils/crypto/md5.js +152 -152
  155. package/utils/crypto/sm3.js +235 -235
  156. package/utils/date.js +381 -381
  157. package/utils/dict/built-in-dict.js +20 -20
  158. package/utils/dict/index.js +167 -167
  159. package/utils/dom.js +38 -38
  160. package/utils/event.js +72 -72
  161. package/utils/excel.js +655 -655
  162. package/utils/file.js +19 -19
  163. package/utils/form/validate.js +29 -29
  164. package/utils/half-year.js +68 -68
  165. package/utils/index.js +41 -41
  166. package/utils/json.js +29 -29
  167. package/utils/lodop.js +165 -165
  168. package/utils/menu/before-close.js +17 -17
  169. package/utils/menu/index.js +395 -395
  170. package/utils/mime_type.js +67 -67
  171. package/utils/modelerUtil.js +227 -227
  172. package/utils/n/api.js +22 -22
  173. package/utils/n/date.js +57 -57
  174. package/utils/n/index.js +9 -9
  175. package/utils/n/is-type.js +176 -176
  176. package/utils/n/number.js +144 -144
  177. package/utils/n/permission-cache.js +11 -11
  178. package/utils/n/reuqest/axiosN.js +17 -17
  179. package/utils/n/reuqest/content-type.js +19 -19
  180. package/utils/n/reuqest/interceptors.js +95 -95
  181. package/utils/n/reuqest/url-params.js +12 -12
  182. package/utils/n/storage.js +51 -51
  183. package/utils/n/token.js +51 -51
  184. package/utils/n/user-cache.js +11 -11
  185. package/utils/n/user.js +34 -34
  186. package/utils/n/uuid.js +16 -16
  187. package/utils/n-generator-routers.js +208 -208
  188. package/utils/n-router.js +205 -205
  189. package/utils/n-theme.js +30 -30
  190. package/utils/number.js +180 -180
  191. package/utils/oss.js +57 -57
  192. package/utils/platform.js +1343 -1334
  193. package/utils/quarter.js +58 -58
  194. package/utils/storage.js +198 -198
  195. package/utils/theme.js +138 -138
  196. package/utils/transform.js +204 -204
  197. package/utils/type.js +102 -102
  198. package/utils/util.js +795 -795
  199. package/utils/validator.js +181 -181
  200. package/utils/vxetable/index.js +25 -25
  201. package/utils/zoomScroll.js +9 -9
package/utils/excel.js CHANGED
@@ -1,655 +1,655 @@
1
- /* eslint-disable */
2
- import XLSX from '@e965/xlsx';
3
- import * as cpexcel from '@e965/xlsx/dist/cpexcel.full.mjs';
4
- XLSX.set_cptable(cpexcel);
5
- import {deepCopy} from "./assist";
6
- import XLSXStyle from 'xlsx-style'
7
-
8
- const titleRules = {
9
- '': '',
10
- '#': '#',
11
- '序号': '序号',
12
- '编号': '编号',
13
- '操作': '操作',
14
- }
15
- const typeRules = {
16
- 'index': 'index',
17
- 'select': 'select',
18
- 'selection': 'selection',
19
- 'single-selection': 'single-selection',
20
- 'checkbox': 'checkbox',
21
- 'radio': 'radio'
22
- }
23
-
24
- /**
25
- * 过滤掉filterData中titleRules、typeRules相关的列
26
- * @param filterData
27
- * @param key 包含typeRules内容的属性名
28
- * @param name 包含titleRules内容的属性名
29
- * @returns {*}
30
- */
31
- function title_filter_base(filterData,key,name) {
32
- for (var i = 0; i < filterData.length; i++) {
33
- if ((filterData[i].hasOwnProperty(key) && filterData[i][key]
34
- && filterData[i][key] === typeRules[filterData[i][key]])
35
- || filterData[i][name] === titleRules[filterData[i][name]]) {
36
- filterData.splice(i, 1)
37
- i--
38
- }
39
- }
40
- return filterData
41
- }
42
-
43
- function title_filter(data) {
44
- let filterData = deepCopy(data);
45
- return title_filter_base(filterData,'type','title')
46
- }
47
-
48
- function title_el_filter(data) {
49
- let filterData = deepCopy(data);
50
- return title_filter_base(filterData,'property','label')
51
- }
52
-
53
- /**
54
- * 组织表格导出时需要的表头单元格内容
55
- * @param treeData 列描述
56
- * @param key 单元格显示内容对应列描述中的属性名
57
- * @returns {*[][]}
58
- */
59
- function title_transform_base(treeData,key) {
60
- // 找到树的最大深度
61
- const maxDepth = findMaxDepth(treeData);
62
-
63
- // 初始化结果数组,每一层都是一个空数组
64
- const result = Array.from({ length: maxDepth }, () => []);
65
-
66
- // 辅助函数,用于找到树的最大深度
67
- function findMaxDepth(nodes) {
68
- let maxDepth = 0;
69
-
70
- function traverse(node, depth = 1) {
71
- maxDepth = Math.max(maxDepth, depth);
72
- if (node.children) {
73
- node.children.forEach(child => traverse(child, depth + 1));
74
- }
75
- }
76
-
77
- nodes.forEach(node => traverse(node));
78
-
79
- return maxDepth;
80
- }
81
-
82
- // 辅助函数,用于创建并返回从根节点到当前节点的路径
83
- function getPath(node, path = [], key) {
84
- path.unshift(node[key]); // 将当前节点的标题添加到路径的开头
85
- if (node.parent) {
86
- return getPath(node.parent, path, key); // 递归调用,直到根节点
87
- }
88
- return path;
89
- }
90
-
91
- // 递归函数,用于遍历树的每个节点并收集标题
92
- function traverseTree(node, depth = 0, parent = null, key) {
93
- // 给节点添加 parent 属性,方便后续创建路径
94
- node.parent = parent;
95
-
96
- // 确保当前深度的结果数组已初始化
97
- if (result.length <= depth) {
98
- result.push([]);
99
- }
100
-
101
- // 获取从根节点到当前节点的路径
102
- const path = getPath(node,[],key);
103
-
104
- // 当前层级和子层级都增加当前节点
105
- for (let i = depth; i < maxDepth; i++) {
106
- result[i].push(node[key])
107
- }
108
- // 当前层级的父层级增加对应的父节点
109
- for (let j = 0; j < depth; j++) {
110
- result[j].push(path[j])
111
- }
112
-
113
-
114
- // 如果还有子节点,递归遍历子节点
115
- if (node.children) {
116
- for (let i = 0; i < maxDepth; i++) {
117
- result[i].pop()
118
- }
119
- node.children.forEach(child => {
120
- traverseTree(child, depth + 1, node, key)
121
- });
122
- }
123
- }
124
-
125
- // 遍历所有根节点并收集标题
126
- treeData.forEach(rootNode => traverseTree(rootNode,0,null,key));
127
-
128
- // 去除每个节点上的 parent 属性(如果需要)
129
- function removeParentProps(nodes) {
130
- nodes.forEach(node => {
131
- delete node.parent;
132
- if (node.children) {
133
- removeParentProps(node.children);
134
- }
135
- });
136
- }
137
- removeParentProps(treeData); // 清理 treeData 中的 parent 属性(可选)
138
-
139
- return result;
140
- }
141
-
142
- export const title_transform = (paramData) => {
143
- let data = title_filter(paramData)
144
- return title_transform_base(data,'title')
145
- }
146
- export const title_el_transform = (paramData) => {
147
- let data = title_el_filter(paramData)
148
- return title_transform_base(data,'label')
149
- }
150
-
151
- /**
152
- * 表格导出时数据区域内容对应的属性名列表
153
- * @param data 列描述
154
- * @param key 表格导出时数据区域内容对应列描述中的属性名
155
- * @returns {*[]}
156
- */
157
- export const key_transform_base = (data,key) => {
158
- let result = []
159
- function traverse(node,key) {
160
- if (node.children) {
161
- node.children.forEach(child => traverse(child,key));
162
- }else{
163
- result.push(node[key])
164
- }
165
- }
166
-
167
- data.forEach(node => traverse(node,key));
168
-
169
- return result;
170
- }
171
-
172
- export const key_transform = (paramData) => {
173
- let data = title_filter(paramData)
174
- // let data = paramData
175
- return key_transform_base(data,'key')
176
- }
177
-
178
- export const key_el_transform = (paramData) => {
179
- let data = title_el_filter(paramData)
180
- // let data = paramData
181
- return key_transform_base(data,'property')
182
- }
183
-
184
- export const key_vxe_transform = (paramData) => {
185
- let data = title_filter(paramData)
186
- // let data = paramData
187
- return key_transform_base(data,'field')
188
- }
189
-
190
- /**
191
- * 表格导出时,表头数据中存储的枚举信息汇总
192
- * @param data 列描述
193
- * @param key 表格数据内容对应列描述的key
194
- * @returns {*[]}
195
- */
196
- export const enums_transform_base = (data,key) => {
197
- let result = []
198
- function traverse(node,key) {
199
- if (node.children) {
200
- node.children.forEach(child => traverse(child,key));
201
- }else if (node.enums){
202
- result.push({key:node[key],enums:node.enums})
203
- }
204
- }
205
-
206
- data.forEach(node => traverse(node,key));
207
- return result
208
- }
209
-
210
- export const enums_transform = (paramData) => {
211
- let result = []
212
- let data = title_filter(paramData)
213
- // let data = paramData
214
- return enums_transform_base(data,'key')
215
- }
216
-
217
- export const enums_el_transform = (paramData) => {
218
- let result = []
219
- let data = title_el_filter(paramData)
220
- // let data = paramData
221
- return enums_transform_base(data,'property')
222
- }
223
-
224
- export const enums_vxe_transform = (paramData) => {
225
- let result = []
226
- let data = title_filter(paramData)
227
- // let data = paramData
228
- return enums_transform_base(data,'field')
229
- }
230
-
231
-
232
- export const enums_to_value = (enums,jsonData)=>{
233
- if(enums&&enums.length>0){
234
- return jsonData.map(v => enums.map(e =>{
235
- v[e.key] = e.enums[v[e.key]]
236
- return v
237
- })[0])
238
- }else{
239
- return jsonData
240
- }
241
- }
242
-
243
- function auto_width(ws, data) {
244
- /*set worksheet max width per col*/
245
- const colWidth = data.map(row => row.map(val => {
246
- /*if null/undefined*/
247
- if (val == null) {
248
- return {'wch': 10};
249
- }
250
- /*if chinese*/
251
- else if (val.toString().charCodeAt(0) > 255) {
252
- return {'wch': val.toString().length * 2};
253
- } else {
254
- return {'wch': val.toString().length > 7 ? val.toString().length : 7};
255
- }
256
- }))
257
- /*start in the first row*/
258
- let result = colWidth[0];
259
- for (let i = 1; i < colWidth.length; i++) {
260
- for (let j = 0; j < colWidth[i].length; j++) {
261
- if (result[j]['wch'] < colWidth[i][j]['wch']) {
262
- result[j]['wch'] = colWidth[i][j]['wch'] > 7 ? colWidth[i][j]['wch'] : 7;
263
- }
264
- }
265
- }
266
- ws['!cols'] = result;
267
- }
268
-
269
- function merge_title(ws,title) {
270
- let mergeData = [];
271
-
272
- for (let i = 0; i < title.length; i++) {
273
- for (let j = 0; j < title[i].length; j++) {
274
- let currentCellValue = title[i][j];
275
- let merge = { s: { r: i, c: j }, e: { r: i, c: j } };
276
-
277
- // Check horizontal direction for merges
278
- while (
279
- j + 1 < title[i].length &&
280
- title[i][j + 1] === currentCellValue &&
281
- !isCellMerged(mergeData, { r: i, c: j + 1 })
282
- ) {
283
- merge.e.c = j + 1;
284
- j++;
285
- }
286
-
287
- // Check vertical direction for merges
288
- let originalRow = i;
289
- while (
290
- i + 1 < title.length &&
291
- title[i + 1][j] === currentCellValue &&
292
- !isCellMerged(mergeData, { r: i + 1, c: j })
293
- ) {
294
- i++;
295
-
296
- // Update the starting row if it's the first iteration of the vertical loop
297
- // if (i === originalRow + 1) {
298
- // merge.s.r = i;
299
- // }
300
-
301
- // Expand the end row
302
- merge.e.r = i;
303
- }
304
-
305
- // Add the merge object to the array if it's not empty
306
- if (merge.e.c > merge.s.c || merge.e.r > merge.s.r) {
307
- mergeData.push(merge);
308
-
309
- // Adjust the outer loop variables since we might have incremented i inside the loop
310
- i = originalRow;
311
- j = merge.e.c;
312
- }
313
- }
314
- }
315
-
316
- // return mergeData
317
- // Add the merge ranges to the worksheet
318
- if (ws['!merges']) {
319
- ws['!merges'] = ws['!merges'].concat(mergeData);
320
- } else {
321
- ws['!merges'] = mergeData;
322
- }
323
-
324
- // Helper function to check if a cell is already part of a merge range
325
- function isCellMerged(mergeData, cell) {
326
- for (let merge of mergeData) {
327
- if (
328
- cell.r >= merge.s.r &&
329
- cell.r <= merge.e.r &&
330
- cell.c >= merge.s.c &&
331
- cell.c <= merge.e.c
332
- ) {
333
- return true;
334
- }
335
- }
336
- return false;
337
- }
338
- }
339
-
340
- function merge_content(ws, tableData, spanColumnKeys, titleLen) {
341
- if (spanColumnKeys == null || spanColumnKeys.length === 0) {
342
- return null;
343
- }
344
- let flag = false
345
- let mergeData = []
346
- let sck = spanColumnKeys, dLen = tableData.length, kLen = sck.length, params = [];
347
- for (let i = 0; i < dLen; i++) {
348
- params[i] = []
349
- for (let j = 0; j < kLen; j++) {
350
- params[i][j] = {}
351
- }
352
- }
353
- for (let i = 0; i < dLen; i++) {
354
- for (let j = 0; j < kLen; j++) {
355
- let merge = {s: {r: i + titleLen, c: j}, e: {r: i + titleLen, c: j}}
356
- flag = false
357
- //如果单元格和右侧内容相同则合并
358
- let n = 1;
359
- while (j + n < kLen && tableData[i][sck[j]] === tableData[i][sck[j + n]]) {
360
- if (params[i][j + n].hasOwnProperty('disable')) {
361
- break
362
- }
363
- params[i][j + n].disable = true
364
- merge.e.c = j + n
365
- flag = true
366
- n++;
367
- }
368
- //如果单元格和下侧内容相同则合并
369
- let m = 1;
370
- while (i + m < dLen && tableData[i][sck[j]] === tableData[i + m][sck[j]] && tableData[i + m][sck[j]] !== '小计') {
371
- if (params[i + m][j].hasOwnProperty('disable')) {
372
- break
373
- }
374
- params[i + m][j].disable = true
375
- merge.e.r = i + titleLen + m
376
- flag = true
377
- m++;
378
- }
379
- if (flag) {
380
- mergeData.push(merge)
381
- params[i][j].disable = true
382
- }
383
- }
384
- }
385
- ws['!merges'] = ws['!merges'].concat(mergeData)
386
- }
387
-
388
- function add_style(ws, title) {
389
-
390
- // 补充空白数据
391
- let rangs = ws['!ref'].split(":");
392
- let rowSum = parseInt(rangs[1].replace(/[^0-9]/ig, ""))
393
- let colhash = []
394
- Object.keys(ws).forEach(item => {
395
- if (/^[A-Z]+\d+$/.test(item)) {
396
- var alphabet = item.replace(/[^a-z]+/ig, "");
397
- if (colhash.indexOf(alphabet) === -1) {
398
- colhash.push(alphabet)
399
- for (var i = 1; i <= rowSum; i++) {
400
- if (!ws.hasOwnProperty(alphabet + i)) {
401
- ws[alphabet + i] = {
402
- v: '',
403
- t: 's'
404
- }
405
- }
406
- }
407
- }
408
- }
409
- })
410
-
411
- let titleStyle = {
412
- border: {
413
- left: {style: 'thin', color: {rgb: "000000"}},
414
- top: {style: 'thin', color: {rgb: "000000"}},
415
- right: {style: 'thin', color: {rgb: "000000"}},
416
- bottom: {style: 'thin', color: {rgb: "000000"}},
417
- },
418
- alignment: {horizontal: "center", vertical: "center"},
419
- fill: {bgColor: {indexed: 64}, fgColor: {rgb: "5A9BD5"}}
420
- }
421
- let bodyPairStyle = {
422
- border: {
423
- left: {style: 'thin', color: {rgb: "000000"}},
424
- top: {style: 'thin', color: {rgb: "000000"}},
425
- right: {style: 'thin', color: {rgb: "000000"}},
426
- bottom: {style: 'thin', color: {rgb: "000000"}},
427
- },
428
- alignment: {vertical: "center"},
429
- fill: {bgColor: {indexed: 64}, fgColor: {rgb: "DDEBF7"}}
430
- }
431
- let bodyStyle = {
432
- border: {
433
- left: {style: 'thin', color: {rgb: "000000"}},
434
- top: {style: 'thin', color: {rgb: "000000"}},
435
- right: {style: 'thin', color: {rgb: "000000"}},
436
- bottom: {style: 'thin', color: {rgb: "000000"}},
437
- },
438
- alignment: {vertical: "center"}
439
- }
440
- Object.keys(ws).forEach(item => {
441
-
442
- /**
443
- * 加载表头样式:蓝色背景,水平垂直居中,边框
444
- */
445
- var reg = new RegExp("^[A-Z]+[1 -" + title.length + "]$", "gim");
446
- if (reg.test(item)) {
447
- ws[item].s = titleStyle
448
- } else
449
-
450
- /**
451
- * 表体样式: 垂直居中,边框
452
- */
453
- if (/^[A-Z]+\d+$/.test(item)) {
454
- if (parseInt(item.replace(/[^0-9]/ig, "")) % 2 === 0) {
455
- ws[item].s = bodyStyle
456
- } else {
457
- ws[item].s = bodyPairStyle
458
- }
459
-
460
- }
461
- })
462
- /* ws.B2 = {
463
- v:'',
464
- t:'s',
465
- s:bodyPairStyle
466
- }*/
467
-
468
- }
469
-
470
- export const export_table_to_excel = (id, filename) => {
471
- const table = document.getElementById(id);
472
- const wb = XLSX.utils.table_to_book(table);
473
- XLSX.writeFile(wb, filename + ".xlsx");
474
-
475
- /* the second way */
476
- // const table = document.getElementById(id);
477
- // const wb = XLSX.utils.book_new();
478
- // const ws = XLSX.utils.table_to_sheet(table);
479
- // XLSX.utils.book_append_sheet(wb, ws, filename);
480
- // XLSX.writeFile(wb, filename);
481
- }
482
-
483
- function json_to_array(key, jsonData) {
484
- return jsonData.map(v => key.map(j => {
485
- return v[j]
486
- }));
487
- }
488
- export const export_json_to_excel = ({data, key, title, filename, spanColumns, autoWidth, format}) => {
489
- const wb = XLSX.utils.book_new();
490
- const ws = XLSX.utils.json_to_sheet(data, {header: key, skipHeader: false});
491
- for (var i = title.length; i > 0; i--) {
492
- data.unshift(title[i - 1])
493
- }
494
- if (autoWidth) {
495
- const arr = json_to_array(key, data);
496
- auto_width(ws, arr);
497
- }
498
- merge_content(ws, data, spanColumns)
499
- XLSX.utils.book_append_sheet(wb, ws, filename);
500
- XLSX.writeFile(wb, filename + '.' + format);
501
- }
502
-
503
- export const export_array_to_excel = ({key, data, title, filename, spanColumns, autoWidth, format}) => {
504
- const wb = XLSX.utils.book_new();
505
- const arr = json_to_array(key, data);
506
- for (var i = title.length; i > 0; i--) {
507
- arr.unshift(title[i - 1])
508
- }
509
- const ws = XLSX.utils.aoa_to_sheet(arr);
510
- if (autoWidth) {
511
- auto_width(ws, arr);
512
- }
513
- // 合并表头
514
- if (!ws['!merges']) ws['!merges'] = [];
515
- if (title.length > 1) {
516
- merge_title(ws, title)
517
- }
518
- merge_content(ws, data, spanColumns, title.length)
519
- add_style(ws, title)
520
- XLSX.utils.book_append_sheet(wb, ws, filename);
521
- if(format === 'csv'){
522
- XLSX.writeFile(wb, filename + '.' + format,{
523
- // 要生成的文件类型
524
- bookType: "csv",
525
- // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
526
- bookSST: false});
527
- }else{
528
- // XLSX.writeFileXLSX(wb, filename + '.' + format);
529
- const workbookBlob = workbook2blob(wb);
530
- saveAs(workbookBlob, filename + '.' + format);
531
- }
532
- }
533
-
534
- /**
535
- * 将一个字符串 s 转换为一个 ArrayBuffer 对象(如果可用)或一个普通数组(如果 ArrayBuffer 不可用)
536
- * @param s
537
- * @returns {any[]|ArrayBuffer}
538
- */
539
- function s2ab(s) {
540
- if (typeof ArrayBuffer !== 'undefined') {
541
- let buf = new ArrayBuffer(s.length);
542
- let view = new Uint8Array(buf);
543
- for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
544
- return buf;
545
- } else {
546
- let buf = new Array(s.length);
547
- for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
548
- return buf;
549
- }
550
- }
551
-
552
- /**
553
- * 将一个 ArrayBuffer 或 TypedArray 对象转换为一个字符串
554
- * @param data
555
- * @returns {string}
556
- */
557
- function ab2s(data) {
558
- let o = ''
559
- let l = 0
560
- const w = 10240
561
- for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
562
- o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
563
- return o
564
- }
565
-
566
- // 将workbook装化成blob对象
567
- function workbook2blob(workbook) {
568
- // 生成excel的配置项
569
- const wopts = {
570
- // 要生成的文件类型
571
- bookType: "xlsx",
572
- // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
573
- bookSST: false,
574
- type: "binary"
575
- };
576
- let wbout = XLSXStyle.write(workbook, wopts);
577
- let blob = new Blob([s2ab(wbout)], {
578
- type: "application/octet-stream"
579
- });
580
- return blob;
581
- }
582
-
583
- export const saveAs = function(blob, fileName) {
584
- // IE10+
585
- if (window.navigator.msSaveOrOpenBlob) {
586
- navigator.msSaveBlob(blob, fileName)
587
- } else {
588
- if (typeof blob == "object" && blob instanceof Blob) {
589
- blob = URL.createObjectURL(blob); // 创建blob地址
590
- }
591
- let aLink = document.createElement("a");
592
- aLink.href = blob;
593
- // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,有时候 file:///模式下不会生效
594
- aLink.download = fileName || "下载";
595
- let event;
596
- if (window.MouseEvent) event = new MouseEvent("click");
597
- //移动端
598
- else {
599
- event = document.createEvent("MouseEvents");
600
- event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
601
- }
602
- aLink.dispatchEvent(event);
603
- setTimeout(function () {
604
- aLink.remove();
605
- URL.revokeObjectURL(blob);
606
- }, 100);
607
- }
608
- }
609
-
610
- // get head from excel file,return array
611
- function get_header_row(sheet) {
612
- const headers = []
613
- const range = XLSX.utils.decode_range(sheet['!ref'])
614
- let C
615
- const R = range.s.r
616
- /* start in the first row */
617
- for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
618
- var cell = sheet[XLSX.utils.encode_cell({c: C, r: R})]
619
- /* find the cell in the first row */
620
- var hdr = 'UNKNOWN ' + C // <-- replace with your desired default
621
- if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
622
- headers.push(hdr)
623
- }
624
- return headers
625
- }
626
-
627
- export const read = (data, type) => {
628
- /* if type == 'base64' must fix data first */
629
- // const fixedData = ab2s(data)
630
- // const workbook = XLSX.read(btoa(fixedData), { type: 'base64' })
631
- const workbook = XLSX.read(data, {type: type});
632
- const firstSheetName = workbook.SheetNames[0];
633
- const worksheet = workbook.Sheets[firstSheetName];
634
- const header = get_header_row(worksheet);
635
- const results = XLSX.utils.sheet_to_json(worksheet);
636
- return {header, results};
637
- }
638
-
639
- export default {
640
- export_table_to_excel,
641
- export_array_to_excel,
642
- export_json_to_excel,
643
- key_transform,
644
- key_el_transform,
645
- key_vxe_transform,
646
- title_transform,
647
- title_el_transform,
648
- enums_transform,
649
- enums_el_transform,
650
- enums_vxe_transform,
651
- enums_to_value,
652
- read,
653
- s2ab,
654
- saveAs
655
- }
1
+ /* eslint-disable */
2
+ import XLSX from '@e965/xlsx';
3
+ import * as cpexcel from '@e965/xlsx/dist/cpexcel.full.mjs';
4
+ XLSX.set_cptable(cpexcel);
5
+ import {deepCopy} from "./assist";
6
+ import XLSXStyle from 'xlsx-style'
7
+
8
+ const titleRules = {
9
+ '': '',
10
+ '#': '#',
11
+ '序号': '序号',
12
+ '编号': '编号',
13
+ '操作': '操作',
14
+ }
15
+ const typeRules = {
16
+ 'index': 'index',
17
+ 'select': 'select',
18
+ 'selection': 'selection',
19
+ 'single-selection': 'single-selection',
20
+ 'checkbox': 'checkbox',
21
+ 'radio': 'radio'
22
+ }
23
+
24
+ /**
25
+ * 过滤掉filterData中titleRules、typeRules相关的列
26
+ * @param filterData
27
+ * @param key 包含typeRules内容的属性名
28
+ * @param name 包含titleRules内容的属性名
29
+ * @returns {*}
30
+ */
31
+ function title_filter_base(filterData,key,name) {
32
+ for (var i = 0; i < filterData.length; i++) {
33
+ if ((filterData[i].hasOwnProperty(key) && filterData[i][key]
34
+ && filterData[i][key] === typeRules[filterData[i][key]])
35
+ || filterData[i][name] === titleRules[filterData[i][name]]) {
36
+ filterData.splice(i, 1)
37
+ i--
38
+ }
39
+ }
40
+ return filterData
41
+ }
42
+
43
+ function title_filter(data) {
44
+ let filterData = deepCopy(data);
45
+ return title_filter_base(filterData,'type','title')
46
+ }
47
+
48
+ function title_el_filter(data) {
49
+ let filterData = deepCopy(data);
50
+ return title_filter_base(filterData,'property','label')
51
+ }
52
+
53
+ /**
54
+ * 组织表格导出时需要的表头单元格内容
55
+ * @param treeData 列描述
56
+ * @param key 单元格显示内容对应列描述中的属性名
57
+ * @returns {*[][]}
58
+ */
59
+ function title_transform_base(treeData,key) {
60
+ // 找到树的最大深度
61
+ const maxDepth = findMaxDepth(treeData);
62
+
63
+ // 初始化结果数组,每一层都是一个空数组
64
+ const result = Array.from({ length: maxDepth }, () => []);
65
+
66
+ // 辅助函数,用于找到树的最大深度
67
+ function findMaxDepth(nodes) {
68
+ let maxDepth = 0;
69
+
70
+ function traverse(node, depth = 1) {
71
+ maxDepth = Math.max(maxDepth, depth);
72
+ if (node.children) {
73
+ node.children.forEach(child => traverse(child, depth + 1));
74
+ }
75
+ }
76
+
77
+ nodes.forEach(node => traverse(node));
78
+
79
+ return maxDepth;
80
+ }
81
+
82
+ // 辅助函数,用于创建并返回从根节点到当前节点的路径
83
+ function getPath(node, path = [], key) {
84
+ path.unshift(node[key]); // 将当前节点的标题添加到路径的开头
85
+ if (node.parent) {
86
+ return getPath(node.parent, path, key); // 递归调用,直到根节点
87
+ }
88
+ return path;
89
+ }
90
+
91
+ // 递归函数,用于遍历树的每个节点并收集标题
92
+ function traverseTree(node, depth = 0, parent = null, key) {
93
+ // 给节点添加 parent 属性,方便后续创建路径
94
+ node.parent = parent;
95
+
96
+ // 确保当前深度的结果数组已初始化
97
+ if (result.length <= depth) {
98
+ result.push([]);
99
+ }
100
+
101
+ // 获取从根节点到当前节点的路径
102
+ const path = getPath(node,[],key);
103
+
104
+ // 当前层级和子层级都增加当前节点
105
+ for (let i = depth; i < maxDepth; i++) {
106
+ result[i].push(node[key])
107
+ }
108
+ // 当前层级的父层级增加对应的父节点
109
+ for (let j = 0; j < depth; j++) {
110
+ result[j].push(path[j])
111
+ }
112
+
113
+
114
+ // 如果还有子节点,递归遍历子节点
115
+ if (node.children) {
116
+ for (let i = 0; i < maxDepth; i++) {
117
+ result[i].pop()
118
+ }
119
+ node.children.forEach(child => {
120
+ traverseTree(child, depth + 1, node, key)
121
+ });
122
+ }
123
+ }
124
+
125
+ // 遍历所有根节点并收集标题
126
+ treeData.forEach(rootNode => traverseTree(rootNode,0,null,key));
127
+
128
+ // 去除每个节点上的 parent 属性(如果需要)
129
+ function removeParentProps(nodes) {
130
+ nodes.forEach(node => {
131
+ delete node.parent;
132
+ if (node.children) {
133
+ removeParentProps(node.children);
134
+ }
135
+ });
136
+ }
137
+ removeParentProps(treeData); // 清理 treeData 中的 parent 属性(可选)
138
+
139
+ return result;
140
+ }
141
+
142
+ export const title_transform = (paramData) => {
143
+ let data = title_filter(paramData)
144
+ return title_transform_base(data,'title')
145
+ }
146
+ export const title_el_transform = (paramData) => {
147
+ let data = title_el_filter(paramData)
148
+ return title_transform_base(data,'label')
149
+ }
150
+
151
+ /**
152
+ * 表格导出时数据区域内容对应的属性名列表
153
+ * @param data 列描述
154
+ * @param key 表格导出时数据区域内容对应列描述中的属性名
155
+ * @returns {*[]}
156
+ */
157
+ export const key_transform_base = (data,key) => {
158
+ let result = []
159
+ function traverse(node,key) {
160
+ if (node.children) {
161
+ node.children.forEach(child => traverse(child,key));
162
+ }else{
163
+ result.push(node[key])
164
+ }
165
+ }
166
+
167
+ data.forEach(node => traverse(node,key));
168
+
169
+ return result;
170
+ }
171
+
172
+ export const key_transform = (paramData) => {
173
+ let data = title_filter(paramData)
174
+ // let data = paramData
175
+ return key_transform_base(data,'key')
176
+ }
177
+
178
+ export const key_el_transform = (paramData) => {
179
+ let data = title_el_filter(paramData)
180
+ // let data = paramData
181
+ return key_transform_base(data,'property')
182
+ }
183
+
184
+ export const key_vxe_transform = (paramData) => {
185
+ let data = title_filter(paramData)
186
+ // let data = paramData
187
+ return key_transform_base(data,'field')
188
+ }
189
+
190
+ /**
191
+ * 表格导出时,表头数据中存储的枚举信息汇总
192
+ * @param data 列描述
193
+ * @param key 表格数据内容对应列描述的key
194
+ * @returns {*[]}
195
+ */
196
+ export const enums_transform_base = (data,key) => {
197
+ let result = []
198
+ function traverse(node,key) {
199
+ if (node.children) {
200
+ node.children.forEach(child => traverse(child,key));
201
+ }else if (node.enums){
202
+ result.push({key:node[key],enums:node.enums})
203
+ }
204
+ }
205
+
206
+ data.forEach(node => traverse(node,key));
207
+ return result
208
+ }
209
+
210
+ export const enums_transform = (paramData) => {
211
+ let result = []
212
+ let data = title_filter(paramData)
213
+ // let data = paramData
214
+ return enums_transform_base(data,'key')
215
+ }
216
+
217
+ export const enums_el_transform = (paramData) => {
218
+ let result = []
219
+ let data = title_el_filter(paramData)
220
+ // let data = paramData
221
+ return enums_transform_base(data,'property')
222
+ }
223
+
224
+ export const enums_vxe_transform = (paramData) => {
225
+ let result = []
226
+ let data = title_filter(paramData)
227
+ // let data = paramData
228
+ return enums_transform_base(data,'field')
229
+ }
230
+
231
+
232
+ export const enums_to_value = (enums,jsonData)=>{
233
+ if(enums&&enums.length>0){
234
+ return jsonData.map(v => enums.map(e =>{
235
+ v[e.key] = e.enums[v[e.key]]
236
+ return v
237
+ })[0])
238
+ }else{
239
+ return jsonData
240
+ }
241
+ }
242
+
243
+ function auto_width(ws, data) {
244
+ /*set worksheet max width per col*/
245
+ const colWidth = data.map(row => row.map(val => {
246
+ /*if null/undefined*/
247
+ if (val == null) {
248
+ return {'wch': 10};
249
+ }
250
+ /*if chinese*/
251
+ else if (val.toString().charCodeAt(0) > 255) {
252
+ return {'wch': val.toString().length * 2};
253
+ } else {
254
+ return {'wch': val.toString().length > 7 ? val.toString().length : 7};
255
+ }
256
+ }))
257
+ /*start in the first row*/
258
+ let result = colWidth[0];
259
+ for (let i = 1; i < colWidth.length; i++) {
260
+ for (let j = 0; j < colWidth[i].length; j++) {
261
+ if (result[j]['wch'] < colWidth[i][j]['wch']) {
262
+ result[j]['wch'] = colWidth[i][j]['wch'] > 7 ? colWidth[i][j]['wch'] : 7;
263
+ }
264
+ }
265
+ }
266
+ ws['!cols'] = result;
267
+ }
268
+
269
+ function merge_title(ws,title) {
270
+ let mergeData = [];
271
+
272
+ for (let i = 0; i < title.length; i++) {
273
+ for (let j = 0; j < title[i].length; j++) {
274
+ let currentCellValue = title[i][j];
275
+ let merge = { s: { r: i, c: j }, e: { r: i, c: j } };
276
+
277
+ // Check horizontal direction for merges
278
+ while (
279
+ j + 1 < title[i].length &&
280
+ title[i][j + 1] === currentCellValue &&
281
+ !isCellMerged(mergeData, { r: i, c: j + 1 })
282
+ ) {
283
+ merge.e.c = j + 1;
284
+ j++;
285
+ }
286
+
287
+ // Check vertical direction for merges
288
+ let originalRow = i;
289
+ while (
290
+ i + 1 < title.length &&
291
+ title[i + 1][j] === currentCellValue &&
292
+ !isCellMerged(mergeData, { r: i + 1, c: j })
293
+ ) {
294
+ i++;
295
+
296
+ // Update the starting row if it's the first iteration of the vertical loop
297
+ // if (i === originalRow + 1) {
298
+ // merge.s.r = i;
299
+ // }
300
+
301
+ // Expand the end row
302
+ merge.e.r = i;
303
+ }
304
+
305
+ // Add the merge object to the array if it's not empty
306
+ if (merge.e.c > merge.s.c || merge.e.r > merge.s.r) {
307
+ mergeData.push(merge);
308
+
309
+ // Adjust the outer loop variables since we might have incremented i inside the loop
310
+ i = originalRow;
311
+ j = merge.e.c;
312
+ }
313
+ }
314
+ }
315
+
316
+ // return mergeData
317
+ // Add the merge ranges to the worksheet
318
+ if (ws['!merges']) {
319
+ ws['!merges'] = ws['!merges'].concat(mergeData);
320
+ } else {
321
+ ws['!merges'] = mergeData;
322
+ }
323
+
324
+ // Helper function to check if a cell is already part of a merge range
325
+ function isCellMerged(mergeData, cell) {
326
+ for (let merge of mergeData) {
327
+ if (
328
+ cell.r >= merge.s.r &&
329
+ cell.r <= merge.e.r &&
330
+ cell.c >= merge.s.c &&
331
+ cell.c <= merge.e.c
332
+ ) {
333
+ return true;
334
+ }
335
+ }
336
+ return false;
337
+ }
338
+ }
339
+
340
+ function merge_content(ws, tableData, spanColumnKeys, titleLen) {
341
+ if (spanColumnKeys == null || spanColumnKeys.length === 0) {
342
+ return null;
343
+ }
344
+ let flag = false
345
+ let mergeData = []
346
+ let sck = spanColumnKeys, dLen = tableData.length, kLen = sck.length, params = [];
347
+ for (let i = 0; i < dLen; i++) {
348
+ params[i] = []
349
+ for (let j = 0; j < kLen; j++) {
350
+ params[i][j] = {}
351
+ }
352
+ }
353
+ for (let i = 0; i < dLen; i++) {
354
+ for (let j = 0; j < kLen; j++) {
355
+ let merge = {s: {r: i + titleLen, c: j}, e: {r: i + titleLen, c: j}}
356
+ flag = false
357
+ //如果单元格和右侧内容相同则合并
358
+ let n = 1;
359
+ while (j + n < kLen && tableData[i][sck[j]] === tableData[i][sck[j + n]]) {
360
+ if (params[i][j + n].hasOwnProperty('disable')) {
361
+ break
362
+ }
363
+ params[i][j + n].disable = true
364
+ merge.e.c = j + n
365
+ flag = true
366
+ n++;
367
+ }
368
+ //如果单元格和下侧内容相同则合并
369
+ let m = 1;
370
+ while (i + m < dLen && tableData[i][sck[j]] === tableData[i + m][sck[j]] && tableData[i + m][sck[j]] !== '小计') {
371
+ if (params[i + m][j].hasOwnProperty('disable')) {
372
+ break
373
+ }
374
+ params[i + m][j].disable = true
375
+ merge.e.r = i + titleLen + m
376
+ flag = true
377
+ m++;
378
+ }
379
+ if (flag) {
380
+ mergeData.push(merge)
381
+ params[i][j].disable = true
382
+ }
383
+ }
384
+ }
385
+ ws['!merges'] = ws['!merges'].concat(mergeData)
386
+ }
387
+
388
+ function add_style(ws, title) {
389
+
390
+ // 补充空白数据
391
+ let rangs = ws['!ref'].split(":");
392
+ let rowSum = parseInt(rangs[1].replace(/[^0-9]/ig, ""))
393
+ let colhash = []
394
+ Object.keys(ws).forEach(item => {
395
+ if (/^[A-Z]+\d+$/.test(item)) {
396
+ var alphabet = item.replace(/[^a-z]+/ig, "");
397
+ if (colhash.indexOf(alphabet) === -1) {
398
+ colhash.push(alphabet)
399
+ for (var i = 1; i <= rowSum; i++) {
400
+ if (!ws.hasOwnProperty(alphabet + i)) {
401
+ ws[alphabet + i] = {
402
+ v: '',
403
+ t: 's'
404
+ }
405
+ }
406
+ }
407
+ }
408
+ }
409
+ })
410
+
411
+ let titleStyle = {
412
+ border: {
413
+ left: {style: 'thin', color: {rgb: "000000"}},
414
+ top: {style: 'thin', color: {rgb: "000000"}},
415
+ right: {style: 'thin', color: {rgb: "000000"}},
416
+ bottom: {style: 'thin', color: {rgb: "000000"}},
417
+ },
418
+ alignment: {horizontal: "center", vertical: "center"},
419
+ fill: {bgColor: {indexed: 64}, fgColor: {rgb: "5A9BD5"}}
420
+ }
421
+ let bodyPairStyle = {
422
+ border: {
423
+ left: {style: 'thin', color: {rgb: "000000"}},
424
+ top: {style: 'thin', color: {rgb: "000000"}},
425
+ right: {style: 'thin', color: {rgb: "000000"}},
426
+ bottom: {style: 'thin', color: {rgb: "000000"}},
427
+ },
428
+ alignment: {vertical: "center"},
429
+ fill: {bgColor: {indexed: 64}, fgColor: {rgb: "DDEBF7"}}
430
+ }
431
+ let bodyStyle = {
432
+ border: {
433
+ left: {style: 'thin', color: {rgb: "000000"}},
434
+ top: {style: 'thin', color: {rgb: "000000"}},
435
+ right: {style: 'thin', color: {rgb: "000000"}},
436
+ bottom: {style: 'thin', color: {rgb: "000000"}},
437
+ },
438
+ alignment: {vertical: "center"}
439
+ }
440
+ Object.keys(ws).forEach(item => {
441
+
442
+ /**
443
+ * 加载表头样式:蓝色背景,水平垂直居中,边框
444
+ */
445
+ var reg = new RegExp("^[A-Z]+[1 -" + title.length + "]$", "gim");
446
+ if (reg.test(item)) {
447
+ ws[item].s = titleStyle
448
+ } else
449
+
450
+ /**
451
+ * 表体样式: 垂直居中,边框
452
+ */
453
+ if (/^[A-Z]+\d+$/.test(item)) {
454
+ if (parseInt(item.replace(/[^0-9]/ig, "")) % 2 === 0) {
455
+ ws[item].s = bodyStyle
456
+ } else {
457
+ ws[item].s = bodyPairStyle
458
+ }
459
+
460
+ }
461
+ })
462
+ /* ws.B2 = {
463
+ v:'',
464
+ t:'s',
465
+ s:bodyPairStyle
466
+ }*/
467
+
468
+ }
469
+
470
+ export const export_table_to_excel = (id, filename) => {
471
+ const table = document.getElementById(id);
472
+ const wb = XLSX.utils.table_to_book(table);
473
+ XLSX.writeFile(wb, filename + ".xlsx");
474
+
475
+ /* the second way */
476
+ // const table = document.getElementById(id);
477
+ // const wb = XLSX.utils.book_new();
478
+ // const ws = XLSX.utils.table_to_sheet(table);
479
+ // XLSX.utils.book_append_sheet(wb, ws, filename);
480
+ // XLSX.writeFile(wb, filename);
481
+ }
482
+
483
+ function json_to_array(key, jsonData) {
484
+ return jsonData.map(v => key.map(j => {
485
+ return v[j]
486
+ }));
487
+ }
488
+ export const export_json_to_excel = ({data, key, title, filename, spanColumns, autoWidth, format}) => {
489
+ const wb = XLSX.utils.book_new();
490
+ const ws = XLSX.utils.json_to_sheet(data, {header: key, skipHeader: false});
491
+ for (var i = title.length; i > 0; i--) {
492
+ data.unshift(title[i - 1])
493
+ }
494
+ if (autoWidth) {
495
+ const arr = json_to_array(key, data);
496
+ auto_width(ws, arr);
497
+ }
498
+ merge_content(ws, data, spanColumns)
499
+ XLSX.utils.book_append_sheet(wb, ws, filename);
500
+ XLSX.writeFile(wb, filename + '.' + format);
501
+ }
502
+
503
+ export const export_array_to_excel = ({key, data, title, filename, spanColumns, autoWidth, format}) => {
504
+ const wb = XLSX.utils.book_new();
505
+ const arr = json_to_array(key, data);
506
+ for (var i = title.length; i > 0; i--) {
507
+ arr.unshift(title[i - 1])
508
+ }
509
+ const ws = XLSX.utils.aoa_to_sheet(arr);
510
+ if (autoWidth) {
511
+ auto_width(ws, arr);
512
+ }
513
+ // 合并表头
514
+ if (!ws['!merges']) ws['!merges'] = [];
515
+ if (title.length > 1) {
516
+ merge_title(ws, title)
517
+ }
518
+ merge_content(ws, data, spanColumns, title.length)
519
+ add_style(ws, title)
520
+ XLSX.utils.book_append_sheet(wb, ws, filename);
521
+ if(format === 'csv'){
522
+ XLSX.writeFile(wb, filename + '.' + format,{
523
+ // 要生成的文件类型
524
+ bookType: "csv",
525
+ // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
526
+ bookSST: false});
527
+ }else{
528
+ // XLSX.writeFileXLSX(wb, filename + '.' + format);
529
+ const workbookBlob = workbook2blob(wb);
530
+ saveAs(workbookBlob, filename + '.' + format);
531
+ }
532
+ }
533
+
534
+ /**
535
+ * 将一个字符串 s 转换为一个 ArrayBuffer 对象(如果可用)或一个普通数组(如果 ArrayBuffer 不可用)
536
+ * @param s
537
+ * @returns {any[]|ArrayBuffer}
538
+ */
539
+ function s2ab(s) {
540
+ if (typeof ArrayBuffer !== 'undefined') {
541
+ let buf = new ArrayBuffer(s.length);
542
+ let view = new Uint8Array(buf);
543
+ for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
544
+ return buf;
545
+ } else {
546
+ let buf = new Array(s.length);
547
+ for (let i = 0; i !== s.length; ++i) buf[i] = s.charCodeAt(i) & 0xFF;
548
+ return buf;
549
+ }
550
+ }
551
+
552
+ /**
553
+ * 将一个 ArrayBuffer 或 TypedArray 对象转换为一个字符串
554
+ * @param data
555
+ * @returns {string}
556
+ */
557
+ function ab2s(data) {
558
+ let o = ''
559
+ let l = 0
560
+ const w = 10240
561
+ for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w)))
562
+ o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
563
+ return o
564
+ }
565
+
566
+ // 将workbook装化成blob对象
567
+ function workbook2blob(workbook) {
568
+ // 生成excel的配置项
569
+ const wopts = {
570
+ // 要生成的文件类型
571
+ bookType: "xlsx",
572
+ // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
573
+ bookSST: false,
574
+ type: "binary"
575
+ };
576
+ let wbout = XLSXStyle.write(workbook, wopts);
577
+ let blob = new Blob([s2ab(wbout)], {
578
+ type: "application/octet-stream"
579
+ });
580
+ return blob;
581
+ }
582
+
583
+ export const saveAs = function(blob, fileName) {
584
+ // IE10+
585
+ if (window.navigator.msSaveOrOpenBlob) {
586
+ navigator.msSaveBlob(blob, fileName)
587
+ } else {
588
+ if (typeof blob == "object" && blob instanceof Blob) {
589
+ blob = URL.createObjectURL(blob); // 创建blob地址
590
+ }
591
+ let aLink = document.createElement("a");
592
+ aLink.href = blob;
593
+ // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,有时候 file:///模式下不会生效
594
+ aLink.download = fileName || "下载";
595
+ let event;
596
+ if (window.MouseEvent) event = new MouseEvent("click");
597
+ //移动端
598
+ else {
599
+ event = document.createEvent("MouseEvents");
600
+ event.initMouseEvent("click", true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
601
+ }
602
+ aLink.dispatchEvent(event);
603
+ setTimeout(function () {
604
+ aLink.remove();
605
+ URL.revokeObjectURL(blob);
606
+ }, 100);
607
+ }
608
+ }
609
+
610
+ // get head from excel file,return array
611
+ function get_header_row(sheet) {
612
+ const headers = []
613
+ const range = XLSX.utils.decode_range(sheet['!ref'])
614
+ let C
615
+ const R = range.s.r
616
+ /* start in the first row */
617
+ for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
618
+ var cell = sheet[XLSX.utils.encode_cell({c: C, r: R})]
619
+ /* find the cell in the first row */
620
+ var hdr = 'UNKNOWN ' + C // <-- replace with your desired default
621
+ if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
622
+ headers.push(hdr)
623
+ }
624
+ return headers
625
+ }
626
+
627
+ export const read = (data, type) => {
628
+ /* if type == 'base64' must fix data first */
629
+ // const fixedData = ab2s(data)
630
+ // const workbook = XLSX.read(btoa(fixedData), { type: 'base64' })
631
+ const workbook = XLSX.read(data, {type: type});
632
+ const firstSheetName = workbook.SheetNames[0];
633
+ const worksheet = workbook.Sheets[firstSheetName];
634
+ const header = get_header_row(worksheet);
635
+ const results = XLSX.utils.sheet_to_json(worksheet);
636
+ return {header, results};
637
+ }
638
+
639
+ export default {
640
+ export_table_to_excel,
641
+ export_array_to_excel,
642
+ export_json_to_excel,
643
+ key_transform,
644
+ key_el_transform,
645
+ key_vxe_transform,
646
+ title_transform,
647
+ title_el_transform,
648
+ enums_transform,
649
+ enums_el_transform,
650
+ enums_vxe_transform,
651
+ enums_to_value,
652
+ read,
653
+ s2ab,
654
+ saveAs
655
+ }