|
@@ -5,10 +5,35 @@
|
|
|
:data="uploadData"
|
|
|
:disabled="isCanuploadVal" :file-list="fileListData" :headers="getHeader()" :on-error="uploadError"
|
|
|
:on-exceed="uploadExceed" :on-preview="uploadPreview" :on-progress="uploadprogress"
|
|
|
- :on-remove="uploadRemove" :on-success="uploadSuccess" class="hc-upload-border" :class="autoUpload === false ? 'hc-upload-border1' : 'hc-upload-border'"
|
|
|
+ :on-remove="uploadRemove" :on-success="uploadSuccess" class="hc-upload-border"
|
|
|
+ :class="autoUpload === false ? 'hc-upload-border1' : 'hc-upload-border'"
|
|
|
drag multiple
|
|
|
:auto-upload="autoUpload"
|
|
|
+ :on-change="handleFileChange"
|
|
|
+ :show-file-list="false"
|
|
|
>
|
|
|
+ <!-- 使用file插槽自定义文件列表 -->
|
|
|
+ <draggable
|
|
|
+ v-model="fileListData"
|
|
|
+ item-key="uid"
|
|
|
+ handle=".drag-handle"
|
|
|
+ class="file-list-container"
|
|
|
+ @end="onDragEnd"
|
|
|
+ >
|
|
|
+ <template #item="{ element }">
|
|
|
+ <div class="file-item">
|
|
|
+ <HcIcon name="drag-move-2" class="drag-handle cursor-move" />
|
|
|
+ <HcIcon name="file" class="file-icon" />
|
|
|
+ <span class="file-name">{{ element.name }}</span>
|
|
|
+
|
|
|
+ <HcIcon
|
|
|
+ name="close"
|
|
|
+ class="float-right cursor-pointer text-red"
|
|
|
+ @click.stop="handleRemove(element)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </draggable>
|
|
|
<template #trigger>
|
|
|
<div v-loading="uploadDisabled" :element-loading-text="loadingText" class="hc-upload-loading h-full" @click.stop="beforesubmitUpload">
|
|
|
<HcIcon name="backup" ui="text-5xl mt-4" />
|
|
@@ -23,20 +48,19 @@
|
|
|
</template>
|
|
|
</el-upload>
|
|
|
<div class="mt-3" style="float: right;">
|
|
|
- <el-button v-if="!autoUpload" type="primary" @click="submitUpload">
|
|
|
+ <el-button v-if="!autoUpload" type="primary" :loading="subLoading" @click="submitUpload">
|
|
|
确认上传
|
|
|
</el-button>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { onMounted, ref, watch } from 'vue'
|
|
|
+import { nextTick, onMounted, ref, watch } from 'vue'
|
|
|
import { getHeader } from 'hc-vue3-ui'
|
|
|
import wbsApi from '~api/data-fill/wbs'
|
|
|
import { isFileSize } from 'js-fast-way'
|
|
|
import { toPdfPage } from '~uti/btn-auth'
|
|
|
-import { number } from 'echarts'
|
|
|
-
|
|
|
+import draggable from 'vuedraggable'
|
|
|
const props = defineProps({
|
|
|
fileList: {
|
|
|
type: Array,
|
|
@@ -52,7 +76,7 @@ const props = defineProps({
|
|
|
},
|
|
|
action:{
|
|
|
type:String,
|
|
|
- default:'/api/blade-manager/exceltab/add-buss-file',
|
|
|
+ default:'#',
|
|
|
},
|
|
|
accept:{
|
|
|
type:String,
|
|
@@ -70,6 +94,10 @@ const props = defineProps({
|
|
|
type:[String, Number],
|
|
|
default:'',
|
|
|
}, //附件类型
|
|
|
+ isListFile:{
|
|
|
+ type:Boolean,
|
|
|
+ default:false,
|
|
|
+ }, //是否列表文件
|
|
|
|
|
|
})
|
|
|
|
|
@@ -85,6 +113,7 @@ const uploadDisabled = ref(false)
|
|
|
const isCanuploadVal = ref(props.isCanupload)
|
|
|
const autoUpload = ref(props.autoUpload)
|
|
|
const typevalue = ref(props.typevalue)
|
|
|
+const isListFile = ref(props.isListFile)
|
|
|
|
|
|
|
|
|
//监听
|
|
@@ -97,8 +126,9 @@ watch(() => [
|
|
|
props.acceptTip,
|
|
|
props.autoUpload,
|
|
|
props.typevalue,
|
|
|
+ props.isListFile,
|
|
|
|
|
|
-], ([fileList, datas, isCanupload, Action, Accept, Tip, auto, type]) => {
|
|
|
+], ([fileList, datas, isCanupload, Action, Accept, Tip, auto, type, list]) => {
|
|
|
uploadData.value = datas
|
|
|
fileListData.value = fileList
|
|
|
isCanuploadVal.value = isCanupload
|
|
@@ -107,6 +137,7 @@ watch(() => [
|
|
|
acceptTip.value = Tip
|
|
|
autoUpload.value = auto
|
|
|
typevalue.value = type
|
|
|
+ isListFile.value = list
|
|
|
})
|
|
|
watch(() => [
|
|
|
props.typevalue,
|
|
@@ -117,6 +148,11 @@ watch(() => [
|
|
|
},
|
|
|
{ immediate: true },
|
|
|
)
|
|
|
+
|
|
|
+// 在watch中添加对fileList的深度监听
|
|
|
+watch(() => props.fileList, (newVal) => {
|
|
|
+ fileListData.value = [...newVal] // 使用新数组保证响应性
|
|
|
+}, { deep: true, immediate: true })
|
|
|
//渲染完成
|
|
|
onMounted(() => {
|
|
|
beforeFileNum.value = 0
|
|
@@ -127,8 +163,15 @@ onMounted(() => {
|
|
|
//上传前
|
|
|
const beforeFileNum = ref(0)
|
|
|
const beforeUpload = async (file) => {
|
|
|
+
|
|
|
+
|
|
|
if (isFileSize(file?.size, 60)) {
|
|
|
beforeFileNum.value++
|
|
|
+ // 获取当前文件的索引
|
|
|
+ const fileIndex = fileListData.value.findIndex(f => f.raw === file.raw)
|
|
|
+
|
|
|
+ // 设置uploadData中的sort参数
|
|
|
+ uploadData.value.sort = fileIndex + 1
|
|
|
return true
|
|
|
} else {
|
|
|
window?.$message?.warning('文件大小, 不能过60M!')
|
|
@@ -136,11 +179,38 @@ const beforeUpload = async (file) => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
//超出限制时
|
|
|
const uploadExceed = () => {
|
|
|
window?.$message?.warning('请上传 jpg/png/pdf/excel/word 的文件,文件大小 不超过60M')
|
|
|
}
|
|
|
+const q = 1 // 假设q是固定偏移量,可以根据需要调整
|
|
|
+// 新增的处理方法
|
|
|
+// 文件变化处理
|
|
|
+const handleFileChange = (file, fileList) => {
|
|
|
+
|
|
|
+
|
|
|
+ fileListData.value = fileList.map((item, index) => ({
|
|
|
+ ...item,
|
|
|
+ sort: index + q, // 为每个文件添加sort字段
|
|
|
+ }))
|
|
|
+}
|
|
|
|
|
|
+// 拖拽结束事件
|
|
|
+const onDragEnd = () => {
|
|
|
+ // 更新排序号
|
|
|
+ fileListData.value = fileListData.value.map((file, index) => ({
|
|
|
+ ...file,
|
|
|
+ sort: index + q,
|
|
|
+ }))
|
|
|
+}
|
|
|
+// 手动删除文件
|
|
|
+const handleRemove = (file) => {
|
|
|
+ const index = fileListData.value.findIndex(f => f.uid === file.uid)
|
|
|
+ if (index !== -1) {
|
|
|
+ fileListData.value.splice(index, 1)
|
|
|
+ }
|
|
|
+}
|
|
|
//上传中
|
|
|
const loadingText = ref('上传中...')
|
|
|
const uploadprogress = () => {
|
|
@@ -182,7 +252,8 @@ const uploadRef = ref(null)
|
|
|
//删除文件
|
|
|
const delUploadData = async (res) => {
|
|
|
const { id, status } = res
|
|
|
-
|
|
|
+ console.log(res, 'res')
|
|
|
+
|
|
|
if (accept.value === 'application/pdf') {
|
|
|
if (!id || status === 'uploading') {
|
|
|
uploadRef.value.abort()
|
|
@@ -229,13 +300,15 @@ const delUploadData = async (res) => {
|
|
|
}
|
|
|
|
|
|
const uploadRemove = () => {
|
|
|
+
|
|
|
+
|
|
|
if (fileListData.value.length <= 0) {
|
|
|
emit('change', { type: 'del' })
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const beforesubmitUpload = () => {
|
|
|
- if (!typevalue.value && !autoUpload.value) {
|
|
|
+ if (!typevalue.value && !autoUpload.value && !isListFile.value) {
|
|
|
window.$message.warning('请先选择附件类型')
|
|
|
return
|
|
|
} else {
|
|
@@ -248,12 +321,65 @@ const beforesubmitUpload = () => {
|
|
|
|
|
|
|
|
|
}
|
|
|
-const submitUpload = ()=>{
|
|
|
- if (!typevalue.value && !autoUpload.value) {
|
|
|
- window.$message.warning('请先选择附件类型')
|
|
|
- return
|
|
|
+const subLoading = ref(false)
|
|
|
+const submitUpload = async () => {
|
|
|
+ if (!typevalue.value && !autoUpload.value && !isListFile.value) {
|
|
|
+ window.$message.warning('请先选择附件类型')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 确保所有文件都有 sort 参数
|
|
|
+ fileListData.value = fileListData.value.map((file, index) => ({
|
|
|
+ ...file,
|
|
|
+ sort: index + q,
|
|
|
+ }))
|
|
|
+
|
|
|
+ // 创建 FormData 对象
|
|
|
+ const formData = new FormData()
|
|
|
+// // 1. 添加多个文件(后端接收的是 files[] 数组)
|
|
|
+ fileListData.value.forEach((file) => {
|
|
|
+
|
|
|
+
|
|
|
+ formData.append('files', file.raw || file) // 确保 file.raw 是 File 对象
|
|
|
+ })
|
|
|
+
|
|
|
+ // 2. 添加其他参数
|
|
|
+ formData.append('classify', uploadData.value.classify)
|
|
|
+ formData.append('nodeId', uploadData.value.nodeId)
|
|
|
+ formData.append('type', uploadData.value.type)
|
|
|
+ formData.append('contractId', uploadData.value.contractId)
|
|
|
+
|
|
|
+ // 3. 发送请求
|
|
|
+ subLoading.value = true
|
|
|
+ if (isListFile.value) {
|
|
|
+ const { error, code, msg } = await wbsApi.addBussFile(formData) // 修改这里
|
|
|
+ uploadDisabled.value = false
|
|
|
+ subLoading.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ window?.$message?.success('上传成功')
|
|
|
+ emit('change', { type: 'success' })
|
|
|
+
|
|
|
+ } else {
|
|
|
+ window?.$message?.error(msg || '操作失败')
|
|
|
+
|
|
|
}
|
|
|
- uploadRef.value.submit()
|
|
|
+ } else {
|
|
|
+ const { error, code, msg } = await wbsApi.addBussFileNode(formData) // 修改这里
|
|
|
+ uploadDisabled.value = false
|
|
|
+ subLoading.value = false
|
|
|
+ if (!error && code === 200) {
|
|
|
+ window?.$message?.success('上传成功')
|
|
|
+ emit('change', { type: 'success' })
|
|
|
+
|
|
|
+ } else {
|
|
|
+ window?.$message?.error(msg || '操作失败')
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
</script>
|
|
|
|
|
@@ -265,3 +391,81 @@ const submitUpload = ()=>{
|
|
|
padding: 40px;
|
|
|
}
|
|
|
</style>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.file-list-container {
|
|
|
+ margin-top: 16px;
|
|
|
+ border: 1px solid #dcdfe6;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f9f9f9;
|
|
|
+}
|
|
|
+
|
|
|
+.file-item {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding: 8px 12px;
|
|
|
+ margin: 6px 0;
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 4px;
|
|
|
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
|
+ transition: all 0.3s ease;
|
|
|
+}
|
|
|
+
|
|
|
+.file-item:hover {
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ transform: translateY(-1px);
|
|
|
+}
|
|
|
+
|
|
|
+.drag-handle {
|
|
|
+ margin-right: 10px;
|
|
|
+ cursor: move;
|
|
|
+ color: #999;
|
|
|
+}
|
|
|
+
|
|
|
+.drag-handle:hover {
|
|
|
+ color: #409eff;
|
|
|
+}
|
|
|
+
|
|
|
+.file-icon {
|
|
|
+ margin-right: 10px;
|
|
|
+ color: #409eff;
|
|
|
+ font-size: 18px;
|
|
|
+}
|
|
|
+
|
|
|
+.file-name {
|
|
|
+ flex: 1;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ font-size: 14px;
|
|
|
+}
|
|
|
+
|
|
|
+.file-status {
|
|
|
+ margin-right: 10px;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.uploading-text {
|
|
|
+ color: #e6a23c;
|
|
|
+}
|
|
|
+
|
|
|
+.success-text {
|
|
|
+ color: #67c23a;
|
|
|
+}
|
|
|
+
|
|
|
+.fail-text {
|
|
|
+ color: #f56c6c;
|
|
|
+}
|
|
|
+
|
|
|
+.cursor-move {
|
|
|
+ cursor: move;
|
|
|
+}
|
|
|
+
|
|
|
+.hc-upload-border1 .el-upload-dragger{
|
|
|
+ padding: 0px;
|
|
|
+}
|
|
|
+.hc-upload-border1 .el-upload-dragger .el-upload__text{
|
|
|
+ padding: 40px;
|
|
|
+}
|
|
|
+</style>
|