From ec3494ea28314ce9950b0ecdced7d93551183e94 Mon Sep 17 00:00:00 2001 From: xiaomai Date: Fri, 1 May 2026 14:50:05 +0800 Subject: [PATCH] docs: expand project design and agent guidelines Rewrite DESIGN.md to detail product goals, data models, and API boundaries Update AGENTS.md with existing UI patterns, i18n rules, and strict completion criteria --- AGENTS.md | 158 ++++++++++++++---- DESIGN.md | 477 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 483 insertions(+), 152 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index e5799c8..9322f34 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,6 +6,7 @@ * Follow the existing structure and conventions strictly. * Make **minimal, targeted changes only**. Do not refactor unrelated code. * Prefer clarity over cleverness. Avoid unnecessary abstraction. +* Keep `DESIGN.md` aligned with implemented product behavior when changing data models, APIs, routes, permissions, or user-facing workflows. --- @@ -22,15 +23,91 @@ For any non-trivial task: Do NOT skip planning. +For documentation-only tasks, still follow the planning workflow, but do not run unrelated builds or tests unless the document change depends on generated output. + +--- + +## Project Context + +* Goal: Pokopia Wiki, a community-editable game wiki. +* Repository: pnpm workspace monorepo. +* Runtime baseline: Node.js >= 22. +* Frontend: + + * Vue + * Vite + * Vue Router + * Vue I18n + * Iconify + * TypeScript + +* Backend: + + * Node.js + * Fastify + * PostgreSQL + * `pg` + * TypeScript + +* Infra: + + * Docker + * docker compose + +--- + +## Existing Product Shape + +* Public users can browse Wiki content. +* Registered users must verify email before editing. +* Verified users can edit Wiki content and management data; there is no separate role system currently. +* Main public sections: + + * Pokemon + * Habitats + * Items + * Recipes + * Daily CheckList + +* Management covers: + + * System config + * Languages + * Daily CheckList tasks + * Sorting for Pokemon, items, recipes, and habitats + +* Main entity create/edit flows use route-backed modal dialogs. +* Internationalization is part of the product model, not just UI copy. +* Detailed edit history and editor attribution are part of entity detail behavior. + --- ## UI Design Guidelines * Use `DesignGuidelines.html` as the reference for UI design, visual style, and component behavior. * Prefer reusing existing components that already match the guidelines. +* Existing shared UI patterns include: + + * `AppShell` + * `PageHeader` + * `Modal` + * `FilterPanel` + * `EntityCard` + * `DetailSection` + * `EditMeta` + * `EditHistoryPanel` + * `Skeleton` + * `Tabs` + * `SwitchGroup` + * `TagsSelect` + * `TranslationFields` + * `ReorderableList` + * If a needed component does not exist, create the smallest necessary component based on `DesignGuidelines.html`. * Existing components may be upgraded to match `DesignGuidelines.html`, but only when directly related to the task. * Do not introduce broad UI rewrites, new design systems, or extra abstraction layers unless explicitly required. +* Use Skeleton loaders for data loading states instead of user-facing loading remarks when the existing page pattern supports it. +* Use icon-based navigation and actions consistently with the existing Iconify setup. --- @@ -42,6 +119,8 @@ Do NOT skip planning. * Introduce new layers (services, utils, hooks, etc.) unless clearly required * Split files unnecessarily * Rewrite existing modules without explicit instruction + * Change unrelated route, API, or schema behavior while working on UI-only tasks + * Prefer editing existing files over creating new ones. * Keep functions and components small and readable. @@ -62,31 +141,52 @@ User-facing UI must NEVER contain: ### Strict Rules -* Only render **business data** and intended UI text +* Only render **business data** and intended UI text. * Never display: * "Updated successfully because..." * "Changed X to Y" * "TODO", "NOTE", "DEBUG" -* Debug information must go to logs, not UI -* Separate internal data from API responses + +* Debug information must go to logs, not UI. +* Separate internal data from API responses. +* Do not expose raw database column names in user-facing labels unless `DESIGN.md` explicitly defines that label. Violations are considered critical errors. --- -## Data & API Design Rules +## Data, API, and i18n Rules -* Follow `DESIGN.md` as the **single source of truth** +* Follow `DESIGN.md` as the **single source of truth**. * PostgreSQL: * use `snake_case` * define proper primary/foreign keys + * preserve existing audit columns on editable entities + * preserve `sort_order` behavior for sortable lists * avoid premature optimization + * APIs: * return only necessary fields - * do not expose internal metadata + * do not expose password hashes, verification token hashes, session token hashes, or internal metadata + * expose editor attribution with only `id` and `displayName` + * keep API response shapes consistent with `frontend/src/services/api.ts` + +* i18n: + + * use `languages` and `entity_translations` for entity translations + * use `X-Locale` for localized API reads + * keep base `name` / `title` fields as the default-language source + * do not let localized editing overwrite the base field unintentionally + * include translations only where the current API shape already supports them + +* Editing and audit: + + * create/update/delete operations on Wiki content should record editor information + * detail pages should continue to support edit metadata and edit history + * delete or update behavior must not leak internal audit payloads to normal UI --- @@ -96,11 +196,15 @@ Violations are considered critical errors. * Components: `PascalCase` * Composables: `useXxx` + * General: * variables/functions: `camelCase` -* Keep files focused and under reasonable length -* Avoid duplication + * TypeScript types/interfaces: match existing local style + +* Keep files focused and under reasonable length. +* Avoid duplication. +* Prefer existing helper APIs and local patterns over introducing new abstractions. --- @@ -110,10 +214,10 @@ This project is developed from WSL, but runtime validation is done through Docke Agent workflow: -* Run: +* Run when practical: - * lint - * typecheck + * `pnpm lint` + * `pnpm typecheck` * Do NOT run tests in WSL. * Do NOT require local test execution before finishing a task. @@ -128,12 +232,13 @@ When adding tests is clearly useful, keep them focused and minimal, but do not e A task is complete ONLY IF: -* Matches `DESIGN.md` -* Minimal diff (no unrelated changes) -* No UI leaks of internal info -* Code is readable and concise -* Passes lint/typecheck when practical -* Docker runtime issues are handled from user-provided `docker compose up --build` output +* Matches `DESIGN.md`. +* Updates `DESIGN.md` when the implemented behavior changes product, API, schema, permission, route, or i18n expectations. +* Minimal diff, with no unrelated changes. +* No UI leaks of internal info. +* Code is readable and concise. +* Passes lint/typecheck when practical. +* Docker runtime issues are handled from user-provided `docker compose up --build` output. --- @@ -143,6 +248,7 @@ A task is complete ONLY IF: * Over-engineering simple features * Creating unused files or abstractions * Mixing internal/debug data into UI +* Exposing token/hash/internal audit data through public API responses * Large, unfocused commits * Silent behavior changes outside scope @@ -150,17 +256,7 @@ A task is complete ONLY IF: ## When Unsure -* Ask for clarification -* Do not guess requirements -* Do not invent features not in `DESIGN.md` - ---- - -## Project Context - -* Goal: Pokopia Wiki -* Stack: - - * Frontend: Vue - * Backend: Node + PostgreSQL - * Infra: Docker +* Ask for clarification. +* Do not guess requirements. +* Do not invent features not in `DESIGN.md`. +* If current code and `DESIGN.md` disagree, call out the mismatch before changing behavior. diff --git a/DESIGN.md b/DESIGN.md index d698bfa..cbb22c7 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,155 +1,390 @@ # Pokopia Wiki +## 产品目标 + +- Pokopia Wiki 是一个面向 Pokopia 游戏资料的社区 Wiki。 +- 所有人都可以浏览 Wiki 内容。 +- 已注册并完成邮箱验证的用户可以创建、编辑、删除 Wiki 内容。 +- 前台以 Pokemon、栖息地、物品、材料单、每日 CheckList 为主要浏览入口。 +- 管理入口用于维护全局配置、语言、列表排序和每日 CheckList。 + ## 技术栈 -- 后端:Postgresql -- 前端:Vue -- 运维:Docker -都要用最新的框架 +- Monorepo:pnpm workspace,Node.js >= 22,TypeScript。 +- 前端:Vue、Vite、Vue Router、Vue I18n、Iconify。 +- 后端:Node.js、Fastify、pg、PostgreSQL。 +- 运维:Docker / docker compose。 +- 依赖版本遵循现有 `package.json`,新增依赖时优先使用当前主流稳定版本,并保持项目结构简单。 -# 功能描述 +## 全局设计原则 -- 一个具有社区功能的 Pokopia 游戏 Wiki +- `DESIGN.md` 是产品行为、数据结构和 API 暴露边界的单一事实来源。 +- API 只返回业务需要的字段,不返回密码、token hash、验证 token、内部调试字段或不必要的元数据。 +- 用户界面只展示业务数据和设计内的文案,不展示提示词、计划、调试信息、字段内部名或修改说明。 +- 可编辑 Wiki 内容必须记录创建者、最后编辑者、创建时间、最后编辑时间和编辑历史。 +- 列表顺序由 `sort_order` 控制,默认按创建时间旧到新初始化,排序值按 10 递增以便后续插入和拖拽排序。 -## 数据 +## 国际化 + +- 前端使用 Vue I18n 管理界面文案,并通过 `X-Locale` 请求头告知后端当前语言。 +- 前端当前语言保存在 `localStorage` 的 `pokopia_locale`。 +- 后端默认语言为 `en`。 +- 语言配置存储在 `languages`: + - `code` + - `name` + - `enabled` + - `is_default` + - `sort_order` +- 语言 code 格式为 `xx` 或 `xx-YY`,例如 `en`、`zh-CN`。 +- 系统必须且只能有一个默认语言。 +- 初始语言包含: + - `en`:English,默认语言 + - `zh-CN`:简体中文 +- 实体翻译存储在 `entity_translations`: + - `entity_type` + - `entity_id` + - `locale` + - `field_name` + - `value` +- 支持翻译的实体: + - Pokemon + - 特长 + - 喜欢的环境 + - 喜欢的东西 / 标签 + - 物品分类 + - 物品用途 + - 入手方式 + - 物品 + - 地图 + - 栖息地 + - 每日 CheckList Task +- 支持翻译的字段: + - `name` + - `title` +- 实体仍保留基础 `name` 或 `title` 字段,默认语言内容以基础字段为准。 +- API 返回展示名称时按当前语言解析,回退顺序为:请求语言翻译 -> 默认语言翻译 -> 基础字段。 +- 编辑表单必须避免本地化 UI 覆盖基础名称;翻译字段只展示当前需要编辑的语言。 + +## 用户与认证 + +- 用户可注册: + - 邮箱 + - 显示名 + - 密码 +- 邮箱保存为小写。 +- 密码只保存 hash。 +- 注册后必须通过邮箱验证。 +- 邮件发送使用 Resend: + - `RESEND_API_KEY` + - `EMAIL_FROM` + - `APP_ORIGIN` 或 `FRONTEND_ORIGIN` +- 验证邮件包含一次性验证链接。 +- 验证 token 只保存 hash,并带过期时间和使用状态。 +- 只有邮箱已验证的用户可以登录。 +- 登录成功后返回明文 session token 给前端;数据库只保存 session token hash。 +- 前端将登录 token 保存在 `localStorage` 的 `pokopia_auth_token`。 +- 用户可退出登录,退出时删除对应 session。 +- 对外用户字段只包含必要信息: + - 当前用户:`id`、`email`、`displayName`、`emailVerified` + - 编辑署名:`id`、`displayName` + +## Community 编辑与审计 + +- 已验证用户可以通过前台或管理入口编辑 Wiki 内容。 +- 新增、修改、删除 Wiki 内容时必须写入审计信息。 +- 可编辑实体包含: + - Pokemon + - 栖息地 + - 物品 + - 材料单 + - 每日 CheckList Task + - 全局配置项 +- 主要可编辑表包含: + - `created_by_user_id` + - `updated_by_user_id` + - `created_at` + - `updated_at` + - `sort_order` +- 详细编辑历史存储在 `wiki_edit_logs`: + - `entity_type` + - `entity_id` + - `action`:`create` / `update` / `delete` + - `user_id` + - `changes` + - `created_at` +- 详情页展示最后编辑者、最后编辑时间和编辑历史面板。 +- 编辑历史中的用户信息只展示必要署名,不暴露邮箱、token、hash 或内部元数据。 + +## 全局配置数据 + +以下配置项都支持创建、编辑、删除、翻译和拖拽排序。 + +### 特长 + +- 名称 +- 是否有掉落物:`has_item_drop` +- 已移除 `subcategory` 字段。 +- 当特长允许掉落物时,Pokemon 编辑中可为该 Pokemon + 特长配置一个掉落物品。 + +### 喜欢的环境 + +- 名称 + +### 喜欢的东西 / 标签 + +- 名称 +- 同时用于: + - Pokemon 喜欢的东西 + - 物品标签 + +### 物品分类 + +- 名称 +- 用于物品和材料单按结果物品分类展示。 + +### 物品用途 + +- 名称 +- 物品用途可为空。 + +### 入手方式 + +- 名称 +- 可关联到物品和材料单。 + +### 地图 + +- 名称 +- 用于栖息地中 Pokemon 出现地点。 + +## Pokemon Pokemon 可配置: + - ID -- 名字 -- 特长(可多选,最多 2 个) -- 特长掉落物品(按 Pokemon + 特长 配置,单选物品) -- 喜欢的环境(单选) -- 喜欢的东西(可多选,最多 6 个) -- 出现的栖息地(可多选) - -特长 可配置: - 名称 -- 是否有掉落物 +- 喜欢的环境:单选 +- 特长:可多选,最多 2 个 +- 特长掉落物品:按 Pokemon + 特长配置,单选物品 +- 喜欢的东西:可多选,最多 6 个 +- 出现的栖息地:由栖息地出现配置反向展示 +- 翻译 +- 排序 -喜欢的环境 可配置: -- 名称 +Pokemon 列表功能: -喜欢的东西(标签) 可配置: -- 名称 +- 搜索 +- 按喜欢的环境筛选 +- 按特长筛选: + - 满足任意条件 + - 满足全部条件 +- 按喜欢的东西筛选: + - 满足任意条件 + - 满足全部条件 +- 按自定义排序展示 + +Pokemon 详情页展示: + +- 基本信息 +- 特长 +- 特长掉落物品 +- 喜欢的环境 +- 喜欢的东西 +- 关联喜欢的东西的物品 +- 出现的栖息地 +- 最后编辑信息 +- 编辑历史 + +## 物品 + +物品可配置: -物品 可配置: - 名称 +- 分类:必填 +- 用途:可为空 +- 入手方式:可多选 +- 客制化: + - 可染色 + - 可双区染色 + - 可改花纹 +- 无材料单:`no_recipe` +- 标签:使用喜欢的东西配置,可多选 +- 翻译 +- 排序 + +物品列表功能: + +- 搜索 +- 按分类展示为标签页 +- 按用途筛选 +- 按标签筛选 +- 按自定义排序展示 + +物品详情页展示: + +- 基本信息 - 分类 - 用途 -- 入手方式(可多选) -- 客制化: - - 可染色 - - 可双区染色 - - 可改花纹 -- 标签(多选) +- 入手方式 +- 客制化 +- 标签 +- 关联材料单 +- 作为材料出现的材料单 +- 相关栖息地 +- 相关 Pokemon 掉落 +- 最后编辑信息 +- 编辑历史 + +## 材料单 + +材料单与物品是一对一关系: + +- 一个材料单必须关联一个结果物品。 +- 一个物品最多只能有一个材料单。 +- 标记为 `no_recipe` 的物品不能创建材料单。 +- 材料单没有独立名称,展示名称来自结果物品。 + +材料单可配置: + +- 结果物品 +- 入手方式:可多选 +- 需要材料:多项物品 + 数量 +- 排序 + +材料单列表功能: + +- 独立于物品列表展示 +- 按结果物品分类展示 +- 按自定义排序展示 + +材料单详情页展示: + +- 结果物品 +- 入手方式 +- 需要材料列表 +- 最后编辑信息 +- 编辑历史 + +## 栖息地 + +栖息地可配置: -材料单 可配置: - 名称 -- 入手方式(可多选) -- 需要材料(可多样,多数量) +- 配方:多项物品 + 数量 +- 可出现的 Pokemon +- 翻译 +- 排序 -物品 / 材料单分类: -- 名称 +Pokemon 出现配置: -物品 / 材料单用途: -- 名称 +- Pokemon +- 地图:可多选 +- 时间:可多选 + - 早晨 + - 中午 + - 傍晚 + - 晚上 +- 天气:可多选 + - 晴天 + - 阴天 + - 雨天 +- 稀有度:1 到 3 星 -入手方式 可配置: -- 名称 +栖息地列表功能: -地图: -- 名称 +- 按自定义排序展示 +- 展示配方摘要和可能出现的 Pokemon 摘要 -栖息地: -- 名称 -- 配方(物品,数量) -- 可出现的宝可梦(可多选) +栖息地详情页展示: -列表顺序: -- 全局配置项、Pokemon、物品、材料单、地图、栖息地均可自定义排序 -- 初始排序按创建时间旧到新 +- 配方列表 +- 可能出现的 Pokemon 列表 +- 出现时间 +- 出现天气 +- 稀有度 +- 出现的地图列表 +- 最后编辑信息 +- 编辑历史 -出现契机 -- 时间:早晨 / 中午 / 傍晚 / 晚上 -- 天气:晴天 / 阴天 / 雨天 -- 稀有度:1 ~ 3 星 -- 地图关联 +## 每日 CheckList -每日 CheckList 可配置: -- Task +每日 CheckList Task 可配置: + +- Task 标题 +- 翻译 - Task 顺序 -## 功能 +前台行为: -- Pokemon 列表 - - 搜索 - - 筛选 - - 特长(可多选,满足任意条件 / 满足全部条件) - - 喜欢的环境 - - 喜欢的东西(可多选,满足任意条件 / 满足全部条件) -- Pokemon 详情页 - - 特长 - - 特长掉落物品 - - 喜欢的环境 - - 喜欢的东西 - - 栖息地 -- 栖息地列表 -- 栖息地详情页 - - 配方列表 - - 可能出现的宝可梦列表 - - 出现时间 - - 出现天气 - - 稀有度 - - 出现的地图列表 -- 物品 / 材料单列表 - - 根据分类显示(标签页) - - 筛选 - - 用途 - - 标签 -- 物品详情页 - - 基本信息 - - 用途 - - 入手方式 - - 自定义 - - 可染色 - - 可双区染色 - - 可改花纹 - - 材料单信息 - - 入手方式 - - 需要材料列表 - - 标签 - - 相关栖息地 - - 相关 Pokemon 掉落 -- 材料单详情页 - - 基本信息 - - 入手方式 - - 需要材料列表 -- 每日 CheckList - - 展示每日做什么 - - 每个 Task 可勾选 - - 每天自动清空勾选状态,不删除 Task - - 管理中可新增 Task 到列表 - - 管理中可通过 Handle 拖曳排序 +- 展示每日要做的 Task。 +- 每个 Task 可勾选。 +- 勾选状态保存在浏览器本地。 +- 勾选状态按本地日期自动清空,不删除 Task。 +- 已删除 Task 的本地勾选状态会自动清理。 -## 用户系统 +管理行为: -- 用户可注册 - - 邮箱 - - 显示名 - - 密码 -- 用户注册后需要通过邮箱验证 - - 使用 Resend 发送验证邮件 - - 邮件内包含验证链接 -- 用户可登录 - - 仅允许已验证邮箱的用户登录 - - 登录后可获取当前用户信息 -- 用户可退出登录 -- API 只返回必要用户字段,不暴露密码、验证 token、会话 token 哈希或内部元数据 +- 已验证用户可新增、编辑、删除 Task。 +- 已验证用户可通过 Handle 拖拽排序。 -## Community 编辑 +## 前端交互与 UI -- 所有人都可浏览 Wiki 内容 -- 已注册并完成邮箱验证的用户都可编辑 Wiki 内容 -- 每次创建、修改、删除 Wiki 内容都需要记录编辑者 -- Wiki 内容展示最后编辑者和最后编辑时间 -- 编辑署名只展示必要用户信息,不暴露邮箱、token、hash 或内部元数据 +- UI 风格以 `DesignGuidelines.html` 为准。 +- 页面结构以 `AppShell`、`PageHeader`、列表、详情区和管理区为核心。 +- 导航和主要操作使用图标增强识别。 +- 数据加载状态使用 Skeleton,避免裸文本 loading。 +- 分类切换使用 Tabs。 +- 布尔或模式选择使用 SwitchGroup、checkbox、segmented control 等合适控件。 +- 多选和单选复用 `TagsSelect`,支持搜索、键盘操作和必要时的内联创建。 +- 主要实体的新建和编辑使用路由驱动的 Modal: + - `/pokemon/new` + - `/pokemon/:id/edit` + - `/habitats/new` + - `/habitats/:id/edit` + - `/items/new` + - `/items/:id/edit` + - `/recipes/new` + - `/recipes/:id/edit` +- 进入或关闭编辑 Modal 时应保留底层页面上下文,不进行不必要的滚动跳转。 +- 用户界面不得展示内部字段名、调试数据、计划说明或“已修改某字段”一类实现说明。 + +## API 概览 + +公开浏览 API: + +- `GET /api/languages` +- `GET /api/options` +- `GET /api/daily-checklist` +- `GET /api/pokemon` +- `GET /api/pokemon/:id` +- `GET /api/habitats` +- `GET /api/habitats/:id` +- `GET /api/items` +- `GET /api/items/:id` +- `GET /api/recipes` +- `GET /api/recipes/:id` + +认证 API: + +- `POST /api/auth/register` +- `POST /api/auth/verify-email` +- `POST /api/auth/login` +- `GET /api/auth/me` +- `POST /api/auth/logout` + +已验证用户编辑 API: + +- Pokemon、栖息地、物品、材料单的创建、更新、删除。 +- 每日 CheckList 的创建、更新、删除、排序。 +- 全局配置项的创建、更新、删除、排序。 +- 语言的创建、更新、删除、排序。 +- Pokemon、物品、材料单、栖息地的列表排序。 + +## 开发与验证 + +- 本项目在 WSL 中开发,运行验证主要通过 Docker。 +- 常规轻量验证: + - `pnpm lint` + - `pnpm typecheck` +- 不在 WSL 中运行测试作为完成任务的前置条件。 +- Docker 运行问题以用户提供的 `docker compose up --build` 输出为准进行后续修复。