<template>
|
<view class="file-list-page">
|
<!-- 页面头部 -->
|
<PageHeader title="附件管理"
|
@back="goBack" />
|
<!-- 附件列表 -->
|
<view class="file-list-container">
|
<view v-if="fileList.length > 0"
|
class="file-list">
|
<view v-for="(file, index) in fileList"
|
:key="file.id || index"
|
class="file-item">
|
<!-- 文件图标 -->
|
<!-- <view class="file-icon"
|
:class="getFileIconClass(file.fileType)">
|
<up-icon :name="getFileIcon(file.fileType)"
|
size="24"
|
color="#ffffff" />
|
</view> -->
|
<!-- 文件信息 -->
|
<view class="file-info">
|
<text class="file-name">{{ file.name }}</text>
|
<!-- <text class="file-meta">{{ formatFileSize(file.fileSize) }} · {{ file.uploadTime || file.createTime }}</text> -->
|
</view>
|
<!-- 操作按钮 -->
|
<view class="file-actions">
|
<!-- <u-button size="small"
|
type="primary"
|
plain
|
@click="previewFile(file)">预览</u-button> -->
|
<u-button size="small"
|
type="info"
|
plain
|
@click="downloadFile(file)">下载</u-button>
|
<u-button size="small"
|
type="error"
|
plain
|
@click="confirmDelete(file, index)">删除</u-button>
|
</view>
|
</view>
|
</view>
|
<!-- 空状态 -->
|
<view v-else
|
class="empty-state">
|
<up-icon name="document"
|
size="64"
|
color="#c0c4cc" />
|
<text class="empty-text">暂无附件</text>
|
</view>
|
</view>
|
<a rel="nofollow"
|
id="downloadLink"
|
href="#"
|
style="display:none;">下载文本文件</a>
|
<!-- 上传按钮 -->
|
<view class="upload-button"
|
@click="chooseFile">
|
<up-icon name="plus"
|
size="24"
|
color="#ffffff" />
|
<text class="upload-text">上传附件</text>
|
</view>
|
</view>
|
</template>
|
|
<script setup>
|
import { ref, onMounted } from "vue";
|
import PageHeader from "@/components/PageHeader.vue";
|
import config from "@/config";
|
import { getToken } from "@/utils/auth";
|
import axios from "axios";
|
import requestApp from "@/utils/requestApp";
|
// import { saveAs } from "file-saver";
|
import {
|
listRuleFiles,
|
addRuleFile,
|
delRuleFile,
|
upload,
|
} from "@/api/managementMeetings/rulesRegulationsManagement";
|
import { blobValidate } from "@/utils/ruoyi";
|
|
// 附件列表
|
const fileList = ref([]);
|
|
// 返回上一页
|
const goBack = () => {
|
uni.navigateBack();
|
};
|
// const request = axios.create({
|
// baseURL: "URL.com",
|
// adapter: axiosAdapterUniapp,
|
// });
|
// 获取文件图标
|
const getFileIcon = fileType => {
|
const iconMap = {
|
doc: "document",
|
docx: "document",
|
xls: "grid",
|
xlsx: "grid",
|
pdf: "document",
|
ppt: "copy",
|
pptx: "copy",
|
txt: "document",
|
jpg: "image",
|
jpeg: "image",
|
png: "image",
|
gif: "image",
|
zip: "folder",
|
rar: "folder",
|
};
|
return iconMap[fileType.toLowerCase()] || "document";
|
};
|
|
// 获取文件图标样式类
|
const getFileIconClass = fileType => {
|
const colorMap = {
|
doc: "blue",
|
docx: "blue",
|
xls: "green",
|
xlsx: "green",
|
pdf: "red",
|
ppt: "orange",
|
pptx: "orange",
|
txt: "gray",
|
jpg: "purple",
|
jpeg: "purple",
|
png: "purple",
|
gif: "purple",
|
zip: "yellow",
|
rar: "yellow",
|
};
|
return colorMap[fileType.toLowerCase()] || "gray";
|
};
|
|
// 格式化文件大小
|
const formatFileSize = bytes => {
|
if (bytes === 0) return "0 B";
|
const k = 1024;
|
const sizes = ["B", "KB", "MB", "GB"];
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
|
};
|
|
// 选择文件
|
const chooseFile = () => {
|
// uni.chooseImage({
|
// count: 9,
|
// sizeType: ["original", "compressed"],
|
// sourceType: ["album", "camera"],
|
// success: res => {
|
// uploadFiles(res.tempFiles);
|
// },
|
// fail: err => {
|
// console.error("选择图片失败:", err);
|
// showToast("选择文件失败");
|
// },
|
// });
|
// uni.chooseFile({
|
// count: 9,
|
// extension: [
|
// ".doc",
|
// ".docx",
|
// ".xls",
|
// ".xlsx",
|
// ".pdf",
|
// ".ppt",
|
// ".pptx",
|
// ".txt",
|
// ".jpg",
|
// ".jpeg",
|
// ".png",
|
// ".gif",
|
// ".zip",
|
// ".rar",
|
// ],
|
// success: res => {
|
// uploadFiles(res.tempFiles);
|
// },
|
// fail: err => {
|
// showToast("选择文件失败");
|
// },
|
// });
|
};
|
|
// 上传文件
|
const uploadFiles = tempFiles => {
|
tempFiles.forEach((tempFile, index) => {
|
// 显示上传中提示
|
uni.showLoading({
|
title: "上传中...",
|
mask: true,
|
});
|
console.log(tempFile, "上传文件");
|
// 1. 直接使用 uni.uploadFile 上传文件
|
uni.uploadFile({
|
url: config.baseUrl + "/file/upload",
|
filePath: tempFile.path,
|
name: "file",
|
header: {
|
Authorization: "Bearer " + getToken(),
|
},
|
success: uploadRes => {
|
uni.hideLoading();
|
try {
|
const res = JSON.parse(uploadRes.data);
|
if (res.code === 200) {
|
// 2. 提取文件信息
|
const fileName = tempFile.name;
|
const fileType = fileName.split(".").pop();
|
// 3. 构造保存文件信息的参数
|
const saveData = {
|
name: fileName,
|
rulesRegulationsManagementId: rulesRegulationsManagementId.value,
|
url: res.data.tempPath || "",
|
};
|
console.log(saveData, "保存文件信息参数");
|
// 4. 调用 addRuleFile 接口保存文件信息
|
addRuleFile(saveData)
|
.then(addRes => {
|
if (addRes.code === 200) {
|
// 5. 添加到文件列表
|
const newFile = {
|
...addRes.data,
|
uploadTime: new Date().toLocaleString(),
|
};
|
// fileList.value.push(newFile);
|
getFileList();
|
showToast("上传成功");
|
} else {
|
showToast("保存文件信息失败");
|
}
|
})
|
.catch(err => {
|
console.error("保存文件信息失败:", err);
|
showToast("保存文件信息失败");
|
});
|
} else {
|
showToast("文件上传失败");
|
}
|
} catch (e) {
|
console.error("解析上传结果失败:", e);
|
showToast("上传失败");
|
}
|
},
|
fail: err => {
|
uni.hideLoading();
|
console.error("上传失败:", err);
|
showToast("上传失败");
|
},
|
});
|
});
|
};
|
|
// 下载文件
|
const downloadFile = file => {
|
var url =
|
config.baseUrl +
|
"/common/download?fileName=" +
|
encodeURIComponent(file.url) +
|
"&delete=true";
|
console.log(url, "url");
|
|
uni
|
.downloadFile({
|
url: url,
|
responseType: "blob",
|
header: { Authorization: "Bearer " + getToken() },
|
})
|
.then(res => {
|
console.log(res, "res");
|
const isBlob = blobValidate(res.data);
|
console.log(isBlob, "isBlob");
|
if (isBlob) {
|
const blob = new Blob([res.data], { type: "text/plain" });
|
const url = URL.createObjectURL(blob);
|
const downloadLink = document.getElementById("downloadLink");
|
downloadLink.href = url;
|
downloadLink.download = file.name;
|
downloadLink.click();
|
// downloadLink.style.display = "block";
|
showToast("下载成功");
|
} else {
|
showToast("下载失败");
|
}
|
})
|
.catch(err => {
|
console.error("下载失败:", err);
|
showToast("下载失败");
|
});
|
};
|
|
// 确认删除
|
const confirmDelete = (file, index) => {
|
uni.showModal({
|
title: "删除确认",
|
content: `确定要删除附件 "${file.name}" 吗?`,
|
success: res => {
|
if (res.confirm) {
|
deleteFile(file.id, index);
|
}
|
},
|
});
|
};
|
|
// 删除文件
|
const deleteFile = (fileId, index) => {
|
uni.showLoading({
|
title: "删除中...",
|
mask: true,
|
});
|
|
delRuleFile([fileId])
|
.then(res => {
|
uni.hideLoading();
|
if (res.code === 200) {
|
// fileList.value.splice(index, 1);
|
getFileList();
|
showToast("删除成功");
|
} else {
|
showToast("删除失败");
|
}
|
})
|
.catch(err => {
|
uni.hideLoading();
|
showToast("删除失败");
|
});
|
};
|
|
// 显示提示
|
const showToast = message => {
|
uni.showToast({
|
title: message,
|
icon: "none",
|
});
|
};
|
const rulesRegulationsManagementId = ref("");
|
// 页面加载时
|
onMounted(() => {
|
// 从 API 获取附件列表
|
getFileList();
|
// 从本地存储获取 rulesRegulationsManagementId
|
rulesRegulationsManagementId.value = uni.getStorageSync(
|
"rulesRegulationsManagement"
|
);
|
});
|
|
// 获取附件列表
|
const getFileList = () => {
|
uni.showLoading({
|
title: "加载中...",
|
mask: true,
|
});
|
|
listRuleFiles()
|
.then(res => {
|
uni.hideLoading();
|
if (res.code === 200) {
|
fileList.value = res.data.records || [];
|
} else {
|
showToast("获取附件列表失败");
|
}
|
})
|
.catch(err => {
|
uni.hideLoading();
|
showToast("获取附件列表失败");
|
});
|
};
|
</script>
|
|
<style scoped lang="scss">
|
@import "../../../styles/sales-common.scss";
|
|
.file-list-page {
|
min-height: 100vh;
|
background: #f8f9fa;
|
padding-bottom: 100rpx;
|
}
|
|
.file-list-container {
|
padding: 20rpx;
|
}
|
|
.file-list {
|
background: #ffffff;
|
border-radius: 8rpx;
|
overflow: hidden;
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
}
|
|
.file-item {
|
display: flex;
|
align-items: center;
|
padding: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
&:last-child {
|
border-bottom: none;
|
}
|
}
|
|
.file-icon {
|
width: 56rpx;
|
height: 56rpx;
|
border-radius: 8rpx;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
margin-right: 20rpx;
|
|
&.blue {
|
background: #409eff;
|
}
|
|
&.green {
|
background: #67c23a;
|
}
|
|
&.red {
|
background: #f56c6c;
|
}
|
|
&.orange {
|
background: #e6a23c;
|
}
|
|
&.gray {
|
background: #909399;
|
}
|
|
&.purple {
|
background: #909399;
|
}
|
|
&.yellow {
|
background: #e6a23c;
|
}
|
}
|
|
.file-info {
|
flex: 1;
|
min-width: 0;
|
}
|
|
.file-name {
|
display: block;
|
font-size: 16px;
|
color: #303133;
|
margin-bottom: 8rpx;
|
overflow: hidden;
|
text-overflow: ellipsis;
|
white-space: nowrap;
|
}
|
|
.file-meta {
|
display: block;
|
font-size: 12px;
|
color: #909399;
|
}
|
|
.file-actions {
|
display: flex;
|
gap: 12rpx;
|
}
|
|
.empty-state {
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
padding: 100rpx 0;
|
background: #ffffff;
|
border-radius: 8rpx;
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
}
|
|
.empty-text {
|
font-size: 14px;
|
color: #909399;
|
margin-top: 20rpx;
|
}
|
|
.upload-button {
|
position: fixed;
|
bottom: 40rpx;
|
right: 40rpx;
|
width: 80rpx;
|
height: 80rpx;
|
border-radius: 50%;
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
box-shadow: 0 4rpx 16rpx rgba(102, 126, 234, 0.4);
|
z-index: 1000;
|
}
|
|
.upload-text {
|
font-size: 10px;
|
color: #ffffff;
|
margin-top: 4rpx;
|
}
|
|
.upload-progress {
|
padding: 40rpx 0;
|
}
|
|
.upload-progress-text {
|
display: block;
|
text-align: center;
|
margin-top: 20rpx;
|
font-size: 14px;
|
color: #606266;
|
}
|
</style>
|