| | |
| | | import React from "react"; |
| | | import { |
| | | Edit, |
| | | SimpleForm, |
| | | useTranslate, |
| | | TextInput, |
| | | NumberInput, |
| | | SaveButton, |
| | | SelectInput, |
| | | Toolbar, |
| | | DeleteButton, |
| | | } from 'react-admin'; |
| | | import { useFormContext } from "react-hook-form"; |
| | | import { Stack, Grid, Typography } from '@mui/material'; |
| | | import { EDIT_MODE } from '@/config/setting'; |
| | | import EditBaseAside from "@/page/components/EditBaseAside"; |
| | | import CustomerTopToolBar from "@/page/components/EditTopToolBar"; |
| | | import MemoInput from "@/page/components/MemoInput"; |
| | | import StatusSelectInput from "@/page/components/StatusSelectInput"; |
| | | Edit, |
| | | SaveButton, |
| | | SimpleForm, |
| | | Toolbar, |
| | | } from "react-admin"; |
| | | import AiParamForm from "./AiParamForm"; |
| | | |
| | | const yesNoChoices = [ |
| | | { id: 1, name: 'common.enums.true' }, |
| | | { id: 0, name: 'common.enums.false' }, |
| | | ]; |
| | | const FormToolbar = () => ( |
| | | <Toolbar sx={{ justifyContent: "space-between" }}> |
| | | <SaveButton /> |
| | | <DeleteButton mutationMode="pessimistic" /> |
| | | </Toolbar> |
| | | ); |
| | | |
| | | const providerChoices = [ |
| | | { id: 'openai', name: 'OpenAI Compatible' }, |
| | | { id: 'mock', name: 'Mock' }, |
| | | ]; |
| | | |
| | | const FormToolbar = () => { |
| | | const { getValues } = useFormContext(); |
| | | |
| | | return ( |
| | | <Toolbar sx={{ justifyContent: 'space-between' }}> |
| | | <SaveButton /> |
| | | <DeleteButton mutationMode="optimistic" /> |
| | | </Toolbar> |
| | | ) |
| | | } |
| | | |
| | | const AiParamEdit = () => { |
| | | const translate = useTranslate(); |
| | | |
| | | return ( |
| | | <Edit |
| | | redirect="list" |
| | | mutationMode={EDIT_MODE} |
| | | actions={<CustomerTopToolBar />} |
| | | aside={<EditBaseAside />} |
| | | > |
| | | <SimpleForm |
| | | shouldUnregister |
| | | warnWhenUnsavedChanges |
| | | toolbar={<FormToolbar />} |
| | | mode="onTouched" |
| | | defaultValues={{}} |
| | | > |
| | | <Grid container width={{ xs: '100%', xl: '80%' }} rowSpacing={3} columnSpacing={3}> |
| | | <Grid item xs={12} md={8}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.main')} |
| | | </Typography> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput label="table.field.aiParam.uuid" source="uuid" parse={v => v} disabled /> |
| | | <TextInput label="table.field.aiParam.name" source="name" parse={v => v} /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput label="table.field.aiParam.modelCode" source="modelCode" parse={v => v} /> |
| | | <SelectInput |
| | | label="table.field.aiParam.provider" |
| | | source="provider" |
| | | choices={providerChoices} |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.aiParam.modelName" |
| | | source="modelName" |
| | | parse={v => v} |
| | | helperText="填写真实模型名,例如 gpt-4o-mini、deepseek-chat" |
| | | /> |
| | | <NumberInput label="table.field.aiParam.maxContextMessages" source="maxContextMessages" /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <NumberInput label="table.field.aiParam.sort" source="sort" /> |
| | | <SelectInput |
| | | label="table.field.aiParam.defaultFlag" |
| | | source="defaultFlag" |
| | | choices={yesNoChoices} |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.aiParam.chatUrl" |
| | | source="chatUrl" |
| | | parse={v => v} |
| | | helperText="支持填写 baseUrl,如 https://api.openai.com 或 https://api.siliconflow.cn,系统会自动补全为 /v1/chat/completions" |
| | | fullWidth |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.aiParam.apiKey" |
| | | source="apiKey" |
| | | parse={v => v} |
| | | type="password" |
| | | helperText="OpenAI 接口模式下填写 Bearer Token,无需手动加 Bearer 前缀" |
| | | fullWidth |
| | | /> |
| | | </Stack> |
| | | <Stack direction='row' gap={2}> |
| | | <TextInput |
| | | label="table.field.aiParam.systemPrompt" |
| | | source="systemPrompt" |
| | | parse={v => v} |
| | | fullWidth |
| | | multiline |
| | | minRows={5} |
| | | /> |
| | | </Stack> |
| | | </Grid> |
| | | <Grid item xs={12} md={4}> |
| | | <Typography variant="h6" gutterBottom> |
| | | {translate('common.edit.title.common')} |
| | | </Typography> |
| | | <StatusSelectInput /> |
| | | <MemoInput /> |
| | | </Grid> |
| | | </Grid> |
| | | </SimpleForm> |
| | | </Edit > |
| | | ) |
| | | } |
| | | const AiParamEdit = () => ( |
| | | <Edit redirect="list" mutationMode="pessimistic"> |
| | | <SimpleForm warnWhenUnsavedChanges toolbar={<FormToolbar />}> |
| | | <AiParamForm /> |
| | | </SimpleForm> |
| | | </Edit> |
| | | ); |
| | | |
| | | export default AiParamEdit; |