chore: restore clean mobile baseline as requested by user

This commit is contained in:
fuenmao
2026-09-21 16:02:49 +08:00
parent 93e9bb604d
commit e4070f207c
4 changed files with 192 additions and 1060 deletions
+54 -188
View File
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { Button as VanButton, showConfirmDialog, showToast } from 'vant'
import { Button as VanButton, showToast } from 'vant'
import { clearTokens } from '../services/auth'
import { healthApi, type Dashboard } from '../services/health'
@@ -9,26 +9,16 @@ const router = useRouter()
const loading = ref(true)
const generating = ref(false)
const dashboard = ref<Dashboard>()
const moduleNames: Record<string, { name: string; icon: string }> = {
sleep: { name: '睡眠', icon: '🌙' },
exercise: { name: '运动', icon: '🏃' },
diet: { name: '饮食', icon: '🥗' }
const moduleNames: Record<string, string> = {
sleep: '睡眠',
exercise: '运动',
diet: '饮食'
}
const greetingInfo = computed(() => {
const greeting = computed(() => {
const hour = new Date().getHours()
if (hour < 11) return { text: '早安', icon: '🌅' }
if (hour < 14) return { text: '午安', icon: '☀️' }
if (hour < 19) return { text: '下午好', icon: '🍵' }
return { text: '晚上好', icon: '🌙' }
})
const todayDateText = computed(() => {
return new Intl.DateTimeFormat('zh-CN', {
month: 'long',
day: 'numeric',
weekday: 'short'
}).format(new Date())
if (hour < 11) return '早上好'
if (hour < 18) return '下午好'
return '晚上好'
})
async function load() {
@@ -47,7 +37,7 @@ async function generate() {
try {
await healthApi.generatePlan()
await load()
showToast({ type: 'success', message: '方案已生成并更新' })
showToast({ type: 'success', message: '方案已更新' })
} catch (error) {
showToast(error instanceof Error ? error.message : '生成失败')
} finally {
@@ -55,17 +45,9 @@ async function generate() {
}
}
function handleUserClick() {
showConfirmDialog({
title: '账户设置',
message: `当前登录:${dashboard.value?.user.displayName || '健康用户'}(${dashboard.value?.user.phone || ''}),确定要退出登录吗?`,
confirmButtonText: '退出登录',
cancelButtonText: '取消',
confirmButtonColor: '#c0392b'
}).then(() => {
clearTokens()
router.replace('/auth')
}).catch(() => {})
function logout() {
clearTokens()
router.replace('/auth')
}
onMounted(load)
@@ -73,184 +55,68 @@ onMounted(load)
<template>
<main class="page-shell dashboard-page">
<!-- 顶部状态栏与用户头像 -->
<header class="dashboard-header">
<div class="header-meta">
<span class="eyebrow">EVERGREEN · TODAY</span>
<h1>{{ greetingInfo.icon }} {{ greetingInfo.text }},{{ dashboard?.user.displayName || '您好' }}</h1>
<div class="date-badge">
<span>📅 {{ todayDateText }}</span>
<span>· 一人一方每日协同</span>
</div>
<div>
<p class="eyebrow">EVERGREEN · TODAY</p>
<h1>{{ greeting }},{{ dashboard?.user.displayName || '您好' }}</h1>
<p>{{ new Intl.DateTimeFormat('zh-CN', { month: 'long', day: 'numeric', weekday: 'long' }).format(new Date()) }}</p>
</div>
<button class="user-chip" type="button" @click="handleUserClick">
<div class="avatar-badge">
{{ dashboard?.user.displayName?.slice(0, 1) || '常' }}
</div>
<span class="user-chip-name">我的账户</span>
<button class="avatar-button" type="button" @click="logout">
{{ dashboard?.user.displayName?.slice(0, 1) || '常' }}
</button>
</header>
<!-- 加载态骨架 -->
<section v-if="loading" class="section-card loading-card" style="padding: 40px 20px;">
<div style="font-size: 24px; margin-bottom: 10px;">🌿</div>
<p style="color: var(--text-sub); font-size: 14px;">正在同步您的今日健康方案与微环境参数…</p>
</section>
<section v-if="loading" class="section-card loading-card">正在读取今日健康方案…</section>
<template v-else>
<!-- 今日方案主卡片 (Hero Card) -->
<section class="hero-card">
<div class="hero-top-row">
<span class="eyebrow" style="color: #f1c37a;">今日专属干预方案</span>
<span v-if="dashboard?.currentPlan" style="font-size: 11px; padding: 2px 8px; border-radius: 10px; background: rgba(255,255,255,0.16); color: #fff;">
V{{ dashboard.currentPlan.version }} · 方案生效中
</span>
</div>
<p class="eyebrow">今日健康建议</p>
<h2>{{ dashboard?.currentPlan?.title || '尚未生成健康方案' }}</h2>
<p class="hero-summary">
{{ dashboard?.currentPlan?.summary || '完成基础板块选择与身体数据录入后,系统将为您量身定制每日干预方案。' }}
</p>
<!-- 启用的健康板块标签 -->
<p>{{ dashboard?.currentPlan?.summary || '完成健康板块选择后,即可生成第一版个人参数。' }}</p>
<div class="tag-row">
<span v-for="code in dashboard?.selectedModules" :key="code" class="tag-pill">
{{ moduleNames[code]?.icon }} {{ moduleNames[code]?.name || code }}
</span>
</div>
<!-- 操作按钮行 -->
<div class="hero-action-row">
<van-button
v-if="!dashboard?.currentPlan"
round
color="#f1c37a"
text-color="#183b34"
style="font-weight: 700;"
:loading="generating"
@click="generate"
>
✨ 立即生成专属方案
</van-button>
<van-button
v-else
round
size="small"
color="rgba(255,255,255,0.18)"
style="border: 1px solid rgba(255,255,255,0.3); color: #fff;"
:loading="generating"
@click="generate"
>
↺ 重新评估生成
</van-button>
<span v-for="code in dashboard?.selectedModules" :key="code">{{ moduleNames[code] || code }}</span>
</div>
<van-button
v-if="!dashboard?.currentPlan"
round
color="#f1c37a"
text-color="#183b34"
:loading="generating"
@click="generate"
>
立即生成
</van-button>
</section>
<!-- 核心指标状态栏 (3 列式卡片) -->
<section class="metric-strip">
<div class="metric-card">
<span class="metric-label">🌙 睡眠目标</span>
<strong>7–8<em>h</em></strong>
<span class="metric-desc">建议 23:00 前</span>
</div>
<div class="metric-card">
<span class="metric-label">🏃 活动目标</span>
<strong>30<em>min</em></strong>
<span class="metric-desc">中等强度</span>
</div>
<div class="metric-card">
<span class="metric-label">🔖 方案版本</span>
<strong>V{{ dashboard?.currentPlan?.version || 0 }}<em>版</em></strong>
<span class="metric-desc">动态演进</span>
</div>
<div><small>睡眠目标</small><strong>7–8<em>h</em></strong></div>
<div><small>活动目标</small><strong>30<em>min</em></strong></div>
<div><small>方案版本</small><strong>V{{ dashboard?.currentPlan?.version || 0 }}</strong></div>
</section>
<!-- 今日六维行动建议 -->
<section class="section-card">
<div class="section-title">
<span>今日执行清单</span>
<button type="button" @click="router.push('/onboarding')">
调整偏好 ›
</button>
</div>
<div v-if="dashboard?.currentPlan?.items?.length">
<article
v-for="item in dashboard.currentPlan.items"
:key="item.moduleCode"
class="plan-item"
>
<div class="plan-item-icon">
{{ item.moduleCode === 'sleep' ? '🌙' : item.moduleCode === 'exercise' ? '🏃' : '🥗' }}
</div>
<div class="plan-item-content">
<div class="plan-item-header">
<strong>{{ item.title }}</strong>
<span class="plan-item-target">{{ item.target }}</span>
</div>
<p class="plan-item-advice">{{ item.advice }}</p>
</div>
</article>
</div>
<div v-else style="text-align: center; padding: 20px; color: var(--text-muted); font-size: 13px;">
暂无执行建议,点击上方按钮即可一键生成方案。
</div>
</section>
<!-- 五感微环境空间联动卡片 -->
<section class="section-card smart-space-card">
<div class="section-title">
<span>五感舒睡空间</span>
<small class="smart-badge">⚡ Home Assistant 待接入</small>
</div>
<div class="smart-scene-box">
<div class="scene-icon-title">
<div class="scene-icon">🛏️</div>
<div class="scene-text">
<strong>深度舒睡模式</strong>
<p>预冷20℃ · 琥珀微光 · 新风正压 · 草本扩香</p>
</div>
<div class="section-title"><span>我的健康板块</span><button type="button" @click="router.push('/onboarding')">调整</button></div>
<article v-for="item in dashboard?.currentPlan?.items" :key="item.moduleCode" class="plan-item">
<div class="plan-index">{{ item.moduleCode === 'sleep' ? '☾' : item.moduleCode === 'exercise' ? '↗' : '◒' }}</div>
<div>
<div class="plan-heading"><strong>{{ item.title }}</strong><span>{{ item.target }}</span></div>
<p>{{ item.advice }}</p>
</div>
<button
type="button"
disabled
style="padding: 6px 10px; border-radius: 12px; font-size: 11px; background: #e8eae6; color: #8e9a95;"
>
准备就绪
</button>
</article>
</section>
<section class="section-card smart-card">
<div class="section-title"><span>健康空间</span><small class="status-dot">Home Assistant 待接入</small></div>
<div class="scene-row">
<div>
<strong>舒睡模式</strong>
<p>灯光 · 空调 · 香氛 · 除湿机</p>
</div>
<button type="button" disabled>下一阶段启用</button>
</div>
</section>
<!-- 免责与合规提示 -->
<p class="medical-disclaimer">
⚠️ 本建议由一人一方生活方式决策模型生成,仅用于日常健康管理与微环境优化,不构成医疗诊断或临床处方。
</p>
<p class="medical-note">健康建议仅用于日常管理演示,不构成医疗诊断或治疗意见。</p>
</template>
<!-- 底部固定快捷导航栏 -->
<nav class="sticky-action" style="display: flex; gap: 8px; justify-content: space-between;">
<van-button
block
round
color="#0c4d3f"
style="flex: 2; height: 46px; font-size: 14px;"
@click="generate"
:loading="generating"
>
✨ 刷新今日建议
</van-button>
<van-button
round
plain
color="#0c4d3f"
style="flex: 1; height: 46px; font-size: 14px;"
@click="router.push('/onboarding')"
>
调整偏好
</van-button>
</nav>
</main>
</template>