Compare commits

...

3 Commits

Author SHA1 Message Date
李神峰 9b161f4012 feat():水情开发 2024-09-23 18:04:37 +08:00
xielei 65449e77a2 caidan 2024-09-23 14:07:06 +08:00
xielei 617c85af3d caidan 2024-09-23 14:06:03 +08:00
45 changed files with 3359 additions and 56 deletions

BIN
src/assets/img/qys1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 471 KiB

BIN
src/assets/img/qys2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 KiB

BIN
src/assets/img/qys3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

BIN
src/assets/img/qys4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 947 B

BIN
src/assets/img/u7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

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 (
<div style={{ display: 'inline' }}>
{
record ? (
<Button style={{ marginRight: 4 }} type="link" size="small" onClick={command('record')} title="培训记录">培训记录</Button>
) : null
}
{
add ? (
<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>
) : null
}
</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: [
{
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',
}
]
}
]
@ -342,6 +333,39 @@ export async function loadMenu(): Promise<MenuItem[]> {
},
],
},
{ id:id(),title:'四全',redirect:'/mgr/sq/qfg/zcdjxx',
children: [
{ id: id(), title: '全覆盖', redirect: '/mgr/sq/qfg/zcdjxx',
children: [
{ id: id(), title: '注册登记信息', path: '/mgr/sq/qfg/zcdjxx'},
]
},
{ id: id(), title: '全要素', redirect: '/mgr/sq/qys/kqys',
children: [
{ id: id(), title: '库区要素', path: '/mgr/sq/qys/kqys'},
{ id: id(), title: '工程要素', path: '/mgr/sq/qys/gcys'},
{ id: id(), title: '下游要素', path: '/mgr/sq/qys/xyys'},
]
},
{ id: id(), title: '全周期', redirect: '/mgr/sq/qzq/gcdsj',
children: [
{ id: id(), title: '工程大事记', path: '/mgr/sq/qzq/gcdsj'},
{ 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'},
]
},
]
},
// { id: id(), title: '基本情况', path: '/mgr/home', icon: 'jbqk' },
// {

View File

@ -66,7 +66,7 @@ import Khrwgl from "./rcgl/jdkh/khrwgl"
// 值班管理
import Zbb from "./zbgl/zbb"
import Zbrz from "./zbgl/zbrz"
import Gcdsj from "./rcgl/gcdsj"
// import Gcdsj from "./rcgl/gcdsj"
import VideoList from './video'
@ -80,8 +80,24 @@ import Spjk from "./video"
import AiWarn from "./spjk/aiWarn"
// 四全
import Zcdjxx from './sq/qfg/zcdjxx'
import Kqys from './sq/qys/kqys/index.js'
import Xyys from './sq/qys/xyys/index.js'
import Gcys from './sq/qys/gcys/index.js'
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/qfg/zcdjxx'
// import Zcdjxx from './sq/qfg/zcdjxx'
// import Zcdjxx from './sq/qfg/zcdjxx'
// 四制 - 组织机构查看
import Zzjgck from './sz/zzjgck'
import Pxjhgl from './sz/pxjhgl'
const HomePage = lazy(() => import('./Home'))
@ -135,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/yhyj', element: <Yhyj /> },
@ -191,7 +212,7 @@ const AppRouters: React.FC = () => {
{ path: 'fxzb/jczw/yqz', 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: 'fxzb/zbb', element: <Zbb /> },
@ -212,8 +233,17 @@ const AppRouters: React.FC = () => {
{ path: 'fxdd/ddjc/ddzl', element: <Ddzl /> },
{ path: 'videoSurveillance', element: <VideoList /> },
// 四全
// 注册登记信息
{ path: 'sq/qfg/zcdjxx', element: <Zcdjxx /> },
//库区要素
{ path: 'sq/qys/kqys', element: <Kqys /> },
{ path: 'sq/qys/xyys', element: <Xyys /> },
{ path: 'sq/qys/gcys', element: <Gcys /> },
{ path: 'sq/qzq/Gcdsj', element: <Gcdsj /> },
// 四制-组织机构查看
{ path: 'sz/gltx/zzjgck', element: <Zzjgck /> },
{ path: 'sz/pxgl/pxjhgl', element: <Pxjhgl /> },
],
},
{ path: '/login', element: <LoginPage /> },

View File

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

View File

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

View File

@ -40,31 +40,9 @@ function DrpSearch({ record }) {
useEffect(() => {
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 = {
stcd: record.stcd,
source: record.source,
@ -75,15 +53,18 @@ function DrpSearch({ record }) {
moment().add(1, 'hour').set({ minute: 0, second: 0 }),
],
}
if (record?.stcd && record.source) {
setParams(option)
getData(option)
}
}, [record])
return (
<div style={{width: "98%", height: '65vh'}} className="jcsj-sq">
<div className="top">
<div className="top-left">
<div className="top-left" style={record?.height?{height:"65vh"}:{}}>
<div className="top-toobar">
<RangePicker showTime allowClear style={{width: "330px"}}
onChange={searchTm}
@ -92,11 +73,11 @@ function DrpSearch({ record }) {
/>
<Button type="primary" onClick={doSearch} style={{marginLeft: "10px"}}>查询</Button>
</div>
<div className="top-left-table">
<div className="top-left-table" style={record?.height?{height:"60vh"}:{}}>
<TableData data={data} />
</div>
</div>
<div className="top-right">
<div className="top-right" style={record?.height?{height:"65vh"}:{}}>
{
data.length > 0 ?
<ReactEcharts
@ -108,7 +89,7 @@ function DrpSearch({ record }) {
}
</div>
</div>
<div className="footer">
<div className="footer" style={record?.height?{fontSize:15}:{}}>
<div className="footer-row">
<div className="footer-item">
<div className="footer-name">近1h雨量(mm)</div>

View File

@ -1,9 +1,10 @@
import { Image } from "antd"
import zd from '../../../assets/img/u0.png'
const Page = () => {
return (
<>
<Image src="../../../"/>
</>
<div style={{display:'flex',justifyContent:'center',alignItems:'center',backgroundColor:'#fff',height:'100%'}}>
<Image src={zd} style={{margin:'auto'}} preview={false}/>
</div>
)
}
export default Page

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>
)
}

View File

@ -0,0 +1,97 @@
import echarts from 'echarts/lib/echarts';
import { GetInterval } from '../../../../../utils/tools'
export default function drpOption({data}) {
const maxVal = Math.ceil(Math.max(...data.map(obj => obj.rz)))
const minVal = Math.floor(Math.min(...data.map(obj => obj.rz)))
const maxValX = Math.max(...data.map(obj => obj.w))
const minValX = Math.min(...data.map(obj => obj.w))
let arr =[]
data.forEach(item=>{
console.log(data);
arr.push([item.w,item.rz])
})
// console.log(GetInterval(minValX,maxValX),'jhsdjkashdjkahjk');
return {
toolbox: {
show: true,
feature: {
saveAsImage: {
show: true,
excludeComponents: ['toolbox'],
pixelRatio: 2,
name:"库容曲线图"
}
},
right: "14%",
top:"5%"
},
title: {
text: "库容曲线图",
left: "40%",
},
tooltip: {
trigger: 'axis',
},
grid: [
{
top: "10%",
left: "15%",
right: "15%",
bottom: "8%"
},
],
xAxis: [
{
name: "库容(万m³)",
nameGap: 5,
type: 'value',
min:Math.floor(minValX / 5) *5,
max:Math.ceil(maxValX / 5) *5,
interval:GetInterval(minValX,maxValX),
data: data.map(o => o.w),
splitLine: {
show: false
},
}
],
yAxis: [
{
type: 'value',
name: "库水位(m)",
minInterval:1,
splitLine: {
show: true,
lineStyle: {
color: '#07a6ff',
width: 0.25,
type: 'dotted'
}
},
axisLabel: {
color: '#333',
fontSize: 12,
},
axisLine: {
show: false
},
axisTick: {
show: false,
},
min: minVal,
max: maxVal
}
],
series: [
{
type: 'line',
color: "#007AFD",
data: arr,
smooth: true
},
]
};
}

View File

@ -0,0 +1,79 @@
import React,{useEffect,useState,useRef} from 'react';
import { Form, Button, Input, Row, Col} from 'antd';
import { formItemLayout, btnItemLayout } from '../../../../../components/crud/FormLayoutProps';
import apiurl from '../../../../../service/apiurl';
const ModalForm = ({ mode, record,onEdit,onSave,onCrudSuccess }) => {
const [form] = Form.useForm();
const onFinish = async (values) => {
values.resCode = "42120250085"
values.id = record?.id
if (mode === 'edit') {
const params = {
...record,
rz: Number(values?.rz),
w: Number(values?.w),
}
onEdit(apiurl.dataResourcesCenter.projectAndWater.kr.update,params)
}
if (mode === 'save') {
onSave(apiurl.dataResourcesCenter.projectAndWater.kr.save,values)
}
}
return (
<>
<Form
form={form}
// {...formItemLayout}
onFinish={onFinish}
initialValues={record}>
<Row>
<Col span={24}>
<Form.Item
label="水位(m)"
name="rz"
labelCol={{ span: 5, offset: 0 }}
wrapperCol={{span:19,offset:0}}
rules={[{ required: true }]}
>
<Input
style={{ width: '100%' }}
allowClear
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="库容(万m³)"
name="w"
labelCol={{ span: 5, offset: 0 }}
wrapperCol={{span:19,offset:0}}
rules={[{ required: true }]}
>
<Input
style={{ width: '100%' }}
allowClear
/>
</Form.Item>
</Col>
</Row>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
</>
);
}
export default ModalForm;

View File

@ -0,0 +1,88 @@
import React,{useEffect,useState,useRef,useMemo} from 'react'
import { Table, Button } from 'antd'
import ModalForm from './form';
import ReactEcharts from 'echarts-for-react';
import drpOption from './drpOption'
import apiurl from '../../../../../service/apiurl';
import { httppost2 } from '../../../../../utils/request';
import { CrudOpRender_text } from '../../../../../components/crud/CrudOpRender';
import BasicCrudModal from '../../../../../components/crud/BasicCrudModal2';
export default function Zrtx() {
const refModal = useRef();
const columns = [
{
title: '序号', dataIndex: 'index', key: 'index', align: "center",
render: (r, c,i) => <span>{i + 1}</span>
},
{ title: '水位(m)', dataIndex: 'rz', key: 'rz',align:"center" },
{ title: '库容(万m³)', dataIndex: 'w', key: 'w',align:"center" },
{
title: '操作', dataIndex: 'op', key: 'op', align: "center",width:200,
render: (value, row, index) => (<CrudOpRender_text del={true} edit={true} command={(cmd) => () => command(cmd)(row)} />)
},
];
const [data, setData] = useState([])
const option = useMemo(() => {
return drpOption({data});
}, [data])
const getData = async () => {
try {
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.kr.list)
setData(res.data.map((item,i) => ({...item,inx:i + 1})))
} catch (error) {
console.log(error);
}
}
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.onDeletePost(apiurl.dataResourcesCenter.projectAndWater.kr.delete,params);
}
}
useEffect(() => {
getData();
}, [])
return (
<div>
<h1><Button type='primary' onClick={() => {refModal.current.showSave({})}}>新增</Button></h1>
<div style={{display:"flex",columnGap:10,width:"100%"}}>
<div style={{width:500}}>
<Table
rowKey="inx"
columns={columns}
dataSource={data}
pagination={false}
scroll={{ y:"calc( 100vh - 300px )"}}
/>
</div>
<div className='right-echarts' style={{ flex: 1 }}>
{
data.length > 0 ?
<ReactEcharts
option={option}
style={{width: "100%", height: '100%'}}
/> : <div style={{textAlign: "center", margin: "10%"}}>
<img src={`${process.env.PUBLIC_URL}/assets/noData.png`} alt=""/>
</div>
}
</div>
</div>
<BasicCrudModal
width={550}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={getData}
/>
</div>
)
}

View File

@ -0,0 +1,41 @@
import React, { useState } from 'react'
import ProjectBasciInfo from './projectBasicInfo'
import TzParams from './tzParams'
import KrLine from './KrLine'
import MonthLl from './monthLl'
import "./index.less"
export default function ShuikuBasicInfo() {
const [tabVal, setTabVal] = useState('1')
return (
<div className='shuiku-content-root'>
<div className='fxdd_hsybjs_toolbar'>
<div
className={tabVal === '1' ? 'fxdd_hsybjs_toolbar_item hsybjs_checked' : 'fxdd_hsybjs_toolbar_item'}
onClick={() => setTabVal('1')}>工程基础信息
</div>
<div
className={tabVal === '2' ? 'fxdd_hsybjs_toolbar_item hsybjs_checked' : 'fxdd_hsybjs_toolbar_item'}
onClick={() => setTabVal('2')}>主要特征参数
</div>
<div
className={tabVal === '3' ? 'fxdd_hsybjs_toolbar_item hsybjs_checked' : 'fxdd_hsybjs_toolbar_item'}
onClick={() => setTabVal('3')}>水库库容曲线
</div>
<div
className={tabVal === '5' ? 'fxdd_hsybjs_toolbar_item hsybjs_checked' : 'fxdd_hsybjs_toolbar_item'}
onClick={() => setTabVal('5')}>月生态流量
</div>
</div>
<div
className='shuiku-content'
style={{marginLeft:(tabVal == 1 || tabVal == 2) ? 60 : 20}}
>
{tabVal === "1" ? <ProjectBasciInfo /> : null}
{tabVal === "2" ? <TzParams /> : null}
{tabVal === "3" ? <KrLine /> : null}
{tabVal === "5" ? <MonthLl /> : null}
</div>
</div>
)
}

