Prompt file imported from MarioooooLin/TaskSystem (
.github/prompts/kol-web-foundation.prompt.md). Copyright stays with the author.
實作 KOL RWD 網站基礎、會員骨架與任務頁面
請直接在目前 TaskSystem solution 實作,不要只提供範例程式碼或文字建議。
0. 先讀取並遵守
開始修改前,完整閱讀:
.github/copilot-instructions.md.github/CONTRIBUTING.md.github/specs/kol-auth.md.github/specs/kol-pages.md.github/instructions/kol.instructions.md.github/schema.sqlKol/Template/下所有 HTML、CSS 與 imagesKol/Program.csInfrastructure/Web/TaskSystemWebExtensions.cs- 既有 Admin/Merchant 的 Account、Email 驗證、Dapper Repository、Application Handler 與 Cookie 登入實作,優先重用既有模式,不複製出另一套基礎設施。
若舊文件出現以下描述,視為已被 kol-auth.md 取代:
- KOL 使用 LIFF 或 LINE MINI App
Users.Email改為 nullable- LINE OAuth
userId存入KolProfiles.LineContactId - Callback URL 填在 Messaging API Webhook
- KOL
.cshtml暫不建立
本次指令已明確授權 Phase 1~5 的必要檔案;不要每完成一個檔案就停下。請依 Phase 分段實作,每完成一個 Phase 先建置並修正該 Phase 造成的錯誤,再繼續下一 Phase。遇到會改變業務規則、資料所有權或金流的真正衝突才停止提問。
1. 已定案架構
- KOL 端是 ASP.NET Core MVC 手機優先 RWD 網站,不使用 LIFF SDK。
- 一般 LINE 官方帳號圖文選單未來導向
/Account/Login。 - 登入採 LINE Login v2.1 Web Authorization Code Flow。
- LINE Login Channel 與 Messaging API Channel 已建立在同一 Provider;Messaging API 只供後續推播,不是登入。
- Callback 最終為
/Account/LineCallback,目前尚無可設定的公開 Callback URL。 Users.Email維持必填且全系統唯一。- 第一次 LINE Login 必須補填並驗證 Email;驗證成功前不建立正式
Users。 - LINE
userId存入UserExternalLogins.ProviderUserId;KolProfiles.LineContactId只保存人工聯絡用 LINE ID。 - 正式登入使用現有
.TaskSystem.KolCookie。 - 本次完成 Phase 1~5;Phase 6 只完成設定、介面、路由與停用狀態,不呼叫真實 LINE API,也不得宣稱 OAuth 已驗證完成。
2. Phase 1 — MVC 共用版型
以 Kol/Template 為設計來源:
- 保留
Kol/Template原檔,不直接修改。 - 將需要的 CSS、images 搬到
Kol/wwwroot的合理位置,使用 ASP.NET Core static file 路徑。 - 建立 KOL 專用
Kol/Views/Shared/_Layout.cshtml。 - 建立並使用:
_KolHeader.cshtml_KolFooter.cshtml_KolBottomNav.cshtml
- 移除 Template 以 jQuery
.load()載入 header/footer/nav 的做法,改為 Razor partial。 - Bottom nav 的 active 狀態由目前 Controller/Action 或明確 ViewModel 決定。
- 保留主要 DOM、class、區塊順序、品牌色、字體、430px mobile-first、
100dvh與 safe-area。 - 桌面版可置中顯示手機寬度內容,但不可破壞一般 RWD 操作。
- 不建立新的 npm、Webpack、Vite 或其他前端 build pipeline。
- 將
href="#"、HTML 檔名連結與 inline onclick 改成正確 tag helper 或 unobtrusive JavaScript;不可保留會跳回頁首的假連結。 - 登入前頁面可透過獨立 layout 或 layout flag 隱藏登入後 bottom nav。
Phase 1 驗收:
- 所有共用區塊由 partial 輸出,Network 不再請求
header.html、footer.html、nav.html。 - 360px、390px、430px 與桌面寬度沒有水平捲軸。
dotnet build Kol/Kol.csproj成功。
3. Phase 2 — 登入與會員骨架
3.1 Schema 與 migration
同步更新 canonical .github/schema.sql,並新增下一號、可重複安全檢查的 migration(目前應從 scripts/migration-016-...sql 起,實作前先確認實際最新編號):
UserExternalLoginsId BIGINT IDENTITYUserId BIGINT NOT NULLFK →UsersProvider NVARCHAR(50) NOT NULLProviderUserId NVARCHAR(255) NOT NULLCreatedAt、UpdatedAtUTC- unique
(Provider, ProviderUserId) - unique
(UserId, Provider)
KolRegistrationRequests- 欄位與索引依
.github/specs/kol-auth.md Email在建立 pending request 時必填- token 只存 SHA-256 hash
- status 使用明確 enum 與 CHECK constraint
- 同一 LINE 身分、Email 不得同時有多筆有效 Pending
- 欄位與索引依
- 不修改
Users.Emailnullability。 - 不修改或移除
KolProfiles.LineContactId。
同步建立必要的 Domain Entity/Enum、Application repository interface、Infrastructure Dapper repository 與 DI 註冊。SQL 必須 parameterized。
3.2 設定與服務邊界
建立 strongly typed options:
LineLoginOptionsKolRegistrationOptionsDevelopmentLoginOptions
設定 key 依 .github/specs/kol-auth.md。真實機密只從已排除版控的 Account/TaskSystem.json/環境設定讀取,不要把值寫進 appsettings.json。
建立 LINE client 的 Application abstraction 與必要 DTO,但本次不要實作真實 HTTP OAuth:
- 建立授權網址所需資料
- 交換 authorization code
- 驗證 ID token 並取得已驗證 LINE
userId/display name/picture
介面不得讓 Controller 自己解析或信任未驗證 JWT。未啟用 LINE Login 時,網站仍要正常啟動。
3.3 Account 路由與 View
建立 Kol/Controllers/AccountController.cs 與 ViewModel/View:
GET /Account/LoginGET /Account/LineLoginGET /Account/LineCallbackGET/POST /Account/CompleteRegistrationGET /Account/VerifyEmailGET/POST /Account/ResendVerificationEmailPOST /Account/LogoutGET /Account/AccessDenied
要求:
- Template 沒有登入頁,請沿用 KOL Template 的視覺語言新增,不得套用 Admin/Merchant 外觀。
- 登入按鈕文字為「使用 LINE 註冊/登入」。
LineLogin.Enabled = false或必要設定缺少時,不拋例外、不產生假 LINE 身分;顯示「LINE 登入功能準備中」。- 已登入 KOL 進入 Login 時導向首頁。
- returnUrl 只接受 local URL。
- POST 使用 Anti-forgery,敏感端點套用既有或新增的 rate limit policy。
- 不在 URL、TempData、Log 或 View 顯示 secret、access token、ID token 或完整 ProviderUserId。
3.4 Email 驗證骨架
依現有 Merchant Email 寄送與 token hash 模式重用基礎設施,但建立 KOL 專用 use cases:
- 建立/更新 pending KOL registration
- 寄送驗證信
- 重寄驗證信與 cooldown
- 驗證一次性 token
- 驗證後建立新 KOL,或安全綁定既有 KOL
驗證完成時必須在同一 transaction:
- row lock 讀取 pending request。
- 驗證狀態、hash、期限與是否已使用。
- 再檢查
Users.Email唯一性。 - Email 不存在時建立:
Users(AccountType = Kol, PasswordHash = NULL, Status = Active)KolProfiles,DisplayName 可先取 LINE 顯示名稱,VerificationStatus 使用現有未建檔初始狀態UserExternalLogins(Provider = LINE, ProviderUserId = 已驗證 LINE userId)
- Email 已屬 KOL 且沒有 LINE 衝突時只新增綁定。
- Email 屬 Admin/Merchant、外部身分已被其他 User 使用、或 KOL 已綁其他 LINE 時,回傳不洩漏敏感資料的衝突結果,不自動合併。
- 回填 request 的 VerifiedAt/UserId/Status。
- commit 後才建立
.TaskSystem.KolCookie。
Phase 2 驗收:
- 未設定 LINE 參數時網站可啟動且登入頁可開啟。
- Users.Email 仍為 NOT NULL。
- schema 與 migration 一致。
- secret/token 不進版控與 Log。
dotnet build TaskSystem.sln成功。
4. Phase 3 — Development 測試登入
建立 POST /Account/DevelopmentLogin:
- Action 本身及 UI 同時要求
environment.IsDevelopment()與DevelopmentLogin.Enabled。 - 非 Development 一律
NotFound();不可只隱藏按鈕。 - 不接受任何外部傳入的 UserId,只能使用
DevelopmentLogin.KolUserId。 - 從資料庫載入 User 與 KolProfile,驗證
AccountType = Kol、Status = Active、KolProfile 存在。 - 使用既有
TaskSystemSignInService建立.TaskSystem.KolCookie。 - 不新增、不修改、不偽造
UserExternalLogins。 - POST 使用 Anti-forgery。
- 可沿用
scripts/seed-kol-registration-states.sql的 Active KOL,設定檔只放實際資料庫產生的 UserId,不把環境特定 ID 寫入版控。
Phase 3 驗收:
- Development 可用指定 KOL 登入並登出。
- 任意 request 不能切換到其他 UserId。
- Production/Staging 路由回 404。
5. Phase 4 — entrance/index 首頁
將以下 Template 轉成資料驅動 Razor:
entrance.html:新註冊、未完成建檔或未審核 KOL。index.html:一般首頁,可顯示進行中任務。
建立完整的 GetKolHomeQuery/Handler/DTO/Repository SQL/ViewModel。Controller 必須:
[Authorize]- 從 claim 取得 UserId
- 驗證 AccountType = Kol
- 以 UserId 取得自己的 KolProfile
- 不接受 request 傳入 KolId
資料至少包含:
- KOL 顯示名稱、頭像 fallback
- 資料完成度(由後端依實際欄位/關聯計算,不能寫死)
- 審核狀態
- LINE 綁定狀態
- 進行中任務摘要
- 導覽所需狀態
沒有資料時顯示合理 empty state,不使用 Template 的 Nene、固定百分比、固定任務與日期作正式資料。
Phase 4 驗收:
- 未登入會導向
/Account/Login。 - 不同 Development KOL 只看到自己的摘要與任務。
- entrance/index 依資料狀態正確選擇。
- 所有導覽使用 MVC route。
6. Phase 5 — 任務頁面
轉換並串接:
| Template | 功能 |
|---|---|
mission-list.html |
可報名案件列表、搜尋與篩選 |
mission-detail.html |
案件詳情 |
sign-up.html |
任務報名表 |
my-mission.html |
我的任務 |
my-mission-detail.html |
我的任務詳情 |
建立符合 .github/specs/kol-pages.md 的完整 Application Query/Command、Handler、Repository SQL、Controller、ViewModel 與 Razor View,至少包含:
GetKolAvailableCasesQueryGetKolCaseDetailQuerySubmitKolApplicationCommand或既有架構中語意相同的單一 CommandGetKolTaskListQueryGetKolTaskDetailQuery
必要規則:
- 所有 KolId 由登入 UserId 解析。
- 案件列表排除 Draft、Settled、Cancelled,並只顯示 KOL 可瀏覽案件。
- 搜尋、reward type、region、platform、pagination 使用 query string 並保留篩選狀態。
- 案件詳情需包含業者摘要、評分、條件符合提示、平台、獎勵、期限、附件與目前報名狀態。
- 條件不符合第一版仍可報名,但必須顯示原因。
- 同一 Case/KOL 只能報名一次;後端與 DB unique constraint 都要防重複。
- 報名 POST 驗證案件仍可報名、message 必填與長度、使用 transaction,成功採 PRG redirect。
- 我的任務列表與詳情只能讀取目前 KOL 的 Task,不能用只靠前端隱藏的方式授權。
- 附件下載使用既有安全檔案機制;沒有權限不可只回傳檔案實體路徑。
- Template 有按鈕但本次沒有對應頁面的成果提交、申訴等功能,不建立假成功或空 Command;保留視覺但明確 disabled/標示後續功能,或只在已有安全 route 時輸出連結。
- 所有固定示範案件、日期、評分與 KOL 名稱改為資料綁定及 empty state。
Phase 5 驗收:
- 可使用 Development Login 完成「首頁 → 案件列表 → 詳情 → 報名 → 我的任務/報名狀態」。
- 改 URL 的 CaseId/TaskId 無法讀取不應公開或不屬於目前 KOL 的資料。
- 重複送出報名不會新增第二筆。
- 篩選、返回與 bottom nav route 正常。
dotnet build TaskSystem.sln成功。
7. Phase 6 本次只保留串接點
本次不要呼叫真實 LINE API。只需確保:
- options、Application abstraction、Controller routes 與準備中 UI 已存在。
LineLogin.Enabled = false時行為安全。- 程式碼沒有硬編 Callback host。
- 後續取得 HTTPS 公開網址後,可設定:
https://<host>/Account/LineCallback
未來真正實作時必須使用:
- Authorization Code Flow
statenonce- PKCE S256
- 完整 ID token 驗證
- scopes
openid profile
Messaging API webhook 與推播不在本次範圍。
8. 品質與交付要求
- 保留使用者現有變更,不修改無關 Admin/Merchant 功能。
- 不以 static list、hard-coded template data、TODO repository 或假成功回應冒充完成。
- 使用 async/CancellationToken、parameterized Dapper SQL、既有 Result/Error 慣例。
- POST 失敗要保留輸入與 ModelState 錯誤。
- 避免 N+1 query;列表資料用合理 SQL 聚合。
- 所有日期依既有專案 UTC 儲存規則,View 顯示再轉換。
- 不新增自動化測試,除非既有程式為該功能已有測試模式;但必須完成 build 與手動驗收說明。
- 不修改
Kol/Template原始設計檔。 - 完成後列出:
- 每個 Phase 的實際變更
- migration 執行順序
Account/TaskSystem.json需要由開發者自行填入的 key(只列 key,不列 secret)- build 結果
- 電腦端手動驗收步驟
- 尚待公開 Callback URL 才能完成的項目
- 任何因缺少設計稿而採用的最小 UI 假設