Files
baiyue-logistics-chat/static/js/admin_tools.js
T

120 lines
5.2 KiB
JavaScript

// Workspace notes, transfers, recalls and historical message search.
function updateAdminTools(){
document.getElementById('transfer-session').disabled = !curSid || Boolean(sendingSid) || Boolean(closingSid);
document.getElementById('agent-emoji-toggle').disabled = !curSid || Boolean(sendingSid) || Boolean(closingSid);
document.getElementById('noteInput').disabled = !curSid || Boolean(sessions[curSid].noteLoading);
document.getElementById('note-save').disabled = !curSid || !sessions[curSid].noteLoaded || Boolean(sessions[curSid].noteLoading);
}
async function loadSessionNote(sid){
const session = sessions[sid];
const input = document.getElementById('noteInput');
input.value = session.noteDraft || '';
if(session.noteLoaded){ updateAdminTools(); return; }
session.noteLoading = true;
updateAdminTools();
try{
const state = await adminRequest('/api/human/poll?sid='+Number(sid)+'&after=0');
if(sessions[sid] !== session) return;
session.noteDraft = state.note || '';
session.noteLoaded = true;
if(curSid === sid) input.value = session.noteDraft;
}catch(error){
if(curSid === sid) setReplyStatus('备注加载失败,请重新选择会话后重试。', true);
}finally{
session.noteLoading = false;
updateAdminTools();
}
}
async function saveNote(){
if(!curSid || !sessions[curSid].noteLoaded) return;
const sid = curSid, session = sessions[sid];
const note = document.getElementById('noteInput').value;
session.noteDraft = note;
try{
await postAdmin('/api/human/note', {sid:Number(sid), note:note});
if(curSid === sid) setReplyStatus(session.noteDraft === note ? '备注已保存' : '先前备注已保存,当前修改尚未保存');
}catch(error){
if(curSid === sid) setReplyStatus('备注保存失败,内容已保留。', true);
}
}
async function transferSession(){
if(!curSid || closingSid || sendingSid) return;
if(!window.confirm('确定转接这个对话?转接后其他客服可在排队列表接入。')) return;
const sid = curSid;
closingSid = sid;
updateComposer();
try{
await postAdmin('/api/human/transfer', {sid:Number(sid)});
delete sessions[sid];
if(curSid === sid) showEmptySession();
renderList();
loadQueue();
}catch(error){
if(curSid === sid) setReplyStatus('转接未成功,会话仍保留。', true);
}finally{
closingSid = '';
updateComposer();
}
}
function applyAdminRecall(sid, mid){
const message = sessions[sid].msgs.find(function(item){ return item.id === mid; });
if(message){ message.side = 'system'; message.content = '该消息已撤回'; }
if(curSid === sid){
const row = document.querySelector('#chatBox [data-message-id="'+Number(mid)+'"]');
if(row){ row.className = 'msg system-msg'; row.textContent = '该消息已撤回'; }
}
return Boolean(message);
}
async function recallMsg(mid){
if(!curSid) return;
const sid = curSid;
try{
await postAdmin('/api/human/recall', {mid:mid});
if(sessions[sid]){ applyAdminRecall(sid, mid); renderList(); }
}catch(error){
if(curSid === sid) setReplyStatus('撤回失败,请稍后重试。', true);
}
}
let searchVersion = 0;
async function doSearch(){
const keyword = document.getElementById('searchBox').value.trim();
const version = ++searchVersion;
const body = document.getElementById('searchBody');
if(!keyword){ body.textContent = '请输入关键词搜索历史消息'; return; }
body.textContent = '正在搜索…';
try{
const list = await adminRequest('/api/search_chat?q='+encodeURIComponent(keyword));
if(version !== searchVersion) return;
const roles = {user:'客户', assistant:'客服', system:'系统'};
body.innerHTML = list.length ? list.map(function(item){
return '<article class="search-result"><h3>'+escapeText(item.title)+'</h3><p>'+escapeText(item.content)+'</p><small>'+escapeText(roles[item.role] || item.role)+' · '+escapeText(item.ctime)+'</small></article>';
}).join('') : '没有匹配的历史消息';
}catch(error){
if(version === searchVersion) body.textContent = '搜索失败,请稍后重试';
}
}
document.getElementById('history-search-toggle').onclick = function(){
document.getElementById('searchResult').showModal();
document.getElementById('searchBox').focus();
};
document.getElementById('search-close').onclick = function(){ document.getElementById('searchResult').close(); };
document.getElementById('history-search-form').addEventListener('submit', function(event){ event.preventDefault(); doSearch(); });
document.getElementById('note-save').onclick = saveNote;
document.getElementById('noteInput').addEventListener('input', function(){
if(curSid) sessions[curSid].noteDraft = this.value;
});
document.getElementById('notifications-toggle').onclick = function(){ SupportUI.enableNotifications(this); };
function updateNightBadge(){
const hour = new Date().getHours();
document.getElementById('nightBadge').hidden = hour >= 8 && hour < 22;
}
updateNightBadge();
setInterval(updateNightBadge, 60000);