Compare commits
3
Commits
7a6262f5ce
...
820914f0f1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
820914f0f1 | ||
|
|
34fbbe608d | ||
|
|
f8fe8482d8 |
@@ -53,3 +53,4 @@
|
||||
| P4 作者主页 | `docs/specs/2026-09-29-author-page-design.md` | `docs/plans/2026-09-29-author-page.md`(已执行,2026-09-29) |
|
||||
| P1 prod 写侧可用 | `docs/specs/2026-09-29-prod-write-side-design.md` | `docs/plans/2026-09-29-prod-write-side.md`(已执行,2026-09-29) |
|
||||
| P5 收藏/评分 | `docs/specs/2026-09-30-favorites-ratings-design.md` | `docs/plans/2026-09-30-favorites-ratings.md`(已执行,2026-09-30) |
|
||||
| 创作者中心 `/creator`(维护者直接需求) | `docs/specs/2026-09-30-creator-center-design.md` | `docs/plans/2026-09-30-creator-center.md` |
|
||||
|
||||
@@ -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 衔接。
|
||||
@@ -0,0 +1,108 @@
|
||||
# 创作者中心(`/creator`)设计 / Creator Center Design
|
||||
|
||||
- **状态**:设计已批准(2026-09-30;入口=主导航、教程卡=占位+链现有文档、数据卡按登录态分流,逐项与维护者确认),待 spec 审阅后转实现计划。
|
||||
- **路线图**:维护者直接需求,未列入既有波次(P1–P8);仅在文末索引登记。
|
||||
- **范围定性**:纯前端新页面(crearte 仓);**零后端、零数据迁移、crearte-deploy 零改动**。
|
||||
|
||||
## 1. 背景与意图
|
||||
|
||||
站内投稿入口埋在登录后的用户下拉菜单里,主导航只有「作品 / 文档」:潜在创作者从任何公开页面都看不到"成为创作者"的路径;已投稿的创作者也没有回看自己作品数据(浏览 / 下载 / 评分)的承载页。
|
||||
|
||||
本子项目先搭骨架:一个首页样式的**创作者中心**(hero + 两张卡)——「作品数据」占位(后续接真实数据)与「创作教程」占位(教程内容维护者仍在构思,文档可能大规模重构,本轮只做占位并链向现有文档)。
|
||||
|
||||
成功标准:主导航出现第三个 tab;`/creator` 渲染 hero 与两张卡;未登录时数据卡引导登录并可回跳,已登录显示建设中文案;noauth 部署下页面可达且不出现死链。
|
||||
|
||||
约束(与维护者确认):
|
||||
|
||||
- 入口放页头主导航(「作品」「文档」旁),匿名可进。
|
||||
- 教程内容定稿前,教程卡只放占位说明 + 链到现有《提交作品指南》。
|
||||
- 数据卡是纯占位:不接任何真实聚合,不做图表。
|
||||
|
||||
## 2. 方案选型
|
||||
|
||||
| 方案 | 内容 | 取舍 |
|
||||
|---|---|---|
|
||||
| **A. 独立新视图 + 主导航 tab(已选)** | 新路由 `/creator`(无参数)、新 `CreatorCenterView`、`AppHeader` 加第三个 tab | 与既有信息架构同构(作品 / 文档 / 创作者中心);页面无参数无 404 面;后续数据卡、教程都可原地替换 |
|
||||
| B. 收进登录后用户下拉菜单 | 与「提交作品」并列 | 仅登录可见,潜在创作者看不到路径;维护者已明确否 |
|
||||
| C. 并入 `/docs` 文档流 | 教程进文档 sidebar,数据卡无处安放 | 数据卡无归属;且文档即将重构,现在挂进去白做 |
|
||||
|
||||
卡内三态(`authEnabled` 未登录 / 已登录 / noauth)直接用既有 `authEnabled` + `session`(`@/auth`,`AppHeader` 同款用法),不引入新的状态管理。
|
||||
|
||||
## 3. 设计详述
|
||||
|
||||
### 3.1 路由与导航
|
||||
|
||||
- `src/app/router/index.ts` 注册 `{ path: '/creator', name: 'creator', component: () => import('@/views/CreatorCenterView.vue') }`,**不加** `meta.requiresAuth`(公开页,登录态只在卡内部分流)。
|
||||
- `src/app/components/AppHeader.vue`:
|
||||
- 新增 `onCreator` computed(`route.name === 'creator'`)。
|
||||
- 主导航加第三个 `RouterLink`「创作者中心」,激活样式与「作品 / 文档」完全一致(`border-b-accent-ink` + `aria-current="page"`)。
|
||||
- 贴纸(sticker)逻辑不变:creator 页回落默认 `HOST YOUR CREATIONS`。
|
||||
|
||||
### 3.2 页面结构(`src/app/views/CreatorCenterView.vue`)
|
||||
|
||||
复刻 `LandingView.vue` 的墨纸语言:同类 class,不引新 design token、不改 `main.css`。
|
||||
|
||||
- **hero 区**(`border-[3px] border-ink bg-surface px-6 py-10 text-center shadow-hard sm:px-10 sm:py-14`):
|
||||
- 徽章「创作者」(`bg-ink` 反转块,同首页「创艺」徽章样式);
|
||||
- 标题「创作者中心」(`font-display` 大字);
|
||||
- 等宽字体标语行 `SHARE YOUR CREATIONS`;
|
||||
- 分隔条 + 说明行「把你的作品分享给所有人」;
|
||||
- 两个按钮:「提交作品」→ `/submit/new`(该路由 `requiresAuth`,未登录由既有守卫转 `/login?next=/submit/new`,无需本页处理)、「投稿指南」→ `/docs/contribute`。
|
||||
- **卡片行**(`mt-8 flex flex-col gap-4 sm:flex-row`,与首页「投稿与文档」行同款;外层 `sr-only` h2「创作者中心」保持大纲结构):
|
||||
- 卡 1 **作品数据**(占位),三态:
|
||||
- `authEnabled && !user`:「登录后即可查看您作品的数据。」+ 链接「登录」→ `/login?next=/creator`;
|
||||
- `authEnabled && user`:「数据面板正在建设中。上线后将展示您作品的浏览、下载与评分。」;
|
||||
- `!authEnabled`(noauth 部署):「数据面板正在建设中。」——**不给登录链接**(该模式无账号体系,链过去会被守卫打回首页)。
|
||||
- 卡 2 **创作教程**(占位):「教程整理中,敬请期待。」+「投稿流程、打包规范与过审要点正在重新整理,完成后在本页发布。」+ 链接「《提交作品指南》」→ `/docs/contribute`(先行阅读)。
|
||||
- 卡片与链接样式复用首页卡片同款 class(`flex-1 border-2 border-ink bg-surface p-4 shadow-hard-sm`、`h3 text-sm font-black`、正文 `mt-2 text-xs leading-relaxed text-ink-soft`、链接 `underline`)。
|
||||
|
||||
### 3.3 数据流与状态
|
||||
|
||||
- **无数据请求**:页面不调 `repo`,不用 `useAsync`;无加载 / 失败态,不套 `StatePanel`(与首页 hero 区一致)。
|
||||
- 登录态:`import { authEnabled, session } from '@/auth'`,`user = computed(() => session.state.user)`;`authEnabled` 为构建期常量(`VITE_API_BASE_URL` 判空,`src/app/content/index.ts` 同款判定)。
|
||||
- 不新增路由守卫、不新增 store、不新增 composable。
|
||||
|
||||
### 3.4 边界与错误处理
|
||||
|
||||
- 无异步 ⇒ 无错误面;`/creator` 无参数 ⇒ 无 404 面。
|
||||
- noauth 部署:页面可达,数据卡降级为纯建设中文案(无登录死链)。
|
||||
- 登录链接的 `next` 经 `LoginView` 既有 `sanitizeNext` 处理,只接受站内路径(`/creator` 合法)。
|
||||
|
||||
## 4. 测试
|
||||
|
||||
- **Playwright 新增 `src/e2e/creator.spec.ts`**:
|
||||
1. 主导航存在「创作者中心」tab;`/creator` 上该 tab `aria-current="page"`;hero 与两张卡渲染。
|
||||
2. 未登录(默认 context):数据卡含「登录」链接,`href="/login?next=/creator"`。
|
||||
3. 已登录(`seedSession`,参考 `auth.spec.ts` 既有用法):数据卡显示建设中文案、**无**登录链接。
|
||||
4. 教程卡含指向 `/docs/contribute` 的链接。
|
||||
5. noauth 配置(`playwright.noauth.config.ts`):`/creator` 可达、数据卡无登录链接。
|
||||
- **无 Vitest 单测**:视图只有登录态分支、无业务逻辑,e2e 覆盖更值(作者页有过滤逻辑故有单测,本页无可测逻辑)。
|
||||
- 门槛:`vue-tsc --noEmit` 全量绿;默认 + noauth 两套 e2e 全量绿(存量不回归)。
|
||||
|
||||
## 5. 影响文件(预估)
|
||||
|
||||
| 文件 | 改动 |
|
||||
|---|---|
|
||||
| `src/app/router/index.ts` | 注册 `/creator` |
|
||||
| `src/app/views/CreatorCenterView.vue` | 新建 |
|
||||
| `src/app/components/AppHeader.vue` | 主导航加 tab + `onCreator` |
|
||||
| `src/e2e/creator.spec.ts` | 新建 |
|
||||
| `docs/CHANGELOG.md`(crearte 仓) | 0.17.0 双语条目(master 顶部为 0.16.0,本功能自 master 切分支) |
|
||||
| `docs/ROADMAP.md`(wrapper 仓) | 文末索引登记本 spec 与实现计划 |
|
||||
|
||||
## 6. 验收标准
|
||||
|
||||
1. 主导航出现「创作者中心」tab,激活态与「作品 / 文档」一致。
|
||||
2. `/creator` 渲染 hero + 两张卡,视觉语言与首页一致(同类边框 / 阴影 / 字号,零新 token)。
|
||||
3. 三态分流正确:未登录给登录链接(`next=/creator`);已登录给建设中文案;noauth 可达且无登录死链。
|
||||
4. 教程卡占位文案 + `/docs/contribute` 链接就位。
|
||||
5. `e2e/creator.spec.ts` 新增用例通过,且存量全量(vitest + 默认 / noauth e2e + `vue-tsc`)全绿。
|
||||
6. `crearte-server` / `crearte-deploy` 零 diff。
|
||||
|
||||
## 7. 明确不做(Out of scope)
|
||||
|
||||
- **作品数据面板的真实聚合**:浏览 / 下载 / 评分的查询、图表、口径——后续数据卡范围,需先定数据来源与埋点。
|
||||
- **教程正文**:待维护者文档重构定稿后另行立项;本轮的占位卡即为将来的替换点。
|
||||
- 「我的提交」入口从用户下拉菜单迁移 / 合并(`/submit` 留在原处)。
|
||||
- 导航贴纸计数、hero 统计条等首页既有元件的复制。
|
||||
- 任何后端 / 部署 / 数据迁移改动。
|
||||
Reference in New Issue
Block a user