从零实现一套低代码(保姆级教程)【后端服务】 --- 【9】实现Table表格组件以及数据展示

摘要

经过前面几章的内容,我们的后端服务已经支持了对页面的管理,对图片的管理,并且也支持了在XinBuilder中如何去使用它们。其实到目前为止,我们的XinBuilderServer服务,已经具备了基本的功能了。

可能是因为我是前端开发的原因,所以我在做这个项目重点一直是放在前端的功能实现的。后端代码比较少。

话说回来,这一篇继续回归到XinBuilder的项目里,再上一篇中,我们实现了和实体相关的后端内容,也就是我们有了持久化的数据存储。但是有了数据之后,我们如何能够在低代码项目里面使用?

对于数据的使用无非就是数据的处理以及数据的展示,在数据展示上,我们有很多种方式,比较常见的有表格,列表等等。

本篇主要通过Table组件来串通数据在XinBuilder中如何展示。

1.创建一张Student表

前期的准备工作,我们就在平台下创建一张Student表。

创建好后,我们来到swagger中,给这张表增加几条数据。

这里可以多加一些数据,方便后续的展示。

有了数据之后,我们希望的是,在XinBuilder中实现一个Table组件,可以去展示这些数据。或者去展示某张表的部分数据。

所以Table组件是一定需要一个属性,去选择对应的实体以及字段。

2.创建Table组件,实现选择实体的功能

Table组件我们放在数据展示分组里面,之前写过很多组件的创建。至于创建组件的过程,这里就不去贴代码了。

我们要实现的是给Table组件能够选择实体的功能。

所以在tableAttribute中,我们需要一个弹窗类型的属性。

javascript 复制代码
  {
    label: '选择实体',
    value: 'entityCode',
    type: 'modal',
    modalType: 'EntitySelect'
  },

同时,在modal下新建一个EntitySelect的文件夹。用来去选择对应的实体,和实体下面的字段。

我们要实现出一个可以选择实体,以及实体下字段的弹窗。

上面的Select选择器用来选择对应的实体,然后再通过Switch去选择该实体下的字段。 所以对于表格组件就需要两个属性。

entityCode:实体编码 schemaList:需要展示的字段

这里我们贴一下弹窗的代码:

javascript 复制代码
import { useEffect, useState } from 'react';
import { Modal, Select, Switch, message } from 'antd';
import { getComById } from '../../../utils/nodeUtils'
import Store from '../../../store/index'
import axios from 'axios';

export interface Entity {
  entityCode: string,
  entityName: string,
  entitySchema: EntitySchema
}

interface EntitySchema {
  [key: string]: string
}

const EntitySelect: React.FunctionComponent = (props: any) => {
  const { openModal, setOpenModal, valueKey } = props;
  const comList = JSON.parse(JSON.stringify(Store.getState().comList))
  const selectCom = Store.getState().selectCom
  const selectNode = getComById(selectCom, comList)
  const [nodeSchemaList, setNodeSchemaList] = useState([...(selectNode.schemaList || [])])

  const [entityList, setEntityList] = useState<Entity []>([])
  const [selectEntity, setSelectEntity] = useState(selectNode.entityCode || '')

  useEffect(() => {
    axios.post("http://localhost:4000/entity/getEntityList")
    .then(res => {
      if(res.data.data) {
        setEntityList(res.data.data)
      }else {
        message.error("请求实体列表失败")
      }
    })
  }, [])

  const handleCancel = () => {
    setOpenModal(false)
    setSelectEntity(selectNode.entityCode || '')
    setNodeSchemaList([...(selectNode.schemaList || [])])
  }

  const handleOk = () => {
    if(selectNode) {
      selectNode[valueKey as keyof typeof selectNode] = selectEntity;
      selectNode.schemaList = nodeSchemaList;
    }
    Store.dispatch({type: 'changeComList', value:comList})
    setOpenModal(false)
    setSelectEntity(selectNode.entityCode || '')
    setNodeSchemaList([...(selectNode.schemaList || [])])
  }

  const getOptions = () => {
    return entityList.map((item: Entity) => {
      return {
        value: item.entityCode,
        label: item.entityCode
      }
    })
  }

  const changeEntity = (value: string) => {
    setSelectEntity(value)
    setNodeSchemaList([])
  }

  const changeSwitch = (schemaCode: string) => {
    return (value: boolean) => {
      if(value && !nodeSchemaList.includes(schemaCode)) {
        nodeSchemaList.push(schemaCode)
      }else if(!value && nodeSchemaList.includes(schemaCode)) {
        const index = nodeSchemaList.indexOf(schemaCode);
        nodeSchemaList.splice(index,1)
      }
      setNodeSchemaList([...nodeSchemaList])
    }
  }

  const getSchemaList = () => {
    const entity = entityList.find((item: Entity) => item.entityCode === selectEntity);
    const schemaList = Object.keys(entity?.entitySchema || {}) || [];
    return <div style={{display:'flex', width:400, justifyContent:'flex-start',flexWrap:'wrap'}}>
      {
        schemaList.map(item => {
          return <div style={{width:'100px'}}>
            <p>{item}</p>
            <Switch onChange={changeSwitch(item)} value={nodeSchemaList.includes(item)}></Switch>
          </div>
        })
      }
    </div>
  }
  
  return <Modal closable={false} open={openModal} onOk={handleOk} onCancel={handleCancel}>
    <div style={{width:250, display:'flex',justifyContent:'space-between'}}>
      <div style={{marginTop:'5px', fontWeight:1000}}>选择实体:</div>
      <Select onChange={changeEntity} value={selectEntity} style={{width: 150}} options={getOptions()}></Select>
    </div>
    <div>
      {
        getSchemaList()
      }
    </div>
  </Modal>;
};

