irc_web/.svn/pristine/d6/d6662d267d5b9c479577a24c574...

937 lines
36 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div v-loading="loading" class="study-wrapper">
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;text-align: center;background-color: #4c4c4c;">
{{ subjectCode }}
</h4>
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;text-align: center;background-color: #4c4c4c;margin-bottom: 5px;">
{{ taskBlindName }}
</h4>
<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">
<!-- 关键序列 -->
{{ $t('trials:reading:title:keySeries') }}
</div>
<div
v-else
class="dicom-desc"
style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
>
<el-tooltip class="item" effect="dark" :content="`${study.StudyCode} ${study.Description?study.Description:''} ${study.Modalities} (${study.SeriesCount})`" placement="right">
<div>
<span>{{ study.StudyCode }} {{ study.Description }}</span>
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span>
</div>
</el-tooltip>
</div>
</template>
<div class="series">
<div
v-for="(series, i) in study.SeriesList"
:key="i"
style="position:relative;margin:10px 0px;"
series-type="current"
@click="showSeriesImage(index,i,series)"
>
<div
:class="{'series-active': i==seriesIndex && index === studyIndex}"
class="series-wrapper"
>
<el-image
class="image-preview"
:src="series.previewImageUrl"
fit="fill"
/>
<div class="image-desc">
<div class="flex-div">
<div>#{{ series.seriesNumber }} </div>
<div v-if="series.isDicom && (series.sliceThickness && parseInt(series.sliceThickness) !== 5 && series.instanceCount > 100) && series.prefetchInstanceCount<series.instanceCount">
<!-- 下载 -->
<el-tooltip v-if="!series.isLoading || series.prefetchInstanceCount === 0" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
</el-tooltip>
<!-- 暂停 -->
<el-tooltip v-else class="item" effect="dark" :content="$t('trials:reading:button:pause')" placement="bottom">
<i class="el-icon-video-pause" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="stopLoadSeries(series,index,i)" />
</el-tooltip>
</div>
<el-tooltip v-else-if="series.prefetchInstanceCount === 0" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
</el-tooltip>
</div>
<p v-show="series.description">
<el-tooltip class="item" effect="dark" :content="series.description" placement="right">
<div style="">{{ series.description }}</div>
</el-tooltip>
</p>
<p v-show="series.sliceThickness">
T: {{ series.sliceThickness }}
</p>
<p v-show="series.instanceCount">
{{ series.modality }}: {{ series.instanceCount }} image
</p>
<div class="flex-div">
<!-- <div>
{{ series.isDicom?`${series.prefetchInstanceCount }/${series.instanceCount}`:series.instanceCount }}
</div> -->
<div v-if="series.isBeMark || measureData.findIndex(v=>v.SeriesId === series.seriesId) > -1">
<!-- 有标注 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:marked')" placement="right">
<i class="el-icon-star-on" style="font-size: 16px;color: #ff5722;" />
</el-tooltip>
</div>
</div>
</div>
</div>
<div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" style="width: 100%;">
<el-progress
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))"
/>
</div>
</div>
</div>
</el-collapse-item>
</el-collapse>
<!-- <div
v-for="(study, index) in studyList"
:key="index"
>
<template v-if="study.IsCriticalSequence">
<div class="dicom-desc">
关键序列
</div>
</template>
<template v-else>
<div class="dicom-desc">
{{ study.StudyCode }}
</div>
<div v-show="study.Description" class="dicom-desc">
{{ study.Description }}
</div>
<div v-show="study.SeriesCount" class="dicom-desc">
{{ study.Modalities }} : {{ study.SeriesCount }} Series
</div>
</template>
<div class="series">
<div
v-for="(series, i) in study.SeriesList"
:key="i"
style="position:relative;margin:10px 0px;"
series-type="current"
@click="showSeriesImage($event,index,i,series)"
>
<div
:class="{'series-active': i==seriesIndex && index === studyIndex}"
class="series-wrapper"
>
<el-image
class="image-preview"
:src="series.previewImageUrl"
fit="fill"
/>
<div class="image-desc">
<div class="flex-div">
<div>#{{ series.seriesNumber }}</div>
<div v-if="series.isDicom && series.instanceCount > 100 && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount">
</div>
</div>
<p v-show="series.InstanceCount">
{{ series.modality }}: {{ series.instanceCount }} image
</p>
<p v-show="series.sliceThickness">
T: {{ series.sliceThickness }}
</p>
<p v-show="series.description">
<el-tooltip class="item" effect="dark" :content="series.description" placement="right">
<span>{{ series.description }}</span>
</el-tooltip>
</p>
<div class="flex-div">
<div>
{{ series.isDicom?`${series.prefetchInstanceCount }/${series.instanceCount}`:series.instanceCount }}
</div>
<div v-if="series.isBeMark || measureData.findIndex(v=>v.SeriesId === series.seriesId) > -1">
<el-tooltip class="item" effect="dark" content="有标注" placement="right">
<i class="el-icon-star-on" style="font-size: 16px;color: #ff5722;" />
</el-tooltip>
</div>
</div>
</div>
</div>
<div v-if="series.isDicom && series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" style="width: 100%;">
<el-progress
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))"
/>
</div>
</div>
</div>
</div> -->
</div>
</div>
</template>
<script>
import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
// import requestPoolManager from '@/utils/request-pool'
import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex'
import store from '@/store'
cornerstoneWADOImageLoader.external.dicomParser = dicomParser
cornerstoneWADOImageLoader.external.cornerstone = cornerstone
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
export default {
name: 'StudyList',
props: {
trialId: {
type: String,
required: true
},
subjectVisitId: {
type: String,
required: true
},
visitTaskId: {
type: String,
required: true
},
isReading: {
type: Number,
default: 0
},
taskBlindName: {
type: String,
default: ''
}
},
data() {
return {
studyList: [],
cachedImages: [],
studyIndex: null,
seriesIndex: null,
loading: false,
measureData: [],
isRender: false,
firstInstanceId: '',
firstSeries: [],
firstSeriesId: '',
isStartLoad: false,
subjectCode: '',
activeNames: [],
seriesArr: [],
imageList: [],
loopLoadStatus: 0, // -1暂停下载 0未下载完成 1下载完成
numRequest: 0, // 正在执行数量
maxRequest: 2
}
},
computed: {
...mapGetters(['visitTaskList'])
},
mounted() {
this.subjectCode = this.$router.currentRoute.query.subjectCode
DicomEvent.$on('getMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
})
DicomEvent.$on('setReadingState', readingTaskState => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1) {
this.studyList = this.visitTaskList[idx].StudyList
}
})
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
cornerstone.events.addEventListener('cornerstoneimagecachechanged', () => {
// const cacheInfo = cornerstone.imageCache.getCacheInfo()
// console.log(cacheInfo)
})
},
beforeDestroy() {
console.log('beforeDestroy')
// requestPoolManager.stopTaskTimer()
// requestPoolManager.resetRequestPool()
cornerstone.imageCache.purgeCache()
DicomEvent.$off('getMeasureData')
},
methods: {
getStudyInfo(isRender = false) {
if (!this.isRender || isRender) {
const loading = this.$loading({ fullscreen: true })
// 初始化待渲染序列
this.getInitSeries().then((res) => {
var i = res.findIndex(s => s.isCurrentTask)
if (i > -1) {
this.firstSeriesId = res[i].seriesId
var p = parseInt(new Date().getTime())
// res[i].imageIds.map(imageId => {
// let priority = p-1
// this.imageList.push({ imageId: imageId, seriesId: res[i].seriesId, priority })
// })
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1) {
this.studyList = this.visitTaskList[idx].StudyList
this.studyList.map(study => {
study.SeriesList.map(series => {
var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
if (sliceThickness === 5 || series.instanceCount <= 100) {
series.imageIds.map(image => {
let priority = 0
if (series.seriesId === res[i].seriesId) {
priority = parseInt(new Date().getTime()) * 10
} else {
priority = --p
}
this.imageList.push({ imageId: image, seriesId: series.seriesId, priority })
})
}
})
})
// console.log(this.imageList)
this.loopLoad()
}
}
DicomEvent.$emit('loadImageStacks', res)
})
this.isRender = true
loading.close()
} else {
this.$emit('loadImageStack', this.studyList[this.studyIndex].SeriesList[this.seriesIndex])
}
},
initStudyList() {
if (!this.isRender) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) {
this.studyList = this.visitTaskList[idx].StudyList
var sIdx = this.studyList.findIndex(s => s.IsDicom)
if (sIdx > -1) {
this.studyIndex = sIdx
this.seriesIndex = 0
this.activeNames = [`${this.studyList[sIdx].StudyId}`]
this.loadImages(this.visitTaskList[idx])
}
}
this.isRender = true
}
},
async getInitSeries() {
var seriesList = []
var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.studyList = this.visitTaskList[idx].StudyList
if (this.visitTaskList[idx].IsBaseLineTask || !isReadingTaskViewInOrder) {
// 基线
const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList])
this.studyIndex = obj.studyIndex
this.seriesIndex = obj.seriesIndex
seriesList.push(obj.series)
this.activeNames = [`${this.studyList[ this.studyIndex].StudyId}`]
const imageId = obj.series.imageIds[obj.series.imageIdIndex]
let instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.firstInstanceId = instanceId
this.firstSeries = obj.series.imageIds
this.studyList[ obj.studyIndex].SeriesList[obj.seriesIndex].isFirstRender = true
} else {
// 随访
var bsIdx = null
var criterionType = parseInt(localStorage.getItem('CriterionType'))
if (criterionType === 10) {
const i = this.visitTaskList.findIndex(i => i.IsCurrentTask)
bsIdx = i - 1
} else {
bsIdx = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
}
if (bsIdx > -1) {
var trialId = this.$router.currentRoute.query.trialId
await store.dispatch('reading/getMeasuredData', this.visitTaskList[bsIdx].VisitTaskId)
await store.dispatch('reading/getStudyInfo', { trialId: trialId, subjectVisitId: this.visitTaskList[bsIdx].VisitId, visitTaskId: this.visitTaskList[bsIdx].VisitTaskId, taskBlindName: this.visitTaskList[bsIdx].TaskBlindName })
const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList])
seriesList.push(firstObj.series)
const secondObj = this.getSecondMarkedSeries(firstObj, { ...this.visitTaskList[idx] })
this.studyIndex = secondObj.studyIndex
this.seriesIndex = secondObj.seriesIndex
seriesList.push(secondObj.series)
const imageId = secondObj.series.imageIds[secondObj.series.imageIdIndex]
let instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.firstInstanceId = instanceId
this.firstSeries = secondObj.series.imageIds
this.studyList[ secondObj.studyIndex].SeriesList[secondObj.seriesIndex].isFirstRender = true
this.studyIndex = secondObj.studyIndex
this.seriesIndex = secondObj.seriesIndex
this.activeNames = [`${this.studyList[secondObj.studyIndex].StudyId}`]
} else {
const sIdx = this.studyList.findIndex(s => s.IsDicom)
const series = this.studyList[sIdx].SeriesList[0]
series.imageIdIndex = Math.floor(series.imageIds.length / 2)
seriesList.push(series)
this.studyIndex = sIdx
this.seriesIndex = 0
this.activeNames = [`${this.studyList[sIdx].StudyId}`]
}
}
return seriesList
},
getSecondMarkedSeries(baseObj, visitTaskInfo) {
var obj = {}
var studyList = visitTaskInfo.StudyList
var measureDatas = visitTaskInfo.MeasureData
if (baseObj.isMarked) {
var i = measureDatas.findIndex(i => Object.keys(i.MeasureData).length > 0 && i.OrderMarkName === baseObj.measureData.OrderMarkName)
if (i !== -1) {
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId)
const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId)
// const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId))
const series = seriesList[srIdx]
series.imageIdIndex = isIdx
obj.studyIndex = sdIndx
obj.seriesIndex = srIdx
obj.series = series
obj.seriesId = series.seriesId
return obj
}
}
// 如果没有相同标记的影像,则筛选描述一致
var seriseArr = []
studyList.forEach((s, i) => {
var series = s.SeriesList.filter(series => series.description === baseObj.series.description)
series.length > 0 ? seriseArr.push(...series) : ''
})
if (seriseArr.length > 0) {
// 描述一致,则筛选层厚一致
var stSeriseArr = seriseArr.filter(s => s.sliceThickness === baseObj.series.sliceThickness)
if (stSeriseArr.length > 0) {
// 层厚一致,则筛选序列号最为接近的
const i = this.findSerialNumberClosest(stSeriseArr, baseObj.series.seriesNumber)
if (i > -1) {
obj.studyIndex = stSeriseArr[i].studyIndex
obj.seriesIndex = stSeriseArr[i].seriesIndex
obj.series = stSeriseArr[i]
var imageIdIndex = Math.floor(stSeriseArr[i].imageIds.length * (baseObj.series.imageIdIndex / baseObj.series.instanceCount))
obj.series.imageIdIndex = imageIdIndex
obj.seriesId = stSeriseArr[i].seriesId
} else {
const sIdx = stSeriseArr[0].studyIndex
const series = stSeriseArr[0]
const imageIdIndex = Math.floor(series.imageIds.length * (baseObj.series.imageIdIndex / baseObj.series.instanceCount))
obj.studyIndex = sIdx
obj.seriesIndex = 0
obj.series = series
obj.series.imageIdIndex = imageIdIndex
obj.seriesId = series.seriesId
}
// 层厚一致,则筛选图像数量一致
// var icSeriseArr = stSeriseArr.filter(s => s.instanceCount === baseObj.series.instanceCount)
// if (icSeriseArr.length > 0) {
// const sIdx = icSeriseArr[0].studyIndex
// const series = icSeriseArr[0]
// var imageIdIndex = Math.floor(series.imageIds.length * (baseObj.series.imageIdIndex / baseObj.series.instanceCount))
// obj.studyIndex = sIdx
// obj.seriesIndex = 0
// obj.series = series
// obj.series.imageIdIndex = imageIdIndex
// obj.seriesId = series.seriesId
// } else {
// const sIdx = stSeriseArr[0].studyIndex
// const series = stSeriseArr[0]
// const imageIdIndex = Math.floor(series.imageIds.length * (baseObj.series.imageIdIndex / baseObj.series.instanceCount))
// obj.studyIndex = sIdx
// obj.seriesIndex = 0
// obj.series = series
// obj.series.imageIdIndex = imageIdIndex
// obj.seriesId = series.seriesId
// }
} else {
const sIdx = seriseArr[0].studyIndex
const series = seriseArr[0]
const imageIdIndex = Math.floor(series.imageIds.length * (baseObj.series.imageIdIndex / baseObj.series.instanceCount))
obj.studyIndex = sIdx
obj.seriesIndex = 0
obj.series = series
obj.series.imageIdIndex = imageIdIndex
obj.seriesId = series.seriesId
}
} else {
// 都不符合要求, 判断是否存在层厚为5的序列否则显示第一个检查的第一个序列
var seriesObj = null
for (let i = 0; i < studyList.length; i++) {
const seriesIdx = studyList[i].SeriesList.findIndex(s => s.sliceThickness && parseInt(s.sliceThickness) === 5)
if (seriesIdx > -1) {
seriesObj = { studyIndex: i, seriesIdx, series: studyList[i].SeriesList[seriesIdx] }
break
}
}
if (seriesObj) {
obj.studyIndex = seriesObj.studyIndex
obj.seriesIndex = seriesObj.seriesIdx
seriesObj.series.imageIdIndex = Math.floor(seriesObj.series.imageIds.length / 2)
obj.series = seriesObj.series
obj.seriesId = seriesObj.series.seriesId
} else {
const sIdx = studyList.findIndex(s => s.IsDicom)
const series = studyList[sIdx].SeriesList[0]
series.imageIdIndex = Math.floor(series.imageIds.length / 2)
obj.studyIndex = sIdx
obj.seriesIndex = 0
obj.series = series
obj.seriesId = series.seriesId
}
}
return obj
},
findSerialNumberClosest(arr, n) {
var absArr = []
for (let i = 0; i < arr.length; i++) {
const m = n - arr[i].seriesNumber
absArr.push({ index: i, n: Math.abs(m) })
}
const num = Math.min.apply(null, absArr.map(item => item.n))
var mIdx = absArr.findIndex(item => item.n === num)
return mIdx
},
getFirstMarkedSeries(measureDatas, studyList) {
var obj = {}
var mIdx = measureDatas.findIndex(m => Object.keys(m.MeasureData).length > 0)
if (mIdx !== -1) {
// 有标记时,显示带标记影像所在序列
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[mIdx].StudyId)
const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId)
// const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId))
const series = seriesList[srIdx]
series.imageIdIndex = isIdx
obj.studyIndex = sdIndx
obj.seriesIndex = srIdx
obj.series = series
obj.seriesId = series.seriesId
obj.isMarked = true
obj.measureData = measureDatas[mIdx]
} else {
var seriesObj = null
for (let i = 0; i < studyList.length; i++) {
const seriesIdx = studyList[i].SeriesList.findIndex(s => s.sliceThickness && parseInt(s.sliceThickness) === 5)
if (seriesIdx > -1) {
seriesObj = { studyIndex: i, seriesIdx, series: studyList[i].SeriesList[seriesIdx] }
break
}
}
if (seriesObj) {
obj.studyIndex = seriesObj.studyIndex
obj.seriesIndex = seriesObj.seriesIdx
seriesObj.series.imageIdIndex = Math.floor(seriesObj.series.imageIds.length / 2)
obj.series = seriesObj.series
obj.seriesId = seriesObj.series.seriesId
obj.isMarked = false
} else {
const sIdx = studyList.findIndex(s => s.IsDicom)
// 判断是否存在层厚为5的序列否则显示第一个检查的第一个序列
const series = studyList[sIdx].SeriesList[0]
var imageIdIndex = Math.floor(series.imageIds.length / 2)
obj.studyIndex = sIdx
obj.seriesIndex = 0
obj.series = series
obj.series.imageIdIndex = imageIdIndex
obj.seriesId = series.seriesId
obj.isMarked = false
}
}
return obj
},
// 缩略图下载成功回调,默认下载第一个检查的所有序列
previewImageLoad() {
this.studyList[0].PreviewImageCount++
if (this.studyList[0].PreviewImageCount === this.studyList[0].SeriesCount) {
this.loadAllImages()
}
},
// 缩略图下载失败回调,默认下载第一个检查的所有序列
previewImageLoadError() {
this.studyList[0].PreviewImageCount++
if (this.studyList[0].previewImageCount === this.studyList[0].seriesCount) {
this.loadAllImages()
}
},
showSeriesImage(studyIndex, seriesIndex, series) {
if (series.isDicom) {
this.studyIndex = studyIndex
this.seriesIndex = seriesIndex
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
var dicomStatck = this.studyList[studyIndex].SeriesList[seriesIndex]
this.$emit('loadImageStack', dicomStatck)
if (!series.loadStatus) {
this.loopLoadStatus = -1
series.isLoading = true
var p = parseInt(new Date().getTime())
series.imageIds.map((imageId, i) => {
var priority = ''
if (i === 0) {
// priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
priority = parseInt(new Date().getTime()) * 10
} else {
priority = --p
}
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
})
if (this.imageList.length > 0) {
this.loopLoadStatus = 0
this.loopLoad()
}
}
DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskId, taskBlindName: this.taskBlindName })
} else {
// 非Dicom预览
this.$emit('previewNoneDicoms', { visitTaskId: this.visitTaskId })
}
},
activeSeries(series) {
console.log(series.studyIndex, series.seriesIndex)
this.studyIndex = series.studyIndex
this.seriesIndex = series.seriesIndex
var activeNames = `${this.studyList[series.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames)
},
toggleStudy(stack) {
console.log('toggleStudy')
if (!stack.studyId) return
if (!this.isRender) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) {
this.studyList = this.visitTaskList[idx].StudyList
this.loadImages(this.visitTaskList[idx])
}
this.isRender = true
}
var studyIdx = this.studyList.findIndex(study => study.StudyId === stack.studyId)
if (studyIdx === -1) return
var study = this.studyList[studyIdx]
var seriesIdx = study.SeriesList.findIndex(series => series.seriesId === stack.seriesId)
if (seriesIdx === -1) return
this.studyIndex = studyIdx
this.seriesIndex = seriesIdx
if (!this.activeNames.includes(`${this.studyList[studyIdx].StudyId}`)) {
this.activeNames.push(`${this.studyList[studyIdx].StudyId}`)
}
DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskId, taskBlindName: this.taskBlindName })
},
loadImages(taskInfo) {
var priority = parseInt(new Date().getTime())
// 当前任务只自动下载层厚为5mm 或者影像数量小于 100张
if (taskInfo.IsCurrentTask) {
this.studyList.map(study => {
study.SeriesList.map(series => {
var sliceThickness = isNaN(parseInt(series.sliceThickness)) ? null : parseInt(series.sliceThickness)
if (sliceThickness === 5 || series.instanceCount <= 100) {
series.imageIds.map(image => {
priority = priority - 1
this.imageList.push({ imageId: image, seriesId: series.seriesId, priority })
})
}
})
})
this.loopLoad()
} else {
// 非当前任务只自动下载关键序列
var idx = this.studyList.findIndex(study => study.IsCriticalSequence)
if (idx === -1) return
this.studyList[idx].SeriesList.forEach(series => {
if (!series.loadStatus) {
series.imageIds.map(image => {
priority--
// this.load(image, series.seriesId, priority)
this.imageList.push({ imageId: image, seriesId: series.seriesId, priority })
})
}
})
this.loopLoad()
}
},
loopLoad() {
if (this.imageList.length > 0 && this.loopLoadStatus !== -1) {
const executeRequest = this.maxRequest - this.numRequest
if (executeRequest > 0) {
for (let i = 0; i < executeRequest; i++) {
this.numRequest++
this.imageList.sort((a, b) => b.priority - a.priority)
var imageId = this.imageList[0].imageId
cornerstone.loadAndCacheImage(imageId).then(res => {
this.numRequest--
this.imageLoaded(imageId, res.data.string('x0020000e'))
this.imageList.splice(0, 1)
if (this.imageList.length > 0) {
this.loopLoad()
} else {
this.loopLoadStatus = 1
}
})
}
}
}
},
// 启动下载序列
loadSeries(series, studyIndex, seriesIndex) {
this.loopLoadStatus = -1
this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', true)
const priority = parseInt(new Date().getTime())
series.imageIds.map(image => {
if (series.imageloadedArr.indexOf(image) === -1) {
this.imageList.push({ imageId: image, seriesId: series.seriesId, priority })
}
})
if (this.imageList.length > 0) {
this.loopLoadStatus = 0
this.loopLoad()
}
},
// 暂停下载
stopLoadSeries(series, studyIndex, seriesIndex) {
this.loopLoadStatus = -1
this.$set(this.studyList[studyIndex].SeriesList[seriesIndex], 'isLoading', false)
for (var i = this.imageList.length - 1; i >= 0; i--) {
var item = this.imageList[i]
if (item.seriesId === series.seriesId) {
this.imageList.splice(i, 1)
}
}
this.loopLoadStatus = 0
// requestPoolManager.removeTask(series.seriesId)
},
load(imageId, seriesId, priority) {
return new Promise((resolve, reject) => {
// requestPoolManager.loadAndCacheImagePlus(imageId, seriesId, priority).then(res => {
// if (!res) return
// this.imageLoaded(imageId, res.data.string('x0020000e'))
// resolve(res)
// }).catch(e => {
// reject(e)
// })
})
},
buildImageRequestTask(imageId, config = {}) {
return {
key: imageId,
...config,
execute: () => {
return cornerstone.loadAndCacheImage(imageId)
}
}
},
datasetsCacheChanged(e) {
const cacheInfo = e.detail.cacheInfo
const cacheSizeInBytes = cacheInfo.cacheSizeInBytes
if (cacheSizeInBytes >= maximumSizeInBytes) {
// 清理缓存的影像
}
},
async imageLoaded(imageId, seriesUid) {
await store.dispatch('reading/updateStudyList', { visitTaskId: this.visitTaskId, imageId, seriesUid })
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) {
this.studyList = this.visitTaskList[idx].StudyList
}
},
// instance下载成功回调
async cornerstoneImageLoaded(e) {
await store.dispatch('reading/updateStudyList', { visitTaskId: this.visitTaskId, imageId: e.detail.image.imageId, seriesUid: e.detail.image.data.string('x0020000e') })
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (e.detail.image.imageId.includes(this.firstInstanceId) && !this.isStartLoad) {
// 初始化图像加载完成时,自动下载
// this.loadImages(this.visitTaskList[idx])
this.isStartLoad = true
}
this.studyList = this.visitTaskList[idx].StudyList
const uri = e.detail.image.sharedCacheKey
const index = this.cachedImages.findIndex(item => item.uri === uri)
if (index === -1) {
this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
} else {
this.cachedImages[index].timestamp = new Date().getTime()
}
var imageId = e.detail.image.imageId
var seriesUid = e.detail.image.data.string('x0020000e')
var studyIndex = -1
var seriesIndex = -1
for (let i = 0; i < this.studyList.length; ++i) {
for (let j = 0; j < this.studyList[i].SeriesList.length; ++j) {
if (this.studyList[i].SeriesList[j].seriesUid === seriesUid) {
studyIndex = i
seriesIndex = j
break
}
}
if (studyIndex > 0) break
}
if (seriesIndex < 0) return
const imageIdIndex = this.studyList[studyIndex].SeriesList[seriesIndex].imageIds.indexOf(imageId)
if (imageIdIndex < 0) return
// console.log(`---下载第${seriesIndex + 1}个序列-第${imageIdIndex + 1}张图像完成---`)
if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
// ++this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount
// this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.push(imageId)
if (this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount >= this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount) {
// this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount
// 设置当前序列状态为已下载完成
this.studyList[studyIndex].SeriesList[seriesIndex].loadStatus = true
// requestPoolManager.stopTaskTimer()
}
}
}
}
}
</script>
<style lang="scss" scoped>
.study-wrapper{
>>>.el-progress-bar__inner{
transition: width 0s ease;
}
width:100%;
height: 100%;
overflow-y: auto;
.dicom-desc{
font-weight: bold;
font-size: 13px;
text-align: left;
color: #d0d0d0;
padding: 2px;
}
.ps {
overflow-anchor: none;
touch-action: auto;
}
.series-active {
background-color: #607d8b!important;
border: 1px solid #607d8b!important;
}
>>>.el-progress__text{
color: #ccc;
font-size: 12px;
}
.series{
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
.series-wrapper {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
height: 95px;
// padding: 1px 2px 1px 8px;
// margin: 10px 0px;
border-radius: 2px;
border: 1px solid #404040;
background-color: #3a3a3a;
.el-progress__text{
display: none;
}
.el-progress-bar{
padding-right:0px;
}
.image-preview {
height: 60px;
width: 60px;
border: 2px solid #252525;
cursor: pointer;
}
.image-desc {
vertical-align: top;
p{
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
color: #ddd;
margin: 0px;
line-height: 1.5;
div{
width: 100px;
}
}
}
.flex-div{
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 1px;
width: 100px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
font-size: 12px;
color: #ddd;
padding: 1px;
margin: 0px;
}
}
}
.el-collapse{
border: none;
>>>.el-collapse-item{
background-color: #000!important;
color: #ddd;
}
>>>.el-collapse-item__content{
padding-bottom:10px;
background-color: #000!important;
}
>>>.el-collapse-item__header{
background-color: #000!important;
color: #ddd;
border-bottom-color:#5a5a5a;
padding-left: 5px;
height: 40px;
line-height: 20px;
}
}
}
</style>