From 33484c91566f6a881af8c3dfc0a1d619947ff265 Mon Sep 17 00:00:00 2001 From: qzc Date: Tue, 24 Sep 2024 16:59:13 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E5=B7=A1=E6=9F=A5?= =?UTF-8?q?=E5=B7=A1=E6=A3=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Home/MapCtrl/Pops/DaiChuLi.js | 49 +++++ src/views/Home/MapCtrl/Pops/XunJian.js | 78 +++++++ src/views/Home/MapCtrl/Pops/index.js | 13 +- src/views/Home/homePanelsLayoutPage/index.js | 2 + .../Home/homePanelsLayoutPage/index.less | 48 +++++ .../item_xunchaxunjian.js | 198 ++++++++++++++++++ 6 files changed, 385 insertions(+), 3 deletions(-) create mode 100644 src/views/Home/MapCtrl/Pops/DaiChuLi.js create mode 100644 src/views/Home/MapCtrl/Pops/XunJian.js create mode 100644 src/views/Home/homePanelsLayoutPage/item_xunchaxunjian.js diff --git a/src/views/Home/MapCtrl/Pops/DaiChuLi.js b/src/views/Home/MapCtrl/Pops/DaiChuLi.js new file mode 100644 index 000000000..64fbeabc7 --- /dev/null +++ b/src/views/Home/MapCtrl/Pops/DaiChuLi.js @@ -0,0 +1,49 @@ +import React, { useEffect, useState } from 'react'; +import { Descriptions, Modal } from 'antd'; +import {CloseOutlined} from '@ant-design/icons'; +import { httpget2 } from '../../../../utils/request'; +import apiurl from '../../../../service/apiurl'; +import moment from "moment" + +function Wxq({ id, data, dispatch }) { + console.log(data); + const width = 400; + const [detail, setDetail] = useState({}) + const [visible,setVisible] = useState(false) + const closePop = () => { + dispatch.runtime.closeFeaturePop(id); + }; + const getDetailData = async(id) => { + try { + const res = await httpget2(`${apiurl.home.wxqdetail}/${id}`); + setDetail(res.data) + } catch (error) { + + } + } + useEffect(() => { + if (data?.PID) { + getDetailData(data?.PID) + } + }, [data]) + + + return ( + <> +
+
+
+ {data.stationCode} +
+ +
+
+
+ daichuli +
+
+ + ) +} + +export default React.memo(Wxq); diff --git a/src/views/Home/MapCtrl/Pops/XunJian.js b/src/views/Home/MapCtrl/Pops/XunJian.js new file mode 100644 index 000000000..4318121e0 --- /dev/null +++ b/src/views/Home/MapCtrl/Pops/XunJian.js @@ -0,0 +1,78 @@ +import React, { useEffect, useState } from 'react'; +import { Descriptions, Modal } from 'antd'; +import {CloseOutlined} from '@ant-design/icons'; +import { httpget2 } from '../../../../utils/request'; +import apiurl from '../../../../service/apiurl'; +import moment from "moment" + +function Wxq({ id, data, dispatch }) { + console.log(data); + const width = 400; + const [detail, setDetail] = useState({}) + const [visible,setVisible] = useState(false) + const closePop = () => { + dispatch.runtime.closeFeaturePop(id); + }; + const getDetailData = async(id) => { + try { + const res = await httpget2(`${apiurl.home.wxqdetail}/${id}`); + setDetail(res.data) + } catch (error) { + + } + } + useEffect(() => { + if (data?.PID) { + getDetailData(data?.PID) + } + }, [data]) + + + return ( + <> +
+
+
+
+
+
+
+ {data.stnm} +
+
{setVisible(true)}}>详情
+
+ +
+
+ +
+ + {data?.adnm || detail?.adnm} + {data?.ptcount || detail?.ptcount} + {data?.etcount || detail?.etcount} + {data.htcount || detail?.htcount} + {data.htcount || detail?.htcount} + +
+
+
+
+
+ + + {setVisible(false)}} + width="60vw" + destroyOnClose + className="queryDrpModal" + style={{top:"15px", height:"58vh"}} + > + + + ) +} + +export default React.memo(Wxq); diff --git a/src/views/Home/MapCtrl/Pops/index.js b/src/views/Home/MapCtrl/Pops/index.js index c04e342e4..9ae934a41 100644 --- a/src/views/Home/MapCtrl/Pops/index.js +++ b/src/views/Home/MapCtrl/Pops/index.js @@ -38,6 +38,8 @@ import YHJMH from './YHJMH' import ShenYa from './ShenYa/index.js'; import ShenLiu from './ShenLiu/index.js'; import WeiYi from './WeiYi/index.js'; +import XunJian from './XunJian.js' +import DaiChuLi from './DaiChuLi.js' import YinShuiGongCheng from './YinShuiGongCheng';//这个先不搞 @@ -201,10 +203,15 @@ function FeaturePops({ mapobj }) { ) + }else if (type === 'xunjian'){ + Comp = XunJian + }else if (type === 'daichuli'){ + return ( + dispatch.runtime.closeFeaturePop(id)} destroyOnClose={true}> + + + ) } - - - else{ return null; } diff --git a/src/views/Home/homePanelsLayoutPage/index.js b/src/views/Home/homePanelsLayoutPage/index.js index b3079f5ec..9bf2a3b84 100644 --- a/src/views/Home/homePanelsLayoutPage/index.js +++ b/src/views/Home/homePanelsLayoutPage/index.js @@ -11,6 +11,7 @@ import GongCheng from './item_gongcheng' import JianCe from './item_jiance' import ShuiZhi from './item_shuizhi' import ShiPinDian from './item_shipindian' +import XunChaXunJian from './item_xunchaxunjian' import GCShuiKu from './item_gongchengshuiku' import DaBa from './item_daba' @@ -206,6 +207,7 @@ const HomePage = ({showPanels}) => { { checkedObj.label === '水质' ? :null } { checkedObj.label === '视频点' ? :null } + { checkedObj.label === '巡查巡检' ? :null } { checkedObj.label === '水库' ? :null } { checkedObj.label === '大坝' ? :null } diff --git a/src/views/Home/homePanelsLayoutPage/index.less b/src/views/Home/homePanelsLayoutPage/index.less index 4ee8e66f3..88cde57d3 100644 --- a/src/views/Home/homePanelsLayoutPage/index.less +++ b/src/views/Home/homePanelsLayoutPage/index.less @@ -151,6 +151,54 @@ } } + + .xunchaxunjian{ + .title{ + width: 100%; + height: 35px; + line-height: 35px; + padding: 0 10px; + background-color: #f2f2f2; + letter-spacing: -0.5px; + font-size: 14px; + font-weight: 500; + margin-bottom: 10px; + } + .bodyBox{ + width: 100%; + display: flex; + flex-wrap: wrap; + .bodyBoxItem{ + width: calc( 33% - 10px); + margin: 5px; + height: 90px; + background-color: rgba(234, 244, 254, 1); + border-radius: 5px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + cursor: pointer; + .num{ + height: 45%; + font-weight: 500; + font-size: 22px; + color: #D9001B; + } + .sw{ + color: #04D919; + } + .content{ + display: block; + font-size: 17px; + color: #409EFF; + font-weight: 500; + } + } + } + } + .home_gongshui{ width: 100%; padding: 5px; diff --git a/src/views/Home/homePanelsLayoutPage/item_xunchaxunjian.js b/src/views/Home/homePanelsLayoutPage/item_xunchaxunjian.js new file mode 100644 index 000000000..4a9234cc2 --- /dev/null +++ b/src/views/Home/homePanelsLayoutPage/item_xunchaxunjian.js @@ -0,0 +1,198 @@ +import { useEffect, useState } from "react" +import { Button, Modal, message, Table } from 'antd'; +import {useDispatch, useSelector} from "react-redux"; + +import GeoJSONFormat from "ol/format/GeoJSON"; +import Feature from "ol/Feature"; +import FillStyle from "ol/style/Fill"; +import VectorLayer from "ol/layer/Vector"; +import Style from "ol/style/Style"; +import StrokeStyle from "ol/style/Stroke"; +import { Vector as VectorSource } from "ol/source"; + +import { httppost2 } from "../../../utils/request"; +import apiurl from "../../../service/apiurl"; +import { geometryCenter } from "../../../utils/tools"; +import moment from "moment"; + + + +const Page = ({mySetTms}) => { + const dispatch = useDispatch(); + let mapObj = useSelector(s => s.map.map) + const [ dataObj, setDataObj ] = useState({}) + const [ open, setOpen ] = useState(false) + const [ key , setkey ] = useState('') + const [ tms , setTms ] = useState([ + moment().add(-1,'days').format('YYYY-MM-DD HH:mm:ss'), + moment().format('YYYY-MM-DD HH:mm:ss'), + ]) + + const columns1 = [ + { title: '巡查完成日期', key: 'stnm', dataIndex: 'stnm',align: "center", ellipsis: true }, + { title: '巡查人', key: 'drp', dataIndex: 'drp',align: "center" }, + { title: '异常项次', key: 'drp', dataIndex: 'drp',align: "center" }, + ]; + + const columns2 = [ + { title: '上报时间', key: 'stnm', dataIndex: 'stnm',align: "center", ellipsis: true }, + { title: '巡检问题描述', key: 'drp', dataIndex: 'drp',align: "center" }, + ]; + + useEffect(()=>{ + (async()=>{ + const params = { + start:tms[0], + end:tms[1] + } + const { code, data } = await httppost2(apiurl.home.yj_qxyj,params) + if(code!==200){ + message.error('请求失败') + return + } + mySetTms([ + moment(tms[0]), + moment(tms[1]) + ]) + setDataObj(data) + })() + },[]) + + + const addHlLayer = (geojsonrv,name,color,item)=>{ + mapObj && mapObj.getLayers().getArray().forEach((layer)=> { + if( (layer.values_.name) && ((layer.values_.name).indexOf("HlSX_") !== -1 || (layer.values_.name).indexOf("HlItem_") !== -1 || (layer.values_.name).indexOf("LyItem_") !== -1) ){ + layer.getSource().clear(); + } + }) + + if(!geojsonrv){ + return + } + const geojsonFormat = new GeoJSONFormat(); + let geometry = geojsonFormat.readGeometry(geojsonrv, { + featureProjection: 'EPSG:3857', + }); + const feature = new Feature({ + geometry, + data: item, + name: name + }); + + var vectorSource = new VectorSource({ + features: [feature] + }); + + const vectorLayer = new VectorLayer({ + // @ts-ignore + name: name, + source: vectorSource, + style: new Style({ + stroke: new StrokeStyle({ + color: color, + width: 4, + }), + }), + zIndex:100 + }); + + mapObj.addLayer(vectorLayer); + } + + + return ( +
+
+
+
{dataObj.qxWarn?.length||0}
+
本月巡查
+
+
+
{dataObj.shiftWarn?.length||0}
+
本年巡查
+
+
+
+
{dataObj.pressWarn?.length||0}
+
未处理异常
+
+
+
+ +
+ +
+
+ + {'本月巡查记录'} +
+
+ +
+ ({ + onClick:()=>{ + addHlLayer(data.data,'HlItem_'+data.stnm,'#00FFFF',data) + const center = geometryCenter({type:"LineString",coordinates:data.data.coordinates[0]}); + dispatch.runtime.setFeaturePop({ + id: data.stnm, + data: data, + type: 'xunjian', + lgtd: center[0], + lttd: center[1], + }) + } + }) + } + /> + + +
+ +
+
+ + {'待处理问题清单'} +
+
+ +
+
({ + onClick:()=>{ + // dispatch.map.setLayerVisible({"HdswLayer":true}); + dispatch.runtime.setFeaturePop({ + id: data.stnm, + data: data, + type: 'daichuli', + lgtd: data.lgtd, + lttd: data.lttd, + }) + } + }) + } + /> + + + ) +} + +export default Page From 556d09b55895b891d7599626512482a7d0c89f6a Mon Sep 17 00:00:00 2001 From: qzc Date: Tue, 24 Sep 2024 17:20:44 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E8=8F=9C=E5=8D=95=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/auth/_.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/models/auth/_.ts b/src/models/auth/_.ts index cb7511087..609546689 100644 --- a/src/models/auth/_.ts +++ b/src/models/auth/_.ts @@ -250,13 +250,13 @@ export async function loadMenu(): Promise { id: id(), title: '四预', redirect: '/mgr/sy/fhxzfx', icon: 'fxzb', children: [ { id: id(), title: '防洪形势', path: '/mgr/sy/fhxzfx' }, - { id: id(), title: '天气预报', path: '/mgr/fxzb/tqyb' }, + { id: id(), title: '天气预报', path: '/mgr/sy/tqyb' }, { - id: id(), title: '洪水预报', redirect: '/mgr/fxzb/hsyb/hyybjs', + id: id(), title: '洪水预报', redirect: '/mgr/sy/hsyb/hyybjs', children: [ - { id: id(), title: '洪水预报计算', path: '/mgr/fxzb/hsyb/hyybjs' }, - { id: id(), title: '预报方案管理', path: '/mgr/fxzb/hsyb/ybfagl' }, - { id: id(), title: '参数管理', path: '/mgr/fxzb/hsyb/csgl' }, + { id: id(), title: '洪水预报计算', path: '/mgr/sy/hsyb/hyybjs' }, + { id: id(), title: '预报方案管理', path: '/mgr/sy/hsyb/ybfagl' }, + { id: id(), title: '参数管理', path: '/mgr/sy/hsyb/csgl' }, ] }, { id: id(), title: '防汛预案', path: '/mgr/sy/fxya' }, From 2a3c2fcf3cb35c35202eb64df3d27b12166e5f0f Mon Sep 17 00:00:00 2001 From: lishenfeng Date: Tue, 24 Sep 2024 17:47:24 +0800 Subject: [PATCH 3/6] =?UTF-8?q?feat():=20=E6=8E=A5=E5=8F=A3=E8=B0=83?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service/apiurl.js | 13 +++++++++++++ src/views/sq/qth/hdsq/index.js | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/service/apiurl.js b/src/service/apiurl.js index f1b072af2..f2c47fe8c 100644 --- a/src/service/apiurl.js +++ b/src/service/apiurl.js @@ -7,6 +7,19 @@ const zdkapi = 'https://slt-sh.chutianyun.gov.cn:8002' //中电科的市级平 const service_fxdd = '/gunshiApp/tsg' const service_shzh = '/shzh' const apiurl = { + pxjh: { + page: service_fxdd + "/personnelPlan/page", + edit: service_fxdd + "/personnelPlan/update", + del: service_fxdd + "/personnelPlanLog/del", + save:service_fxdd + "/personnelPlan/insert", + }, + pxjl: { + page: service_fxdd + "/personnelPlanLog/page", + edit: service_fxdd + "/personnelPlanLog/update", + del: service_fxdd + "/personnelPlanLog/del", + save: service_fxdd + "/personnelPlanLog/insert", + sta:service_fxdd + "/personnelPlanLog/statistics" + }, fxya: { page: service_fxdd + "/resPlanB/list", update: service_fxdd + "/resPlanB/update", diff --git a/src/views/sq/qth/hdsq/index.js b/src/views/sq/qth/hdsq/index.js index 34d4e0623..1bbf71f27 100644 --- a/src/views/sq/qth/hdsq/index.js +++ b/src/views/sq/qth/hdsq/index.js @@ -22,7 +22,7 @@ export default function Sksq() { setSwTableData(await zqrl(stcd)); }; useEffect(() => { - getData({args: "",sources: ["SH", "SW"],}) + getData({args: "",sources: ["SH", "SW"]}) }, []) return (
From 70b19cb2fcf1a1f2bc746a58b3397d2ccf734464 Mon Sep 17 00:00:00 2001 From: qzc Date: Wed, 25 Sep 2024 09:57:08 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/Home/fhxs/sksw.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/Home/fhxs/sksw.js b/src/views/Home/fhxs/sksw.js index 54df731ab..cebe96009 100644 --- a/src/views/Home/fhxs/sksw.js +++ b/src/views/Home/fhxs/sksw.js @@ -33,7 +33,7 @@ const Page = ({data}) => { { tableData.length>0? - :
+ :
} ) From cdd8cc9473b60d6f68c4ddcabbd1f83ee144d0d5 Mon Sep 17 00:00:00 2001 From: lishenfeng Date: Thu, 26 Sep 2024 17:45:57 +0800 Subject: [PATCH 5/6] =?UTF-8?q?feat():=E5=B9=BF=E6=92=AD=E9=A2=84=E8=AD=A6?= =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/DashboardLayout/SiderMenu.tsx | 2 +- src/models/auth/_.ts | 15 +- src/service/apiurl.js | 27 +- src/service/ssyq.js | 11 + src/setupProxy.js | 2 +- src/views/AppRouters.tsx | 3 + .../Home/MapCtrl/components/Jcsj/index.js | 30 +- src/views/gbyj/index.js | 266 ++++++++++++++++++ src/views/gbyj/index.less | 43 +++ src/views/gbyj/toolbar.js | 54 ++++ src/views/sz/pxjhgl/RecordForm.js | 109 ++++--- src/views/sz/pxjhgl/form.js | 131 ++++----- src/views/sz/pxjhgl/index.js | 111 ++++++-- src/views/sz/pxjhgl/toolbar.js | 20 +- src/views/sz/pxjlgl/chartToolbar.js | 14 +- src/views/sz/pxjlgl/form.js | 225 ++++++++------- src/views/sz/pxjlgl/index.js | 67 +++-- src/views/sz/pxjlgl/options.js | 36 ++- src/views/sz/pxjlgl/toolbar.js | 12 +- src/views/sz/zrrgl/form.js | 19 +- src/views/sz/zrrgl/index.js | 22 +- src/views/sz/zrrgl/toolbar.js | 6 +- 22 files changed, 894 insertions(+), 331 deletions(-) create mode 100644 src/views/gbyj/index.js create mode 100644 src/views/gbyj/index.less create mode 100644 src/views/gbyj/toolbar.js diff --git a/src/components/DashboardLayout/SiderMenu.tsx b/src/components/DashboardLayout/SiderMenu.tsx index 4c3767f1d..5ce8bae6c 100644 --- a/src/components/DashboardLayout/SiderMenu.tsx +++ b/src/components/DashboardLayout/SiderMenu.tsx @@ -45,7 +45,7 @@ const SiderMenu: React.FC<{ },[menuIndexes[1]]) - const onOpenChange = (keys:any) => { + const onOpenChange = (keys: any) => { let openLength = 0 if(openKeys===undefined){ openLength = 0 diff --git a/src/models/auth/_.ts b/src/models/auth/_.ts index cb7511087..0e83cd23e 100644 --- a/src/models/auth/_.ts +++ b/src/models/auth/_.ts @@ -207,6 +207,19 @@ export async function loadMenu(): Promise { } ] }, + { + id: id(), title: '培训管理', redirect: '/mgr/sz/pxgl/pxjhgl', + children: [ + { + id: id(), title: '培训计划管理', path: '/mgr/sz/pxgl/pxjhgl', + }, + { + id: id(), title: '培训记录管理', path: '/mgr/sz/pxgl/pxjlgl', + }, + ] + }, + + { id: id(), title: '水政执法', redirect: '/mgr/sz/szzf/ajdj', children: [ @@ -363,7 +376,7 @@ export async function loadMenu(): Promise { ], }, { - id: id(), title: '四全', redirect: '/mgr/sq/qfg/zcdjxx', + id: id(), title: '四全', redirect: '/mgr/sq/qfg/zcdjxx', icon: 'fxzb', children: [ { id: id(), title: '全覆盖', redirect: '/mgr/sq/qfg/zcdjxx', diff --git a/src/service/apiurl.js b/src/service/apiurl.js index 924eccbc2..bcba9dc8d 100644 --- a/src/service/apiurl.js +++ b/src/service/apiurl.js @@ -8,18 +8,36 @@ const service_fxdd = '/gunshiApp/tsg' const service_xyt = '/gunshiApp/tsg'//登陆先用小玉潭 const service_shzh = '/shzh' const apiurl = { + gbyj: { + list: service_fxdd + "/broadcastStation/list", //广播站 + page: service_fxdd + "/broadcastWarn/page", + mblist: service_fxdd + "/broadcastTemplate/list", + bb: service_fxdd + "/broadcastWarn/insert", + mbsave: service_fxdd + "/broadcastTemplate/insert", + mbDel:service_fxdd + "/broadcastTemplate/del" + }, + zrrgl: { + page: service_fxdd + "/resPerson/page", + edit: service_fxdd + "/resPerson/update", + delete: service_fxdd + "/resPerson/del", + save:service_fxdd + "/resPerson/insert", + }, pxjh: { page: service_fxdd + "/personnelPlan/page", edit: service_fxdd + "/personnelPlan/update", - del: service_fxdd + "/personnelPlanLog/del", - save:service_fxdd + "/personnelPlan/insert", + delete: service_fxdd + "/personnelPlan/del", + save: service_fxdd + "/personnelPlan/insert", + import: service_fxdd + '/personnelPlan/template', + export:service_fxdd + "/personnelPlan/download" }, pxjl: { page: service_fxdd + "/personnelPlanLog/page", edit: service_fxdd + "/personnelPlanLog/update", - del: service_fxdd + "/personnelPlanLog/del", + delete: service_fxdd + "/personnelPlanLog/del", save: service_fxdd + "/personnelPlanLog/insert", - sta:service_fxdd + "/personnelPlanLog/statistics" + sta: service_fxdd + "/personnelPlanLog/statistics", + list: service_fxdd + "/personnelPlan/list", + getFile:service_fxdd + "/personnelPlanLog/get" }, fxya: { page: service_fxdd + "/resPlanB/list", @@ -833,6 +851,7 @@ const apiurl = { // //实时雨情 ssyq: { + maxDrp:service_fxdd + "/attResBase/maxRain", status: service_fxdd + '/xfProjectRun/has/read', basNameList: service_fxdd + '/real/rain/basNameList', //流域选择 adnmList: service_fxdd + '/real/rain/adnmList', //行政选择 diff --git a/src/service/ssyq.js b/src/service/ssyq.js index 32d56a90f..d3b88f675 100644 --- a/src/service/ssyq.js +++ b/src/service/ssyq.js @@ -131,6 +131,17 @@ export async function StcdAndStartTimeAndEndTimeHour(params) { return data; } +export async function maxDrpUrl(params) { + params.startTime=moment(params.startTime).format("YYYY-MM-DD HH:mm:ss") + params.endTime=moment(params.endTime).format("YYYY-MM-DD HH:mm:ss") + const { data, code, msg } = await httppost(apiurl.ssyq.maxDrp,params) || {}; + + if (code !== 200) { + message.error(msg || '请求失败'); + } + return data; +} + //实时雨情-弹框详情-测站编码查详细雨量 export async function queryStPptnDetails(stcd) { const { data, code, msg } = await httpget(apiurl.ssyq.queryStPptnDetails,{stcd}) || {}; diff --git a/src/setupProxy.js b/src/setupProxy.js index 6a63f5893..5fa5980f9 100644 --- a/src/setupProxy.js +++ b/src/setupProxy.js @@ -6,7 +6,7 @@ module.exports = function (app) { '/gunshiApp', createProxyMiddleware({ target: 'http://local.gunshiiot.com:18083/',//测试 - // target: 'http://36.139.207.50:18083/',//正式 + // target: 'http://192.168.66.199:24105/',//正式 // target: 'http://36.139.207.50:18083/',//移动云 changeOrigin: true, }) diff --git a/src/views/AppRouters.tsx b/src/views/AppRouters.tsx index 637da7a11..fa4ffc054 100644 --- a/src/views/AppRouters.tsx +++ b/src/views/AppRouters.tsx @@ -78,6 +78,8 @@ import Gstjfx from "./gxsl/gstjfx" // 视频监控 import Spjk from "./video" import AiWarn from "./spjk/aiWarn" +// 广播预警 +import Gbyj from "./gbyj/index" // 四全 @@ -222,6 +224,7 @@ const AppRouters: React.FC = () => { // 视频监控 { path: 'sq/qth/spjk', element: }, { path: 'sg/gjgl/aigj', element: }, + { path: 'sg/gjgl/gbyj', element: }, // { path: 'fxzb/zbb', element: }, // { path: 'fxzb/txl', element: }, diff --git a/src/views/Home/MapCtrl/components/Jcsj/index.js b/src/views/Home/MapCtrl/components/Jcsj/index.js index 2a568168c..dec9cb35e 100644 --- a/src/views/Home/MapCtrl/components/Jcsj/index.js +++ b/src/views/Home/MapCtrl/components/Jcsj/index.js @@ -6,7 +6,7 @@ import clsx from "clsx"; import './index.less' import TableData from './TableData' import drpOption from './drpOption'; -import {StcdAndStartTimeAndEndTime,StcdAndStartTimeAndEndTimeHour,queryStPptnDetails,queryStStbprpPerDayChart,queryStStbprpPerHourChart} from '../../../../../service/ssyq' +import {StcdAndStartTimeAndEndTime,StcdAndStartTimeAndEndTimeHour,queryStPptnDetails,queryStStbprpPerDayChart,queryStStbprpPerHourChart,maxDrpUrl} from '../../../../../service/ssyq' const {RangePicker} = DatePicker; @@ -22,7 +22,7 @@ function DrpSearch({record}) { const [echartData, setEchartData] = useState({}); const [current, setCurrent] = useState(0); const [detail, setDetail] = useState({}); - + const [maxDrp, setMaxDrp] = useState({}) const option = useMemo(() => { return drpOption({echartData}); @@ -45,9 +45,11 @@ function DrpSearch({record}) { console.log("params",params); if(current==0){ setData(await StcdAndStartTimeAndEndTimeHour(params)); + setMaxDrp(await maxDrpUrl(params)); setEchartData(await queryStStbprpPerHourChart(params)); }else{ setData(await StcdAndStartTimeAndEndTime(params)); + setMaxDrp(await maxDrpUrl(params)); setEchartData(await queryStStbprpPerDayChart(params)); } setDetail(await queryStPptnDetails(record?.stcd)) @@ -130,35 +132,35 @@ function DrpSearch({record}) {
-
近1h雨量(mm)
-
{detail?.h1||0}
+
最大1h雨量(mm)
+
{maxDrp?.h1||0}
-
近3h雨量(mm)
-
{detail?.h3||0}
+
最大3h雨量(mm)
+
{maxDrp?.h3||0}
-
近6h雨量(mm)
-
{detail?.h6||0}
+
最大6h雨量(mm)
+
{maxDrp?.h6||0}
-
近12h雨量(mm)
-
{detail?.h12||0}
+
最大12h雨量(mm)
+
{maxDrp?.h12||0}
-
+ {/*
近24h雨量(mm)
{detail?.h24||0}
-
+
*/}
本年降雨天数
{detail?.yearDrpDay}/{days}
-
+ {/*
近48h雨量(mm)
{detail?.h48||0}
-
+
*/}
今日雨量(mm)
{detail.today}
diff --git a/src/views/gbyj/index.js b/src/views/gbyj/index.js new file mode 100644 index 000000000..764300db9 --- /dev/null +++ b/src/views/gbyj/index.js @@ -0,0 +1,266 @@ +import React, { useState, useEffect, useMemo,useRef } from 'react' +import usePageTable from '../../components/crud/usePageTable2'; +import { createCrudService } from '../../components/crud/_'; +import apiurl from '../../service/apiurl'; +import { httppost2,httpget2 } from '../../utils/request'; +import CryptoJS from 'crypto-js'; +import { Card,Table,Button,Radio,Input,Select,Modal,message } from "antd" +import ToolBar from "./toolbar" +import "./index.less" +export default function Gbyj() { + const [searchValue, setSearchVal] = useState() + const [switchVisible, setSwitchVisible] = useState(false); + const [bbParams, setBbParams] = useState({}) + const [addOpen, setAddOpen] = useState(false) + const [mbParams, setMbParams] = useState({}) + const columns = [ + { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" }, + { title: '广播站名称', key: 'name', dataIndex: 'name', width: 200, ellipsis: true }, + { + title: '告警内容', key: 'warnContent', dataIndex: 'warnContent', width: 300,ellipsis: true + }, + { title: '播报时间', key: 'createTime', dataIndex: 'createTime', width: 200 }, + { + title: '播报人员', key: 'createUserName', dataIndex: 'createUserName', width: 200,ellipsis: true + }, + ]; + const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]); + const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.gbyj.page).find_noCode); + //广播站 + const [jh, setJh] = useState([]) + const getJhList = async () => { + try { + const res = await httppost2(apiurl.gbyj.list) + if (res.code == 200) { + setJh(res.data.map(item => ({label:item.name,value:item.id}))) + } + } catch (error) { + console.log(error); + + } + } + const [mbList, setMbList] = useState([]) + + const getMbList = async () => { + try { + const res = await httppost2(apiurl.gbyj.mblist); + if(res.code === 200){ + setMbList(res.data.map(item=>({label:item.content, value:item.id}))); + } + } catch (error) { + console.log(error); + } + + } + + + // 右边添加模版 + const addMb = async () => { + try { + const res = await httppost2(apiurl.gbyj.mbsave, { content: bbParams.warnContent }); + if (res.code == 200) { + message.success('添加成功'); + getMbList(); + } + } catch (error) { + console.log(error); + } + } + + // 左边添加模版 + const saveMb = async () => { + try { + const res = await httppost2(apiurl.gbyj.mbsave, mbParams); + if (res.code == 200) { + message.success('添加成功'); + getMbList(); + setAddOpen(false) + } + } catch (error) { + console.log(error); + } + } + + // 删除模版 + const delMb = async () => { + try { + const res = await httpget2(apiurl.gbyj.mbDel + `/${bbParams.checkId}`); + if (res.code == 200) { + message.success('删除成功'); + getMbList(); + setBbParams({...bbParams,warnContent:'' }) + } + } catch (error) { + console.log(error); + } + } + const handleCheck = (e) => { + const text = mbList.find(item => item.value == e.target.value)?.label + setBbParams({ ...bbParams, warnContent:text,checkId:e.target.value }) + } + + const gbzChange = (e) => { + setBbParams({...bbParams,stationIds:e}) + } + + const textChange = (e) => { + setBbParams({ ...bbParams, warnContent: e.target.value }) + } + + // 播报 + + const playGb = () => { + setSwitchVisible(true); + + } + + + //md5加密 + const encryptData = (data) => { + const encryptedData = CryptoJS.MD5(data).toString(); + return encryptedData; + } + // 确认播报 + const confirmBb = async () => { + const name = localStorage.getItem('userName') + const id = localStorage.getItem('userId') + const params = { + ...bbParams, + ctrlPass: encryptData(bbParams?.ctrlPass), + createUserId: id, + createUserName: name + } + try { + const res = await httppost2(apiurl.gbyj.bb,params); + if (res.code == 200) { + setSwitchVisible(false); + message.success('播报成功'); + refresh() + } + } catch (error) { + console.log(error); + } + + + } + useEffect(()=>{ + const params = { + search: { + ...searchValue, + } + }; + search(params) + }, [searchValue]) + + useEffect(() => { + getMbList() + getJhList() + }, []) + + return ( +
+
+
+ + 广播预警信息查询 +
+ + + +
+
+ + +
+
+
+ + 广播模板 + + +
+
+ +
+
+
+
+ + 编辑播报内容 + +
+
+
+ +
+
+
+ + 选择广播预警站 +
+
+ 已选择: + {setMbParams({...mbParams,content:e.target.value}) + }} /> +
+
+ +
+ ) +} diff --git a/src/views/gbyj/index.less b/src/views/gbyj/index.less new file mode 100644 index 000000000..c53a780a0 --- /dev/null +++ b/src/views/gbyj/index.less @@ -0,0 +1,43 @@ + +.gb-top-title{ + display: flex; + align-items: center; + column-gap: 10px; + margin-bottom: 20px; + .gb-top-icon{ + width: 5px; + height: 20px; + background-color: #0079fe; + } +} +.gb-bottom{ + display: flex; + // align-items: center; + column-gap: 20px; + margin-top: 20px; + .gb-bottom-left{ + flex: 1; + .mb-content{ + width: 100%; + margin-top: 10px; + padding: 10px; + height: 300px; + overflow-y: auto; + border: 1px solid #dfdfdf; + .ant-radio-wrapper{ + margin-bottom: 10px; + } + } + } + .gb-bottom-right{ + flex: 1; + .right-content{ + .station-content{ + display: flex; + align-items: center; + column-gap: 10px; + margin-top: 25px; + } + } + } +} \ No newline at end of file diff --git a/src/views/gbyj/toolbar.js b/src/views/gbyj/toolbar.js new file mode 100644 index 000000000..091e3a39f --- /dev/null +++ b/src/views/gbyj/toolbar.js @@ -0,0 +1,54 @@ +import React, { useEffect,useState } from 'react'; +import { Form, Upload, Button,Row, Col, Input, DatePicker, message,Modal } from 'antd'; +import apiurl from '../../service/apiurl'; +import { httppost2 } from '../../utils/request'; +import moment from 'moment'; +import NormalSelect from '../../components/Form/NormalSelect'; +const { RangePicker } = DatePicker; +const ToolBar = ({ setSearchVal,jh}) => { + const [form] = Form.useForm(); + + const onFinish = (values) => { + let timeRangeSo; + if (values.tm) { + timeRangeSo = { + start: moment(values.tm[0]).format('YYYY-MM-DD HH:mm:ss'), + end: moment(values.tm[1]).format('YYYY-MM-DD HH:mm:ss') + } + } + delete values.tm + setSearchVal({...values, timeRangeSo}); + } + return ( + <> +
+
+ + + + + + + + + + + + + + + + + +
+ + + ); +} + +export default ToolBar; \ No newline at end of file diff --git a/src/views/sz/pxjhgl/RecordForm.js b/src/views/sz/pxjhgl/RecordForm.js index 6ca5d0738..24dc18c13 100644 --- a/src/views/sz/pxjhgl/RecordForm.js +++ b/src/views/sz/pxjhgl/RecordForm.js @@ -7,6 +7,8 @@ import NormalSelect from '../../../components/Form/NormalSelect'; import "./index.less" import moment from 'moment'; import { createCrudService } from '../../../components/crud/_'; +import { httpget2, httppost2 } from '../../../utils/request'; + const { RangePicker } = DatePicker const { Dragger } = Upload; const url = "http://223.75.53.141:9102/test.by-lyf.tmp" @@ -91,7 +93,18 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { setPdfViewOPen(true) } - + const [jh, setJh] = useState([]) + const getJhList = async () => { + try { + const res = await httppost2(apiurl.pxjl.list) + if (res.code == 200) { + setJh(res.data.map(item => ({label:item.name,value:item.id}))) + } + } catch (error) { + console.log(error); + + } + } @@ -102,17 +115,22 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { }, [record]) useEffect(() => { - if (mode !== "save") { - let dataSo = [ - record.validStartDate? moment(record.validStartDate):'', - record.validEndDate? moment(record.validEndDate): '' - ] + getJhList() + }, []) + + +// useEffect(() => { +// if (mode !== "save") { +// let dataSo = [ +// record.validStartDate? moment(record.validStartDate):'', +// record.validEndDate? moment(record.validEndDate): '' +// ] - form.setFieldsValue({...record,dateRangeSo:dataSo}) +// form.setFieldsValue({...record,dateRangeSo:dataSo}) - } +// } - }, [record,mode]) +// }, [record,mode]) return (
@@ -121,21 +139,21 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
- + @@ -145,7 +163,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} @@ -157,7 +175,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -167,52 +185,59 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { - - + setTimeValue(e)} + /> - - + - - + - - + - - + @@ -220,7 +245,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { - - + - + - - + dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} - > diff --git a/src/views/sz/pxjhgl/form.js b/src/views/sz/pxjhgl/form.js index 910933218..5a0093663 100644 --- a/src/views/sz/pxjhgl/form.js +++ b/src/views/sz/pxjhgl/form.js @@ -47,40 +47,14 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { const [pdfViewOPen, setPdfViewOPen] = useState(false) const [loading, setLoading] = useState(false) - /** - * @description 获取查看时文件 - * @param {*} type - * @returns - */ - const getFileInfo = (params) => { - createCrudService(apiurl.fxzb.qsdw.zq.getFile).delGet({ teamId: params.teamId }).then(res => { - if (res.code === 200) { - let fileArr = res.data?.files.map(item => { - return { - name: item.fileName, - response: { - data: { - filePath: item.filePath, - fileId:item.fileId - } - }, - } - }) - setFileList(fileArr) - const result = res.data?.details.map(item => ({ ...item, key: item.detailId })) - console.log("resss",result); - - setDetails(result) - } - }) - } + /** * @description 文件下载 * @param {String} params 文件fileId */ const download = (params) => { let downloadLink = document.createElement("a"); - downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/xyt/rescue/team/file/download/${params}`; + downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/tsg/personnelPlan/file/download/${params}`; downloadLink.download = `${params.fileName}`; downloadLink.style.display = "none"; // 将链接添加到页面中 @@ -120,20 +94,18 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { } - const onfinish = () => { - let values = form.getFieldsValue(); - values.details = details; - values.validStartDate = values.dateRangeSo&&moment(values.dateRangeSo[0]).format("YYYY-MM-DD") - values.validEndDate = values.dateRangeSo&&moment(values.dateRangeSo[1]).format("YYYY-MM-DD") + const onfinish = (values) => { + values.regDate = moment(values.regDate).format('YYYY-MM-DD') + let oldFiles = fileList.map(item => ({fileId:item.response?.data?.fileId })) + values.files = oldFiles; if (mode === 'edit') { - let oldFiles = fileList.map(item => item.response?.data?.fileId ) - values.fileIds = oldFiles; - values.teamId = record.teamId; - onEdit(apiurl.fxzb.qsdw.zq.edit,values) + onEdit(apiurl.pxjh.edit,{...record,...values}) } if (mode === 'save') { - values.fileIds = fileIds - onSave(apiurl.fxzb.qsdw.zq.save,values) + onSave(apiurl.pxjh.save,values) + } + if (mode === "similarSave") { + onSave(apiurl.pxjh.save,values) } } @@ -146,24 +118,31 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { let filterFile = fileList.filter(item => item.response?.data?.fileId !== fileId); setFileList(filterFile) } - useEffect(()=>{ - if (record.teamId ) { - getFileInfo(record) - } - }, [record]) + useEffect(() => { - if (mode !== "save") { - let dataSo = [ - record.validStartDate? moment(record.validStartDate):'', - record.validEndDate? moment(record.validEndDate): '' - ] - - form.setFieldsValue({...record,dateRangeSo:dataSo}) - + if (mode!== "save") { + let fileArr = record?.files.map(item => { + return { + name: item.fileName, + response: { + data: { + filePath: item.filePath, + fileId:item.fileId + } + }, + } + }) + setFileList(fileArr) } - - }, [record,mode]) + }, [mode, record]) + + useEffect(() => { + const userName = localStorage.getItem('userName') + form.setFieldValue("regDate", moment()) + form.setFieldValue("applicant",userName) + }, []) + return (
@@ -172,13 +151,14 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
@@ -187,7 +167,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -198,7 +178,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} @@ -223,7 +203,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} @@ -238,7 +218,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -246,7 +226,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -257,7 +237,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { - + @@ -283,7 +263,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { @@ -308,7 +288,8 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -316,7 +297,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -326,7 +307,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -334,7 +315,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -344,7 +325,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -353,7 +334,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} @@ -378,7 +359,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { console.log(info.dataTransfer.files); }} fileList={fileList} @@ -480,7 +461,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { border: 0, marginTop: 20, }} - src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/xyt/rescue/goods/file/download/${iframeSrc}`)}`} + src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/tsg/personnelPlan/file/download/${iframeSrc}`)}`} /> diff --git a/src/views/sz/pxjhgl/index.js b/src/views/sz/pxjhgl/index.js index 054d3463f..63089013c 100644 --- a/src/views/sz/pxjhgl/index.js +++ b/src/views/sz/pxjhgl/index.js @@ -4,13 +4,13 @@ import BasicCrudModal from '../../../components/crud/BasicCrudModal'; import { Table, Card,Modal,Image,Input,Button,Row,Col,message } from 'antd'; import ToolBar from './toolbar'; import ModalForm from './form'; -import RecordDetails from "./RecordForm" +import RecordDetails from "../pxjlgl/form" import apiurl from '../../../service/apiurl'; import usePageTable from '../../../components/crud/usePageTable2'; import { createCrudService } from '../../../components/crud/_'; import { CrudOpRender_text } from '../../../components/crud/CrudOpRender'; import { exportFile } from '../../../utils/tools.js'; -import { httppost5 } from '../../../utils/request'; +import { httppost5,httpget2 } from '../../../utils/request'; const Page = () => { const url = "http://223.75.53.141:9102/test.by-lyf.tmp" @@ -21,18 +21,21 @@ const Page = () => { const refModal = useRef(); const [searchVal, setSearchVal] = useState(false) const [pxRecordOpen, setPxRecordOpen] = useState(false) + + const [qdItem, setQdItem] = useState() const columns = [ { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" }, - { title: '培训班名称', key: 'teamName', dataIndex: 'teamName', width: 200, ellipsis: true }, + { title: '培训班名称', key: 'name', dataIndex: 'name', width: 200, ellipsis: true }, { - title: '计划培训周期', key: 'personCount', dataIndex: 'personCount', width: 200, + title: '计划培训周期', key: 'num1', dataIndex: 'num1', width: 200, + render: (value, record) => {(record?.stm && record?.etm) ? `${record?.stm}至${record?.etm}` : ''}, }, - { title: '主办单位', key: 'address', dataIndex: 'address', width: 200 }, + { title: '主办单位', key: 'unit', dataIndex: 'unit', width: 200 }, { - title: '培训内容', key: 'managementUnit', dataIndex: 'managementUnit', width: 200,ellipsis: true + title: '培训内容', key: 'content', dataIndex: 'content', width: 200,ellipsis: true }, - { title: '培训地点', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, ellipsis: true }, - { title: '填报人', key: 'phone', dataIndex: 'phone', width: 150, ellipsis: true }, + { title: '培训地点', key: 'addr', dataIndex: 'addr', width: 150, ellipsis: true }, + { title: '填报人', key: 'applicant', dataIndex: 'applicant', width: 150, ellipsis: true }, { title: '操作', key: 'operation', width: 300, fixed: 'right',align: 'center', @@ -48,23 +51,24 @@ const Page = () => { ]; const columns1 = [ { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" }, - { title: '培训日期', key: 'teamName', dataIndex: 'teamName', width: 150, ellipsis: true }, + { title: '培训日期', key: 'planDate', dataIndex: 'planDate', width: 150, ellipsis: true }, { title: '培训时段', key: 'personCount', dataIndex: 'personCount', width: 150, + render: (value, record) => {(record?.stm && record?.etm) ? `${record?.stm}至${record?.etm}` : ''}, }, - { title: '参加人数', key: 'address', dataIndex: 'address', width: 100 }, + { title: '参加人数', key: 'trainees', dataIndex: 'trainees', width: 100 }, { - title: '参训人员', key: 'managementUnit', dataIndex: 'managementUnit', width: 200,ellipsis: true + title: '参训人员', key: 'numPeople', dataIndex: 'numPeople', width: 200,ellipsis: true }, { title: '培训签到表', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, - render: (value) => + render: (value,record) => }, { title: '操作', key: 'operation', width: 100, fixed: 'right',align: 'center', render: (value, row, index) => ( - {setPxRecordOpen(true)}}>查看 + { setPxRecordOpen(true); setQdItem(row)}}>查看 ) }, ]; @@ -74,6 +78,10 @@ const Page = () => { const [pxOpen, setPxOpen] = useState(false) const [imgVisible, setImgVisible] = useState(false) const [imgList, setImgList] = useState([]) + const [fileList1, setFileList1] = useState([]) //上传文件列表 + const [fileList2, setFileList2] = useState([]) //上传文件列表 + + const reviewPic = (arrPic) => { if (arrPic.length > 0) { setImgVisible(true) @@ -88,19 +96,26 @@ const Page = () => { } else if (type === 'view') { refModal.current.showView(params); } else if (type === 'del') { - refModal.current.onDeleteGet(apiurl.fxzb.qsdw.zq.delete + `/${params.teamId}`); + refModal.current.onDeleteGet(apiurl.pxjh.delete + `/${params.id}`); }else if (type === 'similarAdd') { refModal.current.showSimilarSave(params); } else { // 培训记录 + const params1 = { + search: { + ...searchVal, + planId:params.id + } + }; setPxOpen(true); - // setPxItem + search1(params1) + // getFileInfo(params) } } - const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.fxzb.qsdw.zq.page).find_noCode); - const { tableProps:tableProps1, search:search1 } = usePageTable(createCrudService(apiurl.fxzb.qsdw.zq.page).find_noCode); + const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.pxjh.page).find_noCode); + const { tableProps:tableProps1, search:search1 } = usePageTable(createCrudService(apiurl.pxjl.page).find_noCode); /** * @description 处理成功的回调 @@ -110,14 +125,51 @@ const Page = () => { } +// const getFileInfo = async (params) => { +// try { +// const res = await httpget2(apiurl.pxjl.getFile + `/${params.id}`) +// if (res.code === 200) { +// if (res.data?.files1) { +// let fileArr1 = res.data?.files1.map(item => { +// return { +// name: item.fileName, +// response: { +// data: { +// filePath: item.filePath, +// fileId: item.fileId +// } +// }, +// } +// }) +// setFileList1(fileArr1) +// } +// if (res.data?.files2) { +// let fileArr2 = res.data?.files2.map(item => { +// return { +// name: item.fileName, +// response: { +// data: { +// filePath: item.filePath, +// fileId: item.fileId +// } +// }, +// } +// }) +// setFileList2(fileArr2) +// } +// } +// } catch (error) { +// console.log(error); +// } + +// } + // 导出 const exportExcel = () => { let params = { ...searchVal, - - id:1 } - httppost5(apiurl.gcaqjc.gcaqfx.jrx.export, params).then(res => { + httppost5(apiurl.pxjh.export, params).then(res => { exportFile(`培训计划管理.xlsx`,res.data) }) } @@ -129,6 +181,18 @@ const Page = () => { }; search(params) }, [searchVal]) + + // const dataSource = useMemo(() => { + // if (tableProps1.dataSource.length > 0) { + // return tableProps1.dataSource.map(item => ({ + // ...item, + // files1: fileList1, + // files2: fileList2, + // })) + // } else { + // return [] + // } + // },[tableProps1.dataSource,fileList1,fileList2]) return ( @@ -141,7 +205,7 @@ const Page = () => { onSave={command('save')} role={role} callback={refresh} - exportFile={exportExcel} + exportFile1={exportExcel} />
@@ -155,7 +219,6 @@ const Page = () => { title="" component={ModalForm} onCrudSuccess={successCallback} - // onCrudSuccess={()=>{refresh({addvcd:localStorage.getItem('ADCD6')})}} />
{/* 培训记录 */} @@ -173,7 +236,7 @@ const Page = () => { columns={columns1} rowKey="inx" {...tableProps1} - dataSource={[{teamName:1}]} + // dataSource={dataSource} scroll={{ x: width1, y: "calc( 100vh - 400px )" }} /> @@ -189,7 +252,7 @@ const Page = () => { setPxRecordOpen(false); }} > - +
{ +const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFile1 }) => { const [form] = Form.useForm(); const addBtn = role?.rule?.find(item => item.menuName == "新增")|| true; const searchBtn = role?.rule?.find(item => item.menuName == "查询") || true; @@ -20,12 +20,12 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil let dateSo; if (values.tm) { dateSo = { - start: moment(values.tm[0]).format('YYYY'), - end: moment(values.tm[1]).format('YYYY') + stm: moment(values.tm[0]).format('YYYY'), + etm: moment(values.tm[1]).format('YYYY') } } delete values.tm - setSearchVal({...values, dateSo}); + setSearchVal({...values, ...dateSo}); } const beforeUpload = (file) => { @@ -58,7 +58,7 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil } const downTemplate = ()=>{ - httppost5(apiurl.rcgl.zbgl.zbb.import, {}).then(res => { + httpgetExport(apiurl.pxjh.import, {}).then(res => { exportFile(`培训计划管理.xlsx`,res.data) }) } @@ -76,10 +76,10 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil picker='year' /> - + - + {searchBtn ? @@ -99,7 +99,7 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil - +
@@ -117,7 +117,7 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil { console.log(info); }} diff --git a/src/views/sz/pxjlgl/chartToolbar.js b/src/views/sz/pxjlgl/chartToolbar.js index a0d84bfaa..69e25f2ce 100644 --- a/src/views/sz/pxjlgl/chartToolbar.js +++ b/src/views/sz/pxjlgl/chartToolbar.js @@ -1,6 +1,7 @@ import React, { useEffect,useState } from 'react'; import { Form, Upload, Button,Row, Col, Input, DatePicker, message,Modal } from 'antd'; import NormalSelect from '../../../components/Form/NormalSelect'; +import moment from 'moment'; const ToolBar = ({ setSearchVal }) => { const [form] = Form.useForm(); @@ -14,15 +15,24 @@ const ToolBar = ({ setSearchVal }) => { value: 2 }, ] + const valuesChange = (e,allvalue) => { + setSearchVal({ ...allvalue,year:moment(allvalue.year).format("YYYY") }) + } + useEffect(() => { + const value = {teamName:1,year:moment()} + form.setFieldsValue(value) + setSearchVal({...value,year:moment().format("YYYY")}) + }, []) + return ( <>
-
{setSearchVal(e)}}> + - + { value:5 }, ] - const jh = [ - { - label: "工程测量业务知识", - value:1 - }, - { - label: "工程管理标准化业务知识", - value:2 - },{ - label: "消防安全知识培训", - value:3 - },{ - label: "水雨情测报培训", - value:4 - } - ] const [details, setDetails] = useState([]) @@ -73,27 +59,43 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { * @param {*} type * @returns */ - const getFileInfo = (params) => { - createCrudService(apiurl.fxzb.qsdw.zq.getFile).delGet({ teamId: params.teamId }).then(res => { + const getFileInfo = async (params) => { + try { + const res = await httpget2(apiurl.pxjl.getFile + `/${params.id}`) if (res.code === 200) { - let fileArr = res.data?.files.map(item => { - return { - name: item.fileName, - response: { - data: { - filePath: item.filePath, - fileId:item.fileId - } - }, + if (res.data?.files1) { + let fileArr1 = res.data?.files1.map(item => { + return { + name: item.fileName, + response: { + data: { + filePath: item.filePath, + fileId: item.fileId } - }) - setFileList(fileArr) - const result = res.data?.details.map(item => ({ ...item, key: item.detailId })) - console.log("resss",result); - - setDetails(result) + }, + } + }) + setFileList1(fileArr1) + } + if (res.data?.files2) { + let fileArr = res.data?.files2.map(item => { + return { + name: item.fileName, + response: { + data: { + filePath: item.filePath, + fileId: item.fileId + } + }, + } + }) + setFileList(fileArr) + } } - }) + } catch (error) { + console.log(error); + } + } /** * @description 文件下载 @@ -101,7 +103,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { */ const download = (params) => { let downloadLink = document.createElement("a"); - downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/xyt/rescue/team/file/download/${params}`; + downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/tsg/personnelPlanLog/file/download/${params}`; downloadLink.download = `${params.fileName}`; downloadLink.style.display = "none"; // 将链接添加到页面中 @@ -113,7 +115,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { const download1 = (params) => { let downloadLink = document.createElement("a"); - downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/xyt/rescue/team/file/download/${params}`; + downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/tsg/personnelPlanLog/file/download/${params}`; downloadLink.download = `${params.fileName}`; downloadLink.style.display = "none"; // 将链接添加到页面中 @@ -160,6 +162,8 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { }) setFileIds1(fileIds) setFileList1(info.fileList) + console.log(info.fileList); + } /** * @description pdf文件预览 @@ -174,20 +178,19 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { setIframeSrc1(params) setPdfViewOPen1(true) } - const onfinish = () => { - let values = form.getFieldsValue(); - values.details = details; - values.validStartDate = values.dateRangeSo&&moment(values.dateRangeSo[0]).format("YYYY-MM-DD") - values.validEndDate = values.dateRangeSo&&moment(values.dateRangeSo[1]).format("YYYY-MM-DD") + const onfinish = (values) => { + values.stm = values.tm ? values.tm[0].format("HH:mm:ss") : '' + values.etm = values.tm ? values.tm[1].format("HH:mm:ss") : '' + values.regDate = moment(values.regDate).format('YYYY-MM-DD') + const files1 = fileList1.map(item => ({fileId:item.response?.data?.fileId })); + const files = fileList.map(item => ({ fileId: item.response?.data?.fileId })); + values.files1 = files1; + values.files2 = files; if (mode === 'edit') { - let oldFiles = fileList.map(item => item.response?.data?.fileId ) - values.fileIds = oldFiles; - values.teamId = record.teamId; - onEdit(apiurl.fxzb.qsdw.zq.edit,values) + onEdit(apiurl.pxjl.edit,{...record,...values}); } if (mode === 'save') { - values.fileIds = fileIds - onSave(apiurl.fxzb.qsdw.zq.save,values) + onSave(apiurl.pxjl.save,values) } } @@ -206,24 +209,51 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { let filterFile = fileList1.filter(item => item.response?.data?.fileId !== fileId); setFileList1(filterFile) } - useEffect(()=>{ - if (record.teamId ) { - getFileInfo(record) + const [jh, setJh] = useState([]) + const getJhList = async () => { + try { + const res = await httppost2(apiurl.pxjl.list) + if (res.code == 200) { + setJh(res.data.map(item => ({label:item.name,value:item.id}))) } - }, [record]) + } catch (error) { + console.log(error); + + } + } + + const imgbeforeUpload = (file) => { + const isJpgOrPng = + file.type === 'image/jpeg' || + file.type === 'image/jpg' || + file.type === 'image/png'; + + if (!isJpgOrPng) { + message.error('请上传图片格式的文件!'); + } + const isLt2M = file.size / 1024 / 1024 < 5; + if (!isLt2M) { + message.error('图片大小需小于5M!'); + } + return isJpgOrPng && isLt2M ? true : Upload.LIST_IGNORE; + }; + useEffect(()=>{ + if (mode !== "save") { + getFileInfo(record) + const momentArr = (record?.stm && record.etm) ? [dayjs("2024-05-06" + record.stm), dayjs("2024-05-06" +record.etm)] : '' + form.setFieldValue("tm",momentArr) + } + }, [record,mode]) useEffect(() => { - if (mode !== "save") { - let dataSo = [ - record.validStartDate? moment(record.validStartDate):'', - record.validEndDate? moment(record.validEndDate): '' - ] - - form.setFieldsValue({...record,dateRangeSo:dataSo}) + const userName = localStorage.getItem('userName') + form.setFieldValue("regDate", moment()) + form.setFieldValue("applicant",userName) + getJhList() + }, []) + - } - }, [record,mode]) return (
@@ -232,13 +262,14 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
@@ -246,7 +277,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -256,7 +287,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} @@ -267,7 +298,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -279,15 +310,22 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { - + setTimeValue(e)} + /> @@ -297,7 +335,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -307,7 +345,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { @@ -317,7 +355,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { - - - - - @@ -363,15 +391,15 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { - + dateString} getValueProps={(value) => ({ value: value ? moment(value) : undefined })} @@ -384,24 +412,25 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { {mode !== "view" && { console.log(info.dataTransfer.files); }} fileList={fileList1} disabled={loading1} + maxCount={1} // onSuccess={handleSuccess} > -

点击或拖拽文件到此区域上传

+

点击或拖拽文件到此区域上传

- 支持扩展名:.rar .zip .doc .docx .pdf .jpg .png .ppt + 支持扩展名:.jpg .png

} @@ -450,7 +479,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { } {file.name} -
deleteFile(file.response?.data?.fileId)}> +
deleteFile1(file.response?.data?.fileId)}>
@@ -477,7 +506,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { { console.log(info.dataTransfer.files); }} fileList={fileList} @@ -579,7 +608,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { border: 0, marginTop: 20, }} - src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/xyt/rescue/goods/file/download/${iframeSrc}`)}`} + src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/tsg/personnelPlanLog/file/download/${iframeSrc}`)}`} /> @@ -600,7 +629,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => { border: 0, marginTop: 20, }} - src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/xyt/rescue/goods/file/download/${iframeSrc1}`)}`} + src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/tsg/personnelPlanLog/file/download/${iframeSrc1}`)}`} /> diff --git a/src/views/sz/pxjlgl/index.js b/src/views/sz/pxjlgl/index.js index 8b3a6b164..c8b58bcf5 100644 --- a/src/views/sz/pxjlgl/index.js +++ b/src/views/sz/pxjlgl/index.js @@ -12,6 +12,8 @@ import usePageTable from '../../../components/crud/usePageTable2'; import { createCrudService } from '../../../components/crud/_'; import { CrudOpRender_text } from '../../../components/crud/CrudOpRender'; import "./index.less" +import { httpget2 } from '../../../utils/request'; +import moment from 'moment'; const Page = () => { const role = useSelector(state => state.auth.role); @@ -23,18 +25,18 @@ const Page = () => { const [searchChartVal, setSearchChartVal] = useState(false) const columns = [ { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" }, - { title: '培训日期', key: 'teamName', dataIndex: 'teamName', width: 200, ellipsis: true }, + { title: '培训日期', key: 'planDate', dataIndex: 'planDate', width: 200, ellipsis: true }, { - title: '标题', key: 'personCount', dataIndex: 'personCount', width: 200,ellipsis: true + title: '标题', key: 'name', dataIndex: 'name', width: 200,ellipsis: true }, - { title: '主办单位', key: 'address', dataIndex: 'address', width: 150 }, + { title: '主办单位', key: 'unit', dataIndex: 'unit', width: 150 }, { - title: '培训内容', key: 'managementUnit', dataIndex: 'managementUnit', width: 200,ellipsis: true + title: '培训内容', key: 'content', dataIndex: 'content', width: 200,ellipsis: true }, - { title: '参训人员', key: 'teamName', dataIndex: 'teamName', width: 200, ellipsis: true }, - { title: '培训地点', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, ellipsis: true }, - { title: '填报人', key: 'phone', dataIndex: 'phone', width: 150, ellipsis: true }, - { title: '登记日期', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, ellipsis: true }, + { title: '参训人员', key: 'trainees', dataIndex: 'trainees', width: 200, ellipsis: true }, + { title: '培训地点', key: 'addr', dataIndex: 'addr', width: 150, ellipsis: true }, + { title: '填报人', key: 'applicant', dataIndex: 'applicant', width: 150, ellipsis: true }, + { title: '登记日期', key: 'regDate', dataIndex: 'regDate', width: 150, ellipsis: true }, { title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center', @@ -48,9 +50,7 @@ const Page = () => { ]; const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]); - const pxOptions = useMemo(() => { - return options() - }, []) + const command = (type) => (params) => { if (type === 'save') { refModal.current.showSave(); @@ -59,12 +59,12 @@ const Page = () => { } else if (type === 'view') { refModal.current.showView(params); } else if (type === 'del') { - refModal.current.onDeleteGet(apiurl.fxzb.qsdw.zq.delete + `/${params.teamId}`); + refModal.current.onDeleteGet(apiurl.pxjl.delete + `/${params.id}`); } } - const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.fxzb.qsdw.zq.page).find_noCode); + const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.pxjl.page).find_noCode); /** * @description 处理成功的回调 @@ -73,7 +73,29 @@ const Page = () => { refresh() } - +// 获取统计数据 + const [staData, setStaData] = useState() + const pxOptions = useMemo(() => { + if (staData) { + return options(staData) + } else { + return options({}) + } + }, [staData]) + const getStaData = async (params) => { + try { + const res = await httpget2(apiurl.pxjl.sta + `/${params.year}`) + if (res.code == 200) { + if (params.teamName == 1) { + setStaData({...res.data,list:res.data.list1}) + } else { + setStaData({...res.data,list:res.data.list2}) + } + } + } catch (error) { + console.log(error); + } + } useEffect(()=>{ const params = { @@ -84,6 +106,13 @@ const Page = () => { search(params) }, [searchVal]) + useEffect(() => { + if (searchChartVal) { + getStaData(searchChartVal) + } + + }, [searchChartVal]) + return ( <> @@ -96,8 +125,8 @@ const Page = () => {
本年培训期数 计划/实际 - 26 期/ - 26 期 + { staData?.numberOfPeriods2 ?? 1} 期/ + { staData?.numberOfPeriods1 ?? 1} 期
@@ -106,15 +135,15 @@ const Page = () => {
本年培训期数 计划/实际 - 26 人次/ - 26 人次 + { staData?.personNum2 ?? 1} 人次/ + { staData?.personNum1 ?? 1} 人次
diff --git a/src/views/sz/pxjlgl/options.js b/src/views/sz/pxjlgl/options.js index a4b226671..a87590454 100644 --- a/src/views/sz/pxjlgl/options.js +++ b/src/views/sz/pxjlgl/options.js @@ -1,11 +1,25 @@ -export default function options() { - var dataGDP = [900, 500, 1632.33, 1100, 400] - var dataGrowth = [2, 2.1, 3, 2.5, 2.1] - var xAxisData = ['2019年', '2020年', '2021年', '2022年', '2023年'] +export default function options(data={}) { + const xAxisData = data?.list?.map(item => item.month + "月") + const maxCount = data?.list ? Math.ceil(Math.max(...data?.list?.map(obj => [obj.num1,obj.num2]).flat())) : 0 + const minCount = data?.list ? Math.floor(Math.min(...data?.list?.map(obj => [obj.num1, obj.num2]).flat())) : 100 + + const maxRate = data?.list ? Math.ceil(Math.max(...data?.list?.map(obj => obj.rate))) : 0 + const minRate = data?.list ? Math.floor(Math.min(...data?.list?.map(obj => obj.rate))) : 100 return { animation: true, tooltip: { trigger: 'axis', + formatter: function (params) { + var tooltipText = params[0].name + '
'; + params.forEach(function (item) { + if (item.seriesName === '完成率') { + tooltipText += item.marker + ' ' + item.seriesName + ': ' + item.value.toFixed(2) + '%
'; + } else { + tooltipText += item.marker + ' ' + item.seriesName + ': ' + item.value + '
'; + } + }); + return tooltipText; + } }, grid: { top: '15%', @@ -32,13 +46,15 @@ export default function options() { axisLabel: { show: true, margin: 14, - + // formatter: '{value}月' } }, yAxis: [ { type: 'value', offset: 10, + min: minCount, + max: maxCount, axisTick: { show: false }, @@ -55,6 +71,9 @@ export default function options() { { type: 'value', name: '(%)', + + min: minRate, + max: maxRate, offset: 10, nameTextStyle: { color: 'rgba(255,255,255,0.5)', @@ -71,7 +90,6 @@ export default function options() { fontSize: 18, formatter: '{value}%' } - } ], series: [ @@ -79,7 +97,7 @@ export default function options() { name: '计划期数', type: 'bar', barWidth: 25, - data: dataGDP, + data: data?.list?.map(item =>item.num2), itemStyle:{ color:"#6295fa" } @@ -88,7 +106,7 @@ export default function options() { name: '实际期数', type: 'bar', barWidth: 25, - data: dataGDP, + data: data?.list?.map(item =>item.num1), itemStyle:{ color:"#62daab" } @@ -110,7 +128,7 @@ export default function options() { borderColor: '#5d7092', borderWidth: 2 }, - data: dataGrowth, + data: data?.list?.map(item => item.rate), } ] } diff --git a/src/views/sz/pxjlgl/toolbar.js b/src/views/sz/pxjlgl/toolbar.js index 527e78831..9734131fb 100644 --- a/src/views/sz/pxjlgl/toolbar.js +++ b/src/views/sz/pxjlgl/toolbar.js @@ -36,12 +36,12 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil let dateSo; if (values.tm) { dateSo = { - start: moment(values.tm[0]).format('YYYY'), - end: moment(values.tm[1]).format('YYYY') + stm: moment(values.tm[0]).format('YYYY'), + etm: moment(values.tm[1]).format('YYYY') } } delete values.tm - setSearchVal({...values, dateSo}); + setSearchVal({...values, ...dateSo}); } return ( @@ -57,13 +57,13 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFil format={"YYYY-MM-DD"} /> - + - + - + {searchBtn ? diff --git a/src/views/sz/zrrgl/form.js b/src/views/sz/zrrgl/form.js index 538fd2903..abb996f04 100644 --- a/src/views/sz/zrrgl/form.js +++ b/src/views/sz/zrrgl/form.js @@ -27,13 +27,12 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => { }, ] const onFinish = (values) => { - if (mode === 'edit') { values.id = record.id - onEdit(apiurl.fxzb.sxfd.fxtj.edit, values) + onEdit(apiurl.zrrgl.edit, values) } if (mode === 'save') { - onSave(apiurl.fxzb.sxfd.fxtj.save, values) + onSave(apiurl.zrrgl.save, values) } } @@ -45,7 +44,7 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => {
@@ -54,7 +53,7 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => { @@ -65,7 +64,7 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => { @@ -73,7 +72,7 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => { @@ -83,7 +82,7 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => { @@ -92,8 +91,8 @@ const ModalForm = ({ mode, record, onEdit, onSave }) => { { const columns = [ { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" }, { - title: '责任类型', key: 'title', dataIndex: 'title', width: 200, + title: '责任类型', key: 'type', dataIndex: 'type', width: 200, render: (value) => {types[value]} }, - { title: '姓名', key: 'period', dataIndex: 'period', width: 140 }, - { title: '单位', key: 'org', dataIndex: 'org', width: 200}, - { title: '职务', key: 'tmPred', dataIndex: 'tmPred', width: 150, }, - { title: '联系方式', key: 'tmRecv', dataIndex: 'tmRecv', width: 150, }, - { title: '主要职责', key: 'tmRecv', dataIndex: 'tmRecv', width: 250,ellipsis: true}, + { title: '姓名', key: 'name', dataIndex: 'name', width: 140 }, + { title: '单位', key: 'unit', dataIndex: 'unit', width: 200}, + { title: '职务', key: 'duty', dataIndex: 'duty', width: 150, }, + { title: '联系方式', key: 'contactInfo', dataIndex: 'contactInfo', width: 150, }, + { title: '主要职责', key: 'dutyBound', dataIndex: 'dutyBound', width: 250,ellipsis: true}, { title: '操作', key: 'operation', width: 150, fixed: 'right',align: 'center', render: (value, row, index) => ( () => command(cmd)(row)} />) @@ -48,19 +48,17 @@ const Page = () => { } else if (type === 'view') { refModal.current.showView(params); } else if (type === 'del') { - refModal.current.onDeleteGet(apiurl.fxzb.sxfd.fxtj.del + params.id); + refModal.current.onDeleteGet(apiurl.zrrgl.delete + `/${params.id}`); } } - const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.hsyb.skhs.page).find_noCode); + const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.zrrgl.page).find_noCode); useEffect(() => { if (searchVal) { const params = { search: { - title: searchVal.title || undefined, - dateTimeRangeSo: searchVal.dateTimeRangeSo || undefined, - tp:2 + ...searchVal } }; console.log(searchVal); @@ -85,7 +83,7 @@ const Page = () => { ref={refModal} title="" component={ModalForm} - // onCrudSuccess={() => { refresh({ addvcd: localStorage.getItem('ADCD6') }) }} + onCrudSuccess={refresh} /> diff --git a/src/views/sz/zrrgl/toolbar.js b/src/views/sz/zrrgl/toolbar.js index 974f02bba..70a1bd1c0 100644 --- a/src/views/sz/zrrgl/toolbar.js +++ b/src/views/sz/zrrgl/toolbar.js @@ -48,13 +48,13 @@ const ToolBar = ({ setSearchVal, onSave }) => { <>
- + - + - + From 35f59e0f4b233de4617b06b0d08e8e232c4329df Mon Sep 17 00:00:00 2001 From: qzc Date: Thu, 26 Sep 2024 17:48:01 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E9=97=B8=E9=97=A8=E7=9B=91=E6=8E=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 5 +- src/models/auth/_.ts | 3 + src/service/apiurl.js | 8 + src/utils/utils.ts | 14 ++ src/views/AppRouters.tsx | 2 + src/views/rcgl/zmjk/ColorPolygon.tsx | 38 +++ src/views/rcgl/zmjk/Sider.tsx | 46 ++++ src/views/rcgl/zmjk/Topper1.tsx | 105 ++++++++ src/views/rcgl/zmjk/Topper2.tsx | 29 +++ src/views/rcgl/zmjk/Window.tsx | 104 ++++++++ src/views/rcgl/zmjk/ZmColumn.tsx | 119 +++++++++ src/views/rcgl/zmjk/ZmColumns.tsx | 35 +++ src/views/rcgl/zmjk/ZmDec.tsx | 60 +++++ src/views/rcgl/zmjk/consts.ts | 16 ++ src/views/rcgl/zmjk/coordinates.ts | 180 ++++++++++++++ src/views/rcgl/zmjk/index.js | 350 +++++++++++++++++++++++++++ src/views/rcgl/zmjk/index.less | 92 +++++++ src/views/rcgl/zmjk/useLinearAnim.ts | 54 +++++ 18 files changed, 1259 insertions(+), 1 deletion(-) create mode 100644 src/views/rcgl/zmjk/ColorPolygon.tsx create mode 100644 src/views/rcgl/zmjk/Sider.tsx create mode 100644 src/views/rcgl/zmjk/Topper1.tsx create mode 100644 src/views/rcgl/zmjk/Topper2.tsx create mode 100644 src/views/rcgl/zmjk/Window.tsx create mode 100644 src/views/rcgl/zmjk/ZmColumn.tsx create mode 100644 src/views/rcgl/zmjk/ZmColumns.tsx create mode 100644 src/views/rcgl/zmjk/ZmDec.tsx create mode 100644 src/views/rcgl/zmjk/consts.ts create mode 100644 src/views/rcgl/zmjk/coordinates.ts create mode 100644 src/views/rcgl/zmjk/index.js create mode 100644 src/views/rcgl/zmjk/index.less create mode 100644 src/views/rcgl/zmjk/useLinearAnim.ts diff --git a/package.json b/package.json index d75c597ca..a7212e46d 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,10 @@ "react-router-dom": "^6.3.0", "react-scripts": "5.0.1", "redux": "^4.2.0", - "typescript": "^4.7.4" + "typescript": "^4.7.4", + "konva": "^8.3.14", + "react-konva": "^18.2.3" + }, "scripts": { "start": "craco start", diff --git a/src/models/auth/_.ts b/src/models/auth/_.ts index 609546689..9a8325aea 100644 --- a/src/models/auth/_.ts +++ b/src/models/auth/_.ts @@ -302,6 +302,9 @@ export async function loadMenu(): Promise { { id: id(), title: '防治宣传', path: '/mgr/sg/byfz/byxc' }, ] }, + { + id: id(), title: '闸门监控', path: '/mgr/sg/zmjk', + }, { id: id(), title: '维修养护', path: '/mgr/sg/wxyh', }, diff --git a/src/service/apiurl.js b/src/service/apiurl.js index 828072064..9ccad6448 100644 --- a/src/service/apiurl.js +++ b/src/service/apiurl.js @@ -24,6 +24,14 @@ const apiurl = { role: service_xyt + '/system/menu/list' }, + //闸门监控 + zmjk: { + getList : service_xyt + '/attGateB/list', + getInformation: service_xyt + '/attGateB/data', + getDamData: service_xyt + '/gatePore/listByStcd', + getVideo: service_xyt + '/gateValveCctvRel/list' + }, + // 基本情况 home: { yq: service_fxdd + '/real/rain/list',//'/stStbprpB/rainfallStationDetails/rainfallList',//雨情 diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 90b8d4b42..90d5b11bd 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -10,6 +10,20 @@ export function changeObjectStringToMoment(obj: { [key: string]: any }, fields: return ret; } +export function apertureMeter(val?: any): number | undefined { + if (typeof val !== 'number') { + return undefined + } + return val / 1000; +} + +export function renAperture(val?: any) { + if (typeof val !== 'number') { + return '-' + } + + return (val / 1000).toFixed(3); +} export async function base64FromFile(file: File): Promise { return new Promise((resolve) => { diff --git a/src/views/AppRouters.tsx b/src/views/AppRouters.tsx index 637da7a11..bf2affc0f 100644 --- a/src/views/AppRouters.tsx +++ b/src/views/AppRouters.tsx @@ -48,6 +48,7 @@ import Xjxpz from "./rcgl/xcxj/xjxpz" import Fzxc from "./rcgl/byfz/fzxc" import Bypc from "./rcgl/byfz/bypc" +import Zmjk from "./rcgl/zmjk" import Wxyh from "./rcgl/wxyh" import Szzb from "./rcgl/szzb" import Stlljc from "./rcgl/stlljc" @@ -191,6 +192,7 @@ const AppRouters: React.FC = () => { { path: 'sg/xcxj/xjxpz', element: }, { path: 'sg/byfz/byxc', element: }, { path: 'sg/byfz/bypc', element: }, + { path: 'sg/zmjk', element: }, { path: 'sg/wxyh', element: }, { path: 'sg/aqgl/aqjcgl', element: }, { path: 'sg/aqgl/fxgkqd', element: }, diff --git a/src/views/rcgl/zmjk/ColorPolygon.tsx b/src/views/rcgl/zmjk/ColorPolygon.tsx new file mode 100644 index 000000000..815144ca4 --- /dev/null +++ b/src/views/rcgl/zmjk/ColorPolygon.tsx @@ -0,0 +1,38 @@ +import React from 'react' +import { Shape } from 'react-konva'; + +const ColorPolygon: React.FC<{ + pts: ({ x?: number, y?: number } | [number, number])[] + fill: string; + desc?: string; + opacity?: number; +}> = ({ pts, fill, opacity }) => { + return ( + { + context.beginPath(); + pts.forEach((p, i) => { + let x:any, y:any; + if (Array.isArray(p)) { + x = p[0]; + y = p[1]; + } else { + x = p.x; + y = p.y; + } + if (i === 0) { + context.moveTo(x, y); + } else { + context.lineTo(x, y); + } + }) + context.closePath(); + context.fillStrokeShape(shape) + }} + /> + ) +} + +export default ColorPolygon \ No newline at end of file diff --git a/src/views/rcgl/zmjk/Sider.tsx b/src/views/rcgl/zmjk/Sider.tsx new file mode 100644 index 000000000..c443cbd9a --- /dev/null +++ b/src/views/rcgl/zmjk/Sider.tsx @@ -0,0 +1,46 @@ +import React from 'react'; +import { Layer, Rect } from 'react-konva'; +import ColorPolygon from './ColorPolygon'; +import { CanvasH, CanvasW, FarBuildingTop, Horizontal, RoofTop, SideRoomSize } from './consts'; +import { ControlPts } from './coordinates'; +import { RoomWindows } from './Window'; + +const Sider: React.FC<{ + pts: ControlPts; + side: 'left' | 'right'; +}> = ({ side, pts }) => { + + return ( + + + + + + + + + + + + + + + + + + + + + ) +} + +export default React.memo(Sider) \ No newline at end of file diff --git a/src/views/rcgl/zmjk/Topper1.tsx b/src/views/rcgl/zmjk/Topper1.tsx new file mode 100644 index 000000000..4a4f291e6 --- /dev/null +++ b/src/views/rcgl/zmjk/Topper1.tsx @@ -0,0 +1,105 @@ +import React, { useMemo } from 'react'; +import { Layer, Rect } from 'react-konva'; +import ColorPolygon from './ColorPolygon'; +import { Window1, WindowSep } from './Window'; +import { TopRoomHeight } from './consts'; +import { ControlPts, mirror } from './coordinates'; + + +const Topper1: React.FC<{ + pts: ControlPts; + type: number; +}> = ({ pts, type }) => { + + const windows = useMemo<{ + w: number[][]; + h: number[][]; + }>(() => { + const x1 = pts.TopRectLB.x; + const y0 = pts.TopRectLB.y - TopRoomHeight + const y1 = pts.TopRectLB.y - TopRoomHeight * 0.75; + const x2 = pts.TopRectRB.x; + const y2 = pts.TopRectLB.y - TopRoomHeight * 0.25; + if (type === 1) { + const u = (x2 - x1) / 10; + return { + w: [ + [x1 + u, y1, x1 + 3 * u, y2], + [x1 + 4 * u, y1, x1 + 6 * u, y2], + [x1 + 7 * u, y1, x1 + 9 * u, y2], + ], + h: [] + } + } else if (type === 2) { + const u = (x2 - x1 - 8) / 14; + return { + w: [ + [x1 + u, y1, x1 + 3 * u, y2], + [x1 + 4 * u, y1, x1 + 6 * u, y2], + [x1 + 8 * u + 8, y1, x1 + 10 * u + 8, y2], + [x1 + 11 * u + 8, y1, x1 + 13 * u + 8, y2], + ], + h: [ + [x1 + 7 * u, y0, x1 + 7 * u + 8, pts.TopRectLB.y], + ], + } + } else if (type === 3) { + const xc = (x2 - x1) * 0.5; + const u = (xc - 8) / 8; + return { + w: [ + [x1 + u, y1, x1 + 3 * u, y2], + [x1 + 5 * u + 8, y1, x1 + 7 * u + 8, y2], + [x1 + u + xc, y1, x1 + 3 * u + xc, y2], + [x1 + 5 * u + 8 + xc, y1, x1 + 7 * u + 8 + xc, y2], + ], + h: [ + [x1 + 4 * u, y0, x1 + 4 * u + 8, pts.TopRectLB.y], + [x1 + 4 * u + xc, y0, x1 + 4 * u + 8 + xc, pts.TopRectLB.y], + ] + } + } else if (type > 3) { + const xc1 = (x2 - x1) / 3; + const xc2 = xc1 * 2; + const u = (xc1 - 8) / 8; + return { + w: [ + [x1 + u, y1, x1 + 3 * u, y2], + [x1 + 5 * u + 8, y1, x1 + 7 * u + 8, y2], + [x1 + u + xc1, y1, x1 + 3 * u + xc1, y2], + [x1 + 5 * u + 8 + xc1, y1, x1 + 7 * u + 8 + xc1, y2], + [x1 + u + xc2, y1, x1 + 3 * u + xc2, y2], + [x1 + 5 * u + 8 + xc2, y1, x1 + 7 * u + 8 + xc2, y2], + ], + h: [ + [x1 + 4 * u, y0, x1 + 4 * u + 8, pts.TopRectLB.y], + [x1 + 4 * u + xc1, y0, x1 + 4 * u + 8 + xc1, pts.TopRectLB.y], + [x1 + 4 * u + xc2, y0, x1 + 4 * u + 8 + xc2, pts.TopRectLB.y], + ] + } + } + return { + w: [], h: [] + } + }, []) + + return ( + + + + { + pts.SepsLTLBRBRT.map((s, index) => ( + + )) + } + { + windows.w.map((o, index) => ) + } + { + windows.h.map((o, index) => ) + } + + ) +} + +export default React.memo(Topper1); \ No newline at end of file diff --git a/src/views/rcgl/zmjk/Topper2.tsx b/src/views/rcgl/zmjk/Topper2.tsx new file mode 100644 index 000000000..cb393f13c --- /dev/null +++ b/src/views/rcgl/zmjk/Topper2.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Layer, Rect } from 'react-konva'; +import ColorPolygon from './ColorPolygon'; +import { CanvasH, CanvasW, ViewCenter, WaterTop } from './consts'; +import { ControlPts, interpolate, intersection, mirror } from './coordinates'; + + +const Topper2: React.FC<{ + pts: ControlPts; + waterRatio: number; +}> = ({ pts, waterRatio }) => { + + const waterP1 = interpolate(pts.B1, { x: pts.L1.x, y: WaterTop }, waterRatio); + const waterP2 = intersection(waterP1, ViewCenter, { x: 0, y: undefined }); + + return ( + + { + pts.SepsFront.map((s, index) => ( + + )) + } + + + + ) +} + +export default React.memo(Topper2); \ No newline at end of file diff --git a/src/views/rcgl/zmjk/Window.tsx b/src/views/rcgl/zmjk/Window.tsx new file mode 100644 index 000000000..550ed8c7e --- /dev/null +++ b/src/views/rcgl/zmjk/Window.tsx @@ -0,0 +1,104 @@ +import React from 'react' +import { Line, Rect } from 'react-konva'; +import ColorPolygon from './ColorPolygon'; + +const S1 = 4; + +export const Window1: React.FC<{ + rect: number[]; +}> = ({ rect }) => { + const [x1, y1, x2, y2] = rect; + + const w1 = (x2 - x1 - S1) / 2; + const w2 = (x2 - x1 - S1 * 2) / 3; + + return ( + <> + + + + + + + + ) +} + +export const WindowSep: React.FC<{ + rect: number[]; +}> = ({ rect }) => { + const [x1, y1, x2, y2] = rect; + + return ( + + ) +} + +export const RoomWindows: React.FC<{ + rect: number[]; +}> = ({ rect }) => { + const [x1, y1, x2, y2] = rect; + + const u = (x2 - x1) / 10; + const v = (y2 - y1) / 6; + + const c1 = x1 - 10 + 1; + const c2 = x1 - 10 + 7 * u; + const dc = (c2 - c1) / 10; + + return ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(i => ( + + )) + } + + + + ) +} \ No newline at end of file diff --git a/src/views/rcgl/zmjk/ZmColumn.tsx b/src/views/rcgl/zmjk/ZmColumn.tsx new file mode 100644 index 000000000..81aa78024 --- /dev/null +++ b/src/views/rcgl/zmjk/ZmColumn.tsx @@ -0,0 +1,119 @@ +import React from 'react' +import { Circle, Layer, Line, Rect } from 'react-konva'; +import ColorPolygon from './ColorPolygon'; +import { ViewCenter, WaterTop } from './consts'; +import { ControlPts, interpolate, intersection } from './coordinates'; +import ZmDec from './ZmDec'; +import { useLinearAnim } from './useLinearAnim'; + +const ZmColumn: React.FC<{ + kdMax: number; + gtophgt?: number; + idx: number; + pts: ControlPts; + waterRatio: number; + selected: boolean; +}> = ({ kdMax, gtophgt, idx, pts, waterRatio, selected }) => { + + const renKd = gtophgt; //useLinearAnim(gtophgt); + + const a = pts.ZmArea[idx]; + if (!a || typeof renKd !== 'number') { + return null; + } + + const hh1 = (a.lb1.y - a.lt1.y) * 0.5; + const hh2 = (a.lb2.y - a.lt2.y) * 0.5; + + const ratio = renKd / kdMax; + const e1 = hh1 * ratio * 0.8; + const e2 = hh2 * ratio * 0.8; + + const lineLineLeft = { x: (a.lt1.x + a.lt2.x) * 0.5, y: (a.lt1.y + a.lt2.y) * 0.5 }; + const lineLineRight = { x: (a.rt1.x + a.rt2.x) * 0.5, y: (a.rt1.y + a.rt2.y) * 0.5 }; + const line1 = interpolate(lineLineLeft, lineLineRight, 0.25); + const line2 = interpolate(lineLineLeft, lineLineRight, 0.75); + + const ty1 = a.lt1.y + hh1 - e1; + const ty2 = a.lt2.y + hh2 - e2; + const joiny = (ty1 + ty2) * 0.5; + + const waterP1 = interpolate(a.lb0, { x: a.lb0.x, y: WaterTop }, waterRatio); + const waterP1R = { x: a.rb0.x, y: waterP1.y }; + const waterP2 = intersection(ViewCenter, waterP1, { x: a.lb1.x, y: undefined }); + const waterP2R = { x: a.rb1.x, y: waterP2.y }; + const waterP3 = intersection(ViewCenter, waterP1, { x: a.lb3.x, y: undefined }); + waterP3.y -= 26; + const waterP3R = { x: a.rb3.x, y: waterP3.y }; + if (waterP3.x < waterP2.x) { + waterP3.x = waterP2.x; + } + if (waterP3R.x > waterP2R.x) { + waterP3R.x = waterP2R.x + } + + // + const b1 = { x: a.lb0.x, y: a.lb0.y - 32 }; + const b6 = { x: a.rb0.x, y: a.rb0.y - 32 }; + const b2 = interpolate(b1, b6, 0.4); + const b5 = interpolate(b1, b6, 0.6); + const b3 = { x: b2.x, y: b2.y + 12 }; + const b4 = { x: b5.x, y: b5.y + 12 }; + + const b1_1 = intersection(b1, ViewCenter, { x: a.lb1.x, y: undefined }); + const b1_6 = intersection(b6, ViewCenter, { x: a.rb1.x, y: undefined }); + const b1_2 = intersection(b2, ViewCenter, { x: undefined, y: b1_1.y }); + const b1_5 = intersection(b5, ViewCenter, { x: undefined, y: b1_6.y }); + const b1_3 = intersection(b3, ViewCenter, { x: b1_2.x, y: undefined }); + const b1_4 = intersection(b4, ViewCenter, { x: b1_5.x, y: undefined }); + + return ( + <> + { + waterP3 && waterP3R ? ( + + ) : null + } + + + + + + + + + + + + + + + + + + + + { + waterP1.y < b1.y ? ( + + ) : null + } + + + ) +} + +export default React.memo(ZmColumn) \ No newline at end of file diff --git a/src/views/rcgl/zmjk/ZmColumns.tsx b/src/views/rcgl/zmjk/ZmColumns.tsx new file mode 100644 index 000000000..b3b4f8ef7 --- /dev/null +++ b/src/views/rcgl/zmjk/ZmColumns.tsx @@ -0,0 +1,35 @@ +import React, { useMemo } from 'react' +import { Layer } from 'react-konva'; +import { ControlPts } from './coordinates'; +import ZmColumn from './ZmColumn'; +// import { StationItem, GateRuntime } from '../../../models/_/defs'; +import { apertureMeter } from '../../../utils/utils'; + +const ZmColumns: React.FC<{ + zmobj: any; + runtime: any; + pts: ControlPts; + selectedId?: string; + waterRatio: number; +}> = ({ zmobj, runtime, pts, waterRatio }) => { + const eqpnoList = useMemo(() => new Array(runtime.length).fill(0).map((o, index) => index), [runtime]); + return ( + + { + eqpnoList.map((o, index) => ( + ) + ) + } + + ) +} + +export default ZmColumns \ No newline at end of file diff --git a/src/views/rcgl/zmjk/ZmDec.tsx b/src/views/rcgl/zmjk/ZmDec.tsx new file mode 100644 index 000000000..30f9f2681 --- /dev/null +++ b/src/views/rcgl/zmjk/ZmDec.tsx @@ -0,0 +1,60 @@ +import React from 'react' +import { Line, Rect } from 'react-konva'; +import { Horizontal, ViewCenter } from './consts'; +import { XY } from './coordinates' + +const INTERVALS = [0, 1, 2]; + +const ZmDec: React.FC<{ + tl: XY; + rb: XY; +}> = ({ tl, rb }) => { + + const ux = (rb.x - tl.x) / 12; + const uy = (rb.y - tl.y) / 12; + + const ox = tl.x + 3 * ux; + const oy = tl.y + 3 * uy; + + return ( + <> + { + INTERVALS.map(y => ( + + { + INTERVALS.map(x => { + const cx = ox + x * 3 * ux; + const cy = oy + y * 3 * uy; + const l = cx - ux; + const r = cx + ux; + const t = cy - uy; + const b = cy + uy; + return ( + + + { + cx < ViewCenter.x ? ( + + ) : ( + + ) + } + { + cy < Horizontal ? ( + + ) : ( + + ) + } + + ) + }) + } + + )) + } + + ) +} + +export default ZmDec \ No newline at end of file diff --git a/src/views/rcgl/zmjk/consts.ts b/src/views/rcgl/zmjk/consts.ts new file mode 100644 index 000000000..1a9147e3d --- /dev/null +++ b/src/views/rcgl/zmjk/consts.ts @@ -0,0 +1,16 @@ +export const CanvasW = 1080; +export const CanvasH = 640; + +export const Horizontal = CanvasH * 1.4 / 3; +export const ViewCenter = { x: CanvasW * 0.5, y: Horizontal }; + +export const GroundBase = CanvasH * 1.8 / 3; +export const BottomBase = CanvasH * 2.5 / 3; +export const RoofTop = CanvasH * 0.8 / 3; +export const RoofTopFar = RoofTop + 32; +export const FarBuildingTop = RoofTop - 16; + +export const SideRoomSize = CanvasH * 0.7 / 3; +export const TopRoomHeight = SideRoomSize - 24; +export const PillarRatio = 0.2; +export const WaterTop = GroundBase; diff --git a/src/views/rcgl/zmjk/coordinates.ts b/src/views/rcgl/zmjk/coordinates.ts new file mode 100644 index 000000000..93bff7e08 --- /dev/null +++ b/src/views/rcgl/zmjk/coordinates.ts @@ -0,0 +1,180 @@ +import { BottomBase, CanvasW, GroundBase, PillarRatio, RoofTop, RoofTopFar, SideRoomSize, ViewCenter } from "./consts"; + +export type XY = { + x: number; + y: number; +} + +export type XYWH = { + x: number; + y: number; + w: number; + h: number; +} + +export function intersection(pt1: XY, pt2: XY, result: { x?: number, y?: number }): XY { + const invalid: XY = { x: result.x || 0, y: result.y || 0 }; + if (typeof result.x === typeof result.y) { + return invalid; + } + + const x1 = pt1.x, y1 = pt1.y, x2 = pt2.x, y2 = pt2.y; + + if (typeof result.x === 'number') { + const x3 = result.x; + + if (x2 === x1) { + return invalid; + } + + result.y = (y2 - y1) * (x3 - x1) / (x2 - x1) + y1; + } else { + const y3 = result.y!; + + if (y2 === y1) { + return invalid; + } + + result.x = (x2 - x1) * (y3 - y1) / (y2 - y1) + x1; + } + + return result as any; +} + +export function interpolate(pt1: XY, pt2: XY, ratio: number): XY { + return { + x: pt1.x + (pt2.x - pt1.x) * ratio, + y: pt1.y + (pt2.y - pt1.y) * ratio, + } +} + +export function mirror(pt: XY): XY { + return { + x: CanvasW - pt.x, + y: pt.y, + } +} + +export type ControlPts = { + C1: XY; + L1: XY; + B1: XY; + C2: XY; + L2: XY; + B2: XY; + A1: XY; + A2: XY; + B3: XY; + RoomLT: XY; + RoomRT: XY; + RoomRB: XY; + RoomLB: XY; + RoomRTFar: XY; + RoomRBFar: XY; + RoomLBFar: XY; + TopRectLB: XY; + TopRectRB: XY; + SepsLTLBRBRT: XY[][]; + SepsFront: XYWH[]; + ZmArea: { + lt0: XY; lt1: XY; lt2: XY; lt3: XY; + lb0: XY; lb1: XY; lb2: XY; lb3: XY; + rt0: XY; rt1: XY; rt2: XY; rt3: XY; + rb0: XY; rb1: XY; rb2: XY; rb3: XY; + + }[]; +} + + + + +export function contextCoordinates(unitWidth: number, hole: number): ControlPts { + const C1 = { x: unitWidth * 0.6, y: GroundBase }; + const L1 = { x: unitWidth, y: GroundBase }; + const B1 = { x: unitWidth, y: BottomBase } + + const C2 = intersection(ViewCenter, C1, { x: 0, y: undefined }); + const L2 = intersection(ViewCenter, L1, { x: 0, y: undefined }); + const B2 = intersection(ViewCenter, B1, { x: 0, y: undefined }); + + const A1 = { x: L1.x, y: RoofTop }; + const A2 = intersection(ViewCenter, A1, { x: undefined, y: RoofTopFar }); + + const B3 = intersection(ViewCenter, B2, { x: A2.x, y: undefined }) + + const RoomLT = { x: (C1.x + L1.x) * 0.5 - SideRoomSize * 0.5, y: RoofTop - SideRoomSize } + const RoomRT = { x: (C1.x + L1.x) * 0.5 + SideRoomSize * 0.5, y: RoofTop - SideRoomSize } + const RoomRB = { x: (C1.x + L1.x) * 0.5 + SideRoomSize * 0.5, y: RoofTop } + const RoomLB = { x: (C1.x + L1.x) * 0.5 - SideRoomSize * 0.5, y: RoofTop } + const RoomRBFar = intersection(ViewCenter, RoomRB, { x: undefined, y: RoofTopFar }); + const RoomRTFar = intersection(ViewCenter, RoomRT, { x: RoomRBFar.x, y: undefined }); + const RoomLBFar = { x: RoomRBFar.x! - SideRoomSize, y: RoomRBFar.y }; + + + const TopRectLB = interpolate(RoomRB, RoomRBFar, 0.05); + const TopRectRB = mirror(TopRectLB); + + const TopHoleLT = intersection(A1, ViewCenter, { x: undefined, y: TopRectLB.y }); + const TopHoleRT = mirror(TopHoleLT); + const HolesWidth = TopHoleRT.x - TopHoleLT.x; + const PillarWidth = (HolesWidth / hole) * PillarRatio; + const HoleWidth = (HolesWidth - PillarWidth * (hole - 1)) / hole; + + const SepsLTLBRBRT: XY[][] = []; + const SepsFront: XYWH[] = []; + const ZmArea = []; + for (let i = 0; i < hole; i++) { + const TopBase = TopHoleLT.y; + // 隔断 + if (i > 0) { + const frontRight = TopHoleLT.x + (PillarWidth + HoleWidth) * i; + const frontLeft = frontRight - PillarWidth; + SepsFront.push({ x: frontLeft, y: TopBase, w: PillarWidth, h: BottomBase - TopBase }); + if (i < hole / 2) { + // 右侧面 + const p1 = { x: frontRight, y: TopBase }; + const p2 = { x: frontRight, y: BottomBase }; + const p4 = intersection(p1, ViewCenter, { x: undefined, y: RoofTopFar }); + const p3 = intersection(p2, ViewCenter, { x: p4.x, y: undefined }); + SepsLTLBRBRT.push([p1, p2, p3, p4]); + } else if (i > hole / 2) { + // 左侧面 + const p1 = { x: frontLeft, y: TopBase }; + const p2 = { x: frontLeft, y: BottomBase }; + const p4 = intersection(p1, ViewCenter, { x: undefined, y: RoofTopFar }); + const p3 = intersection(p2, ViewCenter, { x: p4.x, y: undefined }); + SepsLTLBRBRT.push([p1, p2, p3, p4]); + } + } + + // 闸门面 + { + const ZmTopBaseFront = TopBase + 6; + const ZmTopBaseBack = ZmTopBaseFront + 10; + const lt0 = { x: TopHoleLT.x + (PillarWidth + HoleWidth) * i, y: TopBase }; + const lb0 = { x: lt0.x, y: BottomBase }; + const rb0 = { x: lt0.x + HoleWidth, y: BottomBase }; + const lt1 = intersection(ViewCenter, lt0, { x: undefined, y: ZmTopBaseFront }); + const lt2 = intersection(ViewCenter, lt0, { x: undefined, y: ZmTopBaseBack }); + const lt3 = intersection(ViewCenter, lt0, { x: undefined, y: RoofTopFar }); + const lb1 = intersection(ViewCenter, lb0, { x: lt1.x, y: undefined }); + const lb2 = intersection(ViewCenter, lb0, { x: lt2.x, y: undefined }); + const lb3 = intersection(ViewCenter, lb0, { x: lt3.x, y: undefined }); + const rb1 = intersection(ViewCenter, rb0, { x: undefined, y: lb1.y }); + const rb2 = intersection(ViewCenter, rb0, { x: undefined, y: lb2.y }); + const rb3 = intersection(ViewCenter, rb0, { x: undefined, y: lb3.y }); + const rt0 = { x: rb0.x, y: lt0.y }; + const rt1 = { x: rb1.x, y: lt1.y }; + const rt2 = { x: rb2.x, y: lt2.y }; + const rt3 = { x: rb3.x, y: lt3.y }; + ZmArea.push({ lt0, lb0, rb0, rt0, lt1, rt1, lb1, rb1, lt2, lb2, rt2, rb2, lt3, lb3, rt3, rb3 }); + } + } + + return { + C1, L1, B1, C2, L2, B2, A1, A2, B3, + RoomLT, RoomRT, RoomRB, RoomLB, RoomRTFar, RoomRBFar, RoomLBFar, + TopRectLB, TopRectRB, + SepsLTLBRBRT, SepsFront, ZmArea, + } +} \ No newline at end of file diff --git a/src/views/rcgl/zmjk/index.js b/src/views/rcgl/zmjk/index.js new file mode 100644 index 000000000..4d6415b9c --- /dev/null +++ b/src/views/rcgl/zmjk/index.js @@ -0,0 +1,350 @@ +import React, { useEffect, useMemo, useState } from 'react' +import { Stage } from 'react-konva'; +import Sider from './Sider'; +import Topper1 from './Topper1'; +import Topper2 from './Topper2'; +import ZmColumns from './ZmColumns'; +import { contextCoordinates } from './coordinates'; +import { renAperture } from '../../../utils/utils'; +import HFivePlayer from '../../../components/video1Plary' +import './index.less'; +import { httpget, httpget2, httppost2 } from '../../../utils/request'; +import apiurl from '../../../service/apiurl'; +const CanvasW = 1080 +const CanvasH = 640 +const waterRatio = 0 +const zmobj ={ + "hpCode": "HP0074208040002120", + "stcd": "4265630075", + "ctrlType": "PLC", + "ctrlProtocol": "PLC", + "uprzStcd": null, + "dwrzStcd": null, + "flowStcd": null, + "gaType": "waga", + "ctrlPass": null, + "maxHgt": 1.9, + "minHgt": 0, + "name": "五岭包节制闸", + "ghtX": null, + "ghtY": null, + "irrCode": "D00000020", + "irrName": "三干渠", + "engCode": "ENG100076", + "engName": "三干渠管理处", + "orgCode": "A07", + "gaorNum": 3, + "wagaType": "节制闸", + "plcType": null, + "bim": 0, + "vip": 0, + "miu": null, + "lgtd": 112.242945, + "lttd": 30.848166, + "runtime": [ + null, + { + "stcd": "4265630075", + "gateNumber": 1, + "realAperture": 376, + "setAperture": 0, + "sensorLever": null, + "altitudeLever": null, + "remoteSignal": 0, + "powerSignal": 0, + "openingSignal": 0, + "closeingSignal": 0, + "errorSignal": 0, + "openedSignal": 0, + "closedSignal": 0, + "tm": "2024-09-25 20:03:26", + "_online": true + }, + { + "stcd": "4265630075", + "gateNumber": 2, + "realAperture": 388, + "setAperture": 0, + "sensorLever": null, + "altitudeLever": null, + "remoteSignal": 0, + "powerSignal": 0, + "openingSignal": 0, + "closeingSignal": 0, + "errorSignal": 0, + "openedSignal": 0, + "closedSignal": 0, + "tm": "2024-09-25 20:03:26", + "_online": true + }, + { + "stcd": "4265630075", + "gateNumber": 3, + "realAperture": 394, + "setAperture": 0, + "sensorLever": null, + "altitudeLever": null, + "remoteSignal": 0, + "powerSignal": null, + "openingSignal": 0, + "closeingSignal": 0, + "errorSignal": 0, + "openedSignal": 0, + "closedSignal": 0, + "tm": "2024-09-25 20:03:26", + "_online": true + } + ], + "real": { + "stcd": "4265630075", + "stationName": "五岭包节制闸", + "z1": null, + "zz1": null, + "z1tm": null, + "z2": null, + "zz2": null, + "z2tm": null, + "hq": null, + "hqtm": null, + "demtl": null + }, + "cctvs": [], + "_idx": 88, + "_fav": false, + "_sort": 10086 +} + +const runtime = [ + null, + { + "stcd": "4265630075", + "gateNumber": 1, + "realAperture": 976, + "setAperture": 0, + "sensorLever": null, + "altitudeLever": null, + "remoteSignal": 0, + "powerSignal": 0, + "openingSignal": 0, + "closeingSignal": 0, + "errorSignal": 0, + "openedSignal": 0, + "closedSignal": 0, + "tm": "2024-09-25 20:03:31" + }, + { + "stcd": "4265630075", + "gateNumber": 2, + "realAperture": 388, + "setAperture": 0, + "sensorLever": null, + "altitudeLever": null, + "remoteSignal": 0, + "powerSignal": 0, + "openingSignal": 0, + "closeingSignal": 0, + "errorSignal": 0, + "openedSignal": 0, + "closedSignal": 0, + "tm": "2024-09-25 20:03:31" + }, + { + "stcd": "4265630075", + "gateNumber": 3, + "realAperture": 394, + "setAperture": 0, + "sensorLever": null, + "altitudeLever": null, + "remoteSignal": 0, + "powerSignal": null, + "openingSignal": 0, + "closeingSignal": 0, + "errorSignal": 0, + "openedSignal": 0, + "closedSignal": 0, + "tm": "2024-09-25 20:03:31" + } +] + +const myType = { + // 闸前水位站 2闸后水位站 3流量站 + '1':'闸前水位/水深(m)', + '2':'闸后水位/水深(m)', + '3':'流量 (m³/s)', +} + +const Page = () => { + const [itemIndex,setItemIndex] = useState(null) + const [data,setData] = useState({}) + const [list, setList ] = useState([]) + const [damList, setDamList ] = useState([]) + const [videoList, setVideoList ] = useState([]) + const [videoArr, setvideoArr] = useState({}) + + + const hole = 3;//zmobj.gaorNum; + const xunit = CanvasW / (2 + hole); + const pts = contextCoordinates(xunit, hole); + const eqpnoList = useMemo(() => damList ? new Array(damList.length).fill(0).map((o, index) => index) : [], [damList]); + + useEffect(()=>{ + getList() + },[]) + + const getList = async()=>{ + const {code, data} = await httppost2(apiurl.zmjk.getList) + if(code!==200){ + return + } + const obj = data[0]||{} + getInformation(obj.gateCode) + getDamData(obj.stcd) + getVideo(obj.gateCode) + setData(obj) + } + + const getInformation = async(gateCode)=>{ + const {code, data} = await httpget2(apiurl.zmjk.getInformation,{gateCode}) + if(code!==200){ + return + } + setList(data) + } + + const getDamData = async(stcd)=>{ + const {code, data} = await httpget2(apiurl.zmjk.getDamData,{stcd}) + if(code!==200){ + return + } + const list = [] + data.map((item)=>{ + list.push({ + ...item + // ,realAperture:item.realAperture*1000 + }) + }) + setDamList(list) + } + + const getVideo = async(valveCode)=>{ + const {code, data} = await httppost2(apiurl.zmjk.getVideo,{valveCode}) + if(code!==200){ + return + } + setVideoList(data) + } + + const getVideoSrc = async (current) => { + const res = await httpget2(`${apiurl.gsxl.zfzl.videosrc}${'32023a7f27d8448fa10511f24e96acff'}`) + if (res.code == 200 && res.data?.length !== 0) { + setvideoArr({src:res.data}) + }else{ + setvideoArr({}) + } + } + + + return ( + <> +
+
+ {/* + */} +
+ + + + + + + + +
+
+ { + eqpnoList.map(o => ( +
{}} + className='o' style={{ flexGrow: 1, width: 100, display: 'flex', justifyContent: 'center', cursor: 'pointer' }}> +
#{o+1}
+
+ )) + } +
+
+
+
+ { + eqpnoList.map(o => ( +
+
{}} + style={{ width: 80, height: 32, border: '1px solid #444', backgroundColor: '#fff', borderRadius: 4, color: '#888', display: 'flex', justifyContent: 'center', alignItems: 'center', fontSize: 18, cursor: 'pointer' }} + > + {renAperture(damList[o]?.realAperture)} +
+
+ )) + } +
+
+
+ +
+
视频监控
+
+
+ { + videoList.map((item,index)=>( +
{setItemIndex(index);getVideoSrc(item.indexCode)}}> + {item.name} +
+ )) + } +
+
+ { + videoArr?.src && +
{ + // if (controlerParams.type == 1) { + // setVideoOpen(true) + // setIsShow(!isShow) + // } + }} + > + + {/*
注:单击视频显示/隐藏云台
*/} +
+ } +
+
+
+
+
监测数据
+
+ { + list?.map((item)=>{ + return ( +
+
{myType[item.type]}
+
112.079 / 1.279
+
07-10 12:09:00
+
+ ) + }) + } +
+
+
》》查看更多信息
+
+
+
+
+ + ); +} + +export default Page; diff --git a/src/views/rcgl/zmjk/index.less b/src/views/rcgl/zmjk/index.less new file mode 100644 index 000000000..b97ba316a --- /dev/null +++ b/src/views/rcgl/zmjk/index.less @@ -0,0 +1,92 @@ +.sg_zmjk{ + .ant-card-body{ + display: flex; + height: 100%; + .sg_zmjk_left{ + top: 30px; + position: relative; + width: 1080px; + height: 640px; + transform: scale(0.9,1); + + } + .sg_zmjk_right{ + flex: 1; + // width: 40%; + height: 100%; + display: flex; + flex-direction: column; + + .sg_zmjk_right_video{ + height: 400px; + margin: 30px 20px 30px -30px; + border-radius: 5px; + border: 1px solid #bbb; + display: flex; + flex-direction: column; + .sg_zmjk_right_video_title{ + height: 35px; + line-height: 35px; + padding-left: 10px; + border-bottom: 1px solid #bbb; + } + .sg_zmjk_right_video_content{ + flex: 1; + display: flex; + width: 100%; + // height: 100%; + .sg_zmjk_right_video_content_left{ + overflow-y: auto; + overflow-x: hidden; + padding: 10px; + width: 130px; + height: 363px; + border-right: 1px solid #bbb; + cursor: pointer; + .sg_zmjk_right_video_content_left_item{ + width: 110px; + // height: 30px; + margin-bottom: 5px; + // line-height: 30px; + text-align: center; + border: 1px solid #bbb; + } + .itemChecked{ + background-color: #1890FF; + color: #ffffff; + } + } + .sg_zmjk_right_video_content_right{ + flex: 1; + height: 100%; + padding: 10px; + } + } + } + .sg_zmjk_right_information{ + height: 180px; + margin: -10px 20px 30px -30px; + border-radius: 5px; + border: 1px solid #bbb; + .sg_zmjk_right_information_title{ + height: 35px; + line-height: 35px; + padding-left: 10px; + border-bottom: 1px solid #bbb; + } + .sg_zmjk_right_information_content{ + display: flex; + padding: 2px 10px; + div{ + width: 33%; + margin-bottom: 10px; + } + } + } + .sg_zmjk_right_more{ + margin: -10px 20px 30px -30px; + cursor: pointer; + } + } + } +} \ No newline at end of file diff --git a/src/views/rcgl/zmjk/useLinearAnim.ts b/src/views/rcgl/zmjk/useLinearAnim.ts new file mode 100644 index 000000000..7fb7040a9 --- /dev/null +++ b/src/views/rcgl/zmjk/useLinearAnim.ts @@ -0,0 +1,54 @@ +import { useEffect, useReducer, useRef, useState } from "react"; + + +const DURATION = 900; +const CNT = 5; + +const INTERVAL = DURATION / CNT; + +export function useLinearAnim(val: number | undefined) { + + const ren = useRef(val); + + const [_, refresh] = useReducer(s => s + 1, 0); + + const alive = useRef(true); + + useEffect(() => { + return () => { + alive.current = false; + } + }, []) + + useEffect(() => { + if (typeof val !== 'number') { + return; + } + + if (ren.current == undefined) { + ren.current = val; + } + const len = val - ren.current; + + let handle: any = null; + if (len) { + const dv = len / CNT; + let cnt = CNT; + handle = setInterval(() => { + if (cnt > 0 && alive.current) { + cnt--; + ren.current! -= dv; + refresh(); + } + }, INTERVAL) + } + + return () => { + if (handle) { + clearInterval(handle); + } + } + }, [val]); + + return ren.current ?? val; +} \ No newline at end of file