66 lines
1.8 KiB
TypeScript
66 lines
1.8 KiB
TypeScript
import { useEffect, useRef, useState } from 'react';
|
|
import { Button } from 'antd';
|
|
import SignaturePad, { type SignaturePadHandle } from './SignaturePad';
|
|
import './SignatureOverlay.css';
|
|
|
|
interface SignatureOverlayProps {
|
|
open: boolean;
|
|
onCancel: () => void;
|
|
onConfirm: (dataUrl: string) => void;
|
|
}
|
|
|
|
function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps) {
|
|
const padRef = useRef<SignaturePadHandle>(null);
|
|
const [, setData] = useState('');
|
|
|
|
useEffect(() => {
|
|
if (!open) return;
|
|
|
|
const prevOverflow = document.body.style.overflow;
|
|
document.body.style.overflow = 'hidden';
|
|
|
|
return () => {
|
|
document.body.style.overflow = prevOverflow;
|
|
};
|
|
}, [open]);
|
|
|
|
if (!open) return null;
|
|
|
|
const handleClear = () => {
|
|
padRef.current?.clear();
|
|
setData('');
|
|
};
|
|
|
|
const handleConfirm = () => {
|
|
const pad = padRef.current;
|
|
if (!pad || pad.isEmpty()) return;
|
|
onConfirm(pad.getDataURL());
|
|
};
|
|
|
|
return (
|
|
<div className="signature-overlay" role="dialog" aria-modal="true">
|
|
<div className="signature-overlay-stage">
|
|
<div className="signature-overlay-bar">
|
|
<Button type="text" onClick={onCancel}>
|
|
取消
|
|
</Button>
|
|
<span className="signature-overlay-title">请在框内签名</span>
|
|
<Button type="text" onClick={handleClear}>
|
|
清除
|
|
</Button>
|
|
</div>
|
|
<div className="signature-overlay-pad">
|
|
<SignaturePad ref={padRef} onChange={setData} />
|
|
</div>
|
|
<div className="signature-overlay-actions">
|
|
<Button size="large" type="primary" block onClick={handleConfirm}>
|
|
保存签名
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default SignatureOverlay;
|