node.js

NODE.JS 활용 (8)

이이태태영영 2024. 4. 9. 16:02

 

 

 

 

 

 

NODE.JS 이미지 구현, 수정 및 삭제

history.back() : 이전 페이지로 돌아가기

const service = require("../../service/board/board_service");
const common = require("../../service/ser_common");

const board_views = {
  list: async (req, res) => {
    const list = await service.boardRead.list();
    res.render("board/list", { list });
  },
  writeForm: (req, res) => {
    const session = req.session;
    const msg = common.sessionCheck(session);
    if (msg != 0) {
      return res.send(msg);
    }
    res.render("board/write_form", { username: session.username });
  },
  data: async (req, res) => {
    const data = await service.boardRead.data(req.params.num);
    const username = req.session.username;
    res.render("board/data", { data, username });
  },
  modifyForm: async (req, res) => {
    const data = await service.boardRead.data(req.params.writeNo);
    res.render("board/modify_form", { data });
  },
};
const board_process = {
  write: async (req, res) => {
    const msg = await service.boardInsert.write(
      req.body,
      req.file,
      req.fileValidation
    );
    res.send(msg);
  },
  delete: (req, res) => {
    console.log("aaaaaaaaaaaaaaaaaaaaaaaaa");
    //데이터베이스 삭제 성공시 file 삭제
    file_process.delete(req.params.imgName);
    service.boardUpdate.delete(req.params.writeNo);
    res.redirect("/board/list");
  },
  modify: async (req, res) => {
    const deleteFile = req.body.change_file_name;
    const message = await service.boardUpdate.modify(req.body, req.file);
    if (req.file != undefined && message.result == 1) {
      file_process.delete(deleteFile);
    }
    res.send(message.msg);
  },
};
const fs = require("fs");
const file_process = {
  delete: (imgName) => {
    if (imgName != "nan") {
      fs.unlinkSync(`./upload_file/${imgName}`);
    }
  },
  download: async (req, res) => {
    const filePath = `./upload_file/${req.params.imgName}`;
    res.download(filePath);
  },
};
module.exports = { board_views, board_process, file_process };
const dao = require("../../database/board/board_dao");
const common = require("../ser_common");

boardUpdate = {
  upHit: (num) => {
    dao.boardUpdate.upHit(num);
  },
  delete: (writeNo) => {
    dao.boardUpdate.delete(writeNo);
  },
  modify: async (body, file) => {
    if (file != undefined) {
      body.origin_file_name = file.originalname;
      body.change_file_name = file.filename;
    }
    console.log("body => ", body);
    const result = await dao.boardUpdate.modify(body);
    console.log("result => ", result);
    let msg, url;
    let message = {};
    message.result = result.rowsAffected;
    if (message.result == 1) {
      msg = "수정 되었습니다";
      url = `/board/data/${body.write_no}`;
    } else {
      msg = "문제 발생 !!!";
      url = `/board/modify_form/${body.write_no}`;
    }
    message.msg = common.getMessage(msg, url);
    return message;
  }
};
const boardRead = {
  list: async () => {
    let list = await dao.boardRead.list();
    list = common.timeModify(list.rows);
    return list;
  },
  data: async (num) => {
    boardUpdate.upHit(num);
    let data = await dao.boardRead.data(num);
    data = common.timeModify(data.rows);
    return data[0];
  },
};
const boardInsert = {
  write: async (body, file, fileValidation) => {
    let msg, url;
    if (fileValidation) {
      msg = fileValidation;
      url = "/board/write_form";
      return common.getMessage(msg, url);
    }
    console.log("file : ", file);
    if (file != undefined) {
      body.origin_file_name = file.originalname;
      body.change_file_name = file.filename;
    } else {
      body.origin_file_name = "nan";
      body.change_file_name = "nan";
    }
    console.log("body : ", body);
    const result = await dao.boardInsert.write(body);
    if (result.rowsAffected === 1) {
      msg = "등록되었습니다!!!";
      url = "/board/list";
    } else {
      msg = "문제 발생!!!";
      url = "/board/write_form";
    }
    return common.getMessage(msg, url);
  },
};
module.exports = { boardRead, boardInsert, boardUpdate };
const con = require("../common_dao");
const boardRead = {
  list: async () => {
    const sql = "select * from board";
    console.log("con : ", con);
    const list = (await con).execute(sql);
    return list;
  },
  data: async (num) => {
    const sql = `select * from board where write_no='${num}'`;
    const data = (await con).execute(sql);
    return data;
  },
};
const boardInsert = {
  write: async (body) => {
    const sql = `insert into board(write_no, id, title, content, origin_file_name,
        change_file_name) values(board_seq.nextval, :id, :title, :content, 
        :origin_file_name, :change_file_name)`;
    const result = await (await con).execute(sql, body);
    console.log("result : ", result);
    return result;
  },
};
boardUpdate = {
  upHit: async (num) => {
    const sql = `update board set hit = hit + 1 where write_no='${num}'`;
    (await con).execute(sql);
  },
  delete: async (writeNo) => {
    const sql = `delete from board where write_no=${writeNo}`;
    (await con).execute(sql);
  },
  modify: async (body) => {
    const sql = `update board set title=:title, content=:content, 
        origin_file_name=:origin_file_name, 
        change_file_name=:change_file_name where write_no=:write_no`;
    let result = 0;
    try {
      result = (await con).execute(sql, body)
    } catch (err) {
      console.log(err);
    }
    return result;
  },
};
module.exports = { boardRead, boardInsert, boardUpdate };

 

