376 lines
8.2 KiB
Vue
376 lines
8.2 KiB
Vue
<script setup lang="ts">
|
|
import { ref, onMounted } from "vue";
|
|
import * as echarts from "echarts";
|
|
|
|
const welcomeText = ref("欢迎使用智慧湿地管理平台");
|
|
|
|
// 统计数据
|
|
const statistics = ref({
|
|
species: {
|
|
total: 128,
|
|
today: 12,
|
|
trend: "+8%",
|
|
},
|
|
environment: {
|
|
normal: 22,
|
|
abnormal: 2,
|
|
trend: "normal",
|
|
},
|
|
patrol: {
|
|
total: 12,
|
|
completed: 8,
|
|
progress: "66%",
|
|
},
|
|
devices: {
|
|
total: 36,
|
|
online: 32,
|
|
rate: "88.9%",
|
|
},
|
|
});
|
|
|
|
// 初始化趋势图表
|
|
const initTrendChart = () => {
|
|
const chartDom = document.getElementById("trendChart");
|
|
if (!chartDom) return;
|
|
|
|
const myChart = echarts.init(chartDom);
|
|
const option = {
|
|
title: {
|
|
text: "近7天监测数据趋势",
|
|
left: "center",
|
|
top: 0,
|
|
textStyle: {
|
|
fontSize: 16,
|
|
fontWeight: 500,
|
|
},
|
|
},
|
|
tooltip: {
|
|
trigger: "axis",
|
|
},
|
|
legend: {
|
|
data: ["物种数量", "水质指数"],
|
|
top: 25,
|
|
},
|
|
grid: {
|
|
top: 70,
|
|
left: "3%",
|
|
right: "4%",
|
|
bottom: "3%",
|
|
containLabel: true,
|
|
},
|
|
xAxis: {
|
|
type: "category",
|
|
boundaryGap: false,
|
|
data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
|
|
},
|
|
yAxis: {
|
|
type: "value",
|
|
},
|
|
series: [
|
|
{
|
|
name: "物种数量",
|
|
type: "line",
|
|
data: [120, 132, 101, 134, 90, 230, 210],
|
|
smooth: true,
|
|
},
|
|
{
|
|
name: "水质指数",
|
|
type: "line",
|
|
data: [220, 182, 191, 234, 290, 330, 310],
|
|
smooth: true,
|
|
},
|
|
],
|
|
};
|
|
|
|
myChart.setOption(option);
|
|
};
|
|
|
|
// 初始化分布图表
|
|
const initDistributionChart = () => {
|
|
const chartDom = document.getElementById("distributionChart");
|
|
if (!chartDom) return;
|
|
|
|
const myChart = echarts.init(chartDom);
|
|
const option = {
|
|
title: {
|
|
text: "物种分布统计",
|
|
left: "center",
|
|
top: 0,
|
|
textStyle: {
|
|
fontSize: 16,
|
|
fontWeight: 500,
|
|
},
|
|
},
|
|
tooltip: {
|
|
trigger: "item",
|
|
},
|
|
legend: {
|
|
orient: "vertical",
|
|
left: "left",
|
|
top: 25,
|
|
},
|
|
series: [
|
|
{
|
|
name: "物种分布",
|
|
type: "pie",
|
|
radius: "50%",
|
|
top: 60,
|
|
data: [
|
|
{ value: 1048, name: "鸟类" },
|
|
{ value: 735, name: "鱼类" },
|
|
{ value: 580, name: "两栖类" },
|
|
{ value: 484, name: "植物" },
|
|
{ value: 300, name: "其他" },
|
|
],
|
|
emphasis: {
|
|
itemStyle: {
|
|
shadowBlur: 10,
|
|
shadowOffsetX: 0,
|
|
shadowColor: "rgba(0, 0, 0, 0.5)",
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
|
|
myChart.setOption(option);
|
|
};
|
|
|
|
// 最新动态
|
|
const activities = ref([
|
|
{
|
|
content: "发现新增鸟类物种:东方白鹳",
|
|
timestamp: "2024-03-20 10:30",
|
|
type: "success",
|
|
},
|
|
{
|
|
content: "B区水质监测点发现异常",
|
|
timestamp: "2024-03-20 09:15",
|
|
type: "warning",
|
|
},
|
|
{
|
|
content: "完成今日巡护任务",
|
|
timestamp: "2024-03-20 08:00",
|
|
type: "success",
|
|
},
|
|
]);
|
|
|
|
onMounted(() => {
|
|
initTrendChart();
|
|
initDistributionChart();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="dashboard-container">
|
|
<div class="welcome-section">
|
|
<h2>{{ welcomeText }}</h2>
|
|
</div>
|
|
|
|
<!-- 统计卡片 -->
|
|
<el-row :gutter="20" class="mt-20">
|
|
<el-col :span="8">
|
|
<el-card
|
|
class="statistics-card"
|
|
shadow="hover"
|
|
@click="handleCardClick('/monitor/species')"
|
|
>
|
|
<template #header>
|
|
<div class="statistics-header">
|
|
<span>物种监测</span>
|
|
<el-tag size="small" type="success">{{ statistics.species.trend }}</el-tag>
|
|
</div>
|
|
</template>
|
|
<div class="statistics-content">
|
|
<div class="main-number">{{ statistics.species.total }}</div>
|
|
<div class="sub-info">
|
|
<span>今日新增</span>
|
|
<span class="highlight">{{ statistics.species.today }}</span>
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
</el-col>
|
|
|
|
<el-col :span="8">
|
|
<el-card
|
|
class="statistics-card"
|
|
shadow="hover"
|
|
>
|
|
<template #header>
|
|
<div class="statistics-header">
|
|
<span>环境监测</span>
|
|
<el-tag
|
|
size="small"
|
|
type="warning"
|
|
v-if="statistics.environment.abnormal > 0"
|
|
>
|
|
{{ statistics.environment.abnormal }}个异常
|
|
</el-tag>
|
|
</div>
|
|
</template>
|
|
<div class="statistics-content">
|
|
<div class="main-number">{{ statistics.environment.normal }}</div>
|
|
<div class="sub-info">
|
|
<span>监测点位</span>
|
|
<span class="highlight">正常</span>
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
</el-col>
|
|
|
|
<el-col :span="8">
|
|
<el-card
|
|
class="statistics-card"
|
|
shadow="hover"
|
|
@click="handleCardClick('/patrol/tasks')"
|
|
>
|
|
<template #header>
|
|
<div class="statistics-header">
|
|
<span>巡护任务</span>
|
|
<el-tag size="small" type="info">{{ statistics.patrol.progress }}</el-tag>
|
|
</div>
|
|
</template>
|
|
<div class="statistics-content">
|
|
<div class="main-number">{{ statistics.patrol.completed }}</div>
|
|
<div class="sub-info">
|
|
<span>已完成</span>
|
|
<span class="highlight">共{{ statistics.patrol.total }}个</span>
|
|
</div>
|
|
</div>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<!-- 图表区域 -->
|
|
<el-row :gutter="20" class="mt-20">
|
|
<el-col :span="16">
|
|
<el-card>
|
|
<div id="trendChart" style="height: 400px; padding-top: 10px"></div>
|
|
</el-card>
|
|
</el-col>
|
|
<el-col :span="8">
|
|
<el-card>
|
|
<div id="distributionChart" style="height: 400px; padding-top: 10px"></div>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
|
|
<!-- 最新动态 -->
|
|
<el-row :gutter="20" class="mt-20">
|
|
<el-col :span="24">
|
|
<el-card>
|
|
<template #header>
|
|
<div class="card-header">
|
|
<span>最新动态</span>
|
|
</div>
|
|
</template>
|
|
<el-timeline>
|
|
<el-timeline-item
|
|
v-for="(activity, index) in activities"
|
|
:key="index"
|
|
:type="activity.type"
|
|
:timestamp="activity.timestamp"
|
|
>
|
|
{{ activity.content }}
|
|
</el-timeline-item>
|
|
</el-timeline>
|
|
</el-card>
|
|
</el-col>
|
|
</el-row>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "../../styles/variables.scss";
|
|
|
|
.dashboard-container {
|
|
.welcome-card {
|
|
background: linear-gradient(
|
|
135deg,
|
|
$primary-color 0%,
|
|
lighten($primary-color, 20%) 100%
|
|
);
|
|
padding: 24px;
|
|
border-radius: 8px;
|
|
color: white;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
|
|
h2 {
|
|
margin: 0;
|
|
font-size: 24px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.welcome-subtitle {
|
|
margin: 8px 0 0;
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
.statistics-card {
|
|
transition: transform 0.3s;
|
|
cursor: pointer;
|
|
|
|
&:hover {
|
|
transform: translateY(-5px);
|
|
}
|
|
|
|
.statistics-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
|
|
span {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: $text-primary;
|
|
}
|
|
}
|
|
|
|
.statistics-content {
|
|
padding: 20px 0;
|
|
|
|
.main-number {
|
|
font-size: 36px;
|
|
font-weight: 600;
|
|
color: $text-primary;
|
|
line-height: 1;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.sub-info {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
color: $text-secondary;
|
|
|
|
.highlight {
|
|
color: $primary-color;
|
|
font-weight: 500;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.mt-20 {
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.card-header {
|
|
font-size: 16px;
|
|
font-weight: 500;
|
|
color: $text-primary;
|
|
}
|
|
|
|
:deep(.el-timeline-item__content) {
|
|
color: $text-regular;
|
|
}
|
|
|
|
:deep(.el-card) {
|
|
border: none;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
|
|
}
|
|
}
|
|
</style>
|