EUNBI N.

MetaHub program

[ SI 프로젝트 ] 콜센터 실시간대응 프로그램

Description

  • IPCC 실시간 대용량서버통신 개선 위해 코드퀄리티 UP
  • 상담사/관리자 권한 및 웹/모바일 환경에 따른 라우터 화면 이동방식 구현
Image1 meta_1Image2 meta_2

#1. 모바일 로그인 / 권한관리

Code

/** 로그인 처리 **/
const _loginHandler = async () => {
  const userId = <string>username.value
  const userPs = <string>password.value
  try {

    const tmp = userId.split('@');
    if (tmp.length < 2 || tmp[1] === "") {
      await modalStore.show('Alert','프로젝트 코드를 입력해주세요.<br/>예) 사용자ID@프로젝트코드')
      return
    }

    // 로그인 요청
    const res = await authStore.login(userId, userPs, useSoft.value)
    const result = res.code
    if (result === 'OK') {
      // 로그인 성공
      if (useSoft.value) {
        const connected = await softphoneStore.open()
        if (connected) {
          softphoneStore.emit('login', {
            userid: userId.split('@')[0],
            mode: 'Outbound',
          })
        } else {
          await modalStore.show('Alert','연결에 실패하였습니다.<br/>잠시 후 다시 시도해주세요.',)
        }
      } else {
        await _loginCallback()
      }
    } else if (result === 'PWD_LOCK') {
      // 비밀번호 5회 불일치 잠금
      await modalStore.show('Alert',`비밀번호 입력 오류로 인해<br/><span style="color: red;">로그인이 5회 실패하였습니다.</span><br/>회원님의 정보 보호를 위해<br/>5분간 접속 차단이 됩니다.`,)
    } else if (result === 'NOTFOUND') {
      // 계정 없음
      await modalStore.show('Alert', '계정을 찾을 수 없습니다.')
    } else if (result === 'DUPLICATE') {
      // 중복 로그인
      await modalStore.show('Alert', '중복로그인 입니다.')
    } else if (result === 'WRONG') {
      // 비밀번호 불일치
      const checkData = res.data.value.split('_')
      const count = checkData[0]
      const total = checkData[1]
      await modalStore.show('Alert', `비밀번호가 일치하지 않습니다.<br/><span style="color: red;">로그인이 ${count}회 실패하였습니다.</span><br/>비밀번호 ${total}회 오류시 5분간 접속이 차단됩니다`)
    } else if (result === 'PWDCHG') {
      // 비밀번호 변경 90일 경과
      popupTitleMessage.value = '비밀번호 변경 안내'
      await modalStore.show('Alert',`비밀번호 변경 후 <span style="color:red">90일이 경과</span>하였습니다.<br>비밀번호를 변경하세요.`)
      _showChangePw(true)
    } else if (result === 'PWDINIT') {
      // 초기 비밀번호 popup
      popupTitleMessage.value = '초기 비밀번호 변경'
      _showChangePw(true)
    } else {
      await modalStore.show('Alert', '처리 중 오류가 발생하였습니다.')
    }
  } catch (error) {
    await modalStore.show('Alert', '처리 중 오류가 발생하였습니다.')
    return error
  }
}


Image3 meta_3Image4 meta_4Image5 meta_5

#2. 실시간 대시보드/ 사이트별 통계

Code

/** @function 대시보드데이터조회 */
const _srchDashBoard = async () => {
  //조회기준: 현재날짜-현재날짜
  const cdate = stringUtil.formatDateStr(params.value.cdate)

  //실시간모니터링(대시보드) 조회
  const dashRslt = await dashBoardStore.getRealTime(cdate)

  if(dashRslt.code === 'OK'){
    totData.value = {...dashRslt.data}
  }
  //미처리건수조회
  const alrtRslt1 = await dashBoardStore.getAlertList('00', cdate) //미열람개수 알림리스트
  if(alrtRslt1.code === 'OK'){
    totData.value.unPrcsCnt = alrtRslt1.list.length //미처리건수
  }

  _setData(totData.value) 
  
}

Image6 meta_6Image7 meta_7

#3. 업무이관/상세조회/처리하기

Code

