<script lang="ts" setup> import { fileFormatSize } from '@/utils/strings' import { computed } from 'vue' import { download, getFileNameSuffix } from '@/utils/functions' import { ITalkRecordExtraFile, ITalkRecord } from '@/types/chat' import filePaperPDF from '@/static/image/chat/file-paper-pdf.png' import filePaperPPT from '@/static/image/chat/file-paper-ppt.png' import filePaperWord from '@/static/image/chat/file-paper-word.png' import filePaperExcel from '@/static/image/chat/file-paper-excel.png' import filePaperOther from '@/static/image/chat/file-paper-other.png' import filePaperPDFBlank from '@/static/image/chat/file-paper-pdf-blank.png' import filePaperPPTBlank from '@/static/image/chat/file-paper-ppt-blank.png' import filePaperWordBlank from '@/static/image/chat/file-paper-word-blank.png' import filePaperExcelBlank from '@/static/image/chat/file-paper-excel-blank.png' import filePaperOtherBlank from '@/static/image/chat/file-paper-other-blank.png' const props = defineProps<{ extra: ITalkRecordExtraFile data: ITalkRecord maxWidth?: Boolean }>() const getFileTypeIMG = computed(() => { const suffix = props.extra.name.split('.').pop()?.toLowerCase() || '' let objT = { finishedImg: '', blankImg: '', progressColor: '', } switch (suffix) { case 'pdf': objT.finishedImg = filePaperPDF objT.blankImg = filePaperPDFBlank objT.progressColor = '#DE4E4E' break case 'doc': case 'docx': objT.finishedImg = filePaperWord objT.blankImg = filePaperWordBlank objT.progressColor = '#2750B2' break case 'xls': case 'xlsx': objT.finishedImg = filePaperExcel objT.blankImg = filePaperExcelBlank objT.progressColor = '#3C7F4B' break case 'ppt': case 'pptx': objT.finishedImg = filePaperPPT objT.blankImg = filePaperPPTBlank objT.progressColor = '#B74B2B' break default: objT.finishedImg = filePaperOther objT.blankImg = filePaperOtherBlank objT.progressColor = '#747474' } return objT }) const previewPDF = () => { if (typeof plus !== 'undefined') { downloadAndOpenFile() } else { document.addEventListener('plusready', () => { downloadAndOpenFile() }) } } const downloadAndOpenFile = () => { uni.showLoading({ title: '加载中...', mask: true }) const downloadUrl = props?.extra?.path if (!downloadUrl) { uni.hideLoading() uni.showToast({ title: '文件路径无效', icon: 'none' }) return } const options = { filename: '_doc/downloads/', // 保存路径 } const dtask = plus.downloader.createDownload(downloadUrl, options, function ( d, status, ) { if (status === 200) { uni.hideLoading() const filePath = d.filename if (filePath) { plus.runtime.openFile(filePath, {}, function () {}) } else { uni.showToast({ title: '文件路径无效', icon: 'none' }) } } else { uni.hideLoading() } }) dtask.start() } </script> <template> <section class="file-message" @click="previewPDF" :class="{ left: data.float === 'left', right: data.float === 'right' }" > <div class="flex justify-between"> <div class="w-[228rpx] text-[32rpx] text-[#1A1A1A] h-[88rpx] leading-[44rpx] textEllipsis file_name" > {{ extra.name }} </div> <div v-if="data.uploadStatus === 2 || !data.uploadStatus" class="w-[95rpx]" > <tm-image :width="95" :height="95" :src="getFileTypeIMG.finishedImg" ></tm-image> </div> <div v-if="data.uploadStatus === 1 || data.uploadStatus === 3" class="w-[95rpx]" > <tm-image :width="95" :height="95" :src="getFileTypeIMG.blankImg" ></tm-image> <wd-circle customClass="circleProgress" :modelValue="data.uploadCurrent" layerColor="#E3E3E3" :color="getFileTypeIMG.progressColor" :strokeWidth="3" :size="20" ></wd-circle> </div> </div> <div class="divider mt-[28rpx]"></div> <div class="text-[24rpx] text-[#747474] mt-[10rpx]"> {{ fileFormatSize(extra.size) }} </div> <!-- <div class="main"> <div class="ext">{{ getFileNameSuffix(extra.name) }}</div> <div class="file-box"> <p class="info"> <span class="name">{{ extra.name }}</span> <span class="size">({{ fileFormatSize(extra.size) }})</span> </p> <p class="notice">文件已成功发送, 文件助手永久保存</p> </div> </div> <div class="footer"> <a @click="download(data.msg_id)">下载</a> <a>在线预览</a> </div> --> </section> </template> <style lang="less" scoped> .file-message { width: 486rpx; min-height: 220rpx; padding: 28rpx 30rpx 22rpx 30rpx; border-radius: 10px; background-color: #fff; border-radius: 0; &.left { background-color: #fff; border-radius: 0 16rpx 16rpx 16rpx; } &.right { background-color: #fff; border-radius: 16rpx 0 16rpx 16rpx; } .file_name { word-break: break-all; /* 在任意字符间断行 */ word-wrap: break-word; /* 允许长单词换行到下一行 */ } .main { height: 45px; display: flex; flex-direction: row; margin-top: 5px; .ext { display: flex; justify-content: center; align-items: center; width: 45px; height: 45px; color: #ffffff; background: #49a4ff; border-radius: 5px; font-size: 12px; } .file-box { flex: 1 1; height: 45px; margin-left: 10px; overflow: hidden; .info { display: flex; justify-content: space-between; align-items: center; overflow: hidden; height: 24px; font-size: 14px; .name { flex: 1 auto; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .size { font-size: 12px; color: #cac6c6; flex-shrink: 0; } } .notice { height: 25px; line-height: 25px; font-size: 12px; color: #929191; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } } } .footer { height: 30px; line-height: 37px; text-align: right; font-size: 12px; border-top: 1px solid var(--border-color); margin-top: 10px; a { margin: 0 3px; user-select: none; cursor: pointer; color: var(--im-text-color); &:hover { color: royalblue; } } } } .textEllipsis { overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } .divider { background-color: #e7e7e7; height: 1rpx; } .circleProgress { position: absolute; top: 120rpx; right: 52rpx; transform: translate(-50%, -50%); z-index: 1; width: 40rpx !important; height: 40rpx !important; } </style>