预览多帧图像处理

uat_us
caiyiling 2024-05-17 15:45:12 +08:00
parent 9c5fa63b89
commit e3034e3b07
2 changed files with 275 additions and 81 deletions

View File

@ -43,6 +43,47 @@
fit="fill" fit="fill"
> >
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div v-if="item.keySeries" style="color:red">
Key Images
</div>
<div v-else>
#{{ item.seriesNumber }}
</div>
<div v-if="item.isExistMutiFrames && item.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in item.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(item, index, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
</div>
<div v-if="item.keySeries" style="padding: 1px;color:red"> <div v-if="item.keySeries" style="padding: 1px;color:red">
Key Images Key Images
</div> </div>
@ -64,7 +105,7 @@
</div> </div>
</div> </div>
<div v-if="showDelete" @click.stop="" style="display: flex;flex-direction: row;justify-content: space-between;"> <div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
<div> <div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') }}</span> <span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') }}</span>
@ -206,14 +247,15 @@ export default {
var seriesList = [] var seriesList = []
Result.forEach(function(item) { Result.forEach(function(item) {
const imageIds = [] const imageIds = []
// item.InstanceList.forEach(function(id) { item.InstanceInfoList.forEach(i => {
// imageIds.push(`wadouri:/api/instance/content/${id}`) if (i.NumberOfFrames && i.NumberOfFrames > 1) {
// }) for (let j = 0; j < i.NumberOfFrames; j++) {
// item.InstanceList.forEach((id) => { const path = `${i.Path}?frame=${j}&instanceId=${i.Id}`
// imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
// }) }
item.InstancePathList.forEach((path) => { } else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}`)
}
}) })
var subjectVisitId = scope.$router.currentRoute.query.subjectVisitId var subjectVisitId = scope.$router.currentRoute.query.subjectVisitId
var studyId = scope.$router.currentRoute.query.studyId var studyId = scope.$router.currentRoute.query.studyId
@ -223,6 +265,7 @@ export default {
subjectVisitId, subjectVisitId,
studyId, studyId,
imageIds: imageIds, imageIds: imageIds,
instanceInfoList: item.InstanceInfoList,
seriesId: item.Id, seriesId: item.Id,
seriesUid: item.SeriesInstanceUid, seriesUid: item.SeriesInstanceUid,
seriesNumber: item.SeriesNumber, seriesNumber: item.SeriesNumber,
@ -238,7 +281,8 @@ export default {
keySeries: item.KeySeries, keySeries: item.KeySeries,
tpCode: scope.tpCode, tpCode: scope.tpCode,
loadStatus: false, loadStatus: false,
imageloadedArr: [] imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
}) })
}) })
scope.seriesList = seriesList scope.seriesList = seriesList
@ -269,20 +313,25 @@ export default {
var isDeleted = res.Result[0].IsDeleted var isDeleted = res.Result[0].IsDeleted
var seriesList = [] var seriesList = []
var imageIds = [] var imageIds = []
let isExistMutiFrames = false
const instanceInfoList = []
res.Result.forEach(instance => { res.Result.forEach(instance => {
if (instance.NumberOfFrames > 1) { if (instance.NumberOfFrames > 1) {
for (let i = 0; i < instance.NumberOfFrames; i++) { for (let i = 0; i < instance.NumberOfFrames; i++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?frame=${i}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?frame=${i}`)
} }
isExistMutiFrames = true
} else { } else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}`)
} }
instanceInfoList.push({ Id: instance.Id, InstanceNumber: instance.InstanceNumber, NumberOfFrames: instance.NumberOfFrames, Path: instance.Path })
}) })
seriesList.push({ seriesList.push({
trialId, trialId,
subjectVisitId, subjectVisitId,
studyId, studyId,
imageIds: imageIds, imageIds: imageIds,
instanceInfoList,
seriesId: seriesId, seriesId: seriesId,
seriesUid: seriesInstanceUid, seriesUid: seriesInstanceUid,
seriesNumber: seriesNumber, seriesNumber: seriesNumber,
@ -295,7 +344,8 @@ export default {
instanceCount: res.Result.length, instanceCount: res.Result.length,
prefetchInstanceCount: 0, prefetchInstanceCount: 0,
loadStatus: false, loadStatus: false,
imageloadedArr: [] imageloadedArr: [],
isExistMutiFrames: isExistMutiFrames
}) })
this.seriesList = seriesList this.seriesList = seriesList
if (this.seriesList.length > 0) { if (this.seriesList.length > 0) {
@ -319,21 +369,38 @@ export default {
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex]) this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
if (!series.loadStatus) { if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId) requestPoolManager.changePriority(series.seriesId)
// var isAddToTakPool = false }
// if (this.showSeriesList.includes(`${seriesIndex}`)) { },
// isAddToTakPool = true showMultiFrames(series, seriesIndex, instanceInfo) {
// } else { this.currentSeriesIndex = seriesIndex
// this.showSeriesList.push(`${seriesIndex}`) const imageIds = []
// } if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
// if (!isAddToTakPool) { for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
// var priority = parseInt(new Date().getTime()) const path = `${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}`
// series.isLoading = true imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)
// series.imageIds.map((imageId) => { }
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority }) } else {
// }) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}`)
// } else { }
// requestPoolManager.changePriority(series.seriesId) const seriesInfo = {
// } trialId: series.trialId,
subjectVisitId: series.subjectVisitId,
studyId: series.studyId,
imageIds: imageIds,
seriesId: series.seriesId,
seriesUid: series.seriesUid,
seriesNumber: series.seriesNumber,
sliceThickness: series.sliceThickness,
modality: series.modality,
description: series.description,
isReading: series.isReading,
isDeleted: series.isDeleted,
previewImageUrl: series.previewImageUrl,
instanceCount: series.instanceCount
}
this.$refs.dicomViewer.loadImageStack(seriesInfo)
if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId)
} }
}, },
initStudy() { initStudy() {
@ -756,6 +823,29 @@ export default {
color: #D0D0D0; color: #D0D0D0;
font-size: 13px; font-size: 13px;
} }
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
/* .viewerRightSidePanel { /* .viewerRightSidePanel {
width: 300px; width: 300px;
height: 100%; height: 100%;

View File

@ -46,13 +46,6 @@
@click="showSeriesImage($event,index,i,series)" @click="showSeriesImage($event,index,i,series)"
> >
<div class="viewernavigatorwrapper"> <div class="viewernavigatorwrapper">
<!-- <el-image
class="image-preview"
style="height:72px;width:72px;"
:src="series.previewImageUrl"
fit="fill"
/> -->
<img <img
class="image-preview" class="image-preview"
:src="series.previewImageUrl" :src="series.previewImageUrl"
@ -62,8 +55,41 @@
fit="fill" fit="fill"
> >
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div style="padding: 1px;"> <div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
#{{ series.seriesNumber }} <div>#{{ series.seriesNumber }}</div>
<div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in series.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(series, i, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
</div> </div>
<div v-show="series.InstanceCount" style="padding: 1px;"> <div v-show="series.InstanceCount" style="padding: 1px;">
{{ series.modality }}: {{ series.instanceCount }} image {{ series.modality }}: {{ series.instanceCount }} image
@ -80,10 +106,10 @@
<div style="padding: 1px;"> <div style="padding: 1px;">
{{ series.prefetchInstanceCount }}/{{ series.instanceCount }} {{ series.prefetchInstanceCount }}/{{ series.instanceCount }}
</div> </div>
<div />
</div> </div>
</div> </div>
<div v-if="showDelete" @click.stop="" style="display: flex;flex-direction: row;justify-content: space-between;"> <div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
<div> <div>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span> <span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span>
@ -163,13 +189,46 @@
> >
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div v-if="seriesItem.keySeries" style="padding: 1px;color:red"> <div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
Key Images <div v-if="seriesItem.keySeries" style="color:red">
Key Images
</div>
<div v-else>#{{ seriesItem.seriesNumber }}</div>
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in seriesItem.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<seriesItem.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(seriesItem, i, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
</div> </div>
<div v-else style="padding: 1px;"> <div v-show="seriesItem.instanceCount" style="padding: 1px;">
#{{ seriesItem.seriesNumber }}
</div>
<div v-show=" seriesItem.instanceCount" style="padding: 1px;">
{{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image {{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image
</div> </div>
<div v-show="seriesItem.sliceThickness" style="padding: 1px;"> <div v-show="seriesItem.sliceThickness" style="padding: 1px;">
@ -180,7 +239,6 @@
{{ seriesItem.description }} {{ seriesItem.description }}
</div> </div>
</el-tooltip> </el-tooltip>
</div> </div>
<!-- <div style="position: absolute;bottom: -10px;left: 0;width: 100%;"> <!-- <div style="position: absolute;bottom: -10px;left: 0;width: 100%;">
<el-progress v-if="seriesItem.prefetchInstanceCount>0 && seriesItem.prefetchInstanceCount<seriesItem.instanceCount" :percentage="Number(seriesItem.prefetchInstanceCount/seriesItem.instanceCount)*100" /> <el-progress v-if="seriesItem.prefetchInstanceCount>0 && seriesItem.prefetchInstanceCount<seriesItem.instanceCount" :percentage="Number(seriesItem.prefetchInstanceCount/seriesItem.instanceCount)*100" />
@ -241,6 +299,7 @@ export default {
} }
}, },
mounted() { mounted() {
document.documentElement.style.userSelect = 'none'
if (this.$router.currentRoute.query.TokenKey) { if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey) store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '') changeURLStatic('TokenKey', '')
@ -274,21 +333,22 @@ export default {
var seriesList = [] var seriesList = []
study.SeriesList.forEach((series) => { study.SeriesList.forEach((series) => {
const imageIds = [] const imageIds = []
series.InstanceInfoList.forEach(i => {
// series.InstanceList.forEach((id) => { if (i.NumberOfFrames && i.NumberOfFrames > 1) {
// imageIds.push(`wadouri:/api/instance/content/${id}`) for (let j = 0; j < i.NumberOfFrames; j++) {
// }) const path = `${i.Path}?frame=${j}&instanceId=${i.Id}`
// series.InstanceList.forEach((id) => { imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)
// imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`) }
// }) } else {
series.InstancePathList.forEach((path) => { imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}`)
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`) }
}) })
seriesList.push({ seriesList.push({
trialId: this.trialId, trialId: this.trialId,
subjectVisitId: this.subjectVisitId, subjectVisitId: this.subjectVisitId,
studyId: study.StudyId, studyId: study.StudyId,
imageIds: imageIds, imageIds: imageIds,
instanceInfoList: series.InstanceInfoList,
seriesId: series.Id, seriesId: series.Id,
seriesUid: series.SeriesInstanceUid, seriesUid: series.SeriesInstanceUid,
seriesNumber: series.SeriesNumber, seriesNumber: series.SeriesNumber,
@ -301,7 +361,8 @@ export default {
instanceCount: series.InstanceCount, instanceCount: series.InstanceCount,
prefetchInstanceCount: 0, prefetchInstanceCount: 0,
loadStatus: false, loadStatus: false,
imageloadedArr: [] imageloadedArr: [],
isExistMutiFrames: series.IsExistMutiFrames
}) })
}) })
data.SeriesList = seriesList data.SeriesList = seriesList
@ -329,21 +390,38 @@ export default {
this.$refs.dicomViewer.loadImageStack(this.studyList[studyIndex].SeriesList[seriesIndex]) this.$refs.dicomViewer.loadImageStack(this.studyList[studyIndex].SeriesList[seriesIndex])
if (!series.loadStatus) { if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId) requestPoolManager.changePriority(series.seriesId)
// var isAddToTakPool = false }
// if (this.showSeriesList.includes(`${studyIndex}_${seriesIndex}`)) { },
// isAddToTakPool = true showMultiFrames(series, seriesIndex, instanceInfo) {
// } else { this.currentSeriesIndex = seriesIndex
// this.showSeriesList.push(`${studyIndex}_${seriesIndex}`) const imageIds = []
// } if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
// if (!isAddToTakPool) { for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
// var priority = parseInt(new Date().getTime()) const path = `${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}`
// series.isLoading = true imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)
// series.imageIds.map((imageId, i) => { }
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority }) } else {
// }) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}`)
// } else { }
// requestPoolManager.changePriority(series.seriesId) const seriesInfo = {
// } trialId: series.trialId,
subjectVisitId: series.subjectVisitId,
studyId: series.studyId,
imageIds: imageIds,
seriesId: series.seriesId,
seriesUid: series.seriesUid,
seriesNumber: series.seriesNumber,
sliceThickness: series.sliceThickness,
modality: series.modality,
description: series.description,
isReading: series.isReading,
isDeleted: series.isDeleted,
previewImageUrl: series.previewImageUrl,
instanceCount: series.instanceCount
}
this.$refs.dicomViewer.loadImageStack(seriesInfo)
if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId)
} }
}, },
changeReadingStatus(callback, data) { changeReadingStatus(callback, data) {
@ -450,17 +528,19 @@ export default {
const res = data.Result const res = data.Result
res.forEach(function(item) { res.forEach(function(item) {
const imageIds = [] const imageIds = []
// item.InstanceList.forEach(function(id) { item.InstanceInfoList.forEach(i => {
// imageIds.push(`wadouri:/api/instance/content/${id}`) if (i.NumberOfFrames && i.NumberOfFrames > 1) {
// }) for (let j = 0; j < i.NumberOfFrames; j++) {
// item.InstanceList.forEach((id) => { const path = `${i.Path}?frame=${j}&instanceId=${i.Id}`
// imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
// }) }
item.InstancePathList.forEach((path) => { } else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`) imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}`)
}
}) })
seriesList.push({ seriesList.push({
imageIds: imageIds, imageIds: imageIds,
instanceInfoList: item.InstanceInfoList,
seriesId: item.Id, seriesId: item.Id,
seriesUid: item.SeriesInstanceUid, seriesUid: item.SeriesInstanceUid,
seriesNumber: item.SeriesNumber, seriesNumber: item.SeriesNumber,
@ -473,7 +553,8 @@ export default {
hasLabel: item.HasLabel, hasLabel: item.HasLabel,
keySeries: item.KeySeries, keySeries: item.KeySeries,
loadStatus: false, loadStatus: false,
imageloadedArr: [] imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
}) })
}) })
scope.relationStudyList[index].seriesCount = seriesList.length scope.relationStudyList[index].seriesCount = seriesList.length
@ -694,9 +775,9 @@ export default {
padding: 5px; padding: 5px;
/* height: 95%; */ /* height: 95%; */
height: 99%; height: 99%;
overflow: hidden; /* overflow: hidden;
text-overflow: clip; text-overflow: clip; */
white-space: nowrap; /* white-space: nowrap; */
} }
.viewerContainer .viewerContentWrapper>div { .viewerContainer .viewerContentWrapper>div {
display: inline-block; display: inline-block;
@ -813,6 +894,29 @@ export default {
height: 40px; height: 40px;
line-height: 20px; line-height: 20px;
} }
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
/* .viewerRightSidePanel { /* .viewerRightSidePanel {
width: 300px; width: 300px;