mirror of
https://git.hmsn.ink/kospo/helptalk/api.git
synced 2026-03-19 19:25:11 +09:00
570 lines
21 KiB
JavaScript
570 lines
21 KiB
JavaScript
import m from 'http://talk.kospo.co.kr:3000/static/bundle/mithril-2.2.2/mithril.js'
|
|
import {global} from "http://talk.kospo.co.kr:3000/static/js/module/variable.js";
|
|
import {talkMapping} from "http://talk.kospo.co.kr:3000/static/js/module/render.js";
|
|
import SockJS from "http://talk.kospo.co.kr:3000/static/bundle/sockjs-client-1.6.1/sockjs.js";
|
|
import {getTalkList, getMessageAll, getMoreMessageAll} from "http://talk.kospo.co.kr:3000/static/js/module/apis.js";
|
|
import {HubEvent} from "http://talk.kospo.co.kr:3000/static/js/module/hubEvent.js";
|
|
import {getApInfo} from "http://talk.kospo.co.kr:3000/static/js/module/apis.js";
|
|
import Common from "http://talk.kospo.co.kr:3000/static/js/utils.js";
|
|
import Hub from "http://talk.kospo.co.kr:3000/static/js/module/hub.js";
|
|
|
|
// 톡방 기능
|
|
let reConnectAttempts = 0;
|
|
let reConnectCnt = 0;
|
|
let errCnt = 0;
|
|
const talkEvent = {
|
|
// 소켓 연결
|
|
connect() {
|
|
const _this_ = this;
|
|
/*현재 서버 정보 호출*/
|
|
getApInfo().then((data) => {
|
|
global.currentServer = data.server
|
|
})
|
|
|
|
return new Promise((resolve, reject) => {
|
|
/*소켓연결*/
|
|
global.sockJS = new SockJS(
|
|
`${global.apiUrl}/stomp/talk`, {
|
|
Authentication: global.option.encSabun
|
|
}, {
|
|
transports: ['websocket'],
|
|
reconnectInterval: 500,
|
|
reconnectDelay: 500,
|
|
}
|
|
);
|
|
|
|
global.stomp = window.Stomp.over(global.sockJS);
|
|
global.stomp.heartbeat.outgoing = 20000;
|
|
global.stomp.heartbeat.incoming = 20000;
|
|
global.stomp.debug = (e) => {
|
|
if (e.includes('ERROR') || e.includes('Exception') || e.includes('failed')) {
|
|
// console.log(new Date().toString())
|
|
// console.error('STOMP error:', e);
|
|
}
|
|
};
|
|
|
|
/*stomp 연결*/
|
|
global.stomp.connect({Authentication: global.option.encSabun, location: 'TALK'}, function (frame) {
|
|
resolve();
|
|
})
|
|
|
|
global.stomp.onerror = (e) => {
|
|
console.log('err', e)
|
|
}
|
|
|
|
global.stomp.onclose = (e) => {
|
|
console.log('close', e)
|
|
}
|
|
|
|
const maxReconnectAttempts = 3;
|
|
const baseDelay = 10;
|
|
global.sockJS.onclose = (e) => {
|
|
if (e.wasClean) {
|
|
console.log('[Chat] WS Closed', new Date())
|
|
} else {
|
|
console.log('[Chat] WS Connecting...', new Date())
|
|
}
|
|
|
|
console.log(e)
|
|
/* 구독 해제 (남아 있는데이터 삭제) */
|
|
talkEvent.allUnsubscribe()
|
|
const delay = Math.min(baseDelay * Math.pow(100, reConnectAttempts), 2000)
|
|
const reConnectTimeout = setTimeout(() => {
|
|
if (reConnectAttempts < maxReconnectAttempts) {
|
|
reConnectAttempts++;
|
|
this.reConnect();
|
|
} else {
|
|
console.log('[Chat] Max Reconnect attempts reached.')
|
|
clearTimeout(reConnectTimeout)
|
|
/*서비스워커 종료*/
|
|
HubEvent.kill(global.talkParams({
|
|
type: 'KILL',
|
|
channelSabun: global.user.sabun
|
|
}))
|
|
global.forceKill = true;
|
|
global.shadowRoot.querySelector('.server-error').classList.remove('cus-hide')
|
|
}
|
|
}, delay)
|
|
}
|
|
})
|
|
|
|
},
|
|
reConnect: async () => {
|
|
console.log('reconnect')
|
|
// 소켓 설정 초기화
|
|
global.subscribeList = [];
|
|
|
|
/*현재 서버 정보 호출*/
|
|
let data = {};
|
|
try {
|
|
data = await getApInfo();
|
|
} catch (e) {
|
|
data['server'] = '';
|
|
}
|
|
|
|
/*ap 다른곳으로 이동시 서비스워커 재설치*/
|
|
if (global.currentServer !== data.server) {
|
|
HubEvent.close({
|
|
type: 'TAB_CLOSE',
|
|
tabId: global.tabId,
|
|
url: global.apiUrl,
|
|
sabun: global.user.sabun,
|
|
channelSabun: global.user.sabun,
|
|
site: global.currentUrl
|
|
})
|
|
|
|
global.hub.install().then(() => {
|
|
// 허브설정
|
|
HubEvent.start(global.talkParams({
|
|
type: 'START',
|
|
tabId: global.tabId
|
|
}))
|
|
});
|
|
}
|
|
|
|
talkEvent.connect().then(async () => {
|
|
global.hub.start();
|
|
// 톡방 재갱신
|
|
getTalkList(false).then(async () => {
|
|
// 톡방 메시지 재갱신
|
|
// getMessageAll(false)
|
|
getMoreMessageAll()
|
|
reConnectAttempts = 0;
|
|
console.log('global.init = true')
|
|
});
|
|
// 현재 탭 외 모든 탭 구독 해지
|
|
HubEvent.send(global.talkParams({
|
|
type: 'UNSUBSCRIBE',
|
|
tabId: global.tabId
|
|
}))
|
|
// 개인 사번 소켓 연결
|
|
try{global.subscribeList[global.user.sabun] = talkEvent.userSubscribe();}catch(e){}
|
|
// 업무별 소켓 연결
|
|
try{global.subscribeList[global.work.workId] = talkEvent.workSubscribe();}catch(e){}
|
|
|
|
global.init = true;
|
|
});
|
|
|
|
global.currentServer = data.server;
|
|
console.log('reConnectAttempts', reConnectAttempts)
|
|
},
|
|
// 오류 보수
|
|
// (추후 사용자 장애시 해당 기능 추가)
|
|
// 서비스워커 제거, 소켓 제거 후 재시작
|
|
repair: () => {
|
|
talkEvent.allUnsubscribe();
|
|
window.location.href = window.location.href;
|
|
},
|
|
// 개인 사번 구독
|
|
userSubscribe: () => {
|
|
return global.stomp.subscribe(`/exchange/user.exchange/user.${global.user.sabun}`, async function (content) {
|
|
const payload = JSON.parse(content.body);
|
|
if(payload.type === 'DEAD_MESSAGE') {
|
|
global.shadowRoot.querySelector('.socket-error').classList.remove('cus-hide')
|
|
} else {
|
|
console.log('userSubscribe', payload)
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.send(payload)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
}
|
|
|
|
});
|
|
},
|
|
// 업무 구독
|
|
workSubscribe: () => {
|
|
return global.stomp.subscribe(`/exchange/work.exchange/work.${global.work.workId}`, async function (content) {
|
|
const payload = JSON.parse(content.body);
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.work(payload)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
});
|
|
},
|
|
// 파일 구독
|
|
fileSubscribe: (payload) => {
|
|
global.fileSubscribeList[payload.talkId] = global.stomp.subscribe(`/exchange/file.exchange/file.${payload.talkId}`, async function (content) {
|
|
const payload = JSON.parse(content.body);
|
|
console.log('file subscribe', payload)
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.fileSend(payload)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
})
|
|
},
|
|
//톡방 구독
|
|
subscribe: (talkId) => {
|
|
return global.stomp.subscribe(`/exchange/talk.exchange/room.${talkId}`, async function (content) {
|
|
const payload = JSON.parse(content.body);
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.send(payload)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
});
|
|
},
|
|
// 구독 해지
|
|
unsubscribe: (talkId) => {
|
|
try {
|
|
global.subscribeList[talkId].unsubscribe()
|
|
} catch (e) {
|
|
}
|
|
delete global.subscribeList[talkId];
|
|
// global.subscribeList[talkId] = null;
|
|
},
|
|
// 전체 구독 해지 (구독과 관련된 모든 데이터 초기화)
|
|
allUnsubscribe: () => {
|
|
Object.keys(global.subscribeList).forEach((key) => {
|
|
try {
|
|
global.subscribeList[key].unsubscribe();
|
|
} catch (e) {
|
|
}
|
|
})
|
|
try {
|
|
global.subscribeList = [];
|
|
if(global.stomp && global.stomp.connected) {
|
|
global.stomp.disconnect(function() {
|
|
try {global.sockJS.close();} catch(e) {}
|
|
console.log('stomp 연결 해지 완료', global.stomp , global.sockJS)
|
|
global.stomp = null;
|
|
global.sockJS = null;
|
|
})
|
|
} else if(global.sockJS && global.sockJS.readyState === 1) {
|
|
try {global.sockJS.close();} catch(e) {}
|
|
console.log('sockjs 연결 해지 완료', global.stomp , global.sockJS)
|
|
global.sockJS = null;
|
|
}
|
|
|
|
} catch (e) {
|
|
console.log('allUnsubscribe error ', e)
|
|
}
|
|
|
|
},
|
|
// 톡 시작
|
|
start: (msgObj) => {
|
|
global.stomp.send(`/pub/talk.start.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
},
|
|
// 톡 메시지 전송
|
|
send: async (msgObj) => {
|
|
if (Common.isMaster()) {
|
|
global.stomp.send(`/pub/talk.message.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
} else {
|
|
msgObj.type = `SEND_${msgObj.type}`
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.send(msgObj)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
}
|
|
},
|
|
// 톡 종료
|
|
close: (msgObj) => {
|
|
global.stomp.send(`/pub/talk.close.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
},
|
|
// 톡 첩부파일 전송
|
|
attach: async (msgObj) => {
|
|
if (Common.isMaster()) {
|
|
global.stomp.send(`/pub/talk.attach.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
} else {
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.fileSend(msgObj)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
}
|
|
},
|
|
// 톡 생성
|
|
join: async (msgObj) => {
|
|
if (Common.isMaster()) {
|
|
global.stomp.send(`/pub/talk.enter.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
} else {
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.send(msgObj)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
}
|
|
},
|
|
// 톡 떠나기
|
|
leave: async (msgObj) => {
|
|
if (Common.isMaster()) {
|
|
global.stomp.send(`/pub/talk.leave.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
} else {
|
|
let sendFlag = false;
|
|
while (!sendFlag) {
|
|
if (global.serviceWorkerConnect) {
|
|
HubEvent.send(msgObj)
|
|
sendFlag = true;
|
|
} else {
|
|
global.registration.active.postMessage({"type": "WAKEUP"})
|
|
}
|
|
await Common.sleep(100)
|
|
}
|
|
global.serviceWorkerConnect = false;
|
|
}
|
|
},
|
|
// 시스템 변경
|
|
change: (msgObj) => {
|
|
/*유지보수 여러탭 구현 필요없음*/
|
|
global.stomp.send(`/pub/talk.change.${msgObj.talkId}`, {}, JSON.stringify(msgObj))
|
|
},
|
|
// 톡 아이디 생성
|
|
generateUUID: () => {
|
|
let d = new Date();
|
|
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
|
|
d + performance.now();
|
|
}
|
|
|
|
const uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxxxxxxyxxxxxxxxxy'.replace(/[xy]/g, function (c) {
|
|
const r = (d + Math.random() * 16) % 16 | 0;
|
|
d = Math.floor(d / 16);
|
|
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
|
})
|
|
return uuid;
|
|
},
|
|
// 탭 아이디 생성
|
|
generateTabUUID: () => {
|
|
let d = new Date();
|
|
if (typeof performance !== 'undefined' && typeof performance.now === 'function') {
|
|
d + performance.now();
|
|
}
|
|
|
|
const uuid = 'xxxxxxxxxxxx4xxxyxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
const r = (d + Math.random() * 16) % 16 | 0;
|
|
d = Math.floor(d / 16);
|
|
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16);
|
|
})
|
|
return uuid;
|
|
},
|
|
/* 톡방 안에 담당자 및 업무명 변경*/
|
|
talkHeaderChange: (workNm, name) => {
|
|
const chatHeader = global.shadowRoot.querySelector('.chat-content-header');
|
|
if (workNm) {
|
|
chatHeader.querySelector('#work-nm').innerText = workNm
|
|
}
|
|
if (name) {
|
|
const names = name.split(',')
|
|
if (names.length === 1) {
|
|
chatHeader.querySelector('#work-sm-nm').classList.remove('cus-tooltip')
|
|
chatHeader.querySelector('#work-sm-nm').classList.remove('chat-inner-tooltip')
|
|
chatHeader.querySelector('#work-sm-nm').setAttribute("data-tooltip", '')
|
|
chatHeader.querySelector('#work-sm-nm').innerText = name;
|
|
} else {
|
|
chatHeader.querySelector('#work-sm-nm').classList.add('cus-tooltip')
|
|
chatHeader.querySelector('#work-sm-nm').classList.add('chat-inner-tooltip')
|
|
chatHeader.querySelector('#work-sm-nm').setAttribute("data-tooltip", name)
|
|
chatHeader.querySelector('#work-sm-nm').innerText = `${names[0]}외 ${names.length - 1}명`;
|
|
}
|
|
}
|
|
},
|
|
// 톡 내용 활성화
|
|
messageShow: () => {
|
|
talkEvent.messageClean();
|
|
global.shadowRoot.querySelector('#chat-tab').click()
|
|
global.shadowRoot.querySelector('#chat-0').classList.add('active')
|
|
global.element.chatSidebar.style.left = '-100%'
|
|
},
|
|
// 톡방 삭제
|
|
talkRemove: (talkId) => {
|
|
//톡방 삭제후 배지 카운트 재정의
|
|
global.talkData.forEach((talk, idx) => {
|
|
if (talk.talkId === talkId) {
|
|
console.log('talkRemove :', idx, talk)
|
|
// delete global.talkData[talk];
|
|
global.talkData.splice(idx, 1)
|
|
}
|
|
})
|
|
|
|
console.log(global.talkData)
|
|
talkMapping(global.talkData)
|
|
|
|
talkEvent.badgeChange()
|
|
},
|
|
// 톡방 보관
|
|
talkMark: (talkId) => {
|
|
let isMarkYn = false;
|
|
global.talkData.forEach((chat, idx) => {
|
|
if (chat.talkId === talkId) {
|
|
chat.markYn = !chat.markYn;
|
|
isMarkYn = chat.markYn;
|
|
if (chat.markYn) {
|
|
global.talkData.splice(idx, 1)
|
|
global.talkData = [chat, ...global.talkData]
|
|
}
|
|
}
|
|
})
|
|
|
|
if (!isMarkYn) {
|
|
global.talkData.sort((a, b) => {
|
|
if (!b.markYn) {
|
|
if (a.insDate > b.insDate) {
|
|
return -1
|
|
} else if (a.insDate < b.insDate) {
|
|
return 1
|
|
}
|
|
}
|
|
})
|
|
}
|
|
talkMapping(global.talkData)
|
|
},
|
|
// 톡방 정렬
|
|
talkSort: () => {
|
|
global.talkData.sort((a, b) => {
|
|
if (a.markYn) {
|
|
return -1;
|
|
} else {
|
|
if (a.lastMessageDate >= b.lastMessageDate) {
|
|
return -1;
|
|
} else if (a.lastMessageDate < b.lastMessageDate) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
})
|
|
},
|
|
// 톡방 현재 스크롤 위치
|
|
messageScrollOriginalPositionMove: () => {
|
|
const contentBody = global.shadowRoot.querySelector('.chat-content-body');
|
|
const _contentScroll = contentBody.querySelector('.simplebar-content-wrapper')
|
|
_contentScroll.scrollTop = _contentScroll.scrollHeight - global.oldScrollPosition
|
|
},
|
|
// 스크롤 위치 가 변경 되었을시 메시지 미리보기
|
|
preMessageShow: (text) => {
|
|
const preMsg = global.shadowRoot.querySelector('.message-preview');
|
|
const msg = preMsg.querySelector('.msg');
|
|
msg.innerText = text;
|
|
|
|
preMsg.classList.remove('cus-hide');
|
|
},
|
|
// 메시지 삭제
|
|
messageClean: () => {
|
|
// 초기화 해야할 데이터
|
|
global.currDay = '0';
|
|
global.yourOldDate = '';
|
|
global.mineOldDate = '';
|
|
|
|
const chatContent = global.shadowRoot.querySelector('#chat-content');
|
|
const content = chatContent.querySelector('.simplebar-content');
|
|
m.render(content, []);
|
|
content.innerHTML = '';
|
|
global.element.chatEditor.innerHTML = '';
|
|
},
|
|
// 메인 뱃지 카운트 초기화
|
|
badgeChange: () => {
|
|
const badgeUnCount = global.talkData.reduce((a, b) => {
|
|
return Number(a) + Number(b.unReadCnt)
|
|
}, 0);
|
|
const chatBadge = global.shadowRoot.querySelector('.unread.badge');
|
|
if (badgeUnCount !== parseInt(0)) {
|
|
chatBadge.classList.remove('cus-hide');
|
|
} else {
|
|
chatBadge.classList.add('cus-hide');
|
|
}
|
|
chatBadge.innerText = badgeUnCount;
|
|
},
|
|
/*채팅룸 읾음 표시로 변경*/
|
|
readMessage: (talkId) => {
|
|
console.log('readmessage', talkId)
|
|
global.shadowRoot.querySelector(`div[data-talk-id="${talkId}"]`).classList.remove('unread-message')
|
|
const room = global.shadowRoot.querySelector(`div[data-talk-id="${talkId}"]`);
|
|
const badge = room.querySelector('.chat-list-badge')
|
|
const cacheTalk = global.talkData.filter((talk) => talk.talkId === talkId)[0];
|
|
try {
|
|
cacheTalk.unReadCnt = 0;
|
|
talkEvent.badgeChange();
|
|
badge.remove()
|
|
} catch (e) {/*badge 텍스트가 없을시 예외 처리*/
|
|
}
|
|
},
|
|
/*채팅방 타이핑에 따른 progress 호출*/
|
|
messageTyped: (msg) => {
|
|
|
|
let html = ''
|
|
|
|
html = `
|
|
<div class="d-flex p-1 your-dot-progress cus-show">
|
|
<div class="avatar avatar-l me-2">
|
|
<!--<img class="rounded-circle" src="../assets/img/team/5.jpg" alt="">-->
|
|
<div class="rounded-circle chat-avatar">
|
|
${msg.insName}
|
|
</div>
|
|
</div>
|
|
<div class="flex-1">
|
|
<div class="w-100">
|
|
<div class="stage your">
|
|
<div class="dot-typing"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`
|
|
const chatContent = global.shadowRoot.querySelector('#chat-content');
|
|
const content = chatContent.querySelector('.simplebar-content');
|
|
if(!content.querySelector('.your-dot-progress')) {
|
|
content.insertAdjacentHTML('beforeend', html)
|
|
}
|
|
},
|
|
|
|
/*채팅방 타이핑을 하지 않을시 progress 제거*/
|
|
messageUnTyped: (msg) => {
|
|
const chatContent = global.shadowRoot.querySelector('#chat-content');
|
|
const content = chatContent.querySelector('.simplebar-content');
|
|
|
|
const dotProgress = content.querySelector('.your-dot-progress')
|
|
if (dotProgress !== null) dotProgress.remove();
|
|
},
|
|
/*채팅리스트 메인 글 변경 */
|
|
talkTitleChange: (talkId, sabun) => {
|
|
const cacheTalk = global.talkData.filter((talk) => talk.talkId === talkId)[0];
|
|
cacheTalk.talkMembers = cacheTalk.talkMembers.filter((member) => (member.sabun === 'info' || member.sabun === global.user.sabun || member.sabun === sabun))
|
|
talkMapping(global.talkData)
|
|
}
|
|
}
|
|
|
|
export {talkEvent} |