Commit 679eab9f authored by hcyhuchaoyue's avatar hcyhuchaoyue

feat:树的拖动排序

parent 8fbacfac
## 2023-01-15
- 树拖动排序
## 2023-01-10 ## 2023-01-10
- 表单优化 - 表单优化
......
...@@ -6,9 +6,11 @@ import nestedDraggable from './infra/nested.vue'; ...@@ -6,9 +6,11 @@ import nestedDraggable from './infra/nested.vue';
const data = [ const data = [
{ {
name: 'task 1', name: 'task 1',
show: true,
tasks: [ tasks: [
{ {
name: 'task 2', name: 'task 2',
show: true,
tasks: [], tasks: [],
}, },
], ],
...@@ -16,9 +18,11 @@ const data = [ ...@@ -16,9 +18,11 @@ const data = [
}, },
{ {
name: 'task 3', name: 'task 3',
show: true,
tasks: [ tasks: [
{ {
name: 'task 4', name: 'task 4',
show: true,
tasks: [], tasks: [],
}, },
], ],
...@@ -26,6 +30,7 @@ const data = [ ...@@ -26,6 +30,7 @@ const data = [
}, },
{ {
name: 'task 5', name: 'task 5',
show: true,
tasks: [], tasks: [],
key: '3', key: '3',
}, },
...@@ -133,6 +138,7 @@ function addItem(data: any) { ...@@ -133,6 +138,7 @@ function addItem(data: any) {
let obj: any = { let obj: any = {
name: null, name: null,
show: true,
key: Date.now(), key: Date.now(),
}; };
obj[key] = []; obj[key] = [];
...@@ -159,6 +165,7 @@ function addNest(data: any) { ...@@ -159,6 +165,7 @@ function addNest(data: any) {
let obj: any = { let obj: any = {
name: null, name: null,
show: true,
key: Date.now(), key: Date.now(),
}; };
obj[key] = []; obj[key] = [];
...@@ -222,13 +229,13 @@ function delTestKey(listdata: any[], delKey = 'test_index') { ...@@ -222,13 +229,13 @@ function delTestKey(listdata: any[], delKey = 'test_index') {
column-gap: 10px; column-gap: 10px;
} }
.tree-box { .tree-box {
width: 600px; // width: 600px;
height: 500px; height: 500px;
box-sizing: border-box; box-sizing: border-box;
border: 1px solid brown; // border: 1px solid brown;
overflow: auto; overflow: auto;
> :nth-child(1) { > :nth-child(1) {
padding-right: 10px; // padding-right: 10px;
} }
} }
</style> </style>
...@@ -3,42 +3,66 @@ ...@@ -3,42 +3,66 @@
class="drag-area" class="drag-area"
tag="div" tag="div"
:list="tasks" :list="tasks"
handle=".handle"
:group="{ name: 'g1' }" :group="{ name: 'g1' }"
handle=".handle-icon"
item-key="key" item-key="key"
:onEnd="onEnd" :onEnd="onEnd"
:animation="150" :animation="150"
> >
<template #item="{ element }"> <template #item="{ element }">
<div class="drag-area-item"> <div class="item">
<div class="drag-area-item-conten"> <div>
<!-- <div class="text">{{ element.name }}</div> --> <div :class="['toggle-box', { 'toggle-box-btn': !element.show }]">
<div> <div class="toggle-left-content">
<i class="fa fa-align-justify handle"></i> <q-icon name="fa-solid fa-bars" class="handle-icon" />
<input type="text" class="form-control" v-model="element.name" /> <input type="text" class="input-control" v-model="element.name" />
</div> </div>
<div class="actions"> <div class="toggle-right-content">
<q-btn color="primary" icon="bi-list" @click="addItem(element)" /> <q-btn flat dense label="同级添加" @click="addItem(element)" />
<q-btn <q-btn flat dense label="子级添加" @click="addNest(element)" />
color="primary" <q-btn
icon="bi-list-nested" flat
@click="addNest(element)" dense
/> label="删除"
<q-btn color="primary" label="删除" @click="delItem(element)" /> style="margin-right: 20px"
@click="delItem(element)"
/>
<q-icon
v-if="!isEmpty(element.tasks)"
name="bi-chevron-down"
:class="[
'expansion-icon',
{ 'expansion-icon-hide': !element.show },
]"
@click="element.show = !element.show"
/>
</div>
</div> </div>
<q-slide-transition>
<div v-show="element.show" class="content">
<div
:class="[
'placeholder',
{ 'placeholder-last': isEmpty(element.tasks) },
]"
></div>
<nested-draggable
v-show="element.show"
:tasks="element.tasks"
@onEnd="onEnd"
@addItem="addItem"
@addNest="addNest"
@delItem="delItem"
/>
</div>
</q-slide-transition>
</div> </div>
<nested-draggable
:tasks="element.tasks"
@onEnd="onEnd"
@addItem="addItem"
@addNest="addNest"
@delItem="delItem"
/>
</div> </div>
</template> </template>
</draggable> </draggable>
</template> </template>
<script> <script>
// import { ref } from 'vue';
import { isEmpty } from 'src/common/utils'; import { isEmpty } from 'src/common/utils';
import draggable from 'vuedraggable'; import draggable from 'vuedraggable';
export default { export default {
...@@ -79,46 +103,86 @@ export default { ...@@ -79,46 +103,86 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.drag-area { .drag-area {
min-width: 450px; // border: 1px solid red;
// min-height: 20px; }
overflow: auto; .item {
/* outline: 1px dashed; */ // outline: 1px solid rgba(0, 0, 0, 0.035);
// background-color: pink;
border: 1px solid red; background-color: rgba(0, 0, 0, 0.035);
margin: 10px 0;
padding-left: 40px; padding-left: 10px;
& > :nth-child(1) { margin-left: 20px;
margin-top: 10px; margin-top: 10px;
} transition: height 0.3s;
.drag-area-item { }
min-width: 450px; .toggle-box {
outline: 1px solid #1ee3cf; display: flex;
margin-bottom: 10px; flex-direction: row;
justify-content: space-between;
align-items: center;
padding-top: 8px;
// padding-bottom: 6px;
padding-right: 10px;
}
.drag-area-item-conten { .toggle-box-btn {
height: 40px; padding-bottom: 6px;
box-sizing: border-box; }
background-color: #f9bcdd;
display: flex; .toggle-left-content {
flex-direction: row; display: flex;
flex-wrap: nowrap; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center;
column-gap: 10px;
}
.toggle-right-content {
display: grid;
grid-template-columns: 70px 70px 60px 30px;
align-items: center;
}
.handle-icon {
font-size: 18px;
box-sizing: border-box;
display: inline-block;
// border: 1px solid red;
cursor: grab;
}
.expansion-icon {
font-size: 16px;
cursor: pointer;
transform: rotate(180deg);
transition: transform 0.3s;
}
.expansion-icon-hide {
transform: rotate(0);
transition: transform 0.3s;
}
.actions { .content {
padding: 10px; // height: 46px;
display: flex; // background-color: pink;
flex-direction: row; }
justify-content: flex-start; .placeholder {
align-items: center; height: 20px;
column-gap: 10px; // background-color: pink;
} }
} .placeholder-last {
} height: 6px;
// background-color: pink;
}
.input-control {
outline-style: none;
border: 1px solid rgba(0, 0, 0, 0.035);
border-radius: 3px;
height: 32px;
padding: 0 6px;
.handle { &:focus {
float: left; border-color: $primary;
padding: 8px; outline: 0;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px $primary-1;
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px $primary-1;
} }
} }
</style> </style>
<template>
<draggable
class="drag-area"
tag="div"
:list="tasks"
handle=".handle"
:group="{ name: 'g1' }"
item-key="key"
:onEnd="onEnd"
:animation="150"
>
<template #item="{ element }">
<div class="drag-area-item">
<div class="drag-area-item-conten">
<!-- <div class="text">{{ element.name }}</div> -->
<div>
<i class="fa fa-align-justify handle"></i>
<input type="text" class="form-control" v-model="element.name" />
</div>
<div class="actions">
<q-btn color="primary" icon="bi-list" @click="addItem(element)" />
<q-btn
color="primary"
icon="bi-list-nested"
@click="addNest(element)"
/>
<q-btn color="primary" label="删除" @click="delItem(element)" />
</div>
</div>
<nested-draggable
:tasks="element.tasks"
@onEnd="onEnd"
@addItem="addItem"
@addNest="addNest"
@delItem="delItem"
/>
</div>
</template>
</draggable>
</template>
<script>
import { isEmpty } from 'src/common/utils';
import draggable from 'vuedraggable';
export default {
name: 'nested-draggable',
props: {
tasks: {
required: true,
type: Array,
},
},
components: {
draggable,
},
setup(props, ctx) {
const addItem = (data) => {
ctx.emit('addItem', data);
};
const addNest = (data) => {
ctx.emit('addNest', data);
};
const delItem = (data) => {
ctx.emit('delItem', data);
};
// 拖拽结束
const onEnd = (data) => {
ctx.emit('onEnd', data);
};
return {
isEmpty,
addItem,
addNest,
delItem,
onEnd,
};
},
};
</script>
<style scoped lang="scss">
.drag-area {
min-width: 450px;
// min-height: 20px;
overflow: auto;
/* outline: 1px dashed; */
border: 1px solid red;
padding-left: 40px;
& > :nth-child(1) {
margin-top: 10px;
}
.drag-area-item {
min-width: 450px;
outline: 1px solid #1ee3cf;
margin-bottom: 10px;
.drag-area-item-conten {
height: 40px;
box-sizing: border-box;
background-color: #f9bcdd;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
.actions {
padding: 10px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
column-gap: 10px;
}
}
}
.handle {
float: left;
padding: 8px;
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment