You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

507 lines
16 KiB

1 year ago
<script>
11 months ago
import { API } from './config/index.js'
import { urlUtils } from './common/util.js'
4 months ago
// #ifdef H5
import wx from 'jweixin-module'
// #endif
11 months ago
1 year ago
export default {
11 months ago
onLaunch: function() {
console.log('App Launch')
// 判断环境
// #ifdef H5
4 months ago
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
console.log('[App] H5 onLaunch, isWeixinBrowser =', isWeixinBrowser, ', typeof wx =', typeof wx)
// 将 wx 挂载到 window 上,保持兼容性
if (typeof window !== 'undefined' && typeof wx !== 'undefined') {
window.wx = wx
console.log('[App] 已将 wx 挂载到 window.wx')
} else {
console.warn('[App] 未找到 wx 对象jweixin-module 可能未正确加载')
}
// 判断是否是开发环境
if (process.env.NODE_ENV === 'development') {
console.log('开发环境,使用模拟登录')
this.mockAccountLogin('songwz', 'Abcd1234')
} else {
this.wxH5AuthLogin()
}
4 months ago
// 配置微信 JS-SDK
this.configWechatJSSDK()
// #endif
// #ifdef MP-WEIXIN
11 months ago
this.wxLogin()
// #endif
1 year ago
},
onShow: function() {
11 months ago
console.log('App Show')
4 months ago
// #ifdef H5
// 在 onShow 中也检查一次登录,因为有时候 onLaunch 可能没有正确执行
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
if (isWeixinBrowser && process.env.NODE_ENV !== 'development') {
const token = uni.getStorageSync('token')
if (!token) {
console.log('[App] onShow 检测到没有 token重新尝试登录')
this.wxH5AuthLogin()
}
}
// #endif
1 year ago
},
onHide: function() {
console.log('App Hide')
11 months ago
},
onLoad: function() {
console.log('App Load')
},
11 months ago
methods: {
wxLogin() {
// const token = uni.getStorageSync('token')
// if (token) {
// console.log('本地已有 token直接使用:', token)
// return
// }
uni.login({
provider: 'weixin',
success: (loginRes) => {
const code = loginRes.code
console.log('微信登录成功code:', code)
// 上传 code 到服务器获取 token
uni.request({
url: API.LOGIN,
method: 'POST',
data: { code },
success: (res) => {
const result = res.data
if (result.errcode === 0) {
const token = result.data.access_token
console.log('获取 token 成功:', token)
uni.setStorageSync('token', token)
} else {
console.error('登录失败:', result.errmsg)
// 可选uni.showToast({ title: result.errmsg, icon: 'none' })
}
},
fail: (err) => {
console.error('获取 token 失败:', err)
}
})
},
fail: (err) => {
console.error('微信登录失败:', err)
}
})
},
// 微信公众号授权登录
wxAuthLogin() {
uni.getUserProfile({
desc: '用于完善用户资料',
success: (profileRes) => {
console.log('获取用户信息成功:', profileRes.userInfo)
const userInfo = profileRes.userInfo
// 存储用户信息到本地
uni.setStorageSync('userInfo', userInfo)
// 获取token
const token = uni.getStorageSync('token')
if (!token) {
uni.showToast({
title: '请先登录',
icon: 'none'
})
return
}
// 上传用户信息到服务器
uni.request({
url: API.GET_USER_INFO,
method: 'POST',
data: {
token,
userInfo
},
success: (res) => {
console.log('上传用户信息成功:', res.data)
uni.showToast({
title: '授权成功',
icon: 'success'
})
},
fail: (err) => {
console.error('上传用户信息失败:', err)
uni.showToast({
title: '授权失败',
icon: 'none'
})
}
})
},
fail: (err) => {
console.error('获取用户信息失败:', err)
uni.showToast({
title: '获取用户信息失败',
icon: 'none'
})
}
})
},
// 微信公众号H5授权登录
wxH5AuthLogin() {
// 判断是否在微信客户端中打开
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
if (!isWeixinBrowser) {
4 months ago
console.log('[App] 非微信环境,跳过登录')
return
}
// 检查是否已经有 token
const existingToken = uni.getStorageSync('token')
if (existingToken) {
console.log('[App] 已存在 token跳过登录')
return
}
4 months ago
let link = window.location.href;
4 months ago
console.log('[App] 当前 URL:', link)
// 改进 code 提取逻辑,支持多种 URL 格式
let code = null;
try {
// 方法1: 使用 URLSearchParams (更可靠)
if (typeof URLSearchParams !== 'undefined') {
const url = new URL(link)
code = url.searchParams.get('code')
}
// 方法2: 如果方法1失败使用正则表达式
if (!code) {
const match = link.match(/[?&]code=([^&?#]+)/)
if (match && match[1]) {
code = decodeURIComponent(match[1].replace(/\+/g, '%20'))
}
}
// 方法3: 备用正则表达式
if (!code) {
const regex = new RegExp('[?|&]' + 'code' + '=' + '([^&;]+?)(&|#|;|$)')
const match = regex.exec(link)
if (match && match[1]) {
code = decodeURIComponent(match[1].replace(/\+/g, '%20'))
}
}
} catch (e) {
console.error('[App] 提取 code 失败:', e)
}
console.log('[App] 提取到的 code:', code)
if (code) {
// 清理 URL 中的 code 参数,避免重复登录
try {
const url = new URL(link)
url.searchParams.delete('code')
url.searchParams.delete('state')
// 使用 replaceState 更新 URL但不刷新页面
if (window.history && window.history.replaceState) {
window.history.replaceState({}, '', url.toString())
}
} catch (e) {
console.warn('[App] 清理 URL 参数失败:', e)
}
// 上传 code 到服务器获取 token
4 months ago
console.log('[App] 开始调用登录接口code:', code)
uni.request({
4 months ago
url: API.WX_LOGIN,
method: 'POST',
data: { code: code },
success: (res) => {
console.log('[App] 登录接口响应:', res.data)
const result = res.data
if (result.errcode === 0) {
const token = result.data.access_token
console.log('[App] 获取 token 成功:', token)
uni.setStorageSync('token', token)
// 触发登录成功事件,通知其他页面 token 已就绪
uni.$emit('loginSuccess', { token })
} else {
console.error('[App] 登录失败:', result.errmsg)
uni.showToast({ title: result.errmsg || '登录失败', icon: 'none' })
}
4 months ago
},
fail: (err) => {
console.error('[App] 获取 token 失败:', err)
uni.showToast({ title: '网络错误,请重试', icon: 'none' })
}
})
} else {
// 没有 code需要跳转到授权页面
console.log('[App] 未找到 code跳转到授权页面')
5 months ago
const appId = 'wx9538bc740fe87fce'
4 months ago
// 获取当前 URL去掉 hash 和已有的 code 参数
let currentUrl = window.location.href.split('#')[0]
// 清理已有的 code 和 state 参数
currentUrl = currentUrl.replace(/[?&]code=[^&]*/g, '').replace(/[?&]state=[^&]*/g, '')
// 如果清理后以 ? 结尾,去掉 ?
currentUrl = currentUrl.replace(/\?$/, '')
const redirectUri = encodeURIComponent(currentUrl)
const scope = 'snsapi_userinfo'
const state = 'STATE'
4 months ago
console.log('[App] redirectUri:', redirectUri)
const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirectUri}&response_type=code&scope=${scope}&state=${state}#wechat_redirect`
// 重定向到微信授权页面
4 months ago
console.log('[App] 跳转到授权页面:', authUrl)
window.location.href = authUrl
}
},
// 模拟微信登录(仅用于本地测试)
mockAccountLogin(username, password) {
uni.request({
url: API.LOGIN_ACCOUNT,
method: 'GET',
data: { username, password },
success: (res) => {
console.log('mockAccountLogin', res)
if (res.data && res.data.code) {
// 用接口返回的 code 走后续流程
// this.handleWxH5Login(res.data.code)
} else if (res.data && res.data.data.access_token) {
// 或者直接返回 token
4 months ago
const token = res.data.data.access_token
uni.setStorageSync('token', token)
uni.showToast({ title: '登录成功', icon: 'success' })
4 months ago
// 触发登录成功事件
uni.$emit('loginSuccess', { token })
} else {
uni.showToast({ title: '登录失败', icon: 'none' })
}
},
fail: () => {
uni.showToast({ title: '请求失败', icon: 'none' })
}
})
},
4 months ago
// 配置微信 JS-SDK
configWechatJSSDK() {
// #ifdef H5
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
console.log('[App] configWechatJSSDK 调用isWeixinBrowser =', isWeixinBrowser, ', typeof wx =', typeof wx, ', has window.wx =', typeof window !== 'undefined' && !!window.wx)
if (!isWeixinBrowser || typeof window === 'undefined' || typeof wx === 'undefined') {
console.log('[App] 非微信环境或微信JS-SDK未加载跳过配置')
return
}
// 获取当前页面URL用于签名去掉 hash 部分
const rawUrl = window.location.href.split('#')[0]
// 按后端要求进行 encodeURIComponent 编码
const encodedUrl = encodeURIComponent(rawUrl)
console.log('[App] 当前用于签名的 URL =', rawUrl, ',编码后 =', encodedUrl)
// 调用后端 wx-config 接口,获取 JSSDK 配置appId/timestamp/nonceStr/signature
uni.request({
url: `${API.WECHAT_JSSDK_CONFIG}?url=${encodedUrl}`,
method: 'GET',
success: (res) => {
console.log('[App] WECHAT_JSSDK_CONFIG 响应:', res.data)
if (!res.data) {
console.warn('[App] WECHAT_JSSDK_CONFIG 返回为空')
return
}
if (res.data.errcode !== 0 || !res.data.data) {
console.warn('[App] 获取微信 JSSDK 配置失败errcode =', res.data.errcode, 'errmsg =', res.data.errmsg)
return
}
// 正常返回配置数据
const cfg = res.data.data
this.initWechatJSSDK(cfg)
},
fail: (err) => {
console.error('[App] 调用 WECHAT_JSSDK_CONFIG 接口失败:', err)
}
})
// #endif
},
// 初始化微信 JS-SDK
initWechatJSSDK(config) {
// #ifdef H5
if (typeof wx === 'undefined') {
console.error('微信 JS-SDK 未加载')
return
}
wx.config({
debug: false, // 生产环境设为 false
appId: config.appId,
timestamp: config.timestamp,
nonceStr: config.nonceStr,
signature: config.signature,
jsApiList: [
'getLocation', // 获取地理位置
'onMenuShareTimeline', // 分享到朋友圈
'onMenuShareAppMessage', // 分享给朋友
'onMenuShareQQ', // 分享到QQ
'onMenuShareWeibo' // 分享到微博
]
})
wx.ready(() => {
console.log('微信 JS-SDK 配置成功')
// 配置成功后,设置全局分享
this.setupGlobalWechatShare()
})
wx.error((res) => {
console.error('微信 JS-SDK 配置失败:', res)
uni.showToast({
title: '微信功能配置失败',
icon: 'none'
})
})
// #endif
},
// 配置全局微信分享
setupGlobalWechatShare() {
// #ifdef H5
const isWeixinBrowser = /MicroMessenger/i.test(navigator.userAgent)
4 months ago
if (!isWeixinBrowser || typeof window === 'undefined') {
console.log('非微信环境,跳过分享配置')
return
}
// 使用 window.wx 或直接使用 wx
const wxObj = window.wx || wx
if (!wxObj) {
console.log('微信JS-SDK未加载跳过分享配置')
return
}
// 获取当前页面入口地址作为分享链接
const currentUrl = window.location.href
// 移除URL中的hash部分只保留基础URL
const baseUrl = currentUrl.split('#')[0]
// 全局分享配置
const shareConfig = {
title: '胥口枢纽闸站公众号',
desc: '主要功能为胥口闸站船只过闸预约、支付等功能',
link: baseUrl,
imgUrl: window.location.origin + '/static/icon_logo.png',
type: 'link'
}
// 生成安全的分享链接
let safeShareUrl = shareConfig.link;
try {
safeShareUrl = urlUtils.generateSafeShareUrl(shareConfig.link, {
source: 'share',
timestamp: Date.now()
})
} catch (error) {
console.warn('生成安全分享链接时出错:', error)
// 使用默认链接
safeShareUrl = shareConfig.link
}
4 months ago
// 使用 ready 回调或直接配置
const setupShare = () => {
console.log('微信JS-SDK准备就绪配置全局分享')
// 分享到朋友圈
4 months ago
wxObj.onMenuShareTimeline({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
imgUrl: shareConfig.imgUrl,
success: () => {
console.log('分享到朋友圈成功')
uni.showToast({ title: '分享到朋友圈成功', icon: 'success' })
},
cancel: () => {
console.log('取消分享到朋友圈')
}
})
// 分享给朋友
4 months ago
wxObj.onMenuShareAppMessage({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
imgUrl: shareConfig.imgUrl,
type: shareConfig.type,
dataUrl: '',
success: () => {
console.log('分享给朋友成功')
uni.showToast({ title: '分享给朋友成功', icon: 'success' })
},
cancel: () => {
console.log('取消分享给朋友')
}
})
// 分享到QQ
4 months ago
wxObj.onMenuShareQQ({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
imgUrl: shareConfig.imgUrl,
success: () => {
console.log('分享到QQ成功')
uni.showToast({ title: '分享到QQ成功', icon: 'success' })
},
cancel: () => {
console.log('取消分享到QQ')
}
})
// 分享到微博
4 months ago
wxObj.onMenuShareWeibo({
title: shareConfig.title,
desc: shareConfig.desc,
link: safeShareUrl,
imgUrl: shareConfig.imgUrl,
success: () => {
console.log('分享到微博成功')
uni.showToast({ title: '分享到微博成功', icon: 'success' })
},
cancel: () => {
console.log('取消分享到微博')
}
})
console.log('全局微信分享配置完成')
4 months ago
}
4 months ago
// 如果 wx 已经 ready直接配置否则等待 ready
if (wxObj.ready) {
wxObj.ready(setupShare)
} else {
// 如果 wx 对象存在但没有 ready 方法,尝试直接配置
setupShare()
}
if (wxObj.error) {
wxObj.error((res) => {
console.error('微信JS-SDK配置失败:', res)
})
}
// #endif
11 months ago
}
1 year ago
}
}
</script>
<style lang="scss">
/*每个页面公共css */
@import "uview-ui/index.scss";
</style>