본문으로 건너뛰기

부운영자 1:1 문의 기능 추가

PHP 7 · GODO25
변경 파일 수: 6개
변경 파일 목록
총 6개
변경 파일 코드
추가삭제
Admin/base/_index_qna_layer.php+154
변경 전_index_qna_layer.php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
변경 후_index_qna_layer.php
<script src="<?= gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/aggregator-message-router.js') ?>"></script>
<div>
<input type="hidden" name="mode" value="grow_qna_register" />
<div class="layer_helper_write" style="display:none;">
<script>
$(document).ready(function() {
var qnaIframeOrigin = '';
var qnaClientInfo = null;
var qnaAjax = null;
 
// 공용 라우터(aggregator-message-router.js) 콜백 등록.
 
// 접속 정보 요청 -> 응답
IframeMessageRouter._config.onRequestClientInfo = function () {
sendClientInfo();
};
 
// 모달 닫기
IframeMessageRouter._config.onModalClose = function () {
modalClose();
};
 
// 상세 팝업(opener)이 relay 한 전송 메시지 처리
IframeMessageRouter._config.onSendToParent = function (message) {
var payload = (message && message.payload) || {};
 
// payload 에 따라 문의 목록 iframe 에 완료 알림
switch (payload.action) {
case 'delete' : notifyInquiryList({ category: 'INQUIRY', type: 'DELETE_COMPLETE' }); break;
case 'reinquiry' : notifyInquiryList({ category: 'INQUIRY', type: 'REINQUIRY_COMPLETE' }); break;
}
 
// payload 에 따라 어드민 개인정보 접근기록(es_adminLog) 작성
recordAccessLog(payload);
};
 
// 상세 페이지를 새 윈도우 팝업으로 연다.
function openInquiryDetail(query) {
var qnaNo = query && query.qnaNo;
if (!qnaNo) {
return;
}
var params = $.param({ endpoint: 'detail', qnaNo: qnaNo });
window.open('/member/layer_qna.php?' + params, '_blank', 'width=1000,height=550,scrollbars=yes,resizable=yes');
}
 
// 레이어팝업을 닫는다. (자식 iframe 의 MODAL_CLOSE 수신 시)
function modalClose() {
$('.layer_helper_write').hide();
$('body').removeAttr('style');
}
 
// endpoint 로 iframe URL/접속정보를 조회해 src 로 주입한다. (최초 로드/재로딩 공통)
function loadInquiryIframe(endpoint) {
if (qnaAjax) {
qnaAjax.abort();
}
var currentAjax = $.ajax({
url: '/member/layer_qna.php',
type: 'GET',
dataType: 'json',
data: { endpoint: endpoint }
});
qnaAjax = currentAjax;
currentAjax.done(function (res) {
if (!res || !res.success || !res.data || !res.data.url) {
return;
}
qnaClientInfo = res.data.postParameters || null;
 
var parsedUrl = null;
try {
parsedUrl = new URL(res.data.url, window.location.origin);
qnaIframeOrigin = parsedUrl.origin;
} catch (e) {
qnaIframeOrigin = '';
}
// http/https 스킴만 iframe 에 로드 (javascript: 등 위험 스킴 차단)
if (parsedUrl && (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:')) {
$('.helper_write_iframe').attr('src', parsedUrl.href);
}
}).always(function () {
if (qnaAjax === currentAjax) {
qnaAjax = null;
}
});
}
 
// 완료 메시지(삭제/재문의완료)를 문의 목록 iframe 에 전달해 목록 API 를 재호출시킨다.
function notifyInquiryList(message) {
var inquiryIframe = $('.helper_write_iframe').get(0);
if (!inquiryIframe || !inquiryIframe.contentWindow || !qnaIframeOrigin) {
return;
}
inquiryIframe.contentWindow.postMessage(message, qnaIframeOrigin);
}
 
// 접속페이지 유형(list·detail:조회, search:검색, delete:삭제, inquiry·reinquiry:등록)을 접속기록 API 로 기록한다.
function recordAccessLog(payload) {
var accessLogActions = ['list', 'search', 'detail', 'delete', 'inquiry', 'reinquiry'];
if (!payload || accessLogActions.indexOf(payload.action) === -1) {
return;
}
$.ajax({
url: '/policy/access_log_ps.php',
type: 'POST',
dataType: 'json',
data: {
action: payload.action,
adminIds: payload.adminIds || [],
searchValue: payload.searchValue || ''
}
});
}
 
// 접속 정보(CLIENT_INFO)를 자식 iframe 에 응답한다. 서버 미응답 값은 fallback 처리.
function sendClientInfo() {
var inquiryIframe = $('.helper_write_iframe').get(0);
if (!inquiryIframe || !inquiryIframe.contentWindow || !qnaIframeOrigin) {
return;
}
var info = qnaClientInfo || {};
inquiryIframe.contentWindow.postMessage({
category: 'INQUIRY',
type: 'CLIENT_INFO',
payload: {
ip: info.ip || '',
device: info.device || 'PC',
userAgent: info.agent || navigator.userAgent,
isSubAdmin: !!info.isSubAdmin,
adminId: info.managerId,
hp: info.cellPhone || '',
email: info.email || '',
}
}, qnaIframeOrigin);
}
 
// 1:1문의 아이콘 클릭 시 레이어팝업 노출
$('.btn_adm_qna').on('click', function (){
var buttonId = this.id;
var layerWidth = (buttonId === 'inquiry') ? '760px' : '1000px';
$('.helper_write_wrap.helper_write_wrap_iframe').css('width', layerWidth);
$('.layer_helper_write').show();
// 1:1문의 iframe URL/접속정보를 조회해 src 로 주입
loadInquiryIframe(buttonId);
});
});
</script>
<div class="helper_write_wrap_dim"></div>
<div class="helper_write_wrap helper_write_wrap_iframe" style="padding:unset;">
<iframe class="helper_write_iframe" src="about:blank" style="flex:none; height:100%"> </iframe>
</div>
</div>
</div>
 
Admin/base/index.php+5-4
변경 전index.php
<?php include($serviceState); ?>
<!-- 운영 필수 서비스 현황 내용 끝 -->
 
<!-- 그로우 상점 1:1문의 시작 -->
<?php include($growData);?>
<!-- 그로우 상점 1:1문의 끝 -->
 
<?php if(gd_is_provider() === false) { ?>
<div class="main-section">
<div class="table-title">
고객센터
<a class="btn btn-white btn-sm <?php if ($manager['isSuper'] == 'y') { ?>btn_grow<?php } else {?>btn_err<?php }?>" style="margin-left:5px;">1:1 문의</a>
 
<div id="panel_link_customerLink" class="pull-right"></div>
</div>
<!-- gorw 상점 유무에 따라 고객센터 번호 호출 -->
 
변경 후index.php
<?php include($serviceState); ?>
<!-- 운영 필수 서비스 현황 내용 끝 -->
 
<!-- 상점 1:1문의 시작 -->
<?php include($qnaPopup);?>
<!-- 상점 1:1문의 끝 -->
 
<?php if(gd_is_provider() === false) { ?>
<div class="main-section">
<div class="table-title">
고객센터
<a class="btn btn-white btn-sm btn_adm_qna" id="inquiry" style="margin-left:5px;">1:1 문의</a>
<a class="btn btn-white btn-sm btn_adm_qna" id="list" style="margin-left:5px;">문의 내역</a>
<div id="panel_link_customerLink" class="pull-right"></div>
</div>
<!-- gorw 상점 유무에 따라 고객센터 번호 호출 -->
 
Admin/base/popup_qna_detail_iframe.php+14
변경 전popup_qna_detail_iframe.php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
변경 후popup_qna_detail_iframe.php
<style>
/* 팝업 창이 iframe 높이(100%)의 기준이 되도록 body 를 뷰포트에 고정하고, 창 세로 스크롤은 막는다 (스크롤은 iframe 내부가 담당) */
body { overflow-y: hidden; height: 100vh; }
</style>
<script src="<?= gd_set_browser_cache(PATH_ADMIN_GD_SHARE . 'ncds/script/common/aggregator-message-router.js') ?>"></script>
<!-- 창 크기가 높이를 정하는 팝업이므로 RESIZE 높이 동기화 제외 -->
<iframe name="qnaDetailPopup" src="<?= htmlspecialchars($pageUrl, ENT_QUOTES, 'UTF-8') ?>" frameborder="0" marginwidth="0" marginheight="0" width="100%" style="height: 100%;" data-frame-height-sync="off"></iframe>
<script>
// 공용 라우터가 수신한 메시지를 처리할 콜백을 인라인으로 주입한다.
// 상세 닫기(MODAL_CLOSE): 팝업 창 종료
IframeMessageRouter._config.onModalClose = function () {
window.close();
};
</script>
 
Component/Admin/AdminLogDAO.php+15-5
변경 전AdminLogDAO.php
use Framework\Utility\ArrayUtils;
use Framework\Utility\DateTimeUtils;
use Framework\Utility\StringUtils;
 
use Origin\Service\Member\ManagerEditPolicy;
 
/**
// 기존 : 운영자정보 접속기록 탭에 관리자 노출, 공급사는 회원정보 접속기록에 노출
// 변경 : 관리자, 공급사 두개 다 운영자정보 접속기록에 노출되도록 작업
// 관리자에 추가된다면, 공급사도 기획측에 확인해서 추가 필요!
$adminListPage = ['/policy/manage_list.php', '/policy/manage_register.php', '/policy/manage_ps.php', '/policy/manage_permission.php', '/share/layer_manage.php'];
$providerListPage = ['/provider/policy/manage_list.php', '/provider/policy/manage_register.php', '/provider/policy/manage_ps.php', '/provider/policy/manage_permission.php', '/provider/share/layer_manage.php'];
 
$adminListPage = array_merge($adminListPage, $providerListPage);
 
if ($request['view'] == 'adminList') {
$where[] = 'a.baseUri IN (?,?,?,?,?,?,?,?,?,?)';
} else { //default
$where[] = 'a.baseUri NOT IN (?,?,?,?,?,?,?,?,?,?)';
}
foreach($adminListPage as $adminListPageVal) {
$this->_db->bind_param_push($arrBind, 's', $adminListPageVal);
case 'manage_ps.php':
case 'manage_list.php':
case 'layer_manage.php':
 
$lVal['data'] = json_decode($lVal['data'], true);
if ($lVal['page'] == 'adminInfo' || empty($lVal['data']['searchData']) === false) {
$data[$lKey]['displayDetailLogFl'] = 'y';
case 'layer_manage.php':
$result['searchTargetMsg'] = '처리 대상 : '. $result['searchData'];
break;
 
 
 
 
 
 
 
 
case 'manage_register.php':
$manager = \App::load('\\Component\\Member\\Manager');
$managerIdArr = $manager->getManagerId($data['data']['GET']['sno']);
// 기존 : 운영자정보 접속기록 탭에 관리자 노출, 공급사는 회원정보 접속기록에 노출
// 변경 : 관리자, 공급사 두개 다 운영자정보 접속기록에 노출되도록 작업
// 관리자에 추가된다면, 공급사도 기획측에 확인해서 추가 필요!
$adminListPage = ['/policy/manage_list.php', '/policy/manage_register.php', '/policy/manage_ps.php', '/policy/manage_permission.php', '/share/layer_manage.php'];
$providerListPage = ['/provider/policy/manage_list.php', '/provider/policy/manage_register.php', '/provider/policy/manage_ps.php', '/provider/policy/manage_permission.php', '/provider/share/layer_manage.php'];
 
$adminListPage = array_merge($adminListPage, $providerListPage);
 
$where[] = 'a.baseUri NOT IN (?,?,?,?,?,?,?,?,?,?)';
 
foreach($adminListPage as $adminListPageVal) {
$this->_db->bind_param_push($arrBind, 's', $adminListPageVal);
 
변경 후AdminLogDAO.php
use Framework\Utility\ArrayUtils;
use Framework\Utility\DateTimeUtils;
use Framework\Utility\StringUtils;
use Origin\Enum\Policy\AccessLogAction;
use Origin\Service\Member\ManagerEditPolicy;
 
/**
// 기존 : 운영자정보 접속기록 탭에 관리자 노출, 공급사는 회원정보 접속기록에 노출
// 변경 : 관리자, 공급사 두개 다 운영자정보 접속기록에 노출되도록 작업
// 관리자에 추가된다면, 공급사도 기획측에 확인해서 추가 필요!
$adminListPage = ['/policy/manage_list.php', '/policy/manage_register.php', '/policy/manage_ps.php', '/policy/manage_permission.php', '/share/layer_manage.php', '/policy/access_log_ps.php'];
$providerListPage = ['/provider/policy/manage_list.php', '/provider/policy/manage_register.php', '/provider/policy/manage_ps.php', '/provider/policy/manage_permission.php', '/provider/share/layer_manage.php'];
 
$adminListPage = array_merge($adminListPage, $providerListPage);
 
if ($request['view'] == 'adminList') {
$where[] = 'a.baseUri IN (?,?,?,?,?,?,?,?,?,?,?)';
} else { //default
$where[] = 'a.baseUri NOT IN (?,?,?,?,?,?,?,?,?,?,?)';
}
foreach($adminListPage as $adminListPageVal) {
$this->_db->bind_param_push($arrBind, 's', $adminListPageVal);
case 'manage_ps.php':
case 'manage_list.php':
case 'layer_manage.php':
case 'access_log_ps.php': // 1:1 문의 접속기록 (대상 관리자 아이디가 남은 경우)
$lVal['data'] = json_decode($lVal['data'], true);
if ($lVal['page'] == 'adminInfo' || empty($lVal['data']['searchData']) === false) {
$data[$lKey]['displayDetailLogFl'] = 'y';
case 'layer_manage.php':
$result['searchTargetMsg'] = '처리 대상 : '. $result['searchData'];
break;
case 'access_log_ps.php':
$result['searchTargetMsg'] = '처리 대상 : '. $result['searchData'];
// 검색어 유무와 관계없이 검색어(...) 형식으로 고정하고, 공통 처리의 ' (키워드)' 조립은 막음
if (($data['data']['POST']['action'] ?? '') === AccessLogAction::SEARCH) {
$result['searchConditionMsg'] = '처리조건 : 검색어(' . ($data['data']['GET']['keyword'] ?? '') . ')';
}
$keyword = '';
break;
case 'manage_register.php':
$manager = \App::load('\\Component\\Member\\Manager');
$managerIdArr = $manager->getManagerId($data['data']['GET']['sno']);
// 기존 : 운영자정보 접속기록 탭에 관리자 노출, 공급사는 회원정보 접속기록에 노출
// 변경 : 관리자, 공급사 두개 다 운영자정보 접속기록에 노출되도록 작업
// 관리자에 추가된다면, 공급사도 기획측에 확인해서 추가 필요!
$adminListPage = ['/policy/manage_list.php', '/policy/manage_register.php', '/policy/manage_ps.php', '/policy/manage_permission.php', '/share/layer_manage.php', '/policy/access_log_ps.php'];
$providerListPage = ['/provider/policy/manage_list.php', '/provider/policy/manage_register.php', '/provider/policy/manage_ps.php', '/provider/policy/manage_permission.php', '/provider/share/layer_manage.php'];
 
$adminListPage = array_merge($adminListPage, $providerListPage);
 
$where[] = 'a.baseUri NOT IN (?,?,?,?,?,?,?,?,?,?,?)';
 
foreach($adminListPage as $adminListPageVal) {
$this->_db->bind_param_push($arrBind, 's', $adminListPageVal);
 
Component/Admin/AdminMenu.php+26
변경 전AdminMenu.php
return $menuList[0]['adminMenuNo'];
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/**
* getMainStatisticsAccessMenu
*
 
변경 후AdminMenu.php
return $menuList[0]['adminMenuNo'];
}
 
/**
* 1차 메뉴 코드를 통해 adminMenu 고유 코드를 반환
*
* @param string $topMenu 1차 메뉴 코드
* @return string 1차 메뉴의 adminMenuNo
*/
public function getTopAdminMenuNo(string $topMenu): string
{
// 1차 메뉴 코드 및 뎁스 구분
$this->arrWhere[] = 'f.adminMenuCode = ?';
$this->db->bind_param_push($this->arrBind, 's', $topMenu);
$this->arrWhere[] = 'f.adminMenuDepth = ?';
$this->db->bind_param_push($this->arrBind, 'i', 1);
 
$this->db->strField = 'f.adminMenuNo';
$this->db->strWhere = implode(' AND ', $this->arrWhere);
$query = $this->db->query_complete();
$strSQL = 'SELECT ' . array_shift($query) . ' FROM ' . DB_ADMIN_MENU . ' as f ' . implode(' ', $query);
$menuData = $this->db->query_fetch($strSQL, $this->arrBind, false);
unset($this->arrBind);
unset($this->arrWhere);
 
// 조회 결과가 없으면 빈 배열이 반환되므로 반환 타입(string) 보장을 위해 방어
return (string) ($menuData['adminMenuNo'] ?? '');
}
 
/**
* getMainStatisticsAccessMenu
*
 
Controller/Admin/Base/IndexController.php+1-1
변경 전IndexController.php
$this->getView()->setDefine('serviceState', 'base/_index_service_state.php'); // 운영 필수 서비스 현황
$this->getView()->setDefine('serviceBoard', 'base/_index_service_board.php'); // 문의 / 답변 관리
$this->getView()->setDefine('servicePlusShop', 'base/_index_service_plus_shop.php'); // 플러스샵 이용현황
$this->getView()->setDefine('growData', 'base/_index_grow_qna.php'); // 그로우 상점 1:1문의
 
$this->setData('svcInfos', $svcInfos);
$this->setData('svcStates', $svcStates);
 
변경 후IndexController.php
$this->getView()->setDefine('serviceState', 'base/_index_service_state.php'); // 운영 필수 서비스 현황
$this->getView()->setDefine('serviceBoard', 'base/_index_service_board.php'); // 문의 / 답변 관리
$this->getView()->setDefine('servicePlusShop', 'base/_index_service_plus_shop.php'); // 플러스샵 이용현황
$this->getView()->setDefine('qnaPopup', 'base/_index_qna_layer.php'); // 상점 1:1문의
 
$this->setData('svcInfos', $svcInfos);
$this->setData('svcStates', $svcStates);