irc_web/.svn/pristine/00/007e1f2075a5382f848ca1aab2a...

549 lines
16 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">
<div class="tool-wrapper">
<div class="dropdown">
<div class="icon">
<svg-icon icon-class="layout" class="svg-icon" />
</div>
<div class="text">布局<i class="el-icon-caret-bottom" /></div>
<div class="dropdown-content">
<ul style="width:40px">
<li v-for="layout in layouts" :key="layout.index">
<a href="#" @click.prevent="changeLayout(layout)">{{ layout.row }}*{{ layout.col }}</a>
</li>
</ul>
</div>
</div>
</div>
<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">缩放</div>
</div>
<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">移动</div>
</div>
<div class="tool-wrapper">
<div
class="icon"
@click.prevent="fitToType('fitToWindow')"
>
<svg-icon icon-class="fitToWindow" class="svg-icon" />
</div>
<div class="text">适应窗口</div>
</div>
<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>
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Length'?'tool_active':'']"
data-tool="Length"
@click.prevent="setToolActive('Length',true)"
>
<svg-icon icon-class="length" class="svg-icon" />
</div>
<div class="text">长度测量</div>
</div>
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Bidirectional'?'tool_active':'']"
data-tool="Bidirectional"
@click.prevent="setToolActive('Bidirectional',true)"
>
<svg-icon icon-class="bidirection" class="svg-icon" />
</div>
<div class="text">十字线</div>
</div>
<div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='ArrowAnnotate'?'tool_active':'']"
data-tool="ArrowAnnotate"
@click.prevent="setToolActive('ArrowAnnotate',true)"
>
<svg-icon icon-class="label" class="svg-icon" />
</div>
<div class="text">文字标注</div>
</div>
<!-- <div class="tool-wrapper">
<div
class="icon"
:class="[activeTool==='Eraser'?'tool_active':'']"
data-tool="Eraser"
@click.prevent="setToolActive('Eraser')"
>
<svg-icon icon-class="clear" class="svg-icon" />
</div>
<div class="text">清除标记</div>
</div> -->
<div class="tool-wrapper">
<div class="dropdown">
<div class="icon">
<svg-icon icon-class="more" class="svg-icon" />
</div>
<div class="text">更多<i class="el-icon-caret-bottom" /></div>
<div class="dropdown-content">
<ul style="width:90px;text-align: left;">
<li>
<a href="#">
<svg-icon icon-class="angle" />
角度测量
</a>
</li>
<li>
<a href="#">
<svg-icon icon-class="cobb" />
Cobb测量
</a>
</li>
<li>
<a href="#">
<svg-icon icon-class="oval" />
椭圆测量
</a>
</li>
<li>
<a href="#">
<svg-icon icon-class="rectangle" />
矩形测量
</a>
</li>
<li>
<a href="#">
<svg-icon icon-class="image" />
导出Png图像
</a>
</li>
</ul>
</div>
</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"
@click="activateDicomCanvas(i-1)"
>
<dicom-canvas
v-if="canvasW"
:ref="`dicomCanvas${i-1}`"
:style="{width:canvasW,height: canvasH}"
:is-current-task="isCurrentTask"
:is-active="i-1===currentDicomCanvasIndex"
@setMeasureData="setMeasureData"
@removeMeasureData="removeMeasureData"
@modifyMeasureData="modifyMeasureData"
/>
</div>
</div>
<div ref="form-container" class="form-container">
<MeasurementList
v-if="visitTaskId"
ref="measurementList"
:is-current-task="isCurrentTask"
/>
</div>
</div>
</div>
</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 MeasurementList from './MeasurementList'
import Store from './Store'
export default {
name: 'DicomViewer',
components: { DicomCanvas, MeasurementList },
props: {
visitTaskId: {
type: String,
default: ''
},
isCurrentTask: {
type: Boolean,
required: true
},
readingTaskState: {
type: Number,
required: true
}
},
data() {
return {
layouts: [
{ index: 0, row: 1, col: 1 },
{ index: 1, row: 1, col: 2 },
{ index: 2, row: 2, col: 1 },
{ index: 3, row: 2, col: 2 }
],
maxCanvas: 1,
layoutRow: 1,
layoutCol: 1,
currentDicomCanvasIndex: 0,
currentDicomCanvas: {
toolState: {
clipPlaying: false
}
},
colormapsList: [],
rotateList: [],
colorList: [],
wwwcList: [],
canvasW: null,
canvasH: null,
activeTool: '',
measuredTools: ['Length', 'Bidirectional']
}
},
mounted() {
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.setCanvasStyle()
window.addEventListener('resize', this.setCanvasStyle)
Store.$on('updateImage', (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].updateImage(measureData)
}
}
console.log('updateImage')
})
},
beforeDestroy() {
Store.$off('updateImage')
},
methods: {
loadImageStack(dicomSeries) {
if (this.activeTool) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
this.activeTool = ''
}
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].loadImageStack(dicomSeries)
},
// 设置画布大小
setCanvasStyle() {
this.canvasW = (window.innerWidth - 520) / this.layoutCol + 'px'
this.canvasH = (window.innerHeight - 130) / this.layoutRow + 'px'
},
// 切换布局
changeLayout(layout) {
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)
})
})
},
// 激活画布
activateDicomCanvas(index) {
if (index !== this.currentDicomCanvasIndex) {
if (this.activeTool) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(this.activeTool)
this.activeTool = ''
}
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
if (stack.studyId) {
Store.$emit('toggleVisitList', stack)
}
}
},
setToolActive(toolName, isMeasuredTool) {
console.log((!this.isCurrentTask && isMeasuredTool) || this.readingTaskState >= 2)
if ((!this.isCurrentTask && isMeasuredTool) || this.readingTaskState >= 2) {
this.activeTool = ''
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
return
}
if (this.activeTool === toolName) {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
this.activeTool = ''
} else {
if (this.measuredTools.includes(toolName)) {
var isCanActiveTool = this.$refs['measurementList'].isCanActiveTool()
if (isCanActiveTool) {
this.activeTool = toolName
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolActive(toolName)
}
}
}
},
setToolEnabled() {
if (!this.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.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToWindow()
} else if (toolName === 'fitToImage') {
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToImage()
}
this.activeTool = toolName
},
setMeasureData(data) {
this.$refs['measurementList'].setMeasuredData(data)
this.activeTool = ''
},
removeMeasureData(uuid) {
console.log(uuid)
},
modifyMeasureData(data) {
this.$refs['measurementList'].modifyMeasuredData(data)
this.activeTool = ''
}
}
}
</script>
<style lang="scss" scoped>
.dicom-viewer-wrapper{
height: 100%;
padding: 5px 0px 5px 5px;
box-sizing: border-box;
.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;
}
}
.tool_active{
background-color: #607d8b;
}
.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: 1;
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;
}
}
.dicom-viewers{
box-sizing: border-box;
flex: 1;
// width: 100%;
margin-top: 5px;
height: 100%;
display: flex;
flex-direction: row;
justify-content: flex-start;
.viewer-container{
box-sizing: border-box;
flex: 1;
height: 100%;
border: 1px solid #727272;
}
.form-container{
// box-sizing: border-box;
width: 300px;
height: 100%;
border: 1px solid #727272;
// overflow-y: auto;
}
.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: 1px solid #5297b9;
}
}
}
.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%
// }
}
}
</style>