新增缺陷增加轴向和弦向字段|缺陷检测界面新增图像预览功能和增加典型图片设置功能|去除可视化菜单

This commit is contained in:
Vic 2025-07-25 00:13:51 +08:00
parent 70fca26e10
commit fe6e84f5f7
6 changed files with 339 additions and 20 deletions

View File

@ -765,12 +765,6 @@ export const systemRoutes: RouteRecordRaw[] = [
redirect: '/construction-operation-platform/implementation-workflow/data-processing/intelligent-inspection/defect-algorithm',
meta: { title: '数据分析与图像检测', icon: 'scan', hidden: false },
children: [
{
path: '/construction-operation-platform/implementation-workflow/data-processing/intelligent-inspection/tree-visualization',
name: 'TreeVisualization',
component: () => import('@/views/project-operation-platform/data-processing/key-info-extraction/index.vue'),
meta: { title: '可视化管理', icon: 'cluster', hidden: false },
},
{
path: '/construction-operation-platform/implementation-workflow/data-processing/intelligent-inspection/defect-algorithm',
name: 'DefectAlgorithm',

View File

@ -70,6 +70,6 @@ declare global {
// for type re-export
declare global {
// @ts-ignore
export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'
export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue'
import('vue')
}

View File

@ -12,6 +12,14 @@
<a-form-item label="缺陷名称" field="defectName">
<a-input v-model="form.defectName" placeholder="请输入缺陷名称" />
</a-form-item>
<!-- 缺陷位置 -->
<a-form-item
field="defectPosition"
label="缺陷位置"
>
<a-input v-model="form.defectPosition" placeholder="请输入缺陷位置" />
</a-form-item>
<!-- 缺陷类型 -->
<a-form-item
@ -27,19 +35,47 @@
<a-option v-for="type in defectTypes" :key="type.code" :value="type.code">{{ type.label }}</a-option>
</a-select>
</a-form-item>
<!-- 缺陷位置 -->
<a-form-item
field="defectPosition"
label="缺陷位置"
>
<a-input v-model="form.defectPosition" placeholder="请输入缺陷位置" />
</a-form-item>
<!--轴向尺寸-->
<div class="dimension-fields">
<a-form-item
field="axialDimension"
label="轴向尺寸 (mm)"
:rules="[{ type: 'number', min: 0, message: '必须大于等于0' }]"
>
<a-input-number
v-model="form.axialDimension"
:min="0"
:step="1"
placeholder="请输入轴向尺寸"
mode="button"
size="large"
>
</a-input-number>
</a-form-item>
<!--弦向尺寸 -->
<a-form-item
field="chordDimension"
label="弦向尺寸 (mm)"
:rules="[{ type: 'number', min: 0, message: '必须大于等于0' }]"
>
<a-input-number
v-model="form.chordDimension"
:min="0"
:step="1"
placeholder="请输入弦向尺寸"
mode="button"
size="large"
>
</a-input-number>
</a-form-item>
</div>
<!-- 缺陷等级 -->
<a-form-item
field="defectLevel"
label="缺陷等级"
label="严重程度"
:rules="[{ required: true, message: '请选择缺陷等级' }]"
>
<a-select
@ -104,6 +140,8 @@ interface DefectFormData {
defectPosition: string
description: string
repairIdea: string
axialDimension: number | 0
chordDimension: number | 0
}
const props = defineProps<{
@ -135,7 +173,9 @@ const form = reactive<DefectFormData>({
defectLevelLabel: '',
defectPosition: '',
description: '',
repairIdea: '建议进行进一步检查'
repairIdea: '建议进行进一步检查',
axialDimension: 0, // null
chordDimension: 0 // null
})
//
@ -326,6 +366,7 @@ const handleSubmit = async () => {
}
//
console.log("form:",form);
emit('submit', form, props.annotation)
} catch (error) {
@ -434,6 +475,25 @@ onMounted(() => {
}
}
.dimension-fields {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 16px;
margin-bottom: 16px;
:deep(.arco-input-number) {
width: 100%;
.arco-input-number-step {
width: 32px;
}
.arco-input-number-input {
text-align: center;
}
}
}
:deep(.arco-form-item) {
margin-bottom: 16px;
}

View File

@ -0,0 +1,243 @@
<template>
<a-modal
:visible="previewModalVisible"
title="图像详情"
width="80%"
:footer="footerButtons"
:mask-closable="true"
@update:visible="emit('update:previewModalVisible', $event)"
:confirm-loading="loading"
>
<div v-if="previewImage" class="modal-image-viewer">
<img :src="getImageUrl(previewImage.imagePath)" :alt="editingData.imageName" class="preview-image" />
<div class="image-details">
<a-form layout="vertical" :model="editingData">
<a-form-item label="图片名称" field="imageName">
<a-input v-model="editingData.imageName" />
</a-form-item>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="大小" field="size">
<a-input :model-value="formatFileSize(editingData.size || 0)" disabled />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="尺寸" field="imageResolution">
<a-input v-model="editingData.imageResolution" />
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="采集员ID" field="collectId">
<a-input v-model="editingData.collectId" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="采集员姓名" field="collectorName">
<a-input v-model="editingData.collectorName" />
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col :span="12">
<a-form-item label="来源" field="imageSource">
<a-input v-model="editingData.imageSource" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="图片类型" field="imageType">
<a-select v-model="editingData.imageType">
<a-option value="DEFECT">缺陷影像</a-option>
<a-option value="TYPICAL">典型影像</a-option>
<a-option value="OTHER">其他影像</a-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-form-item label="图片类型描述" field="imageTypeLabel">
<a-textarea
v-model="editingData.imageTypeLabel"
:auto-size="{ minRows: 2, maxRows: 4 }"
/>
</a-form-item>
</a-form>
</div>
</div>
<template #footer>
<a-button @click="emit('update:previewModalVisible', false)">取消</a-button>
<a-button type="primary" :loading="loading" @click="handleSave">保存</a-button>
</template>
</a-modal>
</template>
<script setup lang="ts">
import { ref, watch, computed } from 'vue'
import { Message } from '@arco-design/web-vue'
import axios from 'axios'
const props = defineProps<{
previewModalVisible: boolean
previewImage: {
imagePath: string
imageName: string
size?: number
imageResolution?: string
collectId?: string
collectorName?: string
imageSource?: string
imageType?: string
imageTypeLabel?: string
partId?: string
} | null
selectedImage: any | null
}>()
const emit = defineEmits<{
'update:previewModalVisible': [visible: boolean]
'save': [data: any]
}>()
const loading = ref(false)
const editingData = ref<{
imagePath: string
imageName: string
size?: number
imageResolution?: string
collectId?: string
collectorName?: string
imageSource?: string
imageType?: string
imageTypeLabel?: string
partId?: string
imageId?:string
}>({
imagePath: '',
imageName: '',
size: 0,
imageResolution: '',
collectId: '',
collectorName: '',
imageSource: '',
imageType: '',
imageTypeLabel: '',
partId: '',
imageId:''
})
//
watch(() => props.previewImage, (newVal) => {
if (newVal) {
editingData.value = { ...newVal }
}
}, { immediate: true, deep: true })
const getImageUrl = (imagePath: string): string => {
if (!imagePath) return ''
if (imagePath.startsWith('http')) return imagePath
const baseUrl = 'http://pms.dtyx.net:9158'
return `${baseUrl}${imagePath}`
}
const formatFileSize = (size: number): string => {
if (size < 1024) return `${size} B`
if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`
if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(1)} MB`
return `${(size / (1024 * 1024 * 1024)).toFixed(1)} GB`
}
const handleSave = async () => {
if (!editingData.value.imageName?.trim()) {
Message.error('图片名称不能为空')
return
}
if (!editingData.value.partId) {
Message.error('缺少部件ID无法保存')
return
}
try {
loading.value = true
//
const requestData = {
collectId: editingData.value.collectId,
collectorName: editingData.value.collectorName,
imageSource: editingData.value.imageSource,
imageType: editingData.value.imageType,
imageTypeLabel: editingData.value.imageTypeLabel,
imageList: [
{
imageId: editingData.value.imageId,
imageName: editingData.value.imageName,
imageResolution: editingData.value.imageResolution,
}
],
}
console.log("requestData:",requestData);
//
const response = await axios.put(
`http://pms.dtyx.net:9158/image/setting-info/${editingData.value.partId}`,
requestData
)
if (response.data && response.data.code === 0) {
Message.success('图片信息保存成功')
emit('save', editingData.value)
emit('update:previewModalVisible', false)
} else {
Message.error(response.data?.message || '保存失败')
}
} catch (error) {
console.error('保存图片信息失败:', error)
Message.error('保存失败,请稍后重试')
} finally {
loading.value = false
}
}
</script>
<style scoped lang="scss">
.modal-image-viewer {
display: flex;
gap: 24px;
align-items: flex-start;
.preview-image {
flex: 1;
max-width: 60%;
max-height: 500px;
object-fit: contain;
border-radius: 8px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.image-details {
flex: 1;
padding: 16px;
:deep(.arco-form) {
.arco-form-item {
margin-bottom: 16px;
}
}
}
}
@media (max-width: 768px) {
.modal-image-viewer {
flex-direction: column;
.preview-image {
max-width: 100%;
}
}
}
</style>

View File

@ -349,6 +349,7 @@ export function useIndustrialImage() {
}
const handleImagePreview = (image: any) => {
console.log("image:",image);
previewImage.value = image
previewModalVisible.value = true
}

View File

@ -145,7 +145,14 @@
</div>
<!-- 模态框 -->
<ImageModals
:preview-modal-visible="previewModalVisible"
:preview-image="previewImage"
:process-image="processImage"
:selected-image="selectedImage"
@update:preview-modal-visible="previewModalVisible = $event"
@save="handleSaveImageSuccess"
/>
</div>
</template>
@ -158,6 +165,7 @@ import ProjectTree from './components/ProjectTree.vue'
import ImagePreview from './components/ImagePreview.vue'
import ImageCanvas from '@/views/project-operation-platform/data-processing/industrial-image/components/ImageCanvas.vue'
import IndustrialImageList from '@/components/IndustrialImageList/index.vue'
import ImageModals from './components/ImageModals.vue'
import RecognitionResults from './components/RecognitionResults.vue'
import DefectListPanel from './components/DefectListPanel.vue'
import DefectDetailsForm from './components/DefectDetailsForm.vue'
@ -212,6 +220,19 @@ const loadDefectLevels = async () => {
}
}
//
const handleSaveImageSuccess = (updatedData: any) => {
//
Message.success('图片信息已更新')
// selectedImagepreviewImage
if (selectedImage.value && selectedImage.value.id === updatedData.id) {
selectedImage.value = { ...selectedImage.value, ...updatedData }
}
if (previewImage.value && previewImage.value.id === updatedData.id) {
previewImage.value = { ...previewImage.value, ...updatedData }
}
}
// 使
const {
//
@ -594,8 +615,8 @@ const handleDefectFormSubmit = async (formData: any, annotation: Annotation) =>
const defectData = {
attachId: attachId,
attachPath: '',
// axial: 0,
// chordwise: 0,
axial: formData.axialDimension,
chordwise: formData.chordDimension,
// defectCode: `MANUAL_${Date.now()}`,
defectId: '',
defectLevel: formData.defectLevel,