164 lines
4.9 KiB
Vue
164 lines
4.9 KiB
Vue
<template>
|
|
<div ref="draggableContainer" class="draggableContainer">
|
|
<main v-for="item in list" :key="item.title" style="margin:2px;">
|
|
<section class="draggable-item">
|
|
<section class="my-handle r-2"
|
|
style="width: 100%;display:flex;justify-content:space-between;line-height:32px;">
|
|
<div>
|
|
<a-input flex="none" readonly :value="item.sequence as number + 1" class="site-input-split" style="width: 40px;border-radius:0; border-top-left-radius: 5pt 5pt;
|
|
border-bottom-left-radius: 5pt 5pt; border-radius: 0;pointer-events: none" />
|
|
|
|
<a-input flex="none" readonly :value="item.title" class="site-input-split" style="width: 100px;border-radius:0; border-top-right-radius: 5pt 5pt;
|
|
border-bottom-right-radius: 5pt 5pt;pointer-events: none" />
|
|
</div>
|
|
<div style="margin-left: 4px;">
|
|
<a-radio-group v-model:value="item.hidden" @change="onChange">
|
|
<a-radio-button value="N">显示</a-radio-button>
|
|
<a-radio-button value="Y">隐藏</a-radio-button>
|
|
</a-radio-group>
|
|
</div>
|
|
<div style="margin-left: 4px;">
|
|
<a-input v-model:value="item.width" @change="onChange" style="width:60px; border-radius:0; border-top-left-radius: 5pt 5pt;
|
|
border-bottom-left-radius: 5pt 5pt; text-align: right;" />
|
|
<a-select style="width:60px; border-radius: 5pt 5pt;" v-model:value="item.fixed" @select="onChange">
|
|
<a-select-option value=""></a-select-option>
|
|
<a-select-option value="left">左</a-select-option>
|
|
<a-select-option value="right">右</a-select-option>
|
|
</a-select>
|
|
</div>
|
|
|
|
</section>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts" setup>
|
|
import { onMounted, onUnmounted, ref } from 'vue';
|
|
import Sortable from 'sortablejs';
|
|
|
|
// interface Item {
|
|
// label: string;
|
|
// value: string; // 可能是会需要value值
|
|
// }
|
|
interface Props {
|
|
list: Array<Column>;
|
|
options?: Sortable.Options;
|
|
}
|
|
|
|
const draggableContainer = ref<HTMLDivElement | null>(null);
|
|
|
|
const props = defineProps<Props>();
|
|
|
|
interface EmitsType {
|
|
(e: 'update:list', value: any[]): void;
|
|
(e: 'onChangeList', value: any[]): void;
|
|
}
|
|
|
|
const emit = defineEmits<EmitsType>();
|
|
|
|
const sortable = ref<Sortable | null>(null);
|
|
|
|
onMounted(() => {
|
|
let i: number = 0;
|
|
props.list.forEach((element: Column) => {
|
|
element.sequence = i++;
|
|
});
|
|
initDraggable();
|
|
});
|
|
|
|
const onChange = () => {
|
|
emit('onChangeList', props.list);
|
|
};
|
|
|
|
const initDraggable = () => {
|
|
if (!draggableContainer.value) {
|
|
console.warn('容器不能为空');
|
|
return;
|
|
}
|
|
sortable.value = Sortable.create(draggableContainer.value, {
|
|
handle: '.my-handle',
|
|
chosenClass: 'chosen',
|
|
dragClass: 'drag',
|
|
direction: 'horizontal',
|
|
forceFallback: true,
|
|
animation: 300,
|
|
onUpdate(e: any) {
|
|
if (e.oldIndex !== undefined && e.newIndex !== undefined) {
|
|
// 删除拖拽的元素
|
|
let list = [...props.list];
|
|
const item = list.splice(e.oldIndex, 1)[0];
|
|
// 把删除的元素放到新的位置
|
|
list.splice(e.newIndex, 0, item);
|
|
let i: number = 0;
|
|
list = list.map((element: Column) => {
|
|
return { ...element, sequence: i++ };
|
|
});
|
|
emit('update:list', list);
|
|
emit('onChangeList', list);
|
|
};
|
|
},
|
|
...props.options
|
|
});
|
|
};
|
|
|
|
onUnmounted(() => {
|
|
sortable.value?.destroy();
|
|
});
|
|
</script>
|
|
|
|
<style lang="less" scoped>
|
|
.draggableContainer {
|
|
max-width: 30rem;
|
|
background: #ffffff;
|
|
color: #495057;
|
|
border: 0 none;
|
|
border-radius: 6px;
|
|
box-shadow: 0 2px 12px 0 rgb(0 0 0 / 10%);
|
|
}
|
|
|
|
.r-2 {
|
|
margin-right: 2rem;
|
|
}
|
|
|
|
.draggable-item {
|
|
margin: 0;
|
|
padding: 0.75rem 1.25rem;
|
|
border-width: 1px;
|
|
border-style: solid;
|
|
border-color: #d9d9d9;
|
|
color: #495057;
|
|
background: transparent;
|
|
transition: box-shadow 0.2s;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
font-weight: normal;
|
|
white-space: nowrap;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
|
|
//.draggable-item:hover {
|
|
// background: #e9ecef;
|
|
//}
|
|
.my-handle {
|
|
cursor: move;
|
|
cursor: -webkit-grabbing;
|
|
}
|
|
|
|
.drag {
|
|
// 正在拖拽中幽灵图的样式
|
|
display: none;
|
|
cursor: move;
|
|
cursor: -webkit-grabbing;
|
|
}
|
|
|
|
.chosen {
|
|
cursor: move;
|
|
cursor: -webkit-grabbing;
|
|
border-radius: 6px;
|
|
box-shadow: 0 2px 10px 0 rgb(0 0 0 / 20%);
|
|
}
|
|
</style> |