View File

@ -0,0 +1,56 @@
.shuiku-content-root{
height: calc(100vh - 93px);
padding: 12px;
overflow-y: auto;
overflow-x: hidden;
background-color: #fff;
margin: 4px 0 0 5px;
.fxdd_hsybjs_toolbar{
width: 100%;
height: 40px;
display: flex;
.fxdd_hsybjs_toolbar_item{
width: 120px;
height: 40px;
line-height: 40px;
margin-right: 5px;
border-radius: 10px 10px 0 0;
background: #D7DFEB;
border: 1px solid rgba(228, 231, 237, 1);
text-align: center;
font-size: 14px;
font-weight: 500;
color: #333;
cursor: pointer;
}
.hsybjs_checked{
color: #409EFF;
background: #ffffff;
}
.fxdd_hsybjs_toolbar_item:hover{
color: #409EFF;
}
}
.shuiku-content{
margin: 0 20px 0 60px;
padding: 20px 0;
}
}
.ant-input[disabled]{
color: rgba(0, 0, 0, 0.5) !important;
}
.ant-select-disabled.ant-select:not(.ant-select-customize-input) .ant-select-selector{
color: rgba(0, 0, 0, 0.5) !important;
}
.ant-picker-input > input[disabled]{
color: rgba(0, 0, 0, 0.5) !important;
}
.ant-select-disabled.ant-select-multiple .ant-select-selection-item{
color: rgba(0, 0, 0, 0.5) !important;
}

View File

