Merge branch 'main' into yoon

This commit is contained in:
yoon 2025-01-21 20:46:40 +09:00
commit b44906ad54
10 changed files with 448 additions and 219 deletions

View File

@ -18,27 +18,26 @@ package io.company.localhost.controller.api;
import java.math.BigInteger; import java.math.BigInteger;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.sql.Blob; import java.sql.Blob;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID;
import org.springframework.http.ResponseEntity; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.PageInfo; import com.github.pagehelper.PageInfo;
import com.github.pagehelper.PageSerializable; import com.github.pagehelper.PageSerializable;
import io.company.localhost.common.annotation.Member;
import io.company.localhost.common.annotation.ParameterCheck;
import io.company.localhost.common.annotation.ReqMap; import io.company.localhost.common.annotation.ReqMap;
import io.company.localhost.common.dto.ApiResponse; import io.company.localhost.common.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto; import io.company.localhost.common.dto.MapDto;
@ -52,12 +51,15 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class BoardController { public class BoardController {
private final localbordService boardService; private final localbordService boardService;
private final PasswordEncoder passwordEncoder;
/** /**
* 공지사항 목록 조회 * 공지사항 목록 조회
* @ReqMap map 요청 파라미터 (searchKeyword) * @ReqMap map 요청 파라미터 (searchKeyword)
* @return 페이징된 공지사항 목록 * @return 전체 공지사항 목록
*/ */
@Member
@ParameterCheck
@GetMapping("/notices") @GetMapping("/notices")
public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) { public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) {
List<MapDto> posts = boardService.getNotices(map); List<MapDto> posts = boardService.getNotices(map);
@ -69,6 +71,12 @@ public class BoardController {
Blob blob = (Blob) content; Blob blob = (Blob) content;
post.put("content", safeBlobToString(blob)); post.put("content", safeBlobToString(blob));
} }
// "id" 값을 Number로 받고 longValue() 변환
Object idObject = post.get("id");
long postId = ((Number) idObject).longValue();
post.put("hasAttachment", boardService.hasAttachments(postId));
} }
return ApiResponse.ok(posts); return ApiResponse.ok(posts);
@ -76,9 +84,11 @@ public class BoardController {
/** /**
* 자유/익명 게시판 목록 조회 * 자유/익명 게시판 목록 조회
* @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함) * @ReqMap map 요청 파라미터 (page, searchKeyword, orderBy)
* @return 페이징된 자유/익명 게시판 목록 * @return 페이징된 자유/익명 게시판 목록
*/ */
@Member
@ParameterCheck
@GetMapping("/general") @GetMapping("/general")
public ApiResponse<PageInfo<MapDto>> getGeneralPosts(@ReqMap MapDto map) { public ApiResponse<PageInfo<MapDto>> getGeneralPosts(@ReqMap MapDto map) {
PageInfo<MapDto> posts = boardService.getGeneralPosts(map); PageInfo<MapDto> posts = boardService.getGeneralPosts(map);
@ -90,6 +100,19 @@ public class BoardController {
Blob blob = (Blob) content; Blob blob = (Blob) content;
post.put("content", safeBlobToString(blob)); post.put("content", safeBlobToString(blob));
} }
// "id" 값을 Number로 받고 longValue() 변환
Object idObject = post.get("id");
if (idObject instanceof Number) {
long postId = ((Number) idObject).longValue();
post.put("commentCount", boardService.getCommentCount(postId));
post.put("hasAttachment", boardService.hasAttachments(postId));
MapDto reactions = boardService.getBoardReactions(postId);
post.put("likeCount", reactions.getOrDefault("likeCount", 0));
post.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
} else {
post.put("commentCount", 0); // id가 없거나 잘못된 경우 기본값 설정
}
} }
return ApiResponse.ok(posts); return ApiResponse.ok(posts);
@ -121,56 +144,55 @@ public class BoardController {
/** /**
* 게시물 작성 * 게시물 작성
* @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함) * @ReqMap map 요청 파라미터 (LOCBRDTTL, LOCBRDCON, MEMBERSEQ, LOCBRDTYP,
* LOCBRDPWD(익명일떄에만), LOCBRDCAT(지식커뮤니티만))
* @return 작성된 게시물의 ID * @return 작성된 게시물의 ID
*/ */
@Member
@ParameterCheck
@PostMapping @PostMapping
public ApiResponse<?> createBoard(@ReqMap MapDto map) { public ApiResponse<?> createBoard(@ReqMap MapDto map) {
// 비밀번호 암호화
if (map.containsKey("LOCBRDPWD")) {
String rawPassword = map.getString("LOCBRDPWD");
String encodedPassword = passwordEncoder.encode(rawPassword);
map.put("LOCBRDPWD", encodedPassword);
}
// LOCBRDCON 필드를 JSON 문자열로 변환
ObjectMapper objectMapper = new ObjectMapper();
if (map.containsKey("LOCBRDCON")) {
try {
String jsonContent = objectMapper.writeValueAsString(map.get("LOCBRDCON"));
map.put("LOCBRDCON", jsonContent); // JSON 문자열로 변환된 설정
} catch (Exception e) {
throw new RuntimeException("Error serializing LOCBRDCON field", e);
}
}
//로그인 미개발 ->임시
map.put("MEMBERSEQ", 1);
BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환 BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환
Map<String, Object> responseData = new HashMap<>(); Map<String, Object> responseData = new HashMap<>();
responseData.put("boardId", createdIdx); responseData.put("CMNBRDSEQ", createdIdx);
responseData.put("message", "게시물이 작성되었습니다."); responseData.put("message", "게시물이 작성되었습니다.");
return ApiResponse.ok(responseData); return ApiResponse.ok(responseData);
} }
/** /**
* 첨부파일 추가 * 첨부파일 추가
* @param boardId 게시물 ID * @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ)
* @param file 업로드된 파일
* @param filePath 파일 저장 경로
* @param originalFileName 원본 파일명
* @param fileExtension 파일 확장자
* @param fileSize 파일 크기
* @param registrantId 등록자 ID
* @param fileName 저장될 파일명
* @return 첨부파일 저장 결과 메시지 * @return 첨부파일 저장 결과 메시지
*/ */
@PostMapping("/{boardId}/attachments") @Member
public ApiResponse<String> uploadAttachment( @ParameterCheck
@PathVariable("boardId") Long boardId, @PostMapping("/{CMNBRDSEQ}/attachments")
@RequestParam("file") MultipartFile file, public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) {
@RequestParam("CMNFLEPAT") String filePath, String filename = UUID.randomUUID().toString();
@RequestParam("CMNFLEORG") String originalFileName, map.put("CMNFLENAM", filename);
@RequestParam("CMNFLEEXT") String fileExtension, map.put("CMNFLEREG", 1);
@RequestParam("CMNFLESIZ") Long fileSize,
@RequestParam("CMNFLEREG") Long registrantId,
@RequestParam("CMNFLENAM") String fileName
) {
// 데이터 준비
MapDto fileData = new MapDto();
fileData.put("CMNBRDSEQ", boardId);
fileData.put("CMNFLENAM", fileName); // 업로드된 파일 이름
fileData.put("CMNFLEORG", originalFileName);
fileData.put("CMNFLEPAT", filePath);
fileData.put("CMNFLEEXT", fileExtension);
fileData.put("CMNFLESIZ", fileSize);
fileData.put("CMNFLEREG", registrantId);
fileData.put("CMNFLERDT", new Date()); // 등록일 현재 시간
log.info("Uploading attachment for board ID: {}", boardId);
// 파일 데이터 저장 // 파일 데이터 저장
boardService.addAttachment(fileData); boardService.addAttachment(map);
return ApiResponse.ok("첨부파일이 저장되었습니다."); return ApiResponse.ok("첨부파일이 저장되었습니다.");
} }
@ -180,10 +202,15 @@ public class BoardController {
* @param boardId 게시물 ID * @param boardId 게시물 ID
* @return 게시물 상세정보, 첨부파일 목록, 댓글 목록 * @return 게시물 상세정보, 첨부파일 목록, 댓글 목록
*/ */
@Member
@ParameterCheck
@GetMapping("/{boardId}") @GetMapping("/{boardId}")
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) { public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
log.info("Fetching details for board ID: {}", boardId); log.info("Fetching details for board ID: {}", boardId);
// 조회수 증가
boardService.incrementViewCount(boardId);
// 게시물 상세정보 조회 // 게시물 상세정보 조회
MapDto boardDetail = boardService.getBoardDetail(boardId); MapDto boardDetail = boardService.getBoardDetail(boardId);
if (boardDetail == null) { if (boardDetail == null) {
@ -201,15 +228,31 @@ public class BoardController {
} }
} }
// 첨부파일 댓글 조회 MapDto reactions = boardService.getBoardReactions(boardId);
boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0));
boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
List<MapDto> attachments = boardService.getAttachments(boardId); List<MapDto> attachments = boardService.getAttachments(boardId);
List<MapDto> comments = boardService.getComments(boardId.intValue()); List<MapDto> comments = boardService.getComments(boardId.intValue());
List<MapDto> commentReactions = boardService.getCommentReactions(boardId);
for (MapDto comment : comments) {
Integer commentId = (Integer) comment.get("LOCCMTSEQ");
for (MapDto reaction : commentReactions) {
if (reaction.get("LOCCMTSEQ").equals(commentId)) {
comment.put("likeCount", reaction.getOrDefault("likeCount", 0));
comment.put("dislikeCount", reaction.getOrDefault("dislikeCount", 0));
}
}
}
// 결과 조합 // 결과 조합
MapDto result = new MapDto(); MapDto result = new MapDto();
result.put("boardDetail", boardDetail); result.put("boardDetail", boardDetail);
result.put("attachments", attachments); result.put("attachments", attachments);
result.put("comments", comments); result.put("comments", comments);
result.put("commentCount", boardService.getCommentCount(boardId));
result.put("hasAttachment", boardService.hasAttachments(boardId));
return ApiResponse.ok(result); return ApiResponse.ok(result);
} }
@ -219,6 +262,8 @@ public class BoardController {
* @param boardId 게시물 ID * @param boardId 게시물 ID
* @return 삭제 결과 메시지 * @return 삭제 결과 메시지
*/ */
@Member
@ParameterCheck
@DeleteMapping("/{boardId}") @DeleteMapping("/{boardId}")
public ApiResponse<String> deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { public ApiResponse<String> deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); map.put("LOCBRDSEQ", boardId);
@ -230,9 +275,11 @@ public class BoardController {
/** /**
* 게시물 수정 * 게시물 수정
* @param boardId 게시물 ID * @param boardId 게시물 ID
* @ReqMap map 수정 데이터 (제목, 내용 ) * @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON)
* @return 수정 결과 메시지 * @return 수정 결과 메시지
*/ */
@Member
@ParameterCheck
@PutMapping("/{boardId}") @PutMapping("/{boardId}")
public ApiResponse<String> updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) { public ApiResponse<String> updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); map.put("LOCBRDSEQ", boardId);
@ -241,72 +288,55 @@ public class BoardController {
} }
/** /**
* 게시물 좋아요/싫어요 추가 * 게시물,댓글 좋아요/싫어요 추가
* @param boardId 게시물 ID * @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ)
* @ReqMap map 좋아요/싫어요 데이터
* @return 반응 추가 결과 메시지 * @return 반응 추가 결과 메시지
*/ */
@PostMapping("/{boardId}/reaction") @Member
public ApiResponse<String> reactToBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) { @ParameterCheck
map.put("LOCBRDSEQ", boardId); @PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction")
public ApiResponse<String> reactToBoard(@ReqMap MapDto map) {
//로그인 미개발 ->임시
map.put("MEMBERSEQ", 1);
boardService.reactToBoard(map); boardService.reactToBoard(map);
return ApiResponse.ok("반응이 추가되었습니다."); return ApiResponse.ok("반응이 성공적으로 처리되었습니다.");
} }
/** /**
* 댓글/대댓글 조회 * 댓글/대댓글 조회
* @param boardId 게시물 ID * @param boardId 게시물 ID
* @return 댓글과 대댓글의 계층 구조 데이터 * @return 댓글과 대댓글의 계층 구조 데이터
*/ */
@Member
@ParameterCheck
@GetMapping("/{boardId}/comments") @GetMapping("/{boardId}/comments")
public ApiResponse<List<Map<String, Object>>> getComments(@PathVariable("boardId") int boardId) { public ApiResponse<List<MapDto>> getComments(@PathVariable("boardId") int boardId) {
// 모든 댓글과 대댓글 조회 // 모든 댓글과 대댓글 조회
List<MapDto> comments = boardService.getComments(boardId); List<MapDto> comments = boardService.getComments(boardId);
// 댓글과 대댓글을 계층 구조로 정렬 return ApiResponse.ok(comments);
Map<Integer, Map<String, Object>> commentMap = new HashMap<>();
for (MapDto comment : comments) {
int commentId = (int) comment.get("LOCCMTSEQ");
Integer parentId = (Integer) comment.get("LOCCMTRPY");
Map<String, Object> commentData = new HashMap<>(comment);
commentData.put("replies", new ArrayList<>()); // 대댓글 리스트 초기화
if (parentId == null) {
// 댓글인 경우
commentMap.put(commentId, commentData);
} else {
// 대댓글인 경우, 부모 댓글의 "replies" 추가
Map<String, Object> parentComment = commentMap.get(parentId);
if (parentComment != null) {
List<Map<String, Object>> replies = (List<Map<String, Object>>) parentComment.get("replies");
replies.add(commentData);
}
}
} }
// 최상위 댓글 리스트 반환
List<Map<String, Object>> result = new ArrayList<>(commentMap.values());
return ApiResponse.ok(result);
}
/** /**
* 댓글/대댓글 작성 * 댓글/대댓글 작성
* @param boardId 게시물 ID * @param boardId 게시물 ID
* @ReqMap map 댓글 데이터 (내용, 부모 ID ) * @ReqMap map 댓글 데이터 (LOCBRDSEQ, LOCCMTRPY, LOCCMTPNT, LOCCMTPWD, MEMBERSEQ )
* @return 작성 결과 메시지 * @return 작성 결과 메시지
*/ */
@PostMapping("/{boardId}/comment") @Member
public ApiResponse<String> addCommentOrReply(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { @ParameterCheck
map.put("LOCBRDSEQ", boardId); @PostMapping("/{LOCBRDSEQ}/comment")
public ApiResponse<String> addCommentOrReply(@ReqMap MapDto map) {
//로그인 미개발 ->임시
map.put("MEMBERSEQ", 1);
// 부모 댓글 확인 // 비밀번호 암호화 (비밀번호가 있는 경우에만)
Integer parentCommentId = (Integer) map.get("LOCCMTRPY"); if (map.containsKey("LOCCMTPWD")) {
if (parentCommentId != null) { String rawPassword = map.getString("LOCCMTPWD");
MapDto parentComment = boardService.getCommentById(parentCommentId); String encodedPassword = passwordEncoder.encode(rawPassword);
if (parentComment == null) { map.put("LOCCMTPWD", encodedPassword);
throw new IllegalArgumentException("Invalid parent comment ID: " + parentCommentId);
}
} }
boardService.addCommentOrReply(map); boardService.addCommentOrReply(map);
@ -316,9 +346,11 @@ public class BoardController {
/** /**
* 댓글/대댓글 수정 * 댓글/대댓글 수정
* @param commentId 댓글 ID * @param commentId 댓글 ID
* @ReqMap map 수정 데이터 (내용, 비밀번호 ) * @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY )
* @return 수정 결과 메시지 * @return 수정 결과 메시지
*/ */
@Member
@ParameterCheck
@PutMapping("/comment/{commentId}") @PutMapping("/comment/{commentId}")
public ApiResponse<String> updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { public ApiResponse<String> updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
// 기존 댓글 조회 // 기존 댓글 조회
@ -327,9 +359,6 @@ public class BoardController {
throw new IllegalArgumentException("Comment not found for ID: " + commentId); throw new IllegalArgumentException("Comment not found for ID: " + commentId);
} }
// 부모 댓글 ID는 수정 불가
map.remove("LOCCMTRPY");
map.put("LOCCMTSEQ", commentId); map.put("LOCCMTSEQ", commentId);
boardService.updateComment(map); boardService.updateComment(map);
@ -339,9 +368,10 @@ public class BoardController {
/** /**
* 댓글/대댓글 삭제 * 댓글/대댓글 삭제
* @param commentId 댓글 ID * @param commentId 댓글 ID
* @ReqMap map 요청 데이터 (비밀번호 )
* @return 삭제 결과 메시지 * @return 삭제 결과 메시지
*/ */
@Member
@ParameterCheck
@DeleteMapping("/comment/{commentId}") @DeleteMapping("/comment/{commentId}")
public ApiResponse<String> deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { public ApiResponse<String> deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId); map.put("LOCCMTSEQ", commentId);
@ -356,10 +386,17 @@ public class BoardController {
* @ReqMap map 비밀번호 데이터 * @ReqMap map 비밀번호 데이터
* @return 비밀번호 확인 결과 * @return 비밀번호 확인 결과
*/ */
@Member
@ParameterCheck
@PostMapping("/comment/{commentId}/password") @PostMapping("/comment/{commentId}/password")
public ApiResponse<Boolean> checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) { public ApiResponse<Boolean> checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId); // DB에서 암호화된 비밀번호 조회
return ApiResponse.ok(boardService.checkCommentPassword(map)); String storedPassword = boardService.getCommentPassword(commentId);
String rawPassword = map.getString("LOCCMTPWD");
// 비밀번호 검증
boolean isMatch = passwordEncoder.matches(rawPassword, storedPassword);
return ApiResponse.ok(isMatch);
} }
/** /**
@ -368,34 +405,17 @@ public class BoardController {
* @ReqMap map 비밀번호 데이터 * @ReqMap map 비밀번호 데이터
* @return 비밀번호 확인 결과 * @return 비밀번호 확인 결과
*/ */
@Member
@ParameterCheck
@PostMapping("/{boardId}/password") @PostMapping("/{boardId}/password")
public ApiResponse<Boolean> checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) { public ApiResponse<Boolean> checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId); // DB에서 암호화된 비밀번호 조회
return ApiResponse.ok(boardService.checkBoardPassword(map)); String storedPassword = boardService.getBoardPassword(boardId);
} String rawPassword = map.getString("LOCBRDPWD");
/** // 비밀번호 검증
* 비밀게시판 여부 확인 boolean isMatch = passwordEncoder.matches(rawPassword, storedPassword);
* @param boardId 게시물 ID return ApiResponse.ok(isMatch);
* @return 비밀게시판 여부
*/
@GetMapping("/{boardId}/isSecret")
public ApiResponse<Boolean> isSecretBoard(@PathVariable("boardId") Long boardId) {
log.info("Checking if board ID {} is secret", boardId);
return ApiResponse.ok(boardService.isSecretBoard(boardId));
}
/**
* 댓글 좋아요/싫어요 추가
* @param commentId 댓글 ID
* @ReqMap map 좋아요/싫어요 데이터
* @return 반응 추가 결과 메시지
*/
@PostMapping("/comment/{commentId}/reaction")
public ApiResponse<String> reactToComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId);
boardService.reactToComment(map);
return ApiResponse.ok("Comment reaction added.");
} }
} }