list.ejs

<%- include ("../default/header") %>
<div class="content wrap">
    <table border="1" style="width:100%;">
        <tr>
            <th>번호</th> <th>id</th> <th>제목</th> <th>날짜</th>
            <th>조회수</th> <th>원본 이미지이름</th> <th>변경 이미지이름</th>
        </tr>
        <% if( list.length == 0){ %>
            <tr>
                <th colspan="7">등록된 글이 없습니다</th>
            </tr>
        <%}else{
            list.forEach(data=>{%>
            <tr>
                <td><%=data.WRITE_NO%></td><td><%=data.ID%></td>
                <td><a href="/board/data/<%= data.WRITE_NO %>"><%=data.TITLE%></a></td><td><%=data.SAVE_DATE%></td>
                <td><%=data.HIT%></td><td><%=data.ORIGIN_FILE_NAME%></td>
                <td><%=data.CHANGE_FILE_NAME%></td>
            </tr>
            <%})
        }%>
        <tr>
            <td colspan="7" align="right">
                <a href="/board/write_form">글 작성</a>
            </td>
        </tr>
    </table>
</div>

 

data.ejs

<%- include ("../default/header") %>
<div class="content wrap">
    <div style="width:600px; margin: 0 auto;">
    <h3 style="text-align: center; margin-bottom: 10px;"> - 개 인 정 보 - </h3>
    <table border="1" align="center">
        <tr>
            <th width="100">글 번호</th> <td width="200"><%= data.WRITE_NO %></td> 
            <th width="100">작성자</th>  <td width="200"><%= data.ID %></td>
        </tr>
        <tr>
            <th>제목</th> <td><%= data.TITLE %></td> 
            <th>등록일자</th> <td><%= data.SAVE_DATE %></td>
        </tr>
        <tr>
            <th>내용</th><td><%= data.CONTENT %></td> 
            <td colspan="2">
                <% if( data.ORIGIN_FILE_NAME === "nan"){%>
                    <b>이미지가 없습니다
                <%}else{%>
                    <b>이미지 : <%=data.ORIGIN_FILE_NAME%> </b>
                    <br>
                    <img src="/board/download/<%= data.CHANGE_FILE_NAME %>" width="100px" height="100px">
                <%}%>
            </td>
        </tr>
        <tr>
            <td colspan="4" align="center">
                <%if(username === data.ID){%>
                    <input type="button" onclick="location.href=
                    '/board/modify_form/<%= data.WRITE_NO %>'" value="수정하기"> 
                    <input type="button" onclick="location.href=
                    '/board/delete/<%=data.WRITE_NO%>/<%=data.CHANGE_FILE_NAME%>'"
                    value="삭제하기">
                <%}%>
                <input type="button" onclick="" value="답글달기"> 
                <input type="button" onclick="" value="리스트로 돌아가기">
            </td>
        </tr>
        </table>
    </div>
</div>

modify_form.ejs

<%- include ("../default/header") %>
<script src="/static/js/image_read.js"></script>
<div class="content wrap">
<div style="width:300px; margin: 0 auto;">
    <form action="/board/modify" enctype="multipart/form-data" method="post" >
        <input type="hidden" name="write_no" value="<%=data.WRITE_NO%>">
        <input type="hidden" name="change_file_name" value="<%=data.CHANGE_FILE_NAME%>">
        <input type="hidden" name="origin_file_name" value="<%=data.ORIGIN_FILE_NAME%>">
        제목  <input type="text" size="30" name="title" value="<%=data.TITLE%>"><hr>
        내용  <textarea rows="5" cols="30" name="content"><%=data.CONTENT%></textarea>
        <hr>
        <img width="200px" height="100px" id="img"
                        src="/board/download/<%=data.CHANGE_FILE_NAME%>">
        <input type="file" name="image_file_name" onchange="readURL(this)">
        <hr>
        <input type="submit" value="수정하기">
        <input type="button" onclick="history.back()" value="이전으로 돌아가기">
    </form>
</div>
</div>

 

실행 결과

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

