Эх сурвалжийг харах

Merge branch 'master' into test-dev

duy 2 сар өмнө
parent
commit
bfd6010b3c

+ 1 - 0
package.json

@@ -33,6 +33,7 @@
         "nprogress": "^0.2.0",
         "pinia": "^2.2.6",
         "pinyin-pro": "^3.26.0",
+        "sortablejs": "^1.15.6",
         "split.js": "^1.6.5",
         "vue": "3.5.12",
         "vue-router": "^4.4.5",

+ 33 - 0
src/api/modules/data-fill/wbs.js

@@ -499,4 +499,37 @@ export default {
             false,
         )
     },
+
+    //附件跳转排序
+        async sortPdf(form) {
+        return HcApi(
+            {
+                url: '/api/blade-manager/tablefile/sort',
+                   method: 'post',
+                data: form,
+            },
+            false,
+        )
+    },
+    //上传文件
+        async addBussFileNode(form) {
+        return HcApi({
+              headers: {
+            'Content-Type': 'multipart/form-data', 
+        },
+            url: '/api/blade-manager/exceltab/add-bussfile-node',
+            method: 'post',
+            data: form,
+        })
+    },
+    async addBussFile(form) {
+        return HcApi({
+              headers: {
+            'Content-Type': 'multipart/form-data', 
+        },
+            url: '/api/blade-manager/exceltab/add-buss-file',
+            method: 'post',
+            data: form,
+        })
+    },
 }

+ 2 - 0
src/views/data-fill/collapse-form/index.vue

@@ -309,6 +309,8 @@
             :datas="uploadData"
             :file-list="fileListData"
             :is-canupload="false"
+            :auto-upload="false"
+            :is-list-file="true"
             @change="uploadChange"
             @close="uploadModalClose"
         />

+ 267 - 0
src/views/data-fill/components/HcUpload copy.vue