@ -0,0 +1,180 @@
import React, { useState,useEffect } from 'react'
import { Table, Input, Form, Row, Col, Button, message } from "antd"
import { httppost2 } from '../../../../../utils/request';
import apiurl from '../../../../../service/apiurl';
import moment from "moment"
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode = <Input style={{ textAlign: "center" }} />;
return (
<td {...restProps}>
{editing ? (
<Form.Item
name={dataIndex}
wrapperCol={[24]}
style={{
margin: 0,
}}
>
{inputNode}
</Form.Item>
) : (
children
)}
</td>
);
};
export default function MonthLl() {
const [form] = Form.useForm()
const columns = Array(12).fill(0).map((item, i) => ({
title: (i + 1) + '月',
key: String(i + 1),
dataIndex: String(i + 1),
align:"center",
ellipsis: true,
editable: true,
}))
const [details, setDetails] = useState([])
const [editingKey, setEditingKey] = useState('');
const [skdisabled, setSkDisabled] = useState(true)
const [data, setData] = useState([])
const isEditing = (record) => {
console.log("editingKey",editingKey,record.id);
return record.id === editingKey;
}
const mergedColumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType: "text",
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
});
const edit = () => {
form.setFieldsValue(details[0])
setSkDisabled(false);
setEditingKey(details[0]?.id)
}
const cancel = () => {
setSkDisabled(true);
setEditingKey("")
}
const editItem = async(arr) => {
try {
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.monthLl.update,arr)
if (res.code == 200) {
message.success('修改成功');
getData()
}
} catch (error) {
console.log(error);
}
}
const save = async () => {
try {
const row = await form.validateFields();
const newData = [];
const index = newData.findIndex((item) => details[0]?.id === item.id);
if (index > -1) {
const item = newData[index];
newData.splice(index, 1, {
...item,
...row,
});
setDetails(newData);
setEditingKey('');
} else {
newData.push(row);
setDetails(newData);
setEditingKey('');
}
setSkDisabled(true)
const arr = data.map(item => ({
...item,
value:newData[0][item.month] ? Number(newData[0][item.month]) : ''
}))
editItem(arr)
} catch (errInfo) {
console.log('Validate Failed:', errInfo);
}
};
const getData = async () => {
try {
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.monthLl.page, { year: moment().year() })
setData(res.data)
let obj = {}
for (let i = 0; i < res.data.length; i++) {
obj[res.data[i].month] = res.data[i].value
}
setDetails([{...obj,id:"42120250085"}])
} catch (error) {
console.log(error);
}
}
useEffect(() => {
console.log(details);
}, [details])
useEffect(() => {
getData()
}, [])
return (
<div>
<h1 style={{ textAlign: "center" }}>月核定生态流量</h1>
<div style={{ textAlign: "center", marginLeft: "30vw" }}>单位:/s</div>
<Form form={form} component={false}>
<Table
rowKey="id"
columns={mergedColumns}
components={{
body: {
cell: EditableCell,
},
}}
dataSource={details}
pagination={false}
/>
</Form>
<Row style={{marginTop:"60vh"}}>
<Col span={24}>
<Form.Item
wrapperCol={{span:14,offset:10}}
>
{
skdisabled ? <Button type="primary" onClick={edit}>编辑</Button> :
<div style={{ display: 'flex', columnGap: 20 }}>
<Button onClick={cancel}>取消</Button>
<Button type="primary" onClick={save}>保存</Button>
</div>
}
</Form.Item>
</Col>
</Row>
</div>
)
}

View File

