728x90
반응형
/* 자바 첨부파일 다운로드 & 업로드 */
FileManagerController.java
package logfarm.admin.file.controller;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import egovframework.com.cmm.service.EgovProperties;
import logfarm.admin.file.util.FileItem;
import logfarm.admin.file.util.FileUploadUtil;
import net.sf.json.JSONObject;
@Controller
@RequestMapping("/api")
public class FileManagerController {
private static final Logger logger = LoggerFactory.getLogger(FileManagerController.class);
private static final String SP = File.separator;
@RequestMapping("/fileUpload.json")
@ResponseBody
public Object uploadFile( @RequestParam("file") MultipartFile multipartFile
) {
try {
FileItem resultFileItem = (FileItem) FileUploadUtil.saveFileInDir(multipartFile);
logger.debug("resultFileItem : " + resultFileItem);
JSONObject jObj = new JSONObject();
jObj.put("success", true);
jObj.put("message", "파일업로드 성공");
jObj.put("payload", resultFileItem);
System.out.println("jObj : " + jObj);
return jObj;
} catch (IOException ioe) {
JSONObject jObj = new JSONObject();
jObj.put("success", false);
jObj.put("message", "파일업로드 실패");
return jObj;
}
}
/**
*
* <pre>
* @desc axios 파일 다운로드
* @param
* @return
* @return
* @throws
* </pre>
*/
@RequestMapping(value = "/downloadAxiosFiles.json" )
public void downloadAxiosFiles(HttpServletRequest request, HttpServletResponse response) {
logger.debug("-------------- 파일다운로드 -------------");
//String getPath = FileUploadUtil.removedFileTraversal(request.getParameter("filepath"));
String getName = FileUploadUtil.removedFileTraversal(request.getParameter("filename"));
String getOrginFileName = FileUploadUtil.removedFileTraversal(request.getParameter("originFileName"));
//외부 입력값에 CRLF를 제거한다.
getName = getName.replaceAll("\n","");
getName = getName.replaceAll("\r","");
logger.debug("getOrginFileName : " + getOrginFileName);
logger.debug("getName : " + getName);
//logger.debug("getPath : " + getPath);
//String filePath = EgovProperties.getProperty("Globals.fileStorePath").trim() + getPath +SP+ getOrginFileName;
String filePath = EgovProperties.getProperty("Globals.fileStorePath").trim() + getOrginFileName;
logger.debug("filePath : " + filePath);
Map<String, Object> reMap = new HashMap<>();
OutputStream os = null;
InputStream is = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
ServletOutputStream sout = null;
File f = new File(filePath);
try {
response.reset();
response.setCharacterEncoding("utf-8");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition","attachment;filename=" + new String(getName.getBytes("UTF-8"), "ISO8859-1"));
is = new FileInputStream(f);
if (is == null) {
reMap.put("msg", "파일이 존재 하지 않습니다.");
}
sout = response.getOutputStream();
bis = new BufferedInputStream(is);
bos = new BufferedOutputStream(sout);
byte[] buff = new byte[2048];
int bytesRead;
while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
bos.write(buff, 0, bytesRead);
}
bos.flush();
bos.close();
bis.close();
is.close();
sout.close();
// os.close();
} catch (IOException e) {
reMap.put("msg", "처리중 오류가 발생하였습니다.");
} catch (Exception e) {
reMap.put("msg", "처리중 오류가 발생하였습니다.");
} finally
{
if (bis != null)
{
try
{
bis.close();
} catch (RuntimeException e) {
f = null;
}
catch (Exception e)
{
f = null;
}
}
if (bos != null)
{
try
{
bos.close();
} catch (RuntimeException e) {
f = null;
}
catch (Exception e)
{
f = null;
}
}
if (is != null)
{
try
{
is.close();
} catch (RuntimeException e) {
f = null;
}
catch (Exception e)
{
f = null;
}
}
if (sout != null)
{
try
{
sout.close();
} catch (RuntimeException e) {
f = null;
}
catch (Exception e)
{
f = null;
}
}
if (os != null)
{
try
{
os.close();
} catch (RuntimeException e) {
f = null;
}
catch (Exception e)
{
f = null;
}
}
}
}
}
FileItem.java
package logfarm.admin.file.util;
public class FileItem {
public FileItem() {}
public FileItem(String fileName, String finalFileName, long size, String mimeType, String extention, String path) {
this.fileName = fileName;
this.finalFileName = finalFileName;
this.size=size;
this.mimeType = mimeType;
this.extention = extention;
this.path = path;
this.status = true;
}
private String fileName;
private long size;
private String mimeType;
private String finalFileName;
private String extention;
private String path;
private Boolean status;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public long getSize() {
return size;
}
public void setSize(long size) {
this.size = size;
}
public String getMimeType() {
return mimeType;
}
public void setMimeType(String mimeType) {
this.mimeType = mimeType;
}
public String getFinalFileName() {
return finalFileName;
}
public void setFinalFileName(String finalFileName) {
this.finalFileName = finalFileName;
}
public String getExtention() {
return extention;
}
public void setExtention(String extention) {
this.extention = extention;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
@Override
public String toString() {
return "FileItem [fileName=" + fileName + ", size=" + size + ", mimeType=" + mimeType + ", finalFileName="
+ finalFileName + ", extention=" + extention + ", path=" + path + ", status=" + status + "]";
}
}
FilesUiResponse.java
package logfarm.admin.file.util;
public class FilesUiResponse {
Boolean success;
String message;
Object payload;
public FilesUiResponse() { }
public FilesUiResponse(Boolean success,String message, Object payload) {
this.success = success;
this.message = message;
this.payload=payload;
}
}
FileUploadUtil.java
package logfarm.admin.file.util;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;
import org.springframework.web.multipart.MultipartFile;
import egovframework.com.cmm.service.EgovProperties;
public class FileUploadUtil {
public static String UPLOAD_PATH = EgovProperties.getProperty("Globals.fileStorePath").trim();
public static FileItem saveFileInDir(MultipartFile multipartFile) throws IOException {
Path uploadDirectory = Paths.get(UPLOAD_PATH);
String fileId = createUUID();
String fileName = multipartFile.getOriginalFilename();
/* 파일확장자 가져오기 */
int pos = fileName.lastIndexOf(".");
String extention = fileName.substring(pos+1);
String finalFileName = createUUIDfileName(extention);
String mimeType = multipartFile.getContentType();
//디렉토리 존재여부
File destination = new File(UPLOAD_PATH);
if( destination.exists() == false) {
boolean mkdirs = destination.mkdirs();
}
long size = multipartFile.getSize();
System.out.println("fileName: " + fileName);
System.out.println("newFIleName: " + finalFileName);
System.out.println("extention: " + extention);
System.out.println("size: " + size);
try (InputStream inputStream = multipartFile.getInputStream()) {
Path filePath = uploadDirectory.resolve(finalFileName);
Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
FileItem finalFileItem = new FileItem(
fileName,
finalFileName,
size,
mimeType,
extention,
UPLOAD_PATH
);
return finalFileItem;
} catch (IOException ioe) {
throw new IOException("Error on saving uploaded file: " + fileName, ioe);
}
}
public static String createUUID() {
UUID uuid = UUID.randomUUID();
String fileId = uuid.toString();
return fileId;
}
public static String createUUIDfileName(String extention) {
return createUUID() + "." + extention;
}
/**
* 파일특수문자 변환
* @return
*/
public static String removedFileTraversal(String fileName) {
if(fileName == null) {
return null;
}
fileName = fileName.replaceAll ("\\.\\./","");
fileName = fileName.replaceAll ("\\\\","");
fileName = fileName.replaceAll ("&","");
return fileName;
}
}
/* 리액트 화면에서 첨부파일 업로드 다운로드 호출 */
/* eslint-disable import/no-extraneous-dependencies */
import React, { useRef, useCallback, useEffect, useMemo } from 'react';
import { styled, createTheme, ThemeProvider } from '@mui/material/styles';
import Grid from '@mui/material/Unstable_Grid2';
import { Dropzone, FileMosaic, FullScreen, ImagePreview, VideoPreview } from '@files-ui/react';
import dayjs from 'dayjs';
import { DemoContainer } from '@mui/x-date-pickers/internals/demo';
import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider';
import { DateField } from '@mui/x-date-pickers/DateField';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { MobileDatePicker } from '@mui/x-date-pickers/MobileDatePicker';
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TablePagination from '@mui/material/TablePagination';
import TableRow from '@mui/material/TableRow';
import Button from '@mui/material/Button';
import InputBase from '@mui/material/InputBase';
import Divider from '@mui/material/Divider';
import IconButton from '@mui/material/IconButton';
import RefreshIcon from '@mui/icons-material/Refresh';
import MenuIcon from '@mui/icons-material/Menu';
import SearchIcon from '@mui/icons-material/Search';
import DirectionsIcon from '@mui/icons-material/Directions';
import TextField from '@mui/material/TextField';
import { outlinedInputClasses } from '@mui/material/OutlinedInput';
import CloseIcon from '@mui/icons-material/Close';
import Slide from '@mui/material/Slide';
import Dialog from '@mui/material/Dialog';
import ListItemText from '@mui/material/ListItemText';
import ListItem from '@mui/material/ListItem';
import List from '@mui/material/List';
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import { FileUploader } from 'react-drag-drop-files';
import Box from '@mui/material/Box';
import FormControl from '@mui/material/FormControl';
import Input from '@mui/material/Input';
import InputLabel from '@mui/material/InputLabel';
import InputAdornment from '@mui/material/InputAdornment';
import FormHelperText from '@mui/material/FormHelperText';
import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import FormLabel from '@mui/material/FormLabel';
import Select from '@mui/material/Select';
import MenuItem from '@mui/material/MenuItem';
import SaveIcon from '@mui/icons-material/Save';
import { Editor, Viewer } from '@toast-ui/react-editor';
import '@toast-ui/editor/dist/toastui-editor.css';
import colorSyntax from '@toast-ui/editor-plugin-color-syntax';
import 'tui-color-picker/dist/tui-color-picker.css';
import '@toast-ui/editor-plugin-color-syntax/dist/toastui-editor-plugin-color-syntax.css';
import '@toast-ui/editor/dist/i18n/ko-kr';
// editor viewer
import '@toast-ui/editor/dist/toastui-editor-viewer.css';
import Alert from '@mui/material/Alert';
import Stack from '@mui/material/Stack';
// eslint-disable-next-line import/no-extraneous-dependencies
import { confirmAlert } from 'react-confirm-alert'; // Import
// eslint-disable-next-line import/no-extraneous-dependencies
import '../css/react-confirm-alert.css'; // Import css
// eslint-disable-next-line import/no-cycle
import { Header } from '../components';
import { useStateContext } from '../contexts/ContextProvider';
// eslint-disable-next-line import/no-named-as-default
import axi from '../comjs/axi';
/* 색상 테마 정의 */
const themes = createTheme({
status: {
danger: '#e53e3e',
},
palette: {
primary: {
main: '#0971f1',
darker: '#053e85',
},
neutral: {
// main: '#64748B',
main: '#0288d1',
contrastText: '#fff',
},
},
});
const Item = styled(Paper)(({ theme }) => ({
backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
...theme.typography.body2,
padding: theme.spacing(1),
textAlign: 'center',
color: theme.palette.text.secondary,
}));
const fileTypes = ['JPG', 'PNG', 'GIF', 'ZIP', 'XLSX'];
const { body } = document;
const html = document.documentElement;
const height = Math.max(
body.scrollHeight,
body.offsetHeight,
html.clientHeight,
html.scrollHeight,
html.offsetHeight,
);
const Transition = React.forwardRef((props, ref) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<Slide direction="up" ref={ref} {...props} />
));
const columns = [
{ id: 'bbscttNo', label: '게시글번호', minWidth: 100, width: 100, align: 'center' },
{ id: 'bbscttSj', label: '제목', minWidth: 100, width: 200 },
{ id: 'bbscttCn', label: '내용', minWidth: 100, width: 250 },
{ id: 'nttInqireCo', label: '조회수', minWidth: 100, width: 100, align: 'right' },
{ id: 'cnt', label: '첨부파일', minWidth: 100, width: 100, align: 'right' },
{ id: 'registDt', label: '등록일자', minWidth: 100, width: 120, align: 'center' },
{ id: 'manage', label: '관리', minWidth: 100, width: 120, align: 'center' },
];
/* 첨부파일 리스트 */
const fileColumns = [
{ id: 'seqNo', label: '순번', minWidth: 100, width: 100, align: 'center' },
{ id: 'fileName', label: '파일명', minWidth: 150, width: 200, align: 'left' },
{ id: 'size', label: '사이즈', minWidth: 100, width: 150, align: 'right', format: (value) => `${value.toLocaleString('en-US')} Byte` },
{ id: 'manage', label: '관리', minWidth: 100, width: 200, align: 'center' },
];
// eslint-disable-next-line prefer-const
let sendSuccessFiles = []; // 전송성공한 첨부파일 리스트
/* html 태그 제거 */
const fnRemoveHtml = (text) => {
let tagRemove = text.replace(/<br\/>/gi, '\n');
tagRemove = tagRemove.replace(/<(\/)?([a-zA-Z]*)(\s[a-zA-Z]*=[^>]*)?(\s)*(\/)?>/gi, '');
return tagRemove;
};
const currentDate = new Date(); // 현재 날짜 및 시간
const nowDate = new Date(); // 현재 날짜 및 시간
const sixMonthDate = new Date(nowDate.setMonth(nowDate.getMonth() - 6)); // 6개월전
export default function BbsReg() {
const [open, setOpen] = React.useState(false);
const [mode, setMode] = React.useState('I');
const { currentColor, activeMenu, setActiveMenu, screenSize } = useStateContext();
/* editoe view */
const [contents, setContents] = React.useState(null);
const [files, setFiles] = React.useState([]);
const [extFiles, setExtFiles] = React.useState([]);
const [imageSrc, setImageSrc] = React.useState(undefined);
const [videoSrc, setVideoSrc] = React.useState(undefined);
const updateFiles = (incommingFiles) => {
// do something with the files
console.log('incommingFiles 전체삭제 업로드', incommingFiles.length);
setExtFiles(incommingFiles);
/* 전체삭제 */
if (incommingFiles.length === 0) {
sendSuccessFiles = [];
}
// console.log('extFiles', extFiles);
// even your own upload implementation
};
const onDelete = (id) => {
console.log('onDelete', id);
setExtFiles(extFiles.filter((x) => x.id !== id));
sendSuccessFiles = sendSuccessFiles.filter((x) => x.id !== id);
console.log('sendSuccessFiles', sendSuccessFiles);
};
const handleSee = (imageSource) => {
setImageSrc(imageSource);
};
const handleWatch = (videoSource) => {
setVideoSrc(videoSource);
};
const handleStart = (filesToUpload) => {
console.log('업로드시작', filesToUpload);
};
const handleFinish = (uploadedFiles) => {
console.log('업로드 성공', uploadedFiles);
const successResult = uploadedFiles.filter((sf) => sf.uploadStatus === 'success');
console.log('successResult:', successResult);
// eslint-disable-next-line no-plusplus
for (let i = 0; i < successResult.length; i++) {
console.log('성공한것만 배열 :', successResult[i]);
const returnObj = {};
returnObj.fileName = successResult[i].name;
returnObj.size = successResult[i].size;
returnObj.id = successResult[i].id;
returnObj.finalFileName = successResult[i].serverResponse.payload.finalFileName;
returnObj.extention = successResult[i].serverResponse.payload.extention;
returnObj.mimeType = successResult[i].serverResponse.payload.mimeType;
returnObj.path = successResult[i].serverResponse.payload.path;
sendSuccessFiles.push(returnObj);
}
console.log('업로드 성공 한것만 최종', sendSuccessFiles);
};
const handleAbort = (id) => {
setExtFiles(
extFiles.map((ef) => {
if (ef.id === id) {
return { ...ef, uploadStatus: 'aborted' };
}
return { ...ef };
}),
);
};
const handleCancel = (id) => {
setExtFiles(
extFiles.map((ef) => {
if (ef.id === id) {
return { ...ef, uploadStatus: undefined };
}
return { ...ef };
}),
);
};
/* 공지사항 팝업창 닫는다 */
const handleClose = () => {
setOpen(false);
};
/* 페이치 처리 초기값 설정 */
const [page, setPage] = React.useState(0);
const [rowsPerPage, setRowsPerPage] = React.useState(10);
/* 화면 높이 설정 */
const [heightSize, setHeightSize] = React.useState(height - 350);
/* 공지사항 데이타 객체 */
const [rows, setRows] = React.useState([]);
/* 첨부파일 데이타 객체 */
const [fileRows, setFileRows] = React.useState([]);
/* 공지사항 항목 초기화 */
const [tbBbscttM, setTbBbscttM] = React.useState({
no: '',
bbsId: '',
bbscttNo: '',
upperbbscttNo: '',
bbscttSj: '',
bbscttCn: '',
nttInqireCo: '',
lcasNm: '',
sortOrdr: '',
bbscttLevel: '',
atchFileNo: '',
registerId: '',
registDt: '',
updusrId: '',
ntceBeginDt: '',
ntceEndDt: '',
manage: '',
});
/* 검색 항목 설정 */
const [searchParam, setSearchParam] = React.useState({
bbsId: 1,
searchBbscttSj: '',
searchStartDt: dayjs(sixMonthDate),
searchEndDt: dayjs(currentDate),
});
/* 에디터 ref 설정 */
const editorRef = useRef();
// 게시글제목
const bbscttSjRef = useRef();
/* 페이지 이벤트 처리 */
const handleChangePage = (event, newPage) => {
setPage(newPage);
};
const handleChangeRowsPerPage = (event) => {
setRowsPerPage(+event.target.value);
setPage(0);
};
/* 첨부파일 삭제 */
const handleFileDelete = (param) => {
console.log('handleFileDelete', param.fileSeqNo);
setFileRows(fileRows.filter((x) => x.fileSeqNo !== param.fileSeqNo));
console.log('fileRows', fileRows);
};
/* 첨부파일 다운로드 */
const handleFileDownLoad = (param) => {
console.log('handleFileDownLoad', param);
axi({
method: 'POST',
url: 'downloadAxiosFiles.json',
responseType: 'blob',
params: {
filepath: param.path,
filename: param.fileName,
originFileName: param.finalFileName,
},
})
.then((response) => {
const { fileName } = param;
const { data } = response;
if (!data) {
return;
}
console.log(response);
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) => {
throw new Error(response);
});
};
/* 검색 */
const handleSearchOnChange = (e) => {
console.log('e', e);
setSearchParam({
...searchParam,
[e.target.name]: e.target.value,
});
};
const handleSearchOnDateChange = (target, value) => {
setSearchParam({
...searchParam,
[target]: value,
});
console.log('SearchParam', searchParam);
};
const handleOnChange = (e) => {
setTbBbscttM({
...tbBbscttM,
[e.target.name]: e.target.value,
});
};
const handleDataOnDateChange = (target, value) => {
setTbBbscttM({
...tbBbscttM,
[target]: value,
});
};
/* 검색초기화 */
const fnInit = () => {
setSearchParam({
...searchParam,
searchBbscttSj: '',
searchStartDt: dayjs(sixMonthDate),
searchEndDt: dayjs(currentDate),
});
};
/* 공지사항 목록 검색 */
const fnSearch = () => {
axi({
method: 'POST',
url: 'selectBbsList.json',
params: {
bbsId: 1,
searchBbscttSj: searchParam.searchBbscttSj,
searchStartDt: dayjs(searchParam.searchStartDt).format('YYYYMMDD'),
searchEndDt: dayjs(searchParam.searchEndDt).format('YYYYMMDD'),
},
})
.then((response) => {
console.log('성공', response);
if (response.data.ResultCode === 'SUCCESS') {
setRows(response.data.list);
}
})
.catch((e) => {
if (e.message) {
console.log('조회중 오류가 발생하였습니다.');
}
});
};
/* 공지사항 등록 초기화 */
const fnAdd = () => {
console.log('tbBbscttM', tbBbscttM);
setTbBbscttM({
...tbBbscttM,
no: '',
bbsId: '',
bbscttNo: '',
upperbbscttNo: '',
bbscttSj: '',
bbscttCn: ' ',
nttInqireCo: '',
lcasNm: '',
sortOrdr: '',
bbscttLevel: '',
atchFileNo: '',
registerId: '',
registDt: '',
updusrId: '',
ntceBeginDt: '',
ntceEndDt: '',
manage: '',
});
setMode('I');
setExtFiles([]);
setFiles([]);
setFileRows([]);
sendSuccessFiles = [];
setOpen(true);
};
/* 공지사항 수정 */
const handleEdit = (param) => {
console.log('클릭', param);
// 코드등록 값전달
setTbBbscttM({
...tbBbscttM,
bbsId: param.bbsId,
bbscttNo: param.bbscttNo,
upperbbscttNo: param.upperbbscttNo,
bbscttSj: param.bbscttSj,
bbscttCn: param.bbscttCn,
atchFileNo: param.atchFileNo,
ntceBeginDt: param.ntceBeginDt,
ntceEndDt: param.ntceEndDt,
manage: param.manage,
});
setMode('U');
setExtFiles([]);
sendSuccessFiles = [];
if (param.atchFileNo !== null && param.atchFileNo !== '' && param.atchFileNo > 0) {
/* 첨부파일이 있으면 첨부파일 목록 가져오기 */
axi({
method: 'POST',
url: 'selectAttachList.json',
params: { atchFileNo: param.atchFileNo },
})
.then((response) => {
console.log('성공', response);
if (response.data.ResultCode === 'SUCCESS') {
setFileRows(response.data.list);
}
})
.catch((e) => {
if (e.message) {
console.log('조회중 오류가 발생하였습니다.');
}
});
} else {
setFileRows([]);
setFiles([]);
}
setOpen(true);
};
/* 공지사항 삭제 */
const deleteSubmit = () => {
/* 데이터 삭제 */
confirmAlert({
title: '공지사항 삭제',
message: '삭제 하시겠습니까?',
buttons: [
{
label: '확인',
onClick: () => {
const delData = {
bbsId: tbBbscttM.bbsId,
bbscttNo: tbBbscttM.bbscttNo,
};
axi({
method: 'POST',
url: 'deleteBbsList.json',
params: delData,
})
.then((response) => {
console.log('성공', response);
setOpen(false);
fnSearch();
})
.catch((e) => {
if (e.message) {
console.log('삭제중 오류가 발생하였습니다.');
}
});
},
},
{
label: '취소',
onClick: () => {},
},
],
});
};
/* 공지사항저장 */
const saveSubmit = () => {
console.log('저장', tbBbscttM);
console.log('업로드 성공 한것만 saveSubmit', sendSuccessFiles);
const fileArray = [...fileRows, ...sendSuccessFiles];
console.log('기존 + 신규 FileRows', fileArray);
// 필수입력 체크
if (tbBbscttM.bbscttSj === '') {
confirmAlert({
title: '제목은 필수 입력입니다.',
message: '항목을 입력 해 주세요',
buttons: [
{
label: '확인',
onClick: () => {
bbscttSjRef.current.focus();
},
},
],
});
} else {
/* 데이터 저장 */
confirmAlert({
title: '공지사항 등록',
message: mode === 'I' ? '저장 하시겠습니까?' : '수정 하시겠습니까?',
buttons: [
{
label: '확인',
onClick: () => {
const savdData = {
tbBbscttM,
tbFileAttach: fileArray,
};
axi({
method: 'POST',
url: mode === 'I' ? 'insertBbsList.json' : 'updateBbsList.json',
data: savdData,
params: {},
})
.then((response) => {
console.log('성공', response);
setOpen(false);
fnSearch();
})
.catch((e) => {
if (e.message) {
console.log('저장중 오류가 발생하였습니다.');
}
});
},
},
{
label: '취소',
onClick: () => {},
},
],
});
}
};
/* 레이어 팝업 인풋박스 포커스 이동 */
useEffect(() => {
if (open) {
setTimeout(() => {
bbscttSjRef.current.focus();
}, 3);
}
}, [open]);
/*
const onChange = () => {
console.log(editorRef.current.getInstance().getHTML());
setContents(editorRef.current.getInstance().getHTML());
// console.log(editorRef.current.getInstance().getMarkdown());
};
*/
const myOwnValidation = (fileValid) => {
const errorList = [];
const validResult = true;
const regExPrefix = /\btest_file\w+/;
// if (!fileValid.name.match(regExPrefix)) {
// validResult = false;
// errorList.push('Prefix "test_file" was not present in the file name');
// }
console.log(validResult, errorList);
return { valid: validResult, errors: errorList };
};
/* 초기화 실행 */
useEffect(() => {
fnSearch();
return () => {
console.log('cleanup');
};
}, []);
return (
<div className="m-2 md:m-3 mt-24 p-2 md:p-7 dark:text-gray-200 bg-white dark:bg-[#484B52] rounded-3xl">
<Header category="기준정보" title="공지사항" />
<Paper
component="form"
sx={{
p: '2px 4px',
display: 'flex',
alignItems: 'center',
width: '100%',
}}
>
<TextField
sx={{ ml: 1, flex: 1, minWidth: 100 }}
name="searchBbscttSj"
value={searchParam.searchBbscttSj}
onChange={(event) => {
// eslint-disable-next-line no-unused-expressions
handleSearchOnChange(event);
}}
label="제목"
variant="standard"
/>
<Divider sx={{ height: 28, m: 0.5 }} orientation="vertical" />
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DemoContainer sx={{ ml: 1, flex: 1, minWidth: 130 }} components={['DatePicker', 'DatePicker']}>
<DatePicker
label="등록시작일자"
// defaultValue={dayjs(sixMonthDate)}
// value={dayjs(searchParam.searchStartDt)}
value={searchParam.searchStartDt}
onChange={(newValue) => {
// eslint-disable-next-line no-unused-expressions
// handleSearchOnDateChange('searchStartDt', dayjs(newValue).format('YYYYMMDD'));
handleSearchOnDateChange('searchStartDt', newValue);
}}
format="YYYY-MM-DD"
variant="standard"
/>
<DatePicker
label="등록종료일자"
// defaultValue={dayjs(currentDate)}
value={searchParam.searchEndDt}
onChange={(newValue) => {
// eslint-disable-next-line no-unused-expressions
handleSearchOnDateChange('searchEndDt', newValue);
}}
format="YYYY-MM-DD"
variant="standard"
/>
</DemoContainer>
</LocalizationProvider>
<Divider sx={{ height: 28, m: 0.5 }} orientation="vertical" />
<IconButton onClick={fnSearch} type="button" sx={{ p: '10px' }} aria-label="search">
<SearchIcon />
검색
</IconButton>
<Divider sx={{ height: 28, m: 0.5 }} orientation="vertical" />
<IconButton onClick={fnInit} type="button" sx={{ p: '10px' }} aria-label="search">
<RefreshIcon />
초기화
</IconButton>
</Paper>
<div className="mt-3 ">
<Button onClick={fnAdd} variant="outlined" className="dark:text-white">
신규등록
</Button>
</div>
<Paper className="mt-1 " sx={{ width: '100%' }}>
<TableContainer sx={{ maxHeight: heightSize }}>
<Table stickyHeader sx={{ minWidth: 650, width: '100%', tableLayout: 'auto' }} aria-label="sticky table">
<TableHead>
<TableRow>
{columns.map((column) => (
<TableCell
sx={{
backgroundColor: currentColor,
color: 'white',
}}
key={column.id}
align={column.align}
width={column.width}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{rows.length > 0 ? (
rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage).map((row) => (
// eslint-disable-next-line react/jsx-indent
<TableRow hover role="checkbox" tabIndex={-1} key={`${row.rowNo + 9999}`}>
{columns.map((column) => {
const value = row[column.id];
return (
<TableCell key={`${column.rowNo + column.id}`} align={column.align}>
{/* eslint-disable-next-line no-nested-ternary */}
{column.id === 'bbscttCn' ? (
// html 태그를 넣을때
// <div dangerouslySetInnerHTML={{ __html: value }} />
fnRemoveHtml(value).substr(0, 30)
) : value === 'edit' ? (
<Button onClick={() => handleEdit(row)} variant="outlined" sx={{ ml: 1 }}>
상세보기
</Button>
) : (
value
)}
{/* column.format && typeof value === 'number' ? column.format(value) : value */}
</TableCell>
);
})}
</TableRow>
// eslint-disable-next-line indent
))
) : (
<TableRow hover>
<TableCell align="center" colSpan={8}>
데이터가 존재 하지 않습니다.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
<TablePagination rowsPerPageOptions={[10, 25, 100]} component="div" count={rows.length} rowsPerPage={rowsPerPage} page={page} onPageChange={handleChangePage} onRowsPerPageChange={handleChangeRowsPerPage} />
</Paper>
<Dialog open={open} TransitionComponent={Transition} fullScreen style={{ zIndex: '1000' }}>
<ThemeProvider theme={themes}>
<AppBar sx={{ position: 'relative', backgroundColor: currentColor }}>
<Toolbar>
<Typography sx={{ ml: 2, flex: 1 }} variant="h6" component="div">
공지사항등록
</Typography>
<IconButton edge="start" color="inherit" onClick={handleClose} aria-label="close">
<CloseIcon />
</IconButton>
</Toolbar>
</AppBar>
</ThemeProvider>
<Box
component="form"
sx={{
'& .MuiTextField-root': { m: 1, width: '100%' },
}}
noValidate
autoComplete="off"
>
<div className="m-2 md:m-3 mt-24 p-2 md:p-7 dark:text-gray-200 bg-white dark:bg-[#484B52] rounded-3xl">
<Grid container justifyContent="flex-start" rowSpacing={1} columnSpacing={{ xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }}>
<Grid xs={12} md={5} lg={6} xl={8}>
<TextField
inputRef={bbscttSjRef}
id="bbscttSj"
name="bbscttSj"
required
sx={{ m: 1, flex: 1, minWidth: '100%', maxWidth: '100%' }}
label="제목"
helperText="*제목필수입력"
focused
autoFocus
inputProps={{ maxLength: 30 }}
value={tbBbscttM.bbscttSj}
onChange={(event) => {
// eslint-disable-next-line no-unused-expressions
handleOnChange(event);
}}
error={tbBbscttM.bbscttSj.length < 1}
/>
</Grid>
<Grid xs={12} md={7} lg={6} xl={4}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
sx={{ minWidth: 200, maxWidth: 200 }}
label="게시시작일"
value={dayjs(tbBbscttM.ntceBeginDt)}
onChange={(newValue) => {
// eslint-disable-next-line no-unused-expressions
handleDataOnDateChange('ntceBeginDt', dayjs(newValue).format('YYYY-MM-DD'));
// handleDataOnDateChange('ntceBeginDt', newValue);
}}
inputFormat="YYYY-MM-DD"
format="YYYY-MM-DD"
variant="standard"
/>
<DatePicker
sx={{ minWidth: 200, maxWidth: 200 }}
label="게시종료일"
value={dayjs(tbBbscttM.ntceEndDt)}
onChange={(newValue) => {
// eslint-disable-next-line no-unused-expressions
handleDataOnDateChange('ntceEndDt', dayjs(newValue).format('YYYY-MM-DD'));
// handleDataOnDateChange('ntceEndDt', newValue);
}}
inputFormat="YYYY-MM-DD"
format="YYYY-MM-DD"
variant="standard"
/>
</LocalizationProvider>
</Grid>
<Grid xs={12}>
<div className="ml-2 ">
<Editor
ref={editorRef}
initialValue={tbBbscttM.bbscttCn}
value={tbBbscttM.bbscttCn}
previewStyle="vertical"
height="600px"
initialEditType="wysiwyg"
useCommandShortcut={false}
plugins={[colorSyntax]}
language="ko-KR"
hideModeSwitch={false}
onChange={(newValue) => {
// eslint-disable-next-line no-unused-expressions
handleDataOnDateChange('bbscttCn', editorRef.current.getInstance().getHTML());
// handleDataOnDateChange('ntceEndDt', newValue);
}}
/>
</div>
</Grid>
{/*
<Grid xs={12}>
<div className="ml-2 ">
<FileUploader handleChange={handleFileChange} name="files" multiple types={fileTypes} label="파일을 선택해 주세요" maxSize={100} />
</div>
</Grid>
*/}
<Grid xs={12}>
<div className="ml-2 ">
<Dropzone
// minHeight="150px"
label="드래그 & 드롭 파일 또는 클릭 브라우저"
background="radial-gradient(circle at 18.7% 37.8%, rgb(250, 250, 250) 0%, rgb(225, 234, 238) 90%);"
onChange={updateFiles}
value={extFiles}
// accept="image/*, video/*"
// maxFileSize={50 * 1024 * 1024}
// maxFiles={5}
// footerConfig={{ customMessage: '허용가능 파일 타입:*.hwp' }}
autoClean
cleanFiles
validator={myOwnValidation}
uploadConfig={{
url: '/api/fileUpload.json',
method: 'POST',
cleanOnUpload: true,
autoUpload: true,
}}
onUploadStart={handleStart}
onUploadFinish={handleFinish}
// fakeUpload
actionButtons={{
position: 'after',
uploadButton: {},
// abortButton: {},
// cleanButton: {},
// deleteButton: {},
}}
>
{extFiles.map((filess) => (
// eslint-disable-next-line react/jsx-props-no-spreading
<FileMosaic {...filess} key={filess.id} onDelete={onDelete} onSee={handleSee} onWatch={handleWatch} onAbort={handleAbort} onCancel={handleCancel} resultOnTooltip alwaysActive preview info />
))}
</Dropzone>
<FullScreen open={imageSrc !== undefined} onClose={() => setImageSrc(undefined)}>
<ImagePreview src={imageSrc} />
</FullScreen>
<FullScreen open={videoSrc !== undefined} onClose={() => setVideoSrc(undefined)}>
<VideoPreview src={videoSrc} autoPlay controls />
</FullScreen>
</div>
</Grid>
{fileRows.length > 0 && (
<Grid xs={12}>
<div className="ml-2 ">
<Paper className="mt-1 " sx={{ width: '100%' }}>
<TableContainer sx={{ maxHeight: heightSize }}>
<Table stickyHeader sx={{ minWidth: 650, width: '100%', tableLayout: 'auto' }} aria-label="sticky table">
<TableHead>
<TableRow>
{fileColumns.map((column) => (
<TableCell
sx={{
backgroundColor: currentColor,
color: 'white',
}}
key={column.id}
align={column.align}
width={column.width}
>
{column.label}
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{fileRows.length > 0 ? (
fileRows.map((row) => (
// eslint-disable-next-line react/jsx-indent
<TableRow hover tabIndex={-1} key={`${row.seqNo + 9999}`}>
{fileColumns.map((column) => {
const value = row[column.id];
return (
<TableCell key={`${column.id + value}`} align={column.align}>
{/* eslint-disable-next-line no-nested-ternary */}
{column.format && typeof value === 'number' ? (
column.format(value)
) : value === 'edit' ? (
<>
<Button onClick={() => handleFileDownLoad(row)} variant="outlined" sx={{ ml: 1 }}>
파일다운로드
</Button>
<Button onClick={() => handleFileDelete(row)} variant="outlined" sx={{ ml: 1 }}>
파일삭제
</Button>
</>
) : (
value
)}
{/* column.format && typeof value === 'number' ? column.format(value) : value */}
</TableCell>
);
})}
</TableRow>
// eslint-disable-next-line indent
))
) : (
<TableRow hover>
<TableCell align="center" colSpan={4}>
데이터가 존재 하지 않습니다.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</TableContainer>
</Paper>
</div>
</Grid>
)}
</Grid>
</div>
</Box>
{/*
<Viewer height="300px" initialValue={contents || '<p>hello react editㄷㄱㄱㄷㅈㄷor world!</p>'} />
*/}
<div className="m-5 text-center ">
<Button type="submit" variant="outlined" className="mr-10 dark:text-white" onClick={saveSubmit}>
<SaveIcon />
저장
</Button>
{mode !== 'I' && (
<Button type="submit" variant="outlined" className="mr-10 dark:text-white" onClick={deleteSubmit}>
<SaveIcon />
삭제
</Button>
)}
<Button type="submit" variant="outlined" className="dark:text-white" onClick={handleClose}>
<SaveIcon />
닫기
</Button>
</div>
</Dialog>
</div>
);
}
728x90
반응형
'프로그램 > 자바' 카테고리의 다른 글
1. java jwt token 생성 및 jar 라이브러리 만드는 방법 (0) | 2024.02.22 |
---|---|
레이어드 아키텍처 (0) | 2023.09.10 |
Java 에서 ValidatorException 등 인증서 관련 에러 해결 (1) | 2023.05.10 |
자바 cors 우회하기 get,post방식 (0) | 2022.07.12 |
자바 랜덤 API 암호화 BASE64 KEY 생성 (0) | 2022.01.13 |
댓글