diff --git a/am.py b/am.py index 97a3644..00492e6 100644 --- a/am.py +++ b/am.py @@ -44,7 +44,7 @@ _hits = defaultdict(list) @app.before_request def rate_limit(): p = request.path - if p.startswith("/static"): + if p.startswith("/static") or p.startswith("/api/human/"): return None ip = request.remote_addr or "unknown" now = time.time() @@ -1236,10 +1236,6 @@ def get_history(): # ===== 管理员后台 ===== -@app.route("/admin") -def admin(): - return render_template("admin.html") - @app.route("/api/admin/stats") def admin_stats(): conn = sqlite3.connect(DB) @@ -1309,6 +1305,13 @@ def human_queue(): conn.close() return jsonify([{"id": r[0], "conv_id": r[1], "ctime": r[3]} for r in rows]) +@app.route("/api/human/active") +def human_active(): + conn = sqlite3.connect(DB) + rows = conn.execute("SELECT id, conv_id FROM human_sessions WHERE status='active' ORDER BY id").fetchall() + conn.close() + return jsonify([{"id": r[0], "conv_id": r[1]} for r in rows]) + @app.route("/api/human/accept", methods=["POST"]) def human_accept(): sid = request.json.get("sid") @@ -1434,6 +1437,11 @@ def uploaded_file(name): def index(): return render_template("index.html") +@app.route("/admin") +def admin(): + return render_template("admin.html") + + if __name__ == "__main__": # 0.0.0.0 = 接受局域网内所有设备访问(手机、其他电脑); # 只在演示时开启,演示完建议改回 127.0.0.1,避免别人误用消耗 API 额度 diff --git a/c.json b/c.json new file mode 100644 index 0000000..d4229bc --- /dev/null +++ b/c.json @@ -0,0 +1 @@ +{"sid":24} diff --git a/check.py b/check.py new file mode 100644 index 0000000..d4106e5 --- /dev/null +++ b/check.py @@ -0,0 +1,5 @@ +import sqlite3 +c = sqlite3.connect('history.db') +print(c.execute('SELECT * FROM human_messages ORDER BY id DESC LIMIT 5').fetchall()) +print('---') +print(c.execute("SELECT id, status FROM human_sessions WHERE status!='closed'").fetchall()) diff --git a/clean.py b/clean.py new file mode 100644 index 0000000..29d69a8 --- /dev/null +++ b/clean.py @@ -0,0 +1,5 @@ +import sqlite3 +c = sqlite3.connect('history.db') +c.execute("UPDATE human_sessions SET status='closed' WHERE status='active'") +c.commit() +print('ok') diff --git a/s.json b/s.json new file mode 100644 index 0000000..22f3245 --- /dev/null +++ b/s.json @@ -0,0 +1 @@ +{"sid":48,"side":"agent","content":"test123"} diff --git a/t.json b/t.json new file mode 100644 index 0000000..6347d41 --- /dev/null +++ b/t.json @@ -0,0 +1 @@ +{"conv_id":999} diff --git a/templates/admin.html b/templates/admin.html index 345b211..68ea4d0 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -62,97 +62,123 @@ th,td{padding:6px 10px;border-bottom:1px solid #eee;text-align:left;} ← 返回客服页 diff --git a/templates/index.html b/templates/index.html index 5a1fd1a..0161ddf 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1202,6 +1202,7 @@ 🤖柏悦物流智能助手 + @@ -1361,6 +1362,27 @@ window.__busy = false; // 生成中状态,用 window 属性避免作用域 } })(); +// ===== 字体大小切换 ===== +(function(){ + var KEY = "wuliu-fontsize"; + var SIZES = [14, 16, 18, 20]; + var idx = 1; + try{ var s = localStorage.getItem(KEY); if(s) idx = parseInt(s); }catch(e){} + var btn = document.getElementById("font-toggle"); + function apply(){ + document.body.style.fontSize = SIZES[idx] + "px"; + if(btn) btn.textContent = SIZES[idx] + "px"; + } + apply(); + if(btn){ + btn.onclick = function(){ + idx = (idx + 1) % SIZES.length; + apply(); + try{ localStorage.setItem(KEY, idx); }catch(e){} + }; + } +})(); + // ===== 中英文切换 ===== const I18N = { zh: { @@ -1872,62 +1894,56 @@ window.showHuman = async function(){ addMsg("您已在人工客服会话中,请直接提问。", false); return; } - const now = new Date(); - const day = now.getDay(); - const h = now.getHours(); - const work = (day >= 1 && day <= 5) && (h >= 9 && h < 18); + var now = new Date(); + var day = now.getDay(); + var h = now.getHours(); + var work = (day >= 1 && day <= 5) && (h >= 9 && h < 19); if(!work){ addMsg("人工客服工作时间:周一至周五 9:00-18:00\n当前非工作时间,留言后工作时间内会尽快回复。", false); return; } addMsg("正在为您转接人工客服...", false); - if(!currentConvId) await ensureConv(); - fetch("/api/human/request",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({conv_id:currentConvId})}) - .then(r=>r.json()).then(d=>{ + if(!currentConvId){ + try{ await ensureConv(); }catch(e){} + } + fetch("/api/human/request",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({conv_id:currentConvId||0})}) + .then(function(r){return r.json()}) + .then(function(d){ if(d.ok){ window.humanSid = d.session_id; addMsg("您已加入人工排队,请稍候...", false); startHumanPoll(); + }else{ + addMsg("转接失败,请稍后再试。", false); } + }) + .catch(function(){ + addMsg("网络错误,请稍后再试。", false); }); } window.humanSid = 0; function startHumanPoll(){ let last=0; - let typingShown=null; const t=setInterval(()=>{ if(!window.humanSid){ clearInterval(t); return; } - fetch("/api/human/poll?sid="+window.humanSid+"&after="+last).then(r=>r.json()).then(d=>{ + fetch("/api/human/poll?sid="+window.humanSid+"&after="+last) + .then(r=>r.json()) + .then(d=>{ if(d.status==="closed"){ clearInterval(t); window.humanSid=0; window.__busy=false; if(typeof setBusy==="function") setBusy(false); addMsg("人工客服已结束,您可以继续向 AI 提问。", false); - inputDom.focus(); return; } - if(typingShown){ typingShown.remove(); typingShown=null; } - if(d.typing){ - typingShown = addMsg("对方正在输入...", false); - } d.messages.forEach(m=>{ last=m.id; - if(m.side==="agent"){ - addMsg(m.content, false); - } + if(m.side==="agent") addMsg(m.content, false); }); - // 已读回执:标记最后一条用户消息 - if(d.messages.some(m=>m.side==="customer" && m.read)){ - const rows=document.querySelectorAll(".msg-row.user-line"); - if(rows.length){ - const last=rows[rows.length-1]; - const ts=last.querySelector(".msg-time"); - if(ts && !ts.textContent.includes("已读")) ts.textContent += " ✓已读"; - } - } - }); - }, 2000); + }) + .catch(()=>{}); + }, 1000); } function addMsg(content, isUser){ diff --git a/启动.bat b/启动.bat index 2582230..0b2dff1 100644 --- a/启动.bat +++ b/启动.bat @@ -1,8 +1,6 @@ @echo off cd /d D:\1\wuliu_chat set DEEPSEEK_API_KEY=sk-529a6318230641a2b45bc28a716a1697 -echo 柏悦物流客服系统已启动 -echo 关闭这个黑窗口就停止服务 -echo 浏览器打开 http://127.0.0.1:5000/ -python am.py -pause +echo Starting... +echo Close this window to stop +start /wait python am.py