Spaces:
Sleeping
Sleeping
把連結補進 LINE 的訊息內容
Browse files確認信 (LINE):直接附上 「👉 確認連結」 和 「🚫 取消連結」。
提醒信 (LINE):附上 「🚫 取消連結」 (方便臨時不能來的客人取消)。
app.py
CHANGED
|
@@ -29,7 +29,7 @@ def get_bookings():
|
|
| 29 |
except:
|
| 30 |
return pd.DataFrame()
|
| 31 |
|
| 32 |
-
# 🔥🔥🔥 核心後端:智慧判斷發送邏輯 (
|
| 33 |
def send_confirmation_hybrid(booking_id):
|
| 34 |
if not booking_id: return "❌ 請輸入訂單 ID"
|
| 35 |
|
|
@@ -57,13 +57,15 @@ def send_confirmation_hybrid(booking_id):
|
|
| 57 |
action_label = "提醒"
|
| 58 |
mail_subject = f"🔔 行前提醒: {booking['date']} - Cié Cié Taipei"
|
| 59 |
|
|
|
|
| 60 |
line_text = (
|
| 61 |
f"🔔 行前提醒\n\n"
|
| 62 |
f"{booking['name']} 您好,期待今晚與您相見!\n\n"
|
| 63 |
f"📅 日期:{booking['date']}\n"
|
| 64 |
f"⏰ 時間:{booking['time']}\n"
|
| 65 |
f"👥 人數:{booking['pax']} 位\n\n"
|
| 66 |
-
f"
|
|
|
|
| 67 |
)
|
| 68 |
|
| 69 |
mail_html = f"""
|
|
@@ -88,13 +90,16 @@ def send_confirmation_hybrid(booking_id):
|
|
| 88 |
action_label = "確認"
|
| 89 |
mail_subject = f"訂位確認: {booking['date']} - Cié Cié Taipei"
|
| 90 |
|
|
|
|
| 91 |
line_text = (
|
| 92 |
f"✅ 訂位確認\n\n"
|
| 93 |
f"{booking['name']} 您好,已收到您的預約。\n\n"
|
| 94 |
f"📅 日期:{booking['date']}\n"
|
| 95 |
f"⏰ 時間:{booking['time']}\n"
|
| 96 |
f"👥 人數:{booking['pax']} 位\n\n"
|
| 97 |
-
f"
|
|
|
|
|
|
|
| 98 |
)
|
| 99 |
|
| 100 |
mail_html = f"""
|
|
@@ -125,7 +130,7 @@ def send_confirmation_hybrid(booking_id):
|
|
| 125 |
else:
|
| 126 |
log_msg += "⚠️ 無Mail "
|
| 127 |
|
| 128 |
-
# LINE
|
| 129 |
if user_id and len(str(user_id)) > 5 and LINE_ACCESS_TOKEN:
|
| 130 |
try:
|
| 131 |
r = requests.post("https://api.line.me/v2/bot/message/push",
|
|
@@ -167,7 +172,6 @@ def render_booking_cards():
|
|
| 167 |
elif '已發' in status:
|
| 168 |
status_bg = "#f1c40f"; status_tx = "#000"; border_color = "#f1c40f"
|
| 169 |
|
| 170 |
-
# 這裡不放按鈕了,改放一個超大的 ID 顯示
|
| 171 |
card = f"""
|
| 172 |
<div class="booking-card" style="
|
| 173 |
background: #1a1a1a;
|
|
@@ -234,8 +238,6 @@ def check_login(user, password):
|
|
| 234 |
# --- CSS ---
|
| 235 |
custom_css = """
|
| 236 |
body, .gradio-container { background-color: #0F0F0F; color: #fff; }
|
| 237 |
-
|
| 238 |
-
/* 讓操作區塊固定在頂部 (Sticky) */
|
| 239 |
#op-panel {
|
| 240 |
position: sticky;
|
| 241 |
top: 0;
|
|
@@ -246,7 +248,6 @@ body, .gradio-container { background-color: #0F0F0F; color: #fff; }
|
|
| 246 |
margin-bottom: 20px;
|
| 247 |
box-shadow: 0 4px 10px rgba(0,0,0,0.5);
|
| 248 |
}
|
| 249 |
-
|
| 250 |
#booking_display {
|
| 251 |
height: auto !important;
|
| 252 |
overflow: visible !important;
|
|
@@ -269,7 +270,6 @@ with gr.Blocks(title="Admin") as demo:
|
|
| 269 |
with gr.Column(elem_id="op-panel"):
|
| 270 |
gr.Markdown("### 🍷 Cié Cié 訂位管理")
|
| 271 |
with gr.Row():
|
| 272 |
-
# 這裡就是最原始、最不會壞的輸入框 + 按鈕
|
| 273 |
id_input = gr.Number(label="輸入 ID 發送通知", precision=0, scale=2)
|
| 274 |
send_btn = gr.Button("🚀 發送通知 / 提醒 (Hybrid)", variant="primary", scale=1)
|
| 275 |
refresh_btn = gr.Button("🔄 刷新列表", scale=1)
|
|
@@ -283,10 +283,8 @@ with gr.Blocks(title="Admin") as demo:
|
|
| 283 |
render_booking_cards, outputs=booking_display
|
| 284 |
)
|
| 285 |
|
| 286 |
-
# 綁定刷新
|
| 287 |
refresh_btn.click(render_booking_cards, outputs=booking_display)
|
| 288 |
|
| 289 |
-
# 綁定發送 (發送完自動刷新列表)
|
| 290 |
send_btn.click(
|
| 291 |
send_confirmation_hybrid,
|
| 292 |
inputs=id_input,
|
|
|
|
| 29 |
except:
|
| 30 |
return pd.DataFrame()
|
| 31 |
|
| 32 |
+
# 🔥🔥🔥 核心後端:智慧判斷發送邏輯 (修正 LINE 連結) 🔥🔥🔥
|
| 33 |
def send_confirmation_hybrid(booking_id):
|
| 34 |
if not booking_id: return "❌ 請輸入訂單 ID"
|
| 35 |
|
|
|
|
| 57 |
action_label = "提醒"
|
| 58 |
mail_subject = f"🔔 行前提醒: {booking['date']} - Cié Cié Taipei"
|
| 59 |
|
| 60 |
+
# 🔥 LINE 修正:加入取消連結,方便客人臨時取消
|
| 61 |
line_text = (
|
| 62 |
f"🔔 行前提醒\n\n"
|
| 63 |
f"{booking['name']} 您好,期待今晚與您相見!\n\n"
|
| 64 |
f"📅 日期:{booking['date']}\n"
|
| 65 |
f"⏰ 時間:{booking['time']}\n"
|
| 66 |
f"👥 人數:{booking['pax']} 位\n\n"
|
| 67 |
+
f"座位已為您準備好。\n"
|
| 68 |
+
f"若無法前來,請點擊下方連結取消:\n{cancel_link}"
|
| 69 |
)
|
| 70 |
|
| 71 |
mail_html = f"""
|
|
|
|
| 90 |
action_label = "確認"
|
| 91 |
mail_subject = f"訂位確認: {booking['date']} - Cié Cié Taipei"
|
| 92 |
|
| 93 |
+
# 🔥 LINE 修正:加入 確認 與 取消 的連結
|
| 94 |
line_text = (
|
| 95 |
f"✅ 訂位確認\n\n"
|
| 96 |
f"{booking['name']} 您好,已收到您的預約。\n\n"
|
| 97 |
f"📅 日期:{booking['date']}\n"
|
| 98 |
f"⏰ 時間:{booking['time']}\n"
|
| 99 |
f"👥 人數:{booking['pax']} 位\n\n"
|
| 100 |
+
f"請點擊下方連結確認出席:\n"
|
| 101 |
+
f"👉 確認:{confirm_link}\n\n"
|
| 102 |
+
f"🚫 取消:{cancel_link}"
|
| 103 |
)
|
| 104 |
|
| 105 |
mail_html = f"""
|
|
|
|
| 130 |
else:
|
| 131 |
log_msg += "⚠️ 無Mail "
|
| 132 |
|
| 133 |
+
# LINE
|
| 134 |
if user_id and len(str(user_id)) > 5 and LINE_ACCESS_TOKEN:
|
| 135 |
try:
|
| 136 |
r = requests.post("https://api.line.me/v2/bot/message/push",
|
|
|
|
| 172 |
elif '已發' in status:
|
| 173 |
status_bg = "#f1c40f"; status_tx = "#000"; border_color = "#f1c40f"
|
| 174 |
|
|
|
|
| 175 |
card = f"""
|
| 176 |
<div class="booking-card" style="
|
| 177 |
background: #1a1a1a;
|
|
|
|
| 238 |
# --- CSS ---
|
| 239 |
custom_css = """
|
| 240 |
body, .gradio-container { background-color: #0F0F0F; color: #fff; }
|
|
|
|
|
|
|
| 241 |
#op-panel {
|
| 242 |
position: sticky;
|
| 243 |
top: 0;
|
|
|
|
| 248 |
margin-bottom: 20px;
|
| 249 |
box-shadow: 0 4px 10px rgba(0,0,0,0.5);
|
| 250 |
}
|
|
|
|
| 251 |
#booking_display {
|
| 252 |
height: auto !important;
|
| 253 |
overflow: visible !important;
|
|
|
|
| 270 |
with gr.Column(elem_id="op-panel"):
|
| 271 |
gr.Markdown("### 🍷 Cié Cié 訂位管理")
|
| 272 |
with gr.Row():
|
|
|
|
| 273 |
id_input = gr.Number(label="輸入 ID 發送通知", precision=0, scale=2)
|
| 274 |
send_btn = gr.Button("🚀 發送通知 / 提醒 (Hybrid)", variant="primary", scale=1)
|
| 275 |
refresh_btn = gr.Button("🔄 刷新列表", scale=1)
|
|
|
|
| 283 |
render_booking_cards, outputs=booking_display
|
| 284 |
)
|
| 285 |
|
|
|
|
| 286 |
refresh_btn.click(render_booking_cards, outputs=booking_display)
|
| 287 |
|
|
|
|
| 288 |
send_btn.click(
|
| 289 |
send_confirmation_hybrid,
|
| 290 |
inputs=id_input,
|