# 推荐组件移除维度参数 实现计划 > **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development。步骤使用复选框(`- [ ]`)语法来跟踪进度。 **目标:** 移除 DimensionProducts/Articles/Activities/Tasks 四个组件的 dimensionCode 参数,组件改为自加载全量推荐内容,父页面不再传维度参数也不负责数据加载。 **架构:** 组件自加载模式。后端 `/api/recommend/dimension-products` 支持空 dimensionCode 返回全量推荐。Article/Activity/Task 后端已支持空过滤参数,无需改动。11 个父页面移除维度传参和本地数据加载。 **技术栈:** Java 8 + Spring Boot 2.7.18 / uni-app Vue 2 + 微信小程序 --- ### 任务 1:后端 ProductRecommendationController 支持空 dimensionCode **文件:** - 修改:`cfc-backend/src/main/java/com/etotem/cfc/controller/recommendation/ProductRecommendationController.java` - [ ] **步骤 1:修改 Controller 校验逻辑** 将 dimensionCode 为空时返回错误的逻辑改为允许空值,调用 service 时用 null: ```java @Operation(summary = "获取推荐商品") @PostMapping("/dimension-products") public Result>> getDimensionProducts(@RequestBody Map params, @RequestAttribute(value = "familyId", required = false) Long familyId) { if (familyId == null) { return Result.noFamily("请先创建或加入家庭"); } // 去掉 dimensionCode 非空校验,允许 null 返回全量推荐 String dimensionCode = (String) params.get("dimensionCode"); Object memberIdObj = params.get("memberId"); Long memberId = memberIdObj != null ? toLong(memberIdObj) : null; @SuppressWarnings("unchecked") List excludeIds = (List) params.get("excludeProductIds"); Object limitObj = params.get("limit"); int limit = limitObj != null ? toInt(limitObj) : 6; List> result = productRecommendationService.getDimensionRecommendations( dimensionCode, familyId, memberId, excludeIds, limit); return Result.success(result); } ``` - [ ] **步骤 2:Commit** ```bash git add cfc-backend/src/main/java/com/etotem/cfc/controller/recommendation/ProductRecommendationController.java git commit -m "fix: 推荐商品接口支持空 dimensionCode 返回全量" ``` --- ### 任务 2:后端 ProductRecommendationService 全量查询逻辑 **文件:** - 修改:`cfc-backend/src/main/java/com/etotem/cfc/service/ProductRecommendationService.java` - [ ] **步骤 1:修改 getDimensionRecommendations 方法 — mapping 查询支持 null dimensionCode** 将第 62-67 行的 mapping 查询改为 conditionally 加 dimensionCode 条件: ```java // 从 mapping 表获取关联商品 LambdaQueryWrapper mappingQw = new LambdaQueryWrapper() .eq(ProductDimensionMapping::getEnabled, 1); if (dimensionCode != null && !dimensionCode.isEmpty()) { mappingQw.eq(ProductDimensionMapping::getDimensionCode, dimensionCode); } List mappings = dimensionMappingMapper.selectList(mappingQw); ``` - [ ] **步骤 2:修改 fallback domain 查询支持 null** 将第 107-118 行 fallback 查询改为 conditionally 加 domain 条件: ```java // fallback: 从 Product.domain 匹配 if (candidates.isEmpty()) { LambdaQueryWrapper domainQw = new LambdaQueryWrapper() .eq(Product::getStatus, "上架") .gt(Product::getStock, 0) .orderByAsc(Product::getSortOrder); if (dimensionCode != null && !dimensionCode.isEmpty()) { domainQw.eq(Product::getDomain, dimensionCode); } if (!purchasedIds.isEmpty()) { domainQw.notIn(Product::getId, purchasedIds); } List domainMatched = productMapper.selectList(domainQw); candidates.addAll(domainMatched); } ``` - [ ] **步骤 3:修改 dimensionBoost / matchScore / reason 方法 — 空 dimensionCode 时使用通用逻辑** 将 `applyDimensionBoost` 方法修改为: ```java private double applyDimensionBoost(int baseScore, String dimensionCode, Map memberScores) { if (dimensionCode == null || dimensionCode.isEmpty()) { return baseScore; } Integer score = memberScores.get(dimensionCode); if (score == null || score >= 70) { return baseScore; } else if (score >= 50) { return baseScore * 1.1; } else { return baseScore * 1.2; } } ``` 将 `calculateMatchScore` 方法修改为: ```java private double calculateMatchScore(Product product, String dimensionCode, Map memberScores) { int base = 70; if (dimensionCode == null || dimensionCode.isEmpty()) { // 无维度时,用最低分维度作为参考 Integer minScore = memberScores.values().stream().min(Integer::compareTo).orElse(null); if (minScore != null) { if (minScore < 50) base = 90; else if (minScore < 70) base = 80; } return base; } Integer myScore = memberScores.get(dimensionCode); if (myScore != null) { if (myScore < 50) base = 90; else if (myScore < 70) base = 80; else base = 70; } return base; } ``` 将 `buildRecommendationReason` 方法修改为: ```java private String buildRecommendationReason(Product product, String dimensionCode, Map memberScores) { if (dimensionCode == null || dimensionCode.isEmpty()) { return "为您推荐的好物"; } Integer score = memberScores.get(dimensionCode); if (score == null) { return "根据您的维度匹配为您推荐"; } if (score < 50) { return "该维度得分偏低,重点推荐"; } else if (score < 70) { return "该维度有提升空间,推荐关注"; } return "丰富您的维度生活"; } ``` - [ ] **步骤 4:编译验证** 运行: ```bash cd cfc-backend && mvn clean compile ``` 预期:编译通过,无错误。 - [ ] **步骤 5:Commit** ```bash git add cfc-backend/src/main/java/com/etotem/cfc/service/ProductRecommendationService.java git commit -m "feat: 商品推荐支持空维度返回全量推荐" ``` --- ### 任务 3:DimensionProducts.vue — 移除 dimensionCode,自加载 **文件:** - 修改:`cfc-frontend/components/DimensionProducts.vue` - [ ] **步骤 1:移除 dimensionCode prop** ```js props: { // 移除 dimensionCode products: { type: Array, default: function() { return [] } }, familyId: { type: [Number, String], default: null }, isLoggedIn: { type: Boolean, default: false }, title: { type: String, default: '推荐商品' }, showMore: { type: Boolean, default: true } }, ``` - [ ] **步骤 2:修改 loadDimensionProducts 方法,去掉 dimensionCode 参数** ```js loadDimensionProducts: function() { var self = this self.loading = true var params = { limit: 4 } getDimensionProducts(params).then(function(res) { self.loading = false if (res.code === 200 && res.data) { self.selfProducts = Array.isArray(res.data) ? res.data : (res.data.records || []) } }).catch(function() { self.loading = false self.selfProducts = [] }) } ``` - [ ] **步骤 3:Commit** ```bash git add cfc-frontend/components/DimensionProducts.vue git commit -m "fix: DimensionProducts 移除维度参数自加载" ``` --- ### 任务 4:DimensionArticles.vue — 移除 dimensionCode,新增自加载 **文件:** - 修改:`cfc-frontend/components/DimensionArticles.vue` - [ ] **步骤 1:添加 API 导入** 在 script 顶部添加: ```js import { getFeaturedArticles } from '@/utils/api.js' ``` - [ ] **步骤 2:移除 dimensionCode prop** ```js props: { // 移除 dimensionCode articles: { type: Array, default: function() { return [] } }, isLoggedIn: { type: Boolean, default: false }, colors: { type: Array, default: function() { return defaultGradientColors } } }, ``` - [ ] **步骤 3:添加 data 和 self-loading** ```js data: function() { return { selfArticles: [], loading: false } }, mounted: function() { if (!this.articles || this.articles.length === 0) { this.loadArticles() } }, ``` - [ ] **步骤 4:修改 displayArticles computed,优先用 selfArticles** ```js displayArticles: function() { var self = this var list = (this.articles && this.articles.length > 0 ? this.articles : self.selfArticles) return (list || []).map(function(item) { item._badges = self.parseWeights(item.dimensionWeights) return item }) } ``` - [ ] **步骤 5:添加 loadArticles 方法** ```js loadArticles: function() { var self = this self.loading = true getFeaturedArticles({ size: 3 }).then(function(res) { self.loading = false if (res && res.code === 200 && res.data) { var list = Array.isArray(res.data) ? res.data : (res.data.records || []) self.selfArticles = list.slice(0, 3) } }).catch(function() { self.loading = false self.selfArticles = [] }) } ``` - [ ] **步骤 6:Commit** ```bash git add cfc-frontend/components/DimensionArticles.vue git commit -m "fix: DimensionArticles 移除维度参数自加载" ``` --- ### 任务 5:DimensionActivities.vue — 移除 dimensionCode,新增自加载 **文件:** - 修改:`cfc-frontend/components/DimensionActivities.vue` - [ ] **步骤 1:添加 API 导入** 在 script 顶部添加: ```js import { getActivityList } from '@/utils/api.js' ``` - [ ] **步骤 2:移除 dimensionCode prop 和 dimensionIcon computed** ```js props: { // 移除 dimensionCode activities: { type: Array, default: function() { return [] } }, isLoggedIn: { type: Boolean, default: false } } ``` 删除 `dimensionIcon` computed。 - [ ] **步骤 3:修改 template 中的图标为固定值** 将 `{{ dimensionIcon }}` 替换为固定图标 `'🎯'`: ```vue 🎯 🎯 ``` - [ ] **步骤 4:添加 data 和 self-loading** ```js data: function() { return { swiperIndex: 0, isMember: false, selfActivities: [], loading: false } }, mounted: function() { if (!this.activities || this.activities.length === 0) { this.loadActivities() } } ``` - [ ] **步骤 5:修改 displayActivities computed,优先用 selfActivities** ```js displayActivities: function() { var self = this var list = (this.activities && this.activities.length > 0 ? this.activities : self.selfActivities) return (list || []).slice(0, 3).map(function(item) { return { id: item.id, title: item.title, coverImage: item.coverImage, startTime: item.startTime, status: item.status, price: item.price, priceLabel: item.priceLabel, memberPrice: item.memberPrice, dimensionWeights: item.dimensionWeights, _badges: self.parseWeights(item.dimensionWeights), _timeText: self.formatTime(item.startTime), _statusText: self.statusText(item.status), _priceDisplay: self.formatPriceWithSymbol(item.price), _memberPriceDisplay: self.formatPriceWithSymbol(item.memberPrice) } }) } ``` - [ ] **步骤 6:添加 loadActivities 方法** ```js loadActivities: function() { var self = this self.loading = true getActivityList({ page: 1, size: 3 }).then(function(res) { self.loading = false if (res && res.code === 200 && res.data) { var list = Array.isArray(res.data) ? res.data : (res.data.records || []) self.selfActivities = list.slice(0, 3) } }).catch(function() { self.loading = false self.selfActivities = [] }) } ``` - [ ] **步骤 7:Commit** ```bash git add cfc-frontend/components/DimensionActivities.vue git commit -m "fix: DimensionActivities 移除维度参数自加载" ``` --- ### 任务 6:DimensionTasks.vue — 移除 dimensionCode,改用 getTodayTasks **文件:** - 修改:`cfc-frontend/components/DimensionTasks.vue` - [ ] **步骤 1:添加 getTodayTasks 导入** ```js import api from '@/utils/api.js' // 确保 api.getTodayTasks 可用(已存在于 api.js 第 453 行) ``` - [ ] **步骤 2:移除 dimensionCode prop** ```js props: { // 移除 dimensionCode tasks: { type: Array, default: function() { return [] } }, memberId: { type: Number, default: null } }, ``` - [ ] **步骤 3:修改 loadTasks 方法,使用 getTodayTasks(不带 category)** ```js loadTasks: function() { var self = this if (!self.memberId) return self.loading = true api.getTodayTasks(self.memberId).then(function(res) { self.loading = false self.tasksData = Array.isArray(res.data) ? res.data : (res.data.records || []) }).catch(function() { self.loading = false self.tasksData = [] }) } ``` - [ ] **步骤 4:Commit** ```bash git add cfc-frontend/components/DimensionTasks.vue git commit -m "fix: DimensionTasks 移除维度参数自加载" ``` --- ### 任务 7:父页面清理 — 7 个维度详情页(body/mind/wisdom/action 两个版本) **文件:** - 修改:`cfc-frontend/pages/body/member-body-detail.vue` - 修改:`cfc-frontend/pages/mind/member-mind-detail.vue` - 修改:`cfc-frontend/pages/wisdom/member-wisdom-detail.vue` - 修改:`cfc-frontend/pages/action-detail/member-action-detail.vue` - 修改:`cfc-frontend/pages/body-detail/member-body-detail.vue` - 修改:`cfc-frontend/pages/mind-detail/member-mind-detail.vue` - 修改:`cfc-frontend/pages/wisdom-detail/member-wisdom-detail.vue` **统一改动模式(每个页面):** - [ ] **步骤 1:去掉 import 中的 API** ```js // 移除 getTodayTasksByCategory, getActivityList, getProductsByDomain import { getEnergyOverview, getFamilyEnergySandbox, getChildren } from '../../utils/api.js' ``` - [ ] **步骤 2:去掉 data 中的数据字段** ```js data() { return { memberId: null, selfId: null, memberInfo: null, sandboxData: null, dualDimension: null, // 移除 dimensionTasks, dimensionActivities, dimensionProducts ... } } ``` - [ ] **步骤 3:去掉 template 中的 dimensionCode 和 props** ```vue ``` - [ ] **步骤 4:去掉 onShow 中的数据加载调用** ```js // 移除 this.loadDimensionTasks() // 移除 this.loadDimensionActivities() // 移除 this.loadDimensionProducts() ``` - [ ] **步骤 5:去掉 loadDimensionTasks / loadDimensionActivities / loadDimensionProducts 方法** 删除这三个方法定义。 - [ ] **步骤 6:对 7 个页面逐一完成上述改动** 每个页面完成后立即 commit: ```bash git add cfc-frontend/pages/body/member-body-detail.vue git commit -m "fix: body 成员详情页移除维度参数" ``` 按 body → mind → wisdom → action → body-detail → mind-detail → wisdom-detail 顺序逐个提交。 --- ### 任务 8:index-home/index.vue — 去掉维度相关数据加载 **文件:** - 修改:`cfc-frontend/pages/index-home/index.vue` - [ ] **步骤 1:去掉 DimensionProducts 和 DimensionArticles 的 dimensionCode prop** ```vue ... /> ``` - [ ] **步骤 2:去掉 loadActionProducts 方法** 删除 `loadActionProducts` 方法定义。 - [ ] **步骤 3:去掉 loadActionArticles 方法** 删除 `loadActionArticles` 方法定义。 - [ ] **步骤 4:去掉 onShow 中的调用** ```js // 移除 this.loadActionProducts() // 移除 this.loadActionArticles() // 移除 this.loadDimensionActivities()(growth-main 已传空 dimensionCode,可保留) ``` - [ ] **步骤 5:去掉 import 中的 getProductsByDomain, getFeaturedArticles** - [ ] **步骤 6:去掉 data 中的 actionArticles, dimensionProducts 字段** - [ ] **步骤 7:Commit** ```bash git add cfc-frontend/pages/index-home/index.vue git commit -m "fix: index-home 移除维度参数" ``` --- ### 任务 9:member-detail.vue 和 home-pages/member-home-detail.vue **文件:** - 修改:`cfc-frontend/pages/member-detail/member-detail.vue` - 修改:`cfc-frontend/pages/home-pages/member-home-detail.vue` - [ ] **步骤 1(member-detail):去掉 DimensionTasks 的 dimensionCode="all" prop** ```vue ``` 注意:`member-detail` 页面的 `this.dimensionCode` 数据属性用于页面导航逻辑(`onGraphMemberTap`),不要删除!只去掉组件的 prop 传参。 - [ ] **步骤 2(member-detail):去掉 loadDimensionTasks 方法(如果存在)** 检查页面是否调用 `getTodayTasksByCategory` 加载任务数据。如果有则删除。 - [ ] **步骤 3(home-pages):去掉 DimensionTasks 的 dimensionCode="all" prop** ```vue ``` - [ ] **步骤 4(home-pages):去掉 loadData 中的任务加载逻辑** ```js // 删除: // getTodayTasksByCategory(self.memberId, 'all').then(...) ``` - [ ] **步骤 5(home-pages):去掉 import 中的 getTodayTasksByCategory** - [ ] **步骤 6:Commit** ```bash git add cfc-frontend/pages/member-detail/member-detail.vue cfc-frontend/pages/home-pages/member-home-detail.vue git commit -m "fix: member-detail 和 home-detail 移除任务维度参数" ``` --- ### 任务 10:growth-main/index.vue — 去掉 DimensionActivities 的 dimensionCode **文件:** - 修改:`cfc-frontend/pages/growth-main/index.vue` - [ ] **步骤 1:去掉 DimensionActivities 的 dimensionCode prop** ```vue ``` - [ ] **步骤 2:去掉 loadDimensionActivities 方法和 onLoad 中的调用** ```js // 删除 loadDimensionActivities 方法 // 删除 onLoad 中的 this.loadDimensionActivities() ``` - [ ] **步骤 3:去掉 data 中的 dimensionActivities 字段** - [ ] **步骤 4:去掉 import 中的 getActivityList** - [ ] **步骤 5:Commit** ```bash git add cfc-frontend/pages/growth-main/index.vue git commit -m "fix: growth-main 移除活动维度参数" ``` --- ### 任务 11:验证与最终提交 - [ ] **步骤 1:后端编译验证** ```bash cd cfc-backend && mvn clean compile ``` 预期:编译通过。 - [ ] **步骤 2:统计所有改动** ```bash git diff --stat ``` 预期:改动涵盖: - `cfc-backend/` — ProductRecommendationController + ProductRecommendationService - `cfc-frontend/components/` — 4 个组件 - `cfc-frontend/pages/` — 11 个页面 - [ ] **步骤 3:最终 Commit** ```bash git add -A git commit -m "fix: 推荐组件移除维度参数(商品/文章/活动/任务)" ``` - [ ] **步骤 4:确认** 运行: ```bash git diff HEAD~1 --stat ``` 确认改动范围正确。