diff --git a/admin/service/route/user.js b/admin/service/route/user.js index 0d9692a4c..ab0210b81 100644 --- a/admin/service/route/user.js +++ b/admin/service/route/user.js @@ -1,6 +1,12 @@ import { User, Pay } from '../schema.js'; import dayjs from 'dayjs'; import { auth } from './system.js'; +import crypto from 'crypto'; + +// 加密 +const hashPassword = (psw) => { + return crypto.createHash('sha256').update(psw).digest('hex'); +}; export const useUserRoute = (app) => { // 获取用户列表 @@ -82,7 +88,14 @@ export const useUserRoute = (app) => { app.put('/users/:id', auth(), async (req, res) => { try { const _id = req.params.id; - + + // Check if a new password is provided in the request body + if (req.body.password) { + // Hash the new password + const hashedPassword = hashPassword(req.body.password); + req.body.password = hashedPassword; + } + const result = await User.updateOne({ _id: _id }, { $set: req.body }); res.json(result); } catch (err) { diff --git a/admin/src/App.tsx b/admin/src/App.tsx index 8adee2d81..c391cf1c9 100644 --- a/admin/src/App.tsx +++ b/admin/src/App.tsx @@ -46,7 +46,7 @@ function App() { }) ]} fields={userFields} - action={{ create: true, detail: true, edit: true }} + action={{ detail: true, edit: true }} /> } /> diff --git a/admin/src/Dashboard.tsx b/admin/src/Dashboard.tsx new file mode 100644 index 000000000..8f5e0f517 --- /dev/null +++ b/admin/src/Dashboard.tsx @@ -0,0 +1,159 @@ +import { + Card, + Link, + Space, + Grid, + Divider, + Typography, +} from '@arco-design/web-react'; +import { IconApps, IconUser, IconUserGroup } from 'tushan/icon'; +import React, { useState, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; + + + +export const Dashboard: React.FC = React.memo(() => { + + const [userCount, setUserCount] = useState(0); //用户数量 + const [kbCount, setkbCount] = useState(0); + const [modelCount, setmodelCount] = useState(0); + useEffect(() => { + const fetchCounts = async () => { + const userResponse = await fetch('http://localhost:3001/users', { + headers: { 'Content-Type': 'application/json' }, + }); + const kbResponse = await fetch('http://localhost:3001/kbs', { + headers: { 'Content-Type': 'application/json' }, + }); + const modelResponse = await fetch('http://localhost:3001/models', { + headers: { 'Content-Type': 'application/json' }, + }); + + const userTotalCount = userResponse.headers.get('X-Total-Count'); + const kbTotalCount = kbResponse.headers.get('X-Total-Count'); + const modelTotalCount = modelResponse.headers.get('X-Total-Count'); + + if (userTotalCount) { + setUserCount(Number(userTotalCount)); + } + if (kbTotalCount) { + setkbCount(Number(kbTotalCount)); + } + if (modelTotalCount) { + setmodelCount(Number(modelTotalCount)); + } + }; + + fetchCounts(); + }, []); + + return ( +
+
+ + + + {'你好,管理员'} + + + + + + + {/* 把 userCount 传递给 DataItem 组件 */} + } + title={'用户'} + count={userCount} + /> + + + + + + } + title={'知识库'} + count={kbCount} + /> + + + + + + } + title={'AI模型'} + count={modelCount} + /> + + + + + + + + +
+
+ ); +}); +Dashboard.displayName = 'Dashboard'; + +const DashboardItem: React.FC< + React.PropsWithChildren<{ + title: string; + href?: string; + }> +> = React.memo((props) => { + const { t } = useTranslation(); + + return ( + + {t('tushan.dashboard.more')} + + ) + } + bordered={false} + style={{ overflow: 'hidden' }} + > + {props.children} + + ); +}); +DashboardItem.displayName = 'DashboardItem'; + +const DataItem: React.FC<{ + icon: React.ReactElement; + title: string; + count: number; +}> = React.memo((props) => { + return ( + +
+ {props.icon} +
+
+
{props.title}
+
{props.count}
+
+
+ ); +}); +DataItem.displayName = 'DataItem'; diff --git a/admin/src/fields.ts b/admin/src/fields.ts index 057498ef0..08ec91afc 100644 --- a/admin/src/fields.ts +++ b/admin/src/fields.ts @@ -1,4 +1,7 @@ -import { createTextField, createNumberField } from 'tushan'; +import { + createTextField, + createNumberField, +} from 'tushan'; export const userFields = [ createTextField('id', { label: 'ID' }),