From 47091251074a72b26bd54765fd0a4b2287a0ac78 Mon Sep 17 00:00:00 2001 From: caiyiling <1321909229@qq.com> Date: Wed, 1 Jul 2026 16:59:24 +0800 Subject: [PATCH] =?UTF-8?q?=E9=9D=9Edicom=E5=9B=BE=E5=83=8F=E8=B4=A8?= =?UTF-8?q?=E6=8E=A7=E8=A7=86=E5=8F=A3=E4=BF=A1=E6=81=AF=E6=9B=B4=E6=94=B9?= =?UTF-8?q?=EF=BC=9B=E6=B7=BB=E5=8A=A0=E9=80=82=E5=BA=94=E7=AA=97=E5=8F=A3?= =?UTF-8?q?=E3=80=81=E9=80=82=E5=BA=94=E5=9B=BE=E5=83=8F=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../none-dicoms/components/file-viewer.vue | 144 ++++++++++++++++-- .../none-dicoms/components/study-list.vue | 3 + 2 files changed, 135 insertions(+), 12 deletions(-) diff --git a/src/views/none-dicoms/components/file-viewer.vue b/src/views/none-dicoms/components/file-viewer.vue index e14f4101..c0d762aa 100644 --- a/src/views/none-dicoms/components/file-viewer.vue +++ b/src/views/none-dicoms/components/file-viewer.vue @@ -11,6 +11,10 @@
{{ v.currentFileName }}
+
{{ `${ v.currentImageIdIndex + 1 } / ${ v.imageIds.length }` }}
+
+
+
{{ `Zoom: ${v.zoomText}` }}
+ @@ -210,6 +220,7 @@ export default { activeTool: '', imageType: ['image/jpeg', 'image/jpg', 'image/bmp', 'image/png'], loading: false, + isFitToWindowMode: false, trialId: null, activeName: '1', tools: [], @@ -257,7 +268,8 @@ export default { oldB: null, oldM: null, isMove: false, - height: 0 + height: 0, + zoomText: '' })) this.initLoader() this.$refs['viewports-wrapper'].addEventListener('wheel', (e) => { @@ -452,6 +464,9 @@ export default { const renderingEngine = getRenderingEngine(renderingEngineId) if (renderingEngine) { renderingEngine.resize(true, false) + this.$nextTick(() => { + this.reapplyFitModeForVisibleViewports() + }) } }) const element1 = this.$refs['canvas-0'][0] @@ -468,6 +483,7 @@ export default { element.oncontextmenu = (e) => e.preventDefault() resizeObserver.observe(element) element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage) + element.addEventListener('CORNERSTONE_IMAGE_RENDERED', this.handleImageRendered) }) const viewportInputArray = [ { @@ -558,16 +574,57 @@ export default { const { detail } = e const i = this.viewportInfos.findIndex(i => i.viewportId === detail.viewportId) if (i === -1) return - this.viewportInfos[i].currentImageIdIndex = detail.imageIdIndex - const obj = this.viewportInfos[i].fileList[detail.imageIdIndex] - if (!obj) return - this.viewportInfos[i].currentFileName = obj.FileName - const total = this.viewportInfos[i].imageIds.length - this.viewportInfos[i].height = total > 1 ? (this.viewportInfos[i].currentImageIdIndex) * 100 / (total - 1) : 0 - this.$emit('toggleImage', { - studyId: this.viewportInfos[i].studyId, - path: obj.Path - }) + if (detail.imageIdIndex !== this.viewportInfos[i].currentImageIdIndex) { + this.viewportInfos[i].currentImageIdIndex = detail.imageIdIndex + const obj = this.viewportInfos[i].fileList[detail.imageIdIndex] + if (!obj) return + this.viewportInfos[i].currentFileName = obj.FileName + const total = this.viewportInfos[i].imageIds.length + this.viewportInfos[i].height = total > 1 ? (this.viewportInfos[i].currentImageIdIndex) * 100 / (total - 1) : 0 + this.$emit('toggleImage', { + studyId: this.viewportInfos[i].studyId, + path: obj.Path + }) + this.$nextTick(() => { + this.applyFitMode(i, this.isFitToWindowMode) + }) + return + } + this.updateZoomDisplayByViewportId(detail.viewportId) + }, + handleImageRendered(e) { + const viewportId = e?.detail?.viewportId || e?.currentTarget?.dataset?.viewportUid + if (!viewportId) return + this.updateZoomDisplayByViewportId(viewportId) + }, + updateZoomDisplayByViewportId(viewportId) { + const index = this.viewportInfos.findIndex(item => item.viewportId === viewportId) + if (index === -1) return + this.updateZoomDisplay(index) + }, + updateZoomDisplay(index) { + const viewportInfo = this.viewportInfos[index] + if (!viewportInfo || !this.imageType.includes(viewportInfo.fileType) || !viewportInfo.imageIds.length) { + if (viewportInfo) viewportInfo.zoomText = '' + return + } + const renderingEngine = getRenderingEngine(renderingEngineId) + const viewport = renderingEngine?.getViewport(viewportInfo.viewportId) + if (!viewport) return + const camera = viewport.getCamera?.() + const canvas = viewport.getCanvas?.() || this.$refs[`canvas-${index}`]?.[0] + const canvasHeight = canvas?.clientHeight + const parallelScale = Number(camera?.parallelScale) + if (!canvasHeight || !Number.isFinite(parallelScale) || parallelScale <= 0) { + viewportInfo.zoomText = '' + return + } + const magnification = canvasHeight / (parallelScale * 2) + if (!Number.isFinite(magnification) || magnification <= 0) { + viewportInfo.zoomText = '' + return + } + viewportInfo.zoomText = `${magnification.toFixed(1)}x` }, // 渲染图片 async renderImage(imageIds, canvasIndex, sliceIndex) { @@ -578,6 +635,10 @@ export default { this.setToolsPassive() viewport.setImageIdIndex(sliceIndex) viewport.render() + this.$nextTick(() => { + this.applyFitMode(canvasIndex, this.isFitToWindowMode) + this.updateZoomDisplay(canvasIndex) + }) // this.updateViewportInfos() }, setActiveCanvasImages(obj) { @@ -636,6 +697,7 @@ export default { }) } else { this.viewportInfos[i].currentFilePath = obj.fileInfo.Path + this.viewportInfos[i].zoomText = '' } }, // 切换图片 @@ -718,6 +780,52 @@ export default { const viewport = (renderingEngine.getViewport(viewportId)) viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true }) renderingEngine.render() + this.updateZoomDisplay(this.activeCanvasIndex) + }, + toggleFitMode() { + this.setToolsPassive() + this.isFitToWindowMode = !this.isFitToWindowMode + this.applyFitMode(this.activeCanvasIndex, this.isFitToWindowMode) + }, + applyFitMode(canvasIndex = this.activeCanvasIndex, isFitToWindowMode = this.isFitToWindowMode) { + const viewportInfo = this.viewportInfos[canvasIndex] + if (!viewportInfo || !this.imageType.includes(viewportInfo.fileType) || !viewportInfo.imageIds.length) return + const renderingEngine = getRenderingEngine(renderingEngineId) + const viewport = renderingEngine?.getViewport(`canvas-${canvasIndex}`) + if (!viewport) return + + viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true }) + if (isFitToWindowMode) { + viewport.render() + return + } + + const canvas = viewport.getCanvas() || this.$refs[`canvas-${canvasIndex}`]?.[0] + const imageData = viewport.getImageData?.()?.imageData + const dimensions = imageData?.getDimensions?.() + const imageWidth = dimensions?.[0] + const imageHeight = dimensions?.[1] + const canvasWidth = canvas?.clientWidth + const canvasHeight = canvas?.clientHeight + + if (!imageWidth || !imageHeight || !canvasWidth || !canvasHeight) { + viewport.render() + return + } + + const fitScale = Math.min(canvasWidth / imageWidth, canvasHeight / imageHeight) + if (fitScale > 0) { + viewport.setZoom(1 / fitScale) + } + viewport.render() + this.updateZoomDisplay(canvasIndex) + }, + reapplyFitModeForVisibleViewports() { + this.viewportInfos.forEach((viewportInfo, index) => { + if (index >= this.cells.length) return + if (!this.imageType.includes(viewportInfo.fileType) || !viewportInfo.imageIds.length) return + this.applyFitMode(index, this.isFitToWindowMode) + }) }, setZoomScale(isZoomIn) { this.setToolsPassive() @@ -733,6 +841,7 @@ export default { const parallelScale = Math.max(0.0001, Math.min(1000000, next)) viewport.setCamera({ parallelScale }) viewport.render() + this.updateZoomDisplay(this.activeCanvasIndex) }, // 滚动条 clickSlider(e, index) { @@ -753,6 +862,7 @@ export default { this.setToolsPassive() viewport.setImageIdIndex(sliceIdx) viewport.render() + this.updateZoomDisplay(index) }, sliderMouseup(e, index) { const i = this.viewportInfos.findIndex(i => i.index === index) @@ -781,6 +891,7 @@ export default { this.setToolsPassive() viewport.setImageIdIndex(sliceIdx) viewport.render() + this.updateZoomDisplay(index) // } // this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx }) }, @@ -983,7 +1094,7 @@ export default { top: 5px; color: #ddd; z-index: 1; - font-size: 12px; + font-size: 14px; .cd-info { color: #ddd; @@ -997,6 +1108,15 @@ export default { } } + .left-bottom-text { + position: absolute; + left: 5px; + bottom: 5px; + color: #ddd; + z-index: 1; + font-size: 14px; + } + .top-center-tool { position: absolute; left: 50%; diff --git a/src/views/none-dicoms/components/study-list.vue b/src/views/none-dicoms/components/study-list.vue index 52fa8531..faa24706 100644 --- a/src/views/none-dicoms/components/study-list.vue +++ b/src/views/none-dicoms/components/study-list.vue @@ -407,6 +407,9 @@ export default { color: #ccc; font-size: 12px; } + ::v-deep .el-switch__label { + color: #ccc; + } .file-list-container { width: 100%;