美文网首页
测试平台系列(22) 编写项目的增删改查接口和页面(4)

测试平台系列(22) 编写项目的增删改查接口和页面(4)

作者: 米洛丶 | 来源:发表于2021-04-10 19:03 被阅读0次

    回顾

    上一节已经贴出了项目列表页面的全部前端代码,由于笔者前端也没有深入学习,所以只能给大家大概讲解一下吧。还是按照之前的几个部分来说吧!

    状态管理

    image

    设置了如下变量:

    • data

      存放当前项目数组

    • pagination

      项目分页

    • visible

      创建项目表单是否可见,默认是否

    • users

      由于我们需要选择项目管理员,所以需要一个userId => 用户信息的映射。当然这个接口我们暂时还没有实现。

    方法编写

    const fetchData = async (current=pagination.current, size=pagination.size) => {
      await process(async ()=> {
        const res = await listProject({page: current, size });
        if (auth.response(res)) {
          setData(res.data)
          setPagination({...pagination, total: res.total})
        }
      });
    }
    

    这个方法是获取项目列表的方法,current代表page,size代表分页大小,如果不传入则是pagination默认的值。

    listProject其实就是包装的request方法,请求后端服务。

    useEffect(async () => {
      await fetchData();
    }, [])
    
    const onSearchProject = async projectName => {
      await process(async ()=> {
        const res = await listProject({page: 1, size: pagination.size, name: projectName});
        if (auth.response(res)) {
          setData(res.data)
          setPagination({...pagination, current: 1, total: res.total})
        }
      });
    }
    

    useEffectreact新版本的特性,它支持2个参数,第一个是方法,第二个是变量数组,传入空数组的话,则每次这个组件开始渲染的时候会调用且只调用一次方法。

    我们如果正式使用的话,是会有多套测试环境的。如果我们对项目做了环境的区分,那么就应该在切换环境的时候,获取不同环境的项目。

    假设我们需要实现这种功能,那么我们先创建一个env的变量,然后改写useEffect:

    useEffect(async () => {
      await fetchData();
    }, [env])
    

    这样的话,每当env发生变化,这个方法就会自动执行一次。需要说明的是,这里只是介绍一下useEffect的使用方式,因为我们这边暂时还没有扩展到多套环境,所以此处我们选择[]即可

    const onHandleCreate = async values => {
      const res = await insertProject(values);
      if (auth.response(res, true)) {
        // 创建成功后自动获取第一页的数据, 因为项目会按创建时间排序
        await fetchData(1);
      }
    }
    

    这边也如出一辙,创建完毕了之后如果接口未返回错误,则刷新项目列表页面,并且自动去第一页

    const content = (item) => {
      return <div>
         {/* <p>负责人: {userMap[item.owner].name}</p> */}
         <p>简介: {item.description || '无'}</p>
         <p>更新时间: {item.updated_at}</p>
      </div>
    };
    
    const opt = <Select placeholder="请选择项目负责人">
      {
        Object.keys(users).map(id => <Option key={id} value={id}>{users[id].name}</Option>)
      }
    </Select>
    
    const fields = [
        {
          name: 'projectName',
          label: '项目名称',
          required: true,
          message: "请输入项目名称",
          type: 'input',
          placeholder: "请输入项目名称",
        },
        {
          name: 'owner',
          label: '项目负责人',
          required: true,
          component: opt,
          type: 'select',
        },
        {
          name: 'description',
          label: '项目描述',
          required: false,
          message: "请输入项目描述",
          type: 'textarea',
          placeholder: "请输入项目描述",
        },
        {
          name: 'private',
          label: '是否私有',
          required: true,
          message: "请选择项目是否私有",
          type: 'switch',
          valuePropName: "checked",
        },
      ]
    

    这里content是一个方法,会返回一个div的html结构,目的是为了展示项目的详情,比如负责人项目描述等。

    fields的话,是表单的字段,因为我针对antd的form进行了一点封装,编写了一套高阶组件。等于说是规划好了表单里面的表单组成,由input和select以及switch组件组成

    待会会讲这个组件!

    最后看return里面的组件

        return (
          <PageContainer title={false}>
            <FormForModal width={600} title="添加项目" left={6} right={18} record={{}}
                          visible={visible} onCancel={() => setVisible(false)} fields={fields} onFinish={onHandleCreate}
            />
            <Row gutter={8} style={{marginBottom: 16}}>
              <Col span={18}>
                <Button type="primary" onClick={() => setVisible(true)}>创建项目
                  <Tooltip title="只有超级管理员可以创建项目"><QuestionCircleOutlined/></Tooltip>
                </Button>
              </Col>
              <Col span={6}>
                <Search onSearch={onSearchProject} style={{float: 'right'}} placeholder="请输入项目名称"/>
              </Col>
            </Row>
            <Spin spinning={false}>
              <Row gutter={16}>
                {
                  data.length === 0 ? <Col span={24} style={{textAlign: 'center', marginBottom: 12}}>
                      <Card><Empty description="暂无项目, 快点击『创建项目』创建一个吧!"/></Card>
                    </Col> :
                    data.map(item =>
                      <Col key={item.id} span={4} style={{marginBottom: 12}}>
                        <Popover content={content(item)} placement="rightTop">
                          <Card hoverable bordered={false} style={{borderRadius: 16, textAlign: 'center'}}
                                bodyStyle={{padding: 16}} onClick={() => {
                            history.push(`/project/${item.id}`);
                          }}>
                            <Avatar style={{backgroundColor: '#87d068'}} size={64}
                            >{item.name.slice(0, 2)}</Avatar>
                            <p style={{
                              textAlign: 'center',
                              fontWeight: 'bold',
                              fontSize: 18,
                              marginTop: 8
                            }}>{item.name}</p>
                          </Card>
                        </Popover>
                      </Col>
                    )
                }
              </Row>
            </Spin>
          </PageContainer>
        )
    }
    

    PageContainer是最外层,也就是咱们看到的这一块:

    image

    FormForModal是一个对话框表单,默认是不显示的,只有点击创建项目才会显示。

    然后用Row分了2行: 分别是 创建栏/搜索栏和项目展示栏

    image

    这边项目展示栏如果data.length === 0就展示一个空状态,提示用户去添加项目,否则就把项目展示出来,每个项目占屏幕的1/6,因为Col总共有24份。

    tips: 这里类似于bootstrap,一行共有24份,所以span={4}代表的是4/24,可参考: 官网介绍

    image

    其他的就是Card(卡片)组件和Avatar(头像)组件的互相嵌入,Popover是悬浮窗口,如图:

    image

    编写获取用户列表的接口

    修改app/dao/auth/UserDao.py

    image

    筛选出未被删除的用户即可。

    修改app/controllers/auth/user.py

    image

    这里注意开启一下权限,但是不能控制太死,能让登录用户访问即可。

    前端页面编写listUsers方法

    image

    看下效果

    image

    发现一个问题: 创建成功后,对话框没有关闭

    所以我们需要在创建成果后,setVisible(false)去关闭对话框。

    image

    还有一个地方就是之前注释掉的项目负责人,现在可以重新开启了。

    image image

    看下搜索效果

    image image

    这就是本节的内容了,大部分是讲解代码为主,因为前端内容居多,所以可能有点懵逼。如果有不理解的地方,还请多多看看reactes6相关的教程。箭头函数,看着别怕,熟悉了就好。

    下一节可能是具体项目的编辑页面了,感觉这一讲就讲了一个世纪,再后面就是用例那块了。

    相关文章

      网友评论

          本文标题:测试平台系列(22) 编写项目的增删改查接口和页面(4)

          本文链接:https://www.haomeiwen.com/subject/rvbnkltx.html