diff --git a/app/citizen-frontend/.env.production b/app/citizen-frontend/.env.production index 3b0dfd3..78906bc 100644 --- a/app/citizen-frontend/.env.production +++ b/app/citizen-frontend/.env.production @@ -1,5 +1,6 @@ # 正式站設定:前端與後端(/service)部署在同一個 IIS 站台/port, # 直接用相對路徑打後端,不需要主機名稱,也不會有 CORS 問題。 # pnpm build 預設走 production mode,會自動套用這份檔案。 +# empowertaipei.com.tw VITE_API_BASE_URL=/service/api VITE_USE_MOCK=false diff --git a/app/citizen-frontend/src/api/auth.ts b/app/citizen-frontend/src/api/auth.ts index 41e056a..af6978a 100644 --- a/app/citizen-frontend/src/api/auth.ts +++ b/app/citizen-frontend/src/api/auth.ts @@ -1,40 +1,41 @@ import { api, clearCsrfToken } from "./client"; import type { AuthResponse, + CheckPhoneRequest, + CheckPhoneResponse, LoginRequest, LogoutResponse, RegisterRequest, + UpdateEmailRequest, + UpdateEmailResponse, } from "./types"; -/** 使用手機門號與密碼登入;登入 Cookie 由共用 HTTP client 自動攜帶。 */ -export function login(request: LoginRequest): Promise; -export function login(phone: string, password: string): Promise; -export function login( - requestOrPhone: LoginRequest | string, - password?: string, -): Promise { - if (typeof requestOrPhone === "string") { - if (!password) { - throw new Error("登入需要密碼"); - } - - return api - .post("v1/auth/login", { - json: { phone: requestOrPhone, password }, - }) - .json(); - } - +/** 檢查手機門號是否具備註冊資格。 */ +export function checkPhone(phone: string): Promise { + const request: CheckPhoneRequest = { phone }; return api - .post("v1/auth/login", { json: requestOrPhone }) - .json(); + .post("v1/auth/check-phone", { json: request }) + .json(); } -/** 使用手機門號、密碼與個資同意狀態註冊帳號。 */ +/** 使用手機門號與密碼登入;登入 Cookie 由共用 HTTP client 自動攜帶。 */ +export function login(request: LoginRequest): Promise { + return api.post("v1/auth/login", { json: request }).json(); +} + +/** 使用手機門號、密碼與 E-Mail 註冊帳號。 */ export function register(request: RegisterRequest): Promise { return api.post("v1/auth/register", { json: request }).json(); } +/** 更新目前登入帳號的 E-Mail。 */ +export function updateEmail(email: string): Promise { + const request: UpdateEmailRequest = { email }; + return api + .put("v1/auth/email", { json: request }) + .json(); +} + /** 呼叫後端登出並讓後端清除登入 Cookie。 */ export function logout(): Promise { return api diff --git a/app/citizen-frontend/src/api/types.ts b/app/citizen-frontend/src/api/types.ts index a025653..1fa0950 100644 --- a/app/citizen-frontend/src/api/types.ts +++ b/app/citizen-frontend/src/api/types.ts @@ -113,12 +113,21 @@ export interface Profile extends ProfileRequest { updatedAt: string; } -/** 註冊請求:僅建立帳號,個人資料由後續流程另行保存。 */ +/** 註冊前檢查手機門號是否具備註冊資格。 */ +export interface CheckPhoneRequest { + phone: string; +} + +export interface CheckPhoneResponse { + code: "PASS"; + message: string; +} + +/** 註冊請求;條款勾選僅為前端門檻,不屬於 Auth API contract。 */ export interface RegisterRequest { phone: string; password: string; - consent: boolean; - consentVersion: ConsentVersion; + email: string; } /** 登入請求。 */ @@ -130,10 +139,19 @@ export interface LoginRequest { /** 登入/註冊成功回應。Cookie 由瀏覽器管理,前端不保存其值。 */ export interface AuthResponse { userID: string; - userName: string; phone: string; group: FitnessGroup; - profile: Profile | null; + mail: 0 | 1; +} + +export interface UpdateEmailRequest { + email: string; +} + +export interface UpdateEmailResponse { + messageCode: string; + email: string; + mail: 0; } /** 舊名稱保留為相容別名,新的 API 請使用 AuthResponse。 */ diff --git a/app/citizen-frontend/src/components/auth/EmailCompletionForm.vue b/app/citizen-frontend/src/components/auth/EmailCompletionForm.vue new file mode 100644 index 0000000..64063dd --- /dev/null +++ b/app/citizen-frontend/src/components/auth/EmailCompletionForm.vue @@ -0,0 +1,65 @@ + + + diff --git a/app/citizen-frontend/src/components/auth/RegisterCredentialsStep.vue b/app/citizen-frontend/src/components/auth/RegisterCredentialsStep.vue new file mode 100644 index 0000000..5a6846c --- /dev/null +++ b/app/citizen-frontend/src/components/auth/RegisterCredentialsStep.vue @@ -0,0 +1,157 @@ + + + diff --git a/app/citizen-frontend/src/components/auth/RegisterPhoneStep.vue b/app/citizen-frontend/src/components/auth/RegisterPhoneStep.vue new file mode 100644 index 0000000..8055773 --- /dev/null +++ b/app/citizen-frontend/src/components/auth/RegisterPhoneStep.vue @@ -0,0 +1,53 @@ + + + diff --git a/app/citizen-frontend/src/components/layout/DefaultLayout.vue b/app/citizen-frontend/src/components/layout/DefaultLayout.vue index 6e871c5..8169e23 100644 --- a/app/citizen-frontend/src/components/layout/DefaultLayout.vue +++ b/app/citizen-frontend/src/components/layout/DefaultLayout.vue @@ -157,6 +157,14 @@ + + +
+ + {{ + EMAIL_COMPLETION_REQUIRED + ? "請先補登 E-Mail,才能繼續使用平台。" + : "尚未設定 E-Mail,前往補登以接收重要通知。" + }} + + + 前往補登 + +
+
@@ -276,10 +313,6 @@
  • 於活動現場合對您的身分。
  • 在去識別化的安全機制下,作為高齡健康促進的政策分析參考。
  • - -

    - 授權狀態:{{ store.userProfile.consent ? "已同意授權" : "未授權" }} -

    @@ -298,13 +331,14 @@ + + diff --git a/app/citizen-frontend/src/pages/login.vue b/app/citizen-frontend/src/pages/login.vue index 6449f3f..53e0183 100644 --- a/app/citizen-frontend/src/pages/login.vue +++ b/app/citizen-frontend/src/pages/login.vue @@ -18,7 +18,7 @@ 登入 - 請輸入您的手機門號與登入密碼 + 請輸入您的手機號碼與登入密碼 - 登入健康平台 + {{ + remainingSeconds > 0 + ? `${remainingSeconds} 秒後再試` + : "登入健康平台" + }} - 註冊新帳號 + 既有帳號建立密碼 - - - - - - - - - - - - 完成註冊並繼續 + 返回登入 - + + + - + 返回登入 @@ -181,118 +59,154 @@ - -