chengaofeng
发布于 2024-10-11 / 8 阅读
0
0

记链表在前端的一次应用

import React from 'react';
import { Table, Space, Button } from 'antd';
import { getPodFromK8sController } from '../api';
import dayjs from 'dayjs';
import { css } from '@emotion/react';
import styles from './index.module.less';

import { ColumnsType } from 'antd/es/table';
import { useMemoizedFn } from 'ahooks';

const tableColumns: ColumnsType<{
  name: string;
  resources: {
    limits: {
      cpu: string;
      memory: string;
    };
  };
}> = [
  {
    dataIndex: 'resources',
    title: 'CPU',
    render: (text, record) => record?.resources?.limits?.cpu,
  },
  {
    dataIndex: 'resources',
    title: '内存',
    render: (text, record) => record?.resources?.limits?.memory,
  },
];

const tableStyle = css`
  padding: 5px 5px 5px 0;
  & .devops-ant-table {
    margin-left: 0 !important;
  }
`;

const columns: ColumnsType<{
  metadata: {
    name: string;
    uid: string;
    namespace: string;
    labels: {
      app: string;
      'pod-template-hash': string;
    };
    resourceVersion: string;
    ownerReferences: [
      {
        kind: string;
        name: string;
      }
    ];
  };
  status: {
    phase: string;
    podIP: string;
    hostIP: string;
    startTime: string;
  };
  spec: {
    nodeName: string;
    containers: {
      name: string;
      resources: {
        limits: {
          cpu: string;
          memory: string;
        };
      };
    }[];
  };
}> = [
  {
    dataIndex: 'metadata',
    title: 'Pod名称',
    ellipsis: true,
    width: 200,
    fixed: 'left',
    render: (text, record) => record.metadata.name,
  },
  {
    dataIndex: 'spec',
    title: '节点名称',
    ellipsis: true,
    width: 200,
    render: (text, record) => record.spec.nodeName,
  },
  {
    dataIndex: 'spec',
    title: '容器',
    width: 100,
    render: (text, record) => (
      <div css={tableStyle}>
        <Table
          size="small"
          columns={tableColumns}
          rowKey="name"
          dataSource={record.spec.containers || []}
          bordered
          pagination={false}
        />
      </div>
    ),
  },
  {
    dataIndex: 'status',
    title: '运行状态',
    ellipsis: true,
    width: 80,
    render: (text, record) => record.status.phase,
  },
  {
    dataIndex: 'status',
    title: 'Node地址',
    ellipsis: true,
    width: 100,
    render: (text, record) => record.status.hostIP,
  },
  {
    dataIndex: 'status',
    title: 'Pod地址',
    ellipsis: true,
    width: 100,
    render: (text, record) => record.status.podIP,
  },
  {
    dataIndex: 'status',
    title: '创建时间',
    ellipsis: true,
    width: 150,
    render: (text, record) => dayjs(record.status.startTime).format('YYYY-MM-DD HH:mm:ss'),
  },
];

interface Node {
  value?: string;
  prev?: Node;
  next?: Node;
}

export interface ChildTableProps {
  k8s_cluster_name: string;
  namespace: string;
  k8s_cluster: {
    area: string;
    group_name: string;
  };
}

const ChildTable: React.FC<ChildTableProps> = (props: ChildTableProps) => {
  const { k8s_cluster_name: cluster_name, namespace: name_space, k8s_cluster } = props;
  const { group_name } = k8s_cluster;
  const [dataSource, setDataSource] = React.useState<any[]>([]);
  const [loading, setLoading] = React.useState(false);
  // 链表记住历史,上一页,下一页
  const [link, setLink] = React.useState<Node | undefined>({
    prev: undefined,
    next: undefined,
    value: undefined,
  });
  const [total, setTotal] = React.useState(0);

  const getData = useMemoizedFn(() => {
    if (cluster_name && name_space && group_name) {
      setLoading(true);
      getPodFromK8sController({
        continue: link?.value,
        cluster_name,
        name_space,
        group_name,
        limit: 10,
      })
        .then(data => {
          const { items, metadata } = data;
          const { continue: next, remainingItemCount } = metadata || {};
          if (next) {
            setLink(p => ({ ...p, next: { value: next, prev: p, next: undefined } }));
          }
          setDataSource(items || []);
          setTotal(remainingItemCount || 0);
        })
        .finally(() => setLoading(false));
    }
  });

  React.useEffect(() => {
    getData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [link?.value]);

  const handlePrev = useMemoizedFn(() => {
    setLink(p => p?.prev);
  });

  const handleNext = useMemoizedFn(() => {
    setLink(p => p?.next);
  });

  return (
    <div className={styles.tableContainer} css={{ padding: '10px 0' }}>
      <Table
        bordered
        rowKey={record => record.metadata.uid}
        size="small"
        scroll={{ x: 1300 }}
        dataSource={dataSource}
        columns={columns}
        loading={loading}
        pagination={false}
      />
      <div css={{ padding: 5 }}>
        <Space>
          <Button
            type="primary"
            size="small"
            loading={loading}
            disabled={link?.value === undefined}
            onClick={handlePrev}
          >
            上一页
          </Button>
          <Button
            loading={loading}
            type="primary"
            size="small"
            disabled={total <= 0}
            onClick={handleNext}
          >
            下一页
          </Button>
          <span>剩余 {total} 条</span>
        </Space>
      </div>
    </div>
  );
};

export default React.memo(ChildTable);


评论