文件缩略图 list-type="picture-card"
使用 scoped-slot 去设置缩略图模版。
编辑时
- 请求详情接口——(先请求接口返回结果后再请求下一个接口)
- 用返回数据请求文件下载接口——(循环中执行多个接口后再加载数据)
- 用返回的文件流生成url
async getDetail(id) {
this.formLoading = true;
try {
// 1. 请求详情接口——(先请求接口返回结果后再请求下一个接口)
const res = await getAchievementDetail({ id: id });
if (res.code == 200) {
this.flawForm = res.data;
this.flawForm.fileListParams = this.flawForm.reportFileList;
}
const dataList = this.flawForm.fileListParams;
if(dataList && dataList.length > 0){
// 2. 用返回数据请求文件下载接口——(循环中执行多个接口后再加载数据)
const results = await Promise.all(dataList.map(async item => {
const response2 = await downLoadFileImage(item.reportFileId);
// 3. 用返回的文件流生成url
const imgUrl = PreviewBackFileImg(response2);
const fileObj = {
name: item.reportFileName,
url: imgUrl,
}
return fileObj;
}))
if(results){
this.fileList = results;
this.formLoading = false;
}
}else{
this.formLoading = false;
}
} catch (error) {
console.error('请求失败:', error);
}
},
页面文件system.vue
<template>
<div>
<!-- 表单弹出框 -->
<el-dialog
append-to-body
:title="title"
:close-on-click-modal="false"
:visible.sync="showDialog"
:before-close="closeDialog"
>
<el-form :model="flawForm" ref="flawForm" label-width="120px" @submit.native.prevent v-loading="formLoading">
<el-row>
<el-col :span="24">
<h3>缩略图信息</h3>
</el-col>
<el-col :span="24">
<el-form-item label="红头文件名称:" prop="redHeaderFileName">
<el-input
v-model.trim="flawForm.redHeaderFileName"
show-word-limit
clearable
maxlength="100"
placeholder="请输入红头文件名称"
></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="漏洞专刊:" prop="flawIssue">
<el-input
v-model.trim="flawForm.flawIssue"
show-word-limit
clearable
maxlength="100"
placeholder="请输入漏洞专刊"
></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="专刊期号:" prop="fileNumber">
<el-input
v-model.trim="flawForm.fileNumber"
show-word-limit
clearable
maxlength="100"
placeholder="请输入专刊期号"
></el-input>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="通报文件图片:" prop="reportFileList">
<FileUpload
ref="fileUploadImageRef"
:backData="fileList"
@onSuccess="onSuccess"
@onPreview="onPreview"
@onRemove="onRemove"
></FileUpload>
</el-form-item>
</el-col>
</el-row>
<!-- 操作按钮 -->
<div class="dialog-btn">
<el-button @click="closeDialog">取消</el-button>
<el-button :loading="submitLoading" @click="onSubmit" type="primary">确认</el-button>
</div>
</el-form>
</el-dialog>
<!-- 文件缩略图-预览图片 -->
<el-dialog :visible.sync="dialogVisible" :close-on-click-modal="false" :before-close="closeImgDialog">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</template>
<script>
import { PreviewBackFileImg } from "@/utils/download";
import { downLoadFileImage } from "@/api/data.js"
import FileUpload from "@/components/FileUploadImage/index.vue";
import { saveAchievement, getAchievementDetail } from "@/api/screenSetting/flawOutputs";
import { method } from "lodash";
export default {
components: { FileUpload },
data() {
return {
pageSize: 1,
title: "添加",
formLoading: false,
flawForm: {
id: null,
redHeaderFileName: '',
flawIssue: '',
fileNumber: '',
reportFileList: [],
fileListParams: [],
},
fileList:[],
submitLoading: false,
dialogImageUrl: '',
dialogVisible: false,
};
},
methods: {
//新增
handleAdd() {
this.showDialog = true;
this.title = "添加";
this.fileList = [];
this.flawForm.fileListParams = [];
},
// 编辑
handleEdit(row) {
this.title = "编辑";
this.getDetail(row.id);
this.showDialog = true;
this.fileList = [];
this.flawForm.fileListParams = [];
},
// 获取上传文件id数组
onSuccess(uploadList) {
this.flawForm.fileListParams.push(uploadList); // 数组返回{reportFileId,reportFileName}
// console.log('onSuccess上传图片后数组',this.flawForm.fileListParams);
},
// 文件缩略图-预览图片
onPreview(fileUrl){
this.dialogVisible = true;
this.dialogImageUrl = fileUrl;
},
closeImgDialog(){
this.dialogVisible = false;
this.dialogImageUrl = '';
},
onRemove(file){
this.flawForm.fileListParams = this.flawForm.fileListParams.filter(item => item.reportFileName != file.name)
},
async getDetail(id) {
this.formLoading = true;
try {
const res = await getAchievementDetail({ id: id });
if (res.code == 200) {
this.flawForm = res.data;
this.flawForm.fileListParams = this.flawForm.reportFileList;
}
const dataList = this.flawForm.fileListParams;
if(dataList && dataList.length > 0){
const results = await Promise.all(dataList.map(async item => {
const response2 = await downLoadFileImage(item.reportFileId);
const imgUrl = PreviewBackFileImg(response2);
const fileObj = {
name: item.reportFileName,
url: imgUrl,
}
return fileObj;
}))
if(results){
this.fileList = results;
this.formLoading = false;
}
}else{
this.formLoading = false;
}
} catch (error) {
console.error('请求失败:', error);
}
},
//弹出框点击确认
onSubmit() {
this.$refs.flawForm.validate(valid => {
if (valid) {
this.submitLoading = true;
let params = {
id: this.title === "添加" ? "" : this.flawForm.id,
};
if(this.tabType == 1){
params.redHeaderFileName = this.flawForm.redHeaderFileName;
params.flawIssue = this.flawForm.flawIssue;
params.fileNumber = this.flawForm.fileNumber;
const fileIds = this.flawForm.fileListParams.map(item => item.reportFileId);
params.reportFileList = fileIds;
}
saveAchievement(params)
.then(res => {
if (res.code === 200) {
this.$message({
message: this.title === "添加" ? "新增成功" : "修改成功",
type: "success",
center: true,
duration: 500,
onClose: () => {
this.submitLoading = false;
this.closeDialog();
if (this.title === "添加") {
this.pageSize = 1;
this.getList();
} else {
this.getList();
}
}
});
}
})
.catch(error => {
this.submitLoading = false;
});
} else {
return false;
}
});
},
resetForm() {
this.fileList = [];
this.flawForm = {};
this.$refs.flawForm.resetFields();
},
closeDialog() {
this.resetForm();
this.submitLoading = false;
this.showDialog = false;
},
getList(){
// 获取列表
}
}
}
</script>
页面文件system.vue中引用文件download.js "@/utils/download";
// 显示头像,返回url
export function PreviewBackFileImg(res) {
const fileName = res.headers["content-disposition"].replace(
/\w+;filename=(.*)/,
"$1"
);
let fileType = fileName.split(".");
if (['png', 'jpg', 'jpeg','gif','bmp','tiff','tif','webp','svg','heic','heif','arw','psd'].includes(fileType[1])) {
const file = new Blob([res.data], {
type: `image/${fileType[1]};chartset=utf-8`
});
let url = window.URL.createObjectURL(file);
return url;
}
}
页面文件system.vue中引用文件data.js "@/api/data.js"
export function uploadAPI(data) {
return request({
url: `/file/uploadFileBack`,
method: 'post',
data,
headers: { "Content-Type": "multipart/form-data" },
})
}
// 获取缩略图-下载图片地址
export function downLoadFileImage(data) {
return request({
url: `/common/downloadFile?fileId=${data}`,
method: 'post',
responseType: 'blob',
headers: {
Authorization: getToken()
},
});
}
页面文件system.vue中引用文件index.vue "@/components/FileUploadImage/index.vue"
- 上传缩略图
list-type="picture-card" - 获取上传文件的所有数据
this.$refs.pictureUpload.uploadFiles - 编辑时查看已上传的文件列表
:file-list="reportFileList" // reportFileList=[{name: '123.jpg', url: 'http://xxx.jpg'}] - 自定义上传
:http-request="httpRequest" - 设置提示信息
<div slot="tip" class="el-upload__tip">请上传通报文件扫描图片,限制上传20个文件,文件大小50M以内。</div>
<!-- 上传文件缩略图 -->
<template>
<div>
<el-upload
ref="pictureUpload"
name="file"
:headers="headers"
:action="uploadFileUrl"
list-type="picture-card"
:limit="20"
:file-list="reportFileList"
:on-exceed="onExceed"
:on-error="handleUploadError"
:on-change="handleBeforeUpload"
:http-request="httpRequest"
>
<i slot="default" class="el-icon-plus"></i>
<div slot="file" slot-scope="{file}">
<img class="el-upload-list__item-thumbnail" :src="file.url" alt="" >
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in"></i>
</span>
<span class="el-upload-list__item-delete" @click="handleDownload(file)">
<i class="el-icon-download"></i>
</span>
<span class="el-upload-list__item-delete" @click="handleRemove(file)">
<i class="el-icon-delete"></i>
</span>
</span>
</div>
<div slot="tip" class="el-upload__tip">
请上传通报文件扫描图片,限制上传20个文件,文件大小50M以内。
</div>
</el-upload>
</div>
</template>
<script>
import { Loading } from "element-ui";
import { getToken } from "@/utils/auth";
import { downloadByData } from "@/utils/fileDownload";
import { uploadAPI } from "@/api/data.js"
const baseUrl = process.env.VUE_APP_BASE_API;
export default {
props:{
backData: {
type: Array,
default: () => []
},
// 大小限制(M)
fileSize: {
type: Number,
default: 50
},
},
data() {
return {
headers: {
Authorization: getToken()
},
uploadFileUrl:`${baseUrl}/file/uploadFileBack`,
reportFileList: [], // [{name: 'food.jpg', url: 'https://xxx.cdn.com/xxx.jpg'}]
uploading: null,
};
},
watch: {
backData: {
deep: true,
immediate: true,
handler: function(val) {
this.reportFileList = val;
}
}
},
methods: {
// 上传前校检格式和大小
handleBeforeUpload(file) {
// 校检文件大小
if (this.fileSize) {
if (file.size == 0) {
this.$message.error(`上传文件需大于0KB`);
return false;
}
const isLt = file.size / 1024 / 1024 < this.fileSize;
if (!isLt) {
this.$message.error(`单个文件大小不超过${this.fileSize}M`);
return false;
}
}
// 校验重复
let flag = this.reportFileList
? this.reportFileList.some(item => item.name == file.name)
: false;
if (flag) {
this.handleRemove(file);
this.$message.error(`文件已存在`);
return false;
}
this.uploading = Loading.service({
lock: true,
text: "正在上传文件,请稍候...",
spinner: "el-icon-loading",
background: "rgba(255, 255, 255, .5)"
});
},
httpRequest(options) {
const { file, onSuccess, onError } = options;
let formData = new FormData();
formData.append("name", file.name);
formData.append("bucketName", 'record');
formData.append("file", file);
if(this.uploading){
this.uploading.close();
}
uploadAPI(formData).then((res) => {
if (res.code === 200) {
const fileItem = {
reportFileId: res.data,
reportFileName: file.name,
}
this.$emit('onSuccess', fileItem);
} else {
this.$message.error(res.msg);
}
})
},
onExceed(){
this.$message.error(`最多上传20个文件`);
},
handleDownload(data) {
console.log(data);
downloadByData(data.raw, data.name);
},
//处理移除图片
handleRemove(file) {
const uploadFiles = this.$refs.pictureUpload.uploadFiles
for (let i = 0; i < uploadFiles.length; i++) {
if (uploadFiles[i]['url'] === file.url) {
uploadFiles.splice(i, 1)
}
}
this.$emit('onRemove',file);
},
// 上传失败
handleUploadError(err) {
try {
const result = JSON.parse(err.message);
this.$message({
message: result.message,
type: "error",
center: true
});
} catch (error) {
console.log("error", error);
}
this.uploading.close();
},
}
}
</script>
文件FileUploadImage/index.vue中引用方法fileDownload.js "@/utils/fileDownload"
/**
* 文件流下载
* @param {*} data Blob | BufferSource | string 文件流
* @param {*} filename string 文件名
* @param {*} mime string 类型 可选
* @param {*} bom Blob | BufferSource | string 可选
*/
export function downloadByData(data, filename, mime, bom) {
const blobData = typeof bom !== "undefined" ? [bom, data] : [data];
const blob = new Blob(blobData, { type: mime || "application/octet-stream" });
const blobURL = window.URL.createObjectURL(blob);
const tempLink = document.createElement("a");
tempLink.style.display = "none";
tempLink.href = blobURL;
tempLink.setAttribute("download", filename);
if (typeof tempLink.download === "undefined") {
tempLink.setAttribute("target", "_blank");
}
document.body.appendChild(tempLink);
tempLink.click();
document.body.removeChild(tempLink);
window.URL.revokeObjectURL(blobURL);
}