irc_web/.svn/pristine/ad/adaad59570bc7a1a76eadb1aa9e...

1753 lines
66 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div class="dicom-viewer-wrapper">
<div class="dicom-viewer-container">
<div class="dicom-tools">
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:layout')}`" placement="bottom">
<div class="tool-wrapper" @click.stop="showPanel($event)" @mouseleave="handleMouseout">
<div class="dropdown">
<div class="icon">
<svg-icon icon-class="layout" class="svg-icon" />
<i class="el-icon-arrow-down" style="color:#fff;" />
</div>
<!-- 布局 -->
<!-- <div class="text">{{ $t('trials:reading:button:layout') }}<i class="el-icon-caret-bottom" /></div> -->
<div class="dropdown-content layout-content">
<ul style="width:50px">
<li class="flex_row" @click.stop="changeLayout('A')">
<div class="layout_box_1_1">
A
</div>
</li>
<li class="flex_row" @click.stop="changeLayout('A|A')">
<div class="layout_box_1_1">
A
</div>
<div class="layout_box_1_1">
A
</div>
</li>
<li v-if="isReadingTaskViewInOrder" class="flex_row" @click.stop="changeLayout('A|B')">
<div class="layout_box_1_1">
A
</div>
<div class="layout_box_1_1">
B
</div>
</li>
<li class="flex_column" @click.stop="changeLayout('A|A|A|A')">
<div style="flex:1;display: flex;width:100%;">
<div class="layout_box_1_2">
A
</div>
<div class="layout_box_1_2">
A
</div>
</div>
<div style="flex:1;display: flex;width:100%;">
<div class="layout_box_1_2">
A
</div>
<div class="layout_box_1_2">
A
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:wwwc')}`" placement="bottom">
<div class="tool-wrapper" @click.stop="showPanel($event)" @mouseleave="handleMouseout">
<div class="dropdown">
<div
class="icon"
data-tool="Wwwc"
:class="[activeTool==='Wwwc'?'tool_active':'']"
@click.prevent="setToolActive('Wwwc',false)"
>
<svg-icon icon-class="reverse" class="svg-icon" />
<i class="el-icon-arrow-down" style="color:#fff;" />
</div>
<!-- 调窗 -->
<!-- <div class="text">{{ $t('trials:reading:button:wwwc') }}<i class="el-icon-caret-bottom" /></div> -->
<div class="dropdown-content">
<ul style="width:165px;padding: 0 10px;">
<li v-for="item in wwwcArr" :key="item.label">
<a href="#" @click.prevent="setDicomCanvasWwwc(item)">
<div v-if="item.wc" style="display:flex;flex-direction: row;justify-content: space-between;">
<div>{{ item.label }}</div>
<div>{{ item.ww }}/{{ item.wc }}</div>
</div>
<div v-else style="text-align:left;">
{{ item.label }}
</div>
</a>
<!-- <div
v-if="item.val === 1"
class="divider"
>
W/L {{ $t('trials:reading:title:preset') }}
</div> -->
<el-divider v-if="item.val === 1" class="divider" content-position="center">{{ ` ${$t('trials:reading:title:preset') }` }}</el-divider>
</li>
</ul>
</div>
</div>
</div>
</el-tooltip>
<!-- <div class="tool-wrapper">
<div
class="icon"
data-tool="WwwcRegion"
:class="[activeTool==='WwwcRegion'?'tool_active':'']"
@click.prevent="setToolActive('WwwcRegion',false)"
>
<svg-icon icon-class="wwwcRegion" class="svg-icon" />
</div>
<div class="text">区域调窗</div>
</div> -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:reverseColor')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='reversecolor'?'tool_active':'']"
@click.prevent="toggleInvert"
>
<svg-icon icon-class="reversecolor" class="svg-icon" />
</div>
<!-- 反色 -->
<!-- <div class="text">{{ $t('trials:reading:button:reverseColor') }}</div> -->
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:zoom')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Zoom'?'tool_active':'']"
data-tool="Zoom"
@click.prevent="setToolActive('Zoom',false)"
>
<svg-icon icon-class="magnifier" class="svg-icon" />
</div>
<!-- 缩放 -->
<div class="text">{{ $t('trials:reading:button:zoom') }}</div>
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:move')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Pan'?'tool_active':'']"
data-tool="Pan"
@click.prevent="setToolActive('Pan',false)"
>
<svg-icon icon-class="move" class="svg-icon" />
</div>
<!-- 移动 -->
<div class="text">{{ $t('trials:reading:button:move') }}</div>
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:rotate')}`" placement="bottom">
<div class="tool-wrapper" @click.stop="showPanel($event)" @mouseleave="handleMouseout">
<!-- @click.prevent="setToolActive('Rotate',false)" -->
<div class="dropdown">
<div
class="icon"
data-tool="Rotate"
:class="[activeTool==='Rotate'?'tool_active':'']"
>
<svg-icon icon-class="rotate" class="svg-icon" />
<i class="el-icon-arrow-down" style="color:#fff;" />
</div>
<!-- 旋转 -->
<div class="text">{{ $t('trials:reading:button:rotate') }}<i class="el-icon-caret-bottom" /></div>
<div class="dropdown-content">
<ul style="width:100px;padding:0 10px;">
<li v-for="rotate in rotateArr" :key="rotate.label" style="text-align:left;">
<a href="#" @click.prevent="setDicomCanvasRotate(rotate.val)">{{ rotate.label }}</a>
</li>
</ul>
</div>
</div>
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="fitType===1?`${$t('trials:reading:button:fitWindow')}`:`${$t('trials:reading:button:fitImage')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="fitToType(fitType===1?'fitToWindow':'fitToImage')"
>
<svg-icon v-if="fitType===1" icon-class="fitToWindow" class="svg-icon" />
<svg-icon v-else icon-class="fitToImage" class="svg-icon" />
</div>
<div class="text">{{ fitType===1?$t('trials:reading:button:fitWindow'):$t('trials:reading:button:fitImage') }}</div>
</div>
</el-tooltip>
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:imageIndexSync')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
:class="[isScrollSync?'tool_active':'']"
@click.prevent="setImageIndexSync"
>
<i v-if="isScrollSync" class="el-icon-lock svg-icon" />
<i v-else class="el-icon-unlock svg-icon" />
</div>
<!-- 同步 -->
<div class="text">{{ $t('trials:reading:button:imageIndexSync') }}</div>
</div>
</el-tooltip>
<!--
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="fitToType('fitToImage')"
>
<svg-icon icon-class="fitToImage" class="svg-icon" />
</div>
<div class="text">适应图像</div>
</div> -->
<el-tooltip class="item" effect="dark" :content="`${$t('trials:reading:button:screenShot')}`" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="saveImage"
>
<svg-icon icon-class="image" class="svg-icon" />
</div>
<!-- 截屏 -->
<div class="text">{{ $t('trials:reading:button:screenShot') }}</div>
</div>
</el-tooltip>
<div
v-for="tool in measuredTools"
:key="tool.toolName"
>
<el-tooltip class="item" effect="dark" placement="bottom">
<div slot="content">
<div v-if="tool.disabledReason">
<h4 style="margin:0;padding-bottom:2px;">{{ tool.text }}</h4>
<br>{{ tool.disabledReason }}
</div>
<div v-else>{{ tool.text }}</div>
</div>
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool===tool.toolName?'tool_active':'']"
:style="{cursor:tool.isDisabled?'not-allowed':'pointer'}"
:data-tool="tool.toolName"
@click.prevent="setToolActive(tool.toolName,true,$event)"
@mouseenter="enter($event,tool.toolName)"
>
<svg-icon :icon-class="tool.icon" class="svg-icon" />
</div>
<div class="text">{{ tool.text }}</div>
</div>
</el-tooltip>
<!-- <div v-else class="tool-wrapper">
<div
class="icon"
:class="[activeTool===tool.toolName?'tool_active':'']"
:style="{cursor:tool.isDisabled?'not-allowed':'pointer'}"
:data-tool="tool.toolName"
@click.prevent="setToolActive(tool.toolName,true,$event)"
@mouseenter="enter($event,tool.toolName)"
>
<svg-icon :icon-class="tool.icon" class="svg-icon" />
</div>
<div class="text">{{ tool.text }}</div>
</div> -->
</div>
<!-- <el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:reset')" placement="bottom">
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="resetViewport"
>
<svg-icon icon-class="refresh" class="svg-icon" />
</div>
<div class="text">{{ $t('trials:reading:button:reset') }}</div>
</div>
</el-tooltip> -->
<div style="margin-left:auto;">
<div style="padding:5px">
<el-button v-if="isExistsManual" type="text" @click="previewManuals">手册</el-button>
<!-- 临床数据 -->
<el-button v-if="isExistsClinicalData" type="text" @click="previewCD">{{ $t('trials:reading:button:clinicalData') }}</el-button>
<!-- <el-button v-if="isExistsNoDicomFile" type="text" @click="previewNoneDicoms">非Dicom文件</el-button> -->
<el-button type="text" @click="previewConfig">个性化配置</el-button>
</div>
</div>
</div>
<div class="dicom-viewers">
<div ref="container" class="viewer-container" :class="['box', `box_${layoutRow}_${layoutCol}`]">
<div
v-for="i in maxCanvas"
:key="i"
:class="['item', i-1===currentDicomCanvasIndex?'item_active':'']"
:data-index="i-1"
:style="i-1===currentDicomCanvasIndex ? cornerstoneStyle : {}"
@click="activateDicomCanvas(i-1)"
>
<dicom-canvas
v-if="canvasW"
:ref="`dicomCanvas${i-1}`"
:style="{width:canvasW,height: canvasH}"
:canvas-index="i-1"
:is-active="i-1===currentDicomCanvasIndex"
:is-scroll-sync="isScrollSync"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
:current-dicom-canvas-index="currentDicomCanvasIndex"
:custom-wwc-tpl="customWwcTpl"
@setMeasureData="setMeasureData"
@modifyMeasureData="modifyMeasureData"
@scrollSync="scrollSync"
@selectViewCanvas="selectViewCanvas"
@setCornerstoneStyle="setCornerstoneStyle(i-1)"
/>
</div>
</div>
<div ref="form-container" class="form-container">
<!-- 激活canvas测量数据 -->
<MeasurementList
:IseCRFShowInDicomReading="IseCRFShowInDicomReading"
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
ref="measurementList"
/>
</div>
</div>
</div>
<el-dialog
v-if="customWwc.visible"
:visible.sync="customWwc.visible"
:close-on-click-modal="false"
:title="customWwc.title"
width="400px"
custom-class="base-dialog-wrapper"
>
<CustomWwwcForm @close="customWwc.visible = false" @setWwwc="setWwwc" />
</el-dialog>
<el-dialog
v-if="personalConfigDialog.visible"
:visible.sync="personalConfigDialog.visible"
:close-on-click-modal="false"
:title="personalConfigDialog.title"
width="600px"
>
<el-tabs v-model="activeName" class="personal_config">
<el-tab-pane label="热键" name="1">
<Hotkeys v-if="activeName === '1'" :reading-tool="0" @reset="resetHotkeyList" />
</el-tab-pane>
<el-tab-pane label="W/L模板" name="2">
<WL v-if="activeName === '2'" @getWwcTpl="getWwcTpl" />
</el-tab-pane>
<el-tab-pane label="其他" name="3">
<Others v-if="activeName === '3'" />
</el-tab-pane>
</el-tabs>
</el-dialog>
<el-dialog
v-if="manualsDialog.visible"
:visible.sync="manualsDialog.visible"
:custom-class="isFullscreen?'manuals-full-dialog-container':'manuals-dialog-container'"
:show-close="false"
:close-on-click-modal="false"
:fullscreen="isFullscreen"
>
<span slot="title" class="dialog-footer">
<span>手册</span>
<span style="position: absolute;right: 20px;font-size: 20px;">
<svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" style="margin-right:10px;cursor: pointer;" @click="isFullscreen=!isFullscreen" />
<svg-icon icon-class="close" style="cursor: pointer;" @click="manualsDialog.visible = false" />
</span>
</span>
<div style="height: 100%;margin:0;">
<Manuals :trial-id="trialId" />
</div>
</el-dialog>
</div>
</template>
<script>
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneMath from 'cornerstone-math'
import * as cornerstoneTools from 'cornerstone-tools'
import Hammer from 'hammerjs'
cornerstoneTools.external.cornerstone = cornerstone
cornerstoneTools.external.Hammer = Hammer
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
// import DicomCanvas from './DicomCanvas'
import DicomCanvas from '@/views/trials/trials-panel/reading/dicoms/components/DicomCanvas.vue'
import MeasurementList from './CustomizeMeasurementList'
import CustomWwwcForm from './CustomWwwcForm'
import Manuals from './Manuals'
import Hotkeys from './Hotkeys'
import WL from './WL'
import Others from './Others'
import DicomEvent from './../components/DicomEvent'
import { mapGetters } from 'vuex'
import store from '@/store'
import { getDoctorShortcutKey,getUserWLTemplateList } from '@/api/user'
export default {
name: 'DicomViewer',
components: {
DicomCanvas,
CustomWwwcForm,
Hotkeys,
WL,
Others,
Manuals,
MeasurementList},
props: {
isExistsClinicalData: {
type: Boolean,
default: false
},
isExistsNoDicomFile: {
type: Boolean,
default: false
},
isExistsManual: {
type: Boolean,
required: true
},
isReadingShowSubjectInfo: {
type: Boolean,
required: true
},
isReadingTaskViewInOrder: {
type: Boolean,
required: true
},
IseCRFShowInDicomReading: {
type: Boolean,
required: true
}
},
data() {
return {
cornerstoneStyle: {},
layouts: [
{ index: 0, row: 1, col: 1, name: 'A' },
{ index: 1, row: 1, col: 2, name: 'A|A' },
{ index: 2, row: 1, col: 2, name: 'A|B' },
{ index: 3, row: 2, col: 2, name: 'A|A|A|A' }
// { index: 2, row: 2, col: 1 },
// { index: 3, row: 2, col: 2 }
],
rotateArr: [
{ label: this.$t('trials:reading:button:rotateDefault'), val: 1 }, // 默认值
{ label: this.$t('trials:reading:button:rotateVertical'), val: 2 }, // 垂直翻转
{ label: this.$t('trials:reading:button:rotateHorizontal'), val: 3 }, // 水平翻转
{ label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4 }, // 左转90度
{ label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 }// 右转90度
],
maxCanvas: 1,
layoutRow: 1,
layoutCol: 1,
currentDicomCanvasIndex: 0,
currentDicomCanvas: {
toolState: {
clipPlaying: false
}
},
colormapsList: [],
rotateList: [],
colorList: [],
wwwcList: [],
canvasW: null,
canvasH: null,
activeTool: '',
CriterionType: 0,
measuredTools: [
// 直径测量
{ toolName: 'Length', text: this.$t('trials:reading:button:length'), icon: 'length', isDisabled: false, disabledReason: '' },
// 长短径测量
{ toolName: 'Bidirectional', text: this.$t('trials:reading:button:bidirectional'), icon: 'bidirection', isDisabled: false, disabledReason: '' },
// 矩形工具
{ toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' },
// 箭头工具
{ toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }
],
fitType: 0,
isDisabledTool: false,
canvasObj: {},
wwwcArr: [],
defaultWwwc: [
{ label: this.$t('trials:reading:button:wwwcDefault'), val: -1, ww: null, wc: null }, // 默认值
{ label: this.$t('trials:reading:button:wwwcCustom'), val: 0, ww: null, wc: null }, // 自定义
{ label: this.$t('trials:reading:button:wwwcRegion'), val: 1, ww: null, wc: null }, // 区域窗宽
{ label: 'CT Brain', wc: 40, ww: 80 },
{ label: 'CT Lungs', wc: -400, ww: 1500 },
{ label: 'CT Abdomen', wc: 60, ww: 400 },
{ label: 'CT Liver', wc: 40, ww: 400 },
{ label: 'CT Bone', wc: 300, ww: 1500 }
],
activeSeries: {},
seriesStack: [],
trialId: '',
isScrollSync: false,
imageIndexSync: {
sourceCanvas: '',
targetCanvas: []
},
isFirstRender: false,
customWwc: { visible: false, title: null }, // 自定义调窗
personalConfigDialog: { visible: false, title: '个性化配置' }, // 个性化配置
layout: '',
isFirstNotLinked: false,
hotKeyList: [],
activeName: '1',
customWwcTpl: [],
isFullscreen: false,
manualsDialog: { visible: false }
}
},
computed: {
...mapGetters(['visitTaskList', 'currentReadingTaskState'])
},
watch: {
currentReadingTaskState: {
immediate: true,
handler(val) {
if (val && this.currentDicomCanvasIndex && this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`]) {
this.canvasObj[this.currentDicomCanvasIndex].readingTaskState = val
if (this.activeTool) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
this.activeTool = ''
}
}
}
}
},
mounted() {
this.getHotKeys()
this.getWwcTpl()
// cornerstone.imageCache.setMaximumSizeBytes(0)
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
// const maximumSizeInBytes = 1024 * 1024 * 500
cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
this.customWwc = { visible: false, title: this.$t('trials:reading:dagTitle:wwwcCustom') }
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
if (this.CriterionType === 10) {
this.measuredTools = [{ toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }]
} else if (this.CriterionType === 17) {
this.measuredTools = [{ toolName: 'Length', text: this.$t('trials:reading:button:length'), icon: 'length', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }, { toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }]
}
this.rotateList[0] = '1'
this.colorList[0] = ''
this.wwwcList[0] = '1'
this.colormapsList = cornerstone.colors.getColormapsList()
this.currentDicomCanvas = this.$refs['dicomCanvas0'] ? this.$refs['dicomCanvas0'][0] : ''
this.trialId = this.$router.currentRoute.query.trialId
this.setCanvasStyle()
window.addEventListener('resize', this.setCanvasStyle)
DicomEvent.$on('updateImage', (instanceId) => {
for (let i = 0; i < this.maxCanvas; i++) {
var stack = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
if (stack.studyId) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].updateImage(instanceId)
}
}
})
DicomEvent.$on('getMeasureData', () => {
for (let i = 0; i < this.maxCanvas; i++) {
var stack = this.$refs[`dicomCanvas${i}`][0].stack
if (stack.visitTaskId) {
this.$refs[`dicomCanvas${i}`][0].getMeasureData()
}
}
console.log('getMeasureData')
})
DicomEvent.$on('getScreenshots', (callback) => {
var base64Str = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].getScreenshots()
callback(base64Str)
console.log('getScreenshots')
})
DicomEvent.$on('imageLocation', measuredData => {
if (!measuredData) return
this.imageLocation(measuredData)
console.log('imageLocation')
})
DicomEvent.$on('setReadingState', readingTaskState => {
this.canvasObj[this.currentDicomCanvasIndex].readingTaskState = readingTaskState
if (this.activeTool) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
this.activeTool = ''
}
})
DicomEvent.$on('PGWC3Active', res => {
this.setToolActive('ArrowAnnotate', true, null, 'open')
})
DicomEvent.$on('loadImageStacks', seriesList => {
this.loadImageStacks(seriesList)
console.log('loadImageStacks')
})
DicomEvent.$on('loadLinkedImageStack', seriesInfo => {
this.loadLinkedImageStack(seriesInfo)
console.log('loadLinkedImageStack')
})
},
beforeDestroy() {
DicomEvent.$off('updateImage')
DicomEvent.$off('getMeasureData')
DicomEvent.$off('imageLocation')
DicomEvent.$off('setReadingState')
DicomEvent.$off('loadImageStacks')
DicomEvent.$off('loadLinkedImageStack')
},
methods: {
getWwcTpl() {
const loading = this.$loading({ fullscreen: true })
getUserWLTemplateList().then(res => {
this.customWwcTpl = []
res.Result.map(i => {
this.customWwcTpl.push({ label: i.TemplateName, wc: i.WL, ww: i.WW })
})
this.wwwcArr = [...this.defaultWwwc, ...this.customWwcTpl]
loading.close()
}).catch(() => { loading.close() })
},
getHotKeys() {
const loading = this.$loading({ fullscreen: true })
getDoctorShortcutKey({ imageToolType: 0 }).then(res => {
res.Result.map(item => {
this.hotKeyList.push({ id: item.Id, altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code, text: item.Text, shortcutKeyEnum: item.ShortcutKeyEnum })
})
this.bindHotKey()
loading.close()
}).catch(() => {
loading.close()
})
},
resetHotkeyList(arr) {
this.hotKeyList = []
arr.map(item => {
this.hotKeyList.push({ id: item.id, altKey: item.keys.controlKey.altKey, ctrlKey: item.keys.controlKey.ctrlKey, shiftKey: item.keys.controlKey.shiftKey, metaKey: item.keys.controlKey.metaKey, key: item.keys.controlKey.key, code: item.keys.controlKey.code, text: item.keys.text, shortcutKeyEnum: item.label })
})
// const loading = this.$loading({ fullscreen: true })
// getDoctorShortcutKey({ imageToolType: 0 }).then(res => {
// res.Result.map(item => {
// this.hotKeyList.push({ id: item.Id, altKey: item.AltKey, ctrlKey: item.CtrlKey, shiftKey: item.ShiftKey, metaKey: item.MetaKey, key: item.Keyboardkey, code: item.Code, text: item.Text, shortcutKeyEnum: item.ShortcutKeyEnum })
// })
// loading.close()
// }).catch(() => {
// loading.close()
// })
},
bindHotKey() {
var container = this.$refs['container']
// window.addEventListener
container.addEventListener('keydown', event => {
console.log(event)
event.preventDefault()
var idx = this.hotKeyList.findIndex(i => i.code === event.code && i.ctrlKey === event.ctrlKey && i.shiftKey === event.shiftKey && i.altKey === event.altKey)
if (idx === -1) return
var shortcutKeyEnum = this.hotKeyList[idx].shortcutKeyEnum
console.log(shortcutKeyEnum)
if (shortcutKeyEnum === 1) {
// 前一图像视口
this.selectViewCanvas(-1)
} else if (shortcutKeyEnum === 2) {
// 后一图像视口
this.selectViewCanvas(1)
} else if (shortcutKeyEnum === 3) {
// 上一个序列
const series = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].series
DicomEvent.$emit('selectSeries', { seriesId: series.seriesId, studyId: series.studyId, offset: -1 })
} else if (shortcutKeyEnum === 4) {
// 下一个序列
const series = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].series
DicomEvent.$emit('selectSeries', { seriesId: series.seriesId, studyId: series.studyId, offset: 1 })
} else if (shortcutKeyEnum === 5) {
// 上一张图像
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].scrollPage(-1)
} else if (shortcutKeyEnum === 6) {
// 下一张图像
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].scrollPage(1)
} else if (shortcutKeyEnum === 7) {
// 向左旋转
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(false, false, -90, 4)
} else if (shortcutKeyEnum === 8) {
// 向右旋转
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(false, false, 90, 5)
} else if (shortcutKeyEnum === 9) {
// 水平翻转
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(true, false, 0, 3)
} else if (shortcutKeyEnum === 10) {
// 垂直翻转
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(false, true, 0, 2)
} else if (shortcutKeyEnum === 11) {
// 放大
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setZoomScale(1)
} else if (shortcutKeyEnum === 12) {
// 缩小
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setZoomScale(0)
} else if (shortcutKeyEnum === 13) {
// 适应图像
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToImage()
} else if (shortcutKeyEnum === 14) {
// 适应窗口
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToWindow()
} else if (shortcutKeyEnum === 15) {
// 截图
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].saveImage()
} else if (shortcutKeyEnum === 16) {
// 反色
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
} else if (shortcutKeyEnum === 17) {
// 窗宽/窗位
var wwwcArrIdx = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].wwwcArrIdx
var wwwcArr = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].wwwcArr
if (wwwcArrIdx + 1 === wwwcArr.length) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].wwwcArrIdx = 0
} else {
++this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].wwwcArrIdx
}
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setWwwc(wwwcArr[wwwcArrIdx].ww, wwwcArr[wwwcArrIdx].wc)
} else if (shortcutKeyEnum === 18) {
// 重置
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetViewport()
}else if (shortcutKeyEnum === 19) {
// 显示或隐藏标记
if (this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].readingTaskState < 2) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setMeasureDataVisible()
}
}
})
},
resetViewport() {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetViewport()
},
previewConfig() {
this.activeName = '1'
this.personalConfigDialog.visible = true
},
setCornerstoneStyle(i) {
if (this.cornerstoneStyle.position) {
this.cornerstoneStyle = {}
this.setCanvasStyle()
} else {
this.cornerstoneStyle = {
position: 'absolute',
top: '72px',
left: '205px',
right: '350px',
zIndex: 10
}
this.canvasW = window.innerWidth - 570 + 'px'
this.canvasH = window.innerHeight - 130 + 'px'
}
this.$nextTick(() => {
// this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].reloadCanvas()
for (var i = 0; i < this.maxCanvas; i++) {
this.$refs[`dicomCanvas${i}`][0].reloadCanvas()
}
})
},
loadImageStacks(seriesList) {
if (seriesList.length === 0) {
const idx = this.visitTaskList.findIndex(i => i.IsCurrentTask)
if (idx > -1) {
store.dispatch('reading/setLastCanvasTaskId', this.visitTaskList[idx].VisitTaskId)
}
return
}
var l = seriesList.length > 1 ? 'A|B' : 'A'
this.layout = l
var i = this.layouts.findIndex(i => i.name === l)
var layout = this.layouts[i]
this.layoutRow = layout.row
this.layoutCol = layout.col
this.setCanvasStyle()
this.maxCanvas = layout.row * layout.col
this.$nextTick(() => {
const elements = document.querySelectorAll('.cornerstone-element')
Array.from(elements).forEach((element) => {
cornerstone.enable(element)
cornerstone.resize(element)
})
seriesList.map((series, index) => {
this.canvasObj[index] = series
if (series.isCurrentTask) {
this.currentDicomCanvasIndex = index
this.activeSeries = series
// this.$refs['measurementList'].initPage(series)
store.dispatch('reading/setActiveSeries', series)
store.dispatch('reading/setLastCanvasTaskId', series.visitTaskId)
}
this.$refs[`dicomCanvas${index}`][0].loadImageStack(series)
if (this.activeTool) {
if (series.isCurrentTask && series.readingTaskState < 2) {
this.$nextTick(() => {
this.$refs[`dicomCanvas${index}`][0].setToolPassive(this.activeTool)
})
} else {
this.$nextTick(() => {
this.$refs[`dicomCanvas${index}`][0].setToolEnabled(this.activeTool)
})
}
this.activeTool = ''
}
})
})
},
loadImageStack(dicomSeries) {
this.canvasObj[this.currentDicomCanvasIndex] = dicomSeries
if (this.activeTool) {
if (dicomSeries.isCurrentTask && dicomSeries.readingTaskState < 2) {
this.$nextTick(() => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
})
} else {
this.$nextTick(() => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
})
}
this.activeTool = ''
}
this.$nextTick(() => {
this.activeSeries = dicomSeries
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].loadImageStack(dicomSeries)
// this.$refs['measurementList'].initPage(dicomSeries)
store.dispatch('reading/setActiveSeries', dicomSeries)
if (this.currentDicomCanvasIndex === this.maxCanvas - 1) {
store.dispatch('reading/setLastCanvasTaskId', dicomSeries.visitTaskId)
}
})
},
loadLinkedImageStack(dicomSeries) {
this.currentDicomCanvasIndex = dicomSeries.canvasIndex
var canvasIndex = dicomSeries.canvasIndex
this.canvasObj[canvasIndex] = dicomSeries
if (this.activeTool) {
if (dicomSeries.isCurrentTask && dicomSeries.readingTaskState < 2) {
this.$nextTick(() => {
this.$refs[`dicomCanvas${canvasIndex}`][0].setToolPassive(this.activeTool)
})
} else {
this.$nextTick(() => {
this.$refs[`dicomCanvas${canvasIndex}`][0].setToolEnabled(this.activeTool)
})
}
this.activeTool = ''
}
this.$nextTick(() => {
this.activeSeries = dicomSeries
this.$refs[`dicomCanvas${canvasIndex}`][0].loadImageStack(dicomSeries)
store.dispatch('reading/setActiveSeries', dicomSeries)
if (this.currentDicomCanvasIndex === this.maxCanvas - 1) {
store.dispatch('reading/setLastCanvasTaskId', dicomSeries.visitTaskId)
}
})
},
// 给显示的画布设置显示的序列信息
async getSeriesShowInCanvas(layout) {
var activeSeries = Object.assign({}, this.activeSeries)
const loading = this.$loading({ fullscreen: true })
if (layout.name === 'A') {
// 判断当前激活窗口是否有序列信息
if (activeSeries) {
this.seriesStack = [activeSeries]
this.currentDicomCanvasIndex = 0
store.dispatch('reading/setLastCanvasTaskId', activeSeries.visitTaskId)
await this.setCanvas(this.seriesStack)
loading.close()
}
} else if (layout.name === 'A|A') {
if (activeSeries) {
this.seriesStack = [activeSeries, activeSeries]
this.currentDicomCanvasIndex = 1
store.dispatch('reading/setLastCanvasTaskId', activeSeries.visitTaskId)
await this.setCanvas(this.seriesStack)
loading.close()
}
} else if (layout.name === 'A|B') {
if (activeSeries) {
const idx = this.visitTaskList.findIndex(i => i.VisitTaskId === activeSeries.visitTaskId)
const visitTaskNum = idx > -1 ? this.visitTaskList[idx].VisitTaskNum : -1
if (visitTaskNum > 0 && this.visitTaskList.length > 1) {
var visitTaskId = ''
if (this.CriterionType === 10) {
const i = this.visitTaskList.findIndex(i => i.VisitTaskNum === visitTaskNum - 1)
visitTaskId = this.visitTaskList[i].VisitTaskId
} else {
const i = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
visitTaskId = this.visitTaskList[i].VisitTaskId
}
this.getFirstSeries(activeSeries, visitTaskId).then(async baseSerires => {
this.seriesStack = [baseSerires, activeSeries]
this.currentDicomCanvasIndex = 1
store.dispatch('reading/setLastCanvasTaskId', activeSeries.visitTaskId)
await this.setCanvas(this.seriesStack)
loading.close()
})
} else {
this.seriesStack = [activeSeries, activeSeries]
this.currentDicomCanvasIndex = 1
store.dispatch('reading/setLastCanvasTaskId', activeSeries.visitTaskId)
await this.setCanvas(this.seriesStack)
loading.close()
}
}
} else if (layout.name === 'A|A|A|A') {
if (activeSeries) {
this.seriesStack = [activeSeries, activeSeries, activeSeries, activeSeries]
this.currentDicomCanvasIndex = 3
store.dispatch('reading/setLastCanvasTaskId', activeSeries.visitTaskId)
await this.setCanvas(this.seriesStack)
loading.close()
}
}
},
// 设置画布序列信息
setCanvas(seriesStack) {
return new Promise(resolve => {
var promiseArr = []
for (let i = 0; i < this.maxCanvas && i < seriesStack.length; i++) {
this.canvasObj[i] = seriesStack[i]
promiseArr.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(seriesStack[i]))
}
Promise.all(promiseArr).then(() => {
// this.activateDicomCanvas(this.currentDicomCanvasIndex)
resolve()
}).catch(() => { resolve() })
})
},
// 根据病灶标识定位图像
// 最后一个窗口显示当前访视下病灶所在的影像序列
// 其他窗口显示该病灶第一次出现的序列信息
async imageLocation(obj) {
var loading = null
var loadImagePromises = []
var isScrollSync = this.isScrollSync
if (this.isScrollSync) {
// 取消滚动同步
this.isScrollSync = false
}
var activeCanvasTaskId = obj.visitTaskId
var index = this.visitTaskList.findIndex(i => i.VisitTaskId === activeCanvasTaskId)
if (index === -1) return
var firstAddSeries = null
var currentAddSeries = null
if (this.isReadingTaskViewInOrder) {
// 有序
// 获取病灶第一次出现的访视序列
var firstAddVisitTaskId = null
var idx = this.visitTaskList[index].MeasureData.findIndex(item => {
return item.OrderMarkName === obj.lesionName
})
if (idx > -1) {
firstAddVisitTaskId = this.visitTaskList[index].MeasureData[idx].FristAddTaskId
}
if (firstAddVisitTaskId) {
var taskIdx = this.visitTaskList.findIndex(i => i.VisitTaskId === firstAddVisitTaskId)
if (taskIdx > -1 && !this.visitTaskList[taskIdx].IsInit) {
loading = this.$loading({ fullscreen: true })
if (!this.visitTaskList[taskIdx].measureDataInit) {
await store.dispatch('reading/getMeasuredData', this.visitTaskList[taskIdx].VisitTaskId)
}
if (!this.visitTaskList[taskIdx].studyListInit) {
await store.dispatch('reading/getStudyInfo', { trialId: this.trialId, subjectVisitId: this.visitTaskList[taskIdx].VisitId, visitTaskId: this.visitTaskList[taskIdx].VisitTaskId, taskBlindName: this.visitTaskList[taskIdx].TaskBlindName })
}
if (!this.visitTaskList[taskIdx].readingQuestionsInit) {
await store.dispatch('reading/getReadingQuestionAndAnswer', { trialId: this.trialId, visitTaskId: this.visitTaskList[taskIdx].VisitTaskId })
}
if (!this.visitTaskList[taskIdx].questionsInit) {
await store.dispatch('reading/getDicomReadingQuestionAnswer', { trialId: this.trialId, visitTaskId: this.visitTaskList[taskIdx].VisitTaskId })
}
await store.dispatch('reading/setStatus', { visitTaskId: this.visitTaskList[taskIdx].VisitTaskId })
}
firstAddSeries = this.getSeriesInfoByMark(firstAddVisitTaskId, obj)
}
// 获取当前访视病灶所在的序列
currentAddSeries = this.getSeriesInfoByMark(activeCanvasTaskId, obj)
if (!firstAddSeries && currentAddSeries) {
// 存在首次出现的病灶及当前病灶
firstAddSeries = currentAddSeries
} else if (!firstAddSeries && !currentAddSeries) {
// 当前新病灶,且未画标记则显示当前的序列信息,不做处理
loading && loading.close()
return
} else if (firstAddSeries && !currentAddSeries) {
// 当前访视序列与首次出现病灶的序列对齐
currentAddSeries = this.getLinkedSeries(firstAddSeries, activeCanvasTaskId)
if (!currentAddSeries) {
// 未找到对齐的,则就显示当前最后一个窗口现实的序列信息
currentAddSeries = this.$refs[`dicomCanvas${this.maxCanvas - 1}`][0].series
}
}
} else {
// 无序
currentAddSeries = this.getSeriesInfoByMark(activeCanvasTaskId, obj)
if (!currentAddSeries) {
// 未找到对齐的,则就显示当前最后一个窗口现实的序列信息
currentAddSeries = this.$refs[`dicomCanvas${this.maxCanvas - 1}`][0].series
}
firstAddSeries = currentAddSeries
}
for (let i = 0; i < this.maxCanvas; i++) {
if (i === this.maxCanvas - 1) {
loadImagePromises.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(currentAddSeries))
this.currentDicomCanvasIndex = i
this.activeSeries = currentAddSeries
store.dispatch('reading/setActiveSeries', currentAddSeries)
} else {
loadImagePromises.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(firstAddSeries))
}
}
Promise.all(loadImagePromises)
.then(() => {
this.isScrollSync = isScrollSync
})
if (loading) {
loading.close()
}
},
selectViewCanvas(offset) {
var canvasIndex = this.currentDicomCanvasIndex + offset
if (canvasIndex < 0 || canvasIndex >= this.maxCanvas) return
this.activateDicomCanvas(canvasIndex)
},
// 根据标记获取标记所在的序列信息
getSeriesInfoByMark(visitTaskId, obj) {
var seriesInfo = null
// 根据任务ID测量病灶信息
var index = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
if (index > -1) {
var idx = -1
if (this.CriterionType === 10) {
idx = this.visitTaskList[index].MeasureData.findIndex(item => item.OrderMarkName === obj.lesionName)
} else {
idx = this.visitTaskList[index].MeasureData.findIndex(item => item.QuestionId === obj.questionId && item.RowIndex === obj.rowIndex)
}
if (idx > -1 && this.visitTaskList[index].MeasureData[idx].MeasureData) {
var studyList = this.visitTaskList[index].StudyList
var studyId = this.visitTaskList[index].MeasureData[idx].StudyId
var seriesId = this.visitTaskList[index].MeasureData[idx].SeriesId
var instanceId = this.visitTaskList[index].MeasureData[idx].InstanceId
var studyIdx = studyList.findIndex(study => study.StudyId === studyId)
if (studyIdx > -1) {
var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId)
if (seriesIdx > -1) {
var series = studyList[studyIdx].SeriesList[seriesIdx]
var instanceIdx = series.instanceList.findIndex(imageId => !!~imageId.indexOf(instanceId))
if (instanceIdx > -1) {
series.imageIdIndex = instanceIdx
seriesInfo = series
}
}
}
}
}
return seriesInfo
},
getLinkedSeries(baseSeries, visitTaskId) {
var index = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
var visitTaskInfo = this.visitTaskList[index]
var obj = null
var studyList = visitTaskInfo.StudyList
// 查找筛选描述一致
var seriesList = studyList.map(s => s.SeriesList).flat()
var similarArr = seriesList.map((i, index) => {
return { similar: this.strSimilarity2Percent(i.description, baseSeries.description), index }
})
similarArr = similarArr.sort((a, b) => {
return b.similar - a.similar
})
const i = similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1
if (i > -1) {
obj = seriesList[i]
}
// if (!obj) {
// // 描述不一致,则筛选层厚一致
// const idx = seriesList.findIndex(series => series.sliceThickness === baseSeries.sliceThickness)
// idx > -1 ? obj = seriesList[idx] : ''
// }
// if (!obj) {
// // 层厚不一致,则筛选图像数量一致
// const idx = seriesList.findIndex(series => series.instanceCount === baseSeries.instanceCount)
// idx > -1 ? obj = seriesList[idx] : ''
// }
if (obj) {
let index = Math.floor(obj.imageIds.length * ((baseSeries.imageIdIndex+1) / baseSeries.instanceCount))
obj.imageIdIndex = index > 0 ? index - 1 : 0
}
return obj
},
strSimilarity2Number(s, t) {
var n = s.length; var m = t.length; var d = []
var i, j, s_i, t_j, cost
if (n === 0) return m
if (m === 0) return n
for (i = 0; i <= n; i++) {
d[i] = []
d[i][0] = i
}
for (j = 0; j <= m; j++) {
d[0][j] = j
}
for (i = 1; i <= n; i++) {
s_i = s.charAt(i - 1)
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1)
if (s_i === t_j) {
cost = 0
} else {
cost = 1
}
d[i][j] = this.Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost)
}
}
return d[n][m]
},
// 两个字符串的相似程度,并返回相似度百分比
strSimilarity2Percent(s, t) {
var l = s.length > t.length ? s.length : t.length
var d = this.strSimilarity2Number(s, t)
return Number((1 - d / l).toFixed(4))
},
Minimum(a, b, c) {
return a < b ? (a < c ? a : c) : (b < c ? b : c)
},
// 获取某个任务下可对齐的序列信息
async getFirstSeries(baseSeries, visitTaskId) {
var index = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
if (!this.visitTaskList[index].studyListInit) {
await store.dispatch('reading/getStudyInfo', { trialId: this.trialId, subjectVisitId: this.visitTaskList[index].VisitId, visitTaskId: this.visitTaskList[index].VisitTaskId, taskBlindName: this.visitTaskList[index].TaskBlindName })
await store.dispatch('reading/getMeasuredData', this.visitTaskList[index].VisitTaskId)
}
var visitTaskInfo = this.visitTaskList[index]
var obj = null
var studyList = visitTaskInfo.StudyList
// 查找筛选描述一致
var seriesList = studyList.map(s => s.SeriesList).flat()
var similarArr = seriesList.map((i, index) => {
return { similar: this.strSimilarity2Percent(i.description, baseSeries.description), index }
})
similarArr = similarArr.sort((a, b) => {
return b.similar - a.similar
})
const i = similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1
if (i > -1) {
obj = seriesList[i]
}
// if (!obj) {
// // 描述不一致,则筛选层厚一致
// const idx = seriesList.findIndex(series => series.sliceThickness === baseSeries.sliceThickness)
// idx > -1 ? obj = seriesList[idx] : ''
// }
// if (!obj) {
// // 层厚不一致,则筛选图像数量一致
// const idx = seriesList.findIndex(series => series.instanceCount === baseSeries.instanceCount)
// idx > -1 ? obj = seriesList[idx] : ''
// }
if (!obj) {
// 都不符合要求, 判断是否存在层厚为5的序列否则显示第一个检查的第一个序列
const idx = seriesList.findIndex(series => series.isDicom && parseInt(series.instanceCount) === 5)
idx > -1 ? obj = seriesList[idx] : obj = seriesList[0]
}
if (obj) {
let index = Math.floor(obj.imageIds.length * ((baseSeries.imageIdIndex + 1) / baseSeries.instanceCount))
obj.imageIdIndex = index > 0 ? index - 1 : 0
}
return obj
},
// 设置画布大小
setCanvasStyle() {
this.canvasW = (window.innerWidth - 570) / this.layoutCol + 'px'
this.canvasH = (window.innerHeight - 130) / this.layoutRow + 'px'
},
// 切换布局
changeLayout(name) {
if (this.activeTool) {
if (this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].isCurrentTask && this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].readingTaskState < 2) {
this.$nextTick(() => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
})
} else {
this.$nextTick(() => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
})
}
this.activeTool = ''
}
this.isScrollSync = false
this.activeSeries = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
this.layout = name
var i = this.layouts.findIndex(i => i.name === name)
var layout = this.layouts[i]
this.layoutRow = layout.row
this.layoutCol = layout.col
this.setCanvasStyle()
this.maxCanvas = layout.row * layout.col
this.$nextTick(() => {
const elements = document.querySelectorAll('.cornerstone-element')
Array.from(elements).forEach((element) => {
cornerstone.enable(element)
cornerstone.resize(element)
})
this.getSeriesShowInCanvas(layout)
this.cornerstoneStyle = {}
this.setCanvasStyle()
})
},
// 更新画布
updateCanvas(measureData) {
for (let i = 0; i < this.maxCanvas; i++) {
var stack = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
if (stack.studyId) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].removeToolState(measureData)
}
}
},
// 旋转
setDicomCanvasRotate(value) {
const type = parseInt(value)
if (type === 1) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetRotate()
} else if (type === 2) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(false, true, 0, type)
} else if (type === 3) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(true, false, 0, type)
} else if (type === 4) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(false, false, -90, type)
} else if (type === 5) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setRotate(false, false, 90, type)
}
},
// 激活画布
activateDicomCanvas(index) {
console.log('激活画布')
if (index !== this.currentDicomCanvasIndex) {
this.currentDicomCanvasIndex = index
// var dicomSeries = this.canvasObj[this.currentDicomCanvasIndex]
var dicomSeries = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
this.activeSeries = dicomSeries
for (let i = 0; i < this.maxCanvas; i++) {
if (this.activeTool) {
var series = this.$refs[`dicomCanvas${i}`][0].stack
if (series.isCurrentTask && series.readingTaskState < 2) {
this.$refs[`dicomCanvas${i}`][0].setToolPassive(this.activeTool)
} else {
this.$refs[`dicomCanvas${i}`][0].setToolEnabled(this.activeTool)
}
}
}
this.activeTool = ''
this.isScrollSync = false
this.currentDicomCanvasIndex = index
this.currentDicomCanvas = this.$refs[`dicomCanvas${index}`]
this.currentDicomCanvas.tabIndex = 0
if (!this.rotateList[this.currentDicomCanvasIndex]) {
this.rotateList[this.currentDicomCanvasIndex] = '1'
}
if (!this.colorList[this.currentDicomCanvasIndex]) {
this.colorList[this.currentDicomCanvasIndex] = ''
}
if (!this.wwwcList[this.currentDicomCanvasIndex]) {
this.wwwcList[this.currentDicomCanvasIndex] = '1'
}
// var stack = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
this.$refs['container'].focus()
// if (stack.studyId) {
// DicomEvent.$emit('toggleVisitList', stack)
// }
store.dispatch('reading/setActiveSeries', dicomSeries)
}
},
// 鼠标移入测量工具时,判断工具是否可激活
enter(e, toolName) {
var i = this.measuredTools.findIndex(item => item.toolName === toolName)
if (i === -1) return
var isCurrentTask = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].isCurrentTask
var readingTaskState = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].readingTaskState
if (!isCurrentTask || readingTaskState >= 2) {
this.measuredTools[i].isDisabled = true
e.target.style.cursor = 'not-allowed'
if (this.activeTool) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
this.activeTool = ''
}
} else {
this.measuredTools[i].isDisabled = false
e.target.style.cursor = 'pointer'
}
},
// 设置测量工具启用(不会对输入作出反应)
setToolActive(toolName, isMeasuredTool, e, type) {
console.log('setToolActive', toolName)
if (isMeasuredTool) {
// var i = this.measuredTools.findIndex(item => item.toolName === toolName)
// if (i === -1 && this.measuredTools[i].isDisabled) return
var toolObj = this.measuredTools.find(i => i.toolName === toolName)
if (!toolObj || toolObj.isDisabled) return
var dicomSeries = this.canvasObj[this.currentDicomCanvasIndex]
if (dicomSeries.isCurrentTask && isMeasuredTool && dicomSeries.readingTaskState < 2) {
if (this.activeTool && !type) {
this.measuredTools.forEach(item => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(item.toolName)
})
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(toolName)
// this.activeTool = ''
this.activeTool = toolName
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolActive(toolName)
} else {
this.measuredTools.forEach(item => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(item.toolName)
})
this.activeTool = toolName
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolActive(toolName)
}
} else {
if (!this.activeTool) return
this.measuredTools.forEach(item => {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(item.toolName)
})
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
this.activeTool = ''
}
} else {
if (this.activeTool === toolName) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
this.activeTool = ''
} else {
this.activeTool = toolName
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolActive(toolName)
}
}
},
// 设置测量工具禁用(不会对输入作出反应)
setToolEnabled() {
var dicomSeries = this.canvasObj[this.currentDicomCanvasIndex]
if (!dicomSeries.isCurrentTask) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
this.activeTool = ''
return
}
if (this.activeTool) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(this.activeTool)
this.activeTool = ''
}
},
// 影像适应图像/适应窗口
fitToType(toolName) {
if (this.activeTool !== 'fitToWindow' && this.activeTool !== 'fitToImage') {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
}
if (toolName === 'fitToWindow') {
this.fitType = 0
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToWindow()
} else if (toolName === 'fitToImage') {
this.fitType = 1
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToImage()
}
this.activeTool = toolName
},
// 添加标记
setMeasureData(data) {
this.$refs['measurementList'].setMeasuredData(data)
this.activeTool = ''
},
// 修改标记
modifyMeasureData(data) {
this.$refs['measurementList'].modifyMeasuredData(data)
this.activeTool = ''
},
saveImage() {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].saveImage()
},
// 设置窗宽/窗位
setDicomCanvasWwwc(v) {
if (v.val === -1) {
// 默认值
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetWwwc()
} else if (v.val === 0) {
// 自定义
this.setCustomWwwc()
} else if (v.val === 1) {
// 区域窗宽
// this.setToolActive('WwwcRegion', false)
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolActive('WwwcRegion')
} else if (v.val === 8) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
} else {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setWwwc(v.ww, v.wc)
}
},
setCustomWwwc() {
this.customWwc.visible = true
},
setWwwc(v) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setWwwc(v.ww, v.wc)
this.customWwc.visible = false
},
toggleInvert() {
if (this.activeTool === 'reversecolor') {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetWwwc()
this.activeTool = ''
} else {
this.activeTool = 'reversecolor'
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
}
},
setImageIndexSync() {
this.isScrollSync = !this.isScrollSync
},
scrollSync(obj) {
for (var i = 0; i < this.maxCanvas; i++) {
if (i !== this.currentDicomCanvasIndex) {
this.$refs[`dicomCanvas${i}`][0].scrollPage(obj.offset)
}
}
},
showPanel(e) {
e.currentTarget.firstChild.lastChild.style.display = 'block'
},
handleMouseout(e) {
e.currentTarget.firstChild.lastChild.style.display = 'none'
},
// 预览临床数据
previewCD() {
this.$emit('previewCD')
},
previewNoneDicoms() {
this.$emit('previewNoneDicoms')
},
previewManuals() {
this.isFullscreen = false
this.manualsDialog.visible = true
}
}
}
</script>
<style lang="scss" scoped>
.dicom-viewer-wrapper{
height: 100%;
padding: 5px 0px 5px 5px;
box-sizing: border-box;
.divider{
display: block;
height: 1px;
width: 100%;
margin: 10px 0;
// background-color: #383838;
// color: #fff;
// background-color: #DCDFE6;
}
.el-divider__text{
padding: 0 10px;
color: #fff;
background-color: #383838;
font-size: 12px;
width: 80px;
}
.dicom-viewer-container{
display:flex;
flex-direction: column;
height: 100%;
}
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.dicom-tools{
box-sizing: border-box;
width: 100%;
height: 80px;
padding: 0 5px;
border: 1px solid #727272;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
.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:20px;
color:#ddd;
}
}
.text{
position: relative;
font-size: 12px;
margin-top: 5px;
color: #d0d0d0;
display: none;
}
}
.tool_active{
background-color: #607d8b;
}
.tool_disabled{
cursor:not-allowed
}
.icon:hover{
background-color: #607d8b;
}
.dropdown {
position: relative;
display: inline-block;
.text{
text-align: center;
}
}
.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 0px;
}
}
}
ul li:hover a{
background-color: #727272;
}
}
// .dropdown:hover .dropdown-content {
// display: block;
// }
.layout-content ul li{
border-top:1px solid #ddd;
border-left:1px solid #ddd;
}
.layout-content ul .flex_row{
// border: 1px solid #ddd;
display: flex;
justify-content: space-between;
flex-direction: row;
align-items: center;
// padding: 2px;
margin-bottom: 2px;
}
.layout-content ul .flex_column{
display: flex;
justify-content: space-between;
flex-direction: column;
align-items: center;
margin-bottom: 2px;
}
.layout_box_1_1{
flex:1;
// border: 1px solid #ddd;
line-height: 30px;
font-size: 12px;
text-align: center;
border-bottom:1px solid #ddd;
border-right:1px solid #ddd;
// padding: 0 5px;
}
.layout_box_1_2{
flex:1;
// border: 1px solid #ddd;
line-height: 15px;
font-size: 10px;
text-align: center;
border-bottom:1px solid #ddd;
border-right:1px solid #ddd;
// padding: 0 5px;
}
.layout-content li .layout_box_1_1 :last-child{
color: red;
}
// .layout_li:last-child{
// .layout_box{
// border-bottom: none;
// }
// }
.layout-content li:hover {
cursor: pointer;
background-color: #727272;
}
}
.dicom-viewers{
box-sizing: border-box;
flex: 1;
// width: 100%;
margin-top: 5px;
height: 100%;
display: flex;
flex-direction: row;
justify-content: flex-start;
.form-container{
// box-sizing: border-box;
width: 350px;
height: 100%;
border: 1px solid #727272;
// overflow-y: auto;
}
.viewer-container{
box-sizing: border-box;
flex: 1;
height: 100%;
border: 1px solid #727272;
}
.measurement-container{
// height: 100%;
overflow-y: auto;
}
.box{
display: grid;
box-sizing: border-box;
height: 100%;
padding: 0;
.item{
box-sizing: border-box;
position: relative;
border: 1px solid rgba(255, 255, 255, 0.21);
position: relative;
&_active{
// border: 2px solid #ffeb3b;
border: 1px dashed #00d1b2;
}
}
}
.box_1_1{
grid-template-columns: repeat(1, 100%); //1列占100%
grid-template-rows: repeat(1, 100%); //1行占100%
}
.box_1_2{
grid-template-columns: repeat(2, 50%); //1列占50%
grid-template-rows: repeat(1, 100%); //1行占100%
}
.box_2_1{
grid-template-columns: repeat(1, 100%); //1列占100%
grid-template-rows: repeat(2, 50%); //1行占50%
}
.box_2_2{
grid-template-columns: repeat(2, 50%); //1列占50%
grid-template-rows: repeat(2, 50%); //1行占50%
}
// .box_3_1{
// grid-template-columns: repeat(3, 100%); //1列占100%
// grid-template-rows: repeat(3, 33.33%); //1行占100%
// }
// .box_3_2{
// grid-template-columns: repeat(3, 50%); //1列占100%
// grid-template-rows: repeat(3, 50%); //1行占100%
// }
// .box_3_3{
// grid-template-columns: repeat(3, 33.33%); //1列占100%
// grid-template-rows: repeat(3, 33.33%); //1行占100%
// }
}
.personal_config {
>>>.el-tabs__content{
height: 450px;
overflow-y: auto;
}
}
>>>.manuals-dialog-container{
margin-top: 50px !important;
width:75%;
height:80%;
.el-dialog__body{
padding: 10px;
height: calc(100% - 50px) !important;
}
.el-dialog__header{
position: relative;
}
}
>>>.manuals-full-dialog-container{
.el-dialog__body{
padding: 10px;
height: calc(100% - 50px) !important;
}
.el-dialog__header{
position: relative;
}
}
}
</style>