346 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
| <template>
 | |
|   <div class="none-dicom_preview-wrapper">
 | |
| 
 | |
|     <div class="image-viewer-wrapper">
 | |
|       <!-- 预览图像 -->
 | |
|       <ImageViewer
 | |
|         v-if="previewVisible"
 | |
|         :on-switch="
 | |
|           (index) => {
 | |
|             selected(index)
 | |
|           }
 | |
|         "
 | |
|         :initial-index="previewImage.index"
 | |
|         :url-list="previewImage.imgList"
 | |
|         :study-code="previewImage.studyCode"
 | |
|         :body-part="previewImage.bodyPart"
 | |
|         :modality="previewImage.modality"
 | |
|       />
 | |
|     </div>
 | |
|     <div class="thumbnail-wrapper" style="z-index:999;background-color:#fff;">
 | |
|       <div class="">
 | |
|         <div class="img-wrapper">
 | |
|           <el-button
 | |
|             icon="el-icon-d-arrow-left"
 | |
|             plain
 | |
|             class="left to"
 | |
|             :disabled="disabledPrev"
 | |
|             @click="toRight"
 | |
|           />
 | |
|           <div ref="imagesWrapper" class="images">
 | |
|             <div v-if="noData" class="empty-text">
 | |
|               <slot name="empty">暂无数据</slot>
 | |
|             </div>
 | |
|             <div v-show="!noData" class="items" :style="itemsStyle">
 | |
|               <div
 | |
|                 v-for="(item, index) in previewImage.imgList"
 | |
|                 :key="index"
 | |
|                 class="item-img"
 | |
|                 :style="imgSize"
 | |
|                 :class="{
 | |
|                   'is-active': index === currentIndex
 | |
|                 }"
 | |
|                 @click="selected(index)"
 | |
|               >
 | |
|                 <img :title="item.FileName" :src="`/api/${item.PreviewPath}`">
 | |
|                 <p v-if="item.FileName" class="item-date">
 | |
|                   {{ `${index+1}` }}
 | |
|                 </p>
 | |
|               </div>
 | |
|             </div>
 | |
|           </div>
 | |
|           <el-button
 | |
|             icon="el-icon-d-arrow-right"
 | |
|             :disabled="disabledNext"
 | |
|             plain
 | |
|             class="right to"
 | |
|             @click="Left"
 | |
|           />
 | |
|         </div>
 | |
|       </div>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| <script>
 | |
| import ImageViewer from './image-viewer'
 | |
