feat(app): 初始化喝酒了么小程序基础架构

- 添加项目配置文件(.editorconfig, .gitignore)
- 创建App.vue主应用文件,包含启动时Mock数据初始化
- 添加index.html和main.js应用入口文件
- 配置manifest.json应用基本信息和权限设置
- 设置pages.json页面路由和全局样式
- 添加uni.promisify.adaptor.js适配器文件
- 创建uni.scss设计令牌系统,定义琥珀夜光主题色彩
- 新增constants.js常量定义,包含酒类分类和品牌数据
This commit is contained in:
cg
2026-07-13 22:15:16 +08:00
parent 35af888097
commit f945ccf4c7
34 changed files with 6447 additions and 0 deletions
+291
View File
@@ -0,0 +1,291 @@
<template>
<view class="page-container card-page">
<!-- 顶部导航 -->
<view class="card-nav">
<view class="step-back" @click="goBack">
<text class="step-back-arrow"></text>
</view>
<text class="card-nav-title">你的酒局卡片</text>
</view>
<!-- 照片提示 -->
<view class="photo-hint" v-if="record">
<text class="photo-hint-text">
{{ photoHintText }}
</text>
</view>
<!-- 模板切换 -->
<view class="template-switcher">
<view
v-for="t in templates"
:key="t.id"
class="template-option"
:class="{ 'template-active': currentTemplate === t.id }"
@click="currentTemplate = t.id"
>
<view class="template-swatch" :style="{ background: t.swatch }">
<view class="swatch-dot" v-if="currentTemplate === t.id"></view>
</view>
<text class="template-label">{{ t.name }}</text>
<text class="template-desc">{{ t.desc }}</text>
</view>
</view>
<!-- 卡片预览 -->
<view class="card-preview-area">
<DrinkCard v-if="record" :record="record" :template="currentTemplate" />
</view>
<!-- 操作按钮 -->
<view class="card-actions">
<button class="btn-cta" @click="saveToAlbum">
💾 保存到相册
</button>
<view class="action-row">
<button class="btn-secondary action-btn" @click="shareToFriend">
🔗 分享好友
</button>
<button class="btn-secondary action-btn" @click="goHome">
🏠 返回首页
</button>
</view>
</view>
<!-- 成功提示 -->
<view v-if="showSuccess" class="success-toast">
<text> 已保存到相册</text>
</view>
</view>
</template>
<script>
import DrinkCard from '../../components/DrinkCard.vue'
import { getRecords } from '../../common/mock-data'
export default {
components: { DrinkCard },
data() {
return {
currentTemplate: 'amber',
record: null,
showSuccess: false,
templates: [
{
id: 'amber',
name: '琥珀流光',
desc: '温暖金色调',
swatch: 'linear-gradient(135deg, #1A1308, #0F0B06)'
},
{
id: 'aurora',
name: '暗夜极光',
desc: '冷色氛围感',
swatch: 'linear-gradient(135deg, #0A0E1A, #0E0A1A)'
},
{
id: 'film',
name: '胶片记忆',
desc: '复古胶片风',
swatch: 'linear-gradient(135deg, #141210, #0D0C0A)'
}
]
}
},
computed: {
photoHintText() {
if (!this.record) return ''
const photos = this.record.photos || []
if (photos.length === 0) return '📷 无照片 · 纯文字排版'
if (photos.length === 1) return '📸 单张照片 · 沉浸式全屏'
return `🖼️ ${photos.length}张照片 · 拼贴布局`
}
},
onLoad(options) {
const records = getRecords()
if (options && options.recordId) {
this.record = records.find(r => r.id === options.recordId)
}
if (!this.record) {
this.record = records.find(r => r.mode === 'drank') || this.getFallbackRecord()
}
},
methods: {
getFallbackRecord() {
return {
date: new Date().toISOString().slice(0, 10),
mode: 'drank',
drinks: [{ category: 'beer', brand: '青岛啤酒', product: '经典', amount: 2, unit: 'bottle', degree: 4.3, standardCups: 3.4 }],
food: { category: 'bbq', name: '烤串' },
feeling: 'tipsy',
photos: [],
standardCupsTotal: 3.4
}
},
saveToAlbum() {
this.showSuccess = true
uni.showToast({ title: '已保存到相册', icon: 'success' })
setTimeout(() => { this.showSuccess = false }, 2000)
},
shareToFriend() {
uni.showToast({ title: '点击右上角分享', icon: 'none' })
},
goHome() {
uni.reLaunch({ url: '/pages/index/index' })
},
goBack() {
uni.navigateBack()
}
},
onShareAppMessage() {
return {
title: '今晚的酒局记录 - 喝酒了么',
path: '/pages/index/index'
}
}
}
</script>
<style lang="scss" scoped>
.card-page {
padding: $sp-lg;
padding-bottom: calc(env(safe-area-inset-bottom) + $sp-xl);
display: flex;
flex-direction: column;
min-height: 100vh;
}
/* 导航 */
.card-nav {
display: flex;
align-items: center;
gap: $sp-md;
padding: $sp-md 0 $sp-lg;
}
.step-back {
width: 64rpx;
height: 64rpx;
display: flex;
align-items: center;
justify-content: center;
border-radius: $radius-full;
background: $bg-card;
}
.step-back-arrow {
font-size: $fs-xl;
color: $text-secondary;
font-weight: $fw-bold;
}
.card-nav-title {
font-size: $fs-lg;
font-weight: $fw-bold;
}
/* 照片数量提示 */
.photo-hint {
text-align: center;
margin-bottom: $sp-md;
}
.photo-hint-text {
font-size: $fs-xs;
color: $text-tertiary;
}
/* 模板切换 - 横排卡片选择 */
.template-switcher {
display: flex;
gap: $sp-md;
margin-bottom: $sp-xl;
justify-content: center;
}
.template-option {
display: flex;
flex-direction: column;
align-items: center;
gap: $sp-xs;
padding: $sp-sm $sp-md;
border-radius: $radius-lg;
border: 2rpx solid rgba(255, 255, 255, 0.05);
background: rgba(255, 255, 255, 0.02);
transition: all $duration-fast $ease-out;
flex: 1;
max-width: 220rpx;
&.template-active {
border-color: $amber;
background: rgba(232, 168, 56, 0.05);
}
}
.template-swatch {
width: 64rpx;
height: 80rpx;
border-radius: $radius-md;
border: 2rpx solid rgba(255, 255, 255, 0.1);
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.swatch-dot {
width: 12rpx;
height: 12rpx;
border-radius: $radius-full;
background: $amber;
}
.template-label {
font-size: $fs-xs;
color: $text-primary;
font-weight: $fw-medium;
}
.template-desc {
font-size: 18rpx;
color: $text-tertiary;
}
/* 卡片预览 */
.card-preview-area {
flex: 1;
display: flex;
align-items: flex-start;
justify-content: center;
margin-bottom: $sp-xl;
width: 100%;
}
/* 操作按钮 */
.card-actions {
padding-bottom: $sp-xl;
}
.action-row {
display: flex;
gap: $sp-md;
margin-top: $sp-md;
}
.action-btn {
flex: 1;
}
.success-toast {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.8);
color: #fff;
padding: $sp-lg $sp-xl;
border-radius: $radius-lg;
font-size: $fs-base;
z-index: 100;
}
</style>