ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Claude Code从零搭建宠物生命周期管理App:Vue3+Spring Cloud Alibaba实战

Claude Code从零搭建宠物生命周期管理App:Vue3+Spring Cloud Alibaba实战

1. 为什么选这个组合来搭宠物生命周期管理App

宠物生命周期管理这个赛道,表面上看是个"记录工具",但真正做过的人都知道,它本质上是一个跨时间维度的状态机系统。一只宠物从领养、疫苗、驱虫、绝育、体检、配种、怀孕、生产、幼崽管理,到老年护理、慢性病跟踪、临终关怀,每个阶段的数据结构、业务规则、提醒策略都不一样。你如果一开始按"宠物档案+提醒"这种扁平模型去设计,做到第三个迭代就会发现表结构根本撑不住。

我这次用 Claude Code 从零搭一个完整项目,技术栈定的是Vue 3 + Spring Cloud Alibaba,原因很直接:前端要处理大量表单、时间轴、图表,Vue 3 的组合式 API 配合 Pinia 管理跨页面状态比 Options API 清爽太多;后端用 Spring Cloud Alibaba 是因为这个业务天然适合拆成"用户中心、宠物档案、健康记录、提醒调度、内容社区"几个微服务,Nacos 做注册配置、Sentinel 做限流、Seata 处理跨服务的领养转移事务,这套组合在国内中小团队里落地成本最低。

Claude Code 在这个项目里的角色不是"帮你写几行代码",而是从项目脚手架、目录结构、接口契约、到具体业务实现的全流程参与者。我实测下来,它最擅长的三件事:一是根据自然语言描述生成符合规范的项目骨架,二是理解已有代码上下文后做增量修改,三是帮你把模糊需求翻译成可执行的技术方案。但它也有明显的短板,后面会细说。

这篇文章适合两类人看:一类是想用 AI 工具从零起一个中大型项目的开发者,另一类是正在做宠物、健康管理、生命周期类产品的同行。我会把整个搭建过程拆开讲,包括每个技术选型背后的理由、Claude Code 的实际使用技巧、踩过的坑,以及可以直接抄的配置和代码结构。

2. 项目整体架构设计与技术选型拆解

2.1 业务域拆分:为什么是这五个微服务

宠物生命周期管理的业务边界其实比想象中复杂。我一开始想做成单体,但梳理完需求后发现几个硬约束:提醒调度需要独立的时间轮和消息队列,健康记录写入频率远高于其他模块,内容社区有独立的审核和推荐逻辑。所以最终拆成五个服务:

服务名核心职责关键技术点
pet-user用户、家庭组、权限JWT + RBAC,家庭组共享宠物
pet-profile宠物档案、生命周期阶段状态机驱动阶段流转
pet-health疫苗、驱虫、体检、病历时序数据存储,附件管理
pet-reminder提醒规则、调度、推送时间轮 + RocketMQ 延迟消息
pet-community动态、问答、经验分享内容审核、Feed 流

这里有个设计决策值得说:宠物档案和健康记录为什么不分在一个服务里。因为档案是低频写、高频读,健康记录是高频写、按时间范围读,两者的存储优化方向完全相反。档案可以用 MySQL 加 Redis 缓存,健康记录我最终选了 MySQL 分表 + 按 petId 哈希,单表超过 500 万行就自动建下一张。

2.2 前端架构:Vue 3 的目录组织逻辑

前端我没有用现成的 admin 模板,而是让 Claude Code 按业务域生成目录。核心思路是按功能模块划分,而不是按文件类型划分。很多人习惯把所有的 views 放一起、所有的 api 放一起,项目一大就找不到东西。我用的结构是这样的:

src/ modules/ pet-profile/ views/ components/ api/ stores/ types/ pet-health/ pet-reminder/ shared/ components/ composables/ utils/ router/ App.vue

每个 module 内部自闭环,跨模块复用的东西才放到 shared。这个结构的好处是,当你要把某个模块抽成独立子应用时,直接整个目录搬走就行。

2.3 Claude Code 在架构阶段的实际用法

我在架构设计阶段用 Claude Code 的方式是:先让它生成方案,我再做减法。具体操作是打开终端,进入空项目目录,直接给它一段结构化描述:

claude

然后在交互里输入类似这样的提示词:

我要搭建一个宠物生命周期管理App,前端Vue3+Vite+Pinia+TypeScript, 后端Spring Cloud Alibaba(Nacos+Sentinel+Seata+RocketMQ)。 请先不要写代码,给我一份完整的项目目录结构方案, 前端按业务模块划分,后端按微服务划分, 每个服务给出包结构和核心依赖。

