Commit c81064a3 by wanglizhen

上传文件

parent 1165d598
<script setup lang="ts" name="CustomUpload">
import { ref, getCurrentInstance, computed, onMounted, watch } from 'vue'
import { getToken } from '@/utils/auth'
import { ElMessage, ElMessageBox } from 'element-plus'
import { parseTime } from '@/utils/ruoyi'
import axios from 'axios'
// import { filePreview } from '@/api/preview'
const { proxy } = getCurrentInstance() as any
// <CustomUpload v-model:file-list="fileList"/>
// const fileList = ref([
// {
// name: 'food.jpeg',
// fileSize: '23423',
// fileType: 'img',
// url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
// createTime: '2024-01-24 16:31'
// },
// {
// name: 'food.jpeg',
// fileSize: '23423',
// fileType: 'img',
// url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100',
// createTime: '2024-01-24 16:31'
// }
// ])
type IFileList = Array<any> | null | undefined
const emit = defineEmits<{
'update:fileList': [fileList: IFileList],
'onSuccess'
}>()
const props = withDefaults(defineProps<{
fileList: IFileList
buttonPermission?: Array<string>
needType?: boolean
needSize?: boolean
needTime?:boolean
needStatus?:boolean,
acceptTypeList?:Array<string>
limit?:number,
prompt?:string,
uploadType?:number,
listShow?: boolean
}>(), {
buttonPermission: () => ['upload', 'delete'],
needType: true,
needSize: true,
needTime: true,
needStatus: true,
limit: 100,
prompt: '点击或将文件拖拽到此处上传',
uploadType: 1,
listShow: false,
// acceptTypeList: () => ['png', 'jpg', 'doc', 'docx', 'pdf']
})
const uploadFileUrl = (props.uploadType === 1 ? ref(import.meta.env.VITE_APP_BASE_API + '/core/dictionaryexcel/importfile') : ref(import.meta.env.VITE_APP_BASE_API + '/eo/TTenantContractlabelTemplateController/uploadTemporary')) // 上传文件服务器地址
const headers = ref({
Token: getToken(),
'from-source': 'platformUi',
'Content-Type': 'mulipart/form-data'
})
// const FileList = ref<Array<any>>([])
const FileList = computed({
get() {
return props.fileList
},
set(val: any) {
// console.log('fileList computed', val)
emit('update:fileList', val)
}
})
const uploadLoading = computed(() => {
if (FileList.value != null && FileList.value.some(item => item.status === 'uploading')) {
return true
}
return false
})
// const fileListlengthCompute = computed(() => {
// return props.fileList.length
// })
// watch(() => props.fileList, (val: IFileList) => {
// console.log('props.fileList', val)
// if (!val) {
// FileList.value = []
// return
// }
// FileList.value = JSON.parse(JSON.stringify(props.fileList))
// }, { deep: true, immediate: true })
// watch(fileListlengthCompute, (val) => {
// console.log(val)
// if (val === 0) {
// emit('update:fileList', [])
// FileList.value = []
// }
// }, { deep: true, immediate: true })
function updateFileList() {
emit('onSuccess')
// emit('update:fileList', FileList.value.filter(item => item.status === 'success'))
}
function beforeUpload(file) {
console.log('beforeUpload', file)
let type = file.name.split('.')
type = type[type.length - 1]
if (props.acceptTypeList.indexOf(type) >= 0) {
const list = {}
for (const key in file) {
list[key] = file[key]
}
// status:uploading、success、error 文件上传状态
// progress 文件上传进度
FileList.value.push({ ...list, progress: 0, status: 'uploading' })
// updateFileList()
httpRequest(file, parms => {
showProgress(list, parms)
})
// 阻止 el-upload的默认上传
return false
}
proxy.$modal.msgError(`文件格式不正确, 请上传${props.acceptTypeList.join('/')}格式文件!`)
return false
}
async function httpRequest(file, callback) {
let formData = new FormData()
formData.append('fileUpload', file)
let progress = 0
axios({
headers: headers.value,
method: 'post',
url: uploadFileUrl.value,
data: formData,
onUploadProgress: progressEvent => { // 获取文件上传进度 axios自带的
progress = (progressEvent.loaded / progressEvent.total * 100) | 0
callback({ progress, status: 'uploading' })
}
}).then((res) => { // 成功状态
// console.log('res', res)
let data = res.data.data
proxy.$emit('uploadSuccessCallback', data)
if (props.uploadType === 1) {
callback({ progress, status: 'success', url: data.url, id: '' })
} else {
callback({ progress, status: 'success', url: data.url, id: data.id })
updateFileList()
}
}).catch(() => { // 失败状态
callback({ progress, status: 'error' })
})
}
function showProgress(file, parms) {
const { progress, status, url } = parms
const arr = [...FileList.value].map(items => {
if (items.uid === file.uid) {
items.progress = progress
items.status = status
items.url = url
items.fileType = file.type
items.fileSize = file.size
items.createTime = parseTime(new Date(), '{y}-{m}-{d} {h}:{i}:{s}')
items.id = parms.id
}
return items
})
FileList.value = [...arr]
// updateFileList()
}
function handleAvatarSuccess(response, uploadFile) {
console.log(response)
console.log(uploadFile)
}
function handlePreviewFile(file) {
console.log(file)
filePreview(file.url)
}
function handleDownFile(file) {
const fileUrl = file.url // 文件的URL地址
fetch(fileUrl)
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.setAttribute('download', file.name)
document.body.appendChild(link)
link.click()
})
.catch(error => {
console.error(error)
})
}
function handleDeleteFile(index) {
FileList.value.splice(index, 1)
// updateFileList()
}
const cancelEvent = () => {
console.log('cancel!')
}
</script>
<template>
<div class="custom-upload-container" v-loading="uploadLoading" element-loading-text="文件上传中,请耐心等待,期间切勿进行任何操作,避免文件上传失败导致丢失。">
<el-upload
v-if="buttonPermission.indexOf('upload') >= 0"
:file-list="FileList"
:show-file-list="false"
class="upload-demo"
action="/"
drag
multiple
:before-upload="beforeUpload"
:on-success="handleAvatarSuccess"
:limit="limit"
:prompt="prompt"
>
<!-- <el-button
icon="Upload"
type="primary"
:loading="uploadLoading">上传文件</el-button> -->
<div class="upload-back">
<div class="flex-container">
<!-- <img class="logo-upload" :src="logoUpload" alt=""> -->
<div>
<el-icon :size="52" color="rgb(51, 153, 255)">
<upload-filled />
</el-icon>
</div>
<div class="text-container">
<div class="accept-type-container">{{ props.prompt }}</div>
</div>
</div>
</div>
</el-upload>
<el-row style="padding-top: 8px;" v-if="FileList&&FileList.length>0 && listShow">
<el-table :data="FileList">
<el-table-column
type="index"
width="65"
align="center"
fixed="left"
label="序号"/>
<el-table-column
prop="name"
align="left"
min-width="160"
:show-overflow-tooltip="true"
label="名称">
<template v-slot="scope">
{{ scope.row.name }}
</template>
</el-table-column>
<el-table-column
v-if="needType"
prop="fileType"
align="left"
:show-overflow-tooltip="true"
label="类型">
<template v-slot="scope">
{{ scope.row.fileType }}
</template>
</el-table-column>
<el-table-column
v-if="needSize"
align="left"
width="140"
prop="fileSize"
label="大小(KB)">
<template v-slot="scope">
{{ Number(scope.row.fileSize)/1000 }}
</template>
</el-table-column>
<el-table-column
v-if="needStatus"
align="center"
prop="name"
label="上传状态"
min-width="140">
<template v-slot="scope">
<template v-if="scope.row.status === 'success' || scope.row.name || scope.row.url"><el-tag class="ml-2" type="success">上传成功</el-tag></template>
<template v-else-if="scope.row.status === 'error'"><el-tag class="ml-2" type="danger">上传失败</el-tag></template>
<el-progress v-else :percentage="scope.row.progress"/>
</template>
</el-table-column>
<el-table-column
v-if="needTime"
align="left"
min-width="200"
prop="createTime"
label="上传时间" />
<el-table-column
align="center"
fixed="right"
label="操作"
width="200">
<template #default="scope">
<el-button
link
icon="View"
type="primary"
size="small"
:disabled="scope.row.status === 'error' || scope.row.status === 'uploading'"
@click="handlePreviewFile(scope.row)"
>预览</el-button>
<el-button
link
icon="Download"
type="primary"
size="small"
:disabled="scope.row.status === 'error' || scope.row.status === 'uploading'"
@click="handleDownFile(scope.row)">下载</el-button>
<el-popconfirm
v-if="buttonPermission.indexOf('delete') >= 0"
confirm-button-text="确认"
cancel-button-text="取消"
icon-color="#626AEF"
title="确认删除?"
@confirm="handleDeleteFile(scope.$index)"
@cancel="cancelEvent"
>
<template #reference>
<el-button
link
icon="Delete"
type="primary"
size="small"
:disabled="scope.row.status === 'uploading'"
>删除</el-button>
</template>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</el-row>
</div>
</template>
<style lang="scss" scoped>
.custom-upload-container {
width: 100%;
border-radius: 8px;
}
:deep(.el-upload){
width: 100%;
.flex-container {
display: flex;
align-items: center;
flex-direction: column;
.text-container{
font-size: 14px;
color: rgb(188, 195, 203);
}
}
}
.upload-demo {
// padding-top: 24px;
// padding-bottom: 16px;
}
.upload-item {
margin-left: 5px;
}
</style>
......@@ -73,11 +73,11 @@ const change = (val) => {
</div>
</div>
</div>
</template>
<template #footer>
<div style="display: flex; justify-content: center; padding-top: 20px;">
<el-button type="primary" style="width: 150px;" @click="test">测试</el-button>
<el-button type="info" style="width: 150px;" @click="cancel">取消</el-button>
<el-button type="primary" style="width: 150px;" @click="confirm">确认</el-button>
</div>
</template>
</ModalPop>
</template>
......
......@@ -22,18 +22,13 @@ const change = (visible: boolean) => {
</script>
<template>
<Modal class="ModalPop" v-model="props.modelValue" :width="width" draggable scrollable sticky @on-cancel="cancel" @on-visible-change="change">
<Modal class="ModalPop" footer-hide :mask-closable="false" v-model="props.modelValue" :width="width" draggable scrollable sticky @on-cancel="cancel" @on-visible-change="change">
<template #header>
<span style="font-size: 16px; font-weight: bold;color: #7A8495;">{{ props.title }}</span>
</template>
<div class="slot-warpper">
<slot name="content"></slot>
</div>
<template #footer>
<div style="display: flex; justify-content: center; padding-top: 20px;">
<slot name="footer"></slot>
</div>
</template>
</Modal>
</template>
......@@ -59,7 +54,7 @@ const change = (visible: boolean) => {
background: rgb(255, 255, 255);
padding: 30px;
border-radius: 4px;
max-height: 500px;
max-height: 550px;
}
}
</style>
\ No newline at end of file
......@@ -5,6 +5,7 @@ import { Split } from 'view-ui-plus';
import ModalPop from "@/components/EditPop/ModalPop.vue"
import AddClass from './modules/AddClass.vue' // 分类
import AddValue from './modules/AddValue.vue' // 值
import uploadModule from './modules/uploadModule.vue' // 上传模块
const splitNum = ref(0.31) // 左右分割比例
......@@ -28,7 +29,7 @@ const modalData = reactive({
show: false,
text: '',
icon: 'error',
cancel: true,
cancel: false,
type: ''
})
......@@ -96,7 +97,6 @@ const addValueClick = (type, item) => {
const valueDelete = (item) => {
console.log('删除值', item)
modalData.type = 'value'
modalData.cancel = true
modalData.icon = 'error'
modalData.text = '删除后无法恢复,是否确认删除[' + item.name + ']?'
modalData.show = true
......@@ -106,7 +106,6 @@ const valueDelete = (item) => {
const classDelete = (item) => {
console.log('删除分类事件', item)
modalData.type = 'class'
modalData.cancel = false
modalData.icon = 'error'
modalData.text = '删除后无法恢复,是否确认删除[' + item.name + ']?'
modalData.show = true
......@@ -133,10 +132,19 @@ const AddDomainConfirm = (item) => {
console.log('新增分类确认', item)
} else if (modalPopData.type === 'value') {
console.log('新增值确认', item)
} else if (modalPopData.type === 'upload') {
console.log('导入', item)
}
modalPopData.show = false
}
// 导入功能
const importClick = () => {
modalPopData.title = '上传文件'
modalPopData.type = 'upload'
modalPopData.show = true
}
// 获取列表数据
const getList = () => {
......@@ -189,7 +197,7 @@ onMounted(() => {
</el-input>
</el-form-item>
<div style="display: flex;">
<el-button icon="Upload" type="primary">导入</el-button>
<el-button icon="Upload" type="primary" @click="importClick">导入</el-button>
<el-button icon="Download" type="success">导出</el-button>
<el-button icon="Plus" type="primary" @click="addValueClick('add')">新增值</el-button>
</div>
......@@ -232,6 +240,7 @@ onMounted(() => {
v-if="modalPopData.type === 'class'" />
<AddValue v-model="addValueForm" :type="modalPopData.operation" @cancel="modalPopCancel" @confirm="AddDomainConfirm"
v-if="modalPopData.type === 'value'" />
<uploadModule @cancel="modalPopCancel" @confirm="AddDomainConfirm" v-if="modalPopData.type === 'upload'" />
</template>
</ModalPop>
</div>
......
<script setup lang="ts" name="AddClass">
import { ref } from "vue";
import CustomUpload from "@/components/CustomUpload/index.vue"
const emit = defineEmits(["update:modelValue", "cancel", "confirm"]);
const radioValue = ref(1);
const fileList = ref<File[]>([]);
// 取消
const cancel = () => {
emit("cancel");
};
// 确认
const confirm = () => {
console.log(fileList.value);
// emit("confirm");
};
const handleUpload = (file: File) => {
console.log(file);
// 上传文件
// 处理上传结果
// 更新modelValue
};
</script>
<template>
<div>
<div class="mb20">
<CustomUpload v-model:file-list="fileList" :limit="1" :needType="false" :needSize="false" :listShow="false" prompt='点击或拖拽文件到此处上传' />
</div>
<el-form-item label="上传方式" label-width="200px">
<el-radio-group v-model="radioValue">
<el-radio :label="1">覆盖原数据</el-radio>
<el-radio :label="2">追加数据</el-radio>
</el-radio-group>
</el-form-item>
<div class="btn">
<el-button type="info" style="width: 150px;" @click="cancel">取消</el-button>
<el-button type="primary" style="width: 150px;" @click="confirm">确认</el-button>
</div>
</div>
</template>
<style lang="scss" scoped>
.btn {
padding: 20px;
display: flex;
justify-content: center;
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论