feat: 用户信息完善 + 一起记功能
- users 表添加 nickname、avatar_url 字段 - 用户信息 API(GET/PUT /me)+ 头像上传(multer) - 头像通过 API 路由获取(公开,不经过 auth) - 登录接口返回用户昵称和头像 - 用户信息 Store + 个人资料编辑页面 - 我的页面和首页显示真实用户信息 - 群组表(groups、group_members)+ transactions 添加 group_id - 群组 API(创建/加入/退出/解散) - 交易和统计 API 支持 group_id 视图切换 - 群组客户端 Store + 身份切换 - 群组管理页面 - App 初始化群组 Store - UPLOAD_DIR 配置化 - Node.js 备份替代 mysqldump - 统一前端 BASE_URL(config.ts) - uploads 加入 .gitignore - 修复 trust proxy 警告
This commit is contained in:
52
client/src/stores/user.ts
Normal file
52
client/src/stores/user.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import * as api from '@/api/user'
|
||||
import { API_BASE } from '@/config'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
const userInfo = ref<api.UserInfo | null>(null)
|
||||
const loading = ref(false)
|
||||
|
||||
const nickname = computed(() => {
|
||||
return userInfo.value?.nickname || uni.getStorageSync('xc:nickname') || '小菜'
|
||||
})
|
||||
|
||||
const avatarUrl = computed(() => {
|
||||
const filename = userInfo.value?.avatar_url || uni.getStorageSync('xc:avatar_url') || ''
|
||||
if (!filename) return ''
|
||||
// 已是完整 URL(http/blob)直接返回
|
||||
if (filename.startsWith('http') || filename.startsWith('blob:')) return filename
|
||||
// 拼接:API_BASE + /user/avatar/ + 文件名
|
||||
return `${API_BASE}/user/avatar/${filename}`
|
||||
})
|
||||
|
||||
async function fetchUserInfo() {
|
||||
loading.value = true
|
||||
try {
|
||||
userInfo.value = await api.getUserInfo()
|
||||
if (userInfo.value) {
|
||||
uni.setStorageSync('xc:nickname', userInfo.value.nickname)
|
||||
uni.setStorageSync('xc:avatar_url', userInfo.value.avatar_url)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[UserStore] fetchUserInfo error:', e)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function updateProfile(nickname: string) {
|
||||
await api.updateNickname(nickname)
|
||||
if (userInfo.value) userInfo.value.nickname = nickname
|
||||
uni.setStorageSync('xc:nickname', nickname)
|
||||
}
|
||||
|
||||
async function uploadAvatar(filePath: string) {
|
||||
const result = await api.uploadAvatar(filePath)
|
||||
if (userInfo.value) userInfo.value.avatar_url = result.avatar_url
|
||||
uni.setStorageSync('xc:avatar_url', result.avatar_url)
|
||||
return avatarUrl.value
|
||||
}
|
||||
|
||||
return { userInfo, loading, nickname, avatarUrl, fetchUserInfo, updateProfile, uploadAvatar }
|
||||
})
|
||||
Reference in New Issue
Block a user