Files
member-platform/frontend/src/pages/admin/SystemsPage.vue

205 lines
7.3 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>
<div class="flex items-center justify-between mb-6">
<h2 class="text-xl font-bold text-gray-800">系統管理</h2>
<el-button type="primary" @click="showCreateDialog = true" :icon="Plus">新增系統</el-button>
</div>
<el-alert v-if="error" :title="errorMsg" type="error" show-icon :closable="false" class="mb-4" />
<el-skeleton v-if="loading" :rows="4" animated />
<el-table v-else :data="systems" stripe border class="w-full shadow-sm">
<template #empty><el-empty description="目前無系統" /></template>
<el-table-column prop="system_key" label="System Key" width="200" />
<el-table-column prop="name" label="系統名稱" min-width="180" />
<el-table-column prop="idp_client_id" label="Keycloak Client ID" min-width="200" />
<el-table-column prop="status" label="狀態" width="110" />
<el-table-column label="操作" width="280">
<template #default="{ row }">
<el-button size="small" @click="openEdit(row)">編輯</el-button>
<el-button size="small" @click="openRoles(row)">角色</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">刪除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="showCreateDialog" title="新增系統" width="620px" @close="resetCreateForm">
<el-form ref="createFormRef" :model="createForm" :rules="rules" label-width="160px">
<el-form-item label="系統名稱" prop="name"><el-input v-model="createForm.name" /></el-form-item>
<el-form-item label="Keycloak Client ID" prop="idp_client_id"><el-input v-model="createForm.idp_client_id" /></el-form-item>
<el-form-item label="狀態">
<el-select v-model="createForm.status" style="width: 100%">
<el-option label="active" value="active" />
<el-option label="inactive" value="inactive" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="showCreateDialog = false">取消</el-button>
<el-button type="primary" :loading="creating" @click="handleCreate">建立</el-button>
</template>
</el-dialog>
<el-dialog v-model="showEditDialog" title="編輯系統" width="620px" @close="resetEditForm">
<el-form :model="editForm" label-width="160px">
<el-form-item label="System Key"><el-input :model-value="editForm.system_key" disabled /></el-form-item>
<el-form-item label="系統名稱"><el-input v-model="editForm.name" /></el-form-item>
<el-form-item label="Keycloak Client ID"><el-input v-model="editForm.idp_client_id" /></el-form-item>
<el-form-item label="狀態">
<el-select v-model="editForm.status" style="width: 100%">
<el-option label="active" value="active" />
<el-option label="inactive" value="inactive" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="showEditDialog = false">取消</el-button>
<el-button type="primary" :loading="saving" @click="handleEdit">儲存</el-button>
</template>
</el-dialog>
<el-dialog v-model="showRolesDialog" :title="`系統角色:${selectedSystemLabel}`" width="980px">
<el-table :data="systemRoles" border stripe v-loading="rolesLoading">
<template #empty><el-empty description="此系統目前沒有角色" /></template>
<el-table-column prop="role_key" label="Role Key" width="200" />
<el-table-column prop="name" label="角色名稱" min-width="200" />
<el-table-column prop="idp_role_name" label="Keycloak Role" min-width="210" />
<el-table-column prop="status" label="狀態" width="110" />
</el-table>
<template #footer>
<el-button @click="showRolesDialog = false">關閉</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus } from '@element-plus/icons-vue'
import { getSystems, createSystem, updateSystem, deleteSystem, getSystemRoles } from '@/api/systems'
const systems = ref([])
const loading = ref(false)
const error = ref(false)
const errorMsg = ref('')
const showCreateDialog = ref(false)
const showEditDialog = ref(false)
const creating = ref(false)
const saving = ref(false)
const createFormRef = ref()
const createForm = ref({ name: '', idp_client_id: '', status: 'active' })
const editForm = ref({ system_key: '', name: '', idp_client_id: '', status: 'active' })
const rules = {
name: [{ required: true, message: '請輸入系統名稱', trigger: 'blur' }],
idp_client_id: [{ required: true, message: '請輸入 Keycloak Client ID', trigger: 'blur' }]
}
const showRolesDialog = ref(false)
const selectedSystemLabel = ref('')
const systemRoles = ref([])
const rolesLoading = ref(false)
async function load() {
loading.value = true
error.value = false
try {
const res = await getSystems()
systems.value = res.data?.items || []
} catch (err) {
error.value = true
errorMsg.value = err.response?.data?.detail || '載入系統失敗'
} finally {
loading.value = false
}
}
function resetCreateForm() {
createForm.value = { name: '', idp_client_id: '', status: 'active' }
}
function openEdit(row) {
editForm.value = {
system_key: row.system_key,
name: row.name,
idp_client_id: row.idp_client_id,
status: row.status || 'active'
}
showEditDialog.value = true
}
function resetEditForm() {
editForm.value = { system_key: '', name: '', idp_client_id: '', status: 'active' }
}
async function handleCreate() {
const valid = await createFormRef.value.validate().catch(() => false)
if (!valid) return
creating.value = true
try {
await createSystem(createForm.value)
ElMessage.success('新增系統成功')
showCreateDialog.value = false
resetCreateForm()
await load()
} catch (err) {
ElMessage.error(err.response?.data?.detail || '新增系統失敗')
} finally {
creating.value = false
}
}
async function handleEdit() {
saving.value = true
try {
await updateSystem(editForm.value.system_key, {
name: editForm.value.name,
idp_client_id: editForm.value.idp_client_id,
status: editForm.value.status
})
ElMessage.success('更新成功')
showEditDialog.value = false
await load()
} catch (err) {
ElMessage.error(err.response?.data?.detail || '更新系統失敗')
} finally {
saving.value = false
}
}
async function handleDelete(row) {
try {
await ElMessageBox.confirm(
`確認刪除系統 ${row.name}${row.system_key}`,
'刪除確認',
{ type: 'warning' }
)
await deleteSystem(row.system_key)
ElMessage.success('刪除成功')
await load()
} catch (err) {
if (err === 'cancel') return
ElMessage.error(err.response?.data?.detail || '刪除系統失敗')
}
}
async function openRoles(row) {
selectedSystemLabel.value = `${row.name} (${row.system_key})`
showRolesDialog.value = true
rolesLoading.value = true
try {
const res = await getSystemRoles(row.system_key)
systemRoles.value = res.data?.roles || []
} catch (_err) {
ElMessage.error('載入系統角色失敗')
systemRoles.value = []
} finally {
rolesLoading.value = false
}
}
onMounted(load)
</script>