它给出的方案大概有 80% 可以直接用,剩下 20% 需要根据我的实际经验调整。比如它默认把 DTO 和 VO 混在一起,我要求分开;它默认用 MyBatis-Plus 的自动填充,我改成手动控制审计字段,因为跨服务场景下自动填充会出问题。

提示:Claude Code 在架构阶段最大的价值不是给你一个完美方案,而是帮你快速穷举可能性。你要做的是判断和裁剪,而不是照单全收。

3. 环境准备与 Claude Code 配置实操

3.1 安装与基础配置

Claude Code 的安装本身不复杂,但国内网络环境下有几个点要注意。我用的是 npm 全局安装方式:

npm install -g @anthropic-ai/claude-code

安装完成后,在项目根目录执行claude就会进入交互模式。第一次使用需要完成账号登录,按终端提示操作即可。这里有个实际经验:如果你在多个项目间切换,建议每个项目单独初始化,因为 Claude Code 会读取当前目录的上下文,包括.claude配置文件和CLAUDE.md项目说明文件。

我在项目根目录建了一个CLAUDE.md,内容是这样的:

# 项目说明 这是一个宠物生命周期管理App,前端Vue3,后端Spring Cloud Alibaba。 ## 代码规范 - 前端使用 Composition API + <script setup> - 后端使用 Java 17,遵循阿里巴巴Java开发手册 - 所有接口返回统一 Result<T> 包装 - 数据库字段使用下划线命名,Java 属性使用驼峰 ## 目录约定 - 前端业务代码在 src/modules 下 - 后端每个微服务独立 Maven 模块 - 公共依赖放在 pet-common ## 禁止事项 - 不要生成 System.out.println - 不要使用已废弃的 API - 不要省略异常处理

这个文件的作用是给 Claude Code 一个持久的项目上下文,避免每次对话都要重复说明规范。实测下来,有了这个文件之后,它生成的代码风格一致性提升非常明显。

3.2 后端项目初始化

后端我用 Maven 多模块结构。让 Claude Code 生成父 POM 和子模块骨架:

请生成一个Maven多模块项目的骨架,父模块pet-parent, 子模块包括 pet-common、pet-gateway、pet-user、pet-profile、 pet-health、pet-reminder、pet-community。 Spring Boot 3.2,Spring Cloud 2023.0,Spring Cloud Alibaba 2023.0.1.0。 父POM统一管理依赖版本。

它生成的父 POM 里,dependencyManagement部分基本正确,但有几个版本号需要手动核对。我踩过的坑是:Spring Cloud Alibaba 的版本必须和 Spring Boot、Spring Cloud 严格对应,版本错配会导致 Nacos 注册失败但没有任何报错,排查起来很痛苦。正确的对应关系是:

Spring BootSpring CloudSpring Cloud Alibaba
3.2.x2023.0.x2023.0.1.0
3.1.x2022.0.x2022.0.0.0
2.7.x2021.0.x2021.0.5.0

3.3 前端项目初始化

前端用 Vite 创建:

npm create vite@latest pet-frontend -- --template vue-ts

然后让 Claude Code 补充依赖和目录结构。我给的提示词是:

基于当前Vite+Vue3+TS项目,补充以下依赖: pinia、vue-router、axios、element-plus、dayjs、echarts。 然后按 modules 结构创建 pet-profile、pet-health、pet-reminder 三个模块目录, 每个模块包含 views、components、api、stores、types 子目录。

这里有个细节:Claude Code 生成的vite.config.ts默认没有配置路径别名和代理,我手动补上了:

import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve(__dirname, 'src'), '@modules': resolve(__dirname, 'src/modules') } }, server: { proxy: { '/api': { target: 'http://localhost:8080', changeOrigin: true } } } })

注意:路径别名配置后,还需要在tsconfig.json的compilerOptions.paths里同步声明,否则 TypeScript 会报找不到模块。这个坑我见过太多人中招。

4. 核心业务模块的实现细节

4.1 宠物生命周期状态机设计

这是整个项目最核心的部分。宠物的生命周期不是一个简单的枚举字段,而是一个带条件流转的状态机。我用的是 Spring StateMachine,但后来发现对这个场景来说太重了,改成了自己实现的轻量状态机。

状态定义:

public enum PetLifeStage { NEWBORN, // 新生(0-2月) JUVENILE, // 幼年(2-12月) ADULT, // 成年(1-7岁) SENIOR, // 老年(7岁以上) GESTATING, // 妊娠中 NURSING, // 哺乳期 DECEASED // 已离世 }

流转规则不是按时间自动流转,而是按事件触发 + 条件判断。比如从 JUVENILE 到 ADULT,需要满足"年龄满12个月"且"已完成基础疫苗"。从 ADULT 到 GESTATING,需要"性别为母"且"有配种记录"。

我用 Claude Code 生成状态机的核心逻辑时,给的提示词是:

实现一个宠物生命周期状态机,状态枚举为 PetLifeStage。 每个状态流转需要满足前置条件,条件用 Predicate 定义。 流转时记录流转日志,包含 fromStage、toStage、triggerEvent、timestamp。 请给出核心类设计和关键代码。

它生成的代码结构是PetStateMachine+TransitionRule+TransitionCondition,我在此基础上加了流转日志的异步落库,避免阻塞主流程。

4.2 提醒调度服务的时间轮实现

提醒服务是技术含量最高的模块。宠物疫苗、驱虫、体检这些提醒,特点是数量大、时间分散、精度要求不高(分钟级)。用 Quartz 太重,用 RocketMQ 延迟消息有精度限制(默认支持 18 个延迟级别,最长 2 小时)。

我最终用的是时间轮 + RocketMQ 兜底的方案:近期(24小时内)的提醒放时间轮,精确到分钟;远期提醒落库,由定时任务每天扫描一次,把第二天到期的提醒投递到时间轮。

时间轮的核心代码:

public class TimingWheel { private final int tickDuration; // 每格时长(秒) private final int wheelSize; // 轮子格数 private final Bucket[] buckets; private final AtomicLong currentTime; public void addTask(long delaySeconds, Runnable task) { long targetTick = (currentTime.get() + delaySeconds) / tickDuration; int bucketIndex = (int) (targetTick % wheelSize); buckets[bucketIndex].addTask(task, targetTick); } }

这里有个参数计算过程:假设 tickDuration = 60 秒,wheelSize = 1440,那么一轮覆盖 24 小时。超过 24 小时的提醒需要多级时间轮或者落库处理。我选了落库方案,因为实现简单且可靠。

实操心得:时间轮的 tickDuration 不要设太小,否则空转消耗 CPU;也不要设太大,否则精度不够。宠物提醒场景下 60 秒是甜点值。

4.3 健康记录的时序数据存储

健康记录包括体重、体温、疫苗、驱虫、体检报告等。这些数据的共同特点是按时间序列查询,比如"查最近半年的体重变化曲线"。

我用的方案是 MySQL 单表 + 按 petId 哈希分表,配合覆盖索引。表结构:

CREATE TABLE pet_health_record ( id BIGINT PRIMARY KEY, pet_id BIGINT NOT NULL, record_type VARCHAR(32) NOT NULL, record_time DATETIME NOT NULL, value_json JSON, attachments JSON, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, INDEX idx_pet_time (pet_id, record_time DESC), INDEX idx_pet_type_time (pet_id, record_type, record_time DESC) );

value_json存具体数值,因为不同记录类型的字段差异很大,用 JSON 比建宽表灵活。查询体重曲线时,直接按pet_id + record_type + record_time走索引,性能很好。

Claude Code 在这个模块帮我做了一件很有价值的事:根据查询场景反推索引设计。我把几个典型查询语句给它,它分析出需要哪些复合索引,比我凭经验拍脑袋更系统。

4.4 前端时间轴组件的实现

宠物生命周期在前端最直观的呈现是一条时间轴。我用的是自己封装的PetTimeline组件,基于 Vue 3 的computed做数据转换,把健康记录、提醒、阶段变更合并成统一的时间线数据。

核心逻辑:

const timelineData = computed(() => { const records = healthStore.records.map(r => ({ type: 'health', time: r.recordTime, title: r.recordTypeName, detail: r.valueJson })) const stages = profileStore.stageHistory.map(s => ({ type: 'stage', time: s.timestamp, title: `进入${s.toStageName}阶段` })) return [...records, ...stages].sort((a, b) => dayjs(b.time).valueOf() - dayjs(a.time).valueOf() ) })

这个组件我让 Claude Code 优化过三次。第一次它用了watch监听多个 store,导致重复计算;第二次改成computed但没做排序;第三次才加上排序和分页。AI 生成的代码往往能跑但不够优,需要你带着性能意识去 review。

5. 常见问题与排查技巧实录

5.1 Claude Code 使用中的典型问题

问题一:生成的代码不符合项目已有风格

这是最常见的问题。Claude Code 每次生成代码时,如果上下文里没有足够的项目代码,它会按自己的默认风格来。解决办法是在提示词里明确引用已有文件,比如"参考src/modules/pet-profile/api/index.ts的风格,生成 pet-health 的 api 文件"。

问题二:跨文件修改时遗漏关联改动

比如你让它改一个 DTO 字段名,它可能只改了 DTO 本身,没改引用它的 Service 和 Controller。我的做法是改完后用全局搜索验证,或者直接告诉它"这个字段在哪些文件被引用,请一并修改"。

问题三:对 Spring Cloud Alibaba 版本特性不熟悉

Claude Code 的训练数据有时间截止点,对最新版本的 API 变化可能不了解。遇到这种情况,我会把官方文档的关键部分贴给它,让它基于文档生成代码。

5.2 项目搭建中的技术坑

问题现象根本原因解决方案
Nacos 注册成功但调用 503版本不匹配或命名空间配置错误核对版本对应表,检查 namespace 和 group
Seata 全局事务不回滚undo_log 表未建或数据源代理配置错误每个参与事务的库都要建 undo_log 表
Vue 3 响应式丢失解构 props 或 store 导致失去响应性用toRefs或storeToRefs
时间轮任务丢失服务重启后内存中的任务未持久化启动时从数据库重新加载未完成任务
跨域请求被拦截网关未配置 CORS 或前端代理未生效网关统一配置 CORS,前端开发用 proxy

5.3 独家避坑技巧

技巧一:用 Claude Code 做代码审查

不要只让它写代码,还要让它 review。我经常把一段代码贴给它,问"这段代码有什么潜在问题",它往往能发现我忽略的空指针、并发问题、资源泄漏。

技巧二:分阶段提交,不要一次性生成太多

Claude Code 一次生成的文件越多,出错概率越高。我的做法是按功能点分批,每批生成后立即编译验证,通过了再进入下一批。

技巧三:善用 CLAUDE.md 积累项目知识

每次踩坑后,把解决方案写进CLAUDE.md。比如"本项目 Nacos 使用 namespace=pet-dev,group=DEFAULT_GROUP",下次它生成配置时就会自动带上。这个文件会随着项目推进越来越有价值。

技巧四:关键业务逻辑自己写,样板代码交给 AI

状态机流转、事务边界、并发控制这些核心逻辑,我坚持自己写。Controller、DTO、Mapper、前端 CRUD 页面这些样板代码,全部交给 Claude Code。这样既保证质量又提升效率。

6. 部署与后续扩展思路

6.1 本地开发环境编排

我用 Docker Compose 编排中间件,让 Claude Code 生成了docker-compose.yml:

version: '3.8' services: nacos: image: nacos/nacos-server:v2.3.0 environment: - MODE=standalone ports: - "8848:8848" mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=pet123456 ports: - "3306:3306" redis: image: redis:7-alpine ports: - "6379:6379" rocketmq-namesrv: image: apache/rocketmq:5.1.0 command: sh mqnamesrv ports: - "9876:9876"

这套编排在 16G 内存的开发机上跑起来没问题,如果内存紧张可以把 RocketMQ 换成 RabbitMQ 的延迟插件方案。

6.2 后续可扩展的方向

这个项目骨架搭好之后,有几个自然的扩展方向。一是接入 AI 健康助手,根据宠物的健康记录生成护理建议,这个用大模型 API 就能做;二是多端同步,目前只有 Web 端,可以加小程序端,后端接口不用改;三是数据分析和报表,把健康记录做成可视化报告,这个用 ECharts 就能实现。

我个人在实际操作中的体会是,用 Claude Code 搭项目最大的价值不是省了多少打字时间,而是它强迫你把需求想清楚。因为你给它的描述越模糊,它生成的代码越离谱,这个反馈循环会倒逼你把业务逻辑梳理明白。我见过很多人抱怨 AI 写的代码不能用,其实问题往往出在自己都没想清楚要什么。

最后分享一个小技巧:Claude Code 的对话历史是有价值的资产。项目做完后,把关键的对话记录导出整理,就是一份很好的项目文档。我在这个项目里积累的提示词模板,后来直接复用到另外两个项目上,效率提升非常明显。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进