feat: reorganize admin llm settings

This commit is contained in:
2026-08-22 22:06:01 +08:00
parent 78c42eff53
commit f8f0b3c4fd
17 changed files with 1019 additions and 432 deletions
+51 -24
View File
@@ -5,7 +5,7 @@ import { adminAuth } from './auth'
import { DashboardOutlined, SettingOutlined, ControlOutlined, SmileOutlined,
GithubOutlined, PictureOutlined, TeamOutlined, AppstoreOutlined,
NotificationOutlined, SafetyCertificateOutlined, AuditOutlined,
LogoutOutlined } from '@ant-design/icons-vue'
LogoutOutlined, CloudServerOutlined, FundOutlined } from '@ant-design/icons-vue'
const router = useRouter()
const route = useRoute()
@@ -14,20 +14,29 @@ const selectedKeys = ref<string[]>([String(route.name)])
watch(() => route.name, (n) => { selectedKeys.value = [String(n)] })
const nav = computed(() => [
{ key: 'Dashboard', icon: DashboardOutlined, label: '仪表盘' },
{ key: 'Settings', icon: ControlOutlined, label: '系统设置' },
{ key: 'Configs', icon: SettingOutlined, label: '品牌配置' },
{ key: 'SysCategories', icon: AppstoreOutlined, label: '默认分类' },
{ key: 'Personas', icon: SmileOutlined, label: 'AI 性格' },
{ key: 'Avatars', icon: GithubOutlined, label: 'AI 形象' },
{ key: 'Stickers', icon: PictureOutlined, label: '表情包库' },
{ key: 'Users', icon: TeamOutlined, label: '用户管理' },
{ key: 'PushCampaigns', icon: NotificationOutlined, label: '推送管理' },
...(adminAuth.identity.value?.role === 'super_admin' ? [
const navGroups = computed(() => [
{ label: '概览', items: [
{ key: 'Dashboard', icon: DashboardOutlined, label: '仪表盘' },
] },
{ label: 'AI 配置', items: [
{ key: 'ModelService', icon: CloudServerOutlined, label: '模型服务' },
{ key: 'Personas', icon: SmileOutlined, label: 'AI 性格' },
{ key: 'Avatars', icon: GithubOutlined, label: 'AI 形象' },
{ key: 'Stickers', icon: PictureOutlined, label: '表情包库' },
] },
{ label: '产品配置', items: [
{ key: 'ProductBasic', icon: SettingOutlined, label: '品牌与基础设置' },
{ key: 'FeatureLimits', icon: ControlOutlined, label: '功能与额度' },
{ key: 'SysCategories', icon: AppstoreOutlined, label: '默认分类' },
] },
{ label: '运营', items: [
{ key: 'Users', icon: TeamOutlined, label: '用户管理' },
{ key: 'PushCampaigns', icon: NotificationOutlined, label: '推送管理' },
] },
...(adminAuth.identity.value?.role === 'super_admin' ? [{ label: '安全', items: [
{ key: 'AdminAccounts', icon: SafetyCertificateOutlined, label: '管理员账号' },
{ key: 'Audit', icon: AuditOutlined, label: '操作审计' },
] : []),
] }] : []),
])
watch(adminAuth.identity, value => {
@@ -43,20 +52,23 @@ async function logout() {
<template>
<router-view v-if="route.meta.public || route.name === 'ChangePassword'" />
<a-layout v-else style="min-height: 100vh">
<a-layout-sider v-model:collapsed="collapsed" collapsible theme="light" :width="200"
style="border-right: 1px solid #f0f0f0">
<div style="padding: 18px 20px; font-size: 16px; font-weight: 700; white-space: nowrap; overflow: hidden;">
<span style="color:#25211E;margin-right:6px"></span>记之 Admin
<a-layout-sider v-model:collapsed="collapsed" collapsible theme="light" :width="224"
breakpoint="lg" class="app-sider">
<div class="brand-lockup">
<FundOutlined />
<span>记之 Admin</span>
</div>
<a-menu v-model:selectedKeys="selectedKeys" mode="inline" :style="{ borderRight: 0 }"
@click="({key}: {key: string}) => router.push({name: key})">
<a-menu-item v-for="n in nav" :key="n.key">
<component :is="n.icon" />
<span>{{ n.label }}</span>
</a-menu-item>
<a-menu-item-group v-for="group in navGroups" :key="group.label" :title="group.label">
<a-menu-item v-for="item in group.items" :key="item.key">
<component :is="item.icon" />
<span>{{ item.label }}</span>
</a-menu-item>
</a-menu-item-group>
</a-menu>
<div style="position:absolute;bottom:16px;left:16px;right:16px">
<a-button type="text" block style="text-align:left" @click="logout">
<div class="logout-area">
<a-button type="text" block @click="logout">
<template #icon><LogoutOutlined /></template>退出登录
</a-button>
</div>
@@ -68,9 +80,24 @@ async function logout() {
<a-tag>{{ adminAuth.identity.value?.role }}</a-tag>
</a-space>
</a-layout-header>
<a-layout-content style="margin: 18px 20px; padding: 20px; background: #fff; border-radius: 8px; min-height: 360px;">
<a-layout-content class="app-content">
<router-view />
</a-layout-content>
</a-layout>
</a-layout>
</template>
<style scoped>
.app-sider { position: sticky; top: 0; height: 100vh; overflow: auto; border-right: 1px solid #eef0f3; }
.brand-lockup { display: flex; align-items: center; gap: 10px; height: 60px; padding: 0 22px; overflow: hidden; color: #191f26; font-size: 16px; font-weight: 700; white-space: nowrap; }
.brand-lockup :first-child { color: #00a67d; font-size: 20px; }
.logout-area { position: sticky; bottom: 0; padding: 12px 16px 16px; background: #fff; }
.logout-area .ant-btn { text-align: left; }
.app-content { min-height: 360px; margin: 18px 20px; padding: 24px; border-radius: 14px; background: #fff; }
:deep(.ant-menu-item-group-title) { padding: 18px 24px 6px; color: #8b949e; font-size: 11px; font-weight: 600; letter-spacing: .08em; }
:deep(.ant-menu-item) { min-height: 42px; }
:deep(.ant-layout-sider-collapsed .ant-menu-item-group-title) { height: 12px; padding: 6px 0; overflow: hidden; color: transparent; }
@media (max-width: 760px) {
.app-content { margin: 10px; padding: 16px; }
}
</style>