对接接口

This commit is contained in:
wangxiaowei
2025-12-17 00:45:31 +08:00
parent 977f7d4038
commit 018a784a8c
20 changed files with 455 additions and 816 deletions

View File

@ -7,37 +7,26 @@
}</route>
<template>
<view class="mt-54rpx">
<view class="mt-54rpx pb-40rpx">
<view class="font-bold text-44rpx text-[#303133] leading-60rpx text-center">切换账号</view>
<view class="mx-30rpx mt-48rpx">
<view class="bg-white rounded-16rpx px-30rpx py-36rpx flex justify-between items-center mb-20rpx">
<view class="flex items-center">
<wd-img width="70rpx" height="70rpx" round src="https://shchazhi.oss-cn-hangzhou.aliyuncs.com/fronted/icon/icon_avatar.png" mode="aspectFit" />
<view class="w-360rpx line-1 ml-24rpx">茶址24小时智能茶室(...</view>
</view>
<view class="flex-1 flex justify-end">
<template v-if="2 < 1">
<view class="font-400 text-28rpx text-[#4C9F44] leading-40rpx">当前登录</view>
</template>
<template v-if="2 > 1">
<view class="w-120rpx h-60rpx bg-[#4C9F44] text-center leading-60rpx text-[#fff] font-400 text-28rpx leading-40rpx rounded-8rpx text-center">切换</view>
</template>
</view>
</view>
<view class="bg-white rounded-16rpx px-30rpx py-36rpx flex justify-between items-center mb-20rpx">
<view class="flex items-center">
<wd-img width="70rpx" height="70rpx" round src="https://shchazhi.oss-cn-hangzhou.aliyuncs.com/fronted/icon/icon_avatar.png" mode="aspectFit" />
<view class="w-360rpx line-1 ml-24rpx">茶址24小时智能茶室(...</view>
</view>
<view class="flex-1 flex justify-end">
<template v-if="2 > 1">
<view class="font-400 text-28rpx text-[#4C9F44] leading-40rpx">当前登录</view>
</template>
<template v-if="2 < 1">
<view class="w-120rpx h-60rpx bg-[#4C9F44] text-center leading-60rpx text-[#fff] font-400 text-28rpx leading-40rpx rounded-8rpx text-center">切换</view>
</template>
</view>
<view
class="bg-white rounded-16rpx px-30rpx py-36rpx flex justify-between items-center mb-20rpx"
v-for="(item, index) in useStore.storeList" :key="item.id">
<view class="flex items-center">
<wd-img width="70rpx" height="70rpx" round src="https://shchazhi.oss-cn-hangzhou.aliyuncs.com/fronted/icon/icon_avatar.png" mode="aspectFit" />
<view class="w-360rpx line-1 ml-24rpx">{{ item.name }}</view>
</view>
<view class="flex-1 flex justify-end">
<template v-if="item.id === useStore.defaultStore.id">
<view class="font-400 text-28rpx text-[#4C9F44] leading-40rpx">当前登录</view>
</template>
<template v-else>
<view class="w-120rpx h-60rpx bg-[#4C9F44] text-center leading-60rpx text-[#fff] font-400 text-28rpx leading-40rpx rounded-8rpx text-center"
@click="Switch.handleChangeAccount(item, index)">切换
</view>
</template>
</view>
</view>
</view>
</view>
@ -45,6 +34,39 @@
<script lang="ts" setup>
import { useStoreStore } from '@/store'
import { switchStore } from '@/api/store'
import { router } from '@/utils/tools'
// 读取仓库
const useStore = useStoreStore()
// 店铺列表
const storeList = ref<Array<any>>([])
onShow(async () => {
// 获取店铺列表
})
onLoad(() => {
console.log("🚀 ~ useStore.defaultStore:", useStore.defaultStore)
})
const Switch = {
handleChangeAccount: async (item: any, index: number) => {
const res = await switchStore(item.id)
// 切换账号
useStore.setDefaultStore({
id: item.id,
name: item.name,
index
})
// 跳转首页
router.navigateBack()
}
}
</script>
<style lang="scss" scoped>

View File

@ -1,211 +0,0 @@
<route lang="jsonc" type="page">
{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
}
}
</route>
<template>
<view class="pb-180rpx">
<view>
<navbar :title="couponType == 1 ? '优惠券' : '团购券'" custom-class='!bg-[#F6F7F8]'></navbar>
</view>
<view>
<view class="mt-30rpx">
<view v-if="couponType == 1">
<!-- 优惠券 -->
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">可用优惠券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">{{ couponList.use.length }}</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<coupon
v-for="(item, index) in couponList.use"
:key="item.id"
:coupon="item"
canUse
showChecked
:checked="item.id === checkedId"
:onCheck="Coupons.handleCheck"
:class="index !== couponList.use.length - 1 ? 'mb-20rpx' : ''"
></coupon>
</wd-radio-group>
</view>
</view>
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">不可用优惠券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">{{ couponList.no_use.length }}</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<coupon
v-for="(item, index) in couponList.no_use"
:key="item.id"
:coupon="item"
:canUse="false"
showChecked
:checked="item.id === checkedId"
:onCheck="Coupons.handleCheck"
:class="index !== couponList.no_use.length - 1 ? 'mb-20rpx' : ''"
></coupon>
</wd-radio-group>
</view>
</view>
</view>
<!-- 团购券 -->
<view v-if="couponType == 2">
<view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">可用团购券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">2</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<group-coupon
v-for="(item, index) in groupCouponList"
:key="item.id"
:coupon="item"
canUse
:checked="item.id === checkedId"
:onCheck="Coupons.handleCheck"
:class="index !== groupCouponList.length - 1 ? 'mb-20rpx' : ''"
></group-coupon>
</wd-radio-group>
</view>
</view>
<!-- <view class="mx-30rpx">
<view class="mx30rpx">
<text class="text-[#303133] font-bold text-30rpx leading-42rpx">不可用团购券</text>
<text class="text-[#606266] font-400 text-28rpx leading-40rpx ml-24rpx">2</text>
</view>
<view class="mt-28rpx radio">
<wd-radio-group v-model="checkedId" size="large" checked-color="#4C9F44">
<group-coupon
v-for="(item, index) in unCouponList"
:key="item.id"
:coupon="item"
:canUse="false"
:checked="item.id === checkedId"
:onCheck="Coupons.handleCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
></group-coupon>
</wd-radio-group>
</view>
</view> -->
</view>
</view>
</view>
<view class="fixed left-0 right-0 bottom-0 z-2 bg-[#fff] flex justify-between items-center" :style="{ height: '140rpx'}">
<view class="ml-60rpx text-[#121212] text-24rpx leading-34rpx">已选择{{ checkedId ? 1 : 0 }}</view>
<view class="mr-30rpx">
<wd-button custom-class='!bg-[#4C9F44] !rounded-8rpx !h-70rpx' @click="Coupons.handleConfirmCoupon">确定</wd-button>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import Coupon from '@/components/coupon/Coupon.vue'
import GroupCoupon from '@/components/coupon/GroupCoupon.vue'
import { getCoupons } from '@/api/user'
import { getTeaRoomGroupCouponList } from '@/api/tea-room'
import type { IUserCouponListResult } from '@/api/types/user'
import { router } from '@/utils/tools'
import { CouponType } from '@/utils/coupon'
const couponType = ref<number>(2) // couponType 1:优惠券 2:团购券
const couponList = ref<IUserCouponListResult>({
no_use: [],
use: []
})
const groupCouponList = ref<any>()
const checkedId = ref<number>(0)
const unCouponList = ref([
{ id: 1, amount: 20, limit: 100, expire: '2024.08.20' },
{ id: 2, amount: 10, limit: 50, expire: '2024.08.25' }
])
const storeId = ref<number>(0) // 门店ID
const teaRoomId = ref<number>(0) // 包间ID
onLoad((args) => {
teaRoomId.value = args.id
storeId.value = args.storeId || 0
couponType.value = args.type // 1:优惠券 2:团购券
// 初始化优惠券数据
if (args.id && args.numbers && args.type == 1) {
// 获取到包间ID和预定了几个小时
Coupons.handleInitCoupon(args.id, args.numbers)
} else if (args.id && args.type == 2) {
Coupons.handleInitGroupCoupon(args.id, args.numbers)
}
})
const Coupons = {
/**
* 初始化优惠券列表
* @param id 包间ID
* @param numbers 预定时长
*/
handleInitCoupon: async (id: number, numbers: number) => {
const res = await getCoupons({id, numbers, type_id: 2})
couponList.value = res
},
/**
* 初始化团购券列表
*/
handleInitGroupCoupon: async (id: number, numbers: number) => {
const res = await getTeaRoomGroupCouponList({store_id: storeId.value})
groupCouponList.value = res.list
},
/**
* 选择优惠券
* @param id 优惠券ID
*/
handleCheck: (id: number) => {
checkedId.value = id
},
/**
* 确认选择优惠券
*/
handleConfirmCoupon: () => {
let coupon = null
if (couponType.value == CouponType.Discount) {
coupon = couponList.value.use.find(item => item.user_coupon_id === checkedId.value)
} else {
coupon = groupCouponList.value.find(item => item.id === checkedId.value)
}
uni.$emit('chooseCoupon', { coupon })
router.navigateBack()
}
}
</script>
<style lang="scss">
page {
background-color: $cz-page-background;
}
.radio {
:deep() {
.wd-radio-group {
background-color: transparent !important;
}
}
}
</style>

View File

@ -1,182 +0,0 @@
<route lang="jsonc" type="page">
{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
}
}
</route>
<template>
<view class="pb-180rpx">
<view>
<navbar title="优惠券" custom-class='!bg-[#F6F7F8]'></navbar>
</view>
<view>
<view class="coupon-tab">
<wd-tabs v-model="tab" swipeable slidable="always" @click="MyCoupon.handleChangeTab" :lazy="false">
<wd-tab title="茶室优惠券">
<view class="mx-30rpx">
<view class="flex">
<view v-for="(item, index) in tag" :key="index"
@click="MyCoupon.handleChangeTag(item.value)"
class="font-400 text-28rpx leading-40rpx w-116rpx h-64rpx flex justify-center items-center border-2rpx border-solid rounded-12rpx mr-20rpx"
:class="item.value === currentTag ? ' border-[#4C9F44] bg-[#F0F6EF] text-[#4C9F44]' : 'border-[#fff] bg-[#fff]'">
{{ item.label }}
</view>
</view>
<view class="mt-32rpx">
<coupon
v-for="(item, index) in couponList"
:key="item.id"
:coupon="item"
canUse
:showChecked="false"
:checked="item.id === checkedId"
:onCheck="MyCoupon.handleCouponCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
></coupon>
</view>
</view>
</wd-tab>
<wd-tab title="茶艺师优惠券">
<view class="mx-30rpx">
<view class="flex">
<view v-for="(item, index) in tag" :key="index"
@click="MyCoupon.handleChangeTag(item.value)"
class="font-400 text-28rpx leading-40rpx w-116rpx h-64rpx flex justify-center items-center border-2rpx border-solid rounded-12rpx mr-20rpx"
:class="item.value === currentTag ? ' border-[#4C9F44] bg-[#F0F6EF] text-[#4C9F44]' : 'border-[#fff] bg-[#fff]'">
{{ item.label }}
</view>
</view>
<view class="mt-32rpx">
<coupon
v-for="(item, index) in couponList"
:key="item.id"
:coupon="item"
canUse
:showChecked="false"
:checked="item.id === checkedId"
:onCheck="MyCoupon.handleCouponCheck"
:class="index !== couponList.length - 1 ? 'mb-20rpx' : ''"
></coupon>
</view>
</view>
</wd-tab>
</wd-tabs>
</view>
</view>
</view>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import Coupon from '@/components/coupon/Coupon.vue'
import GroupCoupon from '@/components/coupon/GroupCoupon.vue'
import { getMyCoupons } from '@/api/user'
//
const tab = ref<number>(0)
const tag = ref<Array<any>>([
{label: '全部', value: 0 },
{label: '已使用', value: 1 },
{label: '快过期', value: 3 },
])
const currentTab = ref<number>(0)
const currentTag = ref<number>(0)
const couponType = ref<number>(2) // couponType 1:优惠券 2:团购券
const OSS = inject('OSS')
const couponList = ref<any[]>([])
const checkedId = ref<number>(0)
const unCouponList = ref([
{ id: 1, amount: 20, limit: 100, expire: '2024.08.20' },
{ id: 2, amount: 10, limit: 50, expire: '2024.08.25' }
])
onLoad((args) => {
if (args.type) {
couponType.value = args.type
}
MyCoupon.handleInit()
})
const MyCoupon = {
/**
* 初始化优惠券列表
*/
handleInit: async () => {
const res: any = await getMyCoupons({status: currentTag.value, type_id: currentTab.value == 0 ? 2 : 1})
if (Array.isArray(res)) {
res.map((res) => {
couponList.value.push({
id: res.coupon_id,
coupon_price: res.userCouponType[0].coupon_price,
use_price: res.userCouponType[0].use_price,
title: res.userCouponType[0].title,
effect_time: res.userCouponType[0].effect_time,
user_coupon_id: res.coupon_id,
expire: res.expire
})
})
}
},
/**
* 切换tab
* @param item 切换项
*/
handleChangeTab: (item: {index: number}) => {
currentTab.value = item.index
currentTag.value = 0
couponList.value = []
MyCoupon.handleInit()
},
/**
* 切换tag
* @param item 切换项
*/
handleChangeTag: (item: number) => {
currentTag.value = item
couponList.value = []
MyCoupon.handleInit()
},
/**
* 选择优惠券-保留这个函数,暂时用不着
* @param id 切换项
*/
handleCouponCheck: (id: number) => {
checkedId.value = id
}
}
</script>
<style lang="scss">
page {
background-color: $cz-page-background;
}
.coupon-tab {
:deep() {
.wd-tabs,
.wd-tabs__nav,
.wd-tabs__line {
background-color: transparent;
}
.wd-tabs__nav-item.is-active {
font-size: 32rpx !important;
}
}
}
</style>

