149 lines
4.3 KiB
Plaintext
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>
|
|
)}
|
|
</>
|
|
)
|
|
}
|