🎨 运行日志流式输出

This commit is contained in:
Cp0204 2024-05-16 13:26:24 +08:00
parent 8e9451d3e9
commit a9a9fe3e99
2 changed files with 50 additions and 24 deletions

View File

@ -2,14 +2,15 @@
# -*- coding: utf-8 -*-
from flask import (
Flask,
render_template,
request,
redirect,
url_for,
session,
jsonify,
send_from_directory,
request,
redirect,
Response,
render_template,
send_from_directory,
stream_with_context,
)
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
@ -140,13 +141,12 @@ def update():
# 处理运行脚本请求
@app.route("/run_script_now", methods=["POST"])
@app.route("/run_script_now", methods=["GET"])
def run_script_now():
if not is_login():
return "未登录"
payload = request.json
task_index = str(payload.get("task_index", ""))
command = [python_path, script_path, config_path, task_index]
task_index = request.args.get("task_index", "")
command = [python_path, "-u", script_path, config_path, task_index]
def generate_output():
process = subprocess.Popen(
@ -154,11 +154,20 @@ def run_script_now():
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
universal_newlines=True,
bufsize=1,
)
for line in process.stdout:
yield line
try:
for line in iter(process.stdout.readline, ""):
yield f"data: {line}\n\n"
yield "data: [DONE]\n\n"
finally:
process.stdout.close()
process.wait()
return Response(generate_output(), mimetype="text/plain")
return Response(
stream_with_context(generate_output()),
content_type="text/event-stream;charset=utf-8",
)
# 定时任务执行的函数

View File

@ -26,6 +26,11 @@
.title {
margin-top: 30px;
}
.modal-body {
max-height: calc(100vh - 200px);
overflow-y: auto;
}
</style>
</head>
@ -230,7 +235,8 @@
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">执行日志</h5>
<h5 class="modal-title">运行日志 <div v-if="modalLoading" class="spinner-border spinner-border-sm m-1" role="status"></div>
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
@ -280,7 +286,8 @@
run_log: "",
taskDirs: [""],
taskDirSelected: "",
taskNameFilter: ""
taskNameFilter: "",
modalLoading: false
},
watch: {
'formData.push_config': {
@ -380,17 +387,27 @@
},
runScriptNow(task_index = "") {
$('#logModal').modal('toggle')
this.run_log = '<div class="spinner-border" role="status"></div> 请耐心等待脚本全部执行完毕...'
axios.post('/run_script_now', {
task_index: task_index,
})
.then(response => {
this.run_log = response.data;
})
.catch(error => {
this.run_log = "错误:\n" + error;
console.error('Error:', error);
});
this.modalLoading = true
this.run_log = ''
const source = new EventSource(`/run_script_now?task_index=${task_index}`);
source.onmessage = (event) => {
if (event.data == "[DONE]") {
this.modalLoading = false
source.close();
} else {
this.run_log += event.data + '\n';
// 在更新 run_log 后将滚动条滚动到底部
this.$nextTick(() => {
const modalBody = document.querySelector('.modal-body');
modalBody.scrollTop = modalBody.scrollHeight;
});
}
};
source.onerror = (error) => {
this.modalLoading = false
console.error('Error:', error);
source.close();
};
},
getParentDirectory(path) {
parentDir = path.substring(0, path.lastIndexOf('/'))