完善功能

This commit is contained in:
wangxiaowei
2025-10-25 17:33:08 +08:00
parent 87664ad114
commit 0abb527276
11 changed files with 354 additions and 174 deletions

View File

@ -1,5 +1,5 @@
import { http } from '@/http/alova'
import type { ITeaSpecialistDetailsResult, ITeaSpecialistFuture7DaysResult } from '@/api/types/tea'
import type { ITeaSpecialistDetailsResult, ITeaSpecialistFuture7DaysResult, ITeaTypeListResult } from '@/api/types/tea'
/**
* 获取茶艺师详情

View File

@ -56,4 +56,15 @@ export interface ITeaHouseListResult {
export interface ITeaSpecialistFuture7DaysResult {
minimum_time: number
time: Array<any>
}
/**
* 茶叶类型列表
*/
export interface ITeaTypeListResult {
id: number
name: string
status: number
tea_price: number
dtime: string
}

View File

@ -39,4 +39,12 @@ export interface IUserAddressListResult {
*/
export interface IUserAddressDetailsResult extends IUserAddressListResult {
address_details: IUserAddressListResult
}
/**
* 优惠券列表
*/
export interface IUserCouponListResult {
no_use: Array<any>
use: Array<any>
}

View File

@ -1,5 +1,5 @@
import { http } from '@/http/alova'
import type { IUserAddressListResult, IUserAddressDetailsResult } from '@/api/types/user'
import type { IUserAddressListResult, IUserAddressDetailsResult, IUserCouponListResult } from '@/api/types/user'
/**
@ -74,3 +74,15 @@ export interface IUserAddressDetailsParams extends IDeleteUserAddressParams {}
export function userAddressDetails(data: IUserAddressDetailsParams) {
return http.Post<IUserAddressDetailsResult>('/api/user/addressDetails', data)
}
/**
* 优惠券列表
*/
export interface IGetCouponsParams {
id: number
numbers: number
}
export function getCoupons(data: IGetCouponsParams) {
return http.Post<IUserCouponListResult>('/api/UserCoupon/UserCoupinList', data)
}

View File

@ -10,7 +10,7 @@
<template>
<view class="pb-180rpx">
<view>
<navbar :title="couponType == 1 ? '优惠券' : '团购券'" custom-class='!bg-[#F6F7F8]'></navbar>
<navbar :title="couponType == 1 ? '优惠券' : '团购券'" custom-class='!bg-[#F6F7F8]' :left-arrow="false"></navbar>
</view>
<view>
@ -20,19 +20,19 @@
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">可用优惠券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">2</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">{{ couponList.no_use.length }}</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<coupon
v-for="(item, index) in couponList"
v-for="(item, index) in couponList.use"
:key="item.id"
:coupon="item"
canUse
showChecked
:checked="item.id === checkedId"
:onCheck="coupons.handleCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
:onCheck="Coupons.handleCheck"
:class="index !== couponList.use.length - 1 ? 'mb-20rpx' : ''"
></coupon>
</wd-radio-group>
</view>
@ -40,73 +40,31 @@
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">不可用优惠券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">2</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">{{ couponList.no_use.length }}</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<coupon
v-for="(item, index) in unCouponList"
v-for="(item, index) in couponList.no_use"
:key="item.id"
:coupon="item"
:canUse="false"
showChecked
:checked="item.id === checkedId"
:onCheck="coupons.handleCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
:onCheck="Coupons.handleCheck"
:class="index !== couponList.no_use.length - 1 ? 'mb-20rpx' : ''"
></coupon>
</wd-radio-group>
</view>
</view>
</view>
<!-- 团购券 -->
<view v-if="couponType == 2">
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">可用团购券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">2</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<group-coupon
v-for="(item, index) in couponList"
:key="item.id"
:coupon="item"
canUse
:checked="item.id === checkedId"
:onCheck="coupons.handleCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
></group-coupon>
</wd-radio-group>
</view>
</view>
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">不可用团购券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">2</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<group-coupon
v-for="(item, index) in unCouponList"
:key="item.id"
:coupon="item"
:canUse="false"
:checked="item.id === checkedId"
:onCheck="coupons.handleCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
></group-coupon>
</wd-radio-group>
</view>
</view>
</view>
</view>
</view>
<view class="fixed left-0 right-0 bottom-0 z-2 bg-[#fff] flex justify-between items-center" :style="{ height: '140rpx'}">
<view class="ml-60rpx text-[#121212] text-24rpx leading-34rpx">已选择1</view>
<view class="ml-60rpx text-[#121212] text-24rpx leading-34rpx">已选择 {{ checkedId ? 1 : 0 }}</view>
<view class="mr-30rpx">
<wd-button custom-class='!bg-[#4C9F44] !rounded-8rpx !h-70rpx'>确定</wd-button>
<wd-button custom-class='!bg-[#4C9F44] !rounded-8rpx !h-70rpx' @click="Coupons.handleConfirmCoupon">确定</wd-button>
</view>
</view>
</view>
@ -116,31 +74,47 @@
import {ref} from 'vue'
import Coupon from '@/components/coupon/Coupon.vue'
import GroupCoupon from '@/components/coupon/GroupCoupon.vue'
import { getCoupons } from '@/api/user'
import type { IUserCouponListResult } from '@/api/types/user'
const couponType = ref<number>(2) // couponType 1:优惠券 2:团购券
const OSS = inject('OSS')
const couponList = ref([
{ id: 1, amount: 20, limit: 100, expire: '2024.08.20' },
{ id: 2, amount: 10, limit: 50, expire: '2024.08.25' }
])
const couponList = ref<IUserCouponListResult>({
no_use: [],
use: []
})
const checkedId = ref<number>(0)
const unCouponList = ref([
{ id: 1, amount: 20, limit: 100, expire: '2024.08.20' },
{ id: 2, amount: 10, limit: 50, expire: '2024.08.25' }
])
onLoad((args) => {
if (args.type) {
couponType.value = args.type
}
if (args.id && args.time) {
// 获取到茶艺师ID和预定了几个小时
Coupons.handleInit(args.id, args.time)
}
})
const coupons = {
handleCheck: (id: number) => {
const Coupons = {
// 初始化优惠券列表
handleInit: async (id: number, numbers: number) => {
const res = await getCoupons({id, numbers})
couponList.value = res
},
// 选择优惠券
handleCheck: (id: any) => {
checkedId.value = id
console.log("🚀 ~ checkedId.value :", checkedId.value )
},
// 确认选择优惠券
handleConfirmCoupon: () => {
const coupon = couponList.value.use.find(item => item.user_coupon_id === checkedId.value)
uni.$emit('chooseCoupon', { coupon })
uni.navigateBack()
}
}
</script>

View File

@ -1,20 +1,20 @@
<template>
<view class="mb-20rpx" @click="onCheck(coupon.id)">
<view class="mb-20rpx" @click="onCheck(coupon.user_coupon_id)">
<view class="coupon h-210rpx flex items-center">
<view class="w-260rpx h-[100%] rounded-l-16rpx rounded-tr-0 rounded-br-0 flex flex-col items-center justify-center" :class="canUse ? 'bg-[#4C9F44]' : 'bg-[#F2F2F2]'">
<view class="flex" :class="canUse ? 'text-[#fff]' : 'text-[#BFC2CC]'">
<view class="text-72rpx leading-100rpx">{{ coupon.amount }}</view>
<view class="text-52rpx leading-100rpx">{{ coupon.coupon_price }}</view>
<view class="text-32rpx leading-44rpx mt-40rpx ml-10rpx"></view>
</view>
<view class="text-26rpx font-400 leading-36rpx text-center" :class="canUse ? 'text-[#fff]' : 'text-[#BFC2CC]'">120元可用</view>
<view class="text-26rpx font-400 leading-36rpx text-center" :class="canUse ? 'text-[#fff]' : 'text-[#BFC2CC]'">{{ coupon.use_price }}元可用</view>
</view>
<view class="bg-[#fff] w-490rpx h-[100%] rounded-r-16rpx rounded-tl-0 rounded-bl-0 flex justify-between items-center">
<view class="ml-30rpx line-1">
<view class="text-34rpx leading-48rpx line-1" :class="canUse ? 'text-[#303133]' : 'text-[#909399]'">茶室优惠</view>
<view class="mt-40rpx text-[#909399] text-24rpx leading-34rpx" :class="canUse ? 'text-[#909399]' : 'text-[#BFC2CC]'">有效期至 2022-08-12</view>
<view class="text-34rpx leading-48rpx line-1" :class="canUse ? 'text-[#303133]' : 'text-[#909399]'">{{ coupon.title }}</view>
<view class="mt-40rpx text-[#909399] text-24rpx leading-34rpx" :class="canUse ? 'text-[#909399]' : 'text-[#BFC2CC]'">有效期至 {{ coupon.effect_time }}</view>
</view>
<view class="h-100% mr-70rpx mt-58rpx" v-if="showChecked">
<wd-radio :value="coupon.id" shape="dot" :disabled="!canUse"></wd-radio>
<wd-radio :value="coupon.user_coupon_id" shape="dot" :disabled="!canUse"></wd-radio>
</view>
</view>
</view>
@ -30,9 +30,11 @@
defineProps<{
coupon: {
id: number
amount: number
limit: number
expire: string
coupon_price: number
use_price: number
title: string
effect_time: string
user_coupon_id: number
}
canUse: boolean
showChecked: boolean

View File

@ -15,29 +15,59 @@
</view>
<view class="text-36rpx text-[#121212] leading-50rpx text-center">费用明细</view>
<view class="mx-30rpx bg-white rounded-16rpx px-30rpx pt-40rpx mt-40rpx pb-30rpx">
<view class="flex justify-between items-center text-30rpx text-[#303133] leading-42rpx">
<view>茶室费</view>
<view>¥640.00</view>
<!-- 服务费 -->
<view>
<view class="flex justify-between items-center text-30rpx text-[#303133] leading-42rpx">
<view>服务费</view>
<view>¥{{ bill.service.total }}</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>服务费(¥{{ bill.service.unitPrice }}元/小时)</view>
<view>x{{ bill.service.num }}</view>
</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>茶室费¥160元/小时)</view>
<view>x4</view>
<!-- 车马费 -->
<view>
<view class="flex justify-between items-center text-30rpx text-[#303133] leading-42rpx mt-52rpx">
<view>车马费</view>
<view>¥{{ bill.travel.total }}</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>车马费(¥{{ bill.travel.unitPrice }}元/小时)</view>
<view>{{ bill.travel.num }}公里</view>
</view>
</view>
<!-- 茶艺服务 -->
<view>
<view class="flex justify-between items-center text-30rpx text-[#303133] leading-42rpx mt-52rpx">
<view>茶艺服务</view>
<view>{{ bill.serviceFee }}</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>车马费¥160元/小时)</view>
<view>x4</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>车马费¥160元/小时)</view>
<view>x4</view>
</view>
</view>
<view class="mt-52rpx">
<view class="flex justify-between items-center text-30rpx text-[#303133] leading-42rpx">
<view>茶室费</view>
<view>优惠</view>
<view class="text-[#4C9F44]">-¥640.00</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>优惠券</view>
<view>-¥20</view>
</view>
<view class="flex justify-between items-center text-24rpx text-[#909399] leading-34rpx mt-16rpx">
<view>优惠券</view>
<view>-¥20</view>
</view>
</view>
<view class="my-30rpx">
@ -81,35 +111,6 @@
</view>
</wd-popup>
<!-- 选择门店 -->
<!-- <wd-popup v-model="showTeaHousePopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
<view class="relative">
<view class="absolute top-18rpx right-30rpx" @click="showTeaHousePopup = false">
<wd-img width="60rpx" height='60rpx' :src="`${OSS}icon/icon_close.png`"></wd-img>
</view>
<view class="text-36rpx text-[#121212] leading-50rpx text-center pt-50rpx pb-40rpx">选择门店</view>
<scroll-view scroll-y class="h-500rpx pb-20rpx">
<view class="mx-56rpx" v-for="(item, index) in 5" :key="index">
<view class="flex items-center justify-between mb-66rpx" @click="TeaRoom.handleChooseTeaHouse(item)">
<view class="mr-32rpx">
<wd-img width="80rpx" height='80rpx' :src="`${OSS}icon/icon_location3.png`"></wd-img>
</view>
<view class="flex-1">
<view>这是茶馆名字</view>
<view class="text-28rpx leading-40rpx text-[#909399] flex items-center mt-10rpx">
<view>距您5.3km</view>
<view>
<wd-divider vertical />
</view>
<view class="w-350rpx line-1">北京市海淀区宏福苑西区20号楼2单元30</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</wd-popup> -->
<!-- 茶艺服务 -->
<wd-popup v-model="showTeaServicePopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
<view class="relative">
@ -133,17 +134,18 @@
<!-- 预定茶叶 -->
<view class="mx-60rpx mb-50rpx">
<view class="text-32rpx leading-44rpx text-#303133">
<text class="mr-20rpx">服务人数</text>
<text class="mr-20rpx">预定茶叶</text>
<text class="text-26rpx leading-36rpx text-#909399">支持多选</text>
</view>
<view class="mt-28rpx">
<view class="grid grid-cols-3 gap-x-16rpx gap-y-16rpx">
<view class="text-28rpx leading-40rpx rounded-8rpx text-center py-14rpx"
:class="selectedTea.includes(item.id) ? 'bg-#4C9F44 text-#fff' : 'bg-#F7F7F7 text-#606266'"
<view
v-for="(item, index) in teaList" :key="index"
@click="TeaRoom.handleToggleTea(item.id)">
class="text-28rpx leading-40rpx rounded-8rpx text-center py-14rpx"
:class="selectedTea.includes(item.id) ? 'bg-#4C9F44 text-#fff' : 'bg-#F7F7F7 text-#606266'"
@click="TeaRoom.handleToggleTea(item.id, item.name, item.tea_price)">
<view>{{item.name}}</view>
<view>¥{{item.price}}</view>
<view>¥{{item.tea_price}}</view>
</view>
</view>
</view>
@ -156,7 +158,7 @@
<view class="flex items-center justify-between w-full">
<view class="text-28rpx leading-40rpx text-#303133">茶具需求</view>
<view>
<wd-radio-group v-model="teaUsageValue" shape="dot" checked-color="#4C9F44" inline>
<wd-radio-group v-model="teaUsageValue" shape="dot" checked-color="#4C9F44" inline @change="TeaRoom.handleChangeTeaUsage">
<block v-for="(item, index) in teaUsageList" :key="index">
<wd-radio :value="item.type">
<view class="text-[#303133] text-26rpx leading-36rpx mt-2rpx">{{item.name}}</view>
@ -175,13 +177,13 @@
<view class="">
<view class="text-24rpx leading-34rpx text-#303133">已选 {{selectedTea.length}} 项</view>
<view class="">
<price-format color="#FF5951" :first-size="40" :second-size="40" :subscript-size="28" :price="23.02"></price-format>
<price-format color="#FF5951" :first-size="40" :second-size="40" :subscript-size="28" :price="totalSelectedTeaPrice"></price-format>
</view>
</view>
<view class="flex items-center">
<view class="w-178rpx h-70rpx leading-70rpx text-center bg-#F6F7F8 text-#303133 rounded-8rpx mr-20rpx">重置</view>
<view class="w-178rpx h-70rpx leading-70rpx text-center bg-#4C9F44 text-#fff rounded-8rpx">确定</view>
<view class="w-178rpx h-70rpx leading-70rpx text-center bg-#F6F7F8 text-#303133 rounded-8rpx mr-20rpx" @click="TeaRoom.handleResetTeaService">重置</view>
<view class="w-178rpx h-70rpx leading-70rpx text-center bg-#4C9F44 text-#fff rounded-8rpx" @click="TeaRoom.handleConfirmTeaService">确定</view>
</view>
</view>
</view>
@ -287,8 +289,13 @@
<view class="flex items-center justify-between">
<view class="text-[26rpx] text-[#606266] leading-36rpx">茶艺服务</view>
<view class="flex items-center">
<view class="text-[28rpx] text-[#909399] leading-40rpx">
{{ teaService.name || '请选择' }}
<view class="text-[28rpx] text-[#909399] leading-40rpx w-430rpx line-1 text-right">
<template v-if="selectedTea.length > 0">
{{ servicePeople }}/{{ selectedTeaTxt.join(',') }}
</template>
<template v-else>
请选择
</template>
</view>
<view>
<wd-icon name="chevron-right" size="32rpx" color="#909399"></wd-icon>
@ -307,12 +314,19 @@
</view>
<!-- 优惠券 -->
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="TeaRoom.handleToCoupon(1)">
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="TeaRoom.handleToCoupon(CouponType.Discount)">
<view class="text-[#303133] text-32rpx leading-44rpx font-bold mb-24rpx">优惠券</view>
<view class="flex items-center justify-between">
<view class="text-[26rpx] text-[#606266] leading-36rpx">优惠券</view>
<view class="flex items-center">
<view class="text-[28rpx] text-[#909399] leading-40rpx">无可用</view>
<view class="text-[28rpx] text-[#909399] leading-40rpx w-430rpx line-1 text-right">
<template v-if="selectedCoupon?.id > 0">
{{ selectedCoupon.name }}
</template>
<template v-else>
请选择
</template>
</view>
<view>
<wd-icon name="chevron-right" size="32rpx" color="#909399"></wd-icon>
</view>
@ -331,7 +345,7 @@
<view class="flex items-center ml-60rpx">
<view class="text-24rpx text-[#303133] leading-34rpx w-72rpx">合计</view>
<view class="flex items-center h-56rpx mr-16rpx">
<price-format color="#FF5951" :first-size="40" :second-size="40" :subscript-size="28" :price="23.02"></price-format>
<price-format color="#FF5951" :first-size="40" :second-size="40" :subscript-size="28" :price="bill.total"></price-format>
<view class="ml-20rpx" v-if="isGroupBuying">
<price-format color="#909399" :first-size="26" :second-size="26" :subscript-size="26" :price="23.02" lineThrough></price-format>
</view>
@ -351,17 +365,18 @@
</template>
<script lang="ts" setup>
import {toast} from '@/utils/toast'
import {router} from '@/utils/tools'
import { toast } from '@/utils/toast'
import { router, toTimes, toPlus } from '@/utils/tools'
import PriceFormat from '@/components/PriceFormat.vue'
import {ReserveServiceCategory} from '@/utils/order'
import { PayList, PayCategory, PayValue } from '@/utils/pay'
import Pay from '@/components/Pay.vue'
import { getTeaSpecialistDetails, getNext7Days, getTeaTypeList } from '@/api/tea'
import type { ITeaSpecialistDetailsFields, ITeaSpecialistFuture7DaysResult } from '@/api/types/tea'
import type { ITeaSpecialistDetailsFields, ITeaSpecialistFuture7DaysResult, ITeaTypeListResult } from '@/api/types/tea'
import { TeaSpecialistLevelValue } from '@/utils/teaSpecialist'
import type { IUserAddressListResult } from '@/api/types/user'
import BookingTime from '@/components/BookingTime.vue'
import { CouponType } from '@/utils/coupon'
const OSS = inject('OSS')
@ -374,11 +389,10 @@
// 选择茶馆
const teaHouse = ref<{id: number, name: string}>({id: 0, name: ''})
const showTeaHousePopup = ref<boolean>(false) // 显示门店列表弹窗
// 选择预定时间
const showBookTimePopup = ref<boolean>(false)
let sevenDay = reactive<ITeaSpecialistFuture7DaysResult>({
const sevenDay = reactive<ITeaSpecialistFuture7DaysResult>({
minimum_time: 0,
time: []
})
@ -402,34 +416,16 @@
const teaService = ref<{id: number, name: string}>({id: 0, name: ''})
const showTeaServicePopup = ref<boolean>(false) // 显示门店列表弹窗
const servicePeople = ref<number>(1) // 服务人数
const teaList = ref<Array<any>>([
{
id: 1,
name: '红茶(3泡)',
price: 1
},
{
id: 2,
name: '绿茶(3泡)',
price: 2
},
{
id: 3,
name: '乌龙茶(3泡)',
price: 13
},
{
id: 4,
name: '普洱茶(3泡)',
price: 4
}
])
const teaList = ref<ITeaTypeListResult[]>([]) // 茶叶列表
const selectedTea = ref<Array<any>>([]) // 选择的茶叶
const selectedTeaTxt = ref<Array<any>>([]) // 选择的茶叶文本
const selectedTeaPrice = ref<Array<any>>([]) // 选择的茶叶价格
const totalSelectedTeaPrice = ref<string>('')
// 茶具使用
const teaUsageList = ref<Array<any>>([
{type: 1, name: '到店服务'},
{type: 2, name: '上门服务'},
{type: 1, name: '客户自备'},
{type: 2, name: '茶艺师提供'},
])
const teaUsageValue = ref<number>(1)
@ -447,7 +443,7 @@
const showPayPopup = ref<boolean>(false) // 支付popup
// 茶艺师
const id = ref<number>(0)
const teaSpecialistId = ref<number>(0)
const info = reactive<ITeaSpecialistDetailsFields>({
name: '',
star: 0,
@ -464,6 +460,32 @@
})
const is90 = ref<boolean>(false)
// 选择的优惠券
const selectedCoupon = ref<{id: number, name: string}>({id: 0, name: ''})
// 计算费用明细 service(服务费) travel(车马费) teaServiceFee(茶艺服务) coupon(优惠券)
const bill = ref<{service: any, travel: any, teaService: any, coupon: number, total: number}>({
service: {
total: 0,
unitPrice: 0,
num: 0
},
travel: {
total: 0,
unitPrice: 0,
num: 0
},
teaService: {
total: 0,
tea: '',
teaTotal: 0,
cup: 0,
peopleNum: 0
},
coupon: 0,
total: 0
})
// 提交的数据
const reserveTime = ref<Array<any>>([])
@ -474,6 +496,8 @@
}
if (args.id) {
teaSpecialistId.value = Number(args.id)
const res = await getTeaSpecialistDetails({
id: args.id,
longitude: 0,
@ -488,43 +512,68 @@
is90.value = true
}
})
bill.value.travel = {
total: toTimes(info.fare_price, info.distance),
unitPrice: info.fare_price,
num: info.distance
}
}
}
// 获取未来7天时间段
const next7 = await getNext7Days()
Object.assign(sevenDay, next7)
// 初始化数据
TeaRoom.handleInit()
})
const TeaRoom = {
const TeaRoom = {
handleInit: async () => {
// 获取未来7天时间段
const next7 = await getNext7Days()
Object.assign(sevenDay, next7)
const tea = await getTeaTypeList()
teaList.value = tea as ITeaTypeListResult[]
console.log("🚀 ~ teaList.value:", teaList.value)
},
handleClick: (item: any) => {
// 处理点击事件
console.log('Clicked item:', item)
},
// 跳转优惠券页面
handleToCoupon(type) {
// 1优惠券 2团购券
uni.navigateTo({ url: `/bundle/coupon/coupon?type=${type}` })
},
handlePay: () => {
// 这里需要判断下如果是预约的话跳转结果通知是reserve的团购是pay的
// uni.navigateTo({ url: '/bundle/reserve-room/result' })
},
handleToggleTea: (id: number) => {
// 切换预定茶叶选择
handleToggleTea: (id: number, name: string, price: number) => {
const index = selectedTea.value.indexOf(id)
if (index > -1) {
// 已选择,取消选择
selectedTea.value.splice(index, 1)
selectedTeaTxt.value.splice(index, 1)
selectedTeaPrice.value.splice(index, 1)
} else {
// 未选择,添加选择
selectedTea.value.push(id)
selectedTeaTxt.value.push(name)
selectedTeaPrice.value.push(price)
}
totalSelectedTeaPrice.value = toPlus(selectedTeaPrice.value)
},
// 切换茶具需求
handleChangeTeaUsage: () => {
// TODO 这边需要加上或减去茶具费用
// if (teaUsageValue.value == 2) {
// totalSelectedTeaPrice.value += toTimes(160, servicePeople.value)
// } else {
// totalSelectedTeaPrice.value = toMinus(selectedTeaPrice.value)
// }
console.log("🚀 ~ teaUsageValue:", teaUsageValue.value)
},
// 选择门店
@ -547,9 +596,51 @@
// 选中预定时间
handleChooseReserveTime: (params: any) => {
console.log("🚀 ~ params:", params)
bill.value.service = {
total: toTimes(info.price, params[1].length),
unitPrice: info.price,
num: params[1].length
},
reserveTime.value = params
},
// 跳转优惠券页面
handleToCoupon(type) {
uni.$on('chooseCoupon', params => {
uni.$off('chooseCoupon')
console.log("🚀 ~ params:", params)
selectedCoupon.value = {id: params.coupon.user_coupon_id, name: `${params.coupon.name}${params.coupon.coupon_price}` }
})
if (reserveTime.value.length == 0) {
toast.info('请选择预定时间')
return
}
// 获取预定了几个小时
const count = reserveTime.value[1].length
uni.navigateTo({ url: `/bundle/coupon/coupon?id=${teaSpecialistId.value}&time=${count}&type=${type}` })
},
// 重置差茶艺服务
handleResetTeaService: () => {
servicePeople.value = 1
selectedTea.value = []
teaUsageValue.value = 1
},
// 确认茶艺服务
handleConfirmTeaService: () => {
if (selectedTea.value.length == 0) {
toast.info('请选择预定茶叶')
return
}
console.log("🚀 ~ servicePeople:", servicePeople.value)
console.log("🚀 ~ servicePeople:", selectedTeaPrice.value)
console.log("🚀 ~ servicePeople:", teaUsageValue.value)
teaService.value = { id: 1, name: '茶艺服务' }
showTeaServicePopup.value = false
},
// 提交表单
handleSubmitOrder: () => {

4
src/utils/coupon.ts Normal file
View File

@ -0,0 +1,4 @@
export const CouponType = {
Discount: 1, // 优惠券
GroupBuy: 2 // 团购券
}

View File

@ -1,3 +1,6 @@
import Decimal from 'decimal.js'
import { allowedNodeEnvironmentFlags } from 'process';
/**
* 页面跳转方法
* @param url 跳转地址
@ -48,4 +51,75 @@ export const router = {
})
}, time);
},
}
/**
* 乘法,避免浮点数精度问题,不进行四舍五入,直接截断
* @param num1 乘数1
* @param num2 乘数2
* @returns 乘积
*/
export function toTimes(num1: number, num2: number) {
const value1 = new Decimal(num1)
const value2 = new Decimal(num2)
const result = value1.times(value2).toDecimalPlaces(2, Decimal.ROUND_DOWN)
console.log("🚀 ~ toPlus ~ result:", result)
return result.toString()
}
/**
* 加法,避免浮点数精度问题,不进行四舍五入,直接截断
* @param args 任意数量的加数
* @returns 求和结果字符串保留2位小数向下截断
*/
/**
* 加法,支持对象参数(如 {0: '128', 1: '128'}),避免浮点数精度问题,不进行四舍五入,直接截断
* @param args 任意数量的加数或对象
* @returns 求和结果字符串保留2位小数向下截断
*/
export function toPlus(...args: any[]): string {
// 支持 toPlus({0: '128', 1: '128'}) 或 toPlus('128', '128')
let arr: any[] = []
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null) {
// 传入的是对象,取所有值
arr = Object.values(args[0])
} else {
arr = args
}
let sum = new Decimal(0)
for (const num of arr) {
// 自动转为数字
const n = Number(num)
if (!isNaN(n)) {
sum = sum.plus(new Decimal(n))
}
}
// 截断2位小数不四舍五入
const result = sum.toDecimalPlaces(2, Decimal.ROUND_DOWN)
return result.toString()
}
/**
* 减法,支持对象参数(如 {0: '128', 1: '28'}),避免浮点数精度问题,不进行四舍五入,直接截断
* @param args 任意数量的被减数和减数或对象
* @returns 结果字符串保留2位小数向下截断
*/
export function toMinus(...args: any[]): string {
// 支持 toMinus({0: '128', 1: '28'}) 或 toMinus('128', '28')
let arr: any[] = []
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null) {
arr = Object.values(args[0])
} else {
arr = args
}
if (arr.length === 0) return '0.00'
let result = new Decimal(Number(arr[0]) || 0)
for (let i = 1; i < arr.length; i++) {
const n = Number(arr[i])
if (!isNaN(n)) {
result = result.minus(new Decimal(n))
}
}
return result.toDecimalPlaces(2, Decimal.ROUND_DOWN).toString()
}