refactor(setting): split model dialogs into separate components
This commit is contained in:
203
src/pages/setting/components/Dialog/BedrockDialog.tsx
Normal file
203
src/pages/setting/components/Dialog/BedrockDialog.tsx
Normal file
@@ -0,0 +1,203 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogActions,
|
||||
Button,
|
||||
TextField,
|
||||
Box,
|
||||
Typography,
|
||||
IconButton,
|
||||
InputAdornment,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Select,
|
||||
MenuItem,
|
||||
CircularProgress,
|
||||
} from '@mui/material';
|
||||
import { Visibility, VisibilityOff } from '@mui/icons-material';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
|
||||
// AWS Bedrock 支持的区域列表
|
||||
export const BEDROCK_REGIONS = [
|
||||
{ value: 'us-east-1', label: 'US East (N. Virginia)' },
|
||||
{ value: 'us-west-2', label: 'US West (Oregon)' },
|
||||
{ value: 'ap-southeast-2', label: 'Asia Pacific (Sydney)' },
|
||||
{ value: 'ap-northeast-1', label: 'Asia Pacific (Tokyo)' },
|
||||
{ value: 'eu-central-1', label: 'Europe (Frankfurt)' },
|
||||
{ value: 'eu-west-3', label: 'Europe (Paris)' },
|
||||
];
|
||||
|
||||
// 表单数据接口
|
||||
export interface BedrockFormData {
|
||||
access_key_id: string;
|
||||
secret_access_key: string;
|
||||
region: string;
|
||||
}
|
||||
|
||||
// 对话框 Props 接口
|
||||
export interface BedrockDialogProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onSubmit: (data: BedrockFormData) => void;
|
||||
loading: boolean;
|
||||
initialData?: BedrockFormData;
|
||||
editMode?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* AWS Bedrock 配置对话框
|
||||
*/
|
||||
function BedrockDialog ({
|
||||
open,
|
||||
onClose,
|
||||
onSubmit,
|
||||
loading,
|
||||
initialData,
|
||||
editMode = false,
|
||||
}: BedrockDialogProps) {
|
||||
const [showAccessKey, setShowAccessKey] = React.useState(false);
|
||||
const [showSecretKey, setShowSecretKey] = React.useState(false);
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
reset,
|
||||
formState: { errors },
|
||||
} = useForm<BedrockFormData>({
|
||||
defaultValues: {
|
||||
access_key_id: '',
|
||||
secret_access_key: '',
|
||||
region: 'us-east-1',
|
||||
},
|
||||
});
|
||||
|
||||
// 当对话框打开或初始数据变化时重置表单
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
reset(initialData || { access_key_id: '', secret_access_key: '', region: 'us-east-1' });
|
||||
}
|
||||
}, [open, initialData, reset]);
|
||||
|
||||
const handleFormSubmit = (data: BedrockFormData) => {
|
||||
onSubmit(data);
|
||||
};
|
||||
|
||||
const toggleShowAccessKey = () => {
|
||||
setShowAccessKey(!showAccessKey);
|
||||
};
|
||||
|
||||
const toggleShowSecretKey = () => {
|
||||
setShowSecretKey(!showSecretKey);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose} maxWidth="sm" fullWidth>
|
||||
<DialogTitle>
|
||||
{editMode ? '编辑' : '配置'} AWS Bedrock
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box component="form" sx={{ mt: 2 }}>
|
||||
<Controller
|
||||
name="access_key_id"
|
||||
control={control}
|
||||
rules={{ required: 'Access Key ID 是必填项' }}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="Access Key ID"
|
||||
type={showAccessKey ? 'text' : 'password'}
|
||||
margin="normal"
|
||||
error={!!errors.access_key_id}
|
||||
helperText={errors.access_key_id?.message}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle access key visibility"
|
||||
onClick={toggleShowAccessKey}
|
||||
edge="end"
|
||||
>
|
||||
{showAccessKey ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="secret_access_key"
|
||||
control={control}
|
||||
rules={{ required: 'Secret Access Key 是必填项' }}
|
||||
render={({ field }) => (
|
||||
<TextField
|
||||
{...field}
|
||||
fullWidth
|
||||
label="Secret Access Key"
|
||||
type={showSecretKey ? 'text' : 'password'}
|
||||
margin="normal"
|
||||
error={!!errors.secret_access_key}
|
||||
helperText={errors.secret_access_key?.message}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<InputAdornment position="end">
|
||||
<IconButton
|
||||
aria-label="toggle secret key visibility"
|
||||
onClick={toggleShowSecretKey}
|
||||
edge="end"
|
||||
>
|
||||
{showSecretKey ? <VisibilityOff /> : <Visibility />}
|
||||
</IconButton>
|
||||
</InputAdornment>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Controller
|
||||
name="region"
|
||||
control={control}
|
||||
rules={{ required: 'Region 是必填项' }}
|
||||
render={({ field }) => (
|
||||
<FormControl fullWidth margin="normal" error={!!errors.region}>
|
||||
<InputLabel>Region</InputLabel>
|
||||
<Select {...field} label="Region">
|
||||
{BEDROCK_REGIONS.map((region) => (
|
||||
<MenuItem key={region.value} value={region.value}>
|
||||
{region.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
{errors.region && (
|
||||
<Typography variant="caption" color="error" sx={{ mt: 1, ml: 2 }}>
|
||||
{errors.region.message}
|
||||
</Typography>
|
||||
)}
|
||||
</FormControl>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onClose} disabled={loading}>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleSubmit(handleFormSubmit)}
|
||||
variant="contained"
|
||||
disabled={loading}
|
||||
startIcon={loading ? <CircularProgress size={20} /> : null}
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
export default BedrockDialog;
|
||||
Reference in New Issue
Block a user