| export default {
 | |
|   name: 'Preview',
 | |
|   components: {
 | |
|     ImageViewer
 | |
|   },
 | |
|   props: {
 | |
|     imgSize: {
 | |
|       type: Object,
 | |
|       default: () => {
 | |
|         return {
 | |
|           width: '120px',
 | |
|           height: '120px'
 | |
|         }
 | |
|       }
 | |
|     },
 | |
|     value: {
 | |
|       type: Number,
 | |
|       default: null
 | |
|     },
 | |
|     previewImage: {
 | |
|       type: Object,
 | |
|       default: () => {
 | |
|         return {
 | |
|           // 所有图片数组
 | |
|           imgList: [],
 | |
|           index: 0, // 当前点击的图片的索引
 | |
|           infinite: true, // 是否可以循环切换
 | |
|           studyCode: '',
 | |
|           modality: '',
 | |
|           bodyPart: ''
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       currentIndex: 0,
 | |
|       previewVisible: true,
 | |
|       translateX: 0,
 | |
|       pageSize: 0, // 一页展示的图片数
 | |
|       urlList: []
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     // 偏移度数
 | |
|     itemsStyle() {
 | |
|       return {
 | |
|         transform: `translateX(${-this.translateX}px)`
 | |
|       }
 | |
|     },
 | |
|     // 每一项宽度
 | |
|     itemWidth() {
 | |
|       return parseInt(this.imgSize.width.replace('px', '')) + 8
 | |
|     },
 | |
|     disabledPrev() {
 | |
|       // 禁用前一页按钮
 | |
|       return this.translateX <= 0
 | |
|     },
 | |
|     disabledNext() {
 | |
|       // 禁用后一页按钮
 | |
|       return (
 | |
|         this.translateX >= (this.previewImage.imgList.length - this.pageSize) * this.itemWidth
 | |
|       )
 | |
|     },
 | |
|     noData() {
 | |
|       return this.previewImage.imgList.length === 0
 | |
|     },
 | |
|     dataLength() {
 | |
|       return this.previewImage.imgList.length
 | |
|     }
 | |
| 
 | |
|   },
 | |
|   watch: {
 | |
|     value: {
 | |
|       immediate: true,
 | |
|       handler(val) {
 | |
|         this.currentIndex = val
 | |
|       }
 | |
|     },
 | |
|     'previewImage.index': {
 | |
|       immediate: true,
 | |
|       handler(val) {
 | |
|         this.urlList.index = val
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   mounted() {
 | |
|     this.pageSize = this.wrapperWidth() / this.itemWidth
 | |
|     this.urlList = this.previewImage
 | |
|     const scope = this
 | |
|     window.onresize = function() {
 | |
|       scope.pageSize = scope.wrapperWidth() / scope.itemWidth
 | |
|       scope.selected(scope.currentIndex)
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     toRight() {
 | |
|       if (this.translateX < this.pageSize * this.itemWidth) {
 | |
|         this.translateX = 0
 | |
|       } else {
 | |
|         this.translateX = this.translateX - this.pageSize * this.itemWidth
 | |
|       }
 | |
|     },
 | |
|     Left() {
 | |
|       this.translateX = this.translateX + this.pageSize * this.itemWidth
 | |
|       const maxTrans = this.itemWidth * (this.dataLength - this.pageSize)
 | |
|       if (this.translateX > maxTrans) {
 | |
|         this.translateX = maxTrans
 | |
|       }
 | |
|     },
 | |
|     selected(index) {
 | |
|       const center = this.pageSize >> 1
 | |
|       // 最后一页的中间位置
 | |
|       const lastCenter = this.dataLength - center
 | |
| 
 | |
|       if (index > center && index < lastCenter) {
 | |
|         // 与相册中间相差的图片数量
 | |
|         const step = index - center
 | |
|         // 将点击图片移动到中间
 | |
|         this.translateX = this.itemWidth * step
 | |
|       } else {
 | |
|         const maxTrans = this.itemWidth * (this.dataLength - this.pageSize)
 | |
|         this.translateX = index <= center ? 0 : maxTrans
 | |
|       }
 | |
|       if (this.currentIndex !== index) {
 | |
|         this.currentIndex = index
 | |
|       }
 | |
|       this.$emit('selectedImg', index)
 | |
|     },
 | |
|     wrapperWidth() {
 | |
|       if (this.$refs.imagesWrapper) {
 | |
|         return this.$refs.imagesWrapper.offsetWidth
 | |
|       }
 | |
|       return 0
 | |
|     }
 | |
| 
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss">
 | |
| .none-dicom_preview-wrapper{
 | |
|   width: 100%;
 | |
|   height: 100%;
 | |
|   display: flex;
 | |
|   flex-direction: column;
 | |
| 
 | |
| .image-viewer-wrapper{
 | |
|   flex: 1;
 | |
| }
 | |
| .thumbnail-wrapper{
 | |
|   height: 130px;
 | |
| }
 | |
| .img-content{
 | |
|   position: absolute;
 | |
|   left: 0;
 | |
|   bottom: 10px;
 | |
|   width: 100%;
 | |
| }
 | |
| .img-wrapper {
 | |
|   display: flex;
 | |
|   position: relative;
 | |
|   margin: 0 20px;
 | |
|   height: 120px;
 | |
|   .to {
 | |
|     width: 32px;
 | |
|     height: 100%;
 | |
|     padding: 0;
 | |
|   }
 | |
|   .images::before {
 | |
|     position: absolute;
 | |
|     z-index: 5;
 | |
|     top: 0;
 | |
|     height: 100%;
 | |
|     width: 84px;
 | |
|     content: '';
 | |
|     pointer-events: none;
 | |
|     background: -webkit-gradient(
 | |
|       linear,
 | |
|       left top,
 | |
|       right top,
 | |
|       from(#fff),
 | |
|       color-stop(50%, rgba(0, 0, 0, 0))
 | |
|     );
 | |
|     background: -o-linear-gradient(left, #fff, rgba(0, 0, 0, 0) 50%);
 | |
|     background: linear-gradient(90deg, #fff, rgba(0, 0, 0, 0) 50%);
 | |
|   }
 | |
|   .images::after {
 | |
|     position: absolute;
 | |
|     z-index: 5;
 | |
|     top: 0;
 | |
|     height: 100%;
 | |
|     right: 0;
 | |
|     width: 84px;
 | |
|     content: '';
 | |
|     pointer-events: none;
 | |
|     background: -webkit-gradient(
 | |
|       linear,
 | |
|       right top,
 | |
|       left top,
 | |
|       from(#fff),
 | |
|       color-stop(50%, rgba(0, 0, 0, 0))
 | |
|     );
 | |
|     background: -o-linear-gradient(right, #fff, rgba(0, 0, 0, 0) 50%);
 | |
|     background: linear-gradient(270deg, #fff, rgba(0, 0, 0, 0) 50%);
 | |
|   }
 | |
|   .images {
 | |
|     position: relative;
 | |
|     overflow: hidden;
 | |
|     width: 100%;
 | |
|     height: 100%;
 | |
|     margin: 0 2px;
 | |
|     .empty-text {
 | |
|       color: rgb(158, 158, 158);
 | |
|       height: 100%;
 | |
|       display: flex;
 | |
|       align-items: center;
 | |
|       justify-content: center;
 | |
|     }
 | |
|     .items {
 | |
|       position: absolute;
 | |
|       top: 0;
 | |
|       left: 0;
 | |
|       display: flex;
 | |
|       // width: 6000px;
 | |
|       height: 100%;
 | |
|       align-items: center;
 | |
|       transition: transform 0.25s ease;
 | |
|       .item-img {
 | |
|         display: inline-block;
 | |
|         box-sizing: border-box;
 | |
|         position: relative;
 | |
|         margin-right: 8px;
 | |
|         border: 2px solid rgba(0, 0, 0, 0);
 | |
|         cursor: pointer;
 | |
|         .item-date {
 | |
|           bottom: 0px;
 | |
|           position: absolute;
 | |
|           width: 100%;
 | |
|           height: 24px;
 | |
|           background: rgba(0, 0, 0, 0.2);
 | |
|           text-align: center;
 | |
|           line-height: 24px;
 | |
|           color: white;
 | |
|         }
 | |
|         img {
 | |
|           width: 100%;
 | |
|           height: 100%;
 | |
|         }
 | |
|       }
 | |
|       .item-img:hover::after {
 | |
|         // border-color: #409EFF;
 | |
|         opacity: 0;
 | |
|       }
 | |
|       .item-img::after {
 | |
|         position: absolute;
 | |
|         top: 0;
 | |
|         left: 0;
 | |
|         width: 100%;
 | |
|         height: 100%;
 | |
|         content: '';
 | |
|         opacity: 0.2;
 | |
|         pointer-events: none;
 | |
|         -webkit-transition: opacity 0.3s ease;
 | |
|         -o-transition: opacity 0.3s ease;
 | |
|         transition: opacity 0.3s ease;
 | |
|         background-color: #fff;
 | |
|       }
 | |
|       .is-active {
 | |
|         border-color: #409eff;
 | |
|       }
 | |
|       .is-active:after {
 | |
|         opacity: 0;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| }
 | |
| </style>
 |