View File

@ -1,4 +1,5 @@
<route lang="jsonc" type="page">{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
@ -9,9 +10,9 @@
<view>
<view class="mx-60rpx mt-20rpx">
<view class="text-[#303133] text-48rpx leading-80rpx font-600">
修改手机号码
{{ page.title }}
</view>
<view class="font-400 text-28rpx leading-44rpx text-[#6B7280] mt-12rpx">手机号一年内可修改2次</view>
<view class="font-400 text-28rpx leading-44rpx text-[#6B7280] mt-12rpx">{{ page.desc }}</view>
</view>
<view class="mt-106rpx mx-48rpx">
<wd-form ref="form" :model="model">
@ -31,7 +32,7 @@
</view>
</view>
<view class="mt-40rpx">
<view class="mt-40rpx" v-if="pageType == 'edit'">
<view class="font-400 text-30rpx text-[#606266] leading-44rpx">验证码</view>
<view class="mt-20rpx">
<wd-input type="text" placeholder="请输入验证码" v-model="model.code" inputmode="numeric" no-border custom-class="!bg-[#F6F7F8] !border !border-solid !border-[#EAECF0] !rounded-16rpx" custom-input-class="!px-32rpx !h-104rpx">
@ -58,15 +59,6 @@
<view class="h-90rpx leading-90rpx mx-60rpx rounded-8rpx text-center mt-112rpx bg-[#4C9F44] text-[#fff]" :class="disabled ? 'opacity-40' : ''" @click="mobile.handleToLogin">登录</view>
<view class="flex items-center mx-52rpx mt-56rpx" v-if="pageType === 'login'">
<view class="w-32rpx h-32rpx">
<wd-checkbox v-model="agree" @change="mobile.handleAgree" 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="mobile.handleToService">服务协议</text> <text class="text-[#4C9F44]" @click.stop="mobile.handleToPrivacy">隐私政策</text>
</view>
</view>
<!-- 手机号修改成功 -->
<wd-popup v-model="showEditSuccessPopup" lock-scroll custom-style="border-radius: 32rpx 32rpx 0rpx 0rpx;" position="bottom">
<view class="relative pt-64rpx pb-74rpx">
@ -94,7 +86,7 @@
const disabled = ref<boolean>(true)
/** 页面 **/
let pageType = 'login' // 页面类型 login:登录 edit:修改手机号
const pageType = ref<string>('') // 页面类型 login:登录 edit:修改手机号
const page = ref<{title: string, desc: string}>({title: '其他手机号登录', desc: '请输入你要登录的手机号'})
const showEditSuccessPopup = ref<boolean>(false) // 显示手机号修改成功弹窗
const userId = ref<number>(0) // 用户ID修改手机号时需要传
@ -114,18 +106,18 @@
})
/** 结束 **/
/** 服务协议和隐私政策 **/
const agree = ref<boolean>(false)
/** 结束 **/
onLoad((args) => {
// 从个人登录页面进入
pageType.value = args.type
userId.value = Number(args.userId) || 0 // userId仅做测试使用实际请传真实用户ID
if (args.type === 'edit') {
userId.value = Number(args.userId) || 0 // userId仅做测试使用实际请传真实用户ID
page.value.title = '修改手机号'
page.value.desc = '手机号一年内可修改2次'
pageType = 'edit'
} else if (args.type === 'change') {
page.value.title = '修改绑定用户'
page.value.desc = '请输入新的手机号进行绑定'
}
})

