add: 添加实验列表界面,实验增删完全依赖数据库实现
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -25,26 +25,37 @@
|
||||
</h1>
|
||||
|
||||
<p class="py-6 text-lg opacity-80 leading-relaxed">
|
||||
Prototype and simulate electronic circuits in your browser with our
|
||||
modern, intuitive interface. Create, test, and share your FPGA
|
||||
designs seamlessly.
|
||||
在浏览器中进行FPGA原型设计和电路仿真,使用现代直观的界面。创建、测试和分享您的FPGA设计,体验从基础学习到高级项目的完整开发流程。
|
||||
</p>
|
||||
<div class="flex flex-wrap gap-4 actions-container">
|
||||
<div class="flex flex-col sm:flex-row gap-4 actions-container">
|
||||
<router-link
|
||||
to="/project"
|
||||
class="btn btn-primary text-base-100 shadow-lg transform transition-all duration-300 hover:scale-105 hover:shadow-xl hover:-translate-y-1"
|
||||
class="btn btn-primary text-base-100 shadow-lg transform transition-all duration-300 hover:scale-105 hover:shadow-xl hover:-translate-y-1 flex-1 sm:flex-none"
|
||||
>
|
||||
<BookOpen class="h-5 w-5 mr-2" />
|
||||
进入工程界面
|
||||
</router-link>
|
||||
<router-link
|
||||
to="/exam"
|
||||
class="btn btn-secondary text-base-100 shadow-lg transform transition-all duration-300 hover:scale-105 hover:shadow-xl hover:-translate-y-1 flex-1 sm:flex-none"
|
||||
>
|
||||
<GraduationCap class="h-5 w-5 mr-2" />
|
||||
实验列表
|
||||
</router-link>
|
||||
</div>
|
||||
<div
|
||||
class="mt-8 p-4 bg-base-300 rounded-lg shadow-inner opacity-80 transition-all duration-300 hover:opacity-100 hover:shadow-md"
|
||||
>
|
||||
<p class="text-sm">
|
||||
<span class="font-semibold text-primary">提示:</span>
|
||||
您可以在工程界面中创建、编辑和测试您的FPGA项目,使用我们简洁直观的界面轻松进行硬件设计。
|
||||
</p>
|
||||
<div class="space-y-2">
|
||||
<p class="text-sm">
|
||||
<span class="font-semibold text-primary">工程界面:</span>
|
||||
自由创建和编辑FPGA项目,使用可视化画布进行电路设计和仿真测试。
|
||||
</p>
|
||||
<p class="text-sm">
|
||||
<span class="font-semibold text-secondary">实验列表:</span>
|
||||
浏览结构化的学习实验,从基础概念到高级应用的系统性学习路径。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,7 +66,7 @@
|
||||
<script lang="ts" setup>
|
||||
import "@/router";
|
||||
import TutorialCarousel from "@/components/TutorialCarousel.vue";
|
||||
import { BookOpen } from "lucide-vue-next";
|
||||
import { BookOpen, GraduationCap } from "lucide-vue-next";
|
||||
</script>
|
||||
|
||||
<style scoped lang="postcss">
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
<DiagramCanvas
|
||||
ref="diagramCanvas"
|
||||
:showDocPanel="showDocPanel"
|
||||
:exam-id="(route.query.examId as string) || ''"
|
||||
@open-components="openComponentsMenu"
|
||||
@toggle-doc-panel="toggleDocPanel"
|
||||
/>
|
||||
@@ -59,7 +60,10 @@
|
||||
v-show="showDocPanel"
|
||||
class="doc-panel overflow-y-auto h-full"
|
||||
>
|
||||
<MarkdownRenderer :content="documentContent" />
|
||||
<MarkdownRenderer
|
||||
:content="documentContent"
|
||||
:examId="(route.query.examId as string) || ''"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SplitterPanel>
|
||||
@@ -115,7 +119,6 @@ import MarkdownRenderer from "@/components/MarkdownRenderer.vue";
|
||||
import BottomBar from "@/views/Project/BottomBar.vue";
|
||||
import RequestBoardDialog from "@/views/Project/RequestBoardDialog.vue";
|
||||
import { useProvideComponentManager } from "@/components/LabCanvas";
|
||||
import type { DiagramData } from "@/components/LabCanvas";
|
||||
import { useAlertStore } from "@/components/Alert";
|
||||
import { AuthManager } from "@/utils/AuthManager";
|
||||
import { useEquipments } from "@/stores/equipments";
|
||||
@@ -182,29 +185,37 @@ async function toggleDocPanel() {
|
||||
// 加载文档内容
|
||||
async function loadDocumentContent() {
|
||||
try {
|
||||
// 从路由参数中获取教程ID
|
||||
const tutorialId = (route.query.tutorial as string) || "02"; // 默认加载02例程
|
||||
|
||||
// 构建文档路径
|
||||
let docPath = `/doc/${tutorialId}/doc.md`;
|
||||
|
||||
// 检查当前路径是否包含下划线(例如 02_key 格式)
|
||||
// 如果不包含,那么使用更新的命名格式
|
||||
if (!tutorialId.includes("_")) {
|
||||
docPath = `/doc/${tutorialId}/doc.md`;
|
||||
// 检查是否有实验ID参数
|
||||
const examId = route.query.examId as string;
|
||||
if (examId) {
|
||||
// 如果有实验ID,从API加载实验文档
|
||||
console.log('加载实验文档:', examId);
|
||||
const client = AuthManager.createAuthenticatedExamClient();
|
||||
|
||||
// 获取markdown类型的资源列表
|
||||
const resources = await client.getExamResourceList(examId, 'doc');
|
||||
|
||||
if (resources && resources.length > 0) {
|
||||
// 获取第一个markdown资源
|
||||
const markdownResource = resources[0];
|
||||
|
||||
// 使用动态API获取资源文件内容
|
||||
const response = await client.getExamResourceById(markdownResource.id);
|
||||
|
||||
if (!response || !response.data) {
|
||||
throw new Error('获取markdown文件失败');
|
||||
}
|
||||
|
||||
const content = await response.data.text();
|
||||
|
||||
// 更新文档内容,暂时不处理图片路径,由MarkdownRenderer处理
|
||||
documentContent.value = content;
|
||||
} else {
|
||||
documentContent.value = "# 暂无实验文档\n\n该实验尚未提供文档内容。";
|
||||
}
|
||||
} else {
|
||||
documentContent.value = "# 无文档";
|
||||
}
|
||||
|
||||
// 获取文档内容
|
||||
const response = await fetch(docPath);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to load document: ${response.status}`);
|
||||
}
|
||||
|
||||
// 更新文档内容,并替换图片路径
|
||||
documentContent.value = (await response.text()).replace(
|
||||
/.\/images/gi,
|
||||
`/doc/${tutorialId}/images`,
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("加载文档失败:", error);
|
||||
documentContent.value = "# 文档加载失败\n\n无法加载请求的文档。";
|
||||
@@ -312,8 +323,8 @@ onMounted(async () => {
|
||||
// 检查并初始化用户实验板
|
||||
await checkAndInitializeBoard();
|
||||
|
||||
// 检查是否有例程参数,如果有则自动打开文档面板
|
||||
if (route.query.tutorial) {
|
||||
// 检查是否有例程参数或实验ID参数,如果有则自动打开文档面板
|
||||
if (route.query.tutorial || route.query.examId) {
|
||||
showDocPanel.value = true;
|
||||
await loadDocumentContent();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user