This commit is contained in:
6977
package-lock.json
generated
6977
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,7 @@
|
||||
"vue": "^3.4.0",
|
||||
"clipboard": "^2.0.11",
|
||||
"dayjs": "^1.11.19",
|
||||
"html5-qrcode": "^2.3.8",
|
||||
"uview-plus": "^3.6.29"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,22 @@
|
||||
<text>扫一扫登录</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="showScanner" class="scanner-overlay">
|
||||
<view class="scanner-container">
|
||||
<view class="scanner-header">
|
||||
<text>扫一扫</text>
|
||||
<text class="close-btn" @tap="closeScanner">×</text>
|
||||
</view>
|
||||
<view id="scanner-region" class="scanner-region"></view>
|
||||
<view class="scanner-tip">将二维码放入框内即可自动扫描</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<view class="agreement">
|
||||
<view class="agreement-text">
|
||||
@@ -65,10 +81,11 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { authApi } from '@/api/index.js';
|
||||
import { useUserStore } from '@/store/index.js';
|
||||
import { APP_ID, USE_WECHAT_AUTH } from '@/utils/env.js';
|
||||
import { Html5Qrcode } from 'html5-qrcode';
|
||||
|
||||
const userStore = useUserStore();
|
||||
|
||||
@@ -81,11 +98,19 @@
|
||||
getPathDeviceId();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (html5QrCode) {
|
||||
html5QrCode.stop().catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
const identifier = ref('');
|
||||
const loading = ref(false);
|
||||
const agreed = ref(true);
|
||||
const inputFocus = ref(false);
|
||||
const showError = ref(false);
|
||||
const showScanner = ref(false);
|
||||
let html5QrCode = null;
|
||||
|
||||
const getCode = () => {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
@@ -125,35 +150,44 @@
|
||||
doLogin();
|
||||
};
|
||||
|
||||
const handleScanLogin = () => {
|
||||
// #ifdef H5
|
||||
if (typeof wx !== 'undefined' && wx.scanQRCode) {
|
||||
wx.scanQRCode({
|
||||
needResult: 1,
|
||||
scanType: ['qrCode', 'barCode'],
|
||||
success: (res) => {
|
||||
const result = res.resultStr;
|
||||
if (result && result.includes('device_id')) {
|
||||
const match = result.match(/device_id[=]([^&]*)/);
|
||||
if (match && match[1]) {
|
||||
identifier.value = match[1];
|
||||
handleLogin();
|
||||
}
|
||||
const handleScanLogin = async () => {
|
||||
showScanner.value = true;
|
||||
|
||||
try {
|
||||
html5QrCode = new Html5Qrcode('scanner-region');
|
||||
await html5QrCode.start(
|
||||
{ facingMode: 'environment' },
|
||||
{
|
||||
fps: 10,
|
||||
qrbox: { width: 250, height: 250 }
|
||||
},
|
||||
(decodedText) => {
|
||||
const match = decodedText.match(/=([^=]+)$/);
|
||||
if (match && match[1]) {
|
||||
identifier.value = match[1];
|
||||
closeScanner();
|
||||
handleLogin();
|
||||
} else {
|
||||
uni.showToast({ title: '无效的二维码', icon: 'none' });
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({ title: '扫码失败,请重试', icon: 'none' });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
uni.showToast({ title: '扫一扫功能暂不可用', icon: 'none' });
|
||||
() => {}
|
||||
);
|
||||
} catch (err) {
|
||||
console.error('扫码失败', err);
|
||||
uni.showToast({ title: '无法访问摄像头', icon: 'none' });
|
||||
closeScanner();
|
||||
}
|
||||
};
|
||||
|
||||
const closeScanner = async () => {
|
||||
showScanner.value = false;
|
||||
if (html5QrCode) {
|
||||
try {
|
||||
await html5QrCode.stop();
|
||||
} catch (e) {}
|
||||
html5QrCode = null;
|
||||
}
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
uni.showToast({ title: '请在微信中打开', icon: 'none' });
|
||||
// #endif
|
||||
};
|
||||
|
||||
const getPathDeviceId = () => {
|
||||
@@ -469,4 +503,52 @@
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.scanner-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.scanner-container {
|
||||
width: 600rpx;
|
||||
background: var(--bg-primary);
|
||||
border-radius: var(--radius-large);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scanner-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
border-bottom: 1rpx solid var(--border-light);
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
font-size: 48rpx;
|
||||
color: var(--text-tertiary);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.scanner-region {
|
||||
width: 100%;
|
||||
height: 600rpx;
|
||||
}
|
||||
|
||||
.scanner-tip {
|
||||
padding: 24rpx;
|
||||
text-align: center;
|
||||
font-size: 26rpx;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
</style>
|
||||
|
||||
29
utils/wxsdk.js
Normal file
29
utils/wxsdk.js
Normal file
@@ -0,0 +1,29 @@
|
||||
import { BASE_URL, APP_ID } from './env.js';
|
||||
|
||||
export const initWxSdk = async () => {
|
||||
if (typeof wx === 'undefined') return false;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${BASE_URL}/api/c/v1/wx/signature?url=${encodeURIComponent(window.location.href)}`);
|
||||
const data = await res.json();
|
||||
|
||||
if (data.code === 200 || data.code === 0) {
|
||||
wx.config({
|
||||
debug: false,
|
||||
appId: APP_ID,
|
||||
timestamp: data.data.timestamp,
|
||||
nonceStr: data.data.nonceStr,
|
||||
signature: data.data.signature,
|
||||
jsApiList: ['scanQRCode']
|
||||
});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
wx.ready(() => resolve(true));
|
||||
wx.error(() => resolve(false));
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('WX SDK init failed', e);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
Reference in New Issue
Block a user