zhou zhou
2026-03-19 d5884d0974d17d96225a5d80e432de33a5ee6552
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
import React, { useState } from "react";
import {
    BooleanInput,
    FormDataConsumer,
    NumberInput,
    SelectInput,
    TextInput,
    useNotify,
} from "react-admin";
import { Alert, Button, Grid, Stack, Typography } from "@mui/material";
import StatusSelectInput from "@/page/components/StatusSelectInput";
import { validateAiParamDraft } from "@/api/ai/configCenter";
 
const providerChoices = [
    { id: "OPENAI_COMPATIBLE", name: "OPENAI_COMPATIBLE" },
];
 
const AiParamValidateSection = ({ formData, readOnly }) => {
    const notify = useNotify();
    const [loading, setLoading] = useState(false);
    const [result, setResult] = useState(null);
 
    const handleValidate = async () => {
        setLoading(true);
        try {
            const data = await validateAiParamDraft(formData);
            setResult(data);
            notify(data?.message || "AI 参数验证成功");
        } catch (error) {
            const nextResult = {
                status: "INVALID",
                message: error?.message || "AI 参数验证失败",
            };
            setResult(nextResult);
            notify(nextResult.message, { type: "error" });
        } finally {
            setLoading(false);
        }
    };
 
    return (
        <>
            {!readOnly && (
                <Grid item xs={12}>
                    <Stack direction="row" spacing={1} alignItems="center">
                        <Button variant="outlined" onClick={handleValidate} disabled={loading}>
                            {loading ? "验证中..." : "保存前验证"}
                        </Button>
                        <Typography variant="body2" color="text.secondary">
                            会直接校验当前 Base URL、API Key 与模型是否可调用。
                        </Typography>
                    </Stack>
                </Grid>
            )}
            {result && (
                <Grid item xs={12}>
                    <Alert severity={result.status === "VALID" ? "success" : "error"}>
                        {result.message}
                        {result.elapsedMs ? ` · ${result.elapsedMs} ms` : ""}
                        {result.validatedAt ? ` · ${result.validatedAt}` : ""}
                    </Alert>
                </Grid>
            )}
        </>
    );
};
 
const AiParamForm = ({ readOnly = false }) => (
    <Grid container spacing={2} width={{ xs: "100%", xl: "80%" }}>
        <Grid item xs={12}>
            <Typography variant="h6">主要配置</Typography>
        </Grid>
        <Grid item xs={12} md={6}>
            <TextInput source="name" label="名称" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={6}>
            <SelectInput source="providerType" label="提供方类型" choices={providerChoices} fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12}>
            <TextInput source="baseUrl" label="Base URL" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={6}>
            <TextInput source="apiKey" label="API Key" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={6}>
            <TextInput source="model" label="模型" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={3}>
            <NumberInput source="temperature" label="Temperature" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={3}>
            <NumberInput source="topP" label="Top P" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={3}>
            <NumberInput source="maxTokens" label="Max Tokens" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={3}>
            <NumberInput source="timeoutMs" label="Timeout(ms)" fullWidth disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={6}>
            <BooleanInput source="streamingEnabled" label="启用流式响应" disabled={readOnly} />
        </Grid>
        <Grid item xs={12} md={6}>
            <StatusSelectInput disabled={readOnly} />
        </Grid>
        <Grid item xs={12}>
            <TextInput source="memo" label="备注" fullWidth multiline minRows={3} disabled={readOnly} />
        </Grid>
        <FormDataConsumer>
            {({ formData }) => <AiParamValidateSection formData={formData} readOnly={readOnly} />}
        </FormDataConsumer>
        <Grid item xs={12}>
            <Typography variant="h6">运行与审计信息</Typography>
        </Grid>
        <Grid item xs={12} md={3}>
            <TextInput source="validateStatus" label="最近校验状态" fullWidth disabled />
        </Grid>
        <Grid item xs={12} md={3}>
            <TextInput source="lastValidateElapsedMs" label="最近校验耗时(ms)" fullWidth disabled />
        </Grid>
        <Grid item xs={12} md={3}>
            <TextInput source="lastValidateTime$" label="最近校验时间" fullWidth disabled />
        </Grid>
        <Grid item xs={12} md={3}>
            <TextInput source="updateBy" label="最近更新人" fullWidth disabled />
        </Grid>
        <Grid item xs={12}>
            <TextInput source="lastValidateMessage" label="最近校验结果" fullWidth multiline minRows={3} disabled />
        </Grid>
        <Grid item xs={12}>
            <TextInput source="updateTime$" label="最近更新时间" fullWidth disabled />
        </Grid>
    </Grid>
);
 
export default AiParamForm;