admin.py 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. import abc
  2. import tkinter as tk
  3. from tkinter import messagebox as msg
  4. from tkinter import ttk
  5. from conf import Config
  6. from core.garbage import GarbageBag
  7. from core.user import User
  8. from equipment.scan_garbage import write_gid_qr, write_all_gid_qr
  9. from equipment.scan_user import write_uid_qr, write_all_uid_qr
  10. from .event import TkEventMain
  11. from sql.db import DB, search_from_garbage_checker_user
  12. from sql.garbage import (create_new_garbage, search_garbage_by_fields, search_from_garbage_view,
  13. del_garbage, del_garbage_not_use, del_garbage_wait_check, del_garbage_has_check,
  14. del_garbage_where_scan_not_use, del_garbage_where_scan_wait_check,
  15. del_garbage_where_scan_has_check,
  16. del_garbage_where_not_use, del_garbage_where_wait_check, del_garbage_where_has_check,
  17. del_all_garbage, del_all_garbage_scan,
  18. update_garbage_check, update_garbage_type)
  19. from sql.user import (create_new_user, del_user, del_user_from_where, del_user_from_where_scan,
  20. search_user_by_fields, search_from_user_view,
  21. update_user_score, update_user_reputation,
  22. creat_user_from_csv, creat_auto_user_from_csv)
  23. from tool.tk import make_font
  24. from tool.typing import *
  25. class AdminStationBase(TkEventMain, metaclass=abc.ABCMeta):
  26. """
  27. AdminStation基类
  28. 封装管理员的相关操作
  29. 主要是柯里化 sql相关函数
  30. """
  31. def __init__(self, db: DB):
  32. self._admin: Optional[User] = None
  33. self._db = db
  34. super(AdminStationBase, self).__init__()
  35. def get_db(self):
  36. return self._db
  37. def create_garbage(self, path: Optional[str], num: int = 1) -> "List[tuple[str, Optional[GarbageBag]]]":
  38. re = []
  39. for _ in range(num):
  40. gar = create_new_garbage(self._db)
  41. assert gar
  42. if path is not None:
  43. res = write_gid_qr(gar.get_gid(), path, self._db)
  44. re.append(res)
  45. else:
  46. re.append(("", gar))
  47. return re
  48. def export_garbage_by_gid(self, path: Optional[str], gid: gid_t) -> Tuple[str, Optional[GarbageBag]]:
  49. return write_gid_qr(gid, path, self._db)
  50. def export_garbage(self, path: Optional[str], where: str) -> List[Tuple[str]]:
  51. return write_all_gid_qr(path, self._db, where=where)
  52. def create_user(self, name: uname_t, passwd: passwd_t, phone: str, manager: bool) -> Optional[User]:
  53. return create_new_user(name, passwd, phone, manager, self._db)
  54. def create_user_from_csv(self, path) -> List[User]:
  55. return creat_user_from_csv(path, self._db)
  56. def create_auto_user_from_csv(self, path) -> List[User]:
  57. return creat_auto_user_from_csv(path, self._db)
  58. def export_user_by_uid(self, path: str, uid: uid_t) -> Tuple[str, Optional[User]]:
  59. return write_uid_qr(uid, path, self._db)
  60. def export_user(self, path: str, where) -> List[str]:
  61. return write_all_uid_qr(path, self._db, where=where)
  62. def del_garbage_not_use(self, gid: gid_t) -> bool:
  63. return del_garbage_not_use(gid, self._db)
  64. def del_garbage_wait_check(self, gid: gid_t) -> bool:
  65. return del_garbage_wait_check(gid, self._db)
  66. def del_garbage_has_check(self, gid: gid_t) -> bool:
  67. return del_garbage_has_check(gid, self._db)
  68. def del_garbage(self, gid: gid_t) -> bool:
  69. return del_garbage(gid, self._db)
  70. def del_garbage_where_not_use(self, where) -> int:
  71. return del_garbage_where_not_use(where, self._db)
  72. def del_garbage_where_wait_check(self, where) -> int:
  73. return del_garbage_where_wait_check(where, self._db)
  74. def del_garbage_where_has_check(self, where) -> int:
  75. return del_garbage_where_has_check(where, self._db)
  76. def del_garbage_where_scan_not_use(self, where) -> int:
  77. return del_garbage_where_scan_not_use(where, self._db)
  78. def del_garbage_where_scan_wait_check(self, where) -> int:
  79. return del_garbage_where_scan_wait_check(where, self._db)
  80. def del_garbage_where_scan_has_check(self, where) -> int:
  81. return del_garbage_where_scan_has_check(where, self._db)
  82. def del_all_garbage_scan(self) -> int:
  83. return del_all_garbage_scan(self._db)
  84. def del_all_garbage(self) -> int:
  85. return del_all_garbage(self._db)
  86. def del_user(self, uid: uid_t) -> bool:
  87. return del_user(uid, self._db)
  88. def del_user_from_where_scan(self, where: str) -> int:
  89. return del_user_from_where_scan(where, self._db)
  90. def del_user_from_where(self, where: str) -> int:
  91. return del_user_from_where(where, self._db)
  92. def search_user(self, columns, uid, name, phone):
  93. return search_user_by_fields(columns, uid, name, phone, self._db)
  94. def search_user_advanced(self, columns, sql):
  95. return search_from_user_view(columns, sql, self._db)
  96. def search_garbage(self, columns, key_values: dict):
  97. return search_garbage_by_fields(columns, **key_values, db=self._db)
  98. def search_garbage_advanced(self, columns, sql):
  99. return search_from_garbage_view(columns, sql, self._db)
  100. def search_advanced(self, columns, sql):
  101. return search_from_garbage_checker_user(columns, sql, self._db)
  102. def update_user_score(self, score: score_t, where: str) -> int:
  103. return update_user_score(where, score, self._db)
  104. def update_user_reputation(self, reputation: score_t, where: str) -> int:
  105. return update_user_reputation(where, reputation, self._db)
  106. def update_garbage_type(self, type_: int, where: str):
  107. return update_garbage_type(where, type_, self._db)
  108. def update_garbage_check(self, check_: str, where: str):
  109. if check_ == 'pass':
  110. check = True
  111. elif check_ == 'fail':
  112. check = False
  113. else:
  114. return -1
  115. return update_garbage_check(where, check, self._db)
  116. @abc.abstractmethod
  117. def login_call(self):
  118. ...
  119. def login(self, user: User) -> bool:
  120. if user is not None and user.is_manager():
  121. self._admin = user
  122. return True
  123. else:
  124. return False
  125. def logout(self):
  126. if self._admin is not None:
  127. self._admin.destruct()
  128. self._admin = None
  129. def exit_(self):
  130. if self._admin is not None:
  131. self._admin.destruct()
  132. self._admin = None
  133. @abc.abstractmethod
  134. def show_loading(self, title: str):
  135. ...
  136. @abc.abstractmethod
  137. def stop_loading(self):
  138. ...
  139. @abc.abstractmethod
  140. def set_after_run(self, ms, func, *args):
  141. ...
  142. @abc.abstractmethod
  143. def to_menu(self, name: str = "主页"):
  144. ...
  145. @abc.abstractmethod
  146. def to_program(self, name: str = "欢迎页"):
  147. ...
  148. @abc.abstractmethod
  149. def show_msg(self, title, info, msg_type='提示'):
  150. ...
  151. @abc.abstractmethod
  152. def show_warning(self, title, info):
  153. ...
  154. @abc.abstractmethod
  155. def hide_msg(self):
  156. ...
  157. from . import admin_program as tk_program
  158. from . import admin_menu as tk_menu
  159. from . import admin_event as tk_event
  160. class AdminStation(AdminStationBase):
  161. """
  162. AdminStation 管理员系统
  163. 使用tkinter作为GUI
  164. 构造与GarbageStation类似
  165. """
  166. def set_after_run(self, ms, func, *args): # super.__init__可能会调用
  167. self.init_after_run_list.append((ms, func, args))
  168. def __conf_set_after_run(self):
  169. for ms, func, args in self.init_after_run_list:
  170. self._window.after(ms, func, *args)
  171. def set_after_run_now(self, ms, func, *args):
  172. self._window.after(ms, func, *args)
  173. def __init__(self, db: DB, refresh_delay: int = Config.tk_refresh_delay):
  174. self.init_after_run_list: List[Tuple[int, Callable, Tuple]] = []
  175. super().__init__(db)
  176. self.refresh_delay = refresh_delay
  177. self._window = tk.Tk()
  178. self.login_window = None
  179. self._sys_height = self._window.winfo_screenheight()
  180. self._sys_width = self._window.winfo_screenwidth()
  181. self._win_height = int(self._sys_height * (2 / 3))
  182. self._win_width = int(self._sys_width * (2 / 3))
  183. self.__conf_windows(before_load=True)
  184. self._full_screen = False
  185. self._is_loading = False
  186. self._disable_all_btn = False
  187. self._menu_now: Optional[Tuple[str, tk.Frame, tk_menu.AdminMenu]] = None
  188. self._program_now: Optional[Tuple[str, tk.Frame, tk_program.AdminProgram]] = None
  189. self.__conf_font_size()
  190. self.__conf_create_tk()
  191. self.__conf_create_menu()
  192. self.__conf_create_program()
  193. self.__conf_windows(before_load=False)
  194. self.__conf_tk() # 在所有的Creat完成后才conf_tk
  195. self.__show_login_window() # 显示登录窗口, Debug期间暂时注释该代码
  196. self.__conf_set_after_run()
  197. def __conf_windows(self, before_load: bool = True):
  198. if before_load:
  199. self._window.title('HGSSystem: Manage Station')
  200. self._window.geometry(f'{self._win_width}x{self._win_height}')
  201. self._window['bg'] = Config.tk_win_bg
  202. self._window.resizable(False, False)
  203. self._window.protocol("WM_DELETE_WINDOW", lambda: self.main_exit())
  204. self._window.title('HGSSystem: Manage Station 加载中')
  205. self._window.iconbitmap(Config.picture_d["logo-ico"])
  206. else:
  207. self._window.title('HGSSystem: Manage Station')
  208. def __conf_create_tk(self):
  209. self._menu_back = tk.Frame(self._window)
  210. self._menu_line = tk.Label(self._menu_back) # 下划线
  211. self._menu_title: Tuple[tk.Label, tk.Variable] = (tk.Label(self._menu_back), tk.StringVar())
  212. self._menu_dict: Dict[str, tk_menu.AdminMenu] = {}
  213. self._menu_list: List[str] = [] # 菜单回溯
  214. self._program_back = tk.Frame(self._window)
  215. self._program_title: Tuple[tk.Label, tk.Variable] = (tk.Label(self._program_back), tk.StringVar())
  216. self._program_dict: Dict[str, tk_program.AdminProgram] = {}
  217. self._win_ctrl_button: List[tk.Button, tk.Button, tk.Button] = [tk.Button(self._menu_back),
  218. tk.Button(self._menu_back),
  219. tk.Button(self._window),
  220. tk.Button(self._window),
  221. tk.Button(self._window)]
  222. self._msg_frame = tk.Frame(self._window)
  223. self._msg_line = tk.Label(self._msg_frame)
  224. self._msg_label = tk.Label(self._msg_frame), tk.Label(self._msg_frame), tk.StringVar(), tk.StringVar()
  225. self._msg_hide = tk.Button(self._msg_frame)
  226. self._loading_pro = ttk.Progressbar(self._window)
  227. def __conf_font_size(self, n: int = 1):
  228. self._login_title_font_size = int(12 * n)
  229. self._login_btn_font_size = int(12 * n)
  230. self._win_ctrl_font_size = int(15 * n)
  231. self._menu_title_font_size = int(17 * n)
  232. self._program_title_font_size = int(14 * n)
  233. self._msg_font_size = int(20 * n)
  234. def __conf_tk(self, n: int = 1):
  235. self.__conf_win_ctrl_button()
  236. self.__conf_menu_title()
  237. self.__conf_menu(n)
  238. self.__conf_program_title()
  239. self.__conf_program(n)
  240. self.__conf_loading()
  241. self.__conf_msg()
  242. self.to_menu() # 显示主页面
  243. self.to_program()
  244. def __conf_win_ctrl_button(self):
  245. title_font = make_font(size=self._win_ctrl_font_size)
  246. title_font_bold = make_font(size=self._win_ctrl_font_size, weight="bold")
  247. for bt in self._win_ctrl_button:
  248. bt: tk.Button
  249. bt['bg'] = Config.tk_btn_bg
  250. bt['font'] = title_font
  251. bt_main: tk.Button = self._win_ctrl_button[1]
  252. bt_main['text'] = '主页'
  253. bt_main['font'] = title_font_bold
  254. bt_main['command'] = lambda: self.__to_main_menu()
  255. bt_main.place(relx=0.02, rely=0.86, relwidth=0.96, relheight=0.06)
  256. bt_back: tk.Button = self._win_ctrl_button[0]
  257. bt_back['text'] = '后退'
  258. bt_back['font'] = title_font_bold
  259. bt_back['state'] = 'disable'
  260. bt_back['command'] = lambda: self.__to_back_menu()
  261. bt_back.place(relx=0.02, rely=0.93, relwidth=0.96, relheight=0.06)
  262. rely = 0.02
  263. bt_help: tk.Button = self._win_ctrl_button[2]
  264. bt_help['text'] = '帮助'
  265. bt_help['command'] = lambda: self.to_program()
  266. bt_help.place(relx=0.81, rely=rely, relwidth=0.05, relheight=0.05)
  267. bt_about: tk.Button = self._win_ctrl_button[3]
  268. bt_about['text'] = '关于'
  269. bt_about['command'] = lambda: self.to_program("关于")
  270. bt_about.place(relx=0.87, rely=rely, relwidth=0.05, relheight=0.05)
  271. bt_exit: tk.Button = self._win_ctrl_button[4]
  272. bt_exit['text'] = '退出'
  273. bt_exit['command'] = lambda: self.main_exit()
  274. bt_exit.place(relx=0.93, rely=rely, relwidth=0.05, relheight=0.05)
  275. def set_ctrl_back_button(self):
  276. if len(self._menu_list) <= 1:
  277. self._win_ctrl_button[0]['state'] = 'disable'
  278. else:
  279. self._win_ctrl_button[0]['state'] = 'normal'
  280. def __to_main_menu(self):
  281. self._menu_list = []
  282. self.to_menu()
  283. def __to_back_menu(self):
  284. assert len(self._menu_list) > 1
  285. self._menu_list.pop() # 弹出最后一个元素
  286. self.to_menu(self._menu_list.pop()) # 再弹出一个元素
  287. def __conf_create_menu(self):
  288. frame_list = []
  289. for i in tk_menu.all_menu:
  290. self._window.update()
  291. frame_list.append(i(self, self._menu_back, Config.tk_second_win_bg))
  292. for i in frame_list:
  293. name = i.get_menu_title()
  294. self._menu_dict[name] = i
  295. def __conf_menu(self, n: int = 1):
  296. for i in self._menu_dict:
  297. menu = self._menu_dict[i]
  298. menu.conf_gui(Config.tk_btn_bg, n)
  299. def __conf_menu_title(self):
  300. self._menu_back['bg'] = Config.tk_second_win_bg
  301. self._menu_back['bd'] = 5
  302. self._menu_back['relief'] = "ridge"
  303. title_font = make_font(size=self._menu_title_font_size, weight="bold")
  304. self._menu_title[0]['bg'] = Config.tk_second_win_bg
  305. self._menu_title[0]['font'] = title_font
  306. self._menu_title[0]['textvariable'] = self._menu_title[1]
  307. self._menu_line['bg'] = '#000000'
  308. # 不立即显示
  309. def to_menu(self, name: str = "主页"):
  310. if self._menu_now is not None:
  311. self._menu_now[1].place_forget()
  312. menu = self._menu_dict.get(name)
  313. if menu is None:
  314. self._menu_title[1].set(f'菜单错误')
  315. self.show_msg("菜单错误", f"系统无法找到菜单:\n {name}")
  316. return
  317. name, frame = menu.get_menu_frame()
  318. self._menu_title[1].set(name)
  319. self._menu_back.place(relx=0.02, rely=0.02, relwidth=0.20, relheight=0.96)
  320. self._menu_line.place(relx=0.06, rely=0.065, relwidth=0.88, height=1) # 一个像素的高度即可
  321. self._menu_title[0].place(relx=0.02, rely=0.02, relwidth=0.96, relheight=0.03)
  322. frame.place(relx=0.02, rely=0.07, relwidth=0.96, relheight=0.79)
  323. self._menu_list.append(name)
  324. self._menu_now = name, frame, menu
  325. self.set_ctrl_back_button()
  326. def __conf_program_title(self):
  327. self._program_back['bg'] = Config.tk_second_win_bg
  328. self._program_back['relief'] = "ridge"
  329. self._program_back['bd'] = 5
  330. title_font = make_font(size=self._program_title_font_size, weight="bold")
  331. self._program_title[0]['bg'] = '#2468a2'
  332. self._program_title[0]['fg'] = "#F0F8FF"
  333. self._program_title[0]['font'] = title_font
  334. self._program_title[0]['anchor'] = 'w'
  335. self._program_title[0]['textvariable'] = self._program_title[1]
  336. # 不立即显示
  337. def __conf_create_program(self):
  338. program_list = []
  339. for i in tk_program.all_program:
  340. self._window.update()
  341. program_list.append(i(self, self._program_back, Config.tk_second_win_bg))
  342. for i in program_list:
  343. name = i.get_title()
  344. self._program_dict[name] = i
  345. def __conf_program(self, n: int = 1):
  346. for i in self._program_dict:
  347. program = self._program_dict[i]
  348. program.conf_gui(n)
  349. def to_program(self, name: str = "欢迎页"):
  350. if self._program_now is not None:
  351. self._program_now[2].leave_program()
  352. self._program_now[1].place_forget()
  353. program = self._program_dict.get(name)
  354. if program is None:
  355. self._program_title[1].set(f' 程序加载错误')
  356. self.show_msg("程序错误", f"系统无法找到程序:\n {name}")
  357. return
  358. program.to_program()
  359. name, frame = program.get_program_frame()
  360. self.__show_program()
  361. self._program_title[1].set(f' {name}')
  362. self._program_title[0].place(relx=0.00, rely=0.00, relwidth=1, relheight=0.05)
  363. frame.place(relx=0.02, rely=0.06, relwidth=0.96, relheight=0.92)
  364. self._program_now = name, frame, program
  365. def __show_program(self):
  366. self._program_back.place(relx=0.26, rely=0.1, relwidth=0.68, relheight=0.84)
  367. def __hide_program(self):
  368. self._program_back.place_forget()
  369. def __conf_loading(self):
  370. self._loading_pro['mode'] = 'indeterminate'
  371. self._loading_pro['orient'] = 'horizontal'
  372. self._loading_pro['maximum'] = 50
  373. def show_loading(self, _):
  374. self._is_loading = True
  375. self.set_all_btn_disable()
  376. self._loading_pro['value'] = 0
  377. self._loading_pro.place(relx=0.30, rely=0.035, relwidth=0.48, relheight=0.03)
  378. self._loading_pro.start(50)
  379. def stop_loading(self):
  380. self._is_loading = False
  381. self._loading_pro.place_forget()
  382. self._loading_pro.stop()
  383. self.set_reset_all_btn()
  384. def __conf_msg(self):
  385. title_font = make_font(size=self._msg_font_size + 1, weight="bold")
  386. info_font = make_font(size=self._msg_font_size - 1)
  387. self._msg_frame['bg'] = Config.tk_second_win_bg
  388. self._msg_frame['bd'] = 5
  389. self._msg_frame['relief'] = "ridge"
  390. # frame 不会立即显示
  391. self._msg_label[0]['font'] = title_font
  392. self._msg_label[0]['bg'] = Config.tk_second_win_bg
  393. self._msg_label[0]['anchor'] = 'w'
  394. self._msg_label[0]['textvariable'] = self._msg_label[2]
  395. self._msg_line['bg'] = '#000000'
  396. self._msg_label[1]['font'] = info_font
  397. self._msg_label[1]['bg'] = Config.tk_second_win_bg
  398. self._msg_label[1]['anchor'] = 'nw'
  399. self._msg_label[1]['textvariable'] = self._msg_label[3]
  400. self._msg_label[1]['justify'] = 'left'
  401. self._msg_label[0].place(relx=0.05, rely=0.05, relwidth=0.9, relheight=0.1)
  402. self._msg_line.place(relx=0.05, rely=0.15, relwidth=0.9, height=1) # 一个像素的高度即可
  403. self._msg_label[1].place(relx=0.075, rely=0.2, relwidth=0.85, relheight=0.58)
  404. self._msg_hide['font'] = info_font
  405. self._msg_hide['text'] = '关闭'
  406. self._msg_hide['bg'] = Config.tk_btn_bg
  407. self._msg_hide['command'] = lambda: self.hide_msg()
  408. self._msg_hide.place(relx=0.375, rely=0.80, relwidth=0.25, relheight=0.10)
  409. def show_msg(self, title, info, msg_type='提示'):
  410. assert not self._is_loading # loading 时不显示msg
  411. self.set_all_btn_disable()
  412. self._msg_label[2].set(f'{msg_type}: {title}')
  413. self._msg_label[3].set(f'{info}')
  414. frame_width = self._win_width * 0.50
  415. self._msg_label[1]['wraplength'] = frame_width * 0.85 - 5 # 设定自动换行的像素
  416. self._msg_frame.place(relx=0.30, rely=0.25, relwidth=0.55, relheight=0.50)
  417. # 不隐藏元素, 隐藏后界面会显得单调
  418. def show_warning(self, title, info):
  419. self.show_msg(title, info, "警告")
  420. def hide_msg(self):
  421. self.set_reset_all_btn()
  422. self._msg_frame.place_forget()
  423. def set_all_btn_disable(self):
  424. for btn in self._win_ctrl_button[:-1]: # Exit 不设置disable
  425. btn['state'] = 'disable'
  426. if self._menu_list != 0:
  427. menu = self._menu_dict.get(self._menu_list[-1], None)
  428. assert menu is not None
  429. menu.set_disable()
  430. if self._program_now is not None:
  431. self._program_now[2].set_disable()
  432. def set_reset_all_btn(self):
  433. for btn in self._win_ctrl_button[:-1]:
  434. btn['state'] = 'normal'
  435. self.set_ctrl_back_button()
  436. if self._menu_list != 0:
  437. menu = self._menu_dict.get(self._menu_list[-1], None)
  438. assert menu is not None
  439. menu.reset_disable()
  440. if self._program_now is not None:
  441. self._program_now[2].reset_disable()
  442. def __show_login_window(self):
  443. self.login_window: Optional[tk.Toplevel] = tk.Toplevel()
  444. self.login_window.title("HGSSystem Login")
  445. self.login_window.iconbitmap(Config.picture_d["logo-ico"])
  446. height = int(self._sys_height * (1 / 5))
  447. width = int(height * 2)
  448. if width > self._sys_width:
  449. width = int(self._sys_width * (2 / 3))
  450. height = int(width / 2)
  451. self.login_window.geometry(f'{width}x{height}')
  452. self.login_window['bg'] = Config.tk_win_bg
  453. self.login_window.resizable(False, False)
  454. self.login_window.protocol("WM_DELETE_WINDOW", lambda: self.login_exit())
  455. self._login_frame = tk.Frame(self.login_window)
  456. self._login_name = [tk.Label(self._login_frame), tk.Entry(self._login_frame), tk.StringVar()]
  457. self._login_passwd = [tk.Label(self._login_frame), tk.Entry(self._login_frame), tk.StringVar()]
  458. self._login_btn = [tk.Button(self.login_window), tk.Button(self.login_window)]
  459. self.__conf_login_window()
  460. self.hide_main()
  461. self.login_window.deiconify()
  462. def __conf_login_window(self):
  463. title_font = make_font(size=self._login_title_font_size)
  464. btn_font = make_font(size=self._login_btn_font_size, weight="bold")
  465. self._login_frame['bg'] = "#EEE8AA"
  466. self._login_frame['bd'] = 5
  467. self._login_frame['relief'] = "ridge"
  468. self._login_frame.place(relx=0.1, rely=0.2, relwidth=0.8, relheight=0.45)
  469. for lb, text in zip([self._login_name[0], self._login_passwd[0]], ["账户:", "密码:"]):
  470. lb['bg'] = "#EEE8AA"
  471. lb['font'] = title_font
  472. lb['text'] = text
  473. lb['anchor'] = 'e'
  474. for lb, var in zip([self._login_name[1], self._login_passwd[1]], [self._login_name[2], self._login_passwd[2]]):
  475. lb['font'] = title_font
  476. lb['textvariable'] = var
  477. self._login_name[0].place(relx=0.00, rely=0.13, relwidth=0.25, relheight=0.30)
  478. self._login_passwd[0].place(relx=0.00, rely=0.53, relwidth=0.25, relheight=0.30)
  479. self._login_name[1].place(relx=0.26, rely=0.13, relwidth=0.64, relheight=0.30)
  480. self._login_passwd[1]['show'] = "*"
  481. self._login_passwd[1].place(relx=0.26, rely=0.53, relwidth=0.64, relheight=0.30)
  482. self._login_btn[0]['bg'] = Config.tk_btn_bg
  483. self._login_btn[0]['font'] = btn_font
  484. self._login_btn[0]['text'] = '登录'
  485. self._login_btn[0]['command'] = lambda: self.login_call()
  486. self._login_btn[0].place(relx=0.54, rely=0.70, relwidth=0.16, relheight=0.15)
  487. self._login_btn[1]['bg'] = Config.tk_btn_bg
  488. self._login_btn[1]['font'] = btn_font
  489. self._login_btn[1]['text'] = '退出'
  490. self._login_btn[1]['command'] = lambda: self.login_exit()
  491. self._login_btn[1].place(relx=0.74, rely=0.70, relwidth=0.16, relheight=0.15)
  492. def login_call(self):
  493. event = tk_event.LoginEvent(self).start(self._login_name[2].get(), self._login_passwd[2].get())
  494. self.push_event(event)
  495. def login(self, user: User):
  496. if super(AdminStation, self).login(user):
  497. self.login_window.destroy()
  498. self.login_window = None
  499. self.show_main()
  500. else:
  501. msg.showerror("登录失败", "请重新尝试")
  502. self._login_name[2].set('')
  503. self._login_passwd[2].set('')
  504. def logout(self):
  505. super(AdminStation, self).logout()
  506. self.__show_login_window()
  507. def login_exit(self):
  508. if not msg.askokcancel('退出', '确定退出管理员系统吗?'):
  509. return
  510. if self.login_window is not None:
  511. self.login_window.destroy()
  512. self.exit_win()
  513. def main_exit(self):
  514. if not msg.askokcancel('退出', '确定退出管理员系统吗?'):
  515. return
  516. self.exit_win()
  517. def hide_main(self):
  518. self._window.withdraw()
  519. def show_main(self):
  520. self._window.update()
  521. self._window.deiconify()
  522. def mainloop(self):
  523. self._window.mainloop()
  524. def exit_win(self):
  525. self.exit_()
  526. self._window.destroy()