feat():水情开发

lsf-dev
李神峰 2024-09-23 18:04:37 +08:00
parent 65449e77a2
commit 9b161f4012
19 changed files with 1288 additions and 52 deletions

View File

@ -38,9 +38,14 @@ export function CrudOpRender_icon({ command, edit, del, restore, add, view }) {
) )
} }
export function CrudOpRender_text({ command,picReview, edit,detail, dispatch,del, restore, add,similarAdd, view,zg, cjxgl,review,download }) { export function CrudOpRender_text({ command,picReview, edit,detail, dispatch,del, restore, add,similarAdd, view,zg, cjxgl,review,download,record }) {
return ( return (
<div style={{ display: 'inline' }}> <div style={{ display: 'inline' }}>
{
record ? (
<Button style={{ marginRight: 4 }} type="link" size="small" onClick={command('record')} title="培训记录">培训记录</Button>
) : null
}
{ {
add ? ( add ? (
<Button style={{ marginRight: 4 }} type="link" size="small" onClick={command('add')} title="增加">增加</Button> <Button style={{ marginRight: 4 }} type="link" size="small" onClick={command('add')} title="增加">增加</Button>
@ -113,6 +118,7 @@ export function CrudOpRender_text({ command,picReview, edit,detail, dispatch,del
</Popconfirm> </Popconfirm>
) : null ) : null
} }
</div> </div>
) )
} }

View File

@ -208,23 +208,14 @@ export async function loadMenu(): Promise<MenuItem[]> {
] ]
}, },
{ {
id: id(), title: '监督考核', redirect: '/mgr/sz/jdkh/khtj', id: id(), title: '培训管理', redirect: '/mgr/sz/pxgl/pxjhgl',
children: [ children: [
{ {
id: id(), title: '考核统计', path: '/mgr/sz/jdkh/khtj', id: id(), title: '培训计划管理', path: '/mgr/sz/pxgl/pxjhgl',
}, },
{ {
id: id(), title: '考核任务管理', path: '/mgr/sz/jdkh/khrwgl', id: id(), title: '培训记录管理', path: '/mgr/sz/pxgl/pxjlgl',
}, },
{
id: id(), title: '考核问题整改', path: '/mgr/sz/jdkh/khwtzg',
},
{
id: id(), title: '考核指标管理', path: '/mgr/sz/jdkh/khzbgl',
},
{
id: id(), title: '考核模板管理', path: '/mgr/sz/jdkh/khmbgl',
}
] ]
} }
] ]
@ -363,6 +354,15 @@ export async function loadMenu(): Promise<MenuItem[]> {
{ id: id(), title: '全周期档案', path: '/mgr/sq/qys/qzqda'}, { id: id(), title: '全周期档案', path: '/mgr/sq/qys/qzqda'},
] ]
}, },
{ id: id(), title: '全天候', redirect: '/mgr/sq/qth/sksq',
children: [
{ id: id(), title: '水库水情', path: '/mgr/sq/qth/sksq'},
{ id: id(), title: '河道水情', path: '/mgr/sq/qth/hdsq'},
{ id: id(), title: '实时雨情', path: '/mgr/sq/qth/ssyq'},
{ id: id(), title: '大坝安全监测', path: '/mgr/sq/qth/dbaqjc'},
{ id: id(), title: '视频监控', path: '/mgr/sq/qth/spjk'},
]
},
] ]
}, },

View File

