7147. 회원탈퇴기능 추가

This commit is contained in:
iyak 2025-07-23 04:21:57 +00:00
parent b052aac45b
commit 4fb54561ba
17 changed files with 1017 additions and 147 deletions

View File

@ -717,6 +717,7 @@
<Content Include="Views\croom\grade0_1.cshtml" />
<Content Include="Views\croom\gradeall0_1.cshtml" />
<Content Include="Views\croom\gradeupload.cshtml" />
<Content Include="Views\user\LeaveHistory.cshtml" />
</ItemGroup>
<ItemGroup>
<Folder Include="App_Data\" />

View File

@ -1,6 +1,8 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
@ -10,9 +12,56 @@ namespace NP.BO.Controllers
{
public class userController : BOBaseController
{
public ActionResult users(NP.Model.VMUser vm){vm.viewname = "user";return us(vm);}
public ActionResult professors(NP.Model.VMUser vm){vm.viewname = "professor";return us(vm);}
public ActionResult admins(NP.Model.VMUser vm){vm.viewname = "admin";return us(vm);}
/// <summary>
/// 사용자설정 > 수강생
/// </summary>
/// <param name="vm"></param>
/// <returns></returns>
public ActionResult users(NP.Model.VMUser vm)
{
vm.viewname = "user";return us(vm);
}
/// <summary>
/// 사용자설정 > 교강사
/// </summary>
/// <param name="vm"></param>
/// <returns></returns>
public ActionResult professors(NP.Model.VMUser vm)
{
vm.viewname = "professor"; return us(vm);
}
/// <summary>
/// 사용자설정 > 운영자
/// </summary>
/// <param name="vm"></param>
/// <returns></returns>
public ActionResult admins(NP.Model.VMUser vm)
{
vm.viewname = "admin";return us(vm);
}
/// <summary>
/// 사용자설정 > 회원탈퇴
/// </summary>
/// <param name="vm">회원탈퇴히스토리 ViewModel</param>
/// <returns></returns>
public ActionResult LeaveHistory(VMUsersLeave vm)
{
#region + Get : users.leavelist ( )
var p = SetHash(vm);
base.SetHash(vm);
p.Add("LeaveStatus", vm.LeaveStatus);
vm.UserLeaves = Dao.Get<UserLeave>("users.leavelist", p) ?? new List<UserLeave>();
vm.pagetotalcount = GetCount(vm.UserLeaves.FirstOrDefault());
#endregion
return View(vm);
}
public ActionResult us(VMUser vm)
{
LogSet(new ActLog() {logtype = 10, logtarget = vm.viewname == "user" ? 11 : vm.viewname == "professor" ? 12 : 13, logdata = vm.viewname == "user" ? "사용자목록" : vm.viewname == "professor" ? "교강사목록" : "운영자목록", uno = SUserInfo.UserNo, uip = GetUserIP() });
@ -43,25 +92,32 @@ namespace NP.BO.Controllers
}
ht[vm.stringval4] = vm.stringval5;
}
vm.Users = Dao.Get<Users>("users.users", ht);
ViewBag.IsSiteAdmin = SUserInfo.IsSiteAdmin;
vm.pagetotalcount = GetCount(vm.Users.FirstOrDefault());
return View("us",vm);
}
public ActionResult userreg(NP.Model.VMUser vm) { return ur(vm); }
public ActionResult professorreg(NP.Model.VMUser vm) { return ur(vm); }
public ActionResult adminreg(NP.Model.VMUser vm) { return ur(vm); }
public ActionResult ur(VMUser vm)
{
vm.User = new Users() { status = 1, /*jointype=0,*/ usertype = vm.viewname == "user" ? 1 : vm.viewname == "professor" ? 11 : 0 };
vm.User = new Users() { status = 1, usertype = vm.viewname == "user" ? 1 : vm.viewname == "professor" ? 11 : 0 };
vm.Lects = new List<Lect>() { };
vm.FileList = new List<File>() { };
vm.CMPRs = new List<CMPR>() { };
vm.Councels = new List<Councel>() { };
vm.ComCodes2 = GetComCodes("bldgcat");
if (vm.intval > 0)
{
vm.User = Dao.Get<Users>("users.users", new System.Collections.Hashtable() { { "userno", vm.intval } , { "includesysadmin", 1 } }).First();
vm.Councel = new Councel() { };
vm.Councels = Dao.Get<Councel>("users.councels", new System.Collections.Hashtable() { { "userno", vm.intval } });
LogSet(new ActLog() { logtype = 20, logtarget = 21, logdata = vm.User.username + "("+vm.User.userid+")", userno = vm.User.userno, uno = SUserInfo.UserNo, uip = GetUserIP() });

View File

@ -9,6 +9,7 @@
<th>미열람쪽지</th>
<th>홈페이지Q&A미답변</th>
<th>강의Q&A미답변</th>
<th>회원탈퇴요청</th>
<th>환불요청</th>
@*<th>교재미배송</th>*@
<th>계산서미확인</th>
@ -19,6 +20,7 @@
<td class="link text-center @(Model.Data.intval > 0 ? "emphasis":"")"><a href="javascript:taskSummaryPendingLink(1);">@Model.Data.intval.ToString("#,0") 건</a></td>
<td class="link text-center @(Model.Data.intval2 > 0 ? "emphasis":"")"><a href="javascript:taskSummaryPendingLink(2);">@Model.Data.intval2.ToString("#,0") 건</a></td>
<td class="link text-center @(Model.Data.intval3 > 0 ? "emphasis":"")"><a href="javascript:taskSummaryPendingLink(3);">@Model.Data.intval3.ToString("#,0") 건</a></td>
<td class="link text-center @(Model.Data.intval3 > 0 ? "emphasis":"")"><a href="javascript:taskSummaryPendingLink(6);">@Model.Data.intval7.ToString("#,0") 건</a></td>
<td class="link text-center @(Model.Data.intval4 > 0 ? "emphasis":"")"><a href="javascript:taskSummaryPendingLink(4);">@Model.Data.intval4.ToString("#,0") 건</a></td>
@*<td class="link text-center @(Model.Data.intval5 > 0 ? "emphasis":"")"><a href="/croom/deliveries">@Model.Data.intval5.ToString("#,0") 건</a></td>*@
<td class="link text-center @(Model.Data.intval6 > 0 ? "emphasis":"")"><a href="javascript:taskSummaryPendingLink(5);">@Model.Data.intval6.ToString("#,0") 건</a></td>
@ -128,7 +130,7 @@
@*
/* 잔여업무 요약 클릭 시 링크
* @param {string} tabNo - 탭 번호 (1: 미열람쪽지, 2: 홈페이지Q&A미답변, 3: 강의Q&A미답변, 4: 환불요청, 5: 계산서미확인)
* @param {string} tabNo - 탭 번호 (1: 미열람쪽지, 2: 홈페이지Q&A미답변, 3: 강의Q&A미답변, 4: 환불요청, 5: 계산서미확인), 6: 회원탈퇴요청
* */
*@
function taskSummaryPendingLink(tabNo) {
@ -156,6 +158,11 @@
p.stringval12 = '0';
postSubmit('/croom/tax', p);
break;
case 6:
var p = {};
p.LeaveStatus = 0;
postSubmit('/user/LeaveHistory', p);
break;
default: break;
}
}

View File

@ -0,0 +1,191 @@
@model NP.Model.VMUsersLeave
<form id="mform" method="post">
<section class="panel panel-default clearfix devsearch" data-cleartbody="tbody1">
@Html.Partial("./Partial/SearchCaption")
<div class="step-content">
<div class="step-pane active form-inline">
<div class="form-group">
@Html.Partial("./Partial/Select", null, new ViewDataDictionary { { "name", "LeaveStatus" }, { "selected", Model.LeaveStatus }, { "valuetext", ":-선택;0:신청;1:완료;2:취소" } })
@Html.Partial("./Partial/Select", null, new ViewDataDictionary { { "name", "searchtype" }, { "selected", Model.searchtype }, { "valuetext", "username:이름;userid:ID" } })
@Html.Partial("./Partial/Text", Model.stringval5, Helpers.DicText(new NP.Model.TextDic() { Name = "searchtext", Value = Model.searchtext, PH = "검색어를 입력하세요.", CssClass = "esitem" }))
<div class="form-group input-group-btn">
<button class="btn btn-default btn-s-xs" type="button" onclick="javascript:userleaveSearch();"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</div>
</section>
<div class="tar buttonbox m-b-sm">
@Html.Partial("./Partial/pagerow", new ViewDataDictionary { { "tbodyid", "tbody1" }, { "searchmethod", "submit()" }, { "pagesize", Model.pagerowcount } })
<a href="javascript:;" onclick="userLeaves(1);" class="btn btn-s-xs btn-danger"><i class="fa fa-ban"></i> 완료처리</a>
<a href="javascript:;" onclick="userLeaves(2);" class="btn btn-s-xs btn-primary"><i class="fa fa-reply-all"></i> 취소처리</a>
</div>
<br/>
<section class="panel panel-default">
<div class="table-responsive" id="excel1">
<table class="table table-striped b-t b-light">
<colgroup>
<col style="width:10%" />
<col />
<col />
<col />
</colgroup>
<thead>
<tr>
<th>선택</th>
<th>아이디</th>
<th>요청일</th>
<th>처리상태</th>
</tr>
</thead>
<tbody class="data" id="tbody1">
@if (Model.UserLeaves.Any())
{
foreach (var item in Model.UserLeaves)
{
<tr>
<td>
@if (item.status == 0 && item.userstatus == 98)
{ // 탈퇴신청이면서 회원상태는 탈퇴신청일때만 체크박스
<input type="checkbox" id="chk_@item.levno" value="@item.userno" />
}
else if (item.status == 0 && item.userstatus != 98)
{ // 위 if절이 명확하지 않으면 readonly 처리 (조작된 데이터로 예상)
<input type="checkbox" id="chk_@item.levno" value="@item.userno" readonly="readonly" />
}
<input type="hidden" id="hdn_UserStatus" value="@item.userstatus" />
</td>
<td>
@if (item.status != 1 && item.userstatus != 99)
{
<a href="javascript:;" onclick="reg(@item.userno);" style="text-decoration: underline; color: blue;">
@item.userid @string.Format("({0})", item.username)
</a>
}
else
{
<span>@item.userid</span>
}
</td>
<td>@item.levdate.ToString("yy-MM-dd HH:mm")</td>
<td>
@if (item.status != 1 && item.userstatus == 99)
{
<span>@this.LeaveStatusToText(item.status)</span> <span>(관리자탈퇴)</span>
}
else
{
<span>@this.LeaveStatusToText(item.status)</span>
}
</td>
</tr>
}
}
</tbody>
</table>
<div id="pagerArea">
@Html.Pager((int)Model.pagenum, 10, Model.pagerowcount, Model.pagetotalcount)
</div>
</div>
</section>
</form>
<form id="dform" method="post" action="/user/userreg">
@Html.Partial("./Partial/dform", Model, new ViewDataDictionary { { "preform", 1 } })
</form>
@section scripts{
<script type="text/javascript">
$(function () {
});
@*/** 검색 */*@
function userleaveSearch() {
var p = {};
p.searchtype = $('#searchtype').val();
p.searchtext = $.trim($('#searchtext').val());
p.LeaveStatus = $.trim($('#LeaveStatus').val());
postSubmit('/user/LeaveHistory', p);
}
@*/** 탈퇴완료 처리 클릭 */ *@
function userLeaves(status) {
var _usernos = $('input[type="checkbox"]:checked')
.map(function () { return this.value; })
.get()
.join(',');
var statusNumber = parseInt(status);
if (isNaN(statusNumber)) {
msg('오류가 발생했습니댜.');
return;
}
if (![1, 2].includes(statusNumber)) {
msg('오류가 발생했습니다.');
return;
}
var confirmMessage = statusNumber == 1 ?
"선택한 수강생을 탈퇴 완료처리 하시겠습니까?" : "선택한 수강생에 대해 취소처리 하시겠습니까?";
if (_usernos != undefined && _usernos != null && _usernos != '') {
// 영남에 confirmmsg가 없다
if (confirm(confirmMessage)) {
capp(
'/acommon/UserLeaves',
{
usernos: _usernos,
leaveStatus: statusNumber
},
'cbUserLeave'
);
}
}
else {
msg('수강생을 선택해주세요.');
}
}
@*/** 탈퇴완료 처리 콜백 */*@
function cbUserLeave() {
msg('선택한 수강생을 탈퇴완료처리 했습니다.');
submit(null, 300);
}
@*/** 회원정보 상세보기 페이지 이동 */*@
function reg(no) {
setv("dform_intval", no);
setv("dform_viewname", "leavehistory");
$("#dform").attr("action", "/user/userreg").submit();
}
</script>
}
@functions{
/// <summary>
/// 탈퇴 신청 히스토리의 상태코드 값을 텍스트로 반환
/// </summary>
/// <param name="status"></param>
/// <returns></returns>
public string LeaveStatusToText(byte status)
{
string result = string.Empty;
switch (status)
{
case 0: result = "신청"; break;
case 1: result = "완료"; break;
case 2: result = "취소"; break;
default: break;
}
return result;
}
}

View File

@ -228,10 +228,15 @@
{
<a href="#" class="btn btn-info" onclick="cancel();">휴면해제</a>
}
else if(Model.viewname == "leavehistory")
{
<a href="javascript:;" class="btn btn-default" onclick="goLeaveHistory();">탈퇴신청내역</a>
}
else
{
<a href="#" class="btn btn-primary" onclick="save();">저장</a>
}
@if (Model.User.userno > 0 && Model.viewname == "user")
{
<a href="#" class="btn btn-danger" onclick="del();">탈퇴</a>
@ -240,7 +245,11 @@
{
<a href="#" class="btn btn-danger" onclick="del();">삭제</a>
}
<a href="#" class="btn btn-default" onclick="golist();">목록</a>
@if (Model.viewname != "leavehistory")
{
<a href="#" class="btn btn-default" onclick="goLeaveHistory();">목록</a>
}
</div>
@Html.HiddenFor(m => m.intval)
@Html.HiddenFor(m => m.User.userno)
@ -639,9 +648,13 @@
function del() {
if (confirm(('@Model.viewname' == "user"?"탈퇴":"삭제")+"처리하시겠습니까?")) {
capp("/acommon/userexitjoin", { userno: @Model.User.userno}, "cbdel");
capp(
"/acommon/UsersDel",
{ usernos: @Model.User.userno},
"cbdel");
}
}
function cbdel() {
if (capResult.code == 1000) {
msg("처리되었습니다.", 0, null, null, true);
@ -784,5 +797,10 @@
$("#taxform").submit();
}, 500);
}
function goLeaveHistory() {
window.location.href = '/user/LeaveHistory';
}
</script>
}

