待学习库ui更新
This commit is contained in:
parent
1d0b35fb3e
commit
fcc43390c6
|
|
@ -170,10 +170,10 @@ class PendingLearningUIMixin:
|
|||
values.append(name)
|
||||
seen.add(name)
|
||||
suggested = (suggested or "").strip()
|
||||
if suggested and suggested in values:
|
||||
initial = suggested
|
||||
else:
|
||||
initial = ""
|
||||
# 最接近菜名即使不在今日菜单/主食里,也填进输入框并放到下拉最前
|
||||
if suggested and suggested not in seen:
|
||||
values.insert(0, suggested)
|
||||
initial = suggested
|
||||
return period_name, period_names, values, initial, is_period
|
||||
|
||||
def _today_menu_info(self):
|
||||
|
|
@ -529,8 +529,11 @@ class PendingLearningUIMixin:
|
|||
header.pack(fill=tk.X, padx=16, pady=(14, 6))
|
||||
tk.Label(header, text="待学习菜品库", bg=COLORS["bg"], fg=COLORS["text"],
|
||||
font=FONTS["h1"]).pack(side=tk.LEFT)
|
||||
tk.Label(header, text=f"共 {len(items)} 条记录", bg=COLORS["bg"],
|
||||
fg=COLORS["muted"], font=FONTS["small"]).pack(side=tk.LEFT, padx=10)
|
||||
count_lbl = tk.Label(header, text=f"共 {len(items)} 条记录", bg=COLORS["bg"],
|
||||
fg=COLORS["muted"], font=FONTS["small"])
|
||||
count_lbl.pack(side=tk.LEFT, padx=10)
|
||||
dialog._pending_count_label = count_lbl
|
||||
dialog._pending_items = items
|
||||
if items:
|
||||
PillButton(header, text="全部忽略", variant="ghost", size="sm",
|
||||
command=lambda: self._ignore_all_pending(items, dialog),
|
||||
|
|
@ -642,7 +645,9 @@ class PendingLearningUIMixin:
|
|||
actions.pack(side=tk.RIGHT, padx=(10, 0))
|
||||
pid = item["id"]
|
||||
PillButton(actions, text="学习", variant="primary", size="sm",
|
||||
command=lambda p=pid, s=suggested: self._learn_pending_from_dialog(p, s, dialog),
|
||||
command=lambda p=pid, s=suggested, row=box: self._learn_pending_from_dialog(
|
||||
p, s, dialog, row=row,
|
||||
),
|
||||
).pack(side=tk.LEFT, padx=2)
|
||||
PillButton(actions, text="忽略", variant="ghost", size="sm",
|
||||
command=lambda p=pid: self._ignore_pending_from_dialog(p, dialog),
|
||||
|
|
@ -683,6 +688,21 @@ class PendingLearningUIMixin:
|
|||
# 保持 _pending_dialog_open / _pending_resume_live,重建列表
|
||||
self.show_pending_dialog()
|
||||
|
||||
def _pl_place_center(self, win, width, height):
|
||||
"""把弹窗放到屏幕中央,避免默认贴在左上角。"""
|
||||
try:
|
||||
win.update_idletasks()
|
||||
sw = win.winfo_screenwidth()
|
||||
sh = win.winfo_screenheight()
|
||||
width = min(int(width), max(sw - 48, 240))
|
||||
height = min(int(height), max(sh - 80, 180))
|
||||
x = max((sw - width) // 2, 0)
|
||||
y = max((sh - height) // 2 - 24, 12)
|
||||
win.geometry(f"{width}x{height}+{x}+{y}")
|
||||
win.lift()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _preview_pending_image(self, image_path, parent=None):
|
||||
"""待学习库:点击缩略图查看对应大图。"""
|
||||
if not image_path or not os.path.exists(image_path):
|
||||
|
|
@ -699,16 +719,35 @@ class PendingLearningUIMixin:
|
|||
win.title("待学习图片预览")
|
||||
win.configure(bg=COLORS["bg"])
|
||||
win.transient(parent or self.root)
|
||||
im.thumbnail((760, 640))
|
||||
try:
|
||||
sw = win.winfo_screenwidth()
|
||||
sh = win.winfo_screenheight()
|
||||
except Exception:
|
||||
sw, sh = 1280, 800
|
||||
max_w = max(720, int(sw * 0.72))
|
||||
max_h = max(520, int(sh * 0.72))
|
||||
iw, ih = im.size
|
||||
scale = min(max_w / float(iw or 1), max_h / float(ih or 1), 4.0)
|
||||
if abs(scale - 1.0) > 0.02:
|
||||
im = im.resize(
|
||||
(max(1, int(iw * scale)), max(1, int(ih * scale))),
|
||||
Image.Resampling.LANCZOS if hasattr(Image, "Resampling") else Image.LANCZOS,
|
||||
)
|
||||
photo = ImageTk.PhotoImage(im)
|
||||
win._photo = photo
|
||||
tk.Label(win, image=photo, bg=COLORS["bg"]).pack(padx=12, pady=12)
|
||||
tk.Label(win, image=photo, bg=COLORS["bg"]).pack(padx=16, pady=(16, 8))
|
||||
tk.Label(win, text=os.path.basename(image_path), bg=COLORS["bg"],
|
||||
fg=COLORS["muted"], font=FONTS["small"]).pack()
|
||||
PillButton(win, text="关闭", variant="ghost",
|
||||
command=win.destroy).pack(pady=(8, 12))
|
||||
command=win.destroy).pack(pady=(8, 14))
|
||||
win.update_idletasks()
|
||||
self._pl_place_center(
|
||||
win,
|
||||
max(win.winfo_reqwidth(), im.width + 48),
|
||||
max(win.winfo_reqheight(), im.height + 96),
|
||||
)
|
||||
|
||||
def _learn_pending_from_dialog(self, pending_id, suggested, dialog):
|
||||
def _learn_pending_from_dialog(self, pending_id, suggested, dialog, row=None):
|
||||
"""待学习库:下拉含主食小库 + 当前餐段菜品。"""
|
||||
period_name, period_names, values, initial, is_period = self._pl_learn_name_choices(suggested)
|
||||
|
||||
|
|
@ -716,7 +755,6 @@ class PendingLearningUIMixin:
|
|||
pick.title("选择菜品名称")
|
||||
pick.configure(bg=COLORS["bg"])
|
||||
pick.transient(dialog)
|
||||
pick.grab_set()
|
||||
pick.resizable(False, False)
|
||||
|
||||
tk.Label(pick, text="学习到哪个菜名?", bg=COLORS["bg"], fg=COLORS["text"],
|
||||
|
|
@ -728,24 +766,45 @@ class PendingLearningUIMixin:
|
|||
else:
|
||||
tip = "暂无候选菜品可选,请手动输入菜名。"
|
||||
tk.Label(pick, text=tip, bg=COLORS["bg"], fg=COLORS["muted"], font=FONTS["small"],
|
||||
wraplength=340, justify=tk.LEFT).pack(padx=20, anchor=tk.W)
|
||||
wraplength=420, justify=tk.LEFT).pack(padx=20, anchor=tk.W)
|
||||
|
||||
if values:
|
||||
Chip(pick, text=f"主食+{period_name} · {len(values)} 道",
|
||||
tone="ok", bg=COLORS["bg"]).pack(padx=20, pady=(8, 0), anchor=tk.W)
|
||||
|
||||
name_var = tk.StringVar(value=initial)
|
||||
name_var = tk.StringVar(value=initial or "")
|
||||
row_pick = tk.Frame(pick, bg=COLORS["bg"])
|
||||
row_pick.pack(fill=tk.X, padx=20, pady=10)
|
||||
combo = ttk.Combobox(
|
||||
pick, textvariable=name_var, values=values,
|
||||
width=34, style="Large.TEntry",
|
||||
row_pick, textvariable=name_var, values=values, width=28,
|
||||
)
|
||||
combo.pack(padx=20, pady=10, fill=tk.X)
|
||||
combo["height"] = 16
|
||||
combo.pack(side=tk.LEFT, fill=tk.X, expand=True)
|
||||
|
||||
def _open_dropdown(_event=None):
|
||||
combo.focus_set()
|
||||
try:
|
||||
combo.tk.call("ttk::combobox::Post", combo._w)
|
||||
except Exception:
|
||||
try:
|
||||
combo.event_generate("<Down>")
|
||||
except Exception:
|
||||
pass
|
||||
return "break"
|
||||
|
||||
PillButton(row_pick, text="选择", variant="secondary", size="sm",
|
||||
command=_open_dropdown).pack(side=tk.LEFT, padx=(8, 0))
|
||||
combo.focus_set()
|
||||
if initial:
|
||||
try:
|
||||
combo.icursor("end")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not values:
|
||||
tk.Label(pick, text="暂无可选菜名,请直接输入新菜名(将新建类别)。",
|
||||
bg=COLORS["bg"], fg=COLORS["warn"], font=FONTS["caption"],
|
||||
wraplength=300, justify=tk.LEFT).pack(padx=20, anchor=tk.W)
|
||||
wraplength=400, justify=tk.LEFT).pack(padx=20, anchor=tk.W)
|
||||
|
||||
btns = tk.Frame(pick, bg=COLORS["bg"])
|
||||
btns.pack(fill=tk.X, padx=20, pady=(10, 18))
|
||||
|
|
@ -761,16 +820,38 @@ class PendingLearningUIMixin:
|
|||
self.refresh_template_list()
|
||||
self.update_pending_btn()
|
||||
self._pl_toast(f"已学习为「{category}」并加入模板库", "ok")
|
||||
dialog.destroy()
|
||||
self.show_pending_dialog()
|
||||
self._drop_pending_row(dialog, pending_id, row)
|
||||
else:
|
||||
messagebox.showerror("失败", "学习失败,请重试", parent=pick)
|
||||
|
||||
PillButton(btns, text="确定学习", variant="primary", command=_confirm).pack(side=tk.RIGHT, padx=4)
|
||||
PillButton(btns, text="取消", variant="ghost", command=pick.destroy).pack(side=tk.RIGHT)
|
||||
pick.bind("<Return>", lambda e: _confirm())
|
||||
pick.update_idletasks()
|
||||
self._pl_place_center(pick, max(pick.winfo_reqwidth(), 480), pick.winfo_reqheight())
|
||||
pick.wait_window()
|
||||
|
||||
def _drop_pending_row(self, dialog, pending_id, row):
|
||||
"""学完只去掉当前行,列表停在原位置,不整页重建。"""
|
||||
items = getattr(dialog, "_pending_items", None)
|
||||
if isinstance(items, list):
|
||||
dialog._pending_items = [
|
||||
it for it in items if it.get("id") != pending_id
|
||||
]
|
||||
lbl = getattr(dialog, "_pending_count_label", None)
|
||||
if lbl is not None:
|
||||
try:
|
||||
n = len(getattr(dialog, "_pending_items", []) or [])
|
||||
lbl.config(text=f"共 {n} 条记录")
|
||||
except Exception:
|
||||
pass
|
||||
if row is not None:
|
||||
try:
|
||||
if row.winfo_exists():
|
||||
row.destroy()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def _ignore_pending_from_dialog(self, pending_id, dialog):
|
||||
if self.manager.ignore_pending(pending_id):
|
||||
self.update_pending_btn()
|
||||
|
|
|
|||
Loading…
Reference in New Issue