View File

@ -1,4 +1,5 @@
<route lang="jsonc" type="page">{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"

View File

@ -1,5 +1,6 @@
<route lang="jsonc" type="page">
{
"needLogin": true,
"layout": "default",
"style": {
"navigationStyle": "custom"
@ -76,7 +77,7 @@
image-mode="scaleToFill"
:action="action"
@success="Profile.handleUploadSuccess">
<wd-img width="64rpx" height="64rpx" :src="user.avatar" mode="aspectFill" round />
<wd-img width="64rpx" height="64rpx" :src="user.avatar || `${OSS}images/store/my/image1.png`" mode="aspectFill" round />
</wd-upload>
</view>
<wd-icon name="arrow-right" size="32rpx" color="#C0C4CC" />
@ -100,7 +101,7 @@
</view>
<!-- 修改手机号 -->
<view class="flex justify-between items-center mb-54rpx" @click="Profile.handleToEditMobile">
<view class="flex justify-between items-center mb-54rpx" @click="router.navigateTo('/bundle/profile/change-mobile?type=edit')">
<view class="font-400 text-[#303133] text-30rpx leading-42rpx">修改手机号</view>
<view class="flex justify-end">
<view class="flex items-center">
@ -116,31 +117,17 @@
<!-- 修改手机号 -->
<view class="flex justify-between items-center mb-54rpx" @click="router.navigateTo('/bundle/profile/change-password')">
<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">
{{ user.nickname }}
</view>
<view>
<wd-icon name="arrow-right" size="32rpx" color="#C0C4CC" />
</view>
</view>
<view class="font-400 text-[#303133] text-30rpx leading-42rpx">修改密码</view>
<view>
<wd-icon name="arrow-right" size="32rpx" color="#C0C4CC" />
</view>
</view>
<!-- 修改绑定用户 -->
<view class="flex justify-between items-center" @click="router.navigateTo('/bundle/profile/change-password')">
<view class="flex justify-between items-center" @click="router.navigateTo('/bundle/profile/change-mobile?type=change')">
<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">
{{ user.nickname }}
</view>
<view>
<wd-icon name="arrow-right" size="32rpx" color="#C0C4CC" />
</view>
</view>
<view>
<wd-icon name="arrow-right" size="32rpx" color="#C0C4CC" />
</view>
</view>
</view>
@ -164,7 +151,7 @@
// 上传文件
const fileList = ref<any[]>([])
const action = 'https://cz.stnav.com/api/upload/image' // 仅做测试使用,实际请换成真实上传接口
const action = import.meta.env.VITE_UPLOAD_BASEURL
// 修改昵称
const showEditNicknamePopup = ref<boolean>(false) // 是否显示退款详情弹出框
@ -195,17 +182,16 @@
onLoad(() => {
token.value = uni.getStorageSync('token')
// Profile.handleInit()
Profile.handleInit()
})
const Profile = {
/**
* 初始化用户信息
*/
handleInit: () => {
getUserInfo().then(res => {
user.value = res
})
handleInit: async () => {
const res = await getUserInfo()
user.value = res
},
/**
@ -221,7 +207,7 @@
const response = JSON.parse(e.file.response)
if (response.code) {
const avatarUrl = response.data.uri
await updateUserInfo({ field: 'avatar', value: avatarUrl })
await updateUserInfo({ avatar: avatarUrl })
user.value.avatar = avatarUrl
toast.info('头像上传成功')
} else {
@ -241,7 +227,7 @@
return
}
await updateUserInfo({ field: 'nickname', value: nickname.value })
await updateUserInfo({ nickname: nickname.value })
showEditNicknamePopup.value = false
user.value.nickname = nickname.value
toast.info('昵称修改成功')
@ -259,9 +245,9 @@
/**
* 退出
*/
handleLogout: () => {
handleLogout: async () => {
const userStore = useUserStore()
userStore.logout()
await userStore.logout()
if (!userStore.isLoggedIn) {
toast.info('退出成功')
router.reLaunch('/pages/my/my')