公司快速註冊 Mockup PRD
此範本專門給 30%-feature-gen 產出的 mockup PRD 使用。
backend-api-spec-generator 會讀取這份文件與 Storybook mockups 來產生後端 API 規格。
1. 文件資訊
- 文件類型:Mockup 需求規格書(前後端共用視圖)
- 適用對象:前端開發、後端開發、產品、QA
- 最後更新:2026/03/16
- 版本:1.2.0
- 對應 Storybook:
storybook/src/stories/mockups/company/CompanyQuickRegister.stories.ts
- Storybook 連結:CompanyQuickRegister
- 建立日期:2026/03/04
2. 開發進度與設計來源
開發進度
設計來源
- Figma 連結:無(組合既有模組)
- 既有畫面參照:
- 校園活動招募 Step 1 註冊/登入 + OTP 驗證(
MockupCampusEventQuickApplySheet.vue + MockMainSiteAuth.vue)
- 既有前端
company-register 頁面
3. 模擬頁面摘要(Mockup Summary)
3.1 功能概述
- 功能名稱:公司快速註冊(Company Quick Register)
- 主要使用者角色:企業主 / HR / 被主管指派建立公司頁面的人
- 核心目標:
- 將「使用者帳號註冊 → email 驗證 → 會員基本資料 → 公司頁面建立」串成一條連貫流程
- 消除現有流程中「註冊帳號後被導回首頁、找不到建立公司入口」的斷裂體驗
- 使用 OTP 驗證碼取代驗證連結,使用者始終留在同一畫面
- OTP 驗證流程與一般網站註冊/登入共用同一套機制,非僅限本流程或校園活動
3.2 範圍界定
- 包含範圍:
- 獨立頁面(沿用既有 company-register URL)
- Step 1:註冊/登入 + OTP 驗證(沿用校園活動模組
MockMainSiteAuth + OTP 流程)
- Step 2:會員基本資料填寫(僅顯示必填欄位,非必填不顯示;僅新註冊用戶需填寫)
- Step 3:公司基本資料填寫(沿用既有前端
company-register 模組)
- Google 註冊/登入(既有模組)
- 多語系(既有模組)
- 已登入使用者(已有個人資料)跳過 Step 1 與 Step 2,直接進入 Step 3
- 已登入未驗證使用者補做 OTP 驗證
- 公司建立上限檢查(每帳號以**擁有者(owner)**身份最多 10 間;僅計算本人為 owner 的公司,被加入為成員的公司不計入)
- 排除範圍:
- 不做履歷相關流程
- 不做公司驗證(上傳文件審核,屬後續既有流程)
- 不做中斷還原的額外處理(公司資料填寫的中斷行為與既有 company-register 一致)
- 不做公司後續管理流程(建立完成後導向既有公司頁面)
3.3 成功條件
- 沒有帳號的人經此流程完成公司帳號註冊的比例
- 有帳號的人經此流程完成新增公司的比例
- 使用者不再因為「註冊帳號後被導回首頁」而迷路
4. 商業規則對齊(Business Rules Alignment)
4.1 本功能使用到的業務規則
| 規則 ID | 規則摘要 | 是否關鍵 | 備註 |
|---|
| BR-001 | 只有信箱認證後才能登入 | ✅ 是 | 本流程使用 OTP 驗證碼完成 email 驗證 |
| BR-002 | 信箱認證後仍然要完成個人資料 | ✅ 是 | Step 2 會員資料即為完成個人資料必填欄位 |
| BR-004 | 只有信箱認證的使用者帳號可以新增公司頁面 | ✅ 是 | 驗證完成後才允許進入公司資料填寫 |
| BR-NEW | 每個帳號以擁有者身份最多建立 10 間公司;被加入為成員不計入 | ✅ 是 | 新規則,需回寫 business-rules.md |
4.2 補充說明
- OTP 驗證碼 API 與一般網站註冊/登入共用同一套端點(校園活動亦沿用),與主站的「驗證連結」方式不同
- 第三方登入(Google)不需 OTP 驗證碼,直接視為 verified
- 公司上限 10 間的檢查以本人為 owner 的公司數量為準;僅為成員(被加入)的公司不計入。檢查在登入/驗證完成後立刻執行,達上限則不進入後續步驟
- Step 2 會員資料僅對新註冊用戶(個人資料尚未填寫)顯示;已登入且個人資料已完成的使用者跳過此步驟
5. 資料實體與欄位(Data Entities & Fields)
5.1 實體列表
| 實體名稱 | 說明 | 來源頁面/區塊 |
|---|
| AuthState | 使用者認證狀態 | Step 1 認證流程 |
| MemberProfileForm | 會員基本資料表單 | Step 2 會員資料填寫 |
| CompanyRegisterForm | 公司基本資料表單 | Step 3(沿用既有 company-register) |
5.2 實體欄位定義(TypeScript 介面)
AuthState(前端認證狀態管理)
interface CompanyRegisterAuthState {
isLoggedIn: boolean
verified: boolean
profileFilled: boolean
companyCount: number
authMode: 'register' | 'login'
loginMethod: 'email' | 'google'
otpSent: boolean
otpVerified: boolean
}
interface MemberProfileForm {
name: string // 姓名(必填)
birthday: string // 生日(必填,YYYY-MM-DD)
email: string // Email(必填,自動帶入,唯讀)
phone: string // 手機號碼(必填)
residence: string // 居住地址(必填)
nationality: string // 國籍(必填)
work_identity_type?: string // 身份種類(條件必填:居住地=台灣 且 國籍≠台灣 時顯示)
}
- 僅顯示必填欄位,非必填欄位完全不渲染
- Email 自動帶入前面註冊/登入時使用的 email,設為唯讀
work_identity_type 為條件欄位:僅當 residence 為台灣且 nationality 不是台灣時才顯示並必填
沿用既有 company-register 前端模組的表單介面,不另定義。
6. 畫面區塊與資料需求(UI Sections & Data Needs)
6.1 區塊列表
| 區塊 ID | 區塊名稱 | 說明 |
|---|
| SEC-1 | Step 指示器 | 顯示目前步驟(1: 註冊驗證 / 2: 會員資料 / 3: 公司資料) |
| SEC-2 | Step 1:註冊/登入 + OTP | 沿用 MockMainSiteAuth + OTP 驗證碼流程 |
| SEC-2.5 | Step 2:會員基本資料填寫 | 僅顯示必填欄位,新註冊用戶專用 |
| SEC-3 | Step 3:公司基本資料填寫 | 沿用既有 company-register 表單模組 |
| SEC-4 | 公司上限提示 | 達 10 間上限時顯示的錯誤提示 |
| SEC-5 | 已登入未驗證提示 | 顯示「email 尚未驗證」+ 發送驗證碼按鈕 |
6.2 各區塊資料需求
SEC-2 Step 1:註冊/登入 + OTP
- 組件:
MockMainSiteAuth(與校園活動完全相同)
- 功能:
- 註冊/登入 Tab 切換
- Email 註冊:email + 密碼 + 確認密碼 → 點擊註冊 → 發送 OTP → 輸入驗證碼
- Email 登入:email + 密碼 → 點擊登入 → 若未驗證則發送 OTP → 輸入驗證碼
- Google 註冊/登入:OAuth 完成即 verified
- 「email 已註冊」提示:引導切換到登入
- OTP 流程:與一般註冊/登入及校園活動共用(輸入驗證碼 → 驗證成功/失敗 → 重發倒數 → 重試直到成功)
SEC-2.5 Step 2:會員基本資料填寫
- 組件:新建 mockup 表單(僅必填欄位)
- 顯示條件:
profileFilled = false(新註冊用戶,個人資料尚未填寫);已登入且已有個人資料者跳過此步驟
- 表單欄位(僅顯示必填,非必填完全不渲染):
| # | 欄位 | 類型 | 備註 |
|---|
| 1 | 姓名 | 文字輸入 | 必填 |
| 2 | 生日 | 日期選擇器 | 必填 |
| 3 | Email | 文字輸入(唯讀) | 自動帶入註冊/登入時的 email |
| 4 | 手機號碼 | 文字輸入 | 必填 |
| 5 | 居住地址 | 下拉選擇 | 必填 |
| 6 | 國籍 | 下拉選擇 | 必填 |
| 7 | 身份種類 | 下拉選擇 | 條件顯示:居住地=台灣 且 國籍≠台灣 時才出現並必填 |
- 行為:填寫完成後點擊「下一步」→ 呼叫更新個人資料 API → 進入 Step 3
SEC-3 Step 3:公司基本資料填寫
- 組件:沿用既有
company-register 前端模組
- 行為:填寫完成後點擊下一步 → 呼叫建立公司 API → 導向公司頁面
SEC-4 公司上限提示
- 觸發條件:登入/驗證完成後,查詢**本人為擁有者(owner)**的公司數量 >= 10(僅為成員的公司不計入)
- 顯示:「您已達公司建立上限(以擁有者身份 10 間),無法再建立新公司。」
- 操作:提供返回按鈕或導向公司管理頁面
SEC-5 已登入未驗證提示
- 觸發條件:已登入但
verified = false
- 顯示:「您的 email 尚未驗證」+ 「發送驗證碼」按鈕
- 操作:使用者手動點擊按鈕後觸發發送 OTP,進入驗證碼輸入流程
7. 使用者動作與後端需求(User Actions & Backend Needs)
| 動作 ID | 動作名稱 | 類型 | 需要後端 | 涉及實體 | 說明 |
|---|
| ACT-1 | Email 註冊 | 寫入 | ✅ 是 | AuthState | 建立帳號 + 發送 OTP(與一般註冊/登入共用 OTP API) |
| ACT-2 | Email 登入 | 查詢 | ✅ 是 | AuthState | 驗證帳密 + 回傳 verified 狀態(與一般註冊/登入共用 OTP API) |
| ACT-3 | 發送 OTP | 寫入 | ✅ 是 | AuthState | 發送驗證碼到 email(與一般註冊/登入共用 OTP API) |
| ACT-4 | 驗證 OTP | 寫入 | ✅ 是 | AuthState | 驗證碼比對(與一般註冊/登入共用 OTP API) |
| ACT-5 | Google OAuth | 查詢 | ✅ 是 | AuthState | 沿用既有 Google OAuth |
| ACT-6 | 查詢擁有公司數量 | 查詢 | ✅ 是 | - | 登入/驗證後查詢該帳號以**擁有者(owner)**身份擁有的公司數量(被加入為成員的公司不計入) |
| ACT-6.5 | 檢查個人資料是否已填寫 | 查詢 | ✅ 是 | AuthState | 判斷是否需要顯示 Step 2(profileFilled?) |
| ACT-7 | 儲存會員基本資料 | 寫入 | ✅ 是 | MemberProfileForm | Step 2 填寫完成後呼叫更新個人資料 API |
| ACT-8 | 建立公司 | 寫入 | ✅ 是 | CompanyRegisterForm | 沿用既有建立公司 API |
場景化動作描述
場景 A:完全新用戶 — Email 註冊
| 項目 | 描述 |
|---|
| 進入條件 | 未登入、無帳號 |
| 畫面呈現 | Step 1 顯示註冊/登入 Tab(預設註冊),填寫 email + 密碼 + 確認密碼 |
| 操作流程 | 點「註冊」→ 帳號建立 + 發送 OTP → 輸入驗證碼 → 驗證成功 → 查公司數量 → Step 2 填寫會員資料 → Step 3 填寫公司資料 → 導向公司頁面 |
| 錯誤處理 | OTP 錯誤/過期 → 同校園活動(重發倒數、重試直到成功) |
場景 B:完全新用戶 — Google 註冊
| 項目 | 描述 |
|---|
| 進入條件 | 未登入、無帳號 |
| 操作流程 | Google OAuth 完成 → 跳過 OTP → 查公司數量 → Step 2 填寫會員資料 → Step 3 填寫公司資料 → 導向公司頁面 |
| 錯誤處理 | Google 失敗/取消 → 提示重試或改用 Email |
場景 C:有帳號未驗證 — 登入
| 項目 | 描述 |
|---|
| 進入條件 | 未登入、有帳號但 verified = false |
| 操作流程 | 登入 Tab → 輸入帳密 → 登入成功 → 發送 OTP → 驗證成功 → 查公司數量 → 檢查個人資料 → 若未填則 Step 2 → Step 3 |
| 錯誤處理 | 帳密錯誤 → 錯誤提示;OTP 錯誤 → 同上 |
場景 D/E:有帳號已驗證 — 登入(個人資料已填寫)
| 項目 | 描述 |
|---|
| 進入條件 | 未登入、有帳號、verified = true、profileFilled = true、公司數量 0~9 |
| 操作流程 | 登入 → 不需 OTP → 查公司數量 → 跳過 Step 2 → 直接進入 Step 3 |
場景 D’/E’:有帳號已驗證 — 登入(個人資料未填寫)
| 項目 | 描述 |
|---|
| 進入條件 | 未登入、有帳號、verified = true、profileFilled = false、公司數量 0~9 |
| 操作流程 | 登入 → 不需 OTP → 查公司數量 → Step 2 填寫會員資料 → Step 3 |
場景 F:有帳號已驗證 — 已達公司上限
| 項目 | 描述 |
|---|
| 進入條件 | 登入完成、本人為擁有者的公司數量 = 10(僅為成員不計入) |
| 操作流程 | 登入後立刻顯示「已達公司建立上限(以擁有者身份 10 間)」,不進入後續步驟 |
場景 G:已登入已驗證直接進入(個人資料已填寫)
| 項目 | 描述 |
|---|
| 進入條件 | 已登入、verified = true、profileFilled = true,直接訪問頁面 URL |
| 操作流程 | 跳過 Step 1 + Step 2 → 查公司數量 → 直接進入 Step 3 |
場景 G’:已登入已驗證直接進入(個人資料未填寫)
| 項目 | 描述 |
|---|
| 進入條件 | 已登入、verified = true、profileFilled = false,直接訪問頁面 URL |
| 操作流程 | 跳過 Step 1 → 查公司數量 → Step 2 填寫會員資料 → Step 3 |
場景 H:已登入未驗證直接進入
| 項目 | 描述 |
|---|
| 進入條件 | 已登入、verified = false,直接訪問頁面 URL |
| 操作流程 | 顯示「email 尚未驗證」+ 發送驗證碼按鈕 → 使用者手動點擊 → 發送 OTP → 驗證成功 → 查公司數量 → 檢查個人資料 → 若未填則 Step 2 → Step 3 |
場景 I:註冊時 email 已存在
| 項目 | 描述 |
|---|
| 進入條件 | 在註冊 Tab 輸入了已註冊的 email |
| 畫面呈現 | 顯示「此 email 已有人註冊,請改用登入」+ 切換到登入 Tab 的按鈕 |
8. API Hints(提示用,非最終 API 設計)
8.1 資料讀取需求(Read)
8.2 資料寫入需求(Write)
-
HINT-MUTATION-1:OTP 註冊(與一般註冊/登入及校園活動共用 API)
- 輸入:
{ email, password }
- 行為:建立帳號 + 發送 OTP 至 email
- 錯誤:email 已存在 → 回傳已註冊錯誤
-
HINT-MUTATION-2:OTP 登入(與一般註冊/登入及校園活動共用 API)
- 輸入:
{ email, password }
- 行為:驗證帳密,若未驗證帳號則回傳
verified = false
-
HINT-MUTATION-3:發送 OTP(與一般註冊/登入及校園活動共用 API)
- 輸入:
{ email }
- 行為:發送 OTP 驗證碼至 email
-
HINT-MUTATION-4:驗證 OTP(與一般註冊/登入及校園活動共用 API)
- 輸入:
{ email, otp_code }
- 行為:比對驗證碼,成功則將帳號標記為 verified
-
HINT-MUTATION-5:儲存會員基本資料
- 對應區塊:SEC-2.5(Step 2 會員資料)
- 輸入:
MemberProfileForm(姓名、生日、手機、居住地、國籍、身份種類)
- 行為:更新使用者個人資料(沿用既有更新個人資料 API)
-
HINT-MUTATION-6:建立公司(沿用既有 API)
- 輸入:公司基本資料(同既有 company-register)
- 行為:建立公司頁面,建立者成為 Owner
9. 導航 / Storybook Map
- Storybook 標題:
Mockups/Company/CompanyQuickRegister
- Stories 路徑:
storybook/src/stories/mockups/company/CompanyQuickRegister.stories.ts
- Storybook 連結:CompanyQuickRegister
- 情境控制:
initialLoggedIn:是否已登入
initialVerified:是否已驗證
initialProfileFilled:個人資料是否已填寫(控制是否顯示 Step 2)
initialCompanyCount:目前公司數量(0~10)
initialAuthVariant:email_register / google_done / login_otp_pending
registerResult:send_otp / already_registered
- 對應 production 路由:
/company-register(既有路徑)
- 入口來源:job-posting 頁面「免費建立公司」按鈕
10. Flowcharts(User / System / Navigation)
10.1 User Flow(使用者操作流程)
flowchart TD
Start[使用者進入公司註冊頁面] --> AuthCheck{已登入?}
AuthCheck -->|是| VerifiedCheck{已驗證 email?}
AuthCheck -->|否| Step1[Step 1:顯示註冊/登入畫面]
Step1 --> AuthTab{註冊 or 登入?}
%% === 註冊路線 ===
AuthTab -->|註冊| RegMethod{Email 註冊 or Google 註冊?}
RegMethod -->|Email 註冊| RegEmail[輸入 email、密碼、確認密碼]
RegEmail --> RegSubmit[點擊「註冊」]
RegSubmit --> RegCheck{此 email 已註冊?}
RegCheck -->|是| ErrReg[顯示「此 email 已有人註冊,請改用登入」]
ErrReg --> AuthTab
RegCheck -->|否| RegOtp[帳號建立 + 發送 OTP 至 Email]
RegOtp --> InputOtp
RegMethod -->|Google 註冊| RegGoogle[Google OAuth]
RegGoogle --> GoogleResult{Google 成功?}
GoogleResult -->|否| GoogleFail[提示重試或改用 Email]
GoogleFail --> RegMethod
GoogleResult -->|是| VerifiedGoogle[verified = true]
VerifiedGoogle --> CompanyLimitCheck
%% === 登入路線 ===
AuthTab -->|登入| LoginMethod{一般登入 or Google 登入?}
LoginMethod -->|一般登入| LoginEmail[輸入 email、密碼]
LoginEmail --> LoginSubmit[點擊「登入」]
LoginSubmit --> LoginResult{登入成功?}
LoginResult -->|否| LoginFail[顯示帳密錯誤]
LoginFail --> LoginEmail
LoginResult -->|是| LoginVerifiedCheck{帳號已 verified?}
LoginVerifiedCheck -->|是| CompanyLimitCheck
LoginVerifiedCheck -->|否| LoginOtp[發送 OTP]
LoginOtp --> InputOtp
LoginMethod -->|Google 登入| LoginGoogle[Google OAuth]
LoginGoogle --> GoogleLoginResult{Google 成功?}
GoogleLoginResult -->|否| GoogleLoginFail[提示重試或改用 Email]
GoogleLoginFail --> LoginMethod
GoogleLoginResult -->|是| VerifiedGoogleLogin[verified = true]
VerifiedGoogleLogin --> CompanyLimitCheck
%% === 共用 OTP 驗證碼流程 ===
subgraph OtpFlow [共用 OTP 驗證碼流程]
InputOtp[輸入驗證碼]
OtpCheck{驗證成功?}
OtpFail[顯示錯誤或過期]
WaitOtp[等待可重發倒數]
ResendOtp[重新發送驗證碼]
InputOtp --> OtpCheck
OtpCheck -->|是| VerifiedOtp[verified = true]
OtpCheck -->|否| OtpFail
OtpFail --> WaitOtp
WaitOtp --> ResendOtp
ResendOtp --> InputOtp
end
VerifiedOtp --> CompanyLimitCheck
%% === 已登入進入的路線 ===
VerifiedCheck -->|是| CompanyLimitCheck
VerifiedCheck -->|否| ShowOtpTrigger[顯示「您的 email 尚未驗證」<br>+ 發送驗證碼按鈕]
ShowOtpTrigger --> TriggerOtp[使用者點擊發送驗證碼]
TriggerOtp --> InputOtp
%% === 公司上限檢查(僅計本人為 owner 的公司)===
CompanyLimitCheck{本人為擁有者的公司數 < 10?}
CompanyLimitCheck -->|否| LimitError[顯示「已達公司建立上限(以擁有者身份 10 間)」]
CompanyLimitCheck -->|是| ProfileCheck{個人資料已填寫?}
%% === 會員資料檢查 ===
ProfileCheck -->|是| Step3[Step 3:公司基本資料填寫<br>(沿用既有 company-register 模組)]
ProfileCheck -->|否| Step2[Step 2:會員基本資料填寫<br>(僅顯示必填欄位)]
Step2 --> Step2Submit[填寫完成,點擊下一步]
Step2Submit --> Step2Save[儲存個人資料]
Step2Save --> Step3
Step3 --> CompanySubmit[填寫完成,點擊下一步]
CompanySubmit --> CompanyPage[導向公司頁面<br>(進入既有後續流程)]
10.2 System Flow(前端狀態與 API 互動)
sequenceDiagram
participant U as 使用者
participant FE as 前端
participant API as 後端 API
U->>FE: 進入公司註冊頁面
FE->>FE: 檢查 auth state(已登入?)
alt 已登入 + 已驗證
FE->>API: GET 查詢擁有公司數量(owner)+ 個人資料狀態
API-->>FE: { count: N, profileFilled: bool }
alt N >= 10(僅計 owner)
FE->>U: 顯示「已達上限」
else profileFilled = true
FE->>U: 跳過 Step 2,直接顯示 Step 3(公司資料填寫)
else profileFilled = false
FE->>U: 顯示 Step 2(會員基本資料填寫)
U->>FE: 填寫會員資料並點擊下一步
FE->>API: POST 儲存個人資料
API-->>FE: 儲存成功
FE->>U: 顯示 Step 3(公司資料填寫)
end
else 已登入 + 未驗證
FE->>U: 顯示「email 尚未驗證」+ 發送驗證碼按鈕
U->>FE: 點擊發送驗證碼
FE->>API: POST 發送 OTP(與一般註冊/登入共用 API)
API-->>FE: OTP 已發送
U->>FE: 輸入驗證碼
FE->>API: POST 驗證 OTP
API-->>FE: 驗證成功
FE->>API: GET 查詢擁有公司數量(owner)+ 個人資料狀態
API-->>FE: { count: N, profileFilled: bool }
FE->>U: 依 profileFilled 顯示 Step 2 或 Step 3
else 未登入
FE->>U: 顯示 Step 1(註冊/登入)
alt Email 註冊
U->>FE: 填寫 email + 密碼 + 確認密碼
U->>FE: 點擊「註冊」
FE->>API: POST OTP 註冊(與一般註冊/登入共用 API)
alt email 已存在
API-->>FE: 已註冊錯誤
FE->>U: 「此 email 已有人註冊,請改用登入」
else 成功
API-->>FE: 帳號建立 + OTP 已發送
U->>FE: 輸入驗證碼
FE->>API: POST 驗證 OTP
API-->>FE: 驗證成功
end
else Email 登入
U->>FE: 填寫 email + 密碼
U->>FE: 點擊「登入」
FE->>API: POST OTP 登入(與一般註冊/登入共用 API)
API-->>FE: 登入成功 + verified 狀態
alt 未驗證
FE->>API: POST 發送 OTP
U->>FE: 輸入驗證碼
FE->>API: POST 驗證 OTP
end
else Google 登入/註冊
U->>FE: 點擊 Google 按鈕
FE->>API: Google OAuth
API-->>FE: 登入成功(verified = true)
end
FE->>API: GET 查詢擁有公司數量(owner)+ 個人資料狀態
API-->>FE: { count: N, profileFilled: bool }
alt N >= 10(僅計 owner)
FE->>U: 顯示「已達上限」
else profileFilled = false
FE->>U: 顯示 Step 2(會員資料)
U->>FE: 填寫會員資料並點擊下一步
FE->>API: POST 儲存個人資料
API-->>FE: 儲存成功
FE->>U: 顯示 Step 3(公司資料)
else profileFilled = true
FE->>U: 跳過 Step 2,顯示 Step 3
end
end
U->>FE: 填寫公司基本資料
U->>FE: 點擊「下一步」
FE->>API: POST 建立公司(沿用既有 API)
API-->>FE: 公司建立成功
FE->>U: 導向公司頁面
11. Mock Data Schema(Mock 資料結構)
- 資料來源:僅 mock,不呼叫真實 API
- CRUD 行為:mock 內所有新增/修改/刪除僅存在元件狀態,重新整理後還原
- 情境切換:
initialLoggedIn:控制已登入/未登入狀態
initialVerified:控制已驗證/未驗證狀態
initialProfileFilled:控制個人資料是否已填寫(影響是否顯示 Step 2)
initialCompanyCount:控制公司數量(影響上限檢查)
initialAuthVariant:控制 Step 1 的初始變體(email_register / google_done / login_otp_pending)
registerResult:控制註冊結果(send_otp / already_registered)
12. 實作備註(Implementation Notes)
- 禁止事項:
- ❌ 本文件不直接定義最終 API path/method,僅提供 Hints
- ❌ 不直接修改
prd/business-rules.md,新規則先在「商業規則對齊」描述,再由人決定是否回寫
- 注意事項:
- 欄位命名與 Storybook/TS interface 一致
- Step 1 完全複用校園活動的
MockMainSiteAuth + OTP 流程,不另建新組件
- Step 2 會員資料表單僅顯示必填欄位(姓名、生日、Email(唯讀)、手機、居住地、國籍、身份種類(條件顯示)),非必填欄位完全不渲染
- Step 2 的 Email 欄位自動帶入註冊/登入時的 email,設為唯讀
- Step 2 的身份種類欄位僅在「居住地=台灣 且 國籍≠台灣」時顯示
- 已登入且個人資料已填寫(
profileFilled = true)的使用者跳過 Step 2
- Step 3 完全複用既有
company-register 前端模組,以子組件形式嵌入同一頁面
- OTP API 與一般網站註冊/登入共用同一套端點(校園活動亦沿用;語意上作為「通用 OTP 認證模組」使用)
- 前端使用單一頁面內的 state 切換 Step 1 / Step 2,不改路由結構
- 公司上限檢查以本人為 owner 的公司數量為準(被加入為成員不計入),在登入/驗證完成後立刻執行,不等到填完公司資料才報錯
架構決策記錄
| 決策項目 | 選擇 | 理由 |
|---|
| OTP API 端點 | 與一般註冊/登入及校園活動共用 | 同一套 OTP 用於全站註冊/登入與本流程,KISS,未來可統一重命名 |
| 已登入未驗證 OTP 觸發方式 | 手動觸發(使用者點按鈕) | 避免使用者還沒準備好就收到驗證碼 |
| 公司上限檢查時機 | 登入/驗證後立刻檢查 | 避免白填公司資料 |
| 前端路由 | 單一頁面 state 切換 | 不改既有路由結構,體驗最連貫 |
| Step 2 會員資料顯示條件 | 依 profileFilled 判斷 | 已有個人資料的使用者不需重複填寫 |
| Step 2 非必填欄位 | 完全不渲染 | 保持表單精簡,減少填寫壓力 |
| Step 1→2→3 銜接 | 同一頁面內依序嵌入各步驟組件 | 使用者始終在同一畫面,減少跳轉 |
入口與狀態約束表
| 入口狀態 | verified | profileFilled | 公司數量 | 預期行為 |
|---|
| 未登入 → 註冊(Email) | false → OTP 後 true | false | 0 | 註冊 → OTP → Step 2(會員資料) → Step 3 |
| 未登入 → 註冊(Google) | true(免 OTP) | false | 0 | Google OAuth → Step 2(會員資料) → Step 3 |
| 未登入 → 登入(未驗證) | false → OTP 後 true | 視情況 | N/A | 登入 → OTP → 檢查上限 → 依 profileFilled 決定 |
| 未登入 → 登入(已驗證、資料已填) | true | true | 0~9 | 登入 → 檢查上限 → 跳過 Step 2 → Step 3 |
| 未登入 → 登入(已驗證、資料未填) | true | false | 0~9 | 登入 → 檢查上限 → Step 2 → Step 3 |
| 未登入 → 登入(已驗證,owner 數=10) | true | N/A | 10 | 登入 → 顯示上限提示(僅計 owner) |
| 未登入 → 登入(Google) | true | 視情況 | N/A | Google OAuth → 檢查上限 → 依 profileFilled 決定 |
| 已登入 + 已驗證 + 資料已填 | true | true | 0~9 | 跳過 Step 1 + 2 → 直接 Step 3 |
| 已登入 + 已驗證 + 資料未填 | true | false | 0~9 | 跳過 Step 1 → Step 2 → Step 3 |
| 已登入 + 已驗證(owner 數=10) | true | N/A | 10 | 顯示上限提示(僅計 owner) |
| 已登入 + 未驗證 | false | N/A | N/A | 顯示驗證提示 → 手動 OTP → 檢查上限 → 依 profileFilled 決定 |
OTP 驗證碼錯誤與重發規則
沿用校園活動(recruitment-campaign-mockup.md §8.1.1)的完整規則:
| 失敗情境 | 處理 |
|---|
| 驗證碼輸入錯誤 | 顯示「驗證碼錯誤,請重新輸入」;不消耗重發次數 |
| 驗證碼已過期 | 顯示「驗證碼已過期,請重新取得」;需點重新發送 |
| 重發等待時間 | 60 秒倒數後才可再次發送 |
| 直到成功為止 | 重複直到驗證成功,通過後進入下一階段 |
新業務規則建議
- 建議新增 BR-NEW:每個帳號以**擁有者(owner)**身份最多建立 10 間公司(僅計算本人為 owner 的公司;被加入為成員的公司不計入)。達上限時顯示提示並阻止建立。建議回寫至
business-rules.md。
13. 下一步(Next Steps)
- 使用
storybook-mockup-gen skill 產出 Storybook mockup
- 產出後將 Storybook 連結回填至本 PRD §1 及 Trello 卡片
- 與後端確認 OTP API 與一般註冊/登入共用之端點
- 將 BR-NEW(每帳號以 owner 身份最多 10 間公司,僅為成員不計入)回寫至
business-rules.md
更新記錄
- 2026-03-16:v1.2.0 — OTP 與一般註冊共用;公司上限僅計 owner
- 明確 OTP 驗證流程與一般網站註冊/登入共用同一套機制與 API,非僅限本流程或校園活動
- 公司建立上限改為僅計算**本人為擁有者(owner)**的公司;被加入為成員的公司不計入,達 10 間(owner)才禁止建立新公司
- 2026-03-13:v1.1.0 — 新增 Step 2 會員基本資料
- 在 Step 1(註冊/驗證)與 Step 3(公司資料)之間新增 Step 2「會員基本資料」
- 僅顯示必填欄位(姓名、生日、Email(唯讀)、手機、居住地、國籍、身份種類(條件顯示))
- 非必填欄位完全不渲染
- 已登入且個人資料已填寫的使用者跳過 Step 2
- 新增
profileFilled 狀態判斷與 MemberProfileForm 實體
- 更新所有場景(A~I)與流程圖
- 從排除範圍中移除「不做個人基本資料填寫」
- 新增 BR-002 至商業規則對齊
- 2026-03-04:初版 PRD
- 公司快速註冊功能:將使用者註冊 + email OTP 驗證 + 公司建立串成一條連貫流程
- Step 1 沿用校園活動的 MockMainSiteAuth + OTP 模組
- Step 2 沿用既有 company-register 前端模組
- 新增公司建立上限:每帳號最多 10 間
- 完整場景列舉(A~I)含邊界情境
- 架構決策記錄:OTP API 沿用、手動觸發驗證、單一頁面 state 切換
文件結束