Selaa lähdekoodia

feat: 美化用户ID和垃圾袋ID的二维码生成

SongZihuan 3 vuotta sitten
vanhempi
sitoutus
2e76c5cca2
56 muutettua tiedostoa jossa 124 lisäystä ja 139 poistoa
  1. 17 4
      conf/__init__.py
  2. BIN
      conf/font/noto/NotoSans.ttf
  3. BIN
      conf/font/noto/NotoSansSC-Black.otf
  4. BIN
      conf/font/noto/NotoSansSC-Bold.otf
  5. BIN
      conf/font/noto/NotoSansSC-Light.otf
  6. BIN
      conf/font/noto/NotoSansSC-Medium.otf
  7. BIN
      conf/font/noto/NotoSansSC-Regular.otf
  8. BIN
      conf/font/noto/NotoSansSC-Thin.otf
  9. 1 1
      conf/font/noto/OFL.txt
  10. 0 99
      conf/font/noto/README.txt
  11. 6 1
      conf/font/noto/__init__.py
  12. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-Black.ttf
  13. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-Bold.ttf
  14. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-ExtraBold.ttf
  15. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-ExtraLight.ttf
  16. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-Light.ttf
  17. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-Medium.ttf
  18. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-Regular.ttf
  19. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-SemiBold.ttf
  20. BIN
      conf/font/noto/static/NotoSansMono/NotoSansMono-Thin.ttf
  21. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Black.ttf
  22. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Bold.ttf
  23. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-ExtraBold.ttf
  24. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-ExtraLight.ttf
  25. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Light.ttf
  26. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Medium.ttf
  27. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Regular.ttf
  28. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-SemiBold.ttf
  29. BIN
      conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Thin.ttf
  30. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Black.ttf
  31. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Bold.ttf
  32. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-ExtraBold.ttf
  33. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-ExtraLight.ttf
  34. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Light.ttf
  35. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Medium.ttf
  36. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Regular.ttf
  37. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-SemiBold.ttf
  38. BIN
      conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Thin.ttf
  39. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Black.ttf
  40. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Bold.ttf
  41. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-ExtraBold.ttf
  42. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-ExtraLight.ttf
  43. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Light.ttf
  44. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Medium.ttf
  45. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Regular.ttf
  46. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-SemiBold.ttf
  47. BIN
      conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Thin.ttf
  48. BIN
      conf/picture/HGSSystem.png
  49. 2 0
      conf/picture/__init__.py
  50. BIN
      conf/picture/favicon.ico
  51. 3 0
      conf/sys_default.py
  52. 15 2
      equipment/scan.py
  53. 38 8
      equipment/scan_garbage.py
  54. 40 12
      equipment/scan_user.py
  55. 2 1
      tk_ui/admin_event.py
  56. 0 11
      tool/pic.py

+ 17 - 4
conf/__init__.py

