통합검색, 게시판내 검색 기능 보충.

master
강석 최 2021-12-21 18:26:14 +09:00
parent 2dd5496f84
commit 8bd2cc6908
12 changed files with 218 additions and 191 deletions

View File

@ -59,10 +59,16 @@ public class BoardController {
}
@GetMapping("/contentList")
public ModelAndView contentList(Board board){
public ModelAndView contentList(
Board board,
@RequestParam(value = "tagName", required = false) List<String> tagNameList
){
ModelAndView mav = new ModelAndView("board/contentList");
mav.addObject("pageTitle", boardCategoryService.getPageTitle(board.getCategorySeq()));
board.setQueryInfo();
if(tagNameList != null && tagNameList.size() != 0){
board = boardService.setHashTagSearch(board, tagNameList);
}
mav.addObject("contentList", boardService.selectContentList(board));
board.setContentCnt(boardService.selectContentListCnt(board));
board.setPaginationInfo();
@ -78,7 +84,10 @@ public class BoardController {
@RequestParam(value = "tagName", required = false) List<String> tagNameList
){
ModelAndView mav = new ModelAndView("board/contentSearchResult");
mav.addObject("boardList", boardService.fullSearchBoardContent(categorySeqList, board, tagNameList));
if(tagNameList != null && tagNameList.size() != 0){
board = boardService.setHashTagSearch(board, tagNameList);
}
mav.addObject("boardList", boardService.fullSearchBoardContent(categorySeqList, board));
return mav;
}

View File

@ -33,18 +33,10 @@ public class BoardService {
private final UserInfoRepository userInfoRepository;
public List<SearchResult> fullSearchBoardContent(List<Integer> categorySeqList, Board board, List<String> tagNameList) {
public List<SearchResult> fullSearchBoardContent(List<Integer> categorySeqList, Board board) {
board.setRowCnt(Integer.MAX_VALUE);
List<HashTag> tagList = new ArrayList<>();
for(String tagName: tagNameList){
HashTag tag = new HashTag();
tag.setTagName(tagName);
tagList.add(tag);
}
board.setHashTagList(tagList);
List<SearchResult> results = new ArrayList<>();
for(int categorySeq : categorySeqList){
SearchResult searchResult = new SearchResult();
BoardCategory category = boardCategoryRepository.findById(categorySeq).orElse(null);
@ -233,6 +225,21 @@ public class BoardService {
return contentSeq;
}
public Board setHashTagSearch(Board board, List<String> tagNameList){
List<HashTag> tagList = new ArrayList<>();
StringBuilder sb = new StringBuilder();
for(String tagName: tagNameList){
HashTag tag = new HashTag();
tag.setTagName(tagName);
tagList.add(tag);
sb.append(tagName).append(",");
}
board.setHashTagList(tagList);
String hashTagStr = sb.toString();
board.setHashTagStr(hashTagStr.substring(0, hashTagStr.length()-1));
return board;
}
private List<BoardCategory> setboardCategoryToLastDepth(List<BoardCategory> categoryList, BoardCategory category){
for(BoardCategory child: category.getChildCategoryList()){
if(child.getDepth()==4){

View File

@ -223,4 +223,22 @@ function childCategoryStatusChange(parentSeq, flag){
childCategoryStatusChange($(el).attr("data-categoryseq"), flag);
})
}
}
function setSearchCondition(){
const searchConditionSelector = $("#searchConditionSelector").val();
const searchTextDiv = $("#searchTextDiv");
const dateSelectorDiv = $("#dateSelectorDiv");
if(searchConditionSelector === "createDate"){
dateSelectorDiv.show();
dateSelectorDiv.children().removeAttr("disabled");
searchTextDiv.hide();
searchTextDiv.children().attr("disabled", "disabled");
}else{
$("#textSearch").attr("name", searchConditionSelector);
searchTextDiv.show();
searchTextDiv.children().removeAttr("disabled");
dateSelectorDiv.hide();
dateSelectorDiv.children().attr("disabled", "disabled");
}
}

View File

@ -1,117 +0,0 @@
$(function (){
$("#dateSelectorDiv").datepicker({
format: "yyyy-mm-dd",
language: "ko"
});
})
$(document).on('click', '.contentTr', function (){
$(".contentCheckBox").prop('checked', false);
const target = $(this).find(".contentCheckBox")[0];
target.checked = true;
const selectedTab = $(".nav-tabs").find(".active")[0].id;
if(selectedTab === "contentTab"){
getBoardContent(target.value);
}else if(selectedTab === "logTab"){
getBoardLog(target.value);
}
})
$(document).on('change', '#fileCheckAll', function (){
$(".fileCheckBox").prop("checked", this.checked);
})
$(document).on('click', '#contentTab', function (){
getBoardContent(getContentSeq())
})
$(document).on('click', '#logTab', function (){
getBoardLog(getContentSeq())
})
$(document).on('click', '.fileDownLink', function (){
let url = "/board/fileDownload?"
url += "contentSeq="+Number($("#detailViewContentSeq").val());
url += "&fileSeq="+$(this).attr("data-fileseq");
window.open(encodeURI(url));
})
$(document).on('click', '#zipDownBtn', function (){
const checkFiles = $(".fileCheckBox:checked");
if(checkFiles.length>0){
let url = "/board/fileDownloadToZip?"
url += "contentSeq="+Number($("#detailViewContentSeq").val());
checkFiles.each(function (idx, el){
url += "&fileSeq="+Number($(el).attr("data-fileseq"))
});
window.open(encodeURI(url));
}else{
alert("선택된 파일이 없습니다.")
}
})
$(document).on('click', '#deleteBtn', function (){
if(confirm("이 게시물을 삭제하시겠습니까?\n되돌릴 수 없습니다.")){
$.ajax({
type : 'DELETE',
url : "/board/deleteContent",
data : {contentSeq: Number($(this).attr("data-contentseq"))},
beforeSend: function (xhr){
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
},
success : function(data) {
alert("저장되었습니다.");
location.reload();
},
error : function(xhr, status) {
}
})
}
})
$(document).on('click', '#modifyBtn', function (){
location.href = "/board/contentWrite?contentSeq="+Number($(this).attr("data-contentseq"));
})
function getContentSeq(){
return $(".contentCheckBox:checked").val();
}
function getBoardContent(contentSeq){
if(contentSeq !== undefined){
const viewContentSeq = $("#detailViewContentSeq").val();
if(contentSeq !== viewContentSeq){
$.ajax({
url: '/board/selectBoardContent',
data: {contentSeq: contentSeq},
type: 'GET',
dataType:"html",
success: function(html){
$("#contentDiv").empty().append(html)
if($("#contentStatus").val() !== "D"){
const viewCntTd = $(".contentCheckBox:checked").parents("tr").find(".viewCntTd");
viewCntTd.text(Number(viewCntTd.text())+1);
}
},
error:function(){
}
});
}
}
}
function getBoardLog(contentSeq){
if(contentSeq !== undefined){
$.ajax({
url: '/board/selectBoardLog',
data: {contentSeq: contentSeq},
type: 'GET',
dataType:"html",
success: function(html){
$("#logDiv").empty().append(html)
},
error:function(){
}
});
}
}

View File

@ -1,3 +1,117 @@
$(function(){
setSearchCondition();
})
$(function (){
$("#dateSelectorDiv").datepicker({
format: "yyyy-mm-dd",
language: "ko"
});
})
$(document).on('click', '.contentTr', function (){
$(".contentCheckBox").prop('checked', false);
const target = $(this).find(".contentCheckBox")[0];
target.checked = true;
const selectedTab = $(".nav-tabs").find(".active")[0].id;
if(selectedTab === "contentTab"){
getBoardContent(target.value);
}else if(selectedTab === "logTab"){
getBoardLog(target.value);
}
})
$(document).on('change', '#fileCheckAll', function (){
$(".fileCheckBox").prop("checked", this.checked);
})
$(document).on('click', '#contentTab', function (){
getBoardContent(getContentSeq())
})
$(document).on('click', '#logTab', function (){
getBoardLog(getContentSeq())
})
$(document).on('click', '.fileDownLink', function (){
let url = "/board/fileDownload?"
url += "contentSeq="+Number($("#detailViewContentSeq").val());
url += "&fileSeq="+$(this).attr("data-fileseq");
window.open(encodeURI(url));
})
$(document).on('click', '#zipDownBtn', function (){
const checkFiles = $(".fileCheckBox:checked");
if(checkFiles.length>0){
let url = "/board/fileDownloadToZip?"
url += "contentSeq="+Number($("#detailViewContentSeq").val());
checkFiles.each(function (idx, el){
url += "&fileSeq="+Number($(el).attr("data-fileseq"))
});
window.open(encodeURI(url));
}else{
alert("선택된 파일이 없습니다.")
}
})
$(document).on('click', '#deleteBtn', function (){
if(confirm("이 게시물을 삭제하시겠습니까?\n되돌릴 수 없습니다.")){
$.ajax({
type : 'DELETE',
url : "/board/deleteContent",
data : {contentSeq: Number($(this).attr("data-contentseq"))},
beforeSend: function (xhr){
xhr.setRequestHeader($("[name='_csrf_header']").val(), $("[name='_csrf']").val());
},
success : function(data) {
alert("저장되었습니다.");
location.reload();
},
error : function(xhr, status) {
}
})
}
})
$(document).on('click', '#modifyBtn', function (){
location.href = "/board/contentWrite?contentSeq="+Number($(this).attr("data-contentseq"));
})
function getContentSeq(){
return $(".contentCheckBox:checked").val();
}
function getBoardContent(contentSeq){
if(contentSeq !== undefined){
const viewContentSeq = $("#detailViewContentSeq").val();
if(contentSeq !== viewContentSeq){
$.ajax({
url: '/board/selectBoardContent',
data: {contentSeq: contentSeq},
type: 'GET',
dataType:"html",
success: function(html){
$("#contentDiv").empty().append(html)
if($("#contentStatus").val() !== "D"){
const viewCntTd = $(".contentCheckBox:checked").parents("tr").find(".viewCntTd");
viewCntTd.text(Number(viewCntTd.text())+1);
}
},
error:function(){
}
});
}
}
}
function getBoardLog(contentSeq){
if(contentSeq !== undefined){
$.ajax({
url: '/board/selectBoardLog',
data: {contentSeq: contentSeq},
type: 'GET',
dataType:"html",
success: function(html){
$("#logDiv").empty().append(html)
},
error:function(){
}
});
}
}

View File

@ -70,6 +70,10 @@ $(document).on('click', '#searchBtn', function (){
})
function searchParamCheck(){
if(!$("#searchCategorySeq").val()){
alert("분류를 하나 이상 선택해주셔야 합니다.")
return false;
}
let emptyCnt = 0;
if(!$("#title").val()){
emptyCnt++;
@ -86,8 +90,8 @@ function searchParamCheck(){
if(!$("#originalName").val()){
emptyCnt++;
}
if(emptyCnt>3){
alert("분류를 제외한 5가지 조건 중 2가지 이상 입력해주세요.")
if(emptyCnt>4){
alert("분류를 제외한 5가지 조건 중 1가지 이상 입력해주세요.")
return false;
}else{
return true;

View File

@ -1,18 +0,0 @@
function setSearchCondition(){
const searchConditionSelector = $("#searchConditionSelector").val();
const searchTextDiv = $("#searchTextDiv");
const dateSelectorDiv = $("#dateSelectorDiv");
if(searchConditionSelector === "createDate"){
dateSelectorDiv.show();
dateSelectorDiv.children().removeAttr("disabled");
searchTextDiv.hide();
searchTextDiv.children().attr("disabled", "disabled");
}else{
$("#textSearch").attr("name", searchConditionSelector);
searchTextDiv.show();
searchTextDiv.children().removeAttr("disabled");
dateSelectorDiv.hide();
dateSelectorDiv.children().attr("disabled", "disabled");
}
}

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,6 @@
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout}">
<th:block layout:fragment="script">
<script type="text/javascript" th:src="@{/js/board/boardCommon.js}"></script>
<script type="text/javascript" th:src="@{/js/board/contentList.js}"></script>
</th:block>
<div layout:fragment="content">
@ -20,6 +19,7 @@
<div class="col-7">
<!--검색 form-->
<form method="get" th:action="@{/board/contentList}">
<input type="hidden" name="categorySeq" id="categorySeq" th:value="${searchParams.categorySeq}">
<input type="hidden" name="pageIndex" id="pageIndex" th:value="${searchParams.pageIndex}">
<div class="row justify-content-between">
<div class="col-auto row">
@ -27,45 +27,48 @@
<label for="rowCnt" class="col-form-label">데이터 수</label>
</div>
<div class="col-auto">
<select class="form-select" name="rowCnt" id="rowCnt">
<select class="form-select form-control-sm" name="rowCnt" id="rowCnt">
<th:block th:each="num : ${#numbers.sequence(1,5)}">
<option th:value="${num*10}" th:text="${num*10}" th:selected="${searchParams.rowCnt==num*10}"></option>
</th:block>
</select>
</div>
</div>
<div class="col-auto">
<div class="row justify-content-end">
<div class="col-auto card">
<div class="row justify-content-end pt-1">
<div class="col-auto">
<select class="form-select" id="searchConditionSelector">
<option>검색조건</option>
</select>
<!--<select class="form-select" id="searchConditionSelector">
<option value="userId" th:selected="${searchParams.userId!=null and searchParams.userId!=''}">아이디</option>
<option value="name" th:selected="${searchParams.name!=null and searchParams.name!=''}">이름</option>
<option value="positionName" th:selected="${searchParams.positionName!=null and searchParams.positionName!=''}">부서</option>
<option value="departmentName" th:selected="${searchParams.departmentName!=null and searchParams.departmentName!=''}">직급</option>
<option value="createDate" th:selected="${searchParams.startDate!=null and searchParams.startDate!=''} or ${searchParams.endDate!=null and searchParams.endDate!=''}">생성일</option>
</select>-->
<div class="row mb-1">
<label for="title" class="col-sm-2 col-form-label">제목</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="title" name="title" th:value="${searchParams.title}">
</div>
<label for="createName" class="col-sm-2 col-form-label">작성자</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="createName" name="createName" th:value="${searchParams.createName}">
</div>
</div>
<div class="row mb-1">
<label for="tagName" class="col-sm-2 col-form-label" data-bs-toggle="tooltip" data-bs-placement="top" title="# 없이 ,로 구분하여 태그 입력">해시태그</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="tagName" name="tagName" th:value="${searchParams.hashTagStr}">
</div>
<label for="originalName" class="col-sm-2 col-form-label">첨부파일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="originalName" name="originalName" th:value="${searchParams.originalName}">
</div>
</div>
<div class="row">
<label for="startDate" class="col-sm-2 col-form-label">작성일</label>
<div class="col-sm-6">
<div class="col-auto input-group w-auto input-daterange" id="dateSelectorDiv">
<input type="text" class="form-control form-control-sm" id="startDate" name="startDate" placeholder="시작일" autocomplete="off" th:value="${searchParams.startDate}" readonly>
<input type="text" class="form-control form-control-sm" id="endDate" name="endDate" placeholder="종료일" autocomplete="off" th:value="${searchParams.endDate}" readonly>
</div>
</div>
</div>
</div>
<div class="col-auto" id="searchTextDiv">
<input type="text" class="form-control" id="textSearch">
<!--<input type="text" class="form-control" id="textSearch" th:value="${
(searchParams.userId!=null and searchParams.userId!='')?searchParams.userId:(
(searchParams.name!=null and searchParams.name!='')?searchParams.name:(
(searchParams.positionName!=null and searchParams.positionName!='')?searchParams.positionName:(
(searchParams.departmentName!=null and searchParams.departmentName!='')?searchParams.departmentName:''
)
)
)
}">-->
</div>
<div class="col-auto input-group w-auto input-daterange" id="dateSelectorDiv" style="display: none">
<input type="text" class="form-control" id="startDate" name="startDate" placeholder="시작일" autocomplete="off" disabled th:value="${searchParams.startDate}">
<input type="text" class="form-control" id="endDate" name="endDate" placeholder="종료일" autocomplete="off" disabled th:value="${searchParams.endDate}">
</div>
<div class="col-auto">
<input type="submit" class="btn btn-primary" id="searchBtn" value="검색">
<div class="col-auto my-auto">
<input type="submit" class="btn btn-primary py-4" id="searchBtn" value="검색">
</div>
</div>
</div>

View File

@ -6,8 +6,8 @@
layout:decorate="~{layout/layout}">
<th:block layout:fragment="script">
<script type="text/javascript" th:src="@{/vendor/jquery-ui-1.13.0.dragSort/jquery-ui.min.js}"></script>
<script type="text/javascript" th:src="@{/js/board/boardCommon.js}"></script>
<script type="text/javascript" th:src="@{/js/board/contentSearch.js}"></script>
<script type="text/javascript" th:src="@{/js/board/contentList.js}"></script>
</th:block>
<div layout:fragment="content">
<main class="pt-3">
@ -44,20 +44,20 @@
</div>
</div>
<div class="row mb-1">
<label for="title" class="col-sm-2 col-form-label">해시태그</label>
<label for="tagName" class="col-sm-2 col-form-label">해시태그</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="tagName" name="tagName" placeholder="# 없이 ,로 구분하여 태그 입력">
</div>
<label for="startDate" class="col-sm-2 col-form-label">작성일</label>
<div class="col-sm-4">
<div class="col-auto input-group w-auto input-daterange" id="dateSelectorDiv">
<input type="text" class="form-control form-control-sm" id="startDate" name="startDate" placeholder="시작일" autocomplete="off">
<input type="text" class="form-control form-control-sm" id="endDate" name="endDate" placeholder="종료일" autocomplete="off">
<input type="text" class="form-control form-control-sm" id="startDate" name="startDate" placeholder="시작일" autocomplete="off" readonly>
<input type="text" class="form-control form-control-sm" id="endDate" name="endDate" placeholder="종료일" autocomplete="off" readonly>
</div>
</div>
</div>
<div class="row">
<label for="title" class="col-sm-2 col-form-label">첨부파일</label>
<label for="originalName" class="col-sm-2 col-form-label">첨부파일</label>
<div class="col-sm-4">
<input type="text" class="form-control form-control-sm" id="originalName" name="originalName">
</div>

View File

@ -21,6 +21,7 @@
<!--bootstrap-->
<script type="text/javascript" th:src="@{/vendor/bootstrap-5.1.3-dist/js/bootstrap.bundle.min.js}"></script>
<script type="text/javascript" th:src="@{/vendor/bootstrap-5.1.3-dist/js/popper.min.js}"></script>
<!--jquery-->
<script type="text/javascript" th:src="@{/vendor/jquery-3.6.0/jquery-3.6.0.min.js}"></script>
<!--bootstrap-datepicker-->

View File

@ -46,11 +46,11 @@
<input type="password" class="form-control" id="password" name="password" placeholder="비밀번호">
<label for="password">비밀번호</label>
</div>
<div class="checkbox mb-3">
<!--<div class="checkbox mb-3">
<label>
<input type="checkbox" class="disabled" value="remember-me"> 계정저장(비활성화)
</label>
</div>
</div>-->
<button class="w-100 btn btn-lg btn-primary" type="submit">로그인</button>
</form>
</div>