Browse Source

feat: 从CSV导入用户

SongZihuan 3 years ago
parent
commit
cf74d9dd4d
5 changed files with 219 additions and 13 deletions
  1. 7 9
      control/admin.py
  2. 34 0
      control/admin_event.py
  3. 7 2
      control/admin_menu.py
  4. 110 2
      control/admin_program.py
  5. 61 0
      sql/user.py

+ 7 - 9
control/admin.py

@@ -20,7 +20,8 @@ from sql.garbage import (create_new_garbage, search_garbage_by_fields, search_fr
 
 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,
-                      update_user_score, update_user_reputation)
+                      update_user_score, update_user_reputation,
+                      creat_user_from_csv, creat_auto_user_from_csv)
 from tool.tk import make_font
 from tool.type_ import *
 
@@ -68,14 +69,11 @@ class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
     def create_user(self, name: uname_t, passwd: passwd_t, phone: str, manager: bool) -> Optional[User]:
         return create_new_user(name, passwd, phone, manager, self._db)
 
-    def create_user_from_list(self, user_list: List[Tuple[uname_t, passwd_t, str]], manager: bool) -> List[User]:
-        re = []
-        for i in user_list:
-            user = create_new_user(i[0], i[1], i[2], manager, self._db)
-            if user is None:
-                raise CreateUserError
-            re.append(user)
-        return re
+    def create_user_from_csv(self, path) -> List[User]:
+        return creat_user_from_csv(path, self._db)
+
+    def create_auto_user_from_csv(self, path) -> List[User]:
+        return creat_auto_user_from_csv(path, self._db)
 
     def export_user_by_uid(self, path: str, uid: uid_t) -> Tuple[str, Optional[User]]:
         return write_uid_qr(uid, path, self._db)

+ 34 - 0
control/admin_event.py

@@ -164,6 +164,40 @@ class ExportUserAdvancedEvent(AdminEventBase):
         self.station.show_msg("Export", f"Export {len(res)} user finished.")
 
 
+class CreateUserFromCSVEvent(AdminEventBase):
+    def func(self, path):
+        return self.station.create_user_from_csv(path)
+
+    def __init__(self, station):
+        super(CreateUserFromCSVEvent, self).__init__(station)
+        self._name = None
+
+    def start(self, path):
+        self.thread = TkThreading(self.func, path)
+        return self
+
+    def done_after_event(self):
+        res: list[User] = self.thread.wait_event()
+        self.station.show_msg("Creat", f"Creat {len(res)} user finished.")
+
+
+class CreateAutoUserFromCSVEvent(AdminEventBase):
+    def func(self, path):
+        return self.station.create_auto_user_from_csv(path)
+
+    def __init__(self, station):
+        super(CreateAutoUserFromCSVEvent, self).__init__(station)
+        self._name = None
+
+    def start(self, path):
+        self.thread = TkThreading(self.func, path)
+        return self
+
+    def done_after_event(self):
+        res: list[User] = self.thread.wait_event()
+        self.station.show_msg("Creat", f"Creat {len(res)} auto user finished.")
+
+
 class DelUserEvent(AdminEventBase):
     def func(self, uid):
         return self.station.del_user(uid)

+ 7 - 2
control/admin_menu.py

@@ -78,8 +78,9 @@ class MainMenu(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(6)]
-        self.btn_name = ["NormalUser", "AutoNormalUser", "ManagerUser", "Garbage", "ExportUser", "ExportGarbage"]
+        self.btn: List[tk.Button] = [tk.Button(self.frame) for _ in range(7)]
+        self.btn_name = ["NormalUser", "AutoNormalUser", "ManagerUser", "Garbage",
+                         "ExportUser", "ExportGarbage", "User From CSV"]
 
     def conf_gui(self, color: str, n: int = 1):
         super().conf_gui(color, n)
@@ -89,6 +90,7 @@ class CreateMenu(AdminMenu):
         self.btn[3]['command'] = lambda: self.create_garbage()
         self.btn[4]['command'] = lambda: self.export_user()
         self.btn[5]['command'] = lambda: self.export_garbage()
+        self.btn[6]['command'] = lambda: self.create_user_from_csv()
 
     def create_normal_user(self):
         self.station.to_program("CreateNormalUser")
@@ -108,6 +110,9 @@ class CreateMenu(AdminMenu):
     def export_garbage(self):
         self.station.to_program("ExportGarbage")
 
