| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- <template>
- <div class="file-preview-panel">
- <div class="panel-header">
- <span class="panel-title">{{ file.name }}</span>
- <div class="close-btn" @click="emit('close')">
- <div class="btn-close-icon"></div>
- </div>
- </div>
- <div class="panel-content file-preview-content">
- <div v-if="isImageFile(file.name)" class="image-preview">
- <img :src="file.preview" alt="预览图片" />
- </div>
- <div v-else-if="isPdfFile(file.name)" class="pdf-preview">
- <iframe v-if="file.preview" :src="file.preview" frameborder="0"></iframe>
- <div v-else class="no-preview-text">无法加载PDF预览</div>
- </div>
- <div v-else-if="isVideoFile(file.name)" class="video-preview">
- <video v-if="file.preview" controls>
- <source :src="file.preview" />
- 您的浏览器不支持视频预览
- </video>
- <div v-else class="no-preview-text">无法加载视频预览</div>
- </div>
- <div v-else-if="isAudioFile(file.name)" class="audio-preview">
- <div class="audio-info">
- <div class="audio-icon"></div>
- <span class="audio-name">{{ file.name }}</span>
- </div>
- <audio v-if="file.preview" controls>
- <source :src="file.preview" />
- 您的浏览器不支持音频预览
- </audio>
- <div v-else class="no-preview-text">无法加载音频预览</div>
- </div>
- <div v-else-if="isTextFile(file.name)" class="text-preview">
- <pre>{{ file.content || '文件内容加载中...' }}</pre>
- </div>
- <div v-else class="no-preview">
- <div class="no-preview-icon"></div>
- <div class="no-preview-text">不支持预览此文件格式</div>
- <div class="no-preview-hint">{{ getFileExtension(file.name) }} 格式文件暂不支持在线预览</div>
- </div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { isImageFile, isPdfFile, isVideoFile, isAudioFile, isTextFile, getFileExtension } from './utils';
- import type { AttachedFile } from './types';
- defineProps<{
- file: AttachedFile;
- }>();
- const emit = defineEmits<{
- (e: 'close'): void;
- }>();
- </script>
- <style scoped lang="less">
- .file-preview-panel {
- height: 100%;
- display: flex;
- flex-direction: column;
- }
- .panel-header {
- padding: 10px 10px 5px 10px;
- display: flex;
- justify-content: space-between;
- align-items: center;
- flex-shrink: 0;
- .panel-title {
- font-size: 15px;
- font-weight: 600;
- line-height: 1.4;
- color: #e0e6ed;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- flex: 1;
- margin-right: 10px;
- }
- .close-btn {
- cursor: pointer;
- width: 36px;
- height: 36px;
- background-image: var(--img-chat-close-bg);
- background-repeat: no-repeat;
- background-size: 100% 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
- transition: all 0.3s;
- margin-bottom: auto;
- .btn-close-icon {
- width: 20px;
- height: 20px;
- background-image: var(--img-chat-minimize-icon);
- background-repeat: no-repeat;
- background-size: 100% 100%;
- }
- }
- }
- .panel-content {
- flex: 1;
- overflow-y: auto;
- padding: 16px;
- }
- .file-preview-content {
- height: 100%;
- .image-preview {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- img {
- width: 100%;
- height: 100%;
- object-fit: contain;
- border-radius: 4px;
- }
- }
- .pdf-preview {
- width: 100%;
- height: 100%;
- iframe {
- width: 100%;
- height: 100%;
- border: none;
- }
- }
- .video-preview {
- width: 100%;
- height: 100%;
- display: flex;
- align-items: center;
- justify-content: center;
- video {
- width: 100%;
- max-height: 100%;
- border-radius: 4px;
- }
- }
- .audio-preview {
- width: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 16px;
- padding: 20px 0;
- .audio-info {
- display: flex;
- align-items: center;
- gap: 10px;
- .audio-icon {
- width: 40px;
- height: 40px;
- background-image: var(--img-chat-attach-icon);
- background-repeat: no-repeat;
- background-size: 100% 100%;
- }
- .audio-name {
- font-size: 14px;
- color: #e0e6ed;
- }
- }
- audio {
- width: 100%;
- }
- }
- .text-preview {
- pre {
- white-space: pre-wrap;
- word-wrap: break-word;
- font-family: monospace;
- font-size: 13px;
- color: #e0e6ed;
- }
- }
- .no-preview {
- display: flex;
- flex-direction: column;
- align-items: center;
- justify-content: center;
- height: 100%;
- gap: 12px;
- .no-preview-icon {
- width: 64px;
- height: 64px;
- background-image: var(--img-chat-attach-icon);
- background-repeat: no-repeat;
- background-size: 100% 100%;
- opacity: 0.4;
- }
- }
- .no-preview-text {
- color: #8b949e;
- font-size: 14px;
- }
- .no-preview-hint {
- color: #6e7681;
- font-size: 12px;
- }
- }
- </style>
|