支持普通链接二维码进入绑定页

This commit is contained in:
stu2not
2026-06-03 11:06:37 +08:00
parent 649a344f55
commit c4d977ce99

View File

@@ -26,6 +26,50 @@ const SESSION_STATUS_COMPLETED = 2
const SESSION_STATUS_EXPIRED = 3 const SESSION_STATUS_EXPIRED = 3
const SESSION_STATUS_FAILED = 4 const SESSION_STATUS_FAILED = 4
const SESSION_STATUS_CANCELLED = 5 const SESSION_STATUS_CANCELLED = 5
const BIND_PAGE_URL = '/pages/bind/index'
function safeDecodeURIComponent(value: string): string {
try {
return decodeURIComponent(value)
} catch (error) {
console.log('[bind] decode uri component failed:', error)
return value
}
}
function decodeQueryComponent(value: string): string {
return safeDecodeURIComponent(value.replace(/\+/g, ' '))
}
function decodeLaunchQrValue(value: string): string {
let decoded = String(value || '').trim()
for (let index = 0; index < 2; index += 1) {
const nextDecoded = safeDecodeURIComponent(decoded).trim()
if (nextDecoded === decoded) break
decoded = nextDecoded
}
return decoded
}
function getRouteParam(params: Record<string, unknown> | undefined, key: string): string {
const value = params?.[key]
if (Array.isArray(value)) return String(value[0] || '').trim()
return String(value || '').trim()
}
function buildPageUrl(pagePath: string, params: Record<string, unknown> | undefined): string {
const query = Object.entries(params || {})
.filter(([key, value]) => key && value !== undefined && value !== null && value !== '')
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join('&')
return query ? `${pagePath}?${query}` : pagePath
}
function getLaunchQrPayload(params: Record<string, unknown> | undefined): string {
const qParam = getRouteParam(params, 'q')
return qParam ? decodeLaunchQrValue(qParam) : ''
}
function normalizeExpiresAt(expiresAt: string): string { function normalizeExpiresAt(expiresAt: string): string {
let normalized = String(expiresAt || '').trim() let normalized = String(expiresAt || '').trim()
@@ -71,7 +115,7 @@ function parseBindingPayload(rawValue: string): { deviceId: string; serialNumber
const pairMap = queryPart.split('&').reduce<Record<string, string>>((result, item) => { const pairMap = queryPart.split('&').reduce<Record<string, string>>((result, item) => {
const [key, ...restValue] = item.split('=') const [key, ...restValue] = item.split('=')
if (!key) return result if (!key) return result
result[decodeURIComponent(key)] = decodeURIComponent(restValue.join('=') || '') result[decodeQueryComponent(key)] = decodeQueryComponent(restValue.join('=') || '')
return result return result
}, {}) }, {})
const deviceId = pairMap.device_id || pairMap.deviceId || '' const deviceId = pairMap.device_id || pairMap.deviceId || ''
@@ -128,6 +172,7 @@ export default function Bind() {
const [remainingBindSeconds, setRemainingBindSeconds] = useState(0) const [remainingBindSeconds, setRemainingBindSeconds] = useState(0)
const pollingRef = useRef<ReturnType<typeof setTimeout> | null>(null) const pollingRef = useRef<ReturnType<typeof setTimeout> | null>(null)
const countdownRef = useRef<ReturnType<typeof setInterval> | null>(null) const countdownRef = useRef<ReturnType<typeof setInterval> | null>(null)
const appliedLaunchQrRef = useRef('')
useDidShow(() => { useDidShow(() => {
void loadPageData() void loadPageData()
@@ -200,6 +245,27 @@ export default function Bind() {
setRemainingBindSeconds(0) setRemainingBindSeconds(0)
} }
const applyLaunchQrPayload = () => {
if (isAssignMode) return false
const launchPayload = getLaunchQrPayload(router.params)
if (!launchPayload || appliedLaunchQrRef.current === launchPayload) return false
appliedLaunchQrRef.current = launchPayload
const parsed = parseBindingPayload(launchPayload)
if (!parsed.deviceId && !parsed.serialNumber) return false
resetBindSessionState()
if (parsed.deviceId) setDeviceId(parsed.deviceId)
if (parsed.serialNumber) setSerialNumber(parsed.serialNumber)
setBindHint(
parsed.serialNumber
? '已读取设备二维码信息,请选择儿童后发送绑卡指令'
: '已读取设备号,请补充设备序列号'
)
return true
}
const resetExpiredBindSession = (showToast = true) => { const resetExpiredBindSession = (showToast = true) => {
stopPolling() stopPolling()
stopCountdown() stopCountdown()
@@ -300,6 +366,7 @@ export default function Bind() {
const loadPageData = async () => { const loadPageData = async () => {
if (!getToken()) { if (!getToken()) {
Taro.setStorageSync('postLoginRedirect', buildPageUrl(BIND_PAGE_URL, router.params))
Taro.reLaunch({ url: '/pages/login/index' }) Taro.reLaunch({ url: '/pages/login/index' })
return return
} }
@@ -317,6 +384,7 @@ export default function Bind() {
setDeviceId(activeBinding.device_id) setDeviceId(activeBinding.device_id)
} else { } else {
setPendingDeviceId(null) setPendingDeviceId(null)
applyLaunchQrPayload()
} }
} catch (error: any) { } catch (error: any) {
console.error('[bind] load failed:', error) console.error('[bind] load failed:', error)