Skip to content

Commit

Permalink
feat: 新增通用图表组件
Browse files Browse the repository at this point in the history
  • Loading branch information
BoBoooooo committed Jan 29, 2021
1 parent 624406a commit afd13cd
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 20 deletions.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="https://cdn.bootcdn.net/ajax/libs/ace/test/ace.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/4.8.0/echarts.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/echarts/5.0.1/echarts.min.js"></script>
<script src="<%= BASE_URL %>js/tinymce4.7.5/tinymce.min.js"></script>
</body>
</html>
10 changes: 10 additions & 0 deletions src/component/form-designer/src/GenerateFormItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,14 @@
:yUnit="widget.options.yUnit"
/>
</template>
<template v-if="widget.type === 'chart-common'">
<Echarts
:title="widget.name"
:height="widget.options.height"
:option="widget.options.option"
:loop="widget.options.loop">
</Echarts>
</template>
</el-form-item>
</template>

Expand All @@ -362,6 +370,7 @@ import GenerateSubForm from './components/SubForm/GenerateSubForm.vue';
import '@riophae/vue-treeselect/dist/vue-treeselect.css';
import lineChart from './components/Charts/lineChart.vue';
import pieChart from './components/Charts/pieChart.vue';
import Echarts from './components/Charts/Echarts.vue';


