Compare commits
2 Commits
2ac1428c34
...
dbd1abdc1c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbd1abdc1c | ||
|
|
c7da09d327 |
@@ -1,4 +1,4 @@
|
|||||||
@import "./markdown.css";
|
/* @import "./markdown.css"; */
|
||||||
|
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@import "@nuxt/ui";
|
@import "@nuxt/ui";
|
||||||
@@ -7,3 +7,7 @@
|
|||||||
--color-primary: #fb9e3a;
|
--color-primary: #fb9e3a;
|
||||||
--color-secondary: #fcef91;
|
--color-secondary: #fcef91;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--color-gray-800: oklch(85% 0 275);
|
||||||
|
}
|
||||||
@@ -1,565 +0,0 @@
|
|||||||
/* markdown.css
|
|
||||||
默认:明亮 / 白色背景主题
|
|
||||||
同时提供:.dark .prose 覆盖(如需启用 class-based dark 模式)
|
|
||||||
依赖:全局定义的 CSS 变量 --color-primary 和 --color-secondary
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* 平滑滚动 */
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 默认:明亮主题(Light) ---------- */
|
|
||||||
|
|
||||||
/* 美化 prose 内容样式 */
|
|
||||||
.prose {
|
|
||||||
@apply text-gray-800 leading-relaxed;
|
|
||||||
font-feature-settings:
|
|
||||||
"kern" 1,
|
|
||||||
"liga" 1;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 标题层级 */
|
|
||||||
.prose h1 {
|
|
||||||
@apply text-4xl font-bold mt-8 mb-6 pb-4 border-b border-gray-200;
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
background-clip: text;
|
|
||||||
-webkit-background-clip: text;
|
|
||||||
color: transparent;
|
|
||||||
background-size: 200% 200%;
|
|
||||||
animation: gradientShift 3s ease infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h2 {
|
|
||||||
@apply text-3xl font-bold text-gray-900 mt-10 mb-5 pb-3 border-b border-gray-200 relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h2::before {
|
|
||||||
content: "";
|
|
||||||
@apply absolute bottom-0 left-0 w-12 h-0.5 rounded-full;
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h3 {
|
|
||||||
@apply text-2xl font-semibold text-gray-800 mt-8 mb-4;
|
|
||||||
color: rgba(31, 41, 55, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h4 {
|
|
||||||
@apply text-xl font-semibold text-gray-700 mt-7 mb-3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h5 {
|
|
||||||
@apply text-lg font-medium text-gray-700 mt-6 mb-3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h6 {
|
|
||||||
@apply text-base font-medium text-gray-600 mt-5 mb-2 italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 段落和文本 */
|
|
||||||
.prose p {
|
|
||||||
@apply text-gray-700 leading-relaxed mb-5;
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose strong {
|
|
||||||
@apply font-bold px-1 rounded;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(252, 239, 145, 0.22),
|
|
||||||
rgba(251, 158, 58, 0.12)
|
|
||||||
);
|
|
||||||
color: rgba(31, 41, 55, 0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose em {
|
|
||||||
@apply italic px-1 rounded;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
background: rgba(251, 158, 58, 0.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose del {
|
|
||||||
@apply line-through px-1 rounded;
|
|
||||||
color: #ef4444;
|
|
||||||
background: rgba(239, 68, 68, 0.06);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 链接 */
|
|
||||||
.prose a {
|
|
||||||
@apply font-medium relative transition-all duration-300;
|
|
||||||
color: var(--color-secondary);
|
|
||||||
text-decoration: underline;
|
|
||||||
text-underline-offset: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose a:hover {
|
|
||||||
color: var(--color-primary);
|
|
||||||
transform: translateY(1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose a::after {
|
|
||||||
content: "";
|
|
||||||
@apply absolute bottom-0 left-0 w-0 h-0.5 transition-all duration-300;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose a:hover::after {
|
|
||||||
@apply w-full;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 外部链接图标 */
|
|
||||||
.prose a[href^="http"]::before {
|
|
||||||
content: "↗";
|
|
||||||
@apply inline-block mr-1 text-xs translate-y-[2px] opacity-70;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h1 a,
|
|
||||||
.prose h2 a,
|
|
||||||
.prose h3 a,
|
|
||||||
.prose h4 a,
|
|
||||||
.prose h5 a,
|
|
||||||
.prose h6 a {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 列表 */
|
|
||||||
.prose ul {
|
|
||||||
@apply list-none space-y-3 mb-6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose ul li {
|
|
||||||
@apply relative pl-6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose ul li::before {
|
|
||||||
content: "";
|
|
||||||
@apply absolute left-0 top-3 w-1.5 h-1.5 rounded-full;
|
|
||||||
background: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose ol {
|
|
||||||
@apply list-decimal list-inside space-y-3 mb-6;
|
|
||||||
counter-reset: list-counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose ol li {
|
|
||||||
@apply relative pl-8;
|
|
||||||
counter-increment: list-counter;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose ol li::before {
|
|
||||||
content: counter(list-counter);
|
|
||||||
@apply absolute left-0 top-0 w-6 h-6 text-white text-xs rounded-full flex items-center justify-center font-bold;
|
|
||||||
background-image: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 代码块(浅色风格) */
|
|
||||||
.prose pre {
|
|
||||||
@apply rounded-xl p-6 my-8 border shadow-sm overflow-x-auto;
|
|
||||||
border: 1px solid rgba(229, 231, 235, 1); /* gray-200 */
|
|
||||||
background: linear-gradient(180deg, #ffffff, #f8fafc);
|
|
||||||
box-shadow: 0 6px 18px rgba(15, 23, 42, 0.04);
|
|
||||||
backdrop-filter: blur(6px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose code {
|
|
||||||
@apply px-2 py-1 rounded text-sm font-mono;
|
|
||||||
background: rgba(243, 244, 246, 0.8); /* gray-50-ish */
|
|
||||||
border: 1px solid rgba(229, 231, 235, 1);
|
|
||||||
color: #0f172a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose pre code {
|
|
||||||
@apply bg-transparent p-0 text-current border-none;
|
|
||||||
color: #0f172a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 引用块(浅色友好) */
|
|
||||||
.prose blockquote {
|
|
||||||
@apply pl-6 italic text-gray-700 my-8 py-4 pr-6 rounded-r-xl relative overflow-hidden;
|
|
||||||
border-left: 4px solid transparent;
|
|
||||||
border-image: linear-gradient(
|
|
||||||
to bottom,
|
|
||||||
rgba(252, 239, 145, 0.9),
|
|
||||||
rgba(251, 158, 58, 0.9)
|
|
||||||
)
|
|
||||||
1;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(252, 239, 145, 0.06),
|
|
||||||
rgba(255, 255, 255, 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose blockquote::before {
|
|
||||||
content: '"';
|
|
||||||
@apply absolute -top-4 -left-2 text-6xl opacity-20 font-serif;
|
|
||||||
color: var(--color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose blockquote p {
|
|
||||||
@apply mb-3 last:mb-0 relative z-10;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 图片 */
|
|
||||||
.prose img {
|
|
||||||
@apply rounded-2xl my-8 mx-auto transition-all duration-500 border-2;
|
|
||||||
border-color: rgba(226, 232, 240, 0.6); /* gray-200 */
|
|
||||||
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.04);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose img:hover {
|
|
||||||
@apply scale-[1.02];
|
|
||||||
border-color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose figure {
|
|
||||||
@apply my-8 text-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose figcaption {
|
|
||||||
@apply text-sm text-gray-500 mt-3 italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 表格 */
|
|
||||||
.prose table {
|
|
||||||
@apply w-full border-collapse my-8 text-sm rounded-xl overflow-hidden shadow-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose thead {
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(252, 239, 145, 0.18),
|
|
||||||
rgba(251, 158, 58, 0.12)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose th {
|
|
||||||
@apply border px-6 py-4 text-left font-bold text-gray-800 text-sm uppercase tracking-wider;
|
|
||||||
border-color: rgba(226, 232, 240, 0.6);
|
|
||||||
background: rgba(250, 250, 250, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose td {
|
|
||||||
@apply border px-6 py-4 text-gray-700;
|
|
||||||
border-color: rgba(226, 232, 240, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose tr:nth-child(even) {
|
|
||||||
@apply bg-gray-50;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose tr:hover {
|
|
||||||
background: rgba(251, 158, 58, 0.06);
|
|
||||||
transition: background 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 分割线 */
|
|
||||||
.prose hr {
|
|
||||||
@apply border-gray-200 my-12 relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose hr::before {
|
|
||||||
content: "";
|
|
||||||
@apply absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-8 h-8 rounded-full opacity-20;
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 任务列表(checkbox) */
|
|
||||||
.prose input[type="checkbox"] {
|
|
||||||
@apply mr-3 rounded w-5 h-5 transition-all duration-200;
|
|
||||||
background: #fff;
|
|
||||||
border: 1px solid rgba(226, 232, 240, 0.8);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose input[type="checkbox"]:checked {
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose .task-list-item {
|
|
||||||
@apply list-none pl-0 flex items-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose .task-list-item input[type="checkbox"] {
|
|
||||||
@apply mt-0.5 flex-shrink-0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 强调和标记 */
|
|
||||||
.prose mark {
|
|
||||||
@apply px-2 py-1 rounded font-medium;
|
|
||||||
background: linear-gradient(
|
|
||||||
120deg,
|
|
||||||
rgba(252, 239, 145, 0.22),
|
|
||||||
rgba(251, 158, 58, 0.18)
|
|
||||||
);
|
|
||||||
color: #8a4b00;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 键盘按键 */
|
|
||||||
.prose kbd {
|
|
||||||
@apply border rounded-lg px-3 py-1.5 text-sm font-mono shadow-sm;
|
|
||||||
background: rgba(247, 249, 250, 0.9);
|
|
||||||
border-color: rgba(226, 232, 240, 0.8);
|
|
||||||
color: #0f172a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 动画定义 */
|
|
||||||
@keyframes gradientShift {
|
|
||||||
0%,
|
|
||||||
100% {
|
|
||||||
background-position: 0% 50%;
|
|
||||||
}
|
|
||||||
50% {
|
|
||||||
background-position: 100% 50%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 滚动条(浅色) */
|
|
||||||
.prose pre::-webkit-scrollbar {
|
|
||||||
@apply h-2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose pre::-webkit-scrollbar-track {
|
|
||||||
@apply rounded-full;
|
|
||||||
background: rgba(243, 244, 246, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose pre::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: 9999px;
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 移动端优化 */
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.prose {
|
|
||||||
@apply text-base;
|
|
||||||
}
|
|
||||||
.prose h1 {
|
|
||||||
@apply text-3xl;
|
|
||||||
}
|
|
||||||
.prose h2 {
|
|
||||||
@apply text-2xl;
|
|
||||||
}
|
|
||||||
.prose h3 {
|
|
||||||
@apply text-xl;
|
|
||||||
}
|
|
||||||
.prose pre {
|
|
||||||
@apply p-4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 打印优化 */
|
|
||||||
@media print {
|
|
||||||
.prose {
|
|
||||||
@apply text-black;
|
|
||||||
}
|
|
||||||
.prose a {
|
|
||||||
@apply text-black no-underline;
|
|
||||||
}
|
|
||||||
.prose pre {
|
|
||||||
@apply bg-gray-100 border border-gray-300;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- 可选:深色模式覆盖(.dark class 优先) ---------- */
|
|
||||||
/* 如果你使用 Tailwind 的 class-based dark 模式(<html class="dark">),.dark .prose 会生效 */
|
|
||||||
/* 也可替换为 @media (prefers-color-scheme: dark) {...} 来自动跟随系统 dark 模式 */
|
|
||||||
|
|
||||||
.dark .prose {
|
|
||||||
@apply text-gray-200;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .prose h1 {
|
|
||||||
border-color: rgba(55, 65, 81, 0.5);
|
|
||||||
}
|
|
||||||
.dark .prose h2 {
|
|
||||||
color: #fff;
|
|
||||||
border-color: rgba(55, 65, 81, 0.4);
|
|
||||||
}
|
|
||||||
.dark .prose p {
|
|
||||||
@apply text-gray-300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .prose pre {
|
|
||||||
border: 1px solid rgba(55, 65, 81, 0.6);
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(17, 24, 39, 0.9),
|
|
||||||
rgba(31, 41, 55, 0.9)
|
|
||||||
);
|
|
||||||
box-shadow: 0 8px 30px rgba(2, 6, 23, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .prose code {
|
|
||||||
background: rgba(31, 41, 55, 0.6);
|
|
||||||
border: 1px solid rgba(55, 65, 81, 0.5);
|
|
||||||
color: #e6eef8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .prose blockquote {
|
|
||||||
border-image: linear-gradient(
|
|
||||||
to bottom,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
)
|
|
||||||
1;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(255, 255, 255, 0.02),
|
|
||||||
rgba(255, 255, 255, 0)
|
|
||||||
);
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark .prose table thead {
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(252, 239, 145, 0.06),
|
|
||||||
rgba(251, 158, 58, 0.04)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.dark .prose tr:nth-child(even) {
|
|
||||||
background: rgba(255, 255, 255, 0.02);
|
|
||||||
}
|
|
||||||
.dark .prose td,
|
|
||||||
.dark .prose th {
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
.dark .prose img {
|
|
||||||
box-shadow: 0 10px 30px rgba(2, 6, 23, 0.6);
|
|
||||||
border-color: rgba(55, 65, 81, 0.5);
|
|
||||||
}
|
|
||||||
.dark .prose kbd {
|
|
||||||
background: rgba(31, 41, 55, 0.7);
|
|
||||||
border-color: rgba(55, 65, 81, 0.6);
|
|
||||||
color: #e6eef8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 滚动条(深色) */
|
|
||||||
.dark .prose pre::-webkit-scrollbar-track {
|
|
||||||
background: rgba(17, 24, 39, 0.8);
|
|
||||||
}
|
|
||||||
.dark .prose pre::-webkit-scrollbar-thumb {
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.prose {
|
|
||||||
@apply text-gray-200;
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose h1 {
|
|
||||||
border-color: rgba(55, 65, 81, 0.5);
|
|
||||||
}
|
|
||||||
.prose h2 {
|
|
||||||
color: #fff;
|
|
||||||
border-color: rgba(55, 65, 81, 0.4);
|
|
||||||
}
|
|
||||||
.prose p {
|
|
||||||
@apply text-gray-300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose pre {
|
|
||||||
border: 1px solid rgba(55, 65, 81, 0.6);
|
|
||||||
background: linear-gradient(
|
|
||||||
135deg,
|
|
||||||
rgba(17, 24, 39, 0.9),
|
|
||||||
rgba(31, 41, 55, 0.9)
|
|
||||||
);
|
|
||||||
box-shadow: 0 8px 30px rgba(2, 6, 23, 0.6);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose code {
|
|
||||||
background: rgba(31, 41, 55, 0.6);
|
|
||||||
border: 1px solid rgba(55, 65, 81, 0.5);
|
|
||||||
color: #e6eef8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose blockquote {
|
|
||||||
border-image: linear-gradient(
|
|
||||||
to bottom,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
)
|
|
||||||
1;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(255, 255, 255, 0.02),
|
|
||||||
rgba(255, 255, 255, 0)
|
|
||||||
);
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
|
|
||||||
.prose table thead {
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(252, 239, 145, 0.06),
|
|
||||||
rgba(251, 158, 58, 0.04)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.prose tr:nth-child(even) {
|
|
||||||
background: rgba(255, 255, 255, 0.02);
|
|
||||||
}
|
|
||||||
.prose td,
|
|
||||||
.prose th {
|
|
||||||
color: rgba(255, 255, 255, 0.9);
|
|
||||||
}
|
|
||||||
.prose img {
|
|
||||||
box-shadow: 0 10px 30px rgba(2, 6, 23, 0.6);
|
|
||||||
border-color: rgba(55, 65, 81, 0.5);
|
|
||||||
}
|
|
||||||
.prose kbd {
|
|
||||||
background: rgba(31, 41, 55, 0.7);
|
|
||||||
border-color: rgba(55, 65, 81, 0.6);
|
|
||||||
color: #e6eef8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 滚动条(深色) */
|
|
||||||
.prose pre::-webkit-scrollbar-track {
|
|
||||||
background: rgba(17, 24, 39, 0.8);
|
|
||||||
}
|
|
||||||
.prose pre::-webkit-scrollbar-thumb {
|
|
||||||
background-image: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
var(--color-primary),
|
|
||||||
var(--color-secondary)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,7 +31,11 @@
|
|||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
const { data: events } = await useAsyncData("events", () =>
|
const { data: events } = await useAsyncData("events", () =>
|
||||||
queryCollection("events").order("date", "DESC").limit(3).all()
|
queryCollection("events")
|
||||||
|
.where("draft", "=", false)
|
||||||
|
.order("date", "DESC")
|
||||||
|
.limit(3)
|
||||||
|
.all()
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,9 @@
|
|||||||
|
|
||||||
<UMain>
|
<UMain>
|
||||||
<Transition name="page" mode="out-in">
|
<Transition name="page" mode="out-in">
|
||||||
<NuxtPage />
|
<div>
|
||||||
|
<NuxtPage />
|
||||||
|
</div>
|
||||||
</Transition>
|
</Transition>
|
||||||
</UMain>
|
</UMain>
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-white">
|
<div class="min-h-screen">
|
||||||
<!-- 装饰性背景元素(浅色柔和光晕) -->
|
|
||||||
<div class="fixed inset-0 overflow-hidden pointer-events-none">
|
|
||||||
<div class="absolute -top-40 -right-40 w-80 h-80 bg-blue-100/40 rounded-full blur-3xl"></div>
|
|
||||||
<div class="absolute -bottom-40 -left-40 w-80 h-80 bg-purple-100/40 rounded-full blur-3xl"></div>
|
|
||||||
<div
|
|
||||||
class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 w-96 h-96 bg-cyan-100/40 rounded-full blur-3xl">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<section class="relative py-16 px-4 sm:px-6 lg:px-8">
|
<section class="relative py-16 px-4 sm:px-6 lg:px-8">
|
||||||
<div class="container mx-auto max-w-4xl">
|
<div class="container mx-auto max-w-4xl">
|
||||||
<!-- 内容卡片 -->
|
<!-- 内容卡片 -->
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<!-- 卡片装饰边框(浅色渐变) -->
|
<!-- 卡片装饰边框(浅色渐变) -->
|
||||||
<div class="absolute inset-0 bg-gradient-to-r from-blue-100 to-purple-100 rounded-2xl blur-sm"></div>
|
<!-- <div class="absolute inset-0 bg-linear-to-r from-blue-100 to-purple-100 rounded-2xl blur-sm"></div> -->
|
||||||
|
|
||||||
<div class="relative bg-white rounded-xl border border-gray-200 shadow-xl overflow-hidden">
|
<div class="relative rounded-xl border border-gray-200 shadow-xl overflow-hidden">
|
||||||
<!-- 顶部装饰条(明亮渐变) -->
|
<!-- 顶部装饰条(明亮渐变) -->
|
||||||
<div class="h-1 bg-gradient-to-r from-blue-400 via-purple-400 to-cyan-400"></div>
|
<div class="h-1 bg-linear-to-r from-blue-400 via-purple-400 to-cyan-400"></div>
|
||||||
|
|
||||||
<div class="p-8 sm:p-10 lg:p-12">
|
<div class="p-8 sm:p-10 lg:p-12">
|
||||||
<!-- 内容渲染器 -->
|
<!-- 内容渲染器 -->
|
||||||
|
|||||||
@@ -12,7 +12,11 @@
|
|||||||
import type { ChangelogVersionProps } from "@nuxt/ui";
|
import type { ChangelogVersionProps } from "@nuxt/ui";
|
||||||
|
|
||||||
const { data: events } = await useAsyncData("events", () =>
|
const { data: events } = await useAsyncData("events", () =>
|
||||||
queryCollection("events").order("date", "DESC").limit(3).all()
|
queryCollection("events")
|
||||||
|
.where("draft", "=", false)
|
||||||
|
.order("date", "DESC")
|
||||||
|
.limit(3)
|
||||||
|
.all()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 将 news 数据转换成 UBlogPosts 可用格式
|
// 将 news 数据转换成 UBlogPosts 可用格式
|
||||||
|
|||||||
@@ -36,6 +36,10 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { BlogPostProps } from "@nuxt/ui";
|
import type { BlogPostProps } from "@nuxt/ui";
|
||||||
|
|
||||||
|
useSeoMeta({
|
||||||
|
title: "首页",
|
||||||
|
});
|
||||||
|
|
||||||
const heroCta = ref([
|
const heroCta = ref([
|
||||||
{
|
{
|
||||||
label: "立即加入我们",
|
label: "立即加入我们",
|
||||||
|
|||||||
@@ -77,12 +77,12 @@ const columns: TableColumn<Member>[] = [
|
|||||||
// 初中毕业
|
// 初中毕业
|
||||||
// 如果 row.original.graduateYear 不能转换成数字,就写成初中毕业
|
// 如果 row.original.graduateYear 不能转换成数字,就写成初中毕业
|
||||||
// 否则计算届别
|
// 否则计算届别
|
||||||
return isNaN(Number(row.original.graduateYear))
|
return isNaN(Number(row.original.graduateYear)) || row.original.graduateYear.trim() == ""
|
||||||
? "初中毕业"
|
? "初中毕业"
|
||||||
: `初中第 ${Number(row.original.graduateYear) - 1958} 届`;
|
: `初中第 ${Number(row.original.graduateYear) - 1958} 届`;
|
||||||
case "s":
|
case "s":
|
||||||
// 高中毕业
|
// 高中毕业
|
||||||
return isNaN(Number(row.original.graduateYear))
|
return isNaN(Number(row.original.graduateYear)) || row.original.graduateYear.trim() == ""
|
||||||
? "高中毕业"
|
? "高中毕业"
|
||||||
: `高中第 ${Number(row.original.graduateYear) - 1965} 届`;
|
: `高中第 ${Number(row.original.graduateYear) - 1965} 届`;
|
||||||
case "dj1":
|
case "dj1":
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ export default defineContentConfig({
|
|||||||
date: z.coerce.date(),
|
date: z.coerce.date(),
|
||||||
location: z.string(),
|
location: z.string(),
|
||||||
cover: z.string().url(),
|
cover: z.string().url(),
|
||||||
|
draft: z.boolean().optional().default(false)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
// 新闻集合
|
// 新闻集合
|
||||||
@@ -31,6 +32,7 @@ export default defineContentConfig({
|
|||||||
seoTitle: z.string().optional(),
|
seoTitle: z.string().optional(),
|
||||||
seoDescription: z.string().optional(),
|
seoDescription: z.string().optional(),
|
||||||
ogImage: z.string().optional(),
|
ogImage: z.string().optional(),
|
||||||
|
draft: z.boolean().optional().default(false)
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
// 名人堂
|
// 名人堂
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
---
|
---
|
||||||
title: "柔联校友会 20 届历史就职典礼"
|
title: "柔联校友会 20 届理事就职典礼"
|
||||||
subtitle: "中学生写作比赛颁奖"
|
subtitle: "中学生写作比赛颁奖"
|
||||||
date: "2025-10-09"
|
date: "2025-10-09"
|
||||||
location: "富华冷气酒家 2 楼"
|
location: "富华冷气酒家 2 楼"
|
||||||
cover: "/events/20251009-roulian-xiaoyouhui-20th/event-photo-1.jpg"
|
cover: "/events/20251009-roulian-xiaoyouhui-20th/event-photo-1.jpg"
|
||||||
---
|
---
|
||||||
# 柔联校友会 20 届历史就职典礼
|
# 柔联校友会 20 届理事就职典礼
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
柔佛州华校校友联合会日前举办第 20 届理事就职典礼与 2025 年 “林赛花教育基金” 柔佛州中学生现场写作比赛颁奖典礼,由马来西亚华校校友会联合总会会长萧成兴担任监誓人。
|
柔佛州华校校友联合会日前举办第 20 届理事就职典礼与 2025 年 “林赛花教育基金” 柔佛州中学生现场写作比赛颁奖典礼,由马来西亚华校校友会联合总会会长萧成兴担任监誓人。
|
||||||
|
|
||||||
|
|||||||
113
content/events/20251115-graduation-ceremony-60.md
Normal file
113
content/events/20251115-graduation-ceremony-60.md
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
---
|
||||||
|
title: "永平中学第 60 届毕业典礼"
|
||||||
|
subtitle: "暨初中第 67 届毕业典礼"
|
||||||
|
date: "2025-11-15"
|
||||||
|
location: "永平中学邱廉书礼堂"
|
||||||
|
# cover: "/events/20250927-return-to-school/event-photo-1.jpg"
|
||||||
|
draft: false
|
||||||
|
|
||||||
|
# SEO 主要字段
|
||||||
|
description: "永平中学高中第 60 届与初中第 67 届毕业典礼圆满举行,师生与家长齐聚邱廉书礼堂,共同见证学子的重要里程碑,并向荣休教师刘连升老师致以诚挚祝福。"
|
||||||
|
keywords:
|
||||||
|
- 永平中学
|
||||||
|
- 毕业典礼
|
||||||
|
- 高中第60届
|
||||||
|
- 初中第67届
|
||||||
|
- 校园活动
|
||||||
|
- 刘连升老师
|
||||||
|
- 永中校友会
|
||||||
|
|
||||||
|
# Open Graph / Facebook
|
||||||
|
og:
|
||||||
|
title: "永平中学第 60 届毕业典礼|初中第 67 届毕业典礼"
|
||||||
|
description: "2025 年永平中学毕业典礼隆重举行,包含师长致辞、奖学金颁发、荣休老师欢送,以及学生精彩演出等精彩环节。"
|
||||||
|
# image: "/events/20250927-return-to-school/event-photo-1.jpg"
|
||||||
|
type: "article"
|
||||||
|
|
||||||
|
# Twitter 卡片
|
||||||
|
twitter:
|
||||||
|
card: "summary_large_image"
|
||||||
|
title: "永平中学第 60 届毕业典礼"
|
||||||
|
description: "永平中学 2025 毕业典礼精彩回顾:致辞、演出、奖学金颁发与荣休教师表扬。"
|
||||||
|
# image: "/events/20250927-return-to-school/event-photo-1.jpg"
|
||||||
|
|
||||||
|
# 文章结构化数据(可选,Nuxt SEO module 会自动识别)
|
||||||
|
structuredData:
|
||||||
|
"@type": "NewsArticle"
|
||||||
|
headline: "永平中学第 60 届毕业典礼圆满举行"
|
||||||
|
# image: "/events/20250927-return-to-school/event-photo-1.jpg"
|
||||||
|
datePublished: "2025-11-15"
|
||||||
|
author:
|
||||||
|
"@type": "Organization"
|
||||||
|
name: "永平中学校友会"
|
||||||
|
publisher:
|
||||||
|
"@type": "Organization"
|
||||||
|
name: "永平中学"
|
||||||
|
logo:
|
||||||
|
"@type": "ImageObject"
|
||||||
|
url: "/logo.png"
|
||||||
|
---
|
||||||
|
|
||||||
|
# 永平中学高中第 60 届、初中第 67 届毕业典礼圆满举行
|
||||||
|
|
||||||
|
2025 年 11 月 15 日,永平中学邱廉书礼堂见证了一个充满祝福与感动的重要时刻:高中第 60 届与初中第 67 届毕业典礼隆重举行。礼堂内座无虚席,毕业生、家长、师长与嘉宾齐聚一堂,共同庆祝学子们学习旅程的重要里程碑。
|
||||||
|
|
||||||
|
经过六年的努力与成长,高三学生正式迎来人生的新阶段;初三毕业生亦迈向更高层次的挑战。典礼在庄严的国州歌声中启幕,掀开充满意义的一天。
|
||||||
|
|
||||||
|
## 董事长马彣清博士致词(由代表宣读)
|
||||||
|
|
||||||
|
因公务繁忙未克出席,马彣清董事长由董事会秘书长黄仰力董事代表致辞。他转达董事长的寄语:“成功从来不是侥幸,而是毅力不断累积的成果。” 同时肯定毕业生在求学路上的坚持,并勉励他们继续以积极态度面对未来。
|
||||||
|
|
||||||
|
## 张嘉群校长三项叮咛:以品格与眼界开创未来
|
||||||
|
|
||||||
|
张嘉群校长在致辞中寄语毕业生,并提出三项叮咛,期许他们在往后的道路上继续发光发热:
|
||||||
|
|
||||||
|
### 叮咛一:永怀初心
|
||||||
|
|
||||||
|
* 保持对学习的好奇与热情
|
||||||
|
* 无论未来走得多远,都不要忘记自己最初的信念
|
||||||
|
|
||||||
|
### 叮咛二:中正致远
|
||||||
|
|
||||||
|
* 既要正直谦和,也要坚守原则
|
||||||
|
* 不只追求速度,更追求稳健与长远
|
||||||
|
|
||||||
|
### 叮咛三:站在巨人肩膀上成为巨人
|
||||||
|
|
||||||
|
* 以董事、父母与师长为榜样
|
||||||
|
* 持续成长,努力成为对国家、社会与家庭有贡献的人才
|
||||||
|
|
||||||
|
## 柔佛州董联会主席兼校务顾问陈大锦先生致辞
|
||||||
|
|
||||||
|
陈大锦先生分享了他访问上海中医药大学的见闻,特别是该校完善的奖助学金制度。他希望本校辅导处与升学资讯处能协助学生把握机会,踊跃申请明年 9 月开课的相关奖学金,为升学之路开拓更多可能。
|
||||||
|
|
||||||
|
## 欢送刘连升老师光荣荣休
|
||||||
|
|
||||||
|
在典礼上,校方特别举行了“欢送刘连升老师荣休”环节,为这位服务永平中学 35 年、深受师生爱戴的资深教师献上诚挚祝福。
|
||||||
|
|
||||||
|
刘连升老师在任职期间,以其和蔼可亲的性格与渊博的历史知识,陪伴无数学生走过求学阶段。他不仅课堂上“聊古论今”,从古代帝王先烈谈到世界变迁,更在课余时与学生畅谈时事,从传统文化一路聊到新兴科技与 AI 技术,是学生眼中既严谨又风趣的良师益友。
|
||||||
|
|
||||||
|
许多毕业生回忆,与刘老师的关系早已超越师生,成为无话不谈的朋友。他的教学风格温和细腻,待人真诚,使无数学子在成长路上深受启发。
|
||||||
|
|
||||||
|
典礼现场气氛温馨感人,全体与会者向刘老师献上热烈掌声,感谢他 35 年来在校园里的付出与贡献。校方也祝愿刘老师退休生活悠然自得、健康安康,继续以他的人生智慧照亮身边的人。
|
||||||
|
|
||||||
|
## 颁发董事长设立的奖学金
|
||||||
|
|
||||||
|
典礼上同步进行董事长设立的各项奖学金颁发仪式,以表扬在学业、操行与综合表现上有卓越成绩的学生。
|
||||||
|
(详见图集)
|
||||||
|
|
||||||
|
## 特别演出:永中之星冠军林妤桐献唱
|
||||||
|
|
||||||
|
在典礼进入高潮之前,校方安排了一场温馨惊喜表演 —— 第一届“永中之星”冠军、来自初三诚的林妤桐学妹献唱两首歌曲:《Forever Young》以及《凤凰花开的路口》。她以清亮而富感染力的歌声,向高三学长姐献上最真挚的祝福,也为典礼增添一份青春与深情的色彩。
|
||||||
|
|
||||||
|
## 高三教师团队呈献毕业回忆视频
|
||||||
|
|
||||||
|
随后,由高三各班班导师亲自策划的毕业回忆视频在礼堂大屏幕播出。画面记录了学生们在校园中的点点滴滴,从努力备考到日常生活,从欢笑到奋斗,皆在此刻化为珍贵回忆。
|
||||||
|
|
||||||
|
校方希望学生们在未来面对困难与挫折时,也能记起这份勇敢、乐观与纯真,继续向前迈进。
|
||||||
|
|
||||||
|
## 歌声中道别,在掌声中启航
|
||||||
|
|
||||||
|
典礼尾声,高三毕业生深情演唱《再见》,而初三与高三学生共同合唱《毕业歌》,歌声回荡礼堂,为今年的毕业典礼写下温馨句点。现场气氛在歌声中变得格外动人,许多毕业生眼眶泛红,纷纷表示将铭记这一刻。
|
||||||
|
|
||||||
|
上午 11 时正,典礼圆满结束。为感谢师生与来宾的参与,马彣清董事长特别准备了供 600 人享用的自助餐,设宴于礼堂楼下。现场气氛融洽温馨。同时,本校友会也成功招收 14 名新会员,为未来的发展注入新的力量。
|
||||||
57
docs/Statistic Card 建议.md
Normal file
57
docs/Statistic Card 建议.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
### 🎓 校友群体类(展示规模)
|
||||||
|
|
||||||
|
* **注册会员人数**(基础指标)
|
||||||
|
* **校友分布地区数**(如「分布于 12 个国家」)
|
||||||
|
* **历届毕业生总数**
|
||||||
|
* **校友企业数**(若可统计,代表社会影响力)
|
||||||
|
* **理事人数 / 活跃志工人数**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💰 贡献与资源类(展示凝聚力)
|
||||||
|
|
||||||
|
* **教育基金总额**(例如「林赛花教育基金已累计 RM XXX,XXX」)
|
||||||
|
* **奖助学金受惠人数**
|
||||||
|
* **年度捐款总额 / 参与人数**
|
||||||
|
* **历年活动赞助商数量**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🏛️ 历史与传承类(展示深度)
|
||||||
|
|
||||||
|
* **成立年份 / 周年数**(基础指标)
|
||||||
|
* **举办活动次数**(历届聚会 / 座谈 / 校庆)
|
||||||
|
* **出版刊物 / 纪念册数量**
|
||||||
|
* **历届理事会届数**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 🌏 影响与传播类(展示影响面)
|
||||||
|
|
||||||
|
* **官方网站访问量 / 月均访问数**
|
||||||
|
* **社交媒体关注人数 / 互动量**
|
||||||
|
* **媒体报道次数**(可简化为“媒体曝光数”)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### 💡 进阶玩法(让页面更有活力)
|
||||||
|
|
||||||
|
* **“活跃率”**:例如「本年度活动参与率 72%」
|
||||||
|
* **“成长曲线”**:每年会员人数变化趋势(用小图表示)
|
||||||
|
* **“校友情谊值”**:趣味指标,比如根据活动签到 / 捐赠 / 投稿自动算出的综合分数(可 Gamify)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### ✅ 推荐组合(简洁又有格调)
|
||||||
|
|
||||||
|
| 分类 | 指标 | 示例展示 |
|
||||||
|
| -------- | ------------- | ---------------- |
|
||||||
|
| 校友群体 | 会员总数 | 1,237 位注册会员 |
|
||||||
|
| 成立历程 | 成立时间 | 创立于 1985 年 |
|
||||||
|
| 贡献力量 | 教育基金累计 | RM 245,000 |
|
||||||
|
| 活动热度 | 年度活动次数 | 12 场活动 |
|
||||||
|
| 社群影响 | Facebook 关注 | 3.4k Followers |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
要我帮你把这五个指标设计成一个统一风格的 **Statistic Card UI**(适合放在 Nuxt + @nuxt/ui 项目里)吗?我可以直接给出结构和样式建议 🔥
|
||||||
@@ -5,12 +5,12 @@ export default defineNuxtConfig({
|
|||||||
compatibilityDate: "2025-07-15",
|
compatibilityDate: "2025-07-15",
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
modules: [
|
modules: [
|
||||||
|
"@nuxtjs/seo",
|
||||||
|
"@nuxt/ui",
|
||||||
"@nuxt/content",
|
"@nuxt/content",
|
||||||
"@nuxt/image",
|
"@nuxt/image",
|
||||||
"@nuxt/ui",
|
|
||||||
"reka-ui/nuxt",
|
"reka-ui/nuxt",
|
||||||
"@nuxtjs/robots",
|
"@nuxtjs/robots",
|
||||||
"@nuxtjs/seo",
|
|
||||||
"@nuxtjs/sitemap",
|
"@nuxtjs/sitemap",
|
||||||
],
|
],
|
||||||
css: ["~/assets/css/main.css"],
|
css: ["~/assets/css/main.css"],
|
||||||
|
|||||||
3764
pnpm-lock.yaml
generated
3764
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user