From 0582b00f5f3a3f2405f3a80e4b004c43bd784379 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 30 Mar 2026 03:25:53 +0800 Subject: [PATCH] feat(admin): add edit flows for all catalogs and member authentik sync --- src/api/companies.js | 1 + src/api/members.js | 2 + src/api/modules.js | 1 + src/api/permission-groups.js | 1 + src/api/sites.js | 1 + src/api/systems.js | 1 + src/pages/admin/CompaniesPage.vue | 76 ++++++--- src/pages/admin/MembersPage.vue | 157 ++++++++++++++++-- src/pages/admin/ModulesPage.vue | 67 +++++++- src/pages/admin/PermissionGroupsPage.vue | 143 +++++++++++++++- src/pages/admin/SitesPage.vue | 109 +++++++++--- src/pages/admin/SystemsPage.vue | 63 ++++++- src/pages/permissions/PermissionAdminPage.vue | 122 ++++++++++++-- 13 files changed, 659 insertions(+), 85 deletions(-) diff --git a/src/api/companies.js b/src/api/companies.js index c62607a..9411dd3 100644 --- a/src/api/companies.js +++ b/src/api/companies.js @@ -2,3 +2,4 @@ import { adminHttp } from './http' export const getCompanies = () => adminHttp.get('/admin/companies') export const createCompany = (data) => adminHttp.post('/admin/companies', data) +export const updateCompany = (companyKey, data) => adminHttp.patch(`/admin/companies/${companyKey}`, data) diff --git a/src/api/members.js b/src/api/members.js index 7a10123..99c1c2f 100644 --- a/src/api/members.js +++ b/src/api/members.js @@ -1,3 +1,5 @@ import { adminHttp } from './http' export const getMembers = () => adminHttp.get('/admin/members') +export const upsertMember = (data) => adminHttp.post('/admin/members/upsert', data) +export const updateMember = (authentikSub, data) => adminHttp.patch(`/admin/members/${authentikSub}`, data) diff --git a/src/api/modules.js b/src/api/modules.js index f54f398..3d0ba34 100644 --- a/src/api/modules.js +++ b/src/api/modules.js @@ -2,3 +2,4 @@ import { adminHttp } from './http' export const getModules = () => adminHttp.get('/admin/modules') export const createModule = (data) => adminHttp.post('/admin/modules', data) +export const updateModule = (moduleKey, data) => adminHttp.patch(`/admin/modules/${moduleKey}`, data) diff --git a/src/api/permission-groups.js b/src/api/permission-groups.js index 3ebf8ea..a78e317 100644 --- a/src/api/permission-groups.js +++ b/src/api/permission-groups.js @@ -2,6 +2,7 @@ import { adminHttp } from './http' export const getPermissionGroups = () => adminHttp.get('/admin/permission-groups') export const createPermissionGroup = (data) => adminHttp.post('/admin/permission-groups', data) +export const updatePermissionGroup = (groupKey, data) => adminHttp.patch(`/admin/permission-groups/${groupKey}`, data) export const addMemberToGroup = (groupKey, authentikSub) => adminHttp.post(`/admin/permission-groups/${groupKey}/members/${authentikSub}`) diff --git a/src/api/sites.js b/src/api/sites.js index 674bddf..7cfa055 100644 --- a/src/api/sites.js +++ b/src/api/sites.js @@ -2,3 +2,4 @@ import { adminHttp } from './http' export const getSites = () => adminHttp.get('/admin/sites') export const createSite = (data) => adminHttp.post('/admin/sites', data) +export const updateSite = (siteKey, data) => adminHttp.patch(`/admin/sites/${siteKey}`, data) diff --git a/src/api/systems.js b/src/api/systems.js index 6d90cd7..90cac1a 100644 --- a/src/api/systems.js +++ b/src/api/systems.js @@ -2,3 +2,4 @@ import { adminHttp } from './http' export const getSystems = () => adminHttp.get('/admin/systems') export const createSystem = (data) => adminHttp.post('/admin/systems', data) +export const updateSystem = (systemKey, data) => adminHttp.patch(`/admin/systems/${systemKey}`, data) diff --git a/src/pages/admin/CompaniesPage.vue b/src/pages/admin/CompaniesPage.vue index 167ed8f..5eca360 100644 --- a/src/pages/admin/CompaniesPage.vue +++ b/src/pages/admin/CompaniesPage.vue @@ -5,38 +5,48 @@ 新增公司 - - + - - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + @@ -44,7 +54,7 @@ import { ref, onMounted } from 'vue' import { ElMessage } from 'element-plus' import { Plus } from '@element-plus/icons-vue' -import { getCompanies, createCompany } from '@/api/companies' +import { getCompanies, createCompany, updateCompany } from '@/api/companies' const companies = ref([]) const loading = ref(false) @@ -52,9 +62,12 @@ const error = ref(false) const errorMsg = ref('') const showDialog = ref(false) const submitting = ref(false) +const showEditDialog = ref(false) +const savingEdit = ref(false) const formRef = ref() const form = ref({ company_key: '', name: '' }) +const editForm = ref({ company_key: '', name: '', status: 'active' }) const rules = { company_key: [{ required: true, message: '請輸入 Company Key', trigger: 'blur' }], name: [{ required: true, message: '請輸入名稱', trigger: 'blur' }] @@ -80,6 +93,15 @@ function resetForm() { form.value = { company_key: '', name: '' } } +function openEdit(row) { + editForm.value = { company_key: row.company_key, name: row.name, status: row.status || 'active' } + showEditDialog.value = true +} + +function resetEditForm() { + editForm.value = { company_key: '', name: '', status: 'active' } +} + async function handleCreate() { const valid = await formRef.value.validate().catch(() => false) if (!valid) return @@ -91,11 +113,25 @@ async function handleCreate() { resetForm() await load() } catch (err) { - ElMessage.error('新增失敗,請稍後再試') + ElMessage.error('新增失敗') } finally { submitting.value = false } } +async function handleEdit() { + savingEdit.value = true + try { + await updateCompany(editForm.value.company_key, { name: editForm.value.name, status: editForm.value.status }) + ElMessage.success('更新成功') + showEditDialog.value = false + await load() + } catch (err) { + ElMessage.error('更新失敗') + } finally { + savingEdit.value = false + } +} + onMounted(load) diff --git a/src/pages/admin/MembersPage.vue b/src/pages/admin/MembersPage.vue index ac0f18b..f98a0ef 100644 --- a/src/pages/admin/MembersPage.vue +++ b/src/pages/admin/MembersPage.vue @@ -2,39 +2,95 @@

會員列表

- 重新整理 +
+ 新增會員 + 重新整理 +
- - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/pages/admin/ModulesPage.vue b/src/pages/admin/ModulesPage.vue index 379952b..8a5aff0 100644 --- a/src/pages/admin/ModulesPage.vue +++ b/src/pages/admin/ModulesPage.vue @@ -18,12 +18,17 @@ - - + + + + + + - @@ -41,6 +46,27 @@ 確認 + + + + + + + + + + + + + + + + + + @@ -48,7 +74,7 @@ import { ref, onMounted } from 'vue' import { ElMessage } from 'element-plus' import { Plus } from '@element-plus/icons-vue' -import { getModules, createModule } from '@/api/modules' +import { getModules, createModule, updateModule } from '@/api/modules' const modules = ref([]) const loading = ref(false) @@ -57,8 +83,11 @@ 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({ system_key: '', module_key: '', name: '' }) +const editForm = ref({ module_key: '', name: '', status: 'active' }) const rules = { system_key: [{ required: true, message: '請輸入 System Key', trigger: 'blur' }], module_key: [{ required: true, message: '請輸入 Module Key', trigger: 'blur' }], @@ -85,6 +114,19 @@ function resetForm() { form.value = { system_key: '', module_key: '', name: '' } } +function openEdit(row) { + editForm.value = { + module_key: row.module_key, + name: row.name, + status: row.status || 'active' + } + showEditDialog.value = true +} + +function resetEditForm() { + editForm.value = { module_key: '', name: '', status: 'active' } +} + async function handleCreate() { const valid = await formRef.value.validate().catch(() => false) if (!valid) return @@ -102,5 +144,22 @@ async function handleCreate() { } } +async function handleEdit() { + savingEdit.value = true + try { + await updateModule(editForm.value.module_key, { + name: editForm.value.name, + status: editForm.value.status + }) + ElMessage.success('更新成功') + showEditDialog.value = false + await load() + } catch (err) { + ElMessage.error('更新失敗') + } finally { + savingEdit.value = false + } +} + onMounted(load) diff --git a/src/pages/admin/PermissionGroupsPage.vue b/src/pages/admin/PermissionGroupsPage.vue index c6b1f1f..39cd342 100644 --- a/src/pages/admin/PermissionGroupsPage.vue +++ b/src/pages/admin/PermissionGroupsPage.vue @@ -16,6 +16,12 @@ + + + + @@ -60,16 +66,34 @@ - + + + - + + + - + + + - + + + 確認 + + + + + + + + + + + + + + + + + + diff --git a/src/pages/admin/SitesPage.vue b/src/pages/admin/SitesPage.vue index ce939d9..3a5b3cc 100644 --- a/src/pages/admin/SitesPage.vue +++ b/src/pages/admin/SitesPage.vue @@ -5,42 +5,59 @@ 新增站台 - - + - - + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -48,29 +65,39 @@ import { ref, onMounted } from 'vue' import { ElMessage } from 'element-plus' import { Plus } from '@element-plus/icons-vue' -import { getSites, createSite } from '@/api/sites' +import { getSites, createSite, updateSite } from '@/api/sites' +import { getCompanies } from '@/api/companies' const sites = ref([]) +const companies = ref([]) const loading = ref(false) const error = ref(false) const errorMsg = ref('') const showDialog = ref(false) const submitting = ref(false) +const showEditDialog = ref(false) +const savingEdit = ref(false) const formRef = ref() const form = ref({ site_key: '', company_key: '', name: '' }) +const editForm = ref({ site_key: '', company_key: '', name: '', status: 'active' }) const rules = { site_key: [{ required: true, message: '請輸入 Site Key', trigger: 'blur' }], - company_key: [{ required: true, message: '請輸入 Company Key', trigger: 'blur' }], + company_key: [{ required: true, message: '請選擇公司', trigger: 'change' }], name: [{ required: true, message: '請輸入名稱', trigger: 'blur' }] } +async function loadCompanies() { + const res = await getCompanies() + companies.value = res.data?.items || [] +} + async function load() { loading.value = true error.value = false try { - const res = await getSites() - sites.value = res.data?.items || [] + const [sitesRes] = await Promise.all([getSites(), loadCompanies()]) + sites.value = sitesRes.data?.items || [] } catch (err) { error.value = true errorMsg.value = err.response?.status === 422 @@ -85,6 +112,20 @@ function resetForm() { form.value = { site_key: '', company_key: '', name: '' } } +function openEdit(row) { + editForm.value = { + site_key: row.site_key, + company_key: row.company_key, + name: row.name, + status: row.status || 'active' + } + showEditDialog.value = true +} + +function resetEditForm() { + editForm.value = { site_key: '', company_key: '', name: '', status: 'active' } +} + async function handleCreate() { const valid = await formRef.value.validate().catch(() => false) if (!valid) return @@ -96,11 +137,29 @@ async function handleCreate() { resetForm() await load() } catch (err) { - ElMessage.error('新增失敗,請稍後再試') + ElMessage.error('新增失敗') } finally { submitting.value = false } } +async function handleEdit() { + savingEdit.value = true + try { + await updateSite(editForm.value.site_key, { + company_key: editForm.value.company_key, + name: editForm.value.name, + status: editForm.value.status + }) + ElMessage.success('更新成功') + showEditDialog.value = false + await load() + } catch (err) { + ElMessage.error('更新失敗') + } finally { + savingEdit.value = false + } +} + onMounted(load) diff --git a/src/pages/admin/SystemsPage.vue b/src/pages/admin/SystemsPage.vue index d6755e6..eb95512 100644 --- a/src/pages/admin/SystemsPage.vue +++ b/src/pages/admin/SystemsPage.vue @@ -20,9 +20,14 @@ + + + + - @@ -37,6 +42,27 @@ 確認 + + + + + + + + + + + + + + + + + + @@ -44,7 +70,7 @@ import { ref, onMounted } from 'vue' import { ElMessage } from 'element-plus' import { Plus } from '@element-plus/icons-vue' -import { getSystems, createSystem } from '@/api/systems' +import { getSystems, createSystem, updateSystem } from '@/api/systems' const systems = ref([]) const loading = ref(false) @@ -53,8 +79,11 @@ 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({ system_key: '', name: '' }) +const editForm = ref({ system_key: '', name: '', status: 'active' }) const rules = { system_key: [{ required: true, message: '請輸入 System Key', trigger: 'blur' }], name: [{ required: true, message: '請輸入名稱', trigger: 'blur' }] @@ -80,6 +109,19 @@ function resetForm() { form.value = { system_key: '', 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 @@ -97,5 +139,22 @@ async function handleCreate() { } } +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 + } +} + onMounted(load) diff --git a/src/pages/permissions/PermissionAdminPage.vue b/src/pages/permissions/PermissionAdminPage.vue index 19d16ef..1710cfd 100644 --- a/src/pages/permissions/PermissionAdminPage.vue +++ b/src/pages/permissions/PermissionAdminPage.vue @@ -15,7 +15,9 @@ @submit.prevent="handleGrant" > - + + + @@ -30,16 +32,24 @@ - + + + - + + + - + + + - + + + - + + + @@ -92,16 +104,24 @@ - + + + - + + + - + + + - + + +