Files
crearte-monorepo/docs/plans/2026-09-30-creator-center.md

17 KiB
Raw Permalink Blame History

创作者中心(/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 切功能分支

cd crearte-monorepo/crearte
git checkout master
git checkout -b feat/creator-center
  • Step 2: 写失败的 e2e(第 1 条用例)

创建 src/e2e/creator.spec.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:

<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 路由行之后插入:

    { path: '/creator', name: 'creator', component: () => import('@/views/CreatorCenterView.vue') },
  • Step 6: AppHeader 加 tab

src/app/components/AppHeader.vue script 段,在 onDocs 行之后加:

const onCreator = computed(() => route.name === 'creator')

template 主导航 <nav> 内,「文档」RouterLink 之后、</nav> 之前插入:

        <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: 提交
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 改为:

import { expect, test } from '@playwright/test'
import { seedSession } from './helpers'

文件末尾追加:

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([]) 之前)追加:

  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 段改为:

<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 加):

  <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: 提交
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 末尾追加:

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> 之前插入:

    <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: 提交
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 之前插入:

## [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: 全量验证(四条命令依次跑,必须全绿)
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
cd crearte-monorepo/crearte
git add docs/CHANGELOG.md
git commit -m "docs: changelog 0.17.0 — creator center"
  • Step 4: 推送功能分支(触发 CI)
git push origin feat/creator-center

Expected: 推送成功;validate.yml 工作流对分支运行(若失败,修复后追加提交再推送,勿改历史)。

  • Step 5: 合并回 master(--no-ff)并删分支
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
git push origin master

Expected: master 更新,包含 4 个功能提交 + 1 个合并提交。

  • Step 7: 收尾核对
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 衔接。