fix(join-group): redirect unauthenticated users to login + docs update
- JoinGroupPage: redirect to login when user is not authenticated - CLAUDE.md: add env details, path alias, and coding constraints Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ Game Group V2 — 游戏组队管理平台。用户创建/加入群组,组队
|
||||
## 开发命令
|
||||
|
||||
```bash
|
||||
# 构建前端
|
||||
# 构建前端(先 vue-tsc 类型检查,再 vite build。类型错误会阻断构建)
|
||||
# 注意:npm run build 默认加载 .env.dev 的变量。Docker 构建时通过 ARG 注入空 VITE_PB_URL,由 nginx 代理处理
|
||||
# 如需本地测试 UAT 构建设置,使用:cd frontend && npm run build -- --mode uat
|
||||
cd frontend && npm run build
|
||||
@@ -63,7 +63,7 @@ docker logs -f gamegroup-frontend-uat # UAT 前端
|
||||
|
||||
Docker Compose 文件:`docker-compose.dev.yml`(Dev 全套)、`docker-compose.uat.yml`(UAT 全套),共享 `gamegroup-net` 网络。每个环境独立运行完整的 PB + LiveKit + Voice Token + 前端服务。
|
||||
|
||||
前端 `.env` 文件:`frontend/.env.dev`(VITE_PB_URL=8711, PORT=7033)和 `frontend/.env.uat`(VITE_PB_URL=8711, PORT=7034)。注意 Dev/UAT 构建时 VITE_PB_URL 都指向 8711,因为 Docker 构建时会将其覆盖为空,由 nginx 反向代理处理。
|
||||
前端 `.env` 文件:`frontend/.env.dev` 和 `frontend/.env.uat`。每个 env 包含四个变量:`VITE_PB_URL`(PocketBase 地址)、`VITE_PORT`(dev server 端口)、`VITE_LIVEKIT_URL`(LiveKit WebSocket 地址)、`VITE_VOICE_TOKEN_URL`(Voice Token 服务地址)。Docker 构建时 `VITE_PB_URL` 被覆盖为空,由 nginx 反向代理处理。
|
||||
|
||||
## 架构
|
||||
|
||||
@@ -78,11 +78,12 @@ pocketbase.ts (PB 客户端初始化)
|
||||
```
|
||||
|
||||
- **`api/pocketbase.ts`** — 单例 PocketBase 客户端,导出 `pb`、`getCurrentUser()`、`isAuthenticated()`、`logout()`
|
||||
- **`api/`** — 每个领域一个文件(`users.ts`, `groups.ts`, `sessions.ts`, `invitations.ts`, `games.ts`, `polls.ts`, `bets.ts`, `points.ts`, `ledgers.ts`, `assets.ts`, `memories.ts`, `notifications.ts`, `gameBlacklist.ts`, `playerBlacklist.ts`, `voice.ts`, `bulletins.ts`)
|
||||
- **`stores/`** — Pinia stores,组合式 API 风格(`defineStore('name', () => {...})`)
|
||||
- **`api/`** — 每个领域一个文件(`users.ts`, `groups.ts`, `sessions.ts`, `invitations.ts`, `games.ts`, `polls.ts`, `bets.ts`, `points.ts`, `ledgers.ts`, `assets.ts`, `memories.ts`, `notifications.ts`, `gameBlacklist.ts`, `playerBlacklist.ts`, `voice.ts`, `bulletins.ts`, `events.ts`)
|
||||
- **`stores/`** — Pinia stores,组合式 API 风格(`defineStore('name', () => {...})`)。共 11 个 store(user/group/team/event/poll/ledger/asset/memory/notification/bulletin),`index.ts` 仅导出前 3 个,其余直接从文件导入
|
||||
- **`composables/useRealtime.ts`** — 统一管理 PocketBase 实时订阅,组件卸载时自动清理
|
||||
- **`composables/useVoiceRoom.ts`** — LiveKit 语音房间封装,处理连接/断开/麦克风/扬声器控制
|
||||
- **`types/index.ts`** — 所有接口集中定义 + `displayName()` 工具函数 + 状态映射常量(如 `UserStatusMap`、`TeamStatusMap`)
|
||||
- **路径别名**: `@/` 映射到 `src/`,在 `vite.config.ts` 和 `tsconfig.json` 中配置
|
||||
|
||||
### 认证流程
|
||||
|
||||
@@ -92,7 +93,7 @@ pocketbase.ts (PB 客户端初始化)
|
||||
|
||||
### 路由结构
|
||||
|
||||
Layout (`/`) 下所有认证页面为子路由:Home, GroupView (`/group/:id`), LedgerView (`/group/:groupId/ledger`), AssetView (`/group/:groupId/assets`), BlacklistView (`/group/:groupId/blacklist`), VoiceRoom (`/group/:groupId/voice/:sessionId`), GamesLibrary, Profile, Settings, Changelog。Login/Register 为独立路由。
|
||||
Layout (`/`) 下所有认证页面为子路由:Home, GroupView (`/group/:id`), LedgerView (`/group/:groupId/ledger`), AssetView (`/group/:groupId/assets`), BlacklistView (`/group/:groupId/blacklist`), VoiceRoom (`/group/:groupId/voice/:sessionId`), GamesLibrary, Profile, Settings, Changelog。Login/Register 为独立路由。JoinGroup (`/join/group/:groupId`) 和 JoinTeam (`/join/team/:sessionId`) 为无需认证的独立页面,用于外部邀请链接。
|
||||
|
||||
### Vite 代理 vs Nginx
|
||||
|
||||
@@ -148,5 +149,10 @@ HTTP 环境下 `navigator.mediaDevices` 受限,已在 `useVoiceRoom.ts` 中给
|
||||
- Auth collection 的 `email` 字段不对未认证请求暴露,登录查找用 `username` 替代
|
||||
- 数据迁移在 `backend/pb_migrations/`,由管理面板操作自动生成。**不要**为 `username` 等系统字段创建 `addField` 迁移,会导致 `duplicate column` 错误
|
||||
- PocketBase 管理面板:`admin@example.com` / `admin123456`
|
||||
- 前端 `.env` 文件:`VITE_PB_URL` 配置后端地址,`VITE_PORT` 配置开发端口
|
||||
- API 调用添加 `$autoCancel: false` 避免 PocketBase SDK 自动取消请求
|
||||
|
||||
## 编码约束
|
||||
|
||||
- **TypeScript 严格模式**: `strict: true` + `noUnusedLocals` + `noUnusedParameters`,未使用的变量/参数会导致构建失败
|
||||
- **无测试框架**: 项目当前没有测试文件和测试配置,不要尝试运行测试
|
||||
- **无 Linter 配置**: 没有 ESLint/Prettier 配置文件
|
||||
|
||||
@@ -19,7 +19,7 @@ const error = ref('')
|
||||
|
||||
const groupId = route.params.groupId as string
|
||||
|
||||
onMounted(async () => {
|
||||
async function loadGroup() {
|
||||
try {
|
||||
group.value = await getGroup(groupId)
|
||||
} catch {
|
||||
@@ -27,6 +27,14 @@ onMounted(async () => {
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (!isAuthenticated()) {
|
||||
router.replace({ name: 'Login', query: { redirect: route.fullPath } })
|
||||
return
|
||||
}
|
||||
await loadGroup()
|
||||
})
|
||||
|
||||
function goToLogin() {
|
||||
|
||||
Reference in New Issue
Block a user