fix:微信公众号登录

This commit is contained in:
MJ 2025-08-02 22:18:17 +08:00
parent 82bae4c441
commit b52c1f9bfd
9 changed files with 228 additions and 223 deletions

View File

@ -1,13 +1,22 @@
<!DOCTYPE html> <!doctype html>
<html> <html>
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<script> <script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') || var coverSupport =
CSS.supports('top: constant(a)')) 'CSS' in window &&
typeof CSS.supports === 'function' &&
(CSS.supports('top: env(a)') || CSS.supports('top: constant(a)'))
document.write( document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' + '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />') (coverSupport ? ', viewport-fit=cover' : '') +
'" />',
)
</script>
<script src="https://cdn.bootcdn.net/ajax/libs/vConsole/3.3.4/vconsole.min.js"></script>
<script>
// 初始化
var vConsole = new VConsole()
</script> </script>
<title></title> <title></title>
<!--preload-links--> <!--preload-links-->

View File

@ -6,12 +6,12 @@ import { http } from './request/request'
export const getBindPhoneTypeApi = async data => { export const getBindPhoneTypeApi = async data => {
return await http.post<any>('/xcx/login/getBindRelationList', data) return await http.post<any>('/xcx/login/getBindRelationList', data)
} }
/** // /**
* // * 手机号获取用户身份
* @param data // * @param data 请求参数
*/ // */
export const getAdminTypeByPhoneApi = async (params: any) => // export const getAdminTypeByPhoneApi = async (params: any) =>
await http.get<any>('/sysUser/getAdminTypeByPhone', params) // await http.get<any>('/sysUser/getAdminTypeByPhone', params)
/** /**
* *
@ -30,12 +30,31 @@ export const smsLoginApi = async data =>
clientType: 'MOBILE', clientType: 'MOBILE',
}) })
/**
*
* @param data
*/
export const wxLoginApi = async data =>
await http.post<any>('/wxLogin', {
...data,
clientType: 'MOBILE',
})
/**
*
* @param data
*/
export const wxBindAccountApi = async data =>
await http.post<any>('/wxBindAccount', {
...data,
clientType: 'MOBILE',
})
/** /**
* *
* @param data * @param data
*/ */
export const getUserInfoApi = async () => export const getUserInfoApi = async () => await http.get<any>('/sysUser/selectUser')
await http.get<any>('/sysUser/selectUser')
/** /**
* *
@ -55,9 +74,7 @@ export const bindAuthInfoApi = async data =>
* *
* @param data * @param data
*/ */
export const getAuthUrlApi = async () => export const getAuthUrlApi = async () => await http.get<any>('/wechatPublic/getAuthUrl')
await http.get<any>('/wechatPublic/getAuthUrl')
// 退出登录 // 退出登录
export const logout = async () => export const logout = async () => await http.get<any>('/logout')
await http.get<any>('/logout')

View File

@ -33,15 +33,12 @@ export const responseInterceptor = async <T>(
console.log('response', response) console.log('response', response)
// 处理成功响应 // 处理成功响应
if (statusCode === HTTP_STATUS.SUCCESS) { if (statusCode === HTTP_STATUS.SUCCESS && data.code === 200) {
if (data.statusCode === 200 || data.code === 200) return response return response
throw {
statusCode,
errMsg: data.data,
}
} else { } else {
throw { throw {
statusCode, statusCode,
errMsg: data.message || '网络问题,请稍后再试',
} }
} }
} }
@ -55,7 +52,7 @@ export const errorInterceptor = (error: any): Promise<ErrorResponse> => {
message = errMsg message = errMsg
} else { } else {
// 处理特定状态码 // 处理特定状态码
switch (error.statusCode) { switch (statusCode) {
case HTTP_STATUS.AUTHENTICATE: case HTTP_STATUS.AUTHENTICATE:
toLogin = true toLogin = true
message = ERROR_MSG.AUTH_ERROR message = ERROR_MSG.AUTH_ERROR

View File

@ -23,8 +23,8 @@ class HttpRequest {
url, url,
timeout: this.timeout, timeout: this.timeout,
})) as unknown as ResponseData<T> })) as unknown as ResponseData<T>
const res = (await responseInterceptor(response)).data as any
return (await responseInterceptor(response)).data return res?.data
} catch (error) { } catch (error) {
return errorInterceptor(error) as any return errorInterceptor(error) as any
} }

