import debug from 'debug';
import React from 'react';
import classNames from 'classnames';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { Map as makeMap } from 'immutable';
import { noop } from 'lodash';

import { clickCloseDetails, clickShowTopologyForNode } from '../actions/request-actions';
import { brightenColor, getNeutralColor, getNodeColorDark,getStatusColor,setNodeColor } from '../utils/color-utils';
import { isGenericTable, isPropertyList } from '../utils/node-details-utils';
import { resetDocumentTitle, setDocumentTitle } from '../utils/title-utils';

import Overlay from './overlay';
import MatchedText from './matched-text';
import NodeDetailsControls from './node-details/node-details-controls';
import NodeDetailsGenericTable from './node-details/node-details-generic-table';
import NodeDetailsPropertyList from './node-details/node-details-property-list';
import NodeDetailsHealth from './node-details/node-details-health';
import NodeDetailsRelatives from './node-details/node-details-relatives';
import NodeDetailsTable from './node-details/node-details-table';
import Warning from './warning';

import * as echarts from 'echarts'
import axios from 'axios'
import moment from 'moment'
import { Table,Radio,Checkbox,Button, Drawer, Descriptions } from "antd";
import "antd/dist/antd.css";
import '../../styles/nodeDetail.less'
import getToken from '../utils/get-token'
const log = debug('scope:node-details');

function getTruncationText(count) {
  return 'This section was too long to be handled efficiently and has been truncated'
  + ` (${count} extra entries not included). We are working to remove this limitation.`;
}

class NodeDetails extends React.Component {
  constructor(props, context) {
    super(props, context);
    this.state = {
      // baseUrl:'http://observe-server.cestong.com.cn',  //本地调试使用
      // traceUrl:'http://observe-front.cestong.com.cn',  //本地调试使用
      // coreBaseUrl: 'http://observe-front.cestong.com.cn/core',  //本地调试使用
      coreBaseUrl:'',//上线时打开
      baseUrl:'/re', //上线时打开
      traceUrl:'',//上线时打开
      nodeData:{},  //节点基础信息
      AnalystData:{},//散点图
      queryParams:{
        start_time:Math.round((new Date().getTime())/1000 - (5*60)),
        end_time:Math.round(new Date().getTime()/1000),
        app_alias:'opentelemetry-demo',
        service_name:'frontend',
        percentile:0.5,
        sort_field:'Timestamp',
        sort_type: 'DESC'
      },
      traceData:[],
      livenessData:[],
      barData:[],
      tableData: [],
      bgColor:setNodeColor('R'),
      pagination: {
        pageIndex:1,
        pageSize:10,
        total:0,
        current:1,
      },
      pagination2: {
        page_num:1,
        page_size:10,
        total:0,
        current:1,
      },
      traceQuery:{
        only_exception:0,
        only_database:0,
      },
      timeoutId: null,
      messaging_stats: {
        topic_stats:[]
      },
      cloudTable: [],
      cloudTable2: [],
      cloudPagination: {
        page_num:1,
        page_size:10,
        total:0,
        current:1,
      }
    }
  }

  handleClickClose = (ev) => {
    ev.preventDefault();
    this.props.clickCloseDetails(this.props.nodeId);
  }

  handleShowTopologyForNode = (ev) => {
    ev.preventDefault();
    this.props.clickShowTopologyForNode(this.props.topologyId, this.props.nodeId);
  }
  handleBeforeUnload = () => {
    // 在这里执行你需要的清理工作
    this.props.clickCloseDetails(this.props.nodeId);
  };
  componentDidMount() {
    let _this = this
    // //上线时打开开始
    const traceURL = `http://${parent.location.hostname}`
    const coreBaseURL = `http://${parent.location.hostname}/core`
    this.setState({
      traceUrl:traceURL,
      coreBaseUrl:coreBaseURL
    },()=>{
    })
    //上线时打开结束
    // 接受父组件参数

    // window.top == window  true 自己本身没有被嵌套
    if(window.top !== window){// false 被嵌套
      const data = JSON.parse(parent.localStorage.topoGlobalTimes)
      const appsItem = JSON.parse(parent.localStorage.appsItem)
      const queryParams = _this.state.queryParams
      queryParams.start_time = data.startTime
      queryParams.end_time = data.endTime
      queryParams.app_alias = appsItem.alias
      _this.setState({
        queryParams: queryParams
      },()=>{
        _this.getMethodByshape(_this)
      });
    }

    window.addEventListener('message', function(event) {
      // 处理接收到的消息
      const data = event.data
      console.log('globalTimesChange------data.data=====', data.data)
      const queryParams = _this.state.queryParams
      if (data.eventType == 'globalTimesChange') {
        queryParams.start_time = data.data.startTime
        queryParams.end_time = data.data.endTime
        _this.setState({
          queryParams: queryParams
        },()=>{

          _this.getMethodByshape(_this)
        });
      }

    }, false);

    window.addEventListener('storage', function(event) {
      if ( event.key == 'topoGlobalTimes') {
        // 这里处理父项目 localStorage 值变化的情况
        const data = JSON.parse(event.newValue)
        console.log('JSON.parse(------', data)
        const queryParams = _this.state.queryParams
        queryParams.start_time = data.startTime
        queryParams.end_time = data.endTime
        _this.setState({
          queryParams: queryParams
        },()=>{
          setTimeout(()=>{
            _this.getMethodByshape(_this)
          },0)
        })
      }
    });
  }
  componentWillUnmount() {
    window.addEventListener('beforeunload', this.handleBeforeUnload);
    clearTimeout(this.timeoutId);
  }
  // setQueryParams(){
  //   var strr = parent.location.href;   //上线做为iframe嵌套时使用
  //   let param = this.parseQueryString(strr);  //全链路需要的参数多，因此解析成对象形式
  //   const queryParams = this.state.queryParams;
  //   const newAppAlias = param.app_alias
  //   queryParams.app_alias = newAppAlias
  //   this.setState({
  //     queryParams: queryParams
  //   },()=>{
  //     this.getMethodByshape(this)
  //   });
  // }
  getMethodByshape(_this){
    if (_this.props.shape == 'cylinder'){
      _this.getTableData(); //table
      setTimeout(()=>{
        _this.getBarData(); // 柱形图
      }, 0)
    }
    if (_this.props.shape == 'dottedcylinder'){
      _this.getDottBasicsData() // dottedcylinder 基础信息
    }
    if (_this.props.shape == 'circle'){
      _this.getNodeBasic();

      setTimeout(()=>{
        _this.getNodeAnalyst();//获取散点图
        _this.getNodeLiveness(); // 折线图
      },0)
      _this.getServiceSpans();
    }
    if (_this.props.shape == 'cloud'){
      _this.getCloudTableData()
    }
  }
  //解析URL
  parseQueryString(url){
    var json = {};
    var arr = url.substr(url.indexOf('?') + 1).split('&');
    arr.forEach(item=>{
        var tmp = item.split('=');
                  json[tmp[0]] = tmp[1];
    });
    return json;
  }
  componentWillUnmount() {
    resetDocumentTitle();
  }

