From e1c28921470ca2a82403ef5a7bc07f1c48619b36 Mon Sep 17 00:00:00 2001 From: 刘嘉威 <daidaibg@163.com> Date: 星期三, 26 十月 2022 16:51:43 +0800 Subject: [PATCH] feat: 增加右上 右中图表 --- src/components/datav/capsule-chart/index.d.ts | 6 src/views/HomeView.vue | 14 src/views/setting.vue | 2 src/views/index/right-center.vue | 36 +++ src/views/index/right-top.vue | 232 +++++++++++++++++++++++++ components.d.ts | 1 src/api/modules/index.ts | 4 src/views/index/center-bottom.vue | 4 src/components/datav/capsule-chart/capsule-chart.vue | 186 ++++++++++++++++++++ src/components/datav/capsule-chart/index.ts | 3 src/utils/query-param.ts | 2 src/mock/mock-index.ts | 44 ++++ src/utils/public.ts | 0 src/plugins/echarts.ts | 6 14 files changed, 513 insertions(+), 27 deletions(-) diff --git a/components.d.ts b/components.d.ts index 835eb88..fba7b29 100644 --- a/components.d.ts +++ b/components.d.ts @@ -7,6 +7,7 @@ declare module '@vue/runtime-core' { export interface GlobalComponents { + CapsuleChart: typeof import('./src/components/datav/capsule-chart/capsule-chart.vue')['default'] CountUp: typeof import('./src/components/count-up/count-up.vue')['default'] ElDrawer: typeof import('element-plus/es')['ElDrawer'] ElRadio: typeof import('element-plus/es')['ElRadio'] diff --git a/src/api/modules/index.ts b/src/api/modules/index.ts index 66db6bd..7cff390 100644 --- a/src/api/modules/index.ts +++ b/src/api/modules/index.ts @@ -5,7 +5,7 @@ "centerBottom":"/bigscreen/installationPlan", // 'big3':"/bigscreen/sbtx", //璁惧鎻愰啋 - // 'big4':"/bigscreen/alarmNum", //鎶ヨ娆℃暟 + 'rightTop':"/bigscreen/alarmNum", //鎶ヨ娆℃暟 // 'big5':'/bigscreen/ssyj',//瀹炴椂棰勮 - // 'big7':'/bigscreen/ranking',// 鎶ヨ鎺掑悕 + 'rightCenter':'/bigscreen/ranking',// 鎶ヨ鎺掑悕 } \ No newline at end of file diff --git a/src/components/datav/capsule-chart/capsule-chart.vue b/src/components/datav/capsule-chart/capsule-chart.vue new file mode 100644 index 0000000..cb81015 --- /dev/null +++ b/src/components/datav/capsule-chart/capsule-chart.vue @@ -0,0 +1,186 @@ +<script setup lang="ts"> +import { onMounted, reactive, ref, watch } from "vue"; +import type { DefaultConfigType } from "./index.d"; +import cloneDeep from "lodash/cloneDeep"; +import merge from "lodash/merge"; +const mergedConfig = ref<any>(null); +const capsuleLength = ref<any>([]); +const capsuleValue = ref<any>([]); +const labelData = ref<any>([]); +// const labelDataLength = ref<any>([]); + +const defaultConfig = reactive<DefaultConfigType>({ + // Colors (hex|rgb|rgba|color keywords) ['#000', 'rgb(0, 0, 0)', 'rgba(0, 0, 0, 1)', 'red'] + colors: [ + "#37a2da", + "#32c5e9", + "#67e0e3", + "#9fe6b8", + "#ffdb5c", + "#ff9f7f", + "#fb7293", + ], + unit: "", + showValue: false, // Show item value +}); +const props = withDefaults( + defineProps<{ + config: object | any; + data: Array<{ + name: string; + value: string | number; + }>; + }>(), + { + config: () => { }, + data: () => [], + } +); +const calcData = () => { + mergeConfig(); + calcCapsuleLengthAndLabelData(); +}; +const mergeConfig = () => { + mergedConfig.value = merge(cloneDeep(defaultConfig), props.config || {}); +}; +const calcCapsuleLengthAndLabelData = () => { + if (!props.data.length) return; + const newcapsuleValue = props.data.map((item: any) => item.value); + const maxValue = Math.max(...newcapsuleValue); + capsuleValue.value = newcapsuleValue; + capsuleLength.value = newcapsuleValue.map((v: any) => + maxValue ? v / maxValue : 0 + ); + const oneFifth = maxValue / 5; + const newlabelData = Array.from( + new Set(new Array(6).fill(0).map((v, i) => Math.ceil(i * oneFifth))) + ); + labelData.value = newlabelData; + // labelDataLength.value = Array.from(newlabelData).map((v) => + // maxValue ? v / maxValue : 0 + // ); + // console.log(labelDataLength.value); +}; +watch( + () => props.data, + (newval: any) => { + calcData(); + }, +); +watch( + () => props.config, + (newval: any) => { + calcData(); + }, +); +onMounted(() => { + calcData(); +}); +</script> + +<template> + <div class="dv-capsule-chart"> + <template v-if="mergedConfig"> + <div class="label-column"> + <div v-for="item in data" :key="item.name"> + {{ item.name }} + </div> + <div> </div> + </div> + <div class="capsule-container"> + <div class="capsule-item" v-for="(capsule, index) in capsuleLength" :key="index"> + <div class="capsule-item-column" :style="`width: ${capsule * 100}%; background-color: ${mergedConfig.colors[index % mergedConfig.colors.length] + };`"> + <div v-if="mergedConfig.showValue" class="capsule-item-value"> + {{ capsuleValue[index] }} + </div> + </div> + </div> + + <div class="unit-label"> + <div v-for="(label, index) in labelData" :key="label + index"> + {{ label }} + </div> + </div> + </div> + + <div class="unit-text" v-if="mergedConfig.unit"> + {{ mergedConfig.unit }} + </div> + </template> + </div> +</template> + +<style scoped lang="scss"> +.dv-capsule-chart { + position: relative; + display: flex; + flex-direction: row; + box-sizing: border-box; + padding: 10px; + color: #fff; + + .label-column { + display: flex; + flex-direction: column; + justify-content: space-between; + box-sizing: border-box; + padding-right: 10px; + text-align: right; + font-size: 12px; + + div { + height: 20px; + line-height: 20px; + } + } + + .capsule-container { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + } + + .capsule-item { + box-shadow: 0 0 3px #999; + height: 10px; + margin: 5px 0px; + border-radius: 5px; + + .capsule-item-column { + position: relative; + height: 8px; + margin-top: 1px; + border-radius: 5px; + transition: all 0.3s; + display: flex; + justify-content: flex-end; + align-items: center; + + .capsule-item-value { + font-size: 12px; + transform: translateX(100%); + } + } + } + + .unit-label { + height: 20px; + font-size: 12px; + position: relative; + display: flex; + justify-content: space-between; + align-items: center; + } + + .unit-text { + text-align: right; + display: flex; + align-items: flex-end; + font-size: 12px; + line-height: 20px; + margin-left: 10px; + } +} +</style> diff --git a/src/components/datav/capsule-chart/index.d.ts b/src/components/datav/capsule-chart/index.d.ts new file mode 100644 index 0000000..82277e8 --- /dev/null +++ b/src/components/datav/capsule-chart/index.d.ts @@ -0,0 +1,6 @@ +export interface DefaultConfigType { + + colors: Array<String>; + unit:string, + showValue:Boolean + } \ No newline at end of file diff --git a/src/components/datav/capsule-chart/index.ts b/src/components/datav/capsule-chart/index.ts new file mode 100644 index 0000000..5b874c0 --- /dev/null +++ b/src/components/datav/capsule-chart/index.ts @@ -0,0 +1,3 @@ +import CapsuleChart from "./capsule-chart.vue" +export * from "./index.d" +export default CapsuleChart \ No newline at end of file diff --git a/src/mock/mock-index.ts b/src/mock/mock-index.ts index 82e78c5..72f33fb 100644 --- a/src/mock/mock-index.ts +++ b/src/mock/mock-index.ts @@ -57,6 +57,50 @@ return a } }, + //鍙充笂 + { + url: "/bigscreen/alarmNum", + type: "get", + response: () => { + const a = Mock.mock({ + success: true, + data: { + dateList: ['2021-11', '2021-12', '2022-01', '2022-02', '2022-03', "2022-04"], + "numList|6": [ + '@integer(0, 1000)' + ], + "numList2|6": [ + '@integer(0, 1000)' + ] + } + }) + return a + } + }, + //鍙充腑 + { + url: "/bigscreen/ranking", + type: "get", + response: () => { + let num =Mock.mock({"list|80":[{ value:"@integer(50,1000)",name:"@city()"}]}).list + // console.log("ranking",num); + let newNum:any =[],numObj:any ={} + num.map((item:any )=>{ + if(!numObj[item.name] && newNum.length<8){ + numObj[item.name] =true + newNum.push(item) + } + }) + let arr = newNum.sort((a:any ,b:any )=>{ + return b.value-a.value + }) + let a ={ + success:true, + data:arr + } + return a + } + }, //瀹夎璁″垝 { url: "/bigscreen/installationPlan", diff --git a/src/plugins/echarts.ts b/src/plugins/echarts.ts index 25fe485..9103847 100644 --- a/src/plugins/echarts.ts +++ b/src/plugins/echarts.ts @@ -14,7 +14,8 @@ LegendComponent, DatasetComponent, VisualMapComponent, - GeoComponent + GeoComponent, + MarkPointComponent } from 'echarts/components' use([ @@ -26,7 +27,8 @@ TitleComponent, DatasetComponent, VisualMapComponent, - GeoComponent + GeoComponent, + MarkPointComponent ]) export const registerEcharts= (app:any)=>{ diff --git a/src/utils/public.ts b/src/utils/public.ts new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/utils/public.ts diff --git a/src/utils/query-param.ts b/src/utils/query-param.ts index 7defb3a..a0cdf6e 100644 --- a/src/utils/query-param.ts +++ b/src/utils/query-param.ts @@ -11,7 +11,7 @@ for (var i = 0; i < urlArray.length; i++) { var urlItem = urlArray[i]; var item = urlItem.split("="); - console.log(item); + // console.log(item); json[item[0]] = item[1]; } return json; diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index 35e6317..dd0535d 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -3,15 +3,14 @@ import { RouterView } from "vue-router"; import ScaleScreen from "@/components/scale-screen"; import Headers from "./header.vue"; -import Setting from "./setting.vue" +import Setting from "./setting.vue"; import { useSettingStore } from "@/stores/index"; -import { storeToRefs } from 'pinia'; -import MessageContent from '@/components/Plugins/MessageContent' +import { storeToRefs } from "pinia"; +import MessageContent from "@/components/Plugins/MessageContent"; const settingStore = useSettingStore(); -const {isScale} =storeToRefs(settingStore) +const { isScale } = storeToRefs(settingStore); const wrapperStyle = {}; - </script> <template> @@ -30,11 +29,10 @@ <div class="content_wrap"> <Headers /> <RouterView /> - <MessageContent/> - + <MessageContent /> </div> </scale-screen> - <Setting/> + <Setting /> </template> <style lang="scss" scoped> .content_wrap { diff --git a/src/views/index/center-bottom.vue b/src/views/index/center-bottom.vue index c047996..b0ee361 100644 --- a/src/views/index/center-bottom.vue +++ b/src/views/index/center-bottom.vue @@ -17,7 +17,6 @@ }); }; const setOption =async (newData: any) => { - await nextTick() option.value = { tooltip: { trigger: "axis", @@ -150,7 +149,10 @@ ], }; }; +onMounted(()=>{ getData(); + +}) </script> <template> diff --git a/src/views/index/right-center.vue b/src/views/index/right-center.vue index 7df5872..6f7af97 100644 --- a/src/views/index/right-center.vue +++ b/src/views/index/right-center.vue @@ -1,13 +1,39 @@ -<script setup lang='ts'> +<script setup lang="ts"> +import { ref, reactive } from "vue"; +import CapsuleChart from "@/components/datav/capsule-chart"; +import { currentGET } from "@/api"; +const config = ref({ + showValue: true, + unit: "娆�", +}); +const data= ref([]) +const getData = () => { + currentGET("rightCenter").then((res) => { + console.log("鎶ヨ鎺掑悕", res); + if (res.success) { + data.value =res.data; + } else { + window["$message"]({ + text: res.msg, + type: "warning", + }); + } + }); +}; +getData(); </script> <template> - <div class=''> - + <div class="right_bottom"> + <CapsuleChart :config="config" style="width: 100%; height: 260px" :data="data"/> </div> </template> -<style scoped lang='scss'> +<style scoped lang="scss"> -</style> \ No newline at end of file +.right_bottom { + box-sizing: border-box; + padding: 0 16px; +} +</style> diff --git a/src/views/index/right-top.vue b/src/views/index/right-top.vue index 7df5872..d0e33eb 100644 --- a/src/views/index/right-top.vue +++ b/src/views/index/right-top.vue @@ -1,13 +1,231 @@ -<script setup lang='ts'> +<script setup lang="ts"> +import { ref,onMounted} from "vue"; +import { currentGET } from "@/api"; +import {graphic} from "echarts/core" +const option = ref({}); +const getData = () => { + currentGET("rightTop", {}).then((res) => { + console.log("鎶ヨ娆℃暟 ", res); + if (res.success) { + setOption(res.data.dateList, res.data.numList, res.data.numList2); + } else { + window["$message"]({ + text: res.msg, + type: "warning", + }); + } + }); +}; +const setOption =async (xData:any[], yData:any[], yData2:any[]) => { + option.value = { + xAxis: { + type: "category", + data: xData, + boundaryGap: false, // 涓嶇暀鐧斤紝浠庡師鐐瑰紑濮� + splitLine: { + show: true, + lineStyle: { + color: "rgba(31,99,163,.2)", + }, + }, + axisLine: { + // show:false, + lineStyle: { + color: "rgba(31,99,163,.1)", + }, + }, + axisLabel: { + color: "#7EB7FD", + fontWeight: "500", + }, + }, + yAxis: { + type: "value", + splitLine: { + show: true, + lineStyle: { + color: "rgba(31,99,163,.2)", + }, + }, + axisLine: { + lineStyle: { + color: "rgba(31,99,163,.1)", + }, + }, + axisLabel: { + color: "#7EB7FD", + fontWeight: "500", + }, + }, + tooltip: { + trigger: "axis", + backgroundColor: "rgba(0,0,0,.6)", + borderColor: "rgba(147, 235, 248, .8)", + textStyle: { + color: "#FFF", + }, + }, + grid: { + //甯冨眬 + show: true, + left: "10px", + right: "30px", + bottom: "10px", + top: "32px", + containLabel: true, + borderColor: "#1F63A3", + }, + series: [ + { + data: yData, + type: "line", + smooth: true, + symbol: "none", //鍘婚櫎鐐� + name: "鎶ヨ1娆℃暟", + color: "rgba(252,144,16,.7)", + areaStyle: { + //鍙筹紝涓嬶紝宸︼紝涓� + color: new graphic.LinearGradient( + 0, + 0, + 0, + 1, + [ + { + offset: 0, + color: "rgba(252,144,16,.7)", + }, + { + offset: 1, + color: "rgba(252,144,16,.0)", + }, + ], + false + ), + }, + markPoint: { + data: [ + { + name: "鏈�澶у��", + type: "max", + valueDim: "y", + symbol: "rect", + symbolSize: [60, 26], + symbolOffset: [0, -20], + itemStyle: { + color: "rgba(0,0,0,0)", + }, + label: { + color: "#FC9010", + backgroundColor: "rgba(252,144,16,0.1)", + borderRadius: 6, + padding: [7, 14], + borderWidth: 0.5, + borderColor: "rgba(252,144,16,.5)", + formatter: "鎶ヨ1锛歿c}", + }, + }, + { + name: "鏈�澶у��", + type: "max", + valueDim: "y", + symbol: "circle", + symbolSize: 6, + itemStyle: { + color: "#FC9010", + shadowColor: "#FC9010", + shadowBlur: 8, + }, + label: { + formatter: "", + }, + }, + ], + }, + }, + { + data: yData2, + type: "line", + smooth: true, + symbol: "none", //鍘婚櫎鐐� + name: "鎶ヨ2娆℃暟", + color: "rgba(9,202,243,.7)", + areaStyle: { + //鍙筹紝涓嬶紝宸︼紝涓� + color: new graphic.LinearGradient( + 0, + 0, + 0, + 1, + [ + { + offset: 0, + color: "rgba(9,202,243,.7)", + }, + { + offset: 1, + color: "rgba(9,202,243,.0)", + }, + ], + false + ), + }, + markPoint: { + data: [ + { + name: "鏈�澶у��", + type: "max", + valueDim: "y", + symbol: "rect", + symbolSize: [60, 26], + symbolOffset: [0, -20], + itemStyle: { + color: "rgba(0,0,0,0)", + }, + label: { + color: "#09CAF3", + backgroundColor: "rgba(9,202,243,0.1)", + borderRadius: 6, + borderColor: "rgba(9,202,243,.5)", + padding: [7, 14], + formatter: "鎶ヨ2锛歿c}", + borderWidth: 0.5, + }, + }, + { + name: "鏈�澶у��", + type: "max", + valueDim: "y", + symbol: "circle", + symbolSize: 6, + itemStyle: { + color: "#09CAF3", + shadowColor: "#09CAF3", + shadowBlur: 8, + }, + label: { + formatter: "", + }, + }, + ], + }, + }, + ], + }; +} +onMounted(()=>{ + getData(); + +}) </script> <template> - <div class=''> - - </div> + <v-chart + class="chart" + :option="option" + v-if="JSON.stringify(option) != '{}'" + /> </template> -<style scoped lang='scss'> - -</style> \ No newline at end of file +<style scoped lang="scss"></style> diff --git a/src/views/setting.vue b/src/views/setting.vue index 92e0d99..1302013 100644 --- a/src/views/setting.vue +++ b/src/views/setting.vue @@ -26,7 +26,7 @@ </script> <template> - <el-drawer v-model="settingStore.settingShow" direction="rtl"> + <el-drawer v-model="settingStore.settingShow" direction="rtl" size="360px"> <template #header> <h2 class="setting-title">璁剧疆</h2> </template> -- Gitblit v1.8.0