@hbdlzy/ui-core 0.1.0 → 0.1.2

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 (51) hide show
  1. package/README.md +61 -3
  2. package/components.manifest.json +239 -24
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.js +3005 -13
  5. package/dist/style.css +1 -0
  6. package/package.json +5 -3
  7. package/src/components/BaseCard/BaseCard.types.ts +38 -0
  8. package/src/components/BaseCard/BaseCard.vue +250 -0
  9. package/src/components/BaseCard/README.md +164 -0
  10. package/src/components/BaseCard/index.ts +5 -0
  11. package/src/components/BaseEChart/BaseEChart.types.ts +35 -0
  12. package/src/components/BaseEChart/BaseEChart.vue +327 -0
  13. package/src/components/BaseEChart/README.md +136 -0
  14. package/src/components/BaseEChart/index.ts +5 -0
  15. package/src/components/BaseExportButton/BaseExportButton.vue +1 -1
  16. package/src/components/BaseExportButton/README.md +104 -8
  17. package/src/components/BaseTable/BaseTable.types.ts +174 -0
  18. package/src/components/BaseTable/BaseTable.vue +809 -0
  19. package/src/components/BaseTable/README.md +398 -0
  20. package/src/components/BaseTable/index.ts +25 -0
  21. package/src/components/OutlinedCascader/OutlinedCascader.types.ts +28 -0
  22. package/src/components/OutlinedCascader/OutlinedCascader.vue +250 -0
  23. package/src/components/OutlinedCascader/README.md +91 -0
  24. package/src/components/OutlinedCascader/index.ts +10 -0
  25. package/src/components/OutlinedDatePicker/OutlinedDatePicker.types.ts +40 -0
  26. package/src/components/OutlinedDatePicker/OutlinedDatePicker.vue +365 -0
  27. package/src/components/OutlinedDatePicker/README.md +137 -0
  28. package/src/components/OutlinedDatePicker/index.ts +11 -0
  29. package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.types.ts +34 -0
  30. package/src/components/OutlinedDateTimePicker/OutlinedDateTimePicker.vue +421 -0
  31. package/src/components/OutlinedDateTimePicker/README.md +88 -0
  32. package/src/components/OutlinedDateTimePicker/index.ts +11 -0
  33. package/src/components/OutlinedInput/OutlinedInput.types.ts +32 -0
  34. package/src/components/OutlinedInput/OutlinedInput.vue +307 -0
  35. package/src/components/OutlinedInput/README.md +154 -0
  36. package/src/components/OutlinedInput/index.ts +10 -0
  37. package/src/components/OutlinedSelect/OutlinedSelect.types.ts +48 -0
  38. package/src/components/OutlinedSelect/OutlinedSelect.vue +359 -0
  39. package/src/components/OutlinedSelect/README.md +166 -0
  40. package/src/components/OutlinedSelect/index.ts +12 -0
  41. package/src/components/OutlinedTimePicker/OutlinedTimePicker.types.ts +36 -0
  42. package/src/components/OutlinedTimePicker/OutlinedTimePicker.vue +303 -0
  43. package/src/components/OutlinedTimePicker/README.md +93 -0
  44. package/src/components/OutlinedTimePicker/index.ts +10 -0
  45. package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.types.ts +56 -0
  46. package/src/components/OutlinedTreeSelect/OutlinedTreeSelect.vue +354 -0
  47. package/src/components/OutlinedTreeSelect/README.md +107 -0
  48. package/src/components/OutlinedTreeSelect/index.ts +12 -0
  49. package/src/echarts/index.ts +12 -0
  50. package/src/excel/exportExcel.ts +36 -10
  51. package/src/index.ts +29 -0
