Files
nanxiisletAdmin/src/views/system/menus/index.vue

167 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="page-container">
<!-- 操作栏 -->
<a-card class="table-card" :bordered="false">
<template #title>
<a-button type="primary" @click="handleAdd()">
<PlusOutlined /> 新增菜单
</a-button>
</template>
<!-- 表格树形 -->
<a-table
:columns="columns"
:data-source="treeData"
:loading="loading"
:pagination="false"
row-key="id"
:default-expand-all-rows="true"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'icon'">
<span v-if="record.icon" class="menu-icon"><component :is="record.icon" /> {{ record.icon }}</span>
<span v-else>-</span>
</template>
<template v-else-if="column.key === 'type'">
<a-tag :color="getTypeColor(record.type)">{{ getTypeName(record.type) }}</a-tag>
</template>
<template v-else-if="column.key === 'status'">
<a-tag :color="record.status === 1 ? 'green' : 'red'">
{{ record.status === 1 ? '正常' : '禁用' }}
</a-tag>
</template>
<template v-else-if="column.key === 'hidden'">
<a-tag :color="record.hidden === 1 ? 'orange' : 'default'">
{{ record.hidden === 1 ? '隐藏' : '显示' }}
</a-tag>
</template>
<template v-else-if="column.key === 'action'">
<a-space>
<a-button type="link" size="small" @click="handleAdd(record.id)">添加子菜单</a-button>
<a-button type="link" size="small" @click="handleEdit(record as MenuRecord)">编辑</a-button>
<a-popconfirm title="确定删除该菜单吗?" @confirm="handleDelete(record.id)">
<a-button type="link" size="small" danger>删除</a-button>
</a-popconfirm>
</a-space>
</template>
</template>
</a-table>
</a-card>
<!-- 新增/编辑弹窗 -->
<MenuFormModal
v-model:visible="modalVisible"
:record="currentRecord"
:menu-tree="treeData"
@success="loadData"
/>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { message } from 'ant-design-vue'
import { PlusOutlined } from '@ant-design/icons-vue'
import type { MenuRecord, MenuFormData } from '@/types/system/menu'
import { getMenuList, deleteMenu } from '@/api/system/menu'
import MenuFormModal from '@/components/system/menu/MenuFormModal.vue'
import { buildMenuTree } from '@/utils/route'
// Note: buildMenuTree expects SysMenu, MenuRecord extends SysMenu so it's fine.
// Using 'any' cast if strict checking fails due to optional properties.
const loading = ref(false)
const treeData = ref<MenuRecord[]>([])
// 表格列定义
const columns = [
{ title: '菜单名称', dataIndex: 'name', key: 'name', width: 200 },
{ title: '编码', dataIndex: 'code', key: 'code', width: 150 },
{ title: '图标', dataIndex: 'icon', key: 'icon', width: 120 },
{ title: '类型', dataIndex: 'type', key: 'type', width: 100 },
{ title: '路径', dataIndex: 'path', key: 'path' },
{ title: '排序', dataIndex: 'sort', key: 'sort', width: 80 },
{ title: '状态', dataIndex: 'status', key: 'status', width: 80 },
{ title: '显示', dataIndex: 'hidden', key: 'hidden', width: 80 },
{ title: '操作', key: 'action', width: 220, fixed: 'right' as const }
]
// 弹窗相关
const modalVisible = ref(false)
const currentRecord = ref<MenuFormData | undefined>(undefined)
function getTypeColor(type: string): string {
const colorMap: Record<string, string> = {
directory: 'blue',
menu: 'green',
button: 'orange'
}
return colorMap[type] || 'default'
}
function getTypeName(type: string): string {
const nameMap: Record<string, string> = {
directory: '目录',
menu: '菜单',
button: '按钮'
}
return nameMap[type] || type
}
// 加载数据
async function loadData() {
loading.value = true
try {
const res = await getMenuList()
// res.data.data is the array
const list = res.data.data || []
// Cast to any because buildMenuTree typings might be strict about SysMenu properties
treeData.value = buildMenuTree(list as any[]) as unknown as MenuRecord[]
} catch (error) {
console.error('加载数据失败:', error)
} finally {
loading.value = false
}
}
function handleAdd(parentId?: number) {
currentRecord.value = {
parentId: parentId || 0
} as MenuFormData
modalVisible.value = true
}
function handleEdit(record: MenuRecord) {
currentRecord.value = { ...record }
modalVisible.value = true
}
async function handleDelete(id: number) {
try {
await deleteMenu(id)
message.success('删除成功')
loadData()
} catch (error) {
console.error('删除失败:', error)
}
}
onMounted(() => {
loadData()
})
</script>
<style scoped>
.page-container {
padding: 0;
}
.table-card {
background: #fff;
}
.menu-icon {
font-size: 14px;
color: #666;
}
</style>