공지사항 신규 개발

This commit is contained in:
kimjhjjang
2022-11-01 13:23:58 +09:00
parent c916d16a46
commit d1d62c76c8
57 changed files with 3721 additions and 319 deletions

View File

@@ -4,42 +4,41 @@ const config = {
//baseURL: 'http://localhost:7070',
// baseURL: apiBaseUrl,
headers: {
'X-Requested-With': 'XMLHttpRequest'
},
timeout: 120000 // timeout은 120초로 설정
'X-Requested-With': 'XMLHttpRequest',
},
timeout: 120000, // timeout은 120초로 설정
};
const httpClient = axios.create(config);
const authInterceptor = config => {
const authInterceptor = (config) => {
// frontend와 backend의 origin이 다른 경우
// devServer.proxy 설정을 하던지 baseURL과 withCredentials 설정을 해야 한다.
// cookie, header 등에 자격정보 설정이 필요한 api는 true 설정으로 호출해야 하고
// 자격정보 설정이 필요없는 api는 withCredentials=false 설정으로 호출해야 한다.
// config.withCredentials = !config.url.startsWith('/api/public/');
// console.log("Test Url : "+ config.url);
/*if(config.url == '/api/auth/login'){
config.baseURL = "http://localhost:3000";
}*/
return config;
};
const tokenInterceptor = config => {
const tokenInterceptor = (config) => {
// console.log('http : ',sessionStorage.authToken);
if(sessionStorage.authToken != null) {
config.headers.Authorization = 'Bearer '+ sessionStorage.authToken;
}else if(sessionStorage.authToken == null && sessionStorage.refreshToken != null){
config.headers.Authorization = 'Bearer '+ sessionStorage.refreshToken;
if (sessionStorage.authToken != null) {
config.headers.Authorization = 'Bearer ' + sessionStorage.authToken;
} else if (sessionStorage.authToken == null && sessionStorage.refreshToken != null) {
config.headers.Authorization = 'Bearer ' + sessionStorage.refreshToken;
}
return config;
}
};
const loggerInterceptor = config => {
const loggerInterceptor = (config) => {
//console.log('testProp:', testProp);
console.log('request url:', config.url, 'params:', config.data, 'config: ', config);
//console.log('request url:', config.url, 'params:', config.data, 'config: ', config);
return config;
};
@@ -49,24 +48,24 @@ const loadingLayer = (type, config) => {
get: httpClient.get(url, { params: { ... }, headers: {"show-layer": "Yes"} }) // in 2nd property
post: httpClient.post(url, params, { headers: {"show-layer": "Yes"} }) // 3rd property
*/
if(type){
document.querySelector('html > body').style.overflow = 'hidden'; // 스크롤 block
if (type) {
document.querySelector('html > body').style.overflow = 'hidden'; // 스크롤 block
document.getElementsByClassName('loadingDimmed')[0].style.display = 'block';
document.getElementsByClassName('sp-3balls')[0].style.display = 'block';
}else{
} else {
document.querySelector('html > body').style.removeProperty('overflow'); // 스크롤 allow
document.getElementsByClassName('loadingDimmed')[0].style.display = 'none';
document.getElementsByClassName('sp-3balls')[0].style.display = 'none';
}
};
const urlInterceptor = config => {
if(sessionStorage.fromUrl != null){
const urlInterceptor = (config) => {
if (sessionStorage.fromUrl != null) {
config.params.fromUrl = sessionStorage.fromUrl;
}
return config;
}
const loadingLayerInterceptor = config => {
};
const loadingLayerInterceptor = (config) => {
loadingLayer(true, config);
return config;
};
@@ -80,61 +79,61 @@ httpClient.interceptors.request.use(loadingLayerInterceptor);
/** Adding the response interceptors */
httpClient.interceptors.response.use(
response => {
loadingLayer(false, response.config);
console.log('response status:', response.status, 'data:', response.data);
console.log('response config url :',response.config.url);
if(response.config.url == '/api/v1/bo/comm/refreshToken'){
if(response.data.data != null && typeof response.data.data != undefined){
(response) => {
loadingLayer(false, response.config);
//console.log('response status:', response.status, 'data:', response.data);
//console.log('response config url :',response.config.url);
if (response.config.url == '/api/v1/bo/comm/refreshToken') {
if (response.data.data != null && typeof response.data.data != undefined) {
sessionStorage.setItem('authToken', response.data.data);
window.location.reload();
}else{
delete sessionStorage.authToken;
} else {
delete sessionStorage.authToken;
window.top.location.href = '/login';
}
}
}
return response;
},
error => {
(error) => {
console.log(error);
//alert(error);
if(error.message === 'Network Error'){
alert('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해주세요.');
if (error.message === 'Network Error') {
alert('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해주세요.');
delete sessionStorage.authToken;
window.top.location.href = '/login';
}
window.top.location.href = '/login';
}
if (error.response != undefined && error.response != null) loadingLayer(false, error.response.config);
else loadingLayer(false, error.config);
if (error.code === 'ECONNABORTED') {
alert('서비스가 지연되고 있습니다. 잠시 후 확인하시고 다시 시도해주세요.');
return Promise.reject(error);
}else if(error.response.status == 401){
alert('세션이 만료되었습니다.');
} else if (error.response.status == 401) {
alert('세션이 만료되었습니다.');
delete sessionStorage.authToken;
window.top.location.href = '/login';
} else if (error.response.status == 418) {
} else if (error.response.status == 418) {
delete sessionStorage.authToken;
if(error.config.url == '/api/v1/bo/comm/refreshToken'){
if (error.config.url == '/api/v1/bo/comm/refreshToken') {
alert('세션이 만료되었습니다.');
delete sessionStorage.authToken;
delete sessionStorage.refreshToken;
return window.top.location.href = '/login';
return (window.top.location.href = '/login');
//return Promise.reject(error);
}
var params = {};
httpClient.post('/api/v1/bo/comm/refreshToken',params);
}else if (error.response.status == 500) {
window.top.location.href = '/view/error/500';
httpClient.post('/api/v1/bo/comm/refreshToken', params);
} else if (error.response.status == 500) {
window.top.location.href = '/view/error/500';
}
// else if (error.message == 'Network Error') {
// alert('네트워크 오류가 발생했습니다. 잠시 후 다시 시도해주세요.');
// return Promise.reject(error);
// }
else {
// }
else {
delete sessionStorage.authToken;
console.log('response error:', error);
console.log('response error:', error);
return Promise.reject(error);
}
}

View File

@@ -37,7 +37,7 @@ export default {
'pageRange', // next or pre 이동할 페이지 단위
],
components: {
VRuntimeTemplate
VRuntimeTemplate,
},
data() {
return {
@@ -59,12 +59,11 @@ export default {
headerData: '',
bodyData: '',
pagingData: '',
nextPageRange: 1
nextPageRange: 1,
};
},
created() {
this.cleanData();
this.cleanData();
if (this.initialRequest == true) {
this.readData();
}
@@ -74,7 +73,7 @@ export default {
this.currentIndex = 1;
this.curPerPage = this.pagePerRows;
this.readData();
}
},
},
methods: {
getData() {
@@ -132,14 +131,14 @@ export default {
var vm = this;
httpClient
//.get(this.url, { params: this.getParams, headers: { 'Show-Layer': 'Yes' }})
.post(this.url, this.getParams, {headers: { 'Show-Layer': 'Yes' }})
.then(response => {
.post(this.url, this.getParams, { headers: { 'Show-Layer': 'Yes' } })
.then((response) => {
let resp = response.data;
//if (resp != null && resp.result == true) {
if (resp != null && resp.retCode == '0000') {
let data = resp.data;
//let conts = data.contents;
let conts = data.list;
let conts = data.list;
vm.bodyList = conts;
bodyStr = vm.makeBodyView();
@@ -151,19 +150,19 @@ export default {
vm.totalCount = data.pagination.totalCount;
pageStr = vm.makePagingView();
}*/
if (vm.pagination == true) {
if (vm.pagination == true) {
vm.currentIndex = data.paging.page == 0 ? 1 : data.paging.page;
vm.totalCount = data.paging.totalCnt;
pageStr = vm.makePagingView();
if(typeof this.pageRange != 'undefined'){
if (typeof this.pageRange != 'undefined') {
vm.nextPageRange = this.pageRange;
}
}
// 조회결과 없음.
}else if(resp != null && resp.retCode == '1004'){
// 조회결과 없음.
} else if (resp != null && resp.retCode == '1004') {
let data = resp.data;
//let conts = data.contents;
let conts = data.list;
let conts = data.list;
vm.bodyList = conts;
bodyStr = vm.makeBodyView();
@@ -171,7 +170,8 @@ export default {
}
vm.setTableView(colStr, headerStr, bodyStr, pageStr);
}).catch(response => {
})
.catch((response) => {
bodyStr = vm.makeBodyView();
if (vm.pagination == true) {
vm.currentIndex = 1;
@@ -541,12 +541,12 @@ export default {
str = '';
}
return str;
},
},
makePagingView() {
let pData = '<div class="pagination">';
let totalPage = Math.ceil(this.totalCount / this.curPerPage);
let totalPage = Math.ceil(this.totalCount / this.curPerPage);
if (totalPage < 1) {
totalPage = 1;
}
@@ -556,7 +556,7 @@ export default {
if (last > totalPage) {
last = totalPage;
}
let first = last - (this.pageCount - 1);
if (first < 1) {
first = 1;
@@ -567,32 +567,31 @@ export default {
prev = 1;
}
// let next = last + 1;
// let next = last + 1;
let next = parseInt(this.currentIndex) + this.nextPageRange;
if (next > totalPage) {
next = totalPage;
}
pData += '<div class="arrow-btn">'
pData += '<div class="arrow-btn">';
pData += '<button href="javascript:void(0);" @click="movePage(1)" class="btn-first"></button>';
pData += '<button href="javascript:void(0);" @click="movePage(' + prev + ')" class="btn-prev"></button>';
pData += '</div>'
pData += '<ul>'
pData += '</div>';
pData += '<ul>';
for (var i = first; i <= last; i++) {
let actCls = '';
if (i == this.currentIndex) {
let actCls = '';
if (i == this.currentIndex) {
actCls = 'class="active"';
}
pData += '<li ' + actCls + '><a href="javascript:void(0);" @click="movePage(' + i + ')" >' + i + '</a></li>';
}
pData += '</ul>'
pData += '<div class="arrow-btn">'
pData += '</ul>';
pData += '<div class="arrow-btn">';
pData += '<button @click="movePage(' + next + ')" class="btn-next"></button>';
pData +=
'<button @click="movePage(' + totalPage + ')" class="btn-last"></button>';
pData += '</div>'
pData += '<button @click="movePage(' + totalPage + ')" class="btn-last"></button>';
pData += '</div>';
pData += '</div>';
return pData;
},
@@ -683,8 +682,8 @@ export default {
_currentPage: this.currentIndex,
_options: {
itemsPerPage: this.curPerPage,
sort: this.getParams['sort']
}
sort: this.getParams['sort'],
},
};
return rslt;
@@ -695,10 +694,9 @@ export default {
if (myChild != null) {
myChild.style.top = rect.y + 20 + 'px';
}
}
}
},
},
};
</script>
<style>
</style>
<style></style>

View File

@@ -1,20 +1,32 @@
<template>
<nav>
<ul v-if="menuList.length > 0" class="main_menu">
<li v-for="child in menuList" :key="child.menuNo" :class="child.classNm">
<div class="menu_btn" ></div>
<a href="javascript:void(0);" class="menu_target" @click="actionMenu" :data-menu-no="child.menuNo">{{child.menuNm}}</a>
<nav>
<ul v-if="menuList.length > 0" class="main_menu">
<li v-for="child in menuList" :key="child.menuNo" :class="child.classNm">
<div class="menu_btn"></div>
<a href="javascript:void(0);" class="menu_target" @click="actionMenu" :data-menu-no="child.menuNo">{{
child.menuNm
}}</a>
<div class="sub_menu_wrap">
<ul class="sub_menu" v-if="child.children.length > 0">
<li v-for="child2 in child.children" :key="child2.menuNo">
<router-link :to="`${child2.menuUrl}`">{{child2.menuNm}}</router-link>
</li>
</ul>
</div>
</li>
</ul>
</nav>
<div class="sub_menu_wrap">
<ul class="sub_menu" v-if="child.children.length > 0">
<li v-for="child2 in child.children" :key="child2.menuNo">
<router-link :to="`${child2.menuUrl}`">{{ child2.menuNm }}</router-link>
</li>
</ul>
</div>
</li>
<li>
<a href="javascript:void(0);" class="menu_target" @click="actionMenu">홈페이지 관리</a>
<div class="sub_menu_wrap">
<ul class="sub_menu">
<li>
<router-link to="/homeMgt/notice">공지사항</router-link>
</li>
</ul>
</div>
</li>
</ul>
</nav>
</template>
<script>
//import "../assets/js/script.js";
@@ -24,32 +36,29 @@ import { mapGetters } from 'vuex';
export default {
name: 'Nav',
props: {
},
props: {},
data() {
return {
isLogin : false,
isAuthChk : false,
isLogin: false,
isAuthChk: false,
isErrPage: false,
navActive: false,
menuList: [],
tempList: [],
nowPath:'',
}
nowPath: '',
};
},
created() {
this.isLogin = !!tokenSvc.getToken();
let curPage = location.pathname;
if (this.isLogin && curPage != "/login") {
this.$store.commit("login/isLogin", true);
if (this.isLogin && curPage != '/login') {
this.$store.commit('login/isLogin', true);
this.setMenuData();
} else {
this.$store.commit("login/isLogin", false);
this.$store.commit('login/isLogin', false);
this.isLogin = false;
}
},
mounted() {
//this.menuhighlight();
@@ -62,7 +71,7 @@ export default {
},
watch: {
getLogin(data) {
if (data != null && data != '' && data == true) {
if (data != null && data != '' && data == true) {
this.isLogin = true;
this.setMenuData();
} else {
@@ -76,99 +85,111 @@ export default {
} else {
this.isErrPage = false;
}
},
},
},
methods: {
setMenuData() {
api.menus().then(response => {
const rootMenu = response.data.data;
if (rootMenu != null && rootMenu.children != null && rootMenu.children.length > 0) {
api
.menus()
.then((response) => {
const rootMenu = response.data.data;
if (rootMenu != null && rootMenu.children != null && rootMenu.children.length > 0) {
this.tempList = rootMenu.children;
var nowUrl = this.$route.fullPath;
for(var i=0; i<this.tempList.length; i++){
var menuNo = this.tempList[i].menuNo;
var classNm = '';
switch(menuNo){
case 1001 : classNm = 'customer';
if(nowUrl.indexOf('custMgt') > -1){
classNm += ' is-current';
}
break;
case 1002 : classNm = 'attract';
if(nowUrl.indexOf('attractMgt') > -1){
classNm += ' is-current';
}
break;
case 1003 : classNm = 'service';
if(nowUrl.indexOf('servMgt') > -1){
classNm += ' is-current';
}
break;
case 1004 : classNm = 'calculate';
if(nowUrl.indexOf('calculate') > -1){
classNm += ' is-current';
}
break;
case 1005 : classNm = 'channel';
if(nowUrl.indexOf('channelMgt') > -1){
classNm += ' is-current';
}
break;
case 1006 : classNm = 'key';
if(nowUrl.indexOf('sendNumMgt') > -1){
classNm += ' is-current';
}
break;
case 1007 : classNm = 'moniter';
if(nowUrl.indexOf('mntrng') > -1){
classNm += ' is-current';
}
break;
case 1008 : classNm = 'risk';
if(nowUrl.indexOf('riskMgt') > -1){
classNm += ' is-current';
}
break;
case 1009 : classNm = 'stats';
if(nowUrl.indexOf('stats') > -1){
classNm += ' is-current';
}
break;
case 1010 : classNm = 'system';
if(nowUrl.indexOf('sysMgt') > -1){
classNm += ' is-current';
}
break;
default : classNm = 'customer';
classNm += ' is-current';
}
for (var i = 0; i < this.tempList.length; i++) {
var menuNo = this.tempList[i].menuNo;
var classNm = '';
switch (menuNo) {
case 1001:
classNm = 'customer';
if (nowUrl.indexOf('custMgt') > -1) {
classNm += ' is-current';
}
break;
case 1002:
classNm = 'attract';
if (nowUrl.indexOf('attractMgt') > -1) {
classNm += ' is-current';
}
break;
case 1003:
classNm = 'service';
if (nowUrl.indexOf('servMgt') > -1) {
classNm += ' is-current';
}
break;
case 1004:
classNm = 'calculate';
if (nowUrl.indexOf('calculate') > -1) {
classNm += ' is-current';
}
break;
case 1005:
classNm = 'channel';
if (nowUrl.indexOf('channelMgt') > -1) {
classNm += ' is-current';
}
break;
case 1006:
classNm = 'key';
if (nowUrl.indexOf('sendNumMgt') > -1) {
classNm += ' is-current';
}
break;
case 1007:
classNm = 'moniter';
if (nowUrl.indexOf('mntrng') > -1) {
classNm += ' is-current';
}
break;
case 1008:
classNm = 'risk';
if (nowUrl.indexOf('riskMgt') > -1) {
classNm += ' is-current';
}
break;
case 1009:
classNm = 'stats';
if (nowUrl.indexOf('stats') > -1) {
classNm += ' is-current';
}
break;
case 1010:
classNm = 'system';
if (nowUrl.indexOf('sysMgt') > -1) {
classNm += ' is-current';
}
break;
default:
classNm = 'customer';
classNm += ' is-current';
}
this.tempList[i].classNm = classNm;
}
this.tempList[i].classNm = classNm;
}
this.menuList = rootMenu.children;
} else {
window.top.location.href = '/';
} else {
window.top.location.href = '/';
this.menuList = null;
}
})
.catch((rsponse) => {
this.menuList = null;
}
}).catch(rsponse => {
this.menuList = null;
})
});
},
clickMenu(link){
var location = this.$route.fullPath;
if(link != location){
this.$router.push({
path: link
clickMenu(link) {
var location = this.$route.fullPath;
if (link != location) {
this.$router.push({
path: link,
});
}
},
reload(){
reload() {
var location = this.$route.fullPath;
if (location == "/" || location == "") {
if (location == '/' || location == '') {
// nothing
} else {
this.$router.replace('/');
@@ -176,25 +197,24 @@ export default {
}
},
actionMenu(e){
actionMenu(e) {
const menuList = document.querySelectorAll('.main_menu .is-current');
if(e.target.classList.contains('menu_target') || e.target.classList.contains('menu_btn')){
if (e.target.classList.contains('menu_target') || e.target.classList.contains('menu_btn')) {
const menuListCheck = e.target.parentNode;
if(menuListCheck.classList.contains('is-current')){
menuListCheck.classList.remove('is-current');
if (menuListCheck.classList.contains('is-current')) {
menuListCheck.classList.remove('is-current');
for(const menu of menuList){
menu.classList.remove('is-current');
}
for (const menu of menuList) {
menu.classList.remove('is-current');
}
} else {
for(const other of menuList){
other.classList.remove('is-current');
}
menuListCheck.classList.add('is-current');
for (const other of menuList) {
other.classList.remove('is-current');
}
menuListCheck.classList.add('is-current');
}
}
},
}
}
</script>
},
};
</script>

View File

@@ -231,8 +231,7 @@ export default {
align: 'center',
width: '11%',
formatter: (props) => {
let result = props.sndCnt;
//.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
let result = props.sndCnt ? props.sndCnt.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') : '0';
return result;
},
},

View File

@@ -0,0 +1,535 @@
<template>
<!-- <div class="wrap bg-wrap"> -->
<div>
<div class="dimmed modal-insertNotice" @click="ModalClose()"></div>
<div class="popup-wrap modal-insertNotice">
<!-- 공지사항 신규 등록 -->
<div class="popup modal-insertNotice popup_form" style="width: 70vw">
<div class="pop-head">
<h3 class="pop-tit">공지사항 신규 등록</h3>
</div>
<form autocomplete="off">
<table>
<colgroup>
<col width="10%" />
<col width="40%" />
<col width="10%" />
<col width="10%" />
<col width="10%" />
<col width="10%" />
</colgroup>
<tbody>
<tr>
<th style="width: 10%">분류코드</th>
<td>
<div class="select_box">
<select name="" id="right" v-model="ctgCd" style="min-width: 500px" ref="_ctgCd">
<option v-for="(option, i) in ctgCdOption" :value="option.code" v-bind:key="i">
{{ option.codeNm }}
</option>
</select>
</div>
</td>
<th style="width: 10%">긴급여부</th>
<td>
<div class="select_box">
<select name="" id="right" v-model="emgYn" style="min-width: 150px">
<option value="Y">Y</option>
<option value="N">N</option>
</select>
</div>
</td>
<th style="width: 10%">사용여부</th>
<td>
<div class="select_box">
<select name="" id="right" v-model="useYn" style="min-width: 150px">
<option value="Y">Y</option>
<option value="N">N</option>
</select>
</div>
</td>
</tr>
<tr>
<th style="width: 10%">제목</th>
<td colspan="5">
<input type="text" placeholder="제목을 입력하세요" v-model="title" ref="_title" />
</td>
</tr>
<tr>
<th style="width: 10%">내용</th>
<td class="sender" colspan="5">
<vue-editor
id="editor"
useCustomImageHandler
@imageAdded="handleImageAdded"
v-model="ntSbst"
ref="_ntSbst"
>
</vue-editor>
</td>
</tr>
<tr>
<th style="width: 10%">첨부파일</th>
<td class="sender" colspan="5">
<p class="file" style="width: 100%; margin-bottom: 15px">파일형식 : jpg, png, pdf, tiff (최대 5MB)</p>
<div class="btn plus">
파일 추가
<input
type="file"
accept=".jpg,.png,.pdf,.tiff"
multiple="multiple"
ref="imageUploader"
@change="onFileChange"
class="form-control-file"
id="my-file"
/>
</div>
<div class="img_list_wrap" v-if="updateFileList.length > 0" style="margin-top: 15px">
<div
class="img_list"
v-for="(item, index) in updateFileList"
:key="index"
style="margin-bottom: 5px"
>
<!-- <a href="javascript:void(0);" @click="download(item.filePath, item.fileNm, item.name)">{{ item.name }}</a> -->
<p class="file_name">{{ item.name }}</p>
<button type="button" class="btn_del" @click="popupHandleRemove(index)">X</button>
</div>
</div>
</td>
</tr>
<tr>
<th style="width: 10%">
이미지셋 <br />
<button type="button" @click="setImg">이미지추가</button>
<button type="button" @click="testImg = ''">이미지클리어</button>
</th>
<td class="sender" colspan="5">
<p v-html="testImg"></p>
</td>
</tr>
</tbody>
</table>
</form>
<div class="popup-btn2">
<button class="btn-pcolor" @click="regisConfirm()">등록</button>
<button class="btn-default" @click="ModalClose()">취소</button>
</div>
</div>
<!-- <common-modal ref="commonModal"></common-modal> -->
<validation-confirm-popup ref="ValidationConfirmPopup"></validation-confirm-popup>
</div>
</div>
</template>
<script>
import { VueEditor } from 'vue2-editor';
import api from '@/service/api';
import homeMgtApi from '../service/homeMgtApi';
import ValidationConfirmPopup from './ValidationConfirmPopup.vue';
import { utils_mixin, chkPattern2 } from '../service/mixins';
export default {
name: 'NoticePop',
mixins: [utils_mixin, chkPattern2],
data() {
return {
testImg: '',
props: {},
row: {},
rsnType: [],
tpType: [],
// 공지사항
title: '',
ntSbst: '', //
emgYn: 'N',
useYn: 'Y',
ctgCd: 'null',
updateFileList: [], // 업로드한 이미지 파일
ctgCdOption: [
{ code: 'null', codeNm: '분류코드를 선택하세요' },
{ code: '01', codeNm: '서비스' },
{ code: '02', codeNm: '개발/작업' },
{ code: '03', codeNm: '정책/약관' },
{ code: '04', codeNm: '오류/장애' },
{ code: '05', codeNm: '이벤트' },
],
// 공지사항
LINE_FEED: 10, // '\n',
maxByte: 2000,
// params: {
// 'blckSndrno' : ''
// ,'ctgCd' : '01'
// ,'blckRsnCd' : '02'
// ,'meno' : ''
// }
};
},
create() {
//this.setCodeDate();
this.formReset();
},
mounted() {
//this.ctgCd = '01'
},
components: {
VueEditor,
ValidationConfirmPopup,
},
methods: {
setImg() {
///%7Cefs%7Chome%7CsendMessage%7C2022%7C09%7C20%7C10%7C2022092010000168664_1.jpg
this.testImg =
"<img src='/api/v1/bo/homeMgt/preview/%7Cefs%7Chome%7CsendMessage%7C2022%7C09%7C20%7C10%7C2022092010000168664_1.jpg' />";
},
handleImageAdded(file, Editor, cursorLocation, resetUploader) {
var fd = new FormData();
fd.append('files', file);
homeMgtApi
.getImageUrl(fd)
.then((response) => {
const url = '..' + response.data.data.replaceAll('\\', '/'); // Get url from response
console.log(url);
Editor.insertEmbed(cursorLocation, 'image', url);
resetUploader();
})
.catch((err) => {
console.log(err);
});
},
//모달 띄우기
ModalOpen() {
var dimmed = document.getElementsByClassName('modal-insertNotice');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'block';
}
this.setCodeDate();
},
// 모달 끄기
ModalClose() {
this.formReset();
var dimmed = document.getElementsByClassName('modal-insertNotice');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'none';
}
},
// 저장 후 부모창 호출
toComplete() {
this.$parent.$refs.table.reloadData();
this.ModalClose();
},
setCodeDate() {
// 발송타입
api.commCode({ grpCd: 'SNDBLCK_TP_CD' }).then((response) => {
this.tpType = response.data.data.list;
});
api.commCode({ grpCd: 'SNDBLCK_RSN_CD' }).then((response) => {
this.rsnType = response.data.data.list;
});
},
doValidate() {
if (this.isNull(this.ctgCd) || this.ctgCd === 'null') {
this.row.title = '공지사항 등록';
this.row.msg1 = '분류코드를 선택해 주세요.';
this.row.focusTaget = '_ctgCd';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
return false;
}
if (this.isNull(this.title)) {
this.row.title = '공지사항 등록';
this.row.msg1 = '제목을 입력해 주세요.';
this.row.focusTaget = '_title';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
return false;
}
if (this.isNull(this.ntSbst)) {
this.row.title = '공지사항 등록';
this.row.msg1 = '내용을 입력해 주세요.';
this.row.focusTaget = '_ntSbst';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
return false;
}
/* const hp = this.blckSndrno;
if (!this.isNull(hp) && !this.isSendnum(hp)) {
this.row.title = '공지사항';
this.row.msg1 = '발신번호 형식이 잘못되었습니다. 확인 해주세요.';
this.$parent.alertInsert(this.row);
this.$refs._blckSndrno.focus();
return false;
} */
this.row.ctgCd = this.ctgCd;
return true;
},
formReset() {
Object.assign(this.$data, this.$options.data());
},
regisConfirm() {
if (this.doValidate()) {
this.$refs.ValidationConfirmPopup.confirmInsertOpen();
}
},
// 바이트길이 구하기
getByteLength: function (decimal) {
return decimal >> 7 || this.LINE_FEED === decimal ? 2 : 1;
},
getByte: function (str) {
return str
.split('')
.map((s) => s.charCodeAt(0))
.reduce((prev, unicodeDecimalValue) => prev + this.getByteLength(unicodeDecimalValue), 0);
},
getLimitedByteText: function (inputText, maxByte) {
const characters = inputText.split('');
let validText = '';
let totalByte = 0;
for (let i = 0; i < characters.length; i += 1) {
const character = characters[i];
const decimal = character.charCodeAt(0);
const byte = this.getByteLength(decimal); // 글자 한 개가 몇 바이트 길이인지 구해주기
// 현재까지의 바이트 길이와 더해 최대 바이트 길이를 넘지 않으면
if (totalByte + byte <= maxByte) {
totalByte += byte; // 바이트 길이 값을 더해 현재까지의 총 바이트 길이 값을 구함
validText += character; // 글자를 더해 현재까지의 총 문자열 값을 구함
} else {
// 최대 바이트 길이를 넘으면
break; // for 루프 종료
}
}
return validText;
},
memoLimitByte() {
this.meno = this.getLimitedByteText(this.meno, this.maxByte);
}, //END 바이트길이 구하기
insertNotice() {
const fd = new FormData();
for (let i = 0; i < this.updateFileList.length; i++) {
fd.append('files', this.updateFileList[i]);
}
const params = {
title: this.title,
ntSbst: this.ntSbst,
emgYn: this.emgYn,
useYn: this.useYn,
ctgCd: this.ctgCd,
regr: this.$store.getters['login/userNm'],
regId: this.$store.getters['login/userId'],
chgId: this.$store.getters['login/userId'],
};
fd.append('key', new Blob([JSON.stringify(params)], { type: 'application/json' }));
for (var pair of fd.entries()) {
console.log(pair[0] + ' : ' + pair[1]);
}
homeMgtApi.insertNotice(fd).then((response) => {
if (response.data.retCode == '0000') {
this.row.title = '공지사항 등록';
this.row.msg1 = '등록이 완료되었습니다.';
this.row.type = 'complete';
//this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
this.toComplete();
} else {
this.row.title = '공지사항 등록 실패';
this.row.msg1 = response.retMsg;
this.row.type = '';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
}
});
},
checkFocus() {
if (this.row.focusTaget === '_title') {
this.$refs._title.focus();
} else if (this.row.focusTaget === '_ntSbst') {
//this.$refs._ntSbst.focus();
} else if (this.row.focusTaget === '_ctgCd') {
this.$refs._ctgCd.focus();
}
},
/////////////////////////////////// 파일 첨부 ////////////////////////////////////////
onFileChange(event) {
const files = event.target.files || event.dataTransfer.files;
if (!files.length) return;
/* if (files.length > 3) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>최대 3장 첨부할 수 있습니다.</li>',
'info'
);
this.imageAddTitle = '이미지는 최대 3장까지 첨부할 수 있습니다.';
//confirm.fnAlert("알림", "첨부파일은 최대 3개까지 가능합니다.", "alert");
return;
} else if (this.updateFileList.length + files.length > 3) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>최대 3장 첨부할 수 있습니다.</li>',
'info'
);
this.imageAddTitle = '이미지는 최대 3장까지 첨부할 수 있습니다.';
// confirm.fnAlert("알림", "첨부파일은 최대 3개까지 가능합니다.", "alert");
return;
} */
this.addFiles(files);
},
async addFiles(files) {
for (let i = 0; i < files.length; i++) {
const src = await this.readFiles(files[i]);
files[i].src = src;
files[i].status = 'update';
files[i].index = this.updateFileList.length;
this.updateFileList.push(files[i]);
/* if (!(files[i].name.indexOf('jpg') > -1 || files[i].name.indexOf('jpeg') > -1)) {
confirm.fnAlert('', '<li>jpg파일 형식만 첨부할 수 있습니다.</li>', 'info');
this.imageAddTitle = 'jpg파일 형식만 첨부할 수 있습니다.';
continue;
} else if (files[i].size > 300000) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>전체 크기 합계가 300KB 이하여야 합니다.</li>',
'info'
);
this.imageAddTitle = '전체 크기 합계가 300KB 이하여야 합니다.';
//confirm.fnAlert("이미지 사이즈 초과", "300KB이하 이미지만 등록 가능합니다.", "alert");
continue;
} else if (files[i].size + this.totalFileSize > 300000) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>전체 크기 합계가 300KB 이하여야 합니다.</li>',
'info'
);
this.imageAddTitle = '전체 크기 합계가 300KB 이하여야 합니다.';
//confirm.fnAlert("이미지 사이즈 초과", "전체 합계 300KB이하 이미지만 등록 가능합니다.", "alert");
continue;
} else if (this.getImageSize(src) === false) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>1,500(가로)x1,440(세로)px 이하 크기만 첨부할 수 있습니다.</li>',
'info'
);
this.imageAddTitle = '1,500(가로)x1,440(세로)px 이하 크기만 첨부할 수 있습니다.';
//confirm.fnAlert("이미지 크기 초과", "1500 * 1440 이하 이미지만 등록 가능합니다.", "alert");
continue;
} else {
files[i].status = 'update';
files[i].index = this.updateFileList.length;
this.updateFileList.push(files[i]);
confirm.fnAlert('', '이미지가 정상적으로 추가 되었습니다.', 'alert');
this.imageAddTitle = '';
} */
}
this.$refs.imageUploader.value = ''; // 이미지 중복 가능하도록 input 초기화
},
// FileReader를 통해 파일을 읽어 thumbnail 영역의 src 값으로 셋팅
async readFiles(files) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = async (e) => {
resolve(e.target.result);
};
reader.readAsDataURL(files);
});
},
getImageSize(src) {
const img = new Image();
let _width = 0;
let _height = 0;
img.src = src;
img.onload = function () {
_width = img.width;
_height = img.height;
if (_width >= 1500 || _height >= 1440) {
return false;
} else {
return true;
}
};
},
popupHandleRemove(index) {
this.updateFileList.splice(index, 1);
},
},
};
</script>
<style scoped>
.popup-btn-wrap {
width: 500px;
margin: auto;
padding: 100px 0;
}
.popup-btn-wrap button {
width: 100%;
margin-bottom: 10px;
height: 50px;
border-radius: 5px;
box-shadow: none;
border: 1px solid #000;
}
.popup-btn-wrap button:hover {
background: #000;
color: #fff;
}
.btn.plus {
font-family: SpoqaHanSansNeo;
font-weight: 400;
font-size: 16px;
color: #fff;
background-color: #35354f;
border-radius: 4px;
text-align: center;
min-width: 89px;
height: 36px;
padding: 10px 20px;
letter-spacing: -0.025em;
border: none;
position: relative;
line-height: 1;
display: inline-block;
box-sizing: border-box;
transition: 0.3s;
}
.btn input {
width: 100%;
height: 100%;
opacity: 0;
position: absolute;
top: 0;
left: 0;
cursor: pointer;
z-index: 1;
}
.file_name {
display: inline-flex;
}
.btn_del {
background: #e4e4e4;
width: 15px;
height: 15px;
border-radius: 50%;
border: none;
font-size: 10px;
margin: 0 0 0 5px;
}
</style>

View File

@@ -0,0 +1,574 @@
<template>
<!-- <div class="wrap bg-wrap"> -->
<div>
<div class="dimmed modal52" @click="ModalClose()"></div>
<div class="popup-wrap modal52">
<!-- 공지사항 수정 -->
<div class="popup modal52 popup_form" style="width: 70vw">
<div class="pop-head">
<h3 class="pop-tit">공지사항 수정</h3>
</div>
<form autocomplete="off">
<table>
<colgroup>
<col width="10%" />
<col width="40%" />
<col width="10%" />
<col width="10%" />
<col width="10%" />
<col width="10%" />
</colgroup>
<tbody>
<tr>
<th style="width: 10%">분류코드</th>
<td>
<div class="select_box">
<select name="" id="right" v-model="ctgCd" style="min-width: 500px" ref="_ctgCd">
<option v-for="(option, i) in ctgCdOption" :value="option.code" v-bind:key="i">
{{ option.codeNm }}
</option>
</select>
</div>
</td>
<th style="width: 10%">긴급여부</th>
<td>
<div class="select_box">
<select name="" id="right" v-model="emgYn" style="min-width: 150px">
<option value="Y">Y</option>
<option value="N">N</option>
</select>
</div>
</td>
<th style="width: 10%">사용여부</th>
<td>
<div class="select_box">
<select name="" id="right" v-model="useYn" style="min-width: 150px">
<option value="Y">Y</option>
<option value="N">N</option>
</select>
</div>
</td>
</tr>
<tr>
<th style="width: 10%">제목</th>
<td colspan="5">
<input type="text" placeholder="제목을 입력하세요" v-model="title" ref="_title" />
</td>
</tr>
<tr>
<th style="width: 10%">내용</th>
<td class="sender" colspan="5">
<vue-editor
id="editor"
useCustomImageHandler
@imageAdded="handleImageAdded"
v-model="ntSbst"
ref="_ntSbst"
>
</vue-editor>
</td>
</tr>
<tr>
<th style="width: 10%">첨부파일</th>
<td class="sender" colspan="5">
<p class="file" style="width: 100%; margin-bottom: 15px">파일형식 : jpg, png, pdf, tiff (최대 5MB)</p>
<div class="btn plus">
파일 추가
<input
type="file"
accept=".jpg,.png,.pdf,.tiff"
multiple="multiple"
ref="imageUploader"
@change="onFileChange"
class="form-control-file"
id="my-file"
/>
</div>
<div class="img_list_wrap" v-if="updateFileList.length > 0" style="margin-top: 15px">
<div
class="img_list"
v-for="(item, index) in updateFileList"
:key="index"
style="margin-bottom: 5px"
>
<a
href="javascript:void(0);"
v-if="item.filePath"
@click="download(item.filePath, item.fileName, item.name)"
>{{ item.name }} (다운로드가능)</a
>
<p class="file_name" v-else>
{{ index + 1 }}. {{ item.name }} {{ item.fileNo ? `(${item.fileNo})` : '' }}
</p>
<button type="button" class="btn_del" @click="popupHandleRemove(index, item.fileNo)">X</button>
</div>
</div>
</td>
</tr>
</tbody>
</table>
</form>
<div class="popup-btn2">
<button class="btn-pcolor" @click="updateConfirm()">수정</button>
<button class="btn-default" @click="ModalClose()">취소</button>
</div>
</div>
<!-- <common-modal ref="commonModal"></common-modal> -->
<validation-confirm-popup ref="ValidationConfirmPopup"></validation-confirm-popup>
</div>
</div>
</template>
<script>
import api from '@/service/api';
import homeMgtApi from '../service/homeMgtApi';
import ValidationConfirmPopup from './ValidationConfirmPopup.vue';
import { VueEditor } from 'vue2-editor';
import { utils_mixin, chkPattern2 } from '../service/mixins';
export default {
name: 'NoticeUpdatePop',
mixins: [utils_mixin, chkPattern2],
data() {
return {
props: {},
row: {},
rsnType: [],
tpType: [],
// 공지사항
ntNo: '',
title: '',
ntSbst: '',
emgYn: 'N',
useYn: 'Y',
ctgCd: 'null',
fileNm: '',
filePath: '',
fileTitle: '',
fileNo: '',
updateFileList: [], // 업로드한 이미지 파일
delFileList: [],
ctgCdOption: [
{ code: 'null', codeNm: '분류코드를 선택하세요' },
{ code: '01', codeNm: '서비스' },
{ code: '02', codeNm: '개발/작업' },
{ code: '03', codeNm: '정책/약관' },
{ code: '04', codeNm: '오류/장애' },
{ code: '05', codeNm: '이벤트' },
],
// 공지사항
LINE_FEED: 10, // '\n',
maxByte: 2000,
// params: {
// 'blckSndrno' : ''
// ,'ctgCd' : '01'
// ,'blckRsnCd' : '02'
// ,'meno' : ''
// }
};
},
create() {
//this.setCodeDate();
this.formReset();
},
mounted() {
//this.ctgCd = '01'
},
components: {
VueEditor,
ValidationConfirmPopup,
},
methods: {
handleImageAdded(file, Editor, cursorLocation, resetUploader) {
var fd = new FormData();
fd.append('files', file);
homeMgtApi
.getImageUrl(fd)
.then((response) => {
const url = '..' + response.data.data.replaceAll('\\', '/'); // Get url from response
console.log(url);
Editor.insertEmbed(cursorLocation, 'image', url);
resetUploader();
})
.catch((err) => {
console.log(err);
});
},
//모달 띄우기
ModalOpen(props) {
var dimmed = document.getElementsByClassName('modal52');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'block';
}
this.setCodeDate();
if (props) {
this.ntNo = props.ntNo;
this.title = props.title;
this.ntSbst = props.ntSbst;
this.emgYn = props.emgYn;
this.useYn = props.useYn;
this.ctgCd = props.ctgCd;
this.fileNm = props.fileNm.split(',');
this.filePath = props.filePath.split(',');
this.fileTitle = props.fileTitle.split(',');
this.fileNo = props.fileNo.split(',');
this.fileCount = props.fileCount;
}
for (let i = 0; i < this.fileCount; i++) {
this.updateFileList.push({
src: '' + encodeURIComponent(this.filePath[i].replaceAll('\\', '/')) + '/' + this.fileNm[i],
filePath: this.filePath[i],
fileNo: this.fileNo[i],
fileName: this.fileNm[i],
name: this.fileTitle[i],
});
}
},
// 모달 끄기
ModalClose() {
this.formReset();
var dimmed = document.getElementsByClassName('modal52');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'none';
}
},
// 저장 후 부모창 호출
toComplete() {
this.$parent.$refs.table.reloadData();
this.ModalClose();
},
setCodeDate() {
// 발송타입
api.commCode({ grpCd: 'SNDBLCK_TP_CD' }).then((response) => {
this.tpType = response.data.data.list;
});
api.commCode({ grpCd: 'SNDBLCK_RSN_CD' }).then((response) => {
this.rsnType = response.data.data.list;
});
},
doValidate() {
if (this.isNull(this.ctgCd) || this.ctgCd === 'null') {
this.row.title = '공지사항 등록';
this.row.msg1 = '분류코드를 선택해 주세요.';
this.row.focusTaget = '_ctgCd';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
return false;
}
if (this.isNull(this.title)) {
this.row.title = '공지사항 등록';
this.row.msg1 = '제목을 입력해 주세요.';
this.row.focusTaget = '_title';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
return false;
}
if (this.isNull(this.ntSbst)) {
this.row.title = '공지사항 등록';
this.row.msg1 = '내용을 입력해 주세요.';
this.row.focusTaget = '_ntSbst';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
return false;
}
/* const hp = this.blckSndrno;
if (!this.isNull(hp) && !this.isSendnum(hp)) {
this.row.title = '공지사항';
this.row.msg1 = '발신번호 형식이 잘못되었습니다. 확인 해주세요.';
this.$parent.alertInsert(this.row);
this.$refs._blckSndrno.focus();
return false;
} */
this.row.ctgCd = this.ctgCd;
return true;
},
formReset() {
Object.assign(this.$data, this.$options.data());
},
updateConfirm() {
if (this.doValidate()) {
this.$refs.ValidationConfirmPopup.confirmUpdateOpen();
}
},
// 바이트길이 구하기
getByteLength: function (decimal) {
return decimal >> 7 || this.LINE_FEED === decimal ? 2 : 1;
},
getByte: function (str) {
return str
.split('')
.map((s) => s.charCodeAt(0))
.reduce((prev, unicodeDecimalValue) => prev + this.getByteLength(unicodeDecimalValue), 0);
},
getLimitedByteText: function (inputText, maxByte) {
const characters = inputText.split('');
let validText = '';
let totalByte = 0;
for (let i = 0; i < characters.length; i += 1) {
const character = characters[i];
const decimal = character.charCodeAt(0);
const byte = this.getByteLength(decimal); // 글자 한 개가 몇 바이트 길이인지 구해주기
// 현재까지의 바이트 길이와 더해 최대 바이트 길이를 넘지 않으면
if (totalByte + byte <= maxByte) {
totalByte += byte; // 바이트 길이 값을 더해 현재까지의 총 바이트 길이 값을 구함
validText += character; // 글자를 더해 현재까지의 총 문자열 값을 구함
} else {
// 최대 바이트 길이를 넘으면
break; // for 루프 종료
}
}
return validText;
},
memoLimitByte() {
this.meno = this.getLimitedByteText(this.meno, this.maxByte);
}, //END 바이트길이 구하기
updateNotice() {
const fd = new FormData();
let legacyFiles = [];
for (let i = 0; i < this.updateFileList.length; i++) {
if (this.updateFileList[i].fileName) {
legacyFiles.push(this.updateFileList[i].fileName);
} else {
fd.append('files', this.updateFileList[i]);
}
}
const params = {
ntNo: this.ntNo,
title: this.title,
ntSbst: this.ntSbst,
emgYn: this.emgYn,
useYn: this.useYn,
ctgCd: this.ctgCd,
chgId: this.$store.getters['login/userId'],
legacyFiles: legacyFiles.join(),
delFileNo: this.delFileList.join(),
};
console.log(params);
console.log(params.delFileNo);
console.log(typeof params.delFileNo);
fd.append('key', new Blob([JSON.stringify(params)], { type: 'application/json' }));
for (var pair of fd.entries()) {
console.log(pair[0] + ' : ' + pair[1]);
}
homeMgtApi.updateNotice(fd).then((response) => {
if (response.data.retCode == '0000') {
this.row.title = '공지사항 수정';
this.row.msg1 = '수정이 완료되었습니다.';
this.row.type = 'update';
//this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
this.toComplete();
} else {
this.row.title = '공지사항 수정 실패';
this.row.msg1 = response.retMsg;
this.row.type = '';
this.$refs.ValidationConfirmPopup.alertModalOpen(this.row);
}
});
},
checkFocus() {
if (this.row.focusTaget === '_title') {
this.$refs._title.focus();
} else if (this.row.focusTaget === '_ntSbst') {
//this.$refs._ntSbst.focus();
} else if (this.row.focusTaget === '_ctgCd') {
this.$refs._ctgCd.focus();
}
},
/////////////////////////////////// 파일 첨부 ////////////////////////////////////////
onFileChange(event) {
const files = event.target.files || event.dataTransfer.files;
if (!files.length) return;
/* if (files.length > 3) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>최대 3장 첨부할 수 있습니다.</li>',
'info'
);
this.imageAddTitle = '이미지는 최대 3장까지 첨부할 수 있습니다.';
//confirm.fnAlert("알림", "첨부파일은 최대 3개까지 가능합니다.", "alert");
return;
} else if (this.updateFileList.length + files.length > 3) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>최대 3장 첨부할 수 있습니다.</li>',
'info'
);
this.imageAddTitle = '이미지는 최대 3장까지 첨부할 수 있습니다.';
// confirm.fnAlert("알림", "첨부파일은 최대 3개까지 가능합니다.", "alert");
return;
} */
this.addFiles(files);
},
async addFiles(files) {
for (let i = 0; i < files.length; i++) {
const src = await this.readFiles(files[i]);
files[i].src = src;
this.updateFileList.push(files[i]);
/* if (!(files[i].name.indexOf('jpg') > -1 || files[i].name.indexOf('jpeg') > -1)) {
confirm.fnAlert('', '<li>jpg파일 형식만 첨부할 수 있습니다.</li>', 'info');
this.imageAddTitle = 'jpg파일 형식만 첨부할 수 있습니다.';
continue;
} else if (files[i].size > 300000) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>전체 크기 합계가 300KB 이하여야 합니다.</li>',
'info'
);
this.imageAddTitle = '전체 크기 합계가 300KB 이하여야 합니다.';
//confirm.fnAlert("이미지 사이즈 초과", "300KB이하 이미지만 등록 가능합니다.", "alert");
continue;
} else if (files[i].size + this.totalFileSize > 300000) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>전체 크기 합계가 300KB 이하여야 합니다.</li>',
'info'
);
this.imageAddTitle = '전체 크기 합계가 300KB 이하여야 합니다.';
//confirm.fnAlert("이미지 사이즈 초과", "전체 합계 300KB이하 이미지만 등록 가능합니다.", "alert");
continue;
} else if (this.getImageSize(src) === false) {
confirm.fnAlert(
// "이미지 첨부 기준 안내",
'',
'<li>1,500(가로)x1,440(세로)px 이하 크기만 첨부할 수 있습니다.</li>',
'info'
);
this.imageAddTitle = '1,500(가로)x1,440(세로)px 이하 크기만 첨부할 수 있습니다.';
//confirm.fnAlert("이미지 크기 초과", "1500 * 1440 이하 이미지만 등록 가능합니다.", "alert");
continue;
} else {
files[i].status = 'update';
files[i].index = this.updateFileList.length;
this.updateFileList.push(files[i]);
confirm.fnAlert('', '이미지가 정상적으로 추가 되었습니다.', 'alert');
this.imageAddTitle = '';
} */
}
console.log(this.updateFileList);
this.$refs.imageUploader.value = ''; // 이미지 중복 가능하도록 input 초기화
},
// FileReader를 통해 파일을 읽어 thumbnail 영역의 src 값으로 셋팅
async readFiles(files) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = async (e) => {
resolve(e.target.result);
};
reader.readAsDataURL(files);
});
},
getImageSize(src) {
const img = new Image();
let _width = 0;
let _height = 0;
img.src = src;
img.onload = function () {
_width = img.width;
_height = img.height;
if (_width >= 1500 || _height >= 1440) {
return false;
} else {
return true;
}
};
},
popupHandleRemove(index, fileNo) {
this.delFileList.push(fileNo);
this.updateFileList.splice(index, 1);
},
download(filePath, fileName, fileTitle) {
this.row = {};
this.row.fileTitle = fileTitle;
this.row.filePath = filePath;
this.row.fileNm = fileName;
console.log(this.row);
homeMgtApi.fileDownload(this.row);
},
},
};
</script>
<style scoped>
.popup-btn-wrap {
width: 500px;
margin: auto;
padding: 100px 0;
}
.popup-btn-wrap button {
width: 100%;
margin-bottom: 10px;
height: 50px;
border-radius: 5px;
box-shadow: none;
border: 1px solid #000;
}
.popup-btn-wrap button:hover {
background: #000;
color: #fff;
}
.btn.plus {
font-family: SpoqaHanSansNeo;
font-weight: 400;
font-size: 16px;
color: #fff;
background-color: #35354f;
border-radius: 4px;
text-align: center;
min-width: 89px;
height: 36px;
padding: 10px 20px;
letter-spacing: -0.025em;
border: none;
position: relative;
line-height: 1;
display: inline-block;
box-sizing: border-box;
transition: 0.3s;
}
.btn input {
width: 100%;
height: 100%;
opacity: 0;
position: absolute;
top: 0;
left: 0;
cursor: pointer;
z-index: 1;
}
.file_name {
display: inline-flex;
}
.btn_del {
background: #e4e4e4;
width: 15px;
height: 15px;
border-radius: 50%;
border: none;
font-size: 10px;
margin: 0 0 0 5px;
}
</style>

View File

@@ -0,0 +1,159 @@
<template>
<div>
<div class="dimmed alertModal" @click="alertModalCancel()"></div>
<div class="popup-wrap alertModal">
<!-- 확인 -->
<div class="popup alertModal">
<div class="pop-head">
<h3 class="pop-tit">{{ title }}</h3>
</div>
<div class="pop-cont">
<p>{{ msg1 }}</p>
<p v-if="msg2 !== ''">{{ msg2 }}</p>
<p v-if="msg3 !== ''">{{ msg3 }}</p>
<p v-if="msg4 !== ''">{{ msg4 }}</p>
</div>
<div class="popup-btn1">
<button class="btn-pcolor" v-if="type" @click="alertModalClose(type)">확인</button>
<button class="btn-pcolor" v-else @click="alertModalClose()">확인</button>
</div>
</div>
</div>
<!-- 공지사항 등록-->
<div class="dimmed confirm-insert" @click="confirmInsertClose()"></div>
<div class="popup-wrap confirm-insert">
<div class="popup confirm-insert">
<div class="pop-head">
<h3 class="pop-tit">공지사항 등록</h3>
</div>
<div class="pop-cont">
<p>작성된 내용으로 등록 하시겠습니까?</p>
</div>
<div class="popup-btn2">
<button class="btn-pcolor" @click="confirmInsert()">확인</button>
<button class="btn-default" @click="confirmInsertClose()">취소</button>
</div>
</div>
</div>
<!-- 공지사항 수정-->
<div class="dimmed confirm-update" @click="confirmUpdateClose()"></div>
<div class="popup-wrap confirm-update">
<div class="popup confirm-update">
<div class="pop-head">
<h3 class="pop-tit">공지사항 수정</h3>
</div>
<div class="pop-cont">
<p>작성된 내용으로 수정 하시겠습니까?</p>
</div>
<div class="popup-btn2">
<button class="btn-pcolor" @click="confirmUpdate()">확인</button>
<button class="btn-default" @click="confirmUpdateClose()">취소</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'validationConfirmPopup',
data() {
return {
row: {},
title: '',
msg: '',
msg1: '',
msg2: '',
msg3: '',
msg4: '',
targetFocus: '',
type: '',
};
},
methods: {
alertModalOpen(props) {
this.title = props.title;
this.msg1 = props.msg1;
this.msg2 = props.msg2;
this.msg3 = props.msg3;
this.msg4 = props.msg4;
this.type = props.type;
var dimmed = document.getElementsByClassName('alertModal');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'block';
}
},
alertModalClose(type) {
if (type) {
this.$parent.formReset();
var dimmed0 = document.getElementsByClassName('alertModal');
for (var i = 0; i < dimmed0.length; i++) {
dimmed0[i].style.display = 'none';
}
var dimmed1 = document.getElementsByClassName('modal52');
for (var k = 0; k < dimmed1.length; k++) {
dimmed1[k].style.display = 'none';
}
} else {
var dimmed = document.getElementsByClassName('alertModal');
for (var j = 0; j < dimmed.length; j++) {
dimmed[j].style.display = 'none';
}
this.$parent.checkFocus();
}
},
//공지사항 등록 팝업
confirmInsertOpen() {
var dimmed = document.getElementsByClassName('confirm-insert');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'block';
}
},
//공지사항 등록
confirmInsert() {
var dimmed = document.getElementsByClassName('confirm-insert');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'none';
}
this.$parent.insertNotice();
},
//공지사항 등록 팝업 Close
confirmInsertClose() {
var dimmed = document.getElementsByClassName('confirm-insert');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'none';
}
},
//공지사항 수정 팝업
confirmUpdateOpen() {
var dimmed = document.getElementsByClassName('confirm-update');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'block';
}
},
//공지사항 수정
confirmUpdate() {
var dimmed = document.getElementsByClassName('confirm-update');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'none';
}
this.$parent.updateNotice();
},
//공지사항 수정 팝업 Close
confirmUpdateClose() {
var dimmed = document.getElementsByClassName('confirm-update');
for (var i = 0; i < dimmed.length; i++) {
dimmed[i].style.display = 'none';
}
},
},
};
</script>

View File

@@ -0,0 +1,11 @@
import Notice from '../views/notice';
export default [
{
path: '/homeMgt/notice',
component: Notice,
name: 'notice',
props: true,
meta: { public: false },
},
];

View File

@@ -0,0 +1,61 @@
import httpClient from '@/common/http-client';
import axios from 'axios';
// 공지사항 등록
const insertNotice = (params) => {
return httpClient.post('/api/v1/bo/homeMgt/insertNotice', params, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
};
// 공지사항 수정
const updateNotice = (params) => {
return httpClient.post('/api/v1/bo/homeMgt/updateNotice', params, { withCredentials: false });
};
const getImageUrl = (params) => {
return httpClient.post('/api/v1/bo/homeMgt/getImageUrl', params, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
};
const fileDownload = (params) => {
axios({
method: 'POST',
url: '/api/v1/bo/homeMgt/filedownload',
responseType: 'blob',
headers: '',
data: params,
params: params,
})
.then((response) => {
const fileName = params.fileTitle;
const data = response.data;
if (!data) {
return;
}
const url = window.URL.createObjectURL(new Blob([data]));
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.setAttribute('download', fileName);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
window.URL.revokeObjectURL(url);
})
.catch((response) => {
console.log(response);
});
};
export default {
insertNotice,
updateNotice,
fileDownload,
getImageUrl,
};

View File

@@ -0,0 +1,370 @@
import lodash from "lodash";
const utils_mixin = {
methods: {
/** * 이메일 형식 체크 * * @param 데이터 */
emailCheck(email, rtnArrYn) {
if (this.isNull(rtnArrYn)) {
rtnArrYn = 'N';
}
// var regExp = /(^[A-Za-z0-9_\.\-]+)@([A-Za-z0-9\-]+\.[A-Za-z0-9\-]+)/;
var regExp = /^([0-9a-zA-Z_\.\-]([-_.]?[0-9a-zA-Z_\.\-])*)@([0-9a-zA-Z]([-_.]?[0-9a-zA-Z])*.[a-zA-Z]{2,3}$)/i;//이메일 정규식
if (regExp.test(email) == false) {
// 이메일 형식이 알파벳+숫자@알파벳+숫자.알파벳+숫자 형식이 아닐경우
if (rtnArrYn == 'Y') {
return email;
}
return false;
} else {
var myArray = regExp.exec(email);
if (rtnArrYn == 'Y') {
return myArray;
}
return true;
}
},
/** * 전화번호 포맷으로 변환 * * @param 데이터 */
formatPhone(phoneNum, fmt, rtnArrYn) {
if (this.isNull(fmt)) {
fmt = '';
}
if (this.isNull(rtnArrYn)) {
fmt = 'N';
}
if (this.isPhone(phoneNum)) {
var rtnNum;
var regExp = /(02)([0-9]{3,4})([0-9]{4})$/;
var myArray;
if (regExp.test(phoneNum)) {
myArray = regExp.exec(phoneNum);
rtnNum = myArray[1] + fmt + myArray[2] + fmt + myArray[3];
if (rtnArrYn == 'Y') {
return myArray;
}
return rtnNum;
} else {
regExp = /(0[3-9]{1}[0-9]{1})([0-9]{3,4})([0-9]{4})$/;
if (regExp.test(phoneNum)) {
myArray = regExp.exec(phoneNum);
rtnNum = myArray[1] + fmt + myArray[2] + fmt + myArray[3];
if (rtnArrYn == 'Y') {
return myArray;
}
return rtnNum;
} else {
return phoneNum;
}
}
} else {
return phoneNum;
}
},
/** * 핸드폰번호 포맷으로 변환 * * @param 데이터 */
formatMobile(phoneNum, fmt, rtnArrYn) {
if (this.isNull(fmt)) {
fmt = '';
}
if (this.isNull(rtnArrYn)) {
fmt = 'N';
}
if (this.isMobile(phoneNum)) {
var rtnNum;
var regExp = /(01[016789])([0-9]{3,4})([0-9]{4})$/;
var myArray;
if (regExp.test(phoneNum)) {
myArray = regExp.exec(phoneNum);
rtnNum = myArray[1] + fmt + myArray[2] + fmt + myArray[3];
if (rtnArrYn == 'Y') {
return myArray;
}
return rtnNum;
} else {
return phoneNum;
}
} else {
return phoneNum;
}
},
/** * 전화번호 형식 체크 * * @param 데이터 */
isPhone(phoneNum) {
var regExp = /(02)([0-9]{3,4})([0-9]{4})$/;
if (regExp.test(phoneNum)) {
return true;
} else {
regExp = /(0[3-9]{1}[0-9]{1})([0-9]{3,4})([0-9]{4})$/;
if (regExp.test(phoneNum)) {
return true;
} else {
return false;
}
}
},
/** * 핸드폰번호 형식 체크 * * @param 데이터 */
isMobile(phoneNum) {
var regExp = /(01[016789])([0-9]{3,4})([0-9]{4})$/;
var myArray;
if (regExp.test(phoneNum)) {
myArray = regExp.exec(phoneNum);
return true;
} else {
return false;
}
},
isMobile2(phoneNum) {
var regExp = /(1[016789])([0-9]{3,4})([0-9]{4})$/;
var myArray;
if (regExp.test(phoneNum)) {
myArray = regExp.exec(phoneNum);
return true;
} else {
return false;
}
},
/** 발신번호 차단 */
isSendnum(phoneNum){
var regExp = /^(01[016789])([0-9]{3,4})([0-9]{4})|((080-[0-9]{3,4}|15(44|66|77|88))[0-9]{4})|(0(2|3[1-3]|4[1-4]|5[1-5]|6[1-4]))(\d{3,4})(\d{4})$/;
var myArray;
if(regExp.test(phoneNum)){
myArray = regExp.exec(phoneNum);
return true;
}else{
return false;
}
},
isNull(obj) {
if (lodash.isNil(obj) || lodash.trim(obj) == '') {
return true;
}
return false;
},
getParent(name) {
let p = this.$parent;
while (typeof p !== 'undefined') {
if (p.$options.name == name) {
return p;
} else {
p = p.$parent;
}
}
return false;
},
getJsonObj(str) {
return JSON.parse(JSON.stringify(str));
},
}
};
var chkPattern2 = {
data: function () {
return {}
},
methods: {
selSesStorage(keyLike) {
if (this.isNull(keyLike)) {
return null;
}
if (sessionStorage.length > 0) {
let keyList = [];
for (let i = 0; i < sessionStorage.length; i++) {
const keyNm = sessionStorage.key(i);
if (keyNm.indexOf(keyLike) > -1) {
keyList.push({name: keyNm, value: sessionStorage.getItem(keyNm)});
}
}
if (keyList.length > 0) {
return keyList;
}
return null;
}
return null;
},
delSesStorage(keyList) {
if (this.isNull(keyList)) {
return null;
}
if (keyList.length > 0) {
keyList.map((o) => (sessionStorage.removeItem(o.name)));
return true;
}
},
setGridMouseDownActive() {
const ele = document.querySelector(`div.tui-grid-container.tui-grid-show-lside-area`);
if (window.getEventListeners(ele).mousedown) {
ele.removeEventListener('mousedown', window.getEventListeners(ele).mousedown[0].listener);
}
},
restrictChars: function ($event, regExp, hanYn) {
if (this.isNull(hanYn)) {
hanYn = 'N';
}
if (hanYn === 'N' && $event.type === 'keydown') {
if ($event.keyCode === 229) {
$event.preventDefault();
return false;
}
}
if ($event.type === 'keypress') {
//한글 처리 불가
if (regExp.test(String.fromCharCode($event.charCode))) {
return true;
} else {
$event.preventDefault();
return false;
}
}
if (hanYn === 'N' && ($event.type === 'keyup' || $event.type === 'input' || $event.type === 'change' || $event.type === 'blur')) {
$event.target.value = $event.target.value.replace(/[ㄱ-ㅎㅏ-ㅣ가-힣]/g, '');
$event.preventDefault();
return false;
}
return true;
},
setLenth: function (e, len) {
this.cut(e, len);
},
onlyCustom: function (e, strRegExp, hanYn) {
var regExp_g = new RegExp(strRegExp, 'g');
this.cut(e);
return this.restrictChars(e, regExp_g, hanYn);
},
onlyCommon: function (strRegExp, e, len, isEventCall, hanYn) {
var regExp_g = new RegExp(strRegExp, 'g');
if (isEventCall === 'N') {
if (!this.cut(e, len, isEventCall)) {
return false;
}
if (!regExp_g.test(e.value)) {
return false;
}
return true;
}
this.cut(e, len);
return this.restrictChars(e, regExp_g, hanYn);
},
onlyNum: function (e, len, isEventCall) {
var strRegExp = '^[0-9]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyEng: function (e, len, isEventCall) {
var strRegExp = '^[A-Za-z]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyLowerEng: function (e, len, isEventCall) {
var strRegExp = '^[a-z]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyUpperEng: function (e, len, isEventCall) {
var strRegExp = '^[A-Z]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyEmail: function (e, len, isEventCall) {
var strRegExp = '^[a-zA-Z0-9_\.\-@._-]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyName: function (e, len, isEventCall) {
var strRegExp = '^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall, 'Y');
},
onlyTitle: function (e, len, isEventCall) {
var strRegExp = '^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall, 'Y');
},
onlyText: function (e, len, isEventCall) {
var strRegExp = '^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9_-]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall, 'Y');
},
onlyPassword: function (e, len, isEventCall) {
var strRegExp = '^[A-Za-z0-9!@#$%^&*]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyId: function (e, len, isEventCall) {
var strRegExp = '^[A-Za-z0-9_\.\-]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyIp: function (e, len, isEventCall) {
var strRegExp = '^[0-9,.*]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
onlyRoleNm_Space: function (e, len, isEventCall) {
var strRegExp = '^[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall, 'Y');
},
onlyRoleId_UnderBar: function (e, len, isEventCall) {
var strRegExp = '^[a-zA-Z0-9_]*$';
return this.onlyCommon(strRegExp, e, len, isEventCall);
},
cut: function (ele, len, isValidChk) {
let e = ele;
if (typeof ele.target != "undefined") {
e = ele.target;
}
let max = this.isNull(len) ? e.attributes.maxlength.value : len;
let str = e.value;
if (this.bytes(str) > max) {
if (this.isNull(isValidChk)) {
e.value = this.cutBytes(str, max);
}
return false;
}
return true;
},
cutBytes: function (str, len) {
while (1 === 1) {
if (this.bytes(str) <= len) {
return str;
}
str = str.slice(0, -1);
}
},
bytes: function (str) {
var length = ((s, b, i, c) => {
// for(b=i=0;c=s.charCodeAt(i++);b+=c>>11?3:c>>7?2:1); // 한글 3바이트
// for(b=i=0;c=s.charCodeAt(i++);b+=c>>11?2:c>>7?1:1); //한글 2바이트
b = 0, i = 0;
while (1 === 1) {
c = s.charCodeAt(i++);
if (isNaN(c)) {
break;
}
b += c >> 11 ? 2 : c >> 7 ? 1 : 1;
}
return b
})(str);
return length;
},
checkPhone: function (str) {
str = str.replace(/[-\s]+/g, '');
if (str.charAt(0) != "0") {
str = "0" + str;
}
if (str.length < 10 || str.length > 12) {
return "";
}
if (isNaN(str)) {
return "";
}
if (str.substr(0, 2) != "01" && str.substr(0, 3) != "070" && str.substr(0, 4) != "0505" && str.substr(0, 4) != "0503") {
return "";
}
return str;
},
}
};
export {utils_mixin, chkPattern2};

View File

@@ -0,0 +1,219 @@
<template>
<div class="contents">
<div class="contents_wrap">
<div class="top_wrap">
<h3 class="title">홈페이지 관리</h3>
<p class="breadcrumb">홈페이지 관리 &gt; 공지사항</p>
</div>
<div class="search_wrap">
<div class="select_box">
<label for="right" class="label">분류코드</label>
<select name="" id="right" v-model="searchType1" @change="search">
<option value="">전체</option>
<option value="01">서비스</option>
<option value="02">개발/작업</option>
<option value="03">정책/약관</option>
<option value="04">오류/장애</option>
<option value="05">이벤트</option>
</select>
</div>
<div class="input_box id">
<label for="id1" class="label">제목</label>
<input
class="search-box"
type="text"
id="id1"
placeholder="제목 입력"
v-model="searchText1"
@keyup.enter="search"
/>
</div>
<button type="button" class="button grey" @click="search">조회</button>
</div>
<div class="info">
<div class="count">
<span>{{ totalItems.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',') }}</span
>
<div class="select_box NumberSe">
<select name="" id="" v-model="perPageCnt" @change="changePerPage()">
<option v-for="option in options" v-bind:value="option.value" v-bind:key="option.value">
{{ option.text }}
</option>
</select>
</div>
</div>
<div class="button_group">
<button type="button" class="button blue admin add" @click="ModalOpen()">공지사항 등록</button>
</div>
</div>
<div class="table">
<custom-grid
ref="table"
:totalItems="'totalItems'"
:url="grid.url"
:pagePerRows="grid.pagePerRows"
:initialRequest="grid.initialRequest"
:pagination="grid.pagination"
:isCheckbox="grid.isCheckbox"
:columns="grid.columns"
:noDataStr="grid.noDataStr"
:addCls="grid.addCls"
:header="grid.headder"
></custom-grid>
</div>
</div>
<NoticePop ref="NoticePop" />
<NoticeUpdatePop ref="NoticeUpdatePop" />
</div>
</template>
<script>
import httpClient from '../../../common/http-client';
import customGrid from '@/components/CustomGrid';
import NoticePop from '../components/NoticePop.vue';
import NoticeUpdatePop from '../components/NoticeUpdatePop.vue';
class CustomATagRenderer {
constructor(props) {
this.props = props;
const el = document.createElement('a');
el.href = 'javascript:void(0);';
el.className = 'btn_text';
el.innerText = String(props.colValue);
this.el = el;
}
getElement() {
return this.el;
}
addEvent(selEl) {
selEl.addEventListener('click', () => {
const { callback } = this.props['cgrido' + this.props.colName].options;
callback(this.props);
});
}
}
export default {
name: 'notice',
components: { customGrid, NoticePop, NoticeUpdatePop },
data() {
return {
totalItems: 0,
perPageCnt: 50,
searchType1: '',
searchText1: '',
options: [
{ text: '20', value: 20 },
{ text: '50', value: 50 },
{ text: '100', value: 100 },
],
grid: {
url: '/api/v1/bo/homeMgt/noticeList',
pagePerRows: 20,
pagination: true,
isCheckbox: true, // true:첫번째 컬럼 앞에 체크박스 생성 / false:체크박스 제거
initialRequest: true,
addCls: 'box_OFvis',
columns: [
{ name: 'no', header: 'No', align: 'center', width: '5%' },
{ name: 'ntNo', header: 'ntNo', align: 'center', width: '5%' },
{ name: 'ctgCdNm', header: '분류코드명', align: 'center', width: '10%' },
{ name: 'emgYn', header: '긴급여부(Y/N)', align: 'center', width: '10%' },
{
name: 'title',
header: '제목',
align: 'left',
width: '50%',
renderer: {
type: CustomATagRenderer,
options: {
callback: this.noticeDetail,
},
},
},
{ name: 'fileYn', header: '파일유무', align: 'center', width: '5%' },
{ name: 'useYn', header: '사용여부', align: 'center', width: '5%' },
{ name: 'regr', header: '등록자', align: 'center', width: '10%' },
{ name: 'regDt', header: '등록일자', align: 'center', width: '10%' },
],
noDataStr: '검색 결과가 없습니다.',
params: {
searchType1: '',
searchType2: '',
searchText1: '',
searchText2: '',
},
excelHeader: [],
},
};
},
mounted() {
// this.fnSelectNoticeList();
//let page = 1;
// 페이지 정보 및 검색 조건
const getCondition = this.$store.getters['searchcondition/getSearchCondition'];
// store에 저장된 페이지 정보 및 검색 조건을 불러오기
let isKeep = false;
if (getCondition) {
this.grid.pagePerRows = getCondition.perPage;
this.grid.params = getCondition.params;
// page = getCondition.page;
isKeep = true;
}
this.search(isKeep);
},
beforeRouteLeave(to, from, next) {
const getP = this.$refs.table.getPagination();
this.$store.commit('searchcondition/updateSearchCondition', {
page: getP._currentPage,
perPage: this.perPageCnt,
params: this.grid.params,
});
// 라우트 하기전 실행
next();
},
methods: {
fnSelectNoticeList() {
const params = { page: 1, pagePerRows: 10 };
httpClient
.post('/api/v1/bo/homeMgt/noticeList', params, { headers: { 'Show-Layer': 'Yes' } })
.then((response) => {
console.log(response.data);
});
},
ModalOpen() {
this.$refs.NoticePop.ModalOpen();
},
noticeDetail(props) {
//console.log(props);
this.$refs.NoticeUpdatePop.ModalOpen(props);
},
search: function (isKeep) {
this.grid.params.searchType1 = this.searchType1;
this.grid.params.searchText1 = this.searchText1;
this.$refs.table.search(this.grid.params, isKeep);
this.sendStoreData();
},
sendStoreData: function () {
const getP = this.$refs.table.getPagination();
this.$store.commit('searchcondition/updateSearchCondition', {
page: getP._currentPage,
perPage: this.perPageCnt,
params: this.grid.params,
});
//const getCondition = this.$store.getters['searchcondition/getSearchCondition'];
},
changePerPage: function () {
// 페이지당 조회할 개수
this.grid.pagePerRows = this.perPageCnt;
this.search(true);
},
},
};
</script>

View File

@@ -1,11 +1,10 @@
import Vue from 'vue';
import Router from 'vue-router';
import store from './store'
import store from './store';
import tokenSvc from '@/common/token-service';
import HubwebLayout from './views/HubwebLayout.vue';
import loginRoutes from './modules/login/router';
import custRoutes from './modules/custMgt/router';
import authRoutes from './modules/sysMgt/router';
@@ -19,8 +18,9 @@ import profileRoutes from './modules/sendNumMgt/router';
import mntrngRoutes from './modules/mntrng/router';
import riskmgtRoutes from './modules/riskMgt/router';
import monthRoutes from './modules/stats/router';
import homeMgtRoutes from './modules/homeMgt/router';
Vue.use(Router)
Vue.use(Router);
const router = new Router({
mode: 'history',
@@ -32,22 +32,22 @@ const router = new Router({
children: [
{
path: '',
component: subsList
},
component: subsList,
},
{
path: '/view/error/404',
component: () => import('./views/ErrorPage404.vue'),
meta: { public: false }
meta: { public: false },
},
{
path: '/view/error/500',
component: () => import('./views/ErrorPage500.vue'),
meta: { public: true }
meta: { public: true },
},
...loginRoutes,
...custRoutes,
...authRoutes,
...channelRoutes,
...authRoutes,
...channelRoutes,
...rejectRoutes,
...clacRoutes,
...templtRoutes,
@@ -55,174 +55,185 @@ const router = new Router({
...mntrngRoutes,
...riskmgtRoutes,
...monthRoutes,
...homeMgtRoutes,
//{path: '*', name: 'error404'}
]
],
},
{path: '*', redirect: '/view/error/404'}
]
{ path: '*', redirect: '/view/error/404' },
],
});
router.beforeEach((to, from, next) => {
const isPublic = to.matched.some(record => record.meta.public);
const loggedIn = !!tokenSvc.getToken();
const isPublic = to.matched.some((record) => record.meta.public);
const loggedIn = !!tokenSvc.getToken();
if (!isPublic && !loggedIn) {
return next('/login');
}else{
var nextUrl = to.fullPath;
var fromUrl = from.fullPath;
var menuUrls = store.getters['login/getMenuUrls'];
if(menuUrls.length > 0){
} else {
var nextUrl = to.fullPath;
var fromUrl = from.fullPath;
var menuUrls = store.getters['login/getMenuUrls'];
if (menuUrls.length > 0) {
var moveFlag = false;
for(var i=0; i<menuUrls.length; i++){
var targetUrl = menuUrls[i];
if(nextUrl == targetUrl){
moveFlag = true;
if(fromUrl != '/' && fromUrl != '/view/error/404' && fromUrl != '/view/error/500'){
if(nextUrl == '/view/error/404' || nextUrl == '/view/error/500' ){
store.commit("login/isErrorPage", true);
}else{
store.commit("login/isErrorPage", false);
if((nextUrl != '/login') && (nextUrl != '/view/login/auth') && (nextUrl != '/view/login/resetPassword') && (nextUrl != '/view/login/updatePassword')){
store.commit("login/isLogin", true);
store.commit("login/isAuthChk", true);
for (var i = 0; i < menuUrls.length; i++) {
var targetUrl = menuUrls[i];
if (nextUrl == targetUrl) {
moveFlag = true;
if (fromUrl != '/' && fromUrl != '/view/error/404' && fromUrl != '/view/error/500') {
if (nextUrl == '/view/error/404' || nextUrl == '/view/error/500') {
store.commit('login/isErrorPage', true);
} else {
store.commit('login/isErrorPage', false);
if (
nextUrl != '/login' &&
nextUrl != '/view/login/auth' &&
nextUrl != '/view/login/resetPassword' &&
nextUrl != '/view/login/updatePassword'
) {
store.commit('login/isLogin', true);
store.commit('login/isAuthChk', true);
}
store.commit("login/saveBeforeUrl", nextUrl);
store.commit('login/saveBeforeUrl', nextUrl);
}
}else if(fromUrl == '/' && loggedIn){
store.commit("login/isErrorPage", false);
} else if (fromUrl == '/' && loggedIn) {
store.commit('login/isErrorPage', false);
}
}
}
}
if((nextUrl == '/custMgt/memberList') || (nextUrl == '/custMgt/memberDetail')
|| (nextUrl == '/custMgt/subsDetail') || (nextUrl == '/custMgt/memberAdminDetail')){
for(var i=0; i<menuUrls.length; i++){
if(menuUrls[i] == '/custMgt/subsList'){
if (
nextUrl == '/custMgt/memberList' ||
nextUrl == '/custMgt/memberDetail' ||
nextUrl == '/custMgt/subsDetail' ||
nextUrl == '/custMgt/memberAdminDetail'
) {
for (var i = 0; i < menuUrls.length; i++) {
if (menuUrls[i] == '/custMgt/subsList') {
moveFlag = true;
}
}
}
// 청약 관리 상세
if(nextUrl == '/custMgt/subsDetail'){
var serviceId = store.getters["dataStore/getDataStore"];
console.log('serviceId : '+serviceId);
if(to.params.serviceId == undefined){
if(serviceId == ''){
if (nextUrl == '/custMgt/subsDetail') {
var serviceId = store.getters['dataStore/getDataStore'];
console.log('serviceId : ' + serviceId);
if (to.params.serviceId == undefined) {
if (serviceId == '') {
return next('/custMgt/subsList');
}else{
} else {
to.params.serviceId = serviceId;
}
}
}
// 회원관리 사용자/어드민 상세
if((nextUrl == '/custMgt/memberDetail') || (nextUrl == '/custMgt/memberAdminDetail')){
var serviceId = store.getters["dataStore/getDataStore"];
if(to.params.serviceId == undefined){
if(serviceId == ''){
if (nextUrl == '/custMgt/memberDetail' || nextUrl == '/custMgt/memberAdminDetail') {
var serviceId = store.getters['dataStore/getDataStore'];
if (to.params.serviceId == undefined) {
if (serviceId == '') {
return next('/custMgt/memberList');
}else{
} else {
to.params.serviceId = serviceId;
}
}
}
}
// url Check 유치채널
if((nextUrl == '/attractMgt/channelDetail')){
for(var i=0; i<menuUrls.length; i++){
if(menuUrls[i] == '/attractMgt/channelList'){
if (nextUrl == '/attractMgt/channelDetail') {
for (var i = 0; i < menuUrls.length; i++) {
if (menuUrls[i] == '/attractMgt/channelList') {
moveFlag = true;
}
}
var userSeq = store.getters["dataStore/getUserSeq"];
if(to.params.userSeq == undefined){
if(userSeq == ''){
}
var userSeq = store.getters['dataStore/getUserSeq'];
if (to.params.userSeq == undefined) {
if (userSeq == '') {
return next('/attractMgt/channelList');
}else{
} else {
to.params.userSeq = userSeq;
}
}
}
// url Check 날짜별 통계
if((nextUrl == '/stats/dayList')){
for(var i=0; i<menuUrls.length; i++){
if(menuUrls[i] == '/stats/monthList'){
}
}
// url Check 날짜별 통계
if (nextUrl == '/stats/dayList') {
for (var i = 0; i < menuUrls.length; i++) {
if (menuUrls[i] == '/stats/monthList') {
moveFlag = true;
}
}
}
// url Check 사업자별 통계
if((nextUrl == '/stats/bsnmDayList')){
for(var i=0; i<menuUrls.length; i++){
if(menuUrls[i] == '/stats/bsnmMonthList'){
// url Check 사업자별 통계
if (nextUrl == '/stats/bsnmDayList') {
for (var i = 0; i < menuUrls.length; i++) {
if (menuUrls[i] == '/stats/bsnmMonthList') {
moveFlag = true;
}
}
}
// url Check 권한 관리
if((nextUrl == '/sysMgt/authAdd') || (nextUrl == '/sysMgt/authModify')){
for(var i=0; i<menuUrls.length; i++){
if(menuUrls[i] == '/sysMgt/authList'){
// url Check 권한 관리
if (nextUrl == '/sysMgt/authAdd' || nextUrl == '/sysMgt/authModify') {
for (var i = 0; i < menuUrls.length; i++) {
if (menuUrls[i] == '/sysMgt/authList') {
moveFlag = true;
}
}
}
if(!moveFlag){
if((fromUrl == '/login') || (fromUrl == '/view/login/auth') || (fromUrl == '/view/login/resetPassword')
|| (fromUrl == '/view/login/updatePassword')){
// url 홈페이지 관리
if (nextUrl == '/homeMgt/notice') {
moveFlag = true;
}
if (!moveFlag) {
if (
fromUrl == '/login' ||
fromUrl == '/view/login/auth' ||
fromUrl == '/view/login/resetPassword' ||
fromUrl == '/view/login/updatePassword'
) {
return next('/login');
}
// store.commit("login/isErrorPage", true);
return next('/view/error/404');
}
if((nextUrl == '/view/login/auth') || (nextUrl == '/view/login/resetPassword')
|| (nextUrl == '/view/login/updatePassword')){
if(fromUrl != '/login'){
if (
nextUrl == '/view/login/auth' ||
nextUrl == '/view/login/resetPassword' ||
nextUrl == '/view/login/updatePassword'
) {
if (fromUrl != '/login') {
return next('/login');
}
}
}
if(nextUrl == '/'){
if (nextUrl == '/') {
const rootUrl = store.getters['login/getRootUrl'];
if(rootUrl == null){
if (rootUrl == null) {
return next('/login');
}
return next(rootUrl);
}
if(nextUrl == '/login' && loggedIn){
const rootUrl = store.getters['login/getRootUrl'];
if(rootUrl == null){
return next('/login');
}
}
return next(rootUrl);
}
if (nextUrl == '/login' && loggedIn) {
const rootUrl = store.getters['login/getRootUrl'];
if (rootUrl == null) {
return next('/login');
}
return next(rootUrl);
}
}
}
to.matched.some(record => {
to.matched.some((record) => {
if (record.meta.usingSearchCondition) {
const shareList = record.meta.shareList;
if (from.name && shareList && shareList.includes(from.name)) {
// shareList에 포함되어 있는 라우터에서 온 경우 검색 조건을 유지한다.
} else {
// 그 외의 경우 검색 조건 초기화
store.commit("searchcondition/updateSearchCondition", null);
store.commit('searchcondition/updateSearchCondition', null);
}
}
next();

View File

@@ -0,0 +1,177 @@
package kr.co.uplus.ez.api.homeMgt;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import kr.co.uplus.ez.api.homeMgt.dto.*;
import kr.co.uplus.ez.common.components.ValidComponents;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.utils.FileIoUtils;
@RestController
@RequestMapping(value ="api/v1/bo/homeMgt")
public class HomeMgtController {
private static final Logger logger = LoggerFactory.getLogger(HomeMgtController.class);
@Autowired
HomeMgtService homeService;
@Autowired
ValidComponents validComponents;
/**
* date : 2022. 10. 18.
* auth : kjh
* desc : 공지사항 조회.
* @param noticeListReqDto
* @return NoticeListResDto
*/
@ApiOperation(value = "noticeList", notes = "공지사항 조회")
@ApiResponses({ @ApiResponse(code = HttpServletResponse.SC_OK, message = "SUCESS") })
@RequestMapping(value = "noticeList", method = {RequestMethod.POST})
@ResponseBody
public NoticeListResDto noticeList(@RequestBody @Valid NoticeListReqDto noticeListReqDto, BindingResult bindingResult, HttpServletResponse response) {
if (validComponents.validParameter(bindingResult)) {
return new NoticeListResDto(ApiResponseCode.CM_PARAMETER_ERROR);
}
return homeService.noticeList(noticeListReqDto);
}
/**
* date : 2022. 10. 21.
* auth : kjh
* desc : 공지사항 등록.
* @param insertNoticeReqDto
* @return InsertNoticeResDto
*/
@ApiOperation(value = "insertNotice", notes = "공지사항 등록")
@ApiResponses({ @ApiResponse(code = HttpServletResponse.SC_OK, message = "SUCESS") })
@RequestMapping(value = "insertNotice", method = {RequestMethod.POST})
@ResponseBody
public InsertNoticeResDto insertNotice(@RequestPart(value = "key") InsertNoticeReqDto insertNoticeReqDto,
MultipartHttpServletRequest multipartRequest) {
return homeService.insertNotice(insertNoticeReqDto ,multipartRequest);
}
/**
* date : 2022. 10. 24.
* auth : kjh
* desc : 공지사항 수정.
* @param updateNoticeReqDto
* @return UpdateNoticeResDto
*/
@ApiOperation(value = "updateNotice", notes = "공지사항 수정")
@ApiResponses({ @ApiResponse(code = HttpServletResponse.SC_OK, message = "SUCESS") })
@RequestMapping(value = "updateNotice", method = {RequestMethod.POST})
@ResponseBody
public UpdateNoticeResDto updateNotice(@RequestPart(value = "key") UpdateNoticeReqDto updateNoticeReqDto,
MultipartHttpServletRequest multipartRequest) {
return homeService.updateNotice(updateNoticeReqDto, multipartRequest);
}
/**
* date : 2022. 10. 24.
* auth : kjh
* desc : 공지사항 editor 이미지 업로드 후 링크 리턴.
* @param updateNoticeReqDto
* @return UpdateNoticeResDto
*/
@ApiOperation(value = "getImageUrl", notes = "공지사항 editor 이미지 업로드 후 링크 리턴")
@ApiResponses({ @ApiResponse(code = HttpServletResponse.SC_OK, message = "SUCESS") })
@RequestMapping(value = "getImageUrl", method = {RequestMethod.POST})
@ResponseBody
public FileResDto fileResDto(MultipartHttpServletRequest multipartRequest) {
return homeService.fileResDto(multipartRequest);
}
/**
* 파일 다운로드
* @throws IOException
*/
@SuppressWarnings("rawtypes")
@RequestMapping("filedownload")
public void filedownload(@RequestBody LinkedHashMap param, HttpServletRequest request, HttpServletResponse response) throws IOException {
logger.debug(param.toString());
File file = new File(param.get("filePath") + File.separator + param.get("fileNm"));
System.out.println("file ::::: " +file);
System.out.println("file.exists() ::::: " + file.exists());
if (file.exists()) {
FileIoUtils.fileDownload(file, request, response );
}
}
@ApiOperation(value = "이미지 미리보기", notes = "이미지 미리보기")
@GetMapping(value = "/preview/{imgurl}", produces=MediaType.APPLICATION_OCTET_STREAM_VALUE)
public ResponseEntity<byte[]> previewImageResource(@PathVariable @ApiParam(value = "이미지 경로") String imgurl) {
System.out.println("imgurl :::: " + imgurl);
System.out.println("call previewImageResource");
try {
String imgurldec = URLDecoder.decode(imgurl);
String imgurlreplace = imgurldec.replaceAll("\\|", "/");
logger.debug("preview image imgurl={} imgurldecode={} imgurlreplace={}", imgurl, imgurldec, imgurlreplace);
Path path = Paths.get(imgurlreplace);
String contentType = Files.probeContentType(path);
String fileNameOnly = imgurlreplace;
String[] fileNameArr = imgurlreplace.split("/");
if(fileNameArr != null && fileNameArr.length != 0) fileNameOnly = fileNameArr[fileNameArr.length-1];
HttpHeaders headers = new HttpHeaders();
headers.setContentDisposition(
ContentDisposition.builder("attachment")
.filename(fileNameOnly, StandardCharsets.UTF_8)
.build());
headers.add(HttpHeaders.CONTENT_TYPE, contentType);
byte[] b = Files.readAllBytes(path);
return new ResponseEntity<byte[]>(b, headers, HttpStatus.OK);
}catch(Exception e) {
logger.error("imgurl err, e={}, e", e.getMessage());
return new ResponseEntity<byte[]>(HttpStatus.NOT_FOUND);
}
}
}

View File

@@ -0,0 +1,29 @@
package kr.co.uplus.ez.api.homeMgt;
import kr.co.uplus.ez.api.homeMgt.dto.*;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface HomeMgtMapper {
int selectNoticeTotalCnt(NoticeListReqDto noticeListReqDto);
List<NoticeDto> selectNoticeList(NoticeListReqDto noticeListReqDto);
int selectNoticeNumber(NoticeListReqDto noticeListReqDto);
void insertNotice(InsertNoticeReqDto insertNoticeReqDto);
int insertNoticeNtNo();
int updateNotice(UpdateNoticeReqDto updateNoticeReqDto);
int updateNoticeFileMaxNum(UpdateNoticeReqDto updateNoticeReqDto);
void insertNoticeFile(InsertNoticeFileDto insertNoticeFileDto);
void delNoticeFile(DelNoticeReqDto delNoticeReqDto);
}

View File

@@ -0,0 +1,286 @@
package kr.co.uplus.ez.api.homeMgt;
import kr.co.uplus.ez.api.homeMgt.dto.*;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.Paging;
import kr.co.uplus.ez.common.utils.DateUtils;
import kr.co.uplus.ez.common.utils.FileIoUtils;
import kr.co.uplus.ez.common.utils.FileUtil;
//import kr.co.uplus.ez.common.utils.EncryptionUtil;
//import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.SqlSessionTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import java.io.File;
import java.util.ArrayList;
//import java.util.HashMap;
import java.util.List;
//import java.util.Map;
@Service
public class HomeMgtService {
private static final Logger logger = LoggerFactory.getLogger(HomeMgtService.class);
@Autowired
@Qualifier("sqlSessionTemplateDb1")
private SqlSessionTemplate sqlSessionMaster;
@Autowired
@Qualifier("sqlSessionTemplateDb2")
private SqlSessionTemplate sqlSessionSlave;
@Value("${file-resource.info.notice.path:/efs/admin/notice/}")
private String noticeFilePath;
/**
* date : 2022. 10. 18.
* auth : kjh
* desc : 공지사항 목록 조회
* @param noticeListReqDto
* @return NoticeListResDto
*/
public NoticeListResDto noticeList(NoticeListReqDto noticeListReqDto) {
HomeMgtMapper homeMgtMapper = sqlSessionSlave.getMapper(HomeMgtMapper.class);
String nowPage = String.valueOf(noticeListReqDto.getPage());
int totalCnt = homeMgtMapper.selectNoticeTotalCnt(noticeListReqDto);
if(totalCnt == 0) {
Paging paging = new Paging();
paging.setPage(nowPage);
paging.setTotalCnt(String.valueOf(totalCnt));
NoticeListRes NoticeListRes = new NoticeListRes();
NoticeListRes.setList(new ArrayList<>());
NoticeListRes.setPaging(paging);
return new NoticeListResDto(ApiResponseCode.CM_NOT_FOUND, NoticeListRes);
}
int page = noticeListReqDto.getPage();
int pagePerRows = noticeListReqDto.getPagePerRows();
page = (page -1) * pagePerRows;
noticeListReqDto.setPage(page);
List<NoticeDto> noticeDto = homeMgtMapper.selectNoticeList(noticeListReqDto);
Paging paging = new Paging();
paging.setPage(nowPage);
paging.setTotalCnt(String.valueOf(totalCnt));
NoticeListRes NoticeListRes = new NoticeListRes();
NoticeListRes.setList(noticeDto);
NoticeListRes.setPaging(paging);
return new NoticeListResDto(ApiResponseCode.SUCCESS, NoticeListRes);
}
/**
* date : 2022. 10. 21.
* auth : kjh
* desc : 공지사항 목록 등록
* @param insertNoticeReqDto
* @return InsertNoticeResDto
*/
public InsertNoticeResDto insertNotice(InsertNoticeReqDto insertNoticeReqDto, MultipartHttpServletRequest multipartRequest) {
HomeMgtMapper homeMgtMapper = sqlSessionSlave.getMapper(HomeMgtMapper.class);
List<MultipartFile> files = multipartRequest.getFiles("files");
String yyyyMMddHHmmss = DateUtils.date2strYMDHMS();
int NT_NO = 0;
//공지사항 등록
try {
homeMgtMapper.insertNotice(insertNoticeReqDto);
NT_NO = homeMgtMapper.insertNoticeNtNo();
}catch(Exception e){
return new InsertNoticeResDto(ApiResponseCode.CM_DB_QUERY_ERR);
}
//공지사항 등록 완료시 파일 저장
int idx = 1;
String yyyyMMdd = DateUtils.date2strYMD();
// Path : efs/admin/notice/yyyy/mm/
String path = noticeFilePath + yyyyMMdd.substring(0, 4) +
File.separator + yyyyMMdd.substring(4, 6) +
File.separator + yyyyMMdd.substring(6, 8);
File dir = new File(path);
if(!dir.isDirectory()) {
dir.mkdirs();
}
try {
for(int i=0; i<files.size(); i++){
// NOTICE FILE UPLOAD.
String ext = FileIoUtils.getExtension(files.get(i).getOriginalFilename());
// File Nm : [reg_req_no]_[doc_no]_[doc_tp_cd].확장자
String fileNm = yyyyMMddHHmmss + "_noticeFile_" + idx +"." + ext;
String titleNm = files.get(i).getOriginalFilename();
long fileSize = files.get(i).getSize();
// File Upload.
FileUtil.upload(files.get(i), fileNm, path);
InsertNoticeFileDto insertNoticeFileDto = new InsertNoticeFileDto();
insertNoticeFileDto.setBbsDivCd("02"); // 게시판 구분 코드 (01:일대일문의,02:공지사항,03:FAQ)
insertNoticeFileDto.setBbsNo(NT_NO);
insertNoticeFileDto.setFileNo(idx);
insertNoticeFileDto.setFileTitle(titleNm);
insertNoticeFileDto.setFileNm(fileNm);
insertNoticeFileDto.setFileSize(fileSize);
insertNoticeFileDto.setFilePath(path.replace("C:/Users/admin/git/hubez-admin/frontend/public", ""));
insertNoticeFileDto.setRegId(insertNoticeReqDto.getRegId());
insertNoticeFileDto.setChgId(insertNoticeReqDto.getRegId());
System.out.println("insertNoticeFileDto.getFilePath() :::: " + insertNoticeFileDto.getFilePath());
homeMgtMapper.insertNoticeFile(insertNoticeFileDto);
idx++;
}
}catch(Exception e) {
return new InsertNoticeResDto(ApiResponseCode.CM_DB_QUERY_ERR);
}
return new InsertNoticeResDto(ApiResponseCode.SUCCESS);
}
/**
* date : 2022. 10. 24.
* auth : kjh
* desc : 공지사항 목록 수정
* @param updateNoticeReqDto
* @return UpdateNoticeResDto
*/
public UpdateNoticeResDto updateNotice(UpdateNoticeReqDto updateNoticeReqDto, MultipartHttpServletRequest multipartRequest) {
HomeMgtMapper homeMgtMapper = sqlSessionMaster.getMapper(HomeMgtMapper.class);
List<MultipartFile> files = multipartRequest.getFiles("files");
String yyyyMMddHHmmss = DateUtils.date2strYMDHMS();
System.out.println(" files len :::: " + files.size());
System.out.println(" legacyFiles :::: " + updateNoticeReqDto.getLegacyFiles());
// 공지사항 수정
try {
homeMgtMapper.updateNotice(updateNoticeReqDto);
} catch (Exception e) {
return new UpdateNoticeResDto(ApiResponseCode.CM_DB_QUERY_ERR);
}
// 공지사항 수정 완료시 파일 저장
int idx = homeMgtMapper.updateNoticeFileMaxNum(updateNoticeReqDto); // 해당 게시물의 최상위 파일 번호 + 1을 가져온다.
String yyyyMMdd = DateUtils.date2strYMD(); // Path : efs/admin/notice/yyyy/mm/
String path = noticeFilePath + yyyyMMdd.substring(0, 4) +
File.separator + yyyyMMdd.substring(4, 6) +
File.separator + yyyyMMdd.substring(6, 8);
File dir = new File(path);
if(!dir.isDirectory()) dir.mkdirs(); // dir 생성
try {
for(int i=0; i<files.size(); i++){
// NOTICE FILE UPLOAD.
String ext = FileIoUtils.getExtension(files.get(i).getOriginalFilename());
// File Nm : [reg_req_no]_[doc_no]_[doc_tp_cd].확장자
String fileNm = yyyyMMddHHmmss + "_noticeFile_" + idx +"." + ext;
String titleNm = files.get(i).getOriginalFilename();
long fileSize = files.get(i).getSize();
// File Upload.
FileUtil.upload(files.get(i), fileNm, path);
InsertNoticeFileDto insertNoticeFileDto = new InsertNoticeFileDto();
insertNoticeFileDto.setBbsDivCd("02"); // 게시판 구분 코드 (01:일대일문의,02:공지사항,03:FAQ)
insertNoticeFileDto.setBbsNo(updateNoticeReqDto.getNtNo());
insertNoticeFileDto.setFileNo(idx);
insertNoticeFileDto.setFileTitle(titleNm);
insertNoticeFileDto.setFileNm(fileNm);
insertNoticeFileDto.setFileSize(fileSize);
insertNoticeFileDto.setFilePath(path.replace("C:/Users/admin/git/hubez-admin/frontend/public", ""));
insertNoticeFileDto.setRegId(updateNoticeReqDto.getChgId());
insertNoticeFileDto.setChgId(updateNoticeReqDto.getChgId());
homeMgtMapper.insertNoticeFile(insertNoticeFileDto);
idx++;
}
}catch(Exception e) {
return new UpdateNoticeResDto(ApiResponseCode.CM_DB_QUERY_ERR);
}
// 첨부파일 삭제
if(!updateNoticeReqDto.getDelFileNo().isEmpty()) {
String[] delFile = updateNoticeReqDto.getDelFileNo().split(",");
for(int j=0; j<delFile.length; j++){
System.out.println("delFile :::: " + delFile[j]);
DelNoticeReqDto delNoticeReqDto = new DelNoticeReqDto();
delNoticeReqDto.setFileNo(Integer.parseInt(delFile[j]));
delNoticeReqDto.setNtNo(updateNoticeReqDto.getNtNo());
System.out.println(delNoticeReqDto);
homeMgtMapper.delNoticeFile(delNoticeReqDto);
}
}else {
System.out.println("파일이 빈 상태입니다.");
}
return new UpdateNoticeResDto(ApiResponseCode.SUCCESS);
}
/**
* date : 2022. 10. 21.
* auth : kjh
* desc : 공지사항 editor 이미지 등록시 URL 리턴
* @param insertNoticeFileDto
* @return FileResDto
*/
public FileResDto fileResDto(MultipartHttpServletRequest multipartRequest) {
HomeMgtMapper homeMgtMapper = sqlSessionSlave.getMapper(HomeMgtMapper.class);
List<MultipartFile> files = multipartRequest.getFiles("files");
System.out.println(" files len :::: " + files.size());
String yyyyMMddHHmmss = DateUtils.date2strYMDHMS();
String yyyyMMdd = DateUtils.date2strYMD(); // Path : efs/admin/notice/yyyy/mm/
String path = noticeFilePath + yyyyMMdd.substring(0, 4) +
File.separator + yyyyMMdd.substring(4, 6) +
File.separator + yyyyMMdd.substring(6, 8);
File dir = new File(path);
String uploadFile = "";
if(!dir.isDirectory()) dir.mkdirs(); // dir 생성
try {
for(int i=0; i<files.size(); i++){
String ext = FileIoUtils.getExtension(files.get(i).getOriginalFilename());
String fileNm = yyyyMMddHHmmss + "_noticeEditFile." + ext;
// File Upload.
FileUtil.upload(files.get(i), fileNm, path);
path = path.replace("C:/Users/admin/git/hubez-admin/frontend/public", "");
uploadFile = path.replace("\\","/") + File.separator + fileNm;
}
}catch(Exception e) {
return new FileResDto(ApiResponseCode.CM_DB_QUERY_ERR);
}
return new FileResDto(ApiResponseCode.SUCCESS, uploadFile);
}
}

View File

@@ -0,0 +1,18 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class DelNoticeReqDto implements Serializable{
@ApiModelProperty(example = "공지사항 번호", name = "공지사항 번호", dataType = "Int")
private int ntNo;
@ApiModelProperty(example = "파일 번호", name = "파일 번호", dataType = "Int")
private int fileNo;
}

View File

@@ -0,0 +1,31 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import java.util.List;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.ResponseMessage;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class FileResDto extends ResponseMessage implements Serializable {
// 데이터.
private Object data;
public FileResDto() {
this.retCode = ApiResponseCode.SUCCESS.getResultCode();
this.retMsg = ApiResponseCode.SUCCESS.getResultMsg();
}
public FileResDto(ApiResponseCode returnStr) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
}
public FileResDto(ApiResponseCode returnStr, Object data) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
this.data = data;
}
}

View File

@@ -0,0 +1,39 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class InsertNoticeFileDto implements Serializable {
@ApiModelProperty(example = "게시판 구분코드", name = "게시판 구분코드", dataType = "String")
private String bbsDivCd;
@ApiModelProperty(example = "게시판 식별번호", name = "게시판 식별번호", dataType = "Int")
private int bbsNo;
@ApiModelProperty(example = "파일 번호", name = "파일 번호", dataType = "Int")
private int fileNo;
@ApiModelProperty(example = "파일 제목", name = "파일 제목", dataType = "String")
private String fileTitle;
@ApiModelProperty(example = "파일 명", name = "파일 명", dataType = "String")
private String fileNm;
@ApiModelProperty(example = "파일 명", name = "파일 명", dataType = "Long")
private Long fileSize;
@ApiModelProperty(example = "파일 경로", name = "파일 경로", dataType = "String")
private String filePath;
@ApiModelProperty(example = "등록 ID", name = "등록 ID", dataType = "String")
private String regId;
@ApiModelProperty(example = "수정 ID", name = "수정 ID", dataType = "String")
private String chgId;
}

View File

@@ -0,0 +1,36 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class InsertNoticeReqDto implements Serializable {
@ApiModelProperty(example = "분류 코드", name = "분류 코드", dataType = "String")
private String ctgCd;
@ApiModelProperty(example = "긴급 여부", name = "긴급 여부", dataType = "String")
private String emgYn;
@ApiModelProperty(example = "제목", name = "제목", dataType = "String")
private String title;
@ApiModelProperty(example = "공지 내용", name = "공지 내용", dataType = "String")
private String ntSbst;
@ApiModelProperty(example = "등록자", name = "등록자", dataType = "String")
private String regr;
@ApiModelProperty(example = "사용 여부", name = "사용 여부", dataType = "String")
private String useYn;
@ApiModelProperty(example = "등록 ID", name = "등록 ID", dataType = "String")
private String regId;
@ApiModelProperty(example = "변경 ID", name = "변경 ID", dataType = "String")
private String chgId;
}

View File

@@ -0,0 +1,31 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.ResponseMessage;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class InsertNoticeResDto extends ResponseMessage implements Serializable{
// 데이터.
private Object data;
public InsertNoticeResDto() {
this.retCode = ApiResponseCode.SUCCESS.getResultCode();
this.retMsg = ApiResponseCode.SUCCESS.getResultMsg();
}
public InsertNoticeResDto(ApiResponseCode returnStr) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
}
public InsertNoticeResDto(ApiResponseCode returnStr, Object data) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
this.data = data;
}
}

View File

@@ -0,0 +1,82 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class NoticeDto implements Serializable {
@ApiModelProperty(example = "리스트 번호", name = "리스트 번호", dataType = "Integer")
private Integer no;
@ApiModelProperty(example = "공지 번호", name = "공지 번호", dataType = "int")
private int ntNo;
@ApiModelProperty(example = "분류코드", name = "분류코드", dataType = "String")
private String ctgCd;
@ApiModelProperty(example = "분류코드명", name = "분류코드명", dataType = "String")
private String ctgCdNm;
@ApiModelProperty(example = "긴급여부(Y/N)", name = "긴급여부(Y/N)", dataType = "String")
private String emgYn;
@ApiModelProperty(example = "제목", name = "제목", dataType = "String")
private String title;
@ApiModelProperty(example = "공지 내용", name = "공지 내용", dataType = "String")
private String ntSbst;
@ApiModelProperty(example = "등록자", name = "등록자", dataType = "String")
private String regr;
@ApiModelProperty(example = "사용 여부", name = "사용 여부", dataType = "String")
private String useYn;
@ApiModelProperty(example = "조회수", name = "조회수", dataType = "Int")
private String retvCnt;
@ApiModelProperty(example = "등록 ID", name = "등록 ID", dataType = "String")
private String regId;
@ApiModelProperty(example = "등록 일시", name = "등록 일시", dataType = "String")
private String regDt;
@ApiModelProperty(example = "변경 ID", name = "변경 ID", dataType = "String")
private String chgId;
@ApiModelProperty(example = "변경 일시", name = "변경 일시", dataType = "String")
private String chgDt;
@ApiModelProperty(example = "파일 제목", name = "파일 제목", dataType = "String")
private String fileTitle;
@ApiModelProperty(example = "파일 이름", name = "파일 이름", dataType = "String")
private String fileNm;
@ApiModelProperty(example = "파일 경로", name = "파일 경로", dataType = "String")
private String filePath;
@ApiModelProperty(example = "파일 개수", name = "파일 개수", dataType = "String")
private String fileCount;
@ApiModelProperty(example = "파일 유무", name = "파일 유무", dataType = "String")
private String fileYn;
@ApiModelProperty(example = "파일 번호", name = "파일 번호", dataType = "String")
private String fileNo;
@NotNull
@ApiModelProperty(example = "페이지당 조회할 목록 수",notes = "페이지당 조회할 목록 수", name = "페이지당 조회할 목록 수", dataType = "int")
private int pagePerRows;
@NotNull
@ApiModelProperty(example = "현재 페이지", name = "현재 페이지", dataType = "int")
private int page;
}

View File

@@ -0,0 +1,43 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class NoticeListReqDto implements Serializable {
@ApiModelProperty(example = "분류 코드", name = "분류 코드", dataType = "String")
private String searchType1;
@ApiModelProperty(example = "제목 검색어", name = "제목 검색어", dataType = "String")
private String searchText1;
@ApiModelProperty(example = "분류코드", name = "분류코드", dataType = "String")
private String ctgCd;
@ApiModelProperty(example = "긴급여부(Y/N)", name = "긴급여부(Y/N)", dataType = "String")
private String emgYn;
@ApiModelProperty(example = "제목", name = "제목", dataType = "String")
private String title;
@ApiModelProperty(example = "공지 내용", name = "공지 내용", dataType = "String")
private String ntSbst;
@ApiModelProperty(example = "사용 여부", name = "사용 여부", dataType = "String")
private String useYn;
@NotNull
@ApiModelProperty(example = "페이지당 조회할 목록 수",notes = "페이지당 조회할 목록 수", name = "페이지당 조회할 목록 수", dataType = "int")
private int pagePerRows;
@NotNull
@ApiModelProperty(example = "현재 페이지", name = "현재 페이지", dataType = "int")
private int page;
}

View File

@@ -0,0 +1,15 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import java.util.List;
import kr.co.uplus.ez.common.data.Paging;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class NoticeListRes implements Serializable {
private Paging paging;
private List<NoticeDto> list;
}

View File

@@ -0,0 +1,30 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.ResponseMessage;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class NoticeListResDto extends ResponseMessage implements Serializable {
// 데이터.
private NoticeListRes data;
public NoticeListResDto() {
this.retCode = ApiResponseCode.SUCCESS.getResultCode();
this.retMsg = ApiResponseCode.SUCCESS.getResultMsg();
}
public NoticeListResDto(ApiResponseCode returnStr) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
}
public NoticeListResDto(ApiResponseCode returnStr, NoticeListRes data) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
this.data = data;
}
}

View File

@@ -0,0 +1,42 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import javax.validation.constraints.NotNull;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class UpdateNoticeReqDto implements Serializable {
@NotNull
@ApiModelProperty(example = "공지 번호", name = "공지 번호", dataType = "int")
private int ntNo;
@ApiModelProperty(example = "분류 코드", name = "분류 코드", dataType = "String")
private String ctgCd;
@ApiModelProperty(example = "긴급 여부", name = "긴급 여부", dataType = "String")
private String emgYn;
@ApiModelProperty(example = "제목", name = "제목", dataType = "String")
private String title;
@ApiModelProperty(example = "공지 내용", name = "공지 내용", dataType = "String")
private String ntSbst;
@ApiModelProperty(example = "사용 여부", name = "사용 여부", dataType = "String")
private String useYn;
@ApiModelProperty(example = "변경 ID", name = "변경 ID", dataType = "String")
private String chgId;
@ApiModelProperty(example = "업로드된 파일", name = "업로드된 파일", dataType = "String")
private String legacyFiles;
@ApiModelProperty(example = "삭제 파일", name = "삭제 파일", dataType = "Int")
private String delFileNo;
}

View File

@@ -0,0 +1,30 @@
package kr.co.uplus.ez.api.homeMgt.dto;
import java.io.Serializable;
import kr.co.uplus.ez.common.data.ApiResponseCode;
import kr.co.uplus.ez.common.data.ResponseMessage;
import lombok.Data;
@SuppressWarnings("serial")
@Data
public class UpdateNoticeResDto extends ResponseMessage implements Serializable{
// 데이터.
private Object data;
public UpdateNoticeResDto() {
this.retCode = ApiResponseCode.SUCCESS.getResultCode();
this.retMsg = ApiResponseCode.SUCCESS.getResultMsg();
}
public UpdateNoticeResDto(ApiResponseCode returnStr) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
}
public UpdateNoticeResDto(ApiResponseCode returnStr, Object data) {
this.retCode = returnStr.getResultCode();
this.retMsg = returnStr.getResultMsg();
this.data = data;
}
}

View File

@@ -58,8 +58,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
"/v3/api-docs/**",
"/",
"/socket/**",
"/api/v1/bo/sendNumMgt/filedownload"
,"/common/healthChk"
"/api/v1/bo/sendNumMgt/filedownload",
"/api/v1/bo/homeMgt/filedownload",
"/common/healthChk"
};
private static final String[] AUTH_URL_ARRAY = {
@@ -72,6 +73,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
"/api/v1/bo/mntrng/**",
"/api/v1/bo/riskMgt/sendNum/**",
"/api/v1/bo/stats/**",
"/api/v1/bo/homeMgt/**",
"/view/error/**"
};

View File

@@ -51,6 +51,7 @@ msghubez:
applicationId: EZ_ADMIN
uri:
sendTemplateMail: /api/v1/fo/sendTemplateMail
notice: /api/v1/fo/notice
homepageLogin: /auth/bo
authKey: "bohubez!@#$%"
@@ -70,6 +71,8 @@ file-resource:
info:
sendNumber:
path: /efs/admin/sendNumber/
notice:
path: /efs/admin/notice/
sendMsg:
tableNm: EZ_MSG_REAL

View File

@@ -51,6 +51,7 @@ msghubez:
applicationId: EZ_ADMIN
uri:
sendTemplateMail: /api/v1/fo/sendTemplateMail
notice: /api/v1/fo/notice
homepageLogin: /auth/bo
authKey: "bohubez!@#$%"
@@ -70,6 +71,8 @@ file-resource:
info:
sendNumber:
path: /efs/admin/sendNumber/
notice:
path: /efs/admin/notice/
sendMsg:
tableNm: EZ_MSG_NORMAL

View File

@@ -51,6 +51,7 @@ msghubez:
applicationId: EZ_ADMIN
uri:
sendTemplateMail: /api/v1/fo/sendTemplateMail
notice: /api/v1/fo/notice
homepageLogin: /auth/bo
authKey: "bohubez!@#$%"
@@ -70,6 +71,8 @@ file-resource:
info:
sendNumber:
path: /efs/admin/sendNumber/
notice:
path: /efs/admin/notice/
sendMsg:
tableNm: EZ_MSG_REAL

View File

@@ -51,6 +51,7 @@ msghubez:
applicationId: EZ_ADMIN
uri:
sendTemplateMail: /api/v1/fo/sendTemplateMail
notice: /api/v1/fo/notice
homepageLogin: /auth/bo
authKey: "bohubez!@#$%"
@@ -70,6 +71,8 @@ file-resource:
info:
sendNumber:
path: /efs/admin/sendNumber/
notice:
path: /efs/admin/notice/
sendMsg:
tableNm: EZ_MSG_REAL

View File

@@ -0,0 +1,214 @@
<?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="kr.co.uplus.ez.api.homeMgt.HomeMgtMapper">
<!-- 공지사항 개수 조회 -->
<select id="selectNoticeTotalCnt"
parameterType="kr.co.uplus.ez.api.homeMgt.dto.NoticeListReqDto"
resultType="int">
/* homeMgt-mapper.xml(selectNoticeTotalCnt) */
SELECT
COUNT(*)
FROM
hubez_common.EZ_NTBBS N1
WHERE 1 = 1
<include refid="NoticeListCondition"></include>
</select>
<!-- 공지사항 조회 -->
<select id="selectNoticeList"
parameterType="kr.co.uplus.ez.api.homeMgt.dto.NoticeListReqDto"
resultType="kr.co.uplus.ez.api.homeMgt.dto.NoticeDto">
/* sysMgt-mapper.xml(selectNoticeList) */
SELECT
@ROWNUM := @ROWNUM + 1 AS NO,
NT_NO,
CTG_CD,
(
SELECT DTL_CD_NM
FROM hubez_common.EZ_CD_DTL
WHERE DTL_CD = N1.CTG_CD
AND GRP_CD = 'NTBBS_CTG_CD' AND USE_YN = 'Y'
) AS CTG_CD_NM,
TITLE,
EMG_YN,
NT_SBST,
REGR,
USE_YN,
RETV_CNT,
REG_ID,
DATE_FORMAT(REG_DT, '%Y-%m-%d') AS regDt,
CHG_ID,
CHG_DT,
(
SELECT
GROUP_CONCAT(FILE_NO SEPARATOR ',')
FROM hubez_common.EZ_BBS_FATC
WHERE BBS_NO = N1.NT_NO
AND BBS_DIV_CD = '02'
) AS FILE_NO,
(
SELECT
GROUP_CONCAT(FILE_PATH SEPARATOR ',')
FROM hubez_common.EZ_BBS_FATC
WHERE BBS_NO = N1.NT_NO
AND BBS_DIV_CD = '02'
) AS FILE_PATH,
(
SELECT
GROUP_CONCAT(FILE_NM SEPARATOR ',')
FROM hubez_common.EZ_BBS_FATC
WHERE BBS_NO = N1.NT_NO
AND BBS_DIV_CD = '02'
) AS FILE_NM,
(
SELECT
GROUP_CONCAT(FILE_TITLE SEPARATOR ',')
FROM hubez_common.EZ_BBS_FATC
WHERE BBS_NO = N1.NT_NO
AND BBS_DIV_CD = '02'
) AS FILE_TITLE,
(SELECT COUNT(*) FROM hubez_common.EZ_BBS_FATC WHERE BBS_NO = N1.NT_NO AND BBS_DIV_CD = '02') AS FILE_COUNT,
CASE
WHEN
(SELECT COUNT(*) FROM hubez_common.EZ_BBS_FATC WHERE BBS_NO = N1.NT_NO AND BBS_DIV_CD = '02') > 0 THEN "Y"
ELSE
"N"
END AS FILE_YN
FROM
hubez_common.EZ_NTBBS N1 , ( SELECT @ROWNUM := #{page} ) AS R
WHERE 1=1
<include refid="NoticeListCondition"></include>
ORDER BY N1.REG_DT DESC
LIMIT #{page}, #{pagePerRows}
</select>
<!-- 공지사항 채번 -->
<select id="selectNoticeNumber"
parameterType="kr.co.uplus.ez.api.homeMgt.dto.NoticeListReqDto"
resultType="int">
/* sysMgt-mapper.xml(selectNoticeList) */
SELECT
NT_NO,
FROM
hubez_common.EZ_NTBBS N1
WHERE 1=1
<include refid="NoticeListCondition"></include>
ORDER BY N1.REG_DT DESC
LIMIT #{page}, #{pagePerRows}
</select>
<!-- 공지사항 등록 -->
<insert id="insertNotice" parameterType="kr.co.uplus.ez.api.homeMgt.dto.InsertNoticeReqDto">
/* homeMgt-mapper.xml (insertNotice) */
INSERT INTO
hubez_common.EZ_NTBBS(
CTG_CD,
EMG_YN,
TITLE,
NT_SBST,
REGR,
USE_YN,
RETV_CNT,
REG_ID,
REG_DT,
CHG_ID,
CHG_DT
)VALUES(
#{ctgCd},
#{emgYn},
#{title},
#{ntSbst},
#{regr},
#{useYn},
0,
#{regId},
NOW(),
#{chgId},
NOW()
)
</insert>
<!-- 공지사항 채번 -->
<select id="insertNoticeNtNo" resultType="int">
SELECT LAST_INSERT_ID()
</select>
<!-- 공지사항 파일 등록 -->
<insert id="insertNoticeFile" parameterType="kr.co.uplus.ez.api.homeMgt.dto.InsertNoticeFileDto">
INSERT INTO
hubez_common.EZ_BBS_FATC (
BBS_DIV_CD,
BBS_NO,
FILE_NO,
FILE_TITLE,
FILE_NM,
FILE_SIZE,
FILE_PATH,
DOWNL_CNT,
REG_ID,
REG_DT,
CHG_ID,
CHG_DT
)
VALUES(
#{bbsDivCd},
#{bbsNo},
#{fileNo},
#{fileTitle},
#{fileNm},
#{fileSize},
#{filePath},
0,
#{regId},
NOW(),
#{chgId},
NOW()
)
</insert>
<!-- 공지사항 정보 변경 -->
<update id="updateNotice" parameterType="kr.co.uplus.ez.api.homeMgt.dto.UpdateNoticeReqDto">
/* homeMgt-mapper.xml (updateNotice) */
UPDATE hubez_common.EZ_NTBBS
SET
CHG_DT = now()
,CTG_CD = #{ctgCd}
,EMG_YN = #{emgYn}
,USE_YN = #{useYn}
,TITLE = #{title}
,NT_SBST = #{ntSbst}
,CHG_DT = NOW()
,CHG_ID = #{chgId}
WHERE
NT_NO = #{ntNo}
</update>
<!-- 첨부파일 번호 최근값 가져오기 -->
<select id="updateNoticeFileMaxNum" parameterType="kr.co.uplus.ez.api.homeMgt.dto.UpdateNoticeReqDto" resultType="int">
SELECT
IFNULL( MAX(FILE_NO), 0) + 1
FROM hubez_common.EZ_BBS_FATC
WHERE BBS_NO = #{ntNo}
</select>
<!-- 첨부파일 삭제 -->
<delete id="delNoticeFile" parameterType="kr.co.uplus.ez.api.homeMgt.dto.DelNoticeReqDto">
DELETE FROM hubez_common.EZ_BBS_FATC
WHERE BBS_NO = #{ntNo}
AND FILE_NO = #{fileNo}
</delete>
<sql id="NoticeListCondition">
<if test="searchType1 != null and searchType1 != ''">
AND N1.CTG_CD = #{searchType1}
</if>
<if test="searchText1 != null and searchText1 != ''">
AND N1.TITLE LIKE CONCAT('%', #{searchText1}, '%')
</if>
</sql>
</mapper>

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-626b9efc"],{bc8d:function(t,r,o){"use strict";o.r(r);var n=function(){var t=this,r=t._self._c;return r("div",{staticClass:"error-body"},[r("img",{attrs:{src:o("ce04")}}),r("p",{staticClass:"header"},[t._v("페이지를 찾을 수 없습니다.")]),t._m(0),r("p",{staticClass:"error-btns"},[r("a",{attrs:{href:"javascript:void(0);"},on:{click:function(r){return t.backGo()}}},[t._v("이전 페이지로")]),r("a",{attrs:{href:"javascript:void(0);"},on:{click:function(r){return t.goMain()}}},[t._v("메인으로")])])])},s=[function(){var t=this,r=t._self._c;return r("span",{staticClass:"message"},[t._v("웹 페이지의 주소가 잘못 입력되었거나,"),r("br"),t._v("\n 변경 또는 삭제되어 요청하신 페이지를 찾을 수 없습니다. "),r("br"),t._v("\n 입력하신 주소가 정확한지 다시 한번 확인해 주시기 바랍니다."),r("br"),t._v("\n 이용에 불편을 드려 죄송합니다.\n ")])}],e={name:"error404",data:function(){return{}},created:function(){this.$store.commit("login/isErrorPage",!0)},mounted:function(){},destroyed:function(){this.$store.commit("login/isErrorPage",!1)},methods:{backGo:function(){var t=this.$store.getters["login/getBeforeUrl"];this.$store.commit("login/isErrorPage",!1),this.$router.push({path:t}).catch((function(){}))},goMain:function(){var t=this.$store.getters["login/getRootUrl"];this.$store.commit("login/isErrorPage",!1),this.$router.push({path:t}).catch((function(){}))}}},i=e,c=o("2877"),a=Object(c["a"])(i,n,s,!1,null,null,null);r["default"]=a.exports},ce04:function(t,r,o){t.exports=o.p+"../static/img/error_message_page.f64f1c59.png"}}]);
//# sourceMappingURL=chunk-626b9efc.afde63a0.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7fafe7e9"],{"123b":function(t,r,s){"use strict";s.r(r);var o=function(){var t=this,r=t._self._c;return r("div",{staticClass:"error-body"},[r("img",{attrs:{src:s("ffa1")}}),r("p",{staticClass:"header"},[t._v("시스템 오류")]),t._m(0),r("p",{staticClass:"error-btns"},[r("a",{attrs:{href:"javascript:void(0);"},on:{click:function(r){return t.backGo()}}},[t._v("이전 페이지로")]),r("a",{attrs:{href:"javascript:void(0);"},on:{click:function(r){return t.goMain()}}},[t._v("메인으로")])])])},n=[function(){var t=this,r=t._self._c;return r("span",{staticClass:"message"},[t._v("이용에 불편을 드려 죄송합니다."),r("br"),t._v("\n 일시적인 오류가 발생하였습니다. "),r("br"),t._v("\n 잠시 후 이용하여 주시기 바랍니다.\n ")])}],i={data:function(){return{}},created:function(){this.$store.commit("login/isErrorPage",!0)},mounted:function(){},destroyed:function(){this.$store.commit("login/isErrorPage",!1)},methods:{backGo:function(){var t=this.$store.getters["login/getBeforeUrl"];this.$store.commit("login/isErrorPage",!1),this.$router.push({path:t}).catch((function(){}))},goMain:function(){var t=this.$store.getters["login/getRootUrl"];this.$store.commit("login/isErrorPage",!1),this.$router.push({path:t}).catch((function(){}))}}},e=i,a=s("2877"),c=Object(a["a"])(e,o,n,!1,null,null,null);r["default"]=c.exports},ffa1:function(t,r,s){t.exports=s.p+"../static/img/error_message_system.7160e0d0.png"}}]);
//# sourceMappingURL=chunk-7fafe7e9.ea3075f8.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1 @@
<!DOCTYPE html><html lang=ko><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><link rel=icon href=/logo.png><title>hubez-admin-web</title><link href=/../static/js/chunk-626b9efc.afde63a0.js rel=prefetch><link href=/../static/js/chunk-7fafe7e9.ea3075f8.js rel=prefetch><link href=/../static/css/app.f9c9f764.css rel=preload as=style><link href=/../static/js/app.62224446.js rel=preload as=script><link href=/../static/js/chunk-vendors.9b80732e.js rel=preload as=script><link href=/../static/css/app.f9c9f764.css rel=stylesheet></head><body><noscript><strong>We're sorry but hubez-admin-web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/../static/js/chunk-vendors.9b80732e.js></script><script src=/../static/js/app.62224446.js></script></body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -7,6 +7,8 @@ xssconfig :
- "/projectApi/manage/saveProject"
- "/api/v1/bo/sendNumMgt/insertNumber"
- "/api/v1/bo/sendNumMgt/filedownload"
# cross-site origin 이면서 application/x-www-form-urlencoded (post) 일때 변수 매핑이 안됨. 제외처리필요.
- "/api/v1/bo/homeMgt/preview"
#- "/uc/test/testUrl" #테스트 URL
#xss 제외 방식(allow, except)
#allow - escape-characters 를 모두 적용 후 allow-elements 만 <, > 치환