antD 时间框清空

import React from 'react'
import { Layout, Row, Button, Table, DatePicker, Form, Col, Select, message, Modal } from 'antd'
import ModalCon from './addEdit'
import ReactEcharts from 'echarts-for-react'
import '../riverWater.less'
import { queryByPage, delFun } from '@api/RiverWater/reportProtect'
import { tempStcdList } from '@api/RiverWater/singleCompare'
import moment from 'moment'
const { Header, Content, Footer } = Layout
const FormItem = Form.Item
const Option = Select.Option
export interface IProps {

}

interface IState {
    columns?: any
    loading?: boolean
    tableData?: any
    pagination?: any
    height: number
    stcd?: any
    stnm?: any
    stcds: any
    treeData?: any
    selectedRowKeys?: any
    selectedRows?: any
    type: string
    isShow: boolean
    startTime: any
    endTime: any
    flagstartTime: any
    flagEndTime: any
    echartsOption?: any
    tableFTime: any
    flagNum?: any
    xAxisData: any
    seriesData: any
}

export default class StationInfo extends React.Component<IProps, IState> {

    constructor(props: IProps) {
        super(props)
        this.getStcdList()
        const stcd = sessionStorage.getItem('stcd')
    
        this.state = {
            tableFTime: '',
            xAxisData: [],
            seriesData: [],
            flagNum: 0,
            isShow: false,
            loading: true,
            tableData: [],
            height: 400,
            startTime: '',
            endTime: '',
            flagstartTime: '',
            flagEndTime: '',
            pagination: {
                showSizeChanger: true,
                showQuickJumper: true,
                current: 1,
                pageSize: 15,
                total: 0,
                showTotal: (total: any) => `共${total} 条`,
                pageSizeOptions: ['15', '30', '45']
            },
            stcd,
            stnm: '',
            stcds: [],
         
            treeData: [],
            selectedRowKeys: [],
            selectedRows: [],
            type: '',
            echartsOption: {},
            columns: [
                {
                    title: '测站编码',
                    dataIndex: 'stcd',
                    width: '8%',
                    align: 'center'
                },
                {
                    title: '测站名称',
                    dataIndex: 'stnm',
                    width: '10%',
                    align: 'center',
                    render: (value, row) => {
                        return (
                            <a href='javascript:;' onClick={this.handleClick.bind(this, row)}>{value}</a>
                        )
                    }
                },
                {
                    title: '时间',
                    dataIndex: 'tm',
                    width: '15%',
                    align: 'center'
                },
                {
                    title: '水位',
                    dataIndex: 'z',
                    width: '5%',
                    align: 'right'
                },
                {
                    title: '水量(m³)',
                    dataIndex: 'q',
                    width: '7%',
                    align: 'right'
                },
                {
                    title: '断面过水面积(m²)',
                    dataIndex: 'xsa',
                    width: '13%',
                    align: 'right'
                },
                {
                    title: '断面平均流速(m/s)',
                    dataIndex: 'xsavv',
                    width: '13%',
                    align: 'right'
                },
                {
                    title: '断面最大流速(m/s)',
                    dataIndex: 'xsmxv',
                    width: '13%',
                    align: 'right'
                },
                {
                    title: '河水特征码',
                    dataIndex: 'flwchrcd',
                    width: '8%',
                    align: 'center'
                },
                {
                    title: '水势',
                    dataIndex: 'wptn',
                    align: 'center',
                    width: '6%',
                }
               
            ]
        }
    }

    handleClick = (row: object) => {
        this.setState({
            isShow: true,
            type: 'detail',
            selectedRows: [row]
        })
    }

    getStcdList = () => {
        tempStcdList().then((res: any) => {
            if (res!.code! === 'CODE_0000') {
                const data = res.data
            
                sessionStorage.setItem('stcd', data[0].stcd)
                this.setState({
                    stcds: data,
                    stcd: data[0].stcd
                })
            }
        })
    }

   

