From 7a0199e685f54edecca4e1bcaf1d339e10599870 Mon Sep 17 00:00:00 2001 From: stefanfeng Date: Tue, 25 Aug 2026 11:44:27 +0800 Subject: [PATCH] feat(avatar): improve multi-avatar management --- digital-avatar-app/src/App.vue | 109 +---- digital-avatar-app/src/router/index.ts | 24 + .../src/utils/avatar-page-data.d.ts | 5 + .../src/utils/avatar-page-data.js | 5 + .../src/views/AuthorizationManage.vue | 9 +- digital-avatar-app/src/views/AvatarManage.vue | 452 +++--------------- .../src/views/KnowledgeManage.vue | 26 +- digital-avatar-app/src/views/QaPairEdit.vue | 12 +- 8 files changed, 125 insertions(+), 517 deletions(-) diff --git a/digital-avatar-app/src/App.vue b/digital-avatar-app/src/App.vue index c54ecb2..c7c6915 100644 --- a/digital-avatar-app/src/App.vue +++ b/digital-avatar-app/src/App.vue @@ -1,73 +1,10 @@ - - diff --git a/digital-avatar-app/src/router/index.ts b/digital-avatar-app/src/router/index.ts index 90d4377..1edac7d 100644 --- a/digital-avatar-app/src/router/index.ts +++ b/digital-avatar-app/src/router/index.ts @@ -45,6 +45,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/AuthorizationManage.vue'), meta: { title: '授权管理', requiresAuth: true } }, + { + path: '/avatar/:avatarId/authorization', + name: 'AvatarAuthorizationManage', + component: () => import('@/views/AuthorizationManage.vue'), + meta: { title: '授权管理', requiresAuth: true } + }, { path: '/token/charge', name: 'TokenCharge', @@ -81,6 +87,12 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/KnowledgeManage.vue'), meta: { title: '知识库管理', requiresAuth: true } }, + { + path: '/avatar/:avatarId/knowledge', + name: 'AvatarKnowledgeManage', + component: () => import('@/views/KnowledgeManage.vue'), + meta: { title: '知识库管理', requiresAuth: true } + }, { path: '/knowledge/qa/create', name: 'QaPairCreate', @@ -93,6 +105,18 @@ const routes: RouteRecordRaw[] = [ component: () => import('@/views/QaPairEdit.vue'), meta: { title: '编辑问答对', requiresAuth: true } }, + { + path: '/avatar/:avatarId/knowledge/qa/create', + name: 'AvatarQaPairCreate', + component: () => import('@/views/QaPairEdit.vue'), + meta: { title: '添加问答对', requiresAuth: true } + }, + { + path: '/avatar/:avatarId/knowledge/qa/:qaId/edit', + name: 'AvatarQaPairEdit', + component: () => import('@/views/QaPairEdit.vue'), + meta: { title: '编辑问答对', requiresAuth: true } + }, { path: '/login/sms', name: 'SmsLogin', diff --git a/digital-avatar-app/src/utils/avatar-page-data.d.ts b/digital-avatar-app/src/utils/avatar-page-data.d.ts index 883f30c..32bdb1f 100644 --- a/digital-avatar-app/src/utils/avatar-page-data.d.ts +++ b/digital-avatar-app/src/utils/avatar-page-data.d.ts @@ -41,5 +41,10 @@ export function pickAvatarId( currentAvatarId: string | null | undefined, avatars?: AvatarPageRecord[] ): string | null +export function pickScopedAvatarId( + routeAvatarId: string | string[] | null | undefined, + currentAvatarId: string | null | undefined, + avatars?: AvatarPageRecord[] +): string | null export function normalizeAvatarEditForm(avatar?: AvatarPageRecord): AvatarEditForm export function buildAvatarUpdatePayload(form: AvatarEditForm): AvatarUpdatePayload diff --git a/digital-avatar-app/src/utils/avatar-page-data.js b/digital-avatar-app/src/utils/avatar-page-data.js index 57be97f..d96fdb9 100644 --- a/digital-avatar-app/src/utils/avatar-page-data.js +++ b/digital-avatar-app/src/utils/avatar-page-data.js @@ -8,6 +8,11 @@ export function pickAvatarId(currentAvatarId, avatars) { return currentAvatarId || avatars?.[0]?.id || null } +export function pickScopedAvatarId(routeAvatarId, currentAvatarId, avatars) { + const requested = Array.isArray(routeAvatarId) ? routeAvatarId[0] : routeAvatarId + return requested ? String(requested) : pickAvatarId(currentAvatarId, avatars) +} + export function normalizeAvatarEditForm(avatar = {}) { const config = avatar.config || {} return { diff --git a/digital-avatar-app/src/views/AuthorizationManage.vue b/digital-avatar-app/src/views/AuthorizationManage.vue index c5095f0..a6510a7 100644 --- a/digital-avatar-app/src/views/AuthorizationManage.vue +++ b/digital-avatar-app/src/views/AuthorizationManage.vue @@ -109,7 +109,7 @@ @@ -234,7 +248,7 @@ onMounted(async () => { .knowledge-page { min-height: 100vh; background: #F8F9FA; - padding-bottom: 80px; + padding-bottom: calc(28px + env(safe-area-inset-bottom)); overflow-x: hidden; } diff --git a/digital-avatar-app/src/views/QaPairEdit.vue b/digital-avatar-app/src/views/QaPairEdit.vue index f9252d3..41161dc 100644 --- a/digital-avatar-app/src/views/QaPairEdit.vue +++ b/digital-avatar-app/src/views/QaPairEdit.vue @@ -49,14 +49,14 @@ import { ref, reactive, computed, onMounted } from 'vue' import { useRouter, useRoute } from 'vue-router' import { useAvatarStore } from '@/store/avatar' -import { pickAvatarId, unwrapListData } from '@/utils/avatar-page-data.js' +import { pickScopedAvatarId, unwrapListData } from '@/utils/avatar-page-data.js' import { getQAPairs, createQAPair, updateQAPair } from '@/api' const router = useRouter() const route = useRoute() const store = useAvatarStore() -const avatarId = computed(() => pickAvatarId(store.currentAvatarId, store.avatars)) +const avatarId = computed(() => pickScopedAvatarId(route.params.avatarId, store.currentAvatarId, store.avatars)) const qaId = computed(() => (route.params.qaId as string) || null) const isEdit = computed(() => !!qaId.value) @@ -104,8 +104,11 @@ const save = async () => { } else { await createQAPair(avatarId.value, payload) } - // 保存成功返回知识库管理页 - router.replace('/knowledge') + if (route.params.avatarId) { + router.replace({ name: 'AvatarKnowledgeManage', params: { avatarId: avatarId.value } }) + } else { + router.replace('/knowledge') + } } catch (e: any) { error.value = e?.message || '保存失败' } finally { @@ -117,6 +120,7 @@ onMounted(async () => { if (!store.avatars.length) { await store.loadAvatars() } + if (avatarId.value) store.currentAvatarId = avatarId.value if (isEdit.value) { await loadForEdit() }