From f4cb3eacf8e31687943e171dda804a5580cad93d Mon Sep 17 00:00:00 2001 From: whyour Date: Thu, 22 Aug 2024 00:47:24 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=97=A5=E5=BF=97=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=97=B6=E9=97=B4=E7=AD=9B=E9=80=89=E5=92=8C=E6=B8=85?= =?UTF-8?q?=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/api/system.ts | 45 +++++++++-- back/services/system.ts | 30 ++++++- back/services/user.ts | 5 +- package.json | 1 + pnpm-lock.yaml | 21 ++--- shell/preload/sitecustomize.js | 6 +- shell/preload/sitecustomize.py | 5 +- src/layouts/index.less | 5 ++ src/pages/setting/index.tsx | 30 ++----- src/pages/setting/systemLog.tsx | 139 +++++++++++++++++++++++++------- 10 files changed, 209 insertions(+), 78 deletions(-) diff --git a/back/api/system.ts b/back/api/system.ts index 33beddc4..0680260d 100644 --- a/back/api/system.ts +++ b/back/api/system.ts @@ -340,12 +340,41 @@ export default (app: Router) => { }, ); - route.get('/log', async (req: Request, res: Response, next: NextFunction) => { - try { - const systemService = Container.get(SystemService); - await systemService.getSystemLog(res); - } catch (e) { - return next(e); - } - }); + route.get( + '/log', + celebrate({ + query: { + startTime: Joi.string().allow('').optional(), + endTime: Joi.string().allow('').optional(), + t: Joi.string().optional(), + }, + }), + async (req: Request, res: Response, next: NextFunction) => { + try { + const systemService = Container.get(SystemService); + await systemService.getSystemLog( + res, + req.query as { + startTime?: string; + endTime?: string; + }, + ); + } catch (e) { + return next(e); + } + }, + ); + + route.delete( + '/log', + async (req: Request, res: Response, next: NextFunction) => { + try { + const systemService = Container.get(SystemService); + await systemService.deleteSystemLog(); + res.send({ code: 200 }); + } catch (e) { + return next(e); + } + }, + ); }; diff --git a/back/services/system.ts b/back/services/system.ts index f74713cb..eceb1697 100644 --- a/back/services/system.ts +++ b/back/services/system.ts @@ -15,6 +15,7 @@ import { parseVersion, promiseExec, readDirs, + rmPath, } from '../config/util'; import { DependenceModel, @@ -34,6 +35,7 @@ import NotificationService from './notify'; import ScheduleService, { TaskCallbacks } from './schedule'; import SockService from './sock'; import os from 'os'; +import dayjs from 'dayjs'; @Service() export default class SystemService { @@ -409,9 +411,25 @@ export default class SystemService { } } - public async getSystemLog(res: Response) { + public async getSystemLog( + res: Response, + query: { + startTime?: string; + endTime?: string; + }, + ) { + const startTime = dayjs(query.startTime || undefined) + .startOf('d') + .valueOf(); + const endTime = dayjs(query.endTime || undefined) + .endOf('d') + .valueOf(); const result = await readDirs(config.systemLogPath, config.systemLogPath); - const logs = result.reverse().filter((x) => x.title.endsWith('.log')); + const logs = result + .reverse() + .filter((x) => x.title.endsWith('.log')) + .filter((x) => x.mtime >= startTime && x.mtime <= endTime); + res.set({ 'Content-Length': sum(logs.map((x) => x.size)), }); @@ -433,4 +451,12 @@ export default class SystemService { } })(res, logs); } + + public async deleteSystemLog() { + const result = await readDirs(config.systemLogPath, config.systemLogPath); + const logs = result.reverse().filter((x) => x.title.endsWith('.log')); + for (const log of logs) { + await rmPath(path.join(config.systemLogPath, log.title)); + } + } } diff --git a/back/services/user.ts b/back/services/user.ts index 94a66047..92d6fb08 100644 --- a/back/services/user.ts +++ b/back/services/user.ts @@ -154,6 +154,7 @@ export default class UserService { status: LoginStatus.success, }, }); + this.getLoginLog(); return { code: 200, data: { token, lastip, lastaddr, lastlogon, retries, platform }, @@ -182,6 +183,7 @@ export default class UserService { status: LoginStatus.fail, }, }); + this.getLoginLog(); if (retries > 2) { const waitTime = Math.round(Math.pow(3, retries + 1)); return { @@ -215,8 +217,9 @@ export default class UserService { (a, b) => b.info!.timestamp! - a.info!.timestamp!, ); if (result.length > 100) { + const ids = result.slice(0, result.length - 100).map((x) => x.id!); await SystemModel.destroy({ - where: { id: result[result.length - 1].id }, + where: { id: ids }, }); } return result.map((x) => x.info); diff --git a/package.json b/package.json index cc3e2308..b05bd3e7 100644 --- a/package.json +++ b/package.json @@ -103,6 +103,7 @@ "ip2region": "2.3.0" }, "devDependencies": { + "moment": "2.30.1", "@ant-design/icons": "^4.7.0", "@ant-design/pro-layout": "6.38.22", "@monaco-editor/react": "4.2.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c643cddf..e27dd14b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -262,6 +262,9 @@ devDependencies: lint-staged: specifier: ^13.0.3 version: 13.2.2 + moment: + specifier: 2.30.1 + version: 2.30.1 monaco-editor: specifier: 0.33.0 version: 0.33.0 @@ -855,7 +858,7 @@ packages: '@babel/runtime': 7.23.1 antd: 4.24.10(react-dom@18.2.0)(react@18.2.0) classnames: 2.3.2 - moment: 2.29.4 + moment: 2.30.1 rc-util: 5.37.0(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -6263,7 +6266,7 @@ packages: fast-deep-equal: 3.1.3 intl: 1.2.5 lodash: 4.17.21 - moment: 2.29.4 + moment: 2.30.1 qiankun: 2.10.8 react-intl: 3.12.1(react@18.2.0) react-redux: 8.0.7(@types/react-dom@18.2.4)(@types/react@18.2.8)(react-dom@18.2.0)(react@18.2.0)(redux@4.2.1) @@ -6849,7 +6852,7 @@ packages: classnames: 2.3.2 copy-to-clipboard: 3.3.3 lodash: 4.17.21 - moment: 2.29.4 + moment: 2.30.1 rc-cascader: 3.7.2(react-dom@18.2.0)(react@18.2.0) rc-checkbox: 3.0.1(react-dom@18.2.0)(react@18.2.0) rc-collapse: 3.4.2(react-dom@18.2.0)(react@18.2.0) @@ -9394,7 +9397,7 @@ packages: /file-stream-rotator@0.6.1: resolution: {integrity: sha512-u+dBid4PvZw17PmDeRcNOtCP9CCK/9lRN2w+r1xIS7yOL9JFrIBKTvrYsxT4P0pGtThYTn++QS5ChHaUov3+zQ==} dependencies: - moment: 2.29.4 + moment: 2.30.1 dev: false /file-uri-to-path@2.0.0: @@ -11619,11 +11622,11 @@ packages: /moment-timezone@0.5.43: resolution: {integrity: sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==} dependencies: - moment: 2.29.4 + moment: 2.30.1 dev: false - /moment@2.29.4: - resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==} + /moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} /monaco-editor@0.33.0: resolution: {integrity: sha512-VcRWPSLIUEgQJQIE0pVT8FcGBIgFoxz7jtqctE+IiCxWugD0DwgyQBcZBhdSrdMC84eumoqMZsGl2GTreOzwqw==} @@ -13757,7 +13760,7 @@ packages: classnames: 2.3.2 date-fns: 2.30.0 dayjs: 1.11.8 - moment: 2.29.4 + moment: 2.30.1 rc-trigger: 5.3.4(react-dom@18.2.0)(react@18.2.0) rc-util: 5.37.0(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 @@ -15115,7 +15118,7 @@ packages: dottie: 2.0.3 inflection: 1.13.4 lodash: 4.17.21 - moment: 2.29.4 + moment: 2.30.1 moment-timezone: 0.5.43 pg-connection-string: 2.6.0 retry-as-promised: 7.0.4 diff --git a/shell/preload/sitecustomize.js b/shell/preload/sitecustomize.js index d313dacc..ab62e194 100644 --- a/shell/preload/sitecustomize.js +++ b/shell/preload/sitecustomize.js @@ -41,8 +41,8 @@ function run() { .replace(/"/g, '\\"') .replace(/\$/g, '\\$'); command = `${command} && eval '${escapeTaskBefore}'`; + console.log('执行前置命令\n'); } - console.log('执行前置命令\n'); const res = execSync( `${command} && echo -e '${splitStr}' && NODE_OPTIONS= node -p 'JSON.stringify(process.env)'"`, { @@ -55,7 +55,9 @@ function run() { process.env[key] = newEnvObject[key]; } console.log(output); - console.log('执行前置命令结束\n'); + if (task_before) { + console.log('执行前置命令结束\n'); + } } catch (error) { if (!error.message.includes('spawnSync /bin/sh E2BIG')) { console.log(`run task before error: `, error); diff --git a/shell/preload/sitecustomize.py b/shell/preload/sitecustomize.py index 9d27be4e..bd73978a 100644 --- a/shell/preload/sitecustomize.py +++ b/shell/preload/sitecustomize.py @@ -46,11 +46,11 @@ def run(): if task_before: escape_task_before = task_before.replace('"', '\\"').replace("$", "\\$") command += f" && eval '{escape_task_before}'" + print("执行前置命令\n") python_command = "PYTHONPATH= python3 -c 'import os, json; print(json.dumps(dict(os.environ)))'" command += f" && echo -e '{split_str}' && {python_command}\"" - print("执行前置命令\n") res = subprocess.check_output(command, shell=True, encoding="utf-8") output, env_str = res.split(split_str) @@ -60,7 +60,8 @@ def run(): os.environ[key] = value print(output) - print("执行前置命令结束") + if task_before: + print("执行前置命令结束") except subprocess.CalledProcessError as error: print(f"run task before error: {error}") diff --git a/src/layouts/index.less b/src/layouts/index.less index da85cf7e..dc40501f 100644 --- a/src/layouts/index.less +++ b/src/layouts/index.less @@ -462,3 +462,8 @@ body[data-dark='true'] { --antd-arrow-background-color: rgb(24, 26, 27); } } + +.ant-tabs-content-holder { + flex: 1; + overflow-y: auto; +} diff --git a/src/pages/setting/index.tsx b/src/pages/setting/index.tsx index 78d1e0c4..bfa1f634 100644 --- a/src/pages/setting/index.tsx +++ b/src/pages/setting/index.tsx @@ -124,15 +124,14 @@ const Setting = () => { const [editedApp, setEditedApp] = useState(); const [tabActiveKey, setTabActiveKey] = useState('security'); const [loginLogData, setLoginLogData] = useState([]); - const [systemLogData, setSystemLogData] = useState(''); const [notificationInfo, setNotificationInfo] = useState(); const containergRef = useRef(null); const [height, setHeight] = useState(0); useResizeObserver(containergRef, (entry) => { const _height = entry.target.parentElement?.parentElement?.offsetHeight; - if (_height && height !== _height - 66) { - setHeight(_height - 66); + if (_height && height !== _height - 110) { + setHeight(_height - 110); } }); @@ -253,19 +252,6 @@ const Setting = () => { }); }; - const getSystemLog = () => { - request - .get(`${config.apiPrefix}system/log`, { - responseType: 'blob', - }) - .then(async (res) => { - setSystemLogData(await res.text()); - }) - .catch((error: any) => { - console.log(error); - }); - }; - const tabChange = (activeKey: string) => { setTabActiveKey(activeKey); if (activeKey === 'app') { @@ -274,8 +260,6 @@ const Setting = () => { getLoginLog(); } else if (activeKey === 'notification') { getNotification(); - } else if (activeKey === 'syslog') { - getSystemLog(); } }; @@ -315,12 +299,14 @@ const Setting = () => { : [] } > -
+
{ { key: 'syslog', label: intl.get('系统日志'), - children: ( - - ), + children: , }, { key: 'login', @@ -383,7 +367,7 @@ const Setting = () => { children: , }, ]} - > + />
{ +const { RangePicker } = DatePicker; + +const SystemLog = ({ height, theme }: any) => { const editorRef = useRef(null); + const panelVisiableRef = useRef<[string, string] | false>(); + const [range, setRange] = useState(['', '']); + const [systemLogData, setSystemLogData] = useState(''); + + const { loading, refresh } = useRequest( + () => { + return request.get( + `${config.apiPrefix}system/log?startTime=${range[0]}&endTime=${range[1]}`, + { + responseType: 'blob', + }, + ); + }, + { + refreshDeps: [range], + async onSuccess(res) { + setSystemLogData(await res.text()); + }, + }, + ); const scrollTo = (position: 'start' | 'end') => { editorRef.current.scrollDOM.scrollTo({ @@ -15,42 +41,93 @@ const SystemLog = ({ data, height, theme }: any) => { }); }; + const deleteLog = () => { + request.delete(`${config.apiPrefix}system/log`).then((x) => { + message.success('删除成功'); + refresh(); + }); + }; + return (
- { - editorRef.current = view; - }} - readOnly={true} - theme={theme.includes('dark') ? 'dark' : 'light'} - /> -
-
+ {systemLogData ? ( + <> + { + editorRef.current = view; + }} + readOnly={true} + theme={theme.includes('dark') ? 'dark' : 'light'} + /> +
+
+ + ) : loading ? ( + + ) : ( + + )}
); };