+    def create_user_from_csv(self):
+        self.station.to_program("CreateUserFromCSV")
+
 
 class DeleteMenu(AdminMenu):
     def __init__(self, station, win, color):

+ 110 - 2
control/admin_program.py

@@ -1,7 +1,7 @@
 import abc
 import tkinter as tk
 import tkinter.ttk as ttk
-from tkinter.filedialog import askdirectory
+from tkinter.filedialog import askdirectory, askopenfilename
 
 from tool.type_ import *
 from tool.tk import make_font, set_tk_disable_from_list
@@ -485,6 +485,114 @@ class ExportUserProgram(ExportProgramBase):
         self.station.push_event(event)
 
 
+class CreateUserFromCSVProgram(AdminProgram):
+    def __init__(self, station, win, color):
+        super().__init__(station, win, color, "CreateUserFromCSV")
+
+        self.auto_frame = tk.Frame(self.frame)
+        self.auto_title: tk.Label = tk.Label(self.auto_frame)
+        self.auto_enter: tk.Entry = tk.Entry(self.auto_frame)
+        self.auto_var: tk.Variable = tk.StringVar()
+
+        self.enter_frame = tk.Frame(self.frame)
+        self.path_title: tk.Label = tk.Label(self.enter_frame)
+        self.path_enter: tk.Entry = tk.Entry(self.enter_frame)
+        self.path_var: tk.Variable = tk.StringVar()
+
+        self.create_btn: List[tk.Button] = [tk.Button(self.frame), tk.Button(self.frame)]
+        self.file_btn: List[tk.Button] = [tk.Button(self.frame), tk.Button(self.frame)]
+
+        self.__conf_font()
+
+    def __conf_font(self, n: int = 1):
+        self.title_font_size = int(16 * n)
+        self.btn_font_size = int(14 * n)
+
+    def conf_gui(self, n: int = 1):
+        self.__conf_font(n)
+
+        title_font = make_font(size=self.title_font_size)
+        btn_font = make_font(size=self.btn_font_size)
+
+        self.enter_frame['bg'] = "#EEE8AA"
+        self.enter_frame['bd'] = 5
+        self.enter_frame['relief'] = "ridge"
+        self.enter_frame.place(relx=0.2, rely=0.2, relwidth=0.6, relheight=0.12)
+
+        self.auto_frame['bg'] = "#EEE8AA"
+        self.auto_frame['bd'] = 5
+        self.auto_frame['relief'] = "ridge"
+        self.auto_frame.place(relx=0.2, rely=0.6, relwidth=0.6, relheight=0.12)
+
+        self.auto_title['font'] = title_font
+        self.auto_title['text'] = "Path:"
+        self.auto_title['bg'] = "#EEE8AA"
+        self.auto_title['anchor'] = 'e'
+
+        self.path_title['font'] = title_font
+        self.path_title['text'] = "Path:"
+        self.path_title['bg'] = "#EEE8AA"
+        self.path_title['anchor'] = 'e'
+
+        self.auto_enter['textvariable'] = self.auto_var
+        self.auto_enter['font'] = title_font
+
+        self.path_enter['textvariable'] = self.path_var
+        self.path_enter['font'] = title_font
+
+        self.auto_title.place(relx=0.01, rely=0.25, relwidth=0.30, relheight=0.50)
+        self.auto_enter.place(relx=0.35, rely=0.25, relwidth=0.60, relheight=0.50)
+
+        self.path_title.place(relx=0.01, rely=0.25, relwidth=0.30, relheight=0.50)
+        self.path_enter.place(relx=0.35, rely=0.25, relwidth=0.60, relheight=0.50)
+
+        for btn, text in zip(self.create_btn + self.file_btn,
+                             ["Create User", "Create Auto User", "Choose CSV", "Choose CSV"]):
+            btn['font'] = btn_font
+            btn['text'] = text
+            btn['bg'] = conf.tk_btn_bg
+
+        self.create_btn[0]['command'] = self.create
+        self.create_btn[1]['command'] = self.create_auto
+        self.create_btn[0].place(relx=0.2, rely=0.34, relwidth=0.25, relheight=0.08)
+        self.create_btn[1].place(relx=0.2, rely=0.74, relwidth=0.25, relheight=0.08)
+
+        self.file_btn[0]['command'] = self.choose_file
+        self.file_btn[1]['command'] = self.choose_file_auto
+        self.file_btn[0].place(relx=0.6, rely=0.34, relwidth=0.2, relheight=0.08)
+        self.file_btn[1].place(relx=0.6, rely=0.74, relwidth=0.2, relheight=0.08)
+
+    def choose_file_auto(self):
+        path = askopenfilename(title='path of csv', filetypes=[("CSV", ".csv")])
+        self.auto_var.set(path)
+
+    def choose_file(self):
+        path = askopenfilename(title='path of csv', filetypes=[("CSV", ".csv")])
+        self.path_var.set(path)
+
+    def create_auto(self):
+        path = self.auto_var.get()
+        event = tk_event.CreateAutoUserFromCSVEvent(self.station).start(path)
+        self.station.push_event(event)
+
+    def create(self):
+        path = self.path_var.get()
+        event = tk_event.CreateUserFromCSVEvent(self.station).start(path)
+        self.station.push_event(event)
+
+    def set_disable(self):
+        self.auto_enter['state'] = 'disable'
+        self.path_enter['state'] = 'disable'
+        set_tk_disable_from_list(self.create_btn)
+        set_tk_disable_from_list(self.file_btn)
+
+    def reset_disable(self):
+        self.auto_enter['state'] = 'normal'
+        self.path_enter['state'] = 'normal'
+        set_tk_disable_from_list(self.create_btn, flat='normal')
+        set_tk_disable_from_list(self.file_btn, flat='normal')
+
+
 class DeleteUserProgram(AdminProgram):
     def __init__(self, station, win, color):
         super().__init__(station, win, color, "DeleteUser")
