전화 관련 commit
This commit is contained in:
319
src/main/resources/mappers/crm/callLog/CallLogSql.xml
Normal file
319
src/main/resources/mappers/crm/callLog/CallLogSql.xml
Normal file
@@ -0,0 +1,319 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.madeu.crm.callLog.map.CallLogMAP">
|
||||
|
||||
<!-- 통화 로그 목록 건수 조회 -->
|
||||
<select id="getCallLogCnt" parameterType="com.madeu.crm.callLog.dto.CallLogSearchDTO" resultType="Integer">
|
||||
/** CallLogMAP.getCallLogCnt **/
|
||||
SELECT COUNT(*) AS TOTAL_COUNT
|
||||
FROM MU_CTI_LOG A
|
||||
WHERE A.USE_YN = 'Y'
|
||||
AND A.FULLDNIS = #{fulldnis}
|
||||
AND A.REG_DATE >= CONCAT(#{sDate}, ' 00:00:00')
|
||||
AND A.REG_DATE <= CONCAT(#{eDate}, ' 23:59:59')
|
||||
<if test="callType != null and callType != '' and callType != 'callback'">
|
||||
AND A.MENU_NO = #{callType}
|
||||
AND A.STATE_TYPE IN ('start', 'ringout')
|
||||
</if>
|
||||
<if test="callType == 'callback'">
|
||||
AND A.STATE_TYPE = 'callback'
|
||||
</if>
|
||||
<if test="callType == null or callType == ''">
|
||||
AND (A.STATE_TYPE = 'start' OR A.STATE_TYPE = 'ringout')
|
||||
</if>
|
||||
<if test="callType1 != null and callType1 != ''">
|
||||
AND A.C_TYPE1 = #{callType1}
|
||||
</if>
|
||||
<if test="callType2 != null and callType2 != ''">
|
||||
AND A.C_TYPE2 = #{callType2}
|
||||
</if>
|
||||
<if test="mCid != null and mCid != ''">
|
||||
AND A.CID LIKE CONCAT('%', #{mCid}, '%')
|
||||
</if>
|
||||
<if test="incallSel != null and incallSel != ''">
|
||||
AND A.INCALL_SEL LIKE CONCAT('%|=|', #{incallSel}, '|=|%')
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 통화 로그 통계 집계 -->
|
||||
<select id="getCallLogStats" parameterType="com.madeu.crm.callLog.dto.CallLogSearchDTO" resultType="com.madeu.crm.callLog.dto.CallLogStatsDTO">
|
||||
/** CallLogMAP.getCallLogStats **/
|
||||
SELECT COUNT(*) AS "totalCnt"
|
||||
,SUM(IF(A.BOUND = 'IN', 1, 0)) AS "inCnt"
|
||||
,SUM(IF(A.BOUND = 'OUT', 1, 0)) AS "outCnt"
|
||||
,SUM(IF(A.C_TYPE1 = '초진', 1, 0)) AS "type1Cnt"
|
||||
,SUM(IF(A.C_TYPE1 = '재진', 1, 0)) AS "type2Cnt"
|
||||
,SUM(IF(A.C_TYPE2 = '상담', 1, 0)) AS "type11Cnt"
|
||||
,SUM(IF(A.C_TYPE2 = '상담후예약', 1, 0)) AS "type12Cnt"
|
||||
,SUM(IF(A.C_TYPE2 = '회차예약', 1, 0)) AS "type13Cnt"
|
||||
FROM MU_CTI_LOG A
|
||||
WHERE A.USE_YN = 'Y'
|
||||
AND A.FULLDNIS = #{fulldnis}
|
||||
AND A.REG_DATE >= CONCAT(#{sDate}, ' 00:00:00')
|
||||
AND A.REG_DATE <= CONCAT(#{eDate}, ' 23:59:59')
|
||||
<if test="callType != null and callType != '' and callType != 'callback'">
|
||||
AND A.MENU_NO = #{callType}
|
||||
AND A.STATE_TYPE IN ('start', 'ringout')
|
||||
</if>
|
||||
<if test="callType == 'callback'">
|
||||
AND A.STATE_TYPE = 'callback'
|
||||
</if>
|
||||
<if test="callType == null or callType == ''">
|
||||
AND (A.STATE_TYPE = 'start' OR A.STATE_TYPE = 'ringout')
|
||||
</if>
|
||||
<if test="callType1 != null and callType1 != ''">
|
||||
AND A.C_TYPE1 = #{callType1}
|
||||
</if>
|
||||
<if test="callType2 != null and callType2 != ''">
|
||||
AND A.C_TYPE2 = #{callType2}
|
||||
</if>
|
||||
<if test="mCid != null and mCid != ''">
|
||||
AND A.CID LIKE CONCAT('%', #{mCid}, '%')
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 통화 연결 건수 (통계용) -->
|
||||
<select id="getCallLogLinkedStats" parameterType="com.madeu.crm.callLog.dto.CallLogSearchDTO" resultType="hashmap">
|
||||
/** CallLogMAP.getCallLogLinkedStats **/
|
||||
SELECT COUNT(*) AS "totalOkCnt"
|
||||
,SUM(IF(A.BOUND = 'IN', 1, 0)) AS "inOkCnt"
|
||||
,SUM(IF(A.BOUND = 'OUT', 1, 0)) AS "outOkCnt"
|
||||
FROM MU_CTI_LOG A
|
||||
WHERE A.USE_YN = 'Y'
|
||||
AND A.FULLDNIS = #{fulldnis}
|
||||
AND A.REG_DATE >= CONCAT(#{sDate}, ' 00:00:00')
|
||||
AND A.REG_DATE <= CONCAT(#{eDate}, ' 23:59:59')
|
||||
AND A.STATE_TYPE = 'link'
|
||||
</select>
|
||||
|
||||
<!-- 통화 로그 목록 조회 -->
|
||||
<select id="getCallLogList" parameterType="com.madeu.crm.callLog.dto.CallLogSearchDTO" resultType="com.madeu.crm.callLog.dto.CallLogDTO">
|
||||
/** CallLogMAP.getCallLogList **/
|
||||
SELECT L.*
|
||||
FROM (
|
||||
SELECT L.*
|
||||
,CAST(@RNUM:=@RNUM + 1 AS CHAR) AS "rowNum"
|
||||
FROM (
|
||||
SELECT A.MU_CTI_LOG_ID AS "muCtiLogId"
|
||||
,A.RECORD_NO AS "recordNo"
|
||||
,A.CID AS "cid"
|
||||
,A.BOUND AS "bound"
|
||||
,A.MENU_NO AS "menuNo"
|
||||
,A.STATE_TYPE AS "stateType"
|
||||
,A.C_TYPE1 AS "cType1"
|
||||
,A.C_TYPE2 AS "cType2"
|
||||
,A.CRM_MB_PID AS "crmMbPid"
|
||||
,A.STORE_PID AS "storePid"
|
||||
,A.INCALL_SEL AS "incallSel"
|
||||
,A.CALL_BACK_CHK AS "callBackChk"
|
||||
,DATE_FORMAT(A.REG_DATE, '%Y-%m-%d %H:%i:%s') AS "regDate"
|
||||
/* ring - ARS 메뉴 선택 */
|
||||
,(SELECT B.MENU_NO
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.CTI_STEP = '2'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "ring"
|
||||
/* 통화 연결 시각 */
|
||||
,(SELECT DATE_FORMAT(B.REG_DATE, '%Y-%m-%d %H:%i:%s')
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.CTI_STEP = '3'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "linkDate"
|
||||
/* 통화 연결 상담원 */
|
||||
,(SELECT B.LOGINCID
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.CTI_STEP = '3'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "linkCid"
|
||||
/* 통화 종료 시각 (step 4) */
|
||||
,(SELECT DATE_FORMAT(B.REG_DATE, '%Y-%m-%d %H:%i:%s')
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.CTI_STEP = '4'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "linkEndDate"
|
||||
/* 통화 종료 시각 (step 5) */
|
||||
,(SELECT DATE_FORMAT(B.REG_DATE, '%Y-%m-%d %H:%i:%s')
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.CTI_STEP = '5'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "bendDate"
|
||||
/* callback CID */
|
||||
,(SELECT B.CID
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.CTI_STEP = '98'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "callbackCid"
|
||||
/* SMS 전송 여부 */
|
||||
,(SELECT B.STATE_TYPE
|
||||
FROM MU_CTI_LOG B
|
||||
WHERE B.RECORD_NO = A.RECORD_NO
|
||||
AND B.STATE_TYPE = 'lms'
|
||||
AND B.USE_YN = 'Y'
|
||||
ORDER BY B.REG_DATE DESC LIMIT 1) AS "smsFlag"
|
||||
/* 통화 메모 */
|
||||
,(SELECT T.CALL_MSG
|
||||
FROM MU_CTI_TEXT T
|
||||
WHERE T.RECORD_NO = A.RECORD_NO
|
||||
AND T.USE_YN = 'Y'
|
||||
ORDER BY T.REG_DATE DESC LIMIT 1) AS "callMsg"
|
||||
/* 고객명 */
|
||||
,(SELECT MM.NAME
|
||||
FROM MU_MEMBER MM
|
||||
WHERE MM.MU_MEMBER_ID = A.CRM_MB_PID
|
||||
AND MM.USE_YN = 'Y'
|
||||
LIMIT 1) AS "memberName"
|
||||
FROM MU_CTI_LOG A
|
||||
WHERE A.USE_YN = 'Y'
|
||||
AND A.FULLDNIS = #{fulldnis}
|
||||
AND A.REG_DATE >= CONCAT(#{sDate}, ' 00:00:00')
|
||||
AND A.REG_DATE <= CONCAT(#{eDate}, ' 23:59:59')
|
||||
<if test="callType != null and callType != '' and callType != 'callback'">
|
||||
AND A.MENU_NO = #{callType}
|
||||
AND A.STATE_TYPE IN ('start', 'ringout')
|
||||
</if>
|
||||
<if test="callType == 'callback'">
|
||||
AND A.STATE_TYPE = 'callback'
|
||||
</if>
|
||||
<if test="callType == null or callType == ''">
|
||||
AND (A.STATE_TYPE = 'start' OR A.STATE_TYPE = 'ringout')
|
||||
</if>
|
||||
<if test="callType1 != null and callType1 != ''">
|
||||
AND A.C_TYPE1 = #{callType1}
|
||||
</if>
|
||||
<if test="callType2 != null and callType2 != ''">
|
||||
AND A.C_TYPE2 = #{callType2}
|
||||
</if>
|
||||
<if test="mCid != null and mCid != ''">
|
||||
AND A.CID LIKE CONCAT('%', #{mCid}, '%')
|
||||
</if>
|
||||
<if test="incallSel != null and incallSel != ''">
|
||||
AND A.INCALL_SEL LIKE CONCAT('%|=|', #{incallSel}, '|=|%')
|
||||
</if>
|
||||
ORDER BY A.REG_DATE DESC
|
||||
LIMIT 18446744073709551615
|
||||
) L, (SELECT @RNUM:=0) R
|
||||
WHERE 1 = 1
|
||||
) L
|
||||
WHERE 1 = 1
|
||||
<if test="gridLimitEnd != null and gridLimitEnd != ''">
|
||||
LIMIT ${gridLimitStart}, ${gridLimitEnd}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 통화 메모 존재 여부 -->
|
||||
<select id="getCallMemoCnt" parameterType="com.madeu.crm.callLog.dto.CallMemoDTO" resultType="Integer">
|
||||
/** CallLogMAP.getCallMemoCnt **/
|
||||
SELECT COUNT(*)
|
||||
FROM MU_CTI_TEXT
|
||||
WHERE RECORD_NO = #{recordNo}
|
||||
AND USE_YN = 'Y'
|
||||
</select>
|
||||
|
||||
<!-- 통화 메모 신규 저장 -->
|
||||
<insert id="saveCallMemo" parameterType="com.madeu.crm.callLog.dto.CallMemoDTO">
|
||||
<selectKey resultType="string" keyProperty="muCtiTextId" order="BEFORE">
|
||||
SELECT CONCAT('CTXT', LPAD(IFNULL(MAX(CAST(SUBSTRING(MU_CTI_TEXT_ID, 5) AS UNSIGNED)), 0) + 1, 11, '0'))
|
||||
FROM MU_CTI_TEXT
|
||||
</selectKey>
|
||||
/** CallLogMAP.saveCallMemo **/
|
||||
INSERT INTO MU_CTI_TEXT (
|
||||
MU_CTI_TEXT_ID
|
||||
,RECORD_NO
|
||||
,CALL_MSG
|
||||
,USE_YN
|
||||
,CUD_FLAG
|
||||
,REG_ID
|
||||
,REG_DATE
|
||||
,MOD_ID
|
||||
,MOD_DATE
|
||||
) VALUES (
|
||||
#{muCtiTextId}
|
||||
,#{recordNo}
|
||||
,#{callMsg}
|
||||
,'Y'
|
||||
,'C'
|
||||
,#{loginMemberId}
|
||||
,NOW()
|
||||
,#{loginMemberId}
|
||||
,NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 통화 메모 수정 -->
|
||||
<update id="modCallMemo" parameterType="com.madeu.crm.callLog.dto.CallMemoDTO">
|
||||
/** CallLogMAP.modCallMemo **/
|
||||
UPDATE MU_CTI_TEXT
|
||||
SET CALL_MSG = #{callMsg}
|
||||
,CUD_FLAG = 'U'
|
||||
,MOD_ID = #{loginMemberId}
|
||||
,MOD_DATE = NOW()
|
||||
WHERE RECORD_NO = #{recordNo}
|
||||
AND USE_YN = 'Y'
|
||||
</update>
|
||||
|
||||
<!-- CTI 로그 저장 (Webhook용) -->
|
||||
<insert id="putCtiLog" parameterType="com.madeu.crm.callLog.dto.CallLogDTO">
|
||||
<selectKey resultType="string" keyProperty="muCtiLogId" order="BEFORE">
|
||||
SELECT CONCAT('CLOG', LPAD(IFNULL(MAX(CAST(SUBSTRING(MU_CTI_LOG_ID, 5) AS UNSIGNED)), 0) + 1, 11, '0'))
|
||||
FROM MU_CTI_LOG
|
||||
</selectKey>
|
||||
/** CallLogMAP.putCtiLog **/
|
||||
INSERT INTO MU_CTI_LOG (
|
||||
MU_CTI_LOG_ID
|
||||
,RECORD_NO
|
||||
,CID
|
||||
,FULLDNIS
|
||||
,BOUND
|
||||
,MENU_NO
|
||||
,STATE_TYPE
|
||||
,CTI_STEP
|
||||
,LOGINCID
|
||||
,C_TYPE1
|
||||
,C_TYPE2
|
||||
,CRM_MB_PID
|
||||
,STORE_PID
|
||||
,INCALL_SEL
|
||||
,USE_YN
|
||||
,CUD_FLAG
|
||||
,REG_DATE
|
||||
,MOD_DATE
|
||||
) VALUES (
|
||||
#{muCtiLogId}
|
||||
,#{recordNo}
|
||||
,#{cid}
|
||||
,#{fulldnis}
|
||||
,#{bound}
|
||||
,#{menuNo}
|
||||
,#{stateType}
|
||||
,#{ctiStep}
|
||||
,#{logincid}
|
||||
,#{cType1}
|
||||
,#{cType2}
|
||||
,#{crmMbPid}
|
||||
,#{storePid}
|
||||
,#{incallSel}
|
||||
,'Y'
|
||||
,'C'
|
||||
,NOW()
|
||||
,NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- CTI 로그 회원 매핑 업데이트 -->
|
||||
<update id="modCtiLogMember" parameterType="hashmap">
|
||||
/** CallLogMAP.modCtiLogMember **/
|
||||
UPDATE MU_CTI_LOG
|
||||
SET STORE_PID = #{storePid}
|
||||
,CRM_MB_PID = #{crmMbPid}
|
||||
,MOD_DATE = NOW()
|
||||
WHERE RECORD_NO = #{recordNo}
|
||||
AND USE_YN = 'Y'
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
133
src/main/resources/mappers/crm/smsTemplate/SmsTemplateSql.xml
Normal file
133
src/main/resources/mappers/crm/smsTemplate/SmsTemplateSql.xml
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.madeu.crm.smsTemplate.map.SmsTemplateMAP">
|
||||
|
||||
<!-- 상용구 목록 건수 조회 -->
|
||||
<select id="getSmsTemplateCnt" parameterType="com.madeu.crm.smsTemplate.dto.SmsTemplateSearchDTO" resultType="Integer">
|
||||
/** SmsTemplateMAP.getSmsTemplateCnt **/
|
||||
SELECT COUNT(*) AS TOTAL_COUNT
|
||||
FROM MU_SMS_TEMPLATE
|
||||
WHERE USE_YN = 'Y'
|
||||
<if test="searchKeyword != null and searchKeyword != ''">
|
||||
AND (TITLE LIKE CONCAT('%', TRIM(#{searchKeyword}), '%')
|
||||
OR CONTENT LIKE CONCAT('%', TRIM(#{searchKeyword}), '%'))
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 상용구 목록 조회 -->
|
||||
<select id="getSmsTemplateList" parameterType="com.madeu.crm.smsTemplate.dto.SmsTemplateSearchDTO" resultType="com.madeu.crm.smsTemplate.dto.SmsTemplateDTO">
|
||||
/** SmsTemplateMAP.getSmsTemplateList **/
|
||||
SELECT ST.*
|
||||
FROM (
|
||||
SELECT ST.*
|
||||
,CAST(@RNUM:=@RNUM + 1 AS CHAR) AS "rowNum"
|
||||
FROM (
|
||||
SELECT ST.MU_SMS_TEMPLATE_ID AS "muSmsTemplateId"
|
||||
,ST.TITLE AS "title"
|
||||
,ST.CONTENT AS "content"
|
||||
,DATE_FORMAT(ST.REG_DATE, '%Y-%m-%d %H:%i') AS "regDate"
|
||||
,DATE_FORMAT(ST.MOD_DATE, '%Y-%m-%d %H:%i') AS "modDate"
|
||||
,(SELECT MM.NAME
|
||||
FROM MU_MEMBER AS MM
|
||||
WHERE MM.USE_YN = 'Y'
|
||||
AND MM.MU_MEMBER_ID = ST.REG_ID
|
||||
LIMIT 0, 1) AS "regName"
|
||||
FROM MU_SMS_TEMPLATE AS ST
|
||||
WHERE ST.USE_YN = 'Y'
|
||||
<if test="searchKeyword != null and searchKeyword != ''">
|
||||
AND (ST.TITLE LIKE CONCAT('%', TRIM(#{searchKeyword}), '%')
|
||||
OR ST.CONTENT LIKE CONCAT('%', TRIM(#{searchKeyword}), '%'))
|
||||
</if>
|
||||
<choose>
|
||||
<when test="gridSort != null and gridSort != ''">
|
||||
ORDER BY ${gridSort}
|
||||
</when>
|
||||
<otherwise>
|
||||
ORDER BY ST.REG_DATE DESC
|
||||
</otherwise>
|
||||
</choose>
|
||||
LIMIT 18446744073709551615
|
||||
) ST, (SELECT @RNUM:=0) R
|
||||
WHERE 1 = 1
|
||||
) ST
|
||||
WHERE 1 = 1
|
||||
<if test="gridLimitEnd != null and gridLimitEnd != ''">
|
||||
LIMIT ${gridLimitStart}, ${gridLimitEnd}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<!-- 상용구 상세 조회 -->
|
||||
<select id="getSmsTemplate" parameterType="com.madeu.crm.smsTemplate.dto.SmsTemplateDTO" resultType="com.madeu.crm.smsTemplate.dto.SmsTemplateDTO">
|
||||
/** SmsTemplateMAP.getSmsTemplate **/
|
||||
SELECT ST.MU_SMS_TEMPLATE_ID AS "muSmsTemplateId"
|
||||
,ST.TITLE AS "title"
|
||||
,ST.CONTENT AS "content"
|
||||
,DATE_FORMAT(ST.REG_DATE, '%Y-%m-%d %H:%i') AS "regDate"
|
||||
,DATE_FORMAT(ST.MOD_DATE, '%Y-%m-%d %H:%i') AS "modDate"
|
||||
,(SELECT MM.NAME
|
||||
FROM MU_MEMBER AS MM
|
||||
WHERE MM.USE_YN = 'Y'
|
||||
AND MM.MU_MEMBER_ID = ST.REG_ID
|
||||
LIMIT 0, 1) AS "regName"
|
||||
FROM MU_SMS_TEMPLATE AS ST
|
||||
WHERE ST.USE_YN = 'Y'
|
||||
AND ST.MU_SMS_TEMPLATE_ID = #{muSmsTemplateId}
|
||||
LIMIT 0, 1
|
||||
</select>
|
||||
|
||||
<!-- 상용구 등록 -->
|
||||
<insert id="putSmsTemplate" parameterType="com.madeu.crm.smsTemplate.dto.SmsTemplateDTO">
|
||||
<selectKey resultType="string" keyProperty="muSmsTemplateId" order="BEFORE">
|
||||
SELECT CONCAT('SMST', LPAD(IFNULL(MAX(CAST(SUBSTRING(MU_SMS_TEMPLATE_ID, 5) AS UNSIGNED)), 0) + 1, 11, '0'))
|
||||
FROM MU_SMS_TEMPLATE
|
||||
</selectKey>
|
||||
/** SmsTemplateMAP.putSmsTemplate **/
|
||||
INSERT INTO MU_SMS_TEMPLATE (
|
||||
MU_SMS_TEMPLATE_ID
|
||||
,TITLE
|
||||
,CONTENT
|
||||
,USE_YN
|
||||
,CUD_FLAG
|
||||
,REG_ID
|
||||
,REG_DATE
|
||||
,MOD_ID
|
||||
,MOD_DATE
|
||||
) VALUES (
|
||||
#{muSmsTemplateId}
|
||||
,#{title}
|
||||
,#{content}
|
||||
,'Y'
|
||||
,'C'
|
||||
,#{loginMemberId}
|
||||
,NOW()
|
||||
,#{loginMemberId}
|
||||
,NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 상용구 수정 -->
|
||||
<update id="modSmsTemplate" parameterType="com.madeu.crm.smsTemplate.dto.SmsTemplateDTO">
|
||||
/** SmsTemplateMAP.modSmsTemplate **/
|
||||
UPDATE MU_SMS_TEMPLATE
|
||||
SET TITLE = #{title}
|
||||
,CONTENT = #{content}
|
||||
,CUD_FLAG = 'U'
|
||||
,MOD_ID = #{loginMemberId}
|
||||
,MOD_DATE = NOW()
|
||||
WHERE USE_YN = 'Y'
|
||||
AND MU_SMS_TEMPLATE_ID = #{muSmsTemplateId}
|
||||
</update>
|
||||
|
||||
<!-- 상용구 삭제 (논리 삭제) -->
|
||||
<update id="delSmsTemplate" parameterType="com.madeu.crm.smsTemplate.dto.SmsTemplateDTO">
|
||||
/** SmsTemplateMAP.delSmsTemplate **/
|
||||
UPDATE MU_SMS_TEMPLATE
|
||||
SET USE_YN = 'N'
|
||||
,CUD_FLAG = 'D'
|
||||
,MOD_ID = #{loginMemberId}
|
||||
,MOD_DATE = NOW()
|
||||
WHERE USE_YN = 'Y'
|
||||
AND MU_SMS_TEMPLATE_ID = #{muSmsTemplateId}
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
350
src/main/resources/static/css/web/call_log.css
Normal file
350
src/main/resources/static/css/web/call_log.css
Normal file
@@ -0,0 +1,350 @@
|
||||
/* ============================================
|
||||
통화 로그 관리 (call_log.css)
|
||||
============================================ */
|
||||
|
||||
/* ---- 검색 필터 영역 ---- */
|
||||
.cl_filter_wrap {
|
||||
background: #fff;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 10px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.cl_filter_row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cl_filter_row+.cl_filter_row {
|
||||
margin-top: 8px;
|
||||
padding-top: 8px;
|
||||
border-top: 1px solid #F0F1F3;
|
||||
}
|
||||
|
||||
.cl_filter_item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.cl_filter_item label {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
white-space: nowrap;
|
||||
min-width: 55px;
|
||||
}
|
||||
|
||||
.cl_filter_item select,
|
||||
.cl_filter_item .cl_select {
|
||||
height: 32px;
|
||||
padding: 0 8px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
background: #fff url(/image/web/select_arrow.svg) no-repeat 95% 55%/18px auto;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
padding-right: 28px;
|
||||
min-width: 90px;
|
||||
}
|
||||
|
||||
.cl_filter_item input[type="text"] {
|
||||
height: 32px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
width: 140px;
|
||||
}
|
||||
|
||||
.cl_filter_item input[type="text"]::placeholder {
|
||||
color: #B5BDC4;
|
||||
}
|
||||
|
||||
/* 날짜 필터 */
|
||||
.cl_date_item input[type="date"] {
|
||||
height: 32px;
|
||||
padding: 0 8px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cl_date_sep {
|
||||
color: #888;
|
||||
font-size: 13px;
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
/* 날짜 단축 버튼 */
|
||||
.cl_quick_btns {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.cl_quick_btns button {
|
||||
height: 30px;
|
||||
padding: 0 10px;
|
||||
border: 1px solid #D5D8DC;
|
||||
border-radius: 4px;
|
||||
background: #FAFBFC;
|
||||
color: #555;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.cl_quick_btns button:hover {
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
border-color: #3985EA;
|
||||
}
|
||||
|
||||
/* 조회 버튼 */
|
||||
.cl_search_btn {
|
||||
height: 32px;
|
||||
padding: 0 20px;
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.cl_search_btn:hover {
|
||||
background: #2D6CC0;
|
||||
}
|
||||
|
||||
/* ---- 통계 요약 바 ---- */
|
||||
.cl_stats_bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
background: #F7F9FC;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
padding: 10px 16px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 13px;
|
||||
color: #555;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cl_stats_bar strong {
|
||||
color: #3985EA;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.cl_stats_sep {
|
||||
color: #D5D8DC;
|
||||
}
|
||||
|
||||
.cl_stats_detail {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.cl_stats_detail strong {
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* ---- ag-Grid 영역 ---- */
|
||||
.cl_grid_box {
|
||||
width: 100%;
|
||||
height: calc(100% - 230px);
|
||||
min-height: 300px;
|
||||
background: #fff;
|
||||
border: solid 1px #E9ECF0;
|
||||
border-radius: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ---- 메모 팝업 ---- */
|
||||
.cl_memo_overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.35);
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.cl_memo_popup {
|
||||
background: #fff;
|
||||
border-radius: 8px;
|
||||
width: 480px;
|
||||
max-width: 90%;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.cl_memo_header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 16px 20px;
|
||||
border-bottom: 1px solid #E9ECF0;
|
||||
}
|
||||
|
||||
.cl_memo_header h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cl_memo_record {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.cl_memo_close {
|
||||
margin-left: auto;
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 22px;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.cl_memo_close:hover {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.cl_memo_body {
|
||||
padding: 16px 20px;
|
||||
}
|
||||
|
||||
.cl_memo_body textarea {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
min-height: 120px;
|
||||
line-height: 1.6;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cl_memo_body textarea:focus {
|
||||
border-color: #3985EA;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(57, 133, 234, 0.12);
|
||||
}
|
||||
|
||||
.cl_memo_footer {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 12px 20px 16px;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.cl_memo_save_btn {
|
||||
height: 34px;
|
||||
padding: 0 20px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cl_memo_save_btn:hover {
|
||||
background: #2D6CC0;
|
||||
}
|
||||
|
||||
.cl_memo_cancel_btn {
|
||||
height: 34px;
|
||||
padding: 0 16px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cl_memo_cancel_btn:hover {
|
||||
background: #F7F8FA;
|
||||
}
|
||||
|
||||
/* ---- 그리드 내 버튼/뱃지 ---- */
|
||||
.cl_play_btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border: 1px solid #3985EA;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
color: #3985EA;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.cl_play_btn:hover {
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.cl_incall_badge {
|
||||
display: inline-block;
|
||||
padding: 1px 6px;
|
||||
margin: 1px 2px;
|
||||
background: #EEF3FB;
|
||||
color: #3366AA;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* ---- 반응형 ---- */
|
||||
@media screen and (max-width: 1500px) {
|
||||
.cl_filter_row {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.cl_filter_item label {
|
||||
min-width: 45px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cl_filter_item select,
|
||||
.cl_filter_item .cl_select {
|
||||
min-width: 80px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cl_filter_item input[type="text"] {
|
||||
width: 120px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.cl_quick_btns button {
|
||||
padding: 0 7px;
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
285
src/main/resources/static/css/web/sms_template.css
Normal file
285
src/main/resources/static/css/web/sms_template.css
Normal file
@@ -0,0 +1,285 @@
|
||||
/* ============================================
|
||||
문자 상용구 관리 - 좌측 목록 / 우측 상세
|
||||
============================================ */
|
||||
|
||||
/* ---- 2패널 컨테이너 ---- */
|
||||
.sms_two_panel {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
height: calc(100% - 60px);
|
||||
min-height: 400px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* ---- 좌측 목록 패널 ---- */
|
||||
.sms_left_panel {
|
||||
width: 45%;
|
||||
min-width: 360px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 검색 영역 */
|
||||
.sms_search_area {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #E9ECF0;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sms_search_box {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.sms_search_box img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: 8px;
|
||||
z-index: 1;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
.sms_search_box input {
|
||||
width: 100%;
|
||||
height: 36px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px 0 32px;
|
||||
font-size: 13px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.sms_search_box input::placeholder {
|
||||
color: #B5BDC4;
|
||||
}
|
||||
|
||||
.sms_search_btn {
|
||||
height: 36px;
|
||||
padding: 0 14px;
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sms_search_btn:hover {
|
||||
background: #2D6CC0;
|
||||
}
|
||||
|
||||
.sms_new_btn {
|
||||
height: 36px;
|
||||
padding: 0 14px;
|
||||
background: #fff;
|
||||
color: #3985EA;
|
||||
border: 1px solid #3985EA;
|
||||
border-radius: 5px;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.sms_new_btn:hover {
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ag-Grid 영역 */
|
||||
.sms_grid_box {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* ---- 우측 상세 패널 ---- */
|
||||
.sms_right_panel {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 빈 상태 */
|
||||
.sms_empty_state {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.sms_empty_state p {
|
||||
text-align: center;
|
||||
color: #B5BDC4;
|
||||
font-size: 14px;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
/* 상세 폼 */
|
||||
.sms_detail_form {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.sms_detail_title_bar {
|
||||
padding: 14px 20px;
|
||||
border-bottom: 1px solid #E9ECF0;
|
||||
}
|
||||
|
||||
.sms_detail_title_bar h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.sms_form_row {
|
||||
padding: 0 20px;
|
||||
margin-top: 14px;
|
||||
}
|
||||
|
||||
.sms_form_row label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.sms_form_row input[type="text"] {
|
||||
width: 100%;
|
||||
height: 38px;
|
||||
padding: 0 12px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sms_form_row textarea {
|
||||
width: 100%;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
min-height: 160px;
|
||||
line-height: 1.6;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sms_form_row input:focus,
|
||||
.sms_form_row textarea:focus {
|
||||
border-color: #3985EA;
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 2px rgba(57, 133, 234, 0.12);
|
||||
}
|
||||
|
||||
.byte_info {
|
||||
text-align: right;
|
||||
margin-top: 5px;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.type_badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
margin-left: 4px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.type_badge.sms {
|
||||
background: #E8F5E9;
|
||||
color: #2E7D32;
|
||||
}
|
||||
|
||||
.type_badge.lms {
|
||||
background: #FFF3E0;
|
||||
color: #E65100;
|
||||
}
|
||||
|
||||
.sms_info_row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
padding: 10px 20px !important;
|
||||
margin-top: 10px !important;
|
||||
border-top: 1px solid #F0F1F3;
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.sms_info_row strong {
|
||||
font-weight: 500;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.sms_btn_group {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 14px 20px;
|
||||
border-top: 1px solid #E9ECF0;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.sms_save_btn {
|
||||
height: 36px;
|
||||
padding: 0 24px;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background: #3985EA;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sms_save_btn:hover {
|
||||
background: #2D6CC0;
|
||||
}
|
||||
|
||||
.sms_delete_btn {
|
||||
height: 36px;
|
||||
padding: 0 18px;
|
||||
border: 1px solid #FF2222;
|
||||
border-radius: 5px;
|
||||
background: transparent;
|
||||
color: #FF2222;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sms_delete_btn:hover {
|
||||
background: #FF2222;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.sms_cancel_btn {
|
||||
height: 36px;
|
||||
padding: 0 18px;
|
||||
border: 1px solid #E9ECF0;
|
||||
border-radius: 5px;
|
||||
background: #fff;
|
||||
color: #666;
|
||||
font-size: 13px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sms_cancel_btn:hover {
|
||||
background: #F7F8FA;
|
||||
}
|
||||
427
src/main/resources/static/js/web/callLog/callLogSelectList.js
Normal file
427
src/main/resources/static/js/web/callLog/callLogSelectList.js
Normal file
@@ -0,0 +1,427 @@
|
||||
/**
|
||||
* 통화 로그 관리 - ag-Grid
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
fn_initGrid();
|
||||
fn_init();
|
||||
fn_setToday();
|
||||
fn_loadCallLogList();
|
||||
});
|
||||
|
||||
/* ============================================
|
||||
전역 변수
|
||||
============================================ */
|
||||
var gridApi = null;
|
||||
|
||||
/* ARS 메뉴 번호 → 텍스트 매핑 */
|
||||
var arsMenuMap = {
|
||||
'1': '상담',
|
||||
'2': '예약',
|
||||
'3': '위치안내'
|
||||
};
|
||||
|
||||
/* ============================================
|
||||
ag-Grid 초기화
|
||||
============================================ */
|
||||
function fn_initGrid() {
|
||||
var columnDefs = [
|
||||
{
|
||||
headerName: 'No',
|
||||
valueGetter: function (params) {
|
||||
return params.node.rowIndex + 1;
|
||||
},
|
||||
width: 60,
|
||||
maxWidth: 60,
|
||||
cellStyle: { textAlign: 'center' },
|
||||
suppressSizeToFit: true
|
||||
},
|
||||
{
|
||||
headerName: 'RECORD NO',
|
||||
field: 'recordNo',
|
||||
width: 100,
|
||||
maxWidth: 110,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '구분1',
|
||||
field: 'menuText',
|
||||
width: 100,
|
||||
maxWidth: 120,
|
||||
cellStyle: { textAlign: 'center' },
|
||||
valueGetter: function (params) {
|
||||
var d = params.data;
|
||||
if (!d) return '';
|
||||
if (d.bound === 'OUT') return 'OUT';
|
||||
if (d.callbackCid) return 'Call Back';
|
||||
return arsMenuMap[d.ring] || '';
|
||||
},
|
||||
cellRenderer: function (params) {
|
||||
if (!params.data) return '';
|
||||
if (params.data.bound === 'OUT') {
|
||||
return '<span style="color:#0000ff;font-weight:600">OUT</span>';
|
||||
}
|
||||
if (params.data.callbackCid) {
|
||||
return 'Call Back<br><small>' + params.data.callbackCid + '</small>';
|
||||
}
|
||||
return params.value || '';
|
||||
}
|
||||
},
|
||||
{
|
||||
headerName: '구분2',
|
||||
field: 'cType1',
|
||||
width: 65,
|
||||
maxWidth: 80,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '구분3',
|
||||
field: 'cType2',
|
||||
width: 80,
|
||||
maxWidth: 100,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '고객명',
|
||||
field: 'memberName',
|
||||
width: 90,
|
||||
maxWidth: 120,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '전화번호',
|
||||
field: 'cid',
|
||||
width: 120,
|
||||
maxWidth: 140,
|
||||
cellStyle: { textAlign: 'center' },
|
||||
valueFormatter: function (params) {
|
||||
return fn_formatPhone(params.value);
|
||||
}
|
||||
},
|
||||
{
|
||||
headerName: '전화 온 시간',
|
||||
field: 'regDate',
|
||||
width: 145,
|
||||
maxWidth: 160,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '통화 시작',
|
||||
field: 'linkDate',
|
||||
width: 145,
|
||||
maxWidth: 160,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '통화 종료',
|
||||
valueGetter: function (params) {
|
||||
if (!params.data) return '';
|
||||
return params.data.linkEndDate || params.data.bendDate || '';
|
||||
},
|
||||
width: 145,
|
||||
maxWidth: 160,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '상담 전화번호',
|
||||
field: 'linkCid',
|
||||
width: 110,
|
||||
maxWidth: 130,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '통화파일',
|
||||
field: 'recordNo',
|
||||
width: 80,
|
||||
maxWidth: 90,
|
||||
cellStyle: { textAlign: 'center' },
|
||||
cellRenderer: function (params) {
|
||||
if (!params.data || !params.data.recordNo || !params.data.linkDate) return '';
|
||||
var btn = '<button type="button" class="cl_play_btn" onclick="fn_playRecord(\'' + params.data.recordNo + '\')">▶</button>';
|
||||
return btn;
|
||||
}
|
||||
},
|
||||
{
|
||||
headerName: 'In Call',
|
||||
field: 'incallSel',
|
||||
width: 150,
|
||||
minWidth: 100,
|
||||
cellStyle: { textAlign: 'left' },
|
||||
cellRenderer: function (params) {
|
||||
var val = params.value;
|
||||
if (!val) return '';
|
||||
// incallSel은 '|=|값1|=||=|값2|=|' 형식
|
||||
var items = val.split('|=|').filter(function (v) { return v.trim() !== ''; });
|
||||
if (items.length === 0) return '';
|
||||
return items.map(function (item) {
|
||||
return '<span class="cl_incall_badge">' + item + '</span>';
|
||||
}).join(' ');
|
||||
}
|
||||
},
|
||||
{
|
||||
headerName: '메모',
|
||||
field: 'callMsg',
|
||||
flex: 1,
|
||||
minWidth: 120,
|
||||
cellStyle: { textAlign: 'left', cursor: 'pointer' },
|
||||
cellRenderer: function (params) {
|
||||
var msg = params.value || '';
|
||||
// HTML 태그 제거하여 표시
|
||||
var plainText = msg.replace(/<[^>]+>/g, '').trim();
|
||||
if (plainText.length > 30) {
|
||||
plainText = plainText.substring(0, 30) + '...';
|
||||
}
|
||||
return plainText || '<span style="color:#B5BDC4">클릭하여 메모 입력</span>';
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
var gridOptions = {
|
||||
columnDefs: columnDefs,
|
||||
rowData: [],
|
||||
rowSelection: 'single',
|
||||
animateRows: true,
|
||||
headerHeight: 36,
|
||||
rowHeight: 40,
|
||||
suppressCellFocus: true,
|
||||
overlayNoRowsTemplate: '<span style="color:#B5BDC4; font-size:13px;">검색된 통화 내역이 없습니다.</span>',
|
||||
onCellClicked: function (event) {
|
||||
if (event.colDef.field === 'callMsg') {
|
||||
fn_openMemo(event.data);
|
||||
}
|
||||
},
|
||||
defaultColDef: {
|
||||
resizable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
var gridDiv = document.querySelector('#callLogGrid');
|
||||
gridApi = new agGrid.Grid(gridDiv, gridOptions);
|
||||
gridApi = gridOptions.api;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
초기화 (이벤트 바인딩)
|
||||
============================================ */
|
||||
function fn_init() {
|
||||
$('#searchBtn').on('click', function () {
|
||||
fn_loadCallLogList();
|
||||
});
|
||||
|
||||
$('#mCid').on('keypress', function (e) {
|
||||
if (e.which === 13) fn_loadCallLogList();
|
||||
});
|
||||
|
||||
$('#sDate, #eDate').on('change', function () {
|
||||
// 날짜 변경 시 자동 검색하지 않음 (사용자가 조회 버튼 클릭)
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
오늘 날짜 설정
|
||||
============================================ */
|
||||
function fn_setToday() {
|
||||
var today = fn_getDateStr(new Date());
|
||||
$('#sDate').val(today);
|
||||
$('#eDate').val(today);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
날짜 단축 버튼
|
||||
============================================ */
|
||||
function fn_dayChk(type) {
|
||||
var now = new Date();
|
||||
var sDate, eDate;
|
||||
|
||||
switch (type) {
|
||||
case 't': // 오늘
|
||||
sDate = new Date();
|
||||
eDate = new Date();
|
||||
break;
|
||||
case 'p': // 어제
|
||||
sDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
||||
eDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
||||
break;
|
||||
case 'w': // 이번주 (월요일~오늘)
|
||||
var dayOfWeek = now.getDay();
|
||||
var diff = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
||||
sDate = new Date(now.getFullYear(), now.getMonth(), now.getDate() - diff);
|
||||
eDate = new Date();
|
||||
break;
|
||||
case 'pw': // 지난주 (월요일~일요일)
|
||||
var dayOfWeek = now.getDay();
|
||||
var diff = dayOfWeek === 0 ? 6 : dayOfWeek - 1;
|
||||
var thisMonday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - diff);
|
||||
sDate = new Date(thisMonday.getFullYear(), thisMonday.getMonth(), thisMonday.getDate() - 7);
|
||||
eDate = new Date(thisMonday.getFullYear(), thisMonday.getMonth(), thisMonday.getDate() - 1);
|
||||
break;
|
||||
case 'm': // 이번달
|
||||
sDate = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
eDate = new Date();
|
||||
break;
|
||||
case 'pm': // 지난달
|
||||
sDate = new Date(now.getFullYear(), now.getMonth() - 1, 1);
|
||||
eDate = new Date(now.getFullYear(), now.getMonth(), 0);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
$('#sDate').val(fn_getDateStr(sDate));
|
||||
$('#eDate').val(fn_getDateStr(eDate));
|
||||
fn_loadCallLogList();
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
목록 조회
|
||||
============================================ */
|
||||
function fn_loadCallLogList() {
|
||||
var param = {
|
||||
sDate: $('#sDate').val(),
|
||||
eDate: $('#eDate').val(),
|
||||
callType: $('#callType').val(),
|
||||
callType1: $('#callType1').val(),
|
||||
callType2: $('#callType2').val(),
|
||||
mCid: $('#mCid').val().replace(/[^0-9]/g, ''),
|
||||
fulldnis: '', // TODO: 매장별 수신번호 설정 필요
|
||||
menuClass: menuClass
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/callLog/getCallLogList.do',
|
||||
type: 'POST',
|
||||
data: param,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
var rows = data.rows || [];
|
||||
gridApi.setRowData(rows);
|
||||
|
||||
if (rows.length === 0) {
|
||||
gridApi.showNoRowsOverlay();
|
||||
}
|
||||
|
||||
// 통계 업데이트
|
||||
fn_updateStats(data.stats);
|
||||
},
|
||||
error: function () {
|
||||
alert('목록 조회 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
통계 업데이트
|
||||
============================================ */
|
||||
function fn_updateStats(stats) {
|
||||
if (!stats) {
|
||||
$('#statTotal, #statIn, #statOut, #statType1, #statType2, #statType11, #statType12, #statType13').text('0');
|
||||
return;
|
||||
}
|
||||
|
||||
$('#statTotal').text(fn_numberFormat(stats.totalCnt || 0));
|
||||
$('#statIn').text(fn_numberFormat(stats.inCnt || 0));
|
||||
$('#statOut').text(fn_numberFormat(stats.outCnt || 0));
|
||||
$('#statType1').text(fn_numberFormat(stats.type1Cnt || 0));
|
||||
$('#statType2').text(fn_numberFormat(stats.type2Cnt || 0));
|
||||
$('#statType11').text(fn_numberFormat(stats.type11Cnt || 0));
|
||||
$('#statType12').text(fn_numberFormat(stats.type12Cnt || 0));
|
||||
$('#statType13').text(fn_numberFormat(stats.type13Cnt || 0));
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
메모 팝업
|
||||
============================================ */
|
||||
function fn_openMemo(data) {
|
||||
if (!data || !data.recordNo) return;
|
||||
|
||||
$('#memoRecordNoVal').val(data.recordNo);
|
||||
$('#memoRecordNo').text('RECORD NO: ' + data.recordNo);
|
||||
$('#memoContent').val(data.callMsg || '');
|
||||
$('#memoOverlay').fadeIn(200);
|
||||
$('#memoContent').focus();
|
||||
}
|
||||
|
||||
function fn_closeMemo() {
|
||||
$('#memoOverlay').fadeOut(200);
|
||||
}
|
||||
|
||||
function fn_saveMemo() {
|
||||
var recordNo = $('#memoRecordNoVal').val();
|
||||
var callMsg = $.trim($('#memoContent').val());
|
||||
|
||||
if (!recordNo) return;
|
||||
|
||||
var param = {
|
||||
recordNo: recordNo,
|
||||
callMsg: callMsg,
|
||||
menuClass: menuClass
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/callLog/saveCallMemo.do',
|
||||
type: 'POST',
|
||||
data: param,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
alert(data.msgDesc || '저장되었습니다.');
|
||||
fn_closeMemo();
|
||||
fn_loadCallLogList();
|
||||
},
|
||||
error: function () {
|
||||
alert('메모 저장 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
유틸리티 함수
|
||||
============================================ */
|
||||
function fn_getDateStr(date) {
|
||||
var y = date.getFullYear();
|
||||
var m = ('0' + (date.getMonth() + 1)).slice(-2);
|
||||
var d = ('0' + date.getDate()).slice(-2);
|
||||
return y + '-' + m + '-' + d;
|
||||
}
|
||||
|
||||
function fn_numberFormat(num) {
|
||||
if (!num && num !== 0) return '0';
|
||||
return Number(num).toLocaleString();
|
||||
}
|
||||
|
||||
function fn_formatPhone(phone) {
|
||||
if (!phone) return '';
|
||||
phone = phone.replace(/[^0-9]/g, '');
|
||||
if (phone.length === 11) {
|
||||
return phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3');
|
||||
} else if (phone.length === 10) {
|
||||
return phone.replace(/(\d{3})(\d{3})(\d{4})/, '$1-$2-$3');
|
||||
} else if (phone.length === 9) {
|
||||
return phone.replace(/(\d{2})(\d{3})(\d{4})/, '$1-$2-$3');
|
||||
}
|
||||
return phone;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
녹음 파일 재생
|
||||
============================================ */
|
||||
function fn_playRecord(recordNo) {
|
||||
if (!recordNo) return;
|
||||
|
||||
$.ajax({
|
||||
url: '/callLog/getRecordFileUrl.do',
|
||||
type: 'POST',
|
||||
data: { recordNo: recordNo },
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.success && data.recordUrl) {
|
||||
window.open(data.recordUrl, '_blank', 'width=400,height=200');
|
||||
} else {
|
||||
alert('녹음 파일을 불러올 수 없습니다.');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
alert('녹음 파일 조회 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,329 @@
|
||||
/**
|
||||
* 문자 상용구 관리 - ag-Grid
|
||||
*/
|
||||
$(document).ready(function () {
|
||||
fn_initGrid();
|
||||
fn_init();
|
||||
fn_loadTemplateList();
|
||||
});
|
||||
|
||||
/* ============================================
|
||||
전역 변수
|
||||
============================================ */
|
||||
var gridApi = null;
|
||||
var currentMode = ''; // 'new' | 'edit'
|
||||
var currentTemplateId = '';
|
||||
|
||||
/* ============================================
|
||||
ag-Grid 초기화
|
||||
============================================ */
|
||||
function fn_initGrid() {
|
||||
var columnDefs = [
|
||||
{
|
||||
headerName: 'No',
|
||||
valueGetter: function (params) {
|
||||
return params.node.rowIndex + 1;
|
||||
},
|
||||
width: 55,
|
||||
maxWidth: 55,
|
||||
cellStyle: { textAlign: 'center' },
|
||||
suppressSizeToFit: true
|
||||
},
|
||||
{
|
||||
headerName: '제목',
|
||||
field: 'title',
|
||||
flex: 2,
|
||||
minWidth: 120,
|
||||
cellStyle: { textAlign: 'left' }
|
||||
},
|
||||
{
|
||||
headerName: '등록자',
|
||||
field: 'regName',
|
||||
width: 80,
|
||||
maxWidth: 100,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
},
|
||||
{
|
||||
headerName: '등록일',
|
||||
field: 'regDate',
|
||||
width: 100,
|
||||
maxWidth: 120,
|
||||
cellStyle: { textAlign: 'center' }
|
||||
}
|
||||
];
|
||||
|
||||
var gridOptions = {
|
||||
columnDefs: columnDefs,
|
||||
rowData: [],
|
||||
rowSelection: 'single',
|
||||
animateRows: true,
|
||||
headerHeight: 36,
|
||||
rowHeight: 38,
|
||||
suppressCellFocus: true,
|
||||
overlayNoRowsTemplate: '<span style="color:#B5BDC4; font-size:13px;">등록된 상용구가 없습니다.</span>',
|
||||
onRowClicked: function (event) {
|
||||
var id = event.data.muSmsTemplateId;
|
||||
if (id) fn_selectTemplate(id);
|
||||
},
|
||||
defaultColDef: {
|
||||
resizable: true,
|
||||
sortable: true
|
||||
}
|
||||
};
|
||||
|
||||
var gridDiv = document.querySelector('#smsTemplateGrid');
|
||||
gridApi = new agGrid.Grid(gridDiv, gridOptions);
|
||||
gridApi = gridOptions.api;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
초기화
|
||||
============================================ */
|
||||
function fn_init() {
|
||||
$('#searchBtn').on('click', function () {
|
||||
fn_loadTemplateList();
|
||||
});
|
||||
|
||||
$('#searchKeyword').on('keypress', function (e) {
|
||||
if (e.which === 13) fn_loadTemplateList();
|
||||
});
|
||||
|
||||
$('#newTemplateBtn').on('click', function () {
|
||||
fn_newTemplate();
|
||||
});
|
||||
|
||||
$('#saveBtn').on('click', function () {
|
||||
fn_saveTemplate();
|
||||
});
|
||||
|
||||
$('#deleteBtn').on('click', function () {
|
||||
fn_deleteTemplate();
|
||||
});
|
||||
|
||||
$('#cancelBtn').on('click', function () {
|
||||
fn_cancelEdit();
|
||||
});
|
||||
|
||||
$('#templateContent').on('input', function () {
|
||||
fn_updateByteCount();
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
목록 조회
|
||||
============================================ */
|
||||
function fn_loadTemplateList() {
|
||||
var param = {
|
||||
searchKeyword: $('#searchKeyword').val(),
|
||||
menuClass: menuClass
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/smsTemplate/getSmsTemplateList.do',
|
||||
type: 'POST',
|
||||
data: param,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
var rows = data.rows || [];
|
||||
gridApi.setRowData(rows);
|
||||
|
||||
if (rows.length === 0) {
|
||||
gridApi.showNoRowsOverlay();
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
alert('목록 조회 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
상세 조회
|
||||
============================================ */
|
||||
function fn_selectTemplate(templateId) {
|
||||
var param = {
|
||||
muSmsTemplateId: templateId,
|
||||
menuClass: menuClass
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/smsTemplate/getSmsTemplate.do',
|
||||
type: 'POST',
|
||||
data: param,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
if (data.data) {
|
||||
fn_showDetail(data.data);
|
||||
} else {
|
||||
alert(data.msgDesc || '상세 조회에 실패하였습니다.');
|
||||
}
|
||||
},
|
||||
error: function () {
|
||||
alert('상세 조회 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fn_showDetail(detail) {
|
||||
currentMode = 'edit';
|
||||
currentTemplateId = detail.muSmsTemplateId;
|
||||
|
||||
$('#detailTitle').text('상용구 수정');
|
||||
$('#muSmsTemplateId').val(detail.muSmsTemplateId);
|
||||
$('#templateTitle').val(detail.title || '');
|
||||
$('#templateContent').val(detail.content || '');
|
||||
$('#regName').text(detail.regName || '-');
|
||||
$('#regDate').text(detail.regDate || '-');
|
||||
$('#modDate').text(detail.modDate || '-');
|
||||
|
||||
$('#infoRow').show();
|
||||
$('#deleteBtn').show();
|
||||
$('#emptyState').hide();
|
||||
$('#detailForm').show();
|
||||
|
||||
fn_updateByteCount();
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
새 상용구
|
||||
============================================ */
|
||||
function fn_newTemplate() {
|
||||
currentMode = 'new';
|
||||
currentTemplateId = '';
|
||||
|
||||
$('#detailTitle').text('상용구 등록');
|
||||
$('#muSmsTemplateId').val('');
|
||||
$('#templateTitle').val('');
|
||||
$('#templateContent').val('');
|
||||
|
||||
$('#infoRow').hide();
|
||||
$('#deleteBtn').hide();
|
||||
$('#emptyState').hide();
|
||||
$('#detailForm').show();
|
||||
|
||||
fn_updateByteCount();
|
||||
|
||||
gridApi.deselectAll();
|
||||
$('#templateTitle').focus();
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
취소
|
||||
============================================ */
|
||||
function fn_cancelEdit() {
|
||||
currentMode = '';
|
||||
currentTemplateId = '';
|
||||
|
||||
$('#detailForm').hide();
|
||||
$('#emptyState').show();
|
||||
|
||||
gridApi.deselectAll();
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
저장 (등록/수정)
|
||||
============================================ */
|
||||
function fn_saveTemplate() {
|
||||
var title = $.trim($('#templateTitle').val());
|
||||
var content = $.trim($('#templateContent').val());
|
||||
|
||||
if (!title) {
|
||||
alert('제목을 입력하세요.');
|
||||
$('#templateTitle').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!content) {
|
||||
alert('내용을 입력하세요.');
|
||||
$('#templateContent').focus();
|
||||
return;
|
||||
}
|
||||
|
||||
var url = '';
|
||||
var param = {
|
||||
title: title,
|
||||
content: content,
|
||||
menuClass: menuClass
|
||||
};
|
||||
|
||||
if (currentMode === 'new') {
|
||||
url = '/smsTemplate/putSmsTemplate.do';
|
||||
} else if (currentMode === 'edit') {
|
||||
url = '/smsTemplate/modSmsTemplate.do';
|
||||
param.muSmsTemplateId = currentTemplateId;
|
||||
}
|
||||
|
||||
if (!url) return;
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
data: param,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
alert(data.msgDesc || '처리되었습니다.');
|
||||
fn_cancelEdit();
|
||||
fn_loadTemplateList();
|
||||
},
|
||||
error: function () {
|
||||
alert('저장 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
삭제
|
||||
============================================ */
|
||||
function fn_deleteTemplate() {
|
||||
if (!currentTemplateId) return;
|
||||
if (!confirm('이 상용구를 삭제하시겠습니까?')) return;
|
||||
|
||||
var param = {
|
||||
muSmsTemplateId: currentTemplateId,
|
||||
menuClass: menuClass
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: '/smsTemplate/delSmsTemplate.do',
|
||||
type: 'POST',
|
||||
data: param,
|
||||
dataType: 'json',
|
||||
success: function (data) {
|
||||
alert(data.msgDesc || '삭제되었습니다.');
|
||||
fn_cancelEdit();
|
||||
fn_loadTemplateList();
|
||||
},
|
||||
error: function () {
|
||||
alert('삭제 중 오류가 발생하였습니다.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
바이트 카운트
|
||||
============================================ */
|
||||
function fn_updateByteCount() {
|
||||
var content = $('#templateContent').val() || '';
|
||||
var byteLen = fn_getByteLength(content);
|
||||
|
||||
$('#byteCount').text(byteLen);
|
||||
|
||||
var $badge = $('#typeBadge');
|
||||
if (byteLen > 90) {
|
||||
$badge.text('LMS').removeClass('sms').addClass('lms');
|
||||
} else {
|
||||
$badge.text('SMS').removeClass('lms').addClass('sms');
|
||||
}
|
||||
}
|
||||
|
||||
function fn_getByteLength(str) {
|
||||
var byte = 0;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
if (str.charCodeAt(i) <= 0x7F) {
|
||||
byte += 1;
|
||||
} else {
|
||||
byte += 2;
|
||||
}
|
||||
}
|
||||
return byte;
|
||||
}
|
||||
126
src/main/resources/templates/web/callLog/callLogSelectList.html
Normal file
126
src/main/resources/templates/web/callLog/callLogSelectList.html
Normal file
@@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{/web/layout/homeLayout}">
|
||||
<th:block layout:fragment="layout_css">
|
||||
<link rel="stylesheet" href="/css/web/webFeedbackSelectList.css">
|
||||
<link rel="stylesheet" href="/css/web/grid.css?v1.1">
|
||||
<link rel="stylesheet" href="/css/web/call_log.css">
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_top_script">
|
||||
<script>
|
||||
let menuClass = "[[${param.menuClass}]]" == "" ? "" : "[[${param.menuClass}]]";
|
||||
let selectUseYn = "[[${selectUseYn}]]" == "" ? "N" : "[[${selectUseYn}]]";
|
||||
let insertUseYn = "[[${insertUseYn}]]" == "" ? "N" : "[[${insertUseYn}]]";
|
||||
let updateUseYn = "[[${updateUseYn}]]" == "" ? "N" : "[[${updateUseYn}]]";
|
||||
let deleteUseYn = "[[${deleteUseYn}]]" == "" ? "N" : "[[${deleteUseYn}]]";
|
||||
let downloadUseYn = "[[${downloadUseYn}]]" == "" ? "N" : "[[${downloadUseYn}]]";
|
||||
</script>
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_content">
|
||||
<!-- 센터쪽 -->
|
||||
<div class="center_box">
|
||||
<p class="page_title">통화 로그 관리</p>
|
||||
|
||||
<!-- 검색 필터 영역 -->
|
||||
<div class="cl_filter_wrap">
|
||||
<!-- 1행: 구분 필터 -->
|
||||
<div class="cl_filter_row">
|
||||
<div class="cl_filter_item">
|
||||
<label>구분1</label>
|
||||
<select id="callType" class="cl_select">
|
||||
<option value="">전체</option>
|
||||
<option value="1">상담</option>
|
||||
<option value="2">예약</option>
|
||||
<option value="3">위치안내</option>
|
||||
<option value="callback">Call Back</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cl_filter_item">
|
||||
<label>구분2</label>
|
||||
<select id="callType1" class="cl_select">
|
||||
<option value="">전체</option>
|
||||
<option value="초진">초진</option>
|
||||
<option value="재진">재진</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cl_filter_item">
|
||||
<label>구분3</label>
|
||||
<select id="callType2" class="cl_select">
|
||||
<option value="">전체</option>
|
||||
<option value="상담">상담</option>
|
||||
<option value="상담후예약">상담후예약</option>
|
||||
<option value="회차예약">회차예약</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="cl_filter_item">
|
||||
<label>고객전화번호</label>
|
||||
<input type="text" id="mCid" placeholder="전화번호 입력" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2행: 날짜 필터 -->
|
||||
<div class="cl_filter_row">
|
||||
<div class="cl_filter_item cl_date_item">
|
||||
<label>검색일자</label>
|
||||
<input type="date" id="sDate" />
|
||||
<span class="cl_date_sep">~</span>
|
||||
<input type="date" id="eDate" />
|
||||
</div>
|
||||
<div class="cl_quick_btns">
|
||||
<button type="button" onclick="fn_dayChk('t')">오늘</button>
|
||||
<button type="button" onclick="fn_dayChk('p')">어제</button>
|
||||
<button type="button" onclick="fn_dayChk('w')">이번주</button>
|
||||
<button type="button" onclick="fn_dayChk('pw')">지난주</button>
|
||||
<button type="button" onclick="fn_dayChk('m')">이번달</button>
|
||||
<button type="button" onclick="fn_dayChk('pm')">지난달</button>
|
||||
</div>
|
||||
<button type="button" id="searchBtn" class="cl_search_btn">조회</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 통계 요약 바 -->
|
||||
<div class="cl_stats_bar">
|
||||
<span>전체: <strong id="statTotal">0</strong></span>
|
||||
<span class="cl_stats_sep">|</span>
|
||||
<span>IN: <strong id="statIn">0</strong></span>
|
||||
<span class="cl_stats_detail">[초진: <strong id="statType1">0</strong> / 재진: <strong
|
||||
id="statType2">0</strong>]</span>
|
||||
<span class="cl_stats_detail">[상담: <strong id="statType11">0</strong> / 상담후예약: <strong
|
||||
id="statType12">0</strong> / 회차예약: <strong id="statType13">0</strong>]</span>
|
||||
<span class="cl_stats_sep">|</span>
|
||||
<span>OUT: <strong id="statOut">0</strong></span>
|
||||
</div>
|
||||
|
||||
<!-- ag-Grid 테이블 -->
|
||||
<div id="callLogGrid" class="cl_grid_box ag-theme-balham"></div>
|
||||
|
||||
<!-- 메모 팝업 -->
|
||||
<div class="cl_memo_overlay" id="memoOverlay" style="display:none;">
|
||||
<div class="cl_memo_popup">
|
||||
<div class="cl_memo_header">
|
||||
<h3>통화 메모</h3>
|
||||
<span class="cl_memo_record" id="memoRecordNo"></span>
|
||||
<button type="button" class="cl_memo_close" onclick="fn_closeMemo()">×</button>
|
||||
</div>
|
||||
<div class="cl_memo_body">
|
||||
<input type="hidden" id="memoRecordNoVal" />
|
||||
<textarea id="memoContent" placeholder="메모를 입력하세요" rows="6"></textarea>
|
||||
</div>
|
||||
<div class="cl_memo_footer">
|
||||
<button type="button" class="cl_memo_save_btn" onclick="fn_saveMemo()">저장</button>
|
||||
<button type="button" class="cl_memo_cancel_btn" onclick="fn_closeMemo()">취소</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="callLogForm" onsubmit="return false;"></form>
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_popup">
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_script">
|
||||
<script src="/js/web/ag-grid-community-29.3.5.min.js"></script>
|
||||
<script src="/js/web/callLog/callLogSelectList.js"></script>
|
||||
</th:block>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,89 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{/web/layout/homeLayout}">
|
||||
<th:block layout:fragment="layout_css">
|
||||
<link rel="stylesheet" href="/css/web/webFeedbackSelectList.css">
|
||||
<link rel="stylesheet" href="/css/web/grid.css?v1.1">
|
||||
<link rel="stylesheet" href="/css/web/sms_template.css">
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_top_script">
|
||||
<script>
|
||||
let menuClass = "[[${param.menuClass}]]" == "" ? "" : "[[${param.menuClass}]]";
|
||||
let selectUseYn = "[[${selectUseYn}]]" == "" ? "N" : "[[${selectUseYn}]]";
|
||||
let insertUseYn = "[[${insertUseYn}]]" == "" ? "N" : "[[${insertUseYn}]]";
|
||||
let updateUseYn = "[[${updateUseYn}]]" == "" ? "N" : "[[${updateUseYn}]]";
|
||||
let deleteUseYn = "[[${deleteUseYn}]]" == "" ? "N" : "[[${deleteUseYn}]]";
|
||||
let downloadUseYn = "[[${downloadUseYn}]]" == "" ? "N" : "[[${downloadUseYn}]]";
|
||||
</script>
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_content">
|
||||
<!-- 센터쪽 -->
|
||||
<div class="center_box">
|
||||
<p class="page_title">문자 상용구 관리</p>
|
||||
|
||||
<!-- 2패널 컨테이너 -->
|
||||
<div class="sms_two_panel">
|
||||
<!-- 좌측: 목록 -->
|
||||
<div class="sms_left_panel">
|
||||
<div class="sms_search_area">
|
||||
<div class="sms_search_box">
|
||||
<img src="/image/web/search_G.svg" alt="search" />
|
||||
<input type="text" id="searchKeyword" placeholder="제목 또는 내용" />
|
||||
</div>
|
||||
<button id="searchBtn" class="sms_search_btn">조회</button>
|
||||
<button type="button" id="newTemplateBtn" class="sms_new_btn">등록</button>
|
||||
</div>
|
||||
|
||||
<div id="smsTemplateGrid" class="sms_grid_box ag-theme-balham"></div>
|
||||
</div>
|
||||
|
||||
<!-- 우측: 상세/편집 -->
|
||||
<div class="sms_right_panel">
|
||||
<!-- 빈 상태 -->
|
||||
<div class="sms_empty_state" id="emptyState">
|
||||
<p>좌측 목록에서 상용구를 선택하거나<br />"등록" 버튼을 클릭하세요.</p>
|
||||
</div>
|
||||
|
||||
<!-- 상세 폼 -->
|
||||
<div class="sms_detail_form" id="detailForm" style="display:none;">
|
||||
<div class="sms_detail_title_bar">
|
||||
<h3 id="detailTitle">상용구 등록</h3>
|
||||
</div>
|
||||
<input type="hidden" id="muSmsTemplateId" />
|
||||
<div class="sms_form_row">
|
||||
<label for="templateTitle">제목</label>
|
||||
<input type="text" id="templateTitle" placeholder="상용구 제목을 입력하세요" maxlength="100" />
|
||||
</div>
|
||||
<div class="sms_form_row">
|
||||
<label for="templateContent">내용</label>
|
||||
<textarea id="templateContent" placeholder="상용구 내용을 입력하세요" rows="8"></textarea>
|
||||
<div class="byte_info">
|
||||
<span><span id="byteCount">0</span> byte</span>
|
||||
<span class="type_badge sms" id="typeBadge">SMS</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sms_form_row sms_info_row" id="infoRow" style="display:none;">
|
||||
<span>등록자: <strong id="regName">-</strong></span>
|
||||
<span>등록일: <strong id="regDate">-</strong></span>
|
||||
<span>수정일: <strong id="modDate">-</strong></span>
|
||||
</div>
|
||||
<div class="sms_btn_group">
|
||||
<button type="button" id="saveBtn" class="sms_save_btn">저장</button>
|
||||
<button type="button" id="deleteBtn" class="sms_delete_btn" style="display:none;">삭제</button>
|
||||
<button type="button" id="cancelBtn" class="sms_cancel_btn">취소</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="smsTemplateForm" onsubmit="return false;"></form>
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_popup">
|
||||
</th:block>
|
||||
<th:block layout:fragment="layout_script">
|
||||
<script src="/js/web/ag-grid-community-29.3.5.min.js"></script>
|
||||
<script src="/js/web/smsTemplate/smsTemplateSelectList.js"></script>
|
||||
</th:block>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user