index.jsx 9.05 KB
/**
 * Author: Charles
 * Date: 2022.9.13
 * Description: [风险列表]
 */
import React, { useEffect } from 'react';
import { connect } from 'umi';
import {
  Card,
  Form,
  Input,
  Button,
  Table,
  Select,
  DatePicker,
  Tooltip,
  Upload,
  message,
} from 'antd';
import { paginations, mapStatus, mapRiskType, mapRiskSourceType } from '@/constants';
import {
  StyledPageContainer,
  StyledPageContent,
  StyledEllipsisWrap,
  StyledPageHeader,
} from '@/components/style';
import { UploadOutlined } from '@ant-design/icons';
import moment from 'moment';
import * as services from '@/services/risk';
import { ExportFile } from '@/utils/utils';

const { RangePicker } = DatePicker;
const FormItem = Form.Item;
const { Option } = Select;

/* SearchForm */
const SearchForm = props => {
  const [form] = Form.useForm();
  const {
    dataSearch,
    dataSearch: { startTime, endTime },
    handleReset,
    handleFinish,
  } = props;

  useEffect(() => {
    form.setFieldsValue({
      ...dataSearch,
      createTime: [
        startTime ? moment(startTime) : undefined,
        endTime ? moment(endTime) : undefined,
      ],
    });
  }, [dataSearch]);

  /* 点击搜索 */

  const onFinish = values => {
    handleFinish(values);
  };

  /* 点击重置 */
  const onReset = () => {
    handleReset();
  };

  return (
    <Form name="Form_Risk" layout="inline" form={form} onFinish={onFinish}>
      <FormItem label="网站地址" name="riskHost">
        <Input placeholder="请输入网站地址" style={{ width: '250px' }} />
      </FormItem>
      <FormItem label="风险类型" name="riskType">
        <Select placeholder="请选择风险类型" style={{ width: '150px' }}>
          <Option value="ALL">全部</Option>
          {Object.values(mapRiskType).map(item => {
            const { label, value } = item;
            return (
              <Option key={value} value={value}>
                {label}
              </Option>
            );
          })}
        </Select>
      </FormItem>
      <FormItem label="风险源类型" name="fileFormat">
        <Select placeholder="请选择风险源类型" style={{ width: '150px' }}>
          <Option value="ALL">全部</Option>
          {Object.values(mapRiskSourceType).map(item => {
            const { label, value } = item;
            return (
              <Option key={value} value={value}>
                {label}
              </Option>
            );
          })}
        </Select>
      </FormItem>
      <FormItem label="处理状态" name="status">
        <Select placeholder="请选择处理状态" style={{ width: '150px' }}>
          <Option value="ALL">全部</Option>
          {Object.values(mapStatus).map(item => {
            const { label, value } = item;
            return (
              <Option key={value} value={value}>
                {label}
              </Option>
            );
          })}
        </Select>
      </FormItem>
      <FormItem label="检测时间" name="createTime">
        <RangePicker allowClear={false} />
      </FormItem>
      <FormItem>
        <Button type="primary" htmlType="submit" className="mr-15">
          搜索
        </Button>
        <Button className="mr-15" htmlType="button" onClick={onReset}>
          重置
        </Button>
      </FormItem>
    </Form>
  );
};

/* DataTable */
const DataTable = props => {
  const {
    loading,
    handleGetList,
    dataRisk: { records = [], current, size, total },
  } = props;

  /* 点击分页 */
  const handlePageChange = (current, size) => {
    handleGetList(current, size);
  };

  const columns = [
    {
      title: '序号',
      dataIndex: 'id',
      align: 'center',
      fixed: 'left',
      width: 80,
      render(t, r, idx) {
        return (current - 1) * size + idx + 1;
      },
    },
    {
      title: '风险源名称',
      dataIndex: 'riskName',
      align: 'center',
      width: 160,
      render: (t, r) => {
        return (
          <Tooltip placement="top" title={t}>
            <StyledEllipsisWrap maxLine={1}>{t}</StyledEllipsisWrap>
          </Tooltip>
        );
      },
    },
    {
      title: '风险源地址',
      dataIndex: 'riskUrl',
      align: 'center',
      width: 160,
      render: (t, r) => {
        return (
          <Tooltip placement="top" title={t}>
            <StyledEllipsisWrap maxLine={2}>{t}</StyledEllipsisWrap>
          </Tooltip>
        );
      },
    },
    {
      title: '风险站点',
      dataIndex: 'riskHost',
      align: 'center',
      width: 160,
      render: (t, r) => {
        return (
          <Tooltip placement="top" title={t}>
            <StyledEllipsisWrap maxLine={2}>{t}</StyledEllipsisWrap>
          </Tooltip>
        );
      },
    },
    {
      title: '关键词',
      dataIndex: 'riskKeyword',
      align: 'center',
      width: 260,
      render: (t, r) => {
        return (
          <Tooltip placement="top" title={t}>
            <StyledEllipsisWrap maxLine={2}>{t}</StyledEllipsisWrap>
          </Tooltip>
        );
      },
    },
    {
      title: '风险类型',
      dataIndex: 'riskType',
      align: 'center',
      width: 160,
      render: (t, r) => {
        return mapRiskType[t] ? mapRiskType[t].label : '-';
      },
    },
    {
      title: '风险源类型',
      dataIndex: 'fileFormat',
      align: 'center',
      width: 160,
      render: (t, r) => {
        return mapRiskSourceType[t] ? mapRiskSourceType[t].label : '-';
      },
    },
    {
      title: '检测时间',
      dataIndex: 'checkTime',
      align: 'center',
      width: 160,
      render: (t, r) => {
        return t ? moment(t).format('YYYY-MM-DD HH:mm:ss') : '-';
      },
    },
    {
      title: '处理状态',
      dataIndex: 'status',
      align: 'center',
      fixed: 'right',
      width: 100,
      render: (t, r) => {
        return mapStatus[t] ? mapStatus[t].label : '-';
      },
    },
  ];
  const pagination = {
    ...paginations,
    total: total,
    pageSize: size,
    current,
    showSizeChanger: total > 10,
    onChange: (current, pageSize) => {
      handlePageChange(current, pageSize);
    },
    onShowSizeChange: (current, pageSize) => {
      handlePageChange(1, pageSize);
    },
    showTotal(total) {
      return `总共 ${total} 条数据`;
    },
  };
  return (
    <Table
      rowKey="id"
      loading={loading}
      dataSource={records}
      columns={columns}
      pagination={pagination}
      scroll={{ x: 1500, y: `calc(100vh - 400px)` }}
    />
  );
};

/* Main */
const Risk = props => {
  const {
    dispatch,
    loading,
    loadingUpload,
    dataSearch,
    dataRisk,
    dataRisk: { size },
  } = props;

  useEffect(() => {
    handleGetList(1, 10);
  }, []);

  /* 账号列表 */
  const handleGetList = (current, size) => {
    dispatch({
      type: 'Risk/getRiskList',
      payload: {
        current: current || 1,
        size: size || 10,
      },
    });
  };

  /* 点击搜索 */
  const handleFinish = values => {
    const { status, riskType, fileFormat, riskHost, createTime } = values;
    dispatch({
      type: 'Risk/changeState',
      payload: {
        dataSearch: {
          status,
          riskType,
          fileFormat,
          riskHost,
          startTime: createTime[0]
            ? moment(createTime[0].startOf('day').valueOf()).format('YYYY-MM-DD HH:mm:ss')
            : undefined,
          endTime: createTime[1]
            ? moment(createTime[1].endOf('day').valueOf()).format('YYYY-MM-DD HH:mm:ss')
            : undefined,
        },
      },
    });
    handleGetList(0, size);
  };

  /* 点击重置 */
  const handleReset = () => {
    dispatch({ type: 'Risk/resetSearch' });
    handleGetList(0, 10);
  };

  /* 上传组件配置 */
  const uploadProps = {
    customRequest: file => {
      const formData = new FormData();
      formData.append('file', file.file);
      dispatch({ type: 'Risk/importRisk', payload: formData });
    },
    beforeUpload: file => {
      const isLt50M = file.size / 1024 / 1024 < 50;
      if (!isLt50M) {
        message.error('文件大小需小于50M');
        return false;
      }
      return isLt50M;
    },
  };

  return (
    <StyledPageContainer>
      <StyledPageHeader>
        <Upload {...uploadProps}>
          <Button loading={loadingUpload} type="primary" icon={<UploadOutlined />}>
            数据导入
          </Button>
        </Upload>
        <Button
          type="primary"
          onClick={() => {
            ExportFile('风险模版', services.exportRiskTemplate, {});
          }}
        >
          模版下载
        </Button>
      </StyledPageHeader>
      <StyledPageContent>
        <Card bordered={false}>
          <SearchForm
            dataSearch={dataSearch}
            handleReset={handleReset}
            handleFinish={handleFinish}
          />
          <div className="mt-16">
            <DataTable loading={loading} handleGetList={handleGetList} dataRisk={dataRisk} />
          </div>
        </Card>
      </StyledPageContent>
    </StyledPageContainer>
  );
};

export default connect(({ Risk, loading }) => ({
  ...Risk,
  loading: loading.effects['Risk/getRiskList'],
  loadingUpload: loading.effects['Risk/importRisk'],
}))(Risk);