suv融合
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
f53412acbf
commit
02fcc4a2c1
|
@ -0,0 +1,276 @@
|
|||
<template>
|
||||
<el-form ref="fusionForm" :model="fusionForm" label-width="120px" label-position="left">
|
||||
<!-- 任务名称 -->
|
||||
<el-form-item :label="$t('trials:lugano:fusionDialog:label:taskBlindName')" prop="taskBlindName">
|
||||
<el-select v-model="fusionForm.visitTaskId" clearable @change="handleTaskIdChange">
|
||||
<el-option v-for="item in taskList" :key="item.VisitTaskId" :label="item.TaskBlindName"
|
||||
:value="item.VisitTaskId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 检查 -->
|
||||
<el-form-item :label="$t('trials:lugano:fusionDialog:label:study')" prop="studyId" :rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select'), trigger: 'blur' }
|
||||
]">
|
||||
<el-select v-model="fusionForm.studyId" clearable @change="handleStudyIdChange">
|
||||
<el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode" :value="item.StudyId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 融合图像 -->
|
||||
<label style="color: #dfdfdf;line-height: 36px;vertical-align: middle;font-size: 14px;">{{
|
||||
$t('trials:lugano:fusionDialog:label:fusionImages') }}</label>
|
||||
<div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom:10px;"
|
||||
class="series-table">
|
||||
|
||||
<div style="border: 1px solid #5e5e5e;border-radius: 5px;padding: 0 10px;">
|
||||
<!-- CT/MRI序列 -->
|
||||
<h3 style="color:#ddd">{{ $t('trials:lugano:fusionDialog:label:ctSeries') }}</h3>
|
||||
<el-table ref="ctSeries" :data="ctSeries" :show-header="false" style="width: 380px" size="mini" height="300"
|
||||
:default-sort="{ prop: 'instanceCount', order: 'descending' }" @selection-change="handleCTSelectionChange"
|
||||
@select="handleCTSelect">
|
||||
|
||||
<el-table-column type="selection" width="30" />
|
||||
<el-table-column label="" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-image style="width: 60px; height: 60px"
|
||||
:src="`${OSSclientConfig.basePath}${scope.row.ImageResizePath}`" fit="fit" crossorigin="anonymous" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="" min-width="50" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<div>#{{ scope.row.SeriesNumber }} </div>
|
||||
<div>{{ scope.row.Modality }}: {{ scope.row.InstanceCount }} images T: {{
|
||||
parseFloat(scope.row.SliceThickness).toFixed(digitPlaces) }}</div>
|
||||
<div>{{ scope.row.Description }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="border: 1px solid #5e5e5e;border-radius: 5px;padding: 0 10px;">
|
||||
<!-- PET序列 -->
|
||||
<h3 style="color:#ddd">{{ $t('trials:lugano:fusionDialog:label:ptSeries') }}</h3>
|
||||
<el-table ref="petSeries" :data="petSeries" :show-header="false" style="width: 380px" size="mini" height="300"
|
||||
@selection-change="handlePTSelectionChange" @select="handlePTSelect">
|
||||
<el-table-column type="selection" width="30" />
|
||||
<el-table-column label="" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-image style="width: 60px; height: 60px"
|
||||
:src="`${OSSclientConfig.basePath}${scope.row.ImageResizePath}`" fit="fit" crossorigin="anonymous" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="" min-width="50" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<div>#{{ scope.row.SeriesNumber }} </div>
|
||||
<div>{{ scope.row.Modality }}: {{ scope.row.InstanceCount }} images T: {{
|
||||
parseFloat(scope.row.SliceThickness).toFixed(digitPlaces) }}</div>
|
||||
<div>{{ scope.row.Description }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<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="handleSubmitFusionSeries">
|
||||
{{ $t('common:button:confirm') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'FusionForm',
|
||||
props: {
|
||||
taskList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
activeTaskIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fusionForm: {
|
||||
visitTaskId: '',
|
||||
studyId: '',
|
||||
taskBlindName: '',
|
||||
isBaseLineTask: null,
|
||||
ctSeriesInfo: {},
|
||||
petSeriesInfo: {},
|
||||
defaultStudyId: '',
|
||||
defaultCTSeriesId: '',
|
||||
defaultPTSeriesId: ''
|
||||
},
|
||||
studyList: [],
|
||||
ctSeries: [],
|
||||
petSeries: [],
|
||||
petctWindow: null,
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
initForm() {
|
||||
if (this.taskList.length === 0) return
|
||||
this.getStudyList(this.taskList[this.activeTaskIndex])
|
||||
this.handleStudyIdChange(this.studyList[0].StudyId)
|
||||
if (this.studyList.length > 0) {
|
||||
this.fusionForm.studyId = this.studyList[0].StudyId
|
||||
this.handleStudyIdChange(this.studyList[0].StudyId)
|
||||
} else {
|
||||
this.fusionForm.studyId = ''
|
||||
this.ctSeries = []
|
||||
this.petSeries = []
|
||||
}
|
||||
this.fusionForm.visitTaskId = this.taskList[this.activeTaskIndex].VisitTaskId
|
||||
this.fusionForm.readingTaskState = this.taskList[this.activeTaskIndex].ReadingTaskState
|
||||
this.fusionForm.taskBlindName = this.taskList[this.activeTaskIndex].TaskBlindName
|
||||
this.fusionForm.subjectCode = this.taskList[this.activeTaskIndex].SubjectCode
|
||||
this.fusionForm.isBaseLineTask = this.taskList[this.activeTaskIndex].IsBaseLineTask
|
||||
this.fusionForm.isCurrentTask = this.taskList[this.activeTaskIndex].IsCurrentTask
|
||||
},
|
||||
getStudyList(obj) {
|
||||
if (obj) {
|
||||
var studyList = obj.StudyList || []
|
||||
studyList = studyList.filter(i => !i.IsCriticalSequence && i.Modalities.indexOf('CT') !== -1 && i.Modalities.indexOf('PT') !== -1)
|
||||
if (studyList.length === 0) return
|
||||
this.studyList = studyList
|
||||
}
|
||||
},
|
||||
handleSubmitFusionSeries() {
|
||||
this.$refs['fusionForm'].validate((valid) => {
|
||||
if (!valid) return
|
||||
if (Object.keys(this.fusionForm.ctSeriesInfo).length === 0 || Object.keys(this.fusionForm.petSeriesInfo).length === 0) {
|
||||
// '请选择序列信息!'
|
||||
this.$confirm(this.$t('trials:lugano:fusionDialog:message:checkSeries'), this.$t('trials:lugano:fusionDialog:warning'), {
|
||||
showCancelButton: false,
|
||||
type: 'warning'
|
||||
}).then(() => { }).catch(() => { })
|
||||
return
|
||||
}
|
||||
var count = Math.abs(this.fusionForm.ctSeriesInfo.instanceCount - this.fusionForm.petSeriesInfo.instanceCount)
|
||||
if (count > 10) {
|
||||
// '选择的两组序列,影像数存在较大差距, 是否继续?'
|
||||
this.$confirm(this.$t('trials:lugano:fusionDialog:message:validSeries'), this.$t('trials:lugano:fusionDialog:warning'), {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.fusion()
|
||||
}).catch(() => { })
|
||||
} else {
|
||||
this.fusion()
|
||||
}
|
||||
})
|
||||
},
|
||||
fusion() {
|
||||
this.$emit('fusion', { ct: this.fusionForm.ctSeriesInfo, pt: this.fusionForm.petSeriesInfo })
|
||||
},
|
||||
handleCancel() {
|
||||
this.$emit('close')
|
||||
},
|
||||
handleTaskIdChange(v) {
|
||||
var idx = this.taskList.findIndex(i => i.VisitTaskId === v)
|
||||
this.studyList = idx > -1 ? this.getStudyList(this.taskList[idx]) : []
|
||||
this.fusionForm.taskBlindName = idx > -1 ? this.taskList[idx].TaskBlindName : ''
|
||||
this.fusionForm.isBaseLineTask = idx > -1 ? this.taskList[idx].IsBaseLineTask : null
|
||||
this.studyList = idx > -1 ? this.taskList[idx].StudyList : null
|
||||
this.fusionForm.studyId = ''
|
||||
this.fusionForm.defaultStudyId = idx > -1 ? this.taskList[idx].StudyId : ''
|
||||
this.fusionForm.defaultCTSeriesId = idx > -1 ? this.taskList[idx].CTSeriesId : ''
|
||||
this.fusionForm.defaultPTSeriesId = idx > -1 ? this.taskList[idx].PTSeriesId : ''
|
||||
this.ctSeries = []
|
||||
this.petSeries = []
|
||||
},
|
||||
handleStudyIdChange(v) {
|
||||
var i = this.studyList.findIndex(i => i.StudyId === v)
|
||||
if (i === -1) {
|
||||
this.ctSeries = []
|
||||
this.petSeries = []
|
||||
} else {
|
||||
var seriesList = this.studyList[i].SeriesList
|
||||
var series = seriesList.filter(series => series.Modality === 'CT')
|
||||
this.ctSeries = series.sort((a, b) => b.instanceCount - a.instanceCount)
|
||||
|
||||
series = seriesList.filter(series => series.Modality === 'PT')
|
||||
this.petSeries = series.sort((a, b) => b.instanceCount - a.instanceCount)
|
||||
}
|
||||
},
|
||||
handleCTSelectionChange(rows) {
|
||||
if (rows.length > 0) {
|
||||
this.fusionForm.ctSeriesInfo = Object.assign({}, rows[0])
|
||||
} else {
|
||||
this.fusionForm.ctSeriesInfo = {}
|
||||
}
|
||||
},
|
||||
handleCTSelect(selection) {
|
||||
if (selection.length > 1) {
|
||||
const del_row = selection.shift()
|
||||
this.$refs.ctSeries.toggleRowSelection(del_row, false)
|
||||
}
|
||||
},
|
||||
handlePTSelectionChange(rows) {
|
||||
if (rows.length > 0) {
|
||||
this.fusionForm.petSeriesInfo = Object.assign({}, rows[0])
|
||||
} else {
|
||||
this.fusionForm.petSeriesInfo = {}
|
||||
}
|
||||
},
|
||||
handlePTSelect(selection) {
|
||||
if (selection.length > 1) {
|
||||
const del_row = selection.shift()
|
||||
this.$refs.petSeries.toggleRowSelection(del_row, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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>
|
|
@ -921,11 +921,13 @@ export default {
|
|||
this.rows = 2;
|
||||
this.cols = 2;
|
||||
this.$refs[`viewport-${0}`][0].setSeriesInfo(this.ctSeriesInfo)
|
||||
this.$refs[`viewport-${1}`][0].setSeriesInfo(this.petSeriesInfo)
|
||||
this.$refs[`viewport-${2}`][0].setSeriesInfo({ ct: this.ctSeriesInfo, pet: this.petSeriesInfo }, false, { isFusion: true })
|
||||
this.$refs[`viewport-${3}`][0].setSeriesInfo(this.petSeriesInfo, false, { isMip: true })
|
||||
this.$refs[`viewport-${1}`][0].setSeriesInfo(this.petSeriesInfo, false, { colorMap: true })
|
||||
this.$refs[`viewport-${2}`][0].setSeriesInfo({ ct: this.ctSeriesInfo, pet: this.petSeriesInfo }, false, { isFusion: true, colorMap: true })
|
||||
this.$refs[`viewport-${3}`][0].setSeriesInfo(this.petSeriesInfo, false, { isMip: true, colorMap: true })
|
||||
this.cellType = ['CT', 'PT', 'FUSION', 'MIP']
|
||||
this.$nextTick(() => {
|
||||
this.setColorMap(this.rgbPresetName)
|
||||
})
|
||||
},
|
||||
handleStudyIdChange(v) {
|
||||
var i = this.studyList.findIndex(i => i.StudyId === v)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div ref="viewport" class="viewport-wrapper" @mouseup="sliderMouseup" @mousemove="sliderMousemove"
|
||||
<div ref="viewport-fusion" class="viewport-wrapper" @mouseup="sliderMouseup" @mousemove="sliderMousemove"
|
||||
@mouseleave="sliderMouseleave">
|
||||
<div v-if="series && taskInfo" class="left-top-text">
|
||||
<div v-if="taskInfo.IsExistsClinicalData && !isMip && !isFusion" class="cd-info"
|
||||
|
@ -38,7 +38,7 @@
|
|||
<div>{{ series.Description }}</div>
|
||||
</div>
|
||||
<div v-if="series" class="left-bottom-text">
|
||||
<div v-show="mousePosition.index.length > 0">
|
||||
<div v-show="mousePosition.index.length > 0 && !isMip">
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
|
||||
</div>
|
||||
<div
|
||||
|
@ -184,6 +184,7 @@ export default {
|
|||
initLeft: null,
|
||||
isMove: false
|
||||
},
|
||||
ptVolumeId: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -196,7 +197,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
initViewport() {
|
||||
this.element = this.$refs['viewport']
|
||||
this.element = this.$refs['viewport-fusion']
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
if (renderingEngine) {
|
||||
|
@ -243,7 +244,17 @@ export default {
|
|||
this.imageInfo.size = `${imagePlaneModule.columns}*${imagePlaneModule.rows}`
|
||||
this.imageInfo.location = imagePlaneModule.sliceLocation
|
||||
this.getOrientationMarker()
|
||||
this.$emit('renderAnnotations', this.series)
|
||||
// this.$emit('renderAnnotations', this.series)
|
||||
var properties = viewport.getProperties()
|
||||
|
||||
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)}`
|
||||
}
|
||||
// const toolGroupId = `viewport-${this.viewportIndex}`
|
||||
// const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
// toolGroup.setToolEnabled('ScaleOverlay')
|
||||
|
@ -295,7 +306,6 @@ export default {
|
|||
},
|
||||
resetOrientationMarkers() {
|
||||
if (this.originalMarkers.length > 0) {
|
||||
console.log(this.originalMarkers)
|
||||
this.orientationMarkers = [...this.originalMarkers]
|
||||
this.setMarkers()
|
||||
}
|
||||
|
@ -388,6 +398,18 @@ export default {
|
|||
// this.$refs[vp.id].voiModified()
|
||||
this.voiModified()
|
||||
})
|
||||
if (this.ptVolumeId) {
|
||||
const viewportsContainingVolumeUIDPT = csUtils.getViewportsWithVolumeId(
|
||||
this.ptVolumeId,
|
||||
viewport.renderingEngineId
|
||||
)
|
||||
|
||||
viewport.setProperties({ voiRange }, this.ptVolumeId)
|
||||
viewportsContainingVolumeUIDPT.forEach((vp) => {
|
||||
vp.render()
|
||||
this.voiModified()
|
||||
})
|
||||
}
|
||||
},
|
||||
renderColorBar(presetName) {
|
||||
var colorMap = null
|
||||
|
@ -470,78 +492,64 @@ export default {
|
|||
imageIds: obj.ImageIds
|
||||
})
|
||||
},
|
||||
async setSeriesInfo(obj, isLocate = false, option = {}) {
|
||||
async setSeriesInfo(obj, option = {}) {
|
||||
try {
|
||||
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) {
|
||||
obj.SliceIndex = this.series.SliceIndex
|
||||
let { data, volumeId } = obj
|
||||
if (this.series && data.Id === this.series.Id && data.Description === this.series.Description) {
|
||||
data.SliceIndex = this.series.SliceIndex
|
||||
}
|
||||
this.ptVolumeId = null
|
||||
this.series = {}
|
||||
let { isFusion, isMip } = option
|
||||
let { isFusion, isMip, colorMap } = option
|
||||
this.isFusion = isFusion;
|
||||
this.isMip = isMip;
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
viewport.setOrientation(OrientationAxis.AXIAL)
|
||||
const toolGroup = ToolGroupManager.getToolGroup(this.viewportId)
|
||||
toolGroup.setToolEnabled(MIPJumpToClickTool.toolName)
|
||||
toolGroup.setToolEnabled(VolumeRotateTool.toolName)
|
||||
if (this.isFusion) {
|
||||
this.$nextTick(() => {
|
||||
this.renderColorBar(this.presetName)
|
||||
})
|
||||
let { ct, pet } = obj
|
||||
this.series = { ...pet }
|
||||
let { ct, data, ctVolumeId, ptVolumeId, fusionVolumeId } = obj
|
||||
this.series = { ...data }
|
||||
this.ctSeries = { ...ct }
|
||||
this.petSeries = { ...pet }
|
||||
const maxCount = Math.max(this.ctSeries.ImageIds.length, this.petSeries.ImageIds.length)
|
||||
this.$set(this.ctSeries, 'imageMaxLength', maxCount)
|
||||
this.$set(this.petSeries, 'imageMaxLength', maxCount)
|
||||
await this.createImageIdsAndCacheMetaData(this.ctSeries)
|
||||
await this.createImageIdsAndCacheMetaData(this.petSeries)
|
||||
let ctVolumeId =
|
||||
'fusion_ct' + ':' + csUtils.uuidv4()
|
||||
let ctVolume = await volumeLoader.createAndCacheVolume(ctVolumeId, { imageIds: this.ctSeries.ImageIds })
|
||||
this.volumeId =
|
||||
'fusion_ct' + ':' + csUtils.uuidv4()
|
||||
let petVolume = await volumeLoader.createAndCacheVolume(this.volumeId, { imageIds: this.petSeries.ImageIds })
|
||||
ctVolume.load();
|
||||
petVolume.load();
|
||||
this.petSeries = { ...data }
|
||||
// const maxCount = Math.max(this.ctSeries.ImageIds.length, this.petSeries.ImageIds.length)
|
||||
// this.$set(this.ctSeries, 'imageMaxLength', maxCount)
|
||||
// this.$set(this.petSeries, 'imageMaxLength', maxCount)
|
||||
// await this.createImageIdsAndCacheMetaData(this.ctSeries)
|
||||
// await this.createImageIdsAndCacheMetaData(this.petSeries)
|
||||
this.volumeId = ptVolumeId
|
||||
this.ptVolumeId = fusionVolumeId
|
||||
await viewport
|
||||
.setVolumes([{
|
||||
.setVolumes([
|
||||
{
|
||||
volumeId: this.ptVolumeId, callback: (r) => {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
console.log("融合pet渲染成功");
|
||||
}
|
||||
},
|
||||
{
|
||||
volumeId: ctVolumeId, callback: (r) => {
|
||||
setCtTransferFunctionForVolumeActor(r)
|
||||
console.log("融合ct渲染成功")
|
||||
}
|
||||
}, {
|
||||
},
|
||||
{
|
||||
volumeId: this.volumeId, callback: (r) => {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
console.log("融合pet渲染成功");
|
||||
}
|
||||
}])
|
||||
},
|
||||
]).then(res => {
|
||||
if (colorMap) {
|
||||
this.setColorMap(this.presetName)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.series = { ...obj }
|
||||
await this.createImageIdsAndCacheMetaData(obj)
|
||||
this.volumeId =
|
||||
'volume' + ':' + csUtils.uuidv4()
|
||||
let volume = await volumeLoader.createAndCacheVolume(this.volumeId, { imageIds: obj.ImageIds })
|
||||
|
||||
volume.load();
|
||||
this.series = { ...data }
|
||||
this.volumeId = volumeId
|
||||
if (this.isMip) {
|
||||
viewport.setOrientation(OrientationAxis.CORONAL);
|
||||
toolGroup.setToolActive(VolumeRotateTool.toolName, {
|
||||
bindings: [
|
||||
{
|
||||
mouseButton: MouseBindings.Wheel, // mouse wheel
|
||||
},
|
||||
],
|
||||
})
|
||||
toolGroup.setToolActive(MIPJumpToClickTool.toolName, {
|
||||
bindings: [
|
||||
{
|
||||
mouseButton: MouseBindings.Primary, // Left Click
|
||||
},
|
||||
],
|
||||
})
|
||||
let { volume } = obj
|
||||
const ptVolumeDimensions = volume.dimensions;
|
||||
const slabThickness = Math.sqrt(
|
||||
ptVolumeDimensions[0] * ptVolumeDimensions[0] +
|
||||
|
@ -552,6 +560,7 @@ export default {
|
|||
.setVolumes([{
|
||||
volumeId: this.volumeId,
|
||||
callback: (r) => {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
console.log("mip渲染成功")
|
||||
},
|
||||
slabThickness,
|
||||
|
@ -559,23 +568,31 @@ export default {
|
|||
defaultOptions: {
|
||||
orientation: OrientationAxis.CORONAL
|
||||
}
|
||||
}])
|
||||
}]).then(res => {
|
||||
if (colorMap) {
|
||||
this.setColorMap(this.presetName)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
viewport
|
||||
.setVolumes([{
|
||||
volumeId: this.volumeId, callback: (r) => {
|
||||
if (this.series.Modality === 'PT') {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
} else {
|
||||
setCtTransferFunctionForVolumeActor(r)
|
||||
}
|
||||
console.log("渲染成功")
|
||||
}
|
||||
}])
|
||||
}]).then(res => {
|
||||
if (colorMap) {
|
||||
this.setColorMap(this.presetName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
viewport.render()
|
||||
if (!this.series.cellType) {
|
||||
if (this.isFusion) return this.series.cellType = 'FUSION'
|
||||
if (this.isMip) return this.series.cellType = 'MIP'
|
||||
this.series.cellType = this.series.Modality
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
@ -660,7 +677,7 @@ export default {
|
|||
},
|
||||
handletoolsMouseWheel(e) {
|
||||
const { viewportId, wheel } = e.detail
|
||||
if (this.series.cellType === 'MIP') {
|
||||
if (this.isMip) {
|
||||
const container = document.getElementById('rotateBar')
|
||||
const slider = document.getElementById('rotateSlider')
|
||||
const containerWidth = container.offsetWidth
|
||||
|
@ -922,7 +939,7 @@ export default {
|
|||
bottom: 5px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #fff;
|
||||
background: #333;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="read-page-container">
|
||||
<div v-loading="loading" :element-loading-text="loadingText" element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)" class="read-page-container">
|
||||
<!-- 检查列表 -->
|
||||
<div class="left-panel">
|
||||
<div class="task-container">
|
||||
|
@ -42,9 +43,9 @@
|
|||
<div class="tools-left">
|
||||
<!-- 布局 -->
|
||||
<div
|
||||
class="tool-item"
|
||||
:class="['tool-item', isFusion ? 'tool-disabled' : '']"
|
||||
:title="$t('trials:reading:button:layout')"
|
||||
@click.stop="showPanel($event)"
|
||||
@click.stop="showPanel($event, 'layout')"
|
||||
@mouseleave="toolMouseout"
|
||||
>
|
||||
<div class="dropdown">
|
||||
|
@ -198,6 +199,10 @@
|
|||
<svg-icon v-if="forceFitToWindow" icon-class="fitToWindow" class="svg-icon" />
|
||||
<svg-icon v-else icon-class="fitToImage" class="svg-icon" />
|
||||
</div>
|
||||
<!--融合-->
|
||||
<div class="tool-item" :title="$t('trials:lugano:button:fusion')" @click.prevent="openFusion" v-if="readingTool === 2">
|
||||
<svg-icon icon-class="fusion" class="svg-icon" />
|
||||
</div>
|
||||
<div
|
||||
v-for="tool in tools"
|
||||
:key="tool.toolName"
|
||||
|
@ -297,6 +302,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 伪彩 -->
|
||||
<template v-if="readingTool === 2">
|
||||
<colorMap v-show="isFusion" ref="colorMap" @setColorMap="setColorMap" @voiChange="voiChange" />
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
|
@ -331,8 +340,8 @@
|
|||
<div ref="container" class="grid-container" :style="gridStyle">
|
||||
<div
|
||||
v-for="(v, index) in cellsMax"
|
||||
v-show="index < cells.length"
|
||||
:key="index"
|
||||
v-show="index < cells.length && !isFusion"
|
||||
:key="`viewport-${index}`"
|
||||
:style="cellStyle"
|
||||
:class="['grid-cell', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
@dblclick="toggleFullScreen($event, index)"
|
||||
|
@ -350,6 +359,29 @@
|
|||
@renderAnnotations="renderAnnotations"
|
||||
/>
|
||||
</div>
|
||||
<template v-if="readingTool === 2">
|
||||
<div
|
||||
v-for="(v, index) in cellsMax"
|
||||
v-show="index < cells.length && isFusion"
|
||||
:key="`viewport-fusion-${index}`"
|
||||
:style="cellStyle"
|
||||
:class="['grid-cell', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
@dblclick="toggleFullScreen($event, index)"
|
||||
@click="activeViewport(index)"
|
||||
>
|
||||
<PetCtViewport
|
||||
:ref="`viewport-fusion-${index}`"
|
||||
:data-viewport-uid="`viewport-fusion-${index}`"
|
||||
:rendering-engine-id="renderingEngineId"
|
||||
:viewport-id="`viewport-fusion-${index}`"
|
||||
:viewport-index="index"
|
||||
@activeViewport="activeViewport"
|
||||
@toggleTaskByViewport="toggleTaskByViewport"
|
||||
@previewCD="previewCD"
|
||||
@renderAnnotations="renderAnnotations"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 表单 -->
|
||||
|
@ -486,6 +518,10 @@
|
|||
</div>
|
||||
|
||||
</el-dialog>
|
||||
<el-dialog :visible.sync="fusionVisible" :close-on-click-modal="false" :title="$t('trials:lugano:button:record')"
|
||||
width="850px" >
|
||||
<FusionForm v-if="fusionVisible" :activeTaskIndex="activeTaskIndex" :taskList="visitTaskList" @close="closeFusion" @fusion="handleFusion" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -497,6 +533,7 @@ import {
|
|||
Enums,
|
||||
// imageLoader,
|
||||
// metaData,
|
||||
volumeLoader,
|
||||
getRenderingEngine,
|
||||
eventTarget,
|
||||
utilities as csUtils,
|
||||
|
@ -511,6 +548,7 @@ import html2canvas from 'html2canvas'
|
|||
import { getTools, getCustomizeStandardsTools, config } from './toolConfig'
|
||||
import StudyList from './StudyList'
|
||||
import Viewport from './Viewport'
|
||||
import PetCtViewport from './PetCtViewport'
|
||||
import mRecisit from './mRecist/QuestionList'
|
||||
import recisit from './Recist/QuestionList'
|
||||
import customizeQuestionList from './customize/QuestionList'
|
||||
|
@ -520,6 +558,8 @@ import Hotkeys from '@/views/trials/trials-panel/reading/dicoms/components/Hotke
|
|||
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 colorMap from './colorMap.vue'
|
||||
const { visibility } = annotation
|
||||
const { ViewportType, Events } = Enums
|
||||
const renderingEngineId = 'myRenderingEngine'
|
||||
|
@ -539,7 +579,9 @@ const {
|
|||
RectangleROITool,
|
||||
PlanarFreehandROITool,
|
||||
CircleROITool,
|
||||
EraserTool
|
||||
EraserTool,
|
||||
MIPJumpToClickTool,
|
||||
VolumeRotateTool,
|
||||
// cursors
|
||||
} = cornerstoneTools
|
||||
|
||||
|
@ -570,9 +612,16 @@ annotation.config.style.setDefaultToolStyles(newStyles)
|
|||
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||
export default {
|
||||
name: 'ReadPage',
|
||||
props: {
|
||||
readingTool: {
|
||||
type: Number,
|
||||
default: 2
|
||||
}
|
||||
},
|
||||
components: {
|
||||
StudyList,
|
||||
Viewport,
|
||||
PetCtViewport,
|
||||
mRecisit,
|
||||
recisit,
|
||||
customizeQuestionList,
|
||||
|
@ -581,7 +630,9 @@ export default {
|
|||
Hotkeys,
|
||||
WL,
|
||||
Others,
|
||||
ClinicalData
|
||||
ClinicalData,
|
||||
FusionForm,
|
||||
colorMap
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -645,7 +696,13 @@ export default {
|
|||
instanceInfo: {},
|
||||
lastViewportTaskIds: [],
|
||||
markedSeriesIds: [],
|
||||
customizeStandards: []
|
||||
customizeStandards: [],
|
||||
|
||||
fusionVisible: false,
|
||||
isFusion: false,
|
||||
studyList: [],
|
||||
volumeData: {},
|
||||
loadingText: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -668,6 +725,9 @@ export default {
|
|||
},
|
||||
cells() {
|
||||
return Array(this.rows * this.cols).fill(0)
|
||||
},
|
||||
viewportKey() {
|
||||
return this.isFusion ? 'viewport-fusion' : 'viewport'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -682,9 +742,9 @@ export default {
|
|||
immediate: true,
|
||||
handler(index) {
|
||||
let series = null
|
||||
if (this.$refs[`viewport-${this.activeViewportIndex}`] && this.$refs[`viewport-${this.activeViewportIndex}`][0]) {
|
||||
this.clipPlaying = this.$refs[`viewport-${this.activeViewportIndex}`][0].playClipState
|
||||
series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
if (this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`] && this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0]) {
|
||||
this.clipPlaying = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].playClipState
|
||||
series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
} else {
|
||||
this.clipPlaying = false
|
||||
this.fps = 15
|
||||
|
@ -950,7 +1010,7 @@ export default {
|
|||
|
||||
if (activeStudyIndex > -1 && activeSeriesIndex > -1) {
|
||||
seriesArr.map((i, index) => {
|
||||
this.$refs[`viewport-${index}`][0].setSeriesInfo(i)
|
||||
this.$refs[`${this.viewportKey}-${index}`][0].setSeriesInfo(i)
|
||||
})
|
||||
const visitTaskId = this.visitTaskList[this.activeTaskIndex].VisitTaskId
|
||||
this.lastViewportTaskId = visitTaskId
|
||||
|
@ -971,7 +1031,7 @@ export default {
|
|||
const element3 = this.$refs['viewport-2'][0].$el
|
||||
const element4 = this.$refs['viewport-3'][0].$el
|
||||
|
||||
const viewportInputArray = [
|
||||
let viewportInputArray = [
|
||||
{
|
||||
viewportId: 'viewport-0',
|
||||
type: ViewportType.STACK,
|
||||
|
@ -993,7 +1053,52 @@ export default {
|
|||
element: element4
|
||||
}
|
||||
]
|
||||
const viewportIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3']
|
||||
let viewportIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3']
|
||||
let fusionViewportIds = ["viewport-fusion-0", "viewport-fusion-1", "viewport-fusion-2", "viewport-fusion-3"]
|
||||
if(this.readingTool === 2){
|
||||
const fusionElement1 = this.$refs['viewport-fusion-0'][0].$el
|
||||
const fusionElement2 = this.$refs['viewport-fusion-1'][0].$el
|
||||
const fusionElement3 = this.$refs['viewport-fusion-2'][0].$el
|
||||
const fusionElement4 = this.$refs['viewport-fusion-3'][0].$el
|
||||
let arr = [
|
||||
{
|
||||
viewportId: 'viewport-fusion-0',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: fusionElement1,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL
|
||||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-fusion-1',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: fusionElement2,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL,
|
||||
// background: [1, 1, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-fusion-2',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: fusionElement3,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.AXIAL
|
||||
}
|
||||
},
|
||||
{
|
||||
viewportId: 'viewport-fusion-3',
|
||||
type: ViewportType.ORTHOGRAPHIC,
|
||||
element: fusionElement4,
|
||||
defaultOptions: {
|
||||
orientation: Enums.OrientationAxis.CORONAL,
|
||||
// background: [1, 1, 1]
|
||||
}
|
||||
}
|
||||
]
|
||||
viewportInputArray = [ ...viewportInputArray, ...arr ]
|
||||
viewportIds = viewportIds.concat(fusionViewportIds)
|
||||
}
|
||||
renderingEngine.setViewports(viewportInputArray)
|
||||
this.addAnnotationListeners()
|
||||
cornerstoneTools.addTool(StackScrollTool)
|
||||
|
@ -1010,9 +1115,12 @@ export default {
|
|||
cornerstoneTools.addTool(BidirectionalTool)
|
||||
cornerstoneTools.addTool(ScaleOverlayTool)
|
||||
cornerstoneTools.addTool(CircleROITool)
|
||||
cornerstoneTools.addTool(MIPJumpToClickTool)
|
||||
cornerstoneTools.addTool(VolumeRotateTool)
|
||||
|
||||
viewportIds.forEach((viewportId, i) => {
|
||||
const toolGroupId = `viewport-${i}`
|
||||
// const toolGroupId = `viewport-${i}`
|
||||
const toolGroupId = viewportId
|
||||
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
|
||||
toolGroup.addViewport(viewportId, renderingEngineId)
|
||||
toolGroup.addTool(StackScrollTool.toolName)
|
||||
|
@ -1029,7 +1137,7 @@ export default {
|
|||
return doneChangingTextCallback(data.text)
|
||||
},
|
||||
getTextCallback: async(doneChangingTextCallback) => {
|
||||
return doneChangingTextCallback('_')
|
||||
return doneChangingTextCallback('Annotation')
|
||||
}
|
||||
})
|
||||
toolGroup.addTool(RectangleROITool.toolName, {
|
||||
|
@ -1054,7 +1162,29 @@ export default {
|
|||
toolGroup.addTool(CircleROITool.toolName, {
|
||||
getTextLines: this.getCircleROIToolTextLines
|
||||
})
|
||||
if(toolGroupId === 'viewport-fusion-3'){
|
||||
toolGroup.addTool(VolumeRotateTool.toolName);
|
||||
toolGroup.setToolActive(VolumeRotateTool.toolName, {
|
||||
bindings: [
|
||||
{
|
||||
mouseButton: MouseBindings.Wheel, // mouse wheel
|
||||
},
|
||||
],
|
||||
});
|
||||
toolGroup.addTool(MIPJumpToClickTool.toolName, {
|
||||
targetViewportIds: fusionViewportIds,
|
||||
});
|
||||
|
||||
// Set the initial state of the tools, here we set one tool active on left click.
|
||||
// This means left click will draw that tool.
|
||||
toolGroup.setToolActive(MIPJumpToClickTool.toolName, {
|
||||
bindings: [
|
||||
{
|
||||
mouseButton: MouseBindings.Primary, // Left Click
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
toolGroup.setToolActive(StackScrollTool.toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||
})
|
||||
|
@ -1210,7 +1340,7 @@ export default {
|
|||
const { annotation } = e.detail
|
||||
if (!annotation) return
|
||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
const referencedImageId = annotation.metadata.referencedImageId
|
||||
const params = this.getInstanceInfo(referencedImageId)
|
||||
|
@ -1236,7 +1366,7 @@ export default {
|
|||
if (!annotation.highlighted) return
|
||||
if (!annotation) return
|
||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
// this.$refs['ecrf'].modifyAnnotation({ annotation, toolName: annotation.metadata.toolName })
|
||||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].modifyAnnotation({ annotation, toolName: annotation.metadata.toolName })
|
||||
|
@ -1264,7 +1394,7 @@ export default {
|
|||
return
|
||||
}
|
||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
const referencedImageId = annotation.metadata.referencedImageId
|
||||
const params = this.getInstanceInfo(referencedImageId)
|
||||
|
@ -1323,7 +1453,7 @@ export default {
|
|||
}
|
||||
if (!annotation.data.label) return
|
||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
this.saveCustomAnnotation(annotation)
|
||||
}
|
||||
|
@ -1351,7 +1481,7 @@ export default {
|
|||
}
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
for (let i = 0; i < this.cells.length; i++) {
|
||||
const viewportId = `viewport-${i}`
|
||||
const viewportId = `${this.viewportKey}-${i}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
viewport.render()
|
||||
}
|
||||
|
@ -1359,7 +1489,7 @@ export default {
|
|||
cornerstoneTools.annotation.state.addAnnotation(annotation)
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
for (let i = 0; i < this.cells.length; i++) {
|
||||
const viewportId = `viewport-${i}`
|
||||
const viewportId = `${this.viewportKey}-${i}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
viewport.render()
|
||||
}
|
||||
|
@ -1371,7 +1501,7 @@ export default {
|
|||
cornerstoneTools.annotation.state.removeAnnotation(annotation.annotationUID)
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
for (let i = 0; i < this.cells.length; i++) {
|
||||
const viewportId = `viewport-${i}`
|
||||
const viewportId = `${this.viewportKey}-${i}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
viewport.render()
|
||||
}
|
||||
|
@ -1440,7 +1570,7 @@ export default {
|
|||
})
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
for (let i = 0; i < this.cells.length; i++) {
|
||||
const viewportId = `viewport-${i}`
|
||||
const viewportId = `${this.viewportKey}-${i}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
viewport.render()
|
||||
}
|
||||
|
@ -1457,7 +1587,7 @@ export default {
|
|||
}
|
||||
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `viewport-${this.activeViewportIndex}`
|
||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
viewport.render()
|
||||
},
|
||||
|
@ -1613,7 +1743,7 @@ export default {
|
|||
},
|
||||
// 激活工具
|
||||
setToolActive(toolName) {
|
||||
const toolGroupId = `viewport-${this.activeViewportIndex}`
|
||||
const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
if (this.activeTool === toolName) {
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
|
@ -1633,9 +1763,9 @@ export default {
|
|||
if (this.readingTaskState === 2) return
|
||||
const toolObj = this.tools.find(i => i.toolName === toolName)
|
||||
if (!toolObj || toolObj.isDisabled) return
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
const toolGroupId = `viewport-${this.activeViewportIndex}`
|
||||
const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
if (this.activeTool === toolName) {
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
|
@ -1654,9 +1784,9 @@ export default {
|
|||
setMoreToolActive(toolName) {
|
||||
if (this.readingTaskState === 2) return
|
||||
this.setToolsPassive()
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
const toolGroupId = `viewport-${this.activeViewportIndex}`
|
||||
const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolActive(toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||
|
@ -1666,7 +1796,7 @@ export default {
|
|||
},
|
||||
setToolsPassive() {
|
||||
if (!this.activeTool) return
|
||||
const toolGroupIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3']
|
||||
const toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`]
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
|
@ -1675,7 +1805,7 @@ export default {
|
|||
},
|
||||
setToolEnabled() {
|
||||
if (!this.activeTool) return
|
||||
const toolGroupIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3']
|
||||
const toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`]
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolEnabled(this.activeTool)
|
||||
|
@ -1686,7 +1816,7 @@ export default {
|
|||
enter(e, toolName) {
|
||||
const i = this.tools.findIndex(i => i.toolName === toolName)
|
||||
if (i === -1) return
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
const isCurrentTask = series.TaskInfo.IsCurrentTask
|
||||
const readingTaskState = this.readingTaskState
|
||||
if (!isCurrentTask || readingTaskState >= 2) {
|
||||
|
@ -1715,7 +1845,7 @@ export default {
|
|||
setViewportRotate(value) {
|
||||
this.setToolsPassive()
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `viewport-${this.activeViewportIndex}`
|
||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
const type = parseInt(value)
|
||||
// 1:默认值;2:垂直翻转;3:水平翻转;4:左转90度;5:右转90度;
|
||||
|
@ -1740,15 +1870,15 @@ export default {
|
|||
viewport.setViewPresentation({ rotation: rotation + 90 })
|
||||
viewport.render()
|
||||
}
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].rotateOrientationMarkers(type)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].rotateOrientationMarkers(type)
|
||||
},
|
||||
// 重置视口
|
||||
resetViewport() {
|
||||
this.setToolsPassive()
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `viewport-${this.activeViewportIndex}`
|
||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].resetOrientationMarkers()
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resetOrientationMarkers()
|
||||
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||
viewport.resetProperties()
|
||||
viewport.render()
|
||||
|
@ -1759,7 +1889,7 @@ export default {
|
|||
this.setToolsPassive()
|
||||
this.fullScreenIndex = null
|
||||
this.layout = v
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
const seriesArr = []
|
||||
if (v === 1) {
|
||||
this.rows = 1
|
||||
|
@ -1830,7 +1960,7 @@ export default {
|
|||
this.activeViewportIndex = 3
|
||||
}
|
||||
seriesArr.map((i, index) => {
|
||||
this.$refs[`viewport-${index}`][0].setSeriesInfo(i)
|
||||
this.$refs[`${this.viewportKey}-${index}`][0].setSeriesInfo(i)
|
||||
})
|
||||
this.$nextTick(() => {
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
|
@ -1841,7 +1971,7 @@ export default {
|
|||
changeVoiRange(v) {
|
||||
this.setToolsPassive()
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `viewport-${this.activeViewportIndex}`
|
||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
if (v.val === -1) {
|
||||
// 默认值
|
||||
|
@ -1849,7 +1979,7 @@ export default {
|
|||
viewport.render()
|
||||
} else if (v.val === 0) {
|
||||
// 自定义
|
||||
const wwwc = this.$refs[`viewport-${this.activeViewportIndex}`][0].imageInfo.wwwc
|
||||
const wwwc = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].imageInfo.wwwc
|
||||
this.activeViewportWW = wwwc ? parseInt(wwwc.split('/')[0]) : null
|
||||
this.activeViewportWC = wwwc ? parseInt(wwwc.split('/')[1]) : null
|
||||
this.customWwc.visible = true
|
||||
|
@ -1870,7 +2000,7 @@ export default {
|
|||
// 设置窗宽窗位
|
||||
setWwwc(v) {
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `viewport-${this.activeViewportIndex}`
|
||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const viewport = renderingEngine.getViewport(viewportId)
|
||||
const lower = v.wc - v.ww / 2
|
||||
const upper = v.wc + v.ww / 2 - 1
|
||||
|
@ -1881,7 +2011,7 @@ export default {
|
|||
// 反色
|
||||
toggleInvert() {
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(`viewport-${this.activeViewportIndex}`)
|
||||
const viewport = renderingEngine.getViewport(`${this.viewportKey}-${this.activeViewportIndex}`)
|
||||
const { invert } = viewport.getProperties()
|
||||
viewport.setProperties({ invert: !invert })
|
||||
viewport.render()
|
||||
|
@ -1889,12 +2019,12 @@ export default {
|
|||
// 翻页
|
||||
scrollPage(type) {
|
||||
this.clipPlaying = false
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].scrollPage(type)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].scrollPage(type)
|
||||
},
|
||||
// 播放
|
||||
toggleClipPlay(isPlay) {
|
||||
this.clipPlaying = !this.clipPlaying
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].toggleClipPlay(isPlay, this.fps)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].toggleClipPlay(isPlay, this.fps)
|
||||
},
|
||||
// 获取窗宽窗位模板
|
||||
async getWwcTpl() {
|
||||
|
@ -1939,18 +2069,18 @@ export default {
|
|||
this.activeViewport(viewportIndex)
|
||||
} else if (shortcutKeyEnum === 3) {
|
||||
// 上一个序列
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
this.$refs[this.activeTaskId][0].getPreviousOrNextSeries(-1, series)
|
||||
} else if (shortcutKeyEnum === 4) {
|
||||
// 下一个序列
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
this.$refs[this.activeTaskId][0].getPreviousOrNextSeries(1, series)
|
||||
} else if (shortcutKeyEnum === 5) {
|
||||
// 上一张图像
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].scrollPage(-1)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].scrollPage(-1)
|
||||
} else if (shortcutKeyEnum === 6) {
|
||||
// 下一张图像
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].scrollPage(1)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].scrollPage(1)
|
||||
} else if (shortcutKeyEnum === 7) {
|
||||
// 向左旋转
|
||||
this.setViewportRotate(4)
|
||||
|
@ -1965,16 +2095,16 @@ export default {
|
|||
this.setViewportRotate(2)
|
||||
} else if (shortcutKeyEnum === 11) {
|
||||
// 放大
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].setZoom(1)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setZoom(1)
|
||||
} else if (shortcutKeyEnum === 12) {
|
||||
// 缩小
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].setZoom(-1)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setZoom(-1)
|
||||
} else if (shortcutKeyEnum === 13) {
|
||||
// 适应图像
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].resize(false)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resize(false)
|
||||
} else if (shortcutKeyEnum === 14) {
|
||||
// 适应窗口
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].resize(true)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resize(true)
|
||||
} else if (shortcutKeyEnum === 15) {
|
||||
// 截图
|
||||
} else if (shortcutKeyEnum === 16) {
|
||||
|
@ -1982,11 +2112,11 @@ export default {
|
|||
this.toggleInvert()
|
||||
} else if (shortcutKeyEnum === 17) {
|
||||
// 窗宽/窗位
|
||||
const wwwcIdx = this.$refs[`viewport-${this.activeViewportIndex}`][0].wwwcIdx
|
||||
const wwwcIdx = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].wwwcIdx
|
||||
const newWwwcIdx = wwwcIdx === this.wwwcArr.length - 1 ? 3 : wwwcIdx + 1
|
||||
const wwwcTpl = this.wwwcArr[newWwwcIdx]
|
||||
this.changeVoiRange(wwwcTpl)
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].setWwwcIdx(newWwwcIdx)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setWwwcIdx(newWwwcIdx)
|
||||
} else if (shortcutKeyEnum === 18) {
|
||||
// 重置
|
||||
this.resetViewport()
|
||||
|
@ -2002,7 +2132,7 @@ export default {
|
|||
})
|
||||
}
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3']
|
||||
const viewportIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`]
|
||||
renderingEngine.renderViewports(viewportIds)
|
||||
}
|
||||
event.stopImmediatePropagation()
|
||||
|
@ -2019,7 +2149,7 @@ export default {
|
|||
},
|
||||
fitToType(forceFitToWindow) {
|
||||
this.forceFitToWindow = !forceFitToWindow
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].resize(forceFitToWindow)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resize(forceFitToWindow)
|
||||
},
|
||||
// 切换全屏
|
||||
toggleFullScreen(e, index) {
|
||||
|
@ -2027,6 +2157,12 @@ export default {
|
|||
this.activeViewportIndex = index
|
||||
},
|
||||
async toggleTask(taskInfo, taskIndex) {
|
||||
if(this.isFusion){
|
||||
let confirm = await this.$confirm(this.$t('trials:reading:confirm:changeStack'))
|
||||
if(!confirm) return false
|
||||
this.isFusion = false
|
||||
this.setToolsPassive()
|
||||
}
|
||||
if (taskIndex === this.activeTaskIndex) return
|
||||
if (!this.selectArr.includes(taskInfo.VisitTaskId)) {
|
||||
this.selectArr.push(taskInfo.VisitTaskId)
|
||||
|
@ -2082,7 +2218,7 @@ export default {
|
|||
}
|
||||
const series = this.getRelatedSeries(this.visitTaskList[i], obj.series)
|
||||
this.$nextTick(() => {
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].setSeriesInfo(series)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series)
|
||||
this.$refs[this.activeTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
|
||||
if (this.activeViewportIndex === this.cells.length - 1) {
|
||||
this.lastViewportTaskId = series.TaskInfo.VisitTaskId
|
||||
|
@ -2092,7 +2228,17 @@ export default {
|
|||
this.setToolsPassive()
|
||||
},
|
||||
async activeSeries(obj) {
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
||||
if(this.isFusion){
|
||||
let confirm = await this.$confirm(this.$t('trials:reading:confirm:changeStack'))
|
||||
if(!confirm) return false
|
||||
this.isFusion = false
|
||||
this.setToolsPassive()
|
||||
this.rows = 1
|
||||
this.cols = 1
|
||||
this.activeViewportIndex = 0
|
||||
return this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
||||
}
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
||||
this.clipPlaying = false
|
||||
this.fps = 15
|
||||
if (this.activeViewportIndex === this.cells.length - 1) {
|
||||
|
@ -2104,7 +2250,7 @@ export default {
|
|||
}
|
||||
},
|
||||
async showMultiFrame(obj) {
|
||||
this.$refs[`viewport-${this.activeViewportIndex}`][0].setSeriesInfo(obj, true)
|
||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj, true)
|
||||
this.clipPlaying = false
|
||||
this.fps = 15
|
||||
if (this.activeViewportIndex === this.cells.length - 1) {
|
||||
|
@ -2118,7 +2264,7 @@ export default {
|
|||
if (this.activeViewportIndex === index) return
|
||||
this.activeViewportIndex = index
|
||||
// 切换检查列表
|
||||
const series = this.$refs[`viewport-${this.activeViewportIndex}`][0].series
|
||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||
if (series) {
|
||||
const i = this.visitTaskList.findIndex(v => v.VisitTaskId === series.TaskInfo.VisitTaskId)
|
||||
if (i > -1) {
|
||||
|
@ -2243,7 +2389,7 @@ export default {
|
|||
if (measureData) {
|
||||
await this.imageLocation(measureData)
|
||||
const divForDownloadViewport = document.querySelector(
|
||||
`div[data-viewport-uid="viewport-${this.activeViewportIndex}"]`
|
||||
`div[data-viewport-uid="${this.viewportKey}-${this.activeViewportIndex}"]`
|
||||
)
|
||||
const canvas = await html2canvas(divForDownloadViewport)
|
||||
const base64Str = canvas.toDataURL('image/png', 1)
|
||||
|
@ -2327,24 +2473,24 @@ export default {
|
|||
// }
|
||||
|
||||
// 显示当前序列
|
||||
currentAddSeries = this.$refs[`viewport-${this.cells.length - 1}`][0].series
|
||||
currentAddSeries = this.$refs[`${this.viewportKey}-${this.cells.length - 1}`][0].series
|
||||
}
|
||||
} else {
|
||||
// 无序
|
||||
currentAddSeries = this.getMarkedSeries(this.visitTaskList[index].StudyList, obj)
|
||||
if (Object.keys(currentAddSeries).length === 0) {
|
||||
// 未找到标注序列的,则就显示当前最后一个窗口现实的序列信息cells.length - 1
|
||||
currentAddSeries = this.$refs[`viewport-${this.cells.length - 1}`][0].series
|
||||
currentAddSeries = this.$refs[`${this.viewportKey}-${this.cells.length - 1}`][0].series
|
||||
}
|
||||
firstAddSeries = currentAddSeries
|
||||
}
|
||||
for (let i = 0; i < this.cells.length; i++) {
|
||||
if (i === this.cells.length - 1) {
|
||||
this.$refs[`viewport-${i}`][0].setSeriesInfo(currentAddSeries, true)
|
||||
this.$refs[`${this.viewportKey}-${i}`][0].setSeriesInfo(currentAddSeries, true)
|
||||
this.activeViewportIndex = i
|
||||
this.$refs[currentAddSeries.TaskInfo.VisitTaskId][0].setSeriesActive(currentAddSeries.StudyIndex, currentAddSeries.SeriesIndex)
|
||||
} else {
|
||||
this.$refs[`viewport-${i}`][0].setSeriesInfo(firstAddSeries, true)
|
||||
this.$refs[`${this.viewportKey}-${i}`][0].setSeriesInfo(firstAddSeries, true)
|
||||
}
|
||||
}
|
||||
this.setToolsPassive()
|
||||
|
@ -2362,7 +2508,7 @@ export default {
|
|||
if (this.activeTool) {
|
||||
this.setToolsPassive()
|
||||
}
|
||||
const toolGroupId = `viewport-${this.activeViewportIndex}`
|
||||
const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolActive(toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||
|
@ -2463,7 +2609,8 @@ export default {
|
|||
return null
|
||||
}
|
||||
},
|
||||
showPanel(e) {
|
||||
showPanel(e, toolName) {
|
||||
if(toolName === 'layout' && this.isFusion) return false
|
||||
e.currentTarget.firstChild.lastChild.style.display = 'block'
|
||||
},
|
||||
toolMouseout(e) {
|
||||
|
@ -2477,7 +2624,94 @@ export default {
|
|||
callback.apply(this, arguments)
|
||||
}, delay)
|
||||
}
|
||||
},
|
||||
setColorMap(rgbPresetName) {
|
||||
let fusionViewportIds = [`viewport-fusion-1`, `viewport-fusion-2`, `viewport-fusion-3`]
|
||||
fusionViewportIds.forEach(id => {
|
||||
this.$refs[id][0].setPreset(rgbPresetName)
|
||||
this.$refs[id][0].renderColorBar(rgbPresetName)
|
||||
this.$refs[id][0].setColorMap(rgbPresetName)
|
||||
})
|
||||
},
|
||||
voiChange(v) {
|
||||
let fusionViewportIds = [`viewport-fusion-1`, `viewport-fusion-2`, `viewport-fusion-3`]
|
||||
fusionViewportIds.forEach(id => {
|
||||
this.$refs[id][0].voiChange(v)
|
||||
})
|
||||
},
|
||||
async handleFusion(data) {
|
||||
try{
|
||||
this.fusionVisible = false
|
||||
this.isFusion = true
|
||||
this.rows = 2;
|
||||
this.cols = 2
|
||||
let { ct, pt } = data
|
||||
this.loading = true
|
||||
this.loadingText = this.$t('trials:lugano:message:loadVolumes')
|
||||
await this.getVolume(ct)
|
||||
await this.getVolume(pt)
|
||||
await this.getVolume(pt, true)
|
||||
this.loading = false
|
||||
this.loadingText = null
|
||||
let ctData = {
|
||||
data: ct,
|
||||
volumeId: this.volumeData[ct.Id].volumeId,
|
||||
}
|
||||
let ptData = {
|
||||
data: pt,
|
||||
volumeId: this.volumeData[pt.Id].volumeId,
|
||||
volume: this.volumeData[pt.Id].volume,
|
||||
}
|
||||
let fusionData = {
|
||||
ct,
|
||||
data: pt,
|
||||
volumeId: this.volumeData[pt.Id].volumeId,
|
||||
ctVolumeId: this.volumeData[ct.Id].volumeId,
|
||||
ptVolumeId: this.volumeData[pt.Id].volumeId,
|
||||
fusionVolumeId: this.volumeData[`fusion_${pt.Id}`].volumeId,
|
||||
}
|
||||
this.$refs[`viewport-0`][0].setSeriesInfo(ct)
|
||||
this.$refs[`viewport-1`][0].setSeriesInfo(pt)
|
||||
this.$refs[`viewport-2`][0].setSeriesInfo(pt)
|
||||
this.$refs[`viewport-3`][0].setSeriesInfo(pt)
|
||||
|
||||
this.$refs[`viewport-fusion-0`][0].setSeriesInfo(ctData)
|
||||
this.$refs[`viewport-fusion-1`][0].setSeriesInfo(ptData, { colorMap: true})
|
||||
this.$refs[`viewport-fusion-2`][0].setSeriesInfo(fusionData, { isFusion: true, colorMap: true })
|
||||
this.$refs[`viewport-fusion-3`][0].setSeriesInfo(ptData, { isMip: true, colorMap: true })
|
||||
this.$nextTick(() => {
|
||||
this.$refs[`colorMap`].init()
|
||||
})
|
||||
}catch(err){
|
||||
console.log(err)
|
||||
this.loading = false
|
||||
this.loadingText = null
|
||||
}
|
||||
},
|
||||
async getVolume(serie, isFusion = false ) {
|
||||
let volumeId = null, volume = null
|
||||
let key = isFusion ? `fusion_${serie.Id}` : serie.Id
|
||||
if(!this.volumeData[key] || !cache.getVolume(this.volumeData[key].volumeId)) {
|
||||
await this.$refs[`viewport-fusion-0`][0].createImageIdsAndCacheMetaData(serie)
|
||||
volumeId = `${isFusion ? 'fusion' : serie.Modality}Volume` + ':' + csUtils.uuidv4()
|
||||
volume = await volumeLoader.createAndCacheVolume(volumeId, { imageIds: serie.ImageIds })
|
||||
volume.load()
|
||||
this.volumeData[key] = {}
|
||||
this.volumeData[key].volumeId = volumeId
|
||||
this.volumeData[key].volume = volume
|
||||
} else {
|
||||
volumeId = this.volumeData[key].volumeId
|
||||
volume = this.volumeData[key].volume
|
||||
}
|
||||
|
||||
return { volumeId, volume }
|
||||
},
|
||||
openFusion() {
|
||||
this.fusionVisible = true
|
||||
},
|
||||
closeFusion() {
|
||||
this.fusionVisible = false
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
<el-tabs v-model="activeName">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane v-if="taskInfo" :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
<read-page v-if="!readingTool" ref="readPage" />
|
||||
<PetCtReadPage v-else-if="readingTool === 2" ref="readPage" />
|
||||
<read-page ref="readPage" :reading-tool="readingTool" />
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane
|
||||
|
|
|
@ -0,0 +1,325 @@
|
|||
<template>
|
||||
<div class="colorMap">
|
||||
<div class="item" effect="dark" :title="$t('trials:lugano:button:colormap')">
|
||||
<div class="colorBar"
|
||||
style="display:flex;justify-content: flex-start;align-items: center;position: relative;"
|
||||
@mouseleave="isSlideMoving = false">
|
||||
<div class="tool-wrapper" style="margin-right:0px" @click.stop="showColorBarPanel($event)"
|
||||
@mouseleave="handleColorBarMouseout">
|
||||
<div>
|
||||
<div class="dropdown">
|
||||
<div id="colorBar" class="icon" style="display: flex;align-items: center;width:266px">
|
||||
<canvas id="colorBarCanvas" />
|
||||
|
||||
</div>
|
||||
<!-- 伪彩 -->
|
||||
<div class="text">{{ $t('trials:lugano:button:colormap') }}</div>
|
||||
<div class="dropdown-content" style="width:266px">
|
||||
<ul>
|
||||
<li v-for="(colorMap, index) in colorMaps" :key="colorMap"
|
||||
style="display: flex;align-items: center;margin-bottom:5px;padding:0 5px;justify-content: space-between;"
|
||||
:class="{ activeLi: rgbPresetName === colorMap }"
|
||||
@click="setColorMap(colorMap)">
|
||||
<canvas :id="`colorBarCanvas${index}`" />
|
||||
<span style="margin-left:5px;font-size: 10px;">{{ colorMap
|
||||
}}</span>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left:-1px;border: 1px solid #424242;">
|
||||
<el-input v-model="range" size="mini" style="width:120px" maxlength="3"
|
||||
oninput="if(value){value=value.replace(/[^\d]/g,'')} if(value<=0){value=''}"
|
||||
@change="upperRangeChange">
|
||||
<template slot="append">g/ml</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div id="slider" style="position: absolute;left: 6px;top:5px;cursor: pointer;">
|
||||
<div id="sliderBox" class="slider" style="height: 17px;width: 10px;background-color: #909399;" />
|
||||
<div id="slider-position" style="color:#ddd;font-size: 12px;">0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
utilities as csUtils,
|
||||
} from '@cornerstonejs/core'
|
||||
import colormaps from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/colormaps'
|
||||
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
|
||||
const { registerColormap, getColormapNames, getColormap } = csUtils.colormap
|
||||
export default {
|
||||
name: "colorMap",
|
||||
data() {
|
||||
return {
|
||||
colorMaps: [],
|
||||
rgbPresetName: 'siemens',
|
||||
range: 40,
|
||||
upper: 6,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
colormaps.forEach(colormap => {
|
||||
registerColormap(colormap)
|
||||
})
|
||||
this.colorMaps = getColormapNames()
|
||||
this.colorMaps.unshift('hsv')
|
||||
this.$nextTick(() => {
|
||||
this.renderColorMaps()
|
||||
this.upperRangeChange(this.range)
|
||||
this.initSlider()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
renderColorMaps() {
|
||||
this.createColorBar(this.rgbPresetName, 'colorBarCanvas', 256, 15)
|
||||
this.colorMaps.forEach((e, index) => {
|
||||
this.createColorBar(e, `colorBarCanvas${index}`, 180, 15)
|
||||
})
|
||||
},
|
||||
voiChange(v) {
|
||||
this.$emit('voiChange', v)
|
||||
},
|
||||
initSlider() {
|
||||
var slider = document.getElementById('slider')
|
||||
var sliderBox = document.getElementById('sliderBox')
|
||||
var container = document.getElementById('colorBarCanvas')
|
||||
slider.addEventListener('mousedown', () => {
|
||||
this.isSlideMoving = true
|
||||
})
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
if (this.isSlideMoving) {
|
||||
var containerWidth = container.clientWidth
|
||||
var sliderWidth = sliderBox.clientWidth
|
||||
var maxLeft = containerWidth - sliderWidth
|
||||
var left = e.clientX - container.getBoundingClientRect().left
|
||||
var position = null
|
||||
position = left
|
||||
if (left < 0) {
|
||||
left = 6
|
||||
position = 0
|
||||
} else if (left > maxLeft) {
|
||||
left = maxLeft + 6
|
||||
position = maxLeft
|
||||
}
|
||||
|
||||
slider.style.left = left + 'px'
|
||||
var positionValue = document.getElementById('slider-position')
|
||||
var upper = this.range
|
||||
position = parseInt((position / maxLeft) * upper)
|
||||
positionValue.textContent = position
|
||||
this.upper = position
|
||||
this.voiChange(position)
|
||||
}
|
||||
})
|
||||
document.addEventListener('mouseup', () => {
|
||||
this.isSlideMoving = false
|
||||
})
|
||||
},
|
||||
upperRangeChange(v) {
|
||||
if (v === 0 || v < this.upper) {
|
||||
return
|
||||
}
|
||||
var sliderBox = document.getElementById('sliderBox')
|
||||
var container = document.getElementById('colorBarCanvas')
|
||||
var containerWidth = container.clientWidth
|
||||
var sliderWidth = sliderBox.clientWidth
|
||||
var maxLeft = containerWidth - sliderWidth
|
||||
var left = (this.upper / this.range) * maxLeft
|
||||
if (left < 0) {
|
||||
left = 6
|
||||
} else if (left >= maxLeft) {
|
||||
left = maxLeft + 6
|
||||
}
|
||||
var slider = document.getElementById('slider')
|
||||
slider.style.left = left + 'px'
|
||||
var positionValue = document.getElementById('slider-position')
|
||||
positionValue.textContent = this.upper
|
||||
},
|
||||
createColorBar(rgbPresetName, elId, width, height) {
|
||||
var colorMap = null
|
||||
if (rgbPresetName === 'hsv') {
|
||||
colorMap = vtkColorMaps.getPresetByName(rgbPresetName)
|
||||
} else {
|
||||
colorMap = getColormap(rgbPresetName)
|
||||
}
|
||||
|
||||
const rgbPoints = colorMap.RGBPoints
|
||||
const canvas = document.getElementById(elId)
|
||||
const ctx = canvas.getContext('2d')
|
||||
const canvasWidth = width
|
||||
const canvasHeight = height
|
||||
const rectWidth = width
|
||||
const rectHeight = canvasHeight
|
||||
canvas.width = canvasWidth
|
||||
canvas.height = canvasHeight
|
||||
const gradient = ctx.createLinearGradient(0, 0, rectWidth, 0)
|
||||
for (let i = 0; i < rgbPoints.length; i += 4) {
|
||||
let position = 0
|
||||
if (rgbPoints[0] === -1) {
|
||||
position = (rgbPoints[i] + 1) / 2
|
||||
} else {
|
||||
position = rgbPoints[i]
|
||||
}
|
||||
const color = `rgb(${parseInt(rgbPoints[i + 1] * 255)}, ${parseInt(rgbPoints[i + 2] * 255)}, ${parseInt(rgbPoints[i + 3] * 255)})`
|
||||
gradient.addColorStop(position, color)
|
||||
}
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, 0, rectWidth, rectHeight)
|
||||
},
|
||||
async setColorMap(rgbPresetName) {
|
||||
this.rgbPresetName = rgbPresetName
|
||||
this.createColorBar(this.rgbPresetName, 'colorBarCanvas', 256, 15)
|
||||
this.$emit("setColorMap", rgbPresetName)
|
||||
},
|
||||
showColorBarPanel(e) {
|
||||
e.currentTarget.firstChild.firstChild.lastChild.style.display = 'block'
|
||||
},
|
||||
handleColorBarMouseout(e) {
|
||||
e.currentTarget.firstChild.firstChild.lastChild.style.display = 'none'
|
||||
},
|
||||
init() {
|
||||
this.createColorBar(this.rgbPresetName, 'colorBarCanvas', 256, 15)
|
||||
this.$emit("setColorMap", this.rgbPresetName)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.activeLi {
|
||||
background-color: #919295;
|
||||
}
|
||||
|
||||
.tool-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 30px;
|
||||
|
||||
.icon {
|
||||
padding: 5px;
|
||||
border: 1px solid #404040;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
.svg-icon {
|
||||
font-size: 25px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
color: #d0d0d0;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
.icon-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #404040;
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tool-icon {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
.svg-icon {
|
||||
font-size: 20px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
cursor: pointer;
|
||||
padding: 7px 2px 7px 0px;
|
||||
}
|
||||
|
||||
.arrow-icon:hover {
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.icon-content-d:hover {
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.tool-icon-d {
|
||||
padding: 5px;
|
||||
|
||||
.svg-icon {
|
||||
font-size: 20px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #383838;
|
||||
color: #fff;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
z-index: 9999;
|
||||
font-size: 12px;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
|
||||
li {
|
||||
a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul li:hover {
|
||||
background-color: #727272;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
border: 1px solid rgba(255, 255, 255, 0.21);
|
||||
position: relative;
|
||||
|
||||
&_active {
|
||||
// border: 2px solid #ffeb3b;fff
|
||||
border: 1px dashed rgb(250, 250, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.colorBar {
|
||||
::v-deep .el-input--mini .el-input__inner {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue