| | |
| | | useListContext, |
| | | useNotify, |
| | | useRefresh, |
| | | useTranslate, |
| | | } from "react-admin"; |
| | | import { |
| | | Box, |
| | |
| | | |
| | | const filters = [ |
| | | <SearchInput source="condition" alwaysOn />, |
| | | <TextInput source="providerType" label="提供方类型" />, |
| | | <TextInput source="model" label="模型" />, |
| | | <TextInput source="providerType" label="ai.param.fields.providerType" />, |
| | | <TextInput source="model" label="ai.param.fields.model" />, |
| | | <SelectInput |
| | | source="status" |
| | | label="状态" |
| | | label="common.field.status" |
| | | choices={[ |
| | | { id: "1", name: "common.enums.statusTrue" }, |
| | | { id: "0", name: "common.enums.statusFalse" }, |
| | |
| | | }; |
| | | |
| | | const AiParamCards = ({ onView, onEdit, onDelete, deleting }) => { |
| | | const translate = useTranslate(); |
| | | const { data, isLoading } = useListContext(); |
| | | const records = useMemo(() => (Array.isArray(data) ? data : []), [data]); |
| | | |
| | |
| | | return ( |
| | | <Box px={2} py={6}> |
| | | <Card variant="outlined" sx={{ p: 3, textAlign: "center", borderStyle: "dashed" }}> |
| | | <Typography variant="subtitle1">暂无 AI 参数配置</Typography> |
| | | <Typography variant="subtitle1">{translate("ai.param.list.emptyTitle")}</Typography> |
| | | <Typography variant="body2" color="text.secondary" mt={1}> |
| | | 可以先新建一个 OpenAI 兼容模型参数卡片。 |
| | | {translate("ai.param.list.emptyDescription")} |
| | | </Typography> |
| | | </Card> |
| | | </Box> |
| | |
| | | <Chip |
| | | size="small" |
| | | color={record.statusBool ? "success" : "default"} |
| | | label={record.statusBool ? "启用" : "停用"} |
| | | label={translate(record.statusBool ? "ai.common.enabled" : "ai.common.disabled")} |
| | | /> |
| | | </Stack> |
| | | <Stack direction="row" spacing={1} flexWrap="wrap" useFlexGap mt={1.5}> |
| | |
| | | size="small" |
| | | variant="outlined" |
| | | color={record.streamingEnabled ? "info" : "default"} |
| | | label={record.streamingEnabled ? "流式响应" : "非流式"} |
| | | label={translate(record.streamingEnabled ? "ai.param.list.streaming" : "ai.param.list.nonStreaming")} |
| | | /> |
| | | </Stack> |
| | | <Divider sx={{ my: 1.5 }} /> |
| | |
| | | <Typography variant="body2">{record.timeoutMs ?? "--"} ms</Typography> |
| | | </Grid> |
| | | </Grid> |
| | | <Typography variant="caption" color="text.secondary" display="block" mt={1.5}> |
| | | 备注 |
| | | </Typography> |
| | | <Typography variant="caption" color="text.secondary" display="block" mt={1.5}>{translate("common.field.memo")}</Typography> |
| | | <Typography variant="body2">{truncateText(record.memo)}</Typography> |
| | | </CardContent> |
| | | <CardActions sx={{ px: 2, pb: 2, pt: 0, justifyContent: "space-between" }}> |
| | | <Stack direction="row" spacing={1}> |
| | | <Button size="small" startIcon={<VisibilityOutlinedIcon />} onClick={() => onView(record.id)}> |
| | | 详情 |
| | | {translate("ai.common.detail")} |
| | | </Button> |
| | | <Button size="small" startIcon={<EditOutlinedIcon />} onClick={() => onEdit(record.id)}> |
| | | 编辑 |
| | | {translate("common.button.edit")} |
| | | </Button> |
| | | </Stack> |
| | | <Button |
| | |
| | | onClick={() => onDelete(record)} |
| | | disabled={deleting} |
| | | > |
| | | 删除 |
| | | {translate("ai.common.delete")} |
| | | </Button> |
| | | </CardActions> |
| | | </Card> |
| | |
| | | }; |
| | | |
| | | const AiParamList = () => { |
| | | const translate = useTranslate(); |
| | | const notify = useNotify(); |
| | | const refresh = useRefresh(); |
| | | const [deleteOne, { isPending: deleting }] = useDelete(); |
| | |
| | | const closeDialog = () => setDialogState({ open: false, mode: "create", recordId: null }); |
| | | |
| | | const handleDelete = (record) => { |
| | | if (!record?.id || !window.confirm(`确认删除“${record.name}”吗?`)) { |
| | | if (!record?.id || !window.confirm(translate("ai.common.confirmDelete", { name: record.name }))) { |
| | | return; |
| | | } |
| | | deleteOne( |
| | |
| | | { id: record.id }, |
| | | { |
| | | onSuccess: () => { |
| | | notify("删除成功"); |
| | | notify(translate("ai.common.deleteSuccess")); |
| | | refresh(); |
| | | }, |
| | | onError: (error) => { |
| | | notify(error?.message || "删除失败", { type: "error" }); |
| | | notify(error?.message || translate("ai.common.deleteFailed"), { type: "error" }); |
| | | }, |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | const dialogTitle = { |
| | | create: "新建 AI 参数", |
| | | edit: "编辑 AI 参数", |
| | | show: "查看 AI 参数详情", |
| | | create: translate("ai.param.dialog.create"), |
| | | edit: translate("ai.param.dialog.edit"), |
| | | show: translate("ai.param.dialog.show"), |
| | | }[dialogState.mode]; |
| | | |
| | | return ( |
| | |
| | | <TopToolbar> |
| | | <FilterButton /> |
| | | <Button variant="contained" startIcon={<AddRoundedIcon />} onClick={() => openDialog("create")}> |
| | | 新建 |
| | | {translate("ai.common.new")} |
| | | </Button> |
| | | <MyExportButton /> |
| | | </TopToolbar> |