1111
This commit is contained in:
+117
-21
@@ -33,22 +33,70 @@ button { cursor: pointer; }
|
||||
linear-gradient(145deg, #0b5548, #123d37 74%);
|
||||
border-radius: 0 0 42px 42px;
|
||||
}
|
||||
.brand-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 5px 14px 5px 6px;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 24px;
|
||||
font-size: 12px;
|
||||
margin-bottom: 20px;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
.brand-badge-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: var(--gold);
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-family: serif;
|
||||
font-weight: 700;
|
||||
font-size: 13px;
|
||||
}
|
||||
.brand-mark {
|
||||
display: grid; place-items: center; width: 48px; height: 48px; margin-bottom: 28px;
|
||||
border: 1px solid rgba(255,255,255,.42); border-radius: 50%; font-family: serif; font-size: 24px;
|
||||
}
|
||||
.brand-panel h1 { max-width: 560px; margin: 0; font-family: "Songti SC", serif; font-size: clamp(32px, 8vw, 54px); line-height: 1.2; font-weight: 500; }
|
||||
.brand-copy { max-width: 480px; margin: 18px 0 24px; color: rgba(255,255,255,.72); line-height: 1.7; }
|
||||
.feature-row { display: flex; gap: 10px; flex-wrap: wrap; }
|
||||
.feature-row span { padding: 7px 12px; background: rgba(255,255,255,.09); border: 1px solid rgba(255,255,255,.14); border-radius: 20px; font-size: 12px; }
|
||||
.feature-row, .feature-pill-row { display: flex; gap: 8px; flex-wrap: wrap; }
|
||||
.feature-row span, .feature-pill-row span { padding: 6px 12px; background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.16); border-radius: 20px; font-size: 12px; }
|
||||
|
||||
.auth-card { position: relative; width: min(520px, calc(100% - 32px)); margin: -20px auto 0; padding: 28px 22px; background: #fff; border-radius: 24px; box-shadow: 0 18px 50px rgba(24,59,52,.12); }
|
||||
.auth-heading h2 { margin: 0; font-family: "Songti SC", serif; font-size: 28px; }
|
||||
.auth-heading > p:last-child { margin: 8px 0 24px; color: #70817d; font-size: 14px; }
|
||||
.auth-card { position: relative; width: min(520px, calc(100% - 32px)); margin: -20px auto 0; padding: 24px 20px; background: #fff; border-radius: 24px; box-shadow: 0 18px 50px rgba(24,59,52,.12); }
|
||||
.auth-tab-switch {
|
||||
display: flex;
|
||||
background: #f1efea;
|
||||
border-radius: 12px;
|
||||
padding: 3px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.auth-tab-switch button {
|
||||
flex: 1;
|
||||
padding: 9px 0;
|
||||
border: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
border-radius: 9px;
|
||||
color: #72847d;
|
||||
background: transparent;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.auth-tab-switch button.active {
|
||||
background: #ffffff;
|
||||
color: var(--green);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.auth-heading h2 { margin: 0; font-family: "Songti SC", serif; font-size: 24px; }
|
||||
.auth-heading > p:last-child { margin: 8px 0 20px; color: #70817d; font-size: 13px; }
|
||||
.auth-card .van-field { margin-bottom: 12px; padding: 14px 12px; background: #f7f7f3; border-radius: 12px; }
|
||||
.auth-card .van-button { margin-top: 20px; height: 48px; }
|
||||
.auth-card .van-button { margin-top: 18px; height: 48px; font-size: 15px; font-weight: 600; }
|
||||
.text-button { display: block; margin: 18px auto 0; border: 0; background: transparent; color: var(--green); font-size: 14px; }
|
||||
.privacy-note { margin: 20px 0 0; color: #9a9f9c; font-size: 11px; line-height: 1.6; text-align: center; }
|
||||
.privacy-note { margin: 18px 0 0; color: #9a9f9c; font-size: 11px; line-height: 1.6; text-align: center; }
|
||||
|
||||
.page-shell { min-height: 100vh; padding: 28px 16px 110px; background: #f3f1ea; }
|
||||
.page-header, .dashboard-header { max-width: 760px; margin: 0 auto 24px; padding: 12px 4px; }
|
||||
@@ -59,19 +107,57 @@ button { cursor: pointer; }
|
||||
.section-title { display: flex; align-items: center; justify-content: space-between; margin-bottom: 16px; }
|
||||
.section-title > span { font-size: 18px; font-weight: 700; }
|
||||
.section-title small { color: #82908c; }
|
||||
.section-title button { border: 0; background: transparent; color: var(--green); }
|
||||
.section-title button {
|
||||
border: 0;
|
||||
background: rgba(12, 80, 69, 0.08);
|
||||
color: var(--green);
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.module-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
|
||||
.module-card { min-height: 160px; padding: 16px; text-align: left; border: 1px solid var(--line); border-radius: 16px; background: #f8f8f4; color: var(--deep); transition: .2s; }
|
||||
.module-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
|
||||
.module-card {
|
||||
min-height: 164px;
|
||||
padding: 14px 6px;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 16px;
|
||||
background: #f8f8f4;
|
||||
color: var(--deep);
|
||||
transition: .2s;
|
||||
}
|
||||
.module-card.selected { color: #fff; background: var(--green); transform: translateY(-2px); box-shadow: 0 12px 24px rgba(12,80,69,.18); }
|
||||
.module-icon { display: grid; place-items: center; width: 38px; height: 38px; margin-bottom: 18px; border: 1px solid currentColor; border-radius: 50%; font-size: 20px; }
|
||||
.module-card strong, .module-card small { display: block; }
|
||||
.module-card small { min-height: 36px; margin-top: 7px; opacity: .7; line-height: 1.5; }
|
||||
.module-card i { display: block; margin-top: 12px; font-size: 11px; font-style: normal; opacity: .75; }
|
||||
.form-card .van-field { padding: 14px 0; border-bottom: 1px solid #eee; }
|
||||
.two-column { display: grid; grid-template-columns: 1fr 1fr; gap: 0 18px; }
|
||||
.module-icon { display: grid; place-items: center; width: 38px; height: 38px; margin-bottom: 10px; border: 1px solid currentColor; border-radius: 50%; font-size: 20px; flex-shrink: 0; }
|
||||
.module-card strong { display: block; font-size: 13px; font-weight: 700; margin-bottom: 4px; }
|
||||
.module-card small { display: flex; align-items: center; justify-content: center; min-height: 28px; margin-top: 2px; opacity: .7; line-height: 1.35; font-size: 11px; }
|
||||
.module-card i {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: auto;
|
||||
padding: 4px 12px;
|
||||
border-radius: 12px;
|
||||
font-size: 11px;
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
background: rgba(18, 63, 55, 0.08);
|
||||
color: var(--deep);
|
||||
}
|
||||
.module-card.selected i {
|
||||
background: rgba(255, 255, 255, 0.22);
|
||||
color: #fff;
|
||||
}
|
||||
.form-card .van-field { padding: 12px 0; border-bottom: 1px solid #eee; }
|
||||
.form-card .van-field:last-of-type { border-bottom: 0; }
|
||||
.two-column { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
|
||||
.sticky-action { position: fixed; z-index: 10; left: 0; right: 0; bottom: 0; padding: 14px 20px max(14px, env(safe-area-inset-bottom)); background: rgba(248,246,240,.94); backdrop-filter: blur(14px); border-top: 1px solid var(--line); }
|
||||
.sticky-action .van-button { max-width: 720px; height: 50px; margin: 0 auto; }
|
||||
.sticky-action .van-button { max-width: 720px; height: 50px; margin: 0 auto; font-size: 15px; font-weight: 600; box-shadow: 0 6px 18px rgba(12,80,69,.2); }
|
||||
|
||||
.dashboard-header { display: flex; align-items: center; justify-content: space-between; }
|
||||
.avatar-button { width: 46px; height: 46px; color: #fff; border: 0; border-radius: 50%; background: var(--green); }
|
||||
@@ -95,14 +181,24 @@ button { cursor: pointer; }
|
||||
.plan-item p, .scene-row p { margin: 7px 0 0; color: #75847f; font-size: 13px; line-height: 1.6; }
|
||||
.status-dot { color: #a27639 !important; }
|
||||
.scene-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 15px; border-radius: 14px; background: #f6f7f3; }
|
||||
.scene-row button { padding: 9px 12px; border: 0; border-radius: 18px; color: #87918e; background: #e4e7e3; font-size: 11px; }
|
||||
.scene-row button {
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
padding: 7px 16px;
|
||||
border: 1px solid rgba(12, 80, 69, 0.2);
|
||||
border-radius: 16px;
|
||||
color: var(--green);
|
||||
background: #eaf3f0;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: .2s;
|
||||
}
|
||||
.scene-row button:active { background: var(--green); color: #fff; }
|
||||
.medical-note { max-width: 760px; margin: 24px auto; color: #969e9b; font-size: 11px; text-align: center; }
|
||||
.loading-card { color: #73817d; text-align: center; }
|
||||
|
||||
@media (max-width: 520px) {
|
||||
.module-grid { grid-template-columns: 1fr; }
|
||||
.module-card { min-height: auto; }
|
||||
.two-column { grid-template-columns: 1fr; }
|
||||
.brand-panel { min-height: 390px; }
|
||||
.auth-card { margin-top: -54px; }
|
||||
.plan-heading { display: block; }
|
||||
|
||||
+34
-16
@@ -9,7 +9,7 @@ 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' ? '欢迎回来' : '创建健康档案')
|
||||
const title = computed(() => mode.value === 'login' ? '欢迎回来' : '开启专属健康档案')
|
||||
|
||||
async function submit() {
|
||||
loading.value = true
|
||||
@@ -31,20 +31,41 @@ async function submit() {
|
||||
<template>
|
||||
<main class="auth-page">
|
||||
<section class="brand-panel">
|
||||
<div class="brand-mark">常</div>
|
||||
<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-row">
|
||||
<span>个性方案</span><span>智能场景</span><span>持续反馈</span>
|
||||
<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">
|
||||
<p class="eyebrow">常青树健康管理</p>
|
||||
<h2>{{ title }}</h2>
|
||||
<p>{{ mode === 'login' ? '登录后查看今日健康方案' : '第一步,建立您的专属健康账户' }}</p>
|
||||
<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">
|
||||
@@ -60,25 +81,22 @@ async function submit() {
|
||||
type="tel"
|
||||
label="手机号"
|
||||
maxlength="11"
|
||||
placeholder="请输入手机号"
|
||||
placeholder="请输入 11 位手机号"
|
||||
:rules="[{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号' }]"
|
||||
/>
|
||||
<van-field
|
||||
v-model="form.password"
|
||||
type="password"
|
||||
label="密码"
|
||||
placeholder="至少 8 位"
|
||||
placeholder="至少 8 位密码"
|
||||
:rules="[{ required: true, message: '请输入至少 8 位密码' }]"
|
||||
/>
|
||||
<van-button block round color="#0c5045" native-type="submit" :loading="loading">
|
||||
{{ mode === 'login' ? '登录' : '注册并继续' }}
|
||||
{{ mode === 'login' ? '登 录' : '创建档案并继续' }}
|
||||
</van-button>
|
||||
</van-form>
|
||||
|
||||
<button class="text-button" type="button" @click="mode = mode === 'login' ? 'register' : 'login'">
|
||||
{{ mode === 'login' ? '还没有账户?立即注册' : '已有账户?返回登录' }}
|
||||
</button>
|
||||
<p class="privacy-note">继续即表示您同意仅将健康信息用于生成个人健康管理建议。</p>
|
||||
<p class="privacy-note">🔒 数据安全说明:所有健康数据仅用于为您生成生活方式干预建议。</p>
|
||||
</section>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@@ -112,7 +112,7 @@ onMounted(load)
|
||||
<strong>舒睡模式</strong>
|
||||
<p>灯光 · 空调 · 香氛 · 除湿机</p>
|
||||
</div>
|
||||
<button type="button" disabled>下一阶段启用</button>
|
||||
<button type="button">准备就绪</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ const router = useRouter()
|
||||
const loading = ref(false)
|
||||
const selected = ref<string[]>(['sleep', 'exercise', 'diet'])
|
||||
const modules = [
|
||||
{ code: 'sleep', icon: '☾', title: '睡眠质量', copy: '睡眠时长、环境与恢复情况' },
|
||||
{ code: 'exercise', icon: '↗', title: '运动情况', copy: '日常活动、训练与久坐提醒' },
|
||||
{ code: 'diet', icon: '◒', title: '饮食情况', copy: '三餐、饮水与营养偏好' }
|
||||
{ code: 'sleep', icon: '☾', title: '睡眠质量', copy: '环境与节律深睡' },
|
||||
{ code: 'exercise', icon: '↗', title: '运动情况', copy: '日常活动与活力' },
|
||||
{ code: 'diet', icon: '◒', title: '饮食情况', copy: '三餐热量与偏好' }
|
||||
]
|
||||
const profile = reactive({
|
||||
gender: '',
|
||||
@@ -59,7 +59,7 @@ async function submit() {
|
||||
</header>
|
||||
|
||||
<section class="section-card">
|
||||
<div class="section-title"><span>健康板块</span><small>可多选</small></div>
|
||||
<div class="section-title"><span>健康板块</span><small>可多选,已选 {{ selected.length }}/3</small></div>
|
||||
<div class="module-grid">
|
||||
<button
|
||||
v-for="item in modules"
|
||||
@@ -72,22 +72,22 @@ async function submit() {
|
||||
<span class="module-icon">{{ item.icon }}</span>
|
||||
<strong>{{ item.title }}</strong>
|
||||
<small>{{ item.copy }}</small>
|
||||
<i>{{ selected.includes(item.code) ? '已选择' : '选择' }}</i>
|
||||
<i>{{ selected.includes(item.code) ? '✓ 已选' : '+ 选择' }}</i>
|
||||
</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section-card form-card">
|
||||
<div class="section-title"><span>基础情况</span><small>用于生成参数</small></div>
|
||||
<div class="section-title"><span>身体基线数据</span><small>用于生成参数</small></div>
|
||||
<div class="two-column">
|
||||
<van-field v-model="profile.gender" label="性别" placeholder="选填" />
|
||||
<van-field v-model.number="profile.heightCm" type="number" label="身高" placeholder="cm" />
|
||||
<van-field v-model.number="profile.weightKg" type="number" label="体重" placeholder="kg" />
|
||||
<van-field v-model.number="profile.averageSleepHours" type="number" label="平均睡眠" placeholder="小时" />
|
||||
<van-field v-model.number="profile.dailyExerciseMinutes" type="number" label="每日运动" placeholder="分钟" />
|
||||
<van-field v-model="profile.gender" label="性别" label-width="40px" placeholder="男 / 女" />
|
||||
<van-field v-model.number="profile.heightCm" type="number" label="身高" label-width="40px" placeholder="厘米(cm)" />
|
||||
<van-field v-model.number="profile.weightKg" type="number" label="体重" label-width="40px" placeholder="公斤(kg)" />
|
||||
<van-field v-model.number="profile.averageSleepHours" type="number" label="睡眠" label-width="40px" placeholder="小时/天" />
|
||||
</div>
|
||||
<van-field v-model="profile.dietPreference" label="饮食偏好" placeholder="例如清淡、少糖" />
|
||||
<van-field v-model="profile.healthGoal" label="健康目标" type="textarea" rows="2" placeholder="例如改善睡眠、增加日常活动" />
|
||||
<van-field v-model.number="profile.dailyExerciseMinutes" type="number" label="日均活动" label-width="70px" placeholder="平均每天中等活动时长(分钟)" />
|
||||
<van-field v-model="profile.dietPreference" label="饮食偏好" label-width="70px" placeholder="例如:少油清淡、偏面食、少糖" />
|
||||
<van-field v-model="profile.healthGoal" label="健康目标" label-width="70px" type="textarea" rows="2" placeholder="例如:希望改善晚上入睡困难、提升精力" />
|
||||
</section>
|
||||
|
||||
<div class="sticky-action">
|
||||
|
||||
Reference in New Issue
Block a user