Update schema and API to support expanded Pokemon profile fields Add UI for editing and displaying types, base stats, and dimensions Support translations for details and genus fields
11 KiB
11 KiB
Pokopia Wiki
产品目标
- Pokopia Wiki 是一个面向 Pokopia 游戏资料的社区 Wiki。
- 所有人都可以浏览 Wiki 内容。
- 已注册并完成邮箱验证的用户可以创建、编辑、删除 Wiki 内容。
- 前台以 Pokemon、栖息地、物品、材料单、每日 CheckList 为主要浏览入口。
- 管理入口用于维护全局配置、语言、列表排序和每日 CheckList。
技术栈
- Monorepo:pnpm workspace,Node.js >= 22,TypeScript。
- 前端:Vue、Vite、Vue Router、Vue I18n、Iconify。
- 后端:Node.js、Fastify、pg、PostgreSQL。
- 运维:Docker / docker compose。
- 依赖版本遵循现有
package.json,新增依赖时优先使用当前主流稳定版本,并保持项目结构简单。
全局设计原则
DESIGN.md是产品行为、数据结构和 API 暴露边界的单一事实来源。- API 只返回业务需要的字段,不返回密码、token hash、验证 token、内部调试字段或不必要的元数据。
- 用户界面只展示业务数据和设计内的文案,不展示提示词、计划、调试信息、字段内部名或修改说明。
- 可编辑 Wiki 内容必须记录创建者、最后编辑者、创建时间、最后编辑时间和编辑历史。
- 列表顺序由
sort_order控制,默认按创建时间旧到新初始化,排序值按 10 递增以便后续插入和拖拽排序。
国际化
- 前端使用 Vue I18n 管理界面文案,并通过
X-Locale请求头告知后端当前语言。 - 前端当前语言保存在
localStorage的pokopia_locale。 - 后端默认语言为
en。 - 语言配置存储在
languages:codenameenabledis_defaultsort_order
- 语言 code 格式为
xx或xx-YY,例如en、zh-CN。 - 系统必须且只能有一个默认语言。
- 初始语言包含:
en:English,默认语言zh-CN:简体中文
- 实体翻译存储在
entity_translations:entity_typeentity_idlocalefield_namevalue
- 支持翻译的实体:
- Pokemon
- 特长
- Pokemon Types
- 喜欢的环境
- 喜欢的东西 / 标签
- 物品分类
- 物品用途
- 入手方式
- 物品
- 地图
- 栖息地
- 每日 CheckList Task
- 支持翻译的字段:
nametitledetails:仅 Pokemon 介绍使用genus:仅 Pokemon Genus 使用
- 实体仍保留基础
name、title、details或genus字段,默认语言内容以基础字段为准。 - API 返回展示名称时按当前语言解析,回退顺序为:请求语言翻译 -> 默认语言翻译 -> 基础字段。
- 编辑表单必须避免本地化 UI 覆盖基础名称;翻译字段只展示当前需要编辑的语言。
用户与认证
- 用户可注册:
- 邮箱
- 显示名
- 密码
- 邮箱保存为小写。
- 密码只保存 hash。
- 注册后必须通过邮箱验证。
- 邮件发送使用 Resend:
RESEND_API_KEYEMAIL_FROMAPP_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_idupdated_by_user_idcreated_atupdated_atsort_order
- 详细编辑历史存储在
wiki_edit_logs:entity_typeentity_idaction:create/update/deleteuser_idchangescreated_at
- 详情页展示最后编辑者、最后编辑时间和编辑历史面板。
- 编辑历史中的用户信息只展示必要署名,不暴露邮箱、token、hash 或内部元数据。
全局配置数据
以下配置项都支持创建、编辑、删除、翻译和拖拽排序。
特长
- 名称
- 是否有掉落物:
has_item_drop - 已移除
subcategory字段。 - 当特长允许掉落物时,Pokemon 编辑中可为该 Pokemon + 特长配置一个掉落物品。
Pokemon Types
- 名称
- 用于 Pokemon 属性配置。
- Pokemon 可选择 1 到 2 个 Type,用于表达双属性。
喜欢的环境
- 名称
喜欢的东西 / 标签
- 名称
- 同时用于:
- Pokemon 喜欢的东西
- 物品标签
物品分类
- 名称
- 用于物品和材料单按结果物品分类展示。
物品用途
- 名称
- 物品用途可为空。
入手方式
- 名称
- 可关联到物品和材料单。
地图
- 名称
- 用于栖息地中 Pokemon 出现地点。
Pokemon
Pokemon 可配置:
- ID
- 名称
- Genus:可为空,支持翻译
- 介绍 / Details:可为空,支持翻译
- Height:默认输入
ft/in,可切换输入m;详情页同时展示ft/in与m - Weight:默认输入磅
lb,可切换输入kg;详情页同时展示lbs与kg - Height / Weight 换算结果四舍五入;
m/kg保留 2 位小数,in取整数,lb保留 1 位小数。 - Types:可多选,最多 2 个
- 喜欢的环境:单选
- 特长:可多选,最多 2 个
- 特长掉落物品:按 Pokemon + 特长配置,单选物品
- 喜欢的东西:可多选,最多 6 个
- 六维:
- HP
- Attack
- Defense
- Special Attack
- Special Defense
- Speed
- 出现的栖息地:由栖息地出现配置反向展示
- 翻译
- 排序
Pokemon 列表功能:
- 搜索
- 按喜欢的环境筛选
- 按特长筛选:
- 满足任意条件
- 满足全部条件
- 按喜欢的东西筛选:
- 满足任意条件
- 满足全部条件
- 按自定义排序展示
Pokemon 详情页展示:
- 基本信息
- 主内容顶部按以下布局展示:
- 左上:Genus & Details;无区块标题;如有 Genus,先展示 Genus,再以分割线连接 Details 内容
- 左下:Height / Weight 与 Types 按 2:1 比例并排;Height / Weight 无区块标题,在 Dimension 区内左右并排展示并以中间分割线隔开,每组按英制、分割线、公制、标签上下排列;Types 不显示 Type 1 / Type 2 文案,上下布局并居中展示
- 右侧:六维 Stats
- 六维使用 ProgressBar 展示,最大值按 150 计算。
- 特长
- 特长掉落物品
- 喜欢的环境
- 喜欢的东西
- 关联喜欢的东西的物品
- 出现的栖息地
- 最后编辑信息
- 编辑历史:保留在右侧 Sidebar 展示
物品
物品可配置:
- 名称
- 分类:必填
- 用途:可为空
- 入手方式:可多选
- 客制化:
- 可染色
- 可双区染色
- 可改花纹
- 无材料单:
no_recipe - 标签:使用喜欢的东西配置,可多选
- 翻译
- 排序
物品列表功能:
- 搜索
- 按分类展示为标签页
- 按用途筛选
- 按标签筛选
- 按自定义排序展示
物品详情页展示:
- 基本信息
- 分类
- 用途
- 入手方式
- 客制化
- 标签
- 关联材料单
- 作为材料出现的材料单
- 相关栖息地
- 相关 Pokemon 掉落
- 最后编辑信息
- 编辑历史
材料单
材料单与物品是一对一关系:
- 一个材料单必须关联一个结果物品。
- 一个物品最多只能有一个材料单。
- 标记为
no_recipe的物品不能创建材料单。 - 材料单没有独立名称,展示名称来自结果物品。
材料单可配置:
- 结果物品
- 入手方式:可多选
- 需要材料:多项物品 + 数量
- 排序
材料单列表功能:
- 独立于物品列表展示
- 按结果物品分类展示
- 按自定义排序展示
材料单详情页展示:
- 结果物品
- 入手方式
- 需要材料列表
- 最后编辑信息
- 编辑历史
栖息地
栖息地可配置:
- 名称
- 配方:多项物品 + 数量
- 可出现的 Pokemon
- 翻译
- 排序
Pokemon 出现配置:
- Pokemon
- 地图:可多选
- 时间:可多选
- 早晨
- 中午
- 傍晚
- 晚上
- 天气:可多选
- 晴天
- 阴天
- 雨天
- 稀有度:1 到 3 星
栖息地列表功能:
- 按自定义排序展示
- 展示配方摘要和可能出现的 Pokemon 摘要
栖息地详情页展示:
- 配方列表
- 可能出现的 Pokemon 列表
- 出现时间
- 出现天气
- 稀有度
- 出现的地图列表
- 最后编辑信息
- 编辑历史
每日 CheckList
每日 CheckList Task 可配置:
- Task 标题
- 翻译
- Task 顺序
前台行为:
- 展示每日要做的 Task。
- 每个 Task 可勾选。
- 勾选状态保存在浏览器本地。
- 勾选状态按本地日期自动清空,不删除 Task。
- 已删除 Task 的本地勾选状态会自动清理。
管理行为:
- 已验证用户可新增、编辑、删除 Task。
- 已验证用户可通过 Handle 拖拽排序。
前端交互与 UI
- 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/languagesGET /api/optionsGET /api/daily-checklistGET /api/pokemonGET /api/pokemon/:idGET /api/habitatsGET /api/habitats/:idGET /api/itemsGET /api/items/:idGET /api/recipesGET /api/recipes/:id
认证 API:
POST /api/auth/registerPOST /api/auth/verify-emailPOST /api/auth/loginGET /api/auth/mePOST /api/auth/logout
已验证用户编辑 API:
- Pokemon、栖息地、物品、材料单的创建、更新、删除。
- 每日 CheckList 的创建、更新、删除、排序。
- 全局配置项的创建、更新、删除、排序。
- 语言的创建、更新、删除、排序。
- Pokemon、物品、材料单、栖息地的列表排序。
开发与验证
- 本项目在 WSL 中开发,运行验证主要通过 Docker。
- 常规轻量验证:
pnpm lintpnpm typecheck
- 不在 WSL 中运行测试作为完成任务的前置条件。
- Docker 运行问题以用户提供的
docker compose up --build输出为准进行后续修复。