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

Merge branch 'logicSaveAndInit' into vue3

This commit is contained in:
shangbin 2022-01-24 12:53:07 +08:00
commit 5d6d7dbf5a
10 changed files with 130 additions and 58 deletions

View File

@ -1,11 +1,11 @@
<template> <template>
<vcc :initCodeEntity="codeStructure" @updateCodeEntity="onCodeUpdate"></vcc> <vcc :initCodeEntity="codeInfoEntity" @updateCodeEntity="onCodeUpdate"></vcc>
</template> </template>
<script> <script>
import { defineAsyncComponent } from 'vue' import { defineAsyncComponent } from 'vue'
// VCC // VCC
const initCodeStr = '{"template":{"lc_id":"root","__children":[{"div":{"class":"container","style":"min-height: 100%; padding-bottom: 100px;","lc_id":"container","__text__":"Hello欢迎使用LCG请往此区域拖拽组件","__children":[{"el-button":{"lc-mark":"","type":"danger","lc_id":"COAAYXizyI","__children":[],"__text__":"危险按钮","@click":"onButtonClick","size":"small"}}]}}]}}' const initCodeStr = '{"template":{"lc_id":"root","__children":[{"div":{"class":"container","style":"min-height: 100%; padding-bottom: 100px;","lc_id":"container","__text__":"Hello欢迎使用LCG请往此区域拖拽组件","__children":[{"div": {"__text__": "{{showText}}", "lc_id": "text"}},{"el-button":{"lc-mark":"","type":"danger","lc_id":"COAAYXizyI","__children":[],"__text__":"{{showValue}}","@click":"hello","size":"small"}}]}}]}}'
export default { export default {
components: { components: {
@ -13,14 +13,32 @@ export default {
}, },
data() { data() {
return { return {
codeInfoEntity: {
codeStructure: JSON.parse(initCodeStr), codeStructure: JSON.parse(initCodeStr),
JSCode: `
{
data() {
return {
showValue: "开启预览模式后,点击我显示预设逻辑",
showText: "这里的值声明于预设JS代码"
};
},
methods: {
hello() {
alert("来自预设逻辑代码的问候");
},
},
}`
},
} }
}, },
mounted() { mounted() {
}, },
methods: { methods: {
onCodeUpdate(newCodeEntity) { onCodeUpdate({ codeRawVueInfo, JSCode }) {
// //
// codeRawVueInfotemplate
// JSCodeJS
} }
} }
} }

View File

@ -16,7 +16,7 @@
</el-col> </el-col>
<el-col :span="3"> <el-col :span="3">
<div style="display:inline-block;"> <div style="display:inline-block;">
<el-link type="primary" @click="onEditModeChange">{{editMode ? 'View' : 'Edit'}} <el-link :type="editMode? 'primary': 'danger'" @click="onEditModeChange">{{editMode ? 'View' : 'Edit'}}
Mode</el-link> Mode</el-link>
</div> </div>
</el-col> </el-col>

View File

@ -51,7 +51,7 @@
<code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" v-model="structureVisible" <code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" v-model="structureVisible"
@reRender="render"> @reRender="render">
</code-structure> </code-structure>
<CodeEditor v-model:codeDialogVisible="jsDialogVisible" @saveJSCode="saveJSCode"></CodeEditor> <CodeEditor v-model:codeDialogVisible="jsDialogVisible" @saveJSCode="saveJSCode" ref="codeEditor"></CodeEditor>
<VueEditor v-model:vueDialogVisible="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor> <VueEditor v-model:vueDialogVisible="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor>
</div> </div>
@ -77,7 +77,14 @@ import keymaster from "keymaster"
export default { export default {
name: "vcc", name: "vcc",
props: ['initCodeEntity'], props: {
initCodeEntity: {
type: Object,
default: () => {
return {};
}
}
},
emits: ['updateCodeEntity'], emits: ['updateCodeEntity'],
components: { components: {
RawComponents: defineAsyncComponent(() => import("@/components/RawComponents.vue")), RawComponents: defineAsyncComponent(() => import("@/components/RawComponents.vue")),
@ -99,7 +106,10 @@ export default {
iconCode: ("https://static.imonkey.xueersi.com/download/vcc-resource/icon/code-working-outline.svg"), iconCode: ("https://static.imonkey.xueersi.com/download/vcc-resource/icon/code-working-outline.svg"),
iconClear: ("https://static.imonkey.xueersi.com/download/vcc-resource/icon/trash-outline.svg"), iconClear: ("https://static.imonkey.xueersi.com/download/vcc-resource/icon/trash-outline.svg"),
editMode: true editMode: true,
codeRawVueInfo: "",
JSCode: ""
}; };
}, },
watch: { watch: {
@ -114,8 +124,12 @@ export default {
} }
}, },
initCodeEntity(newVal) { initCodeEntity(newVal) {
if (newVal) { if (newVal.JSCode) {
this.mainPanelProvider.render(newVal); this.mainPanelProvider.saveJSCodeOnly(this.convertLogicCode(newVal.JSCode));
}
if (newVal.codeStructure) {
this.mainPanelProvider.render(newVal.codeStructure);
} }
} }
}, },
@ -129,6 +143,7 @@ export default {
mounted() { mounted() {
Promise.all([import("../map/load")]) Promise.all([import("../map/load")])
.then(res => { .then(res => {
this.$emit("onLoadFinish");
this.init(); this.init();
}); });
splitInit(); splitInit();
@ -138,6 +153,19 @@ export default {
updated() { }, updated() { },
destoryed() { }, destoryed() { },
methods: { methods: {
convertLogicCode(JSCode) {
try {
const JSCodeInfo = eval(`(function(){return ${JSCode.replace(/\s+/g, "")}})()`);
// JS
this.JSCode = JSCode;
if (this.$refs.codeEditor) {
this.$refs.codeEditor.updateLogicCode(JSCode);
}
return JSCodeInfo;
} catch (e) {
console.warn(`外部逻辑代码解析出错,解析的逻辑代码为: ${JSCode}, Error: ${e}`);
}
},
initShortcut() { initShortcut() {
keymaster('⌘+z, ctrl+z', () => { keymaster('⌘+z, ctrl+z', () => {
@ -173,12 +201,23 @@ export default {
if (this.$refs.codeStructure) { if (this.$refs.codeStructure) {
this.$refs.codeStructure.updateCode(codeRawVueInfo); this.$refs.codeStructure.updateCode(codeRawVueInfo);
} }
this.$emit('updateCodeEntity', codeRawVueInfo); this.codeRawVueInfo = codeRawVueInfo;
this.notifyParent();
}).onNodeDeleted(() => { }).onNodeDeleted(() => {
this.currentEditRawInfo = null; this.currentEditRawInfo = null;
}).onSelectElement(rawInfo => { }).onSelectElement(rawInfo => {
this.currentEditRawInfo = rawInfo; this.currentEditRawInfo = rawInfo;
}).render(this.initCodeEntity ? this.initCodeEntity : this.getFakeData()); }).saveJSCodeOnly(this.convertLogicCode(this.initCodeEntity.JSCode ? this.initCodeEntity.JSCode : ''))
.render(this.initCodeEntity.codeStructure ? this.initCodeEntity.codeStructure : this.getFakeData());
},
//
notifyParent() {
this.$emit('updateCodeEntity', {
codeRawVueInfo: this.codeRawVueInfo,
JSCode: this.JSCode
});
}, },
// //
@ -247,8 +286,11 @@ export default {
this.mainPanelProvider.undo(); this.mainPanelProvider.undo();
}, },
saveJSCode(code) { saveJSCode({ JSCodeInfo: code, JSCode }) {
this.mainPanelProvider.saveJSCode(code); this.mainPanelProvider.saveJSCode(code);
// JS
this.JSCode = JSCode;
this.notifyParent();
}, },
/** /**
@ -444,6 +486,10 @@ export default {
margin: 0 2px; margin: 0 2px;
} }
:root {
--animate-duration: 1.5s;
}
.in-element { .in-element {
outline: 2px solid #4dba87 !important; outline: 2px solid #4dba87 !important;
position: relative; position: relative;

View File

@ -3,11 +3,18 @@
:center=true> :center=true>
<CodeEditor style="max-height: 65vh;" ref="codeEditor" :initCode="code" mode="text/javascript"></CodeEditor> <CodeEditor style="max-height: 65vh;" ref="codeEditor" :initCode="code" mode="text/javascript"></CodeEditor>
<div style="text-align:center;padding: 10px;"> <div style="padding: 10px; display:flex;justify-content: flex-end;align-items: center;">
<div>
<el-button type="primary" @click="onSave">确认修改</el-button> <el-button type="primary" @click="onSave">确认修改</el-button>
<div style="color: #6c6c6c; font-size:12px; margin-top:5px;">Tips: 确认修改之后将会影响最终生成的代码逻辑</div>
<div v-if="error" style="color: red; font-size:12px; margin-top:5px;">请检查语法错误{{error}}</div> <div v-if="error" style="color: red; font-size:12px; margin-top:5px;">请检查语法错误{{error}}</div>
</div> </div>
<div style="margin-left: 5px;">
<el-link href="https://vcc.sahadev.tech/doc/#/improve/logic?id=%e9%80%bb%e8%be%91%e6%a8%a1%e6%9d%bf"
target="_blank" icon="el-icon-question">帮助与说明</el-link>
<div style="color: #6c6c6c; font-size:12px; margin-top:5px;">Tips: 建议看一下使用说明</div>
</div>
</div>
</el-dialog> </el-dialog>
</template> </template>
@ -16,17 +23,10 @@
import dedent from 'dedent' import dedent from 'dedent'
import CodeEditor from './CodeEditor.vue' import CodeEditor from './CodeEditor.vue'
export default { import prettier from "prettier/standalone";
props: ['codeDialogVisible'], import babel from "prettier/parser-babel";
emits: ['saveJSCode', 'update:codeDialogVisible'],
components: {
CodeEditor
},
data() { const example = dedent`
return {
error: '',
code: dedent`
/** /**
* 以下代码中的方法会被注入到最终的代码中如果命名与源代码有相同的则会替换源代码 * 以下代码中的方法会被注入到最终的代码中如果命名与源代码有相同的则会替换源代码
* 内部集成了axios开发者可以直接通过axios发起网络请求不过接口需要允许跨域 * 内部集成了axios开发者可以直接通过axios发起网络请求不过接口需要允许跨域
@ -34,9 +34,6 @@ export default {
* axios官方文档https://www.npmjs.com/package/axios * axios官方文档https://www.npmjs.com/package/axios
*/ */
{ {
props: [],
components: {},
data() { data() {
return { return {
@ -55,25 +52,21 @@ export default {
axios.get('https://apis.sahadev.tech/exchange?url=https://www.baidu.com').then(res => console.info(res), err => console.error(err)); axios.get('https://apis.sahadev.tech/exchange?url=https://www.baidu.com').then(res => console.info(res), err => console.error(err));
} }
}, },
// start
beforeCreate() {},
created() {},
beforeMount() {},
mounted() {},
beforeUpdate() {},
updated() {},
beforeDestory() {},
destoryed() {},
// end
fillter: {},
}; };
` `
export default {
props: ['codeDialogVisible'],
emits: ['saveJSCode', 'update:codeDialogVisible'],
components: {
CodeEditor
},
data() {
return {
error: '',
code: example,
example: `${example}`
}; };
}, },
beforeCreate() { }, beforeCreate() { },
@ -84,9 +77,13 @@ export default {
updated() { }, updated() { },
destoryed() { }, destoryed() { },
methods: { methods: {
// updateLogicCode(newCode) {
request() { if (newCode) {
// const pre = "const a = ";
this.code = prettier.format(pre + newCode, {
plugins: [babel],
}).replace(pre, "");
}
}, },
handleClose() { handleClose() {
this.$emit("update:codeDialogVisible", false); this.$emit("update:codeDialogVisible", false);
@ -94,11 +91,14 @@ export default {
onSave() { onSave() {
const code = this.$refs.codeEditor.getEditorCode(); const code = this.$refs.codeEditor.getEditorCode();
// //
const temp = code.replace(/.+\*\/\s*/gs, ""); const temp = code.replace(/.+\*\/\s*/gs, "").replace(/\s+/g, "");
try { try {
// //
const JSCodeInfo = eval(`(function(){return ${temp}})()`); const JSCodeInfo = eval(`(function(){return ${temp}})()`);
this.$emit("saveJSCode", JSCodeInfo); this.$emit("saveJSCode", {
JSCodeInfo,
JSCode: temp
});
this.handleClose(); this.handleClose();
this.error = ''; this.error = '';
} catch (error) { } catch (error) {

View File

@ -33,7 +33,7 @@ export function createNewCodeGenerator() {
const kav = methodItem.split(":"); const kav = methodItem.split(":");
const key = kav[0]; const key = kav[0];
// 这里获取的是原始data数据 // 这里获取的是原始data数据
if (window.methodSourceMap[key]) { if (window.methodSourceMap && window.methodSourceMap[key]) {
return `${key}: ${window.methodSourceMap[key]}`; return `${key}: ${window.methodSourceMap[key]}`;
} else { } else {
return methodItem; return methodItem;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -129,11 +129,16 @@ export class MainPanelProvider {
} }
saveJSCode(code) { saveJSCode(code) {
this.externalJS = code; this.saveJSCodeOnly(code);
this.codeGenerator.setExternalJS(code); this.codeGenerator && this.codeGenerator.setExternalJS(code);
this.reRender(); this.reRender();
} }
saveJSCodeOnly(code) {
this.externalJS = code || {};
return this;
}
/** /**
* 生成一个新的待挂载容器 * 生成一个新的待挂载容器
*/ */
@ -273,7 +278,12 @@ export class MainPanelProvider {
enableEditMode() { enableEditMode() {
const renderControlPanel = this.getControlPanelRoot(); const renderControlPanel = this.getControlPanelRoot();
// 加一个延迟的作用是给el-table这种绘制需要时间的组件留出充足的时间否则会造成el-table渲染不到页面上 // 加一个延迟的作用是给el-table这种绘制需要时间的组件留出充足的时间否则会造成el-table渲染不到页面上
setTimeout(() => {
if (this.enableDelayTask) {
clearTimeout(this.enableDelayTask);
}
this.enableDelayTask = setTimeout(() => {
// 这种方式可以禁用原节点所有的事件 // 这种方式可以禁用原节点所有的事件
const elClone = renderControlPanel.cloneNode(true); const elClone = renderControlPanel.cloneNode(true);
renderControlPanel.parentNode.replaceChild(elClone, renderControlPanel); renderControlPanel.parentNode.replaceChild(elClone, renderControlPanel);