diff --git a/core/core-frontend/package.json b/core/core-frontend/package.json index 123bfca..55fc8bd 100644 --- a/core/core-frontend/package.json +++ b/core/core-frontend/package.json @@ -23,6 +23,7 @@ "@form-create/designer": "^3.2.11", "@form-create/element-ui": "^3.2.22", "@form-create/vant": "^3.2.25", + "@intlify/unplugin-vue-i18n": "latest", "@monaco-editor/loader": "^1.5.0", "@npkg/tinymce-plugins": "^0.0.7", "@tinymce/tinymce-vue": "^5.1.0", diff --git a/core/core-frontend/src/components/data-visualization/DvToolbar.vue b/core/core-frontend/src/components/data-visualization/DvToolbar.vue index 973e184..cded59e 100644 --- a/core/core-frontend/src/components/data-visualization/DvToolbar.vue +++ b/core/core-frontend/src/components/data-visualization/DvToolbar.vue @@ -49,6 +49,7 @@ import DeAppApply from '@/views/common/DeAppApply.vue' import { useEmitt } from '@/hooks/web/useEmitt' import { useUserStoreWithOut } from '@/store/modules/user' import TabsGroup from '@/custom-component/component-group/TabsGroup.vue' +import TreeGroup from '@/custom-component/component-group/TreeGroup.vue' import { useI18n } from '@/hooks/web/useI18n' import { updatePublishStatus } from '@/api/visualization/dataVisualization' import { useRoute } from 'vue-router' @@ -433,6 +434,9 @@ const fullScreenPreview = () => { + + + +import dvTabShow from '@/assets/svg/dv-tab-show.svg' +import { toRefs } from 'vue' +import eventBus from '@/utils/eventBus' +import DragComponent from '@/custom-component/component-group/DragComponent.vue' +import { commonHandleDragEnd, commonHandleDragStart } from '@/utils/canvasUtils' + +const props = defineProps({ + propValue: { + type: Array, + default: () => [] + }, + dvModel: { + type: String, + default: 'dv' + }, + element: { + type: Object, + default() { + return { + propValue: null + } + } + }, + themes: { + type: String, + default: 'dark' + } +}) + +const { dvModel } = toRefs(props) +const newComponent = () => { + eventBus.emit('handleNew', { componentName: 'DeTree', innerType: 'DeTree' }) +} + +const handleDragStart = e => { + commonHandleDragStart(e, dvModel.value) +} + +const handleDragEnd = e => { + commonHandleDragEnd(e, dvModel.value) +} + + + + + diff --git a/core/core-frontend/src/custom-component/component-list.ts b/core/core-frontend/src/custom-component/component-list.ts index d85120f..c0f1c3b 100644 --- a/core/core-frontend/src/custom-component/component-list.ts +++ b/core/core-frontend/src/custom-component/component-list.ts @@ -579,6 +579,42 @@ const list = [ textDecoration: 'none' } }, + { + component: 'DeTree', + name: t('树'), + label: t('树'), + propValue: [ + { + name: 'tab', + title: t('visualization.new_tab'), + componentData: [], + closable: true + } + ], + icon: 'dv-tab', + innerType: '', + editing: false, + canvasActive: false, + x: 1, + y: 1, + sizeX: 36, + sizeY: 14, + style: { + width: 600, + height: 300, + fontSize: 16, + activeFontSize: 18, + headHorizontalPosition: 'left', + headFontColor: '#000000', + headFontActiveColor: '#000000', + titleHide: false, + showTabTitle: true, + // #13540 + fontWeight: 'normal', + fontStyle: 'normal', + textDecoration: 'none' + } + }, { component: 'ScrollText', name: t('visualization.scroll_text'), @@ -631,6 +667,10 @@ export function findNewComponentFromList( newComponent.propValue[0].name = guid() newComponent['titleBackground'] = deepCopy(COMMON_TAB_TITLE_BACKGROUND) } + if (comp.component === 'DeTree') { + newComponent.propValue[0].name = guid() + newComponent['titleBackground'] = deepCopy(COMMON_TAB_TITLE_BACKGROUND) + } } }) diff --git a/core/core-frontend/src/custom-component/de-tree/Attr.vue b/core/core-frontend/src/custom-component/de-tree/Attr.vue new file mode 100644 index 0000000..5eae527 --- /dev/null +++ b/core/core-frontend/src/custom-component/de-tree/Attr.vue @@ -0,0 +1,68 @@ + + + + + diff --git a/core/core-frontend/src/custom-component/de-tree/Component.vue b/core/core-frontend/src/custom-component/de-tree/Component.vue new file mode 100644 index 0000000..044247e --- /dev/null +++ b/core/core-frontend/src/custom-component/de-tree/Component.vue @@ -0,0 +1,642 @@ + + + + + \ No newline at end of file diff --git a/core/core-frontend/src/models/chart/chart-attr.d.ts b/core/core-frontend/src/models/chart/chart-attr.d.ts index 134dd24..771e574 100644 --- a/core/core-frontend/src/models/chart/chart-attr.d.ts +++ b/core/core-frontend/src/models/chart/chart-attr.d.ts @@ -380,6 +380,10 @@ declare interface ChartBasicStyle { * 圆形填充图间距 */ circlePadding: number + /** + * 占比图图形底色 + */ + proportionBackgroundColor: string } /** * 表头属性 diff --git a/core/core-frontend/src/models/chart/chart-style.d.ts b/core/core-frontend/src/models/chart/chart-style.d.ts index b848233..6db8102 100644 --- a/core/core-frontend/src/models/chart/chart-style.d.ts +++ b/core/core-frontend/src/models/chart/chart-style.d.ts @@ -2,6 +2,7 @@ * 图表样式设置 */ declare interface ChartStyle { + graphicText: any /** * 标题样式设置 */ @@ -89,7 +90,46 @@ declare interface ChartTextStyle { */ fontShadow: boolean } - +/** + * 图形文本标注设置 + */ +declare interface ChartGraphicTextStyle { + /** + * 显隐 + */ + show: boolean + /** + * 展示文字值 + */ + showContent: [ + { + show: boolean + type: string + fontFamily: string + positionX:string + positionY:string + fontSize: number + fill: string + fontWeight: number + textAlign: string + offsetX:number + offsetY:number + }, + { + show: boolean + type: string + fontFamily: string + positionX:string + positionY:string + fontSize: number + fill: string + fontWeight: number + textAlign: string + offsetX:number + offsetY:number + } + ] +} /** * 图例设置 */ diff --git a/core/core-frontend/src/models/chart/editor.d.ts b/core/core-frontend/src/models/chart/editor.d.ts index 8cc1de9..b1ea3fb 100644 --- a/core/core-frontend/src/models/chart/editor.d.ts +++ b/core/core-frontend/src/models/chart/editor.d.ts @@ -33,6 +33,7 @@ declare type EditorProperty = | 'bubble-animate' | 'summary-selector' | 'bullet-graph-selector' + | 'graphic-text-selector' declare type EditorPropertyInner = { [key in EditorProperty]?: string[] } diff --git a/core/core-frontend/src/utils/canvasUtils.ts b/core/core-frontend/src/utils/canvasUtils.ts index 50f3685..1a98727 100644 --- a/core/core-frontend/src/utils/canvasUtils.ts +++ b/core/core-frontend/src/utils/canvasUtils.ts @@ -74,6 +74,10 @@ export function findNewComponent(componentName, innerType, staticMap?) { newComponent.propValue[0].name = guid() newComponent['titleBackground'] = deepCopy(COMMON_TAB_TITLE_BACKGROUND) } + if (newComponent.component === 'DeTree') { + newComponent.propValue[0].name = guid() + newComponent['titleBackground'] = deepCopy(COMMON_TAB_TITLE_BACKGROUND) + } newComponent.innerType = innerType if (newComponent.innerType === 'richText') { newComponent.propValue = { diff --git a/core/core-frontend/src/utils/components.ts b/core/core-frontend/src/utils/components.ts index e12329c..e836825 100644 --- a/core/core-frontend/src/utils/components.ts +++ b/core/core-frontend/src/utils/components.ts @@ -13,6 +13,8 @@ import CanvasIcon from '@/custom-component/canvas-icon/Component.vue' import CanvasIconAttr from '@/custom-component/canvas-icon/Attr.vue' import DeTabs from '@/custom-component/de-tabs/Component.vue' import DeTabsAttr from '@/custom-component/de-tabs/Attr.vue' +import DeTree from '@/custom-component/de-tree/Component.vue' +import DeTreeAttr from '@/custom-component/de-tree/Attr.vue' import DeGraphical from '@/custom-component/de-graphical/Component.vue' import DeGraphicalAttr from '@/custom-component/de-graphical/Attr.vue' import CircleShape from '@/custom-component/circle-shape/Component.vue' @@ -53,6 +55,8 @@ export const componentsMap = { CanvasIconAttr: CanvasIconAttr, DeTabs: DeTabs, DeTabsAttr: DeTabsAttr, + DeTree: DeTree, + DeTreeAttr: DeTreeAttr, DeGraphical: DeGraphical, DeGraphicalAttr: DeGraphicalAttr, CircleShape: CircleShape, diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/ChartStyle.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/ChartStyle.vue index d0b2e5d..6baabfc 100644 --- a/core/core-frontend/src/views/chart/components/editor/editor-style/ChartStyle.vue +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/ChartStyle.vue @@ -8,6 +8,7 @@ import XAxisSelector from '@/views/chart/components/editor/editor-style/componen import YAxisSelector from '@/views/chart/components/editor/editor-style/components/YAxisSelector.vue' import DualYAxisSelector from '@/views/chart/components/editor/editor-style/components/DualYAxisSelector.vue' import TitleSelector from '@/views/chart/components/editor/editor-style/components/TitleSelector.vue' +import GraphicTextSelector from '@/views/chart/components/editor/editor-style/components/GraphicTextSelector.vue' import LegendSelector from '@/views/chart/components/editor/editor-style/components/LegendSelector.vue' import SummarySelector from '@/views/chart/components/editor/editor-style/components/SummarySelector.vue' import { dvMainStoreWithOut } from '@/store/modules/data-visualization/dvMain' @@ -116,6 +117,7 @@ const emit = defineEmits([ 'onChangeYAxisForm', 'onChangeYAxisExtForm', 'onTextChange', + 'onGraphicTextChange', 'onLegendChange', 'onBasicStyleChange', 'onBackgroundChange', @@ -172,7 +174,9 @@ const onChangeYAxisExtForm = (val, prop) => { const onTextChange = (val, prop) => { state.initReady && emit('onTextChange', val, prop) } - +const onGraphicTextChange = (val, prop) => { + state.initReady && emit('onGraphicTextChange', val, prop) +} const onIndicatorChange = (val, prop) => { const value = { indicatorValue: val, indicatorName: undefined } if (prop === 'color' || prop === 'suffixColor') { @@ -344,6 +348,24 @@ watch( @onTextChange="onTextChange" /> + + + + -
11 +
@@ -752,4 +760,16 @@ const colorItemBorderColor = (index, state) => { margin-top: 16px !important; } } +.proportion-color-picker { + :deep(.ed-color-picker--small .ed-color-picker__trigger){ + width: 23px; + height: 23px; + } + :deep(.ed-color-picker .ed-color-picker__icon){ + display: none; + } + :deep(.ed-color-picker__trigger){ + padding: 2px; + } +} diff --git a/core/core-frontend/src/views/chart/components/editor/editor-style/components/graphicTextSelector.vue b/core/core-frontend/src/views/chart/components/editor/editor-style/components/graphicTextSelector.vue new file mode 100644 index 0000000..bf92b0b --- /dev/null +++ b/core/core-frontend/src/views/chart/components/editor/editor-style/components/graphicTextSelector.vue @@ -0,0 +1,612 @@ + + + + + diff --git a/core/core-frontend/src/views/chart/components/editor/index.vue b/core/core-frontend/src/views/chart/components/editor/index.vue index 2e9da8a..5ee8489 100644 --- a/core/core-frontend/src/views/chart/components/editor/index.vue +++ b/core/core-frontend/src/views/chart/components/editor/index.vue @@ -1180,7 +1180,10 @@ const onTextChange = val => { snapshotStore.recordSnapshotCache('renderChart', view.value.id) } } - +const onGraphicTextChange = val => { + view.value.customStyle.graphicText = val + renderChart(view.value) +} const onLegendChange = val => { view.value.customStyle.legend = val renderChart(view.value) @@ -2012,6 +2015,7 @@ const deleteChartFieldItem = id => { @onChangeYAxisForm="onChangeYAxisForm" @onChangeYAxisExtForm="onChangeYAxisExtForm" @onTextChange="onTextChange" + @onGraphicTextChange="onGraphicTextChange" @onIndicatorChange="onIndicatorChange" @onIndicatorNameChange="onIndicatorNameChange" @onLegendChange="onLegendChange" @@ -3351,6 +3355,7 @@ const deleteChartFieldItem = id => { @onChangeYAxisForm="onChangeYAxisForm" @onChangeYAxisExtForm="onChangeYAxisExtForm" @onTextChange="onTextChange" + @onGraphicTextChange="onGraphicTextChange" @onIndicatorChange="onIndicatorChange" @onIndicatorNameChange="onIndicatorNameChange" @onLegendChange="onLegendChange" diff --git a/core/core-frontend/src/views/chart/components/editor/util/chart.ts b/core/core-frontend/src/views/chart/components/editor/util/chart.ts index 7fd9637..cb68a08 100644 --- a/core/core-frontend/src/views/chart/components/editor/util/chart.ts +++ b/core/core-frontend/src/views/chart/components/editor/util/chart.ts @@ -515,7 +515,38 @@ export const DEFAULT_TITLE_STYLE: ChartTextStyle = { letterSpace: '0', fontShadow: false } - +//百分比图图形文本样式 +export const DEFAULT_GRAPHIC_TEXT_STYLE: ChartGraphicTextStyle = { + show: true, + showContent: [ + { + show: true, + type:'名称', + fontFamily:'', + positionX:'50', + positionY:'50', + fontSize: 12, + fill: '#8c8c8c', + fontWeight: 300, + textAlign: 'center', + offsetX:0, + offsetY:-12, + }, + { + show: true, + type:'值', + fontFamily:'', + positionX:'50', + positionY:'50', + fontSize: 18, + fill: '#000000', + fontWeight: 500, + textAlign: 'center', + offsetX:0, + offsetY:10, + } + ] +} export const DEFAULT_INDICATOR_STYLE: ChartIndicatorStyle = { show: true, fontSize: 20, @@ -1739,7 +1770,8 @@ export const DEFAULT_BASIC_STYLE: ChartBasicStyle = { circleBorderWidth: 0, circlePadding: 0, quotaPosition: 'col', - quotaColLabel: t('dataset.value') + quotaColLabel: t('dataset.value'), + proportionBackgroundColor:'#ffffff' } export const BASE_VIEW_CONFIG = { @@ -1782,6 +1814,7 @@ export const BASE_VIEW_CONFIG = { } }, customStyle: { + graphicText:DEFAULT_GRAPHIC_TEXT_STYLE, text: DEFAULT_TITLE_STYLE, legend: DEFAULT_LEGEND_STYLE, xAxis: DEFAULT_XAXIS_STYLE, diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/pie/common.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/pie/common.ts index ce8120c..fc93da4 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/pie/common.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/pie/common.ts @@ -11,7 +11,7 @@ export const PIE_EDITOR_PROPERTY: EditorProperty[] = [ 'label-selector', 'tooltip-selector', 'jump-set', - 'linkage' + 'linkage', ] export const PIE_EDITOR_PROPERTY_INNER: EditorPropertyInner = { 'background-overall-component': ['all'], diff --git a/core/core-frontend/src/views/chart/components/js/panel/charts/pie/proportion.ts b/core/core-frontend/src/views/chart/components/js/panel/charts/pie/proportion.ts index 8fef3c0..f49842d 100644 --- a/core/core-frontend/src/views/chart/components/js/panel/charts/pie/proportion.ts +++ b/core/core-frontend/src/views/chart/components/js/panel/charts/pie/proportion.ts @@ -30,7 +30,6 @@ class ChartWrapper { destroy() { this.chartInstance?.destroy?.() } - render() { this.chartInstance?.render?.() } @@ -39,21 +38,35 @@ class ChartWrapper { export class G2Pie extends G2ChartView { axis: AxisType[] = PIE_AXIS_TYPE - properties = PIE_EDITOR_PROPERTY + // properties = PIE_EDITOR_PROPERTY + properties = [ + 'background-overall-component', + 'border-style', + 'basic-style-selector', + 'title-selector', + 'label-selector', + 'tooltip-selector', + 'jump-set', + 'linkage', + 'graphic-text-selector' + ] as any propertyInner: EditorPropertyInner = { ...PIE_EDITOR_PROPERTY_INNER, - 'basic-style-selector': ['colors', 'alpha', 'radius','innerRadius', 'seriesColor'], - 'tooltip-selector': [...PIE_EDITOR_PROPERTY_INNER['tooltip-selector'], 'carousel'] + 'basic-style-selector': ['colors', 'alpha', 'radius','innerRadius', 'seriesColor','proportionBackgroundColor'], + 'tooltip-selector': [...PIE_EDITOR_PROPERTY_INNER['tooltip-selector'], 'carousel'], + } axisConfig = PIE_AXIS_CONFIG constructor() { - super() + super('pie-proportion') this.name = 'pie-proportion' } async drawChart({ container, chart }: { container: HTMLElement; chart: ChartObj }) { + const customAttr = parseJson(chart.customAttr) + const customStyle = parseJson(chart.customStyle) const innerRadius = customAttr.basicStyle.innerRadius ?? 60 const data = cloneDeep(chart.data?.data || []) const { radius = 0.75, alpha = 1, colors = [] } = customAttr.basicStyle @@ -75,17 +88,24 @@ export class G2Pie extends G2ChartView { g2.legend(false) g2.tooltip({ - showMarkers: false + showMarkers: false, + showContent: (datum) => { + return !datum.some(item => item?.name === '其他'); + }, }) - g2.facet('rect', { fields: ['name'], padding: 20, showTitle: false, eachView: (view, facet) => { const data:any = facet.data + console.log(customAttr,999) let color - color = colorList[0]; + customAttr.basicStyle.seriesColor.forEach((item) => { + if(data.name == item.name){ + color = item.color + } + }) data.push({ name: '其他', value: 100 - data[0].value }) view.data(data) view.coordinate('theta', { @@ -97,44 +117,84 @@ export class G2Pie extends G2ChartView { .adjust('stack') .position('value') .color('name', (name) => { - return name === '其他' ? colorList[1] : colorList[0]; + let colorval = '' + customAttr.basicStyle.seriesColor.forEach((item) => { + if(name == item.name){ + colorval = item.color + } + }) + return name === '其他' ? customAttr.basicStyle.proportionBackgroundColor : colorval; }) .style({ opacity: 1, - }); - view.annotation().text({ - position: [ '50%', '50%' ], - content: data[0].name, - style: { - fontSize: 12, - fill: '#8c8c8c', - fontWeight: 300, - textBaseline: 'bottom', - textAlign: 'center' - }, - offsetY: -12, - }) + }) + if(customStyle.graphicText.show){ + customStyle.graphicText.showContent.forEach(item => { + const positionarr:any = [] + positionarr.push(item.positionX + '%') + positionarr.push(item.positionY + '%') + console.log(positionarr) + if(item.type == '名称' && item.show == true){ + view.annotation().text({ + position: positionarr, + content: data[0].name, + style: { + fontSize: item.fontSize, + fill: item.fill, + fontWeight: item.fontWeight, + textBaseline: 'bottom', + textAlign: 'center' + }, + offsetX: item.offsetX, + offsetY: item.offsetY + }) + }else if(item.type == '值' && item.show == true){ + view.annotation().text({ + position: positionarr, + content: data[0].value, + style: { + fontSize: item.fontSize, + fill: item.fill, + fontWeight: item.fontWeight, + textAlign: 'center' + }, + offsetX: item.offsetX, + offsetY: item.offsetY + }) + } + }) + } + // view.annotation().text({ + // position: [ '50%', '50%' ], + // content: data[0].name, + // style: { + // fontSize: 12, + // fill: '#8c8c8c', + // fontWeight: 300, + // textBaseline: 'bottom', + // textAlign: 'center' + // }, + // offsetY: -12, + // }) - view.annotation().text({ - position: ['50%', '50%'], - content: data[0].value, - style: { - fontSize: 18, - fill: '#fff', - fontWeight: 500, - textAlign: 'center' - }, - offsetY: 10, - }) + // view.annotation().text({ + // position: ['50%', '50%'], + // content: data[0].value, + // style: { + // fontSize: 18, + // fill: '#fff', + // fontWeight: 500, + // textAlign: 'center' + // }, + // offsetY: 10, + // }) } }) g2.render() - return new ChartWrapper(g2) } - public setupSeriesColor(chart: ChartObj, data?: any[]): ChartBasicStyle['seriesColor'] { return setUpSingleDimensionSeriesColor(chart, data) } diff --git a/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue b/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue index ab7e972..b70ec1a 100644 --- a/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue +++ b/core/core-frontend/src/views/chart/components/views/components/ChartComponentG2Plot.vue @@ -276,17 +276,14 @@ const renderChart = async (view, callback?) => { curView = view // view 为引用对象 需要存库 view.data 直接赋值会导致保存不必要的数据 // 与默认图表对象合并,方便增加配置项 - console.log(view,998779) const chart = deepCopy({ ...defaultsDeep(view, cloneDeep(BASE_VIEW_CONFIG)), data: chartData.value, ...(props.fontFamily && props.fontFamily !== 'inherit' ? { fontFamily: props.fontFamily } : {}) }) - console.log('chart1', chart.customAttr.basicStyle.colors) const chartView = chartViewManager.getChartView(view.render, view.type) recursionTransObj(customAttrTrans, chart.customAttr, scale.value, terminal.value) recursionTransObj(customStyleTrans, chart.customStyle, scale.value, terminal.value) - console.log('chart', chart) switch (chartView.library) { case ChartLibraryType.L7_PLOT: await renderL7Plot(chart, chartView as L7PlotChartView, callback)