resource.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. import datetime
  4. from typing import Union
  5. from fastapi import Query, Depends, Path, Body
  6. from sqlalchemy import text, update, between
  7. from sqlalchemy.ext.asyncio import AsyncSession
  8. from common.const import RESOURCE_TYPES
  9. from crud.resource import RESOURCE_CRUDS, crud_collection
  10. from models.resource import RESOURCE_MODES
  11. from models.user import Teacher, Student
  12. from schemas.app.resource import NewResourceCollect, CollectInfo
  13. from schemas.base import OrderByField
  14. from utils.depends import get_async_db, get_current_user
  15. from utils.fileuploader import ossfile_uploader
  16. async def get_resources(page: int = 1,
  17. size: int = 10,
  18. name: str = "",
  19. year: int = 0,
  20. area: str = "",
  21. sid: int = Query(0, description="学校ID,获取考试资源时才传此参数"),
  22. ctype: str = Query(..., description="资源分类名称,exam/work"),
  23. ctgid: int = Query(0, description="资源分类ID"),
  24. rtype: str = Query("", description="作业资源分类"),
  25. isnew: int = Query(0, description="最新资源,是=1,否=0"),
  26. hot: int = Query(0, description="是否热点资源?是=1,否=0"),
  27. order: OrderByField = Query("-id", description="排序字段,用逗号分隔,升降序以-判断"),
  28. db: AsyncSession = Depends(get_async_db),
  29. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  30. # 判断资源类型
  31. if ctype not in RESOURCE_TYPES:
  32. return {"errcode": 400, "mess": "资源类型不存在!"}
  33. else:
  34. model = RESOURCE_MODES[ctype]
  35. # 筛选条件
  36. _q = []
  37. if area and area != "0":
  38. _q.append(model.area == area)
  39. if name:
  40. _q.append(model.name.like(f"%{name}%"))
  41. if year:
  42. _q.append(model.year == year)
  43. if (ctype == "exam") and sid:
  44. _q.append(model.school_id == sid)
  45. if ctgid:
  46. _q.append(model.category_id == ctgid)
  47. if ctype and rtype:
  48. _q.append(model.rtype == rtype)
  49. if hot:
  50. _q.append(model.hot == hot)
  51. now_time = datetime.datetime.now()
  52. if isnew:
  53. start_time = now_time - datetime.timedelta(days=3)
  54. _q.append(between(model.created_at, start_time, now_time))
  55. offset = (page - 1) * size
  56. # 查询
  57. total, db_resources = await RESOURCE_CRUDS[ctype].find_all(db,
  58. filters=_q,
  59. offset=offset,
  60. limit=size,
  61. order_by=order)
  62. # 判断是否最新资源
  63. for item in db_resources:
  64. item.attach_url = item.attach_url.split(";")
  65. if (now_time - item.created_at).days <= 3:
  66. item.isnew = True
  67. else:
  68. item.isnew = False
  69. delattr(item, "attach_url")
  70. return {"data": db_resources, "total": total}
  71. async def download_resource(rid: int = Path(..., description="资源ID"),
  72. ctype: str = Query(..., description="资源分类名称,exam/work"),
  73. db: AsyncSession = Depends(get_async_db),
  74. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  75. # 判断资源类型
  76. if ctype not in RESOURCE_TYPES:
  77. return {"errcode": 400, "mess": "资源类型不存在!"}
  78. else:
  79. model = RESOURCE_MODES[ctype]
  80. crud = RESOURCE_CRUDS[ctype]
  81. # 查询
  82. db_resource = await crud.find_one(db,
  83. filters={"id": rid},
  84. return_fields=["download", "attach_url"])
  85. # 更新下载量
  86. download = db_resource.download + 1
  87. stmt = (update(model).where(model.id == rid).values(download=download))
  88. await crud.execute_v2(db, stmt)
  89. return {"data": {"urls": db_resource.attach_url.split(";"), "download": download}}
  90. async def collect_resource(rid: int = Path(..., description="资源ID"),
  91. ctype: str = Query(..., description="资源分类名称,exam/work"),
  92. opt: CollectInfo = Body(..., description="操作类型,0=取消收藏,1=添加收藏"),
  93. db: AsyncSession = Depends(get_async_db),
  94. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  95. # 判断资源类型
  96. if ctype not in RESOURCE_TYPES:
  97. return {"errcode": 400, "mess": "资源类型不存在!"}
  98. else:
  99. model = RESOURCE_MODES[ctype]
  100. crud = RESOURCE_CRUDS[ctype]
  101. # 判断资源是否存在
  102. db_obj = await crud.find_one(db, filters={"id": rid}, return_fields=["collect"])
  103. if not db_obj:
  104. return {"errcode": 404, "mess": "资源不存在!"}
  105. # 更新收藏量
  106. if opt.opt:
  107. collect_num = db_obj.collect + 1
  108. else:
  109. collect_num = db_obj.collect - 1
  110. stmt = (update(model).where(model.id == rid).values(collect=collect_num))
  111. await crud.execute_v2(db, stmt)
  112. # 写入收藏表
  113. utype = 1 if isinstance(current_user, Teacher) else 2
  114. if opt.opt:
  115. info = NewResourceCollect(rid=rid, ctype=ctype, uid=current_user.id, utype=utype)
  116. await crud_collection.insert_one(db, info)
  117. else:
  118. await crud_collection.delete(db,
  119. where_clauses={
  120. "rid": rid,
  121. "ctype": ctype,
  122. "uid": current_user.id,
  123. "utype": utype
  124. })
  125. return {"data": {"collect": collect_num}}
  126. async def preview_resource(rid: int = Path(..., description="资源ID"),
  127. ctype: str = Query(..., description="资源分类名称,exam/work"),
  128. db: AsyncSession = Depends(get_async_db),
  129. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  130. # 判断资源类型
  131. if ctype not in RESOURCE_TYPES:
  132. return {"errcode": 400, "mess": "资源类型不存在!"}
  133. else:
  134. model = RESOURCE_MODES[ctype]
  135. crud = RESOURCE_CRUDS[ctype]
  136. # 判断资源是否存在
  137. db_obj = await crud.find_one(db, filters={"id": rid}, return_fields=["visit", "attach_url"])
  138. if not db_obj:
  139. return {"errcode": 400, "mess": "资源不存在!"}
  140. # 更新浏览量
  141. visit_num = db_obj.visit + 1
  142. stmt = (update(model).where(model.id == rid).values(visit=visit_num))
  143. await crud.execute_v2(db, stmt)
  144. # 向oss发起预览请求
  145. preview_url = ossfile_uploader.get_preview_url(db_obj.attach_url)
  146. return {"data": {"urls": [preview_url], "visit": visit_num}}
  147. async def get_collected_resource(page: int = 1,
  148. size: int = 10,
  149. name: str = "",
  150. ctype: str = Query(None, description="资源分类名称,exam/work"),
  151. db: AsyncSession = Depends(get_async_db),
  152. current_user: Union[Teacher, Student] = Depends(get_current_user)):
  153. # 判断资源类型
  154. if ctype and (ctype not in RESOURCE_TYPES):
  155. return {"errcode": 400, "mess": "资源类型不存在!"}
  156. # 筛选条件
  157. _q = {"uid": current_user.id, "utype": current_user.utype}
  158. if ctype:
  159. _q["ctype"] = ctype
  160. offset = (page - 1) * size
  161. total = 0 # 总数
  162. collect_info = {} # 收藏列表
  163. work_rids = [] # 作业资源
  164. exam_rids = [] # 考试资源
  165. return_fields = ["id", "ctype", "rid", "created_at"]
  166. _, db_collections = await crud_collection.find_all(db,
  167. filters=_q,
  168. return_fields=return_fields,
  169. limit=size,
  170. offset=offset)
  171. for item in db_collections:
  172. if item[1] == "work":
  173. work_rids.append(str(item.rid))
  174. else:
  175. exam_rids.append(str(item.rid))
  176. collect_info[f"{item.ctype}-{item.rid}"] = [item.id, item.created_at]
  177. # 分别查询作业资源和考试资源
  178. data = []
  179. return_fields = [
  180. "id", "name", "area", "year", "collect", "download", "visit", "category_id", "attach_url"
  181. ]
  182. for item in [(work_rids, "work"), (exam_rids, "exam")]:
  183. if not item[0]:
  184. continue
  185. model = RESOURCE_MODES[item[1]]
  186. crud = RESOURCE_CRUDS[item[1]]
  187. _q = [model.id.in_(item[0])]
  188. if name:
  189. _q.append(model.name.like(f"{name}%"))
  190. total, db_resources = await crud.find_all(db, filters=_q, return_fields=return_fields)
  191. for resource in db_resources:
  192. total += 1
  193. temp = {
  194. "cid": collect_info[f"{item[1]}-{resource.id}"][0],
  195. "rid": resource.id,
  196. "name": resource.name,
  197. "area": resource.area,
  198. "year": resource.year,
  199. "collect": resource.collect,
  200. "download": resource.download,
  201. "visit": resource.visit,
  202. "category_id": resource.category_id,
  203. "attach_url": resource.attach_url,
  204. "ctype": item[1],
  205. "created_at": collect_info[f"{item[1]}-{resource.id}"][1]
  206. }
  207. data.append(temp)
  208. data.sort(key=lambda x: x["created_at"], reverse=True)
  209. return {"data": data, "total": total}