Merge branch 'main' of http://39.101.188.84:7000/suzhou-jichuang-lanhai/park-shanghai
commit
d6a11710b9
Binary file not shown.
After Width: | Height: | Size: 369 B |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 8.4 KiB |
After Width: | Height: | Size: 294 B |
After Width: | Height: | Size: 26 KiB |
@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div ref="chartDom" class="echarts-container"></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
const chartDom = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
const myChart = echarts.init(chartDom.value);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
formatter: (params) => {
|
||||
return `${params[0].axisValue}<br/>数值: ${params[0].value}`;
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['一阶段', '二阶段', '三阶段', '四阶段'],
|
||||
axisLine: {
|
||||
show: false // 隐藏x轴线
|
||||
},
|
||||
axisTick: {
|
||||
show: false // 隐藏刻度
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#fff' // 坐标轴文字颜色
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: 120,
|
||||
interval: 20,
|
||||
axisLine: {
|
||||
show: false // 隐藏y轴线
|
||||
},
|
||||
axisTick: {
|
||||
show: false // 隐藏刻度
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#fff'
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
}
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '阶段数据',
|
||||
type: 'bar',
|
||||
data: [40, 60, 90, 110],
|
||||
barWidth: 12,
|
||||
itemStyle: {
|
||||
borderRadius: 6, // 圆角柱形
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#3CE2FF' },
|
||||
{ offset: 0.57, color: 'rgba(18,211,172,0.38)' },
|
||||
{ offset: 1, color: 'rgba(18,115,211,0)' }
|
||||
]
|
||||
}
|
||||
},
|
||||
emphasis: {
|
||||
disabled: true
|
||||
}
|
||||
}
|
||||
],
|
||||
grid: {
|
||||
top: 20,
|
||||
bottom: 20,
|
||||
left: 40,
|
||||
right: 20
|
||||
}
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
myChart.resize();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.echarts-container {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,20 @@
|
||||
<template>
|
||||
<div class="cell-row">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup></script>
|
||||
|
||||
<style scoped>
|
||||
.cell-row {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background: linear-gradient(
|
||||
180deg,
|
||||
rgba(33, 39, 53, 0) 0%,
|
||||
rgba(18, 116, 210, 0.3) 100%
|
||||
);
|
||||
border-radius: 0px 0px 10px 10px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<div class="container-bottom">
|
||||
<!-- 表头 -->
|
||||
<div class="table-head">
|
||||
<div class="table-row header">
|
||||
<span>工单描述</span>
|
||||
<span>上报时间</span>
|
||||
<span>区域负责人</span>
|
||||
<span>负责人联系方式</span>
|
||||
<span>操作</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 数据行 -->
|
||||
<cellRow
|
||||
v-for="(item, index) in tableData"
|
||||
:key="index"
|
||||
>
|
||||
<div class="table-container">
|
||||
<div class="table-row data">
|
||||
<span>{{ item.desc }}</span>
|
||||
<span>{{ item.time }}</span>
|
||||
<span>{{ item.person }}</span>
|
||||
<span>{{ item.contact }}</span>
|
||||
<div class="status-container">
|
||||
<span :class="['status-tag', getStatusClass(item.status)]">{{
|
||||
item.status
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cellRow>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import cellRow from "./cellRow.vue";
|
||||
|
||||
// 表格数据
|
||||
const tableData = ref([
|
||||
{
|
||||
desc: "金山南路生活垃圾乱堆乱放",
|
||||
time: "2021-05-05 09:05:05",
|
||||
person: "王小虎",
|
||||
contact: "18888888888",
|
||||
status: "待处理",
|
||||
},
|
||||
{
|
||||
desc: "浦东新区道路积水严重",
|
||||
time: "2021-06-01 14:30:00",
|
||||
person: "王小虎",
|
||||
contact: "17777777777",
|
||||
status: "处理中",
|
||||
},
|
||||
{
|
||||
desc: "徐汇区路灯故障",
|
||||
time: "2021-07-15 08:20:00",
|
||||
person: "张三",
|
||||
contact: "13333333333",
|
||||
status: "已处理",
|
||||
},
|
||||
]);
|
||||
|
||||
// 根据状态返回对应的类名
|
||||
const getStatusClass = (status) => {
|
||||
switch (status) {
|
||||
case "待处理":
|
||||
return "status-pending";
|
||||
case "处理中":
|
||||
return "status-processing";
|
||||
case "已处理":
|
||||
return "status-done";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.container-bottom {
|
||||
padding-top: 8px;
|
||||
}
|
||||
.table-head {
|
||||
width: 100%;
|
||||
padding: 10px 0 0px 40px;
|
||||
display: grid;
|
||||
}
|
||||
.table-container {
|
||||
width: 100%;
|
||||
padding: 12px 0 12px 40px;
|
||||
display: grid;
|
||||
gap: 17px;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-template-columns: 2fr 2fr 2fr 2fr 1fr;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
span:last-child {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
color: #9cbeff;
|
||||
font-family: "MiSans-Regular";
|
||||
}
|
||||
|
||||
.data {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-family: "MiSans-Regular";
|
||||
}
|
||||
|
||||
.status-container{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
/* 状态标签通用样式 */
|
||||
.status-tag {
|
||||
width: 60%;
|
||||
padding: 6px 0px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
border-radius: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 待处理 - 橙色 */
|
||||
.status-pending {
|
||||
background-color: #CA7A2A;
|
||||
}
|
||||
|
||||
/* 处理中 - 蓝色 */
|
||||
.status-processing {
|
||||
background-color: #2A95CA;
|
||||
}
|
||||
|
||||
/* 已处理 - 绿色 */
|
||||
.status-done {
|
||||
background-color: #5DCA2A;
|
||||
}
|
||||
</style>
|
@ -1,22 +1,30 @@
|
||||
<template>
|
||||
<div class="main-left">
|
||||
<panelBlock title="应急抢险资源"></panelBlock>
|
||||
<panelBlock title="应急抢险工单"></panelBlock>
|
||||
<panelBlock title="工单派发及完成率分析"></panelBlock>
|
||||
</div>
|
||||
<div class="main-left">
|
||||
<panelBlock title="应急抢险资源">
|
||||
<resources></resources>
|
||||
</panelBlock>
|
||||
<panelBlock title="应急抢险工单">
|
||||
<pieEchart></pieEchart>
|
||||
</panelBlock>
|
||||
<panelBlock title="工单派发及完成率分析">
|
||||
<hopperEchart></hopperEchart>
|
||||
</panelBlock>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { panelBlock } from "@/views/visualization/components/index";
|
||||
import resources from "./resources.vue";
|
||||
import pieEchart from "./pieEchart.vue";
|
||||
import hopperEchart from "./hopperEchart.vue";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main-left{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&>div{
|
||||
flex: 1;
|
||||
}
|
||||
<style lang="scss" scoped>
|
||||
.main-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
& > div {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="main-right">
|
||||
<panelBlock title="最新预警信息">
|
||||
<warning></warning>
|
||||
</panelBlock>
|
||||
<panelBlock title="工单数量变化分析">
|
||||
<lineEchart></lineEchart>
|
||||
</panelBlock>
|
||||
<panelBlock title="工作量统计分析">
|
||||
<barEchart></barEchart>
|
||||
</panelBlock>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { panelBlock } from "@/views/visualization/components/index";
|
||||
import warning from "./warning.vue";
|
||||
import lineEchart from "./lineEchart.vue";
|
||||
import barEchart from "./barEchart.vue";
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main-right {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
& > div {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,128 @@
|
||||
<template>
|
||||
<div
|
||||
ref="chartDom"
|
||||
class="echarts-container"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
const chartDom = ref(null);
|
||||
|
||||
onMounted(() => {
|
||||
const myChart = echarts.init(chartDom.value);
|
||||
|
||||
// 原始数据
|
||||
const rawData = [
|
||||
{ value: 50, name: "应急工单录入" },
|
||||
{ value: 30, name: "工单受理派发" },
|
||||
{ value: 20, name: "工单处理完成" },
|
||||
];
|
||||
|
||||
// 计算总数
|
||||
const total = rawData.reduce((sum, item) => sum + item.value, 0);
|
||||
|
||||
// 百分比
|
||||
const processedData = rawData.map((item) => ({
|
||||
...item,
|
||||
percent: Math.round((item.value / total) * 100),
|
||||
itemStyle: {
|
||||
color: getColor(item.name),
|
||||
},
|
||||
}));
|
||||
|
||||
const option = {
|
||||
animation: false,
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
formatter: (params) => {
|
||||
return `${params.name}<br/>数值: ${params.data.value}<br/>占比: ${params.data.percent}%`;
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "工单派发及完成率分析",
|
||||
type: "funnel",
|
||||
width: "50%",
|
||||
height: "90%",
|
||||
left: "10%",
|
||||
top: "5%",
|
||||
minSize: "20%", //底部变方
|
||||
sort: "descending",
|
||||
label: {
|
||||
show: true,
|
||||
position: "inside",
|
||||
formatter: "{c}%",
|
||||
color: "#fff",
|
||||
fontSize: 13,
|
||||
fontWeight: "bold",
|
||||
fontFamily: "MiSans-Regular",
|
||||
},
|
||||
labelLine: {
|
||||
show: false,
|
||||
},
|
||||
itemStyle: {
|
||||
borderWidth: 0, // 去掉边线
|
||||
},
|
||||
data: processedData.map((item) => ({
|
||||
...item,
|
||||
value: item.percent,
|
||||
})),
|
||||
emphasis: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "funnel",
|
||||
width: "50%",
|
||||
height: "90%",
|
||||
left: "10%",
|
||||
top: "5%",
|
||||
minSize: "20%", // 底部变方
|
||||
sort: "descending",
|
||||
label: {
|
||||
show: true,
|
||||
position: "right",
|
||||
formatter: (params) => {
|
||||
return `${params.name}: ${
|
||||
rawData.find((d) => d.name === params.name).value
|
||||
}`;
|
||||
},
|
||||
color: "#fff",
|
||||
fontSize: 12,
|
||||
align: "left",
|
||||
padding: [0, 0, 0, 10],
|
||||
verticalAlign: "middle", // 垂直居中
|
||||
},
|
||||
itemStyle: {
|
||||
borderWidth: 0, //去掉边线
|
||||
},
|
||||
data: processedData,
|
||||
emphasis: {
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
});
|
||||
|
||||
function getColor(name) {
|
||||
const colors = {
|
||||
应急工单录入: "#395EB0",
|
||||
工单受理派发: "#5595F7",
|
||||
工单处理完成: "#6BABF8",
|
||||
};
|
||||
return colors[name] || "#999";
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.echarts-container {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,122 @@
|
||||
<template>
|
||||
<div class="chart-container">
|
||||
<div
|
||||
id="pieChart"
|
||||
class="pie-chart"
|
||||
></div>
|
||||
<div class="legend">
|
||||
<div
|
||||
v-for="(item, index) in chartData"
|
||||
:key="index"
|
||||
class="legend-item"
|
||||
>
|
||||
<span
|
||||
class="color-box"
|
||||
:style="{ backgroundColor: colors[index] }"
|
||||
></span>
|
||||
<span class="label">{{ item.name }}</span>
|
||||
<span class="value">{{ item.percent }}%</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted } from "vue";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
const chartData = [
|
||||
{ name: "断枝", value: 35 },
|
||||
{ name: "倾斜", value: 40 },
|
||||
{ name: "倒伏", value: 25 },
|
||||
];
|
||||
|
||||
const total = chartData.reduce((sum, item) => sum + item.value, 0);
|
||||
chartData.forEach((item) => {
|
||||
item.percent = ((item.value / total) * 100).toFixed(1);
|
||||
});
|
||||
|
||||
const colors = ["#29CC82", "#FAC300", "#5765FF"];
|
||||
|
||||
const initChart = () => {
|
||||
const chartDom = document.getElementById("pieChart");
|
||||
const myChart = echarts.init(chartDom);
|
||||
|
||||
const option = {
|
||||
tooltip: { trigger: 'item' },
|
||||
color: colors,
|
||||
series: [
|
||||
{
|
||||
type: "pie",
|
||||
radius: ["50%", "70%"],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
data: chartData.map((item) => ({
|
||||
value: item.value,
|
||||
name: item.name,
|
||||
})),
|
||||
itemStyle: (params) => {
|
||||
const color = colors[params.dataIndex];
|
||||
return {
|
||||
color: color,
|
||||
borderColor: color,
|
||||
borderWidth: 0,
|
||||
};
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
initChart();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.chart-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
|
||||
.legend {
|
||||
font-family: Arial, sans-serif;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.color-box {
|
||||
display: inline-block;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 8px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.label {
|
||||
margin-right: 10px;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #fff;
|
||||
margin-top: 1px;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div>
|
||||
<!-- 台风 -->
|
||||
<cellRow>
|
||||
<div class="row-main">
|
||||
<img
|
||||
src="@/assets/images/taifeng.png"
|
||||
alt=""
|
||||
/>
|
||||
<div class="row-main-right">
|
||||
<div class="right-top">
|
||||
<span>台风黄色预警</span>
|
||||
<span>5月18日</span>
|
||||
</div>
|
||||
<div class="right-bottom">
|
||||
<span>东北风</span>
|
||||
<span>风力7~8级</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cellRow>
|
||||
<!-- 暴雨 -->
|
||||
<cellRow>
|
||||
<div class="row-main">
|
||||
<img
|
||||
src="@/assets/images/baoyu.png"
|
||||
alt=""
|
||||
/>
|
||||
<div class="row-main-right">
|
||||
<div class="right-top">
|
||||
<span>暴雨黄色预警</span>
|
||||
<span>5月19日</span>
|
||||
</div>
|
||||
<div class="right-bottom">
|
||||
<span>大暴雨</span>
|
||||
<span>小时雨量大于50毫米</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</cellRow>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import cellRow from "./cellRow.vue";
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.row-main {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 5px;
|
||||
align-items: center;
|
||||
height: 75px;
|
||||
margin-bottom: 5px;
|
||||
font-size: 14px;
|
||||
img {
|
||||
width: 75px;
|
||||
height: 65px;
|
||||
}
|
||||
.row-main-right {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
font-family: "MiSans-Regular";
|
||||
.right-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
color: #ffffff;
|
||||
span:nth-child(1) {
|
||||
color: #f4ec19;
|
||||
font-family: "MiSans-Medium";
|
||||
}
|
||||
}
|
||||
.right-bottom{
|
||||
display: flex;
|
||||
color: #ffffff;
|
||||
gap: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
Loading…
Reference in new issue