feat: 新增验收测试清单(199项24域)替代功能调查问卷; 修复工作台评分环文字重叠

- 新增 acceptance-test.html 交互式验收测试页面(验收人姓名/自动补全/自动统计/CSV+Excel下载)
- 新增 AcceptanceTestModal 组件, TopNav 中用验收测试弹窗替代 SurveyModal
- Settings 页问卷导出替换为验收测试结果导出(支持多验收人汇总MD)
- 修复 Dashboard 合规健康度评分环文字重叠: 圆环增大至w-32, 加overflow-hidden+truncate
This commit is contained in:
selfrelease
2026-08-02 09:22:51 +08:00
parent 787897e6d3
commit 68ebe6a4ff
7 changed files with 2619 additions and 96 deletions
@@ -0,0 +1,57 @@
import { useEffect, useState } from 'react'
import { X } from 'lucide-react'
/**
* 验收测试弹窗 — 全屏加载 acceptance-test.html,支持验收人姓名、自动统计、按姓名保存、下载结果
*/
export default function AcceptanceTestModal({ open, onClose }: { open: boolean; onClose: () => void }) {
const [show, setShow] = useState(false)
useEffect(() => {
if (open) {
document.body.style.overflow = 'hidden'
requestAnimationFrame(() => setShow(true))
} else {
document.body.style.overflow = ''
setShow(false)
}
return () => {
document.body.style.overflow = ''
}
}, [open])
if (!open) return null
return (
<div className="fixed inset-0 z-50 flex items-center justify-center">
<div
className={`fixed inset-0 bg-black/50 transition-opacity duration-200 ${show ? 'opacity-100' : 'opacity-0'}`}
onClick={onClose}
/>
<div
className={`relative bg-white rounded-lg shadow-xl w-full h-[95vh] transition-all duration-200 ${
show ? 'opacity-100 scale-100' : 'opacity-0 scale-95'
}`}
>
{/* 弹窗头部 */}
<div className="flex items-center justify-between px-4 py-2.5 border-b border-gray-200">
<h3 className="font-medium text-gray-900 text-sm"></h3>
<button
onClick={onClose}
className="text-gray-500 hover:text-gray-700 p-1 rounded-md hover:bg-gray-100 transition-colors"
aria-label="关闭"
>
<X className="w-4 h-4" />
</button>
</div>
{/* iframe 加载验收测试页面 */}
<iframe
src="/acceptance-test.html"
className="w-full"
style={{ height: 'calc(95vh - 42px)', border: 'none' }}
title="验收测试清单"
/>
</div>
</div>
)
}
+5 -5
View File
@@ -7,7 +7,7 @@ import { dashboardApi } from '../../lib/api-services'
import Breadcrumb from './Breadcrumb'
import HelpModal from '../HelpModal'
import PortalQRModal from '../PortalQRModal'
import SurveyModal from '../SurveyModal'
import AcceptanceTestModal from '../AcceptanceTestModal'
export default function TopNav({ onMenuClick }: { onMenuClick?: () => void }) {
const navigate = useNavigate()
@@ -15,7 +15,7 @@ export default function TopNav({ onMenuClick }: { onMenuClick?: () => void }) {
const [menuOpen, setMenuOpen] = useState(false)
const [helpOpen, setHelpOpen] = useState(false)
const [portalQROpen, setPortalQROpen] = useState(false)
const [surveyOpen, setSurveyOpen] = useState(false)
const [acceptanceOpen, setAcceptanceOpen] = useState(false)
const { data: dashboardData } = useQuery<any>({
queryKey: ['dashboard'],
@@ -58,13 +58,13 @@ export default function TopNav({ onMenuClick }: { onMenuClick?: () => void }) {
</button>
<HelpModal open={helpOpen} onClose={() => setHelpOpen(false)} />
<button
onClick={() => setSurveyOpen(true)}
onClick={() => setAcceptanceOpen(true)}
className="p-1.5 rounded-md hover:bg-gray-100"
aria-label="功能调查"
aria-label="验收测试"
>
<ClipboardList className="w-4 h-4 text-gray-600" />
</button>
<SurveyModal open={surveyOpen} onClose={() => setSurveyOpen(false)} />
<AcceptanceTestModal open={acceptanceOpen} onClose={() => setAcceptanceOpen(false)} />
<Link to="/settings" className="p-1.5 rounded-md hover:bg-gray-100" aria-label="设置">
<SettingsIcon className="w-4 h-4 text-gray-600" />
</Link>