- URL 하드코딩 → .env APP_URL 기반 동적 URL로 변경 - DB 연결 하드코딩 → .env 기반으로 변경 - MySQL strict mode DATE 오류 수정
1555 lines
54 KiB
PHP
1555 lines
54 KiB
PHP
<?php
|
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/load_GoogleDrive.php'; // 세션 등 여러가지 포함됨 파일 포함
|
|
$titlemsg = '지출결의서';
|
|
|
|
// 법인카드 목록 가져오기
|
|
$jsonFile = $_SERVER['DOCUMENT_ROOT'] . '/account/cardlist.json';
|
|
$cards = [];
|
|
if (file_exists($jsonFile)) {
|
|
$jsonContent = file_get_contents($jsonFile);
|
|
$cards = json_decode($jsonContent, true);
|
|
if (!is_array($cards)) {
|
|
$cards = [];
|
|
}
|
|
}
|
|
?>
|
|
<?php include $_SERVER['DOCUMENT_ROOT'] . '/common.php' ?>
|
|
<?php include $_SERVER['DOCUMENT_ROOT'] . '/load_header.php'; ?>
|
|
<title> <?=$titlemsg?> </title>
|
|
</head>
|
|
<style>
|
|
.show {display:block} /*보여주기*/
|
|
.hide {display:none} /*숨기기*/
|
|
input[type="text"] {
|
|
text-align: left !important ;
|
|
}
|
|
input[type="number"] {
|
|
text-align: left !important ;
|
|
}
|
|
td, th, tr, span, input {
|
|
vertical-align: middle;
|
|
}
|
|
|
|
/* 파일 리스트, 이미지 리스트 공통 컨테이너 */
|
|
.load-container {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
margin: 0 -4px;
|
|
}
|
|
|
|
.load-item {
|
|
position: relative;
|
|
flex: 0 0 auto;
|
|
width: 120px; /* 필요에 따라 조정 */
|
|
height: 120px; /* 필요에 따라 조정 */
|
|
padding: 4px;
|
|
box-sizing: border-box;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
background: #fafafa;
|
|
}
|
|
|
|
/* 이미지 비율에 따라 클래스 부여 */
|
|
.load-item.portrait img {
|
|
width: auto;
|
|
height: 100%;
|
|
}
|
|
.load-item.landscape img {
|
|
width: 100%;
|
|
height: auto;
|
|
}
|
|
|
|
/* 우측 상단 삭제/회전 버튼 */
|
|
.load-item .btn-remove,
|
|
.load-item .btn-rotate {
|
|
position: absolute;
|
|
top: 2px;
|
|
right: 2px;
|
|
padding: 2px 4px;
|
|
font-size: 0.75rem;
|
|
line-height: 1;
|
|
}
|
|
</style>
|
|
<body>
|
|
<?php include $_SERVER['DOCUMENT_ROOT'] . "/common/modal.php"; ?>
|
|
<?php
|
|
$tablename = 'eworks';
|
|
|
|
$mode= $_REQUEST["mode"] ?? '' ;
|
|
$num= $_REQUEST["num"] ?? '' ;
|
|
$author= $user_name ?? '' ;
|
|
// ---------------------------------------------
|
|
// timekey: 임시 저장용 key 생성
|
|
// ---------------------------------------------
|
|
if (empty($_REQUEST['num'])) {
|
|
// 32자리 랜덤 문자열 생성 (PHP 7 이상)
|
|
$timekey = bin2hex(random_bytes(16));
|
|
} else {
|
|
// 이미 생성된 key가 넘어오면 재사용
|
|
$timekey = $_REQUEST['num'];
|
|
}
|
|
|
|
$indate=date("Y-m-d") ?? '' ;
|
|
|
|
if ($mode=="modify" or $mode=="view"){
|
|
try{
|
|
$sql = "select * from {$DB}.eworks where num = ? ";
|
|
$stmh = $pdo->prepare($sql);
|
|
|
|
$stmh->bindValue(1,$num,PDO::PARAM_STR);
|
|
$stmh->execute();
|
|
$count = $stmh->rowCount();
|
|
$row = $stmh->fetch(PDO::FETCH_ASSOC); // $row 배열로 DB 정보를 불러온다.
|
|
if($count<1){
|
|
print "결과가 없습니다.<br>";
|
|
}else{
|
|
include $_SERVER['DOCUMENT_ROOT'] . '/eworks/_row.php';
|
|
// 전자결재의 정보를 다시 변환해 준다.
|
|
$mytitle = $outworkplace ?? '';
|
|
$content = $al_content ?? '';
|
|
$content_reason = $request_comment ?? '';
|
|
|
|
$titlemsg = $mode === 'modify' ? '지출결의서(수정)' : '지출결의서(조회)';
|
|
|
|
}
|
|
}catch (PDOException $Exception) {
|
|
print "오류: ".$Exception->getMessage();
|
|
}
|
|
}
|
|
else{
|
|
// 신규 작성일경우 초기화
|
|
include $_SERVER['DOCUMENT_ROOT'] .'/eworks/_request.php';
|
|
$titlemsg = '지출결의서 작성';
|
|
$mytitle = $outworkplace ?? '';
|
|
$content = $al_content ?? '';
|
|
$content_reason = $request_comment ?? '';
|
|
$al_company = $mycompany ?? ''; // session의 회사명 가져오기
|
|
}
|
|
|
|
|
|
if ($mode!="modify" and $mode!="view" and $mode!="copy"){ // 수정모드가 아닐때 신규 자료일때는 변수 초기화 한다.
|
|
|
|
$indate=date("Y-m-d");
|
|
$paymentdate=date("Y-m-d");
|
|
$requestpaymentdate=date("Y-m-d");
|
|
$author = $user_name;
|
|
$titlemsg = '지출결의서 작성';
|
|
}
|
|
|
|
|
|
if ($mode=="copy"){
|
|
try{
|
|
$sql = "select * from {$DB}.eworks where num = ? ";
|
|
$stmh = $pdo->prepare($sql);
|
|
|
|
$stmh->bindValue(1,$num,PDO::PARAM_STR);
|
|
$stmh->execute();
|
|
$count = $stmh->rowCount();
|
|
$row = $stmh->fetch(PDO::FETCH_ASSOC); // $row 배열로 DB 정보를 불러온다.
|
|
if($count<1){
|
|
print "결과가 없습니다.<br>";
|
|
}else{
|
|
include $_SERVER['DOCUMENT_ROOT'] .'/eworks/_row.php';
|
|
// 전자결재의 정보를 다시 변환해 준다.
|
|
$mytitle = $outworkplace ?? '';
|
|
$content = $al_content ?? '';
|
|
$content_reason = $request_comment ?? '';
|
|
$indate=date("Y-m-d");
|
|
$paymentdate=date("Y-m-d");
|
|
$requestpaymentdate=date("Y-m-d");
|
|
}
|
|
}catch (PDOException $Exception) {
|
|
print "오류: ".$Exception->getMessage();
|
|
}
|
|
|
|
$titlemsg = '(데이터 복사) 지출결의서';
|
|
$num='';
|
|
$id = $num;
|
|
$parentid = $num;
|
|
$author = $user_name;
|
|
$update_log='';
|
|
}
|
|
|
|
// 초기 프로그램은 $num사용 이후 $id로 수정중임
|
|
$id=$num;
|
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/load_GoogleDriveSecond.php'; // attached, image에 대한 정보 불러오기
|
|
?>
|
|
|
|
<form id="board_form" name="board_form" method="post" onkeydown="return captureReturnKey(event)" >
|
|
|
|
<!-- 전달함수 설정 input hidden -->
|
|
<input type="hidden" id="id" name="id" value="<?=$id?>" >
|
|
<input type="hidden" id="num" name="num" value="<?=$num?>" >
|
|
<input type="hidden" id="parentid" name="parentid" value="<?=$parentid?>" >
|
|
<input type="hidden" id="item" name="item" value="<?=$item?>" >
|
|
<input type="hidden" id="tablename" name="tablename" value="<?=$tablename?>" >
|
|
<input type="hidden" id="savetitle" name="savetitle" value="<?=$savetitle?>" >
|
|
<input type="hidden" id="pInput" name="pInput" value="<?=$pInput?>" >
|
|
<input type="hidden" id="mode" name="mode" value="<?=$mode?>" >
|
|
<input type="hidden" id="timekey" name="timekey" value="<?=$timekey?>" > <!-- 신규데이터 작성시 parentid key값으로 사용 -->
|
|
<input type="hidden" id="update_log" name="update_log" value="<?=$update_log?>" >
|
|
<input type="hidden" id="first_writer" name="first_writer" value="<?=$first_writer?>" >
|
|
<input type="hidden" id="e_confirm" name="e_confirm" value="<?=$e_confirm?>" >
|
|
<input type="hidden" id="e_confirm_id" name="e_confirm_id" value="<?=$e_confirm_id?>" >
|
|
<input type="hidden" id="e_line_id" name="e_line_id" value="<?=$e_line_id?>" >
|
|
<input type="hidden" id="status" name="status" value="<?=$status?>" >
|
|
<input type="hidden" id="al_company" name="al_company" value="<?=$al_company?>" >
|
|
<input type="hidden" id="done" name="done" value="<?=$done?>" > <!-- 결재완료 여부 -->
|
|
|
|
<div class="container-fluid" >
|
|
<div class="card">
|
|
<div class="card-body">
|
|
|
|
<div class="row">
|
|
<div class="col-sm-7">
|
|
<div class="d-flex mb-5 mt-5 justify-content-center align-items-center ">
|
|
<h4> <?=$titlemsg?>
|
|
<span data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true"
|
|
title="
|
|
<b>제목:</b> 지출결의할 제목을 작성합니다.
|
|
">
|
|
<i class="bi bi-info-circle-fill"></i>
|
|
</span>
|
|
</h4>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-5">
|
|
<?php
|
|
$approver_ids = explode('!', $e_confirm_id);
|
|
$approver_details = explode('!', $e_confirm);
|
|
|
|
$approvals = array();
|
|
|
|
foreach($approver_ids as $index => $id) {
|
|
if (isset($approver_details[$index])) {
|
|
// Use regex to match the pattern (name title date time)
|
|
// The pattern looks for any character until it hits a series of digits that resemble a date followed by a time
|
|
preg_match("/^(.+ \d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})$/", $approver_details[$index], $matches);
|
|
|
|
// Ensure that the full pattern and the two capturing groups are present
|
|
if (count($matches) === 3) {
|
|
$nameWithTitle = $matches[1]; // This is the name and title
|
|
$time = $matches[2]; // This is the time
|
|
$date = substr($nameWithTitle, -10); // Extract date from the end of the 'nameWithTitle' string
|
|
$nameWithTitle = trim(str_replace($date, '', $nameWithTitle)); // Remove the date from the 'nameWithTitle' to get just the name and title
|
|
$formattedDate = date("m/d H:i:s", strtotime("$date $time")); // Combining date and time
|
|
|
|
$approvals[] = array("name" => $nameWithTitle, "date" => $formattedDate);
|
|
}
|
|
}
|
|
}
|
|
|
|
// // Now $approvals contains the necessary details
|
|
// foreach ($approvals as $approval) {
|
|
// echo "Approver: " . $approval['name'] . ", Date: " . $approval['date'] . "<br>";
|
|
// }
|
|
// }
|
|
|
|
// 금액이 10만원 미만이고 신규작성이 아닐 경우 결재생략 표시
|
|
$suppliercost_numeric = str_replace(',', '', $suppliercost);
|
|
$show_skip_approval = ($mode != '' && $mode != 'copy' && $suppliercost_numeric < 100000);
|
|
|
|
if($status === 'end' and ($e_confirm !=='' && $e_confirm !== null) )
|
|
{
|
|
?>
|
|
|
|
<div class="container mb-2">
|
|
<table class="table table-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th colspan="<?php echo count($approvals); ?>" class="text-center fs-6">결재</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<?php foreach ($approvals as $approval) { ?>
|
|
<td class="text-center fs-6" style="height: 60px;"><?php echo $approval["name"]; ?></td>
|
|
<?php } ?>
|
|
</tr>
|
|
<tr>
|
|
<?php foreach ($approvals as $approval) { ?>
|
|
<td class="text-center"><?php echo $approval["date"]; ?></td>
|
|
<?php } ?>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<? }
|
|
else
|
|
{
|
|
?>
|
|
<div class="container mb-2">
|
|
<table class="table table-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th colspan="<?php echo $show_skip_approval ? 1 : count($approvals); ?>" class="text-center fs-6">
|
|
<?php echo $show_skip_approval ? '결재생략' : '결재 진행 전'; ?>
|
|
</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<?php if ($show_skip_approval) { ?>
|
|
<td class="text-center fs-6" style="height: 60px;">결재생략</td>
|
|
<?php } else { ?>
|
|
<?php foreach ($approvals as $approval) { ?>
|
|
<td class="text-center fs-6" style="height: 60px;"></td>
|
|
<?php } ?>
|
|
<?php } ?>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<? } ?>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<?php if($mode!='view') { ?>
|
|
<div class="row">
|
|
<div class="col-sm-9">
|
|
<div class="d-flex mb-1 justify-content-start align-items-center">
|
|
<button id="saveBtn" type="button" class="btn btn-dark btn-sm me-2" > <i class="bi bi-floppy"></i> 저장(결재상신) </button>
|
|
</div>
|
|
</div>
|
|
<div class="col-sm-3">
|
|
<div class="d-flex mb-1 justify-content-end">
|
|
<button class="btn btn-secondary btn-sm" onclick="self.close();" > <i class="bi bi-x-lg"></i> 창닫기 </button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php } else { ?>
|
|
<div class="row">
|
|
<?php if($chkMobile) { ?>
|
|
<div class="col-sm-12">
|
|
<?php } if(!$chkMobile) { ?>
|
|
<div class="col-sm-7">
|
|
<?php } ?>
|
|
<div class="d-flex justify-content-start">
|
|
<?php if($chkMobile==true) { ?>
|
|
<button class="btn btn-dark btn-sm" onclick="location.href='list.php'" > <i class="bi bi-card-list"></i> 목록 </button>
|
|
<?php } ?>
|
|
<button type="button" class="btn btn-dark btn-sm mx-1" onclick="location.href='write_form.php?mode=modify&num=<?=$num?>'" > <i class="bi bi-pencil-square"></i> 수정 </button>
|
|
<?php if($user_id === $author_id || $admin) { ?>
|
|
<button type="button" class="btn btn-danger btn-sm mx-1"
|
|
onclick="deleteFn()">
|
|
<i class="bi bi-trash"></i> 삭제
|
|
</button>
|
|
<?php } ?>
|
|
<button type="button" class="btn btn-dark btn-sm mx-1" onclick="location.href='write_form.php'" > <i class="bi bi-pencil"></i> 신규 </button>
|
|
<button type="button" class="btn btn-primary btn-sm mx-1" onclick="location.href='write_form.php?mode=copy&num=<?=$num?>'" > <i class="bi bi-copy"></i> 복사 </button>
|
|
</div>
|
|
</div>
|
|
<?php if($chkMobile) { ?>
|
|
<div class="col-sm-12">
|
|
<?php } if(!$chkMobile) { ?>
|
|
<div class="col-sm-5 text-end">
|
|
<?php } ?>
|
|
<div class="d-flex mb-1 justify-content-end">
|
|
<button class="btn btn-secondary btn-sm" type="button" onclick="self.close();" > × 창닫기 </button>
|
|
</div>
|
|
</div>
|
|
</div> <!-- end of row -->
|
|
<?php } // end of elseif ?>
|
|
|
|
<div class="row mt-2">
|
|
<table class="table table-bordered">
|
|
<tr>
|
|
<td class=" text-center w-25 fw-bold">
|
|
<label for="indate">작성일</label>
|
|
</td>
|
|
<td >
|
|
<input type="date" class="form-control w120px viewNoBtn" id="indate" name="indate" value="<?=$indate?>" >
|
|
</td>
|
|
<td class=" text-center w-25 fw-bold">
|
|
<label for="author">기안자</label>
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control text-center w80px viewNoBtn" id="author" name="author" value="<?=$author?>" >
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td class=" text-center w-25 fw-bold">
|
|
<label for="paymentdate">결재일자</label>
|
|
</td>
|
|
<td >
|
|
<input type="date" class="form-control w120px viewNoBtn" id="paymentdate" name="paymentdate" value="<?=$paymentdate?>" >
|
|
</td>
|
|
<td class=" text-center w-25 fw-bold">
|
|
<label for="requestpaymentdate">지출요청일자</label>
|
|
</td>
|
|
<td>
|
|
<input type="date" class="form-control w120px text-center viewNoBtn" id="requestpaymentdate" name="requestpaymentdate" value="<?=$requestpaymentdate?>" >
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<td colspan="4" class="text-center bg-secondary-subtle w-25 fw-bold">
|
|
지출결의서 내역
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
<!-- 지출결의서 내역 테이블 -->
|
|
<div class="row mt-2">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-start mb-2">
|
|
<button type="button" class="btn btn-primary btn-sm viewNoBtn me-2" onclick="addRow()">
|
|
<i class="bi bi-plus-lg"></i> 행 추가
|
|
</button>
|
|
</div>
|
|
<table class="table table-bordered" id="expenseTable">
|
|
<thead>
|
|
<tr>
|
|
<th class="text-center" style="width: 13%">No</th>
|
|
<th class="text-center" style="width: 27%">적요</th>
|
|
<th class="text-center" style="width: 13%">금액</th>
|
|
<th class="text-center" style="width: 37%">비고</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="expenseTableBody">
|
|
<!-- 동적으로 행이 추가될 위치 -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- #region 예상 비용 -->
|
|
<div class="row mt-2 m-5">
|
|
<table class="table table-bordered">
|
|
<tr>
|
|
<td class="text-center w-15 fw-bold">
|
|
<label for="suppliercost">법인카드</label>
|
|
</td>
|
|
<td>
|
|
<div class="d-flex justify-content-start align-items-center ">
|
|
<select class="form-select viewNoBtn text-end me-1" id="companyCard" name="companyCard" style="font-size: 0.9em; height: auto;">
|
|
<option value="">법인카드 선택</option>
|
|
<?php foreach ($cards as $card): ?>
|
|
<option value="<?= htmlspecialchars($card['number'], ENT_QUOTES, 'UTF-8') ?>"
|
|
<?php if(!empty($companyCard) && $companyCard == $card['number']): ?>
|
|
selected
|
|
<?php endif; ?>>
|
|
<?= htmlspecialchars($card['company'] . ' - ' . $card['number'] . ' (' . $card['user'] . ')', ENT_QUOTES, 'UTF-8') ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
</td>
|
|
<td class="text-center w-15 fw-bold">
|
|
<label for="suppliercost">총 비용</label>
|
|
</td>
|
|
<td>
|
|
<div class="d-flex justify-content-start align-items-center ">
|
|
<input type="text" class="form-control w110px viewNoBtn text-end me-1" id="suppliercost" name="suppliercost" placeholder="예상 총 비용" value="<?=$suppliercost?>" style="text-align: right !important;" oninput="formatInput(this)"> 원
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="d-flex mt-3 mb-1 justify-content-center">
|
|
<?php if($mode != 'view') { ?>
|
|
<label for="upfileimage" class="btn btn-outline-dark btn-sm "> 사진 첨부 </label>
|
|
<input id="upfileimage" name="upfileimage[]" type="file" onchange="this.value" multiple accept=".gif, .jpg, .png" style="display:none">
|
|
<?php } ?>
|
|
</div>
|
|
<div class="d-flex mb-1 justify-content-center">
|
|
<div class="d-flex mb-1 justify-content-center fs-6">
|
|
<div id ="displayImage" class="mt-5 mb-5 justify-content-center load-container" style="display:none;">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
|
|
<div class="modal fade" id="loadingImageModal" tabindex="-1" aria-labelledby="loadingImageModalLabel" aria-hidden="true" data-bs-backdrop="static" data-bs-keyboard="false">
|
|
<div class="modal-dialog modal-dialog-centered">
|
|
<div class="modal-content">
|
|
<div class="modal-body text-center">
|
|
<div class="spinner-border text-primary" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p class="mt-3 mb-0">이미지를 불러오고 있습니다. 잠시만 기다려 주세요.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
var ajaxRequest = null;
|
|
|
|
// 페이지 로딩
|
|
$(document).ready(function(){
|
|
var loader = document.getElementById('loadingOverlay');
|
|
if(loader)
|
|
loader.style.display = 'none';
|
|
});
|
|
$(document).ready(function(){
|
|
|
|
$("#saveBtn").click(function(){
|
|
// 조건 확인
|
|
if($("#mytitle").val() === '' || $("#content").val() === '' || $("#content_reason").val() === '' ) {
|
|
showWarningModal();
|
|
} else {
|
|
showMsgModal(2); // 파일저장중
|
|
Toastify({
|
|
text: "변경사항 저장중...",
|
|
duration: 2000,
|
|
close:true,
|
|
gravity:"top",
|
|
position: "center",
|
|
style: {
|
|
background: "linear-gradient(to right, #00b09b, #96c93d)"
|
|
},
|
|
}).showToast();
|
|
setTimeout(function(){
|
|
saveData();
|
|
}, 1000);
|
|
|
|
}
|
|
});
|
|
|
|
function showWarningModal() {
|
|
Swal.fire({
|
|
title: '등록 오류 알림',
|
|
text: '제목, 내용, 사유는 필수입력 요소입니다.',
|
|
icon: 'warning',
|
|
// ... 기타 설정 ...
|
|
}).then(result => {
|
|
if (result.isConfirmed) {
|
|
return; // 사용자가 확인 버튼을 누르면 아무것도 하지 않고 종료
|
|
}
|
|
});
|
|
}
|
|
|
|
function saveData() {
|
|
var num = $("#num").val();
|
|
// 결재상신이 아닌경우 수정안됨
|
|
if(Number(num) < 1 && $("#mode").val() !== 'copy')
|
|
$("#mode").val('insert');
|
|
// 폼데이터 전송시 사용함 Get form
|
|
var form = $('#board_form')[0];
|
|
var datasource = new FormData(form);
|
|
|
|
// 지출결의서 내역 데이터를 JSON으로 처리하는 부분
|
|
let expenseList = [];
|
|
$('#expenseTableBody tr').each(function() {
|
|
let rowData = {};
|
|
$(this).find('input').each(function() {
|
|
let name = $(this).attr('name').replace('[]', '');
|
|
let value = $(this).val();
|
|
// 금액의 경우 콤마 제거
|
|
if (name === 'expense_amount') {
|
|
value = value.replace(/,/g, '');
|
|
}
|
|
rowData[name] = value;
|
|
});
|
|
expenseList.push(rowData);
|
|
});
|
|
|
|
// 데이터를 JSON으로 설정
|
|
datasource.set('expense_data', JSON.stringify(expenseList));
|
|
|
|
if (ajaxRequest !== null) {
|
|
ajaxRequest.abort();
|
|
}
|
|
ajaxRequest = $.ajax({
|
|
enctype: 'multipart/form-data', // file을 서버에 전송하려면 이렇게 해야 함 주의
|
|
processData: false,
|
|
contentType: false,
|
|
cache: false,
|
|
timeout: 600000,
|
|
url: "insert.php",
|
|
type: "post",
|
|
data: datasource,
|
|
dataType: "json",
|
|
success: function(data) {
|
|
if (data.error) {
|
|
Swal.fire({
|
|
title: '오류 발생',
|
|
text: data.message || '데이터 저장 중 오류가 발생했습니다.',
|
|
icon: 'error'
|
|
});
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: '자료등록 완료',
|
|
text: '데이터가 성공적으로 등록되었습니다.',
|
|
icon: 'success'
|
|
});
|
|
|
|
setTimeout(function() {
|
|
if (window.opener && !window.opener.closed) {
|
|
if (typeof window.opener.restorePageNumber === 'function') {
|
|
window.opener.restorePageNumber();
|
|
}
|
|
}
|
|
setTimeout(function() {
|
|
hideMsgModal();
|
|
self.close();
|
|
}, 1000);
|
|
}, 1000);
|
|
},
|
|
error: function(jqxhr, status, error) {
|
|
console.error('Error:', jqxhr, status, error);
|
|
let errorMessage = '데이터 저장 중 오류가 발생했습니다.';
|
|
try {
|
|
const response = JSON.parse(jqxhr.responseText);
|
|
if (response.message) {
|
|
errorMessage = response.message;
|
|
}
|
|
} catch (e) {
|
|
console.error('Error parsing response:', e);
|
|
}
|
|
|
|
Swal.fire({
|
|
title: '오류 발생',
|
|
text: errorMessage,
|
|
icon: 'error'
|
|
});
|
|
}
|
|
});
|
|
} // end of saveData
|
|
|
|
}); // end of document.ready
|
|
|
|
// 기존 deleteFn(...) 함수를 아래로 교체
|
|
function deleteFn() {
|
|
Swal.fire({
|
|
title: '자료 삭제',
|
|
text: "삭제는 신중! 정말 삭제하시겠습니까?",
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#3085d6',
|
|
cancelButtonColor: '#d33',
|
|
confirmButtonText: '삭제',
|
|
cancelButtonText: '취소'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
// soft-delete 모드 세팅
|
|
$("#mode").val('delete');
|
|
|
|
$.ajax({
|
|
url: 'insert.php', // ← delete.php 대신 insert.php
|
|
type: 'POST',
|
|
data: $("#board_form").serialize(),
|
|
dataType: 'json',
|
|
}).done(function(data) {
|
|
Toastify({
|
|
text: "자료 삭제 처리 완료",
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
style: {
|
|
background: "linear-gradient(to right, #00b09b, #96c93d)"
|
|
},
|
|
}).showToast();
|
|
|
|
setTimeout(function() {
|
|
if (window.opener && !window.opener.closed) {
|
|
window.opener.restorePageNumber();
|
|
window.opener.location.reload();
|
|
}
|
|
setTimeout(() => window.close(), 500);
|
|
}, 1000);
|
|
}).fail(function(jqxhr, status, error) {
|
|
console.error("삭제 오류:", status, error);
|
|
Swal.fire('오류', '삭제 처리 중 문제가 발생했습니다.', 'error');
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
function captureReturnKey(e) {
|
|
if(e.keyCode==13 && e.srcElement.type != 'textarea')
|
|
return false;
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
$(document).ready(function () {
|
|
displayImageLoad(); // 기존이미지 업로드 보이기
|
|
|
|
// 첨부파일 업로드 처리
|
|
$("#upfile").change(function (e) {
|
|
if (this.files.length === 0) {
|
|
// 파일이 선택되지 않았을 때
|
|
console.warn("파일이 선택되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
const form = $('#board_form')[0];
|
|
const data = new FormData(form);
|
|
|
|
// 추가 데이터 설정
|
|
data.append("tablename", $("#tablename").val() );
|
|
data.append("item", "attached");
|
|
data.append("upfilename", "upfile"); // upfile 파일 name
|
|
data.append("folderPath", "경동기업/uploads");
|
|
data.append("DBtable", "picuploads");
|
|
|
|
showMsgModal(2); // 파일저장중
|
|
|
|
// AJAX 요청 (Google Drive API)
|
|
$.ajax({
|
|
enctype: 'multipart/form-data',
|
|
processData: false,
|
|
contentType: false,
|
|
cache: false,
|
|
timeout: 600000,
|
|
url: "/filedrive/fileprocess.php",
|
|
type: "POST",
|
|
data: data,
|
|
success: function (response) {
|
|
console.log("응답 데이터:", response);
|
|
|
|
let successCount = 0;
|
|
let errorCount = 0;
|
|
let errorMessages = [];
|
|
|
|
response.forEach((item) => {
|
|
if (item.status === "success") {
|
|
successCount++;
|
|
} else if (item.status === "error") {
|
|
errorCount++;
|
|
errorMessages.push(`파일: ${item.file}, 메시지: ${item.message}`);
|
|
}
|
|
});
|
|
|
|
if (successCount > 0) {
|
|
Toastify({
|
|
text: `${successCount}개의 파일이 성공적으로 업로드되었습니다.`,
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
backgroundColor: "#4fbe87",
|
|
}).showToast();
|
|
}
|
|
|
|
if (errorCount > 0) {
|
|
Toastify({
|
|
text: `오류 발생: ${errorCount}개의 파일 업로드 실패\n상세 오류: ${errorMessages.join("\n")}`,
|
|
duration: 5000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
backgroundColor: "#f44336",
|
|
}).showToast();
|
|
}
|
|
|
|
setTimeout(function () {
|
|
displayFile();
|
|
hideMsgModal();
|
|
}, 1000);
|
|
|
|
},
|
|
error: function (jqxhr, status, error) {
|
|
console.error("업로드 실패:", jqxhr, status, error);
|
|
},
|
|
});
|
|
});
|
|
|
|
// 첨부 이미지 업로드 처리
|
|
$("#upfileimage").change(function (e) {
|
|
if (this.files.length === 0) {
|
|
// 파일이 선택되지 않았을 때
|
|
console.warn("파일이 선택되지 않았습니다.");
|
|
return;
|
|
}
|
|
|
|
const form = $('#board_form')[0];
|
|
const data = new FormData(form);
|
|
|
|
// 추가 데이터 설정
|
|
data.append("tablename", $("#tablename").val() );
|
|
data.append("item", "image");
|
|
data.append("upfilename", "upfileimage"); // upfile 파일 name
|
|
data.append("folderPath", "경동기업/uploads");
|
|
data.append("DBtable", "picuploads");
|
|
|
|
showMsgModal(1); // 이미지저장중
|
|
|
|
// AJAX 요청 (Google Drive API)
|
|
$.ajax({
|
|
enctype: 'multipart/form-data',
|
|
processData: false,
|
|
contentType: false,
|
|
cache: false,
|
|
timeout: 600000,
|
|
url: "/filedrive/fileprocess.php",
|
|
type: "POST",
|
|
data: data,
|
|
success: function (response) {
|
|
console.log("응답 데이터:", response);
|
|
|
|
let successCount = 0;
|
|
let errorCount = 0;
|
|
let errorMessages = [];
|
|
|
|
response.forEach((item) => {
|
|
if (item.status === "success") {
|
|
successCount++;
|
|
} else if (item.status === "error") {
|
|
errorCount++;
|
|
errorMessages.push(`파일: ${item.file}, 메시지: ${item.message}`);
|
|
}
|
|
});
|
|
|
|
if (successCount > 0) {
|
|
Toastify({
|
|
text: `${successCount}개의 파일이 성공적으로 업로드되었습니다.`,
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
backgroundColor: "#4fbe87",
|
|
}).showToast();
|
|
}
|
|
|
|
if (errorCount > 0) {
|
|
Toastify({
|
|
text: `오류 발생: ${errorCount}개의 파일 업로드 실패\n상세 오류: ${errorMessages.join("\n")}`,
|
|
duration: 5000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
backgroundColor: "#f44336",
|
|
}).showToast();
|
|
}
|
|
|
|
setTimeout(function () {
|
|
displayImage();
|
|
hideMsgModal();
|
|
}, 1000);
|
|
|
|
},
|
|
error: function (jqxhr, status, error) {
|
|
console.error("업로드 실패:", jqxhr, status, error);
|
|
},
|
|
});
|
|
});
|
|
|
|
|
|
});
|
|
|
|
// 파일 삭제 처리 함수
|
|
function delFileFn(divID, fileId) {
|
|
Swal.fire({
|
|
title: "파일 삭제 확인",
|
|
text: "정말 삭제하시겠습니까?",
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
confirmButtonText: "삭제",
|
|
cancelButtonText: "취소",
|
|
reverseButtons: true,
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
$.ajax({
|
|
url: '/filedrive/fileprocess.php',
|
|
type: 'DELETE',
|
|
data: JSON.stringify({
|
|
fileId: fileId,
|
|
tablename: $("#tablename").val(),
|
|
item: "attached",
|
|
folderPath: "경동기업/uploads",
|
|
DBtable: "picuploads",
|
|
}),
|
|
contentType: "application/json",
|
|
dataType: 'json',
|
|
}).done(function (response) {
|
|
if (response.status === 'success') {
|
|
console.log("삭제 완료:", response);
|
|
$("#file" + divID).remove();
|
|
$("#delFile" + divID).remove();
|
|
|
|
Swal.fire({
|
|
title: "삭제 완료",
|
|
text: "파일이 성공적으로 삭제되었습니다.",
|
|
icon: "success",
|
|
confirmButtonText: "확인",
|
|
});
|
|
} else {
|
|
console.log(response.message);
|
|
}
|
|
}).fail(function (error) {
|
|
console.error("삭제 중 오류:", error);
|
|
Swal.fire({
|
|
title: "삭제 실패",
|
|
text: "파일 삭제 중 문제가 발생했습니다.",
|
|
icon: "error",
|
|
confirmButtonText: "확인",
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
// 첨부된 이미지 불러오기
|
|
function displayImage() {
|
|
$('#displayImage').show();
|
|
const params = $("#timekey").val() ? $("#timekey").val() : $("#num").val();
|
|
const mode = '<?php echo $mode; ?>';
|
|
|
|
if (!params) {
|
|
console.error("ID 값이 없습니다. 파일을 불러올 수 없습니다.");
|
|
alert("ID 값이 유효하지 않습니다. 다시 시도해주세요.");
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url: '/filedrive/fileprocess.php',
|
|
type: 'GET',
|
|
data: {
|
|
num: params,
|
|
tablename: $("#tablename").val(),
|
|
item: 'image',
|
|
folderPath: '경동기업/uploads',
|
|
},
|
|
dataType: 'json',
|
|
}).done(function (data) {
|
|
$("#displayImage").html('');
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
data.forEach(function (fileData, index) {
|
|
const realName = fileData.realname || '다운로드 파일';
|
|
const thumbnail = fileData.thumbnail || '/assets/default-thumbnail.png';
|
|
const link = fileData.link || '#';
|
|
const fileId = fileData.fileId || null;
|
|
const rotation = fileData.rotation || 0;
|
|
|
|
if (!fileId) {
|
|
console.error("fileId가 누락되었습니다. index: " + index, fileData);
|
|
$("#displayImage").append(
|
|
"<div class='text-danger'>파일 ID가 누락되었습니다.</div>"
|
|
);
|
|
return;
|
|
}
|
|
|
|
let deleteButton = '';
|
|
if (mode !== 'view') {
|
|
deleteButton = `<button type="button" class="btn btn-danger btn-sm" id="delImage${index}" onclick="delImageFn('${index}', '${fileId}')">
|
|
<i class="bi bi-trash"></i>
|
|
</button>`;
|
|
}
|
|
|
|
// 구글 드라이브 이미지 팝업 링크 생성
|
|
$("#displayImage").append(
|
|
"<div class='row mb-3'>" +
|
|
"<div class='col d-flex align-items-center justify-content-center'>" +
|
|
"<div class='position-relative'>" +
|
|
"<a href='#' onclick=\"openTmpImagePopup('" + link + "', 'image" + index + "'); return false;\">" +
|
|
"<img id='image" + index + "' src='" + thumbnail + "' style='width:150px; height:auto; transform: rotate(" + rotation + "deg);'>" +
|
|
"</a>" +
|
|
(mode !== 'view' ?
|
|
"<div class='position-absolute top-0 end-0 mt-1 me-1'>" +
|
|
"<button type='button' class='btn btn-primary btn-sm rotate-btn' onclick=\"rotateImage('" + fileId + "', 'image" + index + "')\">" +
|
|
"<i class='bi bi-arrow-clockwise'></i>" +
|
|
"</button>" +
|
|
"</div>" : "") +
|
|
"</div>" +
|
|
deleteButton +
|
|
"</div>" +
|
|
"</div>"
|
|
);
|
|
});
|
|
} else {
|
|
$("#displayImage").append(
|
|
"<div class='text-center text-muted'>No files</div>"
|
|
);
|
|
}
|
|
}).fail(function (error) {
|
|
console.error("파일 불러오기 오류:", error);
|
|
Swal.fire({
|
|
title: "파일 불러오기 실패",
|
|
text: "파일을 불러오는 중 문제가 발생했습니다.",
|
|
icon: "error",
|
|
confirmButtonText: "확인",
|
|
});
|
|
});
|
|
}
|
|
|
|
// 기존 이미지 불러오기 (Google Drive에서 가져오기)
|
|
function displayImageLoad() {
|
|
$('#displayImage').show();
|
|
var data = <?php echo json_encode($saveimagename_arr); ?>;
|
|
$("#displayImage").html('');
|
|
if (Array.isArray(data) && data.length > 0) {
|
|
data.forEach(function (fileData, i) {
|
|
const realName = fileData.realname || '다운로드 파일';
|
|
const thumbnail = fileData.thumbnail || '/assets/default-thumbnail.png';
|
|
const link = fileData.link || '#';
|
|
const fileId = fileData.fileId || null;
|
|
const rotation = fileData.rotation || 0;
|
|
const mode = '<?php echo $mode; ?>';
|
|
|
|
console.log('link : ',link);
|
|
|
|
if (!fileId) {
|
|
console.error("fileId가 누락되었습니다. index: " + i, fileData);
|
|
return;
|
|
}
|
|
|
|
// 구글 드라이브 이미지 팝업 링크 생성
|
|
let deleteButton = '';
|
|
if (mode !== 'view') {
|
|
deleteButton = `<button type="button" class="btn btn-danger btn-sm mx-3" id="delImage${i}" onclick="delImageFn('${i}', '${fileId}')">
|
|
<i class="bi bi-trash"></i>
|
|
</button>`;
|
|
}
|
|
|
|
$("#displayImage").append(
|
|
"<div class='row mb-3'>" +
|
|
"<div class='col d-flex align-items-center justify-content-center'>" +
|
|
"<div class='position-relative'>" +
|
|
"<a href='#' onclick=\"openTmpImagePopup('" + link + "', 'image" + i + "'); return false;\">" +
|
|
"<img id='image" + i + "' src='" + thumbnail + "' style='width:100px; height:auto; transform: rotate(" + rotation + "deg);'>" +
|
|
"</a>" +
|
|
(mode !== 'view' ?
|
|
"<div class='position-absolute top-0 end-0 mt-1 me-1'>" +
|
|
"<button type='button' class='btn btn-primary btn-sm rotate-btn' onclick=\"rotateImage('" + fileId + "', 'image" + i + "')\">" +
|
|
"<i class='bi bi-arrow-clockwise'></i>" +
|
|
"</button>" +
|
|
"</div>" : "") +
|
|
"</div>" +
|
|
deleteButton +
|
|
"</div>" +
|
|
"</div>"
|
|
);
|
|
});
|
|
} else {
|
|
$("#displayImage").append(
|
|
"<div class='text-center text-muted'>No files</div>"
|
|
);
|
|
}
|
|
}
|
|
|
|
// 이미지 삭제 처리 함수
|
|
function delImageFn(divID, fileId) {
|
|
Swal.fire({
|
|
title: "이미지 삭제 확인",
|
|
text: "정말 삭제하시겠습니까?",
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
confirmButtonText: "삭제",
|
|
cancelButtonText: "취소",
|
|
reverseButtons: true,
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
$.ajax({
|
|
url: '/filedrive/fileprocess.php',
|
|
type: 'DELETE',
|
|
data: JSON.stringify({
|
|
fileId: fileId,
|
|
tablename: $("#tablename").val(),
|
|
item: "image",
|
|
folderPath: "경동기업/uploads",
|
|
DBtable: "picuploads",
|
|
}),
|
|
contentType: "application/json",
|
|
dataType: 'json',
|
|
}).done(function (response) {
|
|
if (response.status === 'success') {
|
|
console.log("삭제 완료:", response);
|
|
// 이미지 컨테이너 전체를 제거 (이미지, 회전 버튼, 삭제 버튼이 모두 포함된 div)
|
|
$("#image" + divID).closest('.row').remove();
|
|
|
|
Swal.fire({
|
|
title: "삭제 완료",
|
|
text: "파일이 성공적으로 삭제되었습니다.",
|
|
icon: "success",
|
|
confirmButtonText: "확인",
|
|
});
|
|
} else {
|
|
console.log(response.message);
|
|
}
|
|
}).fail(function (error) {
|
|
console.error("삭제 중 오류:", error);
|
|
Swal.fire({
|
|
title: "삭제 실패",
|
|
text: "파일 삭제 중 문제가 발생했습니다.",
|
|
icon: "error",
|
|
confirmButtonText: "확인",
|
|
});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// 이미지 회전 함수 추가
|
|
function rotateImage(fileId, imageId) {
|
|
const img = document.getElementById(imageId);
|
|
const currentRotation = parseInt(img.style.transform.replace('rotate(', '').replace('deg)', '')) || 0;
|
|
const newRotation = (currentRotation + 90) % 360;
|
|
img.style.transform = `rotate(${newRotation}deg)`;
|
|
|
|
// 회전 각도를 서버에 저장
|
|
saveRotationAngle(fileId, newRotation);
|
|
}
|
|
|
|
// 회전 각도를 서버에 저장하는 함수
|
|
function saveRotationAngle(fileId, angle) {
|
|
// 로딩 표시
|
|
Toastify({
|
|
text: "회전 상태 저장 중...",
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
style: {
|
|
background: "linear-gradient(to right, #4a90e2, #67b26f)"
|
|
}
|
|
}).showToast();
|
|
|
|
// AJAX 요청 전 데이터 확인
|
|
const requestData = {
|
|
action: 'saveRotation',
|
|
fileId: fileId,
|
|
rotation: angle,
|
|
tablename: $("#tablename").val()
|
|
};
|
|
|
|
console.log('전송 데이터:', JSON.stringify(requestData)); // 디버깅용
|
|
|
|
$.ajax({
|
|
url: '/filedrive/fileprocess.php',
|
|
type: 'POST',
|
|
data: JSON.stringify(requestData),
|
|
contentType: "application/json",
|
|
dataType: 'json',
|
|
success: function(response) {
|
|
console.log('서버 응답:', response); // 디버깅용
|
|
|
|
if (response && response.status === 'success') {
|
|
Toastify({
|
|
text: response.message || "회전 상태가 저장되었습니다",
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
style: {
|
|
background: "linear-gradient(to right, #00b09b, #96c93d)"
|
|
}
|
|
}).showToast();
|
|
} else {
|
|
const errorMessage = response ? response.message : '알 수 없는 오류가 발생했습니다.';
|
|
console.error('회전 각도 저장 실패:', errorMessage);
|
|
Toastify({
|
|
text: errorMessage,
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
style: {
|
|
background: "linear-gradient(to right, #ff5f6d, #ffc371)"
|
|
}
|
|
}).showToast();
|
|
}
|
|
},
|
|
error: function(xhr, status, error) {
|
|
console.error('회전 각도 저장 중 오류:', {
|
|
status: status,
|
|
error: error,
|
|
response: xhr.responseText
|
|
});
|
|
|
|
let errorMessage = "회전 상태 저장 중 오류가 발생했습니다.";
|
|
try {
|
|
if (xhr.responseText) {
|
|
const response = JSON.parse(xhr.responseText);
|
|
if (response && response.message) {
|
|
errorMessage = response.message;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
console.error('응답 파싱 오류:', e);
|
|
}
|
|
|
|
Toastify({
|
|
text: errorMessage,
|
|
duration: 2000,
|
|
close: true,
|
|
gravity: "top",
|
|
position: "center",
|
|
style: {
|
|
background: "linear-gradient(to right, #ff5f6d, #ffc371)"
|
|
}
|
|
}).showToast();
|
|
}
|
|
});
|
|
}
|
|
|
|
function getGoogleDriveFileId(link) {
|
|
// 구글드라이브 파일ID 추출
|
|
var match = link.match(/\/d\/([a-zA-Z0-9_-]+)/);
|
|
return match ? match[1] : '';
|
|
}
|
|
|
|
|
|
// --- 여기부터 수정 및 추가된 함수 ---
|
|
// 로딩 모달을 보여주는 함수 (새로 추가)
|
|
function showImageLoadingModal() {
|
|
$('#loadingImageModal').modal('show');
|
|
}
|
|
|
|
// 로딩 모달을 숨기는 함수 (새로 추가)
|
|
function hideImageLoadingModal() {
|
|
$('#loadingImageModal').modal('hide');
|
|
}
|
|
|
|
|
|
// 이미지 팝업을 여는 함수 (수정됨)
|
|
function openTmpImagePopup(link, imageId) {
|
|
showImageLoadingModal(); // 이미지 클릭 즉시 로딩 모달 표시
|
|
|
|
console.log('link : ',link);
|
|
console.log('imageId : ',imageId);
|
|
|
|
var fileId = getGoogleDriveFileId(link);
|
|
if (!fileId) {
|
|
alert('구글드라이브 파일ID 추출 실패');
|
|
hideImageLoadingModal(); // 오류 발생 시 모달 숨김
|
|
return;
|
|
}
|
|
|
|
const imgElement = document.getElementById(imageId);
|
|
const transformStyle = imgElement.style.transform;
|
|
const currentRotation = transformStyle ? parseInt(transformStyle.replace('rotate(', '').replace('deg)', '')) : 0;
|
|
|
|
$.post('/filedrive/download_and_rotate.php', { fileId: fileId, rotation: currentRotation }, function(res) {
|
|
if (res.success) {
|
|
// 팝업 창 열기. 팝업 창이 로딩 모달을 닫는 역할을 함.
|
|
var popupWindow = popupCenter('/filedrive/view_tmpimg.php?img=' + encodeURIComponent(res.imgUrl) + '&rotation=' + res.rotation, 'imagePopup', 800, 600);
|
|
if (!popupWindow) {
|
|
alert('팝업 창을 여는 데 실패했습니다. 브라우저의 팝업 차단 설정을 확인해주세요.');
|
|
hideImageLoadingModal(); // 팝업 열기 실패 시 모달 숨김
|
|
}
|
|
} else {
|
|
alert(res.msg || '이미지 처리 실패');
|
|
hideImageLoadingModal(); // AJAX 처리 실패 시 모달 숨김
|
|
}
|
|
}, 'json').fail(function() {
|
|
alert('서버와 통신 중 오류가 발생했습니다.');
|
|
hideImageLoadingModal(); // AJAX 통신 자체 실패 시 모달 숨김
|
|
});
|
|
}
|
|
|
|
</script>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const textareas = document.querySelectorAll("textarea.auto-expand");
|
|
|
|
function adjustHeight(el) {
|
|
el.style.height = "auto";
|
|
el.style.height = el.scrollHeight + "px";
|
|
}
|
|
|
|
textareas.forEach(textarea => {
|
|
textarea.addEventListener("input", function() {
|
|
adjustHeight(this);
|
|
});
|
|
adjustHeight(textarea);
|
|
});
|
|
});
|
|
|
|
$(document).ready(function () {
|
|
// 모드가 'view'인 경우 disable 처리 (기존 코드 유지)
|
|
var mode = '<?php echo $mode; ?>';
|
|
if (mode === 'view') {
|
|
disableView();
|
|
}
|
|
|
|
function disableView() {
|
|
$('input, textarea ').prop('readonly', true); // Disable all input, textarea, and select elements
|
|
$('input[type=hidden]').prop('readonly', false);
|
|
|
|
// checkbox와 radio는 클릭 불가능하게 하고 시각적 강조
|
|
$('input[type="checkbox"], input[type="radio"]').each(function() {
|
|
$(this).addClass('readonly-checkbox readonly-radio');
|
|
});
|
|
|
|
// 파일 입력 비활성화
|
|
$('input[type=file]').prop('disabled', true);
|
|
$('.fetch_receiverBtn').prop('disabled', true); // 수신자 버튼 비활성화
|
|
$('.viewNoBtn').prop('disabled', true); //버튼 비활성화
|
|
$('.searchplace').prop('disabled', true); // 수신자 버튼 비활성화
|
|
$('.searchsecondord').prop('disabled', true); // 수신자 버튼 비활성화
|
|
|
|
// 레이블 텍스트 크게 설정
|
|
$('label').css('font-size', '1.2em');
|
|
|
|
// select 속성 readonly 효과 내기
|
|
$('select[data-readonly="true"]').on('mousedown', function(event) {
|
|
event.preventDefault();
|
|
});
|
|
|
|
// checkbox 속성 readonly 효과 내기
|
|
$('input[type="checkbox"][data-readonly="true"]').on('click', function(event) {
|
|
event.preventDefault();
|
|
});
|
|
|
|
}
|
|
});
|
|
|
|
|
|
function formatInput(input) {
|
|
// 숫자와 콤마만 허용
|
|
let value = input.value.replace(/[^\d,]/g, '');
|
|
// 콤마 제거
|
|
value = value.replace(/,/g, '');
|
|
// 숫자가 아닌 문자 제거
|
|
value = value.replace(/[^\d]/g, '');
|
|
// 3자리마다 콤마 추가
|
|
if (value) {
|
|
value = parseInt(value).toLocaleString('ko-KR');
|
|
}
|
|
input.value = value;
|
|
// 금액이 변경될 때마다 총액 계산
|
|
calculateTotal();
|
|
}
|
|
|
|
function calculateTotal() {
|
|
const amounts = document.querySelectorAll('.expense-amount');
|
|
let total = 0;
|
|
|
|
amounts.forEach(input => {
|
|
const value = input.value.replace(/,/g, '');
|
|
total += parseInt(value) || 0;
|
|
});
|
|
|
|
const suppliercostInput = document.getElementById('suppliercost');
|
|
if (suppliercostInput) {
|
|
suppliercostInput.value = total.toLocaleString('ko-KR');
|
|
}
|
|
}
|
|
|
|
// 금액 입력 필드에 이벤트 리스너 추가
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// 기존 금액 입력 필드에 이벤트 리스너 추가
|
|
document.querySelectorAll('.expense-amount').forEach(input => {
|
|
input.addEventListener('input', function() {
|
|
formatInput(this);
|
|
});
|
|
});
|
|
|
|
// 동적으로 추가되는 금액 입력 필드를 위한 이벤트 위임
|
|
document.getElementById('expenseTableBody').addEventListener('input', function(e) {
|
|
if (e.target.classList.contains('expense-amount')) {
|
|
formatInput(e.target);
|
|
}
|
|
});
|
|
});
|
|
|
|
</script>
|
|
|
|
<!-- 부트스트랩 툴팁 -->
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
|
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
return new bootstrap.Tooltip(tooltipTriggerEl);
|
|
});
|
|
// $("#order_form_write").modal("show");
|
|
});
|
|
</script>
|
|
|
|
<script>
|
|
// 지출결의서 내역 관련 함수들
|
|
let rowCount = 0;
|
|
|
|
function addRow(data = null, afterRow = null) {
|
|
const tbody = document.getElementById('expenseTableBody');
|
|
const newRow = document.createElement('tr');
|
|
rowCount++;
|
|
|
|
newRow.innerHTML = `
|
|
<td class="text-center">
|
|
<div class="d-flex align-items-center justify-content-center">
|
|
<span class="me-2">${rowCount}</span>
|
|
<button type="button" class="btn btn-primary btn-sm me-1 viewNoBtn" style="padding:2px;" onclick="addRow(null, this.closest('tr'))">
|
|
<i class="bi bi-plus-lg"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-success btn-sm me-1 viewNoBtn" style="padding:2px;" onclick="copyRow(this)">
|
|
<i class="bi bi-files"></i>
|
|
</button>
|
|
<button type="button" class="btn btn-danger btn-sm viewNoBtn" style="padding:2px;" onclick="deleteRow(this)">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control expense-item" name="expense_item[]" value="${data ? data.item : ''}" placeholder="적요를 입력하세요">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control expense-amount text-end" name="expense_amount[]"
|
|
value="${data ? data.amount : ''}" oninput="formatInput(this)" style="text-align: right !important;" placeholder="금액을 입력하세요">
|
|
</td>
|
|
<td>
|
|
<input type="text" class="form-control expense-note" name="expense_note[]" value="${data ? data.note : ''}" placeholder="비고를 입력하세요">
|
|
</td>
|
|
`;
|
|
|
|
if (afterRow) {
|
|
// 특정 행 다음에 삽입
|
|
afterRow.parentNode.insertBefore(newRow, afterRow.nextSibling);
|
|
} else {
|
|
// 테이블 끝에 추가
|
|
tbody.appendChild(newRow);
|
|
}
|
|
|
|
updateRowNumbers();
|
|
calculateTotal();
|
|
}
|
|
|
|
function deleteRow(button) {
|
|
Swal.fire({
|
|
title: '행 삭제',
|
|
text: '이 행을 삭제하시겠습니까?',
|
|
icon: 'warning',
|
|
showCancelButton: true,
|
|
confirmButtonColor: '#d33',
|
|
cancelButtonColor: '#3085d6',
|
|
confirmButtonText: '삭제',
|
|
cancelButtonText: '취소'
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
const row = button.closest('tr');
|
|
row.remove();
|
|
updateRowNumbers();
|
|
calculateTotal();
|
|
}
|
|
});
|
|
}
|
|
|
|
function copyRow(button) {
|
|
const row = button.closest('tr');
|
|
const data = {
|
|
item: row.querySelector('.expense-item').value,
|
|
amount: row.querySelector('.expense-amount').value,
|
|
note: row.querySelector('.expense-note').value
|
|
};
|
|
addRow(data, row);
|
|
}
|
|
|
|
function updateRowNumbers() {
|
|
const rows = document.querySelectorAll('#expenseTableBody tr');
|
|
rows.forEach((row, index) => {
|
|
const numberSpan = row.querySelector('td:first-child span');
|
|
if (numberSpan) {
|
|
numberSpan.textContent = index + 1;
|
|
}
|
|
});
|
|
rowCount = rows.length;
|
|
}
|
|
|
|
function calculateTotal() {
|
|
const amounts = document.querySelectorAll('.expense-amount');
|
|
let total = 0;
|
|
|
|
amounts.forEach(input => {
|
|
const value = input.value.replace(/,/g, '');
|
|
total += parseInt(value) || 0;
|
|
});
|
|
|
|
document.getElementById('suppliercost').value = total.toLocaleString('ko-KR');
|
|
}
|
|
|
|
// 페이지 로드 시 기존 데이터 불러오기
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
console.log('DOM Content Loaded'); // 디버깅용 로그
|
|
|
|
// 모드가 신규작성인 경우에만 첫 행 추가
|
|
const mode = '<?php echo $mode; ?>';
|
|
if (mode !== 'modify' && mode !== 'view') {
|
|
// 기존 데이터가 없는 경우에만 첫 행 추가
|
|
if ($('#expenseTableBody tr').length === 0) {
|
|
addRow();
|
|
}
|
|
} else {
|
|
loadExpenseData();
|
|
}
|
|
|
|
// 기존 금액 입력 필드에 이벤트 리스너 추가
|
|
document.querySelectorAll('.expense-amount').forEach(input => {
|
|
input.addEventListener('input', function() {
|
|
formatInput(this);
|
|
});
|
|
});
|
|
|
|
// 동적으로 추가되는 금액 입력 필드를 위한 이벤트 위임
|
|
document.getElementById('expenseTableBody').addEventListener('input', function(e) {
|
|
if (e.target.classList.contains('expense-amount')) {
|
|
formatInput(e.target);
|
|
}
|
|
});
|
|
});
|
|
|
|
// 기존 데이터 로드
|
|
function loadExpenseData() {
|
|
let expenseData;
|
|
try {
|
|
// PHP에서 전달된 데이터를 JSON으로 파싱
|
|
const rawData = <?php echo isset($expense_data) ? json_encode($expense_data) : '[]' ?>;
|
|
|
|
// 문자열로 된 JSON인 경우 파싱
|
|
if (typeof rawData === 'string') {
|
|
expenseData = JSON.parse(rawData);
|
|
} else {
|
|
expenseData = rawData;
|
|
}
|
|
|
|
console.log('Loaded expense data:', expenseData); // 디버깅용 로그
|
|
|
|
if (!Array.isArray(expenseData)) {
|
|
console.warn('Expense data is not an array:', expenseData);
|
|
expenseData = [];
|
|
}
|
|
|
|
if (expenseData.length > 0) {
|
|
expenseData.forEach(data => {
|
|
const rowData = {
|
|
item: data.expense_item || '',
|
|
amount: data.expense_amount ? parseInt(data.expense_amount).toLocaleString('ko-KR') : '',
|
|
note: data.expense_note || ''
|
|
};
|
|
console.log('Adding row with data:', rowData); // 디버깅용 로그
|
|
addRow(rowData);
|
|
});
|
|
}
|
|
} catch (e) {
|
|
console.error('Error loading expense data:', e);
|
|
expenseData = [];
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
<script>
|
|
//기존 함수 재선언으로 새롭게 사용함
|
|
function popupCenter(url, title, w, h) {
|
|
// URL에 이미 파라미터가 있는지 확인
|
|
const separator = url.includes('?') ? '&' : '?';
|
|
|
|
var left = (screen.width/2)-(w/2);
|
|
var top = (screen.height/2)-(h/2);
|
|
return window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|