verce-vue-test 0.0.0

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.
@@ -0,0 +1,539 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * ElTablePlus 组件
4
+ * 基于 Element Plus 的增强表格组件,支持列配置、本地存储和分页功能
5
+ */
6
+ import {
7
+ computed,
8
+ ref,
9
+ useAttrs,
10
+ useSlots,
11
+ cloneVNode,
12
+ type VNode,
13
+ } from 'vue'
14
+ import { useRoute } from 'vue-router'
15
+
16
+ // 组件配置选项
17
+ defineOptions({
18
+ name: 'ElTablePlus',
19
+ inheritAttrs: false,
20
+ })
21
+
22
+ /**
23
+ * Props 定义
24
+ */
25
+ const props = withDefaults(
26
+ defineProps<{
27
+ // 表格数据源
28
+ data: any[]
29
+ // 行唯一标识字段
30
+ rowKey?: string
31
+ // 多表格区分 key(用于本地存储)
32
+ tableKey?: string
33
+ // 完全自定义缓存 key,优先级最高
34
+ columnStorageKey?: string
35
+ // 是否开启列配置功能
36
+ columnConfig?: boolean
37
+ // 是否持久化列配置到本地存储
38
+ columnStorage?: boolean
39
+ // 是否显示分页
40
+ pagination?: boolean
41
+ // 总记录数
42
+ total?: number
43
+ // 当前页码
44
+ page?: number
45
+ // 每页条数
46
+ pageSize?: number
47
+ // 可选每页条数列表
48
+ pageSizes?: number[]
49
+ // 分页组件布局
50
+ layout?: string
51
+ }>(),
52
+ {
53
+ columnConfig: true,
54
+ columnStorage: true,
55
+ pagination: true,
56
+ page: 1,
57
+ pageSize: 10,
58
+ pageSizes: () => [10, 20, 50, 100],
59
+ layout: 'total, sizes, prev, pager, next, jumper',
60
+ },
61
+ )
62
+
63
+ /**
64
+ * 事件定义
65
+ */
66
+ const emit = defineEmits<{
67
+ // 更新页码
68
+ 'update:page': [value: number]
69
+ // 更新每页条数
70
+ 'update:pageSize': [value: number]
71
+ // 分页变化
72
+ 'pagination-change': [value: { page: number; pageSize: number }]
73
+ }>()
74
+
75
+ /**
76
+ * 依赖注入
77
+ */
78
+ const route = useRoute()
79
+ const attrs = useAttrs()
80
+ const slots = useSlots()
81
+
82
+ /**
83
+ * 响应式状态
84
+ */
85
+ // 列配置弹窗可见性
86
+ const dialogVisible = ref(false)
87
+
88
+ // 列选项类型定义
89
+ type ColumnOption = {
90
+ key: string // 列唯一标识
91
+ label: string // 列显示名称
92
+ visible: boolean // 是否可见
93
+ vnode: VNode // 列的 VNode 节点
94
+ }
95
+
96
+ // 列选项列表
97
+ const columnOptions = ref<ColumnOption[]>([])
98
+
99
+ // 弹窗中的临时列选项(确认后才应用)
100
+ const pendingColumnOptions = ref<ColumnOption[]>([])
101
+
102
+ /**
103
+ * 计算属性
104
+ */
105
+
106
+ // 本地存储的 key(根据路由路径和表格 key 生成)
107
+ const storageKey = computed(() => {
108
+ // 优先使用自定义的存储 key
109
+ if (props.columnStorageKey) {
110
+ return props.columnStorageKey
111
+ }
112
+ // 如果指定了表格 key,添加到存储 key 中
113
+ if (props.tableKey) {
114
+ return `el-table-plus:${route.path}:${props.tableKey}`
115
+ }
116
+ // 默认使用路由路径作为存储 key
117
+ return `el-table-plus:${route.path}`
118
+ })
119
+
120
+ // 当前页码(双向绑定)
121
+ const currentPage = computed({
122
+ get: () => props.page,
123
+ set: value => {
124
+ emit('update:page', value)
125
+ emit('pagination-change', {
126
+ page: value,
127
+ pageSize: props.pageSize,
128
+ })
129
+ },
130
+ })
131
+
132
+ // 当前每页条数(双向绑定)
133
+ const currentPageSize = computed({
134
+ get: () => props.pageSize,
135
+ set: value => {
136
+ emit('update:pageSize', value)
137
+ emit('pagination-change', {
138
+ page: props.page,
139
+ pageSize: value,
140
+ })
141
+ },
142
+ })
143
+
144
+ // 是否全选(弹窗中的临时状态)
145
+ const isAllSelected = computed({
146
+ get: () => pendingColumnOptions.value.length > 0 && pendingColumnOptions.value.every(col => col.visible),
147
+ set: value => {
148
+ pendingColumnOptions.value.forEach(col => {
149
+ col.visible = value
150
+ })
151
+ },
152
+ })
153
+
154
+ /**
155
+ * 方法定义
156
+ */
157
+
158
+ /**
159
+ * 获取列的唯一标识
160
+ * @param vnode - 列的 VNode 节点
161
+ * @param index - 索引位置
162
+ * @returns 列的唯一标识
163
+ */
164
+ const getColumnKey = (vnode: VNode, index: number) => {
165
+ const columnProps = vnode.props as Record<string, any> | null
166
+
167
+ return (
168
+ columnProps?.columnKey ||
169
+ columnProps?.prop ||
170
+ columnProps?.label ||
171
+ columnProps?.type ||
172
+ `column_${index}`
173
+ )
174
+ }
175
+
176
+ /**
177
+ * 获取列的显示标签
178
+ * @param vnode - 列的 VNode 节点
179
+ * @param index - 索引位置
180
+ * @returns 列的显示标签
181
+ */
182
+ const getColumnLabel = (vnode: VNode, index: number) => {
183
+ const columnProps = vnode.props as Record<string, any> | null
184
+
185
+ return (
186
+ columnProps?.label ||
187
+ columnProps?.prop ||
188
+ columnProps?.type ||
189
+ `列 ${index + 1}`
190
+ )
191
+ }
192
+
193
+ /**
194
+ * 从本地存储恢复列配置
195
+ */
196
+ const restoreColumnConfig = () => {
197
+ // 如果未开启本地存储,直接返回
198
+ if (!props.columnStorage) return
199
+
200
+ // 从 localStorage 获取缓存的列配置
201
+ const cache = localStorage.getItem(storageKey.value)
202
+ if (!cache) return
203
+
204
+ try {
205
+ // 解析缓存数据
206
+ const cacheColumns = JSON.parse(cache) as Array<{
207
+ key: string
208
+ visible: boolean
209
+ }>
210
+
211
+ // 遍历列选项,更新可见性状态
212
+ columnOptions.value.forEach(column => {
213
+ const match = cacheColumns.find(item => item.key === column.key)
214
+ if (match) {
215
+ column.visible = match.visible
216
+ }
217
+ })
218
+ } catch {
219
+ // 解析失败时清除缓存
220
+ localStorage.removeItem(storageKey.value)
221
+ }
222
+ }
223
+
224
+ /**
225
+ * 保存列配置到本地存储
226
+ */
227
+ const saveColumnConfig = () => {
228
+ // 如果未开启本地存储,直接返回
229
+ if (!props.columnStorage) return
230
+
231
+ // 构建需要缓存的数据结构
232
+ const cacheColumns = columnOptions.value.map(column => ({
233
+ key: column.key,
234
+ visible: column.visible,
235
+ }))
236
+
237
+ // 保存到 localStorage
238
+ localStorage.setItem(storageKey.value, JSON.stringify(cacheColumns))
239
+ }
240
+
241
+ /**
242
+ * 打开列配置弹窗
243
+ */
244
+ const openColumnConfigDialog = () => {
245
+ pendingColumnOptions.value = columnOptions.value.map(col => ({ ...col }))
246
+ dialogVisible.value = true
247
+ }
248
+
249
+ /**
250
+ * 确认列配置
251
+ */
252
+ const confirmColumnConfig = () => {
253
+ pendingColumnOptions.value.forEach(pending => {
254
+ const col = columnOptions.value.find(item => item.key === pending.key)
255
+ if (col) {
256
+ col.visible = pending.visible
257
+ }
258
+ })
259
+ saveColumnConfig()
260
+ dialogVisible.value = false
261
+ }
262
+
263
+ /**
264
+ * 取消列配置
265
+ */
266
+ const cancelColumnConfig = () => {
267
+ dialogVisible.value = false
268
+ }
269
+
270
+ /**
271
+ * 初始化列配置
272
+ */
273
+ const initColumns = () => {
274
+ // 获取默认插槽中的子节点(列定义)
275
+ const children = slots.default?.() || []
276
+
277
+ // 转换为列选项列表
278
+ columnOptions.value = children.map((vnode, index) => {
279
+ return {
280
+ key: getColumnKey(vnode, index),
281
+ label: getColumnLabel(vnode, index),
282
+ visible: true,
283
+ vnode,
284
+ }
285
+ })
286
+
287
+ // 从本地存储恢复配置
288
+ restoreColumnConfig()
289
+ }
290
+
291
+ /**
292
+ * 获取可见的列(用于渲染)
293
+ */
294
+ const visibleColumns = computed(() => {
295
+ return columnOptions.value
296
+ .filter(column => column.visible)
297
+ .map(column => cloneVNode(column.vnode))
298
+ })
299
+
300
+ // 初始化列配置
301
+ initColumns()
302
+ </script>
303
+
304
+ <template>
305
+ <div class="el-table-plus">
306
+ <!-- 工具栏 -->
307
+ <div
308
+ v-if="columnConfig"
309
+ class="el-table-plus__toolbar"
310
+ >
311
+ <div class="el-table-plus__toolbar-left">
312
+ <slot name="toolbar" />
313
+ </div>
314
+
315
+ <div class="el-table-plus__toolbar-right">
316
+ <slot name="toolbar-right" />
317
+
318
+ <el-button
319
+ size="small"
320
+ @click="openColumnConfigDialog"
321
+ >
322
+ 列配置
323
+ </el-button>
324
+ </div>
325
+ </div>
326
+
327
+ <!-- 表格主体 -->
328
+ <el-table
329
+ v-bind="attrs"
330
+ :data="data"
331
+ :row-key="rowKey"
332
+ >
333
+ <component
334
+ :is="column"
335
+ v-for="column in visibleColumns"
336
+ :key="column.key"
337
+ />
338
+ </el-table>
339
+
340
+ <!-- 分页组件 -->
341
+ <div
342
+ v-if="pagination"
343
+ class="el-table-plus__pagination"
344
+ >
345
+ <el-pagination
346
+ v-model:current-page="currentPage"
347
+ v-model:page-size="currentPageSize"
348
+ :total="total || data.length"
349
+ :page-sizes="pageSizes"
350
+ :layout="layout"
351
+ background
352
+ />
353
+ </div>
354
+
355
+ <!-- 列配置弹窗 -->
356
+ <el-dialog
357
+ v-model="dialogVisible"
358
+ title="表格列配置"
359
+ width="500px"
360
+ :close-on-click-modal="false"
361
+ >
362
+ <!-- 弹窗提示文字 -->
363
+ <p class="el-table-plus__dialog-tip">
364
+ 请选择需要在表格中显示的数据列
365
+ </p>
366
+
367
+ <!-- 列配置内容 -->
368
+ <div class="el-table-plus__column-config">
369
+ <!-- 全选行 -->
370
+ <div class="el-table-plus__column-select-all">
371
+ <el-checkbox
372
+ v-model="isAllSelected"
373
+ >
374
+ 全选
375
+ </el-checkbox>
376
+ </div>
377
+
378
+ <!-- 分隔线 -->
379
+ <div class="el-table-plus__column-divider"></div>
380
+
381
+ <!-- 列选项网格 -->
382
+ <div class="el-table-plus__column-grid">
383
+ <div
384
+ v-for="column in pendingColumnOptions"
385
+ :key="column.key"
386
+ class="el-table-plus__column-grid-item"
387
+ >
388
+ <el-checkbox
389
+ v-model="column.visible"
390
+ >
391
+ {{ column.label }}
392
+ </el-checkbox>
393
+ </div>
394
+ </div>
395
+ </div>
396
+
397
+ <!-- 弹窗底部按钮 -->
398
+ <template #footer>
399
+ <div class="el-table-plus__dialog-footer">
400
+ <el-button @click="cancelColumnConfig">
401
+ 取消
402
+ </el-button>
403
+
404
+ <el-button
405
+ type="primary"
406
+ @click="confirmColumnConfig"
407
+ >
408
+ 确认
409
+ </el-button>
410
+ </div>
411
+ </template>
412
+ </el-dialog>
413
+ </div>
414
+ </template>
415
+
416
+ <style scoped>
417
+ /**
418
+ * 主容器样式
419
+ */
420
+ .el-table-plus {
421
+ width: 100%;
422
+ }
423
+
424
+ /**
425
+ * 工具栏样式
426
+ */
427
+ .el-table-plus__toolbar {
428
+ display: flex;
429
+ align-items: center;
430
+ justify-content: space-between;
431
+ margin-bottom: 12px;
432
+ }
433
+
434
+ .el-table-plus__toolbar-left,
435
+ .el-table-plus__toolbar-right {
436
+ display: flex;
437
+ align-items: center;
438
+ gap: 8px;
439
+ }
440
+
441
+ /**
442
+ * 分页组件样式
443
+ */
444
+ .el-table-plus__pagination {
445
+ display: flex;
446
+ justify-content: flex-end;
447
+ margin-top: 16px;
448
+ }
449
+
450
+ /**
451
+ * 弹窗提示文字样式
452
+ */
453
+ .el-table-plus__dialog-tip {
454
+ font-size: 14px;
455
+ color: #909399;
456
+ margin-bottom: 16px;
457
+ margin-top: 8px;
458
+ }
459
+
460
+ /**
461
+ * 列配置容器样式
462
+ */
463
+ .el-table-plus__column-config {
464
+ border: 1px solid #EBEEF5;
465
+ border-radius: 4px;
466
+ padding: 12px;
467
+ }
468
+
469
+ /**
470
+ * 全选行样式
471
+ */
472
+ .el-table-plus__column-select-all {
473
+ padding: 8px 0;
474
+ }
475
+
476
+ /**
477
+ * 分隔线样式
478
+ */
479
+ .el-table-plus__column-divider {
480
+ height: 1px;
481
+ background-color: #EBEEF5;
482
+ margin: 8px 0;
483
+ }
484
+
485
+ /**
486
+ * 列选项网格布局样式
487
+ */
488
+ .el-table-plus__column-grid {
489
+ display: grid;
490
+ grid-template-columns: repeat(5, 1fr);
491
+ gap: 8px 0;
492
+ padding: 8px 0;
493
+ }
494
+
495
+ /**
496
+ * 网格项样式
497
+ */
498
+ .el-table-plus__column-grid-item {
499
+ display: flex;
500
+ align-items: center;
501
+ }
502
+
503
+ /**
504
+ * 弹窗底部按钮容器样式
505
+ */
506
+ .el-table-plus__dialog-footer {
507
+ display: flex;
508
+ justify-content: flex-end;
509
+ gap: 12px;
510
+ }
511
+
512
+ /**
513
+ * 弹窗底部取消按钮样式
514
+ */
515
+ .el-table-plus__dialog-footer .el-button:first-child {
516
+ background-color: #F5F7FA;
517
+ color: #606266;
518
+ border-color: #D9D9D9;
519
+ }
520
+
521
+ .el-table-plus__dialog-footer .el-button:first-child:hover {
522
+ background-color: #E4E7ED;
523
+ border-color: #C0C4CC;
524
+ }
525
+
526
+ /**
527
+ * 弹窗底部确认按钮样式
528
+ */
529
+ .el-table-plus__dialog-footer .el-button--primary {
530
+ background-color: #1890FF;
531
+ border-color: #1890FF;
532
+ color: #FFFFFF;
533
+ }
534
+
535
+ .el-table-plus__dialog-footer .el-button--primary:hover {
536
+ background-color: #40A9FF;
537
+ border-color: #40A9FF;
538
+ }
539
+ </style>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
3
+ <path
4
+ d="M15 4a1 1 0 1 0 0 2V4zm0 11v-1a1 1 0 0 0-1 1h1zm0 4l-.707.707A1 1 0 0 0 16 19h-1zm-4-4l.707-.707A1 1 0 0 0 11 14v1zm-4.707-1.293a1 1 0 0 0-1.414 1.414l1.414-1.414zm-.707.707l-.707-.707.707.707zM9 11v-1a1 1 0 0 0-.707.293L9 11zm-4 0h1a1 1 0 0 0-1-1v1zm0 4H4a1 1 0 0 0 1.707.707L5 15zm10-9h2V4h-2v2zm2 0a1 1 0 0 1 1 1h2a3 3 0 0 0-3-3v2zm1 1v6h2V7h-2zm0 6a1 1 0 0 1-1 1v2a3 3 0 0 0 3-3h-2zm-1 1h-2v2h2v-2zm-3 1v4h2v-4h-2zm1.707 3.293l-4-4-1.414 1.414 4 4 1.414-1.414zM11 14H7v2h4v-2zm-4 0c-.276 0-.525-.111-.707-.293l-1.414 1.414C5.42 15.663 6.172 16 7 16v-2zm-.707 1.121l3.414-3.414-1.414-1.414-3.414 3.414 1.414 1.414zM9 12h4v-2H9v2zm4 0a3 3 0 0 0 3-3h-2a1 1 0 0 1-1 1v2zm3-3V3h-2v6h2zm0-6a3 3 0 0 0-3-3v2a1 1 0 0 1 1 1h2zm-3-3H3v2h10V0zM3 0a3 3 0 0 0-3 3h2a1 1 0 0 1 1-1V0zM0 3v6h2V3H0zm0 6a3 3 0 0 0 3 3v-2a1 1 0 0 1-1-1H0zm3 3h2v-2H3v2zm1-1v4h2v-4H4zm1.707 4.707l.586-.586-1.414-1.414-.586.586 1.414 1.414z"
5
+ />
6
+ </svg>
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" fill="currentColor">
3
+ <path
4
+ d="M11 2.253a1 1 0 1 0-2 0h2zm-2 13a1 1 0 1 0 2 0H9zm.447-12.167a1 1 0 1 0 1.107-1.666L9.447 3.086zM1 2.253L.447 1.42A1 1 0 0 0 0 2.253h1zm0 13H0a1 1 0 0 0 1.553.833L1 15.253zm8.447.833a1 1 0 1 0 1.107-1.666l-1.107 1.666zm0-14.666a1 1 0 1 0 1.107 1.666L9.447 1.42zM19 2.253h1a1 1 0 0 0-.447-.833L19 2.253zm0 13l-.553.833A1 1 0 0 0 20 15.253h-1zm-9.553-.833a1 1 0 1 0 1.107 1.666L9.447 14.42zM9 2.253v13h2v-13H9zm1.553-.833C9.203.523 7.42 0 5.5 0v2c1.572 0 2.961.431 3.947 1.086l1.107-1.666zM5.5 0C3.58 0 1.797.523.447 1.42l1.107 1.666C2.539 2.431 3.928 2 5.5 2V0zM0 2.253v13h2v-13H0zm1.553 13.833C2.539 15.431 3.928 15 5.5 15v-2c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM5.5 15c1.572 0 2.961.431 3.947 1.086l1.107-1.666C9.203 13.523 7.42 13 5.5 13v2zm5.053-11.914C11.539 2.431 12.928 2 14.5 2V0c-1.92 0-3.703.523-5.053 1.42l1.107 1.666zM14.5 2c1.573 0 2.961.431 3.947 1.086l1.107-1.666C18.203.523 16.421 0 14.5 0v2zm3.5.253v13h2v-13h-2zm1.553 12.167C18.203 13.523 16.421 13 14.5 13v2c1.573 0 2.961.431 3.947 1.086l1.107-1.666zM14.5 13c-1.92 0-3.703.523-5.053 1.42l1.107 1.666C11.539 15.431 12.928 15 14.5 15v-2z"
5
+ />
6
+ </svg>
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" fill="currentColor">
3
+ <path
4
+ d="M11.447 8.894a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm0 1.789a1 1 0 1 0 .894-1.789l-.894 1.789zM7.447 7.106a1 1 0 1 0-.894 1.789l.894-1.789zM10 9a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0H8zm9.447-5.606a1 1 0 1 0-.894-1.789l.894 1.789zm-2.894-.789a1 1 0 1 0 .894 1.789l-.894-1.789zm2 .789a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zM18 5a1 1 0 1 0-2 0h2zm-2 2.5a1 1 0 1 0 2 0h-2zm-5.447-4.606a1 1 0 1 0 .894-1.789l-.894 1.789zM9 1l.447-.894a1 1 0 0 0-.894 0L9 1zm-2.447.106a1 1 0 1 0 .894 1.789l-.894-1.789zm-6 3a1 1 0 1 0 .894 1.789L.553 4.106zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zm-2-.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 2.789a1 1 0 1 0 .894-1.789l-.894 1.789zM2 5a1 1 0 1 0-2 0h2zM0 7.5a1 1 0 1 0 2 0H0zm8.553 12.394a1 1 0 1 0 .894-1.789l-.894 1.789zm-1.106-2.789a1 1 0 1 0-.894 1.789l.894-1.789zm1.106 1a1 1 0 1 0 .894 1.789l-.894-1.789zm2.894.789a1 1 0 1 0-.894-1.789l.894 1.789zM8 19a1 1 0 1 0 2 0H8zm2-2.5a1 1 0 1 0-2 0h2zm-7.447.394a1 1 0 1 0 .894-1.789l-.894 1.789zM1 15H0a1 1 0 0 0 .553.894L1 15zm1-2.5a1 1 0 1 0-2 0h2zm12.553 2.606a1 1 0 1 0 .894 1.789l-.894-1.789zM17 15l.447.894A1 1 0 0 0 18 15h-1zm1-2.5a1 1 0 1 0-2 0h2zm-7.447-5.394l-2 1 .894 1.789 2-1-.894-1.789zm-1.106 1l-2-1-.894 1.789 2 1 .894-1.789zM8 9v2.5h2V9H8zm8.553-4.894l-2 1 .894 1.789 2-1-.894-1.789zm.894 0l-2-1-.894 1.789 2 1 .894-1.789zM16 5v2.5h2V5h-2zm-4.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zm-2.894-1l-2 1 .894 1.789 2-1L8.553.106zM1.447 5.894l2-1-.894-1.789-2 1 .894 1.789zm-.894 0l2 1 .894-1.789-2-1-.894 1.789zM0 5v2.5h2V5H0zm9.447 13.106l-2-1-.894 1.789 2 1 .894-1.789zm0 1.789l2-1-.894-1.789-2 1 .894 1.789zM10 19v-2.5H8V19h2zm-6.553-3.894l-2-1-.894 1.789 2 1 .894-1.789zM2 15v-2.5H0V15h2zm13.447 1.894l2-1-.894-1.789-2 1 .894 1.789zM18 15v-2.5h-2V15h2z"
5
+ />
6
+ </svg>
7
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor">
3
+ <path
4
+ d="M10 3.22l-.61-.6a5.5 5.5 0 0 0-7.666.105 5.5 5.5 0 0 0-.114 7.665L10 18.78l8.39-8.4a5.5 5.5 0 0 0-.114-7.665 5.5 5.5 0 0 0-7.666-.105l-.61.61z"
5
+ />
6
+ </svg>
7
+ </template>
@@ -0,0 +1,19 @@
1
+ <!-- This icon is from <https://github.com/Templarian/MaterialDesign>, distributed under Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) license-->
2
+ <template>
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ xmlns:xlink="http://www.w3.org/1999/xlink"
6
+ aria-hidden="true"
7
+ role="img"
8
+ class="iconify iconify--mdi"
9
+ width="24"
10
+ height="24"
11
+ preserveAspectRatio="xMidYMid meet"
12
+ viewBox="0 0 24 24"
13
+ >
14
+ <path
15
+ d="M20 18v-4h-3v1h-2v-1H9v1H7v-1H4v4h16M6.33 8l-1.74 4H7v-1h2v1h6v-1h2v1h2.41l-1.74-4H6.33M9 5v1h6V5H9m12.84 7.61c.1.22.16.48.16.8V18c0 .53-.21 1-.6 1.41c-.4.4-.85.59-1.4.59H4c-.55 0-1-.19-1.4-.59C2.21 19 2 18.53 2 18v-4.59c0-.32.06-.58.16-.8L4.5 7.22C4.84 6.41 5.45 6 6.33 6H7V5c0-.55.18-1 .57-1.41C7.96 3.2 8.44 3 9 3h6c.56 0 1.04.2 1.43.59c.39.41.57.86.57 1.41v1h.67c.88 0 1.49.41 1.83 1.22l2.34 5.39z"
16
+ fill="currentColor"
17
+ ></path>
18
+ </svg>
19
+ </template>
package/src/main.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { createApp } from 'vue'
2
+ import { createPinia } from 'pinia'
3
+ import ElementPlus from 'element-plus'
4
+ import 'element-plus/dist/index.css'
5
+
6
+ import App from './App.vue'
7
+ import router from './router'
8
+
9
+ const app = createApp(App)
10
+
11
+ app.use(createPinia())
12
+ app.use(router)
13
+ app.use(ElementPlus)
14
+
15
+ app.mount('#app')
@@ -0,0 +1,40 @@
1
+ import { createRouter, createWebHistory } from 'vue-router'
2
+ import HomeView from '../views/HomeView.vue'
3
+
4
+ const router = createRouter({
5
+ history: createWebHistory(import.meta.env.BASE_URL),
6
+ routes: [
7
+ {
8
+ path: '/',
9
+ name: 'home',
10
+ component: HomeView,
11
+ },
12
+ {
13
+ path: '/about',
14
+ name: 'about',
15
+ component: () => import('../views/AboutView.vue'),
16
+ },
17
+ {
18
+ path: '/dashboard',
19
+ name: 'dashboard',
20
+ component: () => import('../views/DashboardView.vue'),
21
+ },
22
+ {
23
+ path: '/users',
24
+ name: 'users',
25
+ component: () => import('../views/UserView.vue'),
26
+ },
27
+ {
28
+ path: '/form',
29
+ name: 'form',
30
+ component: () => import('../views/FormView.vue'),
31
+ },
32
+ {
33
+ path: '/table-pro',
34
+ name: 'tablePro',
35
+ component: () => import('../views/TableProView.vue'),
36
+ },
37
+ ],
38
+ })
39
+
40
+ export default router
@@ -0,0 +1,12 @@
1
+ import { ref, computed } from 'vue'
2
+ import { defineStore } from 'pinia'
3
+
4
+ export const useCounterStore = defineStore('counter', () => {
5
+ const count = ref(0)
6
+ const doubleCount = computed(() => count.value * 2)
7
+ function increment() {
8
+ count.value++
9
+ }
10
+
11
+ return { count, doubleCount, increment }
12
+ })
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <el-card>
3
+ <el-text tag="h1" size="large">This is an about page</el-text>
4
+ </el-card>
5
+ </template>