feat: add GameGroup2 project with frontend and backend
- Add .gitignore for Node.js and PocketBase projects - Add frontend (Vue 3 + Vite + TypeScript) - Add backend (PocketBase) - Add deployment scripts and Docker compose configs Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
// src/stores/user.ts
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref, computed } from 'vue'
|
||||
import type { User, UserStatus, WorkSchedule } from '@/types'
|
||||
import { pb, getCurrentUser, isAuthenticated, logout as pbLogout } from '@/api/pocketbase'
|
||||
import { getUser, updateUserStatus, updateWorkSchedule } from '@/api/users'
|
||||
|
||||
export const useUserStore = defineStore('user', () => {
|
||||
// 状态
|
||||
const user = ref<User | null>(null)
|
||||
const loading = ref(false)
|
||||
|
||||
// 计算属性
|
||||
const isLoggedIn = computed(() => isAuthenticated() && user.value !== null)
|
||||
const userStatus = computed(() => user.value?.status || 'away')
|
||||
const userId = computed(() => user.value?.id || '')
|
||||
|
||||
// 初始化用户信息
|
||||
async function initUser() {
|
||||
if (!isAuthenticated()) {
|
||||
user.value = null
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
const authUser = getCurrentUser() as User
|
||||
// 获取完整用户信息
|
||||
user.value = await getUser(authUser.id)
|
||||
} catch (error) {
|
||||
console.error('初始化用户信息失败:', error)
|
||||
user.value = null
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 登录
|
||||
async function login(email: string, password: string) {
|
||||
try {
|
||||
loading.value = true
|
||||
await pb.collection('users').authWithPassword(email, password)
|
||||
await initUser()
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || '登录失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 注册
|
||||
async function register(data: { email: string; password: string; passwordConfirm: string; username: string }) {
|
||||
try {
|
||||
loading.value = true
|
||||
await pb.collection('users').create(data)
|
||||
await login(data.email, data.password)
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || '注册失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 登出
|
||||
function logout() {
|
||||
pbLogout()
|
||||
user.value = null
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
async function setStatus(status: UserStatus, note?: string) {
|
||||
try {
|
||||
const updated = await updateUserStatus(status, note)
|
||||
if (user.value) {
|
||||
user.value.status = status
|
||||
user.value.statusNote = note
|
||||
}
|
||||
return updated
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || '更新状态失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 更新工作时间
|
||||
async function setWorkSchedule(schedule: WorkSchedule) {
|
||||
try {
|
||||
const updated = await updateWorkSchedule(schedule)
|
||||
if (user.value) {
|
||||
user.value.workdays = schedule.workdays
|
||||
user.value.workStartTime = schedule.workStartTime
|
||||
user.value.nextWorkTime = updated.nextWorkTime
|
||||
}
|
||||
return updated
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || '更新工作时间失败')
|
||||
}
|
||||
}
|
||||
|
||||
// 检查并自动更新工作时间状态
|
||||
function checkWorkSchedule() {
|
||||
if (!user.value || !user.value.nextWorkTime) return
|
||||
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
if (now >= user.value.nextWorkTime && user.value.status === 'idle') {
|
||||
setStatus('working')
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
user,
|
||||
loading,
|
||||
isLoggedIn,
|
||||
userStatus,
|
||||
userId,
|
||||
initUser,
|
||||
login,
|
||||
register,
|
||||
logout,
|
||||
setStatus,
|
||||
setWorkSchedule,
|
||||
checkWorkSchedule
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user