web.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. from flask import Flask
  2. from flask_login import current_user
  3. import math
  4. from sql.store import get_store_item_list, get_store_item, confirm_order
  5. from tool.typing import *
  6. from tool.page import get_page
  7. from tool.login import create_uid
  8. from core.garbage import GarbageType
  9. from sql import DBBit
  10. from sql.db import DB
  11. from sql.garbage import count_garbage_by_uid, get_garbage_by_uid
  12. from sql.user import find_user_by_name, find_user_by_id, get_rank_for_user, count_all_user
  13. from sql.news import write_news, get_news, get_news_count, delete_news
  14. from sql.store import check_order, get_goods_from_order, set_goods_quantity, set_goods_score, add_new_goods
  15. from . import web_user
  16. from . import web_goods
  17. class WebsiteBase:
  18. def __init__(self, app: Flask, db: DB):
  19. self._db = db
  20. self._app = app
  21. self._user = current_user # 把参函传递的user移迁为该变量
  22. @property
  23. def db(self):
  24. return self._db
  25. @property
  26. def app(self):
  27. return self._app
  28. @property
  29. def user(self):
  30. return self._user
  31. @property
  32. def rel_user(self):
  33. return self._user._get_current_object()
  34. class AuthWebsite(WebsiteBase):
  35. """ 用户界面 """
  36. def load_user_by_name(self, name: uname_t, passwd: passwd_t) -> Optional["web_user.WebUser"]:
  37. user = find_user_by_name(name, passwd, self._db)
  38. if user is None:
  39. return None
  40. user.destruct() # 提前释放, 后续操作与数据库无关
  41. return web_user.WebUser(name, create_uid(name, passwd))
  42. def load_user_by_id(self, uid: uid_t) -> Optional["web_user.WebUser"]:
  43. user = find_user_by_id(uid, self._db)
  44. if user is None:
  45. return None
  46. user.destruct() # 提前释放, 后续操作与数据库无关
  47. return web_user.WebUser(user.get_name(), uid)
  48. def get_user_garbage_count(self, uid: uid_t):
  49. return count_garbage_by_uid(uid, self._db, time_limit=False)
  50. def get_user_garbage_list(self, uid: uid_t, limit: int, offset: int = 0):
  51. garbage_list = get_garbage_by_uid(uid,
  52. columns=["UseTime", "Location", "GarbageType", "CheckResult"],
  53. limit=limit,
  54. db=self.db,
  55. offset=offset)
  56. res = []
  57. for i in garbage_list:
  58. t = i[0].strftime("%Y-%m-%d %H:%M:%S")
  59. loc = i[1]
  60. type_ = GarbageType.GarbageTypeStrList_ch[int(i[2])]
  61. if i[3] is None:
  62. result = "待确定"
  63. result_class = 'wait'
  64. elif i[3] == DBBit.BIT_1:
  65. result = "投放正确"
  66. result_class = 'pass'
  67. else:
  68. result = "投放错误"
  69. result_class = 'fail'
  70. res.append((t, loc, type_, result, result_class))
  71. return res
  72. def get_user_by_id(self, uid: uid_t):
  73. res = find_user_by_id(uid, self._db)
  74. return res
  75. class StoreWebsite(WebsiteBase):
  76. """ 积分商城 """
  77. def get_store_list(self) -> Optional[List]:
  78. return get_store_item_list(self._db)
  79. def get_goods(self, goods_id: int):
  80. goods = get_store_item(goods_id, self._db) # 返回值 ["Name", "Score", "Quantity", "GoodsID"]
  81. if goods is None:
  82. return goods
  83. # 更快的写法应该是 web_goods.Goods(*goods), 但目前的写法可读性更佳
  84. return web_goods.Goods(name=goods[0], score=goods[1], quantity=goods[2], goods_id=goods[3])
  85. def check_order(self, order, uid) -> Tuple[Optional[list], Optional[str]]:
  86. if not check_order(order, uid, self._db):
  87. return None, None
  88. goods = get_goods_from_order(order, self._db)
  89. res = []
  90. for i in goods:
  91. res.append(f"#{i} {i[0]} x {i[1]}")
  92. return res, uid
  93. def confirm_order(self, order_id: int, uid: uid_t) -> bool:
  94. return confirm_order(order_id, uid, self._db)
  95. def set_goods_quantity(self, quantity: int, goods_id: int):
  96. return set_goods_quantity(quantity, goods_id, self._db)
  97. def set_goods_score(self, score: score_t, goods_id: int):
  98. return set_goods_score(score, goods_id, self._db)
  99. def add_new_goods(self, name: str, score: score_t, quantity: int):
  100. return add_new_goods(name, score, quantity, self._db)
  101. class RankWebsite(WebsiteBase):
  102. """ 排行榜 """
  103. def get_rank(self, page: int, order_by: str = "DESC", url: str = "rank_up"):
  104. count = math.ceil(count_all_user(self._db) / 20)
  105. offset = 20 * (page - 1)
  106. return get_rank_for_user(self.db, 20, offset, order_by), get_page(f"rank.{url}", page, count)
  107. class NewsWebsite(WebsiteBase):
  108. """ 博客 """
  109. def write_news(self, context: str, uid: uid_t):
  110. return write_news(context, uid, self.db)
  111. def get_news(self, page: int = 1):
  112. count = math.ceil(get_news_count(self.db) / 10)
  113. if count == 0:
  114. return -1, [], []
  115. elif page > count:
  116. return 0, None, None
  117. res, news_list = get_news(limit=20, offset=((page - 1) * 10), db=self.db)
  118. if not res:
  119. return 0, None, None
  120. return 1, news_list, get_page("news.index", page, count)
  121. def delete_news(self, context_id: str):
  122. return delete_news(context_id, self._db)
  123. class DataWebsite(WebsiteBase):
  124. """
  125. 数据分析
  126. """
  127. def count_by_days(self):
  128. cur = self._db.search(columns=["GarbageType", "DATE_FORMAT(UseTime,'%H') AS days", "count(GarbageID) AS count"],
  129. table="garbage",
  130. group_by=["GarbageType", "days"],
  131. order_by=[("GarbageType", "ASC"), ("days", "ASC")],
  132. where="UseTime IS NOT NULL")
  133. if cur is None:
  134. return None
  135. return cur.fetchall()
  136. def count_by_times(self, days):
  137. cur = self._db.search(columns=["GarbageType", "days", "count(GarbageID) AS count"],
  138. table=f"garbage_{days}d",
  139. group_by=["GarbageType", "days"],
  140. order_by=[("GarbageType", "ASC"), ("days", "ASC")],
  141. where="UseTime IS NOT NULL")
  142. if cur is None:
  143. return None
  144. return cur.fetchall()
  145. def count_passing_rate(self):
  146. cur = self._db.search(columns=["GarbageType",
  147. f"get_avg(count(GarbageID), "
  148. f"(SELECT count(g.GarbageID) "
  149. f"FROM garbage AS g WHERE g.CheckResult is not null)) AS count"],
  150. table="garbage",
  151. where=["CheckResult is not null", "CheckResult=1"],
  152. group_by=["GarbageType"],
  153. order_by=[("GarbageType", "ASC")])
  154. if cur is None:
  155. return None
  156. return cur.fetchall()
  157. class Website(AuthWebsite, StoreWebsite, RankWebsite, NewsWebsite, DataWebsite, WebsiteBase):
  158. def __init__(self, app: Flask, db: DB):
  159. super(Website, self).__init__(app, db)