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

225 lines
7.6 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="showDialog = 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="status" label="狀態" width="120" />
<el-table-column label="操作" width="260">
<template #default="{ row }">
<el-button size="small" @click="openEdit(row)">編輯</el-button>
<el-button size="small" @click="openRelations(row, 'groups')">群組</el-button>
<el-button size="small" @click="openRelations(row, 'members')">會員</el-button>
<el-button size="small" type="danger" @click="handleDelete(row)">刪除</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog v-model="showDialog" title="新增系統" @close="resetForm">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-form-item label="名稱" prop="name">
<el-input v-model="form.name" placeholder="行銷平台" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="showDialog = false">取消</el-button>
<el-button type="primary" :loading="submitting" @click="handleCreate">確認</el-button>
</template>
</el-dialog>
<el-dialog v-model="showEditDialog" title="編輯系統" @close="resetEditForm">
<el-form :model="editForm" label-width="100px">
<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="狀態">
<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="savingEdit" @click="handleEdit">儲存</el-button>
</template>
</el-dialog>
<el-dialog v-model="showRelationDialog" :title="`系統關聯:${relationSystemKey}`" width="900px">
<el-tabs v-model="relationTab">
<el-tab-pane label="所屬群組" name="groups">
<el-table :data="relationGroups" border stripe v-loading="relationLoading">
<template #empty><el-empty description="尚無關聯群組" /></template>
<el-table-column prop="group_key" label="Group Key" width="220" />
<el-table-column prop="group_name" label="名稱" min-width="220" />
<el-table-column prop="status" label="狀態" width="120" />
</el-table>
</el-tab-pane>
<el-tab-pane label="涉及會員" name="members">
<el-table :data="relationMembers" border stripe v-loading="relationLoading">
<template #empty><el-empty description="尚無關聯會員" /></template>
<el-table-column prop="authentik_sub" label="Authentik Sub" min-width="260" />
<el-table-column prop="email" label="Email" min-width="220" />
<el-table-column prop="display_name" label="顯示名稱" min-width="160" />
<el-table-column label="啟用" width="80">
<template #default="{ row }">{{ row.is_active ? '是' : '否' }}</template>
</el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="showRelationDialog = 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, getSystemGroups, getSystemMembers } from '@/api/systems'
const systems = ref([])
const loading = ref(false)
const error = ref(false)
const errorMsg = ref('')
const showDialog = ref(false)
const submitting = ref(false)
const formRef = ref()
const showEditDialog = ref(false)
const savingEdit = ref(false)
const form = ref({ name: '' })
const editForm = ref({ system_key: '', name: '', status: 'active' })
const rules = {
name: [{ required: true, message: '請輸入名稱', trigger: 'blur' }]
}
const showRelationDialog = ref(false)
const relationLoading = ref(false)
const relationSystemKey = ref('')
const relationTab = ref('groups')
const relationGroups = ref([])
const relationMembers = ref([])
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?.status === 422
? '缺少管理員 API 認證,請檢查前端 .env.development'
: '載入失敗,請稍後再試'
} finally {
loading.value = false
}
}
function resetForm() {
form.value = { name: '' }
}
function openEdit(row) {
editForm.value = {
system_key: row.system_key,
name: row.name,
status: row.status || 'active'
}
showEditDialog.value = true
}
function resetEditForm() {
editForm.value = { system_key: '', name: '', status: 'active' }
}
async function handleCreate() {
const valid = await formRef.value.validate().catch(() => false)
if (!valid) return
submitting.value = true
try {
const res = await createSystem(form.value)
ElMessage.success(`新增成功:${res.data?.system_key || ''}`)
showDialog.value = false
resetForm()
await load()
} catch (err) {
ElMessage.error('新增失敗,請稍後再試')
} finally {
submitting.value = false
}
}
async function handleEdit() {
savingEdit.value = true
try {
await updateSystem(editForm.value.system_key, {
name: editForm.value.name,
status: editForm.value.status
})
ElMessage.success('更新成功')
showEditDialog.value = false
await load()
} catch (err) {
ElMessage.error('更新失敗')
} finally {
savingEdit.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 openRelations(row, tab) {
relationSystemKey.value = row.system_key
relationTab.value = tab
showRelationDialog.value = true
relationLoading.value = true
try {
const [groupsRes, membersRes] = await Promise.all([
getSystemGroups(row.system_key),
getSystemMembers(row.system_key)
])
relationGroups.value = groupsRes.data?.items || []
relationMembers.value = membersRes.data?.items || []
} catch (err) {
ElMessage.error('載入系統關聯資料失敗')
} finally {
relationLoading.value = false
}
}
onMounted(load)
</script>