refactor: 移除 VueDraggable 插件

This commit is contained in:
pipipi-pikachu 2023-02-25 15:35:41 +08:00
parent 45a7ed9b46
commit ce58277e12
6 changed files with 161 additions and 39 deletions

38
package-lock.json generated
View File

@ -36,6 +36,7 @@
"prosemirror-state": "^1.4.1", "prosemirror-state": "^1.4.1",
"prosemirror-view": "^1.27.2", "prosemirror-view": "^1.27.2",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"sortablejs": "^1.15.0",
"svg-arc-to-cubic-bezier": "^3.2.0", "svg-arc-to-cubic-bezier": "^3.2.0",
"svg-pathdata": "^6.0.0", "svg-pathdata": "^6.0.0",
"tinycolor2": "^1.6.0", "tinycolor2": "^1.6.0",
@ -50,6 +51,7 @@
"@types/file-saver": "^2.0.1", "@types/file-saver": "^2.0.1",
"@types/lodash": "^4.14.181", "@types/lodash": "^4.14.181",
"@types/resize-observer-browser": "^0.1.4", "@types/resize-observer-browser": "^0.1.4",
"@types/sortablejs": "^1.15.0",
"@types/svg-arc-to-cubic-bezier": "^3.2.0", "@types/svg-arc-to-cubic-bezier": "^3.2.0",
"@types/tinycolor2": "^1.4.3", "@types/tinycolor2": "^1.4.3",
"@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/eslint-plugin": "^5.4.0",
@ -2936,6 +2938,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"node_modules/@types/sortablejs": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==",
"dev": true
},
"node_modules/@types/svg-arc-to-cubic-bezier": { "node_modules/@types/svg-arc-to-cubic-bezier": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz",
@ -13170,9 +13178,9 @@
} }
}, },
"node_modules/sortablejs": { "node_modules/sortablejs": {
"version": "1.14.0", "version": "1.15.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
}, },
"node_modules/source-list-map": { "node_modules/source-list-map": {
"version": "2.0.1", "version": "2.0.1",
@ -14890,6 +14898,11 @@
"vue": "^3.0.1" "vue": "^3.0.1"
} }
}, },
"node_modules/vuedraggable/node_modules/sortablejs": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
},
"node_modules/w3c-keyname": { "node_modules/w3c-keyname": {
"version": "2.2.6", "version": "2.2.6",
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz",
@ -18125,6 +18138,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/sortablejs": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==",
"dev": true
},
"@types/svg-arc-to-cubic-bezier": { "@types/svg-arc-to-cubic-bezier": {
"version": "3.2.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz", "resolved": "https://registry.npmjs.org/@types/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz",
@ -25769,9 +25788,9 @@
} }
}, },
"sortablejs": { "sortablejs": {
"version": "1.14.0", "version": "1.15.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
}, },
"source-list-map": { "source-list-map": {
"version": "2.0.1", "version": "2.0.1",
@ -27058,6 +27077,13 @@
"integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==",
"requires": { "requires": {
"sortablejs": "1.14.0" "sortablejs": "1.14.0"
},
"dependencies": {
"sortablejs": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz",
"integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
}
} }
}, },
"w3c-keyname": { "w3c-keyname": {

View File

@ -37,11 +37,11 @@
"prosemirror-state": "^1.4.1", "prosemirror-state": "^1.4.1",
"prosemirror-view": "^1.27.2", "prosemirror-view": "^1.27.2",
"register-service-worker": "^1.7.2", "register-service-worker": "^1.7.2",
"sortablejs": "^1.15.0",
"svg-arc-to-cubic-bezier": "^3.2.0", "svg-arc-to-cubic-bezier": "^3.2.0",
"svg-pathdata": "^6.0.0", "svg-pathdata": "^6.0.0",
"tinycolor2": "^1.6.0", "tinycolor2": "^1.6.0",
"vue": "^3.2.47", "vue": "^3.2.47"
"vuedraggable": "^4.1.0"
}, },
"devDependencies": { "devDependencies": {
"@commitlint/cli": "^17.4.4", "@commitlint/cli": "^17.4.4",
@ -51,6 +51,7 @@
"@types/file-saver": "^2.0.1", "@types/file-saver": "^2.0.1",
"@types/lodash": "^4.14.181", "@types/lodash": "^4.14.181",
"@types/resize-observer-browser": "^0.1.4", "@types/resize-observer-browser": "^0.1.4",
"@types/sortablejs": "^1.15.0",
"@types/svg-arc-to-cubic-bezier": "^3.2.0", "@types/svg-arc-to-cubic-bezier": "^3.2.0",
"@types/tinycolor2": "^1.4.3", "@types/tinycolor2": "^1.4.3",
"@typescript-eslint/eslint-plugin": "^5.4.0", "@typescript-eslint/eslint-plugin": "^5.4.0",

View File

@ -0,0 +1,86 @@
<template>
<div ref="containerRef" :class="$props.class">
<slot
v-for="(item, index) in list"
:key="item[props.itemKey]"
:element="item"
:index="index"
name="item"
></slot>
</div>
</template>
<script setup lang="ts">
import { ref, PropType, watch, onUnmounted } from 'vue'
import Sortable, { SortableOptions, SortableEvent } from 'sortablejs'
import type { AutoScrollOptions } from 'sortablejs/plugins'
type SortableOptionsProp = SortableOptions | AutoScrollOptions
const props = defineProps({
options: {
type: Object as PropType<SortableOptionsProp>,
default: () => ({}),
},
list: {
/* eslint-disable @typescript-eslint/no-explicit-any */
type: Array as PropType<any[]>,
required: true,
},
itemKey: {
type: String,
required: true,
},
})
const emit = defineEmits<{
(event: 'start', payload: SortableEvent): void
(event: 'end', payload: SortableEvent): void
(event: 'add', payload: SortableEvent): void
(event: 'remove', payload: SortableEvent): void
(event: 'update', payload: SortableEvent): void
}>()
const isDragging = ref(false)
const containerRef = ref<HTMLElement | null>(null)
const sortable = ref<Sortable | null>(null)
watch(containerRef, container => {
if (container) {
sortable.value = new Sortable(container, {
...props.options,
onStart: event => {
isDragging.value = true
emit('start', event)
},
onEnd: event => {
setTimeout(() => {
isDragging.value = false
emit('end', event)
})
},
onAdd: event => emit('add', event),
onRemove: event => emit('remove', event),
onUpdate: event => emit('update', event),
})
}
})
watch(() => props.options, options => {
if (options && sortable.value) {
for (const key in options) {
const name = key as keyof SortableOptionsProp
const value = options[key as keyof SortableOptionsProp]
sortable.value.option(name, value)
}
}
})
onUnmounted(() => {
if (sortable.value) {
sortable.value.destroy()
containerRef.value = null
sortable.value = null
}
})
</script>

View File

@ -15,13 +15,14 @@
</Popover> </Popover>
</div> </div>
<Draggable <Sortable
class="thumbnail-list" class="thumbnail-list"
:modelValue="slides" :list="slides"
:animation="300" :options="{
:scroll="true" animation: 200,
:scrollSensitivity="50" scroll: true,
:setData="null" scrollSensitivity: 50,
}"
@end="handleDragEnd" @end="handleDragEnd"
itemKey="id" itemKey="id"
> >
@ -39,7 +40,7 @@
<ThumbnailSlide class="thumbnail" :slide="element" :size="120" :visible="index < slidesLoadLimit" /> <ThumbnailSlide class="thumbnail" :slide="element" :size="120" :visible="index < slidesLoadLimit" />
</div> </div>
</template> </template>
</Draggable> </Sortable>
<div class="page-number">幻灯片 {{slideIndex + 1}} / {{slides.length}}</div> <div class="page-number">幻灯片 {{slideIndex + 1}} / {{slides.length}}</div>
</div> </div>
@ -55,7 +56,8 @@ import useSlideHandler from '@/hooks/useSlideHandler'
import useScreening from '@/hooks/useScreening' import useScreening from '@/hooks/useScreening'
import useLoadSlides from '@/hooks/useLoadSlides' import useLoadSlides from '@/hooks/useLoadSlides'
import Draggable from 'vuedraggable' import { SortableEvent } from 'sortablejs'
import Sortable from '@/components/Sortable.vue'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue' import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
import LayoutPool from './LayoutPool.vue' import LayoutPool from './LayoutPool.vue'
import { Popover } from 'ant-design-vue' import { Popover } from 'ant-design-vue'
@ -153,8 +155,9 @@ const setThumbnailsFocus = (focus: boolean) => {
} }
// //
const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => { const handleDragEnd = (eventData: SortableEvent) => {
const { newIndex, oldIndex } = eventData const { newIndex, oldIndex } = eventData
if (newIndex === undefined || oldIndex === undefined || newIndex === oldIndex) return
sortSlides(newIndex, oldIndex) sortSlides(newIndex, oldIndex)
} }

