完善茶艺师套餐功能

This commit is contained in:
wangxiaowei
2026-03-31 21:59:42 +08:00
parent 61d0ca2bd1
commit 401b1f0d2f
28 changed files with 593 additions and 176 deletions

10
.vscode/mcp.json vendored Normal file
View File

@ -0,0 +1,10 @@
{
"servers": {
"pencil": {
"type": "stdio",
"command": "E:\\work\\Pencil\\resources\\app.asar.unpacked\\out\\mcp-server-windows-x64.exe",
"args": ["--app", "desktop"],
"env": {}
}
}
}

View File

@ -5,15 +5,69 @@
import { useUserStore } from '@/store'
import { strToParams } from '@/utils/tools'
onLaunch((options) => {
// if (options?.path === 'bundle/order/tea-room/order-detail') {
// uni.setStorageSync('transferOrder', {
// orderId: options?.query?.orderId || '',
// shareSource: options?.query?.shareSource || ''
// })
// console.log("🚀 ~ onLaunch sync:", uni.getStorageSync('transferOrder'))
const showWeixinUpdateFailedModal = () => {
// #ifdef MP-WEIXIN
uni.showModal({
title: '更新失败',
content: '新版本下载失败,请关闭当前小程序后重新进入。',
showCancel: false,
confirmText: '关闭小程序',
success: () => {
if (typeof wx.exitMiniProgram === 'function') {
wx.exitMiniProgram()
return
}
showWeixinUpdateFailedModal()
},
})
// #endif
}
const setupWeixinForcedUpdate = () => {
// #ifdef MP-WEIXIN
if (typeof wx.getUpdateManager !== 'function') {
return
}
const updateManager = wx.getUpdateManager()
updateManager.onCheckForUpdate(({ hasUpdate }) => {
if (!hasUpdate) {
return
}
uni.showLoading({
title: '新版本下载中',
mask: true,
})
})
updateManager.onUpdateReady(() => {
uni.hideLoading()
uni.showModal({
title: '更新提示',
content: '检测到新版本,需重启小程序完成更新。',
showCancel: false,
confirmText: '立即更新',
success: ({ confirm }) => {
if (confirm) {
updateManager.applyUpdate()
}
},
})
})
updateManager.onUpdateFailed(() => {
uni.hideLoading()
showWeixinUpdateFailedModal()
})
// #endif
}
onLaunch((options) => {
setupWeixinForcedUpdate()
// }
// 处理直接进入页面路由的情况如h5直接输入路由、微信小程序分享后进入等
// https://github.com/unibest-tech/unibest/issues/192
if (options?.path) {
@ -22,10 +76,6 @@
else {
navigateToInterceptor.invoke({ url: '/' })
}
// uni.setStorageSync(LOCATION_LAT_KEY, LOCATION_DEFAULT_LAT)
// uni.setStorageSync(LOCATION_LNG_KEY, LOCATION_DEFAULT_LNG)
// uni.setStorageSync(LOCATION_CITY_KEY, LOCATION_DEFAULT_CITY)
})
onShow((options) => {
if (options?.path === 'bundle/order/tea-room/order-detail') {

View File

@ -94,7 +94,7 @@ export function getWxCode() {
* @param params 微信登录参数包含code, reg_source(注册来源,可选)
* @returns Promise 包含登录结果
*/
export function wxLogin(data: { code: string, source?: number }) {
export function wxLogin(data: { code: string, source?: number, store_id?: number }) {
return http.Post<IUserLogin>('/api/login/mnpLogin',
data,
{

View File

@ -17,3 +17,10 @@ export function getTeaPackageList() {
export function getTeaPackageDetail(id: number) {
return http.Post<any>('/api/Teamaster/teamasterGroupDetails', { id })
}
/**
* 获取套餐优惠券
*/
export function getTeaPackageCoupon(id: number, company_name: string, real_name: string, mobile: string ) {
return http.Post<any>('/api/userCoupon/submitYh', { id, company_name, real_name, mobile })
}

View File

@ -51,6 +51,7 @@ export interface IHomeTeaStoreListParams {
latitude: number
longitude: number
city_area_id?: number
level?: number
}
export function getHomeTeaStoreList(data: IHomeTeaStoreListParams) {

View File

@ -116,3 +116,10 @@ export function getExclusiveCirclesLabel() {
}
)
}
/**
* 团体预约茶艺师
*/
export function reserveGroupTeaSpecialist(data) {
return http.Post<any>('/api/user/reservation', data)
}

View File

@ -111,6 +111,31 @@ export function createTeaSpecialistOrder(data: ICreateTeaSpecialistOrderParams)
return http.Post<any>('/api/Teamaster/addTeamOrder', data)
}
/**
* 创建茶艺师套餐订单
*/
export interface ICreateTeaSpecialistPackageOrderParams {
team_user_id: number
server_type: number
longitude: number
latitude: number
store_id: number
start_time: number
end_time: number
hours: number
address: string
remrk: string
is_teacup: number
tea_id: string
user_coupon_id: number
server_number: number
team_group_id?: number
}
export function createTeaSpecialistPackageOrder(data: ICreateTeaSpecialistPackageOrderParams) {
return http.Post<any>('/api/Teamaster/addGroupTeamOrder', data)
}
/***
* 获取订单详情
*/
@ -146,24 +171,3 @@ export interface ITeaSpecialistPayParams {
export function teaSpecialistPay(data: ITeaSpecialistPayParams) {
return http.Post('/api/pay/yuePay', data)
}
/**
* 团体预约
*/
export interface ITeaSpecialistGroupReserveParams {
numbers: string
other_require: string
res_time: string
contact: string
phone: string
code: string
province: string
city: string
district: string
address: string
content: string
}
export function teaSpecialistGroupReserve(data: ITeaSpecialistGroupReserveParams) {
return http.Post('/api/Teamaster/groupReservation', data)
}

View File

@ -617,7 +617,7 @@
// 获取茶叶列表
const tea = await getTeaTypeList({
team_user_id: order.value.team_user_id,
type: 1
type: 0
})
teaList.value = tea
},

View File

@ -0,0 +1,109 @@
<route lang="jsonc" type="page">{
"needLogin": true,
"layout": "default",
"style": {
"navigationBarTitleText": "填写资料",
"navigationBarBackgroundColor": "#fff"
}
}</route>
<template>
<view>
<!-- <wd-navbar title="填写资料" placeholder safeAreaInsetTop :bordered="false">
<template #capsule>
<wd-navbar-capsule @back="router.navigateBack" @back-home="router.switchTab('/pages/index/index')" />
</template>
</wd-navbar> -->
<view class="bg-white rounded-16rpx px-30rpx pt-28rpx mt-20rpx">
<view class="text-32rpx leading-44rpx text-#303133 mb-32rpx flex items-center">
<view class="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>
<view>
<view class="text-26rpx leading-32rpx text-#606266">公司名称</view>
<view class="mt-20rpx border-b border-b-solid border-b-[#F6F7F8] pb-20rpx">
<wd-input no-border placeholder="请填写真实姓名" v-model="form.company_name"></wd-input>
</view>
</view>
<view class="mt-22rpx">
<view class="text-26rpx leading-32rpx text-#606266">姓名</view>
<view class="mt-20rpx border-b border-b-solid border-b-[#F6F7F8] pb-20rpx">
<wd-input no-border placeholder="请填写真实姓名" v-model="form.real_name"></wd-input>
</view>
</view>
<view class="mt-22rpx">
<view class="text-26rpx leading-32rpx text-#606266">手机号</view>
<view class="mt-20rpx border-b border-b-solid border-b-[#F6F7F8] pb-20rpx">
<wd-input no-border placeholder="请填写真实姓名" v-model="form.mobile"></wd-input>
</view>
</view>
</view>
</view>
<!-- 底部按钮 -->
<view class="fixed left-0 right-0 bottom-0 z-2 bg-[#fff] flex items-center justify-center"
:style="{ height: '140rpx' }">
<view class="text-32rpx flex items-center justify-center leading-90rpx text-center w-full px-60rpx">
<view class="flex-1 w-full h-90rpx bg-[#4C9F44] rounded-8rpx text-[#fff]" @click="ClaimCoupon.handleSubmit">提交</view>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import { mobile } from '@/utils/test';
import { router, removeImageUrlPrefix, strToParams } from '@/utils/tools'
import { getTeaPackageCoupon } from '@/api/tea-package'
import { useToast } from 'wot-design-uni'
const toast = useToast()
const OSS = inject('OSS')
const form = reactive({
company_name: '',
real_name: '',
mobile: '',
})
const id = ref<number>(0)
onLoad((args) => {
const scene = args?.scene
if (scene) {
id.value = strToParams(decodeURIComponent(args.scene))?.id
console.log("🚀 ~ id.value:", id.value)
}
})
onShow(() => {
const token = uni.getStorageSync('token')
if (!token) {
router.navigateTo('/pages/login/login')
}
})
const ClaimCoupon = {
handleSubmit: async () => {
if (!id.value) {
toast.show('请重新扫码')
return
}
if (!form.company_name || !form.real_name || !form.mobile) {
toast.show('请完善信息')
return
}
if (!mobile(form.mobile)) {
toast.show('请输入正确的手机号')
return
}
const res = await getTeaPackageCoupon(id.value, form.company_name, form.real_name, form.mobile)
router.switchTab('/pages/index/index', 1000)
}
}
</script>

View File

@ -38,7 +38,7 @@
</view>
<!-- 标题 -->
<view class="text-[#303133] text-36rpx font-bold mt-20rpx">清风套餐-标准品质</view>
<view class="text-[#303133] text-36rpx font-bold mt-20rpx">{{ detail.title }}</view>
<!-- 标签 -->
<view class="flex items-center mt-20rpx">
@ -192,7 +192,8 @@ onLoad((args) => {
// 设置套餐ID
uni.setStorageSync('teaPackageId', args.id)
console.log('teaPackageId', uni.getStorageSync('teaPackageId'))
uni.setStorageSync('teaPackageType', args.type)
console.log('teaPackageId', uni.getStorageSync('teaPackageId'), uni.getStorageSync('teaPackageType'))
teaPackageId.value = args.id
Detail.handleInit()
})

View File

@ -430,7 +430,7 @@ import { useMessage, useToast } from 'wot-design-uni'
import { router, toPlus, previewImage } from '@/utils/tools'
import PriceFormat from '@/components/PriceFormat.vue'
import { OrderType } from '@/utils/order'
import { getTeaTypeList, createTeaSpecialistOrder } from '@/api/tea'
import { getTeaTypeList, createTeaSpecialistPackageOrder } from '@/api/tea'
import type { ITeaSpecialistFuture7DaysResult, ITeaTypeListResult } from '@/api/types/tea'
import BookingTime from '@/components/BookingTime.vue'
import { getTeaSpecialistDetail, getPackageTeaSpecialistFeeDetails } from '@/api/tea-specialist'
@ -654,7 +654,7 @@ const Reserve = {
handleInit: async () => {
const tea = await getTeaTypeList({
team_user_id: id.value,
type: 1
type: uni.getStorageSync('teaPackageType')
})
teaList.value = tea as ITeaTypeListResult[]
},
@ -697,7 +697,7 @@ const Reserve = {
return
}
const res = await getTeaPackageDetail(teaPackageId.value)
const res = await getTeaPackageDetail(uni.getStorageSync('teaPackageId'))
teaPackage.value = res[0]
sevenDay.minimum_time = Number(teaPackage.value.hour)
// costBill.value.package = package.price
@ -730,9 +730,7 @@ const Reserve = {
* 切换预定茶叶选择
*/
handleToggleTea: (id: number, name: string, price: number) => {
console.log("🚀 ~ id:", id)
const index = selectedTea.value.indexOf(id)
console.log("🚀 ~ index:", index)
if (index >= 0) {
// 已选择,取消选择
selectedTea.value.splice(index, 1)
@ -744,7 +742,6 @@ const Reserve = {
selectedTeaTxt.value.push(name)
selectedTeaPrice.value.push(price)
}
console.log("🚀 ~ selectedTea.value:", selectedTea.value)
totalSelectedTeaPrice.value = toPlus(selectedTeaPrice.value)
bill.value.teaService.total = Number(totalSelectedTeaPrice.value) // 更新茶艺服务费用
@ -759,8 +756,6 @@ const Reserve = {
*/
handleToChooseStore: () => {
uni.$on('chooseTeaHouse', params => {
console.log("🚀 ~ params:", params)
uni.$off('chooseTeaHouse')
teaHouse.value = params
@ -965,11 +960,10 @@ const Reserve = {
}
try {
const res = await createTeaSpecialistOrder(params)
const res = await createTeaSpecialistPackageOrder(params)
toast.close()
uni.$on('payment', params => {
console.log("🚀 ~ params:", params)
setTimeout(() => {
uni.$off("payment")
isSubmitting.value = false
@ -978,7 +972,8 @@ const Reserve = {
// 结果通知改为TeaPackage
router.reLaunch(`/pages/notice/reserve?type=${OrderType.TeaPackage}&orderId=${params.orderId}&teaPackageTitle=${teaPackage.value.title}`)
} else {
router.switchTab('/pages/index/index')
toast.info('订单未支付')
router.reLaunch('/bundle/order/tea-specialist/order-list', 800)
}
}, 1000)
})

View File

@ -38,7 +38,17 @@
<!-- 商家信息 -->
<template v-if="serviceType === 1">
<view class="text-34rpx font-bold leading-48rpx text-#303133">商家信息</view>
<view class="mt-32rpx">
<view class="service-search-box relative mt-20rpx">
<wd-search placeholder="门店名称" cancel-txt="搜索" placeholder-left hide-cancel custom-input-class="!h-72rpx" v-model="storeName" >
</wd-search>
<view
class="absolute top-1/2 -translate-y-1/2 right-2rpx w-142rpx h-64rpx leading-64rpx text-center rounded-32rpx bg-#4C9F44 text-#fff font-400 text-32rpx"
@click="Service.handleSearch">
搜索
</view>
</view>
<view class="mt-20rpx">
<mescroll-body @init="mescrollInit" @down="downCallback" @up="Service.upCallback"
:up="upOption">
<wd-radio-group v-model="storeIndex" size="large" shape="dot" checked-color="#4C9F44">
@ -199,6 +209,12 @@ const Service = {
addressList.value = Array.isArray(res) ? res : []
},
// 搜索
handleSearch: () => {
list.value = []
getMescroll().resetUpScroll()
},
/**
* 跳转地址添加/编辑页面
* @param id 地址ID0表示添加非0表示编辑
@ -282,4 +298,12 @@ const Service = {
page {
background: $cz-page-background;
}
.service-search-box {
:deep() {
.wd-search {
padding: 10rpx 0 !important;
}
}
}
</style>

View File

@ -118,7 +118,7 @@
<view class="flex flex-wrap">
<view class="flex flex-wrap items-center">
<view class="mr-8rpx bg-[#4C9F44] text-[#fff] px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx"
v-for="item in info.label" :key="item">{{ item }}</view>
v-for="label in info.label" :key="label.id">{{ label.label_name }}</view>
</view>
</view>
</view>
@ -177,6 +177,7 @@ const TeaSpecialist = {
*/
handleGetTeaSpecialistList: async () => {
if (!hasMore.value) return
console.log("🚀 ~ uni.getStorageSync('teaPackageType'):", uni.getStorageSync('teaPackageType'))
const storage = uni.getStorageSync('selectedPackageService')
const filter = {
@ -184,6 +185,7 @@ const TeaSpecialist = {
size,
latitude: storage.latitude || import.meta.env.VITE_DEFAULT_LATITUDE,
longitude: storage.longitude || import.meta.env.VITE_DEFAULT_LONGITUDE,
level: uni.getStorageSync('teaPackageType'),
}
try {
const res = await getTeaSpecialist(filter)
@ -237,6 +239,7 @@ const TeaSpecialist = {
* 下一步
*/
handleNext: () => {
console.log("🚀 ~ info.value:", info.value)
router.navigateTo(`/bundle/package/reserve?id=${info.value.team_user_id}`)
}
}

View File

@ -100,7 +100,7 @@
</view>
</view>
<view class="flex justify-between items-center">
<view class="flex justify-between items-center mb-54rpx">
<view class="font-400 text-[#303133] text-30rpx leading-42rpx">修改手机号</view>
<view class="flex justify-end">
<view class="flex items-center">
@ -113,6 +113,17 @@
</view>
</view>
</view>
<view class="flex justify-between items-center">
<view class="font-400 text-[#303133] text-30rpx leading-42rpx">版本号</view>
<view class="flex justify-end">
<view class="flex items-center">
<view class="font-400 text-[#303133] text-30rpx leading-42rpx">
2.14.8
</view>
</view>
</view>
</view>
</view>
<view class="bg-white rounded-16rpx mt-144rpx mx-30rpx px-30rpx py-32rpx text-center font-400 text-[#303133] text-30rpx leading-42rpx" @click="showLogoutPopup = true">

View File

@ -24,7 +24,7 @@
</view>
<view class="flex-1">
<wd-input no-border placeholder="请填写预约人数" custom-class="!px-28rpx !py-20rpx"></wd-input>
<wd-input no-border placeholder="请填写预约人数" custom-class="!px-28rpx !py-20rpx" v-model="form.numbers" inputmode="numeric"></wd-input>
</view>
</view>
</view>
@ -35,11 +35,11 @@
<view class="text-32rpx leading-44rpx text-#303133">其他要求</view>
<view class="text-24rpx text-#909399">可以多选</view>
</view>
<wd-checkbox-group v-model="form.other_requirements" shape="square" checked-color="#4C9F44">
<wd-checkbox-group v-model="otherRequirementsModel" shape="square" checked-color="#4C9F44">
<view class="flex flex-wrap">
<view class="w-1/2 mb-30rpx"><wd-checkbox :modelValue="1">需要云华茶艺师</wd-checkbox></view>
<view class="w-1/2 mb-30rpx"><wd-checkbox :modelValue="2">需要茶艺师导师</wd-checkbox></view>
<view class="w-1/2"><wd-checkbox :modelValue="3">需要茶技</wd-checkbox></view>
<view class="w-1/2 mb-30rpx"><wd-checkbox modelValue="需要云华茶艺师">需要云华茶艺师</wd-checkbox></view>
<view class="w-1/2 mb-30rpx"><wd-checkbox modelValue="需要茶艺师导师">需要茶艺师导师</wd-checkbox></view>
<view class="w-1/2"><wd-checkbox modelValue="需要茶技">需要茶技</wd-checkbox></view>
</view>
</wd-checkbox-group>
</view>
@ -50,9 +50,9 @@
<view class="text-32rpx leading-44rpx text-#303133">
预定日期 <text class="text-[#FF3B30] ml-10rpx">*</text>
</view>
<wd-datetime-picker v-model="form.reserve_date" type="date" :min-date="minDate" :max-date="maxDate" use-default-slot @confirm="TeaRoom.handleConfirmDate">
<wd-datetime-picker v-model="form.res_time" type="date" :min-date="minDate" :max-date="maxDate" use-default-slot @confirm="TeaRoom.handleConfirmDate">
<view class="flex items-center">
<view class="text-30rpx mr-8rpx" :class="form.reserve_date ? 'text-#303133' : 'text-#C9C9C9'">
<view class="text-30rpx mr-8rpx" :class="form.res_time ? 'text-#303133' : 'text-#C9C9C9'">
{{ reserveDateStr || '请选择' }}
</view>
<wd-icon name="arrow-right" size="32rpx" color="#C9C9C9"></wd-icon>
@ -73,14 +73,14 @@
<view>
<view class="text-26rpx leading-32rpx text-#606266">联系人</view>
<view class="mt-20rpx border-b border-b-solid border-b-[#F6F7F8] pb-20rpx">
<wd-input no-border placeholder="请填写联系人" v-model="form.username"></wd-input>
<wd-input no-border placeholder="请填写联系人" v-model="form.contact"></wd-input>
</view>
</view>
<view class="mt-22rpx">
<view class="text-26rpx leading-32rpx text-#606266">手机号</view>
<view class="mt-20rpx border-b border-b-solid border-b-[#F6F7F8] pb-20rpx">
<wd-input no-border placeholder="请填写手机号" v-model="form.mobile"></wd-input>
<wd-input no-border placeholder="请填写手机号" v-model="form.phone" inputmode="numeric"></wd-input>
</view>
</view>
@ -140,7 +140,7 @@
订单信息
</view>
<view class="">
<wd-textarea placeholder="有想说的可以在这里写哦!" v-model="form.suggest"
<wd-textarea placeholder="有想说的可以在这里写哦!" v-model="form.content"
custom-class='!rounded-18rpx !border-2rpx !border-[#EFF0EF] !bg-[#F8F9FA]'
custom-textarea-class='!bg-[#F8F9FA]' />
</view>
@ -159,9 +159,11 @@ import { useColPickerData } from '@/hooks/useColPickerData'
import { router, removeImageUrlPrefix } from '@/utils/tools'
import { SMS_ENUM } from '@/enum/sms'
import { mobile } from '@/utils/test'
import { getVerificationCode, addJoinCooperation, getJoinCooperationStatus } from '@/api/user'
import { reserveGroupTeaSpecialist } from '@/api/tea-specialist'
import { getVerificationCode, getJoinCooperationStatus } from '@/api/user'
import { getOpenCityList } from '@/api/tea-room'
import { useToast } from 'wot-design-uni'
import { OrderType } from '@/utils/order'
const OSS = inject('OSS')
const token = ref<string>('') // 用户token
@ -175,49 +177,61 @@ const isSuccess = ref<boolean>(false)
const openCityList = ref<Array<any>>([])
const city = ref<string>('')
// 上传文件
const fileList = ref<any[]>([])
const action = import.meta.env.VITE_UPLOAD_BASEURL // 仅做测试使用,实际请换成真实上传接口
// 验证码倒计时
const countDownTime = ref<number>(1 * 60 * 1000) // 60s倒计时
const startCountDown = ref<boolean>(false) // 是否开始倒计时
const countDown = ref<any>(null) // 倒计时组件
// 表单
const form = ref<{
operation_type: number // 加盟类型
license_img: string // 营业执照
username: string // 联系人姓名
mobile: string // 联系电话
code: string // 验证码
city_id: number // 城市ID
address: string // 详细地址
suggest: string // 意见建议
other_requirements: string[] // 其他要求
reserve_date: number | string // 预定日期
const form = reactive<{
numbers: string
other_requirements: string | string[]
res_time: string | number
contact: string
phone: string
code: string
city_id: string
address: string
content: string
license_img: string
}>({
operation_type: 1,
license_img: '',
username: '',
mobile: '',
code: '',
city_id: 0,
address: '',
suggest: '',
other_requirements: [],
reserve_date: Date.now()
numbers: '', // 预约人数
other_requirements: '', // 其他要求
res_time: '', // 预定日期
contact: '', // 联系人
phone: '', // 联系电话
code: '', // 验证码
city_id: '', // 城市id
address: '', // 详细地址
content: '', // 留言建议
license_img: '' // 证照图片
})
// 审核状态
const status = ref<number>(-1) // 0待审核 1审核成功 2审核失败 3未提交数据
const formatDateToYMD = (value: string | number) => {
if (value === '' || value === null || value === undefined) return ''
const input = typeof value === 'string' && /^\d+$/.test(value) ? Number(value) : value
const d = new Date(input)
if (Number.isNaN(d.getTime())) return ''
return `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`
}
// 预定日期格式化 M月D日
const reserveDateStr = computed(() => {
if (!form.value.reserve_date) return ''
const d = new Date(form.value.reserve_date)
return `${d.getFullYear()}${d.getMonth() + 1}${d.getDate()}`
return formatDateToYMD(form.res_time)
})
const otherRequirementsModel = computed<string[]>({
get: () => Array.isArray(form.other_requirements)
? form.other_requirements
: (form.other_requirements ? [form.other_requirements] : []),
set: (val) => {
form.other_requirements = val
}
})
const minDate = ref<number>(new Date(new Date().setHours(0, 0, 0, 0)).getTime())
const maxDate = ref<number>(new Date(new Date().getFullYear(), 11, 31, 23, 59, 59).getTime())
@ -242,12 +256,12 @@ const TeaRoom = {
* 发送验证码
*/
handleCountDown: async () => {
if (!mobile(form.value.mobile)) {
if (!mobile(form.phone)) {
toast.show('请检查手机号码')
return false
}
await getVerificationCode({ scene: SMS_ENUM.BANK, mobile: String(form.value.mobile) })
await getVerificationCode({ scene: SMS_ENUM.BANK, mobile: String(form.phone) })
startCountDown.value = true
setTimeout(() => {
@ -273,39 +287,60 @@ const TeaRoom = {
* 确认选择预定日期
*/
handleConfirmDate: (e: any) => {
form.value.reserve_date = e.value
form.res_time = e.value
},
/**
* 提交申请
*/
handleSubmit: async () => {
if (!form.value.username) {
if (!form.contact) {
toast.show('请输入联系人')
return false
}
if (!mobile(form.value.mobile)) {
if (!form.res_time) {
toast.show('请选择预定日期')
return false
}
if (!mobile(form.phone)) {
toast.show('请检查手机号码')
return false
}
if (!form.value.code) {
if (!form.code) {
toast.show('请输入验证码')
return false
}
if (!form.value.city_id) {
if (!form.city_id) {
toast.show('请选择地区')
return false
}
if (!form.value.address) {
if (!form.address) {
toast.show('请输入详细地址')
return false
}
form.value.license_img = fileList.value.length > 0 ? removeImageUrlPrefix(fileList.value)[0] : ''
const submitResTime = reserveDateStr.value
const submitOtherRequirements = Array.isArray(form.other_requirements)
? form.other_requirements.join(',')
: form.other_requirements
const payload = {
numbers: form.numbers,
other_requirements: submitOtherRequirements,
res_time: submitResTime,
contact: form.contact,
phone: form.phone,
code: form.code,
city_id: Number(form.city_id),
address: form.address,
content: form.content
}
toast.loading({
loadingType: 'ring',
@ -313,17 +348,13 @@ const TeaRoom = {
msg: '提交中...'
})
try {
await reserveGroupTeaSpecialist(payload as any)
toast.close()
await addJoinCooperation(form.value)
status.value = 0 // 提交成功,变更状态为待审核
setTimeout(() => {
toast.success('提交成功')
}, 100)
router.redirectTo(`/pages/notice/reserve?type=${OrderType.ReserveGroup}`)
} catch (e) {
toast.close()
return
return false
}
}
}

View File

@ -52,10 +52,10 @@
<view class="flex items-center">
<wd-radio-group v-model="form.operation_type" size="large" shape="dot" checked-color="#4C9F44" inline>
<wd-radio :value="1" border>
<view class="leading-36rpx font-400 text-30rpx ml-12rpx mr-60rpx">加盟</view>
<view class="leading-36rpx font-400 text-30rpx ml-12rpx">直营</view>
</wd-radio>
<wd-radio :value="2" border>
<view class="leading-36rpx font-400 text-30rpx ml-12rpx">入驻</view>
<view class="leading-36rpx font-400 text-30rpx ml-12rpx mr-60rpx">加盟</view>
</wd-radio>
</wd-radio-group>
</view>

View File

@ -142,7 +142,7 @@
<view>
<view class="flex items-center flex-wrap">
<view v-for="item in exclusiveCirclesLabel" :key="item.id" class="tea-tag" :style="selectedTags.includes(item.id) ? 'background:#4C9F44;color:#fff;' : 'background:#F3F3F3;color:#818CA9;'
" @click="handleTagClick(item.id)">
" @click="TeaSpecialist.handleTagClick(item.id)">
{{ item.label_name }}
</view>
</view>
@ -332,19 +332,6 @@ const countDownTime = ref<number>(1 * 60 * 1000) // 60s倒计时
const startCountDown = ref<boolean>(false) // 是否开始倒计时
const countDown = ref<any>(null) // 倒计时组件
// 标签点击事件
function handleTagClick(id: number) {
const idx = selectedTags.value.indexOf(id)
if (idx > -1) {
selectedTags.value.splice(idx, 1)
} else {
if (selectedTags.value.length < 6) {
selectedTags.value.push(id)
} else {
toast.show('最多只能选择6个圈子')
}
}
}
// 表单
const form = ref<{
@ -405,6 +392,9 @@ onShow(async () => {
if (token.value) {
const res = await getTeaSpecialistStatus()
status.value = res.status
} else {
console.log("🚀 ~ token.value:", token.value)
router.navigateTo('/pages/login/login')
}
})
@ -420,6 +410,20 @@ const TeaSpecialist = {
exclusiveCirclesLabel.value = label
},
// 标签点击事件
handleTagClick(id: number) {
const idx = selectedTags.value.indexOf(id)
if (idx > -1) {
selectedTags.value.splice(idx, 1)
} else {
if (selectedTags.value.length < 6) {
selectedTags.value.push(id)
} else {
toast.show('最多只能选择6个圈子')
}
}
},
// 选择性别
handleConfirmGender: (gender: string) => {
console.log("🚀 ~ gender:", gender)

View File

@ -185,8 +185,9 @@
</view>
<view class="font-400 text-26rpx leading-36rpx text-#606266">专属圈子</view>
</view>
<view class="flex flex-wrap items-center mt-16rpx" v-for="(item, index) in info.label" :key="index">
<view class="mr-8rpx bg-[#4C9F44] text-[#fff] px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx">{{ item }}</view>
<view class="flex flex-wrap items-center mt-16rpx">
<view class="mr-8rpx bg-[#4C9F44] text-[#fff] px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx"
v-for="(label, index) in info.label" :key="index">{{ label.label_name }}</view>
</view>
</view>
</view>

View File

@ -105,8 +105,8 @@
<view class="flex flex-wrap items-center mt-14rpx">
<view
class="mr-8rpx bg-[#4C9F44] text-[#fff] px-10rpx leading-34rpx font-400 text-24rpx rounded-4rpx"
v-for="(labelText, index) in item.label" :key="index">
{{ labelText }}
v-for="(label, index) in item.label" :key="index">
{{ label.label_name }}
</view>
</view>

View File

@ -609,7 +609,7 @@
handleInit: async () => {
const tea = await getTeaTypeList({
team_user_id: id.value,
type: 1
type: 0
})
teaList.value = tea as ITeaTypeListResult[]
},

View File

@ -242,6 +242,16 @@
"navigationBarTitleText": "分包页面"
}
},
{
"path": "package/claim-coupon",
"type": "page",
"needLogin": true,
"layout": "default",
"style": {
"navigationBarTitleText": "填写资料",
"navigationBarBackgroundColor": "#fff"
}
},
{
"path": "package/detail",
"type": "page",

View File

@ -79,7 +79,7 @@
? 'linear-gradient( 180deg, #FFF3FB 0%, #F6F7F9 100%)'
: 'linear-gradient( 180deg, #FFF9EA 0%, #F6F7F9 100%)'
}"
@click="router.navigateTo(`/bundle/package/detail?id=${item.id}`)"
@click="router.navigateTo(`/bundle/package/detail?id=${item.id}&type=${item.type}`)"
>
<view class="px-10rpx pt-10rpx flex justify-center">
<wd-img width="204rpx" height="124rpx" :src="item.img" radius="16rpx" mode="aspectFill" />

View File

@ -43,10 +43,10 @@
<view class="flex items-center mx-32rpx mt-64rpx">
<view class="w-32rpx h-32rpx">
<wd-checkbox v-model="agree" @change="Login.handleAgree" checked-color="#4C9F44" size="large"> </wd-checkbox>
<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.handleToService">服务协议</text> <text class="text-[#4C9F44]" @click.stop="Login.handleToPrivacy">隐私政策</text>未注册手机号登录后将自动你为您创建账号
我已阅读并同意 <text class="text-[#4C9F44]" @click.stop="Login.handleToWebview('service')">服务协议</text> <text class="text-[#4C9F44]" @click.stop="Login.handleToWebview('privacy')">隐私政策</text>未注册手机号登录后将自动你为您创建账号
</view>
</view>
</view>
@ -57,7 +57,7 @@
import { toast } from '@/utils/toast'
import { getWxCode } from '@/api/login'
import { useUserStore } from '@/store'
import { router } from '@/utils/tools'
import { router, strToParams } from '@/utils/tools'
import { getMobileByMnp } from '@/api/user'
const OSS = inject('OSS')
@ -70,10 +70,20 @@
const redirectUrl = ref<string>('')
const redirectParams = ref<string>('')
// 门店ID
const storeId = ref<number>(0)
// 绑定手机号码popup
const showBindMobilePopup = ref<boolean>(false)
onLoad((args) => {
const scene = args?.scene
console.log("🚀 ~ scene:", scene)
if (scene) {
storeId.value = strToParams(decodeURIComponent(args.scene))?.store_id
console.log("🚀 ~ storeId.value:", storeId.value)
}
redirectUrl.value = args.redirect || ''
})
@ -93,9 +103,7 @@
mask: true
})
try {
console.log("🚀 ~ Login userRegisterSource=", userStore.userRegisterSource)
const res = await userStore.wxLogin()
console.log("🚀 ~ res:", res)
const res = await userStore.wxLogin(Number(storeId.value))
console.log("🚀 ~ token:", uni.getStorageSync('token'))
uni.hideLoading()
if (!res.mobile) {
@ -104,19 +112,6 @@
}
Login.handleToLogin()
// Login.handleToLogin()
// if (res) {
// const decoded = decodeURIComponent(redirectUrl.value)
// console.log("🚀 ~ decoded:", decoded)
// if (decoded == '/bundle/order/tea-room/order-detail') {
// const transferOrderParams = uni.getStorageSync('transferOrderParams')
// uni.$emit('transferOrder', transferOrderParams)
// }
// toast.info('登录成功')
// router.navigateBack(1, 500)
// }
} catch(error) {
uni.hideLoading()
}
@ -180,20 +175,14 @@
}
toast.info('登录成功')
router.navigateBack(1, 500)
},
handleAgree: async (e: any) => {
router.navigateBack(1, 500).catch(err => {
router.switchTab('/pages/my/my')
})
},
// 跳转到服务协议页面
handleToService: () => {
router.navigateTo('/pages/webview/webview?type=service')
},
// 跳转到隐私政策页面
handleToPrivacy: () => {
router.navigateTo('/pages/webview/webview?type=privacy')
handleToWebview: (type: string) => {
router.navigateTo(`/pages/webview/webview?type=${type}`)
},
}
</script>

View File

@ -220,8 +220,7 @@
<view class="bg-white rounded-16rpx mx-30rpx mt-28rpx pb-34rpx">
<view class="px-30rpx pt-30rpx py-24rpx">更多服务</view>
<view class="flex px-30rpx">
<view v-for="(item, index) in serviceMenuList" :key="index">
<navigator :url="item.url" hover-class="none">
<view v-for="(item, index) in serviceMenuList" :key="index" @click="router.navigateTo(`${item.url}`)">
<view class="text-center flex flex-col items-center justify-center mr-30rpx relative" :class="item.badge ? 'w-180rpx ml-[-10rpx]' : 'w-120rpx'">
<view class="w-60rpx h-60rpx flex items-center justify-center">
<wd-img width="100%" height="100%" :src="item.icon"></wd-img>
@ -231,7 +230,6 @@
{{item.badge}}
</view>
</view>
</navigator>
</view>
</view>
</view>

View File

@ -39,7 +39,7 @@
<reserve-notice title="团体茶艺师预约成功" desc="团体茶艺师预约成功">
<template #layout>
<view class="pb-22rpx mt-40rpx mx-30rpx flex justify-between items-center text-[32rpx] text-center">
<view class='bg-[#4C9F44] text-[#fff] rounded-8rpx h-90rpx leading-90rpx w-632rpx' @click="reserve.handleRoomDone">完成</view>
<view class='bg-[#4C9F44] text-[#fff] rounded-8rpx h-90rpx leading-90rpx w-632rpx' @click="router.switchTab('/pages/index/index')">完成</view>
</view>
</template>
</reserve-notice>

View File

@ -115,13 +115,13 @@ export const useUserStore = defineStore(
/**
* 微信登录
*/
const wxLogin = async () => {
const wxLogin = async (storeId: number) => {
// 获取微信小程序登录的code
const data = await getWxCode()
console.log('微信登录code', data)
// 添加注册来源
const loginData = { ...data, source: userRegisterSource.value }
const loginData = { ...data, source: userRegisterSource.value, store_id: storeId }
const res = await _wxLogin(loginData)
uni.setStorageSync('token', res.token)

File diff suppressed because one or more lines are too long