阅片页面更改
parent
4188c0110f
commit
0960b480a6
|
@ -277,7 +277,7 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.preview-wrapper{
|
||||
display: flex;
|
||||
flex-direction: row !important;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
<template>
|
||||
<div ref="container" style="width:100%;height:100%" class="dicom-container">
|
||||
<!-- 访视阅片 -->
|
||||
<div v-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType !== 0" class="reading-wrapper">
|
||||
<div v-if="readingCategory=== 1 && (CriterionType === 7)" class="reading-wrapper">
|
||||
<VisitReview />
|
||||
</div>
|
||||
<div v-else-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType !== 0" class="reading-wrapper">
|
||||
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeave">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
|
@ -29,7 +32,7 @@
|
|||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
<div v-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper">
|
||||
<div v-else-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper">
|
||||
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeaveCustomize">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
|
@ -171,6 +174,7 @@
|
|||
</template>
|
||||
<script>
|
||||
import { getNextTask, readClinicalData, verifyDefaultQuestionBeAnswer } from '@/api/trials'
|
||||
import VisitReview from './../dicoms3D/components/VisitReview'
|
||||
import ReadPage from './components/ReadPage'
|
||||
import CustomizeReadPage from './customize/CustomizeReadPage'
|
||||
import ReportPage from './components/ReportPage'
|
||||
|
@ -187,6 +191,7 @@ import requestPoolManager from '@/utils/request-pool'
|
|||
export default {
|
||||
name: 'Reading',
|
||||
components: {
|
||||
VisitReview,
|
||||
ReadPage,
|
||||
ReportPage,
|
||||
GlobalReview,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,273 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="study-wrapper">
|
||||
<div class="study-info">
|
||||
<div
|
||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
|
||||
:title="taskInfo.SubjectCode"
|
||||
>
|
||||
{{ taskInfo.SubjectCode }}
|
||||
</div>
|
||||
<div
|
||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
|
||||
:title="visitTaskInfo.TaskBlindName"
|
||||
>
|
||||
{{ visitTaskInfo.TaskBlindName }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ps">
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
||||
<template slot="title">
|
||||
<div
|
||||
v-if="!study.IsCriticalSequence"
|
||||
class="dicom-desc"
|
||||
>
|
||||
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
||||
<span v-if="study.StudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName }}</span>
|
||||
<span v-else :title="study.Modalities" style="margin-left: 5px;">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
<div style="text-overflow: ellipsis;overflow: hidden;" v-if="study.StudyName" >
|
||||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="taskInfo && !taskInfo.IsShowStudyName">
|
||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
||||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- 关键序列 -->
|
||||
{{ $t('trials:reading:title:keySeries') }}
|
||||
</div>
|
||||
</template>
|
||||
<div class="dicom-list-container">
|
||||
<div
|
||||
v-for="(series, i) in study.SeriesList"
|
||||
:key="i"
|
||||
style="position:relative;margin-top:1px;"
|
||||
@click="activeSeries(series, i, index)"
|
||||
>
|
||||
<div
|
||||
:class="{'series-active': index === activeStudyIndex && i === activeSeriesIndex}"
|
||||
class="series-wrapper"
|
||||
>
|
||||
<div class="series-image">
|
||||
<el-image
|
||||
style="width: 100%;height: 100%;"
|
||||
:src="`${OSSclientConfig.basePath}${series.ImageResizePath}`"
|
||||
fit="fill"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
</div>
|
||||
<div class="series-text" >
|
||||
<div class="text-desc" v-if="!study.IsCriticalSequence" :title="series.SeriesNumber">
|
||||
#{{ series.SeriesNumber }}
|
||||
</div>
|
||||
<div class="text-desc" v-if="series.Description" :title="series.Description">
|
||||
{{ series.Description }}
|
||||
</div>
|
||||
<div class="text-desc" v-if="series.SliceThickness && !study.IsCriticalSequence">
|
||||
T: {{ parseFloat(series.SliceThickness).toFixed(digitPlaces) }}
|
||||
</div>
|
||||
<div class="text-desc">
|
||||
<span v-show="series.LoadedImageCount < series.InstanceCount">
|
||||
{{ series.Modality }}: {{ series.LoadedImageCount }}/{{ series.InstanceCount }} image
|
||||
</span>
|
||||
<span v-show="series.LoadedImageCount >= series.InstanceCount">{{ series.Modality }}: {{ series.InstanceCount }} image</span>
|
||||
</div>
|
||||
<div v-show="series.IsBeMark">
|
||||
<i class="el-icon-star-on" style="font-size: 16px;color: #ff5722;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series.IsDicom && series.LoadedImageProgress>0 && series.LoadedImageProgress<100" style="width: 100%;">
|
||||
<el-progress
|
||||
:percentage="parseInt((series.LoadedImageProgress).toFixed(2))"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'StudyList',
|
||||
props: {
|
||||
visitTaskInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
activeNames: [],
|
||||
activeStudyIndex: -1,
|
||||
activeSeriesIndex: -1,
|
||||
taskInfo: null,
|
||||
studyList: [],
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.studyList = this.visitTaskInfo.StudyList
|
||||
if (this.studyList.length === 0) return
|
||||
this.$nextTick(() => {
|
||||
this.activeStudy(this.studyList[0].StudyId)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
activeSeries(series, seriesIndex, studyIndex) {
|
||||
this.activeStudyIndex = studyIndex
|
||||
this.activeSeriesIndex = seriesIndex
|
||||
this.$emit('activeSeries', series)
|
||||
},
|
||||
activeStudy(id) {
|
||||
if (this.activeNames.indexOf(id) > -1) return
|
||||
this.activeNames.push(id)
|
||||
},
|
||||
setSeriesActive(studyIndex, seriesIndex) {
|
||||
this.activeStudyIndex = studyIndex
|
||||
this.activeSeriesIndex = seriesIndex
|
||||
let studyId = this.studyList[studyIndex].StudyId
|
||||
if (!studyId) return
|
||||
this.activeStudy(studyId)
|
||||
},
|
||||
getPreviousOrNextSeries(type, series) {
|
||||
let seriseList = this.studyList.map(s => s.SeriesList).flat()
|
||||
let i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId)
|
||||
if (i === -1) return
|
||||
let newIndex = null
|
||||
if (type === -1) {
|
||||
newIndex = i === 0 ? i : i - 1
|
||||
} else {
|
||||
newIndex = i >= seriseList.length - 1 ? i : i +1
|
||||
}
|
||||
let studyIndex = seriseList[newIndex].StudyIndex
|
||||
let seriesIndex = seriseList[newIndex].SeriesIndex
|
||||
this.setSeriesActive(studyIndex, seriesIndex)
|
||||
this.activeSeries(seriseList[newIndex], seriesIndex, studyIndex)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.study-wrapper{
|
||||
width:100%;
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
overflow-x: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.study-info {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
background-color: #4c4c4c;
|
||||
height: 50px;
|
||||
}
|
||||
.dicom-desc{
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.ps {
|
||||
flex: 1;
|
||||
overflow-anchor: none;
|
||||
touch-action: auto;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.series-active {
|
||||
background-color: #607d8b!important;
|
||||
border: 1px solid #607d8b!important;
|
||||
}
|
||||
::v-deep.el-progress__text{
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
.dicom-list-container{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
.series-wrapper {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
background-color: #3a3a3a;
|
||||
.el-progress__text{
|
||||
display: none;
|
||||
}
|
||||
.el-progress-bar{
|
||||
padding-right:0px;
|
||||
}
|
||||
.series-image {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
.series-text {
|
||||
flex: 1;
|
||||
padding-left: 5px;
|
||||
color: #ddd;
|
||||
.text-desc {
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
::v-deep.el-collapse{
|
||||
border: none;
|
||||
.el-collapse-item{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
.el-collapse-item__content{
|
||||
padding-bottom:0px;
|
||||
background-color: #000!important;
|
||||
}
|
||||
.el-collapse-item__header{
|
||||
background-color: #000!important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
padding-left: 5px;
|
||||
// height: 50px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
::v-deep .el-progress-bar__inner{
|
||||
transition: width 0s ease;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,551 @@
|
|||
<template>
|
||||
<div
|
||||
ref="viewport"
|
||||
class="viewport-wrapper"
|
||||
@mouseup="sliderMouseup"
|
||||
@mousemove="sliderMousemove"
|
||||
@mouseleave="sliderMouseleave"
|
||||
>
|
||||
<div class="left-top-text" v-if="series && taskInfo">
|
||||
<div
|
||||
v-if="taskInfo.IsExistsClinicalData"
|
||||
class="cd-info"
|
||||
:title="$t('trials:reading:button:clinicalData')"
|
||||
>
|
||||
<svg-icon
|
||||
style="cursor: pointer;"
|
||||
icon-class="documentation"
|
||||
class="svg-icon"
|
||||
@click.stop="viewCD(series.TaskInfo.VisitTaskId)" />
|
||||
</div>
|
||||
<h2
|
||||
v-if="taskInfo.IsReadingShowSubjectInfo"
|
||||
class="subject-info"
|
||||
>
|
||||
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
|
||||
</h2>
|
||||
<div>Series: #{{ series.SeriesNumber }}</div>
|
||||
<div>Image: #{{ `${series.SliceIndex + 1}/${series.ImageIds.length}` }}</div>
|
||||
<div>{{series.Modality}}</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="series && taskInfo && taskInfo.IsReadingTaskViewInOrder === 1"
|
||||
class="top-center-tool"
|
||||
>
|
||||
<div class="toggle-visit-container">
|
||||
<div
|
||||
class="arrw_icon"
|
||||
:style="{ cursor: series.TaskInfo.VisitTaskNum !== 0 ? 'pointer' : 'not-allowed', color: series.TaskInfo.VisitTaskNum !== 0 ? '#fff': '#6b6b6b' }"
|
||||
@click.stop.prevent="toggleTask($event, series.TaskInfo.VisitTaskNum, -1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<i class="el-icon-caret-left" />
|
||||
</div>
|
||||
<div class="arrow_text">
|
||||
{{ series.TaskInfo.TaskBlindName }}
|
||||
</div>
|
||||
<div
|
||||
class="arrw_icon"
|
||||
:style="{ cursor: series.TaskInfo.VisitTaskNum < taskInfo.VisitNum ? 'pointer' : 'not-allowed', color: series.TaskInfo.VisitTaskNum < taskInfo.VisitNum ? '#fff': '#6b6b6b' }"
|
||||
@click.stop.prevent="toggleTask($event, series.TaskInfo.VisitTaskNum, 1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<i class="el-icon-caret-right" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-top-text" v-if="series">
|
||||
<div>{{ series.Description }}</div>
|
||||
</div>
|
||||
<div class="left-bottom-text" v-if="series">
|
||||
<div v-show="mousePosition.index.length > 0">
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
|
||||
</div>
|
||||
<div v-if="(series.Modality === 'CT' || series.Modality === 'DR' || series.Modality === 'CR') && mousePosition.value">
|
||||
HU: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-else-if="(series.Modality === 'PT' && mousePosition.value)">
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ?mousePosition.value.toFixed(3) :mousePosition.value.toFixed(digitPlaces) }}
|
||||
</div>
|
||||
<div v-else-if="mousePosition.value">
|
||||
Density: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-show="imageInfo.size">
|
||||
W*H: {{ imageInfo.size }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-bottom-text" v-if="series">
|
||||
<div v-show="imageInfo.location">Location: {{ `${Number(imageInfo.location).toFixed(digitPlaces)} mm` }}</div>
|
||||
<div v-show="series.SliceThickness">Slice Thickness: {{ `${Number(series.SliceThickness).toFixed(digitPlaces)} mm` }}</div>
|
||||
<div v-show="imageInfo.wwwc ">WW/WL: {{ imageInfo.wwwc }}</div>
|
||||
</div>
|
||||
<div class="orientation-top">
|
||||
{{ markers.top }}
|
||||
</div>
|
||||
<div class="orientation-right">
|
||||
{{ markers.right }}
|
||||
</div>
|
||||
|
||||
<div class="orientation-bottom">
|
||||
{{ markers.bottom }}
|
||||
</div>
|
||||
<div class="orientation-left">
|
||||
{{ markers.left }}
|
||||
</div>
|
||||
<div ref="sliderBox" class="right-slider-box" @click.stop="clickSlider($event)">
|
||||
<div :style="{top: sliderInfo.height + '%'}" class="slider" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as cornerstonejs from '@cornerstonejs/core'
|
||||
import {
|
||||
RenderingEngine,
|
||||
Enums,
|
||||
imageLoader,
|
||||
metaData,
|
||||
getRenderingEngine,
|
||||
eventTarget,
|
||||
utilities as csUtils
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
import { vec3, mat4 } from 'gl-matrix'
|
||||
export default {
|
||||
name: 'Viewport',
|
||||
props: {
|
||||
renderingEngineId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
viewportId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
viewportIndex: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data(){
|
||||
return {
|
||||
element: '',
|
||||
series: null,
|
||||
taskInfo: null,
|
||||
sliderInfo: {
|
||||
oldB: null,
|
||||
oldM: null,
|
||||
isMove: false,
|
||||
height: 0
|
||||
},
|
||||
mousePosition: {
|
||||
index: [],
|
||||
value: null,
|
||||
modalityUnit: '',
|
||||
world: []
|
||||
},
|
||||
imageInfo: {
|
||||
zoom: null,
|
||||
size: null,
|
||||
location: null,
|
||||
sliceThickness: null,
|
||||
wwwc: null
|
||||
},
|
||||
digitPlaces: 2,
|
||||
orientationMarkers: [],
|
||||
originalMarkers: [],
|
||||
markers: { top: '', right: '', bottom: '', left: '' },
|
||||
playClipState: false,
|
||||
wwwcIdx: 2
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.$nextTick(()=>{
|
||||
this.initViewport()
|
||||
})
|
||||
console.log(cornerstonejs)
|
||||
},
|
||||
methods: {
|
||||
initViewport() {
|
||||
this.element = this.$refs['viewport']
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
if (renderingEngine) {
|
||||
renderingEngine.resize(true, false)
|
||||
}
|
||||
})
|
||||
this.element.oncontextmenu = (e) => e.preventDefault()
|
||||
resizeObserver.observe(this.element)
|
||||
this.element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||
|
||||
this.element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.cornerstoneToolsMouseMove)
|
||||
this.element.addEventListener('mouseleave', () => {
|
||||
this.mousePosition.index = []
|
||||
})
|
||||
// console.log(cornerstonejs,cornerstoneTools)
|
||||
// element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
},
|
||||
stackNewImage(e) {
|
||||
const { detail } = e
|
||||
this.series.SliceIndex = detail.imageIdIndex
|
||||
this.sliderInfo.height = detail.imageIdIndex * 100 / (this.series.ImageIds.length - 1)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
let zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
this.imageInfo.size = `${detail.image.columns}*${detail.image.rows}`
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', detail.imageId)
|
||||
this.imageInfo.location = imagePlaneModule.sliceLocation
|
||||
// this.imageInfo.wwwc = `${Math.round(detail.image.windowWidth)}/${Math.round(detail.image.windowCenter)}`
|
||||
this.getOrientationMarker()
|
||||
},
|
||||
voiModified(e) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const properties = viewport.getProperties()
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
)
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
}
|
||||
},
|
||||
getOrientationMarker() {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const { viewUp, viewPlaneNormal } = viewport.getCamera()
|
||||
|
||||
const viewRight = vec3.create()
|
||||
vec3.cross(viewRight, viewUp, viewPlaneNormal)
|
||||
|
||||
const columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]]
|
||||
const rowCosines = viewRight
|
||||
const rowString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(rowCosines)
|
||||
const columnString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(columnCosines)
|
||||
const oppositeRowString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(rowString)
|
||||
const oppositeColumnString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(columnString)
|
||||
this.markers.top = oppositeColumnString
|
||||
this.markers.right = rowString
|
||||
this.markers.bottom = columnString
|
||||
this.markers.left = oppositeRowString
|
||||
this.orientationMarkers = [oppositeColumnString, rowString, columnString, oppositeRowString]
|
||||
if (this.originalMarkers.length === 0) {
|
||||
this.originalMarkers = [...this.orientationMarkers]
|
||||
}
|
||||
},
|
||||
setMarkers() {
|
||||
let markers = [...this.orientationMarkers]
|
||||
for (const key in this.markers) {
|
||||
let v = markers.shift(0)
|
||||
this.markers[key] = v
|
||||
}
|
||||
},
|
||||
resetOrientationMarkers() {
|
||||
if (this.originalMarkers.length > 0) {
|
||||
console.log(this.originalMarkers)
|
||||
this.orientationMarkers = [...this.originalMarkers]
|
||||
this.setMarkers()
|
||||
}
|
||||
},
|
||||
rotateOrientationMarkers(type) {
|
||||
if (this.orientationMarkers.length > 0) {
|
||||
if (type === 1) {
|
||||
this.resetOrientationMarkers()
|
||||
return
|
||||
}
|
||||
let markers = [...this.orientationMarkers]
|
||||
if (type === 2) {
|
||||
// 垂直翻转
|
||||
this.orientationMarkers[0] = markers[2]
|
||||
this.orientationMarkers[2] = markers[0]
|
||||
} else if (type === 3) {
|
||||
// 水平翻转
|
||||
this.orientationMarkers[1] = markers[3]
|
||||
this.orientationMarkers[3] = markers[1]
|
||||
} else if (type === 4) {
|
||||
// 左转90度
|
||||
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
|
||||
} else if (type === 5) {
|
||||
// 右转90度
|
||||
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
|
||||
}
|
||||
this.setMarkers()
|
||||
}
|
||||
},
|
||||
toggleClipPlay(isPlay, framesPerSecond) {
|
||||
this.playClipState = isPlay
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
if (isPlay) {
|
||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond })
|
||||
} else {
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
}
|
||||
},
|
||||
scrollPage(type) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const currentImageIdIndex = viewport.getCurrentImageIdIndex();
|
||||
const numImages = viewport.getImageIds().length;
|
||||
let newImageIdIndex = null;
|
||||
if (type === 0) {
|
||||
newImageIdIndex = 0
|
||||
} else if (type === -1) {
|
||||
newImageIdIndex = currentImageIdIndex === 0 ? currentImageIdIndex : currentImageIdIndex - 1
|
||||
} else if (type === 1) {
|
||||
newImageIdIndex = currentImageIdIndex === numImages - 1 ? currentImageIdIndex : currentImageIdIndex + 1
|
||||
} else if (type === 99999) {
|
||||
newImageIdIndex = numImages -1
|
||||
}
|
||||
viewport.setImageIdIndex(newImageIdIndex);
|
||||
},
|
||||
setZoom(ratio) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId);
|
||||
const viewport = renderingEngine.getViewport(this.viewportId);
|
||||
|
||||
const zoom = viewport.getZoom();
|
||||
if (ratio > 0) {
|
||||
viewport.setZoom(zoom * 1.05);
|
||||
} else {
|
||||
viewport.setZoom(zoom / 1.05);
|
||||
}
|
||||
viewport.render();
|
||||
},
|
||||
resize(forceFitToWindow) {
|
||||
console.log('resize: ', forceFitToWindow)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId);
|
||||
renderingEngine.resize(true, forceFitToWindow)
|
||||
},
|
||||
async setSeriesInfo(obj){
|
||||
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description) return
|
||||
this.series = {...obj}
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
await viewport.setStack(obj.ImageIds, obj.SliceIndex)
|
||||
cornerstoneTools.utilities.stackPrefetch.enable(viewport.element);
|
||||
viewport.render()
|
||||
},
|
||||
cornerstoneToolsMouseMove(e) {
|
||||
const { currentPoints } = e.detail
|
||||
const worldPoint = currentPoints.world
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const imageData = viewport.getImageData()
|
||||
if (!imageData) return
|
||||
const index = imageData.imageData.worldToIndex(worldPoint)
|
||||
index[0] = Math.floor(index[0])
|
||||
index[1] = Math.floor(index[1])
|
||||
index[2] = Math.floor(index[2])
|
||||
this.mousePosition.index = index
|
||||
},
|
||||
toggleTask(evt, visitTaskNum, i) {
|
||||
this.$emit('activeViewport', this.viewportIndex)
|
||||
const num = visitTaskNum + i
|
||||
if (num >= 0 && num <= this.taskInfo.VisitNum) {
|
||||
this.$emit('toggleTaskByViewport', {series: this.series, visitTaskNum: num})
|
||||
}
|
||||
|
||||
evt.stopImmediatePropagation()
|
||||
evt.stopPropagation()
|
||||
evt.preventDefault()
|
||||
},
|
||||
viewCD(taskId) {
|
||||
this.$emit('previewCD', taskId)
|
||||
},
|
||||
setWwwcIdx(idx) {
|
||||
this.wwwcIdx = idx
|
||||
},
|
||||
clickSlider(e) {
|
||||
const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.height = height
|
||||
let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(sliceIdx)
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseup(e) {
|
||||
this.sliderInfo.isMove = false
|
||||
},
|
||||
sliderMousedown(e) {
|
||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
||||
this.sliderInfo.oldM = e.clientY
|
||||
this.sliderInfo.isMove = true
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
sliderMousemove(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
const delta = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
|
||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
if (delta < 0) return
|
||||
if (delta > boxHeight) return
|
||||
const height = delta * 100 / boxHeight
|
||||
let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
this.sliderInfo.height = height
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(sliceIdx)
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseleave(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
this.sliderInfo.isMove = false
|
||||
},
|
||||
preventDefault(e) {
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.viewport-wrapper {
|
||||
width:100%;
|
||||
height:100%;
|
||||
position: relative;
|
||||
.left-top-text {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
.cd-info {
|
||||
color: #ddd;
|
||||
font-size: 18px;
|
||||
}
|
||||
.subject-info {
|
||||
color:#f44336;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
.top-center-tool {
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
.toggle-visit-container {
|
||||
display: flex;
|
||||
}
|
||||
.arrw_icon{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
.arrow_text{
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding:0 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.right-top-text {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.left-bottom-text {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
bottom: 5px;
|
||||
color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.right-bottom-text {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
.right-slider-box {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
height: calc(100% - 140px);
|
||||
transform: translateY(-50%);
|
||||
top: calc(50% - 30px);
|
||||
width: 10px;
|
||||
background: #333;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
.right-slider-box:after{
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
left: 0;
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
background: #333;
|
||||
}
|
||||
.slider {
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index:10;
|
||||
background: #9e9e9e;
|
||||
cursor: move
|
||||
}
|
||||
.orientation-top {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 30px;
|
||||
color: #f44336;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
.orientation-bottom {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 15px;
|
||||
color: #f44336;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
.orientation-left {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 15px;
|
||||
color: #f44336;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
.orientation-right {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 15px;
|
||||
color: #f44336;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,79 @@
|
|||
<template>
|
||||
<div class="visit-review-container">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
>
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane
|
||||
v-if="taskInfo"
|
||||
:label="$t('trials:reading:tabTitle:review')"
|
||||
name="read"
|
||||
>
|
||||
<read-page />
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane
|
||||
v-if="taskInfo && !taskInfo.IseCRFShowInDicomReading"
|
||||
:label="$t('trials:reading:tabTitle:report')"
|
||||
name="report"
|
||||
>
|
||||
<report-page v-if="activeName === 'report'" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import ReadPage from './ReadPage'
|
||||
import ReportPage from './ReportPage'
|
||||
export default {
|
||||
name: 'VisitReview',
|
||||
components: {
|
||||
ReadPage,
|
||||
ReportPage
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'read',
|
||||
taskInfo: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.visit-review-container {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #000;
|
||||
padding: 5px;
|
||||
::v-deep .el-tabs {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.el-tabs__item {
|
||||
color: #fff;
|
||||
}
|
||||
.el-tabs__item.is-active {
|
||||
color: #428bca;
|
||||
}
|
||||
.el-tabs__item:hover {
|
||||
color: #428bca;
|
||||
}
|
||||
.el-tabs__header {
|
||||
height: 50px;
|
||||
margin:0px;
|
||||
}
|
||||
.el-tabs__content {
|
||||
flex: 1;
|
||||
margin:0px;
|
||||
}
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,193 @@
|
|||
const config = {
|
||||
"standards": [
|
||||
{
|
||||
"type": 1,
|
||||
"name": "RECIST 1.1",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 2,
|
||||
"name": "Lugano 2014",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "iRECIST",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 7,
|
||||
"name": "mRECIST HCC",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 10,
|
||||
"name": "PCWG3",
|
||||
"tools": [
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 17,
|
||||
"name": "PCWG3",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 19,
|
||||
"name": "IVUS定量评估",
|
||||
"tools": []
|
||||
},
|
||||
{
|
||||
"type": 20,
|
||||
"name": "OCT定量评估",
|
||||
"tools": []
|
||||
},
|
||||
{
|
||||
"type": 21,
|
||||
"name": "MRI-PDFF",
|
||||
"tools": [
|
||||
{
|
||||
"name": "圆形测量",
|
||||
"icon": "oval",
|
||||
"toolName": "Probe",
|
||||
"i18nKey": "trials:reading:button:circle"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
const getTools = (criterionType) => {
|
||||
const standard = config.standards.find(s => s.type === criterionType);
|
||||
return standard?.tools || [];
|
||||
};
|
||||
export {config, getTools}
|
|
@ -0,0 +1,113 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="reading-viewer-container">
|
||||
<!-- 访视阅片 -->
|
||||
<visit-review
|
||||
v-if="taskInfo && taskInfo.ReadingCategory=== 1"
|
||||
/>
|
||||
<!-- 临床数据 -->
|
||||
<el-dialog
|
||||
:visible.sync="clinicalDataVisible"
|
||||
:custom-class="isClinicalDataFullscreen?'full-dialog-container':'dialog-container'"
|
||||
:show-close="false"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="isClinicalDataFullscreen"
|
||||
>
|
||||
<span slot="title" class="dialog-footer">
|
||||
<!-- 当前阅片任务存在临床数据,请查看。若已查看,请点击“确认” -->
|
||||
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
|
||||
<div style="position: absolute;right: 20px;top: 10px;">
|
||||
<svg-icon :icon-class="isClinicalDataFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isClinicalDataFullscreen=!isClinicalDataFullscreen" />
|
||||
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="clinicalDataVisible = false" />
|
||||
</div>
|
||||
</span>
|
||||
<div style="height: 100%;margin:0;display: flex;flex-direction: column;">
|
||||
<clinical-data
|
||||
v-if="clinicalDataVisible"
|
||||
style="flex: 1"
|
||||
:trial-id="trialId"
|
||||
:subject-id="taskInfo.SubjectId"
|
||||
:visit-task-id="cdVisitTaskId"
|
||||
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
|
||||
/>
|
||||
<div v-if="!closeCDVisible" style="text-align:right">
|
||||
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import VisitReview from './components/VisitReview'
|
||||
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
||||
export default {
|
||||
name:'Dicoms3d',
|
||||
components: { VisitReview,ClinicalData },
|
||||
data() {
|
||||
return {
|
||||
taskInfo: null,
|
||||
trialId: '',
|
||||
loading: false,
|
||||
clinicalDataVisible: false,
|
||||
isClinicalDataFullscreen: false,
|
||||
closeCDVisible: false,
|
||||
cdVisitTaskId: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getTaskInfo()
|
||||
},
|
||||
methods: {
|
||||
async getTaskInfo() {
|
||||
this.loading = true
|
||||
try {
|
||||
const params = {
|
||||
subjectId: this.$route.query.subjectId,
|
||||
trialId: this.$route.query.trialId,
|
||||
subjectCode: this.$route.query.subjectCode,
|
||||
visitTaskId: this.$route.query.visitTaskId,
|
||||
trialReadingCriterionId: this.$route.query.TrialReadingCriterionId
|
||||
}
|
||||
const res = await getNextTask(params)
|
||||
this.taskInfo = res.Result
|
||||
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
||||
localStorage.setItem('digitPlaces', JSON.stringify(res.Result.DigitPlaces))
|
||||
this.loading = false
|
||||
this.$nextTick(() => {
|
||||
if (this.taskInfo.IsExistsClinicalData && this.taskInfo.IsNeedReadClinicalData && !this.taskInfo.IsReadClinicalData) {
|
||||
this.isClinicalDataFullscreen = false
|
||||
this.clinicalDataVisible = true
|
||||
this.cdVisitTaskId = this.taskInfo.VisitTaskId
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.reading-viewer-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
// ::v-deep .dialog-container{
|
||||
// margin-top: 50px !important;
|
||||
// width:75%;
|
||||
// height:80%;
|
||||
// }
|
||||
// ::v-deep .el-dialog__body{
|
||||
// padding: 10px;
|
||||
// height: calc(100% - 70px);
|
||||
// }
|
||||
// .el-dialog__header{
|
||||
// position: relative;
|
||||
// }
|
||||
// .full-dialog-container{
|
||||
// ::v-deep .is-fullscreen .el-dialog__body{
|
||||
// height: calc(100% - 70px);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
</style>
|
|
@ -295,8 +295,8 @@ export default {
|
|||
async toggleTaskByViewer(visitTaskNum) {
|
||||
const i = this.visitTaskList.findIndex(v => v.VisitTaskNum === visitTaskNum)
|
||||
if (i === -1) return
|
||||
const visistTaskId = this.visitTaskList[i].VisitTaskId
|
||||
this.setActiveTaskVisitId(visistTaskId, true)
|
||||
const visitTaskId = this.visitTaskList[i].VisitTaskId
|
||||
this.setActiveTaskVisitId(visitTaskId, true)
|
||||
},
|
||||
// 设置激活的访视
|
||||
async setActiveTaskVisitId(id, isInitActiveFile = false) {
|
||||
|
|
Loading…
Reference in New Issue