feat():模块开发

lsf-dev
李神峰 2024-09-24 16:52:53 +08:00
parent 9b161f4012
commit 89457a0f49
24 changed files with 2244 additions and 199 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')
}else{
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 lf">
<img src={`${process.env.PUBLIC_URL}/assets/shuili.png`} alt=""/>
<span></span>
<span></span>
</span>
<div className="topMenu lf">
<TopMenu menu={menu} menuIndexes={menuIndexes} />

View File

@ -4,7 +4,7 @@ import Zfzl from '../views/gxsl/zfzl'
const pubapi_old = 'https://owrsvr.cloudowr.cn/svr'
const pubapi = 'https://owrsvr.cloudowr.cn/pubapi'
const zdkapi = 'https://slt-sh.chutianyun.gov.cn:8002' //中电科的市级平台
const service_fxdd = '/gunshiApp/xyt'
const service_fxdd = '/gunshiApp/tsg'
const service_shzh = '/shzh'
const apiurl = {
fxya: {
@ -852,6 +852,7 @@ const apiurl = {
//实时水情
sssq: {
selectList:service_fxdd + "/real/rain/list",
list: service_fxdd + '/river/water/list', //实时水情-河道水情列表
warn: service_fxdd + '/current/situation/rv/warn', //实时水情-河道水情统计
summaryInfo: service_fxdd + '/river/water/summaryInfo', //实时水情-河道水情汇总
@ -860,7 +861,7 @@ const apiurl = {
reservoirsummaryInfo: service_fxdd + '/reservoir/water/summaryInfo', //实时水情-水库水情汇总
//河道弹框详情
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', //水位流量关系
channel: service_fxdd + '/reservoir/water/image/channel', //图像监测-视角
imageinfo: service_fxdd + '/reservoir/water/image/info', //图像监测-列表

View File

@ -97,7 +97,9 @@ import Ssyq from './sq/qth/ssyq'
// 四制 - 组织机构查看
import Zzjgck from './sz/zzjgck'
import Zrrgl from './sz/zrrgl'
import Pxjhgl from './sz/pxjhgl'
import Pxjlgl from './sz/pxjlgl'
const HomePage = lazy(() => import('./Home'))
@ -243,7 +245,9 @@ const AppRouters: React.FC = () => {
{ path: 'sq/qzq/Gcdsj', element: <Gcdsj /> },
// 四制-组织机构查看
{ 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: '/login', element: <LoginPage /> },

View File

@ -20,7 +20,6 @@ function DrpSearch({record}) {
const option = useMemo(() => {
if (data && data.length) {
return drpOption({data,wrz:record.wrz,grz:record.grz});
}
}, [data])
@ -50,30 +49,6 @@ 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,
@ -84,15 +59,18 @@ function DrpSearch({record}) {
moment().add(1, 'hour').set({ minute: 0, second: 0 }),
],
}
setParams(option)
setInitialDateRange(option)
getData(option)
if (record.stcd) {
setParams(option)
setInitialDateRange(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: "320px"}}
onChange={searchTm}
@ -103,11 +81,11 @@ function DrpSearch({record}) {
<Button type="primary" onClick={doSearch} style={{ marginLeft: "10px" }}>查询</Button>
<Button style={{ marginLeft: "10px" }} onClick={() => { handleReset()}}>重置</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
@ -119,7 +97,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,32 +1,35 @@
import React, { useEffect, useState } from 'react'
import { reservoirlist, list} from "../../../../service/sssq";
import { zqrl, list} from "../../../../service/sssq";
import Sssw from './sssw';
import Sjcx from '../../../Home/MapCtrl/components/Sqjcsj/index'
import "./index.less"
import { helpers } from '@turf/turf';
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 [tableData1, setTableData1] = useState([])
const getData = async (params) => {
setTableData(await reservoirlist(params));
}
const getData1 = async (params) => {
setTableData1(await list(params));
}
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(() => {
let option = {
sources: ["SW", "SK"],
args: "",
};
getData(option)
getData1({args: "",sources: ["SH", "SW"],})
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>
<div style={{display:"flex",alignItems:"center"}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时水位</span>
</div>
@ -34,8 +37,22 @@ export default function Sksq() {
</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}}>
@ -44,7 +61,7 @@ export default function Sksq() {
</div>
</div>
<div className='sjcx-content'>
<Sjcx record={tableData[0] || {}}/>
<Sjcx record={{...tableData[0],height:true} || {}}/>
</div>
</div>
</div>

View File

@ -1,6 +1,5 @@
import React from 'react'
import moment from 'moment'
import MyImg from '../../../Home/MapCtrl/components/Skssjc/myImg'
import {Divider} from "antd"
export default function Sssw({data}) {
return (
<div className="ssjc">
@ -12,55 +11,27 @@ export default function Sssw({data}) {
<div className="infoItem">
<div className="row-key">监测水位:</div>
<div className="row-value">{data?.rz ? data?.rz.toFixed(2):'-'}</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?.desFloodLev ? data?.desFloodLev.toFixed(2):'-'}</div>
<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.normWatLev ? data.normWatLev.toFixed(2):'-'}</div>
<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 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

@ -21,7 +21,7 @@ export default function Sksq() {
<div className='content-sk'>
<div className='content-left'>
<div className='comomn-title'>
<div>
<div style={{display:"flex",alignItems:"center"}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时水位</span>
</div>

View File

@ -7,13 +7,10 @@ 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 [tableData, setTableData] = useState([])
const [tableData1, setTableData1] = useState([])
const getData = async (params) => {
setTableData(await reservoirlist(params));
}
const getData1 = async () =>{
const getData1 = async () => {
const { data, code, msg } = await httppost2(apiurl.home.yq)
if (code !== 200) {
message.error(msg || '请求失败');
@ -28,13 +25,28 @@ export default function Sksq() {
setTableData1(list||[])
}
useEffect(() => {
let option = {
sources: ["SW", "SK"],
args: "",
};
getData(option)
}, [])
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()
@ -44,14 +56,23 @@ export default function Sksq() {
<div className='content-sk'>
<div className='content-left'>
<div className='comomn-title'>
<div>
<div style={{display:"flex",alignItems:"center",columnGap:0}}>
<img alt='' src={`${process.env.PUBLIC_URL}/assets/panelTitle.png`} />
<span style={{marginLeft:10}}>实时雨情</span>
</div>
<span>站点{tableData[0]?.stnm}</span>
<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={tableData[0] || {}}/>
<Sssw data={stcdItem || {}}/>
</div>
</div>
<div className='content-right'>
@ -62,7 +83,7 @@ export default function Sksq() {
</div>
</div>
<div className='sjcx-content'>
<Sjcx record={{...tableData1[2],height:true} || {}}/>
<Sjcx record={{stcd:selected,height:true} || {}}/>
</div>
</div>
</div>

View File

@ -1,36 +1,45 @@
import React from 'react'
import moment from 'moment'
import MyImg from '../../../Home/MapCtrl/components/Skssjc/myImg'
export default function Sssw({data}) {
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'
>雨情最新上报时间: {data?.tm}</div>
>雨情最新上报时间: {detail?.tm}</div>
<div className='drp-content'>
<div className='drp-item'>
<div className='value'>12.5&nbsp;<span>mm</span></div>
<div className='value'>{detail?.h1 ?? '-' }&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='value'>{detail?.h3 ?? '-' }&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='value'>{detail?.h6 ?? '-' }&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='value'>{detail?.h12 ?? '-' }&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='value'>{detail?.h24 ?? '-' }&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='value'>{detail?.h48 ?? '-' }&nbsp;<span>mm</span></div>
<div className='name'>近48小时</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;

View File

@ -166,7 +166,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
}, [record,mode])
return (
<>
<div style={{height:"65vh",overflowY:"auto"}}>
<div className='basic-info'>基本信息</div>
{/* <Divider /> */}
<Form
@ -194,94 +194,178 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
</Form.Item>
</Col>
</Row>
<Row>
<Col span={12}>
<Col span={24}>
<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"
label="主办单位"
name="remark"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
rules={[{ required: true }]}
>
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</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="地址"
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 }]}
>
<Input type='text' disabled={mode==='view'} style={{width:'100%'}} allowClear />
<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>
<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={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="teamLeader"
label="联系电话"
name="address"
>
<Input type='num' disabled={mode==='view'} style={{width:'100%'}} allowClear />
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
label="联系电话"
name="phone"
label="填报人"
name="address"
>
<Input type='num' disabled={mode==='view'} style={{width:'100%'}} allowClear />
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear />
</Form.Item>
</Col>
</Row>
</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
@ -363,11 +447,22 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
</Row>
</Form.Item>
</Col>
</Row>
</Row>
{
mode==='view'?null:(
<>
<Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit">
{mode === 'save' ? '保存' :
mode === "similarSave" ? "保存" :
'修改'}
</Button>
</Form.Item>
</>
)
}
</Form>
<div className='basic-info' style={{display:"flex",justifyContent:"space-between"}}>
<span>队伍明细共计{details?.length}</span>
</div>
<Modal
open={pdfViewOPen}
width={1000}
@ -388,7 +483,7 @@ const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
src={`${process.env.PUBLIC_URL}/static/pdf/web/viewer.html?file=${encodeURIComponent(`/gunshiApp/xyt/rescue/goods/file/download/${iframeSrc}`)}`}
/>
</Modal>
</>
</div>
);
}

View File

@ -1,22 +1,26 @@
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 { 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 { 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 [isFetch, setIsFetch] = 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 },
@ -42,10 +46,40 @@ const Page = () => {
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();
@ -55,20 +89,38 @@ const Page = () => {
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()
setIsFetch(!isFetch)
}
// 导出
const exportExcel = () => {
let params = {
...searchVal,
id:1
}
httppost5(apiurl.gcaqjc.gcaqfx.jrx.export, params).then(res => {
exportFile(`培训计划管理.xlsx`,res.data)
})
}
useEffect(()=>{
const params = {
search: {
@ -88,6 +140,8 @@ const Page = () => {
setSearchVal={setSearchVal}
onSave={command('save')}
role={role}
callback={refresh}
exportFile={exportExcel}
/>
</Card>
<div className="ant-card-body" style={{padding:"20px 0 0 0"}}>
@ -104,6 +158,56 @@ const Page = () => {
// 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>
</>
);
}

View File

@ -1,11 +1,21 @@
import React, { useEffect,useState } from 'react';
import { Form, Input, Button, DatePicker } from 'antd';
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 = [] }) => {
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 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) {
@ -18,6 +28,40 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [] }) => {
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 (
<>
@ -53,12 +97,49 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role = [] }) => {
:null
}
<Form.Item>
<Button onClick={() => form.resetFields()}>导入</Button>
<Button onClick={() => {setExportOPen(true)}}>导入</Button>
</Form.Item><Form.Item>
<Button onClick={() => form.resetFields()}>导出</Button>
<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>
</>
);
}

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;