You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
9.3 KiB
Vue

<template>
<div class="bs-custom-components">
<div class="bs-custom-component-header">
<div class="left-title">
<div class="logo-wrap item-wrap">
<img
class="menu-img"
src="~packages/BigScreenDesign/images/app.png"
alt="返回"
@click="backManagement"
>
<span class="logo-text name-span">{{ form.name }}</span>
</div>
</div>
<div class="right-btn-wrap">
<CusBtn>
生成图片
</CusBtn>
<CusBtn
:loading="loading"
@click="save"
>
保存
</CusBtn>
</div>
</div>
<div class="bs-custom-component-content">
<div class="bs-custom-component-content-code">
<div class="left-vue-code component-code">
<div class="code-tab-header">
<div class="code-tab">
VUE组件
</div>
<div class="upload-btn">
<CusBtn @click="upload('vueContent')">
上传
</CusBtn>
</div>
</div>
<div class="code-tab-content">
<!-- <MonacoEditor
ref="vueContent"
v-model="form.vueContent"
class="editor"
language="html"
/> -->
<codemirror
v-model="form.vueContent"
:options="vueOptions"
/>
</div>
</div>
<div class="right-setting-code component-code">
<div class="code-tab-header">
<div class="code-tab">
组件配置
</div>
<div class="upload-btn">
<CusBtn @click="upload('settingContent')">
上传
</CusBtn>
</div>
</div>
<div class="code-tab-content">
<!-- <MonacoEditor
ref="settingContent"
v-model="form.settingContent"
class="editor"
language="javascript"
/> -->
<codemirror
v-model="form.settingContent"
:options="settingOptions"
/>
</div>
</div>
</div>
<div class="bs-custom-component-content-preview">
<div class="bs-preview-inner">
<BizComponentPreview
:vue-content="form.vueContent"
:setting-content="form.settingContent"
/>
</div>
</div>
<!-- 通过计算属性发现accept有问题 -->
<input
ref="vueContentFile"
style="display: none"
type="file"
name="file"
accept=".vue"
@change="handleBatchUpload"
>
<input
ref="settingContentFile"
style="display: none"
type="file"
name="file"
accept=".js"
@change="handleBatchUpload"
>
</div>
</div>
</template>
<script>
import CusBtn from 'packages/BigScreenDesign/BtnLoading'
// import MonacoEditor from 'packages/MonacoEditor'
import BizComponentPreview from './Preview'
import { getBizComponentInfo, updateBizComponent } from 'packages/js/api/bigScreenApi'
import { defaultSettingContent, defaultVueContent } from './config/defaultBizConfig'
import { codemirror } from 'vue-codemirror'
import 'codemirror/lib/codemirror.css'
import 'codemirror/theme/material-darker.css'
import 'codemirror/addon/selection/active-line.js'
import 'codemirror/mode/vue/vue.js'
export default {
name: 'BizComponentDesign',
components: {
CusBtn,
// MonacoEditor,
codemirror,
BizComponentPreview
},
props: {},
data () {
return {
form: {
name: '',
coverPicture: '',
settingContent: '',
vueContent: ''
},
currentContentType: 'vueContent',
loading: false,
vueOptions: {
foldGutter: true,
lineWrapping: true,
gutters: [
'CodeMirror-linenumbers',
'CodeMirror-foldgutter',
'CodeMirror-lint-markers'
],
theme: 'material-darker',
tabSize: 4,
lineNumbers: true,
line: true,
indentWithTabs: true,
smartIndent: true,
autofocus: false,
matchBrackets: true,
mode: 'text/x-vue',
hintOptions: {
completeSingle: false
},
lint: true
},
settingOptions: {
foldGutter: true,
lineWrapping: true,
gutters: [
'CodeMirror-linenumbers',
'CodeMirror-foldgutter',
'CodeMirror-lint-markers'
],
theme: 'material-darker',
tabSize: 4,
lineNumbers: true,
line: true,
indentWithTabs: true,
smartIndent: true,
autofocus: false,
matchBrackets: true,
mode: 'text/javascript',
hintOptions: {
completeSingle: false
},
lint: true
}
}
},
computed: {
},
mounted () {
this.getBizComponentInfo()
},
methods: {
getBizComponentInfo () {
const code = this.$route.query.code
if (code) {
getBizComponentInfo(code).then(data => {
this.form = {
...data,
name: data.name,
coverPicture: data.coverPicture,
settingContent: data.settingContent || defaultSettingContent,
vueContent: data.vueContent || defaultVueContent
}
// this.$refs.vueContent.editor.setValue(this.form.vueContent)
// this.$refs.settingContent.editor.setValue(this.form.settingContent)
})
}
},
upload (type) {
this.currentContentType = type
this.$refs[`${this.currentContentType}File`].click()
},
handleBatchUpload (source) {
const file = source.target.files
const reader = new FileReader() // 新建一个FileReader
reader.readAsText(file[0], 'UTF-8') // 读取文件
reader.onload = (event) => {
const sileString = event.target.result // 读取文件内容
this.form[this.currentContentType] = sileString
// input通过onchange事件来触发js代码的由于两次文件是重复的所以这个时候onchange事件是没有触发到的所以需要手动清空input的值
source.target.value = ''
}
},
backManagement () {
this.$router.push({
path: window.BS_CONFIG?.routers?.componentUrl || '/big-screen-components'
})
},
save () {
this.loading = true
updateBizComponent(this.form).then(() => {
this.$message.success('保存成功')
}).catch(() => {
this.$message.error('保存失败')
}).finally(() => {
this.loading = false
})
}
}
}
</script>
<style lang="scss" scoped>
.bs-custom-components {
position: absolute;
display: flex;
flex-direction: column;
width: 100%;
height: 100vh;
color: var(--bs-el-text);
background: var(--bs-background-2);
overflow: hidden;
> * {
box-sizing: border-box;
}
.bs-custom-component-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
padding: 0 16px;
border-bottom: 4px solid var(--bs-background-1);
background: var(--bs-background-2);
.left-title {
font-size: 16px;
color: var(--bs-el-title);
.logo-wrap {
display: flex;
align-items: center;
}
.menu-img {
width: 18px;
height: 18px;
margin-right: 15px;
margin-left: 9px;
cursor: pointer;
}
}
.right-btn-wrap {
display: flex;
align-items: center;
height: 100%;
}
}
.bs-custom-component-content {
flex: 1;
background: var(--bs-background-2);
display: flex;
flex-direction: column;
.bs-custom-component-content-code {
display: flex;
justify-content: space-between;
width: 100%;
height: 400px;
padding: 16px;
.left-vue-code {
width: 60%;
height: 100%;
/* background: var(--bs-background-1); */
}
.right-setting-code {
width: calc(40% - 16px);
height: 100%;
/* background: var(--bs-background-1); */
}
.component-code {
.code-tab-header {
display: flex;
align-items: center;
justify-content: space-between;
height: 40px;
.code-tab {
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
width: 120px;
height: 100%;
color: var(--bs-el-title);
background: var(--bs-background-1);
}
}
.code-tab-content {
height: calc(100% - 40px);
background: var(--bs-background-1);
}
}
}
.bs-custom-component-content-preview {
flex: 1;
width: 100%;
height: 50%;
padding: 0 16px 16px;
.bs-preview-inner {
width: 100%;
height: 100%;
background: var(--bs-background-1);
position: relative;
}
}
}
}
</style>
<style>
.cm-s-material-darker.CodeMirror,
.cm-s-material-darker .CodeMirror-gutters
{
background: var(--bs-background-1) !important;
}
.CodeMirror-scroll {
background-color: var(--bs-background-1) !important;
}
.CodeMirror-gutters {
border-right: 1px solid var(--bs-background-1) !important;
background-color: var(--bs-background-1) !important;
}
</style>