diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7b274cb..1f11a55 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,7 +1,8 @@ { "permissions": { "allow": [ - "Bash(git add:*)" + "Bash(git add:*)", + "Bash(npm list:*)" ], "deny": [], "ask": [] diff --git a/index.html b/index.html index dadd21a..40d9164 100644 --- a/index.html +++ b/index.html @@ -7,7 +7,6 @@
- diff --git a/package-lock.json b/package-lock.json index 78cd65b..34b5e14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "@dcloudio/uni-h5": "3.0.0-4080720251210001", "clipboard": "^2.0.11", "dayjs": "^1.11.19", + "jweixin-module": "^1.6.0", "uview-plus": "^3.6.29", "vue": "^3.4.0" }, @@ -5096,6 +5097,12 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jweixin-module": { + "version": "1.6.0", + "resolved": "https://registry.npmmirror.com/jweixin-module/-/jweixin-module-1.6.0.tgz", + "integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w==", + "license": "ISC" + }, "node_modules/lcid": { "version": "3.1.1", "resolved": "https://registry.npmmirror.com/lcid/-/lcid-3.1.1.tgz", diff --git a/package.json b/package.json index 72c8d1e..f4db418 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@dcloudio/uni-h5": "3.0.0-4080720251210001", "clipboard": "^2.0.11", "dayjs": "^1.11.19", + "jweixin-module": "^1.6.0", "uview-plus": "^3.6.29", "vue": "^3.4.0" } diff --git a/pages/login/login.vue b/pages/login/login.vue index 7cd341a..1439476 100644 --- a/pages/login/login.vue +++ b/pages/login/login.vue @@ -69,7 +69,7 @@ import { authApi } from '@/api/index.js'; import { useUserStore } from '@/store/index.js'; import { APP_ID } from '@/utils/env.js'; - import { initWxSdk } from '@/utils/wxsdk.js'; + import weChatScanService from '@/utils/wxsdk.js'; const userStore = useUserStore(); @@ -126,26 +126,38 @@ const handleScanLogin = async () => { // #ifdef H5 - const result = await initWxSdk(); - console.log('微信SDK初始化结果:', result); - if (!result.success) { - uni.showToast({ title: result.error || '扫一扫功能暂不可用', icon: 'none' }); - return; - } - wx.scanQRCode({ - needResult: 1, - scanType: ['qrCode', 'barCode'], - success: (res) => { - const result = res.resultStr; + try { + // 检查是否在微信环境 + if (!weChatScanService.isInWechat()) { + uni.showToast({ title: '请在微信中打开', icon: 'none' }); + return; + } + + // 初始化微信 SDK + const initResult = await weChatScanService.initWxSDK(); + console.log('微信SDK初始化结果:', initResult); + + if (!initResult.success) { + uni.showToast({ title: initResult.error || '扫一扫功能暂不可用', icon: 'none' }); + return; + } + + // 调用扫一扫 + const scanResult = await weChatScanService.scanQRCode(); + console.log('扫码结果:', scanResult); + + if (scanResult.success) { + const resultStr = scanResult.result; let value = ''; - if (result.includes('?')) { - const params = new URLSearchParams(result.split('?')[1]); + // 解析二维码内容 + if (resultStr.includes('?')) { + const params = new URLSearchParams(resultStr.split('?')[1]); value = params.get('cardNum') || ''; } if (!value) { - const match = result.match(/=([^=]+)$/); + const match = resultStr.match(/=([^=]+)$/); value = match ? match[1] : ''; } @@ -155,11 +167,11 @@ const handleScanLogin = async () => { } else { uni.showToast({ title: '无效的二维码', icon: 'none' }); } - }, - fail: () => { - uni.showToast({ title: '扫码失败', icon: 'none' }); } - }); + } catch (err) { + console.error('扫码错误:', err); + uni.showToast({ title: err.message || '扫码失败', icon: 'none' }); + } // #endif // #ifndef H5 uni.showToast({ title: '请在微信中打开', icon: 'none' }); diff --git a/utils/wxsdk.js b/utils/wxsdk.js index 537091d..e289fb6 100644 --- a/utils/wxsdk.js +++ b/utils/wxsdk.js @@ -1,48 +1,108 @@ +import wx from 'jweixin-module'; import { wechatApi } from '@/api/index.js'; -export const initWxSdk = async () => { - // #ifdef H5 - try { - console.log('[initWxSdk] 开始初始化...'); - console.log('[initWxSdk] typeof wx:', typeof wx); - - // 检查 wx 是否存在 - if (typeof wx === 'undefined') { - console.error('[initWxSdk] wx对象不存在,请确保在微信中打开'); - return { success: false, error: '请在微信中打开' }; - } - - const currentUrl = window.location.href.split('#')[0]; - console.log('[initWxSdk] 当前URL:', currentUrl); - - const data = await wechatApi.getJssdkConfig(currentUrl); - console.log('[initWxSdk] 获取到配置:', data); - - wx.config({ - debug: true, - appId: data.app_id, - timestamp: data.timestamp, - nonceStr: data.nonce_str, - signature: data.signature, +/** + * 微信 JS-SDK 初始化和扫码功能封装 + */ +class WeChatScanService { + constructor() { + this.isWxReady = false; + this.config = { + debug: true, // 开发环境设置为 true 便于调试 jsApiList: ['scanQRCode'] - }); - - return new Promise((resolve) => { - wx.ready(() => { - console.log('[initWxSdk] SDK配置成功'); - resolve({ success: true }); - }); - wx.error((err) => { - console.error('[initWxSdk] SDK配置失败:', err); - resolve({ success: false, error: err.errMsg || '微信配置失败' }); - }); - }); - } catch (e) { - console.error('[initWxSdk] 初始化失败:', e); - return { success: false, error: e.message || '初始化失败' }; + }; } - // #endif - // #ifndef H5 - return { success: false, error: '请在H5环境中使用' }; - // #endif -}; \ No newline at end of file + + /** + * 初始化微信 JS-SDK + */ + async initWxSDK() { + try { + console.log('[WxSDK] 开始初始化...'); + + // 获取当前页面 URL (去掉 hash 部分) + const currentUrl = window.location.href.split('#')[0]; + console.log('[WxSDK] 当前URL:', currentUrl); + + // 调用后端接口获取签名 + const signatureData = await wechatApi.getJssdkConfig(currentUrl); + console.log('[WxSDK] 获取到签名配置:', signatureData); + + return new Promise((resolve, reject) => { + wx.config({ + debug: this.config.debug, + appId: signatureData.app_id, + timestamp: signatureData.timestamp, + nonceStr: signatureData.nonce_str, + signature: signatureData.signature, + jsApiList: this.config.jsApiList + }); + + wx.ready(() => { + console.log('[WxSDK] 初始化成功'); + this.isWxReady = true; + resolve({ success: true }); + }); + + wx.error((res) => { + console.error('[WxSDK] 初始化失败:', res); + this.isWxReady = false; + reject({ success: false, error: res.errMsg || '微信配置失败' }); + }); + }); + } catch (e) { + console.error('[WxSDK] 初始化异常:', e); + return { success: false, error: e.message || '初始化失败' }; + } + } + + /** + * 调用微信扫一扫功能 + */ + async scanQRCode(options = {}) { + return new Promise((resolve, reject) => { + if (!this.isWxReady) { + reject({ success: false, error: '微信 JS-SDK 未就绪,请先初始化' }); + return; + } + + const defaultOptions = { + needResult: 1, + scanType: ['qrCode', 'barCode'] + }; + + const scanOptions = { ...defaultOptions, ...options }; + + wx.scanQRCode({ + needResult: scanOptions.needResult, + scanType: scanOptions.scanType, + success: (res) => { + console.log('[WxSDK] 扫码成功:', res); + resolve({ + success: true, + result: res.resultStr || res.result, + data: res + }); + }, + fail: (err) => { + console.error('[WxSDK] 扫码失败:', err); + reject({ + success: false, + error: err, + message: '扫码失败,请重试' + }); + } + }); + }); + } + + /** + * 检查是否在微信环境中 + */ + isInWechat() { + return /micromessenger/i.test(navigator.userAgent); + } +} + +// 导出单例 +export default new WeChatScanService(); \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 13b88e9..c0b38e0 100644 --- a/vite.config.js +++ b/vite.config.js @@ -2,26 +2,5 @@ import { defineConfig } from 'vite' import uni from '@dcloudio/vite-plugin-uni' export default defineConfig({ - plugins: [ - uni({ - vueOptions: { - template: { - compilerOptions: { - // 保留微信 JSSDK 相关的全局变量 - isCustomElement: (tag) => tag === 'wx' - } - } - } - }) - ], - build: { - rollupOptions: { - external: ['wx'], - output: { - globals: { - wx: 'wx' - } - } - } - } + plugins: [uni()], })