feat: initialize Evergreen Health mobile app

This commit is contained in:
fuenmao
2026-09-21 15:53:02 +08:00
commit 93e9bb604d
18 changed files with 2715 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { useRouter } from 'vue-router'
import { Button as VanButton, Field as VanField, Form as VanForm, showToast } from 'vant'
import { healthApi } from '../services/health'
import { saveTokens } from '../services/auth'
const router = useRouter()
const mode = ref<'login' | 'register'>('login')
const loading = ref(false)
const form = reactive({ phone: '', password: '', displayName: '' })
const title = computed(() => mode.value === 'login' ? '欢迎回来' : '开启专属健康档案')
async function submit() {
loading.value = true
try {
const output = mode.value === 'login'
? await healthApi.login({ phone: form.phone, password: form.password })
: await healthApi.register(form)
saveTokens(output.accessToken, output.refreshToken)
showToast({ type: 'success', message: mode.value === 'login' ? '登录成功' : '注册成功' })
await router.replace(mode.value === 'login' ? '/dashboard' : '/onboarding')
} catch (error) {
showToast(error instanceof Error ? error.message : '操作失败')
} finally {
loading.value = false
}
}
</script>
<template>
<main class="auth-page">
<section class="brand-panel">
<div class="brand-badge">
<span class="brand-badge-icon">常</span>
<span>一人一方 · 康养管理</span>
</div>
<p class="eyebrow">EVERGREEN HEALTH</p>
<h1>一人一方<br />健康与空间协同</h1>
<p class="brand-copy">以睡眠为切入点,融合五感空间与动态健康处方,开启治未病日常管理。</p>
<div class="feature-pill-row">
<span>🌿 六维处方</span>
<span>🌙 五感微环境</span>
<span>📊 闭环调理</span>
</div>
</section>
<section class="auth-card">
<div class="auth-tab-switch">
<button
type="button"
:class="{ active: mode === 'login' }"
@click="mode = 'login'"
>
账号登录
</button>
<button
type="button"
:class="{ active: mode === 'register' }"
@click="mode = 'register'"
>
注册建档
</button>
</div>
<div class="auth-heading">
<h2 style="font-size: 20px; font-weight: 700; color: #142e27; margin-bottom: 4px;">{{ title }}</h2>
<p style="color: #72847d; font-size: 13px; margin-bottom: 16px;">
{{ mode === 'login' ? '登录查看今日健康处方与微环境状态' : '第一步:填写手机号快速创建健康账户' }}
</p>
</div>
<van-form @submit="submit">
<van-field
v-if="mode === 'register'"
v-model="form.displayName"
label="您的姓名"
placeholder="请输入您的真实姓名或称呼"
:rules="[{ required: true, message: '请输入姓名' }]"
/>
<van-field
v-model="form.phone"
type="tel"
label="手机号码"
maxlength="11"
placeholder="请输入 11 位手机号"
:rules="[{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' }]"
/>
<van-field
v-model="form.password"
type="password"
label="账户密码"
placeholder="请输入至少 8 位密码"
:rules="[{ required: true, message: '请输入至少 8 位密码' }]"
/>
<van-button
block
round
color="#0c4d3f"
native-type="submit"
:loading="loading"
>
{{ mode === 'login' ? '登 录' : '创建档案并下一步' }}
</van-button>
</van-form>
<p class="privacy-note">
🔒 数据安全说明:所有身体体征与处方数据均遵循隐私保护规范,仅用于为您生成生活方式干预建议。
</p>
</section>
</main>
</template>