阅片添加分割工具
parent
18a71725f9
commit
266886fa64
|
|
@ -115,8 +115,7 @@ export default {
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
// this.show = process.env.VUE_APP_OSS_PATH === '/test/dist'
|
||||
this.show = false
|
||||
this.show = process.env.VUE_APP_OSS_PATH === '/test/dist'
|
||||
Vue.prototype.$openI18n = this.openI18n
|
||||
},
|
||||
// watch: {
|
||||
|
|
|
|||
|
|
@ -319,3 +319,84 @@ export function getReportsChartData(param) {
|
|||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
// 分割相关
|
||||
// 获取分割组
|
||||
export function getSegmentationList(param) {
|
||||
return request({
|
||||
url: `/Segmentation/getSegmentationList`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
// 新增修改分割组
|
||||
export function addOrUpdateSegmentation(param) {
|
||||
return request({
|
||||
url: `/Segmentation/addOrUpdateSegmentation`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
// 删除分割组
|
||||
export function deleteSegmentation(segmentationId) {
|
||||
return request({
|
||||
url: `/Segmentation/deleteSegmentation/${segmentationId}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
// 获取分割
|
||||
export function getSegmentList(param) {
|
||||
return request({
|
||||
url: `/Segmentation/getSegmentList`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
// 新增修改分割
|
||||
export function addOrUpdateSegment(param) {
|
||||
return request({
|
||||
url: `/Segmentation/addOrUpdateSegment`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
// 删除分割
|
||||
export function deleteSegment(segmentId) {
|
||||
return request({
|
||||
url: `/Segmentation/deleteSegment/${segmentId}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
// 获取分割绑定关系
|
||||
export function getSegmentBindingList(param) {
|
||||
return request({
|
||||
url: `/Segmentation/getSegmentBindingList`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
// 保存分割绑定关系(可用作修改删除)
|
||||
export function saveSegmentBindingAndAnswer(param) {
|
||||
return request({
|
||||
url: `/Segmentation/saveSegmentBindingAndAnswer`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
// 获取表格问题配置
|
||||
export function getReadingTableQuestionTrialById(params) {
|
||||
return request({
|
||||
url: `/ReadingQuestion/getReadingTableQuestionTrialById`,
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
// 获取外层问题配置
|
||||
export function getReadingQuestionTrialById(params) {
|
||||
return request({
|
||||
url: `/ReadingQuestion/getReadingQuestionTrialById`,
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" class="h-6 w-6" color="#fff">
|
||||
<path
|
||||
d="M10.3945 12.6113C10.043 12.6113 9.78516 12.3945 9.78516 12.0371C9.78516 11.6855 10.043 11.4688 10.3945 11.4688H13.2012C13.5527 11.4688 13.8164 11.6855 13.8164 12.0371C13.8164 12.3945 13.5527 12.6113 13.2012 12.6113H10.3945Z"
|
||||
fill="currentColor"></path>
|
||||
<path opacity="0.5"
|
||||
d="M18.312 6.84473C21.8473 8.88583 22.9225 13.6424 20.7134 17.4687C18.5042 21.2951 13.8473 22.7422 10.312 20.7011C9.51661 20.2419 8.84737 19.6439 8.31042 18.9512C11.3012 19.3598 14.4827 17.8251 16.1946 14.8598C17.9067 11.8945 17.6457 8.3712 15.7963 5.98538C16.6645 6.10409 17.5167 6.38556 18.312 6.84473Z"
|
||||
fill="currentColor"></path>
|
||||
<circle cx="13.7852" cy="13.4688" r="8" stroke="currentColor"></circle>
|
||||
<path
|
||||
d="M4.50586 8.22266C4.14844 8.22266 3.92578 7.9707 3.92578 7.60742V5.68555H2.10352C1.74609 5.68555 1.5 5.46875 1.5 5.11719C1.5 4.76562 1.74609 4.54297 2.10352 4.54297H3.92578V2.61523C3.92578 2.25195 4.14844 2 4.50586 2C4.85742 2 5.08008 2.25195 5.08008 2.61523V4.54297H6.89648C7.25391 4.54297 7.50586 4.76562 7.50586 5.11719C7.50586 5.46875 7.25391 5.68555 6.89648 5.68555H5.08008V7.60742C5.08008 7.9707 4.85742 8.22266 4.50586 8.22266Z"
|
||||
fill="currentColor"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg width="18px" height="18px" viewBox="0 0 18 18" class="text-primary"><g id="view-fill" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Group-13"><rect id="Rectangle" x="0" y="0" width="18" height="18"></rect><rect id="Rectangle" fill="currentColor" x="2" y="2" width="14" height="14" rx="1"></rect></g></g></svg>
|
||||
|
After Width: | Height: | Size: 338 B |
|
|
@ -0,0 +1 @@
|
|||
<svg width="18px" height="18px" viewBox="0 0 18 18" class="text-primary"><g id="view-outline-fill" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Group-13"><rect id="Rectangle" x="0" y="0" width="18" height="18"></rect><rect id="Rectangle" stroke="currentColor" x="1.5" y="1.5" width="15" height="15" rx="1"></rect><rect id="Rectangle" fill="currentColor" x="3.5" y="3.5" width="11" height="11" rx="1"></rect></g></g></svg>
|
||||
|
After Width: | Height: | Size: 446 B |
|
|
@ -0,0 +1 @@
|
|||
<svg width="18px" height="18px" viewBox="0 0 18 18" class="text-primary"><g id="view-outline" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="Group-13"><rect id="Rectangle" x="0" y="0" width="18" height="18"></rect><rect id="Rectangle" stroke="currentColor" x="1.5" y="1.5" width="15" height="15" rx="1"></rect></g></g></svg>
|
||||
|
After Width: | Height: | Size: 347 B |
|
|
@ -0,0 +1,823 @@
|
|||
<template>
|
||||
<div ref="viewport-volume" class="viewport-wrapper" v-loading="loading" :element-loading-text="NSTip"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)" @mouseup="sliderMouseup" @mousemove="sliderMousemove"
|
||||
@mouseleave="sliderMouseleave" :style="{ color: '#ddd' }">
|
||||
<div v-if="series && taskInfo" class="left-top-text">
|
||||
<div v-if="taskInfo.IsExistsClinicalData" class="cd-info" :title="$t('trials:reading:button:clinicalData')">
|
||||
<svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon"
|
||||
@click.stop="viewCD(series.TaskInfo.VisitTaskId)" />
|
||||
</div>
|
||||
<h2 v-if="taskInfo.IsReadingShowSubjectInfo && series.TaskInfo" class="subject-info">
|
||||
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
|
||||
</h2>
|
||||
<div>Series: #{{ series.SeriesNumber }}</div>
|
||||
<div v-if="imageInfo.total">Image: #{{ `${series.SliceIndex + 1}/${imageInfo.total}` }}</div>
|
||||
<div>{{ series.Modality }}</div>
|
||||
</div>
|
||||
<div v-if="series" class="right-top-text">
|
||||
<div>{{ series.Description }}</div>
|
||||
</div>
|
||||
<div v-if="series" class="left-bottom-text">
|
||||
<div v-show="mousePosition.index.length > 0">
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
|
||||
</div>
|
||||
<div
|
||||
v-if="(series.Modality === 'CT' || series.Modality === 'DR' || series.Modality === 'CR') && mousePosition.value">
|
||||
HU: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-else-if="(series.Modality === 'PT' && mousePosition.value)">
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ? mousePosition.value.toFixed(3) :
|
||||
mousePosition.value.toFixed(digitPlaces)
|
||||
}}
|
||||
</div>
|
||||
<div v-else-if="mousePosition.value">
|
||||
Density: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-show="imageInfo.size">
|
||||
W*H: {{ imageInfo.size }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series" class="right-bottom-text">
|
||||
<div v-show="imageInfo.location">Location: {{
|
||||
`${Number(imageInfo.location).toFixed(digitPlaces)} mm`
|
||||
}}</div>
|
||||
<div v-show="imageInfo.sliceThickness">Slice Thickness: {{
|
||||
`${Number(imageInfo.sliceThickness).toFixed(digitPlaces)} mm`
|
||||
}}</div>
|
||||
<div v-show="imageInfo.wwwc">WW/WL: {{ imageInfo.wwwc }}</div>
|
||||
</div>
|
||||
<div class="orientation-top">
|
||||
{{ markers.top }}
|
||||
</div>
|
||||
<div class="orientation-right">
|
||||
{{ markers.right }}
|
||||
</div>
|
||||
|
||||
<div class="orientation-bottom">
|
||||
{{ markers.bottom }}
|
||||
</div>
|
||||
<div class="orientation-left">
|
||||
{{ markers.left }}
|
||||
</div>
|
||||
<div ref="sliderBox" class="right-slider-box" @click.stop="clickSlider($event)">
|
||||
<div :style="{ top: sliderInfo.height + '%' }" class="slider" @click.stop.prevent="() => { return }"
|
||||
@mousedown.stop="sliderMousedown($event)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
metaData,
|
||||
getRenderingEngine,
|
||||
utilities as csUtils,
|
||||
cache
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
|
||||
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||
import { setPetColorMapTransferFunctionForVolumeActor } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetColorMapTransferFunctionForVolumeActor'
|
||||
import { vec3, mat4 } from 'gl-matrix'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
export default {
|
||||
name: 'MPRViewport',
|
||||
props: {
|
||||
renderingEngineId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
viewportId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
viewportIndex: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
MPRInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
element: '',
|
||||
series: {},
|
||||
ctSeries: {},
|
||||
petSeries: {},
|
||||
taskInfo: null,
|
||||
sliderInfo: {
|
||||
oldB: null,
|
||||
oldM: null,
|
||||
isMove: false,
|
||||
height: 0
|
||||
},
|
||||
mousePosition: {
|
||||
index: [],
|
||||
value: null,
|
||||
modalityUnit: '',
|
||||
world: []
|
||||
},
|
||||
imageInfo: {
|
||||
zoom: null,
|
||||
size: null,
|
||||
location: null,
|
||||
sliceThickness: null,
|
||||
wwwc: null,
|
||||
total: 0,
|
||||
sliceThickness: 0
|
||||
},
|
||||
digitPlaces: 2,
|
||||
orientationMarkers: [],
|
||||
originalMarkers: [],
|
||||
markers: { top: '', right: '', bottom: '', left: '' },
|
||||
playClipState: false,
|
||||
wwwcIdx: 2,
|
||||
presetName: '',
|
||||
volumeId: null,
|
||||
defaultWindowLevel: {},
|
||||
rotateAngle: 0,
|
||||
rotateBarLeft: 0,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo'))
|
||||
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.$nextTick(() => {
|
||||
this.initViewport()
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
MPRInfo: {
|
||||
handler() {
|
||||
if (!this.series.orientation) return false
|
||||
switch (this.series.orientation) {
|
||||
case 'AXIAL':
|
||||
this.imageInfo.size = `${this.MPRInfo.SAGITTAL.imageNum}*${this.MPRInfo.CORONAL.imageNum}`
|
||||
break;
|
||||
case 'CORONAL':
|
||||
this.imageInfo.size = `${this.MPRInfo.SAGITTAL.imageNum}*${this.MPRInfo.AXIAL.imageNum}`
|
||||
break;
|
||||
case 'SAGITTAL':
|
||||
this.imageInfo.size = `${this.MPRInfo.CORONAL.imageNum}*${this.MPRInfo.AXIAL.imageNum}`
|
||||
break;
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initViewport() {
|
||||
this.element = this.$refs['viewport-volume']
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
if (renderingEngine) {
|
||||
renderingEngine.resize(true, false)
|
||||
}
|
||||
})
|
||||
this.element.oncontextmenu = (e) => e.preventDefault()
|
||||
// resizeObserver.observe(this.element)
|
||||
this.element.addEventListener("CORNERSTONE_VOLUME_NEW_IMAGE", this.stackNewImage)
|
||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||
this.element.addEventListener('wheel', (e) => {
|
||||
// console.log('CORNERSTONE_STACK_VIEWPORT_SCROLL')
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const currentImageIdIndex = viewport.getCurrentImageIdIndex()
|
||||
const totalImages = this.imageInfo.total;
|
||||
|
||||
// 手动实现循环逻辑
|
||||
if (currentImageIdIndex >= totalImages - 1) {
|
||||
// 滚动到最后一张时跳回第一张
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: 0 });
|
||||
} else if (currentImageIdIndex <= 0) {
|
||||
// 滚动到第一张时跳回最后一张
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: totalImages - 1 });
|
||||
}
|
||||
});
|
||||
this.element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.cornerstoneToolsMouseMove)
|
||||
// this.element.addEventListener(cornerstoneTools.Enums.Events.MOUSE_WHEEL, this.handletoolsMouseWheel)
|
||||
this.element.addEventListener('mouseleave', () => {
|
||||
this.mousePosition.index = []
|
||||
this.mousePosition.value = null
|
||||
})
|
||||
document.addEventListener('mouseup', () => {
|
||||
this.sliderMouseup()
|
||||
})
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
this.sliderMousemove(e)
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
determineImagePlane(imageOrientationPatient) {
|
||||
// imageOrientationPatient 是 [rowX, rowY, rowZ, colX, colY, colZ]
|
||||
// 我们只关心行方向向量 (rowX, rowY, rowZ)
|
||||
const [rowX, rowY, rowZ] = imageOrientationPatient;
|
||||
|
||||
// 计算行方向向量与 X, Y, Z 轴的点积(因为轴向量是单位向量,所以点积就是投影长度)
|
||||
const dotX = Math.abs(rowX);
|
||||
const dotY = Math.abs(rowY);
|
||||
const dotZ = Math.abs(rowZ);
|
||||
|
||||
// 找到最大的点积,确定主方向
|
||||
const maxDot = Math.max(dotX, dotY, dotZ);
|
||||
|
||||
// 根据主方向判断解剖面
|
||||
if (maxDot === dotX) {
|
||||
// 行方向接近 X 轴,说明视线方向接近 Y 或 Z 轴。
|
||||
// 更准确的判断是看视线方向(由行和列向量叉乘得到)。
|
||||
// 但一个简化的、在大多数情况下都成立的规则是:
|
||||
// 如果行向量主要在 X-Y 平面 (rowZ 很小),则为 Axial。
|
||||
// 如果行向量主要在 X-Z 平面 (rowY 很小),则为 Sagittal。
|
||||
// 为了简化,我们可以直接根据视线方向(法线)来判断。
|
||||
// 法线方向 = 行向量 × 列向量
|
||||
const [colX, colY, colZ] = imageOrientationPatient.slice(3);
|
||||
const normalX = rowY * colZ - rowZ * colY;
|
||||
const normalY = rowZ * colX - rowX * colZ;
|
||||
const normalZ = rowX * colY - rowY * colX;
|
||||
|
||||
const absNormalX = Math.abs(normalX);
|
||||
const absNormalY = Math.abs(normalY);
|
||||
const absNormalZ = Math.abs(normalZ);
|
||||
|
||||
const maxNormal = Math.max(absNormalX, absNormalY, absNormalZ);
|
||||
|
||||
if (maxNormal === absNormalZ) {
|
||||
return 'AXIAL';
|
||||
} else if (maxNormal === absNormalY) {
|
||||
return 'SAGITTAL';
|
||||
} else if (maxNormal === absNormalX) {
|
||||
return 'CORONAL';
|
||||
}
|
||||
|
||||
} else if (maxDot === dotY) {
|
||||
// 行方向接近 Y 轴,通常是 Coronal 面。
|
||||
return 'SAGITTAL';
|
||||
} else if (maxDot === dotZ) {
|
||||
// 行方向接近 Z 轴,通常是 Sagittal 面。
|
||||
return 'CORONAL';
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
},
|
||||
stackNewImage(e) {
|
||||
const { detail } = e
|
||||
this.series.SliceIndex = detail.imageIndex
|
||||
this.sliderInfo.height = detail.imageIndex * 100 / detail.numberOfSlices
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
let imageIds = viewport.getImageIds(this.volumeId)
|
||||
let imageId = imageIds[0]
|
||||
let volume = cache.getVolume(this.volumeId)
|
||||
let spacing = volume ? volume.spacing : []
|
||||
// if (this.series.orientation === 'AXIAL') imageId = viewport.getCurrentImageId()
|
||||
if (imageId && volume) {
|
||||
this.$emit('setMPRInfo', { type: this.series.orientation, key: "imageNum", value: detail.numberOfSlices })
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId)
|
||||
let type = this.determineImagePlane(imagePlaneModule.imageOrientationPatient)
|
||||
this.imageInfo.location = type === this.series.orientation ? imagePlaneModule.sliceLocation : ''
|
||||
this.imageInfo.sliceThickness = type === this.series.orientation ? spacing[2] : spacing[0]
|
||||
this.imageInfo.total = detail.numberOfSlices
|
||||
this.getOrientationMarker()
|
||||
let properties = viewport.getProperties(this.volumeId)
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const windowWidth = upper - lower
|
||||
const windowCenter = (upper + lower) / 2
|
||||
this.defaultWindowLevel.windowWidth = windowWidth
|
||||
this.defaultWindowLevel.windowCenter = windowCenter
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
}
|
||||
}
|
||||
if (volume) {
|
||||
const toolGroupId = 'share-viewport-volume'
|
||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolEnabled('ScaleOverlay')
|
||||
}
|
||||
// const toolGroupId = this.viewportId
|
||||
},
|
||||
setFullScreen(index) {
|
||||
setTimeout(() => {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: index })
|
||||
viewport.render()
|
||||
})
|
||||
},
|
||||
voiModified(e) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
let properties = viewport.getProperties()
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
)
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
this.$emit('upperRangeChange', Math.round(windowWidth))
|
||||
}
|
||||
},
|
||||
getOrientationMarker() {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const { viewUp, viewPlaneNormal } = viewport.getCamera()
|
||||
|
||||
const viewRight = vec3.create()
|
||||
vec3.cross(viewRight, viewUp, viewPlaneNormal)
|
||||
|
||||
const columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]]
|
||||
const rowCosines = viewRight
|
||||
const rowString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(rowCosines)
|
||||
const columnString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(columnCosines)
|
||||
const oppositeRowString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(rowString)
|
||||
const oppositeColumnString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(columnString)
|
||||
this.markers.top = oppositeColumnString
|
||||
this.markers.right = rowString
|
||||
this.markers.bottom = columnString
|
||||
this.markers.left = oppositeRowString
|
||||
this.orientationMarkers = [oppositeColumnString, rowString, columnString, oppositeRowString]
|
||||
if (this.originalMarkers.length === 0) {
|
||||
this.originalMarkers = [...this.orientationMarkers]
|
||||
}
|
||||
},
|
||||
setMarkers() {
|
||||
const markers = [...this.orientationMarkers]
|
||||
for (const key in this.markers) {
|
||||
const v = markers.shift(0)
|
||||
this.markers[key] = v
|
||||
}
|
||||
},
|
||||
resetOrientationMarkers() {
|
||||
if (this.originalMarkers.length > 0) {
|
||||
this.orientationMarkers = [...this.originalMarkers]
|
||||
this.setMarkers()
|
||||
}
|
||||
},
|
||||
rotateOrientationMarkers(type) {
|
||||
if (this.orientationMarkers.length > 0) {
|
||||
if (type === 1) {
|
||||
this.resetOrientationMarkers()
|
||||
return
|
||||
}
|
||||
const markers = [...this.orientationMarkers]
|
||||
if (type === 2) {
|
||||
// 垂直翻转
|
||||
this.orientationMarkers[0] = markers[2]
|
||||
this.orientationMarkers[2] = markers[0]
|
||||
} else if (type === 3) {
|
||||
// 水平翻转
|
||||
this.orientationMarkers[1] = markers[3]
|
||||
this.orientationMarkers[3] = markers[1]
|
||||
} else if (type === 4) {
|
||||
// 左转90度
|
||||
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
|
||||
} else if (type === 5) {
|
||||
// 右转90度
|
||||
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
|
||||
}
|
||||
this.setMarkers()
|
||||
}
|
||||
},
|
||||
toggleClipPlay(isPlay, framesPerSecond) {
|
||||
this.playClipState = isPlay
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
if (isPlay) {
|
||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
|
||||
} else {
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
}
|
||||
},
|
||||
scrollPage(type) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const currentImageIdIndex = viewport.getCurrentImageIdIndex()
|
||||
const numImages = viewport.getImageIds().length
|
||||
let newImageIdIndex = null
|
||||
if (type === 0) {
|
||||
newImageIdIndex = 0
|
||||
} else if (type === -1) {
|
||||
newImageIdIndex = currentImageIdIndex === 0 ? currentImageIdIndex : currentImageIdIndex - 1
|
||||
} else if (type === 1) {
|
||||
newImageIdIndex = currentImageIdIndex === numImages - 1 ? currentImageIdIndex : currentImageIdIndex + 1
|
||||
} else if (type === 99999) {
|
||||
newImageIdIndex = numImages - 1
|
||||
}
|
||||
// viewport.setImageIdIndex(newImageIdIndex)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: newImageIdIndex })
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
},
|
||||
setZoom(ratio) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
const zoom = viewport.getZoom()
|
||||
if (ratio > 0) {
|
||||
viewport.setZoom(zoom * 1.05)
|
||||
} else {
|
||||
viewport.setZoom(zoom / 1.05)
|
||||
}
|
||||
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)
|
||||
viewport.render()
|
||||
}
|
||||
},
|
||||
voiChange(v) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const voiRange = { lower: 0, upper: v }
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (!viewport) return
|
||||
let volumeId = this.volumeId
|
||||
const viewportsContainingVolumeUID = csUtils.getViewportsWithVolumeId(
|
||||
volumeId,
|
||||
viewport.renderingEngineId
|
||||
)
|
||||
|
||||
viewport.setProperties({ voiRange }, volumeId)
|
||||
viewportsContainingVolumeUID.forEach((vp) => {
|
||||
vp.render()
|
||||
// this.$refs[vp.id].voiModified()
|
||||
this.voiModified()
|
||||
})
|
||||
},
|
||||
setPreset(presetName) {
|
||||
this.presetName = presetName
|
||||
},
|
||||
async createImageIdsAndCacheMetaData(obj) {
|
||||
this.loading = true
|
||||
await createImageIdsAndCacheMetaData({
|
||||
modality: obj.Modality,
|
||||
imageIds: obj.ImageIds
|
||||
})
|
||||
this.loading = false
|
||||
},
|
||||
async setSeriesInfo(obj, isLocate = false) {
|
||||
try {
|
||||
let data = obj
|
||||
if (this.series && data.Id === this.series.Id && data.Description === this.series.Description && !isLocate && !data.isLocation) {
|
||||
data.SliceIndex = this.series.SliceIndex
|
||||
}
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (isLocate) return csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex });
|
||||
this.series = {}
|
||||
this.volumeId = data.SeriesInstanceUid
|
||||
this.series = { ...data }
|
||||
viewport
|
||||
.setVolumes([{
|
||||
volumeId: this.volumeId, callback: (r) => {
|
||||
if (this.series.Modality === 'PT') {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r, true)
|
||||
} else {
|
||||
setCtTransferFunctionForVolumeActor(r)
|
||||
}
|
||||
console.log("渲染成功")
|
||||
DicomEvent.$emit("isloaded", {})
|
||||
}
|
||||
}]).then(res => {
|
||||
if (data.isLocation) {
|
||||
setTimeout(() => { csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex }); })
|
||||
}
|
||||
})
|
||||
viewport.render()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
},
|
||||
cornerstoneToolsMouseMove(e) {
|
||||
const { currentPoints } = e.detail
|
||||
const worldPoint = currentPoints.world
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const imageData = viewport.getImageData()
|
||||
if (!imageData) return
|
||||
const index = imageData.imageData.worldToIndex(worldPoint)
|
||||
index[0] = Math.floor(index[0])
|
||||
index[1] = Math.floor(index[1])
|
||||
index[2] = Math.floor(index[2])
|
||||
this.mousePosition.index = index
|
||||
},
|
||||
toggleTask(evt, visitTaskNum, i) {
|
||||
this.$emit('activeViewport', this.viewportIndex)
|
||||
const num = visitTaskNum + i
|
||||
if (num >= 0 && num <= this.taskInfo.VisitNum) {
|
||||
this.$emit('toggleTaskByViewport', { series: this.series, visitTaskNum: num })
|
||||
}
|
||||
|
||||
evt.stopImmediatePropagation()
|
||||
evt.stopPropagation()
|
||||
evt.preventDefault()
|
||||
},
|
||||
viewCD(taskId) {
|
||||
this.$emit('previewCD', taskId)
|
||||
},
|
||||
setWwwcIdx(idx) {
|
||||
this.wwwcIdx = idx
|
||||
},
|
||||
clickSlider(e) {
|
||||
const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.height = height
|
||||
let sliceIdx = Math.trunc(this.imageInfo.total * height / 100)
|
||||
sliceIdx = sliceIdx >= this.imageInfo.total ? this.imageInfo.total : sliceIdx < 0 ? 0 : sliceIdx
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
// viewport.setImageIdIndex(sliceIdx)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseup(e) {
|
||||
this.sliderInfo.isMove = false
|
||||
this.$emit('contentMouseup', e)
|
||||
},
|
||||
sliderMousedown(e) {
|
||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
||||
this.sliderInfo.oldM = e.clientY
|
||||
this.sliderInfo.isMove = true
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
sliderMousemove(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
const delta = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
|
||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
if (delta < 0) return
|
||||
if (delta > boxHeight) return
|
||||
const height = delta * 100 / boxHeight
|
||||
let sliceIdx = Math.trunc(this.imageInfo.total * height / 100)
|
||||
sliceIdx = sliceIdx >= this.imageInfo.total ? this.imageInfo.total - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
this.sliderInfo.height = height
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
// viewport.setImageIdIndex(sliceIdx)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseleave(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
this.sliderInfo.isMove = false
|
||||
},
|
||||
rotate(angle) {
|
||||
let renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
let viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const camera = viewport.getCamera()
|
||||
const { viewUp, position, focalPoint } = camera
|
||||
const [cx, cy, cz] = focalPoint
|
||||
const [ax, ay, az] = [0, 0, 1]
|
||||
const newPosition = [0, 0, 0]
|
||||
const newFocalPoint = [0, 0, 0]
|
||||
const newViewUp = [0, 0, 0]
|
||||
|
||||
const transform = mat4.identity(new Float32Array(16))
|
||||
mat4.translate(transform, transform, [cx, cy, cz])
|
||||
mat4.rotate(transform, transform, angle, [ax, ay, az])
|
||||
mat4.translate(transform, transform, [-cx, -cy, -cz])
|
||||
vec3.transformMat4(newPosition, position, transform)
|
||||
vec3.transformMat4(newFocalPoint, focalPoint, transform)
|
||||
|
||||
mat4.identity(transform)
|
||||
mat4.rotate(transform, transform, angle, [ax, ay, az])
|
||||
vec3.transformMat4(newViewUp, viewUp, transform)
|
||||
|
||||
viewport.setCamera({
|
||||
position: newPosition,
|
||||
viewUp: newViewUp,
|
||||
focalPoint: newFocalPoint
|
||||
})
|
||||
|
||||
viewport.render()
|
||||
},
|
||||
clickRotate(e) {
|
||||
// console.log('clickRotate')
|
||||
const container = document.getElementById('rotateBar')
|
||||
const containerWidth = container.offsetWidth
|
||||
const slider = document.getElementById('rotateSlider')
|
||||
const sliderWidth = slider.offsetWidth
|
||||
const x = Math.trunc(e.offsetX)
|
||||
const deltaX = x - this.rotateBarLeft
|
||||
const angle = Math.sin((deltaX * (360 / (containerWidth - sliderWidth))) * Math.PI / 180)
|
||||
this.rotate(angle)
|
||||
this.rotateBarLeft = x
|
||||
},
|
||||
preventDefault(e) {
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
NSTip() {
|
||||
return `NS: ${this.$store.state.trials.uploadTip}`
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.viewport-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
cursor: default !important;
|
||||
|
||||
.left-top-text {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
|
||||
.cd-info {
|
||||
// color: #ddd;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.subject-info {
|
||||
color: #f44336;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.top-center-tool {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
|
||||
.toggle-visit-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.arrw_icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
|
||||
.arrow_text {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding: 0 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-top-text {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.left-bottom-text {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
bottom: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.right-bottom-text {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.right-slider-box {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
height: calc(100% - 140px);
|
||||
transform: translateY(-50%);
|
||||
top: calc(50% - 30px);
|
||||
width: 10px;
|
||||
background: #333;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.right-slider-box:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
left: 0;
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.slider {
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background: #9e9e9e;
|
||||
cursor: move
|
||||
}
|
||||
|
||||
.orientation-top {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 30px;
|
||||
color: #f44336;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.orientation-bottom {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 15px;
|
||||
color: #f44336;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.orientation-left {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 15px;
|
||||
color: #f44336;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.orientation-right {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 15px;
|
||||
color: #f44336;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.color_bar {
|
||||
position: absolute;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: right;
|
||||
left: -150px;
|
||||
top: 30%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.rotate_slider_box {
|
||||
position: absolute;
|
||||
width: 380px;
|
||||
height: 10px;
|
||||
bottom: 5px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #333;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
|
||||
.box {
|
||||
z-index: 10;
|
||||
background: #9e9e9e;
|
||||
height: 100%;
|
||||
width: 20px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
cursor: move
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -162,7 +162,7 @@
|
|||
</div>
|
||||
<!-- MPR -->
|
||||
<div class="tool-item" :title="`${$t('trials:reading:button:mpr')}`" @click.prevent="openMPRViewport()"
|
||||
v-if="criterionType === 0 && readingTool === 0">
|
||||
v-if="(criterionType === 0 && readingTool === 0) || this.readingTool === 3">
|
||||
<svg-icon icon-class="mpr" class="svg-icon" style="transform: rotate(180deg);" />
|
||||
</div>
|
||||
<!-- 十字准星 -->
|
||||
|
|
@ -299,24 +299,29 @@
|
|||
<!-- viewports -->
|
||||
<div class="viewports-wrapper">
|
||||
<div ref="container" class="grid-container">
|
||||
<!-- isMPR && index === 2 ? 'grid-cell-3' : '', -->
|
||||
<div :class="['viewports-box', isFusion || isMPR ? 'viewports-box-down' : '']" :style="gridStyle">
|
||||
<div v-for="(v, index) in cellsMax" v-show="index < cells.length" :key="`viewport-${index}`"
|
||||
:style="cellStyle"
|
||||
:class="['grid-cell', isMPR && index === 2 ? 'grid-cell-3' : '', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
:class="['grid-cell', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
||||
<VolumeViewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
||||
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" v-if="readingTool === 3" />
|
||||
<Viewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
||||
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" />
|
||||
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" v-else />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="criterionType === 0 && readingTool === 0"
|
||||
:class="['viewports-box', !isMPR ? 'viewports-box-down' : '']" :style="gridStyle">
|
||||
<div v-for="(v, index) in 3" :key="`viewport-volume-${index}`" :style="cellStyle"
|
||||
:class="['grid-cell', isMPR && index === 0 ? 'grid-cell-3' : '', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
<div v-if="(criterionType === 0 && readingTool === 0) || readingTool === 3"
|
||||
:class="['viewports-box', !isMPR ? 'viewports-box-down' : '']" :style="gridStyleMPR">
|
||||
<div v-for="(v, index) in 3" :key="`viewport-MPR-${index}`" :style="cellStyle"
|
||||
:class="['grid-cell', index === 0 ? 'grid-cell-3' : '', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
||||
<VolumeViewport :ref="`viewport-volume-${index}`" :data-viewport-uid="`viewport-volume-${index}`"
|
||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-volume-${index}`"
|
||||
<MPRViewport :ref="`viewport-MPR-${index}`" :data-viewport-uid="`viewport-MPR-${index}`"
|
||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-MPR-${index}`"
|
||||
:viewport-index="index" :MPRInfo="MPRInfo" @activeViewport="activeViewport" @setMPRInfo="setMPRInfo"
|
||||
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" />
|
||||
|
|
@ -340,32 +345,59 @@
|
|||
</div>
|
||||
<!-- 表单 -->
|
||||
<div class="form-wrapper">
|
||||
<div v-for="s in visitTaskList" v-show="lastViewportTaskId === s.VisitTaskId" :key="s.VisitTaskId"
|
||||
style="height: 100%;">
|
||||
<mRecisit v-if="lastViewportTaskId && criterionType === 7 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @removeAnnotation="removeAnnotation"
|
||||
@getScreenshots="getScreenshots" @setMarkName="setMarkName" @imageLocation="imageLocation"
|
||||
@resetAnnotations="resetAnnotations" @getAnnotations="getAnnotations" @setToolToTarget="setToolToTarget"
|
||||
@handleReadingChart="handleReadingChart" @setReadingToolPassive="setReadingToolPassive" />
|
||||
<recisit
|
||||
v-else-if="lastViewportTaskId && criterionType === 1 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @removeAnnotation="removeAnnotation"
|
||||
@getScreenshots="getScreenshots" @setMarkName="setMarkName" @imageLocation="imageLocation"
|
||||
@resetAnnotations="resetAnnotations" @getAnnotations="getAnnotations" @setToolToTarget="setToolToTarget"
|
||||
@handleReadingChart="handleReadingChart" @setReadingToolPassive="setReadingToolPassive" />
|
||||
<customize-question-list
|
||||
v-else-if="lastViewportTaskId && criterionType === 0 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="taskInfo && currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @resetAnnotations="resetAnnotations"
|
||||
@setReadingTaskState="setReadingTaskState" @viewCustomAnnotationSeries="viewCustomAnnotationSeries"
|
||||
@getCustomScreenshots="getCustomScreenshots" @setReadingToolActive="setReadingToolActive"
|
||||
@setReadingToolPassive="setReadingToolPassive" @handleReadingChart="handleReadingChart" />
|
||||
</div>
|
||||
<el-tabs v-model="formWrapperActiveName" v-if="readingTool === 3" @tab-click="handleClick">
|
||||
<el-tab-pane :label="$t('trials:reading:dicom3D:tabs:ecrf')" name="ecrf">
|
||||
<div v-for="s in visitTaskList" v-show="lastViewportTaskId === s.VisitTaskId" :key="s.VisitTaskId"
|
||||
style="height: 100%;">
|
||||
<customize-question-list
|
||||
v-if="lastViewportTaskId && criterionType === 0 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="taskInfo && currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @resetAnnotations="resetAnnotations"
|
||||
@setReadingTaskState="setReadingTaskState" @viewCustomAnnotationSeries="viewCustomAnnotationSeries"
|
||||
@getCustomScreenshots="getCustomScreenshots" @setReadingToolActive="setReadingToolActive"
|
||||
@setReadingToolPassive="setReadingToolPassive" @handleReadingChart="handleReadingChart"
|
||||
@openSegmentForm="openSegmentForm" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('trials:reading:dicom3D:tabs:segment')" name="segment">
|
||||
<Segmentations ref="Segmentations" :visitInfo="taskInfo" :isMPR="isMPR"
|
||||
:volumeToolGroupId="volumeToolGroupId" :viewportKey="viewportKey"
|
||||
:activeViewportIndex="activeViewportIndex" :activeTool.sync="activeTool"
|
||||
:actionConfiguration="actionConfiguration" @setToolsPassive="setToolsPassive" @resetQuestion="resetQuestion"/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template v-else>
|
||||
<div v-for="s in visitTaskList" v-show="lastViewportTaskId === s.VisitTaskId" :key="s.VisitTaskId"
|
||||
style="height: 100%;">
|
||||
<mRecisit
|
||||
v-if="lastViewportTaskId && criterionType === 7 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @removeAnnotation="removeAnnotation"
|
||||
@getScreenshots="getScreenshots" @setMarkName="setMarkName" @imageLocation="imageLocation"
|
||||
@resetAnnotations="resetAnnotations" @getAnnotations="getAnnotations"
|
||||
@setToolToTarget="setToolToTarget" @handleReadingChart="handleReadingChart"
|
||||
@setReadingToolPassive="setReadingToolPassive" />
|
||||
<recisit
|
||||
v-else-if="lastViewportTaskId && criterionType === 1 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @removeAnnotation="removeAnnotation"
|
||||
@getScreenshots="getScreenshots" @setMarkName="setMarkName" @imageLocation="imageLocation"
|
||||
@resetAnnotations="resetAnnotations" @getAnnotations="getAnnotations"
|
||||
@setToolToTarget="setToolToTarget" @handleReadingChart="handleReadingChart"
|
||||
@setReadingToolPassive="setReadingToolPassive" />
|
||||
<customize-question-list
|
||||
v-else-if="lastViewportTaskId && criterionType === 0 && lastViewportTaskIds.includes(s.VisitTaskId)"
|
||||
:ref="`ecrf_${s.VisitTaskId}`"
|
||||
:reading-task-state="taskInfo && currentVisitInfo.VisitTaskId === taskInfo.VisitTaskId ? readingTaskState : 2"
|
||||
:last-viewport-task-id="lastViewportTaskId" :visit-info="s" @resetAnnotations="resetAnnotations"
|
||||
@setReadingTaskState="setReadingTaskState" @viewCustomAnnotationSeries="viewCustomAnnotationSeries"
|
||||
@getCustomScreenshots="getCustomScreenshots" @setReadingToolActive="setReadingToolActive"
|
||||
@setReadingToolPassive="setReadingToolPassive" @handleReadingChart="handleReadingChart" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -444,6 +476,11 @@
|
|||
@close="closeFusion" @fusion="handleFusion" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :visible.sync="segmentVisible" :close-on-click-modal="false" :title="$t('trials:segment:title:bind')"
|
||||
width="550px">
|
||||
<SegmentForm v-if="segmentVisible" :visible.sync="segmentVisible" :visitInfo="segmentVisitInfo"
|
||||
@handleSegmentSave="handleSegmentSave" />
|
||||
</el-dialog>
|
||||
<upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId"
|
||||
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible"
|
||||
:visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
|
||||
|
|
@ -479,7 +516,9 @@ import { getTools, getCustomizeStandardsTools, config } from './toolConfig'
|
|||
import StudyList from './StudyList'
|
||||
import Viewport from './Viewport'
|
||||
import PetCtViewport from './PetCtViewport'
|
||||
import MPRViewport from './MPRViewport'
|
||||
import VolumeViewport from './VolumeViewport'
|
||||
import Segmentations from './Segmentations'
|
||||
import mRecisit from './mRecist/QuestionList'
|
||||
import recisit from './Recist/QuestionList'
|
||||
import customizeQuestionList from './customize/QuestionList'
|
||||
|
|
@ -491,6 +530,7 @@ import WL from '@/views/trials/trials-panel/reading/dicoms/components/WL'
|
|||
import Others from '@/views/trials/trials-panel/reading/dicoms/components/Others'
|
||||
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
||||
import FusionForm from './FusionForm.vue'
|
||||
import SegmentForm from './SegmentForm.vue'
|
||||
import colorMap from './colorMap.vue'
|
||||
import RectangleROITool from './tools/RectangleROITool'
|
||||
import ScaleOverlayTool from './tools/ScaleOverlayTool'
|
||||
|
|
@ -527,7 +567,10 @@ const {
|
|||
VolumeRotateTool,
|
||||
CrosshairsTool,
|
||||
EllipticalROITool,
|
||||
synchronizers
|
||||
synchronizers,
|
||||
PlanarFreehandContourSegmentationTool,
|
||||
BrushTool,
|
||||
utilities: CStUtils,
|
||||
// cursors
|
||||
} = cornerstoneTools
|
||||
const { createCameraPositionSynchronizer, createVOISynchronizer, createSlabThicknessSynchronizer } = synchronizers
|
||||
|
|
@ -562,7 +605,9 @@ export default {
|
|||
StudyList,
|
||||
Viewport,
|
||||
PetCtViewport,
|
||||
MPRViewport,
|
||||
VolumeViewport,
|
||||
Segmentations,
|
||||
mRecisit,
|
||||
recisit,
|
||||
customizeQuestionList,
|
||||
|
|
@ -573,6 +618,7 @@ export default {
|
|||
Others,
|
||||
ClinicalData,
|
||||
FusionForm,
|
||||
SegmentForm,
|
||||
colorMap,
|
||||
downloadDicomAndNonedicom,
|
||||
uploadDicomAndNonedicom,
|
||||
|
|
@ -687,6 +733,24 @@ export default {
|
|||
SAGITTAL: {
|
||||
imageNum: 0
|
||||
},
|
||||
},
|
||||
|
||||
segmentVisible: false,
|
||||
segmentVisitInfo: {},
|
||||
formWrapperActiveName: 'ecrf',
|
||||
actionConfiguration: {
|
||||
contourBidirectional: {
|
||||
method: CStUtils.segmentation.segmentContourAction,
|
||||
bindings: [
|
||||
{
|
||||
key: 'c',
|
||||
},
|
||||
],
|
||||
data: {
|
||||
segmentData: new Map(),
|
||||
segmentationId: null
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -694,8 +758,17 @@ export default {
|
|||
gridStyle() {
|
||||
return {
|
||||
display: 'grid',
|
||||
gridTemplateRows: `repeat(${this.isMPR ? 2 : this.rows}, 1fr)`,
|
||||
gridTemplateColumns: `repeat(${this.isMPR ? 2 : this.cols}, 1fr)`,
|
||||
gridTemplateRows: `repeat(${this.rows}, 1fr)`,
|
||||
gridTemplateColumns: `repeat(${this.cols}, 1fr)`,
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
}
|
||||
},
|
||||
gridStyleMPR() {
|
||||
return {
|
||||
display: 'grid',
|
||||
gridTemplateRows: `repeat(2, 1fr)`,
|
||||
gridTemplateColumns: `repeat(2, 1fr)`,
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
}
|
||||
|
|
@ -712,11 +785,11 @@ export default {
|
|||
return Array(this.rows * this.cols).fill(0)
|
||||
},
|
||||
viewportKey() {
|
||||
return this.isMPR ? 'viewport-volume' : this.isFusion ? 'viewport-fusion' : 'viewport'
|
||||
return this.isMPR ? 'viewport-MPR' : this.isFusion ? 'viewport-fusion' : 'viewport'
|
||||
},
|
||||
openManuals() {
|
||||
return !this.taskInfo.IsReadKeyFile && this.taskInfo.IsHaveKeyFile
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
openManuals: {
|
||||
|
|
@ -787,7 +860,7 @@ export default {
|
|||
} else {
|
||||
this.tools = getTools(this.criterionType)
|
||||
}
|
||||
|
||||
console.log(toolsEvents, 'toolsEvents')
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.readingTaskState = this.taskInfo.ReadingTaskState
|
||||
if (!this.taskInfo.IsBaseLine && this.taskInfo.IsReadingTaskViewInOrder !== 0) {
|
||||
|
|
@ -816,6 +889,20 @@ export default {
|
|||
this.getSystemInfoReading();
|
||||
},
|
||||
methods: {
|
||||
resetQuestion(){
|
||||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].getQuestions(false)
|
||||
},
|
||||
handleSegmentSave(obj) {
|
||||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].handleSegmentSave(obj)
|
||||
},
|
||||
openSegmentForm(obj) {
|
||||
let { visitInfo } = obj
|
||||
this.segmentVisitInfo = visitInfo
|
||||
this.segmentVisible = true
|
||||
},
|
||||
handleClick(tab, event) {
|
||||
this.formWrapperActiveName = tab.name
|
||||
},
|
||||
setMPRInfo(obj) {
|
||||
let { type, key, value } = obj
|
||||
this.$set(this.MPRInfo[type], key, value)
|
||||
|
|
@ -1071,7 +1158,7 @@ export default {
|
|||
}
|
||||
let viewportIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3']
|
||||
const fusionViewportIds = ['viewport-fusion-0', 'viewport-fusion-1', 'viewport-fusion-2', 'viewport-fusion-3']
|
||||
const volumeViewportIds = ['viewport-volume-0', 'viewport-volume-1', 'viewport-volume-2']
|
||||
const volumeViewportIds = ['viewport-MPR-0', 'viewport-MPR-1', 'viewport-MPR-2']
|
||||
const element1 = this.$refs['viewport-0'][0].$el
|
||||
const element2 = this.$refs['viewport-1'][0].$el
|
||||
const element3 = this.$refs['viewport-2'][0].$el
|
||||
|
|
@ -1098,13 +1185,49 @@ export default {
|
|||
element: element4
|
||||
}
|
||||
]
|
||||
if (this.criterionType === 0 && this.readingTool === 0) {
|
||||
const volumeElement1 = this.$refs['viewport-volume-0'][0].$el
|
||||
const volumeElement2 = this.$refs['viewport-volume-1'][0].$el
|
||||
const volumeElement3 = this.$refs['viewport-volume-2'][0].$el
|
||||
if (this.readingTool === 3) {
|
||||
viewportInputArray = [
|
||||
{
|
||||
viewportId: 'viewport-0',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: element1,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL
|
||||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-1',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: element2,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL
|
||||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-2',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: element3,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL
|
||||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-3',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: element4,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
if ((this.criterionType === 0 && this.readingTool === 0) || this.readingTool === 3) {
|
||||
const volumeElement1 = this.$refs['viewport-MPR-0'][0].$el
|
||||
const volumeElement2 = this.$refs['viewport-MPR-1'][0].$el
|
||||
const volumeElement3 = this.$refs['viewport-MPR-2'][0].$el
|
||||
const arr = [
|
||||
{
|
||||
viewportId: 'viewport-volume-0',
|
||||
viewportId: 'viewport-MPR-0',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: volumeElement1,
|
||||
defaultOptions: {
|
||||
|
|
@ -1112,7 +1235,7 @@ export default {
|
|||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-volume-1',
|
||||
viewportId: 'viewport-MPR-1',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: volumeElement2,
|
||||
defaultOptions: {
|
||||
|
|
@ -1120,7 +1243,7 @@ export default {
|
|||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-volume-2',
|
||||
viewportId: 'viewport-MPR-2',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: volumeElement3,
|
||||
defaultOptions: {
|
||||
|
|
@ -1198,14 +1321,14 @@ export default {
|
|||
cornerstoneTools.addTool(MIPJumpToClickTool)
|
||||
cornerstoneTools.addTool(VolumeRotateTool)
|
||||
cornerstoneTools.addTool(CrosshairsTool)
|
||||
|
||||
cornerstoneTools.addTool(PlanarFreehandContourSegmentationTool)
|
||||
cornerstoneTools.addTool(BrushTool)
|
||||
viewportIds.forEach((viewportId, i) => {
|
||||
// const toolGroupId = `viewport-${i}`
|
||||
let toolGroupId = viewportId
|
||||
if (volumeViewportIds.includes(viewportId)) {
|
||||
toolGroupId = this.volumeToolGroupId
|
||||
}
|
||||
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) ? ToolGroupManager.getToolGroup(toolGroupId) : ToolGroupManager.createToolGroup(toolGroupId)
|
||||
toolGroup.addViewport(viewportId, renderingEngineId)
|
||||
toolGroup.addTool(StackScrollTool.toolName, {
|
||||
|
|
@ -1215,6 +1338,44 @@ export default {
|
|||
|
||||
toolGroup.addTool(PanTool.toolName)
|
||||
toolGroup.addTool(ZoomTool.toolName)
|
||||
toolGroup.addTool(BrushTool.toolName)
|
||||
if (this.readingTool === 3 || toolGroupId === this.volumeToolGroupId) {
|
||||
toolGroup.addToolInstance(
|
||||
'CircularBrush',
|
||||
BrushTool.toolName,
|
||||
{
|
||||
activeStrategy: 'FILL_INSIDE_CIRCLE',
|
||||
preview: {
|
||||
previewColors: {}
|
||||
}
|
||||
}
|
||||
);
|
||||
toolGroup.addToolInstance(
|
||||
'CircularEraser',
|
||||
BrushTool.toolName,
|
||||
{
|
||||
activeStrategy: 'ERASE_INSIDE_CIRCLE',
|
||||
preview: {
|
||||
previewColors: {}
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
toolGroup.addTool(PlanarFreehandContourSegmentationTool.toolName, {
|
||||
cachedStats: true,
|
||||
});
|
||||
// toolGroup.setToolActive(PlanarFreehandContourSegmentationTool.toolName, {
|
||||
// bindings: [
|
||||
// {
|
||||
// mouseButton: MouseBindings.Primary, // Left Click
|
||||
// },
|
||||
// {
|
||||
// mouseButton: MouseBindings.Primary, // Shift + Left Click
|
||||
// modifierKey: cornerstoneTools.Enums.KeyboardBindings.Shift,
|
||||
// },
|
||||
// ],
|
||||
// });
|
||||
}
|
||||
if (volumeViewportIds.includes(viewportId)) {
|
||||
toolGroup.addTool(WindowLevelTool.toolName, {
|
||||
targetViewportIds: volumeViewportIds
|
||||
|
|
@ -1251,7 +1412,8 @@ export default {
|
|||
// cachedStats: false
|
||||
})
|
||||
toolGroup.addTool(BidirectionalTool.toolName, {
|
||||
// cachedStats: true
|
||||
// cachedStats: true,
|
||||
actions: this.actionConfiguration,
|
||||
getTextLines: this.getBidirectionalToolTextLines
|
||||
})
|
||||
toolGroup.addTool(CircleROITool.toolName, {
|
||||
|
|
@ -1308,9 +1470,6 @@ export default {
|
|||
toolGroup.setToolActive(PanTool.toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Auxiliary }]
|
||||
})
|
||||
// toolGroup.setToolEnabled(ScaleOverlayTool.toolName);
|
||||
// toolGroup.setToolPassive(PanTool.toolName)
|
||||
// toolGroup.setToolPassive(ZoomTool.toolName)
|
||||
toolGroup.setToolPassive(WindowLevelTool.toolName)
|
||||
toolGroup.setToolPassive(WindowLevelRegionTool.toolName)
|
||||
toolGroup.setToolPassive(PlanarRotateTool.toolName)
|
||||
|
|
@ -1326,6 +1485,7 @@ export default {
|
|||
toolGroup.setToolPassive(FixedRadiusCircleROITool.toolName)
|
||||
toolGroup.setToolPassive(AngleTool.toolName)
|
||||
toolGroup.setToolPassive(CobbAngleTool.toolName)
|
||||
if (this.readingTool === 3) toolGroup.setToolPassive(PlanarFreehandContourSegmentationTool.toolName)
|
||||
} else {
|
||||
toolGroup.setToolEnabled(ArrowAnnotateTool.toolName)
|
||||
toolGroup.setToolEnabled(RectangleROITool.toolName)
|
||||
|
|
@ -1337,6 +1497,7 @@ export default {
|
|||
toolGroup.setToolEnabled(FixedRadiusCircleROITool.toolName)
|
||||
toolGroup.setToolEnabled(AngleTool.toolName)
|
||||
toolGroup.setToolEnabled(CobbAngleTool.toolName)
|
||||
if (this.readingTool === 3) toolGroup.setToolEnabled(PlanarFreehandContourSegmentationTool.toolName)
|
||||
}
|
||||
toolGroup.setToolPassive(EraserTool.toolName)
|
||||
})
|
||||
|
|
@ -1346,7 +1507,7 @@ export default {
|
|||
if (this.readingTool === 2) {
|
||||
this.setUpSynchronizers()
|
||||
}
|
||||
if (this.criterionType === 0 && this.readingTool === 0) {
|
||||
if ((this.criterionType === 0 && this.readingTool === 0) || this.readingTool === 3) {
|
||||
this.setUpSynchronizersMPR()
|
||||
}
|
||||
},
|
||||
|
|
@ -1500,7 +1661,6 @@ export default {
|
|||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].setAnnotation({ annotation, toolName: annotation.metadata.toolName })
|
||||
this.markedSeriesIds.push(series.Id)
|
||||
}
|
||||
|
||||
this.setToolsPassive()
|
||||
},
|
||||
annotationModifiedListener(e) {
|
||||
|
|
@ -1516,6 +1676,7 @@ export default {
|
|||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].modifyAnnotation({ annotation, toolName: annotation.metadata.toolName })
|
||||
}
|
||||
this.setToolsPassive()
|
||||
|
||||
},
|
||||
annotationRemovedListener(e) {
|
||||
const { annotation } = e.detail
|
||||
|
|
@ -1552,9 +1713,10 @@ export default {
|
|||
if (!annotation) return
|
||||
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
||||
if (i === -1) {
|
||||
this.setToolsPassive()
|
||||
if (annotation.metadata.toolName !== PlanarFreehandContourSegmentationTool.toolName) this.setToolsPassive()
|
||||
return
|
||||
}
|
||||
if (annotation.data.segmentation || annotation.data.segment) return
|
||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
|
|
@ -1593,7 +1755,6 @@ export default {
|
|||
// }
|
||||
}
|
||||
}
|
||||
|
||||
this.setToolsPassive()
|
||||
},
|
||||
validMarkName(markName) {
|
||||
|
|
@ -1639,9 +1800,10 @@ export default {
|
|||
if (!annotation) return
|
||||
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
||||
if (i === -1) {
|
||||
this.setToolsPassive()
|
||||
if (annotation.metadata.toolName !== PlanarFreehandContourSegmentationTool.toolName) this.setToolsPassive()
|
||||
return
|
||||
}
|
||||
if (annotation.data.segmentation || annotation.data.segment) return
|
||||
if (!annotation.data.label) return
|
||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
|
|
@ -1672,6 +1834,7 @@ export default {
|
|||
// 临时标记
|
||||
return
|
||||
}
|
||||
if (annotation.data.segmentation || annotation.data.segment) return
|
||||
if (annotation.visitTaskId === this.taskInfo.VisitTaskId) {
|
||||
const isBound = this.$refs[`ecrf_${annotation.visitTaskId}`][0].verifyAnnotationIsBound(annotation)
|
||||
if (isBound && this.activeTool === 'Eraser') {
|
||||
|
|
@ -1724,6 +1887,9 @@ export default {
|
|||
},
|
||||
contentMouseup(e) {
|
||||
console.log('contentMouseup')
|
||||
if (this.$refs.Segmentations) {
|
||||
this.$refs.Segmentations.contentMouseup()
|
||||
}
|
||||
if (this.curOperation.type === 'Modified') {
|
||||
let annotation = this.curOperation.annotation
|
||||
this.saveCustomAnnotation(annotation)
|
||||
|
|
@ -2270,6 +2436,7 @@ export default {
|
|||
if (!obj.isCanActiveTool) {
|
||||
if (this.activeTool === toolName) {
|
||||
this.setToolsPassive()
|
||||
|
||||
}
|
||||
this.tools[i].isDisabled = true
|
||||
e.target.style.cursor = 'not-allowed'
|
||||
|
|
@ -2282,6 +2449,7 @@ export default {
|
|||
// 旋转视口
|
||||
setViewportRotate(value) {
|
||||
this.setToolsPassive()
|
||||
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
|
|
@ -2620,6 +2788,7 @@ export default {
|
|||
this.cols = 1
|
||||
this.activeViewportIndex = 0
|
||||
this.setToolsPassive()
|
||||
|
||||
}
|
||||
if (taskIndex === this.activeTaskIndex) return
|
||||
if (!this.selectArr.includes(taskInfo.VisitTaskId)) {
|
||||
|
|
@ -2865,13 +3034,23 @@ export default {
|
|||
const i = this.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
|
||||
if (i === -1) return
|
||||
const studyList = this.visitTaskList[i].StudyList
|
||||
let series = this.getMarkedSeries(studyList, obj.annotation, true)
|
||||
let series = null
|
||||
if (obj.segment) {
|
||||
let study = studyList.find(item => item.StudyId === obj.segmentGroup.StudyId)
|
||||
series = study.SeriesList.find(item => item.Id === obj.segmentGroup.SeriesId)
|
||||
let sliceIndex = obj.segment.bidirectional.sliceIndex || 0
|
||||
series.SliceIndex = series.InstanceCount - 1 - sliceIndex
|
||||
series.segment = obj.segment
|
||||
} else {
|
||||
series = this.getMarkedSeries(studyList, obj.annotation, true)
|
||||
}
|
||||
|
||||
if (series) {
|
||||
if (this.isFusion && series.SeriesInstanceUid !== this.fusionSerieId.ct && series.SeriesInstanceUid !== this.fusionSerieId.pt) {
|
||||
return await this.$confirm(this.$t('trials:reading:confirm:fusionPTOrCTInconsistent'))
|
||||
}
|
||||
this.activeViewportIndex = this.cells.length - 1
|
||||
if (obj.annotation.from === 'MPR') {
|
||||
if (obj.annotation && obj.annotation.from === 'MPR') {
|
||||
let viewPlaneNormal = obj.annotation?.metadata?.viewPlaneNormal.map(i => i == 0 ? 0 : i).join(',')
|
||||
if (viewPlaneNormal === '0,0,-1') {
|
||||
this.activeViewportIndex = 0
|
||||
|
|
@ -2906,7 +3085,7 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series, true)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series, obj.segment ? false : true)
|
||||
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
|
||||
}
|
||||
},
|
||||
|
|
@ -3087,7 +3266,6 @@ export default {
|
|||
if (obj.isActiveTarget && obj.SplitOrMergeType !== '1' && obj.SplitOrMergeType !== '3') {
|
||||
this.setToolToTarget(obj)
|
||||
}
|
||||
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
|
|
@ -3097,6 +3275,7 @@ export default {
|
|||
const toolName = obj.markTool
|
||||
if (this.activeTool) {
|
||||
this.setToolsPassive()
|
||||
|
||||
}
|
||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
|
|
@ -3317,9 +3496,9 @@ export default {
|
|||
syncColormap: false
|
||||
})
|
||||
let viewportIds = [
|
||||
`viewport-volume-0`,
|
||||
`viewport-volume-1`,
|
||||
`viewport-volume-2`
|
||||
`viewport-MPR-0`,
|
||||
`viewport-MPR-1`,
|
||||
`viewport-MPR-2`
|
||||
]
|
||||
viewportIds.forEach((viewportId) => {
|
||||
MPRVoiSynchronizer.add({
|
||||
|
|
@ -3331,9 +3510,9 @@ export default {
|
|||
|
||||
// Add viewports to VOI synchronizers
|
||||
[
|
||||
`viewport-volume-0`,
|
||||
`viewport-volume-1`,
|
||||
`viewport-volume-2`
|
||||
`viewport-MPR-0`,
|
||||
`viewport-MPR-1`,
|
||||
`viewport-MPR-2`
|
||||
].forEach((viewportId) => {
|
||||
synchronizer.add({
|
||||
renderingEngineId: this.renderingEngineId,
|
||||
|
|
@ -3360,7 +3539,7 @@ export default {
|
|||
return new Promise(async (resolve, reject) => {
|
||||
if (this.isMPR) {
|
||||
if (!data) return resolve(false)
|
||||
let viewportSeries = this.$refs[`viewport-volume-0`][0].series
|
||||
let viewportSeries = this.$refs[`viewport-MPR-0`][0].series
|
||||
if (data && viewportSeries.SeriesInstanceUid === data.SeriesInstanceUid) return resolve(true)
|
||||
}
|
||||
if (!data) {
|
||||
|
|
@ -3378,8 +3557,8 @@ export default {
|
|||
if (!res) return false
|
||||
}
|
||||
this.isMPR = true
|
||||
this.rows = 3
|
||||
this.cols = 1
|
||||
// this.rows = 3
|
||||
// this.cols = 1
|
||||
this.loading = true
|
||||
this.loadingText = this.$t('trials:lugano:message:loadVolumes')
|
||||
if (!data) this.activeViewportIndex = 0
|
||||
|
|
@ -3388,9 +3567,9 @@ export default {
|
|||
await this.getVolume(series)
|
||||
this.loading = false
|
||||
this.loadingText = null
|
||||
this.$refs[`viewport-volume-0`][0].setSeriesInfo(Object.assign({ orientation: 'AXIAL', isLocation: data && this.activeViewportIndex === 0 }, series))
|
||||
this.$refs[`viewport-volume-1`][0].setSeriesInfo(Object.assign({ orientation: 'SAGITTAL', isLocation: data && this.activeViewportIndex === 1 }, series))
|
||||
this.$refs[`viewport-volume-2`][0].setSeriesInfo(Object.assign({ orientation: 'CORONAL', isLocation: data && this.activeViewportIndex === 2 }, series))
|
||||
this.$refs[`viewport-MPR-0`][0].setSeriesInfo(Object.assign({ orientation: 'AXIAL', isLocation: data && this.activeViewportIndex === 0 }, series))
|
||||
this.$refs[`viewport-MPR-1`][0].setSeriesInfo(Object.assign({ orientation: 'SAGITTAL', isLocation: data && this.activeViewportIndex === 1 }, series))
|
||||
this.$refs[`viewport-MPR-2`][0].setSeriesInfo(Object.assign({ orientation: 'CORONAL', isLocation: data && this.activeViewportIndex === 2 }, series))
|
||||
resolve(false)
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,193 @@
|
|||
<template>
|
||||
<el-form ref="segmentForm" :model="form" label-width="120px" label-position="left">
|
||||
<!-- 检查名称 -->
|
||||
<el-form-item :label="$t('segment:form:label:studyName')" prop="taskBlindName">
|
||||
<el-select v-model="form.studyId" clearable @change="(e) => handleChange(e, 'study')">
|
||||
<el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode"
|
||||
:value="item.StudyId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 序列名称 -->
|
||||
<el-form-item :label="$t('segment:form:label:seriesName')" prop="taskBlindName">
|
||||
<el-select v-model="form.seriesId" clearable @change="(e) => handleChange(e, 'series')">
|
||||
<el-option v-for="item in seriesList" :key="item.Id"
|
||||
:label="`#${item.SeriesNumber}/${item.Modality}/${item.Description}`" :value="item.Id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 分割组名称 -->
|
||||
<el-form-item :label="$t('segment:form:label:segmentGroupName')" prop="taskBlindName">
|
||||
<el-select v-model="form.segmentGroupId" clearable @change="(e) => handleChange(e, 'segmentGroup')">
|
||||
<el-option v-for="item in segmentGroupList" :key="item.Id" :label="item.SegmentationName"
|
||||
:value="item.Id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 分割名称 -->
|
||||
<el-form-item :label="$t('segment:form:label:segmentName')" prop="taskBlindName">
|
||||
<el-select v-model="form.segmentId" clearable>
|
||||
<el-option v-for="item in segmentList" :key="item.Id" :label="item.SegmentName" :value="item.Id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item style="text-align:right;">
|
||||
<!-- 取消 -->
|
||||
<el-button size="mini" @click="handleCancel">{{ $t('common:button:cancel') }}</el-button>
|
||||
<!-- 确认 -->
|
||||
<el-button type="primary" size="mini" @click="handleSave">
|
||||
{{ $t('common:button:confirm') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { getSegmentationList, getSegmentList } from '@/api/reading'
|
||||
export default {
|
||||
name: 'FusionForm',
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
visitInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
studyId: '',
|
||||
seriesId: '',
|
||||
segmentGroupId: '',
|
||||
segmentId: ""
|
||||
},
|
||||
studyList: [],
|
||||
seriesList: [],
|
||||
segmentGroupList: [],
|
||||
segmentList: [],
|
||||
segmentionList: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
async init() {
|
||||
let studyList = this.visitInfo.StudyList
|
||||
let s = await this.getSegmentationList()
|
||||
this.segmentionList = s
|
||||
let StudyIds = s.map(item => item.StudyId)
|
||||
let SeriesIds = s.map(item => item.SeriesId)
|
||||
studyList = studyList.filter(item => StudyIds.includes(item.StudyId))
|
||||
studyList.forEach(study => {
|
||||
study.SeriesList = study.SeriesList.filter(item => SeriesIds.includes(item.Id))
|
||||
})
|
||||
this.studyList = studyList
|
||||
},
|
||||
async handleChange(e, key) {
|
||||
if (key === 'study') {
|
||||
this.seriesList = this.studyList.find(item => item.StudyId === this.form.studyId).SeriesList
|
||||
}
|
||||
if (key === 'series') {
|
||||
this.segmentGroupList = this.segmentionList.filter(item => item.SeriesId === this.form.seriesId)
|
||||
}
|
||||
if (key === 'segmentGroup') {
|
||||
let list = await this.getSegmentList(this.form.segmentGroupId)
|
||||
this.segmentList = list.filter(item => item.SegmentJson)
|
||||
}
|
||||
},
|
||||
handleCancel() {
|
||||
this.$emit("update:visible", false)
|
||||
},
|
||||
handleSave() {
|
||||
let segment = this.segmentList.find(item => item.Id === this.form.segmentId)
|
||||
if (segment.SegmentJson) {
|
||||
let obj = JSON.parse(segment.SegmentJson)
|
||||
segment.stats = obj.stats
|
||||
segment.bidirectional = obj.bidirectional
|
||||
}
|
||||
this.$emit('handleSegmentSave', segment)
|
||||
this.handleCancel()
|
||||
},
|
||||
// 获取分割组
|
||||
async getSegmentationList() {
|
||||
try {
|
||||
let data = {
|
||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
||||
PageSize: 9999,
|
||||
PageIndex: 1,
|
||||
}
|
||||
this.loading = true;
|
||||
let res = await getSegmentationList(data);
|
||||
this.loading = false;
|
||||
if (res.IsSuccess) {
|
||||
return res.Result.CurrentPageData;
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 获取分割
|
||||
async getSegmentList(id) {
|
||||
try {
|
||||
let data = {
|
||||
SegmentationId: id,
|
||||
PageSize: 9999,
|
||||
PageIndex: 1,
|
||||
}
|
||||
this.loading = true;
|
||||
let res = await getSegmentList(data)
|
||||
this.loading = false;
|
||||
if (res.IsSuccess) {
|
||||
return res.Result.CurrentPageData
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.series-table {
|
||||
::v-deep.el-table {
|
||||
background-color: #1e1e1e !important;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
|
||||
::v-deep.el-table td.el-table__cell,
|
||||
.el-table th.el-table__cell.is-leaf {
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
}
|
||||
|
||||
.el-table--border::after,
|
||||
.el-table--group::after,
|
||||
.el-table::before {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
::v-deep.el-table__header-wrapper {
|
||||
th {
|
||||
background-color: #1e1e1e !important;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.el-table__body-wrapper {
|
||||
tr {
|
||||
background-color: #1e1e1e !important;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
|
||||
tr:hover>td {
|
||||
background-color: #1e1e1e !important;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.el-table__empty-block {
|
||||
background-color: #1e1e1e !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,16 +1,10 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="study-wrapper">
|
||||
<div class="study-info">
|
||||
<div
|
||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
|
||||
:title="taskInfo.SubjectCode"
|
||||
>
|
||||
<div v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo" :title="taskInfo.SubjectCode">
|
||||
{{ taskInfo.SubjectCode }}
|
||||
</div>
|
||||
<div
|
||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
|
||||
:title="visitTaskInfo.TaskBlindName"
|
||||
>
|
||||
<div v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo" :title="visitTaskInfo.TaskBlindName">
|
||||
{{ visitTaskInfo.TaskBlindName }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -18,15 +12,14 @@
|
|||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
||||
<template slot="title">
|
||||
<div
|
||||
v-if="!study.IsCriticalSequence"
|
||||
class="dicom-desc"
|
||||
>
|
||||
<div v-if="!study.IsCriticalSequence" class="dicom-desc">
|
||||
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
||||
<span v-if="study.StudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName }}</span>
|
||||
<span v-else :title="study.Modalities" style="margin-left: 5px;">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
<span v-if="study.StudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName
|
||||
}}</span>
|
||||
<span v-else :title="study.Modalities" style="margin-left: 5px;">{{ `${study.Modalities}
|
||||
(${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
<div v-if="study.StudyName" style="text-overflow: ellipsis;overflow: hidden;">
|
||||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
|
|
@ -46,53 +39,38 @@
|
|||
</div>
|
||||
</template>
|
||||
<div class="dicom-list-container">
|
||||
<div
|
||||
v-for="(series, i) in study.SeriesList"
|
||||
:key="series.Id"
|
||||
style="position:relative;margin-top:1px;"
|
||||
@click="activeSeries(series, i, index)"
|
||||
>
|
||||
<div
|
||||
:class="{'series-active': index === activeStudyIndex && i === activeSeriesIndex}"
|
||||
class="series-wrapper"
|
||||
>
|
||||
<div v-for="(series, i) in study.SeriesList" :key="series.Id" style="position:relative;margin-top:1px;"
|
||||
@click="activeSeries(series, i, index)">
|
||||
<div :class="{ 'series-active': index === activeStudyIndex && i === activeSeriesIndex }"
|
||||
class="series-wrapper">
|
||||
<div class="series-image">
|
||||
<el-image
|
||||
style="width: 100%;height: 100%;"
|
||||
<el-image style="width: 100%;height: 100%;"
|
||||
:src="`${OSSclientConfig.basePath}${series.ImageResizePath || series.NoneDicomFileFirstFile}`"
|
||||
fit="fill"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
fit="fill" crossorigin="anonymous" />
|
||||
</div>
|
||||
<div class="series-text">
|
||||
<div v-if="series.IsExistMutiFrames && series.InstanceCount > 1"
|
||||
style="position: absolute;right: 0;top: 0;">
|
||||
<el-popover
|
||||
placement="right"
|
||||
trigger="hover"
|
||||
popper-class="instance_frame_wrapper"
|
||||
>
|
||||
<div v-if="series.IsExistMutiFrames && series.InstanceCount > 1"
|
||||
style="position: absolute;right: 0;top: 0;">
|
||||
<el-popover placement="right" trigger="hover" popper-class="instance_frame_wrapper">
|
||||
<div class="frame_list">
|
||||
<div
|
||||
v-for="(instance, idx) in series.InstanceInfoList"
|
||||
:key="instance.Id"
|
||||
class="frame_content"
|
||||
:style="{'margin-bottom':idx<series.InstanceInfoList.length-1? '5px':'0px'}"
|
||||
@click.stop="showMultiFrames(index,series, i, instance)"
|
||||
>
|
||||
<div v-for="(instance, idx) in series.InstanceInfoList" :key="instance.Id" class="frame_content"
|
||||
:style="{ 'margin-bottom': idx < series.InstanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||
@click.stop="showMultiFrames(index, series, i, instance)">
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ?
|
||||
instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;color: #ffeb3b;" />
|
||||
<i slot="reference" class="el-icon-connection"
|
||||
style="font-size: 15px;cursor: pointer;color: #ffeb3b;" />
|
||||
</el-popover>
|
||||
</div>
|
||||
<div v-if="!study.IsCriticalSequence" class="text-desc" :title="series.SeriesNumber">
|
||||
#{{ series.SeriesNumber }}
|
||||
|
||||
|
||||
</div>
|
||||
<div v-if="series.Description" class="text-desc" :title="series.Description">
|
||||
{{ series.Description }}
|
||||
|
|
@ -104,17 +82,19 @@
|
|||
<span v-show="series.LoadedImageCount < series.InstanceCount">
|
||||
{{ series.Modality }}: {{ series.LoadedImageCount }}/{{ series.InstanceCount }} image
|
||||
</span>
|
||||
<span v-show="series.LoadedImageCount >= series.InstanceCount">{{ series.Modality }}: {{ series.InstanceCount }} image</span>
|
||||
<span v-show="series.LoadedImageCount >= series.InstanceCount">{{ series.Modality }}: {{
|
||||
series.InstanceCount
|
||||
}} image</span>
|
||||
</div>
|
||||
<div style="line-height: 12px;">
|
||||
<i v-show="series.IsBeMark || markedSeriesIds.includes(series.Id)" class="el-icon-star-on" style="font-size: 12px;color: #ff5722;" />
|
||||
<i v-show="series.IsBeMark || markedSeriesIds.includes(series.Id)" class="el-icon-star-on"
|
||||
style="font-size: 12px;color: #ff5722;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series.LoadedImageCount > 0 && series.LoadedImageCount < series.InstanceCount" style="width: 100%;">
|
||||
<el-progress
|
||||
:percentage="parseInt((series.LoadedImageProgress / series.InstanceCount).toFixed(2))"
|
||||
/>
|
||||
<div v-if="series.LoadedImageCount > 0 && series.LoadedImageCount < series.InstanceCount"
|
||||
style="width: 100%;">
|
||||
<el-progress :percentage="parseInt((series.LoadedImageProgress / series.InstanceCount).toFixed(2))" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -124,6 +104,7 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
export default {
|
||||
name: 'StudyList',
|
||||
props: {
|
||||
|
|
@ -168,6 +149,7 @@ export default {
|
|||
this.activeStudyIndex = studyIndex
|
||||
this.activeSeriesIndex = seriesIndex
|
||||
this.$emit('activeSeries', series)
|
||||
DicomEvent.$emit('activeSeries', series)
|
||||
},
|
||||
activeStudy(id) {
|
||||
if (this.activeNames.indexOf(id) > -1) return
|
||||
|
|
@ -179,6 +161,7 @@ export default {
|
|||
const studyId = this.studyList[studyIndex].StudyId
|
||||
if (!studyId) return
|
||||
this.activeStudy(studyId)
|
||||
DicomEvent.$emit('activeSeries', this.studyList[studyIndex].SeriesList[this.activeSeriesIndex])
|
||||
},
|
||||
showMultiFrames(studyIndex, series, seriesIndex, instance) {
|
||||
let obj = Object.assign({}, series)
|
||||
|
|
@ -203,7 +186,7 @@ export default {
|
|||
obj.ImageIds = imageIds
|
||||
obj.SliceIndex = 0
|
||||
this.$emit('showMultiFrame', obj)
|
||||
|
||||
|
||||
},
|
||||
getPreviousOrNextSeries(type, series) {
|
||||
const seriseList = this.studyList.map(s => s.SeriesList).flat()
|
||||
|
|
@ -224,13 +207,14 @@ export default {
|
|||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.study-wrapper{
|
||||
width:100%;
|
||||
.study-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.study-info {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
|
|
@ -241,7 +225,8 @@ export default {
|
|||
background-color: #4c4c4c;
|
||||
height: 50px;
|
||||
}
|
||||
.dicom-desc{
|
||||
|
||||
.dicom-desc {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
|
|
@ -258,19 +243,23 @@ export default {
|
|||
touch-action: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.series-active {
|
||||
background-color: #607d8b!important;
|
||||
border: 1px solid #607d8b!important;
|
||||
background-color: #607d8b !important;
|
||||
border: 1px solid #607d8b !important;
|
||||
}
|
||||
::v-deep.el-progress__text{
|
||||
|
||||
::v-deep.el-progress__text {
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
.dicom-list-container{
|
||||
|
||||
.dicom-list-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
.series-wrapper {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
|
|
@ -279,21 +268,26 @@ export default {
|
|||
align-items: center;
|
||||
cursor: pointer;
|
||||
background-color: #3a3a3a;
|
||||
.el-progress__text{
|
||||
|
||||
.el-progress__text {
|
||||
display: none;
|
||||
}
|
||||
.el-progress-bar{
|
||||
padding-right:0px;
|
||||
|
||||
.el-progress-bar {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.series-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.series-text {
|
||||
flex: 1;
|
||||
padding-left: 5px;
|
||||
color: #ddd;
|
||||
position: relative;
|
||||
|
||||
.text-desc {
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
|
|
@ -306,27 +300,32 @@ export default {
|
|||
|
||||
}
|
||||
}
|
||||
::v-deep.el-collapse{
|
||||
|
||||
::v-deep.el-collapse {
|
||||
border: none;
|
||||
.el-collapse-item{
|
||||
background-color: #000!important;
|
||||
|
||||
.el-collapse-item {
|
||||
background-color: #000 !important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
.el-collapse-item__content{
|
||||
padding-bottom:0px;
|
||||
background-color: #000!important;
|
||||
|
||||
.el-collapse-item__content {
|
||||
padding-bottom: 0px;
|
||||
background-color: #000 !important;
|
||||
}
|
||||
.el-collapse-item__header{
|
||||
background-color: #000!important;
|
||||
|
||||
.el-collapse-item__header {
|
||||
background-color: #000 !important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
border-bottom-color: #5a5a5a;
|
||||
padding-left: 5px;
|
||||
// height: 50px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
::v-deep .el-progress-bar__inner{
|
||||
|
||||
::v-deep .el-progress-bar__inner {
|
||||
transition: width 0s ease;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,10 @@
|
|||
<div v-if="series" class="right-bottom-text">
|
||||
<div v-show="imageInfo.location">Location: {{
|
||||
`${Number(imageInfo.location).toFixed(digitPlaces)} mm`
|
||||
}}</div>
|
||||
}}</div>
|
||||
<div v-show="imageInfo.sliceThickness">Slice Thickness: {{
|
||||
`${Number(imageInfo.sliceThickness).toFixed(digitPlaces)} mm`
|
||||
}}</div>
|
||||
}}</div>
|
||||
<div v-show="imageInfo.wwwc">WW/WL: {{ imageInfo.wwwc }}</div>
|
||||
</div>
|
||||
<div class="orientation-top">
|
||||
|
|
@ -68,6 +68,8 @@
|
|||
<script>
|
||||
import {
|
||||
metaData,
|
||||
volumeLoader,
|
||||
setVolumesForViewports,
|
||||
getRenderingEngine,
|
||||
utilities as csUtils,
|
||||
cache
|
||||
|
|
@ -77,8 +79,9 @@ import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/read
|
|||
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||
import { setPetColorMapTransferFunctionForVolumeActor } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetColorMapTransferFunctionForVolumeActor'
|
||||
import { vec3, mat4 } from 'gl-matrix'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
export default {
|
||||
name: 'ImageViewport',
|
||||
name: 'MPRViewport',
|
||||
props: {
|
||||
renderingEngineId: {
|
||||
type: String,
|
||||
|
|
@ -92,12 +95,6 @@ export default {
|
|||
type: Number,
|
||||
required: true
|
||||
},
|
||||
MPRInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -125,7 +122,9 @@ export default {
|
|||
sliceThickness: null,
|
||||
wwwc: null,
|
||||
total: 0,
|
||||
sliceThickness: 0
|
||||
sliceThickness: 0,
|
||||
imageOrientationPatient: [],
|
||||
imagePositionPatient: []
|
||||
},
|
||||
digitPlaces: 2,
|
||||
orientationMarkers: [],
|
||||
|
|
@ -271,20 +270,21 @@ export default {
|
|||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
let imageIds = viewport.getImageIds(this.volumeId)
|
||||
let imageId = imageIds[0]
|
||||
let volume = cache.getVolume(this.volumeId)
|
||||
let { spacing } = volume
|
||||
// if (this.series.orientation === 'AXIAL') imageId = viewport.getCurrentImageId()
|
||||
let imageId = viewport.getCurrentImageId()
|
||||
if (imageId) {
|
||||
this.$emit('setMPRInfo', { type: this.series.orientation, key: "imageNum", value: detail.numberOfSlices })
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId)
|
||||
let type = this.determineImagePlane(imagePlaneModule.imageOrientationPatient)
|
||||
this.imageInfo.location = type === this.series.orientation ? imagePlaneModule.sliceLocation : ''
|
||||
this.imageInfo.sliceThickness = type === this.series.orientation ? spacing[2] : spacing[0]
|
||||
this.imageInfo.imageOrientationPatient = imagePlaneModule.imageOrientationPatient
|
||||
this.imageInfo.imagePositionPatient = imagePlaneModule.imagePositionPatient
|
||||
this.imageInfo.size = `${imagePlaneModule.columns}*${imagePlaneModule.rows}`
|
||||
this.imageInfo.location = imagePlaneModule.sliceLocation
|
||||
this.imageInfo.total = detail.numberOfSlices
|
||||
this.getOrientationMarker()
|
||||
let properties = viewport.getProperties(this.volumeId)
|
||||
// this.$emit('renderAnnotations', this.series)
|
||||
let properties = viewport.getProperties()
|
||||
if (this.isFusion) {
|
||||
properties = viewport.getProperties(this.ptVolumeId)
|
||||
}
|
||||
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const windowWidth = upper - lower
|
||||
|
|
@ -293,11 +293,10 @@ export default {
|
|||
this.defaultWindowLevel.windowCenter = windowCenter
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
}
|
||||
const toolGroupId = this.viewportId
|
||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolEnabled('ScaleOverlay')
|
||||
}
|
||||
// const toolGroupId = this.viewportId
|
||||
const toolGroupId = 'share-viewport-volume'
|
||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolEnabled('ScaleOverlay')
|
||||
|
||||
},
|
||||
setFullScreen(index) {
|
||||
|
|
@ -468,17 +467,33 @@ export default {
|
|||
})
|
||||
this.loading = false
|
||||
},
|
||||
async getVolume(serie, isFusion = false) {
|
||||
return new Promise(async res => {
|
||||
let volumeId = `${isFusion ? 'fusion_' : ''}` + serie.SeriesInstanceUid;
|
||||
let volume = null;
|
||||
if (cache.getVolume(volumeId)) {
|
||||
volume = cache.getVolume(volumeId)
|
||||
} else {
|
||||
await this.createImageIdsAndCacheMetaData(serie)
|
||||
volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds: serie.ImageIds })
|
||||
volume.load()
|
||||
}
|
||||
res({ volumeId, volume })
|
||||
})
|
||||
},
|
||||
async setSeriesInfo(obj, isLocate = false) {
|
||||
try {
|
||||
let data = obj
|
||||
if (this.series && data.Id === this.series.Id && data.Description === this.series.Description && !isLocate && !data.isLocation) {
|
||||
data.SliceIndex = this.series.SliceIndex
|
||||
}
|
||||
// console.log(data.SliceIndex)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (isLocate) return csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex });
|
||||
this.series = {}
|
||||
this.volumeId = data.SeriesInstanceUid
|
||||
let res = await this.getVolume(obj)
|
||||
this.volumeId = res.volumeId
|
||||
this.series = { ...data }
|
||||
viewport
|
||||
.setVolumes([{
|
||||
|
|
@ -491,9 +506,13 @@ export default {
|
|||
console.log("渲染成功")
|
||||
}
|
||||
}]).then(res => {
|
||||
if (data.segment) {
|
||||
return DicomEvent.$emit("isloaded", { segment: data.segment })
|
||||
}
|
||||
if (data.isLocation) {
|
||||
setTimeout(() => { csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex }); })
|
||||
}
|
||||
DicomEvent.$emit("isloaded", {})
|
||||
})
|
||||
viewport.render()
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@
|
|||
:parentQsId="parentQsId" :isBaseline="isBaseline" :reading-task-state="readingTaskState"
|
||||
:question-form="QuestionsForm" :visit-task-id="visitTaskId" :criterion-id="criterionId"
|
||||
:type="addOrEdit.type" :calculationList="calculationList" :questionsMarkStatus="questionsMarkStatus"
|
||||
:questionsSegmentMarkStatus="questionsSegmentMarkStatus"
|
||||
@formItemTableNumberChange="formItemTableNumberChange" @resetFormItemData="resetTableFormItemData"
|
||||
@setFormItemData="setFormTableItemData" @operateImageMarker="operateImageMarker" @save="save"
|
||||
@handleReadingChart="handleReadingChart" />
|
||||
|
|
@ -183,7 +184,49 @@
|
|||
<el-input v-if="question.Type === 'increment'" v-model="questionForm[question.Id]" disabled />
|
||||
<!-- 数值 -->
|
||||
<template v-if="question.Type === 'number' && (question.ImageMarkEnum === 1 || question.ImageMarkEnum === 2)">
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;"
|
||||
v-if="question.ImageMarkTypeEnum === 1">
|
||||
<el-input type="text" @change="(val) => { formItemNumberChange(val, question) }"
|
||||
@input="numberInput(question.Id)"
|
||||
@blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? () => { } : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question)"
|
||||
v-model="questionForm[question.Id]"
|
||||
:title="questionsMarkStatus[question.Id] ? questionsMarkStatus[question.Id].OrderMarkName : question.Remark"
|
||||
:disabled="(questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1 || readingTaskState === 2"
|
||||
style="width: 150px;margin-right: 5px;">
|
||||
<template v-if="question.Unit !== 0" slot="append">
|
||||
{{ question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit }}
|
||||
</template>
|
||||
</el-input>
|
||||
<svg-icon v-if="question.ShowChartTypeEnum > 0 && taskInfo.IsReadingTaskViewInOrder === 1"
|
||||
icon-class="readingChart" class="svg-icon svg-readingChart" @click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
QuestionId: question.Id,
|
||||
QuestionName: question.QuestionName
|
||||
}
|
||||
})" />
|
||||
<!-- 绑定 -->
|
||||
<el-button v-if="readingTaskState < 2 && (!questionsSegmentMarkStatus[question.Id])" size="mini" type="text"
|
||||
@click="operateImageMarker({ operateStateEnum: 21, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:bind') }}
|
||||
</el-button>
|
||||
<!-- 更改 -->
|
||||
<el-button v-if="readingTaskState < 2 && (questionsSegmentMarkStatus[question.Id])" size="mini" type="text"
|
||||
@click="operateImageMarker({ operateStateEnum: 22, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:edit') }}
|
||||
</el-button>
|
||||
<!-- 查看 -->
|
||||
<el-button v-if="questionsSegmentMarkStatus[question.Id]" size="mini" type="text"
|
||||
@click="operateImageMarker({ operateStateEnum: 23, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:view') }}
|
||||
</el-button>
|
||||
<!-- 移除 -->
|
||||
<el-button v-if="readingTaskState < 2 && (questionsSegmentMarkStatus[question.Id])" size="mini" type="text"
|
||||
@click="operateImageMarker({ operateStateEnum: 24, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:remove') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;" v-else>
|
||||
<el-input type="text" @change="(val) => { formItemNumberChange(val, question) }"
|
||||
@input="numberInput(question.Id)"
|
||||
@blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? () => { } : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question)"
|
||||
|
|
@ -312,9 +355,10 @@
|
|||
:isNoneDicom="isNoneDicom" :reading-task-state="readingTaskState" :question-form="questionForm"
|
||||
:visit-task-id="visitTaskId" :criterion-id="criterionId" :calculationList="calculationList"
|
||||
:questionMarkInfoList="questionMarkInfoList" :questionsMarkStatus="questionsMarkStatus"
|
||||
@formItemNumberChange="formItemNumberChange" @setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData" @getQuestions="getQuestions" @operateImageMarker="operateImageMarker"
|
||||
@unBindAnnotationToQuestion="unBindAnnotationToQuestion" @handleReadingChart="handleReadingChart" />
|
||||
:questionsSegmentMarkStatus="questionsSegmentMarkStatus" @formItemNumberChange="formItemNumberChange"
|
||||
@setFormItemData="setFormItemData" @resetFormItemData="resetFormItemData" @getQuestions="getQuestions"
|
||||
@operateImageMarker="operateImageMarker" @unBindAnnotationToQuestion="unBindAnnotationToQuestion"
|
||||
@handleReadingChart="handleReadingChart" @saveSegmentBindingAndAnswer="saveSegmentBindingAndAnswer" />
|
||||
</template>
|
||||
|
||||
<!-- <base-model :config="addOrEdit"
|
||||
|
|
@ -397,6 +441,12 @@ export default {
|
|||
return {}
|
||||
}
|
||||
},
|
||||
questionsSegmentMarkStatus: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
isNoneDicom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
|
|
@ -556,8 +606,65 @@ export default {
|
|||
this.operateImageMarker({ operateStateEnum, question: this.question, picturePath })
|
||||
}
|
||||
})
|
||||
DicomEvent.$on('setTableQuestionAnswer', async (DATA) => {
|
||||
let { id, answer, ParentQsId, data } = DATA
|
||||
console.log(ParentQsId, this.question.Id)
|
||||
if (this.question.Id === ParentQsId) {
|
||||
this.QuestionsForm[id] = answer
|
||||
if (data.RowId) {
|
||||
let i = this.AnswersList.findIndex(i => i.RowId === this.QuestionsForm.RowId)
|
||||
this.AnswersList[i][id] = this.QuestionsForm[id]
|
||||
this.$emit('setFormItemData', { key: this.question.Id, val: this.AnswersList, question: this.question })
|
||||
this.formItemNumberChange(this.question.Id, true)
|
||||
this.$emit('saveSegmentBindingAndAnswer', [data])
|
||||
} else {
|
||||
try {
|
||||
// loading = this.$loading({ fullscreen: true })
|
||||
let answers = []
|
||||
let reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
|
||||
for (const k in this.QuestionsForm) {
|
||||
if (reg.test(k)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
|
||||
answers.push({ tableQuestionId: k, answer: this.QuestionsForm[k] })
|
||||
}
|
||||
}
|
||||
}
|
||||
this.QuestionsList.forEach(k => {
|
||||
if (reg.test(k.Id)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k.Id) === -1) {
|
||||
answers.push({ tableQuestionId: k.Id, answer: '' })
|
||||
}
|
||||
}
|
||||
})
|
||||
let params = {
|
||||
questionId: this.question.Id,
|
||||
RowIndex: this.questionForm[this.question.Id].length + 1,
|
||||
RowId: this.QuestionsForm.RowId ? this.QuestionsForm.RowId : '',
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.$route.query.trialId,
|
||||
answerList: answers
|
||||
}
|
||||
let res = await submitTableQuestion(params)
|
||||
if (res.IsSuccess) {
|
||||
this.QuestionsForm.RowId = res.Result.RowId
|
||||
obj.rowId = res.Result.RowId
|
||||
data.RowId = res.Result.RowId
|
||||
this.AnswersList.push(this.QuestionsForm)
|
||||
this.$emit('setFormItemData', { key: this.question.Id, val: this.AnswersList, question: this.question })
|
||||
this.formItemNumberChange(this.question.Id, true)
|
||||
this.$emit('saveSegmentBindingAndAnswer', [data])
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
saveSegmentBindingAndAnswer(list) {
|
||||
this.$emit('saveSegmentBindingAndAnswer', list)
|
||||
},
|
||||
handleReadingChart(row) {
|
||||
this.$emit('handleReadingChart', row)
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@
|
|||
:isNoneDicom="isNoneDicom" :question="question" :question-form="questionForm"
|
||||
:reading-task-state="readingTaskState" :criterion-id="criterionId" :calculation-list="calculationList"
|
||||
:question-mark-info-list="questionMarkInfoList" :questions-mark-status="questionsMarkStatus"
|
||||
:is-baseline="isBaseLineTask" @resetFormItemData="resetFormItemData" @setFormItemData="setFormItemData"
|
||||
@getQuestions="getQuestions" @operateImageMarker="operateImageMarker"
|
||||
@unBindAnnotationToQuestion="unBindAnnotationToQuestion" @handleReadingChart="handleReadingChart" />
|
||||
:questionsSegmentMarkStatus="questionsSegmentMarkStatus" :is-baseline="isBaseLineTask"
|
||||
@resetFormItemData="resetFormItemData" @setFormItemData="setFormItemData" @getQuestions="getQuestions"
|
||||
@operateImageMarker="operateImageMarker" @unBindAnnotationToQuestion="unBindAnnotationToQuestion"
|
||||
@handleReadingChart="handleReadingChart" @saveSegmentBindingAndAnswer="saveSegmentBindingAndAnswer" />
|
||||
</template>
|
||||
|
||||
<el-form-item v-if="readingTaskState < 2">
|
||||
|
|
@ -58,7 +59,7 @@
|
|||
<script>
|
||||
|
||||
import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, verifyVisitTaskQuestions, getQuestionCalculateRelation, saveTaskQuestion } from '@/api/trials'
|
||||
import { setSkipReadingCache, resetReadingTask, saveTableQuestionMark, saveAnswerAndBindingNoneDicomMark, changePlottingScaleChangeAnswer } from '@/api/reading'
|
||||
import { setSkipReadingCache, resetReadingTask, saveTableQuestionMark, saveAnswerAndBindingNoneDicomMark, changePlottingScaleChangeAnswer, getSegmentBindingList, saveSegmentBindingAndAnswer, getSegmentList, getSegmentationList } from '@/api/reading'
|
||||
import const_ from '@/const/sign-code'
|
||||
import QuestionFormItem from './QuestionFormItem'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
|
|
@ -116,6 +117,7 @@ export default {
|
|||
imageTool: '',
|
||||
imageToolAttribute: '',
|
||||
questionsMarkStatus: {},
|
||||
questionsSegmentMarkStatus: {},
|
||||
digitPlaces: 2,
|
||||
questionImageToolAttributeInfo: {},
|
||||
unSaveTargets: [],
|
||||
|
|
@ -133,6 +135,7 @@ export default {
|
|||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.getQuestionCalculateRelation()
|
||||
this.getQuestions(true)
|
||||
this.initSegmentBinding()
|
||||
DicomEvent.$on('opentableCol', (data) => {
|
||||
let { visible } = data
|
||||
this.isTableVisible = visible
|
||||
|
|
@ -433,8 +436,13 @@ export default {
|
|||
REMOVE: 4, // 移除标记
|
||||
SAVE_OUTER: 5, // 保存外层标记
|
||||
UPDATE: 6, // 更改数值内容
|
||||
SAVE_TABLE: 7 // 保存表格标记
|
||||
SAVE_TABLE: 7, // 保存表格标记
|
||||
BIND_SEGMENT: 21, // 绑定分割标记
|
||||
CHANGE_SEGMENT: 22, // 更改分割标记
|
||||
VIEW_SEGMENT: 23, // 查看分割标记
|
||||
REMOVE_SEGMENT: 24, // 移除分割标记
|
||||
}
|
||||
console.log(obj, 'obj')
|
||||
const { question, operateStateEnum, rowId, answer } = obj
|
||||
const { Id, IsTableQuestion, ImageTool, ImageToolAttribute, ParentQsId, RowId, QuestionName, QuestionEnName } = question
|
||||
|
||||
|
|
@ -446,7 +454,7 @@ export default {
|
|||
operateQuestionId: Id,
|
||||
operateQuestionName: this.isEN ? QuestionEnName : QuestionName,
|
||||
operateRowId: RowId,
|
||||
operateParentQsId: ParentQsId
|
||||
operateParentQsId: ParentQsId,
|
||||
})
|
||||
const stateHandlers = {
|
||||
[STATE.BIND]: () => this.$emit('setReadingToolPassive'),
|
||||
|
|
@ -456,12 +464,182 @@ export default {
|
|||
[STATE.REMOVE]: this.handleRemoveAnnotation,
|
||||
[STATE.SAVE_OUTER]: this.isNoneDicom ? this.handleSaveNoneDicomOuterQuestions : this.handleSaveOuterQuestions,
|
||||
[STATE.UPDATE]: this.handleUpdateValue,
|
||||
[STATE.SAVE_TABLE]: this.isNoneDicom ? this.handleSaveNoneDicomTableQuestions : this.handleSaveTableQuestions
|
||||
[STATE.SAVE_TABLE]: this.isNoneDicom ? this.handleSaveNoneDicomTableQuestions : this.handleSaveTableQuestions,
|
||||
[STATE.BIND_SEGMENT]: this.handleBindSegment,
|
||||
[STATE.CHANGE_SEGMENT]: this.handleBindSegment,
|
||||
[STATE.VIEW_SEGMENT]: this.handleViewSegment,
|
||||
[STATE.REMOVE_SEGMENT]: this.handleRemoveSegment,
|
||||
}
|
||||
|
||||
const handler = stateHandlers[operateStateEnum]
|
||||
handler && await handler.call(this, obj)
|
||||
},
|
||||
async handleViewSegment(obj) {
|
||||
try {
|
||||
let o = {}
|
||||
if (this.isTableQuestion) {
|
||||
o.TableQuestionId = this.operateQuestionId
|
||||
o.RowId = this.operateRowId
|
||||
} else {
|
||||
o.QuestionId = this.operateQuestionId
|
||||
}
|
||||
let list = await this.getSegmentBindingList(o)
|
||||
if (list && list.length > 0) {
|
||||
let segment = await this.getSegmentList(list[0].SegmentId)
|
||||
if (segment[0].SegmentJson) {
|
||||
let obj = JSON.parse(segment[0].SegmentJson)
|
||||
segment[0].stats = obj.stats
|
||||
segment[0].bidirectional = obj.bidirectional
|
||||
segment[0].segmentationId = segment[0].SegmentationId
|
||||
segment[0].segmentIndex = segment[0].SegmentMumber
|
||||
}
|
||||
let segmentGroup = await this.getSegmentationList(list[0].SegmentationId)
|
||||
this.$emit('viewCustomAnnotationSeries', {
|
||||
visitTaskId: this.visitTaskId,
|
||||
segment: segment[0],
|
||||
segmentGroup: segmentGroup[0]
|
||||
})
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
handleBindSegment(obj) {
|
||||
this.$emit("openSegmentForm", { visitInfo: this.visitInfo })
|
||||
},
|
||||
handleSegmentSave(obj) {
|
||||
let imageToolAttribute = this.imageToolAttribute
|
||||
let answer = ''
|
||||
if (imageToolAttribute === 'length' || imageToolAttribute === 'width') {
|
||||
let s = {
|
||||
length: "maxMajor",
|
||||
width: 'maxMinor'
|
||||
}
|
||||
if (!obj.bidirectional || !obj.bidirectional.maxMajor) return this.$confirm(this.$t("segment:error:notValue"))
|
||||
answer = obj.bidirectional[s[imageToolAttribute]] ? (obj.bidirectional[s[imageToolAttribute]]).toFixed(this.digitPlaces) : ''
|
||||
} else {
|
||||
if (!obj.stats) return this.$confirm(this.$t("segment:error:notValue"))
|
||||
answer = obj.stats[imageToolAttribute] ? Number((obj.stats[imageToolAttribute]).value).toFixed(this.digitPlaces) : ''
|
||||
}
|
||||
let o = {
|
||||
Answer: answer,
|
||||
SegmentId: obj.Id,
|
||||
SegmentationId: obj.SegmentationId,
|
||||
QuestionId: this.isTableQuestion ? this.operateParentQsId : this.operateQuestionId,
|
||||
RowId: this.isTableQuestion ? this.operateRowId : null,
|
||||
TableQuestionId: this.isTableQuestion ? this.operateQuestionId : null,
|
||||
VisitTaskId: this.visitTaskId,
|
||||
}
|
||||
if (this.isTableQuestion) {
|
||||
return DicomEvent.$emit('setTableQuestionAnswer', { id: this.operateQuestionId, answer, ParentQsId: this.operateParentQsId, data: o })
|
||||
} else {
|
||||
this.$set(this.questionForm, this.operateQuestionId, answer)
|
||||
}
|
||||
this.saveSegmentBindingAndAnswer([o])
|
||||
},
|
||||
// 删除问题与分割标记绑定
|
||||
async handleRemoveSegment(obj) {
|
||||
const { question } = obj
|
||||
let confirm = await this.$confirm(this.$t('segment:confirm:sureDelete'))
|
||||
if (!confirm) return false
|
||||
this.$set(this.questionForm, question.Id, '')
|
||||
let o = {
|
||||
Answer: '',
|
||||
SegmentId: null,
|
||||
SegmentationId: null,
|
||||
QuestionId: this.isTableQuestion ? this.operateParentQsId : this.operateQuestionId,
|
||||
RowId: this.isTableQuestion ? this.operateRowId : null,
|
||||
TableQuestionId: this.isTableQuestion ? this.operateQuestionId : null,
|
||||
VisitTaskId: this.visitTaskId,
|
||||
}
|
||||
this.saveSegmentBindingAndAnswer([o])
|
||||
},
|
||||
// 添加分割标记与问题绑定关系
|
||||
async saveSegmentBindingAndAnswer(list) {
|
||||
try {
|
||||
let data = {
|
||||
VisitTaskId: this.visitTaskId,
|
||||
BindingList: list
|
||||
}
|
||||
let res = await saveSegmentBindingAndAnswer(data)
|
||||
if (res.IsSuccess) {
|
||||
this.initSegmentBinding()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 初始化分割标记与问题绑定关系
|
||||
async initSegmentBinding() {
|
||||
try {
|
||||
let list = await this.getSegmentBindingList()
|
||||
this.questionsSegmentMarkStatus = {}
|
||||
list.forEach(item => {
|
||||
if (item.TableQuestionId && item.RowId) {
|
||||
this.$set(this.questionsSegmentMarkStatus, `${item.RowId}_${item.TableQuestionId}`, item.SegmentId)
|
||||
} else {
|
||||
this.$set(this.questionsSegmentMarkStatus, item.QuestionId, item.SegmentId)
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 获取当前任务分割标记与问题绑定关系
|
||||
async getSegmentBindingList(param = {}) {
|
||||
try {
|
||||
let data = {
|
||||
VisitTaskId: this.visitTaskId,
|
||||
PageSize: 9999,
|
||||
PageIndex: 1,
|
||||
}
|
||||
data = Object.assign(data, param)
|
||||
let res = await getSegmentBindingList(data)
|
||||
if (res.IsSuccess) {
|
||||
return res.Result.CurrentPageData
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 获取分割
|
||||
async getSegmentList(id) {
|
||||
try {
|
||||
let data = {
|
||||
// SegmentationId: id,
|
||||
PageSize: 9999,
|
||||
PageIndex: 1,
|
||||
}
|
||||
if (id) data.Id = id
|
||||
let res = await getSegmentList(data)
|
||||
if (res.IsSuccess) {
|
||||
return res.Result.CurrentPageData
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 获取分割组
|
||||
async getSegmentationList(id) {
|
||||
try {
|
||||
let data = {
|
||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
||||
PageSize: 9999,
|
||||
PageIndex: 1,
|
||||
}
|
||||
if (id) data.Id = id
|
||||
let res = await getSegmentationList(data);
|
||||
|
||||
if (res.IsSuccess) {
|
||||
return res.Result.CurrentPageData;
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
|
||||
async handleViewAnnotation(obj) {
|
||||
const index = this.findMarkIndex(obj.question)
|
||||
if (index === -1) return
|
||||
|
|
|
|||
|
|
@ -107,7 +107,53 @@
|
|||
<el-input v-if="question.Type === 'increment'" v-model="questionForm[question.Id]" disabled />
|
||||
<!-- 数值 -->
|
||||
<template v-if="question.Type === 'number' && (question.ImageMarkEnum === 1 || question.ImageMarkEnum === 2)">
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;"
|
||||
v-if="question.ImageMarkTypeEnum === 1">
|
||||
<el-input type="text" @change="(val) => { formItemNumberChange(val, question) }"
|
||||
@input="numberInput(question.Id)"
|
||||
@blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? () => { } : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question)"
|
||||
v-model="questionForm[question.Id]"
|
||||
:title="questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] ? questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].OrderMarkName : question.Remark"
|
||||
:disabled="(questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1 || question.IsPreinstall"
|
||||
style="width: 150px;margin-right: 5px;">
|
||||
<template v-if="question.Unit !== 0" slot="append">
|
||||
{{ question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit }}
|
||||
</template>
|
||||
</el-input>
|
||||
<svg-icon v-if="question.ShowChartTypeEnum > 0 && taskInfo.IsReadingTaskViewInOrder === 1"
|
||||
icon-class="readingChart" class="svg-icon svg-readingChart" @click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
TableQuestionId: question.Id,
|
||||
RowIndex: questionForm.RowIndex,
|
||||
QuestionName: question.QuestionName
|
||||
}
|
||||
})" />
|
||||
<!-- 绑定 -->
|
||||
<el-button
|
||||
v-if="readingTaskState < 2 && (!questionsSegmentMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id])"
|
||||
size="mini" type="text" @click="operateImageMarker({ operateStateEnum: 21, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:bind') }}
|
||||
</el-button>
|
||||
<!-- 更改 -->
|
||||
<el-button
|
||||
v-if="readingTaskState < 2 && (questionsSegmentMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id])"
|
||||
size="mini" type="text" @click="operateImageMarker({ operateStateEnum: 22, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:edit') }}
|
||||
</el-button>
|
||||
<!-- 查看 -->
|
||||
<el-button v-if="questionsSegmentMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id]" size="mini"
|
||||
type="text" @click="operateImageMarker({ operateStateEnum: 23, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:view') }}
|
||||
</el-button>
|
||||
<!-- 移除 -->
|
||||
<el-button
|
||||
v-if="readingTaskState < 2 && (questionsSegmentMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id])"
|
||||
size="mini" type="text" @click="operateImageMarker({ operateStateEnum: 24, question })">
|
||||
{{ $t('dicom3D:CustomizeQuestionFormItem:button:remove') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;" v-else>
|
||||
<el-input type="text" @change="(val) => { formItemNumberChange(val, question) }"
|
||||
@input="numberInput(question.Id)"
|
||||
@blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? () => { } : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question)"
|
||||
|
|
@ -276,6 +322,12 @@ export default {
|
|||
return {}
|
||||
}
|
||||
},
|
||||
questionsSegmentMarkStatus: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
parentQsId: {
|
||||
type: String,
|
||||
default: ''
|
||||
|
|
|
|||
|
|
@ -386,6 +386,35 @@ const config = {
|
|||
'disabledReason': ''
|
||||
},
|
||||
],
|
||||
'customizeStandardsSegmentDicom': [
|
||||
// {
|
||||
// 'name': 'Contour分割',
|
||||
// 'icon': 'contour',
|
||||
// 'toolName': 'Contour',
|
||||
// 'props': ['length'],
|
||||
// 'i18nKey': 'trials:reading:button:Contour',
|
||||
// 'isDisabled': false,
|
||||
// 'disabledReason': ''
|
||||
// },
|
||||
{
|
||||
'name': 'Labelmap分割',
|
||||
'icon': 'labelmap',
|
||||
'toolName': 'Labelmap',
|
||||
'props': ['max', 'min', 'volume', 'count', 'mean', 'stdDev', 'length', 'width'],
|
||||
'i18nKey': 'trials:reading:button:Labelmap',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
// {
|
||||
// 'name': 'Surface分割',
|
||||
// 'icon': 'surface',
|
||||
// 'toolName': 'Surface',
|
||||
// 'props': ['area', 'mean', 'max', 'stdDev'],
|
||||
// 'i18nKey': 'trials:reading:button:Surface',
|
||||
// 'isDisabled': false,
|
||||
// 'disabledReason': ''
|
||||
// },
|
||||
],
|
||||
}
|
||||
const getTools = (criterionType) => {
|
||||
const standard = config.standards.find(s => s.type === criterionType)
|
||||
|
|
@ -399,4 +428,8 @@ const getCustomizeStandardsNoneDicomTools = (toolNames) => {
|
|||
const filteredTools = config.customizeStandardsNoneDicom.filter(item => toolNames.includes(item.toolName))
|
||||
return filteredTools || []
|
||||
}
|
||||
export { config, getTools, getCustomizeStandardsTools, getCustomizeStandardsNoneDicomTools }
|
||||
const getCustomizeStandardsSegmentDicomTools = (toolNames) => {
|
||||
const filteredTools = config.customizeStandardsSegmentDicom.filter(item => toolNames.includes(item.toolName))
|
||||
return filteredTools || []
|
||||
}
|
||||
export { config, getTools, getCustomizeStandardsTools, getCustomizeStandardsNoneDicomTools, getCustomizeStandardsSegmentDicomTools }
|
||||
|
|
|
|||
|
|
@ -323,7 +323,7 @@ export default {
|
|||
)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (this.readingTool === 0 || this.readingTool === 2) {
|
||||
if (this.readingTool === 0 || this.readingTool === 2 || this.readingTool === 3) {
|
||||
if (this.criterionType === 0 && this.trialId === '08dd28b3-6843-fc05-0242-ac1301000000') {
|
||||
path = `/fusion?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&studyId=62b3dfc4-1e04-4180-910d-fe595f398361&ctseriesId=1bd24f53-d419-32e5-92d4-2b04640aaa65&ptseriesId=2b7b128d-8c3f-8357-ad14-e38f3acbbdff&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&TokenKey=${token}&lang=${this.$i18n.locale}`
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -484,8 +484,15 @@
|
|||
:disabled="form.IsRequired === 2 && item.value === 1">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量工具 ImageTool -->
|
||||
<!--标记类型-->
|
||||
<el-form-item v-if="form.ImageMarkEnum === 1 || form.ImageMarkEnum === 2"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageMarkTypeEnum')" prop="ImageMarkTypeEnum">
|
||||
<el-radio-group v-model="form.ImageMarkTypeEnum" @change="ImageMarkTypeEnumChange">
|
||||
<el-radio v-for="item of $d.ImageMarkType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量工具 ImageTool -->
|
||||
<el-form-item v-if="(form.ImageMarkEnum === 1 || form.ImageMarkEnum === 2) && form.ImageMarkTypeEnum === 0"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageTool')" prop="ImageTool" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select') }
|
||||
]">
|
||||
|
|
@ -495,6 +502,17 @@
|
|||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 分割工具 ImageTool -->
|
||||
<el-form-item v-if="(form.ImageMarkEnum === 1 || form.ImageMarkEnum === 2) && form.ImageMarkTypeEnum === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageTool')" prop="ImageTool" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select') }
|
||||
]">
|
||||
<el-radio-group v-model="form.ImageTool" @change="imageSegmentToolChange">
|
||||
<el-radio v-for="tool of readingSegmentTools" :key="tool.toolName" :label="tool.toolName">
|
||||
{{ $t(tool.i18nKey) }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量值 ImageToolAttribute -->
|
||||
<el-form-item v-if="form.ImageTool && imageToolAttributes.length > 0"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageToolAttribute')" prop="ImageToolAttribute" :rules="[
|
||||
|
|
@ -696,6 +714,12 @@ export default {
|
|||
return []
|
||||
}
|
||||
},
|
||||
readingSegmentTools: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingVersionEnum: {
|
||||
type: Number,
|
||||
default: 0
|
||||
|
|
@ -754,6 +778,7 @@ export default {
|
|||
ClassifyEditType: null,
|
||||
ClassifyShowType: null,
|
||||
ImageMarkEnum: 0,
|
||||
ImageMarkTypeEnum: 0,
|
||||
ShowChartTypeEnum: 0,
|
||||
ImageTool: '',
|
||||
ImageToolAttribute: '',
|
||||
|
|
@ -1050,9 +1075,12 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (this.form.ImageTool) {
|
||||
if (this.form.ImageTool && this.form.ImageMarkTypeEnum === 0) {
|
||||
this.imageToolChange(this.form.ImageTool)
|
||||
}
|
||||
if (this.form.ImageTool && this.form.ImageMarkTypeEnum === 1) {
|
||||
this.imageSegmentToolChange(this.form.ImageTool)
|
||||
}
|
||||
}
|
||||
if (!this.data.ShowOrder && this.data.ShowOrder !== 0) {
|
||||
if (this.list.length > 0) {
|
||||
|
|
@ -1172,14 +1200,26 @@ export default {
|
|||
this.form.ImageTool = ''
|
||||
this.form.ImageToolAttribute = ''
|
||||
this.imageToolAttributes = []
|
||||
this.form.ImageMarkTypeEnum = 0
|
||||
}
|
||||
},
|
||||
ImageMarkTypeEnumChange(val) {
|
||||
this.form.ImageTool = ''
|
||||
this.form.ImageToolAttribute = ''
|
||||
this.imageToolAttributes = []
|
||||
},
|
||||
imageToolChange(v) {
|
||||
let i = this.readingTools.findIndex(tool => tool.toolName === v)
|
||||
if (i > -1) {
|
||||
this.imageToolAttributes = this.readingTools[i].props
|
||||
}
|
||||
},
|
||||
imageSegmentToolChange(v) {
|
||||
let i = this.readingSegmentTools.findIndex(tool => tool.toolName === v)
|
||||
if (i > -1) {
|
||||
this.imageToolAttributes = this.readingSegmentTools[i].props
|
||||
}
|
||||
},
|
||||
parentQuestionChange(val, form) {
|
||||
this.isParentExistGroup = false
|
||||
if (val) {
|
||||
|
|
@ -1273,6 +1313,7 @@ export default {
|
|||
form.ClassifyType = null
|
||||
form.ClassifyShowType = null
|
||||
form.ImageMarkEnum = 0
|
||||
form.ImageMarkTypeEnum = 0
|
||||
form.ShowChartTypeEnum = 0
|
||||
form.ImageTool = ''
|
||||
form.ImageToolAttribute = ''
|
||||
|
|
|
|||
|
|
@ -1,148 +1,81 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<div
|
||||
class="search-form"
|
||||
style="text-align: left;"
|
||||
>
|
||||
<div class="search-form" style="text-align: left;">
|
||||
<!-- 新增 -->
|
||||
<el-button
|
||||
v-if="!isConfirm && hasPermi(['trials:trials-panel:setting:reading-unit:edit']) && !isFromSystem"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
>
|
||||
<el-button v-if="!isConfirm && hasPermi(['trials:trials-panel:setting:reading-unit:edit']) && !isFromSystem"
|
||||
size="mini" type="primary" @click="handleAdd">
|
||||
{{ $t('common:button:add') }}
|
||||
</el-button>
|
||||
<!-- 预览 -->
|
||||
<el-button
|
||||
v-if="isPreview"
|
||||
:disabled="tblList.length===0"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handlePreview"
|
||||
>
|
||||
<el-button v-if="isPreview" :disabled="tblList.length === 0" size="mini" type="primary" @click="handlePreview">
|
||||
{{ $t('common:button:preview') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
:data="tblList"
|
||||
size="small"
|
||||
>
|
||||
<el-table-column
|
||||
prop="ShowOrder"
|
||||
label=""
|
||||
width="50"
|
||||
/>
|
||||
<el-table :data="tblList" size="small">
|
||||
<el-table-column prop="ShowOrder" label="" width="50" />
|
||||
<!-- 分组 -->
|
||||
<el-table-column
|
||||
prop="QuestionGroupName"
|
||||
v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:groupNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionGroupName" v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:groupNameEn')" show-overflow-tooltip />
|
||||
<!-- 分组(EN) -->
|
||||
<el-table-column
|
||||
prop="QuestionGroupEnName"
|
||||
v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:groupNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionGroupEnName" v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:groupNameEn')" show-overflow-tooltip />
|
||||
<!-- 名称 -->
|
||||
<el-table-column
|
||||
prop="QuestionName"
|
||||
v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionName" v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')" show-overflow-tooltip />
|
||||
<!-- 名称(EN) -->
|
||||
<el-table-column
|
||||
prop="QuestionEnName"
|
||||
v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionEnName" v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')" show-overflow-tooltip />
|
||||
<!-- 题型 -->
|
||||
<el-table-column
|
||||
prop="Type"
|
||||
:label="$t('trials:readingUnit:qsList:title:type')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="Type" :label="$t('trials:readingUnit:qsList:title:type')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('Criterion_Question_Type',scope.row.Type) }}
|
||||
{{ $fd('Criterion_Question_Type', scope.row.Type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否显示 -->
|
||||
<el-table-column
|
||||
prop="ShowQuestion"
|
||||
:label="$t('trials:readingUnit:qsList:title:isShow')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="ShowQuestion" :label="$t('trials:readingUnit:qsList:title:isShow')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('ShowQuestion',scope.row.ShowQuestion) }}
|
||||
{{ $fd('ShowQuestion', scope.row.ShowQuestion) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:readingUnit:qsList:title:isRequired')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="IsRequired" :label="$t('trials:readingUnit:qsList:title:isRequired')"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QuestionRequired',scope.row.IsRequired) }}
|
||||
{{ $fd('QuestionRequired', scope.row.IsRequired) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否裁判问题 -->
|
||||
<el-table-column
|
||||
prop="IsJudgeQuestion"
|
||||
:label="$t('trials:readingUnit:qsList:title:isJudgeQuestion')"
|
||||
width="120"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="IsJudgeQuestion" :label="$t('trials:readingUnit:qsList:title:isJudgeQuestion')" width="120"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsJudgeQuestion) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否在阅片页面显示 -->
|
||||
<el-table-column
|
||||
prop="IsShowInDicom"
|
||||
:label="$t('trials:readingUnit:qsList:title:isShowInDicom')"
|
||||
width="140"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="IsShowInDicom" :label="$t('trials:readingUnit:qsList:title:isShowInDicom')" width="140"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsShowInDicom) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否在全局阅片显示 -->
|
||||
<el-table-column
|
||||
prop="GlobalReadingShowType"
|
||||
:label="$t('trials:readingUnit:qsList:title:globalReadingShowType')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="GlobalReadingShowType" :label="$t('trials:readingUnit:qsList:title:globalReadingShowType')"
|
||||
width="160" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('GlobalReadingShowType', scope.row.GlobalReadingShowType) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 导出目标表格 -->
|
||||
<el-table-column
|
||||
prop="ExportResult"
|
||||
:label="$t('trials:readingUnit:qsList:title:ExportResult')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="ExportResult" :label="$t('trials:readingUnit:qsList:title:ExportResult')" width="160"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ getStringResult(scope.row.ExportResult, 'ExportResult') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 限制编辑 -->
|
||||
<el-table-column
|
||||
prop="LimitEdit"
|
||||
:label="$t('trials:readingUnit:qsList:title:limitEdit')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="LimitEdit" :label="$t('trials:readingUnit:qsList:title:limitEdit')" width="160"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('LimitEdit', scope.row.LimitEdit) }}
|
||||
</template>
|
||||
|
|
@ -154,105 +87,50 @@
|
|||
width="140"
|
||||
show-overflow-tooltip
|
||||
/> -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('common:action:action')"
|
||||
width="300"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="" :label="$t('common:action:action')" width="300" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<!-- 编辑 -->
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
<el-button v-if="!isConfirm && !isFromSystem && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
type="primary" size="mini" @click="handleEdit(scope.row)">
|
||||
{{ $t('trials:readingUnit:qsList:title:edit') }}
|
||||
</el-button>
|
||||
<!-- 查看 -->
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handlelook(scope.row)"
|
||||
>
|
||||
<el-button v-else type="primary" size="mini" @click="handlelook(scope.row)">
|
||||
{{ $t('trials:readingUnit:qsList:title:view') }}
|
||||
</el-button>
|
||||
<!-- 表格问题 -->
|
||||
<el-button
|
||||
v-if="scope.row.Type === 'table' || scope.row.Type === 'basicTable'"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleConfig(scope.row)"
|
||||
>
|
||||
<el-button v-if="scope.row.Type === 'table' || scope.row.Type === 'basicTable'" type="primary" size="mini"
|
||||
@click="handleConfig(scope.row)">
|
||||
{{ $t('trials:readingUnit:qsList:title:tableQs') }}
|
||||
</el-button>
|
||||
<!-- 删除 -->
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
type="danger"
|
||||
size="mini"
|
||||
@click="handleDelete(scope.row)"
|
||||
>
|
||||
<el-button v-if="!isConfirm && !isFromSystem && hasPermi(['trials:trials-panel:setting:reading-unit:edit'])"
|
||||
type="danger" size="mini" @click="handleDelete(scope.row)">
|
||||
{{ $t('trials:readingUnit:qsList:title:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog
|
||||
v-if="addOrEdit.visible"
|
||||
:visible.sync="addOrEdit.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="addOrEdit.title"
|
||||
width="800px"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<questions-form
|
||||
ref="addOrEdit"
|
||||
:data="rowData"
|
||||
:trial-criterion-id="trialCriterionId"
|
||||
:is-from-system="isFromSystem"
|
||||
:digit-places="digitPlaces"
|
||||
:readingTools="readingTools"
|
||||
:readingVersionEnum="readingVersionEnum"
|
||||
:list="tblList"
|
||||
:is-look="isLook"
|
||||
:is-system-criterion="isSystemCriterion"
|
||||
@close="addOrEdit.visible = false"
|
||||
@getList="getList"
|
||||
@reloadArbitrationRules="reloadArbitrationRules"
|
||||
/>
|
||||
<el-dialog v-if="addOrEdit.visible" :visible.sync="addOrEdit.visible" :close-on-click-modal="false"
|
||||
:title="addOrEdit.title" width="800px" append-to-body custom-class="base-dialog-wrapper">
|
||||
<questions-form ref="addOrEdit" :data="rowData" :trial-criterion-id="trialCriterionId"
|
||||
:is-from-system="isFromSystem" :digit-places="digitPlaces" :readingTools="readingTools"
|
||||
:readingSegmentTools="readingSegmentTools" :readingVersionEnum="readingVersionEnum" :list="tblList"
|
||||
:is-look="isLook" :is-system-criterion="isSystemCriterion" @close="addOrEdit.visible = false" @getList="getList"
|
||||
@reloadArbitrationRules="reloadArbitrationRules" />
|
||||
</el-dialog>
|
||||
<el-dialog
|
||||
v-if="preview.visible"
|
||||
:visible.sync="preview.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="preview.title"
|
||||
:fullscreen="true"
|
||||
>
|
||||
<el-dialog v-if="preview.visible" :visible.sync="preview.visible" :close-on-click-modal="false"
|
||||
:title="preview.title" :fullscreen="true">
|
||||
<questions-preview :criterion-id="trialCriterionId" :is-system-criterion="isSystemCriterion" :form-type="1" />
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog
|
||||
v-if="config.visible"
|
||||
:visible.sync="config.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="config.title"
|
||||
:fullscreen="true"
|
||||
>
|
||||
<table-qs-list
|
||||
:digit-places="digitPlaces"
|
||||
:reading-question-id="rowData.Id"
|
||||
:is-from-system="isFromSystem"
|
||||
:is-confirm="isConfirm"
|
||||
:criterion-id="trialCriterionId"
|
||||
:readingTools="readingTools"
|
||||
:readingVersionEnum="readingVersionEnum"
|
||||
@close="config.visible = false"
|
||||
/>
|
||||
<el-dialog v-if="config.visible" :visible.sync="config.visible" :close-on-click-modal="false" :title="config.title"
|
||||
:fullscreen="true">
|
||||
<table-qs-list :digit-places="digitPlaces" :reading-question-id="rowData.Id" :is-from-system="isFromSystem"
|
||||
:is-confirm="isConfirm" :criterion-id="trialCriterionId" :readingTools="readingTools"
|
||||
:readingSegmentTools="readingSegmentTools" :readingVersionEnum="readingVersionEnum"
|
||||
@close="config.visible = false" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -310,6 +188,12 @@ export default {
|
|||
return []
|
||||
}
|
||||
},
|
||||
readingSegmentTools: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingVersionEnum: {
|
||||
type: Number,
|
||||
default: 0
|
||||
|
|
@ -350,7 +234,8 @@ export default {
|
|||
this.rowData = {
|
||||
ReadingQuestionCriterionTrialId: this.trialCriterionId,
|
||||
ReadingCriterionPageId: this.readingCriterionPageId,
|
||||
Id: '' }
|
||||
Id: ''
|
||||
}
|
||||
this.isLook = false
|
||||
this.addOrEdit.title = this.$t('trials:readingUnit:qsList:title:add')// '添加'
|
||||
this.addOrEdit.visible = true
|
||||
|
|
@ -362,9 +247,9 @@ export default {
|
|||
this.rowData.ReadingCriterionPageId = this.readingCriterionPageId
|
||||
let title = ''
|
||||
if (this.$i18n.locale === 'zh' && (row.QuestionName || row.GroupName)) {
|
||||
title =`:${row.QuestionName ? row.QuestionName : row.GroupName}`
|
||||
title = `:${row.QuestionName ? row.QuestionName : row.GroupName}`
|
||||
} else if (this.$i18n.locale === 'en' && (row.QuestionEnName || row.GroupEnName)) {
|
||||
title =`: ${row.QuestionEnName ? row.QuestionEnName : row.GroupEnName}`
|
||||
title = `: ${row.QuestionEnName ? row.QuestionEnName : row.GroupEnName}`
|
||||
}
|
||||
this.addOrEdit.title = `${this.$t('trials:readingUnit:qsList:title:view')} ${title} `// '查看'
|
||||
this.addOrEdit.visible = true
|
||||
|
|
@ -400,8 +285,8 @@ export default {
|
|||
// this.preview.visible = true
|
||||
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
||||
var token = getToken()
|
||||
var path = `/criterionquestions?TrialReadingCriterionId=${this.trialCriterionId}&isSystemCriterion=${this.isSystemCriterion}&TokenKey=${token}`
|
||||
|
||||
var path = `/criterionquestions?TrialReadingCriterionId=${this.trialCriterionId}&isSystemCriterion=${this.isSystemCriterion}&TokenKey=${token}`
|
||||
|
||||
var routeData = this.$router.resolve({ path })
|
||||
this.openWindow = window.open(routeData.href, '_blank')
|
||||
},
|
||||
|
|
@ -431,5 +316,4 @@ export default {
|
|||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
|||
|
|
@ -1,59 +1,37 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-form
|
||||
ref="readingCriterionsForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
:rules="rules"
|
||||
label-width="120px"
|
||||
size="small"
|
||||
>
|
||||
<el-form ref="readingCriterionsForm" v-loading="loading" :model="form" :rules="rules" label-width="120px"
|
||||
size="small">
|
||||
<!-- '表单问题' -->
|
||||
<el-form-item :label="$t('trials:readingUnit:readingCriterion:title:formQs')">
|
||||
<questions-list
|
||||
:ref="`questionList${trialReadingCriterionId}`"
|
||||
v-if="form.FormType===1"
|
||||
:trial-reading-criterion-id="trialReadingCriterionId"
|
||||
:list="readingInfo.TrialQuestionList"
|
||||
:trial-criterion-id="readingInfo.TrialCriterionId"
|
||||
:is-confirm="isConfirm"
|
||||
:is-system-criterion="isSystemCriterion"
|
||||
:is-from-system="readingInfo.IsFromSystem"
|
||||
:digit-places="digitPlaces"
|
||||
:readingTools="readingTools"
|
||||
:readingVersionEnum="readingVersionEnum"
|
||||
@reloadArbitrationRules="reloadArbitrationRules"
|
||||
/>
|
||||
<questions-list :ref="`questionList${trialReadingCriterionId}`" v-if="form.FormType === 1"
|
||||
:trial-reading-criterion-id="trialReadingCriterionId" :list="readingInfo.TrialQuestionList"
|
||||
:trial-criterion-id="readingInfo.TrialCriterionId" :is-confirm="isConfirm"
|
||||
:is-system-criterion="isSystemCriterion" :is-from-system="readingInfo.IsFromSystem"
|
||||
:digit-places="digitPlaces" :readingTools="readingTools" :readingSegmentTools="readingSegmentTools"
|
||||
:readingVersionEnum="readingVersionEnum" @reloadArbitrationRules="reloadArbitrationRules" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if=" hasPermi(['trials:trials-panel:setting:reading-unit:edit'])">
|
||||
<!-- <!– 保存 –>-->
|
||||
<!-- <el-button-->
|
||||
<!-- v-if="!isConfirm && isAdditionalAssessment"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- @click="handleSave(true)"-->
|
||||
<!-- >-->
|
||||
<!-- {{ $t('common:button:save') }}-->
|
||||
<!-- </el-button>-->
|
||||
<el-form-item v-if="hasPermi(['trials:trials-panel:setting:reading-unit:edit'])">
|
||||
<!-- <!– 保存 –>-->
|
||||
<!-- <el-button-->
|
||||
<!-- v-if="!isConfirm && isAdditionalAssessment"-->
|
||||
<!-- type="primary"-->
|
||||
<!-- @click="handleSave(true)"-->
|
||||
<!-- >-->
|
||||
<!-- {{ $t('common:button:save') }}-->
|
||||
<!-- </el-button>-->
|
||||
<!-- 基础数据配置 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="configBaseDataVisible = true"
|
||||
>
|
||||
<el-button type="primary" @click="configBaseDataVisible = true">
|
||||
{{ $t('trials:readingUnit:readingCriterion:title:baseDataCfg') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 基础数据配置 -->
|
||||
<el-dialog
|
||||
v-if="configBaseDataVisible"
|
||||
:title="$t('trials:readingUnit:readingCriterion:title:baseDataCfg')"
|
||||
:visible.sync="configBaseDataVisible"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<BaseDataConfig :trial-reading-criterion-id="trialReadingCriterionId" :is-from-system="readingInfo.IsFromSystem" :is-confirm="isConfirm" />
|
||||
<el-dialog v-if="configBaseDataVisible" :title="$t('trials:readingUnit:readingCriterion:title:baseDataCfg')"
|
||||
:visible.sync="configBaseDataVisible" :close-on-click-modal="false" :fullscreen="true" append-to-body
|
||||
custom-class="base-dialog-wrapper">
|
||||
<BaseDataConfig :trial-reading-criterion-id="trialReadingCriterionId" :is-from-system="readingInfo.IsFromSystem"
|
||||
:is-confirm="isConfirm" />
|
||||
</el-dialog>
|
||||
|
||||
|
||||
|
|
@ -85,6 +63,12 @@ export default {
|
|||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingSegmentTools: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
|
@ -122,7 +106,7 @@ export default {
|
|||
this.additionalAssessmentOptionList = res.Result
|
||||
if (this.additionalAssessmentOptionList.length > 0) {
|
||||
this.additionalAssessmentOptionList.forEach(v => {
|
||||
this.$set(this.form, 'AdditionalAssessmentType'+v.Id, v.IsSelected)
|
||||
this.$set(this.form, 'AdditionalAssessmentType' + v.Id, v.IsSelected)
|
||||
})
|
||||
}
|
||||
getTrialReadingCriterionInfo({ trialId, TrialReadingCriterionId: this.trialReadingCriterionId }).then(res => {
|
||||
|
|
@ -185,7 +169,7 @@ export default {
|
|||
reloadArbitrationRules() {
|
||||
this.$emit('reloadArbitrationRules')
|
||||
},
|
||||
handleConfig() {}
|
||||
handleConfig() { }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,9 +30,8 @@
|
|||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量工具 -->
|
||||
<el-form-item
|
||||
v-if="CriterionType === 0 && (form.ReadingTool === 0 || form.ReadingTool === 1 || form.ReadingTool === 2) && form.ReadingVersionEnum === 1"
|
||||
<!-- 测量工具 && (form.ReadingTool === 0 || form.ReadingTool === 1 || form.ReadingTool === 2)-->
|
||||
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1"
|
||||
:label="$t('trials:readingUnit:readingRules:title:measureTool')">
|
||||
<el-checkbox-group v-model="form.ReadingToolList" :disabled="isConfirm ||
|
||||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
||||
|
|
@ -42,6 +41,17 @@
|
|||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<!--分割工具 && (form.ReadingTool === 0 || form.ReadingTool === 1 || form.ReadingTool === 2)-->
|
||||
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1 && form.ReadingTool === 3"
|
||||
:label="$t('trials:readingUnit:readingRules:title:segmentTool')">
|
||||
<el-checkbox-group v-model="form.SegmentToolList" :disabled="isConfirm ||
|
||||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
||||
">
|
||||
<el-checkbox v-for="tool in segmentTools" :key="tool.toolName" :label="tool.toolName" name="SegmentToolList">
|
||||
{{ $t(`${tool.i18nKey}`) }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<!--检查类型筛选-->
|
||||
<el-form-item :label="$t('trials:processCfg:form:IsImageFilter')" prop="IsImageFilter">
|
||||
<el-radio-group v-model="form.IsImageFilter" @input="IsImageFilterChange" :disabled="isConfirm ||
|
||||
|
|
@ -421,6 +431,7 @@ export default {
|
|||
ReadingTool: 0,
|
||||
ReadingVersionEnum: null,
|
||||
ReadingToolList: [],
|
||||
SegmentToolList: [],
|
||||
ReadingTaskViewEnum: null,
|
||||
IsImageLabeled: null,
|
||||
IsReadingShowSubjectInfo: null,
|
||||
|
|
@ -616,7 +627,8 @@ export default {
|
|||
modalityList: [],
|
||||
CriterionModalitys: [],
|
||||
modalityIsCheck: false, // 是否允许影像筛选
|
||||
tools: []
|
||||
tools: [],
|
||||
segmentTools: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -737,13 +749,20 @@ export default {
|
|||
// 阅片工具选择
|
||||
handleReadingToolInput(val) {
|
||||
this.form.ReadingToolList = []
|
||||
if (this.CriterionType !== 0) return this.tools = []
|
||||
if (val === 0 || val === 2) {
|
||||
this.form.SegmentToolList = []
|
||||
if (this.CriterionType !== 0) {
|
||||
this.segmentTools = []
|
||||
return this.tools = []
|
||||
}
|
||||
if (val === 0 || val === 2 || val === 3) {
|
||||
this.tools = [...config.customizeStandards]
|
||||
}
|
||||
if (val === 1) {
|
||||
this.tools = [...config.customizeStandardsNoneDicom]
|
||||
}
|
||||
if (val === 3) {
|
||||
this.segmentTools = [...config.customizeStandardsSegmentDicom]
|
||||
}
|
||||
},
|
||||
// 检查类型筛选值变更
|
||||
IsImageFilterChange(data) {
|
||||
|
|
@ -786,12 +805,15 @@ export default {
|
|||
this.form.KeyFileListStr = this.form.KeyFileList.map(item => item.FileName).join(',')
|
||||
}
|
||||
if (this.CriterionType === 0) {
|
||||
if (this.form.ReadingTool === 0 || this.form.ReadingTool === 2) {
|
||||
if (this.form.ReadingTool === 0 || this.form.ReadingTool === 2 || this.form.ReadingTool === 3) {
|
||||
this.tools = [...config.customizeStandards]
|
||||
}
|
||||
if (this.form.ReadingTool === 1) {
|
||||
this.tools = [...config.customizeStandardsNoneDicom]
|
||||
}
|
||||
if (this.form.ReadingTool === 3) {
|
||||
this.segmentTools = [...config.customizeStandardsSegmentDicom]
|
||||
}
|
||||
}
|
||||
this.CriterionModalitys = this.form.CriterionModalitys
|
||||
? this.form.CriterionModalitys.split('|')
|
||||
|
|
@ -817,7 +839,7 @@ export default {
|
|||
this.$emit('setGlobalReading', res.Result.IsGlobalReading)
|
||||
this.$emit('setOncologyReading', res.Result.IsOncologyReading)
|
||||
this.$emit('setDigitPlaces', res.Result.DigitPlaces)
|
||||
this.$emit('setReadingTools', { readingTools: res.Result.ReadingToolList, isNoneDicom: this.form.ReadingTool === 1 })
|
||||
this.$emit('setReadingTools', { readingTools: res.Result.ReadingToolList, readingSegmentTools: res.Result.SegmentToolList, ReadingTool: this.form.ReadingTool })
|
||||
|
||||
if (res.Result.ReadingType === 1) {
|
||||
this.$emit('setArbitrationReading', false)
|
||||
|
|
@ -859,7 +881,7 @@ export default {
|
|||
this.$emit('setGlobalReading', this.form.IsGlobalReading)
|
||||
this.$emit('setOncologyReading', this.form.IsOncologyReading)
|
||||
this.$emit('setDigitPlaces', this.form.DigitPlaces)
|
||||
this.$emit('setReadingTools', { readingTools: this.form.ReadingToolList, isNoneDicom: this.form.ReadingTool === 1 })
|
||||
this.$emit('setReadingTools', { readingTools: this.form.ReadingToolList, readingSegmentTools: this.form.SegmentToolList, ReadingTool: this.form.ReadingTool })
|
||||
if (this.form.ReadingType === 1) {
|
||||
this.$emit('setArbitrationReading', false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,8 +286,15 @@
|
|||
:disabled="form.IsRequired === 2 && item.value === 1">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量工具 ImageTool -->
|
||||
<!--标记类型-->
|
||||
<el-form-item v-if="form.ImageMarkEnum === 1 || form.ImageMarkEnum === 2"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageMarkTypeEnum')" prop="ImageMarkTypeEnum">
|
||||
<el-radio-group v-model="form.ImageMarkTypeEnum" @change="ImageMarkTypeEnumChange">
|
||||
<el-radio v-for="item of $d.ImageMarkType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量工具 ImageTool -->
|
||||
<el-form-item v-if="(form.ImageMarkEnum === 1 || form.ImageMarkEnum === 2) && form.ImageMarkTypeEnum === 0"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageTool')" prop="ImageTool" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select') }
|
||||
]">
|
||||
|
|
@ -297,6 +304,17 @@
|
|||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 分割工具 ImageTool -->
|
||||
<el-form-item v-if="(form.ImageMarkEnum === 1 || form.ImageMarkEnum === 2) && form.ImageMarkTypeEnum === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageTool')" prop="ImageTool" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select') }
|
||||
]">
|
||||
<el-radio-group v-model="form.ImageTool" @change="imageSegmentToolChange">
|
||||
<el-radio v-for="tool of readingSegmentTools" :key="tool.toolName" :label="tool.toolName">
|
||||
{{ $t(tool.i18nKey) }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量值 ImageToolAttribute -->
|
||||
<el-form-item v-if="form.ImageTool && imageToolAttributes.length > 0"
|
||||
:label="$t('trials:readingUnit:qsList:title:ImageToolAttribute')" prop="ImageToolAttribute" :rules="[
|
||||
|
|
@ -563,6 +581,12 @@ export default {
|
|||
return []
|
||||
}
|
||||
},
|
||||
readingSegmentTools: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingVersionEnum: {
|
||||
type: Number,
|
||||
default: 0
|
||||
|
|
@ -617,6 +641,7 @@ export default {
|
|||
ClassifyEditType: null,
|
||||
ClassifyShowType: null,
|
||||
ImageMarkEnum: 0,
|
||||
ImageMarkTypeEnum: 0,
|
||||
ShowChartTypeEnum: 0,
|
||||
ImageTool: '',
|
||||
ImageToolAttribute: '',
|
||||
|
|
@ -898,9 +923,12 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (this.form.ImageTool) {
|
||||
if (this.form.ImageTool && this.form.ImageMarkTypeEnum === 0) {
|
||||
this.imageToolChange(this.form.ImageTool)
|
||||
}
|
||||
if (this.form.ImageTool && this.form.ImageMarkTypeEnum === 1) {
|
||||
this.imageSegmentToolChange(this.form.ImageTool)
|
||||
}
|
||||
}
|
||||
if (this.form.ClassifyTableQuestionId) {
|
||||
this.classifyQuestionChange(this.form.ClassifyTableQuestionId)
|
||||
|
|
@ -1011,14 +1039,26 @@ export default {
|
|||
this.form.ImageTool = ''
|
||||
this.form.ImageToolAttribute = ''
|
||||
this.imageToolAttributes = []
|
||||
this.form.ImageMarkTypeEnum = 0
|
||||
}
|
||||
},
|
||||
ImageMarkTypeEnumChange(val) {
|
||||
this.form.ImageTool = ''
|
||||
this.form.ImageToolAttribute = ''
|
||||
this.imageToolAttributes = []
|
||||
},
|
||||
imageToolChange(v) {
|
||||
let i = this.readingTools.findIndex(tool => tool.toolName === v)
|
||||
if (i > -1) {
|
||||
this.imageToolAttributes = this.readingTools[i].props
|
||||
}
|
||||
},
|
||||
imageSegmentToolChange(v) {
|
||||
let i = this.readingSegmentTools.findIndex(tool => tool.toolName === v)
|
||||
if (i > -1) {
|
||||
this.imageToolAttributes = this.readingSegmentTools[i].props
|
||||
}
|
||||
},
|
||||
async parentQuestionChange(val, form) {
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
|
|
@ -1129,6 +1169,7 @@ export default {
|
|||
form.ClassifyType = null
|
||||
form.ClassifyShowType = null
|
||||
form.ImageMarkEnum = 0
|
||||
form.ImageMarkTypeEnum = 0
|
||||
form.ShowChartTypeEnum = 0
|
||||
form.ImageTool = ''
|
||||
form.ImageToolAttribute = ''
|
||||
|
|
|
|||
|
|
@ -1,73 +1,37 @@
|
|||
<template>
|
||||
<div v-loading="loading">
|
||||
<div
|
||||
class="search-form"
|
||||
style="text-align: right;"
|
||||
>
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem"
|
||||
size="mini"
|
||||
type="primary"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{$t('common:button:new')}}
|
||||
<div class="search-form" style="text-align: right;">
|
||||
<el-button v-if="!isConfirm && !isFromSystem" size="mini" type="primary" @click="handleAdd">
|
||||
{{ $t('common:button:new') }}
|
||||
</el-button>
|
||||
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
:data="list"
|
||||
size="small"
|
||||
height="100"
|
||||
>
|
||||
<el-table-column
|
||||
prop="ShowOrder"
|
||||
:label="$t('trials:qcCfg:table:order')"
|
||||
min-width="70"
|
||||
/>
|
||||
<el-table v-adaptive="{ bottomOffset: 60 }" :data="list" size="small" height="100">
|
||||
<el-table-column prop="ShowOrder" :label="$t('trials:qcCfg:table:order')" min-width="70" />
|
||||
<!-- 名称 -->
|
||||
<el-table-column
|
||||
prop="QuestionName"
|
||||
v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsName')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionName" v-if="$i18n.locale === 'zh'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsName')" show-overflow-tooltip />
|
||||
<!-- 名称(EN) -->
|
||||
<el-table-column
|
||||
prop="QuestionEnName"
|
||||
v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionEnName" v-if="$i18n.locale === 'en'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')" show-overflow-tooltip />
|
||||
<!-- 题型 -->
|
||||
<el-table-column
|
||||
prop="Type"
|
||||
:label="$t('trials:readingUnit:qsList:title:type')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="Type" :label="$t('trials:readingUnit:qsList:title:type')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('Criterion_Question_Type',scope.row.Type) }}
|
||||
{{ $fd('Criterion_Question_Type', scope.row.Type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否显示 -->
|
||||
<el-table-column
|
||||
prop="ShowQuestion"
|
||||
:label="$t('trials:readingUnit:qsList:title:isShow')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="ShowQuestion" :label="$t('trials:readingUnit:qsList:title:isShow')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('ShowQuestion',scope.row.ShowQuestion) }}
|
||||
{{ $fd('ShowQuestion', scope.row.ShowQuestion) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:readingUnit:qsList:title:isRequired')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="IsRequired" :label="$t('trials:readingUnit:qsList:title:isRequired')"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QuestionRequired',scope.row.IsRequired) }}
|
||||
{{ $fd('QuestionRequired', scope.row.IsRequired) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否裁判问题 -->
|
||||
|
|
@ -104,41 +68,26 @@
|
|||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- 导出目标表格 -->
|
||||
<el-table-column
|
||||
prop="ExportResult"
|
||||
:label="$t('trials:readingUnit:qsList:title:ExportResult')"
|
||||
width="160"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="ExportResult" :label="$t('trials:readingUnit:qsList:title:ExportResult')" width="160"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ getStringResult(scope.row.ExportResult, 'ExportResult') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 限制编辑 -->
|
||||
<el-table-column
|
||||
prop="LimitEdit"
|
||||
:label="$t('trials:readingUnit:qsList:title:limitEdit')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="LimitEdit" :label="$t('trials:readingUnit:qsList:title:limitEdit')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('LimitEdit', scope.row.LimitEdit) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsCopy"
|
||||
:label="$t('trials:readingUnit:qsList:title:PrecopyValue')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="IsCopy" :label="$t('trials:readingUnit:qsList:title:PrecopyValue')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsCopy) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 最大行数 -->
|
||||
<el-table-column
|
||||
prop="MaxRowCount"
|
||||
:label="$t('trials:readingUnit:qsList:title:MaxRowCount')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="MaxRowCount" :label="$t('trials:readingUnit:qsList:title:MaxRowCount')"
|
||||
show-overflow-tooltip>
|
||||
</el-table-column>
|
||||
<!-- 注释 -->
|
||||
<!-- <el-table-column
|
||||
|
|
@ -148,35 +97,15 @@
|
|||
show-overflow-tooltip
|
||||
>
|
||||
</el-table-column> -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('common:action:action')"
|
||||
width="200"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="" :label="$t('common:action:action')" width="200" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem"
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
<el-button v-if="!isConfirm && !isFromSystem" type="primary" size="mini" @click="handleEdit(scope.row)">
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
size="mini"
|
||||
@click="handleLook(scope.row)"
|
||||
>
|
||||
<el-button v-else type="primary" size="mini" @click="handleLook(scope.row)">
|
||||
{{ $t('trials:readingPeriod:button:view') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="!isConfirm && !isFromSystem"
|
||||
type="danger"
|
||||
size="mini"
|
||||
@click="handleDelete(scope.row)"
|
||||
>
|
||||
<el-button v-if="!isConfirm && !isFromSystem" type="danger" size="mini" @click="handleDelete(scope.row)">
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
|
||||
|
|
@ -184,29 +113,12 @@
|
|||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<el-dialog
|
||||
v-if="addOrEdit.visible"
|
||||
:visible.sync="addOrEdit.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="addOrEdit.title"
|
||||
width="600px"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<TableQsForm
|
||||
ref="addOrEdit"
|
||||
:data="rowData"
|
||||
:list="list"
|
||||
:type="type"
|
||||
:is-from-system="isFromSystem"
|
||||
:digit-places="digitPlaces"
|
||||
:reading-question-id="readingQuestionId"
|
||||
:criterion-id="criterionId"
|
||||
:readingTools="readingTools"
|
||||
:readingVersionEnum="readingVersionEnum"
|
||||
@close="addOrEdit.visible = false"
|
||||
@getList="getList"
|
||||
/>
|
||||
<el-dialog v-if="addOrEdit.visible" :visible.sync="addOrEdit.visible" :close-on-click-modal="false"
|
||||
:title="addOrEdit.title" width="600px" append-to-body custom-class="base-dialog-wrapper">
|
||||
<TableQsForm ref="addOrEdit" :data="rowData" :list="list" :type="type" :is-from-system="isFromSystem"
|
||||
:digit-places="digitPlaces" :reading-question-id="readingQuestionId" :criterion-id="criterionId"
|
||||
:readingTools="readingTools" :readingSegmentTools="readingSegmentTools" :readingVersionEnum="readingVersionEnum"
|
||||
@close="addOrEdit.visible = false" @getList="getList" />
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
|
|
@ -250,6 +162,12 @@ export default {
|
|||
return []
|
||||
}
|
||||
},
|
||||
readingSegmentTools: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingVersionEnum: {
|
||||
type: Number,
|
||||
default: 0
|
||||
|
|
@ -296,9 +214,9 @@ export default {
|
|||
this.type = 'look'
|
||||
let title = ''
|
||||
if (this.$i18n.locale === 'zh' && (row.QuestionName || row.GroupName)) {
|
||||
title =`:${row.QuestionName ? row.QuestionName : row.GroupName}`
|
||||
title = `:${row.QuestionName ? row.QuestionName : row.GroupName}`
|
||||
} else if (this.$i18n.locale === 'en' && (row.QuestionEnName || row.GroupEnName)) {
|
||||
title =`: ${row.QuestionEnName ? row.QuestionEnName : row.GroupEnName}`
|
||||
title = `: ${row.QuestionEnName ? row.QuestionEnName : row.GroupEnName}`
|
||||
}
|
||||
this.addOrEdit.title = `${this.$t('trials:readingPeriod:button:view')}${title}`
|
||||
this.addOrEdit.visible = true
|
||||
|
|
@ -337,4 +255,3 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
<el-collapse-item :title="$t('trials:readingUnit:readingCriterion')" name="2">
|
||||
<ReadingCriterions :ref="`readingCriterions${item.TrialReadingCriterionId}`"
|
||||
:trial-reading-criterion-id="TrialReadingCriterionId" :digit-places="digitPlaces"
|
||||
:readingTools="readingTools" :is-additional-assessment="isAdditionalAssessment"
|
||||
@reloadArbitrationRules="reloadArbitrationRules" />
|
||||
:readingTools="readingTools" :readingSegmentTools="readingSegmentTools"
|
||||
:is-additional-assessment="isAdditionalAssessment" @reloadArbitrationRules="reloadArbitrationRules" />
|
||||
</el-collapse-item>
|
||||
<!-- 全局阅片 -->
|
||||
<el-collapse-item v-if="isGlobalReading && CriterionType !== 10"
|
||||
|
|
@ -107,7 +107,7 @@ import GlobalReading from "./components/GlobalReading";
|
|||
import OncologyForm from "./components/OncologyForm";
|
||||
import SignForm from "@/views/trials/components/newSignForm";
|
||||
import const_ from "@/const/sign-code";
|
||||
import { getCustomizeStandardsTools, getCustomizeStandardsNoneDicomTools } from '@/views/trials/trials-panel/reading/dicoms3D/components/toolConfig'
|
||||
import { getCustomizeStandardsTools, getCustomizeStandardsNoneDicomTools, getCustomizeStandardsSegmentDicomTools } from '@/views/trials/trials-panel/reading/dicoms3D/components/toolConfig'
|
||||
export default {
|
||||
name: "ReadingUnit",
|
||||
components: {
|
||||
|
|
@ -141,7 +141,8 @@ export default {
|
|||
isGlobalReading: false,
|
||||
digitPlaces: 0,
|
||||
isAdditionalAssessment: false,
|
||||
readingTools: []
|
||||
readingTools: [],
|
||||
readingSegmentTools: []
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -230,13 +231,16 @@ export default {
|
|||
this.digitPlaces = digitPlaces;
|
||||
},
|
||||
setReadingTools(data) {
|
||||
let { readingTools, isNoneDicom } = data
|
||||
if (isNoneDicom) {
|
||||
let { readingTools, readingSegmentTools, ReadingTool } = data
|
||||
if (ReadingTool === 1) {
|
||||
this.readingTools = getCustomizeStandardsNoneDicomTools(readingTools)
|
||||
} else {
|
||||
this.readingTools = getCustomizeStandardsTools(readingTools)
|
||||
}
|
||||
|
||||
if (ReadingTool === 3) {
|
||||
this.readingSegmentTools = getCustomizeStandardsSegmentDicomTools(readingSegmentTools)
|
||||
}
|
||||
console.log(this.readingSegmentTools, 'this.readingSegmentTools')
|
||||
},
|
||||
setIsClinicalReading(isClinicalReading) {
|
||||
this.isClinicalReading = isClinicalReading;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ export default {
|
|||
'#505372',
|
||||
'#ff994d',
|
||||
'#fb628b',
|
||||
|
||||
],
|
||||
trialCriterionList: [],
|
||||
loading_left: false,
|
||||
|
|
|
|||
Loading…
Reference in New Issue