Allow portrait signature confirmation
This commit is contained in:
@@ -59,41 +59,3 @@
|
||||
.signature-overlay-actions {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.signature-overlay-rotate {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 24px;
|
||||
gap: 14px;
|
||||
background: #f8fafc;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.signature-overlay-rotate-icon {
|
||||
font-size: 64px;
|
||||
color: #1677ff;
|
||||
animation: signature-rotate-hint 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes signature-rotate-hint {
|
||||
0%, 100% { transform: rotate(0deg); }
|
||||
50% { transform: rotate(90deg); }
|
||||
}
|
||||
|
||||
.signature-overlay-rotate-text {
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
color: #1f2937;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.signature-overlay-rotate-hint {
|
||||
font-size: 13px;
|
||||
color: #6b7280;
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { Button } from 'antd';
|
||||
import { RotateRightOutlined } from '@ant-design/icons';
|
||||
import SignaturePad, { type SignaturePadHandle } from './SignaturePad';
|
||||
import './SignatureOverlay.css';
|
||||
|
||||
@@ -10,63 +9,18 @@ interface SignatureOverlayProps {
|
||||
onConfirm: (dataUrl: string) => void;
|
||||
}
|
||||
|
||||
const isLandscapeNow = () =>
|
||||
typeof window !== 'undefined' &&
|
||||
(window.matchMedia('(orientation: landscape)').matches ||
|
||||
window.innerWidth > window.innerHeight ||
|
||||
((window.visualViewport?.width ?? 0) > (window.visualViewport?.height ?? 0)) ||
|
||||
Math.abs(window.screen.orientation?.angle ?? 0) % 180 === 90);
|
||||
|
||||
function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps) {
|
||||
const padRef = useRef<SignaturePadHandle>(null);
|
||||
const [, setData] = useState('');
|
||||
const [landscape, setLandscape] = useState<boolean>(isLandscapeNow);
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
|
||||
const mq = window.matchMedia('(orientation: landscape)');
|
||||
const update = () => setLandscape(mq.matches || window.innerWidth > window.innerHeight);
|
||||
update();
|
||||
if (typeof mq.addEventListener === 'function') {
|
||||
mq.addEventListener('change', update);
|
||||
} else {
|
||||
mq.addListener(update);
|
||||
}
|
||||
window.addEventListener('resize', update);
|
||||
window.addEventListener('orientationchange', update);
|
||||
window.visualViewport?.addEventListener('resize', update);
|
||||
|
||||
const orientation = (screen as Screen & {
|
||||
orientation?: {
|
||||
lock?: (o: string) => Promise<void>;
|
||||
unlock?: () => void;
|
||||
addEventListener?: (type: 'change', listener: () => void) => void;
|
||||
removeEventListener?: (type: 'change', listener: () => void) => void;
|
||||
};
|
||||
}).orientation;
|
||||
orientation?.addEventListener?.('change', update);
|
||||
if (orientation?.lock) {
|
||||
orientation.lock('landscape').catch(() => {
|
||||
// ignore; iOS Safari and most browsers refuse outside fullscreen
|
||||
});
|
||||
}
|
||||
|
||||
const prevOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
|
||||
return () => {
|
||||
if (typeof mq.removeEventListener === 'function') {
|
||||
mq.removeEventListener('change', update);
|
||||
} else {
|
||||
mq.removeListener(update);
|
||||
}
|
||||
window.removeEventListener('resize', update);
|
||||
window.removeEventListener('orientationchange', update);
|
||||
window.visualViewport?.removeEventListener('resize', update);
|
||||
orientation?.removeEventListener?.('change', update);
|
||||
document.body.style.overflow = prevOverflow;
|
||||
orientation?.unlock?.();
|
||||
};
|
||||
}, [open]);
|
||||
|
||||
@@ -85,22 +39,7 @@ function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps)
|
||||
|
||||
return (
|
||||
<div className="signature-overlay" role="dialog" aria-modal="true">
|
||||
{!landscape && (
|
||||
<div className="signature-overlay-rotate">
|
||||
<RotateRightOutlined className="signature-overlay-rotate-icon" />
|
||||
<p className="signature-overlay-rotate-text">请将手机横置以开始签名</p>
|
||||
<p className="signature-overlay-rotate-hint">
|
||||
如果无法旋转,请检查手机是否锁定了竖屏方向
|
||||
</p>
|
||||
<Button onClick={onCancel}>取消</Button>
|
||||
</div>
|
||||
)}
|
||||
{/* SignaturePad stays mounted so its strokes survive accidental rotation flips */}
|
||||
<div
|
||||
className="signature-overlay-stage"
|
||||
style={{ visibility: landscape ? 'visible' : 'hidden' }}
|
||||
aria-hidden={!landscape}
|
||||
>
|
||||
<div className="signature-overlay-stage">
|
||||
<div className="signature-overlay-bar">
|
||||
<Button type="text" onClick={onCancel}>
|
||||
取消
|
||||
|
||||
@@ -259,7 +259,7 @@ function AftersalesConfirmPage() {
|
||||
>
|
||||
<EditOutlined />
|
||||
<span>点击此处签名</span>
|
||||
<small>将进入横屏签名页</small>
|
||||
<small>将进入签名页</small>
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user