From c48c0a97da2a1c5f687e4981cab5691715fbae49 Mon Sep 17 00:00:00 2001 From: Hyojin Ahn Date: Tue, 5 May 2026 10:22:40 -0400 Subject: [PATCH] =?UTF-8?q?v1.2.11=20-=20[CUSTOMER]=20Install=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD,=20=EC=B2=AD=EC=86=8C=20=EC=A0=84,=20=EC=B2=AD?= =?UTF-8?q?=EC=86=8C=20=ED=9B=84=20=EC=82=AC=EC=A7=84=EB=8F=84=20=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95.=20multi=20ima?= =?UTF-8?q?ge=20=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95.?= =?UTF-8?q?=20-=20[MAP]=20Container=20=EA=B5=90=EC=B2=B4=20=EC=9A=94?= =?UTF-8?q?=EC=B2=AD=20=EC=8B=9C=20=EC=82=AC=EC=A7=84=20multi=20upload=20&?= =?UTF-8?q?=20preview.=20-=20[INSTALL=20WAIT=20LIST]=20Install=20request?= =?UTF-8?q?=20=EC=99=84=EB=A3=8C=20=EC=82=AC=EC=A7=84=20multi=20upload=20&?= =?UTF-8?q?=20preview.=20-=20[INSTALL=20ORDER]=20Install=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C=20=EC=82=AC=EC=A7=84=20multi=20upload=20&=20preview.?= =?UTF-8?q?=20=EC=A1=B0=ED=9A=8C=20=EC=A1=B0=EA=B1=B4=20=EB=B0=94=EB=80=8C?= =?UTF-8?q?=EC=96=B4=EB=8F=84=20View=20Mode=20=EC=9C=A0=EC=A7=80=EB=90=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public_html/assets/api/install.php | 60 ++-- public_html/doc/customer_detail.php | 269 +++++++++--------- public_html/doc/install_order.php | 121 +++++--- public_html/doc/install_wait_list.php | 3 +- public_html/doc/map.php | 40 ++- .../lib/customer_image_upload_popup.php | 45 +-- public_html/lib/user_process.php | 35 +-- 7 files changed, 311 insertions(+), 262 deletions(-) diff --git a/public_html/assets/api/install.php b/public_html/assets/api/install.php index d579391..587c841 100644 --- a/public_html/assets/api/install.php +++ b/public_html/assets/api/install.php @@ -264,11 +264,10 @@ trait InstallAPI { while ($img = mysqli_fetch_assoc($ri)) { - $imgPath = $img['i_filepath'] . $img['i_filename']; - $photos[] = [ - 'i_uid' => (int)$img['i_uid'], - 'imgPath' => $imgPath + 'i_uid' => (int)$img['i_uid'], + 'i_filepath' => $img['i_filepath'], + 'i_filename' => $img['i_filename'] ]; } @@ -1708,20 +1707,19 @@ trait InstallAPI { $fail('select_di', 'daily_install not found'); } - if(!isset($_FILES['photo']) || $_FILES['photo']['error'] !== 0){ - $fail('file', 'no file'); + if(!isset($_FILES['photos'])){ + $fail('file', 'no files'); } - $file = $_FILES['photo']; $customer_uid = intval($di['di_customer_uid']); - $ok = $this->save_customer_image_single( + $ok = $this->save_customer_image_multi( $customer_uid, $member_uid, $i_type, - $di_uid, // i_sourceuid = di_uid + $di_uid, $note, - $file + $_FILES['photos'] ); if(!$ok){ @@ -1732,7 +1730,7 @@ trait InstallAPI { exit; } - private function save_customer_image_single($i_customeruid, $i_memberuid, $i_type, $i_sourceuid, $i_note, $file){ + private function save_customer_image_multi($i_customeruid, $i_memberuid, $i_type, $i_sourceuid, $i_note, $files){ $conn = $GLOBALS['conn']; @@ -1744,36 +1742,48 @@ trait InstallAPI { $i_noteEsc = mysqli_real_escape_string($conn, trim($i_note)); $i_createddate = date("YmdHis"); - // 확장자 체크(최소 보안) $allowed = ['jpg','jpeg','png','webp']; - $ext = strtolower(pathinfo($file['name'] ?? '', PATHINFO_EXTENSION)); - if(!$ext || !in_array($ext, $allowed)){ - return false; - } - // 작업 단위 1장 유지: (customeruid + type, sourceuid 는 제외) + // 기존 row 비활성화 $qry_update = " UPDATE tbl_customer_image SET i_status = 'I' WHERE i_customeruid = '{$i_customeruid}' - AND i_type = '{$i_type}' - AND i_status = 'A' + AND i_type = '{$i_type}' + AND i_status = 'A' "; if(qry($qry_update) === false) return false; - // 저장 폴더 + // 폴더 $upload_folder = getenv("DOCUMENT_ROOT")."/upload/customer_image/".$i_customeruid; if(!is_dir($upload_folder)){ mkdir($upload_folder, 0777, true); } - $newFileName = "IMG_".$i_customeruid."_".time().rand(1000,9999)."_0.jpg"; - $savePath = $upload_folder . "/" . $newFileName; + $savedFiles = []; - if (!$this->compressAndResizeImage($file['tmp_name'], $savePath, $ext, 1200, 75)) { - return false; + foreach ($files['name'] as $i => $name) { + + if ($files['error'][$i] !== 0) continue; + + $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION)); + if(!$ext || !in_array($ext, $allowed)) continue; + + $tmp = $files['tmp_name'][$i]; + + $newFileName = "IMG_".$i_customeruid."_".time().rand(1000,9999)."_".$i.".jpg"; + $savePath = $upload_folder . "/" . $newFileName; + + if (!$this->compressAndResizeImage($tmp, $savePath, $ext, 1200, 75)) { + continue; + } + + $savedFiles[] = $newFileName; } + if(empty($savedFiles)) return false; + + $fileNameString = implode(',', $savedFiles); $dbFilePath = "/upload/customer_image/".$i_customeruid."/"; $sqlIns = " @@ -1794,7 +1804,7 @@ trait InstallAPI { '{$i_memberuid}', '{$i_createddate}', '{$i_type}', - '{$newFileName}', + '{$fileNameString}', '{$dbFilePath}', 'A', '{$i_noteEsc}', diff --git a/public_html/doc/customer_detail.php b/public_html/doc/customer_detail.php index 23dfa8a..a4d83ff 100644 --- a/public_html/doc/customer_detail.php +++ b/public_html/doc/customer_detail.php @@ -2048,137 +2048,116 @@ if( $total_count < 1 ) {

nQuery($qry_img, "image list error"); + // 이미지 가져오기 + $qry_img = " + SELECT * + FROM tbl_customer_image tci + LEFT OUTER JOIN tbl_member tm ON tci.i_createdby = tm.m_uid + WHERE tci.i_customeruid = '$c_uid' + AND tci.i_status = 'A' + ORDER BY tci.i_uid DESC + "; + $rt_img = $jdb->nQuery($qry_img, "image list error"); - // 분류 배열 - $install = []; - $container = []; + function getImageTypeLabel($type) { + switch ($type) { + case 'install': + return 'Install Image'; + case 'install_order': + return 'Container Request Image'; + case 'clean_before': + return 'Before Clean'; + case 'clean_after': + return 'After Clean'; + default: + return ucfirst(str_replace('_', ' ', $type)); + } + } - while ($img = mysqli_fetch_array($rt_img, MYSQLI_ASSOC)) { - if ($img['i_type'] == "install") $install[] = $img; - else $container[] = $img; - } - - if (count($install) + count($container) == 0) { + if (mysqli_num_rows($rt_img) == 0) { echo "

No images found.

"; - } else { + } else { + echo '
'; - // =========================== - // INSTALL - // =========================== - if (count($install) > 0) { - echo "

Install

"; + while ($img = mysqli_fetch_array($rt_img, MYSQLI_ASSOC)) { - foreach ($install as $img) { + echo '
'; - echo '
'; + echo ' + + '; - echo '
'; + // 이미지 영역 (위) + echo '
'; - $files = explode(",", $img['i_filename']); - foreach ($files as $f) { - $imgPath = $img['i_filepath'] . trim($f); - echo ' -
- -
- '; - } + $files = explode(",", $img['i_filename']); + foreach ($files as $f) { + $f = trim($f); + if (!$f) continue; - echo '
'; + $imgPath = $img['i_filepath'] . $f; - echo '
- Note: '.nl2br($img['i_note']).'
'; - echo "Created: " . date("Y-m-d H:i:s", strtotime($img['i_createddate'])).'
'; - echo "Created by: " . $img['m_firstname']. ' ' . $img['m_lastname']. ' (' . $img['m_initial']. ')'; - echo '
'; - } + echo ''; + } + echo '
'; + + // 설명 영역 (아래) + echo '
'; + echo ' +
+ + '.htmlspecialchars(getImageTypeLabel($img['i_type'])).' + +
+ +
Note: '.nl2br(htmlspecialchars($img['i_note'])).'
+
Created: '.date("Y-m-d H:i", strtotime($img['i_createddate'])).'
+
By: ' + . htmlspecialchars($img['m_firstname'] ?? '') + . ' ' + . htmlspecialchars($img['m_lastname'] ?? '') + .'
+ '; + + echo '
'; + + echo '
'; // card end } - // =========================== - // CONTAINER - // =========================== - // if (count($container) > 0) { - // echo "

Container

"; - - // foreach ($container as $img) { - - // echo '
'; - - // echo '
'; - - // $files = explode(",", $img['i_filename']); - // foreach ($files as $f) { - // $imgPath = $img['i_filepath'] . trim($f); - // echo ' - //
- // - //
- // '; - // } - - // echo '
'; - - // echo '
- // Note: '.nl2br($img['i_note']).'
'; - // echo "Created: " . date("Y-m-d H:i:s", strtotime($img['i_createddate'])).'
'; - // echo ' - //
- // '; - - // echo '
'; - // } - // } - } + echo '
'; // wrapper end + } ?> @@ -2211,7 +2190,7 @@ if( $total_count < 1 ) {
- +
@@ -2414,22 +2393,48 @@ document.addEventListener("DOMContentLoaded", function () { // Delete image document.addEventListener("DOMContentLoaded", function () { - const deleteBtn = document.getElementById("btnDeleteImage"); - const confirmModalObj = new bootstrap.Modal(document.getElementById("deleteConfirmModal")); + const modalEl = document.getElementById("deleteConfirmModal"); + if (!modalEl) return; - if (deleteBtn) { - deleteBtn.addEventListener("click", function () { - confirmModalObj.show(); - }); - } + const confirmModalObj = new bootstrap.Modal(modalEl); - document.getElementById("confirmDeleteBtn").addEventListener("click", function () { - const uid = document.getElementById("currentImageUid").value; + // 삭제 버튼 클릭 + document.addEventListener("click", function (e) { + const btn = e.target.closest(".btn-delete-image"); + if (!btn) return; + + const uid = btn.dataset.uid; + if (!uid) return; + + // 현재 선택된 이미지 UID 저장 + const uidInput = document.getElementById("currentImageUid"); + if (uidInput) { + uidInput.value = uid; + } + + confirmModalObj.show(); + }); + + // confirm 버튼 클릭 + const confirmBtn = document.getElementById("confirmDeleteBtn"); + if (confirmBtn) { + confirmBtn.addEventListener("click", function () { + + const uid = document.getElementById("currentImageUid")?.value; if (!uid) return; - document.getElementById("delete_i_uid").value = uid; - document.getElementById("deleteImageForm").submit(); - }); + const formInput = document.getElementById("delete_i_uid"); + if (formInput) { + formInput.value = uid; + } + + const form = document.getElementById("deleteImageForm"); + if (form) { + form.submit(); + } + }); + } + }); function openEditModal(uid, note, customeruid, filesString, filepath, type) { diff --git a/public_html/doc/install_order.php b/public_html/doc/install_order.php index 28fb7e5..256b57c 100644 --- a/public_html/doc/install_order.php +++ b/public_html/doc/install_order.php @@ -2,6 +2,7 @@ $selectedDate = $_GET['date'] ?? date('Y-m-d'); $canViewAllDrivers = ($_SESSION['ss_LEVEL'] <= 5 || $_SESSION['ss_GROUP'] == 1); $selectedDriver = $_GET['driver_uid'] ?? ($canViewAllDrivers ? 0 : $_SESSION['ss_DRUID']); +$view_mode = strtolower($_GET['view_mode'] ?? 'list'); $isAdmin = $canViewAllDrivers; @@ -40,6 +41,7 @@ $sql_order = " SELECT 1 FROM tbl_customer_image ci WHERE ci.i_sourceuid = di.di_uid + and ci.i_type in ('install','clean_before','clean_after') LIMIT 1 ) AS has_image FROM tbl_daily_install di @@ -105,11 +107,10 @@ if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') { // filepath + filename split $files = array_filter(array_map('trim', explode(',', $img['i_filename'] ?? ''))); - $first = $files ? $files[0] : ''; - $imgPath = ''; - if ($first !== '') { - $imgPath = ($img['i_filepath'] ?? '') . $first; + $images = []; + foreach ($files as $f) { + $images[] = ($img['i_filepath'] ?? '') . $f; } echo json_encode([ @@ -120,8 +121,7 @@ if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') { 'i_sourceuid' => $img['i_sourceuid'], 'i_note' => $img['i_note'], 'i_createddate' => $img['i_createddate'], - 'imgPath' => $imgPath, - 'filename' => $first + 'images' => $images // ⭐ 핵심 ] ]); exit; @@ -204,11 +204,11 @@ if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') {
@@ -348,7 +348,7 @@ if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') {
- + @@ -359,7 +359,7 @@ if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') {
- + @@ -380,6 +380,7 @@ if (isset($_GET['ajax']) && $_GET['ajax'] === 'work_images') { +