Sfoglia il codice sorgente

动态匹配表头

罗永浩 5 mesi fa
parent
commit
66d5cf4511
1 ha cambiato i file con 47 aggiunte e 12 eliminazioni
  1. 47 12
      addons/admin/src/views/exam/component/ExcelImport.vue

+ 47 - 12
addons/admin/src/views/exam/component/ExcelImport.vue

@@ -64,11 +64,13 @@
             <el-alert title="Excel格式要求" type="info" :closable="false" show-icon>
                 <template slot="default">
                     <p><strong>Excel格式要求:</strong></p>
-                    <p>• 第一行必须是标题行:题目类型、题目、选项A、选项B、选项C、选项D、选项E、选项F、正确答案、解析、分数</p>
+                    <p>• 第一行必须是标题行,支持以下列名:题目类型、题目、选项A~F(或答案A~F)、正确答案、解析、分数</p>
+                    <p>• 列顺序可以任意排列,系统会自动识别各列</p>
                     <p>• 题目类型:单选题、多选题、判断题、填空题、问答题</p>
                     <p>• 正确答案:单选题填选项字母(A/B/C/D/E/F),多选题用逗号分隔(A,B),判断题填对/错,填空题填答案,问答题可留空</p>
                     <p>• 分数:每道题的分值,建议单选题2-5分,多选题5-10分,判断题1-2分,填空题3-8分,问答题10-20分</p>
                     <p>• 支持富文本格式</p>
+                    <p><strong>示例标题行:</strong>题目类型、题目、解析、正确答案、答案A、答案B、答案C、答案D、分数、答案E、答案F</p>
                 </template>
             </el-alert>
         </div>
@@ -267,20 +269,53 @@ export default {
 
                 if (allData.length < 2) return this.$message.error("Excel 数据行数不足");
 
+                // 读取第一行作为标题,动态匹配列索引
+                const headers = allData[0];
+                const getColumnIndex = (searchKeywords) => {
+                    const index = headers.findIndex(header =>
+                        searchKeywords.some(keyword =>
+                            String(header).trim().includes(keyword)
+                        )
+                    );
+                    return index >= 0 ? index : -1;
+                };
+
+                // 动态获取列索引
+                const colIndices = {
+                    topic_type: getColumnIndex(['题目类型', '题型']),
+                    topic_name: getColumnIndex(['题目', '题目内容']),
+                    answer_A: getColumnIndex(['选项A', '答案A', '选项 A', '答案 A']),
+                    answer_B: getColumnIndex(['选项B', '答案B', '选项 B', '答案 B']),
+                    answer_C: getColumnIndex(['选项C', '答案C', '选项 C', '答案 C']),
+                    answer_D: getColumnIndex(['选项D', '答案D', '选项 D', '答案 D']),
+                    answer_E: getColumnIndex(['选项E', '答案E', '选项 E', '答案 E']),
+                    answer_F: getColumnIndex(['选项F', '答案F', '选项 F', '答案 F']),
+                    correct_answer: getColumnIndex(['正确答案', '标准答案', '答案']),
+                    topic_analysis: getColumnIndex(['解析', '题目解析', '答案解析']),
+                    score: getColumnIndex(['分数', '分值', '得分'])
+                };
+
+                // 验证必要的列是否存在
+                const requiredColumns = ['topic_type', 'topic_name', 'correct_answer'];
+                const missingColumns = requiredColumns.filter(key => colIndices[key] === -1);
+                if (missingColumns.length > 0) {
+                    return this.$message.error(`缺少必要的列:${missingColumns.join('、')}`);
+                }
+
                 const rows = allData.slice(1).filter(r => r.some(c => c !== ""));
                 this.previewData = rows.map((r, index) => ({
                     _id: index,
-                    topic_type: r[0] || "",
-                    topic_name: r[1] || "",
-                    answer_A: r[2] || "",
-                    answer_B: r[3] || "",
-                    answer_C: r[4] || "",
-                    answer_D: r[5] || "",
-                    answer_E: r[6] || "",
-                    answer_F: r[7] || "",
-                    correct_answer: r[8] || "",
-                    topic_analysis: r[9] || "",
-                    score: Number(r[10]) || 0,
+                    topic_type: colIndices.topic_type >= 0 ? (r[colIndices.topic_type] || "") : "",
+                    topic_name: colIndices.topic_name >= 0 ? (r[colIndices.topic_name] || "") : "",
+                    answer_A: colIndices.answer_A >= 0 ? (r[colIndices.answer_A] || "") : "",
+                    answer_B: colIndices.answer_B >= 0 ? (r[colIndices.answer_B] || "") : "",
+                    answer_C: colIndices.answer_C >= 0 ? (r[colIndices.answer_C] || "") : "",
+                    answer_D: colIndices.answer_D >= 0 ? (r[colIndices.answer_D] || "") : "",
+                    answer_E: colIndices.answer_E >= 0 ? (r[colIndices.answer_E] || "") : "",
+                    answer_F: colIndices.answer_F >= 0 ? (r[colIndices.answer_F] || "") : "",
+                    correct_answer: colIndices.correct_answer >= 0 ? (r[colIndices.correct_answer] || "") : "",
+                    topic_analysis: colIndices.topic_analysis >= 0 ? (r[colIndices.topic_analysis] || "") : "",
+                    score: colIndices.score >= 0 ? (Number(r[colIndices.score]) || 0) : 0,
                     show_type: 1, // 导入的数据固定为文本类型
                     answer_type: 2, // 导入的数据固定为不可提交图片答案
                     topic_image_id: "", // 默认空值