Merge branch 'refs/heads/dev' into kurt/kurt

# Conflicts:
#	src/main/resources/mybatis/mapper/biz/totalInfo/TotalInfoMapper_maria.xml
pull/25/head
Kurt92 2 weeks ago
commit 243e0f01e9

@ -3,6 +3,7 @@ package go.kr.project.biz.minwon.dayanswer.service.impl;
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 go.kr.project.vo.code.AsStateEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
@ -29,51 +30,14 @@ public class DayAnswerServiceImpl extends EgovAbstractServiceImpl implements Day
@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);
log.info("selectAllDayAnswer 결과 건수 = {}", list.size());
return list;
List<DayAnswerDto.Response.cpMain> list = dayAnswerMapper.selectAllDayAnswer(dto);
list.forEach(item -> {
item.setAsState(AsStateEnum.getDescByCode(item.getAsState()));
});
return list;
}

@ -0,0 +1,78 @@
package go.kr.project.biz.minwon.indivreg.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.biz.minwon.indivreg.dto.IndivRegDto;
import go.kr.project.biz.minwon.indivreg.service.IndivRegService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Collections;
import java.util.List;
@Slf4j
@Controller
@RequiredArgsConstructor
public class IndivRegController {
// 생성자 인젝션
private final IndivRegService indivRegService;
@GetMapping("/minwon/indivreg/indivreg.do")
public String pageReturnIndivReg() {
return "biz/minwon/indivreg/indivreg" + TilesConstants.BASE;
}
@PostMapping("/minwon/indivreg/indivreg-search-myBatis.ajax")
public ResponseEntity<?> openIndivRegList(@ModelAttribute IndivRegDto.Request.Search dto) {
int totalCount = 0;
dto.setTotalCount(totalCount);
// 페이징 처리를 위한 설정
dto.setPagingYn("Y");
List<IndivRegDto.Response.cpSeallOne> result = indivRegService.searchIndivRegMybatis(dto);
return ApiResponseUtil.successWithGrid(result, dto);
}
@GetMapping("/minwon/indivreg/indivregform.do")
public String openIndivRegForm(Model model) {
// 등록 폼에 필요한 초기 데이터가 있다면 여기서 설정
model.addAttribute("indivreg", new IndivRegDto());
return "biz/minwon/indivreg/indivregform" + TilesConstants.BASE;
}
@PostMapping("/minwon/indivreg/indivreginsert.ajax")
@ResponseBody
public ResponseEntity<?> insertIndivReg(@RequestBody IndivRegDto.Request.InsertData dto) {
try {
log.info("등록 요청: {}", dto);
indivRegService.insertIndivReg(dto);
return ResponseEntity.ok(
Collections.singletonMap("result", "succeses")
);
} catch (Exception e) {
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Collections.singletonMap("result", "fail"));
}
}
}

@ -0,0 +1,60 @@
package go.kr.project.biz.minwon.indivreg.dto;
import go.kr.project.system.common.model.PagingVO;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
public class IndivRegDto {
// 요즘 트렌드에 맞춰 이너클래스를 사용한다.
// Request(파라미터를 받을 형식 객체) 와 Response(응답해줄 형식 객체)로 나눠서 관리한다.
// 프론트에서 파라미터 받아오는 객체
public static class Request {
@Getter
@Setter
public static class Search extends PagingVO {
private String searchCondition;
private String searchKeyword;
private String searchUseYn;
private String fromDt;
private String toDt;
private String worker;
}
@Getter
@Setter
public static class InsertData {
private String soSggcode; // 시군구 코드
private String soInGb; // 등록구분
private String soInDt; // 입력일자
private String soJsdate; // 접수일자
private String soBbsNo; // 목록번호
private String soState; // 상태
private Integer soUser; // 사용자 코드
}
}
// 디비 조회해서 프론트로 반납해주는 객체
public static class Response {
@Getter
@Setter
public static class cpSeallOne {
private String soSggcode ;
private String soInDt;
private String soInGb;
private String soJsdate;
private String soBbsNo;
private String soMmcode;
private String soState;
private Integer soUser;
private String soPutDt;
private String umName;
}
}
}

@ -0,0 +1,16 @@
package go.kr.project.biz.minwon.indivreg.mapper;
import go.kr.project.biz.minwon.indivreg.dto.IndivRegDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface IndivRegMapper {
// SQL문이 있는 xml과 연결 해줌
// 해당 메서드가 호출되면 sql문이 나감
List<IndivRegDto.Response.cpSeallOne> selectAllIndivReg(IndivRegDto.Request.Search searchDto);
void insertIndivReg(IndivRegDto.Request.InsertData dto);
}

@ -0,0 +1,17 @@
package go.kr.project.biz.minwon.indivreg.service;
import go.kr.project.biz.minwon.indivreg.dto.IndivRegDto;
import java.util.List;
// 실제 로직을 이어주는 인터페이스
// 해당 인터페이스를 정의하면 반드시 implements를 통해 구현을 해야한다.
// eGov 에서 필수라 사용할 뿐
public interface IndivRegService {
// 해당 인터페이스에 정의한 메소드는 반드시 impl로 구현해야함.
List<IndivRegDto.Response.cpSeallOne> searchIndivRegMybatis(IndivRegDto.Request.Search dto);
void insertIndivReg(IndivRegDto.Request.InsertData dto);
}

@ -0,0 +1,31 @@
package go.kr.project.biz.minwon.indivreg.service.impl;
import go.kr.project.biz.minwon.indivreg.dto.IndivRegDto;
import go.kr.project.biz.minwon.indivreg.mapper.IndivRegMapper;
import go.kr.project.biz.minwon.indivreg.service.IndivRegService;
import lombok.RequiredArgsConstructor;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@RequiredArgsConstructor
public class IndivRegServiceImpl extends EgovAbstractServiceImpl implements IndivRegService {
//dao : DataBase Access Object로 디비와 연겷하는 역할은 한다.
// 현재 프로젝트에서는 dao역할은 mybatis 매퍼인터페이스로 한다.
private final IndivRegMapper indivRegMapper;
@Override
public List<IndivRegDto.Response.cpSeallOne> searchIndivRegMybatis(IndivRegDto.Request.Search testDto) {
// 매퍼 xml의 resultType을 리턴값으로 받아야한다.
List<IndivRegDto.Response.cpSeallOne> result = indivRegMapper.selectAllIndivReg(testDto);
return result;
}
@Override
public void insertIndivReg(IndivRegDto.Request.InsertData dto) {
indivRegMapper.insertIndivReg(dto);
}
}

