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: 为心智页 pages/mind/index.vue 添加心/智双Tab结构,用户可在心理与认知内容之间切换
Architecture: 单页面内通过 activeTab 数据属性 + v-if 控制心/智两个内容区块的显示隐藏,Tab栏位于图谱/快捷入口之后。推荐阅读、维度任务/活动/商品跟随activeTab切换维度参数。
Tech Stack: uni-app Vue 2, 微信小程序
Design Spec Ref: docs/superpowers/specs/2026-06-13-five-dimension-pages-redesign.md §4
cfc-frontend/components/、cfc-frontend/pages/mind/、cfc-frontend/utils/、cfc-frontend/config/ 下搜索。禁止搜索 node_modules/、unpackage/、dist/?.(微信小程序不支持)git commit 或 git push,只修改文件v-if 切换,不得使用 v-show(小程序 v-show 仍会渲染组件,影响性能)function 关键字(Vue 2 Options API),不要使用箭头函数或 get 语法v-for 中的元素如果有 v-if,用 <template v-for> 包裹或移到外层DO NOT 擅自创建/修改其他文件 — 只改 mind/index.vue
Files:
cfc-frontend/pages/mind/index.vue — 全文件(1392行)做什么:
data() 中添加 activeTab: 'emotion'FamilyRelationGraph / UserQuickEntry 之后、原心理能量概况之前,插入Tab栏<template v-if="activeTab === 'emotion'"> 内<template v-if="activeTab === 'cognitive'"> 内switchTab(tab) 方法.tab-bar / .tab-item / .tab-item.active 样式详细步骤:
data() 中添加 activeTab 属性在 data() 中,dimensionProducts: [] 之后添加:
activeTab: 'emotion'
找到(当前模板第53行):
<!-- ===== 心理能量概况 ===== -->
在其之前插入Tab栏:
<!-- ===== 心/智 Tab栏 ===== -->
<view class="tab-bar">
<view
:class="['tab-item', activeTab === 'emotion' ? 'active' : '']"
@click="switchTab('emotion')">
<text class="tab-icon">❤</text>
<text class="tab-label">心·心理</text>
</view>
<view
:class="['tab-item', activeTab === 'cognitive' ? 'active' : '']"
@click="switchTab('cognitive')">
<text class="tab-icon">🧠</text>
<text class="tab-label">智·认知</text>
</view>
</view>
在第53行 <!-- ===== 心理能量概况 ===== --> 之前插入:
<!-- ===== 心·心理 Tab ===== -->
<template v-if="activeTab === 'emotion'">
然后在原认知区块之前(第162行 <!-- ===== 认知区块 ===== -->)找到对应的闭合,替换为:
</template>
在第162行 <!-- ===== 认知区块 ===== --> 之前插入:
<!-- ===== 智·认知 Tab ===== -->
<template v-if="activeTab === 'cognitive'">
然后在 </template>(第311行 </view> 之前那里是底部区块)之前,找到认知区块的结束位置(第276行 <!-- ===== 底部:维度任务/活动/商品 ===== --> 之前),插入:
</template>
等一下 — 我需要更精确地确认包裹范围。
当前认知内容范围:162行(<!-- ===== 认知区块 ===== -->)到276行(底部:维度任务/活动/商品之前)。
所以替换为:
<!-- ===== 智·认知 Tab ===== -->
<template v-if="activeTab === 'cognitive'">
<!-- 原有认知内容... -->
</template>
<!-- ===== 底部:维度任务/活动/商品 ===== -->
switchTab 方法在 methods 中,goAssessment 方法之前添加:
switchTab: function(tab) {
this.activeTab = tab
}
在 <style scoped> 中,.container 样式之后添加:
/* ===== 心/智 Tab 栏 ===== */
.tab-bar {
display: flex;
flex-direction: row;
margin: 20rpx 30rpx;
background: #fff;
border-radius: 20rpx;
padding: 8rpx;
box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06);
}
.tab-item {
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
padding: 20rpx 0;
border-radius: 16rpx;
transition: all 0.3s;
}
.tab-item.active {
background: linear-gradient(135deg, #8B5CF6, #A78BFA);
box-shadow: 0 4rpx 12rpx rgba(139,92,246,0.3);
}
.tab-icon {
font-size: 28rpx;
margin-right: 8rpx;
}
.tab-item.active .tab-icon {
color: #fff;
}
.tab-label {
font-size: 28rpx;
font-weight: 500;
color: #999;
}
.tab-item.active .tab-label {
color: #fff;
font-weight: bold;
}
做什么:
relatedDimensions 字段emotionArticles / cognitiveArticles 计算属性,按 activeTab 过滤relatedDimensions在 loadFeaturedArticles 中,list.map 回调内添加 relatedDimensions:
self.articles = list.map(function(item, index) {
return {
id: item.id,
category: item.categoryName || '成长文章',
categoryColor: gradientColors[index % gradientColors.length],
title: item.title || '',
summary: item.summary || '',
views: item.viewCount ? String(item.viewCount) : '0',
likes: '0',
date: item.publishedAt ? item.publishedAt.slice(0, 10) : '',
relatedDimensions: item.relatedDimensions || [] // 保留维度标签用于过滤
}
})
在 computed 中,intimacyMapForGraph 之后添加:
emotionArticles: function() {
if (!this.articles || this.articles.length === 0) return []
var result = []
for (var i = 0; i < this.articles.length; i++) {
var a = this.articles[i]
if (a.relatedDimensions && a.relatedDimensions.indexOf('mind') !== -1) {
result.push(a)
}
}
// 如果没有匹配 dimension 的文章,回退显示全部
if (result.length === 0) return this.articles.slice(0, 5)
return result.slice(0, 5)
},
cognitiveArticles: function() {
if (!this.articles || this.articles.length === 0) return []
var result = []
for (var i = 0; i < this.articles.length; i++) {
var a = this.articles[i]
if (a.relatedDimensions && a.relatedDimensions.indexOf('wisdom') !== -1) {
result.push(a)
}
}
if (result.length === 0) return this.articles.slice(0, 5)
return result.slice(0, 5)
}
心理Tab中的推荐阅读(第136-160行),v-for="article in articles" 改为 v-for="article in emotionArticles":
<!-- 推荐阅读(心理Tab内) -->
<view class="section" v-if="sectionVisible('recommended_reading')">
<view class="section-header">
<text class="section-title">推荐阅读</text>
</view>
<view class="article-list">
<view class="article-card" v-for="article in emotionArticles" :key="article.id" @click="goArticleDetail(article.id)">
在认知Tab内的推荐阅读部分(需要认知Tab也有一份推荐阅读),在当前认知内容的最底部、认知Tab闭合之前插入:
<!-- 推荐阅读(认知Tab内) -->
<view class="section" v-if="sectionVisible('recommended_reading')">
<view class="section-header">
<text class="section-title">推荐阅读</text>
</view>
<view class="article-list">
<view class="article-card" v-for="article in cognitiveArticles" :key="article.id" @click="goArticleDetail(article.id)">
<view class="article-category" :style="{ background: article.categoryColor }">
<text class="article-category-text">{{ article.category }}</text>
</view>
<text class="article-title">{{ article.title }}</text>
<text class="article-summary">{{ article.summary }}</text>
<view class="article-meta">
<view class="meta-item">
<text class="meta-icon">📖</text>
<text class="meta-text">{{ article.views }}</text>
</view>
<view class="meta-item">
<text class="meta-icon">👍</text>
<text class="meta-text">{{ article.likes }}</text>
</view>
<text class="article-date">{{ article.date }}</text>
</view>
</view>
</view>
</view>
做什么:
currentDimensionCode 计算属性,根据 activeTab 返回 mind 或 wisdomDimensionTasks / DimensionActivities / DimensionProducts 的 dimensionCode 绑定动态值loadDimensionActivities / loadDimensionProducts 方法改为使用动态维度moreActivities / moreProducts 导航URL使用动态维度currentDimensionCode 计算属性在 computed 中,cognitiveArticles 之后添加:
currentDimensionCode: function() {
return this.activeTab === 'emotion' ? 'mind' : 'wisdom'
}
在模板中找到(第278-295行):
<DimensionTasks
v-if="isLoggedIn"
dimensionCode="mind"
... />
<DimensionActivities
dimensionCode="mind"
... />
<DimensionProducts
dimensionCode="mind"
... />
改为:
<DimensionTasks
v-if="isLoggedIn"
:dimensionCode="currentDimensionCode"
... />
<DimensionActivities
:dimensionCode="currentDimensionCode"
... />
<DimensionProducts
:dimensionCode="currentDimensionCode"
... />
注意:DimensionTasks 的 dimensionCode 前加 : 冒号(动态绑定)。
loadDimensionActivities 方法(第750-758行):
loadDimensionActivities: function() {
var self = this
var dimCode = self.currentDimensionCode
getActivityList({ dimensionCode: dimCode, page: 1, size: 3 }).then(function(res) {
if (res && res.data) {
var list = Array.isArray(res.data) ? res.data : (res.data.records || [])
self.dimensionActivities = list.slice(0, 3)
}
}).catch(function() { self.dimensionActivities = [] })
}
loadDimensionProducts 方法(第759-767行):
loadDimensionProducts: function() {
var self = this
var dimCode = self.currentDimensionCode
getProductsByDomain(dimCode, 1, 4).then(function(res) {
if (res && res.data) {
var list = Array.isArray(res.data) ? res.data : (res.data.records || [])
self.dimensionProducts = list.slice(0, 4)
}
}).catch(function() { self.dimensionProducts = [] })
}
switchTab 时重载维度数据更新 switchTab 方法:
switchTab: function(tab) {
if (tab === this.activeTab) return
this.activeTab = tab
// 切换维度后重载对应的活动/商品数据
this.loadDimensionActivities()
this.loadDimensionProducts()
}
goMoreActivities 方法(第804-806行):
goMoreActivities: function() {
var dimCode = this.currentDimensionCode
uni.navigateTo({ url: '/pages/discover/index?type=activity&dimension=' + dimCode })
}
goMoreProducts 方法(第810-812行):
goMoreProducts: function() {
var dimCode = this.currentDimensionCode
uni.navigateTo({ url: '/pages/discover/index?type=product&domain=' + dimCode })
}
做什么:
DimensionActivities 和 DimensionProducts 的 v-if="isLoggedIn"(它们已在onShow中无条件加载)loadFeaturedArticles 在未登录时也调用(当前已调用)当前(第285-295行):
<DimensionActivities
dimensionCode="mind"
:activities="..."
@activityClick="..."
@moreActivities="..." />
<DimensionProducts
dimensionCode="mind"
:products="..."
@productClick="..."
@moreProducts="..." />
确认这些没有 v-if="isLoggedIn" — 它们当前确实没有(只有 DimensionTasks 有 v-if="isLoggedIn")。无需改动。
但需要确认 loadDimensionActivities 和 loadDimensionProducts 在 onShow 中未登录时也被调用 — 当前代码第455-456行已做:
this.loadDimensionActivities()
this.loadDimensionProducts()
这些在 if (this.isLoggedIn) { ... } 块之外,所以没问题。
当前 loadFeaturedArticles() 在 onShow 中无条件调用(第442行),且在未登录时 sectionVisible('recommended_reading') 默认返回 true,没问题。
做什么:
[ ] Step 1: 检查LSP诊断
# 检查修改后的文件有无诊断错误
使用 lsp_diagnostics 工具检查 cfc-frontend/pages/mind/index.vue
手动验证清单:
PageBanner
↓
FamilyMemberStrip (登录后)
↓
LoginGuideCard (未登录)
↓
FamilyEnergyBar (登录后, dualDimension)
↓
FamilyRelationGraph (登录后)
↓
UserQuickEntry (登录后)
↓
┌─ Tab栏 ──────────────────────────────┐
│ [❤ 心·心理] [🧠 智·认知] │
└──────────────────────────────────────┘
↓ activeTab === 'emotion' ↓ activeTab === 'cognitive'
┌─ 心理能量概况 ┐ ┌─ 综合认知评分 ┐
│ EMI 四维条形图 │ │ 认知六维雷达图 │
│ 大五人格雷达图 │ │ 认知训练 │
│ 每日心理 │ │ 本月阅读统计 │
│ 推荐阅读(mind) │ │ 推荐阅读(wisdom)│
└────────────────┘ └────────────────┘
↓ ↓
┌─ DimensionTasks (isLoggedIn) ────────┐
│ (currentDimensionCode=mind/wisdom) │
├──────────────────────────────────────┤
│ DimensionActivities │
│ (currentDimensionCode=mind/wisdom) │
├──────────────────────────────────────┤
│ DimensionProducts │
│ (currentDimensionCode=mind/wisdom) │
└──────────────────────────────────────┘
↓
功能入口 Grid
Agent 注意:
cfc-frontend/pages/mind/index.vue 一个文件edit 工具精确替换lsp_diagnostics 验证