- 移除DrinkCard组件中的模板切换功能和多种布局模式 - 简化DrinkCard组件结构,统一使用琥珀流光样式 - 添加未来日期禁用功能,防止用户选择未来日期 - 优化卡片样式为现代化深色主题设计 - 调整日历单元格点击交互逻辑,过滤未来日期 - 更新Canvas导出尺寸适配新卡片高度 - 优化照片网格布局算法,支持响应式排列 - 简化页面操作按钮,移除冗余功能入口 - 移除情感状态显示,专注核心饮酒记录功能
272 lines
6.0 KiB
Vue
272 lines
6.0 KiB
Vue
<template>
|
||
<view class="card-root">
|
||
<!-- 顶部:日期 -->
|
||
<view class="card-header">
|
||
<text class="header-date">{{ record.date }}</text>
|
||
</view>
|
||
|
||
<!-- 照片区域 -->
|
||
<view v-if="photos.length > 0" class="card-photos">
|
||
<!-- 1张: 大图 -->
|
||
<view v-if="photos.length === 1" class="photo-single">
|
||
<image :src="photos[0]" mode="aspectFill"></image>
|
||
</view>
|
||
<!-- 2-6张: 网格 -->
|
||
<view v-else class="photo-grid">
|
||
<view
|
||
v-for="(photo, i) in photos"
|
||
:key="i"
|
||
class="photo-cell"
|
||
:class="{ 'photo-span': i === 0 && photos.length % 2 !== 0 }"
|
||
>
|
||
<image :src="photo" mode="aspectFill"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 无照片: emoji -->
|
||
<view v-else class="card-hero">
|
||
<view class="hero-emoji-wrap">
|
||
<text class="hero-emoji">{{ mainEmoji }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 酒水清单 -->
|
||
<view class="drink-list">
|
||
<view v-for="(drink, i) in record.drinks" :key="i" class="drink-row">
|
||
<text class="drink-name">{{ getCatEmoji(drink.category) }} {{ drink.brand }}</text>
|
||
<text class="drink-detail">{{ formatAmount(drink) }}·{{ drink.standardCups }}杯</text>
|
||
</view>
|
||
<view v-if="record.food" class="drink-row">
|
||
<text class="drink-name">🍲 {{ getFoodName() }}</text>
|
||
<text class="drink-detail"></text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 分割线 -->
|
||
<view class="divider"></view>
|
||
|
||
<!-- 喝后心得(酒言酒语) -->
|
||
<view class="card-footer">
|
||
<text class="footer-label">喝后心得</text>
|
||
<text class="footer-quote">"{{ quote }}"</text>
|
||
</view>
|
||
|
||
<!-- 品牌 + 二维码 -->
|
||
<view class="card-brand">
|
||
<view class="brand-info">
|
||
<text class="brand-text">🍻 喝了么</text>
|
||
<text class="brand-slogan">记录每一杯的故事</text>
|
||
</view>
|
||
<view class="brand-qr"></view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { DRINK_CATEGORIES, FOOD_CATEGORIES, DRINK_QUOTES } from '../common/constants'
|
||
|
||
const UNIT_NAMES = { ml: 'ml', liang: '两', bottle: '瓶', cup: '杯', can: '听', shot: 'shot' }
|
||
|
||
export default {
|
||
props: {
|
||
record: { type: Object, required: true }
|
||
},
|
||
data() {
|
||
return {
|
||
quote: DRINK_QUOTES[Math.floor(Math.random() * DRINK_QUOTES.length)]
|
||
}
|
||
},
|
||
computed: {
|
||
photos() {
|
||
return (this.record && this.record.photos) || []
|
||
},
|
||
mainEmoji() {
|
||
const first = (this.record.drinks || [])[0]
|
||
return first ? this.getCatEmoji(first.category) : '🥃'
|
||
}
|
||
},
|
||
methods: {
|
||
getCatEmoji(catId) {
|
||
const cat = DRINK_CATEGORIES.find(c => c.id === catId)
|
||
return cat ? cat.emoji : '🥃'
|
||
},
|
||
getFoodName() {
|
||
const food = FOOD_CATEGORIES.find(f => f.id === this.record.food?.category)
|
||
if (!food) return this.record.food?.name || '美食'
|
||
return this.record.food.name ? `${food.name}·${this.record.food.name}` : food.name
|
||
},
|
||
formatAmount(drink) {
|
||
const unitName = UNIT_NAMES[drink.unit] || drink.unit
|
||
return `${drink.amount}${unitName}`
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.card-root {
|
||
position: relative;
|
||
width: 620rpx;
|
||
border-radius: 32rpx;
|
||
overflow: hidden;
|
||
background: linear-gradient(170deg, #1A1510 0%, #0D0B08 100%);
|
||
border: 2rpx solid rgba(232, 168, 56, 0.15);
|
||
box-shadow: 0 24rpx 80rpx rgba(0, 0, 0, 0.5), 0 0 60rpx rgba(232, 168, 56, 0.06);
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
|
||
/* 顶部 */
|
||
.card-header {
|
||
padding: $sp-lg $sp-xl 0;
|
||
}
|
||
.header-date {
|
||
font-size: $fs-sm;
|
||
color: $text-tertiary;
|
||
font-family: $font-num;
|
||
letter-spacing: 4rpx;
|
||
}
|
||
|
||
/* 照片区域 */
|
||
.card-photos {
|
||
padding: $sp-lg $sp-xl 0;
|
||
}
|
||
|
||
/* 1张:大图 */
|
||
.photo-single {
|
||
width: 100%;
|
||
height: 340rpx;
|
||
border-radius: $radius-lg;
|
||
overflow: hidden;
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
/* 2-6张:网格 */
|
||
.photo-grid {
|
||
display: grid;
|
||
grid-template-columns: 1fr 1fr;
|
||
gap: $sp-sm;
|
||
}
|
||
.photo-cell {
|
||
aspect-ratio: 1;
|
||
border-radius: $radius-md;
|
||
overflow: hidden;
|
||
image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
/* 奇数张时第一张占满两列 */
|
||
.photo-span {
|
||
grid-column: span 2;
|
||
aspect-ratio: 16 / 9;
|
||
}
|
||
|
||
/* emoji占位 */
|
||
.card-hero {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding: $sp-xl $sp-xl $sp-lg;
|
||
}
|
||
.hero-emoji-wrap {
|
||
width: 200rpx;
|
||
height: 200rpx;
|
||
border-radius: $radius-full;
|
||
background: rgba(232, 168, 56, 0.08);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.hero-emoji {
|
||
font-size: 100rpx;
|
||
line-height: 1;
|
||
}
|
||
|
||
/* 酒水清单 */
|
||
.drink-list {
|
||
padding: 0 $sp-xl;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: $sp-md;
|
||
}
|
||
.drink-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
}
|
||
.drink-name {
|
||
font-size: $fs-base;
|
||
color: $text-primary;
|
||
font-weight: $fw-medium;
|
||
flex-shrink: 0;
|
||
}
|
||
.drink-detail {
|
||
font-size: $fs-sm;
|
||
color: $amber;
|
||
font-family: $font-num;
|
||
font-weight: $fw-bold;
|
||
flex-shrink: 0;
|
||
margin-left: $sp-md;
|
||
}
|
||
|
||
/* 分割线 */
|
||
.divider {
|
||
margin: $sp-lg $sp-xl;
|
||
height: 2rpx;
|
||
background: linear-gradient(90deg, transparent, rgba(232, 168, 56, 0.15), transparent);
|
||
}
|
||
|
||
/* 底部 */
|
||
.card-footer {
|
||
padding: 0 $sp-xl;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: $sp-sm;
|
||
}
|
||
.footer-label {
|
||
font-size: $fs-xs;
|
||
color: $text-tertiary;
|
||
letter-spacing: 2rpx;
|
||
}
|
||
.footer-quote {
|
||
font-size: $fs-sm;
|
||
color: $text-secondary;
|
||
line-height: $lh-loose;
|
||
font-style: italic;
|
||
}
|
||
|
||
/* 品牌 + 二维码 */
|
||
.card-brand {
|
||
padding: $sp-lg $sp-xl $sp-xl;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
.brand-info {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4rpx;
|
||
}
|
||
.brand-text {
|
||
font-size: $fs-sm;
|
||
color: $text-tertiary;
|
||
font-weight: $fw-bold;
|
||
letter-spacing: 2rpx;
|
||
}
|
||
.brand-slogan {
|
||
font-size: $fs-xs;
|
||
color: $text-tertiary;
|
||
}
|
||
.brand-qr {
|
||
width: 80rpx;
|
||
height: 80rpx;
|
||
border-radius: $radius-sm;
|
||
border: 2rpx solid rgba(232, 168, 56, 0.15);
|
||
background: rgba(255, 255, 255, 0.03);
|
||
}
|
||
</style>
|