    initEcharts = () => {
        const   { xAxisData, seriesData } = this.state
        // 绘制图表
        const option = {
            title: {
                text: '河道水情来报维护折线图',
                x: 'center',
                y: 'top',
                textAlign: 'left',
                top: 10,
                left: 'left'
            },
            tooltip: {
                trigger: 'axis'
            },
            // legend: {
            //     data: ['齐齐哈勒克', '坝上', '出库', '且末']
            // },
            calculable: true,
            xAxis: [
                {
                    type: 'category',
                    boundaryGap: false,
                    data: xAxisData
                }
            ],
            yAxis: [
                {
                    name: '水位(m)',
                    nameLocation: 'middle',
                    nameRotate: 90,
                    nameGap: 40,
                    nameTextStyle: {
                        fontSize: 13
                    }
                }
            ],
            series: [
                {
                    name: '水位',
                    type: 'line',                   
                    data: seriesData
                }
            ]
        }
        return option
    }
    componentDidMount = () => {
        const contentHeight = document.getElementById('js-page-content')!.offsetHeight
        this.setState({
            height: contentHeight - 450
        })
        const { stcd } = this.state
        this.getTableData(stcd, '', '')
    }
    getTableData = (stcd, startTime, endTime) => {
        const { pagination } = this.state
        const param = {
            stcd,
            page: 1, 
            rows: 1000,
            rvnm: '',
            startTime: startTime ? moment(startTime).format('YYYY-MM-DD HH:mm:ss') : '',
            endTime: endTime ? moment(endTime).format('YYYY-MM-DD HH:mm:ss') : '',
        }
        if (this.state.flagNum < 2) {
            queryByPage(param).then((res: any) => {
            //    console.log(res)
                if (res.code === 'CODE_0000') {
                    const xAxisData: any [] = []
                    const seriesData: any [] = []
                    res.data.records.map(item => {
                        xAxisData.push(item.tm)
                        seriesData.push(item.z)
                    })
                    this.setState({
                        tableData: res.data.records,
                        tableFTime: res.data.records.length ? res.data.records[0].tm : '',
                        loading: false,
                        flagNum: this.state.flagNum + 1,
                        xAxisData,
                        seriesData,
                        pagination: {
                            showSizeChanger: true,
                            showQuickJumper: true,
                            current: pagination.current,
                            pageSize: pagination.pageSize,
                            total: res.data.total,
                            showTotal: (total: any) => `共${total} 条`
                        }
                    }, () => {
                       
                        if (this.state.tableData.length) {
                            const { tableFTime } = this.state
                            const startT = moment(tableFTime).add(-12, 'hour').format('YYYY-MM-DD HH:mm:ss')
                            const endT = moment(tableFTime).add(12, 'hour').format('YYYY-MM-DD HH:mm:ss')
                            this.getTableData(stcd, startT, endT)
                            this.setState({
                                flagstartTime: startT,
                                flagEndTime: endT,
                                echartsOption: this.initEcharts()
                            })
                        }
                    })
                }
            })
        }
        
      
    }


    handleReset = (e) => {
        e.preventDefault()
        const stcd = sessionStorage.getItem('stcd')
        this.setState({
            stcd,
            startTime: '',
            endTime: ''
        })
    }

    handleTableChange = (pagination) => {
        this.setState({ pagination }, () => {
            const { stcd } = this.state
            this.getTableData(stcd, '', '')
        })
    }

    getQueryStnm = (e) => {
     
        this.setState({
            stcd: e
        })
       
    }

    onSelectChange = (selectedRowKeys, selectedRows) => {
        this.setState({
            selectedRowKeys,
            selectedRows
        })
    }

    setFn = () => {
        this.setState({
            isShow: false,
            selectedRowKeys: [],
            flagNum: 0
        }, () => {
            const { stcd, flagstartTime, flagEndTime } = this.state  
            this.getTableData(stcd, flagstartTime, flagEndTime)
        })
        
    }

    addBtn = () => {
        this.setState({
            isShow: true,
            type: 'add'
        })
    }

    editBtn = () => {
        if (this.state.selectedRowKeys.length === 1) {
            this.setState({
                isShow: true,
                type: 'edit'
            })
        } else {
            message.error('请选择一条数据进行编辑')
        }
    }

    delBtn = (e) => {
        e.preventDefault()
        const self = this
        const confirm = Modal.confirm
        const { selectedRowKeys } = this.state
        if (selectedRowKeys.length === 1) {
            confirm({
                title: '提示',
                content: '确认要删除?',
                okText: '确认',
                cancelText: '取消',
                onOk() {
                    self.delBtnFn()
                }
            })
        } else {
            message.warn('请选择一条数据')
        }
    }

