瀏覽代碼

feat: 数据库更新

SongZihuan 3 年之前
父節點
當前提交
538c266a90
共有 8 個文件被更改,包括 499 次插入174 次删除
  1. 31 14
      control/admin.py
  2. 108 7
      control/admin_event.py
  3. 11 11
      control/admin_menu.py
  4. 113 33
      control/admin_program.py
  5. 1 1
      control/event.py
  6. 186 91
      sql/garbage.py
  7. 38 17
      sql/user.py
  8. 11 0
      tool/time_.py

+ 31 - 14
control/admin.py

@@ -10,18 +10,17 @@ from equipment.scan_garbage import write_gid_qr
 from equipment.scan_user import write_uid_qr, write_all_uid_qr
 from event import TkEventMain
 from sql.db import DB, search_from_garbage_checker_user
-from sql.garbage import (create_new_garbage, search_from_garbage_view,
+from sql.garbage import (create_new_garbage, search_garbage_by_fields, search_from_garbage_view,
                          del_garbage, del_garbage_not_use, del_garbage_wait_check, del_garbage_has_check,
-
                          del_garbage_where_scan_not_use, del_garbage_where_scan_wait_check,
                          del_garbage_where_scan_has_check,
-
                          del_garbage_where_not_use, del_garbage_where_wait_check, del_garbage_where_has_check,
-
-                         del_garbage_not_use_many, del_all_garbage, del_all_garbage_scan)
+                         del_all_garbage, del_all_garbage_scan,
+                         update_garbage_check, update_garbage_type)
 
 from sql.user import (create_new_user, del_user, del_user_from_where, del_user_from_where_scan,
-                      search_user_by_fields, search_from_user_view)
+                      search_user_by_fields, search_from_user_view,
+                      update_user_score, update_user_reputation)
 from tool.tk import make_font
 from tool.type_ import *
 
@@ -30,11 +29,11 @@ class AdminStationException(Exception):
     ...
 
 
-class createGarbageError(AdminStationException):
+class CreateGarbageError(AdminStationException):
     ...
 
 
-class createUserError(AdminStationException):
+class CreateUserError(AdminStationException):
     ...
 
 
@@ -52,7 +51,7 @@ class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
         for _ in range(num):
             gar = create_new_garbage(self._db)
             if gar is None:
-                raise createGarbageError
+                raise CreateGarbageError
             if path is not None:
                 res = write_gid_qr(gar.get_gid(), path, self._db)
                 re.append(res)
@@ -68,7 +67,7 @@ class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
         for i in user_list:
             user = create_new_user(i[0], i[1], i[2], manager, self._db)
             if user is None:
-                raise createUserError
+                raise CreateUserError
             re.append(user)
         return re
 
@@ -120,9 +119,6 @@ class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
     def del_all_garbage(self) -> int:
         return del_all_garbage(self._db)
 
-    def del_garbage_many(self, from_: gid_t, to_: gid_t) -> int:
-        return del_garbage_not_use_many(from_, to_, self._db)
-
     def del_user(self, uid: uid_t) -> bool:
         return del_user(uid, self._db)
 
@@ -138,12 +134,33 @@ class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
     def search_user_advanced(self, columns, sql):
         return search_from_user_view(columns, sql, self._db)
 
+    def search_garbage(self, columns, key_values: dict):
+        return search_garbage_by_fields(columns, **key_values, db=self._db)
+
     def search_garbage_advanced(self, columns, sql):
         return search_from_garbage_view(columns, sql, self._db)
 
     def search_advanced(self, columns, sql):
         return search_from_garbage_checker_user(columns, sql, self._db)
 
+    def update_user_score(self, score: score_t, where: str) -> int:
+        return update_user_score(where, score, self._db)
+
+    def update_user_reputation(self, reputation: score_t, where: str) -> int:
+        return update_user_reputation(where, reputation, self._db)
+
+    def update_garbage_type(self, type_: int, where: str):
+        return update_garbage_type(where, type_, self._db)
+
+    def update_garbage_check(self, check_: str, where: str):
+        if check_ == 'pass':
+            check = True
+        elif check_ == 'fail':
+            check = False
+        else:
+            return -1
+        return update_garbage_check(where, check, self._db)
+
     @abc.abstractmethod
     def login_call(self):
         ...
@@ -298,7 +315,7 @@ class AdminStation(AdminStationBase):
         bt_main.place(relx=0.02, rely=0.86, relwidth=0.96, relheight=0.06)
 
         bt_back: tk.Button = self._win_ctrl_button[0]
-        bt_back['text'] = 'back'
+        bt_back['text'] = 'Back'
         bt_back['font'] = title_font_bold
         bt_back['state'] = 'disable'
         bt_back['command'] = lambda: self.__to_back_menu()

+ 108 - 7
control/admin_event.py

@@ -11,6 +11,7 @@ from event import TkEventBase, TkThreading
 import admin
 import admin_program
 
+
 class AdminEventBase(TkEventBase):
     def __init__(self, station):
         super(AdminEventBase, self).__init__()
@@ -50,12 +51,12 @@ class TestProgressEvent(AdminEventBase):
         self.thread = TkThreading(self.func, 5)
 
 
-class createUserEvent(AdminEventBase):
+class CreateUserEvent(AdminEventBase):
     def func(self, name, passwd, phone, is_manager):
         return self.station.create_user(name, passwd, phone, is_manager)
 
     def __init__(self, station):
-        super(createUserEvent, self).__init__(station)
+        super(CreateUserEvent, self).__init__(station)
         self._name = None
 
     def start(self, name, passwd, phone, is_manager):
@@ -66,18 +67,18 @@ class createUserEvent(AdminEventBase):
     def done_after_event(self):
         res: Optional[User] = self.thread.wait_event()
         if res is None:
-            self.station.show_msg("createUserError", f"Can't not create user: {self._name}", "Warning")
+            self.station.show_msg("CreateUserError", f"Can't not create user: {self._name}", "Warning")
         else:
             name = res.get_name()
-            self.station.show_msg("createUser", f"create user {name} success")
+            self.station.show_msg("CreateUser", f"create user {name} success")
 
 
-class createGarbageEvent(AdminEventBase):
+class CreateGarbageEvent(AdminEventBase):
     def func(self, path, count):
         return self.station.create_garbage(path, count)
 
     def __init__(self, station):
-        super(createGarbageEvent, self).__init__(station)
+        super(CreateGarbageEvent, self).__init__(station)
         self._name = None
 
     def start(self, path, count):
@@ -86,7 +87,7 @@ class createGarbageEvent(AdminEventBase):
 
     def done_after_event(self):
         res: list[tuple[str, Optional[GarbageBag]]] = self.thread.wait_event()
