2025-10-13 12:26:10 +08:00
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
|
import {
|
|
|
|
|
|
Dialog,
|
|
|
|
|
|
DialogTitle,
|
|
|
|
|
|
DialogContent,
|
|
|
|
|
|
DialogActions,
|
|
|
|
|
|
Button,
|
|
|
|
|
|
Typography,
|
|
|
|
|
|
Box,
|
|
|
|
|
|
IconButton,
|
|
|
|
|
|
} from '@mui/material';
|
|
|
|
|
|
import {
|
|
|
|
|
|
Close as CloseIcon,
|
|
|
|
|
|
Info as InfoIcon,
|
|
|
|
|
|
CheckCircle as SuccessIcon,
|
|
|
|
|
|
Warning as WarningIcon,
|
|
|
|
|
|
Error as ErrorIcon,
|
|
|
|
|
|
Help as ConfirmIcon,
|
|
|
|
|
|
} from '@mui/icons-material';
|
2025-10-29 16:40:20 +08:00
|
|
|
|
import { useTranslation } from 'react-i18next';
|
2025-10-13 12:26:10 +08:00
|
|
|
|
import { type IDialogInstance } from '../../interfaces/common';
|
|
|
|
|
|
|
|
|
|
|
|
interface DialogComponentProps {
|
|
|
|
|
|
dialog: IDialogInstance;
|
|
|
|
|
|
onClose: (result: boolean) => void;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const DialogComponent: React.FC<DialogComponentProps> = ({ dialog, onClose }) => {
|
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
2025-10-29 16:40:20 +08:00
|
|
|
|
const { t } = useTranslation();
|
2025-10-13 12:26:10 +08:00
|
|
|
|
const { config } = dialog;
|
|
|
|
|
|
|
|
|
|
|
|
// 获取对话框图标
|
|
|
|
|
|
const getDialogIcon = () => {
|
|
|
|
|
|
const iconProps = { sx: { fontSize: 24, mr: 1 } };
|
|
|
|
|
|
|
|
|
|
|
|
switch (config.type) {
|
|
|
|
|
|
case 'info':
|
|
|
|
|
|
return <InfoIcon {...iconProps} color="info" />;
|
|
|
|
|
|
case 'success':
|
|
|
|
|
|
return <SuccessIcon {...iconProps} color="success" />;
|
|
|
|
|
|
case 'warning':
|
|
|
|
|
|
return <WarningIcon {...iconProps} color="warning" />;
|
|
|
|
|
|
case 'error':
|
|
|
|
|
|
return <ErrorIcon {...iconProps} color="error" />;
|
|
|
|
|
|
case 'confirm':
|
|
|
|
|
|
return <ConfirmIcon {...iconProps} color="warning" />;
|
|
|
|
|
|
default:
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 获取确认按钮颜色
|
|
|
|
|
|
const getConfirmButtonColor = () => {
|
|
|
|
|
|
switch (config.type) {
|
|
|
|
|
|
case 'error':
|
|
|
|
|
|
case 'warning':
|
|
|
|
|
|
return 'error';
|
|
|
|
|
|
case 'success':
|
|
|
|
|
|
return 'success';
|
|
|
|
|
|
case 'info':
|
|
|
|
|
|
return 'info';
|
|
|
|
|
|
default:
|
|
|
|
|
|
return 'primary';
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 处理确认操作
|
|
|
|
|
|
const handleConfirm = async () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
|
|
|
|
|
|
|
if (config.onConfirm) {
|
|
|
|
|
|
await config.onConfirm();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onClose(true);
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('Dialog confirm error:', error);
|
|
|
|
|
|
// 即使出错也关闭对话框,但返回false
|
|
|
|
|
|
onClose(false);
|
|
|
|
|
|
} finally {
|
|
|
|
|
|
setLoading(false);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 处理取消操作
|
|
|
|
|
|
const handleCancel = () => {
|
|
|
|
|
|
if (config.onCancel) {
|
|
|
|
|
|
config.onCancel();
|
|
|
|
|
|
}
|
|
|
|
|
|
onClose(false);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 处理遮罩点击
|
|
|
|
|
|
const handleBackdropClick = () => {
|
|
|
|
|
|
if (config.maskClosable !== false) {
|
|
|
|
|
|
handleCancel();
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
|
<Dialog
|
|
|
|
|
|
open={true}
|
|
|
|
|
|
onClose={handleBackdropClick}
|
|
|
|
|
|
maxWidth="sm"
|
|
|
|
|
|
fullWidth
|
2025-10-13 18:25:44 +08:00
|
|
|
|
slotProps={{
|
|
|
|
|
|
paper: {
|
|
|
|
|
|
sx: {
|
|
|
|
|
|
width: config.width || 'auto',
|
|
|
|
|
|
minWidth: config.width || '300px',
|
|
|
|
|
|
maxWidth: config.width || '500px',
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-13 12:26:10 +08:00
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{/* 标题栏 */}
|
|
|
|
|
|
<DialogTitle sx={{ display: 'flex', alignItems: 'center', pr: 1 }}>
|
|
|
|
|
|
<Box sx={{ display: 'flex', alignItems: 'center', flex: 1 }}>
|
|
|
|
|
|
{getDialogIcon()}
|
|
|
|
|
|
<Typography variant="h6" component="span">
|
2025-10-29 16:40:20 +08:00
|
|
|
|
{config.title || t('dialog.defaultTitle')}
|
2025-10-13 12:26:10 +08:00
|
|
|
|
</Typography>
|
|
|
|
|
|
</Box>
|
|
|
|
|
|
<IconButton
|
|
|
|
|
|
onClick={handleCancel}
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
sx={{ ml: 1 }}
|
|
|
|
|
|
>
|
|
|
|
|
|
<CloseIcon />
|
|
|
|
|
|
</IconButton>
|
|
|
|
|
|
</DialogTitle>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 内容区域 */}
|
|
|
|
|
|
<DialogContent>
|
|
|
|
|
|
<Typography variant="body1" sx={{ py: 1 }}>
|
|
|
|
|
|
{config.content}
|
|
|
|
|
|
</Typography>
|
|
|
|
|
|
</DialogContent>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 操作按钮 */}
|
|
|
|
|
|
<DialogActions sx={{ px: 3, pb: 2 }}>
|
|
|
|
|
|
{config.showCancel !== false && (
|
|
|
|
|
|
<Button
|
|
|
|
|
|
onClick={handleCancel}
|
|
|
|
|
|
variant="outlined"
|
|
|
|
|
|
disabled={loading}
|
|
|
|
|
|
>
|
2025-10-29 16:40:20 +08:00
|
|
|
|
{config.cancelText || t('common.cancel')}
|
2025-10-13 12:26:10 +08:00
|
|
|
|
</Button>
|
|
|
|
|
|
)}
|
|
|
|
|
|
<Button
|
|
|
|
|
|
onClick={handleConfirm}
|
|
|
|
|
|
variant="contained"
|
|
|
|
|
|
color={getConfirmButtonColor() as any}
|
|
|
|
|
|
disabled={loading}
|
|
|
|
|
|
sx={{ ml: 1 }}
|
|
|
|
|
|
>
|
2025-10-29 16:40:20 +08:00
|
|
|
|
{loading ? t('dialog.processing') : (config.confirmText || t('common.confirm'))}
|
2025-10-13 12:26:10 +08:00
|
|
|
|
</Button>
|
|
|
|
|
|
</DialogActions>
|
|
|
|
|
|
</Dialog>
|
|
|
|
|
|
);
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
export default DialogComponent;
|