更新
This commit is contained in:
@@ -56,27 +56,55 @@
|
||||
<!-- 2. 血糖趋势(无就诊卡或累计录入不足 7 天显示示例曲线) -->
|
||||
<view class="st-chart-card">
|
||||
<view class="st-chart-head">
|
||||
<view style="padding: 0 20rpx;">
|
||||
<view class="st-chart-head-text">
|
||||
<text class="st-chart-title">血糖趋势</text>
|
||||
<text class="st-chart-sub">{{ rangeText }} · mmol/L</text>
|
||||
|
||||
</view>
|
||||
<view class="st-chart-legend">
|
||||
<view
|
||||
class="st-legend-item"
|
||||
:class="{ inactive: !chartSeriesVisible.fasting }"
|
||||
@click="toggleChartSeries('fasting')"
|
||||
>
|
||||
<view class="st-dot st-dot-fasting" />
|
||||
<text>空腹</text>
|
||||
<view class="st-chart-toolbar">
|
||||
<view class="st-chart-legend">
|
||||
<view
|
||||
class="st-legend-item"
|
||||
:class="{ inactive: !chartSeriesVisible.fasting }"
|
||||
@click="toggleChartSeries('fasting')"
|
||||
>
|
||||
<view class="st-dot st-dot-fasting" />
|
||||
<text>空腹</text>
|
||||
</view>
|
||||
<view
|
||||
class="st-legend-item"
|
||||
:class="{ inactive: !chartSeriesVisible.postprandial }"
|
||||
@click="toggleChartSeries('postprandial')"
|
||||
>
|
||||
<view class="st-dot st-dot-post" />
|
||||
<text>餐后</text>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="st-legend-item"
|
||||
:class="{ inactive: !chartSeriesVisible.postprandial }"
|
||||
@click="toggleChartSeries('postprandial')"
|
||||
v-if="bloodCareEligible"
|
||||
class="st-chart-ai-chip"
|
||||
:class="{
|
||||
active: bloodCarePanelOpen,
|
||||
loading: bloodCareLoading,
|
||||
hint: !bloodCarePanelOpen && !bloodCareLoading
|
||||
}"
|
||||
role="button"
|
||||
aria-label="AI 照护建议"
|
||||
@click.stop="toggleBloodCareFromChart"
|
||||
>
|
||||
<view class="st-dot st-dot-post" />
|
||||
<text>餐后</text>
|
||||
<view class="st-chart-ai-chip-inner">
|
||||
<view class="st-chart-ai-chip-icon">
|
||||
<TongjiIcon
|
||||
name="sparkles"
|
||||
size="sm"
|
||||
:color="bloodCarePanelOpen ? '#ffffff' : '#006c49'"
|
||||
/>
|
||||
</view>
|
||||
<text class="st-chart-ai-chip-label">{{
|
||||
bloodCareLoading
|
||||
? '生成中'
|
||||
: (bloodCarePanelOpen ? '收起建议' : '照护建议')
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -98,6 +126,88 @@
|
||||
<view v-if="chartUseMockData" class="st-chart-foot">
|
||||
<text class="st-chart-mock-hint">示例数据,累计记录满 7 天后显示您的真实趋势</text>
|
||||
</view>
|
||||
|
||||
<!-- 趋势卡内:点击标题栏 AI 按钮后展开 -->
|
||||
<view v-if="bloodCareEligible && bloodCarePanelOpen" class="st-chart-care-panel">
|
||||
<view class="st-chart-care-head">
|
||||
<text class="st-chart-care-title">AI 照护建议</text>
|
||||
<view class="st-chart-care-actions">
|
||||
<view
|
||||
class="st-chart-care-refresh"
|
||||
:class="{ disabled: bloodCareLoading }"
|
||||
@click.stop="refreshBloodCareAi"
|
||||
>
|
||||
<TongjiIcon name="refresh" size="sm" color="#006c49" />
|
||||
<text>{{ bloodCareLoading ? '生成中' : '换一换' }}</text>
|
||||
</view>
|
||||
<view class="st-chart-care-close" @click.stop="closeBloodCarePanel">
|
||||
<text>收起</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="st-chart-care-sub">基于您累计 7 天血糖 · 监测与中医调理方向(非处方)</text>
|
||||
|
||||
<view v-if="bloodCareControlLabel" class="st-care-badge st-care-badge--in-chart">
|
||||
<text>{{ bloodCareControlLabel }}</text>
|
||||
</view>
|
||||
|
||||
<view v-if="bloodCareLoading && !hasBloodCareContent" class="st-skeleton st-skeleton--in-chart">
|
||||
<view class="st-skeleton-line" />
|
||||
<view class="st-skeleton-line short" />
|
||||
</view>
|
||||
|
||||
<view v-else-if="hasBloodCareContent" class="st-care-cards st-care-cards--in-chart">
|
||||
<view class="st-meal-glass st-care-block">
|
||||
<view class="st-meal-head">
|
||||
<text class="st-meal-label">总评</text>
|
||||
</view>
|
||||
<text class="st-meal-text">
|
||||
{{ bloodCarePlan.summary || '…' }}<text v-if="bloodCareLoading && bloodCareStreamField === 'summary'" class="ai-stream-cursor">▍</text>
|
||||
</text>
|
||||
</view>
|
||||
<view class="st-meal-glass st-care-block">
|
||||
<view class="st-meal-head">
|
||||
<text class="st-meal-label">血糖管理</text>
|
||||
</view>
|
||||
<text class="st-meal-text">
|
||||
{{ bloodCarePlan.blood_advice || '…' }}<text v-if="bloodCareLoading && bloodCareStreamField === 'blood_advice'" class="ai-stream-cursor">▍</text>
|
||||
</text>
|
||||
</view>
|
||||
<view class="st-meal-glass st-care-block st-care-block--tcm">
|
||||
<view class="st-meal-head">
|
||||
<text class="st-meal-label">中医调理</text>
|
||||
</view>
|
||||
<text class="st-meal-text">
|
||||
{{ bloodCarePlan.tcm_plan || '…' }}<text v-if="bloodCareLoading && bloodCareStreamField === 'tcm_plan'" class="ai-stream-cursor">▍</text>
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="bloodCarePlan.watch_points && bloodCarePlan.watch_points.length" class="st-care-watch">
|
||||
<text class="st-care-watch-title">留意</text>
|
||||
<view v-for="(item, wi) in bloodCarePlan.watch_points" :key="wi" class="st-care-watch-item">
|
||||
<text class="st-care-watch-dot">·</text>
|
||||
<text class="st-care-watch-text">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="bloodCarePlan.next_steps" class="st-meal-glass st-care-block st-care-block--next">
|
||||
<view class="st-meal-head">
|
||||
<text class="st-meal-label">复诊提醒</text>
|
||||
</view>
|
||||
<text class="st-meal-text">
|
||||
{{ bloodCarePlan.next_steps }}<text v-if="bloodCareLoading && bloodCareStreamField === 'next_steps'" class="ai-stream-cursor">▍</text>
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="bloodCareAnalysis.length" class="st-care-stats st-care-stats--in-chart">
|
||||
<view v-for="(s, si) in bloodCareAnalysis" :key="si" class="st-care-stat-chip">
|
||||
<text class="st-care-stat-label">{{ s.label }}</text>
|
||||
<text class="st-care-stat-val">记录 {{ s.record_days }} 天 · 达标 {{ s.compliance }}%</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<text v-if="bloodCareDisclaimer" class="st-care-disclaimer st-care-disclaimer--in-chart">{{ bloodCareDisclaimer }}</text>
|
||||
</view>
|
||||
|
||||
<view class="st-game-entry st-game-entry--in-card" @click="goGamePage" style="margin: 0 20rpx 0 20rpx;">
|
||||
<view class="st-game-entry-icon">
|
||||
<TongjiIcon name="activity" size="sm" color="#006c49" />
|
||||
@@ -109,6 +219,7 @@
|
||||
<TongjiIcon name="chevron-right" size="sm" color="#64748b" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="st-training-section">
|
||||
<dev-training-entry inline tone="weekly" />
|
||||
</view>
|
||||
@@ -414,6 +525,7 @@ import { onLoad, onShow, onHide, onUnload, onPullDownRefresh, onShareAppMessage
|
||||
import SugarTreeGraphic from '../components/SugarTreeGraphic.vue'
|
||||
import TongjiIcon from '../components/TongjiIcon.vue'
|
||||
import { useDietAi } from '../composables/useDietAi.js'
|
||||
import { useBloodCareAi } from '../composables/useBloodCareAi.js'
|
||||
import { useSpeechToText } from '../composables/useSpeechToText.js'
|
||||
import TabBarDock from '@/components/app-tab-bar/tab-bar-dock.vue'
|
||||
import DevTrainingEntry from '@/components/dev-training-entry/index.vue'
|
||||
@@ -924,6 +1036,27 @@ const chartHasDisplayData = computed(() => {
|
||||
return bloodHasData.value
|
||||
})
|
||||
|
||||
const {
|
||||
bloodCarePlan,
|
||||
bloodCareLoading,
|
||||
bloodCareStreamField,
|
||||
bloodCareEligible,
|
||||
bloodCarePanelOpen,
|
||||
hasBloodCareContent,
|
||||
bloodCareAnalysis,
|
||||
bloodCareControlLabel,
|
||||
bloodCareDisclaimer,
|
||||
toggleBloodCareFromChart,
|
||||
closeBloodCarePanel,
|
||||
refreshBloodCareAi,
|
||||
resetBloodCarePlan
|
||||
} = useBloodCareAi(proxy, {
|
||||
diagnosisId,
|
||||
chartUseMockData,
|
||||
showUserToast,
|
||||
formatUserMessage
|
||||
})
|
||||
|
||||
const bloodHighDayCount = computed(() => {
|
||||
return chartDates.value.filter((date) => {
|
||||
const b = bloodByDate.value[date]
|
||||
@@ -1380,6 +1513,7 @@ async function onSelectCard(card) {
|
||||
exerciseRecords.value = []
|
||||
trackingNotes.value = []
|
||||
hoverInfo.value = null
|
||||
resetBloodCarePlan()
|
||||
await applyCard(card)
|
||||
fetchAll()
|
||||
}
|
||||
@@ -1436,6 +1570,9 @@ async function fetchAll() {
|
||||
trackingNotes.value = []
|
||||
}
|
||||
await fetchDietAiRecommend(false)
|
||||
if (!bloodCareEligible.value) {
|
||||
resetBloodCarePlan()
|
||||
}
|
||||
} catch (e) {
|
||||
uni.showToast({ title: '加载失败,请稍后再试', icon: 'none' })
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user