Browse Source

feat: GUI界面支持登录系统

SongZihuan 3 years ago
parent
commit
64aacf80a4
9 changed files with 474 additions and 41 deletions
  1. 6 1
      conf/__init__.py
  2. 3 1
      conf/font/noto/__init__.py
  3. 5 0
      conf/picture/__init__.py
  4. BIN
      conf/picture/head.png
  5. 112 36
      control/__init__.py
  6. 340 0
      control/tk.py
  7. 6 1
      equipment/scan.py
  8. 1 1
      equipment/scan_garbage.py
  9. 1 1
      tool/pic.py

+ 6 - 1
conf/__init__.py

@@ -6,6 +6,7 @@
 import sys
 import warnings
 from font.noto import noto_font
+from picture import *
 
 if len(sys.argv) != 4:
     warnings.warn(f"参数不足: {len(sys.argv)}")
@@ -24,9 +25,13 @@ limit_rubbish_week = 50
 
 base_location = "Guangdong-Guangzhou"
 
-font_dict = {
+font_d = {
     "noto": noto_font
 }
 
+pic_d = {
+    "head": head_pic
+}
+
 capture_num = 0  # 摄像头号
 capture_arg = []

+ 3 - 1
conf/font/noto/__init__.py

@@ -1,3 +1,5 @@
 import os
+
+
 font = os.path.dirname(os.path.abspath(__file__))
-noto_font = os.path.join(font, "NotoSansMono-VariableFont_wdth,wght.ttf")
+noto_font = os.path.join(font, "NotoSansMono-VariableFont_wdth,wght.ttf")

+ 5 - 0
conf/picture/__init__.py

@@ -0,0 +1,5 @@
+import os
+
+
+pic = os.path.dirname(os.path.abspath(__file__))
+head_pic = os.path.join(pic, "head.png")

BIN
conf/picture/head.png


+ 112 - 36
control/__init__.py

@@ -1,13 +1,13 @@
 import conf
-import abc
+import time
 from tool.type_ import *
 from sql.db import DB, mysql_db
-from sql.user import update_user, find_user_by_id
-from sql.garbage import update_garbage
+from sql.user import update_user, find_user_by_id, creat_new_user
+from sql.garbage import update_garbage, creat_new_garbage
 from equipment.scan import HGSCapture, HGSQRCoder, QRCode, capture, qr_capture
 from equipment.scan_user import scan_user
-from equipment.scan_garbage import scan_garbage
-from core.user import User
+from equipment.scan_garbage import scan_garbage, write_gid_qr
+from core.user import User, UserNotSupportError
 from core.garbage import GarbageBag, GarbageType, GarbageBagNotUse
 
 
@@ -27,12 +27,27 @@ class CheckGarbageError(ControlError):
     ...
 
 
-class ControlBase(metaclass=abc.ABCMeta):
+class CreatGarbageError(ControlError):
+    ...
+
+
+class CreatUserError(ControlError):
+    ...
+
+
+class ControlScanType:
+    switch_user = 1
+    throw_garbage = 2
+    check_garbage = 3
+    no_to_done = 4
+
+
+class Control:
     __control = None
 
     def __new__(cls, *args, **kwargs):
         if cls.__control is None:
-            cls.__control = super().__new__()
+            cls.__control = super(Control, cls).__new__(cls, *args, **kwargs)
         return cls.__control
 
     def __init__(self,
@@ -45,8 +60,40 @@ class ControlBase(metaclass=abc.ABCMeta):
         self._qr = qr
         self._loc: location_t = loc
         self._user: Optional[User] = None  # 操作者
+        self._user_last_time: time_t = 0
+
+    def check_user(self):
+        if time.time() - self._user_last_time > 20:
+            self._user = None
+        if self._user is None:
+            return False
+        return True
+
+    def __check_user(self):
+        if self.check_user():
+            raise ControlNotLogin
+        self._user_last_time = time.time()
 
-    def scan(self) -> bool:
+    def __check_normal_user(self):
+        self.__check_user()
+        if self._user.is_manager():
+            raise UserNotSupportError
+
+    def __check_manager_user(self):
+        self.__check_user()
+        if not self._user.is_manager():
+            raise UserNotSupportError
+
+    def get_user_info(self):
+        self.__check_user()
+        return self._user.get_info()
+
+    def get_user_info_no_update(self) -> Dict[str, str]:
+        if not self.check_user():
+            return {}
+        return self._user.get_info()
+
+    def scan(self) -> Tuple[int, any]:
         """
         处理扫码事务
         二维码扫描的任务包括: 登录, 扔垃圾, 标记垃圾
@@ -54,27 +101,49 @@ class ControlBase(metaclass=abc.ABCMeta):
         """
         self._cap.get_image()
         qr_code = self._qr.get_qr_code()
+        if qr_code is None:
+            return ControlScanType.no_to_done, None
 
         user: Optional[User] = scan_user(qr_code, self._db)
         if user is not None:
-            self.switch_user(user)
-            return True
+            return ControlScanType.switch_user, user
 
         garbage: Optional[GarbageBag] = scan_garbage(qr_code, self._db)
         if garbage is not None:
             if self._user is None:
                 raise ControlNotLogin
-            return True
+            if self._user.is_manager():
+                return ControlScanType.check_garbage, garbage
+            return ControlScanType.throw_garbage, garbage
 
-    def throw_garbage(self, garbage: GarbageBag):
-        garbage_type = self.get_rubbish_type()  # 获得垃圾类型
+        return ControlScanType.no_to_done, None
+
+    def get_cap_img(self):
+        return self._cap.get_frame()
+
+    def switch_user(self, user: User) -> bool:
+        """
+        切换用户: 退出/登录
+        :param user: 新用户
+        :return: 登录-True, 退出-False
+        """
+        if self._user is not None and self._user.get_uid() == user.get_uid() and self.check_user():  # 正在登陆期
+            self._user = None  # 退出登录
+            self._user_last_time = None
+            return False
+        self._user = user
+        self._user_last_time = time.time()
+        return True  # 登录
+
+    def throw_garbage(self, garbage: GarbageBag, garbage_type: enum):
+        self.__check_normal_user()
         if not self._user.throw_rubbish(garbage, garbage_type, self._loc):
             raise ThrowGarbageError
         update_garbage(garbage, self._db)
         update_user(self._user, self._db)
 
-    def check_garbage(self, garbage: GarbageBag):
-        check_result = self.get_rubbish_check()  # 获取垃圾检查结果
+    def check_garbage(self, garbage: GarbageBag, check_result: bool):
+        self.__check_manager_user()
         user = find_user_by_id(garbage.get_user(), self._db)
         if user is None:
             raise GarbageBagNotUse
@@ -84,27 +153,34 @@ class ControlBase(metaclass=abc.ABCMeta):
         update_user(self._user, self._db)
         update_user(user, self._db)
 
-    @abc.abstractmethod
-    def get_rubbish_type(self) -> enum:
-        ...
+    def creat_garbage(self, path: str, num: int = 1) -> List[tuple[str, Optional[GarbageBag]]]:
+        self.__check_manager_user()
+        if self._user is None:
+            raise ControlNotLogin
 
-    @abc.abstractmethod
-    def get_rubbish_check(self) -> bool:
-        ...
+        re = []
+        for _ in range(num):
+            gar = creat_new_garbage(self._db)
+            if gar is None:
+                raise CreatGarbageError
+            res = write_gid_qr(gar.get_gid(), path, self._db)
+            re.append(res)
+        return re
+
+    def creat_user(self, name: uname_t, passwd: passwd_t, phone: str, manager: bool) -> Optional[User]:
+        user = creat_new_user(name, passwd, phone, manager, self._db)
+        if user is None:
+            raise CreatUserError
+        return user
 
-    def switch_user(self, user: User) -> bool:
-        """
-        切换用户: 退出/登录
-        :param user: 新用户
-        :return: 登录-True, 退出-False
-        """
-        if self._user is not None and self._user.get_uid() == user.get_uid():
-            self._user = None  # 退出登录
-            return False
-        self._user = user
-        return True  # 登录
+    def creat_user_from_list(self, user_list: List[Tuple[uname_t, passwd_t, str]], manager: bool) -> List[User]:
+        re = []
+        for i in user_list:
+            user = creat_new_user(i[0], i[1], i[2], manager, self._db)
+            if user is None:
+                raise CreatUserError
+            re.append(user)
+        return re
 
-    def get_user_info(self):
-        if self._user is None:
-            raise ControlNotLogin
-        return self._user.get_info()
+
+global_control = Control()

+ 340 - 0
control/tk.py

@@ -0,0 +1,340 @@
+import PIL.Image
+
+import conf
+import cv2
+import tkinter as tk
+import tkinter.font as font
+from tool.type_ import *
+import datetime
+from PIL import Image, ImageTk
+from control import Control, global_control, ControlScanType, ControlNotLogin
+
+
+class GarbageStation:
+    def __init__(self, ctrl: Control = global_control):
+        self._ctrl = ctrl
+        self._window = tk.Tk()
+        self._sys_height = self._window.winfo_screenheight()
+        self._sys_width = self._window.winfo_screenwidth()
+        self._win_height = int(self._sys_height * (2 / 3))
+        self._win_width = int(self._sys_width * (2 / 3))
+        self.__conf_windows()
+
+        self._title_font_size = 25
+        self._title_label = tk.Label(self._window)
+        self.__conf_title_label()
+
+        self._win_ctrl_font_size = 15
+        self._win_ctrl_button: Tuple[tk.Button, tk.Button, tk.Button] = (tk.Button(self._window),
+                                                                         tk.Button(self._window),
+                                                                         tk.Button(self._window))
+        self.__conf_win_ctrl_button()
+
+        self._win_info_font_size = 18
+        win_info_type = Tuple[tk.Label, tk.Label, tk.Variable, str]
+        self._user_frame = tk.Frame(self._window)
+        self._user_name: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
+                                          tk.StringVar(), "UserName")
+        self._user_uid: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
+                                         tk.StringVar(), "UserID")
+        self._user_score: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
+                                           tk.StringVar(), "Score")
+        self._user_rubbish: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
+                                             tk.StringVar(), "Garbage")
+        self._user_eval: win_info_type = (tk.Label(self._user_frame), tk.Label(self._user_frame),
+                                          tk.StringVar(), "Evaluation")
+        self._user_img = tk.Label(self._user_frame)
+        self.__conf_user_info_label()
+
+        self._throw_ctrl_btn_font_size = 20
+        self._throw_ctrl_frame = tk.Frame(self._window)
+        self._throw_ctrl_btn: List[tk.Button] = [tk.Button(self._throw_ctrl_frame), tk.Button(self._throw_ctrl_frame),
+                                                 tk.Button(self._throw_ctrl_frame), tk.Button(self._throw_ctrl_frame)]
+        self.__conf_throw_btn()
+
+        self.__check_ctrl_btn_font_size = 20
+        self._check_ctrl_frame = tk.Frame(self._window)
+        self._check_ctrl_btn: List[tk.Button] = [tk.Button(self._check_ctrl_frame), tk.Button(self._check_ctrl_frame)]
+        self.__conf_check_btn()
+
+        self._sys_info_font_size = 18
+        self._sys_info_frame = tk.Frame(self._window)
+        self._garbage_id: win_info_type = (tk.Label(self._sys_info_frame), tk.Label(self._sys_info_frame),
+                                           tk.StringVar(), "GID")
+        self._sys_date: win_info_type = (tk.Label(self._sys_info_frame), tk.Label(self._sys_info_frame),
+                                         tk.StringVar(), "Date")
+        self.__conf_sys_info_label()
+
+        self._cap_img = None
+        self._cap_label = tk.Label(self._window)
+        self.__conf_cap_label()
+
+        self._user_btn_font_size = 20
+        self._user_btn_frame = tk.Frame(self._window)
+        self._user_btn: List[tk.Button] = [tk.Button(self._user_btn_frame), tk.Button(self._user_btn_frame),
+                                           tk.Button(self._user_btn_frame)]
+        self.__conf_user_btn()
+        self.__conf_after()
+
+    def __conf_windows(self):
+        self._window.title('HGSSystem: Garbage Station')
+        self._window.geometry(f'{self._win_width}x{self._win_height}')
+        self._window['bg'] = "#F0FFF0"  # 蜜瓜绿
+        self._window.attributes("-topmost", True)
+        self._window.resizable(False, False)
+
+    def __conf_title_label(self):
+        title_font = self.__make_font(size=self._title_font_size, weight="bold")
+        self._title_label['font'] = title_font
+        self._title_label['bg'] = "#F0FFF0"  # 蜜瓜绿
+        self._title_label['text'] = "HGSSystem: GarbageStation Control Center"
+        self._title_label['anchor'] = 'w'
+        self._title_label.place(relx=0.02, rely=0.0, relwidth=0.6, relheight=0.07)
+
+    def __conf_win_ctrl_button(self):
+        title_font = self.__make_font(size=self._win_ctrl_font_size)
+
+        for bt in self._win_ctrl_button:
+            bt: tk.Button
+            bt['font'] = title_font
+            bt['bg'] = "#B0C4DE"  # 浅钢青
+
+        bt_help: tk.Button = self._win_ctrl_button[0]
+        bt_help['text'] = 'Help'
+        bt_help.place(relx=0.81, rely=0.01, relwidth=0.05, relheight=0.05)
+
+        bt_about: tk.Button = self._win_ctrl_button[1]
+        bt_about['text'] = 'About'
+        bt_about.place(relx=0.87, rely=0.01, relwidth=0.05, relheight=0.05)
+
+        bt_exit: tk.Button = self._win_ctrl_button[2]
+        bt_exit['text'] = 'Exit'
+        bt_exit.place(relx=0.93, rely=0.01, relwidth=0.05, relheight=0.05)
+
+    def __conf_user_info_label(self):
+        title_font = self.__make_font(size=self._win_info_font_size - 1, weight="bold")
+        info_font = self.__make_font(size=self._win_info_font_size + 1)
+
+        frame_width = self._win_width * 0.4
+        frame_height = self._win_height * 0.4
+        self._user_frame['bg'] = "#FA8072"
+        self._user_frame.place(relx=0.02, rely=0.1, relwidth=0.4, relheight=0.40)
+        self._user_frame['bd'] = 5
+        self._user_frame['relief'] = "ridge"
+
+        h_label = 5
+        h_label_s = 1
+        h_top = 2
+        height_count = h_label * 5 + h_label_s * 4 + h_top * 2
+        height_label = h_label / height_count
+        height = h_top / height_count
+
+        for lb_list in [self._user_score, self._user_rubbish, self._user_eval, self._user_name, self._user_uid]:
+            lb_list[0]['font'] = title_font
+            lb_list[0]['bg'] = "#FA8072"
+            lb_list[0]['fg'] = "#FFB6C1"
+            lb_list[0]['text'] = lb_list[3] + " " * (10 - len(lb_list[3])) + " :"
+            lb_list[0]['anchor'] = 'e'
+            lb_list[0].place(relx=0.0, rely=height, relwidth=0.35, relheight=height_label)
+            height += height_label + h_label_s / height_count
+
+        for lb_list in [self._user_score, self._user_rubbish, self._user_eval, self._user_name, self._user_uid]:
+            lb_list[1]['font'] = info_font
+            lb_list[1]['bg'] = "#FA8073"
+            lb_list[1]['fg'] = "#000000"
+            lb_list[1]['textvariable'] = lb_list[2]
+            lb_list[1]['anchor'] = 'w'
+            lb_list[2].set('test')
+
+        height = h_top / height_count
+        for lb_list in [self._user_score, self._user_rubbish, self._user_eval]:
+            lb_list[1].place(relx=0.36, rely=height, relwidth=0.19, relheight=height_label)
+            height += height_label + h_label_s / height_count
+
+        for lb_list in [self._user_name, self._user_uid]:
+            lb_list[1].place(relx=0.36, rely=height, relwidth=0.63, relheight=height_label)
+            height += height_label + h_label_s / height_count
+
+        img_relwidth = 0.30
+        img_relheight = height_label * 3 + (h_label_s / height_count) * 2
+        img = (Image.open(conf.pic_d['head']).
+               resize((int(img_relwidth * frame_width), int(img_relheight * frame_height))))
+        self._user_im = ImageTk.PhotoImage(image=img)
+        self._user_img['image'] = self._user_im
+        self._user_img.place(relx=1 - img_relwidth - 0.06, rely=0.09,
+                             relwidth=img_relwidth, relheight=img_relheight)
+        self._user_img['bd'] = 5
+        self._user_img['relief'] = "ridge"
+
+    def __conf_throw_btn(self):
+        btn_font = self.__make_font(size=self._throw_ctrl_btn_font_size, weight="bold")
+        btn_info: List[Tuple[str, str]] = [("Recyclable", "#00BFFF"),
+                                           ("Other", "#A9A9A9"),
+                                           ("Hazardous", "#DC143C"),
+                                           ("Kitchen", "#32CD32")]
+
+        self._throw_ctrl_frame.place(relx=0.45, rely=0.1, relwidth=0.53, relheight=0.70)
+
+        for btn, info in zip(self._throw_ctrl_btn, btn_info):
+            btn['font'] = btn_font
+            btn['bg'] = info[1]
+            btn['text'] = info[0]
+
+        self._throw_ctrl_btn[0].place(relx=0.000, rely=0.000, relwidth=0.495, relheight=0.495)
+        self._throw_ctrl_btn[1].place(relx=0.505, rely=0.000, relwidth=0.495, relheight=0.495)
+        self._throw_ctrl_btn[2].place(relx=0.000, rely=0.505, relwidth=0.495, relheight=0.495)
+        self._throw_ctrl_btn[3].place(relx=0.505, rely=0.505, relwidth=0.495, relheight=0.495)
+
+    def __conf_check_btn(self):
+        btn_font = self.__make_font(size=self.__check_ctrl_btn_font_size, weight="bold")
+        btn_info: List[Tuple[str, str]] = [("Fail", "#ef7a82"),
+                                           ("Pass", "#70f3ff")]
+
+        self._check_ctrl_frame.place(relx=0.45, rely=0.82, relwidth=0.53, relheight=0.16)
+
+        for btn, info in zip(self._check_ctrl_btn, btn_info):
+            btn['font'] = btn_font
+            btn['text'] = info[0]
+            btn['bg'] = info[1]
+            btn['state'] = 'disabled'
+
+        self._check_ctrl_btn[0].place(relx=0.000, rely=0.000, relwidth=0.495, relheight=1)
+        self._check_ctrl_btn[1].place(relx=0.505, rely=0.000, relwidth=0.495, relheight=1)
+
+    def __conf_sys_info_label(self):
+        title_font = self.__make_font(size=self._sys_info_font_size - 1, weight="bold")
+        info_font = self.__make_font(size=self._sys_info_font_size + 1)
+
+        self._sys_info_frame['bg'] = "#F0F8FF"
+        self._sys_info_frame.place(relx=0.02, rely=0.51, relwidth=0.4, relheight=0.14)
+        self._sys_info_frame['bd'] = 5
+        self._sys_info_frame['relief'] = "ridge"
+
+        h_label = 5
+        h_label_s = 1
+        h_top = 2
+        height_count = h_label * 2 + h_label_s * 1 + h_top * 2
+        height_label = h_label / height_count
+
+        height = h_top / height_count
+        for info_list in [self._garbage_id, self._sys_date]:
+            info_list[0]['font'] = title_font
+            info_list[0]['bg'] = "#F0F8FF"
+            info_list[0]['anchor'] = 'e'
+            info_list[0]['text'] = info_list[3] + " " * (10 - len(info_list[3])) + " :"
+            info_list[0].place(relx=0.0, rely=height, relwidth=0.35, relheight=height_label)
+            height += height_label + h_label_s / height_count
+
+        height = h_top / height_count
+        for info_list in [self._garbage_id, self._sys_date]:
+            info_list[1]['font'] = info_font
+            info_list[1]['bg'] = "#F0F8FF"
+            info_list[1]['textvariable'] = info_list[2]
+            info_list[1]['anchor'] = 'w'
+            info_list[2].set('test')
+            info_list[1].place(relx=0.36, rely=height, relwidth=0.63, relheight=height_label)
+            height += height_label + h_label_s / height_count
+
+    def __conf_user_btn(self):
+        btn_font = self.__make_font(size=self._user_btn_font_size, weight="bold")
+        btn_info: List[Tuple[str, str]] = [("Detail", "#b0a4e3"),
+                                           ("Ranking", "#b0a4e3"),
+                                           ("Search", "#b0a4e3")]
+
+        self._user_btn_frame.place(relx=0.02, rely=0.66, relwidth=0.19, relheight=0.32)
+        self._user_btn_frame['bg'] = "#F0FFF0"
+
+        h_label = 5
+        h_label_s = 1
+        height_count = h_label * 3 + h_label_s * 2
+        height_label = h_label / (h_label * 3 + h_label_s * 2)
+
+        height = 0
+        for btn, info in zip(self._user_btn, btn_info):
+            btn['font'] = btn_font
+            btn['text'] = info[0]
+            btn['bg'] = info[1]
+            btn.place(relx=0.0, rely=height, relwidth=1.00, relheight=height_label)
+            height += height_label + h_label_s / height_count
+
+    def __conf_cap_label(self):
+        self._cap_label['bg'] = "#000000"
+        self._cap_label.place(relx=0.22, rely=0.66, relwidth=0.2, relheight=0.32)
+
+    def __define_after(self, ms, func, *args):
+        self._window.after(ms, func, *args)
+
+    def __conf_after(self):
+        self.__define_after(10, self.update_time)
+        self.__define_after(10, self.update_control)
+        self.__define_after(10, self.update_scan)
+
+    def update_time(self):
+        var: tk.Variable = self._sys_date[2]
+        t = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+        var.set(f"{t}")
+        self.__define_after(10, self.update_time)
+
+    def update_control(self, update: bool = True):
+        name: tk.Variable = self._user_name[2]
+        uid: tk.Variable = self._user_uid[2]
+        score: tk.Variable = self._user_score[2]
+        rubbish: tk.Variable = self._user_rubbish[2]
+        eval_: tk.Variable = self._user_eval[2]
+
+        user_info: Dict[str, str] = self._ctrl.get_user_info_no_update()
+        if user_info.get('uid') is None:
+            name.set('Not-Login')
+            uid.set('Not-Login')
+            eval_.set('---')
+            rubbish.set('---')
+            score.set('---')
+        elif user_info.get('manager', False):
+            name.set(user_info.get('name'))
+            uid.set(user_info.get('uid'))
+            eval_.set('Manager-User')
+            rubbish.set('Manager-User')
+            score.set('Manager-User')
+        else:
+            name.set(user_info.get('name'))
+            uid_get = user_info.get('uid', None)
+            if uid_get is None or len(uid_get) < 32:
+                uid.set('error')
+            else:
+                uid.set(uid_get[0:21])
+            eval_.set(user_info.get('reputation'))
+            rubbish.set(user_info.get('rubbish'))
+            score.set(user_info.get('score'))
+
+        if update:
+            self.__define_after(10, self.update_control)
+
+    def update_scan(self):
+        res: Tuple[enum, any] = ControlScanType.no_to_done, None
+        try:
+            res = self._ctrl.scan()
+        except ControlNotLogin:
+            ...
+
+        # 需要存储一些数据 谨防被gc释放
+        _cap_img_info = (Image.fromarray(cv2.cvtColor(self._ctrl.get_cap_img(), cv2.COLOR_BGR2RGB)).
+                         transpose(Image.FLIP_LEFT_RIGHT))
+        self._cap_img = ImageTk.PhotoImage(image=_cap_img_info)
+        self._cap_label['image'] = self._cap_img
+
+        if res[0] == ControlScanType.switch_user:
+            self._ctrl.switch_user(res[1])
+            self.update_control(False)
+
+        self.__define_after(10, self.update_scan)
+
+    @staticmethod
+    def __make_font(family: str = 'noto', **kwargs):
+        return font.Font(family=conf.font_d[family], **kwargs)
+
+    def mainloop(self):
+        self._window.mainloop()
+
+
+station = GarbageStation()
+station.mainloop()

