◆ wport | pm_35

履歷 AI 複製 Mockup PRD(給後端 API 規格產生器使用)

履歷 AI 複製

來源 doc/feature/pm_35/resume-ai-copy-mockup.md

履歷 AI 複製 Mockup PRD(給後端 API 規格產生器使用)

此文件描述「履歷 AI 複製」在既有 my-resume / edit-resume 頁面的增量需求,供前後端、產品、QA 對齊。


1. 文件資訊

  • 文件類型:Mockup 需求規格書(前後端共用視圖)
  • 適用對象:前端開發、後端開發、產品、QA
  • 最後更新:2026/04/15
  • 版本:1.0.0
  • 對應 StorybookTBD(尚未建立對應 story)
  • Storybook 連結TBD
  • 建立日期:2026/04/15

2. 開發進度與設計來源

開發進度

  • 前端 PR #:TBD
  • 後端 PR #:TBD

設計來源

  • Figma 連結:待補上
  • 既有畫面來源(增量基準)
    • W101-Web/main-web/packages/user/src/views/my-resume/Index.vue
    • W101-Web/main-web/packages/user/src/views/my-resume/edit-resume/index.vue
    • W101-Web/main-web/packages/user/src/router/index.ts

3. 模擬頁面摘要(Mockup Summary)

3.1 功能概述

  • 功能名稱:履歷 AI 複製
  • 主要使用者角色:求職者(在台僑外生 / 外籍求職者)
  • 核心目標
    • 降低求職者從既有履歷搬移到 Wport 的成本,將「貼上文字 / 上傳 PDF(轉 md)/ prompt」轉為可編輯履歷草稿,並一鍵保存。

3.2 範圍界定

  • 包含範圍
    • 採用三層處理架構:Parsing -> Processing -> UI/UX Filling。
    • my-resume 新增「AI 複製建立履歷」入口(沿用新增履歷上限與資格限制)。
    • 支援輸入來源:
      • plain text 直接貼上。
      • PDF 上傳後先轉 md,再由 AI 轉結構化 JSON(非 OCR 深度辨識)。
      • prompt 輸入。
    • AI 解析後提供欄位映射預覽,使用者可編輯後再保存到既有履歷模型。
    • 解析失敗時保留原文,允許在 1 小時內重試。
    • 生成流程不覆蓋既有履歷資料,僅建立新草稿/新履歷。
  • 排除範圍
    • 不做 OCR 深度辨識與掃描品質修復。
    • 不做專業翻譯/潤稿服務。
    • 不做與第三方履歷平台雙向同步。

3.3 成功條件

  • 使用者可在單次流程內完成:輸入內容 -> AI 生成草稿 -> 編輯 -> 保存。
  • 解析後欄位可成功儲存並顯示於既有履歷頁。
  • 失敗時顯示明確提示且保留原文,不覆蓋既有履歷。
  • 上線後可追蹤「AI 生成履歷使用率」。

4. 商業規則對齊(Business Rules Alignment)

4.1 本功能使用到的業務規則

規則 ID規則摘要是否關鍵備註
BR-002信箱驗證後仍需完成個人資料才能新增履歷✅ 是AI 複製建立履歷仍屬新增履歷入口
BR-010履歷建立條件與數量上限✅ 是本功能沿用每人最多 6 份履歷上限
BR-017使用者只能編輯自己的履歷✅ 是AI 生成結果僅能保存到本人履歷

4.2 補充說明

  • 「PDF -> md -> JSON」屬於 AI 解析流程,與「OCR 深度辨識」不同,並不違反本功能 out-of-scope。
  • 若使用者已達 6 份履歷上限,AI 複製入口顯示禁用與提示文案,不可建立新履歷。

5. 資料實體與欄位(Data Entities & Fields)

5.1 實體列表

