diff --git a/src/main/java/go/kr/project/biz/minwon/dayanswer/controller/DayAnswerController.java b/src/main/java/go/kr/project/biz/minwon/dayanswer/controller/DayAnswerController.java index 7cb570d..80c9e7a 100644 --- a/src/main/java/go/kr/project/biz/minwon/dayanswer/controller/DayAnswerController.java +++ b/src/main/java/go/kr/project/biz/minwon/dayanswer/controller/DayAnswerController.java @@ -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 result; + dto.setTotalCount(0); + dto.setPagingYn("N"); - result = dayAnswerService.selectAllDayAnswer(dto); + List result = dayAnswerService.selectAllDayAnswer(dto); return ApiResponseUtil.successWithGrid(result, dto); } @@ -131,57 +129,7 @@ public class DayAnswerController { HttpServletResponse response ) throws Exception { - // 검색 조건을 이용해 전체 리스트 조회 - List 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 updateAllState( + @ModelAttribute DayAnswerDto.Request.Search dto, + @RequestParam("newState") String newState) { + + int updated = dayAnswerService.updateAllState(dto, newState); + + Map result = new HashMap<>(); + result.put("updated", updated); + result.put("result", "success"); + return result; + } + + @PostMapping("/minwon/dayanswer/update-one-state.ajax") + @ResponseBody + public Map updateOneState( + @RequestParam("asMmcode") String asMmcode, + @RequestParam("newState") String newState) { + + int updated = dayAnswerService.updateOneState(asMmcode, newState); + Map result = new HashMap<>(); + result.put("updated", updated); + result.put("result", "success"); + return result; + } } diff --git a/src/main/java/go/kr/project/biz/minwon/dayanswer/mapper/DayAnswerMapper.java b/src/main/java/go/kr/project/biz/minwon/dayanswer/mapper/DayAnswerMapper.java index aada213..4632e6f 100644 --- a/src/main/java/go/kr/project/biz/minwon/dayanswer/mapper/DayAnswerMapper.java +++ b/src/main/java/go/kr/project/biz/minwon/dayanswer/mapper/DayAnswerMapper.java @@ -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 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 selectAllDayAnswerForExcel(DayAnswerDto.Request.Search dto); } diff --git a/src/main/java/go/kr/project/biz/minwon/dayanswer/model/DayAnswerDto.java b/src/main/java/go/kr/project/biz/minwon/dayanswer/model/DayAnswerDto.java index f74caf7..7e5ad40 100644 --- a/src/main/java/go/kr/project/biz/minwon/dayanswer/model/DayAnswerDto.java +++ b/src/main/java/go/kr/project/biz/minwon/dayanswer/model/DayAnswerDto.java @@ -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; } } diff --git a/src/main/java/go/kr/project/biz/minwon/dayanswer/service/DayAnswerService.java b/src/main/java/go/kr/project/biz/minwon/dayanswer/service/DayAnswerService.java index 99d4a53..b65d1d1 100644 --- a/src/main/java/go/kr/project/biz/minwon/dayanswer/service/DayAnswerService.java +++ b/src/main/java/go/kr/project/biz/minwon/dayanswer/service/DayAnswerService.java @@ -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; } diff --git a/src/main/java/go/kr/project/biz/minwon/dayanswer/service/impl/DayAnswerServiceImpl.java b/src/main/java/go/kr/project/biz/minwon/dayanswer/service/impl/DayAnswerServiceImpl.java index c8cf4db..d3d67ec 100644 --- a/src/main/java/go/kr/project/biz/minwon/dayanswer/service/impl/DayAnswerServiceImpl.java +++ b/src/main/java/go/kr/project/biz/minwon/dayanswer/service/impl/DayAnswerServiceImpl.java @@ -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 selectAllDayAnswer(DayAnswerDto.Request.Search dto) { + @Override + public List 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 list = dayAnswerMapper.selectAllDayAnswer(dto); - List 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 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; + } } diff --git a/src/main/java/go/kr/project/biz/minwon/init/controller/MinwonInitController.java b/src/main/java/go/kr/project/biz/minwon/init/controller/MinwonInitController.java index 1bdb24e..101bb14 100644 --- a/src/main/java/go/kr/project/biz/minwon/init/controller/MinwonInitController.java +++ b/src/main/java/go/kr/project/biz/minwon/init/controller/MinwonInitController.java @@ -34,6 +34,18 @@ public class MinwonInitController { return "biz/minwon/init/init" + TilesConstants.BASE; } + + /** + * 민원접수 초기자료 팝업 페이지 + * @return 뷰 경로 + */ + @GetMapping("/minwon/init/init_popup.do") + public String initPopupView() { + + return "biz/minwon/init/init_popup" + TilesConstants.POPUP; + } + + @PostMapping("/minwon/init/list.ajax") public ResponseEntity getMinwonInitListAjax(@ModelAttribute MinwonInitDto.Request.SearchMinwonInitList dto) { diff --git a/src/main/java/go/kr/project/biz/search/controller/SearchController.java b/src/main/java/go/kr/project/biz/search/controller/SearchController.java new file mode 100644 index 0000000..7e8f64e --- /dev/null +++ b/src/main/java/go/kr/project/biz/search/controller/SearchController.java @@ -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 result = searchService.selectAllSearch(dto); + + + return ApiResponseUtil.successWithGrid(result, dto); + + } + +} diff --git a/src/main/java/go/kr/project/biz/search/mapper/SearchMapper.java b/src/main/java/go/kr/project/biz/search/mapper/SearchMapper.java new file mode 100644 index 0000000..4778fed --- /dev/null +++ b/src/main/java/go/kr/project/biz/search/mapper/SearchMapper.java @@ -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 selectAllSearch(SearchDto.Request.Search dto); + +} diff --git a/src/main/java/go/kr/project/biz/search/model/SearchDto.java b/src/main/java/go/kr/project/biz/search/model/SearchDto.java new file mode 100644 index 0000000..e8dcebe --- /dev/null +++ b/src/main/java/go/kr/project/biz/search/model/SearchDto.java @@ -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; + } + } +} diff --git a/src/main/java/go/kr/project/biz/search/service/SearchService.java b/src/main/java/go/kr/project/biz/search/service/SearchService.java new file mode 100644 index 0000000..1fc25d7 --- /dev/null +++ b/src/main/java/go/kr/project/biz/search/service/SearchService.java @@ -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 selectAllSearch(SearchDto.Request.Search dto); +} diff --git a/src/main/java/go/kr/project/biz/search/service/impl/SearchServiceImpl.java b/src/main/java/go/kr/project/biz/search/service/impl/SearchServiceImpl.java new file mode 100644 index 0000000..6ec6457 --- /dev/null +++ b/src/main/java/go/kr/project/biz/search/service/impl/SearchServiceImpl.java @@ -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 selectAllSearch(SearchDto.Request.Search dto){ + + List list = searchMapper.selectAllSearch(dto); + + return list; + + } +} diff --git a/src/main/resources/mybatis/mapper/biz/minwon/DayAnswerMapper_maria.xml b/src/main/resources/mybatis/mapper/biz/minwon/DayAnswerMapper_maria.xml index 65ed684..d27a0e0 100644 --- a/src/main/resources/mybatis/mapper/biz/minwon/DayAnswerMapper_maria.xml +++ b/src/main/resources/mybatis/mapper/biz/minwon/DayAnswerMapper_maria.xml @@ -10,62 +10,299 @@ resultType은 쿼리 결과를 반납하는 객체를 넣어준다. 아래 보면 이너클래스는 $형태로 들어간다. --> - + 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 - - AND as_jsdate >= REPLACE(#{searchStartDt}, '-', '') - - - AND as_jsdate <= REPLACE(#{searchEndDt}, '-', '') - + + + AND + + + AS_STATE = '6' + + + AS_STATE = '7' + + + AS_STATE IN ('8') + + + AS_STATE IN ('9') + + + AS_STATE = '5' + + + AS_STATE IN ('A','B') + + + + + + + AND as_jsdate >= REPLACE(#{searchStartDt}, '-', '') + + + AND as_jsdate <= REPLACE(#{searchEndDt}, '-', '') + + + + + + + AND as_jsno LIKE CONCAT('%', #{searchKeyword}, '%') + + + + AND as_user LIKE CONCAT('%', #{searchKeyword}, '%') + + + + AND REPLACE(as_tel, '-', '') LIKE CONCAT('%', REPLACE(#{searchKeyword}, '-', ''), '%') + + + + + AND ( + as_jsno LIKE CONCAT('%', #{searchKeyword}, '%') + OR as_user LIKE CONCAT('%', #{searchKeyword}, '%') + OR as_tel LIKE CONCAT('%', #{searchKeyword}, '%') + ) + + + + + ORDER BY AS_JSDATE DESC, AS_JSNO DESC + + + + + + + + + + + + UPDATE cp_answer + SET AS_STATE = #{newState} + WHERE 1 = 1 + + AND + + + AS_JSNO LIKE CONCAT('%', #{vo.searchKeyword}, '%') + + + AS_REUSER LIKE CONCAT('%', #{vo.searchKeyword}, '%') + + + + + AND AS_JSDATE >= #{vo.searchStartDt} + + + AND AS_JSDATE <= #{vo.searchEndDt} + + + + + UPDATE cp_answer + SET AS_STATE = #{newState} + WHERE AS_MMCODE = #{asMmcode} + diff --git a/src/main/resources/mybatis/mapper/biz/search/SearchMapper_maria.xml b/src/main/resources/mybatis/mapper/biz/search/SearchMapper_maria.xml new file mode 100644 index 0000000..b663765 --- /dev/null +++ b/src/main/resources/mybatis/mapper/biz/search/SearchMapper_maria.xml @@ -0,0 +1,69 @@ + + + + + + diff --git a/src/main/webapp/WEB-INF/views/biz/minwon/dayanswer/dayanswer.jsp b/src/main/webapp/WEB-INF/views/biz/minwon/dayanswer/dayanswer.jsp index fd0b95e..5598b2c 100644 --- a/src/main/webapp/WEB-INF/views/biz/minwon/dayanswer/dayanswer.jsp +++ b/src/main/webapp/WEB-INF/views/biz/minwon/dayanswer/dayanswer.jsp @@ -11,7 +11,6 @@ -
    @@ -22,6 +21,7 @@ +
  • 검색어
  • @@ -33,7 +33,6 @@
  • -
  • @@ -42,13 +41,78 @@
  • / Pages
+
+
    +
  • 전체
  • +
  • 답변완료(부과)
  • +
  • 답변완료(계도)
  • +
  • 답변완료(미부과)
  • +
  • 답변완료(수기)
  • +
  • 답변실패
  • +
  • 답변미대상
  • +
+
+ +
@@ -60,429 +124,324 @@
+
+ +
+
+ + + + + + +
+
+ + 초기 0, 대기 1, 대상(부과) 2, 대상(계도) 3, 대상(서손) 4, 실패 5, + 완료(부과) 6, 완료(계도) 7, 완료(서손) 8, 완료(수기) 9, 미대상 A, 미대상(서손) B + +
+
diff --git a/src/main/webapp/WEB-INF/views/biz/minwon/init/init.jsp b/src/main/webapp/WEB-INF/views/biz/minwon/init/init.jsp index 340f828..664b29e 100644 --- a/src/main/webapp/WEB-INF/views/biz/minwon/init/init.jsp +++ b/src/main/webapp/WEB-INF/views/biz/minwon/init/init.jsp @@ -37,7 +37,7 @@
  • 접수일자 지정
  • - ~ + ~
  • @@ -71,366 +71,178 @@ diff --git a/src/main/webapp/WEB-INF/views/biz/minwon/init/init_popup.jsp b/src/main/webapp/WEB-INF/views/biz/minwon/init/init_popup.jsp new file mode 100644 index 0000000..424afe2 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/biz/minwon/init/init_popup.jsp @@ -0,0 +1,597 @@ +<%-- + Created by IntelliJ IDEA. + User: kurt + Date: 2025. 7. 31. + Time: 오후 5:34 + To change this template use File | Settings | File Templates. +--%> +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + +
    + +
    +
    +
    민원 접수 초기자료 편집
    +
    + Double Click 민원원본보기 + +
    +
    + + +
    + <%-- 부모창에서 받아오는 리스트 배열 --%> + + <%-- 부모창에서 받아오는 리스크 커서 --%> + + <%-- 개별총정보 상태값 --%> + + +
    + 0of 0 +
    + +
    + +
    + +
    +
    위반 정보
    +
    등록구분/위반일시/위반내역 등
    + +
    + + +
    +
    +
    등록구분
    +
    + +
    +
    +
    +
    목록번호
    +
    + +
    +
    +
    + + +
    +
    +
    위반일자
    +
    + +
    +
    +
    +
    위반시간
    +
    + +
    +
    +
    + + +
    +
    +
    위반내용
    +
    + +
    +
    +
    +
    영상매체
    +
    + +
    +
    +
    + + +
    +
    +
    신고자
    +
    + +
    +
    +
    +
    연락처
    +
    + +
    +
    +
    + + +
    +
    +
    담당자
    +
    + +
    +
    +
    +
    + + +
    +
    +
    신고내용
    +
    + +
    +
    +
    + + +
    +
    +
    위반장소
    +
    + +
    +
    +
    + + +
    +
    +
    시군구
    +
    + +
    +
    +
    +
    법정동
    +
    + +
    +
    +
    + + +
    +
    +
    접수일
    +
    + +
    +
    +
    +
    답변기한
    +
    + +
    +
    +
    + + +
    +
    차량 정보
    + + +
    +
    +
    차량번호
    +
    + +
    +
    +
    +
    + + +
    +
    +
    특기사항
    +
    + +
    +
    +
    + + +
    +
    +
    차량명
    +
    + +
    +
    +
    +
    차량색상
    +
    + +
    +
    +
    + + +
    +
    +
    연료구분
    +
    + +
    +
    +
    +
    + + +
    +
    +
    소유주
    +
    + +
    +
    +
    +
    등록구분
    +
    + +
    +
    +
    + + +
    +
    +
    주민번호
    +
    + +
    +
    +
    +
    우편번호
    +
    + +
    +
    +
    + + +
    +
    +
    주소
    +
    + +
    +
    +
    + + +
    +
    +
    번지
    +
    + +
    +
    +
    +
    차대번호
    +
    + +
    +
    +
    + + +
    +
    +
    도로코드
    +
    + +
    +
    +
    +
    + +
    +
    + + +
    +
    사진
    +
    + <%-- IMG area --%> +
    + +
    + 지도 +
    + +
    + 미리보기 +
    +
    + +
    + + + + + + + + + +
    +
    + +
    +
    +
    + 3 사진 + +
    +
    +
    + + +
    + + +<%----%> +<%----%> + diff --git a/src/main/webapp/WEB-INF/views/biz/search/search.jsp b/src/main/webapp/WEB-INF/views/biz/search/search.jsp new file mode 100644 index 0000000..f73d3b3 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/biz/search/search.jsp @@ -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" %> + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
      +
    • 검색구분
    • +
    • + +
    • +
    • 검색어
    • +
    • +
    • 접수일자 지정
    • +
    • + ~ + +
    • +
    • + +
    • +
    +
      +
    • + + / Pages +
    • +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + + diff --git a/src/main/webapp/WEB-INF/views/biz/totalInfo/totalInfo_photo_dialog.jsp b/src/main/webapp/WEB-INF/views/biz/totalInfo/totalInfo_photo_dialog.jsp index 6fb0fb7..16f3c5c 100644 --- a/src/main/webapp/WEB-INF/views/biz/totalInfo/totalInfo_photo_dialog.jsp +++ b/src/main/webapp/WEB-INF/views/biz/totalInfo/totalInfo_photo_dialog.jsp @@ -22,51 +22,51 @@
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -
    - -<%-- --%> -<%--
    --%> -<%-- -<%-- src=""--%> -<%-- alt="사진 보기"--%> -<%-- style="max-width:100%; height:auto; display:block; margin:0 auto;">--%> - -<%--
    --%> -<%-- --%> -<%-- --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> +<%-- --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> +<%--
    --%> <%--
    --%> <%--
    --%> -<%-- --%> -<%-- + + +
    --%> <%----%> diff --git a/src/main/webapp/WEB-INF/views/layouts/base/default.jsp b/src/main/webapp/WEB-INF/views/layouts/base/default.jsp index 0909e4f..b25b7c2 100644 --- a/src/main/webapp/WEB-INF/views/layouts/base/default.jsp +++ b/src/main/webapp/WEB-INF/views/layouts/base/default.jsp @@ -75,6 +75,11 @@ + + <%-- tui grid new --%> + + + " /> diff --git a/src/main/webapp/WEB-INF/views/layouts/base/menu.jsp b/src/main/webapp/WEB-INF/views/layouts/base/menu.jsp index 3864708..7e96817 100644 --- a/src/main/webapp/WEB-INF/views/layouts/base/menu.jsp +++ b/src/main/webapp/WEB-INF/views/layouts/base/menu.jsp @@ -11,93 +11,139 @@ <%-- 활성화된 메뉴 정보 저장할 변수 --%> - -<%-- 콘솔 디버깅 용도 (개발 환경에서만 사용) --%> - +
  • + + + + - \ No newline at end of file + diff --git a/src/main/webapp/resources/css/cc.css b/src/main/webapp/resources/css/cc.css index 161bfea..d2a37b1 100644 --- a/src/main/webapp/resources/css/cc.css +++ b/src/main/webapp/resources/css/cc.css @@ -256,7 +256,7 @@ /* 카드/헤더 */ .detail-card{border:1px solid var(--border); border-radius:10px; overflow:hidden; background:#fff;} -.detail-card .card-header{display:flex; justify-content:space-between; align-items:center; background:var(--green); color:#fff; padding:10px 12px;} +.detail-card .card-header{display:flex; justify-content:space-between; align-items:center; background:#202342; color:#fff; padding:10px 12px;} .card-header .title{font-weight:700} .card-header .actions{display:flex; gap:6px; align-items:center} .pill{font-size:12px; background:rgba(255,255,255,.25); padding:3px 8px; border-radius:999px} @@ -270,14 +270,30 @@ .subnote{font-size:12px; color:#888; text-align:right; margin-top:-4px; margin-bottom:8px} /* 폼 그리드 */ -.form-grid{display:grid; grid-template-columns: 110px 1fr 110px 1fr; gap:8px 10px} -.lbl{align-self:center; color:#444; font-size:13px} -.fld input,.fld textarea,.fld select{width:100%; padding:6px 8px; border:1px solid var(--border); border-radius:6px; font-size:13px; background:#fff} -.fld input[readonly],.fld textarea[readonly]{background:#fafafa} -.fld textarea{height:80px; resize:vertical} -.badge{display:inline-block; background:#eef2ff; color:#1d4ed8; border:1px solid #c7d2fe; padding:3px 8px; border-radius:999px; font-size:12px} -.hl{background:var(--warn)} -.block{grid-column: 1 / -1} +/*.form-grid{display:grid; grid-template-columns: 110px 1fr 110px 1fr; gap:8px 10px}*/ +/*.lbl{align-self:center; color:#444; font-size:13px}*/ +/*.fld input,.fld textarea,.fld select{width:100%; padding:6px 8px; border:1px solid var(--border); border-radius:6px; font-size:13px; background:#fff}*/ +/*.fld input[readonly],.fld textarea[readonly]{background:#fafafa}*/ +/*.fld textarea{height:80px; resize:vertical}*/ +/*.badge{display:inline-block; background:#eef2ff; color:#1d4ed8; border:1px solid #c7d2fe; padding:3px 8px; border-radius:999px; font-size:12px}*/ +/*.hl{background:var(--warn)}*/ +/*.block{grid-column: 1 / -1}*/ + +/** 플렉스 폼 start */ +.form-grid {display: flex;flex-direction: column; row-gap: 8px;} +.form-row {display: flex;column-gap: 10px;} +.field-group {display: flex;align-items: center;flex: 1 1 0;min-width: 0;gap: 6px;} +.field-group .lbl {flex: 0 0 110px;color: #444;font-size: 13px;align-self: center;white-space: nowrap;font-weight: 400;} +.field-group .fld {flex: 1 1 0;} +.field-group .fld input, .field-group .fld textarea, .field-group .fld select {width: 100%;padding: 6px 8px;border: 1px solid var(--border);border-radius: 6px;font-size: 13px;background: #fff;box-sizing: border-box;} +.field-group .fld input[readonly], .field-group .fld textarea[readonly] {background: #fafafa;} .field-group .fld textarea {height: 80px;resize: vertical;} .form-row.block .field-group.full {flex: 1 1 100%;display: flex;align-items: flex-start;} +.form-row.block .field-group.full .lbl {margin-top: 4px;} +.field-group.empty {flex: 1 1 0;} +.badge {display: inline-block;background: #eef2ff;color: #1d4ed8;border: 1px solid #c7d2fe;padding: 3px 8px;border-radius: 999px;font-size: 12px;} +.hl {background: var(--warn);} +@media (max-width: 1200px) { .form-row {flex-direction: column;} } +/* 플렉스 폼 end */ + .bar{height:1px; background:var(--border); margin:8px 0} @@ -356,4 +372,5 @@ + /** totalInfo End */ \ No newline at end of file diff --git a/src/main/webapp/resources/xit/tuiGridCustom/xit-tui-grid.css b/src/main/webapp/resources/xit/tuiGridCustom/xit-tui-grid.css new file mode 100644 index 0000000..ebdebf8 --- /dev/null +++ b/src/main/webapp/resources/xit/tuiGridCustom/xit-tui-grid.css @@ -0,0 +1,71 @@ +@charset "utf-8"; + + + +tui-grid-content-area {border-radius: 10px;} + +/* selected row */ +table.tui-grid-table tr.tui-grid-cell-current-row > td{ + background-color: rgba(199, 235, 235, 1); +} + +table.tui-grid-table tr.tui-grid-cell-current-row > td:focus{ + outline: none; +} + + +/* font size */ +table.tui-grid-table th{ + border-color: #fff; + font-size: 14px; + font-family: 'notokr-bold'; +} +table.tui-grid-table td div{ + font-size: 0.80rem; +} + + +/* header color */ +table.tui-grid-table th.tui-grid-cell-header, table.tui-grid-table th.tui-grid-cell-row-header{ + background-color: #f2f4ff; + border-right: 1px solid #fff; + /*border-top: 2px solid #d0d0d0;*/ + font-size: 14px; + font-weight: bold; +} +.tui-grid-scrollbar-right-top {background-color: #f2f4ff;} + +.tui-grid-body-area {margin-right: 3px;} +.tui-grid-scrollbar-y-outer-border {background-color: unset !important;} +.tui-grid-scrollbar-right-bottom { border-bottom-right-radius: 10px;} + /* grid cell */ +/* table.tui-grid-table td.tui-grid-cell div.tui-grid-cell-content{ */ +/* overflow: auto; */ +/* } */ +table.tui-grid-table td.tui-grid-cell-editable > div.tui-grid-cell-content{ + /* border: 1px outset; */ + cursor: pointer; + +} + +/* summary영역 수정 */ +.tui-grid-summary-area .tui-grid-cell { + text-align: right; + font-size: 11px; + padding-right: 5px; + background-color: rgba(238, 238, 238, 1); + border: 1px solid white; +} + +.tui-grid-table tr { + border-bottom: 1px solid #eee; +} + +/* "CustomButtonRenderer" print cell .. */ +table.tui-grid-table tr > td > span > p { + color: #0000ee; + cursor: pointer; + padding-bottom: 1px; + border-bottom: solid 1px; + padding-left: 10px; +} \ No newline at end of file diff --git a/src/main/webapp/resources/xit/tuiGridCustom/xit-tui-grid.js b/src/main/webapp/resources/xit/tuiGridCustom/xit-tui-grid.js new file mode 100644 index 0000000..a6c6a64 --- /dev/null +++ b/src/main/webapp/resources/xit/tuiGridCustom/xit-tui-grid.js @@ -0,0 +1,698 @@ +const Grid = tui.Grid; + +const customTheme = { + selection: { + background: '#4daaf9', + border: '#004082' + }, + scrollbar: { + background: '#f5f5f5', + thumb: '#d9d9d9', + active: '#c1c1c1' + }, + row: { + even: { + // background: '#f2f4ff' + background: '#fff' + }, + hover: { + background: '#ccc' + } + }, + cell: { + normal: { + background: '#fbfbfb', + border: '#e0e0e0', + showVerticalBorder: false + }, + header: { + background: '#f2f4ff', + // border: '#ccc', + text:'#09097a', + showVerticalBorder: false + }, + rowHeader: { + // border: '#ccc', + showVerticalBorder: false + }, + editable: { + background: '#fbfbfb' + }, + selectedHeader: { + background: '#d8d8d8' + }, + focused: { + border: '#418ed4' + }, + disabled: { + text: '#b0b0b0' + } + } +} + +class CustomRowNumberRenderer { + constructor(props) { + const el = document.createElement('span'); + + this.el = el; + this.el.innerHTML = this.getRowNum(props); + } + + getRowNum(props) { + // paging 처리시 : scroll인 경우 제외 + const currentPage = props.grid.getPagination()?._currentPage; + // You can change the number `5` as your perPage option. + return Number(props.formattedValue) + (currentPage - 1) * props.grid.getPagination()?._options?.itemsPerPage; + } + + getElement() { + return this.el; + } + + render(props) { + this.el.innerHTML = this.getRowNum(props); + } +} + + +/***************************************** + * Tui-Grid 공식문서 + * https://nhn.github.io/tui.grid/latest/ + ******************************************/ +const TuiGrid = { + instance: null, + defaultOptions: { + el: $('#grid'), + //[선택]DataSource 정보(readData|createData|updateData|modifyData|deleteData 등) + data: { + headers: { + AJAX: true + }, + withCredentials: false, + initialRequest: false, + api: { + readData: { + contentType: 'application/json', + dataType: 'json', + method: 'get', + initParams: {} + } + , createData: {url: '', method: 'POST'} + , updateData: {url: '', method: 'PUT'} + , modifyData: {url: '', method: 'PUT'} + , deleteData: {url: '', method: 'DELETE'} + } + }, + header: { + align:'left', //헤더 좌측정렬 + columns: [{name: "_checked", align: "center"}] //헤더 채크박스 가운데정렬 + }, //[선택]헤더정보(헤더 명칭 및 매핑 field) + columns: [], //[필수]컬럼정보(헤더 명칭 및 매핑 field) + rowHeaders: [], //[선택]ROW 헤더 타입(rowNum: 순번, checkbox: 체크박스) + bodyHeight: 467, //[선택]Grid 높이 (number(단위: px)|'auto'|'fitToParent') + minBodyHeight: 350, //[선택]Grid 최소 높이 (단위: px) + rowHeight: 50, //[선택]Grid row 높이 (number(단위: px)|'auto' ) + minRowHeight: 50, //[선택]Grid row 최소 높이 (단위: px) + pageOptions: { + useClient: false, + page: 1, + perPage: 10 + }, //[선택]한 페이지에 출력할 건수 + columnOptions: { //[선택]고정 컬럼 + //frozenCount: 0 //고정컬럼 갯수 + frozenBorderWidth: 2 //고정컬럼 보더(border) 두께 + , resizable: true + , minWidth: 100 //최소 사이즈 + }, + summary: [], //[선택]하단합계 + treeColumnOptions: {}, //[선택]tree 구조 grid + }, + + of: function (options, dataSource, successCallback) { + + this.instance = null; + // rowNum fix + if (options.pageOptions?.type !== 'scroll') { + options.rowHeaders.filter((r, idx) => { + if (r === 'rowNum') { + options.rowHeaders[idx] = { + type: 'rowNum', + renderer: { + type: CustomRowNumberRenderer + } + } + } + }) + } + const newOptions = $.extend(true, {}, this.defaultOptions, options, {data: dataSource}); + newOptions.el = document.getElementById(options.el); + //this.elId = options.el; + + // language + tui.Grid.setLanguage('en', { + display: { + noData: options?.noData + } + }); + // theme + //tui.Grid.applyTheme('custom', eval(customTheme)); + //Grid.applyTheme('custom', customTheme); + Grid.applyTheme('striped', customTheme); + // console.log("newOpt", newOptions); + this.instance = new tui.Grid(newOptions); + + + this.instance.on('successResponse', function (ev) { + // console.log(`successResponse >>>>>>>>>>>>>>>>>> `,ev); + var msg = JSON.parse(ev.xhr.response).message; //tui-grid 기본 format 메시지 + + //if($('#totCnt span')){ + if (document.getElementById('totCnt')) { + const res = JSON.parse(ev.xhr.response); + // paging + if (res.data.pagination) { + $('#totCnt span').text(res.data.pagination.totalCount); + // no paging + } else { + $('#totCnt span').text(res.count) + } + // console.log('totCnt >>>>> ',$('#totCnt span').text()) + } + + if (successCallback) successCallback(JSON.parse(ev.xhr.response)); + //if(successCallback) successCallback(ev); + }); + // 결과가 false인 경우 발생한 경우 + this.instance.on('failResponse', function (ev) { + // console.log(`failResponse >>>>>>>>>>>>>>>>>> `,ev); + try { + //tui-grid 기본 format 메시지 + + const res = JSON.parse(ev.xhr.response); + + let msg = ''; + if (!(res.message == null || res.message == undefined || res.message == '')) { + alert(res.message); + } else { + alert(res); + } + } catch (e) { + alert("오류가 발생하였습니다."); + // console.error('TuiGrid::failResponse parsing error', e) + } + }); + // 오류가 발생한 경우 + this.instance.on('errorResponse', function (ev) { + // console.log(`errorResponse >>>>>>>>>>>>>>>>>> `,ev); + try { + //tui-grid 기본 format 메시지 + const res = JSON.parse(ev.xhr.response); + if (!(res.message == null || res.message == undefined || res.message == '')) { + alert(res.message); + } else { + alert(res); + } + } catch (e) { + alert("오류가 발생하였습니다."); + // console.error('TuiGrid::errorResponse parsing error', e) + } + }); + + /** + * grid check box event start + * */ + // 체크박스 이벤트 + this.instance.on("check", () => { + $("#selectOption").addClass("active"); + $("#remove").attr("disabled", false); + $("#sendMessageBtn").removeClass("disabled"); + $("#sendMessageBtn").attr("disabled", false); + $("#checkedCount").text(GRID.getCheckedRows().length); + $("#assigns-btn").removeClass("disabled"); + $("#assigns-btn").attr("disabled", false); + $("#suspend-btn").attr("disabled", false); + $("#returnBtn").attr("disabled", false); + }); + // 체크박스 해제 이벤트 + this.instance.on("uncheck", () => { + const checkedCount = GRID.getCheckedRows().length; + if (checkedCount === 0) { + $("#selectOption").removeClass("active"); + $("#remove").attr("disabled", true); + $("#sendMessageBtn").addClass("disabled"); + $("#sendMessageBtn").attr("disabled", true); + $("#assigns-btn").addClass("disabled"); + $("#assigns-btn").attr("disabled", true); + $("#suspend-btn").attr("disabled", true); + $("#returnBtn").attr("disabled", true); + } + $("#checkedCount").text(checkedCount); + }); + // 전체 체크박스 이벤트 + this.instance.on("checkAll", () => { + $("#selectOption").addClass("active"); + $("#remove").attr("disabled", false); + $("#sendMessageBtn").removeClass("disabled"); + $("#sendMessageBtn").attr("disabled", false); + $("#checkedCount").text(GRID.getCheckedRows().length); + $("#assigns-btn").removeClass("disabled"); + $("#assigns-btn").attr("disabled", false); + $("#suspend-btn").attr("disabled", false); + $("#returnBtn").attr("disabled", false); + }); + // 전체 체크박스 해제 이벤트 + this.instance.on("uncheckAll", () => { + $("#selectOption").removeClass("active"); + $("#remove").attr("disabled", true); + $("#sendMessageBtn").addClass("disabled"); + $("#sendMessageBtn").attr("disabled", true); + $("#checkedCount").text(GRID.getCheckedRows().length); + $("#assigns-btn").addClass("disabled"); + $("#assigns-btn").attr("disabled", true); + $("#suspend-btn").attr("disabled", true); + $("#returnBtn").attr("disabled", true); + }); + /** + * grid check box event end + * */ + + + return this.instance; + }, + + + /** Excel Export */ + exportExcel: function (_instance, fileName, rowHeader) { + /* 필수값 설정 */ + var _gridId = _instance.el.id; + var _frstColTyp = rowHeader; + var _arrHeader = []; + var _arrName = []; + var _mCustomRenderer = {}; + /* ================= + * 2021.04.30. 박민규 + * 컬럼 취득 방법 변경 + * AsIs: GridConfig 에 설정한 Columns 정보 + * ToBe: instance 에 설정된 Columns 정보 + ================= */ + //2021.04.30. 주석처리 +// this.getOptColumns().forEach(function(opt, idx){ + _instance.getColumns().forEach(function (opt, idx) { + _arrHeader.push(opt.header); + _arrName.push(opt.name); + //2021.04.30. 주석처리 +// if(!fnIsEmpty(opt.renderer)){ + if (!(fnIsEmpty(opt.renderer) || 'DefaultRenderer' == opt.renderer.type.name || fnIsEmpty(opt.renderer.type.name))) { //브라우저별 opt.renderer.type.name 값의 차이 => Chrome: "DefaultRenderer", IE: undefined + _mCustomRenderer[opt.name] = opt.renderer; + } + }); + + + /* grid head Setting */ + var elementTHEAD = document.createElement('table'); + var $sltHeader = $('#' + _gridId + ' .tui-grid-header-area > table.tui-grid-table').clone(); + //head 처리(table 고정셀 이용 시) + if ($sltHeader.length > 1) { + //좌측 table의 head Selector + var firstTableTh = $sltHeader.find('tr:last-child th'); + //우측 table row의 헤드(th)를 좌측 table row에 병합 + for (var i = 1; i < $sltHeader.length; i++) { + $sltHeader.eq(i).find('tr').each(function (idx, row) { + var firstTableRow = $sltHeader.eq(0).find('tr:eq(' + idx + ')'); + if (firstTableRow.length == 0) { + // 신규생성 + var tr = document.createElement('tr'); + tr.innerHTML = row.innerHTML; + $sltHeader.eq(0).append(tr); + //firstTable 의 rowspan 변경 + for (var j = 0; j < firstTableTh.length; j++) { + firstTableTh.eq(j).attr('rowspan', Number(firstTableTh.eq(j).attr('rowspan')) + 1); + } + } else { + firstTableRow.append(row.innerHTML); + } + }); + } + } + elementTHEAD.innerHTML = $sltHeader.eq(0).find('tbody').html(); + + + /* grid body Setting */ + var elementTBODY = document.createElement('tbody'); + _instance.getData().forEach(function (row, idxRow) { + var elementTR = document.createElement('tr'); + + //타입별 element 생성( 첫번째 컬럼타입 설정 시 ) + if (!fnIsEmpty(_frstColTyp)) + elementTR.appendChild(fnCreateTdByFrstCol(_frstColTyp, row)); + // element 생성 + _arrName.forEach(function (columnName, idxColumn) { + var columnVal = ''; + var customRenderer = _mCustomRenderer[columnName]; + if (fnIsEmpty(customRenderer)) { + //column Value 설정 + columnVal = fnNvl(row[columnName]); + } else { + //prop 객체 생성 + var columnInfo = {}; + columnInfo['renderer'] = customRenderer; + columnInfo['name'] = columnName; + var props = {}; + props['columnInfo'] = columnInfo; + props['rowKey'] = row.rowKey; + props['grid'] = _instance; + + //렌더러 호출 + customRenderer.type(props); + + //column Value 설정 + columnVal = fnNvl(row[columnName]); + if (row.rowKey < 15) { +// // console.log('[export]rowKey->'+row.rowKey+'/ column->'+columnName+' / value->'+row[columnName]); +// // console.log(_instance.getRow(row.rowKey)); + } + } + + var elementTD = document.createElement('td'); + elementTD.innerHTML = columnVal; + elementTR.appendChild(elementTD); + }); + elementTBODY.appendChild(elementTR); + }); + + + /* grid table Setting */ + var elementTABLE = document.createElement('table'); + elementTABLE.appendChild(elementTHEAD); + elementTABLE.appendChild(elementTBODY); + + + /* export Excel */ + var fileUtil = new luluFileExportUtil(fileName, 'table', elementTABLE); + fileUtil.exportExcel(); + + + /* member Function Declare */ + + //isEmpty Function + function fnIsEmpty(val) { + if (val == undefined || val == null || val == '' || val == {} || val == []) + return true; + return false; + } + + //nvl Function + function fnNvl(val, replaceVal) { + replaceVal = fnIsEmpty(replaceVal) ? '' : replaceVal; + val = fnIsEmpty(val) ? replaceVal : val; + return val; + } + + // element 생성 Function + function fnCreateTdByFrstCol(colType, row) { + var returnVal = ''; + + /* column 타입별 value 설정 */ + switch (colType) { + case 'rowNum': + returnVal = row._attributes.rowNum; + break; + case 'checkbox': + if (row._attributes.checked) + returnVal = '☑'; + else + returnVal = '□'; + break; + default: + return returnVal; + break; + } + + /* element 생성 */ + var elementFrstTD = document.createElement('td'); + elementFrstTD.innerHTML = returnVal; + + + return elementFrstTD; + } + } +} + +/** + * Button 렌더러 + * -설명: Grid의 cell에 Button을 생성 한다. + * 버튼명칭에 format 사용이 가능하며 사용방법은 아래와 같다. + * ex) value: 'A is {0}. B is {1}. {0}!={1}', + * listColumns: ['컬럼1', '컬럼2'] + * @param value 버튼에 출력 할 명칭 + * @param listColumns format에 매칭할 컬럼 목록 + * @param callbackFnc 버튼 클릭 시 호출 할 함수명 + * @author 박민규 + * @date 2020.05.28. + */ +var LuluButtonRenderer = function (props) { +// // console.log('XitButtonRenderer Called!!-> '+props.columnInfo.name); + //options get + var opt = props.columnInfo.renderer.options; + var value = opt.value; + var id = opt.id; + var btnClass = opt.btnClass; + var callbackFnc = opt.callbackFnc; + var args = opt.listColumns; + + //"value" Formatting + if (args != undefined) { + var row = props.grid.getRow(props.rowKey); + for (var i = 0; i < args.length; i++) { + var regEx = new RegExp('\\{' + i + '\\}', 'gi'); + value = value.replace(regEx, row[args[i]]); + } + } + + //Element Setting + //23.07.24 최정민 추 + //iuput button에서 button으로 수정 (아이콘을 넣기위함) + //el id추가 + //버튼에 아이콘을 쓰기위하여 아이콘 클레스명 인자로 받아갈것. + var el = document.createElement('button'); + var icon = document.createElement('i'); + icon.className = btnClass; // 원하는 아이콘 클래스를 설정하세요. + el.className = btnClass; + el.type = 'button'; + el.value = value; + el.id = id; + + //EventListener Setting + el.addEventListener('click', function () { + var callback = callbackFnc + '(props)'; + eval(callback); + }); + + //Element render + this.el = el; +// this.render(props); + if (props.rowKey < 15) { +// // console.log('[Renderer]rowKey->'+props.rowKey+' column->'+props.columnInfo.name+' / el.value->'+el.value); + } + //DataSet Injection ( Dataset에 추가해야 "복사(ctrl+c)" 기능 사용 가능 ) + props.grid.setValue(props.rowKey, props.columnInfo.name, el.value, false); +} +LuluButtonRenderer.prototype.getElement = function () { + return this.el; +} +LuluButtonRenderer.prototype.render = function (props) { + this.el.value = props.value; +} + + +/** + * column 병합 렌더러 + * -설명: 다수의 Column을 하나의 Column으로 병합하여 cell에 출력 한다. + * 필요 시 format 사용이 가능하며 사용방법은 아래와 같다. (※포맷 사용 시 "구분자(separator)"는 적용되지 않는다) + * [단순 컬럼 병합] + * ex) listColumns: ['컬럼1', '컬럼2'], + * separator: '/' + * [포맷사용 컬럼 병합] + * ex) listColumns: ['컬럼1', '컬럼2'], + * format: 'A is {0}. B is {1}. {0}!={1}' + * @param listColumns 병합할 컬럼 name 목록 + * @param separator 컬럼 연결 구분자(default: 공백(' ')) + * @param format 출력 포맷 + * @author 박민규 + * @date 2020.05.28. + */ +var XitColumnMergeRenderer = function (props) { +// // console.log('XitColumnMergeRenderer Called!!-> '+props.columnInfo.name); + //options get + var opt = props.columnInfo.renderer.options; + var args = opt.listColumns; + var separator = opt.separator; + if (fnIsEmpty(separator)) + separator = ' '; + var value = opt.format; + + //Columns merge + if (fnIsEmpty(value)) { + var arrStr = []; + var row = props.grid.getRow(props.rowKey); + args.forEach(function (column) { + arrStr.push(row[column]); + }); + value = arrStr.join(separator); + } else { + var row = props.grid.getRow(props.rowKey); + for (var i = 0; i < args.length; i++) { + var regEx = new RegExp('\\{' + i + '\\}', 'gi'); + value = value.replace(regEx, fnNvl(row[args[i]])); + } + } + + function fnNvl(val) { + if (val == undefined || val == null) + return ''; + return val; + } + + function fnIsEmpty(val) { + if (val == undefined || val == null || val == '' || val == [] || val == {}) + return true; + return false; + } + + //Element Setting + var el = document.createElement('div'); + el.setAttribute('class', 'tui-grid-cell-content'); + el.innerHTML = value; + + //Element render + this.el = el; +// this.render(props); + if (props.rowKey < 15) { +// // console.log('[Renderer]rowKey->'+props.rowKey+' column->'+props.columnInfo.name+' / el.value->'+el.innerHTML); + } + + //DataSet Injection ( Dataset에 추가해야 "복사(ctrl+c)" 기능 사용 가능 ) + props.grid.setValue(props.rowKey, props.columnInfo.name, el.innerHTML, false); +} +XitColumnMergeRenderer.prototype.getElement = function () { + return this.el; +} +XitColumnMergeRenderer.prototype.render = function (props) { + this.el.value = props.value; +} + + +/** + * Button 렌더러 + * @author 최유수 + * @date 2020.07.15. + * formatter : 셀 안에 입력될 문자열. + ,eventType : 셀에 걸 이벤트. + ,eventFunction : 이벤트에 부여될 함수. + + element 속성 + element : 생성 엘리먼트 속성 + type : 생성 엘리먼트의 타입 + value : 들어갈 텍스트 + */ +/** + * 요구사항 + * 셀 속성을 부여할때 + * + * 1.셀에 개발자가 원하는 Element를 생성 할 수 있음 + * 2.1의 속성에 개발자가 원하는 이벤트를 부여 할 수 있음 + * 3. 2의 이벤트에 개발자가 원하는 함수를 부여 할 수 있음 + * 4. 개발자가 원하는만큼 유형을 추가 할 수 있음.(유형이 여러개일수도 아닐수도 있음) + */ +var CustomButtonRenderer = function (props) { + //options get + var opt = props.columnInfo.renderer.options; + //formatter를 구성할 인자값(해당 인자값은 함수형일때 배열일 수 있음.) + var formatter = opt.formatter; + //이벤트로 사용할 함수 + var eventFunction = opt.eventFunction; + //이벤트 속성 + var eventType = opt.eventType; + //객체 유형 + var element = opt.element; + //객체 속성 + var type = opt.type; + + + var formattObject = formatter; + if (typeof formatter == "function") { + //formatter가 함수에 의해 구현이됨, Return값은 Arr, Objcect임; + //Object는 formatter : Text 와 Element로 구성됨. + formattObject = formatter(props); + } else { + //formatter가 단순 텍스트임. + formattObject = opt; + } + + var ele = cellMaker(formattObject, eventFunction, eventType, element, type, props); + this.el = ele; +} +CustomButtonRenderer.prototype.getElement = function () { + return this.el; +} + +//셀을 만듦. +var cellMaker = function (formattObject, eventFunction, eventType, element, type, props) { + var spanEle = document.createElement("span"); + var ele; + + //셀에 1개 이상의 데이터가 들어가는 경우 + if (formattObject instanceof Array && formattObject.length != 0) { + formattObject.forEach(function (elementObject, index, arrays) { + elementObject["eventFunction"] = eventFunction; + elementObject["eventType"] = eventType; + ele = elMaker(elementObject, props); + $(spanEle).append(ele); + //객체가 다수이면 띄어쓰기 함 + if (index < formattObject.length - 1) { + $(spanEle).append(document.createTextNode('\u00a0 // \u00a0')); + } + }); + } + + //셀에 데이터가 1개이지만 함수로 Obj를 가져와서 만듦 + if (formattObject instanceof Object) { + formattObject["eventFunction"] = eventFunction; + formattObject["eventType"] = eventType; + ele = elMaker(formattObject, props); + spanEle.appendChild(ele); + } + + return spanEle; +} + +var elMaker = function (elementObject, props) { + var text = elementObject.formatter + var eventType = elementObject.eventType + var element = elementObject.element + var eventFunction = elementObject.eventFunction + var type = elementObject.type + + var ele; + if (element == "text") { + ele = document.createElement("p"); + ele.style.whiteSpace = 'nowrap'; + ele.style.display = 'inline-block'; + ele.style.fontSize = '11px'; + ele.style.fontFamily = 'Nanum Barun Gothic'; + ele.appendChild(document.createTextNode(text)); + } else { + ele = document.createElement(element); + ele.type = type; + ele.value = text; + } + //이벤트가 함수이면 이벤트 부여함. + if (typeof eventFunction == "function") { + ele.addEventListener(eventType, function (event) { + eventFunction(props, event) + }); + } + + return ele; + +}