添加测试号、生产环境可以查看debug

This commit is contained in:
wangxiaowei
2025-10-05 18:05:58 +08:00
parent bdfa0a90f4
commit 168084029a
11 changed files with 184 additions and 49 deletions

2
.gitignore vendored
View File

@ -14,6 +14,7 @@ dist
# Editor directories and files # Editor directories and files
.idea .idea
.history
*.suo *.suo
*.ntvs* *.ntvs*
*.njsproj *.njsproj
@ -29,6 +30,7 @@ docs/.vitepress/cache
src/types src/types
# lock 文件还是不要了,我主要的版本写死就好了 # lock 文件还是不要了,我主要的版本写死就好了
# pnpm-lock.yaml # pnpm-lock.yaml
# package-lock.json # package-lock.json

11
env/.env vendored
View File

@ -5,18 +5,21 @@ VITE_UNI_APPID = '__UNI__D1E5001'
VITE_WX_APPID = 'wxa2abb91f64032a2b' VITE_WX_APPID = 'wxa2abb91f64032a2b'
# h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base # h5部署网站的base配置到 manifest.config.ts 里的 h5.router.base
VITE_APP_PUBLIC_BASE=/ VITE_APP_PUBLIC_BASE = '/h5'
# 登录页面 # 登录页面
VITE_LOGIN_URL = '/pages/login/login' VITE_LOGIN_URL = '/pages/login/login'
# 第一个请求地址 # 第一个请求地址
VITE_SERVER_BASEURL = 'https://mnp.zhuzhuda.cn' VITE_SERVER_BASEURL = 'https://cz.stnav.com/gzhapi'
VITE_UPLOAD_BASEURL = 'https://mnp.zhuzhuda.cn/upload' VITE_UPLOAD_BASEURL = 'https://cz.stnav.com/upload'
# h5是否需要配置代理 # h5是否需要配置代理
VITE_APP_PROXY=false VITE_APP_PROXY=false
VITE_APP_PROXY_PREFIX = '/api' VITE_APP_PROXY_PREFIX = '/api'
# 第二个请求地址 (目前alova中可以使用) # 第二个请求地址 (目前alova中可以使用)
VITE_API_SECONDARY_URL = 'https://mnp.zhuzhuda.cn' VITE_API_SECONDARY_URL = 'https://cz.stnav.com'
# 公众号APPID
VITE_WX_SERVICE_ACCOUNT_APPID = 'wx0224f558e3b3f499'

2
env/.env.production vendored
View File

@ -1,6 +1,6 @@
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 # 变量必须以 VITE_ 为前缀才能暴露给外部读取
NODE_ENV = 'development' NODE_ENV = 'development'
# 是否去除console 和 debugger # 是否去除console 和 debugger
VITE_DELETE_CONSOLE = true VITE_DELETE_CONSOLE = false
# 是否开启sourcemap # 是否开启sourcemap
VITE_SHOW_SOURCEMAP = false VITE_SHOW_SOURCEMAP = false

View File

