수업/프로젝트

220406~14 세미

jumphare 2022. 4. 14. 23:26

0406

글 작성 -> 파일명 안 넘어가는 오류 해결
목록 -> 공지, 게시글 따로 분리해 출력 완료
글 내용 -> 내용 출력+첨부파일+다운로드 완료
글 수정 -> 첨부파일 변경시 기존파일 삭제까지 완료
글 삭제 -> 첨부파일 삭제까지 완료

내일 할 일: 답글 달기, 답글달린 글 삭제했을 때 리스트에 출력 어떻게 할지 + (가능하다면)권한 별로 컬럼, 버튼 숨기기


경로가 왜 계속 바뀌는지... 진짜 돌아버릴것같애
--> 해결한듯함.
내 문제는 자꾸 경로 사이에 저장된 디렉토리가 끼었다 안 끼었다 하는 문제였는데
경로대로 쫓아가보니 git 저장하는 과정에서 예전 프로젝트 이름으로 된 빈 디렉토리가 남아있었고 그 안에 프로젝트를 풀어버려서 사이에 이상한 경로가 하나 더 낀 것이었음
싹 삭제하고 다시 clone으로 받아와 실행하니 원래대로 경로가 출력됨을 확인함

 

0407
다른 조원들 거 pull로 땡겨와서 내 코드 수정하는 데에 한세월 보내고
답글기능 완료
목록에 체크박스 숨김처리 완료
본문에 계정 별로 버튼 다르게 출력시키는거 완료

 

-----0408 목표
관리자: 리스트에서 글 다중 삭제 (체크박스) 기능
글 검색기능
++ 더 시간이 된다면 댓글 기능을 한번 알아보자


0408

다중 선택 -> 삭제 sql
파일 다중 삭제 dao 따로 돌리기
select로 string[] mb_num 값 돌려서

 

체크박스 코드

목록에 삭제 표시
<form action="<%=request.getContextPath() %>/member_board_multidel.do" method="post" name="form1" id="form1">

<c:if test="${sessionScope.member_grade==1 }">
<td colspan=4 align="right" style="border-top:0;"><input type="submit" class="btn btn-outline-secondary btn-sm"  value="삭제"></td>
</c:if>
<!-- 삭제는 관리자가 들어갈 때만 보이게 설정... checked 위에. -->
</tr>
</table>
전체 체크박스
<c:if test="${sessionScope.member_grade==1 }">
<th width="50" ><input type="checkbox" id="allchk" name="allchk" ></th> <!-- 전체 체크 -->
</c:if>
<!-- 관리자가 들어갈 때만 컬럼이 보이게 설정 -->
각 글마다 체크박스
<c:if test="${sessionScope.member_grade==1 }">
<td align=center> <input type="checkbox" name="chk" value="${b.mb_Num }"> </td>   
</c:if>
script.js

$(document).ready(function(){

//체크박스 유효성
$("form[name='form1']").submit(function(){
if($("input:checkbox[name=chk]:checked").length < 1){
alert("삭제할 글을 체크해주세요");
return false;
}
if($("input:checkbox[name=chk]:checked").length >=1){
var del=confirm("삭제하시겠습니까?");     // 확인/취소 메시지 뜨게
if(del) document.form.submit();    //확인 누르면 서브밋
else return false;
}
});  
//#allchk 클릭 시 전체 체크박스 체크/해제 기능
$("#allchk").click(function(){
   if($("#allchk").is(":checked")) $("input[name=chk]").prop("checked", true);
   else $("input[name=chk]").prop("checked", false);
});
});

});
multidel.java
String[] mb_num=request.getParameterValues("chk"); //체크된 글번호 저장
String path = request.getRealPath("mb_upload");  //본문에 파일 있을 경우 파일들 저장되는 경로
int result=dao.multidel(mb_num, path);  //dao로~
dao

//파일 먼저 삭제
String sql="select mb_file from member_board where mb_num=?";

for(int i=0; i<mb_num.length; i++) {
   pstmt=con.prepareStatement(sql);
   pstmt.setString(1, mb_num[i]);
   rs=pstmt.executeQuery();

   if(rs.next()) { //첨부파일이 있다면
      File file=new File(path);
      File[] f= file.listFiles(); 
      for(int j=0; j<f.length; j++) {
         if(f[j].getName().equals(rs.getString("mb_file"))) {
            f[j].delete(); //파일 삭제
         }
      }
   }
}
pstmt.close();

//글 삭제
sql="delete from member_board where mb_num=?";
pstmt=con.prepareStatement(sql);

for(int i=0; i<mb_num.length; i++) {
   pstmt.setString(1, mb_num[i]);
   pstmt.addBatch();      //글번호 입력한 sql문을 쌓아두기
}
int[] cnt=pstmt.executeBatch();      //실행결과 배열로 저장

