logic_ui.py 14 KB

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