| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598 |
- <template>
- <div class="permissions-management">
- <div class="page-header">
- <h2>权限管理</h2>
- <p>管理系统权限和资源访问控制</p>
- </div>
- <!-- 操作栏 -->
- <div class="toolbar">
- <div class="toolbar-left">
- <el-button type="primary" @click="showCreateDialog = true">
- <el-icon><Plus /></el-icon>
- 创建权限
- </el-button>
- <el-button @click="refreshPermissions">
- <el-icon><Refresh /></el-icon>
- 刷新
- </el-button>
- </div>
- <div class="toolbar-right">
- <el-select
- v-model="selectedResource"
- placeholder="选择资源类型"
- style="width: 150px; margin-right: 12px;"
- @change="handleResourceFilter"
- clearable
- >
- <el-option label="全部资源" value="" />
- <el-option label="用户管理" value="user" />
- <el-option label="角色管理" value="role" />
- <el-option label="菜单管理" value="menu" />
- <el-option label="应用管理" value="app" />
- <el-option label="系统管理" value="system" />
- </el-select>
- <el-input
- v-model="searchKeyword"
- placeholder="搜索权限名称..."
- style="width: 300px"
- @input="handleSearch"
- >
- <template #prefix>
- <el-icon><Search /></el-icon>
- </template>
- </el-input>
- </div>
- </div>
- <!-- 权限列表 -->
- <el-table
- v-loading="loading"
- :data="permissions"
- style="width: 100%"
- @selection-change="handleSelectionChange"
- >
- <el-table-column type="selection" width="55" />
- <el-table-column prop="display_name" label="权限名称" min-width="150">
- <template #default="{ row }">
- <div class="permission-info">
- <span class="permission-name">{{ row.display_name }}</span>
- <el-tag size="small" style="margin-left: 8px;">{{ row.name }}</el-tag>
- </div>
- </template>
- </el-table-column>
- <el-table-column prop="resource" label="资源" width="120">
- <template #default="{ row }">
- <el-tag :type="getResourceTagType(row.resource)" size="small">
- {{ getResourceLabel(row.resource) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="action" label="操作" width="100">
- <template #default="{ row }">
- <el-tag :type="getActionTagType(row.action)" size="small">
- {{ getActionLabel(row.action) }}
- </el-tag>
- </template>
- </el-table-column>
- <el-table-column prop="description" label="描述" min-width="200" show-overflow-tooltip />
- <el-table-column prop="is_active" label="状态" width="100" align="center">
- <template #default="{ row }">
- <el-switch
- v-model="row.is_active"
- @change="handleStatusChange(row)"
- />
- </template>
- </el-table-column>
- <el-table-column prop="created_at" label="创建时间" width="180">
- <template #default="{ row }">
- {{ formatDateTime(row.created_at) }}
- </template>
- </el-table-column>
- <el-table-column label="操作" width="200" fixed="right">
- <template #default="{ row }">
- <el-button type="primary" size="small" @click="editPermission(row)">
- 编辑
- </el-button>
- <el-button type="info" size="small" @click="viewRoles(row)">
- 查看角色
- </el-button>
- <el-button type="danger" size="small" @click="deletePermission(row)">
- 删除
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页 -->
- <div class="pagination">
- <el-pagination
- v-model:current-page="currentPage"
- v-model:page-size="pageSize"
- :page-sizes="[10, 20, 50, 100]"
- :total="total"
- layout="total, sizes, prev, pager, next, jumper"
- @size-change="handleSizeChange"
- @current-change="handleCurrentChange"
- />
- </div>
- <!-- 创建/编辑权限对话框 -->
- <el-dialog
- v-model="showCreateDialog"
- :title="editingPermission ? '编辑权限' : '创建权限'"
- width="600px"
- @close="resetForm"
- >
- <el-form
- ref="permissionFormRef"
- :model="permissionForm"
- :rules="permissionRules"
- label-width="100px"
- >
- <el-form-item label="权限名称" prop="display_name">
- <el-input v-model="permissionForm.display_name" placeholder="请输入权限显示名称" />
- </el-form-item>
- <el-form-item label="权限标识" prop="name">
- <el-input
- v-model="permissionForm.name"
- placeholder="请输入权限标识(如:user.create)"
- :disabled="!!editingPermission"
- />
- </el-form-item>
- <el-row :gutter="20">
- <el-col :span="12">
- <el-form-item label="资源类型" prop="resource">
- <el-select v-model="permissionForm.resource" placeholder="请选择资源类型">
- <el-option label="用户管理" value="user" />
- <el-option label="角色管理" value="role" />
- <el-option label="菜单管理" value="menu" />
- <el-option label="应用管理" value="app" />
- <el-option label="系统管理" value="system" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="操作类型" prop="action">
- <el-select v-model="permissionForm.action" placeholder="请选择操作类型">
- <el-option label="查看" value="view" />
- <el-option label="创建" value="create" />
- <el-option label="编辑" value="edit" />
- <el-option label="删除" value="delete" />
- <el-option label="分配" value="assign" />
- <el-option label="配置" value="config" />
- <el-option label="审计" value="audit" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="权限描述" prop="description">
- <el-input
- v-model="permissionForm.description"
- type="textarea"
- :rows="3"
- placeholder="请输入权限描述"
- />
- </el-form-item>
- </el-form>
- <template #footer>
- <el-button @click="showCreateDialog = false">取消</el-button>
- <el-button type="primary" @click="savePermission" :loading="saving">
- {{ editingPermission ? '更新' : '创建' }}
- </el-button>
- </template>
- </el-dialog>
- <!-- 查看权限角色对话框 -->
- <el-dialog
- v-model="showRolesDialog"
- title="权限关联角色"
- width="500px"
- >
- <div v-if="currentPermission">
- <h4>权限 "{{ currentPermission.display_name }}" 关联的角色</h4>
- <el-empty v-if="permissionRoles.length === 0" description="暂无关联角色" />
- <div v-else class="roles-list">
- <el-tag
- v-for="role in permissionRoles"
- :key="role.id"
- size="large"
- style="margin: 4px;"
- >
- {{ role.display_name }}
- <el-tag v-if="role.is_system" type="info" size="small" style="margin-left: 4px;">
- 系统角色
- </el-tag>
- </el-tag>
- </div>
- </div>
- <template #footer>
- <el-button @click="showRolesDialog = false">关闭</el-button>
- </template>
- </el-dialog>
- </div>
- </template>
- <script setup lang="ts">
- import { ref, reactive, onMounted } from 'vue'
- import { ElMessage, ElMessageBox } from 'element-plus'
- import { Plus, Search, Refresh } from '@element-plus/icons-vue'
- import request from '@/api/request'
- // 响应式数据
- const loading = ref(false)
- const saving = ref(false)
- const permissions = ref<any[]>([])
- const selectedPermissions = ref<any[]>([])
- const searchKeyword = ref('')
- const selectedResource = ref('')
- const currentPage = ref(1)
- const pageSize = ref(20)
- const total = ref(0)
- // 对话框状态
- const showCreateDialog = ref(false)
- const showRolesDialog = ref(false)
- const editingPermission = ref<any>(null)
- const currentPermission = ref<any>(null)
- const permissionRoles = ref<any[]>([])
- // 表单数据
- const permissionForm = reactive({
- display_name: '',
- name: '',
- resource: '',
- action: '',
- description: ''
- })
- // 表单验证规则
- const permissionRules = {
- display_name: [
- { required: true, message: '请输入权限名称', trigger: 'blur' }
- ],
- name: [
- { required: true, message: '请输入权限标识', trigger: 'blur' },
- { pattern: /^[a-zA-Z_][a-zA-Z0-9_.]*$/, message: '权限标识只能包含字母、数字、下划线和点号,且以字母或下划线开头', trigger: 'blur' }
- ],
- resource: [
- { required: true, message: '请选择资源类型', trigger: 'change' }
- ],
- action: [
- { required: true, message: '请选择操作类型', trigger: 'change' }
- ]
- }
- // 引用
- const permissionFormRef = ref()
- // 获取资源标签类型
- const getResourceTagType = (resource: string) => {
- const types: Record<string, string> = {
- user: 'primary',
- role: 'success',
- menu: 'warning',
- app: 'info',
- system: 'danger'
- }
- return types[resource] || 'default'
- }
- // 获取资源标签文本
- const getResourceLabel = (resource: string) => {
- const labels: Record<string, string> = {
- user: '用户',
- role: '角色',
- menu: '菜单',
- app: '应用',
- system: '系统'
- }
- return labels[resource] || resource
- }
- // 获取操作标签类型
- const getActionTagType = (action: string) => {
- const types: Record<string, string> = {
- view: 'info',
- create: 'success',
- edit: 'warning',
- delete: 'danger',
- assign: 'primary',
- config: 'warning',
- audit: 'info'
- }
- return types[action] || 'default'
- }
- // 获取操作标签文本
- const getActionLabel = (action: string) => {
- const labels: Record<string, string> = {
- view: '查看',
- create: '创建',
- edit: '编辑',
- delete: '删除',
- assign: '分配',
- config: '配置',
- audit: '审计'
- }
- return labels[action] || action
- }
- // 加载权限列表
- const loadPermissions = async () => {
- loading.value = true
- try {
- // TODO: 实现权限列表API
- // 模拟数据
- const mockData = {
- code: 0,
- data: {
- items: [
- {
- id: '1',
- name: 'user.view',
- display_name: '查看用户',
- resource: 'user',
- action: 'view',
- description: '查看用户列表和详情',
- is_active: true,
- created_at: new Date().toISOString()
- },
- {
- id: '2',
- name: 'user.create',
- display_name: '创建用户',
- resource: 'user',
- action: 'create',
- description: '创建新用户',
- is_active: true,
- created_at: new Date().toISOString()
- },
- {
- id: '3',
- name: 'role.view',
- display_name: '查看角色',
- resource: 'role',
- action: 'view',
- description: '查看角色列表和详情',
- is_active: true,
- created_at: new Date().toISOString()
- }
- ],
- total: 3,
- page: currentPage.value,
- page_size: pageSize.value
- }
- }
-
- permissions.value = mockData.data.items
- total.value = mockData.data.total
- } catch (error) {
- console.error('加载权限列表失败:', error)
- ElMessage.error('加载权限列表失败')
- } finally {
- loading.value = false
- }
- }
- // 刷新权限
- const refreshPermissions = () => {
- loadPermissions()
- }
- // 搜索处理
- const handleSearch = () => {
- currentPage.value = 1
- loadPermissions()
- }
- // 资源过滤
- const handleResourceFilter = () => {
- currentPage.value = 1
- loadPermissions()
- }
- // 分页处理
- const handleSizeChange = (size: number) => {
- pageSize.value = size
- currentPage.value = 1
- loadPermissions()
- }
- const handleCurrentChange = (page: number) => {
- currentPage.value = page
- loadPermissions()
- }
- // 选择处理
- const handleSelectionChange = (selection: any[]) => {
- selectedPermissions.value = selection
- }
- // 状态切换
- const handleStatusChange = async (permission: any) => {
- try {
- // TODO: 实现权限状态切换API
- ElMessage.success('权限状态更新成功')
- } catch (error) {
- console.error('更新权限状态失败:', error)
- ElMessage.error('更新权限状态失败')
- // 恢复原状态
- permission.is_active = !permission.is_active
- }
- }
- // 编辑权限
- const editPermission = (permission: any) => {
- editingPermission.value = permission
- Object.assign(permissionForm, {
- display_name: permission.display_name,
- name: permission.name,
- resource: permission.resource,
- action: permission.action,
- description: permission.description
- })
- showCreateDialog.value = true
- }
- // 查看权限关联角色
- const viewRoles = async (permission: any) => {
- currentPermission.value = permission
- try {
- // TODO: 实现获取权限关联角色API
- // 模拟数据
- permissionRoles.value = [
- { id: '1', display_name: '超级管理员', is_system: true },
- { id: '2', display_name: '管理员', is_system: true }
- ]
- showRolesDialog.value = true
- } catch (error) {
- console.error('获取权限角色失败:', error)
- ElMessage.error('获取权限角色失败')
- }
- }
- // 删除权限
- const deletePermission = async (permission: any) => {
- try {
- await ElMessageBox.confirm(
- `确定要删除权限 "${permission.display_name}" 吗?此操作不可恢复。`,
- '确认删除',
- {
- confirmButtonText: '确定',
- cancelButtonText: '取消',
- type: 'warning'
- }
- )
-
- // TODO: 实现删除权限API
- ElMessage.success('权限删除成功')
- loadPermissions()
- } catch (error) {
- if (error !== 'cancel') {
- ElMessage.error('删除权限失败')
- }
- }
- }
- // 保存权限
- const savePermission = async () => {
- try {
- await permissionFormRef.value.validate()
-
- saving.value = true
-
- if (editingPermission.value) {
- // TODO: 实现更新权限API
- ElMessage.success('权限更新成功')
- } else {
- // TODO: 实现创建权限API
- ElMessage.success('权限创建成功')
- }
-
- showCreateDialog.value = false
- loadPermissions()
- } catch (error) {
- console.error('保存权限失败:', error)
- ElMessage.error('保存权限失败')
- } finally {
- saving.value = false
- }
- }
- // 重置表单
- const resetForm = () => {
- editingPermission.value = null
- Object.assign(permissionForm, {
- display_name: '',
- name: '',
- resource: '',
- action: '',
- description: ''
- })
- permissionFormRef.value?.clearValidate()
- }
- // 格式化日期时间
- const formatDateTime = (dateTime: string) => {
- if (!dateTime) return '-'
- return new Date(dateTime).toLocaleString('zh-CN')
- }
- // 组件挂载
- onMounted(() => {
- loadPermissions()
- })
- </script>
- <style scoped>
- .permissions-management {
- padding: 20px;
- }
- .page-header {
- margin-bottom: 20px;
- }
- .page-header h2 {
- margin: 0 0 8px 0;
- color: #333;
- }
- .page-header p {
- margin: 0;
- color: #666;
- font-size: 14px;
- }
- .toolbar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- padding: 16px;
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- }
- .toolbar-left {
- display: flex;
- gap: 12px;
- }
- .toolbar-right {
- display: flex;
- gap: 12px;
- align-items: center;
- }
- .permission-info {
- display: flex;
- align-items: center;
- }
- .permission-name {
- font-weight: 500;
- }
- .roles-list {
- margin-top: 16px;
- }
- .pagination {
- margin-top: 20px;
- display: flex;
- justify-content: center;
- }
- :deep(.el-table) {
- background: #fff;
- border-radius: 8px;
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
- }
- :deep(.el-dialog__body) {
- padding: 20px;
- }
- </style>
|