vue自定义组件实现文件列表预览与下载
由于ant-design-vue自带的a-upload组件与JeecgBoot封装的j-upload组件在查看上传文件列表时都不太满足项目需要,就自定义了文件列表查看组件,主要仿a-upload组件list-type="picture-card"样式设计,封装了在线预览(仅实现了图片与pdf文件的预览功能)和下载功能。1.首先安装vue-pdf插件 用于预览pdfnpm install --sav
·
由于ant-design-vue自带的a-upload组件与JeecgBoot封装的j-upload组件在查看上传文件列表时都不太满足项目需要,就自定义了文件列表查看组件,主要仿a-upload组件list-type="picture-card"样式设计,封装了在线预览(仅实现了图片与pdf文件的预览功能)和下载功能。
1.首先安装vue-pdf插件 用于预览pdf
npm install --save vue-pdf
2.组件FileList.vue代码如下 放置在src/components/FileList
<template>
<div>
<a-row :gutter="16">
<a-col :span="8" v-for="(item,i) in fileList">
<div class="upload-item">
<span class="file-type" :style="getFileTypeIcon(item)"></span>
<div class="master">
<a-space class="operator">
<a @click="handlePreview(item)" alt="查看文件" class=""><a-icon type="eye" /></a>
<a @click="handleDownload(item)" alt="下载文件" ><a-icon type="download" /></a>
</a-space>
</div>
</div>
</a-col>
</a-row>
<!--图片预览 by cuizhiyun --20220225-->
<a-modal :visible="previewVisible" @cancel="handleCancel" @ok="handleCancel">
<img :alt="fileName" style="width: 100%" :src="previewImage" />
</a-modal>
<a-modal width="1000px" :visible="previewPdfVisible" @cancel="handlePdfCancel" @ok="handlePdfCancel">
<pdf
ref="pdf"
v-for="i in pdfNumPages"
:key="i"
:page="i"
:src="previewPdf">
</pdf>
</a-modal>
<!--图片预览 end by cuizhiyun --20220225-->
</div>
</template>
<script>
import pdf from 'vue-pdf';
export default {
name: 'FileList',
components: {
pdf
},
data() {
return {
previewVisible: false,
previewImage:'',
fileName:'',
previewPdfVisible:false,
previewPdf:'',
pdfNumPages: null, // pdf 总页数
}
},
props: {
fileList: {
type: Array,
required: false,
default: []
},
},
methods:{
handleCancel(){
this.previewVisible = false;
},
handlePdfCancel(){
this.previewPdfVisible = false;
},
//查看文件
handlePreview(fileName){
let fileUrl=process.env.VUE_APP_API_BASE_URL + "/sys/common/static/"+fileName;
console.log(fileUrl);
let suffix=this.getSuffix(fileName);
if(['jpg','gif','png','jpeg','bmp','webp'].indexOf(suffix)!=-1){//图片预览
this.previewVisible=true;
this.fileName=fileName;
this.previewImage=fileUrl;
}else if(['pdf'].indexOf(suffix)!=-1){
this.previewPdfVisible=true;
this.previewPdf=fileUrl;
//计算pdf页码总数
let loadingTask = pdf.createLoadingTask(this.previewPdf)
loadingTask.promise.then(pdf => {
this.pdfNumPages = pdf.numPages
}).catch(err => {
this.$message.error('pdf 加载失败:'+ err);
})
}else{//非图片打开新窗口
location.href = fileUrl;
//window.open(fileUrl,'_blank');
}
},
//下载文件
handleDownload(file){
location.href=process.env.VUE_APP_API_BASE_URL + "/sys/common/static/"+file;
},
getSuffix(fileName){
return fileName.substring(fileName.indexOf('.')+1);
},
getFileTypeIcon(fileName){
let suffix=this.getSuffix(fileName);
let fileType='txt';
if(['jpg','gif','png','jpeg','bmp','webp'].indexOf(suffix)!=-1){
fileType='pic';
}else if(['doc','docx'].indexOf(suffix)!=-1){
fileType='doc';
}else if(['pdf'].indexOf(suffix)!=-1){
fileType='pdf';
}else{
fileType='txt';
}
return 'background: url(\'/img/'+fileType+'.png\') no-repeat';
},
}
}
</script>
<style scoped>
>>> .upload-item{
position: relative;
height: 100px;
width: 100px;
padding: 8px;
border: 1px solid #d9d9d9;
border-radius: 4px;
margin-bottom: 16px;
}
>>> .upload-item .file-type{
content:'';
width: 40px;
height: 40px;
position: absolute;
left:50%;
transform: translateX(-50%);
}
>>> .upload-item .master{
display: none;
height: 84px;
width: 84px;
margin: 0 8px 8px 0;
background: #000;
z-index: 1;
position: absolute;
opacity:0.5;
}
>>> .upload-item:hover .master{
display: block;
}
>>> .upload-item .operator{
width: 80px;
position: absolute;
left:17px;
top:30px;
}
>>> .upload-item .operator .anticon{
font-size: 20px;
color: #fff;
}
</style>
3.使用组件
import FileList from '@/components/FileList'
export default {
name: 'StartPermitApplicationForm',
components: {
FileList
},
}
<a-col :span="12">
<a-form-model-item label="银企直连授权书" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<file-list :fileList="bankArr"></file-list>
</a-form-model-item>
</a-col>
4.使用组件 完整代码如下
<template>
<a-spin :spinning="confirmLoading">
<j-form-container>
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="12">
<a-form-model-item label="项目名称" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input v-model="mainProjectName" placeholder="请输入项目名称" disabled style="width: 960px"></a-input>
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24" style="display: none">
<a-form-model-item label="项目id" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="mainProjectId">
<a-input v-model="model.mainProjectId" placeholder="请输入项目id" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="合同金额" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input-number class="t_right" v-model="contractAomunt" placeholder="请输入合同金额" :disabled="true" style="width: 100%"
:formatter="value => `${value}元`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
:parser="value => value.replace(/(,*)/g, '').replace('元', '')"
></a-input-number>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="农工费占比" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<a-input class="t_right" v-model="workerCostRate" placeholder="请输入农工费占比" :disabled="true" suffix="%" ></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="银企直连授权书" :labelCol="labelCol" :wrapperCol="wrapperCol" >
<file-list :fileList="bankArr"></file-list>
</a-form-model-item>
</a-col>
<!--<a-col :span="24">
<a-form-model-item label="审批状态" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="approvalStatus">
<a-input-number v-model="model.approvalStatus" placeholder="请输入审批状态" style="width: 100%" />
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="审批时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="approvalDate">
<j-date placeholder="请选择审批时间" v-model="model.approvalDate" style="width: 100%" />
</a-form-model-item>
</a-col>-->
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
import FileList from '@/components/FileList'
export default {
name: 'StartPermitApplicationForm',
components: {
FileList
},
props: {
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
projectCode:'',
contractAomunt:'',
workerCostRate:'',
workerCost:'',
mainContName:'',
mainProjectName:"",
mainCreditCode:'',
account:'',
bank:'',
noticeArr:[],
contractArr:[],
licenceArr:[],
cashArr:[],
bankArr:[],
model:{
},
labelCol: {
xs: { span: 24 },
sm: { span: 5 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
},
url: {
add: "/project/startPermitApplication/add",
edit: "/project/startPermitApplication/edit",
queryById: "/project/startPermitApplication/queryById",
queryByProjectId:"/project/startPermitApplication/queryByProjectId",
queryWinBidNoticeByProjectId:"/project/winBidNotice/queryByProjectId",
queryContractByProjectId:"/project/generalContract/queryByProjectId",
queryAccountByProjectId:"/project/specialAccount/queryByProjectId",
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
},
methods: {
initProject(project){
this.model.mainProjectId = project.id;
this.mainProjectName = project.mainProjectName;
this.model.mainContractorId = project.mainContractorId;
this.mainContName = project.mainContractorName;
this.model.mainDeptId = project.mainDeptId;
this.model.mainDeptName = project.mainDeptName;
this.model.settlementId = project.settlementId;
this.model.regionCode = project.regionCode;
this.projectCode = project.mainProjectCode;
getAction(this.url.queryByProjectId,{projectId:project.id}).then((res) =>{
if (res.success) {
//如果更新了总包项目怎么办,所以这个地方每次要最新的
this.model.id=res.result.id;
// this.model = Object.assign({}, res.result);
}
})
//获取营业执照号
getAction('/project/company/company/queryById',{id:project.mainContractorId}).then(response => {
this.mainCreditCode = response.result.uniformSocialCreditCode;
this.$forceUpdate()
});
//获取中标通知书信息
getAction(this.url.queryWinBidNoticeByProjectId,{projectId:project.id}).then(response => {
if(response.success){
this.model.winBidId = response.result.id;
this.noticeArr = response.result.attachment.split(',');
this.$forceUpdate()
}else {
this.$message.error("请先上报中标通知书")
this.$emit('cancel');
}
});
//获取总包合同信息
getAction(this.url.queryContractByProjectId,{projectId:project.id}).then(response => {
if(response.success){
this.model.generalContractId = response.result.id;
this.contractAomunt = response.result.contractAmount;
this.workerCostRate = response.result.workerCostProportion;
this.workerCost = (Number(response.result.contractAmount) * Number(response.result.workerCostProportion) / 100).toFixed(2);
this.contractArr = response.result.attachment.split(',');
this.$forceUpdate()
}else {
this.$message.error("请先上报总包合同")
this.$emit('cancel');
}
});
//获取农民工专户信息
getAction("/project/regionConfig/queryByRegionCodeAndAmount",{regionCode:project.regionCode,amount:project.contractAmount}).then((res) =>{
if (res.success) {
getAction(this.url.queryAccountByProjectId,{projectId:project.id}).then(response => {
if(response.success){
this.model.specialAccountId = response.result.id;
this.account = response.result.bankAccount;
this.bank = response.result.bankDeposit;
this.licenceAttr = response.result.licenceAttachment;
this.cashArr = response.result.cashManageAttachment.split(',');
this.bankArr = response.result.bankCorporateAttachment.split(',');
this.$forceUpdate()
}else {
this.$message.error("请先上报农民工专户")
this.$emit('cancel');
}
});
}
})
},
add () {
this.edit(this.modelDefault);
},
edit (record) {
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm () {
const that = this;
// 触发表单验证
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>
<style scoped>
>>> .t_right{
text-align: right!important;
}
>>> .t_right .ant-input-number-input{
text-align: right!important;
}
</style>
更多推荐
已为社区贡献3条内容
所有评论(0)