mirror of
https://gitee.com/myxzgzs/boyue-ui-admin-vue3
synced 2025-08-09 17:02:43 +08:00
【代码优化】系统菜单管理使用虚拟列表优化加载速度
This commit is contained in:
parent
c50f59d181
commit
5832fd687f
@ -67,87 +67,159 @@
|
|||||||
|
|
||||||
<!-- 列表 -->
|
<!-- 列表 -->
|
||||||
<ContentWrap>
|
<ContentWrap>
|
||||||
<el-table
|
<el-auto-resizer>
|
||||||
v-if="refreshTable"
|
<template #default="{ width }">
|
||||||
v-loading="loading"
|
<el-table-v2
|
||||||
|
v-model:expanded-row-keys="expandedRowKeys"
|
||||||
|
:columns="columns"
|
||||||
:data="list"
|
:data="list"
|
||||||
:default-expand-all="isExpandAll"
|
:expand-column-key="columns[0].key"
|
||||||
|
:height="1000"
|
||||||
|
:width="width"
|
||||||
|
fixed
|
||||||
row-key="id"
|
row-key="id"
|
||||||
>
|
|
||||||
<el-table-column :show-overflow-tooltip="true" label="菜单名称" prop="name" width="250" />
|
|
||||||
<el-table-column align="center" label="图标" prop="icon" width="100">
|
|
||||||
<template #default="scope">
|
|
||||||
<Icon :icon="scope.row.icon" />
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="排序" prop="sort" width="60" />
|
|
||||||
<el-table-column :show-overflow-tooltip="true" label="权限标识" prop="permission" />
|
|
||||||
<el-table-column :show-overflow-tooltip="true" label="组件路径" prop="component" />
|
|
||||||
<el-table-column :show-overflow-tooltip="true" label="组件名称" prop="componentName" />
|
|
||||||
<el-table-column label="状态" prop="status">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-switch
|
|
||||||
class="ml-4px"
|
|
||||||
v-model="scope.row.status"
|
|
||||||
v-hasPermi="['system:menu:update']"
|
|
||||||
:active-value="CommonStatusEnum.ENABLE"
|
|
||||||
:inactive-value="CommonStatusEnum.DISABLE"
|
|
||||||
:loading="menuStatusUpdating[scope.row.id]"
|
|
||||||
@change="(val) => handleStatusChanged(scope.row, val as number)"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-auto-resizer>
|
||||||
<el-table-column align="center" label="操作">
|
|
||||||
<template #default="scope">
|
|
||||||
<el-button
|
|
||||||
v-hasPermi="['system:menu:update']"
|
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
@click="openForm('update', scope.row.id)"
|
|
||||||
>
|
|
||||||
修改
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-hasPermi="['system:menu:create']"
|
|
||||||
link
|
|
||||||
type="primary"
|
|
||||||
@click="openForm('create', undefined, scope.row.id)"
|
|
||||||
>
|
|
||||||
新增
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-hasPermi="['system:menu:delete']"
|
|
||||||
link
|
|
||||||
type="danger"
|
|
||||||
@click="handleDelete(scope.row.id)"
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</ContentWrap>
|
</ContentWrap>
|
||||||
|
|
||||||
<!-- 表单弹窗:添加/修改 -->
|
<!-- 表单弹窗:添加/修改 -->
|
||||||
<MenuForm ref="formRef" @success="getList" />
|
<MenuForm ref="formRef" @success="getList" />
|
||||||
</template>
|
</template>
|
||||||
<script lang="ts" setup>
|
<script lang="tsx" setup>
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
import { handleTree } from '@/utils/tree'
|
import { handleTree } from '@/utils/tree'
|
||||||
import * as MenuApi from '@/api/system/menu'
|
import * as MenuApi from '@/api/system/menu'
|
||||||
import { MenuVO } from '@/api/system/menu'
|
import { MenuVO } from '@/api/system/menu'
|
||||||
import MenuForm from './MenuForm.vue'
|
import MenuForm from './MenuForm.vue'
|
||||||
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
import DictTag from '@/components/DictTag/src/DictTag.vue'
|
||||||
|
import { Icon } from '@/components/Icon'
|
||||||
|
import { ElButton, TableV2FixedDir } from 'element-plus'
|
||||||
|
import { checkPermi } from '@/utils/permission'
|
||||||
import { CommonStatusEnum } from '@/utils/constants'
|
import { CommonStatusEnum } from '@/utils/constants'
|
||||||
|
import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
|
||||||
|
|
||||||
defineOptions({ name: 'SystemMenu' })
|
defineOptions({ name: 'SystemMenu' })
|
||||||
|
|
||||||
|
// 虚拟列表表格
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
title: '菜单名称',
|
||||||
|
dataKey: 'name',
|
||||||
|
width: 250,
|
||||||
|
fixed: TableV2FixedDir.LEFT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'icon',
|
||||||
|
title: '图标',
|
||||||
|
dataKey: 'icon',
|
||||||
|
width: 100,
|
||||||
|
align: 'center',
|
||||||
|
cellRenderer: ({ cellData: icon }) => <Icon icon={icon} />
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'sort',
|
||||||
|
title: '排序',
|
||||||
|
dataKey: 'sort',
|
||||||
|
width: 60
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'permission',
|
||||||
|
title: '权限标识',
|
||||||
|
dataKey: 'permission',
|
||||||
|
width: 300
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'component',
|
||||||
|
title: '组件路径',
|
||||||
|
dataKey: 'component',
|
||||||
|
width: 500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'componentName',
|
||||||
|
title: '组件名称',
|
||||||
|
dataKey: 'componentName',
|
||||||
|
width: 200
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'status',
|
||||||
|
title: '状态',
|
||||||
|
dataKey: 'status',
|
||||||
|
width: 60,
|
||||||
|
fixed: TableV2FixedDir.RIGHT,
|
||||||
|
cellRenderer: ({ rowData }) => {
|
||||||
|
// 检查权限
|
||||||
|
if (!checkPermi(['system:menu:update'])) {
|
||||||
|
return <DictTag type={DICT_TYPE.COMMON_STATUS} value={rowData.status} />
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有权限,渲染 ElSwitch
|
||||||
|
return (
|
||||||
|
<ElSwitch
|
||||||
|
v-model={rowData.status}
|
||||||
|
active-value={CommonStatusEnum.ENABLE}
|
||||||
|
inactive-value={CommonStatusEnum.DISABLE}
|
||||||
|
loading={menuStatusUpdating[rowData.id]}
|
||||||
|
class="ml-4px"
|
||||||
|
onChange={(val) => handleStatusChanged(rowData, val)}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'operations',
|
||||||
|
title: '操作',
|
||||||
|
align: 'center',
|
||||||
|
width: 160,
|
||||||
|
fixed: TableV2FixedDir.RIGHT,
|
||||||
|
cellRenderer: ({ rowData }) => {
|
||||||
|
// 定义按钮列表
|
||||||
|
const buttons = []
|
||||||
|
|
||||||
|
// 检查权限并添加按钮
|
||||||
|
if (checkPermi(['system:menu:update'])) {
|
||||||
|
buttons.push(
|
||||||
|
<ElButton key="edit" link type="primary" onClick={() => openForm('update', rowData.id)}>
|
||||||
|
修改
|
||||||
|
</ElButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (checkPermi(['system:menu:create'])) {
|
||||||
|
buttons.push(
|
||||||
|
<ElButton
|
||||||
|
key="create"
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
onClick={() => openForm('create', undefined, rowData.id)}
|
||||||
|
>
|
||||||
|
新增
|
||||||
|
</ElButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (checkPermi(['system:menu:delete'])) {
|
||||||
|
buttons.push(
|
||||||
|
<ElButton key="delete" link type="danger" onClick={() => handleDelete(rowData.id)}>
|
||||||
|
删除
|
||||||
|
</ElButton>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
// 如果没有权限,返回 null
|
||||||
|
if (buttons.length === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
// 渲染按钮列表
|
||||||
|
return <>{buttons}</>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const { wsCache } = useCache()
|
const { wsCache } = useCache()
|
||||||
const { t } = useI18n() // 国际化
|
const { t } = useI18n() // 国际化
|
||||||
const message = useMessage() // 消息弹窗
|
const message = useMessage() // 消息弹窗
|
||||||
|
|
||||||
const loading = ref(true) // 列表的加载中
|
const loading = ref(true) // 列表的加载中
|
||||||
const list = ref<any>([]) // 列表的数据
|
const list = ref<any[]>([]) // 列表的数据
|
||||||
const queryParams = reactive({
|
const queryParams = reactive({
|
||||||
name: undefined,
|
name: undefined,
|
||||||
status: undefined
|
status: undefined
|
||||||
@ -156,6 +228,9 @@ const queryFormRef = ref() // 搜索的表单
|
|||||||
const isExpandAll = ref(false) // 是否展开,默认全部折叠
|
const isExpandAll = ref(false) // 是否展开,默认全部折叠
|
||||||
const refreshTable = ref(true) // 重新渲染表格状态
|
const refreshTable = ref(true) // 重新渲染表格状态
|
||||||
|
|
||||||
|
// 添加展开行控制
|
||||||
|
const expandedRowKeys = ref<number[]>([])
|
||||||
|
|
||||||
/** 查询列表 */
|
/** 查询列表 */
|
||||||
const getList = async () => {
|
const getList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@ -186,11 +261,14 @@ const openForm = (type: string, id?: number, parentId?: number) => {
|
|||||||
|
|
||||||
/** 展开/折叠操作 */
|
/** 展开/折叠操作 */
|
||||||
const toggleExpandAll = () => {
|
const toggleExpandAll = () => {
|
||||||
refreshTable.value = false
|
if (!isExpandAll.value) {
|
||||||
|
// 展开所有
|
||||||
|
expandedRowKeys.value = list.value.map((item) => item.id)
|
||||||
|
} else {
|
||||||
|
// 折叠所有
|
||||||
|
expandedRowKeys.value = []
|
||||||
|
}
|
||||||
isExpandAll.value = !isExpandAll.value
|
isExpandAll.value = !isExpandAll.value
|
||||||
nextTick(() => {
|
|
||||||
refreshTable.value = true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 刷新菜单缓存按钮操作 */
|
/** 刷新菜单缓存按钮操作 */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user