317 lines
6.2 KiB
Vue
317 lines
6.2 KiB
Vue
<template>
|
||
<view class="page container">
|
||
<view class="stage-card">
|
||
<view class="stage-badge">第 {{ stageDay }}/30 天</view>
|
||
<text class="stage-label">当前减量计划阶段</text>
|
||
<text class="stage-name">阶段 {{ stage }} : {{ stageName }}</text>
|
||
<text class="stage-days">本阶段还剩 {{ daysLeft }} 天</text>
|
||
<view class="stage-progress-row">
|
||
<text class="stage-progress-label">阶段进度</text>
|
||
<text class="stage-progress-value text-primary">{{ Math.round(stageProgress * 100) }}%</text>
|
||
</view>
|
||
<view class="stage-progress-bar">
|
||
<view class="stage-progress-fill" :style="{ width: stageProgress * 100 + '%' }"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section">
|
||
<view class="section-header">
|
||
<text class="section-icon">🤖</text>
|
||
<text class="section-title">每日 AI 分析</text>
|
||
</view>
|
||
|
||
<view class="ai-chat card">
|
||
<view class="ai-chat-header">
|
||
<text class="ai-chat-name text-primary">AI 教练</text>
|
||
<text class="ai-chat-time">· 刚刚</text>
|
||
</view>
|
||
<view class="ai-chat-bubble">
|
||
<text class="ai-chat-text">{{ aiAdvice }}</text>
|
||
</view>
|
||
<view class="ai-avatar">
|
||
<text>🤖</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="section">
|
||
<view class="section-header">
|
||
<text class="section-title">今日目标</text>
|
||
<text class="section-badge">已完成 {{ completedGoals }}/{{ goals.length }}</text>
|
||
</view>
|
||
|
||
<view class="goals-list">
|
||
<view
|
||
v-for="goal in goals"
|
||
:key="goal.id"
|
||
class="goal-item card"
|
||
@tap="toggleGoal(goal)"
|
||
>
|
||
<view class="goal-check" :class="{ 'goal-check-done': goal.done }">
|
||
<text v-if="goal.done">✓</text>
|
||
</view>
|
||
<text class="goal-text" :class="{ 'goal-text-done': goal.done }">{{ goal.text }}</text>
|
||
<text class="goal-icon">{{ goal.icon }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="record-btn btn btn-primary" @tap="goRecord">
|
||
<text class="record-icon">➕</text>
|
||
<text>记录吸烟或烟瘾</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref, computed } from 'vue'
|
||
|
||
const stageDay = ref(18)
|
||
const stage = ref(2)
|
||
const stageName = ref('减量期')
|
||
const daysLeft = ref(12)
|
||
const stageProgress = ref(0.4)
|
||
|
||
const aiAdvice = ref('早上好 Alex。昨天你的吸烟量比限额少了 2 支。这是一个巨大的胜利!🏆\n\n数据显示你的烟瘾在下午 2 点左右达到顶峰——今天试着那个时候去散散步。')
|
||
|
||
const goals = ref([
|
||
{ id: 1, text: '喝 2 升水', icon: '🏆', done: true },
|
||
{ id: 2, text: '控制在 5 支烟以内', icon: '', done: false },
|
||
{ id: 3, text: '阅读激励卡片', icon: '🏆', done: false }
|
||
])
|
||
|
||
const completedGoals = computed(() => {
|
||
return goals.value.filter(g => g.done).length
|
||
})
|
||
|
||
function toggleGoal(goal) {
|
||
goal.done = !goal.done
|
||
}
|
||
|
||
function goRecord() {
|
||
uni.switchTab({ url: '/pages/index/index' })
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page {
|
||
padding-bottom: 180rpx;
|
||
}
|
||
|
||
.stage-card {
|
||
background: linear-gradient(135deg, rgba(74, 222, 128, 0.1) 0%, rgba(74, 222, 128, 0.05) 100%);
|
||
border-radius: 24rpx;
|
||
padding: 32rpx;
|
||
margin-bottom: 32rpx;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.stage-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: url('data:image/svg+xml,...') no-repeat center;
|
||
opacity: 0.1;
|
||
}
|
||
|
||
.stage-badge {
|
||
position: absolute;
|
||
top: 24rpx;
|
||
right: 24rpx;
|
||
background-color: var(--color-primary);
|
||
color: var(--color-bg);
|
||
padding: 8rpx 20rpx;
|
||
border-radius: 20rpx;
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.stage-label {
|
||
font-size: 24rpx;
|
||
color: var(--color-primary);
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.stage-name {
|
||
font-size: 48rpx;
|
||
font-weight: 700;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.stage-days {
|
||
font-size: 24rpx;
|
||
color: var(--color-text-secondary);
|
||
display: block;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.stage-progress-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.stage-progress-label {
|
||
font-size: 24rpx;
|
||
color: var(--color-text-secondary);
|
||
}
|
||
|
||
.stage-progress-value {
|
||
font-size: 24rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.stage-progress-bar {
|
||
height: 12rpx;
|
||
background-color: rgba(74, 222, 128, 0.2);
|
||
border-radius: 6rpx;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.stage-progress-fill {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, var(--color-primary), #22C55E);
|
||
border-radius: 6rpx;
|
||
}
|
||
|
||
.section {
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.section-icon {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.section-badge {
|
||
margin-left: auto;
|
||
font-size: 24rpx;
|
||
color: var(--color-primary);
|
||
background-color: rgba(74, 222, 128, 0.1);
|
||
padding: 8rpx 16rpx;
|
||
border-radius: 16rpx;
|
||
}
|
||
|
||
.ai-chat {
|
||
position: relative;
|
||
padding: 32rpx;
|
||
padding-left: 100rpx;
|
||
}
|
||
|
||
.ai-chat-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8rpx;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.ai-chat-name {
|
||
font-weight: 600;
|
||
}
|
||
|
||
.ai-chat-time {
|
||
font-size: 24rpx;
|
||
color: var(--color-text-muted);
|
||
}
|
||
|
||
.ai-chat-bubble {
|
||
background-color: var(--color-bg-card-light);
|
||
padding: 24rpx;
|
||
border-radius: 24rpx;
|
||
border-top-left-radius: 8rpx;
|
||
}
|
||
|
||
.ai-chat-text {
|
||
font-size: 28rpx;
|
||
line-height: 1.6;
|
||
white-space: pre-wrap;
|
||
}
|
||
|
||
.ai-avatar {
|
||
position: absolute;
|
||
left: 24rpx;
|
||
bottom: 32rpx;
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
background-color: var(--color-bg-card-light);
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.goals-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.goal-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 20rpx;
|
||
padding: 24rpx;
|
||
}
|
||
|
||
.goal-check {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
border-radius: 50%;
|
||
border: 4rpx solid var(--color-border);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 28rpx;
|
||
color: var(--color-bg);
|
||
}
|
||
|
||
.goal-check-done {
|
||
background-color: var(--color-primary);
|
||
border-color: var(--color-primary);
|
||
}
|
||
|
||
.goal-text {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.goal-text-done {
|
||
text-decoration: line-through;
|
||
color: var(--color-text-muted);
|
||
}
|
||
|
||
.goal-icon {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.record-btn {
|
||
position: fixed;
|
||
bottom: 140rpx;
|
||
left: 32rpx;
|
||
right: 32rpx;
|
||
gap: 12rpx;
|
||
}
|
||
|
||
.record-icon {
|
||
font-size: 32rpx;
|
||
}
|
||
</style>
|