<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>审核结论弹窗</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/css/font-awesome.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#1890ff',
border: '#d9d9d9',
background: 'rgba(0, 0, 0, 0.5)'
}
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.modal-shadow {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.radio-checked {
border-color: #1890ff;
color: #1890ff;
background-color: #e6f7ff;
}
.checkbox-checked {
border-color: #1890ff;
background-color: #1890ff;
}
.other-input:focus {
outline: none;
border-color: #1890ff;
box-shadow: 0 0 0 1px #1890ff;
}
}
</style>
</head>
<body class="bg-gray-100 flex items-center justify-center h-screen">
<!-- 背景遮罩 -->
<div id="modalOverlay" class="fixed inset-0 bg-background flex items-center justify-center z-50">
<!-- 弹窗容器 -->
<div id="reviewModal" class="bg-white rounded modal-shadow w-[520px] max-w-[90%]">
<!-- 弹窗头部 -->
<div class="flex justify-between items-center px-6 py-4 border-b border-border">
<h2 class="text-lg font-medium">审核结论</h2>
<button id="closeModal" class="text-gray-500 hover:text-gray-700 focus:outline-none">
<i class="fa fa-times"></i>
</button>
</div>
<!-- 弹窗内容 -->
<div class="p-6">
<!-- 审核结论选项 -->
<div class="mb-6">
<label class="block text-base font-medium mb-3">审核结论:</label>
<div class="flex space-x-4">
<label class="inline-flex items-center cursor-pointer">
<input type="radio" name="reviewResult" value="pass" class="hidden peer" checked>
<span class="px-4 py-2 border border-border rounded text-center peer-checked:radio-checked transition-all duration-200">通过</span>
</label>
<label class="inline-flex items-center cursor-pointer">
<input type="radio" name="reviewResult" value="reject" class="hidden peer">
<span class="px-4 py-2 border border-border rounded text-center peer-checked:radio-checked transition-all duration-200">拒绝</span>
</label>
</div>
</div>
<!-- 分类选择 -->
<div class="mb-4">
<div class="mb-2">
<label class="block text-base font-medium">分类选择:</label>
</div>
<div id="categoryContainer" class="space-y-3">
<!-- 分类内容将通过JavaScript动态生成 -->
</div>
</div>
<!-- 审核备注 -->
<div>
<label for="reviewRemark" class="block text-base font-medium mb-3">审核备注:</label>
<textarea id="reviewRemark" rows="4" class="w-full px-3 py-2 border border-border rounded focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent resize-none" placeholder="请输入审核备注..."></textarea>
</div>
</div>
<!-- 弹窗底部 -->
<div class="flex justify-end px-6 py-4 border-t border-border">
<button id="cancelBtn" class="px-4 py-2 text-gray-700 bg-gray-100 rounded hover:bg-gray-200 focus:outline-none mr-3">取消</button>
<button id="confirmBtn" class="px-4 py-2 text-white bg-primary rounded hover:bg-blue-600 focus:outline-none">确定</button>
</div>
</div>
</div>
<script>
// 获取DOM元素
const modalOverlay = document.getElementById('modalOverlay');
const closeModal = document.getElementById('closeModal');
const cancelBtn = document.getElementById('cancelBtn');
const confirmBtn = document.getElementById('confirmBtn');
const reviewResultRadios = document.querySelectorAll('input[name="reviewResult"]');
const reviewRemark = document.getElementById('reviewRemark');
const categoryContainer = document.getElementById('categoryContainer');
// 分类数据
const categoryData = [
{
id: 'certificate',
name: '证件',
subCategories: [
{ id: 'id_card', name: '身份证' },
{ id: 'hukou', name: '户口本' },
{ id: 'passport', name: '护照' },
{ id: 'mainland_permit', name: '港澳大陆通行证' },
{ id: 'other_certificate', name: '其他', isOther: true }
]
},
{
id: 'diagnosis',
name: '诊断证明',
subCategories: [
{ id: 'nsclc', name: '非小细胞肺癌(NSCLC)' },
{ id: 'sclc', name: '小细胞肺癌(SCLC)' },
{ id: 'other_cancer', name: '其他恶性肿瘤' },
{ id: 'other_diagnosis', name: '其他', isOther: true }
]
},
{
id: 'prescription',
name: '用药处方',
subCategories: [
{ id: 'valid_prescription', name: '有效资质大陆医疗机构处方' },
{ id: 'digital_prescription', name: '电子版处方' },
{ id: 'other_prescription', name: '其他处方' },
{ id: 'other_medication', name: '其他', isOther: true }
]
},
{
id: 'her2_test',
name: 'HER2基因检测报告',
subCategories: [
{ id: 'her2_positive', name: 'HER2阳性' },
{ id: 'her2_negative', name: 'HER2阴性' },
{ id: 'equivocal_result', name: '结果不确定' },
{ id: 'other_her2', name: '其他', isOther: true }
]
},
{
id: 'medical_record',
name: '病历',
subCategories: [
{ id: 'inpatient_record', name: '住院病历' },
{ id: 'outpatient_record', name: '门诊病历' },
{ id: 'surgery_record', name: '手术记录' },
{ id: 'other_record', name: '其他', isOther: true }
]
},
{
id: 'other',
name: '其他',
isOtherCategory: true
}
];
// 渲染分类
function renderCategories() {
categoryContainer.innerHTML = '';
categoryData.forEach(category => {
const categoryDiv = document.createElement('div');
categoryDiv.className = 'category-item';
// 大类
const categoryHeader = document.createElement('div');
categoryHeader.className = 'flex items-center mb-1';
// 如果是"其他"大类,直接显示输入框
if (category.isOtherCategory) {
categoryHeader.innerHTML = `
<label class="inline-flex items-center cursor-pointer w-full">
<input type="checkbox" name="category" value="${category.id}" class="hidden peer category-checkbox">
<span class="w-4 h-4 border border-border rounded flex items-center justify-center mr-2 peer-checked:checkbox-checked transition-all duration-200">
<i class="fa fa-check text-white text-xs opacity-0 peer-checked:opacity-100"></i>
</span>
<span class="font-medium">${category.name}</span>
<input type="text" class="ml-2 px-2 py-0.5 border border-border rounded text-sm hidden other-category-input" placeholder="请输入其他类别内容" data-category="${category.id}" style="width: 200px;">
</label>
`;
categoryDiv.appendChild(categoryHeader);
} else {
// 创建Popover容器
const popoverContainer = document.createElement('div');
popoverContainer.className = 'relative inline-block';
// 大类标签
const categoryLabel = `
<label class="inline-flex items-center cursor-pointer">
<input type="checkbox" name="category" value="${category.id}" class="hidden peer category-checkbox">
<span class="w-4 h-4 border border-border rounded flex items-center justify-center mr-2 peer-checked:checkbox-checked transition-all duration-200">
<i class="fa fa-check text-white text-xs opacity-0 peer-checked:opacity-100"></i>
</span>
<span class="font-medium flex items-center">
${category.name}
<i class="fa fa-info-circle ml-1 text-gray-400 hover:text-primary cursor-help"></i>
</span>
</label>
`;
// Popover内容
const popoverContent = `
<div class="absolute left-0 mt-1 bg-white border border-gray-200 rounded-md shadow-lg p-3 w-64 z-10 hidden popover-content">
<div class="font-medium text-sm mb-2">小类列表:</div>
<div class="space-y-1">
${category.subCategories.map(subCategory => `
<div class="text-sm py-1 px-2 hover:bg-gray-100 rounded">${subCategory.name}</div>
`).join('')}
</div>
</div>
`;
popoverContainer.innerHTML = categoryLabel + popoverContent;
categoryHeader.appendChild(popoverContainer);
// 先添加大类标题
categoryDiv.appendChild(categoryHeader);
// 文本录入框容器
const textInputContainer = document.createElement('div');
textInputContainer.className = 'ml-6 hidden';
// 文本录入框
const textInputWrapper = document.createElement('div');
textInputWrapper.className = 'w-full';
textInputWrapper.innerHTML = `
<textarea class="w-full px-3 py-2 border border-border rounded text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent resize-none category-text-input"
rows="3" placeholder="请输入详细内容..."
data-category="${category.id}"></textarea>
`;
textInputContainer.appendChild(textInputWrapper);
categoryDiv.appendChild(textInputContainer);
}
categoryContainer.appendChild(categoryDiv);
});
// 添加事件监听器
addCategoryEventListeners();
}
// 添加分类事件监听器
function addCategoryEventListeners() {
// 大类复选框事件
document.querySelectorAll('.category-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', function() {
const categoryId = this.value;
const categoryItem = this.closest('.category-item');
const textInputContainer = categoryItem.querySelector('.ml-6');
// 处理"其他"大类
const otherCategoryInput = this.closest('label').querySelector('.other-category-input');
if (otherCategoryInput) {
if (this.checked) {
otherCategoryInput.classList.remove('hidden');
otherCategoryInput.focus();
} else {
otherCategoryInput.classList.add('hidden');
otherCategoryInput.value = '';
}
return;
}
// 处理普通大类
if (textInputContainer) {
if (this.checked) {
textInputContainer.classList.remove('hidden');
// 聚焦到文本输入框
const textInput = textInputContainer.querySelector('.category-text-input');
if (textInput) {
textInput.focus();
}
} else {
textInputContainer.classList.add('hidden');
// 清空文本输入框
const textInput = textInputContainer.querySelector('.category-text-input');
if (textInput) {
textInput.value = '';
}
}
}
});
});
// 添加Popover事件
document.querySelectorAll('.fa-info-circle').forEach(icon => {
const popoverContainer = icon.closest('.relative');
const popoverContent = popoverContainer.querySelector('.popover-content');
// 鼠标悬停显示Popover
icon.addEventListener('mouseenter', function() {
popoverContent.classList.remove('hidden');
});
// 鼠标离开隐藏Popover
icon.addEventListener('mouseleave', function() {
// 延迟隐藏,让用户有时间移动到Popover上
setTimeout(() => {
// 检查鼠标是否在Popover内容上
if (!popoverContent.matches(':hover')) {
popoverContent.classList.add('hidden');
}
}, 100);
});
// 确保Popover在容器内悬停时也保持显示
popoverContent.addEventListener('mouseenter', function() {
this.classList.remove('hidden');
});
popoverContent.addEventListener('mouseleave', function() {
this.classList.add('hidden');
});
});
}
// 初始化渲染分类
renderCategories();
// 重置表单函数
function resetForm() {
// 重置表单
reviewResultRadios[0].checked = true;
reviewRemark.value = '';
// 重置分类选择
document.querySelectorAll('.category-checkbox').forEach(checkbox => {
checkbox.checked = false;
});
document.querySelectorAll('.ml-6').forEach(container => {
container.classList.add('hidden');
});
document.querySelectorAll('.other-category-input, .category-text-input').forEach(input => {
input.value = '';
});
}
// 关闭按钮点击事件 - 仅重置表单
closeModal.addEventListener('click', resetForm);
cancelBtn.addEventListener('click', resetForm);
// 确认按钮点击事件
confirmBtn.addEventListener('click', function() {
// 获取选中的审核结论
let selectedResult = '';
reviewResultRadios.forEach(radio => {
if (radio.checked) {
selectedResult = radio.value;
}
});
// 获取审核备注
const remark = reviewRemark.value.trim();
// 验证是否填写了审核备注
if (selectedResult === 'reject' && !remark) {
alert('拒绝时必须填写审核备注!');
return;
}
// 获取选中的分类
const selectedCategories = [];
document.querySelectorAll('.category-checkbox:checked').forEach(checkbox => {
const categoryId = checkbox.value;
const category = categoryData.find(cat => cat.id === categoryId);
if (category) {
// 处理"其他"大类
if (category.isOtherCategory) {
const otherCategoryInput = checkbox.closest('label').querySelector('.other-category-input');
if (otherCategoryInput && otherCategoryInput.value.trim()) {
selectedCategories.push({
id: category.id,
name: category.name,
otherText: otherCategoryInput.value.trim()
});
}
return;
}
// 处理普通大类
const textInputContainer = checkbox.closest('.category-item').querySelector('.ml-6');
if (textInputContainer) {
const textInput = textInputContainer.querySelector('.category-text-input');
if (textInput && textInput.value.trim()) {
selectedCategories.push({
id: category.id,
name: category.name,
textContent: textInput.value.trim()
});
}
}
}
});
// 模拟提交数据
console.log('审核结论:', selectedResult);
console.log('审核备注:', remark);
console.log('选中的分类:', selectedCategories);
// 显示提交成功信息
alert('审核已提交!');
// 关闭弹窗
closeModalFunc();
});
// 审核结论单选框切换事件
reviewResultRadios.forEach(radio => {
radio.addEventListener('change', function() {
// 如果选择了拒绝,自动聚焦到备注文本框
if (this.value === 'reject') {
reviewRemark.focus();
}
});
});
</script>
</body>
</html>
index.html
style.css
index.js
index.html