自动化测试平台(八):列表组件公共化封装和用例项目管理功能开发

x33g5p2x  于2021-12-23 转载在 其他  
字(6.1k)|赞(0)|评价(0)|浏览(420)

一、前言

上一章我们完成了整个用户管理模块的功能,能够正确的增、删、改、查用户。但其中有很多判断实际上是其他类似的模块也会有的,例如:

  1. 创建用户后回到首页刷新列表;
  2. 删除次页最后一条数据,回到前一页刷新列表;
  3. 查询条件的格式化;

难道我们每写一个类似的模块,都要去写一遍这些重复的逻辑代码吗?

显然是没必要的,所以我们需要将其抽离成公共列表组件提供给其他模块使用,避免大量的做重复的事情,并让代码更容易维护。本章还将完成用例项目管理功能,它主要用于管理不同类型(API、UI),不同项目、项目状态等。

由于博主本身也才开始使用ts,很多类型都是用any来定义的,后续会逐渐完善。

项目在线演示地址:http://121.43.43.59/ (帐号:admin 密码:123456)

实现效果如下:

二、实现公共列表组件

1. 公共Table组件

src/components下创建ComTable文件夹,并在其下创建index.tsx文件,它的代码如下:

import React, { useImperativeHandle, useRef, useState } from 'react';
import ProTable from '@ant-design/pro-table';
import { Button } from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import { reqList, reqDelete } from '@/globalEnum';
interface ActionType {
  reload: () => void;
  fetchMore: () => void;
  reset: () => void;
}
const Table: React.FC<any> = ({
  actionRef,
  func,
  headerTitle,
  showModal,
  columns,
}) => {
  const ref = useRef<ActionType | any>();
  const [params, setParams] = useState<any>({ page: 1, page_size: 10 }); //默认请求第一页,10条数据
  const [dataLength, setDataLength] = useState<number>(0); //列表返回数据的长度(行数)
  const handlePagination: any = {
    pageSize: params.page_size,
    showSizeChanger: false,
    page: params.page,
    onChange: (current: number, size: number) => {
      setParams({ page: current, page_size: size });
    },
  };
  useImperativeHandle(actionRef, () => ({
    tableRef: ref,
    comDeleteData: (func: any, record_id: any) => {
      func(record_id, reqDelete).then((res: any) => {
        if (params.page > 1 && dataLength <= 1) {
          //在非首页的最后一条数据被删除时,改变页码为前一页进行请求
          setParams({ ...params, ...{ page: params.page - 1 } });
        }
        ref.current.reload();
      });
    }
  }));
  return (
    <ProTable
      actionRef={ref}
      columns={columns}
      scroll={{ y: 'calc(100vh - 300px)' }}
      request={(...tableParams) => {
        var filters: object = tableParams[2];
        for (let key in filters) {
          //删除查询条件为空的
          if (!filters[key]) {
            delete filters[key];
          }
        }
        setParams({ ...params, ...filters });
        return func({ ...params, ...filters }, reqList).then((res: any) => {
          setDataLength(res.data.length);
          return res;
        });
      }}
      rowKey="id"
      pagination={handlePagination}
      size="middle"
      headerTitle={< h3 style={{ fontWeight: 'bold' }}> {headerTitle}</h3 >}
      search={false}
      toolBarRender={() => [
        <Button
          type="primary"
          icon={<PlusOutlined />}
          onClick={() => showModal('create')}
        >
          新建
        </Button>,
      ]}
      dateFormatter="string"
    />
  );
};
export default React.memo<any>(Table);

这里只是简单封装,可以根据自己的需求进行diy

2. 用户列表接入公共Table组件

公共Table完成后,可以将我们之前用户模块代码进行接入,完整代码如下:

import React, { useState, useEffect, useRef } from 'react';
import { ProColumns } from '@ant-design/pro-table';
import { message } from 'antd';
import { reqCreate, reqUpdate } from '@/globalEnum';
import { UserAll } from '@/services/users';
import Form from './form';
import ComTable from '@/components/ComTable';

