feat(视图): 组件样式,增加标题、图例的样式设置

This commit is contained in:
junjie 2021-03-22 13:44:07 +08:00
parent 7cd71cd601
commit 2fad127615
15 changed files with 346 additions and 15 deletions

View File

@ -28,14 +28,15 @@
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.2",
"umy-ui": "^1.1.6",
"vcolorpicker": "^1.1.0",
"vue": "2.6.10",
"vue-codemirror": "^4.0.6",
"vue-i18n": "7.3.2",
"vue-router": "3.0.6",
"vue-uuid": "2.0.2",
"vuedraggable": "^2.24.3",
"vuex": "3.1.0",
"webpack": "^4.46.0",
"vue-uuid": "2.0.2"
"webpack": "^4.46.0"
},
"devDependencies": {
"@babel/core": "^7.4.0-0",

View File

@ -638,7 +638,23 @@ export default {
pie_inner_radius: '内径',
pie_outer_radius: '外径',
funnel_width: '宽度',
line_smooth: '平滑折线'
line_smooth: '平滑折线',
title_style: '标题样式',
text_fontsize: '字体大小',
text_color: '字体颜色',
text_h_position: '水平位置',
text_v_position: '垂直位置',
text_pos_left: '左',
text_pos_center: '中',
text_pos_right: '右',
text_pos_top: '上',
text_pos_bottom: '下',
text_italic: '字体倾斜',
italic: '倾斜',
orient: '方向',
horizontal: '水平',
vertical: '垂直',
legend: '图例'
},
dataset: {
datalist: '数据集',

View File

@ -25,6 +25,10 @@ import UmyUi from 'umy-ui'
Vue.use(UmyUi)
import vcolorpicker from 'vcolorpicker'
Vue.use(vcolorpicker)
/**
* If you don't want to use mock-server
* you want to use MockJs for mock api

View File

@ -1,4 +1,5 @@
import { hexColorToRGBA } from '../util.js'
import { componentStyle } from '../common/common'
export function baseBarOption(chart_option, chart) {
// 处理shape attr
@ -35,6 +36,7 @@ export function baseBarOption(chart_option, chart) {
}
}
// console.log(chart_option);
componentStyle(chart_option, chart)
return chart_option
}
@ -86,6 +88,7 @@ export function horizontalBarOption(chart_option, chart) {
}
}
// console.log(chart_option);
componentStyle(chart_option, chart)
return chart_option
}

View File

@ -16,12 +16,27 @@ export const DEFAULT_SIZE = {
pieOuterRadius: 60,
funnelWidth: 80
}
export const DEFAULT_TITLE_STYLE = {
fontSize: '18',
color: '#000000',
hPosition: 'center',
vPosition: 'top',
isItalic: false
}
export const DEFAULT_LEGEND_STYLE = {
show: true,
hPosition: 'center',
vPosition: 'bottom',
orient: 'horizontal'
}
export const BASE_BAR = {
title: {
text: ''
},
tooltip: {},
legend: {
show: true,
type: 'scroll',
data: []
},
xAxis: {
@ -30,7 +45,12 @@ export const BASE_BAR = {
yAxis: {
type: 'value'
},
series: []
series: [],
dataZoom: [
{
type: 'inside'
}
]
}
export const HORIZONTAL_BAR = {
title: {
@ -38,6 +58,8 @@ export const HORIZONTAL_BAR = {
},
tooltip: {},
legend: {
show: true,
type: 'scroll',
data: []
},
xAxis: {
@ -46,7 +68,12 @@ export const HORIZONTAL_BAR = {
yAxis: {
data: []
},
series: []
series: [],
dataZoom: [
{
type: 'inside'
}
]
}
export const BASE_LINE = {
@ -55,6 +82,8 @@ export const BASE_LINE = {
},
tooltip: {},
legend: {
show: true,
type: 'scroll',
data: []
},
xAxis: {
@ -63,7 +92,12 @@ export const BASE_LINE = {
yAxis: {
type: 'value'
},
series: []
series: [],
dataZoom: [
{
type: 'inside'
}
]
}
export const BASE_PIE = {
@ -74,7 +108,10 @@ export const BASE_PIE = {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {},
legend: {
show: true,
type: 'scroll'
},
series: [
{
name: '',
@ -101,7 +138,8 @@ export const BASE_FUNNEL = {
trigger: 'item'
},
legend: {
// data: []
show: true,
type: 'scroll'
},
series: [
{

View File

@ -0,0 +1,20 @@
export function componentStyle(chart_option, chart) {
if (chart.customStyle) {
const customStyle = JSON.parse(chart.customStyle)
if (customStyle.text) {
chart_option.title.left = customStyle.text.hPosition
chart_option.title.top = customStyle.text.vPosition
const style = chart_option.title.textStyle ? chart_option.title.textStyle : {}
style.fontSize = customStyle.text.fontSize
style.color = customStyle.text.color
customStyle.text.isItalic ? style.fontStyle = 'italic' : style.fontStyle = 'normal'
chart_option.title.textStyle = style
}
if (customStyle.legend) {
chart_option.legend.show = customStyle.legend.show
chart_option.legend.left = customStyle.legend.hPosition
chart_option.legend.top = customStyle.legend.vPosition
chart_option.legend.orient = customStyle.legend.orient
}
}
}

View File

@ -1,4 +1,5 @@
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { componentStyle } from '../common/common'
export function baseFunnelOption(chart_option, chart) {
// 处理shape attr
@ -36,6 +37,7 @@ export function baseFunnelOption(chart_option, chart) {
}
}
// console.log(chart_option);
componentStyle(chart_option, chart)
return chart_option
}

View File

@ -1,4 +1,5 @@
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { componentStyle } from '../common/common'
export function baseLineOption(chart_option, chart) {
// 处理shape attr
@ -35,6 +36,7 @@ export function baseLineOption(chart_option, chart) {
}
}
// console.log(chart_option);
componentStyle(chart_option, chart)
return chart_option
}

View File

@ -1,4 +1,5 @@
import { hexColorToRGBA } from '@/views/chart/chart/util'
import { componentStyle } from '../common/common'
export function basePieOption(chart_option, chart) {
// 处理shape attr
@ -34,6 +35,7 @@ export function basePieOption(chart_option, chart) {
}
}
// console.log(chart_option);
componentStyle(chart_option, chart)
return chart_option
}

View File

@ -0,0 +1,103 @@
<template>
<div>
<div style="width:100%;height: 32px;margin:0;padding:0 4px;border-radius: 4px;border: 1px solid #DCDFE6;display: flex;align-items: center;">
<el-popover
placement="right"
width="400"
trigger="click"
>
<el-col>
<el-form ref="legendForm" :model="legendForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.show')" class="form-item">
<el-checkbox v-model="legendForm.show" @change="changeLegendStyle">{{ $t('chart.show') }}</el-checkbox>
</el-form-item>
<el-form-item :label="$t('chart.orient')" class="form-item">
<el-radio-group v-model="legendForm.orient" size="mini" @change="changeLegendStyle">
<el-radio-button label="horizontal">{{ $t('chart.horizontal') }}</el-radio-button>
<el-radio-button label="vertical">{{ $t('chart.vertical') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.text_h_position')" class="form-item">
<el-radio-group v-model="legendForm.hPosition" size="mini" @change="changeLegendStyle">
<el-radio-button label="left">{{ $t('chart.text_pos_left') }}</el-radio-button>
<el-radio-button label="center">{{ $t('chart.text_pos_center') }}</el-radio-button>
<el-radio-button label="right">{{ $t('chart.text_pos_right') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.text_v_position')" class="form-item">
<el-radio-group v-model="legendForm.vPosition" size="mini" @change="changeLegendStyle">
<el-radio-button label="top">{{ $t('chart.text_pos_top') }}</el-radio-button>
<el-radio-button label="center">{{ $t('chart.text_pos_center') }}</el-radio-button>
<el-radio-button label="bottom">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</el-radio-group>
</el-form-item>
</el-form>
</el-col>
<el-button slot="reference" size="mini" class="shape-item">{{ $t('chart.legend') }}<i class="el-icon-setting el-icon--right" /></el-button>
</el-popover>
</div>
</div>
</template>
<script>
import { DEFAULT_LEGEND_STYLE } from '../../chart/chart'
export default {
name: 'LegendSelector',
props: {
chart: {
type: Object,
required: true
}
},
data() {
return {
legendForm: JSON.parse(JSON.stringify(DEFAULT_LEGEND_STYLE))
}
},
watch: {
'chart': {
handler: function() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.customStyle) {
const customStyle = JSON.parse(chart.customStyle)
if (customStyle.legend) {
this.legendForm = customStyle.legend
}
}
}
}
},
mounted() {
},
methods: {
changeLegendStyle() {
this.$emit('onLegendChange', this.legendForm)
}
}
}
</script>
<style scoped lang="scss">
.shape-item{
padding: 6px;
border: none;
}
.form-item-slider>>>.el-form-item__label{
font-size: 12px;
line-height: 38px;
}
.form-item>>>.el-form-item__label{
font-size: 12px;
}
.el-select-dropdown__item{
padding: 0 20px;
}
span{
font-size: 12px
}
.el-form-item{
margin-bottom: 6px;
}
</style>

View File

@ -0,0 +1,117 @@
<template>
<div>
<div style="width:100%;height: 32px;margin:0;padding:0 4px;border-radius: 4px;border: 1px solid #DCDFE6;display: flex;align-items: center;">
<el-popover
placement="right"
width="400"
trigger="click"
>
<el-col>
<el-form ref="titleForm" :model="titleForm" label-width="80px" size="mini">
<el-form-item :label="$t('chart.text_fontsize')" class="form-item">
<el-select v-model="titleForm.fontSize" :placeholder="$t('chart.text_fontsize')" size="mini" @change="changeTitleStyle">
<el-option v-for="option in fontSize" :key="option.value" :label="option.name" :value="option.value" />
</el-select>
</el-form-item>
<el-form-item :label="$t('chart.text_color')" class="form-item">
<colorPicker v-model="titleForm.color" style="padding-top: 6px;cursor: pointer;z-index: 999" @change="changeTitleStyle" />
</el-form-item>
<el-form-item :label="$t('chart.text_h_position')" class="form-item">
<el-radio-group v-model="titleForm.hPosition" size="mini" @change="changeTitleStyle">
<el-radio-button label="left">{{ $t('chart.text_pos_left') }}</el-radio-button>
<el-radio-button label="center">{{ $t('chart.text_pos_center') }}</el-radio-button>
<el-radio-button label="right">{{ $t('chart.text_pos_right') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.text_v_position')" class="form-item">
<el-radio-group v-model="titleForm.vPosition" size="mini" @change="changeTitleStyle">
<el-radio-button label="top">{{ $t('chart.text_pos_top') }}</el-radio-button>
<el-radio-button label="center">{{ $t('chart.text_pos_center') }}</el-radio-button>
<el-radio-button label="bottom">{{ $t('chart.text_pos_bottom') }}</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('chart.text_italic')" class="form-item">
<el-checkbox v-model="titleForm.isItalic" @change="changeTitleStyle">{{ $t('chart.italic') }}</el-checkbox>
</el-form-item>
</el-form>
</el-col>
<el-button slot="reference" size="mini" class="shape-item">{{ $t('chart.title') }}<i class="el-icon-setting el-icon--right" /></el-button>
</el-popover>
</div>
</div>
</template>
<script>
import { DEFAULT_TITLE_STYLE } from '../../chart/chart'
export default {
name: 'TitleSelector',
props: {
chart: {
type: Object,
required: true
}
},
data() {
return {
titleForm: JSON.parse(JSON.stringify(DEFAULT_TITLE_STYLE)),
fontSize: []
}
},
watch: {
'chart': {
handler: function() {
const chart = JSON.parse(JSON.stringify(this.chart))
if (chart.customStyle) {
const customStyle = JSON.parse(chart.customStyle)
if (customStyle.text) {
this.titleForm = customStyle.text
}
}
}
}
},
mounted() {
this.init()
},
methods: {
init() {
const arr = []
for (let i = 10; i <= 60; i = i + 2) {
arr.push({
name: i + '',
value: i + ''
})
}
this.fontSize = arr
},
changeTitleStyle() {
this.$emit('onTextChange', this.titleForm)
}
}
}
</script>
<style scoped lang="scss">
.shape-item{
padding: 6px;
border: none;
}
.form-item-slider>>>.el-form-item__label{
font-size: 12px;
line-height: 38px;
}
.form-item>>>.el-form-item__label{
font-size: 12px;
}
.el-select-dropdown__item{
padding: 0 20px;
}
span{
font-size: 12px
}
.el-form-item{
margin-bottom: 6px;
}
</style>

View File

@ -26,7 +26,6 @@
<el-button slot="reference" size="mini" class="shape-item">{{ $t('chart.color') }}<i class="el-icon-setting el-icon--right" /></el-button>
</el-popover>
<!--todo other color attr-->
</div>
</div>
</template>

View File

@ -65,7 +65,6 @@
<el-button slot="reference" size="mini" class="shape-item">{{ $t('chart.size') }}<i class="el-icon-setting el-icon--right" /></el-button>
</el-popover>
<!--todo other size attr-->
</div>
</div>
</template>

View File

@ -211,7 +211,7 @@
<script>
import { post } from '@/api/chart/chart'
import TableSelector from '../view/TableSelector'
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '../chart/chart'
import { DEFAULT_COLOR_CASE, DEFAULT_LEGEND_STYLE, DEFAULT_SIZE, DEFAULT_TITLE_STYLE } from '../chart/chart'
export default {
name: 'Group',
@ -509,6 +509,10 @@ export default {
color: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE
})
view.customStyle = JSON.stringify({
text: DEFAULT_TITLE_STYLE,
legend: DEFAULT_LEGEND_STYLE
})
post('/chart/view/save', view).then(response => {
this.selectTableFlag = false
this.$store.dispatch('chart/setTableId', null)

View File

@ -97,7 +97,10 @@
<color-selector class="attr-selector" :chart="chart" @onColorChange="onColorChange" />
<size-selector class="attr-selector" :chart="chart" @onSizeChange="onSizeChange" />
</el-tab-pane>
<el-tab-pane :label="$t('chart.module_style')" class="padding-lr">TODO</el-tab-pane>
<el-tab-pane :label="$t('chart.module_style')" class="padding-lr">
<title-selector class="attr-selector" :chart="chart" @onTextChange="onTextChange" />
<legend-selector class="attr-selector" :chart="chart" @onLegendChange="onLegendChange" />
</el-tab-pane>
</el-tabs>
</div>
<div style="height: 30%;overflow:auto;border-top: 1px solid #e6e6e6" class="padding-lr">
@ -154,14 +157,16 @@ import draggable from 'vuedraggable'
import DimensionItem from '../components/DimensionItem'
import QuotaItem from '../components/QuotaItem'
import ChartComponent from '../components/ChartComponent'
// shape attr
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE } from '../chart/chart'
// shape attr,component style
import { DEFAULT_COLOR_CASE, DEFAULT_SIZE, DEFAULT_TITLE_STYLE, DEFAULT_LEGEND_STYLE } from '../chart/chart'
import ColorSelector from '../components/shape_attr/ColorSelector'
import SizeSelector from '../components/shape_attr/SizeSelector'
import TitleSelector from '../components/component_style/TitleSelector'
import LegendSelector from '../components/component_style/LegendSelector'
export default {
name: 'ChartEdit',
components: { SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
components: { LegendSelector, TitleSelector, SizeSelector, ColorSelector, ChartComponent, QuotaItem, DimensionItem, draggable },
data() {
return {
table: {},
@ -176,6 +181,10 @@ export default {
customAttr: {
color: DEFAULT_COLOR_CASE,
size: DEFAULT_SIZE
},
customStyle: {
text: DEFAULT_TITLE_STYLE,
legend: DEFAULT_LEGEND_STYLE
}
},
//
@ -263,6 +272,7 @@ export default {
view.xaxis = JSON.stringify(view.xaxis)
view.yaxis = JSON.stringify(view.yaxis)
view.customAttr = JSON.stringify(view.customAttr)
view.customStyle = JSON.stringify(view.customStyle)
post('/chart/view/save', view).then(response => {
// this.get(response.data.id);
this.getData(response.data.id)
@ -280,6 +290,7 @@ export default {
this.view.xaxis = this.view.xaxis ? JSON.parse(this.view.xaxis) : []
this.view.yaxis = this.view.yaxis ? JSON.parse(this.view.yaxis) : []
this.view.customAttr = this.view.customAttr ? JSON.parse(this.view.customAttr) : {}
this.view.customStyle = this.view.customStyle ? JSON.parse(this.view.customStyle) : {}
// echart
this.chart = response.data
})
@ -386,6 +397,16 @@ export default {
onSizeChange(val) {
this.view.customAttr.size = val
this.save()
},
onTextChange(val) {
this.view.customStyle.text = val
this.save()
},
onLegendChange(val) {
this.view.customStyle.legend = val
this.save()
}
}
}