254 lines
7.7 KiB
Vue
254 lines
7.7 KiB
Vue
<template>
|
||
<div class="bg-base-200 min-h-screen p-6">
|
||
<div class="flex flex-row justify-between items-center">
|
||
<h1 class="text-3xl font-bold mb-6">FPGA 设备管理</h1>
|
||
<button class="btn btn-ghost text-error hover:underline" @click="
|
||
() => {
|
||
isEditMode = !isEditMode;
|
||
}
|
||
">
|
||
编辑
|
||
</button>
|
||
</div>
|
||
|
||
<div class="card bg-base-100 shadow-xl">
|
||
<div class="card-body">
|
||
<div class="flex flex-row justify-between items-center">
|
||
<h2 class="card-title mb-4">IP 地址列表</h2>
|
||
<button class="btn btn-ghost" @click="">刷新</button>
|
||
</div>
|
||
|
||
<div class="overflow-x-auto">
|
||
<table class="table w-full">
|
||
<!-- 表头 -->
|
||
<thead>
|
||
<tr class="bg-base-300">
|
||
<th class="w-50">IP 地址</th>
|
||
<th class="w-30">版本号</th>
|
||
<th class="w-50">默认启动位流</th>
|
||
<th class="w-80">黄金位流</th>
|
||
<th class="w-80">应用位流1</th>
|
||
<th class="w-80">应用位流2</th>
|
||
<th class="w-80">应用位流3</th>
|
||
<th>操作</th>
|
||
</tr>
|
||
</thead>
|
||
|
||
<!-- 表格内容 -->
|
||
<tbody>
|
||
<tr class="hover">
|
||
<td class="font-medium">
|
||
<input v-if="isEditMode" type="text" placeholder="Type here" class="input m-0" v-model="devAddr" />
|
||
<span v-else>{{ devAddr }}</span>
|
||
</td>
|
||
<td>v1.2.3</td>
|
||
<td>
|
||
<select class="select select-bordered w-full max-w-xs" v-model="selectBitstream">
|
||
<option selected>黄金位流</option>
|
||
<option>应用位流1</option>
|
||
<option>应用位流2</option>
|
||
<option>应用位流3</option>
|
||
</select>
|
||
</td>
|
||
<!-- 黄金位流上传区 -->
|
||
<td>
|
||
<div class="flex flex-col items-center gap-2">
|
||
<input type="file" class="file-input file-input-primary" @change="handleFileChange($event, 0)" />
|
||
</div>
|
||
</td>
|
||
<!-- 应用位流1上传区 -->
|
||
<td>
|
||
<div class="flex flex-col items-center gap-2">
|
||
<input type="file" class="file-input file-input-secondary" @change="handleFileChange($event, 1)" />
|
||
</div>
|
||
</td>
|
||
<!-- 应用位流2上传区 -->
|
||
<td>
|
||
<div class="flex flex-col items-center gap-2">
|
||
<input type="file" class="file-input file-input-accent" @change="handleFileChange($event, 2)" />
|
||
</div>
|
||
</td>
|
||
<!-- 应用位流3上传区 -->
|
||
<td>
|
||
<div class="flex flex-col items-center gap-2">
|
||
<input type="file" class="file-input file-input-info" @change="handleFileChange($event, 3)" />
|
||
</div>
|
||
</td>
|
||
|
||
<!-- 操作按钮 -->
|
||
<td class="flex gap-2">
|
||
<button class="btn grow btn-warning" @click="
|
||
uploadAndDownloadBitstreams(
|
||
devAddr,
|
||
goldBitstreamFile,
|
||
appBitstream1File,
|
||
appBitstream2File,
|
||
appBitstream3File,
|
||
)
|
||
">
|
||
固化
|
||
</button>
|
||
<button class="btn grow btn-success" @click="
|
||
hotresetBitstream(devAddr, getSelectedBitstreamNum())
|
||
">
|
||
切换并热启动
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="mt-6 bg-base-300 p-4 rounded-lg">
|
||
<p class="text-sm opacity-80">
|
||
<span class="font-semibold text-error">提示:</span>
|
||
请谨慎操作FPGA固化和热启动功能,确保上传的位流文件无误,以避免设备损坏。
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { isNull, isUndefined } from "lodash";
|
||
import { ref } from "vue";
|
||
import { RemoteUpdateClient } from "@/APIClient";
|
||
import { useDialogStore } from "@/stores/dialog";
|
||
import { Common } from "@/utils/Common";
|
||
|
||
const dialog = useDialogStore();
|
||
|
||
// 编辑状态
|
||
const isEditMode = ref(false);
|
||
|
||
// 选择热切换的比特流
|
||
const selectBitstream = ref("黄金位流");
|
||
|
||
// 存储上传文件的信息
|
||
const goldBitstreamFile = ref<File>();
|
||
const appBitstream1File = ref<File>();
|
||
const appBitstream2File = ref<File>();
|
||
const appBitstream3File = ref<File>();
|
||
|
||
// 远程升级相关参数
|
||
const devAddr = ref("192.168.1.100");
|
||
const devPort = 1234;
|
||
const remoteUpdater = new RemoteUpdateClient();
|
||
|
||
// 处理文件上传
|
||
function handleFileChange(event: Event, bistreamNum: number) {
|
||
const target = event.target as HTMLInputElement;
|
||
const file = target.files?.[0]; // 获取选中的第一个文件
|
||
|
||
if (!file) {
|
||
return;
|
||
}
|
||
|
||
if (bistreamNum === 0) {
|
||
goldBitstreamFile.value = file;
|
||
} else if (bistreamNum === 1) {
|
||
appBitstream1File.value = file;
|
||
} else if (bistreamNum === 2) {
|
||
appBitstream2File.value = file;
|
||
} else if (bistreamNum === 3) {
|
||
appBitstream3File.value = file;
|
||
} else {
|
||
goldBitstreamFile.value = file;
|
||
}
|
||
}
|
||
|
||
function getSelectedBitstreamNum(): number {
|
||
if (selectBitstream.value == "黄金位流") {
|
||
return 0;
|
||
} else if (selectBitstream.value == "应用位流1") {
|
||
return 1;
|
||
} else if (selectBitstream.value == "应用位流2") {
|
||
return 2;
|
||
} else if (selectBitstream.value == "应用位流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(),
|
||
);
|
||
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(devAddr.value, devPort);
|
||
} catch (e) {
|
||
dialog.error("获取数据失败");
|
||
console.error(e);
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped lang="postcss">
|
||
@import "../assets/main.css";
|
||
</style>
|