Merge branch 'dev' into krc/receipt_waiting

pull/22/head
고락춘 2 weeks ago
commit d6989887a5

@ -56,13 +56,11 @@ public class DayAnswerController {
@PostMapping("/minwon/dayanswer/dayanswer-select.ajax")
public ResponseEntity<?> list(@ModelAttribute DayAnswerDto.Request.Search dto) {
dto.setTotalCount(0);
dto.setPagingYn("Y");
List<DayAnswerDto.Response.cpMain> result;
dto.setTotalCount(0);
dto.setPagingYn("N");
result = dayAnswerService.selectAllDayAnswer(dto);
List<DayAnswerDto.Response.cpMain> result = dayAnswerService.selectAllDayAnswer(dto);
return ApiResponseUtil.successWithGrid(result, dto);
}
@ -131,57 +129,7 @@ public class DayAnswerController {
HttpServletResponse response
) throws Exception {
// 검색 조건을 이용해 전체 리스트 조회
List<DayAnswerDto.Response.cpMain> list = dayAnswerService.selectAllDayAnswer(dto);
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("일별답변결과");
int rowNo = 0;
Row header = sheet.createRow(rowNo++);
header.createCell(0).setCellValue("메인코드");
header.createCell(1).setCellValue("시군구코드");
header.createCell(2).setCellValue("구분");
header.createCell(3).setCellValue("접수일자");
header.createCell(4).setCellValue("접수번호");
header.createCell(5).setCellValue("처리자");
header.createCell(6).setCellValue("전화번호");
header.createCell(7).setCellValue("휴대폰");
header.createCell(8).setCellValue("이메일");
header.createCell(9).setCellValue("처리상태");
header.createCell(10).setCellValue("답변내용");
for (DayAnswerDto.Response.cpMain rowData : list) {
Row row = sheet.createRow(rowNo++);
row.createCell(0).setCellValue(nvl(rowData.getAsMmcode()));
row.createCell(1).setCellValue(nvl(rowData.getAsSggcode()));
row.createCell(2).setCellValue(nvl(rowData.getAsIngb()));
row.createCell(3).setCellValue(nvl(rowData.getAsJsdate()));
row.createCell(4).setCellValue(nvl(rowData.getAsJsno()));
row.createCell(5).setCellValue(nvl(rowData.getAsUser()));
row.createCell(6).setCellValue(nvl(rowData.getAsTel()));
row.createCell(7).setCellValue(nvl(rowData.getAsCell()));
row.createCell(8).setCellValue(nvl(rowData.getAsEmail()));
row.createCell(9).setCellValue(nvl(rowData.getAsState()));
row.createCell(10).setCellValue(nvl(rowData.getAsText()));
}
for (int i = 0; i <= 10; i++) {
sheet.autoSizeColumn(i);
}
String fileName = URLEncoder.encode("일별답변결과.xlsx", StandardCharsets.UTF_8.name())
.replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
wb.write(response.getOutputStream());
wb.close();
}
private String nvl(String s) {
return s == null ? "" : s;
dayAnswerService.downloadExcel(dto, response);
}
@GetMapping("/minwon/dayanswer/history.ajax")
@ -194,4 +142,30 @@ public class DayAnswerController {
System.out.println(" 결과건수 = " + (list != null ? list.size() : 0));
return list;
}
@PostMapping("/minwon/dayanswer/update-all-state.ajax")
@ResponseBody
public Map<String, Object> updateAllState(
@ModelAttribute DayAnswerDto.Request.Search dto,
@RequestParam("newState") String newState) {
int updated = dayAnswerService.updateAllState(dto, newState);
Map<String, Object> result = new HashMap<>();
result.put("updated", updated);
result.put("result", "success");
return result;
}
@PostMapping("/minwon/dayanswer/update-one-state.ajax")
@ResponseBody
public Map<String, Object> updateOneState(
@RequestParam("asMmcode") String asMmcode,
@RequestParam("newState") String newState) {
int updated = dayAnswerService.updateOneState(asMmcode, newState);
Map<String, Object> result = new HashMap<>();
result.put("updated", updated);
result.put("result", "success");
return result;
}
}

