2025-05-14 03:50:52 +00:00
|
|
|
<script setup>
|
2024-12-24 08:14:21 +00:00
|
|
|
import { fileFormatSize } from '@/utils/strings'
|
2025-05-14 03:50:52 +00:00
|
|
|
import { ref, computed } from 'vue'
|
2025-05-15 08:07:56 +00:00
|
|
|
import { useUploadsStore } from '@/store'
|
|
|
|
import pptText from '@/assets/image/ppt-text.png'
|
|
|
|
import excelText from '@/assets/image/excel-text.png'
|
|
|
|
import wordText from '@/assets/image/word-text.png'
|
|
|
|
import pdfText from '@/assets/image/pdf-text.png'
|
|
|
|
import fileText from '@/assets/image/file-text.png'
|
2025-05-21 11:57:07 +00:00
|
|
|
import { ArrowDownload16Filled } from '@vicons/fluent'
|
|
|
|
import { download } from '@/utils/functions.js'
|
2025-05-14 03:50:52 +00:00
|
|
|
// 定义组件属性
|
|
|
|
const props = defineProps({
|
|
|
|
// 文件的额外信息
|
|
|
|
extra: {
|
|
|
|
type: Object,
|
|
|
|
required: true
|
|
|
|
},
|
|
|
|
// 聊天记录数据
|
|
|
|
data: {
|
|
|
|
type: Object,
|
|
|
|
required: true
|
|
|
|
},
|
|
|
|
// 是否使用最大宽度
|
|
|
|
maxWidth: {
|
|
|
|
type: Boolean,
|
|
|
|
default: false
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2025-05-15 08:07:56 +00:00
|
|
|
const uploadsStore = useUploadsStore()
|
2025-05-14 03:50:52 +00:00
|
|
|
const isPlaying = ref(false)
|
|
|
|
|
2025-05-15 08:07:56 +00:00
|
|
|
// 文件类型配置
|
|
|
|
const fileTypes = {
|
|
|
|
PDF: { icon: pdfText, color: '#DE4E4E', type: 'PDF' },
|
|
|
|
PPT: { icon: pptText, color: '#B74B2B', type: 'PPT' },
|
|
|
|
EXCEL: { icon: excelText, color: '#3C7F4B', type: 'EXCEL' },
|
|
|
|
WORD: { icon: wordText, color: '#2750B2', type: 'WORD' },
|
|
|
|
DEFAULT: { icon: fileText, color: '#747474', type: '文件' }
|
|
|
|
}
|
|
|
|
|
|
|
|
// Excel文件扩展名映射
|
|
|
|
const EXCEL_EXTENSIONS = ['XLS', 'XLSX', 'CSV']
|
|
|
|
// Word文件扩展名映射
|
|
|
|
const WORD_EXTENSIONS = ['DOC', 'DOCX', 'RTF', 'DOT', 'DOTX']
|
|
|
|
// PPT文件扩展名映射
|
|
|
|
const PPT_EXTENSIONS = ['PPT', 'PPTX', 'PPS', 'PPSX']
|
|
|
|
|
|
|
|
// 获取文件类型信息
|
|
|
|
const fileInfo = computed(() => {
|
|
|
|
const extension = getFileExtension(props.extra.name)
|
|
|
|
if (EXCEL_EXTENSIONS.includes(extension)) {
|
|
|
|
return fileTypes.EXCEL
|
|
|
|
}
|
|
|
|
if (WORD_EXTENSIONS.includes(extension)) {
|
|
|
|
return fileTypes.WORD
|
|
|
|
}
|
|
|
|
if (PPT_EXTENSIONS.includes(extension)) {
|
|
|
|
return fileTypes.PPT
|
|
|
|
}
|
|
|
|
return fileTypes[extension] || fileTypes.DEFAULT
|
|
|
|
})
|
|
|
|
|
|
|
|
// 获取文件扩展名
|
|
|
|
function getFileExtension(filename) {
|
|
|
|
const parts = filename.split('.')
|
|
|
|
return parts.length > 1 ? parts.pop().toUpperCase() : ''
|
2025-05-14 03:50:52 +00:00
|
|
|
}
|
|
|
|
|
2025-05-15 08:07:56 +00:00
|
|
|
// 切换播放状态
|
|
|
|
const togglePlay = () => {
|
|
|
|
isPlaying.value = !isPlaying.value
|
|
|
|
|
|
|
|
if (props.extra.is_uploading && props.extra.upload_id) {
|
|
|
|
const action = isPlaying.value ? 'resumeUpload' : 'pauseUpload'
|
|
|
|
uploadsStore[action](props.extra.upload_id)
|
|
|
|
}
|
2025-05-14 03:50:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// 计算SVG圆环进度条的参数
|
2025-05-15 08:07:56 +00:00
|
|
|
const radius = 9
|
|
|
|
const circumference = computed(() => 2 * Math.PI * radius)
|
2025-05-14 03:50:52 +00:00
|
|
|
const strokeDashoffset = computed(() =>
|
2025-05-15 08:07:56 +00:00
|
|
|
circumference.value * (1 - (props.extra.percentage || 0) / 100)
|
2025-05-14 03:50:52 +00:00
|
|
|
)
|
2025-05-20 07:32:20 +00:00
|
|
|
|
|
|
|
// 处理文件点击事件
|
|
|
|
const handleClick = () => {
|
2025-05-22 07:07:27 +00:00
|
|
|
console.log('handleClick')
|
2025-05-20 07:32:20 +00:00
|
|
|
window.open(
|
2025-05-21 05:18:41 +00:00
|
|
|
`${window.location.origin}/office?url=${props.extra.path}`,
|
2025-05-20 07:32:20 +00:00
|
|
|
'_blank',
|
2025-05-21 05:18:41 +00:00
|
|
|
'width=1200,height=900,left=200,top=200,toolbar=no,menubar=no,scrollbars=yes,resizable=yes,location=no,status=no'
|
2025-05-20 07:32:20 +00:00
|
|
|
);
|
|
|
|
}
|
2025-05-22 02:30:02 +00:00
|
|
|
|
2025-05-22 07:07:27 +00:00
|
|
|
function downloadFileWithProgress(resourceUrl, filename) {
|
|
|
|
const iframe = document.createElement('iframe');
|
|
|
|
iframe.style.display = 'none';
|
|
|
|
iframe.src = resourceUrl;
|
|
|
|
document.body.appendChild(iframe);
|
|
|
|
setTimeout(() => {
|
|
|
|
document.body.removeChild(iframe);
|
|
|
|
}, 60000);
|
2025-05-22 02:30:02 +00:00
|
|
|
}
|
|
|
|
|
2025-05-21 11:57:07 +00:00
|
|
|
|
|
|
|
// 处理下载事件
|
|
|
|
const handleDownload = () => {
|
2025-05-22 02:30:02 +00:00
|
|
|
downloadFileWithProgress(props.extra.path,props.extra.name)
|
2025-05-21 11:57:07 +00:00
|
|
|
}
|
2024-12-24 08:14:21 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
2025-05-26 04:00:30 +00:00
|
|
|
<div class="file-message flex flex-col" @click="handleClick">
|
2025-05-14 03:50:52 +00:00
|
|
|
<!-- 文件头部信息 -->
|
2025-05-15 08:07:56 +00:00
|
|
|
<div class="file-header">
|
2025-05-14 03:50:52 +00:00
|
|
|
<!-- 文件名 -->
|
2025-05-15 08:07:56 +00:00
|
|
|
<div class="file-name">{{ extra.name }}</div>
|
2025-05-14 03:50:52 +00:00
|
|
|
<!-- 文件图标区域 -->
|
2025-05-15 08:07:56 +00:00
|
|
|
<div class="file-icon-container">
|
|
|
|
<img class="file-icon" :src="fileInfo.icon" alt="文件图标">
|
|
|
|
|
2025-05-14 03:50:52 +00:00
|
|
|
<!-- 上传进度圆环 - 上传状态 -->
|
2025-05-15 08:07:56 +00:00
|
|
|
<div v-if="extra.is_uploading" class="progress-overlay">
|
2025-05-14 03:50:52 +00:00
|
|
|
<div class="circle-progress-container" @click="togglePlay">
|
|
|
|
<svg class="circle-progress" width="20" height="20" viewBox="0 0 20 20">
|
|
|
|
<!-- 底色圆环 -->
|
|
|
|
<circle
|
|
|
|
cx="10"
|
|
|
|
cy="10"
|
|
|
|
r="9"
|
|
|
|
fill="transparent"
|
|
|
|
stroke="#EEEEEE"
|
|
|
|
stroke-width="2"
|
|
|
|
/>
|
|
|
|
<!-- 进度圆环 -->
|
|
|
|
<circle
|
|
|
|
cx="10"
|
|
|
|
cy="10"
|
|
|
|
r="9"
|
|
|
|
fill="transparent"
|
2025-05-15 08:07:56 +00:00
|
|
|
:stroke="fileInfo.color"
|
2025-05-14 03:50:52 +00:00
|
|
|
stroke-width="2"
|
|
|
|
:stroke-dasharray="circumference"
|
|
|
|
:stroke-dashoffset="strokeDashoffset"
|
|
|
|
transform="rotate(-90 10 10)"
|
|
|
|
class="progress-circle"
|
|
|
|
/>
|
|
|
|
|
2025-05-15 08:07:56 +00:00
|
|
|
<!-- 暂停/播放图标 -->
|
|
|
|
<g v-if="isPlaying" class="pause-icon">
|
|
|
|
<rect x="7" y="5" width="2" height="10" :fill="fileInfo.color" />
|
|
|
|
<rect x="11" y="5" width="2" height="10" :fill="fileInfo.color" />
|
2025-05-14 03:50:52 +00:00
|
|
|
</g>
|
|
|
|
<g v-else class="play-icon">
|
2025-05-15 08:07:56 +00:00
|
|
|
<rect x="6" y="6" width="8" height="8" :fill="fileInfo.color" />
|
2025-05-14 03:50:52 +00:00
|
|
|
</g>
|
|
|
|
</svg>
|
|
|
|
</div>
|
|
|
|
</div>
|
2024-12-24 08:14:21 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
2025-05-14 03:50:52 +00:00
|
|
|
<!-- 文件大小信息 -->
|
2025-05-26 04:00:30 +00:00
|
|
|
<div class="flex justify-between items-center grow-1">
|
2025-05-21 11:57:07 +00:00
|
|
|
<div class="file-size">{{ fileFormatSize(extra.size) }}</div>
|
2025-05-22 02:30:02 +00:00
|
|
|
<div class="flex items-center" v-if="!extra.is_uploading">
|
2025-05-21 11:57:07 +00:00
|
|
|
<div class="flex items-center" @click.stop="handleDownload"> <img class="w-11.7px h-11.74px mr-7px" src="@/assets/image/dofd.png" alt=""> <span class="text-12px text-#46299D">下载</span></div>
|
|
|
|
|
|
|
|
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-05-14 03:50:52 +00:00
|
|
|
</div>
|
2024-12-24 08:14:21 +00:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<style lang="less" scoped>
|
2025-05-15 08:07:56 +00:00
|
|
|
.file-message {
|
|
|
|
width: 243px;
|
|
|
|
background-color: #fff;
|
2025-05-22 07:26:48 +00:00
|
|
|
height: 110px;
|
2025-05-15 08:07:56 +00:00
|
|
|
border-radius: 8px;
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
|
|
padding: 0 14px;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
.file-header {
|
|
|
|
display: flex;
|
|
|
|
padding: 14px 5px 14px 0;
|
|
|
|
justify-content: space-between;
|
|
|
|
width: 100%;
|
|
|
|
border-bottom: 1px solid #EEEEEE;
|
|
|
|
}
|
|
|
|
|
|
|
|
.file-name {
|
2025-05-19 03:39:20 +00:00
|
|
|
height: 50px;
|
2025-05-15 08:07:56 +00:00
|
|
|
color: #1A1A1A;
|
|
|
|
font-size: 14px;
|
|
|
|
word-break: break-word;
|
|
|
|
overflow: hidden;
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
display: -webkit-box;
|
|
|
|
-webkit-line-clamp: 2;
|
|
|
|
-webkit-box-orient: vertical;
|
|
|
|
}
|
|
|
|
|
|
|
|
.file-icon-container {
|
2025-05-26 04:00:30 +00:00
|
|
|
height: 48px;
|
2025-05-15 08:07:56 +00:00
|
|
|
position: relative;
|
|
|
|
}
|
|
|
|
|
|
|
|
.file-icon {
|
|
|
|
width: 48px;
|
|
|
|
height: 48px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.progress-overlay {
|
|
|
|
background-color: #fff;
|
|
|
|
position: absolute;
|
|
|
|
top: 6px;
|
|
|
|
left: 11px;
|
|
|
|
width: 30px;
|
|
|
|
height: 30px;
|
|
|
|
display: flex;
|
|
|
|
justify-content: center;
|
|
|
|
align-items: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
.file-size {
|
|
|
|
color: #747474;
|
|
|
|
font-size: 12px;
|
|
|
|
}
|
|
|
|
|
2025-05-14 03:50:52 +00:00
|
|
|
.circle-progress-container {
|
|
|
|
width: 20px;
|
|
|
|
height: 20px;
|
|
|
|
position: relative;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
2024-12-24 08:14:21 +00:00
|
|
|
|
2025-05-14 03:50:52 +00:00
|
|
|
.circle-progress {
|
|
|
|
transform: rotate(-90deg);
|
|
|
|
transform-origin: center;
|
|
|
|
}
|
2024-12-24 08:14:21 +00:00
|
|
|
|
2025-05-14 03:50:52 +00:00
|
|
|
.progress-circle {
|
|
|
|
transition: stroke-dashoffset 0.3s ease;
|
|
|
|
}
|
2024-12-24 08:14:21 +00:00
|
|
|
|
2025-05-14 03:50:52 +00:00
|
|
|
.pause-icon, .play-icon {
|
|
|
|
transform-origin: center;
|
|
|
|
}
|
2024-12-24 08:14:21 +00:00
|
|
|
|
2025-05-15 08:07:56 +00:00
|
|
|
.pause-icon {
|
2025-05-14 03:50:52 +00:00
|
|
|
transform: rotate(90deg);
|
2024-12-24 08:14:21 +00:00
|
|
|
}
|
|
|
|
</style>
|