feat(app): 项目重命名为干杯日记并优化UI设计
- 将应用名称从"喝了么"更改为"干杯日记" - 更新所有相关文件中的品牌标识和描述信息 - 升级HaveADrink依赖包从1.0.3到1.0.4版本 - 在pages.json中新增分享个人资料页面配置 - 重构DrinkCard组件UI,增加装饰背景、酒类图标支持、饮酒感受徽章等功能 - 优化API错误处理逻辑,增加静默模式支持 - 修改白酒类别图标为 urn emoji,黄酒图标为 tea emoji - 添加分享功能按钮并优化页面返回交互体验 - 引入新的工具函数用于获取酒类图标和路径判断 - 更新主题混入、常量定义等基础配置文件 - 调整全局样式和设计令牌以匹配新品牌形象
This commit is contained in:
+294
-123
@@ -1,17 +1,25 @@
|
||||
<template>
|
||||
<view class="card-root">
|
||||
<!-- 顶部:日期 -->
|
||||
<view class="card-header">
|
||||
<text class="header-date">{{ record.date }}</text>
|
||||
<!-- 装饰背景层 -->
|
||||
<view class="card-decor">
|
||||
<view class="decor-circle decor-circle-1"></view>
|
||||
<view class="decor-circle decor-circle-2"></view>
|
||||
<view class="decor-circle decor-circle-3"></view>
|
||||
<view class="decor-glow"></view>
|
||||
</view>
|
||||
|
||||
<!-- 照片区域 -->
|
||||
<!-- 顶部日期 -->
|
||||
<view class="card-top">
|
||||
<view class="date-line"></view>
|
||||
<text class="header-date">{{ record.date }}</text>
|
||||
<view class="date-line"></view>
|
||||
</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"
|
||||
@@ -23,43 +31,65 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 无照片: emoji -->
|
||||
<view v-else class="card-hero">
|
||||
<view class="hero-emoji-wrap">
|
||||
<text class="hero-emoji">{{ mainEmoji }}</text>
|
||||
<view class="hero-ring"></view>
|
||||
<view class="hero-inner">
|
||||
<image v-if="isIconPath(mainIcon)" :src="mainIcon" class="hero-icon-img" mode="aspectFit"></image>
|
||||
<text v-else class="hero-emoji">{{ mainIcon }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 饮酒感受徽章 -->
|
||||
<view v-if="feelingData" class="feeling-badge">
|
||||
<text class="feeling-emoji">{{ feelingData.emoji }}</text>
|
||||
<text class="feeling-name">{{ feelingData.name }}</text>
|
||||
<text class="feeling-desc">{{ feelingData.desc }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 酒水清单 -->
|
||||
<view class="drink-list">
|
||||
<view class="list-title-row">
|
||||
<view class="list-dot"></view>
|
||||
<text class="list-title">今夜菜单</text>
|
||||
<view class="list-dot"></view>
|
||||
</view>
|
||||
<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) }}</text>
|
||||
<view class="drink-left">
|
||||
<image v-if="isIconPath(getCatIcon(drink.category))" :src="getCatIcon(drink.category)" class="drink-icon-img" mode="aspectFit"></image>
|
||||
<text v-else class="drink-emoji">{{ getCatEmoji(drink.category) }}</text>
|
||||
<text class="drink-name">{{ drink.brand }}</text>
|
||||
</view>
|
||||
<view class="drink-dots"></view>
|
||||
<text class="drink-amount">{{ formatAmount(drink) }}</text>
|
||||
</view>
|
||||
<view v-if="record.food" class="drink-row">
|
||||
<text class="drink-name">🍲 {{ getFoodName() }}</text>
|
||||
<text class="drink-detail"></text>
|
||||
<view class="drink-left">
|
||||
<text class="drink-emoji">🍲</text>
|
||||
<text class="drink-name">{{ getFoodName() }}</text>
|
||||
</view>
|
||||
<view class="drink-dots"></view>
|
||||
<text class="drink-amount">佐酒</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 饮酒感受 -->
|
||||
<view v-if="feelingLabel" class="feeling-row">
|
||||
<text class="feeling-text">{{ feelingLabel }}</text>
|
||||
<!-- 分割装饰 -->
|
||||
<view class="divider-decor">
|
||||
<view class="divider-line"></view>
|
||||
<text class="divider-icon">🥂</text>
|
||||
<view class="divider-line"></view>
|
||||
</view>
|
||||
|
||||
<!-- 分割线 -->
|
||||
<view class="divider"></view>
|
||||
|
||||
<!-- 喝后心得(酒言酒语) -->
|
||||
<view class="card-footer">
|
||||
<text class="footer-label">喝后心得</text>
|
||||
<text class="footer-quote">"{{ quote }}"</text>
|
||||
<!-- 酒言酒语 -->
|
||||
<view class="quote-section">
|
||||
<text class="quote-mark">"</text>
|
||||
<text class="quote-text">{{ quote }}</text>
|
||||
<text class="quote-mark quote-mark-end">"</text>
|
||||
</view>
|
||||
|
||||
<!-- 品牌 + 二维码 -->
|
||||
<!-- 品牌底栏 -->
|
||||
<view class="card-brand">
|
||||
<view class="brand-info">
|
||||
<text class="brand-text">🍻 喝了么</text>
|
||||
<view class="brand-left">
|
||||
<text class="brand-name">干杯日记</text>
|
||||
<text class="brand-slogan">记录每一杯的故事</text>
|
||||
</view>
|
||||
<view class="brand-qr"></view>
|
||||
@@ -69,6 +99,7 @@
|
||||
|
||||
<script>
|
||||
import { DRINK_CATEGORIES, FOOD_CATEGORIES, DRINK_QUOTES, FEELINGS } from '../common/constants'
|
||||
import { getCatIcon, isIconPath } from '../common/utils'
|
||||
|
||||
const UNIT_NAMES = { ml: 'ml', liang: '两', bottle: '瓶', cup: '杯', can: '听', shot: 'shot' }
|
||||
|
||||
@@ -85,16 +116,17 @@ export default {
|
||||
photos() {
|
||||
return (this.record && this.record.photos) || []
|
||||
},
|
||||
mainEmoji() {
|
||||
mainIcon() {
|
||||
const first = (this.record.drinks || [])[0]
|
||||
return first ? this.getCatEmoji(first.category) : '🥃'
|
||||
return first ? getCatIcon(first.category) : '🥃'
|
||||
},
|
||||
feelingLabel() {
|
||||
const f = FEELINGS.find(fe => fe.id === this.record.feeling)
|
||||
return f ? `${f.emoji} ${f.name}` : ''
|
||||
feelingData() {
|
||||
return FEELINGS.find(fe => fe.id === this.record.feeling) || null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCatIcon,
|
||||
isIconPath,
|
||||
getCatEmoji(catId) {
|
||||
const cat = DRINK_CATEGORIES.find(c => c.id === catId)
|
||||
return cat ? cat.emoji : '🥃'
|
||||
@@ -116,178 +148,317 @@ export default {
|
||||
.card-root {
|
||||
position: relative;
|
||||
width: 620rpx;
|
||||
border-radius: 32rpx;
|
||||
border-radius: 40rpx;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(170deg, var(--card-gradient-start, #1A1510) 0%, var(--card-gradient-end, #0D0B08) 100%);
|
||||
border: 2rpx solid var(--border-subtle, rgba(255, 255, 255, 0.10));
|
||||
box-shadow: var(--shadow-lg, 0 16rpx 48rpx rgba(0, 0, 0, 0.45)), 0 0 60rpx var(--amber-glow, rgba(232, 168, 56, 0.15));
|
||||
background: linear-gradient(175deg, #1C1428 0%, #0F0A1A 40%, #0A0710 100%);
|
||||
border: 2rpx solid rgba(232, 168, 56, 0.2);
|
||||
box-shadow: 0 24rpx 80rpx rgba(0, 0, 0, 0.6), 0 0 80rpx rgba(232, 168, 56, 0.08), inset 0 1rpx 0 rgba(255, 255, 255, 0.06);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 56rpx 48rpx 40rpx;
|
||||
}
|
||||
|
||||
/* 顶部 */
|
||||
.card-header {
|
||||
padding: $sp-lg $sp-xl 0;
|
||||
/* === 装饰背景 === */
|
||||
.card-decor {
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0; bottom: 0;
|
||||
pointer-events: none;
|
||||
overflow: hidden;
|
||||
}
|
||||
.decor-circle {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
border: 1.5rpx solid rgba(232, 168, 56, 0.12);
|
||||
}
|
||||
.decor-circle-1 {
|
||||
width: 300rpx; height: 300rpx;
|
||||
top: -80rpx; right: -60rpx;
|
||||
}
|
||||
.decor-circle-2 {
|
||||
width: 200rpx; height: 200rpx;
|
||||
bottom: 200rpx; left: -60rpx;
|
||||
border-color: rgba(139, 133, 184, 0.1);
|
||||
}
|
||||
.decor-circle-3 {
|
||||
width: 120rpx; height: 120rpx;
|
||||
top: 320rpx; right: 40rpx;
|
||||
background: rgba(232, 168, 56, 0.03);
|
||||
}
|
||||
.decor-glow {
|
||||
position: absolute;
|
||||
width: 400rpx; height: 400rpx;
|
||||
top: -100rpx; left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: radial-gradient(circle, rgba(232, 168, 56, 0.06) 0%, transparent 70%);
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
/* === 顶部日期 === */
|
||||
.card-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 40rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.date-line {
|
||||
width: 60rpx;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, rgba(232, 168, 56, 0.5));
|
||||
}
|
||||
.date-line:last-child {
|
||||
background: linear-gradient(90deg, rgba(232, 168, 56, 0.5), transparent);
|
||||
}
|
||||
.header-date {
|
||||
font-size: $fs-sm;
|
||||
color: $text-tertiary;
|
||||
font-size: 22rpx;
|
||||
color: rgba(232, 168, 56, 0.8);
|
||||
font-family: $font-num;
|
||||
letter-spacing: 4rpx;
|
||||
letter-spacing: 6rpx;
|
||||
font-weight: $fw-medium;
|
||||
}
|
||||
|
||||
/* 照片区域 */
|
||||
/* === 照片区域 === */
|
||||
.card-photos {
|
||||
padding: $sp-lg $sp-xl 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
/* 1张:大图 */
|
||||
.photo-single {
|
||||
width: 100%;
|
||||
height: 340rpx;
|
||||
border-radius: $radius-lg;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.4);
|
||||
image { width: 100%; height: 100%; }
|
||||
}
|
||||
|
||||
/* 2-6张:网格 */
|
||||
.photo-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: $sp-sm;
|
||||
gap: 12rpx;
|
||||
}
|
||||
.photo-cell {
|
||||
aspect-ratio: 1;
|
||||
border-radius: $radius-md;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
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;
|
||||
padding: 24rpx 0 32rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.hero-emoji-wrap {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
border-radius: $radius-full;
|
||||
background: rgba(232, 168, 56, 0.08);
|
||||
.hero-ring {
|
||||
position: absolute;
|
||||
width: 220rpx; height: 220rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid rgba(232, 168, 56, 0.15);
|
||||
animation: pulse-ring 3s ease-in-out infinite;
|
||||
}
|
||||
@keyframes pulse-ring {
|
||||
0%, 100% { transform: scale(1); opacity: 0.6; }
|
||||
50% { transform: scale(1.08); opacity: 1; }
|
||||
}
|
||||
.hero-inner {
|
||||
width: 180rpx; height: 180rpx;
|
||||
border-radius: 50%;
|
||||
background: radial-gradient(circle at 35% 35%, rgba(232, 168, 56, 0.15), rgba(232, 168, 56, 0.04));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 8rpx 32rpx rgba(232, 168, 56, 0.1), inset 0 0 40rpx rgba(232, 168, 56, 0.05);
|
||||
}
|
||||
.hero-emoji {
|
||||
font-size: 100rpx;
|
||||
font-size: 88rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
.hero-icon-img {
|
||||
width: 110rpx;
|
||||
height: 110rpx;
|
||||
}
|
||||
|
||||
/* 酒水清单 */
|
||||
.drink-list {
|
||||
padding: 0 $sp-xl;
|
||||
/* === 感受徽章 === */
|
||||
.feeling-badge {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $sp-md;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12rpx;
|
||||
margin: 0 auto 32rpx;
|
||||
padding: 14rpx 32rpx;
|
||||
background: linear-gradient(135deg, rgba(232, 168, 56, 0.12), rgba(232, 168, 56, 0.04));
|
||||
border: 1.5rpx solid rgba(232, 168, 56, 0.25);
|
||||
border-radius: 999rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.feeling-emoji {
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.feeling-name {
|
||||
font-size: 26rpx;
|
||||
color: #E8A838;
|
||||
font-weight: $fw-bold;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
.feeling-desc {
|
||||
font-size: 20rpx;
|
||||
color: rgba(232, 168, 56, 0.6);
|
||||
}
|
||||
|
||||
/* === 酒水清单 === */
|
||||
.drink-list {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 32rpx;
|
||||
background: rgba(255, 255, 255, 0.02);
|
||||
border-radius: 24rpx;
|
||||
border: 1.5rpx solid rgba(255, 255, 255, 0.05);
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.list-title-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
.list-dot {
|
||||
width: 8rpx; height: 8rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(232, 168, 56, 0.5);
|
||||
}
|
||||
.list-title {
|
||||
font-size: 22rpx;
|
||||
color: rgba(232, 168, 56, 0.7);
|
||||
letter-spacing: 8rpx;
|
||||
font-weight: $fw-medium;
|
||||
}
|
||||
.drink-row {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 14rpx 0;
|
||||
}
|
||||
.drink-name {
|
||||
font-size: $fs-base;
|
||||
color: $text-primary;
|
||||
font-weight: $fw-medium;
|
||||
.drink-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.drink-detail {
|
||||
font-size: $fs-sm;
|
||||
color: $amber;
|
||||
.drink-icon-img {
|
||||
width: 34rpx; height: 34rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.drink-emoji {
|
||||
font-size: 28rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.drink-name {
|
||||
font-size: 28rpx;
|
||||
color: #FFFFFF;
|
||||
font-weight: $fw-medium;
|
||||
}
|
||||
.drink-dots {
|
||||
flex: 1;
|
||||
height: 2rpx;
|
||||
margin: 0 16rpx;
|
||||
background: repeating-linear-gradient(90deg, rgba(255,255,255,0.15) 0, rgba(255,255,255,0.15) 4rpx, transparent 4rpx, transparent 10rpx);
|
||||
}
|
||||
.drink-amount {
|
||||
font-size: 26rpx;
|
||||
color: #E8A838;
|
||||
font-family: $font-num;
|
||||
font-weight: $fw-bold;
|
||||
flex-shrink: 0;
|
||||
margin-left: $sp-md;
|
||||
}
|
||||
|
||||
/* 饮酒感受 */
|
||||
.feeling-row {
|
||||
padding: $sp-sm $sp-xl 0;
|
||||
/* === 分割装饰 === */
|
||||
.divider-decor {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
margin-bottom: 32rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.feeling-text {
|
||||
font-size: $fs-base;
|
||||
color: $amber;
|
||||
font-weight: $fw-medium;
|
||||
letter-spacing: 2rpx;
|
||||
.divider-line {
|
||||
flex: 1;
|
||||
height: 1.5rpx;
|
||||
background: linear-gradient(90deg, transparent, rgba(232, 168, 56, 0.2), transparent);
|
||||
}
|
||||
.divider-icon {
|
||||
font-size: 28rpx;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* 分割线 */
|
||||
.divider {
|
||||
margin: $sp-lg $sp-xl;
|
||||
height: 2rpx;
|
||||
background: linear-gradient(90deg, transparent, rgba(232, 168, 56, 0.15), transparent);
|
||||
/* === 酒言酒语 === */
|
||||
.quote-section {
|
||||
text-align: center;
|
||||
padding: 0 16rpx;
|
||||
margin-bottom: 40rpx;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* 底部 */
|
||||
.card-footer {
|
||||
padding: 0 $sp-xl;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $sp-sm;
|
||||
.quote-mark {
|
||||
font-size: 48rpx;
|
||||
color: rgba(232, 168, 56, 0.3);
|
||||
font-family: Georgia, serif;
|
||||
line-height: 1;
|
||||
}
|
||||
.footer-label {
|
||||
font-size: $fs-xs;
|
||||
color: $text-tertiary;
|
||||
.quote-mark-end {
|
||||
display: block;
|
||||
text-align: right;
|
||||
}
|
||||
.quote-text {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
line-height: 1.8;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
.footer-quote {
|
||||
font-size: $fs-sm;
|
||||
color: $text-secondary;
|
||||
line-height: $lh-loose;
|
||||
padding: 8rpx 0;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* 品牌 + 二维码 */
|
||||
/* === 品牌底栏 === */
|
||||
.card-brand {
|
||||
padding: $sp-lg $sp-xl $sp-xl;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 32rpx;
|
||||
border-top: 1.5rpx solid rgba(255, 255, 255, 0.05);
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
.brand-info {
|
||||
.brand-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4rpx;
|
||||
gap: 6rpx;
|
||||
}
|
||||
.brand-text {
|
||||
font-size: $fs-sm;
|
||||
color: $text-tertiary;
|
||||
.brand-name {
|
||||
font-size: 26rpx;
|
||||
color: rgba(232, 168, 56, 0.8);
|
||||
font-weight: $fw-bold;
|
||||
letter-spacing: 2rpx;
|
||||
letter-spacing: 4rpx;
|
||||
}
|
||||
.brand-slogan {
|
||||
font-size: $fs-xs;
|
||||
color: $text-tertiary;
|
||||
font-size: 20rpx;
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
.brand-qr {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: $radius-sm;
|
||||
border: 2rpx solid var(--border-subtle, rgba(255, 255, 255, 0.10));
|
||||
background: var(--bg-subtle, rgba(255, 255, 255, 0.03));
|
||||
border-radius: 12rpx;
|
||||
border: 1.5rpx solid rgba(232, 168, 56, 0.2);
|
||||
background: rgba(232, 168, 56, 0.04);
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user