feat: 新增图表独立配置混合

This commit is contained in:
mtruning 2022-02-26 17:38:24 +08:00
parent f8095ca52a
commit 4e9e492c29
43 changed files with 271 additions and 170 deletions

View File

@ -1,3 +0,0 @@
import AppleControlBtn from './index.vue';
export { AppleControlBtn };

View File

@ -1,6 +1,6 @@
<template>
<n-divider style="margin: 10px 0;" />
<n-collapse arrow-placement="right" :default-expanded-names="name" accordion>
<n-collapse arrow-placement="right" :default-expanded-names="expanded ? name : null" accordion>
<!-- 右侧 -->
<template #header-extra>
<div @click="click">
@ -19,6 +19,11 @@ defineProps({
name: {
type: String,
required: true
},
expanded: {
type: Boolean,
required: false,
default: false
}
})

View File

@ -0,0 +1,3 @@
import MacOsControlBtn from './index.vue';
export { MacOsControlBtn };

View File

@ -6,49 +6,55 @@ import cloneDeep from 'lodash/cloneDeep'
export const includes = ['legend', 'xAxis', 'yAxis']
// 图表配置项
const option = echartOptionProfixHandle(
{
tooltip: {
export const option = {
tooltip: {
show: true,
trigger: 'axis',
axisPointer: {
show: true,
trigger: 'axis',
axisPointer: {
show: true,
type: 'shadow'
}
},
legend: {
show: true,
},
xAxis: {
show: true,
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
show: true,
type: 'value'
},
series: [
{
name: 'data1',
type: 'bar',
data: [120, 200, 150, 80, 70, 110, 130]
},
{
name: 'data2',
type: 'bar',
data: [130, 130, 312, 268, 155, 117, 160]
}
]
type: 'shadow'
}
},
includes
)
legend: {
show: true,
},
xAxis: {
show: true,
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
show: true,
type: 'value'
},
series: [
{
name: 'data1',
type: 'bar',
barWidth: null,
itemStyle: {
color: null,
borderRadius: 0
},
data: [120, 200, 150, 80, 70, 110, 130]
},
{
name: 'data2',
type: 'bar',
barWidth: null,
itemStyle: {
color: null,
borderRadius: 0
},
data: [130, 130, 312, 268, 155, 117, 160]
}
]
}
export default class Config extends publicConfig
implements CreateComponentType {
public key = BarCommonConfig.key
public chartConfig = omit(cloneDeep(BarCommonConfig), ['node'])
// 图表配置项
public option = option
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -1,7 +1,45 @@
<template>
<div>配置项目</div>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-数据-${index+1}`" :expanded="true">
<SettingItemBox name="图形">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color" />
</SettingItem>
<SettingItem>
<n-button size="small" @click="item.itemStyle.color = null">恢复默认</n-button>
</SettingItem>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
/>
</SettingItem>
<SettingItem name="圆角">
<n-input-number
v-model:value="item.itemStyle.borderRadius"
:min="0"
size="small"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/ChartItemSetting/index'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const seriesList = computed(() => {
return props.optionData.series
})
</script>

View File

@ -1,4 +1,5 @@
import BarCommon from './index.vue'
import Configuration from './config.vue'
import image from '@/assets/images/chart/charts/bar_x.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@ -10,5 +11,6 @@ export const BarCommonConfig: ConfigType = {
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
node: BarCommon,
conNode: () => Configuration,
image: image,
}

View File

@ -6,48 +6,55 @@ import cloneDeep from 'lodash/cloneDeep'
export const includes = ['legend', 'xAxis', 'yAxis']
const option = echartOptionProfixHandle(
{
tooltip: {
export const option = {
tooltip: {
show: true,
trigger: 'axis',
axisPointer: {
show: true,
trigger: 'axis',
axisPointer: {
show: true,
type: 'shadow'
}
type: 'shadow',
},
legend: {
show: true,
},
xAxis: {
show: true,
type: 'value',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
show: true,
type: 'category'
},
series: [
{
name: 'data1',
type: 'bar',
data: [120, 200, 150, 80, 70, 110, 130]
},
{
name: 'data2',
type: 'bar',
data: [130, 130, 312, 268, 155, 117, 160]
}
]
},
includes
)
legend: {
show: true,
},
xAxis: {
show: true,
type: 'value',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
show: true,
type: 'category',
},
series: [
{
name: 'data1',
type: 'bar',
barWidth: null,
itemStyle: {
color: null,
borderRadius: 0,
},
data: [120, 200, 150, 80, 70, 110, 130],
},
{
name: 'data2',
type: 'bar',
barWidth: null,
itemStyle: {
color: null,
borderRadius: 0,
},
data: [130, 130, 312, 268, 155, 117, 160],
},
],
}
export default class Config extends publicConfig
implements CreateComponentType {
public key: string = BarCrossrangefig.key
public chartConfig = omit(cloneDeep(BarCrossrangefig), ['node'])
// 图表配置项
public option = option
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -1,7 +1,45 @@
<template>
<div>配置项目</div>
<CollapseItem v-for="(item, index) in seriesList" :key="index" :name="`柱状图-数据-${index+1}`" :expanded="true">
<SettingItemBox name="图形">
<SettingItem name="颜色">
<n-color-picker size="small" :modes="['hex']" v-model:value="item.itemStyle.color" />
</SettingItem>
<SettingItem>
<n-button size="small" @click="item.itemStyle.color = null">恢复默认</n-button>
</SettingItem>
<SettingItem name="宽度">
<n-input-number
v-model:value="item.barWidth"
:min="1"
:max="100"
size="small"
placeholder="自动计算"
/>
</SettingItem>
<SettingItem name="圆角">
<n-input-number
v-model:value="item.itemStyle.borderRadius"
:min="0"
size="small"
/>
</SettingItem>
</SettingItemBox>
</CollapseItem>
</template>
<script setup lang="ts">
import { PropType, computed } from 'vue'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/ChartItemSetting/index'
import { option } from './config'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
const seriesList = computed(() => {
return props.optionData.series
})
</script>

View File

@ -1,4 +1,5 @@
import BarCrossrange from './index.vue'
import Configuration from './config.vue'
import image from '@/assets/images/chart/charts/bar_y.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@ -10,5 +11,6 @@ export const BarCrossrangefig: ConfigType = {
categoryName: ChatCategoryEnumName.BAR,
package: PackagesCategoryEnum.CHARTS,
node: BarCrossrange,
conNode: () => Configuration,
image: image
}

View File

@ -5,7 +5,7 @@ import omit from 'lodash/omit'
export const includes = ['legend', 'xAxis', 'yAxis']
const options = echartOptionProfixHandle({
const option = {
legend: {
show: true,
},
@ -23,18 +23,13 @@ const options = echartOptionProfixHandle({
name: 'data1',
type: 'line',
data: [120, 200, 150, 80, 70, 110, 130]
},
{
name: 'data2',
type: 'line',
data: [130, 130, 312, 268, 155, 117, 160]
}
]
}, includes)
}
export default class Config extends publicConfig implements CreateComponentType {
public key: string = LineCommonConfig.key
public chartConfig = omit(LineCommonConfig, ['node'])
// 图表配置项
public option = options
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -1,5 +1,4 @@
<template>
<div>配置项目</div>
</template>
<script setup lang="ts">

View File

@ -1,4 +1,5 @@
import LineCommon from './index.vue'
import Configuration from './config.vue'
import image from '@/assets/images/chart/charts/line.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@ -10,5 +11,6 @@ export const LineCommonConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
node: LineCommon,
conNode: () => Configuration,
image: image
}

View File

@ -1,5 +1,4 @@
<template>
<div>配置项目</div>
</template>
<script setup lang="ts">

View File

@ -1,4 +1,5 @@
import LineGradientSingle from './index.vue'
import Configuration from './config.vue'
import image from '@/assets/images/chart/charts/line_gradient_single.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@ -10,5 +11,6 @@ export const LineGradientSingleConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
node: LineGradientSingle,
conNode: () => Configuration,
image: image
}

View File

@ -6,72 +6,69 @@ import omit from 'lodash/omit'
export const includes = ['legend', 'xAxis', 'yAxis']
const options = echartOptionProfixHandle(
{
legend: {
show: true
const option = {
legend: {
show: true,
},
xAxis: {
show: true,
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
show: true,
type: 'value',
},
series: [
{
name: 'data1',
type: 'line',
smooth: false,
data: [120, 200, 150, 80, 70, 110, 130],
areaStyle: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(25,163,223,.3)',
},
{
offset: 1,
color: 'rgba(25,163,223, 0)',
},
]),
},
},
xAxis: {
show: true,
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
show: true,
type: 'value'
},
series: [
{
name: 'data1',
type: 'line',
smooth: false,
data: [120, 200, 150, 80, 70, 110, 130],
areaStyle: {
{
name: 'data2',
type: 'line',
smooth: false,
areaStyle: {
normal: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(25,163,223,.3)'
color: 'rgba(0,202,149,0.3)',
},
{
offset: 1,
color: 'rgba(25,163,223, 0)'
}
])
}
},
{
name: 'data2',
type: 'line',
smooth: false,
areaStyle: {
normal: {
opacity: 0.8,
color: new graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(0,202,149,0.3)'
},
{
offset: 1,
color: 'rgba(0,202,149,0)'
}
]),
shadowColor: 'rgba(0,202,149, 0.9)',
shadowBlur: 20
}
color: 'rgba(0,202,149,0)',
},
]),
shadowColor: 'rgba(0,202,149, 0.9)',
shadowBlur: 20,
},
data: [130, 130, 312, 268, 155, 117, 160]
}
]
},
includes
)
},
data: [130, 130, 312, 268, 155, 117, 160],
},
],
}
export default class Config extends publicConfig
implements CreateComponentType {
public key: string = LineGradientsConfig.key
public chartConfig = omit(LineGradientsConfig, ['node'])
// 图表配置项
public option = options
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -1,5 +1,4 @@
<template>
<div>配置项目</div>
</template>
<script setup lang="ts">

View File

@ -1,4 +1,5 @@
import LineGradients from './index.vue'
import Configuration from './config.vue'
import image from '@/assets/images/chart/charts/line_gradient2.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@ -10,5 +11,6 @@ export const LineGradientsConfig: ConfigType = {
categoryName: ChatCategoryEnumName.LINE,
package: PackagesCategoryEnum.CHARTS,
node: LineGradients,
conNode: () => Configuration,
image: image
}

View File

@ -5,7 +5,7 @@ import omit from 'lodash/omit'
export const includes = ['legend']
const option = echartOptionProfixHandle({
const option = {
tooltip: {
show: true,
trigger: 'item'
@ -17,7 +17,7 @@ const option = echartOptionProfixHandle({
{
name: 'Access From',
type: 'pie',
radius: ['40%', '70%'],
radius: ['40%', '65%'],
center: ['50%', '60%'],
avoidLabelOverlap: false,
itemStyle: {
@ -49,7 +49,7 @@ const option = echartOptionProfixHandle({
]
}
]
}, includes)
}
export default class Config extends publicConfig implements CreateComponentType {
public key: string = PieCommonConfig.key
@ -57,5 +57,5 @@ export default class Config extends publicConfig implements CreateComponentType
public chartConfig = omit(PieCommonConfig, ['node'])
// 图表配置项
public option = option
public option = echartOptionProfixHandle(option, includes)
}

View File

@ -1,5 +1,4 @@
<template>
<div>配置项目</div>
</template>
<script setup lang="ts">

View File

@ -1,4 +1,5 @@
import PieCommon from './index.vue'
import Configuration from './config.vue'
import image from '@/assets/images/chart/charts/pie.png'
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
@ -10,5 +11,6 @@ export const PieCommonConfig: ConfigType = {
categoryName: ChatCategoryEnumName.PIE,
package: PackagesCategoryEnum.CHARTS,
node: PieCommon,
conNode: () => Configuration,
image
}

View File

@ -9,6 +9,7 @@ export type ConfigType = {
categoryName: string
package: string
node: Component
conNode: () => Component
image: string | (() => Promise<typeof import('*.png')>)
}

View File

@ -6,7 +6,7 @@ import { packagesList } from '@/packages/index'
export const usePackagesStore = defineStore({
id: 'usePackagesStore',
state: (): PackagesStoreType => ({
packagesList
packagesList: Object.freeze(packagesList)
}),
getters: {
getPackagesList(): PackagesType {

View File

@ -5,7 +5,7 @@ import { AsyncLoading, AsyncSkeletonLoading } from '@/components/LoadingComponen
* *
*/
export const componentInstall = <T> (key:string, node: T) => {
if(!window['$vue'].component(key)) {
if(!window['$vue'].component(key) && key && node) {
window['$vue'].component(key, node)
}
}

View File

@ -2,7 +2,7 @@ import * as CryptoJS from 'crypto-ts'
export default {
AES_KEY: 'mt',
encode(data: string): string {
cryptoEncode(data: string): string {
if (typeof data !== 'string') return ''
// 加密
const key = CryptoJS.enc.Utf8.parse(this.AES_KEY)
@ -15,7 +15,7 @@ export default {
return encryptedData.toString()
},
// 解密
decode(data: string): string {
cryptoDecode(data: string): string {
if (typeof data !== 'string') return ''
const encryptedHexStr = CryptoJS.enc.Utf8.parse(data)
const encryptedBase64Str = CryptoJS.enc.Utf8.stringify(encryptedHexStr)

View File

@ -7,7 +7,7 @@ import throttle from 'lodash/throttle'
* * ID
* @param { Number } randomLength
*/
export function getUUID(randomLength = 10) {
export const getUUID = (randomLength = 10) =>{
return Number(
Math.random().toString().substr(2, randomLength) + Date.now()
).toString(36)

View File

@ -9,7 +9,7 @@
@dragstart="handleDragStart($event, item)"
>
<div class="list-header">
<AppleControlBtn :mini="true" :disabled="true"></AppleControlBtn>
<MacOsControlBtn :mini="true" :disabled="true"></MacOsControlBtn>
<n-text class="list-header-text" depth="3">{{ item.title }}</n-text>
</div>
<div class="list-center go-flex-center">
@ -26,7 +26,8 @@
</template>
<script setup lang="ts">
import { AppleControlBtn } from '@/components/AppleControlBtn/index'
import { PropType } from 'vue'
import { MacOsControlBtn } from '@/components/MacOsControlBtn/index'
import { requireFallbackImg, componentInstall } from '@/utils'
import { DragKeyEnum } from '@/enums/editPageEnum'
import { ConfigType } from '@/packages/index.d'
@ -34,13 +35,14 @@ import omit from 'lodash/omit'
defineProps({
menuOptions: {
type: Array,
type: Array as PropType<ConfigType[]>,
default: () => []
}
})
//
const handleDragStart = (e: DragEvent, item: ConfigType) => {
//
componentInstall(item.key, item.node)
//
e!.dataTransfer!.setData(DragKeyEnum.DROG_KEY, JSON.stringify(omit(item, ['node', 'image'])))

View File

@ -17,12 +17,12 @@ const {
// 图表
const { getPackagesList } = usePackagesStore()
const menuOptions = shallowReactive<{
const menuOptions:{
key: string
icon: ReturnType<typeof renderIcon>
label: ReturnType<typeof renderLang>
list: PackagesType
}[]>([])
}[] = []
const packagesListObj = {
[PackagesCategoryEnum.CHARTS]: {

View File

@ -43,7 +43,6 @@
</template>
<script setup lang="ts">
import { reactive, ref, toRefs } from 'vue'
import { ContentBox } from '../ContentBox/index'
import { OptionContent } from './components/OptionContent'
import {

View File

@ -1,5 +1,6 @@
<template>
<div class="go-chart-content-details" v-if="targetData">
<!-- 名称 -->
<SettingItemBox name="名称">
<n-input
type="text"
@ -10,7 +11,11 @@
v-model:value="targetData.chartConfig.title"
/>
</SettingItemBox>
<!-- 位置 -->
<PositionSetting :chartAttr="targetData.attr" />
<!-- 自定义配置项 -->
<component :is="targetData.chartConfig.conNode()" :optionData="targetData.option"></component>
<!-- 全局设置 -->
<GlobalSetting :optionData="targetData.option" :in-chart="true" />
</div>
</template>

View File

@ -0,0 +1,3 @@
import ContentConfigurations from './index.vue'
export { ContentConfigurations }

View File

@ -1,3 +0,0 @@
import ContentDetails from './index.vue'
export { ContentDetails }

View File

@ -11,7 +11,7 @@
</template>
<script setup lang="ts">
import { ref, computed, PropType, h } from 'vue';
import { ref, computed, PropType } from 'vue';
import { useChartEditStoreStore } from '@/store/modules/chartEditStore/chartEditStore'
import { useDesignStore } from '@/store/modules/designStore/designStore'
import { CreateComponentType } from '@/packages/index.d'

View File

@ -61,7 +61,7 @@ const btnList = reactive<ItemType[]>([
])
// store ContentDetails collapsed
// store ContentConfigurations collapsed
const styleHandle = (item: ItemType) => {
if (item.key === ChartLayoutStoreEnum.DETAILS) {
return item.select ? '' : 'success'

View File

@ -16,7 +16,7 @@
<n-layout-content content-style="overflow:hidden; display: flex">
<ContentCharts />
<ContentLayers />
<ContentDetails />
<ContentConfigurations />
</n-layout-content>
</n-layout>
</div>
@ -60,8 +60,8 @@ const ContentLayers = loadAsyncComponent(() =>
const ContentCharts = loadAsyncComponent(() =>
import('./ContentCharts/index.vue')
)
const ContentDetails = loadAsyncComponent(() =>
import('./ContentDetails/index.vue')
const ContentConfigurations = loadAsyncComponent(() =>
import('./ContentConfigurations/index.vue')
)
//

View File

@ -4,7 +4,7 @@
<div class="list-content">
<!-- 顶部按钮 -->
<div class="list-content-top">
<AppleControlBtn
<MacOsControlBtn
class="top-btn"
:hidden="['remove']"
@close="deleteHanlde"
@ -85,7 +85,7 @@
import { reactive, ref } from 'vue'
import { renderIcon, renderLang, requireUrl, requireFallbackImg } from '@/utils'
import { icon } from '@/plugins'
import { AppleControlBtn } from '@/components/AppleControlBtn'
import { MacOsControlBtn } from '@/components/MacOsControlBtn'
const {
EllipsisHorizontalCircleSharpIcon,

View File

@ -17,7 +17,7 @@
</n-space>
<!-- 顶部按钮 -->
<n-space class="list-content-top">
<AppleControlBtn
<MacOsControlBtn
:narrow="true"
:hidden="['close']"
@remove="closeHandle"
@ -78,7 +78,7 @@
import { reactive } from 'vue'
import { renderIcon, renderLang, requireUrl } from '@/utils'
import { icon } from '@/plugins'
import { AppleControlBtn } from '@/components/AppleControlBtn'
import { MacOsControlBtn } from '@/components/MacOsControlBtn'
const { HammerIcon } = icon.ionicons5