Files
huihuiSquare/digital-avatar-app/src/store/avatar.ts

114 lines
3.4 KiB
TypeScript

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { getAvatarList, createAvatar as apiCreate, deleteAvatar as apiDelete, getTokenBalance, getTokenUsage, getUserProfile } from '@/api'
import { unwrapListData } from '@/utils/avatar-page-data'
export const useAvatarStore = defineStore('avatar', () => {
// 已创建的分身列表(来自后端)
const avatars = ref<any[]>([])
// 当前用户所有分身共享的 Token 账户
const tokenBalance = ref<number>(0)
const tokenConsumed = ref<number>(0)
const tokenUsageByAvatar = ref<Record<string, number>>({})
// 当前选中分身 id
const currentAvatarId = ref<string | null>(null)
// 会会用户资料(头像/昵称,来自会会接口)
const userProfile = ref<any>(null)
// 拉取分身列表
const loadAvatars = async () => {
try {
const res = await getAvatarList()
avatars.value = unwrapListData(res)
if (avatars.value.length) currentAvatarId.value = avatars.value[0].id
} catch (e) {
console.error('加载分身失败', e)
}
}
// 拉取 Token 余额
const loadTokenBalance = async () => {
try {
const res = await getTokenBalance()
tokenBalance.value = (res as any)?.balance ?? 0
tokenConsumed.value = (res as any)?.totalConsumed ?? 0
} catch (e) {
console.error('加载余额失败', e)
}
}
const loadTokenUsage = async () => {
try {
const rows = await getTokenUsage()
tokenUsageByAvatar.value = rows.reduce<Record<string, number>>((result, row) => {
result[row.avatarId] = (result[row.avatarId] || 0) + row.totalTokens
return result
}, {})
} catch (e) {
console.error('加载 Token 用量失败', e)
}
}
// 拉取会会用户资料(头像/昵称)
const loadUserProfile = async () => {
// 若已通过 uniapp 壳注入(混合架构),优先保留,不回退到后端 mock
if (userProfile.value && (userProfile.value as any).__native) return
try {
const res = await getUserProfile()
userProfile.value = res as any
} catch (e) {
console.error('加载用户资料失败', e)
}
}
// 由 uniapp 壳注入的会会资料(混合架构),标记为原生来源
const setNativeProfile = (profile: { userId?: string; nickname?: string; avatarUrl?: string }) => {
userProfile.value = {
userId: profile.userId || '',
nickname: profile.nickname || '',
avatarUrl: profile.avatarUrl || '',
__native: true
}
}
// 创建分身(写入后端)
const addAvatar = async (avatar: any) => {
const res: any = await apiCreate(avatar)
const created = res?.data ? res.data : res
avatars.value.unshift(created)
currentAvatarId.value = created.id
return created
}
// 删除分身(写入后端,级联清理关联数据)
const removeAvatar = async (id: string) => {
await apiDelete(id)
avatars.value = avatars.value.filter((a) => a.id !== id)
if (currentAvatarId.value === id) {
currentAvatarId.value = avatars.value[0]?.id || null
}
}
// 同步余额(充值后)
const setTokenBalance = (balance: number) => {
tokenBalance.value = balance
}
return {
avatars,
tokenBalance,
tokenConsumed,
tokenUsageByAvatar,
currentAvatarId,
userProfile,
loadAvatars,
loadTokenBalance,
loadTokenUsage,
loadUserProfile,
setNativeProfile,
addAvatar,
removeAvatar,
setTokenBalance
}
})