단속 > 단속 등록&열람: 위치정보 수정 로직 추가, 팝업 수정 모드 구현, 컬럼 가시성 및 입력 필드 검증 로직 개선, 지적·공시지가 마스크 추가

dev
박성영 4 months ago
parent d8d2a21f6e
commit fc508bd000

@ -61,13 +61,15 @@ public class CrdnPstnInfoController {
/**
*
* : / , (, ) .
* pstnInfoId .
*/
@GetMapping("/popup.do")
@Operation(summary = "위치정보 등록 팝업", description = "위치정보 등록을 위한 팝업 화면을 제공합니다.")
@Operation(summary = "위치정보 등록/수정 팝업", description = "위치정보 등록 또는 수정을 위한 팝업 화면을 제공합니다.")
public ModelAndView popup(
@Parameter(description = "단속 연도") @RequestParam String crdnYr,
@Parameter(description = "단속 번호") @RequestParam String crdnNo,
@Parameter(description = "모드(C/U/V)") @RequestParam(defaultValue = "C") String mode,
@Parameter(description = "위치정보 ID (수정시 필수)") @RequestParam(required = false) String pstnInfoId,
Model model) {
// 법정동 코드 목록
@ -86,10 +88,17 @@ public class CrdnPstnInfoController {
.build();
model.addAttribute("ldcgCdList", commonCodeService.selectCodeDetailList(ldcgSearch));
// 중요로직: 수정 모드인 경우 기존 데이터 조회하여 전달
CrdnPstnInfoVO data = null;
if ("U".equals(mode) && pstnInfoId != null) {
data = service.selectPstnInfoByPk(pstnInfoId);
}
ModelAndView mav = new ModelAndView("crdn/crndRegistAndView/crdnPstnInfo/popup" + TilesConstants.POPUP);
mav.addObject("crdnYr", crdnYr);
mav.addObject("crdnNo", crdnNo);
mav.addObject("mode", mode);
mav.addObject("data", data);
return mav;
}
@ -114,4 +123,24 @@ public class CrdnPstnInfoController {
}
return ApiResponseUtil.error(MessageConstants.Common.SAVE_ERROR);
}
/**
* (AJAX)
* : ID . SQL NOW() .
*/
@Operation(summary = "위치정보 수정", description = "단속 자료의 위치정보를 수정합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "수정 성공"),
@ApiResponse(responseCode = "400", description = "수정 실패")
})
@PostMapping("/update.ajax")
public ResponseEntity<?> updateAjax(@ModelAttribute CrdnPstnInfoVO vo) {
vo.setMdfr(SessionUtil.getUserId());
int result = service.updatePstnInfo(vo);
if (result > 0) {
return ApiResponseUtil.success(MessageConstants.Common.SAVE_SUCCESS);
}
return ApiResponseUtil.error(MessageConstants.Common.SAVE_ERROR);
}
}

@ -20,4 +20,10 @@ public interface CrdnPstnInfoMapper {
/** 등록 */
int insertPstnInfo(CrdnPstnInfoVO vo);
/** 상세 조회 */
CrdnPstnInfoVO selectPstnInfoByPk(String pstnInfoId);
/** 수정 */
int updatePstnInfo(CrdnPstnInfoVO vo);
}

@ -11,4 +11,10 @@ public interface CrdnPstnInfoService {
List<CrdnPstnInfoVO> selectPstnInfoList(CrdnPstnInfoVO vo);
int selectPstnInfoListTotalCount(CrdnPstnInfoVO vo);
int insertPstnInfo(CrdnPstnInfoVO vo);
// 중요로직: 상세 조회 - 그리드 더블클릭 시 사용
CrdnPstnInfoVO selectPstnInfoByPk(String pstnInfoId);
// 중요로직: 수정 - 팝업에서 수정 저장 시 사용
int updatePstnInfo(CrdnPstnInfoVO vo);
}

