164 lines
4.6 KiB
Vue
164 lines
4.6 KiB
Vue
<template>
|
||
<div
|
||
v-if="open"
|
||
class="fixed inset-0 z-50 flex items-center justify-center bg-opacity-30 backdrop-blur-sm shadow-2xl"
|
||
>
|
||
<div class="bg-base-100 rounded-lg shadow-xl max-w-md w-full mx-4">
|
||
<div class="p-6">
|
||
<h2 class="text-xl font-bold mb-4">申请实验板</h2>
|
||
|
||
<div v-if="!loading && !hasBoard" class="space-y-4">
|
||
<p class="text-base-content">
|
||
检测到您尚未绑定实验板,请申请一个可用的实验板以继续实验。
|
||
</p>
|
||
|
||
<div class="flex justify-end space-x-2">
|
||
<button
|
||
@click="$emit('close')"
|
||
class="btn btn-ghost"
|
||
:disabled="requesting"
|
||
>
|
||
取消
|
||
</button>
|
||
<button
|
||
@click="requestBoard"
|
||
class="btn btn-primary"
|
||
:disabled="requesting"
|
||
>
|
||
<span
|
||
v-if="requesting"
|
||
class="loading loading-spinner loading-sm"
|
||
></span>
|
||
{{ requesting ? "申请中..." : "申请实验板" }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div v-else-if="loading" class="text-center py-8">
|
||
<span class="loading loading-spinner loading-lg"></span>
|
||
<p class="mt-2">检查实验板状态中...</p>
|
||
</div>
|
||
|
||
<div v-else-if="hasBoard" class="space-y-4">
|
||
<div class="bg-base-200 p-4 rounded">
|
||
<h3 class="font-semibold mb-2">实验板信息</h3>
|
||
<div class="space-y-1 text-sm">
|
||
<p>
|
||
<span class="font-medium">名称:</span>
|
||
{{ boardInfo?.boardName }}
|
||
</p>
|
||
<p><span class="font-medium">ID:</span> {{ boardInfo?.id }}</p>
|
||
<p>
|
||
<span class="font-medium">地址:</span>
|
||
{{ boardInfo?.ipAddr }}:{{ boardInfo?.port }}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="flex justify-end">
|
||
<button
|
||
v-if="boardInfo"
|
||
@click="$emit('success', boardInfo)"
|
||
class="btn btn-primary"
|
||
>
|
||
开始实验
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, watch } from "vue";
|
||
import { CheckCircle } from "lucide-vue-next";
|
||
import { AuthManager } from "@/utils/AuthManager";
|
||
import { useAlertStore } from "@/components/Alert";
|
||
import type { Board } from "@/APIClient";
|
||
|
||
interface Props {
|
||
open: boolean;
|
||
}
|
||
|
||
interface Emits {
|
||
(e: "close"): void;
|
||
(e: "success", board: Board): void;
|
||
}
|
||
|
||
const props = defineProps<Props>();
|
||
const emit = defineEmits<Emits>();
|
||
|
||
const alert = useAlertStore();
|
||
|
||
const loading = ref(false);
|
||
const requesting = ref(false);
|
||
const hasBoard = ref(false);
|
||
const boardInfo = ref<Board | null>(null);
|
||
|
||
// 监听对话框打开状态,自动检查用户信息
|
||
watch(
|
||
() => props.open,
|
||
async (newOpen) => {
|
||
if (newOpen) {
|
||
await checkUserBoard();
|
||
}
|
||
},
|
||
);
|
||
|
||
// 检查用户是否已绑定实验板
|
||
async function checkUserBoard() {
|
||
loading.value = true;
|
||
hasBoard.value = false;
|
||
boardInfo.value = null;
|
||
|
||
try {
|
||
const client = AuthManager.createAuthenticatedDataClient();
|
||
const userInfo = await client.getUserInfo();
|
||
|
||
if (userInfo.boardID && userInfo.boardID.trim() !== "") {
|
||
// 用户已绑定实验板,获取实验板信息
|
||
try {
|
||
const board = await client.getBoardByID(userInfo.boardID);
|
||
boardInfo.value = board;
|
||
hasBoard.value = true;
|
||
} catch (boardError) {
|
||
console.error("获取实验板信息失败:", boardError);
|
||
alert?.error("获取实验板信息失败,请重试");
|
||
}
|
||
}
|
||
} catch (err) {
|
||
console.error("检查用户信息失败:", err);
|
||
alert?.error("检查用户信息失败,请重试");
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
|
||
// 申请实验板
|
||
async function requestBoard() {
|
||
requesting.value = true;
|
||
|
||
try {
|
||
const client = AuthManager.createAuthenticatedDataClient();
|
||
const board = await client.getAvailableBoard(undefined);
|
||
|
||
if (board) {
|
||
boardInfo.value = board;
|
||
hasBoard.value = true;
|
||
} else {
|
||
alert?.error("当前没有可用的实验板,请稍后重试");
|
||
}
|
||
} catch (err: any) {
|
||
console.error("申请实验板失败:", err);
|
||
if (err.status === 404) {
|
||
alert?.error("当前没有可用的实验板,请稍后重试");
|
||
} else {
|
||
alert?.error("申请实验板失败,请重试");
|
||
}
|
||
} finally {
|
||
requesting.value = false;
|
||
}
|
||
}
|
||
</script>
|