const User: React.FC = () => {
  const ref = useRef<any>();
  const [tableRef, setTableRef] = useState<any>({});
  const [formData, setFormData] = useState<any>({}); //传递给弹窗显示的数据
  const [formVisible, setFormVisible] = useState<boolean>(false); //控制弹窗显示还是隐藏
  useEffect(() => {
    setTableRef(ref.current.tableRef)
  }, []);
  const columns: ProColumns[] = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
      width: 100,
      render: (v: any, record: any) => (
        <span>{`${record.last_name}${record.first_name}`}</span>
      ),
    },
    {
      title: '用户名',
      key: 'username',
      width: 100,
      dataIndex: 'username',
    },
    {
      title: '邮箱地址',
      key: 'email',
      dataIndex: 'email',
      width: 200,
    },
    {
      title: '加入时间',
      key: 'date_joined',
      dataIndex: 'date_joined',
      width: 200,
      valueType: 'dateTime',
    },
    {
      title: '状态',
      dataIndex: 'is_active',
      width: 100,
      filters: true,
      filterMultiple: false,
      valueEnum: {
        true: { text: '启用', status: 'Success' },
        false: { text: '禁用', status: 'Error' },
      },
    },
    {
      title: '操作',
      key: 'option',
      dataIndex: 'option',
      width: 120,
      valueType: 'option',
      render: (v: any, record: any) => [
        <a key={record.id} onClick={() => showModal('update', record)}>
          修改
        </a>,
        <a
          key={record.id}
          onClick={() => { ref.current.comDeleteData(UserAll, record.id) }}
        >
          删除
        </a>,
      ],
    },
  ];

  //点击新建/修改,执行的代码
  const showModal = (type: string, values = {}) => {
    values['formType'] = type;
    setFormData(values);
    setFormVisible(true);
  };

  // 弹窗点确认按钮执行的方法
  const onFormFinish = async (values: any, formType: string) => {
    var reqType: string;
    if (formType === 'create') {
      reqType = reqCreate;
    } else {
      reqType = reqUpdate;
      values.id = formData.id;
    }
    return await UserAll(values, reqType).then((res) => {
      message.success('操作成功!');
      setFormVisible(false);
      formType === 'create' ? tableRef.current.reloadAndRest() : tableRef.current.reload();
    });
  };

  return (
    <>
      <Form
        formData={formData}
        onFinish={(values: object, formType: string) =>
          onFormFinish(values, formType)
        }
        cancel={() => setFormVisible(false)}
        visible={formVisible}
      />
      <ComTable
        actionRef={ref}
        columns={columns}
        func={UserAll}
        showModal={showModal}
        headerTitle="用户列表"
      />
    </>
  );
};
export default React.memo(User);

三、实现项目管理功能

1. 后台接口

首先在代码项目下执行创建项目模块的命令:

django-admin startapp project

为了让后面创建的表都有创建时间结束时间这两个字段,需要先在comFunc文件夹中创建一个comModel.py的文件,用于放置公共的数据库模型,这样需要拥有公共模型字段的模型继承公共模型即可。
拥有创建时间结束时间的公共模型代码如下:

from django.db import models

class ComModel(models.Model):
    """ 公共模型 """
    created = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated = models.DateTimeField(auto_now=True, verbose_name='修改时间', null=True, blank=True)

    class Meta:
        abstract = True

然后在model.py中添加项目的数据库模型代码:

from django.db import models
from comFunc.comModel import ComModel

class Project(ComModel):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=32, verbose_name="项目名称")
    remark = models.TextField(blank=True, null=True, verbose_name="备注")
    status = models.IntegerField(verbose_name="项目状态")
    type = models.IntegerField(verbose_name="项目类型")

    class Meta:
        verbose_name = '项目表'
        db_table = 'project'

再在settings.py配置里的INSTALLED_APPS中加入project进行注册,然后执行模型迁移的命令即可:

python manage.py makemigrations
python manage.py migrate

这样我们就把项目模块的数据库表建立成功了,再按照user模块中的代码、代码结构并结合之前的教程进行代码开发即可。

2. 前端页面

1)在前端项目下,执行创建project模块文件的命令:

npx umi g page project/index --typescript

2)在.umirc.ts文件配置路由中加入project的跳转:

routes: [
     	...
        {
          name: '项目管理',
          path: '/project',
          icon: 'users',
          component: '@/pages/project',
        },
        ...
      ],

这样我们就把项目模块的基础页面建立好了,再按照user模块的代码并结合之前的教程进行代码开发即可,实现后的效果如下:

需要注意的是,在用例类型的筛选中,自定义了proTable的valueType实现,教程文档地址:自定义valueType

四、总结

这一章主要涉及技术的教学只有一个公共列表组件的抽离和使用,其他都是重复的CURD了,所以只给了数据库表模型,没有直接贴代码。

需要源码的可以点击下方的演示地址进行获取:

在线演示地址:http://121.43.43.59/ (帐号:admin 密码:123456)

欢迎在文章头部右上角订阅本专栏,及时获取最新教程分享!

相关文章