1 Commits

Author SHA1 Message Date
2cedcf376e 添加百度的数据埋点 2026-04-16 16:44:17 +08:00
35 changed files with 434 additions and 1224 deletions

View File

@ -135,7 +135,7 @@ export default defineManifestConfig({
'scope.userLocation' : {
desc : "我们需要获取您的位置,以方便推荐附近茶室给您"
}
}
},
},
'mp-alipay': {
usingComponents: true,

View File

@ -103,7 +103,6 @@
"js-cookie": "^3.0.5",
"pinia": "2.0.36",
"pinia-plugin-persistedstate": "3.2.1",
"umtrack-wx": "^2.8.0",
"vue": "3.4.21",
"wot-design-uni": "^1.9.1",
"z-paging": "2.8.7"

9
pnpm-lock.yaml generated
View File

@ -97,9 +97,6 @@ importers:
pinia-plugin-persistedstate:
specifier: 3.2.1
version: 3.2.1(pinia@2.0.36(typescript@5.9.2)(vue@3.4.21(typescript@5.9.2)))
umtrack-wx:
specifier: ^2.8.0
version: 2.8.0
vue:
specifier: 3.4.21
version: 3.4.21(typescript@5.9.2)
@ -5288,7 +5285,6 @@ packages:
phin@3.7.1:
resolution: {integrity: sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==}
engines: {node: '>= 8'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@ -6044,9 +6040,6 @@ packages:
ufo@1.6.1:
resolution: {integrity: sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==}
umtrack-wx@2.8.0:
resolution: {integrity: sha512-F5ul+Q7bDJ6MDrn9ysPAyB9nyP1vCxLGUBkSJ4uvknt8rjmX4tqy1IUnJuWKj9ZH2BtkjRFpldQXJSlLDOYfhQ==}
unconfig@0.5.5:
resolution: {integrity: sha512-VQZ5PT9HDX+qag0XdgQi8tJepPhXiR/yVOkn707gJDKo31lGjRilPREiQJ9Z6zd/Ugpv6ZvO5VxVIcatldYcNQ==}
@ -13753,8 +13746,6 @@ snapshots:
ufo@1.6.1: {}
umtrack-wx@2.8.0: {}
unconfig@0.5.5:
dependencies:
'@antfu/utils': 0.7.10

View File

@ -4,7 +4,7 @@ import { http } from '@/http/alova'
* 获取首页轮播图
*/
export function getHomeBannerList() {
return http.Post<{ list: Array<{ address: string;}> }>('/api/index/carouselLists', {},
return http.Post<{ list: Array<{ address: string;}> }>('/api/index/carouselLists', null,
{
meta: { ignoreAuth: true }
}
@ -21,22 +21,10 @@ export function getHomeCouponPopup() {
/**
* 首页领取88元优惠券
*/
export function claimIndexCoupon(id: number) {
return http.Post('/api/UserCoupon/shouyeCoupon', {id})
export function claimIndexCoupon() {
return http.Post('/api/UserCoupon/shouyeCoupon', {})
}
export function getWxacode() {
return http.Post('/api/wxCode/getWxacode', {})
}
/**
* 获取茶艺师入口图
*/
export function getTeaArtistEntrance() {
return http.Post<any>('/api/index/homeImage', {},
{
meta: { ignoreAuth: true }
}
)
}

View File

@ -100,7 +100,7 @@ export interface IRoomDetailParams {
}
export function getTeaRoomDetail(data: IRoomDetailParams) {
return http.Post<any>('/api/teaStore/teaStoreDetails', data, {
return http.Post<ITeaRoomDetailResult>('/api/teaStore/teaStoreDetails', data, {
meta: { ignoreAuth: true }
})
}

View File

@ -17,10 +17,7 @@ export interface ITeaSpecialistParams {
longitude: number
level?: string
search?: string
server_type?: string | number // 1到店服务 2上门服务
status?: string | number // 0可约 1已约 2已取消
state?: string | number // 0全部 1已约 2不可约
city_id?: string | number // 城市ID
server_type?: number // 1到店服务 2上门服务
}
export function getTeaSpecialist(data: ITeaSpecialistParams) {
@ -34,7 +31,6 @@ export function getTeaSpecialist(data: ITeaSpecialistParams) {
* @param latitude 纬度
*/
export interface ITeaSpecialistDetailParams {
user_id?: number
team_user_id: number
longitude: number
latitude: number
@ -127,27 +123,4 @@ export function getExclusiveCirclesLabel() {
*/
export function reserveGroupTeaSpecialist(data) {
return http.Post<any>('/api/user/reservation', data)
}
/**
* 隐藏上门服务
*/
export function getSetting() {
return http.Post<any>('/api/setting/set', null, {
meta: { ignoreAuth: true }
})
}
/**
* 收藏茶艺师
*/
export function collectTeaSpecialist(data) {
return http.Post<any>('/api/teamaster/teamasterCollect', data)
}
/**
* 获取茶艺师收藏列表
*/
export function getCollectTeaSpecialistList(data) {
return http.Post<any>('/api/teamaster/teamasterCollectList', data)
}

View File

@ -103,7 +103,7 @@ export interface ICreateTeaSpecialistOrderParams {
is_teacup: number
tea_id: string
user_coupon_id: number
server_number: string
server_number: number
team_group_id?: number
}

View File

@ -93,13 +93,6 @@ export function getMyCoupon() {
return http.Post<IUserCouponListResult>('/api/UserCoupon/coupinList')
}
/**
* 个人中心可用优惠券
*/
export function getMyAvailableCoupon() {
return http.Post<any>('/api/UserCoupon/personUserCoupinList')
}
/**
* 领取个人中心优惠券
*/
@ -252,11 +245,4 @@ export function getConfig() {
return http.Post<any>('/api/setting/get' , null , {
meta: { ignoreAuth: true }
})
}
/**
* 拨打虚拟手机号码
*/
export function callVirtualNumber(order_sn: string) {
return http.Post<any>('/api/order/mobileBind', {order_sn})
}
}

View File

@ -1,30 +1,31 @@
<route lang="jsonc" type="page">{
<route lang="jsonc" type="page">
{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
}
}</route>
}
</route>
<template>
<view class="pb-180rpx">
<view>
<navbar title="收藏" custom-class='!bg-[#F6F7F8]'></navbar>
</view>
<navbar title="收藏" custom-class='!bg-[#F6F7F8]'></navbar>
</view>
<view>
<view class="coupon-tab">
<wd-tabs v-model="tab" swipeable slidable="always" @click="Collect.handleChangeTab" :lazy="false">
<!-- <wd-tab title="茶室"></wd-tab> -->
<wd-tabs v-model="tab" swipeable slidable="always" @click="Collect.handleChangeTab" :lazy="false">
<wd-tab title="茶室"></wd-tab>
<!-- TODO 茶艺师内容先隐藏 -->
<wd-tab title="茶艺师"></wd-tab>
<!-- <wd-tab title="茶艺师"></wd-tab> -->
</wd-tabs>
<view class="">
<mescroll-body @init="mescrollInit" :down="downOption" @down="downCallback" :up="upOption"
@up="Collect.upCallback" top="28rpx">
<mescroll-body @init="mescrollInit" :down="downOption" @down="downCallback" :up="upOption" @up="Collect.upCallback" top="28rpx">
<!-- 茶室列表 -->
<!-- <template v-if="tab === 0">
<template v-if="tab === 0">
<view class="relative p-20rp mb-24rpx" v-for="(item, index) in list" :key="index" @click="Collect.handleToTeaRoom(item.tea_store_id)">
<view class="absolute top--28rpx left-0 z-1">
<wd-img width="110rpx" height="110rpx" :src="`${OSS}images/home/home_image4.png`"/>
@ -64,99 +65,55 @@
</view>
</view>
</view>
</template> -->
</template>
<!-- 茶艺师列表 -->
<template v-if="tab === 0">
<view class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx relative"
v-for="(item, index) in list" :key="index">
<view class="mr-28rpx relative z-2" @click="Collect.handlePreviewImage(item.image)">
<wd-img width="260rpx" height="320rpx" :src="item.image" mode="aspectFill"
radius="10rpx"></wd-img>
<view
class="tea-specialist-time absolute z-3 top-26rpx left-0 bg-[#4C9F44] text-[#fff] font-400 text-18rpx flex items-center justify-center">
<text v-if="item.state == 0">可约</text>
<text v-if="item.state == 1">工作中</text>
<text v-if="item.state == 2">不可约</text>
<template v-if="tab === 1">
<view class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx">
<view class="mr-28rpx relative">
<wd-img width="200rpx" height="200rpx" :src="`${OSS}images/home/home_image5.png`"></wd-img>
<view class="tea-specialist-time absolute top-6rpx left-0 text-[#fff] font-400 text-18rpx leading-26rpx flex items-center justify-center">
可约9:00
</view>
</view>
<view class="flex-1"
@click="Collect.handleReserveTeaSpecialist(item.team_user_id, item.state)">
<view class="flex-1">
<view class="flex items-center justify-between">
<view class="flex items-center mb-8rpx">
<view class="font-bold text-[#303133] text-30rpx leading-42rpx mr-12rpx">
{{ item.name }}
</view>
<view class="flex items-center">
<wd-icon name="star-on" size="22rpx" color="#FF5951"></wd-icon>
<view class="font-400 text-24rpx text-[#FF5951] leading-34rpx ml-6rpx">
{{ item.star }}
</view>
</view>
<view class="font-bold text-[#303133] text-30rpx leading-42rpx mr-14rpx">
凝香茶业
</view>
<view @click.stop="Collect.handleCancelTeamaster(item.team_user_id)">
<view class="w-168rpx h-40rpx relative mr-44rpx">
<view class="absolute left-0 top-0 h-36rpx flex items-start">
<wd-img :src="`${OSS}icon/icon_gold_medal.png`" width="36rpx" height="36rpx"></wd-img>
</view>
<view class="bg-[#F0F6EF] text-[#006C2D] font-400 text-22rpx leading-32rpx rounded-4rpx text-center w-150rpx ml-18rpx pb-4rpx">金牌茶艺师</view>
</view>
<view @click.stop="Collect.handleCancelTeaRoom(1)">
<wd-icon name="heart-filled" size="22px" color="#F65353"></wd-icon>
</view>
</view>
<view class="flex items-center mb-14rpx">
<!-- 到店服务标签 -->
<view class="mr-12rpx" v-if="item.server_type == 1 || item.server_type == 3">
<wd-tag color="#F55726" bg-color="#F55726" plain
custom-class="!rounded-4rpx">到店服务</wd-tag>
</view>
<!-- 上门服务标签 -->
<view class="mr-12rpx" v-if="item.server_type == 2 || item.server_type == 3">
<wd-tag color="#40AE36" bg-color="#40AE36" plain
custom-class="!rounded-4rpx">上门服务</wd-tag>
</view>
<view class="flex items-center">
<view class="mr-12rpx">
<wd-tag color="#818CA9" bg-color="#F3F3F3">{{ item.both }}岁</wd-tag>
<wd-tag color="#40AE36" bg-color="#40AE36" plain custom-class="!rounded-4rpx">上门服务</wd-tag>
</view>
<view class="mr-12rpx">
<wd-tag color="#F55726" bg-color="#F55726" plain>到点服务</wd-tag>
</view>
<view class="mr-12rpx">
<wd-tag color="#818CA9" bg-color="#F3F3F3">28</wd-tag>
</view>
<view class="flex items-center mt-8rpx">
<wd-img
:src="item.sex == 1 ? `${OSS}icon/icon_man.png` : `${OSS}icon/icon_woman.png`"
width="28rpx" height="28rpx"></wd-img>
<wd-img :src="`${OSS}icon/icon_woman.png`" width="28rpx" height="28rpx"></wd-img>
</view>
</view>
<view class="flex flex-wrap items-center mt-14rpx mb-24rpx">
<view
class="mr-8rpx px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx mb-14rpx"
:style="Collect.handleGetLabelStyle(Number(index))"
v-for="(label, index) in item.label" :key="index">
{{ label.label_name }}
</view>
<view class="font-400 text-[#F29747] text-24rpx leading-34rpx mt-20rpx">
100+收藏
</view>
<view class="flex items-center justify-between mb-8rpx">
<view class="mr-20rpx w-200rpx">
<view class="flex items-center">
<view class="flex items-center">
<wd-img :src="`${OSS}icon/icon_store_cert2.png`" width="30rpx"
height="30rpx"></wd-img>
</view>
<text class="ml-8rpx font-400 text-24rpx leading-4rpx"
:class="item.company_status ? 'text-#4C9F44' : 'text-#303133'">
{{ item.company_abv }}
</text>
</view>
</view>
</view>
<view
class="font-400 text-[#FF5951] text-26rpx leading-40rpx flex items-center justify-between mt-4rpx">
<view class="">
<text class="text-32rpx">{{ item.price }}</text>
<text class="text-24rpx">/小时</text>
</view>
<!-- <view class="font-400 text-22rpx leading-32rpx text-#92928C">{{ item.is_time }}
</view> -->
<view class="font-400 text-[#FF5951] text-26rpx leading-40rpx">
<text class="text-32rpx">180</text>
<text class="text-24rpx">/小时</text>
</view>
</view>
</view>
@ -169,154 +126,103 @@
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { toast } from '@/utils/toast'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import { getCollectTeaRoomList, collectTeaRoom } from '@/api/tea-room'
import { getCollectTeaSpecialistList, collectTeaSpecialist } from '@/api/tea-specialist'
import { router, previewImage } from '@/utils/tools'
import {ref} from 'vue'
import {toast} from '@/utils/toast'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import { getCollectTeaRoomList, collectTeaRoom } from '@/api/tea-room'
const tab = ref<number>(0)
const OSS = inject('OSS')
const tab = ref<number>(0)
const OSS = inject('OSS')
// 分页
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom) // 调用mescroll的hook
const downOption = {
auto: true
}
const upOption = {
auto: true,
textNoMore: '~ 已经到底啦 ~', //无更多数据的提示
}
const list = ref<Array<any>>([])
// 分页
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom) // 调用mescroll的hook
const downOption = {
auto: true
}
const upOption = {
auto: true,
textNoMore: '~ 已经到底啦 ~', //无更多数据的提示
}
const list = ref<Array<any>>([])
onLoad((args) => { })
onLoad((args) => {
const Collect = {
// 上拉加载的回调: 其中num:当前页 从1开始, size:每页数据条数,默认10
upCallback: (mescroll) => {
const filter = {
page: mescroll.num,
size: mescroll.size,
}
})
console.log("🚀 ~ tab.value:", tab.value)
// if (tab.value == 0) {
// getCollectTeaRoomList(filter).then( res => {
// console.log("🚀 ~ res:", res)
// const curPageData = res.list || [] // 当前页数据
// if(mescroll.num == 1) list.value = [] // 第一页需手动制空列表
// list.value = list.value.concat(curPageData) //追加新数据
// mescroll.endSuccess(curPageData.length, Boolean(res.more))
// }).catch(() => {
// mescroll.endErr() // 请求失败, 结束加载
// })
// } else
if (tab.value == 0) {
getCollectTeaSpecialistList(filter).then(res => {
console.log("🚀 ~ res:", res)
const curPageData = res.list || [] // 当前页数据
if (mescroll.num == 1) list.value = [] // 第一页需手动制空列表
list.value = list.value.concat(curPageData) //追加新数据
mescroll.endSuccess(curPageData.length, Boolean(res.more))
}).catch(() => {
mescroll.endErr() // 请求失败, 结束加载
const Collect = {
// 上拉加载的回调: 其中num:当前页 从1开始, size:每页数据条数,默认10
upCallback: (mescroll) => {
const filter = {
page: mescroll.num,
size: mescroll.size,
}
getCollectTeaRoomList(filter).then( res => {
console.log("🚀 ~ res:", res)
const curPageData = res.list || [] // 当前页数据
if(mescroll.num == 1) list.value = [] // 第一页需手动制空列表
list.value = list.value.concat(curPageData) //追加新数据
mescroll.endSuccess(curPageData.length, Boolean(res.more))
}).catch(() => {
mescroll.endErr() // 请求失败, 结束加载
})
},
// 切换tab
handleChangeTab: (item: any) => {
tab.value = Number(item.index)
},
// 去茶室的详情
handleToTeaRoom: (id: number) => {
uni.navigateTo({
url: `/bundle/tea-room/room?id=${id}`
})
}
},
},
// 切换tab
handleChangeTab: (item: any) => {
tab.value = Number(item.index)
},
// 取消收藏
handleCancelTeaRoom: async (id: number) => {
await collectTeaRoom({
id,
status: 0
})
toast.info('取消收藏成功')
list.value = []
getMescroll().resetUpScroll()
},
// 去茶室的详情
handleToTeaRoom: (id: number) => {
uni.navigateTo({
url: `/bundle/tea-room/room?id=${id}`
})
},
// 取消收藏
handleCancelTeaRoom: async (id: number) => {
await collectTeaRoom({
id,
status: 0
})
toast.info('取消收藏成功')
list.value = []
getMescroll().resetUpScroll()
},
// 取消收藏茶艺师
handleCancelTeaSpecialist: (item: any) => {
toast.info('取消收藏成功')
},
handleGetLabelStyle: (index: number) => {
const firstThreeStyles = [
{ backgroundColor: '#FAF1F1', color: '#CE295A' },
{ backgroundColor: '#F1F3FA', color: '#2934CE' },
{ backgroundColor: '#F1FAF9', color: '#29C9CE' },
]
return firstThreeStyles[index] || { backgroundColor: '#F3F3F3', color: '#818CA9' }
},
/**
* 预约茶艺师
* @param id
* @param state 茶艺师状态: 0可约 1工作中
*/
handleReserveTeaSpecialist: (id: number, state: number) => {
router.navigateTo(`/bundle_b/pages/tea-specialist/detail?id=${id}`)
},
/**
* 预览图片
*/
handlePreviewImage: (img: any) => {
previewImage(img, [img])
},
// 取消收藏茶艺师
handleCancelTeamaster: async (id: number) => {
await collectTeaSpecialist({
id,
status: 0
})
toast.info('取消收藏成功')
list.value = []
getMescroll().resetUpScroll()
// 取消收藏茶艺师
handleCancelTeaSpecialist: (item: any) => {
toast.info('取消收藏成功')
}
}
}
</script>
<style lang="scss">
page {
background-color: $cz-page-background;
}
page {
background-color: $cz-page-background;
}
.coupon-tab {
:deep() {
.coupon-tab {
:deep() {
.wd-tabs,
.wd-tabs__nav,
.wd-tabs__line {
background-color: transparent !important;
}
.wd-tabs,
.wd-tabs__nav,
.wd-tabs__line {
background-color: transparent !important;
}
.wd-tabs__line {
display: none !important;
.wd-tabs__line {
display: none !important;
}
}
}
}
.tea-specialist-time {
width: 106rpx;
height: 38rpx;
background-image: url(#{$OSS}images/collect/collect_image1.png);
background-size: 100% 100%;
}
.tea-specialist-time {
width: 106rpx;
height: 38rpx;
background-image: url(#{$OSS}images/collect/collect_image1.png);
background-size: 100% 100%;
}
</style>

View File

@ -38,7 +38,7 @@
</wd-radio-group>
</view>
</view>
<!-- <view class="mx-30rpx">
<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">{{ couponList.no_use.length }}</text>
@ -58,7 +58,7 @@
></coupon>
</wd-radio-group>
</view>
</view> -->
</view>
</view>
</view>
</view>
@ -66,7 +66,7 @@
<script lang="ts" setup>
import Coupon from '@/components/coupon/Coupon.vue'
import { getMyAvailableCoupon } from '@/api/user'
import { getCoupons } from '@/api/user'
import type { IUserCouponListResult } from '@/api/types/user'
@ -94,11 +94,14 @@
* @param numbers 预定时长
*/
handleInitCoupon: async () => {
const res = await getMyAvailableCoupon() // 1茶艺师 2茶室 3 个人中心
console.log("🚀 ~ res:", res)
useCoupon.value = res.count
const res = await getCoupons({type_id: 3, price: 0}) // 1茶艺师 2茶室 3 个人中心
// couponList.value = res
useCoupon.value = res.count.yes_use
unUseCoupon.value = res.count.no_use
if (res.result.length > 0) {
couponList.value.use = res.result
couponList.value.use = res.result.filter(item => item.is_use == 0)
couponList.value.no_use = res.result.filter(item => item.is_use == 1)
}
},

View File

@ -502,7 +502,6 @@
import { getTeaTypeList } from '@/api/tea'
import { getTeaSpecialistFeeDetails, createTeaSpecialistRenewOrder } from '@/api/tea-specialist'
import type { ITeaTypeListResult } from '@/api/types/tea'
import { callVirtualNumber } from '@/api/user'
const OSS = inject('OSS')
const toast = useToast()
@ -816,11 +815,9 @@
/**
* 拨打电话
*/
handleCall: async () => {
const res = await callVirtualNumber(order.value.order_sn)
console.log("🚀 ~ res:", res)
handleCall: () => {
uni.makePhoneCall({
phoneNumber: res.mobile
phoneNumber: order.value.team_mobile
})
}
}

View File

@ -15,7 +15,7 @@
<wd-popup v-model="showReservePopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;"
position="bottom">
<view class="relative">
<view class="absolute top-18rpx right-30rpx" @tap.stop.prevent="Door.handleCloseReservePopup">
<view class="absolute top-18rpx right-30rpx" @click="showReservePopup = 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>
@ -49,9 +49,9 @@
<view class="pb-22rpx mt-40rpx mx-30rpx flex justify-between items-center text-[32rpx] text-center">
<view class='bg-[#F6F7F8] text-[#303133] rounded-8rpx h-90rpx leading-90rpx w-[50%] mr-28rpx'
@tap.stop.prevent="Door.handleResetTime">重置</view>
@click="Door.handleResetTime">重置</view>
<view class='bg-[#4C9F44] text-[#fff] rounded-8rpx h-90rpx leading-90rpx w-[50%]'
@tap.stop.prevent="Door.handleConfirmHour">确定({{ totalHour }}小时)</view>
@click="Door.handleConfirmHour">确定({{ totalHour }}小时)</view>
</view>
</view>
</wd-popup>
@ -372,11 +372,10 @@
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="Reserve.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="text-[26rpx] text-[#606266] leading-36rpx">优惠券</view>
<view class="flex items-center">
<view class="text-[28rpx] text-[#909399] leading-40rpx w-430rpx line-1 text-right">
<template v-if="selectedCoupon?.id > 0">
<text class="bg-#FEF1F0 text-#FF5951 rounded-6rpx text-center text-22rpx leading-40rpx px-10rpx py-2rpx">待使用</text>
{{ selectedCoupon.name }}
</template>
<template v-else>
@ -1084,13 +1083,6 @@ const Door = {
return `${year}-${month}-${day} ${hour}:${minute}`
},
handleCloseReservePopup: () => {
uni.hideKeyboard()
setTimeout(() => {
showReservePopup.value = false
}, 50)
},
/**
* 重置预定时间
*/
@ -1132,7 +1124,7 @@ const Door = {
// },
// })
// }
Door.handleCloseReservePopup()
showReservePopup.value = false
// 计算费用明细
costParams.value.hours = totalHour.value

View File

@ -25,7 +25,7 @@
<wd-radio :value="1" border>
<view class="leading-36rpx font-400 text-30rpx ml-12rpx mr-60rpx">到店服务</view>
</wd-radio>
<wd-radio :value="2" border v-if="setting.status == 1">
<wd-radio :value="2" border>
<view class="leading-36rpx font-400 text-30rpx ml-12rpx">上门服务</view>
</wd-radio>
</wd-radio-group>
@ -156,7 +156,6 @@ import { getHomeTeaStoreList } from '@/api/tea-room'
import type { ITeaHouseListResult } from '@/api/types/tea'
import type { IUserAddressListResult } from '@/api/types/user'
import { getUserAddress } from '@/api/user'
import { getSetting } from '@/api/tea-specialist'
const OSS = inject('OSS')
@ -176,13 +175,9 @@ const upOption = {
textNoMore: '~ 已经到底啦 ~', //无更多数据的提示
}
const setting = ref<any>({})
onLoad((args) => {
// 初始化地址列表
Service.handleInitAddress()
// 初始化设置
Service.handleInitSetting()
})
const Service = {
@ -214,16 +209,6 @@ const Service = {
addressList.value = Array.isArray(res) ? res : []
},
/**
* 初始化设置
*/
handleInitSetting: async () => {
const res = await getSetting()
setting.value = res || {}
console.log("🚀 ~ res:", setting.value.status)
},
// 搜索
handleSearch: () => {
list.value = []

View File

@ -194,8 +194,6 @@ const TeaSpecialist = {
longitude: storage.longitude || import.meta.env.VITE_DEFAULT_LONGITUDE,
level: uni.getStorageSync('teaPackageType'),
server_type: serviceType.value, // 1到店服务 2上门服务
state: 1, // 1可约 2不可约
city_id: uni.getStorageSync('cityId') || 0,
}
try {
const res = await getTeaSpecialist(filter)

View File

@ -119,7 +119,7 @@
<view class="flex justify-end">
<view class="flex items-center">
<view class="font-400 text-[#303133] text-30rpx leading-42rpx">
2.14.16
2.14.9
</view>
</view>
</view>

View File

@ -168,35 +168,13 @@
</view>
</view>
<!-- 茶艺师资格证书 -->
<!-- <view class="bg-white rounded-16rpx px-30rpx py-28rpx mt-20rpx">
<view class="flex items-center">
<view class="text-32rpx leading-44rpx text-#303133 mr-10rpx">茶艺师资格证书</view>
<view class="flex items-center">
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`"></wd-img>
</view>
</view>
<view class="mt-32rpx flex items-center">
<wd-upload
:header="{'token': token}"
v-model:file-list="fileList"
:limit="1"
image-mode="scaleToFill"
:action="action">
<view class="border-2rpx border-dashed border-[#E5E5E5] w-184rpx h-184rpx flex flex-col items-center justify-center rounded-16rpx">
<view>
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_upload.png`" mode="aspectFill" />
</view>
<view class="font-400 text-26rpx leading-36rpx text-#303133">资格证书</view>
</view>
</wd-upload>
</view>
</view> -->
<!-- 身份证 -->
<view class="bg-white rounded-16rpx px-30rpx py-28rpx mt-20rpx">
<view class="flex items-center">
<view class="text-32rpx leading-44rpx text-#303133 mr-10rpx">身份证</view>
<view class="flex items-center">
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`"></wd-img>
</view>
</view>
<view class="mt-32rpx flex items-center gap-16rpx">
<wd-upload
@ -229,6 +207,32 @@
</view>
</view>
<!-- 茶艺师资格证书 -->
<view class="bg-white rounded-16rpx px-30rpx py-28rpx mt-20rpx">
<view class="flex items-center">
<view class="text-32rpx leading-44rpx text-#303133 mr-10rpx">茶艺师资格证书</view>
<view class="flex items-center">
<wd-img width="16rpx" height="16rpx" :src="`${OSS}icon/icon_validate.png`"></wd-img>
</view>
</view>
<view class="mt-32rpx flex items-center">
<wd-upload
:header="{'token': token}"
v-model:file-list="fileList"
:limit="1"
image-mode="scaleToFill"
:action="action">
<view class="border-2rpx border-dashed border-[#E5E5E5] w-184rpx h-184rpx flex flex-col items-center justify-center rounded-16rpx">
<view>
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_upload.png`" mode="aspectFill" />
</view>
<view class="font-400 text-26rpx leading-36rpx text-#303133">资格证书</view>
</view>
</wd-upload>
</view>
</view>
<!-- 个人照片 -->
<view class="bg-white rounded-16rpx px-30rpx py-28rpx mt-20rpx">
<view class="flex items-center">
@ -253,7 +257,7 @@
</view>
<!-- 健康证书信息 -->
<!-- <view class="bg-white rounded-16rpx px-30rpx py-28rpx mt-20rpx">
<view class="bg-white rounded-16rpx px-30rpx py-28rpx mt-20rpx">
<view class="flex items-center">
<view class="text-32rpx leading-44rpx text-#303133 mr-10rpx">健康证</view>
</view>
@ -272,7 +276,7 @@
</wd-upload>
</view>
</view>
</view> -->
</view>
<!-- 联系方式 -->
<view class="bg-white rounded-16rpx px-30rpx py-32rpx mt-20rpx">
@ -327,12 +331,8 @@
class="text-32rpx leading-44rpx flex items-center justify-center leading-90rpx text-center text-[#303133] mt-112rpx pb-66rpx">
<view class="w-330rpx h-90rpx bg-[#FFFFFF] rounded-8rpx mr-30rpx"
@click="router.navigateTo('/bundle/contact/contact')">联系我们</view>
<view class="w-330rpx h-90rpx bg-[#4C9F44] rounded-8rpx text-#fff flex items-center justify-center"
:class="{ 'bg-[#C9C9C9]': isSubmitting }"
@click="TeaSpecialist.handleSubmit">
<text v-if="!isSubmitting">提交申请</text>
<text v-else>提交中...</text>
</view>
<view class="w-330rpx h-90rpx bg-[#4C9F44] rounded-8rpx text-#fff" @click="TeaSpecialist.handleSubmit">
提交申请</view>
</view>
</template>
@ -373,13 +373,10 @@ const countDownTime = ref<number>(1 * 60 * 1000) // 60s倒计时
const startCountDown = ref<boolean>(false) // 是否开始倒计时
const countDown = ref<any>(null) // 倒计时组件
// 防重复提交
const isSubmitting = ref<boolean>(false) // 是否正在提交
// 表单
const form = ref<{
// license_img: string // 营业执照
license_img: string // 营业执照
username: string // 茶艺师名字
gender: number // 茶艺师性别(1男 2女)
both: number | string // 出生年月
@ -389,7 +386,7 @@ const form = ref<{
avatar: string // 头像
mobile: string // 联系电话
code: string // 验证码
// health_certificate?: string // 健康证
health_certificate?: string // 健康证
information?: string // 个人展示
image?: string // 个人展示
front_card?: string // 身份证正面
@ -397,7 +394,7 @@ const form = ref<{
broker_user_id?: number // 经纪人ID可选扫码绑定经纪人时携带
label_id?: string // 专属圈子标签ID逗号分隔
}>({
// license_img: '', // 营业执照
license_img: '', // 营业执照
username: '', // 茶艺师名字
gender: 2, // 茶艺师性别(1男 2女)
both: '', // 出生年月
@ -407,7 +404,7 @@ const form = ref<{
avatar: '', // 头像
mobile: '', // 联系电话
code: '', // 验证码
// health_certificate: '', // 健康证
health_certificate: '', // 健康证
information: '', // 个人展示(2026-04-07暂时废弃)
image: '', // 本人照片
front_card: '', // 身份证正面
@ -563,26 +560,26 @@ const TeaSpecialist = {
return false
}
// 身份证正面和反面校验
if (frontCard.value.length === 0) {
toast.show('请上传身份证正面照片')
return false
}
if (!form.value.city_id) {
toast.show('请选择服务区域')
return false
}
// 身份证正面和反面校验
// if (frontCard.value.length === 0) {
// toast.show('请上传身份证正面照片')
// return false
// }
if (backCard.value.length === 0) {
toast.show('请上传身份证反面照片')
return false
}
// if (backCard.value.length === 0) {
// toast.show('请上传身份证反面照片')
// return false
// }
// if (fileList.value.length == 0) {
// toast.show('请上传茶艺师资格证书')
// return false
// }
if (fileList.value.length == 0) {
toast.show('请上传茶艺师资格证书')
return false
}
// if (fileList4.value.length == 0) {
// toast.show('请至少上传一张个人展示照片')
@ -600,9 +597,9 @@ const TeaSpecialist = {
}
form.value.label_id = selectedTags.value.join(',') // 专属圈子标签ID逗号分隔
// form.value.license_img = fileList.value.length > 0 ? removeImageUrlPrefix(fileList.value)[0] : '' // 茶艺师资格证书
form.value.license_img = fileList.value.length > 0 ? removeImageUrlPrefix(fileList.value)[0] : '' // 茶艺师资格证书
form.value.avatar = fileList2.value.length > 0 ? removeImageUrlPrefix(fileList2.value)[0] : '' // 个人照片
// form.value.health_certificate = fileList3.value.length > 0 ? removeImageUrlPrefix(fileList3.value)[0] : '' // 健康证
form.value.health_certificate = fileList3.value.length > 0 ? removeImageUrlPrefix(fileList3.value)[0] : '' // 健康证
form.value.image = fileList4.value.length > 0 ? removeImageUrlPrefix(fileList4.value) : '' // 个人展示
form.value.image = Array.isArray(form.value.image) ? form.value.image.join(',') : form.value.image
form.value.front_card = frontCard.value.length > 0 ? removeImageUrlPrefix(frontCard.value)[0] : '' // 身份证正面
@ -611,12 +608,6 @@ const TeaSpecialist = {
let data = form.value
data.both = both.value
// 防重复提交
if (isSubmitting.value) {
return
}
isSubmitting.value = true
toast.loading({
loadingType: 'ring',
loadingColor: '#4C9F44',
@ -632,8 +623,7 @@ const TeaSpecialist = {
}, 100)
} catch (e) {
toast.close()
} finally {
isSubmitting.value = false // 无论成功失败都要重置状态
return
}
}
}

View File

@ -163,11 +163,10 @@
<view class="bg-white rounded-16rpx py-26rpx px-30rpx mt-24rpx mx-30rpx" @click="Detail.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="text-[26rpx] text-[#606266] leading-36rpx">优惠券</view>
<view class="flex items-center">
<view class="text-[28rpx] text-[#909399] leading-40rpx w-430rpx line-1 text-right">
<template v-if="selectedCoupon?.id > 0">
<text class="bg-#FEF1F0 text-#FF5951 rounded-6rpx text-center text-22rpx leading-40rpx px-10rpx py-2rpx">待使用</text>
{{ selectedCoupon.name }}
</template>
<template v-else>

View File

@ -161,7 +161,7 @@
import type { ITeaRoomDetailResult } from '@/api/types/tea-room'
import type {IUserInfoVo } from '@/api/types/login'
import { useUserStore } from '@/store'
import { router, previewImage, strToParams } from '@/utils/tools'
import { router, previewImage } from '@/utils/tools'
import { StoreType } from '@/utils/tea'
import DouYinExcharge from '@/bundle/components/DouYinExcharge.vue'
@ -206,13 +206,6 @@
onLoad((args) => {
console.log("🚀 ~ args:", args)
// 处理小程序码扫码进入时的 scene 参数
if (!args.id && args.scene) {
const scene = decodeURIComponent(args.scene)
const params = strToParams(scene)
Object.assign(args, params)
}
if (args.id) {
teaRoomId.value = Number(args.id)
storeType.value = Number(args.type) || StoreType.Direct
@ -304,11 +297,6 @@
longitude: uni.getStorageSync('longitude') || import.meta.env.VITE_DEFAULT_LONGITUDE,
user_id: userInfo.value.id || 0
})
if (res && res.status == 0) {
router.switchTab('/pages/index/index')
return
}
teaRoom.value = res.details
storeType.value = teaRoom.value.operation_type
@ -412,7 +400,7 @@
*/
handleToRecharge: () => {
// router.navigateTo(`/bundle/store-recharge/store-recharge?id=${teaRoom.value.id}&storeName=${teaRoom.value.name}`)
router.navigateTo('/bundle/wallet/recharge-store?storeId=' + teaRoom.value.id)
router.navigateTo('/bundle/wallet/recharge?storeId=' + teaRoom.value.id)
},
/**

View File

@ -102,7 +102,7 @@
</view>
<view class="btn text-center leading-108rpx mx-auto mt-116rpx" @click="benefits.handledToBuyVip" v-if="currentVipType === 'normal'">
立即成为会员 29.9/
立即成为会员 9.9/
</view>
</view>
</view>

View File

@ -16,7 +16,7 @@
<view class="mt-24rpx mx-30rpx">
<view class="text-center">
<view class="text-48rpx leading-66rpx text-[#303133]">29.9</view>
<view class="text-48rpx leading-66rpx text-[#303133]">9.9</view>
<view class="mt-20rpx text-28rpx leading-40rpx text-[#9CA3AF]">开通会员解锁更多精彩内容</view>
</view>

View File

@ -1,183 +0,0 @@
<route lang="jsonc" type="page">
{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
}
}
</route>
<template>
<view class="bg">
<view>
<navbar title="平台充值" custom-class='!bg-[#F6F7F8]'></navbar>
</view>
<view class="mt-24rpx text-center font-400 text-30rpx leading-42rpx text-[#303133]" v-if="rechargeList.length == 0">
当前平台暂无充值活动
</view>
<view class="mt-24rpx mx-30rpx" v-if="rechargeList.length > 0">
<view class="ml-70rpx flex items-center">
<view class="font-400 text-30rpx leading-42rpx text-[#303133]">
充值活动
</view>
</view>
<view class="mt-32rpx recharge-radio" >
<wd-radio-group v-model="rechargeValue">
<view
class="bg-white rounded-16rpx mt-20rpx px-30rpx py-28rpx flex items-center justify-between border border-2rpx border-solid border-[#FFF]"
:class="{acitve: item.id === rechargeValue }"
v-for="item in rechargeList" :key="item.id"
@click="rechargeValue = item.id">
<view class="text-28rpx text-[#606266] leading-40rpx flex items-center">
<view class="text-36rpx leading-50rpx text-[#121212] mr-24rpx">{{ item.price }}</view>
<view class="flex items-center">
<view class="w-44rpx h-44rpx rounded-44rpx bg-[#FF5951] text-[#fff] text-30rpx text-center leading-44rpx mr-18rpx"></view>
<view class="font-bold text-32rpx leading-40rpx text-[#FF5951]">{{ item.gift_price }}</view>
</view>
</view>
<view class="flex items-center">
<wd-radio :value="item.id" checked-color="#4C9F44" size='large' shape="dot"></wd-radio>
</view>
</view>
</wd-radio-group>
</view>
<view class="fixed left-0 right-0 bottom-92rpx z-2 bg-[#4C9F44] text-[#fff] flex justify-center items-center h-90rpx rounded-8rpx mx-60rpx" @click="Recharge.handleRecharge">
充值
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { PayList, PayCategory, PayValue, PayOrderType, PayOrderSource, PayValueMap } from '@/utils/pay'
import { teaRoomRecharge, getRechargeActivity } from '@/api/tea-room'
import { wechatPay } from '@/hooks/usePay'
import { createRechargeOrder, newPrePay } from '@/api/pay'
import { useToast } from 'wot-design-uni'
const toast = useToast()
// 门店ID
const storeId = ref<number>(0)
const rechargeList = ref<Array<{
id: number
price: number
gift_price: number
title: string
}>>([]) // 充值活动列表
const rechargeValue = ref<number>(0) // 充值活动选择
onLoad((args) => {
storeId.value = Number(args.storeId) || 0
if (storeId.value) {
Recharge.handleInit()
}
})
const Recharge = {
/**
* 充值活动列表
*/
handleInit: async () => {
const res = await getRechargeActivity({store_id: storeId.value})
rechargeList.value = res || []
},
/**
* 购买套餐
*/
handleRecharge: async () => {
if (rechargeValue.value === 0) {
toast.show('请选择充值套餐')
return
}
toast.loading({
loadingType: 'ring',
loadingColor: '#4C9F44',
msg: '操作中...'
})
try {
// 先请求充值接口
const res = await createRechargeOrder({id: rechargeValue.value})
if (res.order_id) {
// 预支付
const pay = await newPrePay({
from: PayValueMap[PayValue.WeChatPay],
order_id: res.order_id, //如果是续单的话则用续单的订单ID
pay_way: PayValue.WeChatPay,
order_source: PayOrderSource.MINI, //订单来源1-小程序; 2-h5; 3app
order_type: PayOrderType.TeaRoomRecharge, // 茶艺师订单
})
wechatPay(pay.config).then((res) => {
uni.hideLoading()
if (res === 'success') {
setTimeout(() => {
toast.success('支付成功')
}, 100);
return
} else if (res === 'cancel') {
setTimeout(() => {
toast.show('已取消支付')
}, 100);
return
} else {
setTimeout(() => {
toast.show('支付失败,请重试')
}, 100);
return
}
}).catch(() => {
toast.close()
})
} else {
toast.close()
}
} catch (error) {
toast.close()
}
}
}
</script>
<style lang="scss">
page {
background: $cz-page-background;
}
.pay-tabs {
:deep() {
.wd-tabs__line {
background-color: #4C9F44;
}
}
}
.recharge-radio {
:deep() {
.wd-radio-group {
background-color: transparent !important;
}
.wd-radio {
margin-top: 0 !important;
}
}
}
.acitve {
background: #FFF4F4;
border: 2rpx solid #FF5951;
}
</style>

View File

@ -11,191 +11,147 @@
<template>
<view class="bg">
<view>
<navbar title="充值" custom-class='!bg-[#F6F7F8]'></navbar>
<navbar title="平台充值" custom-class='!bg-[#F6F7F8]'></navbar>
</view>
<view class="mt-24rpx mx-30rpx">
<view class="mt-24rpx text-center font-400 text-30rpx leading-42rpx text-[#303133]" v-if="rechargeList.length == 0">
当前平台暂无充值活动
</view>
<view class="mt-24rpx mx-30rpx" v-if="rechargeList.length > 0">
<view class="ml-70rpx flex items-center">
<view class="mr-72rpx font-400 text-30rpx leading-42rpx text-[#303133]">
充值方式
</view>
<view class="flex items-center">
<view class="flex items-center mr-20rpx">
<wd-img width="50rpx" height="50rpx" :src="`${OSS}icon/icon_weichat.png`"></wd-img>
</view>
<view class="font-bold text-32rpx leading-44rpx text-[#303133]">微信</view>
<view class="font-400 text-30rpx leading-42rpx text-[#303133]">
充值活动
</view>
</view>
<view class="bg-white rounded-16rpx px-38rpx py-28rpx mt-28rpx">
<view class="font-400 text-28rpx leading-40rpx text-[#303133]">
充值方式
</view>
<view class="flex items-center">
<view class="font-400 text-36rpx leading-50rpx text-[#303133] mr-20rpx mt-40rpx"></view>
<view class="mt-44rpx">
<wd-input type="text" v-model="rechargeMoney" placeholder="请输入金额" no-border custom-input-class="!h-80rpx !text-48rpx !leading-66rpx" >
</wd-input>
<view class="mt-32rpx recharge-radio" >
<wd-radio-group v-model="rechargeValue">
<view
class="bg-white rounded-16rpx mt-20rpx px-30rpx py-28rpx flex items-center justify-between border border-2rpx border-solid border-[#FFF]"
:class="{acitve: item.id === rechargeValue }"
v-for="item in rechargeList" :key="item.id"
@click="rechargeValue = item.id">
<view class="text-28rpx text-[#606266] leading-40rpx flex items-center">
<view class="text-36rpx leading-50rpx text-[#121212] mr-24rpx">{{ item.price }}</view>
<view class="flex items-center">
<view class="w-44rpx h-44rpx rounded-44rpx bg-[#FF5951] text-[#fff] text-30rpx text-center leading-44rpx mr-18rpx"></view>
<view class="font-bold text-32rpx leading-40rpx text-[#FF5951]">{{ item.gift_price }}</view>
</view>
</view>
<view class="flex items-center">
<wd-radio :value="item.id" checked-color="#4C9F44" size='large' shape="dot"></wd-radio>
</view>
</view>
</view>
</wd-radio-group>
</view>
<!-- 推广方式 -->
<!-- <view class="mt-60rpx">
<view class="mx-30rpx text-32rpx leading-44rpx text-[#303133]">
<text class="mr-12rpx">推广方式</text>
<text class="text-26rpx leading-36rpx text-[#909399]">(选填)</text>
</view>
<view class="bg-white rounded-16rpx py-26rpx mt-28rpx pay-tabs">
<wd-tabs v-model="tab" swipeable slidable="always">
<wd-tab title="门店">
<view>
<wd-gap height="2rpx" bg-color="#F6F7F9"></wd-gap>
</view>
<view class="mx-30rpx mt-34rpx flex items-center">
<view class="font-bold text-30rpx leading-42rpx text-[#303133] mr-28rpx">门店推广</view>
<view class="bg-[#F8F9FA] px-28rpx p-20rpx text-30rpx text-[#C9C9C9] h-80rpx rounded-8rpx flex items-center flex-1" @click="showStorePopup = true">
<text class="mr-14rpx">请选择门店</text>
<wd-icon name="arrow-down" size="22rpx"></wd-icon>
</view>
</view>
</wd-tab>
<wd-tab title="茶艺师">
<view>
<wd-gap height="2rpx" bg-color="#F6F7F9"></wd-gap>
</view>
<view class="mx-30rpx mt-34rpx flex items-center">
<view class="font-bold text-30rpx leading-42rpx text-[#303133] mr-28rpx">茶艺师推广</view>
<view class="flex items-center flex-1">
<wd-input type="text" v-model="person" no-border custom-class="!bg-[#F6F7F8] !rounded-8rpx w-full" custom-input-class="!px-32rpx !h-80rpx">
</wd-input>
</view>
</view>
</wd-tab>
</wd-tabs>
</view>
</view> -->
<view class="fixed left-0 right-0 bottom-92rpx z-2 bg-[#4C9F44] text-[#fff] flex justify-center items-center h-90rpx rounded-8rpx mx-60rpx" @click="buy.handleRecharge">
确定充值
<view class="fixed left-0 right-0 bottom-92rpx z-2 bg-[#4C9F44] text-[#fff] flex justify-center items-center h-90rpx rounded-8rpx mx-60rpx" @click="Recharge.handleRecharge">
充值
</view>
</view>
<!-- 推广方式 -->
<wd-popup v-model="showStorePopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
<view class="relative">
<view class="absolute top-18rpx right-30rpx" @click="showStorePopup = 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="buy.handleChooseStore(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>
</view>
</template>
<script lang="ts" setup>
import { PayList, PayCategory, PayValue, PayOrderType, PayOrderSource } from '@/utils/pay'
import { teaRoomRecharge } from '@/api/tea-room'
import { PayList, PayCategory, PayValue, PayOrderType, PayOrderSource, PayValueMap } from '@/utils/pay'
import { teaRoomRecharge, getRechargeActivity } from '@/api/tea-room'
import { wechatPay } from '@/hooks/usePay'
import { prePay, balancePay } from '@/api/pay'
import { toast } from '@/utils/toast'
import { createRechargeOrder, newPrePay } from '@/api/pay'
import { useToast } from 'wot-design-uni'
const pay = ref<number>(PayValue.WeChatPay) // 默认微信支付方式
const OSS = inject('OSS')
const toast = useToast()
// 推广方式
const tab = ref<number>(0)
const person = ref<string>('') // 个人推广码
const showStorePopup = ref<boolean>(false) // 显示门店列表弹窗
const rechargeMoney = ref<string>('')
// 门店ID
const storeId = ref<number>(0)
const rechargeList = ref<Array<{
id: number
price: number
gift_price: number
title: string
}>>([]) // 充值活动列表
const rechargeValue = ref<number>(0) // 充值活动选择
onLoad(() => {
onLoad((args) => {
storeId.value = Number(args.storeId) || 0
if (storeId.value) {
Recharge.handleInit()
}
})
const buy = {
// 选择门店
handleChooseStore: (item: any) => {
const Recharge = {
/**
* 充值活动列表
*/
handleInit: async () => {
const res = await getRechargeActivity({store_id: storeId.value})
rechargeList.value = res || []
},
// 确定充值
handleConfirmRecharge: () => {
uni.navigateTo({
url: '/pages/notice/pay?type=vip'
})
},
// 充值
/**
* 购买套餐
*/
handleRecharge: async () => {
if (!rechargeMoney.value) {
toast.info('请输入充值金额')
if (rechargeValue.value === 0) {
toast.show('请选择充值套餐')
return
}
uni.showLoading({ title: '支付中...' })
toast.loading({
loadingType: 'ring',
loadingColor: '#4C9F44',
msg: '操作中...'
})
try {
// 先请求充值接口
const res = await teaRoomRecharge(Number(rechargeMoney.value))
const res = await createRechargeOrder({id: rechargeValue.value})
if (res.order_id) {
// 预支付
const pay = await newPrePay({
from: PayValueMap[PayValue.WeChatPay],
order_id: res.order_id, //如果是续单的话则用续单的订单ID
pay_way: PayValue.WeChatPay,
order_source: PayOrderSource.MINI, //订单来源1-小程序; 2-h5; 3app
order_type: PayOrderType.TeaRoomRecharge, // 茶艺师订单
})
// 预支付
const pay = await prePay({
from: 'recharge',
order_id: res.order_id,
pay_way: 2,
order_source: PayOrderSource.MINI, //订单来源1-小程序; 2-h5; 3app
order_type: PayOrderType.Recharge,
store_id: 0
})
wechatPay(pay.pay.config).then((res) => {
uni.hideLoading()
if (res === 'success') {
toast.success('支付成功')
setTimeout(() => {
uni.navigateBack()
}, 800)
return
} else if (res === 'cancel') {
toast.info('已取消支付')
return
} else {
toast.info('支付失败,请重试')
return
}
}).catch(() => {
uni.hideLoading()
toast.info('支付失败,请重试')
})
wechatPay(pay.config).then((res) => {
uni.hideLoading()
if (res === 'success') {
setTimeout(() => {
toast.success('支付成功')
}, 100);
return
} else if (res === 'cancel') {
setTimeout(() => {
toast.show('已取消支付')
}, 100);
return
} else {
setTimeout(() => {
toast.show('支付失败,请重试')
}, 100);
return
}
}).catch(() => {
toast.close()
})
} else {
toast.close()
}
} catch (error) {
uni.hideLoading()
toast.info('支付失败,请重试')
toast.close()
}
}
}
</script>
<style lang="scss" scoped>
<style lang="scss">
page {
background: $cz-page-background;
}
@ -207,4 +163,21 @@
}
}
}
.recharge-radio {
:deep() {
.wd-radio-group {
background-color: transparent !important;
}
.wd-radio {
margin-top: 0 !important;
}
}
}
.acitve {
background: #FFF4F4;
border: 2rpx solid #FF5951;
}
</style>

View File

@ -83,29 +83,14 @@
</view>
</view>
</template>
<template #right>
<view class="flex items-center" :style="{ paddingRight: rightPadding }">
<view class="mr-16rpx flex items-center" @click="Detail.handleCollect">
<template v-if="info.collect > 0">
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc_s.png`"></wd-img>
</template>
<template v-else>
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc.png`"></wd-img>
</template>
</view>
<!-- <view @click="Detail.handleShare" class="flex items-center">
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_share.png`"></wd-img>
</view> -->
</view>
</template>
</navbar>
</view>
<view class="pb-30rpx bg-white">
<!-- 轮播图 -->
<view class="mx-30rpx">
<wd-swiper value-key="image" height="660rpx" :indicator="{ type: 'dots-bar' }" :list="info.image_arr"
imageMode="aspectFit" @click="Detail.handlePreviewImage"></wd-swiper>
<wd-swiper value-key="image" height="400rpx" :indicator="{ type: 'dots-bar' }" :list="info.image_arr"
mode="aspectFit" @click="Detail.handlePreviewImage"></wd-swiper>
</view>
<!-- 昵称显示 -->
@ -391,7 +376,7 @@
<script lang="ts" setup>
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import { useMessage } from 'wot-design-uni'
import { getTeaSpecialistDetail, collectTeaSpecialist } from '@/api/tea-specialist'
import { getTeaSpecialistDetail } from '@/api/tea-specialist'
import { ITeaSpecialistDetailsFields } from '@/api/types/tea'
import type { ITeaSpecialistRewardAmountsResult } from '@/api/types/tea'
import { toast } from '@/utils/toast'
@ -401,7 +386,6 @@ import { useUserStore } from '@/store'
import type { IUserInfoVo } from '@/api/types/login'
const OSS = inject('OSS')
const rightPadding = inject('capsuleOffset')
// tab
const tab = ref<number>(0)
@ -436,7 +420,6 @@ const info = ref({
license_img: '', // 营业执照图片
health_certificate: '', // 健康证图片
state: 0, // 茶艺师状态 0可约 1工作中 2不可约
collect: 0, // 是否收藏
})
const latitude = ref<number>(0) // 纬度
const longitude = ref<number>(0) // 经度
@ -512,7 +495,6 @@ const Detail = {
*/
handleGetTeaSpecialistDetail: async () => {
const res = await getTeaSpecialistDetail({
user_id: userInfo.value.id,
team_user_id: id.value,
latitude: uni.getStorageSync('latitude') || import.meta.env.VITE_DEFAULT_LATITUDE,
longitude: uni.getStorageSync('longitude') || import.meta.env.VITE_DEFAULT_LONGITUDE,
@ -521,23 +503,16 @@ const Detail = {
},
/**
* 处理收藏
* TODO 处理收藏-暂时不要
*/
handleCollect: async () => {
if (!userInfo.value.id) {
toast.info('请先登录')
router.navigateTo('/pages/login/login', 200)
}
await Detail.handleGetTeaSpecialistDetail()
// let status = info.collect == 0 ? 1 : 0
// await collectTeaSpecialist({
// id: id.value,
// status
// })
let status = info.value.collect == 0 ? 1 : 0
await collectTeaSpecialist({
id: id.value,
status
})
info.value.collect = status
// info.collect = info.collect == 0 ? 1 : 0
},
/**

View File

@ -9,63 +9,6 @@
<template>
<view class="home-bg">
<!-- 茶艺师-筛选 -->
<wd-popup v-model="showFilterPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
<view class="relative">
<view class="absolute top-18rpx right-30rpx" @click="showFilterPopup = 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>
<view class="">
<!-- 性别筛选 -->
<view class="mx-30rpx mb-30rpx">
<view class="text-32rpx leading-44rpx text-#303133">茶艺师性别</view>
<view class="flex items-center mt-28rpx">
<view class="h-60rpx w-178rpx rounded-8rpx flex items-center justify-center mr-20rpx"
:class="gender === '1' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="List.handleGenderChange('1')">
<text class="text-26rpx leading-36rpx">男</text>
</view>
<view class="h-60rpx w-178rpx rounded-8rpx flex items-center justify-center"
:class="gender === '2' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="List.handleGenderChange('2')">
<text class="text-26rpx leading-36rpx">女</text>
</view>
</view>
</view>
<!-- 服务方式筛选 -->
<view class="mx-30rpx mb-30rpx">
<view class="text-32rpx leading-44rpx text-#303133">服务方式</view>
<view class="flex items-center mt-28rpx">
<view class="h-60rpx w-178rpx rounded-8rpx flex items-center justify-center mr-20rpx"
:class="serverType === '3' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="List.handleServerTypeChange('3')">
<text class="text-26rpx leading-36rpx">全部服务</text>
</view>
<view class="h-60rpx w-178rpx rounded-8rpx flex items-center justify-center mr-20rpx"
:class="serverType === '1' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="List.handleServerTypeChange('1')">
<text class="text-26rpx leading-36rpx">到店服务</text>
</view>
<view class="h-60rpx w-178rpx rounded-8rpx flex items-center justify-center"
:class="serverType === '2' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="List.handleServerTypeChange('2')">
<text class="text-26rpx leading-36rpx">上门服务</text>
</view>
</view>
</view>
</view>
<view class="pb-22rpx mt-100rpx mx-30rpx flex justify-between items-center text-[32rpx] text-center">
<view class='bg-[#F6F7F8] text-[#303133] rounded-8rpx h-90rpx leading-90rpx w-[50%] mr-28rpx' @click="List.handleResetFilter">清空</view>
<view class='bg-[#4C9F44] text-[#fff] rounded-8rpx h-90rpx leading-90rpx w-[50%]' @click="List.handleConfirmFilter">确认</view>
</view>
</view>
</wd-popup>
<view class="home-bg w-[100%] sticky top-0 left-0 z-100">
<wd-navbar safeAreaInsetTop :bordered="false" custom-style="background-color: #fff !important;">
<template #left>
@ -102,42 +45,13 @@
<!-- 茶艺师列表 -->
<view class="level-bg pt-28rpx">
<!-- 茶艺师等级筛选 -->
<view class="">
<view
class="flex items-center text-#303133 overflow-x-auto whitespace-nowrap ml-30rpx mb-20rpx tea-level-scrollbar">
<view v-for="(item, index) in TeaSpecialistLevels" :key="index"
class="h-64rpx rounded-12rpx px-24rpx py-12rpx flex items-center justify-center font-400 text-28rpx mr-20rpx"
:class="selectedLevel.includes(item.level) ? 'border-2rpx border-solid border-[#4C9F44] text-[#4C9F44] bg-[#fff]' : 'bg-[#FFF] text-[#606266]'"
@click="List.handleToggleTeaSpecialistLevel(item.level)">
{{ item.label }}
</view>
</view>
<view class="mx-30rpx mb-30rpx">
<view class="flex items-center justify-between">
<view class="flex items-center">
<view class="mr-20rpx">
<wd-checkbox v-model="condition1" shape="square" checked-color="#4C9F44" @change="List.handleRadioClick('condition1', 1)">
<text class="text-[#909399]">只看可约</text>
</wd-checkbox>
</view>
<view class="mr-20rpx">
<wd-checkbox v-model="condition3" shape="square" checked-color="#4C9F44" @change="List.handleRadioClick('condition3', 3)">
<text class="text-[#909399]">只看工作中</text>
</wd-checkbox>
</view>
<view>
<wd-checkbox v-model="condition2" shape="square" checked-color="#4C9F44" @change="List.handleRadioClick('condition2', 2)">
<text class="text-[#909399]">只看不可约</text>
</wd-checkbox>
</view>
</view>
<view class="flex items-center" @click="showFilterPopup = true">
<wd-icon name="filter1" size="32rpx" color="#909399"></wd-icon>
<view class="text-[#909399]">筛选</view>
</view>
</view>
<view
class="flex items-center text-#303133 overflow-x-auto whitespace-nowrap ml-30rpx mb-30rpx tea-level-scrollbar">
<view v-for="(item, index) in TeaSpecialistLevels" :key="index"
class="h-64rpx rounded-12rpx px-24rpx py-12rpx flex items-center justify-center font-400 text-28rpx mr-20rpx"
:class="selectedLevel.includes(item.level) ? 'border-2rpx border-solid border-[#4C9F44] text-[#4C9F44] bg-[#fff]' : 'bg-[#FFF] text-[#606266]'"
@click="List.handleToggleTeaSpecialistLevel(item.level)">
{{ item.label }}
</view>
</view>
@ -146,8 +60,7 @@
<view class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx relative"
v-for="(item, index) in list" :key="index">
<view class="mr-28rpx relative z-2" @click="List.handlePreviewImage(item.image)">
<wd-img width="260rpx" height="320rpx" :src="item.image" mode="aspectFill"
radius="10rpx"></wd-img>
<wd-img width="260rpx" height="320rpx" :src="item.image" mode="aspectFill" radius="10rpx"></wd-img>
<view
class="tea-specialist-time absolute z-3 top-26rpx left-0 bg-[#4C9F44] text-[#fff] font-400 text-18rpx flex items-center justify-center">
<text v-if="item.state == 0">可约</text>
@ -160,13 +73,9 @@
<view class="font-bold text-[#303133] text-30rpx leading-42rpx mr-12rpx">
{{ item.name }}
</view>
<view class="tea-specialist-level-badge flex items-center shrink-0 mr-12rpx">
<text class="tea-specialist-level-badge__text ml-6rpx">{{ GetTeaSpecialistLevelLabel(item.level) }}</text>
</view>
<view class="flex items-center">
<wd-icon name="star-on" size="22rpx" color="#FF5951"></wd-icon>
<view class="font-400 text-24rpx text-[#FF5951] leading-34rpx ml-6rpx">{{ item.star }}
</view>
<view class="font-400 text-24rpx text-[#FF5951] leading-34rpx ml-6rpx">{{ item.star }}</view>
</view>
</view>
@ -193,9 +102,10 @@
</view>
<view class="flex flex-wrap items-center mt-14rpx mb-24rpx">
<view class="mr-8rpx px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx mb-14rpx"
:style="List.handleGetLabelStyle(Number(index))" v-for="(label, index) in item.label"
:key="index">
<view
class="mr-8rpx px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx mb-14rpx"
:style="List.handleGetLabelStyle(Number(index))"
v-for="(label, index) in item.label" :key="index">
{{ label.label_name }}
</view>
</view>
@ -207,8 +117,7 @@
<wd-img :src="`${OSS}icon/icon_store_cert2.png`" width="30rpx"
height="30rpx"></wd-img>
</view>
<text class="ml-8rpx font-400 text-24rpx leading-4rpx"
:class="item.company_status ? 'text-#4C9F44' : 'text-#303133'">
<text class="ml-8rpx font-400 text-24rpx leading-4rpx" :class="item.company_status ? 'text-#4C9F44' : 'text-#303133'">
{{ item.company_abv }}
</text>
</view>
@ -216,7 +125,7 @@
<view class="flex items-center font-400 text-24rpx leading-34rpx text-#92928C">距您{{
item.distance
}}km</view>
}}km</view>
</view>
<view
@ -242,7 +151,7 @@ import { router, previewImage } from '@/utils/tools'
import { getTeaSpecialist } from '@/api/tea-specialist'
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import type { ITeaSpecialistResult } from '@/api/types/tea-specialist'
import { TeaSpecialistLevelValue, TeaSpecialistLevels, GetTeaSpecialistLevelLabel } from '@/utils/teaSpecialist'
import { TeaSpecialistLevelValue, TeaSpecialistLevels } from '@/utils/teaSpecialist'
const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight')
@ -267,9 +176,8 @@ const upOption = {
const orderStatus = ref<string>('')
const list = ref<Array<any>>([]) // 茶室列表
const keywords = ref<string>('') // 搜索关键词
const cityId = ref<number>(0)
onLoad(async () => {
console.log("🚀 ~ 213:", 213)
uni.$on('refreshTeaSpecialist', () => {
list.value = []
getMescroll().resetUpScroll()
@ -288,15 +196,6 @@ onShareAppMessage(() => {
}
})
// 筛选条件(单选)
const condition = ref<string>('') // 当前选中的筛选条件
const condition1 = ref<boolean>(false)
const condition2 = ref<boolean>(false)
const condition3 = ref<boolean>(false)
const showFilterPopup = ref<boolean>(false)
const gender = ref<string>('')
const serverType = ref<string>('')
const List = {
handleGetLabelStyle: (index: number) => {
const firstThreeStyles = [
@ -319,10 +218,7 @@ const List = {
latitude: uni.getStorageSync('latitude') || import.meta.env.VITE_DEFAULT_LATITUDE,
longitude: uni.getStorageSync('longitude') || import.meta.env.VITE_DEFAULT_LONGITUDE,
search: keywords.value,
server_type: serverType.value || '',
state: condition.value || 0,
gender: gender.value || '',
city_id: uni.getStorageSync('cityId') || 0,
server_type: 0
}
getTeaSpecialist(filter).then((res: ITeaSpecialistResult) => {
@ -361,75 +257,6 @@ const List = {
List.handleSearch()
},
/**
* 处理单选checkbox点击模拟单选行为
*/
handleRadioClick: (type: string, value: number) => {
if (type === 'condition1') {
if (condition1.value) {
condition.value = String(value)
condition2.value = false
condition3.value = false
} else {
condition.value = ''
}
} else if (type === 'condition2') {
if (condition2.value) {
condition.value = String(value)
condition1.value = false
condition3.value = false
} else {
condition.value = ''
}
} else if (type === 'condition3') {
if (condition3.value) {
condition.value = String(value)
condition1.value = false
condition2.value = false
} else {
condition.value = ''
}
}
List.handleSearch()
},
/**
* 重置茶艺师筛选
*/
handleResetFilter: () => {
condition1.value = false
condition2.value = false
condition3.value = false
condition.value = ''
selectedLevel.value = []
gender.value = ''
serverType.value = ''
showFilterPopup.value = false
List.handleSearch()
},
/**
* 确认筛选
*/
handleConfirmFilter: () => {
showFilterPopup.value = false
List.handleSearch()
},
/**
* 性别筛选切换
*/
handleGenderChange: (value: string) => {
gender.value = gender.value === value ? '' : value
},
/**
* 服务方式筛选切换
*/
handleServerTypeChange: (value: string) => {
serverType.value = serverType.value === value ? '' : value
},
/**
* 搜索茶艺师列表
*/
@ -500,34 +327,9 @@ page {
height: 38rpx;
}
.tea-specialist-level-badge {
height: 40rpx;
padding: 0 14rpx 0 8rpx;
border-radius: 999rpx;
background: linear-gradient(135deg, #f7fbf4 0%, #e5f5de 100%);
border: 1rpx solid rgba(76, 159, 68, 0.18);
box-shadow: 0 6rpx 16rpx rgba(76, 159, 68, 0.08);
}
.tea-specialist-level-badge__text {
color: #2f7d32;
font-size: 22rpx;
line-height: 22rpx;
font-weight: 600;
letter-spacing: 2rpx;
}
.level-bg {
background: linear-gradient(180deg, #E9FFF1 0%, #F6F7F8 100%) no-repeat;
background-size: 100% 220rpx;
border-radius: 20rpx 20rpx 0rpx 0rpx;
:deep(.wd-radio-group) {
background: transparent !important;
}
:deep(.wd-checkbox__label) {
margin-left: 14rpx !important;
}
}
</style>

View File

@ -14,7 +14,7 @@
<!-- 上门服务-预定时间 -->
<wd-popup v-model="showReservePopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
<view class="relative">
<view class="absolute top-18rpx right-30rpx" @tap.stop.prevent="Door.handleCloseReservePopup">
<view class="absolute top-18rpx right-30rpx" @click="showReservePopup = 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>
@ -59,8 +59,8 @@
</view>
<view class="pb-22rpx mt-40rpx mx-30rpx flex justify-between items-center text-[32rpx] text-center">
<view class='bg-[#F6F7F8] text-[#303133] rounded-8rpx h-90rpx leading-90rpx w-[50%] mr-28rpx' @tap.stop.prevent="Door.handleResetTime">重置</view>
<view class='bg-[#4C9F44] text-[#fff] rounded-8rpx h-90rpx leading-90rpx w-[50%]' @tap.stop.prevent="Door.handleConfirmHour">确定({{ totalHour }}小时)</view>
<view class='bg-[#F6F7F8] text-[#303133] rounded-8rpx h-90rpx leading-90rpx w-[50%] mr-28rpx' @click="Door.handleResetTime">重置</view>
<view class='bg-[#4C9F44] text-[#fff] rounded-8rpx h-90rpx leading-90rpx w-[50%]' @click="Door.handleConfirmHour">确定({{ totalHour }}小时)</view>
</view>
</view>
</wd-popup>
@ -151,7 +151,7 @@
<scroll-view scroll-y class="h-900rpx">
<view class="">
<!-- 服务人数 -->
<!-- <view class="mx-60rpx mb-56rpx">
<view class="mx-60rpx mb-56rpx">
<view class="text-32rpx leading-44rpx text-#303133">服务人数</view>
<view class="flex items-center justify-between mt-28rpx">
<view class="text-28rpx leading-40rpx text-#303133">服务人数</view>
@ -159,21 +159,6 @@
<wd-input-number v-model="servicePeople"/>
</view>
</view>
</view> -->
<view class="mx-60rpx mb-56rpx">
<view class="text-32rpx leading-44rpx text-#303133">服务人数</view>
<view class="flex items-center mt-28rpx">
<view class="h-60rpx w-178rpx rounded-30rpx flex items-center justify-center mr-20rpx"
:class="servicePeople === '1-3' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="Reserve.servicePeopleChange('1-3')">
<text class="text-26rpx leading-36rpx">1人~3人</text>
</view>
<view class="h-60rpx w-178rpx rounded-30rpx flex items-center justify-center"
:class="servicePeople === '4-6' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#606266]'"
@click="Reserve.servicePeopleChange('4-6')">
<text class="text-26rpx leading-36rpx">4人~6人</text>
</view>
</view>
</view>
<!-- 茶具使用 -->
@ -359,11 +344,10 @@
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="Reserve.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="text-[26rpx] text-[#606266] leading-36rpx">优惠券</view>
<view class="flex items-center">
<view class="text-[28rpx] text-[#909399] leading-40rpx w-430rpx line-1 text-right">
<template v-if="selectedCoupon?.id > 0">
<text class="bg-#FEF1F0 text-#FF5951 rounded-6rpx text-center text-22rpx leading-40rpx px-10rpx py-2rpx">待使用</text>
{{ selectedCoupon.name }}
</template>
<template v-else>
@ -487,7 +471,7 @@
// 茶艺服务
const showTeaServicePopup = ref<boolean>(false) // 显示门店列表弹窗
const servicePeople = ref<string>('1-3') // 服务人数
const servicePeople = ref<number>(1) // 服务人数
const teaList = ref<ITeaTypeListResult[]>([]) // 茶叶列表
const selectedTea = ref<Array<any>>([]) // 选择的茶叶
const selectedTeaTxt = ref<Array<any>>([]) // 选择的茶叶文本
@ -619,14 +603,6 @@
})
const Reserve = {
/**
* 选择服务人数
* @param type 人数范围 '1-3' 或 '4-6'
*/
servicePeopleChange: (type: string) => {
servicePeople.value = type
},
/**
* 初始化-获取茶叶列表
*/
@ -853,7 +829,7 @@
* 重置差茶艺服务
*/
handleResetTeaService: () => {
servicePeople.value = '1-3'
servicePeople.value = 1
selectedTea.value = []
teaUsageValue.value = 0
},
@ -1050,13 +1026,6 @@
return `${year}-${month}-${day} ${hour}:${minute}`
},
handleCloseReservePopup: () => {
uni.hideKeyboard()
setTimeout(() => {
showReservePopup.value = false
}, 50)
},
/**
* 重置预定时间
*/
@ -1093,7 +1062,7 @@
// },
// })
// }
Door.handleCloseReservePopup()
showReservePopup.value = false
// 计算费用明细
costParams.value.hours = totalHour.value

View File

@ -5,22 +5,24 @@ import { requestInterceptor } from './http/interceptor'
import { routeInterceptor } from './router/interceptor'
import NavBar from '@/components/Navbar.vue'
import './utils/mtj-wx-sdk.config'
import './utils/mtj-wx-sdk'
import store from './store'
import '@/style/index.scss'
import 'virtual:uno.css'
import { getNavBarHeight, getCapsuleOffset } from '@/utils/index'
// import uma from './uma';
export function createApp() {
const app = createSSRApp(App)
/* 注册全局组件 */
app.component('NavBar', NavBar) // 注册全局组件
app.use(store)
app.use(routeInterceptor)
app.use(requestInterceptor)
// app.use(uma)
app.use(VueQueryPlugin)
app.provide('OSS', 'https://chaz.oss-cn-shanghai.aliyuncs.com/fronted/')

View File

@ -431,15 +431,6 @@
"navigationStyle": "custom"
}
},
{
"path": "wallet/recharge-store",
"type": "page",
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "wallet/recharge",
"type": "page",

View File

@ -11,49 +11,21 @@
<template>
<view class="">
<!-- 领取优惠券 -->
<wd-overlay :show="showCoupon" @click="Index.handleCloseCoupon('coupon1')">
<wd-overlay :show="showCoupon" @click="showCoupon = false">
<view class="flex flex-col justify-center items-center h-100%">
<view class="w-652rpx h-590rpx relative" >
<wd-img :src="`${OSS}images/home/home_image10.png`" width="100%" height="100%"></wd-img>
<view class="absolute top-200rpx left-1/2 transform -translate-x-1/2 flex flex-col items-center">
<view class="mt-220rpx" @click.stop="Index.handleCloseCoupon('coupon1')">
<view class="mt-220rpx" @click.stop="showCoupon = false">
<view class="h-90rpx relative">
<wd-img :src="`${OSS}images/home/home_image9.png`" width="342rpx" height="90rpx"></wd-img>
<view class="absolute top-20rpx left-1/2 transform -translate-x-1/2 flex flex-col items-center" @click.stop="Index.handleToGetCoupon('coupon1')">立即领取</view>
<view class="absolute top-20rpx left-1/2 transform -translate-x-1/2 flex flex-col items-center" @click.stop="Index.handleToGetCoupon">立即领取</view>
</view>
</view>
</view>
</view>
<view class="mt-80rpx" @click.stop="Index.handleCloseCoupon('coupon1')">
<wd-img :src="`${OSS}icon/icon_close2.png`" width="72rpx" height="72rpx"></wd-img>
</view>
</view>
</wd-overlay>
<!-- 领取20张20元优惠券 -->
<wd-overlay :show="showCoupon2" @click="Index.handleCloseCoupon('coupon2')">
<view class="flex flex-col justify-center items-center h-100%">
<view class="w-572rpx h-518rpx relative" >
<wd-img :src="`${OSS}images/home/home_image_20.png`" width="100%" height="100%"></wd-img>
<view class="absolute top-50rpx left-1/2 transform -translate-x-1/2">
<view class="text-[#FF5643] font-bold text-32rpx leading-42rpx text-center">通用优惠券</view>
<view class="text-[#E64545] font-bold flex items-end mt-20rpx">
<view class="text-52rpx mb-20rpx"></view>
<view class="text-102rpx">400</view>
</view>
</view>
<view class="absolute top-200rpx left-1/2 transform -translate-x-1/2 flex flex-col items-center">
<view class="mt-160rpx" @click.stop="Index.handleCloseCoupon('coupon2')">
<view class="h-90rpx relative" @click.stop="Index.handleToGetCoupon('coupon2')">
<wd-img :src="`${OSS}images/home/home_image9.png`" width="342rpx" height="90rpx"></wd-img>
<view class="absolute top-20rpx left-1/2 transform -translate-x-1/2 flex flex-col items-center">立即领取</view>
</view>
</view>
</view>
</view>
<view class="mt-80rpx" @click.stop="Index.handleCloseCoupon('coupon2')">
<view class="mt-80rpx" @click.stop="showCoupon = false">
<wd-img :src="`${OSS}icon/icon_close2.png`" width="72rpx" height="72rpx"></wd-img>
</view>
</view>
@ -89,9 +61,9 @@
></wd-swiper>
</view>
<view class="text-36rpx text-[#303133] leading-50rpx mx-30rpx mt-40rpx mb-32rpx font-bold" v-if="setting.status == 1">热门场景</view>
<view class="text-36rpx text-[#303133] leading-50rpx mx-30rpx mt-40rpx mb-32rpx font-bold">热门场景</view>
<view class="package-row px-30rpx" v-if="setting.status == 1">
<view class="package-row px-30rpx">
<view class="grid grid-cols-3 gap-x-0 gap-y-20rpx">
<view
v-for="(item, idx) in teaPackageList"
@ -120,8 +92,8 @@
</view>
<!-- 专属定制 -->
<view class="flex justify-center mt-24rpx" @click="router.navigateTo(`/bundle_b/pages/tea-specialist/list`)" v-if="setting.status == 1">
<wd-img :src="teaArtistEntrance" width="690rpx" height="200rpx" mode="scaleToFill" />
<view class="flex justify-center mt-24rpx" @click="router.navigateTo(`/bundle_b/pages/tea-specialist/list`)">
<wd-img :src="`${OSS}images/home/home_image_19.png`" width="690rpx" height="200rpx" mode="scaleToFill" />
</view>
</view>
@ -203,12 +175,11 @@
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import { LOCATION_DENY_TIME_KEY, handleEnsureLocationAuthHooks, LOCATION_DEFAULT_CITY, handleGetLocationCity, LOCATION_CITY_KEY, handleForceGetLocation } from '@/hooks/useLocation'
import { getHomeBannerList, getHomeCouponPopup, claimIndexCoupon, getTeaArtistEntrance } from '@/api/home'
import { getHomeBannerList, getHomeCouponPopup, claimIndexCoupon } from '@/api/home'
import { getTeaPackageList } from '@/api/tea-package'
import { getHomeTeaStoreList } from '@/api/tea-room'
import { useUserStore } from '@/store'
import { useToast } from 'wot-design-uni'
import { getSetting } from '@/api/tea-specialist'
const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight')
@ -247,18 +218,8 @@
// 套餐列表
const teaPackageList = ref<Array<any>>([])
// 优惠券状态
const couponStatus = ref<any>({})
// 显示优惠券弹窗
const showCoupon = ref<boolean>(false)
// 显示第2种优惠券弹窗
const showCoupon2 = ref<boolean>(false)
// 获取设置
const setting = ref<any>({})
// 茶艺师入口图
const teaArtistEntrance = ref<string>('')
const showCoupon = ref<boolean>(false)
onShow(async () => {
// if (canLocation) {
@ -290,18 +251,8 @@
if (userId) {
// 获取首页优惠券弹窗
const res = await getHomeCouponPopup()
couponStatus.value = res
if (Number(res.status) === 0) {
showCoupon.value = true
} else {
showCoupon.value = false
}
// 如果第一张优惠券的弹窗没有被触发(可能是因为用户关闭了第一个优惠券的弹窗),但是接口返回还可以领第二张优惠券,就继续显示第二个优惠券的弹窗(如果一下子都弹出来,用户可能会觉得烦,所以分开两个弹窗)
if (Number(res.status) !== 0 && Number(res.general_status) === 0 ) {
showCoupon2.value = true
} else {
showCoupon2.value = false
}
}
})
@ -324,9 +275,6 @@
latitude.value = location.latitude
longitude.value = location.longitude
// 删除city_id的缓存
uni.removeStorageSync('cityId')
Index.handleResetSearch()
})
@ -389,28 +337,14 @@
* 初始化首页数据
*/
handleInit: () => {
// 获取设置
getSetting().then(res => {
setting.value = res
})
// 获取轮播图
getHomeBannerList().then(res => {
swiperList.value = res.list.map(item => item.address)
})
// 获取茶艺师入口图
getTeaArtistEntrance().then(res => {
console.log("🚀 ~ res:", res)
// 如果接口返回的状态是1才显示茶艺师入口图
teaArtistEntrance.value = res.url
})
// 获取套餐列表
getTeaPackageList().then(res => {
teaPackageList.value = res
})
},
/**
@ -424,7 +358,6 @@
city_id.value = params.id
// latitude.value = params.latitude
// longitude.value = params.longitude
uni.setStorageSync('cityId', params.id)
Index.handleResetSearch()
})
router.navigateTo(`/pages/city/city?lat=${latitude.value}&lng=${longitude.value}`)
@ -478,16 +411,10 @@
/**
* 跳转领取优惠券页面
*/
handleToGetCoupon: async (type: string) => {
// 1是茶艺师优惠券2是茶馆优惠券
if (type === 'coupon1') {
await claimIndexCoupon(1)
showCoupon.value = false
router.navigateTo('/bundle_b/pages/tea-specialist/list')
} else if (type === 'coupon2') {
await claimIndexCoupon(6)
showCoupon2.value = false
}
handleToGetCoupon: async () => {
await claimIndexCoupon()
showCoupon.value = false
router.navigateTo('/bundle_b/pages/tea-specialist/list')
},
/**
@ -522,10 +449,6 @@
// const index = e.currentTarget.dataset.index
},
/**
* 排序
* @param type
*/
handleSort(type: 'smart' | 'distance' | 'sales' | 'open' | 'use') {
const userStore = useUserStore()
const userId = userStore.userInfo?.id
@ -554,22 +477,7 @@
*/
handlePreviewImage: (e: {index: number, item: any}) => {
previewImage(swiperList.value[e.index], swiperList.value)
},
/**
* 关闭优惠券
*/
handleCloseCoupon: (type: string) => {
if (type === 'coupon1') {
showCoupon.value = false
// 验证下,如果用户关闭了第一个优惠券的弹窗,如果还可以领第二个优惠券,就继续显示第二个优惠券的弹窗(如果一下子都弹出来,用户可能会觉得烦,所以分开两个弹窗)
if (Number(couponStatus.value.general_status) === 0 ) {
showCoupon2.value = true
}
} else if (type === 'coupon2') {
showCoupon2.value = false
}
}
}
}
</script>

View File

@ -46,10 +46,7 @@
<wd-checkbox v-model="agree" checked-color="#4C9F44" size="large"> </wd-checkbox>
</view>
<view class="font-400 text-26rpx leading-40rpx text-[#8F959E] ml-14rpx flex-1" @click="agree = !agree">
我已阅读并同意
<text class="text-[#4C9F44]" @click.stop="Login.handleToWebview('service')">服务协议</text>
<text class="text-[#4C9F44]" @click.stop="Login.handleToWebview('privacy')">隐私政策</text>
<text class="text-[#4C9F44]" @click.stop="Login.handleToAgreement()">茶址平台用户协议</text>未注册手机号登录后将自动你为您创建账号
我已阅读并同意 <text class="text-[#4C9F44]" @click.stop="Login.handleToWebview('service')">服务协议</text> <text class="text-[#4C9F44]" @click.stop="Login.handleToWebview('privacy')">隐私政策</text>未注册手机号登录后将自动你为您创建账号
</view>
</view>
</view>
@ -97,7 +94,7 @@
*/
handleLogin: async (e: object) => {
if (!agree.value) {
toast.info('请同意服务协议隐私政策、茶址平台用户协议')
toast.info('请同意服务协议隐私政策')
return
}
@ -185,31 +182,6 @@
handleToWebview: (type: string) => {
router.navigateTo(`/pages/webview/webview?type=${type}`)
},
// 跳转到茶址茶艺师入驻协议页面
handleToAgreement: () => {
const fileUrl = import.meta.env.VITE_SERVER_BASEURL + '/茶址平台用户协议.docx'
uni.downloadFile({
url: fileUrl,
success: (downloadRes) => {
if (downloadRes.statusCode === 200) {
uni.openDocument({
filePath: downloadRes.tempFilePath,
showMenu: true,
fail: (err) => {
console.error('打开文档失败:', err)
toast.info('打开文档失败,请稍后重试')
}
})
} else {
toast.info('下载协议失败')
}
},
fail: (err) => {
toast.info('下载协议失败,请稍后重试')
}
})
},
}
</script>

View File

@ -57,10 +57,10 @@
<view class="font-bold text-36rpx leading-50rpx"> {{ isLogin ? user.coupon_count : '- -' }}</view>
<view class="text-24rpx leading-34rpx">优惠券</view>
</view>
<view class="w-160rpx text-[#303133] text-center" @click="router.navigateTo('/bundle/collect/collect')">
<!-- <view class="w-160rpx text-[#303133] text-center" @click="router.navigateTo('/bundle/collect/collect')">
<view class="font-bold text-36rpx leading-50rpx"> {{ isLogin ? user.collect_count : '- -' }}</view>
<view class="text-24rpx leading-34rpx">收藏</view>
</view>
</view> -->
</view>
<view class="relative">
<view class="w-378rpx h-148rpx">
@ -116,7 +116,7 @@
<!-- <view class="mt-50rpx ml-24rpx">
<scroll-view class="w-[100%] whitespace-nowrap" :scroll-x="true" scroll-left="120">
<view class="scroll-item mr-20rpx" v-for="(item, index) in couponList" :key="index">
<view class="font-bold text-22rpx text-[#AF6400] leading-32rpx mt-6rpx">{{ item.type_id == 0 ? '通用券' : (item.type_id == 1 ? '茶艺师券' : '茶室券') }}</view>
<view class="font-bold text-22rpx text-[#AF6400] leading-32rpx mt-6rpx">{{ item.type_id == 1 ? '茶艺师券' : '茶室券' }}</view>
<view class="font-bold text-[#1C1C1D] leading-34rpx mt-8rpx">
<text class="text-24rpx">¥</text>
<text class="text-30rpx">{{ item.coupon_price }}</text>
@ -147,7 +147,7 @@
<view class="bg-white rounded-16rpx mx-30rpx mt-28rpx px-30rpx py-20rpx flex items-center justify-between" v-if="isLogin && couponList.length > 0">
<scroll-view class="w-[100%] whitespace-nowrap" :scroll-x="true" scroll-left="120">
<view class="scroll-item mr-20rpx" v-for="(item, index) in couponList" :key="index">
<view class="font-bold text-22rpx text-[#AF6400] leading-32rpx mt-6rpx">{{ item.type_id == 0 ? '通用券' : (item.type_id == 1 ? '茶艺师券' : '茶室券') }}</view>
<view class="font-bold text-22rpx text-[#AF6400] leading-32rpx mt-6rpx">{{ item.type_id == 1 ? '茶艺师券' : '茶室券' }}</view>
<view class="font-bold text-[#1C1C1D] leading-34rpx mt-8rpx">
<text class="text-24rpx">¥</text>
<text class="text-30rpx">{{ item.coupon_price }}</text>
@ -202,7 +202,7 @@
</view>
<!-- 茶艺师订单 -->
<view class="bg-white rounded-16rpx mx-30rpx mt-28rpx pb-34rpx" v-if="setting.status == 1">
<view class="bg-white rounded-16rpx mx-30rpx mt-28rpx pb-34rpx">
<view class="px-30rpx pt-30rpx py-24rpx">茶艺师订单</view>
<view class="flex relative px-30rpx">
<view v-for="(item, index) in teaReserveMenuList" :key="index">
@ -270,7 +270,6 @@
import { useUserStore } from '@/store'
import { getUserInfo, getMyCoupon, claimMyCoupon, getUserMember, getConfig } from '@/api/user'
import type { IUserResult } from '@/api/types/user'
import { getSetting } from '@/api/tea-specialist'
const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight')
@ -338,9 +337,6 @@
// 过期时间
const expireTime = ref<string>('')
// 获取设置
const setting = ref<any>({})
onShow(() => {
const userStore = useUserStore()
isLogin.value = userStore.isLoggedIn
@ -406,10 +402,6 @@
sheetMenu.value = [{ name: serviceMobile }]
}
})
getSetting().then(res => {
setting.value = res
})
},
/**

View File

@ -26,7 +26,7 @@
<view class="tabs">
<wd-tabs v-model="tab" swipeable slidable="always" @change="Reserve.handleChangeTab" :lazy="false">
<wd-tab title="茶室预约"></wd-tab>
<wd-tab title="茶艺师预约" v-if="setting.status == 1"></wd-tab>
<wd-tab title="茶艺师预约"></wd-tab>
</wd-tabs>
</view>
</view>
@ -57,7 +57,6 @@
import { router } from '@/utils/tools'
import { getTeaRoomOrderList } from '@/api/tea-room'
import { getTeaSpecialistOrderList } from '@/api/teaSpecialist-order'
import { getSetting } from '@/api/tea-specialist'
const OSS = inject('OSS')
const navbarHeight = Number(inject('navbarHeight')) + 42 + 14 // 42为tabs的高度 14是边距值
@ -66,9 +65,6 @@
const tab = ref<number>(0)
const reserveType = ref<number>(0) // 0:茶室预约 1:茶艺师预约
// 获取设置
const setting = ref<any>({})
// mescroll
const { mescrollInit, downCallback, getMescroll } = useMescroll(onPageScroll, onReachBottom) // 调用mescroll的hook
const downOption = {
@ -100,10 +96,6 @@
list.value = []
getMescroll().resetUpScroll()
})
getSetting().then(res => {
setting.value = res
})
})
onUnload(() => {

View File

@ -1,11 +0,0 @@
// #ifdef MP-WEIXIN
import uma from 'umtrack-wx';
uma.init({
appKey: '69e081af6f259537c799f90c',
useOpenid: false,
autoGetOpenid: false,
debug: true
});
// #endif
export default uma

View File

@ -0,0 +1,39 @@
/**
* @file 百度移动统计配置文件
*/
module.exports = {
/**
* 从百度移动统计获取的AppKey
* @type {string}
*/
appKey: 'd4a524dade',
/**
* 是否使用了插件
* @type {boolean}
*/
hasPlugin: false,
/**
* 是否获取当前的地理位置和速度信息
* @type {boolean}
*/
getLocation: false,
/**
* 是否获取组件滚动信息
* @type {boolean}
*/
getComponentScroll: false,
/**
* 是否开启了A/B 测试
* @type {boolean}
*/
hasABTest: false,
/**
* 是否开启热力图功能
* @type {boolean}
*/
hasHeatmap: false,
};

1
src/utils/mtj-wx-sdk.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -24,10 +24,3 @@ export const TeaSpecialistLevels = [
{ id: 1, value: 'gold', label: TeaSpecialistLevel.Gold, level: 4 },
// { id: 5, value: 'enthusiast', label: TeaSpecialistLevel.Enthusiast, level: 1 }
];
// 获取茶艺师等级标签
export function GetTeaSpecialistLevelLabel(level: number) {
const found = TeaSpecialistLevels.find(item => item.level == level)
return found ? found.label.slice(0, 2) : '未知';
}