非dicom阅片更改

uat
caiyiling 2025-03-03 13:46:57 +08:00
parent 5f960348ed
commit 3aa66af253
5 changed files with 453 additions and 18 deletions

View File

@ -229,7 +229,7 @@ export default {
mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.readingTaskState = this.taskInfo.ReadingTaskState
if (this.taskInfo.VisitNum > 0) {
if (this.taskInfo.VisitNum > 0 && this.taskInfo.IsReadingTaskViewInOrder !== 0) {
this.rows = 1
this.cols = 2
this.activeCanvasIndex = 1

View File

@ -0,0 +1,331 @@
<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>
<!-- 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)"
>
<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"/>
<!-- <div class="left-top-text">
<div
v-if="v.taskInfo.IsExistsClinicalData"
class="cd-info"
:title="$t('trials:reading:button:clinicalData')"
@click.stop="viewCD($event)"
>
<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>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
// import { addNoneDicomMark, deleteTrialFileType } from '@/api/trials'
import { mapGetters } from 'vuex'
import store from '@/store'
export default {
name: 'PdfViewer',
data() {
return {
rows: 1,
cols: 1,
fullScreenIndex: null,
imageIds: [],
activeCanvasIndex: 0,
layout: '1*2',
cellsMax: 4,
viewportInfos: [],
taskInfo: null,
activeTool: '',
readingTaskState: 2
}
},
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'])
},
watch: {
relatedStudyInfo: {
immediate: true,
handler(obj) {
if (!obj || Object.keys(obj).length === 0) return
this.updateViewportInfos(0, obj)
}
}
},
mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.readingTaskState = this.taskInfo.ReadingTaskState
this.viewportInfos = Array.from({ length: this.cellsMax }, (_, index) => ({
index: index,
taskInfo: '',
studyId: '',
viewportId: `canvas-${index}`,
currentFileName: '',
currentFilePath: ''
}))
// this.addIframeEventListener()
window.addEventListener('message', this.handleIframeMessage);
},
beforeDestroy() {
window.removeEventListener('message', this.handleIframeMessage);
},
methods: {
handleIframeMessage(event) {
if (event.data.type === 'pdf-clicked') {
let 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)
}
},
setActiveCanvasImages(obj) {
if (!obj || Object.keys(obj).length === 0) return
const i = this.viewportInfos.findIndex(i => i.index === this.activeCanvasIndex)
if (i === -1) return
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)
},
//
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].currentFilePath = obj.fileList[obj.fileIndex].Path
this.viewportInfos[i].studyId = obj.studyId
},
//
handleCommand(command) {
this.fullScreenIndex = null
this.layout = command
this.rows = parseInt(command.split('*')[0])
this.cols = parseInt(command.split('*')[1])
},
//
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()
},
//
viewCD(e) {
}
}
}
</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>

View File