-        self.station.show_msg("createGarbage", f"create {len(res)} garbage finished.")
+        self.station.show_msg("CreateGarbage", f"create {len(res)} garbage finished.")
 
 
 class DelUserEvent(AdminEventBase):
@@ -304,6 +305,30 @@ class SearchUserAdvancedEvent(AdminEventBase):
             self.program.view.insert('', 'end', values=i)
 
 
+class SearchGarbageEvent(AdminEventBase):
+    def func(self, columns, key_values: dict):
+        return self.station.search_garbage(columns, key_values)
+
+    def __init__(self, station):
+        super(SearchGarbageEvent, self).__init__(station)
+        self.program: Optional[admin_program.SearchUserProgram] = None
+
+    def start(self, columns, key_values: dict, program):
+        self.thread = TkThreading(self.func, columns, key_values)
+        self.program = program
+        return self
+
+    def done_after_event(self):
+        res: list[list] = self.thread.wait_event()
+        if res is None or self.program is None:
+            self.station.show_msg("Search Garbage Error", f"Search error")
+            return
+        for i in self.program.view.get_children():
+            self.program.view.delete(i)
+        for i in res:
+            self.program.view.insert('', 'end', values=i)
+
+
 class SearchGarbageAdvancedEvent(AdminEventBase):
     def func(self, columns, sql):
         return self.station.search_garbage_advanced(columns, sql)
@@ -350,3 +375,79 @@ class SearchAdvancedEvent(AdminEventBase):
             self.program.view.delete(i)
         for i in res:
             self.program.view.insert('', 'end', values=i)
+
+
+class UpdateUserScoreEvent(AdminEventBase):
+    def func(self, score, where):
+        return self.station.update_user_score(score, where)
+
+    def __init__(self, station):
+        super(UpdateUserScoreEvent, self).__init__(station)
+
+    def start(self, score, where):
+        self.thread = TkThreading(self.func, score, where)
+        return self
+
+    def done_after_event(self):
+        res: int = self.thread.wait_event()
+        if res == -1:
+            self.station.show_msg("UpdateError", f"Update user score error")
+        else:
+            self.station.show_msg("Update", f"Update {res} user score success")
+
+
+class UpdateUserReputationEvent(AdminEventBase):
+    def func(self, reputation, where):
+        return self.station.update_user_reputation(reputation, where)
+
+    def __init__(self, station):
+        super(UpdateUserReputationEvent, self).__init__(station)
+
+    def start(self, reputation, where):
+        self.thread = TkThreading(self.func, reputation, where)
+        return self
+
+    def done_after_event(self):
+        res: int = self.thread.wait_event()
+        if res == -1:
+            self.station.show_msg("UpdateError", f"Update user reputation error")
+        else:
+            self.station.show_msg("Update", f"Update {res} user reputation success")
+
+
+class UpdateGarbageTypeEvent(AdminEventBase):
+    def func(self, type_, where):
+        return self.station.update_garbage_type(type_, where)
+
+    def __init__(self, station):
+        super(UpdateGarbageTypeEvent, self).__init__(station)
+
+    def start(self, type_, where):
+        self.thread = TkThreading(self.func, type_, where)
+        return self
+
+    def done_after_event(self):
+        res: int = self.thread.wait_event()
+        if res == -1:
+            self.station.show_msg("UpdateError", f"Update garbage type error")
+        else:
+            self.station.show_msg("Update", f"Update {res} garbage type success")
+
+
+class UpdateGarbageCheckEvent(AdminEventBase):
+    def func(self, check, where):
+        return self.station.update_garbage_check(check, where)
+
+    def __init__(self, station):
+        super(UpdateGarbageCheckEvent, self).__init__(station)
+
+    def start(self, check, where):
+        self.thread = TkThreading(self.func, check, where)
+        return self
+
+    def done_after_event(self):
+        res: int = self.thread.wait_event()
+        if res == -1:
+            self.station.show_msg("UpdateError", f"Update garbage check result error")
+        else:
+            self.station.show_msg("Update", f"Update {res} garbage check result success")

+ 11 - 11
control/admin_menu.py

@@ -49,7 +49,7 @@ class MainMenu(AdminMenu):
     def __init__(self, station, win, color):
         super().__init__(station, win, color, "Main")
         self.btn: List[tk.Button] = [tk.Button(self.frame) for _ in range(5)]
-        self.btn_name = ["create", "Delete", "Search", "Update", "Logout"]
+        self.btn_name = ["Create", "Delete", "Search", "Update", "Logout"]
 
     def conf_gui(self, color: str, n: int = 1):
         super().conf_gui(color, n)
@@ -60,7 +60,7 @@ class MainMenu(AdminMenu):
         self.btn[4]['command'] = lambda: self.logout_command()
 
     def create_command(self):
-        self.station.to_menu("create")
+        self.station.to_menu("Create")
 
     def delete_command(self):
         self.station.to_menu("Delete")
@@ -75,11 +75,11 @@ class MainMenu(AdminMenu):
         self.station.logout()
 
 
-class createMenu(AdminMenu):
+class CreateMenu(AdminMenu):
     def __init__(self, station, win, color):
-        super().__init__(station, win, color, "create")
-        self.btn: List[tk.Button] = [tk.Button(self.frame) for _ in range(4)]
-        self.btn_name = ["NormalUser", "AutoNormalUser", "ManagerUser", "Garbage"]
+        super().__init__(station, win, color, "Create")
+        self.btn: List[tk.Button] = [tk.Button(self.frame) for _ in range(6)]
+        self.btn_name = ["NormalUser", "AutoNormalUser", "ManagerUser", "Garbage", "ExportUser", "ExportGarbage"]
 
     def conf_gui(self, color: str, n: int = 1):
         super().conf_gui(color, n)
@@ -89,16 +89,16 @@ class createMenu(AdminMenu):
         self.btn[3]['command'] = lambda: self.create_garbage()
 
     def create_normal_user(self):
-        self.station.to_program("createNormalUser")
+        self.station.to_program("CreateNormalUser")
 
     def create_auto_user(self):
-        self.station.to_program("createAutoNormalUser")
+        self.station.to_program("CreateAutoNormalUser")
 
     def create_manager_user(self):
-        self.station.to_program("createManagerUser")
+        self.station.to_program("CreateManagerUser")
 
     def create_garbage(self):
-        self.station.to_program("createGarbage")
+        self.station.to_program("CreateGarbage")
 
 
 class DeleteMenu(AdminMenu):
@@ -201,4 +201,4 @@ class StatisticsMenu(AdminMenu):
         super().conf_gui(color, n)
 
 
-all_menu = [MainMenu, createMenu, DeleteMenu, SearchMenu, UpdateMenu, StatisticsMenu]
+all_menu = [MainMenu, CreateMenu, DeleteMenu, SearchMenu, UpdateMenu, StatisticsMenu]

