ソースを参照

게시판 완료

junekeunsong 4 年 前
コミット
7d083ada7d

+ 262 - 13
src/main/java/com/lemon/lifecenter/controller/BoardController.java

@@ -36,7 +36,6 @@ import com.lemon.lifecenter.dto.BoardDTO;
 import com.lemon.lifecenter.service.BoardService;
 
 @Controller
-@RequestMapping("/board")
 public class BoardController extends LifeCenterController {
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
     
@@ -111,7 +110,7 @@ public class BoardController extends LifeCenterController {
         String sesGroupIdx = LifeCenterSessionController.getSession(request, "sesGroupIdx");
         
         if (!sesGroupIdx.equals("1")) {
-            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '공지사항 작성 권한이 없습니다.', callBack : function(){ location.href='/board/notice/list'; } });" );
+            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '공지사항 작성 권한이 없습니다.', callBack : function(){ location.href='/notice/list'; } });" );
             return "/common/blank";
         }
         
@@ -136,6 +135,7 @@ public class BoardController extends LifeCenterController {
             dto.setFileName(saveFileName);
             dto.setFileExtension(ext);
             dto.setFileSize(fileSize);
+            dto.setBoardType("N");
         }
 
         String title = dto.getTitle().trim();
@@ -162,7 +162,7 @@ public class BoardController extends LifeCenterController {
             }
         }
         
-        return "redirect:/board/notice/content?postSeq=" + dto.getPostSeq();
+        return "redirect:/notice/content?postSeq=" + dto.getPostSeq();
     }
     
     @RequestMapping("/notice/content")
@@ -208,10 +208,15 @@ public class BoardController extends LifeCenterController {
     public void boardFile(HttpServletRequest request, HttpServletResponse response,
             @RequestParam(value="postSeq", required=false, defaultValue="") int postSeq) {
         
-        int total = boardService.selectFileCount(postSeq);
         BoardDTO dto = new BoardDTO();
+        dto.setPostSeq(postSeq);
+        dto.setBoardType("N");
+        int total = boardService.selectFileCount(dto);
+        
         if (total > 0) {
-            dto = boardService.selectFile(postSeq);
+            dto.setPostSeq(postSeq);
+            dto.setBoardType("N");
+            dto = boardService.selectFile(dto);
             String filePath = config.filePath + "/" + dto.getFileName();
             String fileName = dto.getFileOriginalName();
             logger.error("filePath -- > " + filePath);
@@ -222,18 +227,27 @@ public class BoardController extends LifeCenterController {
     @RequestMapping(value="/notice/content/delete")
     @Transactional(propagation=Propagation.REQUIRED)
     public String contentDelete(HttpServletRequest request, HttpServletResponse response,
-            @RequestParam(value="postSeq", required=false, defaultValue="") int postSeq) {
+            @RequestParam(value="postSeq", required=false, defaultValue="") int postSeq,
+            @RequestParam(value="fileName", required=false, defaultValue="") String fileName) {
         String sesGroupIdx = LifeCenterSessionController.getSession(request, "sesGroupIdx");
         
         if (!sesGroupIdx.equals("1")) {
-            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '해당 글을 삭제할 수 없습니다.', callBack : function(){ location.href='/board/notice/list'; } });" );
+            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '해당 글을 삭제할 수 없습니다.', callBack : function(){ location.href='/notice/list'; } });" );
             return "/common/blank";
         }
         
+        BoardDTO dto = new BoardDTO();
+        dto.setPostSeq(postSeq);
+        dto.setBoardType("N");
         boardService.deleteNoticeIfno(postSeq);
-        boardService.deleteFile(postSeq);
         
-        LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '게시글이 삭제되었습니다. ', callBack : function(){ location.href='/board/notice/list'; } });" );
+        String path = config.filePath + "/" + fileName.trim();
+        File rFile = new File(path);
+        rFile.delete();
+        
+        boardService.deleteFile(dto);
+        
+        LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '게시글이 삭제되었습니다. ', callBack : function(){ location.href='/notice/list'; } });" );
         
         return "/common/blank";
     }
@@ -272,7 +286,7 @@ public class BoardController extends LifeCenterController {
         String sesGroupIdx = LifeCenterSessionController.getSession(request, "sesGroupIdx");
         
         if (!sesGroupIdx.equals("1")) {
-            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '공지사항 작성 권한이 없습니다.', callBack : function(){ location.href='./list'; } });" );
+            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '공지사항 수정 권한이 없습니다.', callBack : function(){ location.href='./list'; } });" );
             return "/common/blank";
         }
         
@@ -302,7 +316,8 @@ public class BoardController extends LifeCenterController {
             dto.setFileName(saveFileName);
             dto.setFileExtension(ext);
             dto.setFileSize(fileSize);
-            int cnt = boardService.selectFileCount(postSeq);
+            dto.setBoardType("N");
+            int cnt = boardService.selectFileCount(dto);
             if (cnt > 0) {
                 boardService.updateFile(dto);
             } else {
@@ -314,14 +329,15 @@ public class BoardController extends LifeCenterController {
                 String path = config.filePath + "/" + dto.getFileName().trim();
                 File rFile = new File(path);
                 rFile.delete();
-                boardService.deleteFile(postSeq);
+                dto.setBoardType("N");
+                boardService.deleteFile(dto);
             }
         }
         
         dto.setUpdateBy(sesId);
         boardService.updateNoticeBoard(dto);
         
-        return "redirect:/board/notice/content?postSeq=" + dto.getPostSeq();
+        return "redirect:/notice/content?postSeq=" + dto.getPostSeq();
     }
     
     @RequestMapping("/qna/list")
@@ -368,4 +384,237 @@ public class BoardController extends LifeCenterController {
         mv.addObject("pageSize", dto.getLimitMax());
         return mv;
     }
