pm_44 封鎖公司:功能審查整合報告
審查對象:
block-company-prd.mdv1.0.1 + StorybookMockups/求職者/封鎖公司(storybook.wport.me 線上實測) 審查方法:功能面流程分析(不以 PRD 為標準)+ PRD×mockup 逐行靜態比對 + 瀏覽器實際操作 + 系統交互時序盤點 + 同業參照(104 / 1111 / Indeed / LinkedIn / Glassdoor / Cake) 審查日期:2026/07/14
0. TL;DR
| 類別 | 數量 | 最嚴重的一條 |
|---|---|---|
| P0 結構性矛盾 | 4 | v1 範圍矛盾:pm_44 說「封鎖隱藏再投入口」是 v1 成功條件,pm_42 把同一件事排到 v2 |
| P1 單邊缺漏 | 11 | BR-029 封鎖原因 UI 完全缺席;SEC-4 遮罩未實作 |
| P2 文案與細節 | 3 | 「已達上限」文案寫死,0/50 也顯示 |
| PRD 功能面遺漏 | 6 | 解除封鎖無確認/undo(高影響動作) |
| 系統交互情境未定義 | 12 | 已有訊息往來後才封鎖 → 能否再發、歷史可見性全未定義 |
| 同業參照 | 6 平台 + 3 條必帶教訓 | 集團子公司繞過(104 最大客訴源)、封鎖名單外洩(1111 真實事故) |
1. P0:結構性矛盾
1-1. 入口與寫入語意分歧:mockup 實作了 SEC-1 子集+一套 PRD 未規格化的搜尋新增流程
共通部分:mockup 的封鎖清單頁就是 PRD 的 SEC-1(含解除封鎖、空狀態 SEC-5、上限 BR-028)。 分歧部分:PRD 的進入路徑是「瀏覽中封鎖」——公司頁 / 職缺卡 overflow(SEC-2)→ 確認 Modal(雙向隱藏說明、收藏移除提示、選填原因,SEC-3)→ 確認才寫入;mockup 則發明了 PRD 沒有的「主動搜尋封鎖」——搜尋公司 → 逐筆或「封鎖全部」→ 點了立即寫入,無確認步驟,且 SEC-2/3/4 全數未做。入口集合和寫入語意(確認制 vs 即點即寫)雙雙對不上。
flowchart LR
subgraph PRD 的世界
A1[公司頁 / 職缺卡 overflow] --> B1[點封鎖]
B1 --> C1[確認 Modal<br/>雙向隱藏說明+選填原因]
C1 -->|確認| D1[寫入]
C1 -->|離開| E1[不寫入]
end
subgraph Mockup 的世界
A2[帳號設定 > 封鎖公司] --> B2[新增封鎖 Modal<br/>搜尋公司]
B2 --> C2[逐筆點新增封鎖<br/>或 封鎖全部]
C2 --> D2[立即寫入 無確認]
D2 -->|按取消關窗| E2[已寫入的不回滾]
end
為什麼重要(實例):小美想封鎖現任雇主,但她絕不想瀏覽現雇主的公司頁(怕留下「誰來看我」足跡)。PRD 的入口逼她去公司頁;mockup 的搜尋入口才符合她的需求。反過來,阿明滑職缺時看到前東家想順手封鎖——mockup 沒有這個入口。兩種入口其實互補,建議 PRD 裁決兩者都收,而非改掉任一邊。
- 出處:PRD §6.2(SEC-2/SEC-3)、PRD:184
BlockTogglevsMockupBlockCompany.vue:159-167 - 修正對象:PRD(裁決 IA)+ mockup(補確認語意)
1-2. 「封鎖全部」可突破 50 上限(違反 BR-028)
openModal() 在達上限時擋住開窗,但 blockOne() / blockAll() 內部不再檢查上限。
實例:已封鎖 49 家 → 開新增 Modal(49 < 50 可開)→ 按「封鎖全部(5)」→ 變 54 家。
- 出處:
MockupBlockCompany.vue:50-51(只擋開窗)、:66-69(blockAll 無檢查) - 修正對象:mockup(PRD 若收「封鎖全部」也要補批次遇上限的截斷規則:封到 50 停?整批拒絕?)
1-3. 重複封鎖產生重複項(瀏覽器實測確認)
華勝已在封鎖清單,Modal 內仍顯示「新增封鎖」,點擊後清單出現兩筆華勝(實測畫面 6/50 含重複)。搜尋候選的 isBlocked 旗標沒有和清單同步,違反 PRD edge case「(user,company) 唯一、idempotent」(PRD:234)。
- 出處:
block-company.ts:37-43(候選資料寫死isBlocked:false) - 修正對象:mockup
1-4. v1 交付範圍矛盾:「封鎖隱藏再投入口」到底 v1 還 v2
pm_44 把它寫成 v1 成功條件:「該公司『再次應徵』入口在封鎖下隱藏」(PRD:55)。
pm_42 把同一件事明確排到 v2:「pm_44 封鎖公司互動(再投隱藏 / is_blocked_by_me)→ v2(pm_44 上線後)」(pm_42:52)。
兩卡對 v1 範圍的認知直接衝突——如果照 pm_42 的排程,pm_44 v1 上線後會有一段窗口期:使用者封鎖了 C 公司,但應徵紀錄頁的「再次應徵」按鈕照常可點。要嘛 pm_42 提前接 is_blocked_by_me,要嘛 pm_44 的成功條件降級並定義窗口期的過渡行為。
- 修正對象:兩卡 PRD 對齊(v1 範圍裁決)
2. P1:單邊缺漏
PRD 有、mockup 沒做
| # | 項目 | PRD 出處 | 說明 |
|---|---|---|---|
| 1 | BR-029 封鎖原因選填 UI | PRD:81, 105, 140 | mock 型別連 reason_code 欄位都沒有 |
| 2 | SEC-4 已封鎖遮罩 | PRD:143-145 | 「你已封鎖此公司」畫面完全未實作 |
| 3 | SEC-2 BlockToggle 元件 + isolation story | PRD:184 | 不存在 |
| 4 | scenario 缺 2 個 | PRD:183 | 無 confirm-modal、blocked-overlay;saved-conflict 只是 mock 第一筆剛好 isSaved:true 的副作用,資料一改就消失 |
| 5 | SEC-1 分頁 | PRD:132 | mockup 無分頁 |
| 6 | 事件字典三事件 | PRD:280-284 | 無任何實作痕跡 |
mockup 有、PRD 沒寫
| # | 項目 | mockup 出處 | 說明 |
|---|---|---|---|
| 7 | 搜尋新增 Modal + 「封鎖全部」批次 | .vue:136-178 | 無對應 ACT / API Hint |
| 8 | 「封鎖清單掛在帳號設定頁」的 IA | block-company.ts:46-51 | PRD 未提掛載位置 |
行為不一致(皆瀏覽器實測)
| # | 項目 | PRD 說 | mockup 實際 |
|---|---|---|---|
| 9 | Modal 中離開 | 不建立封鎖(PRD:236) | 已點的封鎖不回滾,按取消照樣留著 |
| 10 | 達上限 | 「禁用並提示」(PRD:141) | 按鈕變灰,點擊完全靜默 |
| 11 | 資料結構 | 巢狀 company 物件、ISO8601 | 攤平結構、YYYY/MM/DD |
3. P2:文案與細節
- 「X / 50 家(已達上限將無法再新增)」是寫死的常駐文案——0/50、5/50 都掛著這句,讀起來像已達上限(實測 0、4、5、6、50 全部同句)。
.vue:114 - 搜尋框是假的:
keyword有 v-model 但無過濾邏輯,輸入任何字清單不變,QA/PM 易誤判搜尋已模擬。.vue:44, 144-147 - **「封鎖行為是完全匿名的,對方不會收到通知」**是 mockup 自寫 claim。「不收到通知」做得到;「完全匿名」要逐一驗證企業端所有計數器(人才搜尋數、誰來看我數、CRM 統計)不因封鎖出現可推斷變化,否則是過度承諾(見 §6-2 的 104 教訓)。
4. PRD 功能面遺漏(不以 PRD 為標準的檢查)
- 解除封鎖無確認、無 undo——解除等於「讓前東家重新看到你」,是高影響動作,PRD 只寫「即時恢復曝光」。實測 mockup 也是一點即解、無任何確認。
- 封鎖成功/失敗的回饋機制(toast / inline)未定義。
- 50 家清單無搜尋/篩選規格(滿額時找一家很痛苦)。
- 被封鎖公司倒閉/改名/下架後,清單裡那筆怎麼顯示。
- System Flow 的「GET 狀態(含已封鎖數)」在 API Hints 無對應欄位。
- loading 態全篇未提(只有 timeout 15s 常數)。
5. 系統交互時序情境(19 條未定義,本節為核心增補)
5-1. 最高優先:先互動、後封鎖
sequenceDiagram
participant U as 求職者 U
participant SYS as 平台
participant C as 公司 C(HR)
Note over U,C: ── 封鎖前,關聯已存在 ──
U->>C: 已投遞應徵(pm_42)
C->>U: 已發面試邀約(pm_32)
C->>C: 已把 U 加入人才 CRM pipeline(pm_45)
C->>C: 已收藏 U(人才庫)
C->>U: 已有訊息往來(既有訊息功能)
SYS-->>U: 已排程 19:00 彙整通知(含 C 的動態)
Note over U,C: ── U 此刻封鎖 C ──
U->>SYS: 封鎖公司 C
Note over SYS: ❓ 以下全部 PRD 未定義:
Note over SYS: 應徵紀錄 → 已定義:保留、藏再投(PRD:55)✅<br/>但未告知 U「C 仍看得到已投履歷」
Note over SYS: 面試邀約 → 通知還送嗎?邀約卡片顯示什麼?
Note over SYS: CRM pipeline → 隱藏還是刪除?
Note over SYS: C 對 U 的收藏 → BR-024 只寫 U→C 方向
Note over SYS: 訊息 → C 還能發嗎?歷史對話可見性?
Note over SYS: 已排程通知 → 送達前要重新過濾嗎?
| 情境 | 現況 | 出處 | 業界做法 | 建議 |
|---|---|---|---|---|
| 已應徵 → 才封鎖 | ✅ 唯一有定義:歷史保留、隱藏再投 | PRD:55, 240 | 104 / Indeed 皆「不溯及既往」,Indeed 官方明文:封鎖後雇主仍可看你已投的應徵 | 補告知文案:「已投遞的應徵,該公司仍可查看」,防使用者誤以為封鎖=對方看不到 |
| 面試邀約已發出 → 才封鎖 | ❌ 未定義;pm_32:111 把邀約通知當事件、pm_42:50-51 把邀約狀態 UI 延到 v2——兩卡 scope 未對齊(非邏輯矛盾),邀約實際上線狀態需向 owner 確認 | pm_32 / pm_42 | 無直接對標 | 先確認邀約上線狀態,再裁決:通知送不送、求職者端邀約卡顯示什麼 |
| HR 已加 U 入 CRM pipeline → 被封鎖 | ❌ BR-027#3 說不出現在 CRM,但 pipeline 記錄隱藏 vs 刪除未講。pm_45 尚未實作——趁實作前把封鎖行為寫進 pm_45 規格,成本最低 | pm_45:155-171 vs PRD:77 | LinkedIn block 回溯清除推薦信且不可恢復(有事前警告) | 建議隱藏不刪除(解封恢復),直接回寫 pm_45 PRD 而非事後補 |
| 企業已收藏 U → 被封鎖 | ❌ BR-024 只寫求職者→公司方向。pm_45 尚未實作,同上趁規格期定義 | pm_45:173-180 | — | 裁決 BR-024 是否對稱適用,回寫 pm_45 PRD |
| 已排程未送達通知 | ❌ | pm_32:225-230 | — | 送達前重新過濾封鎖名單,否則封鎖後還收到 C 的通知 |
| 已有訊息往來 → 才封鎖 | ❌ 訊息是既有系統功能(pm_32 以既存事件引用 talent_new_message / employer_talent_reply;上線狀態經 delivery owner 2026/07/14 確認),pm_44 對它隻字未提 | pm_32:278-284 | LinkedIn:封鎖即斷訊息、雙方互看不到 | v1 必須裁決:封鎖後 C 能否再發訊息?歷史對話雙方還看得到嗎?未讀訊息通知要過濾嗎? |
| 企業直連 URL 開 U 的候選人詳情頁 | ❌ BR-027#3 只涵蓋清單/時間軸,缺對稱於 SEC-4 的企業端遮罩 | pm_45:222-226 | — | 補企業端直連行為(遮罩或 404 擇一,並與求職者端語意一致) |
| 帳號刪除時 CompanyBlock 去留 | ❌ BR-012 資料處理表沒列 | business-rules.md:346-369 | — | 補資料處理表 |
5-2. 解除封鎖的恢復範圍(隱藏地雷)
BR-024 用詞是「移除」收藏(非「隱藏」)→ 隱含不可逆。
實例:小美收藏了 C 公司 3 個職缺 → 手滑封鎖 C → 收藏被連動移除 → 立刻解除封鎖 → 3 個收藏回不來,而她完全沒被警告過這件事。
flowchart TD
A[封鎖 C] -->|BR-024 連動| B[移除公司收藏 + 旗下職缺收藏]
A --> C[雙向隱藏生效]
D[解除封鎖 C] --> E[曝光恢復 ✅ PRD:53 有定義]
D --> F{收藏恢復?}
F -->|PRD 未定義| G[❓ 移除=永久消失?<br/>❓ 還是隱藏可恢復?]
style F fill:#f96,stroke:#333,color:#111
style G fill:#f96,stroke:#333,color:#111
二選一並寫明:(a) 不可逆 → 確認 Modal 文案加「移除後解除封鎖也不會恢復」(LinkedIn 對推薦信就是這樣警告的);(b) 改為隱藏、解封恢復。另可參考 LinkedIn 的 48 小時冷卻期,防封鎖/解封循環。
5-3. 匹配單位與繞過路徑(業界最大漏洞區)
封鎖綁 enc_id,以下全部繞得過:
flowchart LR
U[求職者 U 封鎖 enc_id_A] -.擋住.-> A[公司 C 帳號 A]
B[同法人帳號 B<br/>BR-022 允許最多10家] -->|照樣看到 U| U2[U 的履歷]
C2[C 砍帳號重註冊 enc_id_X] -->|照樣看到 U| U2
H[獵頭代招 C 的職缺<br/>pm_46 深連結] -->|繞過 BR-027 過濾?| U2
style B fill:#f96,color:#111
style C2 fill:#f96,color:#111
style H fill:#f96,color:#111
- 同法人多帳號:BR-022 允許一個負責人開最多 10 家企業帳號(business-rules.md:191-201),封 1 個擋不住其他 9 個。104 的同款問題是最大客訴源(封母公司、子公司照看),104 的解法是「統編+關鍵字」雙軌匹配。
- 改名/重註冊:PRD:97-102 未界定封鎖鍵綁 enc_id 還是公司實體。
- 獵頭深連結:pm_46:63-66 的轉介連結是否套 BR-027 過濾未定義。查詢層過濾漏一個入口,隱私承諾就整個破產——LinkedIn Open to Work 只擋付費 Recruiter 席位、一般員工帳號照樣搜得到,官方只能自承「不保證隱私」,是現成的反面教材。
6. 同業參照重點
6-1. 規格對照
| 平台 | 功能 | 上限 | 既有互動處理 | 特色/教訓 |
|---|---|---|---|---|
| 104 | 統編/關鍵字封鎖公司 | 各 10 組 | 不溯及既往;主動應徵已封鎖公司會跳二次確認 | 關鍵字可涵蓋集團;「誰來看我」足跡一併遮蔽 |
| 1111 | 封鎖公司 | 8 間 | 未載明 | 2018 封鎖名單遭員工外洩 2 萬筆——封鎖清單本身是高敏感個資 |
| Indeed | Block employers | 100 間 | 官方明文:已投應徵雇主仍可見 | App 不支援只有 Web 有——平台不一致的反例 |
| 無封鎖公司功能 | — | — | Open to Work 排除只擋付費席位=假隱藏;解封 48h 冷卻期 | |
| Glassdoor | 無此功能 | — | — | — |
| Cake / Yourator | 只查到整體可見度分級,無特定公司黑名單(未能完整確認) | — | — | — |
6-2. 三條必須帶走的教訓
- 主動應徵已封鎖公司要二次確認(104 有做):BR-027 靠預防性隱藏讓你點不到,但獵頭深連結、外部分享連結仍可能把使用者帶到應徵頁——該補「你已封鎖此公司,主動應徵對方即可看到你的履歷」確認。
- 防識別是程度問題不是開關:104 實務上 HR 仍能感知「有人封鎖我」(匿名投遞痕跡、私訊勸關履歷)。mockup 的「完全匿名」文案在後端逐一驗證所有計數器前不要上。
- 封鎖清單要當高敏感個資管:它等於「使用者的現任雇主+防範對象清單」。1111 的外洩是真實案例。建議 BR-017 之上明確加存取管控與稽核 log 條款。
7. 行動清單與處理狀態(2026/07/14 分流後)
分流原則:delivery owner 可決事項已回寫 PRD v1.1.0;需產品拍板的 6 題移至
block-company-pm-decisions.md(Q1-Q6);mockup 修正為實作待辦。
| # | 行動 | 狀態 |
|---|---|---|
| 1 | 既有訊息功能的封鎖行為 | ➡️ PM 便箋 Q1(Blocking) |
| 1b | pm_45:pipeline 隱藏 vs 刪除、企業收藏對稱性(列表排除 pm_45:216 已接) | ➡️ 與 pm_45 owner 對齊(規格期) |
| 1c | v1 範圍矛盾:再投隱藏 v1/v2(§1-4) | ➡️ PM 便箋 Q2(Blocking) |
| 2 | 兩種入口是否都收 | ✅ 已裁決 Q3=C(PRD v1.2.0 fa0ced0):只留帳號設定搜尋入口,公司頁入口廢除 |
| 3 | mockup 三 bug | ✅ 突破上限、重複封鎖已修(0abb390,瀏覽器實測);取消不回滾隨 Q3 確認語意處理 |
| 4 | 收藏移除可逆性 | ➡️ PM 便箋 Q4 |
| 5 | Edge Case 表補列(排程過濾/帳號刪除/企業端直連/公司關閉/回饋) | ✅ 已回寫 PRD v1.1.0 §10.4;多帳號匹配範圍 ➡️ Q5 |
| 6 | 原因 UI、SEC-4 遮罩、BlockToggle、缺 scenario | 🔧 mockup 待辦 |
| 7 | 「已投對方仍可見」告知文案 | ✅ 已回寫 PRD SEC-3;二次確認 ➡️ Q6 |
| 8 | 封鎖名單資安等級條款 | ✅ 已回寫 PRD §12 注意事項 |
| 9 | 上限文案/假搜尋/「完全匿名」 | ✅ 三項均已修(0abb390,瀏覽器實測);「匿名」文案禁令 ✅ 已寫入 PRD §12 |
| 10 | 回饋機制、清單搜尋、公司關閉顯示、loading | ✅ 已回寫 PRD SEC-1/SEC-3/§10.4;解封 undo 政策隨 Q4 |
附錄:瀏覽器實測記錄
- 環境:storybook.wport.me(線上版),story 互動模式逐 scenario 操作
- 實測路徑:has-items 解除封鎖(即點即移除、計數 5→4、無確認無 toast)→ 新增封鎖 Modal(三宏含收藏提示、點擊立即寫入)→ 重複封鎖華勝(清單出現兩筆,6/50)→ 取消關窗(已寫入不回滾)→ limit-reached(50/50 按鈕灰、點擊靜默)→ empty(空狀態文案正常,但 0/50 仍掛「已達上限」句)
- 靜態比對範圍:PRD 全文 320 行 ×
MockupBlockCompany.vue(508 行)×block-company.ts×BlockCompany.stories.ts×block-company-demo.vue
文件結束