thkim 2026-02-06 16:34:28 +09:00
commit 4b5c82d5bd
10 changed files with 546 additions and 5 deletions

View File

@ -0,0 +1,73 @@
package geoinfo.drilling.account;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import geoinfo.drilling.account.service.DrillingAccountService;
@Controller
public class DrillingAccountController {
private static final Logger LOGGER = LoggerFactory.getLogger(DrillingAccountController.class);
@Autowired
DrillingAccountService drillingAccountService;
@RequestMapping(value = "/drilling/mypage.do")
public String drillingAccountMypage(@RequestParam HashMap<String, Object> params, ModelMap model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if(request.getSession().getAttribute("USERNAME") == null){
return "redirect:/index.do";
}
return "/drilling/account/mypage";
}
@RequestMapping(value = "/drilling/account/updateMypage.do", method = RequestMethod.POST)
@ResponseBody
public JSONObject drillingInputAdd(HttpServletRequest request, HttpServletResponse response, @RequestParam HashMap<String,Object> params) throws Exception {
JSONObject jSONOResponse = new JSONObject();
String userId = (String)request.getSession().getAttribute("USERID");
int resultCnt = 0;
if ("".equals(userId)) {
jSONOResponse.put("result", "FAIL");
jSONOResponse.put("message", "아이디 정보가 없습니다. 다시 로그인하시기 바랍니다.");
} else {
params.put("userid", userId);
resultCnt = drillingAccountService.updateDrillingAccountMyPage(request, params);
if(resultCnt < 1) {
jSONOResponse.put("result", "FAIL");
jSONOResponse.put("message", "회원정보 수정처리 중 오류가 발생했습니다. 다시 시도해주시기 바랍니다.");
} else {
jSONOResponse.put("result", "SUCCESS");
jSONOResponse.put("message", "회원정보가 수정되었습니다.");
request.getSession().setAttribute("USERNAME", params.get("userName"));
request.getSession().setAttribute("PHONE", params.get("phone"));
request.getSession().setAttribute("EMAIL", params.get("email"));
}
}
return jSONOResponse;
}
}

View File

@ -0,0 +1,18 @@
package geoinfo.drilling.account.service;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import egovframework.rte.psl.dataaccess.mapper.Mapper;
import egovframework.rte.psl.dataaccess.util.EgovMap;
@Mapper("drillingAccountMapper")
public interface DrillingAccountMapper {
public int updateDrillingAccountMyPage(Map<String, Object> map);
}

View File

@ -0,0 +1,11 @@
package geoinfo.drilling.account.service;
import java.util.HashMap;
import javax.servlet.http.HttpServletRequest;
public interface DrillingAccountService {
int updateDrillingAccountMyPage(HttpServletRequest request, HashMap<String, Object> params) throws Exception;
}

View File

@ -0,0 +1,28 @@
package geoinfo.drilling.account.service.impl;
import java.util.HashMap;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import geoinfo.drilling.account.service.DrillingAccountMapper;
import geoinfo.drilling.account.service.DrillingAccountService;
@Service("drillingAccountService")
public class DrillingAccountServiceImpl implements DrillingAccountService {
@Resource(name="drillingAccountMapper")
private DrillingAccountMapper drillingAccountMapper;
@Override
public int updateDrillingAccountMyPage(HttpServletRequest request, HashMap<String, Object> params) throws Exception {
int resultCnt = 0;
resultCnt = drillingAccountMapper.updateDrillingAccountMyPage(params);
return resultCnt;
}
}

View File

@ -0,0 +1,20 @@
<?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="geoinfo.drilling.account.service.DrillingAccountMapper">
<update id="updateDrillingAccountMyPage">
UPDATE WEB_MEMBER_IN
SET CLS = '2'
<if test='userName != null and userName != ""'>
,USER_NAME = #{userName}
</if>
<if test='phone != null and phone != ""'>
,PHONE = #{phone}
</if>
<if test='email != null and email != ""'>
,EMAIL = #{email}
</if>
WHERE USERID = #{userid}
</update>
</mapper>

View File

