@karinjs/plugin-basic 1.3.3 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,22 +10,26 @@ pnpm add @karinjs/plugin-basic -w
10
10
 
11
11
  ## 基本指令
12
12
 
13
- ```
13
+ ```bash
14
14
  # 关机
15
15
  ```
16
16
 
17
- ```
17
+ ```text
18
18
  # 重启
19
19
  ```
20
20
 
21
- ```
21
+ ```text
22
22
  # 状态
23
23
  ```
24
24
 
25
- ```
25
+ ```text
26
26
  # 插件列表
27
27
  ```
28
28
 
29
- ```
29
+ ```text
30
30
  #web登录
31
31
  ```
32
+
33
+ ```text
34
+ #日志
35
+ ```
@@ -1,62 +1,143 @@
1
1
  import {
2
2
  render
3
- } from "../chunk-AAM3ZLYA.js";
3
+ } from "../chunk-4GSJ5FLI.js";
4
4
 
5
5
  // src/apps/logger.ts
6
6
  import fs from "fs";
7
7
  import path from "path";
8
8
  import { karin, logger } from "node-karin";
9
+ var ESC = "\x1B";
10
+ var ANSI_REGEX = new RegExp(`${ESC}\\[([0-9;]+)m`, "g");
11
+ var escapeHtml = (str) => str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
12
+ var ANSI_COLOR_MAP = {
13
+ 30: "#020617",
14
+ 31: "#ef4444",
15
+ 32: "#22c55e",
16
+ 33: "#eab308",
17
+ 34: "#3b82f6",
18
+ 35: "#ec4899",
19
+ 36: "#06b6d4",
20
+ 37: "#e5e7eb",
21
+ 90: "#6b7280",
22
+ 91: "#f97373",
23
+ 92: "#4ade80",
24
+ 93: "#fde047",
25
+ 94: "#60a5fa",
26
+ 95: "#a855f7",
27
+ 96: "#38bdf8",
28
+ 97: "#f9fafb"
29
+ };
30
+ var LOG_TIME_PREFIX_REGEX = /^\[\d{2}:\d{2}:\d{2}\.\d{3}\]/;
31
+ var LOG_HEADER_REGEX = /^(\[\d{2}:\d{2}:\d{2}\.\d{3}\])(\[(?:INFO|WARN|ERROR|ERRO|FATAL|DEBUG|TRACE|MARK)\])/;
32
+ var LOG_LEVEL_COLOR_CODE = {
33
+ INFO: "\x1B[32m",
34
+ // 绿色
35
+ WARN: "\x1B[33m",
36
+ // 黄色
37
+ ERROR: "\x1B[31m",
38
+ // 红色
39
+ ERRO: "\x1B[31m",
40
+ // 兼容旧字段
41
+ FATAL: "\x1B[35m",
42
+ // 紫色
43
+ DEBUG: "\x1B[90m",
44
+ // 灰色
45
+ TRACE: "\x1B[90m",
46
+ // 灰色
47
+ MARK: "\x1B[90m"
48
+ // 灰色
49
+ };
50
+ var ansi256ToRgb = (idx) => {
51
+ if (idx < 0 || idx > 255 || Number.isNaN(idx)) return null;
52
+ const basicPalette = [
53
+ "#020617",
54
+ // 0: black
55
+ "#ef4444",
56
+ // 1: red
57
+ "#22c55e",
58
+ // 2: green
59
+ "#eab308",
60
+ // 3: yellow
61
+ "#3b82f6",
62
+ // 4: blue
63
+ "#ec4899",
64
+ // 5: magenta
65
+ "#06b6d4",
66
+ // 6: cyan
67
+ "#e5e7eb",
68
+ // 7: white (light gray)
69
+ "#6b7280",
70
+ // 8: bright black (gray)
71
+ "#f97373",
72
+ // 9: bright red
73
+ "#4ade80",
74
+ // 10: bright green
75
+ "#fde047",
76
+ // 11: bright yellow
77
+ "#60a5fa",
78
+ // 12: bright blue
79
+ "#a855f7",
80
+ // 13: bright magenta
81
+ "#38bdf8",
82
+ // 14: bright cyan
83
+ "#f9fafb"
84
+ // 15: bright white
85
+ ];
86
+ if (idx <= 15) {
87
+ return basicPalette[idx];
88
+ }
89
+ if (idx >= 16 && idx <= 231) {
90
+ const n = idx - 16;
91
+ const r = Math.floor(n / 36);
92
+ const g = Math.floor(n % 36 / 6);
93
+ const b = n % 6;
94
+ const conv = (c) => c === 0 ? 0 : 55 + c * 40;
95
+ return `rgb(${conv(r)}, ${conv(g)}, ${conv(b)})`;
96
+ }
97
+ const gray = 8 + (idx - 232) * 10;
98
+ return `rgb(${gray}, ${gray}, ${gray})`;
99
+ };
9
100
  var ansiToHtml = (text) => {
10
101
  if (!text) return "";
11
- const ESC = "\x1B";
12
- const ansiRegex = new RegExp(`${ESC}\\[([0-9;]+)m`, "g");
13
- const escapeHtml = (str) => str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
14
102
  let result = "";
15
103
  let lastIndex = 0;
16
104
  let openSpan = "";
17
- const colorMap = {
18
- 30: "#020617",
19
- 31: "#ef4444",
20
- 32: "#22c55e",
21
- 33: "#eab308",
22
- 34: "#3b82f6",
23
- 35: "#ec4899",
24
- 36: "#06b6d4",
25
- 37: "#e5e7eb",
26
- 90: "#6b7280",
27
- 91: "#f97373",
28
- 92: "#4ade80",
29
- 93: "#fde047",
30
- 94: "#60a5fa",
31
- 95: "#a855f7",
32
- 96: "#38bdf8",
33
- 97: "#f9fafb"
34
- };
35
- text.replace(ansiRegex, (match, codesStr, offset) => {
105
+ text.replace(ANSI_REGEX, (match, codesStr, offset) => {
36
106
  const chunk = text.slice(lastIndex, offset);
37
107
  if (chunk) {
38
108
  result += escapeHtml(chunk);
39
109
  }
40
110
  lastIndex = offset + match.length;
41
- const codes = codesStr.split(";").map((n) => Number(n) || 0);
111
+ const codes = codesStr.split(";").map((n) => parseInt(n, 10));
42
112
  if (openSpan) {
43
113
  result += "</span>";
44
114
  openSpan = "";
45
115
  }
46
- if (codes.includes(0) || codes.includes(39)) {
47
- return "";
48
- }
49
116
  if (codes[0] === 38 && codes[1] === 2 && codes.length >= 5) {
50
117
  const r = codes[2];
51
118
  const g = codes[3];
52
119
  const b = codes[4];
53
- openSpan = `color: rgb(${r}, ${g}, ${b})`;
54
- result += `<span style="${openSpan}">`;
120
+ if (!isNaN(r) && !isNaN(g) && !isNaN(b)) {
121
+ openSpan = `color: rgb(${r}, ${g}, ${b})`;
122
+ result += `<span style="${openSpan}">`;
123
+ }
55
124
  return "";
56
125
  }
57
- const colorCode = codes.find((c) => colorMap[c]);
126
+ if (codes[0] === 38 && codes[1] === 5 && codes.length >= 3) {
127
+ const idx = codes[2];
128
+ const rgb = ansi256ToRgb(idx);
129
+ if (rgb) {
130
+ openSpan = `color: ${rgb}`;
131
+ result += `<span style="${openSpan}">`;
132
+ }
133
+ return "";
134
+ }
135
+ if (codes.length === 1 && (codes[0] === 0 || codes[0] === 39)) {
136
+ return "";
137
+ }
138
+ const colorCode = codes.find((c) => ANSI_COLOR_MAP[c]);
58
139
  if (colorCode !== void 0) {
59
- const color = colorMap[colorCode];
140
+ const color = ANSI_COLOR_MAP[colorCode];
60
141
  openSpan = `color: ${color}`;
61
142
  result += `<span style="${openSpan}">`;
62
143
  return "";
@@ -72,21 +153,19 @@ var ansiToHtml = (text) => {
72
153
  }
73
154
  return result;
74
155
  };
75
- var trimEmptyLines = (text) => {
76
- const lines = text.split("\n");
77
- while (lines.length && !lines[0].trim()) lines.shift();
78
- while (lines.length && !lines[lines.length - 1].trim()) lines.pop();
79
- return lines.join("\n");
156
+ var colorizeLog = (line) => {
157
+ return line.replace(LOG_HEADER_REGEX, (match, timePart, levelPart) => {
158
+ const levelKey = levelPart.replace("[", "").replace("]", "");
159
+ const colorCode = LOG_LEVEL_COLOR_CODE[levelKey] ?? "\x1B[37m";
160
+ return `${colorCode}${timePart}${levelPart}\x1B[0m`;
161
+ });
80
162
  };
81
163
  var groupLogLines = (lines) => {
82
164
  const groups = [];
83
165
  let current = [];
84
- const isNewEntry = (line) => {
85
- const trimmed = line.trim();
86
- if (!trimmed) return false;
87
- return /^\[\d{2}:\d{2}:\d{2}\.\d{3}\]\[[A-Z]+]/.test(trimmed);
88
- };
166
+ const isNewEntry = (line) => LOG_TIME_PREFIX_REGEX.test(line);
89
167
  for (const line of lines) {
168
+ if (!line.trim()) continue;
90
169
  if (isNewEntry(line)) {
91
170
  if (current.length) groups.push(current);
92
171
  current = [line];
@@ -99,9 +178,15 @@ var groupLogLines = (lines) => {
99
178
  }
100
179
  }
101
180
  if (current.length) groups.push(current);
102
- return groups.map((item) => item.join("\n"));
181
+ return groups.map((g) => g.join("\n"));
103
182
  };
104
- var getTodayLogs = async (limit = 50) => {
183
+ var readAndGroupLogFile = (logFile, limit) => {
184
+ const content = fs.readFileSync(logFile, "utf-8");
185
+ const lines = content.split("\n");
186
+ const groups = groupLogLines(lines);
187
+ return groups.slice(-limit);
188
+ };
189
+ var getTodayLogs = async (limit = 100) => {
105
190
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
106
191
  const logDir = path.join(process.cwd(), "@karinjs", "logs");
107
192
  const logFile = path.join(logDir, `logger.${today}.log`);
@@ -112,21 +197,15 @@ var getTodayLogs = async (limit = 50) => {
112
197
  return ["\u6682\u65E0\u65E5\u5FD7\u8BB0\u5F55"];
113
198
  }
114
199
  const latestLog = path.join(logDir, files[0]);
115
- const content2 = fs.readFileSync(latestLog, "utf-8");
116
- const lines2 = content2.split("\n").filter((line) => line.trim());
117
- const groups2 = groupLogLines(lines2);
118
- return groups2.slice(-limit).reverse();
200
+ return readAndGroupLogFile(latestLog, limit);
119
201
  }
120
- const content = fs.readFileSync(logFile, "utf-8");
121
- const lines = content.split("\n").filter((line) => line.trim());
122
- const groups = groupLogLines(lines);
123
- return groups.slice(-limit).reverse();
202
+ return readAndGroupLogFile(logFile, limit);
124
203
  } catch (error) {
125
204
  logger.error("\u8BFB\u53D6\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:", error);
126
205
  return ["\u8BFB\u53D6\u65E5\u5FD7\u5931\u8D25"];
127
206
  }
128
207
  };
129
- var getErrorLogs = async (limit = 50) => {
208
+ var getErrorLogs = async (limit = 100) => {
130
209
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
131
210
  const errorDir = path.join(process.cwd(), "@karinjs", "logs", "error");
132
211
  if (!fs.existsSync(errorDir)) {
@@ -147,47 +226,23 @@ var getErrorLogs = async (limit = 50) => {
147
226
  }
148
227
  }
149
228
  if (!logFile) return [];
150
- const content = fs.readFileSync(logFile, "utf-8");
151
- const lines = content.split("\n").filter((line) => line.trim());
152
- const groups = groupLogLines(lines);
153
- return groups.slice(-limit).reverse();
229
+ return readAndGroupLogFile(logFile, limit);
154
230
  } catch (error) {
155
231
  logger.error("\u8BFB\u53D6\u9519\u8BEF\u65E5\u5FD7\u6587\u4EF6\u5931\u8D25:", error);
156
232
  return [];
157
233
  }
158
234
  };
159
- var parseLogLine = (line) => {
160
- const [firstLine, ...rest] = line.split("\n");
161
- let time = "";
162
- let levelRaw = "INFO";
163
- const timeMatch = firstLine.match(/^\[(\d{2}:\d{2}:\d{2}\.\d{3})]/);
164
- const levelMatch = firstLine.match(/\[([A-Z]+)]/);
165
- if (timeMatch) time = timeMatch[1];
166
- if (levelMatch) levelRaw = levelMatch[1];
167
- const levelKey = levelRaw.toLowerCase();
168
- const level = levelKey === "erro" ? "error" : levelKey;
169
- const messageHead = firstLine.replace(/^\[\d{2}:\d{2}:\d{2}\.\d{3}]\[[A-Z]+]\s*/, "");
170
- const messageTail = rest.length ? "\n" + rest.join("\n") : "";
171
- const fullMessage = trimEmptyLines(`${messageHead}${messageTail}`);
172
- const plainMessage = fullMessage.replace(/\u001b\[[0-9;]+m/g, "");
173
- return {
174
- time,
175
- level,
176
- message: plainMessage,
177
- messageHtml: ansiToHtml(fullMessage)
178
- };
179
- };
180
235
  var logViewer = karin.command(/^#日志\s*(\d+)?$/, async (e) => {
181
236
  const match = e.msg.match(/^#日志\s*(\d+)?$/);
182
237
  let limit = match && match[1] ? Number(match[1]) : 50;
183
238
  if (!Number.isFinite(limit) || limit <= 0) limit = 50;
184
239
  if (limit > 1e3) limit = 1e3;
185
240
  const logs = await getTodayLogs(limit);
186
- const parsedLogs = logs.map(parseLogLine);
241
+ const logsHtml = logs.map((line) => ansiToHtml(colorizeLog(line)));
187
242
  try {
188
243
  const img = await render("logger/index", {
189
- logs: parsedLogs,
190
- total: parsedLogs.length,
244
+ logs: logsHtml,
245
+ total: logs.length,
191
246
  date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
192
247
  });
193
248
  await e.reply(img);
@@ -208,11 +263,11 @@ var errorLogViewer = karin.command(/^#错误日志\s*(\d+)?$/, async (e) => {
208
263
  await e.reply("\u6682\u65E0\u9519\u8BEF\u65E5\u5FD7");
209
264
  return true;
210
265
  }
211
- const parsedLogs = logs.map(parseLogLine);
266
+ const logsHtml = logs.map((line) => ansiToHtml(colorizeLog(line)));
212
267
  try {
213
268
  const img = await render("logger/index", {
214
- logs: parsedLogs,
215
- total: parsedLogs.length,
269
+ logs: logsHtml,
270
+ total: logs.length,
216
271
  date: (/* @__PURE__ */ new Date()).toLocaleString("zh-CN")
217
272
  });
218
273
  await e.reply(img);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cfg
3
- } from "../chunk-ZRGOU5NN.js";
4
- import "../chunk-AAM3ZLYA.js";
3
+ } from "../chunk-TUC5A7K4.js";
4
+ import "../chunk-4GSJ5FLI.js";
5
5
 
6
6
  // src/apps/login.ts
7
7
  import karin, { common, contactFriend, logger, segment } from "node-karin";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cfg
3
- } from "../chunk-ZRGOU5NN.js";
4
- import "../chunk-AAM3ZLYA.js";
3
+ } from "../chunk-TUC5A7K4.js";
4
+ import "../chunk-4GSJ5FLI.js";
5
5
 
6
6
  // src/apps/restart.ts
7
7
  import { common, karin, logger, restart } from "node-karin";
@@ -7,8 +7,8 @@ import {
7
7
  } from "../chunk-ODFXVVIE.js";
8
8
  import {
9
9
  cfg
10
- } from "../chunk-ZRGOU5NN.js";
11
- import "../chunk-AAM3ZLYA.js";
10
+ } from "../chunk-TUC5A7K4.js";
11
+ import "../chunk-4GSJ5FLI.js";
12
12
 
13
13
  // src/apps/status.ts
14
14
  import { karin } from "node-karin";
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  cfg,
3
3
  sendToFirstAdmin
4
- } from "../chunk-ZRGOU5NN.js";
4
+ } from "../chunk-TUC5A7K4.js";
5
5
  import {
6
6
  render
7
- } from "../chunk-AAM3ZLYA.js";
7
+ } from "../chunk-4GSJ5FLI.js";
8
8
 
9
9
  // src/apps/update.ts
10
10
  import fs from "fs";
@@ -7,7 +7,7 @@ import { karinPathBase } from "node-karin";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@karinjs/plugin-basic",
10
- version: "1.3.3",
10
+ version: "1.3.5",
11
11
  description: "Karin\u7684\u57FA\u7840\u63D2\u4EF6,\u63D0\u4F9B\u6700\u57FA\u7840\u7684\u529F\u80FD",
12
12
  homepage: "https://github.com/KarinJS/karin-plugin-basic",
13
13
  bugs: {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  plugin
3
- } from "./chunk-AAM3ZLYA.js";
3
+ } from "./chunk-4GSJ5FLI.js";
4
4
 
5
5
  // src/utils/utils.ts
6
6
  import karin, { config, logger } from "node-karin";
package/dist/index.js CHANGED
@@ -9,10 +9,10 @@ import {
9
9
  } from "./chunk-ODFXVVIE.js";
10
10
  import {
11
11
  cfg
12
- } from "./chunk-ZRGOU5NN.js";
12
+ } from "./chunk-TUC5A7K4.js";
13
13
  import {
14
14
  plugin
15
- } from "./chunk-AAM3ZLYA.js";
15
+ } from "./chunk-4GSJ5FLI.js";
16
16
 
17
17
  // src/index.ts
18
18
  import { logger, restartDirect } from "node-karin";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  cfg
3
- } from "./chunk-ZRGOU5NN.js";
3
+ } from "./chunk-TUC5A7K4.js";
4
4
  import {
5
5
  plugin
6
- } from "./chunk-AAM3ZLYA.js";
6
+ } from "./chunk-4GSJ5FLI.js";
7
7
 
8
8
  // src/web.config.ts
9
9
  import { components, defineConfig } from "node-karin";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@karinjs/plugin-basic",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "Karin的基础插件,提供最基础的功能",
5
5
  "homepage": "https://github.com/KarinJS/karin-plugin-basic",
6
6
  "bugs": {
@@ -1,200 +1,58 @@
1
1
  :root {
2
- --bg-color: #1e1e1e;
3
- --container-bg: #252526;
4
- --text-color: #d4d4d4;
5
- --border-color: #3e3e42;
6
- --header-bg: #333333;
7
- --accent-color: #007acc;
8
-
9
- --level-debug: #b5cea8;
10
- --level-info: #569cd6;
11
- --level-mark: #c586c0;
12
- --level-warn: #ce9178;
13
- --level-error: #f44747;
14
- --level-fatal: #d16969;
2
+ --bg-color: #000000;
3
+ --text-color: #c1c1c1;
4
+ --font-family: 'Consolas', 'Lucida Console', 'Courier New', monospace;
5
+ --border-color: #333333;
15
6
  }
16
7
 
17
- * {
8
+ body {
18
9
  margin: 0;
19
10
  padding: 0;
20
- box-sizing: border-box;
21
- }
22
-
23
- body {
24
- font-family: 'Fira Code', 'Consolas', 'Monaco', 'Courier New', monospace;
25
11
  background-color: var(--bg-color);
26
12
  color: var(--text-color);
27
- padding: 0;
28
- margin: 0;
13
+ font-family: var(--font-family);
29
14
  font-size: 14px;
30
- line-height: 1.5;
31
- }
32
-
33
- .container {
34
- max-width: 100%;
35
- margin: 0;
36
- background: var(--bg-color);
15
+ line-height: 1.15;
16
+ min-height: 100vh;
37
17
  display: flex;
38
18
  flex-direction: column;
39
19
  }
40
20
 
41
21
  .header {
42
- background: var(--header-bg);
43
- padding: 10px 20px;
44
- border-bottom: 1px solid var(--border-color);
22
+ padding: 8px 15px;
23
+ border-bottom: 1px dashed var(--border-color);
24
+ background-color: var(--bg-color);
45
25
  display: flex;
46
26
  justify-content: space-between;
47
27
  align-items: center;
48
- position: sticky;
49
- top: 0;
50
- z-index: 100;
51
- box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
52
- }
53
-
54
- .header h1 {
55
- font-size: 16px;
56
- font-weight: 600;
57
- color: #fff;
58
- margin: 0;
59
- display: flex;
60
- align-items: center;
61
- gap: 10px;
62
28
  }
63
29
 
64
- .header h1::before {
65
- content: '>';
66
- color: var(--accent-color);
30
+ .title {
67
31
  font-weight: bold;
32
+ color: #ffffff;
68
33
  }
69
34
 
70
- .info {
71
- display: flex;
72
- gap: 15px;
73
- font-size: 12px;
74
- color: #cccccc;
75
- }
76
-
77
- .info span {
78
- background: rgba(255, 255, 255, 0.1);
79
- padding: 2px 8px;
80
- border-radius: 3px;
81
- }
82
-
83
- .header-bg-text {
84
- display: none;
85
- }
86
-
87
- .logs-container {
88
- padding: 10px 0;
89
- }
90
-
91
- .log-item {
92
- padding: 2px 10px;
93
- border-left: 3px solid transparent;
94
- transition: background-color 0.1s;
95
- font-size: 13px;
96
- line-height: 1.6;
97
- }
98
-
99
- .log-item:hover {
100
- background-color: #2a2d2e;
101
- }
102
-
103
- .log-content {
104
- display: block;
105
- }
106
-
107
- .log-prefix {
108
- color: #858585;
35
+ .meta {
109
36
  font-size: 12px;
110
- white-space: nowrap;
111
- opacity: 0.9;
112
- margin-right: 8px;
37
+ color: #888888;
113
38
  }
114
39
 
115
- .log-time {
116
- color: #858585;
117
- }
118
-
119
- .log-level {
120
- font-weight: bold;
121
- text-transform: uppercase;
122
- font-size: 12px;
123
- }
124
-
125
- .level-debug {
126
- color: var(--level-debug);
127
- }
128
-
129
- .level-info {
130
- color: var(--level-info);
131
- }
132
-
133
- .level-mark {
134
- color: var(--level-mark);
135
- }
136
-
137
- .level-warn {
138
- color: var(--level-warn);
139
- }
140
-
141
- .level-error {
142
- color: var(--level-error);
143
- }
144
-
145
- .level-fatal {
146
- color: var(--level-fatal);
147
- background: #5a1d1d;
148
- padding: 0 4px;
149
- border-radius: 2px;
150
- }
151
-
152
- .log-message {
40
+ .logs {
41
+ flex: 1;
42
+ padding: 15px;
153
43
  white-space: pre-wrap;
154
- word-break: break-word;
155
- color: #cccccc;
156
- }
157
-
158
- /* Log item border indicators */
159
- .log-item.log-error {
160
- border-left-color: var(--level-error);
161
- background: rgba(244, 71, 71, 0.05);
162
- }
163
-
164
- .log-item.log-warn {
165
- border-left-color: var(--level-warn);
166
- background: rgba(206, 145, 120, 0.05);
167
- }
168
-
169
- .log-item.log-fatal {
170
- border-left-color: var(--level-fatal);
171
- background: rgba(209, 105, 105, 0.1);
44
+ word-break: break-all;
172
45
  }
173
46
 
174
47
  .footer {
175
- padding: 5px 20px;
48
+ padding: 8px 15px;
49
+ border-top: 1px dashed var(--border-color);
50
+ font-size: 12px;
51
+ color: #666666;
176
52
  text-align: center;
177
- color: #666;
178
- font-size: 11px;
179
- border-top: 1px solid var(--border-color);
180
- background: var(--container-bg);
53
+ background-color: var(--bg-color);
181
54
  }
182
55
 
183
- /* Scrollbar */
184
56
  ::-webkit-scrollbar {
185
- width: 10px;
186
- height: 10px;
187
- }
188
-
189
- ::-webkit-scrollbar-track {
190
- background: var(--bg-color);
191
- }
192
-
193
- ::-webkit-scrollbar-thumb {
194
- background: #424242;
195
- border-radius: 5px;
57
+ display: none;
196
58
  }
197
-
198
- ::-webkit-scrollbar-thumb:hover {
199
- background: #4f4f4f;
200
- }
@@ -3,36 +3,19 @@
3
3
 
4
4
  <head>
5
5
  <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Karin 日志</title>
8
6
  <link rel="stylesheet" href="{{pluResPath}}logger/index.css">
9
7
  </head>
10
8
 
11
9
  <body>
12
- <div class="container">
13
- <div class="header">
14
- <h1>Karin 日志</h1>
15
- <div class="info">
16
- <span class="date">{{date}}</span>
17
- <span class="count">共 {{total}} 条日志</span>
18
- </div>
19
- </div>
10
+ <div class="header">
11
+ <div class="title">Karin 日志</div>
12
+ <div class="meta">{{date}} | 共 {{total}} 条日志</div>
13
+ </div>
20
14
 
21
- <div class="logs-container">
22
- {{each logs}}
23
- <div class="log-item log-{{$value.level}}">
24
- <div class="log-content">
25
- <span class="log-prefix">[<span class="log-time">{{$value.time}}</span>][<span
26
- class="log-level level-{{$value.level}}">{{$value.level}}</span>]</span>
27
- <span class="log-message">{{@ $value.messageHtml}}</span>
28
- </div>
29
- </div>
30
- {{/each}}
31
- </div>
15
+ <div class="logs">{{@ logs.join('\n') }}</div>
32
16
 
33
- <div class="footer">
34
- <p>{{sys.copyright}}</p>
35
- </div>
17
+ <div class="footer">
18
+ {{sys.copyright}}
36
19
  </div>
37
20
  </body>
38
21