295 changed files with 63947 additions and 298 deletions
@ -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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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,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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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 @@ |
|||||||
|
<?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'); |
||||||
|
} |
||||||
|
}; |
@ -0,0 +1,28 @@ |
|||||||
|
<?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('asset_ownership', function (Blueprint $table) { |
||||||
|
$table->id(); |
||||||
|
$table->string('name')->comment('財產所屬單位名稱'); |
||||||
|
// $table->timestamps(); |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reverse the migrations. |
||||||
|
*/ |
||||||
|
public function down(): void |
||||||
|
{ |
||||||
|
Schema::dropIfExists('asset_ownership'); |
||||||
|
} |
||||||
|
}; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue