irc_web/src/views/trials/trials-panel/reading/visit-review/components/ReadPage.vue

427 lines
12 KiB
Vue

<template>
<div v-loading="loading" class="read-page-container">
<!-- 检查列表 -->
<div class="left-panel">
<div class="task-container">
<div class="task-info">
<div
v-for="s in visitTaskList"
:key="s.VisitTaskId"
class="task-item"
:class="{'task-item-active': activeTaskVisitId==s.VisitTaskId}"
@click.prevent="toggleTask(s)"
>{{ s.TaskBlindName }}</div>
</div>
</div>
<div class="study-info">
<div
v-for="s in visitTaskList"
v-show="activeTaskVisitId === s.VisitTaskId"
:key="s.VisitTaskId"
style="height:100%;"
>
<study-list
v-if="selectArr.includes(s.VisitTaskId) && s.StudyList.length > 0"
:ref="s.VisitTaskId"
:visit-task-info="s"
@selectFile="selectFile"
/>
</div>
</div>
</div>
<!-- 图像 -->
<div class="middle-panel">
<!-- <image-viewer
ref="imageViewer"
:related-study-info="relatedStudyInfo"
@toggleTaskByViewer="toggleTaskByViewer"
@toggleTask="toggleTask"
@toggleImage="toggleImage"
/> -->
<!-- <pdf-viewer
ref="imageViewer"
:related-study-info="relatedStudyInfo"
@toggleTaskByViewer="toggleTaskByViewer"
@toggleTask="toggleTask"
@toggleImage="toggleImage"
/> -->
<file-viewer
ref="fileViewer"
:related-study-info="relatedStudyInfo"
:psArr="psArr"
@toggleTaskByViewer="toggleTaskByViewer"
@toggleTask="toggleTask"
@toggleImage="toggleImage"
@previewCD="previewCD"
@setPS="setPS"
/>
</div>
<!-- 表单 -->
<div class="right-panel">
<div
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
class="text-info"
>
<h3>
<span
v-if="currentVisitInfo && currentVisitInfo.SubjectCode"
>
{{ currentVisitInfo.SubjectCode }}
</span>
<span
v-if="currentVisitInfo && currentVisitInfo.TaskBlindName"
style="margin-left:5px;"
>
{{ currentVisitInfo.TaskBlindName }}
</span>
</h3>
</div>
<ecrf-list
v-if="currentVisitInfo"
:visit-task-info="currentVisitInfo"
/>
</div>
<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">
<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 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>
</el-dialog>
</div>
</template>
<script>
import { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto } from '@/api/trials'
import StudyList from './StudyList'
// import ImageViewer from './ImageViewer'
// import PdfViewer from './PDFViewer'
import FileViewer from './FileViewer'
import EcrfList from './EcrfList'
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
import { mapGetters } from 'vuex'
export default {
name: 'ReadPage',
components: {
StudyList,
FileViewer,
// ImageViewer,
// PdfViewer,
EcrfList,
ClinicalData
},
data() {
return {
loading: false,
// 当前任务信息
taskInfo: null,
// 当前激活的任务Id
activeTaskVisitId: '',
// 表单数据
formData: {
name: '',
description: ''
},
// 当前任务关联的任务信息
visitTaskList: [],
selectArr: [],
fileType: 'image',
currentStudyInfo: null,
currentVisitInfo: null,
relatedStudyInfo: null,
clinicalDataVisible: false,
isClinicalDataFullscreen: false,
trialId: '',
cdVisitTaskId: '',
psArr: []
}
},
computed: {
...mapGetters(['lastViewportTaskId'])
},
watch: {
lastViewportTaskId: {
immediate: true,
handler(id) {
if (!id) return
const idx = this.visitTaskList.findIndex(i => i.VisitTaskId === id)
if (idx === -1) return
this.currentVisitInfo = this.visitTaskList[idx]
// this.activeTaskVisitId = id
}
}
},
mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.trialId = this.$route.query.trialId
this.getRelatedTask()
},
methods: {
// 获取关联任务信息
async getRelatedTask() {
this.loading = true
try {
const params = {
visitTaskId: this.taskInfo.VisitTaskId
}
const res = await getRelatedVisitTask(params)
this.visitTaskList = res.Result.map((item) => ({
...item,
StudyList: [],
Annotations: []
}))
const idx = res.Result.findIndex(i => i.IsCurrentTask)
if (idx > -1) {
await this.setActiveTaskVisitId(res.Result[idx].VisitTaskId)
this.$nextTick(() => {
this.$refs[res.Result[idx].VisitTaskId][0].setInitActiveFile()
})
}
if (this.taskInfo.IsReadingTaskViewInOrder !== 0 && res.Result.length > 1) {
const i = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
if (i > -1) {
await this.getReadingImageFile(res.Result[i].VisitTaskId, i)
await this.getAnnotations(res.Result[i].VisitTaskId, i)
const studyList = this.visitTaskList[i].StudyList
if (studyList.length > 0) {
const fileInfo = studyList[0].NoneDicomStudyFileList[0]
this.relatedStudyInfo = { fileInfo, visitTaskInfo: this.visitTaskList[i], fileList: studyList[0].NoneDicomStudyFileList, fileIndex: 0, studyId: studyList[0].Id }
if (!this.selectArr.includes(res.Result[i].VisitTaskId)) {
this.selectArr.push(res.Result[i].VisitTaskId)
}
}
}
}
this.loading = false
} catch (e) {
console.log(e)
this.loading = false
}
},
// 获取任务关联的文件信息
getReadingImageFile(visitTaskId, visitTaskIdx) {
return new Promise(async(resolve, reject) => {
this.loading = true
try {
const params = {
subjectId: this.taskInfo.SubjectId,
trialId: this.$route.query.trialId,
visistTaskId: visitTaskId
}
const res = await getReadingImageFile(params)
this.$set(this.visitTaskList[visitTaskIdx], 'StudyList', res.Result)
this.loading = false
resolve()
} catch (e) {
console.log(e)
this.loading = false
reject(e)
}
})
},
// 获取任务关联的标注信息
getAnnotations(visitTaskId, visitTaskIdx) {
return new Promise(async(resolve, reject) => {
this.loading = true
try {
const params = {
visitTaskId: visitTaskId
}
const res = await getNoneDicomMarkListOutDto(params)
let arr = res.Result.NoneDicomMarkList.map(i=>{
if (typeof i.MeasureData === 'string') {
i.MeasureData = JSON.parse(i.MeasureData)
}
if (i.MeasureData.metadata.toolName === 'Length' && this.psArr.findIndex(p=>p.NoneDicomFileId === i.NoneDicomFileId) === -1) {
this.psArr.push({NoneDicomFileId: i.NoneDicomFileId, Path: i.Path, PS: i.MeasureData.data.ps})
}
return i
})
this.$set(this.visitTaskList[visitTaskIdx], 'Annotations', arr)
this.loading = false
resolve()
} catch (e) {
console.log(e)
this.loading = false
reject(e)
}
})
},
setPS(obj) {
let i = this.psArr.findIndex(p=>p.NoneDicomFileId === obj.NoneDicomFileId)
if (i > -1) {
this.psArr[i].PS = obj.PS
} else {
this.psArr.push(obj)
}
},
// 切换任务
toggleTask(taskInfo) {
this.setActiveTaskVisitId(taskInfo.VisitTaskId)
},
// 视图触发任务切换
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)
},
// 设置激活的访视
async setActiveTaskVisitId(id, isInitActiveFile = false) {
if (!id) return
if (!this.selectArr.includes(id)) {
this.selectArr.push(id)
}
const idx = this.visitTaskList.findIndex(i => i.VisitTaskId === id)
if (idx === -1) return
if (this.visitTaskList[idx].StudyList.length === 0) {
await this.getReadingImageFile(id, idx)
await this.getAnnotations(id, idx)
}
this.activeTaskVisitId = id
this.$nextTick(() => {
if (isInitActiveFile) {
this.$refs[id][0].setInitActiveFile()
}
})
},
// 切换图片
toggleImage(obj) {
this.$refs[obj.taskId][0].activeImage(obj)
},
previewCD(taskId) {
this.isClinicalDataFullscreen = false
this.dialogVisible = true
this.cdVisitTaskId = taskId
this.clinicalDataVisible = true
},
selectFile(obj) {
// this.$refs['imageViewer'].setActiveCanvasImages(obj)
this.$refs['fileViewer'].setActiveCanvasImages(obj)
}
}
}
</script>
<style lang="scss" scoped>
.read-page-container {
box-sizing: border-box;
height: 100%;
display: flex;
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.left-panel {
display: flex;
width: 200px;
border: 1px solid #727272;
color: #fff;
::-webkit-scrollbar {
width: 3px;
height: 3px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.task-container {
position: relative;
width: 25px;
overflow-y: auto;
}
.task-info {
position: absolute;
top: 5px;
right: 20px;
transform-origin: right top;
transform: rotate(-90deg);
display: flex;
.task-item {
margin-left: 10px;
white-space: nowrap;
padding: 0px 4px;
border: 1px solid #999999;
border-bottom:none ;
text-align: center;
background-color: #4e4e4e;
color: #d5d5d5;
cursor: pointer;
}
.task-item-active {
background-color: #607d8b;
border: 1px solid #607d8b;
}
}
.study-info {
width: 170px;
border-left: 1px solid #727272;
}
}
.middle-panel {
flex: 1;
border: 1px solid #727272;
margin: 0 5px;
}
.right-panel {
width: 400px;
border: 1px solid #727272;
padding: 0 10px;
overflow-y: auto;
.text-info {
display: flex;
align-items: center;
justify-content: space-between;
color: #ddd;
}
}
::v-deep .dialog-container{
margin-top: 50px !important;
width:75%;
height:80%;
}
::v-deep .el-dialog__body{
padding: 20px 20px 0 20px;
height: calc(100% - 70px);
}
.el-dialog__header{
position: relative;
}
.full-dialog-container{
::v-deep .is-fullscreen .el-dialog__body{
height: calc(100% - 70px);
}
}
}
</style>