實體名稱說明來源頁面/區塊
ResumeAiDraftInput使用者提供給 AI 的原始內容與來源資訊my-resume / AI 複製 modal
ResumeAiParseJob一次 AI 解析任務與狀態my-resume / 解析流程狀態
ResumeAiParsedResumeAI 輸出的履歷結構化結果edit-resume / 預填草稿
ResumeCreateResult建立履歷後回傳結果my-resume / 列表更新

5.2 實體欄位定義(TypeScript 介面)

ResumeAiDraftInput

interface ResumeAiDraftInput {
  source_type: 'plain_text' | 'pdf_to_md' | 'prompt';
  raw_content: string;
  raw_file_url?: string;
  locale?: 'zh-TW' | 'en';
}

ResumeAiParseJob

interface ResumeAiParseJob {
  parse_job_id: string;
  user_id: string;
  status: 'draft' | 'parsing' | 'parsed' | 'user_edited' | 'saved' | 'failed' | 'expired';
  started_at: string;
  completed_at?: string;
  retry_window_ends_at: string; // started_at + 1 hour
  error_code?: string;
  error_message?: string;
}

ResumeAiParsedResume

interface ResumeAiParsedResume {
  parse_job_id: string;
  resume_name: string;
  personal_background?: Record<string, unknown>;
  education?: Array<Record<string, unknown>>;
  work_experience?: Array<Record<string, unknown>>;
  professional_skill?: Array<Record<string, unknown>>;
  languages?: Array<Record<string, unknown>>;
  certificates?: Array<Record<string, unknown>>;
  portfolio_links?: Array<Record<string, unknown>>;
  autobiography?: string;
  confidence_score?: number;
  warnings?: string[];
}

6. 畫面區塊與資料需求(UI Sections & Data Needs)

6.1 區塊列表

區塊 ID區塊名稱說明
SEC-1my-resume AI 複製入口新增按鈕與上限/資格提示
SEC-2AI 輸入區text / pdf / prompt 輸入
SEC-3解析中與結果預覽區顯示狀態、錯誤、重試、映射結果
SEC-4edit-resume 編輯區(沿用)解析完成後進入既有編輯頁補修

6.2 各區塊資料需求

SEC-1 my-resume AI 複製入口

  • 顯示實體resumeList, extra.max_resumes_quota, user profile complete state
  • 資料需求:沿用既有履歷列表 API。
  • 約束
    • 已達 6 份履歷:禁用入口並顯示提示。
    • 未完成個人資料或信箱驗證:禁用入口並引導至 edit-member

SEC-2 AI 輸入區

  • 顯示實體ResumeAiDraftInput
  • 資料需求:輸入內容長度檢查、PDF 轉 md 前置處理。
  • 是否即時打 API:否(按下「開始解析」才送出)。

SEC-3 解析中與結果預覽區

  • 顯示實體ResumeAiParseJob, ResumeAiParsedResume
  • 資料需求:輪詢或 webhook 更新 status
  • 錯誤處理
    • failed:顯示錯誤訊息,保留輸入內容。
    • 1 小時內可重試,超過 1 小時狀態改 expired,需重新建立 parse job。

SEC-4 edit-resume 編輯區(沿用)

  • 顯示實體:既有履歷 sections + AI 帶入欄位
  • 資料需求:將 parsed payload 映射到既有 ResumeSections 模型,使用者可修改後保存。

7. 使用者動作與後端需求(User Actions & Backend Needs)

動作 ID動作名稱類型需要後端涉及實體說明
ACT-1開啟 AI 複製入口UI❌ 否-僅前端顯示與資格檢查
ACT-2提交輸入給 AI 解析寫入(Write)✅ 是ResumeAiDraftInput, ResumeAiParseJob建立 parse job
ACT-3查詢解析狀態查詢(Read)✅ 是ResumeAiParseJob解析中輪詢
ACT-4取得解析結果查詢(Read)✅ 是ResumeAiParsedResume取回可編輯草稿
ACT-51 小時內重試解析寫入(Write)✅ 是ResumeAiParseJob沿用原輸入重跑
ACT-6保存為新履歷寫入(Write)✅ 是ResumeCreateResult建立新履歷,不覆蓋既有

7.1 場景細節(複數場景逐一描述)

  1. 已登入 + 條件完整 + 未達上限
    • 可使用 AI 複製,完成後建立新履歷並跳轉 edit-resume/:resumeId
  2. 已登入 + 未完成個人資料/未驗證信箱
    • AI 複製入口禁用,提示先完成會員資料,導向 edit-member
  3. 已登入 + 已達 6 份上限
    • 禁用 AI 複製與新增履歷,提示刪除後再建立。
  4. 未登入
    • 無法進入 my-resume / edit-resume(沿用 login guard)。
  5. 解析失敗(服務錯誤/格式不符)
    • 顯示失敗原因、保留原文、提供重試;重試窗口 1 小時。
  6. 解析結果部分欄位缺漏
    • 可進入 edit-resume 由使用者補齊,未補齊欄位遵循既有必填限制。

7.2 入口與狀態約束

入口狀態欄位約束預期行為
/my-resumeprofile_complete必為 true才可啟用 AI 複製按鈕
/my-resumeresume_count必 < 6否則禁用並提示上限
AI parse jobstatus=failedwithin 1 hour可重試並保留原文
AI parse jobstatus=failedover 1 hour狀態轉 expired,需重建任務
/edit-resume/:resumeIdparsed payload可為部分缺漏允許人工補齊後保存

8. API Hints(提示用,非最終 API 設計)

8.1 資料讀取需求(Read)

  • HINT-GET-1:取得 AI parse job 狀態

    • 對應區塊:SEC-3
    • 輸入:{ parse_job_id }
  • HINT-GET-2:取得 parse 結果 payload

    • 對應區塊:SEC-3 / SEC-4
    • 輸入:{ parse_job_id }

8.2 資料寫入需求(Write)

  • HINT-MUTATION-1:建立 AI parse job

    • 輸入:{ source_type, raw_content | raw_file_url, locale }
    • 行為:建立解析任務並回傳 parse_job_id;若 source_type=pdf_to_md,先執行 PDF->MD 再進入 LLM。
  • HINT-MUTATION-2:重試 parse job

    • 輸入:{ parse_job_id }
    • 行為:僅在 1 小時窗口內可重試
  • HINT-MUTATION-3:以解析結果建立新履歷

    • 輸入:{ parse_job_id, mapped_resume_payload }
    • 行為:建立新履歷並回傳 encResumeId

9. 導航 / Storybook Map

  • Storybook 標題Mockups/Resume/ResumeAiCopy
  • Stories 路徑storybook/src/stories/mockups/resume/ResumeAiCopy.stories.ts(待建立)
  • Storybook 連結TBD
  • 對應 production 路由
    • /my-resume
    • /edit-resume/:resumeId

10. Flowcharts(User / System / Navigation)

10.1 User Flow(使用者操作流程)

flowchart TD
    A[進入 my-resume] --> B{已完成會員資料且履歷數<6?}
    B -->|否| C[顯示限制提示並引導]
    B -->|是| D[開啟 AI 複製輸入]
    D --> E[貼文字 / 上傳PDF轉md / 輸入prompt]
    E --> F[送出 AI 解析]
    F --> G{解析成功?}
    G -->|否| H[顯示錯誤 + 保留原文]
    H --> I{1小時內?}
    I -->|是| F
    I -->|否| J[任務過期 需重建]
    G -->|是| K[顯示可編輯草稿]
    K --> L[進入 edit-resume 補修]
    L --> M[保存為新履歷]

10.2 System Flow(前端狀態與資料流)

