diff --git a/src/main/java/com/baobaot/exam/Controller/AdminController.java b/src/main/java/com/baobaot/exam/Controller/AdminController.java index bd8180d..9f678af 100644 --- a/src/main/java/com/baobaot/exam/Controller/AdminController.java +++ b/src/main/java/com/baobaot/exam/Controller/AdminController.java @@ -33,17 +33,19 @@ public class AdminController { return "admin"; } - // API: 获取题目列表(支持全部、按类型、按分值) + // API: 获取题目列表(支持全部、按类型、按分值、按标题模糊查询、联合查询) @GetMapping("/admin/api/questions") @ResponseBody public ResponseEntity> getQuestions( @RequestParam(required = false) Integer type, - @RequestParam(required = false) Integer score) { + @RequestParam(required = false) Integer score, + @RequestParam(required = false) String title) { Map result = new HashMap<>(); List questions; - if (type != null) { - questions = adminService.getQuestionsByType(type); + if (type != null || title != null) { + // 联合查询:按类型和/或标题 + questions = adminService.getQuestionsByTypeAndTitle(type, title); } else if (score != null) { questions = adminService.getQuestionsByScore(score); } else { diff --git a/src/main/java/com/baobaot/exam/Service/adminService.java b/src/main/java/com/baobaot/exam/Service/adminService.java index 03fa806..9f11345 100644 --- a/src/main/java/com/baobaot/exam/Service/adminService.java +++ b/src/main/java/com/baobaot/exam/Service/adminService.java @@ -23,6 +23,14 @@ public interface adminService extends IService { */ List getQuestionsByType(Integer type); + /** + * 根据类型和/或标题模糊查询题目(联合查询) + * @param type 题目类型,可为null + * @param title 标题关键词,可为null,支持模糊匹配 + * @return 符合条件的题目列表 + */ + List getQuestionsByTypeAndTitle(Integer type, String title); + /** * 根据分数查询所有题目 */ diff --git a/src/main/java/com/baobaot/exam/Service/impl/adminServiceImpl.java b/src/main/java/com/baobaot/exam/Service/impl/adminServiceImpl.java index 1e91159..d254c57 100644 --- a/src/main/java/com/baobaot/exam/Service/impl/adminServiceImpl.java +++ b/src/main/java/com/baobaot/exam/Service/impl/adminServiceImpl.java @@ -47,6 +47,20 @@ public class adminServiceImpl extends ServiceImpl impl return list(wrapper); } + @Override + public List getQuestionsByTypeAndTitle(Integer type, String title) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + + if (type != null) { + wrapper.eq(question::getType, type); + } + if (title != null && !title.trim().isEmpty()) { + wrapper.like(question::getTitle, title.trim()); + } + + return list(wrapper); + } + @Override public List getQuestionsByScore(Integer score) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 486ed1a..f58ac92 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -2,8 +2,8 @@ spring: application: name: exam datasource: -# url: jdbc:mysql://localhost:3306/exam - url: jdbc:mysql://192.168.1.56:3306/exam?useSSL=true&requireSSL=true&serverTimezone=UTC + url: jdbc:mysql://localhost:3306/exam +# url: jdbc:mysql://192.168.1.56:3306/exam?useSSL=true&requireSSL=true&serverTimezone=UTC username: root password: 521707 driver-class-name: com.mysql.cj.jdbc.Driver \ No newline at end of file diff --git a/src/main/resources/templates/admin.html b/src/main/resources/templates/admin.html index 5307ffb..777bc57 100644 --- a/src/main/resources/templates/admin.html +++ b/src/main/resources/templates/admin.html @@ -283,26 +283,26 @@
- - +
-
-
- - +
+ +
- +
-
+
创建试卷 查看试卷 @@ -316,6 +316,7 @@ 题目列表 + @@ -399,31 +400,49 @@ function loadAllQuestions() { document.getElementById('queryTypeTag').style.display = 'none'; document.getElementById('queryScoreTag').style.display = 'none'; + document.getElementById('queryTitleTag').style.display = 'none'; + document.getElementById('queryType').value = ''; + document.getElementById('queryTitle').value = ''; fetchQuestions('/admin/api/questions'); } - // 按类型查询 - function queryByType() { + // 联合查询:按类型和/或标题 + function queryQuestions() { const type = document.getElementById('queryType').value; - const typeTag = document.getElementById('queryTypeTag'); - typeTag.textContent = type === '1' ? '选择题' : '简答题'; - typeTag.style.display = 'inline'; - document.getElementById('queryScoreTag').style.display = 'none'; - fetchQuestions('/admin/api/questions?type=' + type); - } - - // 按分值查询 - function queryByScore() { - const score = document.getElementById('queryScore').value; - if (!score && score !== '0') { - showAlert('请输入分值', 'error'); + const title = document.getElementById('queryTitle').value.trim(); + + // 如果类型和标题都为空,查询全部 + if (!type && !title) { + loadAllQuestions(); return; } - const scoreTag = document.getElementById('queryScoreTag'); - scoreTag.textContent = score + '分'; - scoreTag.style.display = 'inline'; - document.getElementById('queryTypeTag').style.display = 'none'; - fetchQuestions('/admin/api/questions?score=' + score); + + const typeTag = document.getElementById('queryTypeTag'); + const titleTag = document.getElementById('queryTitleTag'); + + if (type) { + typeTag.textContent = type === '1' ? '选择题' : '简答题'; + typeTag.style.display = 'inline'; + } else { + typeTag.style.display = 'none'; + } + + if (title) { + titleTag.textContent = '关键词: ' + title; + titleTag.style.display = 'inline'; + } else { + titleTag.style.display = 'none'; + } + + document.getElementById('queryScoreTag').style.display = 'none'; + + let url = '/admin/api/questions?'; + const params = []; + if (type) params.push('type=' + encodeURIComponent(type)); + if (title) params.push('title=' + encodeURIComponent(title)); + url += params.join('&'); + + fetchQuestions(url); } // 获取题目列表 @@ -514,7 +533,7 @@ '-'; html += ` - + ${q.id} ${escapeHtml(q.title)} ${typeTag} @@ -524,7 +543,7 @@
- +
@@ -536,7 +555,7 @@ } // 删除题目 - function deleteQuestion(title) { + function deleteQuestion(id, title) { if (!confirm('确定要删除这道题吗?')) return; const formData = new FormData(); @@ -550,7 +569,13 @@ .then(data => { if (data.success) { showAlert('删除成功!', 'success'); - loadAllQuestions(); + // 局部删除:从DOM中移除该行,不刷新整个列表 + const row = document.getElementById('question-row-' + id); + if (row) { + row.remove(); + // 更新计数 + updateQuestionCount(); + } } else { showAlert(data.message || '删除失败', 'error'); } @@ -561,6 +586,15 @@ }); } + // 更新题目计数 + function updateQuestionCount() { + const countTag = document.getElementById('questionCount'); + if (countTag) { + const rows = document.querySelectorAll('#questionsContainer tbody tr'); + countTag.textContent = `共 ${rows.length} 题`; + } + } + // 转义HTML function escapeHtml(text) { if (!text) return ''; @@ -683,8 +717,9 @@ .then(data => { if (data.success) { showAlert('修改成功!', 'success'); + // 局部更新:只刷新修改的那一行(必须在 closeEditModal 之前调用) + updateQuestionRow(currentEditId, currentEditType, formData); closeEditModal(); - loadAllQuestions(); } else { showAlert(data.message || '修改失败', 'error'); } @@ -695,13 +730,58 @@ }); } - // 点击弹窗外部关闭 - window.onclick = function(event) { - const modal = document.getElementById('editModal'); - if (event.target == modal) { - closeEditModal(); + // 局部更新题目行 + function updateQuestionRow(id, type, formData) { + const row = document.getElementById('question-row-' + id); + if (!row) return; + + const title = formData.get('title'); + const score = formData.get('score'); + const rAnswer = formData.get('rAnswer'); + + const typeTag = type == 1 ? + '选择题' : + '简答题'; + + let optionsHtml = ''; + if (type == 1) { + const answerA = formData.get('answerA'); + const answerB = formData.get('answerB'); + const answerC = formData.get('answerC'); + const answerD = formData.get('answerD'); + const parts = []; + if (answerA) parts.push(`A: ${escapeHtml(answerA)}`); + if (answerB) parts.push(`B: ${escapeHtml(answerB)}`); + if (answerC) parts.push(`C: ${escapeHtml(answerC)}`); + if (answerD) parts.push(`D: ${escapeHtml(answerD)}`); + optionsHtml = parts.join('
'); + } else { + const answer = formData.get('answer'); + optionsHtml = answer ? escapeHtml(answer) : '无答案'; } + + const rAnswerHtml = rAnswer ? + `${escapeHtml(rAnswer)}` : + '-'; + + // 更新行内容 + row.innerHTML = ` + ${id} + ${escapeHtml(title)} + ${typeTag} + ${optionsHtml} + ${rAnswerHtml} + ${score} + +
+ + +
+ + `; } + +