353 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			353 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Plaintext
		
	
	
<template>
 | 
						|
  <div class="preview-wrapper">
 | 
						|
 | 
						|
    <div class="image-viewer-wrapper">
 | 
						|
      <!-- 预览图像 -->
 | 
						|
      <NoneDicomsCanvas
 | 
						|
        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"
 | 
						|
        :study-id="previewImage.studyId"
 | 
						|
        :reading-task-state="readingTaskState"
 | 
						|
      />
 | 
						|
    </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="`${OSSclientConfig.basePath + 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 NoneDicomsCanvas from './NoneDicomsCanvas'
 | 
						|
export default {
 | 
						|
  name: 'NoneDicomsViewer',
 | 
						|
  components: {
 | 
						|
    NoneDicomsCanvas
 | 
						|
  },
 | 
						|
  props: {
 | 
						|
    readingTaskState: {
 | 
						|
      type: Number,
 | 
						|
      default: 2
 | 
						|
    },
 | 
						|
    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: '',
 | 
						|
          studyId: ''
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  },
 | 
						|
  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" scoped>
 | 
						|
.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>
 |