    delBtnFn = () => {
      
        const { selectedRows } = this.state
        const param = {
            stcd: selectedRows[0].stcd,
            tm: selectedRows[0].tm
        }
        delFun(param).then((res: any) => {
          //  console.log(res)
            if (res) {
                message.success('删除成功', 3)
                this.setState({
                    selectedRowKeys: [],
                    flagNum: 1
                }, () => {
                    const { stcd, flagstartTime, flagEndTime } = this.state
                   
                    this.getTableData(stcd, flagstartTime, flagEndTime)
                })
               
            }
        })
       
    }
    onChangeStartTime = (value, dateString) => {
        const param = { value, dateString }
        this.setState({
            startTime:  param.dateString ? moment(param.dateString, 'YYYY-MM-DD HH:mm:ss') : ''  // 点击输入框清除按钮防止出错
        })
    }
    onChangeEndTime = (value, dateString) => {
       
        const param = { value, dateString }
        this.setState({
            endTime: param.dateString ? moment(param.dateString, 'YYYY-MM-DD HH:mm:ss') : ''
        })
    }
    // 查询
    getSelect = () => {
        this.setState({
            flagNum: 1
        }, () => {
            const { stcd, startTime, endTime } = this.state
            this.getTableData(stcd, startTime, endTime)
        })
    }
     // 设置开始日期不能选择的时间
    disabledStartDate = current => {
        if (this.state.endTime) {
            return current > Date.now() || current > new Date(this.state.endTime).getTime()
        } else {
            return current > Date.now()
        }
     }

    // 设置结束不能选择的时间
     disabledEndDate = current => {
        return current < new Date(this.state.startTime).getTime()  || current > Date.now()
      }
    render() {
        const { columns, pagination, loading, tableData, selectedRowKeys, stcds } = this.state
        const rowSelection = {
            loading: true,
            selectedRowKeys,
            onChange: this.onSelectChange
        }
        return (
            <Layout className='bodyClass'>
                <Form layout='inline' className='queryForm'>
                    <Row>
                        <Col sm={24} md={6} >
                        <FormItem label='测站名称'>
                           <Select value={this.state.stcd} style={{width: '100%'}} onChange={this.getQueryStnm}>
                                {
                                    stcds.map((item: any) => (
                                        <Option key={item.stcd}>{item.stnm}</Option>
                                    ))
                                }
                            </Select>
                            </FormItem>
                           
                        </Col>
                        <Col sm={24} md={6} >
                            <FormItem label='开始时间' style={{ width: '100%' }}>
                               <DatePicker value={this.state.startTime} showTime placeholder='请选择开始时间' disabledDate={this.disabledStartDate} onChange={this.onChangeStartTime}  />
                               
                            </FormItem>
                        </Col>
                        <Col sm={24} md={6} >
                            <FormItem label='结束时间' style={{ width: '100%' }}>
                               <DatePicker value={this.state.endTime} showTime placeholder='请选择结束时间'  disabledDate={this.disabledEndDate} onChange={this.onChangeEndTime}  />
                            </FormItem>
                        </Col>
                        <Col sm={24} md={6} className='user_btn' >
                            <Button className='searchBtn' icon='search' onClick={this.getSelect}>查询</Button>
                            <Button className='resetBtn' icon='reload' onClick={this.handleReset}>重置</Button>
                        </Col>
                    </Row>
                    {/* <Row>
                        <Col sm={24} md={6} >
                            <FormItem label='选择时间' style={{ width: '100%' }}>
                                <RangePicker style={{ width: '100%' }} format='YYYY-MM-DD' />
                            </FormItem>
                        </Col>
                    </Row> */}
                </Form>
                <Content className='contentLayout'>
                    <Header className='contentHeader'>
                        <Row>
                            <Button onClick={this.addBtn}>新增</Button>
                            <Button onClick={this.editBtn}>编辑</Button>
                            <Button onClick={this.delBtn}>删除</Button>
                        </Row>
                    </Header>
                    <Table
                        columns={columns}
                        rowKey='id'
                        pagination={pagination}
                        loading={loading}
                        dataSource={tableData}
                        rowSelection={rowSelection}
                        onChange={this.handleTableChange}
                        scroll={{ x: true, y: 200 }}
                        bordered
                    />
                    <ModalCon
                        isShow={this.state.isShow}
                        setFn={this.setFn}
                        type={this.state.type}
                        rowData={this.state.selectedRows![0]}
                    />
                </Content>
                <Footer className='contentLayout' style={{height: this.state.height}}>
                    <div id='histogram' className='containerDiv'>
                        {
                            tableData.length > 0 ? <ReactEcharts
                                option={this.state.echartsOption}
                                theme='clear'
                                style={{ width: '100%', height: '100%' }}
                            /> : 
                            <div style={{textAlign: 'center', display: 'flex', flexDirection: 'column', height: '100%'}}>
                                <h1 style={{fontSize: 20, fontWeight: 'bolder'}}>
                                    河道水情来报维护
                                </h1>
                                <div className='nodata' style={{flex: 1}}/>
                            </div>
                        }
                        
                    </div>
                </Footer>

            </Layout>
        )
    }
}

 

