|
|
@@ -67,80 +67,56 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 五行相生寻源建议(P0-2) -->
|
|
|
+ <!-- AI 健康解读(P0-1) -->
|
|
|
<view class="scr-card" v-if="result.advices && result.advices.length > 0">
|
|
|
<view class="scr-card-title">
|
|
|
- <text class="scr-card-title-text">五行相生 · 寻源建议</text>
|
|
|
- <text class="scr-card-sub">低分维度 {{ result.advices.length }} 项</text>
|
|
|
+ <text class="scr-card-title-text">AI 健康解读</text>
|
|
|
+ <text class="scr-card-sub">基于你的五维自检结果</text>
|
|
|
</view>
|
|
|
- <view class="scr-advice-intro">低于6分的维度,先别硬补——从"生"它的上游借力,同时避开"克"它的压制源:</view>
|
|
|
- <view class="scr-advice-item" v-for="adv in result.advices" :key="adv.dimension">
|
|
|
- <!-- 低分维度 -->
|
|
|
+ <view v-for="adv in result.advices" :key="adv.dimension" class="scr-advice-item">
|
|
|
<view class="scr-advice-dim-row">
|
|
|
<view class="scr-advice-dim-badge" :style="{ background: adv.color }">
|
|
|
<text class="scr-advice-dim-name">{{ adv.dimensionName }}</text>
|
|
|
- <text class="scr-advice-dim-elem">{{ adv.element }}</text>
|
|
|
+ <text class="scr-advice-dim-elem">{{ adv.score }}分</text>
|
|
|
</view>
|
|
|
- <text class="scr-advice-dim-score">{{ adv.score }}分</text>
|
|
|
</view>
|
|
|
-
|
|
|
- <!-- 相生寻源 -->
|
|
|
- <view class="scr-advice-flow">
|
|
|
- <view class="scr-flow-node">
|
|
|
- <view class="scr-flow-dot" :style="{ background: adv.upstreamColor }"></view>
|
|
|
- <text class="scr-flow-label">上游 · {{ adv.upstreamName }}({{ adv.upstreamElement }})</text>
|
|
|
- </view>
|
|
|
- <text class="scr-flow-arrow">⟶</text>
|
|
|
- <text class="scr-flow-action">{{ adv.upstreamReason }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 相克寻源 -->
|
|
|
- <view class="scr-advice-flow">
|
|
|
- <view class="scr-flow-node">
|
|
|
- <view class="scr-flow-dot" :style="{ background: adv.restrainerColor }"></view>
|
|
|
- <text class="scr-flow-label">压制 · {{ adv.restrainerName }}({{ adv.restrainerElement }})</text>
|
|
|
- </view>
|
|
|
- <text class="scr-flow-arrow">⛔</text>
|
|
|
- <text class="scr-flow-action">{{ adv.restrainerReason }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 行动建议 -->
|
|
|
- <view class="scr-advice-action">
|
|
|
- <text class="scr-advice-action-label">本周行动</text>
|
|
|
- <text class="scr-advice-action-text">{{ adv.action }}</text>
|
|
|
- </view>
|
|
|
-
|
|
|
- <!-- 一键加入今日微行动(微行动×五维联动) -->
|
|
|
- <view class="scr-micro-row" v-if="joinedDims[adv.dimension]">
|
|
|
- <text class="scr-micro-done">✅ 今日微行动已完成,能量已入账</text>
|
|
|
- </view>
|
|
|
- <view class="scr-micro-row" v-else>
|
|
|
- <button class="scr-micro-btn" :loading="joiningDim === adv.dimension" :disabled="joiningDim !== ''" @click="joinMicroAction(adv)">
|
|
|
- ⚡ 加入今日微行动
|
|
|
- </button>
|
|
|
+ <text class="scr-advice-interpretation" v-if="adv.interpretation">{{ adv.interpretation }}</text>
|
|
|
+ <view class="scr-advice-actions" v-if="adv.microActions && adv.microActions.length > 0">
|
|
|
+ <text class="scr-advice-action-label">本周行动:</text>
|
|
|
+ <text v-for="(action, i) in adv.microActions" :key="'ma'+i" class="scr-advice-action">{{ i+1 }}. {{ action }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
+ <view class="scr-family-insight" v-if="result.advices[0] && result.advices[0].familyInsight">
|
|
|
+ <text class="scr-family-insight-label">💡 家庭整体洞察</text>
|
|
|
+ <text class="scr-family-insight-text">{{ result.advices[0].familyInsight }}</text>
|
|
|
+ </view>
|
|
|
+ <view class="scr-fallback" v-if="result.advices[0] && result.advices[0].fallbackUsed">
|
|
|
+ <text>AI 分析暂时不可用,请稍后再试</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
-
|
|
|
<!-- 全部健康提示 -->
|
|
|
- <view class="scr-card" v-else>
|
|
|
+ <view class="scr-card" v-else-if="result.totalScore >= 35">
|
|
|
<view class="scr-all-healthy">
|
|
|
<text class="scr-all-healthy-icon">🌿</text>
|
|
|
<text class="scr-all-healthy-text">五维状态均健康,请继续保持这份平衡!</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
- <!-- 历史与重测 -->
|
|
|
+ <!-- 历史与操作 -->
|
|
|
<view class="scr-footer">
|
|
|
<button class="scr-btn scr-btn-primary" @click="goHistory">历史记录</button>
|
|
|
<button class="scr-btn scr-btn-outline" @click="retake">重新自检</button>
|
|
|
+ <button class="scr-btn scr-btn-secondary" v-if="hasLowScore" :loading="planGenerating" @click="generatePlan">
|
|
|
+ 生成健康计划
|
|
|
+ </button>
|
|
|
+ <button class="scr-btn scr-btn-ghost" @click="askAI">问问 AI</button>
|
|
|
</view>
|
|
|
</template>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { getSelfCheckLatest, getSelfCheckHistory } from '@/utils/api'
|
|
|
+import { getSelfCheckLatest, getSelfCheckHistory, generateSelfCheckPlan } from '@/utils/api'
|
|
|
import { microActionToday, microActionComplete } from '@/utils/api'
|
|
|
import { parseDate } from '@/utils/format.js'
|
|
|
|
|
|
@@ -164,7 +140,8 @@ export default {
|
|
|
},
|
|
|
// 今日微行动联动状态
|
|
|
joiningDim: '',
|
|
|
- joinedDims: {}
|
|
|
+ joinedDims: {},
|
|
|
+ planGenerating: false
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -176,6 +153,11 @@ export default {
|
|
|
},
|
|
|
overallLevelName: function() {
|
|
|
return this.levelMap[this.overallLevel] || '留意'
|
|
|
+ },
|
|
|
+ hasLowScore: function() {
|
|
|
+ return this.result && this.result.advices && this.result.advices.some(function(a) {
|
|
|
+ return a.score != null && a.score <= 6
|
|
|
+ })
|
|
|
}
|
|
|
},
|
|
|
onLoad: function(options) {
|
|
|
@@ -393,6 +375,33 @@ export default {
|
|
|
},
|
|
|
retake: function() {
|
|
|
uni.navigateTo({ url: '/pages/family/self-check-entry' })
|
|
|
+ },
|
|
|
+ generatePlan: function() {
|
|
|
+ var self = this
|
|
|
+ if (this.planGenerating) return
|
|
|
+ this.planGenerating = true
|
|
|
+ generateSelfCheckPlan({ checkId: this.result && this.result.id }).then(function(res) {
|
|
|
+ self.planGenerating = false
|
|
|
+ if (res.code === 200 && res.data && res.data.planId) {
|
|
|
+ uni.showToast({ title: '计划已生成,可在健康计划页查看', icon: 'success' })
|
|
|
+ setTimeout(function() {
|
|
|
+ uni.navigateTo({ url: '/pages/health-main/index?planId=' + res.data.planId })
|
|
|
+ }, 1000)
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: (res && res.message) || '计划生成失败', icon: 'none' })
|
|
|
+ }
|
|
|
+ }).catch(function() {
|
|
|
+ self.planGenerating = false
|
|
|
+ uni.showToast({ title: '计划生成失败', icon: 'none' })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ askAI: function() {
|
|
|
+ var selfCheckId = this.result && this.result.id
|
|
|
+ if (!selfCheckId) {
|
|
|
+ uni.showToast({ title: '暂无自检记录', icon: 'none' })
|
|
|
+ return
|
|
|
+ }
|
|
|
+ uni.navigateTo({ url: '/pages/ai/chat?selfCheckId=' + selfCheckId })
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -756,4 +765,66 @@ export default {
|
|
|
color: #F97316;
|
|
|
border: 2rpx solid #F97316;
|
|
|
}
|
|
|
+.scr-btn-secondary {
|
|
|
+ background: linear-gradient(135deg, #10B981, #34D399);
|
|
|
+ color: #fff;
|
|
|
+ font-weight: 600;
|
|
|
+}
|
|
|
+.scr-btn-ghost {
|
|
|
+ background: #fff;
|
|
|
+ color: #666;
|
|
|
+ border: 2rpx solid #D1D5DB;
|
|
|
+}
|
|
|
+.scr-advice-interpretation {
|
|
|
+ display: block;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #555;
|
|
|
+ line-height: 1.6;
|
|
|
+ margin: 16rpx 0;
|
|
|
+}
|
|
|
+.scr-advice-actions {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ margin-top: 12rpx;
|
|
|
+}
|
|
|
+.scr-advice-action-label {
|
|
|
+ font-size: 24rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #F97316;
|
|
|
+}
|
|
|
+.scr-advice-action {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #555;
|
|
|
+ line-height: 1.5;
|
|
|
+}
|
|
|
+.scr-family-insight {
|
|
|
+ background: #F5FAFE;
|
|
|
+ border-radius: 16rpx;
|
|
|
+ padding: 20rpx 24rpx;
|
|
|
+ margin-top: 24rpx;
|
|
|
+}
|
|
|
+.scr-family-insight-label {
|
|
|
+ display: block;
|
|
|
+ font-size: 24rpx;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #F97316;
|
|
|
+ margin-bottom: 8rpx;
|
|
|
+}
|
|
|
+.scr-family-insight-text {
|
|
|
+ display: block;
|
|
|
+ font-size: 26rpx;
|
|
|
+ color: #555;
|
|
|
+ line-height: 1.6;
|
|
|
+}
|
|
|
+.scr-fallback {
|
|
|
+ background: #FFF7ED;
|
|
|
+ border-radius: 12rpx;
|
|
|
+ padding: 16rpx 20rpx;
|
|
|
+ margin-top: 16rpx;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+.scr-fallback text {
|
|
|
+ font-size: 24rpx;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
</style>
|