Files
QueryCarInfo2/templates/query.html
T
2025-09-23 08:17:10 +08:00

563 lines
30 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!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>登录部门</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.user_name }}</td>
<td>{{ query.user_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">
<!-- 详情弹窗已使用layui动态生成,此处不再需要静态模态框 -->
{% include 'footer.html' %}
<!-- 页面JavaScript -->
<script>
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', function() {
// 获取DOM元素
var addQueryBtn = document.getElementById('addQueryBtn');
// 为查询历史记录行添加单击事件
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);
});
// 为了提升用户体验,添加鼠标悬停效果
rows[i].style.cursor = 'pointer';
rows[i].style.transition = 'background-color 0.2s ease';
rows[i].addEventListener('mouseenter', function() {
this.style.backgroundColor = '#f5f7fa';
});
rows[i].addEventListener('mouseleave', function() {
this.style.backgroundColor = '';
});
}
// 增加查询按钮点击事件
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;
}
});
});
// 详情弹窗已使用layui实现,点击背景关闭功能由layui自动处理
// 表单提交逻辑已整合到layui弹窗中,不需要单独的表单提交事件
// 加载查询历史详情
function loadHistoryDetail(historyId) {
// 创建加载中的弹窗
const loadingIndex = layer.load(2, {
shade: [0.3, '#fff'],
content: '<div style="padding: 20px;"><i class="fa fa-spinner fa-spin mr-2"></i>正在加载详情...</div>',
shadeClose: false
});
// 发送AJAX请求获取详情
fetch('/query_history_detail/' + historyId)
.then(function(response) {
return response.json();
})
.then(function(data) {
// 关闭加载弹窗
layer.close(loadingIndex);
// 创建详情弹窗内容
let content = '';
// 转义特殊字符以防止XSS攻击
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text || '';
return div.innerHTML;
}
if (data.error) {
// 显示错误信息
content = `
<div class="layui-text" style="text-align: center; padding: 60px 40px;">
<div style="display: inline-flex; align-items: center; justify-content: center; width: 80px; height: 80px; background-color: #fef0f0; border-radius: 50%; margin-bottom: 20px;">
<i class="fa fa-exclamation-circle text-red-500 text-4xl"></i>
</div>
<p style="color: #666; font-size: 16px;">${data.error}</p>
</div>
`;
} else if (data.car_owners && data.car_owners.length > 0) {
// 添加查询信息标题
content = `
<div class="layui-text" style="padding: 15px;">
<div class="mb-4 pb-3 border-b border-gray-200">
</div>
<div class="space-y-4" id="carOwnerCards">
`;
// 添加车辆信息卡片
for (var i = 0; i < data.car_owners.length; i++) {
var carOwner = data.car_owners[i];
content += `
<div class="bg-white border border-gray-200 rounded-lg shadow-sm">
<div class="p-3 grid grid-cols-1 gap-2">
<div class="flex items-center p-2">
<i class="fa fa-id-card-o text-gray-400 w-8 text-center"></i>
<span class="text-gray-500 w-20">车牌号:</span>
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.plate_number)}</span>
</div>
<div class="flex items-center p-2">
<i class="fa fa-mobile text-gray-400 w-8 text-center"></i>
<span class="text-gray-500 w-20">手机号:</span>
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.phone)}</span>
</div>
<div class="flex items-center p-2">
<i class="fa fa-user text-gray-400 w-8 text-center"></i>
<span class="text-gray-500 w-20">车主姓名:</span>
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.name)}</span>
</div>
<div class="flex items-center p-2">
<i class="fa fa-id-card text-gray-400 w-8 text-center"></i>
<span class="text-gray-500 w-20">身份证号:</span>
<span class="font-medium text-gray-800 flex-1">${escapeHtml(carOwner.id_card)}</span>
</div>
</div>
</div>
`;
}
content += `
</div>
</div>
`;
} else {
// 显示无结果状态
content = `
<div class="layui-text" style="text-align: center; padding: 60px 40px;">
<div style="display: inline-flex; align-items: center; justify-content: center; width: 80px; height: 80px; background-color: #f5f7fa; border-radius: 50%; margin-bottom: 20px;">
<i class="fa fa-search text-gray-300 text-4xl"></i>
</div>
<p style="color: #666; font-size: 16px; margin-bottom: 8px;">暂无车辆信息</p>
<p style="color: #909399; font-size: 14px;">该查询条件下未找到相关车辆信息</p>
</div>
`;
}
// 打开详情弹窗 - 优化布局和样式
layer.open({
type: 1,
title: '<i class="fa fa-file-text-o"></i> 查询详情',
area: ['700px', 'auto'], // 使用自适应高度
offset: '10%',
shade: [0.3, '#fff'],
shadeClose: true,
anim: 2,
content: content,
btn: ['关闭'],
btnAlign: 'c',
btnClass: ['layui-btn layui-btn-primary'],
skin: 'layui-layer-molv',
success: function(layero, index) {
}
});
})
.catch(function(error) {
// 关闭加载弹窗
layer.close(loadingIndex);
// 显示错误弹窗
layer.open({
type: 1,
title: '<i class="fa fa-exclamation-circle"></i> 加载失败',
area: ['360px', 'auto'],
offset: '10%',
shade: 0.3,
shadeClose: false,
anim: 2,
content: `
<div class="layui-text" style="text-align: center; padding: 30px 20px;">
<div style="display: inline-flex; align-items: center; justify-content: center; width: 60px; height: 60px; background-color: #fef0f0; border-radius: 50%; margin-bottom: 15px;">
<i class="fa fa-exclamation-circle text-red-500 text-3xl"></i>
</div>
<p style="color: #666; font-size: 14px;">加载详情时发生错误</p>
<p style="color: #999; font-size: 12px; margin-top: 8px;">请稍后重试</p>
</div>
`,
btn: ['确定'],
btnAlign: 'c',
btnClass: ['layui-btn layui-btn-primary'],
skin: 'layui-layer-molv'
});
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>
</body>
</html>