You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
634 lines
26 KiB
634 lines
26 KiB
@extends('system.layouts.app') |
|
|
|
@section('title', '計時系統') |
|
@section('name', 'timelog') |
|
|
|
@section('css') |
|
@parent |
|
<link rel="stylesheet" href="{{ asset('css/v2/datatables.min.css') }}"> |
|
<link rel="stylesheet" href="{{ asset('css/bootstrap-select.min.css') }}"> |
|
|
|
<style> |
|
.searchTable { |
|
text-align: right; |
|
} |
|
|
|
.table>tbody>tr>td { |
|
vertical-align: middle; |
|
text-align: -moz-center; |
|
} |
|
|
|
.btn.disabled, |
|
.btn:disabled { |
|
cursor: not-allowed; |
|
} |
|
|
|
.selectpicker { |
|
background-color: #212529; |
|
color: #dee2e6; |
|
} |
|
|
|
.table { |
|
--bs-table-bg: none; |
|
} |
|
|
|
.table-striped tbody tr:nth-of-type(odd) { |
|
background-color: rgba(255, 255, 255, .05); |
|
} |
|
</style> |
|
@stop |
|
|
|
@section('content') |
|
<div class="container-fluid mt-2" style="min-height:calc(100vh-60px) !important"> |
|
<div class="w-100 text-center"> |
|
<h2 class="title">計時系統 </h2> |
|
</div> |
|
<div> |
|
<!-- Date Filter --> |
|
<div class="d-flex justify-content-start"> |
|
<div> |
|
<h2>最新資料</h2> |
|
</div> |
|
<!-- 強制校時按鈕 --> |
|
<div class="ms-3"> |
|
<button type="button" class="btn btn-sm btn-danger" id="forceTime">強制校時</button> |
|
</div> |
|
|
|
</div> |
|
<div class="row justify-content-center"> |
|
<div class="col-12"> |
|
<table id="nowTable" class="table table-striped table-bordered" style="width:100%"> |
|
<thead> |
|
</thead> |
|
<tbody> |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="mt-3"> |
|
<!-- Date Filter --> |
|
<div class="row justify-content-start"> |
|
<div class="col-10"> |
|
<h2>伺服器端</h2> |
|
</div> |
|
</div> |
|
<div class="row justify-content-center"> |
|
<div class="col-12"> |
|
<table id="serverlog" class="table table-striped table-bordered" style="width:100%"> |
|
<thead> |
|
</thead> |
|
<tbody> |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
</div> |
|
<div class="mt-3"> |
|
<!-- Date Filter --> |
|
<div class="row justify-content-start"> |
|
<div class="col-10"> |
|
<h2>設備端</h2> |
|
</div> |
|
</div> |
|
<div class="row justify-content-center"> |
|
<div class="col-12"> |
|
<table id="clientlog" class="table table-striped table-bordered" style="width:100%"> |
|
<thead> |
|
</thead> |
|
<tbody> |
|
</tbody> |
|
</table> |
|
</div> |
|
</div> |
|
</div> |
|
|
|
</div> |
|
|
|
@endsection |
|
|
|
|
|
@section('js') |
|
@parent |
|
<script src="{{ asset('js/v2/datatables.min.js') }}"></script> |
|
<!-- Latest compiled and minified JavaScript --> |
|
{{-- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap-select.min.js"></script> --}} |
|
<script src="{{ asset('js/bootstrap-select.min.js') }}"></script> |
|
<script> |
|
|
|
// 強制校時按鈕 post api |
|
$('#forceTime').on('click', function() { |
|
Swal.fire({ |
|
title: '強制校時', |
|
text: '確定要強制校時嗎?', |
|
icon: 'warning', |
|
showCancelButton: true, |
|
confirmButtonColor: '#d33', |
|
cancelButtonColor: '#3085d6', |
|
confirmButtonText: '確定', |
|
cancelButtonText: '取消' |
|
}).then((result) => { |
|
if (result.isConfirmed) { |
|
$.post("{{ route('api.itl.forceTime') }}", { |
|
type: 'client' |
|
}, function(response) { |
|
if (response.message == 'success') { |
|
Swal.fire({ |
|
title: '強制校時成功', |
|
text: '請稍後重新整理', |
|
icon: 'success', |
|
showConfirmButton: false, |
|
timer: 1500 |
|
}); |
|
} else { |
|
Swal.fire({ |
|
title: '強制校時失敗', |
|
text: '請稍後再試', |
|
icon: 'error', |
|
showConfirmButton: false, |
|
timer: 1500 |
|
}); |
|
} |
|
}); |
|
} |
|
}); |
|
}); |
|
|
|
// DataTable 初始化 |
|
$(document).ready(function() { |
|
$.fn.dataTableExt.sErrMode = 'throw'; |
|
// input 加入時間選擇 |
|
$('input#search_fromdate').datetimepicker({ |
|
format: 'YYYY-MM-DD' |
|
}); |
|
$('input#search_todate').datetimepicker({ |
|
format: 'YYYY-MM-DD' |
|
}); |
|
|
|
|
|
nowTable = $('#nowTable').DataTable({ |
|
"dom": `<'row'<'col-sm-12't>>`, |
|
// 語系設定 UI介面中文化 |
|
"language": { |
|
"processing": "處理中...", |
|
"loadingRecords": "載入中...", |
|
"lengthMenu": "顯示 _MENU_ 項結果", |
|
"zeroRecords": "沒有符合的結果", |
|
"info": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項", |
|
"infoEmpty": "顯示第 0 至 0 項結果,共 0 項", |
|
"infoFiltered": "(從 _MAX_ 項結果中過濾)", |
|
"infoPostFix": "", |
|
"search": "搜尋:", |
|
"paginate": { |
|
"first": "第一頁", |
|
"previous": "上一頁", |
|
"next": "下一頁", |
|
"last": "最後一頁" |
|
}, |
|
"aria": { |
|
"sortAscending": ": 升冪排列", |
|
"sortDescending": ": 降冪排列" |
|
} |
|
}, |
|
// 搜尋欄位 是否顯示 |
|
searching: false, |
|
// searching: true, |
|
// 處理中 是否顯示 |
|
processing: false, |
|
// |
|
serverSide: true, |
|
// Ajax 取資料 |
|
ajax: { |
|
//processcheckStatus =0 未審 |
|
'url': "{{ route('api.itl.getNow') }}", |
|
'data': function(data) { |
|
data.type = 'clientsecond'; |
|
}, |
|
'error': function() { |
|
// violationparkingTable.draw(); |
|
}, |
|
}, |
|
// 設定不提供排序條件的欄位(例如圖片) |
|
columnDefs: [{ |
|
orderable: false, |
|
targets: [0, 1, 2, 3, 4, 5, 6] |
|
}, { |
|
visible: false, |
|
targets: [] |
|
}, |
|
{ |
|
className: "dt-center", |
|
targets: [0, 1, 2, 3, 4, 5, 6] |
|
} |
|
], |
|
order: [ |
|
|
|
], |
|
// 設定 顯示在Table上的欄位 |
|
columns: [ |
|
// 格式 data: 後端傳遞過來的 欄位名稱 |
|
{ |
|
data: 'to_time', |
|
title: '校時對象時間' |
|
}, |
|
{ |
|
data: 'to_ip', |
|
title: '校時對象IP' |
|
}, |
|
{ |
|
data: 'before_time', |
|
title: '本機校時前' |
|
}, |
|
{ |
|
data: 'this_time', |
|
title: '本機校時後' |
|
}, |
|
{ |
|
data: 'diffsecond', |
|
title: '時間誤差(ms)' |
|
}, |
|
{ |
|
data: 'this_ip', |
|
title: '本機IP' |
|
}, |
|
{ |
|
data: 'name', |
|
title: '本機名稱' |
|
} |
|
|
|
], |
|
initComplete: function() { |
|
$('.selectpicker').selectpicker(); |
|
|
|
}, |
|
drawCallback: function(settings) { |
|
$('.selectpicker').selectpicker(); |
|
let api = this.api(); |
|
api.rows().every(function(rowIdx, tableLoop, rowLoop) { |
|
let data = this.data(); |
|
if (data.force_time == 1) { // 获取隐藏列的数据 |
|
$(this.node()).find('td').css('color', 'yellow'); |
|
} |
|
if (Math.abs(data.diffsecond) > 200) { |
|
$(this.node()).find('td').css('color', 'red'); |
|
} |
|
if (data.timeout == 1) { |
|
$(this.node()).find('td').css('color', 'red'); |
|
} |
|
|
|
}); |
|
} |
|
// stripeClasses:['striped-odd','striped-even'] |
|
}); |
|
|
|
serverlog = $('#serverlog').DataTable({ |
|
"dom": `<'row'<'d-flex justify-content-between mt-2 mb-2' lf<'serverSearch'>>> |
|
<'row'<'col-sm-12'tr>> |
|
<'row'<'col-sm-12 col-md-12'<'d-flex justify-content-between' ip>>>`, |
|
"lengthMenu": [ |
|
[5, 10, 25, 50, 100], |
|
[5, 10, 25, 50, 100] |
|
], // 設定顯示選項 |
|
// 語系設定 UI介面中文化 |
|
"language": { |
|
"processing": "處理中...", |
|
"loadingRecords": "載入中...", |
|
"lengthMenu": "顯示 _MENU_ 項結果", |
|
"zeroRecords": "沒有符合的結果", |
|
"info": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項", |
|
"infoEmpty": "顯示第 0 至 0 項結果,共 0 項", |
|
"infoFiltered": "(從 _MAX_ 項結果中過濾)", |
|
"infoPostFix": "", |
|
"search": "搜尋:", |
|
"paginate": { |
|
"first": "第一頁", |
|
"previous": "上一頁", |
|
"next": "下一頁", |
|
"last": "最後一頁" |
|
}, |
|
"aria": { |
|
"sortAscending": ": 升冪排列", |
|
"sortDescending": ": 降冪排列" |
|
} |
|
}, |
|
// 搜尋欄位 是否顯示 |
|
searching: false, |
|
// searching: true, |
|
// 處理中 是否顯示 |
|
processing: false, |
|
// |
|
serverSide: true, |
|
// Ajax 取資料 |
|
ajax: { |
|
//processcheckStatus =0 未審 |
|
'url': "{{ route('api.itl.getHistory') }}", |
|
'data': function(data) { |
|
data.type = 'server'; |
|
data.searchByFromdate = $('#serverlog_fromdate').val(); |
|
data.searchByTodate = $('#serverlog_todate').val(); |
|
}, |
|
'error': function() { |
|
// violationparkingTable.draw(); |
|
}, |
|
}, |
|
// 設定不提供排序條件的欄位(例如圖片) |
|
columnDefs: [{ |
|
orderable: false, |
|
targets: [0, 1, 2, 3, 4, 5, 6] |
|
}, { |
|
visible: false, |
|
targets: [] |
|
}, |
|
{ |
|
className: "dt-center", |
|
targets: [0, 1, 2, 3, 4, 5, 6] |
|
} |
|
], |
|
order: [ |
|
[3, 'desc'] |
|
], |
|
// 設定 顯示在Table上的欄位 |
|
columns: [ |
|
// 格式 data: 後端傳遞過來的 欄位名稱 |
|
{ |
|
data: 'to_time', |
|
title: '校時對象時間' |
|
}, |
|
{ |
|
data: 'to_ip', |
|
title: '校時對象IP' |
|
}, |
|
{ |
|
data: 'before_time', |
|
title: '本機校時前' |
|
}, |
|
{ |
|
data: 'this_time', |
|
title: '本機校時後' |
|
}, |
|
{ |
|
data: 'diffsecond', |
|
title: '時間誤差(ms)' |
|
}, |
|
{ |
|
data: 'this_ip', |
|
title: '本機IP' |
|
}, |
|
{ |
|
data: 'name', |
|
title: '本機名稱' |
|
} |
|
|
|
], |
|
initComplete: function() { |
|
$('.selectpicker').selectpicker(); |
|
// 初始化 serverSearch 該div中包含 一個input日期起 一個input日期訖 一個搜尋按鈕 一個匯出報表按鈕 根據bootstrap5 排版 |
|
$('.serverSearch').html(` |
|
<div class="input-group"> |
|
<input type="text" class="form-control" id="serverlog_fromdate" placeholder="日期起" aria-label="日期起" aria-describedby="button-addon2"> |
|
<input type="text" class="form-control" id="serverlog_todate" placeholder="日期訖" aria-label="日期訖" aria-describedby="button-addon2"> |
|
<button class="btn btn-primary" type="button" id="serverlog-search">搜尋</button> |
|
<button class="btn btn-success" type="button" id="serverlog-export">匯出報表</button> |
|
</div> |
|
`); |
|
$('input#serverlog_fromdate').datetimepicker({ |
|
format: 'YYYY-MM-DD' |
|
}); |
|
$('input#serverlog_todate').datetimepicker({ |
|
format: 'YYYY-MM-DD' |
|
}); |
|
// 按下搜尋 帶入日期條件 |
|
$('#serverlog-search').on('click', function() { |
|
serverlog.draw(); |
|
}); |
|
// 按下匯出報表 |
|
$('#serverlog-export').on('click', function() { |
|
let fromdate = $('#serverlog_fromdate').val(); |
|
let todate = $('#serverlog_todate').val(); |
|
let url = "{{ route('api.itl.getHistory') }}"; |
|
let data = { |
|
type: 'server', |
|
searchByFromdate: fromdate, |
|
searchByTodate: todate, |
|
export: 1 |
|
}; |
|
// form 回傳的 response.url 是下載連結 請直接下載 |
|
$.get(url, data, function(response) { |
|
// Swal 提示 下載中請稍後 |
|
Swal.fire({ |
|
title: '下載中', |
|
text: '請稍後', |
|
icon: 'info', |
|
showConfirmButton: false, |
|
timer: 2500 |
|
}); |
|
if (response.url) { |
|
window.location.href = response.url; |
|
} |
|
}); |
|
}); |
|
|
|
}, |
|
drawCallback: function(settings) { |
|
$('.selectpicker').selectpicker(); |
|
// 如果 diffsecond > |200| 時 顯示紅色 |
|
let api = this.api(); |
|
api.rows().every(function(rowIdx, tableLoop, rowLoop) { |
|
let data = this.data(); |
|
if (data.force_time == 1) { // 获取隐藏列的数据 |
|
$(this.node()).find('td').css('color', 'yellow'); |
|
} |
|
if (Math.abs(data.diffsecond) > 200) { |
|
$(this.node()).find('td').css('color', 'red'); |
|
} |
|
|
|
}); |
|
} |
|
// stripeClasses:['striped-odd','striped-even'] |
|
}); |
|
|
|
clientlog = $('#clientlog').DataTable({ |
|
"dom": `<'row'<'d-flex justify-content-between mt-2 mb-2' lf<'clientSearch'>>> |
|
<'row'<'col-sm-12'tr>> |
|
<'row'<'col-sm-12 col-md-12'<'d-flex justify-content-between' ip>>>`, |
|
"lengthMenu": [ |
|
[5, 10, 25, 50, 100], |
|
[5, 10, 25, 50, 100] |
|
], // 設定顯示選項 |
|
// 語系設定 UI介面中文化 |
|
"language": { |
|
"processing": "處理中...", |
|
"loadingRecords": "載入中...", |
|
"lengthMenu": "顯示 _MENU_ 項結果", |
|
"zeroRecords": "沒有符合的結果", |
|
"info": "顯示第 _START_ 至 _END_ 項結果,共 _TOTAL_ 項", |
|
"infoEmpty": "顯示第 0 至 0 項結果,共 0 項", |
|
"infoFiltered": "(從 _MAX_ 項結果中過濾)", |
|
"infoPostFix": "", |
|
"search": "搜尋:", |
|
"paginate": { |
|
"first": "第一頁", |
|
"previous": "上一頁", |
|
"next": "下一頁", |
|
"last": "最後一頁" |
|
}, |
|
"aria": { |
|
"sortAscending": ": 升冪排列", |
|
"sortDescending": ": 降冪排列" |
|
} |
|
}, |
|
// 搜尋欄位 是否顯示 |
|
searching: false, |
|
// searching: true, |
|
// 處理中 是否顯示 |
|
processing: false, |
|
// |
|
serverSide: true, |
|
// Ajax 取資料 |
|
ajax: { |
|
//processcheckStatus =0 未審 |
|
'url': "{{ route('api.itl.getHistory') }}", |
|
'data': function(data) { |
|
data.type = 'clientsecond'; |
|
data.searchByFromdate = $('#clientlog_fromdate').val(); |
|
data.searchByTodate = $('#clientlog_todate').val(); |
|
data.name = $('#clientlog_serialnumber').val(); |
|
}, |
|
'error': function() { |
|
// violationparkingTable.draw(); |
|
}, |
|
}, |
|
// 設定不提供排序條件的欄位(例如圖片) |
|
columnDefs: [{ |
|
orderable: false, |
|
targets: [0, 1, 2, 3, 4, 5, 6] |
|
}, { |
|
visible: false, |
|
targets: [] |
|
}, |
|
{ |
|
className: "dt-center", |
|
targets: [0, 1, 2, 3, 4, 5, 6] |
|
} |
|
], |
|
order: [ |
|
[3, 'desc'] |
|
], |
|
// 設定 顯示在Table上的欄位 |
|
columns: [ |
|
// 格式 data: 後端傳遞過來的 欄位名稱 |
|
{ |
|
data: 'to_time', |
|
title: '校時對象時間' |
|
}, |
|
{ |
|
data: 'to_ip', |
|
title: '校時對象IP' |
|
}, |
|
{ |
|
data: 'before_time', |
|
title: '本機校時前' |
|
}, |
|
{ |
|
data: 'this_time', |
|
title: '本機校時後' |
|
}, |
|
{ |
|
data: 'diffsecond', |
|
title: '時間誤差(ms)' |
|
}, |
|
{ |
|
data: 'this_ip', |
|
title: '本機IP' |
|
}, |
|
{ |
|
data: 'name', |
|
title: '本機名稱' |
|
}, |
|
{ |
|
data: 'force_time', |
|
title: '強制校時', |
|
visible: false |
|
} |
|
|
|
], |
|
initComplete: function() { |
|
$('.clientSearch').html(` |
|
<div class="input-group"> |
|
<select class="selectpicker form-control" id="clientlog_serialnumber" data-style="btn-dark border" data-live-search="true" title="請選擇設備" data-width="auto"> |
|
@if (isset($equipment)) |
|
@foreach ($equipment as $item) |
|
<option value="{{ $item->name }}">{{ $item->name }}</option> |
|
@endforeach |
|
@endif |
|
</select> |
|
<input type="text" class="form-control" id="clientlog_fromdate" placeholder="日期起" aria-label="日期起" aria-describedby="button-addon2"> |
|
<input type="text" class="form-control" id="clientlog_todate" placeholder="日期訖" aria-label="日期訖" aria-describedby="button-addon2"> |
|
<button class="btn btn-primary" type="button" id="clientlog-search">搜尋</button> |
|
<button class="btn btn-success" type="button" id="clientlog-export">匯出報表</button> |
|
</div> |
|
`); |
|
$('.selectpicker').selectpicker(); |
|
$('input#clientlog_fromdate').datetimepicker({ |
|
format: 'YYYY-MM-DD' |
|
}); |
|
$('input#clientlog_todate').datetimepicker({ |
|
format: 'YYYY-MM-DD' |
|
}); |
|
// 按下搜尋 帶入日期條件 |
|
$('#clientlog-search').on('click', function() { |
|
clientlog.draw(); |
|
}); |
|
// 按下匯出報表 |
|
$('#clientlog-export').on('click', function() { |
|
let fromdate = $('#clientlog_fromdate').val(); |
|
let todate = $('#clientlog_todate').val(); |
|
let url = "{{ route('api.itl.getHistory') }}"; |
|
let data = { |
|
type: 'clientsecond', |
|
searchByFromdate: fromdate, |
|
searchByTodate: todate, |
|
export: 1, |
|
name: $('#clientlog_serialnumber').val() |
|
}; |
|
// form 回傳的 response.url 是下載連結 請直接下載 |
|
$.get(url, data, function(response) { |
|
// Swal 提示 下載中請稍後 |
|
Swal.fire({ |
|
title: '下載中', |
|
text: '請稍後', |
|
icon: 'info', |
|
showConfirmButton: false, |
|
timer: 2500 |
|
}); |
|
if (response.url) { |
|
window.location.href = response.url; |
|
} |
|
}); |
|
}); |
|
}, |
|
drawCallback: function(settings) { |
|
$('.selectpicker').selectpicker(); |
|
// 如果 response aaData 的 force_time = 1 時 顯示黃色,表示強制校時 |
|
let api = this.api(); |
|
api.rows().every(function(rowIdx, tableLoop, rowLoop) { |
|
let data = this.data(); |
|
if (data.force_time == 1) { // 获取隐藏列的数据 |
|
$(this.node()).find('td').css('color', 'yellow'); |
|
} |
|
if (Math.abs(data.diffsecond) > 200) { |
|
$(this.node()).find('td').css('color', 'red'); |
|
} |
|
|
|
}); |
|
} |
|
// stripeClasses:['striped-odd','striped-even'] |
|
}); |
|
}); |
|
setInterval(function() { |
|
nowTable.ajax.reload(null, false); |
|
serverlog.ajax.reload(null, false); |
|
clientlog.ajax.reload(null, false); |
|
}, 5000); // 5000毫秒 = 5秒 |
|
</script> |
|
@stop
|
|
|