@ -1,5 +1,6 @@
package go.kr.project.crdn.crndRegistAndView.crdnPstnInfo.service.impl;
import egovframework.exception.MessageException;
import go.kr.project.crdn.crndRegistAndView.crdnPstnInfo.mapper.CrdnPstnInfoMapper;
import go.kr.project.crdn.crndRegistAndView.crdnPstnInfo.model.CrdnPstnInfoVO;
import go.kr.project.crdn.crndRegistAndView.crdnPstnInfo.service.CrdnPstnInfoService;
@ -33,6 +34,25 @@ public class CrdnPstnInfoServiceImpl extends EgovAbstractServiceImpl implements
@Override
public int insertPstnInfo(CrdnPstnInfoVO vo) {
CrdnPstnInfoVO existingRecord = mapper.selectPstnInfoList(CrdnPstnInfoVO.builder()
.crdnYr(vo.getCrdnYr())
.crdnNo(vo.getCrdnNo())
.build()).stream().findFirst().orElse(null);
if (existingRecord != null) {
throw new MessageException("이미 등록된 위치정보가 있습니다.");
}
return mapper.insertPstnInfo(vo);
}
@Override
public CrdnPstnInfoVO selectPstnInfoByPk(String pstnInfoId) {
return mapper.selectPstnInfoByPk(pstnInfoId);
}
@Override
public int updatePstnInfo(CrdnPstnInfoVO vo) {
return mapper.updatePstnInfo(vo);
}
}

@ -103,6 +103,8 @@
RMRK,
REG_DT,
RGTR,
MDFCN_DT,
MDFR,
DEL_YN
) VALUES (
LPAD(NEXTVAL(seq_pstn_info_id), 10, '0'),
@ -131,8 +133,87 @@
#{rmrk},
NOW(),
#{rgtr},
NOW(),
#{rgtr},
'N'
)
</insert>
<!-- 위치정보 상세 조회 -->
<select id="selectPstnInfoByPk" parameterType="String" resultType="CrdnPstnInfoVO">
/* PstnInfoMapper.selectPstnInfoByPk : 위치정보 상세 조회 */
SELECT
p.PSTN_INFO_ID,
p.SGG_CD,
sgg.CD_NM AS SGG_CD_NM,
p.CRDN_YR,
p.CRDN_NO,
p.STDG_EMD_CD,
emd.CD_NM AS STDG_EMD_CD_NM,
p.LDCG_CD,
ld.CD_NM AS LDCG_CD_NM,
p.PTOUT,
p.OALP,
p.LOTNO_WHOL_ADDR,
p.ROAD_NM_WHOL_ADDR,
p.ZIP,
p.LOTNO_ADDR,
p.ROAD_NM_ADDR,
p.DTL_ADDR,
p.REF_ADDR,
p.PBADMS_ZONE_CD,
p.ROAD_NM_CD,
p.LOTNO_MNO,
p.LOTNO_SNO,
p.BLDG_MNO,
p.BLDG_SNO,
p.UDGD_YN_CD,
p.MTN_YN_CD,
p.RMRK,
p.REG_DT,
p.RGTR,
p.MDFCN_DT,
p.MDFR,
p.DEL_YN,
p.DEL_DT,
p.DLTR
FROM tb_pstn_info p
LEFT JOIN tb_cd_detail sgg ON sgg.CD_GROUP_ID = 'ORG_CD' AND sgg.CD_ID = p.SGG_CD AND sgg.USE_YN = 'Y'
LEFT JOIN tb_cd_detail emd ON emd.CD_GROUP_ID = 'STDG_EMD_CD' AND emd.CD_ID = p.STDG_EMD_CD AND emd.USE_YN = 'Y'
LEFT JOIN tb_cd_detail ld ON ld.CD_GROUP_ID = 'LDCG_CD' AND ld.CD_ID = p.LDCG_CD AND ld.USE_YN = 'Y'
WHERE p.PSTN_INFO_ID = #{pstnInfoId}
AND p.DEL_YN = 'N'
</select>
<!-- 위치정보 수정 -->
<update id="updatePstnInfo" parameterType="CrdnPstnInfoVO">
/* PstnInfoMapper.updatePstnInfo : 위치정보 수정 */
UPDATE tb_pstn_info
SET
STDG_EMD_CD = #{stdgEmdCd},
LDCG_CD = #{ldcgCd},
PTOUT = #{ptout},
OALP = #{oalp},
LOTNO_WHOL_ADDR = #{lotnoWholAddr},
ROAD_NM_WHOL_ADDR = #{roadNmWholAddr},
ZIP = #{zip},
LOTNO_ADDR = #{lotnoAddr},
ROAD_NM_ADDR = #{roadNmAddr},
DTL_ADDR = #{dtlAddr},
REF_ADDR = #{refAddr},
PBADMS_ZONE_CD = #{pbadmsZoneCd},
ROAD_NM_CD = #{roadNmCd},
LOTNO_MNO = #{lotnoMno},
LOTNO_SNO = #{lotnoSno},
BLDG_MNO = #{bldgMno},
BLDG_SNO = #{bldgSno},
UDGD_YN_CD = #{udgdYnCd},
MTN_YN_CD = #{mtnYnCd},
RMRK = #{rmrk},
MDFCN_DT = NOW(),
MDFR = #{mdfr}
WHERE PSTN_INFO_ID = #{pstnInfoId}
AND DEL_YN = 'N'
</update>
</mapper>

