| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- <template>
- <el-dialog
- :visible.sync="dialogVisible"
- custom-class="c-dialog--transparent lg"
- :close-on-click-modal="false"
- append-to-body
- @open="onOpen"
- @close="onClose"
- @closed="onClosed"
- >
- <template v-if="contentRender">
- <auto-image
- v-if="isImage"
- class="o-preview u-font-size--3xl"
- :src="assetUrl"
- retry
- />
- <video
- v-if="isVideo"
- class="o-preview"
- :src="assetUrl"
- autoplay
- controls
- controlslist="nodownload noremoteplayback"
- />
- <audio
- v-if="isAudio"
- :src="assetUrl"
- autoplay
- controls
- controlslist="nodownload noremoteplayback"
- />
- <video
- v-if="isStreamingMedia"
- ref="streamingMediaPlayer"
- class="o-preview"
- autoplay
- controls
- />
- <i
- class="o-close el-icon-close has-active u-bold"
- @click="hide"
- />
- <template v-if="isMultipleFiles">
- <i
- class="o-arrow o-icon el-icon-arrow-left has-active u-bold"
- @click="onPresent"
- />
- <i
- class="o-arrow o-icon el-icon-arrow-right has-active u-bold"
- @click="onNext"
- />
- <div class="o-total">
- {{ active + 1 }}/{{ total }}
- </div>
- </template>
- </template>
- </el-dialog>
- </template>
- <script>
- import HlsJs from 'hls.js'
- import { AssetType } from '@/constant'
- import { getAssetUrl } from '@/api/asset'
- import dialogMixin from '@/mixins/dialog'
- const isSupported = HlsJs.isSupported()
- const isHttps = location.protocol === 'https:'
- export default {
- name: 'PreviewDialog',
- mixins: [dialogMixin],
- data () {
- return {
- isMultipleFiles: false,
- total: 0,
- active: 0,
- source: null
- }
- },
- computed: {
- fileType () {
- return this.source?.type
- },
- isImage () {
- return this.fileType === AssetType.IMAGE
- },
- isVideo () {
- return this.fileType === AssetType.VIDEO
- },
- isAudio () {
- return this.fileType === AssetType.AUDIO
- },
- isStreamingMedia () {
- return this.fileType === AssetType.STREAMING_MEDIA
- },
- assetUrl () {
- console.log('assetUrl---:', this.source && getAssetUrl(this.source.url))
- return this.source && getAssetUrl(this.source.url)
- }
- },
- beforeDestroy () {
- this.onClose()
- },
- methods: {
- show (source) {
- if (!source) {
- return
- }
- this.$sources = source.files?.length
- ? source.files.map(({ type, keyName }) => {
- return { type, url: keyName }
- })
- : [source]
- this.isMultipleFiles = this.$sources.length > 1
- this.total = this.$sources.length
- this.active = 0
- this.source = this.$sources[this.active]
- this.dialogVisible = true
- console.log('source::', this.$sources)
- },
- onOpen () {
- this.contentRender = true
- if (this.isStreamingMedia) {
- this.$nextTick(() => {
- this.playStreamingMedia()
- })
- }
- },
- onClose () {
- if (this.hlsjs) {
- this.hlsjs.destroy()
- this.hlsjs = null
- }
- },
- onPresent () {
- this.active = (this.active - 1 + this.total) % this.total
- this.source = this.$sources[this.active]
- },
- onNext () {
- this.active = (this.active + 1) % this.total
- this.source = this.$sources[this.active]
- },
- playStreamingMedia () {
- const url = isHttps ? this.source.url.replace(/^http:/, '') : this.source.url
- if (this.$refs.streamingMediaPlayer.canPlayType('application/vnd.apple.mpegurl')) {
- this.$refs.streamingMediaPlayer.src = url
- } if (isSupported) {
- if (!this.hlsjs) {
- this.hlsjs = new HlsJs()
- this.hlsjs.attachMedia(this.$refs.streamingMediaPlayer)
- this.hlsjs.on(HlsJs.Events.MANIFEST_PARSED, () => {
- this.$refs.streamingMediaPlayer.play()
- })
- this.hlsjs.on(HlsJs.Events.ERROR, e => {
- console.log('error', e)
- })
- }
- this.hlsjs.loadSource(url)
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .o-preview {
- max-width: 100%;
- max-height: 100%;
- color: #fff;
- line-height: 0;
- }
- .o-close {
- position: absolute;
- top: 0;
- right: 0;
- padding: $padding--md $padding--lg;
- color: #fff;
- font-size: $font-size--xl;
- transform: translateY(-100%);
- }
- .o-arrow {
- position: absolute;
- color: #fff;
- top: 50%;
- &.el-icon-arrow-left {
- left: 0;
- transform: translate(-100%, -50%);
- }
- &.el-icon-arrow-right {
- right: 0;
- transform: translate(100%, -50%);
- }
- }
- .o-total {
- position: absolute;
- left: 50%;
- bottom: -$font-size--xl * 2;
- color: #fff;
- font-size: $font-size--xl;
- transform: translateX(-50%);
- }
- </style>
|