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} */ 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 } /** * 网页扫码登录:标记会话已扫码(供 PC 端轮询展示「已扫码」)。 * @param {string} sessionId 完整 sessionId 或小程序码 scene(短码) */ export async function webQrScanned(sessionId) { return post('/mini/auth/web-qr-scanned', { sessionId }) } /** * 网页扫码登录:授权手机号并确认(不写本地会话,仅完成 PC 端登录)。 * @param {{ sessionId: string, loginCode: string, phoneCode: string }} params */ export async function webQrConfirm({ sessionId, loginCode, phoneCode }) { return post('/mini/auth/web-qr-confirm', { sessionId, loginCode, phoneCode }) } /** * 深链无 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) } }