# Agents 开发规范 - 涉及到任何代码修改,记得更新此文档和设计文档 - 需求记录文档: [`docs/REQUIREMENTS.md`](docs/REQUIREMENTS.md) ## 前端开发启动 使用统一启动脚本,自动检查端口占用并清理后启动: ```bash # 同时启动 健康APP(5173) + 商城(5174) npm run dev # 或 node scripts/dev.js # 仅启动健康APP npm run dev:web # 或 node scripts/dev.js web # 仅启动商城 npm run dev:mall # 或 node scripts/dev.js mall # 仅关闭占用端口的进程 npm run dev:kill # 或 node scripts/dev.js --kill ``` | 项目 | 目录 | 端口 | 说明 | |------|------|------|------| | 健康APP (web) | `web/` | 5173 | 健康AI助手前端 | | 健康商城 (mall) | `mall/` | 5174 | 独立商城前端 | | 后端 API | `server/` | 8080 | Go-Zero 后端 | ## 前端自动化测试规范 **重要**: 前端进行功能更新和修改后,必须使用 Playwright 进行自动化测试验证。 **详细文档**: 参见 [`tests/README.md`](tests/README.md) ### 测试目录结构 ``` tests/ ├── README.md # 测试使用文档 ├── constitution.test.js # 体质分析功能测试 ├── profile.test.js # "我的"页面功能测试 ├── health-profile-complete.test.js # 健康档案完整功能测试(推荐) ├── chat.test.js # 问答页对话管理与流式输出测试 ├── mall.test.js # 商城前端测试(53项,含公开浏览+登录守卫,API Mock) ├── mall-real.test.js # 商城前端真实数据测试(52项,需后端) └── screenshots/ # 测试截图目录 ``` ### 测试流程 1. **修改代码后**:编写或运行 Playwright 测试脚本验证功能 2. **测试通过后**:才能确认修复完成 3. **不要让用户手动测试**:自动化测试能发现的问题应自行解决 ### 测试脚本示例 ```javascript // test-功能名.js const { chromium } = require("playwright"); (async () => { const browser = await chromium.launch({ headless: false }); const page = await browser.newPage(); // 1. 打开应用 await page.goto("http://localhost:8081"); await page.waitForTimeout(2000); // 2. 执行测试步骤... // 3. 截图验证 await page.screenshot({ path: "test-screenshot.png" }); // 4. 断言检查 const element = await page.locator("text=期望文本").first(); if (await element.isVisible()) { console.log("✓ 测试通过"); } else { console.log("✗ 测试失败"); } await browser.close(); })(); ``` ### 运行测试 ```bash # 安装 (首次) npm install playwright npx playwright install chromium # 运行测试 node test-功能名.js ``` ### 测试检查清单 1. [ ] 功能正常工作 2. [ ] 截图验证 UI 显示正确 3. [ ] 错误场景处理正确 4. [ ] 清理测试文件 (`rm test-*.js test-*.png`) --- ## 前后端 API 响应格式规范 **重要**: 所有 API 必须遵循此格式约定,避免响应格式不匹配问题。 ### 统一响应结构 ```json { "code": 0, // 0=成功,其他=错误码 "message": "success", "data": // 业务数据 } ``` ### data 字段约定 | 接口类型 | data 格式 | 示例 | | -------- | ------------------ | -------------------------- | | 列表接口 | 直接返回数组 `T[]` | `data: [{id:1}, {id:2}]` | | 详情接口 | 返回对象 `T` | `data: {id:1, name:"xxx"}` | | 创建接口 | 返回创建的对象 | `data: {id:1, ...}` | | 删除接口 | `null` 或空 | `data: null` | ### 字段命名约定 - **后端 API**: 使用 snake_case(`created_at`, `user_id`) - **前端应用**: 使用 camelCase(`createdAt`, `userId`) - **前端需做转换**: 在 Store 层统一转换 ### 类型定义文件 - **后端**: `server/docs/API.md` - API 文档 - **前端**: `app/src/api/types.ts` - 统一类型定义 ### 新增 API 检查清单 1. [ ] 查看 `server/docs/API.md` 确认后端响应格式 2. [ ] 在 `app/src/api/types.ts` 添加类型定义 3. [ ] 在 API 模块中使用正确的泛型类型 4. [ ] 在 Store 中添加 snake_case → camelCase 转换 --- ## 开发记录 ### 2026-02-02: Expo Web 兼容性修复 **问题**: React Native 的 `Alert.alert()` 在 Web 上无法正常显示弹窗 **解决方案**: 创建跨平台的 `AlertProvider` 组件,使用 react-native-paper 的 Snackbar 和 Dialog 替代原生 Alert **新增文件**: - `app/src/components/AlertProvider.tsx` - 全局 Alert Context 和组件 - `app/src/components/index.ts` - 组件导出 **修改文件**: - `app/App.tsx` - 集成 AlertProvider - `app/src/screens/auth/LoginScreen.tsx` - 替换 Alert 调用 - `app/src/screens/chat/ChatDetailScreen.tsx` - 替换 Alert 调用 - `app/src/screens/chat/ChatListScreen.tsx` - 替换 Alert 调用 - `app/src/screens/constitution/ConstitutionTestScreen.tsx` - 替换 Alert 调用 - `app/src/screens/profile/ProfileScreen.tsx` - 替换 Alert 调用 **使用方式**: ```tsx import { useAlert } from "../../components"; const { showAlert, showToast } = useAlert(); // Toast 简单提示 showToast("请输入正确的手机号"); // Dialog 确认弹窗 showAlert("确认删除", "确定要删除吗?", [ { text: "取消", style: "cancel" }, { text: "删除", style: "destructive", onPress: () => handleDelete() }, ]); ``` --- ### 2026-02-02: 健康档案功能对接 **内容**: 对接后端真实 API,实现健康档案功能 **新增文件**: - `app/src/stores/healthStore.ts` - 健康档案状态管理 - `app/src/screens/profile/HealthProfileScreen.tsx` - 健康档案页面 **修改文件**: - `app/src/api/user.ts` - 添加健康档案相关 API(病史、家族病史、过敏记录) - `app/src/navigation/index.tsx` - 添加 ProfileStack 和健康档案路由 - `app/src/screens/profile/ProfileScreen.tsx` - 对接健康档案导航和真实病史数据 **功能说明**: 1. **健康档案页面**: 展示基础信息、生活习惯、病史记录、家族病史、过敏记录 2. **用药记录**: 改用后端病史数据,显示"治疗中"状态的记录 3. **支持下拉刷新和长按删除** **API 对接**: - `GET /api/user/health-profile` - 获取完整健康档案 - `GET /api/user/lifestyle` - 获取生活习惯 - `GET /api/user/medical-history` - 获取病史列表 - `GET /api/user/family-history` - 获取家族病史 - `GET /api/user/allergy-records` - 获取过敏记录 - `DELETE /api/user/medical-history/:id` - 删除病史 - `DELETE /api/user/family-history/:id` - 删除家族病史 - `DELETE /api/user/allergy-records/:id` - 删除过敏记录 --- ### 2026-02-02: API 响应格式统一规范 **问题**: 前后端响应格式不匹配导致数据解析失败(已出现两次:Token 获取、对话列表) **根本原因**: - 前端期望: `data: { conversations: [...], total: number }` - 后端实际: `data: [...]` (直接返回数组) **解决方案**: 1. 创建统一类型定义文件 `app/src/api/types.ts` 2. 明确约定:列表接口 data 直接返回数组,不包装 3. Store 层统一做 snake_case → camelCase 转换 **新增文件**: - `app/src/api/types.ts` - 统一 API 类型定义 **修改文件**: - `app/src/api/conversation.ts` - 使用新类型定义 - `app/src/stores/chatStore.ts` - 添加转换函数 **关键代码**: ```typescript // app/src/api/types.ts - API 响应类型与后端保持一致 export interface ConversationItem { id: number; title: string; created_at: string; // snake_case updated_at: string; } // app/src/stores/chatStore.ts - 转换函数 const convertConversation = (item: ConversationItem): Conversation => ({ id: String(item.id), title: item.title, createdAt: item.created_at, // 转为 camelCase updatedAt: item.updated_at, }); ``` --- ### 2026-02-02: 体质分析功能修复 **问题**: 体质分析功能多处 API 格式不匹配导致运行时错误 **错误信息**: 1. `Cannot read properties of undefined (reading 'length')` - questions 字段 2. `currentQuestion.options.map is not a function` - options 字段格式 3. `Cannot read properties of undefined (reading 'suggestions')` - 结果格式 **根本原因**: - 问卷题目:后端直接返回数组 `data: [...]`,前端期望 `data: { questions: [...] }` - 选项格式:后端存储 `["没有","很少","有时","经常","总是"]`,前端期望 `[{value, label}]` - 结果格式:后端返回 `{ primary_constitution: {...}, all_scores: [...] }`,前端期望 `{ primaryType, scores }` **修改文件**: - `app/src/stores/constitutionStore.ts` - 添加数据格式转换 - `app/src/api/constitution.ts` - 更新类型定义 - `app/src/screens/constitution/ConstitutionResultScreen.tsx` - 添加防御性代码 **关键修复代码**: ```typescript // 问卷数据转换 const questions = rawQuestions.map((q: any) => { let parsedOptions = typeof q.options === "string" ? JSON.parse(q.options) : q.options; // 字符串数组转为 {value, label} 格式 if (Array.isArray(parsedOptions) && typeof parsedOptions[0] === "string") { parsedOptions = parsedOptions.map((label: string, index: number) => ({ value: index + 1, label, })); } return { id: q.id || q.ID, constitution_type: q.constitution_type, question: q.question_text || q.question, options: parsedOptions, order_num: q.order_num, }; }); // 结果数据转换 const scores: Record = {}; apiResult.all_scores?.forEach((item: any) => { scores[item.type] = item.score; }); const result = { primaryType: apiResult.primary_constitution?.type, scores, // ... }; ``` **测试验证**: - 测试脚本: `tests/constitution.test.js` - 测试结果: 12/13 通过,67 道题完整测试 - 测试截图: `tests/screenshots/constitution-result.png` --- ### 2026-02-02: "我的"页面功能测试 **测试内容**: 1. 用户信息显示(昵称、手机号、体质标签) 2. 编辑昵称功能 3. 适老模式开关 4. 健康管理菜单(健康档案、用药记录、体质报告、对话历史) 5. 用药/治疗记录弹窗 6. 关于我们弹窗 7. 退出登录功能 8. 健康档案导航 **测试结果**: 16/18 通过 **通过项目**: - ✓ 用户信息显示完整 - ✓ 编辑昵称功能正常 - ✓ 适老模式开关正常 - ✓ 所有菜单项显示正常 - ✓ 用药记录弹窗正常 - ✓ 退出登录按钮显示 - ✓ 健康档案导航正常 **测试文件**: - 测试脚本: `tests/profile.test.js` - 测试截图: `tests/screenshots/profile-*.png`, `tests/screenshots/health-profile-*.png` - 测试文档: `tests/README.md` --- ### 2026-02-02: 健康档案编辑功能 **新增功能**: 1. 基础信息编辑弹窗 - 编辑姓名、性别、出生日期、身高、体重、血型、职业、婚姻状况、地区 2. 生活习惯编辑弹窗 - 编辑睡眠时间、睡眠质量、饮食、运动、吸烟、饮酒等 3. 病史记录新增功能 - 添加疾病名称、类型、诊断日期、状态、备注 4. 家族病史新增功能 - 添加亲属关系、疾病名称、备注 5. 过敏记录新增功能 - 添加过敏类型、过敏原、严重程度、反应描述 **修改文件**: - `app/src/api/user.ts` - 添加 addMedicalHistory, addFamilyHistory, addAllergyRecord API - `app/src/stores/healthStore.ts` - 添加创建记录的方法 - `app/src/screens/profile/HealthProfileScreen.tsx` - 添加编辑弹窗和新增功能 **测试结果**: 23/25 通过 **通过项目**: - ✓ 健康档案页面打开 - ✓ 基础信息卡片显示 - ✓ 基础信息编辑弹窗打开 - ✓ 生活习惯卡片显示 - ✓ 病史记录卡片显示 - ✓ 病史记录新增弹窗打开 - ✓ 家族病史卡片显示 - ✓ 过敏记录卡片显示 --- ### 2026-02-02: 健康档案保存功能修复 **问题描述**: 1. 基础信息保存后页面不显示更新的数据 2. 病史记录、家族病史、过敏记录添加失败 3. 后端返回的数据格式与前端期望不匹配 **根本原因**: 1. `fetchHealthProfile` 错误地将 `response.data` 直接赋给 `profile`,但后端返回的是嵌套结构 `{ profile, lifestyle, medical_history, ... }` 2. 后端字段名 `medical_history`(单数)与前端使用的 `medical_histories`(复数)不匹配 3. 添加记录时后端返回 `data: null`,但前端检查 `response.code === 0 && response.data`,导致误判为失败 **修复内容**: - `app/src/stores/healthStore.ts`: - `fetchHealthProfile`: 修复数据解析,支持嵌套结构 `data.profile || data` - `fetchHealthProfile`: 兼容两种字段名 `data.medical_history || data.medical_histories` - `updateHealthProfile`: 修改判断条件,只检查 `response.code === 0` - `updateLifestyle`: 同上 - `addMedicalHistory`: 修改判断条件,只检查 `response.code === 0`,并在成功后调用 `fetchHealthProfile()` 刷新数据 - `addFamilyHistory`: 同上 - `addAllergyRecord`: 同上 **测试验证**: - 测试脚本: `tests/health-profile-complete.test.js` - 测试范围: - 基础信息: 9 个字段(姓名、性别、出生日期、身高、体重、血型、职业、婚姻状况、地区) - 生活习惯: 10 个字段(入睡时间、起床时间、睡眠质量、三餐规律、饮食偏好、日饮水量、运动频率、运动类型、吸烟、饮酒) - 病史记录: 5 个字段(疾病名称、疾病类型、诊断日期、治疗状态、备注) - 家族病史: 3 个字段(亲属关系、疾病名称、备注) - 过敏记录: 4 个字段(过敏类型、过敏原、严重程度、过敏反应描述) - 测试结果: **58/58 通过** ✓ - 测试截图: `tests/screenshots/hp-*.png` --- ### 2026-02-02: AI 问答功能增强 **修改内容**: 1. **等待动画**: 添加 LoadingDots 组件,在等待 AI 回复和思考过程中显示动态加载动画 2. **思考过程显示**: 支持显示 AI 思考过程(需要模型支持 `enable_thinking`) 3. **放开思考过程过滤**: 移除之前添加的关键词过滤逻辑,完整显示 AI 思考内容 **修改文件**: - `app/src/screens/chat/ChatDetailScreen.tsx`: - 添加 `LoadingDots` 组件,实现三个点的脉冲动画 - 在 AI 回复等待时显示 "AI 正在回复..." - 在思考过程等待时显示 "💭 思考中..." - `server/internal/service/ai/aliyun.go`: - 移除 `thinkingFilterKeywords` 关键词列表 - 移除 `shouldFilterThinking` 过滤函数 - 简化思考过程流式输出,直接转发不过滤 - `server/config.yaml`: - 注释掉 `app_id` 配置(应用 API 格式与 OpenAI 兼容模式不同,暂不支持) **LoadingDots 组件示例**: ```tsx const LoadingDots = ({ text = "思考中", fontSize = 15 }) => { const [dotCount, setDotCount] = useState(1); useEffect(() => { const interval = setInterval(() => { setDotCount((prev) => (prev >= 3 ? 1 : prev + 1)); }, 400); return () => clearInterval(interval); }, []); return ( {text} {".".repeat(dotCount)} ); }; ``` **备注**: - 阿里云百炼应用 API 需要使用专用的 `/api/v1/apps/{APP_ID}/completion` 端点,与当前 OpenAI 兼容模式实现不同 - 思考过程功能需要使用支持 `enable_thinking` 参数的模型(如 qwen-plus) --- ### 2026-02-03: 商城后端 API 开发 **内容**: 在现有健康AI后端基础上扩展商城功能,共享用户体系和JWT认证 **新增模型**: - `ProductCategory` - 商品分类 - `ProductSku` - 商品SKU - `PointsRecord` - 积分变动记录 - `CartItem` - 购物车 - `Address` - 收货地址 - `Order` / `OrderItem` - 订单 **新增API路由** (`/api/mall`): - 公开路由: 分类列表、商品列表/详情/搜索/推荐 - 认证路由: 会员信息、积分、购物车CRUD、地址CRUD、订单全流程、体质推荐 **API定义**: `backend/healthapi/healthapi.api` (商城部分在文件末尾) **测试**: `backend/healthapi/tests/mall_api_test.go` - 30个Go集成测试全部通过 --- ### 2026-02-07: 商城 Web H5 前端开发 → 独立项目拆分 **内容**: 基于 Vue 3 + TypeScript + Element Plus 开发商城 Web H5 前端,后拆分为独立项目 **项目结构调整**: 商城从 `web/` 项目中拆分为独立的 `mall/` 项目: - `web/` (端口 5173) - 健康AI助手前端 - `mall/` (端口 5174) - 健康商城前端 - 两个项目共享同一后端(端口 8080)和 JWT Token(通过 localStorage 共享) - 双向跳转通过 `VITE_MALL_URL` / `VITE_HEALTH_AI_URL` 环境变量配置 **mall/ 项目文件结构**: ``` mall/ ├── package.json # 独立依赖管理 ├── vite.config.ts # Vite 配置(端口 5174) ├── tsconfig.json # TypeScript 配置 ├── .env # 环境变量(API地址、健康AI地址) ├── index.html └── src/ ├── main.ts # 入口文件 ├── App.vue ├── router/index.ts # 路由(根路径 / 开头) ├── api/ │ ├── request.ts # Axios 封装(共享Token拦截器) │ ├── auth.ts # 认证 API │ └── mall.ts # 商城 API(商品/购物车/订单/地址/会员) ├── stores/ │ ├── auth.ts # 认证状态(从 localStorage 恢复) │ ├── constitution.ts # 体质数据(从 localStorage 读取) │ ├── mall.ts # 购物车和分类 │ ├── order.ts # 订单 │ └── member.ts # 会员信息 ├── types/index.ts # 商城类型定义 + 体质类型 ├── utils/healthAI.ts # 健康AI跳转工具 ├── styles/index.scss # 全局样式 └── views/ ├── layout/MallLayout.vue # H5布局 └── mall/ # 10个页面 ├── MallHomeView.vue # 首页 ├── CategoryView.vue # 分类 ├── ProductDetailView.vue # 商品详情 ├── SearchView.vue # 搜索 ├── CartView.vue # 购物车 ├── CheckoutView.vue # 结算 ├── OrderListView.vue # 订单列表 ├── OrderDetailView.vue # 订单详情 ├── AddressListView.vue # 地址管理 └── MemberView.vue # 会员中心 ``` **web/ 项目变更**: - 移除所有商城代码(views/mall/、stores/mall|order|member、api/mall、utils/healthAI等) - `web/src/router/index.ts` - 移除 `/mall` 路由组 - `web/src/views/home/HomeView.vue` - "健康商城"改为外部链接跳转 - `web/src/views/profile/ProfileView.vue` - "健康商城"改为外部链接跳转 - `web/src/types/index.ts` - 移除商城类型定义 - `web/.env` - 新增 `VITE_MALL_URL` 环境变量 **认证策略(按需登录)**: 商城采用"公开浏览 + 按需登录"策略,用户可自由浏览商品,仅在涉及个人数据的操作时要求登录: | 页面/操作 | 是否需要登录 | 说明 | |-----------|:----------:|------| | 首页、分类、商品详情、搜索 | 否 | 自由浏览 | | 加入购物车、立即购买 | 是 | 弹窗引导登录 | | 购物车、结算、订单 | 是 | 路由守卫重定向 | | 地址管理、会员中心 | 是 | 路由守卫重定向 | - 路由守卫:仅 `meta.requiresAuth` 的路由会重定向到 `/login` - 操作拦截:`useAuthCheck().requireAuth()` 弹窗引导登录 - 401 处理:API 返回 401 时清除 token 并跳转到本地登录页 **跨项目跳转机制**: ``` 健康AI (web/) ←→ 商城 (mall/) ├── 共享: localStorage 中的 token 和 user 信息 ├── web → mall: window.open(VITE_MALL_URL) ├── mall → web: jumpToHealthAI() / goToHealthAI() └── mall 独立登录: /login 页面(不再依赖 web 登录页) ``` **启动方式**: ```bash # 健康AI前端 cd web && npm run dev # http://localhost:5173 # 商城前端 cd mall && npm run dev # http://localhost:5174 # 后端 cd backend && go run . # http://localhost:8080 ``` **设计规范**: - 主色调: #52C41A (绿色/健康主题) - 价格色: #FF4D4F - H5 布局 max-width: 750px - 面向中老年用户:大字体、大按钮、简洁流程 - 与健康AI双向跳转集成(AI咨询悬浮按钮、体质推荐等) --- ### 2026-02-07: 商城认证策略优化 — 公开浏览 + 按需登录 **需求**: 商城应允许用户自由浏览商品,仅在生成订单或支付时才需要登录 **修改内容**: 1. **路由守卫改造** (`mall/src/router/index.ts`): - 取消全局登录拦截,改为按路由标记 `meta.requiresAuth` - 公开页面(首页/分类/商品详情/搜索)无需登录 - 受保护页面(购物车/订单/结算/地址/会员)需要登录 2. **操作级登录引导** (`mall/src/utils/auth.ts`): - 新增 `useAuthCheck()` composable - `requireAuth(message)` 方法:未登录时弹 `ElMessageBox.confirm` 引导登录 - 用于商品详情页的"加入购物车"和"立即购买"按钮 3. **商品详情页** (`mall/src/views/mall/ProductDetailView.vue`): - `handleAddToCart()` 和 `handleBuyNow()` 执行前调用 `requireAuth()` 检查 4. **测试更新** (`tests/mall.test.js`): - 新增 Phase 7A: 未登录公开浏览测试(首页/分类/商品/搜索可正常访问) - 更新 Phase 7B: 受保护页面重定向测试(5个路由均重定向到 /login) - 53项测试全部通过 **新增文件**: - `mall/src/utils/auth.ts` - 认证检查 composable **修改文件**: - `mall/src/router/index.ts` - 路由守卫改造 - `mall/src/views/mall/ProductDetailView.vue` - 按钮登录检查 - `tests/mall.test.js` - 测试更新 --- ### 2026-02-11: 商城页面补全 — 购物车 / 我的 **问题**: 购物车页和我的页关键交互缺失,影响日常使用。 **补全内容**: 1. **购物车页** (`mall/src/views/mall/CartView.vue`) - 新增顶部操作区:`删除已选`、`清空购物车` - 删除/清空前增加确认弹窗,完成后成功提示 - 操作中禁用按钮,避免重复点击导致重复请求 2. **购物车 Store** (`mall/src/stores/mall.ts`) - 新增 `removeCartItems(ids)` 批量删除方法 - 使用并发删除后统一刷新购物车,减少页面闪烁 3. **我的页** (`mall/src/views/mall/MemberView.vue`) - 新增订单状态角标(待支付/待发货/待收货/已完成) - 新增会员信息加载失败提示与重试按钮 - 新增“退出登录”菜单项 - 增加退出确认弹窗,退出后跳转本地登录页 4. **会员 Store** (`mall/src/stores/member.ts`) - 修复积分“加载更多”逻辑:第2页开始追加而非覆盖 - 增加重置状态方法 `resetMemberState()` 5. **订单 Store** (`mall/src/stores/order.ts`) - 兼容 `page_info` 缺失场景 - 修复分页“加载更多”逻辑:第2页开始追加而非覆盖 **验证**: - `mall` 执行 `npx vue-tsc --noEmit` 通过 - `tests/mall.test.js` 执行通过(62项,失败0) --- ### 2026-02-03: 项目文档整理与子模块修复 **问题**: 其他机器 `git clone` 后无法启动项目。 **根因分析**: 1. `app/` 以 gitlink(mode 160000)记录在仓库中,但缺少 `.gitmodules` 文件,clone 后 `app/` 为空目录 2. `web/.env` 和 `mall/.env` 被 `.gitignore` 排除,clone 后前端无法得知后端地址 3. `README.md` 内容过时,缺少完整的环境搭建步骤 **修复内容**: 1. **app 子模块转为普通目录**: - `git rm --cached app` 移除 gitlink 条目 - 删除 `app/.git`,消除嵌套仓库 - `git add app/` 将 47 个源文件纳入主仓库常规跟踪 - 解决了 clone 后 `app/` 为空的问题 2. **环境变量模板**: - 新增 `web/.env.example` — 包含 `VITE_API_BASE_URL` 和 `VITE_MALL_URL` - 新增 `mall/.env.example` — 包含 `VITE_API_BASE_URL` 和 `VITE_HEALTH_AI_URL` - `.gitignore` 添加 `!.env.example` 放行规则 3. **README.md 重写**: - 完整项目结构树 - 技术栈总览表(后端/Web/Mall/APP/测试) - 环境要求(Node、Go、Git 版本) - 从零开始的详细搭建步骤(后端 → Web → Mall → APP) - 一键启动说明(start.bat / start.sh / npm scripts) - 环境变量配置参考 - 常见问题排查(依赖缺失、.env 缺失、端口占用、数据库目录、APP 连接) - 项目关系架构图 **新增文件**: - `web/.env.example` - `mall/.env.example` **修改文件**: - `README.md` — 完全重写 - `.gitignore` — 添加 `!.env.example` 和 `backend/healthapi/data/` - `app/` — 从 gitlink 转为 47 个常规跟踪文件