View File

@ -48,23 +48,6 @@
</view> </view>
<button class="phone_btn" @click="handleLogin">登录</button> <button class="phone_btn" @click="handleLogin">登录</button>
</view> </view>
<!-- 多层身份弹窗 -->
<wd-popup
v-model="adminPopup"
safe-area-inset-bottom
position="bottom"
custom-style="border-radius: 20px 20px 0 0;padding-bottom: 30px;"
>
<view class="popup_box">
<view class="header_title"> 请选择身份 </view>
<view class="method_list">
<view v-for="(i, idx) in userAdmin" :key="idx" class="item" @click="chooseAdmin(i)">
{{ i.adminTypeName }}
</view>
</view>
</view>
</wd-popup>
</mj-page> </mj-page>
</template> </template>
@ -74,10 +57,11 @@ import { ref, computed, nextTick, onMounted } from 'vue'
import { import {
getBindPhoneTypeApi, getBindPhoneTypeApi,
sendCodeMessageApi, sendCodeMessageApi,
getAdminTypeByPhoneApi,
smsLoginApi, smsLoginApi,
getUserInfoApi, getUserInfoApi,
getAuthUrlApi, getAuthUrlApi,
wxLoginApi,
wxBindAccountApi,
} from '@/api' } from '@/api'
import { setCache, getCache } from '@/utils' import { setCache, getCache } from '@/utils'
import { getUserInfo as dx_getUserInfoApi } from '@/api/inspector/mine' import { getUserInfo as dx_getUserInfoApi } from '@/api/inspector/mine'
@ -129,12 +113,8 @@ async function fetchDXUserInfo() {
} }
// //
async function getCode() { async function getCode() {
loginForm.value.phone = formatPhone.value.replace(/\s+/g, '') if (!validatePhone()) {
if (!loginForm.value.phone) { hud.error('请输入正确的手机号')
uni.showToast({
icon: 'none',
title: '请输入手机号',
})
return return
} }
try { try {
@ -161,76 +141,64 @@ async function handleLogin() {
}) })
return return
} }
uni.showLoading({ if (db.get('openid')) {
title: '登录中...', await wxBindAccount()
}) } else {
getAdminTypeByPhone()
}
//
async function getAdminTypeByPhone() {
const res = await getAdminTypeByPhoneApi({
phone: loginForm.value.phone,
})
userAdmin.value = res
if (userAdmin.value.length <= 1) {
//
loginForm.value.adminType = userAdmin.value[0].adminType
await smsLogin() await smsLogin()
if (loginForm.value.adminType === 6) return
} else {
//
uni.hideLoading()
adminPopup.value = true
} }
} }
async function smsLogin() { async function smsLogin() {
uni.showLoading({ hud.load({
title: '登录中...', task: async () => {
const token = await smsLoginApi(loginForm.value)
setToken(token)
await getUserInfo()
router.reLaunch('/pages/home/index')
},
option: '登录',
}) })
const res = await smsLoginApi(loginForm.value) }
setToken(res)
const data = await getUserInfo()
if (!data.openid) { async function wxBindAccount() {
// hud.load({
const authRes = await getAuthUrlApi() task: async () => {
// #ifdef H5 await wxBindAccountApi(loginForm.value)
window.location.href = authRes await getUserInfo()
// #endif router.reLaunch('/pages/home/index')
// if (data.adminType === 16) { },
// const authRes = await getAuthUrlApi(); option: '登录',
// // #ifdef H5 })
// window.location.href = authRes.data; }
// // #endif
// } else { async function wxLogin() {
// fetchDXUserInfo(); const code = db.get('code')
// uni.reLaunch({ if (!code) {
// url: '/pages/inspector/schedule/index', return
// });
// }
} else {
router.reLaunch('/pages/home/index')
// let adminType = getCache('userInfo').adminType;
// if (adminType === 16) {
// uni.reLaunch({
// url: '/pages/home/index',
// });
// } else if (adminType === 6) {
// fetchDXUserInfo();
// uni.reLaunch({
// url: '/pages/inspector/schedule/index',
// });
// }
} }
uni.hideLoading() // code
} db.pop('code')
async function chooseAdmin(i) {
loginForm.value.adminType = i.adminType hud.load({
adminPopup.value = false task: async () => {
await smsLogin() //
if (loginForm.value.adminType === 6) return const { accessToken, openid } = await wxLoginApi({
code,
})
db.set('openid', openid)
setToken(accessToken)
},
option: '微信自动登录',
})
} }
onMounted(async () => {
// token
db.pop('token')
//
wxLogin()
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,5 +1,5 @@
<template> <template>
<view class="page"> <mj-page class="page">
<BackBar v-if="pageType === 1" title="完善信息" /> <BackBar v-if="pageType === 1" title="完善信息" />
<view class="info"> <view class="info">
<view class="info_item info_header"> <view class="info_item info_header">
@ -53,30 +53,31 @@
> >
<view class="confirm_box"> 是否确定退出登录 </view> <view class="confirm_box"> 是否确定退出登录 </view>
</CustomPopup> </CustomPopup>
</view> </mj-page>
</template> </template>
<script setup> <script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'; import { ref, computed, onMounted, onUnmounted } from 'vue'
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app'
import { user } from '@/store'; import { user } from '@/store'
import { updateUserInfoApi } from '@/api'; import { updateUserInfoApi } from '@/api'
import { storeToRefs } from 'pinia'; import { storeToRefs } from 'pinia'
import router from '@/router/router'; import router from '@/router/router'
import CustomPopup from '@/components/CustomPopup/index.vue'; import CustomPopup from '@/components/CustomPopup/index.vue'
// #ifdef H5 // #ifdef H5
import { h5Authorization } from '@/store'; import { h5Authorization } from '@/store'
const { authorizedLogin } = h5Authorization(); import hud from '@/utils/hud'
const { authorizedLogin } = h5Authorization()
// #endif // #endif
const popupRef = ref(null); const popupRef = ref(null)
const OSS_URL = import.meta.env.VITE_OSS_HOST; const OSS_URL = import.meta.env.VITE_OSS_HOST
const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`; const defaultAvatar = `${OSS_URL}/urm/default_avatar.png`
const arrow = `${OSS_URL}/iconfont/down_arrow.png`; const arrow = `${OSS_URL}/iconfont/down_arrow.png`
const { logout, getUserInfo } = user(); const { logout, getUserInfo } = user()
const { userInfo } = storeToRefs(user()); const { userInfo } = storeToRefs(user())
const indicatorStyle = ref(`height: 50px;`); const indicatorStyle = ref(`height: 50px;`)
const showCustomPopup = ref(false); const showCustomPopup = ref(false)
const pageType = ref(); // 1- const pageType = ref() // 1-
const pickList = ref([ const pickList = ref([
{ {
name: '从相册选择', name: '从相册选择',
@ -88,24 +89,24 @@ const pickList = ref([
type: 2, type: 2,
sourceType: 'camera', sourceType: 'camera',
}, },
]); ])
const info = ref({ const info = ref({
avatar: '', // id avatar: '', // id
avatarUrl: '', avatarUrl: '',
id: '', // id id: '', // id
nickName: '', nickName: '',
}); })
function handlePreview() { function handlePreview() {
if (!info.value.avatarUrl) return; if (!info.value.avatarUrl) return
uni.previewImage({ uni.previewImage({
urls: [info.value.avatarUrl], urls: [info.value.avatarUrl],
current: 0, current: 0,
}); })
} }
function chooseUploadMethod(i) { function chooseUploadMethod(i) {
popupRef.value.close(); popupRef.value.close()
uni.chooseImage({ uni.chooseImage({
count: 1, // count: 1, //
sizeType: ['compressed', 'original'], // original compressed sizeType: ['compressed', 'original'], // original compressed
@ -113,14 +114,14 @@ function chooseUploadMethod(i) {
success: res => { success: res => {
router.navigateTo({ router.navigateTo({
path: `/pages/mine/prefectInformation/cropper`, path: `/pages/mine/prefectInformation/cropper`,
query: { file: res.tempFilePaths[0] } query: { file: res.tempFilePaths[0] },
}); })
}, },
fail: err => { fail: err => {
// //
console.log('chooseImage fail', err); console.log('chooseImage fail', err)
}, },
}); })
} }
async function saveUpdate() { async function saveUpdate() {
@ -128,45 +129,50 @@ async function saveUpdate() {
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
title: '头像、昵称不能为空', title: '头像、昵称不能为空',
}); })
return; return
} }
uni.showLoading({ title: '更新中...' }); uni.showLoading({ title: '更新中...' })
try { try {
await updateUserInfoApi(info.value); await updateUserInfoApi(info.value)
await getUserInfo(); await getUserInfo()
uni.hideLoading(); uni.hideLoading()
router.redirectTo('/pages/mine/index'); router.redirectTo('/pages/mine/index')
} catch (err) { } catch (err) {
uni.hideLoading(); uni.hideLoading()
} }
} }
function handleConfirmPopup() { function handleConfirmPopup() {
showCustomPopup.value = false; showCustomPopup.value = false
logout(); hud.load({
task: async () => {
await logout()
},
option: '退出登录',
})
} }
onLoad(option => { onLoad(option => {
pageType.value = option.type ? Number(option.type) : undefined; pageType.value = option.type ? Number(option.type) : undefined
uni.$on('filePathMsg', data => { uni.$on('filePathMsg', data => {
info.value.avatarUrl = data.filePath; info.value.avatarUrl = data.filePath
info.value.avatar = data.id; info.value.avatar = data.id
pageType.value = data.type; pageType.value = data.type
}); })
for (let key in info.value) { for (let key in info.value) {
info.value[key] = userInfo.value[key]; info.value[key] = userInfo.value[key]
} }
}); })
onMounted(() => { onMounted(() => {
// #ifdef H5 // #ifdef H5
if (pageType.value === 1) return; if (pageType.value === 1) return
authorizedLogin(); authorizedLogin()
// #endif // #endif
}); })
onUnmounted(() => { onUnmounted(() => {
uni.$off('filePathMsg'); uni.$off('filePathMsg')
}); })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,37 +1,38 @@
/* eslint-disable no-param-reassign */
import page from './page' import page from './page'
// 可以在不同的地方共享数据、传参 // 可以在不同的地方共享数据、传参
function get<T>(key?: string, defaultValue?: T): T { function get<T>(key?: string, defaultValue?: T): T {
if (!key) { if (!key) {
key = page.getPagePath() key = page.getPagePath()
} }
const val = uni.getStorageSync(key) const val = uni.getStorageSync(key)
return (val === undefined ? defaultValue : val) as T return (val === undefined ? defaultValue : val) as T
} }
// 设值 // 设值
function set(key: string, value: any) { function set(key: string, value: any) {
uni.setStorageSync(key, value) uni.setStorageSync(key, value)
} }
// 弹出值 // 弹出值
function pop<T>(key?: string, defaultValue?: T): T { function pop<T>(key?: string, defaultValue?: T): T {
if (!key) { if (!key) {
key = page.getPagePath() key = page.getPagePath()
} }
const value = uni.getStorageSync(key) const value = uni.getStorageSync(key)
uni.removeStorageSync(key) uni.removeStorageSync(key)
return value || defaultValue return value || defaultValue
} }
// 清空 // 清空
function clear() { function clear() {
uni.clearStorageSync() uni.clearStorageSync()
} }
export default { export default {
get, get,
set, set,
pop, pop,
clear, clear,
} }

View File

@ -1,79 +1,85 @@
/* eslint-disable no-param-reassign */
import page from './page' import page from './page'
// 可以在不同的地方共享数据、传参 // 可以在不同的地方共享数据、传参
let _DATA: { [key: string]: any } = {} let _DATA: { [key: string]: any } = {}
function get<T>(key?: string, defaultValue?: T): T { function get<T>(key?: string, defaultValue?: T): T {
if (!key) { if (!key) {
key = page.getPagePath() key = page.getPagePath()
} }
const val = _DATA[key] const val = _DATA[key]
return (val === undefined ? defaultValue : val) as T return (val === undefined ? defaultValue : val) as T
} }
// 设值 // 设值
function set(key: string, value: any) { function set(key: string, value: any) {
_DATA[key] = value _DATA[key] = value
} }
// 弹出值 // 弹出值
function pop<T>(key?: string, defaultValue?: T): T { function pop<T>(key?: string, defaultValue?: T): T {
if (!key) { if (!key) {
key = page.getPagePath() key = page.getPagePath()
} }
const value = _DATA[key] const value = _DATA[key]
delete _DATA[key] delete _DATA[key]
return value || defaultValue return value || defaultValue
} }
// 清空 // 清空
function clear() { function clear() {
_DATA = {} _DATA = {}
} }
// 函数的key // 函数的key
function _pageFnObjKey(pageUrl: string) { function _pageFnObjKey(pageUrl: string) {
return pageUrl + '_mj_fn_obj' return pageUrl + '_mj_fn_obj'
} }
function _getPageFnObj(pageUrl: string) { function _getPageFnObj(pageUrl: string) {
const key = _pageFnObjKey(pageUrl) if (!pageUrl) return undefined
let fnObj = _DATA[key] const key = _pageFnObjKey(pageUrl)
if (!fnObj) { let fnObj = _DATA[key]
fnObj = {} if (!fnObj) {
_DATA[key] = fnObj fnObj = {}
} _DATA[key] = fnObj
return fnObj }
return fnObj
} }
// 调用函数 // 调用函数
function callFn(key: string, ...args: any) { function callFn(key: string, ...args: any) {
// 函数对象 // 函数对象
const fn = _getPageFnObj(page.getPagePath())[key] const obj = _getPageFnObj(page.getPagePath())
if (fn) { if (!obj) return
// 直接调用 const fn = obj[key]
return fn(...args) if (fn) {
} // 直接调用
// console.log('callFn', _DATA) return fn(...args)
}
// console.log('callFn', _DATA)
} }
// 存储函数 // 存储函数
function setFn(key: string, fn: any) { function setFn(key: string, fn: any) {
_getPageFnObj(page.getPagePath())[key] = fn const obj = _getPageFnObj(page.getPagePath())
// console.log('setFn', _DATA) if (!obj) return
obj[key] = fn
// console.log('setFn', _DATA)
} }
function popPageFns(pageUrl: string) { function popPageFns(pageUrl: string) {
delete _DATA[_pageFnObjKey(pageUrl)] delete _DATA[_pageFnObjKey(pageUrl)]
// console.log('popPageFns', _DATA) // console.log('popPageFns', _DATA)
} }
export default { export default {
get, get,
set, set,
pop, pop,
clear, clear,
callFn, callFn,
setFn, setFn,
popPageFns, popPageFns,
} }

View File

@ -1,15 +1,16 @@
const DATA: { [key: string]: any } = {} const DATA: { [key: string]: any } = {}
function getPage() { function getPage() {
const pages = getCurrentPages() const pages = getCurrentPages()
return pages[pages.length - 1] return pages?.length ? pages[pages.length - 1] : undefined
} }
function getPagePath() { function getPagePath() {
return '/' + getPage().route const route = getPage()?.route
return route ? '/' + route : ''
} }
export default { export default {
getPage, getPage,
getPagePath, getPagePath,
} }