@ -4,6 +4,7 @@ import go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface DayAnswerMapper {
@ -19,4 +20,14 @@ public interface DayAnswerMapper {
List<DayAnswerDto.Response.History> selectHistoryasMmcode(String asMmcode);
int insertAnswerHistory(DayAnswerDto.Request.Update dto);
int updateAllState(@Param("search") DayAnswerDto.Request.Search dto,
@Param("newState") String newState);
int updateOneState(@Param("asMmcode") String asMmcode,
@Param("newState") String newState);
int selectAllDayAnswerCount(DayAnswerDto.Request.Search dto);
List<DayAnswerDto.Response.cpMain> selectAllDayAnswerForExcel(DayAnswerDto.Request.Search dto);
}

@ -17,11 +17,13 @@ public class DayAnswerDto {
public static class Search extends PagingVO {
private String searchCondition;
private String searchKeyword;
private String searchStartDt;
private String searchEndDt;
private String worker;
private String tabState;
}
@Data
@ -70,14 +72,18 @@ public class DayAnswerDto {
private String asSysGubunC;
private String asPetiAncCodeV;
private String asPetiNoC;
private String ccCause;
private String mmCarno;
private String mmDate;
private String mmCode;
}
@Data
public static class History {
private String asMmcode;
private String asText;
private String asUser;
private String asState;
private String updateDt;
private String asMmcode;
private String asText;
private String asUser;
private String asState;
private String updateDt;
}
}

@ -18,5 +18,11 @@ public interface DayAnswerService {
void updateDayAnswer(DayAnswerDto.Request.Update dto);
int updateAllState(DayAnswerDto.Request.Search dto, String newState);
int updateOneState(String asMmcode, String newState);
void downloadExcel(DayAnswerDto.Request.Search dto,
javax.servlet.http.HttpServletResponse response) throws Exception;
}

@ -4,26 +4,79 @@ import go.kr.project.biz.minwon.dayanswer.mapper.DayAnswerMapper;
import go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto;
import go.kr.project.biz.minwon.dayanswer.service.DayAnswerService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
@Service
@RequiredArgsConstructor
@Slf4j
public class DayAnswerServiceImpl extends EgovAbstractServiceImpl implements DayAnswerService {
private final DayAnswerMapper dayAnswerMapper;
@Override
public List<DayAnswerDto.Response.cpMain> selectAllDayAnswer(DayAnswerDto.Request.Search dto) {
@Override
public List<DayAnswerDto.Response.cpMain> selectAllDayAnswer(DayAnswerDto.Request.Search dto) {
//log.info("검색 DTO = page={}, perPage={}, startIndex={}, tabState={}, keyword={}",
// dto.getPage(), dto.getPerPage(), dto.getStartIndex(),
// dto.getTabState(), dto.getSearchKeyword());
//log.info("totalCount = {}", dto.getTotalCount());
//
// // 1. page / perPage 기본값 처리
// Integer page = dto.getPage();
// Integer perPage = dto.getPerPage();
//
// if (page == null || page <= 0) {
// page = 1;
// }
// if (perPage == null || perPage <= 0) {
// perPage = 30; // PagingVO 기본값과 맞추기
// }
//
// dto.setPage(page);
// dto.setPerPage(perPage);
//
// // 2. 전체 건수 조회
// int totalCount = dayAnswerMapper.selectAllDayAnswerCount(dto);
// dto.setTotalCount(totalCount);
//
// // 3. startIndex / endIndex 계산
// int startIndex = (page - 1) * perPage;
// dto.setStartIndex(startIndex);
// dto.setEndIndex(startIndex + perPage);
//
// // 4. 전체 페이지 수 계산
// int totalPages = totalCount > 0
// ? (int) Math.ceil((double) totalCount / perPage)
// : 0;
// dto.setTotalPages(totalPages);
//
//log.info("검색 DTO = page={}, perPage={}, startIndex={}, tabState={}, keyword={}",
// dto.getPage(), dto.getPerPage(), dto.getStartIndex(),
// dto.getTabState(), dto.getSearchKeyword());
//log.info("totalCount = {}", dto.getTotalCount());
// 5. 실제 목록 조회
List<DayAnswerDto.Response.cpMain> list = dayAnswerMapper.selectAllDayAnswer(dto);
List<DayAnswerDto.Response.cpMain> result = dayAnswerMapper.selectAllDayAnswer(dto);
log.info("selectAllDayAnswer 결과 건수 = {}", list.size());
return list;
return result;
}
@Override
public DayAnswerDto.Response.cpMain selectOneByasMmcode (String asMmcode){
return dayAnswerMapper.selectOneByasMmcode(asMmcode);
@ -46,6 +99,76 @@ public class DayAnswerServiceImpl extends EgovAbstractServiceImpl implements Day
dayAnswerMapper.updateDayAnswer(dto);
dayAnswerMapper.insertAnswerHistory(dto);
}
@Override
public int updateAllState(DayAnswerDto.Request.Search dto, String newState) {
return dayAnswerMapper.updateAllState(dto, newState);
}
@Override
public int updateOneState(String asMmcode, String newState) {
return dayAnswerMapper.updateOneState(asMmcode, newState);
}
@Override
public void downloadExcel(DayAnswerDto.Request.Search dto,
HttpServletResponse response) throws Exception {
// 페이징 없이 전체 조회 (엑셀용 쿼리)
List<DayAnswerDto.Response.cpMain> list =
dayAnswerMapper.selectAllDayAnswerForExcel(dto);
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("일별답변결과");
int rowNo = 0;
// 헤더
Row header = sheet.createRow(rowNo++);
header.createCell(0).setCellValue("메인코드");
header.createCell(1).setCellValue("시군구코드");
header.createCell(2).setCellValue("구분");
header.createCell(3).setCellValue("접수일자");
header.createCell(4).setCellValue("접수번호");
header.createCell(5).setCellValue("처리자");
header.createCell(6).setCellValue("전화번호");
header.createCell(7).setCellValue("휴대폰");
header.createCell(8).setCellValue("이메일");
header.createCell(9).setCellValue("처리상태");
header.createCell(10).setCellValue("답변내용");
// 데이터
for (DayAnswerDto.Response.cpMain rowData : list) {
Row row = sheet.createRow(rowNo++);
row.createCell(0).setCellValue(nvl(rowData.getAsMmcode()));
row.createCell(1).setCellValue(nvl(rowData.getAsSggcode()));
row.createCell(2).setCellValue(nvl(rowData.getAsIngb()));
row.createCell(3).setCellValue(nvl(rowData.getAsJsdate()));
row.createCell(4).setCellValue(nvl(rowData.getAsJsno()));
row.createCell(5).setCellValue(nvl(rowData.getAsUser()));
row.createCell(6).setCellValue(nvl(rowData.getAsTel()));
row.createCell(7).setCellValue(nvl(rowData.getAsCell()));
row.createCell(8).setCellValue(nvl(rowData.getAsEmail()));
row.createCell(9).setCellValue(nvl(rowData.getAsState()));
row.createCell(10).setCellValue(nvl(rowData.getAsText()));
}
for (int i = 0; i <= 10; i++) {
sheet.autoSizeColumn(i);
}
String fileName = URLEncoder.encode("일별답변결과.xlsx", StandardCharsets.UTF_8.name())
.replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition",
"attachment; filename=\"" + fileName + "\"");
wb.write(response.getOutputStream());
wb.close();
}
private String nvl(String s) {
return s == null ? "" : s;
}
}

@ -0,0 +1,50 @@
package go.kr.project.biz.search.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto;
import go.kr.project.biz.search.model.SearchDto;
import go.kr.project.biz.search.service.SearchService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Controller
@Slf4j
@RequiredArgsConstructor
public class SearchController {
private final SearchService searchService;
@GetMapping("/search/search.do")
public String searchPageReturn () {
return "biz/search/search" + TilesConstants.BASE;
}
@PostMapping("/search/search-select.ajax")
public ResponseEntity<?> list(@ModelAttribute SearchDto.Request.Search dto) {
dto.setTotalCount(0);
dto.setPagingYn("N");
List<SearchDto.Response.cpMain> result = searchService.selectAllSearch(dto);
return ApiResponseUtil.successWithGrid(result, dto);
}
}

@ -0,0 +1,14 @@
package go.kr.project.biz.search.mapper;
import go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto;
import go.kr.project.biz.search.model.SearchDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface SearchMapper {
List<SearchDto.Response.cpMain> selectAllSearch(SearchDto.Request.Search dto);
}

@ -0,0 +1,41 @@
package go.kr.project.biz.search.model;
import go.kr.project.system.common.model.PagingVO;
import lombok.Getter;
import lombok.Setter;
public class SearchDto {
public static class Request {
@Getter
@Setter
public static class Search extends PagingVO {
private String searchCondition;
private String searchKeyword;
private String searchStartDt;
private String searchEndDt;
private String worker;
}
}
public static class Response {
@Getter
@Setter
public static class cpMain {
private String mmIngb;
private String mmDate;
private String mmCarno;
private String omJno;
private String omName;
private String mmKeum2;
private String mmImageGb;
private String mmImageCnt;
private String mmCarcheck;
private String mmCode;
}
}
}

@ -0,0 +1,9 @@
package go.kr.project.biz.search.service;
import go.kr.project.biz.search.model.SearchDto;
import java.util.List;
public interface SearchService {
List<SearchDto.Response.cpMain> selectAllSearch(SearchDto.Request.Search dto);
}

@ -0,0 +1,28 @@
package go.kr.project.biz.search.service.impl;
import go.kr.project.biz.search.mapper.SearchMapper;
import go.kr.project.biz.search.model.SearchDto;
import go.kr.project.biz.search.service.SearchService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
@Slf4j
public class SearchServiceImpl extends EgovAbstractServiceImpl implements SearchService {
private final SearchMapper searchMapper;
@Override
public List<SearchDto.Response.cpMain> selectAllSearch(SearchDto.Request.Search dto){
List<SearchDto.Response.cpMain> list = searchMapper.selectAllSearch(dto);
return list;
}
}

@ -10,62 +10,299 @@
resultType은 쿼리 결과를 반납하는 객체를 넣어준다.
아래 보면 이너클래스는 $형태로 들어간다.
-->
<select id="selectAllDayAnswer"
parameterType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Request$Search"
resultType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Response$cpMain">
select *
from cp_answer
<!-- left outer join cp_answer CA on(cm.mm_code = ca.as_mmcode)-->
<!-- 목록 조회 -->
<select id="selectAllDayAnswer"
parameterType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Request$Search"
resultType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Response$cpMain">
SELECT
AS_MMCODE,
AS_SGGCODE,
AS_INGB,
DATE_FORMAT(AS_JSDATE,'%Y-%m-%d') AS asJsdate,
AS_JSNO,
AS_JSNO_M,
AS_BBS_NO,
DATE_FORMAT(AS_LIMIT_DT,'%Y-%m-%d') AS asLimitDt,
AS_USER,
AS_TEL,
AS_CELL,
AS_EMAIL,
AS_STATE,
AS_POST_CD,
AS_POST_DT,
DATE_FORMAT(AS_STATE_DT, '%Y-%m-%d %H:%i:%s') AS asStateDt,
AS_TEXT,
AS_REUSER,
AS_INLINE,
AS_SYS_GUBUN_C,
AS_PETI_ANC_CODE_V,
AS_PETI_NO_C,
DATE_FORMAT(
STR_TO_DATE(CONCAT(M.MM_DATE, M.MM_TIME), '%Y%m%d%H%i%s'),
'%Y-%m-%d %H:%i:%s' ) AS mmDate,
MM_CARNO,
CC_CAUSE,
MM_CODE
FROM CP_ANSWER A
JOIN CP_MAIN M ON A.AS_MMCODE = M.MM_CODE
JOIN CP_OWNER O ON M.MM_OMCODE = O.OM_CODE
LEFT JOIN CP_CANCEL C ON M.MM_CODE = C.CC_MMCODE
<where>
<if test="searchStartDt != null and searchStartDt != ''">
AND as_jsdate &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND as_jsdate &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
<!-- 탭 상태 필터 -->
<if test="tabState != null and tabState != ''">
AND
<choose>
<when test="tabState == 'FIN_BU'">
AS_STATE = '6'
</when>
<when test="tabState == 'FIN_GE'">
AS_STATE = '7'
</when>
<when test="tabState == 'FIN_ME'">
AS_STATE IN ('8')
</when>
<when test="tabState == 'FIN_ADD'">
AS_STATE IN ('9')
</when>
<when test="tabState == 'FAIL'">
AS_STATE = '5'
</when>
<when test="tabState == 'INCOMP'">
AS_STATE IN ('A','B')
</when>
</choose>
</if>
<!-- 날짜 -->
<if test="searchStartDt != null and searchStartDt != ''">
AND as_jsdate &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND as_jsdate &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
<!-- 검색구분 + 검색어 -->
<choose>
<!-- 접수번호 -->
<when test="searchCondition == 'title' and searchKeyword != null and searchKeyword != ''">
AND as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<!-- 처리자명 -->
<when test="searchCondition == 'contents' and searchKeyword != null and searchKeyword != ''">
AND as_user LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<!-- 전화번호 -->
<when test="searchCondition == 'writer' and searchKeyword != null and searchKeyword != ''">
AND REPLACE(as_tel, '-', '') LIKE CONCAT('%', REPLACE(#{searchKeyword}, '-', ''), '%')
</when>
<!-- 검색구분 없이 검색어만 있는 경우 -->
<otherwise>
<if test="searchKeyword != null and searchKeyword != ''">
AND (
as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_user LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_tel LIKE CONCAT('%', #{searchKeyword}, '%')
)
</if>
</otherwise>
</choose>
</where>
ORDER BY AS_JSDATE DESC, AS_JSNO DESC
<!-- &lt;!&ndash; startIndex, perPage 둘 다 있을 때만 LIMIT &ndash;&gt;-->
<!-- <if test="startIndex != null and perPage != null">-->
<!-- LIMIT #{startIndex}, #{perPage}-->
<!-- </if>-->
</select>
<!-- 전체 건수 조회 -->
<select id="selectAllDayAnswerCount"
parameterType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Request$Search"
resultType="int">
SELECT
AS_MMCODE,
AS_SGGCODE,
AS_INGB,
DATE_FORMAT(AS_JSDATE,'%Y-%m-%d') AS asJsdate,
AS_JSNO,
AS_JSNO_M,
AS_BBS_NO,
DATE_FORMAT(AS_LIMIT_DT,'%Y-%m-%d') AS asLimitDt,
AS_USER,
AS_TEL,
AS_CELL,
AS_EMAIL,
AS_STATE,
AS_POST_CD,
AS_POST_DT,
DATE_FORMAT(AS_STATE_DT, '%Y-%m-%d %H:%i:%s') AS asStateDt,
AS_TEXT,
AS_REUSER,
AS_INLINE,
AS_SYS_GUBUN_C,
AS_PETI_ANC_CODE_V,
AS_PETI_NO_C,
DATE_FORMAT(
STR_TO_DATE(CONCAT(M.MM_DATE, M.MM_TIME), '%Y%m%d%H%i%s'),
'%Y-%m-%d %H:%i:%s' ) AS mmDate,
MM_CARNO,
CC_CAUSE,
MM_CODE
FROM CP_ANSWER A
JOIN CP_MAIN M ON A.AS_MMCODE = M.MM_CODE
JOIN CP_OWNER O ON M.MM_OMCODE = O.OM_CODE
LEFT JOIN CP_CANCEL C ON M.MM_CODE = C.CC_MMCODE
<where>
<if test="tabState != null and tabState != ''">
AND
<choose>
<when test="tabState == 'FIN_BU'">
AS_STATE = '6'
</when>
<when test="tabState == 'FIN_GE'">
AS_STATE = '7'
</when>
<when test="tabState == 'FIN_ME'">
AS_STATE IN ('8')
</when>
<when test="tabState == 'FIN_ADD'">
AS_STATE IN ('9')
</when>
<when test="tabState == 'FAIL'">
AS_STATE = '5'
</when>
<when test="tabState == 'INCOMP'">
AS_STATE IN ('A','B')
</when>
</choose>
</if>
<if test="searchStartDt != null and searchStartDt != ''">
AND as_jsdate &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND as_jsdate &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
<choose>
<!-- 접수번호 -->
<when test="searchCondition == 'title' and searchKeyword != null and searchKeyword != ''">
AND as_Jsno LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<choose>
<when test="searchCondition == 'title' and searchKeyword != null and searchKeyword != ''">
AND as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'contents' and searchKeyword != null and searchKeyword != ''">
AND as_user LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'writer' and searchKeyword != null and searchKeyword != ''">
AND REPLACE(as_tel, '-', '') LIKE CONCAT('%', REPLACE(#{searchKeyword}, '-', ''), '%')
</when>
<otherwise>
<if test="searchKeyword != null and searchKeyword != ''">
AND (
as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_user LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_tel LIKE CONCAT('%', #{searchKeyword}, '%')
)
</if>
</otherwise>
</choose>
</where>
</select>
<select id="selectAllDayAnswerForExcel"
parameterType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Request$Search"
resultType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Response$cpMain">
SELECT
AS_MMCODE,
AS_SGGCODE,
AS_INGB,
AS_JSDATE,
AS_JSNO,
AS_JSNO_M,
AS_BBS_NO,
AS_LIMIT_DT,
AS_USER,
AS_TEL,
AS_CELL,
AS_EMAIL,
AS_STATE,
AS_POST_CD,
AS_POST_DT,
DATE_FORMAT(AS_STATE_DT, '%Y-%m-%d %H:%i:%s') AS AS_STATE_DT,
AS_TEXT,
AS_REUSER,
AS_INLINE,
AS_SYS_GUBUN_C,
AS_PETI_ANC_CODE_V,
AS_PETI_NO_C
FROM cp_answer
<where>
<!-- 처리자명 -->
<when test="searchCondition == 'contents' and searchKeyword != null and searchKeyword != ''">
AND as_User LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<if test="tabState != null and tabState != ''">
AND
<choose>
<when test="tabState == 'FIN_BU'">
AS_STATE = '6'
</when>
<when test="tabState == 'FIN_GE'">
AS_STATE = '7'
</when>
<when test="tabState == 'FIN_ME'">
AS_STATE IN ('8')
</when>
<when test="tabState == 'FIN_ADD'">
AS_STATE IN ('9')
</when>
<when test="tabState == 'FAIL'">
AS_STATE = '5'
</when>
<when test="tabState == 'INCOMP'">
AS_STATE IN ('A','B')
</when>
</choose>
</if>
<!-- 전화번호: 컬럼/입력 하이픈 제거 후 비교 -->
<when test="searchCondition == 'writer' and searchKeyword != null and searchKeyword != ''">
AND REPLACE(as_Tel, '-', '') LIKE CONCAT('%', REPLACE(#{searchKeyword}, '-', ''), '%')
</when>
<!-- 검색구분 비어 있고 키워드만 있는 경우 -->
<otherwise>
<if test="searchKeyword != null and searchKeyword != ''">
AND (
as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_user LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_tel LIKE CONCAT('%', #{searchKeyword}, '%')
)
<if test="searchStartDt != null and searchStartDt != ''">
AND as_jsdate &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND as_jsdate &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
</otherwise>
</choose>
</where>
<choose>
<when test="searchCondition == 'title' and searchKeyword != null and searchKeyword != ''">
AND as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'contents' and searchKeyword != null and searchKeyword != ''">
AND as_user LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'writer' and searchKeyword != null and searchKeyword != ''">
AND REPLACE(as_tel, '-', '') LIKE CONCAT('%', REPLACE(#{searchKeyword}, '-', ''), '%')
</when>
<otherwise>
<if test="searchKeyword != null and searchKeyword != ''">
AND (
as_jsno LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_user LIKE CONCAT('%', #{searchKeyword}, '%')
OR as_tel LIKE CONCAT('%', #{searchKeyword}, '%')
)
</if>
</otherwise>
</choose>
</where>
</select>
<select id="selectOneByasMmcode" parameterType="string" resultType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Response$cpMain">
select
AS_MMCODE asMmcode,
AS_SGGCODE asSggcode,
AS_INGB asIngb,
AS_JSDATE asJsdate,
AS_JSNO asJsno,
AS_BBS_NO asBbsNo,
AS_LIMIT_DT asLimitDt,
AS_USER asUser,
AS_TEL asTel,
AS_CELL asCell,
AS_EMAIL asEmail,
AS_TEXT asText
AS_MMCODE ,
AS_SGGCODE ,
AS_INGB ,
AS_JSDATE ,
AS_JSNO ,
AS_BBS_NO ,
AS_LIMIT_DT ,
AS_USER ,
AS_TEL ,
AS_CELL ,
AS_EMAIL ,
AS_TEXT
from cp_answer
<!-- left outer join cp_answer CA on(cm.mm_code = ca.as_mmcode) -->
WHERE AS_MMCODE = #{asMmcode}
@ -101,13 +338,41 @@
resultType="go.kr.project.biz.minwon.dayanswer.model.DayAnswerDto$Response$History">
SELECT
AS_MMCODE asMmcode,
AS_TEXT asText,
AS_USER asUser,
AS_STATE asState,
AS_MMCODE ,
AS_TEXT ,
AS_USER ,
AS_STATE ,
DATE_FORMAT(UPDATE_DT, '%Y-%m-%d %H:%i:%s') as updateDt
FROM cp_answer_history
WHERE AS_MMCODE = #{asMmcode}
ORDER BY UPDATE_DT DESC
</select>
<update id="updateAllState">
UPDATE cp_answer
SET AS_STATE = #{newState}
WHERE 1 = 1
<if test="vo.searchCondition != null and vo.searchKeyword != null and vo.searchKeyword != ''">
AND
<choose>
<when test="vo.searchCondition == 'title'">
AS_JSNO LIKE CONCAT('%', #{vo.searchKeyword}, '%')
</when>
<when test="vo.searchCondition == 'contents'">
AS_REUSER LIKE CONCAT('%', #{vo.searchKeyword}, '%')
</when>
</choose>
</if>
<if test="vo.searchStartDt != null and vo.searchStartDt != ''">
AND AS_JSDATE &gt;= #{vo.searchStartDt}
</if>
<if test="vo.searchEndDt != null and vo.searchEndDt != ''">
AND AS_JSDATE &lt;= #{vo.searchEndDt}
</if>
</update>
<update id="updateOneState">
UPDATE cp_answer
SET AS_STATE = #{newState}
WHERE AS_MMCODE = #{asMmcode}
</update>
</mapper>

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="go.kr.project.biz.search.mapper.SearchMapper">
<select id="selectAllSearch"
parameterType="go.kr.project.biz.search.model.SearchDto$Request$Search"
resultType="go.kr.project.biz.search.model.SearchDto$Response$cpMain">
SELECT M.MM_INGB,
DATE_FORMAT(
STR_TO_DATE(CONCAT(M.MM_DATE, M.MM_TIME), '%Y%m%d%H%i%s'),
'%Y-%m-%d %H:%i:%s' ) AS mmDate,
M.MM_CARNO,
O.OM_JNO,
O.OM_NAME,
M.MM_KEUM2,
M.MM_IMAGEGB,
M.MM_IMAGECNT,
M.MM_CARCHECK,
M.MM_STATE,
M.MM_CODE
FROM CP_MAIN M
LEFT OUTER JOIN CP_ANSWER A ON M.MM_CODE = AS_MMCODE
LEFT OUTER JOIN CP_CANCEL C ON M.MM_CODE=CC_MMCODE
JOIN CP_OWNER O ON M.MM_OMCODE=O.OM_CODE
<where>
<!-- 날짜 -->
<if test="searchStartDt != null and searchStartDt != ''">
AND as_jsdate &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND as_jsdate &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
<!-- 검색구분 + 검색어 -->
<choose>
<!-- 차량번호 -->
<when test="searchCondition == 'title' and searchKeyword != null and searchKeyword != ''">
AND MM_CARNO LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<!-- 소유자 -->
<when test="searchCondition == 'contents' and searchKeyword != null and searchKeyword != ''">
AND OM_NAME LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<!-- 주민번호 -->
<when test="searchCondition == 'writer' and searchKeyword != null and searchKeyword != ''">
AND OM_JNO LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<!-- 코드 -->
<when test="searchCondition == 'code' and searchKeyword != null and searchKeyword != ''">
AND MM_CODE LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<!-- 검색구분 없이 검색어만 있는 경우 -->
<otherwise>
<if test="searchKeyword != null and searchKeyword != ''">
AND (
MM_CARNO LIKE CONCAT('%', #{searchKeyword}, '%')
OR OM_NAME LIKE CONCAT('%', #{searchKeyword}, '%')
OR OM_JNO LIKE CONCAT('%', #{searchKeyword}, '%')
OR MM_CODE LIKE CONCAT('%', #{searchKeyword}, '%')
)
</if>
</otherwise>
</choose>
</where>
ORDER BY AS_JSDATE DESC, AS_JSNO DESC
</select>
</mapper>

@ -11,7 +11,6 @@
</section>
</div>
</section>
<input type="text" id="bbs_no">
<div class="contants_body">
<div class="gs_b_top">
<ul class="lef">
@ -22,6 +21,7 @@
<option value="title" <c:if test="${paramVO.searchCondition eq 'title'}">selected</c:if>>접수번호</option>
<option value="contents" <c:if test="${paramVO.searchCondition eq 'contents'}">selected</c:if>>처리자명</option>
<option value="writer" <c:if test="${paramVO.searchCondition eq 'writer'}">selected</c:if>>전화번호</option>
<input type="hidden" id="tabState" name="tabState" value=""/>
</select>
</li>
<li class="th">검색어</li>
@ -33,7 +33,6 @@
</li>
<li>
<button type="button" id="search_btn" class="newbtnss bg1">검색</button>
<button type="button" id="btnAdd" class="newbtnss bg1">자료등록</button>
<button type="button" id="btnExcel" class="newbtnss bg1">엑셀다운로드</button>
</li>
@ -42,13 +41,78 @@
<li>
<select id="perPageSelect" class="input">
<option value="10" <c:if test="${param.perPage eq '10'}">selected</c:if>>페이지당 10</option>
<option value="20" <c:if test="${param.perPage eq '20'}">selected</c:if>>페이지당 20</option>
<option value="30" <c:if test="${param.perPage eq '30'}">selected</c:if>>페이지당 30</option>
<option value="30" <c:if test="${empty param.perPage or param.perPage eq '30'}">selected</c:if>>페이지당 30</option>
<option value="100" <c:if test="${param.perPage eq '100'}">selected</c:if>>페이지당 100</option>
</select>
<span class="page_number"><span id="currentPage"></span><span class="bar">/</span><sapn id="totalPages"></sapn> Pages</span>
</li>
</ul>
</div>
<div class="state-tab-wrap">
<ul class="state-tabs">
<li class="on" data-state="">전체</li>
<li data-state="FIN_BU" value="6">답변완료(부과)</li>
<li data-state="FIN_GE" value="7">답변완료(계도)</li>
<li data-state="FIN_ME" value="8">답변완료(미부과)</li>
<li data-state="FIN_ADD" value="9">답변완료(수기)</li>
<li data-state="FAIL" value="5">답변실패</li>
<li data-state="INCOMP" value="fail">답변미대상</li>
</ul>
</div>
<style>
.state-tab-wrap {
margin: 10px 0;
}
.state-tabs {
list-style: none;
padding: 0;
margin: 0;
display: flex;
}
.state-tabs li {
padding: 6px 14px;
border: 1px solid #ccc;
border-bottom: none;
background: #f5f5f5;
font-size: 12px;
cursor: pointer;
margin-right: 4px;
}
.state-tabs li.on {
background: #ffffff;
font-weight: bold;
border-bottom: 1px solid #ffffff;
}
.state-area {
margin-top: 10px;
padding: 10px 0;
display: flex;
align-items: center;
gap: 10px;
}
.state-label {
font-weight: bold;
margin-right: 5px;
white-space: nowrap;
}
.state-input {
width: 120px;
height: 28px;
padding: 4px;
border: 1px solid #ccc;
}
.state-area button {
height: 32px;
padding: 0 12px;
}
</style>
<div class="gs_booking">
<div class="row">
<div class="col-sm-12">
@ -60,429 +124,324 @@
</div>
</div>
</div>
<div class="gs_booking">
</div>
<div class="state-area">
<label class="state-label">새처리상태값</label>
<input type="text" id="newStateValue" class="state-input">
<button type="button" id="btnAllChange" class="newbtnss bg1">전체 답변상태변경</button>
<button type="button" id="btnOneChange" class="newbtnss bg1">1개 답변상태변경</button>
<button type="button" id="btncdmake" class="newbtnss bg1">표지정보조회 CD 만들기</button>
</div>
<div class="status-right">
<span id="statusSummary">
초기 0, 대기 1, 대상(부과) 2, 대상(계도) 3, 대상(서손) 4, 실패 5,
완료(부과) 6, 완료(계도) 7, 완료(서손) 8, 완료(수기) 9, 미대상 A, 미대상(서손) B
</span>
</div>
</div>
</div>
</div>
<!-- /Main body -->
<script type="text/javascript">
/**
* 게시판 목록 관리 모듈
* 게시판 목록을 조회하고 관리하는 기능을 제공합니다.
*/
(function(window, $) {
'use strict';
var SEARCH_COND = {};
// 검색정보 셋팅
var setSearchCond = function() {
var searchCondition = $.trim(nvl($("#searchCondition").val(), ""));
var searchKeyword = $.trim(nvl($("#searchKeyword").val(), ""));
var searchUseYn = $.trim(nvl($("#searchUseYn").val(), ""));
var searchStartDt = $.trim(nvl($("#searchStartDt").val(), ""));
var searchEndDt = $.trim(nvl($("#searchEndDt").val(), ""));
SEARCH_COND.searchCondition = searchCondition;
SEARCH_COND.searchKeyword = searchKeyword;
SEARCH_COND.searchUseYn = searchUseYn;
SEARCH_COND.searchStartDt = searchStartDt;
SEARCH_COND.searchEndDt = searchEndDt;
};
/**
* 게시판 목록 관리 네임스페이스
*/
var NoticeList = {
/**
* 그리드 관련 객체
*/
grid: {
/**
* 그리드 인스턴스
*/
instance: null,
/**
* 그리드 설정 초기화
* @returns {Object} 그리드 설정 객체
*/
initConfig: function() {
// 데이터 소스 설정
var dataSource = this.createDataSource();
// 현재 선택된 perPage 값 가져오기
var perPage = parseInt($('#perPageSelect').val() || 10, 10);
// 그리드 설정 객체 생성
var gridConfig = new XitTuiGridConfig();
// 기본 설정
gridConfig.setOptDataSource(dataSource); // 데이터소스 연결
gridConfig.setOptGridId('grid'); // 그리드를 출력할 Element ID
gridConfig.setOptGridHeight(390); // 그리드 높이(단위: px)
gridConfig.setOptRowHeight(30); // 그리드 행 높이(단위: px)
gridConfig.setOptRowHeaderType('checkbox'); // 행 첫번째 셀 타입(rowNum: 순번, checkbox: 체크박스, '': 출력 안함)
// 페이징 옵션 설정
gridConfig.setOptPageOptions({
useClient: false, // 클라이언트 페이징 여부(false: 서버 페이징)
perPage: perPage // 페이지당 표시 건수
});
gridConfig.setOptUseClientSort(false); // 서버사이드 정렬 false
// 컬럼 정보 설정
gridConfig.setOptColumns([
{
header: 'asMmcode',
name: 'asMmcode',
width: 50,
align: 'center'
},
{
header: 'asSggcode',
name: 'asSggcode',
width: 70,
align: 'center'
},
{
header: 'asIngb',
name: 'asIngb',
width: 100,
align: 'center'
},
{
header: 'asJsdate',
name: 'asJsdate',
width: 100,
align: 'center'
},
{
header: 'asJsno',
name: 'asJsno',
width: 150,
align: 'center'
},
{
header: 'asJsnoM',
name: 'asJsnoM',
width: 70,
align: 'center'
},
{
header: 'asBbsNo',
name: 'asBbsNo',
width: 70,
align: 'center'
},
{
header: 'asLimitDt',
name: 'asLimitDt',
width: 150,
align: 'center'
},
{
header: 'asUser',
name: 'asUser',
width: 150,
align: 'center'
},
{
header: 'asTel',
name: 'asTel',
width: 50,
align: 'center'
},
{
header: 'asCell',
name: 'asCell',
width: 250,
align: 'center'
},
{
header: 'asEmail',
name: 'asEmail',
width: 150,
align: 'center'
},
{
header: 'asState',
name: 'asState',
width: 150,
align: 'center'
},
{
header: 'asPostCd',
name: 'asPostCd',
width: 150,
align: 'center'
},
{
header: 'asPostDt',
name: 'asPostDt',
width: 150,
align: 'center'
},
{
header: 'asStateDt',
name: 'asStateDt',
width: 150,
align: 'center'
},
{
header: 'asText',
name: 'asText',
width: 150,
align: 'center'
},
{
header: 'asReuser',
name: 'asReuser',
width: 150,
align: 'center'
},
{
header: 'asInline',
name: 'asInline',
width: 150,
align: 'center'
},
{
header: 'asSysGubunC',
name: 'asSysGubunC',
width: 150,
align: 'center'
},
{
header: 'asPetiAncCodeV',
name: 'asPetiAncCodeV',
width: 150,
align: 'center'
},
{
header: 'asPetiNoC',
name: 'asPetiNoC',
width: 150,
align: 'center'
}
]);
return gridConfig;
},
/**
* 데이터 소스 생성
* @returns {Object} 데이터 소스 객체
*/
createDataSource: function() {
return {
api: {
readData: {
url: '<c:url value="/minwon/dayanswer/dayanswer-select.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: false,
serializer: function (params) {
setSearchCond();
SEARCH_COND.perPage = params.perPage;
SEARCH_COND.page = params.page;
return $.param(SEARCH_COND);
}
};
},
/**
* 그리드 인스턴스 생성
*/
create: function() {
var gridConfig = this.initConfig();
var Grid = tui.Grid;
this.instance = gridConfig.instance(Grid);
// 그리드 테마 설정
Grid.applyTheme('striped');
// 그리드 이벤트 설정
this.gridBindEvents();
},
/**
* 그리드 이벤트 바인딩
*/
gridBindEvents: function() {
var self = this;
// 요청 성공 시 총 건수 표시
this.instance.on('successResponse', function(ev) {
var responseObj = JSON.parse(ev.xhr.response);
//$('.totCnt').text(responseObj.data.pagination.totalCount);
$("#currentPage").text(responseObj.data.pagination.page);
$("#totalPages").text(responseObj.data.pagination.totalPages);
});
this.instance.on('dblclick', function (ev) {
if (ev.rowKey === undefined) {
return;
}
var rowData = self.instance.getRow(ev.rowKey);
if (!rowData) {
return;
}
var asMmcode = rowData.asMmcode;
console.log("더블클릭 asMmcode =", asMmcode);
if (!asMmcode) {
alert("선택한 행에 asMmcode 값이 없습니다.");
return;
}
var popUrl = '<c:url value="/minwon/dayanswer/dayanswertotalPop.do"/>'
+ '?asMmcode=' + encodeURIComponent(asMmcode);
console.log("팝업 URL =", popUrl);
var popTitle = "상세정보";
var popOption = "width=1100,height=700,resizable=yes,scrollbars=yes,location=no,top=100,left=100";
window.open(popUrl, popTitle, popOption);
});
$('#btnAdd').on('click', function() {
const popUrl = '${pageContext.request.contextPath}/minwon/dayanswer/dayanswerregister.do';
const popTitle = '자료 등록';
const popOption = 'width=700,height=600,resizable=yes,scrollbars=yes';
window.open(popUrl, popTitle, popOption);
});
let INIT_POPUP = null;
let SEARCH_COND = {};
let GRID = null;
// 검색조건 세팅
let setSearchCond = function () {
let searchCondition = $.trim(nvl($("#searchCondition").val(), ""));
let searchKeyword = $.trim(nvl($("#searchKeyword").val(), ""));
let searchUseYn = $.trim(nvl($("#searchUseYn").val(), ""));
let searchStartDt = $.trim(nvl($("#searchStartDt").val(), ""));
let searchEndDt = $.trim(nvl($("#searchEndDt").val(), ""));
let tabState = $.trim(nvl($("#tabState").val(), ""));
SEARCH_COND.searchCondition = searchCondition;
SEARCH_COND.searchKeyword = searchKeyword;
SEARCH_COND.searchUseYn = searchUseYn;
SEARCH_COND.searchStartDt = searchStartDt;
SEARCH_COND.searchEndDt = searchEndDt;
SEARCH_COND.tabState = tabState;
};
const fnBiz = {
init: () => {
initGrid();
},
eventListener: () => {
// 엑셀 다운로드
$('#btnExcel').on('click', function () {
const params = $.param({
searchCondition: $('#searchCondition').val(),
searchKeyword: $('#searchKeyword').val(),
searchStartDt: $('#searchStartDt').val(),
searchEndDt: $('#searchEndDt').val()
});
const url = '${pageContext.request.contextPath}/minwon/dayanswer/dayanswer-excel.do?' + params;
window.location.href = url;
});
// 전체 상태 변경
$('#btnAllChange').on('click', function () {
const newState = $.trim($('#newStateValue').val());
if (!GRID) {
alert('그리드가 아직 초기화되지 않았습니다.');
return;
}
},
/**
* 이벤트 핸들러 설정
*/
eventBindEvents: function(e) {
const checkedRowKeys = GRID.getCheckedRowKeys();
if (checkedRowKeys.length > 0) {
alert('체크된 행이 있습니다.\n전체 답변상태변경은 체크를 모두 해제한 상태에서만 가능합니다.\n' +
'한 개만 수정하려면 [1개 답변상태변경] 버튼을 사용해주세요.');
return;
}
if (!newState) {
alert('새 처리상태값을 입력하세요.');
return;
}
var self = this;
if (!confirm('현재 조회된 모든 건의 처리상태를 [' + newState + '] 로 변경하시겠습니까?')) {
return;
}
$('#btnExcel').on('click', function() {
// 지금 화면의 검색조건 그대로 가져오기
const params = $.param({
$.ajax({
url: '<c:url value="/minwon/dayanswer/update-all-state.ajax"/>',
type: 'POST',
data: {
newState: newState,
searchCondition: $('#searchCondition').val(),
searchKeyword: $('#searchKeyword').val(),
searchStartDt: $('#searchStartDt').val(),
searchEndDt: $('#searchEndDt').val()
});
searchKeyword: $('#searchKeyword').val(),
searchStartDt: $('#searchStartDt').val(),
searchEndDt: $('#searchEndDt').val()
},
success: function () {
alert('전체 답변상태가 변경되었습니다.');
const currentPage = GRID.getPagination()._currentPage || 1;
GRID.readData(currentPage);
},
error: function () {
alert('상태 변경 중 오류가 발생했습니다.');
}
});
});
const url = '${pageContext.request.contextPath}/minwon/dayanswer/dayanswer-excel.do?' + params;
console.log("엑셀 다운로드 URL:", url);
// 한 건 상태 변경
$('#btnOneChange').on('click', function () {
const newState = $.trim($('#newStateValue').val());
window.location.href = url;
});
// 검색 버튼 클릭 이벤트
$('#search_btn').on('click', function() {
if (!newState) {
alert('새 처리상태값을 입력하세요.');
return;
}
if (!GRID) {
alert('그리드가 아직 초기화되지 않았습니다.');
return;
}
SEARCH_COND = {};
// 등록일 from~to 유효성 검사
var startDate = $("#searchStartDt").val().trim();
var endDate = $("#searchEndDt").val().trim();
const checkedRowKeys = GRID.getCheckedRowKeys();
// 시작일과 종료일 중 하나만 입력된 경우 체크
if ((startDate && !endDate) || (!startDate && endDate)) {
alert("등록일 검색 시 시작일과 종료일을 모두 입력해주세요.");
return;
}
if (checkedRowKeys.length === 0) {
alert('상태를 변경할 행을 1개 선택하세요.');
return;
}
if (checkedRowKeys.length > 1) {
alert('1개 답변상태변경은 한 행만 선택할 수 있습니다.');
return;
}
const rowData = GRID.getRow(checkedRowKeys[0]);
if (!rowData) {
alert('선택된 행 정보를 가져올 수 없습니다.');
return;
}
const asMmcode = rowData.asMmcode;
// 시작일과 종료일이 모두 입력된 경우 유효성 검사
if (startDate && endDate) {
if (!isDate(startDate) || !isDate(endDate)) {
alert("유효한 날짜 형식이 아닙니다. (YYYY-MM-DD)");
return;
}
// 시작일이 종료일보다 늦은 경우 체크
var startDateObj = new Date(startDate);
var endDateObj = new Date(endDate);
if (startDateObj > endDateObj) {
alert("시작일은 종료일보다 이후일 수 없습니다.");
return;
}
if (!confirm('선택한 건의 상태를 [' + newState + '] 로 변경하시겠습니까?')) {
return;
}
$.ajax({
url: '<c:url value="/minwon/dayanswer/update-one-state.ajax"/>',
type: 'POST',
data: {
asMmcode: asMmcode,
newState: newState
},
success: function () {
alert('선택한 답변 상태가 변경되었습니다.');
const currentPage = GRID.getPagination()._currentPage || 1;
GRID.readData(currentPage);
},
error: function () {
alert('상태 변경 중 오류가 발생했습니다.');
}
// 페이지를 1로 리셋
$("#page").val(1);
// 그리드 데이터 리로드
self.grid.instance.readData(1);
});
});
// 검색어 입력 필드에서 엔터키 이벤트 처리
$('#searchKeyword').on('keypress', function(e) {
if (e.which === 13) { // 엔터키 코드는 13
e.preventDefault(); // 기본 이벤트 방지
$('#search_btn').trigger('click'); // 검색 버튼 클릭 이벤트 트리거
// 검색 버튼
$('#search_btn').on('click', function () {
let startDate = $("#searchStartDt").val();
let endDate = $("#searchEndDt").val();
if ((startDate && !endDate) || (!startDate && endDate)) {
alert("등록일 검색 시 시작일과 종료일을 모두 입력해주세요.");
return;
}
if (startDate && endDate) {
if (!isDate(startDate) || !isDate(endDate)) {
alert("유효한 날짜 형식이 아닙니다. (YYYY-MM-DD)");
return;
}
});
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
if (startDateObj > endDateObj) {
alert("시작일은 종료일보다 이후일 수 없습니다.");
return;
}
}
// perPage 변경 이벤트 추가
$('#perPageSelect').on('change', function() {
var perPage = parseInt($(this).val(), 10);
// Grid의 perPage 설정 변경 및 데이터 리로드
self.grid.instance.setPerPage(perPage);
});
$("#page").val(1);
GRID.readData(1);
});
// 검색어 엔터
$('#searchKeyword').on('keypress', function (e) {
if (e.which === 13) {
e.preventDefault();
$('#search_btn').trigger('click');
}
});
// perPage 변경 이벤트 추가
$('#perPageSelect').on('change', () => {
const pagination = TuiGrid.instance.getPagination();
if (!pagination) return;
pagination.setItemsPerPage($('#perPageSelect').val());
pagination.reset(TuiGrid.instance.getRowCount());
pagination.movePageTo(1);
});
// 상태 탭 클릭
$('.state-tabs li').on('click', function (e) {
$('.state-tabs li').removeClass('on');
$(this).addClass('on');
const state = $(this).data('state') || '';
$('#tabState').val(state);
SEARCH_COND = {};
GRID.readData(1);
});
}
};
/** tui-grid Set */
const initGrid = () => {
const gridColumns = [
{ header: '답변일시', name: 'asPostDt', width: 150, align: 'center' },
{ header: '번호', name: 'asBbsNo', width: 150, align: 'center' },
{ header: '신청자', name: 'asUser', width: 150, align: 'center' },
{ header: '접수일자', name: 'asJsdate', width: 150, align: 'center' },
{ header: '처리기한', name: 'asLimitDt',width: 150, align: 'center' },
{ header: '위반일자', name: 'mmDate', width: 150, align: 'center' },
{ header: '접수번호', name: 'asJsno', width: 150, align: 'center' },
{ header: '차량번호', name: 'mmCarno', width: 150, align: 'center' },
{ header: '미부과사유',name: 'ccCause', width: 150, align: 'center' },
{ header: '처리상태', name: 'asState', width: 150, align: 'center' },
{ header: 'mmCode', name: 'mmCode', sortable: true, width: 150, align: 'center', hidden: true}
];
const gridDatasource = {
api: {
readData: {
url: '<c:url value="/minwon/dayanswer/dayanswer-select.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
/**
* 모듈 초기화
*/
init: function() {
initialRequest: false, // 직접 readData(1) 호출할 거라 false
serializer: function (params) {
setSearchCond();
SEARCH_COND.perPage = params.perPage;
SEARCH_COND.page = params.page;
// 그리드 생성
this.grid.create();
return $.param(SEARCH_COND);
}
};
// 이벤트 핸들러 설정
this.eventBindEvents();
const perPage = parseInt($('#perPageSelect').val() || 10, 10);
this.grid.instance.readData(${param.page eq null or param.page eq 0 ? 1 : param.page});
const gridOptions = {
el: 'grid',
rowHeaders: ['checkbox'],
columns: gridColumns,
noData: "처리 할 초기자료가 없습니다.",
pageOptions: {
useClient: true,
perPage: perPage
}
};
// 페이지 로드 시 초기화
$(function() {
NoticeList.init();
// $.ajax({
// url: "http://localhost:8080/postman/test",
// type: 'POST',
// contentType: 'application/json',
// data: JSON.stringify({
// aaa: "111",
// bbb: "222",
// ccc: "333"
// }), // 비어 있어도 {}
// success: function(response) {
// console.log(response);
// $("#bbs_no").val(response.asBbsNo);
// console.log($("#bbs_no").val());
//
//
// },
// error: function(xhr, status, error) {
// // 에러 처리는 xit-common.js의 ajaxError에서 처리됨
// }
// });
// 실제 GRID 생성
GRID = TuiGrid.of(gridOptions, gridDatasource, (res) => {
// 서버 응답 후 페이지 정보 세팅
const data = res.data || {};
if (data.pagination) {
$("#currentPage").text(data.pagination.page || '');
$("#totalPages").text(data.pagination.totalPages || '');
}
// 더블 클릭 이벤트
GRID.on("dblclick", (e) => {
var popUrl = '/minwon/init/init_popup.do';
var popTitle = "initPopup";
var popOption = "width=1400px, height=900px, resizable=yes, scrollbars=yes, location=no, top=100px, left=100px";
// 1) localStorage에 저장
console.log(e)
let cursor = e.instance.getValue(e.rowKey, 'mmCode');
let mmCodes = e.instance.getData().map(row => row.mmCode);
console.log(cursor);
const state = { cursor, mmCodes, savedAt: Date.now() };
localStorage.setItem('TOTAL_INFO_STATE', JSON.stringify(state));
// 2) 팝업이 없거나 닫혀 있으면 새로 열기
if (!INIT_POPUP || INIT_POPUP.closed) {
INIT_POPUP = window.open(popUrl, popTitle, popOption);
} else {
// 이미 떠 있으면 새로 안 만들고, 그 창에 포커스만 줌
INIT_POPUP.focus();
INIT_POPUP.INIT_POP_API.search();
}
});
});
// 전역 네임스페이스에 모듈 노출
window.NoticeList = NoticeList;
// 최초 1페이지 조회
GRID.readData(1);
};
// 레디펑션
$(function () {
fnBiz.init();
fnBiz.eventListener();
});
})(window, jQuery);
</script>

@ -0,0 +1,264 @@
<%--
Created by IntelliJ IDEA.
User: moong
Date: 2025-11-20
Time: 오전 10:07
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<div class="main_body">
<section id="section8" class="main_bars">
<div class="bgs-main">
<section id="section5">
<div class="sub_title"></div>
<button type="button" onclick="location.href='<c:url value='/template/noticeSample/register.do'/>'" class="newbtn bg1">등록</button>
</section>
</div>
</section>
<div class="contants_body">
<div class="gs_b_top">
<ul class="lef">
<li class="th">검색구분</li>
<li>
<select id="searchCondition" name="searchCondition" class="input">
<option value="">검색구분</option>
<option value="title" <c:if test="${paramVO.searchCondition eq 'title'}">selected</c:if>>차량번호</option>
<option value="contents" <c:if test="${paramVO.searchCondition eq 'contents'}">selected</c:if>>소유자</option>
<option value="writer" <c:if test="${paramVO.searchCondition eq 'writer'}">selected</c:if>>주민번호</option>
<option value="code" <c:if test="${paramVO.searchCondition eq 'code'}">selected</c:if>>코드</option>
</select>
</li>
<li class="th">검색어</li>
<li><input type="text" id="searchKeyword" name="searchKeyword" class="input" value="${param.searchKeyword}"/></li>
<li class="th">접수일자 지정</li>
<li>
<input type="text" id="searchStartDt" name="searchStartDt" class="input calender datepicker" value="${param.searchStartDt}" /> ~
<input type="text" id="searchEndDt" name="searchEndDt" class="input calender datepicker" value="${param.searchEndDt}" />
</li>
<li>
<button type="button" id="search_btn" class="newbtnss bg1">검색</button>
</li>
</ul>
<ul class="rig2">
<li>
<select id="perPageSelect" class="input">
<option value="10" <c:if test="${param.perPage eq '10'}">selected</c:if>>페이지당 10</option>
<option value="30" <c:if test="${empty param.perPage or param.perPage eq '30'}">selected</c:if>>페이지당 30</option>
<option value="100" <c:if test="${param.perPage eq '100'}">selected</c:if>>페이지당 100</option>
</select>
<span class="page_number"><span id="currentPage"></span><span class="bar">/</span><sapn id="totalPages"></sapn> Pages</span>
</li>
</ul>
</div>
<div class="gs_booking">
<div class="row">
<div class="col-sm-12">
<div class="box_column">
<div class="containers">
<div id="grid"></div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
let INIT_POPUP = null;
let SEARCH_COND = {};
let GRID = null;
// 검색조건 세팅
let setSearchCond = function () {
let searchCondition = $.trim(nvl($("#searchCondition").val(), ""));
let searchKeyword = $.trim(nvl($("#searchKeyword").val(), ""));
let searchUseYn = $.trim(nvl($("#searchUseYn").val(), ""));
let searchStartDt = $.trim(nvl($("#searchStartDt").val(), ""));
let searchEndDt = $.trim(nvl($("#searchEndDt").val(), ""));
SEARCH_COND.searchCondition = searchCondition;
SEARCH_COND.searchKeyword = searchKeyword;
SEARCH_COND.searchUseYn = searchUseYn;
SEARCH_COND.searchStartDt = searchStartDt;
SEARCH_COND.searchEndDt = searchEndDt;
};
const fnBiz = {
init: () => {
initGrid();
},
eventListener: () => {
// 엑셀 다운로드
$('#btnExcel').on('click', function () {
const params = $.param({
searchCondition: $('#searchCondition').val(),
searchKeyword: $('#searchKeyword').val(),
searchStartDt: $('#searchStartDt').val(),
searchEndDt: $('#searchEndDt').val()
});
const url = '${pageContext.request.contextPath}/minwon/dayanswer/dayanswer-excel.do?' + params;
window.location.href = url;
});
// 검색 버튼
$('#search_btn').on('click', function () {
let startDate = $("#searchStartDt").val();
let endDate = $("#searchEndDt").val();
if ((startDate && !endDate) || (!startDate && endDate)) {
alert("등록일 검색 시 시작일과 종료일을 모두 입력해주세요.");
return;
}
if (startDate && endDate) {
if (!isDate(startDate) || !isDate(endDate)) {
alert("유효한 날짜 형식이 아닙니다. (YYYY-MM-DD)");
return;
}
let startDateObj = new Date(startDate);
let endDateObj = new Date(endDate);
if (startDateObj > endDateObj) {
alert("시작일은 종료일보다 이후일 수 없습니다.");
return;
}
}
$("#page").val(1);
GRID.readData(1);
});
// 검색어 엔터
$('#searchKeyword').on('keypress', function (e) {
if (e.which === 13) {
e.preventDefault();
$('#search_btn').trigger('click');
}
});
// perPage 변경 이벤트 추가
$('#perPageSelect').on('change', () => {
const pagination = TuiGrid.instance.getPagination();
if (!pagination) return;
pagination.setItemsPerPage($('#perPageSelect').val());
pagination.reset(TuiGrid.instance.getRowCount());
pagination.movePageTo(1);
});
// 상태 탭 클릭
$('.state-tabs li').on('click', function () {
$('.state-tabs li').removeClass('on');
$(this).addClass('on');
const state = $(this).data('state') || '';
$('#tabState').val(state);
SEARCH_COND = {};
GRID.readData(1);
});
}
};
/** tui-grid Set */
const initGrid = () => {
const gridColumns = [
{ header: '자료출처', name: 'mmIngb', width: 150, align: 'center' },
{ header: '접수(위반)일시', name: 'mmDate', width: 150, align: 'center' },
{ header: '차량번호', name: 'mmCarno', width: 150, align: 'center' },
{ header: '주민번호', name: 'omJno', width: 150, align: 'center' },
{ header: '소유자', name: 'omName', width: 150, align: 'center' },
{ header: '잔액', name: 'mmKeum2', width: 150, align: 'center' },
{ header: '영상매체', name: 'mmImageGb', width: 150, align: 'center' },
{ header: '사진', name: 'mmImageCnt', width: 150, align: 'center' },
{ header: '차량확인', name: 'mmCarcheck', width: 150, align: 'center' },
{ header: '처리상태', name: 'mmState', width: 150, align: 'center' },
{ header: 'mmCode', name: 'mmCode', sortable: true, width: 150, align: 'center', hidden: true}
];
const gridDatasource = {
api: {
readData: {
url: '<c:url value="/search/search-select.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: false, // 직접 readData(1) 호출할 거라 false
serializer: function (params) {
setSearchCond();
SEARCH_COND.perPage = params.perPage;
SEARCH_COND.page = params.page;
return $.param(SEARCH_COND);
}
};
const perPage = parseInt($('#perPageSelect').val() || 10, 10);
const gridOptions = {
el: 'grid',
rowHeaders: ['checkbox'],
columns: gridColumns,
noData: "처리 할 초기자료가 없습니다.",
pageOptions: {
useClient: false,
perPage: perPage
}
};
// 실제 GRID 생성
GRID = TuiGrid.of(gridOptions, gridDatasource, (res) => {
// 서버 응답 후 페이지 정보 세팅
const data = res.data || {};
if (data.pagination) {
$("#currentPage").text(data.pagination.page || '');
$("#totalPages").text(data.pagination.totalPages || '');
}
// 더블 클릭 이벤트
GRID.on("dblclick", (e) => {
var popUrl = '/minwon/init/init_popup.do';
var popTitle = "initPopup";
var popOption = "width=1400px, height=900px, resizable=yes, scrollbars=yes, location=no, top=100px, left=100px";
// 1) localStorage에 저장
console.log(e)
let cursor = e.instance.getValue(e.rowKey, 'mmCode');
let mmCodes = e.instance.getData().map(row => row.mmCode);
console.log(cursor);
const state = { cursor, mmCodes, savedAt: Date.now() };
localStorage.setItem('TOTAL_INFO_STATE', JSON.stringify(state));
// 2) 팝업이 없거나 닫혀 있으면 새로 열기
if (!INIT_POPUP || INIT_POPUP.closed) {
INIT_POPUP = window.open(popUrl, popTitle, popOption);
} else {
// 이미 떠 있으면 새로 안 만들고, 그 창에 포커스만 줌
INIT_POPUP.focus();
INIT_POPUP.INIT_POP_API.search();
}
});
});
// 최초 1페이지 조회
GRID.readData(1);
};
// 레디펑션
$(function () {
fnBiz.init();
fnBiz.eventListener();
});
</script>
Loading…
Cancel
Save