+ 113 - 33
control/admin_program.py

@@ -88,7 +88,7 @@ class WelcomeProgram(AdminProgram):
         set_tk_disable_from_list(self.btn, flat='normal')
 
 
-class createUserProgramBase(AdminProgram):
+class CreateUserProgramBase(AdminProgram):
     def __init__(self, station, win, color, title: str):
         super().__init__(station, win, color, title)
 
@@ -136,7 +136,7 @@ class createUserProgramBase(AdminProgram):
             height += 0.30
 
         for btn, text, x, func in zip(self.btn,
-                                      ["create", "GetUID"],
+                                      ["Create", "GetUID"],
                                       [0.2, 0.6],
                                       [lambda: self.create_by_name(), lambda: self.get_uid()]):
             btn['font'] = btn_font
@@ -161,7 +161,7 @@ class createUserProgramBase(AdminProgram):
         if res is None:
             return
         name, passwd, phone = res
-        event = tk_event.createUserEvent(self.station).start(name, passwd, phone, self.is_manager)
+        event = tk_event.CreateUserEvent(self.station).start(name, passwd, phone, self.is_manager)
         self.station.push_event(event)
 
     def get_uid(self):
@@ -181,20 +181,20 @@ class createUserProgramBase(AdminProgram):
         set_tk_disable_from_list(self.enter, flat='normal')
 
 
-class createNormalUserProgram(createUserProgramBase):
+class CreateNormalUserProgram(CreateUserProgramBase):
     def __init__(self, station, win, color):
-        super(createNormalUserProgram, self).__init__(station, win, color, "createNormalUser")
+        super(CreateNormalUserProgram, self).__init__(station, win, color, "CreateNormalUser")
 
 
-class createManagerUserProgram(createUserProgramBase):
+class CreateManagerUserProgram(CreateUserProgramBase):
     def __init__(self, station, win, color):
-        super(createManagerUserProgram, self).__init__(station, win, color, "createManagerUser")
+        super(CreateManagerUserProgram, self).__init__(station, win, color, "CreateManagerUser")
         self._conf("#4b5cc4", True)
 
 
-class createAutoNormalUserProgram(AdminProgram):
+class CreateAutoNormalUserProgram(AdminProgram):
     def __init__(self, station, win, color):
-        super().__init__(station, win, color, "createAutoNormalUser")
+        super().__init__(station, win, color, "CreateAutoNormalUser")
 
         self.enter_frame = tk.Frame(self.frame)
         self.title: tk.Label = tk.Label(self.enter_frame)
@@ -231,7 +231,7 @@ class createAutoNormalUserProgram(AdminProgram):
         self.enter.place(relx=0.30, rely=0.2, relwidth=0.60, relheight=0.48)
 
         self.btn['font'] = btn_font
-        self.btn['text'] = "create"
+        self.btn['text'] = "Create"
         self.btn['bg'] = conf.tk_btn_bg
         self.btn['command'] = lambda: self.create_user()
         self.btn.place(relx=0.4, rely=0.7, relwidth=0.2, relheight=0.08)
@@ -240,7 +240,7 @@ class createAutoNormalUserProgram(AdminProgram):
         phone = self.var.get()
         if len(phone) != 11:
             self.station.show_msg("UserInfoError", "Please, enter Phone(11)")
-        event = tk_event.createUserEvent(self.station).start(None, None, phone, False)
+        event = tk_event.CreateUserEvent(self.station).start(None, None, phone, False)
         self.station.push_event(event)
 
     def set_disable(self):
@@ -252,9 +252,9 @@ class createAutoNormalUserProgram(AdminProgram):
         self.enter['state'] = 'normal'
 
 
-class createGarbageProgram(AdminProgram):
+class CreateGarbageProgram(AdminProgram):
     def __init__(self, station, win, color):
-        super().__init__(station, win, color, "createGarbage")
+        super().__init__(station, win, color, "CreateGarbage")
 
         self.enter_frame = tk.Frame(self.frame)
         self.title: List[tk.Label] = [tk.Label(self.enter_frame), tk.Label(self.enter_frame)]
@@ -295,7 +295,7 @@ class createGarbageProgram(AdminProgram):
             height += 0.43
 
         for btn, text, x, func in zip([self.create_btn, self.file_btn],
-                                      ["create", "ChoosePath"],
+                                      ["Create", "ChoosePath"],
                                       [0.2, 0.6],
                                       [lambda: self.create_garbage(), lambda: self.choose_file()]):
             btn['font'] = btn_font
@@ -319,7 +319,7 @@ class createGarbageProgram(AdminProgram):
             path = self.var[1].get()
             if len(path) == 0:
                 path = None
-            event = tk_event.createGarbageEvent(self.station).start(path, count)
+            event = tk_event.CreateGarbageEvent(self.station).start(path, count)
             self.station.push_event(event)
 
     def set_disable(self):
@@ -957,11 +957,13 @@ class SearchGarbageProgram(SearchBaseProgram):
         super().__init__(station, win, color, "SearchGarbage")
 
         self.enter_frame = tk.Frame(self.frame)
-        self.title: List[tk.Label] = [tk.Label(self.enter_frame) for _ in range(7)]
-        self.enter: List[tk.Entry] = [tk.Entry(self.enter_frame) for _ in range(7)]
-        self.var: List[tk.Variable] = [tk.StringVar() for _ in range(7)]
+        self.title: List[tk.Label] = [tk.Label(self.enter_frame) for _ in range(8)]
+        self.enter: List[tk.Entry] = [tk.Entry(self.enter_frame) for _ in range(8)]
+        self.var: List[tk.Variable] = [tk.StringVar() for _ in range(8)]
         self.check: List[Tuple[tk.Checkbutton, tk.Variable]] = [(tk.Checkbutton(self.enter_frame), tk.IntVar())
-                                                                for _ in range(7)]
+                                                                for _ in range(8)]
+        self._columns = ["GarbageID", "UserID", "CheckerID", "CreateTime", "UseTime", "Location", "GarbageType",
+                         "CheckResult"]
         self.btn: tk.Button = tk.Button(self.frame)
         self.__conf_font()
 
@@ -978,11 +980,11 @@ class SearchGarbageProgram(SearchBaseProgram):
         self.enter_frame['bg'] = "#7bbfea"
         self.enter_frame['bd'] = 5
         self.enter_frame['relief'] = "ridge"