  renderTools() {
    const showSwitchTopology = this.props.nodeId !== this.props.selectedNodeId;
    const topologyTitle = `View ${this.props.label} in ${this.props.topologyId}`;

    return (
      <div className="node-details-tools-wrapper">
        <div className="node-details-tools">
          {showSwitchTopology
            && (
            <i
              title={topologyTitle}
              className="fa fa-long-arrow-alt-left"
              onClick={this.handleShowTopologyForNode}>
              <span>
Show in
                {/* <span>{this.props.topologyId.replace(/-/g, ' ')}</span> */}
              </span>
            </i>
            )
          }
          <i
            title="Close details"
            className="fa fa-times close-details"
            onClick={this.handleClickClose}
          />
        </div>
      </div>
    );
  }

  renderLoading() {
    const node = this.props.nodes.get(this.props.nodeId);
    const label = node ? node.get('label') : this.props.label;
    // NOTE: If we start the fa-spin animation before the node details panel has been
    // mounted, the spinner is displayed blurred the whole time in Chrome (possibly
    // caused by a bug having to do with animating the details panel).
    const spinnerClassName = classNames('fa fa-circle-notch', { 'fa-spin': this.props.mounted });
    const nodeColor = (node
      ? getNodeColorDark(node.get('rank'), label, node.get('pseudo'))
      : getNeutralColor());
    const tools = this.renderTools();
    const styles = {
      header: {
        backgroundColor: nodeColor
      }
    };

    return (
      <div className="node-details">
        {tools}
        <div className="node-details-header" style={styles.header}>
          <div className="node-details-header-wrapper">
            <h2 className="node-details-header-label truncate">
              {label}
            </h2>
            <div className="node-details-relatives truncate">
              Loading...
            </div>
          </div>
        </div>
        <div className="node-details-content" style="padding:0 12px">
          <div className="node-details-content-loading">
            <span className={spinnerClassName} />
          </div>
        </div>
      </div>
    );
  }

  renderNotAvailable() {
    const tools = this.renderTools();
    return (
      <div className="node-details">
        {tools}
        <div className="node-details-header node-details-header-notavailable">
          <div className="node-details-header-wrapper">
            <h2 className="node-details-header-label">
              {this.props.label}
            </h2>
            <div className="node-details-relatives truncate">
              n/a
            </div>
          </div>
        </div>
        <div className="node-details-content">
          <p className="node-details-content-info">
            <strong>{this.props.label}</strong>
            {' '}
not found!
          </p>
        </div>
        <Overlay faded={this.props.transitioning} />
      </div>
    );
  }

  render() {
    // if (this.props.notFound) {
    //   return this.renderNotAvailable();
    // }

    // if (this.props.details) {
    //   return this.renderDetails();
    // }

    // return this.renderLoading();

    return this.renderNodeDetails();

  }


  renderDetails() {
    const {
      details, nodeControlStatus, nodeMatches = makeMap(), topologyId
    } = this.props;
    const showControls = details.controls && details.controls.length > 0;
    const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo);
    // const nodeColor= setNodeColor(details.color)
    const {error, pending} = nodeControlStatus ? nodeControlStatus.toJS() : {};
    const tools = this.renderTools();
    const styles = {
      controls: {
        backgroundColor: brightenColor(nodeColor)
      },
      header: {
        backgroundColor: nodeColor
      }
    };

    return (
      <div className="tour-step-anchor node-details">
        {tools}
        <div className="node-details-header" style={styles.header}>
          <div className="node-details-header-wrapper">
            <h2 className="node-details-header-label truncate" title={details.label}>
              <MatchedText text={details.label} match={nodeMatches.get('label')} />
            </h2>
            <div className="node-details-header-relatives">
              {details.parents && (
              <NodeDetailsRelatives
                matches={nodeMatches.get('parents')}
                relatives={details.parents} />
              )}
            </div>
          </div>
        </div>

        {showControls
          && (
          <div className="tour-step-anchor node-details-controls-wrapper" style={styles.controls}>
            <NodeDetailsControls
              nodeId={this.props.nodeId}
              controls={details.controls}
              pending={pending}
              error={error} />
          </div>
          )
        }

        <div className="node-details-content">
          {details.metrics
            && (
            <div className="node-details-content-section">
              <div className="node-details-content-section-header">Status</div>
              <NodeDetailsHealth
                metrics={details.metrics}
                topologyId={topologyId}
                />
            </div>
            )
          }
          {details.metadata
            && (
            <div className="node-details-content-section">
              <div className="node-details-content-section-header">Info</div>
              <NodeDetailsInfo rows={details.metadata} matches={nodeMatches.get('metadata')} />
            </div>
            )
          }

          {details.connections && details.connections.filter(cs => cs.connections.length > 0)
            .map(connections => (
              <div className="node-details-content-section" key={connections.id}>
                <NodeDetailsTable
                  {...connections}
                  nodes={connections.connections}
                  nodeIdKey="nodeId"
                />
              </div>
            ))}

          {details.children && details.children.map(children => (
            <div className="node-details-content-section" key={children.topologyId}>
              <NodeDetailsTable {...children} />
            </div>
          ))}

          {details.tables && details.tables.length > 0 && details.tables.map((table) => {
            if (table.rows.length > 0) {
              return (
                <div className="node-details-content-section" key={table.id}>
                  <div className="node-details-content-section-header">
                    {table.label && table.label.length > 0 && table.label}
                    {table.truncationCount > 0
                      && (
                      <span
                        className="node-details-content-section-header-warning">
                        <Warning text={getTruncationText(table.truncationCount)} />
                      </span>
                      )
                    }
                  </div>
                  {this.renderTable(table)}
                </div>
              );
            }
            return null;
          })}

          {this.props.renderNodeDetailsExtras({ details, topologyId })}
        </div>

        <Overlay faded={this.props.transitioning} />
      </div>
    );
  }

  renderNodeDetails(){
    const {
      details, nodeControlStatus, nodeMatches = makeMap(), topologyId
    } = this.props;
    const node = this.props.nodes.get(this.props.nodeId);
    const label = node ? node.get('label') : this.props.label;
    // const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo);
    // const nodeColor= setNodeColor(details.color)
    const {error, pending} = nodeControlStatus ? nodeControlStatus.toJS() : {};
    const tools = this.renderTools();
    const styles = {
      controls: {
        // backgroundColor: brightenColor(nodeColor)
      },
      header: {
        backgroundColor:this.state.bgColor
      }
    };
    const columns = [
      {
        title: 'TraceID',
        dataIndex: 'trace_id',
        key: 'trace_id',
        width:'20%',
        ellipsis:true,
        align:'center',
        // scopedSlots:{customRender:'trace_id'},
        render: (text,record) => <a target='_blank' href={`${this.state.traceUrl}/#/latency/index?traceId=${text}&app_alias=${this.state.queryParams.app_alias}&span_id=${record.span_id}&datetime=${Date.parse(record.datetime)/1000}`}>{text}</a>
      },
      {
        title: '方法',
        dataIndex: 'method',
        key: 'method',
        width:'15%',
        ellipsis:true,
        align:'center'
      },
      {
        title: '状态码',
        dataIndex: 'code',
        key: 'code',
        width:'15%',
        ellipsis:true,
        align:'center'
      },
      {
        title: '请求时长(ms)',
        dataIndex: 'duration',
        key: 'duration',
        width:'30%',
        ellipsis:true,
        align:'center',
        render:(text) => <span>{(text && Number(text.toFixed(2))) || 0 }</span>
      },
      {
        title: '日期',
        dataIndex: 'datetime',
        key: 'datetime',
        width:'30%',
        ellipsis:true,
        align:'center',
        defaultSortOrder: 'descend',
        sorter:true
      },
    ]
    const colums2 = [
      {
        title: '服务名',
        dataIndex: 'service_name',
        key: 'service_name',
        ellipsis:true,
        align:'center',
        render: (text, record) => (
          <span>{record.service_name_cn? record.service_name_cn: record.service_name}</span>
        )
      },
      {
        title: '执行语句',
        dataIndex: 'query',
        key: 'query',
        width:'40%',
        ellipsis:true,
        align:'center',
        render: (text, record) => (
          <textarea value={record.query} disabled rows="2" />
        )
      },
      {
        title: '慢查询次数',
        dataIndex: 'slow_num',
        key: 'slow_num',
        ellipsis:true,
        align:'center'
      },
      {
        title: '错误数量',
        dataIndex: 'error_num',
        key: 'error_num',
        ellipsis:true,
        align:'center'
      }
    ]
    const cloudColums = [
      {
        title: '应用名称',
        dataIndex: 'app_name',
        align:'center',
        width: 200,
        key: 'app_name'
      },
      {
        title: '请求总数',
        width: 100,
        dataIndex: 'request_total',
        align:'center',
        key: 'request_total',
      },
      {
        title: '错误数',
        dataIndex: 'error_num',
        align:'center',
        width: 130,
        key: 'error_num',
      },
      {
        title: '平均延迟',
        dataIndex: 'duration_average',
        align:'center',
        key: 'duration_average',
        width: 130,
        render: (text, record) => (
          <span>{(record.duration_average && Number(record.duration_average).toFixed(2)) || 0}</span>
        )
      },
      {
        title: '中位延迟',
        dataIndex: 'duration_median',
        align:'center',
        width: 140,
        key: 'duration_median',
        render: (text, record) => (
          <span>{(record.duration_median && Number(record.duration_median).toFixed(2)) || 0 }</span>
        )
      }
    ];
    const cloudColums2 = [
      {
        title: '应用名称',
        align:'center',
        dataIndex: 'name',
        width: 210,
        key: 'name'
      },
      {
        title: '请求总数',
        align:'center',
        width: 100,
        dataIndex: 'request_total',
        key: 'request_total',
      },
      {
        title: '错误数',
        align:'center',
        width: 140,
        dataIndex: 'error_num',
        key: 'error_num',
      },
      {
        title: '平均延迟',
        dataIndex: 'duration_average',
        align:'center',
        width: 130,
        key: 'duration_average',
        render: (text, record) => (
          <span>{(record.duration_average && Number(record.duration_average).toFixed(2)) || 0}</span>
        )
      },
      {
        title: '中位延迟',
        dataIndex: 'duration_median',
        align:'center',
        width: 140,
        key: 'duration_median',
        render: (text, record) => (
          <span>{(record.duration_median && Number(record.duration_median).toFixed(2)) || 0 }</span>
        )
      }
    ];
    const expandedRowRender = (record) => {
      const columns = [
        {
          title: '服务名',
          dataIndex: 'service_name_cn',
          align:'center',
          width: 180,
          key: 'service_name_cn',
        },
        {
          title: '请求总数',
          dataIndex: 'request_total',
          align:'center',
          width: 114,
          key: 'request_total',
        },
        {
          title: '错误数',
          dataIndex: 'error_num',
          align:'center',
          width: 120,
          key: 'error_num',
        },
        {
          title: '平均延迟',
          dataIndex: 'duration_average',
          key: 'duration_average',
          align:'center',
          width: 130,
          render: (text, record) => (
            <span>{(record.duration_average && Number(record.duration_average).toFixed(2)) ||0 }</span>
          )
        },
        {
          title: '中位延迟',
          dataIndex: 'duration_median',
          key: 'duration_median',
          align:'center',
          width: 130,
          render: (text, record) => (
            <span>{(record.duration_median && Number(record.duration_median).toFixed(2)) || 0 }</span>
          )
        }
      ];
      return <Table columns={columns} rowKey={'service_name'}  dataSource={record.service_list} pagination={false} size='small' />;
    };
    return (
      <Drawer  placement="right"
      onClose={this.handleClickClose} visible={true}
      destroyOnClose={true}
      width="65%">
        <div className="tour-step-anchor node-details">
          {tools}
          <div className="node-details-header" style={styles.header}>
            <div className="node-details-header-wrapper">
              <h2 className="node-details-header-label truncate">
              {label}
              </h2>
              <div className="node-details-header-relatives">
                {this.state.nodeData.subtitle}
              </div>
            </div>
          </div>
          {/* {showControls
            && (
            <div className="tour-step-anchor node-details-controls-wrapper" style={styles.controls}>
              <NodeDetailsControls
                nodeId={this.props.nodeId}
                controls={details.controls}
                pending={pending}
                error={error} />
            </div>
            )
          } */}
          {
            this.props.shape == 'cylinder'&&
            <div className="node-details-content" >
              <div style={{marginTop:'16px'}}>
                <div className="node-details-content-section-header" style={{marginBottom:0}}>执行次数</div>
                <div id="chartContent"  style={{width: '100%', height: '300px', borderRadius: '12px'}}></div>
              <div style={{paddingBottom:'20px'}}>
                <Table dataSource={this.state.tableData} columns={colums2} rowKey={(record, index) => `${record.service_name}${index}`} pagination={this.state.pagination2} onChange={this.handleTableChange2} size='small' >
                </Table>
              </div>
              </div>
            </div>
          }


          { this.props.shape == 'circle'&&
            (<div className="node-details-content">
              <div>
                <div className="node-details-content-section">
                  <div className="node-details-content-section-header">基本信息</div>
                  <div className='node-details-info'>
                    <div style={{textAlign:'right'}}>
                      <Button size='small'><a target='_blank' style={{fontSize:'12px'}} href={`${this.state.traceUrl}/#/service/serviceDetail/index?app_alias=${this.state.queryParams.app_alias}&service_name=${this.props.id}&isShowBackBtn=false`}>服务详情</a></Button>
                    </div>
                  </div>
                </div>

          {/* https://zhongdian.feishu.cn/docx/HkXSdrGa2ou84zxPvvycGX5Fn3b 中让去掉的 */}
                {/* <div className="node-details-content-section">
                  <div className="node-details-content-section-header">状态</div>
                  <div>
                      <div className='node-details-info-field'>
                        <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>可用性</div>
                        <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>
                          {this.state.nodeData.apdex?Math.floor(this.state.nodeData.apdex*100):0}
                        </div>
                      </div>
                      <div className='node-details-info-field'>
                        <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>成功率</div>
                        <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.arc__success?Number(this.state.nodeData.arc__success*100).toFixed(2):0}%</div>
                      </div>
                      <div className='node-details-info-field'>
                        <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>失败率</div>
                        <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.arc__faild?Number(this.state.nodeData.arc__faild*100).toFixed(2):0}%</div>
                      </div>
                      <div className='node-details-info-field'>
                        <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>接收数量</div>
                        <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.receive?this.state.nodeData.receive:0}</div>
                      </div>
                      <div className='node-details-info-field'>
                        <div className='node-details-info-field-label truncate w50' style={{width:"50%"}}>发送数量</div>
                        <div className='node-details-info-field-value truncate w50' style={{width:"50%"}}>{this.state.nodeData.send?this.state.nodeData.send:0}</div>
                      </div>
                  </div>
                </div> */}
                <div className="node-details-content-section">
                  <div className="node-details-content-section-header">调用次数</div>
                  <div className='node-details-info'>
                    {
                      <div>
                        <div  id='box' className="echartsbox"></div>
                      </div>
                    }
                  </div>
                </div>

                <div className="node-details-content-section">
                  <div className="node-details-content-section-header">延迟比例</div>
                  <div className='node-details-info' style={{marginTop: "-15px",position:'relative'}}>
                    {
                      <div>
                        <div id='main' className="echartsbox" style={{height:'240px'}}></div>
                      </div>
                    }
                    <div className='LatencySelect'>
                      <Radio.Group onChange={this.onChange} value={this.state.queryParams.percentile} size="small">
                        <Radio value={0.5}>50分位</Radio>
                        {/* <Radio value={0.95}>p.95</Radio> */}
                        <Radio value={0.99}>99分位</Radio>
                      </Radio.Group>
                    </div>
                  </div>
                </div>

                <div className='node-details-content-section'>
                  <div className="node-details-content-section-header">链路列表</div>
                  <div className='node-serch'>
                    <Checkbox onChange={this.onChangeError}>仅异常</Checkbox>
                    <Checkbox onChange={this.onChangeSql}>仅SQL</Checkbox>
                  </div>
                  <Table dataSource={this.state.traceData} columns={columns} rowKey={(record, index) => `${record.span_id}${index}`}  pagination={this.state.pagination} onChange={this.handleTableChange} size='small'>
                    {/* <span slot='trace_id' slot-scope='text,record'>
                      <template>
                        <div>
                          <a target='_blank' href={`${this.state.traceUrl}/#/latency/index?traceId=${record.trace_id}&app_alias=${this.state.queryParams.app_alias}&span_id=${record.span_id}`}>{record.trace_id}</a>
                        </div>
                      </template>
                    </span> */}
                  </Table>
                </div>
              </div>
            </div>)
          }
          {
            this.props.shape == 'dottedcylinder' && (
              <div className='ant-descriptions-header'>
                <Descriptions title="" >
                  {/* <Descriptions.Item label="系统名称">{this.state.messaging_stats.name}</Descriptions.Item> */}
                  <Descriptions.Item label="生产消息数量">{this.state.messaging_stats.produce_num || 0}</Descriptions.Item>
                  <Descriptions.Item label="消费消息数量">{this.state.messaging_stats.consume_num || 0}</Descriptions.Item>
                  <Descriptions.Item label="生产消息错误率">{this.state.messaging_stats.produce_error_rate?Number(this.state.messaging_stats.produce_error_rate*100).toFixed(2):0}</Descriptions.Item>
                  <Descriptions.Item label="消费消息错误率">{this.state.messaging_stats.consume_error_rate?Number(this.state.messaging_stats.consume_error_rate*100).toFixed(2):0}</Descriptions.Item>
                  <Descriptions.Item label="生产消息平均耗时">{this.state.messaging_stats.produce_duration_average?Number(this.state.messaging_stats.produce_duration_average).toFixed(2):0}</Descriptions.Item>
                  <Descriptions.Item label="消费消息耗时">{this.state.messaging_stats.consume_duration_average?Number(this.state.messaging_stats.consume_duration_average).toFixed(2):0}</Descriptions.Item>
                  <Descriptions.Item label="平均消息大小">{this.state.messaging_stats.message_size_average?Number(this.state.messaging_stats.message_size_average).toFixed(2):0}</Descriptions.Item>
                  <Descriptions.Item label="主题数量">{this.state.messaging_stats.topic_num || 0}</Descriptions.Item>
                </Descriptions>
               <div className="bisic-title">主题统计信息</div>
               <div>
                 {this.state.messaging_stats && this.state.messaging_stats.topic_stats && this.state.messaging_stats.topic_stats.length > 0  && this.state.messaging_stats.topic_stats.map((item, index)=>{
                   return <Descriptions key={index+item.name} >
                     <Descriptions.Item label="主题名称" >{item.name || '--'}</Descriptions.Item>
                     <Descriptions.Item label="生产消息数量">{item.produce_num || 0}</Descriptions.Item>
                     <Descriptions.Item label="消费消息数量">{item.consume_num || 0}</Descriptions.Item>
                     <Descriptions.Item label="生产消息错误率">{item.produce_error_rate ? Number(item.produce_error_rate*100).toFixed(2)+'%' :0}</Descriptions.Item>
                     <Descriptions.Item label="消费消息错误率">{item.consume_error_rate?Number(item.consume_error_rate*100).toFixed(2)+ '%' :0}</Descriptions.Item>
                     <Descriptions.Item label="生产消息平均耗时">{item.produce_duration_average?Number(item.produce_duration_average).toFixed(2):0}</Descriptions.Item>
                     <Descriptions.Item label="消费消息耗时">{item.consume_duration_average?Number(item.consume_duration_average).toFixed(2):0}</Descriptions.Item>
                     <Descriptions.Item label="平均消息大小">{item.message_size_average?Number(item.message_size_average).toFixed(2):0}</Descriptions.Item>
                   </Descriptions>
                 })}
               </div>
              </div>

            )
          }
          {
            this.props.shape == 'cloud' && (
              <div className="node-details-content" >
                <div style={{marginTop:'30px'}}>
                  <div style={{width:'100%'}}>
                    <h4>已知应用</h4>
                    <Table dataSource={this.state.cloudTable}
                    columns={cloudColums}

                    rowKey={'app_alias'}
                    expandedRowRender={(record) => expandedRowRender(record)}
                    size='small' bordered pagination={false}>
                    </Table>
                  </div>
                  <div style={{marginTop:'40px'}}>
                    <h4>未知应用</h4>
                    <div style={{paddingLeft: '80px'}}>
                      <Table dataSource={this.state.cloudTable2}
                      columns={cloudColums2}
                      rowKey={`name`}  size='small' bordered pagination={false}>
                      </Table>
                    </div>
                  </div>

                </div>
              </div>)
          }
        </div>
      </Drawer>
    );
  }

  //获取基础信息
  getNodeBasic(){
    axios({
      url: `${this.state.baseUrl}/api/v1/apps_score/${this.state.queryParams.app_alias}/svr`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        source_service:this.props.id,
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time
      }
    }).then(res => {
        if(res && res.data.code == 200){
          const newObj= ((res ||{}).data || {}).data || {}
          this.setState({
            nodeData:{...newObj}
          },()=>{
            if(JSON.stringify(this.state.nodeData)!="{}"){
              this.state.nodeData.apdex>=0.94?this.setState({bgColor:setNodeColor('G')})
              :(this.state.nodeData.apdex>=0.85&&this.state.nodeData.apdex<0.94)?this.setState({bgColor:setNodeColor('B')})
              :(this.state.nodeData.apdex>=0.7&&this.state.nodeData.apdex<0.85)?this.setState({bgColor:setNodeColor('DI')})
              :(this.state.nodeData.apdex>=0.5&&this.state.nodeData.apdex<0.7)?this.setState({bgColor:setNodeColor('Y')})
              :this.setState({bgColor:setNodeColor('R')})
            }else{
              this.setState({bgColor:setNodeColor('R')})
            }
          })
        }
    });
  }

  //获取散点图--延迟比例
  getNodeAnalyst(){
    let chart = echarts.getInstanceByDom(document.getElementById("main"));
    if (chart == null) {
      chart = echarts.init(document.getElementById("main"));
    }else {
      chart.dispose();
      chart = echarts.init(document.getElementById("main"));
    }
    // 显示loading动画
    chart.showLoading(
      {
        text: ''
      }
    );
    axios({
      url: `${this.state.baseUrl}/api/v1/app/analyst/${this.state.queryParams.app_alias}/svr`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        source_service:this.props.id,
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time,
        percentile:this.state.queryParams.percentile
      }
    }).then(res => {
        chart.hideLoading();
        if(res && res.data.code == 200){
          const obj = ((res || {}).data ||{}).data || {}
          this.setState({
            AnalystData:{...obj}
          },()=>{
            if(JSON.stringify(this.state.AnalystData)!="{}"){
              this.initChart(this.state.AnalystData, chart)
            }
          })
        }
    });
  }

  // 散点图渲染
  initChart(tmpData, chart) {
    let option = {}

    if (tmpData?.success || tmpData?.failed){
      let successData = tmpData.success && tmpData.success.map(item => new Date(item[0]).toLocaleString()) || []
      let failedData = tmpData.failed && tmpData.failed.map(item => new Date(item[0]).toLocaleString()) || []
      option = {
        title: {
          text: '',
          subtext: '',
          textStyle:{
            fontSize:14
          },
        },
        grid: {
          top:'8%',
          left: '3%',
          right: '7%',
          bottom: '14%',
          containLabel: true
        },
        tooltip: {
          showDelay: 0,
          formatter: function (params) {
            let newParams = moment(params.data[0]).format('YYYY-MM-DD HH:mm:ss');
            let time = newParams+"<br/>"+ '延迟：' + params.data[1]+"ms"
            return time;
          }
        },
        toolbox: {
          show:true,
          showTitle: true,
          feature: {
            rect: {
              show: true,
              title: 'Trace选择'
            },
            brush: {
              type: ["rect"], // 开启矩形选择
              show: true,//是否显示 这里我们直接true
              iconStyle: {
                opacity: 0,//通过opacity设置为0隐藏图标
              },
            }
          },
          left:"40%",                              //组件离容器左侧的距离,'left', 'center', 'right','20%'
          top:"-3%",                                   //组件离容器上侧的距离,'top', 'middle', 'bottom','20%'
          right:"auto",                               //组件离容器右侧的距离,'20%'
          bottom:"auto",
        },
        brush: {
          toolbox: ['rect'],
          brushLink: 'all', // 设置brush时同时选中x轴和y轴的数据
          throttleType:'debounce',
          throttleDelay:600
        },
        legend: {
          data: ['成功', '失败'],
          left: 'center',
          bottom: 0,
          itemGap: 100,
          textStyle: {//文字颜色
            fontSize: 12,
            padding:[0,3],//文字与图形之间的左右间距
            rich:{
              labelName:{
                fontSize:14,
                color:'#333',
                fontWeight:500
              }
            }
          },
          formatter: function (params) {
            // 获取legend显示内容
            let data = tmpData;
            let sl,fl;
            if(data.success!=null){
              sl = tmpData.success.length;
            }else{
              sl = 0
            }
            if( data.failed!=null){
              fl = tmpData.failed.length;
            }else{
              fl = 0
            }
            var target;
            if(params == '成功'){
              target = sl;
            }else if(params == '失败'){
              target = fl;
            }
            return target != undefined?params +' '+`{labelName|${target}}`:params
          },
        },
        xAxis: [
          {

            type: 'time',
            data: [
            ...successData,
            ...failedData
            ],
            gridIndex:0,
            axisLabel: {
              show:true,
              rotate: 45, // 旋转标签，适用于标签较长的情况
              interval: 'auto',
              margin: 10, // 增加刻度标签间隔
              textStyle: {
                fontSize: 10,
                textAlign:'center'
              },
              formatter: function(params) {
                let newParams = moment(params).format('HH:mm:ss');
                let time = newParams
                return time;
              }
            },
            splitLine: {
              show: true
            },
          }
        ],
        yAxis: [
          {
            type: 'value',
            // scale: true,
            gridIndex:0,
            boundaryGap: [0, '30%'],
            axisLabel: {
              formatter: '{value}'
            },
            axisLine:{
              show:true
            },
            axisTick:{
              show:true
            },
            splitLine: {
              show: true
            },
            data:[0,2500,5000,7500,10000],
          }
        ],
        series: [
          {
            name: '成功',
            type: 'scatter',
            emphasis: {
              focus: 'series'
            },
            //设置散点图样式
            itemStyle:{
              color:'#13ce66'
            },
            symbolSize:10,//设置散点的大小
            data:tmpData.success,
            markArea: {
              silent: true,
              itemStyle: {
                color: 'transparent',
                borderWidth: 0,
                borderType: 'dashed'
              },
            },
          },
          {
            name: '失败',
            type: 'scatter',
            emphasis: {
              focus: 'series'
            },
            itemStyle:{
              color:'#ff4949'
            },
            // prettier-ignore
            data:tmpData.failed,
            // data:[],
            markArea: {
              silent: true,
              itemStyle: {
                color: 'transparent',
                borderWidth: 0,
                borderType: 'dashed'
              },
            },
          }
        ]
      }
    } else {
      option = {
        title: {
          text: '暂无数据',
          x: 'center',
          y: 'center',
          textStyle: {
            color: '#999',
            fontSize: 14
          }
        }
      }
    }

    chart.setOption(option,true)
    // 默认开启框选
    chart.dispatchAction({
      type: 'takeGlobalCursor',
      key: 'brush',
      brushOption: {
        brushType: 'rect' // 指定选框类型
      }
    })
    chart.off("brushSelected");
    //框选选择数据
    chart.on('brushSelected', (params) => {

      var brushComponent = params.batch[0];

      let successIndexList=[];
      let failIndexList =[];
      let successList=[];
      let failList=[];
        if(brushComponent.selected.length>1){
          successIndexList = brushComponent.selected[0].dataIndex
          failIndexList = brushComponent.selected[1].dataIndex
        }else{
          if(brushComponent.selected[0].seriesName !=undefined){
            if(brushComponent.selected[0].seriesName =="失败"){
              failIndexList = brushComponent.selected[0].dataIndex
            }else{
              successIndexList = brushComponent.selected[0].dataIndex
            }
          }
        }

        if(successIndexList.length>0){
            for(let i = 0;i<tmpData.success.length;i++){
              for(let j=0;j<successIndexList.length;j++){
                if(successIndexList[j] == i){
                  successList.push(tmpData.success[i])
                }
              }
            }
        }

        if(failIndexList.length>0){
          for(let k=0;k<tmpData.failed.length;k++){
            for(let l=0;l<failIndexList.length;l++){
              if(failIndexList[l] == k){
                failList.push(tmpData.failed[k])
              }
            }
          }
        }

        let arr =successList.concat(failList);
        let dataRange={};
        if(arr.length>0){
            let timeArr =[];
            let valueArr=[];
            for(let m=0;m<arr.length;m++){
              timeArr.push(Math.round(Date.parse(arr[m][0])/1000));
              valueArr.push(arr[m][1]);
            }

            let minTime = Math.min(...timeArr);
            let maxTime = Math.max(...timeArr);

            let minValue = Math.min(...valueArr);
            let maxValue = Math.max(...valueArr)

            if(minTime == maxTime){
              minTime = minTime-1;
              maxTime = maxTime+1;
            }

            if(minValue == maxValue){
              minValue = minValue-1;
              maxValue = maxValue+1;
            }


            //看是否有成功节点
            if(successIndexList.length>0){
                dataRange = {
                start_time:minTime,
                end_time:maxTime,
                min_duration:minValue,
                max_duration:maxValue,
                failed:false,
                app_alias:this.state.queryParams.app_alias,
                service_name:this.props.id,
              }
            }else{
              dataRange = {
                start_time:minTime,
                end_time:maxTime,
                min_duration:minValue,
                max_duration:maxValue,
                failed:true,
                app_alias:this.state.queryParams.app_alias,
                service_name:this.props.id,
              }
            }


            let timeAndDuration = JSON.stringify(dataRange);

            // let href = this.$router.resolve({
            //   path:'/latency/index',
            //   query:{
            //     data:timeAndDuration
            //   }
            // })
            // window.open(window.location.origin+"/"+href.href,"_blank")


            let href = `${this.state.traceUrl}/#/latency/index?start_time=${dataRange.start_time}&end_time=${dataRange.end_time}&min_duration=${dataRange.min_duration}&max_duration=${dataRange.max_duration}&failed=${dataRange.failed}&app_alias=${this.state.queryParams.app_alias}&service_name=${this.props.id}`
              window.open(href,"_blank")
              this.timeoutId = setTimeout(()=>{
              chart.dispatchAction({
                  type: 'brush',//选择action行为
                  areas:[]//areas表示选框的集合，此时为空即可。
              });
            },500)

        }


    });

    window.addEventListener("resize",function (){
      chart.resize();
    });
  }

  //获取折线图
  getNodeLiveness(){
    let liveChart = echarts.getInstanceByDom(document.getElementById("box"));
    if (liveChart == null) {
      liveChart = echarts.init(document.getElementById("box"));
    }else {
      liveChart.dispose();
      liveChart = echarts.init(document.getElementById("box"));
    }
    liveChart.showLoading(
      {
        text: ''
      }
    );
    axios({
      url: `${this.state.baseUrl}/api/v1/service/liveness`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        service_name:this.props.id,
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time,
      }
    }).then(res => {
        liveChart.hideLoading();
        if(res && res.data.code == 200){
          const list = ((res || {}).data || {}).data || []
          this.setState({
            livenessData:[...list]
          },()=>{
            this.initLiveness(this.state.livenessData, liveChart);
          })
        }
    });
  }
  //渲染折线图
  initLiveness(data, liveChart){
    let option = {}
    if (data.length > 0 ){
      const xAxisData = []
      const lineArr1 = []
      const lineArr2 = []

      data.forEach((item)=>{
        if (item){
          xAxisData.push(item[0])
          lineArr1.push(item[1])
          const num = item[2] && item[2].toFixed(2)
          lineArr2.push(num)
        }
      })
      option = {
        grid: {
          top:'15%',
          left: '3%',
          right: '7%',
          bottom: '14%',
          containLabel: true
        },
        tooltip: {
          trigger: 'axis',
          showDelay: 0,
          formatter: function (params) {
            if (params && params.length === 2) {
              let newParams = moment(params[0].name).format('YYYY-MM-DD HH:mm:ss');
              let time = newParams+"<br/>"+ params[0].seriesName +':'+ params[0].value + '<br/>' + params[1].seriesName +':'+ params[1].value
              return time;

            }
            return ''
          }
        },
        xAxis: {
          data: xAxisData,
          type: 'category',
          boundaryGap: false,
          axisLabel: {
            show:true,
            rotate: 45, // 旋转标签，适用于标签较长的情况
            interval: 10,
            margin: 10, // 增加刻度标签间隔
            textStyle: {
              fontSize: 10,
              textAlign:'center'
            },
            formatter: function(params) {
              let newParams = moment(params).format('HH:mm:ss');
              let time = newParams
              return time;
            }
          },
          splitLine: {
            show: true
          },
        },

        yAxis: [
          {
            boundaryGap: [0, '20%'],
            type: 'value',
            show:true,
            name: '调用次数',
            position: 'left',
            alignTicks: true,
            axisLine: {
              show: true
            },
            axisLabel: {
              formatter: '{value}'
            }
          },
          {
            boundaryGap: [0, '20%'],
            type: 'value',
            show:true,
            offset: 0,          // 防止与第一个Y轴重叠
            // splitNumber: 5,
            nameGap: 20,  // 设置 Y 轴名称和轴线之间的间距
            name: '中位延迟',
            position: 'right',
            alignTicks: true,
            axisLine: {
              show: true
            },
            axisLabel: {
              formatter: '{value} ms'
            }
          },
        ],
        legend: {
          data: ['调用次数', '中位延迟'],
          bottom: 0,
          itemGap: 100,
        },
        series: [
          {
            name: '调用次数',
            type: 'line',
            smooth: true,
            yAxisIndex: 0,  // 使用第一条 Y 轴
            data: lineArr1
          },
          {
            name: '中位延迟',
            type: 'line',
            smooth: true,
            yAxisIndex: 1,  // 使用第二条 Y 轴
            data: lineArr2
          }
        ]
      };

    } else {
      option = {
        title: {
          text: '暂无数据',
          x: 'center',
          y: 'center',
          textStyle: {
            color: '#999',
            fontSize: 14
          }
        }
      }
    }
    liveChart.setOption(option,true)
  }

  //获取异常trace列表 /api/v1/service/spans
  getServiceSpans(){
    this.setState({ loading: true });
    this.setState({
      traceData:[],
      pagination:{total:0}
    },()=>{
    })
    axios({
      url: `${this.state.baseUrl}/api/v1/service/spans`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        service_name:this.props.id,
        only_exception:this.state.traceQuery.only_exception,  // 仅显示异常trace相关
        only_database:this.state.traceQuery.only_database,
        pageIndex:this.state.pagination.pageIndex,
        pageSize:this.state.pagination.pageSize,
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time,
        app_alias:this.state.queryParams.app_alias,
        sort_field:'Timestamp',
        sort_type: this.state.queryParams.sort_type
      }
    }).then(res => {

        if(res && res.data.code == 200){
          const list = (((res || {}).data || {}).data || {}).list || []
          const total = Number((((res || {}).data || {}).data || {}).count || 0)
          this.setState({
            traceData:[...list],
            pagination:{...this.state.pagination,total:total}
          },()=>{
          })
        }
    });
  }
  //获取table 数据
  getTableData(){
    this.setState({ loading: true });
    this.setState({
      tableData:[],
      pagination2:{total:0}
    },()=>{
    })
    axios({
      url: `${this.state.coreBaseUrl}/v1/system-component/reqlist`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        page_num:this.state.pagination2.page_num,
        page_size:this.state.pagination2.page_size,
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time,
        app_alias:this.state.queryParams.app_alias,
        component: this.props.id//
      }
    }).then(res => {

        if(res && res.data.code == 200){
          const list = (((res || {}).data || {}).data || {}).list || []
          const total = Number((((res || {}).data || {}).data || {}).total || 0)
          const page_num = (((res || {}).data || {}).data || {}).page_num || 1
          const page_size = (((res || {}).data || {}).data || {}).page_size || 10
          this.setState({
            tableData:[...list],
            pagination2:{page_num:page_num,page_size:page_size,total:total}
          },()=>{
          })
        }
    });
  }
  getBarData(){// 获取柱状图数据
    let liveChart = echarts.getInstanceByDom(document.getElementById("chartContent"));
    if (liveChart == null) {
      liveChart = echarts.init(document.getElementById("chartContent"));
    } else {
      liveChart.dispose();
      liveChart = echarts.init(document.getElementById("chartContent"));
    }
    this.setState({
      tableData:[],
      pagination2:{total:0}
    },()=>{
    })
    liveChart.showLoading(
      {
        text: ''
      }
    );
    axios({
      url: `${this.state.coreBaseUrl}/v1/system-component/stats`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time,
        app_alias:this.state.queryParams.app_alias,
        component: this.props.id //
      }
    }).then(res => {
      liveChart.hideLoading();
      if(res && res.data.code == 200){
        const list = res?.data?.data?.database_stats?.request_bar || []
        this.setState({
          barData:list
        },()=>{
          if(this.state.barData.length>0){
            setTimeout(()=>{
              this.initLineBar(this.state.barData, liveChart);
            },0)
          }
        })
      }
    });
  }

  // 渲染调用统计 折线/柱形图
  initLineBar(data, liveChart){
    let xAxisArr = data.map(item => item.start_time) || []
    let dataArr = data.map(item => item.total) || []
    let option = {}
    if (data && data.length > 0) {
      option = {
        xAxis: {
          type: 'category',
          data: xAxisArr,
          axisLabel: {
            show:true,
            rotate: 45, // 旋转标签，适用于标签较长的情况
            interval: 'auto',
            margin: 10, // 增加刻度标签间隔
            textStyle: {
              fontSize: 10,
              textAlign:'center'
            },
            formatter: function(params) {
              let newParams = moment(params).format('HH:mm:ss');
              let time = newParams
              return time;
            }
          },
        },
        tooltip: {
          showDelay: 0,
          axisPointer: {
            show: true,
            type: 'cross',
            lineStyle: {
              type: 'dashed',
              width: 1
            }
          }
        },
        yAxis: {
          type: 'value'
        },
        series: [
          {
            data: dataArr,
            type: 'bar'
          }
        ]
      };
    } else {
      option = {
        title: {
          text: '暂无数据',
          x: 'center',
          y: 'center',
          textStyle: {
            color: '#999',
            fontSize: 14
          }
        }
      }
    }

    liveChart.setOption(option,true)
  }
  handleTableChange=(pagination,filters, sorter, extra)=>{
    const {current} = pagination
    let sort = ''
    if(sorter && sorter.order == 'ascend'){
      sort = 'ASC'
    } else if(sorter && sorter.order == 'descend'){
      sort = 'DESC'
    }

    this.setState({
      pagination: {...this.state.pagination,pageIndex:current,current:current},
      queryParams:{...this.state.queryParams,sort_type:sort}
    },()=>{
      this.getServiceSpans();
    });
  }
  handleTableChange2=(pagination,filters, sorter, extra)=>{
    const {current} = pagination
    this.setState({
      pagination2: {...this.state.pagination2,page_num:current}
    },()=>{
      this.getTableData();
    });
  }
  //仅异常
  onChangeError = e =>{
    const only_exception = e.target.checked ? 1:0;
    const pageIndex = 1
    const current = 1
    this.setState({
      traceQuery:{...this.state.traceQuery,only_exception:only_exception},
      pagination: {...this.state.pagination,pageIndex:pageIndex,current:current},
    },()=>{
      this.getServiceSpans();
    });

  }
  //仅sql
  onChangeSql = e =>{
    const only_database = e.target.checked ? 1:0;
    const pageIndex = 1
    const current = 1
    this.setState({
      traceQuery:{...this.state.traceQuery,only_database:only_database},
      pagination: {...this.state.pagination,pageIndex:pageIndex,current:current},
    },()=>{
      this.getServiceSpans(this.props.source,this.props.target);
    });
  }

   //单选按钮
  onChange = e => {
    const percentile = e.target.value
    this.setState({
      queryParams:{...this.state.queryParams,percentile:percentile},
      AnalystData:[]
    },()=>{
      this.getNodeAnalyst();
    });
  };

  renderTable(table) {
    const { nodeMatches = makeMap() } = this.props;

    if (isGenericTable(table)) {
      return (
        <NodeDetailsGenericTable
          rows={table.rows}
          columns={table.columns}
          matches={nodeMatches.get('tables')}
        />
      );
    } if (isPropertyList(table)) {
      return (
        <NodeDetailsPropertyList
          rows={table.rows}
          controls={table.controls}
          matches={nodeMatches.get('property-lists')}
        />
      );
    }

    log(`Undefined type '${table.type}' for table ${table.id}`);
    return null;
  }

  componentDidUpdate() {
    this.updateTitle();
  }

  updateTitle() {
    setDocumentTitle(this.props.details && this.props.details.label);
  }

  //dottedcylinder 类型 -获取基础信息
  getDottBasicsData(){
    this.setState({ loading: true });
    this.setState({
      messaging_stats:{
        topic_stats:[]
      }
    },()=>{
    })
    axios({
      url: `${this.state.coreBaseUrl}/v1/system-component/stats`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        start_time:this.state.queryParams.start_time,
        end_time:this.state.queryParams.end_time,
        app_alias:this.state.queryParams.app_alias,
        component: this.props.id//
      }
    }).then(res => {

        if(res && res.data.code == 200){
          const messaging_stats = (((res || {}).data || {}).data || {}).messaging_stats || {}
          this.setState({
            messaging_stats:messaging_stats
          },()=>{
          })

        }
    });
  }

  // cloud 类型-获取嵌套table
  getCloudTableData(){// 获取柱状图数据
    this.setState({ loading: true });
    this.setState({
      cloudTable:[],
      cloudTable2:[],
    },()=>{
    })
    axios({
      url: `${this.state.coreBaseUrl}/v1/service/related-apps`,
      method: "get",
      headers: { 'Authorization': getToken },
      params: {
        start_time: this.state.queryParams.start_time, //1727366400
        end_time:this.state.queryParams.end_time, // 1727415703
        app_alias:this.state.queryParams.app_alias,
        type: this.props.id //
      }
    }).then(res => {
      if(res && res.data.code == 200){
        const list = (((res || {}).data ||{}).data || {}).app_list || []
        const list2 = (((res ||{}).data ||{}).data ||{}).client_list || []

        this.setState({
          cloudTable:[...list],
          cloudTable2: [...list2]
        },()=>{
        })
      }
    });
  }
}

NodeDetails.propTypes = {
  renderNodeDetailsExtras: PropTypes.func,
};

NodeDetails.defaultProps = {
  renderNodeDetailsExtras: noop,
};

function mapStateToProps(state, ownProps) {
  const currentTopologyId = state.get('currentTopologyId');
  return {
    nodeMatches: state.getIn(['searchNodeMatches', currentTopologyId, ownProps.id]),
    nodes: state.get('nodes'),
    selectedNodeId: state.get('selectedNodeId'),
    transitioning: state.get('pausedAt') !== ownProps.timestamp,
  };
}

export default connect(
  mapStateToProps,
  { clickCloseDetails, clickShowTopologyForNode }
)(NodeDetails);
