630 lines
20 KiB
HTML
630 lines
20 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>数据库维护页面 - LawRisk</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: 'Microsoft YaHei', Arial, sans-serif;
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
min-height: 100vh;
|
|
padding: 20px;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1400px;
|
|
margin: 0 auto;
|
|
background: white;
|
|
border-radius: 12px;
|
|
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
|
|
padding: 30px;
|
|
}
|
|
|
|
.header {
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
padding-bottom: 20px;
|
|
border-bottom: 3px solid #667eea;
|
|
}
|
|
|
|
.header h1 {
|
|
color: #333;
|
|
font-size: 28px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.header p {
|
|
color: #666;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.step-indicator {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
margin-bottom: 30px;
|
|
gap: 10px;
|
|
}
|
|
|
|
.step {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.step-number {
|
|
width: 36px;
|
|
height: 36px;
|
|
border-radius: 50%;
|
|
background: #e0e7ff;
|
|
color: #667eea;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-weight: bold;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.step.active .step-number {
|
|
background: #667eea;
|
|
color: white;
|
|
}
|
|
|
|
.step-label {
|
|
font-size: 14px;
|
|
color: #666;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.step.active .step-label {
|
|
color: #667eea;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.arrow {
|
|
color: #ccc;
|
|
font-size: 24px;
|
|
}
|
|
|
|
.content-area {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 30px;
|
|
min-height: 600px;
|
|
}
|
|
|
|
.panel {
|
|
background: #f8f9fa;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
border: 1px solid #e0e0e0;
|
|
}
|
|
|
|
.panel h2 {
|
|
color: #333;
|
|
font-size: 18px;
|
|
margin-bottom: 15px;
|
|
padding-bottom: 10px;
|
|
border-bottom: 2px solid #667eea;
|
|
}
|
|
|
|
.selection-area {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
min-height: 500px;
|
|
}
|
|
|
|
.item-list {
|
|
list-style: none;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
.item-list li {
|
|
padding: 12px 16px;
|
|
margin-bottom: 8px;
|
|
background: #f8f9fa;
|
|
border: 1px solid #e0e0e0;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
transition: all 0.3s;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
|
|
.item-list li:hover {
|
|
background: #e0e7ff;
|
|
border-color: #667eea;
|
|
transform: translateX(5px);
|
|
}
|
|
|
|
.item-list li.active {
|
|
background: #667eea;
|
|
color: white;
|
|
border-color: #667eea;
|
|
}
|
|
|
|
.item-list li.active:hover {
|
|
background: #5568d3;
|
|
}
|
|
|
|
.item-name {
|
|
font-size: 15px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.item-count {
|
|
font-size: 12px;
|
|
background: rgba(102, 126, 234, 0.1);
|
|
padding: 4px 10px;
|
|
border-radius: 12px;
|
|
color: #667eea;
|
|
}
|
|
|
|
.item-list li.active .item-count {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
color: white;
|
|
}
|
|
|
|
.details-area {
|
|
background: white;
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
min-height: 500px;
|
|
}
|
|
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100%;
|
|
color: #999;
|
|
}
|
|
|
|
.empty-state svg {
|
|
width: 80px;
|
|
height: 80px;
|
|
margin-bottom: 15px;
|
|
opacity: 0.3;
|
|
}
|
|
|
|
.empty-state p {
|
|
font-size: 16px;
|
|
}
|
|
|
|
.details-content {
|
|
animation: fadeIn 0.3s;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(10px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.detail-section {
|
|
margin-bottom: 25px;
|
|
}
|
|
|
|
.detail-section h3 {
|
|
color: #667eea;
|
|
font-size: 16px;
|
|
margin-bottom: 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
}
|
|
|
|
.detail-section h3::before {
|
|
content: '';
|
|
width: 4px;
|
|
height: 16px;
|
|
background: #667eea;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
.detail-content {
|
|
background: #f8f9fa;
|
|
padding: 15px;
|
|
border-radius: 6px;
|
|
border-left: 3px solid #667eea;
|
|
line-height: 1.8;
|
|
color: #444;
|
|
}
|
|
|
|
.risk-item {
|
|
background: white;
|
|
padding: 15px;
|
|
margin-bottom: 12px;
|
|
border-radius: 6px;
|
|
border: 1px solid #e0e0e0;
|
|
}
|
|
|
|
.risk-item h4 {
|
|
color: #d32f2f;
|
|
font-size: 15px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.risk-field {
|
|
margin-bottom: 10px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.risk-field strong {
|
|
color: #333;
|
|
display: inline-block;
|
|
min-width: 80px;
|
|
}
|
|
|
|
.risk-field p {
|
|
color: #555;
|
|
display: inline;
|
|
}
|
|
|
|
.scope-item {
|
|
background: white;
|
|
padding: 10px 15px;
|
|
margin-bottom: 8px;
|
|
border-radius: 4px;
|
|
border-left: 3px solid #667eea;
|
|
}
|
|
|
|
.permit-status {
|
|
display: inline-block;
|
|
padding: 4px 12px;
|
|
border-radius: 4px;
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
margin-right: 8px;
|
|
}
|
|
|
|
.status-active {
|
|
background: #e8f5e9;
|
|
color: #2e7d32;
|
|
}
|
|
|
|
.status-inactive {
|
|
background: #ffebee;
|
|
color: #c62828;
|
|
}
|
|
|
|
.loading {
|
|
display: inline-block;
|
|
width: 20px;
|
|
height: 20px;
|
|
border: 3px solid #f3f3f3;
|
|
border-top: 3px solid #667eea;
|
|
border-radius: 50%;
|
|
animation: spin 1s linear infinite;
|
|
margin-right: 10px;
|
|
}
|
|
|
|
@keyframes spin {
|
|
0% { transform: rotate(0deg); }
|
|
100% { transform: rotate(360deg); }
|
|
}
|
|
|
|
.error {
|
|
background: #ffebee;
|
|
color: #c62828;
|
|
padding: 15px;
|
|
border-radius: 6px;
|
|
margin: 15px 0;
|
|
border-left: 4px solid #c62828;
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
.content-area {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>🗃️ 数据库维护系统</h1>
|
|
<p>LawRisk 法律风险提示系统 - 数据库维护与查询工具</p>
|
|
</div>
|
|
|
|
<div class="step-indicator">
|
|
<div class="step active" id="step1">
|
|
<div class="step-number">1</div>
|
|
<div class="step-label">选择地区</div>
|
|
</div>
|
|
<div class="arrow">→</div>
|
|
<div class="step" id="step2">
|
|
<div class="step-number">2</div>
|
|
<div class="step-label">选择主题</div>
|
|
</div>
|
|
<div class="arrow">→</div>
|
|
<div class="step" id="step3">
|
|
<div class="step-number">3</div>
|
|
<div class="step-label">选择许可</div>
|
|
</div>
|
|
<div class="arrow">→</div>
|
|
<div class="step" id="step4">
|
|
<div class="step-number">4</div>
|
|
<div class="step-label">查看详情</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="content-area">
|
|
<div class="panel">
|
|
<h2>选择区域</h2>
|
|
<div class="selection-area">
|
|
<div id="regionList" class="item-list"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<h2>主题/许可详情</h2>
|
|
<div class="details-area">
|
|
<div class="empty-state">
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
<path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/>
|
|
</svg>
|
|
<p>请先选择地区以查看可用主题</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let currentRegion = null;
|
|
let currentTheme = null;
|
|
let currentPermit = null;
|
|
|
|
// 加载地区列表
|
|
async function loadRegions() {
|
|
try {
|
|
const response = await fetch('/fs-ai-asistant/api/workflow/lawrisk/admin/regions');
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
const regionList = document.getElementById('regionList');
|
|
regionList.innerHTML = '';
|
|
|
|
if (data.data.regions.length === 0) {
|
|
regionList.innerHTML = '<div class="error">未找到地区数据</div>';
|
|
return;
|
|
}
|
|
|
|
data.data.regions.forEach(region => {
|
|
const li = document.createElement('li');
|
|
li.innerHTML = `
|
|
<span class="item-name">${region.name}</span>
|
|
<span class="item-count">加载中...</span>
|
|
`;
|
|
li.onclick = () => selectRegion(region.id, region.name, li);
|
|
regionList.appendChild(li);
|
|
});
|
|
} else {
|
|
document.getElementById('regionList').innerHTML = `<div class="error">加载地区失败:${data.message}</div>`;
|
|
}
|
|
} catch (error) {
|
|
document.getElementById('regionList').innerHTML = `<div class="error">网络错误:${error.message}</div>`;
|
|
}
|
|
}
|
|
|
|
// 选择地区
|
|
async function selectRegion(regionId, regionName, element) {
|
|
// 更新UI
|
|
document.querySelectorAll('#regionList li').forEach(li => li.classList.remove('active'));
|
|
element.classList.add('active');
|
|
|
|
// 更新步骤指示器
|
|
updateStepIndicator(2);
|
|
|
|
currentRegion = { id: regionId, name: regionName };
|
|
currentTheme = null;
|
|
currentPermit = null;
|
|
|
|
// 清空并加载主题
|
|
const detailsArea = document.querySelector('.details-area');
|
|
detailsArea.innerHTML = '<div class="loading"></div>加载主题列表...';
|
|
|
|
try {
|
|
const response = await fetch(`/fs-ai-asistant/api/workflow/lawrisk/admin/themes?region=${regionId}`);
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
const themes = data.data.themes;
|
|
|
|
if (themes.length === 0) {
|
|
detailsArea.innerHTML = `<div class="error">地区 "${regionName}" 下没有可用的主题</div>`;
|
|
return;
|
|
}
|
|
|
|
// 创建主题列表
|
|
let html = '<div class="item-list">';
|
|
themes.forEach(theme => {
|
|
html += `
|
|
<li onclick="selectTheme('${theme.id}', '${theme.name}', '${theme.option_id}', this)">
|
|
<span class="item-name">${theme.name}</span>
|
|
<span class="item-count">点击查看许可</span>
|
|
</li>
|
|
`;
|
|
});
|
|
html += '</div>';
|
|
detailsArea.innerHTML = html;
|
|
} else {
|
|
detailsArea.innerHTML = `<div class="error">加载主题失败:${data.message}</div>`;
|
|
}
|
|
} catch (error) {
|
|
detailsArea.innerHTML = `<div class="error">网络错误:${error.message}</div>`;
|
|
}
|
|
}
|
|
|
|
// 选择主题
|
|
async function selectTheme(themeId, themeName, optionId, element) {
|
|
// 更新UI
|
|
document.querySelectorAll('.details-area .item-list li').forEach(li => li.classList.remove('active'));
|
|
element.classList.add('active');
|
|
|
|
// 更新步骤指示器
|
|
updateStepIndicator(3);
|
|
|
|
currentTheme = { id: themeId, name: themeName };
|
|
currentPermit = null;
|
|
|
|
// 加载许可列表
|
|
const detailsArea = document.querySelector('.details-area');
|
|
detailsArea.innerHTML = '<div class="loading"></div>加载许可列表...';
|
|
|
|
try {
|
|
const response = await fetch(`/fs-ai-asistant/api/workflow/lawrisk/admin/permits?region=${currentRegion.id}&theme=${themeId}`);
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
const permits = data.data.permits;
|
|
|
|
if (permits.length === 0) {
|
|
detailsArea.innerHTML = `<div class="error">主题 "${themeName}" 下没有可用的许可</div>`;
|
|
return;
|
|
}
|
|
|
|
// 创建许可列表
|
|
let html = '<div class="item-list">';
|
|
permits.forEach(permit => {
|
|
const riskCount = permit.risks ? permit.risks.length : 0;
|
|
html += `
|
|
<li onclick="selectPermit('${permit.id}', '${permit.name.replace(/'/g, "\\'")}', '${themeId}', this)">
|
|
<span class="item-name">${permit.name}</span>
|
|
<span class="item-count">${riskCount} 个风险</span>
|
|
</li>
|
|
`;
|
|
});
|
|
html += '</div>';
|
|
detailsArea.innerHTML = html;
|
|
} else {
|
|
detailsArea.innerHTML = `<div class="error">加载许可失败:${data.message}</div>`;
|
|
}
|
|
} catch (error) {
|
|
detailsArea.innerHTML = `<div class="error">网络错误:${error.message}</div>`;
|
|
}
|
|
}
|
|
|
|
// 选择许可
|
|
async function selectPermit(permitId, permitName, themeId, element) {
|
|
// 更新UI
|
|
document.querySelectorAll('.details-area .item-list li').forEach(li => li.classList.remove('active'));
|
|
element.classList.add('active');
|
|
|
|
// 更新步骤指示器
|
|
updateStepIndicator(4);
|
|
|
|
currentPermit = { id: permitId, name: permitName };
|
|
|
|
// 加载许可详情
|
|
const detailsArea = document.querySelector('.details-area');
|
|
detailsArea.innerHTML = '<div class="loading"></div>加载许可详情...';
|
|
|
|
try {
|
|
const response = await fetch(`/fs-ai-asistant/api/workflow/lawrisk/admin/permit-details?region=${currentRegion.id}&theme=${themeId}&permit=${permitId}`);
|
|
const data = await response.json();
|
|
|
|
if (data.success) {
|
|
renderPermitDetails(data.data.permit);
|
|
} else {
|
|
detailsArea.innerHTML = `<div class="error">加载详情失败:${data.message}</div>`;
|
|
}
|
|
} catch (error) {
|
|
detailsArea.innerHTML = `<div class="error">网络错误:${error.message}</div>`;
|
|
}
|
|
}
|
|
|
|
// 渲染许可详情
|
|
function renderPermitDetails(permit) {
|
|
const detailsArea = document.querySelector('.details-area');
|
|
let html = '<div class="details-content">';
|
|
|
|
// 许可基本信息
|
|
html += `
|
|
<div class="detail-section">
|
|
<h3>许可信息</h3>
|
|
<div class="detail-content">
|
|
<p><strong>许可名称:</strong>${permit.name}</p>
|
|
${permit.permit_status ? `<p style="margin-top: 10px;"><strong>许可状态:</strong><span class="permit-status ${permit.permit_status === 'active' ? 'status-active' : 'status-inactive'}">${permit.permit_status}</span></p>` : ''}
|
|
${permit.subitem_summary ? `<p style="margin-top: 10px;"><strong>子项说明:</strong>${permit.subitem_summary}</p>` : ''}
|
|
${permit.responsible_contact ? `<p style="margin-top: 10px;"><strong>负责部门:</strong>${permit.responsible_contact}</p>` : ''}
|
|
${permit.jurisdiction_scope ? `<p style="margin-top: 10px;"><strong>管辖范围:</strong>${permit.jurisdiction_scope}</p>` : ''}
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
// 经营范围
|
|
if (permit.business_scopes && permit.business_scopes.length > 0) {
|
|
html += '<div class="detail-section"><h3>经营范围</h3><div class="detail-content">';
|
|
permit.business_scopes.forEach(scope => {
|
|
html += `<div class="scope-item">${scope.description}</div>`;
|
|
});
|
|
html += '</div></div>';
|
|
}
|
|
|
|
// 法律风险
|
|
if (permit.risks && permit.risks.length > 0) {
|
|
html += '<div class="detail-section"><h3>法律风险</h3><div class="detail-content">';
|
|
permit.risks.forEach(risk => {
|
|
html += `
|
|
<div class="risk-item">
|
|
<h4>风险 ${risk.id}</h4>
|
|
${risk.risk_content ? `<div class="risk-field"><strong>风险内容:</strong><p>${risk.risk_content}</p></div>` : ''}
|
|
${risk.legal_basis ? `<div class="risk-field"><strong>法律依据:</strong><p>${risk.legal_basis}</p></div>` : ''}
|
|
${risk.document_no ? `<div class="risk-field"><strong>文件编号:</strong><p>${risk.document_no}</p></div>` : ''}
|
|
${risk.summary ? `<div class="risk-field"><strong>摘要:</strong><div style="margin-top: 5px;">${risk.summary}</div></div>` : ''}
|
|
</div>
|
|
`;
|
|
});
|
|
html += '</div></div>';
|
|
} else {
|
|
html += `
|
|
<div class="detail-section">
|
|
<h3>法律风险</h3>
|
|
<div class="detail-content">
|
|
<p style="color: #999;">暂无法律风险信息</p>
|
|
</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
html += '</div>';
|
|
detailsArea.innerHTML = html;
|
|
}
|
|
|
|
// 更新步骤指示器
|
|
function updateStepIndicator(step) {
|
|
for (let i = 1; i <= 4; i++) {
|
|
const stepElement = document.getElementById(`step${i}`);
|
|
if (i <= step) {
|
|
stepElement.classList.add('active');
|
|
} else {
|
|
stepElement.classList.remove('active');
|
|
}
|
|
}
|
|
}
|
|
|
|
// 页面加载时初始化
|
|
window.addEventListener('DOMContentLoaded', () => {
|
|
loadRegions();
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|