@ -0,0 +1,358 @@
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%
if (request.getSession().getAttribute("USERID") == null) {
%>
<script>alert('로그인후 이용하실 수 있습니다.');window.location.href='/index.do';</script>
<%
return;
}
%>
<%
if (request.getSession().getAttribute("CLS") == null || "2".equals(request.getSession().getAttribute("CLS") ) == false ) {
%>
<script>alert('발주 기관 회원만 이용가능합니다.');window.location.href='/index.do';</script>
<%
return;
}
%>
<%@ include file="/include/inc_head_2021_new.jsp" %>
<!-- header start-->
<c:import url="/drilling/common/includeTopMenu.do" charEncoding="UTF-8" />
<!-- header end-->
<style>
@keyframes shake {
0% { transform: translateX(0); }
10% { transform: translateX(-5px); }
20% { transform: translateX(5px); }
30% { transform: translateX(-5px); }
40% { transform: translateX(5px); }
50% { transform: translateX(-5px); }
60% { transform: translateX(5px); }
70% { transform: translateX(-5px); }
80% { transform: translateX(5px); }
90% { transform: translateX(-5px); }
100% { transform: translateX(0); }
}
.shake-animation {
animation: shake 0.6s;
}
/* The snackbar - position it at the bottom and in the middle of the screen */
#snackbar {
visibility: hidden; /* Hidden by default. Visible on click */
min-width: 250px; /* Set a default minimum width */
margin-left: -125px; /* Divide value of min-width by 2 */
background-color: #000000; /* Black background color */
color: #ff0000; /* White text color */
text-align: center; /* Centered text */
border-radius: 2px; /* Rounded borders */
padding: 16px; /* Padding */
position: fixed; /* Sit on top of the screen */
z-index: 1; /* Add a z-index if needed */
left: 50%; /* Center the snackbar */
bottom: 80px; /* 30px from the bottom */
font-weight: 500;
}
/* Show the snackbar when clicking on a button (class added with JavaScript) */
#snackbar.show {
visibility: visible; /* Show the snackbar */
/* Add animation: Take 0.5 seconds to fade in and out the snackbar.
However, delay the fade out process for 2.5 seconds */
-webkit-animation: fadein 0.5s, fadeout 0.5s 2.5s;
animation: fadein 0.5s, fadeout 0.5s 2.5s;
}
/* Animations to fade the snackbar in and out */
@-webkit-keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 80px; opacity: 1;}
}
@keyframes fadein {
from {bottom: 0; opacity: 0;}
to {bottom: 80px; opacity: 1;}
}
@-webkit-keyframes fadeout {
from {bottom: 80px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
@keyframes fadeout {
from {bottom: 80px; opacity: 1;}
to {bottom: 0; opacity: 0;}
}
/* 카드 박스 */
/* .mypage-card { */
/* background: #fff; */
/* border: 1px solid #ddd; */
/* padding: 40px; */
/* box-shadow: 0 2px 6px rgba(0,0,0,0.05); */
/* } */
/* 카드 타이틀 */
.card-title {
font-size: 20px;
font-weight: 600;
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 2px solid #222;
}
/* 테이블 */
.mypage-table {
width: 100%;
border-top: 1px solid #ccc;
}
.mypage-table th {
background: #f5f5f5;
text-align: left;
padding: 15px 20px;
font-weight: 500;
border-bottom: 1px solid #ddd;
}
.mypage-table td {
padding: 15px 20px;
border-bottom: 1px solid #ddd;
}
.mypage-table td span.error {
font-size: 11px;
color:#10398e;
}
/* input */
.mypage-table input {
width: 300px;
height: 36px;
padding: 0 10px;
border: 1px solid #ccc;
margin: 0;
}
</style>
<!-- javascript start-->
<script type="text/javascript">
let validPass = false; // 입력값 전체 유효성 검사 통과
document.addEventListener('DOMContentLoaded', function() {
// 전화번호
const phoneInput = document.getElementById("phone");
//자동 하이픈 처리 (input)
phoneInput.addEventListener("input", function (e) {
let value = e.target.value.replace(/\D/g, ""); // 숫자만 남기기
if (value.length <= 3) {
e.target.value = value;
} else if (value.length <= 7) {
e.target.value = value.slice(0, 3) + "-" + value.slice(3);
} else {
e.target.value = value.slice(0, 3) + "-" + value.slice(3, 7) + "-" + value.slice(7, 11);
}
});
// 이메일
const emailInput = document.getElementById("email");
// 이메일 형식체크
emailInput.addEventListener("blur", function (e) {
const email = emailInput.value;
const emailTd = e.target.closest('td')
// 이메일 정규식
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
// 기존 에러 전부 제거 (중복 방지)
emailTd.querySelectorAll('.error').forEach(el => el.remove());
if (email && !emailRegex.test(email)) { // 형식 오류
validPass = false;
emailTd.insertAdjacentHTML('beforeend','<span class="error">이메일형식이맞지않습니다</span>');
return;
}
});
// 전화번호
const saveButton = document.getElementById("btnSaveMypage");
//자동 하이픈 처리 (input)
saveButton.addEventListener("click", function (e) {
if (!(validForm())) {
return false;
};
const nameEle = document.getElementById("username");
const phoneEle = document.getElementById("phone");
const emailEle = document.getElementById("email");
$.ajax({
type : "POST",
url : "/drilling/account/updateMypage.do",
data : {
userName : username.value,
phone : phone.value,
email : emailEle.value
},
dataType : "json",
success:function(json){
if(json.result == "SUCCESS") {
alert("회원정보가 수정되었습니다. 메인화면으로 이동합니다.");
location.href="/drilling/index.do"
} else {
alert("회원정보 수정처리를 실패했습니다. 다시 시도해주시기 바랍니다.");
}
},
error : function( xhr, option, error ) {
alert(xhr.status); // 오류 코드
alert(error); // 오류 내용
}
});
});
})
function validForm() {
validPass = true;
// 기존 에러 전부 제거 (중복 방지)
document.querySelectorAll('.error').forEach(el => el.remove());
const nameEle = document.getElementById("username");
const phoneEle = document.getElementById("phone");
const emailEle = document.getElementById("email");
if (emailEle.value == "") {
const parentTd = emailEle.closest('td');
parentTd.insertAdjacentHTML('beforeend','<span class="error">이메일을 입력해주세요.</span>');
validPass = false;
} else { // 값 있음. 형식 체크
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; // 이메일 정규식
if (emailEle.value && !emailRegex.test(emailEle.value)) { // 형식 오류
const parentTd = emailEle.closest('td');
parentTd.insertAdjacentHTML('beforeend','<span class="error">이메일형식이맞지않습니다</span>');
validPass = false;
}
}
if (phoneEle.value == "") {
const parentTd = phoneEle.closest('td');
parentTd.insertAdjacentHTML('beforeend','<span class="error">전화번호를 입력해주세요.</span>');
validPass = false;
} else {
if (phoneEle.value.length < 8) {
const parentTd = phoneEle.closest('td');
parentTd.insertAdjacentHTML('beforeend','<span class="error">전화번호를 정확히 입력해주세요.</span>');
validPass = false;
}
}
if (nameEle.value == "") {
const parentTd = nameEle.closest('td');
parentTd.insertAdjacentHTML('beforeend','<span class="error">이름을 입력해주세요.</span>');
validPass = false;
}
return validPass;
}
</script>
<!-- javascript end-->
<!-- 페이지 컨테이너 시작 -->
<section class="drilling-page-container">
<div class="page-content-wrapper drilling inquiry">
<!-- 서브메뉴 시작 -->
<div class="page-sidebar-wrapper">
<div class="page-sidebar">
<div class="treeview-project-name">
<p class="project-title">마이페이지</p>
<p class="project-value value-is-active">정보수정</p>
<!-- <p class="project-value"><a href="/drilling/input.do">건설현장 입력</a></p> -->
</div>
</div>
</div>
<!-- 서브메뉴 끝 -->
<!-- 콘텐츠 시작 -->
<div class="page-content">
<div class="page-content-inner">
<!-- 카테고리 시작 -->
<div class="category-wrapper">
<ul class="page-category">
<li class="category-item"></li>
<li class="category-item">마이페이지</li>
</ul>
<a href="#" class="btn btn-help">도움말</a>
</div>
<!-- 카테고리 끝 -->
<h1 class="page-title-1depth">정보수정</h1>
<!-- 내용 시작 -->
<div class="content-wrapper">
<div class="content1">
<h2 class="card-title">회원 정보 수정</h2>
<!-- <form id="memberInfoForm" method="post" action="/drilling/account/updateMypage.do"> -->
<form id="memberInfoForm" method="post" action="/drilling/account/updateMypage.do">
<table class="mypage-table">
<colgroup>
<col style="width: 200px;">
<col>
</colgroup>
<tbody>
<tr>
<th>아이디</th>
<td>
<input type="text" id="userid" name="userid" value="${USERID}" readonly disabled />
</td>
</tr>
<tr>
<th>이름</th>
<td>
<input type="text" id="username" name="username" autocomplete="username" value="${USERNAME}" />
</td>
</tr>
<tr>
<th>전화번호</th>
<td>
<input type="text" id="phone" name="phone" autocomplete="phone" value="${PHONE}" placeholder="010-0000-0000" />
</td>
</tr>
<tr>
<th>이메일</th>
<td>
<input type="text" id="email" name="email" autocomplete="email" value="${EMAIL}" placeholder="example@email.com" />
</td>
</tr>
</tbody>
</table>
<div class="bottom-buttons marT30">
<button type="button" id="btnSaveMypage" class="btn btn-save-mypage pull-right">수정</button>
</div>
</form>
</div>
</div>
<!-- 내용 끝 -->
</div>
</div>
<!-- 콘텐츠 끝 -->
</div>
</section>
<!-- 페이지 컨테이너 끝 -->
<!-- <div id="calenderDiv" class="trViewOff" style="position:absolute;"></div> -->
<%@ include file="/include/inc_footer_2021_new.jsp" %>

View File

@ -208,6 +208,11 @@
<a href="/logout.do?location=index"> <a href="/logout.do?location=index">
로그아웃 로그아웃
</a> </a>
</li>
<li class="">
<a href="/drilling/mypage.do">
마이페이지
</a>
</li> </li>
</ul> </ul>
</nav> </nav>

View File

@ -3564,7 +3564,6 @@ ul.faq-q > li textarea {
width: 100%; width: 100%;
max-width: 1280px; max-width: 1280px;
margin: 0 auto; margin: 0 auto;
padding-right: 65px;
} }
.drilling-wrap-header #header_cont .wrap_menu .wrap_area .gnb > ul:after { .drilling-wrap-header #header_cont .wrap_menu .wrap_area .gnb > ul:after {
content: ""; content: "";
@ -3573,7 +3572,7 @@ ul.faq-q > li textarea {
} }
.drilling-wrap-header #header_cont .wrap_menu .wrap_area .gnb > ul > li { .drilling-wrap-header #header_cont .wrap_menu .wrap_area .gnb > ul > li {
float: left; float: left;
width: calc(16.6666666667% - 0.1px); width: calc(14.2857142857% - 0.1px);
max-width: 203px; max-width: 203px;
} }
.drilling-wrap-header #header_cont .wrap_menu .wrap_area .gnb > ul > li:first-child a i:before { .drilling-wrap-header #header_cont .wrap_menu .wrap_area .gnb > ul > li:first-child a i:before {
@ -6502,6 +6501,19 @@ ul.faq-q > li textarea {
width: 26px; width: 26px;
height: 26px; height: 26px;
} }
.drilling .content-wrapper .bottom-buttons .btn-save-mypage::before {
content: "";
display: block;
position: absolute;
top: 4px;
left: 8px;
width: 24px;
height: 24px;
background: url(/com/img/common/icon/ico_btn_write.png) no-repeat 50% 50%;
}
.drilling .content-wrapper .bottom-buttons .btn-save-mypage:hover {
background: #199acb;
}
.drilling .content1 { .drilling .content1 {
position: relative; position: relative;
width: 100%; width: 100%;

File diff suppressed because one or more lines are too long

View File

@ -3064,7 +3064,6 @@ ul.faq-q > li textarea {
width:100%; width:100%;
max-width:1280px; max-width:1280px;
margin:0 auto; margin:0 auto;
padding-right:65px;
&:after{ &:after{
content:''; content:'';
@ -3073,7 +3072,7 @@ ul.faq-q > li textarea {
} }
& > li{ & > li{
float:left; float:left;
width:calc(100%/6 - 0.1px); width:calc(100%/7 - 0.1px);
max-width:203px; max-width:203px;
&:first-child a i:before{ &:first-child a i:before{
display:none display:none
@ -4821,6 +4820,23 @@ ul.faq-q > li textarea {
height: 26px; height: 26px;
} }
} }
.btn-save-mypage{
&::before {
content: "";
display: block;
position: absolute;
top: 4px;
left: 8px;
width: 24px;
height: 24px;
background: url(/com/img/common/icon/ico_btn_write.png) no-repeat 50% 50%;
}
&:hover {
background: #199acb;
}
}
} }
} }
.content1 { .content1 {