NODE.JS 페이징 및 댓글 달기

 

 

reply.css 작성

#modal_wrap{
    display: none; position: fixed; z-index: 9;
    margin: 0 auto; top:0; left: 0; right: 0;
    width:100%; height:100%;
    background-color: rgba(0, 0, 0, 0.4);
}
#first{ 
    position: fixed; z-index: 10; margin: 0 auto;
    top:30px; left: 0; right: 0; display:none;
    background-color: rgba(212, 244, 250, 0.9);
    height:350px; width:300px;
}

reply.css 코드

 

reply.js 작성

function reply_form(){
    $("#first").slideDown('slow'); 
    $("#modal_wrap").show();
}
function reply_hide(){
    $("#first").slideUp('fast'); 
    $("#modal_wrap").hide();
}
function rep(){
    let form={}; 
    let arr = $("#frm").serializeArray();
    arr.forEach( d => { form[d.name] = d.value; })
    fetch("/boardrep/register", {
        method : "post",
        headers : {"Content-Type" : "application/json"},
        body : JSON.stringify( form )
    })
    .then(res => res.json() )
    .then( result => {
        if(result === 1)
            alert("답글이 달렸습니다!!")
        reply_hide();
    })
}

reply.js 코드

 

reply_form.ejs 작성

<link href="/static/css/reply.css" rel="stylesheet" >
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="/static/js/reply.js"></script>
<div id="modal_wrap">
    <div id="first">
        <div style="width:250px;margin: 0 auto;padding-top: 20px;">
            <form id="frm">
                <input type="hidden" name="write_no" value="<%= data.WRITE_NO %>">
                <input type="hidden" name="id" value="<%= username %>">
                <b>답글 작성 페이지</b> <hr>
                <b>작성자 : <%= username %></b> <hr>
                <b>제목</b><br><input type="text" size="30" name="title"><hr>
                <b>내용</b><br>
                <textarea name="content" rows="5" cols="30"></textarea>
                <hr>
                <button type="button" onclick="rep()">답글</button>
                <button type="button" onclick="reply_hide()">취소</button>
            </form>
        </div>
    </div>
</div>

reply_form.ejs 코드

 

data.ejs 위에 작성

 

data.ejs 에 추가 작성 ( 이 작업은 댓글 창을 따로 띄우는 것이 아닌 페이지 내에 띄우는 작업, 댓글 창 스타일에 따라 작성 )

 

답글 달기 버튼을 눌렀을때 텍스트 박스와 답변 버튼이 조그맣게 생기는 부분이 data.ejs 하단에 script 와 button, div, form 태그 추가한 부분

 

댓글을 달때 fetch 를 통해 넘어오는 json 형태의 데이터를 받기 위해 app.js 에 json 형태를 받을 수 있게 추가

 

기본 router.js 에서 답글 기능에 대한 라우터를 board_reply_router.js 에 위임

 

board_reply_router.js 에 경로 작성

 

board_reply_ctrl.js 에 로직 작성

 

board_reply_service.js 작성

 

board_reply_dao.js 작성

 

reply_view.js 작성

function init( groupNum ){
        fetch(`/boardrep/replyData/`+groupNum )
        .then( res => res.json() )
        .then( data => {
            let html = ""
            data.forEach((d)=>{
                html += "<div align='left'><b>아이디 : </b>"+d.ID+"님 / ";
                html += "<b>작성일</b> : "+d.SAVE_DATE+"<br>"
                html += "<b>제목</b> : "+d.TITLE+"<br>"
                html += "<b>내용</b> : "+d.CONTENT+"<hr></div>"
            });
            const content = document.getElementById("content");
            content.innerHTML = html;
        });
    }

reply_view.js 코드

 

data.ejs 에 내용 추가 ( td 추가한 부분은 댓글 부분 )

 

header.ejs 에 작성 ( header.ejs 가 onload 로 기본으로 실행될 때 init 함수가 실행되게 함

 

board_reply_router.js 작성

 

board_reply_ctrl.js 작성

 

board_reply_service.js 작성 ( 시간을 설정하기 위해 ser_common 의 기능을 호출하여 사용함 )

 

board_reply_dao.js 작성

 

 

 

현재는 답글 달면 새로고침 하기 전에 보이지 않는데 바로 댓글 입력한 데이터를 바로 출력하게끔 입력 받은 값을 덧붙여서 출력 ( 새로 고침을 하게 되면 DB 에서 끌고온 데이터가 출력되며, 이 방법은 일시적으로 데이터를 출력할 뿐 )

 

댓글을 바로 데이터로 덧붙여서 보여주게끔 설정, 위 코드는 일시적으로 댓글을 달면 자신이 단 댓글을 보여줄 뿐이며 실제 DB 에 적용된 데이터는 새로고침을 하면 출력되게 된다

 

실행 결과