marktask.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import datetime
  4. import json
  5. import os
  6. from fastapi import Depends, Query, Path
  7. from sqlalchemy import desc
  8. from sqlalchemy import text
  9. from sqlalchemy.ext.asyncio import AsyncSession
  10. from starlette.background import BackgroundTasks
  11. from bgtask.tasks import delete_student_task_question
  12. from core.config import settings
  13. from crud.mark import crud_mark, crud_studentmark
  14. from crud.paper import crud_paper
  15. from crud.school.school import crud_school, crud_grade, crud_class
  16. from crud.user.user import crud_student
  17. from models.mark import StudentMarkTask
  18. from models.user import SysUser
  19. from schemas.base import ReturnField, OrderByField
  20. from schemas.paper import NewMarkTask, UpdateMarkTaskInfo, MarkTaskInDB
  21. from utils.depends import get_async_db, get_current_user
  22. async def create_mark_task(info: NewMarkTask,
  23. db: AsyncSession = Depends(get_async_db),
  24. current_user: SysUser = Depends(get_current_user)):
  25. info_dict = info.dict(exclude_none=True)
  26. if not info_dict:
  27. return {"errcode": 400, "mess": "请求参数为空!"}
  28. # 查询关联对象,组装阅卷任务对象,并写入数据库
  29. db_school = await crud_school.find_one(db, {"id": info_dict["school_id"]})
  30. db_grade = await crud_grade.find_one(db, {"id": info_dict["grade_id"]})
  31. db_class = await crud_class.find_one(db, {"id": info_dict["class_id"]})
  32. if info_dict["mtype"] == "work":
  33. db_paper = await crud_paper.find_one(db, {"id": info_dict["pid"]})
  34. pid = db_paper.id
  35. pno = db_paper.pno
  36. pname = db_paper.name
  37. question_amount = db_paper.question_amount
  38. else:
  39. pid = 0
  40. pno = ""
  41. pname = info_dict["name"]
  42. question_amount = 0
  43. info_dict["name"] = pname
  44. info_dict["pno"] = pno
  45. info_dict["pname"] = pname
  46. info_dict["year"] = datetime.date.today().year
  47. info_dict["school_name"] = db_school.name
  48. info_dict["grade_name"] = db_grade.name
  49. info_dict["class_name"] = db_class.name
  50. info_dict["student_amount"] = db_class.student_amount
  51. info_dict["creator_id"] = info_dict["editor_id"] = current_user.id
  52. info_dict["creator_name"] = info_dict["editor_name"] = current_user.username
  53. obj_in = MarkTaskInDB(**info_dict)
  54. db_task = await crud_mark.insert_one(db, obj_in)
  55. # 生成每个学生的阅卷任务
  56. student_mark_tasks = []
  57. students = await crud_student.fetch_all(
  58. db, filters={"class_id": info_dict["class_id"]})
  59. for stu in students:
  60. task = {
  61. "task_id": db_task.id,
  62. "pid": pid,
  63. "pno": pno,
  64. "pname": pname,
  65. "pimgs": "",
  66. "question_amount": question_amount,
  67. "student_id": stu.id,
  68. "student_sno": stu.sno,
  69. "student_name": stu.name
  70. }
  71. task["creator_id"] = task["editor_id"] = current_user.id
  72. task["creator_name"] = task["editor_name"] = current_user.username
  73. student_mark_tasks.append(task)
  74. await crud_studentmark.insert_many(db, student_mark_tasks)
  75. # 创建扫描目录
  76. ftpname = f"T{db_task.id}-{db_task.pno}"
  77. ftppath = os.path.join(settings.PAPERS_PATH, ftpname)
  78. if not os.path.exists(ftppath):
  79. os.makedirs(ftppath)
  80. return {"data": db_task}
  81. async def update_mark_task(info: UpdateMarkTaskInfo,
  82. tid: int = Path(..., description="阅卷任务ID"),
  83. db: AsyncSession = Depends(get_async_db),
  84. current_user: SysUser = Depends(get_current_user)):
  85. info_dict = info.dict(exclude_none=True)
  86. if not info_dict:
  87. return {"errcode": 400, "mess": "请求参数为空!"}
  88. # 查询阅卷任务是否存在
  89. db_task = await crud_mark.find_one(db, {"id": tid})
  90. if not db_task:
  91. return {"errcode": 400, "mess": "阅卷任务不存在!"}
  92. # 判断学校是否更新
  93. if ("school_id"
  94. in info_dict) and (info_dict["school_id"] != db_task.school_id):
  95. db_school = await crud_school.find_one(
  96. db, filters={"id": info_dict["school_id"]})
  97. if not db_school:
  98. return {"errcode": 404, "mess": "学校不存在!"}
  99. info_dict["school_name"] = db_school.name
  100. # 判断年级是否更新
  101. if ("grade_id"
  102. in info_dict) and (info_dict["grade_id"] != db_task.grade_id):
  103. db_grade = await crud_grade.find_one(
  104. db, filters={"id": info_dict["grade_id"]})
  105. if not db_grade:
  106. return {"errcode": 404, "mess": "年级不存在!"}
  107. info_dict["grade_name"] = db_grade.name
  108. # 判断班级是否更新
  109. if ("class_id"
  110. in info_dict) and (info_dict["class_id"] != db_task.class_id):
  111. db_class = await crud_class.find_one(
  112. db, filters={"id": info_dict["class_id"]})
  113. if not db_class:
  114. return {"errcode": 404, "mess": "班级不存在!"}
  115. info_dict["class_name"] = db_class.name
  116. info_dict["student_amount"] = db_class.student_amount
  117. # 判断试卷是否更新
  118. if ("pid" in info_dict) and (info_dict["pid"] != db_task.pid):
  119. db_paper = await crud_paper.find_one(db,
  120. filters={"id": info_dict["pid"]})
  121. if not db_paper:
  122. return {"errcode": 404, "mess": "试卷不存在!"}
  123. info_dict["pno"] = db_paper.pno
  124. info_dict["pname"] = db_paper.name
  125. # 更新
  126. info_dict["editor_id"] = current_user.id
  127. info_dict["editor_name"] = current_user.username
  128. db_task = await crud_mark.update(db, db_task, info)
  129. # 更新student_task
  130. if ("pid" in info_dict) and (info_dict["pid"] != db_task.pid):
  131. stmt = "UPDATE {} SET pid={},pno='{}',pname='{}' WHERE task_id={}".format(
  132. StudentMarkTask.__tablename__, db_task.pid, db_task.pno,
  133. db_task.pname, db_task.id)
  134. await crud_studentmark.execute(db, stmt)
  135. return {"data": db_task}
  136. async def delete_mark_task(bg_task: BackgroundTasks,
  137. tid: int = Path(..., description="阅卷任务ID"),
  138. db: AsyncSession = Depends(get_async_db),
  139. current_user: SysUser = Depends(get_current_user)):
  140. existed = await crud_mark.count(db, {"id": tid})
  141. if existed:
  142. return {"errcode": 400, "mess": "阅卷任务不存在!"}
  143. # 删除学生阅卷任务
  144. bg_task.add_task(delete_student_task_question, db, tid)
  145. return {"data": None}
  146. async def get_mark_task(tid: int = Path(..., description="阅卷任务ID"),
  147. db: AsyncSession = Depends(get_async_db),
  148. current_user: SysUser = Depends(get_current_user)):
  149. db_exist = await crud_mark.find_one(db, {"id": tid})
  150. if not db_exist:
  151. return {"errcode": 400, "mess": "角色不存在!"}
  152. # 获取阅卷任务的学生
  153. students = await crud_studentmark.fetch_all(
  154. db, filters={"task_id": db_exist.id}, order_by=[desc("updated_at")])
  155. for stu in students:
  156. stu.pimgs = json.loads(stu.pimgs) if stu.pimgs else []
  157. db_exist.students = students
  158. cur_students = students
  159. cur_imgs = cur_students[0].pimgs if cur_students else []
  160. db_exist.cur_imgs = cur_imgs
  161. db_exist.total = len(students)
  162. # 已完成上传
  163. finish_students = filter(lambda x: x.pimgs, students)
  164. db_exist.finish = len(list(finish_students))
  165. db_exist.ftp_path = f"T{db_exist.id}-{db_exist.pno}"
  166. return {"data": db_exist}
  167. async def get_mark_tasks(page: int = 1,
  168. size: int = 10,
  169. name: str = "",
  170. year: int = 0,
  171. status: int = 0,
  172. order: OrderByField = Query(
  173. "-created_at",
  174. description="排序字段,用逗号分隔,升降序以-判断,默认-created_at"),
  175. res: ReturnField = Query("",
  176. description="控制返回字段,字段逗号分隔"),
  177. db: AsyncSession = Depends(get_async_db),
  178. current_user: SysUser = Depends(get_current_user)):
  179. filters = []
  180. if name:
  181. filters.append(text(f"name LIKE '%{name}%'"))
  182. if year:
  183. filters.append(text(f"year == {year}"))
  184. if status:
  185. filters.append(text(f"status == {status}"))
  186. offset = (page - 1) * size
  187. if isinstance(order, str):
  188. order = [text(order)]
  189. total, items = await crud_mark.find_all(db,
  190. filters=filters,
  191. offset=offset,
  192. limit=size,
  193. order_by=order,
  194. return_fields=res)
  195. return {"total": total, "data": items}