604 lines
31 KiB
HTML
604 lines
31 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>车主信息查询系统 - 查询</title>
|
||
<!-- 引入Layui CSS -->
|
||
<link rel="stylesheet" href="{{ url_for('static', filename='css/layui.css') }}">
|
||
<!-- 引入Font Awesome -->
|
||
<link href="{{ url_for('static', filename='css/font-awesome.min.css') }}" rel="stylesheet">
|
||
<!-- 引入自定义CSS -->
|
||
<link href="{{ url_for('static', filename='css/custom.css') }}" rel="stylesheet">
|
||
|
||
<!-- 引入Layui JS -->
|
||
<script src="{{ url_for('static', filename='layui.js') }}"></script>
|
||
|
||
<script>
|
||
layui.use(['layer', 'form', 'table'], function(){
|
||
var layer = layui.layer;
|
||
var form = layui.form;
|
||
var table = layui.table;
|
||
});
|
||
</script>
|
||
|
||
<style>
|
||
@keyframes fadeIn {
|
||
from {
|
||
opacity: 0;
|
||
transform: translateY(-10px);
|
||
}
|
||
to {
|
||
opacity: 1;
|
||
transform: translateY(0);
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<!-- 引入统一的顶部导航栏 -->
|
||
{% include 'header.html' %}
|
||
|
||
<!-- 主要内容区域 -->
|
||
<div class="content-container">
|
||
<div class="content-wrapper">
|
||
<div class="card">
|
||
<div class="card-body">
|
||
<!-- 表单已清除 -->
|
||
|
||
<!-- 消息提示区域 -->
|
||
{% if error %}
|
||
<div class="error-message">
|
||
<i class="fa fa-exclamation-circle"></i> {{ error }}
|
||
</div>
|
||
{% endif %}
|
||
{% if success %}
|
||
<div class="success-message">
|
||
<i class="fa fa-check-circle"></i> {{ success }}
|
||
</div>
|
||
{% endif %}
|
||
|
||
<!-- 最近查询记录 -->
|
||
{% if recent_queries %}
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<i class="fa fa-history"></i> 最近查询记录
|
||
<button id="addQueryBtn" class="layui-btn layui-btn-normal" style="
|
||
float: right;
|
||
padding: 6px 16px;
|
||
border-radius: 6px;
|
||
background-color: #009688;
|
||
border-color: #009688;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
color: white;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 5px;
|
||
">
|
||
<i class="fa fa-plus-circle"></i> 新增查询记录
|
||
</button>
|
||
</div>
|
||
<div class="card-body">
|
||
<table class="layui-table">
|
||
<thead>
|
||
<tr>
|
||
<th>序号</th>
|
||
<th>查询日期</th>
|
||
<th>车牌号</th>
|
||
<th>手机号</th>
|
||
<th>状态</th>
|
||
<th>登录部门</th>
|
||
<th>登录IP</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for query in recent_queries %}
|
||
<tr class="table-hover" data-history-id="{{ query.id }}">
|
||
<td>{{ loop.index }}</td>
|
||
<td>{{ query.query_date }}</td>
|
||
<td>{{ query.plate_number }}</td>
|
||
<td>{{ query.phone }}</td>
|
||
<td>
|
||
<span class="layui-badge
|
||
{% if query.results_count == -1 %}
|
||
layui-bg-orange
|
||
{% elif query.results_count > 0 %}
|
||
layui-bg-green
|
||
{% else %}
|
||
layui-bg-red
|
||
{% endif %}">
|
||
{% if query.results_count == -1 %}
|
||
待查询
|
||
{% else %}
|
||
{{ query.results_count }} 条记录
|
||
{% endif %}
|
||
</span>
|
||
</td>
|
||
<td>{{ query.department }}</td>
|
||
<td>{{ query.query_ip }}</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 用于layui增加查询弹窗的隐藏字段 -->
|
||
<input type="hidden" id="add_plate_number">
|
||
<input type="hidden" id="add_phone">
|
||
|
||
<!-- 详情模态框 -->
|
||
<div id="detailModal" class="fixed inset-0 bg-black/50 z-50 hidden flex items-center justify-center p-4">
|
||
<div class="bg-white rounded-lg shadow-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
|
||
<div class="p-6" id="modalContent">
|
||
<!-- 结果列表 -->
|
||
<div id="resultList" class="hidden">
|
||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6" id="carOwnerCards">
|
||
<!-- 车辆信息卡片会动态添加到这里 -->
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
{% include 'footer.html' %}
|
||
|
||
<!-- 页面JavaScript -->
|
||
<script>
|
||
// 等待DOM加载完成
|
||
document.addEventListener('DOMContentLoaded', function() {
|
||
// 获取DOM元素
|
||
var addQueryBtn = document.getElementById('addQueryBtn');
|
||
var addQueryModal = document.getElementById('addQueryModal');
|
||
var closeAddModal = document.getElementById('closeAddModal');
|
||
var cancelAddBtn = document.getElementById('cancelAddBtn');
|
||
var addQueryForm = document.getElementById('addQueryForm');
|
||
var addQueryLoading = document.getElementById('addQueryLoading');
|
||
var detailModal = document.getElementById('detailModal');
|
||
var closeModal = document.getElementById('closeModal');
|
||
var loadingState = document.getElementById('loadingState');
|
||
var noResultState = document.getElementById('noResultState');
|
||
var resultList = document.getElementById('resultList');
|
||
var carOwnerCards = document.getElementById('carOwnerCards');
|
||
|
||
// 为查询历史记录行添加点击事件
|
||
var rows = document.querySelectorAll('tr[data-history-id]');
|
||
for (var i = 0; i < rows.length; i++) {
|
||
rows[i].addEventListener('click', function() {
|
||
var historyId = this.getAttribute('data-history-id');
|
||
loadHistoryDetail(historyId);
|
||
});
|
||
}
|
||
|
||
// 增加查询按钮点击事件
|
||
addQueryBtn.addEventListener('click', function() {
|
||
// 使用layui创建增加查询记录弹窗,并美化设计
|
||
layer.open({
|
||
type: 1,
|
||
title: '<i class="fa fa-plus-circle"></i> 增加查询记录',
|
||
area: ['520px', '380px'],
|
||
offset: '10%',
|
||
shade: 0.3,
|
||
shadeClose: false,
|
||
anim: 2,
|
||
content: `
|
||
<div class="form-container" style="padding: 24px;">
|
||
|
||
|
||
<!-- 表单主体 -->
|
||
<form class="layui-form">
|
||
<!-- 车牌号输入框 -->
|
||
<div class="form-group" style="margin-bottom: 20px;">
|
||
<label for="layui_add_plate_number" style="display: block; font-size: 14px; color: #333; margin-bottom: 8px; font-weight: 500;">
|
||
<i class="fa fa-id-card-o" style="color: #009688; margin-right: 6px;"></i>车牌号
|
||
</label>
|
||
<div class="input-wrapper" style="position: relative;">
|
||
<input type="text" id="layui_add_plate_number"
|
||
style="
|
||
width: 100%;
|
||
height: 42px;
|
||
padding: 0 12px;
|
||
border: 1px solid #dcdfe6;
|
||
border-radius: 6px;
|
||
font-size: 14px;
|
||
transition: all 0.3s ease;
|
||
box-sizing: border-box;
|
||
"
|
||
placeholder="请输入车牌号(如:京A123456)"
|
||
onfocus="this.style.borderColor='#009688'; this.style.boxShadow='0 0 0 2px rgba(0,150,136,0.2)';"
|
||
onblur="this.style.borderColor='#dcdfe6'; this.style.boxShadow='none';">
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 手机号输入框 -->
|
||
<div class="form-group" style="margin-bottom: 24px;">
|
||
<label for="layui_add_phone" style="display: block; font-size: 14px; color: #333; margin-bottom: 8px; font-weight: 500;">
|
||
<i class="fa fa-mobile" style="color: #009688; margin-right: 6px;"></i>手机号
|
||
</label>
|
||
<div class="input-wrapper" style="position: relative;">
|
||
<input type="tel" id="layui_add_phone"
|
||
style="
|
||
width: 100%;
|
||
height: 42px;
|
||
padding: 0 12px;
|
||
border: 1px solid #dcdfe6;
|
||
border-radius: 6px;
|
||
font-size: 14px;
|
||
transition: all 0.3s ease;
|
||
box-sizing: border-box;
|
||
"
|
||
placeholder="请输入手机号(如:13800138001)"
|
||
onfocus="this.style.borderColor='#009688'; this.style.boxShadow='0 0 0 2px rgba(0,150,136,0.2)';"
|
||
onblur="this.style.borderColor='#dcdfe6'; this.style.boxShadow='none';">
|
||
</div>
|
||
<div class="form-tip" style="margin-top: 6px;">
|
||
<i class="fa fa-info-circle" style="color: #909399; font-size: 12px;"></i>
|
||
<span style="color: #909399; font-size: 12px; margin-left: 4px;">提示:请至少输入车牌号或手机号其中一项</span>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 加载状态 -->
|
||
<div id="layui_addQueryLoading" class="loading-state" style="display: none; flex-direction: column; align-items: center; justify-content: center; padding: 30px 0;">
|
||
<div class="spinner" style="width: 40px; height: 40px; border: 3px solid #f0f0f0; border-top: 3px solid #009688; border-radius: 50%; animation: spin 1s linear infinite;"></div>
|
||
<p style="margin-top: 12px; color: #606266; font-size: 14px;">正在处理...</p>
|
||
</div>
|
||
|
||
<style>
|
||
@keyframes spin {
|
||
0% { transform: rotate(0deg); }
|
||
100% { transform: rotate(360deg); }
|
||
}
|
||
</style>
|
||
</form>
|
||
<style>
|
||
.btn-success {
|
||
background-color: #009688;
|
||
border-color: #009688;
|
||
color: white;
|
||
padding: 8px 20px;
|
||
border-radius: 6px;
|
||
font-size: 14px;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
box-shadow: 0 2px 4px rgba(0, 150, 136, 0.2);
|
||
outline: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.btn-success:hover {
|
||
background-color: #26a69a;
|
||
border-color: #26a69a;
|
||
box-shadow: 0 4px 8px rgba(0, 150, 136, 0.3);
|
||
}
|
||
|
||
.btn-success:active {
|
||
transform: translateY(1px);
|
||
}
|
||
|
||
.btn-secondary {
|
||
background-color: #f0f2f5;
|
||
border-color: #dcdfe6;
|
||
color: #606266;
|
||
padding: 8px 20px;
|
||
border-radius: 6px;
|
||
font-size: 14px;
|
||
transition: all 0.3s ease;
|
||
outline: none;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background-color: #e6eaf0;
|
||
border-color: #c0c4cc;
|
||
}
|
||
</style>
|
||
</div>
|
||
`,
|
||
btn: ['保存', '取消'],
|
||
btnAlign: 'c',
|
||
btnClass: ['btn-success', 'btn-secondary'],
|
||
btn1: function(index, layero) {
|
||
const plateNumber = document.getElementById('layui_add_plate_number').value;
|
||
const phone = document.getElementById('layui_add_phone').value;
|
||
|
||
// 验证输入
|
||
if (!plateNumber && !phone) {
|
||
layer.msg('请至少输入车牌号或手机号其中一项', {
|
||
icon: 5,
|
||
anim: 6,
|
||
time: 2000
|
||
});
|
||
return false;
|
||
}
|
||
|
||
// 手机号格式验证
|
||
if (phone && !/^1[3-9]\d{9}$/.test(phone)) {
|
||
layer.msg('请输入正确的手机号码', {
|
||
icon: 5,
|
||
anim: 6,
|
||
time: 2000
|
||
});
|
||
return false;
|
||
}
|
||
|
||
// 车牌号格式简单验证(可根据实际需求调整)
|
||
if (plateNumber && plateNumber.length < 5) {
|
||
layer.msg('请输入正确的车牌号', {
|
||
icon: 5,
|
||
anim: 6,
|
||
time: 2000
|
||
});
|
||
return false;
|
||
}
|
||
|
||
// 显示加载状态
|
||
document.getElementById('layui_addQueryLoading').style.display = 'flex';
|
||
|
||
// 模拟提交数据
|
||
setTimeout(function() {
|
||
// 创建表单用于提交数据
|
||
var form = document.createElement('form');
|
||
form.method = 'POST';
|
||
form.action = '/query';
|
||
|
||
// 添加车牌号字段
|
||
var plateInput = document.createElement('input');
|
||
plateInput.type = 'hidden';
|
||
plateInput.name = 'plate_number';
|
||
plateInput.value = plateNumber;
|
||
form.appendChild(plateInput);
|
||
|
||
// 添加手机号字段
|
||
var phoneInput = document.createElement('input');
|
||
phoneInput.type = 'hidden';
|
||
phoneInput.name = 'phone';
|
||
phoneInput.value = phone;
|
||
form.appendChild(phoneInput);
|
||
|
||
// 添加标识字段,表示这是从"增加"按钮提交的请求
|
||
var isAddInput = document.createElement('input');
|
||
isAddInput.type = 'hidden';
|
||
isAddInput.name = 'is_add_query';
|
||
isAddInput.value = 'true';
|
||
form.appendChild(isAddInput);
|
||
|
||
// 隐藏加载状态
|
||
document.getElementById('layui_addQueryLoading').style.display = 'none';
|
||
|
||
// 关闭弹窗
|
||
layer.close(index);
|
||
|
||
// 显示成功消息
|
||
layer.msg('查询记录添加成功', {
|
||
icon: 1,
|
||
time: 2000,
|
||
end: function() {
|
||
// 提交表单,将数据发送到服务器
|
||
document.body.appendChild(form);
|
||
form.submit();
|
||
}
|
||
});
|
||
}, 800);
|
||
},
|
||
btn2: function(index, layero) {
|
||
layer.close(index);
|
||
return false;
|
||
}
|
||
});
|
||
});
|
||
|
||
// 移除对已删除元素的引用
|
||
|
||
// 点击详情模态框背景关闭
|
||
detailModal.addEventListener('click', function(e) {
|
||
if (e.target === detailModal) {
|
||
// 兼容classList API
|
||
if (detailModal.classList) {
|
||
detailModal.classList.add('hidden');
|
||
} else {
|
||
detailModal.className += ' hidden';
|
||
}
|
||
}
|
||
});
|
||
|
||
// 表单提交逻辑已整合到layui弹窗中,不需要单独的表单提交事件
|
||
|
||
|
||
// 加载查询历史详情
|
||
function loadHistoryDetail(historyId) {
|
||
// 显示模态框和加载状态
|
||
// 兼容classList API
|
||
if (detailModal.classList) {
|
||
detailModal.classList.remove('hidden');
|
||
} else {
|
||
detailModal.className = detailModal.className.replace('hidden', '');
|
||
}
|
||
if (loadingState.classList) {
|
||
loadingState.classList.remove('hidden');
|
||
} else {
|
||
loadingState.className = loadingState.className.replace('hidden', '');
|
||
}
|
||
if (noResultState.classList) {
|
||
noResultState.classList.add('hidden');
|
||
} else {
|
||
noResultState.className += ' hidden';
|
||
}
|
||
if (resultList.classList) {
|
||
resultList.classList.add('hidden');
|
||
} else {
|
||
resultList.className += ' hidden';
|
||
}
|
||
carOwnerCards.innerHTML = '';
|
||
|
||
// 发送AJAX请求获取详情
|
||
fetch('/query_history_detail/' + historyId)
|
||
.then(function(response) {
|
||
return response.json();
|
||
})
|
||
.then(function(data) {
|
||
// 隐藏加载状态
|
||
// 兼容classList API
|
||
if (loadingState.classList) {
|
||
loadingState.classList.add('hidden');
|
||
} else {
|
||
loadingState.className += ' hidden';
|
||
}
|
||
|
||
if (data.error) {
|
||
// 显示错误信息
|
||
noResultState.querySelector('p').textContent = data.error;
|
||
// 兼容classList API
|
||
if (noResultState.classList) {
|
||
noResultState.classList.remove('hidden');
|
||
} else {
|
||
noResultState.className = noResultState.className.replace('hidden', '');
|
||
}
|
||
} else if (data.car_owners && data.car_owners.length > 0) {
|
||
// 显示结果列表
|
||
// 兼容classList API
|
||
if (resultList.classList) {
|
||
resultList.classList.remove('hidden');
|
||
} else {
|
||
resultList.className = resultList.className.replace('hidden', '');
|
||
}
|
||
|
||
// 添加车辆信息卡片
|
||
for (var i = 0; i < data.car_owners.length; i++) {
|
||
var carOwner = data.car_owners[i];
|
||
var card = document.createElement('div');
|
||
card.className = 'bg-white border border-gray-200 rounded-lg p-5 shadow-sm hover:shadow-md transition-shadow duration-200';
|
||
|
||
// 使用字符串拼接替代模板字符串
|
||
var cardHtml = '';
|
||
cardHtml += '<h4 class="text-lg font-medium text-gray-800 mb-4 flex items-center">';
|
||
cardHtml += ' <i class="fa fa-car text-primary mr-2"></i>';
|
||
cardHtml += ' 车辆信息';
|
||
cardHtml += '</h4>';
|
||
cardHtml += '<div class="space-y-3">';
|
||
cardHtml += ' <div class="flex justify-between items-center">';
|
||
cardHtml += ' <span class="text-gray-500">车牌号:</span>';
|
||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.plate_number || '') + '</span>';
|
||
cardHtml += ' </div>';
|
||
cardHtml += ' <div class="flex justify-between items-center">';
|
||
cardHtml += ' <span class="text-gray-500">手机号:</span>';
|
||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.phone || '') + '</span>';
|
||
cardHtml += ' </div>';
|
||
cardHtml += ' <div class="flex justify-between items-center">';
|
||
cardHtml += ' <span class="text-gray-500">车主姓名:</span>';
|
||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.name || '') + '</span>';
|
||
cardHtml += ' </div>';
|
||
cardHtml += ' <div class="flex justify-between items-center">';
|
||
cardHtml += ' <span class="text-gray-500">身份证号:</span>';
|
||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.id_card || '') + '</span>';
|
||
cardHtml += ' </div>';
|
||
cardHtml += ' <div class="flex justify-between items-center">';
|
||
cardHtml += ' <span class="text-gray-500">电子邮箱:</span>';
|
||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.email || '未提供') + '</span>';
|
||
cardHtml += ' </div>';
|
||
cardHtml += ' <div class="flex justify-between items-center">';
|
||
cardHtml += ' <span class="text-gray-500">居住地址:</span>';
|
||
cardHtml += ' <span class="font-medium text-gray-800">' + (carOwner.address || '未提供') + '</span>';
|
||
cardHtml += ' </div>';
|
||
cardHtml += '</div>';
|
||
|
||
card.innerHTML = cardHtml;
|
||
carOwnerCards.appendChild(card);
|
||
}
|
||
} else {
|
||
// 显示无结果状态
|
||
// 兼容classList API
|
||
if (noResultState.classList) {
|
||
noResultState.classList.remove('hidden');
|
||
} else {
|
||
noResultState.className = noResultState.className.replace('hidden', '');
|
||
}
|
||
}
|
||
})
|
||
.catch(function(error) {
|
||
// 隐藏加载状态,显示错误信息
|
||
// 兼容classList API
|
||
if (loadingState.classList) {
|
||
loadingState.classList.add('hidden');
|
||
} else {
|
||
loadingState.className += ' hidden';
|
||
}
|
||
noResultState.querySelector('p').textContent = '加载详情时发生错误';
|
||
// 兼容classList API
|
||
if (noResultState.classList) {
|
||
noResultState.classList.remove('hidden');
|
||
} else {
|
||
noResultState.className = noResultState.className.replace('hidden', '');
|
||
}
|
||
console.error('Error loading history detail:', error);
|
||
});
|
||
}
|
||
|
||
// 响应式处理:当窗口大小改变时,重新绑定事件(因为表格可能会重新渲染)
|
||
window.addEventListener('resize', function() {
|
||
// 重新绑定事件到查询历史记录行
|
||
var rows = document.querySelectorAll('tr[data-history-id]');
|
||
for (var i = 0; i < rows.length; i++) {
|
||
var row = rows[i];
|
||
// 先移除旧的事件监听器
|
||
var newRow = row.cloneNode(true);
|
||
row.parentNode.replaceChild(newRow, row);
|
||
|
||
// 添加新的事件监听器
|
||
newRow.addEventListener('click', function() {
|
||
var historyId = this.getAttribute('data-history-id');
|
||
loadHistoryDetail(historyId);
|
||
});
|
||
}
|
||
});
|
||
});
|
||
</script>
|
||
|
||
|
||
|
||
|
||
<script>
|
||
// 全局搜索变量
|
||
var searchQuery = '';
|
||
</script>
|
||
|
||
<script>
|
||
// ESC键关闭详情弹窗
|
||
document.addEventListener('keydown', function(e) {
|
||
// 使用keyCode替代key,提高兼容性
|
||
var key = e.key || e.keyCode;
|
||
var isEscape = key === 'Escape' || key === 'Esc' || key === 27;
|
||
|
||
var detailModal = document.getElementById('detailModal');
|
||
var isHidden = false;
|
||
|
||
// 兼容classList API
|
||
if (detailModal.classList) {
|
||
isHidden = detailModal.classList.contains('hidden');
|
||
} else {
|
||
isHidden = detailModal.className.indexOf('hidden') !== -1;
|
||
}
|
||
|
||
if (isEscape && !isHidden) {
|
||
// 兼容classList API
|
||
if (detailModal.classList) {
|
||
detailModal.classList.add('hidden');
|
||
} else {
|
||
detailModal.className += ' hidden';
|
||
}
|
||
}
|
||
});
|
||
</script>
|
||
|
||
|
||
|
||
</body>
|
||
</html> |