mirror of
https://github.com/sahadev/vue-component-creater-ui.git
synced 2025-06-06 13:04:05 +08:00
update: 完全升级Vue3过程中的记录
This commit is contained in:
parent
23bb007b5b
commit
d6f575c503
13
index.html
Normal file
13
index.html
Normal file
@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite App</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
</html>
|
999
package-lock.json
generated
999
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
20
package.json
20
package.json
@ -9,6 +9,7 @@
|
||||
],
|
||||
"main": "./dist/vcc.umd.min.js",
|
||||
"scripts": {
|
||||
"dev": "vite --port 8008",
|
||||
"serve": "vue-cli-service serve --open --port 8008",
|
||||
"build:release": "vue-cli-service build",
|
||||
"build": "vue-cli-service build --report --target lib --name vcc './src/components-v2/VCC.vue' && node ./src/script/distClear.js",
|
||||
@ -22,36 +23,41 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.11.5",
|
||||
"ant-design-vue": "^1.7.2",
|
||||
"@originjs/vite-plugin-require-context": "^1.0.9",
|
||||
"@vitejs/plugin-vue": "^1.10.0",
|
||||
"@vue/compat": "^3.2.22",
|
||||
"@vue/compiler-sfc": "^3.2.22",
|
||||
"axios": "^0.21.4",
|
||||
"copy-to-clipboard": "^3.3.1",
|
||||
"core-js": "^3.6.4",
|
||||
"crypto-random-string": "^3.3.0",
|
||||
"css": "^3.0.0",
|
||||
"element-ui": "^2.15.6",
|
||||
"element-plus": "^1.2.0-beta.3",
|
||||
"escodegen": "^2.0.0",
|
||||
"espree": "^7.3.0",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"fast-xml-parser": "^3.17.4",
|
||||
"file-saver": "^2.0.2",
|
||||
"fs-extra": "^9.0.1",
|
||||
"get-own-enumerable-property-symbols": "^3.0.2",
|
||||
"glob": "^7.1.6",
|
||||
"html2canvas": "^1.0.0-rc.7",
|
||||
"is-absolute-url": "^3.0.3",
|
||||
"keymaster": "^1.6.2",
|
||||
"lodash": "^4.17.20",
|
||||
"lodash-es": "^4.17.21",
|
||||
"md5": "^2.3.0",
|
||||
"modern-normalize": "^1.0.0",
|
||||
"object-inspect": "^1.11.0",
|
||||
"parse-package-name": "^0.1.0",
|
||||
"prettier": "^2.4.0",
|
||||
"prismjs": "^1.20.0",
|
||||
"query-string": "^6.13.7",
|
||||
"register-service-worker": "^1.6.2",
|
||||
"split.js": "^1.6.2",
|
||||
"stringify-object": "^3.3.0",
|
||||
"vant": "^2.10.7",
|
||||
"view-design": "^4.3.2",
|
||||
"vue": "^2.6.14",
|
||||
"vite": "^2.6.14",
|
||||
"vue": "^3.2.22",
|
||||
"vue-codemirror": "^4.0.6",
|
||||
"vue-nestable": "^2.6.0",
|
||||
"vue-router": "^3.4.9",
|
||||
@ -72,7 +78,9 @@
|
||||
"lint-staged": "^9.5.0",
|
||||
"sass": "^1.25.0",
|
||||
"sass-loader": "^8.0.2",
|
||||
"vue-template-compiler": "^2.6.14"
|
||||
"vue-template-compiler": "^2.6.14",
|
||||
"is-obj": "^3.0.0",
|
||||
"is-regexp": "^3.0.0"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
@ -3,12 +3,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
// 以这样一段结构初始化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"}}]}}]}}'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
vcc: () => import('./components-v2/VCC.vue'),
|
||||
vcc: defineAsyncComponent(() => import('./components-v2/VCC.vue')),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
@ -16,7 +16,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<attribute-input :enableRemoveButton="true" class="attribute" @save="onSaveAttr" @remove="onRemove"
|
||||
ref="attributeInput" shortcutInitMode="hand" @codeRefresh="generateVueCode" style="display:none;"
|
||||
ref="attributeInput" shortcutInitMode="hand" @codeRefresh="generateVueCode"
|
||||
:__rawVueInfo__="currentEditRawInfo">
|
||||
</attribute-input>
|
||||
</div>
|
||||
@ -41,19 +41,21 @@
|
||||
<el-tooltip effect="dark" content="清空当前编辑内容" placement="top-start">
|
||||
<el-popconfirm confirmButtonText="确认" cancelButtonText="点错了" icon="el-icon-info" iconColor="red"
|
||||
title="点我将清空所有编辑的内容, 确认吗?" @onConfirm="clear">
|
||||
<img slot="reference" class="round-icon" :src="iconClear" alt="">
|
||||
<template #reference>
|
||||
<img class="round-icon" :src="iconClear" alt="">
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<lc-code :rawCode="code" :codeDialogVisible.sync="codeDialogVisible">
|
||||
<lc-code :rawCode="code" v-model:codeDialogVisible="codeDialogVisible">
|
||||
</lc-code>
|
||||
<code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" :visible.sync="structureVisible"
|
||||
<code-structure @save="onSaveAttr" @remove="onRemove" ref="codeStructure" v-model="structureVisible"
|
||||
@codeRefresh="generateVueCode" @onLevelChange="onLevelChange">
|
||||
</code-structure>
|
||||
<CodeEditor :codeDialogVisible.sync="jsDialogVisible" @saveJSCode="saveJSCode"></CodeEditor>
|
||||
<VueEditor :vueDialogVisible.sync="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor>
|
||||
<CodeEditor v-model:codeDialogVisible="jsDialogVisible" @saveJSCode="saveJSCode"></CodeEditor>
|
||||
<VueEditor v-model:vueDialogVisible="vueDialogVisible" @codeParseSucess="codeParseSucess"></VueEditor>
|
||||
</div>
|
||||
|
||||
<!-- 辅助定位线 -->
|
||||
@ -64,24 +66,24 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import { splitInit } from "../libs/split-init";
|
||||
// 这个文件不可以进行懒加载,它会导致运行时不可点击的行为,具体原因未知
|
||||
// // 这个文件不可以进行懒加载,它会导致运行时不可点击的行为,具体原因未知
|
||||
import { MainPanelProvider } from "../libs/main-panel";
|
||||
import { initContainerForLine } from "@/utils/lineHelper";
|
||||
|
||||
const keymaster = require('keymaster');
|
||||
import keymaster from "keymaster"
|
||||
|
||||
export default {
|
||||
name: "vcc",
|
||||
props: ['initCodeEntity'],
|
||||
components: {
|
||||
RawComponents: () => import("../components/RawComponents"),
|
||||
ToolsBar: () => import("./ToolsBar"),
|
||||
AttributeInput: () => import("../components/AttributeInput"),
|
||||
CodeStructure: () => import("../components/CodeStructure"),
|
||||
"lc-code": () => import("../components/Code"),
|
||||
CodeEditor: () => import('../components/JSCodeEditorDialog.vue'),
|
||||
VueEditor: () => import('../components/VueCodeParseDialog.vue')
|
||||
RawComponents: defineAsyncComponent(() => import("@/components/RawComponents.vue")),
|
||||
ToolsBar: defineAsyncComponent(() => import("./ToolsBar")),
|
||||
AttributeInput: defineAsyncComponent(() => import("../components/AttributeInput")),
|
||||
CodeStructure: defineAsyncComponent(() => import("../components/CodeStructure")),
|
||||
"lc-code": defineAsyncComponent(() => import("../components/Code")),
|
||||
CodeEditor: defineAsyncComponent(() => import('../components/JSCodeEditorDialog.vue')),
|
||||
VueEditor: defineAsyncComponent(() => import('../components/VueCodeParseDialog.vue'))
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@ -101,7 +103,7 @@ export default {
|
||||
currentEditRawInfo(newValue) {
|
||||
const attributeContainter = document.querySelector(".attribute");
|
||||
if (newValue) {
|
||||
attributeContainter.style = "right:10px;";
|
||||
attributeContainter.style = "right:10px; display:block;";
|
||||
this.$refs['attributeInput'].onShow();
|
||||
} else {
|
||||
attributeContainter.style = "right: calc(-300px - 20px); display:none;";
|
||||
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<el-card class="attribute-container">
|
||||
|
||||
<center>
|
||||
<div style="text-algin: center;">
|
||||
<el-switch v-model="editMode" active-text="自由编辑" inactive-text="约束编辑" active-color="#13ce66"
|
||||
inactive-color="#13ce66">
|
||||
</el-switch>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<div name="1" v-show="!editMode">
|
||||
@ -44,8 +44,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<center style="margin-top: 10px;">
|
||||
<el-tooltip class="item" effect="dark" content="新增属性 ctrl+a" placement="bottom">
|
||||
<div style="margin-top: 10px;text-align:center;">
|
||||
<!-- <el-tooltip class="item" effect="dark" content="新增属性 ctrl+a" placement="bottom">
|
||||
<el-button type="primary" class="center" @click="createNew" icon="el-icon-circle-plus-outline" circle>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
@ -60,12 +60,11 @@
|
||||
<el-button v-if="enableBroButton" type="primary" class="center" icon="el-icon-copy-document" @click="copyBro"
|
||||
circle>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
|
||||
<center>
|
||||
</el-tooltip> -->
|
||||
<div style="text-algin: center;">
|
||||
<span class="shortcut-tip">支持快捷键操作</span>
|
||||
</center>
|
||||
</center>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
</template>
|
||||
@ -73,7 +72,7 @@
|
||||
<script>
|
||||
import { getRawComponentKey, getRawComponentContent } from "@/utils/common";
|
||||
import { brotherEleEnum, copyBroCode } from "@/libs/bro-ele-config";
|
||||
const keymaster = require('keymaster');
|
||||
import keymaster from "keymaster"
|
||||
|
||||
export default {
|
||||
props: ['__rawVueInfo__', 'enableRemoveButton', 'shortcutInitMode'],// __rawVueInfo__为当前编辑的原始代码对象, shortcutInitMode快捷键的初始化方式
|
||||
@ -117,8 +116,6 @@ export default {
|
||||
|
||||
initShortcut() {
|
||||
console.log(`init by mode: ${this.shortcutInitMode}`)
|
||||
|
||||
|
||||
keymaster('⌘+a, ctrl+a', () => {
|
||||
if (this.enable) {
|
||||
this.createNew();
|
||||
|
@ -1,22 +1,21 @@
|
||||
<template>
|
||||
<el-dialog title="代码预览" :visible.sync="codeDialogVisible" width="70%" top="10vh" :before-close="handleClose"
|
||||
:center=true>
|
||||
<el-dialog title="代码预览" v-model="codeDialogVisible" width="70%" top="10vh" :before-close="handleClose" :center=true>
|
||||
<pre style="max-height: 60vh;">
|
||||
<code v-html="formatCode"></code>
|
||||
</pre>
|
||||
<div>
|
||||
<center style="color: #666; font-size: 12px;">使用代码前请确认相应的组件库已集成至项目</center>
|
||||
<div style="color: #666; font-size: 12px;text-align">使用代码前请确认相应的组件库已集成至项目</div>
|
||||
</div>
|
||||
<span slot="footer">
|
||||
|
||||
<el-tooltip effect="dark" content="拷贝" placement="left">
|
||||
<img class="round-icon" :src="iconCopy" alt="" @click="copyCheck">
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="下载" placement="right">
|
||||
<img class="round-icon" :src="iconDownload" alt="" @click="download">
|
||||
</el-tooltip>
|
||||
|
||||
</span>
|
||||
<template v-slot:footer>
|
||||
<span>
|
||||
<el-tooltip effect="dark" content="拷贝" placement="left">
|
||||
<img class="round-icon" :src="iconCopy" alt="" @click="copyCheck">
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="下载" placement="right">
|
||||
<img class="round-icon" :src="iconDownload" alt="" @click="download">
|
||||
</el-tooltip>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
</template>
|
||||
|
@ -50,12 +50,12 @@ import 'codemirror/addon/fold/indent-fold.js'
|
||||
import 'codemirror/addon/fold/markdown-fold.js'
|
||||
import 'codemirror/addon/fold/xml-fold.js'
|
||||
|
||||
require(['axios'], axios => {
|
||||
self.axios = axios.create({
|
||||
baseURL: '',
|
||||
timeout: 1000,
|
||||
});
|
||||
});
|
||||
// require(['axios'], axios => {
|
||||
// self.axios = axios.create({
|
||||
// baseURL: '',
|
||||
// timeout: 1000,
|
||||
// });
|
||||
// });
|
||||
|
||||
export default {
|
||||
props: ['initCode', 'mode'],
|
||||
|
@ -1,19 +1,19 @@
|
||||
<template>
|
||||
<el-drawer :visible.sync="drawer" :with-header="false" size="70%" direction="btt">
|
||||
<el-drawer v-model="drawer" :with-header="false" size="70%" direction="btt">
|
||||
<div class="container">
|
||||
|
||||
<center>组件结构检视图
|
||||
<div style="text-algin: center;">组件结构检视图
|
||||
<br>
|
||||
<span style="font-size:12px;">Components
|
||||
Structure</span>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
<el-row :gutter="20" style="height:0px;flex-grow:1;">
|
||||
<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 slot-scope="{ item }">
|
||||
<template v-slot="{ item }">
|
||||
<vue-nestable-handle :item="item">
|
||||
<i class="el-icon-rank icon-s"></i>
|
||||
</vue-nestable-handle>
|
||||
@ -21,9 +21,9 @@
|
||||
<span @click="onNodeClick(item)">{{ item.text }}</span>
|
||||
</template>
|
||||
|
||||
<div slot="placeholder">
|
||||
<b>The editor is empty.</b>
|
||||
</div>
|
||||
<template v-slot:placeholder>
|
||||
<div><b>The editor is empty.</b></div>
|
||||
</template>
|
||||
</vue-nestable>
|
||||
|
||||
</div>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<el-dialog title="JS逻辑编辑" :visible.sync="codeDialogVisible" width="70%" top="10vh" :before-close="handleClose"
|
||||
<el-dialog title="JS逻辑编辑" v-model="codeDialogVisible" width="70%" top="10vh" :before-close="handleClose"
|
||||
: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;">
|
||||
<el-button type="primary" @click="onSave">确认修改</el-button>
|
||||
@ -14,12 +14,12 @@
|
||||
|
||||
<script>
|
||||
import dedent from 'dedent'
|
||||
import CodeEditor from './CodeEditor.vue'
|
||||
// import CodeEditor from './CodeEditor.vue'
|
||||
|
||||
export default {
|
||||
props: ['codeDialogVisible'],
|
||||
components: {
|
||||
CodeEditor
|
||||
// CodeEditor
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -88,7 +88,7 @@ export default {
|
||||
// 网络请求,可选
|
||||
},
|
||||
handleClose() {
|
||||
this.$emit("update:codeDialogVisible", false);
|
||||
// this.$emit("update:codeDialogVisible", false);
|
||||
},
|
||||
onSave() {
|
||||
const code = this.$refs.codeEditor.getEditorCode();
|
||||
|
@ -34,11 +34,11 @@
|
||||
</nav>
|
||||
|
||||
<nav v-if="currentSelectBrand.titleArray && currentSelectBrand.titleArray.length > 0">
|
||||
<center style="margin-bottom:10px;">
|
||||
<div style="margin-bottom:10px;text-align:center;">
|
||||
<div style="padding:5px;font-size:12px;color:grey;">快速查找需要的</div>
|
||||
<el-autocomplete class="inline-input" v-model="componentSearch" :fetch-suggestions="querySearch" size="mini"
|
||||
placeholder="请输入..." @select="handleSelect"></el-autocomplete>
|
||||
</center>
|
||||
</div>
|
||||
<div class="dismiss-scroll">
|
||||
<div v-for="(item, index) in currentSelectBrand.titleArray" :key="item.title" class="second-nav"
|
||||
:class="{'active':currentSelectBrand.selectIndex === index}" @click="selectSubnav(currentSelectBrand, index)">
|
||||
@ -60,8 +60,8 @@
|
||||
// import vant from "../rawComponents/vant";
|
||||
// import iview from "../rawComponents/iview";
|
||||
// import quasar from "../rawComponents/quasar";
|
||||
import raw from "../rawComponents/raw";
|
||||
import ele from "../rawComponents/element";
|
||||
import raw from "../rawComponents/raw/index.vue";
|
||||
import ele from "../rawComponents/element/index.vue";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -94,7 +94,7 @@ export default {
|
||||
enable: false
|
||||
},],
|
||||
|
||||
currentIndex: 1
|
||||
currentIndex: 0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-dialog title="Vue二次编辑" :visible.sync="vueDialogVisible" width="70%" top="10vh" :before-close="handleClose"
|
||||
<el-dialog title="Vue二次编辑" v-model="vueDialogVisible" width="70%" top="10vh" :before-close="handleClose"
|
||||
:center=true>
|
||||
<CodeEditor style="max-height: 65vh;" ref="codeEditor" :initCode="code" mode="text/html"></CodeEditor>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//该文件会遍历Object,获取关键的class,事件,data, 最终拼装为一个完整的SFC文件
|
||||
|
||||
import stringifyObject from 'stringify-object';
|
||||
import _ from 'lodash';
|
||||
import stringifyObject from '@/libs/stringify-object'
|
||||
import merge from 'lodash-es/merge';
|
||||
import cloneDeep from 'lodash-es/cloneDeep';
|
||||
import prettier from 'prettier/standalone.js';
|
||||
import parserBabel from 'prettier/parser-babel.js';
|
||||
|
||||
@ -422,14 +422,6 @@ const scriptTemplate = `{
|
||||
fillter: {},
|
||||
};`;
|
||||
|
||||
const { merge, cloneDeep } = _;
|
||||
|
||||
const rawAdd = Set.prototype.add;
|
||||
Set.prototype.add = function (value) {
|
||||
if (typeof value === "string" && checkKeyword(value))
|
||||
rawAdd.apply(this, arguments);
|
||||
};
|
||||
|
||||
function checkKeyword(value) {
|
||||
return value != "true" && value != "false";
|
||||
}
|
||||
@ -499,7 +491,7 @@ function findVarFormExpression(expression) {
|
||||
}
|
||||
}
|
||||
|
||||
class CodeGenerator {
|
||||
export class CodeGenerator {
|
||||
|
||||
constructor(options = {}) {
|
||||
this.options = options;
|
||||
@ -629,23 +621,23 @@ class CodeGenerator {
|
||||
classes.forEach((item) => {
|
||||
// 处理多个空字符串
|
||||
if (!item) return;
|
||||
this.classSet.add(item);
|
||||
this.classSet.addeee(item);
|
||||
});
|
||||
} else if (/^v-on/g.test(key) || /^@/g.test(key)) {
|
||||
// 匹配@,v-on
|
||||
if (getVarName(value)) {
|
||||
this.methodSet.add(value);
|
||||
this.methodSet.addeee(value);
|
||||
}
|
||||
} else if (/^v-/g.test(key) || /^:+/g.test(key)) {
|
||||
// 优先使Method消费,因为有的:也是method
|
||||
if (this.options.checkIsMethodDirectives && this.options.checkIsMethodDirectives(key)) {
|
||||
value = getVarName(value);
|
||||
value && this.methodSet.add(value);
|
||||
value && this.methodSet.addeee(value);
|
||||
} else
|
||||
// 业务侧可能会全部消费/^:+/g.test(key)
|
||||
if (this.options.checkIsDataDirectives && this.options.checkIsDataDirectives(key)) {
|
||||
value = getVarName(value);
|
||||
value && this.dataSet.add(value);
|
||||
value && this.dataSet.addeee(value);
|
||||
} else {
|
||||
this.options.unSupportedKey && this.options.unSupportedKey(key, value);
|
||||
}
|
||||
@ -655,7 +647,7 @@ class CodeGenerator {
|
||||
// 用于匹配v-text {{}}
|
||||
const temp = findVarFormExpression(value);
|
||||
temp.forEach((element) => {
|
||||
this.dataSet.add(element);
|
||||
this.dataSet.addeee(element);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@ -693,4 +685,15 @@ class CodeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
export { CodeGenerator };
|
||||
|
||||
const rawAdd = Set.prototype.add;
|
||||
try {
|
||||
//为何不能给add赋值?且没有报错?
|
||||
Set.prototype.addeee = function (value) {
|
||||
if (typeof value === "string" && checkKeyword(value))
|
||||
rawAdd.apply(this, arguments);
|
||||
};
|
||||
// 经验证可以赋值,而代码会直接跳转至最后一行
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
//该文件用于解析HTML,输出为Object对象
|
||||
|
||||
const htmlparser2 = require("htmlparser2");
|
||||
import htmlparser2 from "htmlparser2"
|
||||
|
||||
function getNodeContent(node) {
|
||||
return node[Object.keys(node)[0]];
|
||||
|
@ -1,8 +1,7 @@
|
||||
// 代码生成对象工厂,每次初始化需要获取一个新的实例,所以工厂方法模式最为适用
|
||||
import { CodeGenerator } from "./bundle-core-esm";
|
||||
import { checkIsDataDirectives, checkIsMethodDirectives } from '@/libs/directiveCheck';
|
||||
|
||||
const stringifyObject = require("stringify-object");
|
||||
import stringifyObject from '@/libs/stringify-object'
|
||||
|
||||
export function createNewCodeGenerator() {
|
||||
return new CodeGenerator({
|
||||
|
@ -9,8 +9,8 @@ import { parseComponent } from 'vue-template-compiler/browser';
|
||||
import { merge, insertPresetAttribute, getSplitTag, replaceRowID, updateLinkTree, findCodeElemNode, findRawVueInfo, removeAllID } from "@/utils/forCode";
|
||||
import { getRawComponentContent, getRawComponentKey, isObject } from '@/utils/common';
|
||||
import { createNewCodeGenerator } from "@/libs/code-generator-factory";
|
||||
const EventEmitter = require('eventemitter3');
|
||||
const { cloneDeep } = require('lodash');
|
||||
import EventEmitter from 'eventemitter3'
|
||||
import { cloneDeep } from 'lodash-es';
|
||||
|
||||
/**
|
||||
* 主控制面板辅助类,用于代码的生成与绘制
|
||||
@ -64,17 +64,16 @@ export class MainPanelProvider {
|
||||
let newScript = script.content.replace(/\s*export default\s*/, "")
|
||||
|
||||
const componentOptions = (new Function(`return ${newScript}`))();
|
||||
|
||||
const res = Vue.compile(template.content);
|
||||
const render = compile(template.content);
|
||||
|
||||
componentOptions.render = function () {
|
||||
const rootVNode = res.render.apply(this, arguments);
|
||||
const rootVNode = render.apply(this, arguments);
|
||||
return rootVNode;
|
||||
};
|
||||
componentOptions.staticRenderFns = res.staticRenderFns;
|
||||
// componentOptions.staticRenderFns = render.staticRenderFns;
|
||||
|
||||
// 渲染当前代码
|
||||
new Vue(componentOptions).$mount(readyForMoutedElement);
|
||||
createBaseApp(componentOptions).mount(readyForMoutedElement);
|
||||
|
||||
// 拍平数据结构
|
||||
this.editMode && this.flatDataStructure(rawDataStructure);
|
||||
|
139
src/libs/stringify-object.js
Normal file
139
src/libs/stringify-object.js
Normal file
@ -0,0 +1,139 @@
|
||||
import isRegexp from 'is-regexp';
|
||||
import isObject from 'is-obj';
|
||||
|
||||
const getOwnEnumPropSymbols = (object) => Object
|
||||
.getOwnPropertySymbols(object)
|
||||
.filter((keySymbol) => Object.prototype.propertyIsEnumerable.call(object, keySymbol));
|
||||
|
||||
export default function stringifyObject(input, options, pad) {
|
||||
const seen = [];
|
||||
|
||||
return (function stringify(input, options = {}, pad = '') {
|
||||
const indent = options.indent || '\t';
|
||||
|
||||
let tokens;
|
||||
if (options.inlineCharacterLimit === undefined) {
|
||||
tokens = {
|
||||
newline: '\n',
|
||||
newlineOrSpace: '\n',
|
||||
pad,
|
||||
indent: pad + indent,
|
||||
};
|
||||
} else {
|
||||
tokens = {
|
||||
newline: '@@__STRINGIFY_OBJECT_NEW_LINE__@@',
|
||||
newlineOrSpace: '@@__STRINGIFY_OBJECT_NEW_LINE_OR_SPACE__@@',
|
||||
pad: '@@__STRINGIFY_OBJECT_PAD__@@',
|
||||
indent: '@@__STRINGIFY_OBJECT_INDENT__@@',
|
||||
};
|
||||
}
|
||||
|
||||
const expandWhiteSpace = string => {
|
||||
if (options.inlineCharacterLimit === undefined) {
|
||||
return string;
|
||||
}
|
||||
|
||||
const oneLined = string
|
||||
.replace(new RegExp(tokens.newline, 'g'), '')
|
||||
.replace(new RegExp(tokens.newlineOrSpace, 'g'), ' ')
|
||||
.replace(new RegExp(tokens.pad + '|' + tokens.indent, 'g'), '');
|
||||
|
||||
if (oneLined.length <= options.inlineCharacterLimit) {
|
||||
return oneLined;
|
||||
}
|
||||
|
||||
return string
|
||||
.replace(new RegExp(tokens.newline + '|' + tokens.newlineOrSpace, 'g'), '\n')
|
||||
.replace(new RegExp(tokens.pad, 'g'), pad)
|
||||
.replace(new RegExp(tokens.indent, 'g'), pad + indent);
|
||||
};
|
||||
|
||||
if (seen.includes(input)) {
|
||||
return '"[Circular]"';
|
||||
}
|
||||
|
||||
if (
|
||||
input === null
|
||||
|| input === undefined
|
||||
|| typeof input === 'number'
|
||||
|| typeof input === 'boolean'
|
||||
|| typeof input === 'function'
|
||||
|| typeof input === 'symbol'
|
||||
|| isRegexp(input)
|
||||
) {
|
||||
return String(input);
|
||||
}
|
||||
|
||||
if (input instanceof Date) {
|
||||
return `new Date('${input.toISOString()}')`;
|
||||
}
|
||||
|
||||
if (Array.isArray(input)) {
|
||||
if (input.length === 0) {
|
||||
return '[]';
|
||||
}
|
||||
|
||||
seen.push(input);
|
||||
|
||||
const returnValue = '[' + tokens.newline + input.map((element, i) => {
|
||||
const eol = input.length - 1 === i ? tokens.newline : ',' + tokens.newlineOrSpace;
|
||||
|
||||
let value = stringify(element, options, pad + indent);
|
||||
if (options.transform) {
|
||||
value = options.transform(input, i, value);
|
||||
}
|
||||
|
||||
return tokens.indent + value + eol;
|
||||
}).join('') + tokens.pad + ']';
|
||||
|
||||
seen.pop();
|
||||
|
||||
return expandWhiteSpace(returnValue);
|
||||
}
|
||||
|
||||
if (isObject(input)) {
|
||||
let objectKeys = [
|
||||
...Object.keys(input),
|
||||
...getOwnEnumPropSymbols(input),
|
||||
];
|
||||
|
||||
if (options.filter) {
|
||||
objectKeys = objectKeys.filter(element => options.filter(input, element));
|
||||
}
|
||||
|
||||
if (objectKeys.length === 0) {
|
||||
return '{}';
|
||||
}
|
||||
|
||||
seen.push(input);
|
||||
|
||||
const returnValue = '{' + tokens.newline + objectKeys.map((element, i) => {
|
||||
const eol = objectKeys.length - 1 === i ? tokens.newline : ',' + tokens.newlineOrSpace;
|
||||
const isSymbol = typeof element === 'symbol';
|
||||
const isClassic = !isSymbol && /^[a-z$_][$\w]*$/i.test(element);
|
||||
const key = isSymbol || isClassic ? element : stringify(element, options);
|
||||
|
||||
let value = stringify(input[element], options, pad + indent);
|
||||
if (options.transform) {
|
||||
value = options.transform(input, element, value);
|
||||
}
|
||||
|
||||
return tokens.indent + String(key) + ': ' + value + eol;
|
||||
}).join('') + tokens.pad + '}';
|
||||
|
||||
seen.pop();
|
||||
|
||||
return expandWhiteSpace(returnValue);
|
||||
}
|
||||
|
||||
input = String(input).replace(/[\r\n]/g, x => x === '\n' ? '\\n' : '\\r');
|
||||
|
||||
if (options.singleQuotes === false) {
|
||||
input = input.replace(/"/g, '\\"');
|
||||
return `"${input}"`;
|
||||
}
|
||||
|
||||
input = input.replace(/\\?'/g, '\\\'');
|
||||
return `'${input}'`;
|
||||
})(input, options, pad);
|
||||
}
|
27
src/main.js
27
src/main.js
@ -1,19 +1,16 @@
|
||||
import Vue from "vue";
|
||||
import ElementUI from "element-ui";
|
||||
import "element-ui/lib/theme-chalk/index.css";
|
||||
|
||||
import AntdUI from "ant-design-vue";
|
||||
import "ant-design-vue/dist/antd.css";
|
||||
import { createApp, compile } from "vue";
|
||||
import ElementPlus from "element-plus";
|
||||
import "element-plus/dist/index.css";
|
||||
import APP from "./App.vue";
|
||||
|
||||
Vue.use(ElementUI);
|
||||
Vue.use(AntdUI);
|
||||
function createBaseApp(renderComponent = {}) {
|
||||
const app = createApp(renderComponent);
|
||||
app.use(ElementPlus);
|
||||
return app;
|
||||
}
|
||||
|
||||
createBaseApp(APP).mount("#app");
|
||||
|
||||
// 内部需要同样配置的全局Vue
|
||||
self.Vue = Vue;
|
||||
|
||||
new Vue({
|
||||
el: "#app",
|
||||
render: (h) => h(APP),
|
||||
});
|
||||
|
||||
self.createBaseApp = createBaseApp;
|
||||
self.compile = compile;
|
||||
|
@ -4,9 +4,9 @@
|
||||
<div class="demonstration-element" lc_id="tr6tZHyaax" @click="dialogVisible = true">Dialog 对话框</div>
|
||||
<div lc-mark lc_id="KqRoagSJYH">
|
||||
<el-button type="text" lc_id="IbBWKHUvQx">直接拖我看结果</el-button>
|
||||
<el-dialog title="提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose" lc_id="kl38EP183o">
|
||||
<el-dialog title="提示" v-model="dialogVisible" width="30%" :before-close="handleClose" lc_id="kl38EP183o">
|
||||
<span lc_id="o7tyPWHtXQ">这是一段信息</span>
|
||||
<span slot="footer" class="dialog-footer" lc_id="4xYQZAAk6B">
|
||||
<span footer class="dialog-footer" lc_id="4xYQZAAk6B">
|
||||
<el-button @click="dialogVisible = false" lc_id="nlc9K6Rhcp">取 消</el-button>
|
||||
<el-button type="primary" @click="dialogVisible = false" lc_id="mgZZJ553WQ">确 定</el-button>
|
||||
</span>
|
||||
|
@ -10,7 +10,7 @@
|
||||
<el-radio label="btt" lc_id="iP/9XjMVBe">从下往上开</el-radio>
|
||||
</el-radio-group>
|
||||
<el-button @click="drawer = true" type="primary" style="margin-left: 16px;" disabled lc_id="hrOAKkng+k">点我打开</el-button>
|
||||
<el-drawer title="我是标题" :visible.sync="drawer" :direction="direction" :before-close="handleDrawerClose" lc_id="rXvMMLyeYl">
|
||||
<el-drawer title="我是标题" v-model="drawer" :direction="direction" :before-close="handleDrawerClose" lc_id="rXvMMLyeYl">
|
||||
<span lc_id="mc44ZyLRo7">我来啦!</span>
|
||||
</el-drawer>
|
||||
</div>
|
||||
|
@ -13,18 +13,18 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import button from "./button";
|
||||
import icon from "./icon";
|
||||
import layout from "./layout";
|
||||
import container from "./container";
|
||||
import form from "./form";
|
||||
import button from "./button.vue";
|
||||
import table from "./table";
|
||||
import formBase from "./form-base";
|
||||
import dialog from "./dialog";
|
||||
import image from "./image";
|
||||
import final from "./final";
|
||||
// import icon from "./icon";
|
||||
// import layout from "./layout";
|
||||
// import container from "./container";
|
||||
// import form from "./form";
|
||||
// import formBase from "./form-base";
|
||||
// import dialog from "./dialog";
|
||||
// import image from "./image";
|
||||
// import final from "./final";
|
||||
|
||||
import { deepLCEle } from "@/utils/initRawComponent";
|
||||
// import { deepLCEle } from "@/utils/initRawComponent";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
@ -34,22 +34,22 @@ export default {
|
||||
this.$emit('mounted');
|
||||
// 对所有拥有lc-mark的元素进行初始化
|
||||
let countComponentCount = 0;
|
||||
deepLCEle(document.querySelector('.element-class'), () => {
|
||||
countComponentCount++;
|
||||
});
|
||||
// deepLCEle(document.querySelector('.element-class'), () => {
|
||||
// countComponentCount++;
|
||||
// });
|
||||
},
|
||||
methods: {},
|
||||
components: {
|
||||
"lc-button": button,
|
||||
"lc-icon": icon,
|
||||
"lc-form": form,
|
||||
"lc-layout": layout,
|
||||
"lc-container": container,
|
||||
"lc-table": table,
|
||||
"lc-form-base": formBase,
|
||||
"lc-dialog": dialog,
|
||||
"lc-image": image,
|
||||
"lc-final": final,
|
||||
// "lc-icon": icon,
|
||||
// "lc-form": form,
|
||||
// "lc-layout": layout,
|
||||
// "lc-container": container,
|
||||
// "lc-form-base": formBase,
|
||||
// "lc-dialog": dialog,
|
||||
// "lc-image": image,
|
||||
// "lc-final": final,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -17,14 +17,6 @@
|
||||
<span lc_id="m+Oy7pHzNT" lc-mark>Span Element</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr lc_id="xunAa9pXZZ">
|
||||
<td lc_id="m11Db3zz1r">
|
||||
<div class="title" lc_id="dSImHjC62W">center:</div>
|
||||
</td>
|
||||
<td lc_id="KrJXHbe0Y4">
|
||||
<center lc_id="CN8KOU6sKz" lc-mark>Center Element</center>
|
||||
</td>
|
||||
</tr>
|
||||
<tr lc_id="Ejan36KyM/">
|
||||
<td lc_id="ke9QDthYso">
|
||||
<div class="title" lc_id="V2t1JzpJnA">a(超链接):</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import isEqual from "lodash/isEqual";
|
||||
import cryptoRandomString from "crypto-random-string";
|
||||
import isEqual from "lodash-es/isEqual";
|
||||
// import cryptoRandomString from "crypto-random-string";
|
||||
|
||||
export function getRawComponentKey(__rawVueInfo__) {
|
||||
return Object.keys(__rawVueInfo__)[0];
|
||||
@ -50,7 +50,7 @@ export function ergodic(jsonObj) {
|
||||
|
||||
// 添加ID
|
||||
if (!jsonObj["lc_id"]) {
|
||||
jsonObj["lc_id"] = cryptoRandomString({ length: 10, type: "base64" });
|
||||
// jsonObj["lc_id"] = cryptoRandomString({ length: 10, type: "base64" });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
import { isObject, isArray, getRawComponentKey } from '@/utils/common';
|
||||
import presetAttribute from "../libs/presetAttribute";
|
||||
const cryptoRandomString = require("crypto-random-string");
|
||||
// const cryptoRandomString = require("crypto-random-string");
|
||||
|
||||
// 将预生成的ID替换,否则当有两个组件挂在同一个树上时,后一个会将前一个的属性覆盖
|
||||
export function replaceRowID(codeObj, html) {
|
||||
@ -14,10 +14,7 @@ export function replaceRowID(codeObj, html) {
|
||||
const element = obj[key];
|
||||
if (key == "lc_id") {
|
||||
const oldID = obj[key];
|
||||
const newID = cryptoRandomString({
|
||||
length: 10,
|
||||
type: "base64",
|
||||
});
|
||||
const newID = 3333;
|
||||
newHtml = newHtml.replace(oldID, newID);
|
||||
obj[key] = newID;
|
||||
} else if (isObject(element)) {
|
||||
@ -40,7 +37,7 @@ export function updateLinkTree(codeObj) {
|
||||
window.tree = {};
|
||||
}
|
||||
if (!window.treeWithID) {
|
||||
const innerObj = {};
|
||||
let innerObj = {};
|
||||
Object.defineProperty(window, 'treeWithID', {
|
||||
get: function () {
|
||||
return innerObj;
|
||||
|
32
vite.config.js
Normal file
32
vite.config.js
Normal file
@ -0,0 +1,32 @@
|
||||
import { defineConfig } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import ViteRequireContext from "@originjs/vite-plugin-require-context";
|
||||
|
||||
import path from "path";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
ViteRequireContext(),
|
||||
],
|
||||
resolve: {
|
||||
alias: [
|
||||
{
|
||||
find: "@",
|
||||
replacement: path.resolve(__dirname, "src"),
|
||||
},
|
||||
{
|
||||
find: "vue",
|
||||
replacement: "vue/dist/vue.esm-bundler.js"
|
||||
}
|
||||
],
|
||||
extensions: [".vue", ".js"],
|
||||
},
|
||||
server: {
|
||||
fs: {
|
||||
// 可以为项目根目录的上一级提供服务
|
||||
allow: [".."],
|
||||
},
|
||||
},
|
||||
});
|
@ -3,7 +3,8 @@ const path = require("path");
|
||||
module.exports = {
|
||||
css: { extract: false },
|
||||
chainWebpack: (config) => {
|
||||
config.resolve.alias.set("vue$", "vue/dist/vue.esm.js");
|
||||
// config.resolve.alias.set("vue$", "vue/dist/vue.esm.js");
|
||||
// config.resolve.alias.set('vue', '@vue/compat/dist/vue.esm-browser.prod.js')
|
||||
},
|
||||
|
||||
publicPath: process.env.PUBLIC_PATH,
|
||||
|
Loading…
x
Reference in New Issue
Block a user