#!/usr/bin/env python # -*- coding: utf-8 -*- import datetime from typing import Union from fastapi import Query, Depends, Path, Body from sqlalchemy import text, update, between from sqlalchemy.ext.asyncio import AsyncSession from common.const import RESOURCE_TYPES from crud.resource import RESOURCE_CRUDS, crud_collection from models.resource import RESOURCE_MODES from models.user import Teacher, Student from schemas.app.resource import NewResourceCollect, CollectInfo from schemas.base import OrderByField from utils.depends import get_async_db, get_current_user from utils.fileuploader import ossfile_uploader async def get_resources(page: int = 1, size: int = 10, name: str = "", year: int = 0, area: str = "", sid: int = Query(0, description="学校ID,获取考试资源时才传此参数"), ctype: str = Query(..., description="资源分类名称,exam/work"), ctgid: int = Query(0, description="资源分类ID"), rtype: str = Query("", description="作业资源分类"), isnew: int = Query(0, description="最新资源,是=1,否=0"), hot: int = Query(0, description="是否热点资源?是=1,否=0"), order: OrderByField = Query("-id", description="排序字段,用逗号分隔,升降序以-判断"), db: AsyncSession = Depends(get_async_db), current_user: Union[Teacher, Student] = Depends(get_current_user)): # 判断资源类型 if ctype not in RESOURCE_TYPES: return {"errcode": 400, "mess": "资源类型不存在!"} else: model = RESOURCE_MODES[ctype] # 筛选条件 _q = [] if area and area != "0": _q.append(model.area == area) if name: _q.append(model.name.like(f"%{name}%")) if year: _q.append(model.year == year) if (ctype == "exam") and sid: _q.append(model.school_id == sid) if ctgid: _q.append(model.category_id == ctgid) if ctype and rtype: _q.append(model.rtype == rtype) if hot: _q.append(model.hot == hot) now_time = datetime.datetime.now() if isnew: start_time = now_time - datetime.timedelta(days=3) _q.append(between(model.created_at, start_time, now_time)) offset = (page - 1) * size # 查询 total, db_resources = await RESOURCE_CRUDS[ctype].find_all(db, filters=_q, offset=offset, limit=size, order_by=order) # 判断是否最新资源 for item in db_resources: item.attach_url = item.attach_url.split(";") if (now_time - item.created_at).days <= 3: item.isnew = True else: item.isnew = False delattr(item, "attach_url") return {"data": db_resources, "total": total} async def download_resource(rid: int = Path(..., description="资源ID"), ctype: str = Query(..., description="资源分类名称,exam/work"), db: AsyncSession = Depends(get_async_db), current_user: Union[Teacher, Student] = Depends(get_current_user)): # 判断资源类型 if ctype not in RESOURCE_TYPES: return {"errcode": 400, "mess": "资源类型不存在!"} else: model = RESOURCE_MODES[ctype] crud = RESOURCE_CRUDS[ctype] # 查询 db_resource = await crud.find_one(db, filters={"id": rid}, return_fields=["download", "attach_url"]) # 更新下载量 download = db_resource.download + 1 stmt = (update(model).where(model.id == rid).values(download=download)) await crud.execute_v2(db, stmt) return {"data": {"urls": db_resource.attach_url.split(";"), "download": download}} async def collect_resource(rid: int = Path(..., description="资源ID"), ctype: str = Query(..., description="资源分类名称,exam/work"), opt: CollectInfo = Body(..., description="操作类型,0=取消收藏,1=添加收藏"), db: AsyncSession = Depends(get_async_db), current_user: Union[Teacher, Student] = Depends(get_current_user)): # 判断资源类型 if ctype not in RESOURCE_TYPES: return {"errcode": 400, "mess": "资源类型不存在!"} else: model = RESOURCE_MODES[ctype] crud = RESOURCE_CRUDS[ctype] # 判断资源是否存在 db_obj = await crud.find_one(db, filters={"id": rid}, return_fields=["collect"]) if not db_obj: return {"errcode": 404, "mess": "资源不存在!"} # 更新收藏量 if opt.opt: collect_num = db_obj.collect + 1 else: collect_num = db_obj.collect - 1 stmt = (update(model).where(model.id == rid).values(collect=collect_num)) await crud.execute_v2(db, stmt) # 写入收藏表 utype = 1 if isinstance(current_user, Teacher) else 2 if opt.opt: info = NewResourceCollect(rid=rid, ctype=ctype, uid=current_user.id, utype=utype) await crud_collection.insert_one(db, info) else: await crud_collection.delete(db, where_clauses={ "rid": rid, "ctype": ctype, "uid": current_user.id, "utype": utype }) return {"data": {"collect": collect_num}} async def preview_resource(rid: int = Path(..., description="资源ID"), ctype: str = Query(..., description="资源分类名称,exam/work"), db: AsyncSession = Depends(get_async_db), current_user: Union[Teacher, Student] = Depends(get_current_user)): # 判断资源类型 if ctype not in RESOURCE_TYPES: return {"errcode": 400, "mess": "资源类型不存在!"} else: model = RESOURCE_MODES[ctype] crud = RESOURCE_CRUDS[ctype] # 判断资源是否存在 db_obj = await crud.find_one(db, filters={"id": rid}, return_fields=["visit", "attach_url"]) if not db_obj: return {"errcode": 400, "mess": "资源不存在!"} # 更新浏览量 visit_num = db_obj.visit + 1 stmt = (update(model).where(model.id == rid).values(visit=visit_num)) await crud.execute_v2(db, stmt) # 向oss发起预览请求 preview_url = ossfile_uploader.get_preview_url(db_obj.attach_url) return {"data": {"urls": [preview_url], "visit": visit_num}} async def get_collected_resource(page: int = 1, size: int = 10, name: str = "", ctype: str = Query(None, description="资源分类名称,exam/work"), db: AsyncSession = Depends(get_async_db), current_user: Union[Teacher, Student] = Depends(get_current_user)): # 判断资源类型 if ctype and (ctype not in RESOURCE_TYPES): return {"errcode": 400, "mess": "资源类型不存在!"} # 筛选条件 _q = {"uid": current_user.id, "utype": current_user.utype} if ctype: _q["ctype"] = ctype offset = (page - 1) * size total = 0 # 总数 collect_info = {} # 收藏列表 work_rids = [] # 作业资源 exam_rids = [] # 考试资源 return_fields = ["id", "ctype", "rid", "created_at"] _, db_collections = await crud_collection.find_all(db, filters=_q, return_fields=return_fields, limit=size, offset=offset) for item in db_collections: if item[1] == "work": work_rids.append(str(item.rid)) else: exam_rids.append(str(item.rid)) collect_info[f"{item.ctype}-{item.rid}"] = [item.id, item.created_at] # 分别查询作业资源和考试资源 data = [] return_fields = [ "id", "name", "area", "year", "collect", "download", "visit", "category_id", "attach_url" ] for item in [(work_rids, "work"), (exam_rids, "exam")]: if not item[0]: continue model = RESOURCE_MODES[item[1]] crud = RESOURCE_CRUDS[item[1]] _q = [model.id.in_(item[0])] if name: _q.append(model.name.like(f"{name}%")) total, db_resources = await crud.find_all(db, filters=_q, return_fields=return_fields) for resource in db_resources: total += 1 temp = { "cid": collect_info[f"{item[1]}-{resource.id}"][0], "rid": resource.id, "name": resource.name, "area": resource.area, "year": resource.year, "collect": resource.collect, "download": resource.download, "visit": resource.visit, "category_id": resource.category_id, "attach_url": resource.attach_url, "ctype": item[1], "created_at": collect_info[f"{item[1]}-{resource.id}"][1] } data.append(temp) data.sort(key=lambda x: x["created_at"], reverse=True) return {"data": data, "total": total}