feat: 统一资源管理

This commit is contained in:
alivender
2025-08-02 13:14:01 +08:00
parent e5f2be616c
commit 9904fecbee
15 changed files with 1178 additions and 838 deletions

View File

@@ -88,17 +88,17 @@ export async function loadDiagramData(examId?: string): Promise<DiagramData> {
// 如果提供了examId优先从API加载实验的diagram
if (examId) {
try {
const examClient = AuthManager.createAuthenticatedExamClient();
const resourceClient = AuthManager.createAuthenticatedResourceClient();
// 获取diagram类型的资源列表
const resources = await examClient.getExamResourceList(examId, 'canvas');
const resources = await resourceClient.getResourceList(examId, 'canvas', 'template');
if (resources && resources.length > 0) {
// 获取第一个diagram资源
const diagramResource = resources[0];
// 使用动态API获取资源文件内容
const response = await examClient.getExamResourceById(diagramResource.id);
const response = await resourceClient.getResourceById(diagramResource.id);
if (response && response.data) {
const text = await response.data.text();

View File

@@ -6,8 +6,6 @@ import hljs from 'highlight.js';
import 'highlight.js/styles/github.css'; // 亮色主题
// 导入主题存储
import { useThemeStore } from '@/stores/theme';
// 导入ExamClient用于获取图片资源
import { ExamClient } from '@/APIClient';
import { AuthManager } from '@/utils/AuthManager';
const props = defineProps({
@@ -36,8 +34,8 @@ const imageResourceCache = ref<Map<string, string>>(new Map());
// 获取图片资源ID的函数
async function getImageResourceId(examId: string, imagePath: string): Promise<string | null> {
try {
const client = AuthManager.createAuthenticatedExamClient();
const resources = await client.getExamResourceList(examId, 'images');
const client = AuthManager.createAuthenticatedResourceClient();
const resources = await client.getResourceList(examId, 'images', 'template');
// 查找匹配的图片资源
const imageResource = resources.find(r => r.name === imagePath || r.name.endsWith(imagePath));
@@ -52,8 +50,8 @@ async function getImageResourceId(examId: string, imagePath: string): Promise<st
// 通过资源ID获取图片数据URL
async function getImageDataUrl(resourceId: string): Promise<string | null> {
try {
const client = AuthManager.createAuthenticatedExamClient();
const response = await client.getExamResourceById(parseInt(resourceId));
const client = AuthManager.createAuthenticatedResourceClient();
const response = await client.getResourceById(parseInt(resourceId));
if (response && response.data) {
return URL.createObjectURL(response.data);

View File

@@ -127,12 +127,13 @@ onMounted(async () => {
let thumbnail: string | undefined;
try {
// 获取实验的封面资源
const resourceList = await client.getExamResourceList(exam.id, 'cover');
// 获取实验的封面资源(模板资源)
const resourceClient = AuthManager.createAuthenticatedResourceClient();
const resourceList = await resourceClient.getResourceList(exam.id, 'cover', 'template');
if (resourceList && resourceList.length > 0) {
// 使用第一个封面资源
const coverResource = resourceList[0];
const fileResponse = await client.getExamResourceById(coverResource.id);
const fileResponse = await resourceClient.getResourceById(coverResource.id);
// 创建Blob URL作为缩略图
thumbnail = URL.createObjectURL(fileResponse.data);
}

View File

@@ -75,8 +75,8 @@ import { useDialogStore } from "@/stores/dialog";
import { isNull, isUndefined } from "lodash";
interface Props {
uploadEvent?: (file: File) => Promise<boolean>;
downloadEvent?: () => Promise<boolean>;
uploadEvent?: (file: File, examId: string) => Promise<number | null>;
downloadEvent?: (bitstreamId: number) => Promise<boolean>;
maxMemory?: number;
examId?: string; // 新增examId属性
}
@@ -127,9 +127,9 @@ async function loadAvailableBitstreams() {
}
try {
const examClient = AuthManager.createAuthenticatedExamClient();
// 使用新的API获取比特流资源列表
const resources = await examClient.getExamResourceList(props.examId, 'bitstream');
const resourceClient = AuthManager.createAuthenticatedResourceClient();
// 使用新的ResourceClient API获取比特流模板资源列表
const resources = await resourceClient.getResourceList(props.examId, 'bitstream', 'template');
availableBitstreams.value = resources.map(r => ({ id: r.id, name: r.name })) || [];
} catch (error) {
console.error('加载比特流列表失败:', error);
@@ -143,10 +143,10 @@ async function downloadExampleBitstream(bitstream: {id: number, name: string}) {
isDownloading.value = true;
try {
const examClient = AuthManager.createAuthenticatedExamClient();
const resourceClient = AuthManager.createAuthenticatedResourceClient();
// 使用动态API获取资源文件
const response = await examClient.getExamResourceById(bitstream.id);
// 使用新的ResourceClient API获取资源文件
const response = await resourceClient.getResourceById(bitstream.id);
if (response && response.data) {
// 创建下载链接
@@ -173,37 +173,21 @@ async function downloadExampleBitstream(bitstream: {id: number, name: string}) {
// 直接烧录示例比特流
async function programExampleBitstream(bitstream: {id: number, name: string}) {
if (isProgramming.value || !props.uploadEvent) return;
if (isProgramming.value) return;
isProgramming.value = true;
try {
const examClient = AuthManager.createAuthenticatedExamClient();
// 使用动态API获取比特流文件数据
const response = await examClient.getExamResourceById(bitstream.id);
if (!response || !response.data) {
throw new Error('获取比特流文件失败');
}
const file = new File([response.data], response.fileName || bitstream.name, { type: response.data.type });
// 调用上传事件
const uploadSuccess = await props.uploadEvent(file);
if (uploadSuccess) {
// 如果有下载事件(烧录),则执行
if (props.downloadEvent) {
const downloadSuccess = await props.downloadEvent();
if (downloadSuccess) {
dialog.info("示例比特流烧录成功");
} else {
dialog.error("烧录失败");
}
const resourceClient = AuthManager.createAuthenticatedResourceClient();
if (props.downloadEvent) {
const downloadSuccess = await props.downloadEvent(bitstream.id);
if (downloadSuccess) {
dialog.info("示例比特流烧录成功");
} else {
dialog.info("示例比特流上传成功");
dialog.error("烧录失败");
}
} else {
dialog.error("上传失败");
dialog.info("示例比特流props.downloadEvent未定义 无法烧录");
}
} catch (error) {
console.error('烧录示例比特流失败:', error);
@@ -234,6 +218,7 @@ function checkFile(file: File): boolean {
}
async function handleClick(event: Event): Promise<void> {
console.log("上传按钮被点击");
if (isNull(bitstream.value) || isUndefined(bitstream.value)) {
dialog.error(`未选择文件`);
return;
@@ -246,19 +231,21 @@ async function handleClick(event: Event): Promise<void> {
}
isUploading.value = true;
let uploadedBitstreamId: number | null = null;
try {
const ret = await props.uploadEvent(bitstream.value);
console.log("开始上传比特流文件:", bitstream.value.name);
const bitstreamId = await props.uploadEvent(bitstream.value, props.examId || '');
console.log("上传结果ID:", bitstreamId);
if (isUndefined(props.downloadEvent)) {
if (ret) {
dialog.info("上传成功");
emits("finishedUpload", bitstream.value);
} else dialog.error("上传失败");
return;
}
if (!ret) {
console.log("上传成功,下载未定义");
isUploading.value = false;
return;
}
if (bitstreamId === null || bitstreamId === undefined) {
isUploading.value = false;
return;
}
uploadedBitstreamId = bitstreamId;
} catch (e) {
dialog.error("上传失败");
console.error(e);
@@ -267,9 +254,14 @@ async function handleClick(event: Event): Promise<void> {
// Download
try {
const ret = await props.downloadEvent();
if (ret) dialog.info("下载成功");
else dialog.error("下载失败");
console.log("开始下载比特流ID:", uploadedBitstreamId);
if (uploadedBitstreamId === null || uploadedBitstreamId === undefined) {
dialog.error("uploadedBitstreamId is null or undefined");
} else {
const ret = await props.downloadEvent(uploadedBitstreamId);
if (ret) dialog.info("下载成功");
else dialog.error("下载失败");
}
} catch (e) {
dialog.error("下载失败");
console.error(e);

View File

@@ -22,8 +22,9 @@
</div>
<div class="divider"></div>
<UploadCard
:exam-id="props.examId"
:upload-event="eqps.jtagUploadBitstream"
:download-event="eqps.jtagDownloadBitstream"
:download-event="handleDownloadBitstream"
:bitstream-file="eqps.jtagBitstream"
@update:bitstream-file="handleBitstreamChange"
>
@@ -127,6 +128,11 @@ function handleBitstreamChange(file: File | undefined) {
eqps.jtagBitstream = file;
}
async function handleDownloadBitstream(bitstreamId: number): Promise<boolean> {
console.log("开始下载比特流ID:", bitstreamId);
return await eqps.jtagDownloadBitstream(bitstreamId);
}
function handleSelectJtagSpeed(event: Event) {
const target = event.target as HTMLSelectElement;
eqps.jtagSetSpeed(target.selectedIndex);