Industrial-image-management.../src/views/operation-platform/data-processing/data-storage/index.vue

495 lines
12 KiB
Vue
Raw Normal View History

2025-07-14 11:11:33 +08:00
<template>
<GiPageLayout>
<!-- 页面标题 -->
<!-- <div class="page-header">
<h2 class="page-title">图像音频关联查看</h2>
</div>-->
<!-- 选项卡区域 -->
<div class="tabs-section">
<a-tabs v-model:active-key="activeTab" type="line">
<a-tab-pane key="image" tab="列表" title="列表">
<div class="tab-content">
<!-- 筛选条件区域 -->
<div class="filter-section">
<a-space size="large">
<!-- 项目选择 -->
<div class="filter-item">
<span class="filter-label">项目</span>
<a-select
v-model="filterParams.project"
placeholder="请选择项目"
:options="projectOptions"
allow-search
allow-clear
:loading="loading.project"
style="width: 200px"
@change="handleFilterChange"
/>
</div>
<!-- 机组选择 -->
<div class="filter-item">
<span class="filter-label">机组</span>
<a-select
v-model="filterParams.unit"
placeholder="请先选择项目"
:options="unitOptions"
allow-search
allow-clear
:disabled="!filterParams.project"
:loading="loading.unit"
style="width: 200px"
@change="handleFilterChange"
/>
</div>
<!-- 部件选择 -->
<div class="filter-item">
<span class="filter-label">部件</span>
<a-select
v-model="filterParams.component"
placeholder="请先选择机组"
:options="componentOptions"
allow-search
allow-clear
:disabled="!filterParams.unit"
:loading="loading.component"
style="width: 200px"
@change="handleFilterChange"
/>
</div>
</a-space>
2025-07-14 11:11:33 +08:00
</div>
<!-- 已上传数据列表 -->
<div class="uploaded-files-section">
<a-table
:columns="fileColumns"
:data="imageList"
:pagination="false"
:scroll="{ x: '100%', y: 'calc(100vh - 380px)' }"
:loading="loading.image"
class="scrollable-table"
>
<!-- 文件类型 -->
<template #type="{ record }">
<a-tag :color="getFileTypeColor(record.type)" size="small">
{{ record.type }}
</a-tag>
</template>
<!-- 文件大小 -->
<template #size="{ record }">
<span>{{ record.imageTypeLabel}}</span>
</template>
<!-- 状态 -->
<template #status="{ record }">
<a-tag :color="getStatusColor(record.preTreatment)" size="small">
{{ record.preTreatment }}
</a-tag>
</template>
<!-- 操作 -->
<template #action="{ record }">
<a-space>
<a-button size="small" @click="previewFile(record)">预览</a-button>
<a-button size="small" status="danger" @click="deleteFile(record)">删除</a-button>
</a-space>
</template>
</a-table>
2025-07-14 11:11:33 +08:00
</div>
</div>
</a-tab-pane>
</a-tabs>
</div>
2025-07-14 11:11:33 +08:00
<!-- 文件预览模态框 -->
<PreviewModal ref="previewModal" />
2025-07-14 11:11:33 +08:00
</GiPageLayout>
</template>
<script setup lang="ts">
import { ref, reactive, computed,onMounted } from 'vue'
2025-07-14 11:11:33 +08:00
import { Message } from '@arco-design/web-vue'
import type { TableColumnData } from '@arco-design/web-vue'
import PreviewModal from './components/PreviewModal.vue'
import {
getProjectList,
getTurbineList,
getPartList,
getImageList,
deleteImage,
autoAnnotateImage,
generateReport,
batchUploadImages,
uploadImageToPartV2
} from '@/apis/industrial-image'
const previewModal = ref()
2025-07-14 11:11:33 +08:00
// 活动选项卡
const activeTab = ref('image')
// 筛选参数
const filterParams = reactive({
project: null,
unit: null,
component: null
})
// 筛选选项
const projectOptions = ref<Array<{label: string, value: string}>>([])
const unitOptions = ref<Array<{label: string, value: string}>>([])
const componentOptions = ref<Array<{label: string, value: string}>>([])
// 图像列表
const imageList = ref<Array<{
id: number
name: string
type: string
imageTypeLabel: string
shootingTime: string
preTreatment: string
url: string
}>>([])
// 加载状态
const loading = reactive({
project: false,
unit: false,
component: false,
image: false
})
// 在组件挂载时获取项目列表
onMounted(() => {
fetchProjectList()
})
// 监听项目变化,获取机组列表
if (watch) {
watch(() => filterParams.project, (newVal) => {
// 清空已选的机组和部件
filterParams.unit = null
filterParams.component = null
unitOptions.value = []
componentOptions.value = []
imageList.value = []
if (newVal) {
fetchTurbineList(newVal)
}
})
}
// 监听机组变化,获取部件列表
if (watch) {
watch(() => filterParams.unit, (newVal) => {
// 清空已选的部件
filterParams.component = null
componentOptions.value = []
imageList.value = []
if (newVal && filterParams.project) {
fetchPartList(filterParams.project, newVal)
}
})
}
// 获取项目列表
const fetchProjectList = async () => {
loading.project = true
try {
const res = await getProjectList({ page: 1, pageSize: 1000 });
projectOptions.value = res.data.map(item => ({
label: item.projectName,
value: item.projectId
}))
} catch (error) {
Message.error('获取项目列表失败')
} finally {
loading.project = false
}
}
// 获取机组列表
const fetchTurbineList = async (projectId: string) => {
loading.unit = true
try {
const res = await getTurbineList({ projectId })
unitOptions.value = res.data.map(item => ({
label: item.turbineName,
value: item.turbineId
}))
} catch (error) {
console.error('获取机组列表失败:', error)
Message.error('获取机组列表失败')
} finally {
loading.unit = false
}
}
// 获取部件列表
const fetchPartList = async (projectId: string, turbineId: string) => {
loading.component = true
try {
const res = await getPartList({ projectId, turbineId })
componentOptions.value = res.data.map(item => ({
label: item.partName, // 根据实际接口调整
value: item.partId // 根据实际接口调整
}))
} catch (error) {
console.error('获取部件列表失败:', error)
Message.error('获取部件列表失败')
} finally {
loading.component = false
}
}
// 处理筛选变化,获取图像列表
const handleFilterChange = async () => {
// if (!filterParams.project) return
loading.image = true
try {
let params = {
projectId: filterParams.project
}
if(filterParams.unit){
params = {
projectId: filterParams.project,
turbineId: filterParams.unit
}
}
if(filterParams.component){
params = {
projectId: filterParams.project,
turbineId: filterParams.unit,
partId: filterParams.component
}
}
const res = await getImageList(params)
imageList.value = res.data.map((item: any) => ({
id: item.imageId,
name: item.imageName,
type: item.imageType?item.imageType:"未指定类型",
imageTypeLabel: item.imageTypeLabel,
shootingTime: item.shootingTime,
preTreatment: item.preTreatment?"已审核":"未审核",
imagePath: item.imagePath,
audioList:item.audioList
}))
Message.success(`获取到 ${imageList.value.length} 条图像数据`)
} catch (error) {
Message.error('获取图像列表失败')
} finally {
loading.image = false
}
}
// const response = await getTurbineList({ projectId: node.id })
2025-07-14 11:11:33 +08:00
// 上传状态
const uploading = ref(false)
const uploadQueue = ref<any[]>([])
// 预览模态框
const previewModalVisible = ref(false)
const previewFileData = ref<any>(null)
// 已上传文件列表
const uploadedFiles = ref([])
2025-07-14 11:11:33 +08:00
// 文件表格列配置
const fileColumns: TableColumnData[] = [
{ title: '文件名', dataIndex: 'name', width: 250 },
{ title: '类型', dataIndex: 'type', slotName: 'type', width: 100 },
{ title: '类型描述', dataIndex: 'imageTypeLabel', slotName: 'imageTypeLabel', width: 100 },
{ title: '上传时间', dataIndex: 'shootingTime', width: 150 },
{ title: '状态', dataIndex: 'preTreatment', slotName: 'preTreatment', width: 100 },
2025-07-14 11:11:33 +08:00
{ title: '操作', slotName: 'action', width: 150, fixed: 'right' }
]
// 过滤后的文件列表
const filteredFiles = computed(() => {
return uploadedFiles.value.filter(file =>
(filterParams.project === null || file.project === filterParams.project) &&
(filterParams.unit === null || file.unit === filterParams.unit) &&
(filterParams.component === null || file.component === filterParams.component)
)
})
2025-07-14 11:11:33 +08:00
// 获取文件类型颜色
const getFileTypeColor = (type: string) => {
const colorMap: Record<string, string> = {
'TYPICAL': 'blue',
'DEFECT': 'orange',
2025-07-14 11:11:33 +08:00
'other': 'gray'
}
return colorMap[type] || 'gray'
}
// 获取状态颜色
const getStatusColor = (status: string) => {
console.log(status);
2025-07-14 11:11:33 +08:00
const colorMap: Record<string, string> = {
'已审核': 'green',
'未审核': 'red'
2025-07-14 11:11:33 +08:00
}
return colorMap[status] || 'gray'
}
// 格式化文件大小
const formatFileSize = (bytes: number) => {
if (bytes === 0) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + sizes[i]
}
const getImageUrl = (imagePath: string): string => {
if (!imagePath) return ''
if (imagePath.startsWith('http')) return imagePath
const baseUrl = 'http://pms.dtyx.net:9158'
return `${baseUrl}${imagePath}`
2025-07-14 11:11:33 +08:00
}
// 预览文件
const previewFile = (file: any) => {
/* previewFileData.value = file
previewModalVisible.value = true*/
const fileObj ={
id: file.id,
name: file.name,
url: getImageUrl(file.imagePath),
audios: file.audioList
}
previewModal.value.openPreview(fileObj)
2025-07-14 11:11:33 +08:00
}
// 删除文件
const deleteFile = (file: any) => {
console.log(index);
2025-07-14 11:11:33 +08:00
const index = uploadedFiles.value.findIndex(f => f.id === file.id)
if (index > -1) {
uploadedFiles.value.splice(index, 1)
Message.success('文件已删除')
}
}
</script>
<style scoped lang="less">
.data-storage-container {
padding: 16px;
background: #f5f5f5;
min-height: 100vh;
}
.page-header {
margin-bottom: 16px;
2025-07-14 11:11:33 +08:00
.page-title {
font-size: 20px;
font-weight: 500;
color: #262626;
margin: 0;
}
}
.tabs-section {
background: #fff;
border-radius: 8px;
padding: 16px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.tab-content {
margin-top: 16px;
}
.filter-section {
2025-07-14 11:11:33 +08:00
margin-bottom: 16px;
padding: 12px;
background: #fafafa;
border-radius: 4px;
.filter-item {
display: inline-flex;
2025-07-14 11:11:33 +08:00
align-items: center;
.filter-label {
font-size: 14px;
color: #595959;
margin-right: 8px;
2025-07-14 11:11:33 +08:00
}
}
}
.uploaded-files-section {
.section-title {
font-size: 16px;
font-weight: 500;
color: #262626;
margin: 0 0 16px 0;
}
}
.preview-container {
text-align: center;
2025-07-14 11:11:33 +08:00
.image-preview,
.video-preview {
max-height: 500px;
overflow: hidden;
}
2025-07-14 11:11:33 +08:00
.file-info {
text-align: left;
2025-07-14 11:11:33 +08:00
p {
margin: 8px 0;
font-size: 14px;
color: #595959;
}
}
}
:deep(.arco-tabs-nav) {
margin-bottom: 0;
}
:deep(.arco-tabs-tab) {
font-size: 14px;
padding: 8px 16px;
}
:deep(.arco-table-th) {
background-color: #fafafa;
color: #8c8c8c;
font-weight: 500;
}
:deep(.arco-table-td) {
padding: 12px 16px;
}
:deep(.arco-tag) {
border-radius: 4px;
font-size: 12px;
}
:deep(.arco-btn-size-small) {
padding: 2px 8px;
font-size: 12px;
}
:deep(.arco-upload-drag:hover) {
border-color: #1890ff;
}
</style>