Przeglądaj źródła

feat: 系统初始化

SongZihuan 3 lat temu
rodzic
commit
6452098ac6
9 zmienionych plików z 318 dodań i 24 usunięć
  1. 0 7
      app/ranking.py
  2. 15 0
      conf/args.py
  3. 4 9
      conf/sql.py
  4. 78 4
      main.py
  5. 62 0
      setup.py
  6. 119 0
      setup.sql
  7. 2 4
      sql/mysql_db.py
  8. 0 0
      steup.py
  9. 38 0
      tool/thread_.py

+ 0 - 7
app/ranking.py

@@ -19,13 +19,6 @@ class RankWebsite:
                                f"WHERE IsManager = 0 "
                                f"ORDER BY Reputation {order_by}, Score {order_by}, UserID {order_by} "
                                f"LIMIT 200;"))
-
-        print(f"SELECT UserID, Name, Score, Reputation "
-              f"FROM user "
-              f"WHERE IsManager = 0 "
-              f"ORDER BY Reputation {order_by}, Score {order_by}, UserID {order_by}"
-              f"LIMIT 200;")
-
         if cur is None:
             return None
         res = []

+ 15 - 0
conf/args.py

@@ -0,0 +1,15 @@
+import argparse
+
+parser = argparse.ArgumentParser()
+parser.add_argument("--mysql_url", nargs=1, required=True, type=str, help="MySQL-URL")
+parser.add_argument("--mysql_name", nargs=1, required=True, type=str, help="MySQL-用户名")
+parser.add_argument("--mysql_passwd", nargs=1, required=True, type=str, help="MySQL-密码")
+
+parser.add_argument("--program", nargs=1, required=True, type=str, choices=["setup",
+                                                                            "garbage",
+                                                                            "ranking",
+                                                                            "manager",
+                                                                            "ranking_website"],
+                    help="选择启动的程序")
+
+p_args = parser.parse_args()

+ 4 - 9
conf/sql.py

@@ -1,11 +1,6 @@
-import sys
-import warnings
-
-if len(sys.argv) != 4:
-    warnings.warn(f"参数不足: {len(sys.argv)}")
-    raise exit(1)
+from . import args
 
 database = 'MySQL'
-mysql_url = sys.argv[1]
-mysql_name = sys.argv[2]
-mysql_passwd = sys.argv[3]
+mysql_url = args.p_args.mysql_url[0]
+mysql_name = args.p_args.mysql_name[0]
+mysql_passwd = args.p_args.mysql_passwd[0]

+ 78 - 4
main.py

@@ -1,5 +1,79 @@
+"""
+入口程序
+包都按需导入, 不需要使用的模块则不会导入
+因此安装过程可以选用不完整安装
+但依赖模块都都是固定的
+"""
+
+import sys
+
 import conf
-import app.ranking as ranking_website
-import tk_ui.ranking as ranking_station
-import tk_ui.station as garbage_station
-import tk_ui.admin as admin_station
+from conf.args import p_args
+
+program_name = p_args.program[0]
+if program_name == "setup":  # setup程序不需要数据库链接等操作
+    import os
+    import sys
+
+    __main = os.path.dirname(os.path.abspath(__file__))
+    res = os.system(f"{sys.executable} {os.path.join(__main, 'setup.py')} "
+                    f"--mysql_url={conf.mysql_url} "
+                    f"--mysql_name={conf.mysql_name} "
+                    f"--mysql_passwd={conf.mysql_passwd} "
+                    f"--program=setup")
+    if res != 0:
+        print("初始化程序加载失败", file=sys.stderr)
+        exit(1)
+    exit(0)
+
+from sql.db import DB
+
+mysql = DB()
+
+
+def can_not_load(name):
+    print(f"无法加载 {name} 模块, 该系统可能不存在", file=sys.stderr)
+
+
+if program_name == "garbage":
+    try:
+        from equipment.scan import HGSCapture, HGSQRCoder
+        import tk_ui.station as garbage_station
+    except ImportError:
+        can_not_load("垃圾站系统")
+        sys.exit(1)
+
+    cap = HGSCapture()
+    qr = HGSQRCoder(cap)
+    station = garbage_station.GarbageStation(mysql, cap, qr)
+    station.mainloop()
+elif program_name == "ranking":
+    try:
+        import tk_ui.ranking as ranking_station
+    except ImportError:
+        can_not_load("排行榜系统")
+        sys.exit(1)
+
+    station = ranking_station.RankingStation(mysql)
+    station.mainloop()
+elif program_name == "manager":
+    try:
+        import tk_ui.admin as admin_station
+    except ImportError:
+        can_not_load("管理员系统")
+        sys.exit(1)
+
+    station = admin_station.AdminStation(mysql)
+    station.mainloop()
+elif program_name == "ranking_website":
+    try:
+        import app.ranking as ranking_website
+    except ImportError:
+        can_not_load("在线排行榜服务")
+        sys.exit(1)
+
+    web, app = ranking_website.creat_ranking_website(mysql)
+    web.run()
+else:
+    can_not_load(program_name)
+    sys.exit(1)

