From 23ac15f97814efa3e76d0ae072f64de72aef4d07 Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Wed, 23 Apr 2025 14:10:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B8=83=E5=B1=80=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reading/dicoms3D/components/ReadPage.vue | 292 +++++++++++++----- 1 file changed, 212 insertions(+), 80 deletions(-) diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue index 49b98832..d690b51c 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue @@ -34,7 +34,7 @@ - +
@@ -290,73 +290,76 @@
- -
-
+
+ +
+
+
+ +
+
+
+ +
- +
+
- -
-
- - -
- -
+ import { getRelatedVisitTask, getReadingVisitStudyList, getTableAnswerRowInfoList } from '@/api/trials' import { getDoctorShortcutKey, getUserWLTemplateList } from '@/api/user' +import { getCustomTag, submitCustomTag } from '@/api/reading' import { RenderingEngine, Enums, @@ -555,7 +559,7 @@ export default { renderingEngineId: renderingEngineId, sLoading: false, renderedTaskIds: [], - citerionType: null, + criterionType: null, tools: [], rotateOptions: [ { label: this.$t('trials:reading:button:rotateDefault'), val: 1 }, @@ -679,10 +683,38 @@ export default { }, mounted() { this.taskInfo = JSON.parse(localStorage.getItem('taskInfo')) - this.citerionType = this.taskInfo.CriterionType + this.criterionType = this.taskInfo.CriterionType const digitPlaces = Number(localStorage.getItem('digitPlaces')) this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces - this.tools = getTools(this.citerionType) + if (this.criterionType === 0) { + this.tools = [{ + "name": "直径测量工具", + "icon": "length", + "toolName": "Length", + "i18nKey": "trials:reading:button:length", + "isDisabled": false, + "disabledReason": '' + }, + { + "name": "矩形工具", + "icon": "rectangle", + "toolName": "RectangleROI", + "i18nKey": "trials:reading:button:rectangle", + "isDisabled": false, + "disabledReason": '' + }, + { + "name": "箭头工具", + "icon": "arrow", + "toolName": "ArrowAnnotate", + "i18nKey": "trials:reading:button:arrowAnnotate", + "isDisabled": false, + "disabledReason": '' + }] + } else { + this.tools = getTools(this.criterionType) + } + this.trialId = this.$route.query.trialId this.readingTaskState = this.taskInfo.ReadingTaskState if (!this.taskInfo.IsBaseLine && this.taskInfo.IsReadingTaskViewInOrder !== 0) { @@ -828,11 +860,19 @@ export default { res1.Result[keyStudyIndex].SeriesList[keySeriesIndex].ImageIds = keyImageIds } // 获取标注信息 - const res2 = await getTableAnswerRowInfoList(taskId) + let res2 = null + if (this.criterionType === 0) { + res2 = await getCustomTag({visitTaskId: taskId}) + } else { + res2 = await getTableAnswerRowInfoList(taskId) + } const annotationUIDs = [] const annotations = res2.Result.map(i => { if (typeof i.MeasureData === 'string' && i.MeasureData) { i.MeasureData = JSON.parse(i.MeasureData) + if (this.criterionType === 0) { + i.MeasureData.id = i.Id + } annotationUIDs.push(i.MeasureData.annotationUID) } return i @@ -960,7 +1000,7 @@ export default { toolGroup.addTool(WindowLevelTool.toolName) toolGroup.addTool(WindowLevelRegionTool.toolName) toolGroup.addTool(PlanarRotateTool.toolName) - if (this.citerionType === 0) { + if (this.criterionType === 0) { toolGroup.addTool(ArrowAnnotateTool.toolName, { arrowHeadStyle: 'standard', changeTextCallback: async(data, eventData, doneChangingTextCallback) => { @@ -1107,7 +1147,7 @@ export default { }, addAnnotationListeners() { const debouncedCallback = this.debounce((evt) => { - this.annotationModifiedListener(evt) + this.criterionType === 0 ? this.customAnnotationModifiedListener(evt) : this.annotationModifiedListener(evt) }, 100) eventTarget.addEventListener( toolsEvents.ANNOTATION_MODIFIED, @@ -1117,11 +1157,11 @@ export default { ) eventTarget.addEventListener( toolsEvents.ANNOTATION_COMPLETED, - this.annotationCompletedListener + this.criterionType === 0 ? this.customAnnotationCompletedListener : this.annotationCompletedListener ) eventTarget.addEventListener( toolsEvents.ANNOTATION_REMOVED, - this.annotationRemovedListener + this.criterionType === 0 ? this.customAnnotationRemovedListener : this.annotationRemovedListener ) // eventTarget.addEventListener( // toolsEvents.ANNOTATION_ADDED, @@ -1141,6 +1181,7 @@ export default { annotationAddedListener(e) { }, + annotationCompletedListener(e) { console.log('Completed') if (this.readingTaskState === 2) return @@ -1170,7 +1211,6 @@ export default { console.log('Modified') if (this.readingTaskState === 2) return const { annotation } = e.detail - console.log(annotation.highlighted) if (!annotation.highlighted) return if (!annotation) return if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return @@ -1191,7 +1231,77 @@ export default { this.markedSeriesIds.splice(index, 1) } } - console.log(this.markedSeriesIds) + }, + async customAnnotationCompletedListener(e) { + if (this.readingTaskState === 2) return + const { annotation } = e.detail + if (!annotation) return + if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return + const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series + if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { + const referencedImageId = annotation.metadata.referencedImageId + const params = this.getInstanceInfo(referencedImageId) + annotation.visitTaskId = series.TaskInfo.VisitTaskId + annotation.studyId = series.StudyId + annotation.seriesId = series.Id + annotation.instanceId = params.instanceId + annotation.sliceThickness = series.SliceThickness + annotation.numberOfFrames = isNaN(parseInt(params.frame)) ? null : parseInt(params.frame) + annotation.markTool = annotation.metadata.toolName + this.markedSeriesIds.push(series.Id) + let markName = await this.customPrompt() + if (markName) { + annotation.data.label = markName + this.saveCustomAnnotation(annotation) + } else { + this.removeAnnotation(annotation) + } + + } + + this.setToolsPassive() + }, + async saveCustomAnnotation(annotation) { + try { + let measureData = Object.assign({}, annotation) + let params = {} + params.VisitTaskId = annotation.visitTaskId + params.StudyId = annotation.studyId + params.SeriesId = annotation.seriesId + params.InstanceId = annotation.instanceId + params.Id = annotation.id ? annotation.id : '' + params.MeasureData = JSON.stringify(measureData) + params.NumberOfFrames = annotation.numberOfFrames + let res = await submitCustomTag(params) + annotation.id = res.Result + console.log(res) + } catch(e) { + console.log(e) + } + }, + customAnnotationModifiedListener(e) { + if (this.readingTaskState === 2) return + const { annotation } = e.detail + if (!annotation.highlighted) return + if (!annotation) return + if (!annotation.data.label) return + if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return + const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series + if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { + this.saveCustomAnnotation(annotation) + } + this.setToolsPassive() + }, + customAnnotationRemovedListener(e) { + if (this.readingTaskState === 2) return + const { annotation } = e.detail + if (!annotation) return + if (annotation.visitTaskId === this.taskInfo.VisitTaskId && annotation.seriesId) { + const index = this.markedSeriesIds.indexOf(annotation.seriesId) + if (index !== -1) { + this.markedSeriesIds.splice(index, 1) + } + } }, removeAnnotation(annotation) { cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID) @@ -1208,11 +1318,19 @@ export default { if (taskIdx === -1) return if (!this.visitTaskList[taskIdx].IsCurrentTask) return // 获取标注信息 - const res = await getTableAnswerRowInfoList(visitTaskId) + let res = null + if (this.criterionType === 0) { + res = await getCustomTag({visitTaskId: visitTaskId}) + } else { + res = await getTableAnswerRowInfoList(visitTaskId) + } const annotationUIDs = [] const annotations = res.Result.map(i => { if (typeof i.MeasureData === 'string' && i.MeasureData) { i.MeasureData = JSON.parse(i.MeasureData) + if (this.criterionType === 0) { + i.MeasureData.id = i.Id + } annotationUIDs.push(i.MeasureData.annotationUID) } return i @@ -1226,10 +1344,18 @@ export default { if (taskIdx === -1) return if (!this.visitTaskList[taskIdx].IsCurrentTask) return // 获取标注信息 - const res = await getTableAnswerRowInfoList(visitTaskId) + let res = null + if (this.criterionType === 0) { + res = await getCustomTag({visitTaskId: visitTaskId}) + } else { + res = await getTableAnswerRowInfoList(visitTaskId) + } const annotations = res.Result.map(i => { if (typeof i.MeasureData === 'string' && i.MeasureData) { i.MeasureData = JSON.parse(i.MeasureData) + if (this.criterionType === 0) { + i.MeasureData.id = i.Id + } } return i }) @@ -1440,7 +1566,7 @@ export default { this.setToolEnabled() } } else { - // const obj = this.$refs['ecrf'].validTool(toolName, true) + if (this.criterionType === 0) return const obj = this.$refs[`ecrf_${this.lastViewportTaskId}`][0].validTool(toolName, true) this.tools[i].disabledReason = obj.reason if (!obj.isCanActiveTool) { @@ -1528,7 +1654,7 @@ export default { const visitTaskNum = idx > -1 ? this.visitTaskList[idx].VisitTaskNum : -1 if (visitTaskNum > 0) { let visitTaskIdx = -1 - if (this.citerionType === 10) { + if (this.criterionType === 10) { visitTaskIdx = this.visitTaskList.findIndex(i => i.VisitTaskNum === visitTaskNum - 1) } else { visitTaskIdx = this.visitTaskList.findIndex(i => i.IsBaseLineTask) @@ -2434,6 +2560,11 @@ export default { color: #fff; } } + .content-wrapper { + flex: 1; + display: flex; + flex-direction: row; + } .viewports-wrapper { flex: 1; .grid-container { @@ -2457,14 +2588,15 @@ export default { grid-row: 1 / -1; } } + .form-wrapper { + width: 400px; + border: 1px solid #727272; + overflow-y: auto; + user-select: none; + } } } - .right-panel { - width: 400px; - border: 1px solid #727272; - overflow-y: auto; - user-select: none; - } + .personal_config { ::v-deep .el-tabs__content{ height: 450px;