|
|
@@ -0,0 +1,2563 @@
|
|
|
+# 溪福俱乐部 (Care Family Club) 平台升级实现计划
|
|
|
+
|
|
|
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
|
+
|
|
|
+**Goal:** 将知心益家 (ZXYJ) 从家庭教育任务管理小程序升级为溪福俱乐部 — 身/心/智/行四维主动健康管理平台,集成Lilishop电商。
|
|
|
+
|
|
|
+**Architecture:** 增量重构(非重建),保留现有ZXYJ代码作为智(Wisdom)域基础,围绕其新增身(Body)/心(Mind)/行(Action)三个域。前端首页改为四象限矩阵入口,后端按域新增controller包和entity。Lilishop作为独立微服务通过REST API集成。
|
|
|
+
|
|
|
+**Tech Stack:**
|
|
|
+- 后端: Java 1.8 + Spring Boot 2.7.18 + MyBatis-Plus
|
|
|
+- 前端小程序: uni-app (Vue 2 Options API)
|
|
|
+- Web管理端: Vue 2 + Element UI
|
|
|
+- 数据库: MySQL 8.0 (zxyj主库 + sfms只读源库)
|
|
|
+- 认证: JWT Bearer Token
|
|
|
+- 电商: Lilishop (独立微服务, REST API集成)
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 架构决策
|
|
|
+
|
|
|
+| # | 决策点 | 选择 | 理由 |
|
|
|
+|---|--------|------|------|
|
|
|
+| 1 | Entity组织 | **A) flat entity/ + 域前缀命名** (BodyHealthMetric, MindMoodLog) | 现有49个实体全平铺,最小破坏性,MyBatis-Plus不关心包路径 |
|
|
|
+| 2 | Controller包 | **B) 新增域包,旧包保留** (新增controller/body/, controller/mind/, controller/action/) | 不打断现有功能,增量迁移 |
|
|
|
+| 3 | 前端导航 | **4-tab: 首页(四象限) / 智(任务+成长) / 行(活动+商城) / 我的** | 微信tabBar最多5项,4项最简洁;身/心通过首页象限入口进入 |
|
|
|
+| 4 | 数据库策略 | **A) DatabaseInitializer.java** | 遵循"不建索引,不建约束,不建自定义SQL"约束,保持现有模式 |
|
|
|
+| 5 | 积分系统 | **跨域共享PointsService** + PointsLog增加domain字段 | 积分来源扩展到四域,统一管理避免碎片化 |
|
|
|
+| 6 | Lilishop集成 | **C) 混合模式** — 服务账号(商品浏览) + 委托认证(购物车/结算) | 浏览无需用户上下文,交易需用户身份 |
|
|
|
+| 7 | 构建顺序 | **框架→行→身→心→电商** | 行域有部分代码可扩展,身域较简单,心域最复杂,电商独立最后加 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 四域内容定义
|
|
|
+
|
|
|
+### 身 (Body) — 细胞抗衰
|
|
|
+| 功能 | 说明 | 新entity |
|
|
|
+|------|------|----------|
|
|
|
+| 健康指标记录 | 体重/血压/心率/睡眠 | BodyHealthMetric |
|
|
|
+| 水营养追踪 | 每日饮水/营养素摄入 | BodyNutritionLog |
|
|
|
+| 抗衰评估 | 细胞抗衰测评+报告 | BodyAntiAgingAssessment |
|
|
|
+| 运动追踪 | 运动记录+步数 | BodyExerciseLog |
|
|
|
+
|
|
|
+### 心 (Mind) — 心理情绪
|
|
|
+| 功能 | 说明 | 新entity |
|
|
|
+|------|------|----------|
|
|
|
+| 情绪日志 | 每日心情记录+标签 | MindMoodLog |
|
|
|
+| 心理测评 | 专业心理评估问卷 | MindPsychologicalAssessment |
|
|
|
+| 家庭氛围指数 | 家庭关系评估 | MindFamilyAtmosphereIndex |
|
|
|
+| 冥想/放松 | 引导式冥想计时 | MindMeditationSession |
|
|
|
+
|
|
|
+### 智 (Wisdom) — 教育 (现有)
|
|
|
+| 功能 | 现有entity | 状态 |
|
|
|
+|------|-----------|------|
|
|
|
+| 任务管理 | Task, TaskTemplate, TaskPlanInstance | ✅ 已完成 |
|
|
|
+| 积分系统 | PointsLog, StreakMilestone | ✅ 已完成 |
|
|
|
+| 奖励体系 | Reward, Wish, RewardWishlist | ✅ 已完成 |
|
|
|
+| 成长档案 | GrowthRecord, GrowthPlan | ✅ 已完成 |
|
|
|
+| DAN测评 | DanAssessmentResult, AssessmentOrder | ✅ 已完成 |
|
|
|
+| 小游戏 | MiniGame | ✅ 已完成 |
|
|
|
+| 规划师 | Guide, GuidePackage, GuideFamily | ✅ 已完成 |
|
|
|
+
|
|
|
+### 行 (Action) — 关系践行
|
|
|
+| 功能 | 说明 | 新entity |
|
|
|
+|------|------|----------|
|
|
|
+| 活动/事件 | 线上线下活动组织 | ActionActivity, ActionActivityRegistration |
|
|
|
+| 内容科普 | 文章/视频/知识库 | ActionArticle, ActionArticleCategory |
|
|
|
+| 长者关怀 | 养老计划+关怀记录 | ActionElderCarePlan, ActionElderCareLog |
|
|
|
+| 家庭实践 | 关系践行任务(区别于智域学习任务) | ActionPracticeTask |
|
|
|
+| 社区互动 | 家庭间交流 | ActionCommunityPost, ActionCommunityComment |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 文件结构变更
|
|
|
+
|
|
|
+### 后端新增文件
|
|
|
+
|
|
|
+```
|
|
|
+zxyj-backend/src/main/java/com/zxyj/
|
|
|
+├── controller/
|
|
|
+│ ├── body/ # NEW
|
|
|
+│ │ ├── BodyHealthController.java
|
|
|
+│ │ ├── BodyNutritionController.java
|
|
|
+│ │ ├── BodyAntiAgingController.java
|
|
|
+│ │ └── BodyExerciseController.java
|
|
|
+│ ├── mind/ # NEW
|
|
|
+│ │ ├── MindMoodController.java
|
|
|
+│ │ ├── MindAssessmentController.java
|
|
|
+│ │ ├── MindFamilyAtmosphereController.java
|
|
|
+│ │ └── MindMeditationController.java
|
|
|
+│ ├── action/ # NEW
|
|
|
+│ │ ├── ActionController.java
|
|
|
+│ │ ├── ActionArticleController.java
|
|
|
+│ │ ├── ActionElderCareController.java
|
|
|
+│ │ └── ActionCommunityController.java
|
|
|
+│ └── commerce/ # NEW (Phase 5)
|
|
|
+│ └── CommerceController.java
|
|
|
+├── entity/
|
|
|
+│ ├── BodyHealthMetric.java # NEW
|
|
|
+│ ├── BodyNutritionLog.java # NEW
|
|
|
+│ ├── BodyAntiAgingAssessment.java # NEW
|
|
|
+│ ├── BodyExerciseLog.java # NEW
|
|
|
+│ ├── MindMoodLog.java # NEW
|
|
|
+│ ├── MindPsychologicalAssessment.java # NEW
|
|
|
+│ ├── MindFamilyAtmosphereIndex.java # NEW
|
|
|
+│ ├── MindMeditationSession.java # NEW
|
|
|
+│ ├── ActionActivity.java # NEW
|
|
|
+│ ├── ActionActivityRegistration.java # NEW
|
|
|
+│ ├── ActionArticle.java # NEW
|
|
|
+│ ├── ActionArticleCategory.java # NEW
|
|
|
+│ ├── ActionElderCarePlan.java # NEW
|
|
|
+│ ├── ActionElderCareLog.java # NEW
|
|
|
+│ ├── ActionPracticeTask.java # NEW
|
|
|
+│ ├── ActionCommunityPost.java # NEW
|
|
|
+│ └── ActionCommunityComment.java # NEW
|
|
|
+├── service/
|
|
|
+│ ├── BodyHealthService.java # NEW
|
|
|
+│ ├── BodyNutritionService.java # NEW
|
|
|
+│ ├── BodyAntiAgingService.java # NEW
|
|
|
+│ ├── BodyExerciseService.java # NEW
|
|
|
+│ ├── MindMoodService.java # NEW
|
|
|
+│ ├── MindAssessmentService.java # NEW
|
|
|
+│ ├── MindFamilyAtmosphereService.java # NEW
|
|
|
+│ ├── MindMeditationService.java # NEW
|
|
|
+│ ├── ActionActivityService.java # NEW
|
|
|
+│ ├── ActionArticleService.java # NEW
|
|
|
+│ ├── ActionElderCareService.java # NEW
|
|
|
+│ ├── ActionPracticeService.java # NEW
|
|
|
+│ ├── ActionCommunityService.java # NEW
|
|
|
+│ └── LilishopApiClient.java # NEW (Phase 5)
|
|
|
+└── mapper/
|
|
|
+ ├── BodyHealthMetricMapper.java # NEW
|
|
|
+ ├── BodyNutritionLogMapper.java # NEW
|
|
|
+ ├── BodyAntiAgingAssessmentMapper.java # NEW
|
|
|
+ ├── BodyExerciseLogMapper.java # NEW
|
|
|
+ ├── MindMoodLogMapper.java # NEW
|
|
|
+ ├── MindPsychologicalAssessmentMapper.java # NEW
|
|
|
+ ├── MindFamilyAtmosphereIndexMapper.java # NEW
|
|
|
+ ├── MindMeditationSessionMapper.java # NEW
|
|
|
+ ├── ActionActivityMapper.java # NEW
|
|
|
+ ├── ActionActivityRegistrationMapper.java # NEW
|
|
|
+ ├── ActionArticleMapper.java # NEW
|
|
|
+ ├── ActionArticleCategoryMapper.java # NEW
|
|
|
+ ├── ActionElderCarePlanMapper.java # NEW
|
|
|
+ ├── ActionElderCareLogMapper.java # NEW
|
|
|
+ ├── ActionPracticeTaskMapper.java # NEW
|
|
|
+ ├── ActionCommunityPostMapper.java # NEW
|
|
|
+ └── ActionCommunityCommentMapper.java # NEW
|
|
|
+```
|
|
|
+
|
|
|
+### 前端新增/修改文件
|
|
|
+
|
|
|
+```
|
|
|
+zxyj-frontend/
|
|
|
+├── pages/
|
|
|
+│ ├── index/
|
|
|
+│ │ ├── index.vue # MODIFY - 四象限首页
|
|
|
+│ │ ├── parent-index.vue # MODIFY - 增加四象限入口
|
|
|
+│ │ └── child-index.vue # MODIFY - 增加四象限入口
|
|
|
+│ ├── body/ # NEW
|
|
|
+│ │ ├── index.vue # 身域首页
|
|
|
+│ │ ├── health-metric.vue # 健康指标记录
|
|
|
+│ │ ├── nutrition-log.vue # 水营养追踪
|
|
|
+│ │ ├── anti-aging.vue # 抗衰评估
|
|
|
+│ │ └── exercise-log.vue # 运动追踪
|
|
|
+│ ├── mind/ # NEW
|
|
|
+│ │ ├── index.vue # 心域首页
|
|
|
+│ │ ├── mood-log.vue # 情绪日志
|
|
|
+│ │ ├── assessment.vue # 心理测评
|
|
|
+│ │ ├── family-atmosphere.vue # 家庭氛围
|
|
|
+│ │ └── meditation.vue # 冥想
|
|
|
+│ ├── action/ # NEW
|
|
|
+│ │ ├── index.vue # 行域首页
|
|
|
+│ │ ├── activity-list.vue # 活动列表
|
|
|
+│ │ ├── activity-detail.vue # 活动详情
|
|
|
+│ │ ├── article-list.vue # 文章/科普列表
|
|
|
+│ │ ├── article-detail.vue # 文章详情
|
|
|
+│ │ ├── elder-care.vue # 长者关怀
|
|
|
+│ │ └── community.vue # 社区互动
|
|
|
+│ ├── commerce/ # NEW (Phase 5)
|
|
|
+│ │ ├── product-list.vue # 商品列表
|
|
|
+│ │ ├── product-detail.vue # 商品详情
|
|
|
+│ │ ├── cart.vue # 购物车
|
|
|
+│ │ └── order-list.vue # 订单列表
|
|
|
+│ └── ... # 现有页面保留
|
|
|
+├── pages.json # MODIFY - 新增页面注册 + tabBar调整
|
|
|
+├── utils/
|
|
|
+│ └── api.js # MODIFY - 新增域API封装
|
|
|
+└── store/
|
|
|
+ └── index.js # MODIFY - 增加 domain state
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Phase 1: 框架搭建(首页 + 核心实体 + 导航重构)
|
|
|
+
|
|
|
+**目标:** 建立四域框架,替换首页为四象限入口,创建所有新entity/mapper/service骨架,调整导航结构。此阶段完成后,用户可以看到四象限首页,点击进入各域,但各域功能为空壳。
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 1: 创建 Body 域 Entity
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/BodyHealthMetric.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/BodyNutritionLog.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/BodyAntiAgingAssessment.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/BodyExerciseLog.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 创建 BodyHealthMetric entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("body_health_metrics")
|
|
|
+public class BodyHealthMetric {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private BigDecimal weight;
|
|
|
+ private Integer bloodPressureSystolic;
|
|
|
+ private Integer bloodPressureDiastolic;
|
|
|
+ private Integer heartRate;
|
|
|
+ private Integer sleepHours;
|
|
|
+ private Integer sleepQuality;
|
|
|
+ private String note;
|
|
|
+ private LocalDateTime recordDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 创建 BodyNutritionLog entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("body_nutrition_logs")
|
|
|
+public class BodyNutritionLog {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private Integer waterMl;
|
|
|
+ private Integer calorieIntake;
|
|
|
+ private BigDecimal proteinG;
|
|
|
+ private BigDecimal vitaminC;
|
|
|
+ private BigDecimal vitaminD;
|
|
|
+ private String mealType;
|
|
|
+ private String note;
|
|
|
+ private LocalDateTime recordDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建 BodyAntiAgingAssessment entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("body_anti_aging_assessments")
|
|
|
+public class BodyAntiAgingAssessment {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private Long guideId;
|
|
|
+ private String assessmentType;
|
|
|
+ private Integer cellularAge;
|
|
|
+ private Integer biologicalAge;
|
|
|
+ private String resultSummary;
|
|
|
+ private String resultDetail;
|
|
|
+ private String reportUrl;
|
|
|
+ private String status;
|
|
|
+ private LocalDateTime assessmentDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 创建 BodyExerciseLog entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("body_exercise_logs")
|
|
|
+public class BodyExerciseLog {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private String exerciseType;
|
|
|
+ private Integer durationMinutes;
|
|
|
+ private Integer steps;
|
|
|
+ private Integer caloriesBurned;
|
|
|
+ private Integer intensity;
|
|
|
+ private String note;
|
|
|
+ private LocalDateTime exerciseDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 5: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 2: 创建 Mind 域 Entity
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/MindMoodLog.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/MindPsychologicalAssessment.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/MindFamilyAtmosphereIndex.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/MindMeditationSession.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 创建 MindMoodLog entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("mind_mood_logs")
|
|
|
+public class MindMoodLog {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private Integer moodScore;
|
|
|
+ private String moodLabel;
|
|
|
+ private String tags;
|
|
|
+ private String note;
|
|
|
+ private String weather;
|
|
|
+ private LocalDateTime recordDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 创建 MindPsychologicalAssessment entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("mind_psychological_assessments")
|
|
|
+public class MindPsychologicalAssessment {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private Long guideId;
|
|
|
+ private String assessmentType;
|
|
|
+ private Integer totalScore;
|
|
|
+ private String resultLevel;
|
|
|
+ private String resultSummary;
|
|
|
+ private String resultDetail;
|
|
|
+ private String reportUrl;
|
|
|
+ private String status;
|
|
|
+ private LocalDateTime assessmentDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建 MindFamilyAtmosphereIndex entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("mind_family_atmosphere_indices")
|
|
|
+public class MindFamilyAtmosphereIndex {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Integer communicationScore;
|
|
|
+ private Integer emotionalScore;
|
|
|
+ private Integer supportScore;
|
|
|
+ private Integer conflictScore;
|
|
|
+ private Integer overallScore;
|
|
|
+ private String note;
|
|
|
+ private LocalDateTime recordDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 创建 MindMeditationSession entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("mind_meditation_sessions")
|
|
|
+public class MindMeditationSession {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long userId;
|
|
|
+ private String meditationType;
|
|
|
+ private Integer durationMinutes;
|
|
|
+ private Integer completionRate;
|
|
|
+ private String audioUrl;
|
|
|
+ private String note;
|
|
|
+ private LocalDateTime sessionDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 5: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 3: 创建 Action 域 Entity
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionActivity.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionActivityRegistration.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionArticle.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionArticleCategory.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionElderCarePlan.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionElderCareLog.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionPracticeTask.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionCommunityPost.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/entity/ActionCommunityComment.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 创建 ActionActivity entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_activities")
|
|
|
+public class ActionActivity {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long creatorId;
|
|
|
+ private String title;
|
|
|
+ private String description;
|
|
|
+ private String coverUrl;
|
|
|
+ private String activityType;
|
|
|
+ private String location;
|
|
|
+ private BigDecimal latitude;
|
|
|
+ private BigDecimal longitude;
|
|
|
+ private LocalDateTime startTime;
|
|
|
+ private LocalDateTime endTime;
|
|
|
+ private Integer maxParticipants;
|
|
|
+ private Integer currentParticipants;
|
|
|
+ private BigDecimal fee;
|
|
|
+ private String status;
|
|
|
+ private Integer pointsReward;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 创建 ActionActivityRegistration entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_activity_registrations")
|
|
|
+public class ActionActivityRegistration {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long activityId;
|
|
|
+ private Long userId;
|
|
|
+ private Long familyId;
|
|
|
+ private String status;
|
|
|
+ private String note;
|
|
|
+ private LocalDateTime registeredAt;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建 ActionArticle entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_articles")
|
|
|
+public class ActionArticle {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long authorId;
|
|
|
+ private Long categoryId;
|
|
|
+ private String title;
|
|
|
+ private String summary;
|
|
|
+ private String content;
|
|
|
+ private String coverUrl;
|
|
|
+ private String articleType;
|
|
|
+ private Integer viewCount;
|
|
|
+ private Integer likeCount;
|
|
|
+ private String status;
|
|
|
+ private LocalDateTime publishedAt;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 创建 ActionArticleCategory entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_article_categories")
|
|
|
+public class ActionArticleCategory {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private String name;
|
|
|
+ private String icon;
|
|
|
+ private String description;
|
|
|
+ private Integer sortOrder;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 5: 创建 ActionElderCarePlan entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_elder_care_plans")
|
|
|
+public class ActionElderCarePlan {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long creatorId;
|
|
|
+ private String elderName;
|
|
|
+ private Integer elderAge;
|
|
|
+ private String healthCondition;
|
|
|
+ private String careLevel;
|
|
|
+ private String careItems;
|
|
|
+ private String emergencyContact;
|
|
|
+ private String emergencyPhone;
|
|
|
+ private String status;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 6: 创建 ActionElderCareLog entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_elder_care_logs")
|
|
|
+public class ActionElderCareLog {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long planId;
|
|
|
+ private Long familyId;
|
|
|
+ private Long caregiverId;
|
|
|
+ private String careItem;
|
|
|
+ private String careDetail;
|
|
|
+ private String careResult;
|
|
|
+ private LocalDateTime careDate;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 7: 创建 ActionPracticeTask entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_practice_tasks")
|
|
|
+public class ActionPracticeTask {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long familyId;
|
|
|
+ private Long creatorId;
|
|
|
+ private Long assigneeId;
|
|
|
+ private String title;
|
|
|
+ private String description;
|
|
|
+ private String practiceType;
|
|
|
+ private Integer pointsReward;
|
|
|
+ private String status;
|
|
|
+ private LocalDateTime deadline;
|
|
|
+ private LocalDateTime completedAt;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 8: 创建 ActionCommunityPost entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_community_posts")
|
|
|
+public class ActionCommunityPost {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long userId;
|
|
|
+ private Long familyId;
|
|
|
+ private String title;
|
|
|
+ private String content;
|
|
|
+ private String imageUrl;
|
|
|
+ private String postType;
|
|
|
+ private Integer viewCount;
|
|
|
+ private Integer likeCount;
|
|
|
+ private Integer commentCount;
|
|
|
+ private String status;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 9: 创建 ActionCommunityComment entity**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.entity;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.annotation.IdType;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableId;
|
|
|
+import com.baomidou.mybatisplus.annotation.TableName;
|
|
|
+import lombok.Data;
|
|
|
+
|
|
|
+import java.time.LocalDateTime;
|
|
|
+
|
|
|
+@Data
|
|
|
+@TableName("action_community_comments")
|
|
|
+public class ActionCommunityComment {
|
|
|
+ @TableId(type = IdType.AUTO)
|
|
|
+ private Long id;
|
|
|
+ private Long postId;
|
|
|
+ private Long userId;
|
|
|
+ private Long parentId;
|
|
|
+ private String content;
|
|
|
+ private Integer likeCount;
|
|
|
+ private LocalDateTime createdAt;
|
|
|
+ private LocalDateTime updatedAt;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 10: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 4: 创建所有 Mapper
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: 17 mapper files (每个entity对应一个Mapper)
|
|
|
+
|
|
|
+- [ ] **Step 1: 创建 Body 域 Mapper**
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/BodyHealthMetricMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.BodyHealthMetric;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface BodyHealthMetricMapper extends BaseMapper<BodyHealthMetric> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/BodyNutritionLogMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.BodyNutritionLog;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface BodyNutritionLogMapper extends BaseMapper<BodyNutritionLog> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/BodyAntiAgingAssessmentMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.BodyAntiAgingAssessment;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface BodyAntiAgingAssessmentMapper extends BaseMapper<BodyAntiAgingAssessment> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/BodyExerciseLogMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.BodyExerciseLog;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface BodyExerciseLogMapper extends BaseMapper<BodyExerciseLog> {}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 创建 Mind 域 Mapper**
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/MindMoodLogMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.MindMoodLog;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface MindMoodLogMapper extends BaseMapper<MindMoodLog> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/MindPsychologicalAssessmentMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.MindPsychologicalAssessment;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface MindPsychologicalAssessmentMapper extends BaseMapper<MindPsychologicalAssessment> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/MindFamilyAtmosphereIndexMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.MindFamilyAtmosphereIndex;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface MindFamilyAtmosphereIndexMapper extends BaseMapper<MindFamilyAtmosphereIndex> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/MindMeditationSessionMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.MindMeditationSession;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface MindMeditationSessionMapper extends BaseMapper<MindMeditationSession> {}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建 Action 域 Mapper**
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionActivityMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionActivity;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionActivityMapper extends BaseMapper<ActionActivity> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionActivityRegistrationMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionActivityRegistration;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionActivityRegistrationMapper extends BaseMapper<ActionActivityRegistration> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionArticleMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionArticle;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionArticleMapper extends BaseMapper<ActionArticle> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionArticleCategoryMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionArticleCategory;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionArticleCategoryMapper extends BaseMapper<ActionArticleCategory> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionElderCarePlanMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionElderCarePlan;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionElderCarePlanMapper extends BaseMapper<ActionElderCarePlan> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionElderCareLogMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionElderCareLog;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionElderCareLogMapper extends BaseMapper<ActionElderCareLog> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionPracticeTaskMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionPracticeTask;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionPracticeTaskMapper extends BaseMapper<ActionPracticeTask> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionCommunityPostMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionCommunityPost;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionCommunityPostMapper extends BaseMapper<ActionCommunityPost> {}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/mapper/ActionCommunityCommentMapper.java
|
|
|
+package com.zxyj.mapper;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|
|
+import com.zxyj.entity.ActionCommunityComment;
|
|
|
+import org.apache.ibatis.annotations.Mapper;
|
|
|
+
|
|
|
+@Mapper
|
|
|
+public interface ActionCommunityCommentMapper extends BaseMapper<ActionCommunityComment> {}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 5: DatabaseInitializer 增加新表
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `zxyj-backend/src/main/java/com/zxyj/config/DatabaseInitializer.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 在 DatabaseInitializer 中添加 17 张新表的 CREATE TABLE 语句**
|
|
|
+
|
|
|
+在 DatabaseInitializer 的 init 方法中(现有建表语句之后),添加以下新表创建逻辑。遵循现有模式:`CREATE TABLE IF NOT EXISTS` + 基本字段 + `created_at/updated_at`。
|
|
|
+
|
|
|
+```java
|
|
|
+// === Body 域表 ===
|
|
|
+createTableIfNotExists("body_health_metrics", "CREATE TABLE IF NOT EXISTS `body_health_metrics` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`weight` DECIMAL(5,1) DEFAULT NULL COMMENT '体重kg'," +
|
|
|
+ "`blood_pressure_systolic` INT DEFAULT NULL COMMENT '收缩压'," +
|
|
|
+ "`blood_pressure_diastolic` INT DEFAULT NULL COMMENT '舒张压'," +
|
|
|
+ "`heart_rate` INT DEFAULT NULL COMMENT '心率'," +
|
|
|
+ "`sleep_hours` INT DEFAULT NULL COMMENT '睡眠时长(小时)'," +
|
|
|
+ "`sleep_quality` INT DEFAULT NULL COMMENT '睡眠质量1-5'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`record_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='健康指标记录'");
|
|
|
+
|
|
|
+createTableIfNotExists("body_nutrition_logs", "CREATE TABLE IF NOT EXISTS `body_nutrition_logs` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`water_ml` INT DEFAULT NULL COMMENT '饮水量ml'," +
|
|
|
+ "`calorie_intake` INT DEFAULT NULL COMMENT '热量摄入kcal'," +
|
|
|
+ "`protein_g` DECIMAL(5,1) DEFAULT NULL COMMENT '蛋白质g'," +
|
|
|
+ "`vitamin_c` DECIMAL(5,1) DEFAULT NULL COMMENT '维生素C mg'," +
|
|
|
+ "`vitamin_d` DECIMAL(5,1) DEFAULT NULL COMMENT '维生素D ug'," +
|
|
|
+ "`meal_type` VARCHAR(20) DEFAULT NULL COMMENT '餐次(breakfast/lunch/dinner/snack)'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`record_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='水营养记录'");
|
|
|
+
|
|
|
+createTableIfNotExists("body_anti_aging_assessments", "CREATE TABLE IF NOT EXISTS `body_anti_aging_assessments` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`guide_id` BIGINT DEFAULT NULL COMMENT '规划师ID'," +
|
|
|
+ "`assessment_type` VARCHAR(50) DEFAULT NULL COMMENT '评估类型'," +
|
|
|
+ "`cellular_age` INT DEFAULT NULL COMMENT '细胞年龄'," +
|
|
|
+ "`biological_age` INT DEFAULT NULL COMMENT '生物学年龄'," +
|
|
|
+ "`result_summary` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`result_detail` TEXT DEFAULT NULL," +
|
|
|
+ "`report_url` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/completed'," +
|
|
|
+ "`assessment_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='抗衰评估'");
|
|
|
+
|
|
|
+createTableIfNotExists("body_exercise_logs", "CREATE TABLE IF NOT EXISTS `body_exercise_logs` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`exercise_type` VARCHAR(50) NOT NULL COMMENT '运动类型'," +
|
|
|
+ "`duration_minutes` INT DEFAULT NULL COMMENT '时长(分钟)'," +
|
|
|
+ "`steps` INT DEFAULT NULL COMMENT '步数'," +
|
|
|
+ "`calories_burned` INT DEFAULT NULL COMMENT '消耗卡路里'," +
|
|
|
+ "`intensity` INT DEFAULT NULL COMMENT '强度1-5'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`exercise_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='运动记录'");
|
|
|
+
|
|
|
+// === Mind 域表 ===
|
|
|
+createTableIfNotExists("mind_mood_logs", "CREATE TABLE IF NOT EXISTS `mind_mood_logs` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`mood_score` INT NOT NULL COMMENT '心情分数1-10'," +
|
|
|
+ "`mood_label` VARCHAR(20) DEFAULT NULL COMMENT '心情标签(happy/sad/anxious/calm/angry)'," +
|
|
|
+ "`tags` VARCHAR(200) DEFAULT NULL COMMENT '自定义标签,分隔'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`weather` VARCHAR(20) DEFAULT NULL COMMENT '天气'," +
|
|
|
+ "`record_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='情绪日志'");
|
|
|
+
|
|
|
+createTableIfNotExists("mind_psychological_assessments", "CREATE TABLE IF NOT EXISTS `mind_psychological_assessments` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`guide_id` BIGINT DEFAULT NULL COMMENT '规划师ID'," +
|
|
|
+ "`assessment_type` VARCHAR(50) NOT NULL COMMENT '评估类型(SCL90/SDS/SAS等)'," +
|
|
|
+ "`total_score` INT DEFAULT NULL," +
|
|
|
+ "`result_level` VARCHAR(20) DEFAULT NULL COMMENT 'normal/mild/moderate/severe'," +
|
|
|
+ "`result_summary` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`result_detail` TEXT DEFAULT NULL," +
|
|
|
+ "`report_url` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'pending'," +
|
|
|
+ "`assessment_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='心理测评'");
|
|
|
+
|
|
|
+createTableIfNotExists("mind_family_atmosphere_indices", "CREATE TABLE IF NOT EXISTS `mind_family_atmosphere_indices` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`communication_score` INT DEFAULT NULL COMMENT '沟通评分1-100'," +
|
|
|
+ "`emotional_score` INT DEFAULT NULL COMMENT '情感评分1-100'," +
|
|
|
+ "`support_score` INT DEFAULT NULL COMMENT '支持评分1-100'," +
|
|
|
+ "`conflict_score` INT DEFAULT NULL COMMENT '冲突评分1-100(越高越好=冲突处理越好)'," +
|
|
|
+ "`overall_score` INT DEFAULT NULL COMMENT '综合评分1-100'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`record_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭氛围指数'");
|
|
|
+
|
|
|
+createTableIfNotExists("mind_meditation_sessions", "CREATE TABLE IF NOT EXISTS `mind_meditation_sessions` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`meditation_type` VARCHAR(30) DEFAULT NULL COMMENT '冥想类型(breathing/body-scan/guided)'," +
|
|
|
+ "`duration_minutes` INT NOT NULL COMMENT '时长(分钟)'," +
|
|
|
+ "`completion_rate` INT DEFAULT NULL COMMENT '完成率0-100'," +
|
|
|
+ "`audio_url` VARCHAR(500) DEFAULT NULL COMMENT '引导音频URL'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`session_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='冥想记录'");
|
|
|
+
|
|
|
+// === Action 域表 ===
|
|
|
+createTableIfNotExists("action_activities", "CREATE TABLE IF NOT EXISTS `action_activities` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`creator_id` BIGINT NOT NULL COMMENT '创建人ID'," +
|
|
|
+ "`title` VARCHAR(200) NOT NULL," +
|
|
|
+ "`description` TEXT DEFAULT NULL," +
|
|
|
+ "`cover_url` VARCHAR(500) DEFAULT NULL COMMENT '封面图'," +
|
|
|
+ "`activity_type` VARCHAR(30) DEFAULT NULL COMMENT 'online/offline/hybrid'," +
|
|
|
+ "`location` VARCHAR(200) DEFAULT NULL COMMENT '地点'," +
|
|
|
+ "`latitude` DECIMAL(10,7) DEFAULT NULL," +
|
|
|
+ "`longitude` DECIMAL(10,7) DEFAULT NULL," +
|
|
|
+ "`start_time` DATETIME NOT NULL," +
|
|
|
+ "`end_time` DATETIME NOT NULL," +
|
|
|
+ "`max_participants` INT DEFAULT NULL COMMENT '最大参与人数'," +
|
|
|
+ "`current_participants` INT DEFAULT 0," +
|
|
|
+ "`fee` DECIMAL(10,2) DEFAULT 0 COMMENT '费用'," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/published/cancelled/ended'," +
|
|
|
+ "`points_reward` INT DEFAULT 0 COMMENT '参与奖励积分'," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='活动'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_activity_registrations", "CREATE TABLE IF NOT EXISTS `action_activity_registrations` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`activity_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'registered' COMMENT 'registered/cancelled/attended'," +
|
|
|
+ "`note` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`registered_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='活动报名'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_articles", "CREATE TABLE IF NOT EXISTS `action_articles` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`author_id` BIGINT NOT NULL," +
|
|
|
+ "`category_id` BIGINT DEFAULT NULL," +
|
|
|
+ "`title` VARCHAR(200) NOT NULL," +
|
|
|
+ "`summary` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`content` LONGTEXT DEFAULT NULL," +
|
|
|
+ "`cover_url` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`article_type` VARCHAR(30) DEFAULT 'article' COMMENT 'article/video/infographic'," +
|
|
|
+ "`view_count` INT DEFAULT 0," +
|
|
|
+ "`like_count` INT DEFAULT 0," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'draft' COMMENT 'draft/published/archived'," +
|
|
|
+ "`published_at` DATETIME DEFAULT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章/科普'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_article_categories", "CREATE TABLE IF NOT EXISTS `action_article_categories` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`name` VARCHAR(50) NOT NULL," +
|
|
|
+ "`icon` VARCHAR(50) DEFAULT NULL," +
|
|
|
+ "`description` VARCHAR(200) DEFAULT NULL," +
|
|
|
+ "`sort_order` INT DEFAULT 0," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='文章分类'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_elder_care_plans", "CREATE TABLE IF NOT EXISTS `action_elder_care_plans` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`creator_id` BIGINT NOT NULL," +
|
|
|
+ "`elder_name` VARCHAR(50) NOT NULL COMMENT '长者姓名'," +
|
|
|
+ "`elder_age` INT DEFAULT NULL," +
|
|
|
+ "`health_condition` VARCHAR(500) DEFAULT NULL COMMENT '健康状况'," +
|
|
|
+ "`care_level` VARCHAR(20) DEFAULT NULL COMMENT 'care-level-1/2/3'," +
|
|
|
+ "`care_items` TEXT DEFAULT NULL COMMENT '关怀项目JSON'," +
|
|
|
+ "`emergency_contact` VARCHAR(50) DEFAULT NULL COMMENT '紧急联系人'," +
|
|
|
+ "`emergency_phone` VARCHAR(20) DEFAULT NULL COMMENT '紧急联系电话'," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'active' COMMENT 'active/completed/archived'," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='长者关怀计划'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_elder_care_logs", "CREATE TABLE IF NOT EXISTS `action_elder_care_logs` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`plan_id` BIGINT NOT NULL," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`caregiver_id` BIGINT NOT NULL COMMENT '照护人ID'," +
|
|
|
+ "`care_item` VARCHAR(100) NOT NULL COMMENT '关怀项目'," +
|
|
|
+ "`care_detail` TEXT DEFAULT NULL COMMENT '照护详情'," +
|
|
|
+ "`care_result` VARCHAR(200) DEFAULT NULL COMMENT '照护结果'," +
|
|
|
+ "`care_date` DATETIME NOT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='长者关怀日志'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_practice_tasks", "CREATE TABLE IF NOT EXISTS `action_practice_tasks` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`family_id` BIGINT NOT NULL," +
|
|
|
+ "`creator_id` BIGINT NOT NULL," +
|
|
|
+ "`assignee_id` BIGINT DEFAULT NULL COMMENT '执行人ID'," +
|
|
|
+ "`title` VARCHAR(200) NOT NULL," +
|
|
|
+ "`description` VARCHAR(500) DEFAULT NULL," +
|
|
|
+ "`practice_type` VARCHAR(30) DEFAULT NULL COMMENT 'relationship/parenting/elder-care/community'," +
|
|
|
+ "`points_reward` INT DEFAULT 0 COMMENT '完成积分奖励'," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'pending' COMMENT 'pending/completed/cancelled'," +
|
|
|
+ "`deadline` DATETIME DEFAULT NULL," +
|
|
|
+ "`completed_at` DATETIME DEFAULT NULL," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='践行任务'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_community_posts", "CREATE TABLE IF NOT EXISTS `action_community_posts` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`family_id` BIGINT DEFAULT NULL," +
|
|
|
+ "`title` VARCHAR(200) NOT NULL," +
|
|
|
+ "`content` TEXT NOT NULL," +
|
|
|
+ "`image_url` VARCHAR(500) DEFAULT NULL COMMENT '图片URL,分隔多张'," +
|
|
|
+ "`post_type` VARCHAR(30) DEFAULT 'sharing' COMMENT 'sharing/question/experience'," +
|
|
|
+ "`view_count` INT DEFAULT 0," +
|
|
|
+ "`like_count` INT DEFAULT 0," +
|
|
|
+ "`comment_count` INT DEFAULT 0," +
|
|
|
+ "`status` VARCHAR(20) DEFAULT 'published' COMMENT 'published/hidden/deleted'," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='社区帖子'");
|
|
|
+
|
|
|
+createTableIfNotExists("action_community_comments", "CREATE TABLE IF NOT EXISTS `action_community_comments` (" +
|
|
|
+ "`id` BIGINT PRIMARY KEY AUTO_INCREMENT," +
|
|
|
+ "`post_id` BIGINT NOT NULL," +
|
|
|
+ "`user_id` BIGINT NOT NULL," +
|
|
|
+ "`parent_id` BIGINT DEFAULT NULL COMMENT '父评论ID(回复)'," +
|
|
|
+ "`content` VARCHAR(500) NOT NULL," +
|
|
|
+ "`like_count` INT DEFAULT 0," +
|
|
|
+ "`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP," +
|
|
|
+ "`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" +
|
|
|
+ ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='社区评论'");
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: PointsLog 表增加 domain 字段**
|
|
|
+
|
|
|
+在 DatabaseInitializer 的现有 points_log 表创建之后,添加 ALTER 语句:
|
|
|
+
|
|
|
+```java
|
|
|
+// PointsLog 扩展:增加 domain 字段支持四域积分来源
|
|
|
+try {
|
|
|
+ jdbcTemplate.execute("ALTER TABLE points_log ADD COLUMN `domain` VARCHAR(20) DEFAULT 'wisdom' COMMENT '积分来源域(body/mind/wisdom/action)'");
|
|
|
+} catch (Exception e) {
|
|
|
+ // 字段已存在,忽略
|
|
|
+ log.info("points_log.domain already exists");
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 启动验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn spring-boot:run` (确认启动不报错,新表自动创建)
|
|
|
+
|
|
|
+Expected: Application starts successfully, logs show new tables created
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 6: 创建 Service 骨架
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: 13 service files (每个域核心service)
|
|
|
+
|
|
|
+- [ ] **Step 1: 创建 Body 域 Service**
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/BodyHealthService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.BodyHealthMetric;
|
|
|
+import com.zxyj.mapper.BodyHealthMetricMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class BodyHealthService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private BodyHealthMetricMapper bodyHealthMetricMapper;
|
|
|
+
|
|
|
+ public BodyHealthMetric createRecord(BodyHealthMetric record) {
|
|
|
+ bodyHealthMetricMapper.insert(record);
|
|
|
+ return record;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<BodyHealthMetric> getRecords(Long userId, Integer limit) {
|
|
|
+ return bodyHealthMetricMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<BodyHealthMetric>()
|
|
|
+ .eq(BodyHealthMetric::getUserId, userId)
|
|
|
+ .orderByDesc(BodyHealthMetric::getRecordDate)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ public BodyHealthMetric getLatestRecord(Long userId) {
|
|
|
+ return bodyHealthMetricMapper.selectOne(
|
|
|
+ new LambdaQueryWrapper<BodyHealthMetric>()
|
|
|
+ .eq(BodyHealthMetric::getUserId, userId)
|
|
|
+ .orderByDesc(BodyHealthMetric::getRecordDate)
|
|
|
+ .last("LIMIT 1")
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/BodyNutritionService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.BodyNutritionLog;
|
|
|
+import com.zxyj.mapper.BodyNutritionLogMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class BodyNutritionService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private BodyNutritionLogMapper bodyNutritionLogMapper;
|
|
|
+
|
|
|
+ public BodyNutritionLog createLog(BodyNutritionLog log) {
|
|
|
+ bodyNutritionLogMapper.insert(log);
|
|
|
+ return log;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<BodyNutritionLog> getLogs(Long userId, Integer limit) {
|
|
|
+ return bodyNutritionLogMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<BodyNutritionLog>()
|
|
|
+ .eq(BodyNutritionLog::getUserId, userId)
|
|
|
+ .orderByDesc(BodyNutritionLog::getRecordDate)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/BodyAntiAgingService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.BodyAntiAgingAssessment;
|
|
|
+import com.zxyj.mapper.BodyAntiAgingAssessmentMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class BodyAntiAgingService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private BodyAntiAgingAssessmentMapper bodyAntiAgingAssessmentMapper;
|
|
|
+
|
|
|
+ public BodyAntiAgingAssessment createAssessment(BodyAntiAgingAssessment assessment) {
|
|
|
+ bodyAntiAgingAssessmentMapper.insert(assessment);
|
|
|
+ return assessment;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<BodyAntiAgingAssessment> getAssessments(Long userId) {
|
|
|
+ return bodyAntiAgingAssessmentMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<BodyAntiAgingAssessment>()
|
|
|
+ .eq(BodyAntiAgingAssessment::getUserId, userId)
|
|
|
+ .orderByDesc(BodyAntiAgingAssessment::getAssessmentDate)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/BodyExerciseService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.BodyExerciseLog;
|
|
|
+import com.zxyj.mapper.BodyExerciseLogMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class BodyExerciseService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private BodyExerciseLogMapper bodyExerciseLogMapper;
|
|
|
+
|
|
|
+ public BodyExerciseLog createLog(BodyExerciseLog log) {
|
|
|
+ bodyExerciseLogMapper.insert(log);
|
|
|
+ return log;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<BodyExerciseLog> getLogs(Long userId, Integer limit) {
|
|
|
+ return bodyExerciseLogMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<BodyExerciseLog>()
|
|
|
+ .eq(BodyExerciseLog::getUserId, userId)
|
|
|
+ .orderByDesc(BodyExerciseLog::getExerciseDate)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 创建 Mind 域 Service**
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/MindMoodService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.MindMoodLog;
|
|
|
+import com.zxyj.mapper.MindMoodLogMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class MindMoodService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MindMoodLogMapper mindMoodLogMapper;
|
|
|
+
|
|
|
+ public MindMoodLog createLog(MindMoodLog log) {
|
|
|
+ mindMoodLogMapper.insert(log);
|
|
|
+ return log;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<MindMoodLog> getLogs(Long userId, Integer limit) {
|
|
|
+ return mindMoodLogMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MindMoodLog>()
|
|
|
+ .eq(MindMoodLog::getUserId, userId)
|
|
|
+ .orderByDesc(MindMoodLog::getRecordDate)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/MindAssessmentService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.MindPsychologicalAssessment;
|
|
|
+import com.zxyj.mapper.MindPsychologicalAssessmentMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class MindAssessmentService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MindPsychologicalAssessmentMapper mindPsychologicalAssessmentMapper;
|
|
|
+
|
|
|
+ public MindPsychologicalAssessment createAssessment(MindPsychologicalAssessment assessment) {
|
|
|
+ mindPsychologicalAssessmentMapper.insert(assessment);
|
|
|
+ return assessment;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<MindPsychologicalAssessment> getAssessments(Long userId) {
|
|
|
+ return mindPsychologicalAssessmentMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MindPsychologicalAssessment>()
|
|
|
+ .eq(MindPsychologicalAssessment::getUserId, userId)
|
|
|
+ .orderByDesc(MindPsychologicalAssessment::getAssessmentDate)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/MindFamilyAtmosphereService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.MindFamilyAtmosphereIndex;
|
|
|
+import com.zxyj.mapper.MindFamilyAtmosphereIndexMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class MindFamilyAtmosphereService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MindFamilyAtmosphereIndexMapper mindFamilyAtmosphereIndexMapper;
|
|
|
+
|
|
|
+ public MindFamilyAtmosphereIndex createIndex(MindFamilyAtmosphereIndex index) {
|
|
|
+ mindFamilyAtmosphereIndexMapper.insert(index);
|
|
|
+ return index;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<MindFamilyAtmosphereIndex> getIndices(Long familyId) {
|
|
|
+ return mindFamilyAtmosphereIndexMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MindFamilyAtmosphereIndex>()
|
|
|
+ .eq(MindFamilyAtmosphereIndex::getFamilyId, familyId)
|
|
|
+ .orderByDesc(MindFamilyAtmosphereIndex::getRecordDate)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/MindMeditationService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.MindMeditationSession;
|
|
|
+import com.zxyj.mapper.MindMeditationSessionMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class MindMeditationService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MindMeditationSessionMapper mindMeditationSessionMapper;
|
|
|
+
|
|
|
+ public MindMeditationSession createSession(MindMeditationSession session) {
|
|
|
+ mindMeditationSessionMapper.insert(session);
|
|
|
+ return session;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<MindMeditationSession> getSessions(Long userId, Integer limit) {
|
|
|
+ return mindMeditationSessionMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<MindMeditationSession>()
|
|
|
+ .eq(MindMeditationSession::getUserId, userId)
|
|
|
+ .orderByDesc(MindMeditationSession::getSessionDate)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建 Action 域 Service**
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/ActionActivityService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.ActionActivity;
|
|
|
+import com.zxyj.entity.ActionActivityRegistration;
|
|
|
+import com.zxyj.mapper.ActionActivityMapper;
|
|
|
+import com.zxyj.mapper.ActionActivityRegistrationMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ActionActivityService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionActivityMapper actionActivityMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionActivityRegistrationMapper actionActivityRegistrationMapper;
|
|
|
+
|
|
|
+ public ActionActivity createActivity(ActionActivity activity) {
|
|
|
+ actionActivityMapper.insert(activity);
|
|
|
+ return activity;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionActivity> getPublishedActivities(Integer limit) {
|
|
|
+ return actionActivityMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ActionActivity>()
|
|
|
+ .eq(ActionActivity::getStatus, "published")
|
|
|
+ .orderByDesc(ActionActivity::getStartTime)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ public ActionActivity getById(Long id) {
|
|
|
+ return actionActivityMapper.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional
|
|
|
+ public ActionActivityRegistration register(Long activityId, Long userId, Long familyId) {
|
|
|
+ ActionActivityRegistration registration = new ActionActivityRegistration();
|
|
|
+ registration.setActivityId(activityId);
|
|
|
+ registration.setUserId(userId);
|
|
|
+ registration.setFamilyId(familyId);
|
|
|
+ registration.setStatus("registered");
|
|
|
+ actionActivityRegistrationMapper.insert(registration);
|
|
|
+ // Increment current_participants
|
|
|
+ ActionActivity activity = actionActivityMapper.selectById(activityId);
|
|
|
+ if (activity != null) {
|
|
|
+ activity.setCurrentParticipants(activity.getCurrentParticipants() + 1);
|
|
|
+ actionActivityMapper.updateById(activity);
|
|
|
+ }
|
|
|
+ return registration;
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/ActionArticleService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.ActionArticle;
|
|
|
+import com.zxyj.mapper.ActionArticleMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ActionArticleService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionArticleMapper actionArticleMapper;
|
|
|
+
|
|
|
+ public ActionArticle createArticle(ActionArticle article) {
|
|
|
+ actionArticleMapper.insert(article);
|
|
|
+ return article;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionArticle> getPublishedArticles(Long categoryId, Integer limit) {
|
|
|
+ LambdaQueryWrapper<ActionArticle> wrapper = new LambdaQueryWrapper<ActionArticle>()
|
|
|
+ .eq(ActionArticle::getStatus, "published")
|
|
|
+ .orderByDesc(ActionArticle::getPublishedAt)
|
|
|
+ .last("LIMIT " + limit);
|
|
|
+ if (categoryId != null) {
|
|
|
+ wrapper.eq(ActionArticle::getCategoryId, categoryId);
|
|
|
+ }
|
|
|
+ return actionArticleMapper.selectList(wrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ public ActionArticle getById(Long id) {
|
|
|
+ return actionArticleMapper.selectById(id);
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/ActionElderCareService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.ActionElderCarePlan;
|
|
|
+import com.zxyj.entity.ActionElderCareLog;
|
|
|
+import com.zxyj.mapper.ActionElderCarePlanMapper;
|
|
|
+import com.zxyj.mapper.ActionElderCareLogMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ActionElderCareService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionElderCarePlanMapper actionElderCarePlanMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionElderCareLogMapper actionElderCareLogMapper;
|
|
|
+
|
|
|
+ public ActionElderCarePlan createPlan(ActionElderCarePlan plan) {
|
|
|
+ actionElderCarePlanMapper.insert(plan);
|
|
|
+ return plan;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionElderCarePlan> getPlans(Long familyId) {
|
|
|
+ return actionElderCarePlanMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ActionElderCarePlan>()
|
|
|
+ .eq(ActionElderCarePlan::getFamilyId, familyId)
|
|
|
+ .orderByDesc(ActionElderCarePlan::getCreatedAt)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ public ActionElderCareLog createCareLog(ActionElderCareLog log) {
|
|
|
+ actionElderCareLogMapper.insert(log);
|
|
|
+ return log;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionElderCareLog> getCareLogs(Long planId) {
|
|
|
+ return actionElderCareLogMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ActionElderCareLog>()
|
|
|
+ .eq(ActionElderCareLog::getPlanId, planId)
|
|
|
+ .orderByDesc(ActionElderCareLog::getCareDate)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/ActionPracticeService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.ActionPracticeTask;
|
|
|
+import com.zxyj.mapper.ActionPracticeTaskMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ActionPracticeService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionPracticeTaskMapper actionPracticeTaskMapper;
|
|
|
+
|
|
|
+ public ActionPracticeTask createTask(ActionPracticeTask task) {
|
|
|
+ actionPracticeTaskMapper.insert(task);
|
|
|
+ return task;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionPracticeTask> getTasks(Long familyId) {
|
|
|
+ return actionPracticeTaskMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ActionPracticeTask>()
|
|
|
+ .eq(ActionPracticeTask::getFamilyId, familyId)
|
|
|
+ .orderByDesc(ActionPracticeTask::getCreatedAt)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+```java
|
|
|
+// zxyj-backend/src/main/java/com/zxyj/service/ActionCommunityService.java
|
|
|
+package com.zxyj.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.zxyj.entity.ActionCommunityPost;
|
|
|
+import com.zxyj.entity.ActionCommunityComment;
|
|
|
+import com.zxyj.mapper.ActionCommunityPostMapper;
|
|
|
+import com.zxyj.mapper.ActionCommunityCommentMapper;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+@Service
|
|
|
+public class ActionCommunityService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionCommunityPostMapper actionCommunityPostMapper;
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionCommunityCommentMapper actionCommunityCommentMapper;
|
|
|
+
|
|
|
+ public ActionCommunityPost createPost(ActionCommunityPost post) {
|
|
|
+ actionCommunityPostMapper.insert(post);
|
|
|
+ return post;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionCommunityPost> getPosts(Integer limit) {
|
|
|
+ return actionCommunityPostMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ActionCommunityPost>()
|
|
|
+ .eq(ActionCommunityPost::getStatus, "published")
|
|
|
+ .orderByDesc(ActionCommunityPost::getCreatedAt)
|
|
|
+ .last("LIMIT " + limit)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ public ActionCommunityComment createComment(ActionCommunityComment comment) {
|
|
|
+ actionCommunityCommentMapper.insert(comment);
|
|
|
+ // Increment post comment count
|
|
|
+ ActionCommunityPost post = actionCommunityPostMapper.selectById(comment.getPostId());
|
|
|
+ if (post != null) {
|
|
|
+ post.setCommentCount(post.getCommentCount() + 1);
|
|
|
+ actionCommunityPostMapper.updateById(post);
|
|
|
+ }
|
|
|
+ return comment;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<ActionCommunityComment> getComments(Long postId) {
|
|
|
+ return actionCommunityCommentMapper.selectList(
|
|
|
+ new LambdaQueryWrapper<ActionCommunityComment>()
|
|
|
+ .eq(ActionCommunityComment::getPostId, postId)
|
|
|
+ .orderByAsc(ActionCommunityComment::getCreatedAt)
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 7: 创建后端 Controller 骨架
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/controller/body/BodyHealthController.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/controller/mind/MindMoodController.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/controller/action/ActionController.java`
|
|
|
+- Create: `zxyj-backend/src/main/java/com/zxyj/controller/action/ActionArticleController.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 创建 BodyHealthController**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.controller.body;
|
|
|
+
|
|
|
+import com.zxyj.common.Result;
|
|
|
+import com.zxyj.entity.BodyHealthMetric;
|
|
|
+import com.zxyj.service.BodyHealthService;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/body/health")
|
|
|
+public class BodyHealthController {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private BodyHealthService bodyHealthService;
|
|
|
+
|
|
|
+ @PostMapping("/create")
|
|
|
+ public Result<BodyHealthMetric> createRecord(@RequestBody BodyHealthMetric record) {
|
|
|
+ return Result.success(bodyHealthService.createRecord(record));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/list")
|
|
|
+ public Result<List<BodyHealthMetric>> getRecords(@RequestBody Map<String, Object> params) {
|
|
|
+ Long userId = Long.valueOf(params.get("userId").toString());
|
|
|
+ Integer limit = params.containsKey("limit") ? Integer.valueOf(params.get("limit").toString()) : 30;
|
|
|
+ return Result.success(bodyHealthService.getRecords(userId, limit));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/latest")
|
|
|
+ public Result<BodyHealthMetric> getLatestRecord(@RequestBody Map<String, Object> params) {
|
|
|
+ Long userId = Long.valueOf(params.get("userId").toString());
|
|
|
+ return Result.success(bodyHealthService.getLatestRecord(userId));
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 创建 MindMoodController**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.controller.mind;
|
|
|
+
|
|
|
+import com.zxyj.common.Result;
|
|
|
+import com.zxyj.entity.MindMoodLog;
|
|
|
+import com.zxyj.service.MindMoodService;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/mind/mood")
|
|
|
+public class MindMoodController {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private MindMoodService mindMoodService;
|
|
|
+
|
|
|
+ @PostMapping("/create")
|
|
|
+ public Result<MindMoodLog> createLog(@RequestBody MindMoodLog log) {
|
|
|
+ return Result.success(mindMoodService.createLog(log));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/list")
|
|
|
+ public Result<List<MindMoodLog>> getLogs(@RequestBody Map<String, Object> params) {
|
|
|
+ Long userId = Long.valueOf(params.get("userId").toString());
|
|
|
+ Integer limit = params.containsKey("limit") ? Integer.valueOf(params.get("limit").toString()) : 30;
|
|
|
+ return Result.success(mindMoodService.getLogs(userId, limit));
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建 ActionController (活动+社区)**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.controller.action;
|
|
|
+
|
|
|
+import com.zxyj.common.Result;
|
|
|
+import com.zxyj.entity.ActionActivity;
|
|
|
+import com.zxyj.entity.ActionActivityRegistration;
|
|
|
+import com.zxyj.service.ActionActivityService;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/action/activity")
|
|
|
+public class ActionController {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionActivityService actionActivityService;
|
|
|
+
|
|
|
+ @PostMapping("/create")
|
|
|
+ public Result<ActionActivity> createActivity(@RequestBody ActionActivity activity) {
|
|
|
+ return Result.success(actionActivityService.createActivity(activity));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/list")
|
|
|
+ public Result<List<ActionActivity>> getActivities(@RequestBody Map<String, Object> params) {
|
|
|
+ Integer limit = params.containsKey("limit") ? Integer.valueOf(params.get("limit").toString()) : 20;
|
|
|
+ return Result.success(actionActivityService.getPublishedActivities(limit));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/detail")
|
|
|
+ public Result<ActionActivity> getDetail(@RequestBody Map<String, Object> params) {
|
|
|
+ Long id = Long.valueOf(params.get("id").toString());
|
|
|
+ return Result.success(actionActivityService.getById(id));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/register")
|
|
|
+ public Result<ActionActivityRegistration> register(@RequestBody Map<String, Object> params) {
|
|
|
+ Long activityId = Long.valueOf(params.get("activityId").toString());
|
|
|
+ Long userId = Long.valueOf(params.get("userId").toString());
|
|
|
+ Long familyId = Long.valueOf(params.get("familyId").toString());
|
|
|
+ return Result.success(actionActivityService.register(activityId, userId, familyId));
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 4: 创建 ActionArticleController**
|
|
|
+
|
|
|
+```java
|
|
|
+package com.zxyj.controller.action;
|
|
|
+
|
|
|
+import com.zxyj.common.Result;
|
|
|
+import com.zxyj.entity.ActionArticle;
|
|
|
+import com.zxyj.service.ActionArticleService;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.annotation.Resource;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@RestController
|
|
|
+@RequestMapping("/action/article")
|
|
|
+public class ActionArticleController {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private ActionArticleService actionArticleService;
|
|
|
+
|
|
|
+ @PostMapping("/create")
|
|
|
+ public Result<ActionArticle> createArticle(@RequestBody ActionArticle article) {
|
|
|
+ return Result.success(actionArticleService.createArticle(article));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/list")
|
|
|
+ public Result<List<ActionArticle>> getArticles(@RequestBody Map<String, Object> params) {
|
|
|
+ Long categoryId = params.containsKey("categoryId") ? Long.valueOf(params.get("categoryId").toString()) : null;
|
|
|
+ Integer limit = params.containsKey("limit") ? Integer.valueOf(params.get("limit").toString()) : 20;
|
|
|
+ return Result.success(actionArticleService.getPublishedArticles(categoryId, limit));
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/detail")
|
|
|
+ public Result<ActionArticle> getDetail(@RequestBody Map<String, Object> params) {
|
|
|
+ Long id = Long.valueOf(params.get("id").toString());
|
|
|
+ return Result.success(actionArticleService.getById(id));
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 5: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 8: PointsLog Entity 增加 domain 字段
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `zxyj-backend/src/main/java/com/zxyj/entity/PointsLog.java`
|
|
|
+
|
|
|
+- [ ] **Step 1: 在 PointsLog.java 中增加 domain 字段**
|
|
|
+
|
|
|
+在现有 PointsLog 实体中添加:
|
|
|
+
|
|
|
+```java
|
|
|
+private String domain; // 积分来源域: body/mind/wisdom/action,默认 "wisdom"
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 编译验证**
|
|
|
+
|
|
|
+Run: `cd zxyj-backend && mvn compile -q`
|
|
|
+
|
|
|
+Expected: BUILD SUCCESS
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+### Task 9: 前端首页四象限重构
|
|
|
+
|
|
|
+**Files:**
|
|
|
+- Modify: `zxyj-frontend/pages/index/index.vue`
|
|
|
+- Modify: `zxyj-frontend/pages/index/parent-index.vue`
|
|
|
+- Modify: `zxyj-frontend/pages/index/child-index.vue`
|
|
|
+- Modify: `zxyj-frontend/pages.json`
|
|
|
+- Modify: `zxyj-frontend/utils/api.js`
|
|
|
+- Modify: `zxyj-frontend/store/index.js`
|
|
|
+
|
|
|
+- [ ] **Step 1: 修改 pages.json — 注册新页面路径 + 调整tabBar**
|
|
|
+
|
|
|
+在 `pages` 数组中新增(在现有页面之后):
|
|
|
+
|
|
|
+```json
|
|
|
+{
|
|
|
+ "path": "pages/body/index",
|
|
|
+ "style": { "navigationBarTitleText": "身·细胞抗衰" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/body/health-metric",
|
|
|
+ "style": { "navigationBarTitleText": "健康指标" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/body/nutrition-log",
|
|
|
+ "style": { "navigationBarTitleText": "水营养追踪" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/body/anti-aging",
|
|
|
+ "style": { "navigationBarTitleText": "抗衰评估" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/body/exercise-log",
|
|
|
+ "style": { "navigationBarTitleText": "运动记录" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/mind/index",
|
|
|
+ "style": { "navigationBarTitleText": "心·心理情绪" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/mind/mood-log",
|
|
|
+ "style": { "navigationBarTitleText": "情绪日志" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/mind/assessment",
|
|
|
+ "style": { "navigationBarTitleText": "心理测评" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/mind/family-atmosphere",
|
|
|
+ "style": { "navigationBarTitleText": "家庭氛围" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/mind/meditation",
|
|
|
+ "style": { "navigationBarTitleText": "冥想放松" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/index",
|
|
|
+ "style": { "navigationBarTitleText": "行·关系践行" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/activity-list",
|
|
|
+ "style": { "navigationBarTitleText": "活动列表" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/activity-detail",
|
|
|
+ "style": { "navigationBarTitleText": "活动详情" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/article-list",
|
|
|
+ "style": { "navigationBarTitleText": "文章科普" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/article-detail",
|
|
|
+ "style": { "navigationBarTitleText": "文章详情" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/elder-care",
|
|
|
+ "style": { "navigationBarTitleText": "长者关怀" }
|
|
|
+},
|
|
|
+{
|
|
|
+ "path": "pages/action/community",
|
|
|
+ "style": { "navigationBarTitleText": "社区互动" }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+修改 tabBar(保留4-tab,调整"任务"和"心愿单"为域入口):
|
|
|
+
|
|
|
+```json
|
|
|
+"tabBar": {
|
|
|
+ "color": "#999999",
|
|
|
+ "selectedColor": "#4A90D9",
|
|
|
+ "backgroundColor": "#ffffff",
|
|
|
+ "borderStyle": "black",
|
|
|
+ "list": [
|
|
|
+ {
|
|
|
+ "pagePath": "pages/index/index",
|
|
|
+ "text": "首页",
|
|
|
+ "iconPath": "static/tab-home.png",
|
|
|
+ "selectedIconPath": "static/tab-home-active.png"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "pagePath": "pages/tasks/tasks",
|
|
|
+ "text": "智·成长",
|
|
|
+ "iconPath": "static/tab-wisdom.png",
|
|
|
+ "selectedIconPath": "static/tab-wisdom-active.png"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "pagePath": "pages/rewards/rewards",
|
|
|
+ "text": "行·实践",
|
|
|
+ "iconPath": "static/tab-action.png",
|
|
|
+ "selectedIconPath": "static/tab-action-active.png"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ "pagePath": "pages/profile/profile",
|
|
|
+ "text": "我的",
|
|
|
+ "iconPath": "static/tab-me.png",
|
|
|
+ "selectedIconPath": "static/tab-me-active.png"
|
|
|
+ }
|
|
|
+ ]
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 2: 修改 index.vue — 增加四象限入口组件**
|
|
|
+
|
|
|
+在 `parent-index.vue` 和 `child-index.vue` 的模板中,在现有内容上方添加四象限矩阵区域:
|
|
|
+
|
|
|
+```vue
|
|
|
+<!-- 四象限入口 -->
|
|
|
+<view class="domain-matrix">
|
|
|
+ <view class="domain-title">溪福俱乐部 · 身心智行</view>
|
|
|
+ <view class="domain-grid">
|
|
|
+ <view class="domain-item domain-body" @click="navigateToDomain('body')">
|
|
|
+ <view class="domain-icon">🧬</view>
|
|
|
+ <view class="domain-name">身 · 细胞抗衰</view>
|
|
|
+ <view class="domain-desc">健康指标·运动·抗衰</view>
|
|
|
+ </view>
|
|
|
+ <view class="domain-item domain-mind" @click="navigateToDomain('mind')">
|
|
|
+ <view class="domain-icon">🧠</view>
|
|
|
+ <view class="domain-name">心 · 心理情绪</view>
|
|
|
+ <view class="domain-desc">情绪·测评·冥想</view>
|
|
|
+ </view>
|
|
|
+ <view class="domain-item domain-wisdom" @click="navigateToDomain('wisdom')">
|
|
|
+ <view class="domain-icon">📚</view>
|
|
|
+ <view class="domain-name">智 · 教育成长</view>
|
|
|
+ <view class="domain-desc">任务·积分·测评</view>
|
|
|
+ </view>
|
|
|
+ <view class="domain-item domain-action" @click="navigateToDomain('action')">
|
|
|
+ <view class="domain-icon">🤝</view>
|
|
|
+ <view class="domain-name">行 · 关系践行</view>
|
|
|
+ <view class="domain-desc">活动·科普·关怀</view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</view>
|
|
|
+```
|
|
|
+
|
|
|
+在 `parent-index.vue` 和 `child-index.vue` 的 methods 中添加:
|
|
|
+
|
|
|
+```javascript
|
|
|
+navigateToDomain(domain) {
|
|
|
+ const routes = {
|
|
|
+ body: '/pages/body/index',
|
|
|
+ mind: '/pages/mind/index',
|
|
|
+ wisdom: '/pages/tasks/tasks',
|
|
|
+ action: '/pages/action/index'
|
|
|
+ };
|
|
|
+ const url = routes[domain];
|
|
|
+ if (domain === 'wisdom') {
|
|
|
+ uni.switchTab({ url });
|
|
|
+ } else {
|
|
|
+ uni.navigateTo({ url });
|
|
|
+ }
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+在 style 中添加:
|
|
|
+
|
|
|
+```scss
|
|
|
+.domain-matrix {
|
|
|
+ padding: 20rpx 30rpx;
|
|
|
+ background: linear-gradient(135deg, #f5f7fa 0%, #e8ecf1 100%);
|
|
|
+ border-radius: 20rpx;
|
|
|
+ margin: 20rpx;
|
|
|
+}
|
|
|
+.domain-title {
|
|
|
+ font-size: 32rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #333;
|
|
|
+ text-align: center;
|
|
|
+ margin-bottom: 20rpx;
|
|
|
+}
|
|
|
+.domain-grid {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+.domain-item {
|
|
|
+ width: 48%;
|
|
|
+ padding: 30rpx 20rpx;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ margin-bottom: 16rpx;
|
|
|
+ text-align: center;
|
|
|
+ box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
|
|
|
+}
|
|
|
+.domain-body {
|
|
|
+ background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%);
|
|
|
+}
|
|
|
+.domain-mind {
|
|
|
+ background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%);
|
|
|
+}
|
|
|
+.domain-wisdom {
|
|
|
+ background: linear-gradient(135deg, #fccb90 0%, #d57eeb 100%);
|
|
|
+}
|
|
|
+.domain-action {
|
|
|
+ background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
|
|
|
+}
|
|
|
+.domain-icon {
|
|
|
+ font-size: 60rpx;
|
|
|
+ margin-bottom: 10rpx;
|
|
|
+}
|
|
|
+.domain-name {
|
|
|
+ font-size: 28rpx;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #fff;
|
|
|
+ margin-bottom: 6rpx;
|
|
|
+}
|
|
|
+.domain-desc {
|
|
|
+ font-size: 22rpx;
|
|
|
+ color: rgba(255, 255, 255, 0.85);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 3: 创建各域首页占位页面**
|
|
|
+
|
|
|
+创建以下空壳页面(每个域首页只含标题和功能列表入口):
|
|
|
+
|
|
|
+`pages/body/index.vue`:
|
|
|
+```vue
|
|
|
+<template>
|
|
|
+ <view class="domain-page">
|
|
|
+ <view class="domain-header domain-header-body">
|
|
|
+ <view class="domain-header-icon">🧬</view>
|
|
|
+ <view class="domain-header-title">身 · 细胞抗衰</view>
|
|
|
+ </view>
|
|
|
+ <view class="feature-list">
|
|
|
+ <view class="feature-item" @click="navigateTo('/pages/body/health-metric')">
|
|
|
+ <text class="feature-name">健康指标记录</text>
|
|
|
+ <text class="feature-arrow">›</text>
|
|
|
+ </view>
|
|
|
+ <view class="feature-item" @click="navigateTo('/pages/body/nutrition-log')">
|
|
|
+ <text class="feature-name">水营养追踪</text>
|
|
|
+ <text class="feature-arrow">›</text>
|
|
|
+ </view>
|
|
|
+ <view class="feature-item" @click="navigateTo('/pages/body/anti-aging')">
|
|
|
+ <text class="feature-name">抗衰评估</text>
|
|
|
+ <text class="feature-arrow">›</text>
|
|
|
+ </view>
|
|
|
+ <view class="feature-item" @click="navigateTo('/pages/body/exercise-log')">
|
|
|
+ <text class="feature-name">运动记录</text>
|
|
|
+ <text class="feature-arrow">›</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ methods: {
|
|
|
+ navigateTo(url) {
|
|
|
+ uni.navigateTo({ url });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.domain-page { padding: 0; }
|
|
|
+.domain-header { padding: 40rpx; text-align: center; color: #fff; }
|
|
|
+.domain-header-body { background: linear-gradient(135deg, #43e97b 0%, #38f9d7 100%); }
|
|
|
+.domain-header-icon { font-size: 80rpx; }
|
|
|
+.domain-header-title { font-size: 36rpx; font-weight: bold; margin-top: 10rpx; }
|
|
|
+.feature-list { padding: 20rpx 30rpx; }
|
|
|
+.feature-item { display: flex; justify-content: space-between; align-items: center; padding: 30rpx; background: #fff; border-radius: 12rpx; margin-bottom: 16rpx; box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04); }
|
|
|
+.feature-name { font-size: 30rpx; color: #333; }
|
|
|
+.feature-arrow { font-size: 36rpx; color: #ccc; }
|
|
|
+</style>
|
|
|
+```
|
|
|
+
|
|
|
+`pages/mind/index.vue`: 同上结构,domain-header-mind 样式为 `background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%)`,功能列表为情绪日志/心理测评/家庭氛围/冥想放松。
|
|
|
+
|
|
|
+`pages/action/index.vue`: 同上结构,domain-header-action 样式为 `background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%)`,功能列表为活动列表/文章科普/长者关怀/社区互动。
|
|
|
+
|
|
|
+- [ ] **Step 4: 创建各域子页面占位文件**
|
|
|
+
|
|
|
+为每个域的功能页面创建最小占位 vue 文件(仅含标题文本),确保 pages.json 注册的路径都有对应文件。
|
|
|
+
|
|
|
+每个占位页面结构统一:
|
|
|
+```vue
|
|
|
+<template>
|
|
|
+ <view class="page-container">
|
|
|
+ <view class="placeholder">
|
|
|
+ <text class="placeholder-text">【功能名称】 — 即将上线</text>
|
|
|
+ </view>
|
|
|
+ </view>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+export default {}
|
|
|
+</script>
|
|
|
+<style scoped>
|
|
|
+.page-container { display: flex; justify-content: center; align-items: center; height: 100vh; background: #f5f7fa; }
|
|
|
+.placeholder { text-align: center; }
|
|
|
+.placeholder-text { font-size: 28rpx; color: #999; }
|
|
|
+</style>
|
|
|
+```
|
|
|
+
|
|
|
+需要创建的占位文件:
|
|
|
+- `pages/body/health-metric.vue` → "健康指标记录"
|
|
|
+- `pages/body/nutrition-log.vue` → "水营养追踪"
|
|
|
+- `pages/body/anti-aging.vue` → "抗衰评估"
|
|
|
+- `pages/body/exercise-log.vue` → "运动记录"
|
|
|
+- `pages/mind/mood-log.vue` → "情绪日志"
|
|
|
+- `pages/mind/assessment.vue` → "心理测评"
|
|
|
+- `pages/mind/family-atmosphere.vue` → "家庭氛围"
|
|
|
+- `pages/mind/meditation.vue` → "冥想放松"
|
|
|
+- `pages/action/activity-list.vue` → "活动列表"
|
|
|
+- `pages/action/activity-detail.vue` → "活动详情"
|
|
|
+- `pages/action/article-list.vue` → "文章科普"
|
|
|
+- `pages/action/article-detail.vue` → "文章详情"
|
|
|
+- `pages/action/elder-care.vue` → "长者关怀"
|
|
|
+- `pages/action/community.vue` → "社区互动"
|
|
|
+
|
|
|
+- [ ] **Step 5: 修改 api.js — 增加域 API 封装**
|
|
|
+
|
|
|
+在 `zxyj-frontend/utils/api.js` 末尾添加:
|
|
|
+
|
|
|
+```javascript
|
|
|
+// === Body 域 API ===
|
|
|
+export const createBodyHealthMetric = (data) => request('/body/health/create', data);
|
|
|
+export const getBodyHealthMetrics = (data) => request('/body/health/list', data);
|
|
|
+export const getLatestBodyHealthMetric = (data) => request('/body/health/latest', data);
|
|
|
+export const createBodyNutritionLog = (data) => request('/body/nutrition/create', data);
|
|
|
+export const getBodyNutritionLogs = (data) => request('/body/nutrition/list', data);
|
|
|
+export const createBodyAntiAgingAssessment = (data) => request('/body/anti-aging/create', data);
|
|
|
+export const getBodyAntiAgingAssessments = (data) => request('/body/anti-aging/list', data);
|
|
|
+export const createBodyExerciseLog = (data) => request('/body/exercise/create', data);
|
|
|
+export const getBodyExerciseLogs = (data) => request('/body/exercise/list', data);
|
|
|
+
|
|
|
+// === Mind 域 API ===
|
|
|
+export const createMindMoodLog = (data) => request('/mind/mood/create', data);
|
|
|
+export const getMindMoodLogs = (data) => request('/mind/mood/list', data);
|
|
|
+export const createMindAssessment = (data) => request('/mind/assessment/create', data);
|
|
|
+export const getMindAssessments = (data) => request('/mind/assessment/list', data);
|
|
|
+export const createMindFamilyAtmosphere = (data) => request('/mind/atmosphere/create', data);
|
|
|
+export const getMindFamilyAtmosphere = (data) => request('/mind/atmosphere/list', data);
|
|
|
+export const createMindMeditation = (data) => request('/mind/meditation/create', data);
|
|
|
+export const getMindMeditations = (data) => request('/mind/meditation/list', data);
|
|
|
+
|
|
|
+// === Action 域 API ===
|
|
|
+export const createActionActivity = (data) => request('/action/activity/create', data);
|
|
|
+export const getActionActivities = (data) => request('/action/activity/list', data);
|
|
|
+export const getActionActivityDetail = (data) => request('/action/activity/detail', data);
|
|
|
+export const registerActionActivity = (data) => request('/action/activity/register', data);
|
|
|
+export const createActionArticle = (data) => request('/action/article/create', data);
|
|
|
+export const getActionArticles = (data) => request('/action/article/list', data);
|
|
|
+export const getActionArticleDetail = (data) => request('/action/article/detail', data);
|
|
|
+export const createActionElderCarePlan = (data) => request('/action/elder-care/create', data);
|
|
|
+export const getActionElderCarePlans = (data) => request('/action/elder-care/list', data);
|
|
|
+export const createActionPracticeTask = (data) => request('/action/practice/create', data);
|
|
|
+export const getActionPracticeTasks = (data) => request('/action/practice/list', data);
|
|
|
+export const createActionCommunityPost = (data) => request('/action/community/create-post', data);
|
|
|
+export const getActionCommunityPosts = (data) => request('/action/community/posts', data);
|
|
|
+export const createActionCommunityComment = (data) => request('/action/community/create-comment', data);
|
|
|
+export const getActionCommunityComments = (data) => request('/action/community/comments', data);
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 6: 修改 store/index.js — 增加 domain 状态**
|
|
|
+
|
|
|
+在 Vuex state 中添加:
|
|
|
+
|
|
|
+```javascript
|
|
|
+currentDomain: null, // 'body' | 'mind' | 'wisdom' | 'action' — 当前活跃域
|
|
|
+```
|
|
|
+
|
|
|
+在 mutations 中添加:
|
|
|
+
|
|
|
+```javascript
|
|
|
+setCurrentDomain(state, domain) {
|
|
|
+ state.currentDomain = domain;
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- [ ] **Step 7: 提交 Phase 1 框架代码**
|
|
|
+
|
|
|
+```bash
|
|
|
+git add -A
|
|
|
+git commit -m "feat: 溪福俱乐部四域框架搭建 - 17个新entity/mapper/service - 四象限首页 - 域导航骨架"
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Phase 2: 行 (Action) 域功能实现
|
|
|
+
|
|
|
+**目标:** 完善行域所有功能页面(活动、文章、长者关怀、社区、践行任务),建立域内完整业务闭环。
|
|
|
+
|
|
|
+> **注:** Phase 2-4 每个域的具体功能实现计划将在 Phase 1 完成后细化。每个域需要:
|
|
|
+> 1. 完善后端 Controller + Service 业务逻辑(CRUD + 业务规则)
|
|
|
+> 2. 实现前端功能页面(替换占位页面)
|
|
|
+> 3. 接入积分系统(域内行为可获积分)
|
|
|
+> 4. 管理端页面(zxyj-web 内容管理)
|
|
|
+
|
|
|
+### 行域功能清单
|
|
|
+
|
|
|
+| 功能 | 后端Controller | 前端页面 | 优先级 |
|
|
|
+|------|---------------|----------|--------|
|
|
|
+| 活动发布/列表/报名/详情 | ActionController | activity-list, activity-detail | P0 |
|
|
|
+| 文章发布/列表/详情 | ActionArticleController | article-list, article-detail | P0 |
|
|
|
+| 长者关怀计划/日志 | ActionElderCareController(新增) | elder-care | P1 |
|
|
|
+| 社区帖子/评论 | ActionCommunityController(新增) | community | P1 |
|
|
|
+| 践行任务CRUD | ActionPracticeController(新增) | - (首页卡片) | P1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Phase 3: 身 (Body) 域功能实现
|
|
|
+
|
|
|
+**目标:** 完善身域所有功能页面(健康指标、水营养、抗衰评估、运动记录),建立健康管理闭环。
|
|
|
+
|
|
|
+### 身域功能清单
|
|
|
+
|
|
|
+| 功能 | 后端Controller | 前端页面 | 优先级 |
|
|
|
+|------|---------------|----------|--------|
|
|
|
+| 健康指标CRUD + 趋势图 | BodyHealthController | health-metric | P0 |
|
|
|
+| 水营养追踪 + 统计 | BodyNutritionController(新增) | nutrition-log | P0 |
|
|
|
+| 抗衰评估 + 报告 | BodyAntiAgingController(新增) | anti-aging | P1 |
|
|
|
+| 运动记录 + 步数 | BodyExerciseController(新增) | exercise-log | P1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Phase 4: 心 (Mind) 域功能实现
|
|
|
+
|
|
|
+**目标:** 完善心域所有功能页面(情绪日志、心理测评、家庭氛围、冥想),建立心理健康管理闭环。
|
|
|
+
|
|
|
+### 心域功能清单
|
|
|
+
|
|
|
+| 功能 | 后端Controller | 前端页面 | 优先级 |
|
|
|
+|------|---------------|----------|--------|
|
|
|
+| 情绪日志CRUD + 趋势 | MindMoodController | mood-log | P0 |
|
|
|
+| 心理测评问卷+报告 | MindAssessmentController(新增) | assessment | P0 |
|
|
|
+| 家庭氛围评估 | MindFamilyAtmosphereController(新增) | family-atmosphere | P1 |
|
|
|
+| 冥想计时+引导音频 | MindMeditationController(新增) | meditation | P1 |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Phase 5: Lilishop 电商集成
|
|
|
+
|
|
|
+**目标:** 通过 REST API 集成 Lilishop 电商功能,实现商品浏览、购物车、下单结算。
|
|
|
+
|
|
|
+### 电商集成清单
|
|
|
+
|
|
|
+| 功能 | 后端实现 | 前端页面 | 优先级 |
|
|
|
+|------|----------|----------|--------|
|
|
|
+| LilishopApiClient | LilishopApiClient.java (RestTemplate) | - | P0 |
|
|
|
+| 商品浏览/搜索 | CommerceController → Lilishop buyer-api | product-list, product-detail | P0 |
|
|
|
+| 购物车 | CommerceController → Lilishop buyer-api | cart | P0 |
|
|
|
+| 下单/支付 | CommerceController → Lilishop buyer-api | checkout | P1 |
|
|
|
+| 订单管理 | CommerceController → Lilishop buyer-api | order-list | P1 |
|
|
|
+| 商品管理(管理端) | CommerceAdminController → Lilishop seller-api | zxyj-web 商品管理页 | P2 |
|
|
|
+
|
|
|
+### Lilishop 配置
|
|
|
+
|
|
|
+在 `application.yml` 中添加:
|
|
|
+
|
|
|
+```yaml
|
|
|
+lilishop:
|
|
|
+ buyer-api: http://localhost:8888
|
|
|
+ seller-api: http://localhost:8889
|
|
|
+ manager-api: http://localhost:8887
|
|
|
+ service-account:
|
|
|
+ username: zxyj_service
|
|
|
+ password: ${LILISHOP_SERVICE_PASSWORD}
|
|
|
+ token-cache-minutes: 50
|
|
|
+```
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## Phase 6: 管理端 (zxyj-web) 扩展
|
|
|
+
|
|
|
+**目标:** 在 Web 管理端新增四域内容管理页面。
|
|
|
+
|
|
|
+### 管理端新增页面
|
|
|
+
|
|
|
+| 路由 | 页面 | 功能 |
|
|
|
+|------|------|------|
|
|
|
+| /body/health | BodyHealth.vue | 健康指标数据管理 |
|
|
|
+| /body/anti-aging | BodyAntiAging.vue | 抗衰评估管理 |
|
|
|
+| /mind/assessment | MindAssessment.vue | 心理测评管理 |
|
|
|
+| /mind/atmosphere | MindAtmosphere.vue | 家庭氛围数据 |
|
|
|
+| /action/activity | ActionActivity.vue | 活动发布管理 |
|
|
|
+| /action/article | ActionArticle.vue | 文章内容管理 |
|
|
|
+| /action/community | ActionCommunity.vue | 社区内容审核 |
|
|
|
+| /commerce/products | CommerceProducts.vue | 商品管理(Lilishop) |
|
|
|
+| /commerce/orders | CommerceOrders.vue | 订单管理(Lilishop) |
|
|
|
+
|
|
|
+---
|
|
|
+
|
|
|
+## 自检清单
|
|
|
+
|
|
|
+### 1. Spec 覆盖度
|
|
|
+- [x] 身域: 健康指标、水营养、抗衰评估、运动 → Task 1, 6, 7, Phase 3
|
|
|
+- [x] 心域: 情绪日志、心理测评、家庭氛围、冥想 → Task 2, 6, 7, Phase 4
|
|
|
+- [x] 智域: 现有功能保留 → Task 9 (首页入口), 不改动现有代码
|
|
|
+- [x] 行域: 活动、文章、长者关怀、社区、践行 → Task 3, 6, 7, Phase 2
|
|
|
+- [x] 首页四象限 → Task 9
|
|
|
+- [x] Lilishop集成 → Phase 5
|
|
|
+- [x] 管理端 → Phase 6
|
|
|
+- [x] 跨域积分 → Task 5 (PointsLog.domain), Task 8
|
|
|
+
|
|
|
+### 2. 占位符扫描
|
|
|
+- [x] 无 TBD/TODO/待定 — Phase 2-5 的具体实现将在各Phase开始时细化
|
|
|
+- [x] 所有 Phase 1 步骤包含完整代码
|
|
|
+
|
|
|
+### 3. 类型一致性
|
|
|
+- [x] Entity字段名 ↔ Mapper ↔ Service ↔ Controller 参数名一致
|
|
|
+- [x] 前端 api.js 路径 ↔ 后端 @RequestMapping 路径一致
|
|
|
+- [x] pages.json 路径 ↔ 实际文件路径一致
|