@@ -0,0 +1,267 @@
+<template>
+    <el-upload
+        ref="uploadRef"
+        :accept="accept" :action="action" :before-remove="delUploadData" :before-upload="beforeUpload"
+        :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'"
+        drag multiple
+        :auto-upload="autoUpload"
+    >
+        <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" />
+                <div class="el-upload__text">拖动文件到这里 或 <em>点击这里选择文件</em></div>
+            </div>
+        </template>
+
+        <template #tip>
+            <div class="el-upload__tip" style="font-size: 14px;">
+                {{ acceptTip }}
+            </div>
+        </template>
+    </el-upload>
+    <div class="mt-3" style="float: right;">
+        <el-button v-if="!autoUpload" type="primary" @click="submitUpload">
+            确认上传
+        </el-button>
+    </div>
+</template>
+
+<script setup>
+import { 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'
+
+const props = defineProps({
+    fileList: {
+        type: Array,
+        default: () => ([]),
+    },
+    datas: {
+        type: Object,
+        default: () => ({}),
+    },
+    isCanupload:{
+        type:Boolean,
+        default:false,
+    },
+    action:{
+        type:String,
+        default:'/api/blade-manager/exceltab/add-buss-file',
+    },
+    accept:{
+        type:String,
+        default:'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,application/pdf,.doc,.docx,application/msword',
+    },
+    acceptTip:{
+        type:String,
+        default:'允许格式:pdf/excel/word, 文件大小 小于 60MB',
+    },
+    autoUpload:{
+        type:Boolean,
+        default:true,
+    },
+    typevalue:{
+        type:[String, Number],
+        default:'',
+    }, //附件类型
+
+})
+
+//事件
+const emit = defineEmits(['change', 'close'])
+//变量
+const uploadData = ref(props.datas)
+const fileListData = ref(props.fileList)
+const action = ref(props.action)
+const accept = ref(props.accept)
+const acceptTip = ref(props.acceptTip)
+const uploadDisabled = ref(false)
+const isCanuploadVal = ref(props.isCanupload)
+const autoUpload = ref(props.autoUpload)
+const typevalue = ref(props.typevalue)
+
+
+//监听
+watch(() => [
+    props.fileList,
+    props.datas,
+    props.isCanupload,
+    props.action,
+    props.accept,
+    props.acceptTip,
+    props.autoUpload,
+    props.typevalue,
+
+], ([fileList, datas, isCanupload, Action, Accept, Tip, auto, type]) => {
+    uploadData.value = datas
+    fileListData.value = fileList
+    isCanuploadVal.value = isCanupload
+    action.value = Action
+    accept.value = Accept
+    acceptTip.value = Tip
+    autoUpload.value = auto
+    typevalue.value = type
+})
+watch(() => [
+    props.typevalue,
+    props.autoUpload,
+], ([ type, auto]) => {
+    typevalue.value = type
+    autoUpload.value = auto
+},
+{ immediate: true },
+)
+//渲染完成
+onMounted(() => {
+    beforeFileNum.value = 0
+    finishFileNum.value = 0
+    errorFileNum.value = 0
+})
+
+//上传前
+const beforeFileNum = ref(0)
+const beforeUpload = async (file) => {
+    if (isFileSize(file?.size, 60)) {
+        beforeFileNum.value++
+        return true
+    } else {
+        window?.$message?.warning('文件大小, 不能过60M!')
+        return false
+    }
+}
+
+//超出限制时
+const uploadExceed = () => {
+    window?.$message?.warning('请上传 jpg/png/pdf/excel/word 的文件,文件大小 不超过60M')
+}
+
+//上传中
+const loadingText = ref('上传中...')
+const uploadprogress = () => {
+    loadingText.value = '上传中...'
+    uploadDisabled.value = true
+}
+
+//上传完成
+const finishFileNum = ref(0)
+const uploadSuccess = () => {
+    finishFileNum.value++
+    if (beforeFileNum.value === finishFileNum.value) {
+        uploadDisabled.value = false
+        emit('change', { type: 'success' })
+    }
+}
+
+//上传失败
+const errorFileNum = ref(0)
+const uploadError = () => {
+    errorFileNum.value++
+    window?.$message?.error('上传失败')
+    const num = finishFileNum.value + errorFileNum.value
+    if (beforeFileNum.value === num) {
+        uploadDisabled.value = false
+        emit('change', { type: 'success' })
+    }
+}
+
+//预览
+const uploadPreview = ({ url }) => {
+    emit('close')
+    toPdfPage(url)
+    /*if (url) {
+        window.open(url, '_blank')
+    }*/
+}
+const uploadRef = ref(null)
+//删除文件
+const delUploadData = async (res) => {
+    const { id, status } = res
+
+    if (accept.value === 'application/pdf') {
+        if (!id || status === 'uploading') {
+            uploadRef.value.abort()
+            uploadDisabled.value = false
+            return true
+         } else {
+            loadingText.value = '删除中...'
+            uploadDisabled.value = true
+            const { error, code, msg } = await wbsApi.delTabById({
+                ids: id,
+            })
+            uploadDisabled.value = false
+            if (!error && code === 200) {
+                window?.$message?.success('删除成功')
+                return true
+            } else {
+                window?.$message?.error(msg || '操作失败')
+                return false
+            }
+        }
+
+    } else {
+        if (!id || status === 'uploading') {
+            uploadRef.value.abort()
+            uploadDisabled.value = false
+            return true
+        } else {
+            loadingText.value = '删除中...'
+            uploadDisabled.value = true
+            const { error, code, msg } = await wbsApi.removeBussFile({
+                ids: id,
+            })
+            uploadDisabled.value = false
+            if (!error && code === 200) {
+                window?.$message?.success('删除成功')
+                return true
+            } else {
+                window?.$message?.error(msg || '操作失败')
+                return false
+            }
+        }
+
+    }
+}
+
+const uploadRemove = () => {
+    if (fileListData.value.length <= 0) {
+        emit('change', { type: 'del' })
+    }
+}
+
+const beforesubmitUpload = () => {
+    if (!typevalue.value && !autoUpload.value) {
+        window.$message.warning('请先选择附件类型')
+        return
+    } else {
+        const uploadInput = uploadRef.value.$el.querySelector('input[type=file]')
+        if (uploadInput) {
+            uploadInput.click()
+        }
+    }
+
+
+
+}
+const submitUpload = ()=>{
+    if (!typevalue.value && !autoUpload.value) {
+        window.$message.warning('请先选择附件类型')
+        return
+    }
+    uploadRef.value.submit()
+}
+</script>
+
+<style lang="scss">
+.hc-upload-border1 .el-upload-dragger{
+    padding: 0px;
+}
+.hc-upload-border1 .el-upload-dragger .el-upload__text{
+    padding: 40px;
+}
+</style>

+ 218 - 14
src/views/data-fill/components/HcUpload.vue

@@ -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>

+ 136 - 8
src/views/data-fill/wbs.vue

@@ -1235,7 +1235,7 @@
         <!-- 查看附件 -->
         <hc-new-dialog
             v-model="attachmentModal"
-            :footer="false"
+         
             is-table
             title="附件列表"
             widths="780px"
@@ -1244,20 +1244,30 @@
                 v-if="attachmentList.length > 0"
                 v-loading="attachmentListLoaing"
             >
+                <div class="mb-1 p-2">
+                    <span class="text-orange">按住鼠标拖动文件可进行附件列表排序</span>
+                </div>
                 <div
                     v-for="item in attachmentList"
                     :key="item.id"
                     class="hc-attachment-card"
                 >
-                    <div class="hc-attachment-header">{{ item?.nodeName }}</div>
-                    <div class="hc-attachment-content">
+                    <div class="hc-attachment-header">
+                        {{ item?.nodeName }}
+                        <!-- <el-button type="success" :loading="saveFileOrderLoad" style="float:right" @click="saveFileOrder">确定排序</el-button> -->
+                    </div>
+                    <div 
+                        :ref="setAttachmentListRef"
+                        class="hc-attachment-content"
+                    >
                         <div
                             v-for="item1 in item.fileList"
                             :key="item1.id"
                             class="hc-attachment-item"
                         >
                             <div class="hc-attachment-file-name">
-                                <HcIcon name="attachment" />
+                                <HcIcon name="drag-move-2" class="text-blue" />
+                                <HcIcon name="attachment" class="ml-2" />
                                 <div class="name">{{ item1?.name }}</div>
                             </div>
                             <div class="hc-attachment-btn-box">
@@ -1287,9 +1297,10 @@
                     </div>
                 </div>
             </div>
-            <div v-else style="height: 100%; width: 100%">
-                <hc-no-data />
-            </div>
+            <template #footer>
+                <el-button @click="attachmentModal = false">关闭</el-button>
+                <el-button type="primary" :loading="saveFileOrderLoad" @click="saveFileOrder">确定排序</el-button>
+            </template>
         </hc-new-dialog>
         <!-- 上传文件 -->
         <hc-new-dialog
@@ -1320,7 +1331,7 @@
                 :datas="uploadData"
                 :file-list="fileListData"
                 :is-canupload="false"
-                action="/api/blade-manager/exceltab/add-bussfile-node"
+                action="#"
                 accept="application/pdf"
                 accept-tip="允许格式:pdf"
                 :auto-upload="false"
@@ -1416,6 +1427,7 @@ import { HcUploadFileApi } from 'hc-vue3-ui'
 import { getStoreValue, setStoreValue } from '~src/utils/storage'
 import { getDictionaryData } from '~uti/tools'
 import { getChildList } from '~api/other'
+import Sortable from 'sortablejs'
 import {
     arrToKey,
     deepClone,
@@ -3078,7 +3090,11 @@ const abolishOneSave = async () => {
 const attachmentModal = ref(false)
 const attachmentModalShow = () => {
     attachmentModal.value = true
+
     getAttachmentList()
+    nextTick(()=>{
+          initSortable()
+    })
 }
 const attachmentListLoaing = ref(false)
 const attachmentList = ref([])
@@ -3099,6 +3115,62 @@ const getAttachmentList = async () => {
         attachmentList.value = []
     }
 }
+
+// 新增拖拽相关代码
+const attachmentListRefs = ref([])
+
+const setAttachmentListRef = (el) => {
+  if (el) {
+    attachmentListRefs.value.push(el)
+  }
+}
+
+// 初始化拖拽排序
+const initSortable = () => {
+  nextTick(() => {
+    attachmentListRefs.value.forEach((el, index) => {
+      new Sortable(el, {
+        animation: 150,
+        ghostClass: 'sortable-ghost',
+        handle: '.hc-attachment-item', // 整个条目可拖拽
+        onEnd: (evt) => {
+          const { oldIndex, newIndex } = evt
+          if (oldIndex !== newIndex) {
+            // 更新对应节点的文件顺序
+            const node = attachmentList.value[index]
+            const [movedItem] = node.fileList.splice(oldIndex, 1)
+            node.fileList.splice(newIndex, 0, movedItem)
+            
+            // // 这里可以调用API保存新的顺序
+  
+          }
+        },
+      })
+    })
+  })
+}
+
+// 保存文件顺序到后端
+const saveFileOrderLoad = ref(false)
+const saveFileOrder = async () => {
+
+    saveFileOrderLoad.value = true
+ 
+    const { error, code, msg } = await wbsApi.sortPdf( attachmentList.value)
+    saveFileOrderLoad.value = false
+    if (!error && code === 200) {
+       window?.$message?.success(msg)
+       getAttachmentList()
+         initSortable()
+    } 
+}
+
+// 监听attachmentList变化时初始化拖拽
+watch(() => attachmentList.value, () => {
+     nextTick(()=>{
+          initSortable()
+    })
+}, { deep: true })
 //预览
 const previewFile = (item) => {
     toPdfPage(item['domainPdfUrl'])
@@ -3290,6 +3362,7 @@ const changeType = (val) => {
 //上传文件
 const uploadChange = async ({ type }) => {
     if (type === 'success') {
+        
         getBussFileList(primaryKeyId.value)
     } else if (type === 'del') {
         getBussFileList(primaryKeyId.value)
@@ -3754,3 +3827,58 @@ html.theme-dark {
     }
 }
 </style>
+
+<style lang="scss" scoped>
+/* 新增拖拽排序相关样式 */
+.sortable-ghost {
+  opacity: 0.5;
+  background: #f5f5f5;
+}
+
+.hc-attachment-item {
+  transition: all 0.3s;
+  cursor: move;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  padding: 12px;
+  margin-bottom: 8px;
+  background: #fff;
+  border-radius: 4px;
+  border: 1px solid #ebeef5;
+  
+  &:hover {
+    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
+  }
+}
+
+.hc-attachment-content {
+  min-height: 20px;
+}
+
+/* 原有样式保持不变 */
+.hc-attachment-card {
+  margin-bottom: 16px;
+  
+  .hc-attachment-header {
+    font-weight: bold;
+    margin-bottom: 8px;
+    padding-left: 8px;
+    border-left: 3px solid #409eff;
+
+  }
+  
+  .hc-attachment-file-name {
+    display: flex;
+    align-items: center;
+    
+    .name {
+      margin-left: 8px;
+    }
+  }
+  
+  .hc-attachment-btn-box {
+    display: flex;
+  }
+}
+</style>

+ 5 - 0
yarn.lock

@@ -2924,6 +2924,11 @@ sortablejs@^1.15.3:
   resolved "http://219.151.181.73:9000/sortablejs/-/sortablejs-1.15.6.tgz#ff93699493f5b8ab8d828f933227b4988df1d393"
   integrity sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==
 
+sortablejs@^1.15.6:
+  version "1.15.6"
+  resolved "https://registry.npmmirror.com/sortablejs/-/sortablejs-1.15.6.tgz#ff93699493f5b8ab8d828f933227b4988df1d393"
+  integrity sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==
+
 "source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1, source-map-js@^1.2.0:
   version "1.2.0"
   resolved "http://219.151.181.73:9000/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"