@ -3,7 +3,8 @@ package go.kr.project.biz.minwon.init.dto;
import lombok.Getter;
import lombok.Setter;
public class SampleDto {
public class
SampleDto {
// 요즘 트렌드에 맞춰 이너클레스를 사용한다.
// Request(파라미터를 받을 형식 객체) 와 Response(응답해줄 형식 객체)로 나눠서 관리한다.

@ -18,8 +18,6 @@ import java.util.stream.Collectors;
@RequiredArgsConstructor
public class MinwonInitServiceImpl implements MinwonInitService {
private final CpMainRepository cpMainRepository;
private final CpAnswerRepository cpAnswerRepository;
private final MinwonInitQueryDslRepository minwonInitQueryDslRepository;
@Override
@ -30,6 +28,7 @@ public class MinwonInitServiceImpl implements MinwonInitService {
// Enum Desc 변환
result.forEach(item -> {
item.setMmDlgb(MmDlgbEnum.getDescByCode(item.getMmDlgb()));
//item. (MmDlgbEnum.getDescByCode(item.getMmDlgb()));
});

@ -0,0 +1,58 @@
package go.kr.project.biz.minwon.wait.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.biz.minwon.wait.dto.MinwonWaitDto;
import go.kr.project.biz.minwon.wait.service.MinwonWaitService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
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 org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@Controller
@Slf4j
@RequiredArgsConstructor
public class MinwonWaitController {
private final MinwonWaitService minwonWaitService;
/**
*
* @return
*/
@GetMapping("/minwon/wait/wait.do")
@Operation(summary = "민원접수 대기자료", description="민원접수 대기자료 목록 페이지를 조회합니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "조회 성공")
})
public String minwonWaitView(){
return "biz/minwon/wait/wait" + TilesConstants.BASE;
}
@PostMapping("/minwon/wait/minwonwait-myBatis.ajax")
public ResponseEntity<?> minwonwaitAjaxMybatis(@ModelAttribute MinwonWaitDto.Request.Search waitDto, String searchKeyword) {
// 총 게시물 수 조회
int totalCount = 0;
waitDto.setTotalCount(totalCount);
// 페이징 처리를 위한 설정
waitDto.setPagingYn("N");
List<MinwonWaitDto.Response.cpMainAnswerCancel> result = minwonWaitService.findminwonwaitSearchMybatis(waitDto, searchKeyword);
return ApiResponseUtil.successWithGrid(result, waitDto);
}
}

@ -0,0 +1,39 @@
package go.kr.project.biz.minwon.wait.dto;
import go.kr.project.system.common.model.PagingVO;
import lombok.Getter;
import lombok.Setter;
public class MinwonWaitDto {
public static class Request {
@Getter
@Setter
public static class Search extends PagingVO {
private String mmDlgb;
}
}
public static class Response {
@Getter
@Setter
public static class cpMainAnswerCancel{
private String mmCode;
private String mmDlgb;
private String asBbsNo;
private String mmSgnm;
private String mmSgtel;
private String mmDate;
private String asLimitDt;
private String mmIndt;
private String asJsno;
private String mmCarno;
private String ccCause;
private String asIngb;
private String mmText;
private String asText;
}
}
}

@ -0,0 +1,11 @@
package go.kr.project.biz.minwon.wait.mapper;
import go.kr.project.biz.minwon.wait.dto.MinwonWaitDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface MinwonWaitMapper {
List<MinwonWaitDto.Response.cpMainAnswerCancel> findminwonwaitSearchMybatis(MinwonWaitDto.Request.Search waitDto, String searchKeyword);
}

@ -0,0 +1,178 @@
//package go.kr.project.biz.minwon.wait.repository;
//
//import com.querydsl.core.types.Projections;
//import com.querydsl.jpa.impl.JPAQueryFactory;
//import lombok.RequiredArgsConstructor;
//import org.springframework.stereotype.Repository;
//
//import java.util.List;
//
//import static go.kr.project.domain.entity.QCpAnswer.cpAnswer;
//import static go.kr.project.domain.entity.QCpMain.cpMain;
//
//@Repository
//@RequiredArgsConstructor
//public class MinwonWaitQueryDsRepository {
//
// private final JPAQueryFactory queryFactory;
//
// public List<MinwonWaitDto.Response.WaitAnswers> findWaitAnswers(MinwonWaitDto.Request.SearchMinwonWaitList dto) {
//
// List<MinwonWaitDto.Response.WaitAnswers> result = queryFactory
// .select(
// Projections.fields(
// MinwonWaitDto.Response.WaitAnswers.class,
// cpAnswer.asJsdate,
// cpAnswer.asJsno,
// cpAnswer.asJsnoM,
// cpAnswer.asState,
// cpAnswer.asPostCd,
// cpAnswer.asLimitDt,
// cpAnswer.asPostDt,
// cpMain.mmCarno
// )
// )
// .from(cpMain)
// .innerJoin(cpAnswer).on(cpMain.mmCode.eq(cpAnswer.asMmcode))
// .where(
// //cpAnswer.asState.eq("01")
// cpMain.mmState.eq("01"),
// cpAnswer.asState.eq("0")
// )
// .fetch();
// return result;
// }
//
// public List<MinwonWaitDto.Response.WaitAnswers> findWaitAnswersSearch(MinwonWaitDto.Request.SearchMinwonWaitList dto, String searchCondition, String searchKeyword, String searchStartDt, String searchEndDt) {
//
// if (searchCondition.equals("jsdate")) {
// List<MinwonWaitDto.Response.WaitAnswers> result = queryFactory
// .select(
// Projections.fields(
// MinwonWaitDto.Response.WaitAnswers.class,
// cpAnswer.asJsdate,
// cpAnswer.asJsno,
// cpAnswer.asJsnoM,
// cpAnswer.asState,
// cpAnswer.asPostCd,
// cpAnswer.asLimitDt,
// cpAnswer.asPostDt,
// cpMain.mmCarno
// )
// )
// .from(cpMain)
// .innerJoin(cpAnswer).on(cpMain.mmCode.eq(cpAnswer.asMmcode))
// .where(
// cpMain.mmState.eq("01"),
//// cpAnswer.asState.eq("0"),
// cpAnswer.asJsdate.between(searchStartDt, searchEndDt)
// )
// .fetch();
// return result;
//
// } else if (searchCondition.equals("jsno")) {
// List<MinwonWaitDto.Response.WaitAnswers> result = queryFactory
// .select(
// Projections.fields(
// MinwonWaitDto.Response.WaitAnswers.class,
// cpAnswer.asJsdate,
// cpAnswer.asJsno,
// cpAnswer.asJsnoM,
// cpAnswer.asState,
// cpAnswer.asPostCd,
// cpAnswer.asLimitDt,
// cpAnswer.asPostDt,
// cpMain.mmCarno
// )
// )
// .from(cpMain)
// .innerJoin(cpAnswer).on(cpMain.mmCode.eq(cpAnswer.asMmcode))
// .where(
// cpMain.mmState.eq("01"),
//// cpAnswer.asState.eq("0"),
// cpAnswer.asJsno.like("%" + searchKeyword + "%")
// )
// .fetch();
// return result;
//
// } else if (searchCondition.equals("iimitdt")) {
// List<MinwonWaitDto.Response.WaitAnswers> result = queryFactory
// .select(
// Projections.fields(
// MinwonWaitDto.Response.WaitAnswers.class,
// cpAnswer.asJsdate,
// cpAnswer.asJsno,
// cpAnswer.asJsnoM,
// cpAnswer.asState,
// cpAnswer.asPostCd,
// cpAnswer.asLimitDt,
// cpAnswer.asPostDt,
// cpMain.mmCarno
// )
// )
// .from(cpMain)
// .innerJoin(cpAnswer).on(cpMain.mmCode.eq(cpAnswer.asMmcode))
// .where(
// cpMain.mmState.eq("01"),
//// cpAnswer.asState.eq("0"),
// cpAnswer.asLimitDt.between(searchStartDt, searchEndDt)
// )
// .fetch();
// return result;
//
// } else {
// List<MinwonWaitDto.Response.WaitAnswers> result = queryFactory
// .select(
// Projections.fields(
// MinwonWaitDto.Response.WaitAnswers.class,
// cpAnswer.asJsdate,
// cpAnswer.asJsno,
// cpAnswer.asJsnoM,
// cpAnswer.asState,
// cpAnswer.asPostCd,
// cpAnswer.asLimitDt,
// cpAnswer.asPostDt,
// cpMain.mmCarno
// )
// )
// .from(cpMain)
// .innerJoin(cpAnswer).on(cpMain.mmCode.eq(cpAnswer.asMmcode))
// .where(
// cpMain.mmState.eq("01"),
//// cpAnswer.asState.eq("0")
// cpAnswer.asJsno.like("%" +searchKeyword + "%")
// )
// .fetch();
// return result;
// }
//
//
///*
// List<MinwonWaitDto.Response.WaitAnswers> result = queryFactory
// .select(
// Projections.fields(
// MinwonWaitDto.Response.WaitAnswers.class,
// cpAnswer.asJsdate,
// cpAnswer.asJsno,
// cpAnswer.asJsnoM,
// cpAnswer.asState,
// cpAnswer.asPostCd,
// cpAnswer.asLimitDt,
// cpAnswer.asPostDt,
// cpMain.mmCarno
// )
// )
// .from(cpMain)
// .innerJoin(cpAnswer).on(cpMain.mmCode.eq(cpAnswer.asMmcode))
// .where(
// cpMain.mmState.eq("01"),
//// cpAnswer.asState.eq("0"),
// cpAnswer.asJsno.like("%" + searchKeyword + "%")
// )
// .fetch();
// return result;
//
// */
//
// }
//}

@ -0,0 +1,11 @@
package go.kr.project.biz.minwon.wait.service;
import go.kr.project.biz.minwon.wait.dto.MinwonWaitDto;
import java.util.List;
public interface MinwonWaitService {
List<MinwonWaitDto.Response.cpMainAnswerCancel> findminwonwaitSearchMybatis(MinwonWaitDto.Request.Search waitDto, String searchKeyword);
}

@ -0,0 +1,40 @@
package go.kr.project.biz.minwon.wait.service.impl;
import go.kr.project.biz.minwon.wait.dto.MinwonWaitDto;
import go.kr.project.biz.minwon.wait.mapper.MinwonWaitMapper;
import go.kr.project.biz.minwon.wait.service.MinwonWaitService;
import go.kr.project.domain.repo.cp.CpAnswerRepository;
import go.kr.project.domain.repo.cp.CpMainRepository;
import go.kr.project.vo.code.AsIngbEnum;
import go.kr.project.vo.code.MmDlgbEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
public class MinwonWaitServiceImpl implements MinwonWaitService {
private final CpMainRepository cpMainRepository;
private final CpAnswerRepository cpAnswerRepository;
// private final MinwonWaitQueryDsRepository minwonWaitQueryDsRepository;
private final MinwonWaitMapper minwonWaitMapper;
@Override
public List<MinwonWaitDto.Response.cpMainAnswerCancel> findminwonwaitSearchMybatis(MinwonWaitDto.Request.Search waitDto, String searchKeyword) {
List<MinwonWaitDto.Response.cpMainAnswerCancel> result = minwonWaitMapper.findminwonwaitSearchMybatis(waitDto, searchKeyword);
result.forEach(item -> {
item.setMmDlgb(MmDlgbEnum.getDescByCode(item.getMmDlgb()));
item.setAsIngb(AsIngbEnum.getDescByCode(item.getAsIngb()));
});
return result;
}
}

@ -0,0 +1,40 @@
package go.kr.project.biz.search.caution.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.biz.search.caution.model.CautionDto;
import go.kr.project.biz.search.caution.service.CautionService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
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 CautionController {
private final CautionService cautionService;
@GetMapping("/search/caution/caution.do")
public String cautionPageReturn() {
return "biz/search/caution" + TilesConstants.BASE;
}
@PostMapping("/search/caution/caution-select.ajax")
public ResponseEntity<?> list(@ModelAttribute CautionDto.Request.Search dto) {
dto.setTotalCount(0);
dto.setPagingYn("N");
List<CautionDto.Response.cpMain> result = cautionService.selectAllSearch(dto);
return ApiResponseUtil.successWithGrid(result,dto);
}
}

@ -0,0 +1,12 @@
package go.kr.project.biz.search.caution.mapper;
import go.kr.project.biz.search.caution.model.CautionDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface CautionMapper {
List<CautionDto.Response.cpMain> selectAllSearch(CautionDto.Request.Search dto);
}

@ -0,0 +1,73 @@
package go.kr.project.biz.search.caution.model;
import go.kr.project.system.common.model.PagingVO;
import lombok.Getter;
import lombok.Setter;
public class CautionDto {
public static class Request {
@Getter
@Setter
public static class Search extends PagingVO {
private String searchCondition;
private String searchCondition1;
private String searchCondition2;
private String searchCondition3;
private String searchCondition4;
private String searchKeyword;
private String searchStartDt;
private String searchEndDt;
private String searchCarno;
private String searchName;
private String searchJno;
private String searchUser;
private String searchTel;
private String searchBbsno;
private String searchPos;
private String searchAddr;
private String searchTime1;
private String searchTime2;
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 mmState;
private String mmCode;
private String asUser;
private String asJsno;
private String asJsdate;
private String asBbsNo;
private String ccCause;
private String ccDate;
private String ccEtc;
}
@Getter
@Setter
public static class Violation {
private String vlCode;
private String vlId;
}
}
}

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

@ -0,0 +1,30 @@
package go.kr.project.biz.search.caution.service.impl;
import go.kr.project.biz.search.caution.mapper.CautionMapper;
import go.kr.project.biz.search.caution.model.CautionDto;
import go.kr.project.biz.search.caution.service.CautionService;
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 CautionServiceImpl extends EgovAbstractServiceImpl implements CautionService {
private final CautionMapper cautionMapper;
@Override
public List<CautionDto.Response.cpMain> selectAllSearch(CautionDto.Request.Search dto) {
List<CautionDto.Response.cpMain> list = cautionMapper.selectAllSearch(dto);
return list;
}
}

@ -0,0 +1,42 @@
package go.kr.project.biz.search.filtersearch.controller;
import egovframework.constant.TilesConstants;
import egovframework.util.ApiResponseUtil;
import go.kr.project.biz.search.filtersearch.model.FilterSearchDto;
import go.kr.project.biz.search.filtersearch.service.FilterSearchService;
import go.kr.project.biz.search.model.SearchDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
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 FilterSearchController {
private final FilterSearchService filterSearchService;
@GetMapping("/search/filtersearch/filtersearch.do")
public String searchPageReturn() {
return "biz/search/filtersearch" + TilesConstants.BASE;
}
@PostMapping("/search/filtersearch/filtersearch-select.ajax")
public ResponseEntity<?> list(@ModelAttribute FilterSearchDto.Request.Search dto) {
dto.setTotalCount(0);
dto.setPagingYn("N");
List<FilterSearchDto.Response.cpMain> result = filterSearchService.selectAllSearch(dto);
return ApiResponseUtil.successWithGrid(result,dto);
}
}

@ -0,0 +1,12 @@
package go.kr.project.biz.search.filtersearch.mapper;
import go.kr.project.biz.search.filtersearch.model.FilterSearchDto;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface FilterSearchMapper {
List<FilterSearchDto.Response.cpMain> selectAllSearch(FilterSearchDto.Request.Search dto);
}

@ -0,0 +1,73 @@
package go.kr.project.biz.search.filtersearch.model;
import go.kr.project.system.common.model.PagingVO;
import lombok.Getter;
import lombok.Setter;
public class FilterSearchDto {
public static class Request {
@Getter
@Setter
public static class Search extends PagingVO {
private String searchCondition;
private String searchCondition1;
private String searchCondition2;
private String searchCondition3;
private String searchCondition4;
private String searchKeyword;
private String searchStartDt;
private String searchEndDt;
private String searchCarno;
private String searchName;
private String searchJno;
private String searchUser;
private String searchTel;
private String searchBbsno;
private String searchPos;
private String searchAddr;
private String searchTime1;
private String searchTime2;
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 mmState;
private String mmCode;
private String asUser;
private String asJsno;
private String asJsdate;
private String asBbsNo;
private String ccCause;
private String ccDate;
private String ccEtc;
}
@Getter
@Setter
public static class Violation {
private String vlCode;
private String vlId;
}
}
}

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

@ -0,0 +1,38 @@
package go.kr.project.biz.search.filtersearch.service.impl;
import go.kr.project.biz.search.filtersearch.mapper.FilterSearchMapper;
import go.kr.project.biz.search.filtersearch.model.FilterSearchDto;
import go.kr.project.biz.search.filtersearch.service.FilterSearchService;
import go.kr.project.vo.code.MmIngbEnum;
import go.kr.project.vo.code.MmStateEnum;
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 FilterSearchServiceImpl extends EgovAbstractServiceImpl implements FilterSearchService {
private final FilterSearchMapper filterSearchMapper;
@Override
public List<FilterSearchDto.Response.cpMain> selectAllSearch(FilterSearchDto.Request.Search dto) {
List<FilterSearchDto.Response.cpMain> list = filterSearchMapper.selectAllSearch(dto);
// Enum Desc 변환
list.forEach(item -> {
item.setMmIngb(MmIngbEnum.getDescByCode(item.getMmIngb()));
item.setMmState(MmStateEnum.getDescByCode(item.getMmState()));
});
if (dto.getSearchCondition1() != null && !dto.getSearchCondition1().isEmpty()) {
MmStateEnum.getCodeByDesc(dto.getSearchCondition1());
}
return list;
}
}

@ -35,7 +35,9 @@ public class SearchDto {
private String mmImageGb;
private String mmImageCnt;
private String mmCarcheck;
private String mmState;
private String mmCode;
}
}
}

@ -3,6 +3,9 @@ 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 go.kr.project.vo.code.MmDlgbEnum;
import go.kr.project.vo.code.MmIngbEnum;
import go.kr.project.vo.code.MmStateEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.egovframe.rte.fdl.cmmn.EgovAbstractServiceImpl;
@ -22,6 +25,14 @@ public class SearchServiceImpl extends EgovAbstractServiceImpl implements Search
List<SearchDto.Response.cpMain> list = searchMapper.selectAllSearch(dto);
// Enum Desc 변환
list.forEach(item -> {
item.setMmIngb(MmIngbEnum.getDescByCode(item.getMmIngb()));
item.setMmState(MmStateEnum.getDescByCode(item.getMmState()));
});
return list;
}

