添加错题删除功能和优化错题列表

**新增功能**:
- 新增删除单个错题的接口 (DELETE /api/wrong-questions/:id)
- 错题列表每个项添加删除按钮
- 支持单独删除不想要的错题记录

**技术实现**:
- 后端: 实现DeleteWrongQuestion处理器,确保用户只能删除自己的错题
- 前端: 添加deleteWrongQuestion API 调用
- UI: 在List.Item中添加actions属性,显示删除按钮
- 删除时显示二次确认弹窗

**注意事项**:
- 删除需要确认,防止误操作
- 删除成功后自动刷新列表
- 仅显示操作用户自己的错题

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
yanlongqi 2025-11-04 15:42:59 +08:00
parent 2bcf6bdacc
commit 6082ca0bf3
4 changed files with 80 additions and 1 deletions

View File

@ -263,3 +263,41 @@ func GetRandomWrongQuestion(c *gin.Context) {
"data": dto,
})
}
// DeleteWrongQuestion 删除单个错题
func DeleteWrongQuestion(c *gin.Context) {
userID, exists := c.Get("user_id")
if !exists {
c.JSON(http.StatusUnauthorized, gin.H{
"success": false,
"message": "未登录",
})
return
}
wrongQuestionID := c.Param("id")
db := database.GetDB()
// 删除错题(确保只能删除自己的错题)
result := db.Where("id = ? AND user_id = ?", wrongQuestionID, userID).Delete(&models.WrongQuestion{})
if result.Error != nil {
c.JSON(http.StatusInternalServerError, gin.H{
"success": false,
"message": "删除失败",
})
return
}
if result.RowsAffected == 0 {
c.JSON(http.StatusNotFound, gin.H{
"success": false,
"message": "错题不存在",
})
return
}
c.JSON(http.StatusOK, gin.H{
"success": true,
"message": "已删除",
})
}

View File

@ -54,6 +54,7 @@ func main() {
auth.GET("/wrong-questions", handlers.GetWrongQuestions) // 获取错题列表
auth.GET("/wrong-questions/stats", handlers.GetWrongQuestionStats) // 获取错题统计
auth.GET("/wrong-questions/random", handlers.GetRandomWrongQuestion) // 获取随机错题
auth.DELETE("/wrong-questions/:id", handlers.DeleteWrongQuestion) // 删除单个错题
auth.PUT("/wrong-questions/:id/mastered", handlers.MarkWrongQuestionMastered) // 标记已掌握
auth.DELETE("/wrong-questions", handlers.ClearWrongQuestions) // 清空错题本
}

View File

@ -57,6 +57,11 @@ export const markWrongQuestionMastered = (id: number) => {
return request.put<ApiResponse<null>>(`/wrong-questions/${id}/mastered`)
}
// 删除单个错题
export const deleteWrongQuestion = (id: number) => {
return request.delete<ApiResponse<null>>(`/wrong-questions/${id}`)
}
// 清空错题本
export const clearWrongQuestions = () => {
return request.delete<ApiResponse<null>>('/wrong-questions')

View File

@ -67,6 +67,27 @@ const WrongQuestions: React.FC = () => {
})
}
// 删除单个错题
const handleDelete = (id: number) => {
Modal.confirm({
title: '确定要删除这道错题吗?',
content: '删除后将无法恢复',
okText: '确定',
cancelText: '取消',
onOk: async () => {
try {
const res = await questionApi.deleteWrongQuestion(id)
if (res.success) {
message.success('已删除')
loadWrongQuestions()
}
} catch (error) {
message.error('删除失败')
}
},
})
}
// 开始错题练习
const handlePractice = () => {
// 跳转到答题页面,错题练习模式
@ -170,7 +191,21 @@ const WrongQuestions: React.FC = () => {
loading={loading}
dataSource={wrongQuestions}
renderItem={(item) => (
<List.Item key={item.id} className={styles.listItem}>
<List.Item
key={item.id}
className={styles.listItem}
actions={[
<Button
key="delete"
type="text"
danger
icon={<DeleteOutlined />}
onClick={() => handleDelete(item.id)}
>
</Button>
]}
>
<List.Item.Meta
title={
<Space>