feat: 添加注册界面

This commit is contained in:
2025-07-11 19:26:27 +08:00
parent fae07d9eae
commit 3f2c772eeb
10 changed files with 294 additions and 179 deletions

View File

@@ -0,0 +1,253 @@
<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>

View File

@@ -7,6 +7,9 @@
<li id="2" @click="setActivePage">
<a :class="{ 'menu-active': activePage === 2 }">Item 2</a>
</li>
<li id="" @click="setActivePage">
<a :class="{ 'menu-active': activePage === 2 }">Item 2</a>
</li>
</ul>
<div class="divider divider-horizontal h-full"></div>
<div class="card bg-base-200 w-300"></div>