+    
+    @RequestMapping("/qna/new")
+    public ModelAndView boardQnaNew(HttpServletRequest request, HttpServletResponse response) {
+        String sesGroupIdx = LifeCenterSessionController.getSession( request, "sesGroupIdx" );
+        ModelAndView mv = setMV("qna/new");
+        mv.addObject("groupIdx",sesGroupIdx);
+        
+        return mv;
+    }
+    
+    @RequestMapping("/qna/new/insert")
+    @Transactional(propagation=Propagation.REQUIRED)
+    public String boardQnaNewInsert(
+            HttpServletRequest request, HttpServletResponse response,
+            @ModelAttribute("dto") final BoardDTO dto,
+            MultipartFile file) {
+        String sesId = LifeCenterSessionController.getSession(request, "sesId");
+        
+        if (file.isEmpty() == false) {
+            UUID uuid = UUID.randomUUID();
+            String fileName = file.getOriginalFilename();
+            int fileSize = (int) file.getSize(); //단위는 byte
+            String ext = FilenameUtils.getExtension(fileName);
+            String saveFileName = uuid + "." + ext;
+            
+            try {
+                String tempPath = config.filePath;
+                File saveFile = new File(tempPath, saveFileName);
+                FileCopyUtils.copy(file.getBytes(),saveFile);
+            } catch (IOException e) {
+                e.printStackTrace();
+                LifeCenterFunction.scriptMessage( response, "alertBox({ txt : '파일 업로드에 실패하였습니다.', callBack : function(){ history.back(); } });" );
+                return "/common/blank";
+            }
+            
+            dto.setFileOriginalName(fileName);
+            dto.setFileName(saveFileName);
+            dto.setFileExtension(ext);
+            dto.setFileSize(fileSize);
+            dto.setBoardType("Q");
+        }
+
+        String title = dto.getTitle().trim();
+        String content = dto.getContent().trim();
+        
+        dto.setTitle(title);
+        dto.setContent(content);
+        dto.setCreateBy(sesId);
+        
+        boardService.qnaInsert(dto);
+        int postSeq = dto.getPostSeq();
+        
+        if (postSeq == 0) {
+            LifeCenterFunction.scriptMessage( response, "alertBox({ txt : '게시물 등록에 실패하였습니다.', callBack : function(){ history.back(); } });" );
+            return "/common/blank";
+        } else {
+            if (file.isEmpty() == false) {
+                boardService.fileUploadDataInsert(dto);
+                int fileIdx = dto.getFileIdx();
+                if (fileIdx == 0) {
+                    LifeCenterFunction.scriptMessage( response, "alertBox({ txt : '게시물 등록에 실패하였습니다.', callBack : function(){ history.back(); } });" );
+                    return "/common/blank";
+                }
+            }
+        }
+        
+        return "redirect:/qna/content?postSeq=" + dto.getPostSeq();
+    }
+    
+    @RequestMapping("/qna/content")
+    public ModelAndView boardQnaContent(
+            @RequestParam(value="postSeq", required=false, defaultValue="") int postSeq,
+            HttpServletRequest request, HttpServletResponse response) {
+        String referer     = request.getHeader("referer");
+        String sesId       = LifeCenterSessionController.getSession(request, "sesId");
+        String sesName     = LifeCenterSessionController.getSession(request, "sesName");
+        String sesGroupIdx = LifeCenterSessionController.getSession( request, "sesGroupIdx" );
+        
+        int total = boardService.selectQnaBoardCountOne(postSeq);
+        BoardDTO dto = new BoardDTO();
+        if (total > 0) {
+            boardService.updateQnaView(postSeq);
+            dto = boardService.selectQnaBoardInfoOne(postSeq);
+        }
+        
+        int prePostCnt = boardService.selectQnaPrePostCount(postSeq);
+        int nextPostCnt = boardService.selectQnaNextPostCount(postSeq);
+        
+        BoardDTO preDto = new BoardDTO();
+        BoardDTO nextDto = new BoardDTO();
+        if (prePostCnt > 0) {
+            preDto = boardService.selectQnaPrePost(postSeq);
+        }
+        
+        if (nextPostCnt > 0) {
+            nextDto = boardService.selectQnaNextPost(postSeq);
+        }
+        
+        ModelAndView mv = setMV("qna/content");
+        mv.addObject("filePath", config.filePath);
+        mv.addObject("content", dto);
+        mv.addObject("sesId", sesId);
+        mv.addObject("sesName", sesName);
+        mv.addObject("groupIdx", sesGroupIdx);
+        mv.addObject("prePostCnt", prePostCnt);
+        mv.addObject("nextPostCnt", nextPostCnt);
+        mv.addObject("prePost", preDto);
+        mv.addObject("nextPost", nextDto);
+        mv.addObject("referer", referer);
+        return mv;
+    }
+    
+    @RequestMapping("/qna/content/answer")
+    public String boardQnaAnswer(HttpServletRequest request, HttpServletResponse response,
+            @ModelAttribute("dto") final BoardDTO dto) {
+        
+        logger.error("postSeq -- > " + dto.getPostSeq());
+        logger.error("answerId -- > " + dto.getAnswerId());
+        logger.error("answerContent -- > " + dto.getAnswerContent());
+        boardService.qnaAnswerInsert(dto);
+        
+        return "redirect:/qna/content?postSeq=" + dto.getPostSeq();
+    }
+    
+    @RequestMapping("/qna/edit")
+    public ModelAndView boarQnadEdit(HttpServletRequest request, HttpServletResponse response,
+            @RequestParam(value="postSeq", required=false, defaultValue="") int postSeq) {
+        ModelAndView mv = setMV("qna/edit");
+        
+        BoardDTO dto = new BoardDTO();
+        int cnt = boardService.selectQnaBoardCountOne(postSeq);
+        if (cnt == 0) {
+            
+        } else {
+            dto = boardService.selectQnaBoardInfoOne(postSeq);
+        }
+        mv.addObject("item", dto);
+        return mv;
+    }
+    
+    @RequestMapping("/qna/edit/update")
+    @Transactional(propagation=Propagation.REQUIRED)
+    public String boardQnaEditUpdate(
+            HttpServletRequest request, HttpServletResponse response,
+            @ModelAttribute("dto") final BoardDTO dto,
+            MultipartFile file) {
+        
+        String sesId = LifeCenterSessionController.getSession(request, "sesId");
+        
+        if (!sesId.equals(dto.getCreateBy())) {
+            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '해당글의 수정 권한이 없습니다.', callBack : function(){ location.href='./list'; } });" );
+            return "/common/blank";
+        }
+        
+        int postSeq = dto.getPostSeq();
+        
+        if (file.isEmpty() == false) {
+            UUID uuid = UUID.randomUUID();
+            String fileName = file.getOriginalFilename();
+            int fileSize = (int) file.getSize(); //단위는 byte
+            String ext = FilenameUtils.getExtension(fileName);
+            String saveFileName = uuid + "." + ext;
+            
+            try {
+                File saveFile = new File(config.filePath, saveFileName);
+                FileCopyUtils.copy(file.getBytes(),saveFile);
+                
+                String path = config.filePath + "/" + dto.getFileName().trim();
+                File rFile = new File(path);
+                rFile.delete();
+            } catch (IOException e) {
+                e.printStackTrace();
+                LifeCenterFunction.scriptMessage( response, "alertBox({ txt : '파일 업로드에 실패하였습니다.', callBack : function(){ history.back(); } });" );
+                return "/common/blank";
+            }
+            
+            dto.setFileOriginalName(fileName);
+            dto.setFileName(saveFileName);
+            dto.setFileExtension(ext);
+            dto.setFileSize(fileSize);
+            dto.setBoardType("Q");
+            int cnt = boardService.selectFileCount(dto);
+            if (cnt > 0) {
+                boardService.updateFile(dto);
+            } else {
+                boardService.fileUploadDataInsert(dto);
+            }
+            
+        } else {
+            if (dto.getFileOriginalName().equals("")) {
+                String path = config.filePath + "/" + dto.getFileName().trim();
+                File rFile = new File(path);
+                rFile.delete();
+                dto.setBoardType("Q");
+                boardService.deleteFile(dto);
+            }
+        }
+        
+        dto.setUpdateBy(sesId);
+        boardService.updateQnaBoard(dto);
+        
+        return "redirect:/qna/content?postSeq=" + postSeq;
+    }
+    
+    @RequestMapping(value="/qna/content/delete")
+    @Transactional(propagation=Propagation.REQUIRED)
+    public String contentQnaDelete(HttpServletRequest request, HttpServletResponse response,
+            @RequestParam(value="postSeq", required=false, defaultValue="") int postSeq,
+            @RequestParam(value="createBy", required=false, defaultValue="") String createBy,
+            @RequestParam(value="fileName", required=false, defaultValue="") String fileName) {
+        
+        String sesId = LifeCenterSessionController.getSession(request, "sesId");
+        
+        if (!sesId.equals(createBy)) {
+            LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '해당 글을 삭제할 수 없습니다.', callBack : function(){ location.href='/qna/list'; } });" );
+            return "/common/blank";
+        }
+        
+        BoardDTO dto = new BoardDTO();
+        dto.setPostSeq(postSeq);
+        dto.setBoardType("Q");
+        boardService.deleteQnaIfno(postSeq);
+        
+        String path = config.filePath + "/" + fileName.trim();
+        File rFile = new File(path);
+        rFile.delete();
+        
+        boardService.deleteFile(dto);
+        
+        LifeCenterFunction.scriptMessage( response, "alertBox({ txt: '게시글이 삭제되었습니다. ', callBack : function(){ location.href='/qna/list'; } });" );
+        
+        return "/common/blank";
+    }
 }