@ -52,37 +52,37 @@
*/
getGridColumns: function() {
return [
{ header: '위치정보ID', name: 'pstnInfoId', align: 'center', width: 110 },
{ header: '단속년도', name: 'crdnYr', align: 'center', width: 80 },
{ header: '단속번호', name: 'crdnNo', align: 'center', width: 90 },
{ header: '시군구', name: 'sggCdNm', align: 'center', width: 100 },
{ header: '위치정보ID', name: 'pstnInfoId', align: 'center', width: 110, hidden: true },
{ header: '단속년도', name: 'crdnYr', align: 'center', width: 80, hidden: true },
{ header: '단속번호', name: 'crdnNo', align: 'center', width: 90, hidden: true },
{ header: '시군구', name: 'sggCdNm', align: 'center', width: 100, hidden: true },
{ header: '법정동', name: 'stdgEmdCdNm', align: 'center', width: 100 },
{ header: '지목', name: 'ldcgCdNm', align: 'center', width: 90 },
{ header: '지번 전체주소', name: 'lotnoWholAddr', align: 'left', width: 200 },
{ header: '도로명 전체주소', name: 'roadNmWholAddr', align: 'left', width: 220 },
{ header: '우편번호', name: 'zip', align: 'center', width: 90 },
{ header: '지번 주소', name: 'lotnoAddr', align: 'left', width: 180 },
{ header: '도로명 주소', name: 'roadNmAddr', align: 'left', width: 200 },
{ header: '상세주소', name: 'dtlAddr', align: 'left', width: 180 },
{ header: '참고주소', name: 'refAddr', align: 'left', width: 180 },
{ header: '행정구역코드', name: 'pbadmsZoneCd', align: 'center', width: 130 },
{ header: '도로명 코드', name: 'roadNmCd', align: 'center', width: 120 },
{ header: '지번 본번', name: 'lotnoMno', align: 'right', width: 90 },
{ header: '지번 부번', name: 'lotnoSno', align: 'right', width: 90 },
{ header: '건물 본번', name: 'bldgMno', align: 'right', width: 90 },
{ header: '건물 부번', name: 'bldgSno', align: 'right', width: 90 },
{ header: '지하여부', name: 'udgdYnCd', align: 'center', width: 80 },
{ header: '산여부', name: 'mtnYnCd', align: 'center', width: 80 },
{ header: '지적(PTOUT)', name: 'ptout', align: 'right', width: 120, formatter: function(e){ return e.value != null ? Number(e.value).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 }) : ''; } },
{ header: '공시지가(OALP)', name: 'oalp', align: 'right', width: 130, formatter: function(e){ return e.value != null ? Number(e.value).toLocaleString() : ''; } },
{ header: '지번 전체주소', name: 'lotnoWholAddr', align: 'left', width: 300 },
{ header: '지목', name: 'ldcgCdNm', align: 'center', width: 90 },
{ header: '지적(PTOUT)', name: 'ptout', align: 'right', width: 180, formatter: function(e){ return e.value != null ? Number(e.value).toLocaleString(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 2 }) : ''; } },
{ header: '공시지가(OALP)', name: 'oalp', align: 'right', width: 180, formatter: function(e){ return e.value != null ? Number(e.value).toLocaleString() : ''; } },
{ header: '도로명 전체주소', name: 'roadNmWholAddr', align: 'left', width: 220, hidden: true },
{ header: '지번 주소', name: 'lotnoAddr', align: 'left', width: 180, hidden: true },
{ header: '도로명 주소', name: 'roadNmAddr', align: 'left', width: 200, hidden: true },
{ header: '상세주소', name: 'dtlAddr', align: 'left', width: 180, hidden: true },
{ header: '참고주소', name: 'refAddr', align: 'left', width: 180, hidden: true },
{ header: '행정구역코드', name: 'pbadmsZoneCd', align: 'center', width: 130, hidden: true },
{ header: '도로명 코드', name: 'roadNmCd', align: 'center', width: 120, hidden: true },
{ header: '지번 본번', name: 'lotnoMno', align: 'right', width: 90, hidden: true },
{ header: '지번 부번', name: 'lotnoSno', align: 'right', width: 90, hidden: true },
{ header: '건물 본번', name: 'bldgMno', align: 'right', width: 90, hidden: true },
{ header: '건물 부번', name: 'bldgSno', align: 'right', width: 90, hidden: true },
{ header: '지하여부', name: 'udgdYnCd', align: 'center', width: 80, hidden: true },
{ header: '산여부', name: 'mtnYnCd', align: 'center', width: 80, hidden: true },
{ header: '비고', name: 'rmrk', align: 'left', width: 200 },
{ header: '등록일시', name: 'regDt', align: 'center', width: 150, formatter: function (e) { return e.value ? moment(e.value).format('YYYY-MM-DD HH:mm:ss') : ''; } },
{ header: '등록자', name: 'rgtr', align: 'center', width: 100 },
{ header: '수정일시', name: 'mdfcnDt', align: 'center', width: 150, formatter: function (e) { return e.value ? moment(e.value).format('YYYY-MM-DD HH:mm:ss') : ''; } },
{ header: '등록일시', name: 'regDt', align: 'center', width: 150, hidden: true },
{ header: '등록자', name: 'rgtr', align: 'center', width: 100, hidden: true },
{ header: '수정일시', name: 'mdfcnDt', align: 'center', width: 150 },
{ header: '수정자', name: 'mdfr', align: 'center', width: 100 },
{ header: '삭제여부', name: 'delYn', align: 'center', width: 80 },
{ header: '삭제일시', name: 'delDt', align: 'center', width: 150, formatter: function (e) { return e.value ? moment(e.value).format('YYYY-MM-DD HH:mm:ss') : ''; } },
{ header: '삭제자', name: 'dltr', align: 'center', width: 100 }
{ header: '삭제여부', name: 'delYn', align: 'center', width: 80, hidden: true },
{ header: '삭제일시', name: 'delDt', align: 'center', width: 150, hidden: true },
{ header: '삭제자', name: 'dltr', align: 'center', width: 100, hidden: true }
];
},
@ -136,7 +136,26 @@
// 데이터 로딩 완료 이벤트
this.instance.on('successResponse', function(ev) {
// 중요로직: 그리드 데이터 건수에 따른 "위치정보 추가" 버튼 활성화/비활성화 처리
var responseObj = JSON.parse(ev.xhr.response);
var totalCount = 0;
if( responseObj ){
totalCount = responseObj.data.contents.length;
}
console.log(totalCount);
var $pstnInfoRegistBtn = $('#pstnInfoRegistBtn');
if (totalCount >= 1) {
// 데이터가 1건 이상 있을 경우 버튼 비활성화
$pstnInfoRegistBtn.prop('disabled', true);
$pstnInfoRegistBtn.addClass('disabled');
$pstnInfoRegistBtn.hide();
} else {
// 데이터가 0건일 경우 버튼 활성화
$pstnInfoRegistBtn.prop('disabled', false);
$pstnInfoRegistBtn.removeClass('disabled');
$pstnInfoRegistBtn.show();
}
});
// 행 클릭 이벤트
@ -153,9 +172,34 @@
var rowData = self.instance.getRow(rowKey);
if (rowData) {
console.log('위치 정보 행 더블클릭:', rowData);
// 상세 정보 표시 또는 추가 동작 구현 가능
// 중요로직: 수정 팝업 호출
self.openEditPopup(rowData);
}
});
},
/**
* 수정 팝업 호출
* 중요로직: 그리드 더블클릭 시 선택된 행 데이터를 가지고 수정 팝업을 연다.
*/
openEditPopup: function(rowData) {
if (!rowData || !rowData.pstnInfoId) {
alert('위치정보 ID가 없습니다.');
return;
}
var crdnYr = $('#crdnYr').val();
var crdnNo = $('#crdnNo').val();
var popUrl = '<c:url value="/crdn/crndRegistAndView/crdnPstnInfo/popup.do"/>';
var params = '?mode=U&crdnYr=' + encodeURIComponent(crdnYr) +
'&crdnNo=' + encodeURIComponent(crdnNo) +
'&pstnInfoId=' + encodeURIComponent(rowData.pstnInfoId);
popUrl += params;
var popTitle = "위치정보 수정";
var popOption = "width=1000px, height=700px, resizable=yes, scrollbars=yes, location=no, top=50px, left=100px";
window.open(popUrl, popTitle, popOption);
}
},

