|
@@ -0,0 +1,231 @@
|
|
|
|
+<!--
|
|
|
|
+ * @Author: WangJiaCheng
|
|
|
|
+ * @Date: 2021-07-28 14:18:16
|
|
|
|
+ * @LastEditors: WangJiaCheng
|
|
|
|
+ * @LastEditTime: 2021-07-29 16:37:04
|
|
|
|
+ * @Description: 代码编辑
|
|
|
|
+-->
|
|
|
|
+<template>
|
|
|
|
+ <div style="height:100%">
|
|
|
|
+ <el-row style="height:100%;overflow:auto">
|
|
|
|
+ <el-col :md="24" :lg="12" class="left-editor">
|
|
|
|
+ <el-tabs v-model="activeTab" type="card" class="editor-tabs">
|
|
|
|
+ <el-tab-pane name="html">
|
|
|
|
+ <span slot="label">
|
|
|
|
+ <i v-if="activeTab==='html'" class="el-icon-edit" />
|
|
|
|
+ <i v-else class="el-icon-document" />
|
|
|
|
+ template
|
|
|
|
+ </span>
|
|
|
|
+ </el-tab-pane>
|
|
|
|
+ <el-tab-pane name="js">
|
|
|
|
+ <span slot="label">
|
|
|
|
+ <i v-if="activeTab==='js'" class="el-icon-edit" />
|
|
|
|
+ <i v-else class="el-icon-document" />
|
|
|
|
+ script
|
|
|
|
+ </span>
|
|
|
|
+ </el-tab-pane>
|
|
|
|
+ <el-tab-pane name="css">
|
|
|
|
+ <span slot="label">
|
|
|
|
+ <i v-if="activeTab==='css'" class="el-icon-edit" />
|
|
|
|
+ <i v-else class="el-icon-document" />
|
|
|
|
+ css
|
|
|
|
+ </span>
|
|
|
|
+ </el-tab-pane>
|
|
|
|
+ </el-tabs>
|
|
|
|
+ <div v-show="activeTab==='html'" id="codeEditorHtml" class="tab-editor" />
|
|
|
|
+ <div v-show="activeTab==='js'" id="codeEditorJs" class="tab-editor" />
|
|
|
|
+ <div v-show="activeTab==='css'" id="codeEditorCss" class="tab-editor" />
|
|
|
|
+ </el-col>
|
|
|
|
+ </el-row>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+import { parse } from '@babel/parser'
|
|
|
|
+import ClipboardJS from 'clipboard'
|
|
|
|
+import { saveAs } from 'file-saver'
|
|
|
|
+import {
|
|
|
|
+ makeUpHtml, vueTemplate, vueScript, cssStyle, makeUpWcHtml
|
|
|
|
+} from '@/components/generator/html'
|
|
|
|
+import { makeUpJs, makeUpWcJs } from '@/components/generator/js'
|
|
|
|
+import { buildTable, makeTableJs } from '@/components/generator/table'
|
|
|
|
+import { buildTabs, makeTabsJs } from '@/components/generator/tabs'
|
|
|
|
+import { makeUpCss } from '@/components/generator/css'
|
|
|
|
+import { exportDefault, beautifierConf } from '@/utils/index'
|
|
|
|
+import loadMonaco from '@/utils/loadMonaco'
|
|
|
|
+import loadBeautifier from '@/utils/loadBeautifier'
|
|
|
|
+
|
|
|
|
+const editorObj = {
|
|
|
|
+ html: null,
|
|
|
|
+ js: null,
|
|
|
|
+ css: null
|
|
|
|
+}
|
|
|
|
+const mode = {
|
|
|
|
+ html: 'html',
|
|
|
|
+ js: 'javascript',
|
|
|
|
+ css: 'css'
|
|
|
|
+}
|
|
|
|
+let beautifier
|
|
|
|
+let monaco
|
|
|
|
+
|
|
|
|
+export default {
|
|
|
|
+ name: 'CodeEditor',
|
|
|
|
+ props: {
|
|
|
|
+ codeType: {
|
|
|
|
+ type: String,
|
|
|
|
+ default: 'page'
|
|
|
|
+ },
|
|
|
|
+ formData: {
|
|
|
|
+ type: Object,
|
|
|
|
+ default() {
|
|
|
|
+ return {}
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ generateConf: {
|
|
|
|
+ type: Object,
|
|
|
|
+ default() {
|
|
|
|
+ return {}
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ activeTab: 'html',
|
|
|
|
+ htmlCode: '',
|
|
|
|
+ jsCode: '',
|
|
|
|
+ cssCode: '',
|
|
|
|
+ codeFrame: '',
|
|
|
|
+ isIframeLoaded: false,
|
|
|
|
+ isInitcode: false, // 保证open后两个异步只执行一次runcode
|
|
|
|
+ isRefreshCode: false, // 每次打开都需要重新刷新代码
|
|
|
|
+ scripts: [],
|
|
|
|
+ links: [],
|
|
|
|
+ monaco: null
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ watch: {
|
|
|
|
+ codeType: {
|
|
|
|
+ handler(val) {
|
|
|
|
+ if (val) {
|
|
|
|
+ this.renderCode()
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ mounted() {
|
|
|
|
+ window.addEventListener('keydown', this.preventDefaultSave)
|
|
|
|
+ const clipboard = new ClipboardJS('.copy-btn', {
|
|
|
|
+ text: trigger => {
|
|
|
|
+ const codeStr = this.generateCode()
|
|
|
|
+ this.$notify({
|
|
|
|
+ title: '成功',
|
|
|
|
+ message: '代码已复制到剪切板,可粘贴。',
|
|
|
|
+ type: 'success'
|
|
|
|
+ })
|
|
|
|
+ return codeStr
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ clipboard.on('error', e => {
|
|
|
|
+ this.$message.error('代码复制失败')
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ beforeDestroy() {
|
|
|
|
+ window.removeEventListener('keydown', this.preventDefaultSave)
|
|
|
|
+ },
|
|
|
|
+ methods: {
|
|
|
|
+ setEditorValue(id, type, codeStr) {
|
|
|
|
+ if (editorObj[type]) {
|
|
|
|
+ editorObj[type].setValue(codeStr)
|
|
|
|
+ } else {
|
|
|
|
+ editorObj[type] = monaco.editor.create(document.getElementById(id), {
|
|
|
|
+ value: codeStr,
|
|
|
|
+ theme: 'vs-dark',
|
|
|
|
+ language: mode[type],
|
|
|
|
+ automaticLayout: true
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ // ctrl + s 刷新
|
|
|
|
+ editorObj[type].onKeyDown(e => {
|
|
|
|
+ if (e.keyCode === 49 && (e.metaKey || e.ctrlKey)) {
|
|
|
|
+ this.runCode()
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ renderCode() {
|
|
|
|
+ const { type = 'file' } = this.generateConf
|
|
|
|
+ if (this.codeType === 'page') {
|
|
|
|
+ this.htmlCode = makeUpWcHtml(this.formData, type)
|
|
|
|
+ this.jsCode = makeUpWcJs(this.formData, type)
|
|
|
|
+ this.cssCode = makeUpCss(this.formData)
|
|
|
|
+ }
|
|
|
|
+ if (this.codeType === 'tab') {
|
|
|
|
+ this.htmlCode = buildTabs(this.formData, type)
|
|
|
|
+ this.jsCode = makeTabsJs(this.formData, type)
|
|
|
|
+ this.cssCode = makeUpCss(this.formData)
|
|
|
|
+ }
|
|
|
|
+ if (this.codeType === 'list') {
|
|
|
|
+ this.htmlCode = buildTable(this.formData, type)
|
|
|
|
+ this.jsCode = makeTableJs(this.formData, type)
|
|
|
|
+ this.cssCode = makeUpCss(this.formData)
|
|
|
|
+ }
|
|
|
|
+ if (this.codeType === 'form') {
|
|
|
|
+ this.htmlCode = makeUpHtml(this.formData.formModel, type)
|
|
|
|
+ this.jsCode = makeUpJs(this.formData.formModel, type)
|
|
|
|
+ this.cssCode = makeUpCss(this.formData.formModel)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ loadBeautifier(btf => {
|
|
|
|
+ beautifier = btf
|
|
|
|
+ this.htmlCode = beautifier.html(this.htmlCode, beautifierConf.html)
|
|
|
|
+ this.jsCode = beautifier.js(this.jsCode, beautifierConf.js)
|
|
|
|
+ // this.cssCode = beautifier.css(this.cssCode, beautifierConf.html)
|
|
|
|
+
|
|
|
|
+ loadMonaco(val => {
|
|
|
|
+ monaco = val
|
|
|
|
+ this.setEditorValue('codeEditorHtml', 'html', this.htmlCode)
|
|
|
|
+ this.setEditorValue('codeEditorJs', 'js', this.jsCode)
|
|
|
|
+ this.setEditorValue('codeEditorCss', 'css', this.cssCode)
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</script>
|
|
|
|
+
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
+@import '@/styles/mixin.scss';
|
|
|
|
+.tab-editor {
|
|
|
|
+ position: absolute;
|
|
|
|
+ top: 33px;
|
|
|
|
+ bottom: 0;
|
|
|
|
+ left: 0;
|
|
|
|
+ right: 0;
|
|
|
|
+ font-size: 14px;
|
|
|
|
+}
|
|
|
|
+.left-editor {
|
|
|
|
+ position: relative;
|
|
|
|
+ height: 500px;
|
|
|
|
+ background: #1e1e1e;
|
|
|
|
+ overflow: hidden;
|
|
|
|
+ width: 100%;
|
|
|
|
+}
|
|
|
|
+.setting{
|
|
|
|
+ position: absolute;
|
|
|
|
+ right: 15px;
|
|
|
|
+ top: 3px;
|
|
|
|
+ color: #a9f122;
|
|
|
|
+ font-size: 18px;
|
|
|
|
+ cursor: pointer;
|
|
|
|
+ z-index: 1;
|
|
|
|
+}
|
|
|
|
+.right-preview {
|
|
|
|
+ height: 100%;
|
|
|
|
+ .result-wrapper {
|
|
|
|
+ height: calc(100vh - 33px);
|
|
|
|
+ width: 100%;
|
|
|
|
+ overflow: auto;
|
|
|
|
+ padding: 12px;
|
|
|
|
+ box-sizing: border-box;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+</style>
|