Files
MBTI_wang/miniprogram/utils/questionBank.js
Ghost 6fec2965aa feat: SBTI 测评接入与管理端题目/财务/用户联动
1、修复了用户详情、定价与题目管理、财务与分销等管理端展示与接口问题。

2、新增 SBTI 小程序测评/结果页、sbtiData 引擎、题库 SQL 与脚本;admin sbtiDisplay。

3、优化 AppConfig/CrmReport/Test、历史与个人中心、test-select 与支付相关逻辑。

Made-with: Cursor
2026-04-11 16:16:32 +08:00

119 lines
3.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 仅从服务端拉取启用题库(/api/test/questions无本地题目保底。
* enterpriseId未传时与 test/submit 一致,见 enterpriseContext.getEnterpriseIdForApiPayload()
*/
const { requestPromise } = require('./request')
function getAppSafe() {
try {
return getApp()
} catch (e) {
return null
}
}
/**
* Fisher-Yates打乱题目顺序并随机每题选项顺序深拷贝
* @param {Array} questions
* @returns {Array}
*/
function shuffleQuestions(questions) {
const arr = (questions || []).map(q => ({
...q,
options: (q.options || []).slice().sort(() => Math.random() - 0.5)
}))
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[arr[i], arr[j]] = [arr[j], arr[i]]
}
return arr
}
/**
* @param {{ enterpriseId?: number|null }} opts
* @returns {number|null}
*/
function resolveEnterpriseIdForQuestionBank(opts) {
const o = opts || {}
if (Object.prototype.hasOwnProperty.call(o, 'enterpriseId')) {
const v = o.enterpriseId
if (v == null || v === '') {
return null
}
const n = Number(v)
return Number.isFinite(n) && n > 0 ? n : null
}
try {
const { getEnterpriseIdForApiPayload } = require('./enterpriseContext')
return getEnterpriseIdForApiPayload()
} catch (e) {
return null
}
}
function getTestQuestionDrawCount() {
const app = getAppSafe()
const n = app && app.globalData && app.globalData.testQuestionDrawCount
const num = parseInt(String(n == null || n === '' ? '0' : n), 10)
if (!Number.isFinite(num) || num <= 0) {
return 0
}
return Math.min(500, num)
}
function applyDrawCountAfterShuffle(questions) {
const n = getTestQuestionDrawCount()
if (!n || questions.length <= n) {
return questions
}
return questions.slice(0, n)
}
/**
* @param {'mbti'|'sbti'|'disc'|'pdp'} type
* @param {number|null|undefined} enterpriseId
* @returns {Promise<Array>}
*/
function fetchQuestionBank(type, enterpriseId) {
const q = [`type=${encodeURIComponent(type)}`]
if (enterpriseId != null && Number(enterpriseId) > 0) {
q.push(`enterpriseId=${Number(enterpriseId)}`)
}
return requestPromise({
url: `/api/test/questions?${q.join('&')}`,
method: 'GET',
needAuth: true
}).then((res) => {
const body = res.data || {}
if (body.code !== 200 || body.data == null) {
throw new Error(body.message || '拉取题库失败')
}
const list = body.data.list
if (!Array.isArray(list)) {
throw new Error('题库格式错误')
}
return list
})
}
/**
* @param {'mbti'|'sbti'|'disc'|'pdp'} type
* @param {{ enterpriseId?: number|null }} opts
* @returns {Promise<Array>} 乱序后的题目;接口无题或失败则 reject
*/
function loadQuestions(type, opts = {}) {
const enterpriseId = resolveEnterpriseIdForQuestionBank(opts)
return fetchQuestionBank(type, enterpriseId).then((list) => {
if (!list.length) {
throw new Error('暂无启用题目')
}
return applyDrawCountAfterShuffle(shuffleQuestions(list))
})
}
module.exports = {
fetchQuestionBank,
loadQuestions,
shuffleQuestions
}