@ -41,6 +41,13 @@
@toggleTask="toggleTask"
@toggleImage="toggleImage"
/>
<!-- <pdf-viewer
ref="imageViewer"
:related-study-info="relatedStudyInfo"
@toggleTaskByViewer="toggleTaskByViewer"
@toggleTask="toggleTask"
@toggleImage="toggleImage"
/> -->
</div>
<!-- 表单 -->
<div class="right-panel">
@ -74,6 +81,7 @@
import { getRelatedVisitTask, getReadingImageFile, getNoneDicomMarkListOutDto } from '@/api/trials'
import StudyList from './StudyList'
import ImageViewer from './ImageViewer'
import PdfViewer from './PDFViewer'
import EcrfList from './EcrfList'
import { mapGetters } from 'vuex'
export default {
@ -81,6 +89,7 @@ export default {
components: {
StudyList,
ImageViewer,
PdfViewer,
EcrfList
},
data() {
@ -145,7 +154,7 @@ export default {
this.$refs[res.Result[idx].VisitTaskId][0].setInitActiveFile()
})
}
if (this.taskInfo.IsReadingTaskViewInOrder === 1 && res.Result.length > 1) {
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)
@ -178,6 +187,71 @@ export default {
}
const res = await getReadingImageFile(params)
this.$set(this.visitTaskList[visitTaskIdx], 'StudyList', res.Result)
// const arr = [
// {
// BodyPart: '',
// Code: 0,
// CodeView: '',
// Description: '',
// FileCount: 0,
// Id: '6783b9e8-738f-42d6-bc36-8d3b36b060ee',
// ImageDate: '0001-01-01 00:00:00',
// IsCriticalSequence: true,
// IsDeleted: false,
// IsReading: false,
// Modality: '',
// StudyName: '',
// SubjectId: '08dd3125-be6c-d544-0242-0a0001000000',
// SubjectVisitId: '01000000-0a10-0242-4a73-08dd3125be6d',
// TrialId: '08dd2ee1-0754-9e3d-0242-0a0001000000',
// UpdateTime: '0001-01-01 00:00:00',
// NoneDicomStudyFileList: [
// {
// Id: '08dd3480-5a81-cb9d-0242-0a0001000000',
// Path: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706111094_Independent%20Review%20Charter.pdf',
// FileName: 'A11CF934.jpg',
// CreateTime: '2025-01-14 17:46:43',
// CreateUserId: '746d0000-3e2c-0016-f276-08daeedff8de',
// NoneDicomStudyId: '08dd3480-4747-4454-0242-0a0001000000',
// FileSize: 29137,
// FullFilePath: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706111094_Independent%20Review%20Charter.pdf',
// FileType: 'image/jpeg'
// }
// ]
// },
// {
// BodyPart: '',
// Code: 0,
// CodeView: '',
// Description: '',
// FileCount: 0,
// Id: '6783b9e8-738f-42f6-bc36-8d3b36b060ee',
// ImageDate: '0001-01-01 00:00:00',
// IsCriticalSequence: true,
// IsDeleted: false,
// IsReading: false,
// Modality: '',
// StudyName: '',
// SubjectId: '08dd3125-be6c-d544-0242-0a0001000000',
// SubjectVisitId: '01000000-0a00-0242-4a73-08dd3125be6d',
// TrialId: '08dd2ee1-0754-9e3d-0242-0a0001000000',
// UpdateTime: '0001-01-01 00:00:00',
// NoneDicomStudyFileList: [
// {
// Id: '08dd3480-5a81-cb8d-0242-0a0001000000',
// Path: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706163441_IRaCIS%20%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9FV%201.0%20CRO%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3_20200601.pdf',
// FileName: 'A11CF934.jpg',
// CreateTime: '2025-01-14 17:46:43',
// CreateUserId: '746d0000-3e2c-0016-f276-08daeedff8de',
// NoneDicomStudyId: '08dd3480-4747-4454-0242-0a0001000000',
// FileSize: 29137,
// FullFilePath: '/08dd2ee1-0754-9e3d-0242-0a0001000000/DocumentToSign/1740706163441_IRaCIS%20%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9FV%201.0%20CRO%E7%94%A8%E6%88%B7%E4%BD%BF%E7%94%A8%E6%96%87%E6%A1%A3_20200601.pdf',
// FileType: 'image/jpeg'
// }
// ]
// }
// ]
// this.$set(this.visitTaskList[visitTaskIdx], 'StudyList', arr)
this.loading = false
resolve()
} catch (e) {

View File

@ -33,20 +33,29 @@
关键文件
</div>
</template>
<div class="series">
<div class="file-list-container">
<div
v-for="(k, i) in study.NoneDicomStudyFileList"
:key="i"
style="position:relative;margin-top:1px;"
series-type="current"
@click="selectFile(study, index, i)"
>
<div
:class="{'series-active': index === activeStudyIndex && i === activeFileIndex}"
class="series-wrapper"
:title="k.FileName"
:class="{'file-active': index === activeStudyIndex && i === activeFileIndex}"
class="file-wrapper"
>
{{ k.FileName }}
<div v-if="k.FileType === 'image/jpeg'" class="file-image">
<el-image
style="width: 100%;height: 100%;"
:src="`${OSSclientConfig.basePath}${k.Path}?x-oss-process=image/resize,w_50,h_50/format,png`"
fit="fill"
crossorigin="anonymous"
/>
</div>
<div class="file-text" :title="k.FileName">
{{ k.FileName }}
</div>
</div>
</div>
</div>
@ -80,14 +89,18 @@ export default {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.studyList = this.visitTaskInfo.StudyList
if (this.studyList.length === 0) return
this.activeNames.push(this.studyList[0].Id)
this.$nextTick(() => {
this.activeNames.push(this.studyList[0].Id)
})
},
methods: {
//
setInitActiveFile() {
if (this.studyList.length === 0) return
this.activeNames.push(this.studyList[0].Id)
this.selectFile(this.studyList[0], 0, 0)
this.$nextTick(() => {
this.activeNames.push(this.studyList[0].Id)
this.selectFile(this.studyList[0], 0, 0)
})
},
//
selectFile(study, studyIndex, fileIndex) {
@ -139,7 +152,7 @@ export default {
touch-action: auto;
overflow-y: auto;
}
.series-active {
.file-active {
background-color: #607d8b!important;
border: 1px solid #607d8b!important;
}
@ -147,26 +160,41 @@ export default {
color: #ccc;
font-size: 12px;
}
.series{
.file-list-container{
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
.series-wrapper {
.file-wrapper {
width: 100%;
padding: 5px;
display: flex;
flex-direction: row;
align-items: center;
cursor: pointer;
background-color: #3a3a3a;
color: #ddd;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
// color: #ddd;
// white-space: nowrap;
// overflow: hidden;
// text-overflow: ellipsis;
.el-progress__text{
display: none;
}
.el-progress-bar{
padding-right:0px;
}
.file-image {
width: 50px;
height: 50px;
}
.file-text {
flex: 1;
padding-left: 5px;
color: #ddd;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
}

View File

@ -2759,6 +2759,8 @@ function webViewerTouchStart(evt) {
}
function webViewerClick(evt) {
console.log('webViewerClick')
window.parent.postMessage({ type: 'pdf-clicked', data: {baseUrl: PDFViewerApplication.baseUrl}})
if (!PDFViewerApplication.secondaryToolbar.isOpen) {
return;
}