fix(scancode): 小程序扫码登录修复黑屏并统一为微信扫码→授权页
- scan-login: 去 useLoad/useDidShow/getEnterOptionsSync 元钩子(原生计时器调度React hook致黑屏),改纯React useEffect+getCurrentInstance 读scene;window.setInterval→setInterval - mine: 移除内部 Taro.scanCode 跨端口扫码登录入口/按钮/状态,改为引导卡片,统一「微信扫小程序码→进小程序→授权页确认」 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ import { View, Text, Button, Input, Image } from '@tarojs/components';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useTabIndex } from '@/utils/tab';
|
||||
import { isAuthed, getUser, logout, wxLogin, phoneLogin, bindPhone, sendCode, wxPhoneBind, updateProfile, getMe, mpQrConfirm } from '@/utils/auth';
|
||||
import { isAuthed, getUser, logout, wxLogin, phoneLogin, bindPhone, sendCode, wxPhoneBind, updateProfile, getMe } from '@/utils/auth';
|
||||
import { getMyBookings, checkIn, parseIso, BK_STATUS_OPTIONS, BK_TOPIC_OPTIONS, BK_SOURCE_OPTIONS } from '@/utils/booking';
|
||||
import Skeleton from '@/components/skeleton';
|
||||
import CountdownBox from '@/components/CountdownBox';
|
||||
@@ -200,8 +200,6 @@ export default function Mine() {
|
||||
const [pTopics, setPTopics] = useState((user && user.topics) || []);
|
||||
const [pSource, setPSource] = useState((user && user.source) || '');
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [scanBusy, setScanBusy] = useState(false);
|
||||
const [scanErr, setScanErr] = useState('');
|
||||
useEffect(() => {
|
||||
setPName((user && user.name) || '');
|
||||
setPStatus((user && user.status) || '');
|
||||
@@ -264,23 +262,6 @@ export default function Mine() {
|
||||
Taro.showToast({ title: '已退出登录', icon: 'none' });
|
||||
};
|
||||
|
||||
/* ============ 跨端口扫码登录:扫电脑/网页登录页二维码 → 小程序确认 ============ */
|
||||
const onScanLogin = async () => {
|
||||
setScanErr(''); setScanBusy(true);
|
||||
try {
|
||||
const res = await Taro.scanCode(); // 扫其它端口登录页的「小程序扫码」二维码
|
||||
const str = res.result || '';
|
||||
const m = str.match(/[?&]scene=([^&#]+)/); // 二维码内容=跨端口 login url,含 scene
|
||||
if (!m) throw new Error('无效的扫码登录二维码');
|
||||
const scene = decodeURIComponent(m[1]);
|
||||
const { code } = await Taro.login(); // 微信登录 code
|
||||
await mpQrConfirm(scene, code); // 确认 → 目标端口轮询取到登录令牌
|
||||
Taro.showToast({ title: '已登录目标端口,请回电脑/网页查看', icon: 'none' });
|
||||
} catch (e) {
|
||||
setScanErr((e && e.message) || '扫码登录失败');
|
||||
} finally { setScanBusy(false); }
|
||||
};
|
||||
|
||||
/* ============ 未登录:登录入口 ============ */
|
||||
if (!user || !isAuthed()) {
|
||||
return (
|
||||
@@ -354,12 +335,10 @@ export default function Mine() {
|
||||
<Button className="btn-ghost logout-btn" onClick={onLogout}>退出</Button>
|
||||
</View>
|
||||
|
||||
{/* 跨端口扫码登录:扫电脑/网页登录页的「小程序扫码」二维码 → 用本小程序确认登录该端口 */}
|
||||
{/* 跨端口扫码登录:由电脑/网页登录页展示「小程序码」,微信扫码自动进入小程序授权页确认 */}
|
||||
<View className="card next-card">
|
||||
<Text className="next-lbl">跨端口登录</Text>
|
||||
<Text className="bind-tip">在电脑/网页登录页点「小程序扫码」,用本小程序「扫一扫」即可登录该端口</Text>
|
||||
<Button className="btn-main" loading={scanBusy} onClick={onScanLogin}>扫码登录其它端口</Button>
|
||||
{scanErr && <Text className="scan-err">{scanErr}</Text>}
|
||||
<Text className="next-lbl">登录其它端</Text>
|
||||
<Text className="bind-tip">在电脑/网页登录页点「小程序扫码」,用微信扫一扫,进入小程序授权页确认即可登录</Text>
|
||||
</View>
|
||||
|
||||
{/* 下一场活动倒计时(个人信息卡之后显示;取最早的待参加且未开始的报名场次) */}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { View, Text, Button, Input } from '@tarojs/components';
|
||||
import Taro, { useDidShow } from '@tarojs/taro';
|
||||
import { useState } from 'react';
|
||||
import Taro from '@tarojs/taro';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { isAuthed, wxLogin, phoneLogin, sendCode, mpQrConfirm } from '@/utils/auth';
|
||||
import './index.scss';
|
||||
|
||||
@@ -20,13 +20,18 @@ export default function ScanLogin() {
|
||||
const [gateCode, setGateCode] = useState('');
|
||||
const [cd, setCd] = useState(0);
|
||||
|
||||
useDidShow(() => {
|
||||
const opts = Taro.getEnterOptionsSync();
|
||||
const q = (opts && opts.query) || {};
|
||||
const s = String(q.scene || opts.scene || '');
|
||||
setScene(s);
|
||||
setDone(false); setMsg('');
|
||||
});
|
||||
// 冷启动/扫码进入:纯 React useEffect 读当前实例参数(wxacode 的 scene 在 router.params.scene)。
|
||||
// 不再用 useLoad/useDidShow 等 Taro 元钩子(其内部在原生计时器里调度 React hook,会触发
|
||||
// "Invalid attempt to destruct non-iterable" → 页面黑屏)。
|
||||
useEffect(() => {
|
||||
try {
|
||||
const inst = Taro.getCurrentInstance();
|
||||
const router = (inst && inst.router) || {};
|
||||
const params = (router && (router.params || router.query)) || {};
|
||||
const s = String(params.scene || router.scene || '');
|
||||
if (s) setScene(s);
|
||||
} catch { /* 忽略取参异常 */ }
|
||||
}, []);
|
||||
|
||||
const wxLoginNow = async () => {
|
||||
setBusy(true); setMsg('');
|
||||
@@ -47,7 +52,8 @@ export default function ScanLogin() {
|
||||
const r = await sendCode(gatePhone);
|
||||
setMsg(`验证码已发送${r.debugCode ? `(演示 ${r.debugCode})` : ''}`);
|
||||
setCd(60);
|
||||
const t = window.setInterval(() => setCd((c) => (c <= 1 ? (window.clearInterval(t), 0) : c - 1)), 1000);
|
||||
// 小程序无 window,用全局 setInterval/clearInterval(源码里 window.* 会导致运行时 ReferenceError)
|
||||
const t = setInterval(() => setCd((c) => (c <= 1 ? (clearInterval(t), 0) : c - 1)), 1000);
|
||||
} catch (e) { setMsg((e && e.message) || '发送失败'); }
|
||||
finally { setBusy(false); }
|
||||
};
|
||||
@@ -106,7 +112,7 @@ export default function ScanLogin() {
|
||||
<View className="sl-icon">{done ? '✓' : '✅'}</View>
|
||||
<Text className="sl-title">{done ? '已完成' : '确认扫码操作'}</Text>
|
||||
<Text className="sl-desc">
|
||||
{done ? msg : `确认使用当前微信账号${scene.includes('bind') || true ? '' : ''}在你操作的端口${scene ? '' : ' '}完成登录 / 绑定?`}
|
||||
{done ? msg : `确认使用当前微信账号在你操作的端口完成登录 / 绑定?`}
|
||||
</Text>
|
||||
{!done && scene && <Text className="sl-scene">请求 #{scene.slice(0, 12)}</Text>}
|
||||
{!done && (
|
||||
|
||||
Reference in New Issue
Block a user