@ -86,6 +86,9 @@ import Kqys from './sq/qys/kqys/index.js'
import Xyys from './sq/qys/xyys/index.js' import Xyys from './sq/qys/xyys/index.js'
import Gcys from './sq/qys/gcys/index.js' import Gcys from './sq/qys/gcys/index.js'
import Gcdsj from './sq/qzq/gcdsj' import Gcdsj from './sq/qzq/gcdsj'
import Sksq from './sq/qth/sksq'
import Hdsq from './sq/qth/hdsq'
import Ssyq from './sq/qth/ssyq'
// import Zcdjxx from './sq/qys/' // import Zcdjxx from './sq/qys/'
// import Zcdjxx from './sq/qfg/zcdjxx' // import Zcdjxx from './sq/qfg/zcdjxx'
@ -94,6 +97,7 @@ import Gcdsj from './sq/qzq/gcdsj'
// 四制 - 组织机构查看 // 四制 - 组织机构查看
import Zzjgck from './sz/zzjgck' import Zzjgck from './sz/zzjgck'
import Pxjhgl from './sz/pxjhgl'
const HomePage = lazy(() => import('./Home')) const HomePage = lazy(() => import('./Home'))
@ -147,6 +151,11 @@ const AppRouters: React.FC = () => {
// 工程安全监测 // 工程安全监测
{ path: 'sq/qth/dbaqjc', element: <Bzt isHome={false}/> },
{ path: 'sq/qth/sksq', element: <Sksq /> },
{ path: 'sq/qth/hdsq', element: <Hdsq /> },
{ path: 'sq/qth/ssyq', element: <Ssyq /> },
// 预警 // 预警
{ path: 'gcaqjc/gcaqyj/bzt', element: <Bzt isHome={false}/> }, { path: 'gcaqjc/gcaqyj/bzt', element: <Bzt isHome={false}/> },
{ path: 'gcaqjc/gcaqyj/yhyj', element: <Yhyj /> }, { path: 'gcaqjc/gcaqyj/yhyj', element: <Yhyj /> },
@ -203,7 +212,7 @@ const AppRouters: React.FC = () => {
{ path: 'fxzb/jczw/yqz', element: <HomePage /> }, { path: 'fxzb/jczw/yqz', element: <HomePage /> },
{ path: 'fxzb/jczw/sqz', element: <HomePage /> }, { path: 'fxzb/jczw/sqz', element: <HomePage /> },
// 视频监控 // 视频监控
{ path: 'spjk/spjk', element: <Spjk /> }, { path: 'sq/qth/spjk', element: <Spjk /> },
{ path: 'sg/gjgl/aigj', element: <AiWarn /> }, { path: 'sg/gjgl/aigj', element: <AiWarn /> },
// { path: 'fxzb/zbb', element: <Zbb /> }, // { path: 'fxzb/zbb', element: <Zbb /> },
@ -234,6 +243,7 @@ const AppRouters: React.FC = () => {
{ path: 'sq/qzq/Gcdsj', element: <Gcdsj /> }, { path: 'sq/qzq/Gcdsj', element: <Gcdsj /> },
// 四制-组织机构查看 // 四制-组织机构查看
{ path: 'sz/gltx/zzjgck', element: <Zzjgck /> }, { path: 'sz/gltx/zzjgck', element: <Zzjgck /> },
{ path: 'sz/pxgl/pxjhgl', element: <Pxjhgl /> },
], ],
}, },
{ path: '/login', element: <LoginPage /> }, { path: '/login', element: <LoginPage /> },

View File