转载于:https://www.cnblogs.com/whlBooK/p/11540396.html

<think>好的,我现在需要帮用户解决在使用antd的Tree组件时遇到的点击穿透问题。用户提到弹窗,所以可能是在Tree节点点击后触发了弹窗,但弹窗关闭时,下层Tree节点的点击事件被触发了。这属于典型的点击穿透问题。 首先,我得回忆一下点击穿透的常见原因。通常是因为移动端的touch事件和click事件的延迟,导致上层元素隐藏后,下层的click事件被触发。不过在antd的Tree组件中,可能更多是React或Vue架下的事件冒泡问题,尤其是弹窗和Tree节点的事件处理。 用户提供的引用中,有提到React中使用clearTimeout来消除双击事件的延时,还有在Vue中通过@click.stop.prevent阻止事件冒泡,以及使用::v-deep修改样式。这些可能都是相关的解决方案。 接下来,我需要结合antd Tree组件的特性来思考。Tree节点的点击事件可能在弹窗关闭后仍然触发,可能是因为弹窗关闭时没有正确阻止事件冒泡,或者触发了下层元素的事件。 解决方案可能包括几个方面: 1. **阻止事件冒泡**:在弹窗的关闭事件中,使用e.stopPropagation()来防止事件冒泡到Tree节点。这在用户提供的引用2中提到过,通过@click.stop.prevent来阻止事件冒泡,类似的在React中可能需要手动调用stopPropagation。 2. **延迟关闭弹窗**:弹窗关闭后,可能仍有事件在传播,延迟关闭可以确保事件队列清空。用户引用1中使用了setTimeout来延迟操作,可能适用于此场景。 3. **禁用下层交互**:在弹窗显示时,通过CSS的pointer-events: none来禁用Tree组件的交互,关闭后再恢复。用户引用3提到了::v-deep修改样式,可能可以用来覆盖antd组件的样式,实现pointer-events的控制。 4. **使用遮罩层**:在弹窗下方添加透明的遮罩层,拦截点击事件。这可能需要在弹窗结构中加入一个遮罩元素,并处理其事件。 另外,需要注意antd Tree组件的事件处理机制。例如,onSelect事件可能会在节点点击时触发,如果弹窗的关闭没有阻止事件传播,可能导致Tree的onSelect再次被触发。 可能需要分步骤解决:首先确认点击穿透的具体场景,是在弹窗关闭后点击了Tree节点,还是弹窗关闭过程中触发了Tree的事件。然后针对性地阻止事件冒泡或延迟处理。 还要考虑React和Vue的不同实现,用户之前的问题可能涉及Vue(引用3是Vue3+antdv),但当前问题是在antd(React)中使用Tree组件,所以解决方案需要基于React的语法。 例如,在React中,弹窗组件关闭时,在事件处理函数中调用e.stopPropagation()。或者在Tree节点的点击事件处理中,判断弹窗是否处于打开状态,如果是则阻止默认行为。 此外,可能需要结合antd的API,比如Tree的onSelect事件参数是否有可以取消事件的方法,或者利用state控制弹窗显示时禁用Tree的交互。 总之,解决方案需要综合事件冒泡处理、延迟操作、CSS控制以及可能的组件状态管理。需要确保在弹窗显示期间,下层Tree组件不会响应点击事件,或者在事件传播路径上正确阻止冒泡。</think>#### **Ant Design Tree 组件点击穿透问题解决方案** 在 Ant Design Tree 组件中,节点点击与弹窗交互可能因**事件冒泡**或**异步时序问题**导致点击穿透(如弹窗关闭后触发下层节点事件)。以下是具体解决方案: --- ### **一、核心原因分析** 1. **事件冒泡机制** - Tree 节点点击事件冒泡到父容器,若弹窗关闭逻辑未阻止冒泡,可能触发下层节点事件[^2]。 2. **异步时序问题** - 弹窗关闭后,浏览器可能仍在处理未完成的 `click` 事件队列,导致穿透到下层元素[^1]。 --- ### **二、针对性解决方案** #### **1. 阻止事件冒泡** 在弹窗关闭逻辑中显式阻止事件冒泡,避免触发 Tree 节点事件。 **React 代码示例**: ```jsx // 弹窗关闭函数 const handleCloseModal = (e) => { e.stopPropagation(); // 阻止事件冒泡 setModalVisible(false); }; // Tree 节点点击事件 <Tree onSelect={(selectedKeys, { node, event }) => { event.stopPropagation(); // 可选:阻止节点自身事件冒泡 setSelectedNode(node); setModalVisible(true); }} /> ``` **适用场景**:弹窗与 Tree 节点直接关联,需快速阻断事件链[^2]。 --- #### **2. 延迟关闭弹窗** 通过 `setTimeout` 延迟关闭弹窗,确保浏览器事件队列清空。 **代码示例**: ```jsx const handleCloseModal = (e) => { e.stopPropagation(); setTimeout(() => { setModalVisible(false); }, 100); // 延迟 100ms 关闭 }; ``` **原理**:等待潜在未完成的 `click` 事件执行完毕[^1]。 --- #### **3. 禁用下层交互(CSS 控制)** 弹窗显示时,通过 `pointer-events: none` 禁用 Tree 组件的交互。 **代码示例**: ```css /* 弹窗显示时禁用 Tree */ .disabled-tree .ant-tree { pointer-events: none; opacity: 0.6; /* 可选:视觉提示禁用状态 */ } ``` **React 动态控制**: ```jsx <div className={modalVisible ? "disabled-tree" : ""}> <Tree /> <Modal visible={modalVisible} onCancel={handleCloseModal} /> </div> ``` **优势**:无需修改事件逻辑,通过 CSS 直接控制交互状态[^3]。 --- #### **4. 添加遮罩层拦截事件** 在弹窗下方插入透明遮罩层,拦截穿透的点击事件。 **代码示例**: ```jsx {modalVisible && ( <div style={{ position: "absolute", inset: 0, zIndex: 1000 }} onClick={handleCloseModal} /> )} ``` **注意**:遮罩层需覆盖整个 Tree 区域,并通过 `z-index` 确保层级高于 Tree[^3]。 --- ### **三、方案对比与选择建议** | 方案 | 适用场景 | 注意事项 | |-------------------|----------------------------------|-----------------------------| | 阻止事件冒泡 | 简单弹窗交互,需快速阻断事件链 | 需在多个事件处理函数中添加逻辑 | | 延迟关闭弹窗 | 异步操作较多的复杂场景 | 延迟时间需根据实际情况调整 | | CSS 禁用交互 | 弹窗覆盖范围大,需全局控制交互 | 需处理视觉禁用状态的样式 | | 遮罩层拦截 | 需要物理隔离点击事件的场景 | 需管理遮罩层的层级与布局 | --- ### **四、扩展优化** - **自定义 Hook 管理状态**: 封装逻辑复用弹窗与 Tree 的交互状态: ```jsx const usePreventClickThrough = () => { const [isModalOpen, setIsModalOpen] = useState(false); const closeModal = (e) => { e?.stopPropagation(); setIsModalOpen(false); }; return { isModalOpen, setIsModalOpen, closeModal }; }; ``` - **Ant Design 组件增强**: 使用 `ConfigProvider` 全局覆盖 Tree 组件样式: ```jsx <ConfigProvider theme={{ components: { Tree: { nodeHoverBg: "transparent" } } }}> <Tree /> </ConfigProvider> ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值