初始化
This commit is contained in:
215
frontend/packages/BizComponent/Preview.vue
Normal file
215
frontend/packages/BizComponent/Preview.vue
Normal file
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<div
|
||||
v-loading="loading"
|
||||
class="bs-remote-preview"
|
||||
element-loading-text="远程组件加载中..."
|
||||
>
|
||||
<div class="remote-preview-inner-wrap">
|
||||
<component
|
||||
:is="remoteComponent"
|
||||
:config="config"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import remoteVueLoader from 'remote-vue-loader'
|
||||
import * as _echarts from 'echarts'
|
||||
import * as g2Plot from '@antv/g2plot'
|
||||
import { getBizComponentInfo } from 'data-room-ui/js/api/bigScreenApi'
|
||||
import innerRemoteComponents, { getRemoteComponents } from 'data-room-ui/RemoteComponents/remoteComponentsList'
|
||||
export default {
|
||||
name: 'BsComponentPreview',
|
||||
props: {
|
||||
vueContent: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
settingContent: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
config: {
|
||||
get () {
|
||||
// eslint-disable-next-line prefer-const
|
||||
let option = {}
|
||||
// eslint-disable-next-line prefer-const
|
||||
let setting = []
|
||||
// eslint-disable-next-line prefer-const, no-unused-vars
|
||||
let title = ''
|
||||
// eslint-disable-next-line prefer-const, no-unused-vars
|
||||
let data = []
|
||||
// eslint-disable-next-line prefer-const, no-unused-vars
|
||||
let optionHandler = ''
|
||||
const g2Plots = g2Plot
|
||||
const echarts = _echarts
|
||||
// eslint-disable-next-line prefer-const
|
||||
let settingContent = this.settingContentInner?.replaceAll('const ', '')
|
||||
// 去掉 export default及后面代码
|
||||
settingContent = settingContent?.replace(/export default[\s\S]*/, '')
|
||||
eval(settingContent)
|
||||
return {
|
||||
title,
|
||||
option,
|
||||
setting,
|
||||
echarts,
|
||||
g2Plots,
|
||||
optionHandler
|
||||
}
|
||||
},
|
||||
set (val) {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
settingContentInner () {
|
||||
this.getRemoteComponent()
|
||||
},
|
||||
vueContentInner () {
|
||||
this.getRemoteComponent()
|
||||
},
|
||||
vueContent (newVal) {
|
||||
this.vueContentInner = newVal
|
||||
},
|
||||
settingContent (newVal) {
|
||||
this.settingContentInner = newVal
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
remoteComponent: null,
|
||||
vueContentInner: this.vueContent,
|
||||
settingContentInner: this.settingContent?.replaceAll('const ', '')
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.viewComponent()
|
||||
},
|
||||
methods: {
|
||||
async viewComponent () {
|
||||
// 如果有编码,则获取组件信息
|
||||
if (this.$route.query?.code) {
|
||||
const data = await getBizComponentInfo(this.$route.query?.code)
|
||||
this.vueContentInner = data.vueContent
|
||||
this.settingContentInner = data.settingContent
|
||||
this.config = this.dataFormatting(this.config)
|
||||
this.remoteComponent = remoteVueLoader('data:text/plain,' + encodeURIComponent(this.vueContentInner))
|
||||
this.loading = false
|
||||
}
|
||||
|
||||
// 如果有组件的dirName,则获取系统组件信息
|
||||
if (this.$route.query?.dirName) {
|
||||
const dirName = this.$route.query?.dirName
|
||||
const remoteComponentList = [...innerRemoteComponents, ...getRemoteComponents()]
|
||||
const config = remoteComponentList?.find(item => item.customize.vueSysComponentDirName === dirName)
|
||||
this.config.option = config?.option
|
||||
this.config.title = config?.title
|
||||
const vueFile = config.customize?.vueFile
|
||||
this.remoteComponent = vueFile
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
// 尝试渲染远程文件或远程字符串
|
||||
getRemoteComponent () {
|
||||
this.loading = true
|
||||
this.config = this.dataFormatting(this.config, { success: false })
|
||||
this.remoteComponent = remoteVueLoader('data:text/plain,' + encodeURIComponent(this.vueContentInner))
|
||||
this.loading = false
|
||||
},
|
||||
/**
|
||||
* 组件的配置
|
||||
* @returns {Promise<unknown>}
|
||||
*/
|
||||
// 将config.setting的配置转化为option里的配置,这里之所以将转化的方法提出来,是因为在改变维度指标和样式的时候都需要转化
|
||||
transformSettingToOption (config, type) {
|
||||
let option = null
|
||||
config.setting.forEach(set => {
|
||||
if (set.optionField) {
|
||||
const optionField = set.optionField.split('.')
|
||||
option = config.option
|
||||
optionField.forEach((field, index) => {
|
||||
if (index === optionField.length - 1) {
|
||||
// 数据配置时,必须有值才更新
|
||||
if ((set.tabName === type && type === 'data' && set.value) || (set.tabName === type && type === 'custom')) {
|
||||
option[field] = set.value
|
||||
}
|
||||
} else {
|
||||
// 如果没有这个属性,则创建该属性,并赋值为空对值
|
||||
if (!option[field]) {
|
||||
option[field] = {}
|
||||
}
|
||||
option = option[field]
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return config
|
||||
},
|
||||
dataFormatting (config, data) {
|
||||
// 数据返回成功则赋值
|
||||
if (data?.success) {
|
||||
data = data.data
|
||||
config = this.transformSettingToOption(config, 'data')
|
||||
// 获取到后端返回的数据,有则赋值
|
||||
// const option = config.option
|
||||
// const setting = config.setting
|
||||
if (config.dataHandler) {
|
||||
try {
|
||||
// 此处函数处理data
|
||||
eval(config.dataHandler)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
config.option.data = data
|
||||
} else {
|
||||
// 数据返回失败则赋前端的模拟数据
|
||||
config.option.data = this.plotList?.find(plot => plot.name === config.name)?.option?.data || config.option.data
|
||||
}
|
||||
return config
|
||||
},
|
||||
// 组件的样式改变,返回改变后的config
|
||||
changeStyle (config) {
|
||||
config = { ...this.config, ...config }
|
||||
config = this.transformSettingToOption(config, 'custom')
|
||||
// 这里定义了option和setting是为了保证在执行eval时,optionHandler、dataHandler里面可能会用到,
|
||||
// const option = config.option
|
||||
// const setting = config.setting
|
||||
if (this.config.optionHandler) {
|
||||
try {
|
||||
// 此处函数处理config
|
||||
eval(this.config.optionHandler)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
if (this.chart) {
|
||||
this.chart.update(config.option)
|
||||
}
|
||||
this.changeChartConfig(config)
|
||||
return config
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bs-remote-preview {
|
||||
position: absolute;
|
||||
min-height: 100%;
|
||||
min-width: 100%;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
|
||||
.remote-preview-inner-wrap {
|
||||
position: absolute;
|
||||
height: calc(100% - 40px);
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
padding: 5px 20px;
|
||||
background-color: var(--bs-background-1);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
165
frontend/packages/BizComponent/config/defaultBizConfig.js
Normal file
165
frontend/packages/BizComponent/config/defaultBizConfig.js
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* @description: 此处是业务组件的代码案例
|
||||
* @Date: 2023-06-06 15:45:07
|
||||
*/
|
||||
|
||||
// vue 组件片段
|
||||
export const defaultVueContent = `
|
||||
|
||||
<!-- 这是一个代码案例 -->
|
||||
<template>
|
||||
<div class="div-test-container" @click="testClick">
|
||||
<p>点击测试下点击事件</p>
|
||||
<br />
|
||||
{{ customize.text }}
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'TestA',
|
||||
components: {
|
||||
},
|
||||
// 业务组件提供的props
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
// 计算属性
|
||||
computed: {
|
||||
option () {
|
||||
return this.config.option
|
||||
},
|
||||
optionData () {
|
||||
return this.option.data
|
||||
},
|
||||
customize () {
|
||||
return this.option.customize
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 联动需要调用次接口
|
||||
linkage (row) {
|
||||
this.$emit('linkage', row)
|
||||
},
|
||||
// 自己随便写的方法
|
||||
testClick () {
|
||||
this.$message.success('点击了边框')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// 此处书写样式,支持scss
|
||||
.div-test-container {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border: 4px solid #f00;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
flex-direction: column;
|
||||
|
||||
.item {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
`
|
||||
|
||||
// 配置 片段
|
||||
export const defaultSettingContent = `
|
||||
// 这是一个配置案例
|
||||
// 组件备注名称
|
||||
const title = '边框案例'
|
||||
// 右侧配置项
|
||||
const setting = [
|
||||
{
|
||||
label: '维度',
|
||||
// 设置组件类型, select / input / colorPicker
|
||||
type: 'select',
|
||||
// 字段
|
||||
field: 'xField',
|
||||
optionField: 'xField', // 对应options中的字段
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
// 绑定的值
|
||||
value: '',
|
||||
// tab页。 data: 数据, custom: 自定义
|
||||
tabName: 'data'
|
||||
},
|
||||
{
|
||||
label: '指标',
|
||||
// 设置组件类型
|
||||
type: 'select',
|
||||
// 字段
|
||||
field: 'yField',
|
||||
// 对应options中的字段
|
||||
optionField: 'yField',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '',
|
||||
tabName: 'data'
|
||||
},
|
||||
{
|
||||
label: '用户名',
|
||||
// 设置组件类型, select / input / colorPicker
|
||||
type: 'input',
|
||||
// 字段
|
||||
field: 'customize_username',
|
||||
optionField: 'customize.username', // 对应options中的字段
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
// 绑定的值
|
||||
value: '',
|
||||
// tab页。 data: 数据, custom: 自定义
|
||||
tabName: 'custom'
|
||||
},
|
||||
{
|
||||
label: '手机号',
|
||||
// 设置组件类型, select / input / colorPicker
|
||||
type: 'input',
|
||||
// 字段
|
||||
field: 'customize_phone',
|
||||
optionField: 'customize.phone', // 对应options中的字段
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
// 绑定的值
|
||||
value: '',
|
||||
// tab页。 data: 数据, custom: 自定义
|
||||
tabName: 'custom'
|
||||
}
|
||||
]
|
||||
|
||||
// 模拟数据
|
||||
const data = []
|
||||
|
||||
const option = {
|
||||
// 数据
|
||||
data: data,
|
||||
// 数据的字段相关属性
|
||||
xField: '',
|
||||
yField: '',
|
||||
seriesField: '',
|
||||
// 自定义组件其他属性
|
||||
customize: {
|
||||
text: '这是一个边框'
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
title,
|
||||
option,
|
||||
setting
|
||||
}
|
||||
`
|
||||
232
frontend/packages/BizComponent/config/defaultEchartsConfig.js
Normal file
232
frontend/packages/BizComponent/config/defaultEchartsConfig.js
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* @description: 此处是业务组件的代码案例
|
||||
* @Date: 2023-06-06 15:45:07
|
||||
*/
|
||||
|
||||
// vue 组件片段
|
||||
export const defaultEchartsVueContent = `
|
||||
<!-- 这是一个代码案例 -->
|
||||
<template>
|
||||
<div
|
||||
:id="chatId"
|
||||
style="width: 100%;height: 100%"
|
||||
/>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
|
||||
name: 'TestA',
|
||||
components: {
|
||||
},
|
||||
// 业务组件提供的props
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
chart: null,
|
||||
}
|
||||
},
|
||||
// 计算属性
|
||||
computed: {
|
||||
chatId(){
|
||||
return 'echarts' + this.config.code
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//响应式变化组件大小方法,无需改动
|
||||
onResize () {
|
||||
this.chart.resize({
|
||||
animation: {
|
||||
duration: 300,
|
||||
easing: 'linear'
|
||||
// delay: 500,
|
||||
}
|
||||
})
|
||||
},
|
||||
// 初始化图表
|
||||
newChart (config) {
|
||||
let option = config.option
|
||||
const xList=config.option.data.map(item=> item[config.option.xField])
|
||||
const yList=config.option.data.map(item=> item[config.option.yField])
|
||||
option.xAxis.data=xList
|
||||
option.series[0].data=yList
|
||||
const dom = document.getElementById(this.chatId)
|
||||
this.chart = config.echarts.init(dom)
|
||||
this.chart.setOption(option,true)
|
||||
},
|
||||
},
|
||||
mounted(){
|
||||
this.newChart(this.config)
|
||||
//响应式变化组件大小,无需改动
|
||||
const dragSelect = document.querySelector("#"+this.chatId)
|
||||
let pre = Date.now()
|
||||
const wait = 300
|
||||
const resizeObserver = new ResizeObserver(entries => {
|
||||
const now = Date.now()
|
||||
if (now - pre >= wait) {
|
||||
setTimeout(() => {
|
||||
this.onResize()
|
||||
}, wait)
|
||||
pre = Date.now()
|
||||
}
|
||||
})
|
||||
resizeObserver.observe(dragSelect)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// 此处书写样式,支持scss
|
||||
|
||||
</style>
|
||||
`
|
||||
|
||||
// 配置 片段
|
||||
export const defaultEchartsSettingContent = `
|
||||
// 这是一个配置案例
|
||||
// 组件备注名称
|
||||
const title = 'echarts案例'
|
||||
|
||||
// 右侧配置项
|
||||
const setting = [
|
||||
{
|
||||
label: '维度',
|
||||
// 设置组件类型, select / input / colorPicker
|
||||
type: 'select',
|
||||
// 字段
|
||||
field: 'xField',
|
||||
optionField: 'xField', // 对应options中的字段
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
// 绑定的值
|
||||
value: '',
|
||||
// tab页。 data: 数据, custom: 自定义
|
||||
tabName: 'data'
|
||||
},
|
||||
{
|
||||
label: '指标',
|
||||
// 设置组件类型
|
||||
type: 'select',
|
||||
// 字段
|
||||
field: 'yField',
|
||||
// 对应options中的字段
|
||||
optionField: 'yField',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '',
|
||||
tabName: 'data'
|
||||
},
|
||||
{
|
||||
label: '柱形颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'color',
|
||||
optionField: 'color',
|
||||
value: '#007aff',
|
||||
tabName: 'custom',
|
||||
groupName: 'graph'
|
||||
},
|
||||
{
|
||||
label: 'x轴类型',
|
||||
type: 'input',
|
||||
field: 'xAxis_type',
|
||||
optionField: 'xAxis.type',
|
||||
value: 'category',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '是否显示标签',
|
||||
type: 'switch',
|
||||
field: 'xAxis_axisLabel_show',
|
||||
optionField: 'xAxis.axisLabel.show',
|
||||
value: true,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签旋转角度',
|
||||
type: 'inputNumber',
|
||||
field: 'xAxis_axisLabel_rotate',
|
||||
optionField: 'xAxis.axisLabel.rotate',
|
||||
value: 0,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'xAxis_axisLabel_color',
|
||||
optionField: 'xAxis.axisLabel.color',
|
||||
value: '#fff',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: 'y轴类型',
|
||||
type: 'input',
|
||||
field: 'yAxis_type',
|
||||
optionField: 'yAxis.type',
|
||||
value: 'value',
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
}
|
||||
]
|
||||
|
||||
// 模拟数据
|
||||
const data = [
|
||||
{ Date: '2010-01', scales: 1998 },
|
||||
{ Date: '2010-02', scales: 1850 },
|
||||
{ Date: '2010-03', scales: 1720 },
|
||||
{ Date: '2010-04', scales: 1818 },
|
||||
{ Date: '2010-05', scales: 1920 },
|
||||
{ Date: '2010-06', scales: 1802 },
|
||||
{ Date: '2010-07', scales: 1945 },
|
||||
{ Date: '2010-08', scales: 1856 },
|
||||
{ Date: '2010-09', scales: 2107 },
|
||||
{ Date: '2010-10', scales: 2140 }
|
||||
]
|
||||
|
||||
const option = {
|
||||
// 数据将要放入到哪个字段中
|
||||
dataKey: 'data',
|
||||
// 图表内边距
|
||||
appendPadding: [0, 0, 0, 0],
|
||||
data,
|
||||
//柱状图颜色
|
||||
color: '#007aff',
|
||||
appendPadding: [16, 16, 16, 16], // 设置图标的边距
|
||||
xField: 'Date',
|
||||
yField: 'scales',
|
||||
xAxis: {
|
||||
type:'category',
|
||||
data: [],
|
||||
axisLabel:{
|
||||
show:true,
|
||||
color:'#fff',
|
||||
rotate:0
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
},
|
||||
series:[
|
||||
{
|
||||
data: [],
|
||||
type: 'bar',
|
||||
backgroundStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export default {
|
||||
title,
|
||||
option,
|
||||
setting
|
||||
}
|
||||
`
|
||||
513
frontend/packages/BizComponent/config/defaultG2Config.js
Normal file
513
frontend/packages/BizComponent/config/defaultG2Config.js
Normal file
@@ -0,0 +1,513 @@
|
||||
/*
|
||||
* @description: 此处是业务组件的代码案例
|
||||
* @Date: 2023-06-06 15:45:07
|
||||
*/
|
||||
|
||||
// vue 组件片段
|
||||
export const defaultG2VueContent = `
|
||||
<!-- 这是一个代码案例 -->
|
||||
<template>
|
||||
<div
|
||||
:id="chatId"
|
||||
style="width: 100%;height: 100%"
|
||||
/>
|
||||
</template>
|
||||
<script>
|
||||
|
||||
export default {
|
||||
|
||||
name: 'TestA',
|
||||
components: {
|
||||
},
|
||||
// 业务组件提供的props
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
chart: null,
|
||||
}
|
||||
},
|
||||
// 计算属性
|
||||
computed: {
|
||||
chatId(){
|
||||
return 'g2' + this.config.code
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
// 联动需要调用次接口
|
||||
newChart (config) {
|
||||
this.chart = new config.g2Plots['Line'](this.chatId, {
|
||||
renderer: 'svg',
|
||||
// 仪表盘缩放状态下,点击准确
|
||||
supportCSSTransform: true,
|
||||
...config.option
|
||||
})
|
||||
this.chart.render()
|
||||
},
|
||||
},
|
||||
mounted(){
|
||||
this.newChart(this.config)
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
// 此处书写样式,支持scss
|
||||
|
||||
</style>
|
||||
`
|
||||
|
||||
// 配置 片段
|
||||
export const defaultG2SettingContent = `
|
||||
// 这是一个配置案例
|
||||
// 组件备注名称
|
||||
const title = 'g2案例'
|
||||
|
||||
// 右侧配置项
|
||||
const setting = [
|
||||
{
|
||||
label: '维度',
|
||||
// 设置组件类型, select / input / colorPicker
|
||||
type: 'select',
|
||||
// 字段
|
||||
field: 'xField',
|
||||
optionField: 'xField', // 对应options中的字段
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
// 绑定的值
|
||||
value: '',
|
||||
// tab页。 data: 数据, custom: 自定义
|
||||
tabName: 'data'
|
||||
},
|
||||
{
|
||||
label: '指标',
|
||||
// 设置组件类型
|
||||
type: 'select',
|
||||
// 字段
|
||||
field: 'yField',
|
||||
// 对应options中的字段
|
||||
optionField: 'yField',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '',
|
||||
tabName: 'data'
|
||||
},
|
||||
/** 样式配置 **/
|
||||
// 图表 graph
|
||||
{
|
||||
label: '曲线宽度',
|
||||
type: 'inputNumber',
|
||||
field: 'lineStyle_lineWidth',
|
||||
optionField: 'lineStyle.lineWidth',
|
||||
value: 2,
|
||||
tabName: 'custom',
|
||||
groupName: 'graph'
|
||||
},
|
||||
{
|
||||
label: '曲线颜色',
|
||||
type: 'gradual',
|
||||
field: 'lineStyle_stroke',
|
||||
optionField: 'lineStyle.stroke',
|
||||
value: 'l(0) 0:#5F92F9 1:#62FF00',
|
||||
tabName: 'custom',
|
||||
groupName: 'graph'
|
||||
},
|
||||
// 网格线 grid
|
||||
{
|
||||
label: '虚线',
|
||||
type: 'switch',
|
||||
field: 'yAxis_grid_line_style_lineDash',
|
||||
optionField: 'yAxis.grid.line.style.lineDash',
|
||||
value: 0,
|
||||
active: 5,
|
||||
inactive: 0,
|
||||
tabName: 'custom',
|
||||
groupName: 'grid'
|
||||
},
|
||||
{
|
||||
label: '宽度',
|
||||
type: 'inputNumber',
|
||||
field: 'yAxis_grid_line_style_lineWidth',
|
||||
optionField: 'yAxis.grid.line.style.lineWidth',
|
||||
value: 1,
|
||||
tabName: 'custom',
|
||||
groupName: 'grid'
|
||||
},
|
||||
{
|
||||
label: '颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'yAxis_grid_line_style_stroke',
|
||||
optionField: 'yAxis.grid.line.style.stroke',
|
||||
value: '#E5E6EB10',
|
||||
tabName: 'custom',
|
||||
groupName: 'grid'
|
||||
},
|
||||
// 图例 legend
|
||||
// X轴 xAxis
|
||||
{
|
||||
label: '标题',
|
||||
type: 'input',
|
||||
field: 'xAxis_title_text',
|
||||
optionField: 'xAxis.title.text',
|
||||
value: '',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标题位置',
|
||||
type: 'select',
|
||||
field: 'xAxis_title_position',
|
||||
optionField: 'xAxis.title.position',
|
||||
value: 'end',
|
||||
tabName: 'custom',
|
||||
options: [
|
||||
{
|
||||
label: '左',
|
||||
value: 'start'
|
||||
},
|
||||
{
|
||||
label: '中',
|
||||
value: 'center'
|
||||
},
|
||||
{
|
||||
label: '右',
|
||||
value: 'end'
|
||||
}],
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标题字体大小',
|
||||
type: 'inputNumber',
|
||||
field: 'xAxis_title_style_fontSize',
|
||||
optionField: 'xAxis.title.style.fontSize',
|
||||
value: 12,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标题颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'xAxis_title_style_fill',
|
||||
optionField: 'xAxis.title.style.fill',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#e9e9e9',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签大小',
|
||||
type: 'inputNumber',
|
||||
field: 'xAxis_label_style_fontSize',
|
||||
optionField: 'xAxis.label.style.fontSize',
|
||||
value: 12,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'xAxis_label_style_fill',
|
||||
optionField: 'xAxis.label.style.fill',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#e9e9e9',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '轴线宽度',
|
||||
type: 'inputNumber',
|
||||
field: 'xAxis_line_style_lineWidth',
|
||||
optionField: 'xAxis.line.style.lineWidth',
|
||||
value: 1,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '轴线颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'xAxis_line_style_stroke',
|
||||
optionField: 'xAxis.line.style.stroke',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#C9CDD4',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '刻度线宽度',
|
||||
type: 'inputNumber',
|
||||
field: 'xAxis_tickLine_style_lineWidth',
|
||||
optionField: 'xAxis.tickLine.style.lineWidth',
|
||||
value: 1,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '刻度线颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'xAxis_tickLine_style_stroke',
|
||||
optionField: 'xAxis.tickLine.style.stroke',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#C9CDD4',
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签过多时旋转',
|
||||
type: 'switch',
|
||||
field: 'xAxis_label_autoRotate',
|
||||
optionField: 'xAxis.label.autoRotate',
|
||||
value: true,
|
||||
active: true,
|
||||
inactive: false,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签过多时隐藏',
|
||||
type: 'switch',
|
||||
field: 'xAxis_label_autoHide',
|
||||
optionField: 'xAxis.label.autoHide',
|
||||
value: true,
|
||||
active: true,
|
||||
inactive: false,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
{
|
||||
label: '标签过长时省略',
|
||||
type: 'switch',
|
||||
field: 'xAxis_label_autoEllipsis',
|
||||
optionField: 'xAxis.label.autoEllipsis',
|
||||
value: false,
|
||||
active: true,
|
||||
inactive: false,
|
||||
tabName: 'custom',
|
||||
groupName: 'xAxis'
|
||||
},
|
||||
// Y轴 yAxis
|
||||
{
|
||||
label: '标题',
|
||||
type: 'input',
|
||||
field: 'yAxis_title_text',
|
||||
optionField: 'yAxis.title.text',
|
||||
value: '',
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '标题位置',
|
||||
type: 'select',
|
||||
field: 'yAxis_title_position',
|
||||
optionField: 'yAxis.title.position',
|
||||
value: 'end',
|
||||
tabName: 'custom',
|
||||
options: [
|
||||
{
|
||||
label: '上',
|
||||
value: 'end'
|
||||
},
|
||||
{
|
||||
label: '中',
|
||||
value: 'center'
|
||||
},
|
||||
{
|
||||
label: '下',
|
||||
value: 'start'
|
||||
}],
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '标题字体大小',
|
||||
type: 'inputNumber',
|
||||
field: 'yAxis_title_style_fontSize',
|
||||
optionField: 'yAxis.title.style.fontSize',
|
||||
value: 12,
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '标题颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'yAxis_title_style_fill',
|
||||
optionField: 'yAxis.title.style.fill',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#e9e9e9',
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '显示标签',
|
||||
type: 'switch',
|
||||
field: 'yAxis_label_style_opacity',
|
||||
optionField: 'yAxis.label.style.opacity',
|
||||
value: 1,
|
||||
active: 1,
|
||||
inactive: 0,
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '标签字体大小',
|
||||
type: 'inputNumber',
|
||||
field: 'yAxis_label_style_fontSize',
|
||||
optionField: 'yAxis.label.style.fontSize',
|
||||
value: 12,
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '标签颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'yAxis_label_style_fill',
|
||||
optionField: 'yAxis.label.style.fill',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#e9e9e9',
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '轴线宽度',
|
||||
type: 'inputNumber',
|
||||
field: 'yAxis_line_lineWidth',
|
||||
optionField: 'yAxis.line.style.lineWidth',
|
||||
value: 0,
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
{
|
||||
label: '轴线颜色',
|
||||
type: 'colorPicker',
|
||||
field: 'yAxis_line_stroke',
|
||||
optionField: 'yAxis.line.style.stroke',
|
||||
// 是否多选
|
||||
multiple: false,
|
||||
value: '#C9CDD4',
|
||||
tabName: 'custom',
|
||||
groupName: 'yAxis'
|
||||
},
|
||||
// 内边距 appendPadding
|
||||
{
|
||||
label: '图表边距',
|
||||
type: 'padding',
|
||||
field: 'appendPadding',
|
||||
optionField: 'appendPadding',
|
||||
value: [16, 16, 16, 16],
|
||||
tabName: 'custom',
|
||||
groupName: 'padding'
|
||||
}
|
||||
]
|
||||
|
||||
// 模拟数据
|
||||
const data = [
|
||||
{ Date: '2010-01', scales: 1998 },
|
||||
{ Date: '2010-02', scales: 1850 },
|
||||
{ Date: '2010-03', scales: 1720 },
|
||||
{ Date: '2010-04', scales: 1818 },
|
||||
{ Date: '2010-05', scales: 1920 },
|
||||
{ Date: '2010-06', scales: 1802 },
|
||||
{ Date: '2010-07', scales: 1945 },
|
||||
{ Date: '2010-08', scales: 1856 },
|
||||
{ Date: '2010-09', scales: 2107 },
|
||||
{ Date: '2010-10', scales: 2140 }
|
||||
]
|
||||
|
||||
const option = {
|
||||
// 数据将要放入到哪个字段中
|
||||
dataKey: 'data',
|
||||
// 图表内边距
|
||||
appendPadding: [0, 0, 0, 0],
|
||||
data,
|
||||
color: '',
|
||||
appendPadding: [16, 16, 16, 16], // 设置图标的边距
|
||||
xField: 'Date',
|
||||
yField: 'scales',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
lineWidth: 2,
|
||||
stroke: 'l(0) 0:#6b74e4 1:#4391f4'
|
||||
},
|
||||
xAxis: {
|
||||
title: {
|
||||
text: '',
|
||||
position: 'end',
|
||||
style: {
|
||||
fill: '#e9e9e9',
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
label: {
|
||||
autoRotate: false,
|
||||
autoHide: false,
|
||||
autoEllipsis: true,
|
||||
style: {
|
||||
fill: '#e9e9e9',
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
line: {
|
||||
style: {
|
||||
stroke: '#C9CDD4',
|
||||
lineWidth: 1
|
||||
}
|
||||
},
|
||||
tickLine: {
|
||||
style: {
|
||||
stroke: '#C9CDD4',
|
||||
lineWidth: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: '',
|
||||
position: 'end',
|
||||
autoRotate: false,
|
||||
// rotation: Math.PI / 2,
|
||||
style: {
|
||||
fill: '#8C8C8C',
|
||||
fontSize: 12
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
line: {
|
||||
style: {
|
||||
stroke: '#E5E6EB10',
|
||||
lineWidth: 1,
|
||||
lineDash: [4, 5],
|
||||
strokeOpacity: 0.7
|
||||
}
|
||||
}
|
||||
},
|
||||
label: {
|
||||
style: {
|
||||
fill: '#e9e9e9',
|
||||
fontSize: 12,
|
||||
opacity: 1
|
||||
}
|
||||
},
|
||||
line: {
|
||||
style: {
|
||||
stroke: '#C9CDD4',
|
||||
lineWidth: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
title,
|
||||
option,
|
||||
setting
|
||||
}
|
||||
|
||||
`
|
||||
660
frontend/packages/BizComponent/index.vue
Normal file
660
frontend/packages/BizComponent/index.vue
Normal file
@@ -0,0 +1,660 @@
|
||||
<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="../BigScreenDesign/images/app.png"
|
||||
alt="返回"
|
||||
@click="backManagement"
|
||||
>
|
||||
<span class="logo-text name-span">{{ form.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-btn-wrap">
|
||||
<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-left">
|
||||
<div class="code-tab">
|
||||
组件模板
|
||||
</div>
|
||||
<div
|
||||
class="code-tab-btn"
|
||||
@click="change('echart')"
|
||||
>
|
||||
echarts组件
|
||||
</div>
|
||||
<div
|
||||
class="code-tab-btn"
|
||||
@click="change('g2plot')"
|
||||
>
|
||||
G2Plot组件
|
||||
</div>
|
||||
<div
|
||||
class="code-tab-btn"
|
||||
@click="change('native')"
|
||||
>
|
||||
原生组件
|
||||
</div>
|
||||
<div
|
||||
class="code-tab-btn"
|
||||
@click="change('3DEchart')"
|
||||
>
|
||||
3D组件
|
||||
</div>
|
||||
</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">
|
||||
<div class="code-tab-header">
|
||||
<div class="code-tab">
|
||||
效果预览
|
||||
</div>
|
||||
<div class="upload-btn">
|
||||
<CusBtn
|
||||
:loading="loading"
|
||||
@click.native="createdImg()"
|
||||
>
|
||||
生成图片
|
||||
</CusBtn>
|
||||
</div>
|
||||
</div>
|
||||
<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 { toJpeg } from 'html-to-image'
|
||||
import CusBtn from 'data-room-ui/BigScreenDesign/BtnLoading'
|
||||
// import MonacoEditor from 'data-room-ui/MonacoEditor'
|
||||
import BizComponentPreview from './Preview'
|
||||
import { getBizComponentInfo, updateBizComponent } from 'data-room-ui/js/api/bigScreenApi'
|
||||
import { defaultSettingContent, defaultVueContent } from './config/defaultBizConfig'
|
||||
import { defaultEchartsSettingContent, defaultEchartsVueContent } from './config/defaultEchartsConfig'
|
||||
import { defaultG2SettingContent, defaultG2VueContent } from './config/defaultG2Config'
|
||||
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'
|
||||
|
||||
import {
|
||||
showSize,
|
||||
compressImage
|
||||
// dataURLtoBlob,
|
||||
// translateBlobToBase64
|
||||
} from 'data-room-ui/js/utils/compressImg'
|
||||
// import * as imageConversion from 'image-conversion'
|
||||
|
||||
export default {
|
||||
name: 'BizComponentDesign',
|
||||
components: {
|
||||
CusBtn,
|
||||
// MonacoEditor,
|
||||
codemirror,
|
||||
BizComponentPreview
|
||||
},
|
||||
props: {},
|
||||
data () {
|
||||
return {
|
||||
initialCoverPicture: '',
|
||||
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
|
||||
const type = this.$route.query.type
|
||||
if (code) {
|
||||
getBizComponentInfo(code).then(data => {
|
||||
this.initialCoverPicture = data.coverPicture || ''
|
||||
if (type && type === 'g2plot') {
|
||||
this.form = {
|
||||
...data,
|
||||
name: data.name,
|
||||
coverPicture: data.coverPicture,
|
||||
settingContent: data.settingContent || defaultG2SettingContent,
|
||||
vueContent: data.vueContent || defaultG2VueContent
|
||||
}
|
||||
} else if (type && type === 'echart') {
|
||||
this.form = {
|
||||
...data,
|
||||
name: data.name,
|
||||
coverPicture: data.coverPicture,
|
||||
settingContent: data.settingContent || defaultEchartsSettingContent,
|
||||
vueContent: data.vueContent || defaultEchartsVueContent
|
||||
}
|
||||
} else {
|
||||
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)
|
||||
})
|
||||
}
|
||||
},
|
||||
changeTemp (val) {
|
||||
if (val === 'g2plot') {
|
||||
this.form.settingContent = defaultG2SettingContent
|
||||
this.form.vueContent = defaultG2VueContent
|
||||
} else if (val === 'native') {
|
||||
this.form.settingContent = defaultSettingContent
|
||||
this.form.vueContent = defaultVueContent
|
||||
} else if (val === 'echart') {
|
||||
this.form.settingContent = defaultEchartsSettingContent
|
||||
this.form.vueContent = defaultEchartsVueContent
|
||||
}
|
||||
},
|
||||
change (val) {
|
||||
if (val === '3DEchart') {
|
||||
return this.$confirm('开发中。。。。', '提示', {
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
cancelButtonClass: 'cancel-btn',
|
||||
type: 'warning',
|
||||
customClass: 'bs-el-message-box'
|
||||
}).then(() => {
|
||||
}).catch((action) => {
|
||||
})
|
||||
}
|
||||
this.$confirm('确定替换为选中模板吗?未保存的代码将被覆盖!', '提示', {
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: '确定',
|
||||
showCancelButton: false,
|
||||
cancelButtonClass: 'cancel-btn',
|
||||
type: 'warning',
|
||||
customClass: 'bs-el-message-box'
|
||||
}).then(() => {
|
||||
this.changeTemp(val)
|
||||
}).catch((action) => {
|
||||
|
||||
})
|
||||
},
|
||||
// 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 () {
|
||||
// 给出一个确认框提示,提示如下确定返回主页面吗?未保存的配置将会丢失。3个按钮 : 留在页面 、离开页面、保存后离开页面
|
||||
this.$confirm('确定返回主页面吗?未保存的配置将会丢失。', '提示', {
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: '保存后离开页面',
|
||||
cancelButtonText: '离开页面',
|
||||
cancelButtonClass: 'cancel-btn',
|
||||
type: 'warning',
|
||||
customClass: 'bs-el-message-box'
|
||||
}).then(() => {
|
||||
this.save(true)
|
||||
}).catch((action) => {
|
||||
if (action === 'cancel') {
|
||||
this.pageJump()
|
||||
}
|
||||
})
|
||||
},
|
||||
async save (pageJump = false) {
|
||||
this.loading = true
|
||||
let dataUrl = ''
|
||||
const node = document.querySelector('.remote-preview-inner-wrap')
|
||||
// 获取node下的第一个子节点
|
||||
const childrenNode = node.children[0]
|
||||
try {
|
||||
dataUrl = await toJpeg(childrenNode, { quality: 0.2 })
|
||||
} catch (error) {
|
||||
console.info(error)
|
||||
}
|
||||
if (dataUrl) {
|
||||
if (showSize(dataUrl) > 200) {
|
||||
// const url = dataURLtoBlob(dataUrl)
|
||||
// 压缩到500KB,这里的500就是要压缩的大小,可自定义
|
||||
// imageConversion.compressAccurately(
|
||||
// url,
|
||||
// {
|
||||
// size: 200, // 图片大小压缩到100kb
|
||||
// width: 1280, // 宽度压缩到1280
|
||||
// height: 720 // 高度压缩到720
|
||||
// }
|
||||
// ).then((res) => {
|
||||
// translateBlobToBase64(res, (e) => {
|
||||
// this.form.coverPicture = e.result
|
||||
// })
|
||||
// })
|
||||
this.$message.info('由于封面图片过大,进行压缩中')
|
||||
this.form.coverPicture = await compressImage(dataUrl, { width: 1280, height: 720, size: 400, quality: 1 })
|
||||
} else {
|
||||
this.form.coverPicture = dataUrl
|
||||
}
|
||||
|
||||
} else {
|
||||
this.$message.warning('保存封面失败,将使用上次保存的封面')
|
||||
this.form.coverPicture = this.initialCoverPicture
|
||||
}
|
||||
|
||||
updateBizComponent(this.form).then(() => {
|
||||
this.$message({
|
||||
message: '保存成功',
|
||||
type: 'success',
|
||||
duration: 800,
|
||||
onClose: () => {
|
||||
// 此处写提示关闭后需要执行的函数
|
||||
if (pageJump) {
|
||||
this.pageJump()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.loading = false
|
||||
}).catch((error) => {
|
||||
console.info(error)
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
createdImg () {
|
||||
this.loading = true
|
||||
const node = document.querySelector('.remote-preview-inner-wrap')
|
||||
// 获取node下的第一个子节点
|
||||
const childrenNode = node.children[0]
|
||||
// 为childrenNode添加一个背景颜色
|
||||
childrenNode.style.backgroundColor = 'var(--bs-background-1)'
|
||||
toJpeg(childrenNode)
|
||||
.then((dataUrl) => {
|
||||
const link = document.createElement('a')
|
||||
link.download = `${this.form.name}.png`
|
||||
link.href = dataUrl
|
||||
link.click()
|
||||
link.addEventListener('click', () => {
|
||||
link.remove()
|
||||
})
|
||||
this.loading = false
|
||||
})
|
||||
.catch((error) => {
|
||||
console.info(error)
|
||||
this.loading = false
|
||||
// 判断的error.currentTarget是img标签,如果是的,就弹出消息说是图片跨域
|
||||
// 确认框
|
||||
this.$confirm('图片、视频资源跨域导致使用toDataURL API生成图片失败,请将资源上传到资源库,然后在组件中使用资源库中的图片资源,确保没有跨域问题。', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
showCancelButton: false,
|
||||
type: 'warning',
|
||||
customClass: 'bs-el-message-box'
|
||||
}).then(() => { }).catch(() => { })
|
||||
})
|
||||
},
|
||||
pageJump () {
|
||||
const data = { componentsManagementType: 'bizComponent' }
|
||||
this.$router.app.$options.globalData = data // 将数据存储在全局变量中
|
||||
this.$router.push({ path: window.BS_CONFIG?.routers?.componentUrl || '/big-screen-components' })
|
||||
}
|
||||
}
|
||||
}
|
||||
</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: 354px;
|
||||
padding: 5px 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-left {
|
||||
height: 100%;
|
||||
width: 450px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.code-tab-btn {
|
||||
// width: 90px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.code-tab {
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 120px;
|
||||
height: 100%;
|
||||
color: var(--bs-el-title);
|
||||
background: var(--bs-background-1);
|
||||
}
|
||||
}
|
||||
|
||||
.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% - 88px);
|
||||
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;
|
||||
|
||||
.code-tab-header {
|
||||
height: 40px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: var(--bs-background-2);
|
||||
|
||||
.code-tab {
|
||||
font-size: 14px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
width: 120px;
|
||||
margin-right: 20px;
|
||||
height: 100%;
|
||||
color: var(--bs-el-title);
|
||||
background: var(--bs-background-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</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;
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar {
|
||||
right: 0;
|
||||
top: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
/* Webkit浏览器滚动条样式 */
|
||||
.CodeMirror-vscrollbar::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
/* 滚动条宽度 */
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar::-webkit-scrollbar-thumb {
|
||||
background-color: #444851;
|
||||
/* 滚动条滑块颜色 */
|
||||
border-radius: 4px;
|
||||
/* 滚动条滑块圆角 */
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #444851;
|
||||
/* 滚动条滑块悬停时颜色 */
|
||||
}
|
||||
|
||||
/* Firefox和新版Chrome浏览器滚动条样式 */
|
||||
.CodeMirror-vscrollbar {
|
||||
scrollbar-width: thin;
|
||||
/* 滚动条宽度 */
|
||||
scrollbar-color: #444851 #444851;
|
||||
/* 滚动条颜色 */
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar::-webkit-scrollbar-thumb {
|
||||
background-color: #444851;
|
||||
/* 滚动条滑块颜色 */
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #444851;
|
||||
/* 滚动条滑块悬停时颜色 */
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user