许宏杰 2 weeks ago
commit d6a11710b9

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

@ -21,4 +21,8 @@
@font-face {
font-family: 'Alimama ShuHeiTi-Bold';
src: url("../font/ALIMAMASHUHEITI-BOLD.TTF");
}
@font-face {
font-family: 'LESLIE';
src: url("../font/LESLIEB.ttf");
}

@ -1,7 +1,9 @@
<template>
<div class="panel-block">
<div class="panel-block__header">{{ title }}</div>
<div class="panel-block__body"></div>
<div class="panel-block__body">
<slot></slot>
</div>
</div>
</template>

@ -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,105 @@
<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: ["4月1日", "4月2日", "4月3日", "4月4日", "4月5日"],
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: "line",
data: [30, 60, 90, 80, 110],
smooth: false, // 线
symbol: "circle", //
lineStyle: {
color: "#3BE0FD",
width: 2,
},
areaStyle: {
color: {
type: "linear",
x: 0,
y: 0,
x2: 0,
y2: 1,
colorStops: [
{ offset: 0, color: "rgba(59, 224, 253, 0.4)" }, //
{ offset: 1, color: "rgba(59, 224, 253, 0)" }, //
],
},
},
itemStyle: {
borderWidth: 0,
},
},
],
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,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,142 @@
<template>
<cellRow>
<div class="row-one">
<span>养护班组</span>
<span>5</span>
<div class="wifi" style="visibility: hidden;">
<img
src="@/assets/images/WiFi.png"
alt=""
/>
<span>10</span>
</div>
</div>
</cellRow>
<cellRow>
<div class="row-one">
<span>巡查人员</span>
<span>16</span>
<div class="wifi">
<img
src="@/assets/images/WiFi.png"
alt=""
/>
<span>10</span>
</div>
</div>
</cellRow>
<cellRow>
<div class="row-three">
<!-- -->
<div>
<img
src="@/assets/images/caricon.png"
alt=""
/>
<div>
<span>车辆总数</span>
<span class="carnumber">36</span>
</div>
</div>
<!-- -->
<div class="jiantou">
<img
src="@/assets/images/jiantou.png"
alt=""
/>
</div>
<!-- -->
<div class="three-right">
<span>运行中</span>
<span class="carnumber">16</span>
</div>
</div>
</cellRow>
</template>
<script setup>
import cellRow from "./cellRow.vue";
</script>
<style>
.row-one {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
height: 37px;
color: #fff;
font-size: 12px;
font-family: "MiSans-Regular";
color: rgba(255, 255, 255, 0.8);
span:nth-child(2) {
color: #00eeff;
font-family: "LESLIE";
font-size: 16px;
}
.wifi {
display: flex;
align-items: center;
gap: 4px;
img {
width: 14px;
}
}
.wifi span {
margin-top: 1px;
color: #64d886;
font-family: "LESLIE";
}
}
.row-three {
width: 100%;
display: flex;
justify-content: space-around;
align-items: center;
height: 57px;
color: #fff;
font-size: 12px;
padding: 10px;
padding-right: 20px;
img {
width: 45px;
height: 45px;
}
div:nth-child(1) {
display: flex;
gap: 5px;
align-items: center;
color: rgba(255, 255, 255, 0.8);
div {
display: flex;
flex-direction: column;
gap: 3px;
}
}
div:nth-child(3) {
display: flex;
flex-direction: column;
}
.jiantou {
height: 100%;
padding-top: 4px;
display: flex;
justify-content: center;
img {
width: 80%;
height: 8px;
}
}
}
.three-right {
display: flex;
flex-direction: column;
gap: 3px;
color: rgba(255, 255, 255, 0.8);
}
.carnumber {
font-family: "LESLIE";
color: #ffffff;
font-size: 18px;
}
</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>

@ -1,13 +1,11 @@
<template>
<div class="emergency-container">
<containerLeft></containerLeft>
<div class="main-right">
<panelBlock title="最新预警信息"></panelBlock>
<panelBlock title="工单数量变化分析"></panelBlock>
<panelBlock title="工作量统计分析"></panelBlock>
</div>
<containerLeft></containerLeft>
<containerRight></containerRight>
<div class="main-bottom">
<panelBlock title="最新应急抢险工单"></panelBlock>
<panelBlock title="最新应急抢险工单">
<containerBottom></containerBottom>
</panelBlock>
</div>
<MarsMap
:url="configUrl"
@ -25,7 +23,10 @@ import { onUnmounted } from "vue";
import wallImg from "@/assets/images/visualization/fence-top.png";
import areaBg from "@/assets/images/visualization/area-bg.png";
import { panelBlock } from "@/views/visualization/components/index";
import containerLeft from "./components/containerLeft.vue"
import containerLeft from "./components/containerLeft.vue";
import containerRight from "./components/containerRight.vue";
import containerBottom from "./components/containerBottom.vue";
//
const configUrl = "lib/config/config.json";
let mapData = null;
@ -148,7 +149,6 @@ onUnmounted(() => {
padding-bottom: 34px;
width: 16%;
height: 100%;
}
.main-left {
@ -162,9 +162,9 @@ onUnmounted(() => {
bottom: 0;
left: 50%;
transform: translateX(-50%);
height:calc((100% / 3) - 20px);
height: calc((100% / 3) - 20px);
z-index: 10;
width:55%;
width: 55%;
padding-bottom: 34px;
}
}

@ -3,7 +3,8 @@ export default {
chinaCRS: mars3d.ChinaCRS.GCJ02, // 标识坐标系
},
scene: {
center: {"lat":31.167163,"lng":121.430428,"alt":36454.4,"heading":357.1,"pitch":-89.8},
// 原先的lat:31.167163
center: {"lat":31.147163,"lng":121.430428,"alt":36454.4,"heading":357.1,"pitch":-89.8},
// sceneMode:2,
showSun: false, //太阳
showMoon: false, //月亮

Loading…
Cancel
Save