import PropTypes from 'prop-types'; import * as Yup from 'yup'; import { Formik } from 'formik'; import { useTheme } from '@mui/material/styles'; import { useState, useEffect } from 'react'; import dayjs from 'dayjs'; import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Divider, Alert, FormControl, InputLabel, OutlinedInput, InputAdornment, Autocomplete, Checkbox, TextField, Switch, FormHelperText } from '@mui/material'; import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { LocalizationProvider } from '@mui/x-date-pickers/LocalizationProvider'; import { DateTimePicker } from '@mui/x-date-pickers/DateTimePicker'; import { renderQuotaWithPrompt, showSuccess, showError } from 'utils/common'; import { API } from 'utils/api'; import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank'; import CheckBoxIcon from '@mui/icons-material/CheckBox'; import { createFilterOptions } from '@mui/material/Autocomplete'; require('dayjs/locale/zh-cn'); const icon = ; const checkedIcon = ; const filter = createFilterOptions(); const validationSchema = Yup.object().shape({ is_edit: Yup.boolean(), name: Yup.string().required('名称 不能为空'), remain_quota: Yup.number().min(0, '必须大于等于0'), expired_time: Yup.number(), unlimited_quota: Yup.boolean() }); const originInputs = { is_edit: false, name: '', remain_quota: 0, expired_time: -1, unlimited_quota: false, subnet: '', models: [] }; const EditModal = ({ open, tokenId, onCancel, onOk }) => { const theme = useTheme(); const [inputs, setInputs] = useState(originInputs); const [modelOptions, setModelOptions] = useState([]); const submit = async (values, { setErrors, setStatus, setSubmitting }) => { setSubmitting(true); values.remain_quota = parseInt(values.remain_quota); let res; let models = values.models.join(','); if (values.is_edit) { res = await API.put(`/api/token/`, { ...values, id: parseInt(tokenId), models: models }); } else { res = await API.post(`/api/token/`, { ...values, models: models }); } const { success, message } = res.data; if (success) { if (values.is_edit) { showSuccess('令牌更新成功!'); } else { showSuccess('令牌创建成功,请在列表页面点击复制获取令牌!'); } setSubmitting(false); setStatus({ success: true }); onOk(true); } else { showError(message); setErrors({ submit: message }); } }; const loadToken = async () => { let res = await API.get(`/api/token/${tokenId}`); const { success, message, data } = res.data; if (success) { data.is_edit = true; if (data.models === '') { data.models = []; } else { data.models = data.models.split(','); } setInputs(data); } else { showError(message); } }; const loadAvailableModels = async () => { let res = await API.get(`/api/user/available_models`); const { success, message, data } = res.data; if (success) { setModelOptions(data); } else { showError(message); } }; useEffect(() => { if (tokenId) { loadToken().then(); } else { setInputs({ ...originInputs }); } loadAvailableModels().then(); }, [tokenId]); return ( {tokenId ? '编辑令牌' : '新建令牌'} 注意,令牌的额度仅用于限制令牌本身的最大额度使用量,实际的使用受到账户的剩余额度限制。 {({ errors, handleBlur, handleChange, handleSubmit, touched, values, setFieldError, setFieldValue, isSubmitting }) => (
名称 {touched.name && errors.name && ( {errors.name} )} { const event = { target: { name: 'models', value: value } }; handleChange(event); }} onBlur={handleBlur} // filterSelectedOptions disableCloseOnSelect renderInput={(params) => } filterOptions={(options, params) => { const filtered = filter(options, params); const { inputValue } = params; const isExisting = options.some((option) => inputValue === option); if (inputValue !== '' && !isExisting) { filtered.push(inputValue); } return filtered; }} renderOption={(props, option, { selected }) => (
  • {option}
  • )} /> {errors.models ? ( {errors.models} ) : ( 请选择允许使用的模型,留空则不进行限制 )}
    IP 限制 {touched.subnet && errors.subnet ? ( {errors.subnet} ) : ( 请输入允许访问的网段,例如:192.168.0.0/24,请使用英文逗号分隔多个网段 )} {values.expired_time !== -1 && ( { if (newError === null) { setFieldError('expired_time', null); } else { setFieldError('expired_time', '无效的日期'); } }} onChange={(newValue) => { setFieldValue('expired_time', newValue.unix()); }} slotProps={{ actionBar: { actions: ['today', 'accept'] } }} /> {errors.expired_time && ( {errors.expired_time} )} )} { if (values.expired_time === -1) { setFieldValue('expired_time', Math.floor(Date.now() / 1000)); } else { setFieldValue('expired_time', -1); } }} />{' '} 永不过期 额度 {renderQuotaWithPrompt(values.remain_quota)}} onBlur={handleBlur} onChange={handleChange} aria-describedby="helper-text-channel-remain_quota-label" disabled={values.unlimited_quota} /> {touched.remain_quota && errors.remain_quota && ( {errors.remain_quota} )} { setFieldValue('unlimited_quota', !values.unlimited_quota); }} />{' '} 无限额度 )}
    ); }; export default EditModal; EditModal.propTypes = { open: PropTypes.bool, tokenId: PropTypes.number, onCancel: PropTypes.func, onOk: PropTypes.func };