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.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
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.RequestParam;
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.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.dto.ApiResponse;
import io.company.localhost.common.dto.MapDto;
@ -52,12 +51,15 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class BoardController {
private final localbordService boardService;
private final PasswordEncoder passwordEncoder;
/**
* 공지사항 목록 조회
* @ReqMap map 요청 파라미터 (searchKeyword)
* @return 페이징된 공지사항 목록
* @return 전체 공지사항 목록
*/
@Member
@ParameterCheck
@GetMapping("/notices")
public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) {
List<MapDto> posts = boardService.getNotices(map);
@ -69,6 +71,12 @@ public class BoardController {
Blob blob = (Blob) content;
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);
@ -76,9 +84,11 @@ public class BoardController {
/**
* 자유/익명 게시판 목록 조회
* @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함)
* @ReqMap map 요청 파라미터 (page, searchKeyword, orderBy)
* @return 페이징된 자유/익명 게시판 목록
*/
@Member
@ParameterCheck
@GetMapping("/general")
public ApiResponse<PageInfo<MapDto>> getGeneralPosts(@ReqMap MapDto map) {
PageInfo<MapDto> posts = boardService.getGeneralPosts(map);
@ -90,6 +100,19 @@ public class BoardController {
Blob blob = (Blob) content;
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);
@ -121,56 +144,55 @@ public class BoardController {
/**
* 게시물 작성
* @ReqMap map 요청 파라미터 (page, size, searchKeyword 포함)
* @ReqMap map 요청 파라미터 (LOCBRDTTL, LOCBRDCON, MEMBERSEQ, LOCBRDTYP,
* LOCBRDPWD(익명일떄에만), LOCBRDCAT(지식커뮤니티만))
* @return 작성된 게시물의 ID
*/
@PostMapping
public ApiResponse<?> createBoard(@ReqMap MapDto map) {
BigInteger createdIdx = boardService.createBoard(map); // 작성된 게시물의 idx를 반환
Map<String, Object> responseData = new HashMap<>();
responseData.put("boardId", createdIdx);
responseData.put("message", "게시물이 작성되었습니다.");
return ApiResponse.ok(responseData);
}
@Member
@ParameterCheck
@PostMapping
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를 반환
Map<String, Object> responseData = new HashMap<>();
responseData.put("CMNBRDSEQ", createdIdx);
responseData.put("message", "게시물이 작성되었습니다.");
return ApiResponse.ok(responseData);
}
/**
* 첨부파일 추가
* @param boardId 게시물 ID
* @param file 업로드된 파일
* @param filePath 파일 저장 경로
* @param originalFileName 원본 파일명
* @param fileExtension 파일 확장자
* @param fileSize 파일 크기
* @param registrantId 등록자 ID
* @param fileName 저장될 파일명
* @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ)
* @return 첨부파일 저장 결과 메시지
*/
@PostMapping("/{boardId}/attachments")
public ApiResponse<String> uploadAttachment(
@PathVariable("boardId") Long boardId,
@RequestParam("file") MultipartFile file,
@RequestParam("CMNFLEPAT") String filePath,
@RequestParam("CMNFLEORG") String originalFileName,
@RequestParam("CMNFLEEXT") String fileExtension,
@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);
@Member
@ParameterCheck
@PostMapping("/{CMNBRDSEQ}/attachments")
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) {
String filename = UUID.randomUUID().toString();
map.put("CMNFLENAM", filename);
map.put("CMNFLEREG", 1);
// 파일 데이터 저장
boardService.addAttachment(fileData);
boardService.addAttachment(map);
return ApiResponse.ok("첨부파일이 저장되었습니다.");
}
@ -180,10 +202,15 @@ public class BoardController {
* @param boardId 게시물 ID
* @return 게시물 상세정보, 첨부파일 목록, 댓글 목록
*/
@Member
@ParameterCheck
@GetMapping("/{boardId}")
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
log.info("Fetching details for board ID: {}", boardId);
// 조회수 증가
boardService.incrementViewCount(boardId);
// 게시물 상세정보 조회
MapDto boardDetail = boardService.getBoardDetail(boardId);
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> 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();
result.put("boardDetail", boardDetail);
result.put("attachments", attachments);
result.put("comments", comments);
result.put("commentCount", boardService.getCommentCount(boardId));
result.put("hasAttachment", boardService.hasAttachments(boardId));
return ApiResponse.ok(result);
}
@ -219,6 +262,8 @@ public class BoardController {
* @param boardId 게시물 ID
* @return 삭제 결과 메시지
*/
@Member
@ParameterCheck
@DeleteMapping("/{boardId}")
public ApiResponse<String> deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId);
@ -230,9 +275,11 @@ public class BoardController {
/**
* 게시물 수정
* @param boardId 게시물 ID
* @ReqMap map 수정 데이터 (제목, 내용 )
* @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON)
* @return 수정 결과 메시지
*/
@Member
@ParameterCheck
@PutMapping("/{boardId}")
public ApiResponse<String> updateBoard(@PathVariable("boardId") Long boardId,@ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId);
@ -241,72 +288,55 @@ public class BoardController {
}
/**
* 게시물 좋아요/싫어요 추가
* @param boardId 게시물 ID
* @ReqMap map 좋아요/싫어요 데이터
* 게시물,댓글 좋아요/싫어요 추가
* @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ)
* @return 반응 추가 결과 메시지
*/
@PostMapping("/{boardId}/reaction")
public ApiResponse<String> reactToBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId);
@Member
@ParameterCheck
@PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction")
public ApiResponse<String> reactToBoard(@ReqMap MapDto map) {
//로그인 미개발 ->임시
map.put("MEMBERSEQ", 1);
boardService.reactToBoard(map);
return ApiResponse.ok("반응이 추가되었습니다.");
return ApiResponse.ok("반응이 성공적으로 처리되었습니다.");
}
/**
/**
* 댓글/대댓글 조회
* @param boardId 게시물 ID
* @return 댓글과 대댓글의 계층 구조 데이터
*/
@Member
@ParameterCheck
@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);
// 댓글과 대댓글을 계층 구조로 정렬
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);
return ApiResponse.ok(comments);
}
/**
* 댓글/대댓글 작성
* @param boardId 게시물 ID
* @ReqMap map 댓글 데이터 (내용, 부모 ID )
* @ReqMap map 댓글 데이터 (LOCBRDSEQ, LOCCMTRPY, LOCCMTPNT, LOCCMTPWD, MEMBERSEQ )
* @return 작성 결과 메시지
*/
@PostMapping("/{boardId}/comment")
public ApiResponse<String> addCommentOrReply(@PathVariable("boardId") int boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId);
@Member
@ParameterCheck
@PostMapping("/{LOCBRDSEQ}/comment")
public ApiResponse<String> addCommentOrReply(@ReqMap MapDto map) {
//로그인 미개발 ->임시
map.put("MEMBERSEQ", 1);
// 부모 댓글 확인
Integer parentCommentId = (Integer) map.get("LOCCMTRPY");
if (parentCommentId != null) {
MapDto parentComment = boardService.getCommentById(parentCommentId);
if (parentComment == null) {
throw new IllegalArgumentException("Invalid parent comment ID: " + parentCommentId);
}
// 비밀번호 암호화 (비밀번호가 있는 경우에만)
if (map.containsKey("LOCCMTPWD")) {
String rawPassword = map.getString("LOCCMTPWD");
String encodedPassword = passwordEncoder.encode(rawPassword);
map.put("LOCCMTPWD", encodedPassword);
}
boardService.addCommentOrReply(map);
@ -316,9 +346,11 @@ public class BoardController {
/**
* 댓글/대댓글 수정
* @param commentId 댓글 ID
* @ReqMap map 수정 데이터 (내용, 비밀번호 )
* @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY )
* @return 수정 결과 메시지
*/
@Member
@ParameterCheck
@PutMapping("/comment/{commentId}")
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);
}
// 부모 댓글 ID는 수정 불가
map.remove("LOCCMTRPY");
map.put("LOCCMTSEQ", commentId);
boardService.updateComment(map);
@ -339,9 +368,10 @@ public class BoardController {
/**
* 댓글/대댓글 삭제
* @param commentId 댓글 ID
* @ReqMap map 요청 데이터 (비밀번호 )
* @return 삭제 결과 메시지
*/
@Member
@ParameterCheck
@DeleteMapping("/comment/{commentId}")
public ApiResponse<String> deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId);
@ -356,10 +386,17 @@ public class BoardController {
* @ReqMap map 비밀번호 데이터
* @return 비밀번호 확인 결과
*/
@Member
@ParameterCheck
@PostMapping("/comment/{commentId}/password")
public ApiResponse<Boolean> checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
map.put("LOCCMTSEQ", commentId);
return ApiResponse.ok(boardService.checkCommentPassword(map));
// DB에서 암호화된 비밀번호 조회
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 비밀번호 데이터
* @return 비밀번호 확인 결과
*/
@Member
@ParameterCheck
@PostMapping("/{boardId}/password")
public ApiResponse<Boolean> checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) {
map.put("LOCBRDSEQ", boardId);
return ApiResponse.ok(boardService.checkBoardPassword(map));
}
// DB에서 암호화된 비밀번호 조회
String storedPassword = boardService.getBoardPassword(boardId);
String rawPassword = map.getString("LOCBRDPWD");
/**
* 비밀게시판 여부 확인
* @param boardId 게시물 ID
* @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.");
// 비밀번호 검증
boolean isMatch = passwordEncoder.matches(rawPassword, storedPassword);
return ApiResponse.ok(isMatch);
}
}

View File

@ -1,6 +1,7 @@
package io.company.localhost.controller.api;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@ -45,4 +46,16 @@ public class VacationController {
// 성공적으로 저장된 경우 응답 반환
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 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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@ -39,7 +35,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@RequestMapping("/api/img")
@RequestMapping("/api/quilleditor")
@RequiredArgsConstructor
public class ImageUploadController {
@ -47,8 +43,8 @@ public class ImageUploadController {
private String boardFilePath;
/**
* 에디터 이미지 업로
* @form-data file 업로드할 파일실제경로/파일이름
* quilleditor 안에서 삽입된 이미지를 서버에 저장하는 메소
* @form-data 서버에 저장된 이미지 경로와 이름
* @return
*/
@ParameterCheck

View File

@ -16,6 +16,9 @@ public interface localbordMapper {
// 자유/비밀 게시판 조회
List<MapDto> getGeneralPosts(MapDto map);
// 조회수 증가
void incrementViewCount(Long boardId);
// 게시물 작성
void createBoard(MapDto map);
@ -25,11 +28,20 @@ public interface localbordMapper {
// 게시물 삭제
void deleteBoard(MapDto map);
// 게시물 삭제시 댓글/대댓글 삭제
void deleteCommentsByBoardId(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);
@ -40,28 +52,47 @@ public interface localbordMapper {
// 댓글/대댓글 수정
void updateComment(MapDto map);
// 댓글/대댓글 삭제
// 대댓글인지 확인
boolean isReply(MapDto map);
// 댓글에 대댓글이 있는지 확인
boolean hasReplies(MapDto map);
// 댓글 내용만 삭제 처리 (대댓글 유지)
void softDeleteComment(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);
// 댓글 갯수
int countComments(Long boardId);
// 첨부파일 유무
int countAttachments(Long boardId);
// 게시물 좋아요/싫어요 개수
MapDto getBoardReactions(Long boardId);
// 댓글 좋아요/싫어요 개수
List<MapDto> getCommentReactions(Long boardId);
// 첨부파일 가져오기
List<MapDto> selectAttachments(Long boardId);
//댓글 좋아요/싫어요추가
void reactToComment(MapDto map);
//댓글id 확인
MapDto getCommentById(int commentId);
}

View File

@ -1,13 +1,18 @@
package io.company.localhost.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import io.company.localhost.common.dto.MapDto;
@Mapper
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) {
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
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);
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) {
boardMapper.createBoard(map); // 게시물 작성
boardMapper.createBoard(map);
return (BigInteger) map.get("LOCBRDSEQ"); // Mapper에서 자동 생성된 key를 가져옴
}
@ -47,8 +60,8 @@ public class localbordService {
return boardMapper.selectAttachments(boardId);
}
public void deleteBoard(MapDto map) {
boardMapper.deleteCommentsByBoardId(map);
boardMapper.deleteBoard(map);
}
@ -57,7 +70,16 @@ public class localbordService {
}
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) {
@ -65,39 +87,65 @@ public class localbordService {
}
public void addCommentOrReply(MapDto map) {
if (map.get("LOCCMTPNT") == null) {
map.put("LOCCMTPNT", null);
}
boardMapper.addCommentOrReply(map);
}
public void updateComment(MapDto map) {
boardMapper.updateComment(map);
}
public void deleteComment(MapDto map) {
boardMapper.deleteComment(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);
}
}
}
public boolean checkBoardPassword(MapDto map) {
return boardMapper.checkBoardPassword(map);
public String getCommentPassword(int commentId) {
return boardMapper.selectCommentPassword(commentId);
}
public boolean checkCommentPassword(MapDto map) {
return boardMapper.checkCommentPassword(map);
}
public boolean isSecretBoard(Long boardId) {
return boardMapper.isSecretBoard(boardId);
}
public void reactToComment(MapDto map) {
boardMapper.reactToComment(map);
public String getBoardPassword(int boardId) {
return boardMapper.selectBoardPassword(boardId);
}
public MapDto getCommentById(int 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);
}
public List<MapDto> getVacationList() {
return localvacaMapper.findVacations();
}
}

View File

@ -58,6 +58,18 @@ public class PageUtil {
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;
}
}

View File

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

View File

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