1
0
mirror of https://github.com/sahadev/vue-component-creater-ui.git synced 2025-06-07 21:54:05 +08:00

update: 集成好vuedraggable

This commit is contained in:
shangbin 2021-12-08 18:59:04 +08:00
parent 1c61f4b83a
commit b870e28608
9 changed files with 766 additions and 92 deletions

27
package-lock.json generated
View File

@ -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": { "@vue/eslint-config-airbnb": {
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://r.cnpmjs.org/@vue/eslint-config-airbnb/download/@vue/eslint-config-airbnb-5.3.0.tgz", "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": { "source-list-map": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://r.cnpmjs.org/source-list-map/download/source-list-map-2.0.1.tgz", "resolved": "https://r.cnpmjs.org/source-list-map/download/source-list-map-2.0.1.tgz",
@ -13347,10 +13357,21 @@
"integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=", "integrity": "sha1-HuO8mhbsv1EYvjNLsV+cRvgvWCU=",
"dev": true "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": { "vuex": {
"version": "3.6.2", "version": "4.0.2",
"resolved": "https://r.cnpmjs.org/vuex/download/vuex-3.6.2.tgz", "resolved": "https://rg.cnpmjs.org/vuex/download/vuex-4.0.2.tgz",
"integrity": "sha1-I2vAhqhww655lG8QfxbeWdWJXnE=" "integrity": "sha1-+Jbb1b8qDpY/AMZ+m2EN50nMrMk=",
"requires": {
"@vue/devtools-api": "^6.0.0-beta.11"
}
}, },
"watchpack": { "watchpack": {
"version": "1.7.5", "version": "1.7.5",

View File

@ -62,7 +62,8 @@
"vue": "^3.2.22", "vue": "^3.2.22",
"vue-nestable": "^2.6.0", "vue-nestable": "^2.6.0",
"vue-router": "^3.4.9", "vue-router": "^3.4.9",
"vuex": "^3.1.2" "vuedraggable": "^4.1.0",
"vuex": "^4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@babel/generator": "^7.11.6", "@babel/generator": "^7.11.6",

View File

@ -16,8 +16,7 @@
</div> </div>
</div> </div>
<attribute-input :enableRemoveButton="true" class="attribute" @save="onSaveAttr" @remove="onRemove" <attribute-input :enableRemoveButton="true" class="attribute" @save="onSaveAttr" @remove="onRemove"
ref="attributeInput" shortcutInitMode="hand" @codeRefresh="generateVueCode" ref="attributeInput" shortcutInitMode="hand" :__rawVueInfo__="currentEditRawInfo">
:__rawVueInfo__="currentEditRawInfo">
</attribute-input> </attribute-input>
</div> </div>
</div> </div>
@ -50,7 +49,7 @@
<lc-code :rawCode="code" v-model:codeDialogVisible="codeDialogVisible"> <lc-code :rawCode="code" v-model:codeDialogVisible="codeDialogVisible">
</lc-code> </lc-code>
<code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" v-model="structureVisible" <code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" v-model="structureVisible"
@codeRefresh="generateVueCode" @onLevelChange="onLevelChange"> @reRender="render">
</code-structure> </code-structure>
<CodeEditor v-model:codeDialogVisible="jsDialogVisible" @saveJSCode="saveJSCode"></CodeEditor> <CodeEditor v-model:codeDialogVisible="jsDialogVisible" @saveJSCode="saveJSCode"></CodeEditor>
<VueEditor v-model:vueDialogVisible="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor> <VueEditor v-model:vueDialogVisible="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor>
@ -220,11 +219,6 @@ export default {
this.mainPanelProvider.saveAttribute(resultList, lc_id); this.mainPanelProvider.saveAttribute(resultList, lc_id);
}, },
onLevelChange(removeID, movePath) {
this.mainPanelProvider.onLevelChange(removeID, movePath);
},
generateVueCode() { },
onRemove({ lc_id }) { onRemove({ lc_id }) {
this.mainPanelProvider.remove(lc_id); this.mainPanelProvider.remove(lc_id);
}, },
@ -240,10 +234,20 @@ export default {
this.mainPanelProvider.saveJSCode(code); this.mainPanelProvider.saveJSCode(code);
}, },
/**
* 二级编辑解析
*/
codeParseSucess(vueCodeEntity) { codeParseSucess(vueCodeEntity) {
this.mainPanelProvider.render(vueCodeEntity); this.mainPanelProvider.render(vueCodeEntity);
}, },
/**
* 渲染指定结构
*/
render(codeEntity) {
this.mainPanelProvider.render(codeEntity);
},
help() { help() {
window.open('/doc') window.open('/doc')
} }

View File