@@ -0,0 +1,354 @@
1
+ <template>
2
+ <div
3
+ class="outlined-tree-select"
4
+ :class="[containerClasses, rootClass]"
5
+ :style="[containerStyle, rootStyle]"
6
+ >
7
+ <el-tree-select
8
+ ref="treeSelectRef"
9
+ v-bind="treeSelectAttrs"
10
+ class="outlined-tree-select__control"
11
+ :model-value="treeSelectValue"
12
+ :data="data"
13
+ :props="resolvedTreeProps"
14
+ :placeholder="placeholder"
15
+ :disabled="disabled"
16
+ :clearable="clearable"
17
+ :filterable="filterable"
18
+ :multiple="multiple"
19
+ :show-checkbox="showCheckbox"
20
+ :check-strictly="checkStrictly"
21
+ :check-on-click-node="checkOnClickNode"
22
+ :default-expand-all="defaultExpandAll"
23
+ :expand-on-click-node="expandOnClickNode"
24
+ :render-after-expand="renderAfterExpand"
25
+ :collapse-tags="collapseTags"
26
+ :collapse-tags-tooltip="collapseTagsTooltip"
27
+ :max-collapse-tags="maxCollapseTags"
28
+ :popper-class="popperClass"
29
+ :node-key="nodeKey"
30
+ :style="treeSelectStyle"
31
+ @update:model-value="handleModelValueUpdate"
32
+ @focus="handleFocus"
33
+ @blur="handleBlur"
34
+ @change="handleChange"
35
+ @visible-change="handleVisibleChange"
36
+ @clear="handleClear"
37
+ >
38
+ <template #empty>
39
+ <slot name="empty" />
40
+ </template>
41
+
42
+ <template #header>
43
+ <slot name="header" />
44
+ </template>
45
+
46
+ <template #footer>
47
+ <slot name="footer" />
48
+ </template>
49
+ </el-tree-select>
50
+
51
+ <div
52
+ v-if="floatingLabel"
53
+ class="outlined-tree-select__label"
54
+ :class="labelClasses"
55
+ >
56
+ {{ floatingLabel }}
57
+ </div>
58
+ </div>
59
+ </template>
60
+
61
+ <script setup lang="ts">
62
+ import { computed, ref, useAttrs, watch } from 'vue'
63
+ import type {
64
+ OutlinedTreeSelectCssValue,
65
+ OutlinedTreeSelectExpose,
66
+ OutlinedTreeSelectOptionValue,
67
+ OutlinedTreeSelectProps,
68
+ OutlinedTreeSelectValue
69
+ } from './OutlinedTreeSelect.types'
70
+
71
+ defineOptions({
72
+ name: 'OutlinedTreeSelect',
73
+ inheritAttrs: false
74
+ })
75
+
76
+ const props = withDefaults(defineProps<OutlinedTreeSelectProps>(), {
77
+ value: undefined,
78
+ data: () => [],
79
+ propsValue: undefined,
80
+ placeholder: '',
81
+ label: '',
82
+ disabled: false,
83
+ clearable: true,
84
+ filterable: true,
85
+ multiple: false,
86
+ showCheckbox: false,
87
+ checkStrictly: false,
88
+ checkOnClickNode: false,
89
+ defaultExpandAll: false,
90
+ expandOnClickNode: false,
91
+ renderAfterExpand: false,
92
+ collapseTags: false,
93
+ collapseTagsTooltip: true,
94
+ maxCollapseTags: 5,
95
+ popperClass: '',
96
+ nodeKey: 'value',
97
+ keyValue: 'value',
98
+ labelValue: 'label',
99
+ childrenValue: 'children',
100
+ disabledValue: 'disabled',
101
+ inputHeight: 40,
102
+ isBorder: false,
103
+ marginBottom: 20,
104
+ paddingTop: 20
105
+ })
106
+
107
+ const emit = defineEmits<{
108
+ (event: 'input', value: OutlinedTreeSelectValue | ''): void
109
+ (event: 'update:value', value: OutlinedTreeSelectValue | ''): void
110
+ (event: 'change', value: OutlinedTreeSelectValue | ''): void
111
+ (event: 'focus', value: FocusEvent): void
112
+ (event: 'blur', value: FocusEvent): void
113
+ (event: 'visible-change', value: boolean): void
114
+ (event: 'clear'): void
115
+ }>()
116
+
117
+ const attrs = useAttrs()
118
+ const treeSelectRef = ref<any>(null)
119
+ const treeSelectValue = ref<OutlinedTreeSelectValue | ''>(normalizeTreeSelectValue(props.value, isArrayMode()))
120
+ const focused = ref(false)
121
+ const blurred = ref(false)
122
+ const visible = ref(false)
123
+
124
+ watch(
125
+ () => [props.value, props.multiple, props.showCheckbox] as const,
126
+ ([value]) => {
127
+ treeSelectValue.value = normalizeTreeSelectValue(value, isArrayMode())
128
+ },
129
+ { immediate: true }
130
+ )
131
+
132
+ const rootClass = computed(() => attrs.class)
133
+ const rootStyle = computed(() => attrs.style)
134
+
135
+ const treeSelectAttrs = computed(() => {
136
+ const { class: _class, style: _style, ...rest } = attrs
137
+ return rest
138
+ })
139
+
140
+ const containerClasses = computed(() => ({
141
+ 'outlined-tree-select--bordered': props.isBorder
142
+ }))
143
+
144
+ const containerStyle = computed(() => ({
145
+ marginBottom: toCssValue(props.marginBottom),
146
+ paddingTop: toCssValue(props.paddingTop)
147
+ }))
148
+
149
+ const treeSelectStyle = computed(() => ({
150
+ minHeight: `${props.inputHeight}px`,
151
+ height: isArrayMode() ? 'auto' : `${props.inputHeight}px`
152
+ }))
153
+
154
+ const resolvedTreeProps = computed(() => {
155
+ if (props.propsValue) {
156
+ return props.propsValue
157
+ }
158
+
159
+ return {
160
+ value: props.keyValue,
161
+ label: props.labelValue,
162
+ children: props.childrenValue,
163
+ disabled: props.disabledValue
164
+ }
165
+ })
166
+
167
+ const floatingLabel = computed(() => props.label || props.placeholder || '')
168
+
169
+ const hasContent = computed(() => {
170
+ if (isArrayMode()) {
171
+ return Array.isArray(treeSelectValue.value) && treeSelectValue.value.length > 0
172
+ }
173
+
174
+ return hasFilledValue(treeSelectValue.value)
175
+ })
176
+
177
+ const labelClasses = computed(() => ({
178
+ 'outlined-tree-select__label--floating': focused.value || hasContent.value,
179
+ 'outlined-tree-select__label--placeholder': !focused.value && !hasContent.value,
180
+ 'outlined-tree-select__label--filled': hasContent.value && !focused.value
181
+ }))
182
+
183
+ function isArrayMode() {
184
+ return props.multiple || props.showCheckbox
185
+ }
186
+
187
+ function handleModelValueUpdate(value: OutlinedTreeSelectValue) {
188
+ const normalizedValue = normalizeTreeSelectValue(value, isArrayMode())
189
+ treeSelectValue.value = normalizedValue
190
+ emitModelValue(normalizedValue)
191
+ }
192
+
193
+ function handleChange(value: OutlinedTreeSelectValue) {
194
+ const normalizedValue = normalizeTreeSelectValue(value, isArrayMode())
195
+ treeSelectValue.value = normalizedValue
196
+ emit('change', normalizedValue)
197
+ }
198
+
199
+ function handleFocus(event: FocusEvent) {
200
+ blurred.value = false
201
+ focused.value = true
202
+ emit('focus', event)
203
+ }
204
+
205
+ function handleBlur(event: FocusEvent) {
206
+ blurred.value = true
207
+
208
+ if (!visible.value) {
209
+ focused.value = false
210
+ emitModelValue(treeSelectValue.value)
211
+ }
212
+
213
+ emit('blur', event)
214
+ }
215
+
216
+ function handleVisibleChange(nextVisible: boolean) {
217
+ visible.value = nextVisible
218
+
219
+ if (!nextVisible && blurred.value) {
220
+ focused.value = false
221
+ }
222
+
223
+ emit('visible-change', nextVisible)
224
+ }
225
+
226
+ function handleClear() {
227
+ emit('clear')
228
+ }
229
+
230
+ function emitModelValue(value: OutlinedTreeSelectValue | '') {
231
+ emit('input', value)
232
+ emit('update:value', value)
233
+ }
234
+
235
+ function normalizeTreeSelectValue(
236
+ value: OutlinedTreeSelectValue | undefined,
237
+ arrayMode: boolean
238
+ ): OutlinedTreeSelectValue | '' {
239
+ if (arrayMode) {
240
+ if (Array.isArray(value)) {
241
+ return value
242
+ }
243
+
244
+ if (value === undefined || value === null || value === '') {
245
+ return []
246
+ }
247
+
248
+ return [value as OutlinedTreeSelectOptionValue]
249
+ }
250
+
251
+ return value ?? ''
252
+ }
253
+
254
+ function hasFilledValue(value: unknown) {
255
+ return value !== undefined && value !== null && String(value) !== ''
256
+ }
257
+
258
+ function toCssValue(value: OutlinedTreeSelectCssValue | undefined) {
259
+ if (typeof value === 'number') {
260
+ return `${value}px`
261
+ }
262
+
263
+ return value
264
+ }
265
+
266
+ defineExpose<OutlinedTreeSelectExpose>({
267
+ focus: () => {
268
+ treeSelectRef.value?.focus?.()
269
+ },
270
+ blur: () => {
271
+ treeSelectRef.value?.blur?.()
272
+ },
273
+ clear: () => {
274
+ if (isArrayMode()) {
275
+ treeSelectValue.value = []
276
+ emitModelValue([])
277
+ emit('change', [])
278
+ emit('clear')
279
+ return
280
+ }
281
+
282
+ treeSelectValue.value = ''
283
+ emitModelValue('')
284
+ emit('change', '')
285
+ emit('clear')
286
+ },
287
+ getTreeSelectRef: () => treeSelectRef.value
288
+ })
289
+ </script>
290
+
291
+ <style scoped>
292
+ .outlined-tree-select {
293
+ position: relative;
294
+ }
295
+
296
+ .outlined-tree-select__label {
297
+ position: absolute;
298
+ left: -2px;
299
+ padding: 2px 5px;
300
+ border-radius: 2px;
301
+ background-color: #ffffff;
302
+ font-size: 12px;
303
+ line-height: 1;
304
+ transition: color 200ms cubic-bezier(0, 0, 0.2, 1), transform 200ms cubic-bezier(0, 0, 0.2, 1);
305
+ pointer-events: none;
306
+ }
307
+
308
+ .outlined-tree-select__label--floating {
309
+ top: 18px;
310
+ z-index: 1;
311
+ opacity: 1;
312
+ transform: translate(14px, -6px) scale(1);
313
+ color: var(--el-color-primary);
314
+ }
315
+
316
+ .outlined-tree-select__label--placeholder {
317
+ top: 50%;
318
+ left: 1px;
319
+ z-index: -1;
320
+ opacity: 0;
321
+ transform: translate(14px, 6px) scale(1);
322
+ }
323
+
324
+ .outlined-tree-select__label--filled {
325
+ color: var(--el-text-color-regular);
326
+ }
327
+
328
+ :deep(.outlined-tree-select__control.el-select) {
329
+ width: 100%;
330
+ }
331
+
332
+ :deep(.outlined-tree-select__control .el-select__wrapper) {
333
+ min-height: inherit;
334
+ height: inherit;
335
+ }
336
+
337
+ :deep(.outlined-tree-select__control .el-select__selection) {
338
+ min-height: inherit;
339
+ }
340
+
341
+ :deep(.outlined-tree-select__control .el-select__tags) {
342
+ padding-top: 4px;
343
+ }
344
+
345
+ :deep(.outlined-tree-select--bordered .el-select__wrapper) {
346
+ box-shadow: none;
347
+ border-radius: 0;
348
+ border-bottom: 1px solid #cccccc;
349
+ }
350
+
351
+ :deep(.outlined-tree-select--bordered .el-select__wrapper.is-focused) {
352
+ border-bottom-color: var(--el-color-primary);
353
+ }
354
+ </style>
@@ -0,0 +1,107 @@
1
+ # OutlinedTreeSelect
2
+
3
+ `OutlinedTreeSelect` 是 `OutlinedForm` 系列里的树形下拉选择控件,用来统一封装浮动标签、树节点字段映射、树面板显隐和常用树选择参数。
4
+
5
+ ## 适用场景
6
+
7
+ - 页面里需要在下拉框中选择组织树、区域树、节点树
8
+ - 需要统一 `el-tree-select` 的浮动标签样式
9
+ - 需要兼容自定义节点字段,比如 `id`、`name`、`children`
10
+ - 需要直接在页面层调用聚焦、清空等实例方法
11
+
12
+ ## 基本用法
13
+
14
+ ```vue
15
+ <script setup lang="ts">
16
+ import { ref } from 'vue'
17
+ import { OutlinedTreeSelect, type OutlinedTreeSelectExpose } from '@hbdlzy/ui'
18
+
19
+ const treeSelectRef = ref<OutlinedTreeSelectExpose | null>(null)
20
+ const parentId = ref('')
21
+
22
+ const treeData = [
23
+ {
24
+ id: 'north',
25
+ name: '华北',
26
+ children: [
27
+ { id: 'beijing', name: '北京节点' },
28
+ { id: 'tianjin', name: '天津节点' }
29
+ ]
30
+ }
31
+ ]
32
+ </script>
33
+
34
+ <template>
35
+ <OutlinedTreeSelect
36
+ ref="treeSelectRef"
37
+ v-model:value="parentId"
38
+ placeholder="选择父节点"
39
+ :data="treeData"
40
+ :props-value="{ value: 'id', label: 'name', children: 'children' }"
41
+ :check-strictly="true"
42
+ :is-border="true"
43
+ clearable
44
+ filterable
45
+ />
46
+ </template>
47
+ ```
48
+
49
+ ## Props
50
+
51
+ | 属性 | 类型 | 默认值 | 说明 |
52
+ | --- | --- | --- | --- |
53
+ | `value` | `string \| number \| boolean \| object \| Array<...>` | `undefined` | `v-model:value` 绑定值 |
54
+ | `data` | `OutlinedTreeSelectNode[]` | `[]` | 树节点数据 |
55
+ | `propsValue` | `Record<string, unknown>` | `undefined` | 透传给 `el-tree-select` 的 `props` |
56
+ | `placeholder` | `string` | `''` | 占位文案,也会作为浮动标签文案 |
57
+ | `label` | `string` | `''` | 自定义浮动标签文案,优先级高于 `placeholder` |
58
+ | `disabled` | `boolean` | `false` | 是否禁用 |
59
+ | `clearable` | `boolean` | `true` | 是否允许清空 |
60
+ | `filterable` | `boolean` | `true` | 是否允许搜索 |
61
+ | `multiple` | `boolean` | `false` | 是否多选 |
62
+ | `showCheckbox` | `boolean` | `false` | 是否显示树节点勾选框 |
63
+ | `checkStrictly` | `boolean` | `false` | 是否取消父子节点关联 |
64
+ | `checkOnClickNode` | `boolean` | `false` | 是否点击节点内容时选中 |
65
+ | `defaultExpandAll` | `boolean` | `false` | 是否默认展开所有节点 |
66
+ | `expandOnClickNode` | `boolean` | `false` | 是否点击节点展开树 |
67
+ | `renderAfterExpand` | `boolean` | `false` | 是否在展开后再渲染子节点 |
68
+ | `collapseTags` | `boolean` | `false` | 多选时是否折叠 tag |
69
+ | `collapseTagsTooltip` | `boolean` | `true` | 折叠 tag 时是否显示 tooltip |
70
+ | `maxCollapseTags` | `number` | `5` | 最多展示多少个折叠 tag |
71
+ | `popperClass` | `string` | `''` | 自定义弹层类名 |
72
+ | `nodeKey` | `string` | `'value'` | 树节点唯一标识字段 |
73
+ | `keyValue` | `string` | `'value'` | 默认值字段名 |
74
+ | `labelValue` | `string` | `'label'` | 默认标签字段名 |
75
+ | `childrenValue` | `string` | `'children'` | 默认子节点字段名 |
76
+ | `disabledValue` | `string` | `'disabled'` | 默认禁用字段名 |
77
+ | `inputHeight` | `number` | `40` | 输入框高度 |
78
+ | `isBorder` | `boolean` | `false` | 是否启用下边框风格 |
79
+ | `marginBottom` | `string \| number` | `20` | 外层下边距 |
80
+ | `paddingTop` | `string \| number` | `20` | 外层上内边距,用于浮动标签留白 |
81
+
82
+ ## Emits
83
+
84
+ | 事件 | 参数 | 说明 |
85
+ | --- | --- | --- |
86
+ | `input` | `OutlinedTreeSelectValue \| ''` | 输入值变化时触发 |
87
+ | `update:value` | `OutlinedTreeSelectValue \| ''` | `v-model:value` 同步事件 |
88
+ | `change` | `OutlinedTreeSelectValue \| ''` | 选项确认变化时触发 |
89
+ | `focus` | `FocusEvent` | 聚焦时触发 |
90
+ | `blur` | `FocusEvent` | 失焦时触发 |
91
+ | `visible-change` | `boolean` | 面板显隐变化时触发 |
92
+ | `clear` | 无 | 清空时触发 |
93
+
94
+ ## Expose
95
+
96
+ | 方法 | 说明 |
97
+ | --- | --- |
98
+ | `focus()` | 聚焦树选择控件 |
99
+ | `blur()` | 取消聚焦 |
100
+ | `clear()` | 清空当前值 |
101
+ | `getTreeSelectRef()` | 获取内部 `el-tree-select` 实例 |
102
+
103
+ ## 设计约束
104
+
105
+ - 组件只处理通用树选择壳子和交互状态,不直接耦合组织树接口、区域树接口等业务数据源
106
+ - 如果业务已经有固定的树字段协议,优先传 `propsValue`,不要在页面层二次转一份树数据
107
+ - 如果后续要支持领域级树选择行为,比如自动拼接父路径、限定层级,只建议在业务包里再封一层
@@ -0,0 +1,12 @@
1
+ import OutlinedTreeSelect from './OutlinedTreeSelect.vue'
2
+
3
+ export default OutlinedTreeSelect
4
+
5
+ export type {
6
+ OutlinedTreeSelectCssValue,
7
+ OutlinedTreeSelectExpose,
8
+ OutlinedTreeSelectNode,
9
+ OutlinedTreeSelectOptionValue,
10
+ OutlinedTreeSelectProps,
11
+ OutlinedTreeSelectValue
12
+ } from './OutlinedTreeSelect.types'
@@ -0,0 +1,12 @@
1
+ import * as echarts from 'echarts'
2
+
3
+ export type {
4
+ ECharts as EChartInstance,
5
+ EChartsOption as EChartOption,
6
+ InitOpts as EChartInitOptions,
7
+ LoadingOption as EChartLoadingOptions,
8
+ ResizeOpts as EChartResizeOptions,
9
+ SetOptionOpts as EChartSetOptionOptions
10
+ } from 'echarts'
11
+
12
+ export { echarts }
@@ -1,4 +1,5 @@
1
- import * as XLSX from 'xlsx'
1
+ import ExcelJS from 'exceljs'
2
+ import { saveAs } from 'file-saver'
2
3
 
