From 51877df13075ad10ef51107f15bcd21f1661febe Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期二, 17 三月 2026 09:48:01 +0800
Subject: [PATCH] #AI
---
rsf-admin/src/page/system/aiParam/AiParamList.jsx | 165 +++++++++++++++++++++++++++++++++++++++---------------
1 files changed, 118 insertions(+), 47 deletions(-)
diff --git a/rsf-admin/src/page/system/aiParam/AiParamList.jsx b/rsf-admin/src/page/system/aiParam/AiParamList.jsx
index 8f12399..41fb75c 100644
--- a/rsf-admin/src/page/system/aiParam/AiParamList.jsx
+++ b/rsf-admin/src/page/system/aiParam/AiParamList.jsx
@@ -1,42 +1,25 @@
import React, { useState } from "react";
import {
List,
- DatagridConfigurable,
SearchInput,
TopToolbar,
SelectColumnsButton,
- EditButton,
FilterButton,
- BulkDeleteButton,
- WrapperField,
- TextField,
- NumberField,
- DateField,
- BooleanField,
TextInput,
DateInput,
SelectInput,
+ useListContext,
+ Pagination,
+ EditButton,
DeleteButton,
} from 'react-admin';
-import { Box } from '@mui/material';
-import { styled } from '@mui/material/styles';
+import { Box, Chip, Grid, Stack, Typography } from '@mui/material';
import EmptyData from "@/page/components/EmptyData";
import MyCreateButton from "@/page/components/MyCreateButton";
import MyExportButton from '@/page/components/MyExportButton';
import { OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting';
import AiParamCreate from "./AiParamCreate";
-
-const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({
- '& .css-1vooibu-MuiSvgIcon-root': {
- height: '.9em'
- },
- '& .RaDatagrid-row': {
- cursor: 'auto'
- },
- '& .opt': {
- width: 200
- },
-}));
+import { AiConsoleLayout, AiConsolePanel, aiCardSx } from "@/page/components/AiConsoleLayout";
const filters = [
<SearchInput source="condition" alwaysOn />,
@@ -63,14 +46,123 @@
{ id: '0', name: 'common.enums.statusFalse' },
]}
/>,
-]
+];
+
+const providerLabel = (provider) => {
+ if (provider === 'openai') {
+ return 'OpenAI Compatible';
+ }
+ if (provider === 'mock') {
+ return 'Mock';
+ }
+ return provider || '鏈厤缃�';
+};
+
+const AiParamBoard = () => {
+ const { data, isLoading } = useListContext();
+ const records = data || [];
+ const enabledCount = records.filter((item) => item.status === 1).length;
+ const defaultCount = records.filter((item) => item.defaultFlag === 1).length;
+ const openaiCount = records.filter((item) => item.provider === 'openai').length;
+ const mockCount = records.filter((item) => item.provider === 'mock').length;
+
+ if (!isLoading && !records.length) {
+ return <EmptyData />;
+ }
+
+ return (
+ <AiConsoleLayout
+ title="AI鍙傛暟"
+ subtitle="淇濇寔褰撳墠绯荤粺鍚庡彴鐨勭櫧搴曞崱鐗囧拰杞昏竟妗嗛鏍硷紝鐢ㄥ崱鐗囨柟寮忓睍绀烘ā鍨嬮厤缃鍐碉紝鏂逛究鍜屽叾浠� AI 椤甸潰缁熶竴鏌ョ湅銆�"
+ stats={[
+ { label: '鍙傛暟鎬绘暟', value: records.length },
+ { label: '鍚敤', value: enabledCount },
+ { label: '榛樿妯″瀷', value: defaultCount },
+ { label: 'OpenAI / Mock', value: `${openaiCount} / ${mockCount}` },
+ ]}
+ >
+ <AiConsolePanel
+ title="妯″瀷閰嶇疆"
+ subtitle="灞曠ず妯″瀷缂栫爜銆佷緵搴斿晢銆佷笂涓嬫枃杞暟鍜岄粯璁ょ姸鎬侊紱鍒涘缓銆佺紪杈戙�佸垹闄や粛娌跨敤鍘熺郴缁熺殑寮圭獥涓庣紪杈戦〉銆�"
+ minHeight={460}
+ >
+ <Box
+ sx={{
+ display: 'grid',
+ gridTemplateColumns: 'repeat(auto-fit, minmax(320px, 1fr))',
+ gap: 2,
+ }}
+ >
+ {records.map((record) => (
+ <Box key={record.id}>
+ <Box sx={aiCardSx(record.defaultFlag === 1)}>
+ <Stack direction="row" justifyContent="space-between" alignItems="flex-start" spacing={1}>
+ <Box>
+ <Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
+ {record.name || record.modelCode || record.uuid}
+ </Typography>
+ <Typography variant="caption" color="text.secondary">
+ {record.modelCode || '鏈~鍐欐ā鍨嬬紪鐮�'}
+ </Typography>
+ </Box>
+ <Stack direction="row" spacing={0.75} flexWrap="wrap" justifyContent="flex-end">
+ <Chip size="small" color={record.status === 1 ? 'success' : 'default'} label={record.status === 1 ? '鍚敤' : '鍋滅敤'} />
+ {record.defaultFlag === 1 ? <Chip size="small" color="primary" label="榛樿" /> : null}
+ </Stack>
+ </Stack>
+ <Grid container spacing={1.25} sx={{ mt: 1 }}>
+ <Grid item xs={6}>
+ <Typography variant="caption" color="text.secondary">渚涘簲鍟�</Typography>
+ <Typography variant="body2" sx={{ mt: 0.25 }}>{providerLabel(record.provider)}</Typography>
+ </Grid>
+ <Grid item xs={6}>
+ <Typography variant="caption" color="text.secondary">妯″瀷鍚�</Typography>
+ <Typography variant="body2" sx={{ mt: 0.25 }}>{record.modelName || '-'}</Typography>
+ </Grid>
+ <Grid item xs={6}>
+ <Typography variant="caption" color="text.secondary">涓婁笅鏂囪疆鏁�</Typography>
+ <Typography variant="body2" sx={{ mt: 0.25 }}>{record.maxContextMessages || 0}</Typography>
+ </Grid>
+ <Grid item xs={6}>
+ <Typography variant="caption" color="text.secondary">鎺掑簭</Typography>
+ <Typography variant="body2" sx={{ mt: 0.25 }}>{record.sort || 0}</Typography>
+ </Grid>
+ <Grid item xs={12}>
+ <Typography variant="caption" color="text.secondary">鑱婂ぉ鍦板潃</Typography>
+ <Typography variant="body2" sx={{ mt: 0.25, wordBreak: 'break-all' }}>
+ {record.chatUrl || '鏈厤缃�'}
+ </Typography>
+ </Grid>
+ <Grid item xs={12}>
+ <Typography variant="caption" color="text.secondary">澶囨敞</Typography>
+ <Typography variant="body2" sx={{ mt: 0.25, minHeight: 42 }}>
+ {record.memo || '鏈~鍐欏娉�'}
+ </Typography>
+ </Grid>
+ </Grid>
+ <Stack direction="row" spacing={1} sx={{ mt: 1.5 }}>
+ <EditButton record={record} sx={{ px: 1.25, py: 0.5, minWidth: 64 }} />
+ <DeleteButton record={record} sx={{ px: 1.25, py: 0.5, minWidth: 64 }} mutationMode={OPERATE_MODE} />
+ </Stack>
+ </Box>
+ </Box>
+ ))}
+ </Box>
+ <Box sx={{ mt: 2 }}>
+ <Pagination rowsPerPageOptions={[DEFAULT_PAGE_SIZE, 25, 50]} />
+ </Box>
+ </AiConsolePanel>
+ </AiConsoleLayout>
+ );
+};
const AiParamList = () => {
const [createDialog, setCreateDialog] = useState(false);
return (
- <Box display="flex">
+ <Box display="flex" sx={{ width: '100%' }}>
<List
+ sx={{ width: '100%', flexGrow: 1 }}
title={"menu.aiParam"}
empty={<EmptyData onClick={() => { setCreateDialog(true) }} />}
filters={filters}
@@ -84,30 +176,9 @@
</TopToolbar>
)}
perPage={DEFAULT_PAGE_SIZE}
+ pagination={false}
>
- <StyledDatagrid
- preferenceKey='aiParam'
- bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />}
- rowClick={false}
- omit={['id', 'createTime', 'memo', 'statusBool', 'defaultFlagBool']}
- >
- <NumberField source="id" />
- <TextField source="uuid" label="table.field.aiParam.uuid" />
- <TextField source="name" label="table.field.aiParam.name" />
- <TextField source="modelCode" label="table.field.aiParam.modelCode" />
- <TextField source="provider" label="table.field.aiParam.provider" />
- <TextField source="modelName" label="table.field.aiParam.modelName" />
- <NumberField source="maxContextMessages" label="table.field.aiParam.maxContextMessages" />
- <NumberField source="sort" label="table.field.aiParam.sort" />
- <BooleanField source="defaultFlagBool" label="table.field.aiParam.defaultFlag" sortable={false} />
- <BooleanField source="statusBool" label="common.field.status" sortable={false} />
- <DateField source="updateTime" label="common.field.updateTime" showTime />
- <TextField source="memo" label="common.field.memo" sortable={false} />
- <WrapperField cellClassName="opt" label="common.field.opt">
- <EditButton sx={{ padding: '1px', fontSize: '.75rem' }} />
- <DeleteButton sx={{ padding: '1px', fontSize: '.75rem' }} mutationMode={OPERATE_MODE} />
- </WrapperField>
- </StyledDatagrid>
+ <AiParamBoard />
</List>
<AiParamCreate
open={createDialog}
--
Gitblit v1.9.1