|
@@ -38,10 +38,19 @@
|
|
|
</div>
|
|
|
|
|
|
<!-- 页面展示 -->
|
|
|
- <div class="page-container">
|
|
|
- <div v-for="(item, index) in pageList" :key="`${item.type} - ${index}`" class="page" :class="{ 'selected': selectedPageList.includes(index) }">
|
|
|
+ <div class="page-container" ref="dragContainer">
|
|
|
+ <div v-for="(item, index) in pageList" :key="`${item.type} - ${index}`" class="page"
|
|
|
+ :class="{
|
|
|
+ 'selected': selectedPageList.includes(index),
|
|
|
+ // 'drag-indicate-right': dragToIndex === index && !isDragToLeft,
|
|
|
+ // 'drag-indicate-left': dragToIndex + 1 === index && isDragToLeft,
|
|
|
+ 'drag-indicate-right': dragToIndex === index && !isDragToLeft,
|
|
|
+ 'drag-indicate-left': dragToIndex + 1 === index && isDragToLeft,
|
|
|
+ 'drag-indicate-disable': dragIndicateDisable(index)
|
|
|
+ }"
|
|
|
+ >
|
|
|
<div class="img-box">
|
|
|
- <img v-if="item.img" :src="item.img" draggable="false" @click="selectPage(index)" :style="`transform: rotate(${rotationToAngle(item.rotation)}deg);`" />
|
|
|
+ <img v-if="item.img" :src="item.img" @click="selectPage(index)" :style="`transform: rotate(${rotationToAngle(item.rotation)}deg);`" />
|
|
|
<img v-else-if="item.type === 'blank'"
|
|
|
:class="{ 'blank-page': item.type === 'blank', 'w-auto': item.size.width <= item.size.height, 'h-auto': item.size.width > item.size.height }"
|
|
|
:width="item.size.width / ratio"
|
|
@@ -67,6 +76,9 @@ import { computed, ref, watch, onMounted, reactive, onUnmounted } from 'vue'
|
|
|
import { useViewerStore } from '@/stores/modules/viewer'
|
|
|
import { useDocumentStore } from '@/stores/modules/document'
|
|
|
import core from '@/core'
|
|
|
+import { useMouseInElement } from '@vueuse/core'
|
|
|
+
|
|
|
+const { Sortable } = defineProps(['Sortable'])
|
|
|
|
|
|
const useViewer = useViewerStore()
|
|
|
const useDocument = useDocumentStore()
|
|
@@ -77,8 +89,33 @@ const data = reactive({
|
|
|
})
|
|
|
let { pageList, selectedPageList } = data
|
|
|
|
|
|
+const dragContainer = ref(null)
|
|
|
+const dragFromIndex = ref(-2)
|
|
|
+const dragToIndex = ref(-2)
|
|
|
+const isDragToLeft = ref(false)
|
|
|
+
|
|
|
const ratio = window.devicePixelRatio || 1
|
|
|
|
|
|
+onMounted(() => {
|
|
|
+ Sortable.create(dragContainer.value, {
|
|
|
+ multiDrag: true,
|
|
|
+ selectedClass: 'sortable-selected',
|
|
|
+ handle: '.img-box',
|
|
|
+ dragClass: "sortable-drag",
|
|
|
+ sort: false,
|
|
|
+ forceFallback: true,
|
|
|
+ fallbackTolerance: 20,
|
|
|
+ onStart: dragStart,
|
|
|
+ onEnd: dragEnd
|
|
|
+ })
|
|
|
+
|
|
|
+ core.getDocEditorPages()
|
|
|
+})
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ core.removeEvent('getDocEditorPages', getPages)
|
|
|
+})
|
|
|
+
|
|
|
// 初始化 获取所有页面数量和序号
|
|
|
const totalPages = core.getPagesCount()
|
|
|
for (let i = 0; i < totalPages; i++) {
|
|
@@ -87,10 +124,6 @@ for (let i = 0; i < totalPages; i++) {
|
|
|
})
|
|
|
}
|
|
|
|
|
|
-onMounted(() => {
|
|
|
- core.getDocEditorPages()
|
|
|
-})
|
|
|
-
|
|
|
// 获取单个页面图片
|
|
|
const getPages = (data) => {
|
|
|
const { index, pageData } = data
|
|
@@ -98,10 +131,6 @@ const getPages = (data) => {
|
|
|
}
|
|
|
core.addEvent('getDocEditorPages', getPages)
|
|
|
|
|
|
-onUnmounted(() => {
|
|
|
- core.removeEvent('getDocEditorPages', getPages)
|
|
|
-})
|
|
|
-
|
|
|
// 打开插入页面选项弹窗
|
|
|
const openDeletePageDialog = () => {
|
|
|
useViewer.openElement('deletePageDialog')
|
|
@@ -305,9 +334,15 @@ const openMovePageDialog = () => {
|
|
|
|
|
|
// 移动页面
|
|
|
const handleMovePage = (targetIndex) => {
|
|
|
- if (selectedPageList.length === 1) { // 移动一页
|
|
|
- const index = selectedPageList[0]
|
|
|
+ if (selectedPageList.length === 1 ||
|
|
|
+ (selectedPageList.length < 2 && dragFromIndex.value >= 0) ||
|
|
|
+ (selectedPageList.length > 1 && dragFromIndex.value >= 0 && !selectedPageList.includes(dragFromIndex.value))
|
|
|
+ ) { // 移动一页
|
|
|
+ const dragSelectedOrNoDrag = (selectedPageList.length === 1 && selectedPageList.includes(dragFromIndex.value)) || (selectedPageList.length === 1 && dragFromIndex.value < 0)
|
|
|
+ const index = dragSelectedOrNoDrag ? selectedPageList[0] : [dragFromIndex.value]
|
|
|
const tIndex = index > targetIndex ? targetIndex : targetIndex - 1
|
|
|
+ if (index === tIndex) return
|
|
|
+
|
|
|
const [page] = pageList.splice(index, 1)
|
|
|
pageList.splice(tIndex, 0, page)
|
|
|
|
|
@@ -316,13 +351,14 @@ const handleMovePage = (targetIndex) => {
|
|
|
index,
|
|
|
targetIndex: tIndex
|
|
|
}
|
|
|
+ // console.log(operation)
|
|
|
core.saveDocumentEdit(operation)
|
|
|
useDocument.setDocEditorOperationList(operation)
|
|
|
- selectedPageList[0] = tIndex
|
|
|
+ if (dragSelectedOrNoDrag) selectedPageList[0] = tIndex
|
|
|
|
|
|
} else { // 移动多页
|
|
|
selectedPageList.sort((a, b) => a - b)
|
|
|
-
|
|
|
+
|
|
|
for (let i = 0; i < selectedPageList.length; i++) {
|
|
|
let index, tIndex
|
|
|
if (selectedPageList[i] === targetIndex) {
|
|
@@ -353,12 +389,62 @@ const handleMovePage = (targetIndex) => {
|
|
|
index,
|
|
|
targetIndex: tIndex
|
|
|
}
|
|
|
+ // console.log(operation)
|
|
|
core.saveDocumentEdit(operation)
|
|
|
useDocument.setDocEditorOperationList(operation)
|
|
|
selectedPageList[i] = selectedPageList[i] > targetIndex ? tIndex : tIndex - i
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// 拖拽开始
|
|
|
+const dragStart = (e) => {
|
|
|
+ dragFromIndex.value = e.oldIndex
|
|
|
+ dragContainer.value.addEventListener('mousemove', dragging)
|
|
|
+}
|
|
|
+
|
|
|
+// 拖拽中
|
|
|
+const dragging = (e) => {
|
|
|
+ if (selectedPageList.length > 1 && selectedPageList.includes(dragFromIndex.value)) {
|
|
|
+ dragContainer.value.querySelector('.sortable-drag').style.setProperty("--after-content", "'" + selectedPageList.length + "'")
|
|
|
+ }
|
|
|
+
|
|
|
+ let target = e.target
|
|
|
+ const pageDomList = dragContainer.value.children
|
|
|
+
|
|
|
+ for (let i = 0; i < pageDomList.length; i++) {
|
|
|
+ const element = pageDomList[i]
|
|
|
+ if (element.contains(target)) {
|
|
|
+ const domRect = element.getBoundingClientRect().width
|
|
|
+ isDragToLeft.value = e.offsetX < domRect / 2
|
|
|
+ if (isDragToLeft.value) {
|
|
|
+ dragToIndex.value = i - 1
|
|
|
+ } else {
|
|
|
+ dragToIndex.value = i
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 拖拽结束
|
|
|
+const dragEnd = (e) => {
|
|
|
+ dragContainer.value.removeEventListener('mousemove', dragging)
|
|
|
+ if (dragToIndex.value >= -1 && ![dragToIndex.value, dragToIndex.value + 1].includes(dragFromIndex.value) && !(selectedPageList.includes(dragFromIndex.value) && selectedPageList.includes(dragToIndex.value + 1))) {
|
|
|
+ handleMovePage(dragToIndex.value + 1, dragFromIndex.value)
|
|
|
+ }
|
|
|
+ dragFromIndex.value = -2
|
|
|
+ dragToIndex.value = -2
|
|
|
+}
|
|
|
+
|
|
|
+// 拖拽计算是否置灰显示位置样式
|
|
|
+const dragIndicateDisable = (index) => {
|
|
|
+ if (![index - 1, index, index + 1].includes(dragToIndex.value + 1)) return false
|
|
|
+
|
|
|
+ if ([dragToIndex.value, dragToIndex.value + 1].includes(dragFromIndex.value)) return true
|
|
|
+ if (selectedPageList.includes(dragFromIndex.value) && selectedPageList.includes(dragToIndex.value + 1)) return true
|
|
|
+
|
|
|
+ return false
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
@@ -462,6 +548,29 @@ const handleMovePage = (targetIndex) => {
|
|
|
&.selected {
|
|
|
background-color: #DDE9FF;
|
|
|
}
|
|
|
+
|
|
|
+ &.drag-indicate-right {
|
|
|
+ border-right: 3px solid var(--c-popup-bg-active);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.drag-indicate-left {
|
|
|
+ border-left: 3px solid var(--c-popup-bg-active);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.drag-indicate-disable {
|
|
|
+ border-color: var(--c-divider);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.sortable-drag::after {
|
|
|
+ content: var(--after-content, '1');
|
|
|
+ position: absolute;
|
|
|
+ top: 10px;
|
|
|
+ left: 10px;
|
|
|
+ padding: 5px 20px;
|
|
|
+ border-radius: 50px;
|
|
|
+ background-color: var(--c-popup-bg-active);
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -484,9 +593,9 @@ const handleMovePage = (targetIndex) => {
|
|
|
|
|
|
@media screen and (min-width: 578px) {
|
|
|
.document-editor-container .tools-container .button {
|
|
|
- &:not(.disabled):hover {
|
|
|
- background-color: var(--c-header-button-active);
|
|
|
- }
|
|
|
+ &:not(.disabled):hover {
|
|
|
+ background-color: var(--c-header-button-active);
|
|
|
}
|
|
|
}
|
|
|
+}
|
|
|
</style>
|