View File

@ -52,15 +52,17 @@
<Divider /> <Divider />
<Draggable <Sortable
class="animation-sequence" class="animation-sequence"
:modelValue="animationSequence" :list="animationSequence"
:animation="300" :options="{
:scroll="true" animation: 200,
:scrollSensitivity="50" scroll: true,
handle=".sequence-content" scrollSensitivity: 50,
@end="handleDragEnd" handle: '.sequence-content',
}"
itemKey="id" itemKey="id"
@end="handleDragEnd"
> >
<template #item="{ element }"> <template #item="{ element }">
<div class="sequence-item" :class="[element.type, { 'active': handleElement?.id === element.elId }]"> <div class="sequence-item" :class="[element.type, { 'active': handleElement?.id === element.elId }]">
@ -109,7 +111,7 @@
</div> </div>
</div> </div>
</template> </template>
</Draggable> </Sortable>
</div> </div>
</template> </template>
@ -130,7 +132,8 @@ import {
import { ELEMENT_TYPE_ZH } from '@/configs/element' import { ELEMENT_TYPE_ZH } from '@/configs/element'
import useHistorySnapshot from '@/hooks/useHistorySnapshot' import useHistorySnapshot from '@/hooks/useHistorySnapshot'
import Draggable from 'vuedraggable' import { SortableEvent } from 'sortablejs'
import Sortable from '@/components/Sortable.vue'
import { import {
InputNumber, InputNumber,
Divider, Divider,
@ -224,9 +227,9 @@ const deleteAnimation = (id: string) => {
} }
// //
const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => { const handleDragEnd = (eventData: SortableEvent) => {
const { newIndex, oldIndex } = eventData const { newIndex, oldIndex } = eventData
if (oldIndex === newIndex) return if (newIndex === undefined || oldIndex === undefined || newIndex === oldIndex) return
const animations: PPTAnimation[] = JSON.parse(JSON.stringify(currentSlideAnimations.value)) const animations: PPTAnimation[] = JSON.parse(JSON.stringify(currentSlideAnimations.value))
const animation = animations[oldIndex] const animation = animations[oldIndex]

View File

@ -1,15 +1,16 @@
<template> <template>
<div class="mobile-thumbnails"> <div class="mobile-thumbnails">
<Draggable <Sortable
class="thumbnail-list" class="thumbnail-list"
:modelValue="slides" :list="slides"
:animation="300" :options="{
:scroll="true" animation: 200,
:scrollSensitivity="50" scroll: true,
:setData="null" scrollSensitivity: 50,
delayOnTouchOnly: true,
delay: 800,
}"
itemKey="id" itemKey="id"
:delayOnTouchOnly="true"
:delay="800"
@end="handleDragEnd" @end="handleDragEnd"
> >
<template #item="{ element, index }"> <template #item="{ element, index }">
@ -22,7 +23,7 @@
<ThumbnailSlide class="thumbnail" :slide="element" :size="120" :visible="index < slidesLoadLimit" /> <ThumbnailSlide class="thumbnail" :slide="element" :size="120" :visible="index < slidesLoadLimit" />
</div> </div>
</template> </template>
</Draggable> </Sortable>
</div> </div>
</template> </template>
@ -32,7 +33,8 @@ import { useSlidesStore } from '@/store'
import useLoadSlides from '@/hooks/useLoadSlides' import useLoadSlides from '@/hooks/useLoadSlides'
import useSlideHandler from '@/hooks/useSlideHandler' import useSlideHandler from '@/hooks/useSlideHandler'
import Draggable from 'vuedraggable' import { SortableEvent } from 'sortablejs'
import Sortable from '@/components/Sortable.vue'
import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue' import ThumbnailSlide from '@/views/components/ThumbnailSlide/index.vue'
const slidesStore = useSlidesStore() const slidesStore = useSlidesStore()
@ -46,8 +48,9 @@ const changeSlideIndex = (index: number) => {
} }
// //
const handleDragEnd = (eventData: { newIndex: number; oldIndex: number }) => { const handleDragEnd = (eventData: SortableEvent) => {
const { newIndex, oldIndex } = eventData const { newIndex, oldIndex } = eventData
if (newIndex === undefined || oldIndex === undefined || newIndex === oldIndex) return
sortSlides(newIndex, oldIndex) sortSlides(newIndex, oldIndex)
} }
</script> </script>