#!/usr/bin/env python # -*- coding: utf-8 -*- import datetime import json import os from fastapi import Depends, Query, Path from sqlalchemy import desc from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession from starlette.background import BackgroundTasks from bgtask.tasks import delete_student_task_question from core.config import settings from crud.mark import crud_mark, crud_studentmark from crud.paper import crud_paper from crud.school.school import crud_school, crud_grade, crud_class from crud.user.user import crud_student from models.mark import StudentMarkTask from models.user import SysUser from schemas.base import ReturnField, OrderByField from schemas.paper import NewMarkTask, UpdateMarkTaskInfo, MarkTaskInDB from utils.depends import get_async_db, get_current_user async def create_mark_task(info: NewMarkTask, db: AsyncSession = Depends(get_async_db), current_user: SysUser = Depends(get_current_user)): info_dict = info.dict(exclude_none=True) if not info_dict: return {"errcode": 400, "mess": "请求参数为空!"} # 查询关联对象,组装阅卷任务对象,并写入数据库 db_school = await crud_school.find_one(db, {"id": info_dict["school_id"]}) db_grade = await crud_grade.find_one(db, {"id": info_dict["grade_id"]}) db_class = await crud_class.find_one(db, {"id": info_dict["class_id"]}) if info_dict["mtype"] == "work": db_paper = await crud_paper.find_one(db, {"id": info_dict["pid"]}) pid = db_paper.id pno = db_paper.pno pname = db_paper.name question_amount = db_paper.question_amount else: pid = 0 pno = "" pname = info_dict["name"] question_amount = 0 info_dict["name"] = pname info_dict["pno"] = pno info_dict["pname"] = pname info_dict["year"] = datetime.date.today().year info_dict["school_name"] = db_school.name info_dict["grade_name"] = db_grade.name info_dict["class_name"] = db_class.name info_dict["student_amount"] = db_class.student_amount info_dict["creator_id"] = info_dict["editor_id"] = current_user.id info_dict["creator_name"] = info_dict["editor_name"] = current_user.username obj_in = MarkTaskInDB(**info_dict) db_task = await crud_mark.insert_one(db, obj_in) # 生成每个学生的阅卷任务 student_mark_tasks = [] students = await crud_student.fetch_all( db, filters={"class_id": info_dict["class_id"]}) for stu in students: task = { "task_id": db_task.id, "pid": pid, "pno": pno, "pname": pname, "pimgs": "", "question_amount": question_amount, "student_id": stu.id, "student_sno": stu.sno, "student_name": stu.name } task["creator_id"] = task["editor_id"] = current_user.id task["creator_name"] = task["editor_name"] = current_user.username student_mark_tasks.append(task) await crud_studentmark.insert_many(db, student_mark_tasks) # 创建扫描目录 ftpname = f"T{db_task.id}-{db_task.pno}" ftppath = os.path.join(settings.PAPERS_PATH, ftpname) if not os.path.exists(ftppath): os.makedirs(ftppath) return {"data": db_task} async def update_mark_task(info: UpdateMarkTaskInfo, tid: int = Path(..., description="阅卷任务ID"), db: AsyncSession = Depends(get_async_db), current_user: SysUser = Depends(get_current_user)): info_dict = info.dict(exclude_none=True) if not info_dict: return {"errcode": 400, "mess": "请求参数为空!"} # 查询阅卷任务是否存在 db_task = await crud_mark.find_one(db, {"id": tid}) if not db_task: return {"errcode": 400, "mess": "阅卷任务不存在!"} # 判断学校是否更新 if ("school_id" in info_dict) and (info_dict["school_id"] != db_task.school_id): db_school = await crud_school.find_one( db, filters={"id": info_dict["school_id"]}) if not db_school: return {"errcode": 404, "mess": "学校不存在!"} info_dict["school_name"] = db_school.name # 判断年级是否更新 if ("grade_id" in info_dict) and (info_dict["grade_id"] != db_task.grade_id): db_grade = await crud_grade.find_one( db, filters={"id": info_dict["grade_id"]}) if not db_grade: return {"errcode": 404, "mess": "年级不存在!"} info_dict["grade_name"] = db_grade.name # 判断班级是否更新 if ("class_id" in info_dict) and (info_dict["class_id"] != db_task.class_id): db_class = await crud_class.find_one( db, filters={"id": info_dict["class_id"]}) if not db_class: return {"errcode": 404, "mess": "班级不存在!"} info_dict["class_name"] = db_class.name info_dict["student_amount"] = db_class.student_amount # 判断试卷是否更新 if ("pid" in info_dict) and (info_dict["pid"] != db_task.pid): db_paper = await crud_paper.find_one(db, filters={"id": info_dict["pid"]}) if not db_paper: return {"errcode": 404, "mess": "试卷不存在!"} info_dict["pno"] = db_paper.pno info_dict["pname"] = db_paper.name # 更新 info_dict["editor_id"] = current_user.id info_dict["editor_name"] = current_user.username db_task = await crud_mark.update(db, db_task, info) # 更新student_task if ("pid" in info_dict) and (info_dict["pid"] != db_task.pid): stmt = "UPDATE {} SET pid={},pno='{}',pname='{}' WHERE task_id={}".format( StudentMarkTask.__tablename__, db_task.pid, db_task.pno, db_task.pname, db_task.id) await crud_studentmark.execute(db, stmt) return {"data": db_task} async def delete_mark_task(bg_task: BackgroundTasks, tid: int = Path(..., description="阅卷任务ID"), db: AsyncSession = Depends(get_async_db), current_user: SysUser = Depends(get_current_user)): existed = await crud_mark.count(db, {"id": tid}) if existed: return {"errcode": 400, "mess": "阅卷任务不存在!"} # 删除学生阅卷任务 bg_task.add_task(delete_student_task_question, db, tid) return {"data": None} async def get_mark_task(tid: int = Path(..., description="阅卷任务ID"), db: AsyncSession = Depends(get_async_db), current_user: SysUser = Depends(get_current_user)): db_exist = await crud_mark.find_one(db, {"id": tid}) if not db_exist: return {"errcode": 400, "mess": "角色不存在!"} # 获取阅卷任务的学生 students = await crud_studentmark.fetch_all( db, filters={"task_id": db_exist.id}, order_by=[desc("updated_at")]) for stu in students: stu.pimgs = json.loads(stu.pimgs) if stu.pimgs else [] db_exist.students = students cur_students = students cur_imgs = cur_students[0].pimgs if cur_students else [] db_exist.cur_imgs = cur_imgs db_exist.total = len(students) # 已完成上传 finish_students = filter(lambda x: x.pimgs, students) db_exist.finish = len(list(finish_students)) db_exist.ftp_path = f"T{db_exist.id}-{db_exist.pno}" return {"data": db_exist} async def get_mark_tasks(page: int = 1, size: int = 10, name: str = "", year: int = 0, status: int = 0, order: OrderByField = Query( "-created_at", description="排序字段,用逗号分隔,升降序以-判断,默认-created_at"), res: ReturnField = Query("", description="控制返回字段,字段逗号分隔"), db: AsyncSession = Depends(get_async_db), current_user: SysUser = Depends(get_current_user)): filters = [] if name: filters.append(text(f"name LIKE '%{name}%'")) if year: filters.append(text(f"year == {year}")) if status: filters.append(text(f"status == {status}")) offset = (page - 1) * size if isinstance(order, str): order = [text(order)] total, items = await crud_mark.find_all(db, filters=filters, offset=offset, limit=size, order_by=order, return_fields=res) return {"total": total, "data": items}