Merge branch 'lsf-dev'

lsf-dev
李神峰 2024-09-24 17:00:17 +08:00
commit ba59774b4b
34 changed files with 3369 additions and 80 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -88,7 +88,7 @@ const DashboardLayout: React.FC = () => {
navigate('/login') navigate('/login')
}else{ }else{
dispatch.auth.loadMenu(); dispatch.auth.loadMenu();
document.title = "小玉潭水库综合管理系统"; document.title = "檀树岗水库现代化运行管理矩阵平台";
} }
},[]) },[])
@ -148,7 +148,7 @@ const DashboardLayout: React.FC = () => {
{/*<span className="app-title">{TITLE}{SUBTITLE}</span>*/} {/*<span className="app-title">{TITLE}{SUBTITLE}</span>*/}
<span className="app-title lf"> <span className="app-title lf">
<img src={`${process.env.PUBLIC_URL}/assets/shuili.png`} alt=""/> <img src={`${process.env.PUBLIC_URL}/assets/shuili.png`} alt=""/>
<span></span> <span></span>
</span> </span>
<div className="topMenu lf"> <div className="topMenu lf">
<TopMenu menu={menu} menuIndexes={menuIndexes} /> <TopMenu menu={menu} menuIndexes={menuIndexes} />

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

@ -380,11 +380,19 @@ export async function loadMenu(): Promise<MenuItem[]> {
] ]
}, },
{ { id: id(), title: '全周期', redirect: '/mgr/sq/qzq/gcdsj',
id: id(), title: '全周期', redirect: '/mgr/sq/qzq/gcdsj',
children: [ children: [
{ id: id(), title: '工程大事记', path: '/mgr/sq/qzq/gcdsj' }, { id: id(), title: '工程大事记', path: '/mgr/sq/qzq/gcdsj'},
{ 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

@ -5,7 +5,7 @@ const pubapi_old = 'https://owrsvr.cloudowr.cn/svr'
const pubapi = 'https://owrsvr.cloudowr.cn/pubapi' const pubapi = 'https://owrsvr.cloudowr.cn/pubapi'
const zdkapi = 'https://slt-sh.chutianyun.gov.cn:8002' //中电科的市级平台 const zdkapi = 'https://slt-sh.chutianyun.gov.cn:8002' //中电科的市级平台
const service_fxdd = '/gunshiApp/tsg' const service_fxdd = '/gunshiApp/tsg'
const service_xyt = '/gunshiApp/xyt'//登陆先用小玉潭 const service_xyt = '/gunshiApp/tsg'//登陆先用小玉潭
const service_shzh = '/shzh' const service_shzh = '/shzh'
const apiurl = { const apiurl = {
fxya: { fxya: {
@ -853,6 +853,7 @@ const apiurl = {
//实时水情 //实时水情
sssq: { sssq: {
selectList:service_fxdd + "/real/rain/list",
list: service_fxdd + '/river/water/list', //实时水情-河道水情列表 list: service_fxdd + '/river/water/list', //实时水情-河道水情列表
warn: service_fxdd + '/current/situation/rv/warn', //实时水情-河道水情统计 warn: service_fxdd + '/current/situation/rv/warn', //实时水情-河道水情统计
summaryInfo: service_fxdd + '/river/water/summaryInfo', //实时水情-河道水情汇总 summaryInfo: service_fxdd + '/river/water/summaryInfo', //实时水情-河道水情汇总
@ -861,7 +862,7 @@ const apiurl = {
reservoirsummaryInfo: service_fxdd + '/reservoir/water/summaryInfo', //实时水情-水库水情汇总 reservoirsummaryInfo: service_fxdd + '/reservoir/water/summaryInfo', //实时水情-水库水情汇总
//河道弹框详情 //河道弹框详情
monitor: service_fxdd + '/river/water/monitor/data', //监测数据 monitor: service_fxdd + '/river/water/monitor/data', //监测数据
detail: service_fxdd + '/reservoir/water/detail', //监测数据-下方表格 detail: service_fxdd + '/river/water/detail', //监测数据-下方表格
zqrl: service_fxdd + '/river/water/zqrl', //水位流量关系 zqrl: service_fxdd + '/river/water/zqrl', //水位流量关系
channel: service_fxdd + '/reservoir/water/image/channel', //图像监测-视角 channel: service_fxdd + '/reservoir/water/image/channel', //图像监测-视角
imageinfo: service_fxdd + '/reservoir/water/image/info', //图像监测-列表 imageinfo: service_fxdd + '/reservoir/water/image/info', //图像监测-列表

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 Qzqda from './sq/qzq/qzqda' import Qzqda from './sq/qzq/qzqda'
// 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,9 @@ import Qzqda from './sq/qzq/qzqda'
// 四制 - 组织机构查看 // 四制 - 组织机构查看
import Zzjgck from './sz/zzjgck' import Zzjgck from './sz/zzjgck'
import Zrrgl from './sz/zrrgl'
import Pxjhgl from './sz/pxjhgl'
import Pxjlgl from './sz/pxjlgl'
import Flfg from './sz/flfg' import Flfg from './sz/flfg'
import Zdgl from './sz/zdgl' import Zdgl from './sz/zdgl'
import Ajdj from './sz/szzf/ajdj' import Ajdj from './sz/szzf/ajdj'
@ -153,6 +159,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 /> },
@ -209,7 +220,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 /> },
@ -242,6 +253,9 @@ const AppRouters: React.FC = () => {
// 四制-组织机构查看 // 四制-组织机构查看
{ path: 'sz/gltx/zzjgck', element: <Zzjgck /> }, { path: 'sz/gltx/zzjgck', element: <Zzjgck /> },
{ path: 'sz/gltx/zrrgl', element: <Zrrgl /> },
{ path: 'sz/pxgl/pxjhgl', element: <Pxjhgl /> },
{ path: 'sz/pxgl/pxjlgl', element: <Pxjlgl /> },
{ path: 'sz/flfg', element: <Flfg /> }, { path: 'sz/flfg', element: <Flfg /> },
{ path: 'sz/zdgl', element: <Zdgl /> }, { path: 'sz/zdgl', element: <Zdgl /> },
{ path: 'sz/szzf/ajdj', element: <Ajdj /> }, { path: 'sz/szzf/ajdj', element: <Ajdj /> },

View File

@ -77,10 +77,12 @@ function DrpSearch({record}) {
], ],
} }
if (record.stcd) {
setParams(option) 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 }),
], ],
} }
if (record?.stcd && record.source) {
setParams(option) setParams(option)
getData(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

@ -20,7 +20,6 @@ function DrpSearch({record}) {
const option = useMemo(() => { const option = useMemo(() => {
if (data && data.length) { if (data && data.length) {
return drpOption({data,wrz:record.wrz,grz:record.grz}); return drpOption({data,wrz:record.wrz,grz:record.grz});
} }
}, [data]) }, [data])
@ -50,30 +49,6 @@ 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,
@ -84,15 +59,18 @@ function DrpSearch({record}) {
moment().add(1, 'hour').set({ minute: 0, second: 0 }), moment().add(1, 'hour').set({ minute: 0, second: 0 }),
], ],
} }
if (record.stcd) {
setParams(option) setParams(option)
setInitialDateRange(option) setInitialDateRange(option)
getData(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: "320px"}} <RangePicker showTime allowClear style={{width: "320px"}}
onChange={searchTm} onChange={searchTm}
@ -103,11 +81,11 @@ function DrpSearch({record}) {
<Button type="primary" onClick={doSearch} style={{ marginLeft: "10px" }}>查询</Button> <Button type="primary" onClick={doSearch} style={{ marginLeft: "10px" }}>查询</Button>
<Button style={{ marginLeft: "10px" }} onClick={() => { handleReset()}}>重置</Button> <Button style={{ marginLeft: "10px" }} onClick={() => { handleReset()}}>重置</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
@ -119,7 +97,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,71 @@
import React, { useEffect, useState } from 'react'
import { zqrl, list} from "../../../../service/sssq";
import Sssw from './sssw';
import Sjcx from '../../../Home/MapCtrl/components/Sqjcsj/index'
import "./index.less"
import { Table } from 'antd';
export default function Sksq() {
const columns = [
{title: '水位(m)', key: 'z', dataIndex: 'z', align: 'center'},
{title: '流量(m³/s)', key: 'q', dataIndex: 'q', align: 'center'},
]
const [tableData, setTableData] = useState([])
const [swtableData, setSwTableData] = useState([])
const getData = async (params) => {
let res = await list(params)
setTableData(res);
getSwTableData(res[0]?.stcd)
}
const getSwTableData = async (stcd) => {
setSwTableData(await zqrl(stcd));
};
useEffect(() => {
getData({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 style={{display:"flex",alignItems:"center"}}>
<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 className='comomn-title'>
<div style={{display:"flex",alignItems:"center"}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>水位流量关系表</span>
</div>
</div>
<div className='sssw-content' style={{padding:10}}>
<Table
dataSource={swtableData}
rowKey="adcd"
columns={columns}
pagination={false}
/>
</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,37 @@
import React from 'react'
import {Divider} from "antd"
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?.z ? data?.z.toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">警戒水位:</div>
<div className="row-value">{data?.wrz ? data?.wrz.toFixed(2) : '-'}</div>
<Divider type="vertical" style={{height:25,background:"#000",width:2,margin:"0 30px"}}/>
<div className="row-value" style={{width:"20%"}}>{(data.wrz && data?.z) ? (data.wrz - data?.z).toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
<div className="infoItem">
<div className="row-key">危险水位:</div>
<div className="row-value">{data.grz ? data.grz.toFixed(2) : '-'}</div>
<Divider type="vertical" style={{height:25,background:"#000",width:2,margin:"0 30px"}}/>
<div className="row-value" style={{width:"20%"}}>{(data.grz && data?.z) ? (data.grz - data?.z).toFixed(2):'-'}</div>
<div className="row-unit">m</div>
</div>
</div>
</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 style={{display:"flex",alignItems:"center"}}>
<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,93 @@
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';
import NormalSelect from '../../../../components/Form/NormalSelect';
export default function Sksq() {
const [tableData1, setTableData1] = useState([])
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||[])
}
const [selectList, setSelectList] = useState([])
const [selected, setSelected] = useState('')
const [stcdItem, setStcdItem] = useState({})
const getList = async() => {
try {
const res = await httppost2(apiurl.sssq.selectList)
setSelectList(res.data.map(item => ({ label: item.stnm, value: item.stcd,...item})))
setSelected(res.data[0].stcd)
setStcdItem(res.data[0])
} catch (error) {
console.log(error);
}
}
const handleChange = (e) =>{
setSelected(e);
setStcdItem(selectList.find(item => item.stcd === e))
}
useEffect(() => {
getList()
}, [])
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 style={{display:"flex",alignItems:"center",columnGap:0}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时雨情</span>
</div>
<div style={{display:"flex",columnGap:10,width:"45%",alignItems:"center"}}>
<span style={{width:"18%"}}>站点</span>
<NormalSelect
style={{ width: '77%' }}
allowClear
options={selectList}
value={selected}
onChange={(e) => { handleChange(e)}}
/>
</div>
</div>
<div className='sssw-content'>
<Sssw data={stcdItem || {}}/>
</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={{stcd:selected,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,52 @@
import React,{useState,useEffect} from 'react'
import {queryStPptnDetails} from '../../../../service/ssyq'
export default function Sssw({ data }) {
const [detail, setDetail] = useState({})
const getDetail = async (data) => {
setDetail(await queryStPptnDetails(data))
}
useEffect(() => {
if (data.stcd) {
getDetail(data.stcd)
}
}, [data])
return (
<div className="ssjc">
<div className="root">
<div className="realinfo">
<div
className='report-time'
>雨情最新上报时间: {detail?.tm}</div>
<div className='drp-content'>
<div className='drp-item'>
<div className='value'>{detail?.h1 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近1小时</div>
</div>
<div className='drp-item'>
<div className='value'>{detail?.h3 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近3小时</div>
</div>
<div className='drp-item'>
<div className='value'>{detail?.h6 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近6小时</div>
</div>
<div className='drp-item'>
<div className='value'>{detail?.h12 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近12小时</div>
</div>
<div className='drp-item'>
<div className='value'>{detail?.h24 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近24小时</div>
</div> <div className='drp-item'>
<div className='value'>{detail?.h48 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近48小时</div>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1,392 @@
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 [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 pdf文件预览
* @param {String} params 文件预览url
*/
const viewPdf = (params) => {
setIframeSrc(params)
setPdfViewOPen(true)
}
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 style={{height:"65vh",overflowY:"auto"}}>
<div className='basic-info'>基本信息</div>
{/* <Divider /> */}
<Form
form={form}
{...formItemLayout}
// initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="培训计划"
name="teamName"
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="培训分类"
name="teamName"
>
<NormalSelect disabled={true} style={{ width: '100%' }} allowClear options={types} />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={true} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="标题名称"
name="teamName"
rules={[{ required: true }]}
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训时段"
name="address"
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="培训时长(小时)"
name="address"
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训地点"
name="remark"
rules={[{ required: true }]}
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="主办单位"
name="remark"
rules={[{ required: true }]}
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训内容"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input.TextArea disabled={true} style={{width:'100%',minHeight:'50px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训范围"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input disabled={true} style={{width:'100%',minHeight:'50px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="参训人员"
name="remark"
>
<Input min={0} disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="参加人数"
name="address"
>
<Input disabled={true} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="填报人"
name="address"
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="登记日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={true} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训签到表"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
</Form.Item>
</Col>
</Row>
<div className='basic-info' style={{display:"flex",justifyContent:"space-between"}}>
<span>其他信息</span>
</div>
<Row>
<Col span={24}>
<Form.Item
label="附件"
name="fieldId"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<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'} >
<DeleteOutlined />
</div>
</div>
</Col>
)
})
}
</Row>
</Form.Item>
</Col>
</Row>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '保存' :
mode === "similarSave" ? "保存" :
'修改'}
</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/rescue/goods/file/download/${iframeSrc}`)}`}
/>
</Modal>
</div>
);
}
export default ModalForm;

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

@ -0,0 +1,490 @@
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 style={{height:"65vh",overflowY:"auto"}}>
<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={24}>
<Form.Item
label="主办单位"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="开始培训日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="结束培训日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={mode==='view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训天数(天)"
name="address"
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="培训期数(期)"
name="address"
rules={[{ required: true }]}
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训地点"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训内容"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'50px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训范围"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="参训人员"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="参训人数(人)"
name="address"
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="联系人"
name="address"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="联系电话"
name="address"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="填报人"
name="address"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="状态"
name="address"
rules={[{ required: true }]}
>
<NormalSelect disabled={mode==='view'} style={{width:'100%'}} allowClear options={[{label:"有效",value:1},{label:"无效",value:2}]} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="登记日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={true} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<div className='basic-info' style={{display:"flex",justifyContent:"space-between"}}>
<span>其他信息</span>
</div>
<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>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '保存' :
mode === "similarSave" ? "保存" :
'修改'}
</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/rescue/goods/file/download/${iframeSrc}`)}`}
/>
</Modal>
</div>
);
}
export default ModalForm;

View File

@ -0,0 +1,215 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import { useSelector } from 'react-redux';
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card,Modal,Image,Input,Button,Row,Col,message } from 'antd';
import ToolBar from './toolbar';
import ModalForm from './form';
import RecordDetails from "./RecordForm"
import apiurl from '../../../service/apiurl';
import usePageTable from '../../../components/crud/usePageTable2';
import { createCrudService } from '../../../components/crud/_';
import { CrudOpRender_text } from '../../../components/crud/CrudOpRender';
import { exportFile } from '../../../utils/tools.js';
import { httppost5 } from '../../../utils/request';
const Page = () => {
const url = "http://223.75.53.141:9102/test.by-lyf.tmp"
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 [pxRecordOpen, setPxRecordOpen] = 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 columns1 = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '培训日期', key: 'teamName', dataIndex: 'teamName', width: 150, ellipsis: true },
{
title: '培训时段', key: 'personCount', dataIndex: 'personCount', width: 150,
},
{ title: '参加人数', key: 'address', dataIndex: 'address', width: 100 },
{
title: '参训人员', key: 'managementUnit', dataIndex: 'managementUnit', width: 200,ellipsis: true
},
{
title: '培训签到表', key: 'teamLeader', dataIndex: 'teamLeader', width: 150,
render: (value) => <div>{value ? <a onClick={()=>reviewPic(value)}> {value} </a>: ''}</div>
},
{
title: '操作', key: 'operation', width: 100, fixed: 'right',align: 'center',
render: (value, row, index) => (
<a onClick={() => {setPxRecordOpen(true)}}>查看</a>
)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const width1 = useMemo(() => columns1.reduce((total, cur) => total + (cur.width), 0), [columns1]);
const [pxOpen, setPxOpen] = useState(false)
const [imgVisible, setImgVisible] = useState(false)
const [imgList, setImgList] = useState([])
const reviewPic = (arrPic) => {
if (arrPic.length > 0) {
setImgVisible(true)
setImgList(arrPic)
}
}
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}`);
}else if (type === 'similarAdd') {
refModal.current.showSimilarSave(params);
} else {
// 培训记录
setPxOpen(true);
// setPxItem
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.fxzb.qsdw.zq.page).find_noCode);
const { tableProps:tableProps1, search:search1 } = usePageTable(createCrudService(apiurl.fxzb.qsdw.zq.page).find_noCode);
/**
* @description 处理成功的回调
*/
const successCallback = () => {
refresh()
}
// 导出
const exportExcel = () => {
let params = {
...searchVal,
id:1
}
httppost5(apiurl.gcaqjc.gcaqfx.jrx.export, params).then(res => {
exportFile(`培训计划管理.xlsx`,res.data)
})
}
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}
callback={refresh}
exportFile={exportExcel}
/>
</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>
{/* 培训记录 */}
<Modal
title="培训记录"
width={1000}
open={pxOpen}
destroyOnClose
footer={null}
onCancel={() => {
setPxOpen(false);
}}
>
<Table
columns={columns1}
rowKey="inx"
{...tableProps1}
dataSource={[{teamName:1}]}
scroll={{ x: width1, y: "calc( 100vh - 400px )" }} />
</Modal>
{/* 培训记录查看 */}
<Modal
title="查看"
width={800}
open={pxRecordOpen}
destroyOnClose
footer={null}
onCancel={() => {
setPxRecordOpen(false);
}}
>
<RecordDetails mode={"view"} record={{}} />
</Modal>
<div style={{ display: "none" }}>
<Image.PreviewGroup
preview={{
visible:imgVisible,
onVisibleChange: (vis) => setImgVisible(vis),
}}
>
{
imgList.length > 0 ? imgList.map(item => (
<Image src={ url + item.filePath} key={item?.id}/>
))
: null
}
</Image.PreviewGroup>
</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,147 @@
import React, { useEffect,useState } from 'react';
import { Form, Upload, Button,Row, Col, Input, DatePicker, message,Modal } from 'antd';
import {RightOutlined,LeftOutlined,FileExcelOutlined,DeleteOutlined} from '@ant-design/icons';
import { createCrudService } from '../../../components/crud/_';
import apiurl from '../../../service/apiurl';
import { httppost5 } from '../../../utils/request';
import { exportFile } from '../../../utils/tools';
import moment from 'moment';
const { Dragger } = Upload;
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFile }) => {
const [form] = Form.useForm();
const addBtn = role?.rule?.find(item => item.menuName == "新增")|| true;
const searchBtn = role?.rule?.find(item => item.menuName == "查询") || true;
const [exportOPen, setExportOPen] = useState(false)
const [fileList, setFileList] = useState([]) //上传文件列表
const [loading, setLoading] = useState(false)
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});
}
const beforeUpload = (file) => {
const accept = [".xlsx",".xls"]
const fileType = file?.name.split(".");
const fileDate = fileType.slice(-1);
const isEecel = accept.includes(`.${fileDate[0]}`)
if (!isEecel) {
message.error('请上传.xls .xlsx格式的文件');
}
return isEecel ? true : Upload.LIST_IGNORE;
};
const fileChange = (info) => {
console.log(info);
if (info.file.status === "done") {
setLoading(false);
setExportOPen(false)
callback()
}
if (info.file.status === "uploading") {
setLoading(true);
}
if (info.file.status === "error") {
message.error("文件上传失败")
setLoading(false);
}
setFileList(info.fileList)
}
const downTemplate = ()=>{
httppost5(apiurl.rcgl.zbgl.zbb.import, {}).then(res => {
exportFile(`培训计划管理.xlsx`,res.data)
})
}
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={() => {setExportOPen(true)}}>导入</Button>
</Form.Item><Form.Item>
<Button onClick={()=>exportFile()}>导出</Button>
</Form.Item>
</Form>
</div>
{/* 导入 */}
<Modal
open={exportOPen}
width={700}
title="仅支持表格文件上传,请按照模板示例数据填写"
destroyOnClose
onCancel={() => setExportOPen(false)}
footer={null}
>
<Row>
<Col span={24}>
<Dragger
name='file'
// multiple
action="/gunshiApp/xyt/rota/importData"
onChange={fileChange}
beforeUpload={beforeUpload}
onDrop={(info) => { console.log(info); }}
fileList={fileList}
disabled={loading}
accept=".xls, .xlsx"
>
<p className="ant-upload-text">点击或拖拽文件到此区域上传</p>
<p className="ant-upload-hint">
支持扩展名.xls .xlsx
</p>
</Dragger>
</Col>
</Row>
<Row>
<Col span={24} style={{ textAlign: 'right',marginTop:15 }}>
<Button onClick={downTemplate} type="primary" style={{marginRight:10}}>下载模板</Button>
{/* <Button type="primary" onClick={() => {}}>提交</Button> */}
</Col>
</Row>
</Modal>
</>
);
}
export default ToolBar;

View File

@ -0,0 +1,41 @@
import React, { useEffect,useState } from 'react';
import { Form, Upload, Button,Row, Col, Input, DatePicker, message,Modal } from 'antd';
import NormalSelect from '../../../components/Form/NormalSelect';
const ToolBar = ({ setSearchVal }) => {
const [form] = Form.useForm();
const types = [
{
label: '培训期数',
value: 1
},
{
label: '培训人次',
value: 2
},
]
return (
<>
<div style={{display:'flex',justifyContent:'space-between'}}>
<Form form={form} className='toolbarBox' layout="inline" onValuesChange={(e) => {setSearchVal(e)}}>
<Form.Item label="统计维度" name="teamName">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item>
<Form.Item label="选择年份" name="tm">
<DatePicker
allowClear
showTime
style={{ width: "150px" }}
picker='year'
/>
</Form.Item>
</Form>
</div>
</>
);
}
export default ToolBar;

610
src/views/sz/pxjlgl/form.js Normal file
View File

@ -0,0 +1,610 @@
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 jh = [
{
label: "工程测量业务知识",
value:1
},
{
label: "工程管理标准化业务知识",
value:2
},{
label: "消防安全知识培训",
value:3
},{
label: "水雨情测报培训",
value:4
}
]
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)
const [fileList1, setFileList1] = useState([]) //上传文件列表
const [fileIds1, setFileIds1] = useState([])
const [iframeSrc1, setIframeSrc1] = useState('')
const [pdfViewOPen1, setPdfViewOPen1] = useState(false)
const [loading1, setLoading1] = 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();
}
const download1 = (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)
}
const fileChange1 = (info) => {
if (info.file.status === "done") {
setLoading1(false);
}
if (info.file.status === "uploading") {
setLoading1(true);
}
if (info.file.status === "error") {
message.error("文件上传失败")
setLoading1(false);
}
let fileIds = info.fileList.map(file => {
return file.response?.data?.fileId
})
setFileIds1(fileIds)
setFileList1(info.fileList)
}
/**
* @description pdf文件预览
* @param {String} params 文件预览url
*/
const viewPdf = (params) => {
setIframeSrc(params)
setPdfViewOPen(true)
}
const viewPdf1 = (params) => {
setIframeSrc1(params)
setPdfViewOPen1(true)
}
const onfinish = () => {
let values = form.getFieldsValue();
values.details = details;
values.validStartDate = values.dateRangeSo&&moment(values.dateRangeSo[0]).format("YYYY-MM-DD")
values.validEndDate = values.dateRangeSo&&moment(values.dateRangeSo[1]).format("YYYY-MM-DD")
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)
}
const deleteFile1 = (fileId) => {
console.log(fileId);
let filterFile = fileList1.filter(item => item.response?.data?.fileId !== fileId);
setFileList1(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 style={{height:"65vh",overflowY:"auto"}}>
<div className='basic-info'>基本信息</div>
{/* <Divider /> */}
<Form
form={form}
{...formItemLayout}
// initialValues={record}
>
<Row>
<Col span={12}>
<Form.Item
label="培训计划"
name="teamName"
>
<NormalSelect disabled={mode==='view'} style={{width:'100%'}} allowClear options={jh}/>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="培训分类"
name="teamName"
>
<NormalSelect disabled={mode === 'view'} style={{ width: '100%' }} allowClear options={types} />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={mode === 'view'} format={'YYYY-MM-DD'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="标题名称"
name="teamName"
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训时段"
name="address"
>
<Input disabled={mode === 'view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="培训时长(小时)"
name="address"
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="培训地点"
name="remark"
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="主办单位"
rules={[{ required: true }]}
name="remark"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训内容"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input.TextArea disabled={mode==='view'} style={{width:'100%',minHeight:'50px'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="培训范围"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="参训人员"
name="remark"
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="参加人数"
name="address"
>
<InputNumber min={0} disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="填报人"
rules={[{ required: true }]}
name="address"
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="登记日期"
name="startDate"
rules={[{ required: true }]}
getValueFromEvent={(e,dateString) => dateString}
getValueProps={(value) => ({ value: value ? moment(value) : undefined })}
>
<DatePicker disabled={true} format={'YYYY-MM-DD'} 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={fileChange1}
onDrop={(info) => { console.log(info.dataTransfer.files); }}
fileList={fileList1}
disabled={loading1}
// 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]}>
{
fileList1.length > 0 && fileList1.map(file => {
return (
<Col span={12}>
<div className="file-item" style={{width:"75%"}}>
<div className='file-description'>
{file.name.indexOf('.docx') > -1 ?
<div
onClick={() => { download1(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileWordOutlined
style={{ fontSize: 40 }}
/>
</div>
:
file.name.indexOf('.pdf') > -1 ?
<div
onClick={() => { viewPdf1(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FilePdfOutlined style={{ fontSize: 40 }} />
</div>
:
file.name.indexOf('.zip') > -1 ?
<div
onClick={() => { download1(file.response?.data?.fileId) }}
style={{ cursor: 'pointer' }}
>
<FileZipOutlined style={{ fontSize: 40 }} />
</div>
:
file.name.indexOf('.xlsx') > -1 ?
<div
onClick={() => { download1(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>
<div className='basic-info' style={{display:"flex",justifyContent:"space-between"}}>
<span>其他信息</span>
</div>
<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>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '保存' :
mode === "similarSave" ? "保存" :
'修改'}
</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/rescue/goods/file/download/${iframeSrc}`)}`}
/>
</Modal>
<Modal
open={pdfViewOPen1}
width={1000}
title=""
footer={null}
style={{marginTop:"-5%"}}
onCancel={() => {
setPdfViewOPen1(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/${iframeSrc1}`)}`}
/>
</Modal>
</div>
);
}
export default ModalForm;

View File

@ -0,0 +1,156 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react';
import { useSelector } from 'react-redux';
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card,Modal,Image,Input,Button,Row,Col,message } from 'antd';
import ToolBar from './toolbar';
import ChartToolBar from './chartToolbar';
import ModalForm from './form';
import apiurl from '../../../service/apiurl';
import options from "./options";
import ReactEcharts from 'echarts-for-react';
import usePageTable from '../../../components/crud/usePageTable2';
import { createCrudService } from '../../../components/crud/_';
import { CrudOpRender_text } from '../../../components/crud/CrudOpRender';
import "./index.less"
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 [searchChartVal, setSearchChartVal] = useState(false)
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align:"center" },
{ title: '培训日期', key: 'teamName', dataIndex: 'teamName', width: 200, ellipsis: true },
{
title: '标题', key: 'personCount', dataIndex: 'personCount', width: 200,ellipsis: true
},
{ title: '主办单位', key: 'address', dataIndex: 'address', width: 150 },
{
title: '培训内容', key: 'managementUnit', dataIndex: 'managementUnit', width: 200,ellipsis: true
},
{ title: '参训人员', key: 'teamName', dataIndex: 'teamName', width: 200, ellipsis: true },
{ title: '培训地点', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, ellipsis: true },
{ title: '填报人', key: 'phone', dataIndex: 'phone', width: 150, ellipsis: true },
{ title: '登记日期', key: 'teamLeader', dataIndex: 'teamLeader', width: 150, ellipsis: true },
{
title: '操作', key: 'operation', width: 200, fixed: 'right',align: 'center',
render: (value, row, index) => (
<CrudOpRender_text
edit={editBtn ? true : false}
del={delBtn ? true : false}
view={viewBtn ? true : false}
command={(cmd) => () => command(cmd)(row)} />)
},
];
const width = useMemo(() => columns.reduce((total, cur) => total + (cur.width), 0), [columns]);
const pxOptions = useMemo(() => {
return options()
}, [])
const command = (type) => (params) => {
if (type === 'save') {
refModal.current.showSave();
} 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()
}
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%" }}>
<div style={{ width: "100%", height: "35vh", marginBottom: 20, padding: 10,display:"flex",columnGap:10 }}>
<div className='pxrecord-title-left'>
<div className='first-item'>
<img src={`${process.env.PUBLIC_URL}/assets/images/qishu.jpg`} alt='' />
<div className='children-itm'>
<span>本年培训期数</span>
<span>计划/实际</span>
<span><span style={{fontSize:22,fontWeight:"bold"}}>26</span>&nbsp;期/
<span style={{fontSize:22,fontWeight:"bold"}}>26</span>&nbsp;</span>
</div>
</div>
<div className='second-item'>
<img src={`${process.env.PUBLIC_URL}/assets/images/renchi.jpg`} alt='' />
<div className='children-itm'>
<span>本年培训期数</span>
<span>计划/实际</span>
<span><span style={{fontSize:22,fontWeight:"bold"}}>26</span>&nbsp;人次/
<span style={{fontSize:22,fontWeight:"bold"}}>26</span>&nbsp;</span>
</div>
</div>
</div>
<div className='pxrecord-title-right'>
<div className='chart-tool'>
<ChartToolBar
setSearchVal={setSearchVal}
/>
</div>
<div className='chart-box'>
<ReactEcharts
option={pxOptions || {}}
style={{ width: "100%", height: '100%' }}
notMerge={true}
/>
</div>
</div>
</div>
<Card className='nonebox'>
<ToolBar
setSearchVal={setSearchVal}
onSave={command('save')}
role={role}
callback={refresh}
/>
</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,59 @@
.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;
}
}
.pxrecord-title-left{
width: 300px;
.first-item,.second-item{
display: flex;
align-items: center;
justify-content: center;
column-gap: 10px;
width: 300px;
height: 16vh;
padding: 20px;
img{
width: 80px;
height: 60px;
}
.children-itm{
display: flex;
flex-direction: column;
}
}
.first-item{
background: #e4f4f8;
margin-bottom: 10px;
}
.second-item{
background: #e9f4ff;
}
}
.pxrecord-title-right{
display: flex;
flex:1;
background-color: #f4f8ff;
flex-direction: column;
.chart-tool{
margin-left: auto;
}
.chart-box{
height: calc(320px - 46px);
}
}

View File

@ -0,0 +1,117 @@
export default function options() {
var dataGDP = [900, 500, 1632.33, 1100, 400]
var dataGrowth = [2, 2.1, 3, 2.5, 2.1]
var xAxisData = ['2019年', '2020年', '2021年', '2022年', '2023年']
return {
animation: true,
tooltip: {
trigger: 'axis',
},
grid: {
top: '15%',
bottom: '15%',
right: '8%',
left: '7%',
},
legend: {
show: true,
left: "10%",
top: "-1%",
itemWidth: 11,
itemHeight: 10,
},
xAxis: {
data:xAxisData,
axisLine: {
show: true // 隐藏X轴轴线
},
axisTick: {
show: true // 隐藏X轴轴线
},
axisLabel: {
show: true,
margin: 14,
}
},
yAxis: [
{
type: 'value',
offset: 10,
axisTick: {
show: false
},
axisLine: {
show: false,
},
axisLabel: {
show: true,
margin: 0,
fontSize: 18,
}
},
{
type: 'value',
name: '(%)',
offset: 10,
nameTextStyle: {
color: 'rgba(255,255,255,0.5)',
fontSize: '12px'
},
axisTick: {
show: false
},
axisLine: {
show: false,
},
axisLabel: {
show: true,
fontSize: 18,
formatter: '{value}%'
}
}
],
series: [
{
name: '计划期数',
type: 'bar',
barWidth: 25,
data: dataGDP,
itemStyle:{
color:"#6295fa"
}
},
{
name: '实际期数',
type: 'bar',
barWidth: 25,
data: dataGDP,
itemStyle:{
color:"#62daab"
}
},
{
name: '完成率',
type: 'line',
yAxisIndex: 1,
showSymbol:false,
smooth: false, // 平滑曲线显示
lineStyle: {
width: 2,
color: '#5d7092'
},
itemStyle: {
color: '#5d7092',
shadowColor: '#5d7092',
shadowBlur: 10,
borderColor: '#5d7092',
borderWidth: 2
},
data: dataGrowth,
}
]
}
}

View File

@ -0,0 +1,91 @@
import React, { useEffect,useState } from 'react';
import { Form, Upload, Button,Row, Col, Input, DatePicker, message,Modal } from 'antd';
import {RightOutlined,LeftOutlined,FileExcelOutlined,DeleteOutlined} from '@ant-design/icons';
import { createCrudService } from '../../../components/crud/_';
import apiurl from '../../../service/apiurl';
import { httppost5 } from '../../../utils/request';
import { exportFile } from '../../../utils/tools';
import moment from 'moment';
import NormalSelect from '../../../components/Form/NormalSelect';
const { Dragger } = Upload;
const { RangePicker } = DatePicker;
const ToolBar = ({ setSearchVal, onSave, storeData, role = [],callback,exportFile }) => {
const [form] = Form.useForm();
const addBtn = role?.rule?.find(item => item.menuName == "新增")|| true;
const searchBtn = role?.rule?.find(item => item.menuName == "查询") || true;
const types = [
{
label: "水利",
value:1
},
{
label: "岗前培训",
value:2
},{
label: "在岗培训",
value:3
},{
label: "政治学习教育",
value:4
},{
label: "其他",
value:5
},
]
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" }}
format={"YYYY-MM-DD"}
/>
</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>
<Form.Item label="培训分类" name="teamName">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</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;

122
src/views/sz/zrrgl/form.js Normal file
View File

@ -0,0 +1,122 @@
import React, { useEffect, useState } from 'react';
import { Form, Button, Input, Row, Col, DatePicker, Modal,Image } from 'antd';
import { formItemLayout, btnItemLayout } from '../../../components/crud/FormLayoutProps';
import apiurl from '../../../service/apiurl';
import NormalSelect from '../../../components/Form/NormalSelect';
import moment from 'moment';
const ModalForm = ({ mode, record, onEdit, onSave }) => {
const [form] = Form.useForm();
const types = [
{
label: "行政责任人",
value: 1
},
{
label: "主管部门责任人",
value: 2
}, {
label: "管理单位责任人",
value: 3
}, {
label: "巡查责任人",
value: 4
}, {
label: "技术责任人",
value: 5
},
]
const onFinish = (values) => {
if (mode === 'edit') {
values.id = record.id
onEdit(apiurl.fxzb.sxfd.fxtj.edit, values)
}
if (mode === 'save') {
onSave(apiurl.fxzb.sxfd.fxtj.save, values)
}
}
return (
<>
<Form form={form} {...formItemLayout} onFinish={onFinish} initialValues={record}>
<Row>
<Col span={12}>
<Form.Item
label="责任类型"
name="title"
rules={[{ required: true }]}
>
<NormalSelect allowClear style={{ width: '100%' }} options={types} />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="姓名"
name="period"
rules={[{ required: true }]}
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="单位"
name="org"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="职务"
name="tmPred"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Form.Item
label="联系方式"
name="tmPred"
>
<Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item>
</Col>
</Row>
<Row>
<Col span={24}>
<Form.Item
label="接收时间"
name="tmRecv"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode === 'view'} style={{width:'100%',minHeight:'50px'}}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,95 @@
import React, { Fragment, useRef, useMemo, useEffect, useState } from 'react';
import BasicCrudModal from '../../../components/crud/BasicCrudModal';
import { Table, Card } 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';
import moment from 'moment';
const Page = () => {
const types = {
1:"行政责任人",
2:"主管部门责任人",
3:"管理单位责任人",
4:"巡查责任人",
5:"技术责任人",
}
const refModal = useRef();
const [searchVal, setSearchVal] = useState({})
const columns = [
{ title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
{
title: '责任类型', key: 'title', dataIndex: 'title', width: 200,
render: (value) => <span>{types[value]}</span>
},
{ title: '姓名', key: 'period', dataIndex: 'period', width: 140 },
{ title: '单位', key: 'org', dataIndex: 'org', width: 200},
{ title: '职务', key: 'tmPred', dataIndex: 'tmPred', width: 150, },
{ title: '联系方式', key: 'tmRecv', dataIndex: 'tmRecv', width: 150, },
{ title: '主要职责', key: 'tmRecv', dataIndex: 'tmRecv', width: 250,ellipsis: true},
{
title: '操作', key: 'operation', width: 150, fixed: 'right',align: 'center',
render: (value, row, index) => (<CrudOpRender_text edit={true} del={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.sxfd.fxtj.del + params.id);
}
}
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.hsyb.skhs.page).find_noCode);
useEffect(() => {
if (searchVal) {
const params = {
search: {
title: searchVal.title || undefined,
dateTimeRangeSo: searchVal.dateTimeRangeSo || undefined,
tp:2
}
};
console.log(searchVal);
search(params)
}
}, [searchVal])
return (
<>
<div className='content-root clearFloat xybm' style={{ paddingRight: "0", paddingBottom: "0" }}>
<div className='adcdTableBox'>
<Card className='nonebox'>
<ToolBar setSearchVal={setSearchVal} onSave={command('save')} />
</Card>
<div className="ant-card-body" style={{ padding: "20px 0 0 0" }}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{width:width, y: "calc( 100vh - 400px )" }} />
</div>
</div>
<BasicCrudModal
width={800}
ref={refModal}
title=""
component={ModalForm}
// onCrudSuccess={() => { refresh({ addvcd: localStorage.getItem('ADCD6') }) }}
/>
</div>
</>
);
}
export default Page;

View File

@ -0,0 +1,81 @@
import React, { useEffect, useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
import { SearchOutlined, UndoOutlined, PlusOutlined } from '@ant-design/icons';
import moment from 'moment';
import NormalSelect from '../../../components/Form/NormalSelect';
const ToolBar = ({ setSearchVal, onSave }) => {
const [form] = Form.useForm();
const types = [
{
label: "行政责任人",
value: 1
},
{
label: "主管部门责任人",
value: 2
}, {
label: "管理单位责任人",
value: 3
}, {
label: "巡查责任人",
value: 4
}, {
label: "技术责任人",
value: 5
},
]
const onFinish = (val) => {
if (val.dateTimeRangeSo) {
val.dateTimeRangeSo = {
start: moment(val.dateTimeRangeSo[0]).format("YYYY-MM-DD HH:mm:ss"),
end:moment(val.dateTimeRangeSo[1]).format("YYYY-MM-DD HH:mm:ss")
}
}
setSearchVal(val);
}
const onReset = () => {
form.resetFields();
};
return (
<>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="责任类型" name="title">
<NormalSelect allowClear style={{ width: '150px' }} options={types} />
</Form.Item>
<Form.Item label="姓名" name="title">
<Input allowClear style={{ width: '150px' }} />
</Form.Item>
<Form.Item label="联系方式" name="title">
<Input allowClear style={{ width: '150px' }} />
</Form.Item>
<Form.Item>
<Button type="primary" icon={<SearchOutlined />} htmlType="submit">查询</Button>
</Form.Item>
<Form.Item>
<Button htmlType="button" onClick={onReset} icon={<UndoOutlined />}>
重置
</Button>
</Form.Item>
{
onSave && (
<Form.Item>
<Button onClick={onSave}>新增</Button>
</Form.Item>
)
}
</Form>
</div>
</>
);
}
export default ToolBar;