Files changed (1) hide show
  1. app.py +36 -6
app.py CHANGED
@@ -52,7 +52,7 @@ def check_url_action(request: gr.Request):
52
 
53
 
54
  # ==========================================
55
- # 模組 1:訂位與通知管理 (包含 No-Show 切換)
56
  # ==========================================
57
 
58
  def get_bookings():
@@ -138,6 +138,17 @@ def toggle_no_show(booking_id, is_noshow=True):
138
  except Exception as e:
139
  return f"❌ 錯誤: {str(e)}"
140
 
 
 
 
 
 
 
 
 
 
 
 
141
  def render_booking_cards():
142
  df = get_bookings()
143
  count_html = f"<div style='color:#bbb; margin-bottom:10px; text-align:right; font-size:14px;'>📊 共 <span style='color:#fff; font-weight:bold;'>{len(df)}</span> 筆資料</div>"
@@ -154,6 +165,7 @@ def render_booking_cards():
154
  elif '取消' in status: status_bg = "#e74c3c"; status_tx = "#fff"; border_color = "#e74c3c"
155
  elif '已發' in status: status_bg = "#f1c40f"; status_tx = "#000"; border_color = "#f1c40f"
156
  elif 'No-Show' in status: status_bg = "#000"; status_tx = "#e74c3c"; border_color = "#e74c3c"
 
157
 
158
  line_badge = "<span style='background:#00B900; color:white; padding:2px 6px; border-radius:4px; font-size:0.7em; margin-left:8px;'>LINE綁定</span>" if has_line else ""
159
 
@@ -324,19 +336,37 @@ with gr.Blocks(title="Cié Cié Admin", css=custom_css, theme=gr.themes.Monochro
324
  # --- 分頁 1:訂位與通知管理 ---
325
  with gr.TabItem("🍷 訂位與通知管理"):
326
  with gr.Column(elem_id="op-panel"):
327
- gr.Markdown("### 🚀 發送通知與防鴿子標記")
 
 
328
  with gr.Row():
329
- id_input = gr.Number(label="輸入訂單 ID", precision=0, scale=2)
330
- send_btn = gr.Button("🚀 發送提醒/確認", variant="primary", scale=1)
331
- # No-Show 雙按鈕
 
 
 
 
 
 
 
 
332
  noshow_btn = gr.Button("🚫 標記 No-Show", variant="stop", scale=1)
333
  revert_noshow_btn = gr.Button("✅ 撤銷 No-Show", scale=1)
334
  refresh_btn = gr.Button("🔄 刷新列表", scale=1)
 
335
  log_output = gr.Textbox(label="執行結果日誌", lines=1)
336
 
337
  booking_display = gr.HTML(elem_id="booking_display")
338
 
339
- # 按鈕事件
 
 
 
 
 
 
 
340
  refresh_btn.click(render_booking_cards, outputs=booking_display)
341
  send_btn.click(send_confirmation_hybrid, inputs=id_input, outputs=log_output).then(render_booking_cards, outputs=booking_display)
342
  noshow_btn.click(toggle_no_show, inputs=[id_input, gr.State(True)], outputs=log_output).then(render_booking_cards, outputs=booking_display)
 
52
 
53
 
54
  # ==========================================
55
+ # 模組 1:訂位與通知管理 (包含 No-Show 切換與手動狀態)
56
  # ==========================================
57
 
58
  def get_bookings():
 
138
  except Exception as e:
139
  return f"❌ 錯誤: {str(e)}"
140
 
141
+ # 🌟 新增:手動強制更新狀態 🌟
142
+ def update_booking_status(booking_id, new_status):
143
+ if not booking_id: return "❌ 請輸入訂單 ID"
144
+ if not new_status: return "⚠️ 請選擇要更改的新狀態"
145
+ try:
146
+ res = supabase.table("bookings").update({"status": new_status}).eq("id", booking_id).execute()
147
+ if not res.data: raise Exception("找不到該筆訂單或權限不足")
148
+ return f"✅ 訂單 {booking_id} 狀態已成功更新為:【{new_status}】"
149
+ except Exception as e:
150
+ return f"❌ 狀態更新失敗: {str(e)}"
151
+
152
  def render_booking_cards():
153
  df = get_bookings()
154
  count_html = f"<div style='color:#bbb; margin-bottom:10px; text-align:right; font-size:14px;'>📊 共 <span style='color:#fff; font-weight:bold;'>{len(df)}</span> 筆資料</div>"
 
165
  elif '取消' in status: status_bg = "#e74c3c"; status_tx = "#fff"; border_color = "#e74c3c"
166
  elif '已發' in status: status_bg = "#f1c40f"; status_tx = "#000"; border_color = "#f1c40f"
167
  elif 'No-Show' in status: status_bg = "#000"; status_tx = "#e74c3c"; border_color = "#e74c3c"
168
+ elif '付款' in status: status_bg = "#3498db"; status_tx = "#fff"; border_color = "#3498db"
169
 
170
  line_badge = "<span style='background:#00B900; color:white; padding:2px 6px; border-radius:4px; font-size:0.7em; margin-left:8px;'>LINE綁定</span>" if has_line else ""
171
 
 
336
  # --- 分頁 1:訂位與通知管理 ---
337
  with gr.TabItem("🍷 訂位與通知管理"):
338
  with gr.Column(elem_id="op-panel"):
339
+ gr.Markdown("### 🚀 訂單操作控制台")
340
+
341
+ # 第一排:ID 輸入與狀態變更選單
342
  with gr.Row():
343
+ id_input = gr.Number(label="輸入訂單 ID", precision=0, scale=1)
344
+ new_status_dropdown = gr.Dropdown(
345
+ label="手動選擇新狀態",
346
+ choices=["待處理", "待處理 (已付訂金)", "待付款", "已發確認信", "顧客已確認", "顧客已取消", "No-Show", "已完成 (結案)"],
347
+ scale=1
348
+ )
349
+
350
+ # 第二排:各式操作按鈕
351
+ with gr.Row():
352
+ send_btn = gr.Button("🚀 發信/LINE", variant="primary", scale=1)
353
+ update_status_btn = gr.Button("💾 變更狀態", variant="secondary", scale=1)
354
  noshow_btn = gr.Button("🚫 標記 No-Show", variant="stop", scale=1)
355
  revert_noshow_btn = gr.Button("✅ 撤銷 No-Show", scale=1)
356
  refresh_btn = gr.Button("🔄 刷新列表", scale=1)
357
+
358
  log_output = gr.Textbox(label="執行結果日誌", lines=1)
359
 
360
  booking_display = gr.HTML(elem_id="booking_display")
361
 
362
+ # 🌟 新增:手動更新狀態的按鈕事件 🌟
363
+ update_status_btn.click(
364
+ update_booking_status,
365
+ inputs=[id_input, new_status_dropdown],
366
+ outputs=log_output
367
+ ).then(render_booking_cards, outputs=booking_display)
368
+
369
+ # 其餘按鈕事件
370
  refresh_btn.click(render_booking_cards, outputs=booking_display)
371
  send_btn.click(send_confirmation_hybrid, inputs=id_input, outputs=log_output).then(render_booking_cards, outputs=booking_display)
372
  noshow_btn.click(toggle_no_show, inputs=[id_input, gr.State(True)], outputs=log_output).then(render_booking_cards, outputs=booking_display)