sequenceDiagram
    participant U as User
    participant FE as Frontend
    participant BE as Backend API
    participant AI as LLM Provider

    U->>FE: 開啟 AI 複製並送出輸入
    FE->>BE: 建立 parse job
    BE->>AI: 解析履歷內容
    AI-->>BE: 回傳結構化結果(JSON)
    BE-->>FE: job status = parsed / failed
    alt parsed
      FE->>BE: 取得 parsed payload
      BE-->>FE: 履歷草稿資料
      U->>FE: 編輯後按保存
      FE->>BE: 建立新履歷
      BE-->>FE: encResumeId
    else failed
      FE-->>U: 顯示錯誤並保留原文
      U->>FE: 1 小時內重試
      FE->>BE: retry parse job
    end

10.3 Navigation / Story Flow

flowchart LR
    N1[/my-resume/] --> N2[AI 複製輸入與解析]
    N2 --> N3[/edit-resume/:resumeId/]
    N3 --> N4[保存後返回 my-resume 列表]

11. Mock Data Schema(Mock 資料結構)

  • 資料來源:以 mock provider 回傳 parse job 與 parsed payload,不呼叫真實模型。
  • CRUD 行為
    • parse job 狀態在 Storybook 以 controls 切換:parsing / parsed / failed / expired
    • 建立與編輯行為僅存在元件狀態,重新整理後還原。
  • 情境切換
    • scenario=success:可順利帶入 edit-resume。
    • scenario=partial:部分欄位缺漏。
    • scenario=failed_retryable:失敗但在 1 小時內。
    • scenario=failed_expired:失敗超過 1 小時。

12. 實作備註(Implementation Notes)

  • 三層技術建議(新增)

    1. 解析層(Parsing)
      • Input:使用者上傳 PDF 或貼上純文字。
      • Action:
        • 若為 PDF,建議優先使用開源工具將內容轉為 Markdown(推薦 MarkerPyMuPDF),保留段落/標題結構。
        • 若為 plain text,直接進入下一層。
      • 目的:降低 PDF 原始噪訊、保留語意結構,並降低後續 LLM token 消耗。
    2. 轉換層(Processing)
      • Input:Markdown 內容 + Wport 官方標準 JSON Schema(履歷欄位規範)。
      • Action:呼叫 LLM,要求「嚴格依 Schema 輸出 JSON」;若欄位缺漏則輸出 null 或空陣列,不可輸出 Schema 外欄位。
      • 目的:將非結構化語意轉為可落庫資料,提升格式一致性與可驗證性。
    3. 呈現層(UI/UX Filling)
      • Input:Processing 產出的 JSON。
      • Action:前端根據欄位映射規則自動 pre-fill 對應 input 元件,使用者僅需補齊缺漏後儲存。
      • 目的:提供「快速填入」體驗,縮短建立履歷時間。
  • 模型供應商策略(成本/品質)

    • 預設建議使用 Gemini 2.5 Flash 做第一層履歷結構化(通常 token 成本與延遲較低)。
    • 若解析信心分數低或欄位缺漏高,再 fallback 到 Claude Sonnet 做第二層修復。
    • OpenAI 可作為第三層備援或 A/B 評測。
    • 所有供應商需統一輸出 schema,避免前端映射分岔。
  • Schema 驗證要求(新增)

    • LLM 回傳 JSON 後,後端需做一次 schema validator 驗證;不通過則標記 failed 並回傳可重試原因。
    • 目標是「格式 100% 可驗證正確」,不是「內容 100% 無需人工修正」;仍保留使用者最終編輯權。
  • 非功能需求

    • 單次解析請求應記錄 provider, token_usage, latency_ms, status
    • 必須可追蹤「AI 生成履歷使用率」與解析成功率。
  • 禁止事項

    • 不可直接覆蓋使用者既有履歷資料。
    • 不可繞過 BR-002 / BR-010 的入口限制。

13. 下一步(Next Steps)

  • 與後端確認 parse job 的最終資料表與 API 契約。
  • 補齊 Storybook mockup 與故事連結,回填本 PRD 第 1、9 節。
  • 定義 AI 生成履歷使用率的儀表板口徑(分母/分子)。
  • 規劃 QA 測試矩陣(來源型別、上限、失敗重試、過期場景)。

文件結束