
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="admin-wrap">
<div class="content-box">
<div class="title-wrap">
<div class="flex-start">
<img src="../../../../resources/jpg/tech-logo.png" alt="기술문서 아이콘" class="title-icon">
<h2 class="main-title">기술문서</h2>
</div>
</div>
<div class="content-wrap dataUpdate">
<table class="insert-table">
<tbody>
<tr>
<th>제목</th>
<td><input type="text" name="" id="techTitle" v-model="post.post_title"></td>
</tr>
<tr>
<th>카테고리</th>
<td>
<div class="flex-start">
<div>
<input type="radio" name="category" id="api" value="api" style="display:none"
checked v-model="post.ctgry_nm">
<label for="api" class="category">API</label>
</div>
<div>
<input type="radio" name="category" id="tech" value="tech" style="display:none"
v-model="post.ctgry_nm">
<label for="tech" class="category">기술리포트</label>
</div>
<div>
<input type="radio" name="category" id="issue" value="standard" style="display:none"
v-model="post.ctgry_nm">
<label for="issue" class="category">기술규격문서</label>
</div>
<div>
<input type="radio" name="category" id="service" value="service"
style="display:none" v-model="post.ctgry_nm">
<label for="service" class="category">서비스</label>
</div>
</div>
</td>
</tr>
<tr v-if="post.ctgry_nm == 'service'">
<th style="width:15%">기술문서 필수내용</th>
<td>
<div class="atech-grid">
<input type="date" name="" id="date" data-placeholder="배포날짜 (ex : 2023-11-17)" required
aria-required="true" v-model="post.tech_doc_dt">
<input type="text" name="" id="keyword" placeholder="키워드[키워드간의 구분은 쉼표로 할 수 있습니다]"
v-model="post.tech_doc_keyword">
<input type="Text" name="" id="link_url" placeholder="링크를 입력해주세요" v-model="post.link_url">
</div>
</td>
</tr>
<tr v-if="post.ctgry_nm != 'service'">
<th>기술문서 필수내용</th>
<td>
<div class="atech-grid">
<input type="text" name="" id="techName" placeholder="기술문서명" v-model="post.tech_doc_nm">
<input type="text" name="" id="version" placeholder="버전"
v-model="post.tech_doc_version">
<input type="date" name="" id="date" placeholder="배포날짜 (ex : 2023-11-17)"
v-model="post.tech_doc_dt">
<input type="text" name="" id="keyword" placeholder="키워드"
v-model="post.tech_doc_keyword">
<input style="grid-column: 1 / span 2;" type="Text" name="" id="techContent"
placeholder="주요내용(20자 내외)" v-model="post.tech_doc_main_content">
</div>
</td>
</tr>
<tr v-if="post.ctgry_nm != 'service'">
<th>내용</th>
<td><textarea name="smart" id="smart"></textarea></td>
</tr>
<tr class="file-zone" v-if="post.ctgry_nm != 'service'">
<th>등록된 썸네일파일</th>
<td>
<div class="join-sub-input join-imgbox"
@click="openFileInput('thumbnail', 'thumbnailInput')">
<p>375 X 251</p>
<img v-if="thumbnailPreview" :src="thumbnailPreview" />
<input type="file" name="file" id="file" ref="thumbnailInput" style="display: none"
@change="fileUpload('thumbnail')">
</div>
</td>
</tr>
<tr class="file-zone" v-if="post.ctgry_nm != 'service'">
<th>등록된 첨부파일</th>
<td colspan="6">
<div v-if="attachFileList.length == 0">
<label>첨부된 파일이 없습니다.</label>
</div>
<ul v-else v-for="(item, idx) in attachFileList" :key="idx">
<li class="file-item">
{{ item.real_file_nm }}
<button class="aclose-btn" @click="fileRemove(item, idx)">X</button>
</li>
</ul>
</td>
</tr>
<tr class="file-zone" v-if="post.ctgry_nm != 'service'">
<th>추가 첨부파일</th>
<td colspan="6">
<div class="btn-upload" @click="openFileInput('attach', 'attachInput')">파일 업로드</div>
<input type="file" name="file" id="file" ref="attachInput" style="display: none"
@change="fileUpload('attach')">
<ul v-for="(item, idx) in insertFileList" :key="idx" class="file-list">
<li v-if="insertFileList.length != 0">{{ item.file.name }} <button class="aclose-btn"
@click="fileRemove(item, idx)">X</button></li>
</ul>
</td>
</tr>
</tbody>
</table>
<div class="btn-wrap">
<button class="dark-gray-btn" @click="postSelectListPage()">이전</button>
<button class="blue-btn" @click="openUpdateModal()">수정</button>
</div>
</div>
</div>
<div v-show="isUpdateModalOpen" class="modal-wrapper">
<div class="modal-container admin-alert">
<div class="modal-content-monthly alert-modal ">
<p>해당 기술 문서를 수정하시겠습니까?</p>
</div>
<div class="modal-end">
<button class="dark-gray-btn small-btn" @click="closeUpdateModal()">취소</button>
<button class="blue-btn small-btn" @click="postUpdateCheck">확인</button>
</div>
</div>
</div>
</div>
</template>
<script>
import axios from 'axios';
import COMMON_UTIL from '../../../../resources/js/commonUtil.js';
import { useRoute } from 'vue-router';
export default {
data() {
return {
post: {
post_id: null,
post_title: null,
post_content: null,
notice_yn: null,
notice_start_dt: null,
notice_end_dt: null,
reg_dt: null,
mdfcn_dt: null,
link_url: null,
view_cnt: null,
file_id: null,
bbs_id: '3',
rgtr_id: null,
mdfr_id: null,
ctgry_nm: null,
tech_doc_nm: null,
tech_doc_version: null,
tech_doc_main_content: null,
tech_doc_keyword: null,
tech_doc_dt: null,
},
fileList: [],
deleteFileList: [],
insertFileList: [],
filecount: 0,
insertCount: 0,
deleteCount: 0,
oEditors: [], // oEditors는 스마트에디터용
route: useRoute(),
oldThumbnailFileList: [],
newThumbnailFileList: [],
attachFileList: [],
thumbnailPreview: null,
fileInputRef: null,
file_ty: null,
isUpdateModalOpen:false
};
},
methods: {
openUpdateModal: function () {
this.isUpdateModalOpen = true;
},
closeUpdateModal: function () {
this.isUpdateModalOpen = false;
},
//게시글 및 첨부파일 등록
postSelectOne: function () {
const vm = this;
axios({
url: '/post/postSelectOne.json',
method: 'post',
hearder: {
'Content-Type': "application/json; charset=UTF-8",
},
data: { 'post_id': vm.route.query.post_id, 'file_id': vm.route.query.file_id }
}).then(function (response) {
vm.post = response.data.postSelectOne.post;
if (response.data.selectFileList.length != 0) {
vm.fileList = response.data.selectFileList;
vm.filecount = response.data.selectFileList.length;
for (let i = 0; i < vm.fileList.length; i++) {
if (vm.fileList[i].file_ty === 'thumbnail') {
vm.oldThumbnailFileList.push(vm.fileList[i])
vm.thumbnailPreview = 'http://localhost:8080' + vm.fileList[i].file_path.replace('C:', '') +
'/' + vm.fileList[i].file_nm + '.' + vm.fileList[i].file_extn_nm;
} else {
vm.attachFileList.push(vm.fileList[i]);
}
}
}
vm.initEditor(vm.post.post_content);
}).catch(function (error) {
console.log("error - ", error)
alert("게시글 상세보기 조회 오류, 관리자에게 문의하세요.");
})
},
//게시글 및 첨부파일 등록
postUpdate: function () {
const vm = this;
let formData = new FormData();
if (vm.newThumbnailFileList.length > 0) {
vm.newThumbnailFileList.forEach(fileItem => {
vm.insertFileList.push(fileItem);
});
}
if (vm.insertFileList.length > 0 || vm.deleteFileList.length > 0) {
for (let i = 0; i < vm.insertFileList.length; i++) {
formData.append('file', vm.insertFileList[i].file);
formData.append('file_ty', vm.insertFileList[i].file_ty);
console.log('file - ', formData.get('file'));
}
if (vm.deleteFileList.length > 0) {
formData.append('deleteFile', JSON.stringify(vm.deleteFileList));
console.log('deleteFile - ', formData.get('deleteFile'));
}
formData.append("post", JSON.stringify(vm.post));
axios({
url: '/post/newsFileUpdate.file',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data',
},
data: formData
}).then(function (response) {
console.log("qnaInsert - response : ", response);
let result = response.data;
console.log("result===" + result)
if (result > 0) {
alert("수정을 완료하였습니다.");
vm.postSelectListPage()
} else {
alert("수정 실패, 관리자에게 문의해주세요.");
}
}).catch(function (error) {
console.log("qnaInsert - error : ", error);
alert("수정 오류, 관리자에게 문의해주세요.");
});
} else {
axios({
url: '/post/postFileUpdate.json',
method: 'post',
headers: {
'Content-Type': "application/json; charset=UTF-8",
},
data: vm.post
}).then(function (response) {
console.log("newsInsert - response : ", response);
let result = response.data;
if (result > 0) {
alert("수정을 완료하였습니다.");
vm.postSelectListPage()
} else {
alert("수정 실패, 관리자에게 문의해주세요.");
}
}).catch(function (error) {
console.log("newsInsert - error : ", error);
alert("수정 오류, 관리자에게 문의해주세요.");
});
}
},
//등록 유효성 검사
postUpdateCheck: function () {
if(this.post.ctgry_nm !== 'service'){
const oEditors = this.oEditors;
oEditors.getById["smart"].exec("UPDATE_CONTENTS_FIELD", []);
// 스마트에디터의 iframe에 있는 내용을 textarea로.
this.post.post_content = document.getElementById("smart").value;
if (COMMON_UTIL.isEmpty(this.post.post_title) === false) {
alert("제목을 입력해주세요.");
document.getElementById("techTitle").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.ctgry_nm) === false) {
alert("카테고리를 선택해주세요.");
document.getElementById("api").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.tech_doc_nm) === false) {
alert("기술문서명을 입력해주세요");
document.getElementById("techName").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.tech_doc_version) === false) {
alert("버전을 입력해주세요");
document.getElementById("version").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.tech_doc_dt) === false) {
alert("배포날짜를 입력해주세요");
document.getElementById("date").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.tech_doc_keyword) === false) {
alert("키워드를 입력해주세요");
document.getElementById("keyword").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.tech_doc_main_content) === false) {
alert("주요내용을 입력해주세요");
document.getElementById("techContent").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.post_content) === false || this.post.post_content === "<p><br></p>") {
alert("내용을 입력해주세요.");
document.getElementById("smart").focus();
return false;
}
} else {
if (COMMON_UTIL.isEmpty(this.post.post_title) === false) {
alert("제목을 입력해주세요.");
document.getElementById("techTitle").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.ctgry_nm) === false) {
alert("카테고리를 선택해주세요.");
document.getElementById("api").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.tech_doc_dt) === false) {
alert("배포날짜를 입력해주세요");
document.getElementById("date").focus();
return false;
}
if (COMMON_UTIL.isEmpty(this.post.link_url) === false) {
alert("링크를 입력해주세요");
document.getElementById("link_url").focus();
return false;
}
if (!this.post.link_url.startsWith('http://') && !this.post.link_url.startsWith('https://')) {
alert("링크는 http:// 또는 https://로 시작해야합니다.");
document.getElementById("link_url").focus();
return false;
}
}
this.postUpdate();
},
// 에디터 만들기
initEditor: function (initData) {
// 스마트 에디터 적용
const oEditors = this.oEditors;
nhn.husky.EZCreator.createInIFrame({
oAppRef: oEditors,
elPlaceHolder: "smart",
sSkinURI: "/client/smarteditor2-2.8.2.3/SmartEditor2Skin.html",
htParams: {
bSkipXssFilter: true,
bUseVerticalResizer: true,
bUseModeChanger: true
},
fOnAppLoad: function () {
oEditors.getById["smart"].exec("PASTE_HTML", [initData]);
},
fCreator: "createSEditor2"
});
},
//파일업로드
fileUpload: function () {
this.insertFileList[this.insertCount] = this.$refs.fileInput.files[0];
this.insertCount += 1;
console.log("insertFile - ", this.insertFileList);
},
//파일업로드 중 업로드 파일 삭제
fileRemove(item, idx) {
if (item.file_path === undefined) {
this.insertFileList.splice(idx, 1);
this.insertCount = this.insertFileList.length;
console.log("insertfile", this.insertFileList);
} else {
this.attachFileList.splice(idx, 1);
this.deleteFileList.push(item);
this.deleteCount += 1
this.filecount = this.fileList.length;
console.log("deleteFile - ", this.deleteFileList);
}
},
// 파일 업로드 커스텀을 위한 함수
openFileInput: function (file_ty, inputRef) {
this.file_ty = file_ty;
this.fileInputRef = inputRef;
this.$refs[inputRef].click();
},
// 파입 업로드
fileUpload: function (file_ty) {
const vm = this;
const MIN_WIDTH = 375;
const MIN_HEIGHT = 251;
const file = this.$refs[this.fileInputRef].files[0];
const fileItem = { file, file_ty: file_ty };
if (file_ty === 'thumbnail') {
const thumbnailIndex = this.fileList.findIndex(file => file.file_ty === 'thumbnail');
if (thumbnailIndex !== -1) {
this.fileList.splice(thumbnailIndex, 1);
}
let reader = new FileReader();
reader.onload = (e) => {
const originalThumbnail = this.thumbnailPreview;
this.thumbnailPreview = e.target.result;
// 이미지크기 확인
const img = new Image();
img.src = this.thumbnailPreview;
img.onload = () => {
if (img.width < MIN_WIDTH || img.height < MIN_HEIGHT) {
alert("썸네일 이미지 크기는 최소 " + MIN_WIDTH + "픽셀" + "x" + MIN_HEIGHT + "픽셀" + "입니다.");
this.thumbnailPreview = originalThumbnail;
this.$refs.thumbnailInput.value = ''
} else {
this.deleteFileList.push(...this.oldThumbnailFileList.filter(file => file.file_ty === 'thumbnail'));
this.deleteCount += 1;
//썸네일에 새 이미지가 업로드 되면, 초기화 하고 새 이미지파일만 넣어준다.
this.newThumbnailFileList = [];
this.newThumbnailFileList.push(fileItem);
}
};
};
reader.readAsDataURL(file);
} else {
vm.insertFileList.push(fileItem)
}
},
//게시글 리스트로 이동
postSelectListPage: function () {
this.$router.push({ path: '/adm/techSelectList.page' });
},
},
watch: {},
computed: {},
components: {},
mounted() {
this.postSelectOne();
// 스마트 에디터 적용
}
};
</script>