From 396272908b8c4c129850057a4c80cc8088148f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E7=90=A6?= Date: Fri, 26 Jun 2026 13:37:16 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=A1=B5=E9=9D=A2=E3=80=81?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DBUG?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/admin/AdminTableFilter.vue | 81 ++++- .../src/components/admin/PostHistoryModal.vue | 305 ++++++++++++++---- client/src/composables/useToast.ts | 138 +++++++- client/src/pages/BlogDetail.vue | 167 ++++------ client/src/pages/Services.vue | 16 +- client/src/pages/admin/AccessLogs.vue | 110 +++++-- client/src/pages/admin/Logs.vue | 134 +++++--- client/src/pages/admin/Posts.vue | 135 ++++---- client/src/router.ts | 5 + client/src/services/api.ts | 15 + client/src/utils/markdownRenderer.ts | 134 ++++++-- server/handlers/column.go | 18 ++ server/handlers/post.go | 101 +++--- server/main.go | 1 + server/models/post.go | 1 + server/repositories/code_type_repository.go | 34 ++ server/repositories/column_repository.go | 23 +- server/repositories/post_repository.go | 88 ++++- .../repositories/post_snippet_repository.go | 9 +- 19 files changed, 1105 insertions(+), 410 deletions(-) diff --git a/client/src/components/admin/AdminTableFilter.vue b/client/src/components/admin/AdminTableFilter.vue index 1efc3aa..e7714ff 100644 --- a/client/src/components/admin/AdminTableFilter.vue +++ b/client/src/components/admin/AdminTableFilter.vue @@ -1,6 +1,6 @@ diff --git a/client/src/composables/useToast.ts b/client/src/composables/useToast.ts index 333c7be..fbf2efb 100644 --- a/client/src/composables/useToast.ts +++ b/client/src/composables/useToast.ts @@ -1,23 +1,129 @@ +/** + * 质感提升说明: + * 1. 请确保全局样式或 index.css 中包含以下动画定义: + * * #toast-container { + * position: fixed; top: 2rem; left: 50%; transform: translateX(-50%); + * display: flex; flex-direction: column; gap: 0.75rem; z-index: 9999; + * pointer-events: none; + * } + * .toast-item { + * pointer-events: auto; + * opacity: 0; + * transform: translateY(-16px) scale(0.92); + * transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275); // 物理弹簧曲线 + * will-change: transform, opacity; + * } + * .toast-item.show { + * opacity: 1; + * transform: translateY(0) scale(1); + * } + */ + export const useToast = () => { - const showToast = (message: string, type: 'success' | 'error' = 'success') => { + // 高级感动画:成功的生长对勾 + const getSuccessIcon = () => ` + + + + + + + ` + + // 高级感动画:失败的错落叉号 (新增抖动效果) + const getErrorIcon = () => ` + + + + + + + + ` + + // 高级感动画:信息的优雅提示 (天蓝色丝滑延展) + const getInfoIcon = () => ` + + + + + + + + ` + + // 高级感动画:警告的重点提示 (琥珀色三角 + 抖动) + const getWarningIcon = () => ` + + + + + + + + ` + + type ToastType = 'success' | 'error' | 'info' | 'warning' + + const showToast = (message: string, type: ToastType = 'success') => { const container = document.getElementById('toast-container') if (!container) return const toast = document.createElement('div') - toast.className = `toast ${type === 'success' ? 'toast-success' : 'toast-error'}` + + // 质感核心:毛玻璃 (backdrop-blur) + 微调阴影 (shadow-2xl) + 细腻高光边框 (border-white/10) + const baseClasses = 'toast-item flex items-center gap-3.5 px-4 py-3.5 rounded-2xl border backdrop-blur-xl shadow-2xl transition-all' + + // 状态配置表 (Map映射),消除啰嗦的 if-else + const typeConfig: Record = { + success: { icon: getSuccessIcon(), classes: 'bg-zinc-900/85 border-white/10 shadow-black/40 text-zinc-100' }, + error: { icon: getErrorIcon(), classes: 'bg-red-950/85 border-red-500/20 shadow-red-900/20 text-red-50' }, + info: { icon: getInfoIcon(), classes: 'bg-sky-950/85 border-sky-500/20 shadow-sky-900/20 text-sky-50' }, + warning: { icon: getWarningIcon(), classes: 'bg-amber-950/85 border-amber-500/20 shadow-amber-900/20 text-amber-50' } + } + + const currentConfig = typeConfig[type] || typeConfig.success + toast.className = `${baseClasses} ${currentConfig.classes}` + + // 注入我们设计的原生 SVG 动画 toast.innerHTML = ` - - ${message} + ${currentConfig.icon} + ${message} ` container.appendChild(toast) - // 初始化Lucide图标 - if (window.lucide) { - window.lucide.createIcons() - } - // 显示动画 - requestAnimationFrame(() => toast.classList.add('show')) + requestAnimationFrame(() => { + requestAnimationFrame(() => toast.classList.add('show')) + }) // 3秒后自动隐藏 setTimeout(() => { @@ -26,7 +132,7 @@ export const useToast = () => { }, 3000) } - // 便捷方法 + // 便捷方法保持不变 const success = (message: string) => { showToast(message, 'success') } @@ -34,10 +140,18 @@ export const useToast = () => { const error = (message: string) => { showToast(message, 'error') } + const info = (message: string) => { + showToast(message, 'info') + } + const warning = (message: string) => { + showToast(message, 'warning') + } return { showToast, success, - error + error, + info, + warning } } \ No newline at end of file diff --git a/client/src/pages/BlogDetail.vue b/client/src/pages/BlogDetail.vue index 5523b15..856f4b5 100644 --- a/client/src/pages/BlogDetail.vue +++ b/client/src/pages/BlogDetail.vue @@ -1,10 +1,21 @@