创建Presentation单文件组件
This commit is contained in:
parent
99f00a2297
commit
ed6e484d94
@ -1,5 +1,6 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { getPageData, getAllSlugs } from "@/utils/data";
|
||||
import { getPageData } from "@/utils/data";
|
||||
import Presentation from "@/components/presentation/Presentation";
|
||||
|
||||
export default async function PresentationPage({ params }) {
|
||||
const resolvedParams = await params;
|
||||
@ -14,21 +15,5 @@ export default async function PresentationPage({ params }) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
// PPT展示页面 - 全屏展示
|
||||
return (
|
||||
<div className="min-h-screen bg-black">
|
||||
<div className="w-full h-screen flex items-center justify-center">
|
||||
<div className="w-full h-full relative">
|
||||
<div className="absolute inset-0 bg-black bg-opacity-40 flex items-center justify-center">
|
||||
<div className="text-center text-white max-w-4xl mx-auto px-8">
|
||||
{data.content && (
|
||||
<div className="text-lg md:text-xl mb-8 leading-relaxed"
|
||||
dangerouslySetInnerHTML={{ __html: data.content }} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
return <Presentation data={data} />;
|
||||
}
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
"use client";
|
||||
import { useEffect, useRef } from "react";
|
||||
'use client';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import Reveal from 'reveal.js';
|
||||
import 'reveal.js/dist/reveal.css';
|
||||
import 'reveal.js/dist/theme/white.css';
|
||||
import 'reveal.js/dist/theme/black.css';
|
||||
import { marked } from 'marked';
|
||||
|
||||
export default function UI({ data, showNavButtons = false }) {
|
||||
export default function Presentation({ data }) {
|
||||
const deckRef = useRef(null);
|
||||
const revealRef = useRef(null);
|
||||
|
||||
@ -20,14 +21,6 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
mangle: false,
|
||||
});
|
||||
|
||||
// 将 markdown 内容转换为幻灯片
|
||||
const slides = parseMarkdownToSlides(data);
|
||||
|
||||
// 更新 deck 内容
|
||||
if (deckRef.current) {
|
||||
deckRef.current.innerHTML = slides;
|
||||
}
|
||||
|
||||
// 初始化 Reveal.js
|
||||
if (revealRef.current) {
|
||||
revealRef.current.destroy();
|
||||
@ -73,6 +66,17 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
|
||||
revealRef.current.initialize();
|
||||
|
||||
// 在Reveal.js初始化后,更新slides内容
|
||||
setTimeout(() => {
|
||||
if (deckRef.current) {
|
||||
const slides = parseMarkdownToSlides(data);
|
||||
const slidesContainer = deckRef.current.querySelector('.slides');
|
||||
if (slidesContainer) {
|
||||
slidesContainer.innerHTML = slides;
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
|
||||
// 清理函数
|
||||
return () => {
|
||||
if (revealRef.current) {
|
||||
@ -165,7 +169,7 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="reveal-container" style={{ height: '100vh', width: '100%', position: 'fixed', top: 0, left: 0, zIndex: 1000, background: 'white' }}>
|
||||
<div className="reveal-container" style={{ height: '100vh', width: '100%', position: 'fixed', top: 0, left: 0, zIndex: 1000, background: 'black' }}>
|
||||
<style jsx global>{`
|
||||
.reveal-container .reveal {
|
||||
height: 100% !important;
|
||||
@ -184,6 +188,7 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
align-items: center !important;
|
||||
text-align: center !important;
|
||||
padding: 2rem !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section h1,
|
||||
@ -193,33 +198,38 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
.reveal-container .reveal .slides section h5,
|
||||
.reveal-container .reveal .slides section h6 {
|
||||
margin-bottom: 1rem !important;
|
||||
color: #333 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section p {
|
||||
margin-bottom: 0.5rem !important;
|
||||
line-height: 1.6 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section ul,
|
||||
.reveal-container .reveal .slides section ol {
|
||||
text-align: left !important;
|
||||
margin: 1rem 0 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section li {
|
||||
margin-bottom: 0.5rem !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section code {
|
||||
background: #f4f4f4 !important;
|
||||
background: #333 !important;
|
||||
color: #fff !important;
|
||||
padding: 0.2rem 0.4rem !important;
|
||||
border-radius: 3px !important;
|
||||
font-family: 'Courier New', monospace !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section pre {
|
||||
background: #f4f4f4 !important;
|
||||
background: #333 !important;
|
||||
color: #fff !important;
|
||||
padding: 1rem !important;
|
||||
border-radius: 5px !important;
|
||||
text-align: left !important;
|
||||
@ -227,27 +237,30 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section blockquote {
|
||||
border-left: 4px solid #ddd !important;
|
||||
border-left: 4px solid #666 !important;
|
||||
padding-left: 1rem !important;
|
||||
margin: 1rem 0 !important;
|
||||
text-align: left !important;
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section table {
|
||||
border-collapse: collapse !important;
|
||||
width: 100% !important;
|
||||
margin: 1rem 0 !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section th,
|
||||
.reveal-container .reveal .slides section td {
|
||||
border: 1px solid #ddd !important;
|
||||
border: 1px solid #666 !important;
|
||||
padding: 0.5rem !important;
|
||||
text-align: left !important;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section th {
|
||||
background: #f4f4f4 !important;
|
||||
background: #444 !important;
|
||||
}
|
||||
|
||||
.reveal-container .reveal .slides section img {
|
||||
@ -275,11 +288,12 @@ export default function UI({ data, showNavButtons = false }) {
|
||||
className="reveal"
|
||||
style={{ height: '100%', width: '100%' }}
|
||||
>
|
||||
{/* 初始内容,会被 JavaScript 替换 */}
|
||||
<section>
|
||||
<h1>{data?.title || '演示文稿'}</h1>
|
||||
<p>正在加载内容...</p>
|
||||
</section>
|
||||
<div className="slides">
|
||||
{/* 初始内容,会被 JavaScript 替换 */}
|
||||
<section>
|
||||
<p>正在加载内容...</p>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@ -1,16 +0,0 @@
|
||||
import { getComponentName } from "@/utils/getComponentName";
|
||||
import { fetchComponentData } from "@/utils/data";
|
||||
import UI from "./UI";
|
||||
|
||||
const componentName = getComponentName(import.meta.url);
|
||||
|
||||
export default async function Component() {
|
||||
const result = await fetchComponentData(componentName);
|
||||
|
||||
if (result.error || !result.data) {
|
||||
if (result.error) console.error(`Failed to fetch ${componentName} data:`, result.error);
|
||||
return null;
|
||||
}
|
||||
|
||||
return <UI data={result.data} showNavButtons={true} />;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user