ai-chatbot/vendor/zoo-modeling-app/HicadManufacturingLauncher.tsx.template

149 lines
4.3 KiB
Plaintext

import {
Component,
lazy,
Suspense,
useEffect,
useState,
type ErrorInfo,
type ReactNode,
} from 'react'
const ManufacturingPanel = lazy(() =>
import('./HicadManufacturingPanel').then((module) => ({
default: module.HicadManufacturingPanel,
}))
)
class ManufacturingBoundary extends Component<
{
children: ReactNode
onClose: () => void
},
{ failed: boolean }
> {
state = { failed: false }
static getDerivedStateFromError() {
return { failed: true }
}
componentDidCatch(error: unknown, info: ErrorInfo) {
console.error('[HiCAD Manufacturing] Extension failed safely', error, info)
}
render() {
if (!this.state.failed) return this.props.children
return (
<div
className="fixed inset-0 z-[100] grid place-items-center bg-black/50 p-4"
role="dialog"
aria-modal="true"
aria-label="工程工具加载失败"
>
<div className="w-full max-w-md border border-chalkboard-30 bg-chalkboard-10 p-6 shadow-2xl dark:border-chalkboard-70 dark:bg-chalkboard-100">
<h2 className="text-lg font-semibold">工程工具暂时无法打开</h2>
<p className="mt-2 text-sm text-chalkboard-60 dark:text-chalkboard-40">
HiCAD 主编辑器没有受到影响。关闭后可以继续建模并稍后重试。
</p>
<button
type="button"
className="mt-5 h-9 bg-chalkboard-100 px-4 text-sm font-medium text-chalkboard-10 dark:bg-chalkboard-10 dark:text-chalkboard-100"
onClick={this.props.onClose}
>
关闭
</button>
</div>
</div>
)
}
}
export function HicadManufacturingLauncher({
projectName,
}: {
projectName: string
}) {
const [active, setActive] = useState(false)
const [triggerPosition, setTriggerPosition] = useState({
left: 16,
bottom: 48,
})
useEffect(() => {
const updateTriggerPosition = () => {
const canvas = [...document.querySelectorAll('canvas')]
.map((element) => ({
element,
rect: element.getBoundingClientRect(),
}))
.filter(({ rect }) => rect.width > 280 && rect.height > 220)
.sort(
(left, right) =>
right.rect.width * right.rect.height -
left.rect.width * left.rect.height
)[0]
if (!canvas) return
setTriggerPosition({
left: Math.round(canvas.rect.left + 16),
bottom: Math.round(
Math.max(window.innerHeight - canvas.rect.bottom + 16, 48)
),
})
}
const observer = new ResizeObserver(updateTriggerPosition)
const observeCanvases = () =>
document.querySelectorAll('canvas').forEach((canvas) => observer.observe(canvas))
const mutationObserver = new MutationObserver(() => {
observeCanvases()
updateTriggerPosition()
})
observeCanvases()
mutationObserver.observe(document.body, { childList: true, subtree: true })
window.addEventListener('resize', updateTriggerPosition)
updateTriggerPosition()
return () => {
observer.disconnect()
mutationObserver.disconnect()
window.removeEventListener('resize', updateTriggerPosition)
}
}, [])
return (
<>
<button
type="button"
data-testid="hicad-manufacturing-trigger"
onClick={() => setActive(true)}
style={triggerPosition}
className="fixed z-20 h-9 border border-chalkboard-30 bg-chalkboard-10 px-3 text-sm font-medium shadow-sm hover:bg-chalkboard-20 dark:border-chalkboard-70 dark:bg-chalkboard-90 dark:hover:bg-chalkboard-80"
>
工程出图
</button>
{active && (
<ManufacturingBoundary onClose={() => setActive(false)}>
<Suspense
fallback={
<div className="fixed inset-0 z-[100] grid place-items-center bg-black/50">
<div className="border border-chalkboard-30 bg-chalkboard-10 px-5 py-4 text-sm shadow-xl dark:border-chalkboard-70 dark:bg-chalkboard-100">
正在加载工程工具…
</div>
</div>
}
>
<ManufacturingPanel
hideTrigger
initialOpen
onRequestClose={() => setActive(false)}
projectName={projectName}
/>
</Suspense>
</ManufacturingBoundary>
)}
</>
)
}