diff --git a/pkg/core/bootutils/log.py b/pkg/core/bootutils/log.py
index dea961b5..ce53efd5 100644
--- a/pkg/core/bootutils/log.py
+++ b/pkg/core/bootutils/log.py
@@ -36,8 +36,8 @@ async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.
qcg_logger.setLevel(level)
color_formatter = colorlog.ColoredFormatter(
- fmt="%(log_color)s[%(asctime)s.%(msecs)03d] %(pathname)s (%(lineno)d) - [%(levelname)s] :\n %(message)s",
- datefmt="%Y-%m-%d %H:%M:%S",
+ fmt="%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : %(message)s",
+ datefmt="%m-%d %H:%M:%S",
log_colors=log_colors_config,
)
diff --git a/web/package-lock.json b/web/package-lock.json
index 205a2956..a1b258ae 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -15,6 +15,7 @@
"ajv-errors": "^3.0.0",
"ajv-formats": "^3.0.1",
"ajv-i18n": "^4.2.0",
+ "ansi_up": "^6.0.2",
"axios": "^1.7.7",
"codemirror": "^5.65.18",
"core-js": "^3.37.1",
@@ -1334,6 +1335,15 @@
"ajv": "^8.0.0-beta.0"
}
},
+ "node_modules/ansi_up": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/ansi_up/-/ansi_up-6.0.2.tgz",
+ "integrity": "sha512-3G3vKvl1ilEp7J1u6BmULpMA0xVoW/f4Ekqhl8RTrJrhEBkonKn5k3bUc5Xt+qDayA6iDX0jyUh3AbZjB/l0tw==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
diff --git a/web/package.json b/web/package.json
index c02f2737..2420dd2b 100644
--- a/web/package.json
+++ b/web/package.json
@@ -15,6 +15,7 @@
"ajv-errors": "^3.0.0",
"ajv-formats": "^3.0.1",
"ajv-i18n": "^4.2.0",
+ "ansi_up": "^6.0.2",
"axios": "^1.7.7",
"codemirror": "^5.65.18",
"core-js": "^3.37.1",
diff --git a/web/src/pages/Logs.vue b/web/src/pages/Logs.vue
index fbdfb72a..e85d7adc 100644
--- a/web/src/pages/Logs.vue
+++ b/web/src/pages/Logs.vue
@@ -1,14 +1,18 @@
-
+
-
+
+
+
-
+
+
@@ -25,6 +29,7 @@ const snackbar = inject('snackbar');
const { proxy } = getCurrentInstance()
const logContent = ref('')
+const logContentHTML = ref('')
const refresh = () => {
refreshLog()
@@ -35,6 +40,10 @@ let logPointer = {
"start_offset": 0
}
+import { AnsiUp } from 'ansi_up';
+
+const ansiUp = new AnsiUp()
+
const refreshLog = () => {
proxy.$axios.get(`/logs`, {
params: {
@@ -47,8 +56,14 @@ const refreshLog = () => {
return
}
logContent.value += response.data.data.logs
+ logContentHTML.value += ansiUp.ansi_to_html(response.data.data.logs)
logPointer.start_page_number = response.data.data.end_page_number
logPointer.start_offset = response.data.data.end_offset
+
+ if (proxy.$store.state.autoScrollLog) {
+ // 滚动到最底部
+ document.getElementById('log-content-html').scrollTop = document.getElementById('log-content-html').scrollHeight
+ }
}).catch(error => {
snackbar.error(error.message)
})
@@ -73,7 +88,7 @@ onUnmounted(() => {
\ No newline at end of file
+
+#log-content-html {
+ white-space: pre-wrap;
+ overflow-y: auto;
+}
+
diff --git a/web/src/store/index.js b/web/src/store/index.js
index eb041cbc..fa452a9b 100644
--- a/web/src/store/index.js
+++ b/web/src/store/index.js
@@ -6,6 +6,7 @@ export default createStore({
state: {
apiBaseUrl: 'http://localhost:5300/api/v1',
autoRefreshLog: false,
+ autoScrollLog: true,
settingsPageTab: '',
version: 'v0.0.0',
debug: false,