产品/客户搜索改为输入框下方下拉列表,选中后阻止trace重复触发搜索

This commit is contained in:
2026-05-15 16:25:34 +08:00
parent ed62b49921
commit 6caa6deaa3
+31 -27
View File
@@ -217,9 +217,11 @@ class App:
r0 = Frame(fixed_frame)
r0.pack(fill=X, pady=2)
Label(r0, text="产品:", width=10, anchor="e").pack(side="left")
Entry(r0, textvariable=self.fv_product, width=20).pack(side="left", padx=5)
self.fv_product_entry = Entry(r0, textvariable=self.fv_product, width=20)
self.fv_product_entry.pack(side="left", padx=5)
Label(r0, text="客户:", width=10, anchor="e").pack(side="left", padx=(30, 0))
Entry(r0, textvariable=self.fv_customer, width=20).pack(side="left", padx=5)
self.fv_customer_entry = Entry(r0, textvariable=self.fv_customer, width=20)
self.fv_customer_entry.pack(side="left", padx=5)
# Row 1: 寄达地 | 无影响
r1 = Frame(fixed_frame)
@@ -443,7 +445,7 @@ class App:
return
names = [c.get("productName", "") for c in candidates]
self._show_search_dropdown(
"选择产品", names,
self.fv_product_entry, names,
lambda idx: self._on_product_selected(candidates[idx]),
)
except Exception as e:
@@ -461,26 +463,28 @@ class App:
for c in candidates
]
self._show_search_dropdown(
"选择客户", names,
self.fv_customer_entry, names,
lambda idx: self._on_customer_selected(candidates[idx]),
)
except Exception as e:
self._log(f"[error] 客户搜索失败: {e}")
def _show_search_dropdown(self, title: str, options: list[str], on_select):
"""在屏幕中央弹出下拉选择窗口。"""
def _show_search_dropdown(self, entry: Entry, options: list[str], on_select):
"""在输入框正下方弹出下拉候选列表。"""
popup = Toplevel(self.root)
popup.title(title)
popup.geometry("360x260")
popup.transient(self.root)
popup.grab_set()
popup.overrideredirect(True)
popup.attributes("-topmost", True)
Label(popup, text=title, font=("", 10, "bold"), pady=6).pack()
# 定位在输入框正下方
x = entry.winfo_rootx()
y = entry.winfo_rooty() + entry.winfo_height()
w = entry.winfo_width()
popup.geometry(f"{w}x180+{x}+{y}")
frame = Frame(popup)
frame.pack(fill="both", expand=True, padx=10, pady=5)
listbox = Listbox(frame, font=("", 10))
frame = Frame(popup, bd=1, relief="solid")
frame.pack(fill="both", expand=True)
listbox = Listbox(frame, font=("", 10), selectmode="browse", activestyle="none")
scroll = Scrollbar(frame, orient=VERTICAL, command=listbox.yview)
listbox.configure(yscrollcommand=scroll.set)
scroll.pack(side=RIGHT, fill=Y)
@@ -488,37 +492,35 @@ class App:
for opt in options:
listbox.insert(END, opt)
chosen = [False]
def select():
def select(e=None):
sel = listbox.curselection()
if sel:
chosen[0] = True
popup.destroy()
on_select(sel[0])
def cancel():
def cancel(e=None):
popup.destroy()
listbox.bind("<Double-1>", lambda e: select())
listbox.bind("<Return>", lambda e: select())
listbox.bind("<Escape>", lambda e: cancel())
listbox.bind("<ButtonRelease-1>", select)
listbox.bind("<Return>", select)
listbox.bind("<Escape>", cancel)
listbox.focus_set()
if listbox.size() > 0:
listbox.selection_set(0)
btn_f = Frame(popup)
btn_f.pack(pady=8)
Button(btn_f, text="选择", command=select, bg="#4CAF50", fg="white", width=8).pack(side=LEFT, padx=5)
Button(btn_f, text="取消", command=cancel, width=8).pack(side=LEFT, padx=5)
# 点击外部关闭
def on_focus_out(e):
popup.after(150, lambda: popup.destroy() if not popup.focus_get() else None)
popup.bind("<FocusOut>", on_focus_out)
popup.protocol("WM_DELETE_WINDOW", cancel)
popup.wait_window()
def _on_product_selected(self, choice: dict):
"""产品选中:缓存选择并获取详情。"""
self._product_cached_choice = choice
self._loading_config = True # 阻止 trace 再次触发搜索
self.fv_product.set(choice.get("productName", ""))
self._loading_config = False
# 获取产品详情
try:
biz_id = choice.get("productId", "")
@@ -532,7 +534,9 @@ class App:
def _on_customer_selected(self, choice: dict):
"""客户选中:缓存选择并获取详情和寄件人实名。"""
self._customer_cached_choice = choice
self._loading_config = True # 阻止 trace 再次触发搜索
self.fv_customer.set(choice.get("customerFullName", choice.get("customerName", "")))
self._loading_config = False
# 获取客户详情
try:
cust_id = choice.get("customerId", "")