View File

@ -1,6 +1,7 @@
package io.company.localhost.controller.api; package io.company.localhost.controller.api;
import java.util.List; import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -45,4 +46,16 @@ public class VacationController {
// 성공적으로 저장된 경우 응답 반환 // 성공적으로 저장된 경우 응답 반환
return ApiResponse.ok("모든 휴가가 성공적으로 저장되었습니다."); return ApiResponse.ok("모든 휴가가 성공적으로 저장되었습니다.");
} }
/**
* 휴가 정보를 조회하여 프론트엔드로 전달
*/
@GetMapping("/list")
public ApiResponse<List<MapDto>> getVacationList() {
// 서비스 호출을 통해 데이터 조회
List<MapDto> vacationList = localVacaService.getVacationList();
return ApiResponse.ok(vacationList);
}
} }

View File

@ -21,11 +21,7 @@ import java.nio.file.Paths;
import java.util.UUID; import java.util.UUID;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
@ -39,7 +35,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
@RestController @RestController
@RequestMapping("/api/img") @RequestMapping("/api/quilleditor")
@RequiredArgsConstructor @RequiredArgsConstructor
public class ImageUploadController { public class ImageUploadController {
@ -47,8 +43,8 @@ public class ImageUploadController {
private String boardFilePath; private String boardFilePath;
/** /**
* 에디터 이미지 업로 * quilleditor 안에서 삽입된 이미지를 서버에 저장하는 메소
* @form-data file 업로드할 파일실제경로/파일이름 * @form-data 서버에 저장된 이미지 경로와 이름
* @return * @return
*/ */
@ParameterCheck @ParameterCheck

View File

@ -16,6 +16,9 @@ public interface localbordMapper {
// 자유/비밀 게시판 조회 // 자유/비밀 게시판 조회
List<MapDto> getGeneralPosts(MapDto map); List<MapDto> getGeneralPosts(MapDto map);
// 조회수 증가
void incrementViewCount(Long boardId);
// 게시물 작성 // 게시물 작성
void createBoard(MapDto map); void createBoard(MapDto map);
@ -25,11 +28,20 @@ public interface localbordMapper {
// 게시물 삭제 // 게시물 삭제
void deleteBoard(MapDto map); void deleteBoard(MapDto map);
// 게시물 삭제시 댓글/대댓글 삭제
void deleteCommentsByBoardId(MapDto map);
// 게시물 수정 // 게시물 수정
void updateBoard(MapDto map); void updateBoard(MapDto map);
// 게시물 좋아요/싫어요 추가 // 기존 반응 조회
void reactToBoard(MapDto map); MapDto findReaction(MapDto map);
// 반응 삽입
void insertReaction(MapDto map);
// 기존 반응 업데이트
void updateReaction(MapDto map);
// 댓글 조회 // 댓글 조회
List<MapDto> getComments(int boardSeq); List<MapDto> getComments(int boardSeq);
@ -40,28 +52,47 @@ public interface localbordMapper {
// 댓글/대댓글 수정 // 댓글/대댓글 수정
void updateComment(MapDto map); void updateComment(MapDto map);
// 댓글/대댓글 삭제 // 대댓글인지 확인
boolean isReply(MapDto map);
// 댓글에 대댓글이 있는지 확인
boolean hasReplies(MapDto map);
// 댓글 내용만 삭제 처리 (대댓글 유지)
void softDeleteComment(MapDto map);
// 댓글 삭제 (대댓글 없음)
void deleteComment(MapDto map); void deleteComment(MapDto map);
// 게시물 비밀번호 확인 // 대댓글 삭제
boolean checkBoardPassword(MapDto map); void deleteReply(MapDto map);
// 댓글 비밀번호 확인 // 게시물 비밀번호 조회
boolean checkCommentPassword(MapDto map); String selectCommentPassword(int commentId);
// 비밀 게시판 여부 확인 // 댓글 비밀번호 조회
boolean isSecretBoard(Long boardId); String selectBoardPassword(int boardId);
// 게시물 상세보기 // 게시물 상세보기
MapDto selectBoardDetail(Long boardId); MapDto selectBoardDetail(Long boardId);
// 댓글 갯수
int countComments(Long boardId);
// 첨부파일 유무
int countAttachments(Long boardId);
// 게시물 좋아요/싫어요 개수
MapDto getBoardReactions(Long boardId);
// 댓글 좋아요/싫어요 개수
List<MapDto> getCommentReactions(Long boardId);
// 첨부파일 가져오기 // 첨부파일 가져오기
List<MapDto> selectAttachments(Long boardId); List<MapDto> selectAttachments(Long boardId);
//댓글 좋아요/싫어요추가
void reactToComment(MapDto map);
//댓글id 확인 //댓글id 확인
MapDto getCommentById(int commentId); MapDto getCommentById(int commentId);
} }

View File

@ -1,13 +1,18 @@
package io.company.localhost.mapper; package io.company.localhost.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import io.company.localhost.common.dto.MapDto; import io.company.localhost.common.dto.MapDto;
@Mapper @Mapper
public interface localvacaMapper { public interface localvacaMapper {
void insertVacation(MapDto vacationRequest); void insertVacation(MapDto map);
List<MapDto> findVacations();
} }

View File

@ -26,12 +26,25 @@ public class localbordService {
public PageInfo<MapDto> getGeneralPosts(MapDto map) { public PageInfo<MapDto> getGeneralPosts(MapDto map) {
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1; int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10; int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10;
String orderBy = map.getString("orderBy");
if (orderBy == null || (!orderBy.equals("date") && !orderBy.equals("views"))) {
map.put("orderBy", "date");
}
PageHelper.startPage(page, size); PageHelper.startPage(page, size);
return PageUtil.redefineNavigation(new PageInfo<>(boardMapper.getGeneralPosts(map), size));
List<MapDto> result = boardMapper.getGeneralPosts(map);
return PageUtil.redefineNavigation(new PageInfo<>(result, size));
}
public void incrementViewCount(Long boardId) {
boardMapper.incrementViewCount(boardId);
} }
public BigInteger createBoard(MapDto map) { public BigInteger createBoard(MapDto map) {
boardMapper.createBoard(map); // 게시물 작성 boardMapper.createBoard(map);
return (BigInteger) map.get("LOCBRDSEQ"); // Mapper에서 자동 생성된 key를 가져옴 return (BigInteger) map.get("LOCBRDSEQ"); // Mapper에서 자동 생성된 key를 가져옴
} }
@ -47,8 +60,8 @@ public class localbordService {
return boardMapper.selectAttachments(boardId); return boardMapper.selectAttachments(boardId);
} }
public void deleteBoard(MapDto map) { public void deleteBoard(MapDto map) {
boardMapper.deleteCommentsByBoardId(map);
boardMapper.deleteBoard(map); boardMapper.deleteBoard(map);
} }
@ -57,7 +70,16 @@ public class localbordService {
} }
public void reactToBoard(MapDto map) { public void reactToBoard(MapDto map) {
boardMapper.reactToBoard(map); // 기존 반응 확인
MapDto existingReaction = boardMapper.findReaction(map);
if (existingReaction != null) {
// 기존 반응이 있는 경우 업데이트
boardMapper.updateReaction(map);
} else {
// 기존 반응이 없는 경우 새로 삽입
boardMapper.insertReaction(map);
}
} }
public List<MapDto> getComments(int boardSeq) { public List<MapDto> getComments(int boardSeq) {
@ -65,39 +87,65 @@ public class localbordService {
} }
public void addCommentOrReply(MapDto map) { public void addCommentOrReply(MapDto map) {
if (map.get("LOCCMTPNT") == null) {
map.put("LOCCMTPNT", null);
}
boardMapper.addCommentOrReply(map); boardMapper.addCommentOrReply(map);
} }
public void updateComment(MapDto map) { public void updateComment(MapDto map) {
boardMapper.updateComment(map); boardMapper.updateComment(map);
} }
public void deleteComment(MapDto map) { public void deleteComment(MapDto map) {
// 댓글인지 대댓글인지 확인
boolean isReply = boardMapper.isReply(map);
if (isReply) {
// 대댓글 삭제
boardMapper.deleteReply(map);
} else {
// 댓글인 경우
boolean hasReplies = boardMapper.hasReplies(map);
if (hasReplies) {
// 대댓글이 있는 경우 내용 업데이트
boardMapper.softDeleteComment(map);
} else {
// 대댓글이 없는 경우 댓글 삭제
boardMapper.deleteComment(map); boardMapper.deleteComment(map);
} }
}
public boolean checkBoardPassword(MapDto map) {
return boardMapper.checkBoardPassword(map);
} }
public boolean checkCommentPassword(MapDto map) { public String getCommentPassword(int commentId) {
return boardMapper.checkCommentPassword(map); return boardMapper.selectCommentPassword(commentId);
} }
public String getBoardPassword(int boardId) {
public boolean isSecretBoard(Long boardId) { return boardMapper.selectBoardPassword(boardId);
return boardMapper.isSecretBoard(boardId);
}
public void reactToComment(MapDto map) {
boardMapper.reactToComment(map);
} }
public MapDto getCommentById(int commentId) { public MapDto getCommentById(int commentId) {
return boardMapper.getCommentById(commentId); return boardMapper.getCommentById(commentId);
} }
public int getCommentCount(Long boardId) {
return boardMapper.countComments(boardId);
}
public boolean hasAttachments(Long boardId) {
int count = boardMapper.countAttachments(boardId);
return count > 0;
}
public MapDto getBoardReactions(Long boardId) {
return boardMapper.getBoardReactions(boardId);
}
public List<MapDto> getCommentReactions(Long boardId) {
return boardMapper.getCommentReactions(boardId);
}
} }

View File

@ -18,4 +18,8 @@ public class localvacaService {
localvacaMapper.insertVacation(vacationRequest); localvacaMapper.insertVacation(vacationRequest);
} }
public List<MapDto> getVacationList() {
return localvacaMapper.findVacations();
}
} }

