feat: add game library CRUD/import/export/favorites/comments, fix team creation
- Game library: add/delete games per group, JSON/CSV import/export, favorites, star ratings & comments - Fix team session creation: add creator to members array, handle null currentGroup - Fix image loading: rename SVG files from .png to .svg extensions - Add PocketBase migrations for game_comments and game_favorites collections - Remove seed data script Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -82,7 +82,7 @@ function confirmCustomGame() {
|
||||
@click="selectGame(game)"
|
||||
>
|
||||
<img
|
||||
:src="game.cover || '/game-placeholder.png'"
|
||||
:src="game.cover || '/game-placeholder.svg'"
|
||||
:alt="game.name"
|
||||
class="game-cover"
|
||||
/>
|
||||
|
||||
@@ -59,7 +59,7 @@ async function inviteMember(userId: string, username: string) {
|
||||
class="member-item"
|
||||
>
|
||||
<img
|
||||
:src="member.avatar || '/default-avatar.png'"
|
||||
:src="member.avatar || '/default-avatar.svg'"
|
||||
:alt="member.username"
|
||||
class="avatar"
|
||||
/>
|
||||
|
||||
@@ -49,7 +49,7 @@ async function rejectInvitation() {
|
||||
<div class="invitation-card">
|
||||
<div class="invitation-header">
|
||||
<img
|
||||
:src="invitation.expand?.from?.avatar || '/default-avatar.png'"
|
||||
:src="invitation.expand?.from?.avatar || '/default-avatar.svg'"
|
||||
:alt="invitation.expand?.from?.username"
|
||||
class="avatar"
|
||||
/>
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
<!-- src/components/team/TeamSessionPanel.vue -->
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { useTeamStore } from '@/stores/team'
|
||||
import { useGroupStore } from '@/stores/group'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { TeamStatusMap } from '@/types'
|
||||
import { ElMessageBox } from 'element-plus'
|
||||
import { ElMessageBox, ElMessage } from 'element-plus'
|
||||
import GameSelectDialog from '@/components/team/GameSelectDialog.vue'
|
||||
|
||||
const teamStore = useTeamStore()
|
||||
const groupStore = useGroupStore()
|
||||
const userStore = useUserStore()
|
||||
|
||||
const session = computed(() => teamStore.currentSession)
|
||||
const statusText = computed(() => session.value ? TeamStatusMap[session.value.status] : '')
|
||||
const showGameSelect = ref(false)
|
||||
|
||||
const memberDetails = computed(() => {
|
||||
if (!session.value) return []
|
||||
@@ -43,6 +47,35 @@ async function endGame() {
|
||||
// 用户取消
|
||||
}
|
||||
}
|
||||
|
||||
async function handleGameSelected(gameName: string) {
|
||||
let group = groupStore.currentGroup
|
||||
if (!group) {
|
||||
if (groupStore.groups.length > 0) {
|
||||
group = groupStore.groups[0]
|
||||
await groupStore.setCurrentGroup(group.id)
|
||||
} else {
|
||||
ElMessage.warning('请先创建或加入一个群组')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (teamStore.currentSession) return
|
||||
|
||||
const userId = userStore.userId
|
||||
try {
|
||||
await teamStore.createSession({
|
||||
sourceGroup: group.id,
|
||||
name: `${gameName} 小队`,
|
||||
gameName,
|
||||
members: [userId]
|
||||
})
|
||||
ElMessage.success('临时小队创建成功!')
|
||||
} catch (error: any) {
|
||||
console.error('创建临时小队失败:', error)
|
||||
ElMessage.error('创建临时小队失败:' + (error.message || '未知错误'))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -66,7 +99,7 @@ async function endGame() {
|
||||
class="member-item"
|
||||
>
|
||||
<img
|
||||
:src="member.avatar || '/default-avatar.png'"
|
||||
:src="member.avatar || '/default-avatar.svg'"
|
||||
:alt="member.username"
|
||||
class="avatar"
|
||||
/>
|
||||
@@ -87,8 +120,13 @@ async function endGame() {
|
||||
</div>
|
||||
|
||||
<div v-else class="no-session">
|
||||
<p>暂未加入任何临时小组</p>
|
||||
<p class="no-session-text">暂未加入任何临时小组</p>
|
||||
<button class="create-team-btn" @click="showGameSelect = true">
|
||||
创建临时小队
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<GameSelectDialog v-model="showGameSelect" @select="handleGameSelected" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
@@ -251,9 +289,30 @@ async function endGame() {
|
||||
background: var(--gg-bg-card);
|
||||
border: 1px solid var(--gg-border);
|
||||
border-radius: var(--gg-radius-md);
|
||||
padding: 48px 32px;
|
||||
padding: 40px 32px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.no-session-text {
|
||||
color: var(--gg-text-muted);
|
||||
font-size: 15px;
|
||||
margin: 0 0 20px;
|
||||
}
|
||||
|
||||
.create-team-btn {
|
||||
padding: 12px 32px;
|
||||
border: none;
|
||||
border-radius: var(--gg-radius-sm);
|
||||
background: var(--gg-gradient-green);
|
||||
color: white;
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: box-shadow 0.3s, transform 0.15s;
|
||||
}
|
||||
|
||||
.create-team-btn:hover {
|
||||
box-shadow: 0 4px 20px rgba(5, 150, 105, 0.3);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user