+ 62 - 0
setup.py

@@ -0,0 +1,62 @@
+import os
+import sys
+import warnings
+
+try:
+    __import__("pip")
+except ImportError:
+    warnings.warn("The pip not found")
+    raise
+
+__setup = os.path.dirname(os.path.abspath(__file__))
+
+
+def check_import(package, pip):
+    try:
+        __import__(package)
+    except ImportError:
+        res = os.system(f"{sys.executable} -m pip install {pip}")
+        if res != 0:
+            print(f"{pip} 依赖安装失败")
+            exit(1)
+
+
+check_import("cv2", "opencv-python")  # 图像处理
+check_import("qrcode", "qrcode")  # 二维码生成
+check_import("pymysql", "PyMySQL")  # 连接 MySQL服务器
+check_import("cryptography", "cryptography")  # 链接 MySQL 服务器时加密
+check_import("flask", "Flask")  # 网页服务
+check_import("PIL", "Pillow")  # 图片处理
+
+import pymysql
+import conf
+
+mysql_url = conf.mysql_url
+mysql_name = conf.mysql_name
+mysql_passwd = conf.mysql_passwd
+
+sql = pymysql.connect(user=mysql_name, password=mysql_passwd, host=mysql_url)
+cursor = sql.cursor()
+with open(os.path.join(__setup, "setup.sql"), "r", encoding='utf-8') as f:
+    all_sql = f.read().split(';')
+    for s in all_sql:
+        if s.strip() == "":
+            continue
+        cursor.execute(f"{s};")
+    sql.commit()
+
+admin_passwd = input("Enter Admin Passwd: ")
+admin_phone = ""
+while len(admin_phone) != 11:
+    admin_phone = input("Enter Admin Phone[len = 11]: ")
+
+from tool.login import create_uid
+from tool.time_ import mysql_time
+
+# 生成基本 admin 用户
+uid = create_uid("admin", admin_passwd, admin_phone)
+cursor.execute(f"INSERT INTO user(UserID, Name, IsManager, Phone, Score, Reputation, CreateTime) "
+               f"VALUES ('{uid}', 'admin', 1, '{admin_phone}', 10, 300, {mysql_time()});")
+sql.commit()
+cursor.close()
+sql.close()

+ 119 - 0
setup.sql

