Skip to content

Commit 2cf384d

Browse files
committed
Vue3 重构:地区接入 TableV2 高性能表格
1 parent c56a887 commit 2cf384d

File tree

4 files changed

+114
-17
lines changed

4 files changed

+114
-17
lines changed

src/api/system/area/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ export const getAreaTree = async () => {
66
}
77

88
// 获得 IP 对应的地区名
9-
export const getDeptApi = async (ip: string) => {
9+
export const getAreaByIp = async (ip: string) => {
1010
return await request.get({ url: '/system/area/get-by-ip?ip=' + ip })
1111
}

src/types/auto-components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ declare module '@vue/runtime-core' {
7373
ElSwitch: typeof import('element-plus/es')['ElSwitch']
7474
ElTable: typeof import('element-plus/es')['ElTable']
7575
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
76+
ElTableV2: typeof import('element-plus/es')['ElTableV2']
7677
ElTabPane: typeof import('element-plus/es')['ElTabPane']
7778
ElTabs: typeof import('element-plus/es')['ElTabs']
7879
ElTag: typeof import('element-plus/es')['ElTag']

src/views/system/area/form.vue

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<template>
2+
<Dialog title="IP 查询" v-model="modelVisible">
3+
<el-form
4+
ref="formRef"
5+
:model="formData"
6+
:rules="formRules"
7+
label-width="80px"
8+
v-loading="formLoading"
9+
>
10+
<el-form-item label="IP" prop="ip">
11+
<el-input v-model="formData.ip" placeholder="请输入 IP 地址" />
12+
</el-form-item>
13+
<el-form-item label="地址" prop="result">
14+
<el-input v-model="formData.result" readonly placeholder="展示查询 IP 结果" />
15+
</el-form-item>
16+
</el-form>
17+
<template #footer>
18+
<div class="dialog-footer">
19+
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
20+
<el-button @click="modelVisible = false">取 消</el-button>
21+
</div>
22+
</template>
23+
</Dialog>
24+
</template>
25+
<script setup lang="ts">
26+
import * as AreaApi from '@/api/system/area'
27+
const message = useMessage() // 消息弹窗
28+
29+
const modelVisible = ref(false) // 弹窗的是否展示
30+
const formLoading = ref(false) // 表单的加载中:提交的按钮禁用
31+
const formData = ref({
32+
ip: '',
33+
result: undefined
34+
})
35+
const formRules = reactive({
36+
ip: [{ required: true, message: 'IP 地址不能为空', trigger: 'blur' }]
37+
})
38+
const formRef = ref() // 表单 Ref
39+
40+
/** 打开弹窗 */
41+
const openModal = async () => {
42+
modelVisible.value = true
43+
resetForm()
44+
}
45+
defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
46+
47+
/** 提交表单 */
48+
const submitForm = async () => {
49+
// 校验表单
50+
if (!formRef) return
51+
const valid = await formRef.value.validate()
52+
if (!valid) return
53+
// 提交请求
54+
formLoading.value = true
55+
try {
56+
formData.value.result = await AreaApi.getAreaByIp(formData.value.ip!.trim())
57+
message.success('查询成功')
58+
} finally {
59+
formLoading.value = false
60+
}
61+
}
62+
63+
/** 重置表单 */
64+
const resetForm = () => {
65+
formData.value = {
66+
ip: '',
67+
result: undefined
68+
}
69+
formRef.value?.resetFields()
70+
}
71+
</script>

src/views/system/area/index.vue

Lines changed: 41 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,71 @@
11
<template>
2-
<ContentWrap>
3-
<div style="width: 100%; height: 500px">
2+
<!-- 操作栏 -->
3+
<content-wrap>
4+
<el-button type="primary" @click="openModal()">
5+
<Icon icon="ep:plus" class="mr-5px" /> IP 查询
6+
</el-button>
7+
</content-wrap>
8+
9+
<!-- 列表 -->
10+
<content-wrap>
11+
<div style="width: 100%; height: 700px">
12+
<!-- AutoResizer 自动调节大小 -->
413
<el-auto-resizer>
514
<template #default="{ height, width }">
15+
<!-- Virtualized Table 虚拟化表格:高性能,解决表格在大数据量下的卡顿问题 -->
616
<el-table-v2
717
:columns="columns"
8-
:data="tableData"
18+
:data="list"
919
:width="width"
1020
:height="height"
11-
fixed
1221
expand-column-key="id"
1322
/>
1423
</template>
1524
</el-auto-resizer>
1625
</div>
17-
</ContentWrap>
26+
</content-wrap>
27+
28+
<!-- 表单弹窗:添加/修改 -->
29+
<area-form ref="modalRef" />
1830
</template>
19-
<script setup lang="tsx">
20-
import { Column, ElTableV2 } from 'element-plus'
31+
<script setup lang="tsx" name="Area">
32+
import type { Column } from 'element-plus'
33+
import AreaForm from './form.vue'
2134
import * as AreaApi from '@/api/system/area'
2235
36+
// 表格的 column 字段
2337
const columns: Column[] = [
2438
{
25-
key: 'id',
26-
dataKey: 'id', // 需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
39+
dataKey: 'id', // 需要渲染当前列的数据字段。例如说:{id:9527, name:'Mike'},则填 id
2740
title: '编号', // 显示在单元格表头的文本
28-
width: 200, // 当前列的宽度,必须设置
29-
fixed: true // 是否固定列
41+
width: 400, // 当前列的宽度,必须设置
42+
fixed: true, // 是否固定列
43+
key: 'id' // 树形展开对应的 key
3044
},
3145
{
32-
key: 'name',
3346
dataKey: 'name',
3447
title: '地名',
3548
width: 200
3649
}
3750
]
51+
// 表格的数据
52+
const list = ref([])
3853
39-
const tableData = ref([])
40-
54+
/**
55+
* 获得数据列表
56+
*/
4157
const getList = async () => {
42-
tableData.value = await AreaApi.getAreaTree()
58+
list.value = await AreaApi.getAreaTree()
59+
}
60+
61+
/** 添加/修改操作 */
62+
const modalRef = ref()
63+
const openModal = () => {
64+
modalRef.value.openModal()
4365
}
4466
45-
getList()
67+
/** 初始化 **/
68+
onMounted(() => {
69+
getList()
70+
})
4671
</script>

0 commit comments

Comments
 (0)