# Patbond 开发实施文档 > 状态:Draft 1.0 > 更新日期:2026-09-03 > 适用仓库:`patbond-api`、`patbond-doc`、`patbond-flutter` ## 1. 文档目标 本文档用于把现有 Flutter 静态 Demo、本地 PostgreSQL 数据库和 Java 登录原型组织成可持续开发的产品。它定义当前基线、目标边界、接口约定、迭代顺序、质量门禁和验收标准。 文档按类型分目录管理,避免产品、接口、数据库和运维内容混杂: ```text docs/ index.md development/ # 开发计划、编码规范和协作流程 api/ # OpenAPI、接口约定和调用示例 architecture/ # 系统设计、ADR 和模块边界 database/ # 数据模型、迁移说明和 SQL testing/ # 测试策略、用例和质量报告 operations/ # 部署、配置、监控和故障处理 ``` 目录在出现对应文档时创建,不放无内容的占位文件。新增文档后必须同步更新 `mkdocs.yml` 导航。 当前尚无独立 PRD 和 OpenAPI 契约。出现冲突时,按以下顺序处理: 1. 团队已确认的产品需求和 API 契约。 2. `patbond-doc/docs/database/patbond_postgresql.sql` 中的数据约束。 3. Flutter Demo 所表达的页面流程和交互意图。 4. 当前 Java 原型代码。 Demo 中的示例文案、模拟延迟、图片地址和展示型字段不视为正式业务契约。 ## 2. 当前基线 | 仓库 | 已有能力 | 主要缺口 | | --- | --- | --- | | `patbond-flutter` | 首页、AI 创作、宠物档案、本地服务、个人中心五个 Tab;点赞、收藏、评论、宠物及疫苗编辑等本地交互 | 无登录页、网络层、鉴权状态和真实业务接口;AI 与预约为模拟流程 | | `patbond-api` | Maven 多模块;`auth`、`user`、`common`;注册、登录、用户创建/查询/密码校验共 6 个接口 | 用户仅存内存;token 不可验证;未连接 PostgreSQL;无其余业务域接口 | | `patbond-doc` | PostgreSQL 16+ 目标模型,包含 7 个 schema、36 张表、开发数据、约束和参考查询 | SQL 是一次性 bootstrap,不是 Flyway 迁移;MkDocs 首页和工程文档尚不完整 | 当前三仓没有形成真实端到端链路。现阶段应定义为:**可交互产品 Demo + 身份服务原型 + 已导入本地数据库的目标数据模型**。 ## 3. 产品范围与主流程 Patbond 面向宠物主人,围绕一个核心闭环开发: ```text 注册/登录 -> 建立宠物档案 -> 记录体重、疫苗和健康事件 -> 浏览社区或使用 AI 创作 -> 发布、点赞、收藏和评论 -> 查找附近服务并预约 -> 将完成的服务回写健康档案 ``` 目标业务域如下: | 业务域 | 主要能力 | 数据 schema | | --- | --- | --- | | 身份 | 用户、凭证、会话、地址、偏好 | `identity` | | 媒体 | 头像、宠物照片、帖子媒体、健康附件、AI 输入输出 | `media` | | 宠物健康 | 宠物、共同照护人、体重、疫苗、健康事件、提醒 | `pet_health` | | 社区 | 动态、评论、点赞、收藏、关注、话题、Feed | `community` | | AI 创作 | 模型、风格、异步任务、重试、生成结果 | `creation` | | 本地服务 | 服务商、服务项目、可预约资源、预约状态流转 | `marketplace` | | 平台能力 | 地区、通知、事务 Outbox | `platform` | ## 4. MVP 架构原则 ### 4.1 后端形态 MVP 阶段沿用当前 Maven 多模块仓库和 Spring 服务框架,但不一次性拆出七个独立微服务。 - 保留 `patbond-auth`:面向客户端的认证入口。 - 保留 `patbond-user`:身份、凭证和用户资料的唯一数据所有者。 - 保留 `patbond-common`:仅放稳定的跨模块契约和基础类型,不承载业务逻辑,也不应让所有服务被动引入 RabbitMQ、Feign 等依赖。 - 按迭代增加宠物健康、社区、AI 创作和本地服务模块;模块边界与数据库 schema 对齐。 - MVP 可共享一个 PostgreSQL 实例,但每个业务模块只直接读写自己拥有的 schema。 - 跨域写入通过应用服务完成;异步通知使用事务 Outbox。不要依靠客户端同时调用多个服务维持一致性。 如果未来采用“每服务独立数据库”,应先移除跨 schema 外键并设计事件一致性,不能直接把当前 SQL 按 schema 拆库。 ### 4.2 客户端形态 Flutter 保留现有页面作为交互参考,逐页替换本地数据: ```text Page/Widget -> Feature Controller -> Repository -> API Client -> Local Cache ``` - `AppState` 不再直接承担所有业务状态和持久化职责。 - 按 `auth`、`pets`、`community`、`creation`、`marketplace` 拆分 feature 状态。 - access token 仅保存在安全存储中;不得写入普通 `SharedPreferences`。 - `SharedPreferences` 仅保留主题、引导状态等非敏感轻量配置。 - 服务端数据是事实来源;本地缓存需要定义失效、刷新和冲突策略。 ### 4.3 数据库演进 现有 `patbond_postgresql.sql` 作为已评审目标模型和本地开发基线,不再直接修改为日常发布脚本。 - 把结构、开发种子数据和校验脚本拆开。 - 后端接入 Flyway,每次结构变更新增版本化迁移,不修改已发布迁移。 - 已导入的本地库应先备份;接入 Flyway 时优先重建开发库,或在核对 schema checksum 后建立 baseline,禁止直接重复执行 bootstrap。 - 正式环境不得导入开发账号、示例帖子或演示预约。 - ID 统一使用 UUID;应用层优先生成 UUIDv7,数据库的 `gen_random_uuid()` 作为兜底。 - 所有时间以 `timestamptz` 保存并通过 ISO 8601 传输;客户端按本地时区显示。 - 金额使用整数分;距离、年龄、疫苗进度和相对时间均由事实字段计算,不持久化展示字符串。 ## 5. 本地开发基线 ### 5.1 环境要求 - JDK 17。不要使用更高版本 JDK 代替团队基线进行发布构建。 - Maven 3.9+;M0 完成后改用仓库内 Maven Wrapper。 - PostgreSQL 16+,现有本地库作为开发数据源。 - Nacos,供当前 `patbond-auth` 发现 `patbond-user`。 - Flutter/Dart 版本需满足 `patbond-flutter/pubspec.yaml`,M0 完成后通过版本管理工具锁定。 不要在仓库中提交数据库密码、token、对象存储密钥或第三方服务密钥。 ### 5.2 当前原型启动 后端配置目前只有 `.sample` 文件。首次启动时应在本机复制为被 Git 忽略的 `application.yml`,并确认 Nacos 地址: ```bash cp patbond-user/src/main/resources/application.yml.sample \ patbond-user/src/main/resources/application.yml cp patbond-auth/src/main/resources/application.yml.sample \ patbond-auth/src/main/resources/application.yml mvn -pl patbond-common -am install mvn -f patbond-user/pom.xml spring-boot:run mvn -f patbond-auth/pom.xml spring-boot:run ``` 两个服务需分别在终端中运行。默认端口是 `8082`(user)和 `8081`(auth)。当前版本不读取 PostgreSQL;只有 M1 的数据源和 Repository 完成后,本地数据库才会进入运行链路。 Flutter 启动: ```bash flutter pub get flutter run ``` ### 5.3 数据库接入目标 M1 应通过环境变量注入以下配置,变量名在实现时统一: ```text PATBOND_DB_URL=jdbc:postgresql://127.0.0.1:5432/patbond PATBOND_DB_USERNAME= PATBOND_DB_PASSWORD= NACOS_SERVER_ADDR=127.0.0.1:8848 ``` 连接前至少验证 `identity`、`media`、`pet_health`、`community`、`creation`、`marketplace`、`platform` 七个 schema 均存在。应用账号应使用最小权限,不使用 PostgreSQL 超级用户运行服务。 ## 6. API 契约规范 正式开发前先建立 OpenAPI 文档。建议统一使用 `/api/v1` 前缀,内部服务接口使用独立的 `/internal` 前缀且必须具备服务间认证。 ### 6.1 通用规则 - JSON 字段统一使用 `camelCase`。 - 资源 ID 对外表示为 UUID 字符串。 - 成功响应可沿用 `{ "code": 0, "message": "success", "data": ... }`。 - 错误必须同时返回正确 HTTP 状态码和稳定业务错误码,禁止只返回异常文本。 - 列表采用 cursor 分页;动态 Feed 禁止深度 `OFFSET`。 - 创建帖子、生成任务和预约等写接口必须支持 `Idempotency-Key`。 - 更新宠物、帖子、预约等聚合时使用 `version` 做乐观锁。 - 日志不得记录密码、token、手机号全文或上传签名。 ### 6.2 第一批接口 | 域 | 建议接口 | 用途 | | --- | --- | --- | | Auth | `POST /api/v1/auth/register` | 注册并创建会话 | | Auth | `POST /api/v1/auth/login` | 登录 | | Auth | `POST /api/v1/auth/refresh` | 轮换 refresh token | | Auth | `POST /api/v1/auth/logout` | 撤销当前会话 | | User | `GET /api/v1/me` | 当前用户资料 | | User | `PATCH /api/v1/me` | 修改资料与偏好 | | Media | `POST /api/v1/media/uploads` | 获取上传凭据/创建媒体记录 | | Pets | `GET/POST /api/v1/pets` | 查询、新建宠物 | | Pets | `GET/PATCH /api/v1/pets/{petId}` | 宠物详情与更新 | | Pets | `GET/POST /api/v1/pets/{petId}/weights` | 体重记录 | | Pets | `GET/POST/PATCH /api/v1/pets/{petId}/vaccinations` | 疫苗记录 | | Pets | `GET/POST /api/v1/pets/{petId}/health-events` | 健康时间线 | 后续接口按社区、AI 创作、本地服务的迭代顺序补充,先写 OpenAPI 和契约测试,再实现客户端调用。 ## 7. 分阶段开发计划 ### M0:工程基线与契约冻结 目标:让所有开发者能用一致方式启动、测试和联调。 - 确认 Java 17、Flutter SDK、PostgreSQL 16 的固定版本。 - 增加 Maven Wrapper 和 Flutter 版本固定方案。 - 提供可提交的 `application.yml` 默认配置,敏感值全部由环境变量注入。 - 增加本地基础设施编排:PostgreSQL、Nacos;RabbitMQ 在异步任务阶段启用。 - 将 bootstrap SQL 转为 Flyway baseline,并分离开发种子数据。 - 确定 UUID、时间、金额、错误响应、分页和幂等规范。 - 建立 OpenAPI、CI 和基本代码检查。 验收标准:新机器仅依据仓库文档即可启动后端、连接本地数据库并运行自动化检查。 ### M1:身份与媒体纵向闭环 目标:用户能够在 Flutter 完成真实注册、登录和会话恢复。 - API 将内存用户迁移到 `identity.users`、`identity.user_credentials`。 - 将 `Long` 用户 ID 改为 UUID。 - 实现可验证的 access token、refresh token 轮换、退出和会话撤销。 - 保护 `/internal/**`,增加登录失败限制和安全日志。 - 实现媒体元数据与对象存储上传流程。 - Flutter 增加登录/注册、API Client、Repository、鉴权拦截和安全存储。 验收标准:注册后重启服务数据不丢失;token 过期可刷新;退出后 refresh token 不可再次使用;客户端可恢复登录态。 ### M2:宠物健康 目标:替换 Flutter 档案页的本地宠物和疫苗数据。 - 实现宠物、照护权限、体重、疫苗、健康事件和提醒接口。 - 校验当前用户对宠物的 owner/caregiver/viewer 权限。 - Flutter 接入真实列表、详情、编辑、加载、空态和错误态。 - 体重、疫苗进度、下次接种和月度花费从事实表聚合生成。 验收标准:数据可跨设备读取;无权限用户不能访问宠物;并发更新返回明确冲突;关键流程具备 API 集成测试和 Flutter 组件测试。 ### M3:社区 目标:完成真实动态发布和互动闭环。 - 实现 Feed、帖子详情、草稿/发布、媒体、评论、点赞、收藏、关注和话题。 - Feed 使用游标分页;点赞、收藏使用幂等写入。 - Flutter 替换本地帖子,并实现刷新、分页、失败重试和乐观更新回滚。 验收标准:发布后可在另一客户端看到;重复点赞不重复计数;分页不丢失、不重复;删除或隐藏内容不可继续出现在公共 Feed。 ### M4:AI 创作 目标:替换上传和生成延时模拟。 - 实现模型/风格目录、生成任务创建、查询和取消。 - Worker 通过队列消费任务,使用租约、重试和幂等键防止重复生成。 - 输出写入媒体表,成功后可一键创建社区草稿。 - Flutter 展示排队、生成进度、失败重试和取消状态。 验收标准:任务状态流转合法;Worker 重启不丢任务;相同幂等请求不重复扣费或生成;失败原因可追踪。 ### M5:本地服务与预约 目标:完成附近搜索、服务选择和真实预约。 - 实现地区、服务商、服务项目、资源和预约接口。 - 附近搜索先用经纬度边界框,再计算精确距离。 - 实现预约 hold、确认、服务中、完成、取消和过期状态机。 - 后台任务释放过期 hold;数据库排斥约束防止资源时段重叠。 - Flutter 增加时间、宠物、服务项、地址选择及订单列表。 验收标准:并发预约同一资源时段最多一个成功;非法状态迁移被拒绝;过期占位自动释放;完成服务可关联健康事件。 ### M6:交付加固 - 通知、事务 Outbox 发布器和失败重试。 - 限流、审计、结构化日志、指标、Trace 和告警。 - 容器镜像、环境配置、数据库备份恢复和回滚方案。 - Flutter 包名、签名、图标、启动页、隐私声明和商店配置。 - 完成安全、性能、可访问性、弱网和多尺寸测试。 ## 8. 第一迭代建议任务 第一迭代只做“真实登录纵切”,避免同时铺开全部业务域: 1. 从 bootstrap SQL 提取 identity/media 的 Flyway baseline。 2. 为 `patbond-user` 增加 PostgreSQL Repository,实现 UUID 用户持久化。 3. 实现统一异常响应及用户名、手机号的数据库一致校验。 4. 将随机 token 替换为可校验 access token,并实现 refresh session。 5. 增加注册、登录、刷新、退出和鉴权集成测试。 6. 建立 OpenAPI,并据此生成或手写 Flutter API Client。 7. Flutter 增加登录页、安全 token 存储和登录态恢复。 8. 建立一条端到端用例:注册 → 登录 → 获取当前用户 → 退出。 第一迭代暂不开发 AI Worker、社区 Feed 或预约,先验证数据库、认证、客户端和测试链路能够贯通。 ## 9. 测试与质量门禁 ### 后端 - 单元测试:校验、状态转换、权限和领域规则。 - 集成测试:使用真实 PostgreSQL/Testcontainers 验证 Repository、迁移、事务和约束。 - 契约测试:验证 OpenAPI 与实际响应一致。 - 安全测试:密码不泄露、token 撤销有效、越权访问失败、内部接口受保护。 - 每个业务模块至少覆盖成功、参数错误、资源不存在、无权限、并发冲突和幂等重试。 ### Flutter - 单元测试:DTO 映射、Repository、缓存和状态转换。 - Widget 测试:登录、宠物编辑、动态互动、生成状态、预约状态。 - Golden/响应式测试:手机、平板和桌面宽度,以及 200% 文字缩放。 - Integration/E2E:注册登录、宠物档案、发帖和预约主路径。 - 所有网络页面必须覆盖 loading、empty、error、retry 和离线状态。 ### CI 最低门禁 ```bash # Java mvn clean test # Flutter dart format --output=none --set-exit-if-changed lib test flutter analyze flutter test # 文档 mkdocs build --strict ``` 数据库迁移还需在全新 PostgreSQL 16 实例执行一次,并对升级路径执行一次。 ### 可观测性与产品验证 - 技术指标至少包含请求量、错误率、P95 延迟、数据库连接池、队列积压和 Worker 失败率。 - 首批产品漏斗事件建议覆盖注册完成、登录成功、宠物创建、动态发布、AI 任务成功和预约确认。 - 埋点携带事件版本、用户/会话标识和服务端时间,但不得包含密码、token 或非必要个人信息。 - A/B 实验必须使用稳定分流和独立曝光事件;在基础埋点、指标口径和样本量规则完成前不启动产品实验。 ## 10. 完成定义(Definition of Done) 一个功能只有同时满足以下条件才算完成: - 需求和异常路径已明确。 - OpenAPI、数据库迁移和代码实现保持一致。 - 不依赖 Demo 常量或只在当前进程存在的数据。 - 权限、输入校验、幂等性和并发行为已处理。 - API 单元/集成测试及对应 Flutter 测试通过。 - 页面具有加载、空、错误和重试状态。 - 日志和指标能定位失败原因,且不泄露敏感数据。 - 文档已更新,代码通过 CI,可在干净环境复现。 ## 11. 当前已知风险 1. API 使用 `Long`,数据库使用 UUID;必须在新增业务前统一。 2. 当前 token 是随机字符串,无法验证、刷新或撤销。 3. `/internal/users/**` 尚无服务间访问控制。 4. Flutter 没有网络层,模型中仍有相对时间、距离等展示字符串。 5. `application.yml` 只有 sample,干净检出无法按 README 直接启动服务。 6. API 没有自动化测试;Flutter 仅有一个导航冒烟测试。 7. PostgreSQL bootstrap 含开发数据,不可直接作为生产迁移。 8. Spring Boot 2.7/Spring Cloud 2021 已进入旧技术代际,需要决定先交付 MVP 还是先升级 Boot 3。 9. 数据库使用大量跨 schema 外键,与严格的独立数据库微服务模式存在冲突。 10. AI 提供方、对象存储、天气/地图供应商和通知渠道尚未确定。 ## 12. 开工前待确认事项 - 第一版是否以“注册登录 + 宠物档案”为 MVP,还是必须包含社区发布。 - 后端继续多服务部署,还是先采用模块化单体以降低早期运维成本。 - access/refresh token 有效期及多设备登录策略。 - 对象存储、AI 模型、天气和地图服务供应商。 - 是否支持手机号登录、短信验证码和第三方登录。 - 预约首版是否包含支付、退款和服务商后台;当前数据库只覆盖预约,不包含支付域。 - 首发平台是 Android/iOS,还是同时支持 Web/桌面。 上述事项未确认前,可以完成 M0 和身份持久化,但不应并行扩展所有业务模块。