feat(server): 用户管理与变更历史接口;修复 result_revisions.parent_id 从未写入
This commit is contained in:
1 parent
f3813171d3
commit
72462792ec
39 files changed
+10001
-28
No files matched your search
@@ -0,0 +1,90 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import PageHeader from '../components/PageHeader.vue'
|
||||
import UsersPanel from '../components/system/UsersPanel.vue'
|
||||
import BackupPanel from '../components/system/BackupPanel.vue'
|
||||
import EventInfoPanel from '../components/system/EventInfoPanel.vue'
|
||||
import { useAuthStore } from '../stores/auth'
|
||||
import { useEventStore } from '../stores/event'
|
||||
|
||||
/**
|
||||
* 系统页(devdocs/07 第 1 节)。
|
||||
*
|
||||
* 三块内容互相独立,用页签切换而不是塞进一屏:用户管理需要横向空间,
|
||||
* 备份和赛事信息又很少同时改。每个面板各自负责加载态 / 空态 / 错误态。
|
||||
*/
|
||||
|
||||
type TabKey = 'users' | 'backup' | 'event'
|
||||
|
||||
const TABS: ReadonlyArray<{ key: TabKey; label: string }> = [
|
||||
{ key: 'users', label: '用户管理' },
|
||||
{ key: 'backup', label: '备份' },
|
||||
{ key: 'event', label: '赛事信息' },
|
||||
]
|
||||
|
||||
const auth = useAuthStore()
|
||||
const data = useEventStore()
|
||||
|
||||
const activeTab = ref<TabKey>('users')
|
||||
|
||||
const isAdmin = computed(() => auth.user?.role === 'admin')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<PageHeader title="系统" subtitle="用户管理 / 备份恢复 / 赛事信息(devdocs/08 第 2、6 节)" />
|
||||
|
||||
<div class="system-toolbar">
|
||||
<div class="mx-tabs">
|
||||
<button
|
||||
v-for="tab in TABS"
|
||||
:key="tab.key"
|
||||
class="mx-tab"
|
||||
:class="{ active: activeTab === tab.key }"
|
||||
type="button"
|
||||
@click="activeTab = tab.key"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</div>
|
||||
<span class="mx-badge" :class="isAdmin ? 'mx-badge-success' : 'mx-badge-neutral'">
|
||||
{{ isAdmin ? `当前身份:${auth.displayName}` : `只读访客 · ${auth.displayName}` }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<p v-if="!isAdmin" class="role-note">
|
||||
系统配置类接口对 Guest 一律 403(devdocs/08 第 2 节),因此这里的写操作按钮全部禁用;
|
||||
登录管理员账号后即可操作。
|
||||
</p>
|
||||
|
||||
<p v-if="data.error !== null" class="role-note error">数据加载失败:{{ data.error }}</p>
|
||||
|
||||
<UsersPanel v-if="activeTab === 'users'" />
|
||||
<BackupPanel v-else-if="activeTab === 'backup'" />
|
||||
<EventInfoPanel v-else />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.system-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.role-note {
|
||||
font-size: 12px;
|
||||
color: var(--mx-t3);
|
||||
line-height: 1.7;
|
||||
padding: 8px 10px;
|
||||
border-radius: var(--mx-r-xs);
|
||||
background: var(--mx-s3);
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
.role-note.error {
|
||||
color: var(--mx-error);
|
||||
background: rgba(248, 113, 113, 0.1);
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user