@ -1,7 +1,7 @@
<template> <template>
<el-card class="attribute-container"> <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" <el-switch v-model="editMode" active-text="自由编辑" inactive-text="约束编辑" active-color="#13ce66"
inactive-color="#13ce66"> inactive-color="#13ce66">
</el-switch> </el-switch>
@ -197,7 +197,7 @@ export default {
}, },
copyBro() { copyBro() {
copyBroCode(this.__rawVueInfo__); copyBroCode(this.__rawVueInfo__);
this.$emit('codeRefresh'); this.$store.commit('onDragEnd');
}, },
onShow() { onShow() {
// //

View File

@ -2,7 +2,7 @@
<el-drawer v-model="drawer" :with-header="false" size="70%" direction="btt"> <el-drawer v-model="drawer" :with-header="false" size="70%" direction="btt">
<div class="container"> <div class="container">
<div style="text-algin: center;">组件结构检视图 <div style="text-align: center;">组件结构检视图
<br> <br>
<span style="font-size:12px;">Components <span style="font-size:12px;">Components
Structure</span> Structure</span>
@ -12,26 +12,13 @@
<el-col :span="16" style="height: 100%;"> <el-col :span="16" style="height: 100%;">
<div style="overflow: scroll;height:100%; margin: 0 20px;padding: 10px;"> <div style="overflow: scroll;height:100%; margin: 0 20px;padding: 10px;">
<!-- <vue-nestable v-model="treeData" @change="onLevelChange"> <nested-draggable :data="treeData" />
<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> -->
</div> </div>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<attribute-input ref="attributeInput" :enableRemoveButton="true" v-if="currentEditRawInfo && drawer" <attribute-input ref="attributeInput" :enableRemoveButton="true" v-if="currentEditRawInfo" @save="onSaveAttr"
@save="onSaveAttr" shortcutInitMode="auto" @remove="onRemove" @codeRefresh="codeRefresh" shortcutInitMode="auto" @remove="onRemove" :__rawVueInfo__="currentEditRawInfo">
:__rawVueInfo__="currentEditRawInfo">
</attribute-input> </attribute-input>
</el-col> </el-col>
</el-row> </el-row>
@ -41,81 +28,33 @@
</template> </template>
<script> <script>
import "./halower-tree.min.css";
import "@/assets/nestable.css"
import { isObject, getRawComponentKey, getRawComponentContent } from "@/utils/common"; import { isObject, getRawComponentKey, getRawComponentContent } from "@/utils/common";
// import { VueNestable, VueNestableHandle } from 'vue-nestable'; import nestedDraggable from './nested.vue'
import { defineAsyncComponent } from 'vue'
export default { export default {
props: ['visible'], props: ['visible'],
emits: ['codeRefresh', 'onLevelChange', 'remove', 'save', 'update:visible'], emits: ['onLevelChange', 'remove', 'save', 'update:visible', 'reRender'],
components: { components: {
AttributeInput: resolve => { require(["./AttributeInput"], resolve) }, AttributeInput: defineAsyncComponent(() => import("@/components/AttributeInput.vue")),
// VueNestable, nestedDraggable
// VueNestableHandle
}, },
data() { data() {
return { return {
// //
treeData: [], treeData: [],
currentEditRawInfo: null
}; };
}, },
beforeCreate() { }, beforeCreate() { },
created() { }, created() { },
beforeMount() { }, beforeMount() { },
mounted() { }, mounted() {
},
beforeUpdate() { }, beforeUpdate() { },
updated() { }, updated() { },
destoryed() { }, destoryed() { },
methods: { 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) { onNodeClick(nodeInfo) {
this.currentEditRawInfo = nodeInfo.rawInfo; this.currentEditRawInfo = nodeInfo.rawInfo;
@ -131,12 +70,17 @@ export default {
}, },
updateCode(codeRawInfo) { updateCode(codeRawInfo) {
this.treeData = [this.convertStructure(codeRawInfo)]; this._codeRawInfo = codeRawInfo;
const content = getRawComponentContent(codeRawInfo);
const children = content.__children;
this.treeData = children;
}, },
}, },
watch: { watch: {
canInitShortcut(newValue) { renderCount(){
// vuedraggable v-model
this.$emit('reRender', this._codeRawInfo);
} }
}, },
computed: { computed: {
@ -148,8 +92,21 @@ export default {
this.$emit('update:visible', false); this.$emit('update:visible', false);
} }
}, },
renderCount(){
return this.$store.state.renderCount;
},
canInitShortcut() { canInitShortcut() {
return this.currentEditRawInfo !== null && this.drawer; 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: {}, fillter: {},

File diff suppressed because one or more lines are too long

89
src/components/nested.vue Normal file
View 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
View 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);

View File

@ -1,4 +1,4 @@
import { createApp, compile } from "vue"; import { createApp } from "vue";
import ElementPlus from "element-plus"; import ElementPlus from "element-plus";
import { QuestionFilled, CirclePlus, DocumentCopy, Delete, Refresh, Minus } from "@element-plus/icons"; import { QuestionFilled, CirclePlus, DocumentCopy, Delete, Refresh, Minus } from "@element-plus/icons";
@ -19,8 +19,12 @@ function createBaseApp(renderComponent = {}) {
return app; return app;
} }
createBaseApp(APP).mount("#app"); const globalApp = createBaseApp(APP)
globalApp.mount("#app");
// 内部需要同样配置的全局Vue // 内部需要同样配置的全局Vue
self.createBaseApp = createBaseApp; self.createBaseApp = createBaseApp;
self.compile = compile; self.globalApp = globalApp; // 内部需要使用Vuex
import("@/libs/store.js");