feat: dynamic switching components

This commit is contained in:
Qiuxia Fan 2022-01-04 22:29:35 +08:00
parent 731aded68b
commit b9a6e648ae
6 changed files with 116 additions and 88 deletions

View File

@ -21,7 +21,6 @@ export const routesGen: Array<RouteRecordRaw> = [
{ {
path: "", path: "",
name: "GeneralService", name: "GeneralService",
redirect: "/generalService",
meta: { meta: {
title: "generalService", title: "generalService",
icon: "chart", icon: "chart",

View File

@ -53,6 +53,10 @@ router.beforeEach((to, from, next) => {
} }
(window as any).axiosCancel = []; (window as any).axiosCancel = [];
} }
next(); if (to.path === "/") {
next({ path: "/generalService" });
} else {
next();
}
}); });
export default router; export default router;

View File

@ -14,11 +14,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ElLoading, ILoadingInstance } from "element-plus"; import { ElLoading } from "element-plus";
type Props = { text?: string; fullscreen?: boolean }; type Props = { text?: string; fullscreen?: boolean };
export default function (): { export default function (): {
loading: (props: Props) => ILoadingInstance; loading: (props: Props) => any;
} { } {
const loading = (props: Props) => { const loading = (props: Props) => {
const loadingInstance = ElLoading.service(props); const loadingInstance = ElLoading.service(props);

View File

@ -15,7 +15,11 @@ limitations under the License. -->
<template> <template>
<div class="widget-config"> <div class="widget-config">
<div class="graph" style="height: 350px; width: 100%"> <div class="graph" style="height: 350px; width: 100%">
<Bar :data="source" :intervalTime="appStoreWithOut.intervalTime" /> <component
:is="states.chartType"
:intervalTime="appStoreWithOut.intervalTime"
:data="source"
/>
<span v-show="!source">No Data</span> <span v-show="!source">No Data</span>
</div> </div>
<div class="config"> <div class="config">
@ -45,8 +49,8 @@ limitations under the License. -->
<label>Select you visualization</label> <label>Select you visualization</label>
<div class="chart-types"> <div class="chart-types">
<span <span
v-for="type in ChartTypes" v-for="(type, index) in ChartTypes"
:key="type.value" :key="index"
@click="changeChartType(type)" @click="changeChartType(type)"
:class="{ active: type.value === states.chartType }" :class="{ active: type.value === states.chartType }"
> >
@ -74,8 +78,8 @@ limitations under the License. -->
</div> </div>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts">
import { reactive } from "vue"; import { reactive, defineComponent } from "vue";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useDashboardStore } from "@/store/modules/dashboard"; import { useDashboardStore } from "@/store/modules/dashboard";
import { useAppStoreWithOut } from "@/store/modules/app"; import { useAppStoreWithOut } from "@/store/modules/app";
@ -83,61 +87,81 @@ import { ElMessage, ElButton } from "element-plus";
import { ValuesTypes, MetricQueryTypes, ChartTypes } from "../data"; import { ValuesTypes, MetricQueryTypes, ChartTypes } from "../data";
import { Option } from "@/types/app"; import { Option } from "@/types/app";
import Loading from "@/utils/loading"; import Loading from "@/utils/loading";
import Bar from "../graphs/Bar.vue"; import charts from "../graphs";
const states = reactive<{ export default defineComponent({
metrics: string; name: "WidgetConfig",
valueTypes: Option[]; components: { ...charts, ElButton },
valueType: string; setup() {
metricQueryType: string; const states = reactive<{
chartType: string; metrics: string;
}>({ valueTypes: Option[];
metrics: "", valueType: string;
valueTypes: [], metricQueryType: string;
valueType: "", chartType: string;
metricQueryType: "", }>({
chartType: "", metrics: "",
valueTypes: [],
valueType: "",
metricQueryType: "",
chartType: "Bar",
});
const { t } = useI18n();
const dashboardStore = useDashboardStore();
const appStoreWithOut = useAppStoreWithOut();
const { loading } = Loading();
async function changeMetrics(val: Option[]) {
if (!val.length) {
states.valueTypes = [];
states.valueType = "";
return;
}
const loadingInstance = loading({ text: t("loading"), fullscreen: true });
const resp = await dashboardStore.fetchMetricType(val[0].value);
loadingInstance.close();
if (resp.error) {
ElMessage.error(resp.data.error);
return;
}
const { typeOfMetrics } = resp.data;
states.valueTypes = ValuesTypes[typeOfMetrics];
states.valueType = ValuesTypes[typeOfMetrics][0].value;
}
function changeValueType(val: Option[]) {
states.valueType = String(val[0].value);
states.metricQueryType = (MetricQueryTypes as any)[states.valueType];
}
function changeChartType(item: Option) {
states.chartType = String(item.value);
}
const metricOpts = [
{ value: "service_apdex", label: "service_apdex" },
{ value: "service_sla", label: "service_sla" },
{ value: "service_cpm", label: "service_cpm" },
{ value: "service_resp_time", label: "service_resp_time" },
{ value: "service_percentile", label: "service_percentile" },
{
value: "service_mq_consume_latency",
label: "service_mq_consume_latency",
},
{ value: "service_mq_consume_count", label: "service_mq_consume_count" },
];
const source = {
count: [1, 2, 3, 4, 5, 6, 7, 3, 4, 5, 2, 1, 6, 9],
};
return {
states,
changeChartType,
changeValueType,
changeMetrics,
t,
appStoreWithOut,
ChartTypes,
source,
metricOpts,
};
},
}); });
const { t } = useI18n();
const dashboardStore = useDashboardStore();
const appStoreWithOut = useAppStoreWithOut();
const { loading } = Loading();
async function changeMetrics(val: Option[]) {
if (!val.length) {
states.valueTypes = [];
states.valueType = "";
return;
}
const loadingInstance = loading({ text: t("loading"), fullscreen: true });
const resp = await dashboardStore.fetchMetricType(val[0].value);
loadingInstance.close();
if (resp.error) {
ElMessage.error(resp.data.error);
return;
}
const { typeOfMetrics } = resp.data;
states.valueTypes = ValuesTypes[typeOfMetrics];
states.valueType = ValuesTypes[typeOfMetrics][0].value;
}
function changeValueType(val: Option[]) {
states.valueType = String(val[0].value);
states.metricQueryType = (MetricQueryTypes as any)[states.valueType];
}
function changeChartType(item: Option) {
states.chartType = String(item.value);
}
const metricOpts = [
{ value: "service_apdex", label: "service_apdex" },
{ value: "service_sla", label: "service_sla" },
{ value: "service_cpm", label: "service_cpm" },
{ value: "service_resp_time", label: "service_resp_time" },
{ value: "service_percentile", label: "service_percentile" },
{ value: "service_mq_consume_latency", label: "service_mq_consume_latency" },
{ value: "service_mq_consume_count", label: "service_mq_consume_count" },
];
const source = {
count: [1, 2, 3, 4, 5, 6, 7, 3, 4, 5, 2, 1, 6, 9],
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.widget-config { .widget-config {

View File

@ -22,7 +22,7 @@ limitations under the License. -->
/> />
<div class="mb-5 ell"> <div class="mb-5 ell">
<span class="calls sm mr-10">{{ i.value }}</span> <span class="calls sm mr-10">{{ i.value }}</span>
<span class="cp link-hover" @click="handleLink(i)"> <span class="cp link-hover">
{{ i.name + getTraceId(i) }} {{ i.name + getTraceId(i) }}
</span> </span>
</div> </div>
@ -33,7 +33,7 @@ limitations under the License. -->
/> />
</div> </div>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import type { PropType } from "vue"; import type { PropType } from "vue";
import { defineProps, computed } from "vue"; import { defineProps, computed } from "vue";
import { ElProgress } from "element-plus"; import { ElProgress } from "element-plus";
@ -53,33 +53,33 @@ const props = defineProps({
}); });
const maxValue = computed(() => { const maxValue = computed(() => {
if (!props.data.length) { if (!props.data.length) {
return null; return 0;
} }
const temp: number[] = props.data.map((i: any) => i.value); const temp: number[] = props.data.map((i: any) => i.value);
return Math.max.apply(null, temp); return Math.max.apply(null, temp);
}); });
const getTraceId = computed((i: { [key: string]: (number | string)[] }) => { const getTraceId = (i: { [key: string]: (number | string)[] }): string => {
return i.traceIds && i.traceIds[0] ? ` - ${i.traceIds[0]}` : ""; return i.traceIds && i.traceIds[0] ? ` - ${i.traceIds[0]}` : "";
}); };
const datas: any = computed(() => { const datas: any = () => {
if (!props.data.length) { if (!props.data.length) {
return []; return [];
} }
const { sortOrder } = props.itemConfig; const { sortOrder } = props.itemConfig;
let val: { [key: string]: number | string }[] = []; const val: any = props.data;
switch (sortOrder) { switch (sortOrder) {
case "DES": case "DES":
val = props.data.sort((a: any, b: any) => b.value - a.value); val.sort((a: any, b: any) => b.value - a.value);
break; break;
case "ASC": case "ASC":
val = props.data.sort((a: any, b: any) => a.value - b.value); val.sort((a: any, b: any) => a.value - b.value);
break; break;
default: default:
break; break;
} }
return val; return val;
}); };
function handleClick(i: string) { function handleClick(i: string) {
copy(i); copy(i);
} }

View File

@ -15,22 +15,22 @@
* limitations under the License. * limitations under the License.
*/ */
import ChartArea from "./Area.vue"; import Area from "./Area.vue";
import ChartLine from "./Line.vue"; import Line from "./Line.vue";
import ChartBar from "./Bar.vue"; import Bar from "./Bar.vue";
import ChartHeatmap from "./Heatmap.vue"; import Heatmap from "./Heatmap.vue";
import ProgressBar from "./ProgressBar.vue"; // import ProgressBar from "./ProgressBar.vue";
import ChartTable from "./Table.vue"; import Table from "./Table.vue";
import ChartPie from "./Pie.vue"; import Pie from "./Pie.vue";
import ChartCard from "./Card.vue"; import Card from "./Card.vue";
export default { export default {
ChartLine, Line,
ChartBar, Bar,
ChartHeatmap, Heatmap,
ProgressBar, // ProgressBar,
ChartArea, Area,
ChartTable, Table,
ChartPie, Pie,
ChartCard, Card,
}; };