feat(dashboard): 添加内容发布来源组件并更新数据面板
- 新增 ContentPublishingSource 组件,用于展示设备状态、设备类型和告警类型等图表 - 更新 DataPanel 组件,使用传入的设备、告警和产品信息进行展示 - 在主页面中引入新组件并优化布局
This commit is contained in:
parent
64d2079779
commit
0b660c69b0
@ -0,0 +1,403 @@
|
||||
<template>
|
||||
<a-spin :loading="loading" style="width: 100%">
|
||||
<a-grid :cols="24" :row-gap="10" :col-gap="10" class="panel">
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
:span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 8, xxl: 8 }"
|
||||
>
|
||||
<a-card
|
||||
class="general-card"
|
||||
>
|
||||
<Chart style="width: 100%; height: 300px" :option="deviceSatusChartOption" />
|
||||
</a-card>
|
||||
</a-grid-item>
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
:span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 8, xxl: 8 }"
|
||||
>
|
||||
<a-card
|
||||
class="general-card"
|
||||
>
|
||||
<Chart style="width: 100%; height: 300px" :option="deviceTypeChartOption" />
|
||||
</a-card>
|
||||
</a-grid-item>
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
:span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 8, xxl: 8 }"
|
||||
>
|
||||
<a-card
|
||||
class="general-card"
|
||||
>
|
||||
<Chart style="width: 100%; height: 300px" :option="warringTypeChartOption" />
|
||||
</a-card>
|
||||
</a-grid-item>
|
||||
</a-grid>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import useLoading from '@/hooks/loading';
|
||||
import useChartOption from '@/hooks/chart-option';
|
||||
|
||||
const props = defineProps({
|
||||
deviceInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
alarmInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
productInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const { chartOption: deviceSatusChartOption } = useChartOption((isDark) => {
|
||||
const graphicElementStyle = {
|
||||
textAlign: 'center',
|
||||
fill: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969',
|
||||
fontSize: 14,
|
||||
lineWidth: 10,
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
return {
|
||||
legend: {
|
||||
left: 'center',
|
||||
data: ['在线', '离线', '停用'],
|
||||
bottom: 0,
|
||||
icon: 'circle',
|
||||
itemWidth: 8,
|
||||
textStyle: {
|
||||
color: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969',
|
||||
},
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'item',
|
||||
},
|
||||
graphic: {
|
||||
elements: [
|
||||
{
|
||||
type: 'text',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
style: {
|
||||
text: '设备状态',
|
||||
...graphicElementStyle,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['50%', '70%'],
|
||||
center: ['50%', '50%'],
|
||||
label: {
|
||||
formatter: '{d}% ',
|
||||
color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
|
||||
},
|
||||
itemStyle: {
|
||||
borderColor: isDark ? '#000' : '#fff',
|
||||
borderWidth: 1,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: props.deviceInfo.onlineCount,
|
||||
name: '在线',
|
||||
itemStyle: {
|
||||
color: '#249EFF',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: props.deviceInfo.offlineCount,
|
||||
name: '离线',
|
||||
itemStyle: {
|
||||
color: '#846BCE',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: props.deviceInfo.disableCount,
|
||||
name: '停用',
|
||||
itemStyle: {
|
||||
color: '#21CCFF',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
// {
|
||||
// type: 'pie',
|
||||
// radius: ['50%', '70%'],
|
||||
// center: ['50%', '50%'],
|
||||
// label: {
|
||||
// formatter: '{d}% ',
|
||||
// color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
|
||||
// },
|
||||
// itemStyle: {
|
||||
// borderColor: isDark ? '#000' : '#fff',
|
||||
// borderWidth: 1,
|
||||
// },
|
||||
// data: [
|
||||
// {
|
||||
// value: [148564],
|
||||
// name: 'UGC原创',
|
||||
// itemStyle: {
|
||||
// color: '#249EFF',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [334271],
|
||||
// name: '国外网站',
|
||||
// itemStyle: {
|
||||
// color: '#846BCE',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [445694],
|
||||
// name: '转载文章',
|
||||
// itemStyle: {
|
||||
// color: '#21CCFF',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [445694],
|
||||
// name: '行业报告',
|
||||
// itemStyle: {
|
||||
// color: '#0E42D2',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [445694],
|
||||
// name: '其他',
|
||||
// itemStyle: {
|
||||
// color: '#86DF6C',
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// type: 'pie',
|
||||
// radius: ['50%', '70%'],
|
||||
// center: ['88%', '50%'],
|
||||
// label: {
|
||||
// formatter: '{d}% ',
|
||||
// color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
|
||||
// },
|
||||
// itemStyle: {
|
||||
// borderColor: isDark ? '#000' : '#fff',
|
||||
// borderWidth: 1,
|
||||
// },
|
||||
// data: [
|
||||
// {
|
||||
// value: [148564],
|
||||
// name: 'UGC原创',
|
||||
// itemStyle: {
|
||||
// color: '#249EFF',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [334271],
|
||||
// name: '国外网站',
|
||||
// itemStyle: {
|
||||
// color: '#846BCE',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [445694],
|
||||
// name: '转载文章',
|
||||
// itemStyle: {
|
||||
// color: '#21CCFF',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [445694],
|
||||
// name: '行业报告',
|
||||
// itemStyle: {
|
||||
// color: '#0E42D2',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// value: [445694],
|
||||
// name: '其他',
|
||||
// itemStyle: {
|
||||
// color: '#86DF6C',
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
};
|
||||
});
|
||||
const { chartOption: deviceTypeChartOption } = useChartOption((isDark) => {
|
||||
const graphicElementStyle = {
|
||||
textAlign: 'center',
|
||||
fill: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969',
|
||||
fontSize: 14,
|
||||
lineWidth: 10,
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
return {
|
||||
legend: {
|
||||
left: 'center',
|
||||
data: ['直连设备', '网关设备', '网关子设备'],
|
||||
bottom: 0,
|
||||
icon: 'circle',
|
||||
itemWidth: 8,
|
||||
textStyle: {
|
||||
color: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969',
|
||||
},
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'item',
|
||||
},
|
||||
graphic: {
|
||||
elements: [
|
||||
{
|
||||
type: 'text',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
style: {
|
||||
text: '设备类型',
|
||||
...graphicElementStyle,
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['50%', '70%'],
|
||||
center: ['50%', '50%'],
|
||||
label: {
|
||||
formatter: '{d}% ',
|
||||
color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
|
||||
},
|
||||
itemStyle: {
|
||||
borderColor: isDark ? '#000' : '#fff',
|
||||
borderWidth: 1,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: props.deviceInfo.directCount,
|
||||
name: '直连设备',
|
||||
itemStyle: {
|
||||
color: '#249EFF',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: props.deviceInfo.gatewayCount,
|
||||
name: '网关设备',
|
||||
itemStyle: {
|
||||
color: '#846BCE',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: props.deviceInfo.gatewaySubCount,
|
||||
name: '网关子设备',
|
||||
itemStyle: {
|
||||
color: '#21CCFF',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
const { chartOption: warringTypeChartOption } = useChartOption((isDark) => {
|
||||
const graphicElementStyle = {
|
||||
textAlign: 'center',
|
||||
fill: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969',
|
||||
fontSize: 14,
|
||||
lineWidth: 10,
|
||||
fontWeight: 'bold',
|
||||
};
|
||||
return {
|
||||
legend: {
|
||||
left: 'center',
|
||||
data: ['注意', '告警', '严重'],
|
||||
bottom: 0,
|
||||
icon: 'circle',
|
||||
itemWidth: 8,
|
||||
textStyle: {
|
||||
color: isDark ? 'rgba(255,255,255,0.7)' : '#4E5969',
|
||||
},
|
||||
itemStyle: {
|
||||
borderWidth: 0,
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'item',
|
||||
},
|
||||
graphic: {
|
||||
elements: [
|
||||
{
|
||||
type: 'text',
|
||||
left: 'center',
|
||||
top: 'center',
|
||||
style: {
|
||||
text: '告警类型',
|
||||
...graphicElementStyle,
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
series: [
|
||||
{
|
||||
type: 'pie',
|
||||
radius: ['50%', '70%'],
|
||||
center: ['50%', '50%'],
|
||||
label: {
|
||||
formatter: '{d}% ',
|
||||
color: isDark ? 'rgba(255, 255, 255, 0.7)' : '#4E5969',
|
||||
},
|
||||
itemStyle: {
|
||||
borderColor: isDark ? '#000' : '#fff',
|
||||
borderWidth: 1,
|
||||
},
|
||||
data: [
|
||||
{
|
||||
value: props.alarmInfo.firstWarningCount,
|
||||
name: '注意',
|
||||
itemStyle: {
|
||||
color: '#249EFF',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: props.alarmInfo.secondWarningCount,
|
||||
name: '告警',
|
||||
itemStyle: {
|
||||
color: '#846BCE',
|
||||
},
|
||||
},
|
||||
{
|
||||
value: props.alarmInfo.thirdWarningCount,
|
||||
name: '严重',
|
||||
itemStyle: {
|
||||
color: '#ff2121',
|
||||
},
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
});
|
||||
const { loading } = useLoading(false);
|
||||
</script>
|
||||
|
||||
<style scoped lang="less"></style>
|
@ -11,7 +11,7 @@
|
||||
<a-statistic
|
||||
title="产品数"
|
||||
value-style="font-size:36px"
|
||||
:value="365"
|
||||
:value="props.productInfo.productCount"
|
||||
:value-from="0"
|
||||
animation
|
||||
>
|
||||
@ -32,7 +32,7 @@
|
||||
<!-- />-->
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-descriptions :data="data" layout="inline-vertical" class="responsive-margin" />
|
||||
<a-descriptions :data="productData" layout="inline-vertical" class="responsive-margin" />
|
||||
|
||||
|
||||
</a-card>
|
||||
@ -47,7 +47,7 @@
|
||||
<a-statistic
|
||||
title="设备数"
|
||||
value-style="font-size:36px"
|
||||
:value="deviceInfo.deviceCount"
|
||||
:value="props.deviceInfo.deviceCount"
|
||||
:value-from="0"
|
||||
animation
|
||||
>
|
||||
@ -62,7 +62,7 @@
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-descriptions :data="data" layout="inline-vertical" class="responsive-margin" />
|
||||
<a-descriptions :data="deviceData" layout="inline-vertical" class="responsive-margin" />
|
||||
|
||||
|
||||
</a-card>
|
||||
@ -77,7 +77,7 @@
|
||||
<a-statistic
|
||||
title="产品数"
|
||||
value-style="font-size:36px"
|
||||
:value="365"
|
||||
:value="props.alarmInfo.warningCount"
|
||||
:value-from="0"
|
||||
animation
|
||||
>
|
||||
@ -92,7 +92,7 @@
|
||||
/>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-descriptions :data="data" layout="inline-vertical" class="responsive-margin" />
|
||||
<a-descriptions :data="alarmData" layout="inline-vertical" class="responsive-margin" />
|
||||
|
||||
|
||||
</a-card>
|
||||
@ -107,97 +107,65 @@
|
||||
<a-divider class="panel-border" />
|
||||
</a-grid-item>
|
||||
</a-grid>
|
||||
<a-grid :span="24" :row-gap="10" :col-gap="10" class="panel">
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 }">
|
||||
<ChainItem
|
||||
title="分享总量"
|
||||
quota="share"
|
||||
chart-type="pie"
|
||||
:card-style="{
|
||||
background: isDark
|
||||
? 'linear-gradient(180deg, #312565 0%, #201936 100%)'
|
||||
: 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)',
|
||||
}"
|
||||
/>
|
||||
</a-grid-item>
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 }">
|
||||
<ChainItem
|
||||
title="分享总量"
|
||||
quota="share"
|
||||
chart-type="pie"
|
||||
:card-style="{
|
||||
background: isDark
|
||||
? 'linear-gradient(180deg, #312565 0%, #201936 100%)'
|
||||
: 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)',
|
||||
}"
|
||||
/>
|
||||
</a-grid-item>
|
||||
<a-grid-item
|
||||
class="panel-col"
|
||||
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 }">
|
||||
<ChainItem
|
||||
title="分享总量"
|
||||
quota="share"
|
||||
chart-type="pie"
|
||||
:card-style="{
|
||||
background: isDark
|
||||
? 'linear-gradient(180deg, #312565 0%, #201936 100%)'
|
||||
: 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)',
|
||||
}"
|
||||
/>
|
||||
</a-grid-item>
|
||||
<a-grid-item :span="24">
|
||||
<a-divider class="panel-border" />
|
||||
</a-grid-item>
|
||||
</a-grid>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import Announcement from '@/views/dashboard/workplace/components/announcement.vue';
|
||||
import ChainItem from '@/views/dashboard/workplace/components/chain-item.vue';
|
||||
import useThemes from '@/hooks/themes';
|
||||
import { getDeviceInfo } from '@/api/dashboard';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { ref } from 'vue';
|
||||
|
||||
const data = [{
|
||||
label: 'Name',
|
||||
value: 'Socrates',
|
||||
const props = defineProps(
|
||||
{
|
||||
deviceInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
alarmInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
productInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
},
|
||||
},
|
||||
}
|
||||
);
|
||||
const productData = [{
|
||||
label: '启用',
|
||||
value: props.productInfo.enabledCount,
|
||||
}, {
|
||||
label: 'Mobile',
|
||||
value: '123',
|
||||
}, {
|
||||
label: 'Residence',
|
||||
value: 'Beijing'
|
||||
label: '停用',
|
||||
value: props.productInfo.disabledCount,
|
||||
}];
|
||||
const deviceInfo = ref({
|
||||
deviceCount: 0,
|
||||
onlineCount: 0,
|
||||
offlineCount: 0,
|
||||
alarmCount: 0,
|
||||
productCount: 0,
|
||||
})
|
||||
const fetchData = async () => {
|
||||
const res = await getDeviceInfo();
|
||||
deviceInfo.value = res.data;
|
||||
}
|
||||
const { isDark } = useThemes();
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
})
|
||||
const deviceData = [
|
||||
{
|
||||
label: '属性',
|
||||
value: props.deviceInfo.propertyCount,
|
||||
}, {
|
||||
label: '服务',
|
||||
value: props.deviceInfo.serveCount,
|
||||
}, {
|
||||
label: '事件',
|
||||
value: props.deviceInfo.eventCount,
|
||||
}];
|
||||
const alarmData = [{
|
||||
label: '今日新增',
|
||||
value: props.alarmInfo.todayWarningCount,
|
||||
}];
|
||||
console.log(props.deviceInfo, props.alarmInfo, props.productInfo);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.arco-grid.panel {
|
||||
margin-bottom: 0;
|
||||
padding: 10px 20px 0 0;
|
||||
}
|
||||
.panel-col {
|
||||
padding-left: 20px; // 修改: 调整内边距以使卡片看起来更大
|
||||
border-right: 1px solid rgb(var(--gray-2));
|
||||
}
|
||||
.col-avatar {
|
||||
@ -222,7 +190,6 @@
|
||||
}
|
||||
.responsive-margin {
|
||||
margin-top: 20px; // 默认值
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -3,7 +3,8 @@
|
||||
<div class="left-side">
|
||||
<div class="panel">
|
||||
<Banner />
|
||||
<DataPanel />
|
||||
<DataPanel v-if="computedDeviceInfo && alarmInfo && productInfo" :deviceInfo="computedDeviceInfo" :alarmInfo='alarmInfo' :productInfo='productInfo' />
|
||||
<ContentPublishingSource v-if="computedDeviceInfo && alarmInfo && productInfo" :deviceInfo="computedDeviceInfo" :alarmInfo='alarmInfo' :productInfo='productInfo' />
|
||||
</div>
|
||||
<a-grid :cols="24" :col-gap="16" :row-gap="16" style="margin-top: 16px">
|
||||
<a-grid-item
|
||||
@ -16,32 +17,38 @@
|
||||
</a-grid-item>
|
||||
</a-grid>
|
||||
</div>
|
||||
<!-- <div class="right-side">-->
|
||||
<!-- <a-grid :cols="24" :row-gap="16">-->
|
||||
<!-- <a-grid-item :span="24">-->
|
||||
<!-- <div class="panel moduler-wrap">-->
|
||||
<!--<!– <QuickOperation />–>-->
|
||||
<!--<!– <RecentlyVisited />–>-->
|
||||
<!-- </div>-->
|
||||
<!-- </a-grid-item>-->
|
||||
<!-- <a-grid-item class="panel" :span="24">-->
|
||||
<!-- <Announcement />-->
|
||||
<!-- </a-grid-item>-->
|
||||
<!-- <a-grid-item class="panel" :span="24">-->
|
||||
<!-- <Announcement />-->
|
||||
<!-- </a-grid-item>-->
|
||||
<!-- <a-grid-item class="panel" :span="24"> </a-grid-item>-->
|
||||
<!-- </a-grid>-->
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { getAlarmInfo, getDeviceInfo, getProductInfo } from '@/api/dashboard';
|
||||
import Banner from './components/banner.vue';
|
||||
import DataPanel from './components/data-panel.vue';
|
||||
import RecentlyVisited from './components/recently-visited.vue';
|
||||
import QuickOperation from './components/quick-operation.vue';
|
||||
import Announcement from './components/announcement.vue';
|
||||
import ContentPublishingSource from './components/content-publishing-source.vue';
|
||||
|
||||
const deviceInfo = ref<any>();
|
||||
const computedDeviceInfo = computed(() => {
|
||||
return deviceInfo.value; // 返回 deviceInfo 的值
|
||||
});
|
||||
const alarmInfo = ref<any>();
|
||||
const productInfo = ref<any>();
|
||||
|
||||
const fetchData = async () => {
|
||||
const res = await getDeviceInfo();
|
||||
deviceInfo.value = res.data;
|
||||
const res1 = await getAlarmInfo();
|
||||
alarmInfo.value = res1.data;
|
||||
const res2 = await getProductInfo();
|
||||
productInfo.value = res2.data;
|
||||
console.log(computedDeviceInfo.value);
|
||||
console.log(deviceInfo.value);
|
||||
}
|
||||
onMounted(() => {
|
||||
fetchData();
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
Loading…
Reference in New Issue
Block a user