+ 0 - 7
src/main/java/com/lemon/lifecenter/controller/MobileHealthController.java

@@ -53,13 +53,6 @@ public class MobileHealthController extends LifeCenterController {
         String referer  = request.getHeader( "Referer" );
         String path = new URL( referer ).getPath();
         
-        System.err.println( pdto.getPhrType() );
-        System.err.println( pdto.getPhrValue() );
-        System.err.println( pdto.getPhrValue2() );
-        System.err.println( phrTypeAnother );
-        System.err.println( phrValueAnother );
-        System.err.println( phrValueAnother2 );
-        
         if( pdto.getPhrType().equals( "symptom" ) ) {
             
             sdto.setPatientIdx( patientIdx );

+ 15 - 0
src/main/java/com/lemon/lifecenter/dto/BoardDTO.java

@@ -13,12 +13,14 @@ public class BoardDTO {
     private String answerContent = "";
     private String answerDate    = null;
     private String answerId      = "";
+    private String answerName    = "";
     
     private int fileIdx = 0;
     private String fileOriginalName = "";
     private String fileName = "";
     private String fileExtension = "";
     private int fileSize = 0;
+    private String boardType = "";
     
     private int limit = 0;
     private int limitMax = 0;
@@ -28,6 +30,13 @@ public class BoardDTO {
     private int nextPostSeq = 0;
     private String nextPostTitle = "";
     
+    
+    public String getBoardType() {
+        return boardType;
+    }
+    public void setBoardType(String boardType) {
+        this.boardType = boardType;
+    }
     public int getPrePostSeq() {
         return prePostSeq;
     }
@@ -124,6 +133,12 @@ public class BoardDTO {
     public void setAnswerId(String answerId) {
         this.answerId = answerId;
     }
+    public String getAnswerName() {
+        return answerName;
+    }
+    public void setAnswerName(String answerName) {
+        this.answerName = answerName;
+    }
     public int getFileIdx() {
         return fileIdx;
     }

+ 14 - 3
src/main/java/com/lemon/lifecenter/mapper/BoardMapper.java

@@ -18,10 +18,10 @@ public interface BoardMapper {
     public int selectNoticeBoardCountOne(int postSeq);
     public BoardDTO selectNoticeBoardInfoOne(int postSeq);
     public int updateNoticeBoard(BoardDTO dto);
-    public int selectFileCount(int postSeq);
+    public int selectFileCount(BoardDTO dto);
     public int updateFile(BoardDTO dto);
-    public int deleteFile(int postSeq);
-    public BoardDTO selectFile(int postSeq);
+    public int deleteFile(BoardDTO dto);
+    public BoardDTO selectFile(BoardDTO dto);
     public int selectPrePostCount(int postSeq);
     public BoardDTO selectPrePost(int postSeq);
     public int selectNextPostCount(int postSeq);
@@ -32,5 +32,16 @@ public interface BoardMapper {
     //의견게시판
     public int selectQnaListCount(BoardDTO dto);
     public List<BoardDTO> selectQnaList(BoardDTO dto);
+    public void qnaInsert(BoardDTO dto);
+    public int selectQnaBoardCountOne(int postSeq);
+    public BoardDTO selectQnaBoardInfoOne(int postSeq);
+    public int selectQnaPrePostCount(int postSeq);
+    public BoardDTO selectQnaPrePost(int postSeq);
+    public int selectQnaNextPostCount(int postSeq);
+    public BoardDTO selectQnaNextPost(int postSeq);
+    public void updateQnaView(int postSeq);
+    public int updateQnaBoard(BoardDTO dto);
+    public int deleteQnaIfno(int postSeq);
+    public int qnaAnswerInsert(BoardDTO dto);
     //의견게시판
 }

+ 39 - 6
src/main/java/com/lemon/lifecenter/service/BoardService.java

@@ -42,20 +42,20 @@ public class BoardService {
         return mapper.updateNoticeBoard(dto);
     }
     
-    public int selectFileCount(int postSeq) {
-        return mapper.selectFileCount(postSeq);
+    public int selectFileCount(BoardDTO dto) {
+        return mapper.selectFileCount(dto);
     }
     
     public int updateFile(BoardDTO dto) {
         return mapper.updateFile(dto);
     }
     
-    public int deleteFile(int postSeq) {
-        return mapper.deleteFile(postSeq);
+    public int deleteFile(BoardDTO dto) {
+        return mapper.deleteFile(dto);
     }
     
-    public BoardDTO selectFile(int postSeq) {
-        return mapper.selectFile(postSeq);
+    public BoardDTO selectFile(BoardDTO dto) {
+        return mapper.selectFile(dto);
     }
     
     public int selectPrePostCount(int postSeq) {
@@ -84,5 +84,38 @@ public class BoardService {
     public List<BoardDTO> selectQnaList(BoardDTO dto) {
         return mapper.selectQnaList(dto);
     }
+    public void qnaInsert(BoardDTO dto) {
+        mapper.qnaInsert(dto);
+    }
+    public int selectQnaBoardCountOne(int postSeq) {
+        return mapper.selectQnaBoardCountOne(postSeq);
+    }
+    public BoardDTO selectQnaBoardInfoOne(int postSeq) {
+        return mapper.selectQnaBoardInfoOne(postSeq);
+    }
+    public int selectQnaPrePostCount(int postSeq) {
+        return mapper.selectQnaPrePostCount(postSeq);
+    }
+    public BoardDTO selectQnaPrePost(int postSeq) {
+        return mapper.selectQnaPrePost(postSeq);
+    }
+    public int selectQnaNextPostCount(int postSeq) {
+        return mapper.selectQnaNextPostCount(postSeq);
+    }
+    public BoardDTO selectQnaNextPost(int postSeq) {
+        return mapper.selectQnaNextPost(postSeq);
+    }
+    public void updateQnaView(int postSeq) {
+        mapper.updateQnaView(postSeq);
+    }
+    public int updateQnaBoard(BoardDTO dto) {
+        return mapper.updateQnaBoard(dto);
+    }
+    public int deleteQnaIfno(int postSeq) {
+        return mapper.deleteQnaIfno(postSeq);
+    }
+    public int qnaAnswerInsert(BoardDTO dto) {
+        return mapper.qnaAnswerInsert(dto);
+    }
     //의견게시판
 }

+ 124 - 11
src/main/resources/mybatis/mapper/board/board.xml

@@ -73,8 +73,8 @@
         </selectKey>
         <![CDATA[
             INSERT INTO BOARD_ATTACH_FILE
-                        (POST_SEQ,   FILE_ORIGINAL_NAME,  FILE_NAME,   FILE_EXTENSION,   FILE_SIZE)
-                 VALUES (#{postSeq}, #{fileOriginalName}, #{fileName}, #{fileExtension}, #{fileSize})
+                        (POST_SEQ,   FILE_ORIGINAL_NAME,  FILE_NAME,   FILE_EXTENSION,   FILE_SIZE,   BOARD_TYPE)
+                 VALUES (#{postSeq}, #{fileOriginalName}, #{fileName}, #{fileExtension}, #{fileSize}, #{boardType})
         ]]>
     </insert>
     
@@ -127,20 +127,21 @@
              WHERE POST_SEQ = #{postSeq}
         ]]>
     </update>
-    <select id="selectFileCount" parameterType="int" resultType="int">
+    <select id="selectFileCount" parameterType="BoardDTO" resultType="int">
         <![CDATA[
             SELECT COUNT(*) AS cnt
               FROM BOARD_ATTACH_FILE
-             WHERE POST_SEQ = ${postSeq}
+             WHERE POST_SEQ = #{postSeq}
+               AND BOARD_TYPE = #{boardType}
         ]]>
     </select>
-    <select id="selectFile" parameterType="int" resultType="BoardDTO">
+    <select id="selectFile" parameterType="BoardDTO" resultType="BoardDTO">
         <![CDATA[
             SELECT FILE_NAME           AS fileName,
                    FILE_ORIGINAL_NAME  AS fileOriginalName
               FROM BOARD_ATTACH_FILE
              WHERE POST_SEQ = ${postSeq}
-              
+               AND BOARD_TYPE = ${boardType}
         ]]>
     </select>
     <update id="updateFile" parameterType="BoardDTO">
@@ -153,9 +154,9 @@
              WHERE POST_SEQ = #{postSeq}
         ]]>
     </update>
-    <delete id="deleteFile" parameterType="int">
+    <delete id="deleteFile" parameterType="BoardDTO">
         <![CDATA[
-            DELETE FROM BOARD_ATTACH_FILE WHERE POST_SEQ = #{postSeq}
+            DELETE FROM BOARD_ATTACH_FILE WHERE POST_SEQ = #{postSeq} AND BOARD_TYPE = #{boardType}
         ]]>
     </delete>
     <select id="selectPrePostCount" parameterType="int" resultType="int">
@@ -218,7 +219,7 @@
              ]]>
          </if>
     </select>
-        <select id="selectQnaList" parameterType="BoardDTO" resultType="BoardDTO">
+    <select id="selectQnaList" parameterType="BoardDTO" resultType="BoardDTO">
         <![CDATA[
             SELECT POST_SEQ                                      AS postSeq,
                    TITLE                                         AS title,
@@ -227,8 +228,8 @@
                    VIEWS                                         AS views,
                    (SELECT FILE_EXTENSION
                       FROM BOARD_ATTACH_FILE BAF
-                    WHERE BAF.POST_SEQ = POST_SEQ)               AS fileExtension
-              FROM BOARD_REQUEST
+                    WHERE BAF.POST_SEQ = BR.POST_SEQ)               AS fileExtension
+              FROM BOARD_REQUEST BR
              WHERE 1 = 1
          ]]>
          <if test='title != null and title != ""'>
@@ -246,6 +247,118 @@
                  AND CONTENT LIKE CONCAT('%', #{content}, '%')
              ]]>
          </if>
+         <![CDATA[
+             ORDER BY BR.CREATE_DATE DESC
+             LIMIT ${limit}, ${limitMax}
+         ]]>
+    </select>
+    <insert id="qnaInsert" parameterType="BoardDTO">
+        <selectKey keyProperty="postSeq" resultType="int" order="AFTER">
+            <![CDATA[
+                SELECT CURRENT_VAL AS postSeq FROM db_serial WHERE NAME = 'board_request_ai_post_seq'
+            ]]>
+        </selectKey>
+        <![CDATA[
+            INSERT INTO BOARD_REQUEST
+                        (TITLE, CONTENT, CREATE_BY, CREATE_DATE)
+                 VALUES (#{title}, #{content}, #{createBy}, DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s'))
+        ]]>
+    </insert>
+    <select id="selectQnaBoardCountOne" parameterType="int" resultType="int">
+        <![CDATA[
+            SELECT COUNT(*) CNT
+              FROM BOARD_REQUEST BR
+              LEFT JOIN BOARD_ATTACH_FILE BAF
+                ON BR.POST_SEQ = BAF.POST_SEQ
+             WHERE 1 = 1
+               AND BR.POST_SEQ = #{postSeq}
+        ]]>
+    </select>
+    <select id="selectQnaBoardInfoOne" parameterType="int" resultType="BoardDTO">
+        <![CDATA[
+            SELECT BR.POST_SEQ                                       AS postSeq,
+                   BR.TITLE                                          AS title,
+                   BR.CONTENT                                        AS content,
+                   BAF.FILE_ORIGINAL_NAME                            AS fileOriginalName,
+                   BAF.FILE_NAME                                     AS fileName,
+                   DATE_FORMAT(BR.CREATE_DATE, '%Y-%m-%d %H:%i:%s')  AS createDate,
+                   BR.CREATE_BY                                      AS createBy,
+                   (SELECT NAME
+                      FROM member
+                     WHERE ID = BR.CREATE_BY)                        AS createByName,
+                   BR.ANSWER_CONTENT                                 AS answerContent,
+                   BR.ANSWER_ID                                      AS answerId,
+                   (SELECT NAME
+                      FROM MEMBER M
+                     WHERE M.ID = BR.ANSWER_ID)                      AS answerName,
+                   BR.VIEWS                                          AS views
+              FROM BOARD_REQUEST BR
+              LEFT JOIN BOARD_ATTACH_FILE BAF
+                ON BR.POST_SEQ = BAF.POST_SEQ
+             WHERE 1 = 1
+               AND BR.POST_SEQ = #{postSeq}
+        ]]>
     </select>
+    <update id="qnaAnswerInsert" parameterType="BoardDTO">
+        <![CDATA[
+            UPDATE BOARD_REQUEST
+               SET ANSWER_DATE    = DATE_FORMAT(NOW(), '%Y-%M-%D %H:%I:%S'),
+                   ANSWER_ID      = #{answerId},
+                   ANSWER_CONTENT = #{answerContent}
+             WHERE POST_SEQ       = #{postSeq}
+        ]]>
+    </update>
+    <select id="selectQnaPrePostCount" parameterType="int" resultType="int">
+        <![CDATA[
+            SELECT COUNT(*) AS cnt
+              FROM BOARD_REQUEST
+             WHERE POST_SEQ = (SELECT MAX(POST_SEQ) FROM BOARD_REQUEST WHERE POST_SEQ < #{postSeq})
+        ]]>
+    </select>
+    <select id="selectQnaPrePost" parameterType="int" resultType="BoardDTO">
+        <![CDATA[
+            SELECT POST_SEQ AS prePostSeq,
+                   TITLE    AS prePostTitle
+              FROM BOARD_REQUEST
+             WHERE POST_SEQ = (SELECT MAX(POST_SEQ) FROM BOARD_REQUEST WHERE POST_SEQ < #{postSeq})
+        ]]>
+    </select>
+    <select id="selectQnaNextPostCount" parameterType="int" resultType="int">
+        <![CDATA[
+            SELECT COUNT(*) AS cnt
+              FROM BOARD_REQUEST
+             WHERE POST_SEQ = (SELECT MIN(POST_SEQ) FROM BOARD_REQUEST WHERE POST_SEQ > #{postSeq})
+        ]]>
+    </select>
+    <select id="selectQnaNextPost" parameterType="int" resultType="BoardDTO">
+        <![CDATA[
+            SELECT POST_SEQ AS nextPostSeq,
+                   TITLE    AS nextPostTitle
+              FROM BOARD_REQUEST
+             WHERE POST_SEQ = (SELECT MIN(POST_SEQ) FROM BOARD_REQUEST WHERE POST_SEQ > #{postSeq})
+        ]]>
+    </select>
+    <update id="updateQnaView" parameterType="int">
+        <![CDATA[
+            UPDATE BOARD_REQUEST
+               SET VIEWS = VIEWS + 1
+             WHERE POST_SEQ = #{postSeq}
+        ]]>
+    </update>
+    <update id="updateQnaBoard" parameterType="BoardDTO">
+        <![CDATA[
+            UPDATE BOARD_REQUEST
+               SET TITLE     = #{title},
+                   CONTENT   = #{content},
+                   UPDATE_BY = #{updateBy},
+                   UPDATE_DATE = DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')
+             WHERE POST_SEQ = #{postSeq}
+        ]]>
+    </update>
+    <delete id="deleteQnaIfno">
+        <![CDATA[
+            DELETE FROM BOARD_REQUEST WHERE POST_SEQ = #{postSeq}
+        ]]>
+    </delete>
     <!-- 의견게시판 -->
 </mapper>

+ 6 - 0
src/main/webapp/WEB-INF/jsp/include/sidebar.jsp

@@ -81,6 +81,12 @@ $( function(){
                             <a class="sidebar-link" href="/push/list">푸시 서비스 관리(테스트)</a>
                         </li>
                     </c:if>
+                        <li class="sidebar-item <c:if test='${data._MENUPATH eq "notice"}'>active</c:if>">
+                            <a class="sidebar-link" href="/notice/list">공지사항</a>
+                        </li>
+                        <li class="sidebar-item <c:if test='${data._MENUPATH eq "qna"}'>active</c:if>">
+                            <a class="sidebar-link" href="/qna/list">의견 게시판</a>
+                        </li>
                 </ul>
             </li>
         </ul>

+ 4 - 3
src/main/webapp/WEB-INF/jsp/notice/content.jsp

@@ -20,14 +20,14 @@ function deleteConfirm(){
 }
 
 var listPage = '<c:out value="${referer}"/>'.replaceAll( "&amp;", "&" );
-if( listPage.includes( '/board/notice/list' ) ) {
+if( listPage.includes( '/notice/list' ) ) {
     encodeURIComponent(listPage);
     setCookie( "boardlistPage", listPage );
 }
 function goListPage(){
     var referer = getCookie( "boardlistPage" );
     if( referer == "" ) {
-        referer = "/board/notice/list";
+        referer = "/notice/list";
     }
     location.href = referer;
 }
@@ -50,7 +50,7 @@ function goListPage(){
                             <nav aria-label="breadcrumb">
                                 <ol class="breadcrumb">
                                     <li class="breadcrumb-item"><a href="javscript:;">Home</a></li>
-                                    <li class="breadcrumb-item">공지사항 수정</li>
+                                    <li class="breadcrumb-item">공지사항</li>
                                 </ol>
                             </nav>
                         </div>
@@ -60,6 +60,7 @@ function goListPage(){
                             <div class="card">
                                 <form id="sendForm" action="./notice/content/delete" method="post">
                                     <input type="hidden" name="postSeq" value="${content.postSeq}" >
+                                    <input type="hidden" name="fileName" value="${content.fileName}" >
                                     <div class="card-body">
                                         <table class="table mobile-table">
                                             <colgroup>

+ 219 - 0
src/main/webapp/WEB-INF/jsp/qna/content.jsp

@@ -0,0 +1,219 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+    pageEncoding="UTF-8"%>
+<jsp:include page="${data._INCLUDE}/header.jsp"></jsp:include>
+<script>
+function deleteConfirm(){
+    alertBox({ type : "confirm", 
+               txt : "정말로 삭제할까요? (해당 게시글이 삭제되며 복구가 불가능합니다)", 
+               callBack : function( result ){
+                   if( result ){
+                       $( "#sendForm" ).attr( "action", "./content/delete" );
+                       $( "#sendForm" ).submit();
+                   }
+               }
+    });
+    return false;
+}
+
+function answerConfirm(){
+    alertBox({ type : "confirm", 
+               txt : "답변을 등록하시겠습니까?", 
+               callBack : function( result ){
+                   console.log( result );
+                   if( result ){
+                       var newForm = $( "#sendForm" ).clone();
+                       newForm.attr("id", "answerForm");
+                       newForm.attr("method", "post");
+                       newForm.attr("action", "./content/answer");
+
+                       $(document.body).append(newForm);
+                       newForm.submit();
+                       $("#answerForm").remove();
+//                        $( "#sendForm" ).attr( "action", "./content/answer" );
+//                        $( "#sendForm" ).submit();
+                   }
+               }
+    });
+    return false;
+}
+
+var listPage = '<c:out value="${referer}"/>'.replaceAll( "&amp;", "&" );
+if( listPage.includes( '/qna/list' ) ) {
+    encodeURIComponent(listPage);
+    setCookie( "boardQnalistPage", listPage );
+}
+function goListPage(){
+    var referer = getCookie( "boardQnalistPage" );
+    if( referer == "" ) {
+        referer = "/qna/list";
+    }
+    location.href = referer;
+}
+</script>
+</head>
+<body>
+    <div class="wrapper">
+        <jsp:include page="${data._INCLUDE}/sidebar.jsp"></jsp:include>
+        
+        <div class="main">
+            <jsp:include page="${data._INCLUDE}/top.jsp"></jsp:include>
+
+            <main class="content">
+                <div class="container-fluid p-0">
+                    <div class="row">
+                        <div class="col-12 col-lg-6">
+                            <h1 class="h3 mb-3">의견 게시판</h1>
+                        </div>
+                        <div class="col-12 col-lg-6  text-right">
+                            <nav aria-label="breadcrumb">
+                                <ol class="breadcrumb">
+                                    <li class="breadcrumb-item"><a href="javscript:;">Home</a></li>
+                                    <li class="breadcrumb-item">의견 게시판</li>
+                                </ol>
+                            </nav>
+                        </div>
+                    </div>
+                    <div class="row">
+                        <div class="col-12">
+                            <div class="card">
+                                <form id="sendForm" action="./qna/content/delete" method="post">
+                                    <input type="hidden" name="postSeq" value="${content.postSeq}" >
+                                    <input type="hidden" name="createBy" value="${content.createBy}" >
+                                    <input type="hidden" name="fileName" value="${content.fileName}" >
+                                    <div class="card-body">
+                                        <table class="table mobile-table">
+                                            <colgroup>
+                                                <col style="width:75%">
+                                                <col style="width:">
+                                                <col style="width:">
+                                            </colgroup>
+                                            
+                                            <tr>
+                                                <td>조회수 : <c:out value="${content.views}"></c:out></td>
+                                                <th class="text-center">작성자</th>
+                                                <td><c:out value="${content.createBy}(${content.createByName})" /></td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <td class="text-bold text-info"><c:out value="${content.title}" /></td>
+                                                <th class="text-center">작성일</th>
+                                                <td><c:out value="${content.createDate}" /></td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <td colspan="3" style="white-space: pre-line;"><div style="min-height:200px;"><c:out value="${content.content}" /></div></td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <td colspan="3">
+                                                    <span class="badge bg-primary">첨부파일</span>
+                                                    <a href="./content/file?postSeq=${content.postSeq}" class="text-dark" target="_blank"><c:out value="${content.fileOriginalName}" /></a>
+                                                </td>
+                                            </tr>
+                                        </table>
+                                        
+                                        <c:if test="${groupIdx eq 1}">
+                                            <input type="hidden" name="answerId" value="${sesId}">
+                                            <table class="mt-3 table mobile-table">
+                                                <colgroup>
+                                                    <col style="width:10%">
+                                                    <col style="width:">
+                                                </colgroup>
+                                                
+                                                <tr>
+                                                    <th>작성자</th>
+<!--                                                     <td> -->
+<%--                                                         <c:out value="${sesName}(${sesId})" /> --%>
+<!--                                                     </td> -->
+                                                    <c:if test="${content.answerId eq ''}">
+                                                        <td>
+                                                            <c:out value="${sesName}(${sesId})" />
+                                                        </td>
+                                                    </c:if>
+                                                    <c:if test="${content.answerId ne ''}">
+                                                        <td>
+                                                            <c:out value="${content.answerName}(${content.answerId})" />
+                                                        </td>
+                                                    </c:if>
+                                                </tr>
+                                                <tr>
+                                                    <th>답변</th>
+                                                    <c:if test="${content.answerContent eq ''}">
+                                                        <td>
+                                                            <textarea class="form-control" rows="2" cols="" name="answerContent" placeholder="내용을 입력하세요" maxlength="1000" required><c:out value="${item.content}" /></textarea>
+                                                        </td>
+                                                    </c:if>
+                                                    <c:if test="${content.answerContent ne ''}">
+                                                        <td colspan="3" style="white-space: pre-line;"><div style="min-height:100px;"><c:out value="${content.answerContent}" /></div></td>
+                                                    </c:if>
+                                                </tr>
+                                            </table>
+                                            
+                                            <c:if test="${content.answerId eq ''}">
+                                                <div class="row mt-3">
+                                                    <div class="col-12">
+                                                        <div class="text-right">
+                                                            <button type="button" onclick="answerConfirm()" class="btn btn-primary w100">답변</button>
+                                                        </div>
+                                                    </div>
+                                                </div>
+                                            </c:if>
+
+                                        </c:if>
+                                        
+                                        <table class="mt-3 table mobile-table">
+                                            <colgroup>
+                                                <col style="width:10%">
+                                                <col style="width:">
+                                            </colgroup>
+                                            
+                                            <tr>
+                                                <th>이전글 ▲</th>
+                                                <td>
+                                                    <c:if test="${prePostCnt eq 0}">
+                                                        이전 글이 없습니다.
+                                                    </c:if>
+                                                    <c:if test="${prePostCnt ne 0}">
+                                                        <a href="./content?postSeq=${prePost.prePostSeq}"><c:out value="${prePost.prePostTitle}" /></a>
+                                                    </c:if>
+                                                </td>
+                                            </tr>
+                                            <tr>
+                                                <th>다음글 ▼</th>
+                                                <td>
+                                                    <c:if test="${nextPostCnt eq 0}">
+                                                        다음 글이 없습니다.
+                                                    </c:if>
+                                                    <c:if test="${nextPostCnt ne 0}">
+                                                        <a href="./content?postSeq=${nextPost.nextPostSeq}"><c:out value="${nextPost.nextPostTitle}" /></a>
+                                                    </c:if>
+                                                </td>
+                                            </tr>
+                                        </table>
+                                        
+                                        <div class="row mt-3">
+                                            <div class="col-12">
+                                                <div class="text-right">
+                                                    <c:if test="${sesId eq content.createBy}">
+                                                        <button type="button" onclick="location.href='./edit?postSeq=${content.postSeq}';" class="btn btn-primary w100">수정</button>
+                                                        <button type="button" onclick="deleteConfirm();" class="btn btn-danger w100">삭제</button>
+                                                    </c:if>
+                                                    <button type="button" class="btn btn-outline-primary w100" onclick="goListPage();">목록</button>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </main>
+            <jsp:include page="${data._INCLUDE}/footer.jsp"></jsp:include>
+        </div>
+    </div>
+</body>
+</html>

+ 169 - 0
src/main/webapp/WEB-INF/jsp/qna/edit.jsp

@@ -0,0 +1,169 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+    pageEncoding="UTF-8"%>
+<jsp:include page="${data._INCLUDE}/header.jsp"></jsp:include>
+<script>
+$( function(){
+    $( "#sendForm" ).validate({
+        rules: {
+            title : {
+                maxlength : 100
+            },
+            content: {
+                maxlength : 4000
+            },
+        },
+        messages : {
+            title : {
+                required : "제목을 입력해주세요."
+            },
+            content : {
+                required : "내용을 입력해주세요."
+            }
+        },
+        onkeyup: function( element, event ) {
+            $( element ).valid();
+        },
+        onfocusout: function (element) {
+            $( element ).val( $.trim( $( element ).val() ) );
+            $( element ).valid();
+        },
+        submitHandler: function(form) {
+            form.submit();
+        }
+    });
+
+    var button = '';
+    var fileOrgName = '<c:out value="${item.fileOriginalName}" />';
+    button = '<input type="file" style="display: none;" id="file" name="file" onchange="checkFile(this);">';
+    if (fileOrgName == "") {
+        button = '<input type="file" id="file" name="file" onchange="checkFile(this);">';
+        button += '<button type="button" class="btn btn-danger" id="fileRemoveBtn" onclick="removeFile();">첨부파일 삭제</button>';
+    } else {
+        button += '<button type="button" class="btn btn-danger" id="fileRemoveBtn" onclick="removeFileNameTag();">첨부파일 삭제</button>';
+    }
+
+    $("#fileTd").append(button);
+})
+
+function checkFile(el){
+    // files 로 해당 파일 정보 얻기.
+    var file = el.files;
+
+    // file[0].size 는 파일 용량 정보입니다.
+    if(file[0].size > 1024 * 1024 * 10){
+        // 용량 초과시 경고후 해당 파일의 용량도 보여줌
+        alert('10MB 이하 파일만 등록할 수 있습니다.\n\n' + '현재파일 용량 : ' + (Math.round(file[0].size / 1024 / 1024 * 100) / 100) + 'MB');
+    } else {
+        // 체크를 통과했다면 종료.
+        return;
+    }
+
+    // 체크에 걸리면 선택된 내용 취소 처리를 해야함.
+    // 파일선택 폼의 내용은 스크립트로 컨트롤 할 수 없습니다.
+    // 그래서 그냥 새로 폼을 새로 써주는 방식으로 초기화 합니다.
+    // 이렇게 하면 간단 !?
+    el.outerHTML = el.outerHTML;
+}
+
+function removeFileNameTag() {
+    $("#fileName").css("display", "none");
+    $("#file").remove();
+    $("#fileTd").prepend('<input type="file" id="file" name="file" onchange="checkFile(this);">');
+    $("input[name=fileOriginalName]").val("");
+    document.getElementById("fileRemoveBtn").setAttribute("onClick", "removeFile()");
+}
+
+function removeFile() {
+    $("#file").val("");
+}
+</script>
+</head>
+<body>
+    <div class="wrapper">
+        <jsp:include page="${data._INCLUDE}/sidebar.jsp"></jsp:include>
+        
+        <div class="main">
+            <jsp:include page="${data._INCLUDE}/top.jsp"></jsp:include>
+
+            <main class="content">
+                <div class="container-fluid p-0">
+                    <div class="row">
+                        <div class="col-12 col-lg-6">
+                            <h1 class="h3 mb-3">의견 게시판</h1>
+                        </div>
+                        <div class="col-12 col-lg-6  text-right">
+                            <nav aria-label="breadcrumb">
+                                <ol class="breadcrumb">
+                                    <li class="breadcrumb-item"><a href="javscript:;">Home</a></li>
+                                    <li class="breadcrumb-item">의견 게시판 수정</li>
+                                </ol>
+                            </nav>
+                        </div>
+                    </div>
+                    <div class="row">
+                        <div class="col-12">
+                            <div class="card">
+                                <form id="sendForm" action="./edit/update" method="post" enctype="multipart/form-data">
+                                    <input type="hidden" name="createBy" value="${item.createBy}" >
+                                    <input type="hidden" name="postSeq" value="${item.postSeq}" >
+                                    <input type="hidden" name="fileName" value="${item.fileName}" >
+                                    <input type="hidden" name="fileOriginalName" value="${item.fileOriginalName}" >
+                                    <div class="card-body">
+                                        <table class="table mobile-table">
+                                            <colgroup>
+                                                <col style="width:20%">
+                                                <col style="width:80%">
+                                            </colgroup>
+                                            <tr>
+                                                <th><span class="fix">*</span>제목</th>
+                                                <td>
+                                                    <input type="text" name="title" class="form-control" value="${item.title}" placeholder="제목을 입력하세요" maxlength="80" required>
+                                                </td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <th><span class="fix">*</span>내용</th>
+                                                <td>
+                                                    <textarea  class="form-control" rows="10" cols="" name="content" placeholder="내용을 입력하세요" maxlength="1000" required><c:out value="${item.content}" /></textarea>
+                                                </td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <th>첨부파일</th>
+                                                <td id="fileTd">
+                                                    <c:if test="${item.fileOriginalName eq ''}">
+                                                        
+                                                    </c:if>
+                                                    <c:if test="${item.fileOriginalName ne ''}">
+                                                        <span id="fileName"><c:out value="${item.fileOriginalName}" /></span>
+                                                    </c:if>
+                                                    
+<!--                                                     <input type="file" style="display: none;" id="file" name="file" onchange="checkFile(this);"> -->
+                                                </td>
+                                            </tr>
+                                        </table>
+                                        
+                                        <div class="row mt-3">
+                                            <div class="col-12">
+                                                <div class="text-right">
+                                                    <button type="button" class="btn btn-outline-primary w100" onclick="history.back();">취소</button>
+                                                    <button type="submit" class="btn btn-primary w100">수정</button>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </main>
+
+            <jsp:include page="${data._INCLUDE}/footer.jsp"></jsp:include>
+        </div>
+    </div>
+</body>
+</html>

+ 157 - 0
src/main/webapp/WEB-INF/jsp/qna/new.jsp

@@ -0,0 +1,157 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
+<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+    pageEncoding="UTF-8"%>
+<jsp:include page="${data._INCLUDE}/header.jsp"></jsp:include>
+<script>
+$( function(){
+    $( "#sendForm" ).validate({
+        rules: {
+            title : {
+                maxlength : 100
+            },
+            content: {
+                maxlength : 4000
+            },
+        },
+        messages : {
+            title : {
+                required : "제목을 입력해주세요."
+            },
+            content : {
+                required : "내용을 입력해주세요."
+            }
+        },
+        onkeyup: function( element, event ) {
+            $( element ).valid();
+        },
+        onfocusout: function (element) {
+            $( element ).val( $.trim( $( element ).val() ) );
+            $( element ).valid();
+        },
+        submitHandler: function(form) {
+            form.submit();
+        }
+    });
+})
+
+function checkFile(el){
+    // files 로 해당 파일 정보 얻기.
+    var file = el.files;
+
+    // file[0].size 는 파일 용량 정보입니다.
+    if(file[0].size > 1024 * 1024 * 10){
+        // 용량 초과시 경고후 해당 파일의 용량도 보여줌
+        alert('10MB 이하 파일만 등록할 수 있습니다.\n\n' + '현재파일 용량 : ' + (Math.round(file[0].size / 1024 / 1024 * 100) / 100) + 'MB');
+    } else {
+        // 체크를 통과했다면 종료.
+        return;
+    }
+
+    // 체크에 걸리면 선택된 내용 취소 처리를 해야함.
+    // 파일선택 폼의 내용은 스크립트로 컨트롤 할 수 없습니다.
+    // 그래서 그냥 새로 폼을 새로 써주는 방식으로 초기화 합니다.
+    // 이렇게 하면 간단 !?
+    el.outerHTML = el.outerHTML;
+}
+
+function removeFile() {
+    $("#file").val("");
+    /* if ($.browser.msie) { 
+        // ie 일때 input[type=file] init. 
+        $("#file").replaceWith( $("#file").clone(true) ); 
+    } else {
+        // other browser 일때 input[type=file] init. 
+        
+    } */
+}
+</script>
+</head>
+<body>
+    <div class="wrapper">
+        <jsp:include page="${data._INCLUDE}/sidebar.jsp"></jsp:include>
+        
+        <div class="main">
+            <jsp:include page="${data._INCLUDE}/top.jsp"></jsp:include>
+
+            <main class="content">
+                <div class="container-fluid p-0">
+                    <div class="row">
+                        <div class="col-12 col-lg-6">
+                            <h1 class="h3 mb-3">의견게시판</h1>
+                        </div>
+                        <div class="col-12 col-lg-6  text-right">
+                            <nav aria-label="breadcrumb">
+                                <ol class="breadcrumb">
+                                    <li class="breadcrumb-item"><a href="javscript:;">Home</a></li>
+                                    <li class="breadcrumb-item">의견 작성</li>
+                                </ol>
+                            </nav>
+                        </div>
+                    </div>
+                    <div class="row">
+                        <div class="col-12">
+                            <div class="card">
+                                <form id="sendForm" action="./new/insert" method="post" enctype="multipart/form-data">
+                                    <div class="card-body">
+                                        <table class="table mobile-table">
+                                            <colgroup>
+                                                <col style="width:20%">
+                                                <col style="width:80%">
+                                            </colgroup>
+                                            <tr>
+                                                <th><span class="fix">*</span>제목</th>
+                                                <td>
+                                                    <input type="text" name="title" class="form-control" placeholder="제목을 입력하세요" maxlength="100" required>
+                                                </td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <th><span class="fix">*</span>내용</th>
+                                                <td>
+                                                    <textarea  class="form-control" rows="10" cols="" name="content" placeholder="내용을 입력하세요" maxlength="4000" required></textarea>
+                                                </td>
+                                            </tr>
+                                            
+                                            <tr>
+                                                <th>첨부파일</th>
+                                                <td>
+                                                    <input type="file" id="file" name="file" onchange="checkFile(this);">
+                                                    <button type="button" class="btn btn-danger" onclick="removeFile();">첨부파일 삭제</button>
+<!--                                                     <div class="form-row"> -->
+<!--                                                         <div class="col-6"> -->
+<!--                                                             <select class="custom-select  form-control" id="selectState" name="selectState"> -->
+<!--                                                                 <option value="nbTitle">제목</option> -->
+<!--                                                                 <option value="nbContent">내용</option> -->
+<!--                                                             </select> -->
+<!--                                                         </div> -->
+<!--                                                         <div class="col-6"> -->
+<%--                                                             <input type="text" class="form-control" name="sData" value="${searchTxt}" placeholder="검색어를 입력하세요."> --%>
+<!--                                                         </div> -->
+<!--                                                     </div> -->
+                                                </td>
+                                            </tr>
+                                        </table>
+                                        
+                                        <div class="row mt-3">
+                                            <div class="col-12">
+                                                <div class="text-right">
+                                                    <button type="button" class="btn btn-outline-primary w100" onclick="history.back();">취소</button>
+                                                    <button type="submit" class="btn btn-primary w100">등록</button>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </form>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </main>
+
+            <jsp:include page="${data._INCLUDE}/footer.jsp"></jsp:include>
+        </div>
+    </div>
+</body>
+</html>