114 lines
3.4 KiB
TypeScript
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
|
|
}
|
|
})
|