|
@@ -41,11 +41,6 @@
|
|
|
<text class="feat-title">每日打卡</text>
|
|
<text class="feat-title">每日打卡</text>
|
|
|
<text class="feat-desc">饮食·运动·睡眠·心情</text>
|
|
<text class="feat-desc">饮食·运动·睡眠·心情</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="feat-card" @click="handleGuestFeatureTap">
|
|
|
|
|
- <text class="feat-icon">📋</text>
|
|
|
|
|
- <text class="feat-title">成长记录</text>
|
|
|
|
|
- <text class="feat-desc">每周家庭健康问卷</text>
|
|
|
|
|
- </view>
|
|
|
|
|
<view class="feat-card" @click="handleGuestFeatureTap">
|
|
<view class="feat-card" @click="handleGuestFeatureTap">
|
|
|
<text class="feat-icon">🏆</text>
|
|
<text class="feat-icon">🏆</text>
|
|
|
<text class="feat-title">里程碑</text>
|
|
<text class="feat-title">里程碑</text>
|
|
@@ -56,6 +51,11 @@
|
|
|
<text class="feat-title">家庭挑战</text>
|
|
<text class="feat-title">家庭挑战</text>
|
|
|
<text class="feat-desc">全家参与的互动任务</text>
|
|
<text class="feat-desc">全家参与的互动任务</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <view class="feat-card" @click="handleGuestFeatureTap">
|
|
|
|
|
+ <text class="feat-icon">📋</text>
|
|
|
|
|
+ <text class="feat-title">任务中心</text>
|
|
|
|
|
+ <text class="feat-desc">执行任务·完成挑战</text>
|
|
|
|
|
+ </view>
|
|
|
</view>
|
|
</view>
|
|
|
<!-- 五维健康体系 -->
|
|
<!-- 五维健康体系 -->
|
|
|
<view class="wuxing-section">
|
|
<view class="wuxing-section">
|
|
@@ -141,6 +141,58 @@
|
|
|
<text class="reminder-text">⚠ 今日还有 {{ incompleteCount }} 项未记录</text>
|
|
<text class="reminder-text">⚠ 今日还有 {{ incompleteCount }} 项未记录</text>
|
|
|
<text class="reminder-close" @click="dismissReminder">✕</text>
|
|
<text class="reminder-close" @click="dismissReminder">✕</text>
|
|
|
</view>
|
|
</view>
|
|
|
|
|
+ <!-- 里程碑(最上) -->
|
|
|
|
|
+ <view class="section">
|
|
|
|
|
+ <view class="milestone-card">
|
|
|
|
|
+ <text class="section-title-row">🏆 里程碑</text>
|
|
|
|
|
+ <view class="milestone-grid">
|
|
|
|
|
+ <view class="milestone-item">
|
|
|
|
|
+ <text class="milestone-icon">🔥</text>
|
|
|
|
|
+ <text class="milestone-value">{{ streakDays }}天</text>
|
|
|
|
|
+ <text class="milestone-label">连续打卡</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="milestone-item">
|
|
|
|
|
+ <text class="milestone-icon">🎯</text>
|
|
|
|
|
+ <text class="milestone-value">{{ activeChallenges }}</text>
|
|
|
|
|
+ <text class="milestone-label">进行中挑战</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="milestone-item">
|
|
|
|
|
+ <text class="milestone-icon">📈</text>
|
|
|
|
|
+ <text class="milestone-value">{{ completeness }}%</text>
|
|
|
|
|
+ <text class="milestone-label">档案完整度</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <!-- 健康报告状态卡片 -->
|
|
|
|
|
+ <view class="section" v-if="reportStatus.hasReport">
|
|
|
|
|
+ <view class="report-card" @click="goToReport">
|
|
|
|
|
+ <view class="report-left">
|
|
|
|
|
+ <text class="report-icon">📋</text>
|
|
|
|
|
+ <view class="report-info">
|
|
|
|
|
+ <text class="report-title">已有健康报告</text>
|
|
|
|
|
+ <text class="report-desc" v-if="reportStatus.reportType === 'gut_flora'">肠道菌群检测 · {{ reportStatus.reportDate }}</text>
|
|
|
|
|
+ <text class="report-desc" v-else-if="reportStatus.reportType === 'physical_exam'">体检报告 · {{ reportStatus.reportDate }}</text>
|
|
|
|
|
+ <text class="report-desc" v-else>健康报告 · {{ reportStatus.reportDate }}</text>
|
|
|
|
|
+ <text class="report-score" v-if="reportStatus.overallScore">综合评分:{{ reportStatus.overallScore }}分</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text class="report-arrow">›</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view class="section" v-else>
|
|
|
|
|
+ <view class="report-upload-card" @click="goToUploadReport">
|
|
|
|
|
+ <view class="report-upload-left">
|
|
|
|
|
+ <text class="report-upload-icon">📷</text>
|
|
|
|
|
+ <view class="report-upload-info">
|
|
|
|
|
+ <text class="report-upload-title">上传健康报告</text>
|
|
|
|
|
+ <text class="report-upload-desc">上传体检或菌群检测报告,获取个性化营养方案</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <text class="report-upload-arrow">›</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <!-- 今日成长 -->
|
|
|
<view class="section">
|
|
<view class="section">
|
|
|
<view class="progress-card">
|
|
<view class="progress-card">
|
|
|
<view class="progress-header">
|
|
<view class="progress-header">
|
|
@@ -170,8 +222,7 @@
|
|
|
<text class="action-arrow">›</text>
|
|
<text class="action-arrow">›</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
-
|
|
|
|
|
- <!-- 饮食推荐(恢复) -->
|
|
|
|
|
|
|
+ <!-- 饮食推荐 -->
|
|
|
<view class="section">
|
|
<view class="section">
|
|
|
<view class="action-card" @click="goToFoods">
|
|
<view class="action-card" @click="goToFoods">
|
|
|
<text class="action-icon">🍽️</text>
|
|
<text class="action-icon">🍽️</text>
|
|
@@ -182,73 +233,19 @@
|
|
|
<text class="action-arrow">›</text>
|
|
<text class="action-arrow">›</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
-
|
|
|
|
|
- <view class="section">
|
|
|
|
|
- <view class="tracking-card">
|
|
|
|
|
- <view class="tracking-tabs">
|
|
|
|
|
- <view class="tracking-tab" :class="activeTab === tab.key ? 'tab-active' : ''" v-for="tab in trackingTabs" :key="tab.key" @click="switchTab(tab.key)">
|
|
|
|
|
- <text class="tab-text" :class="activeTab === tab.key ? 'tab-active-text' : ''">{{ tab.label }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="tracking-content">
|
|
|
|
|
- <view class="tracking-empty" v-if="currentRecords.length === 0">
|
|
|
|
|
- <text class="empty-icon">📊</text>
|
|
|
|
|
- <text class="empty-text">还没有记录</text>
|
|
|
|
|
- <text class="empty-hint">开始记录{{ activeTabLabel }}吧</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="tracking-record" v-for="(rec, rIdx) in currentRecords" :key="getRecordKey(rec)">
|
|
|
|
|
- <text class="record-date">{{ rec._date || rec._text }}</text>
|
|
|
|
|
- <text class="record-content">{{ rec._content }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="tracking-more" v-if="currentRecords.length > 0" @click="viewAllRecords">查看全部 ›</view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="section">
|
|
|
|
|
- <view class="milestone-card">
|
|
|
|
|
- <text class="section-title-row">🏆 里程碑</text>
|
|
|
|
|
- <view class="milestone-grid">
|
|
|
|
|
- <view class="milestone-item">
|
|
|
|
|
- <text class="milestone-icon">🔥</text>
|
|
|
|
|
- <text class="milestone-value">{{ streakDays }}天</text>
|
|
|
|
|
- <text class="milestone-label">连续打卡</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="milestone-item">
|
|
|
|
|
- <text class="milestone-icon">🎯</text>
|
|
|
|
|
- <text class="milestone-value">{{ activeChallenges }}</text>
|
|
|
|
|
- <text class="milestone-label">进行中挑战</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="milestone-item">
|
|
|
|
|
- <text class="milestone-icon">📈</text>
|
|
|
|
|
- <text class="milestone-value">{{ completeness }}%</text>
|
|
|
|
|
- <text class="milestone-label">档案完整度</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
- </view>
|
|
|
|
|
|
|
+ <!-- 任务中心 -->
|
|
|
<view class="section">
|
|
<view class="section">
|
|
|
- <view class="survey-card">
|
|
|
|
|
- <text class="section-title-row">📋 成长记录</text>
|
|
|
|
|
- <view class="survey-pending" v-if="pendingSurvey">
|
|
|
|
|
- <text class="survey-alert">⚠ 本周还未完成调研</text>
|
|
|
|
|
- <text class="survey-title-text">{{ pendingSurvey.title }}</text>
|
|
|
|
|
- <text class="survey-btn" @click="startSurvey">[开始填写]</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <view class="survey-done" v-else-if="allDone"><text class="survey-done-text">✅ 所有调研已完成</text></view>
|
|
|
|
|
- <view class="survey-history-list" v-if="surveyHistory.length > 0">
|
|
|
|
|
- <text class="history-label">历史调研:</text>
|
|
|
|
|
- <view class="history-item" v-for="(h, hIdx) in surveyHistory" :key="getHistoryKey(h)">
|
|
|
|
|
- <text class="history-date">{{ h._date }}</text>
|
|
|
|
|
- <text class="history-content">{{ h._content }}</text>
|
|
|
|
|
- </view>
|
|
|
|
|
- <text class="survey-more" @click="viewAllHistory">查看全部调研 ›</text>
|
|
|
|
|
|
|
+ <view class="action-card" @click="goToTasks">
|
|
|
|
|
+ <text class="action-icon">📋</text>
|
|
|
|
|
+ <view class="action-info">
|
|
|
|
|
+ <text class="action-title">任务中心</text>
|
|
|
|
|
+ <text class="action-desc">查看今日待办任务,完成挑战获取奖励</text>
|
|
|
</view>
|
|
</view>
|
|
|
- <view class="survey-empty" v-else-if="!pendingSurvey"><text class="survey-empty-text">暂无待完成调研</text></view>
|
|
|
|
|
|
|
+ <text class="action-arrow">›</text>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
|
<DimensionActivities :isLoggedIn="true" @activityClick="goActivityDetail" @moreActivities="goMoreActivities" style="margin-bottom:60rpx" />
|
|
<DimensionActivities :isLoggedIn="true" @activityClick="goActivityDetail" @moreActivities="goMoreActivities" style="margin-bottom:60rpx" />
|
|
|
-
|
|
|
|
|
- <!-- 推荐商品(组件化,移到底部) -->
|
|
|
|
|
|
|
+ <!-- 推荐商品 -->
|
|
|
<view class="section">
|
|
<view class="section">
|
|
|
<view class="section-header">
|
|
<view class="section-header">
|
|
|
<text class="section-title">🛍️ 推荐商品</text>
|
|
<text class="section-title">🛍️ 推荐商品</text>
|
|
@@ -256,8 +253,7 @@
|
|
|
</view>
|
|
</view>
|
|
|
<DimensionProducts :isLoggedIn="true" :showMore="false" @productClick="goToProduct" />
|
|
<DimensionProducts :isLoggedIn="true" :showMore="false" @productClick="goToProduct" />
|
|
|
</view>
|
|
</view>
|
|
|
-
|
|
|
|
|
- <!-- 推荐阅读(组件化,移到底部) -->
|
|
|
|
|
|
|
+ <!-- 推荐阅读 -->
|
|
|
<view class="section" v-if="recommendArticles.length > 0">
|
|
<view class="section" v-if="recommendArticles.length > 0">
|
|
|
<view class="section-header">
|
|
<view class="section-header">
|
|
|
<text class="section-title">📖 推荐阅读</text>
|
|
<text class="section-title">📖 推荐阅读</text>
|
|
@@ -265,7 +261,6 @@
|
|
|
</view>
|
|
</view>
|
|
|
<ArticleBookshelf :articles="recommendArticles" :isLoggedIn="true" @articleClick="goToArticle" />
|
|
<ArticleBookshelf :articles="recommendArticles" :isLoggedIn="true" @articleClick="goToArticle" />
|
|
|
</view>
|
|
</view>
|
|
|
-
|
|
|
|
|
<view class="bottom-spacer" style="height: 40rpx;"></view>
|
|
<view class="bottom-spacer" style="height: 40rpx;"></view>
|
|
|
</view>
|
|
</view>
|
|
|
</view>
|
|
</view>
|
|
@@ -276,19 +271,18 @@ import LoginGuideCard from '../../components/LoginGuideCard.vue'
|
|
|
import DimensionActivities from '../../components/DimensionActivities.vue'
|
|
import DimensionActivities from '../../components/DimensionActivities.vue'
|
|
|
import DimensionProducts from '../../components/DimensionProducts.vue'
|
|
import DimensionProducts from '../../components/DimensionProducts.vue'
|
|
|
import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
|
|
import ArticleBookshelf from '../../components/ArticleBookshelf.vue'
|
|
|
-import { healthCheckinList, getHealthMealList, getSurveyStatus, getSurveyHistory, getFoodCautionList, getGrowthRecommendations, getExerciseRecords, getSleepRecords, getEmotionCheckinList, getCheckinList } from '../../utils/api.js'
|
|
|
|
|
|
|
+import { healthCheckinList, getHealthMealList, getFoodCautionList, getGrowthRecommendations, getExerciseRecords, getSleepRecords, getEmotionCheckinList, getCheckinList, getLatestHealthReport } from '../../utils/api.js'
|
|
|
import { parseDate } from '../../utils/format.js'
|
|
import { parseDate } from '../../utils/format.js'
|
|
|
export default {
|
|
export default {
|
|
|
components: { PageBanner, LoginGuideCard, DimensionActivities, DimensionProducts, ArticleBookshelf },
|
|
components: { PageBanner, LoginGuideCard, DimensionActivities, DimensionProducts, ArticleBookshelf },
|
|
|
- data() { return { memberId: '', todayDate: '', hasIncomplete: false, incompleteCount: 0, progressItems: [], activeTab: 'diet', trackingTabs: [{ key: 'diet', label: '饮食' }, { key: 'exercise', label: '运动' }, { key: 'sleep', label: '睡眠' }, { key: 'emotion', label: '心情' }], trackingData: { diet: [], exercise: [], sleep: [], emotion: [] }, streakDays: 0, activeChallenges: 0, completeness: 0, cautionCount: 0,
|
|
|
|
|
|
|
+ data() { return { memberId: '', todayDate: '', hasIncomplete: false, incompleteCount: 0, progressItems: [], streakDays: 0, activeChallenges: 0, completeness: 0, cautionCount: 0,
|
|
|
healthArticles: [],
|
|
healthArticles: [],
|
|
|
growthArticles: [],
|
|
growthArticles: [],
|
|
|
- pendingSurvey: null, allDone: false, surveyHistory: [], isLoggedIn: false } },
|
|
|
|
|
|
|
+ isLoggedIn: false,
|
|
|
|
|
+ reportStatus: { hasReport: false, reportId: null, reportType: '', reportDate: '', overallScore: null } } },
|
|
|
computed: {
|
|
computed: {
|
|
|
doneCount: function() { var c = 0; for (var i = 0; i < this.progressItems.length; i++) if (this.progressItems[i] && this.progressItems[i].done) c++; return c },
|
|
doneCount: function() { var c = 0; for (var i = 0; i < this.progressItems.length; i++) if (this.progressItems[i] && this.progressItems[i].done) c++; return c },
|
|
|
totalCount: function() { return this.progressItems.length },
|
|
totalCount: function() { return this.progressItems.length },
|
|
|
- activeTabLabel: function() { var m = { diet: '饮食', exercise: '运动', sleep: '睡眠', emotion: '心情' }; return m[this.activeTab] || '' },
|
|
|
|
|
- currentRecords: function() { return this.trackingData[this.activeTab] || [] },
|
|
|
|
|
recommendArticles: function() {
|
|
recommendArticles: function() {
|
|
|
var arr = []
|
|
var arr = []
|
|
|
if (this.healthArticles && this.healthArticles.length > 0) arr = arr.concat(this.healthArticles)
|
|
if (this.healthArticles && this.healthArticles.length > 0) arr = arr.concat(this.healthArticles)
|
|
@@ -308,24 +302,23 @@ export default {
|
|
|
methods: {
|
|
methods: {
|
|
|
pad: function(n) { return n < 10 ? '0' + n : '' + n },
|
|
pad: function(n) { return n < 10 ? '0' + n : '' + n },
|
|
|
getProgressKey: function(item) { return item && item.label ? item.label : 'p-' + Math.random() },
|
|
getProgressKey: function(item) { return item && item.label ? item.label : 'p-' + Math.random() },
|
|
|
- getRecordKey: function(rec) { return rec && (rec._id || rec.id) ? 'r' + (rec._id || rec.id) : (rec && rec._text ? rec._text + rec._content : 'r-' + Math.random()) },
|
|
|
|
|
- getHistoryKey: function(h) { return h && h._date ? h._date + h._content : 'h-' + Math.random() },
|
|
|
|
|
dismissReminder: function() { this.hasIncomplete = false },
|
|
dismissReminder: function() { this.hasIncomplete = false },
|
|
|
- switchTab: function(key) { this.activeTab = key; this.loadTrackingData(key) },
|
|
|
|
|
handleProgressClick: function(item) {
|
|
handleProgressClick: function(item) {
|
|
|
if (!item || !item.key) return
|
|
if (!item || !item.key) return
|
|
|
- var m = { checkin: '/pages/wealth-sub/checkin', diet: '/pages/health/diet-index', exercise: '/pages/health/exercise-index', sleep: '/pages/health/sleep-index', emotion: '/pages/mind/index' }
|
|
|
|
|
|
|
+ var m = { diet: '/pages/growth/diet-checkin', exercise: '/pages/growth/exercise-checkin', sleep: '/pages/growth/sleep-checkin', emotion: '/pages/growth/growth-emotion-checkin', checkin: '/pages/wealth-sub/checkin' }
|
|
|
var url = m[item.key]
|
|
var url = m[item.key]
|
|
|
- if (item.key === 'survey' && this.pendingSurvey && this.pendingSurvey.templateId) {
|
|
|
|
|
- url = '/pages/health/survey-questionnaire?templateId=' + this.pendingSurvey.templateId + '&templateTitle=' + encodeURIComponent(this.pendingSurvey.title) + '&templateDimension=' + (this.pendingSurvey.dimension || '')
|
|
|
|
|
- }
|
|
|
|
|
if (url) uni.navigateTo({ url: url })
|
|
if (url) uni.navigateTo({ url: url })
|
|
|
},
|
|
},
|
|
|
- startSurvey: function() { if (this.pendingSurvey && this.pendingSurvey.templateId) uni.navigateTo({ url: '/pages/health/survey-questionnaire?templateId=' + this.pendingSurvey.templateId + '&templateTitle=' + encodeURIComponent(this.pendingSurvey.title) + '&templateDimension=' + (this.pendingSurvey.dimension || '') }) },
|
|
|
|
|
- viewAllRecords: function() { var m = { diet: '/pages/health/diet-index', exercise: '/pages/health/exercise-index', sleep: '/pages/health/sleep-index', emotion: '/pages/mind/index' }; if (m[this.activeTab]) uni.navigateTo({ url: m[this.activeTab] }) },
|
|
|
|
|
- viewAllHistory: function() { uni.navigateTo({ url: '/pages/health/survey-history?memberId=' + this.memberId }) },
|
|
|
|
|
|
|
+ goToReport: function() {
|
|
|
|
|
+ if (this.reportStatus.reportId) uni.navigateTo({ url: '/pages/health/report-detail?id=' + this.reportStatus.reportId })
|
|
|
|
|
+ },
|
|
|
|
|
+ goToUploadReport: function() {
|
|
|
|
|
+ var id = this.memberId || ''
|
|
|
|
|
+ uni.navigateTo({ url: '/pages/health/report-upload?memberId=' + id + '&from=growth' })
|
|
|
|
|
+ },
|
|
|
goActivityDetail: function(act) { uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id }) },
|
|
goActivityDetail: function(act) { uni.navigateTo({ url: '/pages/activity/activity-detail/activity-detail?id=' + act.id }) },
|
|
|
goMoreActivities: function() { uni.navigateTo({ url: '/pages/activity/index' }) },
|
|
goMoreActivities: function() { uni.navigateTo({ url: '/pages/activity/index' }) },
|
|
|
|
|
+ goToTasks: function() { uni.navigateTo({ url: '/pages/child/tasks' }) },
|
|
|
handleGuestFeatureTap: function() { uni.showToast({ title: '登录后即可体验该功能', icon: 'none' }) },
|
|
handleGuestFeatureTap: function() { uni.showToast({ title: '登录后即可体验该功能', icon: 'none' }) },
|
|
|
goToCaution: function() { uni.navigateTo({ url: '/pages/growth/caution-detail' }) },
|
|
goToCaution: function() { uni.navigateTo({ url: '/pages/growth/caution-detail' }) },
|
|
|
goToFoods: function() { uni.navigateTo({ url: '/pages/growth/foods-detail' }) },
|
|
goToFoods: function() { uni.navigateTo({ url: '/pages/growth/foods-detail' }) },
|
|
@@ -334,7 +327,6 @@ export default {
|
|
|
goMoreProducts: function() { uni.navigateTo({ url: '/pages/shop/index/index' }) },
|
|
goMoreProducts: function() { uni.navigateTo({ url: '/pages/shop/index/index' }) },
|
|
|
goMoreArticles: function() { uni.navigateTo({ url: '/pages/article-center/index?dimension=action' }) },
|
|
goMoreArticles: function() { uni.navigateTo({ url: '/pages/article-center/index?dimension=action' }) },
|
|
|
goPage: function(url) { uni.navigateTo({ url: url }) },
|
|
goPage: function(url) { uni.navigateTo({ url: url }) },
|
|
|
- loadTrackingData: function(key) { return this.trackingData[key] || [] },
|
|
|
|
|
formatDateKey: function(dateVal) {
|
|
formatDateKey: function(dateVal) {
|
|
|
if (!dateVal) return ''
|
|
if (!dateVal) return ''
|
|
|
var d = parseDate(dateVal)
|
|
var d = parseDate(dateVal)
|
|
@@ -353,87 +345,85 @@ export default {
|
|
|
},
|
|
},
|
|
|
async loadAllData() {
|
|
async loadAllData() {
|
|
|
var self = this
|
|
var self = this
|
|
|
|
|
+ try { await self.loadReportStatus() } catch(e) {}
|
|
|
try { await self.loadProgressItems() } catch(e) {}
|
|
try { await self.loadProgressItems() } catch(e) {}
|
|
|
try { await self.loadCautionData() } catch(e) {}
|
|
try { await self.loadCautionData() } catch(e) {}
|
|
|
try { await self.loadGrowthRecommendations() } catch(e) {}
|
|
try { await self.loadGrowthRecommendations() } catch(e) {}
|
|
|
- try { await self.loadSurveyData() } catch(e) {}
|
|
|
|
|
try { await self.loadMilestones() } catch(e) {}
|
|
try { await self.loadMilestones() } catch(e) {}
|
|
|
},
|
|
},
|
|
|
|
|
+ async loadReportStatus() {
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ if (!self.memberId) return
|
|
|
|
|
+ try {
|
|
|
|
|
+ var res = await getLatestHealthReport(self.memberId)
|
|
|
|
|
+ if (res.code === 200 && res.data) {
|
|
|
|
|
+ var r = res.data
|
|
|
|
|
+ self.reportStatus = {
|
|
|
|
|
+ hasReport: true,
|
|
|
|
|
+ reportId: r.id,
|
|
|
|
|
+ reportType: r.reportType || '',
|
|
|
|
|
+ reportDate: r.reportDate ? r.reportDate.substring(0, 10) : '',
|
|
|
|
|
+ overallScore: r.overallScore || null
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ self.reportStatus = { hasReport: false, reportId: null, reportType: '', reportDate: '', overallScore: null }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch(e) {
|
|
|
|
|
+ self.reportStatus = { hasReport: false, reportId: null, reportType: '', reportDate: '', overallScore: null }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
async loadProgressItems() {
|
|
async loadProgressItems() {
|
|
|
var self = this
|
|
var self = this
|
|
|
var items = []
|
|
var items = []
|
|
|
- // 饮食记录:health/meal/list 返回当日记录数组
|
|
|
|
|
var dietDone = false
|
|
var dietDone = false
|
|
|
try {
|
|
try {
|
|
|
var dParams = self.memberId ? { memberId: self.memberId } : {}
|
|
var dParams = self.memberId ? { memberId: self.memberId } : {}
|
|
|
var dRes = await getHealthMealList(dParams)
|
|
var dRes = await getHealthMealList(dParams)
|
|
|
var dList = (dRes.code === 200 && dRes.data) ? dRes.data : []
|
|
var dList = (dRes.code === 200 && dRes.data) ? dRes.data : []
|
|
|
- self.trackingData.diet = []
|
|
|
|
|
for (var di = 0; di < dList.length; di++) {
|
|
for (var di = 0; di < dList.length; di++) {
|
|
|
var dr = dList[di]
|
|
var dr = dList[di]
|
|
|
if (!dr) continue
|
|
if (!dr) continue
|
|
|
if (self.formatDateKey(dr.createdAt || dr.recordDate) === self.todayDate) dietDone = true
|
|
if (self.formatDateKey(dr.createdAt || dr.recordDate) === self.todayDate) dietDone = true
|
|
|
- if (di < 5) {
|
|
|
|
|
- var foods = dr.foodNames || dr.mealContent || dr.notes || ''
|
|
|
|
|
- self.trackingData.diet.push({ _id: dr.id, _date: self.mealTypeLabel(dr.mealType), _content: foods || '已记录' })
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
} catch(e) {}
|
|
} catch(e) {}
|
|
|
items.push({ key: 'diet', icon: '🍽️', label: '饮食记录', done: dietDone, actionText: '补录' })
|
|
items.push({ key: 'diet', icon: '🍽️', label: '饮食记录', done: dietDone, actionText: '补录' })
|
|
|
- // 运动记录
|
|
|
|
|
var exerciseDone = false
|
|
var exerciseDone = false
|
|
|
try {
|
|
try {
|
|
|
var eParams = self.memberId ? { memberId: self.memberId } : {}
|
|
var eParams = self.memberId ? { memberId: self.memberId } : {}
|
|
|
var eRes = await getExerciseRecords(eParams)
|
|
var eRes = await getExerciseRecords(eParams)
|
|
|
var eList = (eRes.code === 200 && eRes.data) ? eRes.data : []
|
|
var eList = (eRes.code === 200 && eRes.data) ? eRes.data : []
|
|
|
- self.trackingData.exercise = []
|
|
|
|
|
for (var ei = 0; ei < eList.length; ei++) {
|
|
for (var ei = 0; ei < eList.length; ei++) {
|
|
|
var er = eList[ei]
|
|
var er = eList[ei]
|
|
|
if (!er) continue
|
|
if (!er) continue
|
|
|
if (self.formatDateKey(er.startTime || er.createdAt) === self.todayDate) exerciseDone = true
|
|
if (self.formatDateKey(er.startTime || er.createdAt) === self.todayDate) exerciseDone = true
|
|
|
- if (ei < 5) {
|
|
|
|
|
- var eText = (er.exerciseType || '运动') + (er.durationMinutes ? ' ' + er.durationMinutes + '分钟' : '') + (er.caloriesBurned ? ' · ' + er.caloriesBurned + '千卡' : '')
|
|
|
|
|
- self.trackingData.exercise.push({ _id: er.id, _date: self.formatRecordDate(er.startTime || er.createdAt), _content: eText })
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
} catch(e) {}
|
|
} catch(e) {}
|
|
|
items.push({ key: 'exercise', icon: '🏃', label: '运动记录', done: exerciseDone, actionText: '记录' })
|
|
items.push({ key: 'exercise', icon: '🏃', label: '运动记录', done: exerciseDone, actionText: '记录' })
|
|
|
- // 睡眠记录
|
|
|
|
|
var sleepDone = false
|
|
var sleepDone = false
|
|
|
try {
|
|
try {
|
|
|
var sParams = self.memberId ? { memberId: self.memberId } : {}
|
|
var sParams = self.memberId ? { memberId: self.memberId } : {}
|
|
|
var sRes = await getSleepRecords(sParams)
|
|
var sRes = await getSleepRecords(sParams)
|
|
|
var sList = (sRes.code === 200 && sRes.data) ? sRes.data : []
|
|
var sList = (sRes.code === 200 && sRes.data) ? sRes.data : []
|
|
|
- self.trackingData.sleep = []
|
|
|
|
|
for (var si = 0; si < sList.length; si++) {
|
|
for (var si = 0; si < sList.length; si++) {
|
|
|
var sr = sList[si]
|
|
var sr = sList[si]
|
|
|
if (!sr) continue
|
|
if (!sr) continue
|
|
|
if (self.formatDateKey(sr.sleepTime || sr.createdAt) === self.todayDate) sleepDone = true
|
|
if (self.formatDateKey(sr.sleepTime || sr.createdAt) === self.todayDate) sleepDone = true
|
|
|
- if (si < 5) {
|
|
|
|
|
- var sText = (sr.durationMinutes ? sr.durationMinutes + '分钟' : '') + (sr.qualityScore ? ' · 质量' + sr.qualityScore + '分' : '')
|
|
|
|
|
- self.trackingData.sleep.push({ _id: sr.id, _date: self.formatRecordDate(sr.sleepTime || sr.createdAt), _content: sText || '已记录' })
|
|
|
|
|
- }
|
|
|
|
|
}
|
|
}
|
|
|
} catch(e) {}
|
|
} catch(e) {}
|
|
|
items.push({ key: 'sleep', icon: '😴', label: '睡眠记录', done: sleepDone, actionText: '记录' })
|
|
items.push({ key: 'sleep', icon: '😴', label: '睡眠记录', done: sleepDone, actionText: '记录' })
|
|
|
- // 心情记录:mind/checkin/list 返回 List<EmotionCheckinVO>
|
|
|
|
|
var emotionDone = false
|
|
var emotionDone = false
|
|
|
try {
|
|
try {
|
|
|
var mParams = { page: 1, size: 10 }
|
|
var mParams = { page: 1, size: 10 }
|
|
|
if (self.memberId) mParams.memberId = self.memberId
|
|
if (self.memberId) mParams.memberId = self.memberId
|
|
|
var mRes = await getEmotionCheckinList(mParams)
|
|
var mRes = await getEmotionCheckinList(mParams)
|
|
|
var mList = (mRes.code === 200 && mRes.data) ? mRes.data : []
|
|
var mList = (mRes.code === 200 && mRes.data) ? mRes.data : []
|
|
|
- self.trackingData.emotion = []
|
|
|
|
|
for (var mi = 0; mi < mList.length; mi++) {
|
|
for (var mi = 0; mi < mList.length; mi++) {
|
|
|
var mr = mList[mi]
|
|
var mr = mList[mi]
|
|
|
if (!mr) continue
|
|
if (!mr) continue
|
|
|
if (self.formatDateKey(mr.checkinDate || mr.createdAt) === self.todayDate) emotionDone = true
|
|
if (self.formatDateKey(mr.checkinDate || mr.createdAt) === self.todayDate) emotionDone = true
|
|
|
- var mText = (mr.moodWeather || '') + (mr.moodScore ? ' · ' + mr.moodScore + '分' : '')
|
|
|
|
|
- self.trackingData.emotion.push({ _id: mr.id, _date: self.formatRecordDate(mr.checkinDate || mr.createdAt), _content: mText || (mr.note || '已记录') })
|
|
|
|
|
}
|
|
}
|
|
|
} catch(e) {}
|
|
} catch(e) {}
|
|
|
items.push({ key: 'emotion', icon: '😊', label: '心情记录', done: emotionDone, actionText: '记录' })
|
|
items.push({ key: 'emotion', icon: '😊', label: '心情记录', done: emotionDone, actionText: '记录' })
|
|
|
- // 记账打卡
|
|
|
|
|
var checkinDone = false
|
|
var checkinDone = false
|
|
|
try {
|
|
try {
|
|
|
var cParams = self.memberId ? { memberId: self.memberId } : {}
|
|
var cParams = self.memberId ? { memberId: self.memberId } : {}
|
|
@@ -452,32 +442,12 @@ export default {
|
|
|
for (var pi = 0; pi < items.length; pi++) if (items[pi] && !items[pi].done) self.incompleteCount++
|
|
for (var pi = 0; pi < items.length; pi++) if (items[pi] && !items[pi].done) self.incompleteCount++
|
|
|
self.hasIncomplete = self.incompleteCount > 0
|
|
self.hasIncomplete = self.incompleteCount > 0
|
|
|
},
|
|
},
|
|
|
- async loadSurveyData() {
|
|
|
|
|
- var self = this
|
|
|
|
|
- try {
|
|
|
|
|
- var statusRes = await getSurveyStatus({})
|
|
|
|
|
- if (statusRes.code === 200 && statusRes.data) {
|
|
|
|
|
- var list = statusRes.data
|
|
|
|
|
- self.pendingSurvey = null; self.allDone = true; var hasAny = false
|
|
|
|
|
- for (var si = 0; si < list.length; si++) { var s = list[si]; if (!s) continue; hasAny = true; if (s.status === 'pending') { self.pendingSurvey = { templateId: s.templateId, title: s.title || '成长记录', dimension: s.dimension || '' }; self.allDone = false } }
|
|
|
|
|
- if (!hasAny) { self.pendingSurvey = null; self.allDone = false }
|
|
|
|
|
- }
|
|
|
|
|
- } catch(e) {}
|
|
|
|
|
- try {
|
|
|
|
|
- var histRes = await getSurveyHistory({})
|
|
|
|
|
- if (histRes.code === 200 && histRes.data) {
|
|
|
|
|
- var hlist = histRes.data; self.surveyHistory = []
|
|
|
|
|
- for (var hi = 0; hi < Math.min(hlist.length, 3); hi++) { var h = hlist[hi]; self.surveyHistory.push({ _date: h && h.submittedAt ? h.submittedAt.substring(0, 10) : '', _content: '已完成调研' }) }
|
|
|
|
|
- }
|
|
|
|
|
- } catch(e) {}
|
|
|
|
|
- },
|
|
|
|
|
async loadGrowthRecommendations() {
|
|
async loadGrowthRecommendations() {
|
|
|
var self = this
|
|
var self = this
|
|
|
try {
|
|
try {
|
|
|
var res = await getGrowthRecommendations('health', 6)
|
|
var res = await getGrowthRecommendations('health', 6)
|
|
|
if (res && res.code === 200 && res.data) {
|
|
if (res && res.code === 200 && res.data) {
|
|
|
var arts = res.data.articles || []
|
|
var arts = res.data.articles || []
|
|
|
- // 按 growth_category 分组
|
|
|
|
|
self.healthArticles = arts.filter(function(a){ return a.growthCategory === 'health' })
|
|
self.healthArticles = arts.filter(function(a){ return a.growthCategory === 'health' })
|
|
|
self.growthArticles = arts.filter(function(a){ return a.growthCategory === 'growth' })
|
|
self.growthArticles = arts.filter(function(a){ return a.growthCategory === 'growth' })
|
|
|
}
|
|
}
|
|
@@ -536,23 +506,27 @@ export default {
|
|
|
.action-title{font-size:28rpx;font-weight:600;color:#333;display:block}
|
|
.action-title{font-size:28rpx;font-weight:600;color:#333;display:block}
|
|
|
.action-desc{font-size:22rpx;color:#888;margin-top:4rpx;display:block}
|
|
.action-desc{font-size:22rpx;color:#888;margin-top:4rpx;display:block}
|
|
|
.action-arrow{font-size:32rpx;color:#ccc}
|
|
.action-arrow{font-size:32rpx;color:#ccc}
|
|
|
-/* section-header 组件通用样式(推荐商品/阅读) */
|
|
|
|
|
|
|
+/* section-header 组件通用样式 */
|
|
|
.section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12rpx}
|
|
.section-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:12rpx}
|
|
|
.section-title{font-size:28rpx;font-weight:600;color:#333}
|
|
.section-title{font-size:28rpx;font-weight:600;color:#333}
|
|
|
.section-more{font-size:24rpx;color:#F97316}
|
|
.section-more{font-size:24rpx;color:#F97316}
|
|
|
-/* 登录后原有样式 */
|
|
|
|
|
|
|
+/* 登录后 */
|
|
|
.reminder-bar{margin:12rpx 24rpx;background:#FFF3E0;border:1rpx solid #FFB74D;border-radius:12rpx;padding:14rpx 20rpx;display:flex;align-items:center;justify-content:space-between}
|
|
.reminder-bar{margin:12rpx 24rpx;background:#FFF3E0;border:1rpx solid #FFB74D;border-radius:12rpx;padding:14rpx 20rpx;display:flex;align-items:center;justify-content:space-between}
|
|
|
.reminder-text{font-size:24rpx;color:#E65100}
|
|
.reminder-text{font-size:24rpx;color:#E65100}
|
|
|
.reminder-close{font-size:28rpx;color:#999}
|
|
.reminder-close{font-size:28rpx;color:#999}
|
|
|
|
|
+/* 里程碑 */
|
|
|
|
|
+.milestone-card{background:#fff;border-radius:20rpx;padding:24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06)}
|
|
|
|
|
+.section-title-row{font-size:26rpx;font-weight:bold;color:#333;margin-bottom:16rpx;display:block}
|
|
|
|
|
+.milestone-grid{display:flex;justify-content:space-between}
|
|
|
|
|
+.milestone-item{display:flex;flex-direction:column;align-items:center;flex:1}
|
|
|
|
|
+.milestone-icon{font-size:40rpx;margin-bottom:4rpx}
|
|
|
|
|
+.milestone-value{font-size:28rpx;font-weight:bold;color:#F97316;margin-bottom:2rpx}
|
|
|
|
|
+.milestone-label{font-size:22rpx;color:#999}
|
|
|
|
|
+/* 今日成长 */
|
|
|
.progress-card{background:#fff;border-radius:20rpx;padding:24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06)}
|
|
.progress-card{background:#fff;border-radius:20rpx;padding:24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06)}
|
|
|
.progress-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16rpx}
|
|
.progress-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16rpx}
|
|
|
.progress-title{font-size:28rpx;font-weight:bold;color:#333}
|
|
.progress-title{font-size:28rpx;font-weight:bold;color:#333}
|
|
|
.progress-date{font-size:22rpx;color:#999}
|
|
.progress-date{font-size:22rpx;color:#999}
|
|
|
-.progress-item{display:flex;align-items:center;padding:12rpx 0;border-bottom:1rpx solid #f5f5f5}
|
|
|
|
|
-.progress-item:last-of-type{border-bottom:none}
|
|
|
|
|
-.progress-icon{font-size:28rpx;margin-right:12rpx;flex-shrink:0}
|
|
|
|
|
-.progress-label{font-size:26rpx;color:#333;flex:1}
|
|
|
|
|
-.progress-status{font-size:22rpx;margin-right:8rpx;flex-shrink:0}
|
|
|
|
|
.progress-grid{display:flex;justify-content:space-between}
|
|
.progress-grid{display:flex;justify-content:space-between}
|
|
|
.progress-grid-item{flex:1;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20rpx 8rpx;background:#FFF7ED;border-radius:16rpx;margin-right:12rpx}
|
|
.progress-grid-item{flex:1;box-sizing:border-box;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:20rpx 8rpx;background:#FFF7ED;border-radius:16rpx;margin-right:12rpx}
|
|
|
.progress-grid-item:last-child{margin-right:0}
|
|
.progress-grid-item:last-child{margin-right:0}
|
|
@@ -562,54 +536,32 @@ export default {
|
|
|
.progress-grid-status{font-size:20rpx;flex-shrink:0}
|
|
.progress-grid-status{font-size:20rpx;flex-shrink:0}
|
|
|
.status-done{color:#10B981}
|
|
.status-done{color:#10B981}
|
|
|
.status-pending{color:#ccc}
|
|
.status-pending{color:#ccc}
|
|
|
-.progress-btn{font-size:22rpx;color:#F97316;padding:4rpx 16rpx;border:1rpx solid #F97316;border-radius:20rpx;flex-shrink:0}
|
|
|
|
|
.progress-footer{display:flex;justify-content:space-between;align-items:center;margin-top:16rpx;padding-top:16rpx;border-top:1rpx solid #f5f5f5}
|
|
.progress-footer{display:flex;justify-content:space-between;align-items:center;margin-top:16rpx;padding-top:16rpx;border-top:1rpx solid #f5f5f5}
|
|
|
.footer-text{font-size:24rpx;color:#666;font-weight:bold}
|
|
.footer-text{font-size:24rpx;color:#666;font-weight:bold}
|
|
|
.footer-streak{font-size:24rpx;color:#F97316;font-weight:bold}
|
|
.footer-streak{font-size:24rpx;color:#F97316;font-weight:bold}
|
|
|
-.tracking-card{background:#fff;border-radius:20rpx;padding:24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06)}
|
|
|
|
|
-.tracking-tabs{display:flex;margin-bottom:16rpx}
|
|
|
|
|
-.tracking-tab{flex:1;text-align:center;padding:10rpx 0;border-radius:20rpx;margin-right:8rpx;background:#FFF7ED}
|
|
|
|
|
-.tracking-tab:last-child{margin-right:0}
|
|
|
|
|
-.tab-active{background:#F97316}
|
|
|
|
|
-.tab-text{font-size:24rpx;color:#666}
|
|
|
|
|
-.tab-active-text{color:#fff;font-weight:bold}
|
|
|
|
|
-.tracking-content{min-height:200rpx}
|
|
|
|
|
-.tracking-empty{display:flex;flex-direction:column;align-items:center;padding:60rpx 0}
|
|
|
|
|
-.empty-icon{font-size:60rpx;margin-bottom:12rpx}
|
|
|
|
|
-.empty-text{font-size:26rpx;color:#999}
|
|
|
|
|
-.empty-hint{font-size:22rpx;color:#ccc;margin-top:8rpx}
|
|
|
|
|
-.tracking-record{display:flex;align-items:center;padding:10rpx 0;border-bottom:1rpx solid #f5f5f5}
|
|
|
|
|
-.record-date{font-size:22rpx;color:#999;width:120rpx;flex-shrink:0}
|
|
|
|
|
-.record-content{font-size:24rpx;color:#333;flex:1}
|
|
|
|
|
-.tracking-more{text-align:right;font-size:24rpx;color:#F97316;padding:12rpx 0 0 0}
|
|
|
|
|
-.milestone-card{background:#fff;border-radius:20rpx;padding:24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06)}
|
|
|
|
|
-.section-title-row{font-size:26rpx;font-weight:bold;color:#333;margin-bottom:16rpx;display:block}
|
|
|
|
|
-.milestone-grid{display:flex;justify-content:space-between}
|
|
|
|
|
-.milestone-item{display:flex;flex-direction:column;align-items:center;flex:1}
|
|
|
|
|
-.milestone-icon{font-size:40rpx;margin-bottom:4rpx}
|
|
|
|
|
-.milestone-value{font-size:28rpx;font-weight:bold;color:#F97316;margin-bottom:2rpx}
|
|
|
|
|
-.milestone-label{font-size:22rpx;color:#999}
|
|
|
|
|
-.survey-card{background:#fff;border-radius:20rpx;padding:24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06)}
|
|
|
|
|
-.survey-pending{background:#FFF3E0;border-radius:12rpx;padding:16rpx;margin-bottom:12rpx}
|
|
|
|
|
-.survey-alert{font-size:24rpx;color:#E65100;font-weight:bold;display:block;margin-bottom:4rpx}
|
|
|
|
|
-.survey-title-text{font-size:24rpx;color:#333;display:block;margin-bottom:8rpx}
|
|
|
|
|
-.survey-btn{font-size:22rpx;color:#F97316;font-weight:bold}
|
|
|
|
|
-.survey-done{padding:8rpx 0}
|
|
|
|
|
-.survey-done-text{font-size:24rpx;color:#10B981}
|
|
|
|
|
-.survey-history-list{border-top:1rpx solid #f5f5f5;padding-top:12rpx}
|
|
|
|
|
-.history-label{font-size:22rpx;color:#999;display:block;margin-bottom:6rpx}
|
|
|
|
|
-.history-item{display:flex;align-items:center;padding:6rpx 0}
|
|
|
|
|
-.history-date{font-size:22rpx;color:#999;width:120rpx;flex-shrink:0}
|
|
|
|
|
-.history-content{font-size:24rpx;color:#666;flex:1}
|
|
|
|
|
-.survey-more{text-align:right;font-size:22rpx;color:#F97316;padding-top:8rpx}
|
|
|
|
|
-.survey-empty{padding:12rpx 0}
|
|
|
|
|
-.survey-empty-text{font-size:24rpx;color:#999}
|
|
|
|
|
-
|
|
|
|
|
|
|
+/* 报告状态卡片 */
|
|
|
|
|
+.report-card{background:#fff;border-radius:16rpx;padding:20rpx 24rpx;box-shadow:0 2rpx 12rpx rgba(0,0,0,0.06);display:flex;align-items:center;cursor:pointer}
|
|
|
|
|
+.report-card:active{opacity:0.85}
|
|
|
|
|
+.report-left{display:flex;align-items:center;flex:1;min-width:0}
|
|
|
|
|
+.report-icon{font-size:40rpx;margin-right:16rpx;flex-shrink:0}
|
|
|
|
|
+.report-info{flex:1;min-width:0}
|
|
|
|
|
+.report-title{font-size:28rpx;font-weight:600;color:#333;display:block}
|
|
|
|
|
+.report-desc{font-size:22rpx;color:#888;display:block;margin-top:4rpx;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
|
|
|
|
|
+.report-score{font-size:22rpx;color:#10B981;font-weight:bold;display:block;margin-top:2rpx}
|
|
|
|
|
+.report-arrow{font-size:32rpx;color:#ccc;flex-shrink:0}
|
|
|
|
|
+/* 报告上传提示卡 */
|
|
|
|
|
+.report-upload-card{background:linear-gradient(135deg,#FF8C42,#F97316);border-radius:16rpx;padding:20rpx 24rpx;box-shadow:0 4rpx 16rpx rgba(249,115,22,0.25);display:flex;align-items:center}
|
|
|
|
|
+.report-upload-card:active{opacity:0.9}
|
|
|
|
|
+.report-upload-left{display:flex;align-items:center;flex:1;min-width:0}
|
|
|
|
|
+.report-upload-icon{font-size:44rpx;margin-right:16rpx;flex-shrink:0}
|
|
|
|
|
+.report-upload-info{flex:1;min-width:0}
|
|
|
|
|
+.report-upload-title{font-size:28rpx;font-weight:600;color:#fff;display:block}
|
|
|
|
|
+.report-upload-desc{font-size:22rpx;color:rgba(255,255,255,0.85);display:block;margin-top:4rpx}
|
|
|
|
|
+.report-upload-arrow{font-size:32rpx;color:rgba(255,255,255,0.7);flex-shrink:0}
|
|
|
/* ===== 五维闭环体系样式 ===== */
|
|
/* ===== 五维闭环体系样式 ===== */
|
|
|
.wuxing-section { margin: 0 24rpx 16rpx; background: #fff; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
|
|
.wuxing-section { margin: 0 24rpx 16rpx; background: #fff; border-radius: 20rpx; padding: 24rpx; box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.06); }
|
|
|
.wuxing-title { font-size: 30rpx; font-weight: bold; color: #333; text-align: center; margin-bottom: 6rpx; }
|
|
.wuxing-title { font-size: 30rpx; font-weight: bold; color: #333; text-align: center; margin-bottom: 6rpx; }
|
|
|
.wuxing-desc { font-size: 22rpx; color: #999; text-align: center; margin-bottom: 20rpx; }
|
|
.wuxing-desc { font-size: 22rpx; color: #999; text-align: center; margin-bottom: 20rpx; }
|
|
|
-.wuxing-diagram { position: relative; height: 320rpx; margin: 0 auto 20rpx; }
|
|
|
|
|
.wuxing-relations { margin-top: 8rpx; }
|
|
.wuxing-relations { margin-top: 8rpx; }
|
|
|
.rel-group { margin-bottom: 16rpx; }
|
|
.rel-group { margin-bottom: 16rpx; }
|
|
|
.rel-title { font-size: 24rpx; font-weight: bold; color: #333; margin-bottom: 8rpx; display: block; }
|
|
.rel-title { font-size: 24rpx; font-weight: bold; color: #333; margin-bottom: 8rpx; display: block; }
|