test:1.组件嵌套拖拽
2.schema定义与动态绑定
This commit is contained in:
4
auto-imports.d.ts
vendored
4
auto-imports.d.ts
vendored
@ -152,6 +152,7 @@ declare global {
|
||||
const useDeviceOrientation: typeof import('@vueuse/core')['useDeviceOrientation']
|
||||
const useDevicePixelRatio: typeof import('@vueuse/core')['useDevicePixelRatio']
|
||||
const useDevicesList: typeof import('@vueuse/core')['useDevicesList']
|
||||
const useDialog: typeof import('naive-ui')['useDialog']
|
||||
const useDisplayMedia: typeof import('@vueuse/core')['useDisplayMedia']
|
||||
const useDocumentVisibility: typeof import('@vueuse/core')['useDocumentVisibility']
|
||||
const useDraggable: typeof import('@vueuse/core')['useDraggable']
|
||||
@ -184,6 +185,7 @@ declare global {
|
||||
const useKeyModifier: typeof import('@vueuse/core')['useKeyModifier']
|
||||
const useLastChanged: typeof import('@vueuse/core')['useLastChanged']
|
||||
const useLink: typeof import('vue-router')['useLink']
|
||||
const useLoadingBar: typeof import('naive-ui')['useLoadingBar']
|
||||
const useLocalStorage: typeof import('@vueuse/core')['useLocalStorage']
|
||||
const useMagicKeys: typeof import('@vueuse/core')['useMagicKeys']
|
||||
const useManualRefHistory: typeof import('@vueuse/core')['useManualRefHistory']
|
||||
@ -191,6 +193,7 @@ declare global {
|
||||
const useMediaQuery: typeof import('@vueuse/core')['useMediaQuery']
|
||||
const useMemoize: typeof import('@vueuse/core')['useMemoize']
|
||||
const useMemory: typeof import('@vueuse/core')['useMemory']
|
||||
const useMessage: typeof import('naive-ui')['useMessage']
|
||||
const useMounted: typeof import('@vueuse/core')['useMounted']
|
||||
const useMouse: typeof import('@vueuse/core')['useMouse']
|
||||
const useMouseInElement: typeof import('@vueuse/core')['useMouseInElement']
|
||||
@ -198,6 +201,7 @@ declare global {
|
||||
const useMutationObserver: typeof import('@vueuse/core')['useMutationObserver']
|
||||
const useNavigatorLanguage: typeof import('@vueuse/core')['useNavigatorLanguage']
|
||||
const useNetwork: typeof import('@vueuse/core')['useNetwork']
|
||||
const useNotification: typeof import('naive-ui')['useNotification']
|
||||
const useNow: typeof import('@vueuse/core')['useNow']
|
||||
const useObjectUrl: typeof import('@vueuse/core')['useObjectUrl']
|
||||
const useOffsetPagination: typeof import('@vueuse/core')['useOffsetPagination']
|
||||
|
||||
10
components.d.ts
vendored
10
components.d.ts
vendored
@ -7,13 +7,23 @@ export {}
|
||||
/* prettier-ignore */
|
||||
declare module 'vue' {
|
||||
export interface GlobalComponents {
|
||||
AButton: typeof import('@arco-design/web-vue')['Button']
|
||||
AInput: typeof import('@arco-design/web-vue')['Input']
|
||||
ARate: typeof import('@arco-design/web-vue')['Rate']
|
||||
ASwitch: typeof import('@arco-design/web-vue')['Switch']
|
||||
ATable: typeof import('@arco-design/web-vue')['Table']
|
||||
ElButton: typeof import('element-plus/es')['ElButton']
|
||||
ElInput: typeof import('element-plus/es')['ElInput']
|
||||
ElLabel: typeof import('element-plus/es')['ElLabel']
|
||||
ElTable: typeof import('./src/components/ElTable.vue')['default']
|
||||
ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
|
||||
ElText: typeof import('element-plus/es')['ElText']
|
||||
MyComponent1: typeof import('./src/components/MyComponent1.vue')['default']
|
||||
MyComponent2: typeof import('./src/components/MyComponent2.vue')['default']
|
||||
MyComponent3: typeof import('./src/components/MyComponent3.vue')['default']
|
||||
NDataTable: typeof import('naive-ui')['NDataTable']
|
||||
NestedDirective: typeof import('./src/components/NestedDirective.vue')['default']
|
||||
NestedFunction: typeof import('./src/components/NestedFunction.vue')['default']
|
||||
VueDemo: typeof import('./src/components/VueDemo.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
930
package-lock.json
generated
930
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@vueuse/core": "^10.11.0",
|
||||
"element-plus": "^2.7.8",
|
||||
"lodash": "^4.17.21",
|
||||
"lsp-uuid": "^3.2.0",
|
||||
"vue": "^3.2.25",
|
||||
@ -18,12 +17,15 @@
|
||||
"vue-draggable-plus": "^0.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arco-design/web-vue": "^2.56.0",
|
||||
"@vitejs/plugin-vue": "^5.0.5",
|
||||
"less": "^4.2.0",
|
||||
"naive-ui": "^2.39.0",
|
||||
"sass": "^1.77.8",
|
||||
"typescript": "^5.2.2",
|
||||
"unplugin-auto-import": "^0.18.2",
|
||||
"unplugin-vue-components": "^0.27.3",
|
||||
"vfonts": "^0.0.3",
|
||||
"vite": "^5.3.4",
|
||||
"vue-loader": "^17.4.2",
|
||||
"vue-template-compiler": "^2.7.16",
|
||||
|
||||
22
src/components/ElTable.vue
Normal file
22
src/components/ElTable.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="el-table">
|
||||
<tr v-for="item in list" :key="item.name" class="cursor-move">
|
||||
<td>{{ item.id }}</td>
|
||||
<td>{{ item.name }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
list: Record<'name' | 'id', string>[]
|
||||
}
|
||||
defineProps<Props>()
|
||||
</script>
|
||||
@ -1,33 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 左侧组件列表 -->
|
||||
<div class="left">
|
||||
<div
|
||||
class="left-item"
|
||||
v-for="item in list1"
|
||||
:key="item.code"
|
||||
draggable
|
||||
>
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 画布区域 -->
|
||||
<div class="targetContent" ref="targetContent">
|
||||
<div
|
||||
class="item"
|
||||
v-for="item in list2"
|
||||
:key="item.id"
|
||||
:ref="item.id"
|
||||
:style="{
|
||||
top: `${item.top - 16}px`,
|
||||
left: `${item.left - 85}px`,
|
||||
'z-index': `${item.zIndex}`
|
||||
}"
|
||||
>
|
||||
<template v-if="item.code === 'MyInput'">
|
||||
<a-input></a-input>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<div style="background: lightgreen; height: 100%; padding: 10px;">
|
||||
组件2内容
|
||||
<div v-if="$slots.default" class="slot-area">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MyComponent2'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.slot-area {
|
||||
border: 2px dashed grey;
|
||||
min-height: 50px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
@ -1,22 +0,0 @@
|
||||
<template>
|
||||
<div style="background: lightcoral; height: 100%; padding: 10px;">
|
||||
组件3内容
|
||||
<div v-if="$slots.default" class="slot-area">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MyComponent3'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.slot-area {
|
||||
border: 2px dashed grey;
|
||||
min-height: 50px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
</style>
|
||||
37
src/components/NestedDirective.vue
Normal file
37
src/components/NestedDirective.vue
Normal file
@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<ul v-draggable="[list, { group: 'g1' }]" class="drag-area">
|
||||
<li v-for="el in modelValue" :key="el.name">
|
||||
<p>{{ el.name }}</p>
|
||||
<nested-directive v-model="el.children" />
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { vDraggable } from 'vue-draggable-plus'
|
||||
import { computed } from 'vue'
|
||||
|
||||
interface IList {
|
||||
name: string
|
||||
children: IList[]
|
||||
}
|
||||
|
||||
interface Props {
|
||||
modelValue: IList[]
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', value: IList[]): void
|
||||
}
|
||||
const emits = defineEmits<Emits>()
|
||||
const list = computed({
|
||||
get: () => props.modelValue,
|
||||
set: value => emits('update:modelValue', value)
|
||||
})
|
||||
</script>
|
||||
<style scoped>
|
||||
.drag-area {
|
||||
min-height: 50px;
|
||||
outline: 1px dashed;
|
||||
}
|
||||
</style>
|
||||
55
src/components/NestedFunction.vue
Normal file
55
src/components/NestedFunction.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<ul class="drag-area" ref="el">
|
||||
<li v-for="el in modelValue" :key="el.name">
|
||||
<div style="width: 200px;border: 1px solid red;">
|
||||
<p>{{ el.name }}:{{ el.id }}</p>
|
||||
</div>
|
||||
<nested-function v-model="el.children" />
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useDraggable} from 'vue-draggable-plus'
|
||||
import { computed, ref } from 'vue'
|
||||
import { IList } from '../type/IList'
|
||||
|
||||
interface Props {
|
||||
modelValue: IList[]
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', value: IList[]): void
|
||||
}
|
||||
const emits = defineEmits<Emits>()
|
||||
const list = computed({
|
||||
get: () => props.modelValue,
|
||||
set: value => emits('update:modelValue', value)
|
||||
})
|
||||
|
||||
const el = ref()
|
||||
useDraggable(el, list, {
|
||||
group: 'designer',
|
||||
animation: 150,
|
||||
onStart() {
|
||||
console.log('start')
|
||||
},
|
||||
onUpdate() {
|
||||
console.log('update list1')
|
||||
},
|
||||
onAdd: (e) => {
|
||||
// console.log(e)
|
||||
console.log('add list1')
|
||||
},
|
||||
onRemove: () => {
|
||||
console.log('remove list1')
|
||||
}
|
||||
},)
|
||||
</script>
|
||||
<style scoped>
|
||||
.drag-area {
|
||||
min-height: 50px;
|
||||
outline: 1px dashed;
|
||||
background-color: hsl(0, 0%, 100%);
|
||||
}
|
||||
</style>
|
||||
@ -1,81 +1,75 @@
|
||||
<template>
|
||||
<div style="display: flex;">
|
||||
<section v-draggable="[
|
||||
list1,
|
||||
{
|
||||
animation: 150,
|
||||
group: {
|
||||
name: 'people',
|
||||
pull: 'clone',
|
||||
put: false
|
||||
},
|
||||
sort: false,
|
||||
clone
|
||||
}
|
||||
]">
|
||||
<div v-for="item in list1" :key="item.id" style="border: 1px solid green;margin: 5px;">
|
||||
{{ item.name }}
|
||||
<div style="display: flex;flex-direction: row;">
|
||||
<div ref="el2" style="margin: 5%;display: flex;flex-direction: column;">
|
||||
<div v-for="item in list1" :key="item.id" style="width: 200px;border: 1px solid red;">
|
||||
{{ item.name }}:{{ item.id }}
|
||||
</div>
|
||||
</section>
|
||||
<section v-draggable="[
|
||||
list2,
|
||||
{
|
||||
animation: 150,
|
||||
group: 'people'
|
||||
}
|
||||
]">
|
||||
<div v-for="item in list2" :key="item.id" style="border: 1px solid red;margin: 5px;">
|
||||
{{ item.name }}
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
{{ list1 }}
|
||||
</div>
|
||||
<div>
|
||||
{{ list2 }}
|
||||
|
||||
<div class="flex justify-between">
|
||||
<NestedFunction v-model="list" class="w-full"></NestedFunction>
|
||||
{{ list }}
|
||||
</div>
|
||||
</br>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { uuid } from 'lsp-uuid'
|
||||
import { vDraggable } from 'vue-draggable-plus'
|
||||
import NestedFunction from './NestedFunction.vue'
|
||||
import { useDraggable } from 'vue-draggable-plus'
|
||||
import { uuid } from 'lsp-uuid';
|
||||
|
||||
|
||||
const list1 = ref([
|
||||
{
|
||||
name: 'Joao',
|
||||
id: '1'
|
||||
{
|
||||
type: 'Switch',
|
||||
name: '开关',
|
||||
id: 'switch',
|
||||
designer: '',
|
||||
props: {},
|
||||
style: '',
|
||||
class: '',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
name: 'Jean',
|
||||
id: '2'
|
||||
type: 'Rate',
|
||||
name: '开关',
|
||||
id: 'rate',
|
||||
designer: '',
|
||||
props: {},
|
||||
style: '',
|
||||
class: '',
|
||||
children: []
|
||||
},
|
||||
{
|
||||
name: 'Johanna',
|
||||
id: '3'
|
||||
},
|
||||
{
|
||||
name: 'Juan',
|
||||
id: '4'
|
||||
type: 'Button',
|
||||
name: '按钮',
|
||||
id: 'button',
|
||||
designer: '',
|
||||
props: {},
|
||||
style: '',
|
||||
class: '',
|
||||
children: []
|
||||
}
|
||||
])
|
||||
const list2 = ref(
|
||||
list1.value.map(item => ({
|
||||
name: `${item.name}-2`,
|
||||
id: `${item.id}-2`
|
||||
}))
|
||||
)
|
||||
|
||||
function clone(element: Record<'name' | 'id', string>) {
|
||||
const len = list2.value.length
|
||||
return {
|
||||
name: `${element.name}-clone-${len}`,
|
||||
id: `${element.id}-clone-${uuid()}`
|
||||
])
|
||||
const list=ref([])
|
||||
|
||||
const el2 = ref()
|
||||
|
||||
useDraggable(el2, list1, {
|
||||
animation: 150,
|
||||
group: { name: 'designer', pull: 'clone', put: false },
|
||||
sort: false,
|
||||
onClone() {
|
||||
console.log('clone')
|
||||
},
|
||||
clone(element: Record<'id'|'children', any>) {
|
||||
return {
|
||||
id: `${element.id}-${uuid()}`,
|
||||
children:[]
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
10
src/type/IList.ts
Normal file
10
src/type/IList.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export interface IList {
|
||||
type: string;
|
||||
name: string;
|
||||
id: string;
|
||||
designer: JSON;
|
||||
props: JSON;
|
||||
style: string;
|
||||
class: string;
|
||||
children: IList[];
|
||||
}
|
||||
@ -5,21 +5,25 @@ import vue from '@vitejs/plugin-vue'
|
||||
// import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
|
||||
import AutoImport from 'unplugin-auto-import/vite'
|
||||
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
|
||||
import { ArcoResolver } from 'unplugin-vue-components/resolvers'
|
||||
import Components from 'unplugin-vue-components/vite'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
AutoImport({
|
||||
resolvers: [ElementPlusResolver({ importStyle: 'sass' })],
|
||||
resolvers: [ArcoResolver()],
|
||||
imports: [
|
||||
'vue',
|
||||
'vue-router',
|
||||
'@vueuse/core',
|
||||
{
|
||||
from: 'element-plus',
|
||||
imports: ['ElMessage', 'ElMessageBox']
|
||||
'naive-ui': [
|
||||
'useDialog',
|
||||
'useMessage',
|
||||
'useNotification',
|
||||
'useLoadingBar'
|
||||
]
|
||||
}
|
||||
],
|
||||
dirs: [
|
||||
@ -30,7 +34,11 @@ export default defineConfig({
|
||||
]
|
||||
}),
|
||||
Components({
|
||||
resolvers: [ElementPlusResolver({ importStyle: 'sass' })]
|
||||
resolvers: [
|
||||
ArcoResolver({
|
||||
sideEffect: true
|
||||
})
|
||||
]
|
||||
}),
|
||||
vue(),
|
||||
// vueDevTools()
|
||||
|
||||
Reference in New Issue
Block a user