for(int i=0; i<cnt.length; i++) {
   if(cnt[i]==-2) {   //성공시 
   result++;   //하나씩 증가시킴
}

if(mb_num.length==result) con.commit();   //모두 성공하면 커밋
else con.rollback();     //문제 있으면 롤백 
결과

 

검색기능
//카운트를 하나로 묶어서 처리할 수 있으면 해야 함
//내생각엔... sel이랑 find값이 따로 주어지지 않으면 null로 들어가게 하고
//dao에서 if else문으로 분리해서 sql문을 두 개 만드는 게 좋을 것 같음


sql = "select * from ( select rownum rnum, no, ";
sql += "writer, passwd, subject, content  from ";

if(sell!=null){ //검색값이 있으면 있는 버전으로 쿼리 추가
sql += "(select * from testboard where "+sel+" like '%"+find+"%' order by no desc)) ";
} else { //없으면 없는 버전으로 쿼리 추가
sql += "(select * from testboard order by no desc)) ";
}

sql += "where rnum >= ? and rnum <= ?";

그리고 그냥 count>0이면 출력하게 넣는거야
어차피 list 뽑아온 시점에서 전체 또는 검색 둘 중 하나만 뽑혔으니까.


list.java
sel, find값을 받고 값이 존재하지 않는다면 전체 리스트 뽑기
값이 존재하면 검색해서 리스트 뽑기

listcount도 이미 만들어둔게 있으니, 값이 존재하는 경우로 위에랑 묶기

값 존재할 경우랑 존재하지 않는 경우를 if문으로 나눠서 각각 처리하는게 나을듯
그리고 각각 처리해서 나온 카운트값을 listcount로 넘기게 하고.
둘 중 하나만 처리될테니 그걸 board로 넣어서 request.setA를 하면 될 것 같고.

select * from ( select rownum rnum, board.* from
(select * from member_board where mb_subject  like '%1%' or mb_content like '%1%' order by mb_ref desc, mb_seq asc) board) 
where rnum >= 1;

 

검색의 경우 선생님이 수업을 해주신 걸 참고함

예제 파일을 확인해보니, 검색 옵션과 검색어가 존재하지 않을 때 (전체 목록 출력할 때) 받은 값이 null로 뜬다는 데에서 힌트를 얻음

서비스 클래스에서 조건마다 다른 dao를 호출하는 것보다 일단 dao를 실행하고 그 안에서 조건에 따라 다른 sql문을 저장해 실행시키는 게 좀 더 괜찮아보임

dao 만든거 하나 코드 여기 표 안에 넣어놓고

조건은 검색어가 없을 경우 ->전체 출력

검색어가 있는데 옵션이 제목/내용/글쓴이 -> 두번째 출력

검색어 있고 옵션이 제목+내용 -> 세번째 출력

 

이렇게 할 경우 sql문만 조건에 따라 바꿔주면 되고 실행은 조건문 밖에서 시키면 되니, 나름 효율적이지 않나..? 싶음...? 

 

검색 시 체크박스 유효성 검사가 자꾸 실행되고 submit으로 값 넘길 시 multidel로 넘어가는 현상

내가 js 파일을 만져보다 else로 return false를 추가했었는데 이게 원인이 아닌가 싶음

 

한 페이지에 폼 여러개를 둘 때 해결 방법 -> form[name='form_name'] 으로 유효성 검사를 한정시키면 된다

주의할 점: 하나의 폼 안에 submit 버튼이 두 개 존재하면 안 됨. 각각 다른 폼으로 만들어야 함!

-----------까지 0408에 했음

검색폼
<form name="form2" id="form2" action="<%=request.getContextPath() %>/member_board_list.do" method="post" >
<div class="container text-center d-flex align-items-center" style="font-family: 'Nanum Gothic', sans-serif; width:30%">
<select name="sel" class="form-control form-control-sm text-center" id="sel1" style="width:40%">
   <option value="all">제목+내용</option>
   <option value="id">작성자</option>
   <option value="mb_subject">제목</option>
   <option value="mb_content">내용</option>
</select>
<input type=text  name="find" id="find"  class="form-control form-control-sm" aria-label="Search" >
<button type="submit"  class="btn btn-primary  btn-sm flex-shrink-0" id="searchBtn" style="width:20%">검색</button>
</div>
</form>
script.js
//검색
$("form[name='form2']").submit(function(){
   if($("#find").val()==""){
      alert("검색어를 입력하세요");
      $("#find").focus();
      return false;
   } 
});
list.java
List<member_board_dto> mb_list=new ArrayList<member_board_dto>(); //목록
mb_list=dao.getMBList(startRow, endRow, sel, find); //리스트 출력
DAO

if(sel==null && find==null) {  //전체 목록 (검색X)
   sql="select * from (select rownum rnum, board.* from ";
   sql+=" (select *from member_board order by mb_ref desc, mb_seq asc) board) ";
   sql+=" where rnum>=? and rnum<=?";
else if(!sel.equals("all")){ //제목+내용 제외
   sql = "select * from ( select rownum rnum, board.* from ";
   sql += "(select * from member_board where "+sel+" like '%"+find+"%' order by mb_ref desc, mb_seq asc) board) ";
   sql += "where rnum >= ? and rnum <= ?";
else { //제목+내용
   sql = "select * from ( select rownum rnum, board.* from ";
   sql += "(select * from member_board where mb_subject  like '%"+find+"%' or mb_content like '%"+find+"%' order by mb_ref desc, mb_seq asc) board)  ";
   sql += "where rnum >= ? and rnum <= ?";
}
결과

----0411 할 것
메인 레이아웃 만들고 액션태그로 각 jsp파일 가져와서 누덕누덕 붙여보기.. 실행만 되면 된다
book 테이블에서 등록일순 정렬해서 rnum=1,2,3 하나씩 가져와서 메인에 보이게 해보기?
검색 부분은 도서검색부분 해결하시면 그 경로로 붙이면 될듯
카로셀은... 머 여기까진 생각하지 말자
아무튼 프론트 레이아웃은 대충 내 생각 비슷한걸 찾았으니 이런 느낌으로 만들어보겠다? 얘기하면 댈듯?

 

프론트는 세세하게 게시판 규격 맞춰 수정

 

배포 시 이미지 엑박 뜨는 문제 

 

0411

관리자: 미반납 리스트 -> 반납일 기준으로 asc
회원 : 대출 내역 -> 반납 처리 ->  rent테이블에서 삭제된 후 location.href=으로 대출 내역 다시 들어가기

책 상세 페이지에서, 로그인한 상태로 대여 -> book_Num, id 가져옴
rent_Num -> primary key 받고 sysdate, sysdate+14일것이고

미반납 리스트 -> 포린키로 book테이블 num 값 받았으니까 이 두 테이블을 조인해서 전체 출력
---> 받는 값은 어차피 book_dto rent_dto를 둘다 써야한단말이야 그럼 리턴을 list로 받을때 데이터형을 한정시키지 말자고
rent_dto rent=new rent_dto();
book_dto book=net boo_dto();
만들어놓고 둘 다 받아서 리스트에 집어넣고 뺄 때 foreach문에서... 변수가 다 다르니까? 변수만 다르게 해서 빼보면 될듯?
---해결---> 선생님한테 여쭤보니까 그냥.. 임의로 그 컬럼값을 rent_dto에 추가시키면 된다고 하셔서, book 테이블 값 일부의 변수를 추가시킨 후 list에 저장하는 방식을 사용함

rentlist -> rent_dao    adminRentList
select * from (select rownum rnum, list.* from (select rent.rent_num, rent.id, rent.book_num, book.book_name, book.writer, book.publisher, rent.rent_date, rent.return_date from rent, book where rent.book_num=book.book_num order by rent.return_date asc) list ) where rnum>=? and rnum<=?;

rentcount -> rent_dao    getCount
select count(*) from rent;

위 sql문으로 리스트랑 글 갯수 구했고 출력 무난하게 시켰음 + 한 페이지 당 20개씩 뜨게 페이징 처리 완.


반납 처리는 회원 대출 내역 다른 조원님이 한걸 받아서 반납 신청에 서블릿 연결함

delete 처리 후 return값을 request 영역으로 넘겨서, alert으로 반납처리 되었습니다 뜨는 jsp 파일로 forward 이동시키고 (returnalert.jap) 그 jsp에서 location.href로 list로 이동~

<c:if test="${result == 1 }">
<script>
alert("반납되었습니다");
    location.href="./rentListAction.do";
</script>
</c:if> 

rejected non fast forward 오류 -> 그냥 다 삭제시키고 다시 클론함... 이게 나한텐 제일 편해..


+++ 관리자 -> 회원 상세페이지 -> 대출내역 추가
기존 id값으로 상세내역 받아서 list에 저장 후 request 영역으로 넘겨서 foreach로 뿌리면 됨

 

0412

color: rgba(33, 37, 41, 0.8);

<td colspan=10 align="left" style="border-top:0;"> <c:if test="${not empty find}">[${find }] 검색 결과</c:if>  총 ${listcount} </td>
<c:if test="${not empty sessionScope.id }">
<td colspan=7 align="right" style="border-top:0;"><input type="button" class="btn btn-outline-secondary btn-sm" value="   작성   " onClick="location.href='./member_board_writeform.do'"></td> 
</c:if>

background-color: #3b4147;
 background-color: rgba(59, 65, 71, 0.7);

#212529

#F8E1C2

text-shadow: -1px 0 #000, 0 1px #000, 1px 0 #000, 0 -1px #000;

#6f42c1

#ffc800;

 

 

0414

프론트는 세세하게 게시판 규격 맞춰 수정

관리자 메뉴바 만들어 적용

배포 시 이미지 엑박 뜨는 문제 -> outputstream 사용 (써놓고도 이해가 잘... 선생님한테 나중에 물어볼 것)

 

0415~18

게시판 규격 통일시키고 세세한 오류 수정 예정