-        self.enter_frame.place(relx=0.2, rely=0.0, relwidth=0.6, relheight=0.45)
+        self.enter_frame.place(relx=0.2, rely=0.0, relwidth=0.6, relheight=0.47)
 
         height = 0.02
         for lb, text, enter, var, check in zip(self.title,
-                                               ["GarbageID:", "UserID:", "CheckerID:", "UseTime:",
+                                               ["GarbageID:", "UserID:", "CheckerID:", "CreateTime:", "UseTime:",
                                                 "Location:", "GarbageType:", "CheckResult:"],
                                                self.enter, self.var, self.check):
             lb['font'] = title_font
@@ -999,18 +1001,33 @@ class SearchGarbageProgram(SearchBaseProgram):
             check[0]['variable'] = check[1]
             check[1].set(1)
 
-            lb.place(relx=0.01, rely=height, relwidth=0.30, relheight=0.12)
-            enter.place(relx=0.35, rely=height, relwidth=0.55, relheight=0.12)
-            check[0].place(relx=0.92, rely=height, relwidth=0.04, relheight=0.12)
-            height += 0.14
+            lb.place(relx=0.01, rely=height, relwidth=0.30, relheight=0.10)
+            enter.place(relx=0.35, rely=height, relwidth=0.55, relheight=0.10)
+            check[0].place(relx=0.92, rely=height, relwidth=0.04, relheight=0.10)
+            height += 0.121
 
         self.btn['font'] = btn_font
         self.btn['bg'] = conf.tk_btn_bg
         self.btn['text'] = "Search"
+        self.btn['command'] = self.search_user
         self.btn.place(relx=0.4, rely=0.9, relwidth=0.2, relheight=0.08)
 
-        columns = ["GarbageID", "UserID", "CheckerID", "UseTime", "Location", "GarbageType", "CheckResult"]
-        self.conf_view_gui(columns, relx=0.05, rely=0.47, relwidth=0.9, relheight=0.40, x_scroll=0.07)
+        self.conf_view_gui(self._columns, relx=0.05, rely=0.49, relwidth=0.9, relheight=0.38, x_scroll=0.07)
+
+    def search_user(self):
+        keys = ["gid", "uid", "cuid", "create_time", "use_time", "loc", "type_", "check"]
+        key_values = {}
+        for i, key in enumerate(keys):
+            ck = self.check[i][1].get()
+            if ck:
+                res = self.enter[i].get()
+                if len(res) > 0:
+                    key_values[key] = res
+                    continue
+            key_values[key] = None
+
+        event = tk_event.SearchGarbageEvent(self.station).start(self._columns, key_values, self)
+        self.station.push_event(event)
 
     def set_disable(self):
         self.btn['state'] = 'disable'
@@ -1024,7 +1041,7 @@ class SearchGarbageProgram(SearchBaseProgram):
 class SearchGarbageAdvancedProgram(SearchAdvancedProgramBase):
     def __init__(self, station, win, color):
         super(SearchGarbageAdvancedProgram, self).__init__(station, win, color, "SearchGarbageAdvanced")
-        columns = ["GarbageID", "UserID", "CheckerID", "createTime", "UseTime", "Location", "GarbageType",
+        columns = ["GarbageID", "UserID", "CheckerID", "CreateTime", "UseTime", "Location", "GarbageType",
                    "CheckResult"]
         self._conf(columns, '#d1923f')
 
@@ -1118,14 +1135,23 @@ class UpdateUserProgramBase(AdminProgram):
             enter_w.place(relx=0.35, rely=height, relwidth=0.60, relheight=0.35)
             height += 0.43
 
-        for btn, text in zip(self.btn, ["Update Advanced", "Update By UserID"]):
+        for btn, text, func in zip(self.btn,
+                                   ["Update Advanced", "Update By UserID"],
+                                   [self.update_by_where, self.update_by_uid]):
             btn['font'] = btn_font
             btn['text'] = text
             btn['bg'] = conf.tk_btn_bg
+            btn['command'] = func
 
         self.btn[0].place(relx=0.55, rely=0.40, relwidth=0.25, relheight=0.08)
         self.btn[1].place(relx=0.55, rely=0.78, relwidth=0.25, relheight=0.08)
 
+    def update_by_uid(self):
+        ...
+
+    def update_by_where(self):
+        ...
+
     def set_disable(self):
         set_tk_disable_from_list(self.btn)
         set_tk_disable_from_list(self.enter)
@@ -1140,12 +1166,36 @@ class UpdateUserScoreBase(UpdateUserProgramBase):
         super(UpdateUserScoreBase, self).__init__(station, win, color, "UpdateScore")
         self._conf(["UserID:", "Score:"], "#afdfe4")
 
+    def update_by_uid(self):
+        uid = self.enter[0].get()
+        score = int(self.enter[1].get())
+        event = tk_event.UpdateUserScoreEvent(self.station).start(score, f"UserID='{uid}'")
+        self.station.push_event(event)
+
+    def update_by_where(self):
+        where = self.where_enter[0].get()
+        score = int(self.where_enter[1].get())
+        event = tk_event.UpdateUserScoreEvent(self.station).start(score, where)
+        self.station.push_event(event)
+
 
 class UpdateUserReputationBase(UpdateUserProgramBase):
     def __init__(self, station, win, color):
         super(UpdateUserReputationBase, self).__init__(station, win, color, "UpdateReputation")
         self._conf(["UserID:", "Reputation:"], "#f8aba6")
 
+    def update_by_uid(self):
+        uid = self.enter[0].get()
+        reputation = int(self.enter[1].get())
+        event = tk_event.UpdateUserReputationEvent(self.station).start(reputation, f"UserID='{uid}'")
+        self.station.push_event(event)
+
+    def update_by_where(self):
+        where = self.where_enter[0].get()
+        reputation = int(self.where_enter[1].get())
+        event = tk_event.UpdateUserReputationEvent(self.station).start(reputation, where)
+        self.station.push_event(event)
+
 
 class UpdateGarbageTypeProgram(AdminProgram):
     def __init__(self, station, win, color):
@@ -1217,14 +1267,29 @@ class UpdateGarbageTypeProgram(AdminProgram):
             lb.place(relx=0.02, rely=0.2, relwidth=0.25, relheight=0.48)
             enter.place(relx=0.30, rely=0.2, relwidth=0.60, relheight=0.48)
 
-        for btn, text in zip(self.btn, ["Update Advanced", "Update By GarbageID"]):
+        for btn, text, func in zip(self.btn,
+                                   ["Update Advanced", "Update By GarbageID"],
+                                   [self.update_by_where, self.update_by_gid]):
             btn['font'] = btn_font
             btn['text'] = text
             btn['bg'] = conf.tk_btn_bg
+            btn['command'] = func
 
         self.btn[0].place(relx=0.55, rely=0.43, relwidth=0.25, relheight=0.08)
         self.btn[1].place(relx=0.55, rely=0.83, relwidth=0.25, relheight=0.08)
 
+    def update_by_gid(self):
+        gid = self.enter.get()
+        type_ = self.var[1].get()
+        event = tk_event.UpdateGarbageTypeEvent(self.station).start(type_, f"GarbageID={gid}")
+        self.station.push_event(event)
+
+    def update_by_where(self):
+        where = self.where_enter.get()
+        type_ = self.where_var[1].get()
+        event = tk_event.UpdateGarbageTypeEvent(self.station).start(type_, where)
+        self.station.push_event(event)
+
     def set_disable(self):
         set_tk_disable_from_list(self.btn)
         self.enter['state'] = 'disable'
@@ -1304,14 +1369,29 @@ class UpdateGarbageCheckResultProgram(AdminProgram):
             lb.place(relx=0.02, rely=0.2, relwidth=0.25, relheight=0.48)
             enter.place(relx=0.30, rely=0.2, relwidth=0.60, relheight=0.48)
 
-        for btn, text in zip(self.btn, ["Update Advanced", "Update By GarbageID"]):
+        for btn, text, func in zip(self.btn,
+                                   ["Update Advanced", "Update By GarbageID"],
+                                   [self.update_by_where, self.update_by_gid]):
             btn['font'] = btn_font
             btn['bg'] = conf.tk_btn_bg
             btn['text'] = text
+            btn['command'] = func
 
         self.btn[0].place(relx=0.55, rely=0.38, relwidth=0.25, relheight=0.08)
         self.btn[1].place(relx=0.55, rely=0.78, relwidth=0.25, relheight=0.08)
 
+    def update_by_gid(self):
+        gid = self.enter.get()
+        check = (self.var[1].get() == 1)
+        event = tk_event.UpdateGarbageCheckEvent(self.station).start(check, f"GarbageID={gid}")
+        self.station.push_event(event)
+
+    def update_by_where(self):
+        where = self.where_enter.get()
+        check = (self.where_var[1].get() == 1)
+        event = tk_event.UpdateGarbageCheckEvent(self.station).start(check, where)
+        self.station.push_event(event)
+
     def set_disable(self):
         set_tk_disable_from_list(self.btn)
         self.enter['state'] = 'disable'
@@ -1323,8 +1403,8 @@ class UpdateGarbageCheckResultProgram(AdminProgram):
         self.where_enter['state'] = 'normal'
 
 
-all_program = [WelcomeProgram, createNormalUserProgram, createManagerUserProgram, createAutoNormalUserProgram,
-               createGarbageProgram, DeleteUserProgram, DeleteUsersProgram, DeleteGarbageProgram,
+all_program = [WelcomeProgram, CreateNormalUserProgram, CreateManagerUserProgram, CreateAutoNormalUserProgram,
+               CreateGarbageProgram, DeleteUserProgram, DeleteUsersProgram, DeleteGarbageProgram,
                DeleteGarbageMoreProgram, DeleteAllGarbageProgram, SearchUserProgram, SearchUserAdvancedProgram,
                SearchGarbageProgram, SearchGarbageAdvancedProgram, SearchAdvancedProgram, UpdateUserScoreBase,
                UpdateUserReputationBase, UpdateGarbageTypeProgram, UpdateGarbageCheckResultProgram]

+ 1 - 1
control/event.py

@@ -91,7 +91,7 @@ class TkThreading(threading.Thread):
         try:
             self.result = self.func(*self.args)
         except:
-            ...
+            traceback.print_exc()
         finally:
             del self.func, self.args
 

+ 186 - 91
sql/garbage.py

@@ -1,8 +1,7 @@
 import time
-from decimal import Decimal
 from db import DB, DBBit, DBDataException, DBDoneException
 from tool.type_ import *
-from tool.time_ import HGSTime
+from tool.time_ import HGSTime, mysql_time, time_from_mysql
 from core.garbage import GarbageBag, GarbageType
 
 
@@ -10,12 +9,115 @@ class GarbageDBException(DBDataException):
     ...
 
 
+def update_garbage_type(where: str, type_: int, db: DB) -> int:
+    if len(where) == 0:
+        return -1
+
+    cur = db.done(f"UPDATE garbage SET GarbageType={type_} WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
+
+
+def update_garbage_check(where: str, check_: bool, db: DB) -> int:
+    if len(where) == 0:
+        return -1
+
+    i = 1 if check_ else 0
+    cur = db.done(f"UPDATE garbage SET CheckResult={i} WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
+
+
+def __get_time(time_str: str) -> float:
+    if time_str == 'now':
+        return time.time()
+    if time_str.startswith("Date:") and len(time_str) >= 5:
+        return time_from_mysql(time_str[5:])
+    return float(time_str)
+
+
+def __get_time_diff(time_str: str) -> float:
+    if time_str.endswith("s") and len(time_str) >= 2:
+        return float(time_str[:-1])
+    elif time_str.endswith("ms") and len(time_str) >= 3:
+        return float(time_str[:-1]) / 1000
+    elif time_str.endswith("min") and len(time_str) >= 4:
+        return float(time_str[:-1]) * 60
+    elif time_str.endswith("h") and len(time_str) >= 2:
+        return float(time_str[:-1]) * 60 * 60
+    elif time_str.endswith("d") and len(time_str) >= 2:
+        return float(time_str[:-1]) * 24 * 60 * 60
+    return float(time_str)
+
+
+def __search_fields_time(time_: str, time_name: str) -> str:
+    if time_ == '<=now':
+        return f"{time_name}<={mysql_time()} AND"
+    sp = time_.split(',')
+    if len(sp) == 2:
+        try:
+            time_list = __get_time(sp[0]), __get_time(sp[1])
+            a = min(time_list)
+            b = max(time_list)
+        except (TypeError, ValueError):
+            return ""
+        else:
+            return f"({time_name} BETWEEN {mysql_time(a)} AND {mysql_time(b)}) AND"
+    sp = time_.split(';')
+    if len(sp) == 2:
+        try:
+            time_list = __get_time(sp[0]), __get_time_diff(sp[1])
+            a = time_list[0] - time_list[1]
+            b = time_list[0] + time_list[1]
+        except (TypeError, ValueError):
+            return ""
+        else:
+            return f"({time_name} BETWEEN {mysql_time(a)} AND {mysql_time(b)}) AND"
+    try:
+        t = __get_time(time_)
+    except (TypeError, ValueError):
+        return ""
+    else:
+        return f"({time_name}={mysql_time(t)} AND"
+
+
+def search_garbage_by_fields(columns, gid, uid, cuid, create_time, use_time, loc, type_, check, db: DB):
+    where = ""
+    if gid is not None:
+        where += f"GarbageID={gid} AND "
+    if uid is not None:
+        where += f"UserID=‘{uid}’ AND "
+    if cuid is not None:
+        where += f"CheckerID='{cuid}' AND "
+    if loc is not None:
+        where += f"Location='{loc}' AND "
+    if check is not None:
+        if check == "False":
+            where += f"CheckResult=0 AND "
+        else:
+            where += f"CheckResult=1 AND "
+    if type_ is not None and type_ in GarbageType.GarbageTypeStrList:
+        res = GarbageType.GarbageTypeStrList.index(type_)
+        where += f"Phone={res} AND "
+    if create_time is not None:
+        where += __search_fields_time(create_time, "CreateTime")
+    if use_time is not None:
+        where += __search_fields_time(use_time, "UseTime")
+
+    if len(where) != 0:
+        where = where[0:-4]  # 去除末尾的AND
+
+    return search_from_garbage_view(columns, where, db)
+
+
 def search_from_garbage_view(columns, where: str, db: DB):
     if len(where) > 0:
         where = f"WHERE {where} "
 
     column = ", ".join(columns)
-    cur = db.search(f"SELECT {column} FROM garbage_view {where};")
+    cur = db.search(f"SELECT {column} FROM garbage {where};")
     if cur is None:
         return None
     res = cur.fetchall()
@@ -26,7 +128,9 @@ def count_garbage_by_time(uid: uid_t, db: DB):
     ti: time_t = time.time()
     start = ti - 3.5 * 24 * 60 * 60  # 前后3.5天
     end = ti + 3.5 * 24 * 60 * 60
-    cur = db.search(f"SELECT gid FROM garbage_time WHERE uid = '{uid}' AND use_time BETWEEN {start} AND {end};")
+    cur = db.search(f"SELECT GarbageID "
+                    f"FROM garbage_time "
+                    f"WHERE UserID = '{uid}' AND UseTime BETWEEN {mysql_time(start)} AND {mysql_time(end)};")
     if cur is None:
         return -1
     return cur.rowcount
@@ -43,18 +147,20 @@ def __find_garbage(sql: str, res_len, db: DB):
 
 
 def find_not_use_garbage(gid: gid_t, db: DB) -> Union[GarbageBag, None]:
-    return __find_garbage(f"SELECT gid FROM garbage_n WHERE gid = {gid};", 1, db)[0]
+    return __find_garbage(f"SELECT GarbageID FROM garbage_n WHERE GarbageID = {gid};", 1, db)[0]
 
 
 def find_wait_garbage(gid: gid_t, db: DB) -> Union[GarbageBag, None]:
-    res: Tuple[int, bytes, Decimal, str, str]
+    res: Tuple[int, bytes, str, str, str]
     gb: GarbageBag
-    gb, res = __find_garbage(f"SELECT gid, type, use_time, uid, loc FROM garbage_c WHERE gid = {gid};", 5, db)
+    gb, res = __find_garbage(f"SELECT GarbageID, GarbageType, UseTime, UserID, Location "
+                             f"FROM garbage_c "
+                             f"WHERE GarbageID = {gid};", 5, db)
     if gb is None:
         return None
 
     garbage_type: enum = int(res[1].decode())
-    use_time: time_t = float(res[2])
+    use_time: time_t = time_from_mysql(res[2])
     uid: uid_t = res[3]
     loc: location_t = res[4]
 
@@ -63,15 +169,16 @@ def find_wait_garbage(gid: gid_t, db: DB) -> Union[GarbageBag, None]:
 
 
 def find_use_garbage(gid: gid_t, db: DB) -> Union[GarbageBag, None]:
-    res: Tuple[int, bytes, Decimal, str, str, bytes]
+    res: Tuple[int, bytes, str, str, str, bytes]
     gb: GarbageBag
-    gb, res = __find_garbage(f"SELECT gid, type, use_time, uid, loc, right_use, check_uid "
-                             f"FROM garbage_u WHERE gid = {gid};", 7, db)
+    gb, res = __find_garbage(f"SELECT GarbageID, GarbageType, UseTime, UserID, Location, CheckResult, CheckerID "
+                             f"FROM garbage_u "
+                             f"WHERE GarbageID = {gid};", 7, db)
     if gb is None:
         return None
 
     garbage_type: enum = int(res[1].decode())
-    use_time: time_t = float(res[2])
+    use_time: time_t = time_from_mysql(res[2])
     uid: uid_t = res[3]
     loc: location_t = res[4]
     check: bool = res[5] == DBBit.BIT_1
@@ -99,7 +206,7 @@ def find_garbage(gid: gid_t, db: DB) -> Union[GarbageBag, None]:
 
 
 def is_garbage_exists(gid: gid_t, db: DB) -> Tuple[bool, int]:
-    cur = db.search(f"SELECT gid, flat FROM garbage WHERE gid = {gid};")
+    cur = db.search(f"SELECT GarbageID, Flat FROM garbage WHERE GarbageID = {gid};")
     if cur is None or cur.rowcount == 0:
         return False, 0
     assert cur.rowcount == 1
@@ -122,20 +229,36 @@ def update_garbage(garbage: GarbageBag, db: DB) -> bool:
     info = garbage.get_info()
 
     try:
-        db.done_(f"DELETE FROM garbage_n WHERE gid = {gid};")
-        db.done_(f"DELETE FROM garbage_c WHERE gid = {gid};")
-        db.done_(f"DELETE FROM garbage_u WHERE gid = {gid};")
-
         if garbage.is_check()[0]:
-            db.done_(f"UPDATE garbage SET flat = 2 WHERE gid = {gid};")
-            db.done_(f"INSERT INTO garbage_u(gid, uid, use_time, type, loc, right_use, check_uid) "
-                     f"VALUES ({info['gid']} , '{info['user']}'  , {info['use_time']}, {info['type']}, "
-                     f"       '{info['loc']}', {info['check']}, '{info['checker']}');")
+            db.done_(f"UPDATE garbage SET "
+                     f"Flat = 2,"
+                     f"UserID = '{info['user']}',"
+                     f"UseTime = {time_from_mysql(info['use_time'])},"
+                     f"GarbageType = {info['type']},"
+                     f"Location = '{info['loc']}',"
+                     f"CheckResult = {info['check']},"
+                     f"CheckerID = '{info['checker']}',"
+                     f"WHERE GarbageID = {gid};")
+        elif garbage.is_use():
+            db.done_(f"UPDATE garbage SET "
+                     f"Flat = 1,"
+                     f"UserID = '{info['user']}',"
+                     f"UseTime = {time_from_mysql(info['use_time'])},"
+                     f"GarbageType = {info['type']},"
+                     f"Location = '{info['loc']}',"
+                     f"CheckResult = NULL,"
+                     f"CheckerID = NULL,"
+                     f"WHERE GarbageID = {gid};")
         else:
-            db.done_(f"UPDATE garbage SET flat = 1 WHERE gid = {gid};")
-            db.done_(f"INSERT INTO garbage_c(gid, uid, use_time, type, loc) "
-                     f"VALUES ({info['gid']} , '{info['user']}', {info['use_time']}, {info['type']}, "
-                     f"       '{info['loc']}');")
+            db.done_(f"UPDATE garbage SET "
+                     f"Flat = 0,"
+                     f"UserID = NULL,"
+                     f"UseTime = NULL,"
+                     f"GarbageType = NULL,"
+                     f"Location = NULL,"
+                     f"CheckResult = NULL,"
+                     f"CheckerID = NULL,"
+                     f"WHERE GarbageID = {gid};")
     except DBDoneException:
         return False
     finally:
@@ -144,106 +267,89 @@ def update_garbage(garbage: GarbageBag, db: DB) -> bool:
 
 
 def create_new_garbage(db: DB) -> Optional[GarbageBag]:
-    cur = db.done("INSERT INTO garbage() VALUES ();")
+    cur = db.done(f"INSERT INTO garbage(CreateTime, Flat) VALUES ({mysql_time()}, 0);")
     if cur is None:
         return None
     assert cur.rowcount == 1
     gid = cur.lastrowid
-    cur = db.done(f"INSERT INTO garbage_n(gid) VALUES ({gid});")
-    if cur is None:
-        return None
-    assert cur.rowcount == 1
     return GarbageBag(str(gid))
 
 
-def del_garbage_core(gid: gid_t, db: DB, from_: str) -> bool:
-    cur = db.done(f"DELETE FROM {from_} WHERE gid = {gid};")
-    if cur is None or cur.rowcount == 0:
-        return False
-    assert cur.rowcount == 1
-    cur = db.done(f"DELETE FROM garbage WHERE gid = {gid};")
+def del_garbage_not_use(gid: gid_t, db: DB) -> bool:
+    cur = db.done(f"DELETE FROM garbage_n WHERE GarbageID = {gid};")
     if cur is None or cur.rowcount == 0:
         return False
     assert cur.rowcount == 1
     return True
 
 
-def del_garbage_not_use(gid: gid_t, db: DB) -> bool:
-    return del_garbage_core(gid, db, "garbage_n")
-
-
 def del_garbage_wait_check(gid: gid_t, db: DB) -> bool:
-    return del_garbage_core(gid, db, "garbage_c")
+    cur = db.done(f"DELETE FROM garbage_c WHERE GarbageID = {gid};")
+    if cur is None or cur.rowcount == 0:
+        return False
+    assert cur.rowcount == 1
+    return True
 
 
 def del_garbage_has_check(gid: gid_t, db: DB) -> bool:
-    return del_garbage_core(gid, db, "garbage_u")
+    cur = db.done(f"DELETE FROM garbage_u WHERE GarbageID = {gid};")
+    if cur is None or cur.rowcount == 0:
+        return False
+    assert cur.rowcount == 1
+    return True
 
 
 def del_garbage(gid, db: DB):
-    res = del_garbage_not_use(gid, db)
-    if res:
-        return True
-    res = del_garbage_wait_check(gid, db)
-    if res:
-        return True
-    return del_garbage_has_check(gid, db)
-
+    cur = db.done(f"DELETE FROM garbage WHERE GarbageID = {gid};")
+    if cur is None or cur.rowcount == 0:
+        return False
+    assert cur.rowcount == 1
+    return True
 
-def del_garbage_where_core(where, db: DB, from_: str, from_int: int) -> int:
-    cur = db.done_(f"DELETE FROM {from_} WHERE {where};")
-    if cur is None:
-        return -1
-    elif cur.rowcount == 0:
-        return 0
 
-    cur = db.done(f"DELETE FROM garbage WHERE flat={from_int} AND gid NOT IN (SELECT gid FROM {from_});")
+def del_garbage_where_not_use(where, db: DB) -> int:
+    cur = db.done_(f"DELETE FROM garbage_n WHERE {where};")
     if cur is None:
         return -1
     return cur.rowcount
 
 
-def del_garbage_where_not_use(where, db: DB) -> int:
-    return del_garbage_where_core(where, db, "garbage_n", 0)
-
-
 def del_garbage_where_wait_check(where, db: DB) -> int:
-    return del_garbage_where_core(where, db, "garbage_c", 1)
+    cur = db.done_(f"DELETE FROM garbage_c WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
 
 
 def del_garbage_where_has_check(where, db: DB) -> int:
-    return del_garbage_where_core(where, db, "garbage_u", 2)
-
-
-def del_garbage_where_scan_core(where, db: DB, from_: str) -> int:
-    cur = db.done(f"SELECT gid FROM {from_} WHERE {where};")
+    cur = db.done_(f"DELETE FROM garbage_u WHERE {where};")
     if cur is None:
         return -1
     return cur.rowcount
 
 
 def del_garbage_where_scan_not_use(where, db: DB) -> int:
-    return del_garbage_where_scan_core(where, db, "garbage_n")
+    cur = db.done(f"SELECT GarbageID FROM garbage_n WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
 
 
 def del_garbage_where_scan_wait_check(where, db: DB) -> int:
-    return del_garbage_where_scan_core(where, db, "garbage_c")
+    cur = db.done(f"SELECT GarbageID FROM garbage_c WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
 
 
 def del_garbage_where_scan_has_check(where, db: DB) -> int:
-    return del_garbage_where_scan_core(where, db, "garbage_u")
+    cur = db.done(f"SELECT GarbageID FROM garbage_u WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
 
 
 def del_all_garbage(db: DB) -> int:
-    cur = db.done(f"DELETE FROM garbage_u WHERE 1;")
-    if cur is None:
-        return -1
-    cur = db.done(f"DELETE FROM garbage_c WHERE 1;")
-    if cur is None:
-        return -1
-    cur = db.done(f"DELETE FROM garbage_n WHERE 1;")
-    if cur is None:
-        return -1
     cur = db.done(f"DELETE FROM garbage WHERE 1;")
     if cur is None:
         return -1
@@ -251,23 +357,12 @@ def del_all_garbage(db: DB) -> int:
 
 
 def del_all_garbage_scan(db: DB) -> int:
-    cur = db.done(f"SELECT gid FROM garbage WHERE 1;")
+    cur = db.done(f"SELECT GarbageID FROM garbage WHERE 1;")
     if cur is None:
         return -1
     return cur.rowcount
 
 
-def del_garbage_not_use_many(gid_from: gid_t, gid_to: gid_t, db: DB) -> int:
-    cur = db.done(f"DELETE FROM garbage "
-                  f"WHERE gid IN (SELECT gid FROM garbage_n WHERE gid BETWEEN {gid_from} and {gid_to});")
-    if cur is None or cur.rowcount == 0:
-        return 0
-    cur = db.done(f"DELETE FROM garbage WHERE gid BETWEEN {gid_from} and {gid_to};")
-    if cur is None or cur.rowcount == 0:
-        return 0
-    return cur.rowcount
-
-
 if __name__ == '__main__':
     mysql_db = DB()
     bag = create_new_garbage(mysql_db)

+ 38 - 17
sql/user.py

@@ -1,11 +1,32 @@
 from db import DB, DBBit
 from tool.type_ import *
 from tool.login import create_uid, randomPassword
+from tool.time_ import mysql_time
 from core.user import NormalUser, ManagerUser, User
 import conf
 from garbage import count_garbage_by_time
 
 
+def update_user_score(where: str, score: score_t, db: DB) -> int:
+    if len(where) == 0 or score < 0:
+        return -1
+
+    cur = db.done(f"UPDATE user SET Score={score} WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
+
+
+def update_user_reputation(where: str, reputation: score_t, db: DB) -> int:
+    if len(where) == 0 or reputation <= 1 or reputation >= 1000:
+        return -1
+
+    cur = db.done(f"UPDATE user SET Reputation={reputation} WHERE {where};")
+    if cur is None:
+        return -1
+    return cur.rowcount
+
+
 def search_user_by_fields(columns, uid: uid_t, name: uname_t, phone: phone_t, db: DB):
     where = ""
     if uid is not None:
@@ -26,7 +47,7 @@ def search_from_user_view(columns, where: str, db: DB):
         where = f"WHERE {where} "
 
     column = ", ".join(columns)
-    cur = db.search(f"SELECT {column} FROM user_view {where};")
+    cur = db.search(f"SELECT {column} FROM user {where};")
     if cur is None:
         return None
     result = cur.fetchall()
@@ -39,7 +60,7 @@ def search_from_user_view(columns, where: str, db: DB):
 
 
 def find_user_by_id(uid: uid_t, db: DB) -> Optional[User]:
-    cur = db.search(f"SELECT uid, name, manager, score, reputation FROM user WHERE uid = '{uid}';")
+    cur = db.search(f"SELECT UserID, Name, IsManager, Score, Reputation FROM user WHERE UserID = '{uid}';")
     if cur is None or cur.rowcount == 0:
         return None
     assert cur.rowcount == 1
@@ -65,7 +86,7 @@ def find_user_by_name(name: uname_t, passwd: passwd_t, db: DB) -> Optional[User]
 
 
 def is_user_exists(uid: uid_t, db: DB) -> bool:
-    cur = db.search(f"SELECT uid FROM user WHERE uid = '{uid}';")
+    cur = db.search(f"SELECT UserID FROM user WHERE UserID = '{uid}';")
     if cur is None or cur.rowcount == 0:
         return False
     assert cur.rowcount == 1
@@ -81,16 +102,16 @@ def update_user(user: User, db: DB) -> bool:
     is_manager = info['manager']
     if is_manager == '1':
         cur = db.done(f"UPDATE user "
-                      f"SET manager = {is_manager} "
-                      f"WHERE uid = '{uid}';")
+                      f"SET IsManager = {is_manager} "
+                      f"WHERE UserID = '{uid}';")
     else:
         score = info['score']
         reputation = info['reputation']
         cur = db.done(f"UPDATE user "
-                      f"SET manager = {is_manager},"
-                      f"    score = {score},"
-                      f"    reputation = {reputation} "
-                      f"WHERE uid = '{uid}';")
+                      f"SET IsManager = {is_manager},"
+                      f"    Score = {score},"
+                      f"    Reputation = {reputation} "
+                      f"WHERE UserID = '{uid}';")
     return cur is not None
 
 
@@ -106,9 +127,9 @@ def create_new_user(name: Optional[uname_t], passwd: Optional[passwd_t], phone:
     if is_user_exists(uid, db):
         return None
     is_manager = '1' if manager else '0'
-    cur = db.done(f"INSERT INTO user(uid, name, manager, phone, score, reputation) "
+    cur = db.done(f"INSERT INTO user(UserID, Name, IsManager, Phone, Score, Reputation, CreateTime) "
                   f"VALUES ('{uid}', '{name}', {is_manager}, '{phone}', {conf.default_score}, "
-                  f"{conf.default_reputation});")
+                  f"{conf.default_reputation}, {mysql_time()});")
     if cur is None:
         return None
     if is_manager:
@@ -117,7 +138,7 @@ def create_new_user(name: Optional[uname_t], passwd: Optional[passwd_t], phone:
 
 
 def get_user_phone(uid: uid_t, db: DB) -> Optional[str]:
-    cur = db.done(f"SELECT phone FROM user WHERE uid = {uid};")
+    cur = db.done(f"SELECT Phone FROM user WHERE UserID = '{uid}';")
     if cur is None or cur.rowcount == 0:
         return None
     assert cur.rowcount == 1
@@ -125,10 +146,10 @@ def get_user_phone(uid: uid_t, db: DB) -> Optional[str]:
 
 
 def del_user(uid: uid_t, db: DB) -> bool:
-    cur = db.search(f"SELECT gid FROM garbage_time WHERE uid = '{uid}';")  # 确保没有引用
+    cur = db.search(f"SELECT GarbageID FROM garbage_time WHERE UserID = '{uid}';")  # 确保没有引用
     if cur is None or cur.rowcount != 0:
         return False
-    cur = db.done(f"DELETE FROM user WHERE uid = '{uid}';")
+    cur = db.done(f"DELETE FROM user WHERE UserID = '{uid}';")
     if cur is None or cur.rowcount == 0:
         return False
     assert cur.rowcount == 1
@@ -136,15 +157,15 @@ def del_user(uid: uid_t, db: DB) -> bool:
 
 
 def del_user_from_where_scan(where: str, db: DB) -> int:
-    cur = db.search(f"SELECT uid FROM user WHERE {where};")
-    print(f"SELECT uid FROM user WHERE {where};")
+    cur = db.search(f"SELECT UserID FROM user WHERE {where};")
+    print(f"SELECT UserID FROM user WHERE {where};")
     if cur is None:
         return -1
     return cur.rowcount
 
 
 def del_user_from_where(where: str, db: DB) -> int:
-    cur = db.search(f"SELECT gid FROM garbage_time WHERE {where};")  # 确保没有引用
+    cur = db.search(f"SELECT GarbageID FROM garbage_time WHERE {where};")  # 确保没有引用
     if cur is None or cur.rowcount != 0:
         return False
     cur = db.done(f"DELETE FROM user WHERE {where};")

+ 11 - 0
tool/time_.py

@@ -17,4 +17,15 @@ class HGSTime:
         return time.time() > self._time
 
 
+def mysql_time(t=None) -> str:
+    if t is None:
+        t = time.time()
+    return f'from_unixtime({t})'
+
+
+def time_from_mysql(t) -> float:
+    t_struct = time.strptime(t, '%Y-%m-%d %H:%M:%S')
+    return time.mktime(t_struct)
+
+
 hgs_time_t = Union[HGSTime, time_t]