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

434 lines
21 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>
<!-- 引入Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 引入Font Awesome -->
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<!-- 配置Tailwind CSS -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#1890ff',
secondary: '#f0f2f5',
success: '#52c41a',
warning: '#faad14',
error: '#f5222d',
info: '#8c8c8c',
'primary-light': '#e6f7ff',
'table-header': '#fafafa'
},
fontFamily: {
sans: ['Microsoft YaHei', 'Arial', 'sans-serif']
}
}
}
}
</script>
<!-- 自定义工具类 -->
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.card-shadow {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
}
.input-focus {
@apply focus:border-primary focus:ring-2 focus:ring-primary/20 focus:outline-none;
}
.table-hover {
@apply hover:bg-primary-light/30 transition-colors duration-150;
}
.animate-fade-in {
animation: fadeIn 0.3s ease-out forwards;
}
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
</head>
<body class="bg-secondary min-h-screen font-sans">
{% include 'header.html' %}
<!-- 主要内容区域 -->
<main class="container mx-auto px-4 pt-24 pb-12">
<!-- 消息提示区域 -->
{% if error %}
<div class="mb-6 bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded-md flex items-start animate-fade-in">
<i class="fa fa-exclamation-circle mt-1 mr-3"></i>
<span>{{ error }}</span>
</div>
{% endif %}
{% if success %}
<div class="mb-6 bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded-md flex items-start animate-fade-in">
<i class="fa fa-check-circle mt-1 mr-3"></i>
<span>{{ success }}</span>
</div>
{% endif %}
<!-- 最近查询记录 -->
{% if recent_queries %}
<div class="bg-white rounded-lg card-shadow p-6 transform hover:translate-y-[-2px] transition-all duration-300">
<div class="flex justify-between items-center mb-4">
<h2 class="text-lg font-semibold text-gray-800 flex items-center">
<i class="fa fa-history text-primary mr-2"></i> 最近查询记录
</h2>
<button id="addQueryBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-md flex items-center transition-all duration-200 shadow-sm hover:shadow">
<i class="fa fa-plus mr-1"></i> 增加
</button>
</div>
</h2>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-table-header">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">序号</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">查询日期</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">车牌号</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">手机号</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">查询结果</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">登录部门</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">登录IP</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
{% for query in recent_queries %}
<tr class="table-hover cursor-pointer transition-all duration-200 hover:bg-primary-light/40" data-history-id="{{ query.id }}">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ loop.index }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.query_date }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.plate_number }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.phone }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full
{% if query.results_count > 0 %}
bg-success/10 text-success
{% else %}
bg-error/10 text-error
{% endif %}">
{{ query.results_count }} 条记录
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.department }}</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-900">{{ query.query_ip }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% endif %}
</main>
<!-- 增加查询模态框 -->
<div id="addQueryModal" 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-md w-full">
<div class="flex justify-between items-center p-6 border-b">
<h3 class="text-xl font-semibold text-gray-800">增加查询记录</h3>
<button id="closeAddModal" class="text-gray-500 hover:text-gray-700 transition-colors">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="p-6">
<form id="addQueryForm">
<div class="mb-4">
<label for="add_plate_number" class="block text-sm font-medium text-gray-700 mb-1">车牌号</label>
<input type="text" id="add_plate_number" name="plate_number"
class="w-full px-4 py-2 border border-gray-300 rounded-md input-focus transition-all duration-200"
placeholder="请输入车牌号(如:京A123456">
</div>
<div class="mb-6">
<label for="add_phone" class="block text-sm font-medium text-gray-700 mb-1">手机号</label>
<input type="tel" id="add_phone" name="phone"
class="w-full px-4 py-2 border border-gray-300 rounded-md input-focus transition-all duration-200"
placeholder="请输入手机号(如:13800138001">
<p class="mt-1 text-sm text-gray-500">提示:请至少输入车牌号或手机号其中一项</p>
</div>
<div class="flex space-x-4">
<button type="submit" class="flex-1 bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-md transition-all duration-200">
保存
</button>
<button type="button" id="cancelAddBtn" class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 px-4 py-2 rounded-md transition-all duration-200">
取消
</button>
</div>
</form>
<!-- 加载状态 -->
<div id="addQueryLoading" class="py-10 flex flex-col items-center justify-center hidden">
<i class="fa fa-spinner fa-spin text-primary text-3xl mb-4"></i>
<p class="text-gray-600">正在处理...</p>
</div>
</div>
</div>
</div>
<!-- 详情模态框 -->
<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="flex justify-between items-center p-6 border-b">
<h3 class="text-xl font-semibold text-gray-800">查询结果详情</h3>
<button id="closeModal" class="text-gray-500 hover:text-gray-700 transition-colors">
<i class="fa fa-times text-xl"></i>
</button>
</div>
<div class="p-6" id="modalContent">
<!-- 加载状态 -->
<div id="loadingState" class="py-10 flex flex-col items-center justify-center">
<i class="fa fa-spinner fa-spin text-primary text-3xl mb-4"></i>
<p class="text-gray-600">正在加载详情...</p>
</div>
<!-- 无结果状态 -->
<div id="noResultState" class="py-10 flex flex-col items-center justify-center hidden">
<i class="fa fa-search text-gray-300 text-5xl mb-4"></i>
<p class="text-gray-600">未找到相关车辆信息</p>
</div>
<!-- 结果列表 -->
<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元素
const addQueryBtn = document.getElementById('addQueryBtn');
const addQueryModal = document.getElementById('addQueryModal');
const closeAddModal = document.getElementById('closeAddModal');
const cancelAddBtn = document.getElementById('cancelAddBtn');
const addQueryForm = document.getElementById('addQueryForm');
const addQueryLoading = document.getElementById('addQueryLoading');
const detailModal = document.getElementById('detailModal');
const closeModal = document.getElementById('closeModal');
const loadingState = document.getElementById('loadingState');
const noResultState = document.getElementById('noResultState');
const resultList = document.getElementById('resultList');
const carOwnerCards = document.getElementById('carOwnerCards');
// 为查询历史记录行添加点击事件
document.querySelectorAll('tr[data-history-id]').forEach(row => {
row.addEventListener('click', function() {
const historyId = this.getAttribute('data-history-id');
loadHistoryDetail(historyId);
});
});
// 增加查询按钮点击事件
addQueryBtn.addEventListener('click', function() {
addQueryModal.classList.remove('hidden');
addQueryForm.reset();
});
// 关闭增加查询模态框
closeAddModal.addEventListener('click', function() {
addQueryModal.classList.add('hidden');
});
// 取消增加查询
cancelAddBtn.addEventListener('click', function() {
addQueryModal.classList.add('hidden');
});
// 点击增加查询模态框背景关闭
addQueryModal.addEventListener('click', function(e) {
if (e.target === addQueryModal) {
addQueryModal.classList.add('hidden');
}
});
// 关闭详情模态框
closeModal.addEventListener('click', function() {
detailModal.classList.add('hidden');
});
// 点击详情模态框背景关闭
detailModal.addEventListener('click', function(e) {
if (e.target === detailModal) {
detailModal.classList.add('hidden');
}
});
// 处理增加查询表单提交
addQueryForm.addEventListener('submit', function(e) {
e.preventDefault();
const plateNumber = document.getElementById('add_plate_number').value.trim();
const phone = document.getElementById('add_phone').value.trim();
if (!plateNumber && !phone) {
alert('请至少输入车牌号或手机号');
return;
}
// 显示加载状态
addQueryForm.classList.add('hidden');
addQueryLoading.classList.remove('hidden');
// 构建表单数据
const formData = new FormData();
formData.append('plate_number', plateNumber);
formData.append('phone', phone);
// 发送请求到查询路由
fetch('/query', {
method: 'POST',
body: formData
})
.then(response => {
if (!response.ok) {
throw new Error('网络错误');
}
// 重新加载页面以显示新的查询记录
window.location.reload();
})
.catch(error => {
console.error('Error submitting query:', error);
alert('提交失败,请重试');
// 恢复表单显示
addQueryForm.classList.remove('hidden');
addQueryLoading.classList.add('hidden');
});
});
// 加载查询历史详情
function loadHistoryDetail(historyId) {
// 显示模态框和加载状态
detailModal.classList.remove('hidden');
loadingState.classList.remove('hidden');
noResultState.classList.add('hidden');
resultList.classList.add('hidden');
carOwnerCards.innerHTML = '';
// 发送AJAX请求获取详情
fetch(`/query_history_detail/${historyId}`)
.then(response => response.json())
.then(data => {
// 隐藏加载状态
loadingState.classList.add('hidden');
if (data.error) {
// 显示错误信息
noResultState.querySelector('p').textContent = data.error;
noResultState.classList.remove('hidden');
} else if (data.car_owners && data.car_owners.length > 0) {
// 显示结果列表
resultList.classList.remove('hidden');
// 添加车辆信息卡片
data.car_owners.forEach(carOwner => {
const 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';
card.innerHTML = `
<h4 class="text-lg font-medium text-gray-800 mb-4 flex items-center">
<i class="fa fa-car text-primary mr-2"></i>
车辆信息
</h4>
<div class="space-y-3">
<div class="flex justify-between items-center">
<span class="text-gray-500">车牌号:</span>
<span class="font-medium text-gray-800">${carOwner.plate_number}</span>
</div>
<div class="flex justify-between items-center">
<span class="text-gray-500">手机号:</span>
<span class="font-medium text-gray-800">${carOwner.phone}</span>
</div>
<div class="flex justify-between items-center">
<span class="text-gray-500">车主姓名:</span>
<span class="font-medium text-gray-800">${carOwner.name}</span>
</div>
<div class="flex justify-between items-center">
<span class="text-gray-500">身份证号:</span>
<span class="font-medium text-gray-800">${carOwner.id_card}</span>
</div>
<div class="flex justify-between items-center">
<span class="text-gray-500">电子邮箱:</span>
<span class="font-medium text-gray-800">${carOwner.email || '未提供'}</span>
</div>
<div class="flex justify-between items-center">
<span class="text-gray-500">居住地址:</span>
<span class="font-medium text-gray-800">${carOwner.address || '未提供'}</span>
</div>
</div>
`;
carOwnerCards.appendChild(card);
});
} else {
// 显示无结果状态
noResultState.classList.remove('hidden');
}
})
.catch(error => {
// 隐藏加载状态,显示错误信息
loadingState.classList.add('hidden');
noResultState.querySelector('p').textContent = '加载详情时发生错误';
noResultState.classList.remove('hidden');
console.error('Error loading history detail:', error);
});
}
// 响应式处理:当窗口大小改变时,重新绑定事件(因为表格可能会重新渲染)
window.addEventListener('resize', function() {
// 重新绑定事件到查询历史记录行
document.querySelectorAll('tr[data-history-id]').forEach(row => {
// 先移除旧的事件监听器
const newRow = row.cloneNode(true);
row.parentNode.replaceChild(newRow, row);
// 添加新的事件监听器
newRow.addEventListener('click', function() {
const historyId = this.getAttribute('data-history-id');
loadHistoryDetail(historyId);
});
});
});
});
</script>
<script>
// 全局搜索变量
let searchQuery = '';
</script>
<script>
// ESC键关闭详情弹窗
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && !document.getElementById('detailModal').classList.contains('hidden')) {
document.getElementById('detailModal').classList.add('hidden');
}
});
</script>
</body>
</html>