新模块<蚕茧识别模块V2>发布
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 5.3 KiB After Width: | Height: | Size: 8.0 KiB |
@@ -1,4 +1,5 @@
|
|||||||
export * from './iva';
|
export * from './iva';
|
||||||
export * from './license';
|
export * from './license';
|
||||||
export * from './sca';
|
export * from './sca';
|
||||||
|
export * from './sca2';
|
||||||
export * from './ticket';
|
export * from './ticket';
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { pyRequestClient } from '#/api/request';
|
|||||||
* 获取已分析的图片列表
|
* 获取已分析的图片列表
|
||||||
*/
|
*/
|
||||||
export async function refreshLicenseImageList(page = 1, pageSize = 10) {
|
export async function refreshLicenseImageList(page = 1, pageSize = 10) {
|
||||||
return pyRequestClient.get('/llm/getLicenseImageList', {
|
return pyRequestClient.get('/cv/getLicenseImageList', {
|
||||||
params: { page, page_size: pageSize },
|
params: { page, page_size: pageSize },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ export async function refreshLicenseImageList(page = 1, pageSize = 10) {
|
|||||||
* 上传图片分析任务
|
* 上传图片分析任务
|
||||||
*/
|
*/
|
||||||
export async function createLicenseImageTask(formData: FormData) {
|
export async function createLicenseImageTask(formData: FormData) {
|
||||||
return pyRequestClient.post('/llm/createLicenseImageTask', formData, {
|
return pyRequestClient.post('/cv/createLicenseImageTask', formData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { pyRequestClient } from '#/api/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取已分析的图片列表
|
||||||
|
*/
|
||||||
|
export async function refreshImageListV2(name = '', page = 1, pageSize = 9) {
|
||||||
|
return pyRequestClient.get('/cv/getSilkwormCocoonAnalysisTasks', {
|
||||||
|
params: { name, page, page_size: pageSize },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传图片分析任务
|
||||||
|
*/
|
||||||
|
export async function createImageTaskV2(formData: FormData) {
|
||||||
|
return pyRequestClient.post(
|
||||||
|
'/cv/createSilkwormCocoonAnalysisTask',
|
||||||
|
formData,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,14 +4,14 @@ import { pyRequestClient } from '#/api/request';
|
|||||||
* 获取已分析的图片列表
|
* 获取已分析的图片列表
|
||||||
*/
|
*/
|
||||||
export async function refreshTicketImageList() {
|
export async function refreshTicketImageList() {
|
||||||
return pyRequestClient.get('/llm/getTicketImageList');
|
return pyRequestClient.get('/cv/getTicketImageList');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 上传图片分析任务
|
* 上传图片分析任务
|
||||||
*/
|
*/
|
||||||
export async function createTicketImageTask(formData: FormData) {
|
export async function createTicketImageTask(formData: FormData) {
|
||||||
return pyRequestClient.post('/llm/createTicketImageTaskV2', formData, {
|
return pyRequestClient.post('/cv/createTicketImageTaskV2', formData, {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
|||||||
import { IFrameView } from '#/layouts';
|
import { IFrameView } from '#/layouts';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
const baseAddress = '10.0.4.22';
|
const baseAddress = '10.10.12.101';
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const routes: RouteRecordRaw[] = [
|
|||||||
{
|
{
|
||||||
meta: {
|
meta: {
|
||||||
icon: 'ic:round-remove-red-eye',
|
icon: 'ic:round-remove-red-eye',
|
||||||
authority: ['iva', 'sca', 'ysa', 'ticket', 'license'],
|
authority: ['iva', 'sca', 'sca2', 'ysa', 'ticket', 'license'],
|
||||||
keepAlive: true,
|
keepAlive: true,
|
||||||
order: 2,
|
order: 2,
|
||||||
title: $t('计算机视觉'),
|
title: $t('计算机视觉'),
|
||||||
@@ -37,6 +37,17 @@ const routes: RouteRecordRaw[] = [
|
|||||||
},
|
},
|
||||||
component: () => import('#/views/cv/sca/index.vue'),
|
component: () => import('#/views/cv/sca/index.vue'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'SCA2',
|
||||||
|
path: '/cv/sca2',
|
||||||
|
meta: {
|
||||||
|
authority: ['sca2'],
|
||||||
|
icon: 'mdi:ice-pop',
|
||||||
|
title: '蚕茧仪评分析V2',
|
||||||
|
keepAlive: false,
|
||||||
|
},
|
||||||
|
component: () => import('#/views/cv/sca2/index.vue'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'YSA',
|
name: 'YSA',
|
||||||
path: '/cv/ysa',
|
path: '/cv/ysa',
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import type { RouteRecordRaw } from 'vue-router';
|
|||||||
import { IFrameView } from '#/layouts';
|
import { IFrameView } from '#/layouts';
|
||||||
import { $t } from '#/locales';
|
import { $t } from '#/locales';
|
||||||
|
|
||||||
const baseAddress = '10.0.4.22';
|
const baseAddress = '10.10.12.101';
|
||||||
|
|
||||||
const routes: RouteRecordRaw[] = [
|
const routes: RouteRecordRaw[] = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -353,7 +353,12 @@ function onListItemClick(video: any) {
|
|||||||
<div class="flex w-64 flex-col border-r bg-white p-4">
|
<div class="flex w-64 flex-col border-r bg-white p-4">
|
||||||
<!-- 按钮组 -->
|
<!-- 按钮组 -->
|
||||||
<div class="mb-4 flex justify-between space-x-2">
|
<div class="mb-4 flex justify-between space-x-2">
|
||||||
<Button type="primary" @click="createTask" class="flex-1">
|
<Button
|
||||||
|
type="primary"
|
||||||
|
@click="createTask"
|
||||||
|
class="flex-1"
|
||||||
|
:disabled="true"
|
||||||
|
>
|
||||||
新建任务
|
新建任务
|
||||||
</Button>
|
</Button>
|
||||||
<Button @click="refreshList" class="flex-1"> 刷新列表 </Button>
|
<Button @click="refreshList" class="flex-1"> 刷新列表 </Button>
|
||||||
|
|||||||
@@ -13,9 +13,8 @@ const selectedItem = ref<any>(null);
|
|||||||
|
|
||||||
async function loadList() {
|
async function loadList() {
|
||||||
error.value = null;
|
error.value = null;
|
||||||
const res =
|
const res = await api.refreshLicenseImageList(page.value, pageSize.value);
|
||||||
(await api.refreshLicenseImageList(page.value, pageSize.value)) || [];
|
list.value = res.items || [];
|
||||||
list.value = res.items;
|
|
||||||
total.value = res.total;
|
total.value = res.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +96,7 @@ function refreshLineChart() {
|
|||||||
文件大小: `${data.size} MB`,
|
文件大小: `${data.size} MB`,
|
||||||
分辨率: data.resolution,
|
分辨率: data.resolution,
|
||||||
证件类型:
|
证件类型:
|
||||||
data.type === -1 ? '未知证件' : data.type === 0 ? '身份证' : '银行卡',
|
data.type === -1 ? '未知证件' : (data.type === 0 ? '身份证' : '银行卡'),
|
||||||
};
|
};
|
||||||
showInfoStr2.value = translateKeys(data.content, keyMap);
|
showInfoStr2.value = translateKeys(data.content, keyMap);
|
||||||
}
|
}
|
||||||
@@ -198,7 +197,6 @@ function handleFileChange(event: Event) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<BaseModal />
|
|
||||||
<div class="flex h-full w-full bg-gray-50">
|
<div class="flex h-full w-full bg-gray-50">
|
||||||
<!-- 左侧:筛选 + 列表 -->
|
<!-- 左侧:筛选 + 列表 -->
|
||||||
<div class="flex w-64 flex-col border-r bg-white p-4">
|
<div class="flex w-64 flex-col border-r bg-white p-4">
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
|
||||||
import { useVbenModal } from '@vben/common-ui';
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
|
||||||
import { Form, Input, message } from 'ant-design-vue';
|
import { Form, Input, message } from 'ant-design-vue';
|
||||||
|
|
||||||
import { createVideoTask } from '#/api/cv/iva';
|
import { createVideoTask } from '#/api/cv/iva';
|
||||||
|
|
||||||
const projectName = ref('');
|
const projectName = ref('');
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ function refreshLineChart() {
|
|||||||
最高置信度: data.max_confidence,
|
最高置信度: data.max_confidence,
|
||||||
最低置信度: data.min_confidence,
|
最低置信度: data.min_confidence,
|
||||||
平均置信度: data.average_confidence,
|
平均置信度: data.average_confidence,
|
||||||
分析时长: data.processing_time,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
renderEcharts1({
|
renderEcharts1({
|
||||||
@@ -166,7 +165,12 @@ onActivated(() => {
|
|||||||
<div class="flex w-64 flex-col border-r bg-white p-4">
|
<div class="flex w-64 flex-col border-r bg-white p-4">
|
||||||
<!-- 按钮组 -->
|
<!-- 按钮组 -->
|
||||||
<div class="mb-4 flex justify-between space-x-2">
|
<div class="mb-4 flex justify-between space-x-2">
|
||||||
<Button type="primary" @click="createTask" class="flex-1">
|
<Button
|
||||||
|
type="primary"
|
||||||
|
@click="createTask"
|
||||||
|
class="flex-1"
|
||||||
|
:disabled="true"
|
||||||
|
>
|
||||||
新建任务
|
新建任务
|
||||||
</Button>
|
</Button>
|
||||||
<Button @click="refreshList" class="flex-1"> 刷新列表 </Button>
|
<Button @click="refreshList" class="flex-1"> 刷新列表 </Button>
|
||||||
|
|||||||
@@ -0,0 +1,386 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import type { EchartsUIType } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import {
|
||||||
|
computed,
|
||||||
|
onActivated,
|
||||||
|
onDeactivated,
|
||||||
|
onMounted,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
import { useVbenModal } from '@vben/common-ui';
|
||||||
|
import { EchartsUI, useEcharts } from '@vben/plugins/echarts';
|
||||||
|
|
||||||
|
import { Button, Form, Input, message } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import * as api from '#/api';
|
||||||
|
import { createImageTaskV2 } from '#/api';
|
||||||
|
|
||||||
|
const list = ref<any[]>([]);
|
||||||
|
const error = ref<null | string>(null);
|
||||||
|
const filterKeyword = ref('');
|
||||||
|
const selectedItem = ref<any>(null);
|
||||||
|
async function loadList() {
|
||||||
|
error.value = null;
|
||||||
|
const res = await api.refreshImageListV2(
|
||||||
|
filterKeyword.value,
|
||||||
|
page.value,
|
||||||
|
pageSize.value,
|
||||||
|
);
|
||||||
|
list.value = res.items || [];
|
||||||
|
total.value = res.total;
|
||||||
|
}
|
||||||
|
function refreshList() {
|
||||||
|
filterKeyword.value = '';
|
||||||
|
loadList();
|
||||||
|
message.success('列表加载完成');
|
||||||
|
}
|
||||||
|
function createTask() {
|
||||||
|
modalApi.open();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function selectItem(item: any) {
|
||||||
|
selectedItem.value = item;
|
||||||
|
refreshLineChart();
|
||||||
|
}
|
||||||
|
// 监听关键词变化,调用防抖接口
|
||||||
|
watch(filterKeyword, () => {
|
||||||
|
loadList();
|
||||||
|
});
|
||||||
|
watch(selectedItem, () => {});
|
||||||
|
onMounted(() => {
|
||||||
|
loadList();
|
||||||
|
});
|
||||||
|
|
||||||
|
const showInfoStr = ref<Record<string, number | string>>({});
|
||||||
|
|
||||||
|
const chartRef1 = ref<EchartsUIType>();
|
||||||
|
const { renderEcharts: renderEcharts1 } = useEcharts(chartRef1);
|
||||||
|
|
||||||
|
const chartRef2 = ref<EchartsUIType>();
|
||||||
|
const { renderEcharts: renderEcharts2 } = useEcharts(chartRef2);
|
||||||
|
|
||||||
|
function refreshLineChart() {
|
||||||
|
const data = selectedItem.value;
|
||||||
|
showInfoStr.value = {
|
||||||
|
项目名: data.name,
|
||||||
|
项目上传时间: data.upload_datetime,
|
||||||
|
文件名: data.file_name,
|
||||||
|
文件大小: `${data.size} MB`,
|
||||||
|
分辨率: data.resolution,
|
||||||
|
最高置信度: data.max_confidence,
|
||||||
|
最低置信度: data.min_confidence,
|
||||||
|
平均置信度: data.average_confidence,
|
||||||
|
预处理时间: `${data.preprocess_time_ms} ms`,
|
||||||
|
推理时间: `${data.inference_time_ms} ms`,
|
||||||
|
后处理时间: `${data.postprocess_time_ms} ms`,
|
||||||
|
};
|
||||||
|
|
||||||
|
renderEcharts1({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true,
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: Object.keys(data.other_info),
|
||||||
|
axisTick: {
|
||||||
|
alignWithLabel: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '数量',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '30%',
|
||||||
|
data: Object.values(data.other_info).map(Number),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
renderEcharts2({
|
||||||
|
legend: { top: '5%', left: 'center' },
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
animationDelay() {
|
||||||
|
return Math.random() * 100;
|
||||||
|
},
|
||||||
|
animationEasing: 'exponentialInOut',
|
||||||
|
animationType: 'scale',
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
color: ['#5ab1ef', '#b6a2de', '#67e0e3', '#2ec7c9'],
|
||||||
|
data: Object.entries(data.other_info).map(([key, val]) => ({
|
||||||
|
name: key,
|
||||||
|
value: Number(val),
|
||||||
|
})),
|
||||||
|
itemStyle: {
|
||||||
|
borderRadius: 10,
|
||||||
|
borderWidth: 3,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
position: 'center',
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false,
|
||||||
|
},
|
||||||
|
padAngle: 5,
|
||||||
|
name: '蚕茧分类',
|
||||||
|
radius: ['10%', '70%'],
|
||||||
|
type: 'pie',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onDeactivated(() => {
|
||||||
|
// 离开路由时清理状态
|
||||||
|
selectedItem.value = null;
|
||||||
|
showInfoStr.value = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
onActivated(() => {
|
||||||
|
// 回来的时候重新刷新一次列表
|
||||||
|
loadList();
|
||||||
|
});
|
||||||
|
|
||||||
|
const projectName = ref('');
|
||||||
|
const fileName = ref('');
|
||||||
|
const selectedFile = ref<File | null>(null);
|
||||||
|
const fileInputRef = ref<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
title: '新建蚕茧分析任务',
|
||||||
|
class: 'w-[600px]',
|
||||||
|
onCancel() {
|
||||||
|
modalApi.close();
|
||||||
|
},
|
||||||
|
onConfirm() {
|
||||||
|
if (!selectedFile.value) {
|
||||||
|
message.warning('请选择蚕茧图片');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uploadFile();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
async function uploadFile() {
|
||||||
|
// 先关闭弹窗
|
||||||
|
modalApi.close();
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('file', selectedFile.value!);
|
||||||
|
formData.append('projectName', projectName.value);
|
||||||
|
await createImageTaskV2(formData).then(() => {
|
||||||
|
// 清空表单
|
||||||
|
projectName.value = '';
|
||||||
|
fileName.value = '';
|
||||||
|
selectedFile.value = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 接口完成后再触发事件
|
||||||
|
message.success('分析完成');
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectFile() {
|
||||||
|
fileInputRef.value?.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleFileChange(event: Event) {
|
||||||
|
const files = (event.target as HTMLInputElement).files;
|
||||||
|
if (files && files.length > 0) {
|
||||||
|
selectedFile.value = files[0];
|
||||||
|
fileName.value = files[0].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分页参数
|
||||||
|
const page = ref(1);
|
||||||
|
const pageSize = ref(9);
|
||||||
|
const total = ref(0); // 总条数
|
||||||
|
// 计算总页数
|
||||||
|
const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
|
||||||
|
|
||||||
|
function changePage(newPage) {
|
||||||
|
page.value = newPage;
|
||||||
|
loadList();
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="flex h-[90dvh] w-full flex-col">
|
||||||
|
<Modal>
|
||||||
|
<Form layout="vertical">
|
||||||
|
<Form.Item label="任务名称">
|
||||||
|
<Input v-model:value="projectName" />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item label="上传蚕茧图片*" required>
|
||||||
|
<div
|
||||||
|
@click="selectFile"
|
||||||
|
style="
|
||||||
|
padding: 16px;
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ fileName || '点击选择文件' }}
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
ref="fileInputRef"
|
||||||
|
@change="handleFileChange"
|
||||||
|
style="display: none"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
<div class="flex h-full w-full bg-gray-50">
|
||||||
|
<!-- 左侧:筛选 + 列表 -->
|
||||||
|
<div class="flex w-64 flex-col border-r bg-white p-4">
|
||||||
|
<!-- 按钮组 -->
|
||||||
|
<div class="mb-4 flex justify-between space-x-2">
|
||||||
|
<Button type="primary" @click="createTask" class="flex-1">
|
||||||
|
新建任务
|
||||||
|
</Button>
|
||||||
|
<Button @click="refreshList" class="flex-1"> 刷新列表 </Button>
|
||||||
|
</div>
|
||||||
|
<!-- 筛选框 -->
|
||||||
|
<input
|
||||||
|
v-model="filterKeyword"
|
||||||
|
placeholder="筛选分析任务"
|
||||||
|
class="focus:ring-primary mb-4 rounded-md border px-3 py-2 focus:outline-none focus:ring-2"
|
||||||
|
/>
|
||||||
|
<!-- 列表 -->
|
||||||
|
<div class="flex-1 space-y-2 overflow-auto">
|
||||||
|
<div
|
||||||
|
v-for="item in list"
|
||||||
|
:key="item.v_id"
|
||||||
|
@click="selectItem(item)"
|
||||||
|
class="cursor-pointer rounded border p-3 hover:bg-gray-100"
|
||||||
|
:class="{ 'bg-gray-100': item.id === selectedItem?.id }"
|
||||||
|
>
|
||||||
|
<div class="text-base font-medium">{{ item.name }}</div>
|
||||||
|
<div class="text-sm text-gray-400">{{ item.upload_datetime }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 分页 -->
|
||||||
|
<div class="mt-2 flex justify-center space-x-2">
|
||||||
|
<button
|
||||||
|
:disabled="page === 1"
|
||||||
|
@click="changePage(page - 1)"
|
||||||
|
class="rounded border px-1"
|
||||||
|
>
|
||||||
|
上一页
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span>第 {{ page }} 页 / 共 {{ totalPages }} 页</span>
|
||||||
|
|
||||||
|
<button
|
||||||
|
:disabled="page === totalPages"
|
||||||
|
@click="changePage(page + 1)"
|
||||||
|
class="rounded border px-1"
|
||||||
|
>
|
||||||
|
下一页
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧:Tab 内容区 -->
|
||||||
|
<div class="flex flex-1 flex-col overflow-hidden p-6">
|
||||||
|
<div
|
||||||
|
v-if="!selectedItem"
|
||||||
|
class="flex h-full items-center justify-center text-gray-400"
|
||||||
|
>
|
||||||
|
请先选择左侧列表中的分析任务
|
||||||
|
</div>
|
||||||
|
<template v-else>
|
||||||
|
<div class="flex h-full flex-col gap-4">
|
||||||
|
<!-- 主内容区域:左右结构 -->
|
||||||
|
<div class="flex flex-1 gap-4">
|
||||||
|
<!-- 左侧 -->
|
||||||
|
<div class="flex w-72 flex-col gap-4">
|
||||||
|
<!-- 视频基础信息展示 -->
|
||||||
|
<div
|
||||||
|
class="w-full rounded border bg-white p-4"
|
||||||
|
id="video_base_info"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(value, key) in showInfoStr"
|
||||||
|
:key="key"
|
||||||
|
class="mb-2 flex text-sm text-gray-700"
|
||||||
|
>
|
||||||
|
<div class="w-32 font-medium text-gray-900">
|
||||||
|
{{ key }}:
|
||||||
|
</div>
|
||||||
|
<div class="flex-1 break-all text-gray-600">
|
||||||
|
{{ value || '—' }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 下:空白卡片 -->
|
||||||
|
<div class="flex-1 rounded border bg-white p-4">
|
||||||
|
<EchartsUI ref="chartRef2" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 右侧 -->
|
||||||
|
<div class="flex flex-1 flex-col gap-4">
|
||||||
|
<!-- 上:左右两个图片显示 -->
|
||||||
|
<div class="flex flex-1 gap-4">
|
||||||
|
<!-- 左图 -->
|
||||||
|
<div
|
||||||
|
class="flex flex-1 items-center justify-center rounded border bg-white p-4"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="selectedItem?.image_pre"
|
||||||
|
alt=""
|
||||||
|
class="h-[30dvh] w-full object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<!-- 右图 -->
|
||||||
|
<div
|
||||||
|
class="flex flex-1 items-center justify-center rounded border bg-white p-4"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
:src="selectedItem?.image_after"
|
||||||
|
alt=""
|
||||||
|
class="h-[30dvh] w-full object-contain"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- 下:柱状图区域 -->
|
||||||
|
<div class="flex-1 rounded border bg-white p-4">
|
||||||
|
<EchartsUI ref="chartRef1" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -29,6 +29,13 @@ const cv: WorkbenchQuickNavItem[] = [
|
|||||||
title: '蚕茧仪评分析',
|
title: '蚕茧仪评分析',
|
||||||
url: '/cv/sca',
|
url: '/cv/sca',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
color: '#3fb27f',
|
||||||
|
authority: ['sca2'],
|
||||||
|
icon: 'mdi:ice-pop',
|
||||||
|
title: '蚕茧仪评分析V2',
|
||||||
|
url: '/cv/sca2',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
color: '#3fb27f',
|
color: '#3fb27f',
|
||||||
authority: ['ysa'],
|
authority: ['ysa'],
|
||||||
@@ -55,7 +62,7 @@ const cv: WorkbenchQuickNavItem[] = [
|
|||||||
icon: 'ion:bar-chart-outline',
|
icon: 'ion:bar-chart-outline',
|
||||||
title: '标注平台入口',
|
title: '标注平台入口',
|
||||||
authority: ['user'],
|
authority: ['user'],
|
||||||
url: 'http://171.212.101.199:13013/',
|
url: 'https://ai.ronsunny.cn:8094/',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const llm: WorkbenchQuickNavItem[] = [
|
const llm: WorkbenchQuickNavItem[] = [
|
||||||
|
|||||||
Reference in New Issue
Block a user