refactor: Fix UI/UX issues across admin pages

- App.vue: max-w-4xl → max-w-6xl(讓表格不被截斷)
- 新增 AdminCredsCard.vue 共用元件,消除兩個頁面的重複認證卡片
- PermissionAdminPage / PermissionGroupsPage 改用 AdminCredsCard
- 所有 el-table 的 slot="empty" 換成 <template #empty>(Vue 3 正確用法)
- 4 個管理頁 Dialog 補 el-form rules + formRef.validate()(取代手動 if 檢查)
- MembersPage: authentik_sub / email 欄位加 show-overflow-tooltip
- PermissionGroupsPage: 成功/失敗訊息由 <p> 改為 el-alert(統一樣式)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Chris
2026-03-30 02:53:54 +08:00
parent e325642b5e
commit f3d5937d37
9 changed files with 125 additions and 143 deletions

View File

@@ -2,28 +2,7 @@
<div>
<h2 class="text-xl font-bold text-gray-800 mb-6">權限群組管理</h2>
<!-- 認證 -->
<el-card class="mb-6 shadow-sm">
<template #header>
<div class="flex items-center justify-between">
<span class="font-medium text-gray-700">管理員認證</span>
<el-tag v-if="credsSaved" type="success" size="small">已儲存session</el-tag>
<el-tag v-else type="warning" size="small">未設定</el-tag>
</div>
</template>
<el-form :model="credsForm" inline>
<el-form-item label="X-Client-Key">
<el-input v-model="credsForm.clientKey" placeholder="client key" style="width: 220px" show-password />
</el-form-item>
<el-form-item label="X-API-Key">
<el-input v-model="credsForm.apiKey" placeholder="api key" style="width: 220px" show-password />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveCreds">儲存認證</el-button>
<el-button v-if="credsSaved" @click="clearCreds" class="ml-2">清除</el-button>
</el-form-item>
</el-form>
</el-card>
<AdminCredsCard />
<el-tabs v-model="activeTab" type="border-card" class="shadow-sm">
<!-- Groups Tab -->
@@ -37,7 +16,7 @@
<el-skeleton v-if="loadingGroups" :rows="4" animated />
<el-table v-else :data="groups" stripe border class="w-full">
<el-empty v-if="groups.length === 0" slot="empty" description="目前無群組" />
<template #empty><el-empty description="目前無群組" /></template>
<el-table-column prop="group_key" label="Group Key" width="180" />
<el-table-column prop="name" label="群組名稱" min-width="200" />
</el-table>
@@ -63,8 +42,8 @@
</el-form-item>
</el-form>
<p v-if="memberError" class="text-red-600 text-sm mb-2">{{ memberError }}</p>
<p v-if="memberSuccess" class="text-green-600 text-sm mb-2">{{ memberSuccess }}</p>
<el-alert v-if="memberError" :title="memberError" type="error" show-icon :closable="false" class="mt-3" />
<el-alert v-if="memberSuccess" :title="memberSuccess" type="success" show-icon :closable="false" class="mt-3" />
</div>
</el-tab-pane>
@@ -116,8 +95,8 @@
</el-form-item>
</el-form>
<p v-if="groupPermError" class="text-red-600 text-sm mb-2">{{ groupPermError }}</p>
<p v-if="groupPermSuccess" class="text-green-600 text-sm mb-2">{{ groupPermSuccess }}</p>
<el-alert v-if="groupPermError" :title="groupPermError" type="error" show-icon :closable="false" class="mt-3" />
<el-alert v-if="groupPermSuccess" :title="groupPermSuccess" type="success" show-icon :closable="false" class="mt-3" />
</div>
</el-tab-pane>
</el-tabs>
@@ -152,34 +131,12 @@ import {
groupGrant,
groupRevoke
} from '@/api/permission-groups'
import AdminCredsCard from '@/components/AdminCredsCard.vue'
const permissionStore = usePermissionStore()
const activeTab = ref('groups')
// 認證
const credsForm = reactive({
clientKey: permissionStore.adminClientKey,
apiKey: permissionStore.adminApiKey
})
const credsSaved = computed(() => permissionStore.hasAdminCreds())
function saveCreds() {
if (!credsForm.clientKey || !credsForm.apiKey) {
ElMessage.warning('請填寫完整認證')
return
}
permissionStore.setAdminCreds(credsForm.clientKey, credsForm.apiKey)
ElMessage.success('認證已儲存session')
}
function clearCreds() {
permissionStore.clearAdminCreds()
credsForm.clientKey = ''
credsForm.apiKey = ''
ElMessage.info('認證已清除')
}
// Groups
const groups = ref([])
const loadingGroups = ref(false)