支持免登录游客聊天并隔离历史与附件

This commit is contained in:
2026-10-30 12:17:43 +08:00
parent e58dd86d5b
commit 147edd042f
36 changed files with 663 additions and 129 deletions
+13 -29
View File
@@ -1,4 +1,5 @@
document.addEventListener('DOMContentLoaded', function(){
const fetch = VisitorSession.fetch;
const chatDom = document.getElementById("chatDom");
const inputDom = document.getElementById("input-text");
const sendBtn = document.getElementById("send-button");
@@ -210,7 +211,7 @@ const I18N = {
thinking: "正在思考中...",
busyRetry: "服务繁忙,请稍后重试",
sessionFail: "会话创建失败,请确认服务已启动",
autoWelcome: "您好!欢迎咨询柏悦物流智能客服,请问有什么可以帮您?输入订单号、入仓码或 Shipment ID 可查订单,或点击下方快捷选项。",
autoWelcome: "您好!欢迎咨询柏悦物流智能客服,可以咨询运费、时效或联系人工客服。订单查询将在客户账号登录并关联后开放。",
humanHours: "人工客服工作时间:每天 8:00-22:00。当前为非工作时间,请留言,工作时间会尽快回复您。",
offlinePrompt: "请输入您的留言:",
offlineSaved: "留言已提交,工作时间(8:00-22:00)会尽快回复您。",
@@ -243,7 +244,7 @@ const I18N = {
retryAIOnly: "请先返回 AI 问答,再重答这条消息。",
clickRetry: "点击重试",
welcomeTitle: "物流问题,随时为您解答",
welcomeSub: "查询订单状态、了解专线报价,或联系人工客服。",
welcomeSub: "咨询运费、时效或联系人工客服。订单查询需关联客户账号。",
welcomeEyebrow: "中欧 · 英国物流服务",
serviceScope: "中欧与英国专线咨询",
serviceTag: "物流咨询服务",
@@ -291,7 +292,7 @@ const I18N = {
order_parent: "父订单号", order_updated: "来源更新时间",
moreTracking: "展开全部轨迹",
lessTracking: "收起较早轨迹",
quickSubs: ["输入订单号、入仓码或 Shipment ID", "了解线路、费用与预计时效", "咨询延误、签收或理赔问题", "进一步沟通您的物流需求"],
quickSubs: ["关联客户账号后查询订单与轨迹", "了解线路、费用与预计时效", "咨询延误、签收或理赔问题", "进一步沟通您的物流需求"],
welcomeTip: "您可以直接输入问题,也可以点击下面选项快速提问。",
hot: "热点问题",
recent: "最近对话记录",
@@ -320,7 +321,7 @@ const I18N = {
thinking: "Thinking...",
busyRetry: "Service busy, please try again later",
sessionFail: "Failed to create session, please check the service is running",
autoWelcome: "Welcome to Baiyue Logistics. Enter an order number, inbound code or Shipment ID, or choose a quick option below.",
autoWelcome: "Welcome to Baiyue Logistics. Ask about rates, transit times or human support. Order lookup will be available after signing in and linking a customer account.",
humanHours: "Our team is available daily, 08:00–22:00. Please leave a message and we will reply during service hours.",
offlinePrompt: "Please leave your message:",
offlineSaved: "Message submitted. Our team will reply during service hours (08:00–22:00).",
@@ -353,7 +354,7 @@ const I18N = {
retryAIOnly: "Return to AI chat before regenerating this answer.",
clickRetry: "Retry",
welcomeTitle: "Your next shipment, made clearer.",
welcomeSub: "Track a parcel, explore freight options, or speak to our team.",
welcomeSub: "Ask about rates, transit times or human support. Order lookup requires a linked customer account.",
welcomeEyebrow: "EUROPE & UK LOGISTICS",
serviceScope: "Europe & UK freight support",
serviceTag: "Logistics support",
@@ -403,7 +404,7 @@ const I18N = {
order_parent: "Parent order", order_updated: "Source updated",
moreTracking: "View full tracking history",
lessTracking: "Show recent updates",
quickSubs: ["Check the latest shipment progress", "Explore routes, rates and transit times", "Get help with delays, delivery or claims", "Discuss your shipping requirements"],
quickSubs: ["Link a customer account to view orders and tracking", "Explore routes, rates and transit times", "Get help with delays, delivery or claims", "Discuss your shipping requirements"],
welcomeTip: "Type your question, or pick a quick option below.",
hot: "Popular Questions",
recent: "Recent Conversations",
@@ -1061,24 +1062,6 @@ window.sendOrder = function(){
}
}
function myOrders(){
var phone = window.prompt("请输入您的手机号:");
if(!phone) return;
addMsg("查询手机号 "+phone+" 的包裹...", false);
fetch("/api/my_orders?phone="+encodeURIComponent(phone))
.then(r=>r.json())
.then(d=>{
if(!d.orders.length){
addMsg("手机号 "+phone+" 下暂无运单记录。", false);
}else{
var txt = "您名下有 "+d.orders.length+" 个包裹:\n";
d.orders.forEach(function(o){ txt += "• "+o.track_no+"("+o.status+")\n"; });
addMsg(txt, false);
}
})
.catch(function(){ addMsg("查询失败,请重试", false); });
}
function updateHumanMode(){
const banner = document.getElementById('human-session');
const label = document.getElementById('human-session-label');
@@ -1129,7 +1112,7 @@ window.showHuman = async function(){
try{
const cid = await ensureConv();
if(humanRequestToken !== token || token.version !== conversationVersion) return;
const data = await humanRequest('/api/human/request', {conv_id:cid});
const data = await humanRequest('/api/visitor/human/request', {conv_id:cid});
if(humanRequestToken !== token || token.version !== conversationVersion) return;
if(data.closed){ await leaveOfflineMessage(); return; }
if(!data.ok || !data.session_id) throw new Error('Human session failed');
@@ -1151,7 +1134,7 @@ async function returnToAI(){
humanClosing = true;
updateHumanMode();
try{
const result = await humanRequest('/api/human/close', {sid:sid});
const result = await humanRequest('/api/visitor/human/close', {sid:sid});
if(!result.ok) throw new Error('Close failed');
if(version !== conversationVersion || window.humanSid !== sid) return;
stopHumanMode();
@@ -1176,7 +1159,7 @@ async function sendHumanMessage(content){
updateHumanMode();
setComposerStatus(t('humanSending'));
try{
const result = await humanRequest('/api/human/send', {sid:sid, conv_id:cid, side:'customer', content:content});
const result = await humanRequest('/api/visitor/human/send', {sid:sid, conv_id:cid, side:'customer', content:content});
if(!result.ok) throw new Error('Send failed');
if(version !== conversationVersion || humanSendingToken !== token) return;
addMsg(content, true);
@@ -1221,7 +1204,7 @@ function startHumanPoll(){
if(window.humanSid !== sid || version !== conversationVersion || currentConvId !== cid){ clearInterval(pollTimer); return; }
if(polling) return;
polling=true;
humanRequest("/api/human/poll?sid="+sid+"&after="+last)
humanRequest("/api/visitor/human/poll?sid="+sid+"&after="+last)
.then(d=>{
if(window.humanSid !== sid || version !== conversationVersion || currentConvId !== cid) return;
if(hadPollError){ setComposerStatus(''); hadPollError=false; }
@@ -1253,7 +1236,7 @@ function startHumanPoll(){
stopHumanMode();
setBusy(false);
addMsg(t('humanClosed'), false);
SupportUI.addRating(chatDom, sid, {question:t('ratingQuestion'), thanks:t('ratingThanks'), failed:t('ratingFailed')});
SupportUI.addRating(chatDom, sid, {question:t('ratingQuestion'), thanks:t('ratingThanks'), failed:t('ratingFailed'), fetch:fetch});
scrollChatToEnd();
return;
}
@@ -1831,6 +1814,7 @@ if(window.visualViewport) window.visualViewport.addEventListener('resize', syncC
syncChatViewport();
voiceInput = ChatVoice.create({
fetch:fetch,
toggle:document.getElementById('voice-toggle'), hold:document.getElementById('voice-hold'),
panel:document.getElementById('voice-panel'), label:document.getElementById('voice-label'),
clock:document.getElementById('voice-clock'), inputArea:document.querySelector('.input-area'), input:inputDom,