Files
nanxiisletAdmin/src/views/system/roles/index.vue
2026-01-15 13:17:41 +08:00

200 lines
5.5 KiB
Vue

<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="tableData"
:loading="loading"
:pagination="false"
row-key="id"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'status'">
<a-tag :color="record.status === 1 ? 'green' : 'red'">
{{ record.status === 1 ? '正常' : '禁用' }}
</a-tag>
</template>
<template v-else-if="column.key === 'action'">
<a-space>
<a-button type="link" size="small" @click="handleEdit(record as RoleRecord)">编辑</a-button>
<a-button type="link" size="small" @click="handleAssignMenus(record as RoleRecord)">分配权限</a-button>
<a-popconfirm
title="确定删除该角色吗?"
@confirm="handleDelete(record.id)"
:disabled="['super_admin', 'admin'].includes(record.code)"
>
<a-button
type="link"
size="small"
danger
:disabled="['super_admin', 'admin'].includes(record.code)"
>
删除
</a-button>
</a-popconfirm>
</a-space>
</template>
</template>
</a-table>
</a-card>
<!-- 新增/编辑弹窗 -->
<RoleFormModal
v-model:visible="modalVisible"
:record="currentRecord"
@success="loadData"
/>
<!-- 分配权限弹窗 -->
<a-modal
v-model:open="assignMenusVisible"
title="分配菜单权限"
:confirm-loading="assignMenusLoading"
width="500px"
@ok="handleAssignMenusOk"
>
<a-spin :spinning="menuTreeLoading">
<a-tree
v-model:checkedKeys="checkedMenuIds"
:tree-data="menuTree"
checkable
:field-names="{ title: 'name', key: 'id', children: 'children' }"
default-expand-all
/>
</a-spin>
</a-modal>
</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 { buildMenuTree } from '@/utils/route'
import { getRoleList, getRolePage, deleteRole, getRoleMenuIds, assignRoleMenus } from '@/api/system/role'
import { getMenuList } from '@/api/system/menu'
import type { RoleRecord, RoleFormData } from '@/types/system/role'
import type { SysMenu } from '@/types/api/auth'
import RoleFormModal from '@/components/system/role/RoleFormModal.vue'
const loading = ref(false)
const tableData = ref<RoleRecord[]>([])
// 表格列定义
const columns = [
{ title: '角色编码', dataIndex: 'code', key: 'code' },
{ title: '角色名称', dataIndex: 'name', key: 'name' },
{ title: '描述', dataIndex: 'description', key: 'description' },
{ title: '排序', dataIndex: 'sort', key: 'sort', width: 80 },
{ title: '状态', dataIndex: 'status', key: 'status', width: 100 },
{ title: '创建时间', dataIndex: 'createdAt', key: 'createdAt', width: 180 },
{ title: '操作', key: 'action', width: 220, fixed: 'right' as const }
]
// 弹窗相关
const modalVisible = ref(false)
const currentRecord = ref<RoleFormData | undefined>(undefined)
// 分配权限相关
const assignMenusVisible = ref(false)
const assignMenusLoading = ref(false)
const menuTreeLoading = ref(false)
const menuTree = ref<any[]>([])
const checkedMenuIds = ref<number[]>([])
const currentRoleId = ref<number>()
// 加载数据
async function loadData() {
loading.value = true
try {
const res = await getRolePage({ pageSize: 100 })
tableData.value = res.records || []
} catch (error) {
console.error('加载数据失败:', error)
} finally {
loading.value = false
}
}
function handleAdd() {
currentRecord.value = undefined
modalVisible.value = true
}
function handleEdit(record: RoleRecord) {
currentRecord.value = { ...record }
modalVisible.value = true
}
async function handleDelete(id: number) {
try {
await deleteRole(id)
message.success('删除成功')
loadData()
} catch (error) {
console.error('删除失败:', error)
}
}
async function handleAssignMenus(record: RoleRecord) {
currentRoleId.value = record.id
checkedMenuIds.value = []
assignMenusVisible.value = true
menuTreeLoading.value = true
try {
// 加载菜单树
// 加载菜单树
const menuRes = await getMenuList()
menuTree.value = buildMenuTree(menuRes.data.data || [])
// 加载角色已有的菜单
const roleMenuRes = await getRoleMenuIds(record.id)
checkedMenuIds.value = roleMenuRes || []
} catch (error) {
console.error('加载数据失败:', error)
} finally {
menuTreeLoading.value = false
}
}
async function handleAssignMenusOk() {
if (!currentRoleId.value) return
assignMenusLoading.value = true
try {
await assignRoleMenus(currentRoleId.value, checkedMenuIds.value)
message.success('权限分配成功')
assignMenusVisible.value = false
} catch (error) {
console.error('权限分配失败:', error)
} finally {
assignMenusLoading.value = false
}
}
onMounted(() => {
loadData()
})
</script>
<style scoped>
.page-container {
padding: 0;
}
.table-card {
background: #fff;
}
</style>