diff --git a/python/Bag1.py b/python/Bag1.py index c8faeda..d26590a 100644 --- a/python/Bag1.py +++ b/python/Bag1.py @@ -111,7 +111,8 @@ def try_printer_connection(printer_name: str, sett: dict) -> bool: FONT_SIZE = 16 FONT_SIZE_BUTTONS = 15 FONT_SIZE_QTY = 12 # smaller for 數量 under batch no. -FONT_SIZE_ITEM = 20 # item code and item name (larger for readability) +FONT_SIZE_ITEM_CODE = 20 # item code (larger for readability) +FONT_SIZE_ITEM_NAME = 26 # item name (bigger than item code) FONT_FAMILY = "Microsoft JhengHei UI" # Traditional Chinese; fallback to TkDefaultFont # Column widths: item code own column; item name at least double, wraps in its column ITEM_CODE_WRAP = 140 # item code column width (long codes wrap under code only) @@ -134,6 +135,7 @@ PRINTER_CHECK_MS = 60 * 1000 # 1 minute when printer OK PRINTER_RETRY_MS = 30 * 1000 # 30 seconds when printer failed PRINTER_SOCKET_TIMEOUT = 3 DATAFLEX_SEND_TIMEOUT = 10 # seconds when sending ZPL to DataFlex +DATE_AUTO_RESET_SEC = 5 * 60 # 5 minutes: if no manual date change, auto-set to today def _zpl_escape(s: str) -> str: @@ -180,9 +182,9 @@ def generate_zpl_dataflex( ^PW700 ^LL500 ^PO N -^FO10,188 +^FO10,20 ^BQR,4,7^FDQA,{batch_no}^FS -^FO170,188 +^FO170,20 ^A@R,72,72,{font_regular}^FD{desc}^FS ^FO0,260 ^A@R,72,72,{font_regular}^FD{batch_esc}^FS @@ -216,8 +218,9 @@ def format_qty(val) -> str: def batch_no(year: int, job_order_id: int) -> str: - """Batch no.: B + 4-digit year + jobOrderId zero-padded to 6 digits.""" - return f"B{year}{job_order_id:06d}" + """Batch no.: B + 2-digit year + jobOrderId zero-padded to 6 digits.""" + short_year = year % 100 + return f"B{short_year:02d}{job_order_id:06d}" def get_font(size: int = FONT_SIZE, bold: bool = False) -> tuple: @@ -380,6 +383,15 @@ def main() -> None: status_frame.configure(bg=BG_STATUS_ERROR) status_lbl.configure(text="連接不到服務器", bg=BG_STATUS_ERROR, fg=FG_STATUS_ERROR) + def set_status_message(msg: str, is_error: bool = False): + """Show a temporary message on the status bar.""" + if is_error: + status_frame.configure(bg=BG_STATUS_ERROR) + status_lbl.configure(text=msg, bg=BG_STATUS_ERROR, fg=FG_STATUS_ERROR) + else: + status_frame.configure(bg=BG_STATUS_OK) + status_lbl.configure(text=msg, bg=BG_STATUS_OK, fg=FG_STATUS_OK) + # Top: left [前一天] [date] [後一天] | right [printer dropdown] top = tk.Frame(root, padx=12, pady=12, bg=BG_TOP) top.pack(fill=tk.X) @@ -387,23 +399,31 @@ def main() -> None: date_var = tk.StringVar(value=date.today().isoformat()) printer_options = ["打袋機 DataFlex", "標簽機", "激光機"] printer_var = tk.StringVar(value=printer_options[0]) + last_manual_date_change_ref = [time.time()] # track when user last changed date manually + + def mark_manual_date_change(): + last_manual_date_change_ref[0] = time.time() def go_prev_day() -> None: try: d = date.fromisoformat(date_var.get().strip()) date_var.set((d - timedelta(days=1)).isoformat()) + mark_manual_date_change() load_job_orders(from_user_date_change=True) except ValueError: date_var.set(date.today().isoformat()) + mark_manual_date_change() load_job_orders(from_user_date_change=True) def go_next_day() -> None: try: d = date.fromisoformat(date_var.get().strip()) date_var.set((d + timedelta(days=1)).isoformat()) + mark_manual_date_change() load_job_orders(from_user_date_change=True) except ValueError: date_var.set(date.today().isoformat()) + mark_manual_date_change() load_job_orders(from_user_date_change=True) # 前一天 (previous day) with left arrow icon @@ -420,6 +440,11 @@ def main() -> None: ) date_entry.pack(side=tk.LEFT, padx=(0, 8), ipady=4) + # Track manual typing in date field as user date change + def on_date_entry_key(event): + mark_manual_date_change() + date_entry.bind("", on_date_entry_key) + # 後一天 (next day) with right arrow icon btn_next = ttk.Button(top, text="後一天 ▶", command=go_next_day) btn_next.pack(side=tk.LEFT, padx=(0, 8)) @@ -643,7 +668,7 @@ def main() -> None: code_lbl = tk.Label( row, text=item_code, - font=get_font(FONT_SIZE_ITEM), + font=get_font(FONT_SIZE_ITEM_CODE), bg=BG_ROW, fg="black", wraplength=ITEM_CODE_WRAP, @@ -652,11 +677,11 @@ def main() -> None: ) code_lbl.pack(side=tk.LEFT, anchor=tk.NW, padx=(12, 8)) - # Column 3: item name only, same bigger font, at least double width, wraps under its own column + # Column 3: item name only, bigger font, at least double width, wraps under its own column name_lbl = tk.Label( row, text=item_name or "—", - font=get_font(FONT_SIZE_ITEM), + font=get_font(FONT_SIZE_ITEM_NAME), bg=BG_ROW, fg="black", wraplength=ITEM_NAME_WRAP, @@ -693,13 +718,13 @@ def main() -> None: if i < n - 1: time.sleep(2) msg = f"已送出列印:批次 {b} x {n} 張" if count != -1 else f"已送出列印:批次 {b} x {n} 張 (連續)" - messagebox.showinfo("打袋機", msg) + set_status_message(msg, is_error=False) except ConnectionRefusedError: - messagebox.showerror("打袋機", f"無法連線至 {ip}:{port},請確認印表機已開機且 IP 正確。") + set_status_message(f"無法連線至 {ip}:{port},請確認印表機已開機且 IP 正確。", is_error=True) except socket.timeout: - messagebox.showerror("打袋機", f"連線逾時 ({ip}:{port}),請檢查網路與連接埠。") + set_status_message(f"連線逾時 ({ip}:{port}),請檢查網路與連接埠。", is_error=True) except OSError as err: - messagebox.showerror("打袋機", f"列印失敗:{err}") + set_status_message(f"列印失敗:{err}", is_error=True) elif printer_var.get() == "標簽機": count = ask_label_count(root) if count is not None: @@ -707,7 +732,7 @@ def main() -> None: msg = "已選擇連續列印標簽" else: msg = f"將列印 {count} 張標簽" - messagebox.showinfo("標簽機", msg) + set_status_message(msg, is_error=False) on_job_order_click(j, b) for w in (row, left, batch_lbl, code_lbl, name_lbl): @@ -730,6 +755,13 @@ def main() -> None: if after_id_ref[0] is not None: root.after_cancel(after_id_ref[0]) after_id_ref[0] = None + # Auto-reset date to today if user hasn't manually changed it recently (for 24x7 use) + if not from_user_date_change: + elapsed = time.time() - last_manual_date_change_ref[0] + today_str = date.today().isoformat() + if elapsed > DATE_AUTO_RESET_SEC and date_var.get().strip() != today_str: + date_var.set(today_str) + from_user_date_change = True # treat as date change to reset selection/scroll date_str = date_var.get().strip() try: plan_start = date.fromisoformat(date_str)