diff --git a/app/Config/Routes.php b/app/Config/Routes.php index f969561..44a3634 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -73,11 +73,15 @@ $routes->group('article', ['namespace' => 'App\Controllers\Article'], function ( $routes->post('apt/savePhoReason', 'Apt::savePhoReason'); $routes->post('apt/saveCate', 'Apt::saveCate'); $routes->post('apt/savePhotoView', 'Apt::savePhotoView'); - $routes->post('apt/savePhotoView', 'Apt::savePhotoView'); + $routes->post('apt/removePhoto', 'Apt::removePhoto'); $routes->post('apt/confirmAptInfo', 'Apt::confirmAptInfo'); $routes->post('apt/resendAptInfo', 'Apt::resendAptInfo'); + $routes->post('apt/savePhoExplain', 'Apt::savePhoExplain'); + $routes->post('apt/saveWriteComplete', 'Apt::saveWriteComplete'); $routes->post('apt/uploadFile', 'Apt::uploadFile'); + $routes->post('apt/savePhoCate', 'Apt::savePhoCate'); + $routes->post('apt/reqRemovePho', 'Apt::reqRemovePho'); }); diff --git a/app/Controllers/Article/Apt.php b/app/Controllers/Article/Apt.php index e431459..65ca672 100644 --- a/app/Controllers/Article/Apt.php +++ b/app/Controllers/Article/Apt.php @@ -6,7 +6,6 @@ use App\Controllers\BaseController; use App\Libraries\MyUpload; use App\Models\article\AptModel; use App\Models\common\CodeModel; -use MY_Upload; class Apt extends BaseController { @@ -673,6 +672,34 @@ class Apt extends BaseController } } + // 단지정보 작성완료 + public function saveWriteComplete() + { + try { + + $rcpt_no = $this->request->getPost('rcpt_no'); + if (empty($rcpt_no)) { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => '정보누락' + ]); + } + + $this->aptModel->saveWriteComplete($rcpt_no); + + return $this->response->setJSON([ + 'code' => '0', + 'msg' => 'success' + ]); + + } catch (\Exception $e) { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => $e->getMessage(), + ]); + } + } + // 검수완료 저장 public function confirmAptInfo() { @@ -868,11 +895,7 @@ class Apt extends BaseController $rcpt_no = $this->request->getPost('rcpt_no'); $uploadType = $this->request->getPost('upload_type'); $files = $this->request->getFiles(); - $imgPath = "/upload/apt_file/" . $rcpt_no . "/"; - - $imgPath = NCLOUD_OBJECT_STORAGE_URL . $imgPath; - $moviePath = $imgPath; - $photo360Path = $imgPath; + $uploadPath = "/upload/apt_file/" . $rcpt_no . "/"; if (!isset($files['files'])) { return $this->response->setJSON([ @@ -881,36 +904,267 @@ class Apt extends BaseController ]); } - if ($uploadType === "photo") { + $arrUploadfile = []; + foreach ($files['files'] as $file) { - // foreach ($files['files'] as $file) { - // if ($file->isValid()) { - // $file->move(WRITEPATH . 'uploads'); + $uploadData = $lib->do_upload2($file, $uploadPath); - // INSERT apt_photo + if ($uploadData !== false) { + $arrUploadfile[] = $uploadData; + } - print_r($_FILES); - // } + } + + $gps_lat = null; + $gps_lon = null; + $camDate = null; + if (!empty($arrUploadfile)) { + foreach ($arrUploadfile as $key => $uploadFile) { + $object_storage_url = $uploadFile['object_storage_url']; + $arrExifData = @exif_read_data($object_storage_url); + if (!empty($arrExifData)) { + $notFound = "Unavailable"; + if (@array_key_exists('DateTime', $arrExifData)) { + $camDate = $arrExifData['DateTime']; + } else { + $camDate = $notFound; + } + + $imageMetaData = $camDate; + $camDate = substr(str_replace(':', '-', $camDate), 0, 10); - // $imageDataBlob = file_get_contents($object_storage_url); - // $im = new Imagick(); - // $im->readImageBlob($imageDataBlob); - // $im->thumbnailImage(105, 80, false); - // $thumb_im = $im->getImageBlob(); - // $lib->upload_object_storage_imagick(); + $arrGPS = $arrExifData['GPS'] ?? null; - // } + if (empty($arrGPS)) { // GPS 섹션이 없으면, 개별 키로도 체크 + if (!empty($arrExifData['GPSLongitude']) && !empty($arrExifData['GPSLatitude'])) { + $arrGPS = [ + 'GPSLongitude' => $arrExifData['GPSLongitude'], + 'GPSLatitude' => $arrExifData['GPSLatitude'], + ]; + } + } + if ( + !empty($arrGPS) + && !empty($arrGPS['GPSLongitude']) + && !empty($arrGPS['GPSLatitude']) + && is_array($arrGPS['GPSLongitude']) + && is_array($arrGPS['GPSLatitude']) + ) { //GPS 정보가 있다면 + if (@array_key_exists('GPSLongitude', $arrGPS) && (@array_key_exists('GPSLatitude', $arrGPS))) { + list($temp_d1, $temp_d2) = sscanf($arrGPS["GPSLatitude"][0], "%d/%d"); //문자->숫자로 계산 + $gps_lat_d = $temp_d1 / $temp_d2; + list($temp_d1, $temp_d2) = sscanf($arrGPS["GPSLatitude"][1], "%d/%d"); + $gps_lat_m = $temp_d1 / $temp_d2; + list($temp_d1, $temp_d2) = sscanf($arrGPS["GPSLatitude"][2], "%d/%d"); + $gps_lat_s = $temp_d1 / $temp_d2; + + list($temp_d1, $temp_d2) = sscanf($arrGPS["GPSLongitude"][0], "%d/%d"); //문자->숫자로 계산 + $gps_lon_d = $temp_d1 / $temp_d2; + list($temp_d1, $temp_d2) = sscanf($arrGPS["GPSLongitude"][1], "%d/%d"); + $gps_lon_m = $temp_d1 / $temp_d2; + list($temp_d1, $temp_d2) = sscanf($arrGPS["GPSLongitude"][2], "%d/%d"); + $gps_lon_s = $temp_d1 / $temp_d2; + + $gps_lat = $gps_lat_d + $gps_lat_m / 60 + $gps_lat_s / 3600; //도분초를 도로 변환 + $gps_lon = $gps_lon_d + $gps_lon_m / 60 + $gps_lon_s / 3600; + } + } else { + $xy = $this->aptModel->getDetail($rcpt_no); + + $gps_lat = $xy['rcpt_y']; + $gps_lon = $xy['rcpt_x']; + } + + + } + + $base = $uploadFile['base_name']; // xxxx + $dir = rtrim(dirname($uploadFile['object_key']), '/'); // upload/apt_file/2 + $thumbKey = $dir . '/' . $base . '_thumb.jpg'; + + $imageDataBlob = file_get_contents($object_storage_url); + $im = new \Imagick(); + $im->readImageBlob($imageDataBlob); + $im->thumbnailImage(105, 80, false); + $thumb_im = $im->getImageBlob(); + // 썸네일 s3 전송 + $lib->upload_object_storage_imagick2($thumbKey, $thumb_im); + + + /** + * 파일업로드 내용 저장 + * rcpt_no, pho_lati, pho_long, filenm, filenm_up, file_path, thumb_path, thumb_nm, cloud_upload_yn + * + */ + $uploadParam = [ + 'rcpt_no' => $rcpt_no, // 접수번호 + 'gps_lat' => $gps_lat, // latitude + 'gps_lon' => $gps_lon, // longitude + 'origin_name' => $uploadFile['origin_name'], // 원본파일명 + 'file_name' => $uploadFile['file_name'], // 저장파일명 + 'upload_path' => $uploadPath, // 저장경로 + 'thumb_name' => $base . '_thumb.jpg', + 'cam_date' => $camDate, // 촬영일 + ]; + + $res = $this->aptModel->saveImg($uploadParam); + log_message('debug', 'apt_file :: rcpt_no : ' . $rcpt_no . ', fileName : ' . $uploadFile['file_name']); + + } + } } else if ($uploadType === "video") { + + $arrUploadfile = []; + foreach ($files['files'] as $file) { + + $uploadData = $lib->do_upload2($file, $uploadPath); + + if ($uploadData !== false) { + $arrUploadfile[] = $uploadData; + } + + } + + // print_r($arrUploadfile); + // exit; + + if (!empty($arrUploadfile)) { + foreach ($arrUploadfile as $key => $uploadFile) { + $uploadParam = [ + 'rcpt_no' => $rcpt_no, // 접수번호 + 'origin_name' => $uploadFile['origin_name'], // 원본파일명 + 'file_name' => $uploadFile['file_name'], // 저장파일명 + 'upload_path' => $uploadPath, // 저장경로 + // 'thumb_name' => $base . '_thumb.jpg', + // 'cam_date' => $camDate, // 촬영일 + ]; + + + // 동영상 정보 저장 + $this->aptModel->saveVideo($uploadParam); + + } + } + + } + return $this->response->setJSON([ + 'code' => '0', + 'msg' => 'success' + ]); + + + } catch (\Exception $e) { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => $e->getMessage(), + ]); + } + } + + // 업로드파일삭제 + public function reqRemovePho() + { + try { + + $type = $this->request->getPost('type'); + + + if ($type === "all") { + $rcpt_no = $this->request->getPost('rcpt_no'); + + // 사진 일괄 삭제 + $this->aptModel->removeAllPho($rcpt_no); + + + } else if ($type === "select") { + $phoNo = $this->request->getPost('phoNo'); // ✅ 배열로 들어옴 + + if (!is_array($phoNo)) + $phoNo = [$phoNo]; + + if (empty($phoNo)) { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => '데이터 누락' + ]); + } + + // 선택 사진 삭제 + $this->aptModel->removePho($phoNo); + + + } else { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => '잘못된 접근' + ]); + } + + + return $this->response->setJSON([ + 'code' => '0', + 'msg' => 'success' + ]); + + + } catch (\Exception $e) { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => $e->getMessage(), + ]); + } + } + + + // 업로드 파일 카테고리 지정 + public function savePhoCate() + { + try { + + $rcpt_no = $this->request->getPost('rcpt_no'); + $code1 = $this->request->getPost('code1'); + $code2 = $this->request->getPost('code2'); + $phoNo = $this->request->getPost('phoNo'); + + if (!is_array($phoNo)) + $phoNo = [$phoNo]; + + if (empty($phoNo)) { + return $this->response->setJSON([ + 'code' => '9', + 'msg' => '데이터 누락' + ]); + } + + foreach ($phoNo as $pho) { + + $data = [ + 'rcpt_no' => $rcpt_no, + 'pho_no' => $pho, + 'code1' => $code1, + 'code2' => $code2, + ]; + + // 카테고리 지정 + $this->aptModel->updatePhoCate($data); + + } + + return $this->response->setJSON([ + 'code' => '0', + 'msg' => 'success' + ]); + } catch (\Exception $e) { return $this->response->setJSON([ diff --git a/app/Libraries/MyUpload.php b/app/Libraries/MyUpload.php index 27d33ed..5615b93 100644 --- a/app/Libraries/MyUpload.php +++ b/app/Libraries/MyUpload.php @@ -3,6 +3,10 @@ namespace App\Libraries; use Aws\S3\S3Client; +use Aws\Exception\AwsException; +use Aws\Credentials\CredentialProvider; +use Aws\Credentials\Credentials; +use CodeIgniter\HTTP\Files\UploadedFile; class MyUpload { @@ -49,12 +53,76 @@ class MyUpload return $this; } - // CI3 스타일: do_upload() + /** + * 파일 업로드 요청 + * 추가일 2025.12.24 + * 작성자 - yangsh + */ + public function do_upload2(UploadedFile $file, $filePath = null): array|false + { + if (!$file->isValid()) { + $this->set_error('upload_invalid_file'); + return false; + } + + // 업로드 전인데 hasMoved()가 true면 비정상 상태 + if ($file->hasMoved()) { + $this->set_error('upload_file_already_moved'); + return false; + } + + $newName = $file->getRandomName(); + + // ✅ PHP 임시 업로드 파일 경로 (writable로 move() 필요 없음) + $tmpFile = $file->getTempName(); + if (!is_file($tmpFile)) { + $this->set_error('upload_temp_file_missing'); + log_message('error', 'do_upload2 temp file missing: ' . $tmpFile); + return false; + } + + // ✅ 클라우드에 올라갈 "Key"를 직접 만든다 (로컬 경로 절대 넣지 말기) + // 예시: upload/tmp/랜덤파일명 또는 upload/apt_file/{rcpt_no}/... + $objectKey = $filePath . $newName; + + $up = $this->upload_object_storage($objectKey, $tmpFile, 'file'); + if ($up === false) { + $this->set_error('upload_destination_cloud_error'); + return false; + } + + // (선택) tmp 파일 삭제 + @unlink($tmpFile); + + $this->s3_data = [ + 'object_key' => $objectKey, + 'object_storage_url' => $up['object_storage_url'] ?? null, + 'origin_name' => $file->getClientName(), + 'file_name' => basename($objectKey), // xxxx.jpg + 'base_name' => pathinfo($objectKey, PATHINFO_FILENAME), // xxxx + 'ext' => pathinfo($objectKey, PATHINFO_EXTENSION), // jpg + ]; + + + log_message('debug', 's3_data=' . json_encode($this->s3_data ?? null, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); + + + return $this->s3_data; + } + + /** + * S3(NCLOUD) 파일 업로드 + * 추가일 2025.12.24 + * 작성자 - yangsh + */ public function do_upload(string $field = 'userfile'): bool { + $request = service('request'); $file = $request->getFile($field); + var_dump($file); + if (!$file) { $this->set_error('upload_no_file_selected'); return false; @@ -222,10 +290,13 @@ class MyUpload $this->errors[] = $msg; } - // -------------------------------------------------------------------- - // === 너의 기존 S3 메서드들 (CI4용으로 client 생성만 보강) === - public function upload_object_storage(string $key, string $temp_file, string $type = 'file'): bool + /** + * S3(NCLOUD) 파일 업로드 + * 수정일 2025.12.24 + * 작성자 - yangsh + */ + public function upload_object_storage(string $key, string $temp_file, string $type = 'file'): array|false { // CI3 코드의 경로 치환 로직 유지 (FCPATH는 CI4에도 존재) $object_storage_upload_path = str_replace(FCPATH, '/', $key); @@ -236,27 +307,77 @@ class MyUpload $s3Client = $this->makeS3Client(); try { - $body = file_get_contents($temp_file); + // $body = file_get_contents($temp_file); + + // $response = $s3Client->putObject([ + // 'Bucket' => NCLOUD_S3_BUCKET, + // 'Key' => ltrim($object_storage_upload_path, '/'), + // 'Body' => $body, + // 'ACL' => 'public-read', + // ]); $response = $s3Client->putObject([ 'Bucket' => NCLOUD_S3_BUCKET, 'Key' => ltrim($object_storage_upload_path, '/'), - 'Body' => $body, + 'SourceFile' => $temp_file, // ✅ 동영상도 OK 'ACL' => 'public-read', + + // (선택) 타입별 ContentType 지정 (브라우저 재생/다운로드에 중요) + // 'ContentType' => $this->guessMime($temp_file, $type), ]); - $this->s3_data = [ - 'object_storage_upload_path' => $object_storage_upload_path, + // $this->s3_data = [ + // 'object_storage_upload_path' => $object_storage_upload_path, + // 'object_storage_url' => $response['ObjectURL'] ?? null, + // ]; + + return [ 'object_storage_url' => $response['ObjectURL'] ?? null, ]; } catch (\Throwable $e) { // 운영에서는 echo 지양. 로그로 남기는 걸 추천 // log_message('error', $e->getMessage()); + log_message('error', '[S3 UPLOAD FAIL] ' . $e->getMessage()); + log_message('error', '[S3 UPLOAD TRACE] ' . $e->getTraceAsString()); + return false; + } + + } + + /** + * S3(NCLOUD) 파일 업로드 - 썸네일 + * 추가일 2025.12.24 + * 작성자 - yangsh + */ + public function upload_object_storage_imagick2($key, $blobData): bool + { + $object_storage_upload_path = str_replace(FCPATH, '/', $key); + $object_storage_upload_path = str_replace('/image/confirms_upload/', '/upload/', $object_storage_upload_path); + $object_storage_upload_path = str_replace('//', '/', $object_storage_upload_path); + $object_storage_upload_path = str_replace('/home/www/upload/confirms_upload/', '/upload/', $object_storage_upload_path); + + $s3Client = $this->makeS3Client(); + + try { + + $response = $s3Client->putObject([ + 'Bucket' => NCLOUD_S3_BUCKET, + 'Key' => ltrim($object_storage_upload_path, '/'), + 'Body' => $blobData, + 'ACL' => 'public-read', + ]); + + + } catch (\Throwable $e) { + // 운영에서는 echo 지양. 로그로 남기는 걸 추천 + log_message('error', '[S3 UPLOAD FAIL] ' . $e->getMessage()); + log_message('error', '[S3 UPLOAD TRACE] ' . $e->getTraceAsString()); return false; } return true; + } public function upload_object_storage_imagick(string $key, $blobData): bool @@ -306,28 +427,18 @@ class MyUpload protected function makeS3Client(): S3Client { - // AWS SDK v2: S3Client::factory / v3+: new S3Client - if (method_exists(S3Client::class, 'factory')) { - /** @noinspection PhpUndefinedMethodInspection */ - return S3Client::factory([ - 'key' => NCLOUD_S3_KEY, - 'secret' => NCLOUD_S3_SECRET, - 'endpoint' => NCLOUD_S3_ENDPOINT, - 'debug' => true, - 'ssl.certificate_authority' => false, - ]); - } + $region = defined('NCLOUD_S3_REGION') ? NCLOUD_S3_REGION : 'ap-northeast-2'; + + // ✅ credentials를 provider로 강제하면 provider-chain(IMDS) 안 탐 + $creds = new Credentials(NCLOUD_S3_KEY, NCLOUD_S3_SECRET); + $provider = CredentialProvider::fromCredentials($creds); return new S3Client([ - 'endpoint' => NCLOUD_S3_ENDPOINT, - 'credentials' => [ - 'key' => NCLOUD_S3_KEY, - 'secret' => NCLOUD_S3_SECRET, - ], - 'region' => defined('NCLOUD_S3_REGION') ? NCLOUD_S3_REGION : 'kr-standard', 'version' => 'latest', - // (보안주의) 필요하면 verify 설정을 추가 - // 'http' => ['verify' => false], + 'region' => $region, + 'endpoint' => NCLOUD_S3_ENDPOINT, + 'credentials' => $provider, + 'use_path_style_endpoint' => true, ]); } diff --git a/app/Models/article/AptModel.php b/app/Models/article/AptModel.php index 47752ca..20d8bc7 100644 --- a/app/Models/article/AptModel.php +++ b/app/Models/article/AptModel.php @@ -772,6 +772,7 @@ class AptModel extends Model ,b.memo, b.note, b.video_target, b.vdo_up_ynx, b.not_vdo_reson, b.apt_step, b.not_vdo_tm, b.check_yn, b.resend_yn, b.write_complete_yn, b.all_no_pho ,b.write_complete_tm, DATE_FORMAT(b.write_complete_tm, '%Y-%m-%d') as rdate_dt_cmpl ,DATE_FORMAT(b.write_complete_tm, '%H:%i:%s') as rdate_tm_cmpl ,b.charger, b.dept_sq ,(SELECT pdept_sq FROM departments WHERE dept_sq = b.dept_sq) bonbu + ,IFNULL((SELECT CONCAT(file_path, '', filenm_up) FROM apt_photo WHERE rcpt_no = a.rcpt_no AND pho_cate1 = 'V' AND pho_cate2 = 'V01' ORDER BY pho_no DESC LIMIT 1), '') AS vdo_path FROM apt_receipt a JOIN apt_result b ON a.rcpt_no = b.rcpt_no @@ -1030,8 +1031,24 @@ class AptModel extends Model 'pho_cate2' => $params['pho_cate2'], ]; - $this->db->where_in('pho_no', $params['pho_no']); - $result = $this->db->update('apt_photo', $data); + $phoNos = $params['pho_no'] ?? []; + + if (!is_array($phoNos)) { + $phoNos = [$phoNos]; + } + + if (empty($phoNos)) { + return [ + 'success' => false, + 'msg' => '대상 pho_no가 없습니다.', + ]; + } + + $builder = $this->db->table('apt_photo'); + + $builder->whereIn('pho_no', $phoNos); + $result = $builder->update($data); + if ($result === false) { return [ @@ -1182,6 +1199,31 @@ class AptModel extends Model ]; } + // 단지정보 작성완료 + public function saveWriteComplete($rcpt_no) + { + $sql = " UPDATE apt_result" . + " SET write_complete_yn = 'Y'" . + " ,apt_step = CASE WHEN vdo_up_ynx = 'N' THEN 'S02' ELSE 'S04' END" . + " ,write_complete_tm = now()" . + " WHERE rcpt_no = ? "; + + if ($this->db->query($sql, [$rcpt_no])) { + return [ + 'success' => false, + 'msg' => '저장실패', + ]; + } + + $now = $this->getDetail($rcpt_no); + $this->saveHistory($rcpt_no, $now['apt_step'], 'C', 'C1', session('usr_id')); + + // 성공 + return [ + 'success' => true, + ]; + } + // 단지실사 API 정보 public function new_api_photo_send_data($rcpt_no) @@ -1246,4 +1288,153 @@ class AptModel extends Model 'success' => true, ]; } + + + // 업로드 파일정보 저장 + public function saveImg($params) + { + $sql = "INSERT INTO apt_photo + (rcpt_no, pho_lati, pho_long, filenm, filenm_up, pho_view_yn, pho_date, insert_tm, file_path, use_yn, thumb_path, thumb_nm, cloud_upload_yn) + VALUES + ( + {$params['rcpt_no']}, + '{$params['gps_lat']}', + '{$params['gps_lon']}', + '{$params['origin_name']}', + '{$params['file_name']}', + 'Y', + '{$params['cam_date']}', + NOW(), + '{$params['upload_path']}', + 'Y', + '{$params['upload_path']}', + '{$params['thumb_name']}', + 'Y' + ) + "; + + if ($this->db->query($sql) === false) { + return [ + 'success' => false, + 'msg' => '저장실패', + ]; + } + + return [ + 'success' => true, + ]; + } + + // 동영상 정보 저장 + public function saveVideo($params) + { + $sql = "INSERT INTO apt_photo + (rcpt_no, pho_cate1, pho_cate2, filenm, filenm_up, insert_tm, file_path, use_yn, cloud_upload_yn) + VALUES + ( + {$params['rcpt_no']}, + 'V', + 'V01', + '{$params['origin_name']}', + '{$params['file_name']}', + NOW(), + '{$params['upload_path']}', + 'Y', + 'Y' + ) + "; + + // print ($sql); + + if ($this->db->query($sql) === false) { + return [ + 'success' => false, + 'msg' => '저장실패', + ]; + } + + $sql = "UPDATE apt_result" . + " SET vdo_up_ynx = 'Y'" . + " ,not_vdo_reson = ''" . + " ,video_target = 'Y'" . + " ,not_vdo_tm = NULL " . + " ,vdo_up_tm = NOW() " . + " ,apt_step = 'S03'" . + " WHERE rcpt_no = {$params['rcpt_no']}"; + + $this->db->query($sql); + + // print ($sql); + + //히스토리 + $this->saveHistory($params['rcpt_no'], 'S03', 'F', 'F1', session('usr_id')); + + return [ + 'success' => true, + ]; + } + + + // 업로드파일 일괄삭제 + public function removeAllPho($rcpt_no) + { + $sql = "UPDATE apt_photo" . + " SET use_yn = 'N'" . + " WHERE rcpt_no = ? "; + + if ($this->db->query($sql, [$rcpt_no]) === false) { + return [ + 'success' => false, + 'msg' => '저장실패', + ]; + } + + return [ + 'success' => true, + ]; + } + + // 선택파일 삭제 + public function removePho($params) + { + $builder = $this->db->table('apt_photo'); + + $builder->whereIn('pho_no', $params); + + $result = $builder->update([ + 'use_yn' => 'N', + ]); + + if ($result === false) { + return [ + 'success' => false, + 'msg' => 'DB 업데이트 실패', + ]; + } + + return [ + 'success' => true, + ]; + } + + // 카테고리 지정 + public function updatePhoCate($data) + { + $sql = "UPDATE apt_photo SET + pho_cate1 = '{$data['code1']}', + pho_cate2 = '{$data['code2']}' + WHERE pho_no = {$data['pho_no']} + "; + + if ($this->db->query($sql) === false) { + return [ + 'success' => false, + 'msg' => '저장 실패', + ]; + } + + return [ + 'success' => true, + ]; + } } \ No newline at end of file diff --git a/app/Models/common/CodeModel.php b/app/Models/common/CodeModel.php index 9fdcdce..c258b2c 100644 --- a/app/Models/common/CodeModel.php +++ b/app/Models/common/CodeModel.php @@ -32,7 +32,7 @@ class CodeModel extends Model ->getResultArray(); } - public function getCategoryCodeList($category = array(), $useYn = '') + public function getCategoryCodeList($category = [], $useYn = '') { $this->db->select('category, cd, cd_nm, use_yn'); $this->db->from('codes'); diff --git a/app/Views/pages/article/detail.php b/app/Views/pages/article/detail.php index 1486799..3ea0812 100644 --- a/app/Views/pages/article/detail.php +++ b/app/Views/pages/article/detail.php @@ -42,6 +42,31 @@ background-color: #ff0000 !important; color: #fff !important; } + + .dropzone { + min-height: 260px; + background-color: #fafbfc; + } + + .dropzone:hover { + background-color: #f4f6f8; + } + + #myDropzone { + position: relative; + padding-top: 110px; + /* 메시지 영역 높이만큼 */ + } + + #uploadModal .modal-dialog { + max-width: 1140px; + /* modal-xl */ + } + + #uploadModal .modal-content { + height: 450px; + max-height: 450px; + }

