8862887baa
新增充值订单查询、通用用户详情、钱包冻结与部分退款操作 接入微信V3退款申请、回调、主动查单、交易账单对账与安全诊断 新增退款占用、权益追回、异常欠账和消费限制事务 补齐Native支付SSE自动收口及退款编号与部分退款校验 同步SpacetimeDB schema、生成绑定、测试与项目文档
110 lines
2.9 KiB
TypeScript
110 lines
2.9 KiB
TypeScript
import {useCallback, useEffect, useRef, useState} from 'react';
|
|
|
|
interface AdminWriteConfirmOptions {
|
|
action: string;
|
|
target: string;
|
|
}
|
|
|
|
interface PendingConfirm extends AdminWriteConfirmOptions {
|
|
resolve: (confirmed: boolean) => void;
|
|
}
|
|
|
|
export function useAdminWriteConfirm() {
|
|
const [pendingConfirm, setPendingConfirm] = useState<PendingConfirm | null>(null);
|
|
const cancelButtonRef = useRef<HTMLButtonElement | null>(null);
|
|
|
|
const confirmWrite = useCallback((options: AdminWriteConfirmOptions) => {
|
|
return new Promise<boolean>((resolve) => {
|
|
setPendingConfirm((current) => {
|
|
if (current) {
|
|
current.resolve(false);
|
|
}
|
|
return {...options, resolve};
|
|
});
|
|
});
|
|
}, []);
|
|
|
|
const closeConfirm = useCallback(
|
|
(confirmed: boolean) => {
|
|
const current = pendingConfirm;
|
|
if (!current) {
|
|
return;
|
|
}
|
|
setPendingConfirm(null);
|
|
current.resolve(confirmed);
|
|
},
|
|
[pendingConfirm],
|
|
);
|
|
|
|
useEffect(() => {
|
|
if (!pendingConfirm) {
|
|
return;
|
|
}
|
|
|
|
cancelButtonRef.current?.focus();
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
if (event.key === 'Escape') {
|
|
event.preventDefault();
|
|
closeConfirm(false);
|
|
}
|
|
};
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [closeConfirm, pendingConfirm]);
|
|
|
|
const confirmDialog = pendingConfirm ? (
|
|
<div
|
|
aria-modal="true"
|
|
aria-labelledby="admin-write-confirm-title"
|
|
className="admin-confirm-backdrop"
|
|
role="dialog"
|
|
onMouseDown={(event) => {
|
|
if (event.target === event.currentTarget) {
|
|
closeConfirm(false);
|
|
}
|
|
}}
|
|
>
|
|
<section className="admin-confirm-panel">
|
|
<div className="admin-panel-heading">
|
|
<h3 id="admin-write-confirm-title">确认操作</h3>
|
|
<span>{pendingConfirm.action}</span>
|
|
</div>
|
|
<dl className="admin-info-list">
|
|
<div>
|
|
<dt>操作</dt>
|
|
<dd>{pendingConfirm.action}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>对象</dt>
|
|
<dd>{pendingConfirm.target}</dd>
|
|
</div>
|
|
</dl>
|
|
<div className="admin-confirm-warning">该操作会立即影响线上数据</div>
|
|
<div className="admin-confirm-actions">
|
|
<button
|
|
className="admin-secondary-button"
|
|
ref={cancelButtonRef}
|
|
type="button"
|
|
onClick={() => closeConfirm(false)}
|
|
>
|
|
取消
|
|
</button>
|
|
<button
|
|
className="admin-danger-button"
|
|
type="button"
|
|
onClick={() => closeConfirm(true)}
|
|
>
|
|
确认
|
|
</button>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
) : null;
|
|
|
|
return {
|
|
confirmWrite,
|
|
confirmDialog,
|
|
isConfirming: pendingConfirm !== null,
|
|
};
|
|
}
|