View File

@ -23,7 +23,7 @@
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="fronturl" value="https://www.ynicte.com" />
<add key="fronturl" value="http://www.ynicte.com" />
<add key="adminurl" value="http://admin.ynicte.com" />
<add key="adminips" value="118.219.255.223;118.219.255.225;118.219.255.189;118.219.255.190" />
<add key="reporturl" value="http://ynicter.nptc.kr" />
@ -33,7 +33,7 @@
<add key="masteremail" value="yicte@cte.or.kr;smtp.daum.net;465;yicte2020;txwhczubbkcbotfd" />
<add key="popbillManager" value="070-5088-4781;박희란" />
<add key="usessl" value="Y" />
<add key="usessl" value="N" />
<add key="daokey" value="ynictelms2020" />
<!--결제 url | mid | hashed signkey | 취소모듈비밀번호 | 거래번호앞두자리-->

View File

@ -8,6 +8,7 @@ using NP.Model;
using System.Collections;
using NP.Base.Auth;
using NP.Base.ENUM;
using IBatisNet.Common.Transaction;
namespace NP.Base.Controllers
{
public partial class ACommonController : NP.Base.BaseController
@ -99,12 +100,35 @@ namespace NP.Base.Controllers
{
return JsonOK(Dao.Save("users.exitjoin", new Hashtable() { { "userno", userno }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } }));
}
public JsonResult UsersDel(String usernos)
{
Dao.Save("users.dormant.delete", new Hashtable() { { "usernos", usernos }});
return JsonOK(Dao.Save("users.exitjoin", new Hashtable() { { "usernos", usernos }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } }));
/// <summary>
/// 탈퇴
/// </summary>
/// <param name="usernos">회원번호들 ("1,2,3,4...")</param>
/// <returns></returns>
public JsonResult UsersDel(string usernos)
{
int resultCode = 0;
var p = new Hashtable();
#region + Save: users.dormant.delete ( )
p.Clear();
p.Add("usernos", usernos);
Dao.Save("users.dormant.delete", p);
#endregion
#region + Save: users.leave ( )
p.Clear();
p.Add("usernos", usernos);
p.Add("uno", SUserInfo.UserNo);
p.Add("uip", GetUserIP());
resultCode = Dao.Save("users.leave", p);
#endregion
return JsonOK(resultCode);
}
public JsonResult UsersDormant(String usernos)
{
return JsonOK(Dao.Save("users.dormant", new Hashtable() { { "usernos", usernos }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } }));
@ -339,6 +363,94 @@ namespace NP.Base.Controllers
}
/// <summary>
/// 회원 탈퇴
/// </summary>
/// <param name="usernos">, 로 구분자 생성된 회원번호들</param>
/// <param name="leaveStatus">탈퇴신청상태 (1:완료, 2:취소)</param>
/// <returns></returns>
[HttpPost]
public JsonResult UserLeaves(string usernos, int leaveStatus)
{
var p = new Hashtable();
try
{
int resultCode = 0;
using (var t = new TransactionScope())
{
if (leaveStatus == 1)
{
#region + Save: users.dormant.delete ( , .)
p.Clear();
p.Add("usernos", usernos);
resultCode = Dao.Save("users.dormant.delete", p);
#endregion
#region + Save: users.leave ( ( ))
p.Clear();
p.Add("usernos", usernos);
p.Add("uno", SUserInfo.UserNo);
p.Add("uip", GetUserIP());
resultCode = Dao.Save("users.leave", p);
#endregion
#region + Save: users.leave.update ( (1))
if (resultCode > 0)
{
p.Clear();
p.Add("status", leaveStatus);
p.Add("usernos", usernos);
p.Add("uno", SUserInfo.UserNo);
p.Add("uip", GetUserIP());
resultCode = Dao.Save("users.leave.update", p);
}
#endregion
}
else if (leaveStatus == 2)
{
#region + Save: users.status.update (: users테이블 status )
p.Clear();
p.Add("usernos", usernos);
p.Add("status", 1); // 탈퇴취소로 정상으로 되돌림
p.Add("uno", SUserInfo.UserNo);
p.Add("uip", GetUserIP());
resultCode = Dao.Save("users.status.update", p);
#endregion
#region + Save: users.leave.update ( (2))
if (resultCode > 0)
{
p.Clear();
p.Add("status", leaveStatus);
p.Add("usernos", usernos);
p.Add("uno", SUserInfo.UserNo);
p.Add("uip", GetUserIP());
resultCode = Dao.Save("users.leave.update", p);
}
#endregion
}
// 쿼리 2건 실행에 대한 최종 커밋
if (resultCode > 0)
{
t.Complete();
}
}
return JsonOK(resultCode);
}
catch (Exception ex)
{
SetError($"회원 탈퇴처리 실패: {ex.Message}");
return JsonBack(new JsonRtn() { code = 1 });
}
}
}