아파트단지 DB구축 상세

@@ -85,12 +110,11 @@
-
-
@@ -155,7 +179,7 @@ - @@ -227,7 +251,7 @@
단지 특이사항
+ style="height: 220px;resize: none;">
@@ -279,10 +303,21 @@ 동영상 - 비디오
- +
+ + + + + 비디오
+ + +
동영상 촬영불가 @@ -352,17 +387,181 @@ 사진 일괄삭제 - + 단지정보 작성완료 - +
+ $val) { + if (empty($val['pho_cate2'])) { + $arrPho[] = $val; + unset($image[$key]); + } + } + + if (!empty($arrPho)): + ?> + +
+
+
+
카테고리 미지정 이미지
+ +
+
+ + +
+ +
+
+ +
+ +
+
+ + <?= esc($fileNm) ?> + + +
+ + +
+
+
+ + + +
+
+ +
+ + +
단지 사진 및 설명 정보
@@ -493,7 +692,7 @@ - + @@ -635,7 +834,7 @@ + style="width:350px;height:90px;resize: none;"> @@ -671,7 +870,7 @@
- -
+ +
+
+
+ 파일을 드래그하거나 클릭해서 추가하세요
+ + 사진 여러 장 가능 / 동영상은 1개만 + +
@@ -773,6 +979,25 @@
+ + endSection() ?>