Files
zkxw/mobile-h5/utils/auth.js
T

161 lines
4.0 KiB
JavaScript

import { validateCredentials } from './validate-credentials.js'
import { buildEncryptedLoginBody } from './login-rsa.js'
import { get, post } from './request.js'
import {
getToken,
getRefreshToken,
isLoggedIn,
getUser,
clearSession,
saveSession,
updateStoredUser,
forceRelogin,
setReturnUrl,
takeReturnUrl
} from './auth-session.js'
export { validateCredentials }
export {
getToken,
getRefreshToken,
isLoggedIn,
getUser,
clearSession,
updateStoredUser,
forceRelogin,
setReturnUrl,
takeReturnUrl
}
/**
* 拉取当前用户资料并写回本地(含职位、部门)。
* @returns {Promise<object|null>}
*/
export async function fetchCurrentUser() {
const token = getToken()
if (!token) return null
const data = await get('/web/auth/current-user', {
Authorization: 'Bearer ' + token
})
if (data) {
const prev = getUser() || {}
const merged = Object.assign({}, prev, data)
updateStoredUser(merged)
return merged
}
return null
}
/**
* 可选:清除历史 mock_ 前缀假会话,避免误判已登录。
*/
export function clearLegacyMockSessionIfNeeded() {
const token = getToken()
if (typeof token === 'string' && token.indexOf('mock_') === 0) {
clearSession()
}
}
/**
* 真实账号密码登录。
* @param {{ username: string, password: string }} params
*/
export async function passwordLogin({ username, password }) {
const v = validateCredentials(username, password)
if (!v.ok) {
const err = new Error(v.message)
err.code = v.code
throw err
}
const body = await buildEncryptedLoginBody(
(username || '').trim(),
password || ''
)
const data = await post('/web/auth/login', body)
if (!data || !data.token) {
throw new Error('登录失败')
}
saveSession({
token: data.token,
refreshToken: data.refreshToken,
userInfo: data.userInfo
})
// 密码登录成功后静默绑定微信(失败不影响登录)
bindWechatQuietly()
return data
}
/**
* 微信授权登录(openid 优先;未绑定需 phoneCode)。
*/
export async function wechatLogin({ loginCode, phoneCode }) {
const payload = { loginCode }
if (phoneCode) {
payload.phoneCode = phoneCode
}
const data = await post('/mini/auth/wechat-login', payload)
if (!data || !data.token) {
throw new Error('登录失败')
}
saveSession({
token: data.token,
refreshToken: data.refreshToken,
userInfo: data.userInfo
})
return data
}
/**
* 深链无 JWT 时静默换票(仅 loginCode,后端按已绑 openid 签发)。
*/
export async function silentWechatLogin() {
const loginRes = await new Promise((resolve, reject) => {
uni.login({ provider: 'weixin', success: resolve, fail: reject })
})
const loginCode = loginRes && loginRes.code
if (!loginCode) throw new Error('静默登录失败')
const data = await post('/mini/auth/wechat-login', { loginCode })
if (!data || !data.token) throw new Error('静默登录失败')
saveSession({
token: data.token,
refreshToken: data.refreshToken,
userInfo: data.userInfo
})
return data
}
/**
* 已登录态下用 wx.login code 绑定 openid;失败静默。
*/
export async function bindWechatQuietly() {
try {
const loginRes = await new Promise((resolve, reject) => {
uni.login({ provider: 'weixin', success: resolve, fail: reject })
})
const loginCode = loginRes && loginRes.code
if (!loginCode) return
const token = getToken()
if (!token) return
await post(
'/mini/auth/wechat-bind',
{ loginCode },
{ Authorization: 'Bearer ' + token }
)
} catch (e) {
console.warn('wechat bind skipped', e && e.message)
}
}
/**
* 查询当前用户是否已绑定服务号(用于微信审批通知)。
* @returns {Promise<{ bound: boolean }>}
*/
export async function fetchMpBindStatus() {
const token = getToken()
if (!token) return { bound: false }
const data = await get('/mini/auth/mp-bind-status', {
Authorization: 'Bearer ' + token
})
return { bound: !!(data && data.bound) }
}