problem.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import json
  4. from typing import Union
  5. from fastapi import APIRouter, Depends, Query, Path
  6. from sqlalchemy import select, func, case, or_, and_, distinct, asc
  7. from sqlalchemy.ext.asyncio import AsyncSession
  8. from starlette.background import BackgroundTasks
  9. from bgtask.tasks import (bgtask_create_student_push_record, bgtask_clone_student_push_record,
  10. bgtask_delete_student_push_record)
  11. from crud.marktask import crud_student_answer, crud_task
  12. from crud.paper import crud_question
  13. from crud.problem import (crud_class_push_record, crud_class_error_statistic,
  14. crud_student_push_record, crud_student_error_statistic)
  15. from crud.school import crud_class
  16. from crud.user import crud_student
  17. from models.marktask import MarkTask, StudentAnswer
  18. from models.paper import PaperQuestion
  19. from models.problem import ClassErrorQuestion, StudentErrorQuestion
  20. from models.user import Student, Teacher
  21. from schemas.base import DetailMixin
  22. from schemas.paper import UpdateMarkTaskInfo
  23. from schemas.problem import (ClassErrorQuestionList, StudentErrorQuestionList,
  24. StudentErrorQuestionDetailList, ClassErrorPushStudentList,
  25. StudentTaskErrorQuestionList, StudentTaskErrorDetail,
  26. ClassErrorRatioInfo)
  27. from schemas.problem import (CreateClassErrorPushRecordInfo, ClassErrorPushRecordInDB,
  28. StudentErrorBookQuestionList, UpdateClassErrorPushRecordInfo,
  29. ClassErrorPushRecordList, ClassErrorPushRecordDetail)
  30. from utils.depends import get_current_user, get_async_db
  31. router = APIRouter(tags=["错题中心-教师学生端"])
  32. @router.get("/cls-errs",
  33. response_model=ClassErrorQuestionList,
  34. response_model_exclude_none=True,
  35. summary="班级错题列表")
  36. async def get_class_errors(page: int = 1,
  37. size: int = 10,
  38. school_id: int = Query(0, alias="sid", description="学校ID"),
  39. grade_id: int = Query(0, alias="gid", description="年级ID"),
  40. class_id: str = Query("", alias="cid", description="班级ID"),
  41. task_id: int = Query(0, alias="tid", description="阅卷任务ID"),
  42. kw: str = Query("", description="题目关键字"),
  43. ratio: int = Query(0, description="错题率"),
  44. db: AsyncSession = Depends(get_async_db),
  45. current_user: Teacher = Depends(get_current_user)):
  46. # 查询条件
  47. _q = []
  48. if school_id: # 学校ID
  49. _q.append(ClassErrorQuestion.school_id == school_id)
  50. if grade_id: # 年级ID
  51. _q.append(ClassErrorQuestion.grade_id == grade_id)
  52. if class_id and (class_id != "0"): # 班级ID
  53. _q.append(ClassErrorQuestion.class_id == int(class_id))
  54. else:
  55. _q.append(
  56. ClassErrorQuestion.class_id.in_([int(x) for x in current_user.class_id.split(",")]))
  57. if task_id: # 试卷ID
  58. _q.append(ClassErrorQuestion.task_id == task_id)
  59. if ratio > 0:
  60. _q.append(ClassErrorQuestion.error_ratio >= min(ratio, 100))
  61. else:
  62. _q.append(ClassErrorQuestion.error_ratio > max(ratio, 0))
  63. if kw: # 题目关键字
  64. _q.append(ClassErrorQuestion.task_name.like(f"%{kw}%"))
  65. # 查询总数
  66. count_stmt = select(func.count()).select_from(ClassErrorQuestion).join(
  67. PaperQuestion, ClassErrorQuestion.qid == PaperQuestion.id)
  68. # 从学生答案表中查出所有的错题
  69. error_fields = [
  70. "student_count", "error_count", "error_ratio", "task_type", "task_name", "qid",
  71. "answer_dist"
  72. ]
  73. question_fields = ["stem", "answer", "analysis"]
  74. data_stmt = select(
  75. *[getattr(ClassErrorQuestion, x) for x in error_fields],
  76. *[getattr(PaperQuestion, x) for x in question_fields],
  77. ).select_from(ClassErrorQuestion).join(PaperQuestion,
  78. ClassErrorQuestion.qid == PaperQuestion.id)
  79. if _q:
  80. count_stmt = count_stmt.where(*_q)
  81. data_stmt = data_stmt.where(*_q)
  82. # 总数
  83. count = await crud_student_answer.execute_v2(db, count_stmt)
  84. total = count[0][0]
  85. # 错题列表
  86. data = []
  87. offset = (page - 1) * size
  88. data_stmt = data_stmt.limit(size).offset(offset).order_by(asc(ClassErrorQuestion.qid))
  89. db_questions = await crud_student_answer.execute_v2(db, data_stmt)
  90. for q in db_questions:
  91. temp = {
  92. "student_count": q[0],
  93. "error_count": q[1],
  94. "right_count": q[0] - q[1],
  95. "error_ratio": q[2],
  96. "task_type": q[3],
  97. "task_name": q[4],
  98. "qid": q[5],
  99. "stem": q[7],
  100. "answer": q[8],
  101. "analysis": q[9]
  102. }
  103. try:
  104. _dist = [{"key": k, "val": v} for k, v in json.loads(q[6]).items()]
  105. _dist.sort(key=lambda x: x["key"])
  106. except json.decoder.JSONDecodeError:
  107. _dist = []
  108. temp["dist"] = _dist
  109. data.append(temp)
  110. return {"data": data, "total": total}
  111. @router.get("/stu-errs",
  112. response_model=StudentErrorQuestionList,
  113. response_model_exclude_none=True,
  114. summary="学生错题列表-综合")
  115. async def get_student_errors(page: int = 1,
  116. size: int = 10,
  117. school_id: int = Query(0, alias="sid", description="学校ID"),
  118. grade_id: int = Query(0, alias="gid", description="年级ID"),
  119. class_id: int = Query(0, alias="cid", description="班级ID"),
  120. kw: str = Query("", description="关键词"),
  121. db: AsyncSession = Depends(get_async_db),
  122. current_user: Teacher = Depends(get_current_user)):
  123. _q = [StudentErrorQuestion.error_ratio > 0]
  124. if class_id: # 班级ID
  125. _q.append(StudentErrorQuestion.class_id == class_id)
  126. if school_id:
  127. _q.append(StudentErrorQuestion.school_id == school_id)
  128. if grade_id:
  129. _q.append(StudentErrorQuestion.grade_id == grade_id)
  130. else: # 通过school_id和grade_id查询class_id
  131. _sq = {}
  132. if school_id:
  133. _sq["school_id"] = school_id
  134. if grade_id:
  135. _sq["grade_id"] = grade_id
  136. if _sq:
  137. total, db_classes = await crud_class.find_all(db, filters=_sq, return_fields=["id"])
  138. if not total:
  139. return {"errcode": 400, "mess": "班级不存在!"}
  140. _q.append(StudentErrorQuestion.class_id.in_([x.id for x in db_classes]))
  141. if kw: # 关键词
  142. _q.append(
  143. or_(StudentErrorQuestion.student_sno == kw, StudentErrorQuestion.student_name == kw))
  144. # 返回结果
  145. offset = (page - 1) * size
  146. stmt = select(func.count(distinct(StudentErrorQuestion.student_id)))\
  147. .select_from(StudentErrorQuestion).where(*_q)
  148. total = (await crud_student_error_statistic.execute_v2(db, stmt))[0][0]
  149. stmt = select(StudentErrorQuestion.student_id, StudentErrorQuestion.student_sno,
  150. StudentErrorQuestion.student_name,
  151. func.sum(StudentErrorQuestion.total_questions).label("total_questions"),
  152. func.sum(StudentErrorQuestion.total_errors).label("total_errors"),
  153. func.sum(StudentErrorQuestion.work_error_count).label("work_error_count"),
  154. func.sum(StudentErrorQuestion.exam_error_count).label("exam_error_count"),
  155. func.avg(StudentErrorQuestion.error_ratio).label("error_ratio"))\
  156. .select_from(StudentErrorQuestion)\
  157. .where(*_q)\
  158. .group_by(StudentErrorQuestion.student_id,
  159. StudentErrorQuestion.student_sno,
  160. StudentErrorQuestion.student_name)\
  161. .offset(offset)\
  162. .limit(size)
  163. # 查询数据
  164. db_errors = await crud_student_error_statistic.execute_v2(db, stmt)
  165. return {"data": db_errors, "total": total}
  166. @router.get("/stu-errs/{sid}/tasks",
  167. response_model=StudentTaskErrorQuestionList,
  168. response_model_exclude_none=True,
  169. summary="学生错题-任务错题统计")
  170. async def get_student_task_errors(page: int = 1,
  171. size: int = 10,
  172. student_id: int = Path(..., alias="sid", description="学生ID"),
  173. task_id: int = Query(0, alias="tid", description="任务ID"),
  174. db: AsyncSession = Depends(get_async_db),
  175. current_user: Teacher = Depends(get_current_user)):
  176. # 查询条件
  177. _q = [StudentErrorQuestion.student_id == student_id, StudentErrorQuestion.error_ratio > 0]
  178. if task_id:
  179. _q.append(StudentErrorQuestion.task_id == task_id)
  180. # 查询错题统计数据
  181. offset = (page - 1) * size
  182. stmt = select(func.count(distinct(StudentErrorQuestion.task_id))) \
  183. .select_from(StudentErrorQuestion).where(*_q)
  184. total = (await crud_student_error_statistic.execute_v2(db, stmt))[0][0]
  185. stmt = select(
  186. StudentErrorQuestion.student_task_id, MarkTask.name, MarkTask.mtype,
  187. StudentErrorQuestion.total_questions, StudentErrorQuestion.work_error_count,
  188. StudentErrorQuestion.exam_error_count, StudentErrorQuestion.error_ratio, MarkTask.id)\
  189. .select_from(StudentErrorQuestion).join(MarkTask, StudentErrorQuestion.task_id == MarkTask.id)\
  190. .where(*_q).offset(offset).limit(size)
  191. # 查询数据
  192. data = []
  193. db_objs = await crud_student_error_statistic.execute_v2(db, stmt)
  194. for item in db_objs:
  195. temp = {
  196. "student_task_id": item[0],
  197. "task_name": item[1],
  198. "task_type": item[2],
  199. "total_count": item[3],
  200. "error_count": item[4] if item[2] == "work" else item[5],
  201. "error_ratio": item[6],
  202. "task_id": item[7]
  203. }
  204. data.append(temp)
  205. return {"data": data, "total": total}
  206. @router.get("/stu-errs/{sid}/tasks/{tid}/error-info",
  207. response_model=StudentTaskErrorDetail,
  208. response_model_exclude_none=True,
  209. summary="学生阅卷任务错题信息(学生错题顶部使用)")
  210. async def get_task_error_info(student_id: int = Path(..., alias="sid", description="学生ID"),
  211. student_task_id: int = Path(..., alias="tid", description="学生阅卷任务ID"),
  212. db: AsyncSession = Depends(get_async_db),
  213. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  214. db_obj = await crud_student_error_statistic.find_one(db,
  215. filters={
  216. "student_id": student_id,
  217. "student_task_id": student_task_id
  218. })
  219. db_task = await crud_task.find_one(db, filters={"id": db_obj.task_id})
  220. data = {
  221. "student_sno": db_obj.student_sno,
  222. "student_name": db_obj.student_name,
  223. "total_questions": db_obj.total_questions,
  224. "total_errors": db_obj.total_errors,
  225. "error_ratio": db_obj.error_ratio,
  226. "task_id": db_obj.task_id,
  227. "task_name": db_task.name
  228. }
  229. if not db_obj:
  230. return {"errcode": 404, "mess": "阅卷任务不存在!"}
  231. return {"data": data}
  232. @router.get("/stu-errs/{sid}/tasks/{tid}/questions",
  233. response_model=StudentErrorQuestionDetailList,
  234. response_model_exclude_none=True,
  235. summary="学生错题-错误试题列表")
  236. async def get_personal_errors(page: int = 1,
  237. size: int = 10,
  238. student_id: int = Path(..., alias="sid", description="学生ID"),
  239. student_task_id: int = Path(..., alias="tid", description="学生阅卷任务ID"),
  240. db: AsyncSession = Depends(get_async_db),
  241. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  242. # 返回结果
  243. data = []
  244. _q = {"incorrect": 1, "student_id": student_id, "student_task_id": student_task_id}
  245. question_ids = []
  246. question_dict = {}
  247. counter = 0
  248. offset = (page - 1) * size
  249. total, db_errors = await crud_student_answer.find_all(
  250. db,
  251. filters=_q,
  252. return_fields=["pid", "qid", "task_id", "task_name", "mtype", "qimg", "marked_img"],
  253. limit=size,
  254. offset=offset,
  255. order_by=[asc(StudentAnswer.qid)])
  256. for x in db_errors:
  257. question_dict[x.qid] = counter
  258. question_ids.append(x.qid)
  259. temp = {
  260. "pid": x.pid,
  261. "qid": x.qid,
  262. "marked_img": x.marked_img or x.qimg,
  263. "task_id": x.task_id,
  264. "task_name": x.task_name,
  265. "task_type": x.mtype.value
  266. }
  267. data.append(temp)
  268. counter += 1
  269. # 查询试题信息
  270. if data:
  271. _q = [PaperQuestion.pid == data[0]['pid']]
  272. if len(question_ids) == 1:
  273. _q.append(PaperQuestion.id == question_ids[0])
  274. else:
  275. _q.append(PaperQuestion.id.in_(question_ids))
  276. _, db_questions = await crud_question.find_all(
  277. db, filters=_q, return_fields=["id", "answer", "analysis", "level", "lpoints"])
  278. for x in db_questions:
  279. data[question_dict[x.id]].update({
  280. "answer": x.answer,
  281. "analysis": x.analysis,
  282. "level": x.level,
  283. "lpoints": x.lpoints
  284. })
  285. return {"data": data, "total": total}
  286. @router.get("/stu-errs/{sprid}/errbook",
  287. response_model=StudentErrorBookQuestionList,
  288. response_model_exclude_none=True,
  289. summary="学生错题本")
  290. async def get_student_error_book(page: int = 1,
  291. size: int = 10,
  292. sprid: int = Path(..., description="学生错题推送记录ID"),
  293. db: AsyncSession = Depends(get_async_db),
  294. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  295. # 分页
  296. offset = (page - 1) * size
  297. # 学生错题推送记录
  298. db_error = await crud_student_push_record.find_one(db, filters={"id": sprid})
  299. # 根据学生错题推送记录中的试题ID去获取相应的试题
  300. _q = []
  301. if len(db_error.push_error_ids) == 1:
  302. _q.append(PaperQuestion.id == db_error.push_error_ids[0])
  303. else:
  304. _q.append(PaperQuestion.id.in_(db_error.push_error_ids))
  305. total, db_questions = await crud_question.find_all(db, filters=_q, limit=size, offset=offset)
  306. return {"data": db_questions, "total": total}
  307. @router.get("/stu-errs/{qid}/rel-questions",
  308. response_model=StudentErrorBookQuestionList,
  309. response_model_exclude_none=True,
  310. summary="举一反三试题列表")
  311. async def get_related_questions(qid: int = Path(..., description="试题ID"),
  312. db: AsyncSession = Depends(get_async_db),
  313. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  314. # 举一反三,使用知识点查询+难度查询
  315. db_question = await crud_question.find_one(db, filters={"id": qid})
  316. _q = [
  317. PaperQuestion.id != qid, PaperQuestion.level == db_question.level,
  318. PaperQuestion.lpoints == db_question.lpoints
  319. ]
  320. total, db_questions = await crud_question.find_all(db, filters=_q, limit=3)
  321. return {"data": db_questions, "total": total}
  322. @router.get("/cls-push-errs",
  323. response_model=ClassErrorPushRecordList,
  324. response_model_exclude_none=True,
  325. summary="错题推送记录列表")
  326. async def get_cls_push_records(page: int = 1,
  327. size: int = 10,
  328. school_id: int = Query(0, alias="sid", description="学校ID"),
  329. grade_id: int = Query(0, alias="gid", description="年级ID"),
  330. class_id: int = Query(0, alias="cid", description="班级ID"),
  331. task_id: int = Query(0, alias="tid", description="阅卷任务ID"),
  332. db: AsyncSession = Depends(get_async_db),
  333. current_user: Teacher = Depends(get_current_user)):
  334. _q = {}
  335. if school_id:
  336. _q["school_id"] = school_id
  337. if grade_id:
  338. _q["grade_id"] = grade_id
  339. if class_id:
  340. _q["class_id"] = class_id
  341. if task_id:
  342. _q["task_id"] = task_id
  343. # 查询并返回
  344. total, db_records = await crud_class_push_record.find_all(db,
  345. filters=_q,
  346. limit=size,
  347. offset=(page - 1) * size)
  348. return {"data": db_records, "total": total}
  349. @router.get("/cls-push-errs/{prid}",
  350. response_model=ClassErrorPushStudentList,
  351. response_model_exclude_none=True,
  352. summary="班级错题推送详情")
  353. async def get_cls_error_push_record(page: int = 1,
  354. size: int = 10,
  355. prid: int = Path(..., description="班级错题推送记录ID"),
  356. db: AsyncSession = Depends(get_async_db),
  357. current_user: Teacher = Depends(get_current_user)):
  358. # 判断推送记录是否存在
  359. db_prd = await crud_class_push_record.find_one(db, filters={"id": prid})
  360. if not db_prd:
  361. return {"errcode": 400, "mess": "推送记录不存在!"}
  362. # 查询学生推送记录
  363. return_fields = [
  364. "id", "student_id", "student_sno", "student_name", "push_error_count", "printed",
  365. "created_at"
  366. ]
  367. total, db_student_push_records = await crud_student_push_record.find_all(
  368. db,
  369. filters={"push_record_id": {db_prd.id}},
  370. return_fields=return_fields,
  371. limit=size,
  372. offset=(page - 1) * size)
  373. return {"data": db_student_push_records, "total": total}
  374. @router.post("/cls-push-errs",
  375. response_model=ClassErrorPushRecordDetail,
  376. response_model_exclude_none=True,
  377. summary="创建错题推送")
  378. async def create_error_push_record(info: CreateClassErrorPushRecordInfo,
  379. bgtask: BackgroundTasks,
  380. db: AsyncSession = Depends(get_async_db),
  381. current_user: Teacher = Depends(get_current_user)):
  382. # 判断班级是否存在
  383. db_class = await crud_class.find_one(db, filters={"id": info.class_id})
  384. if not db_class:
  385. return {"errcode": 400, "mess": "班级不存在!"}
  386. info.school_id = db_class.school_id
  387. info.grade_id = db_class.grade_id
  388. # 判断阅卷任务是否存在
  389. db_task = await crud_task.find_one(db, filters={"id": info.task_id})
  390. if not db_task:
  391. return {"errcode": 400, "mess": "阅卷任务不存在!"}
  392. if db_task.status != 2:
  393. return {"errcode": 400, "mess": "任务批阅中,不能推送错题!"}
  394. # 判断学生是否存在
  395. _q = [and_(Student.class_id == info.class_id, Student.id.in_(info.student_ids))]
  396. student_count, db_students = await crud_student.find_all(db, filters=_q)
  397. if student_count != len(info.student_ids):
  398. return {"errcode": 400, "mess": "有学生不存在!"}
  399. # 获取错题总数
  400. stmt = select(func.sum(case((ClassErrorQuestion.error_ratio > 0, 1), else_=0)),
  401. func.count()).select_from(ClassErrorQuestion).where(
  402. ClassErrorQuestion.class_id == db_class.id,
  403. ClassErrorQuestion.task_id == db_task.id)
  404. result = list(await crud_class_error_statistic.execute_v2(db, stmt))
  405. error_count, total_count = result[0] if result else (0, 0)
  406. if not error_count:
  407. return {
  408. "errcode": 400,
  409. "mess": f"{'考试' if db_task.mtype == 'exam' else '作业'}【{db_task.name}】无错题可推送!"
  410. }
  411. # 创建班级错题推送记录
  412. cls_error = ClassErrorPushRecordInDB(school_id=db_class.school_id,
  413. grade_id=db_class.grade_id,
  414. class_id=db_class.id,
  415. class_name=db_class.name,
  416. task_id=db_task.id,
  417. task_name=db_task.name,
  418. task_type=db_task.mtype,
  419. error_count=error_count,
  420. student_count=db_class.student_amount,
  421. push_student_count=student_count,
  422. push_student_ids=info.student_ids,
  423. creator_id=current_user.id,
  424. creator_name=current_user.name,
  425. editor_id=current_user.id,
  426. editor_name=current_user.name)
  427. db_cls_error = await crud_class_push_record.insert_one(db, cls_error)
  428. # 后台异步创建学生推送列表
  429. bgtask.add_task(bgtask_create_student_push_record, db_task, db_class, total_count,
  430. db_cls_error.id, db_students, current_user)
  431. return {"data": db_cls_error}
  432. @router.put("/cls-push-errs/{prid}",
  433. response_model=ClassErrorPushRecordDetail,
  434. response_model_exclude_none=True,
  435. summary="更新班级错题推送记录")
  436. async def update_error_push_record(info: UpdateClassErrorPushRecordInfo,
  437. bg_task: BackgroundTasks,
  438. prid: int = Path(..., description="班级错题推送记录ID"),
  439. db: AsyncSession = Depends(get_async_db),
  440. current_user: Teacher = Depends(get_current_user)):
  441. # 判断推送记录是否存在
  442. db_prd = await crud_class_push_record.find_one(db, filters={"id": prid})
  443. if not db_prd:
  444. return {"errcode": 400, "mess": "推送记录不存在!"}
  445. info_dict = info.dict(exclude_none=True)
  446. # 判断推送学生是否变更
  447. if ("student_ids" in info_dict) and (info_dict["student_ids"] != db_prd.push_student_ids):
  448. post_student_set = set(info_dict["student_ids"])
  449. pushed_student_set = set(db_prd.push_student_ids)
  450. add_students = post_student_set - pushed_student_set # 待添加的学生
  451. del_students = pushed_student_set - post_student_set # 待删除的学生
  452. # 判断学生是否存在
  453. student_count, db_students = await crud_student.find_all(
  454. db,
  455. filters=[and_(Student.class_id == db_prd.class_id, Student.id.in_(add_students))],
  456. )
  457. if student_count != len(add_students):
  458. return {"errcode": 400, "mess": "有学生不存在!"}
  459. # 后台异步创建/删除学生推送列表
  460. if add_students:
  461. bg_task.add_task(bgtask_clone_student_push_record, db, db_prd, db_students,
  462. current_user)
  463. if del_students:
  464. bg_task.add_task(bgtask_delete_student_push_record, db, db_prd, del_students)
  465. return {"data": db_prd}
  466. @router.delete("/cls-push-errs/{prid}",
  467. response_model=DetailMixin,
  468. response_model_exclude_none=True,
  469. summary="删除班级错题推送记录")
  470. async def delete_cls_push_record(bg_task: BackgroundTasks,
  471. prid: int = Path(..., description="班级错题推送记录ID"),
  472. db: AsyncSession = Depends(get_async_db),
  473. current_user: Teacher = Depends(get_current_user)):
  474. # 删除班级错题推送记录
  475. try:
  476. await crud_class_push_record.delete(db, obj_id=prid)
  477. except Exception as ex:
  478. print(f"[ERROR] 删除班级推送列表失败! 错误信息: {str(ex)}")
  479. else:
  480. bg_task.add_task(bgtask_delete_student_push_record, db, prid) # 删除相关的学生推送记录
  481. return {"data": None}
  482. @router.post("/cls-err/ratio",
  483. response_model=DetailMixin,
  484. response_model_exclude_none=True,
  485. summary="设置阅卷任务错题率")
  486. async def set_class_error_ratio(info: ClassErrorRatioInfo,
  487. db: AsyncSession = Depends(get_async_db),
  488. current_user: Teacher = Depends(get_current_user)):
  489. # 校验task是否存在
  490. db_task = await crud_task.find_one(db, filters={"id": info.task_id})
  491. if not db_task:
  492. return {"errcode": 404, "mess": "阅卷任务不存在!"}
  493. obj4upd = UpdateMarkTaskInfo(error_ratio=info.ratio)
  494. await crud_task.update(db, db_task, obj4upd)
  495. return {"data": info.ratio}