Files
ProxyPanel/resources/views/user/nodeList.blade.php
兔姬桑 b4189cc0e5 优化 中转节点显示 & 失效内容 & 查询效率
1. 优化中转节点显示;
2. 优化节点显示规则;
3. 修复国旗图标失效的问题;
4. 优化节点页面显示的效率问题;
5. 优化页面加载队列;
2022-08-09 19:46:33 +08:00

209 lines
11 KiB
PHP

@extends('user.layouts')
@section('css')
<link href="/assets/global/fonts/font-awesome/css/all.min.css" rel="stylesheet">
<link href="/assets/global/vendor/webui-popover/webui-popover.min.css" type="text/css" rel="stylesheet">
<link href="/assets/global/vendor/jvectormap/jquery-jvectormap.min.css" type="text/css" rel="stylesheet">
@endsection
@section('content')
<!-- BEGIN CONTENT BODY -->
<div class="page-content container-fluid">
<div class="row">
<div class="col-md-9">
<div class="card card-inverse card-shadow bg-white map">
<div class="card-block h-450">
<div class="h-p100" id="world-map"></div>
</div>
</div>
</div>
<div class="col-md-3">
<div class="row map">
<div class="col-md-12">
<div class="card card-block p-20 bg-indigo-500">
<div class="counter counter-lg counter-inverse">
<div class="counter-label text-uppercase font-size-16">{{trans('user.account.level')}}</div>
<div class="counter-number-group">
<span class="counter-icon"><i class="icon wb-user-circle" aria-hidden="true"></i></span>
<span class="counter-number ml-10">{{Auth::getUser()->level}}</span>
</div>
<div class="counter-label text-uppercase font-size-16">{{Auth::getUser()->level_name}}</div>
</div>
</div>
</div>
@if(Auth::getUser()->user_group_id)
<div class="col-md-12">
<div class="card card-block p-20 bg-indigo-500">
<div class="counter counter-lg counter-inverse">
<div class="counter-label text-uppercase font-size-16">{{trans('user.account.group')}}</div>
<div class="counter-number-group">
<span class="counter-icon"><i class="icon wb-globe" aria-hidden="true"></i></span>
<span class="counter-number ml-10">{{Auth::getUser()->userGroup->name}}</span>
</div>
</div>
</div>
</div>
@endif
<div class="col-md-12">
<div class="card card-block p-20 bg-indigo-500">
<div class="counter counter-lg counter-inverse">
<div class="counter-label text-uppercase font-size-16">{{trans('user.account.speed_limit')}}</div>
<div class="counter-number-group">
<span class="counter-icon"><i class="icon wb-signal" aria-hidden="true"></i></span>
<span class="counter-number ml-10">{{Auth::getUser()->speed_limit ?? trans('common.unlimited')}}</span>
</div>
<div class="counter-label font-size-16">Mbps</div>
</div>
</div>
</div>
</div>
</div>
@foreach($nodeList as $node)
<div class="col-xxl-3 col-xl-4 col-sm-6">
<div class="card card-inverse card-shadow bg-white node">
<div class="card-block p-30 row">
<div class="col-4">
<i class="fi fis fi-{{$node->country_code}} h-p100 w-p100" style="border-radius: 25px" aria-hidden="true"></i>
</div>
<div class="col-8 text-break text-right">
<p class="font-size-20 blue-600">
<span class="float-left badge badge-round badge-default">{{$node->level_table->name}}</span>
@if($node->offline && !$node->relay_node_id)
<i class="red-600 icon wb-warning" data-content="{{trans('user.node.unstable')}}"
data-trigger="hover" data-toggle="popover" data-placement="top"></i>
@endif
@if($node->traffic_rate !== 1.0)
<i class="green-600 icon wb-info-circle" data-content="{{trans('user.node.rate', ['ratio' => $node->traffic_rate])}}"
data-trigger="hover" data-toggle="popover" data-placement="top"></i>
@endif
{{$node->name}}
</p>
<blockquote>
@foreach($node->labels as $label)
<span class="badge badge-round badge-info">{{$label->name}}</span>
@endforeach
<br>
{{$node->description}}
</blockquote>
<p class="font-size-14">
<button class="btn btn-sm btn-outline-info" onclick="getInfo('{{$node->id}}','code')">
<i id="code{{$node->id}}" class="fa-solid fa-code"></i>
</button>
<button class="btn btn-sm btn-outline-info" onclick="getInfo('{{$node->id}}','qrcode')">
<i id="qrcode{{$node->id}}" class="fa-solid fa-qrcode"></i>
</button>
<button class="btn btn-sm btn-outline-info" onclick="getInfo('{{$node->id}}','text')">
<i id="text{{$node->id}}" class="fa-solid fa-list"></i>
</button>
</p>
</div>
</div>
</div>
</div>
@endforeach
</div>
</div>
@endsection
@section('javascript')
<script src="/assets/global/vendor/matchheight/jquery.matchHeight-min.js" type="text/javascript"></script>
<script src="/assets/global/js/Plugin/matchheight.js" type="text/javascript"></script>
<script src="/assets/custom/jquery-qrcode/jquery.qrcode.min.js" type="text/javascript"></script>
<script src="/assets/global/js/Plugin/webui-popover.js" type="text/javascript"></script>
<script src="/assets/global/vendor/jvectormap/jquery-jvectormap.min.js"></script>
<script src="/assets/custom/maps/jquery-jvectormap-world-mill-cn.js"></script>
<script type="text/javascript">
$(function() {
$('#world-map').vectorMap({
map: 'world_mill',
scaleColors: ['#C8EEFF', '#0071A4'],
normalizeFunction: 'polynomial',
zoomAnimate: true,
hoverOpacity: 0.7,
hoverColor: false,
regionStyle: {
initial: {
fill: '#3E8EF7',
},
hover: {
fill: '#589FFC',
},
selected: {
fill: '#0B69E3',
},
selectedHover: {
fill: '#589FFC',
},
},
markerStyle: {
initial: {
r: 3,
fill: '#FF4C52',
'stroke-width': 0,
},
hover: {
r: 6,
stroke: '#FF4C52',
'stroke-width': 0,
},
},
backgroundColor: '#fff',
markers: [
@foreach($nodesGeo as $name => $geo)
{
latLng: [{{$name}}], name: '{{$geo}}',
},
@endforeach
],
});
$('.node').matchHeight();
$('.map').matchHeight();
});
function getInfo(id, type) {
const oldClass = $('#' + type + id).attr('class');
$.ajax({
method: 'POST',
url: '{{route('node')}}',
data: {_token: '{{csrf_token()}}', id: id, type: type},
beforeSend: function() {
$('#' + type + id).removeAttr('class').addClass('icon wb-loop icon-spin');
},
success: function(ret) {
if (ret.status === 'success') {
switch (type) {
case 'code':
swal.fire({
html: '<textarea class="form-control" rows="8" readonly="readonly">' + ret.data + '</textarea>' +
'<a href="' + ret.data + '" class="btn btn-danger btn-block mt-10">{{trans('common.open')}}' + ret.title + '</a>',
showConfirmButton: false,
});
break;
case 'qrcode':
swal.fire({
title: '{{trans('user.scan_qrcode')}}',
html: '<div id="qrcode"></div>',
onBeforeOpen: () => {
$('#qrcode').qrcode({text: ret.data});
},
showConfirmButton: false,
});
break;
case 'text':
swal.fire({
title: '{{trans('user.node.info')}}',
html: '<textarea class="form-control" rows="12" readonly="readonly">' + ret.data + '</textarea>',
showConfirmButton: false,
});
break;
default:
swal.fire({title: ret.title, text: ret.data, icon: 'error'});
}
}
},
complete: function() {
$('#' + type + id).removeAttr('class').addClass(oldClass);
},
});
}
</script>
@endsection