Commit 72139ecf by qlintonger xeno

fix: 添加额外图表类型呢

parent 2113a2c9
<script lang="ts" setup> <script lang="ts" setup>
import {ChartCompType} from "./lib/Table2Chart/const/chartCompType.ts"; import { layout } from "./layout.conf.ts";
const layout = [
{x: 0, y: 0, w: 4, h: 1,},
{x: 4, y: 0, w: 8, h: 1,},
{x: 0, y: 2, w: 2, h: 1,},
{x: 2, y: 2, w: 2, h: 1,},
{x: 4, y: 2, w: 3, h: 1,},
{x: 7, y: 1, w: 5, h: 4,},
{x: 0, y: 1, w: 7, h: 1,},
{x: 0, y: 3, w: 7, h: 2,}
].map((a, q) => ({
...a, title: `示例图${q + 1}`, chartData: Math.random() > .6 ? [
{
type: ChartCompType.EChartsBar,
category: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: [120, 200, 150, 80, 70, 110, 130]
},
{
type: ChartCompType.EChartsBar,
category: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: [120, 200, 150, 80, 70, 110, 130]
}
] : [
{
type: ChartCompType.EChartsBar,
category: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: [120, 200, 150, 80, 70, 110, 130]
},
]
}));
</script> </script>
<template> <template>
<screen-chart :layout="layout"/> <screen-chart :layout="layout" />
</template> </template>
<style scoped> <style scoped></style>
</style>
import { ChartCompType } from "./lib/Table2Chart/const/chartCompType.ts";
import { mapHeight, mapWidth } from "./lib/Table2Chart/funcs/mapGEOStyle.ts";
const sampleForLineCharts = {
type: ChartCompType.EChartsBar,
category: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
data: [120, 200, 150, 80, 70, 110, 130],
};
const sampleForPieCharts = {
type: ChartCompType.EChartsPieCenterText,
radius: ["60%", "90%"],
title: "示例图表",
data: [
{ name: "类型一", color: "#ffaacc", value: 100 },
{ name: "类型二", color: "#abc001", value: 200 },
{ name: "类型三", color: "#cad13c", value: 50 },
],
};
const bottomCenterTextCharts = {
title: "奇特上下排位图表",
columns: 4,
chartData: Array(12)
.fill(2)
.map(() => ({
type: ChartCompType.EchartsPieBottomCenterText,
radius: ["60%", "90%"],
chartWidth: () => mapWidth(120),
chartHeight: () => mapHeight(120),
title: "示例图表",
data: [
{ name: "类型一", color: "#ffaacc", value: 100 },
{ name: "类型二", color: "#abc001", value: 200 },
{ name: "类型三", color: "#cad13c", value: 50 },
],
bottomText: "奇特数据呢!",
})),
};
const indexMapper: Record<string, any> = {
7: bottomCenterTextCharts,
3: {
title: "简单数字内容显示",
columns: 2,
chartData: Array(2)
.fill(1)
.map(() => ({
title: 15,
bottomText: "奇特数据",
type: ChartCompType.BottomCenterText,
})),
},
2: {
title: "混编数据",
columns: 2,
chartData: [
{
type: ChartCompType.BottomCenterText,
title: 100,
bottomText: "奇特数据",
},
{
type: ChartCompType.EChartsPieCenterText,
radius: ["60%", "90%"],
title: "示例图表",
data: [
{ name: "类型一", color: "#ffaacc", value: 100 },
{ name: "类型二", color: "#abc001", value: 200 },
{ name: "类型三", color: "#cad13c", value: 50 },
],
},
],
},
4: {
title: "简单混排图",
chartData: [sampleForLineCharts, sampleForLineCharts],
},
0: {
title: "简单混排图",
chartData: [sampleForLineCharts, sampleForPieCharts],
},
5: {
title: "啊哈哈表格呢",
columns: 1,
chartData: [
{
type: ChartCompType.SimpleTable,
columns: [
{ key: "a", title: "种类一" },
{ key: "b", title: "种类二" },
{ key: "c", title: "中类似" },
{ key: "d", title: "奇特呢" },
],
data: Array(20)
.fill(1)
.map(() => {
return {
a: 12,
b: 123,
c: 434,
d: 3123,
};
}),
},
],
},
1: {
title: "简单混排图",
chartData: [sampleForLineCharts, sampleForPieCharts],
},
6: {
title: "简单混排图",
chartData: [sampleForLineCharts, sampleForPieCharts],
},
};
const layout = [
{ x: 0, y: 0, w: 4, h: 1 },
{ x: 4, y: 0, w: 8, h: 1 },
{ x: 0, y: 2, w: 2, h: 1 },
{ x: 2, y: 2, w: 2, h: 1 },
{ x: 4, y: 2, w: 3, h: 1 },
{ x: 7, y: 1, w: 5, h: 4 },
{ x: 0, y: 1, w: 7, h: 1 },
{ x: 0, y: 3, w: 7, h: 2 },
].map((a, q) => ({
...a,
...indexMapper[q],
}));
export { layout };
<template> <template>
<template v-if="ps.type === ChartCompType.EChartsBar"> <template v-if="ps.type === ChartCompType.EChartsBar">
<global-echarts v-bind="$attrs" :height="ps.item.chartWidth" :width="ps.item.chartHeight" :options="ps.options"/> <global-echarts
v-bind="$attrs"
:height="ps.item.chartWidth"
:width="ps.item.chartHeight"
:options="ps.options"
/>
</template> </template>
<template v-else-if="ps.type === ChartCompType.EChartsPie"> <template v-else-if="ps.type === ChartCompType.EChartsPieCenterText">
<div class="flex flex-col items-center"> <div class="relative w-full h-full">
<global-echarts
v-bind="$attrs"
:width="ps.item.chartWidth"
:height="ps.item.chartHeight"
:options="ps.options"
/>
<div
class="absolute z-10 top-[50%] left-[50%]"
style="transform: translate(-50%, -50%)"
:style="{
fontSize: mapWidth(14) + 'px',
}"
>
{{ ps.item.title }}
</div>
</div>
</template>
<template v-else-if="ps.type === ChartCompType.EchartsPieBottomCenterText">
<div class="flex flex-col items-center justify-center">
<div class="relative">
<global-echarts
v-bind="$attrs"
:width="ps.item.chartWidth"
:height="ps.item.chartHeight"
:options="ps.options"
/>
<div
class="absolute z-10 top-[50%] left-[50%]"
style="transform: translate(-50%, -50%)"
:style="{
fontSize: mapWidth(14) + 'px',
}"
>
{{ ps.item.title }}
</div>
</div>
<div
:style="{
marginTop: mapHeight(16) + 'px',
fontSize: mapWidth(14) + 'px',
}"
>
{{ ps.item.bottomText }}
</div>
</div>
</template>
<template v-else-if="ps.type === ChartCompType.BottomCenterText">
<div class="flex flex-col items-center justify-center">
<div
:style="{
fontSize: mapWidth(32) + 'px',
}"
>
{{ ps.item.title }}
</div>
<div
:style="{
marginTop: mapHeight(16) + 'px',
fontSize: mapWidth(14) + 'px',
}"
>
{{ ps.item.bottomText }}
</div>
</div>
</template>
<template v-else-if="ps.type === ChartCompType.SimpleTable">
<div class="w-full h-full overflow-auto">
<table class="w-full">
<thead>
<th v-for="(q, w) in tableInside.tableHead" :key="w">{{ q }}</th>
</thead>
<tr v-for="(q, w) in tableInside.rowsDataEach" :key="w">
<td v-for="(z, c) in q" :key="c">{{ z }}</td>
</tr>
</table>
</div> </div>
</template> </template>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {ECBasicOption} from "echarts/types/dist/shared"; import { ECBasicOption } from "echarts/types/dist/shared";
import {ChartCompType} from "../const/chartCompType.ts"; import { ChartCompType } from "../const/chartCompType.ts";
import GlobalEcharts from "./global-echarts.vue"; import GlobalEcharts from "./global-echarts.vue";
import {GeneralChartOptions} from "../types/ScreenChart.typing.ts"; import {
GeneralChartOptions,
SimpleTableChart,
} from "../types/ScreenChart.typing.ts";
import { mapWidth, mapHeight } from "../funcs/mapGEOStyle.ts";
import { computed } from "vue";
interface Props { interface Props {
options?: ECBasicOption; options?: ECBasicOption;
width?: string | number; width?: string | number;
height?: string | number; height?: string | number;
type: ChartCompType; type: ChartCompType;
item: GeneralChartOptions item: GeneralChartOptions;
} }
const tableFont = computed(function () {
return mapWidth(12) + "px";
});
const paddingForTD = computed(() => {
return `${mapHeight(10)}px ${mapWidth(12)}px`;
});
const ps = withDefaults(defineProps<Props>(), { const ps = withDefaults(defineProps<Props>(), {
options: () => { options: () => {
return {}; return {};
}, },
width: "100%", width: "100%",
height: "100%", height: "100%",
type: ChartCompType.EChartsBar type: ChartCompType.EChartsBar,
});
const tableInside = computed(() => {
const { data, columns } = ps.item as SimpleTableChart;
const tableHead = columns.map((vc: any) => vc.title) as string[];
const rowsDataEach = data.map((a: any) => {
return columns.map((v) => a[v.key]);
});
return {
tableHead,
rowsDataEach,
};
}); });
</script> </script>
\ No newline at end of file
<style scoped>
table,
td,
tr,
th {
border-collapse: collapse;
}
td,
th {
border: 1px solid #c2c2c2;
font-size: v-bind(tableFont);
text-align: center;
padding: v-bind(paddingForTD);
}
th {
font-weight: bold;
}
</style>
...@@ -4,14 +4,22 @@ ...@@ -4,14 +4,22 @@
<script setup lang="ts"> <script setup lang="ts">
import * as echarts from "echarts"; import * as echarts from "echarts";
import {ECBasicOption} from "echarts/types/dist/shared"; import { ECBasicOption } from "echarts/types/dist/shared";
import {isNumber} from "lodash"; import { isNumber } from "lodash";
import {computed, getCurrentInstance, nextTick, onMounted, onUnmounted, ref, watch} from "vue"; import {
computed,
getCurrentInstance,
nextTick,
onMounted,
onUnmounted,
ref,
watch,
} from "vue";
interface Props { interface Props {
options?: ECBasicOption; options?: ECBasicOption;
width?: string | number; width?: string | number | Function;
height?: string | number; height?: string | number | Function;
} }
const ps = withDefaults(defineProps<Props>(), { const ps = withDefaults(defineProps<Props>(), {
options: () => { options: () => {
...@@ -21,30 +29,32 @@ const ps = withDefaults(defineProps<Props>(), { ...@@ -21,30 +29,32 @@ const ps = withDefaults(defineProps<Props>(), {
height: "100%", height: "100%",
}); });
const getWidth = computed(() => { const getWidth = computed(() => {
if (isNumber(ps.width)) { let targetWidth = typeof ps.width === "function" ? ps.width() : ps.width;
return ps.width + "px"; if (isNumber(targetWidth)) {
return targetWidth + "px";
} else { } else {
return ps.width; return targetWidth;
} }
}); });
const getHeight = computed(() => { const getHeight = computed(() => {
if (isNumber(ps.height)) { let targetHeight = typeof ps.height === "function" ? ps.height() : ps.height;
return ps.height + "px"; if (isNumber(targetHeight)) {
return targetHeight + "px";
} else { } else {
return ps.height; return targetHeight;
} }
}); });
const chartRef = ref(null); const chartRef = ref(null);
let chartInstance = null as unknown as echarts.ECharts; let chartInstance = null as unknown as echarts.ECharts;
const es = defineEmits(['node-inserted']) const es = defineEmits(["node-inserted"]);
onMounted(() => { onMounted(() => {
const el = chartRef.value; const el = chartRef.value;
const inst = getCurrentInstance() const inst = getCurrentInstance();
if (el) { if (el) {
nextTick(() => { nextTick(() => {
chartInstance = echarts.init(el); chartInstance = echarts.init(el);
setOptions(ps.options); setOptions(ps.options);
es('node-inserted', {uid: inst!.uid, f: () => chartInstance}) es("node-inserted", { uid: inst!.uid, f: () => chartInstance });
chartInstance?.resize(); chartInstance?.resize();
}); });
} }
...@@ -53,20 +63,20 @@ onUnmounted(() => { ...@@ -53,20 +63,20 @@ onUnmounted(() => {
chartInstance?.dispose(); chartInstance?.dispose();
}); });
watch( watch(
() => ps.options, () => ps.options,
(newVal) => { (newVal) => {
setOptions(newVal); setOptions(newVal);
}, },
{ {
deep: true, deep: true,
} }
); );
const setOptions = (options: ECBasicOption) => { const setOptions = (options: ECBasicOption) => {
chartInstance.setOption(options); chartInstance.setOption(options);
}; };
defineExpose({ defineExpose({
getChartInstance: () => chartInstance, getChartInstance: () => chartInstance,
getDom: () => chartRef.value getDom: () => chartRef.value,
}); });
</script> </script>
<style scoped> <style scoped>
......
<script lang="ts" setup> <script lang="ts" setup>
import {ScreenChartProps} from "./types/ScreenChart.typing.ts"; import { ScreenChartProps } from "./types/ScreenChart.typing.ts";
import {getAllGridSize, gridItemStyle, mapContainerStyle} from "./funcs/mapStyle.ts"; import {
import {mapToEchartsOptions} from "./funcs/mapToEchartsOptions.ts"; getAllGridSize,
import {computed, onMounted, onUnmounted} from "vue"; gridItemStyle,
mapContainerStyle,
} from "./funcs/mapStyle.ts";
import { mapToEchartsOptions } from "./funcs/mapToEchartsOptions.ts";
import { computed, onMounted, onUnmounted } from "vue";
import ChartsWrapper from "./Components/charts-wrapper.vue"; import ChartsWrapper from "./Components/charts-wrapper.vue";
import {containerRef, isAllMounted, registerGraph} from "./funcs/procedureFunc.ts"; import {
import {onNew, onRemoved} from "./funcs/hooksFunc.ts"; containerRef,
isAllMounted,
registerGraph,
} from "./funcs/procedureFunc.ts";
import { onNew, onRemoved } from "./funcs/hooksFunc.ts";
import { mapHeight } from "./funcs/mapGEOStyle";
const props = withDefaults(defineProps<ScreenChartProps>(), { const props = withDefaults(defineProps<ScreenChartProps>(), {
gap: 16, containerPadding: 12, gridItemPadding: 12 gap: 16,
}) containerPadding: 12,
gridItemPadding: 12,
});
onUnmounted(function () { onUnmounted(function () {
onRemoved() onRemoved();
}) });
const gridConfig = computed(() => { const gridConfig = computed(() => {
return getAllGridSize(props.layout) return getAllGridSize(props.layout);
}) });
onMounted(function () { onMounted(function () {
onNew() console.log("passing props here", props);
}) onNew();
});
import { singleContainerClass } from "./const/staticConsts.ts";
</script> </script>
<template> <template>
<div :style="mapContainerStyle(props)" class="w-full h-full pr" ref="containerRef"> <div
<div v-for="(item, w) in props.layout" :key="w" :style="gridItemStyle(item, props, gridConfig)" class="flex flex-col"> :style="mapContainerStyle(props)"
class="w-full h-full pr"
ref="containerRef"
>
<div
v-for="(item, w) in props.layout"
:key="w"
:style="gridItemStyle(item, props, gridConfig)"
class="flex flex-col"
>
<div v-if="!item.renderTitle" class="w-full">{{ item.title }}</div> <div v-if="!item.renderTitle" class="w-full">{{ item.title }}</div>
<component :is="item.renderTitle(item, props.layout)" v-else/> <component :is="item.renderTitle(item, props.layout)" v-else />
<div v-if="isAllMounted" class="mt-[12px] w-full flex items-stretch justify-between" <div
style="height: calc(100% - 12px - 12px)"> v-if="isAllMounted"
<ChartsWrapper :type="z.type" :item="z" @node-inserted="registerGraph" v-for="(z,x) in item.chartData" :key="x" :options="mapToEchartsOptions(z)"/> class="w-full"
:class="item.wrapperClass || singleContainerClass"
:style="{
height: `calc(100% - ${mapHeight(24)}px)`,
marginTop: `${mapHeight(12)}px`,
gridTemplateColumns: `repeat(${item.columns || item.chartData.length}, 1fr)`,
rowGap: mapHeight(20) + 'px',
...<Object>(typeof item.wrapperStyle === 'function' ? item.wrapperStyle() : typeof item.wrapperStyle === 'object' ? item.wrapperStyle : {}),
}"
>
<ChartsWrapper
:type="z.type"
:item="z"
@node-inserted="registerGraph"
v-for="(z, x) in item.chartData"
:key="x"
:options="mapToEchartsOptions(z)"
/>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
\ No newline at end of file
export enum ChartCompType { export enum ChartCompType {
EChartsBar, EChartsBar,
EChartsPie EChartsPieCenterText,
} EchartsPieBottomCenterText,
\ No newline at end of file BottomCenterText,
SimpleTable,
}
export const singleContainerClass = "overflow-auto grid justify-between";
import {allGraphRegister, containerRef, isAllMounted, startNow} from "./procedureFunc.ts"; import {
import {nextTick} from "vue"; allGraphRegister,
containerRef,
isAllMounted,
startNow,
} from "./procedureFunc.ts";
import { nextTick } from "vue";
let ro: ResizeObserver | null = null let ro: ResizeObserver | null = null;
export function onRemoved() { export function onRemoved() {
if (ro) { if (ro) {
ro.disconnect() ro.disconnect();
ro = null ro = null;
} }
allGraphRegister.value = [] allGraphRegister.value = [];
} }
export function onNew() { export function onNew() {
nextTick(function () { nextTick(function () {
if (!ro) {
}).then(function () { ro = new ResizeObserver(function () {
isAllMounted.value = true startNow();
if (!ro) { });
ro = new ResizeObserver(startNow) ro.observe(containerRef.value, { box: "border-box" });
ro.observe(containerRef.value, {box: 'border-box'}) startNow();
startNow() }
} }).then(function () {
}) isAllMounted.value = true;
} });
\ No newline at end of file }
import {BarChartOptions, GeneralChartOptions, PieCharOptions} from "../types/ScreenChart.typing.ts"; import {
import {ChartCompType} from "../const/chartCompType.ts"; BarChartOptions,
GeneralChartOptions,
PieCharOptions,
} from "../types/ScreenChart.typing.ts";
import { ChartCompType } from "../const/chartCompType.ts";
export function mapToEchartsOptions(item: GeneralChartOptions) { export function mapToEchartsOptions(item: GeneralChartOptions) {
if (item.type === ChartCompType.EChartsBar) { if (item.type === ChartCompType.EChartsBar) {
let series: any[] let series: any[];
// 简单类型数据 // 简单类型数据
item = <BarChartOptions>item; item = <BarChartOptions>item;
if (item.data.every(a=>typeof a === 'number')) { if (item.data.every((a) => typeof a === "number")) {
series = [{data: item.data, type:'bar'}] series = [{ data: item.data, type: "bar" }];
} else { } else {
series = item.data.map((a) => { series = item.data.map((a) => {
return {
type: 'bar',
name: a.name,
data: a.data
}
})
}
return { return {
tooltip: { type: "bar",
trigger: 'axis', name: a.name,
axisPointer: { data: a.data,
type: 'shadow' };
} });
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true,
top: '5%'
},
xAxis: {
type: 'category',
data: item.category,
},
yAxis: {
type: 'value',
boundaryGap: [0, 0.01]
},
series
}
} }
if (item.type === ChartCompType.EChartsPie) { return {
item = <PieCharOptions>item; tooltip: {
const total = item.data.reduce((a, b) => a + b.value, 0); trigger: "axis",
return { axisPointer: {
legend: { type: "shadow",
top: '5%', },
left: 'center' },
}, grid: {
radius: item.radius, left: "3%",
type: 'pie', right: "4%",
center: ['50%', '50%'], bottom: "3%",
avoidLabelOverlap: false, containLabel: true,
emphasis: { top: "5%",
scaleSize: 3, },
}, xAxis: {
label: { type: "category",
show: false, data: item.category,
}, },
labelLine: { yAxis: {
show: false, type: "value",
}, boundaryGap: [0, 0.01],
data: item.data.map(function (item) { },
return { series,
value: item.value, };
name: item.name, }
itemStyle: { if (
color: item.color item.type === ChartCompType.EChartsPieCenterText ||
} item.type === ChartCompType.EchartsPieBottomCenterText
} ) {
}), item = <PieCharOptions>item;
toolbox: false, const total = item.data.reduce((a, b) => a + b.value, 0);
tooltip: { return {
trigger: "item", grid: {
formatter: function (param: any) { left: 0,
return `${param.name}${ right: 0,
total ? ((param.value * 100) / total).toFixed(2) : 100 bottom: 0,
}% ${param.value}`; containLabel: true,
}, top: 0,
showDelay: 0, },
hideDelay: 0, series: [
extraCssText: "pointer-events: none;", {
position: "top", radius: item.radius || undefined,
appendTo: "body", type: "pie",
}, center: ["50%", "50%"],
} avoidLabelOverlap: false,
} emphasis: {
} scaleSize: 3,
\ No newline at end of file },
label: {
show: false,
},
labelLine: {
show: false,
},
data: item.data.map(function (item) {
return {
value: item.value,
name: item.name,
itemStyle: {
color: item.color,
},
};
}),
},
],
toolbox: false,
legend: item.legend || undefined,
tooltip: {
trigger: "item",
formatter: function (param: any) {
return `${param.name}${
total ? ((param.value * 100) / total).toFixed(2) : 100
}% ${param.value}`;
},
showDelay: 0,
hideDelay: 0,
extraCssText: "pointer-events: none;",
position: "top",
appendTo: "body",
},
};
}
}
import {nextTick, ref} from "vue"; import { nextTick, ref } from "vue";
import {geoContainer} from "./mapGEOStyle.ts"; import { geoContainer } from "./mapGEOStyle.ts";
export const containerRef = ref() export const containerRef = ref();
export const isAllMounted = ref(false) export const isAllMounted = ref(false);
export const allGraphRegister = ref<Array<{ uid: string, f: Function }>>([]) export const allGraphRegister = ref<Array<{ uid: string; f: Function }>>([]);
export function registerGraph(item: { uid: string, f: Function }) { export function registerGraph(item: { uid: string; f: Function }) {
allGraphRegister.value.push(item) allGraphRegister.value.push(item);
} }
export const startNow = function calcGEO() { export const startNow = function calcGEO() {
const rect = containerRef.value.getBoundingClientRect() const rect = containerRef.value.getBoundingClientRect();
geoContainer.value.width = rect.width geoContainer.value.width = rect.width;
geoContainer.value.height = rect.height geoContainer.value.height = rect.height;
const allStyle = window.getComputedStyle(containerRef.value) const allStyle: any = window.getComputedStyle(containerRef.value);
// @ts-ignore // @ts-ignore
geoContainer.value.contentWidth = parseFloat(allStyle['width']) - parseFloat(allStyle['padding-left']) - parseFloat(allStyle['padding-right']) geoContainer.value.contentWidth =
// @ts-ignore parseFloat(allStyle["width"]) -
geoContainer.value.contentHeight = parseFloat(allStyle['height']) - parseFloat(allStyle['padding-top']) - parseFloat(allStyle['padding-bottom']) parseFloat(allStyle["padding-left"]) -
// @ts-ignore parseFloat(allStyle["padding-right"]);
geoContainer.value.paddingAll = parseFloat(allStyle['paddingLeft']) // @ts-ignore
nextTick(function () { geoContainer.value.contentHeight =
parseFloat(allStyle["height"]) -
}).then(function () { parseFloat(allStyle["padding-top"]) -
for (const item of allGraphRegister.value) { parseFloat(allStyle["padding-bottom"]);
const chart: any = item.f() // @ts-ignore
chart.resize(); geoContainer.value.paddingAll = parseFloat(allStyle["paddingLeft"]);
} nextTick(function () {
}) for (const item of allGraphRegister.value) {
} const chart: any = item.f();
\ No newline at end of file chart.resize();
}
}).then(function () {});
};
import {VNode} from "vue"; import { VNode } from "vue";
import {ChartCompType} from "../const/chartCompType.ts"; import { ChartCompType } from "../const/chartCompType.ts";
export type BarChartOptions = { export type BarChartOptions = {
category: string[] category: string[];
data: number[] | { name: string, data: number[] }[], data: number[] | { name: string; data: number[] }[];
type: ChartCompType type: ChartCompType;
chartWidth?: number | string chartWidth?: number | string;
chartHeight?: number | string chartHeight?: number | string;
}; };
export type PieCharOptions = { export type PieChartOptionsBase = {
type: ChartCompType, type: ChartCompType;
title: string, radius: Array<string>;
radius: Array<string>, data: Array<{ value: number; name: string; color: string }>;
data: Array<{value: number, name: string, color: string}>, chartWidth?: number | string;
centerText?: string | Function chartHeight?: number | string;
chartWidth?: number | string legend?: any;
chartHeight?: number | string };
}
export type PieCharOptions = PieChartOptionsBase & {
title: string;
};
export type GeneralChartOptions = BarChartOptions | PieCharOptions export type PieCharOptionsForBottomCenterText = PieCharOptions & {
bottomText: string;
};
export type ChartOptionSet = Array<GeneralChartOptions> export type BottonCenterText = {
title: string;
bottomTex: string;
type: ChartCompType;
};
export type SimpleTableChart = {
type: ChartCompType;
columns: Array<{ title: string; key: string }>;
data: Array<Record<string, any>>;
};
export type GeneralChartOptions =
| BarChartOptions
| PieCharOptions
| PieCharOptionsForBottomCenterText
| BottonCenterText
| SimpleTableChart;
export type ChartOptionSet = Array<GeneralChartOptions>;
export type SingleLayoutConf = { export type SingleLayoutConf = {
x: number, y: number, w: number, h: number, title: string, renderTitle?: (...args: any[]) => VNode, x: number;
chartData: ChartOptionSet y: number;
} w: number;
h: number;
title: string;
renderTitle?: (...args: any[]) => VNode;
chartData: ChartOptionSet;
wrapperClass?: string | Array<string> | Record<string, any>;
wrapperStyle?: Record<string, any> | Function;
columns?: number;
};
export type LayoutConfig = Array<SingleLayoutConf> export type LayoutConfig = Array<SingleLayoutConf>;
export type ScreenChartProps = { export type ScreenChartProps = {
layout: LayoutConfig; layout: LayoutConfig;
gap?: number; gap?: number;
containerPadding?: number; containerPadding?: number;
gridItemPadding?: number; gridItemPadding?: number;
} };
\ No newline at end of file
@import "tailwindcss"; @import "tailwindcss";
@import "tailwindcss/utilities"; @import "tailwindcss/utilities";
html, body, #app { html,
display: block; body,
width: 100%; #app {
height: 100%; display: block;
} width: 100%;
\ No newline at end of file height: 100%;
}
/* 滚动轴 */
::-webkit-scrollbar {
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
width: 3px;
height: 3px;
}
::-webkit-scrollbar-thumb {
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background-color: var(--scrollbar-color, #a1a1a1);
background-clip: padding-box;
min-height: 28px;
}
::-webkit-scrollbar-thumb:hover {
border-radius: 3px;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
background-color: var(--scrollbar-color-hover, #a1a1a1);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment