产品/客户搜索改为输入框下方下拉列表,选中后阻止trace重复触发搜索
This commit is contained in:
@@ -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", "")
|
||||
|
||||
Reference in New Issue
Block a user