@@ -0,0 +1,398 @@
# 创作者中心(/creator) Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal: ** 在 crearte 前端新增首页样式的「创作者中心」页(`/creator` ):hero + 「作品数据」占位卡(按登录态三态分流)+「创作教程」占位卡(链现有文档),页头主导航加第三个 tab。
**Architecture: ** 纯前端改动——一个新路由、一个新视图(复刻 `LandingView.vue` 的墨纸 class 体系,零新 token)、`AppHeader` 加 tab;登录态用既有 `authEnabled` + `session` ( `@/auth` );页面无数据请求、无加载/失败态。测试走 Playwright e2e(默认配置 + noauth 配置),TDD:先写失败 e2e 再实现。
**Tech Stack: ** Vue 3 `<script setup>` + TypeScript + vue-router + Tailwind class 体系;Playwright( `@playwright/test` );crearte 仓(monorepo 内层前端仓)。
**Spec: ** `crearte-monorepo/docs/specs/2026-09-30-creator-center-design.md`
## Global Constraints
- 工作目录:`crearte-monorepo/crearte` (内层前端仓)。除标注外,所有命令在 `crearte-monorepo/crearte/src` 下执行。
- 分支:从 `master` (当前顶端 `eb5fbed` , changelog 0.16.0)切 `feat/creator-center` 。crearte AGENTS.md: dev 分支命名 `{feat|fix|docs|chore}/{name}` ; **不在 master 上直接提交**。
- 每个 Task 完成即提交,提交信息风格对齐仓库现状(`feat(scope): 简述` )。
- 文案逐字采用 spec §3.2,不得改写:hero 徽章「创作者」、标语 `SHARE YOUR CREATIONS` 、说明「把你的作品分享给所有人」、按钮「提交作品」「投稿指南」;卡标题「作品数据」「创作教程」;数据卡三态文案与教程卡占位文案见各 Task。
- 样式只复用 `LandingView.vue` 既有 class;不新增 design token、不改 `main.css` 。
- CHANGELOG: `docs/CHANGELOG.md` ( crearte 仓)顶部追加 `## [0.17.0] - 2026-09-30` 条目;同一条目英文行、中文行连续书写(中间无空行),条目之间空行分隔。
- 完成定义:`npx vitest run` 、`npx vue-tsc --noEmit` 、`npx playwright test` 、`npx playwright test --config playwright.noauth.config.ts` 四条全绿;最后 `--no-ff` 合并回 `master` 、删分支、推送。
- 默认 e2e 构建注入了 `VITE_API_BASE_URL=http://localhost:4173` ( `authEnabled === true` );noauth 构建注入空值(`authEnabled === false` )。两条路径都要覆盖。
---
### Task 1: 分支准备 + 路由 + 主导航 tab + hero
**Files: **
- Create: `src/app/views/CreatorCenterView.vue` (先只含 hero)
- Modify: `src/app/router/index.ts` (在 `home` 路由后插入 `creator` 路由)
- Modify: `src/app/components/AppHeader.vue` ( `onCreator` computed + 主导航第三个 tab)
- Test: `src/e2e/creator.spec.ts` (新建,先写第 1 条用例)
**Interfaces: **
- Consumes: 无(首个任务)
- Produces: 路由 `{ path: '/creator', name: 'creator' }` ;视图默认导出 `CreatorCenterView.vue` ;header tab 可访问名「创作者中心」(激活时 `aria-current="page"` )
- [ ] **Step 1: 从 master 切功能分支 **
``` bash
cd crearte-monorepo/crearte
git checkout master
git checkout -b feat/creator-center
```
- [ ] **Step 2: 写失败的 e2e(第 1 条用例) **
创建 `src/e2e/creator.spec.ts` :
``` ts
import { expect , test } from '@playwright/test'
test ( '主导航有创作者中心 tab, /creator 渲染 hero' , async ( { page } ) = > {
await page . goto ( 'http://localhost:4173/creator' )
const tab = page . locator ( 'header' ) . getByRole ( 'link' , { name : '创作者中心' } )
await expect ( tab ) . toBeVisible ( )
await expect ( tab ) . toHaveAttribute ( 'aria-current' , 'page' )
await expect ( page . getByRole ( 'heading' , { level : 1 , name : '创作者中心' } ) ) . toBeVisible ( )
await expect ( page . getByText ( 'SHARE YOUR CREATIONS' ) ) . toBeVisible ( )
await expect ( page . getByText ( '把你的作品分享给所有人' ) ) . toBeVisible ( )
await expect ( page . getByRole ( 'link' , { name : '提交作品' } ) ) . toHaveAttribute ( 'href' , '/submit/new' )
await expect ( page . getByRole ( 'link' , { name : '投稿指南' } ) ) . toHaveAttribute ( 'href' , '/docs/contribute' )
} )
```
- [ ] **Step 3: 运行确认失败 **
Run: `cd src && npx playwright test e2e/creator.spec.ts`
Expected: FAIL——`/creator` 落入 NotFound 路由,heading「创作者中心」不存在(Playwright 自动拉起 webServer: `build:e2e` + `serve-runtime` ,首次约 1– 3 分钟)。
- [ ] **Step 4: 新建视图(仅 hero) **
创建 `src/app/views/CreatorCenterView.vue` :
``` vue
< script setup lang = "ts" >
import { RouterLink } from 'vue-router'
const SLOGAN = 'SHARE YOUR CREATIONS'
const TAGLINE = '把你的作品分享给所有人'
< / script >
< template >
< section class = "border-[3px] border-ink bg-surface px-6 py-10 text-center shadow-hard sm:px-10 sm:py-14" >
< span class = "inline-block bg-ink px-2 py-1 text-[0.6875rem] font-bold tracking-[0.3em] text-paper" > 创作者 < / span >
< h1 class = "mt-3 font-display text-4xl leading-none font-black tracking-tight sm:text-5xl md:text-6xl" > 创作者中心 < / h1 >
< p class = "mt-3 font-mono text-[0.6875rem] tracking-[0.3em] text-ink-soft" > { { SLOGAN } } < / p >
< div class = "mx-auto my-5 h-[3px] w-16 bg-ink" > < / div >
< p class = "text-sm text-ink-soft" > { { TAGLINE } } < / p >
< div class = "mt-6 flex flex-wrap justify-center gap-3" >
< RouterLink to = "/submit/new" class = "btn-ink lift hover:shadow-hard active:shadow-none" > 提交作品 < / RouterLink >
< RouterLink to = "/docs/contribute" class = "btn-surface lift hover:shadow-hard active:shadow-none" > 投稿指南 < / RouterLink >
< / div >
< / section >
< / template >
```
- [ ] **Step 5: 注册路由 **
`src/app/router/index.ts` ,在 `home` 路由行之后插入:
``` ts
{ path : '/creator' , name : 'creator' , component : ( ) = > import ( '@/views/CreatorCenterView.vue' ) } ,
```
- [ ] **Step 6: AppHeader 加 tab **
`src/app/components/AppHeader.vue` script 段,在 `onDocs` 行之后加:
``` ts
const onCreator = computed ( ( ) = > route . name === 'creator' )
```
template 主导航 `<nav>` 内,「文档」RouterLink 之后、`</nav>` 之前插入:
``` html
< RouterLink
to = "/creator"
class = "border-b-[3px] pb-0.5 text-sm font-bold"
:class = "onCreator ? 'border-b-accent-ink text-accent-ink' : 'border-b-transparent text-ink-soft'"
:aria-current = "onCreator ? 'page' : undefined"
> 创作者中心< / RouterLink >
```
- [ ] **Step 7: 运行确认通过 **
Run: `npx playwright test e2e/creator.spec.ts`
Expected: PASS( 1 passed)
- [ ] **Step 8: 提交 **
``` bash
cd crearte-monorepo/crearte
git add src/app/views/CreatorCenterView.vue src/app/router/index.ts src/app/components/AppHeader.vue src/e2e/creator.spec.ts
git commit -m "feat(creator): /creator route, header tab and hero — landing-style skeleton"
```
---
### Task 2: 作品数据卡(登录态三态分流)
**Files: **
- Modify: `src/app/views/CreatorCenterView.vue` ( script 加 `user` computed; template 在 hero 后加卡片行 + 「作品数据」卡)
- Modify: `src/e2e/creator.spec.ts` (追加第 2、3 条用例)
- Modify: `src/e2e/noauth.spec.ts` (在既有用例末尾追加 `/creator` 断言)
**Interfaces: **
- Consumes: Task 1 的 `/creator` 路由与视图;`authEnabled` / `session` ( `@/auth` , `AppHeader.vue` 同款用法)
- Produces: 卡片标题「作品数据」(h3);未登录时卡内「登录」链接 `href="/login?next=%2Fcreator"`
- [ ] **Step 1: 写失败的 e2e(第 2、3 条用例) **
`src/e2e/creator.spec.ts` 头部 import 改为:
``` ts
import { expect , test } from '@playwright/test'
import { seedSession } from './helpers'
```
文件末尾追加:
``` ts
test ( '数据卡:未登录给登录引导且 next 回跳 /creator' , async ( { page } ) = > {
await page . goto ( 'http://localhost:4173/creator' )
const card = page . getByRole ( 'heading' , { name : '作品数据' } ) . locator ( '..' )
await expect ( card . getByText ( '登录后即可查看您作品的数据。' ) ) . toBeVisible ( )
await expect ( card . getByRole ( 'link' , { name : '登录' } ) ) . toHaveAttribute ( 'href' , '/login?next=%2Fcreator' )
} )
test ( '数据卡:已登录显示建设中文案且无登录链接' , async ( { page } ) = > {
await seedSession ( page )
await page . goto ( 'http://localhost:4173/creator' )
const card = page . getByRole ( 'heading' , { name : '作品数据' } ) . locator ( '..' )
await expect ( card . getByText ( '数据面板正在建设中。上线后将展示您作品的浏览、下载与评分。' ) ) . toBeVisible ( )
await expect ( card . getByRole ( 'link' , { name : '登录' } ) ) . toHaveCount ( 0 )
} )
```
`src/e2e/noauth.spec.ts` 既有用例末尾(`expect(authRequests).toEqual([])` 之前)追加:
``` ts
await page . goto ( '/creator' )
await expect ( page . getByRole ( 'heading' , { level : 1 , name : '创作者中心' } ) ) . toBeVisible ( )
await expect ( page . getByText ( '数据面板正在建设中。' , { exact : true } ) ) . toBeVisible ( )
await expect ( page . getByRole ( 'link' , { name : '登录' } ) ) . toHaveCount ( 0 )
```
- [ ] **Step 2: 运行确认失败 **
Run: `npx playwright test e2e/creator.spec.ts`
Expected: FAIL——「作品数据」heading 不存在。
- [ ] **Step 3: 实现数据卡 **
`src/app/views/CreatorCenterView.vue` script 段改为:
``` vue
< script setup lang = "ts" >
import { computed } from 'vue'
import { RouterLink } from 'vue-router'
import { authEnabled , session } from '@/auth'
const SLOGAN = 'SHARE YOUR CREATIONS'
const TAGLINE = '把你的作品分享给所有人'
const user = computed ( ( ) => session . state . user )
< / script >
```
template 在 hero `</section>` 之后追加(本 Task 先只放数据卡,教程卡在 Task 3 加):
``` html
< section class = "mt-8 flex flex-col gap-4 sm:flex-row" >
< h2 class = "sr-only" > 创作者中心< / h2 >
< section class = "flex-1 border-2 border-ink bg-surface p-4 shadow-hard-sm" >
< h3 class = "text-sm font-black" > 作品数据< / h3 >
< p class = "mt-2 text-xs leading-relaxed text-ink-soft" >
< template v-if = "authEnabled && !user" > 登录后即可查看您作品的数据。< RouterLink :to = "{ path: '/login', query: { next: '/creator' } }" class = "underline" > 登录< / RouterLink > < / template >
< template v-else-if = "authEnabled" > 数据面板正在建设中。上线后将展示您作品的浏览、下载与评分。< / template >
< template v-else > 数据面板正在建设中。< / template >
< / p >
< / section >
< / section >
```
- [ ] **Step 4: 运行确认通过(默认配置) **
Run: `npx playwright test e2e/creator.spec.ts`
Expected: PASS( 3 passed)
- [ ] **Step 5: 运行 noauth 配置确认通过 **
Run: `npx playwright test --config playwright.noauth.config.ts`
Expected: PASS( 1 passed,含新增的 `/creator` 断言)
- [ ] **Step 6: 提交 **
``` bash
cd crearte-monorepo/crearte
git add src/app/views/CreatorCenterView.vue src/e2e/creator.spec.ts src/e2e/noauth.spec.ts
git commit -m "feat(creator): work-data placeholder card with three auth states (anon prompt / signed-in / noauth)"
```
---
### Task 3: 创作教程卡(占位 + 链现有文档)
**Files: **
- Modify: `src/app/views/CreatorCenterView.vue` (卡片行内追加「创作教程」卡)
- Modify: `src/e2e/creator.spec.ts` (追加第 4 条用例)
**Interfaces: **
- Consumes: Task 2 的卡片行结构(`section.mt-8.flex ... sm:flex-row` )
- Produces: 卡片标题「创作教程」(h3);卡内链接「《提交作品指南》」`href="/docs/contribute"`
- [ ] **Step 1: 写失败的 e2e(第 4 条用例) **
`src/e2e/creator.spec.ts` 末尾追加:
``` ts
test ( '教程卡占位并链到提交作品指南' , async ( { page } ) = > {
await page . goto ( 'http://localhost:4173/creator' )
const card = page . getByRole ( 'heading' , { name : '创作教程' } ) . locator ( '..' )
await expect ( card . getByText ( '教程整理中,敬请期待。' ) ) . toBeVisible ( )
await expect ( card . getByRole ( 'link' , { name : '《提交作品指南》' } ) ) . toHaveAttribute ( 'href' , '/docs/contribute' )
} )
```
- [ ] **Step 2: 运行确认失败 **
Run: `npx playwright test e2e/creator.spec.ts`
Expected: FAIL——「创作教程」heading 不存在。
- [ ] **Step 3: 实现教程卡 **
`src/app/views/CreatorCenterView.vue` ,在「作品数据」卡的 `</section>` 之后、卡片行 `</section>` 之前插入:
``` html
< section class = "flex-1 border-2 border-ink bg-surface p-4 shadow-hard-sm" >
< h3 class = "text-sm font-black" > 创作教程< / h3 >
< p class = "mt-2 text-xs leading-relaxed text-ink-soft" > 教程整理中,敬请期待。投稿流程、打包规范与过审要点正在重新整理,完成后在本页发布;可先阅读< RouterLink to = "/docs/contribute" class = "underline" > 《提交作品指南》< / RouterLink > 。< / p >
< / section >
```
- [ ] **Step 4: 运行确认通过 **
Run: `npx playwright test e2e/creator.spec.ts`
Expected: PASS( 4 passed)
- [ ] **Step 5: 提交 **
``` bash
cd crearte-monorepo/crearte
git add src/app/views/CreatorCenterView.vue src/e2e/creator.spec.ts
git commit -m "feat(creator): tutorial placeholder card linking to the submission guide"
```
---
### Task 4: CHANGELOG + 全量验证 + 合并回 master + 推送
**Files: **
- Modify: `docs/CHANGELOG.md` ( crearte 仓,追加 0.17.0)
**Interfaces: **
- Consumes: Task 1– 3 的全部提交(分支 `feat/creator-center` )
- Produces: `master` 上的合并提交与 0.17.0 条目;远端更新
- [ ] **Step 1: 追加 CHANGELOG 条目 **
`docs/CHANGELOG.md` ,在文件说明段之后、`## [0.16.0] - 2026-09-30` 之前插入:
``` md
## [0.17.0] - 2026-09-30
### Added / 新增
- Added the Creator Center (`/creator` ): a homepage-style page with a hero (提交作品 / 投稿指南 CTAs) and two cards — 「作品数据」 (placeholder adapting to auth state: anonymous visitors get a login prompt with `next` return, signed-in users see build-in-progress copy, noauth deploys show no login link) and 「创作教程」 (placeholder linking to the existing submission guide until the tutorial content lands). The header main nav gains a third tab with the same active styling as 作品/文档. No backend or deploy changes.
- 新增创作者中心(`/creator` ):首页样式页面,hero(提交作品 / 投稿指南两个按钮)+ 两张卡——「作品数据」占位卡按登录态分流(未登录给登录引导并带 `next` 回跳、已登录显示建设中文案、noauth 部署不出现登录链接)与「创作教程」占位卡(教程内容定稿前链向现有《提交作品指南》)。页头主导航新增第三个 tab,激活样式与「作品 / 文档」一致。零后端、零部署改动。
```
- [ ] **Step 2: 全量验证(四条命令依次跑,必须全绿) **
``` bash
cd crearte-monorepo/crearte/src
npx vitest run
npx vue-tsc --noEmit
npx playwright test
npx playwright test --config playwright.noauth.config.ts
```
Expected: vitest 全 passed(存量 333+,无新增单测);`vue-tsc` 无输出;默认 e2e 全 passed(含 creator.spec.ts 4 条,存量不回归);noauth e2e 1 passed。
- [ ] **Step 3: 提交 CHANGELOG **
``` bash
cd crearte-monorepo/crearte
git add docs/CHANGELOG.md
git commit -m "docs: changelog 0.17.0 — creator center"
```
- [ ] **Step 4: 推送功能分支(触发 CI) **
``` bash
git push origin feat/creator-center
```
Expected: 推送成功;`validate.yml` 工作流对分支运行(若失败,修复后追加提交再推送,勿改历史)。
- [ ] **Step 5: 合并回 master( --no-ff)并删分支 **
``` bash
git checkout master
git merge --no-ff feat/creator-center -m "merge: creator center (/creator) — placeholder data & tutorial cards, header tab; crearte 0.17.0"
git branch -d feat/creator-center
```
- [ ] **Step 6: 推送 master **
``` bash
git push origin master
```
Expected: `master` 更新,包含 4 个功能提交 + 1 个合并提交。
- [ ] **Step 7: 收尾核对 **
``` bash
git log --oneline -6
git status --short --branch
```
Expected: 合并提交在顶端;工作区干净、与 `origin/master` 同步。
---
## Self-Review 记录(计划编写时自查)
**1. Spec 覆盖核对: **
| Spec 验收标准 | 对应步骤 |
|---|---|
| 1. 主导航 tab + 激活态一致 | Task 1 Step 2/6/7 |
| 2. hero + 两卡、视觉语言复用 | Task 1 Step 4、Task 2 Step 3、Task 3 Step 3 |
| 3. 三态分流(未登录 next / 已登录 / noauth) | Task 2 Step 1/3/4/5 |
| 4. 教程卡占位 + /docs/contribute 链接 | Task 3 |
| 5. 新增 e2e 通过 + 存量全量绿 | Task 2– 4 各 Step 4/5、Task 4 Step 2 |
| 6. server / deploy 零 diff | 全程只碰 `src/` 与 crearte 仓 `docs/CHANGELOG.md` |
**2. 占位符扫描: ** 无 TBD/TODO;每步含确切代码或命令;失败预期逐条写明。
**3. 一致性: ** 路由名 `creator` 、视图 `CreatorCenterView.vue` 、tab 名「创作者中心」、登录链接 `href="/login?next=%2Fcreator"` 、教程链接 `href="/docs/contribute"` 在各 Task 间一致;CHANGELOG 版本 0.17.0 与 master 顶端 0.16.0 衔接。