280 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			280 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			Plaintext
		
	
	
| <template>
 | |
|   <div ref="preview-wrapper">
 | |
|     <div class="viewerContainer">
 | |
|       <div class="viewerContentWrapper" style="padding-top:25px;">
 | |
|         <div class="viewerLeftSidePanel">
 | |
|           <div id="listWrapper" class="sidePanelBody">
 | |
|             <div class="sidePanelThumbs">
 | |
|               <!-- <div class="studyDesc" style="border-bottom:1px solid #9e9e9e;" @click="closeDialog()">
 | |
|               <span style="font-size:14px;color:#d0d0d0;margin:5px 0px;line-height: 25px;">返回列表</span>
 | |
|             </div> -->
 | |
|               <div class="studyDesc" style="line-height: 10px;">
 | |
|                 {{ studyTitle }}
 | |
|               </div>
 | |
|               <div class="studyDesc" style="line-height: 10px">
 | |
|                 {{ seriesCount }} Series
 | |
|               </div>
 | |
|               <div class="viewerSidethumbs ps" style="position: relative;">
 | |
|                 <div class="viewerSidethumbinner">
 | |
|                   <div
 | |
|                     v-for="(item, index) in seriesList"
 | |
|                     :key="index"
 | |
|                     :class="{'viewerSideActive': index==currentSeriesIndex}"
 | |
|                     class="viewernavigatorwrapper"
 | |
|                     @click="showSeriesImage(index)"
 | |
|                   >
 | |
|                     <dicomPreview
 | |
|                       :image-id="item.previewImageId"
 | |
|                       class="image-preview"
 | |
|                       style="height:72px;width:72px;display: inline-block"
 | |
|                     />
 | |
|                     <!-- <span class="viewernavitextwrapper" title>
 | |
|                     <span class="viewernavitexttxt">
 | |
|                       <span>{{ item.seriesTitle }}</span>
 | |
|                     </span>
 | |
|                     <span class="viewernavitextnum">
 | |
|                       {{ item.instanceCount }} image
 | |
| 
 | |
|                     </span>
 | |
|                   </span>-->
 | |
|                     <div class="viewernavitextwrapper">
 | |
|                       <div style="padding: 1px;">#{{ item.seriesTitle }}</div>
 | |
|                       <div
 | |
|                         v-show="item.instanceCount"
 | |
|                         style="padding: 1px;"
 | |
|                       >{{ item.instanceCount }} image</div>
 | |
|                     </div>
 | |
|                   </div>
 | |
|                 </div>
 | |
|               </div>
 | |
|             </div>
 | |
|           </div>
 | |
|         </div>
 | |
|         <div class="viewerContent">
 | |
|           <dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" />
 | |
|         </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 dicomStore from '@/utils/dicom-store.js'
 | |
| import dicomViewer from '@/components/Dicom/DicomViewer'
 | |
| import dicomPreview from '@/components/Dicom/DicomPreview'
 | |
| 
 | |
| cornerstoneWADOImageLoader.external.dicomParser = dicomParser
 | |
| cornerstoneWADOImageLoader.external.cornerstone = cornerstone
 | |
| // cornerstoneWADOImageLoader.webWorkerManager.initialize({
 | |
| //   webWorkerPath: './webWorker.js',
 | |
| //   taskConfiguration: {
 | |
| //     decodeTask: {
 | |
| //       codecsPath: './dicomCodecs.js'
 | |
| //     }
 | |
| //   }
 | |
| // })
 | |
