mirror of
https://github.com/sahadev/vue-component-creater-ui.git
synced 2025-06-06 21:14:03 +08:00
update: 集成好vuedraggable
This commit is contained in:
parent
1c61f4b83a
commit
b870e28608
27
package-lock.json
generated
27
package-lock.json
generated
@ -2189,6 +2189,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@vue/devtools-api": {
|
||||
"version": "6.0.0-beta.20.1",
|
||||
"resolved": "https://rg.cnpmjs.org/@vue/devtools-api/download/@vue/devtools-api-6.0.0-beta.20.1.tgz",
|
||||
"integrity": "sha512-R2rfiRY+kZugzWh9ZyITaovx+jpU4vgivAEAiz80kvh3yviiTU3CBuGuyWpSwGz9/C7TkSWVM/FtQRGlZ16n8Q=="
|
||||
},
|
||||
"@vue/eslint-config-airbnb": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://r.cnpmjs.org/@vue/eslint-config-airbnb/download/@vue/eslint-config-airbnb-5.3.0.tgz",
|
||||
@ -11934,6 +11939,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"sortablejs": {
|
||||
"version": "1.14.0",
|
||||
"resolved": "https://rg.cnpmjs.org/sortablejs/download/sortablejs-1.14.0.tgz",
|
||||
"integrity": "sha1-bS4XzL2yX0ZHNN9iHU811Ks1s9g="
|
||||
},
|
||||
"source-list-map": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://r.cnpmjs.org/source-list-map/download/source-list-map-2.0.1.tgz",
|
||||
@ -13347,10 +13357,21 @@
|
||||
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
|
||||
"dev": true
|
||||
},
|
||||
"vuedraggable": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://rg.cnpmjs.org/vuedraggable/download/vuedraggable-4.1.0.tgz",
|
||||
"integrity": "sha1-7ezmituKTZ4GrM/538kEDmaFInA=",
|
||||
"requires": {
|
||||
"sortablejs": "1.14.0"
|
||||
}
|
||||
},
|
||||
"vuex": {
|
||||
"version": "3.6.2",
|
||||
"resolved": "https://r.cnpmjs.org/vuex/download/vuex-3.6.2.tgz",
|
||||
"integrity": "sha1-I2vAhqhww655lG8QfxbeWdWJXnE="
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://rg.cnpmjs.org/vuex/download/vuex-4.0.2.tgz",
|
||||
"integrity": "sha1-+Jbb1b8qDpY/AMZ+m2EN50nMrMk=",
|
||||
"requires": {
|
||||
"@vue/devtools-api": "^6.0.0-beta.11"
|
||||
}
|
||||
},
|
||||
"watchpack": {
|
||||
"version": "1.7.5",
|
||||
|
@ -62,7 +62,8 @@
|
||||
"vue": "^3.2.22",
|
||||
"vue-nestable": "^2.6.0",
|
||||
"vue-router": "^3.4.9",
|
||||
"vuex": "^3.1.2"
|
||||
"vuedraggable": "^4.1.0",
|
||||
"vuex": "^4.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/generator": "^7.11.6",
|
||||
|
@ -16,8 +16,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<attribute-input :enableRemoveButton="true" class="attribute" @save="onSaveAttr" @remove="onRemove"
|
||||
ref="attributeInput" shortcutInitMode="hand" @codeRefresh="generateVueCode"
|
||||
:__rawVueInfo__="currentEditRawInfo">
|
||||
ref="attributeInput" shortcutInitMode="hand" :__rawVueInfo__="currentEditRawInfo">
|
||||
</attribute-input>
|
||||
</div>
|
||||
</div>
|
||||
@ -50,7 +49,7 @@
|
||||
<lc-code :rawCode="code" v-model:codeDialogVisible="codeDialogVisible">
|
||||
</lc-code>
|
||||
<code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" v-model="structureVisible"
|
||||
@codeRefresh="generateVueCode" @onLevelChange="onLevelChange">
|
||||
@reRender="render">
|
||||
</code-structure>
|
||||
<CodeEditor v-model:codeDialogVisible="jsDialogVisible" @saveJSCode="saveJSCode"></CodeEditor>
|
||||
<VueEditor v-model:vueDialogVisible="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor>
|
||||
@ -220,11 +219,6 @@ export default {
|
||||
this.mainPanelProvider.saveAttribute(resultList, lc_id);
|
||||
},
|
||||
|
||||
onLevelChange(removeID, movePath) {
|
||||
this.mainPanelProvider.onLevelChange(removeID, movePath);
|
||||
},
|
||||
|
||||
generateVueCode() { },
|
||||
onRemove({ lc_id }) {
|
||||
this.mainPanelProvider.remove(lc_id);
|
||||
},
|
||||
@ -240,10 +234,20 @@ export default {
|
||||
this.mainPanelProvider.saveJSCode(code);
|
||||
},
|
||||
|
||||
/**
|
||||
* 二级编辑解析
|
||||
*/
|
||||
codeParseSucess(vueCodeEntity) {
|
||||
this.mainPanelProvider.render(vueCodeEntity);
|
||||
},
|
||||
|
||||
/**
|
||||
* 渲染指定结构
|
||||
*/
|
||||
render(codeEntity) {
|
||||
this.mainPanelProvider.render(codeEntity);
|
||||
},
|
||||
|
||||
help() {
|
||||
window.open('/doc')
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-card class="attribute-container">
|
||||
|
||||
<div style="text-algin: center;">
|
||||
<div style="text-align: center;">
|
||||
<el-switch v-model="editMode" active-text="自由编辑" inactive-text="约束编辑" active-color="#13ce66"
|
||||
inactive-color="#13ce66">
|
||||
</el-switch>
|
||||
@ -197,7 +197,7 @@ export default {
|
||||
},
|
||||
copyBro() {
|
||||
copyBroCode(this.__rawVueInfo__);
|
||||
this.$emit('codeRefresh');
|
||||
this.$store.commit('onDragEnd');
|
||||
},
|
||||
onShow() {
|
||||
// 这种方式适用于常规模式下的初始化,因为这个实例初始化后不会被销毁,一直常驻内存。但又不能受到其它实例销毁时的影响,所以需要明确的再次初始化。
|
||||
|
@ -2,7 +2,7 @@
|
||||
<el-drawer v-model="drawer" :with-header="false" size="70%" direction="btt">
|
||||
<div class="container">
|
||||
|
||||
<div style="text-algin: center;">组件结构检视图
|
||||
<div style="text-align: center;">组件结构检视图
|
||||
<br>
|
||||
<span style="font-size:12px;">Components
|
||||
Structure</span>
|
||||
@ -12,26 +12,13 @@
|
||||
<el-col :span="16" style="height: 100%;">
|
||||
<div style="overflow: scroll;height:100%; margin: 0 20px;padding: 10px;">
|
||||
|
||||
<!-- <vue-nestable v-model="treeData" @change="onLevelChange">
|
||||
<template v-slot="{ item }">
|
||||
<vue-nestable-handle :item="item">
|
||||
<el-icon class="icon-s"><rank /></el-icon>
|
||||
</vue-nestable-handle>
|
||||
|
||||
<span @click="onNodeClick(item)">{{ item.text }}</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:placeholder>
|
||||
<div><b>The editor is empty.</b></div>
|
||||
</template>
|
||||
</vue-nestable> -->
|
||||
<nested-draggable :data="treeData" />
|
||||
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<attribute-input ref="attributeInput" :enableRemoveButton="true" v-if="currentEditRawInfo && drawer"
|
||||
@save="onSaveAttr" shortcutInitMode="auto" @remove="onRemove" @codeRefresh="codeRefresh"
|
||||
:__rawVueInfo__="currentEditRawInfo">
|
||||
<attribute-input ref="attributeInput" :enableRemoveButton="true" v-if="currentEditRawInfo" @save="onSaveAttr"
|
||||
shortcutInitMode="auto" @remove="onRemove" :__rawVueInfo__="currentEditRawInfo">
|
||||
</attribute-input>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -41,81 +28,33 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import "./halower-tree.min.css";
|
||||
import "@/assets/nestable.css"
|
||||
import { isObject, getRawComponentKey, getRawComponentContent } from "@/utils/common";
|
||||
// import { VueNestable, VueNestableHandle } from 'vue-nestable';
|
||||
import nestedDraggable from './nested.vue'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
export default {
|
||||
props: ['visible'],
|
||||
emits: ['codeRefresh', 'onLevelChange', 'remove', 'save', 'update:visible'],
|
||||
emits: ['onLevelChange', 'remove', 'save', 'update:visible', 'reRender'],
|
||||
components: {
|
||||
AttributeInput: resolve => { require(["./AttributeInput"], resolve) },
|
||||
// VueNestable,
|
||||
// VueNestableHandle
|
||||
AttributeInput: defineAsyncComponent(() => import("@/components/AttributeInput.vue")),
|
||||
nestedDraggable
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
// 在此自动生成
|
||||
treeData: [],
|
||||
currentEditRawInfo: null
|
||||
};
|
||||
},
|
||||
beforeCreate() { },
|
||||
created() { },
|
||||
beforeMount() { },
|
||||
mounted() { },
|
||||
mounted() {
|
||||
},
|
||||
beforeUpdate() { },
|
||||
updated() { },
|
||||
destoryed() { },
|
||||
methods: {
|
||||
// 在此自动生成
|
||||
request() {
|
||||
// 网络请求,可选
|
||||
},
|
||||
codeRefresh() {
|
||||
this.$emit('codeRefresh');
|
||||
},
|
||||
onLevelChange(value, options) {
|
||||
this.$emit('onLevelChange', value.id, options.pathTo);
|
||||
},
|
||||
|
||||
convertStructure(rawInfo) {
|
||||
const title = getRawComponentKey(rawInfo);
|
||||
const object = rawInfo[title];
|
||||
const children = [];
|
||||
if (isObject(object)) {
|
||||
for (const key in object) {
|
||||
if (object.hasOwnProperty(key)) {
|
||||
if (key === '__children') {
|
||||
const element = object[key];
|
||||
|
||||
element.forEach(item => {
|
||||
const temp = this.convertStructure(item);
|
||||
temp && children.push(temp);
|
||||
})
|
||||
} else if (isObject(object[key])) {
|
||||
// 组成一个新的结构,适配只有一个子节点的数据结构
|
||||
const __obj = {};
|
||||
__obj[key] = object[key];
|
||||
const child = this.convertStructure(__obj);
|
||||
child && children.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
text: title,
|
||||
expanded: true,
|
||||
children: children,
|
||||
rawInfo: rawInfo,
|
||||
id: getRawComponentContent(rawInfo).lc_id
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
onNodeClick(nodeInfo) {
|
||||
this.currentEditRawInfo = nodeInfo.rawInfo;
|
||||
@ -131,12 +70,17 @@ export default {
|
||||
},
|
||||
|
||||
updateCode(codeRawInfo) {
|
||||
this.treeData = [this.convertStructure(codeRawInfo)];
|
||||
this._codeRawInfo = codeRawInfo;
|
||||
const content = getRawComponentContent(codeRawInfo);
|
||||
const children = content.__children;
|
||||
this.treeData = children;
|
||||
},
|
||||
|
||||
},
|
||||
watch: {
|
||||
canInitShortcut(newValue) {
|
||||
renderCount(){
|
||||
// 这里利用了vuedraggable v-model的特性,它会更改对象本身的引用
|
||||
this.$emit('reRender', this._codeRawInfo);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -148,8 +92,21 @@ export default {
|
||||
this.$emit('update:visible', false);
|
||||
}
|
||||
},
|
||||
|
||||
renderCount(){
|
||||
return this.$store.state.renderCount;
|
||||
},
|
||||
|
||||
canInitShortcut() {
|
||||
return this.currentEditRawInfo !== null && this.drawer;
|
||||
},
|
||||
currentEditRawInfo() {
|
||||
if (this.$store.state.currentEditComp) {
|
||||
const vccData = this.$store.state.currentEditComp.vccData;
|
||||
return window.tree[vccData.lc_id];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
fillter: {},
|
||||
|
576
src/components/halower-tree.min.css
vendored
576
src/components/halower-tree.min.css
vendored
File diff suppressed because one or more lines are too long
89
src/components/nested.vue
Normal file
89
src/components/nested.vue
Normal file
@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<draggable class="dragArea" tag="ul" :list="data" @start="onStartDrag" @choose="onClick"
|
||||
@end="onEndDrag">
|
||||
<template #item="{ element }">
|
||||
<li class="itemArea">
|
||||
<p>{{ getRawComponentKey(element) }}</p>
|
||||
<nested-draggable :data="getRawComponentContent(element).__children" />
|
||||
</li>
|
||||
</template>
|
||||
</draggable>
|
||||
</template>
|
||||
<script>
|
||||
import draggable from "vuedraggable";
|
||||
import { getRawComponentKey, getRawComponentContent } from "@/utils/common";
|
||||
|
||||
export default {
|
||||
props: {
|
||||
data: {
|
||||
required: true,
|
||||
type: Array
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
},
|
||||
methods: {
|
||||
getRawComponentKey,
|
||||
getRawComponentContent,
|
||||
onStartDrag(event) {
|
||||
event.item.classList.add("is-dragging");
|
||||
},
|
||||
onClick(event) {
|
||||
if(this.$store.state.currentEditComp){
|
||||
this.$store.state.currentEditComp.item.classList.remove("is-dragging");
|
||||
}
|
||||
|
||||
event.item.classList.add("is-dragging");
|
||||
|
||||
event.vccData = getRawComponentContent(this.data[event.oldIndex]);
|
||||
this.$store.commit('storeCurrentEditComp', event);
|
||||
},
|
||||
onEndDrag(event) {
|
||||
event.item.classList.remove("is-dragging");
|
||||
|
||||
this.$store.commit('onDragEnd');
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
draggable
|
||||
},
|
||||
name: "nested-draggable"
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.dragArea {
|
||||
min-height: 20px;
|
||||
border: 1px dashed rgb(126, 126, 128);
|
||||
border-radius: 5px;
|
||||
padding-inline-start: 30px;
|
||||
padding-right: 2px;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.itemArea {
|
||||
min-height: 20px;
|
||||
border: 1px dashed rgb(126, 126, 128);
|
||||
padding-right: 2px;
|
||||
padding-bottom: 2px;
|
||||
border-radius: 5px;
|
||||
padding-inline-start: 10px;
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
|
||||
.is-dragging {
|
||||
background-color: rgba(106, 127, 233, 0.274);
|
||||
border: 1px dashed rgb(73, 100, 241);
|
||||
-webkit-border-radius: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
24
src/libs/store.js
Normal file
24
src/libs/store.js
Normal file
@ -0,0 +1,24 @@
|
||||
import { createStore } from 'vuex'
|
||||
|
||||
const store = createStore({
|
||||
state() {
|
||||
return {
|
||||
count: 0,
|
||||
currentEditComp: null,
|
||||
renderCount: 0
|
||||
}
|
||||
},
|
||||
mutations: {
|
||||
increment(state) {
|
||||
state.count++
|
||||
},
|
||||
storeCurrentEditComp(state, newComp) {
|
||||
state.currentEditComp = newComp;
|
||||
},
|
||||
onDragEnd(state) {
|
||||
state.renderCount++;
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
globalApp.use(store);
|
10
src/main.js
10
src/main.js
@ -1,4 +1,4 @@
|
||||
import { createApp, compile } from "vue";
|
||||
import { createApp } from "vue";
|
||||
import ElementPlus from "element-plus";
|
||||
import { QuestionFilled, CirclePlus, DocumentCopy, Delete, Refresh, Minus } from "@element-plus/icons";
|
||||
|
||||
@ -19,8 +19,12 @@ function createBaseApp(renderComponent = {}) {
|
||||
return app;
|
||||
}
|
||||
|
||||
createBaseApp(APP).mount("#app");
|
||||
const globalApp = createBaseApp(APP)
|
||||
globalApp.mount("#app");
|
||||
|
||||
// 内部需要同样配置的全局Vue
|
||||
self.createBaseApp = createBaseApp;
|
||||
self.compile = compile;
|
||||
self.globalApp = globalApp; // 内部需要使用Vuex
|
||||
|
||||
|
||||
import("@/libs/store.js");
|
Loading…
x
Reference in New Issue
Block a user