feat: 前端完成适配后端api
This commit is contained in:
		@@ -50,10 +50,31 @@ const [useAlertProvider, useAlertStore] = createInjectionState(() => {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Convenience methods for different alert types
 | 
			
		||||
  function error(message: string, duration = 2000) {
 | 
			
		||||
    show(message, "error", duration);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function info(message: string, duration = 2000) {
 | 
			
		||||
    show(message, "info", duration);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function warn(message: string, duration = 2000) {
 | 
			
		||||
    show(message, "warning", duration);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function success(message: string, duration = 2000) {
 | 
			
		||||
    show(message, "success", duration);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    alertState,
 | 
			
		||||
    show,
 | 
			
		||||
    hide,
 | 
			
		||||
    error,
 | 
			
		||||
    info,
 | 
			
		||||
    warn,
 | 
			
		||||
    success,
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,7 @@
 | 
			
		||||
    <h1 class="text-3xl font-bold mb-6">FPGA 设备管理</h1>
 | 
			
		||||
    <button
 | 
			
		||||
      class="btn btn-ghost text-error hover:underline"
 | 
			
		||||
      @click="
 | 
			
		||||
        () => {
 | 
			
		||||
          isEditMode = !isEditMode;
 | 
			
		||||
        }
 | 
			
		||||
      "
 | 
			
		||||
      @click="toggleEditMode"
 | 
			
		||||
    >
 | 
			
		||||
      编辑
 | 
			
		||||
    </button>
 | 
			
		||||
@@ -17,7 +13,9 @@
 | 
			
		||||
    <div class="card-body">
 | 
			
		||||
      <div class="flex flex-row justify-between items-center mb-4">
 | 
			
		||||
        <h2 class="card-title">IP 地址列表</h2>
 | 
			
		||||
        <button class="btn btn-ghost" @click="refreshData">刷新</button>
 | 
			
		||||
        <button class="btn btn-ghost" @click="boardManager.refreshData">
 | 
			
		||||
          刷新
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <!-- 搜索和列控制 -->
 | 
			
		||||
@@ -185,45 +183,20 @@ import {
 | 
			
		||||
  getSortedRowModel,
 | 
			
		||||
  useVueTable,
 | 
			
		||||
} from "@tanstack/vue-table";
 | 
			
		||||
import { isNull, isUndefined } from "lodash";
 | 
			
		||||
import { h, ref } from "vue";
 | 
			
		||||
import { RemoteUpdateClient } from "@/APIClient";
 | 
			
		||||
import { useDialogStore } from "@/stores/dialog";
 | 
			
		||||
import { Common } from "@/utils/Common";
 | 
			
		||||
import { h, onMounted, ref } from "vue";
 | 
			
		||||
import { useProvideBoardManager, type BoardData } from "./BoardManager";
 | 
			
		||||
 | 
			
		||||
const dialog = useDialogStore();
 | 
			
		||||
// 使用 BoardManager
 | 
			
		||||
const boardManager = useProvideBoardManager()!;
 | 
			
		||||
 | 
			
		||||
// 编辑状态
 | 
			
		||||
const isEditMode = ref(false);
 | 
			
		||||
 | 
			
		||||
// 远程升级相关参数
 | 
			
		||||
const devPort = 1234;
 | 
			
		||||
const remoteUpdater = new RemoteUpdateClient();
 | 
			
		||||
 | 
			
		||||
// 设备数据接口
 | 
			
		||||
export interface DeviceData {
 | 
			
		||||
  id: string;
 | 
			
		||||
  devAddr: string;
 | 
			
		||||
  version: string;
 | 
			
		||||
  defaultBitstream: string;
 | 
			
		||||
  goldBitstreamFile?: File;
 | 
			
		||||
  appBitstream1File?: File;
 | 
			
		||||
  appBitstream2File?: File;
 | 
			
		||||
  appBitstream3File?: File;
 | 
			
		||||
function toggleEditMode() {
 | 
			
		||||
  isEditMode.value = !isEditMode.value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 模拟数据,实际应该从API获取
 | 
			
		||||
const data = ref<DeviceData[]>([
 | 
			
		||||
  {
 | 
			
		||||
    id: "1",
 | 
			
		||||
    devAddr: "192.168.1.100",
 | 
			
		||||
    version: "v1.2.3",
 | 
			
		||||
    defaultBitstream: "黄金位流",
 | 
			
		||||
  },
 | 
			
		||||
]);
 | 
			
		||||
 | 
			
		||||
// 表格列定义
 | 
			
		||||
const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
const columns: ColumnDef<BoardData>[] = [
 | 
			
		||||
  {
 | 
			
		||||
    id: "select",
 | 
			
		||||
    header: ({ table }) =>
 | 
			
		||||
@@ -258,18 +231,19 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
        ? h("input", {
 | 
			
		||||
            type: "text",
 | 
			
		||||
            class: "input input-sm w-full",
 | 
			
		||||
            value: device.devAddr,
 | 
			
		||||
            value: device.ipAddr,
 | 
			
		||||
            onInput: (e: Event) => {
 | 
			
		||||
              device.devAddr = (e.target as HTMLInputElement).value;
 | 
			
		||||
              device.ipAddr = (e.target as HTMLInputElement).value;
 | 
			
		||||
            },
 | 
			
		||||
          })
 | 
			
		||||
        : h("span", { class: "font-medium" }, device.devAddr);
 | 
			
		||||
        : h("span", { class: "font-medium" }, device.ipAddr);
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    accessorKey: "version",
 | 
			
		||||
    header: "版本号",
 | 
			
		||||
    cell: ({ row }) => row.getValue("version"),
 | 
			
		||||
    cell: ({ row }) =>
 | 
			
		||||
      h("span", { class: "font-mono" }, row.original.firmVersion),
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
    accessorKey: "defaultBitstream",
 | 
			
		||||
@@ -303,7 +277,7 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
        type: "file",
 | 
			
		||||
        class: "file-input file-input-primary file-input-sm",
 | 
			
		||||
        onChange: (e: Event) =>
 | 
			
		||||
          handleFileChange(e, device, "goldBitstreamFile"),
 | 
			
		||||
          boardManager.handleFileChange(e, device, "goldBitstreamFile"),
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
@@ -316,7 +290,7 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
        type: "file",
 | 
			
		||||
        class: "file-input file-input-secondary file-input-sm",
 | 
			
		||||
        onChange: (e: Event) =>
 | 
			
		||||
          handleFileChange(e, device, "appBitstream1File"),
 | 
			
		||||
          boardManager.handleFileChange(e, device, "appBitstream1File"),
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
@@ -329,7 +303,7 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
        type: "file",
 | 
			
		||||
        class: "file-input file-input-accent file-input-sm",
 | 
			
		||||
        onChange: (e: Event) =>
 | 
			
		||||
          handleFileChange(e, device, "appBitstream2File"),
 | 
			
		||||
          boardManager.handleFileChange(e, device, "appBitstream2File"),
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
@@ -342,7 +316,7 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
        type: "file",
 | 
			
		||||
        class: "file-input file-input-info file-input-sm",
 | 
			
		||||
        onChange: (e: Event) =>
 | 
			
		||||
          handleFileChange(e, device, "appBitstream3File"),
 | 
			
		||||
          boardManager.handleFileChange(e, device, "appBitstream3File"),
 | 
			
		||||
      });
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
@@ -357,8 +331,8 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
          {
 | 
			
		||||
            class: "btn btn-warning btn-sm",
 | 
			
		||||
            onClick: () =>
 | 
			
		||||
              uploadAndDownloadBitstreams(
 | 
			
		||||
                device.devAddr,
 | 
			
		||||
              boardManager.uploadAndDownloadBitstreams(
 | 
			
		||||
                device,
 | 
			
		||||
                device.goldBitstreamFile,
 | 
			
		||||
                device.appBitstream1File,
 | 
			
		||||
                device.appBitstream2File,
 | 
			
		||||
@@ -372,9 +346,9 @@ const columns: ColumnDef<DeviceData>[] = [
 | 
			
		||||
          {
 | 
			
		||||
            class: "btn btn-success btn-sm",
 | 
			
		||||
            onClick: () =>
 | 
			
		||||
              hotresetBitstream(
 | 
			
		||||
                device.devAddr,
 | 
			
		||||
                getSelectedBitstreamNum(device.defaultBitstream),
 | 
			
		||||
              boardManager.hotresetBitstream(
 | 
			
		||||
                device,
 | 
			
		||||
                boardManager.getSelectedBitstreamNum(device.defaultBitstream),
 | 
			
		||||
              ),
 | 
			
		||||
          },
 | 
			
		||||
          "热启动",
 | 
			
		||||
@@ -395,7 +369,7 @@ const expanded = ref<ExpandedState>({});
 | 
			
		||||
// 创建表格实例
 | 
			
		||||
const table = useVueTable({
 | 
			
		||||
  get data() {
 | 
			
		||||
    return data.value;
 | 
			
		||||
    return boardManager.boards.value;
 | 
			
		||||
  },
 | 
			
		||||
  columns,
 | 
			
		||||
  getCoreRowModel: getCoreRowModel(),
 | 
			
		||||
@@ -456,110 +430,10 @@ const table = useVueTable({
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// 处理文件上传
 | 
			
		||||
function handleFileChange(
 | 
			
		||||
  event: Event,
 | 
			
		||||
  device: DeviceData,
 | 
			
		||||
  fileKey: keyof DeviceData,
 | 
			
		||||
) {
 | 
			
		||||
  const target = event.target as HTMLInputElement;
 | 
			
		||||
  const file = target.files?.[0];
 | 
			
		||||
  if (file) {
 | 
			
		||||
    (device as any)[fileKey] = file;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getSelectedBitstreamNum(bitstreamName: string): number {
 | 
			
		||||
  if (bitstreamName === "黄金位流") return 0;
 | 
			
		||||
  if (bitstreamName === "应用位流1") return 1;
 | 
			
		||||
  if (bitstreamName === "应用位流2") return 2;
 | 
			
		||||
  if (bitstreamName === "应用位流3") return 3;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function uploadAndDownloadBitstreams(
 | 
			
		||||
  devAddr: string,
 | 
			
		||||
  goldBitstream?: File,
 | 
			
		||||
  appBitstream1?: File,
 | 
			
		||||
  appBitstream2?: File,
 | 
			
		||||
  appBitstream3?: File,
 | 
			
		||||
) {
 | 
			
		||||
  let cnt = 0;
 | 
			
		||||
  if (!isUndefined(goldBitstream)) cnt++;
 | 
			
		||||
  if (!isUndefined(appBitstream1)) cnt++;
 | 
			
		||||
  if (!isUndefined(appBitstream2)) cnt++;
 | 
			
		||||
  if (!isUndefined(appBitstream3)) cnt++;
 | 
			
		||||
  if (cnt === 0) {
 | 
			
		||||
    dialog.error("未选择比特流");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  try {
 | 
			
		||||
    {
 | 
			
		||||
      const ret = await remoteUpdater.uploadBitstreams(
 | 
			
		||||
        devAddr,
 | 
			
		||||
        Common.toFileParameterOrNull(goldBitstream),
 | 
			
		||||
        Common.toFileParameterOrNull(appBitstream1),
 | 
			
		||||
        Common.toFileParameterOrNull(appBitstream2),
 | 
			
		||||
        Common.toFileParameterOrNull(appBitstream3),
 | 
			
		||||
      );
 | 
			
		||||
      if (!ret) {
 | 
			
		||||
        dialog.warn("上传比特流出错");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
      const ret = await remoteUpdater.downloadMultiBitstreams(
 | 
			
		||||
        devAddr,
 | 
			
		||||
        devPort,
 | 
			
		||||
        getSelectedBitstreamNum(data.value[0].defaultBitstream),
 | 
			
		||||
      );
 | 
			
		||||
      if (ret != cnt) {
 | 
			
		||||
        dialog.warn("固化比特流出错");
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.info("固化比特流成功");
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("比特流上传错误");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function hotresetBitstream(devAddr: string, bitstreamNum: number) {
 | 
			
		||||
  try {
 | 
			
		||||
    const ret = await remoteUpdater.hotResetBitstream(
 | 
			
		||||
      devAddr,
 | 
			
		||||
      devPort,
 | 
			
		||||
      bitstreamNum,
 | 
			
		||||
    );
 | 
			
		||||
    if (ret) {
 | 
			
		||||
      dialog.info("切换比特流成功");
 | 
			
		||||
    } else {
 | 
			
		||||
      dialog.error("切换比特流失败");
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("切换比特流失败");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function refreshData() {
 | 
			
		||||
  try {
 | 
			
		||||
    const ret = await remoteUpdater.getFirmwareVersion(
 | 
			
		||||
      data.value[0].devAddr,
 | 
			
		||||
      devPort,
 | 
			
		||||
    );
 | 
			
		||||
    // 更新版本信息
 | 
			
		||||
    if (ret) {
 | 
			
		||||
      data.value[0].version = String(ret);
 | 
			
		||||
    }
 | 
			
		||||
  } catch (e) {
 | 
			
		||||
    dialog.error("获取数据失败");
 | 
			
		||||
    console.error(e);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  // 初始化数据
 | 
			
		||||
  boardManager.fetchBoardsData();
 | 
			
		||||
});
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="postcss">
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,288 @@
 | 
			
		||||
import { ref } from "vue";
 | 
			
		||||
import { createInjectionState } from "@vueuse/core";
 | 
			
		||||
import { RemoteUpdateClient, DataClient, Board } from "@/APIClient";
 | 
			
		||||
import { useDialogStore } from "@/stores/dialog";
 | 
			
		||||
import { useAlertStore } from "@/components/Alert";
 | 
			
		||||
import { Common } from "@/utils/Common";
 | 
			
		||||
import { isUndefined } from "lodash";
 | 
			
		||||
import { AuthManager } from "@/utils/AuthManager";
 | 
			
		||||
 | 
			
		||||
// 统一的板卡数据接口,扩展原有的Board类型
 | 
			
		||||
export interface BoardData extends Board {
 | 
			
		||||
  defaultBitstream: string;
 | 
			
		||||
  goldBitstreamFile?: File;
 | 
			
		||||
  appBitstream1File?: File;
 | 
			
		||||
  appBitstream2File?: File;
 | 
			
		||||
  appBitstream3File?: File;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const [useProvideBoardManager, useBoardManager] = createInjectionState(() => {
 | 
			
		||||
  const dialog = useDialogStore();
 | 
			
		||||
  const alert = useAlertStore();
 | 
			
		||||
 | 
			
		||||
  // 远程升级相关参数
 | 
			
		||||
  const devPort = 1234;
 | 
			
		||||
  const remoteUpdater = new RemoteUpdateClient();
 | 
			
		||||
 | 
			
		||||
  // 统一的板卡数据
 | 
			
		||||
  const boards = ref<BoardData[]>([]);
 | 
			
		||||
 | 
			
		||||
  // 获取位流编号
 | 
			
		||||
  function getSelectedBitstreamNum(bitstreamName: string): number {
 | 
			
		||||
    if (bitstreamName === "黄金位流") return 0;
 | 
			
		||||
    if (bitstreamName === "应用位流1") return 1;
 | 
			
		||||
    if (bitstreamName === "应用位流2") return 2;
 | 
			
		||||
    if (bitstreamName === "应用位流3") return 3;
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 获取所有板卡信息(管理员权限)- 不显示提示信息,供内部调用
 | 
			
		||||
  async function fetchBoardsData(): Promise<boolean> {
 | 
			
		||||
    try {
 | 
			
		||||
      // 验证管理员权限
 | 
			
		||||
      const hasAdminAuth = await AuthManager.verifyAdminAuth();
 | 
			
		||||
      if (!hasAdminAuth) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const client = AuthManager.createAuthenticatedClient();
 | 
			
		||||
      const result = await client.getAllBoards();
 | 
			
		||||
 | 
			
		||||
      if (result) {
 | 
			
		||||
        // 将Board类型转换为BoardData类型,添加默认值
 | 
			
		||||
        boards.value = result.map((board) => {
 | 
			
		||||
          return {
 | 
			
		||||
            ...board,
 | 
			
		||||
            defaultBitstream: "黄金位流", // 设置默认位流
 | 
			
		||||
            goldBitstreamFile: undefined,
 | 
			
		||||
            appBitstream1File: undefined,
 | 
			
		||||
            appBitstream2File: undefined,
 | 
			
		||||
            appBitstream3File: undefined,
 | 
			
		||||
            // Ensure methods from Board are present
 | 
			
		||||
            init: board.init?.bind(board),
 | 
			
		||||
            toJSON: board.toJSON?.bind(board),
 | 
			
		||||
          };
 | 
			
		||||
        });
 | 
			
		||||
        return true;
 | 
			
		||||
      } else {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 获取所有板卡信息(管理员权限)- 显示提示信息,供外部调用
 | 
			
		||||
  async function getAllBoards(): Promise<boolean> {
 | 
			
		||||
    const result = await fetchBoardsData();
 | 
			
		||||
    if (result) {
 | 
			
		||||
      dialog.info("获取板卡信息成功");
 | 
			
		||||
    } else {
 | 
			
		||||
      dialog.warn("获取板卡信息失败");
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 新增板卡(管理员权限)
 | 
			
		||||
  async function addBoard(
 | 
			
		||||
    name: string,
 | 
			
		||||
    ipAddr: string,
 | 
			
		||||
    port: number,
 | 
			
		||||
  ): Promise<boolean> {
 | 
			
		||||
    try {
 | 
			
		||||
      // 验证管理员权限
 | 
			
		||||
      const hasAdminAuth = await AuthManager.verifyAdminAuth();
 | 
			
		||||
      if (!hasAdminAuth) {
 | 
			
		||||
        dialog.error("需要管理员权限");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 验证输入参数
 | 
			
		||||
      if (!name || !ipAddr || !port) {
 | 
			
		||||
        dialog.error("请填写完整的板卡信息");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const client = AuthManager.createAuthenticatedClient();
 | 
			
		||||
      const boardId = await client.addBoard(name, ipAddr, port);
 | 
			
		||||
 | 
			
		||||
      if (boardId) {
 | 
			
		||||
        // 静默刷新板卡列表,不显示重复提示
 | 
			
		||||
        await fetchBoardsData();
 | 
			
		||||
        dialog.info("新增板卡成功");
 | 
			
		||||
        return true;
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.warn("新增板卡失败");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      if (e.status === 401) {
 | 
			
		||||
        dialog.error("权限不足,需要管理员权限");
 | 
			
		||||
      } else if (e.status === 400) {
 | 
			
		||||
        dialog.error("输入参数错误");
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.error("新增板卡失败");
 | 
			
		||||
      }
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 删除板卡(管理员权限)
 | 
			
		||||
  async function deleteBoard(boardId: string): Promise<boolean> {
 | 
			
		||||
    try {
 | 
			
		||||
      // 验证管理员权限
 | 
			
		||||
      const hasAdminAuth = await AuthManager.verifyAdminAuth();
 | 
			
		||||
      if (!hasAdminAuth) {
 | 
			
		||||
        dialog.error("需要管理员权限");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!boardId) {
 | 
			
		||||
        dialog.error("板卡ID不能为空");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const client = AuthManager.createAuthenticatedClient();
 | 
			
		||||
      const result = await client.deleteBoard(boardId);
 | 
			
		||||
 | 
			
		||||
      if (result > 0) {
 | 
			
		||||
        // 静默刷新板卡列表,不显示重复提示
 | 
			
		||||
        await fetchBoardsData();
 | 
			
		||||
        dialog.info("删除板卡成功");
 | 
			
		||||
        return true;
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.warn("删除板卡失败");
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      if (e.status === 401) {
 | 
			
		||||
        dialog.error("权限不足,需要管理员权限");
 | 
			
		||||
      } else if (e.status === 400) {
 | 
			
		||||
        dialog.error("输入参数错误");
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.error("删除板卡失败");
 | 
			
		||||
      }
 | 
			
		||||
      console.error(e);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 上传并固化位流
 | 
			
		||||
  async function uploadAndDownloadBitstreams(
 | 
			
		||||
    board: BoardData,
 | 
			
		||||
    goldBitstream?: File,
 | 
			
		||||
    appBitstream1?: File,
 | 
			
		||||
    appBitstream2?: File,
 | 
			
		||||
    appBitstream3?: File,
 | 
			
		||||
  ) {
 | 
			
		||||
    let cnt = 0;
 | 
			
		||||
    if (!isUndefined(goldBitstream)) cnt++;
 | 
			
		||||
    if (!isUndefined(appBitstream1)) cnt++;
 | 
			
		||||
    if (!isUndefined(appBitstream2)) cnt++;
 | 
			
		||||
    if (!isUndefined(appBitstream3)) cnt++;
 | 
			
		||||
    if (cnt === 0) {
 | 
			
		||||
      dialog.error("未选择比特流");
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const uploadResult = await remoteUpdater.uploadBitstreams(
 | 
			
		||||
        board.ipAddr, // 使用板卡的IP地址
 | 
			
		||||
        Common.toFileParameterOrNull(goldBitstream),
 | 
			
		||||
        Common.toFileParameterOrNull(appBitstream1),
 | 
			
		||||
        Common.toFileParameterOrNull(appBitstream2),
 | 
			
		||||
        Common.toFileParameterOrNull(appBitstream3),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      if (!uploadResult) {
 | 
			
		||||
        dialog.warn("上传比特流出错");
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const downloadResult = await remoteUpdater.downloadMultiBitstreams(
 | 
			
		||||
        board.ipAddr,
 | 
			
		||||
        board.port,
 | 
			
		||||
        getSelectedBitstreamNum(board.defaultBitstream),
 | 
			
		||||
      );
 | 
			
		||||
 | 
			
		||||
      if (downloadResult != cnt) {
 | 
			
		||||
        dialog.warn("固化比特流出错");
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.info("固化比特流成功");
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      dialog.error("比特流上传错误");
 | 
			
		||||
      console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 热启动位流
 | 
			
		||||
  async function hotresetBitstream(board: BoardData, bitstreamNum: number) {
 | 
			
		||||
    try {
 | 
			
		||||
      const ret = await remoteUpdater.hotResetBitstream(
 | 
			
		||||
        board.ipAddr,
 | 
			
		||||
        board.port,
 | 
			
		||||
        bitstreamNum,
 | 
			
		||||
      );
 | 
			
		||||
      if (ret) {
 | 
			
		||||
        dialog.info("切换比特流成功");
 | 
			
		||||
      } else {
 | 
			
		||||
        dialog.error("切换比特流失败");
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      dialog.error("切换比特流失败");
 | 
			
		||||
      console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 刷新板卡数据 - 简化逻辑,避免重复提示
 | 
			
		||||
  async function refreshData() {
 | 
			
		||||
    try {
 | 
			
		||||
      const result = await fetchBoardsData();
 | 
			
		||||
      if (result) {
 | 
			
		||||
        alert?.info("刷新数据成功");
 | 
			
		||||
      } else {
 | 
			
		||||
        alert?.error("获取板卡信息失败");
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      alert?.error("获取数据失败");
 | 
			
		||||
      console.error(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // 处理文件上传
 | 
			
		||||
  function handleFileChange(
 | 
			
		||||
    event: Event,
 | 
			
		||||
    board: BoardData,
 | 
			
		||||
    fileKey: keyof Pick<
 | 
			
		||||
      BoardData,
 | 
			
		||||
      | "goldBitstreamFile"
 | 
			
		||||
      | "appBitstream1File"
 | 
			
		||||
      | "appBitstream2File"
 | 
			
		||||
      | "appBitstream3File"
 | 
			
		||||
    >,
 | 
			
		||||
  ) {
 | 
			
		||||
    const target = event.target as HTMLInputElement;
 | 
			
		||||
    const file = target.files?.[0];
 | 
			
		||||
    if (file) {
 | 
			
		||||
      (board as any)[fileKey] = file;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    boards,
 | 
			
		||||
    uploadAndDownloadBitstreams,
 | 
			
		||||
    hotresetBitstream,
 | 
			
		||||
    refreshData,
 | 
			
		||||
    handleFileChange,
 | 
			
		||||
    getSelectedBitstreamNum,
 | 
			
		||||
    getAllBoards,
 | 
			
		||||
    fetchBoardsData,
 | 
			
		||||
    addBoard,
 | 
			
		||||
    deleteBoard,
 | 
			
		||||
  };
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export { useProvideBoardManager, useBoardManager };
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user