/** @function 상세조회 */
const _onSelected = async (array: any) => {
  detail.value.siteCd = array.siteCd
  detail.value.trId = array.trId

  //업무이관상세조회(A_TRANS_002)
  const rslt = await transStore.info(params.value.projCd, detail.value.siteCd, detail.value.trId)
  if(rslt === null) return
    detail.value = rslt.info
    historyReq.value = _.cloneDeep(rslt.info) //처리이력
    detail.value.phone = stringUtil.formatPhone(detail.value.phone)
    
    prcsInfo.value.length = rslt.processInfo.length
    rslt.processInfo.forEach((r:any, i:number)=> {
      prcsInfo.value[rslt.processInfo.length-1-i] = r //순서 오름차순 정렬
    })
    await _getAuthUser('res', rslt.info.resTeamCd) // 처리정보 담당팀에 따른 담당자 목록 바인딩
    
    files.value = rslt.fileInfo //파일정보(SavesAll)
    fileInfo.value = files.value //파일정보(Ref)
    //파일업로드 용량 카운트
    for (const file of fileInfo.value) {
      file.size = parseInt(file.fileSize)
      fileSizes.value += file.size || 0
    }

    _setMaskYn(detail)
    if(detail.value.trGb){
      //공통코드조회(A_CMMNCD_003)
      const rslt2 = await codeStore.fetchCodesList(detail.value.trGb, '') //이관구분
      if (rslt2.code === 'OK') {
        cmCdDTrType.value = rslt2.list
      }
    }
    //티켓정보조회(A_TICKET_004)
    if(!!detail.value.callSeq){
      ticketInfoYn.value = true
      const rslt3 = await ticketStore.fetchTicketHistory({
        gb: '01',
        projCd: detail.value.projCd,
        siteCd: detail.value.siteCd,
        callSeq: detail.value.callSeq,
        custId: detail.value.custId,
        sdate: params.value.sdateStr,
        edate: params.value.edateStr,
      })
    }
    _getCounsArr(detail.value.siteCd) //티켓유형조회

    _init()

    //라우터이동박식으로 직접접근시 params_detail={}조작을 방지, 접근제한 체크(처리자=본인)
    noAuthAccess.value = userStore.user.userId !== array.resUserId 
}

Image10 meta_10

#4. 설문조사 - 카카오인앱연동

Code


/** 단답형질문에 대한 선택지 선택 */
const fnSelect = (item: any, index: number, aIndex?:number) => {
  //해당질문이 하위섹션유형이 아니고 && 객관식단답형이면
  if (item.sectionYn == 'N' && item.answType == '01' && aIndex !== undefined){
    // 1. 이전에 답변 체크한 값에 따른 하위섹션이 있었는지 체크 (추가된 목록 제거)
    const { aNo } = item
    if (aNo != 0 && item.list[aNo-1].sectionValue != ''){
      const findSubQue = mainQuests.value.find((x:any) => x.qNo === item.list[aNo-1].sectionValue )
      if (findSubQue) {
        mainQuests.value.splice(index, 1)
        --page.value
      }
    }
    // 2. 선택한 해당답변이 연결된 하위섹션이동이 있으면 추가
    if(item.list[aIndex].sectionValue != ''){
      const findSubQue = subQuests.value.find((x:any) => x.qNo === item.list[aIndex].sectionValue )
      if (findSubQue) {
        //순차적 다음질문 이전에 하위섹션먼저 추가
        mainQuests.value.splice(index, 0, findSubQue)
        ++page.value
      }
    } 
  }

  //다음 문항으로
  fnNext(index)
}

/** 설문종료 */
const closeSubmit = () => {
  if(isMobile()){
    const userAgent = window.navigator.userAgent.toLocaleLowerCase()
    // kakaoTalk 인앱 브라우저에서 설문조사 띄웠을경우
    if (userAgent.indexOf("kakaotalk") > -1) {
      // IOS vs Android 에 따른 종료 명령 
      window.location.href = (/iPad|iPhone|iPod/.test(userAgent)) ? "kakaoweb://closeBrowser" : "kakaotalk://inappbrowser/close";
    }
  } else {
    // 웹에서 띄웠을 경우 
    window.open("about:blank","_self")?.close()
  }
}

All rights reserved.