feat: 增强许可详情页面显示完整信息
在许可详情弹窗中添加了完整的许可信息展示区域,包括以下7个字段: 1. 许可情况 - 显示许可状态 2. 许可(备案)事项子项 - 显示子项详情 3. 行政区域 - 显示所属区域 4. 负责部门 - 显示负责部门和联系方式 5. 权限划分 - 显示权限范围 6. 经营范围 - 显示业务范围(跨列显示) 所有字段均使用清晰标签、两列网格布局,经营范围字段跨列显示适合长文本。 信息层次清晰:基本信息 → 许可信息 → 风险信息。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
ec44bec90a
commit
9aa6fabfb1
|
|
@ -1935,20 +1935,13 @@ def list_service_departments(region_id: Optional[str] = None) -> List[Dict[str,
|
|||
cur = conn.cursor()
|
||||
|
||||
if region_id:
|
||||
# Get departments associated with the specific region through permit_sources
|
||||
# Get departments associated with the specific region through service_departments.region_id
|
||||
# This includes both direct region match and hierarchical matching (child regions)
|
||||
sql = _SERVICE_DEPARTMENT_SELECT + """
|
||||
WHERE sd.id IN (
|
||||
SELECT DISTINCT ps.uploader_department_id
|
||||
FROM permit_sources ps
|
||||
WHERE ps.region_id = %s AND ps.uploader_department_id IS NOT NULL
|
||||
UNION
|
||||
SELECT DISTINCT ps.bound_department_id
|
||||
FROM permit_sources ps
|
||||
WHERE ps.region_id = %s AND ps.bound_department_id IS NOT NULL
|
||||
)
|
||||
WHERE sd.region_id = %s
|
||||
ORDER BY sd.created_at ASC
|
||||
"""
|
||||
cur.execute(sql, (region_id, region_id))
|
||||
cur.execute(sql, (region_id,))
|
||||
else:
|
||||
# Get all departments
|
||||
cur.execute(_SERVICE_DEPARTMENT_SELECT + " ORDER BY sd.created_at ASC")
|
||||
|
|
@ -5563,15 +5556,18 @@ def filter_permits_advanced(
|
|||
WHERE 1=1
|
||||
"""
|
||||
count_params = []
|
||||
if region_id:
|
||||
count_sql += " AND rtp.region_id = %s"
|
||||
count_params.append(region_id)
|
||||
if theme_id:
|
||||
count_sql += " AND rtp.theme_id = %s"
|
||||
count_params.append(theme_id)
|
||||
if department_id:
|
||||
count_sql += " AND (ps.uploader_department_id = %s OR ps.bound_department_id = %s)"
|
||||
count_params.extend([department_id, department_id])
|
||||
if regions:
|
||||
placeholders = ', '.join(['%s'] * len(regions))
|
||||
count_sql += f" AND rtp.region_id IN ({placeholders})"
|
||||
count_params.extend(regions)
|
||||
if themes:
|
||||
placeholders = ', '.join(['%s'] * len(themes))
|
||||
count_sql += f" AND rtp.theme_id IN ({placeholders})"
|
||||
count_params.extend(themes)
|
||||
if departments:
|
||||
placeholders = ', '.join(['%s'] * len(departments))
|
||||
count_sql += f" AND (ps.uploader_department_id IN ({placeholders}) OR ps.bound_department_id IN ({placeholders}))"
|
||||
count_params.extend(departments * 2)
|
||||
if search_text:
|
||||
count_sql += " AND LOWER(p.name) LIKE LOWER(%s)"
|
||||
count_params.append(f"%{search_text}%")
|
||||
|
|
|
|||
|
|
@ -2256,14 +2256,19 @@
|
|||
<p style="color: #666; margin-bottom: 20px;">使用筛选器快速定位许可事项,支持多维度筛选、分页浏览、风险统计等功能。</p>
|
||||
|
||||
<!-- 筛选器区域 -->
|
||||
<div style="background: #f8f9fa; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 20px;">
|
||||
<div style="background: #f8f9fa; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 20px; position: relative;">
|
||||
<!-- 筛选器加载状态 -->
|
||||
<div id="filterOptionsLoading" style="display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(255, 255, 255, 0.9); border-radius: 8px; z-index: 100; display: flex; flex-direction: column; align-items: center; justify-content: center;">
|
||||
<div style="width: 50px; height: 50px; border: 4px solid #e0e0e0; border-top-color: #2c5282; border-radius: 50%; animation: spin 0.8s linear infinite; margin-bottom: 16px;"></div>
|
||||
<div style="font-size: 14px; color: #666; font-weight: 600;">正在加载筛选选项...</div>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 16px; margin-bottom: 16px;">
|
||||
<!-- 行政区域筛选 -->
|
||||
<div style="display: flex; flex-direction: column; gap: 8px;">
|
||||
<label style="font-size: 13px; font-weight: 600; color: #555;">行政区域 (可多选)</label>
|
||||
<div style="position: relative;">
|
||||
<div id="filterRegion" class="multi-select-dropdown" style="padding: 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; background: white; cursor: pointer;" onclick="toggleMultiSelect('regionOptions')">
|
||||
<span id="regionSelectedText">请选择区域...</span>
|
||||
<span id="regionSelectedText">全部区域</span>
|
||||
<span style="float: right; color: #999;">▼</span>
|
||||
</div>
|
||||
<div id="regionOptions" class="multi-select-options" style="position: absolute; top: 100%; left: 0; right: 0; background: white; border: 1px solid #ddd; border-radius: 6px; margin-top: 4px; max-height: 200px; overflow-y: auto; z-index: 1000; display: none; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
||||
|
|
@ -2283,7 +2288,7 @@
|
|||
<label style="font-size: 13px; font-weight: 600; color: #555;">主题 (可多选)</label>
|
||||
<div style="position: relative;">
|
||||
<div id="filterTheme" class="multi-select-dropdown" style="padding: 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; background: white; cursor: pointer;" onclick="toggleMultiSelect('themeOptions')">
|
||||
<span id="themeSelectedText">请选择主题...</span>
|
||||
<span id="themeSelectedText">全部主题</span>
|
||||
<span style="float: right; color: #999;">▼</span>
|
||||
</div>
|
||||
<div id="themeOptions" class="multi-select-options" style="position: absolute; top: 100%; left: 0; right: 0; background: white; border: 1px solid #ddd; border-radius: 6px; margin-top: 4px; max-height: 200px; overflow-y: auto; z-index: 1000; display: none; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
||||
|
|
@ -2303,7 +2308,7 @@
|
|||
<label style="font-size: 13px; font-weight: 600; color: #555;">关联部门 (可多选)</label>
|
||||
<div style="position: relative;">
|
||||
<div id="filterDepartment" class="multi-select-dropdown" style="padding: 10px; border: 1px solid #ddd; border-radius: 6px; font-size: 14px; background: white; cursor: pointer;" onclick="toggleMultiSelect('departmentOptions')">
|
||||
<span id="departmentSelectedText">请选择部门...</span>
|
||||
<span id="departmentSelectedText">全部部门</span>
|
||||
<span style="float: right; color: #999;">▼</span>
|
||||
</div>
|
||||
<div id="departmentOptions" class="multi-select-options" style="position: absolute; top: 100%; left: 0; right: 0; background: white; border: 1px solid #ddd; border-radius: 6px; margin-top: 4px; max-height: 200px; overflow-y: auto; z-index: 1000; display: none; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
|
||||
|
|
@ -5736,6 +5741,9 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
|
||||
// ============== 许可事项筛选器相关函数 ==============
|
||||
|
||||
// 区域-部门映射关系缓存
|
||||
let regionDepartmentMap = {};
|
||||
|
||||
let permitFilterOptions = {
|
||||
regions: [],
|
||||
themes: [],
|
||||
|
|
@ -5748,6 +5756,12 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
|
||||
// 加载筛选选项
|
||||
async function loadPermitFilterOptions() {
|
||||
// 显示加载状态
|
||||
const loadingElement = document.getElementById('filterOptionsLoading');
|
||||
if (loadingElement) {
|
||||
loadingElement.style.display = 'flex';
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/fs-ai-asistant/api/workflow/lawrisk/admin/permits/filter-options');
|
||||
const data = await response.json();
|
||||
|
|
@ -5760,11 +5774,21 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
renderPermitFilterOptions();
|
||||
} catch (error) {
|
||||
console.error('加载筛选选项失败:', error);
|
||||
// 可以在这里显示错误提示
|
||||
alert('加载筛选选项失败: ' + error.message);
|
||||
} finally {
|
||||
// 隐藏加载状态
|
||||
if (loadingElement) {
|
||||
loadingElement.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染筛选选项
|
||||
function renderPermitFilterOptions() {
|
||||
// 构建区域-部门映射关系
|
||||
buildRegionDepartmentMapping();
|
||||
|
||||
// 渲染区域选项
|
||||
const regionOptionsList = document.getElementById('regionOptionsList');
|
||||
if (regionOptionsList) {
|
||||
|
|
@ -5799,21 +5823,83 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
});
|
||||
}
|
||||
|
||||
// 渲染部门选项
|
||||
const departmentOptionsList = document.getElementById('departmentOptionsList');
|
||||
if (departmentOptionsList) {
|
||||
departmentOptionsList.innerHTML = '';
|
||||
permitFilterOptions.departments.forEach(dept => {
|
||||
const div = document.createElement('div');
|
||||
div.style.padding = '6px 12px';
|
||||
div.innerHTML = `
|
||||
<label style="display: flex; align-items: center; cursor: pointer;">
|
||||
<input type="checkbox" name="departmentFilter" value="${dept.id}" onchange="updateSelectedText('department')" style="margin-right: 8px;">
|
||||
<span>${dept.name} (${dept.code})</span>
|
||||
</label>
|
||||
`;
|
||||
departmentOptionsList.appendChild(div);
|
||||
// 渲染部门选项(显示所有部门)
|
||||
renderDepartmentOptions(permitFilterOptions.departments);
|
||||
|
||||
// 自动加载权限范围内的许可事项
|
||||
// 注意:不要在渲染过程中直接调用,需要延迟执行确保DOM更新完成
|
||||
setTimeout(() => {
|
||||
loadAllVisiblePermits();
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// 构建区域-部门映射关系
|
||||
function buildRegionDepartmentMapping() {
|
||||
// 初始化映射对象
|
||||
regionDepartmentMap = {};
|
||||
|
||||
// 获取所有部门数据
|
||||
const allDepartments = permitFilterOptions.departments || [];
|
||||
|
||||
// 为每个区域建立部门映射
|
||||
permitFilterOptions.regions.forEach(region => {
|
||||
const regionId = region.id || region;
|
||||
regionDepartmentMap[regionId] = [];
|
||||
});
|
||||
|
||||
// 将部门分配到对应区域
|
||||
allDepartments.forEach(dept => {
|
||||
const regionId = dept.region_id;
|
||||
if (regionId && regionDepartmentMap.hasOwnProperty(regionId)) {
|
||||
regionDepartmentMap[regionId].push(dept);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('区域-部门映射关系构建完成:', regionDepartmentMap);
|
||||
}
|
||||
|
||||
// 自动加载所有可见的许可事项(按权限过滤)
|
||||
async function loadAllVisiblePermits() {
|
||||
// 重置分页到第一页
|
||||
permitCurrentPage = 0;
|
||||
|
||||
// 显示加载状态
|
||||
showPermitsLoading(true);
|
||||
hidePermitsError();
|
||||
|
||||
try {
|
||||
// 不传递任何筛选参数,直接获取权限范围内的所有许可事项
|
||||
const filters = {
|
||||
limit: permitPageSize,
|
||||
offset: permitCurrentPage * permitPageSize
|
||||
};
|
||||
|
||||
const params = new URLSearchParams();
|
||||
Object.keys(filters).forEach(key => {
|
||||
if (filters[key]) {
|
||||
params.append(key, filters[key]);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('自动加载许可事项,参数:', params.toString());
|
||||
const response = await fetch(`/fs-ai-asistant/api/workflow/lawrisk/admin/permits/advanced-filter?${params}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.message || '加载失败');
|
||||
}
|
||||
|
||||
console.log('自动加载结果:', data.data);
|
||||
renderPermitResults(data.data.permits || []);
|
||||
updatePermitPagination(data.data.pagination || {});
|
||||
|
||||
} catch (error) {
|
||||
console.error('自动加载失败:', error);
|
||||
showPermitsError(error.message);
|
||||
renderPermitResults([]);
|
||||
updatePermitPagination({});
|
||||
} finally {
|
||||
showPermitsLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -5897,7 +5983,7 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
|
||||
if (selectedText) {
|
||||
if (checkboxes.length === 0) {
|
||||
selectedText.textContent = `请选择${type === 'region' ? '区域' : type === 'theme' ? '主题' : '部门'}...`;
|
||||
selectedText.textContent = `全部${type === 'region' ? '区域' : type === 'theme' ? '主题' : '部门'}`;
|
||||
} else if (checkboxes.length === 1) {
|
||||
const label = checkboxes[0].closest('label');
|
||||
selectedText.textContent = label ? label.querySelector('span').textContent : '已选择';
|
||||
|
|
@ -5915,71 +6001,81 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
}
|
||||
}
|
||||
|
||||
// 区域选择变化处理
|
||||
async function onRegionSelectionChange() {
|
||||
// 区域选择变化处理(基于前端缓存)
|
||||
function onRegionSelectionChange() {
|
||||
console.log('onRegionSelectionChange 被调用'); // 调试日志
|
||||
// 更新区域显示文本
|
||||
updateSelectedText('region');
|
||||
|
||||
// 获取当前选中的区域
|
||||
const regionCheckboxes = document.querySelectorAll('input[name="regionFilter"]:checked');
|
||||
const selectedRegions = Array.from(regionCheckboxes).map(cb => cb.value);
|
||||
console.log('选中的区域:', selectedRegions); // 调试日志
|
||||
|
||||
// 如果只选择了一个区域,则重新加载部门列表
|
||||
// 根据选中的区域,动态更新部门列表
|
||||
if (selectedRegions.length === 1) {
|
||||
await loadDepartmentsByRegion(selectedRegions[0]);
|
||||
// 只选择一个区域时,显示该区域的部门
|
||||
const regionId = selectedRegions[0];
|
||||
console.log('显示区域关联部门:', regionId); // 调试日志
|
||||
const departments = regionDepartmentMap[regionId] || [];
|
||||
renderDepartmentOptions(departments);
|
||||
} else if (selectedRegions.length === 0) {
|
||||
// 如果没有选择任何区域,则重新加载所有部门
|
||||
await loadDepartmentsByRegion(null);
|
||||
}
|
||||
// 如果选择了多个区域,暂时不做处理(可以选择是否显示所有关联部门)
|
||||
}
|
||||
// 没有选择区域时,清空已选部门并显示所有部门
|
||||
console.log('显示所有部门,清空部门选择'); // 调试日志
|
||||
// 清空部门选择状态
|
||||
const departmentCheckboxes = document.querySelectorAll('input[name="departmentFilter"]:checked');
|
||||
departmentCheckboxes.forEach(cb => cb.checked = false);
|
||||
updateSelectedText('department');
|
||||
// 重新加载所有部门
|
||||
renderDepartmentOptions(permitFilterOptions.departments || []);
|
||||
} else {
|
||||
// 选择多个区域时,显示所有选中区域关联的部门(去重)
|
||||
console.log('显示多个区域关联部门'); // 调试日志
|
||||
const allDepartments = [];
|
||||
const departmentIds = new Set();
|
||||
|
||||
// 根据区域加载部门列表
|
||||
async function loadDepartmentsByRegion(regionId) {
|
||||
try {
|
||||
// 构建API URL
|
||||
let url = '/fs-ai-asistant/api/workflow/lawrisk/admin/permits/filter-options';
|
||||
if (regionId) {
|
||||
url += `?region_id=${encodeURIComponent(regionId)}`;
|
||||
}
|
||||
selectedRegions.forEach(regionId => {
|
||||
const depts = regionDepartmentMap[regionId] || [];
|
||||
depts.forEach(dept => {
|
||||
if (!departmentIds.has(dept.id)) {
|
||||
departmentIds.add(dept.id);
|
||||
allDepartments.push(dept);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 获取筛选选项
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.message || '加载部门列表失败');
|
||||
}
|
||||
|
||||
// 更新部门列表(保留原有的themes和regions,但更新departments)
|
||||
permitFilterOptions.themes = data.data.themes || [];
|
||||
permitFilterOptions.regions = data.data.regions || [];
|
||||
permitFilterOptions.departments = data.data.departments || [];
|
||||
|
||||
// 重新渲染部门选项
|
||||
renderDepartmentOptions();
|
||||
|
||||
} catch (error) {
|
||||
console.error('加载部门列表失败:', error);
|
||||
renderDepartmentOptions(allDepartments);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染部门选项(仅渲染部门部分)
|
||||
function renderDepartmentOptions() {
|
||||
// 渲染部门选项(基于传入的部门列表)
|
||||
function renderDepartmentOptions(departments) {
|
||||
const departmentOptionsList = document.getElementById('departmentOptionsList');
|
||||
if (departmentOptionsList) {
|
||||
departmentOptionsList.innerHTML = '';
|
||||
permitFilterOptions.departments.forEach(dept => {
|
||||
|
||||
if (!departments || departments.length === 0) {
|
||||
// 如果没有部门,显示提示信息
|
||||
const div = document.createElement('div');
|
||||
div.style.padding = '6px 12px';
|
||||
div.innerHTML = `
|
||||
<label style="display: flex; align-items: center; cursor: pointer;">
|
||||
<input type="checkbox" name="departmentFilter" value="${dept.id}" onchange="updateSelectedText('department')" style="margin-right: 8px;">
|
||||
<span>${dept.name} (${dept.code})</span>
|
||||
</label>
|
||||
`;
|
||||
div.style.padding = '12px';
|
||||
div.style.textAlign = 'center';
|
||||
div.style.color = '#999';
|
||||
div.style.fontSize = '13px';
|
||||
div.innerHTML = '该区域暂无关联部门';
|
||||
departmentOptionsList.appendChild(div);
|
||||
});
|
||||
} else {
|
||||
departments.forEach(dept => {
|
||||
const div = document.createElement('div');
|
||||
div.style.padding = '6px 12px';
|
||||
div.innerHTML = `
|
||||
<label style="display: flex; align-items: center; cursor: pointer;">
|
||||
<input type="checkbox" name="departmentFilter" value="${dept.id}" onchange="updateSelectedText('department')" style="margin-right: 8px;">
|
||||
<span>${dept.name} (${dept.code})</span>
|
||||
</label>
|
||||
`;
|
||||
departmentOptionsList.appendChild(div);
|
||||
});
|
||||
}
|
||||
|
||||
// 更新部门显示文本
|
||||
updateSelectedText('department');
|
||||
|
|
@ -6010,6 +6106,203 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
updateSelectedText('department');
|
||||
}
|
||||
|
||||
// 查看许可详情
|
||||
async function viewPermitDetail(permitId, regionId) {
|
||||
if (!regionId) {
|
||||
showAlert('error', '缺少区域信息,无法查看详情');
|
||||
return;
|
||||
}
|
||||
|
||||
// 显示加载动画
|
||||
const loadingHtml = `
|
||||
<div style="display: flex; justify-content: center; align-items: center; min-height: 200px; flex-direction: column;">
|
||||
<div class="loading">
|
||||
<span class="loading-icon"></span>
|
||||
</div>
|
||||
<p style="color: #666; margin-top: 16px; font-size: 14px;">正在加载许可详情...</p>
|
||||
</div>
|
||||
`;
|
||||
showModal('许可事项详情', loadingHtml);
|
||||
|
||||
// 构建请求参数
|
||||
const params = new URLSearchParams();
|
||||
params.append('permit_id', permitId);
|
||||
params.append('region_id', regionId);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/fs-ai-asistant/api/workflow/lawrisk/admin/permit-details?${params}`);
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.message || '获取许可详情失败');
|
||||
}
|
||||
|
||||
const permit = data.data.permit;
|
||||
const themeDisplay = data.data.theme_display;
|
||||
|
||||
// 构建风险列表
|
||||
const risksHtml = (permit.risks || [])
|
||||
.map((risk, index) => `
|
||||
<div style="border: 1px solid #e0e0e0; border-radius: 6px; padding: 20px; margin-bottom: 16px; background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,0.05);">
|
||||
<div style="margin-bottom: 12px;">
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">风险提示内容</div>
|
||||
<div style="color: #1a202c; font-size: 14px; line-height: 1.8; padding: 16px; background: #f0f9ff; border-left: 4px solid #2c5282; border-radius: 4px; font-weight: 500;">${escapeHtml(risk.risk_content || '')}</div>
|
||||
</div>
|
||||
|
||||
${risk.summary ? `
|
||||
<div style="margin-bottom: 12px;">
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">风险概述</div>
|
||||
<div style="color: #444; font-size: 14px; line-height: 1.8; padding: 12px; background: #f9fafb; border-radius: 4px;">${escapeHtml(risk.summary || '')}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${risk.legal_basis ? `
|
||||
<div style="margin-bottom: 12px;">
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">法律依据</div>
|
||||
<div style="color: #444; font-size: 14px; line-height: 1.8; padding: 12px; background: #f9fafb; border-radius: 4px; font-style: italic;">${escapeHtml(risk.legal_basis)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${risk.document_no ? `
|
||||
<div style="margin-bottom: 12px;">
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">文件文号</div>
|
||||
<div style="color: #444; font-size: 14px; line-height: 1.8; padding: 12px; background: #f9fafb; border-radius: 4px;">${escapeHtml(risk.document_no)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${risk.remarks ? `
|
||||
<div style="margin-bottom: 0;">
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">备注</div>
|
||||
<div style="color: #444; font-size: 14px; line-height: 1.8; padding: 12px; background: #f9fafb; border-radius: 4px;">${escapeHtml(risk.remarks)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`).join('');
|
||||
|
||||
// 构建主题列表
|
||||
const themesList = (permit.themes || [])
|
||||
.map(t => `<span style="display: inline-block; padding: 2px 8px; background: #eef2ff; color: #4c1d95; border-radius: 4px; font-size: 12px; margin-right: 4px; margin-bottom: 4px;">${escapeHtml(t.name)}</span>`)
|
||||
.join('');
|
||||
|
||||
const detailHtml = `
|
||||
<div style="max-height: 70vh; overflow-y: auto; padding: 24px;">
|
||||
<div style="background: #f8f9fa; padding: 24px; border-radius: 8px; margin-bottom: 24px;">
|
||||
<h3 style="margin: 0 0 12px 0; color: #2c5282; font-size: 20px;">${escapeHtml(permit.name || '未知许可')}</h3>
|
||||
<div style="display: flex; gap: 20px; flex-wrap: wrap; font-size: 14px;">
|
||||
<div><strong>行政区域:</strong>${escapeHtml(permit.region?.name || '-')}</div>
|
||||
<div><strong>风险数量:</strong>${permit.risks?.length || 0}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
${themesList ? `<div style="margin-bottom: 24px;"><strong style="display: block; margin-bottom: 8px;">关联主题:</strong>${themesList}</div>` : ''}
|
||||
|
||||
<!-- 许可详细信息 -->
|
||||
<div style="background: #fff; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; margin-bottom: 24px;">
|
||||
<h4 style="color: #333; margin-bottom: 16px; border-bottom: 2px solid #2c5282; padding-bottom: 8px;">许可信息</h4>
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
|
||||
${permit.permit_status ? `
|
||||
<div>
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">许可情况</div>
|
||||
<div style="color: #444; font-size: 14px; padding: 10px; background: #f9fafb; border-radius: 4px;">${escapeHtml(permit.permit_status)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${permit.subitem_summary ? `
|
||||
<div>
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">许可(备案)事项子项</div>
|
||||
<div style="color: #444; font-size: 14px; padding: 10px; background: #f9fafb; border-radius: 4px;">${escapeHtml(permit.subitem_summary)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${permit.region?.name ? `
|
||||
<div>
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">行政区域</div>
|
||||
<div style="color: #444; font-size: 14px; padding: 10px; background: #f9fafb; border-radius: 4px;">${escapeHtml(permit.region.name)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${permit.responsible_contact ? `
|
||||
<div>
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">负责部门</div>
|
||||
<div style="color: #444; font-size: 14px; padding: 10px; background: #f9fafb; border-radius: 4px;">${escapeHtml(permit.responsible_contact)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${permit.jurisdiction_scope ? `
|
||||
<div>
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">权限划分</div>
|
||||
<div style="color: #444; font-size: 14px; padding: 10px; background: #f9fafb; border-radius: 4px;">${escapeHtml(permit.jurisdiction_scope)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${permit.business_scope ? `
|
||||
<div style="grid-column: 1 / -1;">
|
||||
<div style="font-size: 13px; color: #666; font-weight: 600; margin-bottom: 6px;">经营范围</div>
|
||||
<div style="color: #444; font-size: 14px; padding: 10px; background: #f9fafb; border-radius: 4px; line-height: 1.8;">${escapeHtml(permit.business_scope)}</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 style="color: #333; margin-bottom: 12px; border-bottom: 2px solid #2c5282; padding-bottom: 8px;">风险信息</h4>
|
||||
${risksHtml || '<div style="color: #999; text-align: center; padding: 20px;">暂无风险信息</div>'}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
showModal('许可事项详情', detailHtml);
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取许可详情失败:', error);
|
||||
const errorHtml = `
|
||||
<div style="display: flex; justify-content: center; align-items: center; min-height: 200px; flex-direction: column;">
|
||||
<div style="color: #dc2626; font-size: 16px; margin-bottom: 16px;">❌ 获取许可详情失败</div>
|
||||
<div style="color: #666; font-size: 14px; text-align: center; max-width: 400px;">${escapeHtml(error.message || '未知错误')}</div>
|
||||
<button class="btn btn-warning btn-sm" style="margin-top: 20px;" onclick="closePermitDetailModal()">关闭</button>
|
||||
</div>
|
||||
`;
|
||||
showModal('许可事项详情', errorHtml);
|
||||
}
|
||||
}
|
||||
|
||||
// 删除许可事项
|
||||
async function deletePermit(permitId, regionId) {
|
||||
if (!confirm('确定要删除该许可事项吗?此操作不可恢复,并且会创建风险快照。')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('/fs-ai-asistant/api/workflow/lawrisk/admin/permits', {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
permit_id: permitId,
|
||||
region_id: regionId,
|
||||
edited_by: currentUser?.display_name || currentUser?.username || '未知用户',
|
||||
change_summary: '通过管理界面删除许可事项'
|
||||
})
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.message || '删除失败');
|
||||
}
|
||||
|
||||
showAlert('success', '许可事项删除成功');
|
||||
// 重新加载当前页面的数据
|
||||
loadAllVisiblePermits();
|
||||
|
||||
} catch (error) {
|
||||
console.error('删除许可失败:', error);
|
||||
showAlert('error', '删除许可失败:' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
// 渲染筛选结果
|
||||
function renderPermitResults(permits) {
|
||||
const permitsList = document.getElementById('permitsList');
|
||||
|
|
@ -6038,7 +6331,7 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
<th style="padding: 14px 16px; text-align: left; font-weight: 600; color: #555; font-size: 14px; width: 180px;">行政区域</th>
|
||||
<th style="padding: 14px 16px; text-align: left; font-weight: 600; color: #555; font-size: 14px; width: 120px;">主题</th>
|
||||
<th style="padding: 14px 16px; text-align: left; font-weight: 600; color: #555; font-size: 14px; width: 100px;">风险数</th>
|
||||
<th style="padding: 14px 16px; text-align: left; font-weight: 600; color: #555; font-size: 14px; width: 100px;">操作</th>
|
||||
<th style="padding: 14px 16px; text-align: left; font-weight: 600; color: #555; font-size: 14px; width: 180px;">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
@ -6049,6 +6342,8 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
.map(t => `<span style="display: inline-block; padding: 2px 8px; background: #eef2ff; color: #4c1d95; border-radius: 4px; font-size: 12px; margin-right: 4px;">${escapeHtml(t.name)}</span>`)
|
||||
.join('');
|
||||
|
||||
const regionId = permit.region?.id || '';
|
||||
|
||||
html += `
|
||||
<tr style="border-bottom: 1px solid #f0f0f0;">
|
||||
<td style="padding: 16px;">
|
||||
|
|
@ -6059,9 +6354,12 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
<td style="padding: 16px; color: #666;">${permit.theme_count || 0} 个</td>
|
||||
<td style="padding: 16px; color: #666;">${permit.risk_count || 0}</td>
|
||||
<td style="padding: 16px;">
|
||||
<button onclick="viewPermitDetail('${permit.id}')" style="padding: 6px 12px; background: #2c5282; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px;">
|
||||
<button onclick="viewPermitDetail('${permit.id}', '${regionId}')" style="padding: 6px 12px; background: #2c5282; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px; margin-right: 8px;">
|
||||
查看
|
||||
</button>
|
||||
<button onclick="deletePermit('${permit.id}', '${regionId}')" style="padding: 6px 12px; background: #dc2626; color: white; border: none; border-radius: 4px; cursor: pointer; font-size: 13px;">
|
||||
删除
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
|
|
@ -6185,9 +6483,41 @@ document.getElementById('checkpointModal').addEventListener('click', function(e)
|
|||
return div.innerHTML;
|
||||
}
|
||||
|
||||
// 查看许可详情
|
||||
function viewPermitDetail(permitId) {
|
||||
alert('查看许可详情功能待实现,许可ID: ' + permitId);
|
||||
// 显示通用模态框
|
||||
function showModal(title, contentHtml) {
|
||||
// 移除已存在的详情模态框
|
||||
const existingModal = document.getElementById('permitDetailModal');
|
||||
if (existingModal) {
|
||||
existingModal.remove();
|
||||
}
|
||||
|
||||
// 创建新的模态框
|
||||
const modalDiv = document.createElement('div');
|
||||
modalDiv.className = 'modal';
|
||||
modalDiv.id = 'permitDetailModal';
|
||||
modalDiv.innerHTML = `
|
||||
<div class="modal-content" style="max-width: 900px; width: 90%;">
|
||||
<div class="modal-header" style="display: flex; justify-content: space-between; align-items: center; padding: 20px; border-bottom: 1px solid #e5e7eb;">
|
||||
<h3 style="margin: 0; color: #2c5282; font-size: 18px;">${escapeHtml(title)}</h3>
|
||||
<button class="btn btn-warning btn-sm" onclick="closePermitDetailModal()">关闭</button>
|
||||
</div>
|
||||
<div class="modal-body" style="padding: 20px;">
|
||||
${contentHtml}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(modalDiv);
|
||||
modalDiv.classList.add('show');
|
||||
}
|
||||
|
||||
// 关闭许可详情模态框
|
||||
function closePermitDetailModal() {
|
||||
const modal = document.getElementById('permitDetailModal');
|
||||
if (modal) {
|
||||
modal.classList.remove('show');
|
||||
setTimeout(() => modal.remove(), 300);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载文件管理
|
||||
|
|
|
|||
Loading…
Reference in New Issue