Merge branch 'main' into uat_us
commit
7dbade1527
|
|
@ -408,6 +408,14 @@ export function changeSegmentationSavedStatus(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 修改分割片段锁定状态
|
||||||
|
export function lockOrUnLockSegment(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Segmentation/lockOrUnLockSegment`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
// 图像数据匿名
|
// 图像数据匿名
|
||||||
export function studyMaskImage(data) {
|
export function studyMaskImage(data) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
||||||
|
|
@ -4448,4 +4448,13 @@ export function editPatientInfo(data) {
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//修正患者基本信息
|
||||||
|
export function amendmentPatientInfo(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Inspection/Study/amendmentPatientInfo`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1609205172733" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2919" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M320 640v256H256v-192H64v-64h256z m640 0v64h-192v192h-64v-256h256zM512 384a128 128 0 1 1 0 256 128 128 0 0 1 0-256zM320 128v256H64V320h192V128h64z m448 0v192h192v64h-256V128h64z" p-id="2920"></path></svg>
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777426164195" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5541" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M316 672h60c4.4 0 8-3.6 8-8V360c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v304c0 4.4 3.6 8 8 8zM512 622c22.1 0 40-17.9 40-39 0-23.1-17.9-41-40-41s-40 17.9-40 41c0 21.1 17.9 39 40 39zM512 482c22.1 0 40-17.9 40-39 0-23.1-17.9-41-40-41s-40 17.9-40 41c0 21.1 17.9 39 40 39z" p-id="5542"></path><path d="M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32z m-40 728H184V184h656v656z" p-id="5543"></path><path d="M648 672h60c4.4 0 8-3.6 8-8V360c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v304c0 4.4 3.6 8 8 8z" p-id="5544"></path></svg>
|
||||||
|
Before Width: | Height: | Size: 581 B After Width: | Height: | Size: 908 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777432778355" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2607" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M954.026667 913.6128H600.746667a35.908267 35.908267 0 0 1-35.771734-35.771733V116.736a35.703467 35.703467 0 0 1 68.266667-15.018667l353.143467 761.0368a35.566933 35.566933 0 0 1-2.2528 34.269867 35.362133 35.362133 0 0 1-30.173867 16.5888z" fill="#FFFFFF" p-id="2608"></path><path d="M465.373867 913.544533H112.162133a35.6352 35.6352 0 0 1-32.494933-50.722133L432.878933 101.717333a35.6352 35.6352 0 0 1 40.277334-19.8656 35.566933 35.566933 0 0 1 27.989333 34.952534V877.909333a35.771733 35.771733 0 0 1-35.771733 35.6352z" fill="#FFFFFF" fill-opacity=".4" p-id="2609"></path></svg>
|
||||||
|
After Width: | Height: | Size: 916 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777426622063" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="8288" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M667.69962 294.974152l0 589.688383 316.384787 0L667.69962 294.974152zM632.522446 884.662535 632.522446 572.426231 34.882973 884.662535 632.522446 884.662535zM510.16777 357.862457l-137.677663-31.323403c0 0 97.523127-217.392192 349.512279-98.842169 0 0-196.516746-248.618381-487.190965 67.571978l-137.677663-31.273261 158.803819 250.082732L510.16777 357.862457z" p-id="8289"></path></svg>
|
||||||
|
After Width: | Height: | Size: 719 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777426691300" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2490" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M34.884 883.64h316.385V293.95L34.884 883.64z m949.201 0L386.446 571.402v312.236h597.64zM763.03 513.053l158.805-250.083-137.678 31.274c-290.674-316.19-487.191-67.572-487.191-67.572 251.99-118.55 349.512 98.842 349.512 98.842l-137.677 31.323L763.03 513.054z" fill="" p-id="2491"></path></svg>
|
||||||
|
After Width: | Height: | Size: 623 B |
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1777432945307" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4263" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M106.496 928.426667V575.2832c0-19.729067 16.042667-35.771733 35.771733-35.771733h761.0368a35.703467 35.703467 0 0 1 15.086934 68.266666L157.354667 960.9216a35.566933 35.566933 0 0 1-34.269867-2.321067 35.362133 35.362133 0 0 1-16.5888-30.173866z" fill="#FFFFFF" p-id="4264"></path><path d="M106.496 439.842133V86.6304a35.6352 35.6352 0 0 1 50.7904-32.494933l761.0368 353.211733a35.6352 35.6352 0 0 1 19.933867 40.209067 35.566933 35.566933 0 0 1-34.952534 27.989333H142.199467a35.771733 35.771733 0 0 1-35.703467-35.703467z" fill="#FFFFFF" fill-opacity=".4" p-id="4265"></path></svg>
|
||||||
|
After Width: | Height: | Size: 916 B |
|
|
@ -259,6 +259,7 @@ import CustomWwwcForm from './../CustomWwwcForm'
|
||||||
import FusionForm from './FusionForm.vue'
|
import FusionForm from './FusionForm.vue'
|
||||||
import { getTableAnswerRowInfoList, getDicomSeriesInfo } from '@/api/trials'
|
import { getTableAnswerRowInfoList, getDicomSeriesInfo } from '@/api/trials'
|
||||||
import FusionEvent from './FusionEvent'
|
import FusionEvent from './FusionEvent'
|
||||||
|
import FusionJumpToPointTool from '../../../dicoms3D/components/tools/FusionJumpToPointTool'
|
||||||
// import { ColorMaps } from '@kitware/vtk.js/Common/Core/ColorMaps'
|
// import { ColorMaps } from '@kitware/vtk.js/Common/Core/ColorMaps'
|
||||||
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
|
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
|
||||||
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction'
|
import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction'
|
||||||
|
|
@ -282,7 +283,6 @@ const {
|
||||||
// StackScrollMouseWheelTool,
|
// StackScrollMouseWheelTool,
|
||||||
StackScrollTool,
|
StackScrollTool,
|
||||||
synchronizers,
|
synchronizers,
|
||||||
MIPJumpToClickTool,
|
|
||||||
// VolumeRotateMouseWheelTool,
|
// VolumeRotateMouseWheelTool,
|
||||||
VolumeRotateTool,
|
VolumeRotateTool,
|
||||||
OrientationMarkerTool,
|
OrientationMarkerTool,
|
||||||
|
|
@ -425,7 +425,12 @@ export default {
|
||||||
fusion: { visible: false }, // 历史记录融合调窗
|
fusion: { visible: false }, // 历史记录融合调窗
|
||||||
screenshotWindow: null,
|
screenshotWindow: null,
|
||||||
hasVoiChanged: false,
|
hasVoiChanged: false,
|
||||||
lastUpper: null
|
lastUpper: null,
|
||||||
|
fusionCrosshairStyle: {
|
||||||
|
lineWidth: 2,
|
||||||
|
lineLength: 20,
|
||||||
|
centerHoleSize: 20,
|
||||||
|
}
|
||||||
// initFirstAnnotation:false
|
// initFirstAnnotation:false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -623,6 +628,7 @@ export default {
|
||||||
this.setUpToolGroups()
|
this.setUpToolGroups()
|
||||||
|
|
||||||
this.setUpSynchronizers()
|
this.setUpSynchronizers()
|
||||||
|
this.dispatchFusionCenterPoint()
|
||||||
// this.$refs['CT_AXIAL'].scroll(0)
|
// this.$refs['CT_AXIAL'].scroll(0)
|
||||||
// this.$refs['PT_AXIAL'].scroll(0)
|
// this.$refs['PT_AXIAL'].scroll(0)
|
||||||
// this.$refs['FUSION_AXIAL'].scroll(0)
|
// this.$refs['FUSION_AXIAL'].scroll(0)
|
||||||
|
|
@ -974,7 +980,7 @@ export default {
|
||||||
cornerstoneTools.addTool(WindowLevelTool)
|
cornerstoneTools.addTool(WindowLevelTool)
|
||||||
cornerstoneTools.addTool(ZoomTool)
|
cornerstoneTools.addTool(ZoomTool)
|
||||||
cornerstoneTools.addTool(StackScrollTool)
|
cornerstoneTools.addTool(StackScrollTool)
|
||||||
cornerstoneTools.addTool(MIPJumpToClickTool)
|
cornerstoneTools.addTool(FusionJumpToPointTool)
|
||||||
cornerstoneTools.addTool(VolumeRotateTool)
|
cornerstoneTools.addTool(VolumeRotateTool)
|
||||||
cornerstoneTools.addTool(EllipticalROITool)
|
cornerstoneTools.addTool(EllipticalROITool)
|
||||||
cornerstoneTools.addTool(CircleROITool)
|
cornerstoneTools.addTool(CircleROITool)
|
||||||
|
|
@ -1006,6 +1012,7 @@ export default {
|
||||||
toolGroup.addTool(ProbeTool.toolName)
|
toolGroup.addTool(ProbeTool.toolName)
|
||||||
toolGroup.addTool(ScaleOverlayTool.toolName)
|
toolGroup.addTool(ScaleOverlayTool.toolName)
|
||||||
toolGroup.addTool(OrientationMarkerTool.toolName)
|
toolGroup.addTool(OrientationMarkerTool.toolName)
|
||||||
|
toolGroup.addTool(FusionJumpToPointTool.toolName, this.getFusionJumpToolConfiguration())
|
||||||
})
|
})
|
||||||
|
|
||||||
fusionToolGroup.addTool(PanTool.toolName)
|
fusionToolGroup.addTool(PanTool.toolName)
|
||||||
|
|
@ -1021,6 +1028,7 @@ export default {
|
||||||
fusionToolGroup.addTool(ProbeTool.toolName)
|
fusionToolGroup.addTool(ProbeTool.toolName)
|
||||||
fusionToolGroup.addTool(ScaleOverlayTool.toolName)
|
fusionToolGroup.addTool(ScaleOverlayTool.toolName)
|
||||||
fusionToolGroup.addTool(OrientationMarkerTool.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
|
// Here is the difference in the toolGroups used, that we need to specify the
|
||||||
// volume to use for the WindowLevelTool for the fusion viewports
|
// volume to use for the WindowLevelTool for the fusion viewports
|
||||||
|
|
||||||
|
|
@ -1072,6 +1080,13 @@ export default {
|
||||||
true // overwrite
|
true // overwrite
|
||||||
)
|
)
|
||||||
toolGroup.setToolEnabled(ScaleOverlayTool.toolName)
|
toolGroup.setToolEnabled(ScaleOverlayTool.toolName)
|
||||||
|
toolGroup.setToolActive(FusionJumpToPointTool.toolName, {
|
||||||
|
bindings: [
|
||||||
|
{
|
||||||
|
mouseButton: MouseBindings.Primary // Left Click
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
// toolGroup.setToolConfiguration(OrientationMarkerTool.toolName, {
|
// toolGroup.setToolConfiguration(OrientationMarkerTool.toolName, {
|
||||||
// orientationWidget: {
|
// orientationWidget: {
|
||||||
// enabled: true,
|
// enabled: true,
|
||||||
|
|
@ -1123,14 +1138,11 @@ export default {
|
||||||
mipToolGroup.setToolActive(VolumeRotateTool.toolName, {
|
mipToolGroup.setToolActive(VolumeRotateTool.toolName, {
|
||||||
bindings: [{ mouseButton: MouseBindings.Wheel }],
|
bindings: [{ mouseButton: MouseBindings.Wheel }],
|
||||||
});
|
});
|
||||||
mipToolGroup.addTool('MIPJumpToClickTool', {
|
mipToolGroup.addTool(FusionJumpToPointTool.toolName, this.getFusionJumpToolConfiguration())
|
||||||
//
|
|
||||||
toolGroupId: ptToolGroupId
|
|
||||||
})
|
|
||||||
|
|
||||||
// Set the initial state of the tools, here we set one tool active on left click.
|
// Set the initial state of the tools, here we set one tool active on left click.
|
||||||
// This means left click will draw that tool.
|
// This means left click will draw that tool.
|
||||||
mipToolGroup.setToolActive('MIPJumpToClickTool', {
|
mipToolGroup.setToolActive(FusionJumpToPointTool.toolName, {
|
||||||
bindings: [
|
bindings: [
|
||||||
{
|
{
|
||||||
mouseButton: MouseBindings.Primary // Left ClickR
|
mouseButton: MouseBindings.Primary // Left ClickR
|
||||||
|
|
@ -1144,6 +1156,81 @@ export default {
|
||||||
// mipToolGroup.setToolActive(OrientationMarkerTool.toolName)
|
// mipToolGroup.setToolActive(OrientationMarkerTool.toolName)
|
||||||
mipToolGroup.addViewport(viewportIds.PETMIP.CORONAL, renderingEngineId)
|
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) {
|
getTextLines(data, targetId) {
|
||||||
const cachedVolumeStats = data.cachedStats[targetId]
|
const cachedVolumeStats = data.cachedStats[targetId]
|
||||||
const {
|
const {
|
||||||
|
|
|
||||||
|
|
@ -41,10 +41,10 @@
|
||||||
<div v-if="series" class="right-bottom-text">
|
<div v-if="series" class="right-bottom-text">
|
||||||
<div v-show="imageInfo.location">Location: {{
|
<div v-show="imageInfo.location">Location: {{
|
||||||
`${Number(imageInfo.location).toFixed(digitPlaces)} mm`
|
`${Number(imageInfo.location).toFixed(digitPlaces)} mm`
|
||||||
}}</div>
|
}}</div>
|
||||||
<div v-show="imageInfo.sliceThickness">Slice Thickness: {{
|
<div v-show="imageInfo.sliceThickness">Slice Thickness: {{
|
||||||
`${Number(imageInfo.sliceThickness).toFixed(digitPlaces)} mm`
|
`${Number(imageInfo.sliceThickness).toFixed(digitPlaces)} mm`
|
||||||
}}</div>
|
}}</div>
|
||||||
<div v-show="imageInfo.wwwc">WW/WL: {{ imageInfo.wwwc }}</div>
|
<div v-show="imageInfo.wwwc">WW/WL: {{ imageInfo.wwwc }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="orientation-top">
|
<div class="orientation-top">
|
||||||
|
|
@ -228,7 +228,7 @@ export default {
|
||||||
DicomEvent.$on('renderSegmentation', async (viewportId) => {
|
DicomEvent.$on('renderSegmentation', async (viewportId) => {
|
||||||
// if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
// if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
if (this.viewportId !== viewportId) return false
|
if (this.viewportId !== viewportId) return false
|
||||||
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration)
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration, this.segmentationId, this.segmentIndex)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -561,16 +561,37 @@ export default {
|
||||||
viewport.render()
|
viewport.render()
|
||||||
},
|
},
|
||||||
resize(forceFitToWindow) {
|
resize(forceFitToWindow) {
|
||||||
console.log('resize: ', forceFitToWindow)
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
if (!forceFitToWindow) {
|
if (!viewport) return
|
||||||
viewport.setZoom(0.5)
|
|
||||||
viewport.render()
|
if (forceFitToWindow) {
|
||||||
} else {
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
viewport.setZoom(1)
|
|
||||||
viewport.render()
|
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) {
|
voiChange(v) {
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
|
@ -644,7 +665,7 @@ export default {
|
||||||
renderingEngine.render()
|
renderingEngine.render()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration)
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration, this.segmentationId, this.segmentIndex)
|
||||||
DicomEvent.$emit('SegmentationLoading', this.viewportId)
|
DicomEvent.$emit('SegmentationLoading', this.viewportId)
|
||||||
let volume = cache.getVolume(this.volumeId)
|
let volume = cache.getVolume(this.volumeId)
|
||||||
// console.log(volume, 'volume')
|
// console.log(volume, 'volume')
|
||||||
|
|
@ -1024,4 +1045,4 @@ export default {
|
||||||
cursor: move
|
cursor: move
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -415,16 +415,42 @@ export default {
|
||||||
viewport.render()
|
viewport.render()
|
||||||
},
|
},
|
||||||
resize(forceFitToWindow) {
|
resize(forceFitToWindow) {
|
||||||
console.log('resize: ', forceFitToWindow)
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
if (!forceFitToWindow) {
|
if (!viewport) return
|
||||||
viewport.setZoom(0.5)
|
|
||||||
viewport.render()
|
if (this.isMip) {
|
||||||
} else {
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
viewport.setZoom(1)
|
|
||||||
viewport.render()
|
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) {
|
voiChange(v) {
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
|
|
||||||
|
|
@ -143,9 +143,10 @@
|
||||||
<i class="el-icon-arrow-down" style="color:#fff;" />
|
<i class="el-icon-arrow-down" style="color:#fff;" />
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown-content">
|
<div class="dropdown-content">
|
||||||
<ul style="width:100px;">
|
<ul style="width:110px;">
|
||||||
<li v-for="rotate in rotateOptions" :key="rotate.label" style="text-align:left;">
|
<li v-for="rotate in rotateOptions" :key="rotate.label" style="text-align:left;">
|
||||||
<span @click.prevent="setViewportRotate(rotate.val)">
|
<span @click.prevent="setViewportRotate(rotate.val)">
|
||||||
|
<svg-icon v-if="rotate.icon" :icon-class="rotate.icon" class="svg-icon" />
|
||||||
{{ rotate.label }}
|
{{ rotate.label }}
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -707,11 +708,11 @@ export default {
|
||||||
criterionType: null,
|
criterionType: null,
|
||||||
tools: [],
|
tools: [],
|
||||||
rotateOptions: [
|
rotateOptions: [
|
||||||
{ label: this.$t('trials:reading:button:rotateDefault'), val: 1 },
|
{ label: this.$t('trials:reading:button:rotateDefault'), val: 1, icon: '' },
|
||||||
{ label: this.$t('trials:reading:button:rotateVertical'), val: 2 },
|
{ label: this.$t('trials:reading:button:rotateVertical'), val: 2, icon: 'rotateVertical' },
|
||||||
{ label: this.$t('trials:reading:button:rotateHorizontal'), val: 3 },
|
{ label: this.$t('trials:reading:button:rotateHorizontal'), val: 3, icon: 'rotateHorizontal' },
|
||||||
{ label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4 },
|
{ label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4, icon: 'rotateTurnLeft' },
|
||||||
{ label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 }
|
{ label: this.$t('trials:reading:button:rotateTurnRight'), val: 5, icon: 'rotateTurnRight' }
|
||||||
],
|
],
|
||||||
defaultWwwc: [
|
defaultWwwc: [
|
||||||
{ label: this.$t('trials:reading:button:wwwcDefault'), val: -1, ww: null, wc: null }, // 默认值
|
{ label: this.$t('trials:reading:button:wwwcDefault'), val: -1, ww: null, wc: null }, // 默认值
|
||||||
|
|
@ -1003,6 +1004,26 @@ export default {
|
||||||
this.getSystemInfoReading();
|
this.getSystemInfoReading();
|
||||||
},
|
},
|
||||||
methods: {
|
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.loading = true
|
||||||
|
this.loadingText = this.$t("segment:loadingText:saveSegmentation")
|
||||||
|
this.$refs.Segmentations.checkSaveLoading(() => {
|
||||||
|
reslove(true)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
reslove(true)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reslove(true)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
resetHistogram() {
|
resetHistogram() {
|
||||||
if (!this.histogramVisible) return false
|
if (!this.histogramVisible) return false
|
||||||
if (this.timer['histogram']) {
|
if (this.timer['histogram']) {
|
||||||
|
|
@ -3042,16 +3063,21 @@ export default {
|
||||||
},
|
},
|
||||||
// 更改视图布局
|
// 更改视图布局
|
||||||
async changeLayout(v) {
|
async changeLayout(v) {
|
||||||
|
if (this.readingTool === 3) {
|
||||||
|
let res = await this.changeScreenSave()
|
||||||
|
if (!res) return false
|
||||||
|
}
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
this.fullScreenIndex = null
|
this.fullScreenIndex = null
|
||||||
this.layout = v
|
this.layout = v
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
let index = series.SliceIndex
|
let index = series.SliceIndex
|
||||||
const seriesArr = []
|
const seriesArr = []
|
||||||
|
let activeViewportIndex = 0
|
||||||
if (v === 1) {
|
if (v === 1) {
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
this.cols = 1
|
this.cols = 1
|
||||||
this.activeViewportIndex = 0
|
activeViewportIndex = 0
|
||||||
series.curIndex = index
|
series.curIndex = index
|
||||||
if (typeof series === 'object') {
|
if (typeof series === 'object') {
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
|
|
@ -3059,7 +3085,7 @@ export default {
|
||||||
} else if (v === 2) {
|
} else if (v === 2) {
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
this.cols = 2
|
this.cols = 2
|
||||||
this.activeViewportIndex = 1
|
activeViewportIndex = 1
|
||||||
series.curIndex = index
|
series.curIndex = index
|
||||||
if (typeof series === 'object') {
|
if (typeof series === 'object') {
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
|
|
@ -3106,7 +3132,7 @@ export default {
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.activeViewportIndex = 1
|
activeViewportIndex = 1
|
||||||
} else if (v === 4) {
|
} else if (v === 4) {
|
||||||
this.rows = 2
|
this.rows = 2
|
||||||
this.cols = 2
|
this.cols = 2
|
||||||
|
|
@ -3117,10 +3143,12 @@ export default {
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
}
|
}
|
||||||
this.activeViewportIndex = 3
|
activeViewportIndex = 3
|
||||||
}
|
}
|
||||||
seriesArr.map((i, index) => {
|
seriesArr.map(async (i, index) => {
|
||||||
this.$refs[`${this.viewportKey}-${index}`][0].setSeriesInfo(i)
|
await this.$refs[`${this.viewportKey}-${index}`][0].setSeriesInfo(i)
|
||||||
|
if (index === seriesArr.length - 1) this.activeViewportIndex = activeViewportIndex
|
||||||
|
|
||||||
})
|
})
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
|
@ -3355,9 +3383,12 @@ export default {
|
||||||
}, time)
|
}, time)
|
||||||
},
|
},
|
||||||
// 切换全屏
|
// 切换全屏
|
||||||
toggleFullScreen(e, index) {
|
async toggleFullScreen(e, index) {
|
||||||
if (this.isDelay && (this.readingTool === 3 || this.isMPR)) return false
|
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.fullScreenIndex = this.fullScreenIndex === index ? null : index
|
||||||
this.activeViewportIndex = index
|
this.activeViewportIndex = index
|
||||||
if (this.readingTool === 3 || this.isMPR) {
|
if (this.readingTool === 3 || this.isMPR) {
|
||||||
|
|
@ -3472,14 +3503,14 @@ export default {
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
this.cols = 1
|
this.cols = 1
|
||||||
this.activeViewportIndex = 0
|
|
||||||
this.fullScreenIndex = null
|
this.fullScreenIndex = null
|
||||||
this.isMPR = false
|
this.isMPR = false
|
||||||
obj.isChange = false
|
obj.isChange = false
|
||||||
return this.$nextTick(() => {
|
return this.$nextTick(() => {
|
||||||
DicomEvent.$emit('activeSeries', obj)
|
DicomEvent.$emit('activeSeries', obj)
|
||||||
DicomEvent.$emit('changeMPR')
|
DicomEvent.$emit('changeMPR')
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
this.$refs[`${this.viewportKey}-0`][0].setSeriesInfo(obj)
|
||||||
|
this.activeViewportIndex = 0
|
||||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
renderingEngine.resize(true, false)
|
renderingEngine.resize(true, false)
|
||||||
renderingEngine.render()
|
renderingEngine.render()
|
||||||
|
|
@ -3493,6 +3524,7 @@ export default {
|
||||||
if (!obj.IsDicom) {
|
if (!obj.IsDicom) {
|
||||||
return this.previewNoneDicoms(obj)
|
return this.previewNoneDicoms(obj)
|
||||||
}
|
}
|
||||||
|
this.activeViewportIndex = 0
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
||||||
this.clipPlaying = false
|
this.clipPlaying = false
|
||||||
this.fps = 15
|
this.fps = 15
|
||||||
|
|
@ -3515,8 +3547,12 @@ export default {
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
},
|
},
|
||||||
// 激活视口
|
// 激活视口
|
||||||
activeViewport(index) {
|
async activeViewport(index) {
|
||||||
if (this.activeViewportIndex === index) return
|
if (this.activeViewportIndex === index) return
|
||||||
|
if (this.readingTool === 3) {
|
||||||
|
let res = await this.changeScreenSave()
|
||||||
|
if (!res) return false
|
||||||
|
}
|
||||||
this.activeViewportIndex = index
|
this.activeViewportIndex = index
|
||||||
// 切换检查列表
|
// 切换检查列表
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
|
|
@ -4173,6 +4209,11 @@ export default {
|
||||||
if (!data) return resolve(false)
|
if (!data) return resolve(false)
|
||||||
let viewportSeries = this.$refs[`viewport-MPR-0`][0].series
|
let viewportSeries = this.$refs[`viewport-MPR-0`][0].series
|
||||||
if (data && viewportSeries.SeriesInstanceUid === data.SeriesInstanceUid) return resolve(true)
|
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) {
|
if (!data) {
|
||||||
let { imageOrientationPatient, imagePositionPatient } = this.$refs[`viewport-${this.activeViewportIndex}`][0].imageInfo
|
let { imageOrientationPatient, imagePositionPatient } = this.$refs[`viewport-${this.activeViewportIndex}`][0].imageInfo
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="Segmentations" v-loading="loading">
|
<div class="Segmentations" v-loading="loading">
|
||||||
<h3 style="color: #fff;margin: 0;padding: 15px 10px 5px">
|
<h3 style="color: #fff;margin: 0;padding: 15px 10px 5px" v-if="series.TaskInfo">
|
||||||
<span>{{ series.TaskInfo.SubjectCode }} </span>
|
<span>{{ series.TaskInfo.SubjectCode }} </span>
|
||||||
<span style="margin-left:5px;">{{ series.TaskInfo.TaskBlindName }}</span>
|
<span style="margin-left:5px;">{{ series.TaskInfo.TaskBlindName }}</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
@ -133,8 +133,8 @@
|
||||||
<template v-if="segmentList.length > 0">
|
<template v-if="segmentList.length > 0">
|
||||||
<div class="SegmentGroupBox">
|
<div class="SegmentGroupBox">
|
||||||
<div style="display: flex;align-items: center;">
|
<div style="display: flex;align-items: center;">
|
||||||
<el-popover placement="left" width="200px" trigger="click" v-if="readingTaskState < 2"
|
<el-popover placement="left" width="200px" trigger="click"
|
||||||
v-model="popoverVisible" :teleported="true">
|
v-if="readingTaskState < 2 && !isMPR" v-model="popoverVisible" :teleported="true">
|
||||||
<div class="SegmentGroupBtnBox">
|
<div class="SegmentGroupBtnBox">
|
||||||
<div class="SegmentGroupBtn" @click.stop="addSegmentGroup">
|
<div class="SegmentGroupBtn" @click.stop="addSegmentGroup">
|
||||||
{{ $t('trials:reading:Segmentations:button:addSegmentGroup') }}
|
{{ $t('trials:reading:Segmentations:button:addSegmentGroup') }}
|
||||||
|
|
@ -151,6 +151,7 @@
|
||||||
</div>
|
</div>
|
||||||
<i slot="reference" class="el-icon-more" style="cursor: pointer;color:#fff" />
|
<i slot="reference" class="el-icon-more" style="cursor: pointer;color:#fff" />
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
<i class="el-icon-more" style="cursor: not-allowed;color: #fff;" v-if="isMPR"></i>
|
||||||
<el-select v-model="segmentationId" placeholder="" @change="selectSegmentGroup()"
|
<el-select v-model="segmentationId" placeholder="" @change="selectSegmentGroup()"
|
||||||
:disabled="saveLoading">
|
:disabled="saveLoading">
|
||||||
<el-option v-for="item in segmentList" :key="`${item.segmentationId}`"
|
<el-option v-for="item in segmentList" :key="`${item.segmentationId}`"
|
||||||
|
|
@ -162,7 +163,7 @@
|
||||||
<i class="el-icon-warning-outline" style="color:red;margin-right: 5px;"
|
<i class="el-icon-warning-outline" style="color:red;margin-right: 5px;"
|
||||||
:title="$t('trials:reading:Segmentations:tip:segmentationIsNotSave')"
|
:title="$t('trials:reading:Segmentations:tip:segmentationIsNotSave')"
|
||||||
v-if="!curSegmentGroup.isSaved"></i>
|
v-if="!curSegmentGroup.isSaved"></i>
|
||||||
<el-button type="success" size="small" :disabled="saveLoading"
|
<el-button type="success" size="small" :disabled="saveLoading || isMPR"
|
||||||
@click="saveSegmentGroup([curSegmentGroup])">
|
@click="saveSegmentGroup([curSegmentGroup])">
|
||||||
{{ $t("trials:reading:Segmentations:button:save") }}
|
{{ $t("trials:reading:Segmentations:button:save") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
@ -225,7 +226,7 @@
|
||||||
<i class="el-icon-lock" v-if="item.lock" @click.stop="lockSegment(item, false)"></i>
|
<i class="el-icon-lock" v-if="item.lock" @click.stop="lockSegment(item, false)"></i>
|
||||||
<el-popover placement="bottom" width="40" trigger="click" class="docShow"
|
<el-popover placement="bottom" width="40" trigger="click" class="docShow"
|
||||||
:value="popoverId === `popover-${item.segmentationId}_${item.segmentIndex}`"
|
:value="popoverId === `popover-${item.segmentationId}_${item.segmentIndex}`"
|
||||||
@show="handleClickPopover(item)" v-if="readingTaskState < 2">
|
@show="handleClickPopover(item)" v-if="readingTaskState < 2 && !isMPR">
|
||||||
<div class="SegmentGroupBtnBox">
|
<div class="SegmentGroupBtnBox">
|
||||||
<div class="SegmentGroupBtn" @click.stop="rename('segment', item)">
|
<div class="SegmentGroupBtn" @click.stop="rename('segment', item)">
|
||||||
{{ $t('trials:reading:Segmentations:button:renameSegmentGroup') }}
|
{{ $t('trials:reading:Segmentations:button:renameSegmentGroup') }}
|
||||||
|
|
@ -244,21 +245,22 @@
|
||||||
</div>
|
</div>
|
||||||
<i slot="reference" class="el-icon-more" style="cursor: pointer;color:#fff" />
|
<i slot="reference" class="el-icon-more" style="cursor: pointer;color:#fff" />
|
||||||
</el-popover>
|
</el-popover>
|
||||||
|
<i class="el-icon-more" style="cursor: not-allowed;color: #fff;" v-if="isMPR"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
<div class="saveBtnBox" v-if="readingTaskState < 2">
|
<div class="saveBtnBox" v-if="readingTaskState < 2 && segmentList && segmentList.length > 1">
|
||||||
<el-button type="success" size="small" :disabled="saveLoading" @click="saveSegmentGroup()">
|
<el-button type="success" size="small" :disabled="saveLoading || isMPR" @click="saveSegmentGroup()">
|
||||||
{{ $t("trials:reading:Segmentations:button:saveAll") }}
|
{{ $t("trials:reading:Segmentations:button:saveAll") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { changeSegmentationSavedStatus, getSegmentationList, addOrUpdateSegmentation, deleteSegmentation, getSegmentList, addOrUpdateSegment, deleteSegment, getSegmentBindingList, saveSegmentBindingAndAnswer, getReadingTableQuestionTrialById, getReadingQuestionTrialById } from '@/api/reading'
|
import { changeSegmentationSavedStatus, getSegmentationList, addOrUpdateSegmentation, deleteSegmentation, getSegmentList, addOrUpdateSegment, deleteSegment, getSegmentBindingList, saveSegmentBindingAndAnswer, getReadingTableQuestionTrialById, getReadingQuestionTrialById, lockOrUnLockSegment } from '@/api/reading'
|
||||||
import * as cornerstoneTools from '@cornerstonejs/tools';
|
import * as cornerstoneTools from '@cornerstonejs/tools';
|
||||||
import * as cornerstone from "@cornerstonejs/core";
|
import * as cornerstone from "@cornerstonejs/core";
|
||||||
import dcmjs from '@/utils/dcmUpload/dcmjs'
|
import dcmjs from '@/utils/dcmUpload/dcmjs'
|
||||||
|
|
@ -400,7 +402,8 @@ export default {
|
||||||
isloaded: false,
|
isloaded: false,
|
||||||
popoverId: null,
|
popoverId: null,
|
||||||
saveLoading: false,
|
saveLoading: false,
|
||||||
popoverVisible: false
|
popoverVisible: false,
|
||||||
|
timer: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -418,7 +421,14 @@ export default {
|
||||||
if (this.isMPR) return false
|
if (this.isMPR) return false
|
||||||
if (Id === this.series.Id && TaskInfo.VisitTaskId === this.visitInfo.VisitTaskId) return false
|
if (Id === this.series.Id && TaskInfo.VisitTaskId === this.visitInfo.VisitTaskId) return false
|
||||||
this.series = series
|
this.series = series
|
||||||
this.$emit("update:curSegSeries", Object.assign(series, {}))
|
this.$emit("update:curSegSeries", Object.assign({}, series))
|
||||||
|
this.popoverId = null
|
||||||
|
this.segmentIndex = null
|
||||||
|
this.segmentationId = null
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
this.getSegmentationList()
|
this.getSegmentationList()
|
||||||
})
|
})
|
||||||
DicomEvent.$on('isloaded', (data) => {
|
DicomEvent.$on('isloaded', (data) => {
|
||||||
|
|
@ -691,9 +701,12 @@ export default {
|
||||||
},
|
},
|
||||||
lockSegment(item, lock) {
|
lockSegment(item, lock) {
|
||||||
if (this.readingTaskState >= 2) return false
|
if (this.readingTaskState >= 2) return false
|
||||||
|
if (this.isMPR) return false
|
||||||
|
this.$emit('setToolsPassive')
|
||||||
segmentation.segmentLocking.setSegmentIndexLocked(item.segmentationId, item.segmentIndex, lock)
|
segmentation.segmentLocking.setSegmentIndexLocked(item.segmentationId, item.segmentIndex, lock)
|
||||||
item.lock = lock
|
item.lock = lock
|
||||||
if (!lock) this.changeSegmentationSavedStatus(item.segmentationId, lock)
|
if (!lock) this.changeSegmentationSavedStatus(item.segmentationId, lock)
|
||||||
|
this.lockOrUnLockSegment(item.id, lock)
|
||||||
},
|
},
|
||||||
selectSegment(item, isChange = true) {
|
selectSegment(item, isChange = true) {
|
||||||
if (isChange) {
|
if (isChange) {
|
||||||
|
|
@ -787,6 +800,7 @@ export default {
|
||||||
},
|
},
|
||||||
async addSegment() {
|
async addSegment() {
|
||||||
if (this.saveLoading) return false
|
if (this.saveLoading) return false
|
||||||
|
if (this.isMPR) return false
|
||||||
if (this.segmentList.length <= 0) {
|
if (this.segmentList.length <= 0) {
|
||||||
let obj = {
|
let obj = {
|
||||||
name: this.getSegmentationName(),
|
name: this.getSegmentationName(),
|
||||||
|
|
@ -831,6 +845,7 @@ export default {
|
||||||
// this.readingSegmentByConfig()
|
// this.readingSegmentByConfig()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
this.changeSegmentationSavedStatus(this.segmentationId, false)
|
||||||
let item = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
let item = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
||||||
let arr = item.segments.sort((a, b) => a.segmentIndex - b.segmentIndex)
|
let arr = item.segments.sort((a, b) => a.segmentIndex - b.segmentIndex)
|
||||||
let segmentIndex = arr[item.segments.length - 1].segmentIndex + 1
|
let segmentIndex = arr[item.segments.length - 1].segmentIndex + 1
|
||||||
|
|
@ -1456,30 +1471,51 @@ export default {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
checkSaveLoading(callback) {
|
||||||
|
if (!this.saveLoading) {
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
|
this.saveSegmentGroup(null, true, callback)
|
||||||
|
} else {
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
if (!this.saveLoading) {
|
||||||
|
console.log(this.saveLoading, 'timer')
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
|
this.saveSegmentGroup(null, true, callback)
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
},
|
||||||
// 保存整个分组
|
// 保存整个分组
|
||||||
async saveSegmentGroup(list = null, saveSegment = true) {
|
async saveSegmentGroup(list = null, saveSegment = true, callback) {
|
||||||
try {
|
try {
|
||||||
|
console.log('saveSegmentGroup')
|
||||||
let segmentList = list ? list : this.segmentList
|
let segmentList = list ? list : this.segmentList
|
||||||
if (segmentList.length <= 0) return false
|
if (segmentList.length <= 0) return false
|
||||||
this.$emit("setToolsPassive")
|
this.$emit("setToolsPassive")
|
||||||
let questionNeedChange = false;
|
// let questionNeedChange = false;
|
||||||
if (saveSegment) {
|
// if (saveSegment) {
|
||||||
for (let i = 0; i < segmentList.length; i++) {
|
// for (let i = 0; i < segmentList.length; i++) {
|
||||||
let segmentGroup = segmentList[i]
|
// let segmentGroup = segmentList[i]
|
||||||
let data = {
|
// let data = {
|
||||||
SegmentationId: segmentGroup.segmentationId
|
// SegmentationId: segmentGroup.segmentationId
|
||||||
}
|
// }
|
||||||
let res = await this.getSegmentBindingList(data)
|
// let res = await this.getSegmentBindingList(data)
|
||||||
if (res && res.length > 0) {
|
// if (res && res.length > 0) {
|
||||||
questionNeedChange = true
|
// questionNeedChange = true
|
||||||
break
|
// break
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (questionNeedChange) {
|
// if (questionNeedChange) {
|
||||||
let confirm = await this.$confirm(this.$t("segment:confirm:questionNeedChange"))
|
// let confirm = await this.$confirm(this.$t("segment:confirm:questionNeedChange"))
|
||||||
if (!confirm) return false
|
// if (!confirm) return false
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
this.$emit("update:globalLoading", true)
|
this.$emit("update:globalLoading", true)
|
||||||
this.$emit("update:loadingText", this.$t("segment:loadingText:saveSegmentation"))
|
this.$emit("update:loadingText", this.$t("segment:loadingText:saveSegmentation"))
|
||||||
let IsBeSegment = false
|
let IsBeSegment = false
|
||||||
|
|
@ -1516,6 +1552,7 @@ export default {
|
||||||
DicomEvent.$emit("IsBeSegment", { StudyId: this.series.StudyId, Id: this.series.Id, IsBeSegment: f })
|
DicomEvent.$emit("IsBeSegment", { StudyId: this.series.StudyId, Id: this.series.Id, IsBeSegment: f })
|
||||||
}
|
}
|
||||||
this.$emit("update:globalLoading", false)
|
this.$emit("update:globalLoading", false)
|
||||||
|
if (callback) callback()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
console.log(err)
|
console.log(err)
|
||||||
|
|
@ -1703,7 +1740,7 @@ export default {
|
||||||
bidirectional: SegmentJson.bidirectional,
|
bidirectional: SegmentJson.bidirectional,
|
||||||
bidirectionalView: true,
|
bidirectionalView: true,
|
||||||
view: true,
|
view: true,
|
||||||
lock: true,
|
lock: s.IsLock,
|
||||||
id: s.Id
|
id: s.Id
|
||||||
}
|
}
|
||||||
obj.segments.push(o)
|
obj.segments.push(o)
|
||||||
|
|
@ -1823,6 +1860,20 @@ export default {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// 修改分割片段锁定状态
|
||||||
|
async lockOrUnLockSegment(SegmentId, IsLock) {
|
||||||
|
try {
|
||||||
|
let data = {
|
||||||
|
SegmentId,
|
||||||
|
IsLock
|
||||||
|
}
|
||||||
|
let res = await lockOrUnLockSegment(data)
|
||||||
|
if (res.IsSuccess) return true
|
||||||
|
return false
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
},
|
||||||
hex2Rgb(hexValue, alpha = 1) {
|
hex2Rgb(hexValue, alpha = 1) {
|
||||||
const rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
const rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||||
const hex = hexValue.replace(rgx, (m, r, g, b) => r + r + g + g + b + b);
|
const hex = hexValue.replace(rgx, (m, r, g, b) => r + r + g + g + b + b);
|
||||||
|
|
@ -1917,7 +1968,12 @@ export default {
|
||||||
return rgbToHex(rgb.r, rgb.g, rgb.b);
|
return rgbToHex(rgb.r, rgb.g, rgb.b);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
destroyed() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
this.timer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
@ -2053,6 +2109,7 @@ export default {
|
||||||
|
|
||||||
.messageBox {
|
.messageBox {
|
||||||
color: #333;
|
color: #333;
|
||||||
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.serialNum {
|
.serialNum {
|
||||||
|
|
|
||||||
|
|
@ -343,16 +343,36 @@ export default {
|
||||||
viewport.render()
|
viewport.render()
|
||||||
},
|
},
|
||||||
resize(forceFitToWindow) {
|
resize(forceFitToWindow) {
|
||||||
console.log('resize: ', forceFitToWindow)
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
if (!forceFitToWindow) {
|
if (!viewport) return
|
||||||
viewport.setZoom(0.5)
|
|
||||||
viewport.render()
|
if (forceFitToWindow) {
|
||||||
} else {
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
viewport.setZoom(1)
|
|
||||||
viewport.render()
|
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) {
|
async prefetchMetadataInformation(imageIdsToPrefetch, modality) {
|
||||||
let taskPromises = []
|
let taskPromises = []
|
||||||
|
|
|
||||||
|
|
@ -245,7 +245,7 @@ export default {
|
||||||
DicomEvent.$on('renderSegmentation', async (viewportId) => {
|
DicomEvent.$on('renderSegmentation', async (viewportId) => {
|
||||||
// if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
// if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
if (this.viewportId !== viewportId) return false
|
if (this.viewportId !== viewportId) return false
|
||||||
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration)
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration, this.segmentationId, this.segmentIndex)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -592,16 +592,36 @@ export default {
|
||||||
viewport.render()
|
viewport.render()
|
||||||
},
|
},
|
||||||
resize(forceFitToWindow) {
|
resize(forceFitToWindow) {
|
||||||
console.log('resize: ', forceFitToWindow)
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
if (!forceFitToWindow) {
|
if (!viewport) return
|
||||||
viewport.setZoom(0.5)
|
|
||||||
viewport.render()
|
if (forceFitToWindow) {
|
||||||
} else {
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
viewport.setZoom(1)
|
|
||||||
viewport.render()
|
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) {
|
voiChange(v) {
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
|
@ -690,7 +710,7 @@ export default {
|
||||||
renderingEngine.render()
|
renderingEngine.render()
|
||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, data.segment, this.actionConfiguration)
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, data.segment, this.actionConfiguration, this.segmentationId, this.segmentIndex)
|
||||||
DicomEvent.$emit('SegmentationLoading', this.viewportId)
|
DicomEvent.$emit('SegmentationLoading', this.viewportId)
|
||||||
if (data.segment) return false
|
if (data.segment) return false
|
||||||
if (this.series.hasOwnProperty('curIndex')) return this.setFullScreen(this.series.curIndex)
|
if (this.series.hasOwnProperty('curIndex')) return this.setFullScreen(this.series.curIndex)
|
||||||
|
|
@ -1058,4 +1078,4 @@ export default {
|
||||||
cursor: move
|
cursor: move
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -27,15 +27,15 @@
|
||||||
|
|
||||||
<el-form-item v-if="readingTaskState < 2">
|
<el-form-item v-if="readingTaskState < 2">
|
||||||
<div style="text-align:center;">
|
<div style="text-align:center;">
|
||||||
<el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" :disabled="isTableVisible" type="primary"
|
<el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" :disabled="isTableVisible || isSaved"
|
||||||
@click="skipTask">
|
type="primary" @click="skipTask">
|
||||||
{{ $t('trials:readingReport:button:skip') }}
|
{{ $t('trials:readingReport:button:skip') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" :disabled="isTableVisible" @click="handleSave">
|
<el-button type="primary" :disabled="isTableVisible || isSaved" @click="handleSave">
|
||||||
{{ $t('common:button:save') }}
|
{{ $t('common:button:save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" :disabled="isTableVisible" type="primary"
|
<el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" :disabled="isTableVisible || isSaved"
|
||||||
@click="handleSubmit">
|
type="primary" @click="handleSubmit">
|
||||||
{{ $t('common:button:submit') }}
|
{{ $t('common:button:submit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -121,7 +121,8 @@ export default {
|
||||||
digitPlaces: 2,
|
digitPlaces: 2,
|
||||||
questionImageToolAttributeInfo: {},
|
questionImageToolAttributeInfo: {},
|
||||||
unSaveTargets: [],
|
unSaveTargets: [],
|
||||||
isTableVisible: false
|
isTableVisible: false,
|
||||||
|
isSaved: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -283,6 +284,7 @@ export default {
|
||||||
const res = await changeDicomReadingQuestionAnswer(params)
|
const res = await changeDicomReadingQuestionAnswer(params)
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
if (isMsg) {
|
if (isMsg) {
|
||||||
|
this.isSaved = true
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
|
@ -1444,6 +1446,12 @@ export default {
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: true
|
immediate: true
|
||||||
},
|
},
|
||||||
|
questionForm: {
|
||||||
|
handler() {
|
||||||
|
this.isSaved = false
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
// questionMarkInfoList: {
|
// questionMarkInfoList: {
|
||||||
// handler() {
|
// handler() {
|
||||||
// console.log(this.questionMarkInfoList, 'questionMarkInfoList')
|
// console.log(this.questionMarkInfoList, 'questionMarkInfoList')
|
||||||
|
|
|
||||||
|
|
@ -229,7 +229,7 @@ function selectSegmentation(viewportId, segmentationId) {
|
||||||
segmentation.activeSegmentation.setActiveSegmentation(viewportId, segmentationId)
|
segmentation.activeSegmentation.setActiveSegmentation(viewportId, segmentationId)
|
||||||
}
|
}
|
||||||
function selectSegment(viewportId, segmentationId, segmentIndex) {
|
function selectSegment(viewportId, segmentationId, segmentIndex) {
|
||||||
if (!segmentIndex) return false
|
if (!segmentIndex || !segmentationId) return false
|
||||||
selectSegmentation(viewportId, segmentationId)
|
selectSegmentation(viewportId, segmentationId)
|
||||||
segmentation.segmentIndex.setActiveSegmentIndex(segmentationId, segmentIndex);
|
segmentation.segmentIndex.setActiveSegmentIndex(segmentationId, segmentIndex);
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +343,7 @@ function resetViewport(viewportId) {
|
||||||
function changeColor(item, viewportId) {
|
function changeColor(item, viewportId) {
|
||||||
segmentation.config.color.setSegmentIndexColor(viewportId, item.segmentationId, item.segmentIndex, hex2Rgb(item.color))
|
segmentation.config.color.setSegmentIndexColor(viewportId, item.segmentationId, item.segmentIndex, hex2Rgb(item.color))
|
||||||
}
|
}
|
||||||
async function renderSegmentation(series, visitInfo, viewportId, SegmentConfig, RenderingEngineId, Segment = null, actionConfiguration) {
|
async function renderSegmentation(series, visitInfo, viewportId, SegmentConfig, RenderingEngineId, Segment = null, actionConfiguration, segmentationId = null, segmentIndex = null) {
|
||||||
try {
|
try {
|
||||||
// console.log(segmentation, 'segmentation')
|
// console.log(segmentation, 'segmentation')
|
||||||
renderingEngineId = RenderingEngineId
|
renderingEngineId = RenderingEngineId
|
||||||
|
|
@ -354,8 +354,6 @@ async function renderSegmentation(series, visitInfo, viewportId, SegmentConfig,
|
||||||
PageSize: 9999,
|
PageSize: 9999,
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
}
|
}
|
||||||
let segmentationId = null;
|
|
||||||
let segmentIndex = null;
|
|
||||||
let res = await getSegmentationList(data);
|
let res = await getSegmentationList(data);
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
let list = res.Result.CurrentPageData;
|
let list = res.Result.CurrentPageData;
|
||||||
|
|
@ -383,7 +381,7 @@ async function renderSegmentation(series, visitInfo, viewportId, SegmentConfig,
|
||||||
let SegmentJson = s.SegmentJson ? JSON.parse(s.SegmentJson) : {};
|
let SegmentJson = s.SegmentJson ? JSON.parse(s.SegmentJson) : {};
|
||||||
segmentation.segmentIndex.setActiveSegmentIndex(s.SegmentationId, s.SegmentNumber);
|
segmentation.segmentIndex.setActiveSegmentIndex(s.SegmentationId, s.SegmentNumber);
|
||||||
segmentation.config.color.setSegmentIndexColor(viewportId, s.SegmentationId, s.SegmentNumber, hex2Rgb(s.ColorRgb))
|
segmentation.config.color.setSegmentIndexColor(viewportId, s.SegmentationId, s.SegmentNumber, hex2Rgb(s.ColorRgb))
|
||||||
segmentation.segmentLocking.setSegmentIndexLocked(s.SegmentationId, s.SegmentNumber, true)
|
segmentation.segmentLocking.setSegmentIndexLocked(s.SegmentationId, s.SegmentNumber, s.IsLock)
|
||||||
if (SegmentJson.bidirectional) {
|
if (SegmentJson.bidirectional) {
|
||||||
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === s.SegmentationId && i.metadata.segmentIndex === SegmentJson.bidirectional.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === s.SegmentationId && i.metadata.segmentIndex === SegmentJson.bidirectional.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
if (!an) {
|
if (!an) {
|
||||||
|
|
|
||||||
|
|
@ -194,9 +194,9 @@
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<el-input v-model="QuestionList[index].JudgeDifferenceValue" clearable
|
<el-input v-model="QuestionList[index].JudgeDifferenceValue" clearable
|
||||||
:disabled="OtherInfo.IsSign"></el-input>
|
:disabled="OtherInfo.IsSign"></el-input>
|
||||||
<span style="margin-left: 10px" v-if="QuestionList[index].JudgeType !== 5">{{
|
<span style="margin-left: 10px" v-if="QuestionList[index].JudgeType !== 5 && QuestionList[index].Unit !== 0">
|
||||||
$fd('ValueUnit', QuestionList[index].Unit)
|
{{ `${QuestionList[index].Unit === 4 ? QuestionList[index].CustomUnit : $fd('ValueUnit', QuestionList[index].Unit)}`}}
|
||||||
}}</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
|
||||||
|
|
@ -307,7 +307,14 @@
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
></el-input>
|
></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item v-if="isAudit" :label="$t('trials:ptData:label:reason')" prop="Reason">
|
||||||
|
<el-input
|
||||||
|
type="textarea"
|
||||||
|
:autosize="{ minRows: 2, maxRows: 4}"
|
||||||
|
v-model="formData.Reason"
|
||||||
|
style="width: 100%"
|
||||||
|
></el-input>
|
||||||
|
</el-form-item>
|
||||||
<!-- 提交 -->
|
<!-- 提交 -->
|
||||||
<el-form-item style="margin-top: 20px;text-align: right;" v-if="isPatientFormCanEdit">
|
<el-form-item style="margin-top: 20px;text-align: right;" v-if="isPatientFormCanEdit">
|
||||||
<el-button type="primary" @click="submitForm">{{ $t('trials:ptData:button:submit') }}</el-button>
|
<el-button type="primary" @click="submitForm">{{ $t('trials:ptData:button:submit') }}</el-button>
|
||||||
|
|
@ -351,6 +358,19 @@
|
||||||
<PreviewFile v-if="previewObj.visible" :file-path="previewObj.filePath" :file-type="previewObj.fileType" />
|
<PreviewFile v-if="previewObj.visible" :file-path="previewObj.filePath" :file-type="previewObj.fileType" />
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
|
||||||
|
append-to-body custom-class="base-dialog-wrapper">
|
||||||
|
<div slot="title">
|
||||||
|
<span style="font-size: 18px">{{
|
||||||
|
$t('common:dialogTitle:sign')
|
||||||
|
}}</span>
|
||||||
|
<span style="font-size: 12px; margin-left: 5px">{{
|
||||||
|
`(${$t('common:label:sign')}${currentUser})`
|
||||||
|
}}</span>
|
||||||
|
</div>
|
||||||
|
<SignForm ref="signForm" :sign-code-enum="signCode" :subject-visit-id="subjectVisitId"
|
||||||
|
@closeDialog="closeSignDialog" />
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -362,7 +382,8 @@ import {
|
||||||
getCRCClinicalData,
|
getCRCClinicalData,
|
||||||
addOrUpdateReadingClinicalData,
|
addOrUpdateReadingClinicalData,
|
||||||
getPatientInfo,
|
getPatientInfo,
|
||||||
editPatientInfo
|
editPatientInfo,
|
||||||
|
amendmentPatientInfo
|
||||||
} from '@/api/trials'
|
} from '@/api/trials'
|
||||||
import PreviousRadiotherapy from './previousRadiotherapy'
|
import PreviousRadiotherapy from './previousRadiotherapy'
|
||||||
import PreviousSurgery from './previousSurgery'
|
import PreviousSurgery from './previousSurgery'
|
||||||
|
|
@ -370,7 +391,9 @@ import PreviousOther from './previousOther'
|
||||||
import PreviousFiles from './previousFiles'
|
import PreviousFiles from './previousFiles'
|
||||||
import clinicalDataQuestions from '@/components/clinicalDataQuestions'
|
import clinicalDataQuestions from '@/components/clinicalDataQuestions'
|
||||||
import PreviewFile from '@/components/PreviewFile/index'
|
import PreviewFile from '@/components/PreviewFile/index'
|
||||||
|
import SignForm from '@/views/trials/components/newSignForm'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
import const_ from '@/const/sign-code'
|
||||||
export default {
|
export default {
|
||||||
name: 'uploadPetClinicalData',
|
name: 'uploadPetClinicalData',
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -380,6 +403,7 @@ export default {
|
||||||
PreviousFiles,
|
PreviousFiles,
|
||||||
clinicalDataQuestions,
|
clinicalDataQuestions,
|
||||||
PreviewFile,
|
PreviewFile,
|
||||||
|
SignForm
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
data: {
|
data: {
|
||||||
|
|
@ -410,6 +434,10 @@ export default {
|
||||||
isPatientFormAllowEdit: {
|
isPatientFormAllowEdit: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
},
|
||||||
|
isAudit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -443,7 +471,8 @@ export default {
|
||||||
RadionuclideHalfLife: null,
|
RadionuclideHalfLife: null,
|
||||||
RadiopharmaceuticalStartTime: null,
|
RadiopharmaceuticalStartTime: null,
|
||||||
AcquisitionTime: null,
|
AcquisitionTime: null,
|
||||||
TimeCheck: ''
|
TimeCheck: '',
|
||||||
|
Reason: ''
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
PatientSex: [
|
PatientSex: [
|
||||||
|
|
@ -470,10 +499,16 @@ export default {
|
||||||
{ type: 'number', message: this.$t('trials:ptData:ruleMessage:number2'), trigger: 'blur' },//请输入数字
|
{ type: 'number', message: this.$t('trials:ptData:ruleMessage:number2'), trigger: 'blur' },//请输入数字
|
||||||
// 自定义校验:确保成像时间不早于注射时间
|
// 自定义校验:确保成像时间不早于注射时间
|
||||||
{ validator: this.validateTime, trigger: 'blur' }
|
{ validator: this.validateTime, trigger: 'blur' }
|
||||||
]
|
],
|
||||||
|
Reason: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||||
|
],
|
||||||
},
|
},
|
||||||
formLoading: false,
|
formLoading: false,
|
||||||
isPatientFormCanEdit: false
|
isPatientFormCanEdit: false,
|
||||||
|
signVisible: false,
|
||||||
|
signCode: '',
|
||||||
|
currentUser: zzSessionStorage.getItem('userName')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -814,7 +849,8 @@ export default {
|
||||||
RadionuclideHalfLife: parseFloat(res.Result.RadionuclideHalfLife) || null,
|
RadionuclideHalfLife: parseFloat(res.Result.RadionuclideHalfLife) || null,
|
||||||
RadiopharmaceuticalStartTime: parseFloat(res.Result.RadiopharmaceuticalStartTime) || '',
|
RadiopharmaceuticalStartTime: parseFloat(res.Result.RadiopharmaceuticalStartTime) || '',
|
||||||
AcquisitionTime: parseFloat(res.Result.AcquisitionTime) || '',
|
AcquisitionTime: parseFloat(res.Result.AcquisitionTime) || '',
|
||||||
TimeCheck: ''
|
TimeCheck: '',
|
||||||
|
Reason: res.Result.Reason
|
||||||
}
|
}
|
||||||
this.computeTimeRelation()
|
this.computeTimeRelation()
|
||||||
this.formLoading = false
|
this.formLoading = false
|
||||||
|
|
@ -828,19 +864,47 @@ export default {
|
||||||
try {
|
try {
|
||||||
let valid = await this.$refs.patientForm.validate()
|
let valid = await this.$refs.patientForm.validate()
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
this.formLoading = true
|
if (this.isAudit) {
|
||||||
let res = await editPatientInfo(this.formData)
|
const { CorrectImageExaminationInformation } = const_.processSignature
|
||||||
this.formLoading = false
|
this.signCode = CorrectImageExaminationInformation
|
||||||
if (res.IsSuccess) {
|
this.signVisible = true
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
} else {
|
||||||
|
this.formLoading = true
|
||||||
|
let res = await editPatientInfo(this.formData)
|
||||||
|
this.formLoading = false
|
||||||
|
if (res && res.IsSuccess) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
this.formLoading = false
|
this.formLoading = false
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
async closeSignDialog(isSign, signInfo) {
|
||||||
|
try {
|
||||||
|
if (isSign) {
|
||||||
|
let data = {
|
||||||
|
data: this.formData,
|
||||||
|
signInfo
|
||||||
|
}
|
||||||
|
let res = await amendmentPatientInfo(data)
|
||||||
|
if (res && res.IsSuccess) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
this.signVisible = false
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.signVisible = false
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@
|
||||||
:disabled="isAudit || scope.row.IsDeleted || SecondReviewState > 0"
|
:disabled="isAudit || scope.row.IsDeleted || SecondReviewState > 0"
|
||||||
@click="handleEditStudy(scope.row)" />
|
@click="handleEditStudy(scope.row)" />
|
||||||
<!-- 预览PET-CT数据 -->
|
<!-- 预览PET-CT数据 -->
|
||||||
<el-button type="primary" icon="el-icon-document tip-i" :title="$t('trials:audit:tab:clinicalData')"
|
<el-button icon="el-icon-document" :title="$t('trials:audit:tab:clinicalData')"
|
||||||
v-if="
|
v-if="
|
||||||
['PT、CT', 'CT、PT', 'PET-CT'].includes(
|
['PT、CT', 'CT、PT', 'PET-CT'].includes(
|
||||||
scope.row.Modalities
|
scope.row.Modalities
|
||||||
|
|
@ -921,7 +921,7 @@
|
||||||
</div>
|
</div>
|
||||||
<!--petct临床数据预览-->
|
<!--petct临床数据预览-->
|
||||||
<el-dialog v-if="petVisible" :show-close="true" :visible.sync="petVisible" append-to-body>
|
<el-dialog v-if="petVisible" :show-close="true" :visible.sync="petVisible" append-to-body>
|
||||||
<uploadPetClinicalData :subject-visit-id="data.Id" :data="data" :studyData="rowData" :allow-add-or-edit="false" :isPatientFormAllowEdit="!isAudit && SecondReviewState == 0"/>
|
<uploadPetClinicalData :subject-visit-id="data.Id" :data="data" :studyData="rowData" :allow-add-or-edit="false" :isPatientFormAllowEdit="isAuditToEdit" :isAudit="isAuditToEdit" @close="petVisible = false"/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue