feat(calendar): 更新日历接口并优化记录流程
- 将GetRecords接口替换为GetCalendar接口获取日历数据 - 重构首页日历数据显示逻辑,支持年月维度的数据获取 - 优化打卡记录流程,合并选酒和记量步骤为单一添加酒水步骤 - 移除登录页面的游客模式选项,简化首次启动逻辑 - 调整引导页逻辑,移除登录跳转改为直接进入首页 - 优化记录页面UI布局,添加状态栏安全距离适配 - 新增酒水列表管理功能,支持添加和删除已选酒水 - 更新依赖包HaveADrink至v1.0.3版本,同步API变更
This commit is contained in:
@@ -59,17 +59,12 @@ export default {
|
|||||||
}
|
}
|
||||||
} catch (e) { /* ignore */ }
|
} catch (e) { /* ignore */ }
|
||||||
},
|
},
|
||||||
// 启动时检查登录与引导状态,决定跳转目标
|
// 启动时检查引导状态,决定跳转目标
|
||||||
checkLaunchRoute() {
|
checkLaunchRoute() {
|
||||||
const isFirst = uni.getStorageSync('is_first_launch')
|
const isFirst = uni.getStorageSync('is_first_launch')
|
||||||
const isLoggedIn = uni.getStorageSync('is_logged_in')
|
|
||||||
|
|
||||||
if (!isFirst || isFirst === 'true') {
|
if (!isFirst || isFirst === 'true') {
|
||||||
// 首次使用 → 引导页
|
// 首次使用 → 引导页
|
||||||
uni.reLaunch({ url: '/pages/onboarding/onboarding' })
|
uni.reLaunch({ url: '/pages/onboarding/onboarding' })
|
||||||
} else if (!isLoggedIn || isLoggedIn !== 'true') {
|
|
||||||
// 未登录 → 登录页
|
|
||||||
uni.reLaunch({ url: '/pages/login/login' })
|
|
||||||
}
|
}
|
||||||
// 否则正常进入首页(index)
|
// 否则正常进入首页(index)
|
||||||
}
|
}
|
||||||
@@ -98,6 +93,7 @@ page {
|
|||||||
background-color: $bg-base;
|
background-color: $bg-base;
|
||||||
color: $text-primary;
|
color: $text-primary;
|
||||||
padding-bottom: env(safe-area-inset-bottom);
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
@@ -255,6 +251,35 @@ page {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 添加酒水按钮(Step 1 底部) */
|
||||||
|
.btn-add-drink {
|
||||||
|
background: linear-gradient(135deg, $amber, $amber-deep);
|
||||||
|
color: $text-on-amber;
|
||||||
|
font-size: $fs-md;
|
||||||
|
font-weight: $fw-bold;
|
||||||
|
padding: $sp-md $sp-xl;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
border: none;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: $shadow-amber;
|
||||||
|
transition: all $duration-fast $ease-out;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.97);
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(232, 168, 56, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[disabled] {
|
||||||
|
background: transparent;
|
||||||
|
color: $text-tertiary;
|
||||||
|
border: 2rpx solid var(--border-subtle, rgba(255, 255, 255, 0.10));
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.btn-text {
|
.btn-text {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
+3
-3
@@ -4,9 +4,9 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"node_modules/HaveADrink": {
|
"node_modules/HaveADrink": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://npm.wash-painting.cn/HaveADrink/-/HaveADrink-1.0.2.tgz",
|
"resolved": "https://npm.wash-painting.cn/HaveADrink/-/HaveADrink-1.0.3.tgz",
|
||||||
"integrity": "sha512-rhcILwsr6F1SBK7z+C4HMemUHHd63pl5ggxHisky0ZDgCOL7bITf3TGgvoiqXRoAGe4qmV+4FT8E6oCbvD1PIg==",
|
"integrity": "sha512-Mp4WRwqFmrf9CQhlF+gdJQ4YGRZkrBSbcu1l+XF4nq5dZmrFW7iggzFH4XSIXewBME1svk+cMhN6vetZVVOA6Q==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-10
@@ -14,7 +14,7 @@
|
|||||||
* 6. 社交模块 - 朋友圈动态、点赞
|
* 6. 社交模块 - 朋友圈动态、点赞
|
||||||
|
|
||||||
|
|
||||||
**版本:** v1.0.2
|
**版本:** v1.0.3
|
||||||
|
|
||||||
## 安装
|
## 安装
|
||||||
|
|
||||||
@@ -816,18 +816,12 @@ client.DeleteRecord(req).then(...).catch(...)
|
|||||||
#### 返回值
|
#### 返回值
|
||||||
|名称|类型|说明|
|
|名称|类型|说明|
|
||||||
|:-|:-:|:-|
|
|:-|:-:|:-|
|
||||||
|data|`CalendarData`| 日历数据<br>|
|
|year|`number`| 年份<br>|
|
||||||
|
|month|`number`| 月份<br>|
|
||||||
|
|days|`Array<CalendarDayData>`| 每天的打卡数据,null表示当天无记录<br>|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**CalendarData**
|
|
||||||
|名称|类型|说明|
|
|
||||||
|:-|:-|:-|
|
|
||||||
|year|`number`| 年份|
|
|
||||||
|month|`number`| 月份|
|
|
||||||
|days|`Array<CalendarDayData>`| 每天的打卡数据,null表示当天无记录|
|
|
||||||
|
|
||||||
|
|
||||||
**CalendarDayData**
|
**CalendarDayData**
|
||||||
|名称|类型|说明|
|
|名称|类型|说明|
|
||||||
|:-|:-|:-|
|
|:-|:-|:-|
|
||||||
@@ -835,6 +829,57 @@ client.DeleteRecord(req).then(...).catch(...)
|
|||||||
|hasRecord|`boolean`| 是否有记录|
|
|hasRecord|`boolean`| 是否有记录|
|
||||||
|mode|`Mode`| 打卡模式|
|
|mode|`Mode`| 打卡模式|
|
||||||
|standardCupsTotal|`number`| 标准杯总数|
|
|standardCupsTotal|`number`| 标准杯总数|
|
||||||
|
|id|`string\|number`| 记录ID|
|
||||||
|
|drinks|`Array<DrinkItem>`| 酒水列表|
|
||||||
|
|food|`FoodInfo`| 配餐信息|
|
||||||
|
|feeling|`Feeling`| 感受|
|
||||||
|
|photos|`Array<string>`| 照片URL数组|
|
||||||
|
|visibility|`Visibility`| 可见范围|
|
||||||
|
|quote|`string`| 酒言酒语|
|
||||||
|
|createdAt|`string`| 创建时间|
|
||||||
|
|
||||||
|
|
||||||
|
**Mode**
|
||||||
|
|名称|值|类型|说明|
|
||||||
|
|:-|:-:|:-|:-|
|
||||||
|
|Drank|"drank"|`Mode`|今日喝了|
|
||||||
|
|Abstain|"abstain"|`Mode`|今日未喝|
|
||||||
|
|
||||||
|
|
||||||
|
**DrinkItem**
|
||||||
|
|名称|类型|说明|
|
||||||
|
|:-|:-|:-|
|
||||||
|
|category|`Category`| 酒类分类ID|
|
||||||
|
|brand|`string`| 品牌名称|
|
||||||
|
|product|`string`| 产品名|
|
||||||
|
|amount|`number`| 饮用量数值|
|
||||||
|
|unit|`Unit`| 单位|
|
||||||
|
|degree|`number`| 酒精度数(%)|
|
||||||
|
|standardCups|`number`| 标准杯数(前端计算,后端应校验)|
|
||||||
|
|
||||||
|
|
||||||
|
**FoodInfo**
|
||||||
|
|名称|类型|说明|
|
||||||
|
|:-|:-|:-|
|
||||||
|
|category|`FoodCategory`| 配餐分类ID|
|
||||||
|
|name|`string`| 具体菜名|
|
||||||
|
|
||||||
|
|
||||||
|
**Feeling**
|
||||||
|
|名称|值|类型|说明|
|
||||||
|
|:-|:-:|:-|:-|
|
||||||
|
|Tipsy|"tipsy"|`Feeling`|微醺|
|
||||||
|
|Buzzed|"buzzed"|`Feeling`|到位|
|
||||||
|
|Drunk|"drunk"|`Feeling`|醉了|
|
||||||
|
|Blackout|"blackout"|`Feeling`|断片|
|
||||||
|
|
||||||
|
|
||||||
|
**Visibility**
|
||||||
|
|名称|值|类型|说明|
|
||||||
|
|:-|:-:|:-|:-|
|
||||||
|
|Public|"public"|`Visibility`|公开|
|
||||||
|
|Friends|"friends"|`Visibility`|仅好友|
|
||||||
|
|Private|"private"|`Visibility`|仅自己|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+66
-6
@@ -1594,14 +1594,54 @@ export declare class CalendarDayData {
|
|||||||
* 标准杯总数
|
* 标准杯总数
|
||||||
*/
|
*/
|
||||||
standardCupsTotal: number;
|
standardCupsTotal: number;
|
||||||
|
/**
|
||||||
|
* 记录ID
|
||||||
|
*/
|
||||||
|
id: string|number;
|
||||||
|
/**
|
||||||
|
* 酒水列表
|
||||||
|
*/
|
||||||
|
drinks: Array<DrinkItem>;
|
||||||
|
/**
|
||||||
|
* 配餐信息
|
||||||
|
*/
|
||||||
|
food: FoodInfo;
|
||||||
|
/**
|
||||||
|
* 感受
|
||||||
|
*/
|
||||||
|
feeling: Feeling;
|
||||||
|
/**
|
||||||
|
* 照片URL数组
|
||||||
|
*/
|
||||||
|
photos: Array<string>;
|
||||||
|
/**
|
||||||
|
* 可见范围
|
||||||
|
*/
|
||||||
|
visibility: Visibility;
|
||||||
|
/**
|
||||||
|
* 酒言酒语
|
||||||
|
*/
|
||||||
|
quote: string;
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
createdAt: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param date string 日期YYYY-MM-DD
|
* @param date string 日期YYYY-MM-DD
|
||||||
* @param hasRecord boolean 是否有记录
|
* @param hasRecord boolean 是否有记录
|
||||||
* @param mode Mode 打卡模式
|
* @param mode Mode 打卡模式
|
||||||
* @param standardCupsTotal number 标准杯总数
|
* @param standardCupsTotal number 标准杯总数
|
||||||
|
* @param id string|number 记录ID
|
||||||
|
* @param drinks Array<DrinkItem> 酒水列表
|
||||||
|
* @param food FoodInfo 配餐信息
|
||||||
|
* @param feeling Feeling 感受
|
||||||
|
* @param photos Array<string> 照片URL数组
|
||||||
|
* @param visibility Visibility 可见范围
|
||||||
|
* @param quote string 酒言酒语
|
||||||
|
* @param createdAt string 创建时间
|
||||||
*/
|
*/
|
||||||
constructor(date: string,hasRecord: boolean,mode: Mode,standardCupsTotal: number,);
|
constructor(date: string,hasRecord: boolean,mode: Mode,standardCupsTotal: number,id: string|number,drinks: Array<DrinkItem>,food: FoodInfo,feeling: Feeling,photos: Array<string>,visibility: Visibility,quote: string,createdAt: string,);
|
||||||
/**
|
/**
|
||||||
* 从对象创建 CalendarDayData
|
* 从对象创建 CalendarDayData
|
||||||
*
|
*
|
||||||
@@ -1610,6 +1650,14 @@ export declare class CalendarDayData {
|
|||||||
* - hasRecord: boolean, // 是否有记录
|
* - hasRecord: boolean, // 是否有记录
|
||||||
* - mode: Mode, // 打卡模式
|
* - mode: Mode, // 打卡模式
|
||||||
* - standardCupsTotal: number, // 标准杯总数
|
* - standardCupsTotal: number, // 标准杯总数
|
||||||
|
* - id: string|number, // 记录ID
|
||||||
|
* - drinks: Array<DrinkItem>, // 酒水列表
|
||||||
|
* - food: FoodInfo, // 配餐信息
|
||||||
|
* - feeling: Feeling, // 感受
|
||||||
|
* - photos: Array<string>, // 照片URL数组
|
||||||
|
* - visibility: Visibility, // 可见范围
|
||||||
|
* - quote: string, // 酒言酒语
|
||||||
|
* - createdAt: string, // 创建时间
|
||||||
*/
|
*/
|
||||||
static fromObject(o: Object): CalendarDayData;
|
static fromObject(o: Object): CalendarDayData;
|
||||||
}
|
}
|
||||||
@@ -1620,19 +1668,31 @@ export declare class CalendarDayData {
|
|||||||
export declare class GetCalendarResp {
|
export declare class GetCalendarResp {
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
/**
|
/**
|
||||||
* 日历数据
|
* 年份
|
||||||
*/
|
*/
|
||||||
data: CalendarData;
|
year: number;
|
||||||
|
/**
|
||||||
|
* 月份
|
||||||
|
*/
|
||||||
|
month: number;
|
||||||
|
/**
|
||||||
|
* 每天的打卡数据,null表示当天无记录
|
||||||
|
*/
|
||||||
|
days: Array<CalendarDayData>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param data CalendarData 日历数据
|
* @param year number 年份
|
||||||
|
* @param month number 月份
|
||||||
|
* @param days Array<CalendarDayData> 每天的打卡数据,null表示当天无记录
|
||||||
*/
|
*/
|
||||||
constructor(data: CalendarData,);
|
constructor(year: number,month: number,days: Array<CalendarDayData>,);
|
||||||
/**
|
/**
|
||||||
* 从对象创建 GetCalendarResp
|
* 从对象创建 GetCalendarResp
|
||||||
*
|
*
|
||||||
* @param o Object
|
* @param o Object
|
||||||
* - data: CalendarData, // 日历数据
|
* - year: number, // 年份
|
||||||
|
* - month: number, // 月份
|
||||||
|
* - days: Array<CalendarDayData>, // 每天的打卡数据,null表示当天无记录
|
||||||
*/
|
*/
|
||||||
static fromObject(o: Object): GetCalendarResp;
|
static fromObject(o: Object): GetCalendarResp;
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-6
@@ -1165,16 +1165,32 @@ export class CalendarDayData {
|
|||||||
* @param hasRecord: boolean 是否有记录
|
* @param hasRecord: boolean 是否有记录
|
||||||
* @param mode: Mode 打卡模式
|
* @param mode: Mode 打卡模式
|
||||||
* @param standardCupsTotal: number 标准杯总数
|
* @param standardCupsTotal: number 标准杯总数
|
||||||
|
* @param id: string|number 记录ID
|
||||||
|
* @param drinks: Array<DrinkItem> 酒水列表
|
||||||
|
* @param food: FoodInfo 配餐信息
|
||||||
|
* @param feeling: Feeling 感受
|
||||||
|
* @param photos: Array<string> 照片URL数组
|
||||||
|
* @param visibility: Visibility 可见范围
|
||||||
|
* @param quote: string 酒言酒语
|
||||||
|
* @param createdAt: string 创建时间
|
||||||
*/
|
*/
|
||||||
constructor(date,hasRecord,mode,standardCupsTotal,) {
|
constructor(date,hasRecord,mode,standardCupsTotal,id,drinks,food,feeling,photos,visibility,quote,createdAt,) {
|
||||||
this.date = date;
|
this.date = date;
|
||||||
this.hasRecord = hasRecord;
|
this.hasRecord = hasRecord;
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
this.standardCupsTotal = standardCupsTotal;
|
this.standardCupsTotal = standardCupsTotal;
|
||||||
|
this.id = id;
|
||||||
|
this.drinks = drinks;
|
||||||
|
this.food = food;
|
||||||
|
this.feeling = feeling;
|
||||||
|
this.photos = photos;
|
||||||
|
this.visibility = visibility;
|
||||||
|
this.quote = quote;
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
|
||||||
}
|
}
|
||||||
static fromObject(o) {
|
static fromObject(o) {
|
||||||
return new CalendarDayData(o.date,o.hasRecord,o.mode,o.standardCupsTotal,);
|
return new CalendarDayData(o.date,o.hasRecord,o.mode,o.standardCupsTotal,o.id,o.drinks,o.food,o.feeling,o.photos,o.visibility,o.quote,o.createdAt,);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1183,14 +1199,18 @@ export class CalendarDayData {
|
|||||||
*/
|
*/
|
||||||
export class GetCalendarResp {
|
export class GetCalendarResp {
|
||||||
/**
|
/**
|
||||||
* @param data: CalendarData 日历数据
|
* @param year: number 年份
|
||||||
|
* @param month: number 月份
|
||||||
|
* @param days: Array<CalendarDayData> 每天的打卡数据,null表示当天无记录
|
||||||
*/
|
*/
|
||||||
constructor(data,) {
|
constructor(year,month,days,) {
|
||||||
this.data = data;
|
this.year = year;
|
||||||
|
this.month = month;
|
||||||
|
this.days = days;
|
||||||
|
|
||||||
}
|
}
|
||||||
static fromObject(o) {
|
static fromObject(o) {
|
||||||
return new GetCalendarResp(o.data,);
|
return new GetCalendarResp(o.year,o.month,o.days,);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "HaveADrink",
|
"name": "HaveADrink",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "v1.0.2",
|
"version": "v1.0.3",
|
||||||
"description": "喝酒了么 API 服务",
|
"description": "喝酒了么 API 服务",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Generated
+4
-4
@@ -5,13 +5,13 @@
|
|||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"HaveADrink": "^1.0.2"
|
"HaveADrink": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/HaveADrink": {
|
"node_modules/HaveADrink": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://npm.wash-painting.cn/HaveADrink/-/HaveADrink-1.0.2.tgz",
|
"resolved": "https://npm.wash-painting.cn/HaveADrink/-/HaveADrink-1.0.3.tgz",
|
||||||
"integrity": "sha512-rhcILwsr6F1SBK7z+C4HMemUHHd63pl5ggxHisky0ZDgCOL7bITf3TGgvoiqXRoAGe4qmV+4FT8E6oCbvD1PIg==",
|
"integrity": "sha512-Mp4WRwqFmrf9CQhlF+gdJQ4YGRZkrBSbcu1l+XF4nq5dZmrFW7iggzFH4XSIXewBME1svk+cMhN6vetZVVOA6Q==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"HaveADrink": "^1.0.2"
|
"HaveADrink": "^1.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+45
-4
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view :class="themeClass" class="page-container card-page">
|
<view :class="themeClass" class="page-container card-page">
|
||||||
<view class="card-nav">
|
<view class="card-nav" :style="{ paddingTop: (statusBarHeight + 12) + 'px' }">
|
||||||
<view class="step-back" @click="goBack">
|
<view class="step-back" @click="goBack">
|
||||||
<text class="step-back-arrow">‹</text>
|
<text class="step-back-arrow">‹</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -21,6 +21,9 @@
|
|||||||
<button class="btn-secondary share-btn" @click="shareToFriend">
|
<button class="btn-secondary share-btn" @click="shareToFriend">
|
||||||
<text>分享给好友</text>
|
<text>分享给好友</text>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="btn-text close-home-btn" @click="closeToHome">
|
||||||
|
<text>返回首页</text>
|
||||||
|
</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<canvas canvas-id="shareCanvas" class="export-canvas" :style="{width:'750px',height:'1600px'}"></canvas>
|
<canvas canvas-id="shareCanvas" class="export-canvas" :style="{width:'750px',height:'1600px'}"></canvas>
|
||||||
@@ -41,7 +44,9 @@ export default {
|
|||||||
mixins: [themeMixin],
|
mixins: [themeMixin],
|
||||||
components: { DrinkCard },
|
components: { DrinkCard },
|
||||||
data() {
|
data() {
|
||||||
|
const sysInfo = uni.getSystemInfoSync()
|
||||||
return {
|
return {
|
||||||
|
statusBarHeight: sysInfo.statusBarHeight || 25,
|
||||||
record: null,
|
record: null,
|
||||||
saving: false,
|
saving: false,
|
||||||
saved: false
|
saved: false
|
||||||
@@ -410,8 +415,9 @@ export default {
|
|||||||
shareToFriend() { uni.showToast({ title: '点击右上角分享', icon: 'none' }) },
|
shareToFriend() { uni.showToast({ title: '点击右上角分享', icon: 'none' }) },
|
||||||
|
|
||||||
goBack() {
|
goBack() {
|
||||||
|
console.log('goBack called, saved:', this.saved)
|
||||||
if (this.saved) {
|
if (this.saved) {
|
||||||
uni.navigateBack()
|
this._doBack()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
@@ -420,12 +426,34 @@ export default {
|
|||||||
confirmText: '保存并离开',
|
confirmText: '保存并离开',
|
||||||
cancelText: '直接离开',
|
cancelText: '直接离开',
|
||||||
success: async (res) => {
|
success: async (res) => {
|
||||||
|
console.log('modal result:', res)
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
await this.saveToAlbum()
|
try { await this.saveToAlbum() } catch (e) { /* ignore */ }
|
||||||
}
|
}
|
||||||
uni.navigateBack()
|
this._doBack()
|
||||||
|
},
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('showModal fail:', err)
|
||||||
|
this._doBack()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
closeToHome() {
|
||||||
|
uni.switchTab({ url: '/pages/index/index' })
|
||||||
|
},
|
||||||
|
_doBack() {
|
||||||
|
console.log('_doBack called, pages:', getCurrentPages().length)
|
||||||
|
if (getCurrentPages().length > 1) {
|
||||||
|
uni.navigateBack({
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('navigateBack fail:', err)
|
||||||
|
uni.reLaunch({ url: '/pages/index/index' })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
console.log('no pages to go back to, reLaunch to index')
|
||||||
|
uni.reLaunch({ url: '/pages/index/index' })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShareAppMessage() {
|
onShareAppMessage() {
|
||||||
@@ -452,6 +480,7 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: $sp-md;
|
gap: $sp-md;
|
||||||
padding: $sp-md $sp-lg;
|
padding: $sp-md $sp-lg;
|
||||||
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-back {
|
.step-back {
|
||||||
@@ -462,6 +491,7 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
background: $bg-card;
|
background: $bg-card;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-back-arrow {
|
.step-back-arrow {
|
||||||
@@ -524,6 +554,17 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.close-home-btn {
|
||||||
|
width: 100%;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
color: $text-tertiary;
|
||||||
|
font-size: $fs-sm;
|
||||||
|
padding: $sp-sm 0;
|
||||||
|
|
||||||
|
&::after { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
.export-canvas {
|
.export-canvas {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: -9999px;
|
left: -9999px;
|
||||||
|
|||||||
+43
-32
@@ -91,7 +91,7 @@
|
|||||||
<view v-if="selectedRecord.mode === 'drank'" class="day-record-info">
|
<view v-if="selectedRecord.mode === 'drank'" class="day-record-info">
|
||||||
<view class="day-drinks">
|
<view class="day-drinks">
|
||||||
<view v-for="(drink, i) in selectedRecord.drinks" :key="i" class="day-drink-item">
|
<view v-for="(drink, i) in selectedRecord.drinks" :key="i" class="day-drink-item">
|
||||||
<text>{{ drink.emoji || '🥃' }} {{ drink.brand }} {{ drink.product }}</text>
|
<text>{{ getCatEmoji(drink.category) }} {{ drink.brand }} {{ drink.product }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="day-meta flex-between">
|
<view class="day-meta flex-between">
|
||||||
@@ -118,8 +118,9 @@
|
|||||||
<script>
|
<script>
|
||||||
import DrinkCalendar from '../../components/DrinkCalendar.vue'
|
import DrinkCalendar from '../../components/DrinkCalendar.vue'
|
||||||
import client from '../../common/api'
|
import client from '../../common/api'
|
||||||
|
import { GetCalendarReq } from 'HaveADrink'
|
||||||
import { getGreeting, formatDate, getWeekStart } from '../../common/utils'
|
import { getGreeting, formatDate, getWeekStart } from '../../common/utils'
|
||||||
import { FEELINGS } from '../../common/constants'
|
import { FEELINGS, DRINK_CATEGORIES } from '../../common/constants'
|
||||||
import themeMixin from '../../common/theme-mixin'
|
import themeMixin from '../../common/theme-mixin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -156,8 +157,7 @@ export default {
|
|||||||
onShow() {
|
onShow() {
|
||||||
// 首次启动跳转引导页
|
// 首次启动跳转引导页
|
||||||
const isFirst = uni.getStorageSync('is_first_launch')
|
const isFirst = uni.getStorageSync('is_first_launch')
|
||||||
const isLoggedIn = uni.getStorageSync('is_logged_in')
|
if (isFirst === 'true') {
|
||||||
if (isFirst === 'true' || !isLoggedIn) {
|
|
||||||
uni.reLaunch({ url: '/pages/onboarding/onboarding' })
|
uni.reLaunch({ url: '/pages/onboarding/onboarding' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ export default {
|
|||||||
const [userResp, statsResp, recordsResp] = await Promise.allSettled([
|
const [userResp, statsResp, recordsResp] = await Promise.allSettled([
|
||||||
client.GetUserProfile({}),
|
client.GetUserProfile({}),
|
||||||
client.GetStatsOverview({}),
|
client.GetStatsOverview({}),
|
||||||
client.GetRecords({ page: 1, pageSize: 100 })
|
client.GetCalendar(new GetCalendarReq(this.calendarYear, this.calendarMonth))
|
||||||
])
|
])
|
||||||
|
|
||||||
// 用户信息
|
// 用户信息
|
||||||
@@ -207,20 +207,24 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 记录列表
|
// 日历数据
|
||||||
if (recordsResp.status === 'fulfilled' && recordsResp.value) {
|
if (recordsResp.status === 'fulfilled' && recordsResp.value) {
|
||||||
const list = recordsResp.value.list || recordsResp.value
|
const calData = recordsResp.value.data || recordsResp.value
|
||||||
this.records = Array.isArray(list) ? list.map(r => ({
|
const days = calData.days || []
|
||||||
...r,
|
this.records = days.filter(d => d && d.hasRecord).map(d => ({
|
||||||
mode: String(r.mode),
|
id: d.id || '',
|
||||||
feeling: r.feeling ? String(r.feeling) : null,
|
date: d.date,
|
||||||
visibility: r.visibility ? String(r.visibility) : 'private',
|
mode: String(d.mode),
|
||||||
drinks: (r.drinks || []).map(d => ({
|
standardCupsTotal: d.standardCupsTotal || 0,
|
||||||
...d,
|
drinks: (d.drinks || []).map(dr => ({
|
||||||
category: String(d.category),
|
...dr,
|
||||||
unit: String(d.unit)
|
category: String(dr.category)
|
||||||
}))
|
})),
|
||||||
})) : []
|
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) {
|
} catch (e) {
|
||||||
console.warn('加载首页数据失败:', e)
|
console.warn('加载首页数据失败:', e)
|
||||||
@@ -241,20 +245,23 @@ export default {
|
|||||||
},
|
},
|
||||||
async loadRecordsForMonth(year, month) {
|
async loadRecordsForMonth(year, month) {
|
||||||
try {
|
try {
|
||||||
const monthStr = `${year}-${String(month).padStart(2, '0')}`
|
const resp = await client.GetCalendar(new GetCalendarReq(year, month))
|
||||||
const resp = await client.GetRecords({ page: 1, pageSize: 100, month: monthStr })
|
const calData = resp.data || resp
|
||||||
const list = resp.list || resp
|
const days = calData.days || []
|
||||||
this.records = Array.isArray(list) ? list.map(r => ({
|
this.records = days.filter(d => d && d.hasRecord).map(d => ({
|
||||||
...r,
|
id: d.id || '',
|
||||||
mode: String(r.mode),
|
date: d.date,
|
||||||
feeling: r.feeling ? String(r.feeling) : null,
|
mode: String(d.mode),
|
||||||
visibility: r.visibility ? String(r.visibility) : 'private',
|
standardCupsTotal: d.standardCupsTotal || 0,
|
||||||
drinks: (r.drinks || []).map(d => ({
|
drinks: (d.drinks || []).map(dr => ({
|
||||||
...d,
|
...dr,
|
||||||
category: String(d.category),
|
category: String(dr.category)
|
||||||
unit: String(d.unit)
|
})),
|
||||||
}))
|
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) {
|
} catch (e) {
|
||||||
console.warn('加载月度记录失败:', e)
|
console.warn('加载月度记录失败:', e)
|
||||||
}
|
}
|
||||||
@@ -268,6 +275,10 @@ export default {
|
|||||||
const f = FEELINGS.find(f => f.id === feelingId)
|
const f = FEELINGS.find(f => f.id === feelingId)
|
||||||
return f ? `${f.emoji} ${f.name}` : ''
|
return f ? `${f.emoji} ${f.name}` : ''
|
||||||
},
|
},
|
||||||
|
getCatEmoji(catId) {
|
||||||
|
const cat = DRINK_CATEGORIES.find(c => c.id === catId)
|
||||||
|
return cat ? cat.emoji : '🥃'
|
||||||
|
},
|
||||||
backfillDate() {
|
backfillDate() {
|
||||||
this.showDayDetail = false
|
this.showDayDetail = false
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
|
|||||||
@@ -65,16 +65,6 @@
|
|||||||
<text class="login-btn-text">{{ loginLoading ? '登录中...' : '完成并进入' }}</text>
|
<text class="login-btn-text">{{ loginLoading ? '登录中...' : '完成并进入' }}</text>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<view class="login-divider">
|
|
||||||
<view class="login-divider-line"></view>
|
|
||||||
<text class="login-divider-text">或</text>
|
|
||||||
<view class="login-divider-line"></view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<button class="btn-secondary" :disabled="loginLoading" @click="handleGuest">
|
|
||||||
先看看再说
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- 协议勾选 -->
|
<!-- 协议勾选 -->
|
||||||
<view class="agreement-check" @click="agreed = !agreed">
|
<view class="agreement-check" @click="agreed = !agreed">
|
||||||
<view class="check-box" :class="{ 'check-box-active': agreed }">
|
<view class="check-box" :class="{ 'check-box-active': agreed }">
|
||||||
@@ -196,25 +186,6 @@ export default {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// ===== 游客模式 =====
|
|
||||||
handleGuest() {
|
|
||||||
if (this.loginLoading) return
|
|
||||||
uni.setStorageSync('is_logged_in', 'true')
|
|
||||||
uni.setStorageSync('is_guest', 'true')
|
|
||||||
uni.setStorageSync('is_first_launch', 'false')
|
|
||||||
// 游客也设置一个基础用户信息
|
|
||||||
const guestInfo = {
|
|
||||||
id: `guest_${Date.now()}`,
|
|
||||||
nickname: '游客模式',
|
|
||||||
avatar: '',
|
|
||||||
isGuest: true,
|
|
||||||
joinedAt: new Date().toISOString().slice(0, 10),
|
|
||||||
preferences: null
|
|
||||||
}
|
|
||||||
uni.setStorageSync('user_info', JSON.stringify(guestInfo))
|
|
||||||
uni.switchTab({ url: '/pages/index/index' })
|
|
||||||
},
|
|
||||||
|
|
||||||
finishLogin() {
|
finishLogin() {
|
||||||
uni.setStorageSync('is_logged_in', 'true')
|
uni.setStorageSync('is_logged_in', 'true')
|
||||||
uni.setStorageSync('is_first_launch', 'false')
|
uni.setStorageSync('is_first_launch', 'false')
|
||||||
@@ -441,23 +412,6 @@ export default {
|
|||||||
font-weight: $fw-bold;
|
font-weight: $fw-bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.login-divider {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: $sp-md;
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-divider-line {
|
|
||||||
flex: 1;
|
|
||||||
height: 2rpx;
|
|
||||||
background: var(--bg-hover, rgba(255, 255, 255, 0.08));
|
|
||||||
}
|
|
||||||
|
|
||||||
.login-divider-text {
|
|
||||||
font-size: $fs-sm;
|
|
||||||
color: $text-tertiary;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 协议勾选 */
|
/* 协议勾选 */
|
||||||
.agreement-check {
|
.agreement-check {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -108,7 +108,8 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
goLogin() {
|
goLogin() {
|
||||||
uni.reLaunch({ url: '/pages/login/login' })
|
uni.setStorageSync('is_first_launch', 'false')
|
||||||
|
uni.reLaunch({ url: '/pages/index/index' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+243
-331
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view :class="themeClass" class="page-container record-page safe-bottom">
|
<view :class="themeClass" class="page-container record-page safe-bottom">
|
||||||
<!-- 顶部进度 -->
|
<!-- 顶部进度 -->
|
||||||
<view class="step-header">
|
<view class="step-header" :style="{ paddingTop: (statusBarHeight + 12) + 'px' }">
|
||||||
<view class="step-back" @click="handleBack">
|
<view class="step-back" @click="handleBack">
|
||||||
<text class="step-back-arrow">‹</text>
|
<text class="step-back-arrow">‹</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -25,8 +25,8 @@
|
|||||||
<text class="step-subtitle">{{ stepSubtitles[currentStep - 1] }}</text>
|
<text class="step-subtitle">{{ stepSubtitles[currentStep - 1] }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Step 1: 选酒 -->
|
<!-- Step 1: 添加酒水(选酒+记量合一) -->
|
||||||
<view v-if="currentStep === 1" class="step-content">
|
<scroll-view v-if="currentStep === 1" class="step-content" scroll-y enhanced :show-scrollbar="false">
|
||||||
<!-- 酒类选择网格 -->
|
<!-- 酒类选择网格 -->
|
||||||
<view class="category-grid">
|
<view class="category-grid">
|
||||||
<view
|
<view
|
||||||
@@ -41,8 +41,9 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 品牌选择 -->
|
<!-- 品牌 + 用量(选酒后展示) -->
|
||||||
<view v-if="currentDrink.category" class="brand-section">
|
<view v-if="currentDrink.category" class="drink-form card">
|
||||||
|
<!-- 品牌选择 -->
|
||||||
<text class="section-label">品牌</text>
|
<text class="section-label">品牌</text>
|
||||||
<view class="brand-tags">
|
<view class="brand-tags">
|
||||||
<view
|
<view
|
||||||
@@ -65,7 +66,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 产品名称 -->
|
<!-- 产品名称 -->
|
||||||
<text class="section-label" style="margin-top: 24rpx;">产品名称</text>
|
<text class="section-label" style="margin-top: 16rpx;">产品名称</text>
|
||||||
<view class="input-row">
|
<view class="input-row">
|
||||||
<input
|
<input
|
||||||
class="input-field"
|
class="input-field"
|
||||||
@@ -74,22 +75,31 @@
|
|||||||
placeholder-class="input-placeholder"
|
placeholder-class="input-placeholder"
|
||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- Step 2: 记量 -->
|
<view class="divider"></view>
|
||||||
<view v-if="currentStep === 2" class="step-content">
|
|
||||||
<view class="amount-section card">
|
<!-- 用量 + 度数 一行 -->
|
||||||
<view class="amount-row">
|
<view class="amount-degree-row">
|
||||||
<input
|
<view class="amount-inline">
|
||||||
class="amount-input text-num"
|
<input
|
||||||
type="digit"
|
class="amount-input text-num"
|
||||||
v-model="amountStr"
|
type="digit"
|
||||||
placeholder="0"
|
v-model="amountStr"
|
||||||
placeholder-class="input-placeholder"
|
placeholder="0"
|
||||||
@input="onAmountChange"
|
placeholder-class="input-placeholder"
|
||||||
/>
|
@input="onAmountChange"
|
||||||
<text class="amount-unit">{{ currentDrink.unit === 'ml' ? 'ml' : currentDrink.unit }}</text>
|
/>
|
||||||
|
<text class="amount-unit">{{ currentDrink.unit === 'ml' ? 'ml' : currentDrink.unit }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="degree-inline">
|
||||||
|
<input
|
||||||
|
class="degree-input text-num"
|
||||||
|
type="digit"
|
||||||
|
v-model="degreeStr"
|
||||||
|
@input="onAmountChange"
|
||||||
|
/>
|
||||||
|
<text class="degree-symbol">°</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 单位切换 -->
|
<!-- 单位切换 -->
|
||||||
@@ -105,60 +115,53 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 酒精度数 -->
|
|
||||||
<view class="degree-row">
|
|
||||||
<text class="section-label">酒精度数</text>
|
|
||||||
<view class="degree-input-wrap">
|
|
||||||
<input
|
|
||||||
class="degree-input text-num"
|
|
||||||
type="digit"
|
|
||||||
v-model="degreeStr"
|
|
||||||
@input="onAmountChange"
|
|
||||||
/>
|
|
||||||
<text class="degree-symbol">°</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view class="divider"></view>
|
|
||||||
|
|
||||||
<!-- 标准杯显示 -->
|
<!-- 标准杯显示 -->
|
||||||
<view class="standard-cup-result">
|
<view class="cup-row">
|
||||||
<view class="standard-cup-label-row">
|
<text class="cup-label">≈</text>
|
||||||
<text class="standard-cup-label">本次饮酒量</text>
|
<text class="cup-value text-num text-amber">{{ currentCups }} 标准杯</text>
|
||||||
<view class="cup-info-btn" @click="showCupInfo = true">
|
<view class="cup-info-btn" @click="showCupInfo = true">
|
||||||
<text class="cup-info-icon">?</text>
|
<text class="cup-info-icon">?</text>
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
<text class="standard-cup-value text-num text-amber">{{ currentCups }} 标准杯</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 已添加的酒水列表 -->
|
<!-- 已添加的酒水列表 -->
|
||||||
<view v-if="drinks.length > 0" class="added-drinks">
|
<view v-if="drinks.length > 0" class="added-drinks">
|
||||||
<text class="section-label">已添加的酒水</text>
|
<view class="added-drinks-header">
|
||||||
|
<text class="section-label">已添加的酒水</text>
|
||||||
|
<text class="added-count">{{ drinks.length }}种</text>
|
||||||
|
</view>
|
||||||
<view v-for="(d, i) in drinks" :key="i" class="added-drink-item card">
|
<view v-for="(d, i) in drinks" :key="i" class="added-drink-item card">
|
||||||
<view class="flex-between">
|
<view class="flex-between">
|
||||||
<text>{{ getCatEmoji(d.category) }} {{ d.brand }} {{ d.product }}</text>
|
<text>{{ getCatEmoji(d.category) }} {{ d.brand }} {{ d.product }} · {{ d.amount }}{{ d.unit }}</text>
|
||||||
<text class="text-amber text-num">{{ d.standardCups }}杯</text>
|
<view class="added-drink-right">
|
||||||
|
<text class="text-amber text-num">{{ d.standardCups }}杯</text>
|
||||||
|
<view class="added-drink-remove" @click="removeDrink(i)">
|
||||||
|
<text class="remove-icon">✕</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 累计标准杯 -->
|
||||||
|
<view class="total-cups-bar">
|
||||||
|
<text class="text-caption">本次累计</text>
|
||||||
|
<text class="total-cups-value text-num text-amber">{{ totalCups }} 标准杯</text>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 累计标准杯 -->
|
|
||||||
<view class="total-cups-bar">
|
|
||||||
<text class="text-caption">本次累计</text>
|
|
||||||
<text class="total-cups-value text-num text-amber">{{ totalCups }} 标准杯</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 健康提醒 -->
|
<!-- 健康提醒 -->
|
||||||
<view v-if="totalCups > 3" class="health-warning card">
|
<view v-if="drinks.length > 0 && totalCups > 3" class="health-warning card">
|
||||||
<text class="health-warning-icon">⚠️</text>
|
<text class="health-warning-icon">⚠️</text>
|
||||||
<text class="health-warning-text">今日已饮用 {{ totalCups }} 标准杯,建议每日不超过2标准杯</text>
|
<text class="health-warning-text">今日已饮用 {{ totalCups }} 标准杯,建议每日不超过2标准杯</text>
|
||||||
</view>
|
</view>
|
||||||
<view v-else class="health-hint">
|
<view v-else-if="drinks.length > 0" class="health-hint">
|
||||||
<text class="text-tiny">建议每日不超过2标准杯(《中国居民膳食指南》)</text>
|
<text class="text-tiny">💡 可继续添加更多酒水,或点击下一步</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
|
<!-- 底部占位 -->
|
||||||
|
<view style="height: 180rpx;"></view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
<!-- 标准杯说明弹窗 -->
|
<!-- 标准杯说明弹窗 -->
|
||||||
<view v-if="showCupInfo" class="cup-info-overlay" @click="showCupInfo = false">
|
<view v-if="showCupInfo" class="cup-info-overlay" @click="showCupInfo = false">
|
||||||
@@ -198,8 +201,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Step 3: 配餐 -->
|
<!-- Step 2: 配餐 -->
|
||||||
<view v-if="currentStep === 3" class="step-content">
|
<view v-if="currentStep === 2" class="step-content">
|
||||||
<view class="food-grid">
|
<view class="food-grid">
|
||||||
<view
|
<view
|
||||||
v-for="food in foodCategories"
|
v-for="food in foodCategories"
|
||||||
@@ -224,8 +227,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Step 4: 感受 -->
|
<!-- Step 3: 感受 -->
|
||||||
<view v-if="currentStep === 4" class="step-content">
|
<view v-if="currentStep === 3" class="step-content">
|
||||||
<view class="feeling-grid">
|
<view class="feeling-grid">
|
||||||
<view
|
<view
|
||||||
v-for="f in feelings"
|
v-for="f in feelings"
|
||||||
@@ -244,8 +247,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Step 5: 照片 -->
|
<!-- Step 4: 照片 -->
|
||||||
<view v-if="currentStep === 5" class="step-content">
|
<view v-if="currentStep === 4" class="step-content">
|
||||||
<view class="photo-grid">
|
<view class="photo-grid">
|
||||||
<view
|
<view
|
||||||
v-for="(photo, index) in photos"
|
v-for="(photo, index) in photos"
|
||||||
@@ -267,39 +270,6 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- Step 6: 确认保存 -->
|
|
||||||
<view v-if="currentStep === 6" class="step-content">
|
|
||||||
<!-- 记录预览 -->
|
|
||||||
<view class="preview-section card">
|
|
||||||
<text class="section-label">记录预览</text>
|
|
||||||
<view class="preview-drinks">
|
|
||||||
<view v-for="(d, i) in allDrinks" :key="i" class="preview-item">
|
|
||||||
<text>{{ getCatEmoji(d.category) }} {{ d.brand }} {{ d.product }} · {{ d.amount }}{{ d.unit }}</text>
|
|
||||||
<text class="text-amber text-num">{{ d.standardCups }}杯</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="divider"></view>
|
|
||||||
<view class="preview-meta">
|
|
||||||
<text v-if="selectedFood !== 'none'" class="preview-line">🍲 {{ getFoodName() }}</text>
|
|
||||||
<text v-if="selectedFeeling" class="preview-line">{{ getFeelingEmoji() }} {{ getFeelingName() }}</text>
|
|
||||||
<text class="preview-line">📍 {{ backfillDate || '今天' }}</text>
|
|
||||||
</view>
|
|
||||||
<view class="preview-total">
|
|
||||||
<text class="text-caption">总计</text>
|
|
||||||
<text class="text-amber text-num" style="font-size: 34rpx;">{{ totalCups }} 标准杯</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 保存后提示 -->
|
|
||||||
<view class="save-hint card">
|
|
||||||
<text class="save-hint-icon">✨</text>
|
|
||||||
<view class="save-hint-text">
|
|
||||||
<text class="save-hint-title">保存后可生成酒局卡片</text>
|
|
||||||
<text class="save-hint-desc">卡片可保存到相册发朋友圈,或分享给好友</text>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 底部操作栏 -->
|
<!-- 底部操作栏 -->
|
||||||
<view class="bottom-actions">
|
<view class="bottom-actions">
|
||||||
<button
|
<button
|
||||||
@@ -309,6 +279,14 @@
|
|||||||
>上一步</button>
|
>上一步</button>
|
||||||
<view v-else class="btn-placeholder"></view>
|
<view v-else class="btn-placeholder"></view>
|
||||||
|
|
||||||
|
<!-- Step 1 显示“+ 添加”按钮 -->
|
||||||
|
<button
|
||||||
|
v-if="currentStep === 1"
|
||||||
|
class="btn-add-drink"
|
||||||
|
:disabled="!canAddDrink"
|
||||||
|
@click="addDrinkToList"
|
||||||
|
>+ 添加</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
v-if="currentStep < totalSteps"
|
v-if="currentStep < totalSteps"
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
@@ -322,11 +300,6 @@
|
|||||||
style="flex: none; width: 55%;"
|
style="flex: none; width: 55%;"
|
||||||
>保存并生成卡片</button>
|
>保存并生成卡片</button>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 添加更多酒水按钮(Step 1) -->
|
|
||||||
<view v-if="currentStep === 1 && drinks.length > 0" class="add-more-bar">
|
|
||||||
<button class="btn-ghost" @click="resetCurrentDrink">+ 再添加一种酒</button>
|
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -343,11 +316,13 @@ import themeMixin from '../../common/theme-mixin'
|
|||||||
export default {
|
export default {
|
||||||
mixins: [themeMixin],
|
mixins: [themeMixin],
|
||||||
data() {
|
data() {
|
||||||
|
const sysInfo = uni.getSystemInfoSync()
|
||||||
return {
|
return {
|
||||||
|
statusBarHeight: sysInfo.statusBarHeight || 25,
|
||||||
currentStep: 1,
|
currentStep: 1,
|
||||||
totalSteps: 6,
|
totalSteps: 4,
|
||||||
stepTitles: ['选择酒水', '记录用量', '配餐', '感受', '照片', '确认保存'],
|
stepTitles: ['添加酒水', '配餐', '感受', '照片'],
|
||||||
stepSubtitles: ['喝了什么酒?', '喝了多少?', '配了什么菜?', '感觉如何?', '拍张照片吧', '保存后可生成分享卡片'],
|
stepSubtitles: ['喝了什么酒?喝了多少?', '配了什么菜?', '感觉如何?', '拍张照片吧'],
|
||||||
|
|
||||||
drinkCategories: DRINK_CATEGORIES,
|
drinkCategories: DRINK_CATEGORIES,
|
||||||
units: DRINK_UNITS,
|
units: DRINK_UNITS,
|
||||||
@@ -359,22 +334,20 @@ export default {
|
|||||||
currentDrink: { category: '', brand: '', product: '', amount: 0, unit: 'ml', degree: 0 },
|
currentDrink: { category: '', brand: '', product: '', amount: 0, unit: 'ml', degree: 0 },
|
||||||
drinks: [],
|
drinks: [],
|
||||||
brandList: [],
|
brandList: [],
|
||||||
|
|
||||||
// Step 2
|
|
||||||
amountStr: '',
|
amountStr: '',
|
||||||
degreeStr: '',
|
degreeStr: '',
|
||||||
|
|
||||||
// Step 3
|
// Step 2
|
||||||
selectedFood: '',
|
selectedFood: '',
|
||||||
foodName: '',
|
foodName: '',
|
||||||
|
|
||||||
// Step 4
|
// Step 3
|
||||||
selectedFeeling: '',
|
selectedFeeling: '',
|
||||||
|
|
||||||
// Step 5
|
// Step 4
|
||||||
photos: [],
|
photos: [],
|
||||||
|
|
||||||
// Step 6
|
// Step 5
|
||||||
visibility: 'friends',
|
visibility: 'friends',
|
||||||
|
|
||||||
// 补打卡日期
|
// 补打卡日期
|
||||||
@@ -390,30 +363,17 @@ export default {
|
|||||||
return calcStandardCups(ml, parseFloat(this.degreeStr) || 0)
|
return calcStandardCups(ml, parseFloat(this.degreeStr) || 0)
|
||||||
},
|
},
|
||||||
totalCups() {
|
totalCups() {
|
||||||
const addedCups = this.drinks.reduce((sum, d) => sum + d.standardCups, 0)
|
return this.drinks.reduce((sum, d) => sum + d.standardCups, 0)
|
||||||
return Math.round((addedCups + this.currentCups) * 100) / 100
|
|
||||||
},
|
},
|
||||||
allDrinks() {
|
canAddDrink() {
|
||||||
const all = [...this.drinks]
|
return this.currentDrink.category && this.currentDrink.brand && parseFloat(this.amountStr) > 0
|
||||||
if (this.amountStr && this.currentDrink.category) {
|
|
||||||
const ml = unitToMl(parseFloat(this.amountStr) || 0, this.currentDrink.unit)
|
|
||||||
all.push({
|
|
||||||
...this.currentDrink,
|
|
||||||
amount: parseFloat(this.amountStr) || 0,
|
|
||||||
degree: parseFloat(this.degreeStr) || 0,
|
|
||||||
standardCups: calcStandardCups(ml, parseFloat(this.degreeStr) || 0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return all
|
|
||||||
},
|
},
|
||||||
canProceed() {
|
canProceed() {
|
||||||
switch (this.currentStep) {
|
switch (this.currentStep) {
|
||||||
case 1: return this.currentDrink.category && this.currentDrink.brand
|
case 1: return this.drinks.length > 0
|
||||||
case 2: return parseFloat(this.amountStr) > 0
|
case 2: return true // 配餐可选
|
||||||
case 3: return true // 配餐可选
|
case 3: return true // 感受可选
|
||||||
case 4: return true // 感受可选
|
case 4: return true // 照片可选
|
||||||
case 5: return true // 照片可选
|
|
||||||
case 6: return true
|
|
||||||
default: return true
|
default: return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -486,20 +446,8 @@ export default {
|
|||||||
removePhoto(index) {
|
removePhoto(index) {
|
||||||
this.photos.splice(index, 1)
|
this.photos.splice(index, 1)
|
||||||
},
|
},
|
||||||
resetCurrentDrink() {
|
removeDrink(index) {
|
||||||
// 保存当前酒水到列表
|
this.drinks.splice(index, 1)
|
||||||
if (this.amountStr && this.currentDrink.category) {
|
|
||||||
const ml = unitToMl(parseFloat(this.amountStr) || 0, this.currentDrink.unit)
|
|
||||||
this.drinks.push({
|
|
||||||
...this.currentDrink,
|
|
||||||
amount: parseFloat(this.amountStr) || 0,
|
|
||||||
degree: parseFloat(this.degreeStr) || 0,
|
|
||||||
standardCups: calcStandardCups(ml, parseFloat(this.degreeStr) || 0)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.currentDrink = { category: '', brand: '', product: '', amount: 0, unit: 'ml', degree: 0 }
|
|
||||||
this.amountStr = ''
|
|
||||||
this.degreeStr = ''
|
|
||||||
},
|
},
|
||||||
handleBack() {
|
handleBack() {
|
||||||
if (this.currentStep > 1) {
|
if (this.currentStep > 1) {
|
||||||
@@ -532,31 +480,28 @@ export default {
|
|||||||
if (this.currentStep > 1) this.currentStep--
|
if (this.currentStep > 1) this.currentStep--
|
||||||
},
|
},
|
||||||
nextStep() {
|
nextStep() {
|
||||||
// Step 1 -> 2: 保存酒水基础信息
|
|
||||||
if (this.currentStep === 1) {
|
|
||||||
if (!this.degreeStr) this.degreeStr = String(this.currentDrink.degree)
|
|
||||||
}
|
|
||||||
// Step 2 -> 3: 保存饮用量
|
|
||||||
if (this.currentStep === 2) {
|
|
||||||
const ml = unitToMl(parseFloat(this.amountStr) || 0, this.currentDrink.unit)
|
|
||||||
this.drinks.push({
|
|
||||||
...this.currentDrink,
|
|
||||||
amount: parseFloat(this.amountStr) || 0,
|
|
||||||
degree: parseFloat(this.degreeStr) || 0,
|
|
||||||
standardCups: calcStandardCups(ml, parseFloat(this.degreeStr) || 0)
|
|
||||||
})
|
|
||||||
// 重置当前输入
|
|
||||||
this.currentDrink = { ...this.currentDrink, amount: 0 }
|
|
||||||
this.amountStr = ''
|
|
||||||
}
|
|
||||||
if (this.currentStep < this.totalSteps) this.currentStep++
|
if (this.currentStep < this.totalSteps) this.currentStep++
|
||||||
},
|
},
|
||||||
|
addDrinkToList() {
|
||||||
|
if (!this.canAddDrink) return
|
||||||
|
const ml = unitToMl(parseFloat(this.amountStr) || 0, this.currentDrink.unit)
|
||||||
|
this.drinks.push({
|
||||||
|
...this.currentDrink,
|
||||||
|
amount: parseFloat(this.amountStr) || 0,
|
||||||
|
degree: parseFloat(this.degreeStr) || 0,
|
||||||
|
standardCups: calcStandardCups(ml, parseFloat(this.degreeStr) || 0)
|
||||||
|
})
|
||||||
|
// 重置表单,准备添加下一种
|
||||||
|
this.currentDrink = { category: '', brand: '', product: '', amount: 0, unit: 'ml', degree: 0 }
|
||||||
|
this.amountStr = ''
|
||||||
|
this.degreeStr = ''
|
||||||
|
this.brandList = []
|
||||||
|
},
|
||||||
async publishRecord() {
|
async publishRecord() {
|
||||||
const allDrinks = this.allDrinks.length > 0 ? this.allDrinks : this.drinks
|
|
||||||
const recordData = {
|
const recordData = {
|
||||||
date: this.backfillDate || formatDate(new Date(), 'YYYY-MM-DD'),
|
date: this.backfillDate || formatDate(new Date(), 'YYYY-MM-DD'),
|
||||||
mode: 'drank',
|
mode: 'drank',
|
||||||
drinks: allDrinks.map(d => ({
|
drinks: this.drinks.map(d => ({
|
||||||
category: d.category,
|
category: d.category,
|
||||||
brand: d.brand,
|
brand: d.brand,
|
||||||
product: d.product || '',
|
product: d.product || '',
|
||||||
@@ -580,7 +525,7 @@ export default {
|
|||||||
uni.hideLoading()
|
uni.hideLoading()
|
||||||
|
|
||||||
// 跳转到卡片页,传递记录ID
|
// 跳转到卡片页,传递记录ID
|
||||||
uni.redirectTo({
|
uni.navigateTo({
|
||||||
url: `/pages/card/card?recordId=${saved.id}`
|
url: `/pages/card/card?recordId=${saved.id}`
|
||||||
})
|
})
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -589,7 +534,7 @@ export default {
|
|||||||
uni.showToast({ title: e.msg || '保存失败,已本地保存', icon: 'none', duration: 2000 })
|
uni.showToast({ title: e.msg || '保存失败,已本地保存', icon: 'none', duration: 2000 })
|
||||||
// 降级:本地保存
|
// 降级:本地保存
|
||||||
const saved = addRecord(recordData)
|
const saved = addRecord(recordData)
|
||||||
uni.redirectTo({
|
uni.navigateTo({
|
||||||
url: `/pages/card/card?recordId=${saved.id}`
|
url: `/pages/card/card?recordId=${saved.id}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -612,6 +557,7 @@ export default {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: $sp-md;
|
gap: $sp-md;
|
||||||
padding: $sp-md 0;
|
padding: $sp-md 0;
|
||||||
|
padding-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-back {
|
.step-back {
|
||||||
@@ -718,8 +664,10 @@ export default {
|
|||||||
color: $text-primary;
|
color: $text-primary;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-section {
|
/* Step 1: 添加酒水(合并选酒+记量) */
|
||||||
margin-top: $sp-lg;
|
.drink-form {
|
||||||
|
margin-bottom: $sp-lg;
|
||||||
|
padding: $sp-lg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-label {
|
.section-label {
|
||||||
@@ -734,7 +682,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: $sp-sm;
|
gap: $sp-sm;
|
||||||
margin-bottom: $sp-lg;
|
margin-bottom: $sp-md;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-row {
|
.input-row {
|
||||||
@@ -754,102 +702,6 @@ export default {
|
|||||||
color: $text-tertiary;
|
color: $text-tertiary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Step 2: 记量 */
|
|
||||||
.amount-section {
|
|
||||||
margin-bottom: $sp-lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.amount-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: $sp-sm;
|
|
||||||
margin-bottom: $sp-xl;
|
|
||||||
}
|
|
||||||
|
|
||||||
.amount-input {
|
|
||||||
font-size: $fs-3xl;
|
|
||||||
font-weight: $fw-black;
|
|
||||||
color: $text-primary;
|
|
||||||
flex: 1;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
height: 100rpx;
|
|
||||||
line-height: 100rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.amount-unit {
|
|
||||||
font-size: $fs-lg;
|
|
||||||
color: $text-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-switcher {
|
|
||||||
display: flex;
|
|
||||||
gap: $sp-sm;
|
|
||||||
margin-bottom: $sp-xl;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.unit-btn {
|
|
||||||
padding: $sp-sm $sp-lg;
|
|
||||||
background: $bg-elevated;
|
|
||||||
border-radius: $radius-full;
|
|
||||||
font-size: $fs-sm;
|
|
||||||
color: $text-secondary;
|
|
||||||
border: 2rpx solid transparent;
|
|
||||||
transition: all $duration-fast $ease-out;
|
|
||||||
|
|
||||||
&.unit-active {
|
|
||||||
background: $amber-glow;
|
|
||||||
color: $amber;
|
|
||||||
border-color: rgba(232,168,56,0.3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.degree-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.degree-input-wrap {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: $sp-xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
.degree-input {
|
|
||||||
width: 120rpx;
|
|
||||||
text-align: center;
|
|
||||||
background: $bg-elevated;
|
|
||||||
border-radius: $radius-md;
|
|
||||||
padding: $sp-sm;
|
|
||||||
color: $text-primary;
|
|
||||||
font-size: $fs-lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.degree-symbol {
|
|
||||||
font-size: $fs-lg;
|
|
||||||
color: $text-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.standard-cup-result {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.standard-cup-label {
|
|
||||||
font-size: $fs-base;
|
|
||||||
color: $text-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.standard-cup-label-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: $sp-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cup-info-btn {
|
.cup-info-btn {
|
||||||
width: 36rpx;
|
width: 36rpx;
|
||||||
height: 36rpx;
|
height: 36rpx;
|
||||||
@@ -866,10 +718,96 @@ export default {
|
|||||||
font-weight: $fw-bold;
|
font-weight: $fw-bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.standard-cup-value {
|
.amount-degree-row {
|
||||||
font-size: $fs-xl;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $sp-lg;
|
||||||
|
margin-bottom: $sp-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount-inline {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: $sp-sm;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.degree-inline {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $sp-xs;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cup-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $sp-xs;
|
||||||
|
padding: $sp-sm 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cup-label {
|
||||||
|
font-size: $fs-sm;
|
||||||
|
color: $text-tertiary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cup-value {
|
||||||
|
font-size: $fs-md;
|
||||||
font-weight: $fw-bold;
|
font-weight: $fw-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount-input {
|
||||||
|
font-size: $fs-3xl;
|
||||||
|
font-weight: $fw-black;
|
||||||
color: $text-primary;
|
color: $text-primary;
|
||||||
|
flex: 1;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
height: 80rpx;
|
||||||
|
line-height: 80rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.amount-unit {
|
||||||
|
font-size: $fs-md;
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-switcher {
|
||||||
|
display: flex;
|
||||||
|
gap: $sp-sm;
|
||||||
|
margin-bottom: $sp-md;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unit-btn {
|
||||||
|
padding: $sp-xs $sp-md;
|
||||||
|
background: $bg-elevated;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
font-size: $fs-xs;
|
||||||
|
color: $text-secondary;
|
||||||
|
border: 2rpx solid transparent;
|
||||||
|
transition: all $duration-fast $ease-out;
|
||||||
|
|
||||||
|
&.unit-active {
|
||||||
|
background: $amber-glow;
|
||||||
|
color: $amber;
|
||||||
|
border-color: rgba(232,168,56,0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.degree-input {
|
||||||
|
width: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
background: $bg-elevated;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
padding: $sp-sm;
|
||||||
|
color: $text-primary;
|
||||||
|
font-size: $fs-lg;
|
||||||
|
}
|
||||||
|
|
||||||
|
.degree-symbol {
|
||||||
|
font-size: $fs-lg;
|
||||||
|
color: $text-secondary;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 标准杯说明弹窗 */
|
/* 标准杯说明弹窗 */
|
||||||
@@ -1245,67 +1183,6 @@ export default {
|
|||||||
margin-top: $sp-xs;
|
margin-top: $sp-xs;
|
||||||
}
|
}
|
||||||
|
|
||||||
.preview-section {
|
|
||||||
margin-bottom: $sp-lg;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-item {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding: $sp-sm 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-meta {
|
|
||||||
margin-bottom: $sp-md;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-line {
|
|
||||||
display: block;
|
|
||||||
font-size: $fs-base;
|
|
||||||
padding: $sp-xs 0;
|
|
||||||
color: $text-secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-total {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: $sp-md;
|
|
||||||
border-top: 2rpx solid var(--border-faint, rgba(255, 255, 255, 0.08));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 保存提示卡片 */
|
|
||||||
.save-hint {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: $sp-md;
|
|
||||||
margin-top: $sp-lg;
|
|
||||||
padding: $sp-lg;
|
|
||||||
background: rgba(232, 168, 56, 0.06);
|
|
||||||
border: 2rpx solid rgba(232, 168, 56, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-hint-icon {
|
|
||||||
font-size: $fs-xl;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-hint-title {
|
|
||||||
display: block;
|
|
||||||
font-size: $fs-base;
|
|
||||||
font-weight: $fw-bold;
|
|
||||||
color: $text-primary;
|
|
||||||
margin-bottom: $sp-xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
.save-hint-desc {
|
|
||||||
display: block;
|
|
||||||
font-size: $fs-sm;
|
|
||||||
color: $text-secondary;
|
|
||||||
line-height: $lh-loose;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 底部操作栏 */
|
/* 底部操作栏 */
|
||||||
.bottom-actions {
|
.bottom-actions {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
@@ -1319,7 +1196,7 @@ export default {
|
|||||||
background: linear-gradient(to top, $bg-base 80%, transparent);
|
background: linear-gradient(to top, $bg-base 80%, transparent);
|
||||||
z-index: 50;
|
z-index: 50;
|
||||||
|
|
||||||
.btn-secondary, .btn-primary {
|
.btn-secondary, .btn-primary, .btn-add-drink {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1328,8 +1205,43 @@ export default {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-more-bar {
|
.added-drinks-header {
|
||||||
padding: $sp-lg 0;
|
display: flex;
|
||||||
text-align: center;
|
align-items: center;
|
||||||
|
gap: $sp-sm;
|
||||||
|
margin-bottom: $sp-md;
|
||||||
|
|
||||||
|
.section-label {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.added-count {
|
||||||
|
font-size: $fs-xs;
|
||||||
|
color: $amber;
|
||||||
|
background: $amber-glow;
|
||||||
|
padding: 2rpx $sp-sm;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.added-drink-right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $sp-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.added-drink-remove {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
background: var(--overlay-mask, rgba(255, 255, 255, 0.08));
|
||||||
|
}
|
||||||
|
|
||||||
|
.remove-icon {
|
||||||
|
font-size: $fs-xs;
|
||||||
|
color: $text-tertiary;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user