/** * 申论题批复解析(与管理端 UserProgressList 约定一致) * review_comment 格式:【第1题】\n评语\n\n【第2题】\n评语\n\n__IMG_COUNTS__:n1,n2,... * review_images 为一维数组,按 __IMG_COUNTS__ 数量依次对应各题 */ const IMG_COUNTS_MARKER = '__IMG_COUNTS__:' /** * 从 progress.review_comment + review_images 解析出各题评语与各题图片数量 * @param {Object} progress - 进度对象,含 review_comment(或 review_comment) * @returns {{ comments: string[], imageCounts: number[] }} */ function parseEssayReview(progress) { var comments = [] var imageCounts = [] var rawComment = (progress && (progress.review_comment || progress.reviewComment)) || '' var text = String(rawComment).trim() if (!text) return { comments: comments, imageCounts: imageCounts } var idx = text.indexOf(IMG_COUNTS_MARKER) if (idx >= 0) { var rest = text.slice(idx + IMG_COUNTS_MARKER.length).trim() var parts = rest.split(',').map(function (s) { return parseInt(s, 10) }) parts.forEach(function (n) { if (!Number.isNaN(n)) imageCounts.push(n) }) text = text.slice(0, idx).trim() } var regex = /【第(\d+)题】\s*\n?/g var starts = [] var match while ((match = regex.exec(text)) !== null) { starts.push({ num: parseInt(match[1], 10), index: match.index }) } for (var i = 0; i < starts.length; i++) { var startIdx = starts[i].index var endIdx = starts[i + 1] ? starts[i + 1].index : text.length var block = text.slice(startIdx, endIdx).replace(/^【第\d+题】\s*\n?/, '').trim() comments[i] = block } return { comments: comments, imageCounts: imageCounts } } /** * 将一维批复图片按各题数量拆成二维数组 * @param {string[]} flat - 一维图片 URL 数组 * @param {number[]} counts - 各题图片数量 [n1, n2, ...] * @returns {string[][]} */ function splitReviewImagesByCounts(flat, counts) { var result = [] var offset = 0 for (var i = 0; i < counts.length; i++) { var n = counts[i] var chunk = (flat || []).slice(offset, offset + n).filter(function (u) { return u && String(u).trim() !== '' }) result.push(chunk) offset += n } return result } module.exports = { IMG_COUNTS_MARKER: IMG_COUNTS_MARKER, parseEssayReview: parseEssayReview, splitReviewImagesByCounts: splitReviewImagesByCounts }