refactor: 使用更简洁的方式进行认证
This commit is contained in:
@@ -266,7 +266,12 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CaptureMode, ChannelConfig, DebuggerConfig } from "@/APIClient";
|
||||
import {
|
||||
CaptureMode,
|
||||
ChannelConfig,
|
||||
DebuggerClient,
|
||||
DebuggerConfig,
|
||||
} from "@/APIClient";
|
||||
import { useAlertStore } from "@/components/Alert";
|
||||
import BaseInputField from "@/components/InputField/BaseInputField.vue";
|
||||
import type { LogicDataType } from "@/components/WaveformDisplay";
|
||||
@@ -421,7 +426,7 @@ async function startCapture() {
|
||||
}
|
||||
|
||||
isCapturing.value = true;
|
||||
const client = AuthManager.createAuthenticatedDebuggerClient();
|
||||
const client = AuthManager.createClient(DebuggerClient);
|
||||
|
||||
// 构造API配置
|
||||
const channelConfigs = channels.value
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
@layout="handleVerticalSplitterResize"
|
||||
>
|
||||
<!-- 使用 v-show 替代 v-if -->
|
||||
<SplitterPanel
|
||||
<SplitterPanel
|
||||
v-show="!isBottomBarFullscreen"
|
||||
id="splitter-group-v-panel-project"
|
||||
:default-size="verticalSplitterSize"
|
||||
@@ -60,8 +60,8 @@
|
||||
v-show="showDocPanel"
|
||||
class="doc-panel overflow-y-auto h-full"
|
||||
>
|
||||
<MarkdownRenderer
|
||||
:content="documentContent"
|
||||
<MarkdownRenderer
|
||||
:content="documentContent"
|
||||
:examId="(route.query.examId as string) || ''"
|
||||
/>
|
||||
</div>
|
||||
@@ -80,11 +80,13 @@
|
||||
<!-- 功能底栏 -->
|
||||
<SplitterPanel
|
||||
id="splitter-group-v-panel-bar"
|
||||
:default-size="isBottomBarFullscreen ? 100 : (100 - verticalSplitterSize)"
|
||||
:default-size="
|
||||
isBottomBarFullscreen ? 100 : 100 - verticalSplitterSize
|
||||
"
|
||||
:min-size="isBottomBarFullscreen ? 100 : 15"
|
||||
class="w-full overflow-hidden pt-3"
|
||||
>
|
||||
<BottomBar
|
||||
<BottomBar
|
||||
:isFullscreen="isBottomBarFullscreen"
|
||||
@toggle-fullscreen="handleToggleBottomBarFullscreen"
|
||||
/>
|
||||
@@ -106,22 +108,48 @@
|
||||
/>
|
||||
|
||||
<!-- Navbar切换浮动按钮 -->
|
||||
<div
|
||||
<div
|
||||
class="navbar-toggle-btn"
|
||||
:class="{ 'with-navbar': navbarControl.showNavbar.value }"
|
||||
>
|
||||
<button
|
||||
<button
|
||||
@click="navbarControl.toggleNavbar"
|
||||
class="btn btn-circle btn-primary shadow-lg hover:shadow-xl transition-all duration-300"
|
||||
:class="{ 'btn-outline': navbarControl.showNavbar.value }"
|
||||
:title="navbarControl.showNavbar.value ? '隐藏顶部导航栏' : '显示顶部导航栏'"
|
||||
:title="
|
||||
navbarControl.showNavbar.value ? '隐藏顶部导航栏' : '显示顶部导航栏'
|
||||
"
|
||||
>
|
||||
<!-- 使用SVG图标表示菜单/关闭状态 -->
|
||||
<svg v-if="navbarControl.showNavbar.value" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||
<svg
|
||||
v-if="navbarControl.showNavbar.value"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
<svg v-else xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||
<svg
|
||||
v-else
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
@@ -131,7 +159,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch, inject, type Ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useLocalStorage } from '@vueuse/core'; // 添加VueUse导入
|
||||
import { useLocalStorage } from "@vueuse/core"; // 添加VueUse导入
|
||||
import { SplitterGroup, SplitterPanel, SplitterResizeHandle } from "reka-ui";
|
||||
import DiagramCanvas from "@/components/LabCanvas/DiagramCanvas.vue";
|
||||
import ComponentSelector from "@/components/LabCanvas/ComponentSelector.vue";
|
||||
@@ -143,7 +171,7 @@ import { useProvideComponentManager } from "@/components/LabCanvas";
|
||||
import { useAlertStore } from "@/components/Alert";
|
||||
import { AuthManager } from "@/utils/AuthManager";
|
||||
import { useEquipments } from "@/stores/equipments";
|
||||
import type { Board } from "@/APIClient";
|
||||
import { DataClient, ResourceClient, type Board } from "@/APIClient";
|
||||
|
||||
import { useRoute } from "vue-router";
|
||||
const route = useRoute();
|
||||
@@ -158,20 +186,29 @@ const equipments = useEquipments();
|
||||
const alert = useAlertStore();
|
||||
|
||||
// --- Navbar控制 ---
|
||||
const navbarControl = inject('navbar') as {
|
||||
const navbarControl = inject("navbar") as {
|
||||
showNavbar: Ref<boolean>;
|
||||
toggleNavbar: () => void;
|
||||
};
|
||||
|
||||
// --- 使用VueUse保存分栏状态 ---
|
||||
// 左右分栏比例(默认60%)
|
||||
const horizontalSplitterSize = useLocalStorage('project-horizontal-splitter-size', 60);
|
||||
const horizontalSplitterSize = useLocalStorage(
|
||||
"project-horizontal-splitter-size",
|
||||
60,
|
||||
);
|
||||
// 上下分栏比例(默认80%)
|
||||
const verticalSplitterSize = useLocalStorage('project-vertical-splitter-size', 80);
|
||||
const verticalSplitterSize = useLocalStorage(
|
||||
"project-vertical-splitter-size",
|
||||
80,
|
||||
);
|
||||
// 底栏全屏状态
|
||||
const isBottomBarFullscreen = useLocalStorage('project-bottom-bar-fullscreen', false);
|
||||
const isBottomBarFullscreen = useLocalStorage(
|
||||
"project-bottom-bar-fullscreen",
|
||||
false,
|
||||
);
|
||||
// 文档面板显示状态
|
||||
const showDocPanel = useLocalStorage('project-show-doc-panel', false);
|
||||
const showDocPanel = useLocalStorage("project-show-doc-panel", false);
|
||||
|
||||
function handleToggleBottomBarFullscreen() {
|
||||
isBottomBarFullscreen.value = !isBottomBarFullscreen.value;
|
||||
@@ -216,25 +253,25 @@ async function loadDocumentContent() {
|
||||
const examId = route.query.examId as string;
|
||||
if (examId) {
|
||||
// 如果有实验ID,从API加载实验文档
|
||||
console.log('加载实验文档:', examId);
|
||||
const client = AuthManager.createAuthenticatedResourceClient();
|
||||
|
||||
console.log("加载实验文档:", examId);
|
||||
const client = AuthManager.createClient(ResourceClient);
|
||||
|
||||
// 获取markdown类型的模板资源列表
|
||||
const resources = await client.getResourceList(examId, 'doc', 'template');
|
||||
|
||||
const resources = await client.getResourceList(examId, "doc", "template");
|
||||
|
||||
if (resources && resources.length > 0) {
|
||||
// 获取第一个markdown资源
|
||||
const markdownResource = resources[0];
|
||||
|
||||
|
||||
// 使用新的ResourceClient API获取资源文件内容
|
||||
const response = await client.getResourceById(markdownResource.id);
|
||||
|
||||
|
||||
if (!response || !response.data) {
|
||||
throw new Error('获取markdown文件失败');
|
||||
throw new Error("获取markdown文件失败");
|
||||
}
|
||||
|
||||
|
||||
const content = await response.data.text();
|
||||
|
||||
|
||||
// 更新文档内容,暂时不处理图片路径,由MarkdownRenderer处理
|
||||
documentContent.value = content;
|
||||
} else {
|
||||
@@ -279,17 +316,17 @@ function updateComponentDirectProp(
|
||||
// 检查并初始化用户实验板
|
||||
async function checkAndInitializeBoard() {
|
||||
try {
|
||||
const client = AuthManager.createAuthenticatedDataClient();
|
||||
const client = AuthManager.createClient(DataClient);
|
||||
const userInfo = await client.getUserInfo();
|
||||
|
||||
if (userInfo.boardID && userInfo.boardID.trim() !== '') {
|
||||
|
||||
if (userInfo.boardID && userInfo.boardID.trim() !== "") {
|
||||
// 用户已绑定实验板,获取实验板信息并更新到equipment
|
||||
try {
|
||||
const board = await client.getBoardByID(userInfo.boardID);
|
||||
updateEquipmentFromBoard(board);
|
||||
alert?.show(`实验板 ${board.boardName} 已连接`, "success");
|
||||
} catch (boardError) {
|
||||
console.error('获取实验板信息失败:', boardError);
|
||||
console.error("获取实验板信息失败:", boardError);
|
||||
alert?.show("获取实验板信息失败", "error");
|
||||
showRequestBoardDialog.value = true;
|
||||
}
|
||||
@@ -298,7 +335,7 @@ async function checkAndInitializeBoard() {
|
||||
showRequestBoardDialog.value = true;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查用户实验板失败:', error);
|
||||
console.error("检查用户实验板失败:", error);
|
||||
alert?.show("检查用户信息失败", "error");
|
||||
showRequestBoardDialog.value = true;
|
||||
}
|
||||
@@ -308,12 +345,12 @@ async function checkAndInitializeBoard() {
|
||||
function updateEquipmentFromBoard(board: Board) {
|
||||
equipments.boardAddr = board.ipAddr;
|
||||
equipments.boardPort = board.port;
|
||||
|
||||
|
||||
console.log(`实验板信息已更新到equipment store:`, {
|
||||
address: board.ipAddr,
|
||||
port: board.port,
|
||||
boardName: board.boardName,
|
||||
boardId: board.id
|
||||
boardId: board.id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -321,7 +358,7 @@ function updateEquipmentFromBoard(board: Board) {
|
||||
function handleRequestBoardClose() {
|
||||
showRequestBoardDialog.value = false;
|
||||
// 如果用户取消申请,可以选择返回上一页或显示警告
|
||||
router.push('/');
|
||||
router.push("/");
|
||||
}
|
||||
|
||||
// 处理申请实验板成功
|
||||
@@ -338,12 +375,12 @@ onMounted(async () => {
|
||||
const isAuthenticated = await AuthManager.isAuthenticated();
|
||||
if (!isAuthenticated) {
|
||||
// 验证失败,跳转到登录页面
|
||||
router.push('/login');
|
||||
router.push("/login");
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('身份验证失败:', error);
|
||||
router.push('/login');
|
||||
console.error("身份验证失败:", error);
|
||||
router.push("/login");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ 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";
|
||||
import { DataClient, type Board } from "@/APIClient";
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
@@ -113,7 +113,7 @@ async function checkUserBoard() {
|
||||
boardInfo.value = null;
|
||||
|
||||
try {
|
||||
const client = AuthManager.createAuthenticatedDataClient();
|
||||
const client = AuthManager.createClient(DataClient);
|
||||
const userInfo = await client.getUserInfo();
|
||||
|
||||
if (userInfo.boardID && userInfo.boardID.trim() !== "") {
|
||||
@@ -140,7 +140,7 @@ async function requestBoard() {
|
||||
requesting.value = true;
|
||||
|
||||
try {
|
||||
const client = AuthManager.createAuthenticatedDataClient();
|
||||
const client = AuthManager.createClient(DataClient);
|
||||
const board = await client.getAvailableBoard(undefined);
|
||||
|
||||
if (board) {
|
||||
|
||||
@@ -433,7 +433,7 @@ const currentVideoSource = ref("");
|
||||
const logs = ref<Array<{ time: Date; level: string; message: string }>>([]);
|
||||
|
||||
// API 客户端
|
||||
const videoClient = AuthManager.createAuthenticatedVideoStreamClient();
|
||||
const videoClient = AuthManager.createClient(VideoStreamClient);
|
||||
|
||||
// 添加日志
|
||||
const addLog = (level: string, message: string) => {
|
||||
|
||||
Reference in New Issue
Block a user