3
4
  export type ExcelCellValue = string | number | boolean | null | undefined | Date
4
5
 
@@ -21,6 +22,12 @@ export interface ExcelExportOptions<Row = Record<string, any>> {
21
22
 
22
23
  const DEFAULT_SHEET_NAME = 'Sheet1'
23
24
  const DEFAULT_COLUMN_WIDTH = 16
25
+ const EXCEL_MIME_TYPE = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
26
+
27
+ interface ExcelMergeRange {
28
+ s: { r: number; c: number }
29
+ e: { r: number; c: number }
30
+ }
24
31
 
25
32
  function getLeafCount<Row>(column: ExcelExportColumn<Row>): number {
26
33
  if (!column.children?.length) {
@@ -74,7 +81,7 @@ function buildHeaderMatrix<Row>(columns: Array<ExcelExportColumn<Row>>) {
74
81
  const maxDepth = getMaxDepth(columns)
75
82
  const totalLeafCount = columns.reduce((count, column) => count + getLeafCount(column), 0)
76
83
  const headerRows = Array.from({ length: maxDepth }, () => Array.from({ length: totalLeafCount }).fill(''))
77
- const merges: XLSX.Range[] = []
84
+ const merges: Array<ExcelMergeRange> = []
78
85
  const leafColumns: Array<ExcelExportColumn<Row>> = []
79
86
 
80
87
  let currentColumnIndex = 0
@@ -133,7 +140,7 @@ function buildColumnWidths<Row>(
133
140
  const targetWidth =
134
141
  column.width ?? (autoWidth ? Math.max(defaultColumnWidth, headerWidth, dataWidth) : defaultColumnWidth)
135
142
 
136
- return { wch: targetWidth }
143
+ return targetWidth
137
144
  })
138
145
  }
139
146
 
@@ -141,7 +148,19 @@ function normalizeFileName(fileName: string) {
141
148
  return fileName.endsWith('.xlsx') ? fileName : `${fileName}.xlsx`
142
149
  }
143
150
 
144
- export function exportExcel<Row = Record<string, any>>(options: ExcelExportOptions<Row>) {
151
+ function applyColumnWidths(worksheet: ExcelJS.Worksheet, columnWidths: Array<number>) {
152
+ columnWidths.forEach((width, index) => {
153
+ worksheet.getColumn(index + 1).width = width
154
+ })
155
+ }
156
+
157
+ function applyMerges(worksheet: ExcelJS.Worksheet, merges: Array<ExcelMergeRange>) {
158
+ merges.forEach(range => {
159
+ worksheet.mergeCells(range.s.r + 1, range.s.c + 1, range.e.r + 1, range.e.c + 1)
160
+ })
161
+ }
162
+
163
+ export async function exportExcel<Row = Record<string, any>>(options: ExcelExportOptions<Row>) {
145
164
  const {
146
165
  fileName,
147
166
  sheetName = DEFAULT_SHEET_NAME,
@@ -157,14 +176,21 @@ export function exportExcel<Row = Record<string, any>>(options: ExcelExportOptio
157
176
 
158
177
  const { headerRows, leafColumns, merges } = buildHeaderMatrix(columns)
159
178
  const dataRows = data.map((row, rowIndex) => leafColumns.map(column => getCellValue(row, rowIndex, column)))
179
+ const columnWidths = buildColumnWidths(leafColumns, dataRows, defaultColumnWidth, autoWidth)
180
+ const workbook = new ExcelJS.Workbook()
181
+ const worksheet = workbook.addWorksheet(sheetName)
182
+
183
+ ;[...headerRows, ...dataRows].forEach(row => {
184
+ worksheet.addRow(row)
185
+ })
186
+
187
+ applyMerges(worksheet, merges)
188
+ applyColumnWidths(worksheet, columnWidths)
160
189
 
161
- const worksheet = XLSX.utils.aoa_to_sheet([...headerRows, ...dataRows])
162
- worksheet['!merges'] = merges
163
- worksheet['!cols'] = buildColumnWidths(leafColumns, dataRows, defaultColumnWidth, autoWidth)
190
+ const buffer = await workbook.xlsx.writeBuffer()
191
+ const blob = new Blob([buffer], { type: EXCEL_MIME_TYPE })
164
192
 
165
- const workbook = XLSX.utils.book_new()
166
- XLSX.utils.book_append_sheet(workbook, worksheet, sheetName)
167
- XLSX.writeFile(workbook, normalizeFileName(fileName))
193
+ saveAs(blob, normalizeFileName(fileName))
168
194
  }
169
195
 
170
196
  export default exportExcel
package/src/index.ts CHANGED
@@ -1,4 +1,33 @@
1
+ export { echarts } from './echarts'
2
+ export type {
3
+ EChartInitOptions,
4
+ EChartInstance,
5
+ EChartLoadingOptions,
6
+ EChartOption,
7
+ EChartResizeOptions,
8
+ EChartSetOptionOptions
9
+ } from './echarts'
10
+ export { default as BaseCard } from './components/BaseCard'
11
+ export * from './components/BaseCard'
12
+ export { default as BaseTable } from './components/BaseTable'
13
+ export * from './components/BaseTable'
14
+ export { default as BaseEChart } from './components/BaseEChart'
15
+ export * from './components/BaseEChart'
1
16
  export { default as BaseExportButton } from './components/BaseExportButton'
2
17
  export * from './components/BaseExportButton'
18
+ export { default as OutlinedInput } from './components/OutlinedInput'
19
+ export * from './components/OutlinedInput'
20
+ export { default as OutlinedSelect } from './components/OutlinedSelect'
21
+ export * from './components/OutlinedSelect'
22
+ export { default as OutlinedDatePicker } from './components/OutlinedDatePicker'
23
+ export * from './components/OutlinedDatePicker'
24
+ export { default as OutlinedDateTimePicker } from './components/OutlinedDateTimePicker'
25
+ export * from './components/OutlinedDateTimePicker'
26
+ export { default as OutlinedTimePicker } from './components/OutlinedTimePicker'
27
+ export * from './components/OutlinedTimePicker'
28
+ export { default as OutlinedCascader } from './components/OutlinedCascader'
29
+ export * from './components/OutlinedCascader'
30
+ export { default as OutlinedTreeSelect } from './components/OutlinedTreeSelect'
31
+ export * from './components/OutlinedTreeSelect'
3
32
  export { exportExcel } from './excel/exportExcel'
4
33
  export type { ExcelCellValue, ExcelExportColumn, ExcelExportOptions } from './excel/exportExcel'