|
@@ -0,0 +1,181 @@
|
|
|
|
|
+<template>
|
|
|
|
|
+ <div class="watcher_file"
|
|
|
|
|
+ :style="height ? {minHeight:height, height: height} : ''">
|
|
|
|
|
+ <div v-if="filePreviewList.includes(previewType)"
|
|
|
|
|
+ class="preview_item"
|
|
|
|
|
+ :style="filePadding"
|
|
|
|
|
+ >
|
|
|
|
|
+ <img
|
|
|
|
|
+ @click="HandleImgPreview"
|
|
|
|
|
+ style="text-align: center;"
|
|
|
|
|
+ v-if="['jpg','png','jpeg','gif','svg','webp'].includes(previewType)"
|
|
|
|
|
+ :src="fileMessage ? fileMessage.url : ''"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div style="text-align: center;" v-else-if="previewType == '加载中'">加载中...</div>
|
|
|
|
|
+ <div style="text-align: center;" v-else>不支持预览 .{{ previewType }}文件</div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 注意:Vue 2 中 el-image-viewer 的关闭事件可能是 'close',具体依 ElementUI 版本而定 -->
|
|
|
|
|
+ <el-image-viewer
|
|
|
|
|
+ v-if="imgVisible"
|
|
|
|
|
+ :url-list="[fileMessage ? fileMessage.url : '']"
|
|
|
|
|
+ show-progress
|
|
|
|
|
+ @close="imgVisible = false"
|
|
|
|
|
+ />
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 页面指示器 -->
|
|
|
|
|
+ <div class="nav_group" v-if="navTotalPage && navTotalPage > 0" :style="{...navBarWidth, ...navBarLeft}">
|
|
|
|
|
+ <span
|
|
|
|
|
+ :class="['pre_nav', {'first': currentNavPage === 1}]"
|
|
|
|
|
+ @click="currentNavPage == 1 ? '' : HandlePageJump('reduce')"
|
|
|
|
|
+ >
|
|
|
|
|
+ <i class="el-icon-arrow-left"></i> <!-- Vue2 常用图标替代 -->
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span
|
|
|
|
|
+ :class="['next_nav', {'end': currentNavPage === navTotalPage}]"
|
|
|
|
|
+ @click="currentNavPage === navTotalPage ? '' : HandlePageJump('add')"
|
|
|
|
|
+ >
|
|
|
|
|
+ <i class="el-icon-arrow-right"></i>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
+
|
|
|
|
|
+<script>
|
|
|
|
|
+
|
|
|
|
|
+// interface FileMsg {
|
|
|
|
|
+// name:String,
|
|
|
|
|
+// url:String
|
|
|
|
|
+// }
|
|
|
|
|
+
|
|
|
|
|
+export default {
|
|
|
|
|
+ name: 'ImageJumpPreview',
|
|
|
|
|
+ // 1. 将 defineModel 的 prop 提取到这里,父组件需使用 :current-nav-page.sync="xxx"
|
|
|
|
|
+ props: {
|
|
|
|
|
+ fileMessage: {
|
|
|
|
|
+ required: true,
|
|
|
|
|
+ type: Object
|
|
|
|
|
+ },
|
|
|
|
|
+ height: {
|
|
|
|
|
+ type: String,
|
|
|
|
|
+ default: ''
|
|
|
|
|
+ },
|
|
|
|
|
+ filePadding: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ default: () => ({})
|
|
|
|
|
+ },
|
|
|
|
|
+ navBarWidth: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ default: () => ({})
|
|
|
|
|
+ },
|
|
|
|
|
+ navBarLeft: {
|
|
|
|
|
+ type: Object,
|
|
|
|
|
+ default: () => ({})
|
|
|
|
|
+ },
|
|
|
|
|
+ navTotalPage: {
|
|
|
|
|
+ type: Number,
|
|
|
|
|
+ default: 0
|
|
|
|
|
+ },
|
|
|
|
|
+ // 对应原 Vue3 中的 defineModel('currentNavPage')
|
|
|
|
|
+ currentNavPage: {
|
|
|
|
|
+ type: Number,
|
|
|
|
|
+ default: 1
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 2. 将 ref 转换为 data
|
|
|
|
|
+ data() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ filePreviewList: ['pptx','pdf','gif','jpeg','jpg','png','svg','webp','xlsx','docx','mp4','avi','mpg','mpeg','wmv','mkv','mov','flv'],
|
|
|
|
|
+ imgVisible: false,
|
|
|
|
|
+ previewType: '加载中'
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 3. 将 watch 转换为选项式侦听器
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ fileMessage: {
|
|
|
|
|
+ handler(newVal) {
|
|
|
|
|
+ if (newVal && newVal.name) {
|
|
|
|
|
+ let suffixName = newVal.name.split('.').pop();
|
|
|
|
|
+ if (suffixName) {
|
|
|
|
|
+ this.previewType = suffixName;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ immediate: true, // 建议加上 immediate,确保初始化时也能解析类型
|
|
|
|
|
+ deep: true
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ methods: {
|
|
|
|
|
+ HandleImgPreview() {
|
|
|
|
|
+ this.imgVisible = true;
|
|
|
|
|
+ },
|
|
|
|
|
+ async HandlePageJump(type) {
|
|
|
|
|
+ let newPage = this.currentNavPage;
|
|
|
|
|
+ switch(type) {
|
|
|
|
|
+ case 'add':
|
|
|
|
|
+ newPage += 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'reduce':
|
|
|
|
|
+ newPage -= 1;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 触发 .sync 更新
|
|
|
|
|
+ this.$emit('update:currentNavPage', newPage);
|
|
|
|
|
+
|
|
|
|
|
+ // 等待 DOM 更新后触发业务事件
|
|
|
|
|
+ await this.$nextTick();
|
|
|
|
|
+ this.$emit('imgNavChange', newPage);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="scss" scoped>
|
|
|
|
|
+.watcher_file{
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ min-height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.nav_group{
|
|
|
|
|
+ position: absolute;
|
|
|
|
|
+ width: calc(100% - 40px - 50px);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ bottom: 50%;
|
|
|
|
|
+ left: 40px;
|
|
|
|
|
+
|
|
|
|
|
+ .pre_nav,
|
|
|
|
|
+ .next_nav{
|
|
|
|
|
+ line-height: 1;
|
|
|
|
|
+ border-radius: 20px;
|
|
|
|
|
+ padding: 10px;
|
|
|
|
|
+ background-color: #415058;
|
|
|
|
|
+ color: white;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+ .first,
|
|
|
|
|
+ .end{
|
|
|
|
|
+ background-color: #c3c8d0;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.preview_item{
|
|
|
|
|
+ min-height: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+
|
|
|
|
|
+ img{
|
|
|
|
|
+ max-height: 100%;
|
|
|
|
|
+ max-width: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .preview_main{
|
|
|
|
|
+ position: relative;
|
|
|
|
|
+ min-height: 100%;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|