完善地址

This commit is contained in:
wangxiaowei
2025-10-21 18:05:47 +08:00
parent 820b445e9c
commit b2f658f3c0
22 changed files with 613 additions and 190 deletions

View File

@ -15,10 +15,6 @@
else {
navigateToInterceptor.invoke({ url: '/' })
}
// 微信静默授权
// await snsapiBaseAuthorize()
// await initJweixinSDK()
})
onShow((options) => {
console.log('App Show', options)

16
src/api/pay.ts Normal file
View File

@ -0,0 +1,16 @@
import { http } from '@/http/alova'
/**
* 给茶艺师打赏
*/
interface ITipTeaSpecialistParams {
id: number
tip_price: number
pay_type: number
}
export function payTipTeaSpecialist(data: ITipTeaSpecialistParams) {
return http.Post('/api/Teamaster/giveTeamasterTipAmount',
data
)
}

View File

@ -6,9 +6,9 @@ import type { ITeaSpecialistDetailsResult } from '@/api/types/tea'
*/
export interface ITeaSpecialistDetailsParams {
id: number
longitude: number
latitude: number
user_id: number
longitude: number | ''
latitude: number | ''
user_id: number | ''
}
export function getTeaSpecialistDetails(data: ITeaSpecialistDetailsParams) {
@ -33,3 +33,10 @@ export function collectTeaSpecialist(data: ICollectTeaSpecialistParams) {
data
)
}
/**
* 获取打赏金额
*/
export function getTeaSpecialistRewardAmounts() {
return http.Post('/api/Teamaster/teamasterTipAmount')
}

View File

@ -28,3 +28,12 @@ export interface ITeaSpecialistDetailsFields {
fare_price: number
collect: number
}
/**
* 茶艺师打赏金额
*/
export interface ITeaSpecialistRewardAmountsResult {
id: number
status: number
tip_price: number
}

42
src/api/types/user.ts Normal file
View File

@ -0,0 +1,42 @@
/**
* 用户信息结果类型
*/
export interface IUserInfoResult {
account: string
avatar: string
create_time: string
has_auth: boolean
has_password: boolean
id: number
mobile: string
nickname: string
real_name: string
sex: string
sn: number
user_money: string
version: number
}
/**
* 地址列表
*/
export interface IUserAddressListResult {
id: number
contact: string
telephone: string
province: string
province_id: number
city: string
city_id: number
district: string
district_id: number
address: string
is_default: number
}
/**
* 地址详情
*/
export interface IUserAddressDetailsResult extends IUserAddressListResult {
address_details: IUserAddressListResult
}

75
src/api/user.ts Normal file
View File

@ -0,0 +1,75 @@
import { http } from '@/http/alova'
import type { IUserAddressListResult, IUserAddressDetailsResult } from '@/api/types/user'
/**
* 获取用户个人信息
*/
export function getUserInfo() {
return http.Post('/api/user/info')
}
/**
* 获取优惠券列表
*/
export function getUserCoupons() {
return http.Post('/api/UserCoupon/UserCoupinList')
}
/**
* 获取用户地址
*/
export function getUserAddress() {
return http.Post('/api/user/addressList')
}
/**
* 用户添加地址
*/
export interface IAddUserAddressParams {
contact: string
telephone: string
province: string
province_id?: number
city: string
city_id?: number
district: string
district_id?: number
address: string
is_default: number
}
export function addUserAddress(data: IAddUserAddressParams) {
return http.Post<IUserAddressListResult>('/api/user/addAddress', data)
}
/**
* 编辑用户地址
*/
export interface IEditUserAddressParams extends IAddUserAddressParams {
id: number
}
export function editUserAddress(data: IAddUserAddressParams) {
return http.Post('/api/user/editAddress', data)
}
/**
* 删除用户地址
*/
export interface IDeleteUserAddressParams {
id: number
}
export function deleteUserAddress(data: IDeleteUserAddressParams) {
return http.Post('/api/user/delAddress', data)
}
/**
* 获取地址详情
*/
export interface IUserAddressDetailsParams extends IDeleteUserAddressParams {}
export function userAddressDetails(data: IUserAddressDetailsParams) {
return http.Post<IUserAddressDetailsResult>('/api/user/addressDetails', data)
}

View File

@ -12,7 +12,7 @@
<view class="ml-20rpx text-30rpx text-[#303133] leading-42rpx">{{ item.name }}</view>
</view>
</view>
<view class="absolute right-0 top-6rpx right-60rpx" v-if="item.type !== PayCategory.WeChatPay">可用202.22</view>
<view class="absolute right-0 top-6rpx right-60rpx" v-if="item.type !== PayCategory.WeChatPay">可用{{ userInfo.user_money }}</view>
</wd-radio>
</block>
</wd-radio-group>
@ -24,12 +24,37 @@
* Pay 支付组件
* @description 用于展示支付
*/
import { PayList as OriginPayList, PayCategory, PayValue } from '@/utils/pay'
import { IUserInfoResult } from '@/api/types/user'
import { getUserInfo } from '@/api/user'
const OSS = inject('OSS')
const pay = ref<number>() // 支付方式
// 当前用户信息
const userInfo = reactive<IUserInfoResult>({
account: '',
avatar: '',
create_time: '',
has_auth: false,
has_password: false,
id: 0,
mobile: '',
nickname: '',
real_name: '',
sex: '',
sn: 0,
user_money: '',
version: 0
})
onMounted(async () => {
// 获取个人用户信息
const userRes = await getUserInfo()
Object.assign(userInfo, userRes || {})
})
const props = defineProps({
// 是否隐藏平台余额支付
hidePlatformBalance: {
@ -52,6 +77,7 @@
// 定义emit事件
const emit = defineEmits(['pay'])
const Pay = {
// 支付方式改变
handleChangePay(e: {value: number}) {
@ -71,6 +97,7 @@
watch(PayList, (list) => {
if (list.length > 0) {
pay.value = list[0].value
emit('pay', pay.value )
} else {
pay.value = undefined
}

View File

@ -1,7 +1,7 @@
import {wxSnsapiBaseLogin} from '@/api/login'
import { useUserStore } from '@/store'
import type { IUserInfoVo } from '@/api/types/login'
import { jump, NAVIGATE_TO } from '@/utils/tools'
import { router } from '@/utils/tools'
import { toast } from '@/utils/toast'
/**
@ -27,17 +27,17 @@ export const getUrlCode = (): { [key: string]: string | undefined } => {
*/
export async function snsapiBaseAuthorize() {
// TODO 测试代码
// wxSnsapiBaseLogin({code: '001Vgi0w3dwIP538nE1w32v6j83Vgi0X'}).then((res: IUserInfoVo) => {
// console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
// // 映射 IUserLogin 到 IUserInfoVo
// useUserStore().setUserInfo(res)
// }).catch(err => {
// // 失败就重新授权
// uni.setStorageSync('wechatCode', 0)
// console.log('请求失败', err)
// })
wxSnsapiBaseLogin({code: '0617Y41007CraV1LKJ300cvi1P27Y41I'}).then((res: IUserInfoVo) => {
console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
// 映射 IUserLogin 到 IUserInfoVo
useUserStore().setUserInfo(res)
}).catch(err => {
// 失败就重新授权
uni.setStorageSync('wechatCode', 0)
console.log('请求失败', err)
})
// return
return
let local = window.location.href // 获取页面url
let appid = import.meta.env.VITE_WX_SERVICE_ACCOUNT_APPID // 公众号的APPID
@ -66,7 +66,7 @@ export async function snsapiBaseAuthorize() {
if (!res.mobile) {
// 如果没有绑定手机号的话需要去绑定手机号
toast.info('请先绑定手机号')
jump('/pages/login/mobile', NAVIGATE_TO, 500)
router.navigateTo('/pages/login/mobile', 500)
} else {
uni.$emit('loginSuccess')
}

View File

@ -7,7 +7,7 @@ import VueHook from 'alova/vue'
import { toast } from '@/utils/toast'
import { ContentTypeEnum, ResultEnum, ShowMessage } from './tools/enum'
import { useUserStore } from '@/store'
import { jump, SWITCH_TAB, NAVIGATE_TO } from '@/utils/tools'
import { router } from '@/utils/tools'
// 配置动态Tag
export const API_DOMAINS = {
@ -72,13 +72,13 @@ const alovaInstance = createAlova({
if (!token) {
toast.info('请先登录')
jump('/pages/my/my', SWITCH_TAB, 500)
router.switchTab('/pages/my/my', 500)
throw new Error('[请求错误]:未登录')
}
if (!mobile) {
toast.info('请先绑定手机号')
jump('/pages/login/mobile', NAVIGATE_TO, 500)
router.navigateTo('/pages/login/mobile', 500)
throw new Error('[请求错误]:未绑定手机号')
}
@ -121,15 +121,13 @@ const alovaInstance = createAlova({
// 处理业务逻辑错误
const { code, msg, data } = rawData as IResponse
// if (code === ResultEnum.Unauthorized) {
// if (config.meta?.toast !== false) {
// toast.info(msg)
// setTimeout(() => {
// uni.navigateTo({ url: '/pages/login/mobile' })
// })
// }
// throw new Error(`登录超时[${code}]${msg}`)
// }
if (code === ResultEnum.Unauthorized) {
if (config.meta?.toast !== false) {
toast.info(msg)
router.switchTab('/pages/my/my')
}
throw new Error(`登录超时[${code}]${msg}`)
}
if (code === ResultEnum.Success) {
if (config.meta?.toast !== false && msg) {

View File

@ -143,8 +143,7 @@
"type": "page",
"layout": "default",
"style": {
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#fff"
"navigationStyle": "custom"
}
},
{

View File

@ -11,7 +11,7 @@
<template>
<view>
<view>
<navbar :title="title" custom-class='!bg-[#fff]'></navbar>
<navbar :title="title" custom-class='!bg-[#fff]' :leftArrow="false"></navbar>
</view>
<view>
@ -19,7 +19,7 @@
<view class="flex items-center mx-36rpx">
<view class="text-30rpx leading-42rpx text-#303133 mr-60rpx w-100rpx">联系人</view>
<view>
<wd-input v-model="form.name" size="large" placeholder="请填写联系人" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
<wd-input v-model="form.contact" size="large" placeholder="请填写联系人" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
</view>
</view>
<view class="h-2rpx bg-#F2F2F2"></view>
@ -29,7 +29,7 @@
<view class="flex items-center mx-36rpx">
<view class="text-30rpx leading-42rpx text-#303133 mr-60rpx w-100rpx">电话</view>
<view>
<wd-input v-model="form.name" size="large" placeholder="请填写联系电话" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
<wd-input v-model="form.telephone" size="large" placeholder="请填写联系电话" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
</view>
</view>
<view class="h-2rpx bg-#F2F2F2"></view>
@ -39,7 +39,7 @@
<view class="flex items-center mx-36rpx">
<view class="text-30rpx leading-42rpx text-#303133 mr-60rpx w-100rpx">省市区</view>
<view class="add-address">
<wd-col-picker v-model="value" :columns="area" :column-change="columnChange" @confirm="Add.handleConfirmAddress" placeholder="请选择省市区"></wd-col-picker>
<wd-col-picker v-model="address" :columns="area" :column-change="columnChange" @confirm="Add.handleConfirmAddress" placeholder="请选择省市区"></wd-col-picker>
</view>
</view>
<view class="h-2rpx bg-#F2F2F2"></view>
@ -49,7 +49,7 @@
<view class="flex items-center mx-36rpx">
<view class="text-30rpx leading-42rpx text-#303133 mr-60rpx w-100rpx">地址</view>
<view>
<wd-input v-model="form.name" size="large" placeholder="请填写具体地址" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
<wd-input v-model="form.address" size="large" placeholder="请填写具体地址" no-border placeholderStyle="font-size: 30rpx; line-height: 42rpx; color: #c9c9c9;"></wd-input>
</view>
</view>
</view>
@ -73,17 +73,28 @@
</view>
<view class="flex items-center justify-between mx-30rpx" v-if="addressId > 0">
<view class="w-330rpx h-90rpx leading-90rpx text-center bg-[#F6F7F8] text-#303133 rounded-8rpx mr-30rpx">删除地址</view>
<view class="w-330rpx h-90rpx leading-90rpx text-center bg-[#F6F7F8] text-#303133 rounded-8rpx mr-30rpx" @click="Add.handleDeleteAddress">删除地址</view>
<view class="w-330rpx h-90rpx leading-90rpx text-center bg-[#4C9F44] text-#FFFFFF rounded-8rpx">确定</view>
</view>
</view>
<!-- 删除地址 -->
<wd-message-box selector="wd-message-box-slot"></wd-message-box>
</view>
</template>
<script lang="ts" setup>
import { useMessage } from 'wot-design-uni'
import { addUserAddress, IAddUserAddressParams, deleteUserAddress, userAddressDetails } from '@/api/user'
import { toast } from '@/utils/toast'
import { mobile } from '@/utils/test'
import { router } from '@/utils/tools'
const OSS = inject('OSS')
// 弹出框
const message = useMessage('wd-message-box-slot')
// 页面标题
const title = ref<string>('新增地址')
@ -91,15 +102,22 @@
const addressId = ref<number>(0)
// 表单信息
const form = reactive<{
name: string,
}>({
name: '',
const form = reactive<IAddUserAddressParams>({
contact: '',
telephone: '',
province: '',
province_id: 0,
city: '',
city_id: 0,
district: '',
district_id: 0,
address: '',
is_default: 0
})
// 省市区数据
const { colPickerData, findChildrenByCode } = useColPickerData()
const value = ref<string[]>([])
const address = ref<string[]>([])
const area = ref<any[]>([
colPickerData.map((item) => {
return {
@ -132,17 +150,98 @@
// 编辑地址
title.value = '修改地址'
addressId.value = Number(args.id)
Add.handleGetAddressDetails()
}
})
const Add = {
// 确认省市区
handleConfirmAddress: (e) => {
console.log('e', 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 () => {
const res = await userAddressDetails({
id: addressId.value
})
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
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
address.value = [res.address_details.province, res.address_details.city, res.address_details.district]
},
// 删除地址
handleDeleteAddress: async () => {
console.log("🚀 ~ 删除地址:", message)
message.confirm({
title: '删除地址',
msg: '确定要删除该地址吗?',
confirmButtonText: '确定',
cancelButtonText: '取消',
cancelButtonProps: {
customClass: '!bg-[#F6F7F8] !text-[#303133] !text-32rpx !leading-44rpx !rounded-8rpx',
},
confirmButtonProps: {
customClass: '!bg-[#4C9F44] !text-[#fff] !text-32rpx !leading-44rpx !rounded-8rpx',
}
}).then(async (res) => {
// 点击确认按钮回调事件
await deleteUserAddress({
id: addressId.value
})
toast.info('删除成功')
uni.$emit('refreshAddressList')
router.navigateBack(500)
}).catch((res) => {
console.log("🚀 ~ res2:", res)
// 点击取消按钮回调事件
})
},
// 添加地址
handleAddAddress: () => {
handleAddAddress: async () => {
if (!form.contact) {
toast.info('请填写联系人')
return
}
if (!mobile(form.telephone)) {
toast.info('请填写正确手机号格式')
return
}
if (!form.province || !form.city || !form.district) {
toast.info('请选择省市区')
return
}
if (!form.address) {
toast.info('请填写具体地址')
return
}
form.is_default = isDefaultAddress.value ? 1 : 0
await addUserAddress(form)
uni.$emit('refreshAddressList')
router.navigateBack(500)
}
}
</script>

View File

@ -11,12 +11,12 @@
<template>
<view class="">
<view>
<navbar title="地址簿" custom-class='!bg-[#F6F7F8]'></navbar>
<navbar title="地址簿" custom-class='!bg-[#F6F7F8]' :leftArrow="false"></navbar>
</view>
<view class="">
<!-- 地址为空显示 -->
<view class="text-center">
<view class="text-center" v-if="addressList.length === 0">
<view class="mt-318rpx">
<wd-img width="290rpx" height='200rpx' :src="`${OSS}images/h5/address/address_image1.png`"></wd-img>
</view>
@ -24,21 +24,21 @@
</view>
<!-- 地址列表 -->
<view class="mx-30rpx mt-20rpx">
<view class="bg-#fff rounded-16rpx px-30rpx py-36rpx flex items-center mb-20rpx" @click="Address.handleEditAddress">
<view class="mx-30rpx mt-20rpx" v-if="addressList.length > 0">
<view class="bg-#fff rounded-16rpx px-30rpx py-36rpx flex items-center mb-20rpx" v-for="(item, index) in addressList" :key="index">
<view>
<view class="flex items-center">
<view class="mr-10rpx">
<wd-tag color="#4C9F44" bg-color="#F3F3F3" custom-class="!rounded-4rpx !px-10rpx">默认</wd-tag>
<wd-tag color="#4C9F44" bg-color="#F3F3F3" custom-class="!rounded-4rpx !px-10rpx" v-if="item.is_default">默认</wd-tag>
</view>
<view class="text-30rpx leading-42rpx text-#303133">
<text class="mr-16rpx">金金</text>
<text>15800000000</text>
<text class="mr-16rpx">{{ item.contact}}</text>
<text>{{ item.telephone }}</text>
</view>
</view>
<view class="w-562rpx line-1 text-26rpx leading-34rpx text-#909399 mt-10rpx">北京市海淀区恒大新宏福苑西区20号楼2单元301</view>
<view class="w-562rpx line-1 text-26rpx leading-34rpx text-#909399 mt-10rpx">{{ item.address }}</view>
</view>
<view class="flex-1 ml-30rpx">
<view class="flex-1 ml-30rpx" @click="Address.handleEditAddress(item.id)">
<wd-icon name="edit-outline" size="32rpx" color="#666666"></wd-icon>
</view>
</view>
@ -50,17 +50,43 @@
</template>
<script lang="ts" setup>
import { getUserAddress } from '@/api/user'
import type { IUserAddressListResult } from '@/api/types/user'
import { router } from '@/utils/tools'
const OSS = inject('OSS')
// 地址列表
const addressList = ref<IUserAddressListResult[]>([])
onLoad(() => {
uni.$on('refreshAddressList', () => {
Address.handleInit()
})
// 初始化地址列表
Address.handleInit()
})
onUnload(() => {
uni.$off('refreshAddressList')
})
const Address = {
// 初始化地址列表
handleInit: async () => {
const res = await getUserAddress()
addressList.value = Array.isArray(res) ? res : []
},
// 跳转地址列表
handleToAddressList: () => {
uni.navigateTo({ url: '/pages/address/add' })
router.navigateTo('/pages/address/add')
},
// 编辑地址
handleEditAddress: () => {
uni.navigateTo({ url: '/pages/address/add?id=1' })
handleEditAddress: (id: number) => {
router.navigateTo(`/pages/address/add?id=${id}`)
}
}
</script>

View File

@ -6,19 +6,17 @@
}
}
</route>
<template>
<view class="">
<view>
<navbar title="收银台" custom-class='!bg-[#F6F7F8]'></navbar>
<view>
<navbar title="收银台" custom-class='!bg-[#F6F7F8]' :leftArrow="false"></navbar>
</view>
<!-- 支付信息 -->
<view class="mt-56rpx text-center">
<view class="text-28rpx leading-40rpx text-#606266">顾客打赏-茶艺师名字</view>
<view class="text-28rpx leading-40rpx text-#606266">顾客打赏-{{ info.name }}</view>
<view class="mt-24rpx">
<price-format color="#303133" :first-size="44" :second-size="44" :subscript-size="28" :price="100"></price-format>
<price-format color="#303133" :first-size="44" :second-size="44" :subscript-size="28" :price="tipMoney"></price-format>
</view>
<view class="mt-12rpx flex items-center justify-center">
<view class="text-24rpx leading-34rpx text-#606266">
@ -35,20 +33,86 @@
<pay hide-store-balance @pay="Cashier.handleGetPayValue"></pay>
</view>
<view class="fixed bottom-70rpx left-0 right-0 bg-#4C9F44 text-#fff font-bold text-30rpx leading-42rpx mx-60rpx h-90rpx leading-90rpx text-center rounded-8rpx">立即支付</view>
<view
class="fixed bottom-70rpx left-0 right-0 bg-#4C9F44 text-#fff font-bold text-30rpx leading-42rpx mx-60rpx h-90rpx leading-90rpx text-center rounded-8rpx"
@click="Cashier.handleToPay">立即支付
</view>
</view>
</template>
<script lang="ts" setup>
import Pay from '@/components/Pay.vue'
import { getTeaSpecialistDetails } from '@/api/tea'
import { ITeaSpecialistDetailsFields } from '@/api/types/tea'
import { toast } from '@/utils/toast'
import { router } from '@/utils/tools'
import { payTipTeaSpecialist } from '@/api/pay'
// 支付倒计时取消
const time = ref<number>(30 * 60 * 60 * 1000)
// 打赏金额
const tipMoney = ref<number>(0)
// 茶艺师详情
const id = ref<number>(0)
const info = reactive<ITeaSpecialistDetailsFields>({
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
})
// 支付方式
const pay = ref<number>(0)
onLoad(async (args) => {
if (args.id && args.lat && args.lng && args.user_id && args.money) {
id.value = Number(args.id)
tipMoney.value = Number(args.money)
// 获取茶艺师详情
const res = await getTeaSpecialistDetails({
id: args.id,
latitude: args.lat,
longitude: args.lng,
user_id: args.user_id
})
// 将返回的数据合并到 reactive 对象中
Object.assign(info, res.teamaster || {})
} else {
toast.info('参数错误')
return
}
console.log('页面加载')
})
const Cashier = {
// 获取支付方式
handleGetPayValue(value: number) {
console.log('支付方式', value)
handleGetPayValue: (value: number) => {
pay.value = value
},
// 去支付
handleToPay: () => {
payTipTeaSpecialist({
id: id.value,
tip_price: tipMoney.value,
pay_type: pay.value
}).then(res => {
router.navigateTo('/pages/notice/reserve?type=tipSuccess')
console.log("🚀 ~ res:", res)
})
}
}
</script>

View File

@ -31,10 +31,10 @@
<view class="mt-62rpx flex justify-between items-center mx-30rpx" v-if="!isOtherTip">
<view class="bg-#F0F6EF flex flex-col items-center justify-center h-240rpx px-20rpx py-24rpx w-[22%] rounded-4rpx text-center"
v-for="(item, index) in tipList" :key="index" @click="Detail.handleTipTeaSpecialist(item)">
<wd-img width="64rpx" height='64rpx' :src="item.image"></wd-img>
<wd-img width="64rpx" height='64rpx' :src="`${OSS}images/h5/tip/tip_image${index + 1}.png`"></wd-img>
<view class="font-bold text-#006C2D text-40rpx leading-30rpx mt-20rpx">
<price-format color="#006C2D" :first-size="40" :subscript-size="22" :show-decimal="false" :price="item.amount" v-if="item.amount > 0"></price-format>
<view class="font-400 text-26rpx leading-36rpx text-#006C2D" v-if="item.amount == 0">其他金额</view>
<price-format color="#006C2D" :first-size="40" :subscript-size="22" :show-decimal="false" :price="item.tip_price" v-if="item.tip_price > 0"></price-format>
<view class="font-400 text-26rpx leading-36rpx text-#006C2D" v-if="item.tip_price == 0">其他金额</view>
</view>
<view class="bg-#4C9F44 rounded-8rpx w-120rpx h-48rpx leading-48rpx text-#fff text-28rpx mt-16rpx">打赏</view>
</view>
@ -42,10 +42,9 @@
<!-- 自定义打赏金额 -->
<view class="mx-30rpx mt-46rpx" v-if="isOtherTip">
<wd-input
clearable
type="text"
placeholder="请输入1~50元的金额"
:v-model="tipMoney"
v-model="tipMoney"
no-border
custom-class="!bg-[#F6F7F8] !rounded-16rpx !text-30rpx !leading-48rpx"
custom-input-class="!h-104rpx !pl-60rpx">
@ -60,8 +59,8 @@
<view class="font-400 text-24rpx leading-34rpx text-#909399 mt-34rpx mx-30rpx">打赏金额将给到茶艺师是您自愿对于茶艺师的赠与</view>
<view class="text-32rpx leading-44rpx text-center flex items-center justify-center mt-136rpx" v-if="isOtherTip">
<view class="w-330rpx h-90rpx leading-90rpx bg-#F6F7F8 text-#303133 rounded-8rpx mr-30rpx">在想想</view>
<view class="w-330rpx h-90rpx leading-90rpx bg-#4C9F44 text-#fff rounded-8rpx">打赏</view>
<view class="w-330rpx h-90rpx leading-90rpx bg-#F6F7F8 text-#303133 rounded-8rpx mr-30rpx" @click="isOtherTip = false">在想想</view>
<view class="w-330rpx h-90rpx leading-90rpx bg-#4C9F44 text-#fff rounded-8rpx" @click="Detail.handleTipTeaSpecialistOtherMoney">打赏</view>
</view>
</view>
@ -79,9 +78,9 @@
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_sc.png`"></wd-img>
</template>
</view>
<view @click="Detail.handleShare" class="flex items-center">
<!-- <view @click="Detail.handleShare" class="flex items-center">
<wd-img width="64rpx" height="64rpx" :src="`${OSS}icon/icon_share.png`"></wd-img>
</view>
</view> -->
</view>
</template>
</navbar>
@ -265,7 +264,7 @@
</view>
打赏
</view>
<view class="w-330rpx h-90rpx bg-[#4C9F44] rounded-8rpx text-#fff" @click="Detail.handleReserveTeaRoom">立即预定</view>
<view class="w-330rpx h-90rpx bg-[#4C9F44] rounded-8rpx text-#fff" @click="Detail.handleReserveTeaspecialist">立即预定</view>
</view>
</view>
</view>
@ -274,13 +273,14 @@
<script lang="ts" setup>
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import { useMessage } from 'wot-design-uni'
import { getTeaSpecialistDetails, collectTeaSpecialist } from '@/api/tea'
import { getTeaSpecialistDetails, collectTeaSpecialist, getTeaSpecialistRewardAmounts } from '@/api/tea'
import { ITeaSpecialistDetailsFields } from '@/api/types/tea'
import type { ITeaSpecialistRewardAmountsResult } from '@/api/types/tea'
import { toast } from '@/utils/toast'
import { TeaSpecialistLevelValue } from '@/utils/teaSpecialist'
import { jump, NAVIGATE_TO } from '@/utils/tools'
import { router } from '@/utils/tools'
import { useUserStore } from '@/store'
import type {IUserInfoVo} from '@/api/types/login'
import type {IUserInfoVo } from '@/api/types/login'
import { wxShare } from '@/utils/jwexin'
const OSS = inject('OSS')
@ -327,19 +327,14 @@
// 打赏主茶艺师
const showTipTeaSpecialistPopup = ref<boolean>(false)
const tipList = ref<Array<any>>([
{id: 1, image: `${OSS}images/h5/tip/tip_image1.png`, amount: 5},
{id: 2, image: `${OSS}images/h5/tip/tip_image2.png`, amount: 10},
{id: 3, image: `${OSS}images/h5/tip/tip_image3.png`, amount: 20},
{id: 4, image: `${OSS}images/h5/tip/tip_image4.png`, amount: 0},
])
const tipList = ref<Array<ITeaSpecialistRewardAmountsResult>>([])
const isOtherTip = ref<boolean>(false) // 是否是其他打赏金额
const tipMoney = ref<Number>(0) // 其他打赏金额
const tipMoney = ref<string>('') // 其他打赏金额
onLoad(async (args) => {
const userStore = useUserStore()
userInfo.value = userStore.userInfo
console.log("🚀 ~ userInfo.value :",userInfo.value)
id.value = args.id || 0
latitude.value = args.lat || 0
@ -363,6 +358,14 @@
}
})
}
// 处理分享
Detail.handleShare()
// 获取打赏金额
getTeaSpecialistRewardAmounts().then((res: Array<ITeaSpecialistRewardAmountsResult>) => {
tipList.value = res
})
})
const Detail = {
@ -387,12 +390,8 @@
imgUrl: image,
link: url
}
wxShare(params)
},
// 预约茶室
handleReserveTeaRoom: () => {
jump('/pages/reserve/tea-room', NAVIGATE_TO)
wxShare(params)
},
// 立即邀约
@ -412,13 +411,35 @@
},
// 打赏茶艺师
handleTipTeaSpecialist: (item: any) => {
if (item.amount == 0) {
handleTipTeaSpecialist: (item: ITeaSpecialistRewardAmountsResult) => {
if (!userInfo.value.token) {
toast.info('请先登录')
router.switchTab('/pages/my/my', 500)
return
}
if (item.tip_price == 0) {
isOtherTip.value = true
} else {
showTipTeaSpecialistPopup.value = false
router.navigateTo(`/pages/cashier/cashier?id=${id.value}&lat=${latitude.value}&lng=${longitude.value}&user_id=${userInfo.value.id}&money=${item.tip_price}`)
}
},
// 打赏茶艺师其它金额
handleTipTeaSpecialistOtherMoney: () => {
if (Number(tipMoney.value) < 1 || Number(tipMoney.value) > 50) {
toast.info('请输入1~50元的金额')
return
}
showTipTeaSpecialistPopup.value = false
router.navigateTo(`/pages/cashier/cashier?id=${id.value}&lat=${latitude.value}&lng=${longitude.value}&user_id=${userInfo.value.id}&money=${tipMoney.value}`)
},
// 预约茶艺师
handleReserveTeaspecialist: () => {
router.navigateTo(`/pages/reserve/tea-room?id=${id.value}`)
},
}
</script>

View File

@ -160,6 +160,7 @@
import {getDecorate, getTeaSpecialistLevels, getTeaSpecialist} from '@/api/home'
import {getCity} from '@/api/city'
import type { IIndexListResult } from '@/api/types/home'
import { router } from '@/utils/tools'
const OSS = inject('OSS')
@ -259,9 +260,7 @@
// 跳转到预约茶艺师页面
handleToReserveTeaSpecialist: (id: number = 1) => {
uni.navigateTo({
url: `/pages/index/detail?id=${id}&lat=${latitude.value}&lng=${longitude.value}`
})
router.navigateTo(`/pages/index/detail?id=${id}&lat=${latitude.value}&lng=${longitude.value}`)
},
// 选择茶艺师等级
@ -280,9 +279,7 @@
// 跳转到团体预约页面
handleToGroupReserve: () => {
uni.navigateTo({
url: '/pages/reserve/group-tea-specialist'
})
router.navigateTo('/pages/reserve/group-tea-specialist')
}
}
</script>

View File

@ -182,7 +182,7 @@
import { toast } from '@/utils/toast'
import { useUserStore } from '@/store'
import { getUrlCode, snsapiBaseAuthorize } from '@/hooks/useWeiXin'
import { jump, NAVIGATE_TO } from '@/utils/tools'
import { router, NAVIGATE_TO } from '@/utils/tools'
const OSS = inject('OSS')
const navbarHeight = inject('navbarHeight')

View File

@ -1,8 +1,7 @@
<route lang="jsonc" type="page">{
"layout": "default",
"style": {
"navigationBarTitleText": "",
"navigationBarBackgroundColor": "#fff"
"navigationStyle": "custom"
}
}</route>
@ -28,13 +27,25 @@
</template>
</reserve-notice>
</view>
<view v-if="type == 'tipSuccess'">
<reserve-notice title="打赏成功">
<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-24rpx h-90rpx leading-90rpx w-632rpx' @click="reserve.handleTipDone">完成</view>
</view>
</template>
</reserve-notice>
</view>
</view>
</template>
<script lang="ts" setup>
import ReserveNotice from '@/components/notice/Reserve.vue'
const type = ref<string>('') // 购买类型 groupTeaSpecialist: 团体茶艺师预约; teaSpecialist: 茶艺师预约
import { router } from '@/utils/tools'
const type = ref<string>('') // 购买类型 groupTeaSpecialist: 团体茶艺师预约; teaSpecialist: 茶艺师预约; tipSuccess: 打赏成功
onLoad((args) => {
type.value = args.type || ''
@ -43,16 +54,17 @@
const reserve = {
// 预约茶室 - 查看订单
handleRoomSeeOrder: () => {
uni.navigateTo({
url: '/bundle/tea-room/order'
})
router.navigateTo('/bundle/tea-room/order')
},
// 预约茶室 - 完成
handleRoomDone: () => {
uni.switchTab({
url: '/pages/index/index'
})
router.switchTab('/pages/index/index')
},
// 打赏成功 - 完成
handleTipDone: () => {
router.switchTab('/pages/index/index')
}
}
</script>

View File

@ -244,7 +244,7 @@
</wd-popup>
<view>
<navbar title="预约茶"></navbar>
<navbar title="预约茶茶艺师" :leftArrow="false"></navbar>
</view>
<view>
@ -255,15 +255,15 @@
</view>
<view class="">
<view class="font-bold text-[#303133] text-30rpx leading-42rpx mr-14rpx">
茶艺师昵称
{{ info.name }}
</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>
<tea-specialist-level :level="'junior'"></tea-specialist-level>
<tea-specialist-level :level="TeaSpecialistLevelValue[info.teamasterLevel?.[0]?.level_name] || 'junior'"></tea-specialist-level>
</view>
<view class="font-400 text-22rpx leading-32rpx text-#6A6363 mt-30rpx">已预约 10+</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>
</view>
@ -392,10 +392,14 @@
<script lang="ts" setup>
import {toast} from '@/utils/toast'
import {router} from '@/utils/tools'
import PriceFormat from '@/components/PriceFormat.vue'
import {ReserveServiceCategory} from '@/utils/order'
import { PayList, PayCategory, PayValue } from '@/utils/pay'
import Pay from '@/components/Pay.vue'
import { getTeaSpecialistDetails } from '@/api/tea'
import { ITeaSpecialistDetailsFields } from '@/api/types/tea'
import { TeaSpecialistLevelValue } from '@/utils/teaSpecialist'
const OSS = inject('OSS')
@ -451,7 +455,6 @@
// 支付方式
const pay = ref<number>(1)
const html: string = '<p>这里是富文本内容,需要后台传递</p>'
const isGroupBuying: boolean = false // 是否是团购套餐
@ -474,11 +477,46 @@
const showCostPopup = ref<boolean>(false) // 费用明细popup
const showPayPopup = ref<boolean>(false) // 支付popup
onLoad((args) => {
// 茶艺师
const id = ref<number>(0)
const info = reactive<ITeaSpecialistDetailsFields>({
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
})
const is90 = ref<boolean>(false)
onLoad(async (args) => {
if (args.type == ReserveServiceCategory.GroupBuying) {
// TODO 如果是团购套餐则直接微信支付?
pay.value = 3
console.log("🚀 ~ pay.value:", pay.value)
}
if (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
}
})
}
}
})
@ -573,7 +611,7 @@
// 选择地址
handleToAddress: () => {
uni.navigateTo({ url: '/pages/address/list' })
router.navigateTo('/pages/address/list?from=reserve')
},
handleSubmitOrder: () => {

View File

@ -68,7 +68,7 @@ MeScroll.prototype.extendDownScroll = function(optDown) {
beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
showLoading: null, // 显示下拉刷新进度的回调
afterLoading: null, // 显示下拉刷新进度的回调之后,马上要执行的代码 (如: 在wxs中使用)
beforeEndDownScroll: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump
beforeEndDownScroll: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotrouter
endDownScroll: null, // 结束下拉刷新的回调
afterEndDownScroll: null, // 结束下拉刷新的回调,马上要执行的代码 (如: 在wxs中使用)
callback: function(mescroll) {

View File

@ -89,11 +89,12 @@ export async function wxShare(data:IJweiXinShareParams) {
},
cancel: function(res) {}
}
console.log("🚀 ~ wxShare ~ data:", data)
console.log("🚀 ~ wxShare ~ params:", params)
wx.ready(function() {
wx.updateAppMessageShareData(params)
wx.updateTimelineShareData(params)
});
console.log("🚀 ~ wxShare ~ params:", params)
}

View File

@ -16,8 +16,8 @@ export enum PayCategory {
export enum PayValue {
PlatformBalance = 1, // 平台余额
StoreBalance = 2, // 门店余额
WeChatPay = 3, // 微信支付
WeChatPay = 2, // 微信支付
StoreBalance = 3, // 门店余额
}
// 支付方式列表
@ -32,18 +32,19 @@ export const PayList: PayMethod[] = [
},
{
id: 2,
name: '微信支付',
icon: 'icon/icon_weichat.png',
balance: 0,
value: PayValue.WeChatPay,
type: PayCategory.WeChatPay
},
{
id: 3,
name: '门店余额',
icon: 'icon/icon_store_balance.png',
balance: 0,
value: PayValue.StoreBalance,
type: PayCategory.StoreBalance
},
{
id: 3,
name: '微信支付',
icon: 'icon/icon_weichat.png',
balance: 0,
value: PayValue.WeChatPay,
type: PayCategory.WeChatPay
}
]

View File

@ -1,56 +1,51 @@
/**
* 页面跳转方法
* @param url 跳转地址
* @param type 跳转类型 1: switchTab 2: navigateTo 3: navigateBack 4: reLaunch 5: redirectTo
* @param time 延迟时间(毫秒)默认0
*/
export const SWITCH_TAB = 1
export const NAVIGATE_TO = 2
export const NAVIGATE_BACK = 3
export const RE_LAUNCH = 4
export const REDIRECT_TO = 5
export function jump(url: string, type: number, time: number = 0) {
switch (type) {
case SWITCH_TAB:
//跳转至 table
setTimeout(function() {
uni.switchTab({
url
})
}, time);
break;
case NAVIGATE_TO:
export const router = {
//跳转至非table页面
navigateTo: (url: string, time = 0) => {
setTimeout(function() {
uni.navigateTo({
url
})
}, time);
break;
case NAVIGATE_BACK:
},
//跳转至 table
switchTab: (url: string, time = 0) => {
setTimeout(function() {
uni.switchTab({
url
})
}, time);
},
//返回上页面
navigateBack: (delta: number = 1, time = 0) => {
setTimeout(function() {
uni.navigateBack({
delta: parseInt(url),
delta
})
}, time);
break;
case RE_LAUNCH:
},
//关闭当前所有页面跳转至非table页面
reLaunch: (url: string, time = 0) => {
setTimeout(function() {
uni.reLaunch({
url,
url
})
}, time);
break;
case REDIRECT_TO:
},
//关闭当前页面跳转至非table页面
redirectTo: (url: string, time = 0) => {
setTimeout(function() {
uni.redirectTo({
url
})
}, time);
break;
}
},
}