@@ -1560,4 +1668,4 @@ all_program = [WelcomeProgram, CreateNormalUserProgram, CreateManagerUserProgram
                DeleteGarbageMoreProgram, DeleteAllGarbageProgram, SearchUserProgram, SearchUserAdvancedProgram,
                SearchGarbageProgram, SearchGarbageAdvancedProgram, SearchAdvancedProgram, UpdateUserScoreBase,
                UpdateUserReputationBase, UpdateGarbageTypeProgram, UpdateGarbageCheckResultProgram,
-               ExportGarbageProgram, ExportUserProgram]
+               ExportGarbageProgram, ExportUserProgram, CreateUserFromCSVProgram]

+ 61 - 0
sql/user.py

@@ -1,3 +1,5 @@
+import csv
+
 from db import DB, DBBit
 from tool.type_ import *
 from tool.login import create_uid, randomPassword
@@ -123,6 +125,9 @@ def create_new_user(name: Optional[uname_t], passwd: Optional[passwd_t], phone:
     if passwd is None:
         passwd = randomPassword()
 
+    if len(phone) != 11:
+        return None
+
     uid = create_uid(name, passwd)
     if is_user_exists(uid, db):
         return None
@@ -174,6 +179,62 @@ def del_user_from_where(where: str, db: DB) -> int:
     return cur.rowcount
 
 
+def creat_user_from_csv(path, db: DB) -> List[User]:
+    res = []
+    with open(path, "r") as f:
+        reader = csv.reader(f)
+        first = True
+        name_index = 0
+        passwd_index = 0
+        phone_index = 0
+        manager_index = 0
+        for item in reader:
+            if first:
+                try:
+                    name_index = item.index('Name')
+                    passwd_index = item.index('Passwd')
+                    phone_index = item.index('Phone')
+                    manager_index = item.index('Manager')
+                except (ValueError, TypeError):
+                    return []
+                first = False
+                continue
+            name = item[name_index]
+            passwd = item[passwd_index]
+            phone = item[phone_index]
+            if item[manager_index].upper() == "TRUE":
+                is_manager = True
+            elif item[manager_index].upper() == "FALSE":
+                is_manager = False
+            else:
+                continue
+            user = create_new_user(name, passwd, phone, is_manager, db)
+            if user is not None:
+                res.append(user)
+    return res
+
+
+def creat_auto_user_from_csv(path, db: DB) -> List[User]:
+    res = []
+    with open(path, "r") as f:
+        reader = csv.reader(f)
+        first = True
+        phone_index = 0
+        for item in reader:
+            if first:
+                try:
+                    phone_index = item.index('Phone')
+                except (ValueError, TypeError):
+                    return []
+                first = False
+                continue
+            phone = item[phone_index]
+            user = create_new_user(None, None, phone, False, db)
+            if user is not None:
+                res.append(user)
+    return res
+
+
 if __name__ == '__main__':
     mysql_db = DB()
     name_ = 'Huan12'