From bea7d88f0cd57890528fdc0c697062cc1cf5d991 Mon Sep 17 00:00:00 2001 From: skytek_xinliang Date: Mon, 31 Aug 2026 10:43:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BB=BA=E8=AD=B0=E8=AA=B2=E7=A8=8B?= =?UTF-8?q?=E5=89=8D=E9=9C=80=E8=A6=81=E5=88=86=E7=B5=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/citizen-frontend/src/api/course.ts | 4 +- .../src/components/layout/DefaultLayout.vue | 3 + .../src/pages/appointment.vue | 26 + app/citizen-frontend/src/pages/course.vue | 720 +++++++++--------- app/citizen-frontend/src/pages/index.vue | 96 ++- app/citizen-frontend/src/router/index.ts | 35 +- app/citizen-frontend/src/stores/course.ts | 92 ++- 7 files changed, 613 insertions(+), 363 deletions(-) diff --git a/app/citizen-frontend/src/api/course.ts b/app/citizen-frontend/src/api/course.ts index 9d3d6f5..7146277 100644 --- a/app/citizen-frontend/src/api/course.ts +++ b/app/citizen-frontend/src/api/course.ts @@ -41,8 +41,8 @@ function toCourseRow(raw: CourseListApiRow): CourseRow { } /** 依登入 Cookie 取得目前使用者的體適能組別。 */ -export function fetchGroup(): Promise { - return api.get("course/group").json(); +export function fetchGroup(): Promise { + return api.get("course/group").json(); } /** 取得是否納入早上時段 */ diff --git a/app/citizen-frontend/src/components/layout/DefaultLayout.vue b/app/citizen-frontend/src/components/layout/DefaultLayout.vue index 4493df3..1598c91 100644 --- a/app/citizen-frontend/src/components/layout/DefaultLayout.vue +++ b/app/citizen-frontend/src/components/layout/DefaultLayout.vue @@ -279,8 +279,10 @@ import { ref, watch } from "vue"; import { useRoute, useRouter } from "vue-router"; import { useAppStore } from "@/stores/app"; +import { useCourseStore } from "@/stores/course"; const store = useAppStore(); +const courseStore = useCourseStore(); const router = useRouter(); const route = useRoute(); @@ -314,6 +316,7 @@ function getBottomNavIconColor(value: string) { async function handleLogout() { await store.logout(); + courseStore.resetGroup(); await router.push("/login"); drawer.value = false; } diff --git a/app/citizen-frontend/src/pages/appointment.vue b/app/citizen-frontend/src/pages/appointment.vue index d09b3d6..4cb549f 100644 --- a/app/citizen-frontend/src/pages/appointment.vue +++ b/app/citizen-frontend/src/pages/appointment.vue @@ -9,6 +9,18 @@ + + 尚未取得您的體適能分組,請先預約並完成現場普測;分組建立後即可查看個人化課程建議。 + + import { computed, ref } from "vue"; +import { useRoute, useRouter } from "vue-router"; import Layout from "@/components/layout/DefaultLayout.vue"; import QRCode from "@/components/QRCode.vue"; import { type Appointment, useAppStore } from "@/stores/app"; const store = useAppStore(); +const route = useRoute(); +const router = useRouter(); const filterTab = ref("all"); +const showMissingGroupNotice = ref( + route.query.reason === "missing-fitness-group", +); const qrcodeDialog = ref(false); const selectedApt = ref(null); @@ -301,6 +319,14 @@ function handleCancel(id: string) { store.cancelAppointment(id); } +async function dismissMissingGroupNotice() { + showMissingGroupNotice.value = false; + + const query = { ...route.query }; + delete query.reason; + await router.replace({ query }); +} + function showCheckinQRCode(apt: Appointment) { selectedApt.value = apt; qrcodeDialog.value = true; diff --git a/app/citizen-frontend/src/pages/course.vue b/app/citizen-frontend/src/pages/course.vue index c06242f..c2b5c19 100644 --- a/app/citizen-frontend/src/pages/course.vue +++ b/app/citizen-frontend/src/pages/course.vue @@ -1,364 +1,402 @@ diff --git a/app/citizen-frontend/src/pages/index.vue b/app/citizen-frontend/src/pages/index.vue index 926e65a..4206fd8 100644 --- a/app/citizen-frontend/src/pages/index.vue +++ b/app/citizen-frontend/src/pages/index.vue @@ -38,6 +38,9 @@ {{ courseStore.groupMeta.label }} + + 尚未分組 + 無資料 @@ -227,12 +230,55 @@ to="/introduction" /> + + + + + 尚未取得體適能分組 + + + + + + + +

+ 預約普測,建立您的體適能分組 +

+

+ 完成預約並到現場參加量測後,系統才能建立您的體適能分組與課程建議。 +

+
+ + + + + + 稍後再說 + + + 前往預約 + + +
+