This commit is contained in:
2026-09-18 16:48:40 +08:00
parent e10d0534ae
commit 24fa3d1c9d
19 changed files with 286 additions and 210 deletions
+7 -10
View File
@@ -50,6 +50,7 @@ function mountServerView(permissionCodes = ['platform:permission:list', 'platfor
plugins: [pinia],
directives: { loading: () => undefined },
stubs: {
RowActions: false,
AdminPage: { template: '<main><slot /></main>' },
ListPageLayout: { template: '<section><slot name="toolbar" /><slot name="state" /><slot /></section>' },
FormSection: { template: '<section><slot /></section>' },
@@ -85,16 +86,12 @@ describe('PermissionsView IAM mode', () => {
expect(permissionsSource).toContain("(row as Permission).status || '—'")
})
it('uses outlined business action buttons while keeping tree view helpers as links', () => {
expect(permissionsSource).toContain('size="small" data-tone="neutral" @click="openCreate((row as Permission).id)"')
expect(permissionsSource).toContain('size="small" data-tone="neutral" :disabled="rowActionId')
expect(permissionsSource).toContain('size="small" :data-tone="(row as Permission).status')
expect(permissionsSource).toContain('size="small" data-tone="danger"')
expect(permissionsSource).toContain('size="small" :aria-label="moreActionsLabel(row as Permission)"')
expect(permissionsSource).toContain('>添加下级</el-button>')
expect(permissionsSource).toContain('>编辑</el-button>')
expect(permissionsSource).toContain(':data-tone=')
expect(permissionsSource).toContain('>删除</el-button>')
expect(permissionsSource).toContain('<MoreHorizontal aria-hidden="true" :size="16" />')
expect(permissionsSource).toContain("import RowActions, { type RowActionItem } from '@/shared/components/RowActions.vue'")
expect(permissionsSource).toContain("{ key: 'add-child', label: '添加下级', priority: 400")
expect(permissionsSource).toContain("{ key: 'edit', label: '编辑', priority: 300")
expect(permissionsSource).toContain("{ key: 'status', label: row.status === '启用' ? '停用' : '启用'")
expect(permissionsSource).toContain("{ key: 'delete', label: '删除', tone: 'danger', divided: true")
expect(permissionsSource).toContain('<RowActions v-if="permissionActions(row as Permission).some')
expect(permissionsSource).toContain('<el-button link type="primary" @click="expandAllRows">展开全部</el-button>')
expect(permissionsSource).not.toContain('canAddChild(row as Permission)" link')
expect(permissionsSource).not.toContain('canEditRow(row as Permission)" link')
+17 -26
View File
@@ -3,7 +3,7 @@ import '@/styles/adminDensity.css'
import '../iamDensity.css'
import { computed, nextTick, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { Braces, FolderTree, MoreHorizontal, Plus, ShieldCheck } from '@lucide/vue'
import { Braces, FolderTree, Plus, ShieldCheck } from '@lucide/vue'
import StatusBadge from '@/shared/components/StatusBadge.vue'
import DataTable, { type DataTableColumn } from '@/shared/components/DataTable.vue'
import QueryToolbar, { type QueryField, type QueryModel } from '@/shared/components/QueryToolbar.vue'
@@ -12,6 +12,7 @@ import AppDialog from '@/shared/components/AppDialog.vue'
import FormSection from '@/shared/components/FormSection.vue'
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import RowActions, { type RowActionItem } from '@/shared/components/RowActions.vue'
import {
changePlatformPermissionStatus,
createPlatformPermission,
@@ -247,24 +248,26 @@ function canChangeStatusRow(row: Permission) {
function canDeleteRow(row: Permission) {
return canDelete.value && !row.builtIn
}
function permissionActionCount(row: Permission) {
return Number(canAddChild(row))
+ Number(canEditRow(row))
+ Number(canChangeStatusRow(row))
+ Number(canDeleteRow(row))
}
function showDeleteDirect(row: Permission) {
return canDeleteRow(row) && permissionActionCount(row) <= 3
}
function showDeleteMore(row: Permission) {
return canDeleteRow(row) && permissionActionCount(row) > 3
}
function moreActionsLabel(row: Permission) {
const resourceLabel = [row.name]
.find((value) => typeof value === 'string' && value.trim())
?.trim() || '当前权限'
return `${resourceLabel}的更多操作`
}
function permissionActions(row: Permission): RowActionItem[] {
return [
{ key: 'add-child', label: '添加下级', priority: 400, visible: canAddChild(row) },
{ key: 'edit', label: '编辑', priority: 300, visible: canEditRow(row), disabled: rowActionId.value === row.id },
{ key: 'status', label: row.status === '启用' ? '停用' : '启用', priority: 200, visible: canChangeStatusRow(row), tone: row.status === '启用' ? 'danger' : 'success', loading: rowActionId.value === row.id },
{ key: 'delete', label: '删除', tone: 'danger', divided: true, visible: canDeleteRow(row), disabled: rowActionId.value === row.id },
]
}
function handlePermissionAction(command: string, row: Permission) {
if (command === 'add-child') openCreate(row.id)
else if (command === 'edit') openEdit(row)
else if (command === 'status') void toggleStatus(row)
else if (command === 'delete') void removePermission(row)
}
onMounted(loadPermissions)
</script>
@@ -283,19 +286,7 @@ onMounted(loadPermissions)
<DataTable :key="tableRenderKey" v-model:page="page" v-model:page-size="pageSize" :data="pagedTreeRows" :columns="permissionColumns" preference-key="permissions-table" :loading="loading" :total="treeRows.length" row-key="id" aria-label="平台权限资源列表" :expand-row-keys="expandedRowKeys" :tree-props="{ children: 'children' }" empty-text="没有符合条件的权限资源">
<template #toolbar-start><div class="permission-tree-tools"><div class="legend-list"><span><i class="is-menu" />目录 / 菜单</span><span><i class="is-action" />操作</span><span><i class="is-api" />接口预留</span><span class="permission-protection-hint">受保护资源不可编辑、停用或删除</span></div><div class="tree-view-actions"><el-button link type="primary" @click="expandAllRows">展开全部</el-button><el-button link @click="collapseActionRows">收起操作权限</el-button></div></div></template>
<template #toolbar-actions><el-button v-if="canCreate" type="primary" @click="openCreate(null)"><Plus :size="16" />新增权限</el-button></template>
<template #actions="{ row }">
<div v-if="permissionActionCount(row as Permission) > 0 || (row as Permission).builtIn" class="table-actions density-actions">
<el-button class="density-action" v-if="canAddChild(row as Permission)" size="small" data-tone="neutral" @click="openCreate((row as Permission).id)">添加下级</el-button>
<el-button class="density-action" v-if="canEditRow(row as Permission)" size="small" data-tone="neutral" :disabled="rowActionId === (row as Permission).id" @click="openEdit(row as Permission)">编辑</el-button>
<el-button class="density-action" v-if="canChangeStatusRow(row as Permission)" size="small" :data-tone="(row as Permission).status === '启用' ? 'danger' : 'success'" :loading="rowActionId === (row as Permission).id" @click="toggleStatus(row as Permission)">{{ (row as Permission).status === '启用' ? '停用' : '启用' }}</el-button>
<el-button class="density-action" v-if="showDeleteDirect(row as Permission)" size="small" data-tone="danger" :disabled="rowActionId === (row as Permission).id" @click="removePermission(row as Permission)">删除</el-button>
<el-dropdown v-if="showDeleteMore(row as Permission)" trigger="click" @command="(command: string) => command === 'delete' && removePermission(row as Permission)">
<el-button data-tone="neutral" class="density-action" size="small" :aria-label="moreActionsLabel(row as Permission)" :title="moreActionsLabel(row as Permission)"><MoreHorizontal aria-hidden="true" :size="16" /></el-button>
<template #dropdown><el-dropdown-menu><el-dropdown-item command="delete" :disabled="rowActionId === (row as Permission).id" class="danger-menu-item">删除</el-dropdown-item></el-dropdown-menu></template>
</el-dropdown>
</div>
<span v-else class="secondary-text">仅查看</span>
</template>
<template #actions="{ row }"><RowActions v-if="permissionActions(row as Permission).some(action => action.visible !== false)" :actions="permissionActions(row as Permission)" :more-label="moreActionsLabel(row as Permission)" @action="handlePermissionAction($event, row as Permission)" /><span v-else class="secondary-text">仅查看</span></template>
<template #name="{ row }"><div class="permission-name"><span :class="`is-${typeClass((row as Permission).type)}`"><FolderTree v-if="['目录', '菜单', '页面'].includes((row as Permission).type)" :size="16" /><ShieldCheck v-else-if="(row as Permission).type === '按钮'" :size="16" /><Braces v-else :size="16" /></span><div><strong>{{ (row as Permission).name }}</strong><small v-if="(row as PermissionTreeNode).children?.length">{{ permissionSummary(row as PermissionTreeNode) }}</small></div></div></template>
<template #code="{ row }"><code class="code-value">{{ (row as Permission).code }}</code></template>
<template #endpoint="{ row }"><div class="endpoint-cell"><span v-if="(row as Permission).method !== '-'">{{ (row as Permission).method }}</span><code>{{ (row as Permission).path || '-' }}</code></div></template>