This commit is contained in:
2025-07-02 21:55:07 +09:00
commit fa63330e69
855 changed files with 432271 additions and 0 deletions

View File

@@ -0,0 +1,762 @@
import m from 'http://devtalk.kospo.co.kr:3000/static/bundle/mithril-2.2.2/mithril.js'
import {global} from "http://devtalk.kospo.co.kr:3000/static/js/module/variable.js";
import {talkEvent} from "http://devtalk.kospo.co.kr:3000/static/js/module/talkEvent.js";
import {talkMapping, messageMapping} from "http://devtalk.kospo.co.kr:3000/static/js/module/render.js"
import {Tab} from "http://devtalk.kospo.co.kr:3000/static/bundle/bootstrap-5.1.3/js/bootstrap.esm.js";
import Common from "http://devtalk.kospo.co.kr:3000/static/js/utils.js";
import {HubEvent} from "http://devtalk.kospo.co.kr:3000/static/js/module/hubEvent.js";
import {showNotification} from "http://devtalk.kospo.co.kr:3000/static/js/notification.js";
import receiver from "http://devtalk.kospo.co.kr:3000/static/js/module/receiver.js";
// api 관리
let isQuestion = true;
const talkInit = () => {
work().then(() => {
manual().then(() => {
question()
})
docManual()
videoManual()
})
}
// 현재 사용자 정보
const getUser = async () => {
global.user = await global.request({
url: `/api/user/info/client`,
method: 'get',
withCredentials: true
})
}
// itsm 만족도 조사 저장
const setITSMSatis = (talkId, reqId, rating, content) => {
global.request({
url: `/api/ict/satis`,
method: 'post',
body: {talk_id : talkId, req_id : reqId, h_point: rating, opinion: content},
withCredentials: true
})
}
// scm 만족도 조사 저장
const setSCMSatis = (talkId, reqId, rating, content) => {
global.request({
url: `/api/scm/satis`,
method: 'post',
body: {talk_id : talkId, req_id : reqId, h_point: rating, opinion: content},
withCredentials: true
})
}
// 접속 중인 시스템 정보
const work = async () => {
global.work = await global.request({
url: `/api/work`,
method: 'get',
params: {workId: global.currentWorkId},
withCredentials: true
})
global.shadowRoot.querySelector('#intro-work').innerText = global.work.workNm;
global.shadowRoot.querySelector('#intro-online').classList.add(global.work.onlineYn ? 'online' : 'offline');
global.shadowRoot.querySelector('#intro-user').innerText = global.user.name;
receiver.changeLoginInfo(global.work)
}
// 접속 중인 시스템의 매뉴얼
const manual = () => {
// 현재 업무의 메뉴얼 & 비디오 메뉴얼 호출
return new Promise((resolve, reject) => {
global.request({
method: 'get',
url: `/api/manual/intro`,
params: {workId: global.work.workId},
withCredentials: true
}).then((images) => {
const manualSlide = global.shadowRoot.querySelector('#manual-play');
const vNode = []
if(images.length === 0) {
const parent = Common.findParentElement(manualSlide, 'mt-4')
parent.remove()
isQuestion = false;
} else {
images.forEach((i, idx) => {
if (i.onm.includes("mp4")) {
vNode.push(
m('div', {class: `carousel-item ${idx === 0 ? 'active' : ''}`}, [
m('video', {
controls: false,
class: 'd-block w-100 intro-video',
muted: true,
preload: 'auto',
autoplay: false
}, [
m('source', {
src: `${global.apiUrl}/api/manual/view/video?id=${i.id}&type=S`,
type: "video/mp4"
})
]),
m('div', {class: 'video-control'}, [
m('div', {class:'video-fullscreen cus-hide', 'data-ori-src': `${global.apiUrl}/api/manual/view/video?id=${i.id}&type=O`}, [
m('i', {class: 'bi-fullscreen bi-color-white'})
])
])
])
)
} else {
vNode.push(
m('div', {class: `carousel-item ${idx === 0 ? 'active' : ''}`}, [
m('img', {
src: `${global.apiUrl}/api/manual/view/image?workId=${global.work.workId}&vnm=${i.vnm}&sabun=${global.user.sabun}`,
class: 'd-block w-100',
alt: 'img1'
})
])
)
}
})
m.render(manualSlide.querySelector('.carousel-inner'), vNode);
/* 숏츠 비디오 이벤트 정의 */
global.shadowRoot.querySelectorAll('.video-control').forEach((target) => {
target.addEventListener('mouseenter', () => {
target.querySelector('.video-fullscreen').classList.remove('cus-hide')
target.querySelector('.video-fullscreen').classList.add('cus-show')
})
target.addEventListener('mouseleave', () => {
target.querySelector('.video-fullscreen').classList.remove('cus-show')
target.querySelector('.video-fullscreen').classList.add('cus-hide')
})
})
global.shadowRoot.querySelectorAll('.video-fullscreen').forEach((target) => {
target.addEventListener('click', () => {
const oriSrc = target.dataset.oriSrc
console.log(oriSrc)
const fullvideo = global.shadowRoot.querySelector('#fullscreen-container');
fullvideo.classList.remove('cus-hide')
fullvideo.classList.add('cus-show');
const video = m('video', {preload: 'none', controls: 'controls', id: 'fullvideo', style: 'width:100%; height:100%;'}, [
m('source', {src: oriSrc, type: 'video/mp4'})
])
m.render(fullvideo, video);
const playVideo = global.shadowRoot.querySelector('#fullvideo');
playVideo.requestFullscreen();
playVideo.play();
window.onresize = () => {
if(window.matchMedia('(display-mode: fullscreen)').matches || window.document.fullscreenElement) {
console.log(true)
} else {
closeFullscreen();
console.log(false);
}
}
})
})
}
resolve();
})
})
}
const closeFullscreen = () => {
const playVideo = global.shadowRoot.querySelector('#fullvideo');
if(playVideo) {
const fullvideo = global.shadowRoot.querySelector('#fullscreen-container');
m.render(fullvideo, []);
fullvideo.classList.remove('cus-show')
fullvideo.classList.add('cus-hide')
}
}
// 접속 중인 시스템의 자주 하는 질문
const question = () => {
const questionCnt = isQuestion ? 5 : 6;
/*현재 업무의 자주하는 질문 설정 */
global.request({
method: 'get',
url: `/api/question/${global.work.workId}`,
withCredentials: true
}).then((question) => {
const questionContent = global.shadowRoot.querySelector('#question');
const question_page = Math.ceil(question.length / questionCnt)
let question_div = null
let paging = 0;
question.forEach((a, idx) => {
if(idx % questionCnt === 0) {
paging++;
question_div = document.createElement('div')
question_div.setAttribute("id", `question-pg-${paging}`)
question_div.classList.add('question-pg-container')
if(paging !== 1) {
question_div.classList.add('cus-hide')
} else {
question_div.classList.add('cus-show')
}
}
const questionP = document.createElement("p");
questionP.classList.add('cursor-pointer', 'question')
const questionText = document.createTextNode(`${a.content}`)
questionP.appendChild(questionText)
question_div.append(questionP);
questionP.addEventListener('click', () => {
const talkId = talkEvent.generateUUID();
// 키보드 숨김 해제
global.element.chatEditorArea.classList.remove('cus-hide');
// 채팅 구독 메시지 보내기
localStorage.setItem(global.tabId, talkId)
// 발 생성자 주입
global.chatCreator = global.tabId;
talkEvent.join(global.talkParams({
type: 'JOIN',
message: a.content,
talkId: talkId,
workId: global.work.workId,
introOwner: 'mine'
}))
talkEvent.messageShow()
})
if(idx % questionCnt === questionCnt-1 || idx === question.length-1) {
questionContent.append(question_div)
}
})
const pagination = document.createElement('div');
pagination.classList.add('fx', 'fx-gap')
pagination.setAttribute("id", 'question_pg')
for(var i=0; i< question_page; i++) {
const pagination_btn = document.createElement('div')
if(i === 0) {
pagination_btn.classList.add('btn', 'active')
pagination_btn.dataset.pg = i
} else {
pagination_btn.classList.add('btn')
pagination_btn.dataset.pg = i
}
pagination.append(pagination_btn)
}
questionContent.append(pagination)
let current_page = 0
function switchToNext(evt) {
const {target} =evt;
if(!target.classList.contains('btn')) {
return;
}
const clickedBtn = target;
if(clickedBtn.classList.contains('active')) {
return;
}
const activeBtn = pagination.getElementsByClassName('active')[0]
activeBtn?.classList.remove("active")
clickedBtn.classList.add('active')
global.shadowRoot.querySelectorAll(".question-pg-container").forEach((el) => {
el.classList.add('cus-hide')
el.classList.remove('cus-show')
});
const active = global.shadowRoot.querySelector(`#question-pg-${Number(clickedBtn.dataset.pg) + 1}`)
active.classList.remove('cus-hide')
active.classList.add('cus-show')
current_page = Number(clickedBtn.dataset.pg) + 1;
}
pagination.addEventListener('click', switchToNext)
/*자주찾는 질문이 2페이지 이상일때만 실행*/
if(question_page > 1) {
setInterval(autoNext, 10000)
function autoNext() {
let movePage = Number(current_page) + 1
if(question_page < movePage) movePage = 1;
global.shadowRoot.querySelectorAll(".question-pg-container").forEach((el) => {
el.classList.add('cus-hide')
el.classList.remove('cus-show')
});
const active = global.shadowRoot.querySelector(`#question-pg-${movePage}`);
active.classList.remove('cus-hide')
active.classList.add('cus-show')
current_page = movePage;
}
}
if(!isQuestion) {
const question = global.shadowRoot.querySelector('#question');
const questionPg = global.shadowRoot.querySelector('.question-pg-container');
question.style.minHeight = '286px';
questionPg.style.minHeight = '230px';
}
})
}
// 접속 중인 시스템의 문서 매뉴얼
const docManual = () => {
/*본인 메뉴얼*/
global.request({
method: 'get',
url: `/api/manual`,
params: {workId: global.work.workId, type: '0000'},
withCredentials: true
}).then((manuals) => {
const manualVNode = [];
manuals.map((ma) => {
manualVNode.push(
m('div', {class: "d-flex justify-content-start manual-content"}, [
m('div', {class: "p-2 text-ellipsis", style: "width:60%;cursor: help;", title:ma.onm}, `${ma.onm}`),
m('div', {class: "p-2", style: "width:20%;"}, `${ma.version}`),
m('a', {
href: `${global.apiUrl}/api/manual/download/doc?workId=${ma.workId}&vnm=${ma.vnm}`,
target: '_download_',
rel: 'noopener',
style: 'padding-top:6px;'
}, [
m('i', {
class: "bi bi-download text-black",
style: "padding-right:10px; font-size:1.0rem; cursor:pointer;"
})
])
])
)
})
const manualBody = global.shadowRoot.querySelector('#manual-doc-body');
const content = manualBody.querySelector('.simplebar-content');
if(manualVNode.length > 0) m.render(content, manualVNode)
})
}
// 접속 중인 시스템의 동영상 매뉴얼
const videoManual = () => {
global.request({
method: 'get',
url: `/api/manual/video`,
params: {workId: global.work.workId},
withCredentials: true
}).then((manuals) => {
const manualVNode = [];
manuals.map((ma) => {
manualVNode.push(
m('div', {class: "d-flex justify-content-evenly manual-content"}, [
m('div', {class: "p-2 text-ellipsis", style: "width:70%;"}, `${ma.onm}`),
// m('div', {class: "p-2", style: "font-size:13px; width:20%;"}, `${ma.version}`),
m('button', {
class: 'btn btn-sm btn-play manual-play-btn p-0',
'data-id': ma.id,
}, '재생')
])
)
})
const manualBody = global.shadowRoot.querySelector('#manual-video-body');
const content = manualBody.querySelector('.simplebar-content');
if(manualVNode.length > 0) m.render(content, manualVNode)
// videoManualPlayEvent();
})
console.log('work init end')
}
// 생성된 톡방 목록 추가
const setChatList = function (chat) {
console.log('setChatList before', global.talkData, chat)
global.talkData.unshift(chat)
console.log('setChatList after', global.talkData)
// 채팅 목록 생성
talkMapping(global.talkData);
// 채팅 목록 구독
if (Common.isMaster()) {
chatConnect([chat]);
}
// 채팅 부트스트랩 이벤트 수동 연결
chatBootstrapEvent();
talkEvent.badgeChange()
}
// 현사용자의 톡방 목록
const getTalkList = function (reset) {
return new Promise((resolve, reject) => {
global.request({
url: `/api/talk`,
method: 'get',
withCredentials: true
}).then((lists) => {
if (reset) {
global.talkData = lists;
getTalkListEvent()
resolve(global.talkData.length === 0 ? true : false)
} else {
lists.forEach(list => {
if (!global.talkData.map(talk => talk.talkId).join(',').includes(list.talkId)) {
global.talkData.push(list)
}
})
getTalkListEvent()
resolve(global.talkData.length === 0 ? true : false)
}
}).catch(function (error) {
console.log(error)
reject()
})
})
}
// 톡방 이벤트 정의 소켓 연결 및 동적으로 생성된 DOM 이벤트 재설정
const getTalkListEvent = () => {
// 채팅 목록 생성
talkMapping(global.talkData);
// 마스터만 채팅 목록 구독
if (Common.isMaster()) {
chatConnect(global.talkData);
}
// 채팅 부트스트랩 이벤트 수동 연결
chatBootstrapEvent();
talkEvent.badgeChange()
}
const getApInfo = () => {
return new Promise((resolve, reject) => {
global.request({
url: `/api/getApInfo`,
method: 'get',
withCredentials: true
}).then(data => {
console.log(data)
resolve(data);
}).catch(() => {
reject();
})
})
}
// 소켓 구독
const chatConnect = function (chats) {
for (const ch of chats) {
if (!ch.closeYn) {
if (!Object.keys(global.subscribeList).includes(ch.talkId)) {
global.subscribeList[ch.talkId] = talkEvent.subscribe(ch.talkId)
}
}
}
}
// 톡방 이벤트 정의
const chatBootstrapEvent = () => {
/*bootstrap 수동 이벤트 설정*/
global.shadowRoot.querySelectorAll('div[data-bs-toggle="tab"]').forEach((el) => {
if (!el.dataset.tabListener) {
const tabTrigger = new Tab(el);
el.addEventListener('click', function (e) {
e.preventDefault();
tabTrigger.show();
})
}
el.dataset.tabListener = true;
})
}
// 톡방 클릭시 해당 메시지
const getMessage = function (messageParams) {
global.request({
url: `/api/message/line`,
method: 'get',
params: messageParams,
withCredentials: true
}).then((dto) => {
const cacheTalk = global.talkData.filter((talk) => talk.talkId === messageParams.talkId)[0];
cacheTalk.messageParams = messageParams;
cacheTalk.talkMessages = dto;
});
}
/*
* 비동기 톡방 메시지 호출
* parameter
* reset : 초기 설정 일시 true 재연결시 false
* */
const getMessageAll = async function (reset) {
const dto = await global.request({
url: `/api/message/all`,
method: 'get',
withCredentials: true
});
if (reset) {
global.talkData.forEach((talk) => {
const cacheTalk = dto.filter((talkData) => talkData.talkId === talk.talkId)[0];
talk.talkMessages = cacheTalk.talkMessages;
})
} else {
let queue = []
global.talkData.forEach((talk) => {
try {
const lastMsg = talk.talkMessages.talks[talk.talkMessages.talks.length - 1]
const cacheTalk = dto.filter((talkData) => talkData.talkId === talk.talkId)[0];
const newMsg = cacheTalk.talkMessages.talks.filter((ct) => {
return Common.dateDifference(new Date(ct.insDate), new Date(lastMsg.insDate))
})
if (newMsg.length > 0) {
newMsg.forEach((msg) => {
msg.workNm = talk.work.workNm
})
talk.lastMessage = newMsg[newMsg.length - 1].message;
talk.lastMessageDate = newMsg[newMsg.length - 1].insDate;
// 톡방 접속중인 경우 메시지 맵핑
if (localStorage.getItem(global.tabId) === talk.talkId) {
messageMapping(talk.talkId, {talks: newMsg}, 'after', false)
// 브라우저 상태가 hidden 인 경우 알림에 추가
if (!document.hasFocus()) queue = [...queue, ...newMsg]
// 그외 메시지 재정의
} else {
talk.talkMessages.talks = [...newMsg, ...talk.talkMessages.talks]
talk.unReadCnt = talk.unReadCnt + newMsg.length;
queue = [...queue, ...newMsg]
}
}
} catch (e) {
console.log(`talk.talkId is null messages`)
}
})
console.log(queue)
// 추가된 큐가 존재 할시 톡방 저체 갱신
// 큐에 정의된 메시지를 알림
if (queue.length > 0) {
talkMapping(global.talkData);
talkEvent.badgeChange();
queue.forEach((que) => {
showNotification(que)
})
}
}
}
const getMoreMessageAll = async function () {
let insDate = '1999-01-01';
global.talkData.forEach(talk => {
if(insDate < talk.lastMessageDate) {
insDate = talk.lastMessageDate
}
})
const dtos = await global.request({
url: `/api/message/more/all`,
method: 'get',
params: {'insDate': insDate},
withCredentials: true
});
let queue = []
dtos.forEach((dto) => {
try {
const cacheTalk = global.talkData.filter((talk) => talk.talkId === dto.talkId)[0];
const newMsg = dto.talkMessages.talks;
console.log(newMsg)
if (newMsg.length > 0) {
newMsg.forEach((msg) => {
msg.workNm = cacheTalk.work.workNm
})
cacheTalk.lastMessage = newMsg[newMsg.length - 1].message;
cacheTalk.lastMessageDate = newMsg[newMsg.length - 1].insDate;
// 톡방 접속중인 경우 메시지 맵핑
if (localStorage.getItem(global.tabId) === cacheTalk.talkId) {
messageMapping(cacheTalk.talkId, {talks: newMsg}, 'after', false)
// 브라우저 상태가 hidden 인 경우 알림에 추가
if (!document.hasFocus()) queue = [...queue, ...newMsg]
// 그외 메시지 재정의
} else {
cacheTalk.talkMessages.talks = [...newMsg, ...cacheTalk.talkMessages.talks]
cacheTalk.unReadCnt = cacheTalk.unReadCnt + newMsg.length;
queue = [...queue, ...newMsg]
}
}
} catch (e) {
console.log(`talk.talkId is null messages`)
}
})
// 추가된 큐가 존재 할시 톡방 저체 갱신
// 큐에 정의된 메시지를 알림
if (queue.length > 0) {
talkMapping(global.talkData);
talkEvent.badgeChange();
queue.forEach((que) => {
showNotification(que)
})
}
}
// 톡방 내용 가져오기
const getMoreMessageLine = (talkId) => {
const cacheTalk = global.talkData.filter((talk) => talk.talkId === talkId)[0];
cacheTalk.messageParams['insDate'] = cacheTalk.talkMessages.talks[cacheTalk.talkMessages.talks.length - 1].insDate;
return new Promise((resolve, reject) => {
global.request({
url: `/api/message/line`,
method: 'get',
params: cacheTalk.messageParams,
withCredentials: true
}).then((dto) => {
if (dto.talks.length > 0) {
messageMapping(talkId, dto, 'before', false);
talkEvent.messageScrollOriginalPositionMove();
let result = '';
if (cacheTalk.talkMessages.talks.length >= dto.total) {
result = 'last';
} else {
result = 'success';
}
HubEvent.send(global.talkParams({
type: 'MORE_MESSAGE_LINE',
talkId: talkId,
tabId: global.tabId,
result: result,
talkMessages: dto
}))
resolve(result)
} else {
resolve('last');
}
}).catch(function (error) {
reject(error)
})
})
}
// 톡방내 메시지 검색
const getMessageSearch = (params) => {
global.request({
url: `/api/message/search`,
method: 'get',
params: {talkId: params.talkId, search: params.search},
withCredentials: true
}).then((lists) => {
params.callback(lists)
})
}
// 메시지 통합 검색
const getAllContentSearch = (params) => {
global.request({
url: `/api/message/search/all`,
method: 'get',
params: {search: params.search},
withCredentials: true,
}).then((lists) => {
params.callback(lists)
})
}
//매뉴얼 조회
const getManual = (params) => {
const sendParam = {type: params.type}
if(params.search !== '') sendParam['search'] = params.search
if(params.workId !== '') sendParam['workId'] = params.workId
global.request({
url: `/api/manual`,
method: 'get',
params: sendParam,
withCredentials: true
}).then((manuals) => {
params.callback(manuals)
})
}
//매뉴얼 조회
const getVideoManual = (params) => {
const sendParam = {type: params.type}
if(params.search !== '') sendParam['search'] = params.search
if(params.workId !== '') sendParam['workId'] = params.workId
global.request({
url: `/api/manual/video`,
method: 'get',
params: sendParam,
withCredentials: true
}).then((manuals) => {
params.callback(manuals)
})
}
// 톡방 삭제 (실제 삭제 여부만 갱신)
const deleteTalk = (params) => {
global.request({
url: `/api/talk/delete/${params.talkId}`,
method: 'put',
withCredentials: true
}).then((data) => {
params.callback(data)
})
}
// 톡방 읽음 표시
const setChatRead = (talkId) => {
console.log('read', talkId)
return new Promise((resolve, reject) => {
global.request({
url: `/api/message/read`,
method: 'post',
body: {talkId: talkId},
withCredentials: true
}).then((result) => {
resolve(result);
}).catch((err) => {
reject(err);
})
})
}
// 톡방 보관
const setTalkMark = (obj) => {
global.request({
url: `/api/talk/mark/${obj.talkId}`,
method: 'put',
withCredentials: true
}).then(() => {
obj.callback()
})
}
export {
talkInit,
getUser,
getApInfo,
getTalkList,
getTalkListEvent,
setChatList,
getMessage,
getMoreMessageLine,
getMessageSearch,
getAllContentSearch,
getManual,
getVideoManual,
setChatRead,
setTalkMark,
setITSMSatis,
setSCMSatis,
deleteTalk,
getMessageAll,
getMoreMessageAll
}