新增功能:界面输出分类并使用不同颜色显示
This commit is contained in:
parent
1c484d3f77
commit
60f43d42be
8 changed files with 99 additions and 34 deletions
|
@ -5,7 +5,7 @@ import requests
|
||||||
|
|
||||||
from launcher.file.extract import extract_7z_file
|
from launcher.file.extract import extract_7z_file
|
||||||
from launcher.file.utils import format_size
|
from launcher.file.utils import format_size
|
||||||
from launcher.webview.events import custom_event
|
from launcher.webview.events import custom_event, LogType
|
||||||
|
|
||||||
|
|
||||||
def download_file(download_name, download_url, destination_folder):
|
def download_file(download_name, download_url, destination_folder):
|
||||||
|
@ -21,7 +21,7 @@ def download_file(download_name, download_url, destination_folder):
|
||||||
|
|
||||||
filename = os.path.basename(download_url)
|
filename = os.path.basename(download_url)
|
||||||
download_path = os.path.join(destination_folder, filename)
|
download_path = os.path.join(destination_folder, filename)
|
||||||
custom_event(f"开始下载: {download_name}")
|
custom_event(LogType.info, f"开始下载: {download_name}")
|
||||||
|
|
||||||
response = requests.get(download_url, stream=True)
|
response = requests.get(download_url, stream=True)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
|
@ -52,8 +52,8 @@ def download_file(download_name, download_url, destination_folder):
|
||||||
formatted_total_size = format_size(total_size)
|
formatted_total_size = format_size(total_size)
|
||||||
formatted_speed = format_size(download_speed) + "/s"
|
formatted_speed = format_size(download_speed) + "/s"
|
||||||
|
|
||||||
custom_event(
|
custom_event(LogType.info,
|
||||||
f"下载进度: {progress_percent:.2f}% ({formatted_downloaded_size}/{formatted_total_size}), 下载速度: {formatted_speed}")
|
f"下载进度: {progress_percent:.2f}% ({formatted_downloaded_size}/{formatted_total_size}), 下载速度: {formatted_speed}")
|
||||||
last_update_time = current_time # 更新上次更新时间
|
last_update_time = current_time # 更新上次更新时间
|
||||||
|
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
|
@ -63,10 +63,10 @@ def download_file(download_name, download_url, destination_folder):
|
||||||
formatted_total_elapsed_time = f"{total_elapsed_time:.2f} 秒"
|
formatted_total_elapsed_time = f"{total_elapsed_time:.2f} 秒"
|
||||||
formatted_average_download_speed = format_size(average_download_speed) + "/s"
|
formatted_average_download_speed = format_size(average_download_speed) + "/s"
|
||||||
|
|
||||||
custom_event(
|
custom_event(LogType.info,
|
||||||
f"下载完成: {filename}, 耗时: {formatted_total_elapsed_time}, 下载速度: {formatted_average_download_speed}")
|
f"下载完成: {filename}, 耗时: {formatted_total_elapsed_time}, 下载速度: {formatted_average_download_speed}")
|
||||||
else:
|
else:
|
||||||
custom_event(f"下载失败: {response.status_code}")
|
custom_event(LogType.error, f"下载失败: {response.status_code}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -84,7 +84,7 @@ def init_download(download_name, download_url, destination_folder):
|
||||||
def download():
|
def download():
|
||||||
target_folder = os.path.join(download_name)
|
target_folder = os.path.join(download_name)
|
||||||
if os.path.exists(target_folder):
|
if os.path.exists(target_folder):
|
||||||
custom_event(f"{download_name} 文件夹已存在,跳过下载")
|
custom_event(LogType.info, f"{download_name} 文件夹已存在,跳过下载")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
filename = os.path.basename(download_url)
|
filename = os.path.basename(download_url)
|
||||||
|
|
|
@ -5,7 +5,7 @@ from py7zr import py7zr
|
||||||
from py7zr.callbacks import ExtractCallback
|
from py7zr.callbacks import ExtractCallback
|
||||||
|
|
||||||
from launcher.file.utils import format_size
|
from launcher.file.utils import format_size
|
||||||
from launcher.webview.events import custom_event
|
from launcher.webview.events import custom_event, LogType
|
||||||
|
|
||||||
|
|
||||||
class MyExtractCallback(ExtractCallback):
|
class MyExtractCallback(ExtractCallback):
|
||||||
|
@ -24,7 +24,7 @@ class MyExtractCallback(ExtractCallback):
|
||||||
self.total_size += int(wrote_bytes)
|
self.total_size += int(wrote_bytes)
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if current_time - self.last_print_time >= 1.0: # 至少每隔1秒输出一次
|
if current_time - self.last_print_time >= 1.0: # 至少每隔1秒输出一次
|
||||||
custom_event(f"已解压: {format_size(self.total_size)}")
|
custom_event(LogType.info, f"已解压: {format_size(self.total_size)}")
|
||||||
self.last_print_time = current_time
|
self.last_print_time = current_time
|
||||||
|
|
||||||
def report_postprocess(self):
|
def report_postprocess(self):
|
||||||
|
@ -49,7 +49,7 @@ def extract_7z_file(file_name, file_path, destination_folder, delete_after_extra
|
||||||
if not os.path.exists(destination_folder):
|
if not os.path.exists(destination_folder):
|
||||||
os.makedirs(destination_folder)
|
os.makedirs(destination_folder)
|
||||||
|
|
||||||
custom_event(f"开始解压文件: {file_name}")
|
custom_event(LogType.info, f"开始解压文件: {file_name}")
|
||||||
try:
|
try:
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
with py7zr.SevenZipFile(file_path, mode='r') as z:
|
with py7zr.SevenZipFile(file_path, mode='r') as z:
|
||||||
|
@ -58,18 +58,17 @@ def extract_7z_file(file_name, file_path, destination_folder, delete_after_extra
|
||||||
end_time = time.time()
|
end_time = time.time()
|
||||||
total_elapsed_time = end_time - start_time
|
total_elapsed_time = end_time - start_time
|
||||||
formatted_total_elapsed_time = f"{total_elapsed_time:.2f} 秒"
|
formatted_total_elapsed_time = f"{total_elapsed_time:.2f} 秒"
|
||||||
custom_event(
|
custom_event(LogType.info,
|
||||||
f"解压完成: {file_name}, 总大小: {format_size(callback.total_size)}, 耗时: {formatted_total_elapsed_time}")
|
f"解压完成: {file_name}, 总大小: {format_size(callback.total_size)}, 耗时: {formatted_total_elapsed_time}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
e.print_exc()
|
custom_event(LogType.error, f"解压失败: {repr(e)}")
|
||||||
custom_event(f"解压失败: {str(e)}")
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if delete_after_extract:
|
if delete_after_extract:
|
||||||
try:
|
try:
|
||||||
os.remove(file_path)
|
os.remove(file_path)
|
||||||
custom_event(f"删除{file_path}成功")
|
custom_event(LogType.info, f"删除{file_path}成功")
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
custom_event(f"删除{file_path}失败: {str(e)}")
|
custom_event(LogType.error, f"删除{file_path}失败: {repr(e)}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -47,7 +47,7 @@ class SysConfig:
|
||||||
# logger.error(f"配置文件未找到: {self.config_path}")
|
# logger.error(f"配置文件未找到: {self.config_path}")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
# logger.error(f"加载配置文件时出错: {str(e)}")
|
# logger.error(f"加载配置文件时出错: {repr(e)}")
|
||||||
|
|
||||||
def get(self, key):
|
def get(self, key):
|
||||||
return self.config.get(key)
|
return self.config.get(key)
|
||||||
|
|
|
@ -17,7 +17,7 @@ from launcher.file.extract import extract_7z_file
|
||||||
from launcher.file.utils import ensure_directory_exists
|
from launcher.file.utils import ensure_directory_exists
|
||||||
from launcher.log import logger
|
from launcher.log import logger
|
||||||
from launcher.sys_config import sys_config
|
from launcher.sys_config import sys_config
|
||||||
from launcher.webview.events import custom_event
|
from launcher.webview.events import custom_event, LogType
|
||||||
|
|
||||||
command_list = {
|
command_list = {
|
||||||
"download_git": lambda: init_download("git", download_git_url, os.getcwd()),
|
"download_git": lambda: init_download("git", download_git_url, os.getcwd()),
|
||||||
|
@ -35,11 +35,11 @@ command_list = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def read_stream(stream, log_func):
|
def read_stream(stream, log_type):
|
||||||
def process_lines(text_io):
|
def process_lines(text_io):
|
||||||
for line in iter(text_io.readline, ''):
|
for line in iter(text_io.readline, ''):
|
||||||
text = line.rstrip('\n')
|
text = line.rstrip('\n')
|
||||||
custom_event(f"{text.strip()}\n")
|
custom_event(log_type, f"{text.strip()}")
|
||||||
|
|
||||||
detected_encoding = 'utf-8'
|
detected_encoding = 'utf-8'
|
||||||
text_io = io.TextIOWrapper(stream, encoding=detected_encoding, errors='replace')
|
text_io = io.TextIOWrapper(stream, encoding=detected_encoding, errors='replace')
|
||||||
|
@ -128,14 +128,16 @@ class Api:
|
||||||
command = command()
|
command = command()
|
||||||
if callable(command):
|
if callable(command):
|
||||||
return "success" if command() else "failed"
|
return "success" if command() else "failed"
|
||||||
custom_event(command + "\n")
|
if cwd is not None:
|
||||||
|
custom_event(LogType.execute_command, f"路径:{cwd}")
|
||||||
|
custom_event(LogType.execute_command, command)
|
||||||
try:
|
try:
|
||||||
with subprocess.Popen(
|
with subprocess.Popen(
|
||||||
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cwd, bufsize=0,
|
command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cwd, bufsize=0,
|
||||||
universal_newlines=False
|
universal_newlines=False
|
||||||
) as p:
|
) as p:
|
||||||
stdout_thread = threading.Thread(target=read_stream, args=(p.stdout, logger.info))
|
stdout_thread = threading.Thread(target=read_stream, args=(p.stdout, LogType.command_out))
|
||||||
stderr_thread = threading.Thread(target=read_stream, args=(p.stderr, logger.error))
|
stderr_thread = threading.Thread(target=read_stream, args=(p.stderr, LogType.command_out))
|
||||||
|
|
||||||
stdout_thread.start()
|
stdout_thread.start()
|
||||||
stderr_thread.start()
|
stderr_thread.start()
|
||||||
|
@ -149,4 +151,4 @@ class Api:
|
||||||
return "failed"
|
return "failed"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.exception(e)
|
logger.exception(e)
|
||||||
custom_event(str(e))
|
custom_event(LogType.error, repr(e))
|
||||||
|
|
|
@ -1,11 +1,32 @@
|
||||||
import json
|
import json
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
import launcher
|
import launcher
|
||||||
from launcher.log import logger
|
from launcher.log import logger
|
||||||
|
|
||||||
|
|
||||||
def custom_event(data):
|
class LogType(Enum):
|
||||||
logger.info(data)
|
info = "信息"
|
||||||
|
error = "错误"
|
||||||
|
execute_command = "执行命令"
|
||||||
|
command_out = "命令输出"
|
||||||
|
|
||||||
|
|
||||||
|
def custom_event(log_type, data):
|
||||||
|
data = f"[{log_type.value}] {data}"
|
||||||
|
|
||||||
|
match log_type:
|
||||||
|
case LogType.info:
|
||||||
|
logger.info(data)
|
||||||
|
case LogType.error:
|
||||||
|
logger.error(data)
|
||||||
|
case LogType.execute_command:
|
||||||
|
logger.info(data)
|
||||||
|
case LogType.command_out:
|
||||||
|
logger.info(data)
|
||||||
|
case _:
|
||||||
|
logger.info(data)
|
||||||
|
|
||||||
data = json.dumps({"log": data + "\n"})
|
data = json.dumps({"log": data + "\n"})
|
||||||
js = f"var event = new CustomEvent('log', {{detail: {data}}}); window.dispatchEvent(event);"
|
js = f"var event = new CustomEvent('log', {{detail: {data}}}); window.dispatchEvent(event);"
|
||||||
launcher.webview.window.evaluate_js(js)
|
launcher.webview.window.evaluate_js(js)
|
||||||
|
|
9
ui/package-lock.json
generated
9
ui/package-lock.json
generated
|
@ -8,6 +8,7 @@
|
||||||
"name": "ui",
|
"name": "ui",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"highlight.js": "^11.11.1",
|
||||||
"pinia": "^2.2.8",
|
"pinia": "^2.2.8",
|
||||||
"vue": "^3.5.11"
|
"vue": "^3.5.11"
|
||||||
},
|
},
|
||||||
|
@ -2075,11 +2076,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/highlight.js": {
|
"node_modules/highlight.js": {
|
||||||
"version": "11.10.0",
|
"version": "11.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz",
|
"resolved": "https://registry.npmmirror.com/highlight.js/-/highlight.js-11.11.1.tgz",
|
||||||
"integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==",
|
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-3-Clause",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
"format": "prettier --write src/"
|
"format": "prettier --write src/"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"highlight.js": "^11.11.1",
|
||||||
"pinia": "^2.2.8",
|
"pinia": "^2.2.8",
|
||||||
"vue": "^3.5.11"
|
"vue": "^3.5.11"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,14 +1,40 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { darkTheme } from 'naive-ui'
|
import { darkTheme } from 'naive-ui'
|
||||||
|
import hljs from 'highlight.js/lib/core'
|
||||||
|
|
||||||
const log = inject('log')
|
const log = inject('log')
|
||||||
const log_ele = inject('log_ele')
|
const log_ele = inject('log_ele')
|
||||||
|
|
||||||
|
hljs.registerLanguage('naive-log', () => ({
|
||||||
|
contains: [
|
||||||
|
{
|
||||||
|
className: 'info',
|
||||||
|
begin: /\[信息\]/,
|
||||||
|
end: /$/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'error',
|
||||||
|
begin: /\[错误\]/,
|
||||||
|
end: /$/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'execute_command',
|
||||||
|
begin: /\[执行命令\]/,
|
||||||
|
end: /$/
|
||||||
|
},
|
||||||
|
{
|
||||||
|
className: 'command_out',
|
||||||
|
begin: /\[命令输出\]/,
|
||||||
|
end: /$/
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-config-provider :theme="darkTheme" class="provider">
|
<n-config-provider :theme="darkTheme" class="provider" :hljs="hljs">
|
||||||
<n-card class="full" content-style="height: 100%">
|
<n-card class="full" content-style="height: 100%">
|
||||||
<n-log :log="log" class="full" ref="log_ele" />
|
<n-log :log="log" class="full selectable-log" ref="log_ele" language="naive-log" />
|
||||||
</n-card>
|
</n-card>
|
||||||
</n-config-provider>
|
</n-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
@ -23,10 +49,27 @@ const log_ele = inject('log_ele')
|
||||||
height: 100% !important;
|
height: 100% !important;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selectable-log {
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
pre {
|
pre {
|
||||||
word-break: break-all !important;
|
word-break: break-all !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.n-code pre .hljs-info {
|
||||||
|
color: #33ff33;
|
||||||
|
}
|
||||||
|
.n-code pre .hljs-error {
|
||||||
|
color: #ff0000;
|
||||||
|
}
|
||||||
|
.n-code pre .hljs-execute_command {
|
||||||
|
color: #edaf1f;
|
||||||
|
}
|
||||||
|
.n-code pre .hljs-command_out {
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Add table
Reference in a new issue