feat(): 白蚁监测开发

qzc-dev
李神峰 2025-09-28 17:45:29 +08:00
parent e37e3d9e41
commit 64ee4a2192
12 changed files with 733 additions and 341 deletions

View File

@ -413,7 +413,9 @@ const apiurl = {
edit: service_fxdd + "/termite/survey/update", edit: service_fxdd + "/termite/survey/update",
delete: service_fxdd + "/termite/survey/del", delete: service_fxdd + "/termite/survey/del",
detail: service_fxdd + "/termite/survey/detail", detail: service_fxdd + "/termite/survey/detail",
dictionary:service_fxdd + "/sysDictB/listByCd" dictionary: service_fxdd + "/sysDictB/listByCd",
allCd: service_fxdd + '/termite/survey/list/allOrder',
historyPage:service_fxdd + '/termite/survey/detail',
}, },
fzxc: { fzxc: {
page: service_fxdd + "/termite/adver/file/page", page: service_fxdd + "/termite/adver/file/page",

View File

@ -47,7 +47,7 @@ export default function drpOption(data,yjData) {
{ {
type: 'category', type: 'category',
data: data.map(o => o.tm), data: data.map(o => o.tm),
inverse: false, inverse: true,
splitLine: { splitLine: {
show: false show: false
}, },

View File

@ -47,7 +47,7 @@ export default function drpOption(data,yjData) {
{ {
type: 'category', type: 'category',
data: data.map(o => o.tm), data: data.map(o => o.tm),
inverse: false, inverse: true,
splitLine: { splitLine: {
show: false show: false
}, },

View File

@ -3,14 +3,14 @@ import React, {useEffect, useState} from 'react';
import moment from 'moment' import moment from 'moment'
const Tabledata = ({tableData}) => { const Tabledata = ({ tableData }) => {
const columns = [ const columns = [
{ title: '序号', key: '', dataIndex: '', align: 'center',render:(a,b,c)=>c+1}, { title: '序号', key: '', dataIndex: '', align: 'center',render:(a,b,c)=>c+1},
{ title: '时间', key: 'tm', dataIndex: 'tm', align: 'center',render: (rec) => <span>{rec ?? "-"}</span> }, { title: '时间', key: 'tm', dataIndex: 'tm', align: 'center',render: (rec) => <span>{rec ?? "-"}</span> },
{ title: '库水位(m)', key: 'rz', dataIndex: 'rz', align: 'center',render: (rec) => <span>{rec ?? "-"}</span> }, { title: '库水位(m)', key: 'rz', dataIndex: 'rz', align: 'center',render: (rec) => <span>{rec ?? "-"}</span> },
{ title: 'X方向位移(mm)', key: 'x', dataIndex: 'x', align: 'center',render: (rec) => <span>{rec ?? "-"}</span>}, { title: 'X方向位移(mm)', key: 'de', dataIndex: 'de', align: 'center',render: (rec) => <span>{rec ?? "-"}</span>},
{ title: 'Y方向位移(mm)', key: 'y', dataIndex: 'y', align: 'center',render: (rec) => <span>{rec ?? "-"}</span>}, { title: 'Y方向位移(mm)', key: 'dn', dataIndex: 'dn', align: 'center',render: (rec) => <span>{rec ?? "-"}</span>},
{ title: 'H方向位移(mm)', key: 'h', dataIndex: 'h', align: 'center',render: (rec) => <span>{rec ?? "-"}</span>}, { title: 'H方向位移(mm)', key: 'du', dataIndex: 'du', align: 'center',render: (rec) => <span>{rec ?? "-"}</span>},
]; ];

View File

@ -1,7 +1,7 @@
export default function drpOption(data,yjData) { export default function drpOption(data,yjData) {
console.log("data",data); console.log("data",data);
const max1 = Math.max(...[...data.map(obj => obj.x),...data.map(obj => obj.y),...data.map(obj => obj.h),...yjData.map(obj => obj.value)]) const max1 = Math.max(...[...data.map(obj => obj.de),...data.map(obj => obj.dn),...data.map(obj => obj.du),...yjData.map(obj => obj.value)])
const min1 = Math.min(...[...data.map(obj => obj.x),...data.map(obj => obj.y),...data.map(obj => obj.h),...yjData.map(obj => obj.value)]) const min1 = Math.min(...[...data.map(obj => obj.de),...data.map(obj => obj.dn),...data.map(obj => obj.du),...yjData.map(obj => obj.value)])
const max2 = Math.max(...data.map(obj => obj.rz)) const max2 = Math.max(...data.map(obj => obj.rz))
const min2 = Math.min(...data.map(obj => obj.rz)) const min2 = Math.min(...data.map(obj => obj.rz))
@ -49,7 +49,7 @@ export default function drpOption(data,yjData) {
{ {
type: 'category', type: 'category',
data: data.map(o => o.tm), data: data.map(o => o.tm),
inverse: false, inverse: true,
splitLine: { splitLine: {
show: false show: false
}, },
@ -75,7 +75,7 @@ export default function drpOption(data,yjData) {
// gridIndex: 1, // gridIndex: 1,
type: 'value', type: 'value',
position: 'left', position: 'left',
name: "位移(m)", name: "位移(mm)",
nameTextStyle: { nameTextStyle: {
padding: [0, 0, 10, 10], padding: [0, 0, 10, 10],
color:'#333333', color:'#333333',

View File

@ -88,7 +88,7 @@ function ShenYa({ id, data, dispatch, onCancel }) {
<div className="normalModalStyle homeModal2"> <div className="normalModalStyle homeModal2">
<div className="normalModalStyle_title"> <div className="normalModalStyle_title">
<div className="normalModalStyle_title_icon"></div> <div className="normalModalStyle_title_icon"></div>
{data.stationCode} {data.cdnm}
<div className="normalModalStyle_title_cancel"> <div className="normalModalStyle_title_cancel">
<CloseOutlined onClick={closePop} style={{color:"#333"}}/> <CloseOutlined onClick={closePop} style={{color:"#333"}}/>
</div> </div>

View File

@ -29,7 +29,7 @@ const Page = () => {
] ]
}else{ }else{
return [ return [
{ title: '监测点', key: 'cd', dataIndex: 'cd',align: "center",width: 80, ellipsis: true }, { title: '监测点', key: 'cdnm', dataIndex: 'cdnm',align: "center",width: 80, ellipsis: true },
{ title: '监测时间', key: 'tm', dataIndex: 'tm',align: "center",width: 80, ellipsis: true, render:(v,row)=><div style={{color:row.flag===1?'red':'#3B4859'}}><div>{v?.slice(5,10)}</div><div>{v?.slice(11,16)}</div></div> }, { title: '监测时间', key: 'tm', dataIndex: 'tm',align: "center",width: 80, ellipsis: true, render:(v,row)=><div style={{color:row.flag===1?'red':'#3B4859'}}><div>{v?.slice(5,10)}</div><div>{v?.slice(11,16)}</div></div> },
{ title: <div><div>x方向</div><div>(mm)</div></div>, key: 'de', dataIndex: 'de',align: "center", ellipsis: true, render:(v,row)=><div style={{color:row.xstatus===1?'red':'#3B4859'}}>{v}</div> }, { title: <div><div>x方向</div><div>(mm)</div></div>, key: 'de', dataIndex: 'de',align: "center", ellipsis: true, render:(v,row)=><div style={{color:row.xstatus===1?'red':'#3B4859'}}>{v}</div> },
{ title: <div><div>y方向</div><div>(mm)</div></div>, key: 'dn', dataIndex: 'dn',align: "center", ellipsis: true, render:(v,row)=><div style={{color:row.ystatus===1?'red':'#3B4859'}}>{v}</div> }, { title: <div><div>y方向</div><div>(mm)</div></div>, key: 'dn', dataIndex: 'dn',align: "center", ellipsis: true, render:(v,row)=><div style={{color:row.ystatus===1?'red':'#3B4859'}}>{v}</div> },

View File

@ -57,7 +57,8 @@ const Page = () => {
{record.valueTwo || ''} {record.valueTwo || ''}
</span> </span>
}, },
{ title: '校验规则描述', key: 'ruleDesc', dataIndex: 'ruleDesc', width: 250, ellipsis: true,align:"center", }, { title: '校验规则描述', key: 'ruleDesc', dataIndex: 'ruleDesc', width: 250, ellipsis: true, align: "center", },
{ title: '处理建议', key: 'resolveSuggest', dataIndex: 'resolveSuggest', width: 200, ellipsis: true, align:"center" },
]; ];

View File

@ -1,61 +1,61 @@
import React,{useEffect,useState,useMemo} from 'react'; import React, { useEffect, useState, useMemo } from 'react';
import { Form, Button, Input, Row, Col, DatePicker, Upload,message,Image,Modal,Radio } from 'antd'; import { Form, Button, Input, Row, Col, DatePicker, Upload, message, Image, Modal, Radio } from 'antd';
import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps'; import { formItemLayout, btnItemLayout } from '../../../../components/crud/FormLayoutProps';
import apiurl from '../../../../service/apiurl'; import apiurl from '../../../../service/apiurl';
import NormalSelect from '../../../../components/Form/NormalSelect'; import NormalSelect from '../../../../components/Form/NormalSelect';
import { httppost2 } from '../../../../utils/request'; import { httppost2 } from '../../../../utils/request';
import moment from 'moment'; import moment from 'moment';
const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => { const ModalForm = ({ mode, record, onEdit, onSave, onSimilarSave }) => {
const optionsType = [ const optionsType = [
{ {
label: "渗压监测", label: "渗压监测",
value:1 value: 1
}, },
{ {
label: "渗流监测", label: "渗流监测",
value:2 value: 2
}, },
{ {
label:"位移监测", label: "位移监测",
value:3 value: 3
}, },
] ]
const optionsLevel = [ const optionsLevel = [
{ {
label: "黄色告警", label: "黄色告警",
value:1 value: 1
}, },
{ {
label: "红色告警", label: "红色告警",
value:2 value: 2
}, },
] ]
const conditionOneType = [ const conditionOneType = [
{ {
label: ">", label: ">",
value:">" value: ">"
}, },
{ {
label: "<", label: "<",
value:"<" value: "<"
}, },
{ {
label: "=", label: "=",
value:"=" value: "="
}, },
{ {
label: ">=", label: ">=",
value:">=" value: ">="
}, },
{ {
label: "<=", label: "<=",
value:"<=" value: "<="
}, },
{ {
label: "!=", label: "!=",
value:"!=" value: "!="
}, },
] ]
@ -63,30 +63,30 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
const condition = [ const condition = [
{ {
label: "且", label: "且",
value:1 value: 1
}, },
{ {
label: "或", label: "或",
value:2 value: 2
}, },
] ]
const wyOptions = [ const wyOptions = [
{ {
label: "X方向", label: "X方向",
value:"x" value: "x"
}, },
{ {
label: "Y方向", label: "Y方向",
value:"y" value: "y"
}, },
{ {
label: "H方向", label: "H方向",
value:"h" value: "h"
}, },
] ]
console.log("record",record); console.log("record", record);
const [form] = Form.useForm(); const [form] = Form.useForm();
const [staCodeList, setStaCodeList] = useState([])//渗压 const [staCodeList, setStaCodeList] = useState([])//渗压
const [Condition, setCondition] = useState("") const [Condition, setCondition] = useState("")
@ -98,10 +98,10 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
if (mode === 'edit') { if (mode === 'edit') {
values.id = record.id; values.id = record.id;
values.createTime = record.createTime values.createTime = record.createTime
onEdit(apiurl.gcaqjc.gcaqyj.yjgzpz.edit,values) onEdit(apiurl.gcaqjc.gcaqyj.yjgzpz.edit, values)
} }
if (mode === 'save') { if (mode === 'save') {
onSave(apiurl.gcaqjc.gcaqyj.yjgzpz.save,values) onSave(apiurl.gcaqjc.gcaqyj.yjgzpz.save, values)
} }
} }
@ -111,7 +111,7 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
const getwYCode = async () => { const getwYCode = async () => {
try { try {
const res = await httppost2(apiurl.gcaqjc.sjtjcx.wycx.list) const res = await httppost2(apiurl.gcaqjc.sjtjcx.wycx.list)
setCodeList(res.data.map(s=>({stationCode:s.cd,label:s.cdNm,value:s.cd})));// setCodeList(res.data.map(s => ({ stationCode: s.cd, label: s.cdNm, value: s.cd })));//
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@ -120,7 +120,7 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
const getSlCode = async () => { const getSlCode = async () => {
try { try {
const res = await httppost2(apiurl.gcaqjc.sjtjcx.wycx.slList) const res = await httppost2(apiurl.gcaqjc.sjtjcx.wycx.slList)
setSlStacodeList(res.data.map(s=>({stationCode:s.dvcd,label:s.dvcd,value:s.dvcd}))); setSlStacodeList(res.data.map(s => ({ stationCode: s.dvcd, label: s.dvcd, value: s.dvcd })));
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
@ -128,14 +128,14 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
const getStationCode = async () => { const getStationCode = async () => {
try { try {
const res = await httppost2(apiurl.gcaqjc.gcaqyj.yjgzpz.list) const res = await httppost2(apiurl.gcaqjc.gcaqyj.yjgzpz.list)
setStaCodeList(res.data.map(s=>({stationCode:s.dvcd,label:s.dvcd,value:s.dvcd}))); setStaCodeList(res.data.map(s => ({ stationCode: s.dvcd, label: s.dvcd, value: s.dvcd })));
} catch (error) { } catch (error) {
console.log(error); console.log(error);
} }
} }
useEffect(()=>{ useEffect(() => {
if (mode !== "save" ) { if (mode !== "save") {
// getFileInfo(record) // getFileInfo(record)
setCondition(record?.condition) setCondition(record?.condition)
setTypes(record.type) setTypes(record.type)
@ -217,7 +217,7 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
rules={[{ required: true }]} rules={[{ required: true }]}
name="ruleDesc" name="ruleDesc"
> >
<Input disabled={mode==='view'} style={{width:'100%'}} allowClear /> <Input disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
@ -254,7 +254,7 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
style={{ width: '100%' }} style={{ width: '100%' }}
allowClear allowClear
options={condition} options={condition}
onChange={(e) => { setCondition(e)} } onChange={(e) => { setCondition(e) }}
/> />
</Form.Item> </Form.Item>
</Col> </Col>
@ -264,8 +264,8 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
<Form.Item <Form.Item
label="" label=""
name="conditionTwo" name="conditionTwo"
wrapperCol={{span:18,offset:6}} wrapperCol={{ span: 18, offset: 6 }}
rules={[{ required: Condition ? true : false}]} rules={[{ required: Condition ? true : false }]}
> >
<NormalSelect disabled={mode === 'view' || !Condition} style={{ width: '78%' }} allowClear options={conditionOneType} /> <NormalSelect disabled={mode === 'view' || !Condition} style={{ width: '78%' }} allowClear options={conditionOneType} />
</Form.Item> </Form.Item>
@ -274,9 +274,9 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
<Form.Item <Form.Item
label="" label=""
name="valueTwo" name="valueTwo"
rules={[{ required: Condition ? true : false}]} rules={[{ required: Condition ? true : false }]}
> >
<Input type='num' disabled={mode === 'view'|| !Condition} style={{ width: '100%' }} allowClear /> <Input type='num' disabled={mode === 'view' || !Condition} style={{ width: '100%' }} allowClear />
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
@ -302,7 +302,7 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
label="" label=""
name="conditionOne" name="conditionOne"
rules={[{ required: true }]} rules={[{ required: true }]}
wrapperCol={{span:12,offset:12}} wrapperCol={{ span: 12, offset: 12 }}
> >
<NormalSelect disabled={mode === 'view'} style={{ width: '100%' }} allowClear options={conditionOneType} /> <NormalSelect disabled={mode === 'view'} style={{ width: '100%' }} allowClear options={conditionOneType} />
</Form.Item> </Form.Item>
@ -311,7 +311,7 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
<Form.Item <Form.Item
label="" label=""
name="valueOne" name="valueOne"
wrapperCol={{span:20,offset:4}} wrapperCol={{ span: 20, offset: 4 }}
// wrapperCol={{span:20,offset:9}} // wrapperCol={{span:20,offset:9}}
> >
<Input type='num' disabled={mode === 'view'} style={{ width: '100%' }} allowClear /> <Input type='num' disabled={mode === 'view'} style={{ width: '100%' }} allowClear />
@ -321,14 +321,14 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
<Form.Item <Form.Item
label="" label=""
name="condition" name="condition"
wrapperCol={{span:12,offset:12}} wrapperCol={{ span: 12, offset: 12 }}
> >
<NormalSelect <NormalSelect
disabled={mode === 'view'} disabled={mode === 'view'}
style={{ width: '100%' }} style={{ width: '100%' }}
allowClear allowClear
options={condition} options={condition}
onChange={(e) => { setCondition(e)} } onChange={(e) => { setCondition(e) }}
/> />
</Form.Item> </Form.Item>
</Col> </Col>
@ -336,8 +336,8 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
<Form.Item <Form.Item
label="" label=""
name="conditionTwo" name="conditionTwo"
wrapperCol={{span:12,offset:12}} wrapperCol={{ span: 12, offset: 12 }}
rules={[{ required: Condition ? true : false}]} rules={[{ required: Condition ? true : false }]}
> >
<NormalSelect disabled={mode === 'view' || !Condition} style={{ width: '100%' }} allowClear options={conditionOneType} /> <NormalSelect disabled={mode === 'view' || !Condition} style={{ width: '100%' }} allowClear options={conditionOneType} />
</Form.Item> </Form.Item>
@ -347,10 +347,10 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
label="" label=""
name="valueTwo" name="valueTwo"
// wrapperCol={{span:10,offset:12}} // wrapperCol={{span:10,offset:12}}
wrapperCol={{span:20,offset:4}} wrapperCol={{ span: 20, offset: 4 }}
rules={[{ required: Condition ? true : false}]} rules={[{ required: Condition ? true : false }]}
> >
<Input type='num' disabled={mode === 'view'|| !Condition} style={{ width: '100%' }} allowClear /> <Input type='num' disabled={mode === 'view' || !Condition} style={{ width: '100%' }} allowClear />
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
@ -370,8 +370,20 @@ const ModalForm = ({ mode, record,onEdit,onSave,onSimilarSave }) => {
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
<Row>
<Col span={24}>
<Form.Item
label="处理建议"
name="resolveSuggest"
labelCol={{ span: 3 }}
wrapperCol={{ span: 19 }}
>
<Input.TextArea disabled={mode === 'view'} style={{ width: '100%', minHeight: '100px' }} allowClear />
</Form.Item>
</Col>
</Row>
{ {
mode==='view'?null:( mode === 'view' ? null : (
<> <>
<Form.Item {...btnItemLayout}> <Form.Item {...btnItemLayout}>
<Button type="primary" htmlType="submit"> <Button type="primary" htmlType="submit">

View File

@ -1,51 +1,58 @@
import React, { Fragment, useRef, useMemo,useEffect,useState } from 'react'; import React, { Fragment, useRef, useMemo, useEffect, useState } from 'react';
import BasicCrudModal from '../../../../components/crud/BasicCrudModal'; import BasicCrudModal from '../../../../components/crud/BasicCrudModal';
import { Table, Card, Modal, Form, Input, Button, Row,Col, Timeline, message, Tabs,Image,Tag } from 'antd'; import { Table, Card, Modal, Form, Input, Button, Row, Col, Timeline, message, Tabs, Image, Tag } from 'antd';
import {FileWordOutlined,FilePdfOutlined,FileZipOutlined,FileExcelOutlined } from '@ant-design/icons'; import { FileWordOutlined, FilePdfOutlined, FileZipOutlined, FileExcelOutlined } from '@ant-design/icons';
import { useSelector } from 'react-redux'; import { useSelector, useDispatch } from 'react-redux';
import ToolBar from './toolbar'; import ToolBar from './toolbar';
import ModalForm from './form'; import ModalForm from './form';
import apiurl from '../../../../service/apiurl'; import apiurl from '../../../../service/apiurl';
import usePageTable from '../../../../components/crud/usePageTable2'; import usePageTable from '../../../../components/crud/usePageTable2';
import { createCrudService } from '../../../../components/crud/_'; import { createCrudService } from '../../../../components/crud/_';
import { httppost2 } from '../../../../utils/request'; import { httppost2, httpget2 } from '../../../../utils/request';
import {CrudOpRender_text} from '../../../../components/crud/CrudOpRender'; import { CrudOpRender_text } from '../../../../components/crud/CrudOpRender';
import PointHistory from './pointHistory';
import './index.less'; import './index.less';
import moment from 'moment'; import moment from 'moment';
// 引入OpenLayers相关依赖
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import XYZSource from 'ol/source/XYZ';
import * as proj from 'ol/proj';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';
import { Vector as VectorLayer } from 'ol/layer';
import { Vector as VectorSource } from 'ol/source';
import { Circle as CircleStyle, Fill, Stroke, Style, Text } from 'ol/style';
import Overlay from 'ol/Overlay';
const url = "http://223.75.53.141:9100/gs-tsg" const url = "http://223.75.53.141:9100/gs-tsg"
const Page = () => { const Page = () => {
const role = useSelector(state => state.auth.role); const role = useSelector(state => state.auth.role);
const editBtn = role?.rule?.find(item => item.menuName == "编辑") || true; const editBtn = role?.rule?.find(item => item.menuName == "编辑") || true;
const viewBtn = 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 delBtn = role?.rule?.find(item => item.menuName == "删除") || true;
const initData = { const initData = {
obDate: moment().format('YYYY-MM-DD') obDate: moment().format('YYYY-MM-DD')
} }
// 添加地图相关的状态和引用
const mapContainerRef = useRef(null);
const [map, setMap] = useState(null);
const [vectorLayer, setVectorLayer] = useState(null);
const [selectedFeature, setSelectedFeature] = useState(null);
const [popupOverlay, setPopupOverlay] = useState(null);
const popupRef = useRef(null);
// 在组件顶部的状态声明中添加一个新的状态
const [highlightLayer, setHighlightLayer] = useState(null);
// 点位弹框
const [modalVisible, setModalVisible] = useState(false)
const [detailPoint, setDetailPoint] = useState({})
const dispatch = useDispatch();
const [stats, setStats] = useState({
total: 400,
withMosquito: 14,
withoutMosquito: 382,
noData: 4
});
const surveyType = {
1: "日常检查排查",
2: "定期普查",
3:"专项调查"
}
const surveyWay = {
1: "人工排查法",
2: "引诱法",
3: "仪器探测法",
4:"其他"
}
const isHarm = {
0: "无危害",
1: "有危害",
}
const refModal = useRef(); const refModal = useRef();
const [searchVal, setSearchVal] = useState({...initData}) const [searchVal, setSearchVal] = useState({ ...initData })
const [count, setCount] = useState({}) const [count, setCount] = useState({})
const [allCdList, setAllCdList] = useState([])
// const columns = [ // const columns = [
// { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" }, // { title: '序号', key: 'inx', dataIndex: 'inx', width: 60, align: "center" },
// {title: '填报日期', key: 'reportDate', dataIndex: 'reportDate', width: 140,}, // {title: '填报日期', key: 'reportDate', dataIndex: 'reportDate', width: 140,},
@ -83,25 +90,25 @@ const Page = () => {
dataIndex: 'obDate', dataIndex: 'obDate',
key: 'obDate', key: 'obDate',
width: 180, width: 180,
align:'center' align: 'center'
}, },
{ {
title: '测点编号', title: '测点编号',
dataIndex: 'order', dataIndex: 'order',
key: 'order', key: 'order',
width: 120, width: 120,
align:'center' align: 'center'
}, },
{ {
title: '有无白蚁', title: '有无白蚁',
dataIndex: 'status', dataIndex: 'status',
align:'center', align: 'center',
key: 'status', key: 'status',
width: 100, width: 100,
render:(text, record) => { render: (text, record) => {
// 如果 isHarm 为 null 或 undefined显示无 // 如果 isHarm 为 null 或 undefined显示无
if (text == null) { if (text == null) {
return <Tag color="#04d919" style={{borderRadius: '50%', padding: '4px 8px'}}></Tag>; return <Tag color="#04d919" style={{ borderRadius: '50%', padding: '4px 8px' }}></Tag>;
} }
// 如果 isHandle 为 null 或 undefined当作 false 处理 // 如果 isHandle 为 null 或 undefined当作 false 处理
@ -109,8 +116,8 @@ const Page = () => {
return ( return (
<Tag <Tag
color={!text ?'#04d919' : '#d9001b'} color={!text ? '#04d919' : '#d9001b'}
style={{borderRadius: '50%', padding: '4px 8px'}} style={{ borderRadius: '50%', padding: '4px 8px' }}
> >
{!text ? '无' : '有'} {!text ? '无' : '有'}
</Tag> </Tag>
@ -160,6 +167,164 @@ const Page = () => {
} }
} }
// 获取白蚁所有测点
const getCdList = async () => {
try {
const res = await httpget2(apiurl.rcgl.byfz.bypc.allCd);
if (res.code == 200) {
setAllCdList(res.data);
// 添加标记点到地图
if (map && res.data && res.data.length > 0) {
addMarkersToMap(res.data);
}
}
} catch (error) {
console.log(error);
}
}
// 添加标记点到地图
const addMarkersToMap = (points) => {
if (!map) return;
// 如果已存在矢量图层,先移除
if (vectorLayer) {
map.removeLayer(vectorLayer);
}
// 创建矢量数据源
const vectorSource = new VectorSource();
// 遍历所有点位数据
points.forEach(point => {
// 确保点位有经纬度
if (point.lgtd && point.lttd) {
// 创建要素
const feature = new Feature({
geometry: new Point(proj.fromLonLat([point.lgtd, point.lttd])),
properties: point // 保存点位的所有属性
});
// 根据status设置样式
const color = point.status === 1 ? '#d9001b' : '#04d919'; // 1为红色0为绿色
feature.setStyle(new Style({
image: new CircleStyle({
radius: 4,
fill: new Fill({ color: color }),
stroke: new Stroke({ color: '#ffffff', width: 1 })
})
}));
// 添加要素到数据源
vectorSource.addFeature(feature);
}
});
// 创建矢量图层
const newVectorLayer = new VectorLayer({
source: vectorSource,
zIndex: 10 // 确保点位在地图上层显示
});
// 添加图层到地图
map.addLayer(newVectorLayer);
// 保存矢量图层引用
setVectorLayer(newVectorLayer);
// 添加点击事件处理
// map.on('click', (event) => {
// const feature = map.forEachFeatureAtPixel(event.pixel, function(feature) {
// return feature;
// });
// if (feature) {
// const properties = feature.get('properties');
// if (properties) {
// // 可以在这里处理点击事件,比如显示详情等
// console.log('点击了标记点:', properties);
// // 可以添加弹窗或其他交互
// }
// }
// });
};
// 修改高亮显示选中的测点函数
const highlightFeature = (feature) => {
if (!feature || !highlightLayer) return;
// 清除之前的高亮
highlightLayer.getSource().clear();
// 获取要素属性
const properties = feature.get('properties');
const color = properties.status === 1 ? '#d9001b' : '#04d919';
// 创建一个新的要素用于高亮显示
const highlightFeature = new Feature({
geometry: feature.getGeometry().clone(),
properties: properties
});
// 设置高亮样式
highlightFeature.setStyle(new Style({
image: new CircleStyle({
radius: 10, // 放大图标
fill: new Fill({ color: color }),
stroke: new Stroke({ color: '#ffffff', width: 3 })
}),
text: new Text({
text: properties.order || '未命名测点',
offsetY: -20,
font: 'bold 14px Arial',
fill: new Fill({ color: '#333' }),
stroke: new Stroke({ color: '#fff', width: 3 })
})
}));
// 添加到高亮图层
highlightLayer.getSource().addFeature(highlightFeature);
// 更新选中的要素引用
setSelectedFeature(feature);
// 平移地图到选中的要素位置
const geometry = feature.getGeometry();
const coordinate = geometry.getCoordinates();
map.getView().animate({
center: coordinate,
duration: 500,
zoom: map.getView().getZoom() < 18 ? 18 : map.getView().getZoom()
});
};
// 根据测点ID查找对应的要素
const findFeatureByDeviceId = (deviceId) => {
if (!vectorLayer) return null;
let targetFeature = null;
vectorLayer.getSource().forEachFeature((feature) => {
const properties = feature.get('properties');
if (properties && properties.order === deviceId) {
targetFeature = feature;
}
});
return targetFeature;
};
// 处理表格行点击事件
const handleRowClick = (record) => {
const feature = findFeatureByDeviceId(record.order);
if (feature) {
highlightFeature(feature);
}
};
useEffect(() => { useEffect(() => {
const params = { const params = {
search: { search: {
@ -170,11 +335,93 @@ const Page = () => {
getCount(); getCount();
}, [searchVal]) }, [searchVal])
// 初始化地图
useEffect(() => {
if (!mapContainerRef.current) return;
// 创建地图实例
const mapInstance = new Map({
target: mapContainerRef.current,
controls: [],
view: new View({
center: proj.fromLonLat([114.764317000, 31.496800000]), // 设置地图中心点坐标
zoom: 18.4, // 设置初始缩放级别
minZoom: 5.5,
maxZoom: 30,
}),
});
// 添加天地图卫星影像图层
const satelliteLayer = new TileLayer({
source: new XYZSource({
url: "https://t{0-7}.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=efc861f25f96dc6e5f884f0403ebfefd",
}),
maxZoom: 30,
});
// 设置图层名称
satelliteLayer.set('name', 'SatelliteImage');
// 添加图层到地图
mapInstance.addLayer(satelliteLayer);
// 创建高亮图层
const highlightVectorLayer = new VectorLayer({
source: new VectorSource(),
zIndex: 999, // 确保高亮图层在最上面
style: null
});
// 添加高亮图层到地图
mapInstance.addLayer(highlightVectorLayer);
setHighlightLayer(highlightVectorLayer);
// 创建弹出层
const overlay = new Overlay({
element: popupRef.current,
positioning: 'bottom-center',
stopEvent: false,
offset: [0, -10]
});
mapInstance.addOverlay(overlay);
setPopupOverlay(overlay);
// 添加地图点击事件
mapInstance.on('click', (event) => {
const feature = mapInstance.forEachFeatureAtPixel(event.pixel, function (feature) {
return feature;
});
if (feature) {
setModalVisible(true)
setDetailPoint(feature?.values_?.properties)
highlightFeature(feature);
}
});
// 保存地图实例
setMap(mapInstance);
// 组件卸载时清理地图
return () => {
if (mapInstance) {
mapInstance.setTarget(null);
}
};
}, []);
// 当地图实例创建完成后获取测点数据
useEffect(() => {
if (map) {
getCdList();
}
}, [map]);
return ( return (
<> <>
<div className='content-root clearFloat xybm' style={{paddingRight:"0",paddingBottom:"0"}}> <div className='content-root clearFloat xybm' style={{ paddingRight: "0", paddingBottom: "0" }}>
<div className='lf CrudAdcdTreeTableBox' style={{ width: "100%" }}> <div className='lf CrudAdcdTreeTableBox' style={{ width: "100%", display: 'flex' }}>
<div className='by-left' style={{ width: "60%", height: "calc(100vh - 180px)" }} ref={mapContainerRef}></div>
<div className='by-right' style={{ width: "40%", marginLeft: 10 }}>
<Row gutter={16} className='statsRow'> <Row gutter={16} className='statsRow'>
<Col span={6}> <Col span={6}>
<div className='statItem'> <div className='statItem'>
@ -221,11 +468,32 @@ const Page = () => {
// role={role} // role={role}
/> />
</Card> </Card>
<div className="ant-card-body" style={{ padding: "20px 0 0 0" ,marginRight:20}}> <div className="ant-card-body" style={{ padding: "20px 0 0 0", marginRight: 20 }}>
<Table columns={columns} rowKey="inx" {...tableProps} scroll={{ x: width , y: "calc( 100vh - 400px )"}}/> <Table
columns={columns}
rowKey="inx"
{...tableProps}
scroll={{ x: width, y: "calc( 100vh - 400px )" }}
onRow={(record) => ({
onClick: () => handleRowClick(record), // 添加行点击事件
style: { cursor: 'pointer' } // 添加鼠标指针样式
})}
/>
</div> </div>
</div> </div>
</div>
{/* 添加测点详情Modal */}
<Modal
title={detailPoint?.order}
open={modalVisible}
onCancel={() => setModalVisible(false)}
width={800}
footer={null}
destroyOnClose
>
<PointHistory data={detailPoint} />
</Modal>
<BasicCrudModal <BasicCrudModal
width={1000} width={1000}
ref={refModal} ref={refModal}

View File

@ -0,0 +1,109 @@
import React,{useEffect,useState} from 'react'
import { DatePicker, Table, Button, Form } from 'antd'
import usePageTable from '../../../../components/crud/usePageTable2';
import { createCrudService } from '../../../../components/crud/_';
import apiurl from '../../../../service/apiurl';
import moment from 'moment';
const {RangePicker} = DatePicker
export default function PointHistory({data}) {
const columns = [
{
title: '序号',
dataIndex: 'inx',
key: 'inx',
width: 60,
// render: (_, __, index) => index + 1
},
{
title: '测点编号',
dataIndex: 'order',
key: 'order',
width: 130
},
{
title: '监测时间',
dataIndex: 'obDate',
key: 'obDate',
width: 180
},
{
title: '白蚁入侵',
dataIndex: 'status',
key: 'status',
width: 100,
render: (status) => <span>{status === 1 ? '有' : '无'}</span>
},
{
title: '电量',
dataIndex: 'electricity',
key: 'electricity',
width: 80
}
]
const [searchVal, setSearchVal] = useState({
dateTimeRangeSo: {
start: moment().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss'),
end:moment().format('YYYY-MM-DD HH:mm:ss')
}
})
const [form] = Form.useForm();
const { tableProps, search, refresh } = usePageTable(createCrudService(apiurl.rcgl.byfz.bypc.historyPage).find_noCode);
const onReset = () => {
form.resetFields();
};
const onFinish = (values) => {
let dateSo;
if (values.tm) {
dateSo = {
start: moment(values.tm[0]).format('YYYY-MM-DD HH:mm:ss'),
end: moment(values.tm[1]).format('YYYY-MM-DD HH:mm:ss')
}
}
delete values.tm
setSearchVal({...values, dateTimeRangeSo:dateSo});
}
useEffect(() => {
const params = {
search: {
...searchVal,
order:data?.order
}
};
search(params)
}, [searchVal,data])
useEffect(() => {
form.setFieldValue('tm',[moment().subtract(1,'days'),moment()])
}, [])
return (
<div>
<div className='toolBar' >
<Form form={form} className='toolbarBox' layout="inline" onFinish={onFinish}>
<Form.Item label="监测时间" name="tm">
<RangePicker
allowClear
style={{ width: "350px" }}
showTime
/>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit" >查询</Button>
</Form.Item>
<Form.Item>
<Button htmlType="button" onClick={onReset}>重置</Button>
</Form.Item>
</Form>
</div>
<Table
columns={columns}
rowKey="inx"
{...tableProps}
style={{marginTop:10}}
/>
</div>
)
}

View File

@ -34,13 +34,13 @@ const ToolBar = ({ setSearchVal, onSave, storeData, role, initData }) => {
<Form.Item label="监测日期" name="year"> <Form.Item label="监测日期" name="year">
<DatePicker <DatePicker
allowClear={false} allowClear={false}
style={{ width: "240px" }} style={{ width: "140px" }}
/> />
</Form.Item> </Form.Item>
<Form.Item label="测点编号" name="order"> <Form.Item label="测点编号" name="order">
<Input <Input
allowClear allowClear
style={{ width: "240px" }} style={{ width: "140px" }}
/> />
</Form.Item> </Form.Item>
{/* <Form.Item label="" name="isHarm"> {/* <Form.Item label="" name="isHarm">