| export default {
 | |
|   components: {
 | |
|     dicomViewer,
 | |
|     dicomPreview
 | |
|   },
 | |
|   props: {
 | |
|     uid: {
 | |
|       type: String,
 | |
|       default: ''
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   data() {
 | |
|     return {
 | |
|       studyTitle: '',
 | |
|       seriesCount: 0,
 | |
|       seriesList: [],
 | |
|       currentSeriesIndex: -1
 | |
|     }
 | |
|   },
 | |
| 
 | |
|   mounted() {
 | |
|     var totalHeight = window.innerHeight || document.body.clientHeight
 | |
|     var wrapper = this.$refs['preview-wrapper']
 | |
|     wrapper.style.height = (totalHeight - 70) + 'px'
 | |
|     if (!dicomStore.studyList || !this.uid) return
 | |
|     this.loadStudy()
 | |
|   },
 | |
| 
 | |
|   methods: {
 | |
|     loadStudy() {
 | |
|       var studyList = dicomStore.studyList
 | |
|       var studyUid = this.uid
 | |
|       var studyItem = studyList.find(function(item) {
 | |
|         return item.dicomInfo.studyUid === studyUid
 | |
|       })
 | |
|       if (!studyItem) return
 | |
| 
 | |
|       this.studyTitle =
 | |
|         studyItem.dicomInfo.patientName || studyItem.dicomInfo.description
 | |
|       this.seriesCount = studyItem.seriesList.length
 | |
|       var scope = this
 | |
| 
 | |
|       studyItem.seriesList.forEach(function(series) {
 | |
|         series.instanceList.sort(function(item1, item2) {
 | |
|           return item1.instanceNumber - item2.instanceNumber
 | |
|         })
 | |
| 
 | |
|         var imageIds = []
 | |
|         series.instanceList.forEach(function(instance) {
 | |
|           var fileId = cornerstoneWADOImageLoader.wadouri.fileManager.add(
 | |
|             instance.file
 | |
|           )
 | |
|           if (instance.frameCount > 1) {
 | |
|             for (var i = 0; i < instance.frameCount; ++i) {
 | |
|               imageIds.push(`${fileId}?frame=${i + 1}`)
 | |
|             }
 | |
|           } else imageIds.push(fileId)
 | |
|         })
 | |
| 
 | |
|         scope.seriesList.push({
 | |
|           seriesNumber: series.seriesNumber,
 | |
|           seriesTitle: series.description || series.modality || '(Anonymous)',
 | |
|           instanceCount: series.instanceList.length,
 | |
|           imageIds: imageIds,
 | |
|           previewImageId: imageIds[0]
 | |
|         })
 | |
|       })
 | |
| 
 | |
|       this.showSeriesImage(0)
 | |
|     },
 | |
| 
 | |
|     showSeriesImage(seriesIndex) {
 | |
|       // if (seriesIndex === this.currentSeriesIndex) return;
 | |
|       this.currentSeriesIndex = seriesIndex
 | |
|       this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
 | |
|     },
 | |
|     closeDialog() {
 | |
|       this.$emit('closeInnerDialog')
 | |
|     }
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style scoped>
 | |
| ::-webkit-scrollbar {
 | |
|   width: 7px;
 | |
|   height: 7px;
 | |
| }
 | |
| ::-webkit-scrollbar-thumb {
 | |
|   border-radius: 10px;
 | |
|   background: #d0d0d0;
 | |
| }
 | |
| .viewerContainer {
 | |
|   display: block;
 | |
|     height: 100%;
 | |
|      margin-top: 20px;
 | |
|     margin-left: auto;
 | |
|     margin-right: auto;
 | |
|     background-color: #444;
 | |
|     overflow: hidden;
 | |
| }
 | |
| .viewerBanner {
 | |
|    background: linear-gradient(0,#444,#222);
 | |
|     min-height: 28px;
 | |
|     font-size: 16px;
 | |
|     margin: 0;
 | |
|     height: 30px;
 | |
|     padding-top: 0;
 | |
|     padding-left: 5px;
 | |
|     padding-right: 5px;
 | |
|     font-weight: bold;
 | |
| }
 | |
| .viewerContentWrapper {
 | |
|   display: flex;
 | |
|   flex-direction: row;
 | |
|   width: 100%;
 | |
|   padding: 5px;
 | |
|   height: 99%;
 | |
|   /* height: 95%; */
 | |
|   overflow: hidden;
 | |
|   text-overflow: clip;
 | |
|   white-space: nowrap;
 | |
| }
 | |
| .viewerContentWrapper > div {
 | |
|   display: inline-block;
 | |
|   white-space: normal;
 | |
| }
 | |
| .viewerLeftSidePanel {
 | |
|   width: 200px;
 | |
|   background-color: #323232;
 | |
|   box-sizing: border-box;
 | |
|   margin: 0;
 | |
|   padding: 0;
 | |
|   margin-right: 2px;
 | |
|   color: #d0d0d0;
 | |
|   overflow-y: auto;
 | |
| }
 | |
| .viewerContentWrapper > div > .sidePanelBody {
 | |
|   background: rgba(50, 50, 50, 1);
 | |
|   word-break: break-all;
 | |
|   display: table;
 | |
|   width: 100%;
 | |
|   border: 1px solid #3e3f3a;
 | |
| }
 | |
| .viewerContentWrapper > div > div.sidePanelBody > div {
 | |
|   width: 100%;
 | |
|   height: 100%;
 | |
| }
 | |
| .studyDesc {
 | |
|   font-weight: bold;
 | |
|   font-size: 13px;
 | |
|   text-align: center;
 | |
|   background: rgb(88 84 83);
 | |
|   color: #d0d0d0;
 | |
|   padding: 2px;
 | |
| }
 | |
| .ps {
 | |
|   overflow: hidden !important;
 | |
|   overflow-anchor: none;
 | |
|   -ms-overflow-style: none;
 | |
|   touch-action: auto;
 | |
|   -ms-touch-action: auto;
 | |
| }
 | |
| .viewerLeftSidePanel .viewernavigatorwrapper {
 | |
|   display: flex;
 | |
|   width: 196px;
 | |
|   height: 84px;
 | |
|   padding: 1px 2px 1px 8px;
 | |
|   margin: 6px 0 6px 1px;
 | |
|   border-radius: 2px;
 | |
|   border: 1px solid #404040;
 | |
| }
 | |
| .ui-draggable-handle {
 | |
|   -ms-touch-action: none;
 | |
|   touch-action: none;
 | |
| }
 | |
| .viewerLeftSidePanel .image-preview {
 | |
|   border: 2px solid #252525;
 | |
|   cursor: pointer;
 | |
| }
 | |
| .viewerLeftSidePanel .viewernavitextwrapper {
 | |
|   flex: 1;
 | |
|   padding: 3px 1px 3px 4px;
 | |
|   vertical-align: top;
 | |
|   font-size: 12px;
 | |
| }
 | |
| .viewerSideActive {
 | |
|   background: #16477b;
 | |
|   background: #16477b80;
 | |
|   border: 1px solid #23527b;
 | |
| }
 | |
| .viewerContent {
 | |
|   flex: 1;
 | |
|   height: 100%;
 | |
|   display: block;
 | |
|   background-color: black;
 | |
|   color: #d0d0d0;
 | |
|   font-size: 13px;
 | |
| }
 | |
| </style>
 |