|
@@ -1236,9 +1236,9 @@
|
|
|
/>
|
|
|
|
|
|
<!-- 查看附件 -->
|
|
|
+
|
|
|
<hc-new-dialog
|
|
|
v-model="attachmentModal"
|
|
|
-
|
|
|
is-table
|
|
|
title="附件列表"
|
|
|
widths="780px"
|
|
@@ -1251,13 +1251,12 @@
|
|
|
<span class="text-orange">按住鼠标拖动文件可进行附件列表排序</span>
|
|
|
</div>
|
|
|
<div
|
|
|
- v-for="item in attachmentList"
|
|
|
+ v-for="(item, index) in attachmentList"
|
|
|
:key="item.id"
|
|
|
class="hc-attachment-card"
|
|
|
>
|
|
|
<div class="hc-attachment-header">
|
|
|
{{ item?.nodeName }}
|
|
|
- <!-- <el-button type="success" :loading="saveFileOrderLoad" style="float:right" @click="saveFileOrder">确定排序</el-button> -->
|
|
|
</div>
|
|
|
<div
|
|
|
:ref="setAttachmentListRef"
|
|
@@ -1267,9 +1266,10 @@
|
|
|
v-for="item1 in item.fileList"
|
|
|
:key="item1.id"
|
|
|
class="hc-attachment-item"
|
|
|
+ :data-id="item1.id"
|
|
|
>
|
|
|
<div class="hc-attachment-file-name">
|
|
|
- <HcIcon name="drag-move-2" class="text-blue" />
|
|
|
+ <HcIcon name="drag-move-2" class="drag-handle text-blue" />
|
|
|
<HcIcon name="attachment" class="ml-2" />
|
|
|
<div class="name">{{ item1?.name }}</div>
|
|
|
</div>
|
|
@@ -1302,9 +1302,17 @@
|
|
|
</div>
|
|
|
<template #footer>
|
|
|
<el-button @click="attachmentModal = false">关闭</el-button>
|
|
|
- <el-button type="primary" :loading="saveFileOrderLoad" :disabled="attachmentList.length === 0" @click="saveFileOrder">确定排序</el-button>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ :loading="saveFileOrderLoad"
|
|
|
+ :disabled="attachmentList.length === 0"
|
|
|
+ @click="saveFileOrder"
|
|
|
+ >
|
|
|
+ 确定排序
|
|
|
+ </el-button>
|
|
|
</template>
|
|
|
</hc-new-dialog>
|
|
|
+
|
|
|
<!-- 上传文件 -->
|
|
|
<hc-new-dialog
|
|
|
v-model="uploadModal"
|
|
@@ -1419,7 +1427,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
|
+import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue'
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
import { useAppStore } from '~src/store'
|
|
|
import { HcIsButton } from '~src/plugins/IsButtons'
|
|
@@ -1543,8 +1551,16 @@ onMounted(() => {
|
|
|
getDictionaryApi()
|
|
|
getStandardTypeOptions()
|
|
|
getMajorDataTypeOptions()
|
|
|
+ nextTick(() => {
|
|
|
+ initDragAndDrop()
|
|
|
+ })
|
|
|
+})
|
|
|
+// 组件卸载前清理事件
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ attachmentListRefs.value.forEach(container => {
|
|
|
+ container.removeEventListener('dragover', () => {})
|
|
|
+ })
|
|
|
})
|
|
|
-
|
|
|
//身份按钮切换数据
|
|
|
const authBtnTabKey = ref('1')
|
|
|
|
|
@@ -3095,9 +3111,9 @@ const attachmentModalShow = () => {
|
|
|
attachmentModal.value = true
|
|
|
|
|
|
getAttachmentList()
|
|
|
- nextTick(()=>{
|
|
|
- initSortable()
|
|
|
- })
|
|
|
+ // nextTick(()=>{
|
|
|
+ // initSortable()
|
|
|
+ // })
|
|
|
}
|
|
|
const attachmentListLoaing = ref(false)
|
|
|
const attachmentList = ref([])
|
|
@@ -3123,37 +3139,71 @@ const getAttachmentList = async () => {
|
|
|
const attachmentListRefs = ref([])
|
|
|
const sortableInstances = ref([])
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+// 设置附件列表的ref
|
|
|
const setAttachmentListRef = (el) => {
|
|
|
if (el) {
|
|
|
attachmentListRefs.value.push(el)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 初始化拖拽排序
|
|
|
-const initSortable = () => {
|
|
|
- nextTick(() => {
|
|
|
- attachmentListRefs.value.forEach((el, index) => {
|
|
|
- const sortable = 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 initDragAndDrop = () => {
|
|
|
+ attachmentListRefs.value.forEach((container) => {
|
|
|
+ const items = container.querySelectorAll('.hc-attachment-item')
|
|
|
+
|
|
|
+ items.forEach((item) => {
|
|
|
+ item.draggable = true
|
|
|
+
|
|
|
+ // 拖拽开始事件
|
|
|
+ item.addEventListener('dragstart', (e) => {
|
|
|
+ e.dataTransfer.setData('text/plain', item.dataset.id)
|
|
|
+ item.classList.add('dragging')
|
|
|
+ setTimeout(() => {
|
|
|
+ item.style.display = 'none'
|
|
|
+ }, 0)
|
|
|
+ })
|
|
|
+
|
|
|
+ // 拖拽结束事件
|
|
|
+ item.addEventListener('dragend', () => {
|
|
|
+ items.forEach(i => {
|
|
|
+ i.classList.remove('dragging')
|
|
|
+ i.style.display = ''
|
|
|
+ })
|
|
|
})
|
|
|
- sortableInstances.value.push(sortable) // 存储 Sortable 实例引用
|
|
|
+ })
|
|
|
+
|
|
|
+ // 拖拽经过事件
|
|
|
+ container.addEventListener('dragover', (e) => {
|
|
|
+ e.preventDefault()
|
|
|
+ const draggingItem = container.querySelector('.dragging')
|
|
|
+ const afterElement = getDragAfterElement(container, e.clientY)
|
|
|
+
|
|
|
+ if (afterElement) {
|
|
|
+ container.insertBefore(draggingItem, afterElement)
|
|
|
+ } else {
|
|
|
+ container.appendChild(draggingItem)
|
|
|
+ }
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
+// 获取拖拽后应该放置的位置
|
|
|
+const getDragAfterElement = (container, y) => {
|
|
|
+ const draggableElements = [...container.querySelectorAll('.hc-attachment-item:not(.dragging)')]
|
|
|
+
|
|
|
+ return draggableElements.reduce((closest, child) => {
|
|
|
+ const box = child.getBoundingClientRect()
|
|
|
+ const offset = y - box.top - box.height / 2
|
|
|
+
|
|
|
+ if (offset < 0 && offset > closest.offset) {
|
|
|
+ return { element: child, offset: offset }
|
|
|
+ } else {
|
|
|
+ return closest
|
|
|
+ }
|
|
|
+ }, { offset: Number.NEGATIVE_INFINITY }).element
|
|
|
+}
|
|
|
// 销毁 Sortable 实例
|
|
|
const destroySortableInstances = () => {
|
|
|
sortableInstances.value.forEach(instance => {
|
|
@@ -3167,7 +3217,7 @@ watch(attachmentModal, (newVal) => {
|
|
|
if (!newVal) {
|
|
|
destroySortableInstances() // 关闭弹窗时销毁 Sortable 实例
|
|
|
} else {
|
|
|
- initSortable() // 打开弹窗时初始化 Sortable
|
|
|
+ initDragAndDrop() // 打开弹窗时初始化 Sortable
|
|
|
}
|
|
|
})
|
|
|
onUnmounted(() => {
|
|
@@ -3184,14 +3234,14 @@ const saveFileOrder = async () => {
|
|
|
if (!error && code === 200) {
|
|
|
window?.$message?.success(msg)
|
|
|
getAttachmentList()
|
|
|
- initSortable()
|
|
|
+ initDragAndDrop()
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 监听attachmentList变化时初始化拖拽
|
|
|
watch(() => attachmentList.value, () => {
|
|
|
nextTick(()=>{
|
|
|
- initSortable()
|
|
|
+ initDragAndDrop()
|
|
|
})
|
|
|
}, { deep: true })
|
|
|
//预览
|
|
@@ -3851,57 +3901,51 @@ html.theme-dark {
|
|
|
}
|
|
|
</style>
|
|
|
|
|
|
-<style lang="scss" scoped>
|
|
|
-/* 新增拖拽排序相关样式 */
|
|
|
-.sortable-ghost {
|
|
|
- opacity: 0.5;
|
|
|
- background: #f5f5f5;
|
|
|
+<style scoped>
|
|
|
+.hc-attachment-content {
|
|
|
+ min-height: 20px;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-radius: 4px;
|
|
|
}
|
|
|
|
|
|
.hc-attachment-item {
|
|
|
- transition: all 0.3s;
|
|
|
- cursor: move;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
- padding: 12px;
|
|
|
+ padding: 10px;
|
|
|
margin-bottom: 8px;
|
|
|
- background: #fff;
|
|
|
- border-radius: 4px;
|
|
|
+ background-color: white;
|
|
|
border: 1px solid #ebeef5;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
- }
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: move;
|
|
|
+ transition: all 0.3s;
|
|
|
}
|
|
|
|
|
|
-.hc-attachment-content {
|
|
|
- min-height: 20px;
|
|
|
+.hc-attachment-item:hover {
|
|
|
+ box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
|
|
|
|
-/* 原有样式保持不变 */
|
|
|
-.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-item.dragging {
|
|
|
+ opacity: 0.5;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+}
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- .hc-attachment-file-name {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
-
|
|
|
- .name {
|
|
|
- margin-left: 8px;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- .hc-attachment-btn-box {
|
|
|
- display: flex;
|
|
|
- }
|
|
|
+.hc-attachment-file-name {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ flex: 1;
|
|
|
+}
|
|
|
+
|
|
|
+.hc-attachment-file-name .name {
|
|
|
+ margin-left: 8px;
|
|
|
+ max-width: 300px;
|
|
|
+ overflow: hidden;
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+}
|
|
|
+
|
|
|
+.drag-handle {
|
|
|
+ cursor: move;
|
|
|
}
|
|
|
</style>
|