前言:avue实现原文件上传是有格式限制的,且预览展示效果稍微差点,我使用kkfileview去写,这样不会限制文件上传格式
1、kkfileview使用参考我另一篇文章【kkFileView】文件文档在线预览解决方案,基本支持主流办公文档的在线预览,如doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,rar,图片,视频,音频等等_^草莓牛乳茶^的博客-CSDN博客
2、全部代码展示
javascript
<template>
<basic-container>
<avue-crud ref="crud"
v-model="form"
:before-open="beforeOpen"
:data="data"
:option="option"
:page.sync="page"
:permission="permissionList"
:table-loading="loading"
:upload-after="uploadAfter"
:upload-before="uploadBefore"
:upload-delete="uploadDelete"
:upload-preview="uploadPreview"
@row-update="rowUpdate"
@row-save="rowSave"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@on-load="onLoad">
<template slot="fileName" slot-scope="{ type, size, row }">
<div class="download">
<div v-for="(item, index) in row.fileLocation" :key="index">
<el-tooltip :content="item.name" class="item" effect="dark
placement="bottom">
<div @click="downloadAnnex(row.fileLocation[index], item)">
{{ item.name }}
</div>
</el-tooltip>
</div>
</div>
</avue-crud>
<showFile ref="showFileList" :fileLocationName="fileLocationName"
:fileUpdata="fileUpdata"></showFile>
</basic-container>
</template>
<script>
import { add, getDetail, getList, remove, update, upspecialdata } from "@/api/safety/administration/safetylicense";
import { mapGetters } from "vuex";
import showFile from "../../safety/showFile.vue";
import safetydivicecloseopenshrecord from "@/views/public/safetydivicecloseopenshrecord.vue";
import { updateFileLocation } from "@/mixins/update-file-location"
export default {
components: {
showFile,
},
mixins: [updateFileLocation],
data() {
fileUpdata: "fileName", // 表格显示时用
fileLocationName: "fileLocation", // 附件本字段
form: {},
query: {},
loading: true,
page: {
pageSize: 10,
currentPage: 1,
total: 0,
},
selectionList: [],
option: {
height: "auto",
calcHeight: 210,
searchShow: true,
searchMenuSpan: 6,
tip: false,
border: true,
index: true,
viewBtn: true,
selection: true,
labelWidth: 140,
column: [
{
label: "许可证照上传",
prop: "fileLocation",
type: "upload",
dataType: "object",
showFileList: true,
showColumn: false,
multiple: true,
drag: false,
loadText: "附件上传中,请稍等",
previewSrcList: false,
propsHttp: {
name: "originalName",
url: "link",
res: "data",
// home: "domain",
},
props: {
label: 'name',
value: 'link'
},
action: "/api/blade-resource/oss/endpoint/put-file-attach",
span: 24, rules: [{
required: true,
message: "请输入附件",
trigger: "blur"
}]
},
{
label: "文件预览",
prop: "fileName",
display: false,
showColumn: true,
rules: [
{
required: true,
message: "请输入文件名称",
trigger: "blur",
},
],
},
},
],
},
data: [],
};
},
methods: {
shrecordfun(row, index) {
this.closeoropenid = row.id;
this.shrecordVisible = true;
},
// 是否点击放大图片
uploadPreview(file, column, done) {
this.$nextTick(() => {
/**
* e:文件路径
* k:源文件名字
*/
this.$refs.showFileList.downloadAnnex(file.url || file.link, file.name);//调用组件方法
});
},
// 预览方法
downloadAnnex(e, k) {
this.$nextTick(() => {
this.$refs.showFileList.downloadAnnex(e.url || e.link, k);//调用组件方法
});
},
// 上传前方法
uploadBefore(file, done, loading, column) {
done()
},
// 上传后方法
uploadAfter(res, done, loading, column) {
this.form[this.fileLocationName] = this.formFileLocation(res, this.fileLocationName)
done()
},
// 删除前的方法
uploadDelete(file, column) {
this.$nextTick(() => {
this.$refs.showFileList.frontUploadDelete(file, column); //调用组件方法
});
},
// 新增数据调取接口
rowSave(row, done, loading) {
row[this.fileLocationName] = JSON.stringify(row[this.fileLocationName])
// 结束
add(row).then(
() => {
done();
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!",
});
},
(error) => {
window.console.log(error);
loading();
}
);
},
// 编辑数据调取接口
rowUpdate(row, index, done, loading) {
// 修改事件
// row[this.tableDisplay] = ""; //表格显示的字段
row[this.fileLocationName] = JSON.stringify(row[this.fileLocationName])
// 结束
update(row).then(
() => {
done();
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!",
});
},
(error) => {
window.console.log(error);
loading();
}
);
},
// 点击查看/编辑查看数据
beforeOpen(done, type) {
this.$nextTick(() => {
this.$refs.showFileList.add(type);//调用组件方法
});
if (["edit", "view"].includes(type)) {
getDetail(this.form.id).then((res) => {
this.form = this.formData(res, this.fileLocationName)
});
}
done();
},
searchReset() {
this.query = {};
this.onLoad(this.page);
},
searchChange(params, done) {
this.query = params;
this.page.currentPage = 1;
this.onLoad(this.page, params);
done();
},
selectionChange(list) {
this.selectionList = list;
},
selectionClear() {
this.selectionList = [];
this.$refs.crud.toggleSelection();
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
this.onLoad(this.page);
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
// 页面初始数据加载
onLoad(page, params = {}) {
this.loading = true;
params.mytype = "3";
getList(
page.currentPage,
page.pageSize,
Object.assign(params, this.query)
).then((res) => {
const data = res.data.data;
this.page.total = data.total;
this.data = this.dataRecords(data, this.fileLocationName)
this.loading = false;
this.selectionClear();
});
},
},
注意:
文件上传:
1)、type:'upload'
2)、
dataType
配置数据的结构string
或object,
当
dataType
配置为object
时,可以配置props
存储的数据结构
label
图片的名称value
路径地址3)、
propsHttp
配置请求接口返回的数据结构
name
图片的名称url
路径地址res
返回数据层级结构home
相对路径的主路径意思就是你配置
dataType为object,传给后台:json数据格式
eg:****"[{\"name\":\"原平经济技术开发区化工园区禁限控目录.pdf\",\"link\":\"/261267-sksoft/upload/20230828/8855ad3f839c2831c2c07c9f8f645af6.pdf\"}]"
字段回显就会是中文,不需要自己在单独处理数据
4)、action:是上传文件调取的接口
5)、showfile文件是我写的公共的上文件组件 不使用原生的预览样式,自己封装的
6)、rowUpdate - rowSave - beforeopen - onLoad页面中使用的方法是我封装的mixins的方法
7)、fileLocationName定义的是上传文件的给后端传接口的字段名字,因为名字不同所以写了这个来定义
3、showfile文件
javascript
<template>
<div>
// 不使用avue原生的预览样式
<el-dialog title="预览与下载" :visible.sync="dialogVisible" width="60%" :fullscreen="dialogFull"
:before-close="handleClose" :append-to-body="true" :modal-append-to-body="false">
<template slot="title">
<div class="avue-crud__dialog__header">
<span class="el-dialog__title">
<span style="
display: inline-block;
background-color: #3478f5;
width: 3px;
height: 20px;
margin-right: 5px;
float: left;
margin-top: 2px;
"></span>
预览与下载
</span>
<div class="avue-crud__dialog__menu" @click="dialogFull ? (dialogFull = false) : (dialogFull = true)">
<i class="el-icon-full-screen"></i>
</div>
</div>
</template>
<div class="dialogVisible">
<div class="dialogVisible_left">
<!-- <img class="imgurl" :src="imgurl" /> -->
<iframe id="frmDialog" frameborder="0" width="100%" height="750rpx" allowfullscreen="true"
:src="pdfWord"></iframe>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="handleClose">取 消</el-button>
<el-button type="primary" @click="dialogVisibleDow">下载</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
props: {
tableDisplay: String,
fileUpdata: String,
fileLocationName: String
},
data() {
return {
dialogFull: false,
dialogVisible: false,
pdfWord: "",
imgurl: "",
flieName: [],
fileUrl: [],
dowName: "",
addName: [],
annexStrList: [],
demoDel: [],
btnAnnexStrList: []
};
},
methods: {
// 全屏
handleClose(done) {
this.dialogVisible = false
this.dialogFull = false,
done();
},
// 文件预览
downloadAnnex(e, data) {
this.dowName = data;
// let KKFILEIP = "线上地址";
let KKFILEIP = "http://127.0.0.1";
// const fileurl =""
// if(e.indexOf(window.location.origin)>=0){
// fileurl =e
// }else{
// fileurl = window.location.origin + e;
// }
// const fileurl = window.location.origin + e;
// const fileurl = '地址' + e;
const fileurl = '测试地址' + e;
console.log(fileurl, 'fileurl');
this.imgurl = fileurl;
this.pdfWord =
KKFILEIP +
// ":10001/preview/onlinePreview?url=" +
":8012/onlinePreview?url=" +
encodeURIComponent(Base64.encode(fileurl));
this.dialogVisible = true;
},
// 下载图片
dialogVisibleDow() {
getBlob(this.imgurl).then((blob) => {
saveAs(blob, this.dowName);
});
function getBlob(url) {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
}
};
xhr.send();
});
}
function saveAs(blob, filename) {
const elelink = document.createElement("a");
elelink.style.display = "none";
elelink.download = filename;
elelink.href = window.URL.createObjectURL(blob);
document.body.appendChild(elelink);
elelink.click();
document.body.removeChild(elelink);
}
},
// 上传前方法
frontUploadBefore(file, done, loading, column) {
this.flieName.push(file.name);
done();
},
// 上传后方法
behindUploadAfter(res, done, loading, column) {
if (this.annexStrList[0] == "" || this.annexStrList[0] == ",") {
this.annexStrList = []
}
let a = { url: res.link, name: res.originalName }
// // this.addName.push(res.link + "-" + res.originalName)
this.addName.push(a)
this.annexStrList.push(a.url)
done();
},
// 删除前的方法
frontUploadDelete(file, column) {
this.fileUrl.push(file.url);
this.demoDel.push(this.annexStrList[file.uid])
this.annexStrList.splice(file.uid, 1)
},
//
//打开时候要执行的东西
add(type) {
this.addName = [];
this.demoDel = [];
if (type == "add") {
this.flieName = [];
}
},
addRes(res) {
if (res.data.data[this.tableDisplay]) {
let filelist = JSON.parse(res.data.data[this.tableDisplay]);
let alist = [];
for (let i = 0; i < filelist.length; i++) {
let b = { name: filelist[i].name, url: filelist[i].url }
alist.push(b);
}
this.annexStrList = alist
return alist;
}
},
flieNameList() {
return this.flieName
},
fileUrlList() {
this.fileUrl = []
},
demoDelList() {
return this.demoDel.toString();
},
addNameList() {
return JSON.stringify(this.addName)
},
annexStrNameList() {
return this.annexStrList.toString()
},
annexStrNameListView() {
return this.annexStrList
},
//初始加载
flieOnload(data) {
for (let i = 0; i < data.records.length; i++) {
let allName = [];
if (data.records[i][this.tableDisplay]) {
data.records[i][this.tableDisplay] = data.records[i][this.tableDisplay].split(",");
let arr = data.records[i][this.tableDisplay];
for (let j = 0; j < arr.length; j++) {
let index = arr[j].indexOf("-");
let list = arr[j].substring(index + 1, arr[j].length);
allName.push(list.toString());
}
data.records[i][this.fileUpdata] = allName;
data.records[i][this.fileLocationName] = data.records[i][this.fileLocationName].split(",");
}
}
},
},
};
</script>
<style scoped lang="scss">
/* dialog*/
.el-dialog__header {
padding: 15px 20px 15px;
}
.el-dialog__headerbtn {
top: 15px;
}
/*dialog header*/
/deep/.el-dialog__header {
background: #e3eaed;
}
/deep/.avue-crud__dialog__header {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
}
/deep/.el-dialog__title {
color: rgba(0, 0, 0, 0.85);
font-weight: 500;
word-wrap: break-word;
}
/deep/.avue-crud__dialog__menu {
padding-right: 20px;
float: left;
}
/deep/.avue-crud__dialog__menu i {
color: #909399;
font-size: 15px;
}
/deep/.el-icon-full-screen {
cursor: pointer;
}
/deep/.el-icon-full-screen:before {
content: "\e719";
}
.download {
color: rgb(50, 185, 226);
}
.dialogVisible {
display: flex;
}
.dialogVisible_right {
width: 50%;
}
.dialogVisible_left {
width: 100%;
}
.imgurl {
height: 100%;
width: 100%;
}
</style>
注意:这一块代码可能会有点乱,vue页面 有上传前,上传后方法就不会使用shoefile文件的方法,showfile页面的方法是针对图片上传的方法
4、updateFileLocation文件
javascript
export const updateFileLocation = {
methods: {
formFileLocation(res, fileLocationName) {
let a = [
...this.form[fileLocationName],
{
name: res.originalName,
link: res.link,
},
]
return a
},
isJSON(data) {
try {
JSON.parse(data)
return true
} catch (error) {
return false
}
},
formData(res, fileLocationName) {
let b = this.isJSON(res.data.data[fileLocationName])
? JSON.parse(res.data.data[fileLocationName])
: ''
return b
},
dataRecords(data, fileLocationName) {
return data.records.map((i) => {
const obj = this.isJSON(i[fileLocationName])
? JSON.parse(i[fileLocationName])
: ''
i[fileLocationName] = obj || null
return i
})
},
},
}