mirror of
https://github.com/chaitin/MonkeyCode.git
synced 2026-02-02 14:53:55 +08:00
@@ -380,6 +380,8 @@ export interface DomainModel {
|
||||
input?: number;
|
||||
/** 是否启用 */
|
||||
is_active?: boolean;
|
||||
/** 是否内部模型 */
|
||||
is_internal?: boolean;
|
||||
/** 模型名称 如: deepseek-v3 */
|
||||
model_name?: string;
|
||||
/** 模型类型 llm:对话模型 coder:代码模型 */
|
||||
|
||||
@@ -189,8 +189,11 @@ const AdminTable = () => {
|
||||
{
|
||||
title: '最近活跃时间',
|
||||
dataIndex: 'last_active_at',
|
||||
render: (text) => {
|
||||
return text === 0 ? '从未使用' : dayjs.unix(text).fromNow();
|
||||
render: (text, record) => {
|
||||
return <Stack direction='column'>
|
||||
<Box sx={{ color: 'text.secondary' }}>{record.created_at ? dayjs.unix(record.created_at).fromNow() + '加入' : '加入时间未知'}</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>{record.last_active_at ? dayjs.unix(record.last_active_at).fromNow() + '活跃' : '活跃时间未知'}</Box>
|
||||
</Stack>
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -212,14 +215,14 @@ const AdminTable = () => {
|
||||
},
|
||||
];
|
||||
return (
|
||||
<Card>
|
||||
<Card sx={{ height: '100%' }}>
|
||||
<Stack
|
||||
direction='row'
|
||||
justifyContent='space-between'
|
||||
alignItems='center'
|
||||
sx={{ mb: 2 }}
|
||||
>
|
||||
<Box sx={{ fontWeight: 700 }}>管理员</Box>
|
||||
<Box sx={{ fontWeight: 700, lineHeight: '36px' }}>管理员</Box>
|
||||
<Button
|
||||
variant='contained'
|
||||
color='primary'
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import React from 'react';
|
||||
import LoginHistory from './loginHistory';
|
||||
import AdminTable from './adminTable';
|
||||
import { Stack } from '@mui/material';
|
||||
import { Grid2 as Grid, Stack } from '@mui/material';
|
||||
|
||||
const Admin = () => {
|
||||
return (
|
||||
<Stack gap={2} sx={{ height: '100%' }}>
|
||||
<AdminTable />
|
||||
<LoginHistory />
|
||||
</Stack>
|
||||
<Grid container spacing={2} sx={{ height: '100%' }}>
|
||||
<Grid size={6}>
|
||||
<AdminTable />
|
||||
</Grid>
|
||||
<Grid size={6}>
|
||||
<LoginHistory />
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -23,17 +23,15 @@ const LoginHistory = () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'IP 地址',
|
||||
title: '源 IP 地址',
|
||||
dataIndex: 'ip',
|
||||
render: (ip, record) => {
|
||||
let address = '';
|
||||
if (record?.ip_info) {
|
||||
address = `${record?.ip_info?.country}-${record?.ip_info?.city}`;
|
||||
}
|
||||
return (
|
||||
<Stack direction='row'>
|
||||
<Box>{ip}</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>({address})</Box>
|
||||
<Stack direction='column'>
|
||||
<Box>{record?.ip_info?.ip}</Box>
|
||||
<Box sx={{ color: 'text.secondary' }}>
|
||||
{record?.ip_info?.country === '中国' ? ('' + record?.ip_info?.province + '-' + record?.ip_info?.city) : (record?.ip_info?.country || '未知')}
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
},
|
||||
@@ -47,14 +45,14 @@ const LoginHistory = () => {
|
||||
},
|
||||
];
|
||||
return (
|
||||
<Card>
|
||||
<Card sx={{ height: '100%' }}>
|
||||
<Stack
|
||||
direction='row'
|
||||
justifyContent='space-between'
|
||||
alignItems='center'
|
||||
sx={{ mb: 2 }}
|
||||
>
|
||||
<Box sx={{ fontWeight: 700 }}>登录记录</Box>
|
||||
<Box sx={{ fontWeight: 700, lineHeight: '36px' }}>登录记录</Box>
|
||||
</Stack>
|
||||
<Table
|
||||
columns={columns}
|
||||
|
||||
@@ -34,7 +34,7 @@ const PieCharts: React.FC<IPieChartsProps> = ({ title, data, extra }) => {
|
||||
},
|
||||
},
|
||||
dataset: {
|
||||
source: data.slice(0, 6),
|
||||
source: data.slice(0, 5),
|
||||
},
|
||||
series: [
|
||||
{
|
||||
|
||||
@@ -116,17 +116,15 @@ const ModelItem = ({
|
||||
}
|
||||
sx={{ fontSize: 24 }}
|
||||
/>
|
||||
<Stack direction='row' alignItems='center' gap={1}>
|
||||
{data.show_name && (
|
||||
<Box sx={{ fontSize: 14, color: 'text.tertiary' }}>
|
||||
{data.show_name} /
|
||||
</Box>
|
||||
)}
|
||||
<Box sx={{ fontWeight: 700 }}>{data.model_name}</Box>
|
||||
<Stack direction='row' alignItems='center' gap={1} sx={{ fontSize: 14, minWidth: 0 }}>
|
||||
<Box sx={{ fontWeight: 700, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
{data.show_name || '未命名'}
|
||||
</Box>
|
||||
<Box sx={{ color: 'text.tertiary', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
||||
/ {data.model_name}
|
||||
</Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
{data.is_active && <StyledLabel color='success'>正在使用</StyledLabel>}
|
||||
</Stack>
|
||||
<Stack
|
||||
gap={1}
|
||||
@@ -157,18 +155,21 @@ const ModelItem = ({
|
||||
</Stack>
|
||||
</Stack>
|
||||
<Stack
|
||||
direction='row-reverse'
|
||||
direction='row'
|
||||
justifyContent='space-between'
|
||||
alignItems='center'
|
||||
gap={2}
|
||||
sx={{ mt: 2 }}
|
||||
>
|
||||
<Stack direction='row' alignItems='center'>
|
||||
{data.is_active && <StyledLabel color='success'>正在使用</StyledLabel>}
|
||||
</Stack>
|
||||
<Stack
|
||||
direction='row'
|
||||
justifySelf='flex-end'
|
||||
sx={{ button: { minWidth: 0 } }}
|
||||
gap={2}
|
||||
>
|
||||
<ButtonBase
|
||||
{!data.is_internal && <ButtonBase
|
||||
disableRipple
|
||||
sx={{
|
||||
color: 'info.main',
|
||||
@@ -176,7 +177,7 @@ const ModelItem = ({
|
||||
onClick={() => onEdit(data)}
|
||||
>
|
||||
编辑
|
||||
</ButtonBase>
|
||||
</ButtonBase>}
|
||||
{!data.is_active && (
|
||||
<ButtonBase
|
||||
disableRipple
|
||||
@@ -244,7 +245,10 @@ const ModelCard: React.FC<IModelCardProps> = ({ title, modelType }) => {
|
||||
{modelList?.length > 0 ? (
|
||||
<Grid container spacing={2} sx={{ mt: 2 }}>
|
||||
{modelList.map((item) => (
|
||||
<Grid size={4} key={item.id}>
|
||||
<Grid
|
||||
size={{ xs: 12, sm: 12, md: 12, lg: 6, xl: 4 }}
|
||||
key={item.id}
|
||||
>
|
||||
<ModelItem data={item} onEdit={onEdit} refresh={refresh} />
|
||||
</Grid>
|
||||
))}
|
||||
|
||||
@@ -25,7 +25,7 @@ const StyledCard = styled(Card)({
|
||||
|
||||
const StyledLabel = styled('div')(({ theme }) => ({
|
||||
fontWeight: 700,
|
||||
fontSize: 14,
|
||||
fontSize: 16,
|
||||
color: theme.vars.palette.text.primary,
|
||||
}));
|
||||
|
||||
@@ -70,7 +70,7 @@ const User = () => {
|
||||
<Grid size={6} container sx={{ height: '100%' }}>
|
||||
<Stack gap={2} sx={{ height: '100%' }}>
|
||||
<StyledCard>
|
||||
<StyledLabel>强制成员启用两步认证</StyledLabel>
|
||||
<StyledLabel>强制启用两步认证</StyledLabel>
|
||||
<Switch
|
||||
checked={data?.force_two_factor_auth}
|
||||
onChange={(e) => {
|
||||
@@ -79,7 +79,7 @@ const User = () => {
|
||||
/>
|
||||
</StyledCard>
|
||||
<StyledCard>
|
||||
<StyledLabel>禁止成员使用密码登录</StyledLabel>
|
||||
<StyledLabel>禁止使用密码登录</StyledLabel>
|
||||
<Switch
|
||||
checked={data?.disable_password_login}
|
||||
onChange={(e) =>
|
||||
@@ -87,6 +87,15 @@ const User = () => {
|
||||
}
|
||||
/>
|
||||
</StyledCard>
|
||||
<StyledCard>
|
||||
<StyledLabel>开放自主注册(无需邀请)</StyledLabel>
|
||||
<Switch
|
||||
checked={data?.enable_auto_login}
|
||||
onChange={(e) =>
|
||||
updateSetting({ enable_auto_login: e.target.checked })
|
||||
}
|
||||
/>
|
||||
</StyledCard>
|
||||
<StyledCard>
|
||||
<StyledLabel>
|
||||
第三方登录
|
||||
@@ -110,15 +119,6 @@ const User = () => {
|
||||
配置
|
||||
</Button>
|
||||
</StyledCard>
|
||||
<StyledCard>
|
||||
<StyledLabel>允许成员自主注册</StyledLabel>
|
||||
<Switch
|
||||
checked={data?.enable_auto_login}
|
||||
onChange={(e) =>
|
||||
updateSetting({ enable_auto_login: e.target.checked })
|
||||
}
|
||||
/>
|
||||
</StyledCard>
|
||||
<LoginHistory />
|
||||
</Stack>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user