@Component({
Expand All @@ -370,6 +379,7 @@ import pieChart from './components/Charts/pieChart.vue';
Tinymce,
FileUpload,
GenerateSubForm,
Echarts,
pieChart,
lineChart,
CrudTable: () => import('@/component/crud-table/src/CrudTable.vue'),
Expand Down
38 changes: 21 additions & 17 deletions src/component/form-designer/src/WidgetConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@
</el-form-item>
<el-form-item :label="elementConfig.type === 'html' ?'HTML' : '图表数据'" v-if="elementConfig.type === 'html' || elementConfig.type.includes('chart-')">
<el-button style="float:right" icon="el-icon-check" size="mini" @click="saveJson">保存修改</el-button>
<div id="jsoneditor2" style="height: 300px;width: 100%;">{{ jsonTemplate }}</div>
<div id="jsoneditor2" ref="jsoneditor2" style="height: 300px;width: 100%;"></div>
</el-form-item>
<el-form-item label="是否空心" v-if="Object.keys(elementConfig.options).indexOf('hollow') >= 0">
<el-switch v-model="elementConfig.options.hollow"></el-switch>
</el-form-item>
<el-form-item label="高度" v-if="Object.keys(elementConfig.options).indexOf('height') >= 0">
<el-input size="mini" v-model="elementConfig.options.height"></el-input>
</el-form-item>
<el-form-item label="是否循环" v-if="Object.keys(elementConfig.options).indexOf('loop') >= 0">
<el-switch v-model="elementConfig.options.loop"></el-switch>
</el-form-item>
<!-- 柱状/折线图特有属性 -->
<template v-if="elementConfig.type == 'chart-line'">
Expand Down Expand Up @@ -540,7 +543,6 @@ export default {
data() {
return {
jsonTemplate: '',
htmlTemplate: '',
jsonEditor: null,
// 字典类型
dictType: [],
Expand Down Expand Up @@ -578,8 +580,11 @@ export default {
},
methods: {
saveJson() {
if (this.elementConfig.type === 'html') {
const { type } = this.elementConfig;
if (type === 'html') {
this.elementConfig.options.html = this.jsonEditor.getValue();
} else if (type === 'chart-common') {
this.elementConfig.options.option = JSON.parse(this.jsonEditor.getValue());
} else {
this.elementConfig.options.data = JSON.parse(this.jsonEditor.getValue());
}
Expand Down Expand Up @@ -698,21 +703,20 @@ export default {
// eslint-disable-next-line func-names
'elementConfig.type': function (val) {
if (val.includes('chart-')) {
this.jsonTemplate = JSON.stringify(this.elementConfig.options.data || '', null, 2);
this.$nextTick(() => {
setTimeout(() => {
this.jsonEditor = ace.edit('jsoneditor2');
this.jsonEditor.session.setMode('ace/mode/json');
}, 0);
});
const jsonData = val === 'chart-common' ? this.elementConfig.options.option : this.elementConfig.options.data;
const jsonString = JSON.stringify(jsonData || '', null, 2);
setTimeout(() => {
this.jsonEditor = ace.edit('jsoneditor2');
this.jsonEditor.session.setMode('ace/mode/json');
this.jsonEditor.setValue(jsonString);
}, 100);
} else if (val === 'html') {
this.jsonTemplate = JSON.stringify(this.elementConfig.options.html || '', null, 2);
this.$nextTick(() => {
setTimeout(() => {
this.jsonEditor = ace.edit('jsoneditor2');
this.jsonEditor.session.setMode('ace/mode/html');
}, 0);
});
const jsonString = JSON.stringify(this.elementConfig.options.html || '', null, 2);
setTimeout(() => {
this.jsonEditor = ace.edit('jsoneditor2');
this.jsonEditor.setValue(jsonString);
this.jsonEditor.session.setMode('ace/mode/html');
}, 100);
}
},
// eslint-disable-next-line func-names
Expand Down
12 changes: 11 additions & 1 deletion src/component/form-designer/src/WidgetFormItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,14 @@
:yUnit="element.options.yUnit"
/>
</template>

<template v-if="element.type === 'chart-common'">
<Echarts
:title="element.name"
:height="element.options.height"
:option="element.options.option"
:loop="element.options.loop">
</Echarts>
</template>
<div class="widget-view-action" v-if="selectWidget.key == element.key">
<i class="el-icon el-icon-document-copy" @click.stop="handleWidgetClone(index)"></i>
<i class="el-icon el-icon-delete-solid" @click.stop="handleWidgetDelete(index)"></i>
Expand All @@ -242,6 +249,8 @@
import Tinymce from './components/Tinymce'; // 富文本编辑器
import lineChart from './components/Charts/lineChart.vue';
import pieChart from './components/Charts/pieChart.vue';
import Echarts from './components/Charts/Echarts.vue';
export default {
name: 'WidgetFormItem',
Expand Down Expand Up @@ -271,6 +280,7 @@ export default {
Tinymce,
pieChart,
lineChart,
Echarts,
},
data() {
return {
Expand Down
176 changes: 176 additions & 0 deletions src/component/form-designer/src/components/Charts/Echarts.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<!--
* @file: 原生Echarts封装
* @author: BoBo
* @copyright: NanJing Anshare Tech .Com
* @Date: 2021-01-29 09:22:24
-->
<template>
<el-card shadow="hover" class="card" :body-style="{ height: height, width: '100%', padding: 0 }">
<div slot="header">
<span>{{ title }}</span>
</div>

<div class="native-echarts-wrap" @mouseover.stop="clearLoop" :class="className" :style="{ height: '100%', width: '100%', padding: '20px' }" @mouseout.stop="startLoop" ref="native-echarts-wrap">
<div ref="native-echarts" class="native-echarts"></div>
</div>
</el-card>
</template>

<script>
import { debounce } from '@/utils/utils';

export default {
name: 'Echarts',
props: {
// 配置项
option: {
type: Object,
required: false,
default() {
return {};
},
},
className: {
type: String,
},
height: {
type: String,
default: '300px',
},
title: {
type: String,
default: '',
},
map: {
type: Object,
default: null,
},
loop: {
type: Boolean,
default: false,
},
wait: {
type: Number,
default: 10000,
},
},

data() {
return {
chart: null,
resizeTimer: null,
loopTimer: [],
};
},
computed: {
eDom() {
return this.$refs['native-echarts'];
},
},
mounted() {
this.initEcharts();
this.resizeHanlder = () => {
if (this.chart) {
this.chart.resize();
}
};
window.addEventListener('resize', debounce(this.resizeHanlder));
},
methods: {
// echarts dom初始化
initEcharts() {
if (this.map) {
echarts.registerMap(this.map.type, this.map.json);
}
// 获得实例对象
this.chart = echarts.init(this.eDom);
// 事件注册
this.initEvent();
// 运行配置参数
this.setOption();
if (this.loop) {
this.initLoopFn();
}
},
initLoopFn() {
const timer = setInterval(() => {
this.chart.clear();
this.setOption(true);
}, this.wait);
this.loopTimer.push(timer);
},
clearLoop() {
this.loopTimer.forEach((timer) => {
window.clearInterval(timer);
});
this.loopTimer = [];
},
startLoop() {
const timer = setTimeout(() => {
this.initLoopFn();
});
this.loopTimer.push(timer);
},
initEvent() {
Object.keys(this.$listeners).forEach((eventName) => {
this.chart.on(eventName, this.$listeners[eventName]);
});
},
setOption(notMerge = this.notMerge) {
if (this.chart) {
this.chart.setOption(this.option, true);
// 此处绑定饼图点击事件,把图例内容抛出,用于数据钻取
this.chart.on('click', (obj) => {
this.$emit('click', obj);
});
this.chart.resize();
}
},
},
watch: {
option: {
deep: true,
handler() {
this.setOption(true);
},
},
loop(val) {
if (val) {
this.initLoopFn();
} else {
this.clearLoop();
}
},
},
beforeDestroy() {
if (!this.chart) {
return;
}
window.removeEventListener('resize', this.resizeHanlder);
this.chart.dispose();
this.chart = null;
if (this.loop) {
this.clearLoop();
}
},
};
</script>

<style lang="scss" scoped>
.card {
::v-deep {
.el-card__header {
padding: 5px 20px;
}
}
.native-echarts-wrap {
width: 100%;
height: 100%;
position: relative;
.native-echarts {
width: 100%;
height: 100%;
}
}
}
</style>
28 changes: 27 additions & 1 deletion src/component/form-designer/src/componentsConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ export const chartComponents = [
xUnit: '', // x轴单位
yUnit: '个', // y轴单位
hiddenLabel: true,
height: '300px',
height: '400px',
data: [
{
name: '商品一',
Expand All @@ -542,4 +542,30 @@ export const chartComponents = [
],
},
},
{
type: 'chart-common',
name: '通用图表',
icon: 'chart-bar',

options: {
className: '',
height: '400px',
hiddenLabel: true,
width: '100%',
loop: false,
option: {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [{
data: [150, 230, 224, 218, 135, 147, 260],
type: 'line',
}],
},
},
},
];
1 change: 1 addition & 0 deletions src/component/form-designer/src/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ import 'vue-awesome/icons/random';
import 'vue-awesome/icons/text-width';
import 'vue-awesome/icons/mouse-pointer';
import 'vue-awesome/icons/file-word';
import 'vue-awesome/icons/chart-bar';

0 comments on commit afd13cd

Please sign in to comment.