Commit 679eab9f authored by hcyhuchaoyue's avatar hcyhuchaoyue

feat:树的拖动排序

parent 8fbacfac
## 2023-01-15
- 树拖动排序
## 2023-01-10
- 表单优化
......
......@@ -6,9 +6,11 @@ import nestedDraggable from './infra/nested.vue';
const data = [
{
name: 'task 1',
show: true,
tasks: [
{
name: 'task 2',
show: true,
tasks: [],
},
],
......@@ -16,9 +18,11 @@ const data = [
},
{
name: 'task 3',
show: true,
tasks: [
{
name: 'task 4',
show: true,
tasks: [],
},
],
......@@ -26,6 +30,7 @@ const data = [
},
{
name: 'task 5',
show: true,
tasks: [],
key: '3',
},
......@@ -133,6 +138,7 @@ function addItem(data: any) {
let obj: any = {
name: null,
show: true,
key: Date.now(),
};
obj[key] = [];
......@@ -159,6 +165,7 @@ function addNest(data: any) {
let obj: any = {
name: null,
show: true,
key: Date.now(),
};
obj[key] = [];
......@@ -222,13 +229,13 @@ function delTestKey(listdata: any[], delKey = 'test_index') {
column-gap: 10px;
}
.tree-box {
width: 600px;
// width: 600px;
height: 500px;
box-sizing: border-box;
border: 1px solid brown;
// border: 1px solid brown;
overflow: auto;
> :nth-child(1) {
padding-right: 10px;
// padding-right: 10px;
}
}
</style>
......@@ -3,42 +3,66 @@
class="drag-area"
tag="div"
:list="tasks"
handle=".handle"
:group="{ name: 'g1' }"
handle=".handle-icon"
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 class="item">
<div>
<div :class="['toggle-box', { 'toggle-box-btn': !element.show }]">
<div class="toggle-left-content">
<q-icon name="fa-solid fa-bars" class="handle-icon" />
<input type="text" class="input-control" v-model="element.name" />
</div>
<div class="toggle-right-content">
<q-btn flat dense label="同级添加" @click="addItem(element)" />
<q-btn flat dense label="子级添加" @click="addNest(element)" />
<q-btn
flat
dense
label="删除"
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>
<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>
<nested-draggable
:tasks="element.tasks"
@onEnd="onEnd"
@addItem="addItem"
@addNest="addNest"
@delItem="delItem"
/>
</div>
</template>
</draggable>
</template>
<script>
// import { ref } from 'vue';
import { isEmpty } from 'src/common/utils';
import draggable from 'vuedraggable';
export default {
......@@ -79,46 +103,86 @@ export default {
</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;
// border: 1px solid red;
}
.item {
// outline: 1px solid rgba(0, 0, 0, 0.035);
// background-color: pink;
background-color: rgba(0, 0, 0, 0.035);
margin: 10px 0;
padding-left: 10px;
margin-left: 20px;
margin-top: 10px;
transition: height 0.3s;
}
.toggle-box {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding-top: 8px;
// padding-bottom: 6px;
padding-right: 10px;
}
.drag-area-item-conten {
height: 40px;
box-sizing: border-box;
background-color: #f9bcdd;
.toggle-box-btn {
padding-bottom: 6px;
}
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: space-between;
.toggle-left-content {
display: flex;
flex-direction: row;
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 {
padding: 10px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
column-gap: 10px;
}
}
}
.content {
// height: 46px;
// background-color: pink;
}
.placeholder {
height: 20px;
// 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 {
float: left;
padding: 8px;
&:focus {
border-color: $primary;
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>
<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