feat:實作 Member Portal MVP 前端與後端整合

後端:
- 新增 DivingOffer Model / DivingOfferController(列表+詳情 API,支援搜尋/篩選/分頁)
- 修正 Google OAuth callback 改為 redirect 至前端(SocialAuthController)
- 新增 config/cors.php 允許前端 origin
- .gitignore 新增 frontend/ 排除規則

前端(frontend/):
- Vue 3 + Vite + Tailwind CSS + Pinia + Vue Router
- 頁面:首頁、課程列表、課程詳情、登入、註冊、個人資料、OAuth callback
- 整合至 Docker(multi-stage build,nginx 靜態服務於 port 5173)

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-10 01:41:28 +08:00
parent 725c86f434
commit 550e2fc97a
48 changed files with 5887 additions and 17 deletions
+39
View File
@@ -0,0 +1,39 @@
<script setup>
import { onMounted } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useAuthStore } from '../stores/auth'
import api from '../api/axios'
const router = useRouter()
const route = useRoute()
const auth = useAuthStore()
onMounted(async () => {
const token = route.query.token
const error = route.query.error
if (error || !token) {
router.push('/login?error=oauth_failed')
return
}
// 存 token 先,再拉 profile
localStorage.setItem('token', token)
try {
const res = await api.get('/member/profile')
auth.setAuth(res.data.data, token)
} catch {
auth.setAuth(null, token)
}
// 清除 URL 上的 token
history.replaceState({}, '', '/auth/callback')
router.push('/courses')
})
</script>
<template>
<main class="min-h-[80vh] flex items-center justify-center text-gray-400">
正在完成登入請稍候...
</main>
</template>