wangzhibo
2026-07-28 fa9b89139f34809b7bf01ca2052fbaa3d1ea64e6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<template>
    <div class="viewer-image">
        <!-- 图片 -->
        <el-image-viewer v-if="img.visible" :url-list="[img.url]" infinite teleported @close="close" />
    </div>
 
    <!-- 文档 -->
    <cl-dialog v-model="doc.visible" :title="$t('文档预览')" height="70vh" width="80%" :scrollbar="false">
        <div v-loading="doc.loading" class="viewer-doc">
            <iframe :ref="setRefs('docIframe')" :src="doc.url" />
        </div>
    </cl-dialog>
</template>
 
<script lang="ts" setup>
defineOptions({
    name: 'file-viewer'
});
 
import { reactive, nextTick } from 'vue';
import { getType } from '../../utils';
import { useCool } from '/@/cool';
 
const { refs, setRefs } = useCool();
 
// 图片预览
const img = reactive({
    visible: false,
    url: ''
});
 
// 文档预览
const doc = reactive({
    visible: false,
    loading: false,
    url: ''
});
 
// 打开
function open(item: Upload.Item) {
    if (item?.type) {
        // 链接
        const url = item.url || '';
 
        // 类型
        const type = getType(url);
 
        // 图片预览
        if (type == 'image') {
            img.visible = true;
            img.url = url;
 
            return true;
        }
 
        if (type === 'pdf') {
            doc.visible = true;
            doc.loading = true;
            // pdf.js viewer 路径(放在 public/pdfjs/)
            doc.url = `/pdfjs/web/viewer.html?file=${encodeURIComponent(url)}`;
 
            nextTick(() => {
                refs.docIframe.onload = () => {
                    doc.loading = false;
                };
            });
 
            return true;
        }
 
        // 文档预览
        if (['word', 'excel', 'ppt'].includes(type)) {
            doc.visible = true;
            doc.loading = true;
            doc.url = `https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)}`;
 
            nextTick(() => {
                refs.docIframe.onload = () => {
                    doc.loading = false;
                };
            });
 
            return true;
        }
 
        window.open(item.url);
    }
}
 
// 关闭
function close() {
    img.visible = false;
}
 
defineExpose({
    open
});
</script>
 
<style lang="scss" scoped>
.viewer-image {
    position: absolute;
}
 
.viewer-doc {
    height: 100%;
    width: 100%;
 
    iframe {
        border: 0;
        height: 100%;
        width: 100%;
    }
}
</style>