@ -7,7 +7,12 @@
<div class="popup_wrap">
<div class="popup_inner">
<div class="popup_tit">
<h2 class="tit">위치정보 등록</h2>
<h2 class="tit" id="popupTitle">
<c:choose>
<c:when test="${mode eq 'U'}">위치정보 수정</c:when>
<c:otherwise>위치정보 등록</c:otherwise>
</c:choose>
</h2>
<a href="#" class="pop-x-btn modalclose" id="btnCloseTop"></a>
</div>
<div class="popup_con">
@ -15,6 +20,7 @@
<!-- 중요로직: 단속연도/번호는 부모창에서 전달받아 그대로 저장에 사용 -->
<form id="pstnInfoForm" name="pstnInfoForm">
<input type="hidden" id="mode" name="mode" value="${mode}" />
<input type="hidden" id="pstnInfoId" name="pstnInfoId" value="${data.pstnInfoId}" />
<input type="hidden" id="crdnYr" name="crdnYr" value="${crdnYr}" />
<input type="hidden" id="crdnNo" name="crdnNo" value="${crdnNo}" />
@ -25,29 +31,13 @@
<col style="width: 18%;" />
<col style="width: 32%;" />
</colgroup>
<tr>
<th class="th">위치정보 ID</th>
<td colspan="3">
<input type="text" id="pstnInfoId" name="pstnInfoId" class="input" style="width: 180px;" readonly />
</td>
</tr>
<tr>
<th class="th">단속년도</th>
<td>
<input type="text" class="input" value="${crdnYr}" readonly style="width: 120px;"/>
</td>
<th class="th">단속번호</th>
<td>
<input type="text" class="input" value="${crdnNo}" readonly style="width: 140px;"/>
</td>
</tr>
<tr>
<th class="th"><span class="required">*</span> 법정동</th>
<td>
<select id="stdgEmdCd" name="stdgEmdCd" class="input" style="width: 180px;" validation-check="required">
<option value="">선택하세요</option>
<c:forEach var="code" items="${stdgEmdCdList}">
<option value="${code.cdId}">${code.cdNm}</option>
<option value="${code.cdId}" <c:if test="${data.stdgEmdCd eq code.cdId}">selected</c:if>>${code.cdNm}</option>
</c:forEach>
</select>
</td>
@ -56,125 +46,120 @@
<select id="ldcgCd" name="ldcgCd" class="input" style="width: 180px;" validation-check="required">
<option value="">선택하세요</option>
<c:forEach var="code" items="${ldcgCdList}">
<option value="${code.cdId}">${code.cdNm}</option>
<option value="${code.cdId}" <c:if test="${data.ldcgCd eq code.cdId}">selected</c:if>>${code.cdNm}</option>
</c:forEach>
</select>
</td>
</tr>
<tr>
<th class="th">우편번호</th>
<th class="th"><span class="required">*</span> 우편번호</th>
<td>
<input type="text" id="zip" name="zip" class="input" maxlength="6" style="width: 120px;" />
<input type="text" id="zip" name="zip" class="input" maxlength="6" style="width: 120px;" validation-check="required" value="${data.zip}" readonly />
<button class="newbtn bg1 userser" type="button" onclick="searchZipCode();">주소 찾기</button>
</td>
</tr>
<tr>
<th class="th">지번 주소</th>
<th class="th"><span class="required">*</span> 지번 주소</th>
<td colspan="3">
<input type="text" id="lotnoAddr" name="lotnoAddr" class="input" style="width: 450px;" maxlength="320" readonly/>
<input type="text" id="lotnoAddr" name="lotnoAddr" class="input" style="width: 450px;" maxlength="320" readonly validation-check="required" value="${data.lotnoAddr}"/>
<input type="text" id="lotnoMno" name="lotnoMno" class="input" style="width: 120px;" maxlength="4" readonly/>
<input type="text" id="lotnoSno" name="lotnoSno" class="input" style="width: 120px;" maxlength="4" readonly/>
</td>
</tr>
<tr>
<th class="th">도로명 주소</th>
<th class="th"><span class="required">*</span> 도로명 주소</th>
<td colspan="3">
<input type="text" id="roadNmAddr" name="roadNmAddr" class="input" style="width: 450px;" maxlength="320" readonly/>
<input type="text" id="bldgMno" name="bldgMno" class="input" style="width: 120px;" maxlength="4" readonly/>
<input type="text" id="bldgSno" name="bldgSno" class="input" style="width: 120px;" maxlength="4" readonly/>
<input type="text" id="roadNmAddr" name="roadNmAddr" class="input" style="width: 450px;" maxlength="320" readonly validation-check="required" value="${data.roadNmAddr}"/>
<input type="text" id="bldgMno" name="bldgMno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.bldgMno}"/>
<input type="text" id="bldgSno" name="bldgSno" class="input" style="width: 120px;" maxlength="4" readonly value="${data.bldgSno}"/>
</td>
</tr>
<tr>
<th class="th">상세주소</th>
<td colspan="3">
<input type="text" id="dtlAddr" name="dtlAddr" class="input" maxlength="320"/>
<input type="text" id="dtlAddr" name="dtlAddr" class="input" maxlength="320" value="${data.dtlAddr}"/>
</td>
</tr>
<tr>
<th class="th">지적(PTOUT)</th>
<th class="th"><span class="required">*</span> 지적(PTOUT)</th>
<td>
<input type="text" id="ptout" name="ptout" class="input" style="width: 180px;" maxlength="22" placeholder="예) 12345.67"/>
<input type="text" id="ptout" name="ptout" class="input ptoutMask" style="width: 180px;" maxlength="25" placeholder="예) 12345.67" validation-check="required number" value="${data.ptout}"/>
</td>
<th class="th">공시지가(OALP)</th>
<th class="th"><span class="required">*</span> 공시지가(OALP)</th>
<td>
<input type="text" id="oalp" name="oalp" class="input" style="width: 180px;" maxlength="13" placeholder="예) 1000000"/>
<input type="text" id="oalp" name="oalp" class="input oalpMask" style="width: 180px;" maxlength="13" placeholder="예) 1000000" validation-check="required integer" value="${data.oalp}"/>
</td>
</tr>
<tr>
<th class="th">비고</th>
<td colspan="3">
<textarea id="rmrk" name="rmrk" class="textarea" rows="3" maxlength="1000"></textarea>
<textarea id="rmrk" name="rmrk" class="textarea" rows="3" maxlength="1000" style="height: 50px;">${data.rmrk}</textarea>
</td>
</tr>
<!-- 아래부터 tb_pstn_info 누락 컬럼 입력 영역 추가 -->
<!-- 시스템 정보 (읽기전용 표시) -->
<tr>
<th class="th">등록 일시</th>
<td></td>
<th class="th">등록자</th>
<td></td>
</tr>
<tr>
<th class="th">수정 일시</th>
<td></td>
<th class="th">수정자</th>
<td></td>
</tr>
<!-- 중요로직: sggCd(시군구 코드는 세션에서 서버가 설정) -->
<tr style="">
<tr style="display: none;">
<th class="th"><span class="required">*</span> 행정구역코드</th>
<td colspan="3">
<input type="text" id="pbadmsZoneCd" name="pbadmsZoneCd" class="input" maxlength="10" style="width: 180px;" placeholder="예) 4128700000"/>
<input type="text" id="pbadmsZoneCd" name="pbadmsZoneCd" class="input" maxlength="10" style="width: 180px;" placeholder="예) 4128700000" readonly value="${data.pbadmsZoneCd}"/>
</td>
</tr>
<tr>
<tr style="display: none;">
<th class="th">지번 전체주소</th>
<td colspan="3">
<input type="text" id="lotnoWholAddr" name="lotnoWholAddr" class="input" maxlength="2000"/>
<input type="text" id="lotnoWholAddr" name="lotnoWholAddr" class="input" maxlength="2000" readonly value="${data.lotnoWholAddr}"/>
</td>
</tr>
<tr>
<tr style="display: none;">
<th class="th">도로명 전체주소</th>
<td colspan="3">
<input type="text" id="roadNmWholAddr" name="roadNmWholAddr" class="input" maxlength="2000"/>
<input type="text" id="roadNmWholAddr" name="roadNmWholAddr" class="input" maxlength="2000" readonly value="${data.roadNmWholAddr}"/>
</td>
</tr>
<tr>
<tr style="display: none;">
<th class="th">참고 주소</th>
<td>
<input type="text" id="refAddr" name="refAddr" class="input" maxlength="320"/>
<input type="text" id="refAddr" name="refAddr" class="input" maxlength="320" readonly value="${data.refAddr}"/>
</td>
<th class="th">도로명 코드</th>
<td>
<input type="text" id="roadNmCd" name="roadNmCd" class="input" style="width: 180px;" maxlength="12"/>
<input type="text" id="roadNmCd" name="roadNmCd" class="input" style="width: 180px;" maxlength="12" readonly value="${data.roadNmCd}"/>
</td>
</tr>
<tr>
<tr style="display: none;">
<th class="th">지하 여부</th>
<td>
<select id="udgdYnCd" name="udgdYnCd" class="input" style="width: 120px;">
<option value="">선택</option>
<option value="Y">Y</option>
<option value="N">N</option>
<option value="Y" <c:if test="${data.udgdYnCd eq 'Y'}">selected</c:if>>Y</option>
<option value="N" <c:if test="${data.udgdYnCd eq 'N'}">selected</c:if>>N</option>
</select>
</td>
<th class="th">산 여부</th>
<td>
<select id="mtnYnCd" name="mtnYnCd" class="input" style="width: 120px;">
<option value="">선택</option>
<option value="Y">Y</option>
<option value="N">N</option>
<option value="Y" <c:if test="${data.mtnYnCd eq 'Y'}">selected</c:if>>Y</option>
<option value="N" <c:if test="${data.mtnYnCd eq 'N'}">selected</c:if>>N</option>
</select>
</td>
</tr>
<!-- 시스템 정보 (읽기전용 표시) -->
<tr>
<th class="th">등록 일시</th>
<td>
</td>
<th class="th">등록자</th>
<td>
</td>
</tr>
<tr>
<th class="th">수정 일시</th>
<td>
</td>
<th class="th">수정자</th>
<td>
</td>
</tr>
</table>
</form>
</div>
@ -192,21 +177,10 @@
(function(window, $) {
'use strict';
// 중요로직: 필수값(법정동, 지목, 행정구역코드) 검증 후 서버에 저장
// 중요로직: xit-validation.js의 formValidation을 사용한 폼 검증 후 서버에 저장
function savePstnInfo() {
if (!$('#stdgEmdCd').val()) {
alert('법정동을 선택하세요.');
$('#stdgEmdCd').focus();
return;
}
if (!$('#ldcgCd').val()) {
alert('지목을 선택하세요.');
$('#ldcgCd').focus();
return;
}
if (!$('#pbadmsZoneCd').val()) {
alert('행정구역코드를 입력하세요.');
$('#pbadmsZoneCd').focus();
// 중요로직: validateFormByAttributes를 사용하여 모든 validation-check 속성 검증
if (!validateFormByAttributes('pstnInfoForm')) {
return;
}
@ -214,14 +188,20 @@
updateWholeAddress();
var formData = $('#pstnInfoForm').serialize();
// 중요로직: 모드에 따라 등록/수정 API 분기 처리
var mode = $('#mode').val();
var apiUrl = (mode === 'U') ?
'<c:url value="/crdn/crndRegistAndView/crdnPstnInfo/update.ajax"/>' :
'<c:url value="/crdn/crndRegistAndView/crdnPstnInfo/insert.ajax"/>';
$.ajax({
url: '<c:url value="/crdn/crndRegistAndView/crdnPstnInfo/insert.ajax"/>',
url: apiUrl,
type: 'POST',
data: formData,
success: function (res) {
if (res && res.success) {
alert('저장되었습니다.');
alert((mode === 'U' ? '수정' : '등록') + '되었습니다.');
try {
if (window.opener && window.opener.CrdnDetailViewPstn && window.opener.CrdnDetailViewPstn.search) {
window.opener.CrdnDetailViewPstn.search(); // 부모창 위치 정보 그리드 새로고침
@ -229,12 +209,8 @@
} catch (e) { console.warn(e); }
window.close();
} else {
alert(res.message || '저장에 실패했습니다.');
alert(res.message || ((mode === 'U' ? '수정' : '등록') + '에 실패했습니다.'));
}
},
error: function(xhr) {
alert('저장 중 오류가 발생했습니다.');
console.error(xhr);
}
});
}
@ -352,8 +328,10 @@
$('#dtlAddr').on('input keyup blur', function() {
updateWholeAddress();
});
});
// 전역 함수로 노출하여 onclick에서 호출 가능하게 처리
window.searchZipCode = searchZipCode;
window.searchZipCodeCallback = searchZipCodeCallback;

@ -36,6 +36,42 @@ $(document).ready(function () {
});
});
// 중요로직: 소수점을 허용하는 숫자 마스크 (지적 등에 사용)
$("body").on("focus", ".decimalMask", function () {
$(this).inputmask("numeric", {
autoGroup: true, // 그룹화 사용 안함
groupSeparator: ",", // 그룹 구분자 없음
digits: 2, // 소수점 2자리까지 허용
allowMinus: false, // 음수 사용 안함
repeat: 15, // 최대 15자리
autoUnmask: true
});
});
// 중요로직: PTOUT 지적 전용 마스크 - decimal(22,2) 스펙에 맞춤
$("body").on("focus", ".ptoutMask", function () {
$(this).inputmask("numeric", {
autoGroup: true, // 그룹화 사용 안함
groupSeparator: ",", // 그룹 구분자 없음
digits: 2, // 소수점 2자리까지 허용
allowMinus: false, // 음수 사용 안함
repeat: 20, // 정수부 최대 20자리
autoUnmask: true
});
});
// 중요로직: OALP 공시지가 전용 마스크 - decimal(13,0) 스펙에 맞춤
$("body").on("focus", ".oalpMask", function () {
$(this).inputmask("numeric", {
autoGroup: true, // 그룹화 사용 안함
groupSeparator: ",", // 그룹 구분자 없음
digits: 0, // 소수점 사용 안함
allowMinus: false, // 음수 사용 안함
repeat: 13, // 정수부 최대 13자리
autoUnmask: true
});
});
});

@ -267,8 +267,9 @@ function validateByAttribute(element) {
newErrorElement.style.color = 'red';
newErrorElement.textContent = errorMessage;
// 요소 바로 뒤에 오류 메시지 요소 추가
element.parentNode.insertBefore(newErrorElement, element.nextSibling);
// 중요로직: 해당 객체의 parent 끝에 에러 메시지 추가
//element.parentNode.insertBefore(newErrorElement, element.nextSibling);
element.parentNode.appendChild(newErrorElement);
}
} else {
element.classList.remove('is-invalid');
@ -300,8 +301,9 @@ function errorElementCreate(element, errorMessage, isValid) {
newErrorElement.style.color = 'red';
newErrorElement.textContent = errorMessage;
// 요소 바로 뒤에 오류 메시지 요소 추가
element.parentNode.insertBefore(newErrorElement, element.nextSibling);
// 중요로직: 해당 객체의 parent 끝에 에러 메시지 추가
//element.parentNode.insertBefore(newErrorElement, element.nextSibling);
element.parentNode.appendChild(newErrorElement);
}
} else {
element.classList.remove('is-invalid-custom');

Loading…
Cancel
Save