logic_ui.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. import hashlib
  2. import json
  3. import time
  4. import tkinter
  5. import uuid
  6. from datetime import datetime
  7. from tkinter import messagebox
  8. import requests
  9. from common.sql_lite import get_global_db_connection
  10. from config import conf
  11. from db.batch_task import batch_task_get_list, batch_task_status, batch_task_update_status
  12. from logic.logic_batch_task_create import open_batch_task_create_win
  13. from logic.logic_batch_task_detail import open_batch_task_detail_win
  14. from service.batch_task import stop_batch_task, start_batch_task
  15. from service.robot import get_robot
  16. from ui.ui import WinGUI
  17. class Win(WinGUI):
  18. def __init__(self):
  19. super().__init__()
  20. self.__event_bind()
  21. self.__style_config()
  22. self.__is_started = False
  23. self.selection_batch_task_id = None
  24. def __event_bind(self):
  25. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_save.bind('<Button-1>', self.save_event)
  26. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_start.bind('<Button-1>', self.start_event)
  27. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_pause.bind('<Button-1>', self.stop_event)
  28. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_version.bind('<Button-1>', self.version_event)
  29. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_button_create.bind('<Button-1>', self.batch_task_create_event)
  30. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.bind('<Double-1>',
  31. self.batch_task_detail_event)
  32. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.bind('<Button-1>', self.just_click_event)
  33. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.bind('<Button-3>',
  34. self.batch_task_action_event)
  35. pass
  36. def __style_config(self):
  37. pass
  38. def version_event(self, event):
  39. messagebox.showinfo('版本信息', '当前版本:v1.0.0')
  40. def stop_event(self, event):
  41. stop_batch_task()
  42. if self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_pause.cget('state') == tkinter.DISABLED:
  43. return
  44. robot = get_robot()
  45. if robot is not None:
  46. robot.wcf.cleanup()
  47. robot = None
  48. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_start.config(state=tkinter.NORMAL)
  49. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_pause.config(state=tkinter.DISABLED)
  50. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_button_create.config(state=tkinter.DISABLED)
  51. self.__is_started = False
  52. messagebox.showinfo('提示', '助手已停止运行!')
  53. @staticmethod
  54. def check_token():
  55. # 获取当前网卡mac地址
  56. mac = uuid.getnode()
  57. url = "https://wxadminapi.gkscrm.com/wechat-api/token/check"
  58. token = str(conf().get("token"))
  59. payload = json.dumps({
  60. "token": token,
  61. "mac": str(mac)
  62. })
  63. headers = {
  64. 'Content-Type': 'application/json'
  65. }
  66. response = requests.request("POST", url, headers=headers, data=payload)
  67. if response.status_code == 200:
  68. resp = json.loads(response.text)
  69. if resp['valid'] == True:
  70. sign = resp['sign']
  71. timestamp = resp['timestamp']
  72. # 获取当前unix时间戳
  73. current_timestamp = int(time.time())
  74. if abs(current_timestamp - int(timestamp)) > 180:
  75. messagebox.showerror('错误', '验证失败!请重试')
  76. return False
  77. # 创建一个MD5哈希对象
  78. md5_hash = hashlib.md5()
  79. # 更新哈希对象
  80. md5_hash.update(token.encode('utf-8'))
  81. # 获取十六进制格式的MD5哈希值
  82. md5_token = md5_hash.hexdigest()
  83. md5_hash = hashlib.md5()
  84. md5_hash.update(str(mac).encode('utf-8'))
  85. md5_mac = md5_hash.hexdigest()
  86. md5_hash = hashlib.md5()
  87. md5_hash.update(str(timestamp).encode('utf-8'))
  88. md5_timestamp = md5_hash.hexdigest()
  89. md5_hash = hashlib.md5()
  90. md5_hash.update((md5_token + md5_mac + md5_timestamp).encode('utf-8'))
  91. md5_sign = md5_hash.hexdigest()
  92. if md5_sign != sign:
  93. messagebox.showerror('错误', 'token验证失败!')
  94. return False
  95. return True
  96. else:
  97. messagebox.showerror('错误',
  98. 'token已失效 或 与当前设备未绑定,每个token只能绑定一台设备!请填入和当前设备绑定的token,或者获取新的token!')
  99. return False
  100. else:
  101. messagebox.showerror('错误', '您的网络状态异常!请稍候重试')
  102. return False
  103. def start_event(self, event):
  104. if self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_start.cget('state') == tkinter.DISABLED:
  105. return
  106. if not self.check_token():
  107. return
  108. # 接收消息
  109. # robot.enableRecvMsg() # 可能会丢消息?
  110. robot = get_robot()
  111. robot.enableReceivingMsg() # 加队列
  112. if robot.wcf.is_login():
  113. self.__is_started = True
  114. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_start.config(state='disabled')
  115. self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_button_pause.config(state='normal')
  116. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_button_create.config(state='normal')
  117. messagebox.showinfo('提示', '助手开始运行!')
  118. start_batch_task()
  119. wx_wxid = robot.wcf.get_self_wxid()
  120. connection = get_global_db_connection()
  121. def refresh_list():
  122. # 清空列表
  123. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.delete(
  124. *self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.get_children())
  125. # 查询数据
  126. cursor = connection.cursor()
  127. try:
  128. results = batch_task_get_list(cursor, wx_wxid)
  129. finally:
  130. cursor.close()
  131. for result in results:
  132. created_at = datetime.fromtimestamp(result["created_at"]).strftime("%Y-%m-%d %H:%M:%S")
  133. status = batch_task_status[result["status"]]
  134. values = (
  135. created_at, status, f"{result['success'] + result['fail']}/{result['total']}", result['fail'],
  136. result['content'])
  137. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.insert('', "end",
  138. iid=result['id'],
  139. values=values)
  140. # 维持选中状态
  141. if result['id'] == self.selection_batch_task_id:
  142. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.selection_set(result['id'])
  143. # 每 3秒调用一次这个函数
  144. self.tk_tabs_main_tabs.after(3000, refresh_list)
  145. self.tk_tabs_main_tabs.after(0, refresh_list)
  146. def save_event(self, event):
  147. conf().update({
  148. "api_base": self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_input_api_base.get(),
  149. "api_key": self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_input_api_key.get(),
  150. "token": self.tk_tabs_main_tabs.tk_tabs_main_tabs_0.tk_input_token.get()
  151. })
  152. # 将字典写入 JSON 文件
  153. with open('config.json', 'w') as json_file:
  154. json.dump(conf(), json_file, indent=4)
  155. messagebox.showinfo('提示', '保存文件成功!')
  156. def batch_task_create_event(self, event):
  157. if self.__is_started:
  158. open_batch_task_create_win()
  159. def batch_task_detail_event(self, event):
  160. # 获取双击项的标识符
  161. item_id = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.identify_row(event.y)
  162. # 获取该项的值
  163. item_values = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.item(item_id, "values")
  164. # print("Double-clicked item:", item_values)
  165. if len(item_values) > 0:
  166. self.selection_batch_task_id = int(item_id)
  167. open_batch_task_detail_win(int(item_id), item_values)
  168. else:
  169. self.selection_batch_task_id = None
  170. def batch_task_start_event(self, event):
  171. # 获取双击项的标识符
  172. item_id = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.identify_row(event.y)
  173. # 获取该项的值
  174. item_values = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.item(item_id, "values")
  175. # print("Double-clicked item:", item_values)
  176. if len(item_values) > 0:
  177. self.selection_batch_task_id = int(item_id)
  178. connection = get_global_db_connection()
  179. cursor = connection.cursor()
  180. try:
  181. batch_task_update_status(cursor, int(item_id), 1)
  182. connection.commit()
  183. except Exception as e:
  184. # 回滚事务
  185. connection.rollback()
  186. print(f"发生错误: {e}")
  187. finally:
  188. # 确保资源被正确释放
  189. cursor.close()
  190. else:
  191. self.selection_batch_task_id = None
  192. def batch_task_stop_event(self, event):
  193. # 获取双击项的标识符
  194. item_id = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.identify_row(event.y)
  195. # 获取该项的值
  196. item_values = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.item(item_id, "values")
  197. # print("Double-clicked item:", item_values)
  198. if len(item_values) > 0:
  199. self.selection_batch_task_id = int(item_id)
  200. connection = get_global_db_connection()
  201. cursor = connection.cursor()
  202. try:
  203. batch_task_update_status(cursor, int(item_id), 3)
  204. connection.commit()
  205. except Exception as e:
  206. # 回滚事务
  207. connection.rollback()
  208. print(f"发生错误: {e}")
  209. finally:
  210. # 确保资源被正确释放
  211. cursor.close()
  212. else:
  213. self.selection_batch_task_id = None
  214. def batch_task_action_event(self, event):
  215. # 获取右键项的标识符
  216. item_id = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.identify_row(event.y)
  217. print(f"Right-clicked item: {item_id}")
  218. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.selection_set(item_id)
  219. # 获取该项的值
  220. item_values = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.item(item_id, "values")
  221. if len(item_values) > 0:
  222. self.selection_batch_task_id = int(item_id)
  223. # print("Right-clicked item:", item_values)
  224. # 创建菜单
  225. menu = tkinter.Menu(self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list, tearoff=0)
  226. menu.add_command(label="查看详情", command=lambda: self.batch_task_detail_event(event))
  227. if item_values[1] == "等待中" or item_values[1] == "已开始":
  228. menu.add_command(label="停止", command=lambda: self.batch_task_stop_event(event))
  229. elif item_values[1] == "已停止":
  230. menu.add_command(label="开始", command=lambda: self.batch_task_start_event(event))
  231. menu.post(event.x_root, event.y_root)
  232. else:
  233. self.selection_batch_task_id = None
  234. def just_click_event(self, event):
  235. item_id = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.identify_row(event.y)
  236. self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.selection_set(item_id)
  237. item_values = self.tk_tabs_main_tabs.tk_tabs_main_tabs_1.tk_table_batch_task_list.item(item_id, "values")
  238. if len(item_values) > 0:
  239. self.selection_batch_task_id = int(item_id)
  240. else:
  241. self.selection_batch_task_id = None