调试茶艺师订单接口

This commit is contained in:
wangxiaowei
2026-01-03 01:40:12 +08:00
parent 66ee35285d
commit 3a31777431
18 changed files with 717 additions and 344 deletions

7
env/.env vendored
View File

@ -10,16 +10,17 @@ VITE_APP_PUBLIC_BASE=/
# 登录页面
VITE_LOGIN_URL = '/pages/login/login'
# 第一个请求地址
VITE_SERVER_BASEURL = 'https://76458.com'
# VITE_SERVER_BASEURL = 'https://76458.com'
VITE_SERVER_BASEURL = 'https://cz.stnav.com'
VITE_UPLOAD_BASEURL = 'https://76458.com/upload'
# h5是否需要配置代理
VITE_APP_PROXY=false
VITE_APP_PROXY_PREFIX = '/api'
# 第二个请求地址 (目前alova中可以使用)
VITE_SERVER_BASEURL = 'https://76458.com'
# VITE_SERVER_BASEURL = 'https://76458.com'
# 默认上海经纬度
VITE_DEFAULT_LONGITUDE = 121.4737

View File

@ -27,6 +27,11 @@
// uni.setStorageSync(LOCATION_CITY_KEY, LOCATION_DEFAULT_CITY)
})
onShow((options) => {
uni.showModal({
title: '提示',
content: `当前请求域名是:${import.meta.env.VITE_SERVER_BASEURL}`,
showCancel: false
})
if (options?.path === 'bundle/order/tea-room/order-detail') {
uni.setStorageSync('transferOrderParams', {
orderId: options?.query?.orderId || '',

View File

@ -47,10 +47,10 @@ export function getLocationToCity(data: ILocationToCityParams) {
export interface IHomeTeaStoreListParams {
page: number
size: number
search: string
search?: string
latitude: number
longitude: number
city_area_id: number
city_area_id?: number
}
export function getHomeTeaStoreList(data: IHomeTeaStoreListParams) {

View File

@ -1,23 +1,47 @@
import { http } from '@/http/alova'
/**
* 获取茶艺师等级
*/
export function getTeaSpecialistLevels() {
return http.Post<any>('/api/Teamaster/teamasterLevel', null)
}
/**
* 获取茶艺师列表
*/
export interface ITeaSpecialistParams {
level_id: string
page: number
size: number
latitude: number
longitude: number
level: string
search: string
}
export function getTeaSpecialist(data: ITeaSpecialistParams) {
return http.Post('/api/Teamaster/teamasterList', data)
}
/**
* 茶艺师详情
* @param team_user_id 茶艺师用户ID
* @param longitude 经度
* @param latitude 纬度
*/
export interface ITeaSpecialistDetailParams {
team_user_id: number
longitude: number
latitude: number
}
export function getTeaSpecialistDetail(data: ITeaSpecialistDetailParams) {
return http.Post<any>('/api/Teamaster/TeamasterDetails', data)
}
/**
* 茶叶商品列表
*/
export function getTeaProducts() {
return http.Post('/api/Teamaster/LeafList')
}
/**
* 获取茶艺师优惠券
*/
export function getTeaSpecialistCoupons() {
return http.Post<any>('/api/Teamaster/userCoupon')
}

View File

@ -48,22 +48,6 @@ export function getTeaSpecialistRewardAmounts() {
return http.Post('/api/Teamaster/teamasterTipAmount')
}
/**
* 获取门店地址
*/
export interface ITeaHouseListParams {
page: number
size: number
latitude: number
longitude: number
search: string
}
export function getTeaHouseList(data: ITeaHouseListParams) {
return http.Post('/api/Store/storeList',
data
)
}
/**
* 获取未来7天时间
@ -76,7 +60,7 @@ export function getNext7Days() {
* 获取茶叶类型列表
*/
export function getTeaTypeList() {
return http.Post('/api/Teamaster/teaType')
return http.Post<any>('/api/Teamaster/LeafList')
}
/**
@ -106,23 +90,23 @@ export function teaSpecialistInvite(data: ITeaSpecialistInviteParams) {
* 创建预约茶艺师订单
*/
export interface ICreateTeaSpecialistOrderParams {
teamaster_id: number
address_id: number
team_user_id: number
server_type: number
longitude: number
latitude: number
store_id: number
start_time: number
end_time: number
nums: number
tea_id: string
service_type: number
store_id: number
latitude: number
longitude: number
remark: string
coupon_id: number
hours: number
address: string
remrk: string
is_teacup: number
tea_id: string
user_coupon_id: number
}
export function createTeaSpecialistOrder(data: ICreateTeaSpecialistOrderParams) {
return http.Post<ICreateTeaSpecialistOrderResult>('/api/order/submitOrder', data)
return http.Post<ICreateTeaSpecialistOrderResult>('/api/Teamaster/addTeamOrder', data)
}
/***

View File

@ -67,9 +67,7 @@ export interface ITeaSpecialistFuture7DaysResult {
export interface ITeaTypeListResult {
id: number
name: string
status: number
tea_price: number
dtime: string
price: number
}
/**

View File

@ -32,12 +32,14 @@ export interface IAddUserAddressParams {
id: number
contact: string
telephone: string
province: string
province_id?: number
city: string
city_id?: number
district: string
district_id?: number
// province: string
// province_id?: number
// city: string
// city_id?: number
// district: string
// district_id?: number
longitude: number,
latitude: number,
address: string
is_default: number
}

View File

@ -35,7 +35,7 @@
<view class="h-2rpx bg-#F2F2F2"></view>
</view>
<view>
<!-- <view>
<view class="flex items-center mx-36rpx">
<view class="text-30rpx leading-42rpx text-#303133 mr-60rpx w-100rpx">省市区</view>
<view class="add-address">
@ -43,13 +43,13 @@
</view>
</view>
<view class="h-2rpx bg-#F2F2F2"></view>
</view>
</view> -->
<view>
<view class="flex items-center mx-36rpx">
<view class="flex items-center mx-36rpx" @click="Add.handleChooseLocation">
<view class="text-30rpx leading-42rpx text-#303133 mr-60rpx w-100rpx">地址</view>
<view>
<wd-input v-model="form.address" size="large" placeholder="请填写具体地址" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
<wd-input readonly v-model="form.address" size="large" placeholder="请填写具体地址" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
</view>
</view>
</view>
@ -106,12 +106,14 @@
const form = reactive<IAddUserAddressParams>({
contact: '',
telephone: '',
province: '',
province_id: 0,
city: '',
city_id: 0,
district: '',
district_id: 0,
// province: '',
// province_id: 0,
// city: '',
// city_id: 0,
// district: '',
// district_id: 0,
longitude: 0,
latitude: 0,
address: '',
is_default: 0,
id: 0
@ -153,14 +155,14 @@
const Add = {
// 确认省市区
handleConfirmAddress: (e) => {
form.province = e.selectedItems[0]?.label || ''
form.province_id = Number(e.selectedItems[0]?.value) || 0
form.city = e.selectedItems[1]?.label || ''
form.city_id = Number(e.selectedItems[1]?.value) || 0
form.district = e.selectedItems[2]?.label || ''
form.district_id = Number(e.selectedItems[2]?.value) || 0
},
// handleConfirmAddress: (e) => {
// form.province = e.selectedItems[0]?.label || ''
// form.province_id = Number(e.selectedItems[0]?.value) || 0
// form.city = e.selectedItems[1]?.label || ''
// form.city_id = Number(e.selectedItems[1]?.value) || 0
// form.district = e.selectedItems[2]?.label || ''
// form.district_id = Number(e.selectedItems[2]?.value) || 0
// },
// 获取地址详情
handleGetAddressDetails: async () => {
@ -169,13 +171,12 @@
})
form.contact = res.address_details.contact
form.telephone = res.address_details.telephone
form.province = res.address_details.province
form.province_id = res.address_details.province_id
console.log("🚀 ~ form.province_id :", form.province_id )
form.city = res.address_details.city
form.city_id = res.address_details.city_id
form.district = res.address_details.district
form.district_id = res.address_details.district_id
// form.province = res.address_details.province
// form.province_id = res.address_details.province_id
// form.city = res.address_details.city
// form.city_id = res.address_details.city_id
// form.district = res.address_details.district
// form.district_id = res.address_details.district_id
form.address = res.address_details.address
form.is_default = res.address_details.is_default
isDefaultAddress.value = res.address_details.is_default === 1 ? true : false
@ -214,7 +215,27 @@
console.log("🚀 ~ res2:", res)
// 点击取消按钮回调事件
})
},
/**
* 选择地址
*/
handleChooseLocation: async () => {
uni.chooseLocation({
success: (res) => {
console.log("🚀 ~ res:", res)
// res.address: "浙江省嘉兴市南湖区景宜路"
// res.name: "嘉兴市南湖区人民政府(景宜路西)"
// res.latitude: 30.74744
// res.longitude: 120.78483
form.address = res.address
form.longitude = res.longitude
form.latitude = res.latitude
},
fail: (err) => {
console.log("🚀 ~ err:", err)
}
})
},
// 添加地址
@ -229,10 +250,10 @@
return
}
if (!form.province || !form.city || !form.district) {
toast.info('请选择省市区')
return
}
// if (!form.province || !form.city || !form.district) {
// toast.info('请选择省市区')
// return
// }
if (!form.address) {
toast.info('请填写具体地址')

View File

@ -91,7 +91,7 @@
<!-- 轮播图 -->
<view class="mx-30rpx">
<wd-swiper value-key="image" height="400rpx"
:indicator="{ type: 'dots-bar' }" :list="swiperList" v-model:current="current" mode="aspectFit"></wd-swiper>
:indicator="{ type: 'dots-bar' }" :list="info.image_arr" mode="aspectFit"></wd-swiper>
</view>
<!-- 昵称显示 -->
@ -99,27 +99,34 @@
<view class="font-bold text-34rpx leading-48rpx text-#303133 pt-36rpx">{{ info.name }}</view>
<view class="flex items-center justify-between mt-4rpx">
<view class="flex items-center">
<wd-rate v-model="rate" readonly active-color="#FF5951" allow-half active-icon="star-filled" icon="star" space="4rpx"/>
<wd-rate v-model="info.star" readonly active-color="#FF5951" allow-half active-icon="star-filled" icon="star" space="4rpx"/>
<view class="font-400 text-26rpx text-#606266 ml-8rpx">{{ info.star }} 推荐</view>
</view>
<view class="font-400 text-22rpx leading-32rpx text-#6A6363">已预约 {{ info.reservation_num > 10 ? info.reservation_num + '+' : info.reservation_num }}</view>
<view class="font-400 text-22rpx leading-32rpx text-#6A6363">已预约 {{ Number(info.sold) > 10 ? Number(info.sold) + '+' : Number(info.sold) }}</view>
</view>
<view class="flex items-center mt-24rpx">
<view class="flex items-center">
<wd-img :src="`${OSS}icon/icon_store_cert.png`" width="36rpx" height="36rpx"></wd-img>
</view>
<text class="ml-8rpx font-400 text-24rpx leading-4rpx text-#303133">商家认证</text>
</view>
<view class="flex items-center justify-between mt-24rpx">
<view class="flex items-center">
<view class="mr-20rpx" v-if="is90">
<wd-tag color="#FF5951" bg-color="#FEF1F0" custom-class="!rounded-6rpx !px-16rpx !py-4rpx !h-40rpx !w-144rpx">90后茶艺师</wd-tag>
<view class="mr-20rpx">
<wd-tag color="#FF5951" bg-color="#FEF1F0" custom-class="!rounded-6rpx !px-16rpx !py-4rpx !h-40rpx !w-144rpx">{{ info.age_range }}后茶艺师</wd-tag>
</view>
<view class="w-160rpx h-40rpx relative mr-44rpx top-6rpx">
<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>
<tea-specialist-level :level="TeaSpecialistLevelValue[info.teamasterLevel?.[0]?.level_name] || 'junior'"></tea-specialist-level>
<tea-specialist-level :level="info.level"></tea-specialist-level>
</view>
</view>
</view>
<view class="font-400 text-24rpx leading-34rpx text-#818CA9">距离您{{ info.distance }}km 预计{{ info.speed }}分钟</view>
<view class="font-400 text-24rpx leading-34rpx text-#818CA9">距离您{{ info.distance }}km {{ info.is_time }}</view>
</view>
</view>
@ -129,22 +136,22 @@
<view class="flex justify-between items-center mx-88rpx text-center mt-30rpx">
<view>
<view class="font-400 text-28rpx leading-40rpx text-#606266">性别</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.real.gender == 1 ? '男' : '女' }}</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.sex == 1 ? '男' : '女' }}</view>
</view>
<view class="w-4rpx h-66rpx bg-#F6F7F9"></view>
<view>
<view class="font-400 text-28rpx leading-40rpx text-#606266">年龄</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.real.both }}</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.both }}</view>
</view>
<view class="w-4rpx h-66rpx bg-#F6F7F9"></view>
<view>
<view class="font-400 text-28rpx leading-40rpx text-#606266">身高</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.real.height }}cm</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.height }}cm</view>
</view>
<view class="w-4rpx h-66rpx bg-#F6F7F9"></view>
<view>
<view class="font-400 text-28rpx leading-40rpx text-#606266">体重</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.real.weight }}kg</view>
<view class="font-bold text-30rpx leading-42rpx text-#303133 mt-12rpx">{{ info.weight }}kg</view>
</view>
</view>
@ -162,7 +169,7 @@
<view class="font-400 text-26rpx leading-36rpx text-#606266">兴趣爱好</view>
</view>
<view class="mt-20rpx font-400 text-28rpx leading-40rpx text-#303133">
“{{ info.real.interests }}”
{{ info.hobby_introduce }}
</view>
</view>
</view>
@ -171,17 +178,16 @@
<view class="content-tab">
<wd-tabs v-model="tab">
<block v-for="(item, index) in tabList" :key="index">
<wd-tab :title="item.title">
<view class="content mx-30rpx mt-44rpx">{{ item.content }}</view>
</wd-tab>
</block>
<wd-tab title="费用说明"></wd-tab>
<wd-tab title="项目介绍"></wd-tab>
<wd-tab title="禁忌说明"></wd-tab>
<wd-tab title="下单须知"></wd-tab>
</wd-tabs>
</view>
<!-- 费用说明 -->
<view class="mx-30rpx mt-44rpx">
<view >
<!-- 费用说明 -->
<view v-if="tab === 0">
<view class="font-bold text-32rpx leading-44rpx text-#303133">
费用说明
</view>
@ -206,7 +212,7 @@
<view class="w-8rpx h-8rpx rounded-8rpx bg-#6A6363 mr-14rpx"></view>
<view class="flex-1 flex items-center justify-between font-500 text-26rpx leading-48rpx text-#303133">
<view>车马费</view>
<view>{{ info.fare_price }}/公里</view>
<view>{{ info.mileage_price }}/公里</view>
</view>
</view>
</view>
@ -238,11 +244,74 @@
</view>
</view>
</view>
</view>
</view>
<view class="h-4rpx bg-#F6F7F9 mt-40rpx mb-26rpx"></view>
<!-- 温馨提示 -->
<!-- 项目介绍 -->
<view v-if="tab === 1">
<view class="font-bold text-32rpx leading-44rpx text-#303133">
项目介绍
</view>
<view class="mt-24rpx">
<view>
<view class="font-bold text-28rpx leading-48rpx text-[#303133]">自饮七步</view>
<view class="mt-24rpx font-500 text-[#303133] text-26rpx leading-48rpx">
<view>
<text class="mr-20rpx"> 选茶</text>
<text class="mr-20rpx"> 择器</text>
<text class="mr-20rpx"> 备水</text>
</view>
<view>
<text class="mr-20rpx"> 入境</text>
<text class="mr-20rpx"> 冲泡</text>
<text class="mr-20rpx"> 品茗</text>
<text class="mr-20rpx"> 回味</text>
</view>
</view>
</view>
<view class="mt-24rpx">
<view class="font-bold text-28rpx leading-48rpx text-[#303133]">对饮八式</view>
<view class="mt-24rpx font-500 text-[#303133] text-26rpx leading-48rpx">
<view>
<text class="mr-20rpx"> 洗尘</text>
<text class="mr-20rpx"> 坦呈</text>
<text class="mr-20rpx"> 苏酲</text>
<text class="mr-20rpx"> 法度</text>
</view>
<view>
<text class="mr-20rpx"> 养成</text>
<text class="mr-20rpx"> 身受</text>
<text class="mr-20rpx"> 分享</text>
<text class="mr-20rpx"> 放下</text>
</view>
</view>
</view>
</view>
</view>
<!-- 禁忌说明 -->
<view v-if="tab === 2">
<view class="font-bold text-32rpx leading-44rpx text-#303133">
禁忌说明
</view>
<view class="mt-24rpx font-500 text-26rpx leading-48rpx text-[#303133]">
<view>绿色正规茶艺师综合服务平台</view>
<view>为确保平台营运的合法合规和避免不必要的纠纷禁止茶师私添加客户微信</view>
<view>禁止茶师私自收款(现金微信支付宝红包或转帐等)</view>
<view>禁止茶师私下接受宴请</view>
<view>以及从事除平台项目之外的其它内容和活动</view>
</view>
</view>
<!-- 下单须知 -->
<view v-if="tab === 3">
<view class="font-bold text-32rpx leading-44rpx text-#303133">
下单须知
</view>
<view class="mt-24rpx font-500 text-26rpx leading-48rpx text-[#303133]">
茶艺师出发后客户取消订单车费不予返还敬请谅解
</view>
<view class="mt-24rpx">
<view class="flex items-center">
<view class="mr-14rpx">
<wd-icon name="info-circle" size="36rpx" color="#707070"></wd-icon>
@ -258,11 +327,10 @@
</view>
</view>
</view>
</view>
<!-- 操作按钮 -->
<view>
<view v-if="!isReserve" class="text-32rpx leading-44rpx flex items-center justify-center leading-90rpx text-center text-[#303133] bg-white mt-24rpx pt-36rpx pb-28rpx">
<view v-if="!isReserve" class="text-32rpx leading-44rpx flex items-center justify-center leading-90rpx text-center text-[#303133] mt-24rpx pt-36rpx pb-28rpx">
<view class="w-630rpx h-90rpx bg-[#4C9F44] rounded-8rpx text-#fff" @click="Detail.handleReserveTeaspecialist">立即邀约</view>
</view>
@ -283,7 +351,7 @@
<script lang="ts" setup>
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import { useMessage } from 'wot-design-uni'
import { getTeaSpecialistDetails, collectTeaSpecialist, getTeaSpecialistRewardAmounts, teaSpecialistInvite } from '@/api/tea'
import { getTeaSpecialistDetail } from '@/api/tea-specialist'
import { ITeaSpecialistDetailsFields } from '@/api/types/tea'
import type { ITeaSpecialistRewardAmountsResult } from '@/api/types/tea'
import { toast } from '@/utils/toast'
@ -295,36 +363,33 @@
const OSS = inject('OSS')
// tab
const tab = ref<number>(1)
const tabList = ref<Array<{id: number, status: number, content: string, title: string}>>([
{id: 0, status: 0, content: '', title: ''},
])
const tab = ref<number>(0)
// 用户信息
const userInfo = ref<IUserInfoVo>(null)
// 茶艺师
const id = ref<number>(0)
const info = reactive<ITeaSpecialistDetailsFields>({
const info = ref({
id: 0,
name: '',
star: 0,
image: '',
reservation_num: 0,
distance: 0,
speed: 0,
real: { gender: 1, both: 18, height: 165, weight: 53, interests: '爱好茶艺,喜欢旅游,把爱好当工作' },
teamasterlabel: [],
teamasterLevel: [],
price: 0,
fare_price: 0,
collect: 0,
up_status: 0,
textarea: []
image_arr: [], // 轮播图
name: '', // 茶艺师名字
star: 0, // 茶艺师评分
sold: 0, // 已预约
age_range: '00', // 茶艺师年龄段
level: 1, // 茶艺师等级
distance: 0, // 距离
is_time: '', // 预计到达
sex: 0, // 性别
both: 0, // 年龄
weight: 0, // 体重
height: 0, // 身高
hobby_introduce: '', // 兴趣爱好介绍
price: 0, // 服务费
mileage_price: 0, // 车马费
})
const latitude = ref<number>(0) // 纬度
const longitude = ref<number>(0) // 经度
const is90 = ref<boolean>(false)
// 是否是预约茶艺师页面
const isReserve = ref<boolean>(false)
@ -332,17 +397,6 @@
// 弹窗
const message = useMessage('wd-message-box-slot')
// 轮播图
const swiperList = ref<string[]>([
`${OSS}images/banner1.png`,
`${OSS}images/banner1.png`,
`${OSS}images/banner1.png`
])
const current = ref<number>(0)
// 评分
const rate = ref<number>(1)
// 打赏茶艺师
const showTipTeaSpecialistPopup = ref<boolean>(false)
const tipList = ref<Array<ITeaSpecialistRewardAmountsResult>>([])
@ -357,35 +411,35 @@
id.value = args.id || 0
// 获取茶艺师详情
const res = await getTeaSpecialistDetails({
id: args.id,
const res = await getTeaSpecialistDetail({
team_user_id: args.id,
latitude: uni.getStorageSync('latitude'),
longitude: uni.getStorageSync('longitude'),
user_id: userInfo.value.id || 0
})
// 将返回的数据合并到 reactive 对象中
Object.assign(info, res.teamaster || {})
rate.value = info.star
tabList.value = info.textarea
console.log("🚀 ~ tabList:", res)
info.value = res.teamaster
console.log("🚀 ~ res:", res)
// 茶艺师是否上线
// if (info.up_status == 0) {
// isReserve.value = true
// rate.value = info.value.star
// tabList.value = info.value.textarea
// console.log("🚀 ~ tabList:", res)
// // 茶艺师是否上线
// // if (info.up_status == 0) {
// // isReserve.value = true
// // }
// if (info.value.teamasterlabel) {
// info.value.teamasterlabel.map(item => {
// if (item.label_name == '90后茶艺师') {
// is90.value = true
// }
// })
// }
if (info.teamasterlabel) {
info.teamasterlabel.map(item => {
if (item.label_name == '90后茶艺师') {
is90.value = true
}
})
}
// 获取打赏金额
getTeaSpecialistRewardAmounts().then((res: Array<ITeaSpecialistRewardAmountsResult>) => {
tipList.value = res
})
// getTeaSpecialistRewardAmounts().then((res: Array<ITeaSpecialistRewardAmountsResult>) => {
// tipList.value = res
// })
})
const Detail = {
@ -393,27 +447,27 @@
* TODO 处理收藏-暂时不要
*/
handleCollect: async () => {
let status = info.collect == 0 ? 1 : 0
await collectTeaSpecialist({
id: id.value,
status
})
// let status = info.collect == 0 ? 1 : 0
// await collectTeaSpecialist({
// id: id.value,
// status
// })
info.collect = info.collect == 0 ? 1 : 0
// info.collect = info.collect == 0 ? 1 : 0
},
/**
* TODO 处理分享-暂时不要
*/
handleShare: () => {
const url = window.location.href
const { name, real, image} = info
const params = {
title: name,
desc: real?.interests,
imgUrl: image,
link: url
}
// const url = window.location.href
// const { name, real, image} = info
// const params = {
// title: name,
// desc: real?.interests,
// imgUrl: image,
// link: url
// }
},
/**

View File

@ -76,19 +76,22 @@
<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.id) ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#FFF] text-[#606266]'"
@click="List.handleToggleTeaSpecialistLevel(item.id)">
{{ item.level_name}}
:class="selectedLevel.includes(item.level) ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#FFF] text-[#606266]'"
@click="List.handleToggleTeaSpecialistLevel(item.level)">
{{ item.label}}
</view>
</view>
<mescroll-body @init="mescrollInit" @down="downCallback" :down="downOption" @up="List.upCallback" :up="upOption" fixed>
<view class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx" v-for="(item, index) in list" :key="index" @click="router.navigateTo(`/bundle_b/pages/tea-specialist/detail?id=${item.id}`)">
<view class="mr-28rpx relative">
<wd-img width="200rpx" height="200rpx" :src="item.image"></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
class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx relative"
v-for="(item, index) in list" :key="index"
@click="List.handleReserveTeaSpecialist(item.team_user_id, item.state)">
<view class="tea-specialist-time absolute z-3 top-6rpx left-0 bg-[#4C9F44] text-[#fff] font-400 text-18rpx flex items-center justify-center">
{{ item.state == 0 ? '可约' : '工作中' }}
</view>
<view class="mr-28rpx relative z-2">
<wd-img width="200rpx" height="200rpx" :src="item.image"></wd-img>
</view>
<view class="flex-1">
<view class="flex items-center">
@ -96,25 +99,23 @@
{{ item.name }}
</view>
<view>
<tea-specialist-level :level="TeaSpecialistLevelValue[item.teamasterLevel[0].level_name]"></tea-specialist-level>
<tea-specialist-level :level="item.level"></tea-specialist-level>
</view>
</view>
<view class="flex items-center">
<template v-for="(label, labelIndex) in item.teamasterlabel" :key="labelIndex">
<!-- 上门服务 -->
<view class="mr-12rpx" v-if="label.id == 1">
<wd-tag color="#40AE36" bg-color="#40AE36" plain custom-class="!rounded-4rpx">{{ label.label_name }}</wd-tag>
<!-- 到店服务 -->
<view class="mr-12rpx" v-if="item.server_type == 1">
<wd-tag color="#F55726" bg-color="#F55726" plain custom-class="!rounded-4rpx">到店服务</wd-tag>
</view>
<!-- 到点服务 -->
<view class="mr-12rpx" v-if="label.id == 2">
<wd-tag color="#F55726" bg-color="#F55726" plain custom-class="!rounded-4rpx">{{ label.label_name }}</wd-tag>
<!-- 上门服务 -->
<view class="mr-12rpx" v-if="item.server_type == 2">
<wd-tag color="#40AE36" bg-color="#40AE36" plain custom-class="!rounded-4rpx">上门服务</wd-tag>
</view>
</template>
<view class="mr-12rpx">
<wd-tag color="#818CA9" bg-color="#F3F3F3">{{ item.both }}</wd-tag>
<wd-tag color="#818CA9" bg-color="#F3F3F3">{{ item.both }}</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>
@ -123,7 +124,7 @@
<view class="flex items-center justify-between mt-18rpx">
<view class="mr-20rpx w-200rpx">
<view class="flex items-center" v-if="item.authent_status == 1">
<view class="flex items-center">
<view class="flex items-center">
<wd-img :src="`${OSS}icon/icon_store_cert.png`" width="36rpx" height="36rpx"></wd-img>
</view>
@ -139,7 +140,7 @@
<text class="text-32rpx">{{ item.price }}</text>
<text class="text-24rpx">/小时</text>
</view>
<view class="font-400 text-22rpx leading-32rpx text-#92928C">最快{{ item.speed }}分钟到达</view>
<view class="font-400 text-22rpx leading-32rpx text-#92928C">{{ item.is_time }}</view>
</view>
</view>
</view>
@ -149,19 +150,20 @@
</template>
<script lang="ts" setup>
import { useToast } from 'wot-design-uni'
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import { router } from '@/utils/tools'
import { getTeaSpecialistLevels, getTeaSpecialist } from '@/api/tea-specialist'
import { getTeaSpecialist } from '@/api/tea-specialist'
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import type { ITeaSpecialistResult } from '@/api/types/tea-specialist'
import {TeaSpecialistLevelValue} from '@/utils/teaSpecialist'
import {TeaSpecialistLevelValue, TeaSpecialistLevels} from '@/utils/teaSpecialist'
const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight')
const toast = useToast()
// 茶艺师等级
const TeaSpecialistLevels = reactive<Array<{ id: number, status: number, level_name: string}>>([])
const selectedLevel = ref<Array<any>>([]) // 选择茶艺师的点击等级
// mescroll
@ -191,10 +193,7 @@
})
onLoad(async () => {
// 获取茶艺师等级tab
getTeaSpecialistLevels().then((res:Array<any>) => {
TeaSpecialistLevels.push(...res)
})
})
@ -204,7 +203,7 @@
*/
upCallback: (mescroll) => {
const filter = {
level_id: selectedLevel.value.join(',') || '0',
level: selectedLevel.value.join(',') || '',
page: mescroll.num,
size: mescroll.size,
latitude: uni.getStorageSync('latitude') || import.meta.env.VITE_DEFAULT_LATITUDE,
@ -222,6 +221,20 @@
})
},
/**
* 预约茶艺师
* @param id
* @param state 茶艺师状态: 0可约 1工作中
*/
handleReserveTeaSpecialist: (id: number, state: number) => {
if (state === 1) {
toast.show('茶艺师工作中,暂不可预约')
return
}
router.navigateTo(`/bundle_b/pages/tea-specialist/detail?id=${id}`)
},
/**
* 获取茶艺师等级
@ -283,4 +296,10 @@
scrollbar-width: none;
}
}
.tea-specialist-time {
border-radius: 0rpx 50rpx 50rpx 0rpx;
min-width: 106rpx;
height: 38rpx;
}
</style>

View File

@ -7,6 +7,63 @@
}</route>
<template>
<view class="pb-180rpx">
<!-- 消息提示框 -->
<wd-message-box selector="wd-message-box-slot" />
<!-- 上门服务-预定时间 -->
<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" @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>
<view class="w-[100%] h-100rpx flex justify-between items-center">
<view
class="w-[50%] h-[100%] flex flex-col items-center justify-center rounded-l-[8rpx]"
:class="`${currentTimePicker == 'start' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#303133]'}`"
@click="currentTimePicker = 'start'">
<view class="text-28rpx leading-40rpx">开始时间</view>
<view class="text-26rpx leading-36rpx mt-2rpx">{{ startTimeLayout }}</view>
</view>
<view
class="w-[50%] h-[100%] flex flex-col items-center justify-center rounded-r-[8rpx]"
:class="`${currentTimePicker == 'end' ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#F6F7F8] text-[#303133]'}`"
@click="currentTimePicker = 'end'">
<view class="text-28rpx leading-40rpx">结束时间</view>
<view class="text-26rpx leading-36rpx mt-2rpx">{{ endTimeLayout }}</view>
</view>
</view>
<view class="date-picker">
<view class="" v-if="currentTimePicker == 'start'">
<wd-datetime-picker-view
:minDate='minTimestamp'
:maxDate='maxTimestamp'
type="datetime"
v-model="startTimeValue"
:formatter="Door.handleFormatTime"
@change="Door.handleStartTimePicker"
/>
</view>
<view class="" v-if="currentTimePicker == 'end'">
<wd-datetime-picker-view
:minDate='minTimestamp'
:maxDate='maxTimestamp'
type="datetime"
v-model="endTimeValue"
:formatter="Door.handleFormatTime"
@change="Door.handleEndTimePicker"
/>
</view>
</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' @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>
<!-- 费用明细 -->
<wd-popup v-model="showCostPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" @close="showCostPopup = false" position="bottom">
<view class='bg-[#FBFBFB] py-40rpx realtive'>
@ -109,9 +166,9 @@
v-for="(item, index) in teaList" :key="index"
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)">
@click="Reserve.handleToggleTea(item.id, item.name, item.price)">
<view>{{item.name}}</view>
<view>¥{{item.tea_price}}</view>
<view>¥{{item.price}}</view>
</view>
</view>
</view>
@ -148,8 +205,8 @@
</view>
<view class="flex items-center">
<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 class="w-178rpx h-70rpx leading-70rpx text-center bg-#F6F7F8 text-#303133 rounded-8rpx mr-20rpx" @click="Reserve.handleResetTeaService">重置</view>
<view class="w-178rpx h-70rpx leading-70rpx text-center bg-#4C9F44 text-#fff rounded-8rpx" @click="Reserve.handleConfirmTeaService">确定</view>
</view>
</view>
</view>
@ -158,7 +215,7 @@
</wd-popup>
<!-- 选择预定时间 -->
<booking-time v-model="showBookTimePopup" :day="sevenDay" @selectedTime="TeaRoom.handleChooseReserveTime"></booking-time>
<booking-time v-model="showBookTimePopup" :day="sevenDay" @selectedTime="Reserve.handleChooseReserveTime"></booking-time>
<view>
<navbar title="预约茶艺师" :leftArrow="false"></navbar>
@ -176,11 +233,11 @@
</view>
<view class="flex items-center mt-18rpx">
<view class="mr-12rpx">
<view class="bg-#FEF1F0 text-#FF5951 w-144rpx h-40rpx rounded-6rpx text-center text-22rpx leading-40rpx">90后茶艺师</view>
<view class="bg-#FEF1F0 text-#FF5951 w-144rpx h-40rpx rounded-6rpx text-center text-22rpx leading-40rpx">{{ info.age_range }}后茶艺师</view>
</view>
<tea-specialist-level :level="TeaSpecialistLevelValue[info.teamasterLevel?.[0]?.level_name] || 'junior'"></tea-specialist-level>
<tea-specialist-level :level="info.level"></tea-specialist-level>
</view>
<view class="font-400 text-22rpx leading-32rpx text-#6A6363 mt-30rpx">已预约 {{ info.reservation_num > 10 ? info.reservation_num + '+' : info.reservation_num }}</view>
<view class="font-400 text-22rpx leading-32rpx text-#6A6363 mt-30rpx">已预约 {{ Number(info.sold) > 10 ? Number(info.sold) + '+' : Number(info.sold) }}</view>
</view>
</view>
@ -189,14 +246,14 @@
<view class="flex items-center justify-between">
<view class="font-bold text-32rpx leading-44rpx">服务方式</view>
<view class="bg-[#F0F6EF] h-60rpx rounded-20rpx flex items-center justify-between py-14rpx px-30rpx relative w-304rpx font-400 text-26rpx text-[#333]">
<view class="absolute left-30rpx top-1/2 -translate-y-1/2 z-2" :class="serviceTypeValue == 1 ? 'text-[#fff]' : ''" @click="TeaRoom.handleChooseService(1)">到店服务</view>
<view class="absolute right-30rpx top-1/2 -translate-y-1/2 z-2" :class="serviceTypeValue == 2 ? 'text-[#fff]' : ''" @click="TeaRoom.handleChooseService(2)">上门服务</view>
<view class="absolute left-30rpx top-1/2 -translate-y-1/2 z-2" :class="serviceTypeValue == 1 ? 'text-[#fff]' : ''" @click="Reserve.handleChooseService(1)">到店服务</view>
<view class="absolute right-30rpx top-1/2 -translate-y-1/2 z-2" :class="serviceTypeValue == 2 ? 'text-[#fff]' : ''" @click="Reserve.handleChooseService(2)">上门服务</view>
<view class="swiper-service" :style="{ transform: serviceTypeValue == 1 ? 'translateY(-50%) translateX(0)' : 'translateY(-50%) translateX(76px)' }"></view>
</view>
</view>
<!-- 预定门店 -->
<view class="flex items-center justify-between mt-48rpx" v-if="serviceTypeValue == 1" @click="TeaRoom.handleToSChooseStore">
<view class="flex items-center justify-between mt-48rpx" v-if="serviceTypeValue == 1" @click="Reserve.handleToChooseStore">
<view class="text-28rpx leading-40rpx">预定店</view>
<view class="flex items-center">
<view class="text-28rpx leading-40rpx text-#303133">{{ teaHouse.name || '请选择茶馆' }}</view>
@ -207,7 +264,7 @@
</view>
<!-- 上门服务地址 -->
<view class="flex items-center justify-between mt-48rpx" v-if="serviceTypeValue == 2" @click="TeaRoom.handleToAddress">
<view class="flex items-center justify-between mt-48rpx" v-if="serviceTypeValue == 2" @click="Reserve.handleToAddress">
<view class="text-28rpx leading-40rpx">地址</view>
<view class="flex items-center">
<view class="text-28rpx leading-40rpx text-#303133 w-430rpx line-1 text-right">
@ -225,14 +282,17 @@
</view>
</view>
<!-- 预定时间 -->
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="showBookTimePopup = true">
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="Reserve.handleChooseTime">
<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">{{ sevenDay.minimum_time }}小时起订</view>
<view class="flex items-center">
<view class="text-[28rpx] text-[#909399] leading-40rpx w-430rpx line-1 text-right">
<template v-if="reserveTime.length > 0">
{{ reserveTime[0] }} {{ reserveTime[1].join(',') }}
<template v-if="serviceTypeValue == 1 && dayHours">
{{ dayTime }} {{ dayHours }}
</template>
<template v-else-if="serviceTypeValue == 2 && startTimeLayout && endTimeLayout">
{{ startTimeLayout }} {{ endTimeLayout }}
</template>
<template v-else>
请选择
@ -276,7 +336,7 @@
</view>
<!-- 优惠券 -->
<view class="bg-white py-26rpx px-30rpx mt-20rpx" @click="TeaRoom.handleToCoupon(CouponType.Discount)">
<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>
@ -298,7 +358,7 @@
<!-- 支付方式 -->
<!-- <view class="bg-white py-26rpx px-30rpx mt-20rpx">
<pay hide-store-balance @pay="TeaRoom.handleGetPayValue"></pay>
<pay hide-store-balance @pay="Reserve.handleGetPayValue"></pay>
</view> -->
<view class="fixed left-0 right-0 bottom-0 z-2 bg-[#fff]"
@ -315,7 +375,7 @@
</view>
</view>
<view class="mr-30rpx">
<wd-button custom-class='!bg-[#4C9F44] !rounded-8rpx !h-70rpx' @click="TeaRoom.handleSubmitOrder">立即预定</wd-button>
<wd-button custom-class='!bg-[#4C9F44] !rounded-8rpx !h-70rpx' @click="Reserve.handleSubmitOrder">立即预定</wd-button>
</view>
</view>
</view>
@ -324,20 +384,23 @@
</template>
<script lang="ts" setup>
import { toast } from '@/utils/toast'
import { router, toTimes, toPlus } from '@/utils/tools'
import { useMessage, useToast } from 'wot-design-uni'
import { digits } from '@/utils/test'
import { router, toTimes, toPlus, getCurrentDate } from '@/utils/tools'
import PriceFormat from '@/components/PriceFormat.vue'
import { ReserveServiceCategory, OrderType } from '@/utils/order'
import { PayList, PayCategory, PayValue } from '@/utils/pay'
import Pay from '@/components/Pay.vue'
import { getTeaSpecialistDetails, getNext7Days, getTeaTypeList, createTeaSpecialistOrder } from '@/api/tea'
import { getTeaSpecialistDetails, getTeaTypeList, createTeaSpecialistOrder } from '@/api/tea'
import { getNext7Days} from '@/api/tea-room'
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'
import { getTeaSpecialistDetail } from '@/api/tea-specialist'
const OSS = inject('OSS')
const toast = useToast()
const message = useMessage('wd-message-box-slot')
// 服务方式
const serviceType = ref<Array<any>>([
@ -350,24 +413,41 @@
const teaHouse = ref<{id: number, name: string}>({id: 0, name: ''})
// 选择预定时间
const MINIMUMTIME = 2 // TODO 暂时写死
const showBookTimePopup = ref<boolean>(false)
const sevenDay = reactive<ITeaSpecialistFuture7DaysResult>({
minimum_time: 0,
minimum_time: MINIMUMTIME,
time: []
})
const reserveTime = ref<Array<any>>([])
const timeSlots = ref<Array<string>>([]) // 连续选择的预约时间
const dayTitle = ref<string>('') // 周三03/18
const dayTime = ref<string>('') // 2024-03-18
const dayHours = ref<string>('') // 预定时长00:00,00:30
const startTime = ref<number>(0) // 开始时间
const endTime = ref<number>(0) // 结束时间
const countHours = ref<number>(0) // 预定了几个小时
// 上门服务-预定时间相关
const showReservePopup = ref<boolean>(false) // 预定时间popup
const currentTimePicker = ref<string>('start') // 当前选择的时间类型
const startTimeValue = ref<string>('') // 开始时间
const endTimeValue = ref<string>('') // 结束时间
const now = new Date()
const minTimestamp = Date.now()
// 允许选择今天及未来六天的日期
const maxTimestamp = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 6, 23, 59, 59, 999).getTime()
const startTimeLayout = ref<string>('')
const endTimeLayout = ref<string>('')
const totalHour = ref<number>(0)
// 上门服务选择的地址
const address = ref<IUserAddressListResult>({
const address = ref({
id: 0,
contact: '',
telephone: '',
province: '',
province_id: 0,
city: '',
city_id: 0,
district: '',
district_id: 0,
longitude: 0,
latitude: 0,
address: '',
is_default: 0,
})
@ -392,35 +472,29 @@
// 订单备注
const orderRemarks = ref<string>('')
// 支付方式
const pay = ref<number>(0)
const html: string = '<p>这里是富文本内容,需要后台传递</p>'
const isGroupBuying: boolean = false // 是否是团购套餐
// 费用明细相关
const showCostPopup = ref<boolean>(false) // 费用明细popup
// 茶艺师
const teaSpecialistId = ref<number>(0)
const info = reactive<ITeaSpecialistDetailsFields>({
const id = ref<number>(0)
const info = ref({
id: 0,
name: '',
star: 0,
image: '',
reservation_num: 0,
distance: 0,
speed: 0,
real: { gender: 1, both: 18, height: 165, weight: 53, interests: '爱好茶艺,喜欢旅游,把爱好当工作' },
teamasterlabel: [],
teamasterLevel: [],
price: 0,
fare_price: 0,
collect: 0,
up_status: 0,
textarea: []
image_arr: [], // 轮播图
name: '', // 茶艺师名字
star: 0, // 茶艺师评分
sold: 0, // 已预约
age_range: '00', // 茶艺师年龄段
level: 1, // 茶艺师等级
distance: 0, // 距离
is_time: '', // 预计到达
sex: 0, // 性别
both: 0, // 年龄
weight: 0, // 体重
height: 0, // 身高
hobby_introduce: '', // 兴趣爱好介绍
price: 0, // 服务费
mileage_price: 0, // 车马费
})
const is90 = ref<boolean>(false)
// 选择的优惠券
const selectedCoupon = ref<{id: number, name: string}>({id: 0, name: ''})
@ -451,43 +525,33 @@
total: 0
})
onLoad(async (args) => {
if (args.id) {
teaSpecialistId.value = Number(args.id)
const res = await getTeaSpecialistDetails({
id: args.id,
longitude: 0,
latitude: 0,
user_id: 0
})
// 将返回的数据合并到 reactive 对象中
Object.assign(info, res.teamaster || {})
if (info.teamasterlabel) {
info.teamasterlabel.map(item => {
if (item.label_name == '90后茶艺师') {
is90.value = true
}
id.value = Number(args.id)
// 获取茶艺师详情
const res = await getTeaSpecialistDetail({
team_user_id: args.id,
latitude: uni.getStorageSync('latitude'),
longitude: uni.getStorageSync('longitude'),
})
info.value = res.teamaster
bill.value.travel = {
total: toTimes(info.fare_price, info.distance),
unitPrice: info.fare_price,
num: info.distance
}
}
// bill.value.travel = {
// total: toTimes(info.fare_price, info.distance),
// unitPrice: info.fare_price,
// num: info.distance
// }
}
// 初始化数据
TeaRoom.handleInit()
Reserve.handleInit()
})
const TeaRoom = {
const Reserve = {
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)
@ -495,9 +559,57 @@
/**
* 选择服务方式
* @param type 服务类型 1到店服务 2上门服务
*/
handleChooseService: (type: number) => {
serviceTypeValue.value = type
if (type === 1) {
Door.handleResetTime()
address.value = {
id: 0,
contact: '',
telephone: '',
longitude: 0,
latitude: 0,
address: '',
is_default: 0,
}
}
if (type === 2) {
// 重置事件选择
reserveTime.value = []
dayTitle.value = ''
dayTime.value = ''
dayHours.value = ''
sevenDay.minimum_time = MINIMUMTIME
sevenDay.time = []
teaHouse.value = {id: 0, name: ''}
}
},
/**
* 选择预订时间
*/
handleChooseTime: async () => {
if (serviceTypeValue.value === 1 && teaHouse.value.id === 0) {
// 到店服务必须要选择门店
toast.show('请先选择门店')
return false
}
if (serviceTypeValue.value === 1) {
const storeId = teaHouse.value.id || 0
const next7 = await getNext7Days(storeId, getCurrentDate())
// disabled = 0 可预约 1不可逾越
Object.assign(sevenDay, next7.data)
Object.assign(sevenDay, {minimum_time: MINIMUMTIME})
showBookTimePopup.value = true
} else if (serviceTypeValue.value === 2) {
// 上门服务
showReservePopup.value = true
}
},
/**
@ -524,8 +636,9 @@
/**
* 选择门店
*/
handleToSChooseStore: () => {
handleToChooseStore: () => {
uni.$on('chooseTeaHouse', params => {
console.log("🚀 ~ params:", params)
uni.$off('chooseTeaHouse')
teaHouse.value = params
})
@ -547,17 +660,45 @@
* 选中预定时间
*/
handleChooseReserveTime: (params: any) => {
console.log("🚀 ~ params:", params)
reserveTime.value = params
if (!digits(params.countSelectedTime)) {
message.alert({
title: '提示',
msg: '选择时间段不满一小时按一小时算请合理选择时间',
confirmButtonText: '确定',
cancelButtonProps: {
customClass: '!bg-[#F6F7F8] !text-[#303133] !text-32rpx !leading-44rpx !rounded-8rpx',
},
confirmButtonProps: {
customClass: '!bg-[#4C9F44] !text-[#fff] !text-32rpx !leading-44rpx !rounded-8rpx',
},
})
}
timeSlots.value = params.selectedTimestamps
dayTitle.value = params.dayTitle
dayTime.value = params.dayTime
const times = params.selectedTime.map(item => {
return item.time
}).join(',')
dayHours.value = times
startTime.value = params.selectedTimestamps[0]
console.log("🚀 ~ startTime.value:", startTime.value)
endTime.value = params.selectedTimestamps[params.selectedTimestamps.length - 1]
console.log("🚀 ~ endTime.value:", endTime.value)
countHours.value = params.countSelectedTime
bill.value.service = {
total: toTimes(info.price, params[3]),
unitPrice: info.price,
num: params[3],
startTime: params[2][0],
endTime: params[2][params[2].length - 1],
},
total: 0,
unitPrice: 0,
num: params.countSelectedTime,
startHour: params.selectedTime[0].time,
endHour: params.selectedTime[params.selectedTime.length - 1].time
}
console.log("🚀 ~ bill.value:", bill.value)
// Detail.handleCalculateTeaRoomPrice()
},
/**
@ -572,18 +713,14 @@
uni.$off('chooseCoupon');
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}` }
// bill.value.coupon = params.coupon.coupon_price
selectedCoupon.value = {id: params.coupon.id, name: `${params.coupon.name}${params.coupon.coupon_price}` }
selectedCoupon.value = {id: params.coupon.id, name: params.coupon.name}
bill.value.coupon = params.coupon.coupon_price
selectCouponId.value = params.coupon.id // 这里的ID是在数据表自增的ID保存下来是为了回显列表的,没有其他作用
})
// 获取预定了几个小时
const count = bill.value.service.num
uni.navigateTo({ url: `/bundle/coupon/coupon?id=${teaSpecialistId.value}&numbers=${count}&type=${type}` })
// router.navigateTo(`/bundle/coupon/coupon?id=${id.value}&numbers=${count}&type=${type}&storeId=${storeId.value}&couponId=${selectCouponId.value}&groupCouponId=${selectGroupCouponId.value}`)
router.navigateTo(`/bundle_b/pages/tea-specialist/coupon?couponId=${selectCouponId.value}`)
},
/**
@ -630,21 +767,21 @@
toast.info('请选择茶艺时服务')
return
}
// 提交的订单数据
const params = {
teamaster_id: info.id,
address_id: address.value.id,
start_time: bill.value.service.startTime,
end_time: bill.value.service.endTime,
nums: servicePeople.value,
tea_id: selectedTea.value.join(','),
service_type: serviceTypeValue.value,
store_id: teaHouse.value.id,
latitude: uni.getStorageSync('latitude') || 0,
longitude: uni.getStorageSync('longitude') || 0,
remark: orderRemarks.value,
coupon_id: selectedCoupon.value.id || 0,
hours: bill.value.service.num
team_user_id: id.value, // 茶艺师ID
server_type: serviceTypeValue.value, // 服务方式 1到店服务 2上门服务
longitude: uni.getStorageSync('longitude'), // 经度
latitude: uni.getStorageSync('latitude'), // 纬度
store_id: serviceTypeValue.value == 1 ? teaHouse.value.id : 0, // 茶室Id如果是上门服务则传0
address: serviceTypeValue.value == 1 ? teaHouse.value.name : address.value.address, // 地址: 到店传茶室名称 上门则传地址
start_time: serviceTypeValue.value == 1 ? startTime.value : Math.floor(Door.startTimeTimestamp / 1000), // 预约开始时间
end_time: serviceTypeValue.value == 1 ? endTime.value : Math.floor(Door.endTimeTimestamp / 1000), // 预约结束时间
hours: serviceTypeValue.value == 1 ? countHours.value : totalHour.value, // 预约小时数
remrk: orderRemarks.value, // 订单备注
is_teacup: teaUsageValue.value, // 是否需要茶具 1客户自备 2茶艺师提供
tea_id: selectedTea.value.join(','), // 茶叶商品ids 多个逗号隔开
user_coupon_id: selectedCoupon.value.id, // 优惠券id默认传0
}
try {
@ -676,6 +813,113 @@
}
}
// 上门服务
const Door = {
startTimeTimestamp: 0, // 记录开始时间戳
endTimeTimestamp: 0, // 记录结束时间戳
handleStartTimePicker: (e: {value: number}) => {
Door.startTimeTimestamp = e.value
startTimeLayout.value = Door.handleFormatDate(e.value)
Door.handleTotalTimestamp()
},
handleEndTimePicker: (e: {value: number}) => {
Door.endTimeTimestamp = e.value
endTimeLayout.value = Door.handleFormatDate(e.value)
Door.handleTotalTimestamp()
},
handleFormatTime: (type: string, values: string) => {
const now = new Date();
if (type === 'year') {
return `${values}`
}
if (type === 'month') {
return `${values}`
}
if (type === 'date') {
return `${values}`
}
if (type === 'hour') {
return `${values}`;
}
if (type === 'minute') {
return `${values}`;
}
return values
},
handleTotalTimestamp: () => {
if (Door.startTimeTimestamp && Door.endTimeTimestamp) {
const diffMs = Door.endTimeTimestamp - Door.startTimeTimestamp
// 计算小时,保留一位小数
const hours = (diffMs / 1000 / 60 / 60)
const result = Math.round(hours * 10) / 10 // 保留一位小数
if (result >= 0) {
totalHour.value = result
}
return result
}
totalHour.value = 0
return 0
},
/**
* 格式化时间
*/
handleFormatDate: (timestamp: number) => {
const date = new Date(timestamp)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hour = String(date.getHours()).padStart(2, '0')
const minute = String(date.getMinutes()).padStart(2, '0')
return `${year}-${month}-${day} ${hour}:${minute}`
},
/**
* 重置预定时间
*/
handleResetTime: () => {
startTimeValue.value = ''
endTimeValue.value = ''
startTimeLayout.value = ''
endTimeLayout.value = ''
Door.startTimeTimestamp = 0
Door.endTimeTimestamp = 0
totalHour.value = 0
currentTimePicker.value = 'start'
},
/**
* 确定时间
*/
handleConfirmHour: () => {
if (totalHour.value <= sevenDay.minimum_time) {
toast.info(`起订时间${sevenDay.minimum_time}小时`)
return
}
if (!digits(totalHour.value)) {
message.alert({
title: '提示',
msg: '选择时间段不满一小时按一小时算请合理选择时间',
confirmButtonText: '确定',
cancelButtonProps: {
customClass: '!bg-[#F6F7F8] !text-[#303133] !text-32rpx !leading-44rpx !rounded-8rpx',
},
confirmButtonProps: {
customClass: '!bg-[#4C9F44] !text-[#fff] !text-32rpx !leading-44rpx !rounded-8rpx',
},
})
}
showReservePopup.value = false
},
}
const billTotal = computed(() => {
const s = Number(bill.value.service.total) || 0
const t = Number(bill.value.travel.total) || 0

View File

@ -52,7 +52,7 @@
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import type { ITeaHouseListResult } from '@/api/types/tea'
import { router } from '@/utils/tools'
import { getTeaHouseList } from '@/api/tea'
import { getHomeTeaStoreList } from '@/api/tea-room'
const OSS = inject('OSS')
@ -96,7 +96,7 @@
search: storeName.value
}
getTeaHouseList(filter).then((res: ITeaHouseListResult) => {
getHomeTeaStoreList(filter).then((res: ITeaHouseListResult) => {
const curPageData = res.list || [] // 当前页数据
if(mescroll.num == 1) list.value = [] // 第一页需手动制空列表
list.value = list.value.concat(curPageData) //追加新数据

View File

@ -19,30 +19,30 @@
defineProps({
level: {
type: String,
type: Number,
default: ''
}
})
// 茶艺师等级对应的icon和文字
// 茶艺师等级对应的icon和文字这个数组5-1就是对应的等级
const levelMap = {
gold: {
5: {
icon: `${OSS}icon/icon_gold_medal.png`,
text: '金牌茶艺师'
},
senior: {
4: {
icon: `${OSS}icon/icon_senior_medal.png`,
text: '高级茶艺师'
},
intermediate: {
3: {
icon: `${OSS}icon/icon_intermediate_medal.png`,
text: '中级茶艺师'
},
junior: {
2: {
icon: `${OSS}icon/icon_junior_medal.png`,
text: '初级茶艺师'
},
enthusiast: {
1: {
icon: `${OSS}icon/icon_enthusiast_medal.png`,
text: '茶艺爱好者'
}

View File

@ -538,6 +538,15 @@
{
"root": "bundle_b",
"pages": [
{
"path": "pages/tea-specialist/coupon",
"type": "page",
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
}
},
{
"path": "pages/tea-specialist/detail",
"type": "page",

View File

@ -38,11 +38,11 @@
<text class="text-22rpx leading-32rpx text-[#818CA9] ml-36rpx">更多茶艺师点击预约</text>
</view>
<!-- <view class="mt-16rpx relative w-690rpx h-180rpx mx-30rpx" @click="router.navigateTo(`/bundle_b/pages/tea-specialist/list`)">
<view class="mt-16rpx relative w-690rpx h-180rpx mx-30rpx" @click="router.navigateTo(`/bundle_b/pages/tea-specialist/list`)">
<wd-img width="690rpx" height="180rpx" :src="`${OSS}images/home/home_image7.png`" mode="scaleToFill" />
</view> -->
</view>
<view class="relative mt-40rpx h-44rpx mx-30rpx">
<!-- <view class="relative mt-40rpx h-44rpx mx-30rpx">
<view class="absolute ele-center" >
<wd-img width="252.04rpx" height="24.43rpx" :src="`${OSS}images/home/home_image3.png`" mode="aspectFit" />
</view>
@ -54,7 +54,7 @@
<text class="mr-8rpx">一键约</text>
<wd-img width="22rpx" height="18.06rpx" :src="`${OSS}icon/icon_arrow_right.png`" mode="aspectFit" />
</view>
</view>
</view> -->
<view>

View File

@ -90,7 +90,7 @@
</view>
</view>
</view>
<view class="font-400 text-24rpx text-[#EECC99] leading-34rpx">会员预定茶室享受8折</view>
<view class="font-400 text-24rpx text-[#EECC99] leading-34rpx">会员预定茶室享受折</view>
</view>
</view>
<view class="mx-40rpx h-40rpx">
@ -291,7 +291,7 @@
// 更多服务
const serviceMenuList = reactive([
{ id: 1, title: '申请茶馆', icon: `${OSS}icon/icon_service_teahouse.png`, badge: '', url: '/bundle/settle-in/tea-room' },
{ id: 1, title: '茶馆入驻', icon: `${OSS}icon/icon_service_teahouse.png`, badge: '', url: '/bundle/settle-in/tea-room' },
{ id: 2, title: '申请茶艺师', icon: `${OSS}icon/icon_service_tea.png`, badge: '', url: '/bundle/settle-in/tea-specialist' },
{ id: 3, title: '合创合伙人', icon: `${OSS}icon/icon_service_partner.png`, badge: '赚佣金', url: '/bundle/settle-in/parten' },
])

View File

@ -7,7 +7,7 @@ export enum TeaSpecialistLevel {
Enthusiast = '茶艺爱好者'
}
// 订单来源对应名称
// 等级名称对应值
export const TeaSpecialistLevelValue = {
['金牌茶艺师']: 'gold',
['高级茶艺师']: 'senior',
@ -18,9 +18,9 @@ export const TeaSpecialistLevelValue = {
// 茶艺师对象结构
export const TeaSpecialistLevels = [
{ id: 1, value: 'gold', label: TeaSpecialistLevel.Gold},
{ id: 2, value: 'senior', label: TeaSpecialistLevel.Senior },
{ id: 3, value: 'intermediate', label: TeaSpecialistLevel.Intermediate },
{ id: 4, value: 'junior', label: TeaSpecialistLevel.Junior },
{ id: 5, value: 'enthusiast', label: TeaSpecialistLevel.Enthusiast }
{ id: 1, value: 'gold', label: TeaSpecialistLevel.Gold, level: 1 },
{ id: 2, value: 'senior', label: TeaSpecialistLevel.Senior, level: 2 },
{ id: 3, value: 'intermediate', label: TeaSpecialistLevel.Intermediate, level: 3 },
{ id: 4, value: 'junior', label: TeaSpecialistLevel.Junior, level: 4 },
{ id: 5, value: 'enthusiast', label: TeaSpecialistLevel.Enthusiast, level: 5 }
];

View File

@ -155,3 +155,15 @@ export function randomLabelColor (index: number) {
return tagColors[index % tagColors.length]
}
/**
* 获取当前年月日格式YYYY-MM-DD
*/
export function getCurrentDate() {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}