224 lines
7.4 KiB
Vue
224 lines
7.4 KiB
Vue
<template>
|
|
<div class="page-body">
|
|
<div class="container-xl">
|
|
<div class="row row-deck row-cards">
|
|
<div class="col-12">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h3 class="card-title">训练记录</h3>
|
|
</div>
|
|
<div class="card-body border-bottom py-3">
|
|
</div>
|
|
<div class="table-responsive">
|
|
<table class="table card-table table-vcenter text-nowrap datatable">
|
|
<thead>
|
|
<tr>
|
|
<th class="w-1 text-center"><input class="form-check-input m-0 align-middle" type="checkbox"
|
|
aria-label="Select all invoices"></th>
|
|
<th class="w-1 text-center">训练编号
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-sm icon-thick" width="24" height="24"
|
|
viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
|
|
stroke-linejoin="round">
|
|
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
|
|
<path d="M6 15l6 -6l6 6" />
|
|
</svg>
|
|
</th>
|
|
<th class="text-center">创建时间</th>
|
|
<th class="text-center">预训练模型</th>
|
|
<th class="text-center">数据集名称</th>
|
|
<th class="text-center">任务类型</th>
|
|
<th class="text-center">mAP</th>
|
|
<th class="text-center">precision</th>
|
|
<th class="text-center">当前状态</th>
|
|
<th class="text-center">action</th>
|
|
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="task in project_training_tasks">
|
|
<td class="text-center"><input class="form-check-input m-0 align-middle" type="checkbox"
|
|
aria-label="Select invoice"></td>
|
|
<td class="text-center"><span class="text-secondary">{{ task.id }}</span></td>
|
|
<td class="text-center"><a href="invoice.html" class="text-reset" tabindex="-1"></a>{{
|
|
formatCreateTime(task.create_time) }}</td>
|
|
<td class="text-center">
|
|
<span class="flag flag-xs flag-country-us me-2"></span>
|
|
{{ task.pre_model_name }}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ task.dataset_name }}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ task.task_type === 'Detect' ? '目标检测' : task.task_type === 'Classify' ? '图像分类' : task.task_type
|
|
}}
|
|
</td>
|
|
<td class="text-center">
|
|
{{ task.epochData }}
|
|
</td>
|
|
<td class="text-center">{{ task.precision }}</td>
|
|
<td class="text-center">
|
|
<span class="badge me-1" :class="{
|
|
'bg-warning': task.status === '初始化',
|
|
'bg-info': task.status === '训练中',
|
|
'bg-success': task.status === '训练完成',
|
|
'bg-danger': task.status === '训练异常'
|
|
}">
|
|
</span>
|
|
{{ task.status }}
|
|
</td>
|
|
|
|
<td class="text-end">
|
|
<span>
|
|
<button class="btn dropdown-toggle align-text-top" data-bs-boundary="viewport"
|
|
data-bs-toggle="dropdown">操作</button>
|
|
<div class="dropdown-menu dropdown-menu-end">
|
|
<router-link class="dropdown-item"
|
|
:to="{ path: '/train-detail', query: { task_id: task.id } }">
|
|
查看详细
|
|
</router-link>
|
|
<a class="dropdown-item" href="#">
|
|
编辑
|
|
</a>
|
|
<a class="dropdown-item" href="#"
|
|
@click="deleteTask(task.id, task.user, task.project_name, task.dataset_name)">
|
|
删除
|
|
</a>
|
|
</div>
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</template>
|
|
|
|
<script setup lang="ts" name="ModelCard">
|
|
import axios from 'axios'
|
|
import { get } from 'http';
|
|
import { API_URL } from '@/config/config'
|
|
import { ref, onMounted } from 'vue';
|
|
// 定义任务的类型
|
|
interface Task {
|
|
id: number;
|
|
user: string;
|
|
project_name: string;
|
|
pre_model_name: string;
|
|
dataset_name: string;
|
|
task_type: string;
|
|
status: string;
|
|
epoch: number;
|
|
batch_size: number;
|
|
image_size: number;
|
|
create_time: string;
|
|
model_size: string;
|
|
epochData: number;
|
|
precision: number;
|
|
}
|
|
|
|
let props = defineProps({
|
|
project_training_tasks: {
|
|
type: Array as () => Task[], // 指定类型为 Task 数组
|
|
default: () => [{
|
|
id: 0,
|
|
user: '',
|
|
project_name: '',
|
|
pre_model_name: '',
|
|
dataset_name: '',
|
|
task_type: '',
|
|
status: '',
|
|
epoch: 0,
|
|
batch_size: 0,
|
|
image_size: 0,
|
|
create_time: '',
|
|
model_size: '',
|
|
epochData: 0.0,
|
|
precision: 0.0,
|
|
}]
|
|
}
|
|
})
|
|
|
|
let mAP = ref<number>(0.0)
|
|
|
|
async function get_curr_epoch_data(training_id: number) {
|
|
try {
|
|
let response = await axios.get(`${API_URL}/training/get_curr_epoch_data/`, {
|
|
params: {
|
|
training_id: training_id
|
|
}
|
|
});
|
|
// 返回一个对象,包含 mAP95 和 precision
|
|
return {
|
|
mAP95: response.data.data.mAP95,
|
|
precision: response.data.data.precision
|
|
};
|
|
} catch (error) {
|
|
console.log(error);
|
|
return { mAP95: 0, precision: 0 }; // 返回默认值
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async function deleteTask(id: number, user: string, projectName: string, datasetName: string) {
|
|
let response1 = await axios.get(`${API_URL}/training/delete_project_training_task/`, {
|
|
params: {
|
|
id: id,
|
|
user: user,
|
|
projectName: projectName
|
|
}
|
|
})
|
|
|
|
if (response1.data.success) {
|
|
alert('删除成功')
|
|
window.location.reload()
|
|
} else {
|
|
alert('删除失败')
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// 在 onMounted 中获取每个任务的 epoch 数据
|
|
onMounted(async () => {
|
|
for (let task of props.project_training_tasks) {
|
|
const { mAP95, precision } = await get_curr_epoch_data(task.id);
|
|
task.epochData = mAP95; // 或者根据需要存储 precision
|
|
task.precision = precision;
|
|
}
|
|
});
|
|
|
|
|
|
// 功能函数
|
|
function formatCreateTime(dateString: string) {
|
|
if (!dateString) { // 检查 dateString 是否有效
|
|
return '无效的日期'; // 返回一个默认值或错误提示
|
|
}
|
|
|
|
const date = new Date(dateString);
|
|
if (isNaN(date.getTime())) { // 检查日期是否有效
|
|
return '无效的日期'; // 返回一个默认值或错误提示
|
|
}
|
|
return date.toISOString().slice(0, 19).replace('T', ' '); // 格式化为 YYYY-MM-DD HH:mm:ss
|
|
}
|
|
|
|
</script>
|
|
|
|
<style>
|
|
.card-link {
|
|
border: 1px solid transparent;
|
|
/* 默认边框 */
|
|
transition: border 0.3s;
|
|
/* 添加过渡效果 */
|
|
}
|
|
|
|
.card-link:hover {
|
|
border: 2px solid rgb(242, 238, 238);
|
|
/* 悬停时的边框效果 */
|
|
}
|
|
</style> |