From 4ff9a7c4824a8b364211ec4302bfced207df771c Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Tue, 22 Apr 2025 13:42:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E5=B8=A7=E6=B8=B2=E6=9F=93=E6=9B=B4?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../reading/dicoms3D/components/ReadPage.vue | 53 ++++++++++++------- .../reading/dicoms3D/components/StudyList.vue | 52 ++++++++++++++++++ .../reading/dicoms3D/components/Viewport.vue | 48 +++++++++++------ 3 files changed, 119 insertions(+), 34 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 3b16a915..d86aba45 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue @@ -27,6 +27,7 @@ :visit-task-info="s" :markedSeriesIds="markedSeriesIds" @activeSeries="activeSeries" + @showMultiFrame="showMultiFrame" /> @@ -436,7 +437,8 @@ import { // metaData, getRenderingEngine, eventTarget, - utilities as csUtils + utilities as csUtils, + cache } from '@cornerstonejs/core' import { annotation @@ -754,11 +756,12 @@ export default { const res1 = await getReadingVisitStudyList(this.trialId, sujectVisitId, taskId) let keyStudyIndex = -1 let keySeriesIndex = -1 - // const arr = res1.Result.filter(i => !i.IsCriticalSequence) + // const arr = [res1.Result[0]] const arr = res1.Result - arr.forEach((study, studyIndex) => { + arr.forEach((study, studyIndex) => { study.SeriesList.forEach((series, seriesIndex) => { const imageIds = [] + const stack = [] series.InstanceInfoList.forEach((instance, instanceIndex) => { if (study.IsCriticalSequence) { keyStudyIndex = studyIndex @@ -773,18 +776,19 @@ export default { const nFrames = instance.NumberOfFrames || 0 if (nFrames === 0) { // 单帧 - imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`) + stack.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`) } else { // 多帧 for (let i = 0; i < nFrames; i++) { const newImageId = `wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}&frame=${i + 1}` - imageIds.push(newImageId) + stack.push(newImageId) } } + imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`) this.instanceInfo[instance.Id] = { taskIndex, studyIndex, seriesIndex } } }) - + series.Stack = stack series.ImageIds = imageIds series.SliceIndex = 0 series.LoadedImageCount = 0 @@ -879,7 +883,7 @@ export default { // 初始化加载器 async initLoader() { await initLibraries() - + cache.setMaxCacheSize(6 * 1024 * 1024 * 1024); let renderingEngine = getRenderingEngine(renderingEngineId) if (!renderingEngine) { renderingEngine = new RenderingEngine(renderingEngineId) @@ -1610,6 +1614,7 @@ export default { }, // 翻页 scrollPage(type) { + this.clipPlaying = false this.$refs[`viewport-${this.activeViewportIndex}`][0].scrollPage(type) }, // 播放 @@ -1822,6 +1827,16 @@ export default { } this.setToolsPassive() }, + async showMultiFrame(obj) { + this.$refs[`viewport-${this.activeViewportIndex}`][0].setSeriesInfo(obj, true) + this.clipPlaying = false + this.fps = 15 + if (this.activeViewportIndex === this.cells.length - 1) { + this.lastViewportTaskId = obj.TaskInfo.VisitTaskId + this.currentVisitInfo = obj.TaskInfo + } + this.setToolsPassive() + }, // 激活视口 activeViewport(index) { if (this.activeViewportIndex === index) return @@ -1861,8 +1876,8 @@ export default { const idx = similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1 if (idx > -1) { obj = Object.assign({}, seriesList[idx]) - const imageIds = seriesList[idx].ImageIds - const sliceIdx = Math.floor(imageIds.length * ((baselineSeries.SliceIndex + 1) / baselineSeries.ImageIds.length)) + const stack = seriesList[idx].Stack + const sliceIdx = Math.floor(stack.length * ((baselineSeries.SliceIndex + 1) / baselineSeries.Stack.length)) // let sliceIdx = Math.floor(imageIds.length / 2) obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0 } @@ -1872,8 +1887,8 @@ export default { const idx = seriesList.findIndex(series => series.InstanceCount === baselineSeries.InstanceCount) if (idx > -1) { obj = Object.assign({}, seriesList[idx]) - const imageIds = seriesList[idx].ImageIds - const sliceIdx = Math.floor(imageIds.length / 2) + const stack = seriesList[idx].Stack + const sliceIdx = Math.floor(stack.length / 2) obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0 } } @@ -1882,8 +1897,8 @@ export default { const idx = seriesList.findIndex(series => series.IsDicom && parseInt(series.SliceThickness) === 5) if (idx > -1) { obj = Object.assign({}, seriesList[idx]) - const imageIds = seriesList[idx].ImageIds - const sliceIdx = Math.floor(imageIds.length / 2) + const stack = seriesList[idx].Stack + const sliceIdx = Math.floor(stack.length / 2) obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0 } } @@ -1897,8 +1912,8 @@ export default { const seriesIdx = studyList[k].SeriesList.findIndex(s => s.SliceThickness && parseInt(s.SliceThickness) === 5) if (seriesIdx > -1) { obj = Object.assign({}, studyList[k].SeriesList[seriesIdx]) - const imageIds = studyList[k].SeriesList[seriesIdx].ImageIds - const sliceIdx = Math.floor(imageIds.length / 2) + const stack = studyList[k].SeriesList[seriesIdx].Stack + const sliceIdx = Math.floor(stack.length / 2) obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0 obj.IsMarked = false break @@ -1910,8 +1925,8 @@ export default { const sIdx = studyList.findIndex(s => s.IsDicom) if (sIdx > -1) { obj = Object.assign({}, studyList[sIdx].SeriesList[0]) - const imageIds = studyList[sIdx].SeriesList[0].ImageIds - const sliceIdx = Math.floor(imageIds.length / 2) + const stack = studyList[sIdx].SeriesList[0].Stack + const sliceIdx = Math.floor(stack.length / 2) obj.SliceIndex = sliceIdx > 0 ? sliceIdx - 1 : 0 obj.IsMarked = false } @@ -1936,8 +1951,8 @@ export default { } else { filterStr = `instanceId=${annotation.InstanceId}` } - const imageIds = seriesList[seriesIdx].ImageIds - const imageIdIdx = imageIds.findIndex(is => is.includes(filterStr)) + const stack = seriesList[seriesIdx].Stack + const imageIdIdx = stack.findIndex(is => is.includes(filterStr)) if (imageIdIdx > -1) { obj = Object.assign({}, seriesList[seriesIdx]) obj.SliceIndex = imageIdIdx diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/StudyList.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/StudyList.vue index 58a30484..4419cdce 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/StudyList.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/StudyList.vue @@ -65,8 +65,34 @@ />
+
+ +
+
+
+
{{ instance.InstanceNumber }}
+
{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}
+
+ +
+
+ +
+
#{{ series.SeriesNumber }} +
{{ series.Description }} @@ -154,6 +180,31 @@ export default { if (!studyId) return this.activeStudy(studyId) }, + showMultiFrames(studyIndex, series, seriesIndex, instance) { + let obj = Object.assign({}, series) + this.activeStudyIndex = studyIndex + this.activeSeriesIndex = seriesIndex + let taskId = this.visitTaskInfo.VisitTaskId + const nFrames = instance.NumberOfFrames || 0 + let imageIds = [] + const stack = [] + if (nFrames === 0) { + // 单帧 + stack.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`) + } else { + // 多帧 + for (let i = 0; i < nFrames; i++) { + const newImageId = `wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}&frame=${i + 1}` + stack.push(newImageId) + } + } + imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${taskId}`) + obj.Stack = stack + obj.ImageIds = imageIds + obj.SliceIndex = 0 + this.$emit('showMultiFrame', obj) + + }, getPreviousOrNextSeries(type, series) { const seriseList = this.studyList.map(s => s.SeriesList).flat() const i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId) @@ -242,6 +293,7 @@ export default { flex: 1; padding-left: 5px; color: #ddd; + position: relative; .text-desc { width: 100px; white-space: nowrap; diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/Viewport.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/Viewport.vue index 76268fab..35ea856b 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/Viewport.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Viewport.vue @@ -26,7 +26,7 @@ {{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
Series: #{{ series.SeriesNumber }}
-
Image: #{{ `${series.SliceIndex + 1}/${series.ImageIds.length}` }}
+
Image: #{{ `${series.SliceIndex + 1}/${series.Stack.length}` }}
{{ series.Modality }}
= 6 || i === imageIdsToPrefetch.length - 1) { + await Promise.all(taskPromises) + taskPromises = [] + } } - this.series = { ...obj } - const renderingEngine = getRenderingEngine(this.renderingEngineId) - const viewport = renderingEngine.getViewport(this.viewportId) - await viewport.setStack(obj.ImageIds, obj.SliceIndex) - cornerstoneTools.utilities.stackPrefetch.enable(viewport.element) - viewport.render() + }, + async setSeriesInfo(obj, isLocate = false) { + try { + if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) { + obj.SliceIndex = this.series.SliceIndex + } + this.series = { ...obj } + const renderingEngine = getRenderingEngine(this.renderingEngineId) + const viewport = renderingEngine.getViewport(this.viewportId) + await this.prefetchMetadataInformation(obj.ImageIds) + await viewport.setStack(this.series.Stack, obj.SliceIndex) + // cornerstoneTools.utilities.stackContextPrefetch.enable(viewport.element) + viewport.render() + } catch(e) { + console.log(e) + } + }, cornerstoneToolsMouseMove(e) { const { currentPoints } = e.detail @@ -373,8 +391,8 @@ export default { clickSlider(e) { const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight this.sliderInfo.height = height - let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100) - sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx + let sliceIdx = Math.trunc(this.series.Stack.length * height / 100) + sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx const renderingEngine = getRenderingEngine(this.renderingEngineId) const viewport = renderingEngine.getViewport( this.viewportId @@ -401,8 +419,8 @@ export default { if (delta < 0) return if (delta > boxHeight) return const height = delta * 100 / boxHeight - let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100) - sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx + let sliceIdx = Math.trunc(this.series.Stack.length * height / 100) + sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx this.sliderInfo.height = height const renderingEngine = getRenderingEngine(this.renderingEngineId) const viewport = renderingEngine.getViewport(