From 73e8f24c3d7b382a005b92df3148e1ad2c32f5fc Mon Sep 17 00:00:00 2001
From: caiyiling <1321909229@qq.com>
Date: Wed, 29 Apr 2026 11:48:21 +0800
Subject: [PATCH 01/15] =?UTF-8?q?=E9=98=85=E7=89=87=E9=A1=B5=E9=9D=A2?=
=?UTF-8?q?=E5=9B=BE=E6=A0=87=E6=9B=B4=E6=94=B9=EF=BC=9B=E9=80=82=E5=BA=94?=
=?UTF-8?q?=E5=9B=BE=E5=83=8F=E9=80=BB=E8=BE=91=E6=9B=B4=E6=94=B9=EF=BC=9B?=
=?UTF-8?q?petct=E5=B7=A5=E5=85=B7=E6=9B=B4=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/icons/svg/fitToImage.svg | 2 +-
src/icons/svg/rotateHorizontal.svg | 1 +
src/icons/svg/rotateTurnLeft.svg | 1 +
src/icons/svg/rotateTurnRight.svg | 1 +
src/icons/svg/rotateVertical.svg | 1 +
.../dicoms/components/Fusion/PetCt.vue | 103 ++++++++++++++++--
.../dicoms3D/components/MPRViewport.vue | 35 ++++--
.../dicoms3D/components/PetCtViewport.vue | 38 ++++++-
.../reading/dicoms3D/components/ReadPage.vue | 13 ++-
.../reading/dicoms3D/components/Viewport.vue | 32 +++++-
.../dicoms3D/components/VolumeViewport.vue | 34 ++++--
11 files changed, 220 insertions(+), 41 deletions(-)
create mode 100644 src/icons/svg/rotateHorizontal.svg
create mode 100644 src/icons/svg/rotateTurnLeft.svg
create mode 100644 src/icons/svg/rotateTurnRight.svg
create mode 100644 src/icons/svg/rotateVertical.svg
diff --git a/src/icons/svg/fitToImage.svg b/src/icons/svg/fitToImage.svg
index 3bf71f3e..a5703249 100644
--- a/src/icons/svg/fitToImage.svg
+++ b/src/icons/svg/fitToImage.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/icons/svg/rotateHorizontal.svg b/src/icons/svg/rotateHorizontal.svg
new file mode 100644
index 00000000..59afcb0b
--- /dev/null
+++ b/src/icons/svg/rotateHorizontal.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/rotateTurnLeft.svg b/src/icons/svg/rotateTurnLeft.svg
new file mode 100644
index 00000000..f14d65da
--- /dev/null
+++ b/src/icons/svg/rotateTurnLeft.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/rotateTurnRight.svg b/src/icons/svg/rotateTurnRight.svg
new file mode 100644
index 00000000..410b26ef
--- /dev/null
+++ b/src/icons/svg/rotateTurnRight.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/rotateVertical.svg b/src/icons/svg/rotateVertical.svg
new file mode 100644
index 00000000..a02e3b6a
--- /dev/null
+++ b/src/icons/svg/rotateVertical.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue
index a0fdf9e8..22010f45 100644
--- a/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue
+++ b/src/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt.vue
@@ -259,6 +259,7 @@ import CustomWwwcForm from './../CustomWwwcForm'
import FusionForm from './FusionForm.vue'
import { getTableAnswerRowInfoList, getDicomSeriesInfo } from '@/api/trials'
import FusionEvent from './FusionEvent'
+import FusionJumpToPointTool from '../../../dicoms3D/components/tools/FusionJumpToPointTool'
// import { ColorMaps } from '@kitware/vtk.js/Common/Core/ColorMaps'
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction'
@@ -282,7 +283,6 @@ const {
// StackScrollMouseWheelTool,
StackScrollTool,
synchronizers,
- MIPJumpToClickTool,
// VolumeRotateMouseWheelTool,
VolumeRotateTool,
OrientationMarkerTool,
@@ -425,7 +425,12 @@ export default {
fusion: { visible: false }, // 历史记录融合调窗
screenshotWindow: null,
hasVoiChanged: false,
- lastUpper: null
+ lastUpper: null,
+ fusionCrosshairStyle: {
+ lineWidth: 2,
+ lineLength: 20,
+ centerHoleSize: 20,
+ }
// initFirstAnnotation:false
}
},
@@ -623,6 +628,7 @@ export default {
this.setUpToolGroups()
this.setUpSynchronizers()
+ this.dispatchFusionCenterPoint()
// this.$refs['CT_AXIAL'].scroll(0)
// this.$refs['PT_AXIAL'].scroll(0)
// this.$refs['FUSION_AXIAL'].scroll(0)
@@ -974,7 +980,7 @@ export default {
cornerstoneTools.addTool(WindowLevelTool)
cornerstoneTools.addTool(ZoomTool)
cornerstoneTools.addTool(StackScrollTool)
- cornerstoneTools.addTool(MIPJumpToClickTool)
+ cornerstoneTools.addTool(FusionJumpToPointTool)
cornerstoneTools.addTool(VolumeRotateTool)
cornerstoneTools.addTool(EllipticalROITool)
cornerstoneTools.addTool(CircleROITool)
@@ -1006,6 +1012,7 @@ export default {
toolGroup.addTool(ProbeTool.toolName)
toolGroup.addTool(ScaleOverlayTool.toolName)
toolGroup.addTool(OrientationMarkerTool.toolName)
+ toolGroup.addTool(FusionJumpToPointTool.toolName, this.getFusionJumpToolConfiguration())
})
fusionToolGroup.addTool(PanTool.toolName)
@@ -1021,6 +1028,7 @@ export default {
fusionToolGroup.addTool(ProbeTool.toolName)
fusionToolGroup.addTool(ScaleOverlayTool.toolName)
fusionToolGroup.addTool(OrientationMarkerTool.toolName)
+ fusionToolGroup.addTool(FusionJumpToPointTool.toolName, this.getFusionJumpToolConfiguration())
// Here is the difference in the toolGroups used, that we need to specify the
// volume to use for the WindowLevelTool for the fusion viewports
@@ -1072,6 +1080,13 @@ export default {
true // overwrite
)
toolGroup.setToolEnabled(ScaleOverlayTool.toolName)
+ toolGroup.setToolActive(FusionJumpToPointTool.toolName, {
+ bindings: [
+ {
+ mouseButton: MouseBindings.Primary // Left Click
+ }
+ ]
+ })
// toolGroup.setToolConfiguration(OrientationMarkerTool.toolName, {
// orientationWidget: {
// enabled: true,
@@ -1123,14 +1138,11 @@ export default {
mipToolGroup.setToolActive(VolumeRotateTool.toolName, {
bindings: [{ mouseButton: MouseBindings.Wheel }],
});
- mipToolGroup.addTool('MIPJumpToClickTool', {
- //
- toolGroupId: ptToolGroupId
- })
+ mipToolGroup.addTool(FusionJumpToPointTool.toolName, this.getFusionJumpToolConfiguration())
// Set the initial state of the tools, here we set one tool active on left click.
// This means left click will draw that tool.
- mipToolGroup.setToolActive('MIPJumpToClickTool', {
+ mipToolGroup.setToolActive(FusionJumpToPointTool.toolName, {
bindings: [
{
mouseButton: MouseBindings.Primary // Left ClickR
@@ -1144,6 +1156,81 @@ export default {
// mipToolGroup.setToolActive(OrientationMarkerTool.toolName)
mipToolGroup.addViewport(viewportIds.PETMIP.CORONAL, renderingEngineId)
},
+ getFusionJumpToolConfiguration() {
+ return {
+ targetViewportIds: [
+ viewportIds.CT.AXIAL,
+ viewportIds.PT.AXIAL,
+ viewportIds.FUSION.AXIAL,
+ viewportIds.PETMIP.CORONAL
+ ],
+ useBrightestPoint: true,
+ jumpToTargetViewports: true,
+ dispatchEventName: 'fusion-mip-point-selected',
+ getReferenceLineColor: this.setFusionCrosshairsToolLineColor,
+ style: this.fusionCrosshairStyle,
+ referenceLinesCenterGapRadius: this.fusionCrosshairStyle.centerHoleSize,
+ minimal: {
+ enabled: true,
+ lineLengthInPx: this.fusionCrosshairStyle.lineLength,
+ },
+ mipViewportIds: [viewportIds.PETMIP.CORONAL]
+ }
+ },
+ setFusionCrosshairsToolLineColor(viewportId) {
+ const colors = {
+ [viewportIds.CT.AXIAL]: '#0000ff',
+ [viewportIds.PT.AXIAL]: '#0000ff',
+ [viewportIds.FUSION.AXIAL]: '#0000ff',
+ [viewportIds.PETMIP.CORONAL]: '#ff0000'
+ }
+ return colors[viewportId] || '#0000ff'
+ },
+ dispatchFusionCenterPoint(retryCount = 0) {
+ const renderEngine = getRenderingEngine(renderingEngineId)
+ if (!renderEngine) return
+ const toolGroupCandidates = [fusionToolGroupId, mipToolGroupUID, ptToolGroupId, ctToolGroupId]
+ let instance = null
+ for (const toolGroupId of toolGroupCandidates) {
+ const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
+ instance = toolGroup?.getToolInstance?.(FusionJumpToPointTool.toolName)
+ if (instance?.setPoint) break
+ }
+ if (!instance?.setPoint) {
+ if (retryCount < 10) {
+ setTimeout(() => {
+ this.dispatchFusionCenterPoint(retryCount + 1)
+ }, 120)
+ }
+ return
+ }
+
+ const candidates = [viewportIds.FUSION.AXIAL, viewportIds.PT.AXIAL, viewportIds.CT.AXIAL]
+ for (const viewportId of candidates) {
+ const viewport = renderEngine.getViewport(viewportId)
+ if (!viewport) continue
+ const width = viewport.element?.clientWidth
+ const height = viewport.element?.clientHeight
+ let worldPoint = null
+ if (width && height && viewport.canvasToWorld) {
+ worldPoint = viewport.canvasToWorld([width / 2, height / 2])
+ }
+ if ((!worldPoint || worldPoint.length < 3) && viewport.getCamera) {
+ worldPoint = viewport.getCamera()?.focalPoint
+ }
+ if (!worldPoint || worldPoint.length < 3) continue
+ instance.setPoint(worldPoint, viewportId, renderEngine.id, {
+ jumpToTargetViewports: true,
+ dispatchEvent: false,
+ })
+ return
+ }
+ if (retryCount < 10) {
+ setTimeout(() => {
+ this.dispatchFusionCenterPoint(retryCount + 1)
+ }, 120)
+ }
+ },
getTextLines(data, targetId) {
const cachedVolumeStats = data.cachedStats[targetId]
const {
diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/MPRViewport.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/MPRViewport.vue
index 242f58c0..de837d4f 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/MPRViewport.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/MPRViewport.vue
@@ -561,16 +561,37 @@ export default {
viewport.render()
},
resize(forceFitToWindow) {
- console.log('resize: ', forceFitToWindow)
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
- if (!forceFitToWindow) {
- viewport.setZoom(0.5)
- viewport.render()
- } else {
- viewport.setZoom(1)
+ if (!viewport) return
+
+ if (forceFitToWindow) {
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
viewport.render()
+ return
}
+
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
+ const canvas = viewport.getCanvas() || this.element.querySelector('canvas')
+ 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) {
+ // zoom=1 通常是 fit-to-window,这里换算为图像接近 1:1 像素显示
+ viewport.setZoom(1 / fitScale)
+ }
+
+ viewport.render()
},
voiChange(v) {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
@@ -1024,4 +1045,4 @@ export default {
cursor: move
}
}
-
\ No newline at end of file
+
diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue
index 2ea372c7..a4aa5c11 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/PetCtViewport.vue
@@ -415,16 +415,42 @@ export default {
viewport.render()
},
resize(forceFitToWindow) {
- console.log('resize: ', forceFitToWindow)
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
- if (!forceFitToWindow) {
- viewport.setZoom(0.5)
- viewport.render()
- } else {
- viewport.setZoom(1)
+ if (!viewport) return
+
+ if (this.isMip) {
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
viewport.render()
+ return
}
+
+ if (forceFitToWindow) {
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
+ viewport.render()
+ return
+ }
+
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
+ const canvas = viewport.getCanvas() || this.element.querySelector('canvas')
+ 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()
},
voiChange(v) {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
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 7c79d450..a86af6f4 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
@@ -143,9 +143,10 @@
-
+
-
+
{{ rotate.label }}
@@ -707,11 +708,11 @@ export default {
criterionType: null,
tools: [],
rotateOptions: [
- { label: this.$t('trials:reading:button:rotateDefault'), val: 1 },
- { label: this.$t('trials:reading:button:rotateVertical'), val: 2 },
- { label: this.$t('trials:reading:button:rotateHorizontal'), val: 3 },
- { label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4 },
- { label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 }
+ { label: this.$t('trials:reading:button:rotateDefault'), val: 1, icon: ''},
+ { label: this.$t('trials:reading:button:rotateVertical'), val: 2, icon: 'rotateVertical' },
+ { label: this.$t('trials:reading:button:rotateHorizontal'), val: 3, icon: 'rotateHorizontal' },
+ { label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4, icon: 'rotateTurnLeft' },
+ { label: this.$t('trials:reading:button:rotateTurnRight'), val: 5, icon: 'rotateTurnRight' }
],
defaultWwwc: [
{ label: this.$t('trials:reading:button:wwwcDefault'), val: -1, ww: null, wc: null }, // 默认值
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 549618a5..8406df9c 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/Viewport.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Viewport.vue
@@ -343,16 +343,36 @@ export default {
viewport.render()
},
resize(forceFitToWindow) {
- console.log('resize: ', forceFitToWindow)
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
- if (!forceFitToWindow) {
- viewport.setZoom(0.5)
- viewport.render()
- } else {
- viewport.setZoom(1)
+ if (!viewport) return
+
+ if (forceFitToWindow) {
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
viewport.render()
+ return
}
+
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
+ const canvas = viewport.getCanvas() || this.element.querySelector('canvas')
+ 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()
},
async prefetchMetadataInformation(imageIdsToPrefetch, modality) {
let taskPromises = []
diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/VolumeViewport.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/VolumeViewport.vue
index 1f2e2ce5..dafc304c 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/VolumeViewport.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/VolumeViewport.vue
@@ -592,16 +592,36 @@ export default {
viewport.render()
},
resize(forceFitToWindow) {
- console.log('resize: ', forceFitToWindow)
const renderingEngine = getRenderingEngine(this.renderingEngineId)
const viewport = renderingEngine.getViewport(this.viewportId)
- if (!forceFitToWindow) {
- viewport.setZoom(0.5)
- viewport.render()
- } else {
- viewport.setZoom(1)
+ if (!viewport) return
+
+ if (forceFitToWindow) {
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
viewport.render()
+ return
}
+
+ viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
+ const canvas = viewport.getCanvas() || this.element.querySelector('canvas')
+ 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()
},
voiChange(v) {
const renderingEngine = getRenderingEngine(this.renderingEngineId)
@@ -1058,4 +1078,4 @@ export default {
cursor: move
}
}
-
\ No newline at end of file
+
From c373b59f230f562e217a20525c2515d858b3fc79 Mon Sep 17 00:00:00 2001
From: caiyiling <1321909229@qq.com>
Date: Wed, 29 Apr 2026 12:41:00 +0800
Subject: [PATCH 02/15] =?UTF-8?q?=E8=B4=A8=E6=8E=A7=E9=80=9A=E8=BF=87?=
=?UTF-8?q?=E6=97=B6pt=E4=B8=B4=E5=BA=8A=E6=95=B0=E6=8D=AE=E5=8F=AF?=
=?UTF-8?q?=E5=86=8D=E6=AC=A1=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/trials.js | 9 +++++
.../components/uploadPetClinicalData.vue | 36 +++++++++++++++----
.../qc-check/components/qualityAssurance.vue | 4 +--
3 files changed, 40 insertions(+), 9 deletions(-)
diff --git a/src/api/trials.js b/src/api/trials.js
index 2e79d92f..bd16e812 100644
--- a/src/api/trials.js
+++ b/src/api/trials.js
@@ -4448,4 +4448,13 @@ export function editPatientInfo(data) {
method: 'post',
data
})
+}
+
+//修正患者基本信息
+export function amendmentPatientInfo(data) {
+ return request({
+ url: `/Study/amendmentPatientInfo`,
+ method: 'post',
+ data
+ })
}
\ No newline at end of file
diff --git a/src/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue b/src/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue
index d3ed41c5..d6da6e43 100644
--- a/src/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue
+++ b/src/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue
@@ -307,7 +307,14 @@
style="width: 100%"
>
-
+
+
+
{{ $t('trials:ptData:button:submit') }}
@@ -362,7 +369,8 @@ import {
getCRCClinicalData,
addOrUpdateReadingClinicalData,
getPatientInfo,
- editPatientInfo
+ editPatientInfo,
+ amendmentPatientInfo
} from '@/api/trials'
import PreviousRadiotherapy from './previousRadiotherapy'
import PreviousSurgery from './previousSurgery'
@@ -410,6 +418,10 @@ export default {
isPatientFormAllowEdit: {
type: Boolean,
default: false,
+ },
+ isAudit: {
+ type: Boolean,
+ default: false
}
},
data() {
@@ -443,7 +455,8 @@ export default {
RadionuclideHalfLife: null,
RadiopharmaceuticalStartTime: null,
AcquisitionTime: null,
- TimeCheck: ''
+ TimeCheck: '',
+ Reason: ''
},
rules: {
PatientSex: [
@@ -470,7 +483,10 @@ export default {
{ type: 'number', message: this.$t('trials:ptData:ruleMessage:number2'), trigger: 'blur' },//请输入数字
// 自定义校验:确保成像时间不早于注射时间
{ validator: this.validateTime, trigger: 'blur' }
- ]
+ ],
+ Reason: [
+ { required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }
+ ],
},
formLoading: false,
isPatientFormCanEdit: false
@@ -814,7 +830,8 @@ export default {
RadionuclideHalfLife: parseFloat(res.Result.RadionuclideHalfLife) || null,
RadiopharmaceuticalStartTime: parseFloat(res.Result.RadiopharmaceuticalStartTime) || '',
AcquisitionTime: parseFloat(res.Result.AcquisitionTime) || '',
- TimeCheck: ''
+ TimeCheck: '',
+ Reason: res.Result.Reason
}
this.computeTimeRelation()
this.formLoading = false
@@ -829,9 +846,14 @@ export default {
let valid = await this.$refs.patientForm.validate()
if (!valid) return
this.formLoading = true
- let res = await editPatientInfo(this.formData)
+ let res = null
+ if (this.isAudit) {
+ res = await amendmentPatientInfo(this.formData)
+ } else {
+ res = await editPatientInfo(this.formData)
+ }
this.formLoading = false
- if (res.IsSuccess) {
+ if (res && res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
} catch(e) {
diff --git a/src/views/trials/trials-panel/visit/qc-check/components/qualityAssurance.vue b/src/views/trials/trials-panel/visit/qc-check/components/qualityAssurance.vue
index be5dce29..b8a6304a 100644
--- a/src/views/trials/trials-panel/visit/qc-check/components/qualityAssurance.vue
+++ b/src/views/trials/trials-panel/visit/qc-check/components/qualityAssurance.vue
@@ -158,7 +158,7 @@
:disabled="isAudit || scope.row.IsDeleted || SecondReviewState > 0"
@click="handleEditStudy(scope.row)" />
-
-
+
From 877e47ccb197faa30d4a8204b6de843adee8fadb Mon Sep 17 00:00:00 2001
From: caiyiling <1321909229@qq.com>
Date: Wed, 29 Apr 2026 13:30:42 +0800
Subject: [PATCH 03/15] =?UTF-8?q?=E9=98=85=E7=89=87=E8=A7=84=E5=88=99?=
=?UTF-8?q?=E5=8D=95=E4=BD=8D=E6=9B=B4=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../setting/reading-unit/components/ArbitrationRules.vue | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue
index ebbe1998..f6d50402 100644
--- a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue
+++ b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue
@@ -194,9 +194,9 @@
- {{
- $fd('ValueUnit', QuestionList[index].Unit)
- }}
+
+ {{ `${QuestionList[index].Unit === 4 ? QuestionList[index].CustomUnit : $fd('ValueUnit', QuestionList[index].Unit)}`}}
+
From 06f52f4f242a828d2c3456e250fdd51445b095b7 Mon Sep 17 00:00:00 2001
From: wangxiaoshuang <825034831@qq.com>
Date: Wed, 29 Apr 2026 13:42:16 +0800
Subject: [PATCH 04/15] =?UTF-8?q?=E5=88=86=E5=89=B2=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E4=B8=8D=E4=B8=80=E8=87=B4=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
src/api/reading.js | 8 ++++
.../reading/dicoms3D/components/ReadPage.vue | 40 +++++++++++++++--
.../dicoms3D/components/Segmentations.vue | 43 ++++++++++++++-----
.../components/helpers/segmentations.js | 2 +-
4 files changed, 79 insertions(+), 14 deletions(-)
diff --git a/src/api/reading.js b/src/api/reading.js
index 53cdedae..e686f326 100644
--- a/src/api/reading.js
+++ b/src/api/reading.js
@@ -408,6 +408,14 @@ export function changeSegmentationSavedStatus(data) {
data
})
}
+// 修改分割片段锁定状态
+export function lockOrUnLockSegment(data) {
+ return request({
+ url: `/Segmentation/lockOrUnLockSegment`,
+ method: 'post',
+ data
+ })
+}
// 图像数据匿名
export function studyMaskImage(data) {
return request({
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 7c79d450..50dcca3a 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue
@@ -1003,6 +1003,24 @@ export default {
this.getSystemInfoReading();
},
methods: {
+ changeScreenSave() {
+ return new Promise(async (reslove, reject) => {
+ if (this.$refs.Segmentations.readingTaskState < 2) {
+ let isSaved = this.$refs.Segmentations.segmentList.some(item => !item.isSaved)
+ if (isSaved) {
+ let confirm = await this.$confirm(this.$t("trials:reading:Segmentations:confirm:changeScreenSave"))
+ if (!confirm) reslove(true)
+ this.$refs.Segmentations.saveSegmentGroup(null, true, () => {
+ reslove(true)
+ })
+ } else {
+ reslove(true)
+ }
+ } else {
+ reslove(true)
+ }
+ })
+ },
resetHistogram() {
if (!this.histogramVisible) return false
if (this.timer['histogram']) {
@@ -3042,6 +3060,10 @@ export default {
},
// 更改视图布局
async changeLayout(v) {
+ if (this.readingTool === 3) {
+ let res = await this.changeScreenSave()
+ if (!res) return false
+ }
this.setToolsPassive()
this.fullScreenIndex = null
this.layout = v
@@ -3355,9 +3377,12 @@ export default {
}, time)
},
// 切换全屏
- toggleFullScreen(e, index) {
+ async toggleFullScreen(e, index) {
if (this.isDelay && (this.readingTool === 3 || this.isMPR)) return false
-
+ if (this.readingTool === 3) {
+ let res = await this.changeScreenSave()
+ if (!res) return false
+ }
this.fullScreenIndex = this.fullScreenIndex === index ? null : index
this.activeViewportIndex = index
if (this.readingTool === 3 || this.isMPR) {
@@ -3515,8 +3540,12 @@ export default {
this.setToolsPassive()
},
// 激活视口
- activeViewport(index) {
+ async activeViewport(index) {
if (this.activeViewportIndex === index) return
+ if (this.readingTool === 3) {
+ let res = await this.changeScreenSave()
+ if (!res) return false
+ }
this.activeViewportIndex = index
// 切换检查列表
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
@@ -4173,6 +4202,11 @@ export default {
if (!data) return resolve(false)
let viewportSeries = this.$refs[`viewport-MPR-0`][0].series
if (data && viewportSeries.SeriesInstanceUid === data.SeriesInstanceUid) return resolve(true)
+ } else {
+ if (this.readingTool === 3) {
+ let res = await this.changeScreenSave()
+ if (!res) return false
+ }
}
if (!data) {
let { imageOrientationPatient, imagePositionPatient } = this.$refs[`viewport-${this.activeViewportIndex}`][0].imageInfo
diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
index abc852fc..03bd9f6e 100644
--- a/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
+++ b/src/views/trials/trials-panel/reading/dicoms3D/components/Segmentations.vue
@@ -133,8 +133,8 @@
-
+
{{ $t('trials:reading:Segmentations:button:addSegmentGroup') }}
@@ -151,6 +151,7 @@
+
-
{{ $t("trials:reading:Segmentations:button:save") }}
@@ -225,7 +226,7 @@
+ @show="handleClickPopover(item)" v-if="readingTaskState < 2 && !isMPR">
{{ $t('trials:reading:Segmentations:button:renameSegmentGroup') }}
@@ -244,21 +245,22 @@
+
-
-
+
+
{{ $t("trials:reading:Segmentations:button:saveAll") }}