非dicom阅片更改
parent
2516be481d
commit
fb1d87e84b
|
@ -49,6 +49,7 @@ const getters = {
|
|||
TotalNeedSignTrialDocCount: state => state.user.TotalNeedSignTrialDocCount,
|
||||
IsFirstSysDocNeedSign: state => state.user.IsFirstSysDocNeedSign,
|
||||
TrialStatusStr: state => state.user.TrialStatusStr,
|
||||
lastViewportTaskId: state => state.noneDicomReview.lastViewportTaskId
|
||||
lastViewportTaskId: state => state.noneDicomReview.lastViewportTaskId,
|
||||
currentTaskState: state => state.noneDicomReview.currentTaskState
|
||||
}
|
||||
export default getters
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const getDefaultState = () => {
|
||||
return {
|
||||
lastViewportTaskId: null
|
||||
lastViewportTaskId: null,
|
||||
currentTaskState: 0
|
||||
}
|
||||
}
|
||||
const state = getDefaultState
|
||||
|
@ -12,6 +13,9 @@ const mutations = {
|
|||
const actions = {
|
||||
setLastViewportTaskId({ state }, id) {
|
||||
state.lastViewportTaskId = id
|
||||
},
|
||||
setCurrentTaskState({ state }, taskState) {
|
||||
state.currentTaskState = taskState
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
import { getTrialReadingQuestion, saveVisitTaskQuestions, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import const_ from '@/const/sign-code'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import FormItem from './FormItem'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
export default {
|
||||
|
@ -89,6 +91,9 @@ export default {
|
|||
taskInfo: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['currentTaskState'])
|
||||
},
|
||||
watch: {
|
||||
'visitTaskInfo.VisitTaskId': {
|
||||
immediate: true,
|
||||
|
@ -100,6 +105,14 @@ export default {
|
|||
this.getQuestionCalculateRelation()
|
||||
this.getQuestions()
|
||||
}
|
||||
},
|
||||
currentTaskState: {
|
||||
immediate: true,
|
||||
handler(state) {
|
||||
if (state === 2) {
|
||||
this.readingTaskState = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
@ -220,7 +233,10 @@ export default {
|
|||
this.$refs['signForm'].btnLoading = false
|
||||
this.signVisible = false
|
||||
this.readingTaskState = 2
|
||||
// window.opener.postMessage('refreshTaskList', window.location)
|
||||
this.taskInfo.ReadingTaskState = 2
|
||||
localStorage.setItem('taskInfo', JSON.stringify(this.taskInfo))
|
||||
store.dispatch('noneDicomReview/setCurrentTaskState', 2)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:noneDicoms:message:msg1'),
|
||||
{
|
||||
|
|
|
@ -0,0 +1,957 @@
|
|||
<template>
|
||||
<div class="none-dicom-viewer">
|
||||
<!-- tools -->
|
||||
<div class="tools-wrapper">
|
||||
<!-- 布局 -->
|
||||
<div class="tool-item" :title="$t('trials:reading:button:layout')">
|
||||
<el-dropdown @command="handleCommand">
|
||||
<span class="el-dropdown-link">
|
||||
<svg-icon icon-class="layout" class="svg-icon" /><i class="el-icon-arrow-down el-icon--right" />
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
|
||||
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
|
||||
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
<!-- 缩放 -->
|
||||
<div
|
||||
:class="['tool-item', activeTool === 'Zoom' ? 'tool-item-active' : '']"
|
||||
:title="$t('trials:reading:button:zoom')"
|
||||
@click.prevent="setToolActive('Zoom')"
|
||||
>
|
||||
<svg-icon icon-class="magnifier" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 移动 -->
|
||||
<div
|
||||
:class="['tool-item', activeTool === 'Pan' ? 'tool-item-active' : '']"
|
||||
:title="$t('trials:reading:button:move')"
|
||||
@click.prevent="setToolActive('Pan')"
|
||||
>
|
||||
<svg-icon icon-class="move" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 旋转 -->
|
||||
<div
|
||||
:class="['tool-item', activeTool === 'PlanarRotate' ? 'tool-item-active' : '']"
|
||||
:title="$t('trials:reading:button:rotate')"
|
||||
@click.prevent="setToolActive('PlanarRotate')"
|
||||
>
|
||||
<svg-icon icon-class="rotate" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 箭头工具 -->
|
||||
<div
|
||||
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'ArrowAnnotate' ? 'tool-item-active' : '']"
|
||||
:title="$t('trials:reading:button:arrowAnnotate')"
|
||||
@click.prevent="setAnnotateToolActive('ArrowAnnotate')"
|
||||
>
|
||||
<svg-icon icon-class="arrow" class="svg-icon" />
|
||||
</div>
|
||||
|
||||
<!-- 自由曲线 -->
|
||||
<div
|
||||
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'PlanarFreehandROI' ? 'tool-item-active' : '']"
|
||||
:title="$t('trials:dicom-show:Eraser')"
|
||||
@click.prevent="setAnnotateToolActive('PlanarFreehandROI')"
|
||||
>
|
||||
<svg-icon icon-class="polygon" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 截图 -->
|
||||
<!-- <div
|
||||
class="tool-item"
|
||||
:title="$t('trials:reading:button:screenShot')"
|
||||
@click.prevent="saveImage"
|
||||
>
|
||||
<svg-icon icon-class="image" class="svg-icon" />
|
||||
</div> -->
|
||||
<!-- 重置 -->
|
||||
<div
|
||||
class="tool-item"
|
||||
:title="$t('trials:reading:button:reset')"
|
||||
@click.prevent="resetViewport"
|
||||
>
|
||||
<svg-icon icon-class="refresh" class="svg-icon" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- viewports -->
|
||||
<div class="viewports-wrapper">
|
||||
<div class="grid-container" :style="gridStyle">
|
||||
<div
|
||||
v-for="(v, index) in viewportInfos"
|
||||
v-show="index < cells.length"
|
||||
:key="index"
|
||||
:style="cellStyle"
|
||||
:class="['grid-cell', index === activeCanvasIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||
@dblclick="toggleFullScreen($event, index)"
|
||||
@click="activeCanvas(index)"
|
||||
@mouseup="sliderMouseup($event, index)"
|
||||
@mousemove="sliderMousemove($event, index)"
|
||||
>
|
||||
<div v-show="v.fileType === 'image/jpeg'" :ref="`canvas-${index}`" class="content">
|
||||
<div class="left-top-text">
|
||||
<div
|
||||
v-if="v.taskInfo.IsExistsClinicalData"
|
||||
class="cd-info"
|
||||
:title="$t('trials:reading:button:clinicalData')"
|
||||
@click.stop="viewCD(v.taskInfo.VisitTaskId)"
|
||||
>
|
||||
<svg-icon icon-class="documentation" class="svg-icon" />
|
||||
</div>
|
||||
<h2
|
||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo && v.taskInfo"
|
||||
class="subject-info"
|
||||
>
|
||||
{{ `${taskInfo.SubjectCode} ${v.taskInfo.TaskBlindName} ` }}
|
||||
</h2>
|
||||
<div v-if="v.currentFileName">{{ v.currentFileName }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="taskInfo && taskInfo.IsReadingTaskViewInOrder === 1 && v.taskInfo"
|
||||
class="top-center-tool"
|
||||
>
|
||||
<div class="toggle-visit-container">
|
||||
<div
|
||||
class="arrw_icon"
|
||||
:style="{ cursor: v.taskInfo.VisitTaskNum !== 0 ? 'pointer' : 'not-allowed', color: v.taskInfo.VisitTaskNum !== 0 ? '#fff': '#6b6b6b' }"
|
||||
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, -1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<i class="el-icon-caret-left" />
|
||||
</div>
|
||||
<div class="arrow_text">
|
||||
{{ v.taskInfo.TaskBlindName }}
|
||||
</div>
|
||||
<div
|
||||
class="arrw_icon"
|
||||
:style="{ cursor: v.taskInfo.VisitTaskNum < taskInfo.VisitNum ? 'pointer' : 'not-allowed', color: v.taskInfo.VisitTaskNum < taskInfo.VisitNum ? '#fff': '#6b6b6b' }"
|
||||
@click.stop.prevent="toggleTask($event, v.taskInfo.VisitTaskNum, 1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<i class="el-icon-caret-right" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div :ref="`sliderBox-${index}`" class="right-slider-box" @click.stop="clickSlider($event, index)">
|
||||
<div :style="{top: v.height + '%'}" class="slider" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event, index)" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="v.fileType === 'application/pdf'" class="content">
|
||||
<iframe v-if="v.currentFilePath" :ref="`iframe-${index}`" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${v.currentFilePath}?index=${index}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { addNoneDicomMark, deleteTrialFileType } from '@/api/trials'
|
||||
import {
|
||||
RenderingEngine,
|
||||
Enums,
|
||||
imageLoader,
|
||||
metaData,
|
||||
getRenderingEngine,
|
||||
eventTarget
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
import initLibraries from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/initLibraries'
|
||||
import hardcodedMetaDataProvider from './../js/hardcodedMetaDataProvider'
|
||||
import registerWebImageLoader from './../js/registerWebImageLoader'
|
||||
import { mapGetters } from 'vuex'
|
||||
import store from '@/store'
|
||||
const { ViewportType } = Enums
|
||||
const renderingEngineId = 'myRenderingEngine'
|
||||
const {
|
||||
ToolGroupManager,
|
||||
Enums: csToolsEnums,
|
||||
StackScrollTool,
|
||||
PanTool,
|
||||
ZoomTool,
|
||||
PlanarRotateTool,
|
||||
ArrowAnnotateTool,
|
||||
PlanarFreehandROITool,
|
||||
EraserTool
|
||||
} = cornerstoneTools
|
||||
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||
export default {
|
||||
name: 'ImageViewer',
|
||||
props: {
|
||||
relatedStudyInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
rows: 1,
|
||||
cols: 1,
|
||||
fullScreenIndex: null,
|
||||
imageIds: [],
|
||||
activeCanvasIndex: 0,
|
||||
activeCanvasFileType: '',
|
||||
layout: '1*2',
|
||||
cellsMax: 4,
|
||||
viewportInfos: [],
|
||||
taskInfo: null,
|
||||
activeTool: '',
|
||||
readingTaskState: 2,
|
||||
renderHistoryAnnotationTaskIds: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
gridStyle() {
|
||||
return {
|
||||
display: 'grid',
|
||||
gridTemplateRows: `repeat(${this.rows}, 1fr)`,
|
||||
gridTemplateColumns: `repeat(${this.cols}, 1fr)`,
|
||||
height: '100%',
|
||||
width: '100%'
|
||||
}
|
||||
},
|
||||
cellStyle() {
|
||||
return {
|
||||
border: '1px dashed #ccc',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
},
|
||||
cells() {
|
||||
return Array(this.rows * this.cols).fill(0)
|
||||
},
|
||||
...mapGetters(['lastViewportTaskId', 'currentTaskState'])
|
||||
},
|
||||
watch: {
|
||||
relatedStudyInfo: {
|
||||
immediate: true,
|
||||
handler(obj) {
|
||||
if (!obj || Object.keys(obj).length === 0) return
|
||||
this.updateViewportInfos(0, obj)
|
||||
}
|
||||
},
|
||||
currentTaskState: {
|
||||
immediate: true,
|
||||
handler(state) {
|
||||
if (state === 2) {
|
||||
this.readingTaskState = 2
|
||||
// 设置标记锁定
|
||||
const annotations = cornerstoneTools.annotation.state.getAllAnnotations()
|
||||
annotations.map(annotation => {
|
||||
cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID)
|
||||
})
|
||||
this.setToolsPassive()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
this.readingTaskState = this.taskInfo.ReadingTaskState
|
||||
if (this.taskInfo.VisitNum > 0 && this.taskInfo.IsReadingTaskViewInOrder !== 0) {
|
||||
this.rows = 1
|
||||
this.cols = 2
|
||||
this.activeCanvasIndex = 1
|
||||
}
|
||||
this.viewportInfos = Array.from({ length: this.cellsMax }, (_, index) => ({
|
||||
index: index,
|
||||
taskInfo: '',
|
||||
studyId: '',
|
||||
currentImageIdIndex: 0,
|
||||
viewportId: `canvas-${index}`,
|
||||
fileType: '',
|
||||
currentFileName: '',
|
||||
currentFilePath: '',
|
||||
imageIds: [],
|
||||
oldB: null,
|
||||
oldM: null,
|
||||
isMove: false,
|
||||
height: 0
|
||||
}))
|
||||
this.initLoader()
|
||||
window.addEventListener('message', this.handleIframeMessage)
|
||||
console.log(cornerstoneTools)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('message', this.handleIframeMessage)
|
||||
},
|
||||
methods: {
|
||||
// 初始化加载器
|
||||
async initLoader() {
|
||||
registerWebImageLoader(imageLoader)
|
||||
await initLibraries()
|
||||
|
||||
let renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
if (!renderingEngine) {
|
||||
renderingEngine = new RenderingEngine(renderingEngineId)
|
||||
}
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
if (renderingEngine) {
|
||||
renderingEngine.resize(true, false)
|
||||
}
|
||||
})
|
||||
const element1 = this.$refs['canvas-0'][0]
|
||||
const element2 = this.$refs['canvas-1'][0]
|
||||
const element3 = this.$refs['canvas-2'][0]
|
||||
const element4 = this.$refs['canvas-3'][0]
|
||||
const elements = [
|
||||
element1,
|
||||
element2,
|
||||
element3,
|
||||
element4
|
||||
]
|
||||
elements.forEach((element, i) => {
|
||||
element.oncontextmenu = (e) => e.preventDefault()
|
||||
resizeObserver.observe(element)
|
||||
element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
})
|
||||
const viewportInputArray = [
|
||||
{
|
||||
viewportId: 'canvas-0',
|
||||
type: ViewportType.STACK,
|
||||
element: element1
|
||||
},
|
||||
{
|
||||
viewportId: 'canvas-1',
|
||||
type: ViewportType.STACK,
|
||||
element: element2
|
||||
},
|
||||
{
|
||||
viewportId: 'canvas-2',
|
||||
type: ViewportType.STACK,
|
||||
element: element3
|
||||
},
|
||||
{
|
||||
viewportId: 'canvas-3',
|
||||
type: ViewportType.STACK,
|
||||
element: element4
|
||||
}
|
||||
]
|
||||
const viewportIds = ['canvas-0', 'canvas-1', 'canvas-2', 'canvas-3']
|
||||
renderingEngine.setViewports(viewportInputArray)
|
||||
this.addAnnotationListeners()
|
||||
cornerstoneTools.addTool(StackScrollTool)
|
||||
cornerstoneTools.addTool(PanTool)
|
||||
cornerstoneTools.addTool(ZoomTool)
|
||||
cornerstoneTools.addTool(PlanarRotateTool)
|
||||
cornerstoneTools.addTool(ArrowAnnotateTool)
|
||||
cornerstoneTools.addTool(PlanarFreehandROITool)
|
||||
cornerstoneTools.addTool(EraserTool)
|
||||
|
||||
viewportIds.forEach((viewportId, i) => {
|
||||
const toolGroupId = `canvas-${i}`
|
||||
const toolGroup = ToolGroupManager.createToolGroup(toolGroupId)
|
||||
toolGroup.addViewport(viewportId, renderingEngineId)
|
||||
toolGroup.addTool(StackScrollTool.toolName)
|
||||
toolGroup.addTool(PanTool.toolName)
|
||||
toolGroup.addTool(ZoomTool.toolName)
|
||||
toolGroup.addTool(PlanarRotateTool.toolName)
|
||||
toolGroup.addTool(ArrowAnnotateTool.toolName, {
|
||||
arrowHeadStyle: 'standard',
|
||||
changeTextCallback: async(data, eventData, doneChangingTextCallback) => {
|
||||
return doneChangingTextCallback(await this.customPrompt())
|
||||
},
|
||||
getTextCallback: async(doneChangingTextCallback) => {
|
||||
return doneChangingTextCallback(await this.customPrompt())
|
||||
}
|
||||
})
|
||||
toolGroup.addTool(PlanarFreehandROITool.toolName)
|
||||
toolGroup.addTool(EraserTool.toolName)
|
||||
toolGroup.setToolActive(StackScrollTool.toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||
})
|
||||
toolGroup.setToolPassive(PanTool.toolName)
|
||||
toolGroup.setToolPassive(ZoomTool.toolName)
|
||||
toolGroup.setToolPassive(PlanarRotateTool.toolName)
|
||||
if (this.readingTaskState < 2) {
|
||||
toolGroup.setToolPassive(ArrowAnnotateTool.toolName)
|
||||
toolGroup.setToolPassive(PlanarFreehandROITool.toolName)
|
||||
} else {
|
||||
toolGroup.setToolEnabled(ArrowAnnotateTool.toolName)
|
||||
toolGroup.setToolEnabled(PlanarFreehandROITool.toolName)
|
||||
}
|
||||
toolGroup.setToolPassive(EraserTool.toolName)
|
||||
})
|
||||
},
|
||||
|
||||
// 加载图片回调
|
||||
stackNewImage(e) {
|
||||
const { detail } = e
|
||||
const i = this.viewportInfos.findIndex(i => i.viewportId === detail.viewportId)
|
||||
if (i === -1) return
|
||||
this.viewportInfos[i].currentImageIdIndex = detail.imageIdIndex
|
||||
const obj = this.viewportInfos[i].fileList[detail.imageIdIndex]
|
||||
if (!obj) return
|
||||
this.viewportInfos[i].currentFileName = obj.FileName
|
||||
this.viewportInfos[i].height = (this.viewportInfos[i].currentImageIdIndex) * 100 / (this.viewportInfos[i].imageIds.length - 1)
|
||||
const path = detail.imageId.split(`web:${this.OSSclientConfig.basePath}`)[1]
|
||||
this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, path: path })
|
||||
this.renderHistoryAnnotations(this.viewportInfos[i].taskInfo)
|
||||
},
|
||||
renderHistoryAnnotations(obj) {
|
||||
if (this.renderHistoryAnnotationTaskIds.includes(obj.VisitTaskId)) return
|
||||
this.renderHistoryAnnotationTaskIds.push(obj.VisitTaskId)
|
||||
const arr = []
|
||||
obj.Annotations.map(i => {
|
||||
if (typeof i.MeasureData === 'string') {
|
||||
const annotation = JSON.parse(i.MeasureData)
|
||||
annotation.annotationId = i.Id
|
||||
arr.push(annotation)
|
||||
cornerstoneTools.annotation.state.addAnnotation(annotation)
|
||||
if (obj.ReadingTaskState === 2) {
|
||||
cornerstoneTools.annotation.locking.setAnnotationLocked(annotation.annotationUID)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 渲染图片
|
||||
async renderImage(imageIds, canvasIndex, sliceIndex) {
|
||||
metaData.addProvider((type, imageId) => hardcodedMetaDataProvider(type, imageId, imageIds), 10000)
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(`canvas-${canvasIndex}`)
|
||||
await viewport.setStack(imageIds)
|
||||
viewport.setImageIdIndex(sliceIndex)
|
||||
viewport.render()
|
||||
// this.updateViewportInfos()
|
||||
},
|
||||
setActiveCanvasImages(obj) {
|
||||
console.log('setActiveCanvasImages')
|
||||
if (!obj || Object.keys(obj).length === 0) return
|
||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||
if (i === -1) return
|
||||
if (obj.studyId === this.viewportInfos[i].studyId && this.viewportInfos[i].fileType === 'image/jpeg' && obj.fileInfo.FileType === 'image/jpeg') {
|
||||
const fileIndex = this.viewportInfos[i].fileList.findIndex(i => i.Path === obj.fileInfo.Path)
|
||||
this.sliceIndex(fileIndex)
|
||||
} else {
|
||||
this.updateViewportInfos(this.activeCanvasIndex, obj)
|
||||
}
|
||||
if (this.activeCanvasIndex === this.cells.length - 1) {
|
||||
store.dispatch('noneDicomReview/setLastViewportTaskId', obj.visitTaskInfo.VisitTaskId)
|
||||
}
|
||||
},
|
||||
// 激活视图
|
||||
activeCanvas(index) {
|
||||
if (this.activeCanvasIndex === index) return
|
||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||
if (i === -1) return
|
||||
this.activeCanvasIndex = index
|
||||
if (index === this.cells.length - 1) {
|
||||
store.dispatch('noneDicomReview/setLastViewportTaskId', this.viewportInfos[i].taskInfo.VisitTaskId)
|
||||
}
|
||||
this.$emit('toggleTask', this.viewportInfos[i].taskInfo)
|
||||
this.setToolsPassive()
|
||||
},
|
||||
// 更新视图信息
|
||||
updateViewportInfos(index, obj) {
|
||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||
if (i === -1) return
|
||||
|
||||
this.viewportInfos[i].taskInfo = obj.visitTaskInfo
|
||||
|
||||
this.viewportInfos[i].currentFileName = obj.fileInfo.FileName
|
||||
this.viewportInfos[i].studyId = obj.studyId
|
||||
this.viewportInfos[i].fileType = obj.fileInfo.FileType
|
||||
if (obj.fileInfo.FileType === 'image/jpeg') {
|
||||
const arr = obj.fileList.filter(i => i.FileType === obj.fileInfo.FileType)
|
||||
this.viewportInfos[i].fileList = arr
|
||||
const fileIndex = this.viewportInfos[i].fileList.findIndex(i => i.Path === obj.fileInfo.Path)
|
||||
this.viewportInfos[i].currentImageIdIndex = fileIndex
|
||||
const imageIds = []
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
const path = arr[i].Path
|
||||
imageIds.push(`web:${this.OSSclientConfig.basePath}${path}`)
|
||||
}
|
||||
this.viewportInfos[i].imageIds = imageIds
|
||||
if (imageIds.length > 0) {
|
||||
this.renderImage(imageIds, index, fileIndex)
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
if (renderingEngine) {
|
||||
renderingEngine.resize(true, false)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.viewportInfos[i].currentFilePath = obj.fileInfo.Path
|
||||
}
|
||||
},
|
||||
// 切换图片
|
||||
sliceIndex(index) {
|
||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||
if (i === -1) return
|
||||
if (index < 0 || index >= this.viewportInfos[i].imageIds.length) return
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportInfos[i].viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(index)
|
||||
viewport.render()
|
||||
},
|
||||
// 更改视图布局
|
||||
handleCommand(command) {
|
||||
this.fullScreenIndex = null
|
||||
this.layout = command
|
||||
this.rows = parseInt(command.split('*')[0])
|
||||
this.cols = parseInt(command.split('*')[1])
|
||||
// 有序阅片 1*1 显示当前图片 1*2 显示基线*当前图片 2*2 显示当前图片
|
||||
// const obj = this.viewportInfos.find(i => i.index === this.activeCanvasIndex)
|
||||
// if (obj && this.rows === 1 && this.cols === 1) {
|
||||
// this.viewportInfos = this.viewportInfos.map((v, i) => {
|
||||
// if (i === 0) {
|
||||
// v.taskInfo = obj.taskInfo
|
||||
// v.currentImageIdIndex === obj.currentImageIdIndex
|
||||
// v.currentFileName === obj.currentFileName
|
||||
// v.imageIds === obj.imageIds
|
||||
// } else {
|
||||
// v.taskInfo = ''
|
||||
// v.currentImageIdIndex === 0
|
||||
// v.currentFileName === ''
|
||||
// v.imageIds === []
|
||||
// }
|
||||
// return v
|
||||
// })
|
||||
// this.activeCanvasIndex = 0
|
||||
// } else if (obj && this.rows === 1 && this.cols === 2 && this.taskInfo.IsReadingTaskViewInOrder === 1) {
|
||||
// this.viewportInfos = this.viewportInfos.map((v, i) => {
|
||||
// if (i === 0) {
|
||||
// v.taskInfo = this.relatedStudyInfo.visitTaskInfo
|
||||
// v.currentImageIdIndex === this.relatedStudyInfo.fileIndex
|
||||
// v.currentFileName === this.relatedStudyInfo.fileInfo.FileName
|
||||
// const imageIds = []
|
||||
// for (let i = 0; i < this.relatedStudyInfo.fileList.length; i++) {
|
||||
// const path = this.relatedStudyInfo.fileList[i].Path
|
||||
// imageIds.push(`web:${this.OSSclientConfig.basePath}${path}`)
|
||||
// }
|
||||
// v.imageIds === imageIds
|
||||
// } else if (i === 1) {
|
||||
// v.taskInfo = obj.taskInfo
|
||||
// v.currentImageIdIndex === obj.currentImageIdIndex
|
||||
// v.currentFileName === obj.currentFileName
|
||||
// v.imageIds === obj.imageIds
|
||||
// } else {
|
||||
// v.taskInfo = ''
|
||||
// v.currentImageIdIndex === 0
|
||||
// v.currentFileName === ''
|
||||
// v.imageIds === []
|
||||
// }
|
||||
// return v
|
||||
// })
|
||||
// this.activeCanvasIndex = 1
|
||||
// } else if (obj && this.rows === 1 && this.cols === 2 && this.taskInfo.IsReadingTaskViewInOrder !== 1) {
|
||||
// this.viewportInfos = this.viewportInfos.map((v, i) => {
|
||||
// if (i === 0 || i === 1) {
|
||||
// v.taskInfo = obj.taskInfo
|
||||
// v.currentImageIdIndex === obj.currentImageIdIndex
|
||||
// v.currentFileName === obj.currentFileName
|
||||
// v.imageIds === obj.imageIds
|
||||
// } else {
|
||||
// v.taskInfo = ''
|
||||
// v.currentImageIdIndex === 0
|
||||
// v.currentFileName === ''
|
||||
// v.imageIds === []
|
||||
// }
|
||||
// return v
|
||||
// })
|
||||
// this.activeCanvasIndex = 1
|
||||
// } else if (obj && (this.rows === 2 && this.cols === 2)) {
|
||||
// this.viewportInfos = this.viewportInfos.map(v => {
|
||||
// v.taskInfo = obj.taskInfo
|
||||
// v.currentImageIdIndex === obj.currentImageIdIndex
|
||||
// v.currentFileName === obj.currentFileName
|
||||
// v.imageIds === obj.imageIds
|
||||
// return v
|
||||
// })
|
||||
// this.activeCanvasIndex = 3
|
||||
// }
|
||||
// this.$nextTick(() => {
|
||||
// this.viewportInfos.forEach(v => {
|
||||
// if (v.imageIds.length > 0) {
|
||||
// this.renderImage(v.imageIds, v.index, v.currentImageIdIndex)
|
||||
// }
|
||||
// })
|
||||
// })
|
||||
},
|
||||
// 切换全屏
|
||||
toggleFullScreen(e, index) {
|
||||
this.fullScreenIndex = this.fullScreenIndex === index ? null : index
|
||||
this.activeCanvasIndex = index
|
||||
},
|
||||
// 切换任务
|
||||
toggleTask(evt, visitTaskNum, i) {
|
||||
const num = visitTaskNum + i
|
||||
if (num >= 0 && num <= this.taskInfo.VisitNum) {
|
||||
this.$emit('toggleTaskByViewer', num)
|
||||
}
|
||||
|
||||
evt.stopImmediatePropagation()
|
||||
evt.stopPropagation()
|
||||
evt.preventDefault()
|
||||
},
|
||||
// 激活工具
|
||||
setToolActive(toolName) {
|
||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||
if (i === -1) return
|
||||
const toolGroupId = `canvas-${this.viewportInfos[i].index}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
if (this.activeTool === toolName) {
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
this.activeTool = ''
|
||||
} else {
|
||||
if (this.activeTool) {
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
}
|
||||
toolGroup.setToolActive(toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||
})
|
||||
this.activeTool = toolName
|
||||
}
|
||||
},
|
||||
// 激活标注工具
|
||||
setAnnotateToolActive(toolName) {
|
||||
if (this.readingTaskState === 2) return
|
||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||
if (i === -1) return
|
||||
if (this.viewportInfos[i].taskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||
const toolGroupId = `canvas-${this.viewportInfos[i].index}`
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
if (this.activeTool === toolName) {
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
this.activeTool = ''
|
||||
} else {
|
||||
if (this.activeTool) {
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
}
|
||||
toolGroup.setToolActive(toolName, {
|
||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||
})
|
||||
this.activeTool = toolName
|
||||
}
|
||||
}
|
||||
},
|
||||
setToolsPassive() {
|
||||
if (!this.activeTool) return
|
||||
const toolGroupIds = ['canvas-0', 'canvas-1', 'canvas-2', 'canvas-3']
|
||||
toolGroupIds.forEach(toolGroupId => {
|
||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
toolGroup.setToolPassive(this.activeTool)
|
||||
})
|
||||
this.activeTool = ''
|
||||
},
|
||||
addAnnotationListeners() {
|
||||
const debouncedCallback = this.debounce((evt) => {
|
||||
this.annotationModifiedListener(evt)
|
||||
}, 100)
|
||||
eventTarget.addEventListener(
|
||||
toolsEvents.ANNOTATION_MODIFIED,
|
||||
(evt) => {
|
||||
debouncedCallback(evt)
|
||||
}
|
||||
)
|
||||
eventTarget.addEventListener(
|
||||
toolsEvents.ANNOTATION_COMPLETED,
|
||||
this.annotationCompletedListener
|
||||
)
|
||||
eventTarget.addEventListener(
|
||||
toolsEvents.ANNOTATION_REMOVED,
|
||||
this.annotationRemovedListener
|
||||
)
|
||||
},
|
||||
async annotationRemovedListener(e) {
|
||||
if (this.readingTaskState === 2) return
|
||||
const { annotation } = e.detail
|
||||
if (!annotation) return
|
||||
if (!annotation.annotationId) return
|
||||
await deleteTrialFileType(annotation.annotationId)
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(`canvas-${this.activeCanvasIndex}`)
|
||||
viewport.render()
|
||||
// 删除成功
|
||||
},
|
||||
async annotationModifiedListener(e) {
|
||||
console.log('Modified')
|
||||
if (this.readingTaskState === 2) return
|
||||
const { annotation } = e.detail
|
||||
if (!annotation) return
|
||||
if (!annotation.annotationId) return
|
||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||
if (i === -1) return
|
||||
if (this.viewportInfos[i].taskInfo.VisitTaskId !== this.taskInfo.VisitTaskId) return
|
||||
const imageId = annotation.metadata.referencedImageId
|
||||
const path = imageId.split(`web:${this.OSSclientConfig.basePath}`)[1]
|
||||
const fileList = this.viewportInfos[i].fileList
|
||||
const fileIndex = fileList.findIndex(f => f.Path === path)
|
||||
if (fileIndex === -1) return
|
||||
const params = {
|
||||
id: annotation.annotationId,
|
||||
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
|
||||
studyId: this.viewportInfos[i].studyId,
|
||||
noneDicomFileId: fileList[fileIndex].Id,
|
||||
path: fileList[fileIndex].Path,
|
||||
measureData: JSON.stringify(annotation)
|
||||
}
|
||||
await addNoneDicomMark(params)
|
||||
// 保存成功
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
},
|
||||
async annotationCompletedListener(e) {
|
||||
console.log('Completed')
|
||||
if (this.readingTaskState === 2) return
|
||||
const { annotation } = e.detail
|
||||
if (!annotation) return
|
||||
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
|
||||
if (i === -1) return
|
||||
if (this.viewportInfos[i].taskInfo.VisitTaskId !== this.taskInfo.VisitTaskId) return
|
||||
const imageId = annotation.metadata.referencedImageId
|
||||
const path = imageId.split(`web:${this.OSSclientConfig.basePath}`)[1]
|
||||
const fileList = this.viewportInfos[i].fileList
|
||||
const fileIndex = fileList.findIndex(f => f.Path === path)
|
||||
if (fileIndex === -1) return
|
||||
const params = {
|
||||
id: '',
|
||||
visitTaskId: this.viewportInfos[i].taskInfo.VisitTaskId,
|
||||
studyId: this.viewportInfos[i].studyId,
|
||||
noneDicomFileId: fileList[fileIndex].Id,
|
||||
path: fileList[fileIndex].Path,
|
||||
measureData: JSON.stringify(annotation)
|
||||
}
|
||||
const res = await addNoneDicomMark(params)
|
||||
annotation.annotationId = res.Result
|
||||
// 保存成功
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
},
|
||||
debounce(callback, delay) {
|
||||
let timerId
|
||||
return function() {
|
||||
clearTimeout(timerId)
|
||||
timerId = setTimeout(() => {
|
||||
callback.apply(this, arguments)
|
||||
}, delay)
|
||||
}
|
||||
},
|
||||
// 重置视图
|
||||
resetViewport() {
|
||||
this.setToolsPassive()
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewportId = `canvas-${this.activeCanvasIndex}`
|
||||
const viewport = (renderingEngine.getViewport(viewportId))
|
||||
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||
renderingEngine.render()
|
||||
},
|
||||
// 箭头工具输入标记名称自定义弹窗
|
||||
async customPrompt() {
|
||||
try {
|
||||
const { value } = await this.$prompt('请输入标记名称')
|
||||
return value
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
},
|
||||
// 滚动条
|
||||
clickSlider(e, index) {
|
||||
const height = e.offsetY * 100 / this.$refs[`sliderBox-${index}`][0].clientHeight
|
||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||
if (i === -1) return
|
||||
this.viewportInfos[i].height = height
|
||||
let sliceIdx = Math.trunc(this.viewportInfos[i].imageIds.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.viewportInfos[i].imageIds.length ? this.viewportInfos[i].imageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportInfos[i].viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(sliceIdx)
|
||||
viewport.render()
|
||||
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
|
||||
},
|
||||
sliderMouseup(e, index) {
|
||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||
if (i === -1 && this.viewportInfos[i].fileType !== 'image/jpeg') return
|
||||
this.viewportInfos[i].isMove = false
|
||||
},
|
||||
sliderMousemove(e, index) {
|
||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||
if (i === -1 && this.viewportInfos[i].fileType !== 'image/jpeg') return
|
||||
if (!this.viewportInfos[i].isMove) return
|
||||
const delta = this.viewportInfos[i].oldB - (this.viewportInfos[i].oldM - e.clientY)
|
||||
const boxHeight = this.$refs[`sliderBox-${index}`][0].clientHeight
|
||||
if (delta < 0) return
|
||||
if (delta > boxHeight) return
|
||||
const height = delta * 100 / boxHeight
|
||||
let sliceIdx = Math.trunc(this.viewportInfos[i].imageIds.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.viewportInfos[i].imageIds.length ? this.viewportInfos[i].imageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
this.viewportInfos[i].height = height
|
||||
if (this.viewportInfos[i].currentImageIdIndex !== i) {
|
||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportInfos[i].viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(sliceIdx)
|
||||
viewport.render()
|
||||
// this.$emit('toggleImage', { taskId: this.viewportInfos[i].taskInfo.VisitTaskId, studyId: this.viewportInfos[i].studyId, imageIndex: sliceIdx })
|
||||
}
|
||||
},
|
||||
sliderMousedown(e, index) {
|
||||
const i = this.viewportInfos.findIndex(i => i.index === index)
|
||||
if (i === -1) return
|
||||
const boxHeight = this.$refs[`sliderBox-${index}`][0].clientHeight
|
||||
this.viewportInfos[i].oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
||||
this.viewportInfos[i].oldM = e.clientY
|
||||
this.viewportInfos[i].isMove = true
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
handleIframeMessage(event) {
|
||||
if (event.data.type === 'pdf-clicked') {
|
||||
const baseUrl = event.data.data.baseUrl
|
||||
const urlParams = new URL(baseUrl)
|
||||
const index = parseInt(urlParams.search.split('=')[1])
|
||||
this.activeCanvas(index)
|
||||
}
|
||||
},
|
||||
preventDefault(e) {
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
// 查看临床数据
|
||||
viewCD(id) {
|
||||
this.$emit('previewCD', id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.none-dicom-viewer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width:100%;
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
.tools-wrapper {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #727272;
|
||||
color: #ddd;
|
||||
.tool-item {
|
||||
padding: 5px;
|
||||
margin: 0 5px;
|
||||
border: 1px solid #333;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.tool-item-active {
|
||||
background-color: #607d8b;
|
||||
}
|
||||
.tool-disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
.viewports-wrapper {
|
||||
flex: 1;
|
||||
.grid-container {
|
||||
display: grid;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.grid-cell {
|
||||
border: 1px dashed #ccc;;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.cell_active {
|
||||
border-color: #fafa00!important;
|
||||
}
|
||||
.cell-full-screen {
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 1 / -1;
|
||||
}
|
||||
|
||||
.content {
|
||||
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;
|
||||
cursor: pointer;
|
||||
}
|
||||
.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-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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -31,7 +31,7 @@
|
|||
<div :ref="`canvas-${index}`" class="content">
|
||||
|
||||
<div style="width: 100%; height: 100%; padding: 1px;">
|
||||
<iframe v-if="v.currentFilePath" :ref="`iframe-${index}`" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${v.currentFilePath}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous"/>
|
||||
<iframe v-if="v.currentFilePath" :ref="`iframe-${index}`" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${v.currentFilePath}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<!-- <div class="left-top-text">
|
||||
<div
|
||||
v-if="v.taskInfo.IsExistsClinicalData"
|
||||
|
@ -123,15 +123,15 @@ export default {
|
|||
currentFilePath: ''
|
||||
}))
|
||||
// this.addIframeEventListener()
|
||||
window.addEventListener('message', this.handleIframeMessage);
|
||||
window.addEventListener('message', this.handleIframeMessage)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('message', this.handleIframeMessage);
|
||||
window.removeEventListener('message', this.handleIframeMessage)
|
||||
},
|
||||
methods: {
|
||||
handleIframeMessage(event) {
|
||||
if (event.data.type === 'pdf-clicked') {
|
||||
let baseUrl = event.data.data.baseUrl
|
||||
const baseUrl = event.data.data.baseUrl
|
||||
const i = this.viewportInfos.findIndex(i => baseUrl.includes(i.currentFilePath))
|
||||
if (i === -1) return
|
||||
this.activeCanvas(this.viewportInfos[i].index)
|
||||
|
|
|
@ -34,13 +34,13 @@
|
|||
|
||||
<!-- 图像 -->
|
||||
<div class="middle-panel">
|
||||
<image-viewer
|
||||
<!-- <image-viewer
|
||||
ref="imageViewer"
|
||||
:related-study-info="relatedStudyInfo"
|
||||
@toggleTaskByViewer="toggleTaskByViewer"
|
||||
@toggleTask="toggleTask"
|
||||
@toggleImage="toggleImage"
|
||||
/>
|
||||
/> -->
|
||||
<!-- <pdf-viewer
|
||||
ref="imageViewer"
|
||||
:related-study-info="relatedStudyInfo"
|
||||
|
@ -48,6 +48,14 @@
|
|||
@toggleTask="toggleTask"
|
||||
@toggleImage="toggleImage"
|
||||
/> -->
|
||||
<file-viewer
|
||||
ref="fileViewer"
|
||||
:related-study-info="relatedStudyInfo"
|
||||
@toggleTaskByViewer="toggleTaskByViewer"
|
||||
@toggleTask="toggleTask"
|
||||
@toggleImage="toggleImage"
|
||||
@previewCD="previewCD"
|
||||
/>
|
||||
</div>
|
||||
<!-- 表单 -->
|
||||
<div class="right-panel">
|
||||
|
@ -74,23 +82,58 @@
|
|||
: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">
|
||||
<!-- 当前阅片任务存在临床数据,请查看。若已查看,请点击“确认” -->
|
||||
<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 { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto } from '@/api/trials'
|
||||
import { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto, readClinicalData } from '@/api/trials'
|
||||
import StudyList from './StudyList'
|
||||
import ImageViewer from './ImageViewer'
|
||||
import PdfViewer from './PDFViewer'
|
||||
// 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,
|
||||
ImageViewer,
|
||||
PdfViewer,
|
||||
EcrfList
|
||||
FileViewer,
|
||||
// ImageViewer,
|
||||
// PdfViewer,
|
||||
EcrfList,
|
||||
ClinicalData
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -110,7 +153,12 @@ export default {
|
|||
fileType: 'image',
|
||||
currentStudyInfo: null,
|
||||
currentVisitInfo: null,
|
||||
relatedStudyInfo: null
|
||||
relatedStudyInfo: null,
|
||||
clinicalDataVisible: false,
|
||||
isClinicalDataFullscreen: false,
|
||||
closeCDVisible: false,
|
||||
trialId: '',
|
||||
cdVisitTaskId: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -131,7 +179,15 @@ export default {
|
|||
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.getRelatedTask()
|
||||
this.$nextTick(() => {
|
||||
if (this.taskInfo.IsExistsClinicalData && this.taskInfo.IsNeedReadClinicalData && !this.taskInfo.IsReadClinicalData) {
|
||||
this.isClinicalDataFullscreen = false
|
||||
this.clinicalDataVisible = true
|
||||
this.cdVisitTaskId = this.taskInfo.VisitTaskId
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
// 获取关联任务信息
|
||||
|
@ -314,8 +370,29 @@ export default {
|
|||
toggleImage(obj) {
|
||||
this.$refs[obj.taskId][0].activeImage(obj)
|
||||
},
|
||||
async handleConfirmCD() {
|
||||
this.loading = true
|
||||
var visitTaskId = this.taskInfo.VisitTaskId
|
||||
try {
|
||||
await readClinicalData({ visitTaskId })
|
||||
this.loading = false
|
||||
this.clinicalDataVisible = false
|
||||
this.closeCDVisible = true
|
||||
// this.isReadClinicalData = true
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
previewCD(taskId) {
|
||||
this.closeCDVisible = true
|
||||
this.isClinicalDataFullscreen = false
|
||||
this.dialogVisible = true
|
||||
this.cdVisitTaskId = taskId
|
||||
this.clinicalDataVisible = true
|
||||
},
|
||||
selectFile(obj) {
|
||||
this.$refs['imageViewer'].setActiveCanvasImages(obj)
|
||||
// this.$refs['imageViewer'].setActiveCanvasImages(obj)
|
||||
this.$refs['fileViewer'].setActiveCanvasImages(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,6 +473,23 @@ export default {
|
|||
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>
|
||||
|
|
|
@ -611,7 +611,9 @@ export default {
|
|||
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
|
||||
this.taskInfo.ReadingTaskState = 2
|
||||
localStorage.setItem('taskInfo', JSON.stringify(this.taskInfo))
|
||||
store.dispatch('noneDicomReview/setCurrentTaskState', 2)
|
||||
// DicomEvent.$emit('setReadingState', 2)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
|
||||
|
|
|
@ -107,7 +107,7 @@ export default {
|
|||
this.activeStudyIndex = studyIndex
|
||||
this.activeFileIndex = fileIndex
|
||||
const fileList = study.NoneDicomStudyFileList
|
||||
this.$emit('selectFile', { fileInfo: fileList[fileIndex], fileList, visitTaskInfo: this.visitTaskInfo, fileIndex: fileIndex, studyId: study.Id })
|
||||
this.$emit('selectFile', { fileInfo: fileList[fileIndex], fileList, visitTaskInfo: this.visitTaskInfo, studyId: study.Id })
|
||||
},
|
||||
activeImage(obj) {
|
||||
if (this.studyList.length === 0) return
|
||||
|
@ -115,7 +115,10 @@ export default {
|
|||
if (i === -1) return
|
||||
this.activeNames.push(obj.studyId)
|
||||
this.activeStudyIndex = i
|
||||
this.activeFileIndex = obj.imageIndex
|
||||
const fileList = this.studyList[i].NoneDicomStudyFileList
|
||||
const fIndex = fileList.findIndex(f => f.Path === obj.path)
|
||||
if (fIndex === -1) return
|
||||
this.activeFileIndex = fIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue