Remove outdated UI components and screens for activity history, AI quit assistant, home dashboard, profile & settings, and smoking statistics. Update API to include a new endpoint for home dashboard data retrieval. Enhance smoke record dialog with improved layout and styling adjustments.
This commit is contained in:
+207
-115
@@ -1,23 +1,17 @@
|
||||
<template>
|
||||
<view class="page">
|
||||
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
<view class="header">
|
||||
<view class="back-btn" @tap="goBack">
|
||||
<text class="back-icon">‹</text>
|
||||
</view>
|
||||
<text class="header-title">数据统计分析</text>
|
||||
<view class="header-spacer"></view>
|
||||
</view>
|
||||
|
||||
<view class="segment">
|
||||
<view
|
||||
v-for="tab in tabs"
|
||||
:key="tab.value"
|
||||
class="segment-item"
|
||||
:class="{ 'segment-active': currentTab === tab.value }"
|
||||
@tap="currentTab = tab.value"
|
||||
>
|
||||
{{ tab.label }}
|
||||
<view class="sticky-bar">
|
||||
<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
|
||||
<view class="segment">
|
||||
<view
|
||||
v-for="tab in tabs"
|
||||
:key="tab.value"
|
||||
class="segment-item"
|
||||
:class="{ 'segment-active': currentTab === tab.value }"
|
||||
@tap="currentTab = tab.value"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -64,9 +58,11 @@
|
||||
|
||||
<view class="savings-card">
|
||||
<view class="savings-header">
|
||||
<view class="savings-icon"></view>
|
||||
<text class="savings-title">节省金额</text>
|
||||
<view class="savings-icon" :class="moneyIconClass">
|
||||
<view class="icon-coin"></view>
|
||||
</view>
|
||||
<text class="savings-title">节省金额</text>
|
||||
</view>
|
||||
<view class="savings-body">
|
||||
<view class="savings-left">
|
||||
<text class="savings-value">{{ savedMoneyText }}</text>
|
||||
@@ -86,7 +82,10 @@
|
||||
<view class="health-card">
|
||||
<view class="health-header">
|
||||
<view class="health-title-row">
|
||||
<view class="health-icon"></view>
|
||||
<view class="health-icon" :class="healthIconClass">
|
||||
<view class="icon-plus-vertical"></view>
|
||||
<view class="icon-plus-horizontal"></view>
|
||||
</view>
|
||||
<text class="health-title">健康恢复里程碑</text>
|
||||
</view>
|
||||
<view class="health-badge">{{ healthStatusText }}</view>
|
||||
@@ -110,7 +109,9 @@
|
||||
|
||||
<view class="stats-grid">
|
||||
<view class="mini-card">
|
||||
<view class="mini-icon mini-icon-fire"></view>
|
||||
<view class="mini-icon mini-icon-fire" :class="streakIconClass">
|
||||
<view class="icon-flame"></view>
|
||||
</view>
|
||||
<text class="mini-label">连续记录</text>
|
||||
<view class="mini-value-row">
|
||||
<text class="mini-value">{{ streakDays }}</text>
|
||||
@@ -119,7 +120,9 @@
|
||||
<text class="mini-sub">保持未吸烟</text>
|
||||
</view>
|
||||
<view class="mini-card">
|
||||
<view class="mini-icon mini-icon-block"></view>
|
||||
<view class="mini-icon mini-icon-block" :class="resistedIconClass">
|
||||
<view class="icon-shield"></view>
|
||||
</view>
|
||||
<text class="mini-label">已拒绝</text>
|
||||
<view class="mini-value-row">
|
||||
<text class="mini-value">{{ resistedTotal }}</text>
|
||||
@@ -221,6 +224,7 @@ const savedMoneyText = computed(() => {
|
||||
return `¥${(money.saved_cent / 100).toFixed(2)}`
|
||||
})
|
||||
|
||||
|
||||
const moneyTargetCent = computed(() => {
|
||||
const money = statsData.value?.money
|
||||
if (!money || !money.available) return 0
|
||||
@@ -259,6 +263,7 @@ const healthStatusText = computed(() => {
|
||||
return '进行中'
|
||||
})
|
||||
|
||||
|
||||
const healthItems = computed(() => {
|
||||
const health = statsData.value?.health
|
||||
if (!health || !health.available || !health.milestones || health.milestones.length === 0) {
|
||||
@@ -284,6 +289,37 @@ const healthItems = computed(() => {
|
||||
const streakDays = computed(() => statsData.value?.streak_days ?? 12)
|
||||
const resistedTotal = computed(() => statsData.value?.resisted_total ?? 24)
|
||||
|
||||
const moneyIconClass = computed(() => {
|
||||
const money = statsData.value?.money
|
||||
if (!money || !money.available) return 'icon-muted'
|
||||
if (moneyPercent.value >= 60) return 'icon-strong'
|
||||
if (moneyPercent.value >= 30) return 'icon-mid'
|
||||
return 'icon-low'
|
||||
})
|
||||
|
||||
const healthIconClass = computed(() => {
|
||||
const health = statsData.value?.health
|
||||
if (!health || !health.available) return 'icon-muted'
|
||||
const minutes = health.smoke_free_minutes || 0
|
||||
if (minutes >= 1440) return 'icon-strong'
|
||||
if (minutes >= 120) return 'icon-mid'
|
||||
return 'icon-low'
|
||||
})
|
||||
|
||||
const streakIconClass = computed(() => {
|
||||
if (streakDays.value <= 0) return 'icon-muted'
|
||||
if (streakDays.value >= 7) return 'icon-strong'
|
||||
if (streakDays.value >= 3) return 'icon-mid'
|
||||
return 'icon-low'
|
||||
})
|
||||
|
||||
const resistedIconClass = computed(() => {
|
||||
if (resistedTotal.value <= 0) return 'icon-muted'
|
||||
if (resistedTotal.value >= 10) return 'icon-strong'
|
||||
if (resistedTotal.value >= 5) return 'icon-mid'
|
||||
return 'icon-low'
|
||||
})
|
||||
|
||||
function formatTrendLabel(label, unit) {
|
||||
if (!label) return ''
|
||||
if (unit === 'month') {
|
||||
@@ -327,17 +363,13 @@ async function fetchStats() {
|
||||
}
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
uni.switchTab({ url: '/pages/index/index' })
|
||||
}
|
||||
|
||||
watch(currentTab, () => {
|
||||
fetchStats()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
const sys = uni.getSystemInfoSync()
|
||||
statusBarHeight.value = sys.statusBarHeight || 0
|
||||
statusBarHeight.value = Math.max((sys.statusBarHeight || 0) - 20, 0)
|
||||
fetchStats()
|
||||
})
|
||||
</script>
|
||||
@@ -345,74 +377,50 @@ onMounted(() => {
|
||||
<style scoped>
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background-color: #F5F7FB;
|
||||
padding: 0 28rpx 180rpx;
|
||||
background: linear-gradient(to bottom, #D1FAE5 0%, #F0FDF4 45%, #FFFFFF 100%);
|
||||
padding: 0 32rpx 200rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.status-bar {
|
||||
background-color: #F5F7FB;
|
||||
background: linear-gradient(to bottom, #D1FAE5, #F0FDF4);
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16rpx 0 12rpx;
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #FFFFFF;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 20rpx rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 36rpx;
|
||||
color: #111827;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #111827;
|
||||
}
|
||||
|
||||
.header-spacer {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
.sticky-bar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
background: linear-gradient(to bottom, #D1FAE5 0%, #F0FDF4 70%, rgba(255, 255, 255, 0.95) 100%);
|
||||
padding-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.segment {
|
||||
display: flex;
|
||||
background-color: #EEF2F7;
|
||||
padding: 8rpx;
|
||||
background-color: #FFFFFF;
|
||||
padding: 6rpx;
|
||||
border-radius: 20rpx;
|
||||
gap: 8rpx;
|
||||
margin-bottom: 24rpx;
|
||||
gap: 6rpx;
|
||||
margin-bottom: 16rpx;
|
||||
border: 2rpx solid #ECFDF3;
|
||||
box-shadow: 0 10rpx 22rpx rgba(16, 185, 129, 0.08);
|
||||
}
|
||||
|
||||
.segment-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
padding: 16rpx 0;
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
padding: 14rpx 0;
|
||||
font-size: 24rpx;
|
||||
font-weight: 600;
|
||||
color: #64748B;
|
||||
border-radius: 16rpx;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.segment-active {
|
||||
background-color: #FFFFFF;
|
||||
color: #111827;
|
||||
box-shadow: 0 8rpx 16rpx rgba(15, 23, 42, 0.06);
|
||||
background-color: #10B981;
|
||||
color: #0B2F23;
|
||||
box-shadow: 0 6rpx 16rpx rgba(16, 185, 129, 0.25);
|
||||
}
|
||||
|
||||
.insight-card {
|
||||
@@ -420,10 +428,11 @@ onMounted(() => {
|
||||
gap: 20rpx;
|
||||
align-items: flex-start;
|
||||
background-color: #ECFDF3;
|
||||
border: 2rpx solid #D4F6E2;
|
||||
border: 2rpx solid #D9FBE7;
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 28rpx;
|
||||
box-shadow: 0 10rpx 20rpx rgba(16, 185, 129, 0.1);
|
||||
}
|
||||
|
||||
.insight-icon {
|
||||
@@ -483,16 +492,19 @@ onMounted(() => {
|
||||
border-radius: 999rpx;
|
||||
font-size: 22rpx;
|
||||
font-weight: 600;
|
||||
border: 2rpx solid transparent;
|
||||
}
|
||||
|
||||
.status-good {
|
||||
background-color: #E8FFF1;
|
||||
color: #16A34A;
|
||||
border-color: #BBF7D0;
|
||||
}
|
||||
|
||||
.status-warn {
|
||||
background-color: #FEF3C7;
|
||||
color: #D97706;
|
||||
border-color: #FDE68A;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
@@ -510,7 +522,8 @@ onMounted(() => {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 28rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 12rpx 24rpx rgba(15, 23, 42, 0.06);
|
||||
border: 2rpx solid #ECFDF3;
|
||||
box-shadow: 0 12rpx 24rpx rgba(16, 185, 129, 0.1);
|
||||
}
|
||||
|
||||
.trend-header {
|
||||
@@ -545,7 +558,7 @@ onMounted(() => {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
height: 260rpx;
|
||||
height: 240rpx;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
@@ -559,8 +572,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.trend-bar {
|
||||
width: 36rpx;
|
||||
background: linear-gradient(180deg, #2DD36F 0%, #1A9F54 100%);
|
||||
width: 32rpx;
|
||||
background: linear-gradient(180deg, #34D399 0%, #10B981 100%);
|
||||
border-radius: 12rpx 12rpx 8rpx 8rpx;
|
||||
}
|
||||
|
||||
@@ -568,7 +581,7 @@ onMounted(() => {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
transform: translateY(-12rpx);
|
||||
background-color: #0F172A;
|
||||
background-color: #0F766E;
|
||||
color: #FFFFFF;
|
||||
font-size: 20rpx;
|
||||
padding: 4rpx 10rpx;
|
||||
@@ -591,7 +604,8 @@ onMounted(() => {
|
||||
border-radius: 28rpx;
|
||||
padding: 24rpx;
|
||||
margin-top: 20rpx;
|
||||
box-shadow: 0 12rpx 24rpx rgba(15, 23, 42, 0.05);
|
||||
border: 2rpx solid #FEF3C7;
|
||||
box-shadow: 0 12rpx 24rpx rgba(245, 158, 11, 0.08);
|
||||
}
|
||||
|
||||
.savings-header {
|
||||
@@ -607,17 +621,34 @@ onMounted(() => {
|
||||
border-radius: 8rpx;
|
||||
background-color: #FDE68A;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #D97706;
|
||||
}
|
||||
|
||||
.savings-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 8rpx;
|
||||
top: 8rpx;
|
||||
width: 16rpx;
|
||||
.savings-icon.icon-muted {
|
||||
background-color: #F1F5F9;
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
.savings-icon.icon-low {
|
||||
color: #E59E0B;
|
||||
}
|
||||
|
||||
.savings-icon.icon-mid {
|
||||
color: #D97706;
|
||||
}
|
||||
|
||||
.savings-icon.icon-strong {
|
||||
color: #B45309;
|
||||
}
|
||||
|
||||
.icon-coin {
|
||||
width: 18rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 4rpx;
|
||||
border: 3rpx solid #F59E0B;
|
||||
border: 3rpx solid currentColor;
|
||||
border-top-width: 6rpx;
|
||||
}
|
||||
|
||||
@@ -683,7 +714,7 @@ onMounted(() => {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 6rpx 16rpx rgba(15, 23, 42, 0.06);
|
||||
box-shadow: 0 6rpx 16rpx rgba(245, 158, 11, 0.12);
|
||||
}
|
||||
|
||||
.ring-value {
|
||||
@@ -697,7 +728,8 @@ onMounted(() => {
|
||||
border-radius: 28rpx;
|
||||
padding: 24rpx;
|
||||
margin-top: 24rpx;
|
||||
box-shadow: 0 12rpx 24rpx rgba(15, 23, 42, 0.05);
|
||||
border: 2rpx solid #ECFDF3;
|
||||
box-shadow: 0 12rpx 24rpx rgba(16, 185, 129, 0.08);
|
||||
}
|
||||
|
||||
.health-header {
|
||||
@@ -719,16 +751,47 @@ onMounted(() => {
|
||||
background-color: #DCFCE7;
|
||||
border-radius: 8rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #16A34A;
|
||||
}
|
||||
|
||||
.health-icon::after {
|
||||
content: '';
|
||||
.health-icon.icon-muted {
|
||||
background-color: #F1F5F9;
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
.health-icon.icon-low {
|
||||
color: #16A34A;
|
||||
}
|
||||
|
||||
.health-icon.icon-mid {
|
||||
color: #16A34A;
|
||||
}
|
||||
|
||||
.health-icon.icon-strong {
|
||||
color: #0F766E;
|
||||
}
|
||||
|
||||
.icon-plus-vertical,
|
||||
.icon-plus-horizontal {
|
||||
position: absolute;
|
||||
left: 12rpx;
|
||||
top: 6rpx;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-color: currentColor;
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.icon-plus-vertical {
|
||||
width: 4rpx;
|
||||
height: 16rpx;
|
||||
background-color: #16A34A;
|
||||
}
|
||||
|
||||
.icon-plus-horizontal {
|
||||
width: 16rpx;
|
||||
height: 4rpx;
|
||||
}
|
||||
|
||||
.health-title {
|
||||
@@ -744,6 +807,7 @@ onMounted(() => {
|
||||
background-color: #E8FFF1;
|
||||
color: #16A34A;
|
||||
font-weight: 600;
|
||||
border: 2rpx solid #BBF7D0;
|
||||
}
|
||||
|
||||
.health-list {
|
||||
@@ -789,7 +853,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.health-bar-fill-muted {
|
||||
background-color: #CBD5F5;
|
||||
background-color: #C7E6D4;
|
||||
}
|
||||
|
||||
.stats-grid {
|
||||
@@ -803,7 +867,8 @@ onMounted(() => {
|
||||
background-color: #FFFFFF;
|
||||
border-radius: 24rpx;
|
||||
padding: 24rpx;
|
||||
box-shadow: 0 12rpx 24rpx rgba(15, 23, 42, 0.04);
|
||||
border: 2rpx solid #ECFDF3;
|
||||
box-shadow: 0 12rpx 24rpx rgba(16, 185, 129, 0.06);
|
||||
}
|
||||
|
||||
.mini-icon {
|
||||
@@ -812,36 +877,63 @@ onMounted(() => {
|
||||
border-radius: 12rpx;
|
||||
margin-bottom: 12rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mini-icon-fire {
|
||||
background-color: #FEE2E2;
|
||||
}
|
||||
|
||||
.mini-icon-fire::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 12rpx;
|
||||
top: 8rpx;
|
||||
width: 16rpx;
|
||||
height: 20rpx;
|
||||
border-radius: 50% 50% 50% 50%;
|
||||
background-color: #F97316;
|
||||
color: #F97316;
|
||||
}
|
||||
|
||||
.mini-icon-block {
|
||||
background-color: #E0E7FF;
|
||||
color: #6366F1;
|
||||
}
|
||||
|
||||
.mini-icon-block::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 12rpx;
|
||||
top: 12rpx;
|
||||
.mini-icon.icon-muted {
|
||||
background-color: #F1F5F9;
|
||||
color: #94A3B8;
|
||||
}
|
||||
|
||||
.mini-icon-fire.icon-low {
|
||||
color: #FB923C;
|
||||
}
|
||||
|
||||
.mini-icon-fire.icon-mid {
|
||||
color: #F97316;
|
||||
}
|
||||
|
||||
.mini-icon-fire.icon-strong {
|
||||
color: #EA580C;
|
||||
}
|
||||
|
||||
.mini-icon-block.icon-low {
|
||||
color: #818CF8;
|
||||
}
|
||||
|
||||
.mini-icon-block.icon-mid {
|
||||
color: #6366F1;
|
||||
}
|
||||
|
||||
.mini-icon-block.icon-strong {
|
||||
color: #4F46E5;
|
||||
}
|
||||
|
||||
.icon-flame {
|
||||
width: 16rpx;
|
||||
height: 16rpx;
|
||||
height: 20rpx;
|
||||
background-color: currentColor;
|
||||
border-radius: 50% 50% 50% 50%;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.icon-shield {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
border-radius: 50%;
|
||||
border: 3rpx solid #6366F1;
|
||||
border: 3rpx solid currentColor;
|
||||
}
|
||||
|
||||
.mini-label {
|
||||
|
||||
Reference in New Issue
Block a user