@@ -0,0 +1,119 @@
+DROP DATABASE IF EXISTS hgssystem;
+CREATE DATABASE IF NOT EXISTS hgssystem;
+USE hgssystem;
+
+CREATE TABLE IF NOT EXISTS user -- 创建用户表
+(
+    ID         INT PRIMARY KEY AUTO_INCREMENT,
+    UserID     char(34)    NOT NULL UNIQUE,
+    Name       varchar(50) NOT NULL,
+    IsManager  bit         NOT NULL DEFAULT 0,
+    Phone      char(11)    NOT NULL,
+    Score      INT         NOT NULL,
+    Reputation INT         NOT NULL,
+    CreateTime DATETIME    NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+CREATE TABLE IF NOT EXISTS garbage -- 创建普通垃圾表
+(
+    GarbageID   INT PRIMARY KEY AUTO_INCREMENT,
+    CreateTime  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+    Flat        TINYINT  NOT NULL DEFAULT 0,
+    UserID      char(34),
+    UseTime     DATETIME,
+    GarbageType TINYBLOB,
+    Location    VARCHAR(50),
+    CheckResult BIT,
+    CheckerID   char(34),
+    FOREIGN KEY (UserID) REFERENCES user (UserID),
+    FOREIGN KEY (CheckerID) REFERENCES user (UserID)
+);
+
+-- 创建视图
+
+DROP VIEW IF EXISTS garbage_n;
+CREATE VIEW garbage_n AS
+SELECT GarbageID, CreateTime
+FROM garbage
+WHERE Flat = 0;
+
+DROP VIEW IF EXISTS garbage_c;
+CREATE VIEW garbage_c AS
+SELECT GarbageID, CreateTime, UserID, UseTime, GarbageType, Location
+FROM garbage
+WHERE Flat = 1;
+
+DROP VIEW IF EXISTS garbage_u;
+CREATE VIEW garbage_u AS
+SELECT GarbageID,
+       CreateTime,
+       UserID,
+       UseTime,
+       GarbageType,
+       Location,
+       CheckerID,
+       CheckResult
+FROM garbage
+WHERE Flat = 2;
+
+DROP VIEW IF EXISTS garbage_time;
+CREATE VIEW garbage_time AS
+SELECT GarbageID, UserID, UseTime
+FROM garbage
+WHERE Flat = 1
+   OR Flat = 2;
+
+DROP VIEW IF EXISTS garbage_user;
+CREATE VIEW garbage_user AS
+SELECT GarbageID          AS GarbageID,
+       garbage.CreateTime AS CreateTime,
+       garbage.UserID     AS UserID,
+       user.Name          AS UserName,
+       user.Phone         AS UserPhone,
+       user.Score         AS UserScore,
+       user.Reputation    AS UserReputation,
+       UseTime            AS UseTime,
+       GarbageType        AS GarbageType,
+       Location           AS Location,
+       CheckResult        AS CheckResult,
+       CheckerID          AS CheckerID
+FROM garbage
+         LEFT JOIN user on garbage.UserID = user.UserID;
+
+DROP VIEW IF EXISTS garbage_checker;
+CREATE VIEW garbage_checker AS
+SELECT GarbageID          AS GarbageID,
+       garbage.CreateTime AS CreateTime,
+       garbage.UserID     AS UserID,
+       UseTime            AS UseTime,
+       GarbageType        AS GarbageType,
+       Location           AS Location,
+       CheckResult        AS CheckResult,
+       CheckerID          AS CheckerID,
+       user.Name          AS CheckerName,
+       user.Phone         AS CheckerPhone,
+       user.Score         AS CheckerScore,
+       user.Reputation    AS CheckerReputation
+FROM garbage
+         LEFT JOIN user on garbage.CheckerID = user.UserID;
+
+DROP VIEW IF EXISTS garbage_checker_user;
+CREATE VIEW garbage_checker_user AS
+SELECT garbage_user.GarbageID       AS GarbageID,
+       garbage_user.CreateTime      AS CreateTime,
+
+       garbage_user.UserID          AS UserID,
+       garbage_user.UserName        AS UserName,
+       garbage_user.UserPhone       AS UserPhone,
+       garbage_user.UserScore       AS UserScore,
+       garbage_user.UserReputation  AS UserReputation,
+
+       garbage_user.UseTime         AS UseTime,
+       garbage_user.GarbageType     AS GarbageType,
+       garbage_user.Location        AS Location,
+       garbage_user.CheckResult     AS CheckResult,
+       garbage_user.CheckerID       AS CheckerID,
+       garbage_checker.CheckerName  AS CheckerName,
+       garbage_checker.CheckerPhone AS CheckerPhone
+FROM garbage_user
+         LEFT JOIN garbage_checker on garbage_user.GarbageID = garbage_checker.GarbageID;

+ 2 - 4
sql/mysql_db.py

@@ -11,13 +11,10 @@ class MysqlDB(Database):
         try:
             self._db = pymysql.connect(user=name, password=passwd, host=host, database="hgssystem")
         except pymysql.err.OperationalError:
-            raise DBException
+            raise
         self._cursor = self._db.cursor()
         self._lock = threading.RLock()
 
-    def __del__(self):
-        self.close()
-
     def close(self):
         if self._cursor is not None:
             self._cursor.close()
@@ -59,6 +56,7 @@ class MysqlDB(Database):
             self._cursor.execute(sql)
         except pymysql.MySQLError:
             self._db.rollback()
+            raise
             return None
         finally:
             self._db.commit()

+ 0 - 0
steup.py


+ 38 - 0
tool/thread_.py

@@ -0,0 +1,38 @@
+import threading
+import traceback
+
+
+class Threading(threading.Thread):
+    """
+    子线程
+    """
+
+    def __init__(self, func, *args, start_now: bool = True):
+        """
+        :param func: 子线程函数
+        :param args: 子线程参数
+        :param start_now: 是否马上运行 (否则要回调.start函数)
+        """
+        threading.Thread.__init__(self)
+        self.func = func
+        self.args = args
+        self.result = None
+
+        if start_now:
+            self.start()
+
+    def run(self):
+        try:
+            self.result = self.func(*self.args)
+        except:
+            traceback.print_exc()
+        finally:
+            del self.func, self.args
+
+    def wait_event(self) -> any:
+        """
+        等待线程结束
+        :return: 线程函数的返回值
+        """
+        self.join()
+        return self.result