refactor(map): 7月28日需求修改

master
LiuJiaNan 2026-07-28 16:31:04 +08:00
parent 47353e9760
commit 4ce4e42c1d
52 changed files with 732 additions and 927 deletions

View File

@ -25,7 +25,7 @@ import pointIco36 from "~/assets/images/map_bi/point/ico36.png";
export const branchOfficeUtilsList = [
{
label: "重点作业",
label: "危险作业",
type: "danger",
list: [
{
@ -92,16 +92,16 @@ export const branchOfficeUtilsList = [
request: "getEightWorkInfoScreenWorkList",
titleKey: "checkNo",
},
{
label: "摄像头",
check: false,
type: "dangerCamera",
markIcon: pointIco3,
},
// {
// label: "摄像头",
// check: false,
// type: "dangerCamera",
// markIcon: pointIco3,
// },
],
},
{
label: "口门门禁",
label: "封闭区域",
type: "door",
list: [
{
@ -239,7 +239,7 @@ export const branchOfficeUtilsList = [
],
},
{
label: "重点工程",
label: "重点作业",
type: "keyProject",
list: [
{
@ -274,9 +274,9 @@ export const branchOfficeUtilsList = [
},
],
},
{
label: "封闭区域",
type: "closedArea",
list: [],
},
// {
// label: "封闭区域",
// type: "closedArea",
// list: [],
// },
];

View File

@ -9,6 +9,7 @@
&.port {
top: 920px;
.option {
position: relative;
cursor: pointer;
@ -91,6 +92,7 @@
&.branch_office {
top: 1020px;
.option {
position: relative;
cursor: pointer;

View File

@ -61,10 +61,10 @@ import ico28 from "~/assets/images/map_bi/bottom_utils/second/ico28.png";
import ico28On from "~/assets/images/map_bi/bottom_utils/second/ico28_on.png";
import ico29 from "~/assets/images/map_bi/bottom_utils/second/ico29.png";
import ico29On from "~/assets/images/map_bi/bottom_utils/second/ico29_on.png";
import ico30 from "~/assets/images/map_bi/bottom_utils/second/ico30.png";
import ico30On from "~/assets/images/map_bi/bottom_utils/second/ico30_on.png";
import ico31 from "~/assets/images/map_bi/bottom_utils/second/ico31.png";
import ico31On from "~/assets/images/map_bi/bottom_utils/second/ico31_on.png";
// import ico30 from "~/assets/images/map_bi/bottom_utils/second/ico30.png";
// import ico30On from "~/assets/images/map_bi/bottom_utils/second/ico30_on.png";
// import ico31 from "~/assets/images/map_bi/bottom_utils/second/ico31.png";
// import ico31On from "~/assets/images/map_bi/bottom_utils/second/ico31_on.png";
import ico32 from "~/assets/images/map_bi/bottom_utils/second/ico32.png";
import ico32On from "~/assets/images/map_bi/bottom_utils/second/ico32_on.png";
// 地图点位图片资源
@ -89,9 +89,9 @@ import pointIco19 from "~/assets/images/map_bi/point/ico19.png";
import pointIco30 from "~/assets/images/map_bi/point/ico30.png";
import pointIco31 from "~/assets/images/map_bi/point/ico31.png";
import pointIco32 from "~/assets/images/map_bi/point/ico32.png";
import pointIco34 from "~/assets/images/map_bi/point/ico34.png";
// import pointIco34 from "~/assets/images/map_bi/point/ico34.png";
import pointIco35 from "~/assets/images/map_bi/point/ico35.png";
import pointIco36 from "~/assets/images/map_bi/point/ico36.png";
// import pointIco36 from "~/assets/images/map_bi/point/ico36.png";
export const portUtilsList = [
{
@ -110,22 +110,22 @@ export const portUtilsList = [
request: "getPrimeportMkmjScreenList",
titleKey: "mkmjName",
},
{
label: "人员",
check: false,
img: ico30,
checkImg: ico30On,
markIcon: pointIco36,
type: "person",
},
{
label: "车辆",
check: false,
img: ico31,
checkImg: ico31On,
markIcon: pointIco34,
type: "car",
},
// {
// label: "人员",
// check: false,
// img: ico30,
// checkImg: ico30On,
// markIcon: pointIco36,
// type: "person",
// },
// {
// label: "车辆",
// check: false,
// img: ico31,
// checkImg: ico31On,
// markIcon: pointIco34,
// type: "car",
// },
{
label: "人员闸机",
check: false,
@ -229,7 +229,7 @@ export const portUtilsList = [
{
img: bottomImg6,
checkImg: bottomImg6On,
label: "重点作业",
label: "危险作业",
type: "danger",
list: [
{
@ -312,14 +312,14 @@ export const portUtilsList = [
request: "getEightWorkInfoScreenWorkList",
titleKey: "checkNo",
},
{
label: "摄像头",
check: false,
type: "dangerCamera",
img: ico3,
checkImg: ico3On,
markIcon: pointIco3,
},
// {
// label: "摄像头",
// check: false,
// type: "dangerCamera",
// img: ico3,
// checkImg: ico3On,
// markIcon: pointIco3,
// },
],
},
{
@ -389,7 +389,7 @@ export const portUtilsList = [
{
img: bottomImg12,
checkImg: bottomImg12On,
label: "重点工程",
label: "重点作业",
type: "keyProject",
list: [
{

View File

@ -64,7 +64,9 @@ function VideoPatrolPanel(props) {
className="index-info-video-patrol__screen"
style={{ backgroundImage: `url(${background})` }}
>
<Spin spinning={props.biStatistics.getFixedCameraVideoListLoading || props.biStatistics.getFixedCameraPlayUrlLoading}>
<Spin
spinning={props.biStatistics.getFixedCameraVideoListLoading || props.biStatistics.getFixedCameraPlayUrlLoading}
>
{playUrl
? (
<AliPlayer source={playUrl} height="100%" isLive />

View File

@ -18,14 +18,14 @@ function HazardSourcePanel() {
<div className="index-info-hazard-source__group">
<HazardSummary
background={summaryBackground}
title="二级重大危险源(1个)"
count="3"
disabled="2"
title="二级重大危险源(0个)"
count="0"
disabled="0"
/>
<HazardSummary
background={summaryBackground}
title="三级重大危险源(2个)"
count="10"
title="三级重大危险源(0个)"
count="0"
disabled="0"
/>
</div>
@ -54,7 +54,7 @@ function HazardSourcePanel() {
<strong>报警处置情况</strong>
<p>温度待处置数/报警个数0/0</p>
<p>压力待处置数/报警个数0/0</p>
<p>液位待处置数/报警个数1/1</p>
<p>液位待处置数/报警个数0/0</p>
</div>
</div>
</Panel>

View File

@ -7,9 +7,9 @@ import "./index.less";
function GatePanel() {
const items = [
["一级口门进出统计", gateBackground],
["进入申请待审批", gateBackground],
["封闭区域人员情况", closedBackground],
["封闭区域作业情况", closedBackground],
["一级口门进出审批", gateBackground],
["封闭区域进出统计", closedBackground],
["封闭区域进出审批", closedBackground],
];
return (
<Panel

View File

@ -54,7 +54,9 @@ function WorkPanel(props) {
}, []);
return (
<Panel title="重点作业管理统计" className="index-info-right-panel__work">
<Spin spinning={props.biStatistics.getEightWorkInfoDangerWorkStatisticsLoading || props.biStatistics.getKeyProjectLargeScreenStatisticsLoading}>
<Spin
spinning={props.biStatistics.getEightWorkInfoDangerWorkStatisticsLoading || props.biStatistics.getKeyProjectLargeScreenStatisticsLoading}
>
<div className="index-info-work__list">
{data.map(item => (
<div className="index-info-work__item" key={item.name}>

View File

@ -2,6 +2,7 @@ import Bottom from "./Bottom";
import Btn from "./Btn";
import LeftPanel from "./LeftPanel";
import RightPanel from "./RightPanel";
// import Search from "./Search";
function IndexInfo(props) {

View File

@ -14,6 +14,7 @@ const gridList = [
{ title: "九宫格", value: 9, gridColumnCount: 3, gridRowCount: 3 },
{ title: "单画面", value: 1, gridColumnCount: 1, gridRowCount: 1 },
];
function Camera(props) {
const { portArea, currentBranchOffice } = useContext(Context);
@ -127,7 +128,13 @@ function Camera(props) {
</Spin>
<div className="branch-office-camera-modal__pagination">
<Button disabled={currentPage === 0} onClick={() => setCurrentPage(currentPage - 1)}>上一组</Button>
<Button disabled={currentPage >= pageCount - 1} type="primary" onClick={() => setCurrentPage(currentPage + 1)}>下一组</Button>
<Button
disabled={currentPage >= pageCount - 1}
type="primary"
onClick={() => setCurrentPage(currentPage + 1)}
>
下一组
</Button>
</div>
</div>
</div>

View File

@ -9,20 +9,14 @@ import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import { getAlertColor, getWeatherIcon } from "~/utils/weather";
import "./index.less";
const records = [
{ department: "技术部", requiredDevices: 150, anchoredDevices: 142 },
{ department: "销售部", requiredDevices: 80, anchoredDevices: 76 },
{ department: "市场部", requiredDevices: 60, anchoredDevices: 58 },
{ department: "运营部", requiredDevices: 120, anchoredDevices: 115 },
{ department: "客服部", requiredDevices: 90, anchoredDevices: 88 },
{ department: "财务部", requiredDevices: 30, anchoredDevices: 29 },
{ department: "人事部", requiredDevices: 25, anchoredDevices: 24 },
{ department: "研发部", requiredDevices: 200, anchoredDevices: 195 },
{ department: "质量部", requiredDevices: 45, anchoredDevices: 42 },
{ department: "采购部", requiredDevices: 35, anchoredDevices: 33 },
const statistics = [
{ label: "部门数", value: 10 },
{ label: "人员数", value: 1250 },
{ label: "相关单位数", value: 23 },
{ label: "相关方人员数", value: 1680 },
];
/** 负责查询并展示天气、预警和部门设备锚定情况。 */
/** 负责查询并展示天气、预警及人员相关统计。 */
function WeatherPreventionPanel(props) {
const [weather, setWeather] = useState({});
const [alerts, setAlerts] = useState([]);
@ -63,6 +57,9 @@ function WeatherPreventionPanel(props) {
</div>
</div>
<div className="branch-office-weather-prevention__alerts">
{
alerts.length > 0
? (
<SeamlessScroll
list={alerts}
step={0.5}
@ -79,8 +76,11 @@ function WeatherPreventionPanel(props) {
</div>
))}
</SeamlessScroll>
)
: <div className="branch-office-weather-prevention__no-alerts">当前暂无气象预警</div>
}
</div>
<DepartmentTable records={records} />
<Statistics />
</div>
</Spin>
</Panel>
@ -104,26 +104,16 @@ function WeatherMetric({ icon, label, value }) {
);
}
/** 天气预防区块内的部门设备锚定列表。 */
function DepartmentTable({ records }) {
/** 天气预防区块内的部门及相关方统计块。 */
function Statistics() {
return (
<div className="branch-office-weather-prevention__table">
<div className="branch-office-weather-prevention__row">
<div>部门名称</div>
<div>需锚定设备数</div>
<div>已锚定设备数</div>
</div>
<div className="branch-office-weather-prevention__table-body">
<SeamlessScroll list={records} step={0.5}>
{records.map((item, index) => (
<div className="branch-office-weather-prevention__row" key={index}>
<div>{item.department}</div>
<div>{item.requiredDevices}</div>
<div>{item.anchoredDevices}</div>
<div className="branch-office-weather-prevention__statistics">
{statistics.map(item => (
<div className="branch-office-weather-prevention__statistic" key={item.label}>
<div className="branch-office-weather-prevention__statistic-label">{item.label}</div>
<div className="branch-office-weather-prevention__statistic-value">{item.value}</div>
</div>
))}
</SeamlessScroll>
</div>
</div>
);
}

View File

@ -58,28 +58,28 @@
.branch-office-weather-prevention__alerts {
height: 20px;
margin-top: 10px;
overflow-y: hidden;
}
.branch-office-weather-prevention__no-alerts {
font-size: 14px;
color: #fff;
}
.branch-office-weather-prevention__alert {
font-size: 14px;
font-weight: bold;
}
.branch-office-weather-prevention__table {
margin-top: 5px;
}
.branch-office-weather-prevention__table-body {
height: 60px;
overflow-y: hidden;
}
.branch-office-weather-prevention__row {
.branch-office-weather-prevention__statistics {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-columns: repeat(2, 1fr);
gap: 6px;
margin-top: 5px;
}
.branch-office-weather-prevention__statistic {
padding: 8px 10px;
background-image: linear-gradient(to bottom,
rgba(0, 42, 85, 0.38),
rgba(1, 37, 74, 0.47),
@ -89,11 +89,18 @@
border-image: linear-gradient(to top,
rgba(8, 41, 87, 0.5),
rgba(64, 152, 255, 0.5)) 1;
display: flex;
align-items: center;
justify-content: space-between;
}
.branch-office-weather-prevention__row div {
padding: 5px;
.branch-office-weather-prevention__statistic-label {
color: #fff;
font-size: 12px;
text-align: center;
}
.branch-office-weather-prevention__statistic-value {
color: #00e7ff;
font-size: 18px;
font-weight: bold;
}

View File

@ -1,245 +0,0 @@
import { useMount } from "ahooks";
import * as echarts from "echarts";
import { useRef } from "react";
import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import "./index.less";
const records = [
{ name: "技术部1", unitCount: 95, personnelCount: 92 },
{ name: "技术部2", unitCount: 95, personnelCount: 92 },
{ name: "技术部3", unitCount: 95, personnelCount: 92 },
{ name: "技术部4", unitCount: 95, personnelCount: 92 },
{ name: "技术部5", unitCount: 95, personnelCount: 92 },
{ name: "技术部6", unitCount: 95, personnelCount: 92 },
{ name: "技术部7", unitCount: 95, personnelCount: 92 },
{ name: "技术部8", unitCount: 95, personnelCount: 92 },
{ name: "技术部9", unitCount: 95, personnelCount: 92 },
{ name: "技术部0", unitCount: 95, personnelCount: 92 },
];
/** 负责展示封闭区域人员状态图表,并管理图表实例生命周期。 */
function ClosedAreaPersonnelPanel() {
const chartInstance = useRef(null);
const chartRef = useRef(null);
const initEcharts = (mainRef, chartInstance, data) => {
chartInstance.current = echarts.init(mainRef.current);
const option = {
color: ["#F1C416", "#0AFCFF"],
tooltip: {
trigger: "axis",
axisPointer: {
type: "shadow",
label: {
backgroundColor: "#6a7985",
},
},
},
grid: {
left: "1%",
right: "4%",
bottom: "6%",
top: 30,
padding: "0 0 10 0",
containLabel: true,
},
legend: {
right: 10,
top: 0,
itemGap: 16,
itemWidth: 18,
itemHeight: 10,
textStyle: {
color: "#fff",
fontStyle: "normal",
fontFamily: "微软雅黑",
fontSize: 12,
},
},
dataZoom: [
{
type: "inside",
xAxisIndex: 0,
start: 0,
end: 50,
zoomOnMouseWheel: "shift",
moveOnMouseWheel: true,
moveOnMouseMove: true,
},
{
type: "slider",
height: 6,
bottom: 0,
show: true,
start: 0,
end: 50,
handleSize: 3,
handleStyle: {
color: "#DCE2E8",
},
xAxisIndex: [0],
filterMode: "filter",
showDetail: false,
},
],
xAxis: [
{
type: "category",
boundaryGap: true,
data: data.map(item => item.name),
axisLabel: {
interval: 0,
margin: 15,
textStyle: {
color: "#fff",
fontStyle: "normal",
fontFamily: "微软雅黑",
fontSize: 12,
},
},
axisTick: {
show: false,
},
axisLine: {
lineStyle: {
color: "#fff",
opacity: 0.2,
},
},
splitLine: {
show: false,
},
},
],
yAxis: [
{
type: "value",
splitNumber: 5,
axisLabel: {
textStyle: {
color: "#fff",
fontStyle: "normal",
fontFamily: "微软雅黑",
fontSize: 12,
},
},
axisLine: {
show: false,
},
axisTick: {
show: false,
},
splitLine: {
show: true,
lineStyle: {
color: ["#fff"],
opacity: 0.06,
},
},
},
],
series: [
{
name: "单位人员数",
type: "pictorialBar",
symbol: "roundRect",
symbolOffset: [-5, 0],
symbolMargin: "1",
barWidth: "10%",
barMaxWidth: "20%",
animationDelay: (dataIndex, params) => {
return params.index * 50;
},
itemStyle: {
normal: {
color: () => {
return new echarts.graphic.LinearGradient(0, 0, 1, 1, [
{
offset: 0,
color: "#F1C416",
},
{
offset: 1,
color: "#FF2F01",
},
]);
},
},
},
z: 1,
barGap: 0,
symbolRepeat: true,
symbolSize: [14, 5],
data: data.map(item => item.unitCount),
animationEasing: "elasticOut",
stack: "2",
},
{
name: "相关方人员数",
type: "pictorialBar",
symbol: "roundRect",
barWidth: "10%",
symbolOffset: [5, 0],
barMaxWidth: "20%",
symbolMargin: "1",
animationDelay: (dataIndex, params) => {
return params.index * 50;
},
itemStyle: {
normal: {
color: () => {
return new echarts.graphic.LinearGradient(0, 0, 1, 1, [
{
offset: 0,
color: "#0AFCFF",
},
{
offset: 1,
color: "#0CA1FE",
},
]);
},
},
},
z: 1,
barGap: 0,
symbolRepeat: true,
symbolSize: [14, 5],
data: data.map(item => item.personnelCount),
animationEasing: "elasticOut",
stack: "1",
},
],
};
chartInstance.current.setOption(option);
};
useMount(() => {
initEcharts(chartRef, chartInstance, records);
return () => {
if (chartInstance.current) {
chartInstance.current.dispose();
chartInstance.current = null;
}
};
});
return (
<Panel
title="封闭区域人员状态"
className="branch-office-index-right__personnel"
>
<div className="branch-office-closed-area-personnel__content">
<div
ref={chartRef}
className="branch-office-closed-area-personnel__chart"
/>
</div>
</Panel>
);
}
export default ClosedAreaPersonnelPanel;

View File

@ -1,12 +0,0 @@
.branch-office-index-right__personnel {
margin-top: 10px;
}
.branch-office-closed-area-personnel__content {
padding: 10px 15px;
}
.branch-office-closed-area-personnel__chart {
width: 100%;
height: 200px;
}

View File

@ -7,46 +7,18 @@ import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import { Context } from "~/pages/Container/Map/js/context";
import "./index.less";
/** 负责合并两类作业统计并展示部门维度数据。 */
/** 负责展示部门维度的重点作业统计。 */
function KeyWorkStatsPanel(props) {
const { portArea, currentBranchOffice } = useContext(Context);
const [data, setData] = useState([]);
useEffect(() => {
const loadData = async () => {
const [{ data: eightWorkData }, { data: keyProjectData }]
= await Promise.all([
props.getEightWorkInfoScreenDepartmentStatistics({
const { data } = await props.getKeyProjectLargeScreenDepartmentStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
props.getKeyProjectLargeScreenDepartmentStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
]);
const departmentMap = new Map(
(keyProjectData || []).map(item => [
item.departmentId,
{
departmentName: item.departmentName,
fourNewHomeworkCount: item.fourNewHomeworkCount,
eightWorkCount: 0,
morePeopleCount: item.morePeopleCount,
},
]),
);
(eightWorkData || []).forEach((item) => {
const department = departmentMap.get(item.departmentId) || {
departmentName: item.departmentName,
fourNewHomeworkCount: 0,
eightWorkCount: 0,
morePeopleCount: 0,
};
department.eightWorkCount = item.workCount || 0;
departmentMap.set(item.departmentId, department);
});
setData([...departmentMap.values()]);
setData(data || []);
};
loadData();
}, []);
@ -61,7 +33,8 @@ function KeyWorkStatsPanel(props) {
<div className="branch-office-key-work-stats__row">
<div>部门名称</div>
<div>三人以上作业数</div>
<div>危险作业数</div>
<div>夜间作业数</div>
<div>其他作业数</div>
<div>四新作业数</div>
</div>
<div className="branch-office-key-work-stats__body">
@ -69,8 +42,6 @@ function KeyWorkStatsPanel(props) {
spinning={
props.biStatistics
.getKeyProjectLargeScreenDepartmentStatisticsLoading
|| props.biStatistics
.getEightWorkInfoScreenDepartmentStatisticsLoading
}
>
<SeamlessScroll list={data} step={0.5}>
@ -81,7 +52,8 @@ function KeyWorkStatsPanel(props) {
>
<div>{item.departmentName}</div>
<div>{item.morePeopleCount}</div>
<div>{item.eightWorkCount}</div>
<div>{item.nightWorkCount}</div>
<div>{item.otherWorkCount}</div>
<div>{item.fourNewHomeworkCount}</div>
</div>
))}

View File

@ -17,7 +17,7 @@
.branch-office-key-work-stats__row {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: 1fr 1.5fr 1fr 1fr 1fr;
margin-top: 5px;
background-color: rgba(17, 51, 112, 0.8);
}

View File

@ -0,0 +1,86 @@
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { Spin } from "antd";
import { useContext, useEffect, useState } from "react";
import AliPlayer from "zy-react-library/components/Video/AliPlayer";
import videoBackground from "~/assets/images/public/bigScreen/bg14.png";
import { NS_BI_STATISTICS } from "~/enumerate/namespace";
import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import { Context } from "~/pages/Container/Map/js/context";
import "./index.less";
/** 将接口返回的企业分组或平铺摄像头数据统一为可播放的视频列表。 */
const formatVideoList = (data = []) => data.flatMap(item => (
Array.isArray(item.fixedCameraCOList) ? item.fixedCameraCOList : [item]
));
/** 负责加载分公司摄像头并支持手动切换播放画面。 */
function VideoPatrolPanel(props) {
const { portArea, currentBranchOffice } = useContext(Context);
const [videoList, setVideoList] = useState([]);
const [activeCameraNumber, setActiveCameraNumber] = useState("");
const [playUrl, setPlayUrl] = useState("");
const selectVideo = async (video) => {
setActiveCameraNumber(video.cameraNumber);
setPlayUrl("");
const { data, success } = await props.getFixedCameraPlayUrl({
indexCode: video.cameraNumber,
});
if (success)
setPlayUrl(data?.url || "");
};
useEffect(() => {
const loadVideoList = async () => {
const { data } = await props.getFixedCameraVideoList({
portArea,
corpinfoId: currentBranchOffice,
pageIndex: 1,
pageSize: 9999,
});
const videos = formatVideoList(data || []);
setVideoList(videos);
if (videos.length)
selectVideo(videos[0]);
};
loadVideoList();
}, []);
return (
<Panel title="视频巡屏" className="branch-office-index-right__video-patrol">
<div className="branch-office-video-patrol__content">
<Spin spinning={props.biStatistics.getFixedCameraVideoListLoading}>
<div className="branch-office-video-patrol__menu">
{videoList.map(video => (
<div
className={`branch-office-video-patrol__menu-item ${video.cameraNumber === activeCameraNumber ? "branch-office-video-patrol__menu-item--active" : ""}`}
key={video.cameraNumber}
onClick={() => selectVideo(video)}
>
{video.videoName}
</div>
))}
</div>
</Spin>
<div
className="branch-office-video-patrol__screen"
style={{ backgroundImage: `url(${videoBackground})` }}
>
<Spin
spinning={
props.biStatistics.getFixedCameraVideoListLoading
|| props.biStatistics.getFixedCameraPlayUrlLoading
}
>
{playUrl
? <AliPlayer source={playUrl} height="100%" isLive />
: <div className="branch-office-video-patrol__empty">暂无视频</div>}
</Spin>
</div>
</div>
</Panel>
);
}
export default Connect([NS_BI_STATISTICS], true)(VideoPatrolPanel);

View File

@ -0,0 +1,60 @@
.branch-office-index-right__video-patrol {
margin-top: 10px;
}
.branch-office-video-patrol__content {
display: flex;
gap: 10px;
padding: 10px 15px;
}
.branch-office-video-patrol__menu {
width: 120px;
height: 180px;
padding: 5px;
overflow-y: auto;
background: rgb(13, 56, 119);
border-radius: 5px;
}
.branch-office-video-patrol__menu-item {
display: block;
width: 100%;
padding: 0 8px;
margin-bottom: 5px;
overflow: hidden;
color: #fff;
font-size: 12px;
line-height: 30px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
background: rgba(18, 96, 181, 0.4);
border: 0;
border-radius: 5px;
}
.branch-office-video-patrol__menu-item--active,
.branch-office-video-patrol__menu-item:hover {
background: rgb(18, 96, 181);
}
.branch-office-video-patrol__screen {
flex: 1;
height: 180px;
padding: 10px;
background-size: 100% 100%;
}
.branch-office-video-patrol__screen .ant-spin-nested-loading,
.branch-office-video-patrol__screen .ant-spin-container {
height: 100%;
}
.branch-office-video-patrol__empty {
height: 100%;
color: #fff;
line-height: 160px;
text-align: center;
}

View File

@ -1,16 +1,16 @@
import AreaAlarmPanel from "./AreaAlarmPanel";
import ClosedAreaPersonnelPanel from "./ClosedAreaPersonnelPanel";
import GateAndClosedAreaPanel from "./GateAndClosedAreaPanel";
import KeyWorkStatsPanel from "./KeyWorkStatsPanel";
import VideoPatrolPanel from "./VideoPatrolPanel";
/** 分公司首页右侧区域仅负责按展示顺序组合业务区块。 */
function IndexRight() {
return (
<div className="branch-office-index-right">
<GateAndClosedAreaPanel />
<ClosedAreaPersonnelPanel />
<AreaAlarmPanel />
<KeyWorkStatsPanel />
<AreaAlarmPanel />
<VideoPatrolPanel />
</div>
);
}

View File

@ -68,7 +68,9 @@ function GateApplicationPanel(props) {
<div>结束时间</div>
</div>
<div className="branch-office-gate-application__body">
<Spin spinning={props.biStatistics.getPrimeportClosedAreaCarApplyScreenListLoading || props.biStatistics.getPrimeportClosedAreaPersonApplyScreenListLoading}>
<Spin
spinning={props.biStatistics.getPrimeportClosedAreaCarApplyScreenListLoading || props.biStatistics.getPrimeportClosedAreaPersonApplyScreenListLoading}
>
{isVisible && (
<SeamlessScroll list={data} step={0.5}>
{data.map((item, index) => (

View File

@ -25,11 +25,8 @@
&__content {
border: 1px solid;
border-top: none;
border-image: linear-gradient(
to bottom,
border-image: linear-gradient(to bottom,
rgba(58, 122, 149, 0),
rgba(58, 122, 149, 1)
)
1;
rgba(58, 122, 149, 1)) 1;
}
}

View File

@ -13,39 +13,7 @@ function DepartmentWorkPanel(props) {
const [data, setData] = useState([]);
useEffect(() => {
const loadData = async () => {
const [{ data: eightWorkData }, { data: keyProjectData }]
= await Promise.all([
props.getEightWorkInfoScreenDepartmentStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
props.getKeyProjectLargeScreenDepartmentStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
]);
const departmentMap = new Map(
(keyProjectData || []).map(item => [
item.departmentId,
{
departmentName: item.departmentName,
fourNewHomeworkCount: item.fourNewHomeworkCount,
eightWorkCount: 0,
morePeopleCount: item.morePeopleCount,
},
]),
);
(eightWorkData || []).forEach((item) => {
const department = departmentMap.get(item.departmentId) || {
departmentName: item.departmentName,
fourNewHomeworkCount: 0,
eightWorkCount: 0,
morePeopleCount: 0,
};
department.eightWorkCount = item.workCount || 0;
departmentMap.set(item.departmentId, department);
});
setData([...departmentMap.values()]);
};
loadData();
}, []);
@ -58,18 +26,12 @@ function DepartmentWorkPanel(props) {
<div className="branch-office-department-work__table">
<div className="branch-office-department-work__row">
<div>部门名称</div>
<div>四新作业</div>
<div>危险作业</div>
<div>三人以上作业数</div>
<div>作业类型</div>
<div>作业状态</div>
</div>
<div className="branch-office-department-work__body">
<Spin
spinning={
props.biStatistics
.getKeyProjectLargeScreenDepartmentStatisticsLoading
|| props.biStatistics
.getEightWorkInfoScreenDepartmentStatisticsLoading
}
spinning={false}
>
<SeamlessScroll list={data} step={0.5}>
{data.map((item, index) => (
@ -77,7 +39,6 @@ function DepartmentWorkPanel(props) {
<div>{item.departmentName}</div>
<div>{item.fourNewHomeworkCount}</div>
<div>{item.eightWorkCount}</div>
<div>{item.morePeopleCount}</div>
</div>
))}
</SeamlessScroll>

View File

@ -17,7 +17,7 @@
.branch-office-department-work__row {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-columns: repeat(3, 1fr);
margin-top: 5px;
color: #fff;
font-size: 12px;

View File

@ -1,133 +1,97 @@
import { Connect } from "@cqsjjb/jjb-dva-runtime";
import { Spin } from "antd";
import { useContext, useEffect, useState } from "react";
import CountUp from "react-countup";
import firstBackground from "~/assets/images/map_bi/content/bg9.png";
import secondBackground from "~/assets/images/map_bi/content/bg10.png";
import * as echarts from "echarts";
import { useEffect, useRef } from "react";
import { NS_BI_STATISTICS } from "~/enumerate/namespace";
import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import { Context } from "~/pages/Container/Map/js/context";
import "./index.less";
const defaultStatistics = [
{
title: (
<>
四新
<br />
作业
</>
),
currentCount: 0,
doingCount: 0,
archivedCount: 0,
},
{
title: (
<>
危险
<br />
作业
</>
),
currentCount: 0,
doingCount: 0,
archivedCount: 0,
},
{
title: (
<>
三人及
<br />
以上作业
</>
),
currentCount: 0,
doingCount: 0,
archivedCount: 0,
},
const records = [
{ name: "动火作业", archivedCount: 24, workingCount: 6, approvalCount: 3 },
{ name: "受限空间", archivedCount: 18, workingCount: 4, approvalCount: 2 },
{ name: "高处作业", archivedCount: 32, workingCount: 8, approvalCount: 5 },
{ name: "吊装作业", archivedCount: 16, workingCount: 3, approvalCount: 1 },
{ name: "临时用电", archivedCount: 27, workingCount: 7, approvalCount: 4 },
{ name: "动土作业", archivedCount: 12, workingCount: 2, approvalCount: 2 },
{ name: "断路作业", archivedCount: 15, workingCount: 5, approvalCount: 3 },
{ name: "盲板抽堵", archivedCount: 9, workingCount: 1, approvalCount: 1 },
];
/** 负责查询并展示各重点作业的执行状态。 */
function KeyWorkPanel(props) {
const { portArea, currentBranchOffice } = useContext(Context);
const [data, setData] = useState(defaultStatistics);
/** 展示八类危险作业在已归档、作业中和审批中三个状态下的数量。 */
function KeyWorkPanel() {
const chartRef = useRef(null);
const chartInstance = useRef(null);
useEffect(() => {
const loadData = async () => {
const [{ data: eightWorkData }, { data: keyProjectData }]
= await Promise.all([
props.getEightWorkInfoDangerWorkStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
props.getKeyProjectLargeScreenStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
]);
setData([
{
...defaultStatistics[0],
currentCount: keyProjectData?.fourNewHomeworkStartCount,
doingCount: keyProjectData?.fourNewHomeworkDoingCount,
archivedCount: keyProjectData?.fourNewHomeworkArchiveCount,
chartInstance.current = echarts.init(chartRef.current);
chartInstance.current.setOption({
color: ["#74CB3F", "#00AEFF", "#FFA800"],
tooltip: {
trigger: "axis",
axisPointer: { type: "shadow" },
},
{
...defaultStatistics[1],
currentCount: eightWorkData?.doingCount,
doingCount: eightWorkData?.workingCount,
archivedCount: eightWorkData?.archivedCount,
legend: {
top: 0,
right: 0,
data: ["已归档", "作业中", "审批中"],
itemWidth: 12,
itemHeight: 10,
textStyle: {
color: "#fff",
fontSize: 12,
},
{
...defaultStatistics[2],
currentCount: keyProjectData?.morePeopleStartCount,
doingCount: keyProjectData?.morePeopleDoingCount,
archivedCount: keyProjectData?.morePeopleArchiveCount,
},
]);
grid: {
top: 35,
right: 10,
bottom: 10,
left: 10,
containLabel: true,
},
xAxis: {
type: "category",
data: records.map(item => item.name),
axisTick: { show: false },
axisLine: {
lineStyle: { color: "rgba(255, 255, 255, 0.25)" },
},
axisLabel: {
color: "#fff",
fontSize: 10,
},
},
yAxis: {
type: "value",
axisLabel: {
color: "#fff",
fontSize: 10,
},
axisLine: { show: false },
axisTick: { show: false },
splitLine: {
lineStyle: {
color: "rgba(255, 255, 255, 0.12)",
type: "dashed",
},
},
},
series: [
{ name: "已归档", type: "bar", barMaxWidth: 14, data: records.map(item => item.archivedCount) },
{ name: "作业中", type: "bar", barMaxWidth: 14, data: records.map(item => item.workingCount) },
{ name: "审批中", type: "bar", barMaxWidth: 14, data: records.map(item => item.approvalCount) },
],
});
return () => {
chartInstance.current?.dispose();
chartInstance.current = null;
};
loadData();
}, []);
return (
<Panel title="重点作业" className="branch-office-danger-work__key-work">
<Spin
spinning={
props.biStatistics.getEightWorkInfoDangerWorkStatisticsLoading
|| props.biStatistics.getKeyProjectLargeScreenStatisticsLoading
}
>
<div className="branch-office-key-work__list">
{data.map((item, index) => (
<div
key={index}
className="branch-office-key-work__item"
style={{
backgroundImage: `url(${index % 2 === 0 ? firstBackground : secondBackground})`,
}}
>
<div className="branch-office-key-work__title">{item.title}</div>
<div className="branch-office-key-work__statistics">
<Statistic label="当前作业数" value={item.currentCount} />
<Statistic label="作业中" value={item.doingCount} />
<Statistic label="已归档" value={item.archivedCount} />
</div>
</div>
))}
</div>
</Spin>
<Panel title="危险作业汇总" className="branch-office-danger-work__key-work">
<div ref={chartRef} className="branch-office-key-work__chart" />
</Panel>
);
}
function Statistic({ label, value }) {
return (
<div>
<div className="branch-office-key-work__label">{label}</div>
<div className="branch-office-key-work__value">
<CountUp end={+value} />
</div>
</div>
);
}
export default Connect([NS_BI_STATISTICS], true)(KeyWorkPanel);

View File

@ -2,69 +2,8 @@
margin-top: 10px;
}
.branch-office-key-work__list {
.branch-office-key-work__chart {
width: 100%;
height: 240px;
padding: 10px 15px;
}
.branch-office-key-work__item {
display: flex;
align-items: center;
padding: 12px 0;
margin-top: 5px;
color: #fff;
background-repeat: no-repeat;
background-size: 100% 100%;
}
.branch-office-key-work__item:first-child {
margin-top: 0;
}
.branch-office-key-work__title {
display: flex;
align-items: center;
justify-content: center;
width: 65px;
height: 50px;
margin-left: 15px;
font-size: 14px;
font-weight: bold;
text-align: center;
border: 1px solid #167ce4;
border-radius: 4px;
}
.branch-office-key-work__statistics {
display: flex;
flex: 1;
align-items: center;
justify-content: space-between;
margin: 0 30px;
text-align: center;
}
.branch-office-key-work__label {
font-weight: bold;
}
.branch-office-key-work__value {
font-size: 16px;
}
.branch-office-key-work__statistics
> div:nth-child(1)
.branch-office-key-work__value {
color: #00aeff;
}
.branch-office-key-work__statistics
> div:nth-child(2)
.branch-office-key-work__value {
color: #ffa800;
}
.branch-office-key-work__statistics
> div:nth-child(3)
.branch-office-key-work__value {
color: #74cb3f;
}

View File

@ -11,14 +11,9 @@ import { Context } from "~/pages/Container/Map/js/context";
import "./index.less";
const defaultStatistics = [
{ title: "四新作业", icon: fourNewIcon, currentCount: 0, applyCount: 0 },
{ title: "危险作业", icon: dangerIcon, currentCount: 0, applyCount: 0 },
{
title: "三人及以上作业",
icon: multiPersonIcon,
currentCount: 0,
applyCount: 0,
},
{ title: "审批中", icon: fourNewIcon, count: 0 },
{ title: "作业中", icon: dangerIcon, count: 0 },
{ title: "已归档", icon: multiPersonIcon, count: 0 },
];
/** 负责查询并展示重点作业当前数量与申请数量。 */
@ -28,46 +23,14 @@ function KeyWorkStatsPanel(props) {
useEffect(() => {
const loadData = async () => {
const [{ data: eightWorkData }, { data: keyProjectData }]
= await Promise.all([
props.getEightWorkInfoDangerWorkStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
props.getKeyProjectLargeScreenStatistics({
portArea,
corpinfoId: currentBranchOffice,
}),
]);
setData([
{
...defaultStatistics[0],
currentCount: keyProjectData?.fourNewHomeworkStartCount,
applyCount: keyProjectData?.fourNewHomeworkApplyCount,
},
{
...defaultStatistics[1],
currentCount: eightWorkData?.workingCount,
applyCount: eightWorkData?.appliedCount,
},
{
...defaultStatistics[2],
currentCount: keyProjectData?.morePeopleStartCount,
applyCount: keyProjectData?.morePeopleApplyCount,
},
]);
};
loadData();
}, []);
return (
<Panel title="重点作业统计">
<Spin
spinning={
props.biStatistics.getEightWorkInfoDangerWorkStatisticsLoading
|| props.biStatistics.getKeyProjectLargeScreenStatisticsLoading
}
>
<Panel title="危险作业统计">
<Spin spinning={false}>
<div className="branch-office-key-work-stats__list">
{data.map(item => (
<div
@ -81,12 +44,7 @@ function KeyWorkStatsPanel(props) {
<img src={item.icon} alt="" />
</div>
<div className="branch-office-key-work-stats__info">
当前作业数
<CountUp end={+item.currentCount} />
</div>
<div className="branch-office-key-work-stats__info">
申请数
<CountUp end={+item.applyCount} />
<CountUp end={+item.count} />
</div>
</div>
))}

View File

@ -25,4 +25,5 @@
.branch-office-key-work-stats__info {
margin-top: 5px;
font-size: 12px;
text-align: center;
}

View File

@ -0,0 +1,45 @@
import SeamlessScroll from "zy-react-library/components/SeamlessScroll";
import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import "./index.less";
const records = [
{ inspectionForm: "码头消防点位检查表", principal: "张建国", pointCount: 28, status: "已完成" },
{ inspectionForm: "堆场消防点位检查表", principal: "李海峰", pointCount: 36, status: "已完成" },
{ inspectionForm: "仓储区消防点位检查表", principal: "王立新", pointCount: 22, status: "点检中" },
{ inspectionForm: "办公区消防点位检查表", principal: "赵明远", pointCount: 18, status: "待点检" },
{ inspectionForm: "散货区消防点位检查表", principal: "陈志强", pointCount: 31, status: "已完成" },
{ inspectionForm: "危化品区消防点位检查表", principal: "刘海涛", pointCount: 16, status: "异常" },
{ inspectionForm: "维修区消防点位检查表", principal: "孙志伟", pointCount: 24, status: "点检中" },
];
/** 展示消防点位检查表的负责人、点位数量和当前点检状态。 */
function FireInspectionRecordPanel() {
return (
<Panel title="消防点检记录" className="branch-office-fire__inspection-record">
<div className="branch-office-fire-inspection-record__content">
<div className="branch-office-fire-inspection-record__table">
<div className="branch-office-fire-inspection-record__row">
<div>消防点位检查表</div>
<div>负责人</div>
<div>点位数</div>
<div>状态</div>
</div>
<div className="branch-office-fire-inspection-record__body">
<SeamlessScroll list={records} step={0.5}>
{records.map(item => (
<div className="branch-office-fire-inspection-record__row" key={item.inspectionForm}>
<div>{item.inspectionForm}</div>
<div>{item.principal}</div>
<div>{item.pointCount}</div>
<div>{item.status}</div>
</div>
))}
</SeamlessScroll>
</div>
</div>
</div>
</Panel>
);
}
export default FireInspectionRecordPanel;

View File

@ -0,0 +1,33 @@
.branch-office-fire__inspection-record {
margin-top: 10px;
}
.branch-office-fire-inspection-record__content {
padding: 10px 15px;
}
.branch-office-fire-inspection-record__table {
margin-top: 5px;
}
.branch-office-fire-inspection-record__body {
height: 155px;
overflow-y: hidden;
}
.branch-office-fire-inspection-record__row {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1fr;
margin-top: 5px;
background-color: rgba(17, 51, 112, 0.8);
}
.branch-office-fire-inspection-record__row div {
padding: 5px;
overflow: hidden;
color: #fff;
font-size: 12px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@ -1,126 +0,0 @@
import { useState } from "react";
import SeamlessScroll from "zy-react-library/components/SeamlessScroll";
import Panel from "~/pages/Container/Map/components/Content/branchOffice/Panel";
import "./index.less";
const tabs = ["消防水罐", "消防泵", "消防管线"];
const records = [
{
pumpRoomName: "一号消防泵房",
liquidLevel: 2.5,
waterPressure: 0.45,
status: 1,
},
{
pumpRoomName: "二号消防泵房",
liquidLevel: 1.8,
waterPressure: 0.38,
status: 1,
},
{
pumpRoomName: "三号消防泵房",
liquidLevel: 3.2,
waterPressure: 0.52,
status: 1,
},
{
pumpRoomName: "四号消防泵房",
liquidLevel: 0.5,
waterPressure: 0.25,
status: 2,
},
{
pumpRoomName: "五号消防泵房",
liquidLevel: 2.8,
waterPressure: 0.48,
status: 1,
},
{
pumpRoomName: "六号消防泵房",
liquidLevel: 1.2,
waterPressure: 0.32,
status: 3,
},
{
pumpRoomName: "七号消防泵房",
liquidLevel: 3.5,
waterPressure: 0.55,
status: 1,
},
{
pumpRoomName: "八号消防泵房",
liquidLevel: 2.1,
waterPressure: 0.42,
status: 1,
},
{
pumpRoomName: "九号消防泵房",
liquidLevel: 0.8,
waterPressure: 0.28,
status: 2,
},
{
pumpRoomName: "十号消防泵房",
liquidLevel: 2.9,
waterPressure: 0.5,
status: 1,
},
];
/** 负责展示消防泵房本地设备数据及分类标签状态。 */
function FirePumpRoomPanel() {
const [activeIndex, setActiveIndex] = useState(0);
return (
<Panel
title="消防泵房状态"
className="branch-office-fire__pump-room"
extra={(
<div className="branch-office-fire-pump-room__tabs">
{tabs.map((item, index) => (
<div
key={item}
className={`branch-office-fire-pump-room__tab ${index === activeIndex ? "branch-office-fire-pump-room__tab--active" : ""}`}
onClick={() => setActiveIndex(index)}
>
{item}
</div>
))}
</div>
)}
>
<div className="branch-office-fire-pump-room__content">
<div className="branch-office-fire-pump-room__table">
<div className="branch-office-fire-pump-room__row">
<div>泵房名称</div>
<div>液位()</div>
<div>水压(mpa)</div>
<div>状态</div>
</div>
<div className="branch-office-fire-pump-room__body">
<SeamlessScroll list={records} step={0.5}>
{records.map((item, index) => (
<div className="branch-office-fire-pump-room__row" key={index}>
<div>{item.pumpRoomName}</div>
<div>{item.liquidLevel}</div>
<div>{`${item.waterPressure}MPa`}</div>
<div
className={`branch-office-fire-pump-room__status branch-office-fire-pump-room__status--${item.status}`}
>
{item.status === 1
? "正常"
: item.status === 2
? "异常"
: "维护中"}
</div>
</div>
))}
</SeamlessScroll>
</div>
</div>
</div>
</Panel>
);
}
export default FirePumpRoomPanel;

View File

@ -1,57 +0,0 @@
.branch-office-fire__pump-room {
margin-top: 10px;
}
.branch-office-fire-pump-room__tabs {
display: flex;
}
.branch-office-fire-pump-room__tab {
padding: 2px 6px;
color: #fff;
font-size: 12px;
cursor: pointer;
background-color: rgba(36, 115, 239, 0.27);
border: 1px solid #5d718c;
border-radius: 2px;
}
.branch-office-fire-pump-room__tab--active {
background-color: #2473ef;
border-color: #2473ef;
}
.branch-office-fire-pump-room__content {
padding: 10px 15px;
}
.branch-office-fire-pump-room__table {
margin-top: 5px;
}
.branch-office-fire-pump-room__body {
height: 155px;
overflow-y: hidden;
}
.branch-office-fire-pump-room__row {
display: grid;
grid-template-columns: repeat(4, 1fr);
margin-top: 5px;
background-color: rgba(17, 51, 112, 0.8);
}
.branch-office-fire-pump-room__row div {
padding: 5px;
color: #fff;
font-size: 12px;
text-align: center;
}
.branch-office-fire-pump-room__row .branch-office-fire-pump-room__status--1 {
color: #60b321;
}
.branch-office-fire-pump-room__row .branch-office-fire-pump-room__status--2 {
color: #f18308;
}

View File

@ -1,6 +1,6 @@
import FireAlarmRecordPanel from "./FireAlarmRecordPanel";
import FireDeviceStatusPanel from "./FireDeviceStatusPanel";
import FirePumpRoomPanel from "./FirePumpRoomPanel";
import FireInspectionRecordPanel from "./FireInspectionRecordPanel";
import VolunteerFireTeamPanel from "./VolunteerFireTeamPanel";
/** 分公司消防模块仅负责按展示顺序组合业务区块。 */
@ -8,9 +8,9 @@ function XiaoFang() {
return (
<div className="branch-office-fire">
<FireDeviceStatusPanel />
<FirePumpRoomPanel />
<FireAlarmRecordPanel />
<VolunteerFireTeamPanel />
<FireAlarmRecordPanel />
<FireInspectionRecordPanel />
</div>
);
}

View File

@ -129,7 +129,11 @@ function ElectricityWork(props) {
</tr>
</Fragment>
))
: <tr><td colSpan={4} className="center">暂无数据</td></tr>
: (
<tr>
<td colSpan={4} className="center">暂无数据</td>
</tr>
)
}
<SafetyMeasures workId={props.workId} colSpan={4} />
<DisclaimerSign

View File

@ -98,7 +98,11 @@ function HotWork(props) {
</tr>
</Fragment>
))
: <tr><td colSpan={4} className="center">暂无数据</td></tr>
: (
<tr>
<td colSpan={4} className="center">暂无数据</td>
</tr>
)
}
<tr>
<td className="title center" colSpan={4}>动火要求安全措施安全提示</td>
@ -188,7 +192,11 @@ function HotWork(props) {
</td>
</tr>
))
: <tr><td colSpan={3} className="center">暂无数据</td></tr>
: (
<tr>
<td colSpan={3} className="center">暂无数据</td>
</tr>
)
}
</tbody>
</table>

View File

@ -123,7 +123,11 @@ const KeyProject = (props) => {
dataSource={info.keyProjectCameraList || []}
columns={[
{ title: "视频名称", dataIndex: "cameraName" },
{ title: "视频类型", dataIndex: "cameraType", render: (_, record) => getLabelName({ status: record.cameraType, list: VIDEO_TYPE }) },
{
title: "视频类型",
dataIndex: "cameraType",
render: (_, record) => getLabelName({ status: record.cameraType, list: VIDEO_TYPE }),
},
]}
disabledResizer
options={false}

View File

@ -1,9 +1,7 @@
.port-panel {
background-image: linear-gradient(
to bottom,
background-image: linear-gradient(to bottom,
rgba(0, 0, 0, 0),
rgba(0, 0, 0, 0.8)
);
rgba(0, 0, 0, 0.8));
&__title {
display: flex;
@ -44,12 +42,9 @@
&__content {
border: 1px solid;
border-top: none;
border-image: linear-gradient(
to bottom,
border-image: linear-gradient(to bottom,
rgba(58, 122, 149, 0),
rgba(58, 122, 149, 1)
)
1;
rgba(58, 122, 149, 1)) 1;
}
}

View File

@ -0,0 +1,43 @@
import SeamlessScroll from "zy-react-library/components/SeamlessScroll";
import Panel from "~/pages/Container/Map/components/Content/port/Panel";
import "./index.less";
const records = [
{ corpName: "港区建设有限公司", onlinePersonnelCount: 126, onlineVehicleCount: 18 },
{ corpName: "临港工程有限公司", onlinePersonnelCount: 98, onlineVehicleCount: 12 },
{ corpName: "海港设备安装有限公司", onlinePersonnelCount: 75, onlineVehicleCount: 9 },
{ corpName: "港航建设集团", onlinePersonnelCount: 142, onlineVehicleCount: 21 },
{ corpName: "东港物流有限公司", onlinePersonnelCount: 86, onlineVehicleCount: 16 },
{ corpName: "港区能源有限公司", onlinePersonnelCount: 63, onlineVehicleCount: 7 },
{ corpName: "海运工程有限公司", onlinePersonnelCount: 109, onlineVehicleCount: 14 },
];
/** 展示各公司当前在线定位的人员和车辆数量。 */
function OnlineLocationInfoPanel() {
return (
<Panel title="在线定位信息" className="port-personnel__online-location-info">
<div className="port-online-location-info__content">
<div className="port-online-location-info__table">
<div className="port-online-location-info__row">
<div className="port-online-location-info__cell">公司名称</div>
<div className="port-online-location-info__cell">在线定位人员数</div>
<div className="port-online-location-info__cell">在线定位车辆数</div>
</div>
<div className="port-online-location-info__body">
<SeamlessScroll list={records} step={0.5}>
{records.map(item => (
<div className="port-online-location-info__row" key={item.corpName}>
<div className="port-online-location-info__cell">{item.corpName}</div>
<div className="port-online-location-info__cell">{item.onlinePersonnelCount}</div>
<div className="port-online-location-info__cell">{item.onlineVehicleCount}</div>
</div>
))}
</SeamlessScroll>
</div>
</div>
</div>
</Panel>
);
}
export default OnlineLocationInfoPanel;

View File

@ -0,0 +1,33 @@
.port-personnel__online-location-info {
margin-top: 10px;
}
.port-online-location-info__content {
padding: 10px;
}
.port-online-location-info__table {
margin-top: 5px;
}
.port-online-location-info__body {
height: 155px;
overflow-y: hidden;
}
.port-online-location-info__row {
display: grid;
grid-template-columns: 1.5fr 1fr 1fr;
margin-top: 5px;
background: rgba(42, 86, 158, 0.53);
}
.port-online-location-info__cell {
padding: 5px;
overflow: hidden;
color: #fff;
font-size: 12px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@ -1,11 +1,13 @@
import AlarmListPanel from "./AlarmListPanel";
import LocationInfoPanel from "./LocationInfoPanel";
import OnlineLocationInfoPanel from "./OnlineLocationInfoPanel";
/** 人员定位模块仅负责按展示顺序组合业务区块。 */
function RenYuan() {
return (
<div className="port-personnel">
<LocationInfoPanel />
<OnlineLocationInfoPanel />
<AlarmListPanel />
</div>
);

View File

@ -1,22 +1,28 @@
.port-danger-work__record {
margin-top: 10px;
}
.port-danger-work-record__content {
padding: 10px;
}
.port-danger-work-record__table {
margin-top: 5px;
}
.port-danger-work-record__table-body {
height: 400px;
overflow-y: hidden;
}
.port-danger-work-record__row {
display: flex;
}
.port-danger-work-record__row:nth-child(odd) {
background-color: rgba(42, 86, 158, 0.53);
}
.port-danger-work-record__cell {
flex: 1;
padding: 5px;
@ -24,14 +30,17 @@
font-size: 12px;
text-align: center;
}
.port-danger-work-record__cell:first-child {
flex: none;
flex-basis: 50px;
text-align: left;
}
.port-danger-work-record__cell:nth-child(2) {
flex-basis: 20%;
}
.port-danger-work-record__rank {
display: flex;
align-items: center;
@ -44,15 +53,19 @@
line-height: 1;
border-radius: 2px;
}
.port-danger-work-record__rank--first {
background: linear-gradient(135deg, #ff6d73, #f23f47);
}
.port-danger-work-record__rank--second {
background: linear-gradient(135deg, #ffb856, #ff871f);
}
.port-danger-work-record__rank--third {
background: linear-gradient(135deg, #ffe477, #f6be1b);
}
.port-danger-work-record__rank--default {
background: linear-gradient(135deg, #5a8fdc, #3367b4);
}

View File

@ -3,11 +3,13 @@
justify-content: space-between;
padding: 13px 15px;
}
.port-danger-work-status__option {
display: flex;
flex-direction: column;
align-items: center;
}
.port-danger-work-status__icon {
width: 70px;
height: 70px;
@ -16,11 +18,13 @@
background-repeat: no-repeat;
background-size: 100% 100%;
}
.port-danger-work-status__icon img {
width: 25px;
height: 26px;
animation: portDangerWorkStatusSlideY 2s infinite;
}
.port-danger-work-status__label {
display: flex;
justify-content: center;
@ -34,6 +38,7 @@
background-repeat: no-repeat;
background-size: 100% 100%;
}
@keyframes portDangerWorkStatusSlideY {
0% {
transform: translateY(0);

View File

@ -1,9 +1,11 @@
.port-danger-work__trend {
margin-top: 10px;
}
.port-danger-work-trend__content {
padding: 10px 15px;
}
.port-danger-work-trend__chart {
width: 100%;
height: 240px;

View File

@ -1,6 +1,7 @@
.port-key-supervision__project {
margin-top: 10px;
}
.port-key-project__options {
position: relative;
display: flex;
@ -10,12 +11,14 @@
height: 150px;
padding: 10px 15px;
}
.port-key-project__option {
display: flex;
align-items: center;
justify-content: space-around;
width: 50%;
}
.port-key-project__icon {
width: 70px;
height: 70px;
@ -25,15 +28,18 @@
background-repeat: no-repeat;
background-size: 100% 100%;
}
.port-key-project__icon img {
width: 25px;
height: 26px;
animation: portKeyProjectSlideY 2s infinite;
}
.port-key-project__info {
flex: 1;
text-align: center;
}
.port-key-project__label {
width: 120px;
height: 24px;
@ -45,10 +51,10 @@
background-repeat: no-repeat;
background-size: 100% 100%;
}
.port-key-project__count {
margin-top: 13px;
font-family:
"PingFang SC", "Helvetica Neue", "Hiragino Sans GB", "Segoe UI",
font-family: "PingFang SC", "Helvetica Neue", "Hiragino Sans GB", "Segoe UI",
"Microsoft YaHei", "微软雅黑", sans-serif;
font-weight: bold;
background: linear-gradient(to top, #48bbf0, #fff);
@ -56,9 +62,11 @@
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.port-key-project__count span {
font-size: 24px;
}
@keyframes portKeyProjectSlideY {
0% {
transform: translateY(0);

View File

@ -0,0 +1,54 @@
import SeamlessScroll from "zy-react-library/components/SeamlessScroll";
import Panel from "~/pages/Container/Map/components/Content/port/Panel";
import "./index.less";
const records = [
{ corpName: "港区建设有限公司", projectName: "码头泊位改造工程", projectStatus: "进行中" },
{ corpName: "临港工程有限公司", projectName: "堆场智能化升级工程", projectStatus: "未开工" },
{ corpName: "海港设备安装有限公司", projectName: "装卸设备检修工程", projectStatus: "完工申请中" },
{ corpName: "港航建设集团", projectName: "航道疏浚维护工程", projectStatus: "已结束" },
{ corpName: "东港物流有限公司", projectName: "散货泊位扩建工程", projectStatus: "进行中" },
{ corpName: "港区能源有限公司", projectName: "岸电设施建设工程", projectStatus: "开工申请中" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
{ corpName: "海运工程有限公司", projectName: "仓储区消防改造工程", projectStatus: "未开工" },
];
/** 展示重点作业的所属公司、工程名称和当前工程状态。 */
function KeyWorkInfoPanel() {
return (
<Panel title="重点作业信息" className="port-key-supervision__work-info">
<div className="port-key-work-info__content">
<div className="port-key-work-info__table">
<div className="port-key-work-info__row">
<div className="port-key-work-info__cell">所属公司</div>
<div className="port-key-work-info__cell">工程名称</div>
<div className="port-key-work-info__cell">工程状态</div>
</div>
<div className="port-key-work-info__body">
<SeamlessScroll list={records} step={0.5}>
{records.map((item, index) => (
<div className="port-key-work-info__row" key={index}>
<div className="port-key-work-info__cell">{item.corpName}</div>
<div className="port-key-work-info__cell">{item.projectName}</div>
<div className="port-key-work-info__cell">{item.projectStatus}</div>
</div>
))}
</SeamlessScroll>
</div>
</div>
</div>
</Panel>
);
}
export default KeyWorkInfoPanel;

View File

@ -0,0 +1,33 @@
.port-key-supervision__work-info {
margin-top: 10px;
}
.port-key-work-info__content {
padding: 10px 15px;
}
.port-key-work-info__table {
margin-top: 5px;
}
.port-key-work-info__body {
height: 350px;
overflow-y: hidden;
}
.port-key-work-info__row {
display: grid;
grid-template-columns: 1fr 1.5fr 1fr;
margin-top: 5px;
background-color: rgba(17, 51, 112, 0.8);
}
.port-key-work-info__cell {
padding: 5px;
overflow: hidden;
color: #fff;
font-size: 12px;
text-align: center;
text-overflow: ellipsis;
white-space: nowrap;
}

View File

@ -2,17 +2,20 @@
display: flex;
justify-content: space-between;
}
.port-video-location__option {
display: flex;
flex-direction: row;
align-items: center;
}
.port-video-location__image {
width: 225px;
height: 160px;
background-repeat: no-repeat;
background-size: 100% 100%;
}
.port-video-location__statistic {
display: flex;
flex: 1;
@ -20,9 +23,11 @@
font-size: 14px;
line-height: 3;
}
.port-video-location__statistic > div:first-child {
margin-right: 5px;
}
.port-video-location__statistic span {
font-size: 14px;
}

View File

@ -1,4 +1,5 @@
import KeyProjectPanel from "./KeyProjectPanel";
import KeyWorkInfoPanel from "./KeyWorkInfoPanel";
import VideoLocationPanel from "./VideoLocationPanel";
/** 重点监管模块仅负责按展示顺序组合业务区块。 */
@ -7,6 +8,7 @@ function ZhongDian() {
<div className="port-key-supervision">
<VideoLocationPanel />
<KeyProjectPanel />
<KeyWorkInfoPanel />
</div>
);
}

View File

@ -6,6 +6,7 @@ import guangImg from "~/assets/images/map_bi/guang.png";
import topImg1 from "~/assets/images/map_bi/top1.png";
import topImg2 from "~/assets/images/map_bi/top2.png";
import { Context } from "~/pages/Container/Map/js/context";
import { closeWindow } from "~/utils/weather";
import "./index.less";
// 标题切换时先让旧标题离开,再让新标题进入,上下滑动和淡入淡出效果。
@ -16,19 +17,18 @@ const headerAnimation = {
};
function Header(props) {
const { currentPort, currentBranchOffice, mapMethods, portArea, headerTitle, actions, closePopup } = useContext(Context);
const {
currentPort,
currentBranchOffice,
mapMethods,
portArea,
headerTitle,
actions,
closePopup,
} = useContext(Context);
const isPortTitle = headerTitle === "秦港股份安全监管平台";
const closeWindow = () => {
window.close();
setTimeout(() => {
if (!window.closed && !window.opener) {
window.location.href = "https://gbs-gateway.qhdsafety.com/";
}
}, 500);
};
const onBack = () => {
closePopup();
sessionStorage.removeItem("mapCurrentBranchOfficeId");

View File

@ -6,6 +6,7 @@ import tooltipImg2 from "~/assets/images/map_bi/right_utils/branch_office/bg11.p
import buttonBg from "~/assets/images/map_bi/right_utils/branch_office/button.png";
import tooltipImg1 from "~/assets/images/map_bi/right_utils/port/tooltip.png";
import { Context } from "~/pages/Container/Map/js/context";
import { closeWindow } from "~/utils/weather";
import { utilsList } from "./utilsList";
import "./index.less";
@ -83,12 +84,7 @@ function RightUtils(props) {
switch (type) {
case "back":
window.close();
setTimeout(() => {
if (!window.closed && !window.opener) {
window.location.href = "https://gbs-gateway.qhdsafety.com/";
}
}, 500);
closeWindow();
break;
case "full":
props.toggleFullscreen();

View File

@ -50,3 +50,12 @@ export const getWeatherIcon = (weatherName) => {
export const getAlertColor = (level) => {
return { 蓝色预警: "#1E90FF", 黄色预警: "#FFA500", 橙色预警: "#FF4500", 红色预警: "#FF0000" }[level] || "#fff";
};
export const closeWindow = () => {
window.close();
setTimeout(() => {
if (!window.closed && !window.opener) {
window.location.href = "https://gbs-gateway.qhdsafety.com/";
}
}, 500);
};