export default EntitySelect;

Ok,有了这个弹窗之后,我们就可以给表格组件赋予这两个属性了。

3.实现表格的数据展示

当表格组件有了这两个属性之后,我们就可以在表格内部通过ajax请求到对应的数据。 赋给表格的columns属性和datasource属性。

javascript 复制代码
import { useState, useEffect } from 'react';
import { Table as AntTable, message } from 'antd';
import axios from 'axios';

const Table: React.FunctionComponent = (props: any) => {
    const { entityCode, schemaList, size, bordered, showHeader = true, pagination = false, comStyle } = props;
    const [entityData, setEntityData] = useState([])
  

    useEffect(() => {
        axios.post("http://localhost:4000/entity/getEntityData", {entityCode})
        .then(res => {
            if(res.data.data) {
                setEntityData(res.data.data)
            }
        })
    }, [entityCode])

    const getColumns = () => {
        return schemaList.map((item: any) => {
            return {
                title: item,
                dataIndex: item,
                key: item
            }
        })
    }

    const getData = () => {
        return entityData.map((item: any) => {
            return {
                key: item._id,
                ...item
            }
        })
    }
 
    return <AntTable
        dataSource={getData()}
        columns={getColumns()}
        size={size}
        pagination={pagination}
        bordered={bordered}
        showHeader={showHeader}
        style={{...comStyle}}
    />;
};

export default Table;

4.补充表格的其他属性

最后我们在给表格补充一下其他属性和样式。 就可以通过关联对应的实体,确定表格的columns和data。从而正常展示数据库中的数据了。

这部分代码提交在github上
github.com/TeacherXin/...
commit: fix: 第十九节:增加Table组件

相关推荐
killerbasd6 小时前
还是迷茫 5.3
前端·react.js·前端框架
亲亲小宝宝鸭12 小时前
拖一拖控件,拖出个问卷(低代码平台)
前端·低代码
江南十四行12 小时前
ReAct Agent 基本理论与项目实战(一)
前端·react.js·前端框架
谢尔登15 小时前
10_从 React Hooks 本质看 useState
前端·ubuntu·react.js
辰同学ovo15 小时前
从全局登录状态管理学习 Redux
前端·javascript·学习·react.js
光影少年16 小时前
reeact虚拟DOM、Diff算法原理、key的作用与为什么不能用index
前端·react.js·掘金·金石计划
wenzhangli717 小时前
在低代码设计中践行 Harness Engineering
android·低代码·rxjava
江南十四行17 小时前
ReAct Agent 基本理论与项目实战(二)
前端·react.js·前端框架
摘星编程18 小时前
当AI开始学会“使用工具“——从ReAct到MCP,大模型如何获得真正的行动力
前端·人工智能·react.js
啊哈一半醒20 小时前
React 核心知识点系统总结:从基础语法到高级 API,一篇文章梳理完整学习路线
javascript·学习·react.js