diff --git a/app/assets/scss/common.scss b/app/assets/scss/common.scss
index d5e9838..e4c9473 100644
--- a/app/assets/scss/common.scss
+++ b/app/assets/scss/common.scss
@@ -1,2 +1,45 @@
@use "./markdown/reset.scss";
-@use "./markdown/green.scss";
\ No newline at end of file
+@use "./markdown/green.scss";
+
+// .code-block-wrapper {
+// position: relative;
+// margin: 16px 0;
+// border-radius: 8px;
+// background: #1e1e1e;
+// overflow: hidden;
+// }
+// .code-header {
+// display: flex;
+// justify-content: space-between;
+// align-items: center;
+// padding: 8px 12px;
+// background: #2d2d2d;
+// color: #ccc;
+// font-size: 14px;
+// }
+// .code-lang {
+// font-weight: 600;
+// text-transform: uppercase;
+// }
+// .copy-btn {
+// padding: 4px 8px;
+// border: none;
+// border-radius: 4px;
+// background: #444;
+// color: #fff;
+// cursor: pointer;
+// font-size: 12px;
+// transition: all 0.2s;
+// }
+// .copy-btn:hover {
+// background: #555;
+// }
+// pre {
+// margin: 0;
+// padding: 12px;
+// overflow-x: auto;
+// }
+// code {
+// color: #d4d4d4;
+// font-family: 'Consolas', 'Monaco', monospace;
+// }
\ No newline at end of file
diff --git a/app/components/PostBodyMarkdownEditor.vue b/app/components/PostBodyMarkdownEditor.vue
index e99df00..683a0a0 100644
--- a/app/components/PostBodyMarkdownEditor.vue
+++ b/app/components/PostBodyMarkdownEditor.vue
@@ -28,6 +28,9 @@ function ensureMdEditorStripFrontMatter() {
mdEditorGlobalConfig({
markdownItConfig(md) {
attachMarkdownItStripFrontMatter(md, 'person_panel_strip_fm')
+ md.set({
+ html: false
+ })
},
})
}
diff --git a/app/utils/render-markdown.ts b/app/utils/render-markdown.ts
index 52399c9..cab9db2 100644
--- a/app/utils/render-markdown.ts
+++ b/app/utils/render-markdown.ts
@@ -7,8 +7,50 @@ const md = new MarkdownIt({
linkify: true,
typographer: false,
breaks: true,
+ // // 开启代码块语言识别
+ // highlight: function (str: string, lang: string) {
+ // // 处理语言标签(如果没有指定语言,默认 text)
+ // const language = lang || 'text'
+ // // 生成带语言标识 + 复制按钮的代码块外壳
+ // return `
+ //
+ //
+ //
${md.utils.escapeHtml(str)}
+ //
+ // `
+ // },
})
+// /** 全局复制代码函数(挂载到 window,确保页面可调用) */
+// declare global {
+// interface Window {
+// copyCode: (btn: HTMLButtonElement) => void
+// }
+// }
+
+// // 只在客户端环境注册复制函数
+// if (typeof window !== 'undefined') {
+// window.copyCode = function (btn: HTMLButtonElement) {
+// const codeBlock = btn.closest('.code-block-wrapper')!.querySelector('code')!
+// const text = codeBlock.textContent || ''
+
+// navigator.clipboard.writeText(text).then(() => {
+// const originalText = btn.textContent
+// btn.textContent = '已复制'
+// btn.style.backgroundColor = '#10b981'
+
+// // 2秒后恢复按钮文字
+// setTimeout(() => {
+// btn.textContent = originalText
+// btn.style.backgroundColor = ''
+// }, 2000)
+// })
+// }
+// }
+
/** 将 Markdown 转为可安全用于 `v-html` 的 HTML(禁用源码中的原始 HTML)。 */
export function renderSafeMarkdown(src: string): string {
if (!src.trim()) {
diff --git a/packages/drizzle-pkg/db.sqlite b/packages/drizzle-pkg/db.sqlite
index d3823f1..84ff945 100644
Binary files a/packages/drizzle-pkg/db.sqlite and b/packages/drizzle-pkg/db.sqlite differ
diff --git a/server/plugins/03.error-logger.ts b/server/plugins/03.error-logger.ts
index c0385fe..1b56fa2 100644
--- a/server/plugins/03.error-logger.ts
+++ b/server/plugins/03.error-logger.ts
@@ -2,6 +2,23 @@ import log4js from "logger";
const logger = log4js.getLogger("ERROR");
+/** 路径/路由类「找不到」:只打控制台,不落盘(避免扫描、错 URL 等刷爆 running.log) */
+function isPathNotFoundLikeError(error: unknown): boolean {
+ if (!error || typeof error !== "object") return false;
+ const e = error as NodeJS.ErrnoException & { statusCode?: number; statusMessage?: string };
+ const code = typeof e.code === "string" ? e.code : "";
+ if (code === "ENOENT" || code === "ENOTDIR") return true;
+
+ if (e.statusCode !== 404) return false;
+ const sm = (e.statusMessage ?? "").trim();
+ if (!sm) return true;
+ if (/^not found$/i.test(sm)) return true;
+ if (/page not found/i.test(sm)) return true;
+ if (/^cannot (get|post|put|delete|patch|head)\b/i.test(sm)) return true;
+ if (/no route found|cannot find.*route|static asset.*not found/i.test(sm)) return true;
+ return false;
+}
+
const processHandlersKey = "__personPanelErrorLoggerProcessHandlers";
function installProcessErrorLogging() {
@@ -32,12 +49,19 @@ export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook("error", (error, context) => {
const event = context.event;
const tags = Array.isArray(context.tags) ? (context.tags as string[]).join(",") : "";
- logger.error(
+ const prefix = [
event?.method ?? "",
event?.path ?? "(no request)",
tags ? `[${tags}]` : "",
- "\n",
- error
- );
+ ]
+ .filter(Boolean)
+ .join(" ");
+
+ if (isPathNotFoundLikeError(error)) {
+ console.error(prefix || "(error)", "\n", error);
+ return;
+ }
+
+ logger.error(prefix, "\n", error);
});
});