外宿申请-附件回显bug
This commit is contained in:
@@ -1,47 +1,33 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<el-upload
|
<el-upload :style="uploadStyle" action="" :class="['cm-affix', { 'is-disabled': inputDisabled }]"
|
||||||
:style="uploadStyle"
|
:disabled="inputDisabled" :multiple="true" :http-request="handleUpload" :file-list="fileList" :accept="accpet"
|
||||||
action=""
|
:show-file-list="false" :before-upload="handleBeforeUpload">
|
||||||
:class="['cm-affix', {'is-disabled': inputDisabled}]"
|
<el-button v-if="inputDisabled !== true" id="affix1" :disabled="notupload" size="small" type="primary"><i
|
||||||
:disabled="inputDisabled"
|
class='el-icon-upload2'></i>点击上传</el-button>
|
||||||
:multiple="true"
|
<el-button v-if="this.affixId !== null && this.affixId !== '' && this.fileList.length > 0" id="affix2"
|
||||||
:http-request="handleUpload"
|
size="small" @click.stop="downloadPack()">
|
||||||
:file-list="fileList"
|
<div v-if="downloading" class="el-icon-loading file-upload"
|
||||||
:accept="accpet"
|
style="margin-left: 0px;margin-right: 3px;font-size: 14px;" />
|
||||||
:show-file-list="false"
|
|
||||||
:before-upload="handleBeforeUpload"
|
|
||||||
>
|
|
||||||
<el-button v-if="inputDisabled !== true" id="affix1" :disabled="notupload" size="small" type="primary"><i class='el-icon-upload2'></i>点击上传</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="this.affixId !== null && this.affixId !== '' && this.fileList.length > 0"
|
|
||||||
id="affix2"
|
|
||||||
size="small"
|
|
||||||
@click.stop="downloadPack()"
|
|
||||||
>
|
|
||||||
<div v-if="downloading" class="el-icon-loading file-upload" style="margin-left: 0px;margin-right: 3px;font-size: 14px;" />
|
|
||||||
打包下载
|
打包下载
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
|
|
||||||
<div v-for="(item, index) in fileList" :key="index" class="file">
|
<div v-for="(item, index) in fileList" :key="index" class="file">
|
||||||
<div class="file-item" :class="[{'is-disabled': inputDisabled}]">
|
<div class="file-item" :class="[{ 'is-disabled': inputDisabled }]">
|
||||||
<div class="file-name">{{ item.name }}</div>
|
<div class="file-name">{{ item.name }}</div>
|
||||||
<div v-if="item.status===1" class="el-icon-loading file-upload" title="上传中..." />
|
<div v-if="item.status === 1" class="el-icon-loading file-upload" title="上传中..." />
|
||||||
<div v-if="item.status===2" class="el-icon-download file-download" title="下载" @click="downloadFile(item)" />
|
<div v-if="item.status === 2" class="el-icon-download file-download" title="下载" @click="downloadFile(item)" />
|
||||||
<div v-if="item.status===2" class="el-icon-delete file-delete" title="删除" @click="deleteFile(item)" />
|
<div v-if="item.status === 2" class="el-icon-delete file-delete" title="删除" @click="deleteFile(item)" />
|
||||||
<div v-if="isImageURL(item.name) && item.status === 2" class="el-icon-picture" title="预览" @click="preview(item)" />
|
<div v-if="isImageURL(item.name) && item.status === 2" class="el-icon-picture" title="预览"
|
||||||
|
@click="preview(item)" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-image v-show="false" ref="preview"
|
<el-image v-show="false" ref="preview" class="preview" :src="hiddenSrc" :preview-src-list="previewList" />
|
||||||
class="preview"
|
|
||||||
:src="hiddenSrc"
|
|
||||||
:preview-src-list="previewList"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -49,310 +35,379 @@
|
|||||||
import { deleteAffix, download, downloadAll, queryAffixs, upload } from '@/api/affix/affix'
|
import { deleteAffix, download, downloadAll, queryAffixs, upload } from '@/api/affix/affix'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CmAffix',
|
name: 'CmAffix',
|
||||||
inject: {
|
inject: {
|
||||||
elForm: {
|
elForm: {
|
||||||
default: ''
|
default: ''
|
||||||
}
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
notupload:{
|
|
||||||
type:Boolean,
|
|
||||||
default:false
|
|
||||||
},
|
|
||||||
value: String, // 父组件值
|
|
||||||
disabled: Boolean,
|
|
||||||
maxSize:{
|
|
||||||
type: Number,
|
|
||||||
default: 20
|
|
||||||
},
|
|
||||||
accpet:{
|
|
||||||
type:String,
|
|
||||||
default:'*'
|
|
||||||
},
|
|
||||||
uploadStyle:
|
|
||||||
{
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
uploadCnt: 0,
|
|
||||||
affixId: '',
|
|
||||||
fileList: [],
|
|
||||||
downloading:false,//控制打包下载loading动画
|
|
||||||
baseurl: process.env.VUE_APP_BASE_API ,
|
|
||||||
hiddenSrc:'',
|
|
||||||
previewList:[],
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
inputDisabled() {
|
|
||||||
return this.disabled || (this.elForm || {}).disabled
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
// 父组件值监听事件
|
|
||||||
value: {
|
|
||||||
handler: function(newVal/*, oldVal*/) {
|
|
||||||
if (newVal === undefined || newVal == null || newVal === ''
|
|
||||||
|| this.affixId === undefined || this.affixId == null || this.affixId === ''
|
|
||||||
|| newVal !== this.affixId) {
|
|
||||||
this.loadData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.loadData()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
// 预览
|
|
||||||
preview(item){
|
|
||||||
this.hiddenSrc = item.savePath
|
|
||||||
|
|
||||||
this.$refs.preview.showViewer = true
|
|
||||||
},
|
|
||||||
isImageURL(url) {
|
|
||||||
// let imgRegex = /(\jpg|\jpeg|\png|\gif|\webp)$/i;
|
|
||||||
const regex = /(\jpg|\jpeg|\png|\gif|\webp)$/i
|
|
||||||
return regex.test(url)
|
|
||||||
},
|
|
||||||
handleUpload(file) {
|
|
||||||
|
|
||||||
upload({'file': file.file, 'affixId': this.affixId}).then(res => {
|
|
||||||
this.uploadCnt--
|
|
||||||
|
|
||||||
if (res.code == 200) {
|
|
||||||
for (let i = 0; i < this.fileList.length; i++) {
|
|
||||||
let item = this.fileList[i]
|
|
||||||
console.log(res.savePath)
|
|
||||||
if(item.name == res.trueName && item.status == 1){
|
|
||||||
|
|
||||||
this.fileList[i].id = res.id
|
|
||||||
this.fileList[i].status = 2
|
|
||||||
this.fileList[i].savePath = this.baseurl + res.savePath
|
|
||||||
if(this.isImageURL(res.savePath)){
|
|
||||||
this.previewList.push( this.fileList[i].savePath)
|
|
||||||
}
|
|
||||||
// this.fileList[i].savePaths =[this.baseurl + res.savePath];
|
|
||||||
|
|
||||||
// 上传成功后,向外传递当前文件的完整信息(包含后端返回的res数据)
|
|
||||||
this.$emit('fileUploaded', {
|
|
||||||
fileId: res.id, // 文件ID
|
|
||||||
fileName: res.trueName, // 文件名
|
|
||||||
filePath: res.savePath, // 文件相对路径(不含baseurl)
|
|
||||||
fullPath: this.fileList[i].savePath, // 完整路径(含baseurl)
|
|
||||||
fileType: this.getFileType(res.trueName), // 文件类型
|
|
||||||
originalFile: file.file // 原始文件对象(可选)
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.message)
|
|
||||||
}
|
|
||||||
}).catch(() => {
|
|
||||||
this.uploadCnt--
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 获取文件类型的方法(Affix组件中新增)
|
|
||||||
getFileType(fileName) {
|
|
||||||
if (!fileName) return '';
|
|
||||||
const lastDotIndex = fileName.lastIndexOf('.');
|
|
||||||
return lastDotIndex > -1 ? fileName.substring(lastDotIndex + 1).toLowerCase() : '';
|
|
||||||
},
|
|
||||||
handleBeforeUpload(file) {
|
|
||||||
|
|
||||||
if (this.affixId == null || this.affixId === '') {
|
|
||||||
this.affixId = this.$tool.uuid()
|
|
||||||
this.$emit('input', this.affixId)
|
|
||||||
}
|
|
||||||
|
|
||||||
let isLt20M = file.size / 1024 / 1024 < this.maxSize
|
|
||||||
if (!isLt20M) {
|
|
||||||
this.$message.error('上传大小不能超过 '+this.maxSize+'MB!')
|
|
||||||
} else {
|
|
||||||
this.fileList.push({name: file.name, status: 1})
|
|
||||||
this.uploadCnt++
|
|
||||||
}
|
|
||||||
|
|
||||||
return isLt20M
|
|
||||||
},
|
|
||||||
getFileName(id){
|
|
||||||
for (let i = 0; i < this.fileList.length; i++) {
|
|
||||||
let item = this.fileList[i]
|
|
||||||
|
|
||||||
if(item.id == id){
|
|
||||||
console.log(item)
|
|
||||||
return item.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
downloadFile(file) {
|
|
||||||
download(file.id).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
let fileName = this.getFileName(file.id).replace(/"/g, '')
|
|
||||||
var blob = new Blob([res], {type: 'application/octet-stream;'})
|
|
||||||
var downloadElement = document.createElement('a')
|
|
||||||
var href = window.URL.createObjectURL(blob) // 创建下载的链接
|
|
||||||
downloadElement.href = href
|
|
||||||
downloadElement.download = decodeURI(fileName) // 下载后文件名
|
|
||||||
document.body.appendChild(downloadElement)
|
|
||||||
downloadElement.click() // 点击下载
|
|
||||||
document.body.removeChild(downloadElement) // 下载完成移除元素
|
|
||||||
window.URL.revokeObjectURL(href) // 释放掉blob对象
|
|
||||||
}).catch((res) => {
|
|
||||||
this.$message.error(res.message)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
downloadPack() {
|
|
||||||
|
|
||||||
if (this.affixId === null || this.affixId === '') {
|
|
||||||
this.$message.error('暂无附件!')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//如果只有一个文件就不打包下载
|
|
||||||
if(this.fileList.length == 1){
|
|
||||||
|
|
||||||
this.downloadFile(this.fileList[0])
|
|
||||||
}else{
|
|
||||||
this.downloading = true
|
|
||||||
downloadAll(this.affixId).then((res) => {
|
|
||||||
var blob = new Blob([res], {type: 'application/octet-stream'})
|
|
||||||
var downloadElement = document.createElement('a')
|
|
||||||
var href = window.URL.createObjectURL(blob) // 创建下载的链接
|
|
||||||
downloadElement.href = href
|
|
||||||
downloadElement.download = decodeURI('download.zip') // 下载后文件名
|
|
||||||
document.body.appendChild(downloadElement)
|
|
||||||
downloadElement.click() // 点击下载
|
|
||||||
document.body.removeChild(downloadElement) // 下载完成移除元素
|
|
||||||
window.URL.revokeObjectURL(href) // 释放掉blob对象
|
|
||||||
this.downloading = false
|
|
||||||
}).catch(() => {
|
|
||||||
this.downloading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
deleteFile(file) {
|
|
||||||
this.$confirm('请确认是否删除此文件?', '提示', {type: 'info'}).then(() => {
|
|
||||||
deleteAffix(file.id).then((res) => {
|
|
||||||
if (res.code == 200) {
|
|
||||||
this.fileList = this.fileList.filter(item => item.id !== file.id)
|
|
||||||
this.previewList = this.previewList.filter(item => item !== file.savePath)//删除图片
|
|
||||||
if(this.fileList.length == 0){
|
|
||||||
this.affixId = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关键:触发自定义事件,传递被删除的文件名
|
|
||||||
// 事件名建议:delete-file,参数:file.name(文件名)
|
|
||||||
this.$emit('delete-file', file.name);
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.message)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
loadData() {
|
|
||||||
this.fileList = []
|
|
||||||
if (typeof this.value !== 'undefined' && this.value !== null && this.value !== '') {
|
|
||||||
queryAffixs(this.value).then((res) => {
|
|
||||||
if (res.code ==200) {
|
|
||||||
if(res.data.length > 0){
|
|
||||||
this.affixId = this.value
|
|
||||||
for (var i=0;i<res.data.length;i++) {
|
|
||||||
if(this.isImageURL(res.data[i].savePath)){
|
|
||||||
this.previewList.push(this.baseurl+ res.data[i].savePath)
|
|
||||||
}
|
|
||||||
this.fileList.push({name: res.data[i].trueName, id: res.data[i].id, status: 2,savePath:this.baseurl+ res.data[i].savePath})
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.affixId = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.$message.error(res.msg)
|
|
||||||
}
|
|
||||||
}).catch((res) => {
|
|
||||||
this.editLoading = false
|
|
||||||
this.$message.error(res.message)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.affixId = ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
clearData() {
|
|
||||||
this.affixId = ''
|
|
||||||
this.fileList = []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
notupload: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
value: String, // 父组件值
|
||||||
|
disabled: Boolean,
|
||||||
|
maxSize: {
|
||||||
|
type: Number,
|
||||||
|
default: 20
|
||||||
|
},
|
||||||
|
accpet: {
|
||||||
|
type: String,
|
||||||
|
default: '*'
|
||||||
|
},
|
||||||
|
uploadStyle:
|
||||||
|
{
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
uploadCnt: 0,
|
||||||
|
affixId: '',
|
||||||
|
fileList: [],
|
||||||
|
downloading: false,//控制打包下载loading动画
|
||||||
|
baseurl: process.env.VUE_APP_BASE_API,
|
||||||
|
hiddenSrc: '',
|
||||||
|
previewList: [],
|
||||||
|
// 解决重复提交的核心变量
|
||||||
|
isQuerying: false, // 请求锁:标记是否正在查询附件
|
||||||
|
retryCount: 0 // 重试次数:捕获重复提交错误时重试
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
inputDisabled() {
|
||||||
|
return this.disabled || (this.elForm || {}).disabled
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 父组件值监听事件
|
||||||
|
value: {
|
||||||
|
immediate: true, // 初始化立即执行
|
||||||
|
handler: function (newVal, oldVal) {
|
||||||
|
// 新旧值不同时,先清空所有旧数据(核心解决数据残留)
|
||||||
|
if (newVal !== oldVal) {
|
||||||
|
this.fileList = [];
|
||||||
|
this.previewList = [];
|
||||||
|
this.affixId = '';
|
||||||
|
this.retryCount = 0;
|
||||||
|
}
|
||||||
|
// 满足条件才加载数据
|
||||||
|
if (newVal && newVal !== '' && newVal !== this.affixId) {
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.loadData()
|
||||||
|
},
|
||||||
|
// 新增:组件激活时清空旧数据(适配keep-alive页面)
|
||||||
|
activated() {
|
||||||
|
this.fileList = [];
|
||||||
|
this.previewList = [];
|
||||||
|
if (this.value) {
|
||||||
|
this.loadData();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 预览
|
||||||
|
preview(item) {
|
||||||
|
this.hiddenSrc = item.savePath
|
||||||
|
|
||||||
|
this.$refs.preview.showViewer = true
|
||||||
|
},
|
||||||
|
isImageURL(url) {
|
||||||
|
// let imgRegex = /(\jpg|\jpeg|\png|\gif|\webp)$/i;
|
||||||
|
const regex = /(\jpg|\jpeg|\png|\gif|\webp)$/i
|
||||||
|
return regex.test(url)
|
||||||
|
},
|
||||||
|
handleUpload(file) {
|
||||||
|
|
||||||
|
upload({ 'file': file.file, 'affixId': this.affixId }).then(res => {
|
||||||
|
this.uploadCnt--
|
||||||
|
|
||||||
|
if (res.code == 200) {
|
||||||
|
for (let i = 0; i < this.fileList.length; i++) {
|
||||||
|
let item = this.fileList[i]
|
||||||
|
console.log(res.savePath)
|
||||||
|
if (item.name == res.trueName && item.status == 1) {
|
||||||
|
|
||||||
|
this.fileList[i].id = res.id
|
||||||
|
this.fileList[i].status = 2
|
||||||
|
this.fileList[i].savePath = this.baseurl + res.savePath
|
||||||
|
if (this.isImageURL(res.savePath)) {
|
||||||
|
this.previewList.push(this.fileList[i].savePath)
|
||||||
|
}
|
||||||
|
// this.fileList[i].savePaths =[this.baseurl + res.savePath];
|
||||||
|
|
||||||
|
// 上传成功后,向外传递当前文件的完整信息(包含后端返回的res数据)
|
||||||
|
this.$emit('fileUploaded', {
|
||||||
|
fileId: res.id, // 文件ID
|
||||||
|
fileName: res.trueName, // 文件名
|
||||||
|
filePath: res.savePath, // 文件相对路径(不含baseurl)
|
||||||
|
fullPath: this.fileList[i].savePath, // 完整路径(含baseurl)
|
||||||
|
fileType: this.getFileType(res.trueName), // 文件类型
|
||||||
|
originalFile: file.file // 原始文件对象(可选)
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.message)
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
this.uploadCnt--
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 获取文件类型的方法(Affix组件中新增)
|
||||||
|
getFileType(fileName) {
|
||||||
|
if (!fileName) return '';
|
||||||
|
const lastDotIndex = fileName.lastIndexOf('.');
|
||||||
|
return lastDotIndex > -1 ? fileName.substring(lastDotIndex + 1).toLowerCase() : '';
|
||||||
|
},
|
||||||
|
handleBeforeUpload(file) {
|
||||||
|
|
||||||
|
if (this.affixId == null || this.affixId === '') {
|
||||||
|
this.affixId = this.$tool.uuid()
|
||||||
|
this.$emit('input', this.affixId)
|
||||||
|
}
|
||||||
|
|
||||||
|
let isLt20M = file.size / 1024 / 1024 < this.maxSize
|
||||||
|
if (!isLt20M) {
|
||||||
|
this.$message.error('上传大小不能超过 ' + this.maxSize + 'MB!')
|
||||||
|
} else {
|
||||||
|
this.fileList.push({ name: file.name, status: 1 })
|
||||||
|
this.uploadCnt++
|
||||||
|
}
|
||||||
|
|
||||||
|
return isLt20M
|
||||||
|
},
|
||||||
|
getFileName(id) {
|
||||||
|
for (let i = 0; i < this.fileList.length; i++) {
|
||||||
|
let item = this.fileList[i]
|
||||||
|
|
||||||
|
if (item.id == id) {
|
||||||
|
console.log(item)
|
||||||
|
return item.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
downloadFile(file) {
|
||||||
|
download(file.id).then((res) => {
|
||||||
|
console.log(res)
|
||||||
|
let fileName = this.getFileName(file.id).replace(/"/g, '')
|
||||||
|
var blob = new Blob([res], { type: 'application/octet-stream;' })
|
||||||
|
var downloadElement = document.createElement('a')
|
||||||
|
var href = window.URL.createObjectURL(blob) // 创建下载的链接
|
||||||
|
downloadElement.href = href
|
||||||
|
downloadElement.download = decodeURI(fileName) // 下载后文件名
|
||||||
|
document.body.appendChild(downloadElement)
|
||||||
|
downloadElement.click() // 点击下载
|
||||||
|
document.body.removeChild(downloadElement) // 下载完成移除元素
|
||||||
|
window.URL.revokeObjectURL(href) // 释放掉blob对象
|
||||||
|
}).catch((res) => {
|
||||||
|
this.$message.error(res.message)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
downloadPack() {
|
||||||
|
|
||||||
|
if (this.affixId === null || this.affixId === '') {
|
||||||
|
this.$message.error('暂无附件!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//如果只有一个文件就不打包下载
|
||||||
|
if (this.fileList.length == 1) {
|
||||||
|
|
||||||
|
this.downloadFile(this.fileList[0])
|
||||||
|
} else {
|
||||||
|
this.downloading = true
|
||||||
|
downloadAll(this.affixId).then((res) => {
|
||||||
|
var blob = new Blob([res], { type: 'application/octet-stream' })
|
||||||
|
var downloadElement = document.createElement('a')
|
||||||
|
var href = window.URL.createObjectURL(blob) // 创建下载的链接
|
||||||
|
downloadElement.href = href
|
||||||
|
downloadElement.download = decodeURI('download.zip') // 下载后文件名
|
||||||
|
document.body.appendChild(downloadElement)
|
||||||
|
downloadElement.click() // 点击下载
|
||||||
|
document.body.removeChild(downloadElement) // 下载完成移除元素
|
||||||
|
window.URL.revokeObjectURL(href) // 释放掉blob对象
|
||||||
|
this.downloading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.downloading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
deleteFile(file) {
|
||||||
|
this.$confirm('请确认是否删除此文件?', '提示', { type: 'info' }).then(() => {
|
||||||
|
deleteAffix(file.id).then((res) => {
|
||||||
|
if (res.code == 200) {
|
||||||
|
this.fileList = this.fileList.filter(item => item.id !== file.id)
|
||||||
|
this.previewList = this.previewList.filter(item => item !== file.savePath)//删除图片
|
||||||
|
if (this.fileList.length == 0) {
|
||||||
|
this.affixId = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关键:触发自定义事件,传递被删除的文件名
|
||||||
|
// 事件名建议:delete-file,参数:file.name(文件名)
|
||||||
|
this.$emit('delete-file', file.name);
|
||||||
|
} else {
|
||||||
|
this.$message.error(res.message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loadData() {
|
||||||
|
// 1. 请求锁:防止同一时刻重复请求(解决重复提交)
|
||||||
|
if (this.isQuerying) return;
|
||||||
|
// 2. 清空旧数据(双重保障解决数据残留)
|
||||||
|
this.fileList = [];
|
||||||
|
this.previewList = [];
|
||||||
|
|
||||||
|
if (typeof this.value !== 'undefined' && this.value !== null && this.value !== '') {
|
||||||
|
this.isQuerying = true; // 加锁
|
||||||
|
// 带重试机制的查询方法
|
||||||
|
const queryWithRetry = () => {
|
||||||
|
queryAffixs(this.value).then((res) => {
|
||||||
|
this.isQuerying = false; // 解锁
|
||||||
|
if (res.code == 200) {
|
||||||
|
if (res.data.length > 0) {
|
||||||
|
this.affixId = this.value;
|
||||||
|
// 重新构建数组,避免引用污染
|
||||||
|
const newFileList = [];
|
||||||
|
const newPreviewList = [];
|
||||||
|
for (var i = 0; i < res.data.length; i++) {
|
||||||
|
const savePath = this.baseurl + res.data[i].savePath;
|
||||||
|
if (this.isImageURL(savePath)) {
|
||||||
|
newPreviewList.push(savePath);
|
||||||
|
}
|
||||||
|
newFileList.push({
|
||||||
|
name: res.data[i].trueName,
|
||||||
|
id: res.data[i].id,
|
||||||
|
status: 2,
|
||||||
|
savePath: savePath
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 直接替换数组,彻底解决残留
|
||||||
|
this.fileList = newFileList;
|
||||||
|
this.previewList = newPreviewList;
|
||||||
|
} else {
|
||||||
|
this.affixId = '';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 捕获"重复提交"错误,重试1次
|
||||||
|
if (res.msg.includes('请勿重复提交') && this.retryCount < 1) {
|
||||||
|
this.retryCount++;
|
||||||
|
this.isQuerying = true;
|
||||||
|
setTimeout(() => queryWithRetry(), 500); // 500ms后重试
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$message.error(res.msg);
|
||||||
|
}
|
||||||
|
}).catch((err) => {
|
||||||
|
this.isQuerying = false; // 解锁
|
||||||
|
// 捕获异常中的重复提交错误,重试1次
|
||||||
|
if (err.message?.includes('请勿重复提交') && this.retryCount < 1) {
|
||||||
|
this.retryCount++;
|
||||||
|
setTimeout(() => queryWithRetry(), 500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.$message.error(err.message || '查询附件失败');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 执行查询
|
||||||
|
queryWithRetry();
|
||||||
|
} else {
|
||||||
|
this.affixId = '';
|
||||||
|
this.isQuerying = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearData() {
|
||||||
|
this.affixId = '';
|
||||||
|
this.fileList = [];
|
||||||
|
this.previewList = [];
|
||||||
|
this.isQuerying = false;
|
||||||
|
this.retryCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.cm-affix >>>.el-upload{
|
.cm-affix>>>.el-upload {
|
||||||
padding: 0px 10px;
|
padding: 0px 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
.file {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.file-item {
|
|
||||||
|
|
||||||
white-space: nowrap;
|
|
||||||
display: flex;
|
|
||||||
justify-content: start;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
.file-item div {
|
|
||||||
display: inline-block;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.file-upload {
|
|
||||||
font-size: 18px;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
.file-download, .file-delete{
|
|
||||||
font-size: 18px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
}
|
|
||||||
.file-download:hover, .file-delete:hover {
|
|
||||||
color: #409EFF;
|
|
||||||
}
|
|
||||||
.file-item[class~=is-disabled] .file-delete {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.download-pack:hover {
|
|
||||||
background: #409eff;
|
|
||||||
border-color: #3999a8;
|
|
||||||
color: #fafbfd;
|
|
||||||
}
|
|
||||||
.preview .file-preview{
|
|
||||||
|
|
||||||
font-size: 19px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
|
.file {
|
||||||
}
|
width: 100%;
|
||||||
|
}
|
||||||
.preview >>>.el-image__inner{
|
|
||||||
|
.file-item {
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
white-space: nowrap;
|
||||||
|
display: flex;
|
||||||
}
|
justify-content: start;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item div {
|
||||||
|
display: inline-block;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-upload {
|
||||||
|
font-size: 18px;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-download,
|
||||||
|
.file-delete {
|
||||||
|
font-size: 18px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-download:hover,
|
||||||
|
.file-delete:hover {
|
||||||
|
color: #409EFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-item[class~=is-disabled] .file-delete {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-pack:hover {
|
||||||
|
background: #409eff;
|
||||||
|
border-color: #3999a8;
|
||||||
|
color: #fafbfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview .file-preview {
|
||||||
|
|
||||||
|
font-size: 19px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview>>>.el-image__inner {
|
||||||
|
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -274,7 +274,7 @@
|
|||||||
<i class="el-icon-folder" />
|
<i class="el-icon-folder" />
|
||||||
保存
|
保存
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" size="medium" @click="submitForm(1)">
|
<el-button type="primary" size="medium" @click="submitForm(1)" v-if="form.id == ''">
|
||||||
<i class="el-icon-check" />
|
<i class="el-icon-check" />
|
||||||
提交申请
|
提交申请
|
||||||
</el-button>
|
</el-button>
|
||||||
@@ -703,63 +703,52 @@ export default {
|
|||||||
submitForm(status) {
|
submitForm(status) {
|
||||||
this.$refs.formRef.validate((valid) => {
|
this.$refs.formRef.validate((valid) => {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
// 生成申请编号
|
// 生成申请编号等逻辑不变
|
||||||
if (!this.form.applyNo) {
|
if (!this.form.applyNo) {
|
||||||
const year = new Date().getFullYear();
|
const year = new Date().getFullYear();
|
||||||
const randomNo = Math.floor(Math.random() * 1000000).toString().padStart(6, '0');
|
const randomNo = Math.floor(Math.random() * 1000000).toString().padStart(6, '0');
|
||||||
this.form.applyNo = `WS${year}${randomNo}`; // 获取申请编号
|
this.form.applyNo = `WS${year}${randomNo}`;
|
||||||
}
|
}
|
||||||
// 生成外宿结束时间(默认次年8月31日)
|
|
||||||
this.form.endDate = this.getOutsideDefaultEndTime()
|
this.form.endDate = this.getOutsideDefaultEndTime()
|
||||||
// 生成本人承诺内容
|
|
||||||
this.form.promiseContent = `
|
this.form.promiseContent = `
|
||||||
<p>1.自觉遵守国家法律、法规;</p>
|
<p>1.自觉遵守国家法律、法规;</p>
|
||||||
<p>2.自觉遵守学生行为规范和学校的规章制度,遵守社会公德;</p>
|
<p>2.自觉遵守学生行为规范和学校的规章制度,遵守社会公德;</p>
|
||||||
<p>3.自觉遵守外宿住址所在社区的有关管理规定;</p>
|
<p>3.自觉遵守外宿住址所在社区的有关管理规定;</p>
|
||||||
<p>4.本人申请外宿,属个人自愿行为,外宿期间发生的一切事故,造成本人、他人或集体的人身、财产损害的,学校不负责任。</p>
|
<p>4.本人申请外宿,属个人自愿行为,外宿期间发生的一切事故,造成本人、他人或集体的人身、财产损害的,学校不负责任。</p>
|
||||||
`
|
`
|
||||||
// 将地址数组转为字符串(用 / 拼接,后端可按此分隔解析)
|
|
||||||
const submitForm = {
|
const submitForm = {
|
||||||
...this.form,
|
...this.form,
|
||||||
address: this.form.address ? this.form.address.join('/') : '', // 数组转字符串
|
address: this.form.address ? this.form.address.join('/') : '',
|
||||||
parentAddress: this.form.parentAddress ? this.form.parentAddress.join('/') : '', // 家长地址同理
|
parentAddress: this.form.parentAddress ? this.form.parentAddress.join('/') : '',
|
||||||
status: status
|
status: this.form.status != 0 ? this.form.status : status
|
||||||
};
|
};
|
||||||
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
if (this.form.id != null) {
|
// 封装请求逻辑为Promise,确保完成后再操作
|
||||||
updateOutsideAccommodationApply(submitForm).then((response) => {
|
const requestPromise = this.form.id != null
|
||||||
// 批量新增材料附件
|
? updateOutsideAccommodationApply(submitForm)
|
||||||
if (this.reasonFileList && this.reasonFileList.length > 0) {
|
: addOutsideAccommodationApply(submitForm);
|
||||||
batchAddOutsideAccommodationAttachment(this.reasonFileList)
|
|
||||||
this.resetForm()
|
requestPromise.then((response) => {
|
||||||
}
|
// 附件处理逻辑不变
|
||||||
this.loading = false;
|
if (this.reasonFileList && this.reasonFileList.length > 0) {
|
||||||
this.$modal.msgSuccess('修改成功')
|
|
||||||
this.goBack()
|
|
||||||
}).catch(error => {
|
|
||||||
this.loading = false;
|
|
||||||
this.goBack()
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
addOutsideAccommodationApply(submitForm).then((response) => {
|
|
||||||
// 填写附件里面的申请编号
|
|
||||||
this.reasonFileList.forEach(element => {
|
this.reasonFileList.forEach(element => {
|
||||||
element.applyId = response.data.id
|
element.applyId = this.form.id || response.data.id;
|
||||||
})
|
});
|
||||||
// 批量新增材料附件
|
batchAddOutsideAccommodationAttachment(this.reasonFileList);
|
||||||
if (this.reasonFileList && this.reasonFileList.length > 0) {
|
}
|
||||||
batchAddOutsideAccommodationAttachment(this.reasonFileList)
|
this.loading = false;
|
||||||
this.resetForm()
|
this.$modal.msgSuccess(this.form.id ? '修改成功' : '新增成功');
|
||||||
}
|
// 延迟跳转:给后端数据落地留时间(关键!)
|
||||||
this.loading = false;
|
setTimeout(() => {
|
||||||
this.$modal.msgSuccess('新增成功')
|
this.goBack();
|
||||||
this.goBack()
|
}, 800); // 800ms延迟,确保后端写入完成
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.goBack()
|
this.$message.error('提交失败:' + (error.msg || '服务器处理异常'));
|
||||||
})
|
// 失败时不跳转,避免用户重复操作
|
||||||
}
|
// this.goBack();
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
this.$message.error('表单填写有误,请检查!')
|
this.$message.error('表单填写有误,请检查!')
|
||||||
@@ -1143,4 +1132,4 @@ li {
|
|||||||
text-align: center !important;
|
text-align: center !important;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -44,8 +44,8 @@
|
|||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
<el-descriptions-item span="4">
|
<el-descriptions-item span="4">
|
||||||
<template slot="label"> 宿费交纳情况(只填写当年度交费情况) </template>
|
<template slot="label"> 宿费交纳情况(只填写当年度交费情况) </template>
|
||||||
<!-- {{ renderData.familyAddress }} -->
|
{{ renderData.accommodationFee }}
|
||||||
已交 绑定当前学年年度住宿费 人民币
|
<!-- 已交 绑定当前学年年度住宿费 人民币 -->
|
||||||
</el-descriptions-item>
|
</el-descriptions-item>
|
||||||
|
|
||||||
<el-descriptions-item span="2">
|
<el-descriptions-item span="2">
|
||||||
|
|||||||
@@ -150,7 +150,7 @@
|
|||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
||||||
v-hasPermi="['dormitory:outsideAccommodationApply:edit']"
|
v-hasPermi="['dormitory:outsideAccommodationApply:edit']"
|
||||||
v-if="scope.row.status == 0 || getRejectInfo(scope.row.outsideAccommodationApprovals).isReject">修改</el-button>
|
>修改</el-button>
|
||||||
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
||||||
v-hasPermi="['dormitory:outsideAccommodationApply:remove']" v-if="scope.row.status == 0">删除</el-button>
|
v-hasPermi="['dormitory:outsideAccommodationApply:remove']" v-if="scope.row.status == 0">删除</el-button>
|
||||||
<el-button v-if="scope.row.applyStatus != 0" size="mini" type="text" icon="el-icon-info"
|
<el-button v-if="scope.row.applyStatus != 0" size="mini" type="text" icon="el-icon-info"
|
||||||
|
|||||||
Reference in New Issue
Block a user