Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
ea22ebf3bc | 2 months ago |
|
87c9d48617 | 2 months ago |
296 changed files with 63998 additions and 298 deletions
@ -0,0 +1,485 @@
@@ -0,0 +1,485 @@
|
||||
<?php |
||||
|
||||
namespace App\Class; |
||||
|
||||
use App\Models\Multisys; |
||||
use App\Models\MultisysEntry; |
||||
use App\Models\OverSpeedRed; |
||||
use App\Models\OverSpeedRedEntry; |
||||
use App\Models\OverSpeedRedEntry2; |
||||
use App\Models\User; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Illuminate\Support\Facades\Storage; |
||||
|
||||
use GuzzleHttp\Client; |
||||
use GuzzleHttp\Exception\RequestException; |
||||
|
||||
use Intervention\Image\Laravel\Facades\Image; |
||||
|
||||
// 入案專用 class |
||||
class Entry |
||||
{ |
||||
|
||||
#region 路口多功能科技執法入案 |
||||
public static function multisys_entry($days = 7) |
||||
{ |
||||
$records = Multisys::query(); |
||||
$records->where('processcheck', 1); |
||||
$records->where('postcheck', 0); |
||||
// $records->where('datatime', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records->where('datatime', '>', '2024-06-01'); |
||||
$data = $records->select('id as multisys_id', 'picture as photo')->get()->toArray(); |
||||
|
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
unset($row['law_type']); |
||||
$values[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
// dd($values); |
||||
if (count($values) > 0) { |
||||
DB::transaction(function () use ($values, $records) { |
||||
// 在這裡執行需要交易的資料庫操作,例如新增、修改、刪除等等 |
||||
DB::insert('INSERT IGNORE INTO multisys_entry (multisys_id, photo) VALUES' . implode(',', $values)); |
||||
$records->update(['postcheck' => 1]); |
||||
}); |
||||
} |
||||
// DB::table('multisys_entry')->insertOrIgnore($data); |
||||
Log::notice('路口多功能入案-資料收集 近' . $days . '天,共' . count($values) . '筆'); |
||||
} |
||||
// 取得要處理的資料 |
||||
public static function get_multisys_entry_data($days = 1) |
||||
{ |
||||
$ids = MultisysEntry::where('status', 0)->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays($days))->pluck('multisys_id'); |
||||
$data = Multisys::whereIn('id', $ids)->get(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$datetime = $row->datatime; |
||||
$date = Carbon::parse($datetime)->toDateString(); |
||||
$twYear = Carbon::parse($date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$twDate = $twYear . Carbon::parse($date)->format('md'); // 將民國年與日期合併 |
||||
$time = Carbon::parse($datetime)->format('His'); |
||||
$row_data = [ |
||||
'datatime' => $row->datatime, |
||||
'SN' => $row->id, |
||||
'ViolationDate' => $twDate, |
||||
'ViolationTime' => $time, |
||||
'UnitId' => User::where('account', $row->jsoncheck)->first()->leader, |
||||
'PoliceName' => User::where('account', $row->jsoncheck)->first()->name, |
||||
'LicensePlate' => $row->carnumber, |
||||
'VehicleType' => $row->cartype, |
||||
'RuleId' => $row->violationcode, |
||||
'Road' => $row->location, |
||||
]; |
||||
array_push($values, $row_data); |
||||
} |
||||
return $values; |
||||
} |
||||
// 本機建檔備存 |
||||
public static function multisys_entry_local($data = []) |
||||
{ |
||||
|
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$datetime = $row_data['datatime']; |
||||
unset($row_data['datatime']); |
||||
// 存放檔案的目錄路徑 |
||||
$directory = 'entry/twosage/' . Carbon::now('Asia/Taipei')->format('Ymd'); |
||||
// 如果目錄不存在,則建立該目錄 |
||||
Storage::makeDirectory($directory); |
||||
// 將資料轉換為 JSON 格式 |
||||
$jsonData = json_encode($row_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); |
||||
// 將 JSON 資料寫入檔案 |
||||
$row_date = Carbon::parse($datetime)->format('Ymd_His'); |
||||
$fileName = 'Ts_' . $row_date . '_' . $row_data['SN'] . '.json'; |
||||
Storage::put($directory . "/$fileName", $jsonData); |
||||
} |
||||
} |
||||
Log::notice('路口多功能入案-資料組合備存,共' . count($data) . '筆'); |
||||
} |
||||
// 送出入案,紀錄回傳no |
||||
public static function multisys_entry_post($data = []) |
||||
{ |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
unset($row_data['datatime']); |
||||
try { |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/X/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
if(json_decode($resp, true)['Message'] == '新增完成'){ |
||||
MultisysEntry::where('multisys_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 1]); |
||||
}else{ |
||||
MultisysEntry::where('multisys_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
MultisysEntry::where('multisys_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('multisys_id: ' . $row_data['SN']); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::notice('路口多功能入案-資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
// 送出佐證圖片 |
||||
public static function multisys_entry_post_img() |
||||
{ |
||||
$re_arr = []; |
||||
$data = MultisysEntry::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(3)) |
||||
// ->whereIn('multisys_id', $re_arr) |
||||
->get(); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
try { |
||||
// 使用 intervention/image 將檔案壓縮至500K以下 |
||||
// 將圖片轉換為 base64 格式 不儲存 |
||||
// Log::notice($row_data->photo); |
||||
$img = Image::read(public_path('ParsingFiles/' . str_replace('*', '/', $row_data->photo))); |
||||
// if ($width > $height) then width = 720, height = 720 * $height / $width |
||||
// if ($height > $width) then height = 480, width = 480 * $width / $height |
||||
$width = $img->width(); |
||||
$height = $img->height(); |
||||
|
||||
if ($width > $height) { |
||||
$img->resize(2560, 2560 * $height / $width); |
||||
} else { |
||||
$img->resize(1440 * $width / $height, 1440); |
||||
} |
||||
$base64 = base64_encode($img->encode()); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
// Log::notice($post_data); |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('multisys_id: ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::notice('路口多功能入案-佐證資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
#endregion |
||||
|
||||
#region 闖紅燈超速入案 |
||||
public static function overspeedred_entry($days = 7) |
||||
{ |
||||
$records = OverSpeedRed::query(); |
||||
$records->where('processcheck', 1); |
||||
$records->where('postcheck', 0); |
||||
// $records->where('datatime', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records->where('datatime', '>', '2024-06-01'); |
||||
$data = $records->select('id as overspeedred_id', 'picture as photo', 'violationtype', 'datatime')->get()->toArray(); |
||||
|
||||
// 嚴重超速 |
||||
$records2 = OverSpeedRed::query(); |
||||
$records2->where('processcheck', 1); |
||||
$records2->where('postcheck', 0); |
||||
// $records->where('datatime', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records2->where('datatime', '>', '2024-06-01'); |
||||
$records2->whereIn('violationcode', ['4310240', '4310241', '4310242']); |
||||
$data2 = $records2->select('id as overspeedred_id', 'picture as photo', 'violationtype', 'datatime')->get()->toArray(); |
||||
|
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
// Log::notice($row); |
||||
unset($row['law_type']); |
||||
$violationtype = $row['violationtype']; |
||||
$time = str_replace('-', '', explode(' ', $row['datatime'])[0]); |
||||
$photoName = explode('*', $row['photo']); |
||||
$photoName = end($photoName); |
||||
$photoPath = "merge/$violationtype/$time/$photoName"; |
||||
$row['photo'] = $photoPath; |
||||
unset($row['violationtype']); |
||||
unset($row['datatime']); |
||||
$values[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
|
||||
// 嚴重超速資料彙整 |
||||
$values2 = []; |
||||
foreach ($data2 as $row) { |
||||
// Log::notice($row); |
||||
unset($row['law_type']); |
||||
$violationtype = $row['violationtype']; |
||||
$time = str_replace('-', '', explode(' ', $row['datatime'])[0]); |
||||
$photoName = explode('*', $row['photo']); |
||||
$photoName = end($photoName); |
||||
$photoPath = "merge/$violationtype/$time/$photoName"; |
||||
$row['photo'] = $photoPath; |
||||
unset($row['violationtype']); |
||||
unset($row['datatime']); |
||||
$values2[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
|
||||
if (count($values) > 0) { |
||||
DB::transaction(function () use ($values, $values2, $records) { |
||||
// 在這裡執行需要交易的資料庫操作,例如新增、修改、刪除等等 |
||||
DB::insert('INSERT IGNORE INTO overspeedred_entry (overspeedred_id, photo) VALUES' . implode(',', $values)); |
||||
if (count($values2) > 0) { |
||||
DB::insert('INSERT IGNORE INTO overspeedred_entry2 (overspeedred_id, photo) VALUES' . implode(',', $values2)); |
||||
} |
||||
$records->update(['postcheck' => 1]); |
||||
}); |
||||
} |
||||
// DB::table('overspeedred_entry')->insertOrIgnore($data); |
||||
Log::notice('闖紅燈超速入案-資料收集 近' . $days . '天,共' . count($values) . '筆'); |
||||
} |
||||
// 取得要處理的資料 |
||||
public static function get_overspeedred_entry_data($days = 1) |
||||
{ |
||||
$ids = OverSpeedRedEntry::where('status', 0)->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays($days))->pluck('overspeedred_id'); |
||||
$data = OverSpeedRed::whereIn('id', $ids)->get(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$datetime = $row->datatime; |
||||
$date = Carbon::parse($datetime)->toDateString(); |
||||
$twYear = Carbon::parse($date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$twDate = $twYear . Carbon::parse($date)->format('md'); // 將民國年與日期合併 |
||||
$time = Carbon::parse($datetime)->format('His'); |
||||
$row_data = [ |
||||
'datatime' => $row->datatime, |
||||
'SN' => $row->id, |
||||
'ViolationDate' => $twDate, |
||||
'ViolationTime' => $time, |
||||
'UnitId' => User::where('account', $row->jsoncheck)->first()->leader, |
||||
'PoliceName' => User::where('account', $row->jsoncheck)->first()->name, |
||||
'LicensePlate' => $row->carnumber, |
||||
'VehicleType' => $row->cartype, |
||||
'RuleId' => $row->violationcode, |
||||
'Road' => $row->location, |
||||
|
||||
]; |
||||
if ($row->violationtype == '超速') { |
||||
$row_data['Speed'] = intval(str_replace('km/h', '', $row->speed)); |
||||
$row_data['LimitSpeed'] = intval(str_replace('km/h', '', $row->limitspeed)); |
||||
} |
||||
array_push($values, $row_data); |
||||
} |
||||
return $values; |
||||
} |
||||
// 本機建檔備存 |
||||
public static function overspeedred_entry_local($data = []) |
||||
{ |
||||
|
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$datetime = $row_data['datatime']; |
||||
unset($row_data['datatime']); |
||||
// 存放檔案的目錄路徑 |
||||
$directory = 'entry/overspeedred/' . Carbon::now('Asia/Taipei')->format('Ymd'); |
||||
// 如果目錄不存在,則建立該目錄 |
||||
Storage::makeDirectory($directory); |
||||
// 將資料轉換為 JSON 格式 |
||||
$jsonData = json_encode($row_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); |
||||
// 將 JSON 資料寫入檔案 |
||||
$row_date = Carbon::parse($datetime)->format('Ymd_His'); |
||||
$fileName = 'OvO_' . $row_date . '_' . $row_data['SN'] . '.json'; |
||||
Storage::put($directory . "/$fileName", $jsonData); |
||||
} |
||||
} |
||||
Log::notice('闖紅燈超速入案-資料組合備存,共' . count($data) . '筆'); |
||||
} |
||||
// 送出入案,紀錄回傳no |
||||
public static function overspeedred_entry_post($data = []) |
||||
{ |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
unset($row_data['datatime']); |
||||
try { |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/X/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
if(json_decode($resp, true)['Message'] == '新增完成'){ |
||||
OverSpeedRedEntry::where('overspeedred_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 1]); |
||||
} |
||||
else{ |
||||
OverSpeedRedEntry::where('overspeedred_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
OverSpeedRedEntry::where('overspeedred_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('overspeedred_id: ' . $row_data['SN']); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
|
||||
// 如果 $row->violationcode 是 4310240 4310241 4310242 才執行的條件 |
||||
if (in_array($row_data['RuleId'], ['4310240', '4310241', '4310242'])) { |
||||
$row_data['RuleId'] = '4340068'; |
||||
try { |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/X/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
if(json_decode($resp, true)['Message'] == '新增完成'){ |
||||
OverSpeedRedEntry2::where('overspeedred_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 1]); |
||||
} |
||||
else{ |
||||
OverSpeedRedEntry2::where('overspeedred_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
OverSpeedRedEntry2::where('overspeedred_id', $row_data['SN'])->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('處車主 overspeedred_id: ' . $row_data['SN']); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
Log::notice('闖紅燈超速入案-資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
// 送出佐證圖片 |
||||
public static function overspeedred_entry_post_img() |
||||
{ |
||||
$re_arr = []; |
||||
$data = OverSpeedRedEntry::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(20)) |
||||
// ->whereIn('overspeedred_id', $re_arr) |
||||
->get(); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
try { |
||||
// 使用 intervention/image 將檔案壓縮至500K以下 |
||||
// 將圖片轉換為 base64 格式 不儲存 |
||||
|
||||
$img = Image::read(public_path(str_replace('*', '/', $row_data->photo))); |
||||
// if ($width > $height) then width = 720, height = 720 * $height / $width |
||||
// if ($height > $width) then height = 480, width = 480 * $width / $height |
||||
$width = $img->width(); |
||||
$height = $img->height(); |
||||
|
||||
if ($width > $height) { |
||||
$img->resize(2560, 2560 * $height / $width); |
||||
} else { |
||||
$img->resize(1440 * $width / $height, 1440); |
||||
} |
||||
$base64 = base64_encode($img->encode()); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('overspeedred_id: ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
$data2 = OverSpeedRedEntry2::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(20)) |
||||
// ->whereIn('overspeedred_id', $re_arr) |
||||
->get(); |
||||
if (count($data2) > 0) { |
||||
foreach ($data2 as $row_data) { |
||||
try { |
||||
// 使用 intervention/image 將檔案壓縮至500K以下 |
||||
// 將圖片轉換為 base64 格式 不儲存 |
||||
|
||||
$img = Image::read(public_path(str_replace('*', '/', $row_data->photo))); |
||||
// if ($width > $height) then width = 720, height = 720 * $height / $width |
||||
// if ($height > $width) then height = 480, width = 480 * $width / $height |
||||
$width = $img->width(); |
||||
$height = $img->height(); |
||||
|
||||
if ($width > $height) { |
||||
$img->resize(2560, 2560 * $height / $width); |
||||
} else { |
||||
$img->resize(1440 * $width / $height, 1440); |
||||
} |
||||
$base64 = base64_encode($img->encode()); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('處車主 overspeedred_id: ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
Log::notice('闖紅燈超速入案-佐證資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
#endregion |
||||
} |
@ -0,0 +1,215 @@
@@ -0,0 +1,215 @@
|
||||
<?php |
||||
|
||||
namespace App\Class; |
||||
use App\Models\Interval; |
||||
use App\Models\IntervalEntry; |
||||
use App\Models\User; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Illuminate\Support\Facades\Storage; |
||||
use Intervention\Image\Laravel\Facades\Image; |
||||
use GuzzleHttp\Client; |
||||
use GuzzleHttp\Exception\RequestException; |
||||
|
||||
// 入案專用 class |
||||
class ItlEntry |
||||
{ |
||||
#region 區間入案 |
||||
public static function interval_entry($days = 7) |
||||
{ |
||||
$records = Interval::query(); |
||||
$records->where('processcheck', 1); |
||||
$records->where('postcheck', 0); |
||||
$records->whereNotNull('violationcode'); |
||||
$records->whereNotNull('jsoncheck'); |
||||
// $records->where('starttime', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records->where(DB::Raw('date(start_time)'), '>=', '2025-01-01'); |
||||
|
||||
$data = $records->select('id as interval_id', 'merge_picture as photo')->get()->toArray(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
unset($row['law_type']); |
||||
$values[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
// dd($values); |
||||
if (count($values) > 0) { |
||||
DB::transaction(function () use ($values, $records) { |
||||
// 在這裡執行需要交易的資料庫操作,例如新增、修改、刪除等等 |
||||
DB::insert('INSERT IGNORE INTO interval_entry (interval_id, photo) VALUES' . implode(',', $values)); |
||||
$records->update(['postcheck' => 1]); |
||||
}); |
||||
} |
||||
Log::channel('entry')->notice('區間入案-資料收集 近' . $days . '天,共' . count($values) . '筆'); |
||||
} |
||||
// 取得要處理的資料 |
||||
public static function get_interval_entry_data($days = 1, $status = [0]) |
||||
{ |
||||
$ids = IntervalEntry::whereIn('status', $status)->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays($days))->pluck('interval_id'); |
||||
$data = Interval::whereIn('id', $ids)->get(); |
||||
// Log::channel('entry')->notice($ids); |
||||
// Log::channel('entry')->notice($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$s_time = $row->start_time; |
||||
$s_date = Carbon::parse($s_time)->toDateString(); |
||||
$s_twYear = Carbon::parse($s_date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$s_twDate = $s_twYear . Carbon::parse($s_date)->format('md'); // 將民國年與日期合併 |
||||
$s_time = Carbon::parse($s_time)->format('His'); |
||||
|
||||
$e_time = $row->end_time; |
||||
$e_date = Carbon::parse($e_time)->toDateString(); |
||||
$e_twYear = Carbon::parse($e_date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$e_twDate = $e_twYear . Carbon::parse($e_date)->format('md'); // 將民國年與日期合併 |
||||
$e_time = Carbon::parse($e_time)->format('His'); |
||||
|
||||
$cartype = $row->cartype; |
||||
if ($row->cartype == '98') { |
||||
$cartype = 1; |
||||
} else if ($row->cartype == '99') { |
||||
$cartype = 3; |
||||
} else{ |
||||
$cartype = $row->cartype; |
||||
} |
||||
$row_data = [ |
||||
'datatime' => $row->start_time, |
||||
'SN' => $row->id, |
||||
'ViolationDate' => $e_twDate, |
||||
'ViolationTime' => $e_time, |
||||
'UnitID' => User::where('account', $row->jsoncheck)->first()->leader, |
||||
'PoliceName' => User::where('account', $row->jsoncheck)->first()->name, |
||||
'LicensePlate' => $row->carnumber, |
||||
'VehicleType' => $cartype, |
||||
'RuleId' => $row->violationcode, |
||||
'Road' => $row->location, |
||||
'Speed' => intval(floor($row->speed)), |
||||
'LimitSpeed' => intval(floor($row->limit_speed)), |
||||
'Distance' => $row->distance, |
||||
'Duration' => $row->diff, |
||||
'InDate' => $s_twDate, |
||||
'InTime' => $s_time, |
||||
'OutDate' => $e_twDate, |
||||
'OutTime' => $e_time, |
||||
]; |
||||
array_push($values, $row_data); |
||||
} |
||||
return $values; |
||||
|
||||
} |
||||
// 本機建檔備存 |
||||
public static function interval_entry_local($data = []) |
||||
{ |
||||
|
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$datetime = $row_data['datatime']; |
||||
unset($row_data['datatime']); |
||||
// 存放檔案的目錄路徑 |
||||
$directory = 'entry/interval/' . Carbon::now('Asia/Taipei')->format('Ymd'); |
||||
// 如果目錄不存在,則建立該目錄 |
||||
Storage::makeDirectory($directory); |
||||
// 將資料轉換為 JSON 格式 |
||||
$jsonData = json_encode($row_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); |
||||
// 將 JSON 資料寫入檔案 |
||||
$row_date = Carbon::parse($datetime)->format('Ymd_His'); |
||||
$fileName = 'ITL_' . $row_date . '_' . $row_data['SN'] . '.json'; |
||||
Storage::put($directory . "/$fileName", $jsonData); |
||||
} |
||||
} |
||||
Log::channel('entry')->notice('區間入案-資料組合備存,共' . count($data) . '筆'); |
||||
} |
||||
// 送出入案,紀錄回傳no |
||||
public static function interval_entry_post($data = []) |
||||
{ |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$interval_id = $row_data['SN']; |
||||
$row_data['SN'] = 'ITL'.$row_data['SN']; |
||||
unset($row_data['datatime']); |
||||
try { |
||||
// Log::channel('entry')->notice($row_data); |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/X/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
if(json_decode($resp, true)['Message'] == '新增完成'){ |
||||
IntervalEntry::where('interval_id', $interval_id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 1]); |
||||
}else{ |
||||
IntervalEntry::where('interval_id', $interval_id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
IntervalEntry::where('interval_id', $interval_id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('interval_id: ' . $interval_id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::channel('entry')->notice('區間入案-資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
// 送出佐證圖片 |
||||
public static function interval_entry_post_img() |
||||
{ |
||||
$re_arr = []; |
||||
$data = IntervalEntry::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(10)) |
||||
// ->whereIn('interval_id', $re_arr) |
||||
->get(); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
try { |
||||
// 使用 intervention/image 將檔案壓縮至500K以下 |
||||
// 將圖片轉換為 base64 格式 不儲存 |
||||
// Log::channel('entry')->notice($row_data->photo); |
||||
$img = Image::read(public_path('ParsingFiles/interval/' . str_replace('*', '/', $row_data->photo))); |
||||
// if ($width > $height) then width = 720, height = 720 * $height / $width |
||||
// if ($height > $width) then height = 480, width = 480 * $width / $height |
||||
$width = $img->width(); |
||||
$height = $img->height(); |
||||
|
||||
if ($width > $height) { |
||||
$img->resize(1920, 1920 * $height / $width); |
||||
} |
||||
$base64 = base64_encode($img->encode()); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
// Log::channel('entry')->notice($post_data); |
||||
$client = new Client(['base_uri' => 'http://trafficfine.typd.gov.tw:88']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::channel('entry')->notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('interval_id(postimg): ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::channel('entry')->notice('區間入案-佐證資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
#endregion |
||||
} |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
<?php |
||||
namespace App\Class; |
||||
|
||||
class LineNotify |
||||
{ |
||||
public static function send($message) |
||||
{ |
||||
$token = 'VAClbvaOmpmnIcmDrVVVkDLS51BWaZ6JQ7udePUSY8J'; |
||||
$header = array( |
||||
'Content-Type: multipart/form-data', |
||||
'Authorization: Bearer ' . $token |
||||
); |
||||
$message = array( |
||||
'message' => $message |
||||
); |
||||
$ch = curl_init(); |
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $header); |
||||
curl_setopt($ch, CURLOPT_URL, 'https://notify-api.line.me/api/notify'); |
||||
curl_setopt($ch, CURLOPT_POST, true); |
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $message); |
||||
|
||||
$result = curl_exec($ch); |
||||
curl_close($ch); |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
<?php |
||||
namespace App\Class; |
||||
|
||||
use App\Models\UserLog; |
||||
use Illuminate\Support\Str; |
||||
|
||||
class LogWriter |
||||
{ |
||||
|
||||
public static function writeLog($data,$guard = null) |
||||
{ |
||||
$log = new UserLog(); |
||||
$log->user_id = auth($guard)->user()->id; |
||||
$log->user_name = auth($guard)->user()->name; |
||||
$log->action = $data['action']; |
||||
$log->action_detail = $data['action_detail']; |
||||
$log->ip = $data['ip']; |
||||
$log->remark = $data['remark'] ?? null; |
||||
$log->carnumber = $data['carnumber'] ?? null; |
||||
$log->location = $data['location'] ?? null; |
||||
$log->save(); |
||||
} |
||||
} |
@ -0,0 +1,620 @@
@@ -0,0 +1,620 @@
|
||||
<?php |
||||
|
||||
namespace App\Classes; |
||||
|
||||
use App\TwoStage; |
||||
use App\TwostageEntry; |
||||
use App\UpdateCarNumber; |
||||
use App\ViolationParkingEntry; |
||||
use App\IntervalDataBack; |
||||
use App\IntervalEntry; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Illuminate\Support\Facades\Storage; |
||||
use Intervention\Image\Facades\Image; |
||||
use GuzzleHttp\Client; |
||||
use GuzzleHttp\Exception\RequestException; |
||||
|
||||
// 入案專用 class |
||||
class NewEntry |
||||
{ |
||||
|
||||
#region 路口多功能科技執法入案 |
||||
public static function twostage_entry($days = 7) |
||||
{ |
||||
$records = TwoStage::query(); |
||||
$records->where('processcheck', 1); |
||||
$records->where('postcheck', 0); |
||||
$records->whereNotNull('violationcode'); |
||||
// $records->where('datatime', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records->where('datatime', '>', '2025-01-15'); |
||||
$data = $records->select('id as twostage_id', 'picture as photo')->get()->toArray(); |
||||
|
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$values[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
// dd($values); |
||||
if (count($values) > 0) { |
||||
DB::transaction(function () use ($values, $records) { |
||||
// 在這裡執行需要交易的資料庫操作,例如新增、修改、刪除等等 |
||||
DB::insert('INSERT IGNORE INTO twostage_entry (twostage_id, photo) VALUES' . implode(',', $values)); |
||||
$records->update(['postcheck' => 1]); |
||||
}); |
||||
} |
||||
// DB::table('twostage_entry')->insertOrIgnore($data); |
||||
Log::notice('路口多功能入案-資料收集 近' . $days . '天,共' . count($values) . '筆'); |
||||
} |
||||
// 取得要處理的資料 |
||||
public static function get_twostage_entry_data($days = 1, $status = [0]) |
||||
{ |
||||
$ids = TwostageEntry::whereIn('status', $status) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays($days)) |
||||
// ->where('created_at', '<', Carbon::now('Asia/Taipei')->subDays(2)) |
||||
->pluck('twostage_id'); |
||||
$data = Twostage::whereIn('id', $ids)->get(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$datetime = $row->datatime; |
||||
$date = Carbon::parse($datetime)->toDateString(); |
||||
$twYear = Carbon::parse($date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$twDate = $twYear . Carbon::parse($date)->format('md'); // 將民國年與日期合併 |
||||
$time = Carbon::parse($datetime)->format('His'); |
||||
|
||||
$row_data = [ |
||||
'datatime' => $row->datatime, |
||||
'SN' => $row->id, |
||||
'ViolationDate' => $twDate, |
||||
'ViolationTime' => $time, |
||||
// 'UnitId' => DB::table('operator')->where('account', $row->jsoncheck)->first()->leader, |
||||
'UnitId' => 'A000', |
||||
'PoliceName' => DB::table('operator')->where('account', $row->jsoncheck)->first()->name, |
||||
'LicensePlate' => $row->carnumber, |
||||
'VehicleType' => $row->cartype, |
||||
'RuleId' => $row->violationcode, |
||||
'Road' => $row->location, |
||||
]; |
||||
|
||||
// if (isset($row->violationmsg)) { |
||||
// $row_data['PunishFACT'] = $row->violationmsg; |
||||
// } |
||||
array_push($values, $row_data); |
||||
} |
||||
return $values; |
||||
} |
||||
// 本機建檔備存 |
||||
public static function twostage_entry_local($data = []) |
||||
{ |
||||
|
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$datetime = $row_data['datatime']; |
||||
unset($row_data['datatime']); |
||||
// unset($row_data['photo']); |
||||
// 存放檔案的目錄路徑 |
||||
$directory = 'entry/twosage/' . Carbon::now('Asia/Taipei')->format('Ymd'); |
||||
// 如果目錄不存在,則建立該目錄 |
||||
Storage::makeDirectory($directory); |
||||
// 將資料轉換為 JSON 格式 |
||||
$jsonData = json_encode($row_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); |
||||
// 將 JSON 資料寫入檔案 |
||||
$row_date = Carbon::parse($datetime)->format('Ymd_His'); |
||||
$fileName = 'Ts_' . $row_date . '_' . $row_data['SN'] . '.json'; |
||||
Storage::put($directory . "/$fileName", $jsonData); |
||||
} |
||||
} |
||||
Log::notice('路口多功能入案-資料組合備存,共' . count($data) . '筆'); |
||||
} |
||||
// 送出入案,紀錄回傳no |
||||
public static function twostage_entry_post($data = []) |
||||
{ |
||||
set_time_limit(0); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
unset($row_data['datatime']); |
||||
$id = $row_data['SN']; |
||||
$row_data['SN'] = 'TS' . $row_data['SN']; |
||||
Log::notice($row_data); |
||||
try { |
||||
// $client = new Client(['base_uri' => 'http://220.128.232.102:5000']); |
||||
$response = $client->request('POST', '/HX/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
if(json_decode($resp, true)['Message'] == '新增完成'){ |
||||
TwostageEntry::where('twostage_id', $id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 1]); |
||||
}else{ |
||||
TwostageEntry::where('twostage_id', $id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
TwostageEntry::where('twostage_id', $id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('twostage_id: ' . $id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::notice('路口多功能入案-資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
public static function twostage_entry_post_img() |
||||
{ |
||||
$re_arr = []; |
||||
$data = TwostageEntry::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(3)) |
||||
// ->whereIn('multisys_id', $re_arr) |
||||
->get(); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
|
||||
try { |
||||
// 取得圖片檔案路徑 |
||||
$filePath = storage_path('app/ParsingFiles/' . str_replace('*', '/', $row_data['photo'])); |
||||
// 使用 Intervention/Image 套件進行壓縮 |
||||
$image = Image::make($filePath); |
||||
|
||||
// 確認圖片寬度是否超過 1920 |
||||
if ($image->getWidth() > 1920) { |
||||
// 計算等比例縮放後的寬度和高度 |
||||
$width = 1920; |
||||
$height = round($image->getHeight() * $width / $image->getWidth()); |
||||
|
||||
// 縮放圖片 |
||||
$image->resize($width, $height, function ($constraint) { |
||||
$constraint->aspectRatio(); |
||||
}); |
||||
} |
||||
|
||||
// 壓縮圖片 |
||||
$image->encode('jpg', 40); |
||||
// 將圖片轉換為 base64 編碼 |
||||
$base64 = base64_encode($image->encoded); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
Log::notice($post_data); |
||||
// $client = new Client(['base_uri' => 'http://220.128.232.102:5000']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('twostage_id: ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::notice('路口多功能入案-佐證資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
#endregion |
||||
|
||||
#region 違規停車入案 |
||||
public static function violationparking_entry($days = 7) |
||||
{ |
||||
$records = UpdateCarNumber::query(); |
||||
$records->where('processcheck', 1); |
||||
$records->where('postcheck', 0); |
||||
$records->whereNotNull('violationcode'); |
||||
// $records->where('time', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records->where('time', '>', '2025-01-15'); |
||||
|
||||
$data = $records->select('id as violationparking_id', 'picture as photo')->get()->toArray(); |
||||
|
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$values[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
// dd($values); |
||||
if (count($values) > 0) { |
||||
DB::transaction(function () use ($values, $records) { |
||||
// 在這裡執行需要交易的資料庫操作,例如新增、修改、刪除等等 |
||||
DB::insert('INSERT IGNORE INTO violationparking_entry (violationparking_id, photo) VALUES' . implode(',', $values)); |
||||
$records->update(['postcheck' => 1]); |
||||
}); |
||||
} |
||||
Log::notice('違停入案-資料收集 近' . $days . '天,共' . count($values) . '筆'); |
||||
} |
||||
// 取得要處理的資料 |
||||
public static function get_violationparking_entry_data($days = 1, $status = [0]) |
||||
{ |
||||
$ids = ViolationParkingEntry::whereIn('status', $status)->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays($days))->pluck('violationparking_id'); |
||||
$data = UpdateCarNumber::whereIn('id', $ids)->get(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$datetime = $row->datatime; |
||||
$date = Carbon::parse($datetime)->toDateString(); |
||||
$twYear = Carbon::parse($date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$twDate = $twYear . Carbon::parse($date)->format('md'); // 將民國年與日期合併 |
||||
$time = Carbon::parse($datetime)->format('His'); |
||||
|
||||
$row_data = [ |
||||
'datatime' => $row->time, |
||||
'SN' => $row->id, |
||||
'ViolationDate' => $twDate, |
||||
'ViolationTime' => $time, |
||||
// 'UnitId' => DB::table('operator')->where('account', $row->jsoncheck)->first()->leader, |
||||
'UnitId' => 'A000', |
||||
'PoliceName' => DB::table('operator')->where('account', $row->jsoncheck)->first()->name, |
||||
'LicensePlate' => $row->carnumber, |
||||
'VehicleType' => $row->cartype, |
||||
'RuleId' => $row->violationcode, |
||||
'Road' => $row->deviceplace, |
||||
]; |
||||
array_push($values, $row_data); |
||||
} |
||||
return $values; |
||||
} |
||||
// 組合資料並建檔備存 |
||||
public static function violationparking_entry_local($data = []) |
||||
{ |
||||
|
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$datetime = $row_data['datatime']; |
||||
unset($row_data['datatime']); |
||||
// 存放檔案的目錄路徑 |
||||
$directory = 'entry/violationparking/' . Carbon::now('Asia/Taipei')->format('Ymd'); |
||||
// 如果目錄不存在,則建立該目錄 |
||||
Storage::makeDirectory($directory); |
||||
// 將資料轉換為 JSON 格式 |
||||
$jsonData = json_encode($row_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); |
||||
// 將 JSON 資料寫入檔案 |
||||
$row_date = Carbon::parse($datetime)->format('Ymd_His'); |
||||
$fileName = 'Vpk_' . $row_date . '_' . $row_data['SN'] . '.json'; |
||||
Storage::put($directory . "/$fileName", $jsonData); |
||||
} |
||||
} |
||||
Log::notice('違停入案-資料組合備存,共' . count($data) . '筆'); |
||||
} |
||||
|
||||
public static function violationparking_entry_post($data = []) |
||||
{ |
||||
set_time_limit(0); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
unset($row_data['datatime']); |
||||
$id = $row_data['SN']; |
||||
$row_data['SN'] = 'TS' . $row_data['SN']; |
||||
Log::notice($row_data); |
||||
try { |
||||
// $client = new Client(['base_uri' => 'http://220.128.232.102:5000']); |
||||
$response = $client->request('POST', '/HX/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
if(json_decode($resp, true)['Message'] == '新增完成'){ |
||||
ViolationParkingEntry::where('violationparking_id', $id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 1]); |
||||
}else{ |
||||
ViolationParkingEntry::where('violationparking_id', $id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
$no = json_decode($resp, true)['No']; |
||||
ViolationParkingEntry::where('violationparking_id', $id)->first()->update(['no' => $no, 'response' => $resp, 'status' => 3]); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('violationparking_id: ' . $id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::notice('違停入案-資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
|
||||
public static function violationparking_entry_post_img() |
||||
{ |
||||
$re_arr = []; |
||||
$data = ViolationParkingEntry::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(3)) |
||||
// ->whereIn('multisys_id', $re_arr) |
||||
->get(); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
|
||||
try { |
||||
// 取得圖片檔案路徑 |
||||
$filePath = storage_path('app/ParsingFiles/' . str_replace('*', '/', $row_data['photo'])); |
||||
// 使用 Intervention/Image 套件進行壓縮 |
||||
$image = Image::make($filePath); |
||||
|
||||
// 確認圖片寬度是否超過 1920 |
||||
if ($image->getWidth() > 1920) { |
||||
// 計算等比例縮放後的寬度和高度 |
||||
$width = 1920; |
||||
$height = round($image->getHeight() * $width / $image->getWidth()); |
||||
|
||||
// 縮放圖片 |
||||
$image->resize($width, $height, function ($constraint) { |
||||
$constraint->aspectRatio(); |
||||
}); |
||||
} |
||||
|
||||
// 壓縮圖片 |
||||
$image->encode('jpg', 40); |
||||
// 將圖片轉換為 base64 編碼 |
||||
$base64 = base64_encode($image->encoded); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
Log::notice($post_data); |
||||
// $client = new Client(['base_uri' => 'http://220.128.232.102:5000']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('violationparking_id: ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::notice('違停入案-佐證資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
#endregion |
||||
|
||||
#region 區間入案 |
||||
public static function interval_entry($days = 7) |
||||
{ |
||||
$records = IntervalDataBack::query(); |
||||
// $records->where('datacheck', 1); |
||||
$records->where('postcheck', 0); |
||||
$records->whereNotNull('viocode'); |
||||
$records->whereNotNull('jsoncheck'); |
||||
// $records->where('starttime', '>', Carbon::now('Asia/Taipei')->subDays($days)); |
||||
$records->where('starttime', '>', '2025-01-15'); |
||||
|
||||
$data = $records->select('id as intervaldataback_id', 'startpicture', 'endpicture')->get()->toArray(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$row['photo'] = str_replace('-merge.jpg', '~', str_replace('Merge', 'Interval', $row['startpicture'])) . str_replace('-merge.jpg', '-interval.png', explode('*', $row['endpicture'])[4]); |
||||
unset($row['startpicture']); |
||||
unset($row['endpicture']); |
||||
$values[] = '(\'' . implode('\',\'', $row) . '\')'; |
||||
} |
||||
// dd($values); |
||||
if (count($values) > 0) { |
||||
DB::transaction(function () use ($values, $records) { |
||||
// 在這裡執行需要交易的資料庫操作,例如新增、修改、刪除等等 |
||||
DB::insert('INSERT IGNORE INTO interval_entry (intervaldataback_id, photo) VALUES' . implode(',', $values)); |
||||
$records->update(['postcheck' => 1]); |
||||
}); |
||||
} |
||||
Log::notice('區間入案-資料收集 近' . $days . '天,共' . count($values) . '筆'); |
||||
} |
||||
|
||||
public static function get_interval_entry_data($days = 1, $status = [0]) |
||||
{ |
||||
$ids = IntervalEntry::whereIn('status', $status)->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays($days))->pluck('intervaldataback_id'); |
||||
$data = IntervalDataBack::whereIn('id', $ids)->get(); |
||||
// dd($data); |
||||
$values = []; |
||||
foreach ($data as $row) { |
||||
$s_time = $row->start_time; |
||||
$s_date = Carbon::parse($s_time)->toDateString(); |
||||
$s_twYear = Carbon::parse($s_date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$s_twDate = $s_twYear . Carbon::parse($s_date)->format('md'); // 將民國年與日期合併 |
||||
$s_time = Carbon::parse($s_time)->format('His'); |
||||
|
||||
$e_time = $row->end_time; |
||||
$e_date = Carbon::parse($e_time)->toDateString(); |
||||
$e_twYear = Carbon::parse($e_date)->format('Y') - 1911; // 取得民國年,即西元年減去1911 |
||||
$e_twDate = $e_twYear . Carbon::parse($e_date)->format('md'); // 將民國年與日期合併 |
||||
$e_time = Carbon::parse($e_time)->format('His'); |
||||
|
||||
$cartype = $row->cartype; |
||||
if ($row->carkind == '汽車' || $row->carkind == '大型車') { |
||||
$cartype = 1; |
||||
} else if ($row->carkind == '機車' || $row->carkind == '大型重型機車') { |
||||
$cartype = 3; |
||||
} else { |
||||
continue; |
||||
} |
||||
$row_data = [ |
||||
'datatime' => $row->start_time, |
||||
'SN' => $row->id, |
||||
'ViolationDate' => $e_twDate, |
||||
'ViolationTime' => $e_time, |
||||
'UnitID' => 'A000', |
||||
'PoliceName' => DB::table('operator')->where('account', $row->jsoncheck)->first()->name ?? '', |
||||
'LicensePlate' => $row->carnumber, |
||||
'VehicleType' => $cartype, |
||||
'RuleId' => $row->violationcode, |
||||
'Road' => $row->location, |
||||
'Speed' => intval(floor($row->speed)), |
||||
'LimitSpeed' => intval(floor($row->limit_speed)), |
||||
'Distance' => $row->distance, |
||||
'Duration' => $row->diff, |
||||
'InDate' => $s_twDate, |
||||
'InTime' => $s_time, |
||||
'OutDate' => $e_twDate, |
||||
'OutTime' => $e_time, |
||||
]; |
||||
array_push($values, $row_data); |
||||
} |
||||
|
||||
return $values; |
||||
} |
||||
|
||||
// 組合資料並建檔備存 |
||||
public static function interval_entry_local($data = []) |
||||
{ |
||||
|
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
$datetime = $row_data['datatime']; |
||||
unset($row_data['datatime']); |
||||
// 存放檔案的目錄路徑 |
||||
$directory = 'entry/interval/' . Carbon::now('Asia/Taipei')->format('Ymd'); |
||||
// 如果目錄不存在,則建立該目錄 |
||||
Storage::makeDirectory($directory); |
||||
// 將資料轉換為 JSON 格式 |
||||
$jsonData = json_encode($row_data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); |
||||
// 將 JSON 資料寫入檔案 |
||||
$row_date = Carbon::parse($datetime)->format('Ymd_His'); |
||||
$fileName = 'ITL_' . $row_date . '_' . $row_data['SN'] . '.json'; |
||||
Storage::put($directory . "/$fileName", $jsonData); |
||||
} |
||||
} |
||||
Log::notice('區間入案-資料組合備存,共' . count($data) . '筆'); |
||||
} |
||||
|
||||
public static function interval_entry_post($data = []) |
||||
{ |
||||
set_time_limit(0); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
unset($row_data['datatime']); |
||||
$id = $row_data['SN']; |
||||
$row_data['SN'] = 'ITL' . $row_data['SN']; |
||||
Log::notice($row_data); |
||||
|
||||
try { |
||||
// $client = new Client(['base_uri' => 'http://220.128.232.102:8000']); |
||||
$response = $client->request('POST', '/HX/sunhouse', ['form_params' => $row_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$resp = $response->getBody(); |
||||
try { |
||||
$res = json_decode($resp, true); |
||||
if ($res['code'] == "200") { |
||||
IntervalEntry::where('intervaldataback_id', $id)->first()->update(['response' => $resp, 'status' => 1]); |
||||
} else { |
||||
IntervalEntry::where('intervaldataback_id', $id)->first()->update(['response' => $resp, 'status' => 4]); |
||||
Log::error('intervaldataback_id: ' . $id . "雖然response->getStatusCode() == 200,但不成功"); |
||||
} |
||||
} catch (\Throwable $th) { |
||||
IntervalEntry::where('intervaldataback_id', $id)->first()->update(['response' => $resp, 'status' => 5]); |
||||
Log::error('intervaldataback_id: ' . $id); |
||||
Log::error($th); |
||||
} |
||||
} else { |
||||
$resp = $response->getBody(); |
||||
IntervalEntry::where('intervaldataback_id', $id)->first()->update(['response' => $resp, 'status' => 6]); |
||||
Log::error('intervaldataback_id: ' . $id . "response->getStatusCode() != 200"); |
||||
} |
||||
// if ($response->getStatusCode() == "200") { |
||||
// $resp = $response->getBody(); |
||||
// IntervalEntry::where('intervaldataback_id', $id)->first()->update(['response' => $resp, 'status' => 1]); |
||||
// } else { |
||||
// $resp = $response->getBody(); |
||||
// IntervalEntry::where('intervaldataback_id', $id)->first()->update(['response' => $resp, 'status' => 3]); |
||||
// } |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('intervaldataback_id: ' . $id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
// break; |
||||
} |
||||
} |
||||
|
||||
Log::notice('區間入案-資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
// 送出佐證圖片 |
||||
public static function interval_entry_post_img() |
||||
{ |
||||
$re_arr = []; |
||||
$data = IntervalEntry::where('status', 1) |
||||
->where('created_at', '>', Carbon::now('Asia/Taipei')->subDays(10)) |
||||
// ->whereIn('interval_id', $re_arr) |
||||
->get(); |
||||
if (count($data) > 0) { |
||||
foreach ($data as $row_data) { |
||||
try { |
||||
// 使用 intervention/image 將檔案壓縮至500K以下 |
||||
// 將圖片轉換為 base64 格式 不儲存 |
||||
$image = Image::make(public_path('ParsingFiles/interval/' . str_replace('*', '/', $row_data->photo))); |
||||
|
||||
// 確認圖片寬度是否超過 1920 |
||||
if ($image->getWidth() > 1920) { |
||||
// 計算等比例縮放後的寬度和高度 |
||||
$width = 1920; |
||||
$height = round($image->getHeight() * $width / $image->getWidth()); |
||||
|
||||
// 縮放圖片 |
||||
$image->resize($width, $height, function ($constraint) { |
||||
$constraint->aspectRatio(); |
||||
}); |
||||
} |
||||
|
||||
// 壓縮圖片 |
||||
$image->encode('jpg', 40); |
||||
// 將圖片轉換為 base64 編碼 |
||||
$base64 = base64_encode($image->encoded); |
||||
$post_data = [ |
||||
'data' => $base64 |
||||
]; |
||||
// Log::channel('entry')->notice($post_data); |
||||
$client = new Client(['base_uri' => 'http://220.128.232.102:8000']); |
||||
$response = $client->request('POST', '/' . $row_data->no, ['form_params' => $post_data, 'connect_timeout' => 10]); |
||||
// Here the code for successful request |
||||
if ($response->getStatusCode() == "200") { |
||||
$msg = json_decode($response->getBody(), true)['Message']; |
||||
if ($msg == '上傳成功') { |
||||
$row_data->status = 2; |
||||
$row_data->save(); |
||||
Log::channel('entry')->notice($row_data->no . "-" . $msg); |
||||
} else { |
||||
$row_data->status = 4; |
||||
$row_data->save(); |
||||
Log::error($row_data->no . "-" . $msg); |
||||
} |
||||
} else { |
||||
$row_data->status = 3; |
||||
$row_data->save(); |
||||
} |
||||
} catch (\Exception $e) { |
||||
// There was another exception. |
||||
Log::error('intervaldataback_id(postimg): ' . $row_data->id); |
||||
Log::error($e->getMessage()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Log::channel('entry')->notice('區間入案-佐證資料送往入案系統,共' . count($data) . '筆'); |
||||
} |
||||
#endregion |
||||
|
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
<?php |
||||
namespace App\Class; |
||||
|
||||
class StaticData |
||||
{ |
||||
// 單位 unit |
||||
public static $unit = [ |
||||
'警察局' => '警察局', |
||||
'交通警察大隊' => '交通警察大隊', |
||||
'執法組' => '執法組', |
||||
'交通分隊' => '交通分隊', |
||||
'廠商維運' => '廠商維運', |
||||
]; |
||||
|
||||
// 不舉發理由(通用) |
||||
public static $reason = [ |
||||
'車牌模糊' => '車牌模糊', |
||||
'車牌無法辨識' => '車牌無法辨識', |
||||
'車種無法識別' => '車種無法識別', |
||||
'沒有車牌' => '沒有車牌', |
||||
'照片採證不足' => '照片採證不足', |
||||
'警車執勤' => '警車執勤', |
||||
'重複舉發' => '重複舉發', |
||||
'違規事實不明確' => '違規事實不明確', |
||||
'執行公務' => '執行公務', |
||||
]; |
||||
|
||||
// 不舉發理由(違規停車) |
||||
public static $reason_vpk = [ |
||||
'黃線20點以後可以停車' => '黃線20點以後可以停車', |
||||
'卸貨車格停車' => '卸貨車格停車', |
||||
'未停車滿3分鐘' => '未停車滿3分鐘', |
||||
'車種停放吻合(計乘車停放計乘車格,自用車停放在自用車格)' => '車種停放吻合(計乘車停放計乘車格,自用車停放在自用車格)', |
||||
'公務車輛於執行任務時,其臨時停車及停車地點得不受前二條之限制' => '公務車輛於執行任務時,其臨時停車及停車地點得不受前二條之限制', |
||||
]; |
||||
|
||||
// 不舉發理由(路口多功能) |
||||
public static $reason_ms = [ |
||||
'1.車牌模糊(遮蔽、過暗、過度曝光)無法辨識。' => '1.車牌模糊(遮蔽、過暗、過度曝光)無法辨識。', |
||||
'2.多車同時進入照相範圍無法辨識違規車道。' => '2.多車同時進入照相範圍無法辨識違規車道。', |
||||
'3.雷達感應速度偵測異常。' => '3.雷達感應速度偵測異常。', |
||||
'4.車輛廠牌顏色與車牌登記不符。' => '4.車輛廠牌顏色與車牌登記不符。', |
||||
'5.交通號誌燈異常無法辨識違規樣態。' => '5.交通號誌燈異常無法辨識違規樣態。', |
||||
'6.重複照片。' => '6.重複照片。', |
||||
'7.相片異常。' => '7.相片異常。', |
||||
'8.檔案逾期。' => '8.檔案逾期。', |
||||
'9.公告尚未完成。' => '9.公告尚未完成。', |
||||
'10.無車牌。' => '10.無車牌。', |
||||
'11.工程、警用、救護重輛。' => '11.工程、警用、救護重輛。', |
||||
'12.主線道未開放。' => '12.主線道未開放。', |
||||
'13.非取締車種。' => '13.非取締車種。', |
||||
'14.緊急避難(禮讓救護車)。' => '14.緊急避難(禮讓救護車)。', |
||||
'15.不宜舉發' => '15.不宜舉發', |
||||
'16.違規類型判別錯誤' => '16.違規類型判別錯誤', |
||||
'17.違規車輛判別錯誤' => '17.違規車輛判別錯誤', |
||||
]; |
||||
|
||||
// 不舉發理由(區間) |
||||
public static $reason_itl = [ |
||||
]; |
||||
// 不舉發理由(超速) |
||||
public static $reason_osr = [ |
||||
'1.車牌模糊(遮蔽、過暗、過度曝光)無法辨識。' => '1.車牌模糊(遮蔽、過暗、過度曝光)無法辨識。', |
||||
'2.多車同時進入照相範圍無法辨識違規車道。' => '2.多車同時進入照相範圍無法辨識違規車道。', |
||||
'3.雷達感應速度偵測異常。' => '3.雷達感應速度偵測異常。', |
||||
'4.車輛廠牌顏色與車牌登記不符。' => '4.車輛廠牌顏色與車牌登記不符。', |
||||
'5.交通號誌燈異常無法辨識違規樣態。' => '5.交通號誌燈異常無法辨識違規樣態。', |
||||
'6.重複照片。' => '6.重複照片。', |
||||
'7.相片異常。' => '7.相片異常。', |
||||
'8.檔案逾期。' => '8.檔案逾期。', |
||||
'9.公告尚未完成。' => '9.公告尚未完成。', |
||||
'10.無車牌。' => '10.無車牌。', |
||||
'11.工程、警用、救護重輛。' => '11.工程、警用、救護重輛。', |
||||
'12.主線道未開放。' => '12.主線道未開放。', |
||||
'13.非取締車種。' => '13.非取締車種。', |
||||
'14.緊急避難(禮讓救護車)。' => '14.緊急避難(禮讓救護車)。', |
||||
'15.不宜舉發' => '15.不宜舉發', |
||||
'16.違規類型判別錯誤' => '16.違規類型判別錯誤', |
||||
'17.違規車輛判別錯誤' => '17.違規車輛判別錯誤', |
||||
]; |
||||
// 不舉發理由(闖紅) |
||||
public static $reason_red = [ |
||||
'1.車牌模糊(遮蔽、過暗、過度曝光)無法辨識。' => '1.車牌模糊(遮蔽、過暗、過度曝光)無法辨識。', |
||||
'2.多車同時進入照相範圍無法辨識違規車道。' => '2.多車同時進入照相範圍無法辨識違規車道。', |
||||
'3.雷達感應速度偵測異常。' => '3.雷達感應速度偵測異常。', |
||||
'4.車輛廠牌顏色與車牌登記不符。' => '4.車輛廠牌顏色與車牌登記不符。', |
||||
'5.交通號誌燈異常無法辨識違規樣態。' => '5.交通號誌燈異常無法辨識違規樣態。', |
||||
'6.重複照片。' => '6.重複照片。', |
||||
'7.相片異常。' => '7.相片異常。', |
||||
'8.檔案逾期。' => '8.檔案逾期。', |
||||
'9.公告尚未完成。' => '9.公告尚未完成。', |
||||
'10.無車牌。' => '10.無車牌。', |
||||
'11.工程、警用、救護重輛。' => '11.工程、警用、救護重輛。', |
||||
'12.主線道未開放。' => '12.主線道未開放。', |
||||
'13.非取締車種。' => '13.非取締車種。', |
||||
'14.緊急避難(禮讓救護車)。' => '14.緊急避難(禮讓救護車)。', |
||||
'15.不宜舉發' => '15.不宜舉發', |
||||
'16.違規類型判別錯誤' => '16.違規類型判別錯誤' |
||||
]; |
||||
|
||||
|
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
<?php |
||||
|
||||
namespace App\Console\Commands; |
||||
|
||||
use App\Classes\NewEntry; |
||||
use Illuminate\Console\Command; |
||||
use Illuminate\Support\Facades\Log; |
||||
|
||||
class EntryInterval extends Command |
||||
{ |
||||
/** |
||||
* The name and signature of the console command. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $signature = 'entry:interval'; |
||||
|
||||
/** |
||||
* The console command description. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $description = '區間入案'; |
||||
|
||||
/** |
||||
* Execute the console command. |
||||
*/ |
||||
public function handle() |
||||
{ |
||||
NewEntry::interval_entry(14); |
||||
$itl_data = NewEntry::get_interval_entry_data(10); |
||||
// Log::channel('entry')->notice($itl_data); |
||||
if(count($itl_data)> 0){ |
||||
NewEntry::interval_entry_local($itl_data); |
||||
NewEntry::interval_entry_post($itl_data); |
||||
} |
||||
NewEntry::interval_entry_post_img(); |
||||
} |
||||
} |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
<?php |
||||
|
||||
namespace App\Events; |
||||
|
||||
use Illuminate\Broadcasting\Channel; |
||||
use Illuminate\Broadcasting\InteractsWithSockets; |
||||
use Illuminate\Broadcasting\PresenceChannel; |
||||
use Illuminate\Broadcasting\PrivateChannel; |
||||
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; |
||||
use Illuminate\Foundation\Events\Dispatchable; |
||||
use Illuminate\Queue\SerializesModels; |
||||
|
||||
|
||||
class ExampleEvent implements ShouldBroadcast |
||||
{ |
||||
use Dispatchable, InteractsWithSockets, SerializesModels; |
||||
|
||||
/** |
||||
* Create a new event instance. |
||||
*/ |
||||
public $message; |
||||
public $token; |
||||
public function __construct($message, $token = null) |
||||
{ |
||||
$this->message = $message; |
||||
$this->token = $token ?? null; |
||||
} |
||||
|
||||
/** |
||||
* Get the channels the event should broadcast on. |
||||
* |
||||
* @return array<int, \Illuminate\Broadcasting\Channel> |
||||
*/ |
||||
public function broadcastOn() |
||||
{ |
||||
// return new Channel('test-channel'); |
||||
if ($this->token) { |
||||
return new PrivateChannel('test-private.' . $this->token); |
||||
} |
||||
return [ |
||||
// 'test-event', |
||||
new Channel('test-channel'), |
||||
new PrivateChannel('test-private'), |
||||
]; |
||||
} |
||||
// public function broadcastWith() |
||||
// { |
||||
// return [ |
||||
// 'data' => 'key' |
||||
// ]; |
||||
// } |
||||
} |
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
<?php |
||||
|
||||
namespace App\Exports; |
||||
|
||||
use Maatwebsite\Excel\Concerns\FromArray; |
||||
use Maatwebsite\Excel\Concerns\WithHeadings; |
||||
use Maatwebsite\Excel\Concerns\WithCustomStartCell; |
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; |
||||
|
||||
class ArrayExport implements FromArray, WithHeadings, WithCustomStartCell |
||||
{ |
||||
protected $data; |
||||
protected $headings; |
||||
protected $startCell; |
||||
|
||||
public function __construct(array $data, array $headings = null, string $startCell = 'A1') |
||||
{ |
||||
$this->data = $data; |
||||
$this->headings = $headings; |
||||
$this->startCell = $startCell; |
||||
} |
||||
|
||||
public function array(): array |
||||
{ |
||||
return $this->data; |
||||
} |
||||
|
||||
public function headings(): array |
||||
{ |
||||
// 定義標題列 |
||||
return $this->headings ?? array_keys($this->data[0]); |
||||
} |
||||
|
||||
public function startCell(): string |
||||
{ |
||||
return $this->startCell ?? 'A1'; |
||||
} |
||||
} |
@ -0,0 +1,147 @@
@@ -0,0 +1,147 @@
|
||||
<?php |
||||
|
||||
namespace App\Exports; |
||||
|
||||
use Maatwebsite\Excel\Concerns\FromArray; |
||||
use Maatwebsite\Excel\Concerns\WithHeadings; |
||||
use Maatwebsite\Excel\Concerns\WithCustomStartCell; |
||||
use Maatwebsite\Excel\Events\AfterSheet; |
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing; |
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; |
||||
use Maatwebsite\Excel\Concerns\WithEvents; |
||||
use Maatwebsite\Excel\Concerns\FromCollection; |
||||
use Illuminate\Support\Collection; |
||||
use PhpOffice\PhpSpreadsheet\Style\Alignment; |
||||
use PhpOffice\PhpSpreadsheet\Style\Border; |
||||
use PhpOffice\PhpSpreadsheet\Worksheet\PageSetup; |
||||
|
||||
class ArrayExportH implements FromArray, WithHeadings, WithCustomStartCell, WithEvents |
||||
{ |
||||
protected $data = []; |
||||
protected $headings = null; |
||||
protected $startCell = 'A1'; |
||||
protected $maxWidthThreshold = 50; // 設定相對的最大值 |
||||
protected $printOrientation = 1; // 預設橫式列印 1 = 橫式列印, 0 = 直式列印 |
||||
protected $showPageNumber = 0; // 是否顯示頁碼 1 = 顯示, 0 = 不顯示 |
||||
protected $showBorder = 0; // 顯示框線 |
||||
|
||||
|
||||
public function __construct(array $data, array $headings = null, array $option = []) |
||||
{ |
||||
$this->data = $data; |
||||
$this->headings = $headings; |
||||
$this->startCell = $option['startCell'] ?? 'A1'; |
||||
$this->maxWidthThreshold = $option['maxWidth'] ?? 50; |
||||
$this->printOrientation = $option['printDef'] ?? 1; |
||||
$this->showPageNumber = $option['showPN'] ?? 1; |
||||
$this->showBorder = $option['showBorder'] ?? 1; |
||||
} |
||||
|
||||
public function array(): array |
||||
{ |
||||
return $this->data; |
||||
} |
||||
|
||||
public function headings(): array |
||||
{ |
||||
// 定義標題列 |
||||
return $this->headings ?? array_keys($this->data[0]); |
||||
} |
||||
|
||||
public function startCell(): string |
||||
{ |
||||
return $this->startCell ?? 'A1'; |
||||
} |
||||
public function registerEvents(): array |
||||
{ |
||||
return [ |
||||
AfterSheet::class => function (AfterSheet $event) { |
||||
// 在這裡設定欄位寬度 |
||||
$sheet = $event->sheet; |
||||
|
||||
// 設定頁尾顯示 |
||||
if ($this->showPageNumber) { |
||||
// $sheet->getDelegate()->getHeaderFooter()->setOddHeader('&L &D &T &R 第 &P 頁,共 &N 頁'); |
||||
$sheet->getDelegate()->getHeaderFooter()->setOddFooter('&R 第 &P 頁,共 &N 頁'); |
||||
} |
||||
|
||||
// 設定列印邊界為窄邊界 |
||||
$sheet->getDelegate()->getPageMargins()->setTop(0.75); |
||||
$sheet->getDelegate()->getPageMargins()->setBottom(0.75); |
||||
$sheet->getDelegate()->getPageMargins()->setLeft(0.25); |
||||
$sheet->getDelegate()->getPageMargins()->setRight(0.25); |
||||
|
||||
// 設定橫式列印 |
||||
if ($this->printOrientation) |
||||
$sheet->getDelegate()->getPageSetup()->setOrientation(PageSetup::ORIENTATION_LANDSCAPE); |
||||
|
||||
// 最高的行和列 |
||||
$highestRow = $sheet->getDelegate()->getHighestRow(); |
||||
$highestColumn = $sheet->getDelegate()->getHighestColumn(); |
||||
|
||||
$sheet->getDelegate()->mergeCells('A1:' . $highestColumn . '1'); // 合併 A1:C1 儲存格 |
||||
$sheet->getDelegate()->mergeCells('A2:' . $highestColumn . '2'); // 合併 A1:C1 儲存格 |
||||
// $sheet->getDelegate()->mergeCells('A3:C3'); // 合併 A1:C1 儲存格 |
||||
// $sheet->getDelegate()->mergeCells('D1:G2'); // 合併 A1:C1 儲存格 |
||||
|
||||
// 自動設定框線 |
||||
if ($this->showBorder) { |
||||
$range = 'A1:' . $highestColumn . $highestRow; |
||||
$sheet->getDelegate()->getStyle($range)->getBorders()->getAllBorders()->setBorderStyle('thin'); |
||||
} |
||||
// 設定資料內容置中 |
||||
$range = 'A3:' . $highestColumn . $highestRow; |
||||
$sheet->getDelegate()->getStyle($range)->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER); |
||||
$sheet->getDelegate()->getStyle($range)->getAlignment()->setVertical(Alignment::VERTICAL_CENTER); |
||||
// 測量欄位內容寬度並設定寬度 |
||||
$maxWidths = []; |
||||
foreach ($sheet->getColumnIterator() as $column) { |
||||
$columnLetter = $column->getColumnIndex(); |
||||
$maxWidth = 0; |
||||
|
||||
foreach ($column->getCellIterator() as $cell) { |
||||
$width = strlen((string)$cell->getValue()) * 1.2; // 設定寬度倍率 |
||||
if ($width > $maxWidth) { |
||||
$maxWidth = $width; |
||||
} |
||||
} |
||||
|
||||
$maxWidths[$columnLetter] = $maxWidth; |
||||
} |
||||
|
||||
foreach ($maxWidths as $columnLetter => $width) { |
||||
$sheet->getColumnDimension($columnLetter)->setWidth($width > $this->maxWidthThreshold ? $this->maxWidthThreshold : $width); |
||||
} |
||||
}, |
||||
]; |
||||
} |
||||
|
||||
protected function wrapTextIfNeeded($value) |
||||
{ |
||||
// 檢查是否需要換行顯示 |
||||
return strlen($value) > $this->maxWidthThreshold ? wordwrap($value, $this->maxWidthThreshold, "\n", true) : $value; |
||||
} |
||||
|
||||
// public function drawings() |
||||
// { |
||||
// $drawings = []; |
||||
|
||||
// foreach ($this->data as $row) { |
||||
// if (isset($row[1]) && !empty($row[1])) { |
||||
// $imagePath = public_path($row[1]); // 圖片路徑 |
||||
// if (file_exists($imagePath)) { |
||||
// $drawing = new Drawing(); |
||||
// $drawing->setName('Image'); |
||||
// $drawing->setDescription('Image'); |
||||
// $drawing->setPath($imagePath); |
||||
// $drawing->setHeight(100); |
||||
// $drawing->setCoordinates('A' . ($this->key() + 2)); // 從第二行開始 |
||||
// $drawings[] = $drawing; |
||||
// } |
||||
// } |
||||
// } |
||||
|
||||
// return $drawings; |
||||
// } |
||||
|
||||
} |
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\Auth; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Providers\RouteServiceProvider; |
||||
use Illuminate\Foundation\Auth\ConfirmsPasswords; |
||||
|
||||
class ConfirmPasswordController extends Controller |
||||
{ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Confirm Password Controller |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| This controller is responsible for handling password confirmations and |
||||
| uses a simple trait to include the behavior. You're free to explore |
||||
| this trait and override any functions that require customization. |
||||
| |
||||
*/ |
||||
|
||||
use ConfirmsPasswords; |
||||
|
||||
/** |
||||
* Where to redirect users when the intended url fails. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $redirectTo = RouteServiceProvider::HOME; |
||||
|
||||
/** |
||||
* Create a new controller instance. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->middleware('auth'); |
||||
} |
||||
} |
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\Auth; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails; |
||||
|
||||
class ForgotPasswordController extends Controller |
||||
{ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Password Reset Controller |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| This controller is responsible for handling password reset emails and |
||||
| includes a trait which assists in sending these notifications from |
||||
| your application to your users. Feel free to explore this trait. |
||||
| |
||||
*/ |
||||
|
||||
use SendsPasswordResetEmails; |
||||
} |
@ -0,0 +1,59 @@
@@ -0,0 +1,59 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\Auth; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Providers\RouteServiceProvider; |
||||
use Illuminate\Foundation\Auth\AuthenticatesUsers; |
||||
use Illuminate\Http\Request; |
||||
|
||||
class LoginController extends Controller |
||||
{ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Login Controller |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| This controller handles authenticating users for the application and |
||||
| redirecting them to your home screen. The controller uses a trait |
||||
| to conveniently provide its functionality to your applications. |
||||
| |
||||
*/ |
||||
|
||||
use AuthenticatesUsers; |
||||
|
||||
/** |
||||
* Where to redirect users after login. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $redirectTo = RouteServiceProvider::HOME; |
||||
protected $maxAttempts = 3; |
||||
protected $decayMinutes = 10; |
||||
|
||||
/** |
||||
* Create a new controller instance. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->middleware('guest')->except('logout'); |
||||
} |
||||
|
||||
//複寫登入驗證 可使用name登入 |
||||
protected function credentials(Request $request) |
||||
{ |
||||
// dd($this->account()); |
||||
$field = filter_var($request->get($this->username()), FILTER_VALIDATE_EMAIL) |
||||
? $this->username() |
||||
: 'account';//欄位名稱 |
||||
|
||||
return [ |
||||
$field => $request->get($this->username()), |
||||
'password' => $request->password, |
||||
]; |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\Auth; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Providers\RouteServiceProvider; |
||||
use App\Models\User; |
||||
use Illuminate\Foundation\Auth\RegistersUsers; |
||||
use Illuminate\Support\Facades\Hash; |
||||
use Illuminate\Support\Facades\Validator; |
||||
|
||||
class RegisterController extends Controller |
||||
{ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Register Controller |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| This controller handles the registration of new users as well as their |
||||
| validation and creation. By default this controller uses a trait to |
||||
| provide this functionality without requiring any additional code. |
||||
| |
||||
*/ |
||||
|
||||
use RegistersUsers; |
||||
|
||||
/** |
||||
* Where to redirect users after registration. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $redirectTo = RouteServiceProvider::HOME; |
||||
|
||||
/** |
||||
* Create a new controller instance. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->middleware('guest'); |
||||
} |
||||
|
||||
/** |
||||
* Get a validator for an incoming registration request. |
||||
* |
||||
* @param array $data |
||||
* @return \Illuminate\Contracts\Validation\Validator |
||||
*/ |
||||
protected function validator(array $data) |
||||
{ |
||||
return Validator::make($data, [ |
||||
'name' => ['required', 'string', 'max:255'], |
||||
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], |
||||
'password' => ['required', 'string', 'min:8', 'confirmed'], |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* Create a new user instance after a valid registration. |
||||
* |
||||
* @param array $data |
||||
* @return \App\Models\User |
||||
*/ |
||||
protected function create(array $data) |
||||
{ |
||||
return User::create([ |
||||
'name' => $data['name'], |
||||
'email' => $data['email'], |
||||
'password' => Hash::make($data['password']), |
||||
]); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\Auth; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Providers\RouteServiceProvider; |
||||
use Illuminate\Foundation\Auth\ResetsPasswords; |
||||
|
||||
class ResetPasswordController extends Controller |
||||
{ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Password Reset Controller |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| This controller is responsible for handling password reset requests |
||||
| and uses a simple trait to include this behavior. You're free to |
||||
| explore this trait and override any methods you wish to tweak. |
||||
| |
||||
*/ |
||||
|
||||
use ResetsPasswords; |
||||
|
||||
/** |
||||
* Where to redirect users after resetting their password. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $redirectTo = RouteServiceProvider::HOME; |
||||
} |
@ -0,0 +1,42 @@
@@ -0,0 +1,42 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\Auth; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Providers\RouteServiceProvider; |
||||
use Illuminate\Foundation\Auth\VerifiesEmails; |
||||
|
||||
class VerificationController extends Controller |
||||
{ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Email Verification Controller |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| This controller is responsible for handling email verification for any |
||||
| user that recently registered with the application. Emails may also |
||||
| be re-sent if the user didn't receive the original email message. |
||||
| |
||||
*/ |
||||
|
||||
use VerifiesEmails; |
||||
|
||||
/** |
||||
* Where to redirect users after verification. |
||||
* |
||||
* @var string |
||||
*/ |
||||
protected $redirectTo = RouteServiceProvider::HOME; |
||||
|
||||
/** |
||||
* Create a new controller instance. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->middleware('auth'); |
||||
$this->middleware('signed')->only('verify'); |
||||
$this->middleware('throttle:6,1')->only('verify', 'resend'); |
||||
} |
||||
} |
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Models\User; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Hash; |
||||
|
||||
class AuthController extends Controller |
||||
{ |
||||
public function resetPassword() |
||||
{ |
||||
return view('auth.resetPassword'); |
||||
} |
||||
|
||||
public function updatePassword(Request $request) |
||||
{ |
||||
if ($request->password == "Aa@123456789") { |
||||
return redirect()->back()->with('message', '請勿使用預設密碼'); |
||||
} |
||||
if($request->password != $request->password_confirmation){ |
||||
return redirect()->back()->with('message', '密碼不一致'); |
||||
} |
||||
$pattern = "/^(?![A-Za-z0-9]+$)(?![a-z0-9\W]+$)(?![A-Za-z\W]+$)(?![A-Z0-9\W]+$)[a-zA-Z0-9\W]{12,}$/"; |
||||
$pregRs = preg_match($pattern, $request->password); |
||||
if ($pregRs == 0) { |
||||
return redirect()->back()->with('message', '密碼錯誤或強度不足,請混合使用 12 個字元以上的英文字母、數字和符號。'); |
||||
} |
||||
DB::beginTransaction(); |
||||
try { |
||||
$user = User::find(auth()->user()->id); |
||||
$exists = DB::table('past_passwords') |
||||
->where('user_id', $user->id) |
||||
->orderBy('created_at', 'desc') |
||||
// ->where('password', Hash::check($request->password, $user->password)) |
||||
->limit(3)->pluck('password'); |
||||
// dd($exists); |
||||
if(isset($exists)){ |
||||
foreach ($exists as $exist) { |
||||
if (Hash::check($request->password, $exist)) { |
||||
return redirect()->back()->with('message', '密碼不可與過去相同'); |
||||
} |
||||
} |
||||
} |
||||
$user->update([ |
||||
'password' => Hash::make($request->password) |
||||
]); |
||||
DB::table('past_passwords')->insert([ |
||||
'user_id'=>$user->id, |
||||
'password'=>$user->password, |
||||
'created_at'=>Carbon::now('Asia/Taipei') |
||||
]); |
||||
|
||||
$logData = [ |
||||
'action' => 'update', |
||||
'action_detail' => '變更密碼', |
||||
'ip' => request()->ip(), |
||||
'remark' => "使用者:$user->name 變更密碼", |
||||
]; |
||||
LogWriter::writeLog($logData, 'web'); |
||||
DB::commit(); |
||||
auth()->logout(); |
||||
return redirect()->route('login'); |
||||
} catch (\Throwable $th) { |
||||
DB::rollback(); |
||||
return redirect()->back()->withErrors(['error' => '密碼更新失敗']); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,28 @@
@@ -0,0 +1,28 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers; |
||||
|
||||
use Illuminate\Http\Request; |
||||
|
||||
class HomeController extends Controller |
||||
{ |
||||
/** |
||||
* Create a new controller instance. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
$this->middleware('auth'); |
||||
} |
||||
|
||||
/** |
||||
* Show the application dashboard. |
||||
* |
||||
* @return \Illuminate\Contracts\Support\Renderable |
||||
*/ |
||||
public function index() |
||||
{ |
||||
return view('home'); |
||||
} |
||||
} |
@ -0,0 +1,126 @@
@@ -0,0 +1,126 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers; |
||||
|
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use Spatie\Permission\Models\Role; |
||||
use Spatie\Permission\Models\Permission; |
||||
use DB; |
||||
use Illuminate\View\View; |
||||
use Illuminate\Http\RedirectResponse; |
||||
|
||||
class RoleController extends Controller |
||||
{ |
||||
/** |
||||
* Display a listing of the resource. |
||||
* |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
function __construct() |
||||
{ |
||||
$this->middleware('permission:role-list|role-create|role-edit|role-delete', ['only' => ['index', 'store']]); |
||||
$this->middleware('permission:role-create', ['only' => ['create', 'store']]); |
||||
$this->middleware('permission:role-edit', ['only' => ['edit', 'update']]); |
||||
$this->middleware('permission:role-delete', ['only' => ['destroy']]); |
||||
} |
||||
/** |
||||
* Display a listing of the resource. |
||||
* |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function index(Request $request): View |
||||
{ |
||||
$roles = Role::orderBy('id', 'DESC')->paginate(5); |
||||
return view('roles.index', compact('roles')) |
||||
->with('i', ($request->input('page', 1) - 1) * 5); |
||||
} |
||||
/** |
||||
* Show the form for creating a new resource. |
||||
* |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function create(): View |
||||
{ |
||||
$permission = Permission::get(); |
||||
return view('roles.create', compact('permission')); |
||||
} |
||||
/** |
||||
* Store a newly created resource in storage. |
||||
* |
||||
* @param \Illuminate\Http\Request $request |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function store(Request $request): RedirectResponse |
||||
{ |
||||
$this->validate($request, [ |
||||
'name' => 'required|unique:roles,name', |
||||
'permission' => 'required', |
||||
]); |
||||
$role = Role::create(['name' => $request->input('name')]); |
||||
$role->syncPermissions($request->input('permission')); |
||||
return redirect()->route('roles.index') |
||||
->with('success', 'Role created successfully'); |
||||
} |
||||
/** |
||||
* Display the specified resource. |
||||
* |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function show($id): View |
||||
{ |
||||
$role = Role::find($id); |
||||
$rolePermissions = Permission::join("role_has_permissions", "role_has_permissions.permission_id", "=", "permissions.id") |
||||
->where("role_has_permissions.role_id", $id) |
||||
->get(); |
||||
return view('roles.show', compact('role', 'rolePermissions')); |
||||
} |
||||
/** |
||||
* Show the form for editing the specified resource. |
||||
* |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function edit($id): View |
||||
{ |
||||
$role = Role::find($id); |
||||
$permission = Permission::get(); |
||||
$rolePermissions = DB::table("role_has_permissions")->where("role_has_permissions.role_id", $id) |
||||
->pluck('role_has_permissions.permission_id', 'role_has_permissions.permission_id') |
||||
->all(); |
||||
return view('roles.edit', compact('role', 'permission', 'rolePermissions')); |
||||
} |
||||
/** |
||||
* Update the specified resource in storage. |
||||
* |
||||
* @param \Illuminate\Http\Request $request |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function update(Request $request, $id): RedirectResponse |
||||
{ |
||||
$this->validate($request, [ |
||||
'name' => 'required', |
||||
'permission' => 'required', |
||||
]); |
||||
$role = Role::find($id); |
||||
$role->name = $request->input('name'); |
||||
$role->save(); |
||||
$role->syncPermissions($request->input('permission')); |
||||
return redirect()->route('roles.index') |
||||
->with('success', 'Role updated successfully'); |
||||
} |
||||
/** |
||||
* Remove the specified resource from storage. |
||||
* |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function destroy($id): RedirectResponse |
||||
{ |
||||
DB::table("roles")->where('id', $id)->delete(); |
||||
return redirect()->route('roles.index') |
||||
->with('success', 'Role deleted successfully'); |
||||
} |
||||
} |
@ -0,0 +1,141 @@
@@ -0,0 +1,141 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\system; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\User; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use PhpOffice\PhpSpreadsheet\Calculation\MathTrig\Exp; |
||||
|
||||
class FileIndexController extends Controller |
||||
{ |
||||
/** |
||||
* Display a listing of the resource. |
||||
*/ |
||||
public function index() |
||||
{ |
||||
return view('filesystem.index'); |
||||
} |
||||
|
||||
//api_index |
||||
public function api_index(Request $request) |
||||
{ |
||||
// 從資料庫取得檔案索引表 ExportFiles |
||||
$user_id = auth('api')->user()->id; |
||||
$files = ExportFiles::where('user_id', $user_id)->get(); |
||||
|
||||
[$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($request); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
|
||||
|
||||
// dd($response); |
||||
echo json_encode($response); |
||||
exit; |
||||
|
||||
} |
||||
// get data |
||||
#region 取得資料 |
||||
function getData($request) |
||||
{ |
||||
$user_id = auth('api')->user()->id; |
||||
|
||||
#region Request 搜尋值 |
||||
if (isset($request->searchByFromdate)) |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
if (isset($request->searchByTodate)) |
||||
$searchByTodate = $request->searchByTodate; |
||||
#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 = ExportFiles::query(); |
||||
$records->where('user_id', $user_id); |
||||
|
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
$query->where('remark', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
//時間限制 |
||||
if (isset($searchByFromdate)) |
||||
$records->where('created_at', ">", $searchByFromdate . ' 00:00:00'); |
||||
if (isset($searchByTodate)) |
||||
$records->where('created_at', "<", $searchByTodate . ' 23:59:59'); |
||||
|
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
|
||||
#region DataTable 分頁(報表不分頁) |
||||
if (!isset($request->export)) { |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
} |
||||
#endregion |
||||
|
||||
$records = $records->get(); |
||||
|
||||
#region 資料處理 |
||||
$data_arr = array(); |
||||
$sno = 1 + ($request->get('start') ?? 0); |
||||
foreach ($records as $record) { |
||||
$data_arr[] = array( |
||||
"id" => $sno++, // $record->id, |
||||
"display_name" => $record->remark, |
||||
"user" => User::find($record->user_id)->name ?? '', |
||||
"created_at" => Carbon::parse($record->created_at)->format('Y-m-d H:i:s'), |
||||
"name" => "$record->name", |
||||
); |
||||
} |
||||
#endregion |
||||
return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr]; |
||||
} |
||||
#endregion |
||||
|
||||
// 下載檔案 透過檔案名稱 |
||||
public function downloadFile(Request $request, $path) |
||||
{ |
||||
$file = ExportFiles::where('name', $path)->first(); |
||||
$path = storage_path('app/' . $file->path . '/' . $file->name); |
||||
// 檔案名稱 |
||||
$name = $file->remark; |
||||
// 副檔名 |
||||
$ext = pathinfo($path, PATHINFO_EXTENSION); |
||||
return response()->download($path, $name . '.' . $ext); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,425 @@
@@ -0,0 +1,425 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Models\IntervalEquipment; |
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\AssetOwnership; |
||||
use App\Models\CustodyUnit; |
||||
use App\Models\Intervaldis; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
|
||||
class IntervalEquipmentController extends Controller |
||||
{ |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->middleware('permission:itl-device-setting'); |
||||
} |
||||
|
||||
public function page() |
||||
{ |
||||
// ['custodyunit' => $custodyunit, 'assetownership' => $assetownership] |
||||
|
||||
$custodyunit = CustodyUnit::all(); |
||||
$assetownership = AssetOwnership::all(); |
||||
return view('system.interval.equipment') |
||||
->with('custodyunit', $custodyunit) |
||||
->with('assetownership', $assetownership); |
||||
} |
||||
public function road() |
||||
{ |
||||
// ['custodyunit' => $custodyunit, 'assetownership' => $assetownership] |
||||
|
||||
$custodyunit = CustodyUnit::all(); |
||||
$assetownership = AssetOwnership::all(); |
||||
$location = IntervalEquipment::select('id', 'serialnumber', 'location')->distinct()->get(); |
||||
// dd($location); |
||||
return view('system.interval.equ_dis') |
||||
->with('location', $location) |
||||
->with('custodyunit', $custodyunit) |
||||
->with('assetownership', $assetownership); |
||||
} |
||||
/** |
||||
* Display a listing of the resource. |
||||
*/ |
||||
public function index(Request $request) |
||||
{ |
||||
#region DataTable 搜尋屬性 |
||||
$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 |
||||
#endregion |
||||
|
||||
// Role with permissions |
||||
$records = IntervalEquipment::query(); |
||||
if (isset($request->dis)) { |
||||
$records = Intervaldis::query(); |
||||
} |
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
// $query->where('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('name', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('serialnumber', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('creator_id', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
|
||||
$data_arr = $records->get(); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
return response()->json($response); |
||||
} |
||||
|
||||
/** |
||||
* Store a newly created resource in storage. |
||||
*/ |
||||
public function store(Request $request) |
||||
{ |
||||
$device = new IntervalEquipment(); |
||||
// 如果缺少必要欄位 |
||||
|
||||
DB::beginTransaction(); |
||||
try { |
||||
|
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->videonumber = $request->videonumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id; |
||||
$device->assetownership_id = $request->assetownership_id; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
|
||||
|
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
|
||||
return response()->json(['success' => true, 'message' => '新增成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display the specified resource. |
||||
*/ |
||||
public function show(string $id) |
||||
{ |
||||
$device = IntervalEquipment::find($id); |
||||
return response()->json(['success' => true, 'data' => $device]); |
||||
} |
||||
|
||||
/** |
||||
* Update the specified resource in storage. |
||||
*/ |
||||
public function update(Request $request, string $id) |
||||
{ |
||||
$device = IntervalEquipment::find($id); |
||||
if (!$request->serialnumber || !$request->location || !$request->precinct || !$request->station) { |
||||
return response()->json(['success' => false, 'message' => '缺少必要欄位']); |
||||
} |
||||
DB::beginTransaction(); |
||||
try { |
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->videonumber = $request->videonumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id ?? null; |
||||
$device->assetownership_id = $request->assetownership_id ?? null; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'update', |
||||
'action_detail' => '更新設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "更新設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '更新成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '更新失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove the specified resource from storage. |
||||
*/ |
||||
public function destroy(string $id) |
||||
{ |
||||
$device = IntervalEquipment::find($id); |
||||
try { |
||||
$device->delete(); |
||||
return response()->json(['success' => true, 'message' => '刪除成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
return response()->json(['success' => false, 'message' => '刪除失敗']); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 取得保管單位資料 |
||||
*/ |
||||
public function indexUnit(Request $request) |
||||
{ |
||||
|
||||
if ($request->type == "custodyunit") { |
||||
$unit = CustodyUnit::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
} else if ($request->type == "assetownership") { |
||||
$unit = AssetOwnership::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
} |
||||
|
||||
return response()->json(['success' => false, 'message' => '取得失敗']); |
||||
} |
||||
|
||||
/** |
||||
* 新增單位資料 |
||||
*/ |
||||
public function storeUnit(Request $request) |
||||
{ |
||||
// custodyunit_id |
||||
//assetownership_id) |
||||
DB::beginTransaction(); |
||||
try { |
||||
if ($request->type == "custodyunit") { |
||||
$unit = new CustodyUnit(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增保管單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增保管單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '保管單位-新增成功']); |
||||
} else if ($request->type == "assetownership") { |
||||
$unit = new AssetOwnership(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增財產所屬單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增財產所屬單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '財產所屬單位-新增成功']); |
||||
} |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
} |
||||
|
||||
|
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Store a newly created resource in storage. |
||||
*/ |
||||
public function storeRoad(Request $request) |
||||
{ |
||||
$road = new Intervaldis(); |
||||
// 如果缺少必要欄位 |
||||
if ( |
||||
!$request->start_num || !$request->end_num || !$request->outlaw_speed || !$request->location |
||||
|| !$request->distance || !$request->limit_speed || !$request->location_id |
||||
|| !$request->start_cert || !$request->end_cert |
||||
) { |
||||
return response()->json(['error' => false, 'message' => '缺少必要欄位']); |
||||
} |
||||
// 起始機號與結束機號不可相同 |
||||
if ($request->start_num == $request->end_num) { |
||||
return response()->json(['error' => false, 'message' => '起始機號與結束機號不可相同']); |
||||
} |
||||
|
||||
// 起始日期不可大於結束日期 |
||||
if ($request->start_cert > $request->end_cert) { |
||||
return response()->json(['error' => false, 'message' => '起始日期不可大於結束日期']); |
||||
} |
||||
DB::beginTransaction(); |
||||
try { |
||||
|
||||
$road->start_serialnumber = $request->start_num; |
||||
$road->end_serialnumber = $request->end_num; |
||||
$road->distance = $request->distance; |
||||
$road->limit_speed = $request->limit_speed; |
||||
$road->outlaw_speed = $request->outlaw_speed; |
||||
$road->limit_time = round(3600 * $request->distance / $request->limit_speed / 1000, 2); |
||||
$road->speed_alert = $request->speed_alert; |
||||
$road->count_alert = $request->count_alert; |
||||
$road->location = $request->location; |
||||
$road->location_id = $request->location_id; |
||||
$road->certificatenumber = $request->certificatenumber; |
||||
$road->start_cert = $request->start_cert; |
||||
$road->end_cert = $request->end_cert; |
||||
|
||||
// dd($road); |
||||
$road->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增路段', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增路段:{$road->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
|
||||
return response()->json(['success' => true, 'message' => '新增成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['error' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display the specified resource. |
||||
*/ |
||||
public function showRoad(string $id) |
||||
{ |
||||
$device = Intervaldis::find($id); |
||||
return response()->json(['success' => true, 'data' => $device]); |
||||
} |
||||
|
||||
/** |
||||
* Update the specified resource in storage. |
||||
*/ |
||||
public function updateRoad(Request $request, string $id) |
||||
{ |
||||
$road = Intervaldis::find($id); |
||||
if ( |
||||
!$request->start_num || !$request->end_num || !$request->outlaw_speed || !$request->location |
||||
|| !$request->distance || !$request->limit_speed || !$request->location_id |
||||
|| !$request->start_cert || !$request->end_cert |
||||
) { |
||||
return response()->json(['error' => false, 'message' => '缺少必要欄位']); |
||||
} |
||||
// 起始機號與結束機號不可相同 |
||||
if ($request->start_num == $request->end_num) { |
||||
return response()->json(['error' => false, 'message' => '起始機號與結束機號不可相同']); |
||||
} |
||||
|
||||
// 起始日期不可大於結束日期 |
||||
if ($request->start_cert > $request->end_cert) { |
||||
return response()->json(['error' => false, 'message' => '起始日期不可大於結束日期']); |
||||
} |
||||
|
||||
DB::beginTransaction(); |
||||
try { |
||||
$road->start_serialnumber = $request->start_num; |
||||
$road->end_serialnumber = $request->end_num; |
||||
$road->distance = $request->distance; |
||||
$road->limit_speed = $request->limit_speed; |
||||
$road->outlaw_speed = $request->outlaw_speed; |
||||
$road->limit_time = round(3600 * $request->distance / $request->limit_speed / 1000, 2); |
||||
$road->speed_alert = $request->speed_alert; |
||||
$road->count_alert = $request->count_alert; |
||||
$road->location = $request->location; |
||||
$road->location_id = $request->location_id; |
||||
$road->certificatenumber = $request->certificatenumber; |
||||
$road->start_cert = $request->start_cert; |
||||
$road->end_cert = $request->end_cert; |
||||
$road->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'update', |
||||
'action_detail' => '更新路段', |
||||
'ip' => request()->ip(), |
||||
'remark' => "更新路段:{$road->location}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '更新成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['error' => false, 'message' => '更新失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove the specified resource from storage. |
||||
*/ |
||||
public function destroyRoad(string $id) |
||||
{ |
||||
$device = Intervaldis::find($id); |
||||
try { |
||||
$device->delete(); |
||||
return response()->json(['success' => true, 'message' => '刪除成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
return response()->json(['error' => false, 'message' => '刪除失敗']); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,200 @@
@@ -0,0 +1,200 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Exports\ArrayExport; |
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\UserLog; |
||||
use Carbon\Carbon; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
|
||||
class LogController extends Controller |
||||
{ |
||||
public function __construct() |
||||
{ |
||||
} |
||||
|
||||
// index |
||||
public function index(Request $request) |
||||
{ |
||||
$actionDetails = UserLog::cachedDistinctActionDetail(); |
||||
$users = UserLog::cachedDistinctUser(); |
||||
return view('system.setting.log') |
||||
->with('actionDetails', $actionDetails) |
||||
->with('users', $users); |
||||
} |
||||
|
||||
// get data |
||||
#region 取得資料 |
||||
function getData($request) |
||||
{ |
||||
#region Request 搜尋值 |
||||
if (isset($request->searchByFromdate)) |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
if (isset($request->searchByTodate)) |
||||
$searchByTodate = $request->searchByTodate; |
||||
#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 = UserLog::query(); |
||||
$records->whereNotIn('user_id', [1]); |
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
$query->where('user_name', 'like', '%' . $searchValue . '%') |
||||
->orwhere('action_detail', 'like', '%' . $searchValue . '%') |
||||
->orwhere('creator_id', 'like', '%' . $searchValue . '%') |
||||
->orwhere('remark', 'like', '%' . $searchValue . '%'); |
||||
// ->orwhere('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('created_at', 'like', '%' . $searchValue . '%') |
||||
}); |
||||
} |
||||
|
||||
//時間限制 |
||||
if (isset($searchByFromdate)) |
||||
$records->where('created_at', ">", $searchByFromdate . ' 00:00:00'); |
||||
if (isset($searchByTodate)) |
||||
$records->where('created_at', "<", $searchByTodate . ' 23:59:59'); |
||||
|
||||
if (isset($request->action_detail)) |
||||
$records->where('action_detail', $request->action_detail); |
||||
if (isset($request->username)) |
||||
$records->whereIn('user_name', $request->username); |
||||
|
||||
$totalRecords = $records->count(); |
||||
$totalRecordswithFilter = $records->count(); |
||||
|
||||
#region DataTable 分頁(報表不分頁) |
||||
if (!isset($request->export)) { |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
} |
||||
#endregion |
||||
|
||||
$records = $records->get(); |
||||
|
||||
#region 資料處理 |
||||
$data_arr = array(); |
||||
$sno = 1+($request->get('start') ?? 0); |
||||
foreach ($records as $record) { |
||||
//還原用id |
||||
|
||||
//報表用的欄位,避免前端錯誤,給預設值 |
||||
$count = $record->count ?? 0; |
||||
$period = $record->period ?? ""; |
||||
|
||||
$data_arr[] = array( |
||||
"id" => $sno++, // $record->id, |
||||
"user_name" => $record->user_name, |
||||
"action_detail" => $record->action_detail, |
||||
"ip" => $record->ip, |
||||
"remark" => $record->remark, |
||||
"created_at" => Carbon::parse($record->created_at)->format('Y-m-d H:i:s'), |
||||
"count" => $count, |
||||
"period" => $period, |
||||
"last_count" => $record->last_count ?? 0, |
||||
"carnumber" => $record->carnumber, |
||||
"location" => $record->location, |
||||
); |
||||
} |
||||
#endregion |
||||
return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr]; |
||||
} |
||||
#endregion |
||||
|
||||
// get datatable |
||||
#region DataTable (AJAX刷新用 參數 processcheckStatus 0未審 1已審 2不舉發 "99清冊用")使用 |
||||
public function getDataTable(Request $request) |
||||
{ |
||||
|
||||
[$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($request); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
|
||||
|
||||
// dd($response); |
||||
echo json_encode($response); |
||||
exit; |
||||
} |
||||
#endregion |
||||
|
||||
public function getLogDataExport(Request $request) |
||||
{ |
||||
|
||||
$remark = '操作紀錄清冊'; |
||||
$columns = ['id', 'created_at', 'user_name', 'ip', 'action_detail', 'remark', 'carnumber', 'location']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['編號', '操作時間', '使用者名稱', 'ip', '動作', '操作說明', '車號', '地點'] |
||||
]; |
||||
|
||||
|
||||
if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { |
||||
$remark = $remark . ' ' . $request->searchByFromdate . ' ~ ' . $request->searchByTodate; |
||||
} |
||||
|
||||
[$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($request); |
||||
$data = array_map(function ($row) use ($columns) { |
||||
$data = array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); |
||||
return $data; |
||||
}, $data_arr); |
||||
|
||||
$fileName = 'log-' . Str::random(10) . '.xlsx'; |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "操作紀錄-$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('ms-export', ['fileName' => $fileName])], 200); |
||||
} |
||||
|
||||
public function Export(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' => '檔案不存在']); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,343 @@
@@ -0,0 +1,343 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System\Monitor; |
||||
|
||||
use App\Exports\ArrayExportH; |
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\PingIp; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
|
||||
class PingIpController extends Controller |
||||
{ |
||||
// |
||||
public $serialNumber = [ |
||||
// '20K888', |
||||
// '20K999', |
||||
// '20K003', |
||||
// '20K001', |
||||
// '20K002', |
||||
// '20K003', |
||||
// '20K004', |
||||
'24H633', |
||||
'24H634', |
||||
'24H635', |
||||
'24H636', |
||||
]; |
||||
public function index() |
||||
{ |
||||
|
||||
// $s=[ |
||||
// [ |
||||
// 's' => '20K001', |
||||
// 'ip' => '192.168.100.2' |
||||
// ], |
||||
// [ |
||||
// 's' => '20K002', |
||||
// 'ip' => '192.168.110.2' |
||||
// ], |
||||
// [ |
||||
// 's' => '20K003', |
||||
// 'ip' => '192.168.80.2' |
||||
// ], |
||||
// [ |
||||
// 's' => '20K004', |
||||
// 'ip' => '192.168.90.2' |
||||
// ], |
||||
// ]; |
||||
// $t = Carbon::parse('2022-09-30 00:00:00'); |
||||
// $arr=[]; |
||||
// for($i = 0; $i < 1440 ;$i++){ |
||||
// $r = rand(150,600); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// array_push($arr,[ |
||||
// 'ping_time'=>$dt->format('Y-m-d H:i:s').'.'.rand(150,600), |
||||
// 'ip'=>$s[0]['ip'], |
||||
// 'serialnumber'=>$s[0]['s'], |
||||
// 'time' => 1 |
||||
// ]); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(-1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// $t = $t->addMinutes(1); |
||||
// } |
||||
// // dd($arr); |
||||
// foreach($arr as $a){ |
||||
// PingIp::create($a); |
||||
// } |
||||
|
||||
// $t = Carbon::parse('2022-09-30 00:00:00'); |
||||
// $arr=[]; |
||||
// for($i = 0; $i < 1440 ;$i++){ |
||||
// $r = rand(150,600); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// array_push($arr,[ |
||||
// 'ping_time'=>$dt->format('Y-m-d H:i:s').'.'.rand(150,600), |
||||
// 'ip'=>$s[1]['ip'], |
||||
// 'serialnumber'=>$s[1]['s'], |
||||
// 'time' => 1 |
||||
// ]); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(-1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// $t = $t->addMinutes(1); |
||||
// } |
||||
// // dd($arr); |
||||
// foreach($arr as $a){ |
||||
// PingIp::create($a); |
||||
// } |
||||
|
||||
// $t = Carbon::parse('2022-09-30 00:00:00'); |
||||
// $arr=[]; |
||||
// for($i = 0; $i < 1440 ;$i++){ |
||||
// $r = rand(150,600); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// array_push($arr,[ |
||||
// 'ping_time'=>$dt->format('Y-m-d H:i:s').'.'.rand(150,600), |
||||
// 'ip'=>$s[2]['ip'], |
||||
// 'serialnumber'=>$s[2]['s'], |
||||
// 'time' => 1 |
||||
// ]); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(-1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// $t = $t->addMinutes(1); |
||||
// } |
||||
// // dd($arr); |
||||
// foreach($arr as $a){ |
||||
// PingIp::create($a); |
||||
// } |
||||
|
||||
// $t = Carbon::parse('2022-09-30 00:00:00'); |
||||
// $arr=[]; |
||||
// for($i = 0; $i < 1440 ;$i++){ |
||||
// $r = rand(150,600); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// array_push($arr,[ |
||||
// 'ping_time'=>$dt->format('Y-m-d H:i:s').'.'.rand(150,600), |
||||
// 'ip'=>$s[3]['ip'], |
||||
// 'serialnumber'=>$s[3]['s'], |
||||
// 'time' => 1 |
||||
// ]); |
||||
// if( $r > 550){ |
||||
// $dt = $t->addSeconds(-1); |
||||
// } |
||||
// else{ |
||||
// $dt = $t; |
||||
// } |
||||
// $t = $t->addMinutes(1); |
||||
// } |
||||
// // dd($arr); |
||||
// foreach($arr as $a){ |
||||
// PingIp::create($a); |
||||
// } |
||||
|
||||
$serialNumber = $this->serialNumber; |
||||
return view('system.monitor.ping', compact('serialNumber')); |
||||
} |
||||
|
||||
#region 輸出excel |
||||
|
||||
public function ExportExcel(Request $request, $status) |
||||
{ |
||||
// dd($request->all(),$processcheckStatus); |
||||
#region 設備限制 |
||||
// $device = explode(',', auth()->user()->devicetype); |
||||
#endregion |
||||
[$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($request, $status); |
||||
$columns = ['ping_time', 'serialnumber', 'ip', 'time']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:". "前端攝影機設備狀態"], |
||||
["【日期區間】:". $request->searchByFromdate. " ~ ". $request->searchByTodate], |
||||
['檢測時間', '設備編號', 'IP', '延遲(ms)'] |
||||
]; |
||||
// $data_arr = $data_arr->toArray(); |
||||
$data = array_map(function ($row) use ($columns) { |
||||
$data = array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); |
||||
return $data; |
||||
}, $data_arr); |
||||
|
||||
$fileName = 'ping-' . Str::random(10) . '.xlsx'; |
||||
|
||||
|
||||
try { |
||||
DB::beginTransaction(); |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports/monitor/', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "PingIP報表匯出", |
||||
'user_id' => auth('api')->user()->id, |
||||
]); |
||||
$option = [ |
||||
'printDef' => $request->printDef ?? 0, |
||||
'showPN' => $request->showPN ?? 0, |
||||
'showBorder' => $request->showBorder ?? 0, |
||||
]; |
||||
Excel::store(new ArrayExportH($data, $columnTitle, $option), 'public/exports/monitor/' . $fileName, 'local', \Maatwebsite\Excel\Excel::XLSX); |
||||
DB::commit(); |
||||
} catch (\Throwable $th) { |
||||
Log::error("報表匯出失敗: " . $th->getMessage()); |
||||
DB::rollBack(); |
||||
} |
||||
|
||||
return response()->json(['url' => route('system.filedownload', ['path' => $fileName])], 200); |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
public function getDataTable(Request $request, $status) |
||||
{ |
||||
[$draw, $totalRecords, $totalRecordswithFilter, $data_arr] = $this->getData($request, $status); |
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
echo json_encode($response); |
||||
exit; |
||||
} |
||||
|
||||
#region 取得資料 |
||||
function getData($request, $status) |
||||
{ |
||||
// 審查狀態 0 未審 1 已審查 2 不舉發 99清冊 |
||||
// $status = 2; |
||||
// dd($device, $request, $status); |
||||
# 日期搜尋值 |
||||
if (isset($request->searchByFromdate)) |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
if (isset($request->searchByTodate)) |
||||
$searchByTodate = $request->searchByTodate; |
||||
//地點搜尋 |
||||
if (isset($request->location)) |
||||
$location = $request->location; |
||||
|
||||
#region DataTable 搜尋屬性 |
||||
$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'); |
||||
if ($status != 999){ |
||||
$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 |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
// Fetch records |
||||
if ($status == 99) { |
||||
$serialNumber = $this->serialNumber; |
||||
$records = []; |
||||
foreach ($serialNumber as $s) { |
||||
$p = PingIp::where("serialnumber", $s)->orderby('ping_time', 'desc')->first(); |
||||
if (isset($p)) |
||||
array_push($records, $p); |
||||
} |
||||
$totalRecords = count($records); |
||||
$totalRecordswithFilter = count($records); |
||||
} else { |
||||
$records = PingIp::query(); |
||||
$totalRecords = $records->count(); |
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
// if (isset($searchValue)) |
||||
// $records->where('carnumber', 'like', '%' . $searchValue . '%'); |
||||
//已審未審 |
||||
|
||||
//時間限制 |
||||
if (isset($searchByFromdate)) |
||||
$records->where('ping_time', ">", $searchByFromdate . ' 00:00:00'); |
||||
else |
||||
$records->where('ping_time', ">", Carbon::now()->subMonths(36)); |
||||
if (isset($searchByTodate)) |
||||
$records->where('ping_time', "<", $searchByTodate . ' 23:59:59'); |
||||
//地點篩選 |
||||
if (isset($location)) |
||||
$records->where('serialnumber', $location); |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
$records->select('*'); |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
$records = $records->get(); |
||||
} |
||||
|
||||
|
||||
$data_arr = array(); |
||||
$sno = $start + 1; |
||||
// dd($records); |
||||
|
||||
foreach ($records as $record) { |
||||
//還原用id |
||||
$id = $record->id; |
||||
//不舉發原因 |
||||
$ip = $record->ip; |
||||
$symbol = $record->symbol; |
||||
$ping_time = $record->ping_time; |
||||
$serialnumber = $record->serialnumber; |
||||
$time = $record->time; |
||||
$ttl = $record->ttl; |
||||
$status = $record->status; |
||||
$data_arr[] = array( |
||||
"id" => $id, |
||||
"ip" => $ip, |
||||
"time" => $time, |
||||
"symbol" => $symbol, |
||||
"serialnumber" => $serialnumber, |
||||
"ping_time" => $ping_time, |
||||
"ttl" => $ttl, |
||||
"status" => $status, |
||||
// "searchByFromdate" => $searchByFromdate, |
||||
// "searchByTodate"=> $searchByTodate |
||||
); |
||||
} |
||||
|
||||
return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr]; |
||||
} |
||||
#endregion |
||||
} |
@ -0,0 +1,987 @@
@@ -0,0 +1,987 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Exports\ArrayExport; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\Multisys; |
||||
use App\Models\MultisysEquipment; |
||||
use App\Models\ViolationLaw; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
use ZipArchive; |
||||
|
||||
class MultisysController extends Controller |
||||
{ |
||||
public $destPath_root; |
||||
public $clientDestPath_root; |
||||
public $unreportPath_root; |
||||
public $month; |
||||
|
||||
function __construct() |
||||
{ |
||||
$this->middleware('permission:ms-review|ms-reduction|ms-device-setting|ms-statistics|ms-analysis|ms-read', ['only' => ['Review']]); |
||||
$this->middleware('permission:ms-review|permission:ms-reduction', ['only' => ['update']]); |
||||
$this->middleware('permission:ms-device-setting', ['only' => ['DeviceSetting']]); |
||||
$this->middleware('permission:ms-statistics', ['only' => ['Statistics']]); |
||||
$this->middleware('permission:ms-analysis', ['only' => ['Analysis']]); |
||||
// OK path |
||||
$this->destPath_root = 'D:\\OK\\MS\\'; |
||||
$this->clientDestPath_root = 'Y:\\'; |
||||
// NOK path |
||||
$this->unreportPath_root = 'C:\\xampp\\SMMS\\storage\\app\\ParsingFiles\\NOK\\MS\\'; |
||||
$this->month['start'] = Carbon::now()->subDays(8)->format('Y-m-d'); |
||||
$this->month['current'] = Carbon::now()->subDays(1)->format('Y-m-d'); |
||||
} |
||||
|
||||
public function Review() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// dd($device); |
||||
$equipmentData = new MultisysEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new Multisys(); |
||||
$locationtype = $violationparking::where('processcheck', 0)->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); |
||||
// dd($data,$page_data); |
||||
|
||||
$violationtype = MultiSys::select('violationtype', 'location', 'serialnumber')->groupby('serialnumber')->orderby('serialnumber', 'asc')->get(); |
||||
$violationtype2 = []; |
||||
foreach ($violationtype as $tmp_vio) { |
||||
array_push($violationtype2, $tmp_vio->violationtype); |
||||
} |
||||
$violationtype2 = array_unique($violationtype2); |
||||
$vio_arr = []; |
||||
foreach (ViolationLaw::whereIn('type', ['未禮讓行人', '路口未淨空', '未依標誌標線號誌行駛', '闖紅燈', '紅燈越線', '紅燈右轉'])->where('sort','!=','-1')->get() as $key => $item) { |
||||
$vio_arr[$key]['violationcode'] = $item->violationcode; |
||||
$vio_arr[$key]['display_name'] = $item->display_name; |
||||
} |
||||
// dd($vio_arr); |
||||
return view('system.multisys.index') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('violationtype', $violationtype) |
||||
->with('violationtype2', $violationtype2) |
||||
->with('vio_arr', $vio_arr) |
||||
->with('month', $this->month); |
||||
} |
||||
|
||||
#region 已審 View |
||||
public function Censored(Request $request) |
||||
{ |
||||
|
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$equipmentData = new MultisysEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new Multisys(); |
||||
$locationtype = $violationparking::where('processcheck', 1)->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); |
||||
$violationtype = MultiSys::select('violationtype', 'location', 'serialnumber')->groupby('serialnumber')->orderby('serialnumber', 'asc')->get(); |
||||
$violationtype2 = []; |
||||
foreach ($violationtype as $tmp_vio) { |
||||
array_push($violationtype2, $tmp_vio->violationtype); |
||||
} |
||||
$violationtype2 = array_unique($violationtype2); |
||||
// dd($data,$page_data); |
||||
return view('system.multisys.manage') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('violationtype', $violationtype) |
||||
->with('violationtype2', $violationtype2) |
||||
->with('month', $this->month); |
||||
} |
||||
#endregion |
||||
|
||||
#region 不舉發 View |
||||
public function Unreport(Request $request) |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$equipmentData = new MultisysEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new Multisys(); |
||||
$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.multisys.unreport') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('unreportreason', $unreportreason) |
||||
->with('month', $this->month); |
||||
} |
||||
#endregion |
||||
|
||||
public function update(Request $request, $id) |
||||
{ |
||||
$data = Multisys::find($id); |
||||
// 先確認 processcheck 狀態 0 修改 1 舉發 2 不舉發 |
||||
// 確認使用者是否可以 review |
||||
DB::beginTransaction(); |
||||
|
||||
try { |
||||
// 如果使用者具 審查權限 |
||||
if (auth('api')->user()->can('ms-review')) { |
||||
// 修改 processcheck = 0 |
||||
if ($request->processcheck == 0) { |
||||
$this->updateIni($data->picture, $data->carnumber, "$request->carnumber", $data->violationtype, $request->violationtype); |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->violationcode = $request->viocode ?? $data->violationcode; |
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '編輯案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "編輯路口多功能案件: $data->carnumber ,案件日期: $data->datatime", |
||||
'carnumber' => $data->carnumber, |
||||
'location' => $data->location, |
||||
]; |
||||
} |
||||
// 舉發 processcheck = 1 |
||||
elseif ($request->processcheck == 1) { |
||||
if ($request->carnumber == null) { |
||||
return response()->json(['error' => '請輸入車牌號碼']); |
||||
} |
||||
if (isset($request->viocode)) { |
||||
if ($request->viocode == null) |
||||
return response()->json(['error' => '請選擇法條代碼']); |
||||
// 如果法條代碼不再資料表中 |
||||
if (!ViolationLaw::where('violationcode', $request->viocode)->exists()) { |
||||
return response()->json(['error' => '此法條代碼不存在']); |
||||
} |
||||
} else { |
||||
return response()->json(['error' => '請選擇法條代碼']); |
||||
} |
||||
$this->updateIni($data->picture, $data->carnumber, "$request->carnumber", $data->violationtype, $request->violationtype); |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->violationcode = $request->viocode ?? $data->violationcode; |
||||
$data->processcheck = 1; |
||||
|
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "舉發路口多功能案件: $data->carnumber ,案件日期: $data->datatime", |
||||
'carnumber' => $data->carnumber, |
||||
'location' => $data->location, |
||||
]; |
||||
$aaData['picture'] = $data->picture; |
||||
$aaData['picture2'] = $data->picture2; |
||||
$aaData['datatime'] = $data->datatime; |
||||
$this->saveFinishFile($aaData); |
||||
} |
||||
// 不舉發 processcheck = 2 |
||||
elseif ($request->processcheck == 2) { |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->unreportreason = $request->unreportreason ?? $data->unreportreason; |
||||
$data->processcheck = 2; |
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '不舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "不舉發路口多功能案件: $data->carnumber ,案件日期: $data->datatime", |
||||
'carnumber' => $data->carnumber, |
||||
'location' => $data->location, |
||||
]; |
||||
} |
||||
// 還原 processcheck = 3 |
||||
elseif ($request->processcheck == 3) { |
||||
//路徑位置設定 |
||||
$destPath_root = $this->destPath_root; |
||||
$clientDestPath_root = $this->clientDestPath_root; |
||||
$unreportPath_root = $this->unreportPath_root; |
||||
|
||||
// $fileName = explode('*', $data->picture)[4]; // 抓取檔名(寫死的) |
||||
$fileName = explode('*', $data->picture)[3]; |
||||
// $fileName2 = explode('*', $data->picture2)[3]; |
||||
$time = str_replace('-', '', explode(' ', $data->datatime)[0]); |
||||
|
||||
#region 已審照片 還原時刪除 |
||||
$iniPath = $destPath_root . Auth::user()->account . "\\" . $time . '\\' . str_replace('jpg', 'ini', $fileName); |
||||
$photoPath = $destPath_root . Auth::user()->account . "\\" . $time . '\\' . $fileName; |
||||
// $photoPath2 = $destPath_root.Auth::user()->account."\\".$time.'\\'.$fileName2; |
||||
$clientDestIniPath = $clientDestPath_root . $time . '\\' . str_replace('jpg', 'ini', $fileName); // 第二路徑測試機用不到 |
||||
$clientDestPhotoPath = $clientDestPath_root . $time . '\\' . $fileName; |
||||
// $clientDestPhotoPath2 = $clientDestPath_root.Auth::user()->account."\\".$time.'\\'.$fileName2; |
||||
|
||||
|
||||
if (file_exists($iniPath)) { |
||||
unlink($iniPath); |
||||
} |
||||
if (file_exists($photoPath)) { |
||||
unlink($photoPath); |
||||
} |
||||
// if (file_exists($photoPath2)) { unlink($photoPath2);} |
||||
if (file_exists($clientDestIniPath)) { |
||||
unlink($clientDestIniPath); |
||||
} |
||||
if (file_exists($clientDestPhotoPath)) { |
||||
unlink($clientDestPhotoPath); |
||||
} |
||||
// if (file_exists($clientDestPhotoPath2)) { unlink($clientDestPhotoPath2);} |
||||
|
||||
#endregion |
||||
#region 不舉發合成圖片 還原時刪除 |
||||
$unreportiniPath = $unreportPath_root . $time . '\\' . str_replace('jpg', 'ini', $fileName); |
||||
$unreportphotoPath = $unreportPath_root . $time . '\\' . $fileName; |
||||
|
||||
if (file_exists($unreportiniPath)) { |
||||
unlink($unreportiniPath); |
||||
} |
||||
if (file_exists($unreportphotoPath)) { |
||||
unlink($unreportphotoPath); |
||||
} |
||||
#endregion |
||||
|
||||
|
||||
$data->violationcode = null; |
||||
$data->unreportreason = ''; |
||||
$data->processcheck = 0; |
||||
$logData = [ |
||||
'action' => 'reduction', |
||||
'action_detail' => '還原案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "還原路口多功能案件: $data->carnumber ,案件日期: $data->datatime", |
||||
'carnumber' => $data->carnumber, |
||||
'location' => $data->location, |
||||
]; |
||||
} |
||||
} |
||||
|
||||
// 紀錄審查者 帳號 |
||||
$data->jsoncheck = auth('api')->user()->account; |
||||
// 資料儲存 |
||||
$data->save(); |
||||
// 紀錄 LOG |
||||
LogWriter::writeLog($logData, 'api'); |
||||
|
||||
DB::commit(); |
||||
// all good |
||||
return response()->json(['success' => $logData['remark']]); |
||||
} catch (\Exception $e) { |
||||
DB::rollback(); |
||||
return response()->json(['error' => '系統錯誤']); |
||||
// something went wrong |
||||
} |
||||
} |
||||
|
||||
#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 = Multisys::query(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) |
||||
$records->where('carnumber', 'like', '%' . $searchValue . '%'); |
||||
//已審未審 |
||||
//清冊用 99 |
||||
$records->where('violationtype', '!=', '違規臨時停車'); |
||||
if (isset($request->violationtype)) { |
||||
$records->whereIn('violationtype', $request->violationtype); |
||||
} |
||||
#region 審查狀態 |
||||
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); |
||||
} |
||||
#endregion |
||||
|
||||
#region 常用搜尋條件 |
||||
//設備限制 |
||||
$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 . '%'); |
||||
|
||||
#endregion |
||||
|
||||
$totalRecords = $records->count(); |
||||
$totalRecordswithFilter = $records->count(); |
||||
|
||||
#region 報表類型 |
||||
//如果有報表類型(1,2,3,...),並需要特別處理欄位的報表 |
||||
if (isset($request->statisticstype)) { |
||||
if ($request->statisticstype == 2) |
||||
$records->groupBy('serialnumber', 'cartype')->select('*', DB::raw('count(*) as count')); |
||||
else if ($request->statisticstype == 3) { |
||||
$currentYear = date('Y'); |
||||
$lastYear = $currentYear - 1; |
||||
$groupbyPara1 = "CAST(DATE_FORMAT(datatime, '%H') AS INT)"; |
||||
$records->groupBy(DB::raw($groupbyPara1), 'serialnumber', 'violationtype')->select('*', DB::raw('COUNT(*) as count, CONCAT(CAST(DATE_FORMAT(datatime,"%H") as INT),"-",CAST(DATE_FORMAT(DATE_ADD(datatime,INTERVAL +1 HOUR),"%H") as INT)) AS period')); |
||||
// $records->addSelect(DB::raw("(SELECT COUNT(*) FROM multisys AS sub_records WHERE DATE_FORMAT(sub_records.datatime,'%Y') = '$lastYear' AND sub_records.serialnumber = multisys.serialnumber AND sub_records.violationtype = multisys.violationtype) AS last_count")); |
||||
$records->orderBy(DB::raw($groupbyPara1), 'ASC'); |
||||
} else if ($request->statisticstype == 4) { |
||||
if ($request->searchByYear) |
||||
$records->whereYear('datatime', $request->searchByYear); |
||||
$records->groupBy('serialnumber', 'cartype')->select('*', DB::raw('count(*) as count')); |
||||
// 去年同期資料 與上述條件相同 |
||||
$lastYear = $request->searchByYear - 1; |
||||
// $records->addSelect(DB::raw("(SELECT COUNT(*) FROM multisys AS sub_records WHERE DATE_FORMAT(sub_records.datatime,'%Y') = '$lastYear' AND sub_records.serialnumber = multisys.serialnumber AND sub_records.cartype = multisys.cartype) AS last_count")); |
||||
// dd($records->toSql(), $records->getBindings()); |
||||
} else if ($request->statisticstype == 5) { |
||||
} |
||||
} else { |
||||
$records->select('*'); |
||||
} |
||||
#endregion |
||||
|
||||
#region DataTable 分頁(報表不分頁) |
||||
if (!isset($request->export)) { |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
} |
||||
#endregion |
||||
|
||||
$records = $records->get(); |
||||
|
||||
#region 資料處理 |
||||
$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; |
||||
$violationcode = $record->violationcode; |
||||
$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' => "輕型機車", |
||||
'8' => "微型電動二輪車", |
||||
'砂石車' => "砂石車" |
||||
|
||||
]; |
||||
|
||||
$processCheckTitle = [ |
||||
'0' => "未審", |
||||
'1' => "已審查", |
||||
'2' => "不舉發" |
||||
]; |
||||
|
||||
if (!isset($cartype)) |
||||
$cartype = 1; |
||||
|
||||
if ($violationcode != null) { |
||||
$display_name = ViolationLaw::where('violationcode', $violationcode)->first()->display_name ?? ''; |
||||
$violationdata = "[$violationcode]" . $display_name; |
||||
} |
||||
$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', $picture), |
||||
"violationtype" => $violationtype, |
||||
"violationdata" => $violationdata ?? '', |
||||
"lawType" => $record->lawType ?? '', |
||||
"cartype" => $cartype, |
||||
"carkind" => $cartypeTitle[$cartype], |
||||
"unreportreason" => $unreportreason ?? '', |
||||
"unreportpicture" => $unreportpicture ?? $picture, |
||||
"postcheck" => $postcheck, |
||||
// 清冊用 |
||||
"processcheck" => $processCheckTitle[$processcheck], |
||||
// "searchByFromdate" => $searchByFromdate, |
||||
// "searchByTodate"=> $searchByTodate, |
||||
"count" => $count, |
||||
"period" => $period, |
||||
"last_count" => $record->last_count ?? 0 |
||||
); |
||||
} |
||||
#endregion |
||||
|
||||
#region 如果需要去年同期比較 |
||||
$data_last_year = []; |
||||
if (isset($request->searchByFromdate) && isset($request->searchByTodate) && $processcheckStatus == 99) { |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
$searchByTodate = $request->searchByTodate; |
||||
$searchByFromdate = Carbon::parse($searchByFromdate)->subYear()->format('Y-m-d'); |
||||
$searchByTodate = Carbon::parse($searchByTodate)->subYear()->format('Y-m-d'); |
||||
$records = Multisys::query(); |
||||
$records->where('violationtype', '!=', '違規臨時停車'); |
||||
$records->where('datatime', ">", $searchByFromdate . ' 00:00:00'); |
||||
$records->where('datatime', "<", $searchByTodate . ' 23:59:59'); |
||||
$records->whereIn('processcheck', [0, 1, 2]); |
||||
$records->whereIn('serialnumber', $device); |
||||
if ($request->statisticstype == 2) |
||||
$records->groupBy('serialnumber', 'cartype')->select('*', DB::raw('count(*) as count')); |
||||
if ($request->statisticstype == 3) { |
||||
$groupbyPara1 = "CAST(DATE_FORMAT(datatime, '%H') AS INT)"; |
||||
$currentYear = date('Y'); |
||||
$lastYear = $currentYear - 1; |
||||
$records->groupBy(DB::raw($groupbyPara1), 'serialnumber', 'violationtype')->select('*', DB::raw('COUNT(*) as count, CONCAT(CAST(DATE_FORMAT(datatime,"%H") as INT),"-",CAST(DATE_FORMAT(DATE_ADD(datatime,INTERVAL +1 HOUR),"%H") as INT)) AS period')); |
||||
$records->addSelect(DB::raw("(SELECT COUNT(*) FROM multisys AS sub_records WHERE DATE_FORMAT(sub_records.datatime,'%Y') = '$lastYear' AND sub_records.serialnumber = multisys.serialnumber AND sub_records.violationtype = multisys.violationtype) AS last_count")); |
||||
$records->orderBy(DB::raw($groupbyPara1), 'ASC'); |
||||
} |
||||
$records = $records->get(); |
||||
foreach ($records as $record) { |
||||
$data_last_year[] = array( |
||||
"datatime" => $record->datatime, |
||||
"serialnumber" => $record->serialnumber, |
||||
"location" => $record->location, |
||||
"carnumber" => $record->carnumber, |
||||
"picture" => $record->picture, |
||||
"picture2" => $record->picture2, |
||||
"violationtype" => $record->violationtype, |
||||
"cartype" => $record->cartype, |
||||
"unreportreason" => $record->unreportreason ?? '', |
||||
"unreportpicture" => $record->unreportpicture ?? $record->picture, |
||||
"processcheck" => $processCheckTitle[$record->processcheck], |
||||
"count" => $record->count ?? 0, |
||||
"period" => $record->period ?? "", |
||||
"last_count" => $record->last_count ?? 0 |
||||
); |
||||
} |
||||
} |
||||
|
||||
return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr, $data_last_year]; |
||||
} |
||||
#endregion |
||||
|
||||
|
||||
|
||||
// 清冊用 |
||||
public function Statistics() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new MultisysEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new Multisys(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.multisys.statistics') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('violationtype', $violationtype); |
||||
} |
||||
public function StatisticsYears() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new MultisysEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new Multisys(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.multisys.statistics_years') |
||||
->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, $data_arr2] = $this->getData($device, $request, $processcheckStatus); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
|
||||
return $response; |
||||
} |
||||
|
||||
public function getStatisticsDataExport(Request $request) |
||||
{ |
||||
#region 設備限制 |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
#endregion |
||||
$processcheckStatus = 99; |
||||
|
||||
if ($request->statisticstype == 1) { |
||||
$remark = '違規件數清冊'; |
||||
$columns = ['datatime', 'serialnumber', 'location', 'carnumber', 'violationtype', 'processcheck']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['違規時段', '設備編號', '違規地點', '車號', '違規類型', '審查狀態'] |
||||
]; |
||||
} elseif ($request->statisticstype == 2) { |
||||
$remark = '違規件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'violationtype', 'carkind', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['設備編號', '違規地點', '違規類型', '車種', '統計'] |
||||
]; |
||||
} elseif ($request->statisticstype == 3) { |
||||
$remark = '違規時段件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'period', 'violationtype', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['設備編號', '違規地點', '違規時段', '違規類型', '統計'] |
||||
]; |
||||
} elseif ($request->statisticstype == 3) { |
||||
$remark = '違規時段件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'period', 'violationtype', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['設備編號', '違規地點', '違規時段', '違規類型', '統計'] |
||||
]; |
||||
} |
||||
|
||||
if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { |
||||
} |
||||
|
||||
[$draw, $totalRecords, $totalRecordswithFilter, $data_arr, $data_arr2] = $this->getData($device, $request, $processcheckStatus); |
||||
$data = array_map(function ($row) use ($columns) { |
||||
$data = array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); |
||||
return $data; |
||||
}, $data_arr); |
||||
|
||||
$fileName = 'ms-' . Str::random(10) . '.xlsx'; |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "路口多功能-$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('export', ['fileName' => $fileName])], 200); |
||||
} |
||||
|
||||
public function Export(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 Analysis() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new MultisysEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new Multisys(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.multisys.analysis') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('violationtype', $violationtype); |
||||
} |
||||
|
||||
public function getAnalysisData(Request $request) |
||||
{ |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
$records = Multisys::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'); |
||||
if (isset($request->search_todate)) |
||||
$records->where('datatime', "<", $request->search_todate . ' 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 = Multisys::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'); |
||||
if (isset($request->search_todate)) |
||||
$records2->where('datatime', "<", $request->search_todate . ' 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); |
||||
} |
||||
} |
||||
|
||||
// dd($data); |
||||
return response()->json(['data' => $data, 'chart_type' => $request->chart_type, 'violationtype' => $violationTypes ?? ''], 200); |
||||
} |
||||
|
||||
// statistics |
||||
// public function statistics() |
||||
// { |
||||
// return view('system.multisys.statistics'); |
||||
// } |
||||
|
||||
public function getStatisticsTest(Request $request) |
||||
{ |
||||
$request->statisticstype; |
||||
// 讀取json file (storage/app/data/get-ms-statistics-1~3.json ) |
||||
|
||||
$json = file_get_contents(storage_path('app/data/get-ms-statistics-1.json')); |
||||
} |
||||
|
||||
//getLocationByViolationtype |
||||
public function getLocationByViolationtype(Request $request) |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$records = Multisys::query(); |
||||
$records->whereIn('serialnumber', $device); |
||||
if (isset($request->violationtype)) |
||||
$records->whereIn('violationtype', $request->violationtype); |
||||
$records->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$data = $records->get(); |
||||
return response()->json(['data' => $data]); |
||||
} |
||||
#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; |
||||
|
||||
$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; |
||||
if (is_dir($destPath) === false) { |
||||
mkdir($destPath, 0777, true); |
||||
} |
||||
try { |
||||
copy($iniPath, $destPath . '\\' . str_replace('jpg', 'ini', $photoName)); |
||||
copy($photoPath, $destPath . '\\' . $photoName); |
||||
// copy($photoPath2, $destPath.'\\'.$photoName2); |
||||
// 存入第二路徑供客戶操作資料 |
||||
$clientDestPath = $clientDestPath_root . $time; |
||||
if (is_dir($clientDestPath) === false) { |
||||
mkdir($clientDestPath, 0777, true); |
||||
} |
||||
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 = Multisys::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 = "MS_OK_" . $fileName; |
||||
if ($processcheck == 2) |
||||
$fileName = "MS_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 |
||||
|
||||
} |
@ -0,0 +1,264 @@
@@ -0,0 +1,264 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Models\MultisysEquipment; |
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\AssetOwnership; |
||||
use App\Models\CustodyUnit; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
|
||||
class MultisysEquipmentController extends Controller |
||||
{ |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->middleware('permission:ms-device-setting'); |
||||
} |
||||
|
||||
public function page() |
||||
{ |
||||
// ['custodyunit' => $custodyunit, 'assetownership' => $assetownership] |
||||
|
||||
$custodyunit = CustodyUnit::all(); |
||||
$assetownership = AssetOwnership::all(); |
||||
return view('system.multisys.equipment') |
||||
->with('custodyunit', $custodyunit) |
||||
->with('assetownership', $assetownership); |
||||
} |
||||
|
||||
/** |
||||
* Display a listing of the resource. |
||||
*/ |
||||
public function index(Request $request) |
||||
{ |
||||
#region DataTable 搜尋屬性 |
||||
$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 |
||||
#endregion |
||||
|
||||
// Role with permissions |
||||
$records = MultisysEquipment::query(); |
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
// $query->where('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('name', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('serialnumber', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('creator_id', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
|
||||
$data_arr = $records->get(); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
return response()->json($response); |
||||
} |
||||
|
||||
/** |
||||
* Store a newly created resource in storage. |
||||
*/ |
||||
public function store(Request $request) |
||||
{ |
||||
$device = new MultisysEquipment(); |
||||
// 如果缺少必要欄位 |
||||
|
||||
DB::beginTransaction(); |
||||
try { |
||||
|
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id; |
||||
$device->assetownership_id = $request->assetownership_id; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
|
||||
|
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
|
||||
return response()->json(['success' => true, 'message' => '新增成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display the specified resource. |
||||
*/ |
||||
public function show(string $id) |
||||
{ |
||||
$device = MultisysEquipment::find($id); |
||||
return response()->json(['success' => true, 'data' => $device]); |
||||
} |
||||
|
||||
/** |
||||
* Update the specified resource in storage. |
||||
*/ |
||||
public function update(Request $request, string $id) |
||||
{ |
||||
$device = MultisysEquipment::find($id); |
||||
if (!$request->serialnumber || !$request->location || !$request->precinct || !$request->station) { |
||||
return response()->json(['success' => false, 'message' => '缺少必要欄位']); |
||||
} |
||||
DB::beginTransaction(); |
||||
try { |
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id ?? null; |
||||
$device->assetownership_id = $request->assetownership_id ?? null; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'update', |
||||
'action_detail' => '更新設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "更新設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '更新成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '更新失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove the specified resource from storage. |
||||
*/ |
||||
public function destroy(string $id) |
||||
{ |
||||
$device = MultisysEquipment::find($id); |
||||
try { |
||||
$device->delete(); |
||||
return response()->json(['success' => true, 'message' => '刪除成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
return response()->json(['success' => false, 'message' => '刪除失敗']); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 取得保管單位資料 |
||||
*/ |
||||
public function indexUnit(Request $request) |
||||
{ |
||||
|
||||
if($request->type == "custodyunit"){ |
||||
$unit = CustodyUnit::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
}else if ($request->type == "assetownership"){ |
||||
$unit = AssetOwnership::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
} |
||||
|
||||
return response()->json(['success' => false, 'message' => '取得失敗']); |
||||
} |
||||
|
||||
/** |
||||
* 新增單位資料 |
||||
*/ |
||||
public function storeUnit(Request $request) |
||||
{ |
||||
// custodyunit_id |
||||
//assetownership_id) |
||||
DB::beginTransaction(); |
||||
try { |
||||
if($request->type == "custodyunit"){ |
||||
$unit = new CustodyUnit(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增保管單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增保管單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '保管單位-新增成功']); |
||||
}else if ($request->type == "assetownership"){ |
||||
$unit = new AssetOwnership(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增財產所屬單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增財產所屬單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '財產所屬單位-新增成功']); |
||||
} |
||||
|
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
} |
||||
|
||||
|
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
@ -0,0 +1,897 @@
@@ -0,0 +1,897 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Exports\ArrayExport; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\OverSpeedRed; |
||||
use App\Models\OverSpeedRedEquipment; |
||||
use App\Models\ViolationLaw; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
use Intervention\Image\ImageManager; |
||||
use Intervention\Image\Drivers\Gd\Driver; |
||||
use ZipArchive; |
||||
|
||||
class OverSpeedController extends Controller |
||||
{ |
||||
public $destPath_root; |
||||
public $clientDestPath_root; |
||||
public $unreportPath_root; |
||||
public $month; |
||||
|
||||
function __construct() |
||||
{ |
||||
$this->middleware('permission:overspeed-review|overspeed-reduction|overspeed-device-setting|overspeed-statistics|overspeed-analysis|overspeed-read', ['only' => ['Review']]); |
||||
$this->middleware('permission:overspeed-review|permission:overspeed-reduction', ['only' => ['update']]); |
||||
$this->middleware('permission:overspeed-device-setting', ['only' => ['DeviceSetting']]); |
||||
$this->middleware('permission:overspeed-statistics', ['only' => ['Statistics']]); |
||||
$this->middleware('permission:overspeed-analysis', ['only' => ['Analysis']]); |
||||
// OK path |
||||
$this->destPath_root = 'D:\\OK\\OverSpeed\\'; |
||||
$this->clientDestPath_root = 'Y:\\'; |
||||
// NOK path |
||||
$this->unreportPath_root = 'C:\\xampp\\SMMS\\storage\\app\\ParsingFiles\\NOK\\OverSpeed\\'; |
||||
$this->month['start'] = Carbon::now()->subDays(8)->format('Y-m-d'); |
||||
$this->month['current'] = Carbon::now()->subDays(1)->format('Y-m-d'); |
||||
} |
||||
|
||||
public function Review() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// dd($device); |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new OverSpeedRed(); |
||||
$locationtype = $violationparking::where('processcheck', 0)->whereIn('violationtype', ['超速'])->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.overspeed.index') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('vio_arr', $vio_arr) |
||||
->with('month', $this->month); |
||||
} |
||||
|
||||
#region 已審 View |
||||
public function Censored(Request $request) |
||||
{ |
||||
|
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new OverSpeedRed(); |
||||
$locationtype = $violationparking::where('processcheck', 1)->whereIn('violationtype', ['超速'])->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); |
||||
|
||||
// dd($data,$page_data); |
||||
return view('system.overspeed.manage') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('month', $this->month); |
||||
} |
||||
#endregion |
||||
|
||||
#region 不舉發 View |
||||
public function Unreport(Request $request) |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new OverSpeedRed(); |
||||
$locationtype = $violationparking::where('processcheck', 2)->whereIn('violationtype', ['超速'])->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); |
||||
$unreportreason = $violationparking->where('processcheck', 2)->whereIn('violationtype', ['超速'])->whereIn('serialnumber', $device)->groupBy('unreportreason')->pluck('unreportreason'); |
||||
// dd($locationtype,$unreportreason); |
||||
return view('system.overspeed.unreport') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('unreportreason', $unreportreason) |
||||
->with('month', $this->month); |
||||
} |
||||
#endregion |
||||
public function mergePic(Request $request) |
||||
{ |
||||
$path = $request->path; |
||||
$image = $request->image; |
||||
// dd($path,$image); |
||||
$data = OverSpeedRed::where('picture', 'like', '%' . $path . '%')->first(); |
||||
// dd($path,$image,$data); |
||||
if ($data) { |
||||
// 使用 Intervention Image 套件開啟圖片檔案 |
||||
$manager = new ImageManager(new Driver()); |
||||
$photoPath = str_replace('*', '\\', storage_path('app' . '\\' . 'ParsingFiles' . '\\' . "$data->picture")); |
||||
$originalImage = $manager->read($photoPath); |
||||
// $originalImage = Image::read($photoPath); |
||||
$cnum = ""; |
||||
// 取得前端傳來的 base64 圖片資料 |
||||
$croppedImage = $manager->read($request->image); |
||||
// $croppedImage = Image::read($request->image); |
||||
$croppedImage->resize($croppedImage->width() * 4, $croppedImage->height() * 4); |
||||
// 獲取圖片的寬度和高度 |
||||
$originalWidth = $originalImage->width(); |
||||
$originalHeight = $originalImage->height(); |
||||
$croppedWidth = $croppedImage->width(); |
||||
$croppedHeight = $croppedImage->height(); |
||||
// dd($originalWidth, $originalHeight, $croppedWidth, $croppedHeight, $request->position); |
||||
// 將裁切後的圖片合成於原圖 |
||||
// 如果 $request->position 為 1,則將圖片合成於左下角,2 為右下角,3 為左上角,4 為右上角 |
||||
|
||||
switch ($request->position) { |
||||
case 1: |
||||
$originalImage->place($croppedImage, 'bottom-left'); |
||||
break; |
||||
case 2: |
||||
$originalImage->place($croppedImage, 'bottom-right'); |
||||
break; |
||||
case 3: |
||||
$originalImage->place($croppedImage, 'top-left', 0, 210); |
||||
break; |
||||
case 4: |
||||
$originalImage->place($croppedImage, 'top-right', 0, 210); |
||||
break; |
||||
default: |
||||
$originalImage->place($croppedImage, 'bottom-left'); |
||||
break; |
||||
} |
||||
|
||||
// $originalImage->place($croppedImage, 'bottom-left', 0, 0); |
||||
|
||||
// 儲存合成後的圖片檔案 |
||||
$photoName = explode('*', $data['picture']); |
||||
$photoName = end($photoName); |
||||
$time = str_replace('-', '', explode(' ', $data['datatime'])[0]); |
||||
$violationtype = $data['violationtype']; |
||||
$photoPath = public_path("merge\\$violationtype\\$time\\$photoName"); |
||||
if (is_dir(public_path("merge\\$violationtype\\$time")) === false) { |
||||
mkdir(public_path("merge\\$violationtype\\$time"), 0777, true); |
||||
} |
||||
$originalImage->save($photoPath); |
||||
// $originalImage->save(public_path('merge\\' . $path)); |
||||
|
||||
// 將合成後的圖片路徑存入資料庫 |
||||
// $data->mergepic = $this->merge_root.$path; |
||||
// $data->save(); |
||||
|
||||
return response()->json(['path' => "/merge/$violationtype/$time/$path", 'carnubmer' => $cnum], 200); |
||||
} |
||||
return response()->json(['path' => 'error'], 400); |
||||
} |
||||
public function update(Request $request, $id) |
||||
{ |
||||
$data = OverSpeedRed::find($id); |
||||
// 先確認 processcheck 狀態 0 修改 1 舉發 2 不舉發 |
||||
// 確認使用者是否可以 review |
||||
DB::beginTransaction(); |
||||
|
||||
try { |
||||
// 如果使用者具 審查權限 |
||||
if (auth('api')->user()->can('overspeed-review')) { |
||||
// 修改 processcheck = 0 |
||||
if ($request->processcheck == 0) { |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->violationcode = $request->viocode ?? $data->violationcode; |
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '編輯案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "編輯闖紅/超速案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
} |
||||
// 舉發 processcheck = 1 |
||||
elseif ($request->processcheck == 1) { |
||||
if ($request->carnumber == null) { |
||||
return response()->json(['error' => '請輸入車牌號碼']); |
||||
} |
||||
if (isset($request->viocode)) { |
||||
if ($request->viocode == null) |
||||
return response()->json(['error' => '請選擇法條代碼']); |
||||
// 如果法條代碼不再資料表中 |
||||
if (!ViolationLaw::where('violationcode', $request->viocode)->exists()) { |
||||
return response()->json(['error' => '此法條代碼不存在']); |
||||
} |
||||
} else { |
||||
return response()->json(['error' => '請選擇法條代碼']); |
||||
} |
||||
$this->updateIni($data->picture, $data->carnumber, "$request->carnumber", $data->violationtype, $request->violationtype); |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->violationcode = $request->viocode ?? $data->violationcode; |
||||
$data->processcheck = 1; |
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "舉發闖紅/超速案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
$pth = explode('*', $data->picture); |
||||
$photoPath = str_replace('*', '\\', storage_path('app' . '\\' . 'ParsingFiles' . '\\' . "$data->picture")); |
||||
$pth = end($pth); |
||||
$violationtype = $data->violationtype; |
||||
$time = str_replace('-', '', explode(' ', $data->datatime)[0]); |
||||
// public_path('merge\\'.$path) |
||||
$mgpath = public_path("merge\\$violationtype\\$time\\$pth"); |
||||
if (!file_exists($mgpath)) { |
||||
if (is_dir(public_path("merge\\$violationtype\\$time")) === false) { |
||||
mkdir(public_path("merge\\$violationtype\\$time"), 0777, true); |
||||
} |
||||
copy($photoPath, $mgpath); |
||||
} |
||||
$aaData['picture'] = $data->picture; |
||||
$aaData['picture2'] = $data->picture2; |
||||
$aaData['datatime'] = $data->datatime; |
||||
$aaData['violationtype'] = $data->violationtype; |
||||
$this->saveFinishFile($aaData); |
||||
} |
||||
// 不舉發 processcheck = 2 |
||||
elseif ($request->processcheck == 2) { |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->unreportreason = $request->unreportreason ?? $data->unreportreason; |
||||
$data->processcheck = 2; |
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '不舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "不舉發闖紅/超速案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
} |
||||
// 還原 processcheck = 3 |
||||
elseif ($request->processcheck == 3) { |
||||
$data->violationcode = null; |
||||
$data->unreportreason = ''; |
||||
$data->processcheck = 0; |
||||
$logData = [ |
||||
'action' => 'reduction', |
||||
'action_detail' => '還原案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "還原闖紅/超速案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
} |
||||
} |
||||
|
||||
// 紀錄審查者 帳號 |
||||
$data->jsoncheck = auth('api')->user()->account; |
||||
// 資料儲存 |
||||
$data->save(); |
||||
// 紀錄 LOG |
||||
LogWriter::writeLog($logData, 'api'); |
||||
|
||||
DB::commit(); |
||||
// all good |
||||
return response()->json(['success' => $logData['remark']]); |
||||
} catch (\Exception $e) { |
||||
DB::rollback(); |
||||
return response()->json(['error' => '系統錯誤']); |
||||
// something went wrong |
||||
} |
||||
} |
||||
|
||||
#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 = OverSpeedRed::query(); |
||||
$records->whereIn('violationtype', ['超速']); |
||||
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')); |
||||
if ($request->statisticstype == 3) { |
||||
$groupbyPara1 = "CAST(DATE_FORMAT(datatime, '%H') AS INT)"; |
||||
$records->groupBy(DB::raw($groupbyPara1), 'serialnumber', 'violationtype')->select('*', DB::raw('COUNT(*) as count, CONCAT(CAST(DATE_FORMAT(datatime,"%H") as INT),"-",CAST(DATE_FORMAT(DATE_ADD(datatime,INTERVAL +1 HOUR),"%H") as INT)) AS period')); |
||||
$records->orderBy(DB::raw($groupbyPara1), 'ASC'); |
||||
} |
||||
} 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; |
||||
$violationcode = $record->violationcode; |
||||
$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' => "輕型機車", |
||||
'8' => "微型電動二輪車" |
||||
]; |
||||
|
||||
$processCheckTitle = [ |
||||
'0' => "未審", |
||||
'1' => "已審查", |
||||
'2' => "不舉發" |
||||
]; |
||||
|
||||
if (!isset($cartype)) |
||||
$cartype = 1; |
||||
// 如果車牌 = None 則 顯示 "" |
||||
if ($carnumber == "None") |
||||
$carnumber = ""; |
||||
|
||||
if ($violationcode == null) { |
||||
if ($record->speed != 0) { |
||||
// 去除 km/h |
||||
$speed = explode('km/h', $record->speed)[0]; |
||||
$speed = (int) $speed; |
||||
// 去除 km/h |
||||
$limitspeed = explode('km/h', $record->limitspeed)[0]; |
||||
$limitspeed = (int) $limitspeed; |
||||
|
||||
// 超速 |
||||
// 如果 speed > $record->limitspeed 20以內法條 4000005 20~40 4000006 40~60 4000007 |
||||
if ($speed > $limitspeed) { |
||||
$violationcode = 4000005; |
||||
if ($speed > $limitspeed + 20) { |
||||
$violationcode = 4000006; |
||||
if ($speed > $limitspeed + 40) { |
||||
$violationcode = 4000007; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
$pthar = explode('*', $record->picture); |
||||
$pth = $pthar[count($pthar) - 1]; |
||||
$time = str_replace('-', '', explode(' ', $datatime)[0]); |
||||
// public_path('merge\\'.$path) |
||||
$mgpath = public_path("merge\\$violationtype\\$time\\$pth"); |
||||
$mergepic = 0; |
||||
if (file_exists($mgpath)) { |
||||
$mergepic = "merge/$violationtype/$time/$pth"; |
||||
} |
||||
if ($violationcode != null) { |
||||
$display_name = ViolationLaw::where('violationcode', $violationcode)->first()->display_name ?? ''; |
||||
$violationdata = "[$violationcode]" . $display_name; |
||||
// $violationdata = "[$violationcode]" . ViolationLaw::where('violationcode', $violationcode)->first()->display_name; |
||||
} |
||||
$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', $picture), |
||||
"violationtype" => $violationtype, |
||||
"violationcode" => $violationcode ?? '', |
||||
"violationdata" => $violationdata ?? '', |
||||
"lawType" => $record->lawType ?? '', |
||||
"cartype" => $cartype, |
||||
"carkind" => $cartypeTitle[$cartype], |
||||
"speed" => $record->speed ?? '', |
||||
"unreportreason" => $unreportreason ?? '', |
||||
"unreportpicture" => $unreportpicture ?? $picture, |
||||
"mergepic" => $mergepic ?? '0', |
||||
"postcheck" => $postcheck, |
||||
// 清冊用 |
||||
"processcheck" => $processCheckTitle[$processcheck], |
||||
// "searchByFromdate" => $searchByFromdate, |
||||
// "searchByTodate"=> $searchByTodate, |
||||
"count" => $count, |
||||
"period" => $period |
||||
); |
||||
} |
||||
return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr]; |
||||
} |
||||
#endregion |
||||
|
||||
// 清冊用 |
||||
public function Statistics() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new OverSpeedRed(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->whereIn('violationtype', ['超速'])->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.overspeed.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) |
||||
{ |
||||
#region 設備限制 |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
#endregion |
||||
$processcheckStatus = 99; |
||||
|
||||
if ($request->statisticstype == 1) { |
||||
$remark = '違規件數清冊'; |
||||
$columns = ['datatime', 'serialnumber', 'location', 'carnumber', 'violationtype', 'processcheck']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['違規時段', '設備編號', '違規地點', '車號', '違規類型', '審查狀態'] |
||||
]; |
||||
} elseif ($request->statisticstype == 2) { |
||||
$remark = '違規件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'violationtype', 'carkind', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['設備編號', '違規地點', '違規類型', '車種', '統計'] |
||||
]; |
||||
} elseif ($request->statisticstype == 3) { |
||||
$remark = '違規時段件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'period', 'violationtype', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $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 = 'overspeed-' . Str::random(10) . '.xlsx'; |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "路口多功能-$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('overspeed-export', ['fileName' => $fileName])], 200); |
||||
} |
||||
|
||||
public function Export(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 Analysis() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new OverSpeedRed(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->whereIn('violationtype', ['超速'])->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.overspeed.analysis') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('violationtype', $violationtype); |
||||
} |
||||
|
||||
public function getAnalysisData(Request $request) |
||||
{ |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
$records = OverSpeedRed::query(); |
||||
$records->whereIn('serialnumber', $device)->whereIn('violationtype', ['超速'])->whereIn('processcheck', [1, 3]); |
||||
// dd($request->all()); |
||||
if (isset($request->search_fromdate)) |
||||
$records->where('datatime', ">", $request->search_fromdate . ' 00:00:00'); |
||||
if (isset($request->search_todate)) |
||||
$records->where('datatime', "<", $request->search_todate . ' 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 = OverSpeedRed::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'); |
||||
if (isset($request->search_todate)) |
||||
$records2->where('datatime', "<", $request->search_todate . ' 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->whereIn('violationtype', ['超速'])->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); |
||||
} |
||||
} |
||||
|
||||
// dd($data); |
||||
return response()->json(['data' => $data, 'chart_type' => $request->chart_type, 'violationtype' => $violationTypes ?? ''], 200); |
||||
} |
||||
|
||||
|
||||
public function getStatisticsTest(Request $request) |
||||
{ |
||||
$request->statisticstype; |
||||
// 讀取json file (storage/app/data/get-overspeed-statistics-1~3.json ) |
||||
|
||||
$json = file_get_contents(storage_path('app/data/get-overspeed-statistics-1.json')); |
||||
} |
||||
#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; |
||||
$violationtype = $data['violationtype']; |
||||
$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']); |
||||
$photoName = end($photoName); |
||||
$photoPath = public_path("merge\\$violationtype\\$time\\$photoName"); |
||||
// $photoName2 = explode('*', $data['picture2'])[3]; |
||||
$destPath = $destPath_root . Auth::user()->account . "\\" . $time; |
||||
if (is_dir($destPath) === false) { |
||||
mkdir($destPath, 0777, true); |
||||
} |
||||
try { |
||||
copy($iniPath, $destPath . '\\' . str_replace('jpg', 'ini', $photoName)); |
||||
copy($photoPath, $destPath . '\\' . $photoName); |
||||
// copy($photoPath2, $destPath.'\\'.$photoName2); |
||||
// 存入第二路徑供客戶操作資料 |
||||
$clientDestPath = $clientDestPath_root . $time; |
||||
if (is_dir($clientDestPath) === false) { |
||||
mkdir($clientDestPath, 0777, true); |
||||
} |
||||
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 = OverSpeedRed::query(); |
||||
$records->where('location', 'not like', '%測試%'); |
||||
$records->whereIn('serialnumber', $device)->whereIn('violationtype', ['超速']); |
||||
$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'); |
||||
foreach (glob(public_path() . '\*.zip') as $file) { |
||||
unlink($file); |
||||
} |
||||
$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 = "OSR_OK_" . $fileName; |
||||
if ($processcheck == 2) |
||||
$fileName = "OSR_X_" . $fileName; |
||||
} |
||||
|
||||
if ($zip->open(public_path($fileName), ZipArchive::CREATE) === TRUE) { |
||||
foreach ($files as $file) { |
||||
$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)); |
||||
} |
||||
} |
||||
$zip->close(); |
||||
} |
||||
|
||||
// response()->download(public_path($fileName))->deleteFileAfterSend(true); |
||||
return "$fileName"; |
||||
} |
||||
#endregion |
||||
|
||||
} |
@ -0,0 +1,258 @@
@@ -0,0 +1,258 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Models\OverSpeedRedEquipment; |
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\AssetOwnership; |
||||
use App\Models\CustodyUnit; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
|
||||
class OverSpeedRedEquipmentController extends Controller |
||||
{ |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->middleware('permission:overspeed-device-setting|red-device-setting'); |
||||
} |
||||
|
||||
public function page() |
||||
{ |
||||
// ['custodyunit' => $custodyunit, 'assetownership' => $assetownership] |
||||
|
||||
$custodyunit = CustodyUnit::all(); |
||||
$assetownership = AssetOwnership::all(); |
||||
return view('system.overspeed.equipment') |
||||
->with('custodyunit', $custodyunit) |
||||
->with('assetownership', $assetownership); |
||||
} |
||||
|
||||
/** |
||||
* Display a listing of the resource. |
||||
*/ |
||||
public function index(Request $request) |
||||
{ |
||||
#region DataTable 搜尋屬性 |
||||
$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 |
||||
#endregion |
||||
|
||||
// Role with permissions |
||||
$records = OverSpeedRedEquipment::query(); |
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
// $query->where('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('name', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('serialnumber', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('creator_id', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
|
||||
$data_arr = $records->get(); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
return response()->json($response); |
||||
} |
||||
|
||||
/** |
||||
* Store a newly created resource in storage. |
||||
*/ |
||||
public function store(Request $request) |
||||
{ |
||||
$device = new OverSpeedRedEquipment(); |
||||
DB::beginTransaction(); |
||||
try { |
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id; |
||||
$device->assetownership_id = $request->assetownership_id; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
|
||||
return response()->json(['success' => true, 'message' => '新增成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display the specified resource. |
||||
*/ |
||||
public function show(string $id) |
||||
{ |
||||
$device = OverSpeedRedEquipment::find($id); |
||||
return response()->json(['success' => true, 'data' => $device]); |
||||
} |
||||
|
||||
/** |
||||
* Update the specified resource in storage. |
||||
*/ |
||||
public function update(Request $request, string $id) |
||||
{ |
||||
$device = OverSpeedRedEquipment::find($id); |
||||
|
||||
DB::beginTransaction(); |
||||
try { |
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id ?? null; |
||||
$device->assetownership_id = $request->assetownership_id ?? null; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
|
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'update', |
||||
'action_detail' => '更新設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "更新設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '更新成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '更新失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove the specified resource from storage. |
||||
*/ |
||||
public function destroy(string $id) |
||||
{ |
||||
$device = OverSpeedRedEquipment::find($id); |
||||
try { |
||||
$device->delete(); |
||||
return response()->json(['success' => true, 'message' => '刪除成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
return response()->json(['success' => false, 'message' => '刪除失敗']); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 取得保管單位資料 |
||||
*/ |
||||
public function indexUnit(Request $request) |
||||
{ |
||||
|
||||
if($request->type == "custodyunit"){ |
||||
$unit = CustodyUnit::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
}else if ($request->type == "assetownership"){ |
||||
$unit = AssetOwnership::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
} |
||||
|
||||
return response()->json(['success' => false, 'message' => '取得失敗']); |
||||
} |
||||
|
||||
/** |
||||
* 新增單位資料 |
||||
*/ |
||||
public function storeUnit(Request $request) |
||||
{ |
||||
// custodyunit_id |
||||
//assetownership_id) |
||||
DB::beginTransaction(); |
||||
try { |
||||
if($request->type == "custodyunit"){ |
||||
$unit = new CustodyUnit(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增保管單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增保管單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '保管單位-新增成功']); |
||||
}else if ($request->type == "assetownership"){ |
||||
$unit = new AssetOwnership(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增財產所屬單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增財產所屬單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '財產所屬單位-新增成功']); |
||||
} |
||||
|
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
} |
||||
|
||||
|
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
@ -0,0 +1,179 @@
@@ -0,0 +1,179 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System\Permissions; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\Permission; |
||||
use App\Models\Role; |
||||
use Illuminate\Http\Request; |
||||
|
||||
class RoleController extends Controller |
||||
{ |
||||
function __construct() |
||||
{ |
||||
$this->middleware('permission:role-list|role-create|role-edit|role-delete', ['only' => ['RoleManager', 'show', 'index']]); |
||||
$this->middleware('permission:role-create', ['only' => ['storeRole']]); |
||||
$this->middleware('permission:role-edit', ['only' => ['updateRole']]); |
||||
$this->middleware('permission:role-delete', ['only' => ['deleteRole']]); |
||||
} |
||||
#region 管理群組(角色)管理 |
||||
public function RoleManager() |
||||
{ |
||||
$typeName = [ |
||||
0 => "檢視管理群組", |
||||
1 => "違規停車-審查", |
||||
2 => "區間-審查", |
||||
3 => "路口-審查", |
||||
4 => "禁行車種-審查", |
||||
5 => "檢視使用者", |
||||
]; |
||||
$permissions = Permission::query(); |
||||
// .env 檔案中的權限類型SYSTEM_MULTISYS SYSTEM_OVERSPEEDRED SYSTEM_VIOLATIONPARKING |
||||
$types = [1, 6]; |
||||
// dd($types); |
||||
if (env('SYSTEM_MULTISYS', false)) { |
||||
array_push($types, 4); |
||||
} |
||||
if (env('SYSTEM_INTERVAL', false)) { |
||||
array_push($types, 3); |
||||
} |
||||
if (env('SYSTEM_OVERSPEEDRED', false)) { |
||||
array_push($types, 7); |
||||
array_push($types, 8); |
||||
} |
||||
if (env('SYSTEM_VIOLATIONPARKING', false)) { |
||||
array_push($types, 2); |
||||
} |
||||
// dd($types); |
||||
$permissions = $permissions->whereIn('type', $types); |
||||
$permissions = $permissions->orderBy('type', 'asc')->orderBy('sort', 'asc')->get(); |
||||
|
||||
// 將權限根據 type 分類 並且排序 |
||||
$permissions = $permissions->sortBy('type')->groupBy('type'); |
||||
// dd(env('SYSTEM_MULTISYS', false), env('SYSTEM_OVERSPEEDRED', false), env('SYSTEM_VIOLATIONPARKING', false)); |
||||
// dd($permissions->toArray()); |
||||
return view('system.setting.RoleManager')->with('permissions', $permissions); |
||||
} |
||||
|
||||
public function index(Request $request) |
||||
{ |
||||
// 如果沒有登入 |
||||
if (!auth('api')->check()) { |
||||
return response()->json(['message' => 'Unauthenticated.'], 401); |
||||
} |
||||
|
||||
#region DataTable 搜尋屬性 |
||||
$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 |
||||
#endregion |
||||
|
||||
// Role with permissions |
||||
$records = Role::query(); |
||||
$records = $records->with('permissions'); |
||||
$records = $records->whereNotIn('id', [1]); |
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
// $query->where('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('name', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('serialnumber', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('creator_id', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
|
||||
$data_arr = $records->get(); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
return response()->json($response); |
||||
} |
||||
|
||||
// 新增管理群組 |
||||
public function store(Request $request) |
||||
{ |
||||
$data = $request->all(); |
||||
$idx = Role::max('id') + 1; |
||||
$data['name'] = "role-$idx"; |
||||
$data['guard_name'] = '*'; |
||||
$role = Role::create($data); |
||||
$role->syncPermissions($request->permission); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增管理群組', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增管理群組:$role->display_name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
return response()->json(['success' => '新增成功']); |
||||
} |
||||
|
||||
public function show(Request $request, $id) |
||||
{ |
||||
if (!auth('api')->check()) { |
||||
return response()->json(['message' => 'Unauthenticated.'], 401); |
||||
} |
||||
$role = Role::with('permissions')->find($id); |
||||
$permissions = Permission::orderBy('type', 'asc')->orderBy('sort', 'asc')->get(); |
||||
return response()->json(['role' => $role, 'permissions' => $permissions]); |
||||
} |
||||
|
||||
public function update(Request $request, $id) |
||||
{ |
||||
if ($id == 1) { |
||||
return response()->json(['error' => '此群組不可編輯']); |
||||
} |
||||
$role = Role::find($id); |
||||
$role->update($request->all()); |
||||
// sync permissions |
||||
$role->syncPermissions($request->permission); |
||||
|
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '編輯管理群組', |
||||
'ip' => request()->ip(), |
||||
'remark' => "編輯管理群組:$role->display_name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
return response()->json(['success' => '編輯成功']); |
||||
} |
||||
|
||||
// 刪除管理群組 |
||||
public function destory(Request $request, $id) |
||||
{ |
||||
if ($id == 1) { |
||||
return response()->json(['error' => '此群組不可刪除']); |
||||
} |
||||
$role = Role::find($id); |
||||
$role->delete(); |
||||
$logData = [ |
||||
'action' => 'delete', |
||||
'action_detail' => '刪除管理群組', |
||||
'ip' => request()->ip(), |
||||
'remark' => "刪除管理群組:$role->display_name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
return response()->json(['success' => '刪除成功']); |
||||
} |
||||
#endregion |
||||
} |
@ -0,0 +1,255 @@
@@ -0,0 +1,255 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System\Permissions; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Exports\ArrayExport; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\MultisysEquipment; |
||||
use App\Models\OverSpeedRed; |
||||
use App\Models\OverSpeedRedEquipment; |
||||
use App\Models\Permission; |
||||
use App\Models\Role; |
||||
use App\Models\User; |
||||
use App\Models\IntervalEquipment; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Hash; |
||||
use Illuminate\Support\Facades\Log; |
||||
use PhpParser\Node\Expr\AssignOp\Mul; |
||||
use Illuminate\Support\Str; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
|
||||
class UserController extends Controller |
||||
{ |
||||
function __construct() |
||||
{ |
||||
$this->middleware('permission:user-list|user-create|user-edit|user-delete', ['only' => ['UserManager', 'show', 'index']]); |
||||
$this->middleware('permission:user-create', ['only' => ['storeUser']]); |
||||
$this->middleware('permission:user-edit', ['only' => ['updateUser']]); |
||||
$this->middleware('permission:user-delete', ['only' => ['deleteUser']]); |
||||
} |
||||
#region 使用者管理 |
||||
public function UserManager() |
||||
{ |
||||
$permissions = Permission::all(); |
||||
$roles = Role::where('id', '!=', 1)->get(); |
||||
$equipments = [ |
||||
// "violationparking" => ViolationParkingEquipment::all(), |
||||
"multisys" => MultisysEquipment::all(), |
||||
"overspeedred" => OverSpeedRedEquipment::all(), |
||||
"interval"=> IntervalEquipment::all(), |
||||
]; |
||||
$equipments_title = [ |
||||
"multisys" => "路口多功能系統", |
||||
"overspeedred" => "闖紅燈超速", |
||||
"interval" => "區間測速", |
||||
]; |
||||
$allow = explode(",", auth()->user()->device); |
||||
// dd($roles->toArray()); |
||||
return view('system.setting.UserManager') |
||||
->with('permissions', $permissions) |
||||
->with('roles', $roles) |
||||
->with('equipments_title', $equipments_title) |
||||
->with('equipments', $equipments) |
||||
->with('allow', $allow); |
||||
} |
||||
|
||||
public function index(Request $request) |
||||
{ |
||||
#region DataTable 搜尋屬性 |
||||
$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 |
||||
#endregion |
||||
|
||||
// Role with permissions |
||||
$records = User::query(); |
||||
$records = $records->with('roles'); |
||||
$records = $records->whereNotIn('id', [1]); |
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
// $query->where('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('name', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('serialnumber', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('creator_id', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
|
||||
$data_arr = $records->get(); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
return response()->json($response); |
||||
} |
||||
|
||||
// 新增使用者 |
||||
public function store(Request $request) |
||||
{ |
||||
if(isset($request->device)){ |
||||
$device = []; |
||||
foreach ($request->device as $key => $value) { |
||||
// $device[] = explode("-", $value)[1]; |
||||
$device[] = $value; |
||||
} |
||||
$request->merge(['device' => implode(",", $device)]); |
||||
}else{ |
||||
$request->merge(['device' => ""]); |
||||
} |
||||
|
||||
DB::beginTransaction(); |
||||
|
||||
try { |
||||
$data = $request->all(); |
||||
$data['password'] = Hash::make("Aa@123456789"); |
||||
$user = User::create($data); |
||||
$user->syncRoles($request->role); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增使用者', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增使用者:$user->name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => '新增成功']); |
||||
} catch (\Exception $e) { |
||||
DB::rollback(); |
||||
Log::error("新增使用者錯誤訊息: " . $e->getMessage()); |
||||
return response()->json(['error' => '新增失敗']); |
||||
} |
||||
} |
||||
|
||||
public function show(Request $request, $id) |
||||
{ |
||||
$user = User::with('roles')->find($id); |
||||
$role = Role::where('id', '!=', 1)->get(); |
||||
return response()->json(['user' => $user, 'role' => $role]); |
||||
} |
||||
|
||||
public function update(Request $request, $id) |
||||
{ |
||||
if ($id == 1) { |
||||
return response()->json(['error' => '此使用者不可編輯']); |
||||
} |
||||
if (isset($request->password_reset)){ |
||||
$user = User::find($id); |
||||
$user->update(['password'=> Hash::make("Aa@123456789")]); |
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '使用者密碼重設', |
||||
'ip' => request()->ip(), |
||||
'remark' => "重設使用者密碼: $user->name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
return response()->json(['success' => '重設成功']); |
||||
} |
||||
if(isset($request->device)){ |
||||
$device = []; |
||||
foreach ($request->device as $key => $value) { |
||||
// $device[] = explode("-", $value)[1]; |
||||
$device[] = $value; |
||||
} |
||||
$request->merge(['device' => implode(",", $device)]); |
||||
}else{ |
||||
$request->merge(['device' => ""]); |
||||
} |
||||
|
||||
DB::beginTransaction(); |
||||
|
||||
try { |
||||
$user = User::find($id); |
||||
$user->update($request->all()); |
||||
$user->syncRoles($request->role); |
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '編輯使用者', |
||||
'ip' => request()->ip(), |
||||
'remark' => "編輯使用者:$user->name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => '編輯成功']); |
||||
} catch (\Exception $e) { |
||||
DB::rollback(); |
||||
Log::error("編輯使用者錯誤訊息: " . $e->getMessage()); |
||||
return response()->json(['error' => '編輯失敗']); |
||||
} |
||||
} |
||||
|
||||
// 刪除使用者 |
||||
public function destory(Request $request, $id) |
||||
{ |
||||
if ($id == 1) { |
||||
return response()->json(['error' => '此使用者不可刪除']); |
||||
} |
||||
|
||||
DB::beginTransaction(); |
||||
try { |
||||
$user = User::find($id); |
||||
$user->update(['deleted_at' => now()]); |
||||
$logData = [ |
||||
'action' => 'delete', |
||||
'action_detail' => '刪除使用者', |
||||
'ip' => request()->ip(), |
||||
'remark' => "刪除使用者:$user->name", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => '刪除成功']); |
||||
} catch (\Exception $e) { |
||||
DB::rollback(); |
||||
return response()->json(['error' => '刪除失敗']); |
||||
} |
||||
} |
||||
|
||||
public function exportUserData() |
||||
{ |
||||
$data_arr = User::whereNotIn('id',[1])->OrderBy('id', 'asc')->get()->toArray(); |
||||
$columns = ['id', 'station', 'unit', 'class', 'name', 'account', 'role_name', 'deleted_at']; |
||||
$columnTitle = [ |
||||
['編號', '分局', '使用單位', '職稱', '姓名', '帳號', '使用者權限', '備註'] |
||||
]; |
||||
$data = array_map(function ($row) use ($columns) { |
||||
return array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); |
||||
}, $data_arr); |
||||
// 修改data中編號id 從1開始 |
||||
foreach ($data as $key => $value) { |
||||
$data[$key]['id'] = $key + 1; |
||||
} |
||||
$fileName = 'userData-' . Str::random(10) . '.xlsx'; |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports_user', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => '使用者匯出', |
||||
'user_id' => 1, |
||||
]); |
||||
Excel::store(new ArrayExport($data, $columnTitle), 'public/exports_user/' . $fileName, 'local', \Maatwebsite\Excel\Excel::XLSX); |
||||
// 直接跳轉下載 |
||||
return response()->json(['success' => '匯出成功', 'file' => 'storage/exports_user/'.$fileName]); |
||||
} |
||||
#endregion |
||||
} |
@ -0,0 +1,811 @@
@@ -0,0 +1,811 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Exports\ArrayExport; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\OverSpeedRed; |
||||
use App\Models\OverSpeedRedEquipment; |
||||
use App\Models\ViolationLaw; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
use ZipArchive; |
||||
|
||||
class RedController extends Controller |
||||
{ |
||||
public $destPath_root; |
||||
public $clientDestPath_root; |
||||
public $unreportPath_root; |
||||
public $month; |
||||
|
||||
function __construct() |
||||
{ |
||||
$this->middleware('permission:red-review|red-reduction|red-device-setting|red-statistics|red-analysis|red-read', ['only' => ['Review']]); |
||||
$this->middleware('permission:red-review|permission:red-reduction', ['only' => ['update']]); |
||||
$this->middleware('permission:red-device-setting', ['only' => ['DeviceSetting']]); |
||||
$this->middleware('permission:red-statistics', ['only' => ['Statistics']]); |
||||
$this->middleware('permission:red-analysis', ['only' => ['Analysis']]); |
||||
// OK path |
||||
$this->destPath_root = 'D:\\OK\\Red\\'; |
||||
$this->clientDestPath_root = 'Y:\\'; |
||||
// NOK path |
||||
$this->unreportPath_root = 'C:\\xampp\\SMMS\\storage\\app\\ParsingFiles\\NOK\\Red\\'; |
||||
$this->month['start'] = Carbon::now()->subDays(8)->format('Y-m-d'); |
||||
$this->month['current'] = Carbon::now()->subDays(1)->format('Y-m-d'); |
||||
} |
||||
|
||||
public function Review() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// dd($device); |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new OverSpeedRed(); |
||||
$locationtype = $violationparking::where('processcheck', 0)->whereIn('violationtype', ['闖紅燈'])->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.red.index') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('vio_arr', $vio_arr) |
||||
->with('month', $this->month); |
||||
} |
||||
|
||||
#region 已審 View |
||||
public function Censored(Request $request) |
||||
{ |
||||
|
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new OverSpeedRed(); |
||||
$locationtype = $violationparking::where('processcheck', 1)->whereIn('violationtype', ['闖紅燈'])->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); |
||||
|
||||
// dd($data,$page_data); |
||||
return view('system.red.manage') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('month', $this->month); |
||||
} |
||||
#endregion |
||||
|
||||
#region 不舉發 View |
||||
public function Unreport(Request $request) |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
$violationparking = new OverSpeedRed(); |
||||
$locationtype = $violationparking::where('processcheck', 2)->whereIn('violationtype', ['闖紅燈'])->whereIn('serialnumber', $device)->groupBy('location')->pluck('location'); |
||||
$unreportreason = $violationparking->where('processcheck', 2)->whereIn('violationtype', ['闖紅燈'])->whereIn('serialnumber', $device)->groupBy('unreportreason')->pluck('unreportreason'); |
||||
// dd($locationtype,$unreportreason); |
||||
return view('system.red.unreport') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('locationtype', $locationtype) |
||||
->with('unreportreason', $unreportreason) |
||||
->with('month', $this->month); |
||||
} |
||||
#endregion |
||||
|
||||
public function update(Request $request, $id) |
||||
{ |
||||
$data = OverSpeedRed::find($id); |
||||
// 先確認 processcheck 狀態 0 修改 1 舉發 2 不舉發 |
||||
// 確認使用者是否可以 review |
||||
DB::beginTransaction(); |
||||
|
||||
try { |
||||
// 如果使用者具 審查權限 |
||||
if (auth('api')->user()->can('red-review')) { |
||||
// 修改 processcheck = 0 |
||||
if ($request->processcheck == 0) { |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->violationcode = $request->viocode ?? $data->violationcode; |
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '編輯案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "編輯違停案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
} |
||||
// 舉發 processcheck = 1 |
||||
elseif ($request->processcheck == 1) { |
||||
if ($request->carnumber == null) { |
||||
return response()->json(['error' => '請輸入車牌號碼']); |
||||
} |
||||
if (isset($request->viocode)) { |
||||
if ($request->viocode == null) |
||||
return response()->json(['error' => '請選擇法條代碼']); |
||||
// 如果法條代碼不再資料表中 |
||||
if (!ViolationLaw::where('violationcode', $request->viocode)->exists()) { |
||||
return response()->json(['error' => '此法條代碼不存在']); |
||||
} |
||||
} else { |
||||
return response()->json(['error' => '請選擇法條代碼']); |
||||
} |
||||
$this->updateIni($data->picture, $data->carnumber, "$request->carnumber", $data->violationtype, $request->violationtype); |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->violationcode = $request->viocode ?? $data->violationcode; |
||||
$data->processcheck = 1; |
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "舉發違停案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
$pth = explode('*', $data->picture); |
||||
$photoPath = str_replace('*', '\\', storage_path('app' . '\\' . 'ParsingFiles' . '\\' . "$data->picture")); |
||||
$pth = end($pth); |
||||
$violationtype = $data->violationtype; |
||||
$time = str_replace('-', '', explode(' ', $data->datatime)[0]); |
||||
// public_path('merge\\'.$path) |
||||
$mgpath = public_path("merge\\$violationtype\\$time\\$pth"); |
||||
if (!file_exists($mgpath)) { |
||||
if (is_dir(public_path("merge\\$violationtype\\$time")) === false) { |
||||
mkdir(public_path("merge\\$violationtype\\$time"), 0777, true); |
||||
} |
||||
copy($photoPath, $mgpath); |
||||
} |
||||
$aaData['picture'] = $data->picture; |
||||
$aaData['picture2'] = $data->picture2; |
||||
$aaData['datatime'] = $data->datatime; |
||||
$aaData['violationtype'] = $data->violationtype; |
||||
$this->saveFinishFile($aaData); |
||||
} |
||||
// 不舉發 processcheck = 2 |
||||
elseif ($request->processcheck == 2) { |
||||
$data->carnumber = $request->carnumber ?? $data->carnumber; |
||||
$data->violationtype = $request->violationtype ?? $data->violationtype; |
||||
$data->cartype = $request->cartype ?? $data->cartype; |
||||
$data->unreportreason = $request->unreportreason ?? $data->unreportreason; |
||||
$data->processcheck = 2; |
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '不舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "不舉發違停案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
} |
||||
// 還原 processcheck = 3 |
||||
elseif ($request->processcheck == 3) { |
||||
$data->violationcode = null; |
||||
$data->unreportreason = ''; |
||||
$data->processcheck = 0; |
||||
$logData = [ |
||||
'action' => 'reduction', |
||||
'action_detail' => '還原案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "還原違停案件: $data->carnumber ,案件日期: $data->datatime", |
||||
]; |
||||
} |
||||
} |
||||
|
||||
// 紀錄審查者 帳號 |
||||
$data->jsoncheck = auth('api')->user()->account; |
||||
// 資料儲存 |
||||
$data->save(); |
||||
// 紀錄 LOG |
||||
LogWriter::writeLog($logData, 'api'); |
||||
|
||||
DB::commit(); |
||||
// all good |
||||
return response()->json(['success' => $logData['remark']]); |
||||
} catch (\Exception $e) { |
||||
DB::rollback(); |
||||
return response()->json(['error' => '系統錯誤']); |
||||
// something went wrong |
||||
} |
||||
} |
||||
|
||||
#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 = OverSpeedRed::query(); |
||||
$records->whereIn('violationtype', ['闖紅燈']); |
||||
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')); |
||||
if ($request->statisticstype == 3) { |
||||
$groupbyPara1 = "CAST(DATE_FORMAT(datatime, '%H') AS INT)"; |
||||
$records->groupBy(DB::raw($groupbyPara1), 'serialnumber', 'violationtype')->select('*', DB::raw('COUNT(*) as count, CONCAT(CAST(DATE_FORMAT(datatime,"%H") as INT),"-",CAST(DATE_FORMAT(DATE_ADD(datatime,INTERVAL +1 HOUR),"%H") as INT)) AS period')); |
||||
$records->orderBy(DB::raw($groupbyPara1), 'ASC'); |
||||
} |
||||
} 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' => "輕型機車", |
||||
'8' => "微型電動二輪車" |
||||
]; |
||||
|
||||
$processCheckTitle = [ |
||||
'0' => "未審", |
||||
'1' => "已審查", |
||||
'2' => "不舉發" |
||||
]; |
||||
|
||||
if (!isset($cartype)) |
||||
$cartype = 1; |
||||
|
||||
// 如果車牌 = None 則 顯示 "" |
||||
if ($carnumber == "None") |
||||
$carnumber = ""; |
||||
|
||||
$pthar = explode('*', $record->picture); |
||||
$pth = $pthar[count($pthar) - 1]; |
||||
$time = str_replace('-', '', explode(' ', $datatime)[0]); |
||||
// public_path('merge\\'.$path) |
||||
$mgpath = public_path("merge\\$violationtype\\$time\\$pth"); |
||||
$mergepic = 0; |
||||
if (file_exists($mgpath)) { |
||||
$mergepic = "merge/$violationtype/$time/$pth"; |
||||
} |
||||
|
||||
$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', $picture), |
||||
"violationtype" => $violationtype, |
||||
"cartype" => $cartype, |
||||
"carkind" => $cartypeTitle[$cartype], |
||||
"unreportreason" => $unreportreason ?? '', |
||||
"unreportpicture" => $unreportpicture ?? $picture, |
||||
"mergepic" => $mergepic ?? '0', |
||||
"postcheck" => $postcheck, |
||||
// 清冊用 |
||||
"processcheck" => $processCheckTitle[$processcheck], |
||||
// "searchByFromdate" => $searchByFromdate, |
||||
// "searchByTodate"=> $searchByTodate, |
||||
"count" => $count, |
||||
"period" => $period |
||||
); |
||||
} |
||||
return [$draw, $totalRecords, $totalRecordswithFilter, $data_arr]; |
||||
} |
||||
#endregion |
||||
|
||||
// 清冊用 |
||||
public function Statistics() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new OverSpeedRed(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->whereIn('violationtype', ['闖紅燈'])->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.red.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) |
||||
{ |
||||
#region 設備限制 |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
#endregion |
||||
$processcheckStatus = 99; |
||||
|
||||
if ($request->statisticstype == 1) { |
||||
$remark = '違規件數清冊'; |
||||
$columns = ['datatime', 'serialnumber', 'location', 'carnumber', 'violationtype', 'processcheck']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['違規時段', '設備編號', '違規地點', '車號', '違規類型', '審查狀態'] |
||||
]; |
||||
} elseif ($request->statisticstype == 2) { |
||||
$remark = '違規件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'violationtype', 'carkind', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['設備編號', '違規地點', '違規類型', '車種', '統計'] |
||||
]; |
||||
} elseif ($request->statisticstype == 3) { |
||||
$remark = '違規時段件數統計清冊'; |
||||
$columns = ['serialnumber', 'location', 'period', 'violationtype', 'count']; |
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【違規日期區間】:", $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 = 'red-' . Str::random(10) . '.xlsx'; |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "路口多功能-$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('red-export', ['fileName' => $fileName])], 200); |
||||
} |
||||
|
||||
public function Export(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 Analysis() |
||||
{ |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
// 違規地點 group by |
||||
$equipmentData = new OverSpeedRedEquipment(); |
||||
$serialNumber = $equipmentData::whereIn('serialnumber', $device)->groupBy('serialnumber')->get(['serialnumber', 'location']); |
||||
// 違規類型 group by |
||||
$violationparking = new OverSpeedRed(); |
||||
$violationtype = $violationparking::whereIn('serialnumber', $device)->whereIn('violationtype', ['闖紅燈'])->groupBy('violationtype')->pluck('violationtype'); |
||||
|
||||
return view('system.red.analysis') |
||||
->with('serialNumber', $serialNumber) |
||||
->with('violationtype', $violationtype); |
||||
} |
||||
|
||||
public function getAnalysisData(Request $request) |
||||
{ |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
$records = OverSpeedRed::query(); |
||||
$records->whereIn('serialnumber', $device)->whereIn('violationtype', ['闖紅燈'])->whereIn('processcheck', [1, 3]); |
||||
// dd($request->all()); |
||||
if (isset($request->search_fromdate)) |
||||
$records->where('datatime', ">", $request->search_fromdate . ' 00:00:00'); |
||||
if (isset($request->search_todate)) |
||||
$records->where('datatime', "<", $request->search_todate . ' 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 = OverSpeedRed::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'); |
||||
if (isset($request->search_todate)) |
||||
$records2->where('datatime', "<", $request->search_todate . ' 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->whereIn('violationtype', ['闖紅燈'])->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); |
||||
} |
||||
} |
||||
|
||||
// dd($data); |
||||
return response()->json(['data' => $data, 'chart_type' => $request->chart_type, 'violationtype' => $violationTypes ?? ''], 200); |
||||
} |
||||
|
||||
// statistics |
||||
// public function statistics() |
||||
// { |
||||
// return view('system.red.statistics'); |
||||
// } |
||||
|
||||
public function getStatisticsTest(Request $request) |
||||
{ |
||||
$request->statisticstype; |
||||
// 讀取json file (storage/app/data/get-red-statistics-1~3.json ) |
||||
|
||||
$json = file_get_contents(storage_path('app/data/get-red-statistics-1.json')); |
||||
} |
||||
|
||||
#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; |
||||
$violationtype = $data['violationtype']; |
||||
$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']); |
||||
$photoName = end($photoName); |
||||
$photoPath = public_path("merge\\$violationtype\\$time\\$photoName"); |
||||
// $photoName2 = explode('*', $data['picture2'])[3]; |
||||
$destPath = $destPath_root . Auth::user()->account . "\\" . $time; |
||||
if (is_dir($destPath) === false) { |
||||
mkdir($destPath, 0777, true); |
||||
} |
||||
try { |
||||
copy($iniPath, $destPath . '\\' . str_replace('jpg', 'ini', $photoName)); |
||||
copy($photoPath, $destPath . '\\' . $photoName); |
||||
// copy($photoPath2, $destPath.'\\'.$photoName2); |
||||
// 存入第二路徑供客戶操作資料 |
||||
$clientDestPath = $clientDestPath_root . $time; |
||||
if (is_dir($clientDestPath) === false) { |
||||
mkdir($clientDestPath, 0777, true); |
||||
} |
||||
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 = OverSpeedRed::query(); |
||||
$records->where('location', 'not like', '%測試%'); |
||||
$records->whereIn('serialnumber', $device)->whereIn('violationtype', ['闖紅燈']); |
||||
$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'); |
||||
foreach (glob(public_path() . '\*.zip') as $file) { |
||||
unlink($file); |
||||
} |
||||
$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 = "OSR_OK_" . $fileName; |
||||
if ($processcheck == 2) |
||||
$fileName = "OSR_X_" . $fileName; |
||||
} |
||||
|
||||
if ($zip->open(public_path($fileName), ZipArchive::CREATE) === TRUE) { |
||||
foreach ($files as $file) { |
||||
$name = explode("\\", $file); |
||||
$iniPath = str_replace('.jpg', '.ini', $file); |
||||
$iniName = explode("\\", $iniPath); |
||||
if (end($name) != '') { |
||||
try { |
||||
$zip->addFile($file, end($name)); |
||||
$zip->addFile($iniPath, end($iniName)); |
||||
} catch (\Throwable $th) { |
||||
Log::error('Error: ' . $th); |
||||
} |
||||
|
||||
} |
||||
} |
||||
$zip->close(); |
||||
} |
||||
|
||||
// response()->download(public_path($fileName))->deleteFileAfterSend(true); |
||||
return "$fileName"; |
||||
} |
||||
#endregion |
||||
|
||||
} |
@ -0,0 +1,516 @@
@@ -0,0 +1,516 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\system; |
||||
|
||||
use App\Exports\ArrayExportH; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\StatisticView; |
||||
use App\Models\EquipmentView; |
||||
use App\Models\MultisysEquipment; |
||||
use App\Models\OverSpeedRedEquipment; |
||||
use App\Models\User; |
||||
use App\Models\ViolationLaw; |
||||
use App\Models\ViolationParkingEquipment; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Illuminate\Support\Str; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
|
||||
class StatisticsController extends Controller |
||||
{ |
||||
public function index(Request $request, $type) |
||||
{ |
||||
$station = []; |
||||
$precinct = []; |
||||
$location = []; |
||||
|
||||
$station = EquipmentView::select('station')->distinct()->pluck('station')->toArray(); |
||||
$precinct = EquipmentView::select('precinct')->distinct()->pluck('precinct')->toArray(); |
||||
$location = EquipmentView::select('location')->distinct()->pluck('location')->toArray(); |
||||
|
||||
|
||||
|
||||
$station = array_filter($station, function ($value) { |
||||
return $value != null; |
||||
}); |
||||
|
||||
$precinct = array_filter($precinct, function ($value) { |
||||
return $value != null; |
||||
}); |
||||
|
||||
$location = array_filter($location, function ($value) { |
||||
return $value != null; |
||||
}); |
||||
// dd($station, $precinct, $location); |
||||
if ($type == '1') { |
||||
$violationTypes = ViolationLaw::getTypeCodes(); |
||||
|
||||
return view('system.statistics_1') |
||||
->with('violationTypes', $violationTypes) |
||||
->with('station', $station) |
||||
->with('precinct', $precinct) |
||||
->with('location', $location); |
||||
} elseif ($type == '2') { |
||||
$titles = ['未驗證', '已驗證舉發', '已驗證不舉發', '未處理比例']; |
||||
return view('system.statistics_2') |
||||
->with('titles', $titles) |
||||
->with('station', $station) |
||||
->with('precinct', $precinct) |
||||
->with('location', $location); |
||||
} elseif ($type == '3') { |
||||
$titles = ['時間區間1已舉發件數', '時間區間2已舉發件數', '增減']; |
||||
return view('system.statistics_3') |
||||
->with('titles', $titles) |
||||
->with('station', $station) |
||||
->with('precinct', $precinct) |
||||
->with('location', $location); |
||||
} elseif ($type == '4') { |
||||
$titles = ['已驗證舉發', '已驗證不舉發', '總件數']; |
||||
return view('system.statistics_4') |
||||
->with('titles', $titles); |
||||
} else { |
||||
// 404 |
||||
return view('errors.404'); |
||||
} |
||||
} |
||||
|
||||
public function getStatistics(Request $request) |
||||
{ |
||||
$draw = $request->get('draw'); |
||||
|
||||
// Fetch records |
||||
// $violationTypes = ['闖紅燈', '超速', '違停']; |
||||
|
||||
if ($request->group_at == '分局') { |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, '分局'); |
||||
} else if ($request->group_at == '使用單位') { |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, '使用單位'); |
||||
} else if ($request->group_at == 'user') { |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, 'user'); |
||||
} else { |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, 'location'); |
||||
} |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords ?? 0, |
||||
"iTotalDisplayRecords" => $totalRecords ?? 0, |
||||
"aaData" => $data_arr ?? [] |
||||
); |
||||
|
||||
return $response; |
||||
} |
||||
|
||||
public static function getViolationSummary($request, $group_at) |
||||
{ |
||||
// dd($request->all()); |
||||
if (isset($request->searchByFromdate)) |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
if (isset($request->searchByTodate)) |
||||
$searchByTodate = $request->searchByTodate; |
||||
if (isset($request->searchByFromdate2)) |
||||
$searchByFromdate2 = $request->searchByFromdate2; |
||||
if (isset($request->searchByTodate2)) |
||||
$searchByTodate2 = $request->searchByTodate2; |
||||
|
||||
if (isset($request->export)) |
||||
$export = true; |
||||
else |
||||
$export = false; |
||||
|
||||
#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 |
||||
|
||||
#region Query 舉發類別分析表 |
||||
if ($request->reportType == '1') { |
||||
if ($group_at == '分局') { |
||||
$groups = EquipmentView::getTypePrecinct($request->s1 ?? []); |
||||
$groupLocationExpression = ''; |
||||
$allSerialNumbers = []; |
||||
foreach ($groups as $group => $serialnumbers) { |
||||
$allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); |
||||
$serialnumber = implode("','", $serialnumbers); |
||||
if ($group == null || $group == '') |
||||
continue; |
||||
$groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; |
||||
} |
||||
$groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; |
||||
|
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} else if ($group_at == '使用單位') { |
||||
$groups = EquipmentView::getTypeStation($request->s2 ?? []); |
||||
// dd($groups); |
||||
$groupLocationExpression = ''; |
||||
$allSerialNumbers = []; |
||||
foreach ($groups as $group => $serialnumbers) { |
||||
$allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); |
||||
$serialnumber = implode("','", $serialnumbers); |
||||
if ($group == null || $group == '') |
||||
continue; |
||||
$groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; |
||||
} |
||||
$groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; |
||||
|
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} else { |
||||
if (isset($request->s3) && $request->s3 != []) |
||||
$allSerialNumbers = EquipmentView::whereIn('location', $request->s3 ?? [])->pluck('serialnumber')->toArray(); |
||||
else |
||||
$allSerialNumbers = EquipmentView::pluck('serialnumber')->toArray(); |
||||
$groupLocationExpression = 'location AS group_location'; |
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} |
||||
|
||||
if (isset($searchByFromdate) && $searchByFromdate != '') { |
||||
$starttime = Carbon::parse($searchByFromdate)->format('Y-m-d'); |
||||
$q1 = "AND datatime >= '$starttime 00:00:00'"; |
||||
} else { |
||||
$q1 = ''; |
||||
} |
||||
if (isset($searchByTodate) && $searchByTodate != '') { |
||||
$endtime = Carbon::parse($searchByTodate)->format('Y-m-d'); |
||||
$q2 = "AND datatime <= '$endtime 23:59:59'"; |
||||
} else { |
||||
$q2 = ''; |
||||
} |
||||
|
||||
$typeCodes = ViolationLaw::getTypeCodes(); |
||||
foreach ($typeCodes as $type => $codes) { |
||||
// where in violationcode in (codes) and violationtype = type and processcheck = 1 |
||||
// 替每個code 加上引號 並用逗號隔開 包含頭尾 |
||||
$codes = implode("','", $codes); |
||||
$query->selectRaw("SUM(CASE WHEN violationcode IN ('$codes') AND processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '$type'"); |
||||
} |
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS total_cases"); |
||||
} |
||||
// 審核統計分析表 |
||||
else if ($request->reportType == '2') { |
||||
if ($group_at == '分局') { |
||||
$groups = EquipmentView::getTypePrecinct($request->s1 ?? []); |
||||
$groupLocationExpression = ''; |
||||
$allSerialNumbers = []; |
||||
foreach ($groups as $group => $serialnumbers) { |
||||
$allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); |
||||
$serialnumber = implode("','", $serialnumbers); |
||||
if ($group == null || $group == '') |
||||
continue; |
||||
$groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; |
||||
} |
||||
$groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; |
||||
|
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} else if ($group_at == '使用單位') { |
||||
$groups = EquipmentView::getTypeStation($request->s2 ?? []); |
||||
$groupLocationExpression = ''; |
||||
$allSerialNumbers = []; |
||||
foreach ($groups as $group => $serialnumbers) { |
||||
$allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); |
||||
$serialnumber = implode("','", $serialnumbers); |
||||
if ($group == null || $group == '') |
||||
continue; |
||||
$groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; |
||||
} |
||||
$groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; |
||||
|
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} else { |
||||
if (isset($request->s3) && $request->s3 != []) |
||||
$allSerialNumbers = EquipmentView::whereIn('location', $request->s3 ?? [])->pluck('serialnumber')->toArray(); |
||||
else |
||||
$allSerialNumbers = EquipmentView::pluck('serialnumber')->toArray(); |
||||
|
||||
$groupLocationExpression = 'location AS group_location'; |
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} |
||||
|
||||
if (isset($searchByFromdate) && $searchByFromdate != '') { |
||||
$starttime = Carbon::parse($searchByFromdate)->format('Y-m-d'); |
||||
$q1 = "AND datatime >= '$starttime 00:00:00'"; |
||||
} else { |
||||
$q1 = ''; |
||||
} |
||||
if (isset($searchByTodate) && $searchByTodate != '') { |
||||
$endtime = Carbon::parse($searchByTodate)->format('Y-m-d'); |
||||
$q2 = "AND datatime <= '$endtime 23:59:59'"; |
||||
} else { |
||||
$q2 = ''; |
||||
} |
||||
|
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 0 $q1 $q2 THEN 1 ELSE 0 END) AS '未驗證'"); |
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '已驗證舉發'"); |
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 2 $q1 $q2 THEN 1 ELSE 0 END) AS '已驗證不舉發'"); |
||||
// 未舉發比例 % = 未舉發 / (已舉發1 + 不舉發2 + 未舉發0) 直接顯示為 (比例數字) + %符號 保留兩位小數 |
||||
$query->selectRaw("CONCAT(ROUND(SUM(CASE WHEN processcheck = 0 $q1 $q2 THEN 1 ELSE 0 END) / (SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) + SUM(CASE WHEN processcheck = 2 $q1 $q2 THEN 1 ELSE 0 END) + SUM(CASE WHEN processcheck = 0 $q1 $q2 THEN 1 ELSE 0 END) ) * 100, 2), '%') AS '未處理比例'"); |
||||
$query->selectRaw("SUM(CASE WHEN processcheck IN ('0', '1', '2') $q1 $q2 THEN 1 ELSE 0 END) AS total_cases"); |
||||
} else if ($request->reportType == '3') { |
||||
if ($group_at == '分局') { |
||||
$groups = EquipmentView::getTypePrecinct($request->s1 ?? []); |
||||
$groupLocationExpression = ''; |
||||
$allSerialNumbers = []; |
||||
foreach ($groups as $group => $serialnumbers) { |
||||
$allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); |
||||
$serialnumber = implode("','", $serialnumbers); |
||||
if ($group == null || $group == '') |
||||
continue; |
||||
$groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; |
||||
} |
||||
$groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; |
||||
|
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} else if ($group_at == '使用單位') { |
||||
$groups = EquipmentView::getTypeStation($request->s2 ?? []); |
||||
$groupLocationExpression = ''; |
||||
$allSerialNumbers = []; |
||||
foreach ($groups as $group => $serialnumbers) { |
||||
$allSerialNumbers = array_merge($allSerialNumbers, $serialnumbers); |
||||
$serialnumber = implode("','", $serialnumbers); |
||||
if ($group == null || $group == '') |
||||
continue; |
||||
$groupLocationExpression .= " WHEN serialnumber IN ('$serialnumber') THEN '$group'"; |
||||
} |
||||
$groupLocationExpression = 'CASE' . $groupLocationExpression . ' ELSE NULL END AS group_location'; |
||||
|
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} else { |
||||
if (isset($request->s3) && $request->s3 != []) |
||||
$allSerialNumbers = EquipmentView::whereIn('location', $request->s3 ?? [])->pluck('serialnumber')->toArray(); |
||||
else |
||||
$allSerialNumbers = EquipmentView::pluck('serialnumber')->toArray(); |
||||
|
||||
$groupLocationExpression = 'location AS group_location'; |
||||
$query = StatisticView::selectRaw($groupLocationExpression); |
||||
$query->whereIn('serialnumber', $allSerialNumbers); |
||||
} |
||||
|
||||
if (isset($searchByFromdate) && $searchByFromdate != '' && isset($searchByTodate) && $searchByTodate != '') { |
||||
$starttime = Carbon::parse($searchByFromdate)->format('Y-m-d'); |
||||
$endtime = Carbon::parse($searchByTodate)->format('Y-m-d'); |
||||
$q1 = "AND datatime >= '$starttime 00:00:00'"; |
||||
$q2 = "AND datatime <= '$endtime 23:59:59'"; |
||||
} else { |
||||
$q1 = ''; |
||||
$q2 = ''; |
||||
} |
||||
if (isset($searchByFromdate2) && $searchByFromdate2 != '' && isset($searchByTodate2) && $searchByTodate2 != '') { |
||||
$starttime2 = Carbon::parse($searchByFromdate2)->format('Y-m-d'); |
||||
$endtime2 = Carbon::parse($searchByTodate2)->format('Y-m-d'); |
||||
$q3 = "AND datatime >= '$starttime2 00:00:00'"; |
||||
$q4 = "AND datatime <= '$endtime2 23:59:59'"; |
||||
} else { |
||||
$q3 = ''; |
||||
$q4 = ''; |
||||
} |
||||
|
||||
|
||||
|
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '時間區間1已舉發件數'"); |
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 1 $q3 $q4 THEN 1 ELSE 0 END) AS '時間區間2已舉發件數'"); |
||||
// 時間區間2 - 時間區間1 |
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 1 $q3 $q4 THEN 1 ELSE 0 END) - SUM(CASE WHEN processcheck = 1 $q1 $q2 THEN 1 ELSE 0 END) AS '增減'"); |
||||
} |
||||
// 審核統計分析表 |
||||
else if ($request->reportType == '4') { |
||||
// distinct user account |
||||
$users = User::select('account')->distinct()->pluck('account')->toArray(); |
||||
$users = array_filter($users, function ($value) { |
||||
return $value != null; |
||||
}); |
||||
// StatisticView 的jsoncheck是 user account 依據 user account 分組統計 processcheck = 1 的數量 跟 processcheck = 2 的數量 還有總數 |
||||
$query = StatisticView::selectRaw("jsoncheck"); |
||||
// 增加一條join 用來取得 user account 關聯的 name |
||||
$query->leftJoin('users', 'users.account', '=', 'jsoncheck'); |
||||
$query->selectRaw("users.name AS 'group_location'"); |
||||
|
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 1 THEN 1 ELSE 0 END) AS '已驗證舉發'"); |
||||
$query->selectRaw("SUM(CASE WHEN processcheck = 2 THEN 1 ELSE 0 END) AS '已驗證不舉發'"); |
||||
$query->selectRaw("SUM(CASE WHEN processcheck IN ('1', '2') THEN 1 ELSE 0 END) AS 總件數"); |
||||
// jsoncheck AS group_location is not null |
||||
$query->whereNotNull('jsoncheck'); |
||||
$query->where('jsoncheck', '!=', 'admin'); |
||||
$query->groupBy('group_location'); |
||||
} |
||||
#endregion |
||||
|
||||
// 所有 processcheck = 1 的案件 |
||||
|
||||
|
||||
$query->groupBy('group_location'); |
||||
if (isset($columnName)) |
||||
$query->orderBy($columnName, $columnSortOrder); |
||||
$data = $query->get(); |
||||
$count = count($data); |
||||
if (!$export) { |
||||
if (isset($start)) |
||||
$query->skip($start); |
||||
if (isset($rowperpage)) |
||||
$query->take($rowperpage); |
||||
} |
||||
$data = $query->get(); |
||||
// 如果data[i] 底下的 group_location 是 null 就不顯示' |
||||
$data = $data->filter(function ($value, $key) { |
||||
return $value->group_location != null; |
||||
}); |
||||
|
||||
|
||||
return [$data, $count]; |
||||
} |
||||
|
||||
public function getStatisticsExport(Request $request) |
||||
{ |
||||
#region Request 搜尋值 |
||||
if (isset($request->searchByFromdate)) |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
else |
||||
$searchByFromdate = ''; |
||||
if (isset($request->searchByTodate)) |
||||
$searchByTodate = $request->searchByTodate; |
||||
else |
||||
$searchByTodate = ''; |
||||
#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; |
||||
} |
||||
|
||||
|
||||
if ($request->group_at == '分局') { |
||||
$title = '分局'; |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, '分局'); |
||||
} else if ($request->group_at == '使用單位') { |
||||
$title = '使用單位'; |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, '使用單位'); |
||||
} else if ($request->group_at == 'user') { |
||||
$title = '員警姓名'; |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, 'user'); |
||||
} else { |
||||
$title = '路口'; |
||||
[$data_arr, $totalRecords] = self::getViolationSummary($request, 'location'); |
||||
} |
||||
if ($request->reportType == '1') { |
||||
$titlef = '舉發類別分析表'; |
||||
} else if ($request->reportType == '2') { |
||||
$titlef = '審核統計分析表'; |
||||
} else if ($request->reportType == '3') { |
||||
$titlef = '審核統計分析表'; |
||||
} else if ($request->reportType == '4') { |
||||
$titlef = '個別案件審核統計表'; |
||||
} |
||||
$remark = '報表-' . $titlef . '-' . $title; |
||||
$columns = ['group_location', 'total_cases']; |
||||
|
||||
if ($request->reportType == '1') { |
||||
$typeCodes = ViolationLaw::getTypeCodes(); |
||||
foreach ($typeCodes as $type => $codes) { |
||||
if ($type == 99 || $type == 3 || $type == 1) { |
||||
continue; |
||||
} |
||||
$columns[] = $type; |
||||
} |
||||
} else if ($request->reportType == '2') { |
||||
$columns = ['group_location', 'total_cases', '未驗證', '已驗證舉發', '已驗證不舉發', '未處理比例']; |
||||
} else if ($request->reportType == '3') { |
||||
$columns = ['group_location', '時間區間1已舉發件數', '時間區間2已舉發件數', '增減']; |
||||
} else if ($request->reportType == '4') { |
||||
$columns = ['group_location', '已驗證舉發', '已驗證不舉發', '總件數']; |
||||
} |
||||
|
||||
|
||||
if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { |
||||
$remark = $remark . ' ' . $request->searchByFromdate . ' ~ ' . $request->searchByTodate; |
||||
} |
||||
$data_arr = $data_arr->toArray(); |
||||
$data = array_map(function ($row) use ($columns) { |
||||
$data = array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); |
||||
return $data; |
||||
}, $data_arr); |
||||
if ($request->reportType == '1' || $request->reportType == '2') { |
||||
$column2 = [$title, '總案件數']; |
||||
} else { |
||||
$column2 = [$title]; |
||||
} |
||||
|
||||
foreach ($columns as $column) { |
||||
if ($column == 'group_location' || $column == 'total_cases') { |
||||
continue; |
||||
} |
||||
$column2[] = $column; |
||||
} |
||||
if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { |
||||
$timeRange = $request->searchByFromdate . ' ~ ' . $request->searchByTodate; |
||||
} else { |
||||
$timeRange = ''; |
||||
} |
||||
$columnTitle = [ |
||||
["【表單名稱】: " . $remark], |
||||
["【查詢日期區間】: " . $timeRange], |
||||
$column2 |
||||
]; |
||||
$fileName = 'statistics-' . Str::random(10) . '.xlsx'; |
||||
|
||||
try { |
||||
DB::beginTransaction(); |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "$remark", |
||||
'user_id' => auth('api')->user()->id, |
||||
]); |
||||
$option = [ |
||||
'printDef' => $request->printDef ?? 0, |
||||
'showPN' => $request->showPN ?? 0, |
||||
'showBorder' => $request->showBorder ?? 0, |
||||
]; |
||||
Excel::store(new ArrayExportH($data, $columnTitle, $option), 'public/exports/' . $fileName, 'local', \Maatwebsite\Excel\Excel::XLSX); |
||||
DB::commit(); |
||||
} catch (\Throwable $th) { |
||||
Log::error("報表匯出失敗: " . $th->getMessage()); |
||||
DB::rollBack(); |
||||
} |
||||
return response()->json(['url' => route('export', ['fileName' => $fileName])], 200); |
||||
} |
||||
} |
@ -0,0 +1,324 @@
@@ -0,0 +1,324 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ExportFiles; |
||||
use App\Models\Multisys; |
||||
use App\Models\MultisysEntry; |
||||
use App\Models\MultisysEquipment; |
||||
use App\Models\OverSpeedRed; |
||||
use App\Models\OverSpeedRedEquipment; |
||||
use App\Models\ViolationParking; |
||||
use App\Models\ViolationParkingEquipment; |
||||
use Carbon\Carbon; |
||||
use GuzzleHttp\Client; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Illuminate\Support\Facades\Storage; |
||||
use ZipArchive; |
||||
use Illuminate\Support\Str; |
||||
|
||||
class SystemController extends Controller |
||||
{ |
||||
public function __construct() |
||||
{ |
||||
} |
||||
public function getDashboardData(Request $request) |
||||
{ |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
|
||||
if ($request->has('location')) { |
||||
$location = $request->input('location'); |
||||
} |
||||
if ($request->has('year')) { |
||||
$year = $request->input('year'); |
||||
} else { |
||||
$year = Carbon::now('Asia/Taipei')->year; |
||||
} |
||||
|
||||
if ($request->has('month')) { |
||||
$month = $request->input('month'); |
||||
} else { |
||||
$month = Carbon::now('Asia/Taipei')->month; |
||||
} |
||||
#region 首頁儀錶板 - 總違規數 - 路口多功能 |
||||
$data = Multisys::query(); |
||||
$data->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$data->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$data->where('serialnumber', $location); |
||||
$data->whereIn('serialnumber', $device); |
||||
$data->groupBy('violationtype'); |
||||
$data->select('violationtype', DB::raw('COUNT(*) as count')); |
||||
$data = $data->get(); |
||||
$data = $data->toArray(); |
||||
#endregion |
||||
|
||||
#region 首頁儀錶板 - 總違規數 - 違規停車 |
||||
$data2 = ViolationParking::query(); |
||||
$data2->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$data2->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$data2->where('serialnumber', $location); |
||||
$data2->whereIn('serialnumber', $device); |
||||
$data2->groupBy('violationtype'); |
||||
$data2->select('violationtype', DB::raw('COUNT(*) as count')); |
||||
$data2 = $data2->get(); |
||||
$data2 = $data2->toArray(); |
||||
#endregion |
||||
|
||||
#region 首頁儀錶板 - 總違規數 - 路口多功能 |
||||
$data3 = OverSpeedRed::query(); |
||||
$data3->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$data3->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$data3->where('serialnumber', $location); |
||||
$data3->whereIn('serialnumber', $device); |
||||
$data3->groupBy('violationtype'); |
||||
$data3->select('violationtype', DB::raw('COUNT(*) as count')); |
||||
$data3 = $data3->get(); |
||||
$data3 = $data3->toArray(); |
||||
#endregion |
||||
|
||||
// $data = ViolationParking::groupBy('violationtype')->select('violationtype', DB::raw('COUNT(*) as count'))->get()->toArray(); |
||||
// $data2 = Multisys::groupBy('violationtype')->select('violationtype', DB::raw('COUNT(*) as count'))->get()->toArray(); |
||||
# merge array |
||||
$data = array_merge($data, $data2); |
||||
$data = array_merge($data, $data3); |
||||
$response = []; |
||||
foreach ($data as $key => $value) { |
||||
$response[] = [ |
||||
'col' => 6, |
||||
'eventType' => $value['violationtype'], |
||||
'todayCount' => $value['count'], |
||||
'lastUpdate' => Carbon::now('Asia/Taipei')->toDateString(), |
||||
]; |
||||
} |
||||
return response()->json(['data' => $response], 200); |
||||
} |
||||
|
||||
public function getDashboardPie(Request $request) |
||||
{ |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
if ($request->has('location')) { |
||||
$location = $request->input('location'); |
||||
} |
||||
if ($request->has('year')) { |
||||
$year = $request->input('year'); |
||||
} else { |
||||
$year = Carbon::now('Asia/Taipei')->year; |
||||
} |
||||
|
||||
if ($request->has('month')) { |
||||
$month = $request->input('month'); |
||||
} else { |
||||
$month = Carbon::now('Asia/Taipei')->month; |
||||
} |
||||
|
||||
#region 首頁儀錶板 - 違規類型統計 |
||||
$multisysQuery = Multisys::query(); |
||||
$multisysQuery->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$multisysQuery->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$multisysQuery->where('serialnumber', $location); |
||||
$multisysQuery->whereIn('serialnumber', $device); |
||||
$multisysQuery->groupBy('violationtype'); |
||||
$multisysQuery->select('violationtype', DB::raw('COUNT(*) as count')); |
||||
$data = $multisysQuery->get(); |
||||
$data = $data->toArray(); |
||||
|
||||
$violationparkingQuery = ViolationParking::query(); |
||||
$violationparkingQuery->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$violationparkingQuery->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$violationparkingQuery->where('serialnumber', $location); |
||||
$violationparkingQuery->whereIn('serialnumber', $device); |
||||
$violationparkingQuery->groupBy('violationtype'); |
||||
$violationparkingQuery->select('violationtype', DB::raw('COUNT(*) as count')); |
||||
$data2 = $violationparkingQuery->get(); |
||||
$data2 = $data2->toArray(); |
||||
|
||||
$overspeedredQuery = OverSpeedRed::query(); |
||||
$overspeedredQuery->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$overspeedredQuery->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$overspeedredQuery->where('serialnumber', $location); |
||||
$overspeedredQuery->whereIn('serialnumber', $device); |
||||
$overspeedredQuery->groupBy('violationtype'); |
||||
$overspeedredQuery->select('violationtype', DB::raw('COUNT(*) as count')); |
||||
$data3 = $overspeedredQuery->get(); |
||||
$data3 = $data3->toArray(); |
||||
|
||||
# merge array |
||||
$data = array_merge($data, $data2); |
||||
$data = array_merge($data, $data3); |
||||
$response = []; |
||||
foreach ($data as $key => $value) { |
||||
$response[] = [ |
||||
'violationtype' => $value['violationtype'], |
||||
'count' => $value['count'], |
||||
]; |
||||
} |
||||
#endregion |
||||
return response()->json(['data' => $response], 200); |
||||
} |
||||
|
||||
public function getDashboardBar(Request $request) |
||||
{ |
||||
$device = explode(',', auth("api")->user()->device) ?? [1]; |
||||
if ($request->has('location')) { |
||||
$location = $request->input('location'); |
||||
} |
||||
if ($request->has('year')) { |
||||
$year = $request->input('year'); |
||||
} else { |
||||
$year = Carbon::now('Asia/Taipei')->year; |
||||
} |
||||
|
||||
if ($request->has('month')) { |
||||
$month = $request->input('month'); |
||||
} else { |
||||
$month = Carbon::now('Asia/Taipei')->month; |
||||
} |
||||
|
||||
#region 首頁儀錶板 - 違規類型統計 |
||||
// 取得所有違規類型 存陣列 |
||||
$violationTypes = Multisys::whereIn('serialnumber', $device)->groupBy('violationtype')->select('violationtype')->get()->toArray(); |
||||
$violationTypes2 = ViolationParking::whereIn('serialnumber', $device)->groupBy('violationtype')->select('violationtype')->get()->toArray(); |
||||
$violationTypes3 = OverSpeedRed::whereIn('serialnumber', $device)->groupBy('violationtype')->select('violationtype')->get()->toArray(); |
||||
$violationTypes = array_merge($violationTypes, $violationTypes2); |
||||
$violationTypes = array_merge($violationTypes, $violationTypes3); |
||||
$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; |
||||
} |
||||
} |
||||
$records = Multisys::query(); |
||||
if ($year != 0) |
||||
$records->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$records->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$records->where('serialnumber', $location); |
||||
$records->whereIn('serialnumber', $device); |
||||
$data = $records->get(); |
||||
$data = $data->groupBy(function ($item, $key) { |
||||
return 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[intval($key)][$violationTypesKey[$viotype]] = $item->count(); |
||||
}); |
||||
}); |
||||
|
||||
$records = ViolationParking::query(); |
||||
if ($year != 0) |
||||
$records->whereYear('datatime', $year); |
||||
if ($month != 0) |
||||
$records->whereMonth('datatime', $month); |
||||
if (isset($location)) |
||||
$records->where('serialnumber', $location); |
||||
$records->whereIn('serialnumber', $device); |
||||
$data = $records->get(); |
||||
$data = $data->groupBy(function ($item, $key) { |
||||
return 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[intval($key)][$violationTypesKey[$viotype]] = $item->count(); |
||||
}); |
||||
}); |
||||
|
||||
|
||||
#endregion |
||||
return response()->json(['data' => $response, 'violationtype' => $violationTypes], 200); |
||||
} |
||||
public function index() |
||||
{ |
||||
// 取得所有的機號 地點 從設備表 |
||||
$device = explode(',', auth()->user()->device) ?? [1]; |
||||
$devices = []; |
||||
// array merge MultisysEquipment::select('serialnumber', 'location')->get(); |
||||
// violationparking |
||||
$devices = array_merge($devices, MultisysEquipment::select('serialnumber', 'location')->whereIn('serialnumber', $device)->get()->toArray()); |
||||
$devices = array_merge($devices, OverSpeedRedEquipment::select('serialnumber', 'location')->whereIn('serialnumber', $device)->get()->toArray()); |
||||
$devices = array_merge($devices, ViolationParkingEquipment::select('serialnumber', 'location')->whereIn('serialnumber', $device)->get()->toArray()); |
||||
|
||||
return view('system.dashboard', compact('devices')); |
||||
} |
||||
|
||||
public function getViolationImage($path) |
||||
{ |
||||
$filePath = str_replace('*', '/', $path); |
||||
|
||||
// dd($filePath); |
||||
|
||||
if (Storage::disk('local')->exists($filePath)) { |
||||
$content = Storage::get($filePath); |
||||
return response($content)->header("Content-Type", "image"); |
||||
} else { |
||||
return abort(404); |
||||
} |
||||
} |
||||
|
||||
function getViolationVideo($path) |
||||
{ |
||||
ini_set('memory_limit', '512M'); // 擴充記憶體,否則 Load 影片會爆掉 |
||||
$filePath = str_replace('*', '/', $path); |
||||
// return view('video_faster')->with('path',$filePath); |
||||
//return response()->view('video_test')->with('path',$filePath); |
||||
|
||||
if (Storage::disk('local')->exists($filePath)) { |
||||
$content = Storage::get($filePath); |
||||
return response($content)->header("Content-Type", "video/mp4"); //video/mp4 |
||||
} else { |
||||
return abort(404); |
||||
} |
||||
} |
||||
|
||||
public function Setting() |
||||
{ |
||||
return view('system.setting.setting'); |
||||
} |
||||
|
||||
public function Export(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' => '檔案不存在']); |
||||
} |
||||
} |
||||
|
||||
public function downloadZip(){ |
||||
$zip = new ZipArchive; |
||||
$rand = Str::random(5); |
||||
$fileName = "_$rand.zip"; |
||||
if ($zip->open(public_path($fileName), ZipArchive::CREATE) === TRUE) { |
||||
$zip->addFile(public_path().'/favicon.ico', "favicon.ico"); |
||||
$zip->close(); |
||||
} |
||||
return response()->download(public_path($fileName)); |
||||
} |
||||
} |
@ -0,0 +1,300 @@
@@ -0,0 +1,300 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Exports\ArrayExport; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\Clientlog; |
||||
use App\Models\Clientlogsecond; |
||||
use App\Models\Serverlog; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use App\Models\ExportFiles; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Storage; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
|
||||
class TimeLogController extends Controller |
||||
{ |
||||
#region view |
||||
public function Timelog() |
||||
{ |
||||
$equipment = Clientlog::cachedDistinctName(); |
||||
return view('system.interval.timelog', compact('equipment')); |
||||
} |
||||
|
||||
public function TimelogSecond() |
||||
{ |
||||
$equipment = Clientlogsecond::cachedDistinctName(); |
||||
return view('system.interval.timelogsecond', compact('equipment')); |
||||
} |
||||
#endregion |
||||
|
||||
#region api |
||||
|
||||
// 強制校時 |
||||
#region forceTime |
||||
public function ForceTime(Request $request) |
||||
{ |
||||
DB::beginTransaction(); |
||||
try { |
||||
$client = Clientlog::cachedDistinctThisIP(); |
||||
|
||||
$txtstring = ""; |
||||
for ($i = 0; $i < count($client); $i++) { |
||||
$txtstring .= $client[$i]->this_ip . "\n"; |
||||
} |
||||
Storage::put( |
||||
"\\Timelog\\Flag\\" . "check.txt", |
||||
$txtstring |
||||
); |
||||
$logData = [ |
||||
'action' => 'forceTime', |
||||
'action_detail' => '強制校時', |
||||
'ip' => request()->ip(), |
||||
'remark' => "強制校時", |
||||
]; |
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
} catch (\Exception $e) { |
||||
DB::rollBack(); |
||||
return response()->json(['message' => 'error'], 500); |
||||
} |
||||
|
||||
return response()->json(['message' => 'success'], 200); |
||||
} |
||||
#endregion |
||||
|
||||
// 取得最新的時間紀錄 |
||||
#region getLatestTimeLog |
||||
public function getLatestTimeLog(Request $request) |
||||
{ |
||||
$data = []; |
||||
#region DataTable 搜尋屬性 |
||||
if (!isset($request->export)) { |
||||
$draw = $request->get('draw'); |
||||
} else { |
||||
$draw = 0; |
||||
} |
||||
#endregion |
||||
if ($request->type == 'client') { |
||||
// 取得 serverLog 的最新時間紀錄 |
||||
$server_log = Serverlog::orderBy('this_time', 'desc')->first(); |
||||
if ($server_log) { |
||||
$data[] = $server_log->toArray(); |
||||
} |
||||
// 取得 clientLog 的最新時間紀錄 |
||||
|
||||
$distinct_name = Clientlog::cachedDistinctName(); |
||||
// dd($distinct_name); |
||||
foreach ($distinct_name as $name) { |
||||
$client_log = Clientlog::where('name', $name->name)->orderBy('this_time', 'desc')->first(); |
||||
if ($client_log) { |
||||
$data[] = $client_log->toArray(); |
||||
} |
||||
} |
||||
} |
||||
if ($request->type == 'clientsecond') { |
||||
// 取得 serverLog 的最新時間紀錄 |
||||
$server_log = Serverlog::orderBy('this_time', 'desc')->first(); |
||||
if ($server_log) { |
||||
$data[] = $server_log->toArray(); |
||||
} |
||||
// 取得 clientLog 的最新時間紀錄 |
||||
|
||||
$distinct_name = Clientlogsecond::cachedDistinctName(); |
||||
foreach ($distinct_name as $name) { |
||||
$client_log = Clientlogsecond::where('name', $name->name)->orderBy('this_time', 'desc')->first(); |
||||
if ($client_log) { |
||||
$data[] = $client_log->toArray(); |
||||
} |
||||
} |
||||
} |
||||
$totalRecords = count($data); |
||||
$totalRecordswithFilter = count($data); |
||||
|
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data |
||||
); |
||||
echo json_encode($response); |
||||
exit; |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
// 取得歷史時間紀錄 |
||||
#region getServerLog |
||||
public function getLogHistory(Request $request) |
||||
{ |
||||
// ini set memory limit |
||||
ini_set('memory_limit', '1024M'); |
||||
// ini set time limit |
||||
set_time_limit(0); |
||||
|
||||
#region Request 搜尋值 |
||||
if (isset($request->searchByFromdate)) |
||||
$searchByFromdate = $request->searchByFromdate; |
||||
if (isset($request->searchByTodate)) |
||||
$searchByTodate = $request->searchByTodate; |
||||
#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 |
||||
if ($request->type == 'client') { |
||||
$records = Clientlog::query(); |
||||
} |
||||
if ($request->type == 'clientsecond') { |
||||
$records = Clientlogsecond::query(); |
||||
} |
||||
if ($request->type == 'server') { |
||||
$records = Serverlog::query(); |
||||
} |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
$query->where('name', 'like', '%' . $searchValue . '%') |
||||
->orwhere('to_ip', 'like', '%' . $searchValue . '%') |
||||
->orwhere('this_ip', 'like', '%' . $searchValue . '%') |
||||
->orwhere('this_time', 'like', '%' . $searchValue . '%') |
||||
->orwhere('diffsecond', 'like', '%' . $searchValue . '%') |
||||
->orwhere('to_time', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
if (isset($request->name)){ |
||||
$records->where('name', $request->name); |
||||
} |
||||
|
||||
//時間限制 |
||||
if (isset($searchByFromdate)) |
||||
$records->where('this_time', ">", $searchByFromdate . ' 00:00:00'); |
||||
if (isset($searchByTodate)) |
||||
$records->where('this_time', "<", $searchByTodate . ' 23:59:59'); |
||||
|
||||
|
||||
$totalRecords = $records->count(); |
||||
$totalRecordswithFilter = $records->count(); |
||||
|
||||
#region DataTable 分頁(報表不分頁) |
||||
if (!isset($request->export)) { |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
} |
||||
#endregion |
||||
|
||||
$records = $records->get(); |
||||
|
||||
#region 資料處理 |
||||
$data_arr = array(); |
||||
$sno = 1 + ($request->get('start') ?? 0); |
||||
foreach ($records as $record) { |
||||
//還原用id |
||||
|
||||
//報表用的欄位,避免前端錯誤,給預設值 |
||||
$count = $record->count ?? 0; |
||||
$period = $record->period ?? ""; |
||||
|
||||
$data_arr[] = array( |
||||
// 校時對象時間 校時對象IP before_time本機校時前(本機校時後 - 時間誤差 毫秒三位數) 本機校時後 時間誤差(ms) 本機IP 本機名稱 |
||||
// "sno" => $sno++, |
||||
"to_time" => $record->to_time, |
||||
"to_ip" => $record->to_ip, |
||||
"before_time" => $record->before_time, |
||||
"diffsecond" => $record->diffsecond, |
||||
"this_time" => $record->this_time, |
||||
"this_ip" => $record->this_ip, |
||||
"name" => $record->name, |
||||
"pushed" => $record->pushed ?? "", |
||||
"force_time" => $record->force_time ?? "0", |
||||
|
||||
); |
||||
} |
||||
if (isset($request->export)) { |
||||
if ($request->type == 'client') |
||||
$remark = '設備端校時資料'; |
||||
if ($request->type == 'clientsecond') |
||||
$remark = '設備端計時資料'; |
||||
if ($request->type == 'server') |
||||
$remark = '伺服器端校時資料'; |
||||
// if ($request->type != 'server') |
||||
// $columns = ['to_time', 'to_ip', 'before_time', 'this_time', 'diffsecond', 'this_ip', 'name', 'pushed']; |
||||
// else |
||||
$columns = ['to_time', 'to_ip', 'before_time', 'this_time', 'diffsecond', 'this_ip', 'name']; |
||||
|
||||
$columnTitle = [ |
||||
["【表單名稱】:", $remark], |
||||
["【查詢日期區間】:", $request->searchByFromdate, " ~ ", $request->searchByTodate], |
||||
['校時對象時間', '校時對象IP', '本機校時前', '本機校時後', '時間誤差(ms)', '本機IP', '本機名稱'] |
||||
]; |
||||
|
||||
|
||||
if (isset($request->searchByFromdate) && isset($request->searchByTodate)) { |
||||
$remark = $remark . ' ' . $request->searchByFromdate . ' ~ ' . $request->searchByTodate; |
||||
} |
||||
|
||||
|
||||
$data = array_map(function ($row) use ($columns) { |
||||
// 如果欄位diffsecond為0 顯示0 |
||||
$data = array_merge(array_flip($columns), array_intersect_key($row, array_flip($columns))); |
||||
$data['diffsecond'] = $data['diffsecond'] == 0 ? "0" : $data['diffsecond']; |
||||
return $data; |
||||
}, $data_arr); |
||||
|
||||
$fileName = $request->type . 'log-' . Str::random(10) . '.xlsx'; |
||||
ExportFiles::create([ |
||||
'name' => $fileName, |
||||
'path' => 'public/exports', |
||||
'type' => 'xlsx', |
||||
'status' => '1', |
||||
'remark' => "$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('system.filedownload', ['path' => $fileName])], 200); |
||||
} |
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
echo json_encode($response); |
||||
exit; |
||||
} |
||||
|
||||
#endregion |
||||
|
||||
|
||||
#endregion |
||||
} |
@ -0,0 +1,702 @@
@@ -0,0 +1,702 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\ViolationLaw; |
||||
use App\Models\ViolationParking; |
||||
use App\Models\ViolationParkingEquipment; |
||||
use Carbon\Carbon; |
||||
use Illuminate\Http\Request; |
||||
use Illuminate\Support\Facades\DB; |
||||
use App\Exports\ArrayExport; |
||||
use App\Models\ExportFiles; |
||||
use App\Services\ViolationParkingService; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Maatwebsite\Excel\Facades\Excel; |
||||
use Illuminate\Support\Str; |
||||
use ZipArchive; |
||||
|
||||
class ViolationParkingController extends Controller |
||||
{ |
||||
public $destPath_root; |
||||
public $clientDestPath_root; |
||||
public $unreportPath_root; |
||||
public $month; |
||||
|
||||
function __construct() |
||||
{ |
||||
$this->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 |
||||
|
||||
} |
@ -0,0 +1,258 @@
@@ -0,0 +1,258 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers\System; |
||||
|
||||
use App\Class\LogWriter; |
||||
use App\Models\ViolationParkingEquipment; |
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\AssetOwnership; |
||||
use App\Models\CustodyUnit; |
||||
use Illuminate\Support\Facades\DB; |
||||
use Illuminate\Support\Facades\Log; |
||||
|
||||
class ViolationParkingEquipmentController extends Controller |
||||
{ |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->middleware('permission:vpk-device-setting'); |
||||
} |
||||
|
||||
public function page() |
||||
{ |
||||
// ['custodyunit' => $custodyunit, 'assetownership' => $assetownership] |
||||
|
||||
$custodyunit = CustodyUnit::all(); |
||||
$assetownership = AssetOwnership::all(); |
||||
return view('system.violationparking.equipment') |
||||
->with('custodyunit', $custodyunit) |
||||
->with('assetownership', $assetownership); |
||||
} |
||||
|
||||
/** |
||||
* Display a listing of the resource. |
||||
*/ |
||||
public function index(Request $request) |
||||
{ |
||||
#region DataTable 搜尋屬性 |
||||
$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 |
||||
#endregion |
||||
|
||||
// Role with permissions |
||||
$records = ViolationParkingEquipment::query(); |
||||
$totalRecords = $records->count(); |
||||
|
||||
if (isset($columnName)) |
||||
$records->orderBy($columnName, $columnSortOrder); |
||||
if (isset($searchValue)) { |
||||
$records->where(function ($query) use ($searchValue) { |
||||
// $query->where('outlet_id', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('name', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('serialnumber', 'like', '%' . $searchValue . '%') |
||||
// ->orwhere('creator_id', 'like', '%' . $searchValue . '%'); |
||||
}); |
||||
} |
||||
|
||||
$totalRecordswithFilter = $records->count(); |
||||
if (isset($start)) |
||||
$records->skip($start); |
||||
if (isset($rowperpage)) |
||||
$records->take($rowperpage); |
||||
|
||||
$data_arr = $records->get(); |
||||
|
||||
$response = array( |
||||
"draw" => intval($draw), |
||||
"iTotalRecords" => $totalRecords, |
||||
"iTotalDisplayRecords" => $totalRecordswithFilter, |
||||
"aaData" => $data_arr |
||||
); |
||||
return response()->json($response); |
||||
} |
||||
|
||||
/** |
||||
* Store a newly created resource in storage. |
||||
*/ |
||||
public function store(Request $request) |
||||
{ |
||||
$device = new ViolationParkingEquipment(); |
||||
DB::beginTransaction(); |
||||
try { |
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id; |
||||
$device->assetownership_id = $request->assetownership_id; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
|
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
|
||||
return response()->json(['success' => true, 'message' => '新增成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Display the specified resource. |
||||
*/ |
||||
public function show(string $id) |
||||
{ |
||||
$device = ViolationParkingEquipment::find($id); |
||||
return response()->json(['success' => true, 'data' => $device]); |
||||
} |
||||
|
||||
/** |
||||
* Update the specified resource in storage. |
||||
*/ |
||||
public function update(Request $request, string $id) |
||||
{ |
||||
$device = ViolationParkingEquipment::find($id); |
||||
|
||||
DB::beginTransaction(); |
||||
try { |
||||
$device->serialnumber = $request->serialnumber; |
||||
$device->brand = $request->brand; |
||||
$device->model = $request->model; |
||||
$device->custodyunit_id = $request->custodyunit_id ?? null; |
||||
$device->assetownership_id = $request->assetownership_id ?? null; |
||||
$device->buydate = $request->buydate; |
||||
$device->activatedate = $request->activatedate; |
||||
$device->locationid = $request->locationid; |
||||
$device->location = $request->location; |
||||
$device->comment = $request->comment; |
||||
$device->precinct = $request->precinct; |
||||
$device->station = $request->station; |
||||
$device->save(); |
||||
|
||||
$logData = [ |
||||
'action' => 'update', |
||||
'action_detail' => '更新設備', |
||||
'ip' => request()->ip(), |
||||
'remark' => "更新設備:{$device->serialnumber}", |
||||
]; |
||||
logWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '更新成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
return response()->json(['success' => false, 'message' => '更新失敗']); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Remove the specified resource from storage. |
||||
*/ |
||||
public function destroy(string $id) |
||||
{ |
||||
$device = ViolationParkingEquipment::find($id); |
||||
try { |
||||
$device->delete(); |
||||
return response()->json(['success' => true, 'message' => '刪除成功']); |
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
return response()->json(['success' => false, 'message' => '刪除失敗']); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 取得保管單位資料 |
||||
*/ |
||||
public function indexUnit(Request $request) |
||||
{ |
||||
|
||||
if($request->type == "custodyunit"){ |
||||
$unit = CustodyUnit::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
}else if ($request->type == "assetownership"){ |
||||
$unit = AssetOwnership::all(); |
||||
return response()->json(['success' => true, 'data' => $unit]); |
||||
} |
||||
|
||||
return response()->json(['success' => false, 'message' => '取得失敗']); |
||||
} |
||||
|
||||
/** |
||||
* 新增單位資料 |
||||
*/ |
||||
public function storeUnit(Request $request) |
||||
{ |
||||
// custodyunit_id |
||||
//assetownership_id) |
||||
DB::beginTransaction(); |
||||
try { |
||||
if($request->type == "custodyunit"){ |
||||
$unit = new CustodyUnit(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增保管單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增保管單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '保管單位-新增成功']); |
||||
}else if ($request->type == "assetownership"){ |
||||
$unit = new AssetOwnership(); |
||||
$unit->name = $request->name; |
||||
$unit->save(); |
||||
$logData = [ |
||||
'action' => 'create', |
||||
'action_detail' => '新增財產所屬單位', |
||||
'ip' => request()->ip(), |
||||
'remark' => "新增財產所屬單位:{$request->name}", |
||||
]; |
||||
|
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
return response()->json(['success' => true, 'message' => '財產所屬單位-新增成功']); |
||||
} |
||||
|
||||
} catch (\Throwable $th) { |
||||
//throw $th; |
||||
Log::error($th); |
||||
DB::rollBack(); |
||||
} |
||||
|
||||
|
||||
return response()->json(['success' => false, 'message' => '新增失敗']); |
||||
} |
||||
} |
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Controllers; |
||||
|
||||
use Illuminate\Http\Request; |
||||
use App\Http\Controllers\Controller; |
||||
use App\Models\User; |
||||
use Spatie\Permission\Models\Role; |
||||
use DB; |
||||
use Hash; |
||||
use Illuminate\Support\Arr; |
||||
use Illuminate\View\View; |
||||
use Illuminate\Http\RedirectResponse; |
||||
|
||||
class UserController extends Controller |
||||
{ |
||||
/** |
||||
* Display a listing of the resource. |
||||
* |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function index(Request $request): View |
||||
{ |
||||
$data = User::latest()->paginate(5); |
||||
|
||||
return view('users.index', compact('data')) |
||||
|
||||
->with('i', ($request->input('page', 1) - 1) * 5); |
||||
} |
||||
|
||||
/** |
||||
* Show the form for creating a new resource. |
||||
* |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function create(): View |
||||
{ |
||||
$roles = Role::pluck('name', 'name')->all(); |
||||
return view('users.create', compact('roles')); |
||||
} |
||||
|
||||
/** |
||||
* Store a newly created resource in storage. |
||||
* |
||||
* @param \Illuminate\Http\Request $request |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function store(Request $request): RedirectResponse |
||||
{ |
||||
$this->validate($request, [ |
||||
'name' => 'required', |
||||
'email' => 'required|email|unique:users,email', |
||||
'password' => 'required|same:confirm-password', |
||||
'roles' => 'required' |
||||
]); |
||||
|
||||
$input = $request->all(); |
||||
$input['password'] = Hash::make($input['password']); |
||||
|
||||
$user = User::create($input); |
||||
$user->assignRole($request->input('roles')); |
||||
|
||||
return redirect()->route('users.index') |
||||
->with('success', 'User created successfully'); |
||||
} |
||||
|
||||
/** |
||||
* Display the specified resource. |
||||
* |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function show($id): View |
||||
{ |
||||
$user = User::find($id); |
||||
return view('users.show', compact('user')); |
||||
} |
||||
/** |
||||
* Show the form for editing the specified resource. |
||||
* |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function edit($id): View |
||||
{ |
||||
$user = User::find($id); |
||||
$roles = Role::pluck('name', 'name')->all(); |
||||
$userRole = $user->roles->pluck('name', 'name')->all(); |
||||
return view('users.edit', compact('user', 'roles', 'userRole')); |
||||
} |
||||
/** |
||||
* Update the specified resource in storage. |
||||
* |
||||
* @param \Illuminate\Http\Request $request |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function update(Request $request, $id): RedirectResponse |
||||
{ |
||||
$this->validate($request, [ |
||||
'name' => 'required', |
||||
'email' => 'required|email|unique:users,email,' . $id, |
||||
'password' => 'same:confirm-password', |
||||
'roles' => 'required' |
||||
]); |
||||
$input = $request->all(); |
||||
if (!empty($input['password'])) { |
||||
$input['password'] = Hash::make($input['password']); |
||||
} else { |
||||
$input = Arr::except($input, array('password')); |
||||
} |
||||
$user = User::find($id); |
||||
$user->update($input); |
||||
DB::table('model_has_roles')->where('model_id', $id)->delete(); |
||||
$user->assignRole($request->input('roles')); |
||||
return redirect()->route('users.index') |
||||
->with('success', 'User updated successfully'); |
||||
} |
||||
/** |
||||
* Remove the specified resource from storage. |
||||
* |
||||
* @param int $id |
||||
* @return \Illuminate\Http\Response |
||||
*/ |
||||
public function destroy($id): RedirectResponse |
||||
{ |
||||
User::find($id)->delete(); |
||||
return redirect()->route('users.index') |
||||
->with('success', 'User deleted successfully'); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -0,0 +1,30 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Middleware; |
||||
|
||||
use App\Models\User; |
||||
use Closure; |
||||
use Illuminate\Http\Request; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
|
||||
class CheckUserAPiStatus |
||||
{ |
||||
/** |
||||
* Handle an incoming request. |
||||
* |
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next |
||||
*/ |
||||
public function handle(Request $request, Closure $next): Response |
||||
{ |
||||
if (auth('api')->check()) { |
||||
$user_id = auth('api')->user()->id; |
||||
$user = User::find($user_id); |
||||
if ($user->status == 1) { |
||||
// 403 page |
||||
return response()->json(['error' => '此帳號已被停用']); |
||||
|
||||
} |
||||
} |
||||
return $next($request); |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Middleware; |
||||
|
||||
use App\Models\User; |
||||
use Closure; |
||||
use Illuminate\Http\Request; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
|
||||
class CheckUserStatus |
||||
{ |
||||
/** |
||||
* Handle an incoming request. |
||||
* |
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next |
||||
*/ |
||||
public function handle(Request $request, Closure $next): Response |
||||
{ |
||||
if (auth()->check()) { |
||||
$user_id = auth()->user()->id; |
||||
$user = User::find($user_id); |
||||
if ($user->status == 1) { |
||||
// 403 page |
||||
return abort(403, '此帳號已被停用'); |
||||
} |
||||
} |
||||
return $next($request); |
||||
} |
||||
} |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
<?php |
||||
|
||||
namespace App\Http\Middleware; |
||||
|
||||
use Closure; |
||||
use Illuminate\Http\Request; |
||||
use Spatie\Permission\Exceptions\UnauthorizedException; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
|
||||
class PermissionMiddleware |
||||
{ |
||||
/** |
||||
* Handle an incoming request. |
||||
* |
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next |
||||
*/ |
||||
public function handle($request, Closure $next, $permission, $guard = null) |
||||
{ |
||||
// dd(auth('api')->user()->can("user-list"), auth('api')->user()); |
||||
$authGuard = app('auth')->guard($guard); |
||||
if (auth()->guest()) { |
||||
// return to login page with unauthorized message session |
||||
// return response()->json(['message' => 'Unauthenticated.'], 401); |
||||
return redirect()->route('login')->with('error', '請先登入'); |
||||
// throw UnauthorizedException::notLoggedIn(); |
||||
} |
||||
|
||||
$permissions = is_array($permission) |
||||
? $permission |
||||
: explode('|', $permission); |
||||
|
||||
foreach ($permissions as $permission) { |
||||
// dd($authGuard->user(), $permission, $authGuard->user()->can($permission)); |
||||
if ($authGuard->user()->can($permission)) { |
||||
return $next($request); |
||||
} |
||||
} |
||||
return redirect()->route('system.dashboard')->with('error', '您無權限訪問此頁面'); |
||||
// throw UnauthorizedException::forPermissions($permissions); |
||||
} |
||||
} |
@ -0,0 +1,46 @@
@@ -0,0 +1,46 @@
|
||||
<?php |
||||
|
||||
namespace App\Listeners; |
||||
|
||||
use Illuminate\Contracts\Queue\ShouldQueue; |
||||
use Illuminate\Queue\InteractsWithQueue; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Illuminate\Support\Facades\Log; |
||||
use Illuminate\Support\Str; |
||||
|
||||
class SuccessfulLogin |
||||
{ |
||||
/** |
||||
* Create the event listener. |
||||
*/ |
||||
public function __construct() |
||||
{ |
||||
// |
||||
} |
||||
|
||||
/** |
||||
* Handle the event. |
||||
*/ |
||||
public function handle(object $event): void |
||||
{ |
||||
$user = Auth::user(); |
||||
$user->api_token = Str::random(80); |
||||
$user->save(); |
||||
try { |
||||
//code... |
||||
$user->userLog()->create([ |
||||
'user_id' => $user->id, |
||||
'user_name' => $user->name, |
||||
'action' => 'login', |
||||
'action_detail' => '登入', |
||||
'ip' => request()->ip(), |
||||
// 'mac' => request()->mac(), |
||||
'remark' => '登入成功', |
||||
]); |
||||
} catch (\Throwable $th) { |
||||
Log::error($th); |
||||
//throw $th; |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class AssetOwnership extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'asset_ownership'; |
||||
|
||||
protected $fillable = [ |
||||
'name', |
||||
]; |
||||
|
||||
public $timestamps = false; |
||||
|
||||
// 有關聯到違規停車設備 |
||||
public function violationparkingequipment() |
||||
{ |
||||
return $this->hasMany(ViolationParkingEquipment::class, 'assetownership_id', 'id'); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Carbon\Carbon; |
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use Illuminate\Support\Facades\Cache; |
||||
|
||||
class Clientlog extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'clientlog'; |
||||
protected $fillable = [ |
||||
'to_ip', |
||||
'to_time', |
||||
'this_ip', |
||||
'this_time', |
||||
'diffsecond', |
||||
'name', |
||||
'pushed', |
||||
]; |
||||
// append before_time |
||||
protected $appends = ['before_time','force_time', 'timeout']; |
||||
|
||||
public function getBeforeTimeAttribute() |
||||
{ |
||||
return substr(Carbon::parse($this->this_time)->subMilliseconds($this->diffsecond)->format('Y-m-d H:i:s.u'), 0, -3); |
||||
} |
||||
|
||||
public function getForceTimeAttribute() |
||||
{ |
||||
$forceTime = UserLog::where('action', 'forceTime')->pluck('created_at')->toArray(); |
||||
// 將資料轉換為 Y-m-d H:i 格式 |
||||
$forceTime = array_map(function ($item) { |
||||
return Carbon::parse($item)->format('Y-m-d H:i'); |
||||
}, $forceTime); |
||||
// 將this_time 轉換為 Y-m-d H:i 格式 並比對是否存在於 forceTime 陣列中 |
||||
$thisTime = Carbon::parse($this->this_time)->format('Y-m-d H:i'); |
||||
// 如果存在於陣列中 則回傳 1 代表強制校時 不存在則回傳 0 |
||||
return in_array($thisTime, $forceTime) ? 1 : 0; |
||||
} |
||||
|
||||
public function getTimeoutAttribute() |
||||
{ |
||||
// this_time 與 serverlog 最新一筆,差超過150秒則回傳1 代表超時 |
||||
|
||||
$serverLog = Serverlog::orderBy('this_time', 'desc')->first(); |
||||
if (!$serverLog) { |
||||
return 1; |
||||
} |
||||
return Carbon::parse($this->this_time)->diffInSeconds($serverLog->this_time) > 150 ? 1 : 0; |
||||
|
||||
// return Carbon::parse($this->this_time)->diffInSeconds() > 150 ? 1 : 0; |
||||
} |
||||
|
||||
// 修改現有的diffsecond格式 |
||||
public function getDiffsecondAttribute($value) |
||||
{ |
||||
return floatval($value) * 1000; |
||||
} |
||||
|
||||
public static function cachedDistinctName() |
||||
{ |
||||
return Cache::remember('client_log_distinct_name', 3600, function () { |
||||
return self::select('name')->distinct()->get(); |
||||
}); |
||||
} |
||||
public static function cachedDistinctThisIP() |
||||
{ |
||||
return Cache::remember('client_log_distinct_thisip', 3600, function () { |
||||
return self::select('this_ip')->distinct()->get(); |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Carbon\Carbon; |
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use Illuminate\Support\Facades\Cache; |
||||
|
||||
class Clientlogsecond extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'clientlogsecond'; |
||||
protected $fillable = [ |
||||
'to_ip', |
||||
'to_time', |
||||
'this_ip', |
||||
'this_time', |
||||
'diffsecond', |
||||
'name', |
||||
'pushed', |
||||
]; |
||||
protected $appends = ['before_time','force_time', 'timeout']; |
||||
|
||||
public function getBeforeTimeAttribute() |
||||
{ |
||||
return substr(Carbon::parse($this->this_time)->subMilliseconds($this->diffsecond)->format('Y-m-d H:i:s.u'), 0, -3); |
||||
} |
||||
|
||||
public function getForceTimeAttribute() |
||||
{ |
||||
$forceTime = UserLog::where('action', 'forceTime')->pluck('created_at')->toArray(); |
||||
// 將資料轉換為 Y-m-d H:i 格式 |
||||
$forceTime = array_map(function ($item) { |
||||
return Carbon::parse($item)->format('Y-m-d H:i'); |
||||
}, $forceTime); |
||||
// 將this_time 轉換為 Y-m-d H:i 格式 並比對是否存在於 forceTime 陣列中 |
||||
$thisTime = Carbon::parse($this->this_time)->format('Y-m-d H:i'); |
||||
// 如果存在於陣列中 則回傳 1 代表強制校時 不存在則回傳 0 |
||||
return in_array($thisTime, $forceTime) ? 1 : 0; |
||||
} |
||||
public function getTimeoutAttribute() |
||||
{ |
||||
// this_time 與 serverlog 最新一筆,差超過150秒則回傳1 代表超時 |
||||
|
||||
$serverLog = Serverlog::orderBy('this_time', 'desc')->first(); |
||||
if (!$serverLog) { |
||||
return 1; |
||||
} |
||||
return Carbon::parse($this->this_time)->diffInSeconds($serverLog->this_time) > 150 ? 1 : 0; |
||||
|
||||
// return Carbon::parse($this->this_time)->diffInSeconds() > 150 ? 1 : 0; |
||||
} |
||||
|
||||
// 修改現有的diffsecond格式 |
||||
public function getDiffsecondAttribute($value) |
||||
{ |
||||
return floatval($value) * 1000; |
||||
} |
||||
|
||||
public static function cachedDistinctName() |
||||
{ |
||||
return Cache::remember('client_log2_distinct_name', 3600, function () { |
||||
return self::select('name')->distinct()->get(); |
||||
}); |
||||
} |
||||
} |
@ -0,0 +1,25 @@
@@ -0,0 +1,25 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class CustodyUnit extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'custody_unit'; |
||||
|
||||
protected $fillable = [ |
||||
'name', |
||||
]; |
||||
|
||||
public $timestamps = false; |
||||
|
||||
// 有關聯到違規停車設備 |
||||
public function violationparkingequipment() |
||||
{ |
||||
return $this->hasMany(ViolationParkingEquipment::class, 'custodyunit_id', 'id'); |
||||
} |
||||
} |
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class EquipmentView extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'equipment_view'; |
||||
protected $fillable = [ |
||||
'serialnumber', |
||||
'location', |
||||
'precinct', |
||||
'station', |
||||
]; |
||||
|
||||
// 有關聯到 |
||||
public static function getTypeStation($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('station')->distinct()->pluck('station')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
if ($options != []) { |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} else { |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
|
||||
return $typeCodes; |
||||
} |
||||
public static function getTypePrecinct($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('precinct')->distinct()->pluck('precinct')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
// $type in $options |
||||
if ($options != []) { |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} else { |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
return $typeCodes; |
||||
} |
||||
} |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class ExportFiles extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'export_files'; |
||||
|
||||
protected $fillable = [ |
||||
'name', |
||||
'path', |
||||
'type', |
||||
'status', |
||||
'remark', |
||||
'user_id', |
||||
]; |
||||
|
||||
// protected $casts = [ |
||||
// 'created_at' => 'datetime:Y-m-d H:i:s', |
||||
// ]; |
||||
|
||||
} |
@ -0,0 +1,166 @@
@@ -0,0 +1,166 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class Interval extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'interval_data'; |
||||
|
||||
protected $fillable = [ |
||||
'is_outlaw', |
||||
'start_id', |
||||
'end_id', |
||||
'start_time', |
||||
'end_time', |
||||
'start_location', |
||||
'end_location', |
||||
'start_serialnumber', |
||||
'end_serialnumber', |
||||
'start_picture', |
||||
'end_picture', |
||||
'start_video', |
||||
'end_video', |
||||
'carnumber', |
||||
'cartype', |
||||
'start_path', |
||||
'end_path', |
||||
'distance', |
||||
'limit_speed', |
||||
'alert_speed', |
||||
'outlaw_speed', |
||||
'limit_time', |
||||
'cert', |
||||
'diff', |
||||
'speed', |
||||
'location', |
||||
'mergedone', |
||||
'intervalnumber', |
||||
'faildata', |
||||
'failreason', |
||||
'violationcode', |
||||
'processcheck', |
||||
'postcheck', |
||||
'jsoncheck', |
||||
'unreportreason', |
||||
'unreportpicture', |
||||
'unreportmergedone', |
||||
'merge_picture' |
||||
]; |
||||
protected $hidden = [ |
||||
'created_at', |
||||
'updated_at', |
||||
'deleted_at' |
||||
]; |
||||
protected $casts = [ |
||||
'is_outlaw' => 'boolean', |
||||
'distance' => 'float', |
||||
'limit_speed' => 'float', |
||||
'alert_speed' => 'float', |
||||
'outlaw_speed' => 'float', |
||||
'limit_time' => 'float', |
||||
'diff' => 'float', |
||||
'mergedone' => 'boolean', |
||||
'faildata' => 'boolean', |
||||
'processcheck' => 'integer', |
||||
'postcheck' => 'integer', |
||||
'unreportmergedone' => 'integer' |
||||
]; |
||||
|
||||
// append fields |
||||
protected $appends = [ |
||||
'law_type', |
||||
]; |
||||
|
||||
public function violationlaw() |
||||
{ |
||||
return $this->hasOne(ViolationLaw::class, 'violationcode', 'violationcode'); |
||||
} |
||||
|
||||
public function getLawTypeAttribute() |
||||
{ |
||||
// 取得陣列 |
||||
$violationtype = "區間超速"; |
||||
// $violationtype = []; |
||||
if ($violationtype == "未依標誌標線號誌" || $violationtype == "未依標誌標線行駛" || $violationtype == "機車未依規定兩段式左轉") { |
||||
$violationtype = ["未依標誌標線號誌行駛"]; |
||||
} else if ($violationtype == "闖紅燈") { |
||||
$violationtype = ["闖紅燈", "紅燈右轉", "紅燈越線"]; |
||||
} else if ($violationtype == "未禮讓行人") { |
||||
$violationtype = ["未禮讓行人"]; |
||||
} else if ($violationtype == "違規停車") { |
||||
$violationtype = ["違規停車"]; |
||||
} else if ($violationtype == "未保持路口淨空") { |
||||
$violationtype = ["未保持路口淨空"]; |
||||
} else if ($violationtype == "超速") { |
||||
$violationtype = ["超速"]; |
||||
} else { |
||||
$violationtype = [$violationtype]; |
||||
} |
||||
$except_arr =[ |
||||
'3310146', |
||||
'3310148', |
||||
'4340069' |
||||
]; |
||||
$types = ViolationLaw::whereIn('type', $violationtype)->whereNotIn('violationcode',$except_arr)->get(); |
||||
$lawData = []; |
||||
foreach ($types as $type) { |
||||
$lawData["$type->violationcode"] = "[$type->violationcode] $type->display_name"; |
||||
} |
||||
|
||||
$customLaws = ViolationLaw::whereIn('violationcode', ['72000041', '72000051', '72000061'])->get(); |
||||
foreach ($customLaws as $type) { |
||||
$lawData["$type->violationcode"] = "[$type->violationcode] $type->display_name"; |
||||
} |
||||
return $lawData; |
||||
} |
||||
// public function getMergePictureAttribute($value) |
||||
// { |
||||
// // replace * with / |
||||
|
||||
// return 'ParsingFiles/Interval/' . str_replace('*', '/', $value); |
||||
// } |
||||
// public function getStartPictureAttribute($value) |
||||
// { |
||||
// return $value ? asset('storage/' . $value) : null; |
||||
// } |
||||
// public function getEndPictureAttribute($value) |
||||
// { |
||||
// return $value ? asset('storage/' . $value) : null; |
||||
// } |
||||
// public function getStartVideoAttribute($value) |
||||
// { |
||||
// return $value ? asset('storage/' . $value) : null; |
||||
// } |
||||
// public function getEndVideoAttribute($value) |
||||
// { |
||||
// return $value ? asset('storage/' . $value) : null; |
||||
// } |
||||
// public function getUnreportPictureAttribute($value) |
||||
// { |
||||
// return $value ? asset('storage/' . $value) : null; |
||||
// } |
||||
// public function getMergePictureAttribute($value) |
||||
// { |
||||
// return $value ? asset('storage/' . $value) : null; |
||||
// } |
||||
// public function getCreatedAtAttribute($value) |
||||
// { |
||||
// return $value ? date('Y-m-d H:i:s', strtotime($value)) : null; |
||||
// } |
||||
// public function getUpdatedAtAttribute($value) |
||||
// { |
||||
// return $value ? date('Y-m-d H:i:s', strtotime($value)) : null; |
||||
// } |
||||
// public function getDeletedAtAttribute($value) |
||||
// { |
||||
// return $value ? date('Y-m-d H:i:s', strtotime($value)) : null; |
||||
// } |
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class IntervalEntry extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'interval_entry'; |
||||
protected $fillable = [ |
||||
'interval_id', |
||||
'no', |
||||
'photo', |
||||
'response', |
||||
'status', |
||||
]; |
||||
|
||||
} |
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class IntervalEquipment extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'interval_equipment'; |
||||
protected $dates = ['deleted_at']; |
||||
protected $fillable = [ |
||||
'serialnumber', |
||||
'brand', |
||||
'model', |
||||
'videonumber', |
||||
'custodyunit_id', |
||||
'assetownership_id', |
||||
'buydate', |
||||
'activatedate', |
||||
'locationid', |
||||
'location', |
||||
'comment', |
||||
'map', |
||||
'precinct', |
||||
'station', |
||||
]; |
||||
// append fields |
||||
protected $appends = [ |
||||
'custodyunit_name', |
||||
'assetownership_name', |
||||
]; |
||||
|
||||
// custome fields |
||||
public function getCustodyunitNameAttribute() |
||||
{ |
||||
$name = CustodyUnit::find($this->custodyunit_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
public function getAssetownershipNameAttribute() |
||||
{ |
||||
$name = AssetOwnership::find($this->assetownership_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
// 有關聯到設備保管單位 |
||||
public function custodyunit() |
||||
{ |
||||
return $this->belongsTo(CustodyUnit::class, 'custodyunit_id', 'id'); |
||||
} |
||||
|
||||
// 有關聯到設備財產權屬 |
||||
public function assetownership() |
||||
{ |
||||
return $this->belongsTo(AssetOwnership::class, 'assetownership_id', 'id'); |
||||
} |
||||
|
||||
// 有關聯到 |
||||
public static function getTypeStation($options = []) |
||||
{ |
||||
$types = self::select('station')->distinct()->pluck('station')->toArray(); |
||||
|
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
|
||||
return $typeCodes; |
||||
} |
||||
public static function getTypePrecinct($options = []) |
||||
{ |
||||
$types = self::select('precinct')->distinct()->pluck('precinct')->toArray(); |
||||
|
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
// $type in $options |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
return $typeCodes; |
||||
} |
||||
} |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class Intervaldis extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'intervaldis'; |
||||
|
||||
protected $fillable = [ |
||||
'start_serialnumber', |
||||
'end_serialnumber', |
||||
'distance', |
||||
'limit_speed', |
||||
'outlaw_speed', |
||||
'limit_time', |
||||
'speed_alert', |
||||
'count_alert', |
||||
'location', |
||||
'location_id', |
||||
'certificatenumber', |
||||
'crosspathban', |
||||
'carkindban', |
||||
'start_cert', |
||||
'end_cert', |
||||
]; |
||||
protected $hidden = [ |
||||
'created_at', |
||||
'updated_at', |
||||
'deleted_at' |
||||
]; |
||||
|
||||
protected $appends = ['start_num', 'end_num']; |
||||
|
||||
public function getStartNumAttribute() |
||||
{ |
||||
return IntervalEquipment::find($this->start_serialnumber)->serialnumber; |
||||
} |
||||
|
||||
public function getEndNumAttribute() |
||||
{ |
||||
return IntervalEquipment::find($this->end_serialnumber)->serialnumber; |
||||
} |
||||
|
||||
public function start() |
||||
{ |
||||
return $this->belongsTo(IntervalEquipment::class, 'start_serialnumber', 'serialnumber'); |
||||
} |
||||
|
||||
public function end() |
||||
{ |
||||
return $this->belongsTo(IntervalEquipment::class, 'end_serialnumber', 'serialnumber'); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,70 @@
@@ -0,0 +1,70 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class Multisys extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'multisys'; |
||||
|
||||
protected $fillable = [ |
||||
'picture', |
||||
'picture2', |
||||
'datatime', |
||||
'cartype', |
||||
'carnumber', |
||||
'serialnumber', |
||||
'location', |
||||
'limitspeed', |
||||
'speed', |
||||
'sid', |
||||
'violationtype', |
||||
'violationcode', |
||||
'processcheck', |
||||
'postcheck', |
||||
'jsoncheck', |
||||
'unreportreason', |
||||
'unreportpicture', |
||||
'unreportmergedone', |
||||
]; |
||||
|
||||
// append fields |
||||
protected $appends = [ |
||||
'law_type', |
||||
]; |
||||
public function violationlaw() |
||||
{ |
||||
return $this->hasOne(ViolationLaw::class, 'violationcode', 'violationcode'); |
||||
} |
||||
|
||||
public function getLawTypeAttribute() |
||||
{ |
||||
// 取得陣列 |
||||
$violationtype = $this->violationtype; |
||||
// $violationtype = []; |
||||
if ($violationtype == "未依標誌標線號誌" || $violationtype == "未依標誌標線行駛" || $violationtype == "機車未依規定兩段式左轉") { |
||||
$violationtype = ["未依標誌標線號誌行駛"]; |
||||
} else if ($violationtype == "闖紅燈") { |
||||
$violationtype = ["闖紅燈", "紅燈右轉", "紅燈越線"]; |
||||
} else if ($violationtype == "未禮讓行人") { |
||||
$violationtype = ["未禮讓行人"]; |
||||
} else if ($violationtype == "違規停車") { |
||||
$violationtype = ["違規停車"]; |
||||
} else if ($violationtype == "未保持路口淨空") { |
||||
$violationtype = ["未保持路口淨空"]; |
||||
} else if ($violationtype == "超速") { |
||||
$violationtype = ["超速"]; |
||||
} else { |
||||
$violationtype = [$violationtype]; |
||||
} |
||||
$types = ViolationLaw::whereIn('type', $violationtype)->get(); |
||||
$lawData = []; |
||||
foreach ($types as $type) { |
||||
$lawData["$type->violationcode"] = "[$type->violationcode] $type->display_name"; |
||||
} |
||||
return $lawData; |
||||
} |
||||
} |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class MultisysEntry extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'multisys_entry'; |
||||
protected $fillable = [ |
||||
'multisys_id', |
||||
'no', |
||||
'photo', |
||||
'response', |
||||
'status', |
||||
]; |
||||
|
||||
} |
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use COM; |
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use Illuminate\Database\Eloquent\SoftDeletes; |
||||
|
||||
class MultisysEquipment extends Model |
||||
{ |
||||
use HasFactory, SoftDeletes; |
||||
protected $table = 'multisys_equipment'; |
||||
protected $dates = ['deleted_at']; |
||||
protected $fillable = [ |
||||
'serialnumber', |
||||
'brand', |
||||
'model', |
||||
'custodyunit_id', |
||||
'assetownership_id', |
||||
'buydate', |
||||
'activatedate', |
||||
'locationid', |
||||
'location', |
||||
'comment', |
||||
'map', |
||||
'precinct', |
||||
'station', |
||||
]; |
||||
// append fields |
||||
protected $appends = [ |
||||
'custodyunit_name', |
||||
'assetownership_name', |
||||
'short_name', |
||||
]; |
||||
|
||||
// custome fields |
||||
public function getShortNameAttribute() |
||||
{ |
||||
$match = [ |
||||
'桃園區國際路二段與大興西路三段路口' => '國際路二段與大興西三段', |
||||
'桃園區復興路與民生路口' => '復興路與民生路', |
||||
'桃園區三民路二段與春日路口' => '三民二段與春日路', |
||||
'桃園區中山路與上海路口' => '中山路與上海路', |
||||
'桃園區三民路二段與民生路口' => '三民路二段與民生路', |
||||
'桃園區春日路與民光東路口' => '春日路與民光東路', |
||||
'桃園區三民路三段與永安路口' => '三民路三段與永安路', |
||||
'蘆竹區中正路與南山路一段路口' => '蘆竹中正路與南山路一段', |
||||
'八德區中華路與永豐路口' => '八德中華路與永豐路', |
||||
'八德區建德路與豐德路口' => '八德建德路與豐德路', |
||||
]; |
||||
$name = $match[$this->location] ?? $this->location; |
||||
return $name; |
||||
} |
||||
public function getCustodyunitNameAttribute() |
||||
{ |
||||
$name = CustodyUnit::find($this->custodyunit_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
public function getAssetownershipNameAttribute() |
||||
{ |
||||
$name = AssetOwnership::find($this->assetownership_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
// 有關聯到設備保管單位 |
||||
public function custodyunit() |
||||
{ |
||||
return $this->belongsTo(CustodyUnit::class, 'custodyunit_id', 'id'); |
||||
} |
||||
|
||||
// 有關聯到設備財產權屬 |
||||
public function assetownership() |
||||
{ |
||||
return $this->belongsTo(AssetOwnership::class, 'assetownership_id', 'id'); |
||||
} |
||||
|
||||
// 有關聯到 |
||||
public static function getTypeStation($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('station')->distinct()->pluck('station')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
|
||||
return $typeCodes; |
||||
} |
||||
public static function getTypePrecinct($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('precinct')->distinct()->pluck('precinct')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
// $type in $options |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
return $typeCodes; |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class OverSpeedRed extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'overspeedred'; |
||||
protected $primaryKey = 'id'; |
||||
protected $fillable = [ |
||||
'picture', |
||||
'picture2', |
||||
'serialnumber', |
||||
'location', |
||||
'limitspeed', |
||||
'violationtype', |
||||
'violationcode', |
||||
'cartype', |
||||
'sid', |
||||
'datatime', |
||||
'speed', |
||||
'carnumber', |
||||
'processcheck', |
||||
'jsoncheck', |
||||
'unreportreason', |
||||
'unreportpicture', |
||||
'unreportmergedone' |
||||
]; |
||||
|
||||
protected $appends = [ |
||||
'law_type', |
||||
]; |
||||
public function violationlaw() |
||||
{ |
||||
return $this->hasOne(ViolationLaw::class, 'violationcode', 'violationcode'); |
||||
} |
||||
|
||||
public function getLawTypeAttribute() |
||||
{ |
||||
// 取得陣列 |
||||
$violationtype = $this->violationtype; |
||||
// $violationtype = []; |
||||
if ($violationtype == "未依標誌標線號誌" || $violationtype == "未依標誌標線行駛") { |
||||
$violationtype = ["未依標誌標線號誌行駛"]; |
||||
} else if ($violationtype == "闖紅燈") { |
||||
$violationtype = ["闖紅燈", "紅燈右轉", "紅燈越線"]; |
||||
} else if ($violationtype == "未禮讓行人") { |
||||
$violationtype = ["未禮讓行人"]; |
||||
} else if ($violationtype == "違規停車") { |
||||
$violationtype = ["違規停車"]; |
||||
} else if ($violationtype == "未保持路口淨空") { |
||||
$violationtype = ["未保持路口淨空"]; |
||||
} else if ($violationtype == "超速") { |
||||
$violationtype = ["超速"]; |
||||
} else { |
||||
$violationtype = [$violationtype]; |
||||
} |
||||
$types = ViolationLaw::whereIn('type', $violationtype)->get(); |
||||
$lawData = []; |
||||
foreach ($types as $type) { |
||||
$lawData["$type->violationcode"] = "[$type->violationcode] $type->display_name"; |
||||
} |
||||
return $lawData; |
||||
} |
||||
} |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class OverSpeedRedEntry extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'overspeedred_entry'; |
||||
protected $fillable = [ |
||||
'overspeedred_id', |
||||
'no', |
||||
'photo', |
||||
'response', |
||||
'status', |
||||
]; |
||||
} |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class OverSpeedRedEntry2 extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'overspeedred_entry2'; |
||||
protected $fillable = [ |
||||
'overspeedred_id', |
||||
'no', |
||||
'photo', |
||||
'response', |
||||
'status', |
||||
]; |
||||
} |
@ -0,0 +1,131 @@
@@ -0,0 +1,131 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use Illuminate\Database\Eloquent\SoftDeletes; |
||||
|
||||
class OverSpeedRedEquipment extends Model |
||||
{ |
||||
use HasFactory; |
||||
use HasFactory, SoftDeletes; |
||||
protected $table = 'overspeedred_equipment'; |
||||
protected $dates = ['deleted_at']; |
||||
protected $fillable = [ |
||||
'serialnumber', |
||||
'brand', |
||||
'model', |
||||
'custodyunit_id', |
||||
'assetownership_id', |
||||
'buydate', |
||||
'activatedate', |
||||
'locationid', |
||||
'location', |
||||
'comment', |
||||
'precinct', |
||||
'station', |
||||
]; |
||||
// append fields |
||||
protected $appends = [ |
||||
'custodyunit_name', |
||||
'assetownership_name', |
||||
'short_name', |
||||
]; |
||||
|
||||
// custome fields |
||||
public function getShortNameAttribute() |
||||
{ |
||||
$match = [ |
||||
'桃園區國際路二段與大興西路三段路口' => '國際路二段與大興西三段', |
||||
'桃園區復興路與民生路口' => '復興路與民生路', |
||||
'桃園區三民路二段與春日路口' => '三民二段與春日路', |
||||
'桃園區中山路與上海路口' => '中山路與上海路', |
||||
'桃園區三民路二段與民生路口' => '三民路二段與民生路', |
||||
'桃園區春日路與民光東路口' => '春日路與民光東路', |
||||
'桃園區三民路三段與永安路口' => '三民路三段與永安路', |
||||
'蘆竹區中正路與南山路一段路口' => '蘆竹中正路與南山路一段', |
||||
'八德區中華路與永豐路口' => '八德中華路與永豐路', |
||||
'八德區建德路與豐德路口' => '八德建德路與豐德路', |
||||
|
||||
'大溪區台七乙線9K+100' => '台七乙線9K+100處', |
||||
'桃園區大興西路三段與正光路口(往交流道)' =>'大興西與正光路', |
||||
'龍潭區台3線50.8K處(往龍潭)' =>'龍潭台3線50.8K', |
||||
'龜山區萬壽路二段472號前' =>'龜山萬壽路472號前', |
||||
'中壢區民權路五段65號前' =>'民權路65號前', |
||||
'楊梅區台1線50K+536處' =>'楊梅台1線50K+536', |
||||
'大溪區仁和路2段517巷' =>'大溪仁和路2段517巷', |
||||
'觀音區濱海路廣興段845號前' =>'觀音濱海路與廣興段', |
||||
'龍潭區中正路三林段330號' =>'龍潭中正路三林段', |
||||
'桃園區中山路輿上海路口' =>'中山路與上海路口', |
||||
]; |
||||
$name = $match[$this->location] ?? $this->location; |
||||
return $name; |
||||
} |
||||
public function getCustodyunitNameAttribute() |
||||
{ |
||||
$name = CustodyUnit::find($this->custodyunit_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
public function getAssetownershipNameAttribute() |
||||
{ |
||||
$name = AssetOwnership::find($this->assetownership_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
// 有關聯到設備保管單位 |
||||
public function custodyunit() |
||||
{ |
||||
return $this->belongsTo(CustodyUnit::class, 'custodyunit_id', 'id'); |
||||
} |
||||
|
||||
// 有關聯到設備財產權屬 |
||||
public function assetownership() |
||||
{ |
||||
return $this->belongsTo(AssetOwnership::class, 'assetownership_id', 'id'); |
||||
} |
||||
// 有關聯到 |
||||
public static function getTypeStation($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('station')->distinct()->pluck('station')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
|
||||
return $typeCodes; |
||||
} |
||||
public static function getTypePrecinct($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('precinct')->distinct()->pluck('precinct')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
// $type in $options |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
return $typeCodes; |
||||
} |
||||
} |
@ -0,0 +1,15 @@
@@ -0,0 +1,15 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class Permission extends \Spatie\Permission\Models\Permission |
||||
{ |
||||
protected $guard = []; |
||||
protected $guard_name = '*'; |
||||
// guard_name = '*' 代表所有 guard 都可以使用這個 model |
||||
// 這樣就不用在每次使用這個 model 時都要加上 guard_name |
||||
|
||||
} |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class PingIp extends Model |
||||
{ |
||||
// |
||||
// protected $connection = 'mysql_ping'; |
||||
protected $table = "ping_ip"; |
||||
protected $fillable = ["ip", "ping_time", "time", "symbol", "serialnumber", "ttl", "status"]; |
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class Role extends \Spatie\Permission\Models\Role |
||||
{ |
||||
protected $guard = []; |
||||
protected $guard_name = '*'; |
||||
// guard_name = '*' 代表所有 guard 都可以使用這個 model |
||||
// 這樣就不用在每次使用這個 model 時都要加上 guard_name |
||||
// 例如: Role::where('name', 'Admin')->first(); |
||||
|
||||
} |
@ -0,0 +1,39 @@
@@ -0,0 +1,39 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Carbon\Carbon; |
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class Serverlog extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'serverlog'; |
||||
protected $fillable = [ |
||||
'to_ip', |
||||
'to_time', |
||||
'this_ip', |
||||
'this_time', |
||||
'diffsecond', |
||||
'name', |
||||
]; |
||||
protected $appends = ['before_time', 'timeout']; |
||||
|
||||
public function getBeforeTimeAttribute() |
||||
{ |
||||
return substr(Carbon::parse($this->this_time)->subMilliseconds($this->diffsecond)->format('Y-m-d H:i:s.u'), 0, -3); |
||||
} |
||||
public function getTimeoutAttribute() |
||||
{ |
||||
// this_time 與現在差超過150秒則回傳1 代表超時 |
||||
return Carbon::parse($this->this_time)->diffInSeconds() > 150 ? 1 : 0; |
||||
} |
||||
|
||||
// 修改現有的diffsecond格式 |
||||
public function getDiffsecondAttribute($value) |
||||
{ |
||||
return floatval($value) * 1000; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class StatisticView extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'statistic_view'; |
||||
protected $fillable = [ |
||||
'datatime', |
||||
'serialnumber', |
||||
'location', |
||||
'violationcode', |
||||
'processcheck', |
||||
'jsoncheck', |
||||
]; |
||||
} |
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use Illuminate\Support\Facades\Cache; |
||||
|
||||
class UserLog extends Model |
||||
{ |
||||
use HasFactory; |
||||
|
||||
protected $table = 'user_log'; |
||||
|
||||
protected $fillable = [ |
||||
'user_id', |
||||
'user_name', |
||||
'action', |
||||
'action_detail', |
||||
'ip', |
||||
'mac', |
||||
'remark', |
||||
'carnumber', |
||||
'location', |
||||
]; |
||||
|
||||
// protected $casts = [ |
||||
// 'created_at' => 'datetime:Y-m-d H:i:s', |
||||
// ]; |
||||
public static function cachedDistinctActionDetail() |
||||
{ |
||||
return Cache::remember('user_log_distinct_action_detail', 3600, function () { |
||||
return self::select('action_detail')->distinct()->get(); |
||||
}); |
||||
} |
||||
//cachedDistinctUser |
||||
public static function cachedDistinctUser() |
||||
{ |
||||
return Cache::remember('user_log_distinct_user', 3600, function () { |
||||
return self::select('user_name')->distinct()->get(); |
||||
}); |
||||
} |
||||
public function user() |
||||
{ |
||||
return $this->belongsTo(User::class); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class ViolationLaw extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'violation_law'; |
||||
protected $fillable = [ |
||||
'code', |
||||
'display_name', |
||||
'type', |
||||
'sort', |
||||
]; |
||||
|
||||
public static function getTypeCodes() |
||||
{ |
||||
$types = self::select('type')->distinct()->pluck('type')->toArray(); |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
if ($type == 99 || $type== 3 || $type == 1) { |
||||
continue; |
||||
} |
||||
$codes = self::where('type', $type)->pluck('violationcode')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
|
||||
return $typeCodes; |
||||
} |
||||
} |
@ -0,0 +1,66 @@
@@ -0,0 +1,66 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
|
||||
class ViolationParking extends Model |
||||
{ |
||||
use HasFactory; |
||||
protected $table = 'violationparking'; |
||||
|
||||
protected $fillable = [ |
||||
'picture', |
||||
'picture2', |
||||
'datatime', |
||||
'cartype', |
||||
'carnumber', |
||||
'serialnumber', |
||||
'location', |
||||
'violationtype', |
||||
'violationcode', |
||||
'processcheck', |
||||
'postcheck', |
||||
'jsoncheck', |
||||
'unreportreason', |
||||
'unreportpicture', |
||||
'unreportmergedone', |
||||
]; |
||||
|
||||
protected $appends = [ |
||||
'law_type', |
||||
]; |
||||
public function violationlaw() |
||||
{ |
||||
return $this->hasOne(ViolationLaw::class, 'violationcode', 'violationcode'); |
||||
} |
||||
|
||||
public function getLawTypeAttribute() |
||||
{ |
||||
// 取得陣列 |
||||
$violationtype = $this->violationtype; |
||||
// $violationtype = []; |
||||
if ($violationtype == "未依標誌標線號誌" || $violationtype == "未依標誌標線行駛") { |
||||
$violationtype = ["未依標誌標線號誌行駛"]; |
||||
} else if ($violationtype == "闖紅燈") { |
||||
$violationtype = ["闖紅燈", "紅燈右轉", "紅燈越線"]; |
||||
} else if ($violationtype == "未禮讓行人") { |
||||
$violationtype = ["未禮讓行人"]; |
||||
} else if ($violationtype == "違規停車") { |
||||
$violationtype = ["違規停車"]; |
||||
} else if ($violationtype == "未保持路口淨空") { |
||||
$violationtype = ["未保持路口淨空"]; |
||||
} else if ($violationtype == "超速") { |
||||
$violationtype = ["超速"]; |
||||
} else { |
||||
$violationtype = [$violationtype]; |
||||
} |
||||
$types = ViolationLaw::whereIn('type', $violationtype)->get(); |
||||
$lawData = []; |
||||
foreach ($types as $type) { |
||||
$lawData["$type->violationcode"] = "[$type->violationcode] $type->display_name"; |
||||
} |
||||
return $lawData; |
||||
} |
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
<?php |
||||
|
||||
namespace App\Models; |
||||
|
||||
use COM; |
||||
use Illuminate\Database\Eloquent\Factories\HasFactory; |
||||
use Illuminate\Database\Eloquent\Model; |
||||
use Illuminate\Database\Eloquent\SoftDeletes; |
||||
|
||||
class ViolationParkingEquipment extends Model |
||||
{ |
||||
use HasFactory, SoftDeletes; |
||||
protected $table = 'violationparking_equipment'; |
||||
protected $dates = ['deleted_at']; |
||||
protected $fillable = [ |
||||
'serialnumber', |
||||
'brand', |
||||
'model', |
||||
'custodyunit_id', |
||||
'assetownership_id', |
||||
'buydate', |
||||
'activatedate', |
||||
'locationid', |
||||
'location', |
||||
'comment', |
||||
'precinct', |
||||
'station', |
||||
]; |
||||
// append fields |
||||
protected $appends = [ |
||||
'custodyunit_name', |
||||
'assetownership_name', |
||||
]; |
||||
|
||||
// custome fields |
||||
public function getCustodyunitNameAttribute() |
||||
{ |
||||
$name = CustodyUnit::find($this->custodyunit_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
public function getAssetownershipNameAttribute() |
||||
{ |
||||
$name = AssetOwnership::find($this->assetownership_id)->name ?? '無'; |
||||
return $name; |
||||
} |
||||
|
||||
// 有關聯到設備保管單位 |
||||
public function custodyunit() |
||||
{ |
||||
return $this->belongsTo(CustodyUnit::class, 'custodyunit_id', 'id'); |
||||
} |
||||
|
||||
// 有關聯到設備財產權屬 |
||||
public function assetownership() |
||||
{ |
||||
return $this->belongsTo(AssetOwnership::class, 'assetownership_id', 'id'); |
||||
} |
||||
// 有關聯到 |
||||
public static function getTypeStation($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('station')->distinct()->pluck('station')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('station', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
|
||||
return $typeCodes; |
||||
} |
||||
public static function getTypePrecinct($options = []) |
||||
{ |
||||
// 获取所有的类型 |
||||
$types = self::select('precinct')->distinct()->pluck('precinct')->toArray(); |
||||
|
||||
// 构建一个关联数组来存储每个类型对应的代码 |
||||
$typeCodes = []; |
||||
foreach ($types as $type) { |
||||
// $type in $options |
||||
if ($options != []){ |
||||
if (in_array($type, $options)) { |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
}else{ |
||||
$codes = self::where('precinct', $type)->pluck('serialnumber')->toArray(); |
||||
$typeCodes[$type] = $codes; |
||||
} |
||||
} |
||||
return $typeCodes; |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
<?php |
||||
|
||||
namespace App\Repositories; |
||||
|
||||
use App\Models\ViolationParking; |
||||
use Illuminate\Support\Facades\DB; |
||||
|
||||
class ViolationParkingRepository |
||||
{ |
||||
public function buildQuery(array $filters) |
||||
{ |
||||
$query = ViolationParking::query(); |
||||
|
||||
if (!empty($filters['device'])) { |
||||
$query->whereIn('serialnumber', $filters['device']); |
||||
} |
||||
|
||||
if (!empty($filters['searchByFromdate'])) { |
||||
$query->where('datatime', '>=', $filters['searchByFromdate'] . ' 00:00:00'); |
||||
} |
||||
|
||||
if (!empty($filters['searchByTodate'])) { |
||||
$query->where('datatime', '<=', $filters['searchByTodate'] . ' 23:59:59'); |
||||
} |
||||
|
||||
if (!empty($filters['location'])) { |
||||
$query->where('serialnumber', $filters['location']); |
||||
} |
||||
|
||||
if (!empty($filters['carnumber'])) { |
||||
$query->where('carnumber', 'like', '%' . $filters['carnumber'] . '%'); |
||||
} |
||||
|
||||
if (!empty($filters['unreportreason'])) { |
||||
$query->where('unreportreason', 'like', '%' . $filters['unreportreason'] . '%'); |
||||
} |
||||
|
||||
if (!empty($filters['processcheckStatus'])) { |
||||
$status = $filters['processcheckStatus']; |
||||
if ($status == 99) { |
||||
$query->whereIn('processcheck', [0, 1, 2]); |
||||
} else { |
||||
$query->where('processcheck', $status); |
||||
} |
||||
} |
||||
|
||||
// 排除違規臨時停車 |
||||
$query->where('violationtype', '!=', '違規臨時停車'); |
||||
|
||||
if (!empty($filters['statisticstype'])) { |
||||
switch ($filters['statisticstype']) { |
||||
case 2: |
||||
$query->groupBy('serialnumber', 'cartype') |
||||
->select('*', DB::raw('count(*) as count')); |
||||
break; |
||||
case 3: |
||||
$query->groupBy(DB::raw("CAST(DATE_FORMAT(datatime, '%H') AS SIGNED)"), '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")) |
||||
->orderBy(DB::raw("CAST(DATE_FORMAT(datatime, '%H') AS SIGNED)"), 'ASC'); |
||||
break; |
||||
default: |
||||
$query->select('*'); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
return $query; |
||||
} |
||||
} |
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
<?php |
||||
|
||||
namespace App\Services; |
||||
|
||||
use App\Repositories\ViolationParkingRepository; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Carbon\Carbon; |
||||
|
||||
class ViolationParkingDataService |
||||
{ |
||||
protected $repository; |
||||
|
||||
public function __construct(ViolationParkingRepository $repository) |
||||
{ |
||||
$this->repository = $repository; |
||||
} |
||||
|
||||
public function getDataTable(array $filters): array |
||||
{ |
||||
$query = $this->repository->buildQuery($filters); |
||||
|
||||
$draw = intval($filters['draw'] ?? 0); |
||||
$start = $filters['start'] ?? 0; |
||||
$length = $filters['length'] ?? 10; |
||||
|
||||
$totalRecords = $query->count(); |
||||
|
||||
if (!isset($filters['export'])) { |
||||
$query->skip($start)->take($length); |
||||
} |
||||
|
||||
$records = $query->get(); |
||||
$data_arr = []; |
||||
|
||||
foreach ($records as $record) { |
||||
$cartypeTitle = [ |
||||
'1' => '汽車', |
||||
'2' => '機車', |
||||
'3' => '重型機車', |
||||
'4' => '輕型機車', |
||||
]; |
||||
$processCheckTitle = [ |
||||
'0' => '未審', |
||||
'1' => '已審查', |
||||
'2' => '不舉發', |
||||
]; |
||||
|
||||
$data_arr[] = [ |
||||
'id' => $record->id, |
||||
'datatime' => $record->datatime, |
||||
'serialnumber' => $record->serialnumber, |
||||
'location' => $record->location, |
||||
'carnumber' => $record->carnumber, |
||||
'picture' => $record->picture, |
||||
'picture2' => $record->picture2, |
||||
'video' => str_replace('.jpg', '.mp4', $record->picture2), |
||||
'violationtype' => $record->violationtype, |
||||
'cartype' => $record->cartype, |
||||
'carkind' => $cartypeTitle[$record->cartype] ?? '', |
||||
'unreportreason' => $record->unreportreason ?? '', |
||||
'unreportpicture' => $record->unreportpicture ?? $record->picture, |
||||
'postcheck' => $record->postcheck ?? 0, |
||||
'processcheck' => $processCheckTitle[$record->processcheck] ?? '', |
||||
'count' => $record->count ?? 0, |
||||
'period' => $record->period ?? '', |
||||
]; |
||||
} |
||||
|
||||
return [ |
||||
'draw' => $draw, |
||||
'iTotalRecords' => $totalRecords, |
||||
'iTotalDisplayRecords' => $totalRecords, |
||||
'aaData' => $data_arr, |
||||
]; |
||||
} |
||||
} |
@ -0,0 +1,108 @@
@@ -0,0 +1,108 @@
|
||||
<?php |
||||
|
||||
namespace App\Services; |
||||
|
||||
use App\Models\ViolationParking; |
||||
use Illuminate\Support\Facades\DB; |
||||
use App\Class\LogWriter; |
||||
use Illuminate\Support\Facades\Auth; |
||||
use Carbon\Carbon; |
||||
|
||||
class ViolationParkingService |
||||
{ |
||||
public function review(ViolationParking $vpk, array $data, $user): array |
||||
{ |
||||
DB::beginTransaction(); |
||||
|
||||
try { |
||||
$logData = []; |
||||
|
||||
switch ($data['processcheck']) { |
||||
case 0: |
||||
// 編輯案件 |
||||
$vpk->carnumber = $data['carnumber'] ?? $vpk->carnumber; |
||||
$vpk->violationtype = $data['violationtype'] ?? $vpk->violationtype; |
||||
$vpk->cartype = $data['cartype'] ?? $vpk->cartype; |
||||
$vpk->violationcode = $data['viocode'] ?? $vpk->violationcode; |
||||
|
||||
$logData = [ |
||||
'action' => 'edit', |
||||
'action_detail' => '編輯案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "編輯違停案件: {$vpk->carnumber} ,案件日期: {$vpk->datatime}", |
||||
]; |
||||
break; |
||||
|
||||
case 1: |
||||
// 舉發 |
||||
$carrepeat = ViolationParking::where('carnumber', $data['carnumber'] ?? $vpk->carnumber) |
||||
->where('id', '<>', $vpk->id) |
||||
->where('processcheck', 1) |
||||
->whereBetween('datatime', [ |
||||
Carbon::parse($vpk->datatime)->subDay()->toDateTimeString(), |
||||
Carbon::parse($vpk->datatime)->addDay()->toDateTimeString() |
||||
])->get(); |
||||
|
||||
if ($carrepeat->count() > 0) { |
||||
$vpk->processcheck = 2; |
||||
$vpk->unreportreason = '該車牌24小時內已被舉發過!!'; |
||||
} else { |
||||
$vpk->processcheck = 1; |
||||
} |
||||
|
||||
$vpk->carnumber = $data['carnumber'] ?? $vpk->carnumber; |
||||
$vpk->violationtype = $data['violationtype'] ?? $vpk->violationtype; |
||||
$vpk->cartype = $data['cartype'] ?? $vpk->cartype; |
||||
$vpk->violationcode = $data['viocode'] ?? $vpk->violationcode; |
||||
|
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => $vpk->processcheck === 1 ? '舉發案件' : '不舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "舉發違停案件: {$vpk->carnumber} ,案件日期: {$vpk->datatime}", |
||||
]; |
||||
break; |
||||
|
||||
case 2: |
||||
// 不舉發 |
||||
$vpk->carnumber = $data['carnumber'] ?? $vpk->carnumber; |
||||
$vpk->violationtype = $data['violationtype'] ?? $vpk->violationtype; |
||||
$vpk->cartype = $data['cartype'] ?? $vpk->cartype; |
||||
$vpk->unreportreason = $data['unreportreason'] ?? $vpk->unreportreason; |
||||
$vpk->processcheck = 2; |
||||
|
||||
$logData = [ |
||||
'action' => 'review', |
||||
'action_detail' => '不舉發案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "不舉發違停案件: {$vpk->carnumber} ,案件日期: {$vpk->datatime}", |
||||
]; |
||||
break; |
||||
|
||||
case 3: |
||||
// 還原 |
||||
$vpk->violationcode = null; |
||||
$vpk->unreportreason = ''; |
||||
$vpk->processcheck = 0; |
||||
|
||||
$logData = [ |
||||
'action' => 'reduction', |
||||
'action_detail' => '還原案件', |
||||
'ip' => request()->ip(), |
||||
'remark' => "還原違停案件: {$vpk->carnumber} ,案件日期: {$vpk->datatime}", |
||||
]; |
||||
break; |
||||
} |
||||
|
||||
$vpk->jsoncheck = $user->account; |
||||
$vpk->save(); |
||||
LogWriter::writeLog($logData, 'api'); |
||||
DB::commit(); |
||||
|
||||
return ['success' => $logData['remark']]; |
||||
} catch (\Exception $e) { |
||||
DB::rollBack(); |
||||
return ['error' => '系統錯誤']; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,364 @@
@@ -0,0 +1,364 @@
|
||||
<?php |
||||
|
||||
use Maatwebsite\Excel\Excel; |
||||
|
||||
return [ |
||||
'exports' => [ |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Chunk size |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When using FromQuery, the query is automatically chunked. |
||||
| Here you can specify how big the chunk should be. |
||||
| |
||||
*/ |
||||
'chunk_size' => 1000, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Pre-calculate formulas during export |
||||
|-------------------------------------------------------------------------- |
||||
*/ |
||||
'pre_calculate_formulas' => false, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Enable strict null comparison |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When enabling strict null comparison empty cells ('') will |
||||
| be added to the sheet. |
||||
*/ |
||||
'strict_null_comparison' => false, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| CSV Settings |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure e.g. delimiter, enclosure and line ending for CSV exports. |
||||
| |
||||
*/ |
||||
'csv' => [ |
||||
'delimiter' => ',', |
||||
'enclosure' => '"', |
||||
'line_ending' => PHP_EOL, |
||||
'use_bom' => false, |
||||
'include_separator_line' => false, |
||||
'excel_compatibility' => false, |
||||
'output_encoding' => '', |
||||
'test_auto_detect' => true, |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Worksheet properties |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure e.g. default title, creator, subject,... |
||||
| |
||||
*/ |
||||
'properties' => [ |
||||
'creator' => '', |
||||
'lastModifiedBy' => '', |
||||
'title' => '', |
||||
'description' => '', |
||||
'subject' => '', |
||||
'keywords' => '', |
||||
'category' => '', |
||||
'manager' => '', |
||||
'company' => '', |
||||
], |
||||
], |
||||
|
||||
'imports' => [ |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Read Only |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When dealing with imports, you might only be interested in the |
||||
| data that the sheet exists. By default we ignore all styles, |
||||
| however if you want to do some logic based on style data |
||||
| you can enable it by setting read_only to false. |
||||
| |
||||
*/ |
||||
'read_only' => true, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Ignore Empty |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When dealing with imports, you might be interested in ignoring |
||||
| rows that have null values or empty strings. By default rows |
||||
| containing empty strings or empty values are not ignored but can be |
||||
| ignored by enabling the setting ignore_empty to true. |
||||
| |
||||
*/ |
||||
'ignore_empty' => false, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Heading Row Formatter |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure the heading row formatter. |
||||
| Available options: none|slug|custom |
||||
| |
||||
*/ |
||||
'heading_row' => [ |
||||
'formatter' => 'slug', |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| CSV Settings |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure e.g. delimiter, enclosure and line ending for CSV imports. |
||||
| |
||||
*/ |
||||
'csv' => [ |
||||
'delimiter' => null, |
||||
'enclosure' => '"', |
||||
'escape_character' => '\\', |
||||
'contiguous' => false, |
||||
'input_encoding' => 'UTF-8', |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Worksheet properties |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure e.g. default title, creator, subject,... |
||||
| |
||||
*/ |
||||
'properties' => [ |
||||
'creator' => '', |
||||
'lastModifiedBy' => '', |
||||
'title' => '', |
||||
'description' => '', |
||||
'subject' => '', |
||||
'keywords' => '', |
||||
'category' => '', |
||||
'manager' => '', |
||||
'company' => '', |
||||
], |
||||
|
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Extension detector |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure here which writer/reader type should be used when the package |
||||
| needs to guess the correct type based on the extension alone. |
||||
| |
||||
*/ |
||||
'extension_detector' => [ |
||||
'xlsx' => Excel::XLSX, |
||||
'xlsm' => Excel::XLSX, |
||||
'xltx' => Excel::XLSX, |
||||
'xltm' => Excel::XLSX, |
||||
'xls' => Excel::XLS, |
||||
'xlt' => Excel::XLS, |
||||
'ods' => Excel::ODS, |
||||
'ots' => Excel::ODS, |
||||
'slk' => Excel::SLK, |
||||
'xml' => Excel::XML, |
||||
'gnumeric' => Excel::GNUMERIC, |
||||
'htm' => Excel::HTML, |
||||
'html' => Excel::HTML, |
||||
'csv' => Excel::CSV, |
||||
'tsv' => Excel::TSV, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| PDF Extension |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Configure here which Pdf driver should be used by default. |
||||
| Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF |
||||
| |
||||
*/ |
||||
'pdf' => Excel::DOMPDF, |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Value Binder |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| PhpSpreadsheet offers a way to hook into the process of a value being |
||||
| written to a cell. In there some assumptions are made on how the |
||||
| value should be formatted. If you want to change those defaults, |
||||
| you can implement your own default value binder. |
||||
| |
||||
| Possible value binders: |
||||
| |
||||
| [x] Maatwebsite\Excel\DefaultValueBinder::class |
||||
| [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class |
||||
| [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class |
||||
| |
||||
*/ |
||||
'value_binder' => [ |
||||
'default' => Maatwebsite\Excel\DefaultValueBinder::class, |
||||
], |
||||
|
||||
'cache' => [ |
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Default cell caching driver |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| By default PhpSpreadsheet keeps all cell values in memory, however when |
||||
| dealing with large files, this might result into memory issues. If you |
||||
| want to mitigate that, you can configure a cell caching driver here. |
||||
| When using the illuminate driver, it will store each value in the |
||||
| cache store. This can slow down the process, because it needs to |
||||
| store each value. You can use the "batch" store if you want to |
||||
| only persist to the store when the memory limit is reached. |
||||
| |
||||
| Drivers: memory|illuminate|batch |
||||
| |
||||
*/ |
||||
'driver' => 'memory', |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Batch memory caching |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When dealing with the "batch" caching driver, it will only |
||||
| persist to the store when the memory limit is reached. |
||||
| Here you can tweak the memory limit to your liking. |
||||
| |
||||
*/ |
||||
'batch' => [ |
||||
'memory_limit' => 60000, |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Illuminate cache |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When using the "illuminate" caching driver, it will automatically use |
||||
| your default cache store. However if you prefer to have the cell |
||||
| cache on a separate store, you can configure the store name here. |
||||
| You can use any store defined in your cache config. When leaving |
||||
| at "null" it will use the default store. |
||||
| |
||||
*/ |
||||
'illuminate' => [ |
||||
'store' => null, |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Cache Time-to-live (TTL) |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| The TTL of items written to cache. If you want to keep the items cached |
||||
| indefinitely, set this to null. Otherwise, set a number of seconds, |
||||
| a \DateInterval, or a callable. |
||||
| |
||||
| Allowable types: callable|\DateInterval|int|null |
||||
| |
||||
*/ |
||||
'default_ttl' => 10800, |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Transaction Handler |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| By default the import is wrapped in a transaction. This is useful |
||||
| for when an import may fail and you want to retry it. With the |
||||
| transactions, the previous import gets rolled-back. |
||||
| |
||||
| You can disable the transaction handler by setting this to null. |
||||
| Or you can choose a custom made transaction handler here. |
||||
| |
||||
| Supported handlers: null|db |
||||
| |
||||
*/ |
||||
'transactions' => [ |
||||
'handler' => 'db', |
||||
'db' => [ |
||||
'connection' => null, |
||||
], |
||||
], |
||||
|
||||
'temporary_files' => [ |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Local Temporary Path |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When exporting and importing files, we use a temporary file, before |
||||
| storing reading or downloading. Here you can customize that path. |
||||
| permissions is an array with the permission flags for the directory (dir) |
||||
| and the create file (file). |
||||
| |
||||
*/ |
||||
'local_path' => storage_path('framework/cache/laravel-excel'), |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Local Temporary Path Permissions |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Permissions is an array with the permission flags for the directory (dir) |
||||
| and the create file (file). |
||||
| If omitted the default permissions of the filesystem will be used. |
||||
| |
||||
*/ |
||||
'local_permissions' => [ |
||||
// 'dir' => 0755, |
||||
// 'file' => 0644, |
||||
], |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Remote Temporary Disk |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When dealing with a multi server setup with queues in which you |
||||
| cannot rely on having a shared local temporary path, you might |
||||
| want to store the temporary file on a shared disk. During the |
||||
| queue executing, we'll retrieve the temporary file from that |
||||
| location instead. When left to null, it will always use |
||||
| the local path. This setting only has effect when using |
||||
| in conjunction with queued imports and exports. |
||||
| |
||||
*/ |
||||
'remote_disk' => null, |
||||
'remote_prefix' => null, |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Force Resync |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| When dealing with a multi server setup as above, it's possible |
||||
| for the clean up that occurs after entire queue has been run to only |
||||
| cleanup the server that the last AfterImportJob runs on. The rest of the server |
||||
| would still have the local temporary file stored on it. In this case your |
||||
| local storage limits can be exceeded and future imports won't be processed. |
||||
| To mitigate this you can set this config value to be true, so that after every |
||||
| queued chunk is processed the local temporary file is deleted on the server that |
||||
| processed it. |
||||
| |
||||
*/ |
||||
'force_resync_remote' => null, |
||||
], |
||||
]; |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
<?php |
||||
|
||||
return [ |
||||
|
||||
/* |
||||
|-------------------------------------------------------------------------- |
||||
| Image Driver |
||||
|-------------------------------------------------------------------------- |
||||
| |
||||
| Intervention Image supports “GD Library” and “Imagick” to process images |
||||
| internally. Depending on your PHP setup, you can choose one of them. |
||||
| |
||||
| Included options: |
||||
| - \Intervention\Image\Drivers\Gd\Driver::class |
||||
| - \Intervention\Image\Drivers\Imagick\Driver::class |
||||
| |
||||
*/ |
||||
|
||||
'driver' => \Intervention\Image\Drivers\Gd\Driver::class |
||||
|
||||
]; |
@ -0,0 +1,161 @@
@@ -0,0 +1,161 @@
|
||||
<?php |
||||
|
||||
return [ |
||||
|
||||
'models' => [ |
||||
|
||||
/* |
||||
* When using the "HasPermissions" trait from this package, we need to know which |
||||
* Eloquent model should be used to retrieve your permissions. Of course, it |
||||
* is often just the "Permission" model but you may use whatever you like. |
||||
* |
||||
* The model you want to use as a Permission model needs to implement the |
||||
* `Spatie\Permission\Contracts\Permission` contract. |
||||
*/ |
||||
|
||||
'permission' => Spatie\Permission\Models\Permission::class, |
||||
|
||||
/* |
||||
* When using the "HasRoles" trait from this package, we need to know which |
||||
* Eloquent model should be used to retrieve your roles. Of course, it |
||||
* is often just the "Role" model but you may use whatever you like. |
||||
* |
||||
* The model you want to use as a Role model needs to implement the |
||||
* `Spatie\Permission\Contracts\Role` contract. |
||||
*/ |
||||
|
||||
'role' => Spatie\Permission\Models\Role::class, |
||||
|
||||
], |
||||
|
||||
'table_names' => [ |
||||
|
||||
/* |
||||
* When using the "HasRoles" trait from this package, we need to know which |
||||
* table should be used to retrieve your roles. We have chosen a basic |
||||
* default value but you may easily change it to any table you like. |
||||
*/ |
||||
|
||||
'roles' => 'roles', |
||||
|
||||
/* |
||||
* When using the "HasPermissions" trait from this package, we need to know which |
||||
* table should be used to retrieve your permissions. We have chosen a basic |
||||
* default value but you may easily change it to any table you like. |
||||
*/ |
||||
|
||||
'permissions' => 'permissions', |
||||
|
||||
/* |
||||
* When using the "HasPermissions" trait from this package, we need to know which |
||||
* table should be used to retrieve your models permissions. We have chosen a |
||||
* basic default value but you may easily change it to any table you like. |
||||
*/ |
||||
|
||||
'model_has_permissions' => 'model_has_permissions', |
||||
|
||||
/* |
||||
* When using the "HasRoles" trait from this package, we need to know which |
||||
* table should be used to retrieve your models roles. We have chosen a |
||||
* basic default value but you may easily change it to any table you like. |
||||
*/ |
||||
|
||||
'model_has_roles' => 'model_has_roles', |
||||
|
||||
/* |
||||
* When using the "HasRoles" trait from this package, we need to know which |
||||
* table should be used to retrieve your roles permissions. We have chosen a |
||||
* basic default value but you may easily change it to any table you like. |
||||
*/ |
||||
|
||||
'role_has_permissions' => 'role_has_permissions', |
||||
], |
||||
|
||||
'column_names' => [ |
||||
/* |
||||
* Change this if you want to name the related pivots other than defaults |
||||
*/ |
||||
'role_pivot_key' => null, //default 'role_id', |
||||
'permission_pivot_key' => null, //default 'permission_id', |
||||
|
||||
/* |
||||
* Change this if you want to name the related model primary key other than |
||||
* `model_id`. |
||||
* |
||||
* For example, this would be nice if your primary keys are all UUIDs. In |
||||
* that case, name this `model_uuid`. |
||||
*/ |
||||
|
||||
'model_morph_key' => 'model_id', |
||||
|
||||
/* |
||||
* Change this if you want to use the teams feature and your related model's |
||||
* foreign key is other than `team_id`. |
||||
*/ |
||||
|
||||
'team_foreign_key' => 'team_id', |
||||
], |
||||
|
||||
/* |
||||
* When set to true, the method for checking permissions will be registered on the gate. |
||||
* Set this to false, if you want to implement custom logic for checking permissions. |
||||
*/ |
||||
|
||||
'register_permission_check_method' => true, |
||||
|
||||
/* |
||||
* When set to true the package implements teams using the 'team_foreign_key'. If you want |
||||
* the migrations to register the 'team_foreign_key', you must set this to true |
||||
* before doing the migration. If you already did the migration then you must make a new |
||||
* migration to also add 'team_foreign_key' to 'roles', 'model_has_roles', and |
||||
* 'model_has_permissions'(view the latest version of package's migration file) |
||||
*/ |
||||
|
||||
'teams' => false, |
||||
|
||||
/* |
||||
* When set to true, the required permission names are added to the exception |
||||
* message. This could be considered an information leak in some contexts, so |
||||
* the default setting is false here for optimum safety. |
||||
*/ |
||||
|
||||
'display_permission_in_exception' => false, |
||||
|
||||
/* |
||||
* When set to true, the required role names are added to the exception |
||||
* message. This could be considered an information leak in some contexts, so |
||||
* the default setting is false here for optimum safety. |
||||
*/ |
||||
|
||||
'display_role_in_exception' => false, |
||||
|
||||
/* |
||||
* By default wildcard permission lookups are disabled. |
||||
*/ |
||||
|
||||
'enable_wildcard_permission' => false, |
||||
|
||||
'cache' => [ |
||||
|
||||
/* |
||||
* By default all permissions are cached for 24 hours to speed up performance. |
||||
* When permissions or roles are updated the cache is flushed automatically. |
||||
*/ |
||||
|
||||
'expiration_time' => \DateInterval::createFromDateString('24 hours'), |
||||
|
||||
/* |
||||
* The cache key used to store all permissions. |
||||
*/ |
||||
|
||||
'key' => 'spatie.permission.cache', |
||||
|
||||
/* |
||||
* You may optionally indicate a specific cache driver to use for permission and |
||||
* role caching using any of the `store` drivers listed in the cache.php config |
||||
* file. Using 'default' here means to use the `default` set in cache.php. |
||||
*/ |
||||
|
||||
'store' => 'default', |
||||
], |
||||
]; |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function up() |
||||
{ |
||||
Schema::create('password_resets', function (Blueprint $table) { |
||||
$table->string('email')->index(); |
||||
$table->string('token'); |
||||
$table->timestamp('created_at')->nullable(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function down() |
||||
{ |
||||
Schema::dropIfExists('password_resets'); |
||||
} |
||||
}; |
@ -0,0 +1,145 @@
@@ -0,0 +1,145 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Support\Facades\Schema; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Spatie\Permission\PermissionRegistrar; |
||||
|
||||
class CreatePermissionTables extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function up() |
||||
{ |
||||
$tableNames = config('permission.table_names'); |
||||
$columnNames = config('permission.column_names'); |
||||
$teams = config('permission.teams'); |
||||
|
||||
if (empty($tableNames)) { |
||||
throw new \Exception('Error: config/permission.php not loaded. Run [php artisan config:clear] and try again.'); |
||||
} |
||||
if ($teams && empty($columnNames['team_foreign_key'] ?? null)) { |
||||
throw new \Exception('Error: team_foreign_key on config/permission.php not loaded. Run [php artisan config:clear] and try again.'); |
||||
} |
||||
|
||||
Schema::create($tableNames['permissions'], function (Blueprint $table) { |
||||
$table->bigIncrements('id'); // permission id |
||||
$table->string('display_name')->nullable(); |
||||
$table->string('type')->nullable(); |
||||
$table->integer('sort')->nullable()->default(0); |
||||
$table->string('name')->nullable(); // For MySQL 8.0 use string('name', 125); |
||||
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125); |
||||
$table->timestamps(); |
||||
|
||||
$table->unique(['name', 'guard_name']); |
||||
}); |
||||
|
||||
Schema::create($tableNames['roles'], function (Blueprint $table) use ($teams, $columnNames) { |
||||
$table->bigIncrements('id'); // role id |
||||
if ($teams || config('permission.testing')) { // permission.testing is a fix for sqlite testing |
||||
$table->unsignedBigInteger($columnNames['team_foreign_key'])->nullable(); |
||||
$table->index($columnNames['team_foreign_key'], 'roles_team_foreign_key_index'); |
||||
} |
||||
$table->string('display_name')->nullable(); |
||||
$table->string('name')->nullable(); // For MySQL 8.0 use string('name', 125); |
||||
$table->string('guard_name'); // For MySQL 8.0 use string('guard_name', 125); |
||||
$table->timestamps(); |
||||
if ($teams || config('permission.testing')) { |
||||
$table->unique([$columnNames['team_foreign_key'], 'name', 'guard_name']); |
||||
} else { |
||||
$table->unique(['name', 'guard_name']); |
||||
} |
||||
}); |
||||
|
||||
Schema::create($tableNames['model_has_permissions'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) { |
||||
$table->unsignedBigInteger(PermissionRegistrar::$pivotPermission); |
||||
|
||||
$table->string('model_type'); |
||||
$table->unsignedBigInteger($columnNames['model_morph_key']); |
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_permissions_model_id_model_type_index'); |
||||
|
||||
$table->foreign(PermissionRegistrar::$pivotPermission) |
||||
->references('id') // permission id |
||||
->on($tableNames['permissions']) |
||||
->onDelete('cascade'); |
||||
if ($teams) { |
||||
$table->unsignedBigInteger($columnNames['team_foreign_key']); |
||||
$table->index($columnNames['team_foreign_key'], 'model_has_permissions_team_foreign_key_index'); |
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], PermissionRegistrar::$pivotPermission, $columnNames['model_morph_key'], 'model_type'], |
||||
'model_has_permissions_permission_model_type_primary'); |
||||
} else { |
||||
$table->primary([PermissionRegistrar::$pivotPermission, $columnNames['model_morph_key'], 'model_type'], |
||||
'model_has_permissions_permission_model_type_primary'); |
||||
} |
||||
|
||||
}); |
||||
|
||||
Schema::create($tableNames['model_has_roles'], function (Blueprint $table) use ($tableNames, $columnNames, $teams) { |
||||
$table->unsignedBigInteger(PermissionRegistrar::$pivotRole); |
||||
|
||||
$table->string('model_type'); |
||||
$table->unsignedBigInteger($columnNames['model_morph_key']); |
||||
$table->index([$columnNames['model_morph_key'], 'model_type'], 'model_has_roles_model_id_model_type_index'); |
||||
|
||||
$table->foreign(PermissionRegistrar::$pivotRole) |
||||
->references('id') // role id |
||||
->on($tableNames['roles']) |
||||
->onDelete('cascade'); |
||||
if ($teams) { |
||||
$table->unsignedBigInteger($columnNames['team_foreign_key']); |
||||
$table->index($columnNames['team_foreign_key'], 'model_has_roles_team_foreign_key_index'); |
||||
|
||||
$table->primary([$columnNames['team_foreign_key'], PermissionRegistrar::$pivotRole, $columnNames['model_morph_key'], 'model_type'], |
||||
'model_has_roles_role_model_type_primary'); |
||||
} else { |
||||
$table->primary([PermissionRegistrar::$pivotRole, $columnNames['model_morph_key'], 'model_type'], |
||||
'model_has_roles_role_model_type_primary'); |
||||
} |
||||
}); |
||||
|
||||
Schema::create($tableNames['role_has_permissions'], function (Blueprint $table) use ($tableNames) { |
||||
$table->unsignedBigInteger(PermissionRegistrar::$pivotPermission); |
||||
$table->unsignedBigInteger(PermissionRegistrar::$pivotRole); |
||||
|
||||
$table->foreign(PermissionRegistrar::$pivotPermission) |
||||
->references('id') // permission id |
||||
->on($tableNames['permissions']) |
||||
->onDelete('cascade'); |
||||
|
||||
$table->foreign(PermissionRegistrar::$pivotRole) |
||||
->references('id') // role id |
||||
->on($tableNames['roles']) |
||||
->onDelete('cascade'); |
||||
|
||||
$table->primary([PermissionRegistrar::$pivotPermission, PermissionRegistrar::$pivotRole], 'role_has_permissions_permission_id_role_id_primary'); |
||||
}); |
||||
|
||||
app('cache') |
||||
->store(config('permission.cache.store') != 'default' ? config('permission.cache.store') : null) |
||||
->forget(config('permission.cache.key')); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
* |
||||
* @return void |
||||
*/ |
||||
public function down() |
||||
{ |
||||
$tableNames = config('permission.table_names'); |
||||
|
||||
if (empty($tableNames)) { |
||||
throw new \Exception('Error: config/permission.php not found and defaults could not be merged. Please publish the package configuration before proceeding, or drop the tables manually.'); |
||||
} |
||||
|
||||
Schema::drop($tableNames['role_has_permissions']); |
||||
Schema::drop($tableNames['model_has_roles']); |
||||
Schema::drop($tableNames['model_has_permissions']); |
||||
Schema::drop($tableNames['roles']); |
||||
Schema::drop($tableNames['permissions']); |
||||
} |
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up() |
||||
{ |
||||
Schema::table('users', function (Blueprint $table) { |
||||
$table->string('api_token', 80)->after('password') |
||||
->unique() |
||||
->nullable() |
||||
->default(null); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::table('users', function (Blueprint $table) { |
||||
// |
||||
}); |
||||
} |
||||
}; |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::table('users', function (Blueprint $table) { |
||||
$table->string('account', 80)->after('id') |
||||
->unique() |
||||
->nullable() |
||||
->comment('帳號'); |
||||
$table->integer('status')->after('account') |
||||
->nullable() |
||||
->default(0) |
||||
->comment('狀態: 0 啟用/ 1 停用'); |
||||
$table->string('class', 255)->after('status') |
||||
->nullable() |
||||
->comment('職級'); |
||||
$table->string('leader', 255)->after('class') |
||||
->nullable() |
||||
->comment('單位代碼'); |
||||
$table->string('exp_op', 255)->after('leader') |
||||
->nullable() |
||||
->comment('員警代碼'); |
||||
$table->string('unit', 255)->after('exp_op') |
||||
->nullable() |
||||
->comment('單位: 第一中隊、第三中隊、交通隊 ...'); |
||||
$table->string('device', 255)->after('unit') |
||||
->nullable() |
||||
->comment('限制設備設定'); |
||||
$table->timestamp('deleted_at')->after('updated_at') |
||||
->nullable() |
||||
->comment('刪除時間'); |
||||
|
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
// |
||||
} |
||||
}; |
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::create('user_log', function (Blueprint $table) { |
||||
$table->id(); |
||||
$table->string('user_id', 80)->nullable()->comment('使用者ID'); |
||||
$table->string('user_name', 80)->nullable()->comment('使用者名稱'); |
||||
$table->string('action', 80)->nullable()->comment('動作'); |
||||
$table->string('action_detail', 80)->nullable()->comment('動作細節'); |
||||
$table->string('ip', 80)->nullable()->comment('IP'); |
||||
$table->string('mac', 80)->nullable()->comment('MAC'); |
||||
$table->longText('remark')->nullable()->comment('備註'); |
||||
$table->timestamps(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::dropIfExists('user_log'); |
||||
} |
||||
}; |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::table('users', function (Blueprint $table) { |
||||
$table->date('renew_password_at')->after('device') |
||||
->nullable() |
||||
->default(null) |
||||
->comment('上次修改密碼時間'); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::table('users', function (Blueprint $table) { |
||||
// |
||||
}); |
||||
} |
||||
}; |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::create('sessions', function (Blueprint $table) { |
||||
$table->string('id')->primary(); |
||||
$table->foreignId('user_id')->nullable()->index(); |
||||
$table->string('ip_address', 45)->nullable(); |
||||
$table->text('user_agent')->nullable(); |
||||
$table->longText('payload'); |
||||
$table->integer('last_activity')->index(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::dropIfExists('sessions'); |
||||
} |
||||
}; |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::create('violation_law', function (Blueprint $table) { |
||||
$table->id(); |
||||
$table->string('violationcode')->nullable()->comment('違規法條代碼'); |
||||
$table->string('display_name')->nullable()->comment('違規法條說明'); |
||||
$table->string('type')->nullable()->comment('違規法條系統分類'); |
||||
$table->integer('sort')->nullable()->default(0)->comment('排序'); |
||||
$table->unique(['violationcode', 'display_name']); |
||||
$table->index('violationcode'); |
||||
$table->timestamps(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::dropIfExists('violation_law'); |
||||
} |
||||
}; |
@ -0,0 +1,44 @@
@@ -0,0 +1,44 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::create('violationparking', function (Blueprint $table) { |
||||
$table->id(); |
||||
$table->string('picture', 255)->nullable()->comment('違規停車照片A'); |
||||
$table->string('picture2', 255)->nullable()->comment('違規停車照片B'); |
||||
$table->dateTime('datatime')->nullable()->comment('違規停車時間'); |
||||
$table->string('cartype', 255)->nullable()->comment('車種'); |
||||
$table->string('carnumber', 255)->nullable()->comment('違規停車車牌'); |
||||
$table->string('serialnumber', 255)->nullable()->comment('設備編號'); |
||||
$table->string('location', 255)->nullable()->comment('設備位置'); |
||||
$table->string('violationtype', 255)->nullable()->comment('違規類型'); |
||||
$table->string('violationcode', 255)->nullable()->comment('違規法條代碼'); |
||||
$table->integer('processcheck')->nullable()->default(0)->comment('審查狀態 0:未審查 1:已審查 2:不舉發'); |
||||
$table->integer('postcheck')->nullable()->default(0)->comment('入案狀態 0:未入案 1:已入案'); |
||||
$table->string('jsoncheck', 255)->nullable()->comment('審查人'); |
||||
$table->string('unreportreason', 255)->nullable()->comment('不舉發原因'); |
||||
$table->string('unreportpicture', 255)->nullable()->comment('不舉發照片路徑'); |
||||
$table->integer('unreportmergedone')->nullable()->default(0)->comment('不舉發照片合成狀態 0:未合併 1:已合併'); |
||||
$table->unique(['carnumber', 'datatime']); |
||||
|
||||
$table->timestamps(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::dropIfExists('violationparking'); |
||||
} |
||||
}; |
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
<?php |
||||
|
||||
use Illuminate\Database\Migrations\Migration; |
||||
use Illuminate\Database\Schema\Blueprint; |
||||
use Illuminate\Support\Facades\Schema; |
||||
|
||||
return new class extends Migration |
||||
{ |
||||
/** |
||||
* Run the migrations. |
||||
*/ |
||||
public function up(): void |
||||
{ |
||||
Schema::create('violationparking_equipment', function (Blueprint $table) { |
||||
$table->id(); |
||||
$table->string('serialnumber', 255)->nullable()->comment('機號'); |
||||
$table->string('brand', 255)->nullable()->comment('廠牌'); |
||||
$table->string('model', 255)->nullable()->comment('型號'); |
||||
// |
||||
$table->unsignedBigInteger('custodyunit_id')->nullable()->comment('保管單位(關聯)'); |
||||
$table->unsignedBigInteger('assetownership_id')->nullable()->comment('財產所屬單位(關聯)'); |
||||
$table->date('buydate')->nullable()->comment('購買日期'); |
||||
$table->date('activatedate')->nullable()->comment('啟用日期'); |
||||
$table->string('locationid', 255)->nullable()->comment('設備位置編號'); |
||||
$table->string('location', 255)->nullable()->comment('設備位置'); |
||||
// |
||||
$table->longText('comment')->nullable()->comment('備註'); |
||||
$table->dateTime('deleted_at')->nullable()->comment('是否刪除'); |
||||
$table->unique(['serialnumber']); |
||||
$table->timestamps(); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* Reverse the migrations. |
||||
*/ |
||||
public function down(): void |
||||
{ |
||||
Schema::dropIfExists('violationparking_equipment'); |
||||
} |
||||
}; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue