const db = require('../../plugin/DataBase/db') const AccessControl = require('../AccessControl') const { BaseStdResponse } = require('../../BaseStdResponse') function isMissing(value) { return value === '' || value === null || value === undefined } function errorResponse(base, msg) { return { ...base, msg } } async function queryAccount(studentNum) { const rows = await db.query( `SELECT uid, token, school_id, student_num, userAgent, state, create_user FROM lepao_account WHERE student_num = ?`, [studentNum] ) return rows?.[0] || null } function validateRunnableAccount(account) { if (!account) { return errorResponse(BaseStdResponse.ERR, '未找到该乐跑账号') } if (account.state !== 1) { return errorResponse(BaseStdResponse.ERR, '仅状态为正常的账号可查看官方记录') } if (!account.uid || !account.token || !account.school_id) { return errorResponse(BaseStdResponse.ERR, '乐跑账号登录信息不完整,请使用登录器更新账号') } return null } async function loadUserOfficialAccount(uuid, studentNum) { const account = await queryAccount(studentNum) if (!account || account.create_user !== uuid) { return { error: errorResponse(BaseStdResponse.ERR, '未找到该乐跑账号或无权限操作') } } const invalid = validateRunnableAccount(account) if (invalid) return { error: invalid } return { account } } async function loadAdminOfficialAccount(uuid, studentNum) { const permission = await AccessControl.getPermission(uuid) if (!permission.includes('admin') && !permission.includes('service') && !permission.includes('server')) { return { error: BaseStdResponse.PERMISSION_DENIED } } const account = await queryAccount(studentNum) const invalid = validateRunnableAccount(account) if (invalid) return { error: invalid } return { account } } function isLoginExpiredError(error) { const msg = error?.message || '' return ( error?.code === 'LEPAO_LOGIN_EXPIRED' || String(msg).includes('重新登录') || String(msg).includes('登录已过期') || String(msg).includes('登录失效') ) } async function markAccountLoginExpired(studentNum, logger) { if (!studentNum) return try { await db.query('UPDATE lepao_account SET state = 0, update_time = ? WHERE student_num = ?', [ Date.now(), studentNum ]) logger?.warn?.(`${studentNum} 官方乐跑登录已失效,账号状态已更新为未登录`) } catch (updateError) { logger?.error?.(`更新乐跑账号登录状态失败 ${studentNum}: ${updateError.stack || updateError}`) } } async function mapOfficialError(error, studentNum, logger) { if (isLoginExpiredError(error)) { await markAccountLoginExpired(studentNum, logger) return errorResponse(BaseStdResponse.ERR, '乐跑登录已过期,请使用登录器更新账号') } const msg = error?.message || '获取官方乐跑记录失败' return errorResponse(BaseStdResponse.ERR, msg) } /** 官方学期记录接口返回的 total_score_num 同步到 lepao_account.total_num */ async function syncOfficialTotalNum(studentNum, officialData, logger) { if (!studentNum || !officialData) return const totalScoreNum = Number(officialData.total_score_num) if (!Number.isFinite(totalScoreNum)) return try { const rows = await db.query( 'UPDATE lepao_account SET total_num = ? WHERE student_num = ?', [totalScoreNum, studentNum] ) } catch (error) { logger?.error?.(`同步官方 total_num 失败 ${studentNum}: ${error.stack || error}`) } } module.exports = { isMissing, loadUserOfficialAccount, loadAdminOfficialAccount, isLoginExpiredError, markAccountLoginExpired, mapOfficialError, syncOfficialTotalNum }