@ -2,6 +2,7 @@
import { onHide, onLaunch, onShow } from '@dcloudio/uni-app' import { onHide, onLaunch, onShow } from '@dcloudio/uni-app'
import { navigateToInterceptor } from '@/router/interceptor' import { navigateToInterceptor } from '@/router/interceptor'
import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only' import 'abortcontroller-polyfill/dist/abortcontroller-polyfill-only'
import {snsapiBaseAuthorize} from '@/hooks/useWeiXin'
onLaunch((options) => { onLaunch((options) => {
// 处理直接进入页面路由的情况如h5直接输入路由、微信小程序分享后进入等 // 处理直接进入页面路由的情况如h5直接输入路由、微信小程序分享后进入等
@ -13,6 +14,9 @@
else { else {
navigateToInterceptor.invoke({ url: '/' }) navigateToInterceptor.invoke({ url: '/' })
} }
// 微信静默授权
snsapiBaseAuthorize()
}) })
onShow((options) => { onShow((options) => {
console.log('App Show', options) console.log('App Show', options)

View File

@ -1,14 +1,31 @@
import type { ICaptcha, IUpdateInfo, IUpdatePassword, IUserInfoVo, IUserLogin } from './types/login' import type { ICaptcha, IUpdateInfo, IUpdatePassword, IUserInfoVo, IUserLogin } from './types/login'
import { http } from '@/http/http' // import { http } from '@/http/http'
import { API_DOMAINS, http } from '@/http/alova'
/**
* 微信静默授权登录参数
*/
export interface IWxSnsapiBaseLoginForm {
code: string
}
/**
* 微信静默授权登录
*/
export function wxSnsapiBaseLogin(loginForm: IWxSnsapiBaseLoginForm) {
return http.Get<IUserLogin>('/login/oaLogin', {params: loginForm})
}
/** /**
* 登录表单 * 登录表单
*/ */
export interface ILoginForm { export interface ILoginForm {
username: string username: string
password: string password: string
code: string code: string
uuid: string uuid: string
} }
/** /**
@ -16,7 +33,7 @@ export interface ILoginForm {
* @returns ICaptcha 验证码 * @returns ICaptcha 验证码
*/ */
export function getCode() { export function getCode() {
return http.get<ICaptcha>('/user/getCode') return http.Get<ICaptcha>('/user/getCode')
} }
/** /**
@ -24,35 +41,35 @@ export function getCode() {
* @param loginForm 登录表单 * @param loginForm 登录表单
*/ */
export function login(loginForm: ILoginForm) { export function login(loginForm: ILoginForm) {
return http.post<IUserLogin>('/user/login', loginForm) return http.Post<IUserLogin>('/user/login', loginForm)
} }
/** /**
* 获取用户信息 * 获取用户信息
*/ */
export function getUserInfo() { export function getUserInfo() {
return http.get<IUserInfoVo>('/user/info') return http.Get<IUserInfoVo>('/user/info')
} }
/** /**
* 退出登录 * 退出登录
*/ */
export function logout() { export function logout() {
return http.get<void>('/user/logout') return http.Get<void>('/user/logout')
} }
/** /**
* 修改用户信息 * 修改用户信息
*/ */
export function updateInfo(data: IUpdateInfo) { export function updateInfo(data: IUpdateInfo) {
return http.post('/user/updateInfo', data) return http.Get('/user/updateInfo', data)
} }
/** /**
* 修改用户密码 * 修改用户密码
*/ */
export function updateUserPassword(data: IUpdatePassword) { export function updateUserPassword(data: IUpdatePassword) {
return http.post('/user/updatePassword', data) return http.Post('/user/updatePassword', data)
} }
/** /**
@ -60,13 +77,13 @@ export function updateUserPassword(data: IUpdatePassword) {
* @returns Promise 包含微信登录凭证(code) * @returns Promise 包含微信登录凭证(code)
*/ */
export function getWxCode() { export function getWxCode() {
return new Promise<UniApp.LoginRes>((resolve, reject) => { return new Promise<UniApp.LoginRes>((resolve, reject) => {
uni.login({ uni.login({
provider: 'weixin', provider: 'weixin',
success: res => resolve(res), success: res => resolve(res),
fail: err => reject(new Error(err)), fail: err => reject(new Error(err)),
}) })
}) })
} }
/** /**
@ -79,5 +96,5 @@ export function getWxCode() {
* @returns Promise 包含登录结果 * @returns Promise 包含登录结果
*/ */
export function wxLogin(data: { code: string }) { export function wxLogin(data: { code: string }) {
return http.post<IUserLogin>('/user/wxLogin', data) return http.Post<IUserLogin>('/user/wxLogin', data)
} }

File diff suppressed because one or more lines are too long

56
src/hooks/useWeiXin.ts Normal file
View File

@ -0,0 +1,56 @@
import {wxSnsapiBaseLogin} from '@/api/login'
// import {setUserInfo, getUserInfo} from '@/store/user'
/**
* 微信静默授权
*/
const getUrlCode = (): { [key: string]: string | undefined } => {
// 截取url中的code方法
const url = location.search
// this.winUrl = url;
let theRequest: { [key: string]: string | undefined } = {}
if (url.indexOf('?') != -1) {
let str = url.slice(1)
let strs = str.split('&')
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split('=')[0]] = strs[i].split('=')[1]
}
}
return theRequest
}
/**
* 微信静默授权登录
*/
export function snsapiBaseAuthorize() {
let local = window.location.href // 获取页面url
let appid = import.meta.env.VITE_WX_SERVICE_ACCOUNT_APPID // 公众号的APPID
console.log("🚀 ~ snsapiBaseAuthorize ~ appid:", appid)
let code = getUrlCode().code // 截取code
// 获取之前的code
let oldCode = uni.getStorageSync('wechatCode')
if (code == null || code === '' || code == 'undefined' || code == oldCode) {
// 如果没有code就去请求获取code
console.log('当前没有code进入授权页面')
let uri = encodeURIComponent(local)
// 设置旧的code为0避免死循环
uni.setStorageSync('wechatCode',0)
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`
} else {
console.log('存在code使用code换取用户信息')
// 保存最新code
uni.setStorageSync('wechatCode',code)
console.log("🚀 ~ snsapiBaseAuthorize ~ code:", code)
// 使用code换取用户信息
wxSnsapiBaseLogin({code}).then(res=>{
console.log("🚀 ~ snsapiBaseAuthorize ~ res:", res)
}).catch(err=>{
// 失败就重新授权
uni.setStorageSync('wechatCode',0)
console.log('请求失败', err)
})
}
}

View File

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

View File

@ -17,7 +17,7 @@
<view class="text-36rpx leading-50rpx text-#303133 mr-38rpx"> <view class="text-36rpx leading-50rpx text-#303133 mr-38rpx">
预约茶艺师 预约茶艺师
</view> </view>
<view class="flex items-center line-1" @click="Home.toCity"> <view class="flex items-center line-1" @click="Index.handleToCity">
<view class=""> <view class="">
<wd-icon name="location" size="32rpx"></wd-icon> <wd-icon name="location" size="32rpx"></wd-icon>
</view> </view>
@ -27,7 +27,7 @@
</view> </view>
</template> </template>
</wd-navbar> </wd-navbar>
<view class="search-box relative"> <view class="search-box relative" @click="Index.handleToSearch">
<wd-search placeholder="茶艺师名称" cancel-txt="搜索" placeholder-left hide-cancel custom-input-class="!h-72rpx"> <wd-search placeholder="茶艺师名称" cancel-txt="搜索" placeholder-left hide-cancel custom-input-class="!h-72rpx">
</wd-search> </wd-search>
<view class="absolute top-1/2 -translate-y-1/2 right-34rpx w-142rpx h-64rpx leading-64rpx text-center rounded-32rpx bg-#4C9F44 text-#fff font-400 text-32rpx"> <view class="absolute top-1/2 -translate-y-1/2 right-34rpx w-142rpx h-64rpx leading-64rpx text-center rounded-32rpx bg-#4C9F44 text-#fff font-400 text-32rpx">
@ -55,7 +55,7 @@
</view> </view>
<view> <view>
<view class="mt-16rpx relative w-690rpx h-260rpx mx-30rpx"> <view class="mt-16rpx relative w-690rpx h-260rpx mx-30rpx" @click="Index.handleToGroupReserve">
<wd-img width="690rpx" height="260rpx" :src="`${OSS}images/h5/home/home_image2.png`" mode="scaleToFill" /> <wd-img width="690rpx" height="260rpx" :src="`${OSS}images/h5/home/home_image2.png`" mode="scaleToFill" />
<view class="h-64rpx absolute bottom-0 right-0 bg-[#4C9F44] text-[#fff] flex items-center px-26rpx rounded"> <view class="h-64rpx absolute bottom-0 right-0 bg-[#4C9F44] text-[#fff] flex items-center px-26rpx rounded">
<text class="mr-8rpx">一键约</text> <text class="mr-8rpx">一键约</text>
@ -77,14 +77,14 @@
class="h-64rpx rounded-12rpx px-24rpx py-12rpx flex items-center justify-center font-400 text-28rpx mr-20rpx" 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]'" :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="Home.handleToggleTeaSpecialistLevel(item.value)"> @click="Index.handleToggleTeaSpecialistLevel(item.value)">
{{ item.label }} {{ item.label }}
</view> </view>
</view> </view>
<mescroll-body @init="mescrollInit" @down="downCallback" @up="Home.upCallback" <mescroll-body @init="mescrollInit" @down="downCallback" @up="Index.upCallback"
:fixed="true"> :fixed="true">
<view class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx" v-for="(item, index) in 100" :key="index" @click="Home.handleToReserveTeaSpecialist(item)"> <view class="flex items-center bg-white p-20rpx rounded-10rpx mx-30rpx mb-20rpx" v-for="(item, index) in 100" :key="index" @click="Index.handleToReserveTeaSpecialist(item)">
<view class="mr-28rpx relative"> <view class="mr-28rpx relative">
<wd-img width="200rpx" height="200rpx" :src="`${OSS}images/home/home_image5.png`"></wd-img> <wd-img width="200rpx" height="200rpx" :src="`${OSS}images/home/home_image5.png`"></wd-img>
<view class="tea-specialist-time absolute top-6rpx left-0 text-[#fff] font-400 text-18rpx leading-26rpx flex items-center justify-center"> <view class="tea-specialist-time absolute top-6rpx left-0 text-[#fff] font-400 text-18rpx leading-26rpx flex items-center justify-center">
@ -161,14 +161,16 @@
onLoad(() => { onLoad(() => {
}) })
const Home = { const Index = {
toCity: () => { // 城市
handleToCity: () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/city/city' url: '/pages/city/city'
}) })
}, },
toSearch: () => { // 搜索
handleToSearch: () => {
uni.navigateTo({ uni.navigateTo({
url: '/pages/search/search' url: '/pages/search/search'
}) })
@ -224,6 +226,13 @@
// 如果未选择该等级,则添加选择 // 如果未选择该等级,则添加选择
selectedLevel.value.push(value); selectedLevel.value.push(value);
} }
},
// 跳转到团体预约页面
handleToGroupReserve: () => {
uni.navigateTo({
url: '/pages/reservve/group-tea-specialist'
})
} }
} }
</script> </script>

View File

@ -1,8 +1,7 @@
<route lang="jsonc" type="page">{ <route lang="jsonc" type="page">{
"layout": "default", "layout": "default",
"style": { "style": {
"navigationBarTitleText": "", "navigationStyle": "custom"
"navigationBarBackgroundColor": "#fff"
} }
}</route> }</route>
@ -19,16 +18,16 @@
<wd-img :src="`${OSS}images/logo.png`" width="100%" height="100%" mode="aspectFill"></wd-img> <wd-img :src="`${OSS}images/logo.png`" width="100%" height="100%" mode="aspectFill"></wd-img>
</view> </view>
<view class="mt-124rpx mx-60rpx box-border"> <view class="mt-124rpx mx-60rpx box-border">
<wd-button open-type="getPhoneNumber" @getphonenumber="login.handleGetPhoneNumber" custom-class="!bg-[#4C9F44] !rounded-8rpx !text-[#fff] !text-30rpx !leading-42rpx !h-90rpx !w-[100%] box-border">手机号一键登录</wd-button> <wd-button open-type="getPhoneNumber" @getphonenumber="Login.handleGetPhoneNumber" custom-class="!bg-[#4C9F44] !rounded-8rpx !text-[#fff] !text-30rpx !leading-42rpx !h-90rpx !w-[100%] box-border">手机号一键登录</wd-button>
<view class="text-30rpx font-400 text-[#303133] leading-42rpx text-center mt-32rpx">其它手机号登录</view> <view class="text-30rpx font-400 text-[#303133] leading-42rpx text-center mt-32rpx" @click="Login.handleToOtherMobileLogin">其它手机号登录</view>
</view> </view>
<view class="flex items-center mx-32rpx mt-64rpx"> <view class="flex items-center mx-32rpx mt-64rpx">
<view class="w-32rpx h-32rpx"> <view class="w-32rpx h-32rpx mr-12rpx">
<wd-checkbox v-model="agree" @change="login.handleAgree" checked-color="#4C9F44" size="large"> </wd-checkbox> <wd-checkbox v-model="agree" @change="Login.handleAgree" checked-color="#4C9F44" size="large"> </wd-checkbox>
</view> </view>
<view class="font-400 text-26rpx leading-40rpx text-[#8F959E] ml-14rpx flex-1" @click="agree = !agree"> <view class="font-400 text-26rpx leading-40rpx text-[#8F959E] m l-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.handleToService">服务协议</text> <text class="text-[#4C9F44]" @click.stop="Login.handleToPrivacy">隐私政策</text>未注册手机号登录后将自动你为您创建账号
</view> </view>
</view> </view>
</view> </view>
@ -40,13 +39,62 @@
const agree = ref<boolean>(false) const agree = ref<boolean>(false)
const login = { const Login = {
handleLogin: () => {
uni.login({
provider: 'weixin',
success: (loginRes) => {
console.log("🚀 ~ loginRes:", loginRes)
// if (!agree.value) {
// uni.showToast({
// title: '请同意服务协议和隐私政策',
// icon: 'none'
// })
// return
// }
// // 发送 loginRes.code 到后台换取 openId, sessionKey, unionId
// uni.request({
// url: 'https://your-backend-api.com/login', // 替换为你的后台登录接口
// method: 'POST',
// data: {
// code: loginRes.code
// },
// success: (res) => {
// console.log('登录成功,返回数据:', res.data);
// // 这里可以存储用户信息到本地,或者进行页面跳转等操作
// },
// fail: (err) => {
// console.error('登录请求失败:', err);
// uni.showToast({
// title: '登录失败,请稍后重试',
// icon: 'none'
// });
// }
// });
},
fail: (err) => {
console.error('登录失败:', err);
uni.showToast({
title: '登录失败,请稍后重试',
icon: 'none'
});
}
});
},
// 获取手机号 // 获取手机号
handleGetPhoneNumber: (e: object) => { handleGetPhoneNumber: (e: object) => {
console.log("🚀 ~ e:", e) console.log("🚀 ~ e:", e)
}, },
// 跳转到其他手机号登录页面
handleToOtherMobileLogin: () => {
uni.navigateTo({
url: '/pages/login/mobile'
})
},
handleAgree: (e: any) => { handleAgree: (e: any) => {
console.log('e', e) console.log('e', e)
}, },

View File

@ -1,8 +1,7 @@
<route lang="jsonc" type="page">{ <route lang="jsonc" type="page">{
"layout": "default", "layout": "default",
"style": { "style": {
"navigationBarTitleText": "", "navigationStyle": "custom"
"navigationBarBackgroundColor": "#fff"
} }
}</route> }</route>