@ -77,10 +77,12 @@ function DrpSearch({record}) {
], ],
} }
setParams(option) if (record.stcd) {
setParams(option)
getData(option) getData(option)
}
}, [current]) }, [current,record])
return ( return (
@ -104,16 +106,16 @@ function DrpSearch({record}) {
<div className="time-type"> <div className="time-type">
{ {
['小时', '日'].map((item, index) => ( ['小时', '日'].map((item, index) => (
<div className={clsx({active: index === current})} onClick={() => setCurrent(index)}>{item}</div> <div className={clsx({sqActive: index === current})} onClick={() => setCurrent(index)}>{item}</div>
)) ))
} }
</div> </div>
</div> </div>
<div className="mid1"> <div className="mid1" >
<div className="mid-left"> <div className="mid-left" style={record?.height ? { height: "55vh" } : {}}>
<TableData data={data} current={current}/> <TableData data={data} current={current}/>
</div> </div>
<div className="mid-right"> <div className="mid-right" style={record?.height ? { height: "55vh" } : {}}>
{ {
data?.length > 0 ? data?.length > 0 ?
<ReactEcharts <ReactEcharts
@ -125,7 +127,7 @@ function DrpSearch({record}) {
} }
</div> </div>
</div> </div>
<div className="footer"> <div className="footer" style={record?.height?{fontSize:15}:{}}>
<div className="footer-row"> <div className="footer-row">
<div className="footer-item"> <div className="footer-item">
<div className="footer-name">近1h雨量(mm)</div> <div className="footer-name">近1h雨量(mm)</div>

View File

@ -13,7 +13,7 @@
padding: 8px 0; padding: 8px 0;
} }
.active { .sqActive {
color: #5FB7FF; color: #5FB7FF;
background: #F0F7FF; background: #F0F7FF;
border: 1px solid #5FB7FF; border: 1px solid #5FB7FF;

View File

@ -40,31 +40,9 @@ function DrpSearch({ record }) {
useEffect(() => { useEffect(() => {
let option = ""; let option = "";
// 比较当前时间和早上八点
// if (currentTime.isBefore(eightAM)) {
// option = {
// stcd: record.stcd,
// source: record.source,
// stm: moment().subtract(8, 'days').startOf('day').set({hour: 8, minute: 0}).format("YYYY-MM-DD HH:mm"),
// etm: moment().subtract(1, 'days').startOf('day').set({hour: 8, minute: 0}).format("YYYY-MM-DD HH:mm"),
// tm: [moment().subtract(8, 'days').startOf('day').set({
// hour: 8,
// minute: 0
// }), moment().subtract(1, 'days').startOf('day').set({hour: 8, minute: 0})],
// }
// } else {
// option = {
// stcd: record.stcd,
// source: record.source,
// stm: moment().subtract(7, 'days').startOf('day').set({hour: 8, minute: 0}).format("YYYY-MM-DD HH:mm"),
// etm: moment().startOf('day').set({hour: 8, minute: 0}).format("YYYY-MM-DD HH:mm"),
// tm: [moment().subtract(7, 'days').startOf('day').set({
// hour: 8,
// minute: 0
// }), moment().startOf('day').set({hour: 8, minute: 0})],
// }
// }
option = { option = {
stcd: record.stcd, stcd: record.stcd,
source: record.source, source: record.source,
@ -75,15 +53,18 @@ function DrpSearch({ record }) {
moment().add(1, 'hour').set({ minute: 0, second: 0 }), moment().add(1, 'hour').set({ minute: 0, second: 0 }),
], ],
} }
setParams(option) if (record?.stcd && record.source) {
getData(option) setParams(option)
getData(option)
}
}, [record]) }, [record])
return ( return (
<div style={{width: "98%", height: '65vh'}} className="jcsj-sq"> <div style={{width: "98%", height: '65vh'}} className="jcsj-sq">
<div className="top"> <div className="top">
<div className="top-left"> <div className="top-left" style={record?.height?{height:"65vh"}:{}}>
<div className="top-toobar"> <div className="top-toobar">
<RangePicker showTime allowClear style={{width: "330px"}} <RangePicker showTime allowClear style={{width: "330px"}}
onChange={searchTm} onChange={searchTm}
@ -92,11 +73,11 @@ function DrpSearch({ record }) {
/> />
<Button type="primary" onClick={doSearch} style={{marginLeft: "10px"}}>查询</Button> <Button type="primary" onClick={doSearch} style={{marginLeft: "10px"}}>查询</Button>
</div> </div>
<div className="top-left-table"> <div className="top-left-table" style={record?.height?{height:"60vh"}:{}}>
<TableData data={data} /> <TableData data={data} />
</div> </div>
</div> </div>
<div className="top-right"> <div className="top-right" style={record?.height?{height:"65vh"}:{}}>
{ {
data.length > 0 ? data.length > 0 ?
<ReactEcharts <ReactEcharts
@ -108,7 +89,7 @@ function DrpSearch({ record }) {
} }
</div> </div>
</div> </div>
<div className="footer"> <div className="footer" style={record?.height?{fontSize:15}:{}}>
<div className="footer-row"> <div className="footer-row">
<div className="footer-item"> <div className="footer-item">
<div className="footer-name">近1h雨量(mm)</div> <div className="footer-name">近1h雨量(mm)</div>

View File

@ -0,0 +1,54 @@
import React, { useEffect, useState } from 'react'
import { reservoirlist, list} from "../../../../service/sssq";
import Sssw from './sssw';
import Sjcx from '../../../Home/MapCtrl/components/Sqjcsj/index'
import "./index.less"
import { helpers } from '@turf/turf';
export default function Sksq() {
const [tableData, setTableData] = useState([])
const [tableData1, setTableData1] = useState([])
const getData = async (params) => {
setTableData(await reservoirlist(params));
}
const getData1 = async (params) => {
setTableData1(await list(params));
}
useEffect(() => {
let option = {
sources: ["SW", "SK"],
args: "",
};
getData(option)
getData1({args: "",sources: ["SH", "SW"],})
}, [])
return (
<div className='lf' style={{ height: 'calc(100vh - 168px)', width: "100%" }}>
<div className='content-sk'>
<div className='content-left'>
<div className='comomn-title'>
<div>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时水位</span>
</div>
<span>站点{tableData[0]?.stnm}</span>
</div>
<div className='sssw-content'>
<Sssw data={tableData[0] || {}}/>
</div>
</div>
<div className='content-right'>
<div className='comomn-title'>
<div style={{display:"flex",alignItems:"center",columnGap:10}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span>数据查询</span>
</div>
</div>
<div className='sjcx-content'>
<Sjcx record={tableData[0] || {}}/>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,108 @@
.content-sk{
display: flex;
column-gap: 10px;
height: calc(100vh - 90px);
.comomn-title{
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 10px;
}
.content-left{
width: 550px;
height: 100%;
background-color: #fff;
.ssjc{
.root {
display: flex;
color: #333;
padding: 1rem 1rem 1rem 1rem;
}
.realinfo {
width: 100%;
margin-right: 1rem
}
.dataTm {
padding: 0.4rem 1rem;
border-radius: 0.4rem;
margin-bottom: 0.5rem;
font-size: 0.8rem;
}
.online, .offline{
color:#fff;
line-height:22px;
font-size:14px;
letter-spacing: 1px;
}
.online {
border: 1px solid #9ccc65;
background-color: #33691e;
}
.report-time,.rain-report{
display: flex;
width: 70%;
align-items: center;
color: #689fff;
font-size: 15px;
font-weight: 500;
line-height: 1.5;
column-gap: 5px;
margin-bottom: 10px;
justify-content: center;
padding: 7px 0;
background-color: #ecf5ff;
border: 1px solid #cde5ff;
border-radius: 5px;
margin-left: 10%;
}
.offline {
border: 1px solid #ef5350;
background-color: #b71c1c;
}
.infoItem {
border-bottom: 1px dashed #aaa;
display: flex;
font-size: 14px;
line-height: 1.8;
margin-bottom: 0.5rem;
& > .row-key{
width: 9rem;
line-height:30px;
}
& > .row-value{
width: 50%;
text-align: right;
font-weight: bold;
margin-right: 0.5rem;
flex-grow: 1;
}
& > .row-unit{
width: 3rem;
flex-shrink: 0;
}
}
}
}
.content-right{
flex: 1;
height: 100%;
background-color: #fff;
.sjcx-content{
padding: 10px;
}
}
.pic-container{
padding: 10px;
}
}

View File

@ -0,0 +1,66 @@
import React from 'react'
import moment from 'moment'
import MyImg from '../../../Home/MapCtrl/components/Skssjc/myImg'
export default function Sssw({data}) {
return (
<div className="ssjc">
<div className="root">
<div className="realinfo">
<div
className='report-time'
>水位上报时间: {data?.tm}</div>
<div className="infoItem">
<div className="row-key">监测水位:</div>
<div className="row-value">{data?.rz ? data?.rz.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">设计洪水位:</div>
<div className="row-value">{data?.desFloodLev ? data?.desFloodLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">正常蓄水位:</div>
<div className="row-value">{data.normWatLev ? data.normWatLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">汛限水位:</div>
<div className="row-value">{data.flLowLimLev ? data.flLowLimLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">死水位:</div>
<div className="row-value">{data.deadLev ? data.deadLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">坝顶高程:</div>
<div className="row-value">{data.crestElev}</div>
<div className="row-unit">{ data.crestElev ? "m" : "-"}</div>
</div>
<div className="infoItem">
<div className="row-key">水库当前库容:</div>
<div className="row-value">{data.nowCap}</div>
<div className="row-unit">万m³</div>
</div>
<div className="infoItem">
<div className="row-key">兴利库容:</div>
<div className="row-value">{data.benResCap}</div>
<div className="row-unit">万m³</div>
</div>
</div>
</div>
<div className='pic-container'>
<MyImg record={data} />
</div>
</div>
)
}

View File

@ -0,0 +1,49 @@
import React, { useEffect, useState } from 'react'
import { reservoirlist, } from "../../../../service/sssq";
import Sssw from './sssw';
import Sjcx from '../../../Home/MapCtrl/components/Sksjcx/index'
import "./index.less"
import { helpers } from '@turf/turf';
export default function Sksq() {
const [tableData, setTableData] = useState([])
const getData = async (params) => {
setTableData(await reservoirlist(params));
}
useEffect(() => {
let option = {
sources: ["SW", "SK"],
args: "",
};
getData(option)
}, [])
return (
<div className='lf' style={{ height: 'calc(100vh - 168px)', width: "100%" }}>
<div className='content-sk'>
<div className='content-left'>
<div className='comomn-title'>
<div>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时水位</span>
</div>
<span>站点{tableData[0]?.stnm}</span>
</div>
<div className='sssw-content'>
<Sssw data={tableData[0] || {}}/>
</div>
</div>
<div className='content-right'>
<div className='comomn-title'>
<div style={{display:"flex",alignItems:"center",columnGap:10}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span>数据查询</span>
</div>
</div>
<div className='sjcx-content'>
<Sjcx record={{...tableData[0],height:true} || {}}/>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,108 @@
.content-sk{
display: flex;
column-gap: 10px;
height: calc(100vh - 90px);
.comomn-title{
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 10px;
}
.content-left{
width: 550px;
height: 100%;
background-color: #fff;
.ssjc{
.root {
display: flex;
color: #333;
padding: 1rem 1rem 1rem 1rem;
}
.realinfo {
width: 100%;
margin-right: 1rem
}
.dataTm {
padding: 0.4rem 1rem;
border-radius: 0.4rem;
margin-bottom: 0.5rem;
font-size: 0.8rem;
}
.online, .offline{
color:#fff;
line-height:22px;
font-size:14px;
letter-spacing: 1px;
}
.online {
border: 1px solid #9ccc65;
background-color: #33691e;
}
.report-time,.rain-report{
display: flex;
width: 70%;
align-items: center;
color: #689fff;
font-size: 15px;
font-weight: 500;
line-height: 1.5;
column-gap: 5px;
margin-bottom: 10px;
justify-content: center;
padding: 7px 0;
background-color: #ecf5ff;
border: 1px solid #cde5ff;
border-radius: 5px;
margin-left: 10%;
}
.offline {
border: 1px solid #ef5350;
background-color: #b71c1c;
}
.infoItem {
border-bottom: 1px dashed #aaa;
display: flex;
font-size: 14px;
line-height: 1.8;
margin-bottom: 0.5rem;
& > .row-key{
width: 9rem;
line-height:30px;
}
& > .row-value{
width: 50%;
text-align: right;
font-weight: bold;
margin-right: 0.5rem;
flex-grow: 1;
}
& > .row-unit{
width: 3rem;
flex-shrink: 0;
}
}
}
}
.content-right{
flex: 1;
height: 100%;
background-color: #fff;
.sjcx-content{
padding: 10px;
}
}
.pic-container{
padding: 10px;
}
}

View File

@ -0,0 +1,66 @@
import React from 'react'
import moment from 'moment'
import MyImg from '../../../Home/MapCtrl/components/Skssjc/myImg'
export default function Sssw({data}) {
return (
<div className="ssjc">
<div className="root">
<div className="realinfo">
<div
className='report-time'
>水位上报时间: {data?.tm}</div>
<div className="infoItem">
<div className="row-key">监测水位:</div>
<div className="row-value">{data?.rz ? data?.rz.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">设计洪水位:</div>
<div className="row-value">{data?.desFloodLev ? data?.desFloodLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">正常蓄水位:</div>
<div className="row-value">{data.normWatLev ? data.normWatLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">汛限水位:</div>
<div className="row-value">{data.flLowLimLev ? data.flLowLimLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">死水位:</div>
<div className="row-value">{data.deadLev ? data.deadLev.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">坝顶高程:</div>
<div className="row-value">{data.crestElev}</div>
<div className="row-unit">{ data.crestElev ? "m" : "-"}</div>
</div>
<div className="infoItem">
<div className="row-key">水库当前库容:</div>
<div className="row-value">{data.nowCap}</div>
<div className="row-unit">万m³</div>
</div>
<div className="infoItem">
<div className="row-key">兴利库容:</div>
<div className="row-value">{data.benResCap}</div>
<div className="row-unit">万m³</div>
</div>
</div>
</div>
<div className='pic-container'>
<MyImg record={data} />
</div>
</div>
)
}

View File

@ -0,0 +1,72 @@
import React, { useEffect, useState } from 'react'
import { reservoirlist, } from "../../../../service/sssq";
import { message } from 'antd';
import Sssw from './sssw';
import Sjcx from '../../../Home/MapCtrl/components/Jcsj/index'
import "./index.less"
import { httppost2 } from '../../../../utils/request';
import apiurl from '../../../../service/apiurl';
import { helpers } from '@turf/turf';
export default function Sksq() {
const [tableData, setTableData] = useState([])
const [tableData1, setTableData1] = useState([])
const getData = async (params) => {
setTableData(await reservoirlist(params));
}
const getData1 = async () =>{
const { data, code, msg } = await httppost2(apiurl.home.yq)
if (code !== 200) {
message.error(msg || '请求失败');
}
const list = data.map((i)=>{
return {
id : i.stcd,
...i,
drp : i.drp ,//i.v,
}
})
setTableData1(list||[])
}
useEffect(() => {
let option = {
sources: ["SW", "SK"],
args: "",
};
getData(option)
}, [])
useEffect(() => {
getData1()
}, [])
return (
<div className='lf' style={{ height: 'calc(100vh - 168px)', width: "100%" }}>
<div className='content-sk'>
<div className='content-left'>
<div className='comomn-title'>
<div>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时雨情</span>
</div>
<span>站点{tableData[0]?.stnm}</span>
</div>
<div className='sssw-content'>
<Sssw data={tableData[0] || {}}/>
</div>
</div>
<div className='content-right'>
<div className='comomn-title'>
<div style={{display:"flex",alignItems:"center",columnGap:10}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span>数据查询</span>
</div>
</div>
<div className='sjcx-content'>
<Sjcx record={{...tableData1[2],height:true} || {}}/>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,82 @@
.content-sk{
display: flex;
column-gap: 10px;
height: calc(100vh - 90px);
.comomn-title{
display: flex;
align-items: center;
justify-content: space-between;
padding: 20px 10px;
}
.content-left{
width: 550px;
height: 100%;
background-color: #fff;
.ssjc{
.root {
display: flex;
color: #333;
padding: 1rem 1rem 1rem 1rem;
.drp-content{
display: flex;
justify-content: center;
flex-wrap: wrap;
column-gap: 40px;
margin-top: 40px;
}
.drp-item{
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
width: 220px;
height: 160px;
background-color: #eaf4fe;
margin-bottom: 40px;
.value{
font-size: 20px;
font-weight: bold;
}
.name{
font-size: 16px;
color: #40a9ff;
}
}
}
.report-time,.rain-report{
display: flex;
width: 70%;
align-items: center;
color: #689fff;
font-size: 15px;
font-weight: 500;
line-height: 1.5;
column-gap: 5px;
margin-bottom: 10px;
justify-content: center;
padding: 7px 0;
background-color: #ecf5ff;
border: 1px solid #cde5ff;
border-radius: 5px;
margin-left: 10%;
}
}
}
.content-right{
flex: 1;
height: 100%;
background-color: #fff;
.sjcx-content{
padding: 10px;
}
}
.pic-container{
padding: 10px;
}
}

View File

@ -0,0 +1,43 @@
import React from 'react'
import moment from 'moment'
import MyImg from '../../../Home/MapCtrl/components/Skssjc/myImg'
export default function Sssw({data}) {
return (
<div className="ssjc">
<div className="root">
<div className="realinfo">
<div
className='report-time'
>雨情最新上报时间: {data?.tm}</div>
<div className='drp-content'>
<div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='name'>近1小时</div>
</div>
<div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='name'>近3小时</div>
</div>
<div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='name'>近6小时</div>
</div>
<div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='name'>近12小时</div>
</div>
<div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='name'>近24小时</div>
</div> <div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='name'>近48小时</div>
</div>
</div>
</div>
</div>
</div>
)
}

395
src/views/sz/pxjhgl/form.js Normal file
View File

@ -0,0 +1,395 @@
import React,{useEffect,useState,useMemo,useRef} from 'react';
import { Form, Button, Input, Row,Upload, Col, Table, DatePicker, InputNumber,message,Image,Modal,Typography ,Popconfirm } from 'antd';
import { DeleteOutlined,FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import apiurl from '../../../service/apiurl';
import NormalSelect from '../../../components/Form/NormalSelect';
import "./index.less"
import moment from 'moment';
import { createCrudService } from '../../../components/crud/_';
const { RangePicker } = DatePicker
const { Dragger } = Upload;
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const types = [
{
label: "水利",
value:1
},
{
label: "岗前培训",
value:2
},{
label: "在岗培训",
value:3
},{
label: "政治学习教育",
value:4
},{
label: "其他",
value:5
},
]
const [details, setDetails] = useState([])
const [form] = Form.useForm();
const [fileList, setFileList] = useState([]) //上传文件列表
const [fileIds, setFileIds] = useState([])
const [iframeSrc, setIframeSrc] = useState('')
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.download = `${params.fileName}`;
downloadLink.style.display = "none";
// 将链接添加到页面中
document.body.appendChild(downloadLink);
// 模拟点击事件,开始下载
downloadLink.click();
}
/**
* @description 上传图片
* @param {string} file 上传的文件
*/
const fileChange = (info) => {
if (info.file.status === "done") {
setLoading(false);
}
if (info.file.status === "uploading") {
setLoading(true);
}
if (info.file.status === "error") {
message.error("文件上传失败")
setLoading(false);
}
let fileIds = info.fileList.map(file => {
return file.response?.data?.fileId
})
setFileIds(fileIds)
setFileList(info.fileList)
}
/**
* @description pdf文件预览
* @param {String} params 文件预览url
*/
const viewPdf = (params) => {
setIframeSrc(params)
setPdfViewOPen(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")
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)
}
if (mode === 'save') {
values.fileIds = fileIds
onSave(apiurl.fxzb.qsdw.zq.save,values)
}
}
/**
* @description 删除上传的图片
* @param {string} id 删除的id
*/
const deleteFile = (fileId) => {
console.log(fileId);
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})
}
}, [record,mode])
return (
<>
<div className='basic-info'>基本信息</div>
{/* <Divider /> */}
<Form
form={form}
{...formItemLayout}
// initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="培训班名称"
name="teamName"
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="培训班分类"
name="teamName"
rules={[{ required: true }]}
>
<NormalSelect disabled={mode === 'view'} style={{ width: '100%' }} allowClear options={types} />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="有效期限"
name="dateRangeSo"
rules={[
{
required: true,
message: `有效期限不能为空`,
},
]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => {
return {
value: value ? [value[0]&&moment(value[0]),value[1]&&moment(value[1])] : undefined
};
}}
>
<RangePicker
allowClear
showTime
disabled={mode==='view'}
// style={{ width: "300px" }}
format="YYYY-MM-DD"
/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="管理单位"
name="managementUnit"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="地址"
name="address"
rules={[{ required: true }]}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
label="经度"
name="lgtd"
labelCol={{ span: 12 }}
wrapperCol={{ span: 10 }}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={6}>
<Form.Item
label="纬度"
name="lttd"
labelCol={{ span: 6 }}
wrapperCol={{ span: 10 }}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="队伍负责人"
name="teamLeader"
>
<Input type='num' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="联系电话"
name="phone"
>
<Input type='num' disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="附件"
name="fieldId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
{mode !== "view" &&
<Dragger
name='file'
// multiple
action="/gunshiApp/xyt/rescue/team/file/upload/singleSimple"
onChange={fileChange}
onDrop={(info) => { console.log(info.dataTransfer.files); }}
fileList={fileList}
disabled={loading}
// onSuccess={handleSuccess}
>
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p className="ant-upload-hint">
支持扩展名.rar .zip .doc .docx .pdf .jpg .png .ppt
</p>
</Dragger>
}
<Row gutter={[16]}>
{
fileList.length > 0 && fileList.map(file => {
return (
<Col span={12}>
<div className="file-item" style={{width:"75%"}}>
<div className='file-description'>
{file.name.indexOf('.docx') > -1 ?
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileWordOutlined
style={{ fontSize: 40 }}
/>
</div>
:
file.name.indexOf('.pdf') > -1 ?
<div
onClick={() => { viewPdf(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FilePdfOutlined style={{ fontSize: 40 }} />
</div>
:
file.name.indexOf('.zip') > -1 ?
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileZipOutlined style={{ fontSize: 40 }} />
</div>
:
file.name.indexOf('.xlsx') > -1 ?
<div
onClick={() => { download(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileExcelOutlined style={{ fontSize: 40 }} />
</div>
:
<Image width={60} src={url +file.response?.data?.filePath} alt='' />
}
<span>{file.name}</span>
</div>
<div className={mode == "view" ? 'delete-icon disable-icon' : 'delete-icon'} onClick={() => deleteFile(file.response?.data?.fileId)}>
<DeleteOutlined />
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
</Form>
<div className='basic-info' style={{display:"flex",justifyContent:"space-between"}}>
<span>队伍明细共计{details?.length}</span>
</div>
<Modal
open={pdfViewOPen}
width={1000}
title=""
footer={null}
style={{marginTop:"-5%"}}
onCancel={() => {
setPdfViewOPen(false)
}}
>
<iframe
style={{
height: '80vh',
width: '100%',
border: 0,
marginTop: 20,
}}
src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/xyt/rescue/goods/file/download/${iframeSrc}`)}`}
/>
</Modal>
</>
);
}
export default ModalForm;

View File

@ -0,0 +1,111 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import { useSelector } from 'react-redux';
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card,Modal,Form,Input,Button,Row,Col,message } from 'antd';
import ToolBar from './toolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import usePageTable from '../../../components/crud/usePageTable2';
import { createCrudService } from '../../../components/crud/_';
import {CrudOpRender_text} from '../../../components/crud/CrudOpRender';
const Page = () => {
const role = useSelector(state => state.auth.role);
const editBtn = role?.rule?.find(item => item.menuName == "编辑") || true;
const viewBtn = role?.rule?.find(item => item.menuName == "查看") || true;
const delBtn = role?.rule?.find(item => item.menuName == "删除") || true;
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const [isFetch, setIsFetch] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '培训班名称', key: 'teamName', dataIndex: 'teamName', width: 200, ellipsis: true },
{
title: '计划培训周期', key: 'personCount', dataIndex: 'personCount', width: 200,
},
{ title: '主办单位', key: 'address', dataIndex: 'address', width: 200 },
{
title: '培训内容', key: 'managementUnit', dataIndex: 'managementUnit', width: 200,ellipsis: true
},
{ title: '培训地点', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, ellipsis: true },
{ title: '填报人', key: 'phone', dataIndex: 'phone', width: 150, ellipsis: true },
{
title: '操作', key: 'operation', width: 300, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={editBtn ? true : false}
del={delBtn ? true : false}
view={viewBtn ? true : false}
similarAdd={true}
record={true}
command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} else if (type === 'edit') {
refModal.current.showEdit({ ...params });
} else if (type === 'view') {
refModal.current.showView(params);
} else if (type === 'del') {
refModal.current.onDeleteGet(apiurl.fxzb.qsdw.zq.delete + `/${params.teamId}`);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.fxzb.qsdw.zq.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
setIsFetch(!isFetch)
}
useEffect(()=>{
const params = {
search: {
...searchVal,
}
};
search(params)
}, [searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{paddingRight:"0",paddingBottom:"0"}}>
<div className='lf CrudAdcdTreeTableBox' style={{width:"100%"}}>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
onSave={command('save')}
role={role}
/>
</Card>
<div className="ant-card-body" style={{padding:"20px 0 0 0"}}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
</div>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={successCallback}
// onCrudSuccess={()=>{refresh({addvcd:localStorage.getItem('ADCD6')})}}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,17 @@
.basic-info{
position: relative;
font-size: 16px;
margin-bottom: 20px;
padding:5px 25px;
border-bottom: 1px solid #eee;
&::before{
position: absolute;
top:8px;
left:0;
content: "";
display: block;
width: 5px;
height: 20px;
background-color: #0079fe;
}
}

View File

@ -0,0 +1,66 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import moment from 'moment';
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, role = [] }) => {
const [form] = Form.useForm();
const addBtn = role?.rule?.find(item => item.menuName == "新增")|| true;
const searchBtn = role?.rule?.find(item => item.menuName == "查询")|| true;
const onFinish = (values) => {
let dateSo;
if (values.tm) {
dateSo = {
start: moment(values.tm[0]).format('YYYY'),
end: moment(values.tm[1]).format('YYYY')
}
}
delete values.tm
setSearchVal({...values, dateSo});
}
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="计划年度" name="tm">
<RangePicker
allowClear
showTime
style={{ width: "300px" }}
picker='year'
/>
</Form.Item>
<Form.Item label="填报人" name="teamName">
<Input allowClear style={{width:'150px'}}/>
</Form.Item>
<Form.Item label="培训班名称" name="teamName">
<Input allowClear style={{width:'150px'}}/>
</Form.Item>
{searchBtn ? <Form.Item>
<Button type="primary" htmlType="submit">查询</Button>
</Form.Item> : null }
<Form.Item>
<Button onClick={() => form.resetFields()}>重置</Button>
</Form.Item>
{
(onSave && addBtn) ?
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
:null
}
<Form.Item>
<Button onClick={() => form.resetFields()}>导入</Button>
</Form.Item><Form.Item>
<Button onClick={() => form.resetFields()}>导出</Button>
</Form.Item>
</Form>
</div>
</>
);
}
export default ToolBar;