一个树状结构的参数需求

基于react antd设计的树状参数需求,之前遇到过这个层级比较深的参数需求,类型与请求后端设计参数,类型可以选择数组对象数字字符串等

ini 复制代码
import React, { useEffect, useState, forwardRef, useImperativeHandle } from 'react';
import { Form, Select, Input, Row, Col, Button, Tree, Space } from 'antd';
import { PlusCircleOutlined, MinusCircleOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import styles from '../index.module.less';
import { cloneDeep } from 'lodash';

const ParamSet = forwardRef((props, ref) => {
  const { onChange, value } = props;
  const [treeData, setTreeData] = useState([
    {
      title: (key) => renderTreeNodesTitle(key),
      key: '0-0',
      isLeaf: false,
      name: 'root',
      type: 'object',
      desc: 'root',
      children: [],
    },
  ]);
  const addNode = (currNode) => {
    if (currNode.isLeaf) {
      currNode.isLeaf = false;
    }
    console.log('currNode', currNode);
    if (currNode.children && currNode.children.length > 0) {
      if (currNode.type === 'array') {
        const firstChild = currNode.children[0];
        currNode.children.push({
          title: (key) => renderTreeNodesTitle(key),
          key: `${currNode.key}-${Date.now().toString().slice(-5)}`,
          isLeaf: true,
          parentType: currNode.type,
          parentNode: currNode,
          name: '',
          type: firstChild.type,
          value: '',
          desc: '',
        });
      } else if (currNode.type === 'object') {
        currNode.children.push({
          title: (key) => renderTreeNodesTitle(key),
          key: `${currNode.key}-${Date.now().toString().slice(-5)}`,
          isLeaf: true,
          parentType: currNode.type,
          name: '',
          type: 'string',
          value: '',
          desc: '',
        });
      }
      console.log('treeData', treeData);
      setTreeData([...treeData]);
      return;
    }
    console.log('zhepaobulai');
    currNode.children = [
      {
        title: (key) => renderTreeNodesTitle(key),
        key: `${currNode.key}-${Date.now().toString().slice(-5)}`,
        isLeaf: true,
        parentType: currNode.type,
        parentNode: currNode,
        name: '',
        type: 'string',
        value: '',
        desc: '',
      },
    ];
    setTreeData([...treeData]);
  };
  const findNodes = (treeData, currNode) => {
    const res = treeData.filter((item) => {
      if (item.key !== currNode.key) {
        if (item.children?.length) {
          item.children = findNodes(item.children, currNode);
        }
        return true;
      } else {
        return false;
      }
    });
    return res;
  };
  const delNode = (currNode) => {
    const res = findNodes(treeData, currNode);
    setTreeData(res);
  };
  const changeParamName = (e, currNode) => {
    console.log(e.target.value);
    currNode.name = e.target.value;
    setTreeData([...treeData]);
  };
  const changeParamType = (e, currNode) => {
    currNode.type = e;
    if (e === 'object' || e === 'array') {
      currNode.children = null;
      currNode.isLeaf = false;
      currNode.value = '';
    } else {
      currNode.children = null;
      currNode.isLeaf = true;
    }
    if (currNode.parentType === 'array') {
      currNode.parentNode.children.forEach((item) => {
        item.type = currNode.type;
      });
    }
    setTreeData([...treeData]);
  };
  const changeParamValue = (e, currNode) => {
    currNode.value = e.target.value;
    setTreeData([...treeData]);
  };
  const changeParamDesc = (e, currNode) => {
    currNode.desc = e.target.value;
    setTreeData([...treeData]);
  };
  const renderTreeNodesTitle = (currNode) => {
    console.log('整棵树', treeData);
    return (
      <div key={currNode.key}>
        <Space size={3}>
          <Input placeholder="参数名" value={currNode.name} disabled={currNode.parentType === 'array'} onChange={(e) => changeParamName(e, currNode)} />
          <Select
            placeholder="参数类型"
            style={{ width: 120 }}
            value={currNode.type}
            onChange={(e) => changeParamType(e, currNode)}
            options={[
              { value: 'string', label: 'string' },
              { value: 'integer', label: 'integer' },
              { value: 'number', label: 'number' },
              { value: 'boolean', label: 'boolean' },
              { value: 'array', label: 'array' },
              { value: 'object', label: 'object' },
            ]}
          />
          <div style={{ width: '120px' }}>
            <Input
              placeholder="参数值"
              disabled={['object', 'array'].includes(currNode.type)}
              value={currNode.value}
              onChange={(e) => changeParamValue(e, currNode)}
            />
          </div>
          <div style={{ width: '120px' }}>
            <Input placeholder="备注" value={currNode.desc} onChange={(e) => changeParamDesc(e, currNode)} />
          </div>
          <div style={{ width: '10px' }}>
            {['object', 'array'].includes(currNode.type) && (
              <PlusCircleOutlined className={styles.headerIcon} onClick={() => addNode(currNode)} />
            )}
          </div>
          <div style={{ width: '10px' }}>
            {!currNode.children?.length && (
              <MinusCircleOutlined className={styles.headerIcon} onClick={() => delNode(currNode)} />
            )}
          </div>
        </Space>
      </div>
    );
  };

  const add = () => {};
  const formatTreeData = (treeData = []) => {
    const res = treeData.map((item) => {
      if (item.type === 'object' || item.type === 'array') {
        if (item.children?.length) {
          item.children = formatTreeData(item.children);
        }
        return {
          name: item.name,
          type: item.type,
          children: item.children,
          desc: item.desc,
        };
      }
      return {
        name: item.name,
        type: item.type,
        value: item.value,
        desc: item.desc,
      };
    });
    return res;
  };
  useEffect(() => {
    const copyData = cloneDeep(treeData);
    const resTreeData = formatTreeData(copyData);
    onChange(resTreeData);
  }, [treeData]);
  useImperativeHandle(ref, () => ({
    getParams: (newParams) => {
      return treeData;
    },
  }));
  return (
    <div>
      <Tree autoExpandParent={true} defaultExpandAll={true} treeData={treeData} />
      {/* <Row>
        <Col span={14}>
          <Button type="dashed" onClick={() => add()} icon={<PlusOutlined />}>
            添加参数信息
          </Button>
        </Col>
      </Row> */}
    </div>
  );
});
export default ParamSet;
相关推荐
加减法原则35 分钟前
Vue3 组合式函数:让你的代码复用如丝般顺滑
前端·vue.js
yanlele1 小时前
我用爬虫抓取了 25 年 6 月掘金热门面试文章
前端·javascript·面试
lichenyang4531 小时前
React移动端开发项目优化
前端·react.js·前端框架
你的人类朋友1 小时前
🍃Kubernetes(k8s)核心概念一览
前端·后端·自动化运维
web_Hsir1 小时前
vue3.2 前端动态分页算法
前端·算法
烛阴2 小时前
WebSocket实时通信入门到实践
前端·javascript
草巾冒小子2 小时前
vue3实战:.ts文件中的interface定义与抛出、其他文件的调用方式
前端·javascript·vue.js
DoraBigHead2 小时前
你写前端按钮,他们扛服务器压力:搞懂后端那些“黑话”!
前端·javascript·架构
Xiaouuuuua3 小时前
一个简单的脚本,让pdf开启夜间模式
java·前端·pdf
@Dream_Chaser3 小时前
uniapp ruoyi-app 中使用checkbox 无法选中问题
前端·javascript·uni-app