505 lines
12 KiB
Vue
505 lines
12 KiB
Vue
<template>
|
||
<div class="role-container">
|
||
<a-card>
|
||
<!-- 操作按钮区域 -->
|
||
<div class="table-operations">
|
||
<a-button type="primary" @click="showModal('add')">
|
||
<template #icon><plus-outlined /></template>
|
||
新增角色
|
||
</a-button>
|
||
<a-button danger :disabled="!hasSelected" @click="handleBatchDelete">
|
||
<template #icon><delete-outlined /></template>
|
||
批量删除
|
||
</a-button>
|
||
</div>
|
||
|
||
<!-- 表格区域 -->
|
||
<a-table
|
||
:columns="columns"
|
||
:data-source="roleData"
|
||
:row-selection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
|
||
:pagination="pagination"
|
||
:loading="loading"
|
||
@change="handleTableChange"
|
||
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-if="column.key === 'action'">
|
||
<a-space>
|
||
<a @click="showModal('edit', record)">编辑</a>
|
||
<a-divider type="vertical" />
|
||
<a @click="showPermissionModal(record)">权限设置</a>
|
||
<a-divider type="vertical" />
|
||
<a-popconfirm
|
||
title="确定要删除此角色吗?"
|
||
ok-text="确定"
|
||
cancel-text="取消"
|
||
@confirm="handleDelete(record)"
|
||
>
|
||
<a class="danger-link">删除</a>
|
||
</a-popconfirm>
|
||
</a-space>
|
||
</template>
|
||
</template>
|
||
</a-table>
|
||
</a-card>
|
||
|
||
<!-- 角色表单弹窗 -->
|
||
<a-modal
|
||
v-model:visible="modalVisible"
|
||
:title="modalType === 'add' ? '新增角色' : '编辑角色'"
|
||
@ok="handleModalOk"
|
||
@cancel="handleModalCancel"
|
||
>
|
||
<a-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
:rules="formRules"
|
||
:label-col="{ span: 6 }"
|
||
:wrapper-col="{ span: 16 }"
|
||
>
|
||
<a-form-item label="角色名称" name="name">
|
||
<a-input v-model:value="formData.name" placeholder="请输入角色名称" />
|
||
</a-form-item>
|
||
<a-form-item label="角色编码" name="code">
|
||
<a-input v-model:value="formData.code" placeholder="请输入角色编码" />
|
||
</a-form-item>
|
||
<a-form-item label="角色描述" name="description">
|
||
<a-textarea
|
||
v-model:value="formData.description"
|
||
placeholder="请输入角色描述"
|
||
:rows="4"
|
||
/>
|
||
</a-form-item>
|
||
<a-form-item label="排序" name="sort">
|
||
<a-input-number
|
||
v-model:value="formData.sort"
|
||
placeholder="请输入排序"
|
||
style="width: 100%"
|
||
/>
|
||
</a-form-item>
|
||
<a-form-item label="状态" name="status">
|
||
<a-radio-group v-model:value="formData.status">
|
||
<a-radio value="1">启用</a-radio>
|
||
<a-radio value="0">禁用</a-radio>
|
||
</a-radio-group>
|
||
</a-form-item>
|
||
</a-form>
|
||
</a-modal>
|
||
|
||
<!-- 权限设置弹窗 -->
|
||
<a-modal
|
||
v-model:visible="permissionModalVisible"
|
||
title="权限设置"
|
||
width="600px"
|
||
@ok="handlePermissionOk"
|
||
@cancel="handlePermissionCancel"
|
||
>
|
||
<div v-if="currentRole">
|
||
<div class="permission-title">
|
||
<span>当前角色: {{ currentRole.name }}</span>
|
||
</div>
|
||
<a-tree
|
||
v-model:checkedKeys="checkedKeys"
|
||
:tree-data="permissionTree"
|
||
checkable
|
||
:default-expand-all="true"
|
||
/>
|
||
</div>
|
||
</a-modal>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, computed, onMounted } from 'vue'
|
||
import { message } from 'ant-design-vue'
|
||
import type { FormInstance } from 'ant-design-vue'
|
||
import {
|
||
PlusOutlined,
|
||
DeleteOutlined
|
||
} from '@ant-design/icons-vue'
|
||
|
||
// 表格列定义
|
||
const columns = [
|
||
{
|
||
title: '角色名称',
|
||
dataIndex: 'name',
|
||
key: 'name'
|
||
},
|
||
{
|
||
title: '角色编码',
|
||
dataIndex: 'code',
|
||
key: 'code'
|
||
},
|
||
{
|
||
title: '描述',
|
||
dataIndex: 'description',
|
||
key: 'description'
|
||
},
|
||
{
|
||
title: '排序',
|
||
dataIndex: 'sort',
|
||
key: 'sort',
|
||
sorter: true
|
||
},
|
||
{
|
||
title: '状态',
|
||
dataIndex: 'status',
|
||
key: 'status'
|
||
},
|
||
{
|
||
title: '创建时间',
|
||
dataIndex: 'createTime',
|
||
key: 'createTime',
|
||
sorter: true
|
||
},
|
||
{
|
||
title: '操作',
|
||
key: 'action',
|
||
width: 250
|
||
}
|
||
]
|
||
|
||
// 模拟角色数据
|
||
const generateMockRoleData = () => {
|
||
return [
|
||
{
|
||
id: '1',
|
||
name: '超级管理员',
|
||
code: 'ADMIN',
|
||
description: '系统最高权限,可以操作系统所有功能',
|
||
sort: 1,
|
||
status: '1',
|
||
createTime: '2023-05-01 12:00:00',
|
||
permissions: ['1', '1-1', '1-2', '1-3', '2', '2-1', '2-2', '3', '3-1', '3-2']
|
||
},
|
||
{
|
||
id: '2',
|
||
name: '运营人员',
|
||
code: 'OPERATOR',
|
||
description: '负责系统日常运营工作',
|
||
sort: 2,
|
||
status: '1',
|
||
createTime: '2023-05-02 12:00:00',
|
||
permissions: ['1', '1-1', '1-2', '2', '2-1']
|
||
},
|
||
{
|
||
id: '3',
|
||
name: '财务人员',
|
||
code: 'FINANCE',
|
||
description: '负责财务相关工作',
|
||
sort: 3,
|
||
status: '1',
|
||
createTime: '2023-05-03 12:00:00',
|
||
permissions: ['1', '1-1', '3', '3-1']
|
||
},
|
||
{
|
||
id: '4',
|
||
name: '客服人员',
|
||
code: 'CUSTOMER_SERVICE',
|
||
description: '负责客户服务工作',
|
||
sort: 4,
|
||
status: '1',
|
||
createTime: '2023-05-04 12:00:00',
|
||
permissions: ['1', '1-1', '2', '2-1']
|
||
},
|
||
{
|
||
id: '5',
|
||
name: '访客',
|
||
code: 'VISITOR',
|
||
description: '系统访客,只有查看权限',
|
||
sort: 5,
|
||
status: '0',
|
||
createTime: '2023-05-05 12:00:00',
|
||
permissions: ['1', '1-1']
|
||
}
|
||
]
|
||
}
|
||
|
||
// 模拟权限树数据
|
||
const permissionTree = [
|
||
{
|
||
title: '系统管理',
|
||
key: '1',
|
||
children: [
|
||
{
|
||
title: '用户管理',
|
||
key: '1-1',
|
||
children: [
|
||
{ title: '查询用户', key: '1-1-1' },
|
||
{ title: '新增用户', key: '1-1-2' },
|
||
{ title: '编辑用户', key: '1-1-3' },
|
||
{ title: '删除用户', key: '1-1-4' }
|
||
]
|
||
},
|
||
{
|
||
title: '角色管理',
|
||
key: '1-2',
|
||
children: [
|
||
{ title: '查询角色', key: '1-2-1' },
|
||
{ title: '新增角色', key: '1-2-2' },
|
||
{ title: '编辑角色', key: '1-2-3' },
|
||
{ title: '删除角色', key: '1-2-4' }
|
||
]
|
||
},
|
||
{
|
||
title: '菜单管理',
|
||
key: '1-3',
|
||
children: [
|
||
{ title: '查询菜单', key: '1-3-1' },
|
||
{ title: '新增菜单', key: '1-3-2' },
|
||
{ title: '编辑菜单', key: '1-3-3' },
|
||
{ title: '删除菜单', key: '1-3-4' }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
title: '内容管理',
|
||
key: '2',
|
||
children: [
|
||
{
|
||
title: '文章管理',
|
||
key: '2-1',
|
||
children: [
|
||
{ title: '查询文章', key: '2-1-1' },
|
||
{ title: '新增文章', key: '2-1-2' },
|
||
{ title: '编辑文章', key: '2-1-3' },
|
||
{ title: '删除文章', key: '2-1-4' }
|
||
]
|
||
},
|
||
{
|
||
title: '分类管理',
|
||
key: '2-2',
|
||
children: [
|
||
{ title: '查询分类', key: '2-2-1' },
|
||
{ title: '新增分类', key: '2-2-2' },
|
||
{ title: '编辑分类', key: '2-2-3' },
|
||
{ title: '删除分类', key: '2-2-4' }
|
||
]
|
||
}
|
||
]
|
||
},
|
||
{
|
||
title: '订单管理',
|
||
key: '3',
|
||
children: [
|
||
{
|
||
title: '订单列表',
|
||
key: '3-1',
|
||
children: [
|
||
{ title: '查询订单', key: '3-1-1' },
|
||
{ title: '订单详情', key: '3-1-2' },
|
||
{ title: '订单导出', key: '3-1-3' }
|
||
]
|
||
},
|
||
{
|
||
title: '退款管理',
|
||
key: '3-2',
|
||
children: [
|
||
{ title: '查询退款', key: '3-2-1' },
|
||
{ title: '审核退款', key: '3-2-2' }
|
||
]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
|
||
// 状态变量
|
||
const loading = ref(false)
|
||
const roleData = ref(generateMockRoleData())
|
||
const selectedRowKeys = ref<string[]>([])
|
||
const modalVisible = ref(false)
|
||
const modalType = ref<'add' | 'edit'>('add')
|
||
const formRef = ref<FormInstance>()
|
||
const permissionModalVisible = ref(false)
|
||
const currentRole = ref<any>(null)
|
||
const checkedKeys = ref<string[]>([])
|
||
|
||
// 编辑表单
|
||
const formData = reactive({
|
||
id: '',
|
||
name: '',
|
||
code: '',
|
||
description: '',
|
||
sort: 0,
|
||
status: '1'
|
||
})
|
||
|
||
// 表单验证规则
|
||
const formRules = {
|
||
name: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
|
||
code: [{ required: true, message: '请输入角色编码', trigger: 'blur' }],
|
||
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }],
|
||
status: [{ required: true, message: '请选择状态', trigger: 'change' }]
|
||
}
|
||
|
||
// 分页配置
|
||
const pagination = reactive({
|
||
current: 1,
|
||
pageSize: 10,
|
||
total: roleData.value.length,
|
||
showSizeChanger: true,
|
||
showTotal: (total: number) => `共 ${total} 条`
|
||
})
|
||
|
||
// 计算属性
|
||
const hasSelected = computed(() => selectedRowKeys.value.length > 0)
|
||
|
||
// 生命周期钩子
|
||
onMounted(() => {
|
||
fetchRoleData()
|
||
})
|
||
|
||
// 方法
|
||
const fetchRoleData = () => {
|
||
loading.value = true
|
||
// 模拟API请求
|
||
setTimeout(() => {
|
||
pagination.total = roleData.value.length
|
||
loading.value = false
|
||
}, 500)
|
||
}
|
||
|
||
const handleTableChange = (pag: any) => {
|
||
pagination.current = pag.current
|
||
pagination.pageSize = pag.pageSize
|
||
fetchRoleData()
|
||
}
|
||
|
||
const onSelectChange = (keys: string[]) => {
|
||
selectedRowKeys.value = keys
|
||
}
|
||
|
||
const showModal = (type: 'add' | 'edit', record?: any) => {
|
||
modalType.value = type
|
||
|
||
// 重置表单
|
||
if (formRef.value) {
|
||
formRef.value.resetFields()
|
||
}
|
||
|
||
if (type === 'edit' && record) {
|
||
Object.keys(formData).forEach(key => {
|
||
if (key in record) {
|
||
formData[key as keyof typeof formData] = record[key]
|
||
}
|
||
})
|
||
} else {
|
||
// 新增时设置默认值
|
||
formData.status = '1'
|
||
formData.sort = roleData.value.length + 1
|
||
}
|
||
|
||
modalVisible.value = true
|
||
}
|
||
|
||
const handleModalOk = () => {
|
||
formRef.value?.validate().then(() => {
|
||
if (modalType.value === 'add') {
|
||
// 模拟添加角色
|
||
const newRole = {
|
||
id: (roleData.value.length + 1).toString(),
|
||
...formData,
|
||
createTime: new Date().toLocaleString(),
|
||
permissions: []
|
||
}
|
||
roleData.value.push(newRole)
|
||
message.success('添加角色成功')
|
||
} else {
|
||
// 模拟编辑角色
|
||
const index = roleData.value.findIndex(item => item.id === formData.id)
|
||
if (index !== -1) {
|
||
roleData.value[index] = {
|
||
...roleData.value[index],
|
||
...formData
|
||
}
|
||
message.success('编辑角色成功')
|
||
}
|
||
}
|
||
|
||
modalVisible.value = false
|
||
fetchRoleData()
|
||
}).catch(error => {
|
||
console.log('表单验证失败:', error)
|
||
})
|
||
}
|
||
|
||
const handleModalCancel = () => {
|
||
modalVisible.value = false
|
||
}
|
||
|
||
const showPermissionModal = (record: any) => {
|
||
currentRole.value = record
|
||
checkedKeys.value = [...record.permissions]
|
||
permissionModalVisible.value = true
|
||
}
|
||
|
||
const handlePermissionOk = () => {
|
||
if (currentRole.value) {
|
||
// 模拟保存权限
|
||
const index = roleData.value.findIndex(item => item.id === currentRole.value.id)
|
||
if (index !== -1) {
|
||
roleData.value[index].permissions = [...checkedKeys.value]
|
||
message.success('权限设置成功')
|
||
}
|
||
}
|
||
permissionModalVisible.value = false
|
||
}
|
||
|
||
const handlePermissionCancel = () => {
|
||
permissionModalVisible.value = false
|
||
}
|
||
|
||
const handleDelete = (record: any) => {
|
||
// 模拟删除角色
|
||
roleData.value = roleData.value.filter(item => item.id !== record.id)
|
||
message.success('删除角色成功')
|
||
|
||
// 如果删除的是已选中的行,需要更新selectedRowKeys
|
||
selectedRowKeys.value = selectedRowKeys.value.filter(key => key !== record.id)
|
||
|
||
fetchRoleData()
|
||
}
|
||
|
||
const handleBatchDelete = () => {
|
||
// 模拟批量删除角色
|
||
roleData.value = roleData.value.filter(item => !selectedRowKeys.value.includes(item.id))
|
||
message.success(`成功删除 ${selectedRowKeys.value.length} 个角色`)
|
||
selectedRowKeys.value = []
|
||
fetchRoleData()
|
||
}
|
||
</script>
|
||
|
||
<style lang="less" scoped>
|
||
.role-container {
|
||
padding: 0;
|
||
|
||
.table-operations {
|
||
margin-bottom: 16px;
|
||
|
||
button {
|
||
margin-right: 8px;
|
||
}
|
||
}
|
||
|
||
.permission-title {
|
||
margin-bottom: 16px;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.danger-link {
|
||
color: #ff4d4f;
|
||
|
||
&:hover {
|
||
color: #ff7875;
|
||
}
|
||
}
|
||
}
|
||
</style>
|