+ 6 - 1
equipment/scan.py

@@ -76,7 +76,12 @@ class HGSQRCoder:
         frame = self._cap.get_frame()
         gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
         coder = cv2.QRCodeDetector()
-        data, points, straight_qrcode = coder.detectAndDecode(gray)
+
+        try:
+            data, points, straight_qrcode = coder.detectAndDecode(gray)
+        except cv2.error:
+            return False
+
         old_qr: Optional[QRCode] = self._last_qr
 
         if len(data) > 0:

+ 1 - 1
equipment/scan_garbage.py

@@ -44,7 +44,7 @@ def make_gid_image(gid: gid_t, path: str):
     return True
 
 
-def write_uid_qr(gid: gid_t, path: str, db: DB) -> Tuple[str, Optional[GarbageBag]]:
+def write_gid_qr(gid: gid_t, path: str, db: DB) -> Tuple[str, Optional[GarbageBag]]:
     user = find_garbage(gid, db)
     if user is None:
         return "", None

+ 1 - 1
tool/pic.py

@@ -6,6 +6,6 @@ from PIL import Image, ImageDraw, ImageFont
 def write_text(pos: Tuple[int, int], font: str, text: str, path: str):
     image = Image.open(path)
     draw = ImageDraw.Draw(image)
-    font = ImageFont.truetype(font=conf.font_dict[font], size=20)
+    font = ImageFont.truetype(font=conf.font_d[font], size=20)
     draw.text(pos, text, font=font)
     image.save(path)