View File

@ -316,23 +316,41 @@ namespace NP.Base
return Convert.ToInt64(b);
}
/// <summary>
/// 현재 HTTP 요청이 POST 메서드를 사용하는지 여부
/// </summary>
/// <returns></returns>
public bool IsPost()
{
return Request.HttpMethod.ToUpper().Equals("POST");
return Request?.HttpMethod?.Equals("POST", StringComparison.OrdinalIgnoreCase) ?? false;
}
public System.Collections.Hashtable SetHash(NP.Model.VMBase vm, bool appendSearch = true)
/// <summary>
/// 매개변수 VMBase를 받아 페이지 번호화 페이지 출력수를 설정한 Hashtable을 반환.
/// </summary>
/// <param name="vm"></param>
/// <returns></returns>
public Hashtable SetHash(VMBase vm, bool appendSearch = true)
{
vm.pagenum = vm.pagenum ?? 1;
vm.pagerowcount = vm.pagerowcount < 1 ? (vm.isexceldown == 1 ? 100000 : PageRowCount) : vm.pagerowcount;
var rht = new System.Collections.Hashtable() { { "pagenum", vm.pagenum.Value }, { "pagerowsize", vm.pagerowcount } };
var rht = new Hashtable()
{
{ "pagenum", vm.pagenum.Value },
{ "pagerowsize", vm.pagerowcount },
{ "pageoffset", (vm.pagenum.Value - 1) * vm.pagerowcount }
};
if (appendSearch)
{
rht.Add("searchtype", vm.searchtype);
rht.Add("searchtext", vm.searchtext);
}
return rht;
}
public List<T> InitM<T>()
{
return new List<T>() { };
@ -1956,7 +1974,7 @@ namespace NP.Base
// p.Add("subdomain", sd);
//}
var u = Dao.Get<NP.Model.Users>("users.userlogin", p).FirstOrDefault();
if (u != null)
if (u != null && u.status != 98 && u.status != 99)
{
/*

View File

@ -1,16 +1,18 @@
using System;
using IBatisNet.Common.Transaction;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NP.Base.Auth;
using NP.Base.ENUM;
using NP.Base.Popbill;
using NP.Model;
using QRCoder;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NP.Model;
using System.Collections;
using NP.Base.Auth;
using NP.Base.ENUM;
using QRCoder;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Web.UI.WebControls;
namespace NP.Base.Controllers
{
@ -272,17 +274,60 @@ namespace NP.Base.Controllers
return JsonOK(passResult);
}
/// <summary>
/// 회원탈퇴 진행
/// </summary>
/// <param name="exitreason"></param>
/// <returns></returns>
[HttpPost]
public JsonResult UserExit(String exitreason)
{
//탈퇴할때데이터 정리는 무엇인가 해야할 텐데?
var rtn = Dao.Save("users.exit", new Hashtable() { { "userno", SUserInfo.UserNo }, { "exitreason", exitreason }, { "uno", SUserInfo.UserNo }, { "uip", GetUserIP() } });
try
{
int rtn = -1;
using (var t = new TransactionScope())
{
#region + Save: users.exit ( )
var p = new Hashtable();
p.Add("userno", SUserInfo.UserNo);
p.Add("status", 98); // 98 탈퇴신청, 99 탈퇴완료
p.Add("uno", SUserInfo.UserNo);
p.Add("uip", GetUserIP());
rtn = Dao.Save("users.exit", p);
#endregion
if (rtn > 0)
{
#region + Save: users.leave.register ( )
rtn = Dao.Save("users.leave.register", p);
#endregion
}
if (rtn > 0)
{
CookieClear(null, true);
}
Session.Abandon();
t.Complete();
return JsonOK(rtn);
}
else
{
return JsonError(JSONCode.Error, "데이터 처리 오류.", false);
}
}
}
catch (Exception ex)
{
SetError($"회원탈퇴 실패: {ex.Message}");
return JsonError(JSONCode.Error, "회원탈퇴에 실패 하였습니다.", false);
}
}
[HttpPost]
public JsonResult AssignUpdate(Assign a)
{

View File

@ -115,9 +115,11 @@ namespace NP.Base.Controllers
{
CookieClear("savedid");
}
if (!string.IsNullOrEmpty(uid) && !string.IsNullOrEmpty(upw))
{
var u = GoLogin(uid, upw);
if (u != null)
{
if(u.intv1 == 1)
@ -152,6 +154,15 @@ namespace NP.Base.Controllers
{
return JsonBack(new JsonRtn() { code = 1000, msg = "-3", obj = u.userno });
}
if (u.status == 98)
{
// 탈퇴신청중
u = null;
CookieClear(null, true);
return JsonBack(new JsonRtn() { code = 1000, msg = "-6", obj = null });
}
return JsonOK(u.userno);
}
}

View File

@ -396,7 +396,13 @@
order by b.username
</select>
<select id="common.home" parameterClass="int" resultClass="data">
select b.cnt intval,c.cnt0 intval2,c.cnt1 intval3,d.cnt intval4,e.cnt intval5,f.cnt intval6
select b.cnt intval
,c.cnt0 intval2
,c.cnt1 intval3
,d.cnt intval4
,e.cnt intval5
,f.cnt intval6
,(SELECT COUNT(*) FROM userleave WHERE status = 0) intval7
from (select 1 col1) a
left outer join (select count(mno) cnt from memouser where userno=#userno# and isread=0 and isdel=0) b on 1=1
left outer join (

View File

@ -2,8 +2,8 @@
<sqlMap xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/tr/xmlschema-1/" namespace="">
<alias>
<!--tfile, 첨부파일 -->
<typeAlias alias="users" type="NP.Model.Users, NP.Model" />
<typeAlias alias="usersleave" type="NP.Model.UserLeave, NP.Model" />
<typeAlias alias="authlog" type="NP.Model.AuthLog, NP.Model" />
<typeAlias alias="loginlog" type="NP.Model.LoginLog, NP.Model" />
<typeAlias alias="assign" type="NP.Model.Assign, NP.Model" />
@ -274,18 +274,14 @@
<isNotNull property="asno" prepend="and">a.asno=#asno#</isNotNull>
<isNotNull property="profandmainadmin" prepend="and">(a.usertype=11 or (a.usertype &gt; 80 and b.ismain=1))</isNotNull>
<isNotNull property="asname" prepend="and">b.asname like concat('%',#asname#,'%')</isNotNull>
<!--<isNotNull property="asname" prepend="and">b.asname = #asname#</isNotNull>-->
<isNotEmpty property="brno" prepend="and">b.brno=#brno#</isNotEmpty>
<isNotNull property="email" prepend="and">
<!--CAST(AES_DECRYPT(UNHEX(a.email), <include refid="sql.digest"></include>) AS char) like concat('%',#email#,'%')-->
a.email=HEX(AES_ENCRYPT(#email#, <include refid="sql.digest"></include>))
</isNotNull>
<isNotEmpty property="mobile" prepend="and">
<!--CAST(AES_DECRYPT(UNHEX(a.mobile), <include refid="sql.digest"></include>) AS char) like concat('%',#mobile#,'%')-->
a.mobile=HEX(AES_ENCRYPT(#mobile#, <include refid="sql.digest"></include>))
</isNotEmpty>
<isNotEmpty property="userpno" prepend="and">
<!--CAST(AES_DECRYPT(UNHEX(a.userpno), <include refid="sql.digest"></include>) AS char) like concat('%',#userpno#,'%')-->
a.userpno=HEX(AES_ENCRYPT(#userpno#, <include refid="sql.digest"></include>))
</isNotEmpty>
<isNotNull property="usertypeover" prepend="and">a.usertype &gt; #usertypeover#</isNotNull>
@ -423,6 +419,8 @@
<isNotNull property="userno">userno=#userno#</isNotNull>
<isNotNull property="usernos">userno in ($usernos$)</isNotNull>
</update>-->
<!-- 탈퇴값 상태변경 (2025.07.22 사용안함) -->
<update id="users.exitjoin" parameterClass="hashtable">
update users set <include refid="sql.up"></include>
,status=99
@ -660,11 +658,49 @@
,CAST(AES_DECRYPT(UNHEX(email), <include refid="sql.digest"></include>) AS char) email
from users where userno=#userno#
</select>
<!--<update id="users.leave" parameterClass="hashtable">
update users set <include refid="sql.up"></include>
,status=99,username='탈퇴',email=null,userid=null,mobile=null,telno=null,userpno=null,bankno=null
where status&lt;&gt;99 <isNotNull property="usernos"> and userno in ($usernos$)</isNotNull>
</update>-->
<!-- 회원탈퇴 (완전히 users 정보 삭제) -->
<update id="users.leave" parameterClass="hashtable">
UPDATE users
SET
<include refid="sql.up"></include>
<![CDATA[
, username = '탈퇴'
, usernameeng = NULL
, email = NULL
, mobile = NULL
, telno = NULL
, userpno = NULL
, bankno = NULL
, post = NULL
, address1 = NULL
, address2 = NULL
, birthday = NULL
, di = NULL
, ci = NULL
, vssn = NULL
, authplatform = 0
, userpass = NULL
, status = 99
WHERE status != 99
]]>
<isNotNull property="userno">AND userno = #userno#</isNotNull>
<isNotNull property="usernos">AND userno IN ($usernos$)</isNotNull>
</update>
<update id="users.status.update" parameterClass="hashtable">
UPDATE users
SET
<include refid="sql.up"></include>
<![CDATA[
, status = #status#
WHERE status != 99
]]>
<isNotNull property="userno">AND userno = #userno#</isNotNull>
<isNotNull property="usernos"> AND userno IN ($usernos$)</isNotNull>
</update>
<select id="users.userlogin" parameterClass="hashtable" resultClass="users">
select a.userid, a.userpass,a.userno,a.username,a.status,usertype,a.asno,a.udt
,b.subdomain
@ -765,12 +801,51 @@
,username='탈퇴회원',usernameeng=null,email=null,mobile=null,telno=null,birthday=null,vssn=null,di=null,ci=null,userpno=null,bankno=null,post=null,address1=null,address2=null,authplatform=0,status=99
where userno=#userno#
</update>-->
<!-- 회원 탈퇴 신청 -->
<update id="users.exit" parameterClass="hashtable">
update users set <include refid="sql.up"></include>
,exitreason=#exitreason#
,status=99
where userno=#userno#
UPDATE users
SET <include refid="sql.up"></include>
, status = #status#
WHERE userno=#userno#
</update>
<!-- 회원 탈퇴 히스토리 등록 -->
<update id="users.leave.register" parameterClass="hashtable">
INSERT INTO userleave (
userno,
userid,
status,
levdate,
uno,
uip
)
SELECT
u.userno,
u.userid,
0 AS status,
NOW() AS levdate,
u.uno,
u.uip
FROM users u
WHERE u.status = #status#
AND u.userno = #userno#
</update>
<update id="users.leave.update" parameterClass="hashtable">
<![CDATA[
UPDATE userleave
SET status = #status#
, uno = #uno#
, uip = #uip#
, levdate = NOW()
]]>
<dynamic prepend="where">
<isNotNull property="usernos">userno IN ($usernos$)</isNotNull>
</dynamic>
</update>
<update id="users.remotelogin.set" parameterClass="hashtable">
update users a
inner join assign b on b.asno=a.asno and b.siteip like concat('%',#siteip#,'%')
@ -923,8 +998,13 @@
delete from userdormant where userno in ($usernos$);
</update>
<!-- 회원휴면 대상자 완전삭제 -->
<update id="users.dormant.delete" parameterClass="hashtable">
delete from userdormant where userno in ($usernos$);
<![CDATA[
DELETE
FROM userdormant
WHERE userno IN ($usernos$);
]]>
</update>
<update id="users.dormant.del" parameterClass="hashtable">
@ -980,7 +1060,33 @@
where userno=#userno#
</update>
<!-- 회원탈퇴 히스토리 리스트 -->
<select id="users.leavelist" parameterClass="hashtable" resultClass="usersleave">
<![CDATA[
SELECT a.levno
, b.userno
, b.username
, a.userid
, a.status
, a.levdate
, a.uno
, a.uip
, b.status as userstatus
, COUNT(*) OVER() AS pagetotalcount
FROM userleave a
INNER JOIN users b
ON a.userno = b.userno
]]>
<dynamic prepend="where">
<isNotNull property="searchtext">
<isEqual property="searchtype" compareValue="username" prepend="and">b.username LIKE CONCAT('%', #searchtext#,'%')</isEqual>
<isEqual property="searchtype" compareValue="userid" prepend="and">a.userid LIKE CONCAT('%', #searchtext#,'%')</isEqual>
</isNotNull>
<isNotNull property="LeaveStatus" prepend="and">a.status = #LeaveStatus#</isNotNull>
</dynamic>
ORDER BY a.levdate DESC
LIMIT $pagerowsize$ OFFSET $pageoffset$
</select>
</statements>
</sqlMap>

View File

@ -76,7 +76,15 @@
function login() {
if (val("uid") != "" && val("upw") != "") {
capp("/focommon/login", { uid: val("uid"), upw: strEnConvert(val("upw")), issaveid: $("#issaveid").prop("checked"), logincnt: logincnt }, "cblogin");
capp(
"/focommon/login",
{
uid: val("uid"),
upw: strEnConvert(val("upw")),
issaveid: $("#issaveid").prop("checked"),
logincnt: logincnt
},
"cblogin");
}
else if (val("uid") == "") {
focus("uid");
@ -135,6 +143,10 @@
else if (capResult.msg == "-5") { // 비활성상태
msg("비밀번호 5회 이상 오류로 로그인이 제한되었습니다.\n교육원으로 문의해주세요.");
}
else if (capResult.msg == "-6") { // 탈퇴신청중
msg("회원탈퇴가 접수되었습니다.<br/>탈퇴 완료까지 평일 기준 1일 정도 소요될 예정입니다.");
logincnt = 0;
}
else {
$("#mform").attr("action", "/");
if ('@(Model.ru??"")' != "") {

View File

@ -15,12 +15,96 @@
<head>
<script type="text/javascript" src="/js/naveridlogin_js_sdk_2.0.0.js"></script>
<script type="text/javascript" src="/js/kakao.js"></script>
<style type="text/css">
/** 회원탈퇴 관련 css */
.mpgpop_base {
display: none;
justify-content: center;
align-items: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
}
.mpgpop_wrapsub {
background-color: #fff;
border-radius: 0.5rem;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
width: 90%;
max-width: 800px;
overflow: hidden;
font-family: 'Inter', sans-serif;
}
.mpgpop_numtext {
margin-bottom: 0.75rem;
line-height: 1.6;
color: #555;
font-size: 0.95rem;
}
.mpgpop_subtitle {
display: inline-block;
width: 8px;
height: 8px;
background-color: #3b82f6;
border-radius: 2px;
margin-right: 0.5rem;
}
.mpgpop_title {
display: flex;
justify-content: center;
align-items: center;
/*padding: 1rem 1.5rem;*/
background-color: #f7f7f7;
border-bottom: 1px solid #eee;
position: relative;
}
.mpgpop_infotext {
font-size: 1.1rem;
font-weight: bold;
color: #333;
margin-bottom: 1rem;
display: flex;
align-items: center;
}
.mpgpop_btn_leave {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
text-decoration: none;
font-weight: bold;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
background-color: #2563eb;
color: #ffffff !important;
}
.mpgpop_btn_close {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
text-decoration: none;
font-weight: bold;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
background-color: #e5e7eb;
color: #333;
}
</style>
</head>
<form id="mform" method="post" enctype="multipart/form-data">
<div id="naverIdLogin" style="display:none"></div>
<ul class="mpgTab col2">
<li class="current" id="liUserTab"><a href="#" onclick="selectTab('user')">회원정보수정</a></li>
<li id="liSnsTab"><a href="#" onclick="selectTab('sns')">SNS연동</a></li>
<li class="current" id="liUserTab"><a href="javascript:;" onclick="selectTab('user')">회원정보수정</a></li>
@*<li id="liSnsTab"><a href="javascript:;" onclick="selectTab('sns')">SNS연동</a></li>*@
</ul>
<input type="hidden" name="username" id="username" value="@u.username" />
<input type="hidden" name="birthday" id="birthday" value="@u.birthday" />
@ -73,7 +157,7 @@
<td>
<ul class="mdfyAddr postbox">
<li><input type="text" name="post" id="post" class="postno" readonly="readonly" style="background-color: #ddd;" value="@u.post" /></li>
<li><a href="#" onclick="getpost2(this);">주소찾기</a></li>
<li><a href="javascript:;" onclick="getpost2(this);">주소찾기</a></li>
<li><input type="text" name="address1" id="address1" class="postadr" readonly="readonly" style="background-color: #ddd;" value="@u.address1" /></li>
<li><input type="text" name="address2" id="address2" class="postadrsub" value="@u.address2" /></li>
</ul>
@ -91,16 +175,16 @@
</td>
</tr>
<tr >
<tr>
<th>학습인증수단</th>
<td>
<div class="mdfyBirth" id="authPlatform_IPIN" @(u.authplatform == AuthPlatform.Mobile ? "style=display:none;" : "") @(u.authplatform == AuthPlatform.None ? "style=padding-bottom:5px;" : "")>
<p id="authPlatform_IPIN_Name">@(u.authplatform == AuthPlatform.None ? "-" : "I-PIN 인증")</p>
<a href="#" onclick="certok3reqview('MOBI', 'AuthPlatformChange');" style="width:150px;">휴대폰 인증으로 변경</a>
<a href="javascript:;" onclick="certok3reqview('MOBI', 'AuthPlatformChange');" style="width:150px;">휴대폰 인증으로 변경</a>
</div>
<div class="mdfyBirth" id="authPlatform_Mobile" @(u.authplatform == AuthPlatform.IPIN ? "style=display:none;" : "")>
<p id="authPlatform_Mobile_Name">@(u.authplatform == AuthPlatform.None ? "-" : "휴대폰 인증")</p>
<a href="#" onclick="certok3reqview('IPIN', 'AuthPlatformChange');" style="width:150px;">I-PIN 인증으로 변경</a>
<a href="javascript:;" onclick="certok3reqview('IPIN', 'AuthPlatformChange');" style="width:150px;">I-PIN 인증으로 변경</a>
</div>
<br />
※ 인증수단 변경 시 추가 인증을 진행해야 합니다.
@ -112,14 +196,14 @@
<th>연락처</th>
<td>
<div class="mdfyBirth">
@if(u.authplatform == AuthPlatform.Mobile)
@if (u.authplatform == AuthPlatform.Mobile)
{
<input type="hidden" name="mobile" id="mobile" value="@(u.mobile)" />
<p id="mobilestr">@(u.mobile)</p><a href="#" onclick="certok3reqview('MOBI', 'MobileNumberChange');">수정</a>
<p id="mobilestr">@(u.mobile)</p><a href="javascript:;" onclick="certok3reqview('MOBI', 'MobileNumberChange');">수정</a>
}
else
{
<input type="text" id="mobile" class="int nocomma" name="mobile" maxlength="13" placeholder="휴대전화번호" value="@(u.mobile)" >
<input type="text" id="mobile" class="int nocomma" name="mobile" maxlength="13" placeholder="휴대전화번호" value="@(u.mobile)">
}
</div>
</td>
@ -140,7 +224,7 @@
<div class="mdfyBirth">
<input type="hidden" id="asno" name="asno" value="@u.asno" />
<p id="asname">@(u.asname ?? "-")</p>
<a href="#" id="btnassign" onclick="chkassign();" style="background-color:@(u.asno == null ? "#ddd;" : "#fff;")">수정</a>
<a href="javascript:;" id="btnassign" onclick="chkassign();" style="background-color:@(u.asno == null ? "#ddd;" : "#fff;")">수정</a>
</div>
</td>
</tr>*@
@ -198,37 +282,61 @@
</form>
@Html.Partial("./Partial/OkCert3", null, new ViewDataDictionary { })
<ul class="lctBtn">
<li><a href="#" class="sm bk" onclick="save(1)">수정</a></li>
<li><a href="#" class="sm" onclick="save(0)">탈퇴</a></li>
<li><a href="javascript:;" class="sm bk" onclick="save(1)">수정</a></li>
<li>
@if (Model.User.status == 1)
{
<a href="javascript:;" class="sm" onclick="save(0)">탈퇴</a>
}
else
{
<a href="javascript:;" class="sm">탈퇴진행중</a>
}
</li>
</ul>
<div id="postlayer" class="daumpost"><a href="#" class="btn btn-xxs btn-select closedaumpost" onclick="closeDaumPostcode();">close</a></div>
<div class="mpgPop" id="pop1" style="display: none;">
<div>
<div>
<div class="mpgPopWrap wdth660">
<div class="mpgPopTitle">
<h5>회원탈퇴안내</h5>
<a href="#" onclick="mpgPopClose();"></a>
<div id="postlayer" class="daumpost"><a href="javascript:;" class="btn btn-xxs btn-select closedaumpost" onclick="closeDaumPostcode();">close</a></div>
@*<!-- 탈퇴 레이어 팝업 -->*@
<div class="mpgPop mpgpop_base" id="pop1">
<div class="mpgPopWrap mpgpop_wrapsub">
<div class="mpgpMdfy" style="padding: 1.5rem;">
<div class="mpgPopTitle mpgpop_title">
<h5 style="font-size: 1.25rem; font-weight: bold; color: #333; margin: 0;">회원탈퇴 안내</h5>
</div>
<div class="mpgpMdfy">
<dl>
<dd>1. 회원 탈퇴 시 영남건설기술교육원의 모든 서비스를 이용하실 수 없습니다.</dd>
<dd>2. 탈퇴신청된 아이디는 영구적으로 재가입이 불가능합니다.</dd>
<dd>3. 탈퇴시 현재 수강중인 동영상 강의를 수강하실 수 없습니다.</dd>
<dd>4. 위 내용 확인 후 교육원으로 전화주시면 회원탈퇴를 도와 드리겠습니다.</dd>
<dd>문의 : 1544-7660</dd>
</dl>
@*<h5>탈퇴사유</h5>
<textarea id="exitreason" maxlength="400" cols="30" rows="10" style="padding: 20px;"></textarea>
<ul class="odrPopBtn col1">
<li><a href="#" class="bk" onclick="save(-1)">탈퇴하기</a></li>
</ul>*@
<br />
<div class="section-title mpgpop_infotext">
<span class="mpgpop_subtitle"></span>회원탈퇴 시 주의사항
</div>
<ul style="list-style: none; padding: 0; margin: 0;">
<li class="mpgpop_numtext">1. 회원탈퇴 후 교육신청 내역 및 수강 정보, 입금관련 정보 등 모든 내역의 확인이 불가능합니다.</li>
<li class="mpgpop_numtext">2. 회원탈퇴 후 교육을 수료한 경우 수료관련 정보(수료증 발급, 수료확인 등)가 더 이상 홈페이지 상에서 확인이 불가능 합니다.</li>
<li class="mpgpop_numtext">3. 회원탈퇴 후 동영상 시청이 불가능 합니다.</li>
<li class="mpgpop_numtext">4. 회원탈퇴 후 그 외 저희 교육원 홈페이지에서 제공하는 모든 서비스를 이용하실 수 없습니다.</li>
<li class="red-text" style="color: #ef4444; font-weight: bold; margin-bottom: 0.75rem; line-height: 1.6; font-size: 0.95rem;">5. 회원탈퇴 후 회원탈퇴를 다시 취소할 수 없습니다.</li>
</ul>
<br />
<div class="section-title mt-6 mpgpop_infotext">
<span class="mpgpop_subtitle"></span>개인정보 삭제 불가 항목 안내
</div>
<ul style="list-style: none; padding: 0; margin: 0;">
<li class="mpgpop_numtext">회원탈퇴 완료 후에도 <strong style="color: #ef4444;">교육수료정보</strong>는 관련법에 근거하여 삭제가 불가능하오니 꼭 참고하시기 바랍니다.</li>
<li class="mpgpop_numtext">- 개인정보보호법 제36조 1항</li>
<li class="mpgpop_numtext">- 건설기술진흥법 시행령 제117조의2 1항</li>
</ul>
<div class="checkbox-container" style="display: flex; align-items: flex-start; margin-top: 1.5rem; padding: 1rem; border: 1px solid #e5e7eb; border-radius: 0.5rem; background-color: #f9fafb;">
<input type="checkbox" id="agreeLeave" name="agreeLeave" style="margin-top: 0.25rem; margin-right: 0.75rem; min-width: 1.25rem; min-height: 1.25rem;">
<label for="agreeWithdrawal" style="font-size: 0.95rem; color: #333; line-height: 1.5;">본인은 <strong style="color: #ef4444;">상기 주의사항을 확인 및 동의하며</strong> 회원탈퇴를 요청 합니다.</label>
</div>
<div class="odrPopBtn" style="display: flex; justify-content: center; gap: 1rem; margin-top: 2rem;">
<a href="javascript:;" class="blue-btn mpgpop_btn_leave" id="withdrawBtn" onclick="save(-1)">회원탈퇴</a>
<a href="javascript:;" class="gray-btn mpgpop_btn_close" id="cancelBtn" onclick="mpgPopClose();">취소</a>
</div>
</div>
</div>
</div>
@*<!-- // 탈퇴 레이어 팝업 -->*@
@Html.Partial("./Partial/BoxAssign", null, new ViewDataDictionary { { "bindmethod", "bindassign" } })
@section scriptsHeader{
@Html.Partial("./Partial/ScriptPost")
@ -356,11 +464,63 @@
cap("/fcommon/UserPassCheck", "mform", "save2");
}
} else if (idx == 0) {
$('html, body').addClass('lock');
$("#pop1").fadeIn("fast");
//$('html, body').addClass('lock');
//$("#pop1").fadeIn("fast");
leavePopupOpen();
} else if (idx == -1) {
confirmtoggle(true, "탈퇴를 진행하시겠습니까?", "gogo()");
if (!$('#agreeLeave').is(':checked')) {
mpgPopClose();
msg(
'주의사항에 동의 하셔야 탈퇴가 가능합니다.',
10,
false,
'',
'leavePopupOpen()',
0,
false);
}
else {
mpgPopClose();
confirmtoggle(
true,
"탈퇴를 진행하시겠습니까?",
"gogo()",
"",
"100px"
);
}
}
}
function leavePopupOpen() {
$('html, body').addClass('lock'); // 스크롤 잠금
// #pop1 (전체 오버레이) 설정
$("#pop1").css({
"position": "fixed",
"top": "0",
"left": "0",
"width": "100%",
"height": "100%",
"background-color": "rgba(0, 0, 0, 0.5)",
"z-index": "9999",
"display": "block"
}).hide();
$(".mpgPopWrap").css({
"position": "absolute",
"top": "-200px", // 시작 위치: 화면 상단에서 200px 위
"left": "50%", // 가로 중앙으로 정렬
"transform": "translateX(-50%)", // 정확한 가로 중앙 정렬
"opacity": "0" // 초기 투명도 0으로 설정하여 페이드인 효과 준비
});
$("#pop1").fadeIn("fast", function () {
$(".mpgPopWrap").animate({
"top": "10%", // 화면 중앙까지 내려옴
"opacity": "1" // 완전 불투명하게
}, "fast");
});
}
function save2() {
@ -372,16 +532,30 @@
}
}
@*/** 탈퇴진행 */*@
function gogo() {
capp("/fcommon/userexit", { exitreason: val("exitreason") }, "cbexit");
capp(
"/fcommon/userexit",
{ exitreason: val("exitreason") },
"cbexit");
}
@*/** 탈퇴진행 > 콜백 */*@
function cbexit() {
if (capResult.code == 1000) {
msg("탈퇴처리되었습니다.", null, null, null, "location.href='/Account/Logout';");
} else {
msg(
"회원탈퇴가 접수되었습니다.<br/>탈퇴 완료까지 평일 기준 1일 정도 소요될 예정입니다.",
null,
null,
null,
"window.location.href='/Account/Logout';"
);
}
else {
msgadmin();
}
}
function cbsave() {
if (capResult.code == 1000) {
msg("저장되었습니다.");

View File

@ -1142,6 +1142,21 @@ function clearComma() {
var _focusitem;
var _focusitem2;
var _okm;
/**
* 사용자에게 메시지를 표시하고, 특정 동작을 수행하거나 특정 HTML 요소에 초점을 맞추는 범용 메시지 상자 함수입니다.
*
* @param {string} m - **표시할 메시지 내용**입니다. 사용자에게 보여줄 핵심 텍스트입니다.
* @param {number} [t=10] - 메시지 상자가 나타나기 전의 **지연 시간** (밀리초)입니다. 기본값은 `10` 밀리초입니다. 시간 후에 배경 레이어와 메시지 레이어가 표시됩니다.
* @param {boolean} [bging=false] - 메시지 상자 뒤에 **배경 레이어를 표시할지 여부**입니다. `true` 설정하면 배경이 함께 나타납니다. 기본값은 `false`입니다.
* @param {string} [fi=""] - 메시지 확인 **초점을 맞출 HTML 요소의 선택자**입니다.
* - `""` ( 문자열) 경우: 함수 호출 현재 **초점이 맞춰져 있는 입력, 선택 또는 텍스트 영역 요소** 초점을 다시 맞춥니다.
* - `"x"` 경우: **아무 요소에도 초점을 맞추지 않습니다.**
* - 다른 유효한 선택자 (: `"#myInput"`, `".someClass"`): 해당 선택자와 일치하는 요소에 초점을 맞춥니다.
* @param {string} [okm=""] - 메시지 상자의 "확인" 버튼 클릭 **실행할 JavaScript 코드** (문자열)입니다. 문자열은 `eval()` 함수를 통해 실행됩니다. 비어있는 문자열인 경우 `fi` 매개변수에 따라 초점 요소를 처리합니다.
* @param {number} [okmt=0] - `okm` 코드가 있을 경우, 해당 코드를 **자동으로 실행할 지연 시간** (밀리초)입니다. 시간이 지나면 "확인" 버튼을 누르지 않아도 `okm` 코드가 실행됩니다. 기본값은 `0` (즉시 실행)입니다.
* @param {boolean} [hidebtn=false] - "확인" 버튼을 **숨길지 여부**입니다. `true` 설정하면 "확인" 버튼이 표시되지 않습니다. 기본값은 `false`입니다.
*/
function msg(m, t, bging, fi, okm, okmt, hidebtn) {
okmt = okmt || 0;
hidebtn = hidebtn || false;
@ -1181,6 +1196,16 @@ function msg(m, t, bging, fi, okm, okmt, hidebtn) {
msglayer(m, bging);
}, t);
}
/**
* 사용자에게 메시지를 표시하고 확인 특정 HTML 요소에 초점을 다시 맞추는 보조 메시지 상자 함수입니다.
* 'msg' 함수와는 별개의 메시지 레이어(`layermessage2`) 사용합니다.
*
* @param {string} m - **표시할 메시지 내용**입니다. 사용자에게 보여줄 핵심 텍스트입니다.
* @param {number} [t=0] - 메시지 상자가 나타나기 전의 **지연 시간** (밀리초)입니다. 기본값은 `0` 밀리초입니다. 시간 후에 배경 레이어와 메시지 레이어가 표시됩니다.
* @param {string} [fi=""] - 메시지 확인 **초점을 맞출 HTML 요소의 선택자**입니다.
* - `""` ( 문자열) 경우: 함수 호출 현재 **초점이 맞춰져 있는 입력, 선택 또는 텍스트 영역 요소** 초점을 다시 맞춥니다.
* - 다른 유효한 선택자 (: `"#anotherInput"`, `".usernameField"`): 해당 선택자와 일치하는 요소에 초점을 맞춥니다.
*/
function msg2(m, t, fi) {
_focusitem2 = (fi || "") == "" ? $("input:focus, select:focus, textarea:focus") : $(fi);
$("#layermessage2 a.mainokbutton2").on("click", function () {
@ -1369,23 +1394,52 @@ function isRepeatedString(str) {
}
function confirmtoggle(b, m, cb, cbcancel) {
/**
* 확인(Confirm) 상자를 토글(표시/숨김)하고, 사용자의 응답에 따라 특정 콜백 함수를 실행합니다.
* 함수는 일반적으로 사용자에게 확인 메시지를 보여주고 "예" 또는 "아니오" 같은 선택을 요구할 사용됩니다.
*
* @param {boolean} [b=false] - 확인 상자를 **표시할지(`true`) 숨길지(`false`) 여부**입니다. `true` 상자가 나타나고, `false` 상자가 사라집니다. 기본값은 `false`입니다.
* @param {string} m - 확인 상자에 **표시될 메시지 내용**입니다. 사용자에게 보여줄 질문이나 안내 텍스트입니다. (상자가 표시될 때만 유효)
* @param {string} [cb="confirmokpage()"] - 사용자가 확인 상자에서 "확인" 또는 긍정적인 응답을 선택했을 **실행할 JavaScript 코드** (문자열)입니다. 문자열은 `eval()` 함수를 통해 실행됩니다. 기본값은 `"confirmokpage()"`입니다.
* @param {string} [cbcancel=""] - 사용자가 확인 상자에서 "취소" 또는 부정적인 응답을 선택했을 **실행할 JavaScript 코드** (문자열)입니다. 문자열은 `eval()` 함수를 통해 실행됩니다. 기본값은 `""` (아무것도 실행하지 않음)입니다.
* @param {string} [top=""] - 확인 상자의 **수직(`top`) 위치를 지정하는 CSS ** (: `"100px"`, `"20%"`).
* - `""` ( 문자열) 경우: 현재 CSS 또는 기본 위치 설정에 따라 상자가 표시됩니다.
* - 유효한 CSS `top` 값인 경우: 해당 값으로 상자의 `top` 위치가 설정됩니다. 기능을 사용하려면 `#confirmbox` 요소의 CSS `position` 속성이 `absolute` 또는 `fixed` 설정되어 있어야 합니다.
*/
function confirmtoggle(b, m, cb, cbcancel, top) {
b = b || false;
top = top || ''; // top 매개변수 기본값 설정
if (b) {
_confirmokcb = "";
_confirmokcbcancel = "";
_confirmokcb = cb || "confirmokpage()";
_confirmokcbcancel = cbcancel || "";
$("#confirmboxmsg").html(m);
if (top !== '') {
// top 위치 설정 로직 추가
$("#confirmbox").css("top", top);
} else {
// top 값이 비어있을 경우, 이전에 설정된 top 속성을 제거하여
// CSS 파일에 정의된 기본값이나 다른 스크립트에 의해 설정된 값이 적용되도록 할 수 있습니다.
$("#confirmbox").css("top", '');
}
setTimeout(function () {
bglayer(); $("#confirmbox").show();
bglayer();
$("#confirmbox").show();
}, 30);
}
else {
_bging = false;
bglayer(false); $("#confirmbox").hide();
bglayer(false);
$("#confirmbox").hide();
// 숨길 때 top 속성 초기화
$("#confirmbox").css("top", '');
if (_confirmokcbcancel != "") {
if (_confirmokcbcancel.substr(_confirmokcbcancel.length - 1, 1) != ';' &&
_confirmokcbcancel.substr(_confirmokcbcancel.length - 1, 1) != ')' &&
@ -1393,10 +1447,12 @@ function confirmtoggle(b, m, cb, cbcancel) {
_confirmokcbcancel.indexOf(')') < 0) {
_confirmokcbcancel += "()";
}
eval(_confirmokcbcancel);
}
}
}
var _confirmokcb;
var _confirmokcbcancel;
function confirmok() {

View File

@ -151,16 +151,26 @@ namespace NP.Model
/// </summary>
public String introhtml { get; set; }
/// <summary>
/// 상태 1: 활성, 8: 휴면, 9: 비활성(정지, 삭제), 99: 탈퇴
/// 상태 1: 활성, 8: 휴면, 9: 비활성(정지, 삭제), 98:탈퇴신청, 99: 탈퇴
/// </summary>
public int status { get; set; }
public String statusname
/// <summary>상태에 따른 한글명칭</summary>
public string statusname
{
get
{
return status == 1 ? "활성" : status == 8 ? "휴면" : status == 9 ? "비활성" : "탈퇴";
switch (status)
{
case 1: return "활성";
case 8: return "휴면";
case 9: return "비활성";
case 98: return "탈퇴신청";
case 99: return "탈퇴";
default: return "";
}
}
}
/// <summary>
/// 공정거래업무경력
/// </summary>
@ -701,4 +711,36 @@ namespace NP.Model
}
/// <summary>
/// 회원 탈퇴 히스토리
/// </summary>
[Serializable]
public class UserLeave
{
/// <summary>탈퇴 히스토리 고유번호</summary>
public int levno { get; set; }
/// <summary>회원 고유번호 (user 테이블 FK)</summary>
public int userno { get; set; }
/// <summary>회원 아이디</summary>
public string userid { get; set; }
/// <summary>회원 이름</summary>
public string username { get; set; }
/// <summary>처리상태: 0=신청, 1=완료, 2=취소</summary>
public byte status { get; set; }
/// <summary>회원상태 (1:활성, 8:휴면, 9:비활성 ,98:탈퇴신청, 99:탈퇴)</summary>
public int userstatus { get; set; }
/// <summary>탈퇴 처리일시</summary>
public DateTime levdate { get; set; }
/// <summary>탈퇴처리 회원번호</summary>
public long uno { get; set; }
/// <summary>탈퇴 처리 IP</summary>
public string uip { get; set; }
/// <summary>페이지 총 카운트</summary>
public int pagetotalcount { get; set; }
}
}

View File

@ -30,4 +30,19 @@ namespace NP.Model
/// </summary>
public int logincnt { get; set; }
}
/// <summary>
/// 회원 탈퇴 히스토리 VM
/// </summary>
public class VMUsersLeave : VMBase
{
/// <summary>처리상태 (UserLeave.status와 동일) : ""천제 "0"신청, "1"완료, "2"취소</summary>
public string LeaveStatus { get; set; }
/// <summary>회원 탈퇴 히스토리 리스트</summary>
public IList<UserLeave> UserLeaves { get; set; }
}
}