233 lines
7.3 KiB
Vue
233 lines
7.3 KiB
Vue
<template>
|
||
<div class="flex flex-row justify-between items-center">
|
||
<h1 class="text-3xl font-bold mb-6">FPGA 设备管理</h1>
|
||
<div>
|
||
<button
|
||
class="btn btn-ghost group"
|
||
@click="tableManager.getAllBoards"
|
||
>
|
||
<RefreshCw class="w-4 h-4 mr-2 transition-transform duration-300 group-hover:rotate-180" />
|
||
刷新
|
||
</button>
|
||
<button
|
||
class="btn btn-ghost text-error hover:underline group"
|
||
@click="tableManager.toggleEditMode"
|
||
>
|
||
<Edit class="w-4 h-4 mr-2 transition-transform duration-200 group-hover:scale-110" />
|
||
编辑
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="card bg-base-100 shadow-xl">
|
||
<div class="card-body">
|
||
<!-- 搜索和列控制 -->
|
||
<div class="flex items-center my-2 gap-4">
|
||
<input
|
||
type="text"
|
||
placeholder="筛选 IP 地址..."
|
||
class="input input-bordered max-w-sm"
|
||
:value="
|
||
tableManager.getColumnByKey('devAddr')?.getFilterValue() as string
|
||
"
|
||
@input="
|
||
tableManager
|
||
.getColumnByKey('devAddr')
|
||
?.setFilterValue(($event.target as HTMLInputElement).value)
|
||
"
|
||
/>
|
||
|
||
<div class="dropdown dropdown-end">
|
||
<div tabindex="0" role="button" class="btn btn-outline">
|
||
列显示
|
||
<svg
|
||
class="w-4 h-4 ml-2"
|
||
fill="none"
|
||
stroke="currentColor"
|
||
viewBox="0 0 24 24"
|
||
>
|
||
<path
|
||
stroke-linecap="round"
|
||
stroke-linejoin="round"
|
||
stroke-width="2"
|
||
d="m19 9-7 7-7-7"
|
||
></path>
|
||
</svg>
|
||
</div>
|
||
<ul
|
||
tabindex="0"
|
||
class="dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52"
|
||
>
|
||
<li
|
||
v-for="column in tableManager.getAllHideableColumns()"
|
||
:key="column.id"
|
||
>
|
||
<label class="label cursor-pointer">
|
||
<span class="label-text capitalize">{{ column.id }}</span>
|
||
<input
|
||
type="checkbox"
|
||
class="checkbox checkbox-sm"
|
||
:checked="column.getIsVisible()"
|
||
@change="
|
||
column.toggleVisibility(
|
||
!!($event.target as HTMLInputElement).checked,
|
||
)
|
||
"
|
||
/>
|
||
</label>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<div class="flex gap-2 ml-auto">
|
||
<button
|
||
class="btn btn-primary group"
|
||
:disabled="!tableManager.isEditMode.value"
|
||
@click="showAddBoardDialog = true"
|
||
>
|
||
<Plus class="w-4 h-4 mr-2 transition-transform duration-200 group-hover:scale-110" />
|
||
新增实验板
|
||
</button>
|
||
|
||
<button
|
||
class="btn btn-error group"
|
||
:disabled="!tableManager.isEditMode.value"
|
||
@click="tableManager.deleteSelectedBoards"
|
||
>
|
||
<Trash2 class="w-4 h-4 mr-2 transition-transform duration-200 group-hover:scale-110 group-hover:animate-pulse" />
|
||
删除选中
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 表格 -->
|
||
<div class="overflow-x-auto border border-base-300 rounded-lg">
|
||
<table class="table w-full">
|
||
<thead>
|
||
<tr
|
||
v-for="headerGroup in tableManager.getHeaderGroups()"
|
||
:key="headerGroup.id"
|
||
class="bg-base-300"
|
||
>
|
||
<th v-for="header in headerGroup.headers" :key="header.id">
|
||
<FlexRender
|
||
v-if="!header.isPlaceholder"
|
||
:render="header.column.columnDef.header"
|
||
:props="header.getContext()"
|
||
/>
|
||
</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<template v-if="tableManager.getRowModel().rows?.length">
|
||
<template
|
||
v-for="row in tableManager.getRowModel().rows"
|
||
:key="row.id"
|
||
>
|
||
<tr
|
||
class="hover"
|
||
:class="{ 'bg-primary/10': row.getIsSelected() }"
|
||
>
|
||
<td v-for="cell in row.getVisibleCells()" :key="cell.id">
|
||
<FlexRender
|
||
:render="cell.column.columnDef.cell"
|
||
:props="cell.getContext()"
|
||
/>
|
||
</td>
|
||
</tr>
|
||
<tr v-if="row.getIsExpanded()">
|
||
<td :colspan="row.getAllCells().length" class="bg-base-200">
|
||
<div class="p-4">
|
||
<pre class="text-sm">{{
|
||
JSON.stringify(row.original, null, 2)
|
||
}}</pre>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
</template>
|
||
</template>
|
||
<tr v-else>
|
||
<td
|
||
:colspan="tableManager.columns.length"
|
||
class="h-24 text-center text-base-content/60"
|
||
>
|
||
暂无数据
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<!-- 分页控制 -->
|
||
<div class="flex items-center justify-between py-4">
|
||
<div class="text-sm text-base-content/60">
|
||
已选择 {{ tableManager.getSelectedRows().length }} /
|
||
{{ tableManager.getAllRows().length }} 行
|
||
</div>
|
||
<div class="flex gap-2">
|
||
<button
|
||
class="btn btn-outline btn-sm"
|
||
:disabled="!tableManager.canPreviousPage()"
|
||
@click="tableManager.previousPage()"
|
||
>
|
||
上一页
|
||
</button>
|
||
<button
|
||
class="btn btn-outline btn-sm"
|
||
:disabled="!tableManager.canNextPage()"
|
||
@click="tableManager.nextPage()"
|
||
>
|
||
下一页
|
||
</button>
|
||
</div>
|
||
</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>
|
||
|
||
<!-- 新增实验板对话框 -->
|
||
<AddBoardDialog
|
||
v-model:visible="showAddBoardDialog"
|
||
@success="handleAddBoardSuccess"
|
||
/>
|
||
</template>
|
||
|
||
<script lang="ts" setup>
|
||
import { FlexRender } from "@tanstack/vue-table";
|
||
import { onMounted, ref } from "vue";
|
||
import { RefreshCw, Edit, Plus, Trash2 } from "lucide-vue-next";
|
||
import { useProvideBoardManager } from "./BoardManager";
|
||
import { useProvideBoardTableManager } from "./BoardTableManager";
|
||
import AddBoardDialog from "./AddBoardDialog.vue";
|
||
|
||
// 使用 BoardManager
|
||
const boardManager = useProvideBoardManager()!;
|
||
|
||
// 使用表格管理器(不再需要参数)
|
||
const tableManager = useProvideBoardTableManager()!;
|
||
|
||
// 新增实验板对话框显示状态
|
||
const showAddBoardDialog = ref(false);
|
||
|
||
// 处理新增实验板成功事件
|
||
const handleAddBoardSuccess = () => {
|
||
showAddBoardDialog.value = false;
|
||
// 刷新数据在 BoardManager.addBoard 中已经处理
|
||
};
|
||
|
||
onMounted(() => {
|
||
// 初始化数据
|
||
boardManager.getAllBoards();
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="postcss">
|
||
@import "@/assets/main.css";
|
||
</style>
|