@@ -3,8 +3,8 @@
 配置文件
 """
 
-from .font.noto import noto_font
-from .picture import head_pic, rank_bg_pic
+from .font.noto import noto_font, noto_bold_font, noto_medium_font, noto_thin_font, noto_black_font, noto_regular_font
+from .picture import head_pic, rank_bg_pic, logo_pic, logo_ico
 from .args import p_args
 from .equipment import ConfigCapture
 from .sql import ConfigDatabase
@@ -21,5 +21,18 @@ class Config(ConfigTkinter, ConfigSecret, ConfigSystem, ConfUser,
     run_type = p_args['run']
     program = p_args['program']
 
-    font_d = {"noto": noto_font}
-    picture_d = {"head": head_pic, "rank_bg": rank_bg_pic}
+    font_d = {
+        "noto": noto_font,
+        "noto-bold": noto_bold_font,
+        "noto-medium": noto_medium_font,
+        "noto-thin": noto_thin_font,
+        "noto-black": noto_black_font,
+        "noto-regular": noto_regular_font
+    }
+
+    picture_d = {
+        "head": head_pic,
+        "rank_bg": rank_bg_pic,
+        "logo": logo_pic,
+        "logo-ico": logo_ico
+    }

BIN
conf/font/noto/NotoSans.ttf


BIN
conf/font/noto/NotoSansSC-Black.otf


BIN
conf/font/noto/NotoSansSC-Bold.otf


BIN
conf/font/noto/NotoSansSC-Light.otf


BIN
conf/font/noto/NotoSansSC-Medium.otf


BIN
conf/font/noto/NotoSansSC-Regular.otf


BIN
conf/font/noto/NotoSansSC-Thin.otf


+ 1 - 1
conf/font/noto/OFL.txt

@@ -11,7 +11,7 @@ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
 
 PREAMBLE
 The goals of the Open Font License (OFL) are to stimulate worldwide
-development of collaborative font projects, to support the font createion
+development of collaborative font projects, to support the font creation
 efforts of academic and linguistic communities, and to provide a free and
 open framework in which fonts may be shared and improved in partnership
 with others.

+ 0 - 99
conf/font/noto/README.txt

@@ -1,99 +0,0 @@
-Noto Sans Mono Variable Font
-============================
-
-This download contains Noto Sans Mono as both a variable font and static fonts.
-
-Noto Sans Mono is a variable font with these axes:
-  wdth
-  wght
-
-This means all the styles are contained in a single file:
-  NotoSansMono-VariableFont_wdth,wght.ttf
-
-If your app fully supports variable fonts, you can now pick intermediate styles
-that aren’t available as static fonts. Not all apps support variable fonts, and
-in those cases you can use the static font files for Noto Sans Mono:
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Thin.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-ExtraLight.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Light.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Regular.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Medium.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-SemiBold.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Bold.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-ExtraBold.ttf
-  static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Black.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-Thin.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-ExtraLight.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-Light.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-Regular.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-Medium.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-SemiBold.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-Bold.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-ExtraBold.ttf
-  static/NotoSansMono_Condensed/NotoSansMono_Condensed-Black.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Thin.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-ExtraLight.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Light.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Regular.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Medium.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-SemiBold.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Bold.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-ExtraBold.ttf
-  static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Black.ttf
-  static/NotoSansMono/NotoSansMono-Thin.ttf
-  static/NotoSansMono/NotoSansMono-ExtraLight.ttf
-  static/NotoSansMono/NotoSansMono-Light.ttf
-  static/NotoSansMono/NotoSansMono-Regular.ttf
-  static/NotoSansMono/NotoSansMono-Medium.ttf
-  static/NotoSansMono/NotoSansMono-SemiBold.ttf
-  static/NotoSansMono/NotoSansMono-Bold.ttf
-  static/NotoSansMono/NotoSansMono-ExtraBold.ttf
-  static/NotoSansMono/NotoSansMono-Black.ttf
-
-Get started
------------
-
-1. Install the font files you want to use
-
-2. Use your app's font picker to view the font family and all the
-available styles
-
-Learn more about variable fonts
--------------------------------
-
-  https://developers.google.com/web/fundamentals/design-and-ux/typography/variable-fonts
-  https://variablefonts.typenetwork.com
-  https://medium.com/variable-fonts
-
-In desktop apps
-
-  https://theblog.adobe.com/can-variable-fonts-illustrator-cc
-  https://helpx.adobe.com/nz/photoshop/using/fonts.html#variable_fonts
-
-Online
-
-  https://developers.google.com/fonts/docs/getting_started
-  https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide
-  https://developer.microsoft.com/en-us/microsoft-edge/testdrive/demos/variable-fonts
-
-Installing fonts
-
-  MacOS: https://support.apple.com/en-us/HT201749
-  Linux: https://www.google.com/search?q=how+to+install+a+font+on+gnu%2Blinux
-  Windows: https://support.microsoft.com/en-us/help/314960/how-to-install-or-remove-a-font-in-windows
-
-Android Apps
-
-  https://developers.google.com/fonts/docs/android
-  https://developer.android.com/guide/topics/ui/look-and-feel/downloadable-fonts
-
-License
--------
-Please read the full license text (OFL.txt) to understand the permissions,
-restrictions and requirements for usage, redistribution, and modification.
-
-You can use them freely in your products & projects - print or digital,
-commercial or otherwise.
-
-This isn't legal advice, please consider consulting a lawyer and see the full
-license for all details.

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

@@ -1,4 +1,9 @@
 import os
 
 __font = os.path.dirname(os.path.abspath(__file__))
-noto_font = os.path.join(__font, "NotoSans.ttf")  # 基础字体
+noto_font = os.path.join(__font, "NotoSansSC-Light.otf")  # 基础字体
+noto_bold_font = os.path.join(__font, "NotoSansSC-Bold.otf")  # 粗体
+noto_medium_font = os.path.join(__font, "NotoSansSC-Medium.otf")  # 中等加粗
+noto_thin_font = os.path.join(__font, "NotoSansSC-Thin.otf")  # 细字体
+noto_black_font = os.path.join(__font, "NotoSansSC-Black.otf")  # 黑体
+noto_regular_font = os.path.join(__font, "NotoSansSC-Regular.otf")  # Regular

BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-Black.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-Bold.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-ExtraBold.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-ExtraLight.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-Light.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-Medium.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-Regular.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-SemiBold.ttf


BIN
conf/font/noto/static/NotoSansMono/NotoSansMono-Thin.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Black.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Bold.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-ExtraBold.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-ExtraLight.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Light.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Medium.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Regular.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-SemiBold.ttf


BIN
conf/font/noto/static/NotoSansMono_Condensed/NotoSansMono_Condensed-Thin.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Black.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Bold.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-ExtraBold.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-ExtraLight.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Light.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Medium.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Regular.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-SemiBold.ttf


BIN
conf/font/noto/static/NotoSansMono_ExtraCondensed/NotoSansMono_ExtraCondensed-Thin.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Black.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Bold.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-ExtraBold.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-ExtraLight.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Light.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Medium.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Regular.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-SemiBold.ttf


BIN
conf/font/noto/static/NotoSansMono_SemiCondensed/NotoSansMono_SemiCondensed-Thin.ttf


BIN
conf/picture/HGSSystem.png


+ 2 - 0
conf/picture/__init__.py

@@ -3,3 +3,5 @@ import os
 __pic = os.path.dirname(os.path.abspath(__file__))
 head_pic = os.path.join(__pic, "head.png")  # 头像
 rank_bg_pic = os.path.join(__pic, "rank_bg.png")  # 排行榜背景
+logo_ico = os.path.join(__pic, "favicon.ico")  # 排行榜背景
+logo_pic = os.path.join(__pic, "HGSSystem.png")  # 排行榜背景

BIN
conf/picture/favicon.ico


+ 3 - 0
conf/sys_default.py

@@ -23,7 +23,10 @@ class ConfigSystemRelease:
 
     base_location = "KZ"
     search_reset_time = 10  # 搜索间隔的时间
+
     show_uid_len = 12  # 展示uid的长度
+    show_gid_len = 12  # 展示uid的长度
+
     about_info = f'''
 HGSSystem is Garbage Sorting System
 

+ 15 - 2
equipment/scan.py

@@ -1,6 +1,7 @@
 import time
 import threading
 import cv2.cv2 as cv2
+import PIL
 
 from conf import Config
 import qrcode
@@ -54,19 +55,31 @@ class QRCode:
     def get_time(self):
         return self._time
 
-    def make_img(self, image: str) -> bool:
+    def save_img(self, image: str) -> bool:
         try:
             with open(image, "wb") as f:
-                img = qrcode.make(self._data)
+                img = self.make_img()
                 img.save(f)
         except (IOError, FileExistsError, FileNotFoundError):
             return False
         else:
             return True
 
+    def make_img(self) -> PIL.Image:
+        qr = qrcode.QRCode(
+            version=None,
+            error_correction=qrcode.constants.ERROR_CORRECT_H,
+            box_size=10,
+            border=4
+        )
+        qr.add_data(self._data)
+        qr.make(fit=True)
+        return qr.make_image()
+
 
 class HGSQRCoder:
     """ 二维码扫描仪 """
+
     def __init__(self, cap: HGSCapture):
         self._cap = cap
         self._last_qr: Optional[QRCode] = None

+ 38 - 8
equipment/scan_garbage.py

@@ -1,13 +1,19 @@
+import re
+import os.path
+from PIL import Image, ImageDraw, ImageFont
+
+from conf import Config
 from core.garbage import GarbageBag
 from sql.db import DB
 from sql.garbage import find_garbage
 from tool.typing import *
-from .scan import QRCode, HGSCapture, HGSQRCoder
-from tool.pic import write_text
-import re
-import os.path
+from .scan import QRCode
 
 qr_user_pattern = re.compile(r'HGSSystem-QR-GARBAGE:([a-z0-9]+)-END', re.I)
+qr_img_title_font = ImageFont.truetype(font=Config.font_d["noto-bold"], size=35, encoding="unic")
+qr_img_title_b_font = ImageFont.truetype(font=Config.font_d["noto-medium"], size=30, encoding="unic")
+qr_img_info_font = ImageFont.truetype(font=Config.font_d["noto"], size=30, encoding="unic")
+qr_Watermark = ImageFont.truetype(font=Config.font_d["noto-black"], size=55, encoding="unic")
 
 
 def scan_gid(code: QRCode) -> gid_t:
@@ -36,10 +42,34 @@ def __get_gid_qr_file_name(gid: gid_t, path: str):
 
 def make_gid_image(gid: gid_t, path: str):
     qr = QRCode(f"HGSSystem-QR-GARBAGE:{gid}-END")
-    res = qr.make_img(path)
-    if not res:
+    qr_img = qr.make_img().convert("RGB").resize((500, 500))
+    if not qr_img:
         return False
-    write_text((30, 5), "noto", f"GID: {gid}", path)
+
+    title = f"HGSSystem 垃圾袋ID"
+    loc = f"垃圾站: {Config.base_location}"
+    title_width, title_height = qr_img_title_font.getsize(title)
+    loc_width, loc_height = qr_img_title_b_font.getsize(loc)
+    if len(str(gid)) > Config.show_gid_len:
+        gid = gid[-Config.show_gid_len:]
+    gid_width, gid_height = qr_img_info_font.getsize(gid)
+
+    if loc_width > 510:
+        loc_width = 510
+
+    image = Image.new('RGB', (510, 500 + title_height + loc_height + 110), (255, 255, 255))
+    logo_image = Image.open(Config.picture_d['logo']).resize((64, 64))
+
+    draw = ImageDraw.Draw(image)
+    draw.text((((510 - title_width) / 2), 5), title, (0, 0, 0), font=qr_img_title_font)
+    draw.text((((510 - loc_width) / 2), title_height + 5), loc, (0, 0, 0), font=qr_img_title_b_font)
+
+    qr_img.paste(logo_image, (int((500 - 64) / 2), int((500 - 64) / 2)))
+    image.paste(qr_img, (5, title_height + loc_height + 10))
+
+    draw.text((((510 - gid_width) / 2), 500 + title_height + loc_height + 10), gid, (0, 0, 0), font=qr_img_info_font)
+
+    image.save(path)
     return True
 
 
@@ -64,6 +94,6 @@ def write_all_gid_qr(path: str, db: DB, where: str = "") -> List[Tuple[str]]:
         res = cur.fetchone()
         assert len(res) == 1
         path_ = __get_gid_qr_file_name(res[0], path)
-        if make_gid_image(res[0], path_):
+        if make_gid_image(str(res[0]), path_):
             re_list.append((path_,))
     return re_list

+ 40 - 12
equipment/scan_user.py

@@ -1,14 +1,19 @@
+import re
+import os.path
+from PIL import Image, ImageDraw, ImageFont
+
 from conf import Config
 from core.user import User
+from sql import DBBit
 from sql.db import DB
 from sql.user import find_user_by_id
 from tool.typing import *
-from .scan import QRCode, HGSCapture, HGSQRCoder
-from tool.pic import write_text
-import re
-import os.path
+from .scan import QRCode
 
 qr_user_pattern = re.compile(r'HGSSystem-QR-USER:([a-z0-9]{32})-END', re.I)
+qr_img_title_font = ImageFont.truetype(font=Config.font_d["noto-bold"], size=35, encoding="unic")
+qr_img_title_b_font = ImageFont.truetype(font=Config.font_d["noto-medium"], size=30, encoding="unic")
+qr_img_info_font = ImageFont.truetype(font=Config.font_d["noto"], size=30, encoding="unic")
 
 
 def scan_uid(code: QRCode) -> uid_t:
@@ -35,12 +40,34 @@ def __get_uid_qr_file_name(uid: uid_t, name: str, path: str, name_type="nu"):
     return path
 
 
-def make_uid_image(uid: uid_t, name: uname_t, path: str):
+def make_uid_image(uid: uid_t, name: uname_t, is_manager: bool, path: str):
     qr = QRCode(f"HGSSystem-QR-USER:{uid}-END")
-    res = qr.make_img(path)
-    if not res:
+    qr_img = qr.make_img().convert("RGB").resize((500, 500))
+    if qr_img is None:
         return False
-    write_text((60, 5), "noto", f"User: {name} {uid[0: Config.show_uid_len]}", path)
+
+    title = f"HGSSystem 用户ID"
+    title_width, title_height = qr_img_title_font.getsize(title)
+    name_width, name_height = qr_img_title_b_font.getsize(name)
+    uid_width, uid_height = qr_img_info_font.getsize(uid[:Config.show_uid_len])
+    uid_color = (220, 20, 60) if is_manager else (0, 0, 0)
+
+    if name_width > 510:
+        name_width = 510
+
+    image = Image.new('RGB', (510, 500 + title_height + name_height + 110), (255, 255, 255))
+    logo_image = Image.open(Config.picture_d['logo']).resize((64, 64))
+
+    draw = ImageDraw.Draw(image)
+    draw.text((((510 - title_width) / 2), 5), title, (0, 0, 0), font=qr_img_title_font)
+    draw.text((((510 - name_width) / 2), title_height + 5), name, (0, 0, 0), font=qr_img_title_b_font)
+
+    qr_img.paste(logo_image, (int((500 - 64) / 2), int((500 - 64) / 2)))
+    image.paste(qr_img, (5, title_height + name_height + 10))
+    draw.text((((510 - uid_width) / 2), 500 + title_height + name_height + 10), uid[:Config.show_uid_len],
+              uid_color, font=qr_img_info_font)
+
+    image.save(path)
     return True
 
 
@@ -50,22 +77,23 @@ def write_uid_qr(uid: uid_t, path: str, db: DB, name="nu") -> Tuple[str, Optiona
         return "", None
 
     user_name = user.get_name()
+    is_manager = user.is_manager()
     path = __get_uid_qr_file_name(uid, user_name, path, name)
-    if make_uid_image(uid, user_name, path):
+    if make_uid_image(uid, user_name, is_manager, path):
         return path, user
     return "", None
 
 
 def write_all_uid_qr(path: str, db: DB, name="nu", where: str = "") -> List[str]:
-    cur = db.search(columns=["UserID", "Name"], table="user", where=where)
+    cur = db.search(columns=["UserID", "Name", "IsManager"], table="user", where=where)
     if cur is None:
         return []
 
     re_list = []
     for _ in range(cur.rowcount):
         res = cur.fetchone()
-        assert len(res) == 2
+        assert len(res) == 3
         path_ = __get_uid_qr_file_name(res[0], res[1], path, name)
-        if make_uid_image(res[0], res[1], path_):
+        if make_uid_image(res[0], res[1], res[2] == DBBit.BIT_1, path_):
             re_list.append(path_)
     return re_list

+ 2 - 1
tk_ui/admin_event.py

@@ -151,7 +151,8 @@ class ExportUserByIDEvent(AdminEventBase):
 
 class ExportUserAdvancedEvent(AdminEventBase):
     def func(self, path, where):
-        return self.station.export_user(path, where)
+        res = self.station.export_user(path, where)
+        return res
 
     def __init__(self, station):
         super(ExportUserAdvancedEvent, self).__init__(station)

+ 0 - 11
tool/pic.py

@@ -1,11 +0,0 @@
-from conf import Config
-from .typing import *
-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=Config.font_d[font], size=20)
-    draw.text(pos, text, font=font)
-    image.save(path)