현장 확인 업로드

This commit is contained in:
2026-03-03 21:41:02 +09:00
parent 243ca0c45e
commit f02f8c0457
126 changed files with 2716 additions and 438 deletions

View File

@@ -23,6 +23,8 @@ class Receipt extends BaseController
public function lists(): string
{
error_log('========== Receipt::lists() CALLED ==========');
$usr_id = $this->request->getGet('usr_id') ?: '';
$sBonbu = $this->request->getGet('bonbu') ?: '';
$sTeanm = $this->request->getGet('dept_sq') ?: '';
@@ -54,6 +56,8 @@ class Receipt extends BaseController
public function getResultList()
{
error_log('========== Receipt::getResultList() CALLED ==========');
$start = (int) $this->request->getGet('start') ?: 0;
$end = (int) $this->request->getGet('length') ?: 10;
@@ -92,9 +96,13 @@ class Receipt extends BaseController
'srchTxt' => $this->request->getGet('srchTxt'), // 검색어
];
error_log('[Receipt::getResultList] START - start=' . $start . ' length=' . $end);
$totalCount = $this->model->getTotalCount($data);
error_log('[Receipt::getResultList] TotalCount = ' . $totalCount);
$datas = $this->model->getResultList($start, $end, $data);
error_log('[Receipt::getResultList] END - returned ' . count($datas) . ' rows');
return $this->response->setJSON(body: [
'recordsTotal' => $totalCount,
@@ -717,6 +725,26 @@ class Receipt extends BaseController
$rsrv_sq = $this->request->getPost('rsrv_sq');
$rcpt_sq = $this->request->getPost('rcpt_sq');
$img_type = $this->request->getPost('img_type');
$img_sub_type = $this->request->getPost('img_sub_type');
$file_order = $this->request->getPost('file_order');
log_message('info', '[Receipt::uploadFile] Request received - rcpt_key:{rcpt_key}, rsrv_sq:{rsrv_sq}, rcpt_sq:{rcpt_sq}, img_type:{img_type}, img_sub_type:{img_sub_type}, file_order:{file_order}', [
'rcpt_key' => $rcpt_key,
'rsrv_sq' => $rsrv_sq,
'rcpt_sq' => $rcpt_sq,
'img_type' => $img_type,
'img_sub_type' => $img_sub_type,
'file_order' => $file_order,
]);
// 필수 파라미터 검증
if (empty($rsrv_sq)) {
log_message('error', '[Receipt::uploadFile] rsrv_sq is empty');
return $this->response->setJSON([
'code' => '9',
'msg' => 'rsrv_sq(예약일련번호)가 필요합니다.'
]);
}
$files = $this->request->getFiles();
$uploadPath = "/upload/result/" . $rsrv_sq . "/";
@@ -738,7 +766,7 @@ class Receipt extends BaseController
// 워터마크 이미지 조회
$watermark_info = [];
if (!empty($receipt) && ($receipt['comp_sq'] ?? '') == '2') {
if (!empty($receipt) && !empty($receipt['rcpt_cpid'])) {
$watermark_info = $this->model->getWatermarkList($receipt['rcpt_cpid']);
}
@@ -758,15 +786,20 @@ class Receipt extends BaseController
if ($uploadData !== false) {
$arrUploadfile[] = $uploadData;
log_message('info', '[Receipt::uploadFile] upload success name={name} stored={stored}', [
log_message('info', '[Receipt::uploadFile] upload success name={name} stored={stored} cloud_url={url}', [
'name' => $file->getName(),
'stored' => $uploadData['file_name'] ?? '(unknown)',
'url' => $uploadData['object_storage_url'] ?? '(none)',
]);
} else {
log_message('error', '[Receipt::uploadFile] do_upload2 failed name={name} error={error}:{errorString}', [
log_message('error', '[Receipt::uploadFile] Cloud upload failed name={name}', [
'name' => $file->getName(),
'error' => $file->getError(),
'errorString' => $file->getErrorString(),
]);
// 클라우드 업로드 실패 시 즉시 에러 반환
return $this->response->setJSON([
'code' => '9',
'msg' => '클라우드 스토리지 업로드 실패: ' . $file->getName() . '\n네트워크 연결 또는 권한을 확인해주세요.'
]);
}
@@ -786,25 +819,79 @@ class Receipt extends BaseController
$dir = rtrim(dirname($uploadFile['object_key']), '/'); // upload/result/*
$thumbKey = $dir . '/' . $base . '_thumb.jpg';
$imageDataBlob = file_get_contents($object_storage_url);
$im = new \Imagick();
$im->readImageBlob($imageDataBlob);
$imgWidth = $im->getImageWidth();
$imgHeight = $im->getImageHeight();
$im->thumbnailImage(105, 80, false);
$thumb_im = $im->getImageBlob();
// 썸네일 s3 전송
$lib->upload_object_storage_imagick2($thumbKey, $thumb_im);
$im->destroy();
try {
// 원본 이미지 다운로드 (클라우드에서)
$imageDataBlob = file_get_contents($object_storage_url);
if (!$imageDataBlob) {
throw new \Exception('Failed to download original image from cloud storage');
}
if (class_exists('\Imagick')) {
// Imagick 사용
$im = new \Imagick();
$im->readImageBlob($imageDataBlob);
$imgWidth = $im->getImageWidth();
$imgHeight = $im->getImageHeight();
$im->thumbnailImage(105, 80, false);
$thumb_im = $im->getImageBlob();
$im->destroy();
// 썸네일 클라우드 업로드
$thumbUploaded = $lib->upload_object_storage_imagick2($thumbKey, $thumb_im);
if (!$thumbUploaded) {
log_message('warning', '[Receipt::uploadFile] Thumbnail cloud upload failed: {key}', ['key' => $thumbKey]);
}
} elseif (extension_loaded('gd')) {
// GD 라이브러리 사용
$source = imagecreatefromstring($imageDataBlob);
if ($source !== false) {
$imgWidth = imagesx($source);
$imgHeight = imagesy($source);
// 썸네일 크기 계산 (105x80 비율 유지)
$thumb_width = 105;
$thumb_height = 80;
// 썸네일 이미지 생성
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
imagecopyresampled($thumb, $source, 0, 0, 0, 0, $thumb_width, $thumb_height, $imgWidth, $imgHeight);
// JPEG로 변환
ob_start();
imagejpeg($thumb, null, 85);
$thumb_im = ob_get_clean();
// 메모리 해제
imagedestroy($source);
imagedestroy($thumb);
// 썸네일 클라우드 업로드
$thumbUploaded = $lib->upload_object_storage_imagick2($thumbKey, $thumb_im);
if (!$thumbUploaded) {
log_message('warning', '[Receipt::uploadFile] Thumbnail cloud upload failed: {key}', ['key' => $thumbKey]);
}
log_message('info', '[Receipt::uploadFile] Thumbnail created with GD: {key}', ['key' => $thumbKey]);
} else {
log_message('warning', '[Receipt::uploadFile] GD failed to create image from string');
}
} else {
log_message('warning', '[Receipt::uploadFile] No image library available (Imagick or GD), skipping thumbnail generation');
}
} catch (\Exception $e) {
log_message('error', '[Receipt::uploadFile] Thumbnail generation failed: {message}', [
'message' => $e->getMessage(),
]);
}
}
// 워터마크 삽입
$watermark_imgs = ['I3', 'I4'];
if (in_array($img_type, $watermark_imgs)) {
if (!empty($watermark_info)) {
$common->watermarking($object_storage_url, $watermark_info, '', $receipt['rcpt_cpid'], $uploadFile['object_key']);
}
if (in_array($img_type, $watermark_imgs) && !empty($watermark_info)) {
$common->watermarking($object_storage_url, $watermark_info, '', $receipt['rcpt_cpid'], $uploadFile['object_key']);
}
// 촬영정보 가져오기
@@ -880,19 +967,34 @@ class Receipt extends BaseController
'meta_data' => $metaData, // 이미지메타데이터
'receipt' => $receipt,
'img_type' => $img_type,
'cloud_upload_yn' => 'Y', // 클라우드 업로드 성공 (여기까지 왔으면 성공)
];
$this->model->saveImg($uploadParam);
$img_sq = $this->model->saveImg($uploadParam);
}
}
// 성공 응답 - JavaScript에서 사용할 이미지 정보 포함
$lastUploadedFile = end($arrUploadfile);
return $this->response->setJSON([
'code' => '0',
'msg' => 'success'
'msg' => 'success',
'img_sq' => $img_sq ?? null,
'img_path' => $uploadPath,
'img_filenm' => $lastUploadedFile['file_name'] ?? '',
'cloud_upload_yn' => 'Y',
'img_location' => ''
]);
} catch (\Exception $e) {
log_message('error', '[Receipt::uploadFile] Exception occurred: {message} at {file}:{line}', [
'message' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
'trace' => $e->getTraceAsString(),
]);
return $this->response->setJSON([
'code' => '9',
'msg' => $e->getMessage(),
@@ -988,6 +1090,69 @@ class Receipt extends BaseController
}
}
// 업로드파일 목록 조회 (AJAX용)
public function getImages()
{
try {
$rsrv_sq = $this->request->getGet('rsrv_sq') ?? $this->request->getPost('rsrv_sq');
$img_type = $this->request->getGet('img_type') ?? $this->request->getPost('img_type');
if (empty($rsrv_sq)) {
return $this->response->setJSON([
'success' => false,
'msg' => 'rsrv_sq가 필요합니다.'
]);
}
// 전체 이미지 리스트 조회
$images = $this->model->getImageList2($rsrv_sq);
// img_type이 지정된 경우 필터링
if (!empty($img_type)) {
$images = array_filter($images, function($img) use ($img_type) {
return $img['img_type'] === $img_type;
});
$images = array_values($images); // 인덱스 재정렬
}
// 이미지 URL 생성
foreach ($images as &$img) {
$temp = explode(".", $img['img_filenm']);
$thumbName = $temp[0] . "_thumb.jpg";
$localOriginalPath = $img['img_path'] . $img['img_filenm'];
$localThumbPath = $img['img_path'] . $thumbName;
// 모든 파일은 클라우드에 저장됨
if (($img['cloud_upload_yn'] ?? 'Y') === 'Y') {
$img['original_url'] = NCLOUD_OBJECT_STORAGE_URL . $localOriginalPath;
$img['thumbnail_url'] = NCLOUD_OBJECT_STORAGE_URL . $localThumbPath;
} else {
// 혹시 모를 레거시 로컬 파일 (로컬 파일 시스템 체크)
$localThumbFullPath = FCPATH . $localThumbPath;
if (file_exists($localThumbFullPath)) {
$img['thumbnail_url'] = $localThumbPath;
} else {
$img['thumbnail_url'] = $localOriginalPath;
}
$img['original_url'] = $localOriginalPath;
}
}
return $this->response->setJSON([
'success' => true,
'images' => $images
]);
} catch (\Exception $e) {
log_message('error', '[Receipt::getImages] Error: ' . $e->getMessage());
return $this->response->setJSON([
'success' => false,
'msg' => $e->getMessage()
]);
}
}
// 업로드파일 삭제
public function removeUploadFile()
{
@@ -1016,17 +1181,76 @@ class Receipt extends BaseController
$lib->deleteFile($thumbPath);
}
$this->model->removeUploadFile($rcpt_sq, $img_sq);
$result = $this->model->removeUploadFile($rcpt_sq, $img_sq);
if (!$result['success']) {
return $this->response->setJSON([
'code' => '1',
'msg' => $result['msg'] ?? '삭제 실패'
]);
}
return $this->response->setJSON([
'code' => '0',
'msg' => 'success'
]);
} catch (\Exception $e) {
log_message('error', 'removeUploadFile error: ' . $e->getMessage());
return $this->response->setJSON([
'code' => '1',
'msg' => '삭제 중 에러가 발생했습니다: ' . $e->getMessage()
]);
}
}
// 이미지 순서 업데이트
public function updateImageOrder()
{
try {
$rcpt_sq = $this->request->getPost('rcpt_sq');
$img_type = $this->request->getPost('img_type');
$orders = $this->request->getPost('orders');
log_message('info', '[updateImageOrder] 요청 데이터 - rcpt_sq: ' . $rcpt_sq . ', img_type: ' . $img_type . ', orders: ' . $orders);
if (!$rcpt_sq || !$img_type || !$orders) {
log_message('error', '[updateImageOrder] 필수 파라미터 누락');
return $this->response->setJSON([
'code' => '1',
'msg' => '필수 파라미터가 누락되었습니다.'
]);
}
// JSON 파싱
$orderData = json_decode($orders, true);
if (!is_array($orderData)) {
return $this->response->setJSON([
'code' => '1',
'msg' => '순서 데이터 형식이 올바르지 않습니다.'
]);
}
// 순서 업데이트
$result = $this->model->updateImageOrder($rcpt_sq, $img_type, $orderData);
if (!$result['success']) {
return $this->response->setJSON([
'code' => '1',
'msg' => $result['msg'] ?? '순서 업데이트 실패'
]);
}
return $this->response->setJSON([
'code' => '0',
'msg' => 'success'
'success' => true,
'msg' => '순서가 저장되었습니다.'
]);
} catch (\Exception $e) {
log_message('error', 'updateImageOrder error: ' . $e->getMessage());
return $this->response->setJSON([
'code' => '1',
'msg' => '순서 업데이트 중 에러가 발생했습니다: ' . $e->getMessage()
]);
}
}