View File

@ -58,6 +58,18 @@ public class PageUtil {
list.setNavigateLastPage(nav2[nav2.length -1]); list.setNavigateLastPage(nav2[nav2.length -1]);
} }
// 페이지 그룹 크기 (: 10개씩)
int groupSize = list.getNavigatePages();
int totalPages = list.getPages();
// 현재 페이지 그룹 계산
int currentGroup = (int) Math.ceil((double) currentPage / groupSize);
int totalGroups = (int) Math.ceil((double) totalPages / groupSize);
// 이전/다음 그룹 존재 여부 설정
list.setHasPreviousPage(currentGroup > 1); // 이전 그룹 존재
list.setHasNextPage(currentGroup < totalGroups); // 다음 그룹 존재
return list; return list;
} }
} }

View File

@ -8,13 +8,14 @@
LOCBRDSEQ AS id, LOCBRDSEQ AS id,
LOCBRDTTL AS title, LOCBRDTTL AS title,
LOCBRDCON AS content, LOCBRDCON AS content,
LOCBRDRDT AS date LOCBRDUDT AS date,
LOCBRDCNT AS cnt
FROM localbord FROM localbord
WHERE LOCBRDTYP = 'N' WHERE LOCBRDTYP = 'N'
<if test="searchKeyword != null and searchKeyword != ''"> <if test="searchKeyword != null and searchKeyword != ''">
AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%') AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
</if> </if>
ORDER BY LOCBRDRDT DESC ORDER BY LOCBRDUDT DESC
</select> </select>
<!-- 자유/익명 게시판 조회 --> <!-- 자유/익명 게시판 조회 -->
@ -23,15 +24,24 @@
LOCBRDSEQ AS id, LOCBRDSEQ AS id,
LOCBRDTTL AS title, LOCBRDTTL AS title,
LOCBRDCON AS content, LOCBRDCON AS content,
LOCBRDRDT AS date LOCBRDUDT AS date,
LOCBRDCNT AS cnt
FROM localbord FROM localbord
WHERE LOCBRDTYP IN ('F', 'S') WHERE LOCBRDTYP IN ('F', 'S')
<if test="searchKeyword != null and searchKeyword != ''"> <if test="searchKeyword != null and searchKeyword != ''">
AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%') AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
</if> </if>
ORDER BY LOCBRDRDT DESC ORDER BY
<choose>
<when test="orderBy == 'date'"> LOCBRDUDT DESC </when>
<when test="orderBy == 'views'"> LOCBRDCNT DESC </when>
</choose>
</select> </select>
<!-- 조회수 증가 -->
<update id="incrementViewCount">
UPDATE localbord SET LOCBRDCNT = LOCBRDCNT + 1 WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</update>
<!-- 게시물 작성 --> <!-- 게시물 작성 -->
<insert id="createBoard" parameterType="map" useGeneratedKeys="true" keyProperty="LOCBRDSEQ"> <insert id="createBoard" parameterType="map" useGeneratedKeys="true" keyProperty="LOCBRDSEQ">
@ -39,7 +49,6 @@
VALUES (#{LOCBRDTTL}, #{LOCBRDCON}, #{LOCBRDCAT}, #{MEMBERSEQ}, 0, NOW(), NOW(), #{LOCBRDPWD}, #{LOCBRDTYP}) VALUES (#{LOCBRDTTL}, #{LOCBRDCON}, #{LOCBRDCAT}, #{MEMBERSEQ}, 0, NOW(), NOW(), #{LOCBRDPWD}, #{LOCBRDTYP})
</insert> </insert>
<!-- 첨부파일 저장 --> <!-- 첨부파일 저장 -->
<insert id="addAttachment" parameterType="map"> <insert id="addAttachment" parameterType="map">
INSERT INTO commonfil ( INSERT INTO commonfil (
@ -47,19 +56,17 @@
CMNFLEEXT,CMNFLESIZ,CMNFLEREG,CMNFLERDT CMNFLEEXT,CMNFLESIZ,CMNFLEREG,CMNFLERDT
) VALUES ( ) VALUES (
#{CMNBRDSEQ},#{CMNFLENAM},#{CMNFLEORG},#{CMNFLEPAT}, #{CMNBRDSEQ},#{CMNFLENAM},#{CMNFLEORG},#{CMNFLEPAT},
#{CMNFLEEXT},#{CMNFLESIZ},#{CMNFLEREG},#{CMNFLERDT} #{CMNFLEEXT},#{CMNFLESIZ},#{CMNFLEREG},NOW()
) )
</insert> </insert>
<!-- 게시물 상세정보 조회 --> <!-- 게시물 상세정보 조회 -->
<select id="selectBoardDetail" resultType="io.company.localhost.common.dto.MapDto"> <select id="selectBoardDetail" resultType="io.company.localhost.common.dto.MapDto">
SELECT LOCBRDSEQ AS id, LOCBRDTTL AS title, LOCBRDCON AS content, LOCBRDRDT AS date, LOCBRDTYP AS type SELECT LOCBRDSEQ AS id, LOCBRDTTL AS title, LOCBRDCON AS content, LOCBRDUDT AS date, LOCBRDTYP AS type
FROM localbord FROM localbord
WHERE LOCBRDSEQ = #{boardId} WHERE LOCBRDSEQ = #{boardId}
</select> </select>
<!-- 첨부파일 목록 조회 --> <!-- 첨부파일 목록 조회 -->
<select id="selectAttachments" resultType="io.company.localhost.common.dto.MapDto"> <select id="selectAttachments" resultType="io.company.localhost.common.dto.MapDto">
SELECT CMNFLESEQ AS id, CMNFLEORG AS originalName, CMNFLENAM AS fileName, CMNFLEPAT AS path, SELECT CMNFLESEQ AS id, CMNFLEORG AS originalName, CMNFLENAM AS fileName, CMNFLEPAT AS path,
@ -69,12 +76,17 @@
ORDER BY CMNFLERDT DESC ORDER BY CMNFLERDT DESC
</select> </select>
<!-- 게시물 삭제 --> <!-- 게시물 삭제 -->
<delete id="deleteBoard"> <delete id="deleteBoard">
DELETE FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ} DELETE FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</delete> </delete>
<!-- 게시물 삭제 시 댓글/대댓글 삭제 -->
<delete id="deleteCommentsByBoardId">
DELETE FROM localcomt
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</delete>
<!-- 게시물 수정 --> <!-- 게시물 수정 -->
<update id="updateBoard"> <update id="updateBoard">
UPDATE localbord UPDATE localbord
@ -82,11 +94,28 @@
WHERE LOCBRDSEQ = #{LOCBRDSEQ} WHERE LOCBRDSEQ = #{LOCBRDSEQ}
</update> </update>
<!-- 게시물 좋아요/싫어요 추가 --> <!-- 기존 반응 조회 -->
<insert id="reactToBoard"> <select id="findReaction" resultType="io.company.localhost.common.dto.MapDto">
INSERT INTO localgorb (LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD ) SELECT LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD
FROM localgorb
WHERE (LOCBRDSEQ = #{LOCBRDSEQ} OR (#{LOCBRDSEQ} IS NULL AND LOCBRDSEQ IS NULL))
AND (LOCCMTSEQ = #{LOCCMTSEQ} OR (#{LOCCMTSEQ} IS NULL AND LOCCMTSEQ IS NULL))
AND MEMBERSEQ = #{MEMBERSEQ}
</select>
<!-- 반응 업데이트 -->
<update id="updateReaction">
UPDATE localgorb
SET LOCGOBGOD = #{LOCGOBGOD}, LOCGOBBAD = #{LOCGOBBAD}
WHERE (LOCBRDSEQ = #{LOCBRDSEQ} OR (#{LOCBRDSEQ} IS NULL AND LOCBRDSEQ IS NULL))
AND (LOCCMTSEQ = #{LOCCMTSEQ} OR (#{LOCCMTSEQ} IS NULL AND LOCCMTSEQ IS NULL))
AND MEMBERSEQ = #{MEMBERSEQ}
</update>
<!-- 새 반응 삽입 -->
<insert id="insertReaction">
INSERT INTO localgorb (LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD)
VALUES (#{LOCBRDSEQ}, #{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGOBGOD}, #{LOCGOBBAD}) VALUES (#{LOCBRDSEQ}, #{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGOBGOD}, #{LOCGOBBAD})
ON DUPLICATE KEY UPDATE LOCGOBGOD = #{LOCGOBGOD}, LOCGOBBAD = #{LOCGOBBAD}
</insert> </insert>
<!-- 댓글/대댓글 조회 --> <!-- 댓글/대댓글 조회 -->
@ -96,52 +125,80 @@
LOCCMTUDT,LOCCMTPWD,LOCCMTRDT,LOCCMTPNT LOCCMTUDT,LOCCMTPWD,LOCCMTRDT,LOCCMTPNT
FROM localcomt FROM localcomt
WHERE LOCBRDSEQ = #{boardId} WHERE LOCBRDSEQ = #{boardId}
ORDER BY LOCCMTPNT ASC, LOCCMTRDT ASC ORDER BY LOCCMTPNT ASC, LOCCMTUDT ASC
</select> </select>
<!-- 댓글/대댓글 작성 --> <!-- 댓글/대댓글 작성 -->
<insert id="addCommentOrReply"> <insert id="addCommentOrReply">
INSERT INTO localcomt (LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTPNT) INSERT INTO localcomt (LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTUDT, LOCCMTPNT, MEMBERSEQ)
VALUES (#{LOCBRDSEQ}, #{LOCCMTRPY}, #{LOCCMTPWD}, NOW(), #{LOCCMTPNT}) VALUES (#{LOCBRDSEQ}, #{LOCCMTRPY}, #{LOCCMTPWD}, NOW(), NOW() , #{LOCCMTPNT}, #{MEMBERSEQ})
</insert> </insert>
<!-- 댓글/대댓글 수정 --> <!-- 댓글/대댓글 수정 -->
<update id="updateComment"> <update id="updateComment">
UPDATE localcomt UPDATE localcomt
SET LOCCMTRPY = #{LOCCMTRPY}, LOCCMTUDT = NOW() SET LOCCMTRPY = #{LOCCMTRPY}, LOCCMTUDT = NOW()
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPWD = #{LOCCMTPWD} WHERE LOCCMTSEQ = #{LOCCMTSEQ}
</update> </update>
<!-- 댓글/대댓글 삭제 --> <!-- 댓글 삭제 -->
<update id="softDeleteComment">
UPDATE localcomt
SET LOCCMTRPY = '삭제된 댓글입니다'
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
AND EXISTS (
SELECT 1 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
)
</update>
<!-- 댓글 삭제 (대댓글 없을 경우) -->
<delete id="deleteComment"> <delete id="deleteComment">
DELETE FROM localcomt DELETE FROM localcomt
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPWD = #{LOCCMTPWD} WHERE LOCCMTSEQ = #{LOCCMTSEQ}
AND NOT EXISTS (
SELECT 1 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
)
</delete> </delete>
<!-- 비밀번호 확인 (게시물) --> <!-- 대댓글 삭제 -->
<select id="checkBoardPassword" resultType="boolean"> <delete id="deleteReply">
SELECT COUNT(*) > 0 FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ} AND LOCBRDPWD = #{LOCBRDPWD} DELETE FROM localcomt
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
AND LOCCMTPNT IS NOT NULL
</delete>
<!-- 대댓글인지 확인 -->
<select id="isReply" resultType="boolean">
SELECT COUNT(1) > 0 FROM localcomt
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPNT IS NOT NULL
</select> </select>
<!-- 비밀번호 확인 (댓글) --> <!-- 댓글에 대댓글이 있는지 확인 -->
<select id="checkCommentPassword" resultType="boolean"> <select id="hasReplies" resultType="boolean">
SELECT COUNT(*) > 0 FROM localcomt WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPWD = #{LOCCMTPWD} SELECT COUNT(1) > 0 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
</select>
<!-- 댓글 비밀번호 조회 -->
<select id="selectCommentPassword" resultType="String">
SELECT LOCCMTPWD
FROM localcomt
WHERE LOCCMTSEQ = #{commentId}
</select>
<!-- 게시물 비밀번호 조회 -->
<select id="selectBoardPassword" resultType="String">
SELECT LOCBRDPWD
FROM localbord
WHERE LOCBRDSEQ = #{boardId}
</select> </select>
<!-- 비밀 게시판 여부 확인 --> <!-- 비밀 게시판 여부 확인 -->
<select id="isSecretBoard" resultType="boolean"> <select id="isSecretBoard" resultType="boolean">
SELECT CASE WHEN LOCBRDTYP = 'S' THEN TRUE ELSE FALSE END SELECT CASE WHEN LOCBRDTYP = 'S' THEN TRUE ELSE FALSE END
FROM localbord FROM localbord
WHERE LOCBRDSEQ = #{LOCBRDSEQ} WHERE LOCBRDSEQ = #{boardId}
</select> </select>
<!-- 댓글 좋아요/싫어요 추가 -->
<insert id="reactToComment">
INSERT INTO localcomt (LOCCMTSEQ, MEMBERSEQ, LOCGORGOD, LOCGORBAD)
VALUES (#{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGORGOD}, #{LOCGORBAD})
ON DUPLICATE KEY UPDATE LOCGORGOD = #{LOCGORGOD}, LOCGORBAD = #{LOCGORBAD}
</insert>
<!-- 댓글 id확인 --> <!-- 댓글 id확인 -->
<select id="getCommentById" resultType="io.company.localhost.common.dto.MapDto"> <select id="getCommentById" resultType="io.company.localhost.common.dto.MapDto">
SELECT LOCCMTSEQ AS id, LOCCMTPNT AS point SELECT LOCCMTSEQ AS id, LOCCMTPNT AS point
@ -149,5 +206,39 @@
WHERE LOCCMTSEQ = #{commentId} WHERE LOCCMTSEQ = #{commentId}
</select> </select>
<!-- 댓글 개수 조회 -->
<select id="countComments" parameterType="long" resultType="int">
SELECT COUNT(*)
FROM localcomt
WHERE LOCBRDSEQ = #{boardId}
</select>
<!-- 첨부파일 유무 -->
<select id="countAttachments" resultType="int">
SELECT COUNT(*)
FROM commonfil
WHERE CMNBRDSEQ = #{boardId}
</select>
<!-- 게시물 좋아요/싫어요 개수 조회 -->
<select id="getBoardReactions" resultType="io.company.localhost.common.dto.MapDto">
SELECT
COALESCE(SUM(CASE WHEN LOCGOBGOD = 'T' THEN 1 ELSE 0 END), 0) AS likeCount,
COALESCE(SUM(CASE WHEN LOCGOBBAD = 'T' THEN 1 ELSE 0 END), 0) AS dislikeCount
FROM localgorb
WHERE LOCBRDSEQ = #{boardId};
</select>
<!-- 댓글별 좋아요/싫어요 개수 조회 -->
<select id="getCommentReactions" resultType="io.company.localhost.common.dto.MapDto">
SELECT
LOCCMTSEQ,
COALESCE(SUM(CASE WHEN LOCGOBGOD = 'T' THEN 1 ELSE 0 END), 0) AS likeCount,
COALESCE(SUM(CASE WHEN LOCGOBBAD = 'T' THEN 1 ELSE 0 END), 0) AS dislikeCount
FROM localgorb
WHERE LOCBRDSEQ = #{boardId}
GROUP BY LOCCMTSEQ
</select>
</mapper> </mapper>

View File

@ -8,4 +8,13 @@
VALUES (#{employeeId}, #{date}, #{type}, NOW()) VALUES (#{employeeId}, #{date}, #{type}, NOW())
</insert> </insert>
<!-- 직원 ID로 휴가 정보 조회 -->
<select id="findVacationsByEmployeeId" parameterType="int" resultType="map">
SELECT
MEMBERSEQ
LOCVACUDT,
LOCVACTYP
FROM
localvaca
</select>
</mapper> </mapper>