对接接口

This commit is contained in:
wangxiaowei
2025-10-14 18:08:12 +08:00
parent 0ff0df7d5b
commit 76da09be91
12 changed files with 180 additions and 79 deletions

2
env/.env vendored
View File

@ -8,7 +8,7 @@ VITE_WX_APPID = 'wxa2abb91f64032a2b'
VITE_APP_PUBLIC_BASE = '/h5' VITE_APP_PUBLIC_BASE = '/h5'
# 登录页面 # 登录页面
VITE_LOGIN_URL = '/pages/login/login' VITE_LOGIN_URL = '/pages/login/mobile'
# 第一个请求地址 # 第一个请求地址
VITE_SERVER_BASEURL = 'https://cz.stnav.com' VITE_SERVER_BASEURL = 'https://cz.stnav.com'

View File

@ -17,7 +17,7 @@
} }
// 微信静默授权 // 微信静默授权
// snsapiBaseAuthorize() snsapiBaseAuthorize()
initJweixinSDK() initJweixinSDK()
}) })
onShow((options) => { onShow((options) => {

27
src/api/home.ts Normal file
View File

@ -0,0 +1,27 @@
import { http } from '@/http/alova'
import type { IIndexResult } from '@/api/types/home'
/**
* 获取首页数据
*/
export interface IIndexData {
id: number
}
export function getDecorate(data: IIndexData) {
return http.Get('/api/index/decorate', {params: data})
}
/**
* 获取茶艺师等级
*/
export function getTeaSpecialistLevels() {
return http.Post('/api/Teamaster/teamasterLevel')
}
/**
* 获取茶艺师列表
*/
export function getTeaSpecialist() {
return http.Post('/api/Teamaster/teamasterLevel')
}

View File

@ -11,7 +11,9 @@ export interface IWxSnsapiBaseLoginForm {
} }
export function wxSnsapiBaseLogin(data: IWxSnsapiBaseLoginForm) { export function wxSnsapiBaseLogin(data: IWxSnsapiBaseLoginForm) {
return http.Post<IUserInfoVo>('/api/login/oaLogin', data) return http.Post<IUserInfoVo>('/api/login/oaLogin', data, {
meta: { ignoreAuth: true }, // 忽略认证
})
} }
/** /**
@ -24,7 +26,19 @@ export interface IPhoneLoginForm {
} }
export function phoneLogin(data: IPhoneLoginForm) { export function phoneLogin(data: IPhoneLoginForm) {
return http.Post<IUserLogin>('/api/login/oaLogin', {params: data}) return http.Post<IUserLogin>('/api/login/oaLogin', data)
}
/**
* 获取验证码
*/
export interface ISMSLogin {
mobile: number,
scene: string
}
export function smsCode(data: ISMSLogin) {
return http.Post('/api/sms/sendCode',data)
} }
/** /**

6
src/api/types/home.ts Normal file
View File

@ -0,0 +1,6 @@
/**
* 首页初始化返回数据
*/
export interface IIndexResult {
data: String
}

View File

@ -25,49 +25,57 @@ const getUrlCode = (): { [key: string]: string | undefined } => {
*/ */
export function snsapiBaseAuthorize() { export function snsapiBaseAuthorize() {
// TODO 测试代码 // TODO 测试代码
const res = { // wxSnsapiBaseLogin({code: '0316MW1w32OBM53meU2w3GPdbe16MW1p'}).then((res: IUserInfoVo) => {
account: "u39317465", // console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
avatar: "https://cz.stnav.com/uploads/user/avatar/c2b3c5f94e3f20c8a989bd302519b4c7.jpeg", // // 映射 IUserLogin 到 IUserInfoVo
channel:2, // useUserStore().setUserInfo(res)
is_new_user: 1, // }).catch(err => {
id: 1, // // 失败就重新授权
sn:"39317465", // uni.setStorageSync('wechatCode', 0)
token: "14a11310d926121e352afec2ef1d2f7f", // console.log('请求失败', err)
nickname: '微信用户', // })
mobile: '15005837859' // const res = {
} // account: "u39317465",
useUserStore().setUserInfo(res) // avatar: "https://cz.stnav.com/uploads/user/avatar/c2b3c5f94e3f20c8a989bd302519b4c7.jpeg",
console.log(useUserStore().userInfo) // channel:2,
return // is_new_user: 1,
// id: 4,
// sn:"39317465",
// token: "c6416f9ebed9f06d3807d01e9c9a9693",
// nickname: '微信用户',
// mobile: '15005837859'
// }
// useUserStore().setUserInfo(res)
// // console.log(useUserStore().userInfo)
// return
let local = window.location.href // 获取页面url // let local = window.location.href // 获取页面url
let appid = import.meta.env.VITE_WX_SERVICE_ACCOUNT_APPID // 公众号的APPID // let appid = import.meta.env.VITE_WX_SERVICE_ACCOUNT_APPID // 公众号的APPID
console.log("🚀 ~ snsapiBaseAuthorize ~ appid:", appid) // console.log("🚀 ~ snsapiBaseAuthorize ~ appid:", appid)
let code = getUrlCode().code // 截取code // let code = getUrlCode().code // 截取code
// 获取之前的code // // 获取之前的code
let oldCode = uni.getStorageSync('wechatCode') // let oldCode = uni.getStorageSync('wechatCode')
if (code == null || code === '' || code == 'undefined' || code == oldCode) { // if (code == null || code === '' || code == 'undefined' || code == oldCode) {
// 如果没有code就去请求获取code // // 如果没有code就去请求获取code
console.log('当前没有code进入授权页面') // console.log('当前没有code进入授权页面')
let uri = encodeURIComponent(local) // let uri = encodeURIComponent(local)
// 设置旧的code为0避免死循环 // // 设置旧的code为0避免死循环
uni.setStorageSync('wechatCode',0) // uni.setStorageSync('wechatCode',0)
window.location.href = // window.location.href =
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${uri}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect` // `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${uri}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect`
} else { // } else {
// 保存最新code // // 保存最新code
uni.setStorageSync('wechatCode',code) // uni.setStorageSync('wechatCode',code)
// 使用code换取用户信息 // // 使用code换取用户信息
wxSnsapiBaseLogin({code}).then((res: IUserInfoVo) => { // wxSnsapiBaseLogin({code}).then((res: IUserInfoVo) => {
console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res) // console.log("登录成功 ~ snsapiBaseAuthorize ~ res:", res)
// 映射 IUserLogin 到 IUserInfoVo // // 映射 IUserLogin 到 IUserInfoVo
useUserStore().setUserInfo(res) // useUserStore().setUserInfo(res)
console.log('登录成功 ~ ' + useUserStore().userInfo) // }).catch(err => {
}).catch(err => { // // 失败就重新授权
// 失败就重新授权 // uni.setStorageSync('wechatCode', 0)
uni.setStorageSync('wechatCode', 0) // console.log('请求失败', err)
console.log('请求失败', err) // })
}) // }
}
} }

View File

@ -56,15 +56,26 @@ const alovaInstance = createAlova({
} }
const { config } = method const { config } = method
console.log("🚀 ~ config.meta?.ignoreAuth:", config)
const ignoreAuth = !config.meta?.ignoreAuth const ignoreAuth = !config.meta?.ignoreAuth
console.log('ignoreAuth===>', ignoreAuth) console.log('ignoreAuth===>', ignoreAuth)
// 处理认证信息 自行处理认证问题 // 处理认证信息 自行处理认证问题
if (ignoreAuth) { if (ignoreAuth) {
const token = 'getToken()' // const token = 'getToken()'
// if (!token) {
// throw new Error('[请求错误]:未登录')
// }
// method.config.headers.token = token;
const userStore = useUserStore()
const { token } = userStore.userInfo as unknown as IUserInfo
console.log("🚀 ~ userStore.userInfo:", userStore.userInfo)
console.log("🚀 ~ token:", token)
if (!token) { if (!token) {
throw new Error('[请求错误]:未登录') throw new Error('[请求错误]:未登录')
} }
// method.config.headers.token = token; method.config.headers.token = token;
} }
// 处理动态域名 // 处理动态域名
@ -102,12 +113,22 @@ const alovaInstance = createAlova({
// } // }
// 处理业务逻辑错误 // 处理业务逻辑错误
const { code, message, data } = rawData as IResponse 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.Success) { if (code !== ResultEnum.Success) {
if (config.meta?.toast !== false) { if (config.meta?.toast !== false) {
toast.warning(message) toast.warning(msg)
} }
throw new Error(`请求错误[${code}]${message}`) throw new Error(`请求错误[${code}]${msg}`)
} }
// 处理成功响应,返回业务数据 // 处理成功响应,返回业务数据
return data return data

View File

@ -1,7 +1,7 @@
export enum ResultEnum { export enum ResultEnum {
Success = 1, // 成功 Success = 1, // 成功
Error = 0, // 错误 Error = 0, // 错误
Unauthorized = 401, // 未授权 Unauthorized = -1, // 未授权
Forbidden = 403, // 禁止访问原为forbidden Forbidden = 403, // 禁止访问原为forbidden
NotFound = 404, // 未找到原为notFound NotFound = 404, // 未找到原为notFound
MethodNotAllowed = 405, // 方法不允许原为methodNotAllowed MethodNotAllowed = 405, // 方法不允许原为methodNotAllowed

View File

@ -11,7 +11,7 @@ export type CustomRequestOptions = UniApp.RequestOptions & {
export interface IResponse<T = any> { export interface IResponse<T = any> {
code: number | string code: number | string
data: T data: T
message: string msg: string
status: string | number status: string | number
} }

View File

@ -74,11 +74,11 @@
<!-- 茶艺师等级筛选 --> <!-- 茶艺师等级筛选 -->
<view class="flex items-center text-#303133 overflow-x-auto whitespace-nowrap ml-30rpx my-30rpx tea-level-scrollbar"> <view class="flex items-center text-#303133 overflow-x-auto whitespace-nowrap ml-30rpx my-30rpx tea-level-scrollbar">
<view <view
class="h-64rpx rounded-12rpx px-24rpx py-12rpx flex items-center justify-center font-400 text-28rpx mr-20rpx"
:class="selectedLevel.includes(item.value) ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#FFF] text-[#606266]'"
v-for="(item, index) in TeaSpecialistLevels" :key="index" v-for="(item, index) in TeaSpecialistLevels" :key="index"
@click="Index.handleToggleTeaSpecialistLevel(item.value)"> class="h-64rpx rounded-12rpx px-24rpx py-12rpx flex items-center justify-center font-400 text-28rpx mr-20rpx"
{{ item.label }} :class="selectedLevel.includes(item.id) ? 'bg-[#4C9F44] text-[#fff]' : 'bg-[#FFF] text-[#606266]'"
@click="Index.handleToggleTeaSpecialistLevel(item.id)">
{{ item.level_name}}
</view> </view>
</view> </view>
@ -146,22 +146,34 @@
<script lang="ts" setup> <script lang="ts" setup>
import { onPageScroll, onReachBottom } from '@dcloudio/uni-app' import { onPageScroll, onReachBottom } from '@dcloudio/uni-app'
import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js" import useMescroll from "@/uni_modules/mescroll-uni/hooks/useMescroll.js"
import {TeaSpecialistLevels} from '@/utils/teaSpecialist'
import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue' import TeaSpecialistLevel from '@/components/TeaSpecialistLevel.vue'
import { OrderSource, OrderStatus } from '@/utils/order' import { OrderSource, OrderStatus } from '@/utils/order'
import {getlocation} from '@/utils/jwexin' import {getlocation} from '@/utils/jwexin'
import {getDecorate, getTeaSpecialistLevels} from '@/api/home'
// import {TeaSpecialistLevels} from '@/utils/teaSpecialist'
const OSS = inject('OSS') const OSS = inject('OSS')
// 茶艺师等级 // 茶艺师等级
const TeaSpecialistLevels = reactive<Array<{ id: number, status: number, level_name: string}>>([])
const selectedLevel = ref<Array<any>>([]) // 选择茶艺师的点击等级 const selectedLevel = ref<Array<any>>([]) // 选择茶艺师的点击等级
// 分页
const { mescrollInit, downCallback } = useMescroll(onPageScroll, onReachBottom) // 调用mescroll的hook const { mescrollInit, downCallback } = useMescroll(onPageScroll, onReachBottom) // 调用mescroll的hook
onLoad(() => { onLoad(() => {
getlocation((res) => { // getlocation((res) => {
console.log('经纬度:' + res.latitude + ',' + res.longitude) // console.log('经纬度:' + res.latitude + ',' + res.longitude)
// })
// getDecorate({id: 1}).then((res: any) => {
// const data = JSON.parse(res.data)
// console.log('装修数据:', data)
// })
// 获取茶艺师等级
getTeaSpecialistLevels().then((res:Array<any>) => {
TeaSpecialistLevels.push(...res)
}) })
}) })

View File

@ -14,12 +14,12 @@
<view class="font-400 text-28rpx leading-44rpx text-[#6B7280] mt-12rpx"> {{ page.desc }}</view> <view class="font-400 text-28rpx leading-44rpx text-[#6B7280] mt-12rpx"> {{ page.desc }}</view>
</view> </view>
<view class="mt-106rpx mx-48rpx"> <view class="mt-106rpx mx-48rpx">
<wd-form ref="form" :model="model"> <wd-form ref="form" :model="form">
<view> <view>
<view class="font-400 text-30rpx text-[#606266] leading-44rpx">手机号</view> <view class="font-400 text-30rpx text-[#606266] leading-44rpx">手机号</view>
<view class="mt-20rpx"> <view class="mt-20rpx">
<wd-input <wd-input
v-model="model.mobile" v-model="form.mobile"
type="text" type="text"
placeholder="请输入手机号码" placeholder="请输入手机号码"
inputmode="numeric" inputmode="numeric"
@ -34,7 +34,7 @@
<view class="mt-40rpx"> <view class="mt-40rpx">
<view class="font-400 text-30rpx text-[#606266] leading-44rpx">验证码</view> <view class="font-400 text-30rpx text-[#606266] leading-44rpx">验证码</view>
<view class="mt-20rpx"> <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"> <wd-input type="text" placeholder="请输入验证码" v-model="form.code" inputmode="numeric" no-border custom-class="!bg-[#F6F7F8] !border !border-solid !border-[#EAECF0] !rounded-16rpx" custom-input-class="!px-32rpx !h-104rpx">
<template #suffix> <template #suffix>
<view class="flex items-center mr-34rpx"> <view class="flex items-center mr-34rpx">
<view class="flex items-center"> <view class="flex items-center">
@ -86,11 +86,12 @@
<script lang="ts" setup> <script lang="ts" setup>
import {mobile as testMobile} from '@/utils/test' import {mobile as testMobile} from '@/utils/test'
import { useToast } from 'wot-design-uni' import {useToast} from 'wot-design-uni'
import {smsCode} from '@/api/login'
const OSS = inject('OSS') const OSS = inject('OSS')
const toast = useToast() const toast = useToast()
const disabled = ref<boolean>(true) const disabled = ref<boolean>(false)
/** 页面 **/ /** 页面 **/
let pageType = 'login' // 页面类型 login:登录 edit:修改手机号 let pageType = 'login' // 页面类型 login:登录 edit:修改手机号
@ -104,11 +105,11 @@
const countDown = ref<any>(null) // 倒计时组件 const countDown = ref<any>(null) // 倒计时组件
/** 表单相关 **/ /** 表单相关 **/
const model = reactive<{ const form = reactive<{
mobile: string mobile: string
code: string code: string
}>({ }>({
mobile: '', mobile: '15005837859',
code: '' code: ''
}) })
/** 结束 **/ /** 结束 **/
@ -131,8 +132,8 @@
const mobile = { const mobile = {
// 验证手机号 // 验证手机号
handleInputMobile: (e: {value: string}) => { handleInputMobile: (e: {value: string}) => {
model.mobile = e.value form.mobile = e.value
disabled.value = !testMobile(model.mobile) disabled.value = !testMobile(form.mobile)
}, },
// 发送验证码 // 发送验证码
@ -149,8 +150,20 @@
startCountDown.value = true startCountDown.value = true
nextTick(() => { nextTick(() => {
countDown.value?.start() countDown.value?.start()
// 发送验证码请求 // 发送验证码请求
console.log("🚀 ~ 发送验证码请求:")
smsCode({ mobile: Number(form.mobile), scene: 'YZMDL' }).then(() => {
toast.show({
iconClass: 'success-circle',
msg: '验证码发送成功',
direction: 'vertical'
})
}).catch((err) => {
console.log("🚀 ~ err:", err)
startCountDown.value = false
countDown.value?.reset()
})
}) })
}, },
@ -172,7 +185,7 @@
return return
} }
if (!testMobile(model.mobile)) { if (!testMobile(form.mobile)) {
toast.show({ toast.show({
iconClass: 'info-circle', iconClass: 'info-circle',
msg: '手机号码错误请重新输入', msg: '手机号码错误请重新输入',
@ -181,7 +194,7 @@
return return
} }
if (!model.code) { if (!form.code) {
toast.show({ toast.show({
iconClass: 'info-circle', iconClass: 'info-circle',
msg: '验证码错误', msg: '验证码错误',

View File

@ -9,9 +9,9 @@ export enum TeaSpecialistLevel {
// 茶艺师对象结构 // 茶艺师对象结构
export const TeaSpecialistLevels = [ export const TeaSpecialistLevels = [
{ value: 'gold', label: TeaSpecialistLevel.Gold}, { id: 1, value: 'gold', label: TeaSpecialistLevel.Gold},
{ value: 'senior', label: TeaSpecialistLevel.Senior }, { id: 2,value: 'senior', label: TeaSpecialistLevel.Senior },
{ value: 'intermediate', label: TeaSpecialistLevel.Intermediate }, { id: 3,value: 'intermediate', label: TeaSpecialistLevel.Intermediate },
{ value: 'junior', label: TeaSpecialistLevel.Junior }, { id: 4,value: 'junior', label: TeaSpecialistLevel.Junior },
{ value: 'enthusiast', label: TeaSpecialistLevel.Enthusiast } { id: 5,value: 'enthusiast', label: TeaSpecialistLevel.Enthusiast }
]; ];