@ -0,0 +1,458 @@
import React,{useState,useEffect} from 'react'
import { Row, Col, Form, Input, DatePicker, Button,Upload,message,Modal } from "antd"
import {PaperClipOutlined,DeleteOutlined} from '@ant-design/icons';
import NormalSelect from '../../../../../components/Form/NormalSelect';
import { formItemLayout } from '../../../../../components/crud/FormLayoutProps'
import apiurl from '../../../../../service/apiurl';
import { httpget2, httppost2 } from '../../../../../utils/request';
import moment from 'moment'
import "./index.less"
export default function ProjectBasciInfo() {
const [form] = Form.useForm();
const [data, setData] = useState()
const [fileList, setFileList] = useState([]) //上传文件列表
const [fileIds, setFileIds] = useState([])
const [loading, setLoading] = useState(false)
const [iframeId, setIframeId] = useState('')
const [perviewOpen, setPerviewOpen] = useState(false)
const [skdisabled, setSkDisabled] = useState(true)
const optionsLevel = [
{
label: "大 (1)型",
value:"1"
},
{
label: "大 (2)型",
value:"2"
},
{
label: "中型",
value:"3"
},
{
label: "小 (1)型",
value:"4"
},
{
label: "小 (2)型",
value:"5"
},
{
label: "其他",
value:"9"
}
]
const getData = async () => {
try {
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.shuikuBasicinfo.detail)
if (res.code == 200) {
form.setFieldsValue(res.data[0])
setData(res.data[0])
if (res.data[0].files.length > 0) {
getFileInfo(res.data[0]?.files[0]?.fileId)
}
}
} catch (error) {
console.log(error);
}
}
const beforeUpload = (file) => {
const isPdf = file.type === 'application/pdf'
if (!isPdf) {
message.error("请上传pdf文件")
}
return isPdf
}
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);
}
if (info?.file.type === "application/pdf") {
let fileIds = info.fileList.map(file => {
return file.response?.data?.fileId
})
setFileIds(fileIds)
setFileList(info.fileList)
}
}
const deleteFile = (fileId) => {
let filterFile = fileList.filter(item => item.response?.data?.fileId !== fileId);
setFileList(filterFile)
}
const onFinish = async () => {
try {
let oldFiles = fileList.map(item => ({ fileId: item.response?.data?.fileId }))
const values = form.getFieldsValue();
const params = {
...data,
...values,
files:oldFiles
}
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.shuikuBasicinfo.update,params)
if (res.code == 200) {
message.success("修改成功")
setSkDisabled(true)
getData()
}
} catch (error) {
console.log(error);
}
}
const getFileInfo = async(id) => {
try {
const res = await httpget2(`${apiurl.dataResourcesCenter.projectAndWater.shuikuBasicinfo.getFile}/${id}`)
let obj ={
name: res.data.fileName,
response: {
data: {
filePath: res.data.filePath,
fileId:res.data.fileId
}
},
}
setFileList([obj])
} catch (error) {
console.log(error);
}
}
useEffect(() => {
getData()
}, [])
return (
<div className='basic-info-content'>
<Form
form={form}
{...formItemLayout}
onFinish={onFinish}
>
<Row>
<Col span={8}>
<Form.Item
label="水库名称"
name="resName"
rules={[{ required: true }]}
>
<Input allowClear style={{ width: '300px' }} disabled={skdisabled} />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="水库代码"
name="resCode"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="注册登记号"
name="regSn"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="注册登记时间"
name="regTime"
getValueFromEvent={(e, dateString) => dateString}
getValueProps={value => ({
value: value ? moment(value) : undefined
})}
>
<DatePicker allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="工程位置"
name="resLoc"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="所在河流(水系)名称"
name="basName"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="水库规模"
name="engScal"
rules={[{ required: true }]}
>
<NormalSelect
style={{ width: '300px' }}
allowClear
options={optionsLevel}
disabled={skdisabled}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="主要功能"
name="rsvFunction"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="经度"
name="lgtd"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="纬度"
name="lttd"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="设计灌溉面积(亩)"
name="designIrrArea"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="实际灌溉面积(亩)"
name="actualIrrArea"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="受益人口(人)"
name="feedPop"
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="开工日期"
name="startDate"
getValueFromEvent={(e, dateString) => dateString}
getValueProps={value => ({
value: value ? moment(value) : undefined
})}
>
<DatePicker allowClear style={{ width: '300px' }} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="竣工日期"
name="compDate"
getValueFromEvent={(e, dateString) => dateString}
getValueProps={value => ({
value: value ? moment(value) : undefined
})}
>
<DatePicker allowClear style={{ width: '300px' }} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="是否病险"
name="isDanger"
>
<NormalSelect
style={{ width: '300px' }}
allowClear
options={[
{
label: '否',
value:0,
},
{
label: '是',
value:1,
},
]}
disabled={skdisabled}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="是否有闸控制"
name="spillwayGate"
>
<NormalSelect
style={{ width: '300px' }}
allowClear
options={[
{
label: '否',
value:"0",
},
{
label: '是',
value:"1",
},
]}
disabled={skdisabled}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="工程特性表"
name=""
rules={[{ required: true }]}
>
<Upload
name='file'
action="/gunshiApp/xyt/attResBase/file/upload/singleSimple"
onChange={fileChange}
fileList={fileList}
maxCount={1}
disabled={loading}
beforeUpload={beforeUpload}
itemRender={(origin,file) => {
return (
<div style={{display:"flex",alignItems:"center",columnGap:10}}>
<PaperClipOutlined />
<span
style={{ cursor: "pointer" }}
onClick={() => { setPerviewOpen(true); setIframeId(file.response?.data?.fileId)}}
>
{file?.name}</span>
{skdisabled ? null :
<DeleteOutlined
style={{ marginLeft: 20, cursor: "pointer" }}
onClick={() => deleteFile(file.response?.data?.fileId)}
/>
}
</div>
)
}}
>
{skdisabled ? null :
<div style={{display:"flex",alignItems:"center",columnGap:10,color:"#4f85ec",cursor:skdisabled?"not-allowed":"pointer"}}>
<PaperClipOutlined />
<a style={{cursor:"pointer"}}>上传PDF文件</a>
</div>
}
</Upload>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="供水效益"
name="benefit"
labelCol={{ span: 2, offset: 0 }}
wrapperCol={{span:21,offset:0}}
>
<Input allowClear disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="工程概况"
name="projOverview"
labelCol={{ span: 2, offset: 0 }}
wrapperCol={{span:21,offset:0}}
>
<Input.TextArea allowClear style={{width:'100%',minHeight:'100px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row style={{marginTop:80}}>
<Col span={24}>
<Form.Item
wrapperCol={{span:14,offset:10}}
>
{
skdisabled ? <Button type="primary" onClick={() => setSkDisabled(false)}>编辑</Button> :
<div style={{ display: 'flex', columnGap: 20 }}>
<Button onClick={() => setSkDisabled(true)}>取消</Button>
<Button type="primary" onClick={() => { onFinish() }}>保存</Button>
</div>
}
</Form.Item>
</Col>
</Row>
</Form>
<Modal
open={perviewOpen}
width={1000}
title=""
footer={null}
style={{marginTop:"-5%"}}
onCancel={() => {
setPerviewOpen(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/attResBase/file/download/${iframeId}`)}`}
/>
</Modal>
</div>
)
}

View File

@ -0,0 +1,271 @@
import React,{useState,useEffect} from 'react'
import { Row, Col, Form, Input, DatePicker, Button,Upload,message,Modal } from "antd"
import {PaperClipOutlined,DeleteOutlined} from '@ant-design/icons';
import NormalSelect from '../../../../../components/Form/NormalSelect';
import { formItemLayout } from '../../../../../components/crud/FormLayoutProps'
import apiurl from '../../../../../service/apiurl';
import { httppost2 } from '../../../../../utils/request';
import moment from 'moment'
import "./index.less"
export default function ProjectBasciInfo() {
const [form] = Form.useForm();
const [data, setData] = useState()
const [skdisabled, setSkDisabled] = useState(true)
const getData = async () => {
try {
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.shuikuBasicinfo.detail)
form.setFieldsValue(res.data[0])
setData(res.data[0])
} catch (error) {
console.log(error);
}
}
const onFinish = async () => {
try {
const values = form.getFieldsValue();
const params = {
...data,
...values,
}
const res = await httppost2(apiurl.dataResourcesCenter.projectAndWater.shuikuBasicinfo.update,params)
if (res.code == 200) {
message.success("修改成功")
setSkDisabled(true)
getData()
}
} catch (error) {
console.log(error);
}
}
useEffect(() => {
getData()
}, [])
return (
<div className='basic-info-content'>
<Form
form={form}
// {...formItemLayout}
onFinish={onFinish}
labelCol={{ span: 8 }}
wrapperCol={{span:14}}
>
<Row>
<Col span={8}>
<Form.Item
label="坝址以上流域面积(km²)"
name="watShedArea"
rules={[{ required: true }]}
>
<Input allowClear style={{ width: '300px' }} disabled={skdisabled} />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="坝顶高程(m)"
name="crestElev"
labelCol={{ span: 5 }}
wrapperCol={{span:14}}
rules={[{ required: true }]}
>
<Input allowClear style={{width:'280px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="最大坝高(m)"
name="maxDamHeig"
labelCol={{ span: 6 }}
wrapperCol={{span:14}}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="校核洪水位(m)"
name="calFloodLev"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8} >
<Form.Item
label="总库容(万m³)"
name="totCap"
labelCol={{ span: 5 }}
wrapperCol={{span:14}}
rules={[{ required: true }]}
>
<Input allowClear style={{width:'280px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8} style={{marginLeft:"-105px"}}>
<Form.Item
label="校核洪水位时最大下泄流量(m³/s)"
name="maxCalFloodFlow"
labelCol={{ span: 11 }}
wrapperCol={{span:13}}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="设计洪水位(m)"
name="desFloodLev"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="调洪库容(万m³)"
name="storFlCap"
labelCol={{ span: 5 }}
wrapperCol={{span:14}}
rules={[{ required: true }]}
>
<Input allowClear style={{width:'280px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8} style={{marginLeft:"-125px"}}>
<Form.Item
label="设计洪水位时最大下泄流量(m³/s)"
name="maxDesFloodFlow"
labelCol={{ span: 12 }}
wrapperCol={{span:12}}
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="防洪高水位(m)"
name="uppLevFlco"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="防洪库容(万m³)"
name="flcoCap "
labelCol={{ span: 5 }}
wrapperCol={{span:14}}
>
<Input allowClear style={{width:'280px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8} style={{marginLeft:"-43px"}}>
<Form.Item
label="下游河道安全泄量(m³/s)"
name="dsSaftFlow"
labelCol={{ span: 8 }}
wrapperCol={{span:14}}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="正常蓄水位(m)"
name="normWatLev"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="兴利库容(万m³)"
name="benResCap"
labelCol={{ span: 5 }}
wrapperCol={{span:14}}
>
<Input allowClear style={{width:'280px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="汛限水位(m)"
name="flLowLimLev"
rules={[{ required: true }]}
labelCol={{ span: 6 }}
wrapperCol={{span:14}}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={8}>
<Form.Item
label="死水位(m)"
name="deadLev"
rules={[{ required: true }]}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="死库容(万m³)"
name="deadCap"
labelCol={{ span: 5 }}
wrapperCol={{span:14}}
rules={[{ required: true }]}
>
<Input allowClear style={{width:'280px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
label="堰顶高程(m)"
name="wcrstel"
rules={[{ required: true }]}
labelCol={{ span: 6 }}
wrapperCol={{span:14}}
>
<Input allowClear style={{width:'300px'}} disabled={skdisabled}/>
</Form.Item>
</Col>
</Row>
<Row style={{marginTop:80}}>
<Col span={24}>
<Form.Item
wrapperCol={{span:14,offset:10}}
>
{
skdisabled ? <Button type="primary" onClick={() => setSkDisabled(false)}>编辑</Button> :
<div style={{ display: 'flex', columnGap: 20 }}>
<Button onClick={() => setSkDisabled(true)}>取消</Button>
<Button type="primary" onClick={() => { onFinish() }}>保存</Button>
</div>
}
</Form.Item>
</Col>
</Row>
</Form>
</div>
)
}

View File

@ -0,0 +1,31 @@
import { Image } from "antd"
import zd from '../../../../assets/img/u0.png'
import qys1 from '../../../../assets/img/qys1.png'
import qys2 from '../../../../assets/img/qys2.jpg'
import qys3 from '../../../../assets/img/qys3.jpg'
import qys4 from '../../../../assets/img/qys4.png'
import './index.less'
import { useState } from "react"
const list=[
{name:'水库地理位置图',key:1,img:qys1},
{name:'水库平面布置图',key:2,img:qys2},
{name:'主坝平面布置图',key:3,img:qys3},
{name:'副坝平面布置图',key:4,img:qys4},
]
const Page = () => {
const [url,setUrl] = useState(qys1)
const tabClick =(item)=>{
setUrl(item.img)
}
return (
<div style={{ backgroundColor: '#fff', height: '100%' }}>
<div style={{ display: 'flex', justifyContent: 'start', alignItems: 'center', }}>
{list.map(item=><div className={url==item.img?"active":"tabCheck"} onClick={()=>tabClick(item)}>{item.name}</div>)}
</div>
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center',overflow:'auto',height:'calc(100% - 100px)' }}>
<Image src={url} width='80%' preview={false} />
</div>
</div>
)
}
export default Page

View File

@ -0,0 +1,47 @@
.tabCheck{
border-width: 0px;
width: 125px;
height: 36px;
background: inherit;
background-color: rgba(215, 223, 235, 1);
box-sizing: border-box;
border-width: 1px;
border-style: solid;
border-color: rgba(228, 231, 237, 1);
border-radius: 10px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
font-size: 14px;
color: #303133;
margin: 10px 0;
text-align: center;
line-height: 36px;
}
.active{
width: 125px;
height: 36px;
background: inherit;
background-color: rgba(255, 255, 255, 1);
box-sizing: border-box;
border-width: 1px;
border-style: solid;
border-color: rgba(228, 231, 237, 1);
border-bottom: 0px;
border-radius: 10px;
border-bottom-right-radius: 0px;
border-bottom-left-radius: 0px;
-moz-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
font-size: 14px;
color: #303133;
margin: 10px 0;
text-align: center;
line-height: 36px;
}

View File

@ -0,0 +1,28 @@
import { Image } from "antd"
import zd from '../../../../assets/img/u7.png'
import title from '../../../../assets/img/titleRight.png'
import './index.less'
const Page = () => {
return (
<div style={{ display: 'flex',height:'100%' }}>
<div style={{ backgroundColor: '#ffffff',width:390,height:'100%',marginRight:10 }}>
<div className="title">
<Image src={title} />保护对象
</div>
<div className="content">
水库防洪标准按50年一遇设计1000年一遇校核设计洪水位111.51校核洪水位 112.75 ,水库担负着红安县城七里坪杏花城关等城镇以及京九铁路汉麻连络线省道S234国道G230,京九铁路汉麻联络线等交通设施安全的防洪重任防洪保护人口32万
保护耕地 15 万亩
</div>
</div>
<div style={{ backgroundColor: '#ffffff',flex:1}}>
<div className="title">
<Image src={title} />转移路线示意图
</div>
<Image src={zd} width='80%' preview={false} />
</div>
</div>
)
}
export default Page

View File

@ -0,0 +1,28 @@
import { Image } from "antd"
import zd from '../../../../assets/img/u7.png'
import title from '../../../../assets/img/titleRight.png'
import './index.less'
const Page = () => {
return (
<div style={{ display: 'flex',height:'100%' }}>
<div style={{ backgroundColor: '#ffffff',width:390,height:'100%',marginRight:10 }}>
<div className="title">
<Image src={title} />保护对象
</div>
<div className="content">
水库防洪标准按50年一遇设计1000年一遇校核设计洪水位111.51校核洪水位 112.75 ,水库担负着红安县城七里坪杏花城关等城镇以及京九铁路汉麻连络线省道S234国道G230,京九铁路汉麻联络线等交通设施安全的防洪重任防洪保护人口32万
保护耕地 15 万亩
</div>
</div>
<div style={{ backgroundColor: '#ffffff',flex:1}}>
<div className="title">
<Image src={title} />转移路线示意图
</div>
<Image src={zd} width='80%' preview={false} />
</div>
</div>
)
}
export default Page

View File

@ -0,0 +1,10 @@
.title{
font-size: 16px;
color: #000000;
width: 112px;
height: 32px
}
.content{
font-size: 17px;
padding: 0 20px;
}

View File

@ -0,0 +1,296 @@
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';
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 [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 {String} params 文件fileId
*/
const download = (params) => {
let downloadLink = document.createElement("a");
downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/xyt/projectEvents/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 = (values) => {
values.eventsDate = values.eventsDate?moment(values.eventsDate).format("YYYY-MM-DD 00:00:00"):''
let oldFiles = fileList.map(item => ({fileId:item.response?.data?.fileId}) )
if (mode === 'edit') {
values.files = oldFiles;
values.id = record.id;
onEdit(apiurl.rcgl.gcdsj.edit,values)
}
if (mode === 'save') {
values.files = oldFiles
onSave(apiurl.rcgl.gcdsj.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 (mode != 'save') {
const imgFile = record?.files?.map(o => ({
name: o.fileName,
response: {
data: {
filePath: o.filePath,
fileId:o.fileId
}
},
}))
setFileList(imgFile)
}
}, [record, mode])
return (
<>
<Form
form={form}
{...formItemLayout}
onFinish={onfinish}
initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="名称"
name="name"
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="发生日期"
name="eventsDate"
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
rules={[
{
required: true,
},
]}
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="事件类型"
name="eventsType"
>
<NormalSelect
allowClear
disabled={mode==='view'}
style={{ width: "100%" }}
options={[{label:"综合大事记",value:1},{label:"专题大事记",value:2}]}
/>
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="事件内容描述"
name="eventsDesc"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'100px'}} 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/projectEvents/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">
支持扩展名.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>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '提交' : '修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
<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/projectEvents/file/download/${iframeSrc}`)}`}
/>
</Modal>
</>
);
}
export default ModalForm;

View File

@ -0,0 +1,223 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import BasicCrudModal from '../../../../components/crud/BasicCrudModal';
import { Table, Card, Modal, Form, Input, Button, Row,Col, Timeline, message, Tabs,Image } from 'antd';
import {FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons';
import { useSelector } from 'react-redux';
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 url = "http://223.75.53.141:9102/test.by-lyf.tmp"
const Page = () => {
const role = useSelector(state => state.auth.role);
const editBtn = role?.rule?.find(item => item.menuName == "编辑");
const viewBtn = role?.rule?.find(item => item.menuName == "查看");
const delBtn = role?.rule?.find(item => item.menuName == "删除");
const refModal = useRef();
const [searchVal, setSearchVal] = useState(false)
const [iframeSrc, setIframeSrc] = useState('')
const [pdfViewOPen, setPdfViewOPen] = useState(false)
const [isFetch, setIsFetch] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '名称', key: 'name', dataIndex: 'name', width: 250, ellipsis: true },
{
title: '发生日期', key: 'eventsDate', dataIndex: 'eventsDate', width: 140,
},
{
title: '事件类型', key: 'eventsType', dataIndex: 'eventsType', width: 140,
render: (value) => <span>{value == 1 ? "综合大事记" : value == 2 ? "专题大事记" : ''}</span>,
},
{
title: '事件内容描述', key: 'eventsDesc', dataIndex: 'eventsDesc', width: 300},
{
title: '操作', key: 'operation', width: 240, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={ true }
del={ true }
view={ 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.rcgl.gcdsj.delete + `/${params.id}`);
}
}
const download = (params) => {
let downloadLink = document.createElement("a");
downloadLink.href = `http://local.gunshiiot.com:18083/gunshiApp/xyt/projectEvents/file/download/${params}`;
downloadLink.download = `${params.fileName}`;
downloadLink.style.display = "none";
// 将链接添加到页面中
document.body.appendChild(downloadLink);
// 模拟点击事件,开始下载
downloadLink.click();
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.rcgl.gcdsj.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
setIsFetch(!isFetch)
}
const viewPdf = (params) => {
setIframeSrc(params)
setPdfViewOPen(true)
}
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%",overflowY:"auto"}}>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
onSave={command('save')}
role={role}
/>
</Card>
<div className="ant-card-body" style={{ padding: "20px 0 0 0" }}>
<Tabs defaultActiveKey="1">
<Tabs.TabPane tab="列表" key="1">
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/>
</Tabs.TabPane>
<Tabs.TabPane tab="时间轴" key="2">
<div className='time-line'>
<Timeline>
{tableProps.dataSource.map((item, index) => (
<Timeline.Item key={index}>
<div className='time-line-item'>
<span style={{width:100}}>{item.eventsDate}</span>
<div className='item-right'>
<span>{item.eventsDesc}</span>
<div style={{ display: "flex"}}>
<span>附件</span>
<Row gutter={[16]} style={{flex:1}}>
{
item.files.length > 0 && item.files.map(file => {
return (
<Col span={12}>
<div className="file-item" style={{width:"100%"}}>
<div className='file-description'>
{file.fileName.indexOf('.docx') > -1 ?
<div
onClick={() => { download(file.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileWordOutlined
style={{ fontSize: 40 }}
/>
</div>
:
file.fileName.indexOf('.pdf') > -1 ?
<div
onClick={() => { viewPdf(file?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FilePdfOutlined style={{ fontSize: 40 }} />
</div>
:
file.fileName.indexOf('.zip') > -1 ?
<div
onClick={() => { download(file?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileZipOutlined style={{ fontSize: 40 }} />
</div>
:
file.fileName.indexOf('.xlsx') > -1 ?
<div
onClick={() => { download(file?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileExcelOutlined style={{ fontSize: 40 }} />
</div>
:
<Image width={60} src={url +file?.filePath} alt='' />
}
<span>{file.fileName}</span>
</div>
</div>
</Col>
)
})
}
</Row>
</div>
</div>
</div>
</Timeline.Item>
))}
</Timeline>
</div>
</Tabs.TabPane>
</Tabs>
</div>
</div>
<BasicCrudModal
width={1000}
ref={refModal}
title=""
component={ModalForm}
onCrudSuccess={successCallback}
// onCrudSuccess={()=>{refresh({addvcd:localStorage.getItem('ADCD6')})}}
/>
</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/projectEvents/file/download/${iframeSrc}`)}`}
/>
</Modal>
</>
);
}
export default Page;

View File

@ -0,0 +1,30 @@
.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;
}
}
.time-line{
width: 50%;
margin-left: 6%;
margin-top: 1%;
.time-line-item{
display: flex;
// align-items: center;
column-gap: 20px;
.item-right{
flex:1
}
}
}

View File

@ -0,0 +1,59 @@
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 addBtn = role?.rule?.find(item => item.menuName == "新增");
const searchBtn = role?.rule?.find(item => item.menuName == "查询");
const [form] = Form.useForm();
const onFinish = (values) => {
let dataSo;
if (values.tm) {
dataSo = {
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, dataSo});
}
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="名称" name="name">
<Input allowClear style={{width:'150px'}}/>
</Form.Item>
<Form.Item label="发生日期" name="tm">
<RangePicker
allowClear
showTime
style={{ width: "300px" }}
format="YYYY-MM-DD HH:mm:ss"
/>
</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>
</div>
</>
);
}
export default ToolBar;

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;