fs-lawrisk/static/permit_filter.html

587 lines
19 KiB
HTML
Raw Permalink Normal View History

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>许可管理与筛选 - LawRisk</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: "Microsoft YaHei", "PingFang SC", -apple-system, BlinkMacSystemFont, sans-serif;
background: linear-gradient(135deg, #f7fafc 0%, #e2e8f0 100%);
min-height: 100vh;
color: #1f2937;
}
.page {
max-width: 1600px;
margin: 0 auto;
padding: 32px 20px 60px;
}
.header {
background: #fff;
border-radius: 18px;
padding: 28px;
box-shadow: 0 20px 60px rgba(79, 70, 229, 0.12);
margin-bottom: 24px;
position: relative;
}
.title {
text-align: center;
}
.title h1 {
font-size: 30px;
margin: 0;
color: #111827;
}
.title p {
margin: 6px 0 0;
color: #4b5563;
font-size: 15px;
}
.filter-section {
background: #fff;
border-radius: 18px;
padding: 28px;
box-shadow: 0 20px 60px rgba(79, 70, 229, 0.12);
margin-bottom: 24px;
}
.filter-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 20px;
margin-bottom: 24px;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.filter-label {
font-size: 14px;
font-weight: 600;
color: #374151;
}
.filter-select, .filter-input {
width: 100%;
padding: 12px 16px;
border: 1px solid #d1d5db;
border-radius: 10px;
font-size: 14px;
background: #fff;
transition: all 0.2s;
}
.filter-select:focus, .filter-input:focus {
outline: none;
border-color: #6366f1;
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}
.filter-select:disabled {
background: #f3f4f6;
color: #9ca3af;
cursor: not-allowed;
}
.filter-actions {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.btn {
padding: 12px 24px;
border: none;
border-radius: 10px;
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary {
background: #6366f1;
color: #fff;
}
.btn-primary:hover {
background: #4f46e5;
transform: translateY(-1px);
box-shadow: 0 10px 20px rgba(99, 102, 241, 0.3);
}
.btn-secondary {
background: #e5e7eb;
color: #374151;
}
.btn-secondary:hover {
background: #d1d5db;
}
.btn:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none !important;
}
.results-section {
background: #fff;
border-radius: 18px;
padding: 28px;
box-shadow: 0 20px 60px rgba(79, 70, 229, 0.12);
}
.results-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 16px;
border-bottom: 2px solid #f3f4f6;
}
.results-count {
font-size: 16px;
color: #4b5563;
}
.results-count strong {
color: #6366f1;
font-size: 18px;
}
.loading {
text-align: center;
padding: 60px 20px;
color: #6b7280;
}
.loading-spinner {
display: inline-block;
width: 40px;
height: 40px;
border: 4px solid #f3f4f6;
border-top-color: #6366f1;
border-radius: 50%;
animation: spin 0.8s linear infinite;
margin-bottom: 12px;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
.error-message {
background: #fee2e2;
border: 1px solid #fecaca;
color: #991b1b;
padding: 16px;
border-radius: 10px;
margin-bottom: 20px;
}
.permits-table {
width: 100%;
border-collapse: collapse;
}
.permits-table th {
background: #f9fafb;
padding: 14px 16px;
text-align: left;
font-weight: 600;
color: #374151;
border-bottom: 2px solid #e5e7eb;
font-size: 14px;
}
.permits-table td {
padding: 14px 16px;
border-bottom: 1px solid #f3f4f6;
font-size: 14px;
color: #4b5563;
}
.permits-table tr:hover {
background: #f9fafb;
}
.empty-state {
text-align: center;
padding: 80px 20px;
color: #9ca3af;
}
.empty-icon {
font-size: 48px;
margin-bottom: 16px;
}
</style>
</head>
<body>
<div class="page">
<!-- 页面头部 -->
<div class="header">
<div class="title">
<h1>许可管理与筛选</h1>
<p>使用过滤器快速定位所需许可文件</p>
</div>
</div>
<!-- 筛选器区域 -->
<div class="filter-section">
<div class="filter-grid">
<!-- 市级单位筛选 -->
<div class="filter-group">
<label class="filter-label">市级单位</label>
<select id="municipalDept" class="filter-select">
<option value="">请选择市级单位</option>
</select>
</div>
<!-- 区级单位筛选 -->
<div class="filter-group">
<label class="filter-label">区级单位</label>
<select id="districtDept" class="filter-select" disabled>
<option value="">请先选择市级单位</option>
</select>
</div>
<!-- 行政区域筛选 -->
<div class="filter-group">
<label class="filter-label">行政区域</label>
<select id="regionFilter" class="filter-select">
<option value="">全部区域</option>
</select>
</div>
<!-- 搜索关键词 -->
<div class="filter-group">
<label class="filter-label">搜索关键词</label>
<input
type="text"
id="searchText"
class="filter-input"
placeholder="输入许可名称关键词..."
/>
</div>
</div>
<!-- 操作按钮 -->
<div class="filter-actions">
<button id="applyBtn" class="btn btn-primary">应用筛选</button>
<button id="resetBtn" class="btn btn-secondary">重置筛选</button>
</div>
</div>
<!-- 结果展示区域 -->
<div class="results-section">
<div class="results-header">
<div class="results-count">
共找到 <strong id="resultCount">0</strong> 个许可文件
</div>
</div>
<div id="loading" class="loading" style="display: none;">
<div class="loading-spinner"></div>
<div>正在加载许可数据...</div>
</div>
<div id="errorMessage" class="error-message" style="display: none;"></div>
<div id="resultsTable">
<div class="empty-state">
<div class="empty-icon">📋</div>
<div>请选择筛选条件并点击"应用筛选"</div>
</div>
</div>
</div>
</div>
<script>
// 全局变量
let municipalTree = [];
let regions = [];
// DOM元素
const municipalSelect = document.getElementById('municipalDept');
const districtSelect = document.getElementById('districtDept');
const regionSelect = document.getElementById('regionFilter');
const searchInput = document.getElementById('searchText');
const applyBtn = document.getElementById('applyBtn');
const resetBtn = document.getElementById('resetBtn');
const resultsTable = document.getElementById('resultsTable');
const resultCount = document.getElementById('resultCount');
const loading = document.getElementById('loading');
const errorMessage = document.getElementById('errorMessage');
// 页面初始化
document.addEventListener('DOMContentLoaded', function() {
loadInitialData();
bindEvents();
});
// 绑定事件
function bindEvents() {
// 市级单位选择变更 - 联动加载区级单位
municipalSelect.addEventListener('change', handleMunicipalChange);
// 应用筛选
applyBtn.addEventListener('click', applyFilter);
// 重置筛选
resetBtn.addEventListener('click', resetFilter);
// 搜索框回车筛选
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
applyFilter();
}
});
}
// 加载初始数据
async function loadInitialData() {
try {
await Promise.all([
loadMunicipalDepartments(),
loadRegions()
]);
} catch (error) {
showError('加载初始数据失败: ' + error.message);
}
}
// 加载市级单位树
async function loadMunicipalDepartments() {
try {
const response = await fetch('/fs-ai-asistant/api/workflow/lawrisk/admin/service-departments/tree');
const data = await response.json();
if (!data.success) {
throw new Error(data.message || '加载市级单位失败');
}
municipalTree = data.data.tree || [];
renderMunicipalOptions(municipalTree);
} catch (error) {
console.error('加载市级单位失败:', error);
throw error;
}
}
// 渲染市级单位选项
function renderMunicipalOptions(tree) {
municipalSelect.innerHTML = '<option value="">请选择市级单位</option>';
tree.forEach(dept => {
const option = document.createElement('option');
option.value = dept.id;
option.textContent = `${dept.name} (${dept.code})`;
municipalSelect.appendChild(option);
});
}
// 加载行政区域
async function loadRegions() {
try {
const response = await fetch('/fs-ai-asistant/api/workflow/lawrisk/v2/regions');
const data = await response.json();
if (!data.success) {
throw new Error(data.message || '加载区域失败');
}
regions = data.data.regions || [];
renderRegionOptions(regions);
} catch (error) {
console.error('加载区域失败:', error);
throw error;
}
}
// 渲染区域选项
function renderRegionOptions(regionList) {
regionSelect.innerHTML = '<option value="">全部区域</option>';
regionList.forEach(region => {
const option = document.createElement('option');
option.value = region.id || region;
option.textContent = region.name || region;
regionSelect.appendChild(option);
});
}
// 处理市级单位选择变更
async function handleMunicipalChange() {
const municipalId = municipalSelect.value;
// 重置区级单位
districtSelect.innerHTML = '<option value="">请选择区级单位</option>';
districtSelect.disabled = !municipalId;
if (!municipalId) {
return;
}
// 加载区级单位
try {
const response = await fetch(
`/fs-ai-asistant/api/workflow/lawrisk/admin/departments/children?parent_id=${municipalId}`
);
const data = await response.json();
if (!data.success) {
throw new Error(data.message || '加载区级单位失败');
}
const children = data.data.units || [];
districtSelect.innerHTML = '<option value="">全部区级单位</option>';
children.forEach(dept => {
const option = document.createElement('option');
option.value = dept.id;
option.textContent = `${dept.name} (${dept.code})`;
districtSelect.appendChild(option);
});
} catch (error) {
console.error('加载区级单位失败:', error);
showError('加载区级单位失败: ' + error.message);
}
}
// 应用筛选
async function applyFilter() {
const filters = {
municipal_dept_id: municipalSelect.value || null,
district_dept_id: districtSelect.value || null,
region: regionSelect.value || null,
search_text: searchInput.value.trim() || null
};
// 显示加载状态
showLoading(true);
hideError();
try {
const response = await fetch('/fs-ai-asistant/api/workflow/lawrisk/admin/permits/filter', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(filters)
});
const data = await response.json();
if (!data.success) {
throw new Error(data.message || '筛选失败');
}
renderResults(data.data.permits || []);
resultCount.textContent = data.data.pagination?.total || 0;
} catch (error) {
console.error('筛选失败:', error);
showError('筛选失败: ' + error.message);
renderResults([]);
resultCount.textContent = 0;
} finally {
showLoading(false);
}
}
// 渲染筛选结果
function renderResults(permits) {
if (!permits || permits.length === 0) {
resultsTable.innerHTML = `
<div class="empty-state">
<div class="empty-icon">📂</div>
<div>未找到符合条件的许可文件</div>
</div>
`;
return;
}
let html = `
<table class="permits-table">
<thead>
<tr>
<th>许可名称</th>
<th>所属单位</th>
<th>行政区域</th>
<th>上传时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
`;
permits.forEach(permit => {
html += `
<tr>
<td>${escapeHtml(permit.name || '未知许可')}</td>
<td>${escapeHtml(permit.department_name || '未知单位')}</td>
<td>${escapeHtml(permit.region_name || '未知区域')}</td>
<td>${formatDate(permit.created_at)}</td>
<td>
<button class="btn btn-primary" style="padding: 6px 12px; font-size: 13px;"
onclick="viewPermit('${permit.id}')">
查看详情
</button>
</td>
</tr>
`;
});
html += `
</tbody>
</table>
`;
resultsTable.innerHTML = html;
}
// 重置筛选
function resetFilter() {
municipalSelect.value = '';
districtSelect.value = '';
districtSelect.disabled = true;
districtSelect.innerHTML = '<option value="">请先选择市级单位</option>';
regionSelect.value = '';
searchInput.value = '';
renderResults([]);
resultCount.textContent = '0';
}
// 显示/隐藏加载状态
function showLoading(show) {
loading.style.display = show ? 'block' : 'none';
applyBtn.disabled = show;
}
// 显示错误信息
function showError(message) {
errorMessage.textContent = message;
errorMessage.style.display = 'block';
setTimeout(() => hideError(), 5000);
}
// 隐藏错误信息
function hideError() {
errorMessage.style.display = 'none';
}
// HTML转义
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 日期格式化
function formatDate(dateString) {
if (!dateString) return '-';
const date = new Date(dateString);
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit'
});
}
// 查看许可详情
function viewPermit(permitId) {
// TODO: 实现许可详情查看功能
alert('查看许可详情功能待实现许可ID: ' + permitId);
}
</script>
</body>
</html>