File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
<template>
<div :class="{
'content overflow-y': true,
'overflow-y': this.$route.path.startsWith('/kdm'),
}">
<div class="admin-page-title mb30" v-if="this.$route.path.startsWith('/kdm')">
<p>교육 ・ 컨설팅</p>
</div>
<div :class="{'top-banner banner': true, [bannerId]: true}" v-else-if="this.$route.path.startsWith('/aidt')">
<div class="flex-column align-center justify-center content">
<h1 class="banner-title text-ct white">{{ $getMenuInfo().menuNm }}</h1>
<p class="box-title text-ct white">{{ $getMenuInfo().menuCn }}</p>
</div>
</div>
<PageNavigationBar v-if="this.$route.path.startsWith('/aidt')"/>
<div :class="{ 'w1280 pt100 pb100': this.$route.path.startsWith('/aidt') }">
<div class="table-zone">
<div class="pb15">
<p class="text-rg small-text"><span class="red-text">*</span>필수사항입니다.</p>
</div>
<table class="form-table mb30">
<colgroup>
<col width="160px" />
<col width="auto" />
<col width="150px" />
<col width="auto" />
</colgroup>
<tbody>
<tr>
<th class=" text-rg">
<span>카테고리</span>
</th>
<td colspan="3">
<div class="gd-2">
<select name="category" id="category" class="full-select" v-model="eduCn.edu_cnslt_ctgry_cd">
<option value="" selected disabled>선택해주세요.</option>
<option v-for="(ctgryCd, idx) in ctgryCdList" :key="idx" :value="ctgryCd.cdId">
{{ ctgryCd.cdNm }}
</option>
</select>
</div>
</td>
</tr>
<tr>
<th class=" text-rg">
<span>교육 ・ 컨설팅명</span>
</th>
<td colspan="3"><input type="text" class="full-input" placeholder="교육 및 컨설팅명을 입력하세요." v-model="eduCn.edu_cnslt_ttl"></td>
</tr>
<tr >
<th class="text-rg ">
<span>교육 ・ 컨설팅 내용</span>
</th>
<td colspan="3">
<textarea name="smart" id="smart" style="width:100%; height: 35rem;"></textarea>
</td>
</tr>
<tr>
<th class=" text-rg">
<span>대표이미지</span>
</th>
<td colspan="3">
<div class="gd-12 pr0">
<div class="flex align-center">
<div class="gd-2 pl0 pr0">
<label for="imgFile" class="large-btn blue-border-btn text-ct">파일찾기</label>
<input type="file" id="imgFile" ref="imgFile" @change="fnImgFileInsert" multiple
accept="image/*">
</div>
<div class="gd-12 pl0">
<div>
<ul v-if="imgFileList.length > 0" style="max-height: 20rem;" class="pt10 pb10 overflow-y">
<li v-for="(file, idx) in imgFileList" :key="index"
class="pd10 mb10 border radius">
<div v-if="file['fileId'] != null"
class="flex align-center justify-between">
<p>{{ file["fileNm"] }}.{{ file["extnNm"] }}</p>
<button class="del-btn"
@click="fnImgFileDelete(file, idx)">X</button>
</div>
<div v-else class="flex align-center justify-between">
<p> {{ file.name }}</p>
<button class="del-btn"
@click="fnImgFileDelete(file, idx)">X</button>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</td>
</tr>
<tr class="border-t">
<th class="text-rg">
첨부파일
</th>
<td colspan="3">
<div class="gd-12 pr0">
<div class="flex align-center">
<div class="gd-2 pl0 pr0">
<label for="file" class="large-btn blue-border-btn text-ct">파일찾기</label>
<input type="file" id="file" ref="file" @change="fnFileInsert" multiple>
</div>
<div class="gd-12 pl0">
<div>
<ul v-if="fileList.length > 0" style="max-height: 20rem;" class="pt10 pb10 overflow-y">
<li v-for="(file, idx) in fileList" :key="index"
class="pd10 mb10 border radius">
<div v-if="file['fileId'] != null"
class="flex align-center justify-between">
<p> {{ file["fileNm"] }}.{{ file["extnNm"] }}</p>
<button class="del-btn"
@click="fnFileDelete(file, idx)">X</button>
</div>
<div v-else class="flex align-center justify-between">
<p>{{ file.name }}</p>
<button class="del-btn"
@click="fnFileDelete(file, idx)">X</button>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</td>
</tr>
<tr class="border-t">
<th class="text-rg">
<span>교육 ・ 컨설팅 대상자</span>
</th>
<td>
<div class="flex align-center no-gutters">
<div class="gd-3">
<input type="radio" name="target" id="targetN" class="mr5" value="N" v-model="eduCn.ent_mngr_yn"/>
<label for="targetN">기업회원</label>
</div>
<div class="gd-3">
<input type="radio" name="target" id="targetY" class="mr5" value="Y" v-model="eduCn.ent_mngr_yn"/>
<label for="targetY">기업단위</label>
</div>
</div>
</td>
<th class="text-rg" v-show="eduCn.ent_mngr_yn === 'Y'">
<span>참석 인원 기준</span>
</th>
<td v-show="eduCn.ent_mngr_yn === 'Y'">
<input type="text" name="attend " id="attend" placeholder="기업당 참석 인원 기준을 입력하세요." v-model="eduCn.rmrk_cn"/>
</td>
</tr>
<tr class="border-t">
<th class="text-rg">
<span>첨부파일 필수여부</span>
</th>
<td>
<div class="flex align-center no-gutters">
<div class="gd-3">
<input type="radio" name="file" id="fileY" class="mr5" value="Y" v-model="eduCn.atch_file_esntl_yn"/>
<label for="fileY">사용</label>
</div>
<div class="gd-3">
<input type="radio" name="file" id="fileN" class="mr5" value="N" v-model="eduCn.atch_file_esntl_yn"/>
<label for="fileN">미사용</label>
</div>
</div>
</td>
<th class="text-rg">
<span>공개여부</span>
</th>
<td>
<div class="flex align-center no-gutters">
<div class="gd-3">
<input type="radio" name="notice" id="notice_y" class="mr5" value="Y" v-model="eduCn.rls_yn"/>
<label for="notice_y">공개</label>
</div>
<div class="gd-3">
<input type="radio" name="notice" id="notice_n" class="mr5" value="N" v-model="eduCn.rls_yn"/>
<label for="notice_n">비공개</label>
</div>
</div>
</td>
</tr>
<tr class="border-t">
<th class=" text-rg">
<span>문의처</span>
</th>
<td colspan="3">
<input type="text" name="" id="" class="gd-3" placeholder="문의처를 입력하세요." v-model="eduCn.edu_cnslt_cttpc_cn"/>
</td>
</tr>
<tr >
<th class=" text-rg">
<span>장소</span>
</th>
<td colspan="3">
<input type="text" class="full-input" placeholder="교육장소를 입력하세요." v-model="eduCn.edu_cnslt_plc_nm">
</td>
</tr>
</tbody>
</table>
</div>
<div class="flex justify-end align-center no-gutters">
<div class="gd-1 mr10">
<button class="large-btn gray-btn" @click="fnCancel">취소</button>
</div>
<div class="gd-1 ">
<button class="large-btn blue-btn" @click="fnInsert">{{ eduCn.edu_cnslt_id == null ? '등록' : '수정'}}</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { mdiClose } from '@mdi/js';
import queryParams from '../../../../resources/js/queryParams';
import axios from "axios";
import PageNavigationBar from '../../../component/pagenavigationbar/PageNavigationBar.vue';
//API
import { findByEduId } from '../../../../resources/api/eduCn.js'
export default {
mixins: [queryParams],
data() {
return {
file: null,
iconPath: mdiClose,
path: this.$store.state.path,
pageAuth: this.$store.state.pageAuth,
pageId: this.$route.query.pageId,
// 글 작성 모드
// insert - 등록 (기본)
// update - 수정
editMode: "insert",
eduCn: {},
// 파일 업로드
files: null,
fileList: [],
deleteFileList: [],
// 파일 업로드
imgFile: null,
imgFileList: [],
deleteImgFileList: [],
//스마트 에디터
oEditors: [],
bannerId: 'guide-banner',
//카테고리 목록
ctgryCdList: []
}
},
created() {
},
methods: {
// 목록으로 이동
fnCancel() {
if (!confirm(this.$getCmmnMessage('cnf008'))) {
return;
}
if (this.eduCn.edu_cnslt_id == null || this.eduCn.edu_cnslt_id == 0) {
this.$router.push({
path: this.path + '/list.page',
});
} else {
this.$router.push({
path: this.path + '/view.page',
query: {
pageId: this.eduCn.edu_cnslt_id
},
});
}
},
// 상세조회
async fnSelectOne() {
try {
const params = {
'edu_cnslt_id': this.pageId,
}
this.$setLoading(true);
const res = await findByEduId(params);
if (res.status == 200) {
this.eduCn = res.data.data.eduCn;
this.fileList = res.data.data.fileList;
this.imgFileList = res.data.data.imgFileList;
this.createEditor();
// this.oEditors.getById["smart"].exec("SET_IR", [res.data.data.eduCn.edu_cnslt_cn]);
}
} catch (error) {
// alert('에러가 발생했습니다.\n시스템관리자에게 문의하세요.');
alert(this.$getCmmnMessage('err005'));
} finally {
this.$setLoading(false);
}
},
// 이미지 파일 등록
fnImgFileInsert() {
// files 개수 만큼 반복해서 type, size 체크
this.imgFile = this.$refs.imgFile.files;
for (let i = 0; i < this.imgFile.length; i++) {
const file = this.imgFile[i];
const extnNm = file.name.split('.').pop();
// 파일이 이미지인지 체크
if (!file.type.startsWith('image/')) {
alert('이미지 파일만 업로드 가능합니다.');
return;
}
}
this.imgFileList = [...this.imgFileList, ...Array.from(this.imgFile)];
},
// 이미지파일 삭제
fnImgFileDelete(file, index) {
if (file["fileId"] != null) {
this.deleteImgFileList.push(file);
}
this.imgFileList.splice(index, 1);
},
// 첨부파일 등록
fnFileInsert() {
// files 개수 만큼 반복해서 type, size 체크
this.files = this.$refs.file.files;
for (let i = 0; i < this.files.length; i++) {
const file = this.files[i];
const extnNm = file.name.split('.').pop().toLowerCase();
if(extnNm === 'exe') {
alert('exe 파일은 첨부할 수 없습니다.')
return;
}
}
this.fileList = [...this.fileList, ...Array.from(this.files)];
},
// 첨부파일 삭제
fnFileDelete(file, index) {
if (file["fileId"] != null) {
this.deleteFileList.push(file);
}
this.fileList.splice(index, 1);
},
fnInsert() {
if (this.eduCn.edu_cnslt_id == null || this.eduCn.edu_cnslt_id == 0) {
this.fnSave();
} else {
this.fnUpdate();
}
},
// 등록
async fnSave() {
const vm = this;
if (!this.Validation()) {
return;
}
// 폼데이터 생성
var formData = new FormData();
formData.append("eduInfo", JSON.stringify(this.eduCn));
for (const file of this.fileList) {
formData.append("file", file);
}
for (const imgFile of this.imgFileList) {
formData.append("imgFile", imgFile);
}
// axios 호출
this.$setLoading(true);
await axios({
url: "/edu/save.file",
method: "post",
headers: {
"Content-Type": "multipart/form-data; charset=UTF-8",
Authorization: this.$store.state.authorization,
},
data: formData,
}).then((response) => {
const eduId = response.data.data;
alert('교육 ・ 컨설팅이 등록되었습니다.');
vm.$router.push({
path: vm.path + '/view.page',
query: { pageId: eduId },
});
}).catch((error) => {
console.log("axiosInsert error: ", error);
alert("교육 ・ 컨설팅 등록에 실패하였습니다.\n관리자에게 문의해주세요.");
}).finally(function () {
vm.$setLoading(false);
});
},
// 수정
async fnUpdate() {
const vm = this;
if (!this.Validation()) {
return;
}
// 폼데이터 생성
var formData = new FormData();
formData.append("eduInfo", JSON.stringify(this.eduCn));
for (const file of this.fileList) {
formData.append("file", file);
}
for (const imgFile of this.imgFileList) {
formData.append("imgFile", imgFile);
}
formData.append("deleteFile",JSON.stringify(this.deleteFileList));
formData.append("deleteImageFile",JSON.stringify(this.deleteImgFileList));
// axios 호출
this.$setLoading(true);
axios({
url: "/edu/update.file",
method: "post",
headers: {
"Content-Type": "multipart/form-data; charset=UTF-8",
Authorization: this.$store.state.authorization,
},
data: formData,
}).then((response) => {
const eduId = response.data.data;
alert(this.$getCmmnMessage('msg005'));
this.$router.push({
path: this.path + '/view.page',
query: {
pageId: eduId
},
});
}).catch((error) => {
console.log("axiosInsert error: ", error);
// alert("에러가 발생했습니다.\n관리자에게 문의해주세요.");
alert(vm.$getCmmnMessage('err005'));
}).finally(function(){
vm.$setLoading(false);
});
},
// 유효성 검사
Validation() {
//카테고리 검사
if(this.isEmpty(this.eduCn.edu_cnslt_ctgry_cd)){
alert('카테고리를 선택해주세요.');
return false;
}
if(this.isEmpty(this.eduCn.edu_cnslt_ttl)){
alert('교육 ・ 컨설팅명을 입력해주세요.');
return false;
}
const oEditors = this.oEditors;
oEditors.getById["smart"].exec("UPDATE_CONTENTS_FIELD", []);
// 스마트에디터의 iframe에 있는 내용을 textarea로.
this.eduCn.edu_cnslt_cn = document.getElementById("smart").value;
// 내용 null검사
if (!this.tagChecked() && (this.isEmpty(this.eduCn.edu_cnslt_cn) || this.removeHtmlAndSpace(this.eduCn.edu_cnslt_cn) === '')) {
alert("교육 ・ 컨설팅 내용을 입력하세요.");
document.getElementById("smart").focus();
return false;
}
// 이미지 파일 null 검사
if (this.imgFileList.length < 1) {
alert('이미지 파일을 첨부해주세요.');
return false;
}
//교육대상자
if(this.isEmpty(this.eduCn.ent_mngr_yn)){
alert('교육 ・ 컨설팅대상자를 선택해주세요.')
return false
}
//참석 인원 기준
if(this.eduCn.ent_mngr_yn === 'Y'){
if(this.isEmpty(this.eduCn.rmrk_cn)){
alert('참석 인원 기준을 입력해주세요.')
return false;
}
}
//첨부파일 필수 여부
if(this.isEmpty(this.eduCn.atch_file_esntl_yn)){
alert('첨부파일 필수 여부를 선택해주세요.')
return false
}
//공개여부
if(this.isEmpty(this.eduCn.rls_yn)){
alert('공개여부를 선택해주세요.')
return false
}
//문의처
if(this.isEmpty(this.eduCn.edu_cnslt_cttpc_cn)){
alert('교육문의처를 입력해주세요.')
return false
}
//장소
if(this.isEmpty(this.eduCn.edu_cnslt_plc_nm)){
alert('교육장소를 입력해주세요.')
return false
}
return true;
},
// 태그 체크
tagChecked() {
const tag = this.eduCn.edu_cnslt_cn;
if (tag.indexOf("<iframe") != -1) {
return true;
} else {
return false;
}
},
/**
* 빈 객체 여부
*/
isEmpty: function (data) {
if (
data === undefined ||
data === null ||
data === "" ||
data.length === 0 ||
(data.constructor == Object && Object.keys(data).length === 0)
) {
return true;
} else {
return false;
}
},
removeHtmlAndSpace: function (str) {
return str.replace(/<[^>]*>/g, '') // HTML 태그 제거
.replace(/ /gi, ' ') // 를 공백으로 변환
.replace(/\s/g, ''); // 모든 공백 제거
},
//신청기간 유효성 체크
checkDateValidity(changeDate, event) {
const val = event.target.value; // 변경된 날짜 값
// 시작일 변경 시
if (changeDate === 'edu_aply_bgng_ymd') {
if (this.eduCn.edu_aply_end_ymd !== null && this.eduCn.edu_aply_end_ymd < val) {
alert('시작일은 종료일보다 클 수 없습니다.');
this.eduCn.edu_aply_bgng_ymd = null; // 유효하지 않은 경우, 시작일을 초기화
} else {
this.eduCn.edu_aply_bgng_ymd = val;
}
}
// 종료일 변경 시
else if (changeDate === 'edu_aply_end_ymd') {
if (this.eduCn.edu_aply_bgng_ymd !== null && this.eduCn.edu_aply_bgng_ymd > val) {
alert('종료일은 시작일보다 작을 수 없습니다.');
this.eduCn.edu_aply_end_ymd = null // 유효하지 않은 경우, 종료일을 초기화
}
else {
this.eduCn.edu_aply_end_ymd = val;
}
}
},
// 에디터 생성
createEditor() {
// 스마트 에디터 적용
let vm = this;
const oEditors = this.oEditors;
nhn.husky.EZCreator.createInIFrame({
oAppRef: oEditors,
elPlaceHolder: "smart",
sSkinURI: "/client/smarteditor2-2.8.2.3/SmartEditor2Skin.html",
htParams: {
bUseToolbar: true, // 툴바 사용 여부 (true:사용/ false:사용하지 않음)
bSkipXssFilter: true,
bUseVerticalResizer: true,
bUseModeChanger: true
},
fOnAppLoad: function () {
if(vm.eduCn && vm.eduCn.edu_cnslt_cn){
oEditors.getById["smart"].exec("SET_IR", [vm.eduCn.edu_cnslt_cn]);
}
},
fCreator: "createSEditor2"
});
},
//카테고리 리스트 불러오기
async findAllCtgry() {
this.ctgryCdList = await this.$getCommonCode('techEduCtgryCd');
},
},
watch: {
},
computed: {
},
components: {
'PageNavigationBar':PageNavigationBar
},
mounted() {
// pageId 확인
this.findAllCtgry();
if (this.pageId != null) {
this.editMode = "update";
this.fnSelectOne();
} else {
this.eduCn.edu_cnslt_ctgry_cd = '';
this.createEditor()
}
}
}
</script>