@ -118,7 +118,7 @@ public class LoginController {
/**
* (AJAX)
* (ApiResponse) .
*
*
* @param userAcnt
* @param passwd
* @param saveId
@ -214,6 +214,7 @@ public class LoginController {
* @param request HTTP
* @param response HTTP
* @return
* d;lfkjas;dfjasl;dfj;l
*/
@Operation(summary = "로그아웃 처리", description = "사용자 로그아웃을 처리하고 로그인 페이지로 리다이렉트합니다.")
@ApiResponses(value = {
@ -240,7 +241,7 @@ public class LoginController {
/**
* (AJAX)
* (ApiResponse) .
*
*
* @param request HTTP
* @param response HTTP
* @return ResponseEntity
@ -267,7 +268,7 @@ public class LoginController {
/**
*
* (ApiResponse) .
*
*
* @param userId ID
* @return ResponseEntity
*/

@ -61,4 +61,4 @@ public class SessionVO implements Serializable {
//이미지 경로
private String imgPath;
}
}

@ -8,21 +8,21 @@ import java.util.Map;
@Getter
public enum AsIngbEnum {
// APP(110, "생활불편신고"), // 안전신문고(120)으로 통합됨.
SMG_SEAL(120, "안전신문고"),
POLICE(130, "경찰청"),
SMG(183, "국민신문고"),
ETC(181, "기타");
SMG_SEAL("120", "안전신문고"),
POLICE("130", "경찰청"),
SMG("183", "국민신문고"),
ETC("181", "기타");
private int code;
private String code;
private String desc;
AsIngbEnum(int code, String desc) {
AsIngbEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
private static final Map<Integer, AsIngbEnum> CODE_MAP = new HashMap<>();
private static final Map<String, AsIngbEnum> CODE_MAP = new HashMap<>();
private static final Map<String, AsIngbEnum> DESC_MAP = new HashMap<>();
static {
@ -33,19 +33,19 @@ public enum AsIngbEnum {
}
// code → desc
public static String getDescByCode(int code) {
public static String getDescByCode(String code) {
AsIngbEnum e = CODE_MAP.get(code);
return e != null ? e.desc : null;
}
// desc → code
public static Integer getCodeByDesc(String desc) {
public static String getCodeByDesc(String desc) {
AsIngbEnum e = DESC_MAP.get(desc);
return e != null ? e.code : null;
}
// code → enum
public static AsIngbEnum fromCode(int code) {
public static AsIngbEnum fromCode(String code) {
return CODE_MAP.get(code);
}

@ -0,0 +1,53 @@
<?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.minwon.indivreg.mapper.IndivRegMapper">
<!--
매퍼인터페이스의 매소드명과 id가 일치해야 한다.
parameterType은 사용할 파라미터,
resultType은 쿼리 결과를 반납하는 객체를 넣어준다.
아래 보면 이너클래스는 $형태로 들어간다.
-->
<select id="selectAllIndivReg"
parameterType="go.kr.project.biz.minwon.indivreg.dto.IndivRegDto$Request$Search"
resultType="go.kr.project.biz.minwon.indivreg.dto.IndivRegDto$Response$cpSeallOne">
select *
from CP_SEALL_ONE
inner join CP_USER on (SO_USER=UM_CODE)
WHERE 1=1
<if test="searchKeyword != null and searchKeyword != ''">
<choose>
<when test="searchCondition == 'soJsdate'">
AND SO_JSDATE LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'soBbsNo'">
AND SO_BBS_NO LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<when test="searchCondition == 'umName'">
AND UM_NAME LIKE CONCAT('%', #{searchKeyword}, '%')
</when>
<otherwise>
AND (
SO_JSDATE LIKE CONCAT('%', #{searchKeyword}, '%')
OR SO_BBS_NO LIKE CONCAT('%', #{searchKeyword}, '%')
OR UM_NAME LIKE CONCAT('%', #{searchKeyword}, '%')
)
</otherwise>
</choose>
</if>
ORDER BY SO_SGGCODE, SO_JSDATE, SO_BBS_NO
</select>
<insert id="insertIndivReg" parameterType="go.kr.project.biz.minwon.indivreg.dto.IndivRegDto$Request$InsertData">
INSERT INTO CP_SEALL_ONE (
SO_SGGCODE, SO_IN_GB, SO_IN_DT, SO_JSDATE, SO_BBS_NO, SO_STATE, SO_USER
) VALUES (
#{soSggcode}, #{soInGb}, #{soInDt}, #{soJsdate}, #{soBbsNo}, #{soState}, #{soUser}, #{soMMcode}, #{soPutDt}
)
</insert>
</mapper>

@ -0,0 +1,38 @@
<?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.minwon.wait.mapper.MinwonWaitMapper">
<select id="findminwonwaitSearchMybatis"
parameterType="go.kr.project.biz.minwon.wait.dto.MinwonWaitDto$Request$Search"
resultType="go.kr.project.biz.minwon.wait.dto.MinwonWaitDto$Response$cpMainAnswerCancel">
select main.MM_CODE
, main.MM_DLGB
, answer.AS_BBS_NO
, main.MM_SGNM
, main.MM_SGTEL
, main.MM_DATE
, answer.AS_LIMIT_DT
, main.MM_INDT
, answer.AS_JSNO
, main.MM_CARNO
, cancel.CC_CAUSE
, answer.AS_INGB
, etc.MM_TEXT
, answer.AS_TEXT
from cp_main main
inner join cp_answer answer on (answer.AS_MMCODE = main.MM_CODE)
left outer join cp_cancel cancel on (cancel.CC_MMCODE = main.MM_CODE)
left outer join cp_main_etc1 etc on (etc.MM_CODE = main.MM_CODE)
where AS_STATE = '1'
<if test="searchKeyword != null and searchKeyword != ''">
and MM_DLGB = #{searchKeyword}
</if>
</select>
</mapper>

@ -0,0 +1,126 @@
<?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.caution.mapper.CautionMapper">
<select id="selectAllSearch"
parameterType="go.kr.project.biz.search.caution.model.CautionDto"
resultType="go.kr.project.biz.search.caution.model.CautionDto$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,
DATE_FORMAT(A.AS_JSDATE, '%Y-%m-%d') AS AS_JSDATE,
A.AS_USER,
A.AS_JSNO,
A.AS_BBS_NO,
C.CC_CAUSE,
DATE_FORMAT(C.CC_DATE, '%Y-%m-%d') AS CC_DATE,
C.CC_ETC,
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
LEFT OUTER JOIN CP_OWNER O ON M.MM_OMCODE=O.OM_CODE
<where>
<!-- 날짜 -->
<if test="searchStartDt != null and searchStartDt != ''">
AND M.MM_DATE &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND M.MM_DATE &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
<!-- 시간 -->
<if test="searchTime1 != null and searchTime1 != ''">
AND M.MM_TIME &gt;= REPLACE(#{searchTime1}, '-', '')
</if>
<if test="searchTime2 != null and searchTime2 != ''">
AND M.MM_TIME &lt;= REPLACE(#{searchTime2}, '-', '')
</if>
<!-- 위반내용 (searchCondition : code1~6) -->
<!-- <if test="searchCondition != null and searchCondition != ''">-->
<!-- &lt;!&ndash; 코드가없다. &ndash;&gt;-->
<!-- AND M.VL_CODE = #{searchCondition}-->
<!-- </if>-->
<!-- 처리상태 (searchCondition1 : code1~22) -->
<if test="searchCondition1 != null and searchCondition1 != ''">
AND M.MM_STATE = #{searchCondition1}
</if>
<!-- 등록구분 -->
<if test="searchCondition2 != null and searchCondition2 != ''">
AND M.MM_DLGB = #{searchCondition2}
</if>
<!-- 자료출처 -->
<if test="searchCondition3 != null and searchCondition3 != ''">
AND M.MM_INGB = #{searchCondition3}
</if>
<!-- &lt;!&ndash; 법정동 &ndash;&gt;-->
<!-- <if test="searchCondition4 != null and searchCondition4 != ''">-->
<!-- AND M.MM_DONG = #{searchCondition4}-->
<!-- </if>-->
<!-- ===== 텍스트 입력 필드들 (값이 있으면 AND LIKE) ===== -->
<!-- 차량번호 -->
<if test="searchCarno != null and searchCarno != ''">
AND M.MM_CARNO LIKE CONCAT('%', #{searchCarno}, '%')
</if>
<!-- 소유자성명 -->
<if test="searchName != null and searchName != ''">
AND O.OM_NAME LIKE CONCAT('%', #{searchName}, '%')
</if>
<!-- 주민번호 -->
<if test="searchJno != null and searchJno != ''">
AND O.OM_JNO LIKE CONCAT('%', #{searchJno}, '%')
</if>
<!-- 신고자 -->
<if test="searchUser != null and searchUser != ''">
AND A.AS_USER LIKE CONCAT('%', #{searchUser}, '%')
</if>
<!-- 신고자 전화번호 -->
<if test="searchTel != null and searchTel != ''">
AND A.AS_TEL LIKE CONCAT('%', #{searchTel}, '%')
</if>
<!-- 목록번호 -->
<if test="searchBbsno != null and searchBbsno != ''">
AND A.AS_BBS_NO LIKE CONCAT('%', #{searchBbsno}, '%')
</if>
<!-- &lt;!&ndash; 위반장소 &ndash;&gt;-->
<!-- <if test="searchPos != null and searchPos != ''">-->
<!-- AND M.MM_PLACE LIKE CONCAT('%', #{searchPos}, '%')-->
<!-- </if>-->
<!-- 상세주소 (예: O.OM_ADDR) -->
<!-- <if test="searchAddr != null and searchAddr != ''">-->
<!-- AND O.OM_ADDR LIKE CONCAT('%', #{searchAddr}, '%')-->
<!-- </if>-->
</where>
ORDER BY AS_JSDATE DESC, AS_JSNO DESC
</select>
<select id="selectViolationList"
resultType="go.kr.project.biz.search.filtersearch.model.FilterSearchDto$Response$Violation">
SELECT
VL_CODE,
VL_ID
FROM CP_VIOLATION
</select>
</mapper>

@ -0,0 +1,126 @@
<?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.filtersearch.mapper.FilterSearchMapper">
<select id="selectAllSearch"
parameterType="go.kr.project.biz.search.filtersearch.model.FilterSearchDto"
resultType="go.kr.project.biz.search.filtersearch.model.FilterSearchDto$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,
DATE_FORMAT(A.AS_JSDATE, '%Y-%m-%d') AS AS_JSDATE,
A.AS_USER,
A.AS_JSNO,
A.AS_BBS_NO,
C.CC_CAUSE,
DATE_FORMAT(C.CC_DATE, '%Y-%m-%d') AS CC_DATE,
C.CC_ETC,
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
LEFT OUTER JOIN CP_OWNER O ON M.MM_OMCODE=O.OM_CODE
<where>
<!-- 날짜 -->
<if test="searchStartDt != null and searchStartDt != ''">
AND M.MM_DATE &gt;= REPLACE(#{searchStartDt}, '-', '')
</if>
<if test="searchEndDt != null and searchEndDt != ''">
AND M.MM_DATE &lt;= REPLACE(#{searchEndDt}, '-', '')
</if>
<!-- 시간 -->
<if test="searchTime1 != null and searchTime1 != ''">
AND M.MM_TIME &gt;= REPLACE(#{searchTime1}, '-', '')
</if>
<if test="searchTime2 != null and searchTime2 != ''">
AND M.MM_TIME &lt;= REPLACE(#{searchTime2}, '-', '')
</if>
<!-- 위반내용 (searchCondition : code1~6) -->
<!-- <if test="searchCondition != null and searchCondition != ''">-->
<!-- &lt;!&ndash; 코드가없다. &ndash;&gt;-->
<!-- AND M.VL_CODE = #{searchCondition}-->
<!-- </if>-->
<!-- 처리상태 (searchCondition1 : code1~22) -->
<if test="searchCondition1 != null and searchCondition1 != ''">
AND M.MM_STATE = #{searchCondition1}
</if>
<!-- 등록구분 -->
<if test="searchCondition2 != null and searchCondition2 != ''">
AND M.MM_DLGB = #{searchCondition2}
</if>
<!-- 자료출처 -->
<if test="searchCondition3 != null and searchCondition3 != ''">
AND M.MM_INGB = #{searchCondition3}
</if>
<!-- &lt;!&ndash; 법정동 &ndash;&gt;-->
<!-- <if test="searchCondition4 != null and searchCondition4 != ''">-->
<!-- AND M.MM_DONG = #{searchCondition4}-->
<!-- </if>-->
<!-- ===== 텍스트 입력 필드들 (값이 있으면 AND LIKE) ===== -->
<!-- 차량번호 -->
<if test="searchCarno != null and searchCarno != ''">
AND M.MM_CARNO LIKE CONCAT('%', #{searchCarno}, '%')
</if>
<!-- 소유자성명 -->
<if test="searchName != null and searchName != ''">
AND O.OM_NAME LIKE CONCAT('%', #{searchName}, '%')
</if>
<!-- 주민번호 -->
<if test="searchJno != null and searchJno != ''">
AND O.OM_JNO LIKE CONCAT('%', #{searchJno}, '%')
</if>
<!-- 신고자 -->
<if test="searchUser != null and searchUser != ''">
AND A.AS_USER LIKE CONCAT('%', #{searchUser}, '%')
</if>
<!-- 신고자 전화번호 -->
<if test="searchTel != null and searchTel != ''">
AND A.AS_TEL LIKE CONCAT('%', #{searchTel}, '%')
</if>
<!-- 목록번호 -->
<if test="searchBbsno != null and searchBbsno != ''">
AND A.AS_BBS_NO LIKE CONCAT('%', #{searchBbsno}, '%')
</if>
<!-- &lt;!&ndash; 위반장소 &ndash;&gt;-->
<!-- <if test="searchPos != null and searchPos != ''">-->
<!-- AND M.MM_PLACE LIKE CONCAT('%', #{searchPos}, '%')-->
<!-- </if>-->
<!-- 상세주소 (예: O.OM_ADDR) -->
<!-- <if test="searchAddr != null and searchAddr != ''">-->
<!-- AND O.OM_ADDR LIKE CONCAT('%', #{searchAddr}, '%')-->
<!-- </if>-->
</where>
ORDER BY AS_JSDATE DESC, AS_JSNO DESC
</select>
<select id="selectViolationList"
resultType="go.kr.project.biz.search.filtersearch.model.FilterSearchDto$Response$Violation">
SELECT
VL_CODE,
VL_ID
FROM CP_VIOLATION
</select>
</mapper>

@ -23,7 +23,7 @@
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
LEFT OUTER JOIN CP_OWNER O ON M.MM_OMCODE=O.OM_CODE
<where>
<!-- 날짜 -->
<if test="searchStartDt != null and searchStartDt != ''">

@ -10,7 +10,7 @@
UPDATE cp_main
SET
MM_LAWGB = ${mmLawgb}
MM_LAWGB = ${mmLawgb},
MM_SGTEL = ${mmSgtel},
MM_SGPOS = ${mmSgpos},
MM_KEUM1 = ${mmKeum1}

@ -17,7 +17,7 @@
<li class="th">검색구분</li>
<li>
<select id="searchCondition" name="searchCondition" class="input">
<option value="">검색구분</option>
<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>
@ -374,7 +374,7 @@
processData: true
}
},
initialRequest: false, // 직접 readData(1) 호출할 거라 false
initialRequest: true, // 직접 readData(1) 호출할 거라 false
serializer: function (params) {
setSearchCond();
SEARCH_COND.perPage = params.perPage;

@ -0,0 +1,364 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- Main body -->
<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='/minwon/indivreg/indivregform.do'/>'" class="newbtn bg1">요청등록</button>
<button type="button" onclick="location.href='<c:url value='/template/noticeSample/register.do'/>'" class="newbtn bg1">한건삭제</button>
<button type="button" onclick="location.href='<c:url value='/template/noticeSample/register.do'/>'" class="newbtn bg1">전체삭제</button>
</section>
</div>
</section>
<input type="text" id="bbs_no">
<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="soJsdate" <c:if test="${paramVO.searchCondition eq 'soJsdate'}">selected</c:if>>접수일자</option>
<option value="soBbsNo" <c:if test="${paramVO.searchCondition eq 'soBbsNo'}">selected</c:if>>목록번호</option>
<option value="umName" <c:if test="${paramVO.searchCondition eq 'umName'}">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="worker" name="worker" class="input" value=""/></li>
<li class="th">사용여부</li>
<li>
<select id="searchUseYn" name="searchUseYn" class="input">
<option value="">전체</option>
<option value="Y" <c:if test="${param.searchUseYn eq 'Y'}">selected</c:if>>사용</option>
<option value="N" <c:if test="${param.searchUseYn eq 'N'}">selected</c:if>>미사용</option>
</select>
</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="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>
</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>
</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: '시군구코드',
name: 'soSggcode',
width: 70,
align: 'center'
},
{
header: '신청일시',
name: 'soInDt',
width: 70,
align: 'center'
},
{
header: '등록구분',
name: 'soInGb',
width: 50,
align: 'center'
},
{
header: '접수일자',
name: 'soJsdate',
width: 70,
align: 'center'
},
{
header: '목록번호',
name: 'soBbsNo',
width: 70,
align: 'center'
},
{
header: '단속ID',
name: 'soMmcode',
width: 120,
align: 'center'
},
{
header: '자료상태',
name: 'soState',
width: 70,
align: 'center'
},
{
header: '등록사용자',
name: 'soUser',
width: 70,
align: 'center'
},
{
header: '등록일시',
name: 'soPutDt',
width: 70,
align: 'center'
},
{
header: '사용자성명',
name: 'umName',
width: 70,
align: 'center'
}
]);
return gridConfig;
},
/**
* 데이터 소스 생성
* @returns {Object} 데이터 소스 객체
*/
createDataSource: function() {
return {
api: {
readData: {
url: '<c:url value="/minwon/indivreg/indivreg-search-myBatis.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) {
var popUrl = '${pageContext.request.contextPath}/total/info.do';
var popTitle = "비밀번호 변경";
var popOption = "width=1400px, height=900px, resizable=yes, scrollbars=yes, location=no, top=100px, left=100px";
window.open(popUrl, popTitle, popOption);
<%--if (ev.rowKey !== undefined && ev.columnName !== '_number') {--%>
<%-- var rowData = self.instance.getRow(ev.rowKey);--%>
<%-- if (rowData && rowData.noticeId) {--%>
<%-- // 새로운 함수를 사용하여 URL 생성 및 페이지 이동--%>
<%-- window.location.href = "<c:url value="/minwon/init/init.do"/>";--%>
<%-- console.log("asd11`11")--%>
<%-- }--%>
<%--}--%>
});
}
},
/**
* 이벤트 핸들러 설정
*/
eventBindEvents: function() {
var self = this;
// 검색 버튼 클릭 이벤트
$('#search_btn').on('click', function() {
// 등록일 from~to 유효성 검사
var startDate = $("#searchStartDt").val();
var endDate = $("#searchEndDt").val();
// 시작일과 종료일 중 하나만 입력된 경우 체크
if ((startDate && !endDate) || (!startDate && endDate)) {
alert("등록일 검색 시 시작일과 종료일을 모두 입력해주세요.");
return;
}
// 시작일과 종료일이 모두 입력된 경우 유효성 검사
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;
}
}
// 페이지를 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'); // 검색 버튼 클릭 이벤트 트리거
}
});
// perPage 변경 이벤트 추가
$('#perPageSelect').on('change', function() {
var perPage = parseInt($(this).val(), 10);
// Grid의 perPage 설정 변경 및 데이터 리로드
self.grid.instance.setPerPage(perPage);
});
},
/**
* 모듈 초기화
*/
init: function() {
// 그리드 생성
this.grid.create();
// 이벤트 핸들러 설정
this.eventBindEvents();
this.grid.instance.readData(${param.page eq null or param.page eq 0 ? 1 : param.page});
}
};
// 페이지 로드 시 초기화
$(function() {
NoticeList.init();
});
// 전역 네임스페이스에 모듈 노출
window.NoticeList = NoticeList;
})(window, jQuery);
</script>

@ -0,0 +1,124 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- TOAST UI Editor CDN -->
<link rel="stylesheet" href="<c:url value="/plugins/tuiEditor/3.2.2/toastui-editor.min.css"/>" />
<script src="<c:url value="/plugins/tuiEditor/3.2.2/toastui-editor-all.min.js"/>"></script>
<!-- TOAST UI Editor 한국어 지원 -->
<script src="<c:url value="/plugins/tuiEditor/3.2.2/i18n/ko-kr.min.js"/>"></script>
<!-- Main body -->
<div class="main_body">
<input type="text" id="soJsdate" name="soJsdate" class="input calender datepicker" value="${param.soJsdate}" />
<section id="section8" class="main_bars">
<div class="bgs-main">
<section id="section5">
<div class="sub_title"></div>
<button type="button" id="btnSave" class="newbtn bg4">확인</button>
<button type="button" onclick="location.href='<c:url value='/minwon/indivreg/indivreg.do'/>'" class="newbtn bg1">목록</button>
</section>
</div>
</section>
<div class="contants_body" >
<form id="registerForm" name="registerForm" enctype="multipart/form-data">
<div class="box_column">
<div class="">
<div class="forms_table_non">
<table>
<tr>
<th class="th"><span class="required">*</span>접수일자</th>
<td colspan="3">
<input type="text" id="soJsdate" name="soJsdate" class="input calender datepicker" value="${param.soJsdate}" />
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span>목록번호</th>
<td colspan="3">
<input type="text" id="soBbsNo" name="soBbsNo" class="input" validation-check="required" />
</td>
</tr>
</table>
</div>
</div>
</div>
</form>
</div>
</div>
<!-- /Main body -->
<%--<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>--%>
<script>
const fnBiz = {
search: (formData) => {
$.ajax({
url: '/minwon/indivreg/indivreginsert.ajax',
type: 'POST',
contentType: 'application/json; charset=UTF-8',
data: JSON.stringify(formData),
success: function(res) {
alert('등록이 완료되었습니다.');
window.close();
if (opener &&opener.NoticeList && opener.NoticeList.grid) {
opener.NoticeList.grid.instance.readData(1);
} else if (opener) {
opener.location.reload();
}
},
error: function (xhr, status, error) {
console.log('등록 실패 응답', xhr.responseText);
alert('등록 실패, 다시 시도해주세요.');
}
})
},
eventListener: () => {
$('#btnSave').on('click', function() {
// 1) 현재 일시 생성 (YYYYMMDDHHmmss)
var now = new Date();
var yyyy = now.getFullYear();
var MM = ('0' + (now.getMonth() + 1)).slice(-2);
var dd = ('0' + now.getDate()).slice(-2);
var HH = ('0' + now.getHours()).slice(-2);
var mm = ('0' + now.getMinutes()).slice(-2);
var ss = ('0' + now.getSeconds()).slice(-2);
var yyyymmddhhmmss = yyyy + MM + dd + HH + mm + ss;
// 2) 접수일자 yyyy-mm-dd → yyyymmdd 변환
var jsd = $('#soJsdate').val(); // 예: "2025-11-19"
var jsdFormat = jsd ? jsd.split('-').join('') : ""; // "20251119"
// 3) 서버로 보낼 데이터
var formData = {
soSggcode: "41590",
soInGb: "1",
soInDt: yyyymmddhhmmss,
soJsdate: jsdFormat, // ← 여기!
soBbsNo: $('#soBbsNo').val(),
soState: "B",
soUser: 20
};
console.log('보내는 데이터:', formData); // 디버깅용
fnBiz.search(formData);
})
}
}
$(function () {
fnBiz.eventListener();
$('.datepicker').datepicker({
orientation: "top",
autoclose: true,
language: "ko",
format: "yyyy.mm.dd"
});
});
</script>

@ -0,0 +1,308 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- Main body -->
<div class="main_body">
<section id="section8" class="main_bars">
<div class="bgs-main">
<section id="section5">
<div class="sub_title"></div>
</section>
</div>
</section>
<div class="lef">
<ul class="lef">
&nbsp;&nbsp;<button type="button" id="view_btn" class="newbtnss bg1">민원내용 원본</button>
&nbsp;&nbsp;<button type="button" id="preview_btn" class="newbtnss bg1">답변내용 미리보기</button>
</ul>
</div>
<div class="contants_body">
<div class="gs_b_top">
<ul class="lef">
<li class="th">등록구분</li>
<li>
<select id="searchKeyword" name="searchKeyword" class="input">
<option value="">등록구분</option>
<option value="0" <c:if test="${paramVO.searchKeyword eq '0'}">selected</c:if>>변환등록</option>
<option value="1" <c:if test="${paramVO.searchKeyword eq '1'}">selected</c:if>>수기등록</option>
<option value="2" <c:if test="${paramVO.searchKeyword eq '2'}">selected</c:if>>자동등록</option>
<option value="3" <c:if test="${paramVO.searchKeyword eq '3'}">selected</c:if>>재등록</option>
<option value="4" <c:if test="${paramVO.searchKeyword eq '4'}">selected</c:if>>복사등록</option>
<option value="5" <c:if test="${paramVO.searchKeyword eq '5'}">selected</c:if>>관외 이첩자료 등록</option>
<option value="6" <c:if test="${paramVO.searchKeyword eq '6'}">selected</c:if>>스마트폰단속</option>
</select>
</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>
</div>
</div>
<div id="popupDiv" style="display:none;">
<ul style="background-color:rgb(173,216,115); border-style:solid; border-width:1px; width:100%; height:60px">
<table style="width:100%; height:60px;">
<tr>
<td style="width:80%; height:100%; text-align:center; font-weight: bold; font-size:20px">민원내용 보기</td>
<td style="width:20%; text-align:center;">
<button type="button" id="view_close_btn" class="newbtnss bg1">닫기</button>
</td>
</tr>
</table>
</ul>
<ul style="background-color:rgb(226,230,233); border-style:solid; border-width:1px; width:100%; height:60px;">
<table style="width:100%; height:100%;">
<tr style="width:100%; height:50%;">
<td style="width: 50px;">&nbsp;</td>
<td style="width: 60px; font-size:12px; text-align:right;">목록번호&nbsp;&nbsp;</td>
<td style="width:140px;">
<input type="text" name="m_BbsNo" id="m_BbsNo" style="width:140px; height:20px; font-size:13px; border-style:none;" readonly>
</td>
<td style="width: 60px; font-size:12px; text-align:right;">신청자&nbsp;&nbsp;</td>
<td style="width:140px;">
<input type="text" name="m_Sgnm" id="m_Sgnm" style="width:140px; height:20px; font-size:13px; border-style:none;" readonly>
</td>
<td style="width: 60px; font-size:12px; text-align:right;">전화번호&nbsp;&nbsp;</td>
<td style="width:140px;">
<input type="text" name="m_Tel" id="m_Tel" style="width:140px; height:20px; font-size:13px; border-style:none;" readonly>
</td>
<td style="width: 50px;">&nbsp;</td>
</tr>
<tr style="height:50%;">
<td>&nbsp;</td>
<td style="font-size:12px; text-align:right;">접수일자&nbsp;&nbsp;</td>
<td>
<input type="text" name="m_Jsdate" id="m_Jsdate" style="width:140px; height:20px; font-size:13px; border-style:none;" readonly>
</td>
<td style="font-size:12px; text-align:right;">처리기한&nbsp;&nbsp;</td>
<td>
<input type="text" name="m_LimitDt" id="m_LimitDt" style="width:140px; height:20px; font-size:13px; border-style:none;" readonly>
</td>
<td style="font-size:12px; text-align:right;">접수번호&nbsp;&nbsp;</td>
<td>
<input type="text" name="m_Jsno" id="m_Jsno" style="width:140px; height:20px; font-size:13px; border-style:none;" readonly>
</td>
<td>&nbsp;</td>
</tr>
</table>
</ul>
<ul style="border-style:solid; border-width:1px; width:100%; height:400px;" >
<textarea id="minwon_view" name="minwon_view" style="font-size:12px; width:100%; height:100%; border-style:none;" readonly></textarea>
</ul>
</div>
<!-- /Main body -->
<script type="text/javascript">
let GRID = null;
let TOTAL_INFO = null;
let SEARCH_COND = {};
let perPage = parseInt($('#perPageSelect').val() || 10, 10);
let selectRow_mmCode = null;
let selectRow_BbsNo = null;
let selectRow_Sgnm = null;
let selectRow_Tel = null;
let selectRow_Jsdate = null;
let selectRow_LimitDt = null;
let selectRow_Jsno = null;
let selectRow_mmText = null;
let selectRow_asText = null;
// 검색정보 셋팅
let setSearchCond = function() {
let searchKeyword = $.trim(nvl($("#searchKeyword").val(), ""));
SEARCH_COND.searchKeyword = searchKeyword;
};
const fnBiz = {
init: () => {
initGrid();
},
eventListener: () => {
// 검색 버튼 클릭 이벤트
$('#search_btn').on('click', function() {
// 페이지를 1로 리셋
$("#page").val(1);
// 그리드 데이터 리로드
TuiGrid.instance.readData(1);
});
// 검색어 입력 필드에서 엔터키 이벤트 처리
$('#searchKeyword').on('keypress', function(e) {
if (e.which === 13) { // 엔터키 코드는 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);
});
}
}
/** tui-grid Set */
const initGrid = () => {
const gridColumns = [
{header: '등록구분', name: 'mmDlgb', sortable: true, width: 50,},
{header: '번호', name: 'asBbsNo', sortable: true, width: 50,},
{header: '신고자', name: 'mmSgnm', sortable: true, width: 80,},
{header: '전화번호', name: 'asTel', width: 100,},
{header: '접수일자', name: 'mmDate', sortable: true, width: 70,},
{header: '처리기한', name: 'asLimitDt', sortable: true, width: 70,},
{header: '위반일자', name: 'mmDate', sortable: true, width: 120,},
{header: '접수번호', name: 'asJsno', sortable: true, width: 150,},
{header: '차량번호', name: 'mmCarno', sortable: true, width: 100,},
{header: '미부과사유', name: 'ccCause', width: 150,},
{header: '메인코드', name: 'mmCode', sortable: true, width: 180, align: 'center', hidden: true},
{header: '민원내용', name: 'mmText', sortable: true, width: 1, hidden: true},
{header: '답변내용', name: 'asText', sortable: true, width: 1, hidden: true}
];
const gridDatasource = {
api: {
readData: {
url: '<c:url value="/minwon/wait/minwonwait-myBatis.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: true, //초기화시 조회
serializer: function (params) {
setSearchCond();
SEARCH_COND.perPage = params.perPage;
SEARCH_COND.page = params.page;
return $.param(SEARCH_COND);
}
}
const gridOptions = {
el: 'grid',
rowHeaders: ['checkbox'],
columns: gridColumns,
noData: "조회된 대기자료가 없습니다.",
pageOptions: {
useClient: true, // 클라이언트 페이징 여부(false: 서버 페이징)
perPage: perPage,
},
};
GRID = TuiGrid.of(gridOptions, gridDatasource, (res) => {
GRID.on("dblclick", (e) => {
var popUrl = '/total/info.do';
var popTitle = "TotaInfo";
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);
const state = { cursor, mmCodes, savedAt: Date.now() };
localStorage.setItem('TOTAL_INFO_STATE', JSON.stringify(state));
// 2) 팝업이 없거나 닫혀 있으면 새로 열기
if (!TOTAL_INFO || TOTAL_INFO.closed) {
TOTAL_INFO = window.open(popUrl, popTitle, popOption);
} else {
// 이미 떠 있으면 새로 안 만들고, 그 창에 포커스만 줌
TOTAL_INFO.focus();
TOTAL_INFO.TOTAL_INFO_POPUP_API.search();
}
});
GRID.on("click", (e) => {
selectRow_mmCode = e.instance.getValue(e.rowKey, 'mmCode');
selectRow_BbsNo = e.instance.getValue(e.rowKey, 'asBbsNo');
selectRow_Sgnm = e.instance.getValue(e.rowKey, 'mmSgnm');
selectRow_Tel = e.instance.getValue(e.rowKey, 'asTel');
selectRow_Jsdate = e.instance.getValue(e.rowKey, 'mmDate');
selectRow_LimitDt = e.instance.getValue(e.rowKey, 'asLimitDt');
selectRow_Jsno = e.instance.getValue(e.rowKey, 'asJsno');
selectRow_mmText = e.instance.getValue(e.rowKey, 'mmText');
selectRow_asText = e.instance.getValue(e.rowKey, 'asText');
});
});
};
// 레디펑션
$(function () {
fnBiz.init();
fnBiz.eventListener();
});
$('#view_btn').on('click', function() {
if (selectRow_mmCode != null && selectRow_mmCode != '') {
document.getElementById('m_BbsNo').value = selectRow_BbsNo;
document.getElementById('m_Sgnm').value = selectRow_Sgnm;
document.getElementById('m_Tel').value = selectRow_Tel;
document.getElementById('m_Jsdate').value = selectRow_Jsdate;
document.getElementById('m_LimitDt').value = selectRow_LimitDt;
document.getElementById('m_Jsno').value = selectRow_Jsno;
document.getElementById('minwon_view').value = selectRow_mmText;
var popupDiv = document.getElementById('popupDiv');
popupDiv.style = 'display:inline-block; position:absolute; top:200px; left:350px; z-index:999999; background-color:rgb(226,230,233); width:900px; height:400px;';
}
});
$('#view_close_btn').on('click', function() {
var popupDiv = document.getElementById('popupDiv');
popupDiv.style = 'display:none;';
});
$('#preview_btn').on('click', function() {
alert('답변내용 미리보기 클릭')
/*
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);
*/
});
</script>

@ -0,0 +1,419 @@
<%--
Created by IntelliJ IDEA.
User: moong
Date: 2025-11-27
Time: 오후 3:21
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>
<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>
<li>
<button type="button" id="btnHwp" 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>
<div class="gs_booking">
<div class="row">
<div class="col-sm-12">
<div class="box_column">
<div class="containers">
<!-- 상단 3개 그리드 -->
<div class="grid-row-top">
<!-- 1. 연도별 경고/과태료 합계 -->
<div class="grid-wrap">
<div class="grid-title">연도별 합계</div>
<div id="gridYear"></div>
</div>
<!-- 2. 연도별 단속수단 -->
<div class="grid-wrap">
<div class="grid-title">연도별 단속수단</div>
<div id="gridDevice"></div>
</div>
<!-- 3. 위반유형별 경고/과태료 -->
<div class="grid-wrap">
<div class="grid-title">위반유형별</div>
<div id="gridType"></div>
</div>
</div>
<!-- 하단 1개 그리드 -->
<div class="grid-row-bottom">
<div class="grid-wrap">
<div class="grid-title">상세 통계</div>
<div id="gridDetail"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
/* 전체 컨테이너 */
.gs_booking {
width: 100%;
}
/* 상단 3개 그리드 영역 */
.grid-row-top {
display: flex;
gap: 10px;
width: 100%;
height: 260px; /* 반드시 px 지정 */
margin-bottom: 10px;
}
/* 상단 개별 박스 */
.grid-row-top .grid-wrap {
flex: 1;
border: 1px solid #c0c0c0;
background: #fff;
display: flex;
flex-direction: column;
}
/* 하단 1개 그리드 영역 */
.grid-row-bottom {
width: 100%;
height: 260px;
margin-top: 10px;
}
.grid-row-bottom .grid-wrap {
height: 100%;
border: 1px solid #c0c0c0;
background: #fff;
display: flex;
flex-direction: column;
}
/* 그리드 타이틀 */
.grid-title {
flex: 0 0 30px;
line-height: 30px;
font-size: 12px;
font-weight: bold;
padding-left: 8px;
background: #f5f5f5;
border-bottom: 1px solid #ddd;
}
#gridYear,
#gridDevice,
#gridType,
#gridDetail {
flex: 1;
min-height: 0;
}
/* 버튼 우측 정렬 */
.btn-area-right {
margin-top: 10px;
text-align: right;
}
</style>
<script type="text/javascript">
let INIT_POPUP = null;
let SEARCH_COND = {};
let GRID_YEAR = null;
let GRID_DEVICE = null;
let GRID_TYPE = null;
let GRID_DETAIL = 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: () => {
// 검색 버튼
$('#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 = () => {
// 1. 연도별 합계
GRID_YEAR = new tui.Grid({
el: document.getElementById('gridYear'),
bodyHeight: '200',
rowHeaders: [],
scrollX: false,
scrollY: true,
columns: [
{ header: '구분', name: 'gbn', width: 80, align: 'center' },
{ header: '경고', name: 'warnCnt', width: 80, align: 'right' },
{ header: '과태료', name: 'fineCnt', width: 80, align: 'right' },
{ header: '전체', name: 'totalCnt', width: 80, align: 'right' }
],
data: []
});
// 2. 연도별 단속수단
GRID_DEVICE = new tui.Grid({
el: document.getElementById('gridDevice'),
bodyHeight: '200',
rowHeaders: [],
scrollX: false,
scrollY: true,
columns: [
{ header: '구분', name: 'gbn', width: 80, align: 'center' },
{ header: '자동단속기', name: 'autoCnt', width: 80, align: 'right' },
{ header: '안전신문고', name: 'safeCnt', width: 80, align: 'right' },
{ header: '합계', name: 'totalCnt', width: 80, align: 'right' }
],
data: []
});
// 3. 위반유형별
GRID_TYPE = new tui.Grid({
el: document.getElementById('gridType'),
bodyHeight: '200',
rowHeaders: [],
scrollX: false,
scrollY: true,
columns: [
{ header: '구분', name: 'gbn', width: 120, align: 'left' },
{ header: '경고', name: 'warnCnt', width: 80, align: 'right' },
{ header: '과태료', name: 'fineCnt', width: 80, align: 'right' },
{ header: '합계', name: 'totalCnt', width: 80, align: 'right' }
],
data: []
});
// 4. 상세 통계 (하단)
GRID_DETAIL = new tui.Grid({
el: document.getElementById('gridDetail'),
bodyHeight: '220',
rowHeaders: [],
scrollX: true,
scrollY: true,
columns: [
{ header: '구분', name: 'gbn', width: 80, align: 'center' },
{ header: '계도-일반', name: 'cdGen', width: 90, align: 'right' },
{ header: '계도-등기', name: 'cd5', width: 90, align: 'right' },
{ header: '사전-일반', name: 'sjGen', width: 90, align: 'right' },
{ header: '사전-등기', name: 'sj5', width: 90, align: 'right' },
{ header: '부과-일반', name: 'bgGen', width: 90, align: 'right' },
{ header: '부과-등기', name: 'bg5', width: 90, align: 'right' },
{ header: '독촉-일반', name: 'dcGen', width: 90, align: 'right' },
{ header: '독촉-등기', name: 'dc5', width: 90, align: 'right' },
{ header: '합계', name: 'totalCnt', width: 90, align: 'right' }
],
data: []
});
const gridDatasource = {
api: {
readData: {
url: '<c:url value="/search/caution/caution-select.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: true,
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);
};
const loadWarningStats = () => {
setSearchCond();
$.ajax({
url: '<c:url value="/caution/statistics.ajax"/>',
type: 'POST',
data: SEARCH_COND,
success: function (res) {
const yearList = res.yearList || [];
const deviceList = res.deviceList || [];
const typeList = res.typeList || [];
const detailList = res.detailList || [];
GRID_YEAR.resetData(yearList);
GRID_DEVICE.resetData(deviceList);
GRID_TYPE.resetData(typeList);
GRID_DETAIL.resetData(detailList);
},
error: function () {
alert('경고 통계 조회 중 오류가 발생했습니다.');
}
});
};
// 레디펑션
$(function () {
fnBiz.init();
fnBiz.eventListener();
});
</script>

@ -0,0 +1,493 @@
<%--
Created by IntelliJ IDEA.
User: moong
Date: 2025-11-25
Time: 오후 5:13
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 lef-row1">
<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 class="th">위반시간</li>
<li>
<input type="text" id="searchTime1" name="searchTime1" class="input" maxlength="4" placeholder="0000" />
<input type="text" id="searchTime2" name="searchTime2" class="input" maxlength="4" placeholder="2359" />
</li>
<li class="th">위반내용</li>
<li>
<select id="searchCondition" name="searchCondition" class="input">
<option value="">전체</option>
<option value="code1" <c:if test="${paramVO.searchCondition eq 'code1'}">selected</c:if>>주차위반</option>
<option value="code2" <c:if test="${paramVO.searchCondition eq 'code2'}">selected</c:if>>주차방해</option>
<option value="code3" <c:if test="${paramVO.searchCondition eq 'code3'}">selected</c:if>>시설훼손</option>
<option value="code4" <c:if test="${paramVO.searchCondition eq 'code4'}">selected</c:if>>완속충전위반</option>
<option value="code5" <c:if test="${paramVO.searchCondition eq 'code5'}">selected</c:if>>급속충전위반</option>
<option value="code6" <c:if test="${paramVO.searchCondition eq 'code6'}">selected</c:if>>전용주차구역</option>
</select>
</li>
<li class="th">처리상태</li>
<li>
<select id="searchCondition1" name="searchCondition1" class="input">
<option value="">전체</option>
<option value="00" <c:if test="${paramVO.searchCondition1 eq 'code1'}">selected</c:if>>보류자료</option>
<option value="01" <c:if test="${paramVO.searchCondition1 eq 'code2'}">selected</c:if>>초기상태</option>
<option value="11" <c:if test="${paramVO.searchCondition1 eq 'code3'}">selected</c:if>>임차인조회대상</option>
<option value="21" <c:if test="${paramVO.searchCondition1 eq 'code4'}">selected</c:if>>차적조회완료</option>
<option value="31" <c:if test="${paramVO.searchCondition1 eq 'code5'}">selected</c:if>>의견진술중</option>
<option value="42" <c:if test="${paramVO.searchCondition1 eq 'code6'}">selected</c:if>>사전통보중</option>
<option value="51" <c:if test="${paramVO.searchCondition1 eq 'code7'}">selected</c:if>>사전통보완료</option>
<option value="52" <c:if test="${paramVO.searchCondition1 eq 'code8'}">selected</c:if>>독촉</option>
<option value="53" <c:if test="${paramVO.searchCondition1 eq 'code9'}">selected</c:if>>압류예고</option>
<option value="54" <c:if test="${paramVO.searchCondition1 eq 'code10'}">selected</c:if>>압류대상</option>
<option value="55" <c:if test="${paramVO.searchCondition1 eq 'code11'}">selected</c:if>>압류</option>
<option value="code12" <c:if test="${paramVO.searchCondition1 eq 'code12'}">selected</c:if>>의견진술 미수용</option>
<option value="code13" <c:if test="${paramVO.searchCondition1 eq 'code13'}">selected</c:if>>의견진술 자진취하</option>
<option value="71" <c:if test="${paramVO.searchCondition1 eq 'code14'}">selected</c:if>>사전통보수납</option>
<option value="72" <c:if test="${paramVO.searchCondition1 eq 'code15'}">selected</c:if>>부과수납</option>
<option value="73" <c:if test="${paramVO.searchCondition1 eq 'code16'}">selected</c:if>>독촉수납</option>
<option value="74" <c:if test="${paramVO.searchCondition1 eq 'code17'}">selected</c:if>>압류예정수납</option>
<option value="75" <c:if test="${paramVO.searchCondition1 eq 'code18'}">selected</c:if>>압류수납</option>
<option value="76" <c:if test="${paramVO.searchCondition1 eq 'code19'}">selected</c:if>>시효결손</option>
<option value="80" <c:if test="${paramVO.searchCondition1 eq 'code20'}">selected</c:if>>부과취소</option>
<option value="81" <c:if test="${paramVO.searchCondition1 eq 'code21'}">selected</c:if>>미부과처리</option>
<option value="82" <c:if test="${paramVO.searchCondition1 eq 'code22'}">selected</c:if>>의견진술수용</option>
</select>
</li>
<li class="th">등록구분</li>
<li>
<select id="searchCondition2" name="searchCondition2" class="input">
<option value="">전체</option>
<option value="code1" <c:if test="${paramVO.searchCondition2 eq 'code1'}">selected</c:if>>변환등록</option>
<option value="code2" <c:if test="${paramVO.searchCondition2 eq 'code2'}">selected</c:if>>수기등록</option>
<option value="code3" <c:if test="${paramVO.searchCondition2 eq 'code3'}">selected</c:if>>자동등록</option>
<option value="code4" <c:if test="${paramVO.searchCondition2 eq 'code4'}">selected</c:if>>재등록</option>
<option value="code5" <c:if test="${paramVO.searchCondition2 eq 'code5'}">selected</c:if>>복사등록</option>
</select>
</li>
<li class="th">자료출처</li>
<li>
<select id="searchCondition3" name="searchCondition3" class="input">
<option value="">전체</option>
<option value="code1" <c:if test="${paramVO.searchCondition3 eq 'code1'}">selected</c:if>>생활불편</option>
<option value="code2" <c:if test="${paramVO.searchCondition3 eq 'code2'}">selected</c:if>>구청단속</option>
<option value="code3" <c:if test="${paramVO.searchCondition3 eq 'code3'}">selected</c:if>>시청단속</option>
<option value="code4" <c:if test="${paramVO.searchCondition3 eq 'code4'}">selected</c:if>>기타</option>
</select>
</li>
<li class="th">법정동</li>
<li>
<select id="searchCondition4" name="searchCondition4" class="input">
<option value="">전체</option>
<option value="code1" <c:if test="${paramVO.searchCondition4 eq 'code1'}">selected</c:if>>생활불편</option>
<option value="code2" <c:if test="${paramVO.searchCondition4 eq 'code2'}">selected</c:if>>구청단속</option>
<option value="code3" <c:if test="${paramVO.searchCondition4 eq 'code3'}">selected</c:if>>시청단속</option>
<option value="code4" <c:if test="${paramVO.searchCondition4 eq 'code4'}">selected</c:if>>기타</option>
</select>
</li>
</ul>
<ul class="lef lef-row2">
<li class="cond">
<span class="th">차량번호</span>
<input type="text" id="searchCarno" name="searchCarno" class="input" />
</li>
<li class="cond">
<span class="th">소유자성명</span>
<input type="text" id="searchName" name="searchName" class="input" />
</li>
<li class="cond">
<span class="th">주민번호</span>
<input type="text" id="searchJno" name="searchJno" class="input" />
</li>
<li class="cond">
<span class="th">신고자</span>
<input type="text" id="searchUser" name="searchUser" class="input" />
</li>
<li class="cond">
<span class="th">신고자 전화번호</span>
<input type="text" id="searchTel" name="searchTel" class="input" />
</li>
<li class="cond">
<span class="th">목록번호</span>
<input type="text" id="searchBbsno" name="searchBbsno" class="input" />
</li>
<li class="cond">
<span class="th">위반장소</span>
<input type="text" id="searchPos" name="searchPos" class="input" />
</li>
<li class="cond">
<span class="th">상세주소</span>
<input type="text" id="searchAddr" name="searchAddr" class="input" />
</li>
<li class="cond cond-button">
<span class="th">&nbsp;</span>
<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><span id="totalPages"></span> 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>
<style>
.gs_b_top ul.lef-row1 {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.gs_b_top ul.lef-row2 {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr)); /* 4열 */
column-gap: 16px; /* 좌우 간격 */
row-gap: 6px; /* 위/아래 간격 */
margin-top: 6px;
}
.gs_b_top ul.lef-row2 li.cond {
display: flex;
align-items: center;
}
.gs_b_top ul.lef-row2 li.cond .th {
display: inline-block;
font-weight: 700;
margin-right: 4px;
min-width: 100px;
font-size: 12px;
}
.gs_b_top ul.lef-row2 li.cond .input {
flex: 1;
}
.gs_b_top {
position: relative;
}
#search_btn {
position: absolute;
right: 500px;
top: 65px;
z-index: 10;
height: 34px;
padding: 0 20px;
}
.gs_b_top {
padding-bottom: 6px !important;
margin-bottom: 0 !important;
}
.gs_b_top ul.lef-row2 {
margin-bottom: 0 !important;
padding-bottom: 0 !important;
}
.gs_booking {
margin-top: 30px !important;
padding-top: 0 !important;
}
</style>
</div>
</div>
<script type="text/javascript">
let INIT_POPUP = null;
let SEARCH_COND = {};
let GRID = null;
function isTimeHHmm(value) {
const timeRegex = /^([01][0-9]|2[0-3])[0-5][0-9]$/;
return timeRegex.test(value);
}
// 검색조건 세팅
let setSearchCond = function () {
let searchCondition = $.trim(nvl($("#searchCondition").val(), ""));
let searchKeyword = $.trim(nvl($("#searchKeyword").val(), ""));
let searchStartDt = $.trim(nvl($("#searchStartDt").val(), ""));
let searchEndDt = $.trim(nvl($("#searchEndDt").val(), ""));
let searchCondition1 = $.trim(nvl($("#searchCondition1").val(), ""));
let searchCondition2 = $.trim(nvl($("#searchCondition2").val(), ""));
let searchCondition3 = $.trim(nvl($("#searchCondition3").val(), ""));
let searchCondition4 = $.trim(nvl($("#searchCondition4").val(), ""));
let searchCarno = $.trim(nvl($("#searchCarno").val(), ""));
let searchName = $.trim(nvl($("#searchName").val(), ""));
let searchJno = $.trim(nvl($("#searchJno").val(), ""));
let searchUser = $.trim(nvl($("#searchUser").val(), ""));
let searchTel = $.trim(nvl($("#searchTel").val(), ""));
let searchBbsno = $.trim(nvl($("#searchBbsno").val(), ""));
let searchPos = $.trim(nvl($("#searchPos").val(), ""));
let searchAddr = $.trim(nvl($("#searchAddr").val(), ""));
let searchTime1 = $.trim(nvl($("#searchTime1").val(), ""));
let searchTime2 = $.trim(nvl($("#searchTime2").val(), ""));
SEARCH_COND.searchCondition = searchCondition;
SEARCH_COND.searchKeyword = searchKeyword;
SEARCH_COND.searchStartDt = searchStartDt;
SEARCH_COND.searchEndDt = searchEndDt;
SEARCH_COND.searchCondition1 = searchCondition1;
SEARCH_COND.searchCondition2 = searchCondition2;
SEARCH_COND.searchCondition3 = searchCondition3;
SEARCH_COND.searchCondition4 = searchCondition4;
SEARCH_COND.searchCarno = searchCarno;
SEARCH_COND.searchName = searchName;
SEARCH_COND.searchJno = searchJno;
SEARCH_COND.searchUser = searchUser;
SEARCH_COND.searchTel = searchTel;
SEARCH_COND.searchBbsno = searchBbsno;
SEARCH_COND.searchPos = searchPos;
SEARCH_COND.searchAddr = searchAddr;
SEARCH_COND.searchTime1 = searchTime1;
SEARCH_COND.searchTime2 = searchTime2;
};
const fnBiz = {
init: () => {
initGrid();
},
eventListener: () => {
// 검색 버튼
$('#search_btn').on('click', function () {
let startDate = $("#searchStartDt").val();
let endDate = $("#searchEndDt").val();
let startTime = $("#searchTime1").val();
let endTime = $("#searchTime2").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;
}
}
if ((startTime && !endTime) || (!startTime && endTime)) {
alert("위반시간 검색 시 시작시간과 종료시간을 모두 입력해주세요.");
return;
}
if (startTime && endTime) {
if (!isTimeHHmm(startTime) || !isTimeHHmm(endTime)) {
alert("시간은 0000 ~ 2359 형식으로 입력해주세요. (예: 0930)");
return;
}
if (parseInt(startTime) > parseInt(endTime)) {
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: 'asUser', width: 150, align: 'center' },
{ header: '접수번호', name: 'asJsno', width: 150, align: 'center' },
{ header: '접수일자', name: 'asJsdate', width: 150, align: 'center' },
{ header: '목록번호', name: 'asBbsNo', 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: '제외사유', name: 'ccCause', width: 150, align: 'center' },
{ header: '제외일자', name: 'ccDate', width: 150, align: 'center' },
{ header: '제외기타사항', name: 'ccEtc', 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/filtersearch/filtersearch-select.ajax"/>',
method: 'POST',
contentType: 'application/x-www-form-urlencoded',
processData: true
}
},
initialRequest: true,
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>

@ -23,7 +23,7 @@
<li class="th">검색구분</li>
<li>
<select id="searchCondition" name="searchCondition" class="input">
<option value="">검색구분</option>
<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>
@ -93,19 +93,6 @@
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();
@ -190,7 +177,7 @@
processData: true
}
},
initialRequest: false, // 직접 readData(1) 호출할 거라 false
initialRequest: true,
serializer: function (params) {
setSearchCond();
SEARCH_COND.perPage = params.perPage;

@ -9638,7 +9638,7 @@ a.text-dark:hover, a.text-dark:focus {
.table, .markdown-result table {
border-collapse: collapse !important;
}
.table td,
.markdown-result table td, .table th, .markdown-result table th {
background-color: #fff !important;

@ -411,12 +411,12 @@ ol {
padding: 5px;
}
.box_title>li.rig .input {
width: 120px;
width: 120px;
height: 25px;
padding: 2px 5px;
}
.box_title>li.rig .input.calender {
width: 120px;
width: 120px;
height: 25px;
background-size: auto 15px;
}
@ -1744,7 +1744,7 @@ label {
}
.gs_flow:nth-child(1):after {
content: "3F";
content: "3F";
}
.gs_flow:nth-child(2):after {
@ -3416,7 +3416,7 @@ label {
overflow-y: auto;
overflow-x: hidden;
}
.scroll_toptable table {
.scroll_toptable table {
table-layout: fixed;
}
@ -4408,4 +4408,4 @@ label {
border-radius: 3px;
cursor: pointer;
transition: all 0.2s;
}
}

Loading…
Cancel
Save