alibaba / x-render

🚴‍♀️ 阿里 - 很易用的中后台「表单 / 表格 / 图表」解决方案
https://xrender.fun
7.08k stars 1.01k forks source link

自定义了一个Table组件,为啥表单提交的时候,没有拿到填写的内容呢? #1580

Open freesaber opened 1 day ago

freesaber commented 1 day ago

下面是表单设计的JsonSchema,其中table_Wr5xOu是自定义的一个组件

{
    "type": "object",
    "labelWidth": 120,
    "displayType": "row",
    "pageSize": "",
    "pageBackground": "",
    "properties": {
        "input_0HuktS": {
            "title": "请假人",
            "type": "string",
            "props": {}
        },
        "number_GFQbeS": {
            "title": "请假天数",
            "type": "number",
            "default": 1
        },
        "date_oWMz7e": {
            "title": "开始时间",
            "type": "string",
            "format": "date"
        },
        "radioGroup_xhNZgf": {
            "title": "请假原因",
            "type": "string",
            "widget": "RadioGroup",
            "layout": "竖向排布",
            "options": [
                {
                    "value": "1",
                    "label": "事假"
                },
                {
                    "value": "2",
                    "label": "病假"
                },
                {
                    "value": "3",
                    "label": "年假"
                }
            ]
        },
        "table_Wr5xOu": {
            "title": "车牌统计",
            "type": "object",
            "widget": "Table",
            "columns": [
                {
                    "title": "姓名",
                    "dataIndex": "name",
                    "render": "单行输入框"
                },
                {
                    "title": "部门",
                    "dataIndex": "dept",
                    "render": "单行输入框"
                },
                {
                    "title": "车牌号",
                    "dataIndex": "number",
                    "render": "单行输入框"
                }
            ],
            "rows": 6,
            "properties": {}
        }
    }
}

下面是自定义Table组件的代码

import React, { useState, useEffect } from 'react';
import { Table as AntTable, Input, InputNumber } from 'antd';
const { TextArea } = Input;
import UploadImg from '../../UploadImg/Render'; // 引入自定义图片上传组件

const Table = (props: any) => {
  const { columns, value, onChange, schema, rows } = props;

  // 初始化 dataSource,根据 rows 动态生成
  const [dataSource, setDataSource] = useState<any[]>([]);

  useEffect(() => {
    if (value && value.length > 0) {
      setDataSource(value);
    } else {
      // 初始化空的数据源,key 为唯一标识
      const initialData = Array.from({ length: rows }, (_, index) => ({
        key: `${index + 1}`,
      }));
      setDataSource(initialData);
    }
  }, [value, rows]);

  // 渲染每个列的表单控件
  const renderFormItem = (text: any, record: any, col: any, index: number) => {
    switch (col.render) {
      case '单行输入框':
        return (
          <Input
            defaultValue={text}
            onChange={(e) => handleInputChange(e.target.value, record, col.dataIndex)}
          />
        );
      case '数字输入框':
        return (
          <InputNumber
            defaultValue={text}
            onChange={(value) => handleInputChange(value, record, col.dataIndex)}
          />
        );
      case '多行输入框':
        return (
          <TextArea
            defaultValue={text}
            onChange={(e) => handleInputChange(e.target.value, record, col.dataIndex)}
            rows={2}
          />
        );
      case '图片上传':
        return (
          <UploadImg
            value={text}
            onChange={(url: any) => handleImageChange(url, record, col.dataIndex)}
          />
        );
      default:
        return text;
    }
  };

  // 处理 Input 输入变化
  const handleInputChange = (value: string | number, record: any, dataIndex: string) => {
    const newData = [...dataSource];
    const target = newData.find((item) => item.key === record.key);
    if (target) {
      target[dataIndex] = value;
      console.log('newData', newData);
      setDataSource(newData);
      onChange?.(newData); // 通知父组件数据已更新
    }
  };

  // 处理图片上传变化
  const handleImageChange = (url: string, record: any, dataIndex: string) => {
    const newData = [...dataSource];
    const target = newData.find((item) => item.key === record.key);
    if (target) {
      target[dataIndex] = url;
      setDataSource(newData);
      onChange?.(newData); // 通知父组件数据已更新
    }
  };

  // 生成表格列配置,动态渲染表单控件
  const tableColumns = columns.map((col:any) => ({
    ...col,
    render: (text: any, record: any, index: number) => renderFormItem(text, record, col, index),
  }));

  return (
    <AntTable
      rowKey="key"
      size='small'
      dataSource={dataSource}
      columns={tableColumns}
      pagination={false}
    />
  );
};

export default Table;

我在表格中填写内容,控制台可以正常打印输出: image

[
    {
        "key": "1",
        "name": "1",
        "dept": "2",
        "number": "3"
    },
    {
        "key": "2"
    },
    {
        "key": "3"
    },
    {
        "key": "4"
    },
    {
        "key": "5"
    },
    {
        "key": "6"
    }
]

问题是,form进行表单提交onFinish的时候

<FormRender
        style={{padding: '12px'}}
        form={form}
        schema={schema}
        onFinish={onFinish}
        maxWidth={600}
        footer={footer => (
          <Space>
            <Button type="primary" htmlType="submit" loading={loading}>提交</Button>
          </Space>
        )}
        widgets={{ ...Widgets }}
      />

其中,formData这个是时候,没有自定义组件,填写的表单项了 const onFinish = (formData:any) => {

} // 这里的formData如下:

{
    "id": "1310632669099073536",
    "formId": "1859417564759007234",
    "fillUserId": null,
    "fillUserName": null,
    "fillTime": "2024-11-25T15:46:18.690Z",
    "fillJson": "{\"input_0HuktS\":\"本人\",\"number_GFQbeS\":1,\"date_oWMz7e\":\"2024-11-01\",\"radioGroup_xhNZgf\":\"2\"}"
}

有大佬,方便指点一下吗?

freesaber commented 1 day ago

好像是表单设计的时候,这里的类型错了 "table_Wr5xOu": { "title": "车牌统计", "type": "object",

应该改成string