middleware('permission:vpk-review|vpk-reduction|vpk-device-setting|vpk-statistics|vpk-analysis|vpk-read', ['only' => ['VpkReview']]); $this->middleware('permission:vpk-review|permission:vpk-reduction', ['only' => ['vpkCensored', 'update']]); $this->middleware('permission:vpk-device-setting', ['only' => ['VpkDeviceSetting']]); $this->middleware('permission:vpk-statistics', ['only' => ['VpkStatistics']]); $this->middleware('permission:vpk-analysis', ['only' => ['VpkAnalysis']]); // OK path $this->destPath_root = 'E:\\OK\\VPK\\'; $this->clientDestPath_root = 'E:\\'; // NOK path $this->unreportPath_root = 'C:\\xampp\\SMMS\\storage\\app\\ParsingFiles\\NOK\\VPK\\'; $this->month['start'] = Carbon::now()->subDays(8)->format('Y-m-d'); $this->month['current'] = Carbon::now()->subDays(1)->format('Y-m-d'); } public function VpkReview() { $device = explode(',', auth()->user()->device) ?? [1]; // dd($device); $equipmentData = new ViolationParkingEquipment(); $serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); $violationparking = new ViolationParking(); $locationtype = $violationparking::where('processcheck', 0)->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); // dd($data,$page_data); $vio_arr = []; foreach (ViolationLaw::whereIn('type', ['違規停車'])->get() as $key => $item) { $vio_arr[$key]['violationcode'] = $item->violationcode; $vio_arr[$key]['display_name'] = $item->display_name; } // dd($vio_arr); return view('system.violationParking.index') ->with('serialNumber', $serialNumber) ->with('locationtype', $locationtype) ->with('vio_arr', $vio_arr) ->with('month', $this->month); } #region 已審 View public function vpkCensored(Request $request) { $device = explode(',', auth()->user()->device) ?? [1]; $equipmentData = new ViolationParkingEquipment(); $serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); $violationparking = new ViolationParking(); $locationtype = $violationparking::where('processcheck', 1)->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); // dd($data,$page_data); return view('system.violationParking.manage') ->with('serialNumber', $serialNumber) ->with('locationtype', $locationtype) ->with('month', $this->month); } #endregion #region 不舉發 View public function vpkUnreport(Request $request) { $device = explode(',', auth()->user()->device) ?? [1]; $equipmentData = new ViolationParkingEquipment(); $serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); $violationparking = new ViolationParking(); $locationtype = $violationparking::where('processcheck', 2)->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); $unreportreason = $violationparking->where('processcheck', 2)->whereIn('serialnumber', $device)->groupBy('unreportreason')->pluck('unreportreason'); // dd($locationtype,$unreportreason); return view('system.violationParking.unreport') ->with('serialNumber', $serialNumber) ->with('locationtype', $locationtype) ->with('unreportreason', $unreportreason) ->with('month', $this->month); } #endregion public function update(Request $request, $id) { if (!auth('api')->user()->can('vpk-review')) { return response()->json(['error' => '無權限審查此案件'], 403); } $vpk = ViolationParking::findOrFail($id); $result = app(ViolationParkingService::class)->review($vpk, $request->all(), auth('api')->user()); return response()->json($result); } #region DataTable (AJAX刷新用 參數 processcheckStatus 0未審 1已審 2不舉發 "99清冊用")使用 public function getDataTable(Request $request) { // dd($request->all()); #region 設備限制 $device = explode(',', auth("api")->user()->device) ?? [1]; // dd($device); #endregion $processcheckStatus = $request->processcheckStatus; // dd($processcheckStatus, $device); [$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($device, $request, $processcheckStatus); $response = array( "draw" => intval($draw), "iTotalRecords" => $totalRecords, "iTotalDisplayRecords" => $totalRecordswithFilter, "aaData" => $data_arr ); // dd($response); echo json_encode($response); exit; } #endregion #region 取得資料 function getData($device, $request, $processcheckStatus = null) { // 審查狀態 0 未審 1 已審查 2 不舉發 99清冊 // $processcheckStatus = 2; // dd($device, $request, $processcheckStatus); #region Request 搜尋值 if (isset($request->searchByFromdate)) $searchByFromdate = $request->searchByFromdate; if (isset($request->searchByTodate)) $searchByTodate = $request->searchByTodate; //地點搜尋 if (isset($request->location)) $location = $request->location; //車牌搜尋 if (isset($request->carnumber)) $carnumber = $request->carnumber; //不舉發理由搜尋 if (isset($request->unreportreason)) $unreportreason = $request->unreportreason; #endregion #region DataTable 搜尋屬性 if (!isset($request->export)) { $draw = $request->get('draw'); $start = $request->get("start"); $rowperpage = $request->get("length"); // Rows display per page $columnIndex_arr = $request->get('order'); $columnName_arr = $request->get('columns'); $order_arr = $request->get('order'); $search_arr = $request->get('search'); $columnIndex = $columnIndex_arr[0]['column']; // Column index $columnName = $columnName_arr[$columnIndex]['data']; // Column name $columnSortOrder = $order_arr[0]['dir']; // asc or desc $searchValue = $search_arr['value']; // Search value } else { $draw = 0; } #endregion // Fetch records $records = ViolationParking::query(); if (isset($columnName)) $records->orderBy($columnName, $columnSortOrder); if (isset($searchValue)) $records->where('carnumber', 'like', '%' . $searchValue . '%'); //已審未審 //清冊用 99 $records->where('violationtype', '!=', '違規臨時停車'); if ($processcheckStatus == 99) { $processcheckStatus = $request->processCheck; if ($processcheckStatus == 99 || $processcheckStatus == null) $records->whereIn('processcheck', [0, 1, 2]); else { $records->where('processcheck', $processcheckStatus); } } else { $records->where('processcheck', $processcheckStatus); } //設備限制 $records->whereIn('serialnumber', $device); //時間限制 if (isset($searchByFromdate)) $records->where('datatime', ">", $searchByFromdate . ' 00:00:00'); if (isset($searchByTodate)) $records->where('datatime', "<", $searchByTodate . ' 23:59:59'); //地點篩選 if (isset($location)) $records->where('serialnumber', $location); //車牌篩選 if (isset($carnumber)) $records->where('carnumber', 'like', '%' . $carnumber . '%'); //不舉發理由 if (isset($unreportreason)) $records->where('unreportreason', 'like', '%' . $unreportreason . '%'); $totalRecords = $records->count(); $totalRecordswithFilter = $records->count(); //如果有報表類型(1,2,3,...),並需要特別處理欄位的報表 if (isset($request->statisticstype)) { if ($request->statisticstype == 2){ $records->groupBy('serialnumber', 'cartype')->select('*', DB::raw('count(*) as count')); $totalRecords = $records->get()->count(); $totalRecordswithFilter = $records->get()->count(); } if ($request->statisticstype == 3) { $groupbyPara1 = "CAST(DATE_FORMAT(datatime, '%H') AS SIGNED)"; $records->groupBy(DB::raw($groupbyPara1), 'serialnumber', 'violationtype')->select('*', DB::raw('COUNT(*) as count, CONCAT(CAST(DATE_FORMAT(datatime,"%H") as SIGNED),"-",CAST(DATE_FORMAT(DATE_ADD(datatime,INTERVAL +1 HOUR),"%H") as SIGNED)) AS period')); $records->orderBy(DB::raw($groupbyPara1), 'ASC'); $totalRecords = $records->get()->count(); $totalRecordswithFilter = $records->get()->count(); } } else { $records->select('*'); } if (!isset($request->export)) { if (isset($start)) $records->skip($start); if (isset($rowperpage)) $records->take($rowperpage); } $records = $records->get(); $data_arr = array(); // $sno = $start + 1; foreach ($records as $record) { //還原用id $id = $record->id; //不舉發原因 $unreportreason = $record->unreportreason; $datatime = $record->datatime; $serialnumber = $record->serialnumber; $location = $record->location; $carnumber = $record->carnumber; $picture = $record->picture; $picture2 = $record->picture2; $violationtype = $record->violationtype; $cartype = $record->cartype; $unreportpicture = $record->unreportpicture; $processcheck = $record->processcheck; $postcheck = $record->postcheck ?? 0; //報表用的欄位,避免前端錯誤,給預設值 $count = $record->count ?? 0; $period = $record->period ?? ""; $cartypeTitle = [ '1' => "汽車", '2' => "機車", '3' => "重型機車", '4' => "輕型機車" ]; $processCheckTitle = [ '0' => "未審", '1' => "已審查", '2' => "不舉發" ]; if (!isset($cartype)) $cartype = 1; $data_arr[] = array( "id" => $id, "datatime" => $datatime, "serialnumber" => $serialnumber, "location" => $location, "carnumber" => $carnumber, "picture" => $picture, "picture2" => $picture2, //影片連結 (用照片的路徑取代成mp4 picture= _A picture2= _B) "video" => str_replace('.jpg', '.mp4', $picture2), "violationtype" => $violationtype, "cartype" => $cartype, "carkind" => $cartypeTitle[$cartype], "unreportreason" => $unreportreason ?? "", "unreportpicture" => $unreportpicture ?? $picture, "postcheck" => $postcheck, // 清冊用 "processcheck" => $processCheckTitle[$processcheck], // "searchByFromdate" => $searchByFromdate, // "searchByTodate"=> $searchByTodate, "count" => $count, "period" => $period ); } return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr]; } #endregion // 清冊用 public function vpkStatistics() { $device = explode(',', auth()->user()->device) ?? [1]; // 違規地點 group by $equipmentData = new ViolationParkingEquipment(); $serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); // 違規類型 group by $violationparking = new ViolationParking(); $violationtype = $violationparking::whereIn('serialnumber', $device)->groupBy('violationtype')->pluck('violationtype'); return view('system.violationParking.statistics') ->with('serialNumber', $serialNumber) ->with('violationtype', $violationtype); } public function getStatisticsData(Request $request) { #region 設備限制 $device = explode(',', auth("api")->user()->device) ?? [1]; #endregion $processcheckStatus = 99; [$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($device, $request, $processcheckStatus); $response = array( "draw" => intval($draw), "iTotalRecords" => $totalRecords, "iTotalDisplayRecords" => $totalRecordswithFilter, "aaData" => $data_arr ); return $response; } public function getStatisticsDataExport(Request $request) { set_time_limit(0); ini_set('memory_limit', '2048M'); #region 設備限制 // $device = ViolationParkingEquipment::all()->pluck('serialnumber')->toArray(); $device = explode(',', auth("api")->user()->device) ?? [1]; #endregion $processcheckStatus = 99; if ($request->statisticstype == 1) { $columns = ['datatime', 'serialnumber', 'location', 'carnumber', 'violationtype', 'processcheck']; $columnTitle = [ ["【表單名稱】:", "違規件數清冊"], ["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], ['違規時段', '設備編號', '違規地點', '車號', '違規類型', '審查狀態'] ]; } elseif ($request->statisticstype == 2) { $columns = ['serialnumber', 'location', 'violationtype', 'carkind', 'count']; $columnTitle = [ ["【表單名稱】:", "違規件數統計清冊"], ["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], ['設備編號', '違規地點', '違規類型', '車種', '統計'] ]; } elseif ($request->statisticstype == 3) { $columns = ['serialnumber', 'location', 'period', 'violationtype', 'count']; $columnTitle = [ ["【表單名稱】:", "違規時段件數統計清冊"], ["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], ['設備編號', '違規地點', '違規時段', '違規類型', '統計'] ]; } [$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($device, $request, $processcheckStatus); $data = array_map(function ($row) use ($columns) { return array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); }, $data_arr); $fileName = 'vpk-' . Str::random(10) . '.xlsx'; ExportFiles::create([ 'name' => $fileName, 'path' => 'public/exports', 'type' => 'xlsx', 'status' => '1', 'remark' => '違規件數清冊', 'user_id' => auth('api')->user()->id, ]); Excel::store(new ArrayExport($data, $columnTitle), 'public/exports/' . $fileName, 'local', \Maatwebsite\Excel\Excel::XLSX); return response()->json(['url' => route('vpk-export', ['fileName' => $fileName])], 200); } public function vpkExport(Request $request, $fileName) { $file = ExportFiles::where('name', $fileName)->first(); $filePath = storage_path('app/public/exports/' . $fileName); if (file_exists($filePath)) { return response()->download($filePath, $file->remark . '.' . $file->type); } else { return response()->json(['error' => '檔案不存在']); } } // 數據分析 vpkAnalysis public function vpkAnalysis() { $device = explode(',', auth()->user()->device) ?? [1]; // 違規地點 group by $equipmentData = new ViolationParkingEquipment(); $serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); // 違規類型 group by $violationparking = new ViolationParking(); $violationtype = $violationparking::whereIn('serialnumber', $device)->groupBy('violationtype')->pluck('violationtype'); return view('system.violationParking.analysis') ->with('serialNumber', $serialNumber) ->with('violationtype', $violationtype); } public function getAnalysisData(Request $request) { // memory ini_set('memory_limit', '2048M'); // timeout set_time_limit(0); // $device = ViolationParkingEquipment::all()->pluck('serialnumber')->toArray(); $device = explode(',', auth("api")->user()->device) ?? [1]; $records = ViolationParking::query(); $records->whereIn('serialnumber', $device)->whereIn('processcheck', [1, 3]); // dd($request->all()); if (isset($request->search_fromdate)) $records->where('datatime', ">", $request->search_fromdate . ' 00:00:00'); else //近七天 $records->where('datatime', ">", '2020-01-01 00:00:00'); if (isset($request->search_todate)) $records->where('datatime', "<", $request->search_todate . ' 23:59:59'); else $records->where('datatime', "<", Carbon::now()->format('Y-m-d') . ' 23:59:59'); //地點搜尋 if (isset($request->location)) $records->where('serialnumber', $request->location); if (isset($request->violation_type)) $records->where('violationtype', $request->violation_type); $data = $records->get(); if (isset($request->chart_type)) { if ($request->chart_type == '1') { // 根據違規類型分類 並計算每一類的總數 $data = $data->groupBy('violationtype')->map(function ($item, $key) { return [ 'title' => $key, 'times' => $item->count() ]; })->toArray(); $data = array_values($data); } elseif ($request->chart_type == '2') { // 根據違規類型分類 並計算每一類的總數 $data = $data->groupBy('location')->map(function ($item, $key) { return [ 'title' => $key, 'times' => $item->count() ]; })->toArray(); $data = array_values($data); } elseif ($request->chart_type == '3') { $records2 = ViolationParking::query(); $records2->whereIn('serialnumber', $device)->whereIn('processcheck', [1, 3]); // dd($request->all()); if (isset($request->search_fromdate)) $records2->where('datatime', ">", $request->search_fromdate . ' 00:00:00'); else //近七天 $records2->where('datatime', ">", '2020-01-01 00:00:00'); if (isset($request->search_todate)) $records2->where('datatime', "<", $request->search_todate . ' 23:59:59'); else $records2->where('datatime', "<", Carbon::now()->format('Y-m-d') . ' 23:59:59'); //地點搜尋 if (isset($request->location)) $records2->where('serialnumber', $request->location); if (isset($request->violation_type)) $records2->where('violationtype', $request->violation_type); $violationTypes = $records2->groupBy('violationtype')->select('violationtype')->get()->toArray(); $violationTypes = array_column($violationTypes, 'violationtype'); // violationTypes key value 互換 $violationTypesKey = array_flip($violationTypes); // dd($violationTypes); // 初始化結果陣列 $response = []; for ($hour = 0; $hour <= 23; $hour++) { // 補零 01, 02, 03, ..., 09 // $hour = str_pad($hour, 2, '0', STR_PAD_LEFT); // 初始化結果陣列 $response[$hour] = [ 'category' => $hour, ]; for ($i = 0; $i < count($violationTypes); $i++) { $response[$hour][$i] = 0; } } $data = $records->get(); $data = $data->groupBy(function ($item, $key) { return intval(Carbon::parse($item->datatime)->format('H')); })->map(function ($item, $key) use (&$response, $violationTypesKey) { $item->groupBy('violationtype')->map(function ($item, $viotype) use ($key, &$response, $violationTypesKey) { $response[$key][$violationTypesKey[$viotype]] = $item->count(); }); }); $data = $response; } } // dd($data); return response()->json(['data' => $data, 'chart_type' => $request->chart_type, 'violationtype' => $violationTypes ?? ''], 200); } #region 更新Ini function updateIni($path, $oldCarNumber, $newCarNumber, $oldViolationType, $newViolationType) { // $oldCarNumber = explode('"', "$oldCarNumber")[1]; $iniPath = str_replace('jpg', 'ini', str_replace('*', '\\', storage_path('app' . '\\' . 'ParsingFiles' . '\\' . "$path"))); $iniFile = fopen("$iniPath", "r+"); $iniData = fread($iniFile, filesize("$iniPath")); $iniData = iconv('Big5', 'UTF-8', "$iniData"); // if(strpos($iniData,'車號')){ // $iniData = str_replace("$oldCarNumber", "$newCarNumber", "$iniData"); // }else{ // $iniData = str_replace("\r\n操作者姓名", "\r\n車號="."$newCarNumber"."\r\n操作者姓名", "$iniData"); // } $iniData = str_replace("$oldCarNumber", "$newCarNumber", "$iniData"); $iniData = str_replace("$oldViolationType", "$newViolationType", "$iniData"); $iniData = iconv('UTF-8', 'Big5', "$iniData"); $iniFile = fopen("$iniPath", "w+"); fwrite($iniFile, "$iniData"); fclose($iniFile); } function saveFinishFile($data) { //路徑位置設定 $destPath_root = $this->destPath_root; $clientDestPath_root = $this->clientDestPath_root; // $ftpPath_root = $this->ftpPath_root; $locPath = "[" . $data['serialnumber'] . "]" . $data['location']; $path = $data['picture']; // $path2 = $data['picture2']; $time = str_replace('-', '', explode(' ', $data['datatime'])[0]); $iniPath = str_replace('jpg', 'ini', str_replace('*', '\\', storage_path('app' . '\\' . 'ParsingFiles' . '\\' . "$path"))); $photoPath = str_replace('*', '\\', storage_path('app' . '\\' . 'ParsingFiles' . '\\' . "$path")); // $photoPath2 = str_replace('*','\\', storage_path('app'.'\\'.'ParsingFiles'.'\\'."$path2")); // $photoName = explode('*', $data['picture'])[4]; //原始有"時" 資料夾的層數 $photoName = explode('*', $data['picture'])[3]; // $photoName2 = explode('*', $data['picture2'])[3]; $destPath = $destPath_root . Auth::user()->account . "\\" . $time . "\\" . $locPath; $clientDestPath = $clientDestPath_root . Auth::user()->account . "\\" . $time . "\\" . $locPath; if (is_dir($destPath) === false) { mkdir($destPath, 0777, true); } if (is_dir($clientDestPath) === false) { mkdir($clientDestPath, 0777, true); } try { copy($iniPath, $destPath . '\\' . str_replace('jpg', 'ini', $photoName)); copy($photoPath, $destPath . '\\' . $photoName); // copy($photoPath2, $destPath.'\\'.$photoName2); // 存入第二路徑供客戶操作資料 copy($iniPath, $clientDestPath . '\\' . str_replace('jpg', 'ini', $photoName)); copy($photoPath, $clientDestPath . '\\' . $photoName); // copy($photoPath2, $clientDestPath.'\\'.$photoName2); // 存入第FTP路徑供客戶操作資料 // $ftpPath = $ftpPath_root.$time; // if( is_dir($ftpPath) === false ) { mkdir($ftpPath, 0777, true);} // copy($iniPath, $ftpPath.'\\'.str_replace('jpg','ini', $photoName)); // copy($photoPath, $ftpPath.'\\'.$photoName); } catch (\Throwable $th) { //throw $th; } } #endregion #region 下載ZIP function downloadZipPicture(Request $request) { set_time_limit(0); ini_set('memory_limit', '2048M'); $device = explode(',', auth("api")->user()->device) ?? [1]; if (isset($request->searchByFromdate)) $searchByFromdate = $request->searchByFromdate; if (isset($request->searchByTodate)) $searchByTodate = $request->searchByTodate; if (isset($request->location)) $serialnumber = $request->location; if (isset($request->carnumber)) $carnumber = $request->carnumber; if (isset($request->processcheck)) $processcheck = $request->processcheck; else $processcheck = 1; $records = ViolationParking::query(); $records->where('location', 'not like', '%測試%'); $records->whereIn('serialnumber', $device); $records->where('processcheck', $processcheck); if (isset($searchByFromdate)) $records->where('datatime', ">", $searchByFromdate . ' 00:00:00'); else { $records->where('datatime', ">", Carbon::now()->subMonths(2)); $searchByFromdate = ''; } if (isset($searchByTodate)) $records->where('datatime', "<", $searchByTodate . ' 23:59:59'); else $searchByTodate = ''; if (isset($serialnumber)) $records->where('serialnumber', $request->location); if (isset($carnumber)) $records->where('carnumber', 'like', '%' . $carnumber . '%'); $records = $records->pluck("picture"); for ($i = 0; $i < count($records); $i++) { $records[$i] = storage_path("app\\ParsingFiles\\" . str_replace('*', '\\', $records[$i])); } $fileName = $this->downloadZip($records, $request->location, $searchByFromdate, $searchByTodate, $processcheck); if (file_exists($fileName)) { ExportFiles::create([ 'name' => $fileName, 'path' => 'public', 'type' => 'zip', 'status' => '1', 'remark' => "違規停車-下載ZIP", 'user_id' => auth('api')->user()->id, ]); return $fileName; } else return "沒有檔案"; } public function downloadZip($files, $serialnumber, $searchByFromdate, $searchByTodate, $processcheck) { set_time_limit(0); ini_set('memory_limit', '2048M'); try { foreach (glob(public_path() . '\*.zip') as $file) { unlink($file); } } catch (\Throwable $th) { //throw $th; } $zip = new ZipArchive; $rand = Str::random(5); $fileName = "_$rand.zip"; if (isset($searchByTodate)) $fileName = str_replace('-', '', $searchByTodate) . $fileName; if (isset($searchByFromdate)) $fileName = str_replace('-', '', $searchByFromdate) . "_" . $fileName; if (isset($serialnumber)) $fileName = $serialnumber . "_" . $fileName; if (isset($processcheck)) { if ($processcheck == 1) $fileName = "VPK_OK_" . $fileName; if ($processcheck == 2) $fileName = "VPK_X_" . $fileName; } if ($zip->open(public_path($fileName), ZipArchive::CREATE) === TRUE) { foreach ($files as $file) { try { $name = explode("\\", $file); $iniPath = str_replace('.jpg', '.ini', $file); $iniName = explode("\\", $iniPath); if (end($name) != '') { $zip->addFile($file, end($name)); $zip->addFile($iniPath, end($iniName)); } } catch (\Throwable $th) { //throw $th; Log::error($th); } } $zip->close(); } // response()->download(public_path($fileName))->deleteFileAfterSend(true); return "$fileName"; } #endregion }