|
|
@@ -5,6 +5,14 @@
|
|
|
tagline="心智成长 · 智慧人生"
|
|
|
quote="知己知彼,百战不殆" />
|
|
|
|
|
|
+ <!-- 家庭成员切换条 -->
|
|
|
+ <FamilyMemberStrip
|
|
|
+ v-if="isLoggedIn && familyMembersVisible.length > 0"
|
|
|
+ :members="familyMembersVisible"
|
|
|
+ :selectedMemberId="selectedMemberId"
|
|
|
+ :selectedMemberType="selectedMemberType"
|
|
|
+ @select="onMemberSelect" />
|
|
|
+
|
|
|
<!-- 游客登录引导卡 -->
|
|
|
<template v-if="!isLoggedIn">
|
|
|
<LoginGuideCard
|
|
|
@@ -33,115 +41,101 @@
|
|
|
@childChanged="onChildChanged"
|
|
|
@scrollTo="scrollToSection" />
|
|
|
|
|
|
- <!-- ===== 双 Tab 切换 ===== -->
|
|
|
- <view class="tab-bar">
|
|
|
- <view :class="['tab-item', activeTab === 'emotion' ? 'tab-active' : '']" @click="switchTab('emotion')">
|
|
|
- <text class="tab-text">心理</text>
|
|
|
+ <!-- ===== 心理能量概况 ===== -->
|
|
|
+ <view class="energy-overview" v-if="emiData">
|
|
|
+ <view class="energy-badge">
|
|
|
+ <text class="badge-icon">❤</text>
|
|
|
+ <text class="badge-value">{{ emiData.overallScore || 0 }}</text>
|
|
|
+ <text class="badge-label">心能量</text>
|
|
|
</view>
|
|
|
- <view :class="['tab-item', activeTab === 'cognitive' ? 'tab-active' : '']" @click="switchTab('cognitive')">
|
|
|
- <text class="tab-text">认知</text>
|
|
|
+ <view class="energy-badge">
|
|
|
+ <text class="badge-icon">💪</text>
|
|
|
+ <text class="badge-value">{{ emiData.resilienceScore || 0 }}</text>
|
|
|
+ <text class="badge-label">韧性评分</text>
|
|
|
</view>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- ===== 心理 Tab ===== -->
|
|
|
- <view v-if="activeTab === 'emotion'">
|
|
|
- <!-- 心理能量概况 -->
|
|
|
- <view class="energy-overview" v-if="emiData">
|
|
|
- <view class="energy-badge">
|
|
|
- <text class="badge-icon">❤</text>
|
|
|
- <text class="badge-value">{{ emiData.overallScore || 0 }}</text>
|
|
|
- <text class="badge-label">心能量</text>
|
|
|
- </view>
|
|
|
- <view class="energy-badge">
|
|
|
- <text class="badge-icon">💪</text>
|
|
|
- <text class="badge-value">{{ emiData.resilienceScore || 0 }}</text>
|
|
|
- <text class="badge-label">韧性评分</text>
|
|
|
- </view>
|
|
|
- <view class="energy-badge">
|
|
|
- <text class="badge-icon">🙏</text>
|
|
|
- <text class="badge-value">{{ emiData.emotionScore || 0 }}</text>
|
|
|
- <text class="badge-label">情绪评分</text>
|
|
|
- </view>
|
|
|
+ <view class="energy-badge">
|
|
|
+ <text class="badge-icon">🙏</text>
|
|
|
+ <text class="badge-value">{{ emiData.emotionScore || 0 }}</text>
|
|
|
+ <text class="badge-label">情绪评分</text>
|
|
|
</view>
|
|
|
+ </view>
|
|
|
|
|
|
- <!-- EMI 四维条形图 -->
|
|
|
- <view class="emi-section" v-if="emiData">
|
|
|
- <view class="emi-card">
|
|
|
- <text class="emi-card-title">EMI 心理四维</text>
|
|
|
- <view class="emi-bar-item" v-for="dim in emiDimensions" :key="dim.key">
|
|
|
- <text class="emi-bar-label">{{ dim.label }}</text>
|
|
|
- <view class="emi-bar-track">
|
|
|
- <view class="emi-bar-fill" :style="{ width: (emiData[dim.key] || 0) + '%', background: dim.color }"></view>
|
|
|
- </view>
|
|
|
- <text class="emi-bar-score">{{ emiData[dim.key] || 0 }}</text>
|
|
|
- <text :class="['emi-bar-level', 'level-' + getScoreLevel(emiData[dim.key] || 0)]">{{ getScoreLevelText(emiData[dim.key] || 0) }}</text>
|
|
|
+ <!-- EMI 四维条形图 -->
|
|
|
+ <view class="emi-section" v-if="emiData">
|
|
|
+ <view class="emi-card">
|
|
|
+ <text class="emi-card-title">EMI 心理四维</text>
|
|
|
+ <view class="emi-bar-item" v-for="dim in emiDimensions" :key="dim.key">
|
|
|
+ <text class="emi-bar-label">{{ dim.label }}</text>
|
|
|
+ <view class="emi-bar-track">
|
|
|
+ <view class="emi-bar-fill" :style="{ width: (emiData[dim.key] || 0) + '%', background: dim.color }"></view>
|
|
|
</view>
|
|
|
- <view class="emi-footer">
|
|
|
- <text class="emi-overall">综合EQ分: {{ emiData.overallScore || 0 }}</text>
|
|
|
- <view class="emi-link" @click="goEmotionReport">
|
|
|
- <text class="emi-link-text">查看完整报告</text>
|
|
|
- <text class="emi-link-arrow">→</text>
|
|
|
- </view>
|
|
|
+ <text class="emi-bar-score">{{ emiData[dim.key] || 0 }}</text>
|
|
|
+ <text :class="['emi-bar-level', 'level-' + getScoreLevel(emiData[dim.key] || 0)]">{{ getScoreLevelText(emiData[dim.key] || 0) }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="emi-footer">
|
|
|
+ <text class="emi-overall">综合EQ分: {{ emiData.overallScore || 0 }}</text>
|
|
|
+ <view class="emi-link" @click="goEmotionReport">
|
|
|
+ <text class="emi-link-text">查看完整报告</text>
|
|
|
+ <text class="emi-link-arrow">→</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ </view>
|
|
|
|
|
|
- <!-- 无 EMI 数据占位 -->
|
|
|
- <view class="placeholder-card" v-if="!emiData && !emiLoading">
|
|
|
- <text class="placeholder-icon">🧠</text>
|
|
|
- <text class="placeholder-title">心理评估</text>
|
|
|
- <text class="placeholder-desc">完成 EMI 心理测评后,可在此查看详细的心理分析报告</text>
|
|
|
- <view class="placeholder-btn" @click="goAssessment" v-if="isLoggedIn">预约测评</view>
|
|
|
- <view class="placeholder-btn" @click="goLogin" v-else>立即登录</view>
|
|
|
- </view>
|
|
|
+ <!-- 无 EMI 数据占位 -->
|
|
|
+ <view class="placeholder-card" v-if="!emiData && !emiLoading">
|
|
|
+ <text class="placeholder-icon">🧠</text>
|
|
|
+ <text class="placeholder-title">心理评估</text>
|
|
|
+ <text class="placeholder-desc">完成 EMI 心理测评后,可在此查看详细的心理分析报告</text>
|
|
|
+ <view class="placeholder-btn" @click="goAssessment" v-if="isLoggedIn">预约测评</view>
|
|
|
+ <view class="placeholder-btn" @click="goLogin" v-else>立即登录</view>
|
|
|
+ </view>
|
|
|
|
|
|
- <!-- 每日心理 -->
|
|
|
- <view class="section" v-if="sectionVisible('daily_tip')">
|
|
|
- <view class="section-header">
|
|
|
- <text class="section-title">每日心理</text>
|
|
|
- </view>
|
|
|
- <view class="tip-card">
|
|
|
- <view class="tip-left-bar"></view>
|
|
|
- <view class="tip-body">
|
|
|
- <text class="tip-title">{{ dailyTip.title }}</text>
|
|
|
- <text class="tip-content">{{ dailyTip.content }}</text>
|
|
|
- <view class="tip-footer">
|
|
|
- <text class="tip-source">{{ dailyTip.source }}</text>
|
|
|
- </view>
|
|
|
+ <!-- 每日心理 -->
|
|
|
+ <view class="section" v-if="sectionVisible('daily_tip')">
|
|
|
+ <view class="section-header">
|
|
|
+ <text class="section-title">每日心理</text>
|
|
|
+ </view>
|
|
|
+ <view class="tip-card">
|
|
|
+ <view class="tip-left-bar"></view>
|
|
|
+ <view class="tip-body">
|
|
|
+ <text class="tip-title">{{ dailyTip.title }}</text>
|
|
|
+ <text class="tip-content">{{ dailyTip.content }}</text>
|
|
|
+ <view class="tip-footer">
|
|
|
+ <text class="tip-source">{{ dailyTip.source }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ </view>
|
|
|
|
|
|
- <!-- 推荐阅读 -->
|
|
|
- <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 articles" :key="article.id" @click="goArticleDetail(article.id)">
|
|
|
- <view class="article-category" :style="{ background: article.categoryColor }">
|
|
|
- <text class="article-category-text">{{ article.category }}</text>
|
|
|
+ <!-- 推荐阅读 -->
|
|
|
+ <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 articles" :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>
|
|
|
- <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 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>
|
|
|
|
|
|
- <!-- ===== 认知 Tab ===== -->
|
|
|
- <view v-if="activeTab === 'cognitive'">
|
|
|
+ <!-- ===== 认知区块 ===== -->
|
|
|
<!-- 综合认知评分 -->
|
|
|
<view class="cognitive-overview" v-if="assessmentData">
|
|
|
<view class="cognitive-score-card">
|
|
|
@@ -255,7 +249,6 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
- </view>
|
|
|
|
|
|
<!-- ===== 底部:维度任务/活动/商品 ===== -->
|
|
|
<DimensionTasks
|
|
|
@@ -305,18 +298,21 @@ import UserQuickEntry from '../../components/UserQuickEntry.vue'
|
|
|
import DimensionTasks from '../../components/DimensionTasks.vue'
|
|
|
import DimensionActivities from '../../components/DimensionActivities.vue'
|
|
|
import DimensionProducts from '../../components/DimensionProducts.vue'
|
|
|
-import { getVisibleSections, getFeaturedArticles, getEmiReport, getAssessmentLatestResult, getDailyTip, getReadingStats, getEnergyOverview, getFamilyEnergySandbox, getTodayTasksByCategory, getActivityList, getProductsByDomain, getChildren } from '../../utils/api.js'
|
|
|
+import FamilyMemberStrip from '../../components/FamilyMemberStrip.vue'
|
|
|
+import { getVisibleSections, getFeaturedArticles, getEmiReport, getAssessmentLatestResult, getDailyTip, getReadingStats, getEnergyOverview, getFamilyEnergySandbox, getTodayTasksByCategory, getActivityList, getProductsByDomain, getChildren, getVisibleFamilyMembers } from '../../utils/api.js'
|
|
|
import config from '../../config.js'
|
|
|
|
|
|
export default {
|
|
|
- components: { PageBanner, RadarChart, LoginGuideCard, FamilyEnergyBar, UserQuickEntry, DimensionTasks, DimensionActivities, DimensionProducts },
|
|
|
+ components: { PageBanner, RadarChart, LoginGuideCard, FamilyEnergyBar, UserQuickEntry, DimensionTasks, DimensionActivities, DimensionProducts, FamilyMemberStrip },
|
|
|
data() {
|
|
|
return {
|
|
|
- activeTab: 'emotion',
|
|
|
isLoggedIn: false,
|
|
|
role: null,
|
|
|
currentChildId: null,
|
|
|
visibleSections: [],
|
|
|
+ familyMembersVisible: [],
|
|
|
+ selectedMemberId: 0,
|
|
|
+ selectedMemberType: 'all',
|
|
|
|
|
|
// 心理 Tab 数据
|
|
|
emiData: null,
|
|
|
@@ -390,6 +386,7 @@ export default {
|
|
|
this.loadDailyTip()
|
|
|
if (this.isLoggedIn) {
|
|
|
this.loadChildren()
|
|
|
+ this.loadFamilyMembersVisible()
|
|
|
this.loadSandboxData()
|
|
|
this.loadEmiData()
|
|
|
this.loadAssessmentData()
|
|
|
@@ -398,11 +395,6 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
- // ===== Tab 切换 =====
|
|
|
- switchTab: function(tab) {
|
|
|
- this.activeTab = tab
|
|
|
- },
|
|
|
-
|
|
|
// ===== 区块可见性 =====
|
|
|
loadSectionConfig: function() {
|
|
|
var self = this
|
|
|
@@ -616,10 +608,6 @@ export default {
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
- if (item.action === 'switchCognitive') {
|
|
|
- this.activeTab = 'cognitive'
|
|
|
- return
|
|
|
- }
|
|
|
if (item.page) uni.navigateTo({ url: item.page })
|
|
|
},
|
|
|
goArticleDetail: function(id) {
|
|
|
@@ -721,6 +709,25 @@ export default {
|
|
|
this.loadAssessmentData()
|
|
|
this.loadReadingStats()
|
|
|
},
|
|
|
+ loadFamilyMembersVisible: function() {
|
|
|
+ var self = this
|
|
|
+ getVisibleFamilyMembers().then(function(res) {
|
|
|
+ self.familyMembersVisible = res.data || []
|
|
|
+ }).catch(function(e) {
|
|
|
+ console.log('获取可见家庭成员失败', e)
|
|
|
+ self.familyMembersVisible = []
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onMemberSelect: function(member) {
|
|
|
+ if (member.memberType === 'all') {
|
|
|
+ this.selectedMemberId = 0
|
|
|
+ this.selectedMemberType = 'all'
|
|
|
+ } else {
|
|
|
+ this.selectedMemberId = member.id
|
|
|
+ this.selectedMemberType = member.memberType
|
|
|
+ }
|
|
|
+ // TODO: 根据选中成员重新加载对应维度数据
|
|
|
+ },
|
|
|
scrollToSection: function(section) {
|
|
|
uni.pageScrollTo({ selector: '#' + section, duration: 300 })
|
|
|
},
|