fix
This commit is contained in:
parent
e746fe3a67
commit
22c6327ccb
158
test/aola.py
158
test/aola.py
@ -19,43 +19,47 @@ class TeamSwitchPacketGenerator:
|
|||||||
self.root.title("阵容切换封包生成器")
|
self.root.title("阵容切换封包生成器")
|
||||||
|
|
||||||
# 获取所有阵容名称和 spell_code
|
# 获取所有阵容名称和 spell_code
|
||||||
self.team_data = self.get_team_data() # 存储 team_name 和 spell_code 的列表
|
self.team_data = self.get_team_data()
|
||||||
self.team_names = [item[0] for item in self.team_data] # 仅 team_name 列表用于显示
|
self.team_names = [item[0] for item in self.team_data]
|
||||||
|
self.last_filtered_teams = self.team_names
|
||||||
# 创建搜索框(替换下拉框)
|
|
||||||
tk.Label(self.root, text="搜索阵容(输入拼音缩写):").pack(anchor=tk.W, padx=5)
|
|
||||||
self.search_var = tk.StringVar()
|
|
||||||
self.search_var.trace("w", self.update_combobox) # 监听输入变化
|
|
||||||
self.search_entry = tk.Entry(self.root, textvariable=self.search_var)
|
|
||||||
self.search_entry.pack(pady=5, padx=5, fill=tk.X)
|
|
||||||
|
|
||||||
# 创建可搜索的下拉框
|
# 创建可搜索的下拉框
|
||||||
self.team_var = tk.StringVar()
|
tk.Label(self.root, text="选择或搜索阵容(输入拼音缩写):").pack(anchor=tk.W, padx=5)
|
||||||
|
self.team_var = tk.StringVar(value="请选择阵容")
|
||||||
self.team_dropdown = ttk.Combobox(self.root, textvariable=self.team_var)
|
self.team_dropdown = ttk.Combobox(self.root, textvariable=self.team_var)
|
||||||
self.team_dropdown['values'] = self.team_names
|
self.team_dropdown['values'] = self.team_names
|
||||||
self.team_dropdown.pack(pady=10)
|
self.team_dropdown.pack(pady=10)
|
||||||
self.team_dropdown.set("请选择阵容")
|
|
||||||
|
# 防抖定时器和状态
|
||||||
|
self.debounce_timer = None
|
||||||
|
self.debounce_delay = 150
|
||||||
|
self.last_search_text = ""
|
||||||
|
self.has_typed = False
|
||||||
|
self.is_dropdown_open = False # 跟踪下拉框状态
|
||||||
|
|
||||||
|
# 绑定事件
|
||||||
|
self.team_dropdown.bind('<KeyRelease>', self.schedule_update_combobox)
|
||||||
|
self.team_dropdown.bind('<FocusIn>', self.clear_default_text)
|
||||||
|
self.team_dropdown.bind('<FocusOut>', self.close_dropdown)
|
||||||
|
self.team_dropdown.bind('<<ComboboxSelected>>', self.on_combobox_select)
|
||||||
|
|
||||||
|
# 获取 Combobox 的内部 Entry 控件
|
||||||
|
self.entry = self.team_dropdown # ttk.Combobox 本身支持 Entry 方法
|
||||||
|
# 绑定下拉框展开/收起事件
|
||||||
|
self.team_dropdown.bind('<Button-1>', self.toggle_dropdown_state)
|
||||||
|
|
||||||
# 创建按钮框架,包含“刷新”和“生成封包”按钮
|
# 创建按钮框架,包含“刷新”和“生成封包”按钮
|
||||||
button_frame = tk.Frame(self.root)
|
button_frame = tk.Frame(self.root)
|
||||||
button_frame.pack(pady=5)
|
button_frame.pack(pady=5)
|
||||||
|
|
||||||
# 刷新按钮
|
|
||||||
tk.Button(button_frame, text="刷新", command=self.refresh_dropdown).pack(side=tk.LEFT, padx=5)
|
tk.Button(button_frame, text="刷新", command=self.refresh_dropdown).pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
# 生成按钮
|
|
||||||
tk.Button(button_frame, text="生成封包(第一次生成请先解锁二级密码)", command=self.generate_packets).pack(side=tk.LEFT, padx=5)
|
tk.Button(button_frame, text="生成封包(第一次生成请先解锁二级密码)", command=self.generate_packets).pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
# 创建 Frame 包含封包输出框和复制按钮
|
# 创建封包输出和复制按钮框架
|
||||||
output_frame = tk.Frame(self.root)
|
output_frame = tk.Frame(self.root)
|
||||||
output_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
output_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
|
||||||
|
|
||||||
# 封包输出框
|
|
||||||
tk.Label(output_frame, text="封包输出:").pack(anchor=tk.W)
|
tk.Label(output_frame, text="封包输出:").pack(anchor=tk.W)
|
||||||
self.output_text = tk.Text(output_frame, height=15, width=60)
|
self.output_text = tk.Text(output_frame, height=15, width=60)
|
||||||
self.output_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
self.output_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
# 复制按钮(放在右侧)
|
|
||||||
tk.Button(output_frame, text="复制脚本", command=self.copy_output).pack(side=tk.RIGHT, padx=5)
|
tk.Button(output_frame, text="复制脚本", command=self.copy_output).pack(side=tk.RIGHT, padx=5)
|
||||||
|
|
||||||
# 信息提示框
|
# 信息提示框
|
||||||
@ -64,49 +68,94 @@ class TeamSwitchPacketGenerator:
|
|||||||
self.info_text.pack(pady=5)
|
self.info_text.pack(pady=5)
|
||||||
|
|
||||||
def get_team_data(self):
|
def get_team_data(self):
|
||||||
"""从数据库获取所有阵容名称和 spell_code"""
|
|
||||||
try:
|
try:
|
||||||
self.cursor.execute("SELECT team_name, spell_code FROM aolaer_team ORDER BY team_name")
|
self.cursor.execute("SELECT team_name, spell_code FROM aolaer_team ORDER BY team_name")
|
||||||
return self.cursor.fetchall() # 返回 [(team_name, spell_code), ...]
|
return [(row[0], row[1] or "") for row in self.cursor.fetchall()]
|
||||||
except sqlite3.Error as e:
|
except sqlite3.Error as e:
|
||||||
self.info_text.insert(tk.END, f"获取阵容数据失败: {e}\n")
|
self.info_text.insert(tk.END, f"获取阵容数据失败: {e}\n")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def update_combobox(self, *args):
|
def clear_default_text(self, event):
|
||||||
"""根据搜索框输入更新下拉框内容"""
|
if self.team_var.get() == "请选择阵容":
|
||||||
search_text = self.search_var.get().strip().lower()
|
self.team_var.set("")
|
||||||
if not search_text:
|
self.has_typed = True
|
||||||
# 如果搜索框为空,显示所有阵容
|
self.entry.focus_set()
|
||||||
self.team_dropdown['values'] = self.team_names
|
self.entry.icursor(tk.END)
|
||||||
self.team_dropdown.set("请选择阵容")
|
|
||||||
|
def schedule_update_combobox(self, event):
|
||||||
|
if event.keysym in ('Shift', 'Control', 'Alt', 'Return', 'Tab', 'Left', 'Right', 'Up', 'Down'):
|
||||||
|
return
|
||||||
|
|
||||||
|
self.has_typed = True
|
||||||
|
if self.debounce_timer is not None:
|
||||||
|
self.root.after_cancel(self.debounce_timer)
|
||||||
|
self.debounce_timer = self.root.after(self.debounce_delay, self.update_combobox)
|
||||||
|
|
||||||
|
def toggle_dropdown_state(self, event):
|
||||||
|
"""跟踪下拉框的展开/收起状态"""
|
||||||
|
# 简单假设点击切换状态(实际可能需要更复杂的状态检测)
|
||||||
|
self.is_dropdown_open = not self.is_dropdown_open
|
||||||
|
|
||||||
|
def update_combobox(self):
|
||||||
|
"""优化后的更新下拉框逻辑"""
|
||||||
|
search_text = self.team_var.get().strip().lower()
|
||||||
|
if search_text == self.last_search_text:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.last_search_text = search_text
|
||||||
|
if not search_text or search_text == "请选择阵容":
|
||||||
|
filtered_teams = self.team_names
|
||||||
else:
|
else:
|
||||||
# 筛选 spell_code 包含搜索文本的阵容
|
|
||||||
filtered_teams = [
|
filtered_teams = [
|
||||||
team_name for team_name, spell_code in self.team_data
|
team_name for team_name, spell_code in self.team_data
|
||||||
if spell_code and search_text in spell_code.lower()
|
if spell_code and search_text in spell_code.lower()
|
||||||
]
|
]
|
||||||
|
if not filtered_teams:
|
||||||
|
filtered_teams = ["无匹配阵容"]
|
||||||
|
|
||||||
|
# 更新下拉框选项
|
||||||
|
if filtered_teams != self.last_filtered_teams:
|
||||||
self.team_dropdown['values'] = filtered_teams
|
self.team_dropdown['values'] = filtered_teams
|
||||||
if filtered_teams:
|
self.last_filtered_teams = filtered_teams
|
||||||
self.team_dropdown.set(filtered_teams[0]) # 默认选中第一个匹配项
|
|
||||||
else:
|
# 打开下拉框(仅在有输入且未打开时)
|
||||||
self.team_dropdown.set("无匹配阵容")
|
if self.has_typed and search_text and not self.is_dropdown_open:
|
||||||
self.team_dropdown['values'] = []
|
self.team_dropdown.event_generate('<Down>')
|
||||||
|
self.is_dropdown_open = True
|
||||||
|
|
||||||
|
# 延迟设置焦点和光标位置
|
||||||
|
def set_focus_and_cursor():
|
||||||
|
self.entry.focus_set()
|
||||||
|
self.entry.icursor(tk.END)
|
||||||
|
# 调试日志
|
||||||
|
self.info_text.insert(tk.END, f"焦点设置: {self.root.focus_get() == self.entry}\n")
|
||||||
|
|
||||||
|
self.root.after(10, set_focus_and_cursor)
|
||||||
|
|
||||||
|
def close_dropdown(self, event):
|
||||||
|
self.has_typed = False
|
||||||
|
if self.is_dropdown_open:
|
||||||
|
self.team_dropdown.event_generate('<Up>')
|
||||||
|
self.is_dropdown_open = False
|
||||||
|
|
||||||
|
def on_combobox_select(self, event):
|
||||||
|
self.has_typed = False
|
||||||
|
self.is_dropdown_open = False
|
||||||
|
self.entry.focus_set()
|
||||||
|
self.entry.icursor(tk.END)
|
||||||
|
|
||||||
def refresh_dropdown(self):
|
def refresh_dropdown(self):
|
||||||
"""刷新下拉框数据"""
|
|
||||||
# 重新获取阵容数据
|
|
||||||
self.team_data = self.get_team_data()
|
self.team_data = self.get_team_data()
|
||||||
self.team_names = [item[0] for item in self.team_data]
|
self.team_names = [item[0] for item in self.team_data]
|
||||||
# 更新下拉框选项
|
|
||||||
self.team_dropdown['values'] = self.team_names
|
self.team_dropdown['values'] = self.team_names
|
||||||
self.team_dropdown.set("请选择阵容")
|
self.last_filtered_teams = self.team_names
|
||||||
# 清空搜索框
|
self.team_var.set("请选择阵容")
|
||||||
self.search_var.set("")
|
self.last_search_text = ""
|
||||||
# 在提示框中显示刷新成功
|
self.has_typed = False
|
||||||
|
self.is_dropdown_open = False
|
||||||
self.info_text.insert(tk.END, "下拉框数据已刷新!\n")
|
self.info_text.insert(tk.END, "下拉框数据已刷新!\n")
|
||||||
|
|
||||||
def copy_output(self):
|
def copy_output(self):
|
||||||
"""复制脚本输出框的内容到剪贴板"""
|
|
||||||
content = self.output_text.get(1.0, tk.END).strip()
|
content = self.output_text.get(1.0, tk.END).strip()
|
||||||
if content:
|
if content:
|
||||||
self.root.clipboard_clear()
|
self.root.clipboard_clear()
|
||||||
@ -116,7 +165,6 @@ class TeamSwitchPacketGenerator:
|
|||||||
self.info_text.insert(tk.END, "脚本输出框为空,无法复制!\n")
|
self.info_text.insert(tk.END, "脚本输出框为空,无法复制!\n")
|
||||||
|
|
||||||
def validate_ids(self, ids_str):
|
def validate_ids(self, ids_str):
|
||||||
"""验证 ids 数组,确保格式正确"""
|
|
||||||
try:
|
try:
|
||||||
ids = json.loads(ids_str)
|
ids = json.loads(ids_str)
|
||||||
if not isinstance(ids, list) or len(ids) != 5:
|
if not isinstance(ids, list) or len(ids) != 5:
|
||||||
@ -129,7 +177,6 @@ class TeamSwitchPacketGenerator:
|
|||||||
return False, "ids 格式不正确"
|
return False, "ids 格式不正确"
|
||||||
|
|
||||||
def generate_packets(self):
|
def generate_packets(self):
|
||||||
"""生成封包代码"""
|
|
||||||
self.output_text.delete(1.0, tk.END)
|
self.output_text.delete(1.0, tk.END)
|
||||||
self.info_text.delete(1.0, tk.END)
|
self.info_text.delete(1.0, tk.END)
|
||||||
packets = []
|
packets = []
|
||||||
@ -140,7 +187,6 @@ class TeamSwitchPacketGenerator:
|
|||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# 获取 team_code 和 team_set
|
|
||||||
self.cursor.execute("SELECT team_code, team_set FROM aolaer_team WHERE team_name = ?", (selected_team,))
|
self.cursor.execute("SELECT team_code, team_set FROM aolaer_team WHERE team_name = ?", (selected_team,))
|
||||||
result = self.cursor.fetchone()
|
result = self.cursor.fetchone()
|
||||||
if not result:
|
if not result:
|
||||||
@ -149,21 +195,16 @@ class TeamSwitchPacketGenerator:
|
|||||||
team_code, team_set = result
|
team_code, team_set = result
|
||||||
packets.append(f'|#send={{"id":13,"param":{{"pms":"{team_code}"}},"cmd":"1222"}}|')
|
packets.append(f'|#send={{"id":13,"param":{{"pms":"{team_code}"}},"cmd":"1222"}}|')
|
||||||
|
|
||||||
# 处理 is_set = 1 的记录(重置魂卡)
|
|
||||||
self.cursor.execute("SELECT id FROM aolaer_id WHERE is_set = 1")
|
self.cursor.execute("SELECT id FROM aolaer_id WHERE is_set = 1")
|
||||||
set_ids = [row[0] for row in self.cursor.fetchall()]
|
set_ids = [row[0] for row in self.cursor.fetchall()]
|
||||||
|
|
||||||
for set_id in set_ids:
|
for set_id in set_ids:
|
||||||
packets.append(
|
packets.append(
|
||||||
f'|#send={{"id":42,"param":{{"bk":1,"petId":{set_id},"ids":[0,0,0,0,0]}},"cmd":"ASC221104_2"}}|')
|
f'|#send={{"id":42,"param":{{"bk":1,"petId":{set_id},"ids":[0,0,0,0,0]}},"cmd":"ASC221104_2"}}|#time=10|')
|
||||||
self.cursor.execute("UPDATE aolaer_id SET is_set = 0 WHERE id = ?", (set_id,))
|
self.cursor.execute("UPDATE aolaer_id SET is_set = 0 WHERE id = ?", (set_id,))
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
# 处理 team_code 中的 ID
|
|
||||||
team_ids = team_code.split('#')
|
team_ids = team_code.split('#')
|
||||||
team_ids = [id for id in team_ids if id]
|
team_ids = [id for id in team_ids if id]
|
||||||
|
|
||||||
# 处理 team_set
|
|
||||||
team_set_codes = None
|
team_set_codes = None
|
||||||
if team_set:
|
if team_set:
|
||||||
team_set_codes = team_set.split('#')
|
team_set_codes = team_set.split('#')
|
||||||
@ -172,17 +213,13 @@ class TeamSwitchPacketGenerator:
|
|||||||
f"警告:team_set 的长度 ({len(team_set_codes)}) 与 team_code 的 ID 数量 ({len(team_ids)}) 不匹配!\n")
|
f"警告:team_set 的长度 ({len(team_set_codes)}) 与 team_code 的 ID 数量 ({len(team_ids)}) 不匹配!\n")
|
||||||
return
|
return
|
||||||
|
|
||||||
# 查询 aolaer_id 表
|
|
||||||
self.cursor.execute(
|
self.cursor.execute(
|
||||||
"SELECT id, div_weapon, aolaer_typecode FROM aolaer_id WHERE id IN ({})".format(
|
"SELECT id, div_weapon, aolaer_typecode FROM aolaer_id WHERE id IN ({})".format(
|
||||||
','.join('?' for _ in team_ids)
|
','.join('?' for _ in team_ids)
|
||||||
),
|
),
|
||||||
team_ids
|
team_ids
|
||||||
)
|
)
|
||||||
|
|
||||||
id_to_typecode = {row[0]: row for row in self.cursor.fetchall()}
|
id_to_typecode = {row[0]: row for row in self.cursor.fetchall()}
|
||||||
|
|
||||||
# 分组生成封包,确保顺序:子宠物 → 魂艺 → 魂卡
|
|
||||||
sub_pet_packets = []
|
sub_pet_packets = []
|
||||||
soul_art_packets = []
|
soul_art_packets = []
|
||||||
soul_card_packets = []
|
soul_card_packets = []
|
||||||
@ -198,14 +235,12 @@ class TeamSwitchPacketGenerator:
|
|||||||
if team_set_codes and team_set_codes[idx] != '0':
|
if team_set_codes and team_set_codes[idx] != '0':
|
||||||
typecode = team_set_codes[idx]
|
typecode = team_set_codes[idx]
|
||||||
|
|
||||||
# 生成子宠物封包(仅当 div_weapon 非空时)
|
|
||||||
if div_weapon and str(div_weapon).strip():
|
if div_weapon and str(div_weapon).strip():
|
||||||
sub_pet_packets.append(
|
sub_pet_packets.append(
|
||||||
f'|#send={{"id":42,"param":{{"subPetId":{id},"petId":{div_weapon}}},"cmd":"ASBS230623_con"}}|')
|
f'|#send={{"id":42,"param":{{"subPetId":{id},"petId":{div_weapon}}},"cmd":"ASBS230623_con"}}|')
|
||||||
else:
|
else:
|
||||||
self.info_text.insert(tk.END, f"提示:ID {id} 的 div_weapon 为空,跳过生成子宠物封包!\n")
|
self.info_text.insert(tk.END, f"提示:ID {id} 的 div_weapon 为空,跳过生成子宠物封包!\n")
|
||||||
|
|
||||||
# 获取 soul_art 和 soul_card
|
|
||||||
self.cursor.execute("SELECT soul_art, soul_card FROM aolaer_type WHERE aolaer_typecode = ?",
|
self.cursor.execute("SELECT soul_art, soul_card FROM aolaer_type WHERE aolaer_typecode = ?",
|
||||||
(typecode,))
|
(typecode,))
|
||||||
result = self.cursor.fetchone()
|
result = self.cursor.fetchone()
|
||||||
@ -214,7 +249,6 @@ class TeamSwitchPacketGenerator:
|
|||||||
continue
|
continue
|
||||||
soul_art, soul_card = result
|
soul_art, soul_card = result
|
||||||
|
|
||||||
# 生成魂艺封包(仅当 soul_art 非空时)
|
|
||||||
if soul_art and soul_art.strip():
|
if soul_art and soul_art.strip():
|
||||||
try:
|
try:
|
||||||
sid1, sid2 = soul_art.split(',')
|
sid1, sid2 = soul_art.split(',')
|
||||||
@ -229,12 +263,11 @@ class TeamSwitchPacketGenerator:
|
|||||||
self.info_text.insert(tk.END,
|
self.info_text.insert(tk.END,
|
||||||
f"提示:typecode {typecode} 的 soul_art 为空,跳过生成魂艺封包!\n")
|
f"提示:typecode {typecode} 的 soul_art 为空,跳过生成魂艺封包!\n")
|
||||||
|
|
||||||
# 生成魂卡封包
|
|
||||||
if soul_card and soul_card.strip():
|
if soul_card and soul_card.strip():
|
||||||
is_valid, ids_or_error = self.validate_ids(soul_card)
|
is_valid, ids_or_error = self.validate_ids(soul_card)
|
||||||
if is_valid:
|
if is_valid:
|
||||||
soul_card_packets.append(
|
soul_card_packets.append(
|
||||||
f'|#send={{"id":42,"param":{{"bk":1,"petId":{id},"ids":{soul_card}}},"cmd":"ASC221104_2"}}|')
|
f'|#send={{"id":42,"param":{{"bk":1,"petId":{id},"ids":{soul_card}}},"cmd":"ASC221104_2"}}|#time=10|')
|
||||||
self.cursor.execute("UPDATE aolaer_id SET is_set = 1 WHERE id = ?", (id,))
|
self.cursor.execute("UPDATE aolaer_id SET is_set = 1 WHERE id = ?", (id,))
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
else:
|
else:
|
||||||
@ -243,7 +276,6 @@ class TeamSwitchPacketGenerator:
|
|||||||
else:
|
else:
|
||||||
self.info_text.insert(tk.END, f"提示:typecode {typecode} 的 soul_card 为空,已跳过处理!\n")
|
self.info_text.insert(tk.END, f"提示:typecode {typecode} 的 soul_card 为空,已跳过处理!\n")
|
||||||
|
|
||||||
# 按顺序添加封包:子宠物 → 魂艺 → 魂卡
|
|
||||||
packets.extend(sub_pet_packets)
|
packets.extend(sub_pet_packets)
|
||||||
packets.extend(soul_art_packets)
|
packets.extend(soul_art_packets)
|
||||||
packets.extend(soul_card_packets)
|
packets.extend(soul_card_packets)
|
||||||
@ -256,11 +288,9 @@ class TeamSwitchPacketGenerator:
|
|||||||
self.info_text.insert(tk.END, f"数据库操作失败: {e}\n")
|
self.info_text.insert(tk.END, f"数据库操作失败: {e}\n")
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""运行程序"""
|
|
||||||
self.root.mainloop()
|
self.root.mainloop()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
"""清理数据库连接"""
|
|
||||||
self.conn.close()
|
self.conn.close()
|
||||||
|
|
||||||
|
|
||||||
|
BIN
test/aola.sqlite
BIN
test/aola.sqlite
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user