style(admin): unify dialog layouts and dense readonly presentation

This commit is contained in:
2026-10-20 10:11:31 +08:00
parent 7ff7c9914f
commit 3267679758
214 changed files with 10931 additions and 2654 deletions
+20 -19
View File
@@ -3,13 +3,13 @@ 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, Plus, ShieldCheck } from '@lucide/vue'
import { 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'
import AdminPage from '@/shared/components/AdminPage.vue'
import AppDialog from '@/shared/components/AppDialog.vue'
import FormSection from '@/shared/components/FormSection.vue'
import InlineHelp from '@/shared/components/InlineHelp.vue'
import ListPageLayout from '@/shared/components/ListPageLayout.vue'
import LoadErrorState from '@/shared/components/LoadErrorState.vue'
import RowActions, { type RowActionItem } from '@/shared/components/RowActions.vue'
@@ -59,7 +59,7 @@ const formRules = computed<FormRules>(() => ({
method: form.type === '接口' ? [{ required: true, message: '请选择 HTTP 方法', trigger: 'change' }] : [],
sort: [{ required: true, type: 'number', message: '请输入显示排序', trigger: 'change' }],
}))
const editorLabel = computed(() => form.id ? '编辑权限' : '新增权限')
const editorLabel = computed(() => form.id ? `编辑权限资源 · ${form.name.trim() || form.code.trim() || '—'}` : '新增权限资源')
const requiredPermission = computed(() => form.id ? 'platform:permission:edit' : 'platform:permission:create')
const { captureBaseline } = useUnsavedWorkRegistration({
key: 'permission-editor',
@@ -206,7 +206,7 @@ async function toggleStatus(row: Permission) {
if (row.builtIn) return
const target = row.status === '启用' ? '停用' : '启用'
try {
await ElMessageBox.confirm(`确认${target}权限“${row.name}”吗?`, '权限状态', { customClass: 'admin-density-confirm', confirmButtonText: '确认', cancelButtonText: '取消' })
await ElMessageBox.confirm(`确认${target}权限“${row.name}”吗?`, `${target}权限 · ${row.name.trim() || row.code || '—'}`, { customClass: 'admin-density-confirm', confirmButtonText: '确认', cancelButtonText: '取消' })
rowActionId.value = row.id
const updated = await changePlatformPermissionStatus(row.id, target === '启用' ? 'ACTIVE' : 'DISABLED')
Object.assign(row, mapPlatformPermission(updated))
@@ -222,7 +222,7 @@ async function toggleStatus(row: Permission) {
async function removePermission(row: Permission) {
if (row.builtIn) return
try {
await ElMessageBox.confirm(`确认删除权限“${row.name}”吗?删除前需确保没有下级资源且未分配给角色。`, '删除权限', { customClass: 'admin-density-confirm', confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning' })
await ElMessageBox.confirm(`确认删除权限“${row.name}”吗?删除前需确保没有下级资源且未分配给角色。`, `删除权限 · ${row.name.trim() || row.code || '—'}`, { customClass: 'admin-density-confirm', confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning' })
rowActionId.value = row.id
await deletePlatformPermission(row.id)
await loadPermissions()
@@ -299,26 +299,25 @@ onMounted(loadPermissions)
</DataTable></section>
</ListPageLayout>
<AppDialog v-model="editorOpen" :title="form.id ? '编辑权限资源' : '新增权限资源'" width="min(720px, calc(100vw - 28px))" class="permission-editor-dialog admin-density-dialog iam-density" :confirm-loading="saving" :confirm-text="form.id ? '保存修改' : '保存权限'" :show-confirm="form.id ? canEdit : canCreate" @confirm="savePermission">
<el-form ref="formRef" :model="form" :rules="formRules" label-position="top" class="density-form">
<FormSection class="density-form-section" title="资源定义" description="定义权限名称、编码、类型和层级关系。">
<div class="form-grid two-cols">
<el-form-item label="权限名称" prop="name" required><el-input v-model="form.name" placeholder="用户可理解的中文名称" maxlength="64" /></el-form-item>
<el-form-item label="权限编码" prop="code" required><el-input v-model="form.code" :disabled="Boolean(form.id)" placeholder="如:platform:customer:list" maxlength="128" /></el-form-item>
<el-form-item label="资源类型" prop="type" required><el-select v-model="form.type" :disabled="Boolean(form.id)" @change="handleTypeChange"><el-option v-for="item in availablePermissionTypes" :key="item" :label="item" :value="item" /></el-select></el-form-item>
<el-form-item label="上级资源" prop="parentId" :required="['按钮', '页面', '接口'].includes(form.type)"><el-select v-model="form.parentId" clearable placeholder="作为一级资源"><el-option v-for="item in parentOptions" :key="item.id" :label="`${item.name} (${item.code})`" :value="item.id" /></el-select></el-form-item>
<el-form-item v-if="['菜单', '页面'].includes(form.type)" label="路由路径" prop="path" required><el-input v-model="form.path" placeholder="如:/customers" /></el-form-item>
<el-form-item v-if="form.type === '接口'" label="HTTP 方法" prop="method" required><el-select v-model="form.method"><el-option v-for="method in ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']" :key="method" :label="method" :value="method" /></el-select></el-form-item>
<el-form-item label="显示排序" prop="sort" required><el-input-number v-model="form.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序值" /></el-form-item>
</div>
</FormSection>
<div class="form-callout"><Braces :size="18" /><div><strong>权限编码约定</strong><p>使用稳定的“业务域:资源:动作”编码;资源类型与后端 MENU、PAGE、BUTTON、API 契约一致。</p></div></div>
<AppDialog v-model="editorOpen" :title="editorLabel" width="min(720px, calc(100vw - 28px))" class="permission-editor-dialog admin-density-dialog iam-density" fullscreenable :confirm-loading="saving" :confirm-text="form.id ? '保存修改' : '保存权限'" :show-confirm="form.id ? canEdit : canCreate" @confirm="savePermission">
<el-form ref="formRef" :model="form" :rules="formRules" label-position="left" label-width="100px" class="density-form" :disabled="saving">
<section class="density-dialog-section" data-tone="work" aria-label="权限资源定义">
<h3 class="density-dialog-section__title">资源定义 <InlineHelp title="权限编码约定">使用稳定的“业务域:资源:动作”编码;资源类型与后端 MENU、PAGE、BUTTON、API 契约一致。</InlineHelp></h3>
<table class="density-table density-table--editable permission-editor-table"><tbody>
<tr><td><el-form-item label="权限名称" prop="name" required><el-input v-model="form.name" placeholder="用户可理解的中文名称" maxlength="64" /></el-form-item></td><td><el-form-item label="权限编码" prop="code" required><span v-if="form.id">{{form.code || '—'}}</span><el-input v-else v-model="form.code" placeholder="如:platform:customer:list" maxlength="128" /></el-form-item></td></tr>
<tr><td><el-form-item label="资源类型" prop="type" required><span v-if="form.id">{{form.type}}</span><el-select v-else v-model="form.type" @change="handleTypeChange"><el-option v-for="item in availablePermissionTypes" :key="item" :label="item" :value="item" /></el-select></el-form-item></td><td><el-form-item label="上级资源" prop="parentId" :required="['按钮', '页面', '接口'].includes(form.type)"><el-select v-model="form.parentId" clearable placeholder="作为一级资源"><el-option v-for="item in parentOptions" :key="item.id" :label="`${item.name} (${item.code})`" :value="item.id" /></el-select></el-form-item></td></tr>
<tr v-if="['菜单', '页面'].includes(form.type)"><td colspan="2"><el-form-item label="路由路径" prop="path" required><el-input v-model="form.path" placeholder="如:/customers" /></el-form-item></td></tr>
<tr><td v-if="form.type === '接口'"><el-form-item label="HTTP 方法" prop="method" required><el-select v-model="form.method"><el-option v-for="method in ['GET', 'POST', 'PUT', 'PATCH', 'DELETE']" :key="method" :label="method" :value="method" /></el-select></el-form-item></td><td :colspan="form.type === '接口' ? 1 : 2"><el-form-item label="显示排序" prop="sort" required><el-input-number v-model="form.sort" :min="0" :max="999" controls-position="right" placeholder="请输入排序值" /></el-form-item></td></tr>
</tbody></table>
</section>
</el-form>
</AppDialog>
</AdminPage>
</template>
<style scoped>
.permission-editor-table { table-layout: fixed; }
.permission-editor-table td:not([colspan="2"]) { width: 50%; }
.permission-tree-tools { display: flex; align-items: center; gap: var(--admin-space-6); }
.permission-protection-hint { color: var(--cc-muted); }
.tree-view-actions { display: flex; align-items: center; gap: var(--admin-space-1); white-space: nowrap; }
@@ -328,6 +327,8 @@ onMounted(loadPermissions)
:deep(.danger-menu-item:not(.is-disabled)) { color: var(--el-color-danger); }
@media (max-width: 720px) {
.permission-editor-table tr { display: grid; }
.permission-editor-table td:not([colspan="2"]) { width: auto; }
.permission-tree-tools { width: 100%; align-items: flex-start; flex-direction: column; gap: 8px; }
}