120 lines
5.2 KiB
JavaScript
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);
|