[TCO] 직원 근태관리(1)
근태조회
- 출퇴근 체크기능
- 이미 출근/퇴근 시 이미 처리 되었다는 ALERT
- 출근내역없이 퇴근시 출근미처리 ALERT
- 출퇴근 성공시
- 이미 출근/퇴근 시 이미 처리 되었다는 ALERT
- 이번달 근무시간 조회
- 이번달 근무 스케줄 조회 및 연차결재로 이어지는 MODAL설정
- 오늘 날짜에 따라 이번 주 근무 날짜가 추출되도록 하는 쿼리때문에 고생함 (이번주 근무)
- 실시간 서버 시계 출력 및 실시간 출퇴근 시간 출력
코드
- sql mapper.xml
<!-- 현재 로그인한 userId에 해당하는 직원에 이름, 프로필 이미지, 직책 출력용 -->
<select id="binfoselect" parameterType="String" resultType="empVO">
SELECT EMP_NM, EMP_IMG, CMNCD_CD
FROM EMP
WHERE EMP_ID = #{empId}
</select>
<!-- 공통코드로 이루어진 직책을 이름으로 가져옴 -->
<select id="sdselect" parameterType="String" resultType="cmncdVO">
SELECT CMNCD_GU_NM, CMNCD_NM1, CMNCD_NM2
FROM CMNCD
WHERE CMNCD_CD = #{cmncdCd}
</select>
<!-- 출근/퇴근시간 확인용 -->
<!-- 출근 여부 확인용 -->
<select id="checkIselect" parameterType="String" resultType="int">
SELECT COUNT(WORKSTTS_BGNG_TM)
FROM WORKSTTS
WHERE EMP_ID=#{empId}
AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 퇴근 여부 확인용 -->
<select id="checkOselect" parameterType="String" resultType="int">
SELECT COUNT(WORKSTTS_END_TM)
FROM WORKSTTS
WHERE EMP_ID=#{empId}
AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 출근내역 insert -->
<update id="ininsert" parameterType="worksttsVO">
UPDATE WORKSTTS
SET WORKSTTS_BGNG_TM = #{worksttsBgngTm}
WHERE EMP_ID=#{empId}
AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</update>
<!-- 출퇴근시 업무상태 UPDATE -->
<update id="workck" parameterType="worksttsVO">
UPDATE WORKSTTS
SET WORKSTTS_CK = #{worksttsCk}
WHERE EMP_ID=#{empId}
AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</update>
<!-- 퇴근내역 insert -->
<update id="outinsert" parameterType="String">
UPDATE WORKSTTS
SET WORKSTTS_END_TM=TO_CHAR(SYSDATE, 'HH24:MI:SS')
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</update>
<!-- 근무시간 INSERT를 위한 과정-->
<!-- 출퇴근 시간 계산 -->
<select id="enbgselect" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_END_TM, 0, 2),0) - LTRIM(SUBSTR(WORKSTTS_BGNG_TM, 0, 2),0)
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 출퇴근 시간/분과 지정된 근무시간을 체크해서 지각인지 정시퇴근인지 조퇴인지 확인용 -->
<!-- 출근시간 -->
<select id="st" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_BGNG_TM, 0, 2),0)
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 출근시간 분 -->
<select id="stm" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_BGNG_TM, 4, 2),0)
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 퇴근시간 -->
<select id="end" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_END_TM, 0, 2),0)
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 지정 출근시간 -->
<select id="stck" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_SC_TM, 3,2 ),0)
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 지정 퇴근시간 -->
<select id="endck" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_SC_TM, 11,2 ),0)
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 지정 근무시간 계산 -->
<select id="CKenbgselect" resultType="int" parameterType="String">
SELECT LTRIM(SUBSTR(WORKSTTS_SC_TM, 11,2 ),0) - LTRIM(SUBSTR(WORKSTTS_SC_TM, 3,2 ),0) - 1
FROM WORKSTTS
WHERE EMP_ID=#{empId} AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</select>
<!-- 근무시간 UPDATE -->
<update id="enbgupdate" parameterType="worksttsVO">
UPDATE WORKSTTS
SET WORKSTTS_TM=#{worksttsTm}
WHERE EMP_ID=#{empId}
AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</update>
<!-- 근태 상태 UPDATE -->
<update id="cdupdate" parameterType="worksttsVO">
UPDATE WORKSTTS
SET CMNCD_CD=#{cmncdCd}
WHERE EMP_ID=#{empId}
AND TO_CHAR(WORKSTTS_DT, 'YYYY/MM/DD')=TO_CHAR(SYSDATE, 'YYYY/MM/DD')
</update>
<!-- 일주일마다 자동으로 실행될 쿼리= 모든 직원들의 일주일 근태컬럼 생성하는 쿼리 -->
<!-- 임시테이블에 일주일 날짜 INSERT -->
<insert id="teminsert">
INSERT INTO ttable
SELECT to_date(sunday + LEVEL -1, 'yyyymmdd') as dates
FROM ( SELECT TO_CHAR(SYSDATE, 'yyyymmdd')as sunday FROM dual )
CONNECT BY LEVEL <![CDATA[ <= ]]> 5
</insert>
<!-- CROSS 조인값 WORKSTTS에 INSERT -->
<insert id="reinsert">
INSERT INTO WORKSTTS(EMP_ID, WORKSTTS_DT)
SELECT A.EMP_ID, B.WORKSTTS_DT
FROM EMP A, ttable B
</insert>
<!-- 근무시간 update -->
<update id="reupdate">
UPDATE WORKSTTS
SET WORKSTTS_SC_TM = '오전09:00~오후18:00', WORKSTTS_TM = 0, WORKSTTS_CK = '업무전'
WHERE WORKSTTS_SC_TM IS NULL
</update>
<!-- 근태 상세에서 출력하는 이번주 근무시간 -->
<!-- 이번달 근무시간 detail -->
<select id="sumtm2" parameterType="String" resultType="int">
SELECT SUM(WORKSTTS_TM)
FROM WORKSTTS
WHERE TO_CHAR(WORKSTTS_DT, 'MM')=TO_CHAR(SYSDATE, 'MM')
AND EMP_ID = #{empId}
</select>
<모듈 부분 생략(서비스 매퍼 등)>
- Controller
@RequestMapping("/att")
@Controller
public class AttController {
@Autowired
AttService attService;
@Autowired
EmpService empService;
private static final Logger logger =
LoggerFactory.getLogger(AttController.class);
@GetMapping("/attdetail")
public String attdetail(Model model, HttpServletRequest request) {
HttpSession session = request.getSession(false);
// getAttribute의 리턴값은 object
String userId = String.valueOf(session.getAttribute("userID"));
logger.info("userid는:" + userId);
EmpVO empVO = attService.binfoselect(userId);
CmncdVO cmncdVO = attService.sdselect(empVO.getCmncdCd());
empVO.setOpt(cmncdVO.getCmncdGuNm());
empVO.setDptopt(cmncdVO.getCmncdNm1());
empVO.setLelopt(cmncdVO.getCmncdNm2());
WorksttsVO worksttsVO = new WorksttsVO();
String gotime = attService.gotime(userId);
String outtime = attService.outtime(userId);
// 출퇴근 둘다 x
if(gotime==null && outtime==null) {
worksttsVO.setWorksttsBgngTm("미등록");
worksttsVO.setWorksttsEndTm("미등록");
// 출근만했을때
}else if(gotime!=null && outtime==null) {
worksttsVO.setWorksttsBgngTm(gotime);
worksttsVO.setWorksttsEndTm("미등록");
// 출퇴근 둘다o
}else {
worksttsVO.setWorksttsBgngTm(gotime);
worksttsVO.setWorksttsEndTm(outtime);
}
model.addAttribute("empVO", empVO);
// 이번달 근무시간
int sumtm = attService.sumtm2(userId);
worksttsVO.setSumtm(sumtm);
// 출근시간 view에 출력위해 model로 보내준다 ^.^
logger.info("시간아나와라?: "+ worksttsVO.toString());
model.addAttribute("worksttsVO", worksttsVO);
// 이번주 지정근무시간, 근무시간 구하기
List<WorksttsVO> list = attService.thisweek(userId);
logger.info("이번쭈: "+ list);
logger.info("이번쮸" + list.get(0).getWorksttsTm());
model.addAttribute("list", list);
return "att/attdetail";
}
DateTimeFormatter dayf = DateTimeFormatter.ofPattern("yy-MM-dd");
DateTimeFormatter timef = DateTimeFormatter.ofPattern("HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
// 출근
@ResponseBody
@PostMapping("/attin")
public int attin(HttpServletRequest request, Model model) throws ParseException {
HttpSession session = request.getSession(false);
String userId = String.valueOf(session.getAttribute("userID"));
String time = now.format(timef);
logger.info("날것: "+ now);
logger.info("시간: "+time);
int ck =attService.checkIselect(userId);
logger.info("ck"+ ck);
if(ck<=0) {
WorksttsVO worksttsVO = new WorksttsVO();
worksttsVO.setWorksttsBgngTm(time);
worksttsVO.setEmpId(userId);
logger.info("vo: "+ worksttsVO);
int result = attService.ininsert(worksttsVO);
// 업무상태 update
worksttsVO.setWorksttsCk("업무중");
attService.workck(worksttsVO);
// 출근시간
int st = attService.st(userId);
// 출근 분
int stm = attService.stm(userId);
// 지정 출근시간
int stck = attService.stck(userId);
// 상태update
if(st>=stck && stm>0) {
worksttsVO.setCmncdCd("A503");
int cd = attService.cdupdate(worksttsVO);
}else {
worksttsVO.setCmncdCd("A501");
int cd = attService.cdupdate(worksttsVO);
}
logger.info("출근시간왜 안나오냐: "+ worksttsVO.toString());
return result;
}else {
return 0;
}
}
// 퇴근
@ResponseBody
@PostMapping("/attout")
public int attout(HttpServletRequest request, Model model) throws ParseException {
HttpSession session = request.getSession(false);
String userId = String.valueOf(session.getAttribute("userID"));
// 퇴근여부
int ck1 =attService.checkOselect(userId);
// 출근여부
int ck2 = attService.checkIselect(userId);
//퇴근 0 이고 출근 1일때 => 성공
if(ck1<=0 && ck2>0) {
WorksttsVO worksttsVO = new WorksttsVO();
worksttsVO.setEmpId(userId);
logger.info("OUTvo: "+ worksttsVO);
int result = attService.outinsert(userId);
// 업무상태 update
worksttsVO.setWorksttsCk("업무종료");
attService.workck(worksttsVO);
// 근무시간 INSERT
// 지정 근무시간 계산
int enbgck = attService.CKenbgselect(userId);
int result2 ;
worksttsVO.setWorksttsTm(enbgck);
result2 = attService.enbgupdate(worksttsVO);
// 업무상태 UPDATE
// 퇴근시간
int end = attService.end(userId);
// 지정 퇴근시간
int endck = attService.endck(userId);
if(end<=endck) {
worksttsVO.setCmncdCd("A504");
int cd = attService.cdupdate(worksttsVO);
}
// model.addAttribute("worksttsVO", worksttsVO);
// logger.info("퇴근시간왜 안나오냐: "+ worksttsVO.toString());
return result2;
// 퇴근 0이고 출근0일때 => 출근해주슈
}else if(ck1<=0 && ck2<=0) {
return 2;
// 퇴근 1이고 출근1일때=> 이미처리
}else if(ck1>0 && ck2>0) {
return 3;
}else {
return 4;
}
}
@Scheduled(cron = "0 0 6 ? * 3")
public void test() {
// 임시테이블에 오늘부터 5일간 날짜 insert
int teminsert = attService.teminsert();
// 크로스 조인한것 insert
int reinsert = attService.reinsert();
// 지정시간 update
int reupdate = attService.reupdate();
logger.info("teminsert:"+teminsert+"reinsert:"+reinsert);
System.out.println("cron 테스트 : 5초에 1번씩 console 찍기");
}
}
- view
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page import = "java.util.Calendar" %>
<!DOCTYPE html>
<html>
<head>
<%
String Today = new java.text.SimpleDateFormat("yyyy-MM-dd").format(new java.util.Date());
%>
<c:set value="<%=Today%>" var="Today" />
<script src="assets/libs/jquery/jquery.min.js"></script>
<script>
function times() {
var onul = new Date(); /* 로컬컴퓨터에 설정된 표준시간대를 기준으로 한 현재 시간을 추출 */
var dd=["Sun","Mon","Tues","Wednes","Thurs","Fri","Satur"];
var y = onul.getFullYear(); //년
var m2 = onul.getMonth() +1 ; //월
var d2 = onul.getDate(); //일
var d=onul.getDay(); /*현재 '요일'을 숫자로 추출 */
var week = new Array('(일) ', '(월) ', '(화) ', '(수) ', '(목) ', '(금) ', '(토) ');
var d3 = week[d];
var h=onul.getHours(); /*현재 '시'를 숫자로 추출 */
var m=onul.getMinutes(); /*현재 '분'을 숫자로 추출 */
var s=onul.getSeconds(); /*현재 '초'를 숫자로 추출 */
m = dasi(m);
s = dasi(s);
document.getElementById('times').innerHTML = y+"년 " + m2 +"월 "+ d2+"일 "+ d3 +h+":"+m+":"+s;
document.getElementById('timesm').innerHTML = "근태조회 | "+ m2 +"월"
var t = setTimeout(function(){times()},1000); /* 1초마다 갱신(refresh) */
}
/*dasi(분,초)에서 숫자를 가져와서 만약 그 수가 10보다 작다면 앞에 "0"을 추가 함 */
function dasi(i) {
if (i<10) {i = "0" + i};
return i;
}
$(function(){
// 출근 버튼 클릭시
$("#in").on("click", function(){
//수정 전송
$.ajax({
type: "POST",
url : "/att/attin",
contentType : "application/x-www-form-urlencoded; charset=utf-8",
dataType : "json",
success : function(data){
console.log("data뭐노?" + data);
// 성공시 return값 String으로 받아오기 때문에 int로 바꿔주세요옹
var res = parseInt(data);
if(res > 0){
// Sweet Alert
Swal.fire({
icon:'success',
title:'출근완료',
}).then(function(){
window.location.reload();
$('#wcheck').val('wing').prop("selected",true);
})
}else{
// Sweet Alert
Swal.fire({
icon:'warning',
title:'이미 처리됨',
}).then(function(){
window.location.reload();
})
}
},
error : function(){
//Ajax 실패시
Swal.fire({
icon:'error',
title:'에러데스까',
}, function(){
//새로고침
window.location.reload();
});
}
});
});
// 퇴근 버튼 클릭시
$("#out").on("click", function(){
//수정 전송
$.ajax({
type: "POST",
url : "/att/attout",
contentType : "application/x-www-form-urlencoded; charset=utf-8",
dataType : "json",
success : function(data){
console.log("data뭐노?" + data);
// 성공시 return값 String으로 받아오기 때문에 int로 바꿔주세요옹
var res = parseInt(data);
if(res == 1){
// Sweet Alert
Swal.fire({
icon:'success',
title:'퇴근완료',
}).then(function(){
window.location.reload();
$('#wcheck').val('wend').prop("selected",true);
})
}else if(res == 3){
// Sweet Alert
Swal.fire({
icon:'warning',
title:'이미 처리됨',
}).then(function(){
window.location.reload();
})
}else if(res == 2){
// Sweet Alert
Swal.fire({
icon:'error',
title:'출근 미처리됨',
}).then(function(){
window.location.reload();
})
}else{
"에러";
}
},
error : function(){
//Ajax 실패시
Swal.fire({
icon:'error',
title:'에러데스까',
}, function(){
//새로고침
window.location.reload();
});
}
});
});
var currentDay = new Date();
var theYear = currentDay.getFullYear();
var theMonth = currentDay.getMonth();
var theDate = currentDay.getDate();
var theDayOfWeek = currentDay.getDay();
var thisWeek = [];
for(var i=0; i<7; i++) {
var resultDay = new Date(theYear, theMonth, theDate + (i - theDayOfWeek));
// var yyyy = resultDay.getFullYear();
var mm = Number(resultDay.getMonth()) + 1;
var dd = resultDay.getDate();
var ddd = resultDay.getDay();
console.log("theDate: "+ theDate);
mm = String(mm).length === 1 ? '0' + mm : mm;
dd = String(dd).length === 1 ? '0' + dd : dd;
if(ddd==1){
ddd='(월)';
}else if(ddd==2){
ddd='(화)'
}else if(ddd==3){
ddd='(수)'
}else if(ddd==4){
ddd='(목)'
}else if(ddd==5){
ddd='(금)'
}else if(ddd==6){
ddd='(토)'
}else if(ddd==0){
ddd='(일)'
}
thisWeek[i] = mm + '월' + dd+ '일'+ ddd;
}
document.getElementById('week1').innerHTML = thisWeek[1];
var date1 = thisWeek[1].substr(3, 2);
console.log("date1 : "+ date1);
if(theDate == date1){
$('#today1').show();
}else{
$('#today1').hide();
}
document.getElementById('week2').innerHTML = thisWeek[2];
var date2 = thisWeek[2].substr(3, 2);
console.log("date2 : "+ date2);
if(theDate == date2){
$('#today2').show();
}else{
$('#today2').hide();
}
document.getElementById('week3').innerHTML = thisWeek[3];
var date3 = thisWeek[3].substr(3, 2);
console.log("date3 : "+ date3);
if(theDate == date3){
$('#today3').show();
}else{
$('#today3').hide();
}
document.getElementById('week4').innerHTML = thisWeek[4];
var date4 = thisWeek[4].substr(3, 2);
console.log("date4 : "+ date4);
if(theDate == date4){
$('#today4').show();
}else{
$('#today4').hide();
}
document.getElementById('week5').innerHTML = thisWeek[5];
var date5 = thisWeek[5].substr(3, 2);
console.log("date5 : "+ date5);
if(theDate == date5){
$('#today5').show();
}else{
$('#today5').hide();
}
document.getElementById('week6').innerHTML = thisWeek[6];
var date6 = thisWeek[6].substr(3, 2);
console.log("date6 : "+ date6);
if(theDate == date6){
$('#today6').show();
}else{
$('#today6').hide();
}
document.getElementById('week0').innerHTML = thisWeek[0];
var date0 = thisWeek[0].substr(3, 2);
console.log("date0 : "+ date0);
if(theDate == date0){
$('#today0').show();
}else{
$('#today0').hide();
}
console.log(thisWeek[0]);
});
</script>
<style>
.se{
width: 40%;
display: inline-block;
margin-top: 10px;
}
.ib{
}
</style>
</head>
<body onload="times()">
<div class="row">
<div class="col-12">
<div class="page-title-box d-sm-flex align-items-center justify-content-between">
<h4 class="mb-sm-0 font-size-18" id="timesm"></h4>
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="javascript: void(0);">근태</a></li>
<li class="breadcrumb-item active">근태관리</li>
</ol>
</div>
</div>
</div>
</div>
<!-- end page title -->
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-lg-4">
<div class="d-flex">
<div class="flex-shrink-0 me-3">
<img src="${empVO.empImg}" alt="" class="avatar-md rounded-circle img-thumbnail">
</div>
<div class="flex-grow-1 align-self-center">
<div class="text-muted">
<p class="mb-2" id="times"></p>
<h5 class="mb-1">${empVO.empNm} ${empVO.lelopt}</h5>
<p class="mb-0">${empVO.opt} / ${empVO.dptopt}</p>
</div>
</div>
</div>
</div>
<div class="col-lg-4 align-self-center">
<div class="text-lg-center mt-4 mt-lg-0">
<div class="row">
<div class="col-4">
<div>
<p class="text-muted text-truncate mb-2">결재할 문서</p>
<h5 class="mb-0">48</h5>
</div>
</div>
<div class="col-4">
<div>
<p class="text-muted text-truncate mb-2">오늘의 일정</p>
<h5 class="mb-0">40</h5>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-4 d-none d-lg-block">
<div class="clearfix mt-4 mt-lg-0">
</div>
</div>
</div>
<!-- end row -->
</div>
</div>
</div>
</div>
<!-- end row -->
<div class="row">
<div class="col-xl-18">
<div class="row">
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<div class="avatar-xs me-3">
<span class="avatar-title rounded-circle bg-primary bg-soft text-primary font-size-18">
<i class="bx bx-time-five"></i>
</span>
</div>
<h5 class="font-size-16 mb-0">이번달 근무시간</h5>
</div>
<h5 class="font-size-15">${worksttsVO.sumtm}시간<span class="float-end">78%</span></h5>
<div class="progress animated-progess progress-md">
<div class="progress-bar" role="progressbar" style="width: 78%" aria-valuenow="78" aria-valuemin="0" aria-valuemax="100"></div>
</div>
출근시간: ${worksttsVO.worksttsBgngTm}<br>
퇴근시간: ${worksttsVO.worksttsEndTm}
</div>
</div>
</div>
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<div class="avatar-xs me-3">
<span class="avatar-title rounded-circle bg-primary bg-soft text-primary font-size-18">
<i class="bx bx-briefcase-alt"></i>
</span>
</div>
<h5 class="font-size-16 mb-0">근태</h5>
</div>
<button type="button" class="btn btn-light waves-effect" id="in" name="in">출근하기</button>
<button type="button" class="btn btn-light waves-effect" id="out" name="out">퇴근하기</button>
<br>
<div class="input-group input-group-sm">
<select class="form-select form-select-sm" id="wcheck">
<option value="0">_업무상태선택_</option>
<option value="wing">업무중</option>
<option value="wend">업무종료</option>
<option value="NO">휴가</option>
<option value="OC">외근</option>
</select>
<label class="input-group-text">상태</label>
</div>
</div>
</div>
</div>
</div>
<!-- end row -->
</div>
</div>
<div class="row">
<div class="col-xl-12">
<div class="card">
<div class="card-body">
<div class="clearfix">
<div class="card-body">
<div class="d-flex align-items-center mb-3">
<div class="avatar-xs me-3">
<span class="avatar-title rounded-circle bg-primary bg-soft text-primary font-size-18">
<i class="bx bx-task"></i>
</span>
</div>
<h5 class="font-size-16 mb-0">이번 주 근무</h5>
</div>
<div class="mt-4">
<div data-simplebar="init" style="max-height: 400px;"><div class="simplebar-wrapper" style="margin: 0px;"><div class="simplebar-height-auto-observer-wrapper"><div class="simplebar-height-auto-observer"></div></div><div class="simplebar-mask"><div class="simplebar-offset" style="right: -17px; bottom: 0px;"><div class="simplebar-content-wrapper" style="height: auto; overflow: hidden scroll;"><div class="simplebar-content" style="padding: 0px;">
<div class="table-wrapper"><div class="table-responsive fixed-solution" data-pattern="priority-columns">
<div class="sticky-table-header" style="visibility: hidden; width: auto; top: -4.40625px;"><table class="table table-nowrap align-middle table-hover mb-0" id="id3c6e7ddbeb24f-clone">
<tbody>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">Skote Saas Dashboard</a></h5>
<p class="text-muted mb-0">Assigned to Mark</p>
</td>
<td style="width: 90px;" data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck02-clone">
<label class="form-check-label" for="tasklistCheck02"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">New Landing UI</a></h5>
<p class="text-muted mb-0">Assigned to Team A</p>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck02-clone">
<label class="form-check-label" for="tasklistCheck02"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">Brand logo design</a></h5>
<p class="text-muted mb-0">Assigned to Janis</p>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck04-clone">
<label class="form-check-label" for="tasklistCheck04"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">Blog Template UI</a></h5>
<p class="text-muted mb-0">Assigned to Dianna</p>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck05-clone">
<label class="form-check-label" for="tasklistCheck05"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">Multipurpose Landing</a></h5>
<p class="text-muted mb-0">Assigned to Team B</p>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck06-clone">
<label class="form-check-label" for="tasklistCheck06"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">Redesign - Landing page</a></h5>
<p class="text-muted mb-0">Assigned to Jerry</p>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck07-clone">
<label class="form-check-label" for="tasklistCheck07"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-14 mb-1"><a href="javascript: void(0);" class="text-dark">Skote Crypto Dashboard</a></h5>
<p class="text-muted mb-0">Assigned to Eric</p>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<ul class="list-inline mb-0 font-size-16">
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-success p-1"><i class="bx bxs-edit-alt"></i></a>
</li>
<li class="list-inline-item">
<a href="javascript: void(0);" class="text-danger p-1"><i class="bx bxs-trash"></i></a>
</li>
</ul>
</div>
</td>
</tr>
</tbody>
</table></div>
<table class="table table-nowrap align-middle table-hover mb-0" style="height:550px;">
<tbody>
<tr>
<td style="width: 50px;" data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck01">
<label class="form-check-label" for="tasklistCheck01"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined" id="todaysp">
<h5 class="text-truncate font-size-16 mb-1">
<a href="javascript: void(0);" class="text-dark" id="week1"></a>
<span class="badge badge-pill badge-soft-success font-size-12" id="today1">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="d-flex flex-wrap gap-3">
<!-- <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"
data-bs-whatever="@mdo">Open modal for @mdo</button> -->
<a href="#" class="text-dark font-size-16" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">
<span class="badge badge-pill badge-soft-secondary font-size-14">근무</span>
${list.get(0).getWorksttsScTm()}
</a>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
${list.get(0).getWorksttsTm()} 시간
</td>
</tr>
<!-- 여기까지 반복해주세옹 -->
<tr>
<td style="width: 50px;" data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck01">
<label class="form-check-label" for="tasklistCheck01"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-16 mb-1"><a href="javascript: void(0);" class="text-dark" id="week2">
</a> <span class="badge badge-pill badge-soft-success font-size-12" id="today2">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="d-flex flex-wrap gap-3">
<!-- <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"
data-bs-whatever="@mdo">Open modal for @mdo</button> -->
<a href="#" class="text-dark font-size-16" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">
<span class="badge badge-pill badge-soft-secondary font-size-14">근무</span>
${list.get(1).getWorksttsScTm()}
</a>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
${list.get(1).getWorksttsTm()} 시간
</td>
</tr>
<tr>
<td style="width: 50px;" data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck01">
<label class="form-check-label" for="tasklistCheck01"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-16 mb-1"><a href="javascript: void(0);" class="text-dark" id="week3">
</a> <span class="badge badge-pill badge-soft-success font-size-12" id="today3">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="d-flex flex-wrap gap-3">
<!-- <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"
data-bs-whatever="@mdo">Open modal for @mdo</button> -->
<a href="#" class="text-dark font-size-16" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">
<span class="badge badge-pill badge-soft-secondary font-size-14">근무</span>
${list.get(2).getWorksttsScTm()}
</a>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
${list.get(2).getWorksttsTm()} 시간
</td>
</tr>
<tr>
<td style="width: 50px;" data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck01">
<label class="form-check-label" for="tasklistCheck01"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-16 mb-1"><a href="javascript: void(0);" class="text-dark" id="week4">
</a> <span class="badge badge-pill badge-soft-success font-size-12" id="today4">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="d-flex flex-wrap gap-3">
<!-- <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"
data-bs-whatever="@mdo">Open modal for @mdo</button> -->
<a href="#" class="text-dark font-size-16" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">
<span class="badge badge-pill badge-soft-secondary font-size-14">근무</span>
${list.get(3).getWorksttsScTm()}
</a>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
${list.get(3).getWorksttsTm()} 시간
</td>
</tr>
<tr>
<td style="width: 50px;" data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck01">
<label class="form-check-label" for="tasklistCheck01"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-16 mb-1"><a href="javascript: void(0);" class="text-dark" id="week5">
</a> <span class="badge badge-pill badge-soft-success font-size-12" id="today5">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="d-flex flex-wrap gap-3">
<!-- <button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal"
data-bs-whatever="@mdo">Open modal for @mdo</button> -->
<a href="#" class="text-dark font-size-16" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo">
<span class="badge badge-pill badge-soft-secondary font-size-14">근무</span>
${list.get(4).getWorksttsScTm()}
</a>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
${list.get(4).getWorksttsTm()} 시간
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck06">
<label class="form-check-label" for="tasklistCheck06"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-16 mb-1"><a href="javascript: void(0);" class="text-dark" id="week6">
</a> <span class="badge badge-pill badge-soft-success font-size-12" id="today6">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div>
<span class="badge badge-pill badge-soft-success font-size-12">쉬는날</span>
</div>
</td>
</tr>
<tr>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="tasklistCheck07">
<label class="form-check-label" for="tasklistCheck07"></label>
</div>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<h5 class="text-truncate font-size-16 mb-1"><a href="javascript: void(0);" class="text-dark" id="week0">
</a><span class="badge badge-pill badge-soft-success font-size-12" id="today0">오늘</span></h5>
</td>
<td data-org-colspan="1" data-columns="id3c6e7ddbeb24f-col-undefined">
<span class="badge badge-pill badge-soft-success font-size-12">쉬는날</span>
</td>
</tr>
</tbody>
</table>
</div></div>
</div></div></div></div>
<div class="simplebar-placeholder" style="width: auto; height: 800px;"></div>
</div>
<div class="simplebar-track simplebar-horizontal" style="visibility: hidden;">
<div class="simplebar-scrollbar" style="transform: translate3d(0px, 0px, 0px); display: none;"></div></div>
<div class="simplebar-track simplebar-vertical" style="visibility: visible;">
<div class="simplebar-scrollbar" style="height: 20px; transform: translate3d(0px, 134px, 0px); display: block;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Modal 시작 -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" >
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div>
<div class="card-body">
<ul class="nav nav-pills nav-justified" role="tablist">
<li class="nav-item waves-effect waves-light">
<a class="nav-link active" data-bs-toggle="tab" href="#profile-1" role="tab">
<span class="d-block d-sm-none"><i class="far fa-user"></i></span>
<span class="d-none d-sm-block">연차</span>
</a>
</li>
<li class="nav-item waves-effect waves-light">
<a class="nav-link" data-bs-toggle="tab" href="#messages-1" role="tab">
<span class="d-block d-sm-none"><i class="far fa-envelope"></i></span>
<span class="d-none d-sm-block">외근</span>
</a>
</li>
<li class="nav-item waves-effect waves-light">
<a class="nav-link" data-bs-toggle="tab" href="#settings-1" role="tab">
<span class="d-block d-sm-none"><i class="fas fa-cog"></i></span>
<span class="d-none d-sm-block">원격근무</span>
</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content p-3 text-muted">
<div class="tab-pane active" id="profile-1" role="tabpanel">
<i class="bx bx-time-five"></i>
<select class="form-select se">
<option>오전반차</option>
<option>오후반차</option>
<option>연차</option>
</select>
<br>
<i class="bx bx-edit-alt"></i>
<input id="" name="" placeholder="휴가 사유" class="form-control se" type="text" value="">
</div>
<div class="tab-pane" id="messages-1" role="tabpanel">
<i class="bx bx-time-five" ></i>
<select id="" name="" title="" tabindex="-1" aria-hidden="true" data-select2-id="4" class="form-control select2 select2-hidden-accessible se" >
<option value="">오전 9:00</option>
<option value="">오전 9:30</option>
<option value="">오전 10:00</option>
<option value="">오전 10:30</option>
<option value="">오전 11:00</option>
<option value="">오전 11:30</option>
</select>
-
<select id="" name="" title="" tabindex="-1" aria-hidden="true" data-select2-id="4" class="form-control select2 select2-hidden-accessible se" >
<option value="">오후 12:00</option>
<option value="">오후 12:30</option>
<option value="">오후 01:00</option>
<option value="">오후 01:30</option>
<option value="">오후 02:00</option>
<option value="">오후 02:30</option>
<option value="">오후 03:00</option>
<option value="">오후 03:30</option>
<option value="">오후 04:00</option>
<option value="">오후 04:30</option>
<option value="">오후 05:00</option>
<option value="">오후 05:30</option>
<option value="">오후 06:00</option>
<option value="">오후 06:30</option>
<option value="">오후 07:00</option>
<option value="">오후 07:30</option>
<option value="">오후 08:00</option>
<option value="">오후 08:30</option>
<option value="">오후 09:00</option>
<option value="">오후 09:30</option>
<option value="">오후 10:00</option>
<option value="">오후 10:30</option>
</select>
</div>
<div class="tab-pane" id="settings-1" role="tabpanel">
<i class="bx bx-time-five" ></i>
<select id="" name="" title="" tabindex="-1" aria-hidden="true" data-select2-id="4" class="form-control select2 select2-hidden-accessible se" >
<option value="">오전 9:00</option>
<option value="">오전 9:30</option>
<option value="">오전 10:00</option>
<option value="">오전 10:30</option>
<option value="">오전 11:00</option>
<option value="">오전 11:30</option>
</select>
-
<select id="" name="" title="" tabindex="-1" aria-hidden="true" data-select2-id="4" class="form-control select2 select2-hidden-accessible se" >
<option value="">오후 12:00</option>
<option value="">오후 12:30</option>
<option value="">오후 01:00</option>
<option value="">오후 01:30</option>
<option value="">오후 02:00</option>
<option value="">오후 02:30</option>
<option value="">오후 03:00</option>
<option value="">오후 03:30</option>
<option value="">오후 04:00</option>
<option value="">오후 04:30</option>
<option value="">오후 05:00</option>
<option value="">오후 05:30</option>
<option value="">오후 06:00</option>
<option value="">오후 06:30</option>
<option value="">오후 07:00</option>
<option value="">오후 07:30</option>
<option value="">오후 08:00</option>
<option value="">오후 08:30</option>
<option value="">오후 09:00</option>
<option value="">오후 09:30</option>
<option value="">오후 10:00</option>
<option value="">오후 10:30</option>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">닫기</button>
<button type="button" class="btn btn-primary">근무 등록하기</button>
</div>
</div>
</div>
</div>
<!-- Modal 끝 -->
</body>
</html>
![](https://imagedelivery.net/v7-TZByhOiJbNM9RaUdzSA/670b803a-7d97-46a6-936b-46b72b686b00/public)
![](https://imagedelivery.net/v7-TZByhOiJbNM9RaUdzSA/4dd67d25-a946-41c9-2894-ea33b9ffdd00/public)
Author And Source
이 문제에 관하여([TCO] 직원 근태관리(1)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@vgo_dongv/TCO-직원-근태관리1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)