- 将应用名称从"喝了么"更改为"干杯日记" - 更新所有相关文件中的品牌标识和描述信息 - 升级HaveADrink依赖包从1.0.3到1.0.4版本 - 在pages.json中新增分享个人资料页面配置 - 重构DrinkCard组件UI,增加装饰背景、酒类图标支持、饮酒感受徽章等功能 - 优化API错误处理逻辑,增加静默模式支持 - 修改白酒类别图标为 urn emoji,黄酒图标为 tea emoji - 添加分享功能按钮并优化页面返回交互体验 - 引入新的工具函数用于获取酒类图标和路径判断 - 更新主题混入、常量定义等基础配置文件 - 调整全局样式和设计令牌以匹配新品牌形象
727 lines
20 KiB
Vue
727 lines
20 KiB
Vue
<template>
|
||
<view :class="themeClass" class="page-container home">
|
||
<!-- 顶部问候 -->
|
||
<view class="greeting-bar" :style="{ paddingTop: statusBarHeight + 'px' }">
|
||
<view class="greeting-left">
|
||
<text class="greeting-text">{{ greeting }},{{ userName }}</text>
|
||
<text class="greeting-sub">今晚喝一杯?</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 核心CTA - 首页最醒目位置 -->
|
||
<view class="hero-cta" @click="goRecord">
|
||
<view class="hero-cta-bg"></view>
|
||
<view class="hero-cta-content">
|
||
<text class="hero-cta-emoji">🍻</text>
|
||
<view class="hero-cta-text">
|
||
<text class="hero-cta-title">开始记录</text>
|
||
<text class="hero-cta-sub">记录今晚的酒局</text>
|
||
</view>
|
||
<text class="hero-cta-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 统计卡片 -->
|
||
<view class="stats-row">
|
||
<view class="stat-card card">
|
||
<text class="stat-value text-num text-amber">{{ stats.monthDrinkCount }}</text>
|
||
<text class="stat-label">本月饮酒</text>
|
||
</view>
|
||
<view class="stat-card card">
|
||
<text class="stat-value text-num">{{ stats.monthCups }}</text>
|
||
<text class="stat-label">标准杯</text>
|
||
</view>
|
||
<view class="stat-card card">
|
||
<text class="stat-value text-num" :class="stats.streakType === 'drank' ? 'text-amber' : 'text-mint'">
|
||
{{ stats.streak }}
|
||
</text>
|
||
<text class="stat-label">{{ stats.streakType === 'drank' ? '连喝天数' : '戒酒天数' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 饮酒日历 -->
|
||
<view class="calendar-section card">
|
||
<DrinkCalendar
|
||
:year="calendarYear"
|
||
:month="calendarMonth"
|
||
:records="records"
|
||
@change-month="onMonthChange"
|
||
@select-date="onDateSelect"
|
||
/>
|
||
</view>
|
||
|
||
<!-- 本周摘要 -->
|
||
<view class="week-summary card">
|
||
<view class="week-header flex-between">
|
||
<text class="text-h3">本周摘要</text>
|
||
<text class="text-caption">{{ weekRange }}</text>
|
||
</view>
|
||
<view class="week-stats flex">
|
||
<view class="week-stat">
|
||
<text class="week-stat-value text-num">{{ stats.weekDrinkCount }}</text>
|
||
<text class="week-stat-label">次饮酒</text>
|
||
</view>
|
||
<view class="week-divider"></view>
|
||
<view class="week-stat">
|
||
<text class="week-stat-value text-num text-amber">{{ stats.weekCups }}</text>
|
||
<text class="week-stat-label">标准杯</text>
|
||
</view>
|
||
</view>
|
||
<view class="health-ref" v-if="stats.weekCups > 0">
|
||
<view class="health-bar-fill" :style="{ width: healthPercent + '%' }"></view>
|
||
<text class="health-text">
|
||
{{ stats.weekCups > 14 ? '本周超标了,注意休息' : '本周控制得不错' }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 底部健康提示 -->
|
||
<view class="bottom-health-tip">
|
||
<text>过量饮酒有害健康 · 请理性记录</text>
|
||
</view>
|
||
|
||
<!-- 日期记录弹窗 -->
|
||
<view v-if="showDayDetail" class="day-overlay" @click="showDayDetail = false">
|
||
<view class="day-detail card-elevated" @click.stop>
|
||
<view class="day-detail-header flex-between">
|
||
<text class="text-h3">{{ selectedDate }}</text>
|
||
<text class="btn-text" @click="showDayDetail = false">关闭</text>
|
||
</view>
|
||
<view v-if="selectedRecord">
|
||
<view v-if="selectedRecord.mode === 'drank'" class="day-record-info">
|
||
<view class="day-drinks">
|
||
<view v-for="(drink, i) in selectedRecord.drinks" :key="i" class="day-drink-item">
|
||
<view class="day-drink-row">
|
||
<view class="day-drink-name">
|
||
<image v-if="isIconPath(getCatIcon(drink.category))" :src="getCatIcon(drink.category)" class="day-drink-icon" mode="aspectFit"></image>
|
||
<text v-else>{{ getCatEmoji(drink.category) }}</text>
|
||
<text>{{ drink.brand }} {{ drink.product }}</text>
|
||
</view>
|
||
<text v-if="drink.customAmount != null" class="day-drink-amount text-num">{{ drink.customAmount }}{{ getUnitLabel(drink.customUnit) }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="day-meta flex-between">
|
||
<text class="text-caption">{{ getFeelingName(selectedRecord.feeling) }}</text>
|
||
<text class="text-caption text-amber text-num">{{ selectedRecord.standardCupsTotal }} 标准杯</text>
|
||
</view>
|
||
<view class="day-action-row">
|
||
<button class="btn-ghost day-action-btn" @click="editRecord">修改</button>
|
||
<button class="btn-ghost day-action-btn" @click="toggleToAbstain">改为未饮酒</button>
|
||
</view>
|
||
<button class="btn-danger day-delete-btn" @click="deleteRecord">删除记录</button>
|
||
</view>
|
||
<view v-else class="day-abstain">
|
||
<text class="day-abstain-emoji">🚫</text>
|
||
<text class="text-caption">今日未饮酒,好样的</text>
|
||
<button class="btn-ghost day-toggle-btn" @click="toggleToDrank">改为饮酒</button>
|
||
<button class="btn-danger day-delete-btn" @click="deleteRecord">删除记录</button>
|
||
</view>
|
||
</view>
|
||
<view v-else class="day-empty">
|
||
<text class="text-caption">当天无记录</text>
|
||
<button v-if="isSelectedToday" class="btn-primary day-record-btn" @click="goRecordToday">去记录</button>
|
||
<button v-else class="btn-ghost" @click="backfillDate">补打卡</button>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import DrinkCalendar from '../../components/DrinkCalendar.vue'
|
||
import client from '../../common/api'
|
||
import { GetCalendarReq, DeleteRecordReq, CreateRecordReq, GetRecordDetailReq } from 'HaveADrink'
|
||
import { getGreeting, formatDate, getWeekStart, getCatIcon, isIconPath } from '../../common/utils'
|
||
import { FEELINGS, DRINK_CATEGORIES, DRINK_UNITS } from '../../common/constants'
|
||
import themeMixin from '../../common/theme-mixin'
|
||
|
||
export default {
|
||
mixins: [themeMixin],
|
||
components: { DrinkCalendar },
|
||
data() {
|
||
const now = new Date()
|
||
const sysInfo = uni.getSystemInfoSync()
|
||
return {
|
||
statusBarHeight: sysInfo.statusBarHeight || 25,
|
||
calendarYear: now.getFullYear(),
|
||
calendarMonth: now.getMonth() + 1,
|
||
records: [],
|
||
stats: {},
|
||
greeting: '',
|
||
userName: '',
|
||
showDayDetail: false,
|
||
selectedDate: '',
|
||
selectedRecord: null
|
||
}
|
||
},
|
||
computed: {
|
||
weekRange() {
|
||
const weekStart = getWeekStart()
|
||
const weekEnd = new Date(weekStart)
|
||
weekEnd.setDate(weekEnd.getDate() + 6)
|
||
return `${formatDate(weekStart, 'MM/DD')} - ${formatDate(weekEnd, 'MM/DD')}`
|
||
},
|
||
healthPercent() {
|
||
// 建议每周不超过14标准杯
|
||
return Math.min((this.stats.weekCups / 14) * 100, 100)
|
||
},
|
||
isSelectedToday() {
|
||
return this.selectedDate === formatDate(new Date(), 'YYYY-MM-DD')
|
||
}
|
||
},
|
||
onShow() {
|
||
// 首次启动跳转引导页
|
||
const isFirst = uni.getStorageSync('is_first_launch')
|
||
if (isFirst === 'true') {
|
||
uni.reLaunch({ url: '/pages/onboarding/onboarding' })
|
||
return
|
||
}
|
||
this.loadData()
|
||
},
|
||
onShareAppMessage() {
|
||
return {
|
||
title: '干杯日记 - 让每一杯酒都有迹可循',
|
||
path: '/pages/index/index'
|
||
}
|
||
},
|
||
onShareTimeline() {
|
||
return {
|
||
title: '干杯日记 - 让每一杯酒都有迹可循',
|
||
query: ''
|
||
}
|
||
},
|
||
methods: {
|
||
async loadData() {
|
||
this.greeting = getGreeting()
|
||
// 并行加载用户信息、统计概览、记录列表
|
||
try {
|
||
const [userResp, statsResp, recordsResp] = await Promise.allSettled([
|
||
client.GetUserProfile({}),
|
||
client.GetStatsOverview({}),
|
||
client.GetCalendar(new GetCalendarReq(this.calendarYear, this.calendarMonth))
|
||
])
|
||
|
||
// 用户信息
|
||
if (userResp.status === 'fulfilled' && userResp.value) {
|
||
const user = userResp.value
|
||
this.userName = user.nickname || '酒友'
|
||
} else {
|
||
this.userName = '酒友'
|
||
}
|
||
|
||
// 统计概览
|
||
if (statsResp.status === 'fulfilled' && statsResp.value) {
|
||
const s = statsResp.value.data || statsResp.value
|
||
this.stats = {
|
||
weekDrinkCount: s.weekDrinkCount || 0,
|
||
weekCups: s.weekCups || 0,
|
||
monthDrinkCount: s.monthDrinkCount || 0,
|
||
monthCups: s.monthCups || 0,
|
||
streak: s.streak || 0,
|
||
streakType: String(s.streakType || 'drank'),
|
||
totalDays: s.totalDays || 0,
|
||
totalRecords: s.totalRecords || 0,
|
||
totalCups: s.totalCups || 0,
|
||
favCategory: s.favCategory ? String(s.favCategory) : null,
|
||
categoryVariety: s.categoryVariety || 0
|
||
}
|
||
}
|
||
|
||
// 日历数据
|
||
if (recordsResp.status === 'fulfilled' && recordsResp.value) {
|
||
const calData = recordsResp.value.data || recordsResp.value
|
||
const days = calData.days || []
|
||
this.records = days.filter(d => d && d.hasRecord).map(d => ({
|
||
id: d.id || '',
|
||
date: d.date,
|
||
mode: String(d.mode),
|
||
standardCupsTotal: d.standardCupsTotal || 0,
|
||
drinks: (d.drinks || []).map(dr => ({
|
||
...dr,
|
||
category: String(dr.category),
|
||
customAmount: dr.customAmount,
|
||
customUnit: dr.customUnit ? String(dr.customUnit) : ''
|
||
})),
|
||
food: d.food ? { category: String(d.food.category), name: d.food.name || '' } : null,
|
||
feeling: d.feeling ? String(d.feeling) : null,
|
||
quote: d.quote || '',
|
||
visibility: d.visibility ? String(d.visibility) : 'friends'
|
||
}))
|
||
}
|
||
} catch (e) {
|
||
console.warn('加载首页数据失败:', e)
|
||
this.userName = '酒友'
|
||
}
|
||
},
|
||
onMonthChange({ year, month }) {
|
||
this.calendarYear = year
|
||
this.calendarMonth = month
|
||
// 切换月份时重新加载记录
|
||
this.loadRecordsForMonth(year, month)
|
||
},
|
||
async loadRecordsForMonth(year, month) {
|
||
try {
|
||
const resp = await client.GetCalendar(new GetCalendarReq(year, month))
|
||
const calData = resp.data || resp
|
||
const days = calData.days || []
|
||
this.records = days.filter(d => d && d.hasRecord).map(d => ({
|
||
id: d.id || '',
|
||
date: d.date,
|
||
mode: String(d.mode),
|
||
standardCupsTotal: d.standardCupsTotal || 0,
|
||
drinks: (d.drinks || []).map(dr => ({
|
||
...dr,
|
||
category: String(dr.category),
|
||
customAmount: dr.customAmount,
|
||
customUnit: dr.customUnit ? String(dr.customUnit) : ''
|
||
})),
|
||
food: d.food ? { category: String(d.food.category), name: d.food.name || '' } : null,
|
||
feeling: d.feeling ? String(d.feeling) : null,
|
||
quote: d.quote || '',
|
||
visibility: d.visibility ? String(d.visibility) : 'friends'
|
||
}))
|
||
} catch (e) {
|
||
console.warn('加载月度记录失败:', e)
|
||
}
|
||
},
|
||
async onDateSelect(dateStr) {
|
||
this.selectedDate = dateStr
|
||
const localRecord = this.records.find(r => r.date === dateStr) || null
|
||
// 如果有记录且有id,拉取完整详情(确保拿到 customAmount/customUnit 等全量字段)
|
||
if (localRecord && localRecord.id && localRecord.mode === 'drank') {
|
||
this.selectedRecord = localRecord // 先用本地数据展示
|
||
this.showDayDetail = true
|
||
try {
|
||
const resp = await client.GetRecordDetail(new GetRecordDetailReq(localRecord.id))
|
||
const rec = resp.data || resp
|
||
if (rec) {
|
||
this.selectedRecord = {
|
||
...localRecord,
|
||
...rec,
|
||
mode: String(rec.mode || localRecord.mode),
|
||
drinks: (rec.drinks || localRecord.drinks || []).map(d => ({
|
||
...d,
|
||
category: String(d.category),
|
||
customUnit: d.customUnit ? String(d.customUnit) : ''
|
||
})),
|
||
feeling: rec.feeling ? String(rec.feeling) : localRecord.feeling,
|
||
visibility: rec.visibility ? String(rec.visibility) : localRecord.visibility
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.warn('获取记录详情失败,使用本地数据:', e)
|
||
}
|
||
} else {
|
||
this.selectedRecord = localRecord
|
||
this.showDayDetail = true
|
||
}
|
||
},
|
||
getFeelingName(feelingId) {
|
||
const f = FEELINGS.find(f => f.id === feelingId)
|
||
return f ? `${f.emoji} ${f.name}` : ''
|
||
},
|
||
getCatEmoji(catId) {
|
||
const cat = DRINK_CATEGORIES.find(c => c.id === catId)
|
||
return cat ? cat.emoji : '🥃'
|
||
},
|
||
getCatIcon,
|
||
isIconPath,
|
||
getUnitLabel(unitId) {
|
||
if (!unitId) return ''
|
||
const u = DRINK_UNITS.find(u => u.id === unitId)
|
||
return u ? u.name : unitId
|
||
},
|
||
backfillDate() {
|
||
this.showDayDetail = false
|
||
uni.navigateTo({
|
||
url: `/pages/record/record?date=${this.selectedDate}&mode=backfill`
|
||
})
|
||
},
|
||
// 修改记录(跳转到记录页编辑)
|
||
editRecord() {
|
||
this.showDayDetail = false
|
||
uni.navigateTo({
|
||
url: `/pages/record/record?date=${this.selectedDate}&mode=edit`
|
||
})
|
||
},
|
||
// 改为未饮酒
|
||
toggleToAbstain() {
|
||
uni.showModal({
|
||
title: '确认修改',
|
||
content: '确定将这天改为未饮酒吗?饮酒记录将被清除。',
|
||
success: async (res) => {
|
||
if (!res.confirm) return
|
||
const recordId = this.selectedRecord && this.selectedRecord.id
|
||
try {
|
||
if (recordId) {
|
||
await client.DeleteRecord(new DeleteRecordReq(recordId))
|
||
}
|
||
uni.showToast({ title: '已修改', icon: 'success' })
|
||
this.showDayDetail = false
|
||
this.loadData()
|
||
} catch (e) {
|
||
console.warn('修改为未饮酒失败:', e)
|
||
uni.showToast({ title: '修改失败,请重试', icon: 'none' })
|
||
}
|
||
}
|
||
})
|
||
},
|
||
// 改为饮酒(跳转到补录页)
|
||
toggleToDrank() {
|
||
this.showDayDetail = false
|
||
uni.navigateTo({
|
||
url: `/pages/record/record?date=${this.selectedDate}&mode=backfill`
|
||
})
|
||
},
|
||
// 删除记录
|
||
deleteRecord() {
|
||
uni.showModal({
|
||
title: '确认删除',
|
||
content: `确定删除 ${this.selectedDate} 的记录吗?删除后不可恢复。`,
|
||
confirmColor: '#e85d3a',
|
||
success: async (res) => {
|
||
if (!res.confirm) return
|
||
const recordId = this.selectedRecord && this.selectedRecord.id
|
||
try {
|
||
if (recordId) {
|
||
await client.DeleteRecord(new DeleteRecordReq(recordId))
|
||
}
|
||
this.showDayDetail = false
|
||
uni.showToast({ title: '已删除', icon: 'success' })
|
||
// 重新加载统计和日历数据
|
||
this.loadData()
|
||
} catch (e) {
|
||
console.warn('删除记录失败:', e)
|
||
uni.showToast({ title: '删除失败,请重试', icon: 'none' })
|
||
}
|
||
}
|
||
})
|
||
},
|
||
goRecord() {
|
||
uni.navigateTo({ url: '/pages/record/record' })
|
||
},
|
||
goRecordToday() {
|
||
this.showDayDetail = false
|
||
uni.navigateTo({ url: '/pages/record/record' })
|
||
},
|
||
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.home {
|
||
padding: $sp-md;
|
||
padding-top: 0;
|
||
}
|
||
|
||
.greeting-bar {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
padding: $sp-md 0 $sp-sm;
|
||
}
|
||
|
||
.greeting-text {
|
||
display: block;
|
||
font-size:38rpx;
|
||
font-weight: $fw-bold;
|
||
color: $text-primary;
|
||
}
|
||
|
||
.greeting-sub {
|
||
display: block;
|
||
font-size: $fs-xs;
|
||
color: $text-secondary;
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.calendar-section {
|
||
margin-bottom: $sp-md;
|
||
padding: $sp-md;
|
||
}
|
||
|
||
.stats-row {
|
||
display: flex;
|
||
gap: $sp-xs;
|
||
margin-bottom: $sp-md;
|
||
}
|
||
|
||
.stat-card {
|
||
flex: 1;
|
||
text-align: center;
|
||
padding: $sp-md $sp-xs;
|
||
}
|
||
|
||
.stat-value {
|
||
display: block;
|
||
font-size: $fs-xl;
|
||
color: $text-primary;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.stat-label {
|
||
font-size: $fs-xs;
|
||
color: $text-secondary;
|
||
}
|
||
|
||
.week-summary {
|
||
padding: $sp-md;
|
||
}
|
||
|
||
.week-header {
|
||
margin-bottom: $sp-sm;
|
||
}
|
||
|
||
.week-stats {
|
||
gap: 0;
|
||
}
|
||
|
||
.week-stat {
|
||
flex: 1;
|
||
text-align: center;
|
||
}
|
||
|
||
.week-stat-value {
|
||
display: block;
|
||
font-size: $fs-xl;
|
||
font-weight: $fw-bold;
|
||
color: $text-primary;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.week-stat-label {
|
||
font-size: $fs-sm;
|
||
color: $text-secondary;
|
||
}
|
||
|
||
.week-divider {
|
||
width: 2rpx;
|
||
background: var(--divider-color, rgba(255, 255, 255, 0.08));
|
||
margin: $sp-xs 0;
|
||
}
|
||
|
||
.health-ref {
|
||
margin-top: $sp-md;
|
||
position: relative;
|
||
height: 12rpx;
|
||
background: $bg-elevated;
|
||
border-radius: $radius-full;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.health-bar-fill {
|
||
height: 100%;
|
||
border-radius: $radius-full;
|
||
background: linear-gradient(90deg, $mint, $amber);
|
||
transition: width $duration-slow $ease-out;
|
||
}
|
||
|
||
.health-text {
|
||
display: block;
|
||
font-size: $fs-xs;
|
||
color: $text-tertiary;
|
||
margin-top: $sp-xs;
|
||
}
|
||
|
||
/* 核心CTA - 首页英雄区域 */
|
||
.hero-cta {
|
||
position: relative;
|
||
margin-bottom: $sp-md;
|
||
border-radius: $radius-lg;
|
||
overflow: hidden;
|
||
padding: $sp-md $sp-lg;
|
||
cursor: pointer;
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
}
|
||
}
|
||
|
||
.hero-cta-bg {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: linear-gradient(135deg, $amber-light, $amber, $amber-deep);
|
||
z-index: 0;
|
||
|
||
&::after {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: -100%;
|
||
width: 100%;
|
||
height: 100%;
|
||
background: linear-gradient(90deg, transparent, var(--btn-shimmer, rgba(255, 255, 255, 0.15)), transparent);
|
||
animation: shimmer 4s infinite;
|
||
}
|
||
}
|
||
|
||
@keyframes shimmer {
|
||
0% { left: -100%; }
|
||
100% { left: 100%; }
|
||
}
|
||
|
||
.hero-cta-content {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: $sp-md;
|
||
}
|
||
|
||
.hero-cta-emoji {
|
||
font-size: 56rpx;
|
||
}
|
||
|
||
.hero-cta-text {
|
||
flex: 1;
|
||
}
|
||
|
||
.hero-cta-title {
|
||
display: block;
|
||
font-size: $fs-xl;
|
||
font-weight: $fw-black;
|
||
color: $text-on-amber;
|
||
letter-spacing: -1rpx;
|
||
}
|
||
|
||
.hero-cta-sub {
|
||
display: block;
|
||
font-size: $fs-xs;
|
||
color: rgba(11, 11, 20, 0.6);
|
||
margin-top: 4rpx;
|
||
}
|
||
|
||
.hero-cta-arrow {
|
||
font-size: 44rpx;
|
||
color: $text-on-amber;
|
||
opacity: 0.5;
|
||
font-weight: $fw-bold;
|
||
}
|
||
|
||
.bottom-health-tip {
|
||
text-align: center;
|
||
padding: $sp-sm 0;
|
||
font-size: $fs-xs;
|
||
color: $text-tertiary;
|
||
opacity: 0.4;
|
||
}
|
||
|
||
/* 日期弹窗 */
|
||
.day-overlay {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: var(--overlay-mask, rgba(0, 0, 0, 0.6));
|
||
display: flex;
|
||
align-items: flex-end;
|
||
z-index: 100;
|
||
padding: $sp-lg;
|
||
}
|
||
|
||
.day-detail {
|
||
width: 100%;
|
||
padding: $sp-xl;
|
||
color: $text-primary;
|
||
border-radius: $radius-xl $radius-xl 0 0;
|
||
}
|
||
|
||
.day-detail-header {
|
||
margin-bottom: $sp-lg;
|
||
}
|
||
|
||
.day-drink-item {
|
||
padding: $sp-sm 0;
|
||
font-size: $fs-base;
|
||
color: $text-primary;
|
||
border-bottom: 2rpx solid var(--border-micro, rgba(255, 255, 255, 0.05));
|
||
}
|
||
|
||
.day-drink-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.day-drink-name {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: $sp-xs;
|
||
flex: 1;
|
||
min-width: 0;
|
||
}
|
||
|
||
.day-drink-icon {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.day-drink-amount {
|
||
font-size: $fs-sm;
|
||
color: $text-secondary;
|
||
white-space: nowrap;
|
||
margin-left: $sp-sm;
|
||
}
|
||
|
||
.day-meta {
|
||
margin-top: $sp-lg;
|
||
}
|
||
|
||
.day-abstain {
|
||
text-align: center;
|
||
padding: $sp-xl 0;
|
||
}
|
||
|
||
.day-abstain-emoji {
|
||
display: block;
|
||
font-size: $fs-hero;
|
||
margin-bottom: $sp-sm;
|
||
}
|
||
|
||
.day-empty {
|
||
text-align: center;
|
||
padding: $sp-xl 0;
|
||
|
||
.btn-ghost, .day-record-btn {
|
||
margin-top: $sp-lg;
|
||
width: 100%;
|
||
}
|
||
}
|
||
|
||
.day-action-row {
|
||
display: flex;
|
||
gap: $sp-sm;
|
||
margin-top: $sp-lg;
|
||
}
|
||
|
||
.day-action-btn {
|
||
flex: 1;
|
||
font-size: $fs-sm;
|
||
color: $text-secondary;
|
||
border-color: var(--border-active, rgba(255, 255, 255, 0.12));
|
||
}
|
||
|
||
.day-delete-btn {
|
||
margin-top: $sp-md;
|
||
width: 100%;
|
||
font-size: $fs-sm;
|
||
color: #e85d3a;
|
||
background: rgba(232, 93, 58, 0.08);
|
||
border: 2rpx solid rgba(232, 93, 58, 0.2);
|
||
}
|
||
|
||
.day-toggle-btn {
|
||
margin-top: $sp-lg;
|
||
width: 100%;
|
||
font-size: $fs-sm;
|
||
color: $text-secondary;
|
||
border-color: var(--border-active, rgba(255, 255, 255, 0.12));
|
||
}
|
||
</style>
|