◆ wport | pm_29

招募活動引擎 Mockup PRD

招募活動引擎、業務專屬頁面

來源 doc/feature/pm_29/recruitment-campaign-mockup.md

招募活動引擎 Mockup PRD

功能概述

招募活動引擎讓企業/代理人建立自訂活動落地頁,並與人才庫統計串接。活動落地頁使用公司頁面 + 預設篩選條件的方式呈現,而非獨立的活動頁面。本文件記錄 Storybook Mockup 的實作細節與業務規則。

##參考連結 http://localhost:6006/?path=/story/mockups-campus-event-campus-event-quick-apply-demo—default

頁面結構

1. 後台:活動管理(Admin)

1.1 活動列表(CampaignListTable)

欄位順序(與職缺管理一致):

  • 活動名稱(可點擊,導向活動落地頁)
  • 點擊(PV;去重:同 IP 或同裝置同一自然日僅計 1 次)
  • 來訪(可點擊,導向人才庫並自動篩選活動來源)
  • 狀態(開關切換)
  • 操作(下拉選單:編輯、QR Code、複製連結、刪除

操作功能

  • 活動名稱點擊:導向活動落地頁(公司頁面 + 預設篩選條件)
  • 編輯:開啟編輯表單
  • QR Code:顯示 QR Code(Mock)
  • 複製連結:複製活動落地頁 URL(包含篩選條件的 query parameters)
  • 刪除:刪除活動(需確認,刪除後求職者的活動來源篩選將無法使用此活動)

分頁

  • 活動列表採分頁顯示,每頁 10 筆
  • 需提供分頁控制(如上一頁/下一頁或頁碼),供 HR 瀏覽多筆活動

1.2 活動編輯表單(CampaignEditorForm)

UI 結構:單一 PrimeVue Dialog,所有欄位在同一視窗內完成(不另開子 Modal)。

表單欄位

  1. 活動標題(必填)

    • 類型:PrimeVue InputText
    • 驗證:不可為空
  2. 活動網址(自動生成)(只讀)

    • 類型:只讀 InputText + 複製按鈕(InputGroup)
    • 格式:https://example.com/companies/company_id?campaign={slug}
    • 規則:
      • 系統自動生成流水號(格式:campaign_001, campaign_002, …)
      • 新增時自動產生,編輯時顯示現有 slug
      • 不可編輯
      • 可點擊「複製連結」按鈕複製完整 URL
    • 提示文字:「系統自動生成,無法編輯。」
  3. 職缺選擇(必填)

    • 類型:PrimeVue DataTable + Checkbox 勾選 + 全選 checkbox
    • 篩選列:關鍵字搜尋(InputText)+ 職務類別 / 工作性質 / 地點(PrimeVue Select)
    • 下拉選單選項採「有結果才顯示」:只顯示目前職缺清單中 count > 0 的選項,避免選到空集合
    • 三個 filter(職務類別 / 工作性質 / 地點)來源是「本次活動已選職缺集合」,不是人力銀行全站所有字典值。
    • 範例:若本次活動已選職缺只分布在「桃園」「新竹」,則地點下拉只顯示這兩個選項,不應出現台北、台中等無對應職缺的地點。
    • 職缺列表以 DataTable 呈現,支援分頁(每頁 8 筆)
    • 顯示「已選 N 筆」Badge
    • 說明:HR 從公司現有職缺清單中勾選要在此活動中展示的職缺,至少須選擇 1 個;提供全選 checkbox 可一次勾選/取消勾選清單內所有職缺
    • 規則:
      • 至少選擇 1 個職缺,否則無法儲存
      • 選取的職缺 ID 列表儲存至活動(job_ids
      • 活動落地頁僅展示被選取的職缺;若職缺下架或刪除,自動從清單移除
  4. 預設篩選條件(選填)

    • 類型:三個下拉選單
    • 欄位與選項:職務類別工作性質地點由後端依「目前擁有職缺」動態回傳,只顯示 count > 0 的選項,不顯示空集合選項。
    • 規則:
      • 所有欄位都是選填
      • 設定後,活動落地頁會自動套用這些篩選條件作為初始過濾
      • 用戶仍可在落地頁自行調整篩選條件
  5. 一鍵加入人才庫預填設定(選填,進階)

    • 目的:於求職者登入後/填履歷流程時,先帶入部分欄位,提升轉換率。
    • 可先進入「預填設定」tab 編輯內容,但其生效前提是活動可被建立/更新。
    • 儲存門檻:若「基本設定」尚未完成(活動標題未填或未選職缺),則在「預填設定」tab 的「儲存」按鈕需為 disabled。
    • 提示方式:當儲存 disabled 時,hover 顯示提示「請先完成基本設定(活動標題與至少 1 個職缺)後,才可儲存預填設定。」

表單驗證規則

  • 活動標題:必填
  • 職缺選擇:必填(至少選擇 1 個職缺,篩選條件為輔助用途,選填)
  • 預設篩選條件:選填(可全部不選)
  • 一鍵加入人才庫預填設定:選填;但若由「預填設定」tab 觸發儲存,仍需先滿足基本設定必填條件(活動標題 + 至少 1 個職缺)

表單提交

  • 驗證失敗時顯示錯誤訊息,不允許提交
  • 驗證通過後執行 onSubmit callback
  • 只傳遞有值的篩選條件與選取的職缺 ID 列表

2. 前台:活動落地頁(Candidate Landing)

設計策略:使用公司頁面 + 預設篩選條件

版面結構(與公司頁面相同):

  • 公司 Header(公司 Logo、名稱、基本資訊)
  • 公司介紹
  • 職缺機會區塊:
    • 職缺篩選列(工作性質、職務類別、地點)
    • 職缺卡片列表
    • 無限下拉(Infinite Scroll):職缺列表採無限下拉方式載入,不使用分頁控制;使用者向下捲動時自動載入更多職缺

預設篩選條件

  • 活動落地頁載入時,會根據活動設定的篩選條件自動設定下拉選單
  • 篩選下拉只顯示目前有職缺結果的選項(count > 0),避免使用者選到空集合
  • 活動頁三個 filter(職務類別 / 工作性質 / 地點)同樣以「該活動已綁定的職缺集合」動態產生,不採全站職缺字典。
  • 範例:活動綁定職缺若只有桃園與新竹,地點 filter 僅顯示「桃園」「新竹」。
  • 用戶仍可自行調整篩選條件
  • 職缺列表會根據篩選條件動態更新

URL 結構

  • 格式:/companies/{company_id}?campaign={campaign_slug}&category={category}&nature={nature}&location={location}
  • Query parameters:
    • campaign:活動 slug(必填)
    • category:職務類別(選填)
    • nature:工作性質(選填)
    • location:地點(選填)

一鍵加入人才庫與多階段流程

  • 求職者在活動落地頁可點擊「一鍵加入人才庫」(或等同入口),進入多階段流程,例如:第 1 階段註冊/登入 → 下一步 → 第 2 階段填寫基本資料/履歷相關欄位 → … → 加入人才庫。此行為本質為「將履歷設為公開 + 記錄來訪」,並非針對特定職缺投遞;履歷來源(source)記為該活動。
  • 第 1 階段註冊/登入:UI 畫面使用 Main Site Auth 組件(main site auth register、main site login),與主站登入/註冊畫面一致,不另做自訂表單。但後端 API 為活動專用(新 API):主站寄送「驗證連結」,活動流程寄送「驗證碼 OTP」,兩者信件 template 不同,不可沿用主站 register / login API。詳見 §9.5。
  • 第 1 階段預填(PM_29 update):可由活動設定帶入 residency_city(居住地)與 identity_type(在台外籍工作身份);進入第一階段時顯示預填值,使用者可改寫後再送出。
  • 狀態還原:使用者在流程中若重新整理頁面關閉後再次從同一活動連結進入,系統應記住目前階段與已填寫欄位,並還原至中斷前的進度,避免從頭填寫。
  • 同一使用者的辨識:在尚未登入前,以同一裝置為準(例如 Cookie、localStorage 的 key 含 campaign_id);登入完成後可將草稿與帳號綁定。實作細節見業務規則 §7。
  • 帳號建立時點、驗證碼用途及「等驗證碼時重整」後之登入與驗證行為,見業務規則 §7.5。

活動落地頁一鍵加入流程圖(狀態:註冊/登入 階段 → 註冊= Email or Google/登入=一般 or Google → 是否驗證 → 是否填寫個人資料 → 是否有履歷):

flowchart TD
    Start[點擊「一鍵加入人才庫」] --> Stage[註冊/登入 階段]

    Stage --> Reg[註冊]
    Stage --> Login[登入]

    Reg --> RegMethod{Email 註冊 or Google 註冊?}
    RegMethod -->|Email 註冊| RegEmail[輸入 email、密碼]
    RegEmail --> RegCheck{此 email 已註冊?}
    RegCheck -->|是| ErrReg[顯示「此 email 已有人註冊,請改用登入」]
    RegCheck -->|否| NeedOtpReg[發送驗證碼至 Email]
    NeedOtpReg --> InputOtp

    RegMethod -->|Google 註冊| RegGoogle[Google 註冊]
    RegGoogle --> Verified2[verified = true<br>不需驗證碼]

    Login --> LoginMethod{一般登入 or Google 登入?}
    LoginMethod -->|一般登入| LoginEmail[輸入 email、密碼]
    LoginEmail --> LoginCheck{帳號已 verified?}
    LoginCheck -->|是| Verified3[已驗證,進入下一階段]
    LoginCheck -->|否| NeedOtpLogin[發送驗證碼]
    NeedOtpLogin --> InputOtp

    LoginMethod -->|Google 登入| LoginGoogle[Google 登入]
    LoginGoogle --> Verified5[verified = true]

    subgraph OtpFlow [共用驗證碼流程]
        InputOtp[輸入驗證碼]
        OtpCheck{驗證成功?}
        OtpFail[顯示錯誤或過期]
        WaitOtp[等待可重發倒數]
        ResendOtp[重新發送驗證碼]
        InputOtp --> OtpCheck
        OtpCheck -->|是| VerifiedOtp[verified = true]
        OtpCheck -->|否| OtpFail
        OtpFail --> WaitOtp
        WaitOtp --> ResendOtp
        ResendOtp --> InputOtp
    end

    VerifiedOtp --> ProfileCheck
    Verified2 --> ProfileCheck
    Verified3 --> ProfileCheck
    Verified5 --> ProfileCheck

    ProfileCheck{已填寫基本資料<br>profileFilled?}
    ProfileCheck -->|否| FillProfile[填寫基本資料]
    FillProfile --> ResumeCheck
    ProfileCheck -->|是| ResumeCheck

    ResumeCheck{已有可投遞履歷<br>hasResume?}
    ResumeCheck -->|否| NewResume[新增履歷]
    ResumeCheck -->|是| ChooseResume[選擇要寄送的履歷<br>或撰寫一份新的]
    NewResume --> Submit[加入人才庫]
    ChooseResume --> Submit
  • 約束:入口為註冊時,profileFilled、hasResume 必為 false;入口為登入時,若 hasResume 為 false 則 profileFilled 必為 false。若用戶已有履歷(hasResume = true),再次點擊時跳至 Step 3(選擇履歷),不重複走完整流程。詳見 §7.6。

驗證碼流程共用:註冊與登入之 Email 驗證碼流程共用同一套 UI 與邏輯(輸入驗證碼 → 驗證成功? → 成功則 verified/失敗則錯誤或過期 → 等待可重發 → 重新發送 → 回到輸入);主站 Auth 可抽成共用 OTP 組件,活動落地頁沿用 Main Site Auth 即受益。驗證碼失敗與重發規則見 §8.1.1。API 是否註冊/登入共用由實作時決定,本 PRD 不訂技術細節。

3. 人才庫 Mock(Talent Pool Mockup)

版面結構(與實際人才庫一致):

  • 左側篩選欄:
    • 職缺下拉
    • 活動來源下拉(新增)
    • 關鍵字搜尋
    • 時間區間選擇
  • Tab 切換:應徵 / 來訪
  • 履歷列表(與實際人才庫的履歷卡片一致)

活動來源篩選

  • 下拉選單包含:
    • 公司活動(所有業務可見,藍色標示)
    • 業務頁面(只顯示當前業務自己的頁面,綠色標示)
  • 已刪除的活動會從下拉選單中移除
  • 從活動管理點擊「來訪」時,會自動帶入該活動來源篩選

來源顯示與互動

  • 人才卡片上會顯示來源標籤(支援複數標籤)
  • 標籤顏色區分:
    • 公司活動:藍色(#e3f2fd 背景,#1976d2 文字)
    • 業務頁面:綠色(#e8f5e9 背景,#388e3c 文字)
  • 標籤可點擊:點擊標籤等同於在左側 filter 選擇該活動來源
  • 下拉選單選項也有對應的顏色區分

多來源支援

  • 如果求職者訪問了多個活動或業務頁面,會顯示多個標籤
  • 篩選時,選擇任一來源都能找到該求職者
  • 統計邏輯:
    • 來訪統計:所有訪問過的來源都計入(多歸屬)

業務規則

1. URL Slug 生成規則

  • 自動生成:系統自動產生流水號格式的 slug(campaign_001, campaign_002, …)
  • 不可編輯:slug 一旦生成後不可修改
  • 唯一性:每個活動的 slug 都是唯一的
  • 顯示與複製:表單中顯示完整 URL(包含 query parameters),提供「複製連結」按鈕

理由

  • 活動頁面不需要 SEO(僅透過 QR Code 或直接連結分享)
  • 使用流水號簡化技術實作,避免使用者輸入錯誤
  • 確保 URL 穩定,避免 QR Code 失效

2. 活動落地頁設計策略

使用公司頁面 + 預設篩選條件

  • 活動落地頁直接使用既有的公司頁面組件
  • 透過 URL query parameters 傳遞活動 ID 和預設篩選條件
  • 公司頁面載入時,根據 query parameters 自動設定篩選條件
  • 活動管理與活動落地頁的篩選下拉皆採「有結果才顯示」:僅顯示目前職缺可命中的職務類別/工作性質/地點(count > 0
  • 用戶仍可自行調整篩選條件

優勢

  • 不需要維護獨立的活動頁面代碼
  • 公司新增符合條件的職缺時,活動頁面會自動顯示
  • 更靈活,用戶可以自行調整篩選條件

3. 必填欄位驗證

以下欄位為必填:

  • 活動標題:不可為空

以下欄位為選填:

  • 預設篩選條件:職務類別、工作性質、地點(可全部不選,顯示所有職缺)

表單提交前會進行驗證,必填欄位未填寫時,顯示錯誤訊息並阻止提交。

3.1 篩選下拉選項規則(避免空集合)

  • 適用範圍:活動管理(CampaignEditorForm)與活動落地頁(Candidate Landing)的職務類別/工作性質/地點下拉。
  • 選項來源:依目前可見職缺集合即時計算,不是顯示 DB 全量字典。
  • 顯示條件:僅顯示 count > 0 的選項;count = 0 不顯示。
  • 目的:避免下拉出現選了就沒有資料的空集合體驗。
  • 編輯活動(後台)三個 filter:以「本次活動目前已選 job_ids 對應的職缺集合」計算可選項。
  • 活動頁(前台)三個 filter:以「該活動可展示職缺集合(= 已綁定且仍有效的職缺)」計算可選項。
  • 共同原則:不是用人力銀行全站所有種類,而是只列出這次活動職缺實際存在的清單值。

3.2 下拉元件互動規則(與既有流程一致)

  • 本功能的下拉元件互動規則需與既有「會員註冊/會員中心編輯資料/履歷編輯」一致。
  • 不提供「不預填」作為下拉選項值。
  • 使用者已選定值後,應提供清空回到空值的互動(例如欄位內 x 清除按鈕),並可再重新選擇有效值。

4. 活動刪除規則

刪除功能

  • 活動列表的操作下拉選單中提供「刪除」選項
  • 刪除前需確認:「確定要刪除「{活動名稱}」嗎?刪除後,求職者的活動來源篩選將無法使用此活動。」

刪除後的影響

  • 活動從列表中移除
  • 人才庫的「活動來源」下拉選單中,該活動選項會被移除
  • 已刪除活動的 enc_id 會被記錄在 deletedCampaignIds 陣列中
  • 求職者若原本透過該活動來源篩選,刪除後將無法再使用該篩選條件

技術實作

  • MockupTalentPoolPage 接收 deletedCampaignIds prop
  • campaignOptions computed 會過濾掉已刪除的活動 ID
  • 刪除操作在 recruitment-campaign-demo.vue 中處理,更新 deletedCampaignIds 狀態

4.1 活動數量上限

  • 同時開啟上限:每間公司最多同時開啟 10 個活動(status = 1)。若已達上限,需先關閉(下架)既有活動才能開啟新活動。
  • 活動總數上限:每間公司的活動總數(含已下架)最多 100 個。若已達上限,需先刪除不需要的活動才能新增。
  • 驗證時機:新增活動時檢查總數上限;切換狀態為「開啟」時檢查同時開啟上限。超過上限時顯示錯誤提示,阻止操作。

5. 點擊數(PV)計算規則

  • 去重維度:同一活動下,以 同一 IP同一裝置(由 Cookie、device_id 等辨識)在 同一自然日(依系統時區)內只計入 1 次點擊。
  • 目的:避免同一人重複點擊連結導致點擊數膨脹,使報表更貼近「不重複觸達」。
  • 實作責任:前端於活動落地頁載入時呼叫「記錄點擊」API;後端依 IP 與可選的 device_id/Cookie 及日期判斷是否已計過,未計過才將該活動 PV +1。

6. 統計、追蹤與事件記錄(Log)

為利於後續轉換漏斗與成效分析,建議蒐集以下事件與欄位(可由前端發送或後端於請求時記錄):

階段/事件觸發時機登入狀態建議記錄欄位備註
點擊/落地頁載入使用者開啟活動落地頁(URL 含 campaign)不需登入(匿名)campaign_idtimestamp、IP、device_id、referrer、是否當日該來源首次PV 去重;HR 視角:多少人掃了 QR Code/點了連結
篩選變更求職者在落地頁變更職缺篩選條件不限campaign_idcategorynaturelocation、timestamp分析篩選偏好
職缺列表曝光職缺列表渲染或進入視窗不限campaign_idjob_ids 或列表版本、timestamp可選:捲動深度
職缺點擊/查看點擊單一職缺卡片或進入職缺詳情不限campaign_idjob_id、user_id(若已登入)、timestamp興趣與熱門職缺
註冊/登入完成在活動流程內完成註冊或登入剛完成登入campaign_id、註冊/登入方式、user_id、timestamp轉換:點擊 → 註冊
來訪(計入人才庫)已登入使用者進入帶 campaign 的落地頁時記錄需已登入campaign_id、user_id、timestamp、session_id(可選)HR 視角:多少人真的有帳號且來訪
加入人才庫送出已登入使用者完成一鍵加入流程,履歷設為公開時(非針對特定職缺,source = 該活動)需已登入campaign_id、user_id、timestampHR 視角:多少人真的送出了履歷
  • 各事件由前端或後端依現有架構擇一記錄;若與既有 analytics 規範並存,可於實作時對齊欄位與命名。

7. 一鍵加入/註冊流程狀態持久化

  • 目標:活動落地頁「一鍵加入人才庫」之多階段流程(註冊 → 下一步 → 第二階段填寫等)在重新整理稍後再次進入時,能還原目前階段與已填寫內容。
  • 辨識同一使用者
    • 未登入:以同一裝置為準,例如 Cookie、localStoragesessionStorage 的 key 含 campaign_id(如 campaign_apply_{campaign_id}),或後端以 Cookie/device_id 建立匿名草稿。
    • 已登入:可將進行中的草稿與帳號綁定,並可選擇清除舊的匿名草稿。
  • 儲存方式(擇一或混合,由實作決定):
    • 前端localStoragesessionStorage 儲存目前階段(step)與各階段已填欄位(JSON);sessionStorage 關閉分頁即清空,localStorage 可支援關閉後再開仍還原。
    • 後端:建立「投遞草稿」或 apply session API,每步送出時寫入;重新載入時由前端取得草稿並還原。利於跨裝置或敏感欄位只存後端。
  • 效期:建議定義草稿/進度保留期限(例如 24 小時或 7 天),過期後清除或提示使用者重新填寫。
  • 敏感資料:若流程含身分證等個資,依產品規範決定是否僅存後端或加密後再存前端。

7.1 繼續填寫之進入點

  • 進入點:僅支援再次從同一活動連結進入(使用者保留原活動連結,例如 QR Code、email、LINE 等,再次點擊進入)。
  • 辨識方式:以同一裝置為準,例如 Cookie、localStoragesessionStorage 的 key 含 campaign_id(如 campaign_apply_{campaign_id}),或後端以 Cookie/device_id 建立匿名草稿;登入完成後可將草稿與帳號綁定。
  • 還原行為:再次從同一活動連結進入時,系統依上述辨識方式還原目前階段與已填寫欄位,導向中斷前的步驟。
  • 換裝置或清除儲存:若使用者換裝置或清除 Cookie/localStorage,無法還原進度,需從頭填寫;本流程不提供「輸入 email 發送繼續填寫連結」等跨裝置補救。

7.5 註冊、驗證與重整後登入行為

帳號與驗證的定義

  • 帳號建立時點:使用者在註冊流程中點擊「註冊」(已填寫 email、密碼等並送出)時,帳號即已建立。驗證碼不用來建立帳號,僅用於「確認 email 為真實」。
  • 驗證碼用途:驗證碼透過 Email 發送,用途為確認該 email 為真實、有人使用。通過驗證後,才允許進入下一階段(例如建立履歷)。第三方登入(如 Google)不需此驗證。
  • 密碼規則:與站上既有註冊流程一致(強度、長度、確認密碼等)。

註冊流程中「等驗證碼時」重整後的行為

  • 重整當下的狀態:帳號已存在(因已點過註冊);尚未登入(未完成驗證碼、無有效 session);帳號狀態為**「尚未完成 email 驗證」**(還沒認證過)。
  • 再次點擊「一鍵加入人才庫」時:顯示登入/註冊選項;應引導使用者選擇登入(因帳號已存在,不應再走註冊一次)。
  • 選擇登入後:使用者輸入帳號(email)與密碼後進入登入流程。因帳號狀態仍為**「還沒認證過」仍須發送驗證碼(Email),不得跳過。使用者填寫此次發送的驗證碼,驗證通過後視為已認證**,並可進入建立履歷階段(或還原至中斷前的步驟)。
  • 若使用者誤點「註冊」且輸入已註冊的 email:後端回傳該 email 已註冊;畫面顯示**「此 email 已經有人註冊過了,可以轉登入」**(或類似文案),並引導改為登入。

重整後流程摘要

  • 不會是「已經登入」且跳過驗證碼。
  • 會是:還沒登入 → 手動點登入 → 觸發寄送驗證碼 → 填寫驗證碼(因狀態仍是「還沒認證過」)→ 通過後可建立履歷。
  • 若誤點註冊且同 email:顯示「此 email 已有人註冊,可轉登入」。

7.6 一鍵加入:入口與狀態約束(API/後端對齊用)

供後端實作與驗證用,精簡列出狀態、約束與必要錯誤。

狀態與入口

  • 入口register(新用戶)/login(既有用戶)。
  • 使用者狀態verified(是否完成 email 驗證)、profileFilled(是否已填寫完整基本資料)、hasResume(是否已有履歷)。

約束(API 可依此驗證或回傳)

  • 入口 = registerprofileFilledhasResume 必為 false。
  • 入口 = login → 若 hasResume === falseprofileFilled 必為 false(要寫履歷須先完成基本資料)。
  • Email 註冊:須經驗證碼流程後才算 verified。
  • Google 登入/註冊:不需驗證碼,視為 verified。
  • 登入:若帳號尚未 verified,仍須走驗證碼流程。

「加入人才庫」的實際 API 行為

「加入人才庫」不是一隻獨立的 API,其實際行為為:

  • UI:使用者勾選「同意公開履歷」→ 此為法律告知,勾選本身不觸發 API。
  • 送出:呼叫既有的 update resume API,將該履歷設為公開狀態。不投遞到任何特定職缺,來源(source)記為該活動。
  • 詳見 §9.4。

已有履歷的用戶再次加入

  • 若用戶已擁有履歷(hasResume === true),再次點擊「一鍵加入人才庫」時,跳至 Step 3(選擇履歷),讓用戶可再次送出或更換履歷。
  • 送出動作同樣是 update resume API(可能更換為不同履歷)。
  • 人才庫中不會產生多份履歷,以最新送出的那份為主(覆蓋更新)。

錯誤/邊界(API 需回傳或處理)

  • 註冊時若 email 已存在 → 回傳「已註冊,請改用登入」等錯誤碼/訊息。

8. 註冊階段錯誤與邊界情境

一鍵加入人才庫流程中,註冊/登入階段可能發生的錯誤與邊界情境如下,實作時需有對應處理或提示。

8.1 註冊/登入失敗

情境建議處理/備註
註冊失敗(後端錯誤、必填未填、格式不符等)顯示明確錯誤訊息,引導使用者修正欄位或稍後再試。
Email 已被註冊引導「使用登入」或「忘記密碼」,勿僅顯示註冊失敗。
登入失敗(帳密錯誤、帳號停用/鎖定)顯示錯誤說明,並提供重試或解鎖方式(如忘記密碼)。
驗證碼錯誤或過期(OTP)提示錯誤或已過期;失敗後須等待可重發時間才能再次發送,使用者可重試直到驗證成功。詳見 §8.1.1。
第三方登入失敗(使用者取消、Token 過期、網路錯誤)提示重試或改以 Email 註冊/登入。

8.1.1 驗證碼(OTP)失敗與重發

失敗情境與處理

失敗情境處理/提示
驗證碼輸入錯誤(與發送之 OTP 不符)顯示「驗證碼錯誤,請重新輸入」;不消耗重發次數,使用者可立即修正後再次送出驗證。
驗證碼已過期(超過效期如 5–10 分鐘)顯示「驗證碼已過期,請重新取得驗證碼」;需點擊「重新發送」並進入重發等待(見下)。
驗證碼格式錯誤(未填、長度不符等)顯示欄位級錯誤,引導正確格式;送出前可前端驗證。

重發規則

  • 失敗後等待時間:使用者點擊「重新發送驗證碼」後,需經過等待時間(例如 60 秒或 1 分鐘,依產品設定)才能再次點擊發送;等待期間按鈕顯示倒數(如「60 秒後可重新發送」),倒數結束後才可再次發送。
  • 直到成功為止:驗證失敗(錯誤或過期)後,不離開流程;使用者可依上述規則重新取得驗證碼並再次輸入,重複直到驗證成功,通過後進入下一階段(填寫基本資料/履歷)。
  • 發送頻率限制(同一 Email/IP)依 §8.5 限流與安全,與「單次失敗後可重發倒數」可並存(例如:單次 60 秒可重發,同一 Email 每 N 分鐘最多 M 次)。

8.2 密碼機制

  • 密碼強度、長度、格式及「確認密碼」等規則,與站上既有註冊流程一致,不另訂規則。

8.3 時間與效期

情境建議處理/備註
填寫時間過久(頁面閒置逾時)定義 session 或 token 逾時;逾時後提示重新登入或從當前步驟繼續/重填。
草稿/進度效期過期(依 §7)提示「進度已過期,請重新填寫」,並可清除舊草稿。
驗證碼效期(如 5–10 分鐘)過期時提示重新發送驗證碼。

8.4 網路與後端

情境建議處理/備註
網路中斷或請求失敗顯示「網路不穩定,請稍後再試」並提供重試。
API 逾時或服務異常(5xx 等)同上,並可記錄 log 供排查。
重複送出(連點、多開分頁送出)送出後按鈕 disabled 或防雙送;後端可做冪等處理。

8.5 限流與安全

情境建議處理/備註
驗證碼發送頻率限制(同一 Email/IP)提示「請 N 分鐘後再試」或顯示可重發倒數。
登入嘗試過多導致鎖定提示鎖定時間或引導「忘記密碼」等解鎖方式。

8.6 狀態與流程邊界

情境建議處理/備註
活動已關閉或已刪除(回來繼續填時)提示「活動已結束」,並可導回首頁或職缺列表。
還原失敗(localStorage 被清、換裝置等)提示「無法還原進度,請重新填寫」。
多分頁/多開同時填寫約定以最後寫入為準,或提示「請在單一分頁操作」。

8.6.1 活動下架時的畫面與流程中斷

  • 進入活動 URL 時:活動下架後,使用者連至該活動 URL 時,不顯示公司與職缺;畫面顯示「找不到此活動」或「活動已下架」。
  • 填寫流程中:若使用者已在第二或第三階段填寫,於點擊「下一步」的當下檢查活動狀態;若活動已下架,跳轉至「活動已下架」提示,不允許繼續送出。

8.7 驗證與業務規則

情境建議處理/備註
必填欄位未填前端與後端皆驗證,並顯示欄位級錯誤訊息。
格式錯誤(Email、手機、生日等)即時或送出時驗證並提示正確格式。
業務限制(如年齡下限)註冊時驗證並說明不符合原因。

9. 一鍵加入人才庫:各階段系統行為定義

9.1 架構決策(已確認)

採用 方案 A:各步驟即時送出

  • Step 1(登入/註冊):驗證完成 → 用戶取得登入狀態,進入 Step 2
  • Step 2(基本資料):用戶點「下一步」→ 系統即時儲存基本資料
  • Step 3(履歷):用戶點「送出」→ 系統將選定/建立的履歷設為公開 → 返回活動頁 → 系統記錄來訪

「一鍵加入人才庫」的實際涵義
此流程的目的是讓求職者的履歷進入企業可見的人才庫。完成流程後,履歷設為公開,用戶以登入狀態回到活動落地頁,系統記錄該用戶對此活動的「來訪」。人才庫的「來訪」頁面即可透過活動來源篩選器篩選出此次流程中公開履歷的求職者。

不涉及「投遞履歷(應徵)」動作,來訪計數(visitors_count)增加。

進度還原策略:前端使用 localStorage 儲存目前步驟(step number);因各步驟資料已即時寫入後端,重整後系統查詢登入狀態與資料完成度,自動還原至正確步驟起點。


9.2 Step 1:登入 / 註冊

9.2.1 整體說明

Step 1 的 Email 登入/註冊為新的驗證方式,Email 驗證從「點擊信件連結」改為「在信件收到 6 碼數字驗證碼,回到網頁輸入」。
Google 登入/註冊沿用現有機制,不改變。


9.2.2 Email 註冊

使用者動作:輸入 email、密碼、確認密碼 → 點擊「註冊」→ 收到驗證碼 Email → 在網頁輸入驗證碼 → 點擊「下一步」

系統行為(依序)

  1. 帳號建立
    用戶點擊「註冊」時,系統立即建立帳號。此時帳號狀態為「未驗證(unverified)」。
    若 email 已存在 → 不建立帳號,顯示「此 email 已有人註冊,請改用登入」。

  2. 發送驗證碼 Email
    帳號建立成功後,系統發送含 6 碼數字驗證碼的 Email。
    驗證碼效期:10 分鐘。同一 email 每 60 秒最多重發一次(依 §8.5 限流規則)。

  3. 驗證碼確認
    用戶在網頁輸入收到的 6 碼驗證碼並送出:

    • 正確 → 帳號標記為「已驗證(verified)」,用戶取得登入狀態,進入 Step 2。
    • 錯誤 → 顯示「驗證碼錯誤,請重新輸入」,不離開輸入畫面。
    • 過期 → 顯示「驗證碼已過期,請重新發送」,允許重新發送。
  4. 重新發送驗證碼
    倒數結束後用戶可重新發送。系統發送新驗證碼,舊驗證碼同時失效。


9.2.3 Email 登入

使用者動作:輸入 email、密碼 → 點擊「登入」→(若未驗證)收到驗證碼 → 在網頁輸入驗證碼 → 點「下一步」

系統行為(依序)

  1. 驗證帳密

    • 帳密正確且已驗證 → 用戶直接取得登入狀態,進入 Step 2(或依狀態進入對應步驟)。
    • 帳密正確但未驗證 → 系統發送驗證碼至 email,進入驗證碼輸入畫面。
    • 帳密錯誤或帳號不存在 → 顯示「帳號或密碼錯誤」。
  2. 驗證碼確認(未驗證時)
    流程與 §9.2.2 步驟 3 相同。


9.2.4 Google 登入 / 註冊

沿用現有 Google 登入機制,後端無需新增或修改任何功能
完成後帳號視為已驗證,用戶取得登入狀態,進入 Step 2(或依狀態進入對應步驟)。

注意(前端實作):原有 Google 登入完成後會跳轉首頁。在活動落地頁情境中,前端需在觸發 Google 登入前將 campaign 上下文暫存,取得登入狀態後不跳轉首頁,改為繼續一鍵加入流程。此為前端路由調整,與後端無關


9.2.5 Step 1 完成條件

無論透過哪種方式,Step 1 完成的標誌為:用戶已取得登入狀態且 verified = true


9.2.6 Step 1 預填欄位(PM_29 update)

活動可設定第一階段的預填值,適用於邀請 QR Code V2:

欄位代碼顯示名稱規則
residency_city居住地若活動有設定預填值,第一階段表單開啟時自動帶入;使用者可改寫。
identity_type在台外籍工作身份若活動有設定預填值,第一階段表單開啟時自動帶入;使用者可改寫。

預填值僅作為初始值,實際儲存以使用者最終提交內容為準。

UI/流程一致性(與既有站點一致)

  • 活動頁一鍵加入流程中的 residency_cityidentity_type 互動與會員中心「編輯會員資料」一致,不另定義新流程。
  • 居住地採「縣市 → 區域」聯動:先選縣市(例如台北市)後才出現對應行政區選項,且需提供搜尋(search bar)。
  • 前台註冊頁的「居住地」不拆成兩個獨立下拉;以單一欄位元件完成選擇(元件內可包含縣市/區域聯動與搜尋)。
  • 下拉選單不提供「不預填」選項;若使用者已選值,行為以不可清空為原則(與既有註冊/履歷編輯一致)。

套用條件

  • 僅在使用者需要執行 Step 1(註冊/登入)時才套用此預填。
  • 若使用者已完成註冊且目前為登入狀態,Step 1 不會出現,故不套用 Step 1 預填。

9.3 Step 2:填寫基本資料

9.3.1 整體說明

Step 1 完成後,系統判斷用戶是否已填寫基本資料(profileFilled):

  • profileFilled = false → 顯示 Step 2 表單
  • profileFilled = true → 跳過 Step 2,直接進入 Step 3
9.3.2 進入 Step 2 時

系統讀取該用戶現有的基本資料(若曾填過),預填入表單各欄位。新用戶表單為空白。

需填寫的欄位

欄位說明必填
name姓名
birthday生日(格式 yyyy-MM-dd
mobile手機號碼
residency_city居住縣市
residency_district居住行政區
nationality國籍(國家代碼,如 TWVNID
identity_type在台外籍工作身份(對應 pm_27 定義的選項值)選填
9.3.3 用戶點「下一步」時

系統即時儲存上述欄位:

  • 儲存成功 → 系統將 profileFilled 標記為 true,進入 Step 3。
  • 儲存失敗(必填未填、格式錯誤等)→ 顯示欄位級錯誤,不進入 Step 3。

profileFilled 定義:所有必填欄位均已提交且通過驗證。


9.4 Step 3:履歷選擇 / 建立

9.4.1 整體說明

Step 2 完成後,系統判斷用戶是否已有公開履歷(hasResume):

  • hasResume = false → 顯示「快速建立履歷」表單(§9.4.3)
  • hasResume = true → 顯示「選擇履歷」畫面(§9.4.2),並提供「現場再撰寫一份」選項

hasResume 定義:用戶名下至少有一份公開且完整可被企業看到的履歷。

Step 3 的核心目的:確保用戶有一份公開履歷,使其能在企業人才庫的「來訪」頁面中被看到。


9.4.2 已有公開履歷時:指定一份

使用者動作:看到現有履歷清單 → 選擇一份 → 點擊「送出」
(或選「現場再撰寫一份」→ 改為顯示 §9.4.3 的表單)

系統行為

  1. 顯示用戶名下所有公開履歷的清單。
  2. 用戶選定後點「送出」:系統確認該履歷維持公開狀態(此時履歷已是公開,不需額外操作),完成 Step 3。
  3. 流程結束,返回活動落地頁(見 §9.5)。

9.4.3 沒有公開履歷時:快速建立新履歷

使用者動作:填寫以下欄位 → 勾選「同意公開履歷」→ 點擊「送出」

系統行為

用戶點「送出」時,系統建立一份新履歷並將其設為公開。完成後流程結束,返回活動落地頁(見 §9.5)。

個人基本資料預填(PM_29 update):若活動有設定以下欄位預填值,履歷新增表單(仍屬 Step 2)載入時先帶入;使用者可在送出前修改,送出時以修改後值寫入。

快速建立履歷欄位原則(實作範圍不預設)

  • 本 PRD 不預先限制「快速建立履歷」的完整欄位清單與 API payload 細節;欄位定義、驗證與資料結構由 BE 依既有履歷模型與實際實作方案決定。
  • 產品規則僅要求:快速建立流程需能完成「建立可用履歷」並讓使用者完成加入人才庫。
  • agree_to_public_resume 為必要同意項(必須勾選)並對應履歷公開設定;未同意不得完成流程。
  • 其餘欄位(例如求職狀態、學歷、工作型態、可上班日、期望薪資等)與既有履歷編輯體驗/字典一致即可,實際 required/optional 與送出格式由 BE/FE 實作對齊。

希望待遇(expected_salary)互動規則

  • 與既有「職缺編輯」中的薪資欄位互動一致。
  • 當選擇「自訂薪資」時,需顯示薪資單位與可輸入數字的 free text 欄位(數字代表薪資)。

本次指定可預填欄位(PM_29 update)

  • job_seeking_status(求職狀態)
  • education_period(就學狀態)
  • school_name(學校名稱)
  • degree(學位)
  • work_types(工作性質)
  • available_date(可上班日)
  • expected_salary(希望待遇)

套用條件

  • 僅在使用者需要建立新履歷(hasResume = false)時,才套用上述 Step 2(履歷新增)預填。
  • 若使用者已完成個人基本資料(profileFilled = true)且已有履歷(hasResume = true),流程會直接進入「選擇履歷」,不套用任何預填設定。
  • 若使用者已完成註冊與個人基本資料,本次活動的預填設定可忽略,不覆蓋既有資料。

9.5 Step 3 完成後:返回活動頁與記錄來訪

9.5.1 系統行為

Step 3 完成後:

  1. 流程結束,前端顯示成功畫面(「恭喜,已進入人才庫」)。
  2. 用戶返回活動落地頁(含 campaign 識別參數)。
  3. 活動落地頁載入時,系統依現有機制記錄此次點擊:
    • 因用戶此時已登入,系統同時將此用戶記錄為本活動的「來訪(visitors)」。
    • visitors_count + 1
  4. 此後,人才庫「來訪」頁面即可透過活動來源篩選器篩選出此用戶的公開履歷。

注意:此流程不涉及「應徵」動作。

9.5.2 去重說明
  • 若用戶曾在今日(同一自然日)已被記錄為來訪,PV 計數不重複累加,但「來訪」記錄可能已存在。
  • 用戶完成此流程後若再次點擊「一鍵加入人才庫」:因已有公開履歷(hasResume = true),系統直接跳至 Step 3 選擇履歷畫面(不需重走 Step 1、Step 2)。

9.6 進入流程時的狀態判斷

何時需要查詢狀態

用戶點擊「一鍵加入人才庫」時,若已登入,系統需知道目前的完成狀態,以決定從哪個步驟開始。

判斷欄位
欄位說明
verified是否完成 Email 驗證(Google 登入者永遠為 true)
profile_filled是否已填寫完整基本資料(§9.3 定義)
has_resume是否已有公開且完整的履歷(§9.4.1 定義)
判斷結果對應步驟
情境顯示步驟
未登入直接顯示 Step 1
已登入,verified = false顯示 Step 1(登入 + OTP 驗證)
已登入,verified = trueprofile_filled = false跳到 Step 2
已登入,verified = trueprofile_filled = truehas_resume = false跳到 Step 3(新建履歷)
已登入,verified = trueprofile_filled = truehas_resume = true跳到 Step 3(選擇/更換履歷)

9.7 進度還原行為(已確認)

  • 前端僅用 localStorage 儲存目前步驟編號(不儲存欄位內容)。
  • 重整後:系統查詢登入狀態與資料完成度,自動還原至正確步驟起點。
  • Step 3 填到一半的欄位重整後不還原(接受此行為,用戶從 Step 3 起點重填)。
  • 用戶已有公開履歷後再次點擊「一鍵加入人才庫」:跳到 Step 3 選擇/更換履歷畫面。

Mock 資料結構

MockCampaignItem

interface MockCampaignItem {
  enc_id: string; // 活動 ID(與 slug 相同)
  name: string; // 活動標題(必填)
  status: 0 | 1; // 狀態(0: 關閉, 1: 開啟)
  pv: number; // 點擊數
  visitors_count: number; // 來訪數
  slug: string; // URL slug(自動生成,只讀)
  // 職缺選擇(必填,活動落地頁僅展示此列表中的職缺)
  job_ids: string[]; // 選取的職缺 ID 列表(至少 1 個)
  // 預設篩選條件(選填,活動落地頁的初始篩選狀態)
  category?: string; // 職務類別(選填)
  work_nature?: string; // 工作性質(選填)
  location?: string; // 地點(選填)
  // 一鍵加入流程預填設定(PM_29 update)
  quick_apply_prefill?: {
    // Step 1
    residency_city?: string; // 居住地
    identity_type?: string; // 在台外籍工作身份
    // Step 2(履歷新增)
    job_seeking_status?: string; // 求職狀態
    education_period?: string; // 就學狀態
    school_name?: string; // 學校名稱
    degree?: string; // 學位
    work_types?: string[]; // 工作性質(多選)
    available_date?: string; // 可上班日
    expected_salary?: string; // 希望待遇
  };
}

Slug 生成邏輯

let campaignCounter = 1;
function generateCampaignId(): string {
  return `campaign_${String(campaignCounter++).padStart(3, "0")}`;
}

新增活動時,系統自動呼叫 generateCampaignId() 產生新的 slug。

使用者流程

新增活動流程

  1. 點擊「新增活動」按鈕
  2. 表單開啟,系統自動生成 slug(顯示在「活動網址」欄位)
  3. 填寫必填欄位:
    • 活動標題
  4. (選填)設定預設篩選條件:
    • 職務類別
    • 工作性質
    • 地點
  5. 點擊「儲存」
  6. 表單驗證:
    • 如有錯誤,顯示錯誤訊息
    • 驗證通過後,活動新增至列表

編輯活動流程

  1. 點擊活動列表的「編輯」
  2. 表單開啟,預填現有資料
  3. 活動網址欄位顯示現有 slug(只讀)
  4. 修改欄位(slug 不可修改)
  5. 可切換至「預填設定」tab 編輯一鍵加入預填欄位
  6. 若基本設定尚未完成(活動標題未填或未選職缺),在「預填設定」tab 的「儲存」按鈕為 disabled,hover 顯示需先完成基本設定
  7. 點擊「儲存」
  8. 表單驗證通過後,更新活動資料

刪除活動流程

  1. 點擊活動列表的「刪除」
  2. 確認對話框:「確定要刪除「{活動名稱}」嗎?刪除後,求職者的活動來源篩選將無法使用此活動。」
  3. 確認後:
    • 活動從列表中移除
    • 活動 ID 加入 deletedCampaignIds
    • 人才庫的「活動來源」下拉選單移除該活動選項

從活動管理導向活動落地頁

  1. 在活動列表中點擊活動名稱
  2. 切換至「活動落地頁」檢視
  3. 顯示公司頁面,並自動套用活動設定的預設篩選條件
  4. 用戶可自行調整篩選條件

從活動管理導向人才庫

  1. 在活動列表中點擊「來訪」數字
  2. 切換至「人才庫」檢視
  3. 「活動來源」下拉自動選中該活動
  4. Tab 自動切換至「來訪」

技術實作備註

Storybook Mockup 位置

  • Mockup 組件storybook/src/mockupcomponents/
    • MockupCampaignListTable.vue
    • MockupCampaignEditorForm.vue
    • MockupCompanyPage.vue(共用組件)
    • MockupTalentPoolPage.vue
    • 一鍵加入人才庫流程(MockupCampusEventQuickApplySheet.vue)之 Step 1 註冊/登入:使用 MockMainSiteAuth(對應 main site auth register、main site login),與主站 Auth 畫面一致。
  • Mock 資料storybook/src/mockupcomponents/campaign/
    • mockCampaignData.ts
    • mockTalentPoolData.ts
  • Demo 頁面storybook/src/mockups/recruitment-campaign-demo.vue
  • Story 檔案storybook/src/stories/mockups/recruitment/RecruitmentCampaign.stories.ts

狀態管理

  • campaignList:活動列表狀態(ref<MockCampaignItem[]>
  • deletedCampaignIds:已刪除活動 ID 列表(ref<string[]>
  • talentPoolSource:人才庫預設活動來源(ref<string>
  • talentPoolTab:人才庫預設 Tab(ref<'applied' | 'visit'>
  • candidateCampaign:當前檢視的活動(ref<MockCampaignItem>

驗證邏輯

表單驗證在 MockupCampaignEditorForm.vuevalidateForm() 函數中實作:

const validateForm = (): boolean => {
  formErrors.value = { name: "" };
  let valid = true;

  if (!form.value.name.trim()) {
    formErrors.value.name = "活動標題為必填";
    valid = false;
  }

  return valid;
};

URL 生成邏輯

const getCampaignUrl = () => {
  const params = new URLSearchParams();
  params.set("campaign", form.value.slug);
  if (form.value.category) params.set("category", form.value.category);
  if (form.value.work_nature) params.set("nature", form.value.work_nature);
  if (form.value.location) params.set("location", form.value.location);
  return `https://example.com/companies/company_id?${params.toString()}`;
};

後續實作注意事項

  1. 後端 API 設計

    • 活動 CRUD API
    • Slug 自動生成邏輯(流水號格式)
    • 刪除活動時,需處理關聯的求職者資料(活動來源欄位)
    • 列表 API 分頁
      • 活動列表 API:支援分頁,每頁 10 筆(如 pagepage_size 參數,回應含 totalhas_next
      • 活動落地頁職缺列表 API:支援無限下拉(cursor-based 或 offset-based,每次載入一批,如 10–20 筆)
    • 點擊記錄 API:落地頁載入時由前端呼叫;後端接收 campaign_idtimestamp,並依 IP 與可選的 device_id/Cookie自然日 去重,未計過才將該活動 PV +1。
  2. 公司頁面整合

    • 公司頁面需支援從 URL query parameters 讀取活動 ID 和篩選條件
    • 根據 query parameters 自動設定篩選條件
    • 職務類別/工作性質/地點下拉需由後端回傳「有結果選項(count > 0)」或由前端依當前職缺集合計算,避免空集合
    • 設定 campaign_id 用於追蹤統計
    • 一鍵加入人才庫之多階段流程需支援狀態還原(§2、§7):重新整理或再次進入時還原階段與已填欄位,可採前端 localStorage/sessionStorage 或後端草稿 API。
  3. 人才庫整合

    • 實際人才庫頁面需新增「活動來源」篩選下拉
    • 從活動管理導向人才庫時,需透過 URL query 或 state 傳遞活動來源
  4. SEO 設定

    • 活動落地頁需設定 noindex meta tag(因為不需要 SEO)
  5. QR Code 生成

    • 後端需提供 QR Code 生成 API
    • QR Code 內容為活動落地頁完整 URL(包含 query parameters)
  6. 追蹤與 Log

    • 依「§6. 統計、追蹤與事件記錄(Log)」實作各事件記錄(落地頁載入、職缺曝光/點擊、註冊登入、來訪、加入人才庫送出)。
    • 與後端 log/分析用 API 或既有 analytics 對接,確保 campaign_id 與來訪/加入人才庫寫入時機與人才庫統計一致。
  7. 多語系與文案對齊

    • 本功能所有下拉選單選項、欄位標題、提示文案與錯誤訊息,需沿用既有主站多語系 key 與翻譯規則,不新增獨立文案體系。
    • 活動頁一鍵加入流程中的欄位文字與既有註冊/會員中心/履歷編輯頁保持一致語意與命名。

更新記錄

  • 2026-02-09:初版功能需求

    • URL slug 改為自動生成流水號(只讀,可複製)
    • 活動標題設為必填
    • 職缺選擇至少一個
    • 新增活動刪除功能
    • 刪除活動後,人才庫的活動來源選項會移除
  • 2026-02-09:重大設計變更

    • 移除 Banner 圖片和活動說明欄位
    • 活動落地頁改為使用公司頁面 + 預設篩選條件
    • 職缺選擇改為篩選條件設定(職務類別、工作性質、地點)
    • 活動名稱可點擊,導向活動落地頁
    • URL 結構改為 query parameters 格式
  • 2026-02-09:新增來源追蹤與顯示功能

    • 活動來源顏色區分(公司活動:藍色,業務頁面:綠色)
    • 業務資料隔離(業務只能看到自己的頁面來源)
    • 人才卡片顯示來源標籤(支援複數標籤)
    • 來源標籤可點擊篩選
    • 多來源統計規則(來訪多歸屬)
    • 下拉選單選項與標籤顏色一致
  • 2026-03-02:點擊數去重與追蹤 Log 規格

    • 點擊(PV)改為同 IP 或同裝置同一自然日僅計 1 次;§1.1 欄位說明與 §5 業務規則補齊
    • 新增 §6 統計、追蹤與事件記錄(Log):落地頁載入、篩選、職缺曝光/點擊、註冊登入、來訪、應徵等事件與建議欄位
    • 後續實作注意事項:點擊記錄 API 去重邏輯、追蹤與 Log 對接
  • 2026-03-02:一鍵加入人才庫多階段流程與狀態還原

    • §2 新增「一鍵加入人才庫與多階段流程」:多階段(註冊 → 下一步 → 第二階段填寫等)、重新整理/再次進入時記住目前階段與已填欄位
    • §7 一鍵加入/註冊流程狀態持久化:同一使用者辨識(裝置/Cookie/campaign_id)、儲存方式(前端 storage 或後端草稿)、效期與敏感資料處理
    • 後續實作注意事項:公司頁面整合補充一鍵加入流程狀態還原
  • 2026-03-02:註冊階段錯誤與邊界情境

    • 新增 §8 註冊階段錯誤與邊界情境:註冊/登入失敗、密碼與站上一致、時間與效期、網路與後端、限流與安全、狀態與流程邊界、驗證與業務規則,供 RD 實作與測試對齊
  • 2026-03-02:註冊、驗證與重整後登入行為

    • 新增 §7.5 註冊、驗證與重整後登入行為:帳號於點擊註冊時即建立、驗證碼僅用於確認 email 真實、第三方登入不需驗證;等驗證碼時重整後為「還沒登入」、引導登入且登入後仍須發送驗證碼;誤點註冊時顯示「此 email 已有人註冊,可轉登入」
  • 2026-03-02:一鍵加入 Step 1 改用 Main Site Auth

    • 第 1 階段註冊/登入改為使用 Main Site Auth 組件(main site auth register、main site login),與主站一致;Storybook Mockup 使用 MockMainSiteAuth
  • 2026-03-02:§7.6 一鍵加入入口與狀態約束(API/後端對齊用)

    • 新增精簡版:入口 register/login、狀態 verified/profileFilled/hasResume、約束(register 時兩者必 false;login 時 hasResume false ⇒ profileFilled false)、註冊時 email 已存在之錯誤回傳
  • 2026-03-02:活動落地頁一鍵加入流程圖

    • §2 新增 Mermaid 流程圖:註冊/登入 → 是否驗證(Email 驗證碼、Google 免驗證)→ 是否填寫個人資料(profileFilled)→ 是否有履歷(hasResume)→ 送出進入人才庫;含 email 已註冊之錯誤分支
  • 2026-03-02:驗證碼失敗與重發規則

    • §8.1 驗證碼錯誤或過期列補充「失敗後等待可重發、重試直到成功」並指向 §8.1.1
    • 新增 §8.1.1 驗證碼(OTP)失敗與重發:失敗情境(錯誤、過期、格式)、重發規則(等待時間與倒數、直到成功為止)、與 §8.5 限流並存
  • 2026-03-03:流程優化—驗證碼共用與繼續填寫進入點

    • 流程圖改為「共用驗證碼子流程」:註冊與登入之 Email 驗證路徑匯入同一 OTP 子流程,成功後匯出至 verified;§2 新增「驗證碼流程共用」說明(共用 OTP 組件與邏輯,API 實作時決定)
    • 新增 §7.1 繼續填寫之進入點:僅支援再次從同一活動連結進入、依同一裝置辨識還原;換裝置或清除儲存需從頭填寫
    • 新增 §8.6.1 活動下架時的畫面與流程中斷:進入活動 URL 時不顯示公司與職缺、顯示找不到/已下架;填寫中點擊下一步時若活動已下架則跳轉至「活動已下架」提示
  • 2026-03-03:PRD 問題清單修正(名詞、欄位、上限、狀態約束)

    • 「一鍵投遞人才庫」全文更名為「一鍵加入人才庫」;行為明確為「將履歷設為公開 + 記錄來訪」,非針對特定職缺投遞,來源(source)記為該活動
    • 刪除 MockCampaignItemapplications_count 欄位;§1.1 活動列表移除「應徵」欄位(活動不產生應徵數)
    • §3 人才庫:刪除應徵統計邏輯(僅保留來訪統計:多歸屬);人才庫既有的應徵 Tab 保留不變
    • §6 統計事件「應徵送出」改為「加入人才庫送出」,描述為非針對特定職缺的履歷送出
    • 從活動管理導向人才庫:僅支援點擊「來訪」導向,移除「應徵」導向
    • 新增 §4.1 活動數量上限:同時開啟最多 10 個(status=1)、活動總數(含下架)最多 100 個
    • §7.6 新增「已有履歷的用戶再次加入」:跳至 Step 3 選擇履歷,source=活動,人才庫以最新履歷為主(覆蓋更新)
  • 2026-03-03:API 互動摘要與落地頁職缺列表改為無限下拉

    • 新增 §9 一鍵加入人才庫 API 互動摘要(後端對齊用):每步驟對應 API 總覽(新/沿用)、狀態判斷來自三隻不同 API、PV vs 來訪 vs 加入人才庫送出定義、「加入人才庫」實際行為拆解(沿用 update resume API 設公開)、註冊/登入 API 與主站差異(驗證碼 OTP vs 驗證連結,需獨立 API)
    • §2 修正 Main Site Auth 描述:UI 畫面沿用主站組件,但後端 API 為活動專用(寄 OTP 驗證碼而非驗證連結)
    • §6 統計事件表新增「登入狀態」欄位:PV = 匿名不需登入、來訪 = 需已登入、加入人才庫送出 = 需已登入;補充 HR 視角說明
    • §7.6 新增「加入人才庫的實際 API 行為」:同意公開履歷為法律告知 UI、送出 = 沿用 update resume API 設公開、再次加入 = 同樣 update + 以最新履歷為主
    • §2 活動落地頁職缺列表改為無限下拉(Infinite Scroll),不使用分頁控制
    • 後續實作注意事項:落地頁職缺列表 API 改為支援無限下拉(cursor-based 或 offset-based)
  • 2026-03-03:新增活動表單 UI 重構

    • MockupCampaignEditorForm.vue 改為單一 PrimeVue Dialog:活動標題、活動網址、選擇職缺(含篩選與 DataTable)合併為同一視窗,移除原本的雙層 Modal 設計
    • 移除 Naive UI 依賴(NButton、NForm、NInput、NPagination、NTooltip),改用 PrimeVue(Dialog、InputText、Button、DataTable、Column、Select、Checkbox、Message、InputGroup)
    • 職缺列表改用 PrimeVue DataTable + Checkbox 勾選,支援分頁、篩選(關鍵字搜尋 + 職務類別 / 工作性質 / 地點下拉)
    • 活動網址顯示為 readonly InputText + 複製按鈕
  • 2026-03-24:PM_29 更新(邀請 QR Code V2 預填)

    • Step 1 新增可預填欄位:residency_city(居住地)、identity_type(在台外籍工作身份)
    • Step 2(履歷新增)新增可預填欄位:job_seeking_statuseducation_periodschool_namedegreework_typesavailable_dateexpected_salary
    • Mock schema 補充 quick_apply_prefill 結構,定義活動層級預填設定來源
  • 2026-03-24:PM_29 更新(篩選下拉避免空集合)

    • 活動管理與活動落地頁的職務類別/工作性質/地點下拉改為僅顯示 count > 0 選項(依目前擁有職缺動態計算)
    • 新增 §3.1 篩選下拉選項規則,明確禁止顯示空集合選項
  • 2026-03-30:PM_29 PRD 補充(預填與互動一致性)

    • Step 1 的 residency_cityidentity_type 明確對齊會員中心「編輯會員資料」流程;居住地採縣市/區域聯動並支援搜尋
    • 前台註冊頁「居住地」改以單一欄位元件處理,不拆為兩個獨立下拉
    • Step 3 expected_salary 互動規則對齊既有職缺編輯:選自訂薪資時顯示單位與數字輸入
    • 下拉選單移除「不預填」選項,已選值可透過清除按鈕(如 x)回到空值後再重選
    • 快速建立履歷改為原則式定義,不在 PRD 預設完整實作欄位範圍,保留 BE 實作彈性
    • 補充本功能所有欄位與下拉選項需沿用既有多語系規則