mirror of
https://github.com/whyour/qinglong.git
synced 2025-07-13 18:16:07 +08:00
修复 command-run 接口日志绑定
This commit is contained in:
parent
0587644a6b
commit
50769c43dd
|
@ -279,14 +279,14 @@ export default (app: Router) => {
|
||||||
res.end();
|
res.end();
|
||||||
},
|
},
|
||||||
onError: async (message: string) => {
|
onError: async (message: string) => {
|
||||||
res.write(`\n${message}`);
|
res.write(message);
|
||||||
const absolutePath = await handleLogPath(logPath);
|
const absolutePath = await handleLogPath(logPath);
|
||||||
await fs.appendFile(absolutePath, `\n${message}`);
|
await fs.appendFile(absolutePath, message);
|
||||||
},
|
},
|
||||||
onLog: async (message: string) => {
|
onLog: async (message: string) => {
|
||||||
res.write(`\n${message}`);
|
res.write(message);
|
||||||
const absolutePath = await handleLogPath(logPath);
|
const absolutePath = await handleLogPath(logPath);
|
||||||
await fs.appendFile(absolutePath, `\n${message}`);
|
await fs.appendFile(absolutePath, message);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -573,7 +573,7 @@ export default class CronService {
|
||||||
return typeof doc.status === 'number' &&
|
return typeof doc.status === 'number' &&
|
||||||
[CrontabStatus.queued, CrontabStatus.running].includes(doc.status)
|
[CrontabStatus.queued, CrontabStatus.running].includes(doc.status)
|
||||||
? '运行中...'
|
? '运行中...'
|
||||||
: '任务空闲中';
|
: '日志不存在...';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ export default class SystemService {
|
||||||
@Inject('logger') private logger: winston.Logger,
|
@Inject('logger') private logger: winston.Logger,
|
||||||
private scheduleService: ScheduleService,
|
private scheduleService: ScheduleService,
|
||||||
private sockService: SockService,
|
private sockService: SockService,
|
||||||
) {}
|
) { }
|
||||||
|
|
||||||
public async getSystemConfig() {
|
public async getSystemConfig() {
|
||||||
const doc = await this.getDb({ type: AuthDataType.systemConfig });
|
const doc = await this.getDb({ type: AuthDataType.systemConfig });
|
||||||
|
@ -287,7 +287,7 @@ export default class SystemService {
|
||||||
);
|
);
|
||||||
const text = await body.text();
|
const text = await body.text();
|
||||||
lastVersionContent = parseContentVersion(text);
|
lastVersionContent = parseContentVersion(text);
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
|
|
||||||
if (!lastVersionContent) {
|
if (!lastVersionContent) {
|
||||||
lastVersionContent = currentVersionContent;
|
lastVersionContent = currentVersionContent;
|
||||||
|
@ -401,11 +401,12 @@ export default class SystemService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async run({ command }: { command: string }, callback: TaskCallbacks) {
|
public async run({ command, logPath }: { command: string; logPath?: string }, callback: TaskCallbacks) {
|
||||||
if (!command.startsWith(TASK_COMMAND)) {
|
if (!command.startsWith(TASK_COMMAND)) {
|
||||||
command = `${TASK_COMMAND} ${command}`;
|
command = `${TASK_COMMAND} ${command}`;
|
||||||
}
|
}
|
||||||
this.scheduleService.runTask(`real_time=true ${command}`, callback, {
|
const logPathPrefix = logPath ? `real_log_path=${logPath}` : ''
|
||||||
|
this.scheduleService.runTask(`${logPathPrefix} real_time=true ${command}`, callback, {
|
||||||
command,
|
command,
|
||||||
id: command.replace(/ /g, '-'),
|
id: command.replace(/ /g, '-'),
|
||||||
runOrigin: 'system',
|
runOrigin: 'system',
|
||||||
|
@ -442,8 +443,7 @@ export default class SystemService {
|
||||||
}
|
}
|
||||||
const dataPaths = dataDirs.map((dir) => `data/${dir}`);
|
const dataPaths = dataDirs.map((dir) => `data/${dir}`);
|
||||||
await promiseExec(
|
await promiseExec(
|
||||||
`cd ${config.dataPath} && cd ../ && tar -zcvf ${
|
`cd ${config.dataPath} && cd ../ && tar -zcvf ${config.dataTgzFile
|
||||||
config.dataTgzFile
|
|
||||||
} ${dataPaths.join(' ')}`,
|
} ${dataPaths.join(' ')}`,
|
||||||
);
|
);
|
||||||
res.download(config.dataTgzFile);
|
res.download(config.dataTgzFile);
|
||||||
|
@ -537,7 +537,7 @@ export default class SystemService {
|
||||||
try {
|
try {
|
||||||
const finalPath = path.join(config.dependenceCachePath, type);
|
const finalPath = path.join(config.dependenceCachePath, type);
|
||||||
await fs.promises.rm(finalPath, { recursive: true });
|
await fs.promises.rm(finalPath, { recursive: true });
|
||||||
} catch (error) {}
|
} catch (error) { }
|
||||||
return { code: 200 };
|
return { code: 200 };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
shell/pub.sh
10
shell/pub.sh
|
@ -2,13 +2,9 @@
|
||||||
echo -e "开始发布"
|
echo -e "开始发布"
|
||||||
|
|
||||||
echo -e "切换master分支"
|
echo -e "切换master分支"
|
||||||
git checkout master
|
git branch -D master
|
||||||
|
git checkout -b master
|
||||||
echo -e "合并develop代码"
|
git push --set-upstream origin master -f
|
||||||
git merge origin/develop
|
|
||||||
|
|
||||||
echo -e "提交master代码"
|
|
||||||
git push
|
|
||||||
|
|
||||||
echo -e "更新cdn文件"
|
echo -e "更新cdn文件"
|
||||||
ts-node-transpile-only sample/tool.ts
|
ts-node-transpile-only sample/tool.ts
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import intl from 'react-intl-universal';
|
import intl from "react-intl-universal";
|
||||||
import React, { useEffect, useRef, useState } from 'react';
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
message,
|
message,
|
||||||
|
@ -8,17 +8,17 @@ import {
|
||||||
Statistic,
|
Statistic,
|
||||||
Button,
|
Button,
|
||||||
Typography,
|
Typography,
|
||||||
} from 'antd';
|
} from "antd";
|
||||||
import { request } from '@/utils/http';
|
import { request } from "@/utils/http";
|
||||||
import config from '@/utils/config';
|
import config from "@/utils/config";
|
||||||
import {
|
import {
|
||||||
Loading3QuartersOutlined,
|
Loading3QuartersOutlined,
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
} from '@ant-design/icons';
|
} from "@ant-design/icons";
|
||||||
import { PageLoading } from '@ant-design/pro-layout';
|
import { PageLoading } from "@ant-design/pro-layout";
|
||||||
import { logEnded } from '@/utils';
|
import { logEnded } from "@/utils";
|
||||||
import { CrontabStatus } from './type';
|
import { CrontabStatus } from "./type";
|
||||||
import Ansi from 'ansi-to-react';
|
import Ansi from "ansi-to-react";
|
||||||
|
|
||||||
const { Countdown } = Statistic;
|
const { Countdown } = Statistic;
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ const CronLogModal = ({
|
||||||
data?: string;
|
data?: string;
|
||||||
logUrl?: string;
|
logUrl?: string;
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = useState<string>(intl.get('启动中...'));
|
const [value, setValue] = useState<string>(intl.get("启动中..."));
|
||||||
const [loading, setLoading] = useState<any>(true);
|
const [loading, setLoading] = useState<any>(true);
|
||||||
const [executing, setExecuting] = useState<any>(true);
|
const [executing, setExecuting] = useState<any>(true);
|
||||||
const [isPhone, setIsPhone] = useState(false);
|
const [isPhone, setIsPhone] = useState(false);
|
||||||
|
@ -49,15 +49,15 @@ const CronLogModal = ({
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
if (
|
if (
|
||||||
code === 200 &&
|
code === 200 &&
|
||||||
localStorage.getItem('logCron') === uniqPath &&
|
localStorage.getItem("logCron") === uniqPath &&
|
||||||
data !== value
|
data !== value
|
||||||
) {
|
) {
|
||||||
const log = data as string;
|
const log = data as string;
|
||||||
setValue(log || intl.get('暂无日志'));
|
setValue(log || intl.get("暂无日志"));
|
||||||
const hasNext = Boolean(
|
const hasNext = Boolean(
|
||||||
log && !logEnded(log) && !log.includes('任务未运行'),
|
log && !logEnded(log) && !log.includes("日志不存在"),
|
||||||
);
|
);
|
||||||
if (!hasNext && !logEnded(value) && value !== intl.get('启动中...')) {
|
if (!hasNext && !logEnded(value) && value !== intl.get("启动中...")) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
autoScroll();
|
autoScroll();
|
||||||
});
|
});
|
||||||
|
@ -85,13 +85,13 @@ const CronLogModal = ({
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document
|
document
|
||||||
.querySelector('#log-flag')!
|
.querySelector("#log-flag")
|
||||||
.scrollIntoView({ behavior: 'smooth' });
|
?.scrollIntoView({ behavior: "smooth" });
|
||||||
}, 600);
|
}, 600);
|
||||||
};
|
};
|
||||||
|
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
localStorage.removeItem('logCron');
|
localStorage.removeItem("logCron");
|
||||||
handleCancel();
|
handleCancel();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ const CronLogModal = ({
|
||||||
|
|
||||||
const titleElement = () => {
|
const titleElement = () => {
|
||||||
return (
|
return (
|
||||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
<div style={{ display: "flex", alignItems: "center" }}>
|
||||||
{(executing || loading) && <Loading3QuartersOutlined spin />}
|
{(executing || loading) && <Loading3QuartersOutlined spin />}
|
||||||
{!executing && !loading && <CheckCircleOutlined />}
|
{!executing && !loading && <CheckCircleOutlined />}
|
||||||
<Typography.Text ellipsis={true} style={{ marginLeft: 5 }}>
|
<Typography.Text ellipsis={true} style={{ marginLeft: 5 }}>
|
||||||
|
@ -144,7 +144,7 @@ const CronLogModal = ({
|
||||||
onCancel={() => cancel()}
|
onCancel={() => cancel()}
|
||||||
footer={[
|
footer={[
|
||||||
<Button type="primary" onClick={() => cancel()}>
|
<Button type="primary" onClick={() => cancel()}>
|
||||||
{intl.get('知道了')}
|
{intl.get("知道了")}
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
@ -156,9 +156,9 @@ const CronLogModal = ({
|
||||||
style={
|
style={
|
||||||
isPhone
|
isPhone
|
||||||
? {
|
? {
|
||||||
fontFamily: 'Source Code Pro',
|
fontFamily: "Source Code Pro",
|
||||||
zoom: 0.83,
|
zoom: 0.83,
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import { disableBody } from '@/utils';
|
import { disableBody } from "@/utils";
|
||||||
import config from '@/utils/config';
|
import config from "@/utils/config";
|
||||||
import { request } from '@/utils/http';
|
import { request } from "@/utils/http";
|
||||||
import WebSocketManager from '@/utils/websocket';
|
import WebSocketManager from "@/utils/websocket";
|
||||||
import Ansi from 'ansi-to-react';
|
import Ansi from "ansi-to-react";
|
||||||
import { Button, Modal, Statistic, message } from 'antd';
|
import { Button, Modal, Statistic, message } from "antd";
|
||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from "react";
|
||||||
import intl from 'react-intl-universal';
|
import intl from "react-intl-universal";
|
||||||
|
|
||||||
const { Countdown } = Statistic;
|
const { Countdown } = Statistic;
|
||||||
|
|
||||||
const CheckUpdate = ({ systemInfo }: any) => {
|
const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
const [updateLoading, setUpdateLoading] = useState(false);
|
const [updateLoading, setUpdateLoading] = useState(false);
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState("");
|
||||||
const modalRef = useRef<any>();
|
const modalRef = useRef<any>();
|
||||||
|
|
||||||
const checkUpgrade = () => {
|
const checkUpgrade = () => {
|
||||||
if (updateLoading) return;
|
if (updateLoading) return;
|
||||||
setUpdateLoading(true);
|
setUpdateLoading(true);
|
||||||
message.loading(intl.get('检查更新中...'), 0);
|
message.loading(intl.get("检查更新中..."), 0);
|
||||||
request
|
request
|
||||||
.put(`${config.apiPrefix}system/update-check`)
|
.put(`${config.apiPrefix}system/update-check`)
|
||||||
.then(({ code, data }) => {
|
.then(({ code, data }) => {
|
||||||
|
@ -42,22 +42,22 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
const showForceUpdateModal = (data: any) => {
|
const showForceUpdateModal = (data: any) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
width: 500,
|
width: 500,
|
||||||
title: intl.get('更新'),
|
title: intl.get("更新"),
|
||||||
content: (
|
content: (
|
||||||
<>
|
<>
|
||||||
<div>{intl.get('已经是最新版了!')}</div>
|
<div>{intl.get("已经是最新版了!")}</div>
|
||||||
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
|
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
|
||||||
{intl.get('青龙')} {data.lastVersion}{' '}
|
{intl.get("青龙")} {data.lastVersion}{" "}
|
||||||
{intl.get('是目前检测到的最新可用版本了。')}
|
{intl.get("是目前检测到的最新可用版本了。")}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
okText: intl.get('重新下载'),
|
okText: intl.get("重新下载"),
|
||||||
onOk() {
|
onOk() {
|
||||||
showUpdatingModal();
|
showUpdatingModal();
|
||||||
request
|
request
|
||||||
.put(`${config.apiPrefix}system/update`)
|
.put(`${config.apiPrefix}system/update`)
|
||||||
.then((_data: any) => {})
|
.then((_data: any) => { })
|
||||||
.catch((error: any) => {
|
.catch((error: any) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
@ -71,10 +71,10 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
width: 500,
|
width: 500,
|
||||||
title: (
|
title: (
|
||||||
<>
|
<>
|
||||||
<div>{intl.get('更新可用')}</div>
|
<div>{intl.get("更新可用")}</div>
|
||||||
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
|
<div style={{ fontSize: 12, fontWeight: 400, marginTop: 5 }}>
|
||||||
{intl.get('新版本')} {lastVersion}{' '}
|
{intl.get("新版本")} {lastVersion}{" "}
|
||||||
{intl.get('可用,你使用的版本为')} {systemInfo.version}。
|
{intl.get("可用,你使用的版本为")} {systemInfo.version}。
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
@ -83,13 +83,13 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
<Ansi>{lastLog}</Ansi>
|
<Ansi>{lastLog}</Ansi>
|
||||||
</pre>
|
</pre>
|
||||||
),
|
),
|
||||||
okText: intl.get('下载更新'),
|
okText: intl.get("下载更新"),
|
||||||
cancelText: intl.get('以后再说'),
|
cancelText: intl.get("以后再说"),
|
||||||
onOk() {
|
onOk() {
|
||||||
showUpdatingModal();
|
showUpdatingModal();
|
||||||
request
|
request
|
||||||
.put(`${config.apiPrefix}system/update`)
|
.put(`${config.apiPrefix}system/update`)
|
||||||
.then((_data: any) => {})
|
.then((_data: any) => { })
|
||||||
.catch((error: any) => {
|
.catch((error: any) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
|
@ -98,14 +98,14 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const showUpdatingModal = () => {
|
const showUpdatingModal = () => {
|
||||||
setValue('');
|
setValue("");
|
||||||
modalRef.current = Modal.info({
|
modalRef.current = Modal.info({
|
||||||
width: 600,
|
width: 600,
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
closable: false,
|
closable: false,
|
||||||
keyboard: false,
|
keyboard: false,
|
||||||
okButtonProps: { disabled: true },
|
okButtonProps: { disabled: true },
|
||||||
title: intl.get('下载更新中...'),
|
title: intl.get("下载更新中..."),
|
||||||
centered: true,
|
centered: true,
|
||||||
content: (
|
content: (
|
||||||
<pre>
|
<pre>
|
||||||
|
@ -122,13 +122,13 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
message.success({
|
message.success({
|
||||||
content: (
|
content: (
|
||||||
<span>
|
<span>
|
||||||
{intl.get('系统将在')}
|
{intl.get("系统将在")}
|
||||||
<Countdown
|
<Countdown
|
||||||
className="inline-countdown"
|
className="inline-countdown"
|
||||||
format="ss"
|
format="ss"
|
||||||
value={Date.now() + 1000 * 30}
|
value={Date.now() + 1000 * 30}
|
||||||
/>
|
/>
|
||||||
{intl.get('秒后自动刷新')}
|
{intl.get("秒后自动刷新")}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
duration: 30,
|
duration: 30,
|
||||||
|
@ -147,12 +147,12 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
width: 600,
|
width: 600,
|
||||||
maskClosable: false,
|
maskClosable: false,
|
||||||
title: intl.get('确认重启'),
|
title: intl.get("确认重启"),
|
||||||
centered: true,
|
centered: true,
|
||||||
content: intl.get('系统安装包下载成功,确认重启'),
|
content: intl.get("系统安装包下载成功,确认重启"),
|
||||||
okText: intl.get('重启'),
|
okText: intl.get("重启"),
|
||||||
onOk() {
|
onOk() {
|
||||||
reloadSystem('system');
|
reloadSystem("system");
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
modalRef.current.update({
|
modalRef.current.update({
|
||||||
|
@ -166,7 +166,7 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!value) return;
|
if (!value) return;
|
||||||
const updateFailed = value.includes('失败,请检查');
|
const updateFailed = value.includes("失败,请检查");
|
||||||
|
|
||||||
modalRef.current.update({
|
modalRef.current.update({
|
||||||
maskClosable: updateFailed,
|
maskClosable: updateFailed,
|
||||||
|
@ -185,19 +185,19 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
|
|
||||||
const handleMessage = useCallback((payload: any) => {
|
const handleMessage = useCallback((payload: any) => {
|
||||||
let { message: _message } = payload;
|
let { message: _message } = payload;
|
||||||
const updateFailed = _message.includes('失败,请检查');
|
const updateFailed = _message.includes("失败,请检查");
|
||||||
|
|
||||||
if (updateFailed) {
|
if (updateFailed) {
|
||||||
message.error(intl.get('更新失败,请检查网络及日志或稍后再试'));
|
message.error(intl.get("更新失败,请检查网络及日志或稍后再试"));
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document
|
document
|
||||||
.querySelector('#log-identifier')!
|
.querySelector("#log-identifier")
|
||||||
.scrollIntoView({ behavior: 'smooth' });
|
?.scrollIntoView({ behavior: "smooth" });
|
||||||
}, 600);
|
}, 600);
|
||||||
|
|
||||||
if (_message.includes('更新包下载成功')) {
|
if (_message.includes("更新包下载成功")) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
showReloadModal();
|
showReloadModal();
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
@ -208,24 +208,24 @@ const CheckUpdate = ({ systemInfo }: any) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const ws = WebSocketManager.getInstance();
|
const ws = WebSocketManager.getInstance();
|
||||||
ws.subscribe('updateSystemVersion', handleMessage);
|
ws.subscribe("updateSystemVersion", handleMessage);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
ws.unsubscribe('updateSystemVersion', handleMessage);
|
ws.unsubscribe("updateSystemVersion", handleMessage);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Button type="primary" onClick={checkUpgrade}>
|
<Button type="primary" onClick={checkUpgrade}>
|
||||||
{intl.get('检查更新')}
|
{intl.get("检查更新")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
onClick={() => reloadSystem('reload')}
|
onClick={() => reloadSystem("reload")}
|
||||||
style={{ marginLeft: 8 }}
|
style={{ marginLeft: 8 }}
|
||||||
>
|
>
|
||||||
{intl.get('重新启动')}
|
{intl.get("重新启动")}
|
||||||
</Button>
|
</Button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user