template_admin/src/views/system/role/index.vue

505 lines
12 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="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>