492 lines
13 KiB
Vue
492 lines
13 KiB
Vue
<script setup lang='ts'>
|
||
import { useI18n } from 'vue-i18n';
|
||
|
||
import { getEmailList, getRecentEmailDatas, getRecentEmailDatasMonth, getTaskHisSta, getTaskStatsDay, getTaskStatsMonth } from '@/utils/axios/sjtbJcfx/index';
|
||
import DataAnalysis from './dataAnalysis.vue';
|
||
import HisCumulative from './hisCumulative.vue';
|
||
import StackChart from './stackChart.vue';
|
||
|
||
const { t } = useI18n();
|
||
|
||
interface SampleItem {
|
||
name: string;
|
||
value: number;
|
||
}
|
||
|
||
// 历史累计同步数据
|
||
const hisCumulativeList = ref<SampleItem[]>([]);
|
||
|
||
// ---------- 1. 定义StackChart需要的图表数据结构 ----------
|
||
interface StackChartData {
|
||
xList: string[]; // x轴分类(小时/日期)
|
||
seriesList: {
|
||
name: string;
|
||
data: number[];
|
||
}[]; // 系列数据
|
||
}
|
||
// 初始化StackChart的数据源(对应你提供的接口数据)
|
||
const stackChartData = ref<StackChartData>({
|
||
xList: [],
|
||
seriesList: [],
|
||
});
|
||
|
||
// 同步数据分析数据(供DataAnalysis子组件使用)
|
||
const chartData = ref({
|
||
xList: [],
|
||
seriesList: [],
|
||
});
|
||
|
||
// 同步数据分析ref实例
|
||
const dataAnalysisRef = ref<InstanceType<typeof DataAnalysis> | null>(null);
|
||
const analysisList = ref<any>([]);
|
||
|
||
// 邮箱图表ref实例
|
||
const stackChartRef = ref<InstanceType<typeof StackChart> | null>(null);
|
||
|
||
function switchActive(index: any) {
|
||
analysisList.value.forEach((item: any) => {
|
||
item.active = false;
|
||
});
|
||
analysisList.value[index].active = true;
|
||
const activeTab = stackChartRef?.value?.activeTab || 'day';
|
||
const activeEmailId = analysisList.value.find((item: any) => item.active)?.id || '';
|
||
if (!activeEmailId)
|
||
return;
|
||
|
||
if (activeTab === 'day') {
|
||
getRecentEmailDatas(activeEmailId, (res) => {
|
||
formatStackChartData(res, 'day');
|
||
});
|
||
}
|
||
else {
|
||
getRecentEmailDatasMonth(activeEmailId, (res) => {
|
||
formatStackChartData(res, 'month');
|
||
});
|
||
}
|
||
}
|
||
|
||
// ---------- 2. 格式化StackChart的接口数据 ----------
|
||
function formatStackChartData(res: any, type: 'day' | 'month') {
|
||
if (!res)
|
||
return;
|
||
stackChartData.value.xList = res.categories || [];
|
||
|
||
// 按维度区分系列名称和数据
|
||
if (type === 'day') {
|
||
stackChartData.value.seriesList = [
|
||
{ name: '今日报警', data: res.series.todayAlarm || [] },
|
||
{ name: '今日处理', data: res.series.todayProcess || [] },
|
||
{ name: '昨日报警', data: res.series.yesterdayAlarm || [] },
|
||
{ name: '昨日处理', data: res.series.yesterdayProcess || [] },
|
||
];
|
||
}
|
||
else {
|
||
stackChartData.value.seriesList = [
|
||
{ name: '本月报警', data: res.series.alarm || [] },
|
||
{ name: '本月处理', data: res.series.process || [] },
|
||
// 若月维度有其他字段,补充对应名称
|
||
];
|
||
}
|
||
}
|
||
|
||
// ---------- 3. 核心:数据格式化工具函数(原DataAnalysis用) ----------
|
||
function formatChartData(res: any) {
|
||
const { dateTimes = [], taskStatsInfos = [] } = res;
|
||
const seriesList: any = [];
|
||
|
||
taskStatsInfos.forEach((task: any) => {
|
||
const { taskName, taskStats = [] } = task;
|
||
const data = Array.from({ length: dateTimes.length }).fill(0);
|
||
|
||
taskStats.forEach((stat: any) => {
|
||
const { dateTime, syncNum } = stat;
|
||
const dateIndex = dateTimes.indexOf(dateTime);
|
||
if (dateIndex > -1) {
|
||
data[dateIndex] = Number(syncNum) || 0;
|
||
}
|
||
});
|
||
|
||
seriesList.push({
|
||
name: taskName,
|
||
data,
|
||
});
|
||
});
|
||
|
||
return {
|
||
xList: dateTimes,
|
||
seriesList,
|
||
};
|
||
}
|
||
|
||
// ---------- 4. 完善查询数据逻辑 ----------
|
||
async function getData() {
|
||
// 1. 查询历史累计数据
|
||
getTaskHisSta((res) => {
|
||
hisCumulativeList.value = res.map((item: any) => ({
|
||
name: item.taskName,
|
||
value: Number(item.syncNum) || 0,
|
||
}));
|
||
});
|
||
|
||
// 2. 获取DataAnalysis子组件Tab维度
|
||
const activeTab = dataAnalysisRef?.value?.activeTab || 'day';
|
||
if (activeTab === 'day') {
|
||
getTaskStatsDay(true, (res) => {
|
||
chartData.value = formatChartData(res);
|
||
});
|
||
}
|
||
else {
|
||
getTaskStatsMonth(true, (res) => {
|
||
chartData.value = formatChartData(res);
|
||
});
|
||
}
|
||
|
||
// 3. 获取StackChart子组件Tab维度并请求数据
|
||
const activeTab2 = stackChartRef?.value?.activeTab || 'day';
|
||
const activeEmailId = analysisList.value.find((item: any) => item.active)?.id || '';
|
||
if (!activeEmailId)
|
||
return;
|
||
|
||
if (activeTab2 === 'day') {
|
||
getRecentEmailDatas(activeEmailId, (res) => {
|
||
console.log('StackChart日维度数据:', res);
|
||
formatStackChartData(res, 'day'); // 格式化并赋值
|
||
});
|
||
}
|
||
else {
|
||
getRecentEmailDatasMonth(activeEmailId, (res) => {
|
||
console.log('StackChart月维度数据:', res);
|
||
formatStackChartData(res, 'month'); // 格式化并赋值
|
||
});
|
||
}
|
||
}
|
||
|
||
// ---------- 5. 生命周期与定时器 ----------
|
||
onMounted(() => {
|
||
// 获取邮箱列表
|
||
getEmailList((res) => {
|
||
analysisList.value = res.map((item: any) => ({
|
||
id: item.sourceId,
|
||
label: item.sourceName,
|
||
active: false,
|
||
}));
|
||
analysisList.value[0].active = true;
|
||
nextTick(() => {
|
||
getData();
|
||
});
|
||
});
|
||
|
||
const timer = setInterval(() => {
|
||
getData();
|
||
}, 10000);
|
||
|
||
onUnmounted(() => {
|
||
clearInterval(timer);
|
||
});
|
||
});
|
||
|
||
// ---------- 6. 监听DataAnalysis Tab切换 ----------
|
||
watch(() => dataAnalysisRef?.value?.activeTab, () => {
|
||
const activeTab = dataAnalysisRef?.value?.activeTab || 'day';
|
||
if (activeTab === 'day') {
|
||
getTaskStatsDay(false, (res) => {
|
||
chartData.value = formatChartData(res);
|
||
});
|
||
}
|
||
else {
|
||
getTaskStatsMonth(false, (res) => {
|
||
chartData.value = formatChartData(res);
|
||
});
|
||
}
|
||
}, { immediate: false });
|
||
|
||
// ---------- 7. 监听StackChart Tab切换 ----------
|
||
watch(() => stackChartRef?.value?.activeTab, () => {
|
||
const activeTab = stackChartRef?.value?.activeTab || 'day';
|
||
const activeEmailId = analysisList.value.find((item: any) => item.active)?.id || '';
|
||
|
||
if (!activeEmailId)
|
||
return;
|
||
if (activeTab === 'day') {
|
||
getRecentEmailDatas(activeEmailId, (res) => {
|
||
formatStackChartData(res, 'day');
|
||
});
|
||
}
|
||
else {
|
||
getRecentEmailDatasMonth(activeEmailId, (res) => {
|
||
formatStackChartData(res, 'month');
|
||
});
|
||
}
|
||
}, { immediate: false });
|
||
</script>
|
||
|
||
<template>
|
||
<div class="largeScreen1">
|
||
<div class="header">
|
||
<div class="logoDom">
|
||
<div class="logo">
|
||
<SvgIcon name="logo" width="50" height="50" />
|
||
<div class="title">
|
||
{{ t('analysisTitle') }}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="contnetBg">
|
||
<div class="content">
|
||
<div class="IDCHeader">
|
||
<div class="left">
|
||
IDC数据同步状态
|
||
</div>
|
||
<div class="right" />
|
||
</div>
|
||
<div class="topChart">
|
||
<div class="left">
|
||
<div class="topChartHeader">
|
||
<div class="title">
|
||
同步数据分析
|
||
</div>
|
||
<div class="status">
|
||
同步异常:网络断开
|
||
</div>
|
||
</div>
|
||
<div class="dataAnalysisDom">
|
||
<DataAnalysis ref="dataAnalysisRef" :chart-data="chartData" />
|
||
</div>
|
||
</div>
|
||
<div class="right">
|
||
<div class="topChartHeader">
|
||
<div class="title">
|
||
历史累积同步
|
||
</div>
|
||
<div class="status" />
|
||
</div>
|
||
<div class="hisCumulativeDom">
|
||
<HisCumulative :list="hisCumulativeList" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="bottomChart">
|
||
<div class="bottomChartHeader">
|
||
<div class="left">
|
||
<div v-for="(v, i) in analysisList" :key="i" class="analysisItem" :class="{ active: v.active }"
|
||
@click="switchActive(i)">
|
||
{{ v.label }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="right">
|
||
<span>连接状态:</span>
|
||
<span class="status">连接中</span>
|
||
</div>
|
||
</div>
|
||
<div class="stackChartDom">
|
||
<StackChart ref="stackChartRef" :chart-data="stackChartData" />
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped lang='less'>
|
||
.largeScreen1 {
|
||
width: 100%;
|
||
background: url('@/assets/img/largeScreenBg.png') no-repeat center center;
|
||
background-size: 100% 100%;
|
||
|
||
.header {
|
||
width: 100%;
|
||
height: 74px;
|
||
background: url('@/assets/img/largeScreenHeader.png') no-repeat center center;
|
||
background-size: 100% 100%;
|
||
position: relative;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
.logoDom {
|
||
min-width: 50px;
|
||
height: 74px;
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: center;
|
||
padding-top: 5px;
|
||
|
||
.logo {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.title {
|
||
margin-left: 9px;
|
||
letter-spacing: 9px;
|
||
font-size: 28px;
|
||
color: #ffffff;
|
||
}
|
||
}
|
||
}
|
||
|
||
.contnetBg {
|
||
width: 100%;
|
||
height: calc(100vh - 74px);
|
||
background: url('@/assets/img/largeScreenContentBg.png') no-repeat center center;
|
||
background-size: 100% 100%;
|
||
padding: 30px 27px;
|
||
|
||
.content {
|
||
width: 100%;
|
||
height: 100%;
|
||
|
||
.IDCHeader {
|
||
width: 100%;
|
||
height: 39px;
|
||
border-top: 1px solid rgb(7, 84, 75);
|
||
border-bottom: 4px solid rgb(7, 84, 75);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding-right: 50px;
|
||
margin-bottom: 15px;
|
||
|
||
.left {
|
||
width: 186px;
|
||
height: 40px;
|
||
font-size: 18px;
|
||
background: rgba(12, 235, 201, 0.05);
|
||
color: rgb(12, 235, 201);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
|
||
.right {
|
||
width: 83px;
|
||
height: 16px;
|
||
background: url('@/assets/img/IDCBg.png') no-repeat center center;
|
||
background-size: 100% 100%;
|
||
}
|
||
}
|
||
|
||
.topChart {
|
||
width: 100%;
|
||
height: 416px;
|
||
margin-bottom: 22px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
|
||
.left {
|
||
width: 1333px;
|
||
height: 100%;
|
||
|
||
.topChartHeader {
|
||
width: 100%;
|
||
height: 40px;
|
||
background-color: rgba(12, 235, 201, 0.08);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 12px;
|
||
|
||
.title {
|
||
color: rgb(173, 230, 238);
|
||
}
|
||
|
||
.status {
|
||
color: rgb(255, 75, 75);
|
||
}
|
||
}
|
||
|
||
.dataAnalysisDom {
|
||
width: 100%;
|
||
height: calc(100% - 40px);
|
||
}
|
||
}
|
||
|
||
.right {
|
||
width: 501px;
|
||
height: 100%;
|
||
|
||
.topChartHeader {
|
||
width: 100%;
|
||
height: 40px;
|
||
background-color: rgba(12, 235, 201, 0.08);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 12px;
|
||
|
||
.title {
|
||
color: rgb(173, 230, 238);
|
||
}
|
||
|
||
.status {
|
||
color: rgb(255, 75, 75);
|
||
}
|
||
}
|
||
|
||
.hisCumulativeDom {
|
||
width: 100%;
|
||
height: calc(100% - 40px);
|
||
}
|
||
}
|
||
}
|
||
|
||
.bottomChart {
|
||
width: 100%;
|
||
height: calc(100% - 416px - 22px - 39px - 15px);
|
||
|
||
.bottomChartHeader {
|
||
width: 100%;
|
||
height: 40px;
|
||
background-color: rgba(12, 235, 201, 0.08);
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 0 12px;
|
||
|
||
.left {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.analysisItem {
|
||
width: auto;
|
||
height: 30px;
|
||
margin-right: 10px;
|
||
color: #c9f6f6;
|
||
background: url('@/assets/img/tabsBtn_default.png') no-repeat center center;
|
||
background-size: 100% 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
padding: 0 15px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.analysisItem.active {
|
||
background: url('@/assets/img/tabsBtn_active.png') no-repeat center center;
|
||
background-size: 100% 100%;
|
||
}
|
||
}
|
||
|
||
.right {
|
||
color: #ade6ee;
|
||
|
||
.status {
|
||
color: #35eb4e;
|
||
}
|
||
}
|
||
}
|
||
|
||
.stackChartDom {
|
||
width: 100%;
|
||
height: calc(100% - 40px);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|