瀏覽代碼

added DIY table form

ZhaoJun 1 年之前
父節點
當前提交
27c4b3a844

+ 29 - 24
src/components/AuditForm/ComponentLibrary.js

@@ -3,16 +3,16 @@ import React, { useState } from 'react';
 import { COMPONENT_LIST } from './constant';
 
 function ComponentLibrary(props) {
-  const { visible, onCancel, onOk } = props;
-  const [currnetItem, setCurrentItem] = useState(null);
+  const { visible, onCancel, onOk, addToTable } = props;
+  const [currentItem, setCurrentItem] = useState(null);
 
   const handleOk = () => {
-    if (!currnetItem) {
+    if (!currentItem) {
       message.error('请选择控件');
       return;
     }
     setCurrentItem(null);
-    onOk?.(currnetItem);
+    onOk?.(currentItem);
   };
   const handleCancel = () => {
     setCurrentItem(null);
@@ -21,26 +21,31 @@ function ComponentLibrary(props) {
   return (
     <Modal visible={visible} onCancel={handleCancel} onOk={handleOk}>
       <Row gutter={12} style={{ paddingTop: 20 }}>
-        {COMPONENT_LIST.map(item => (
-          <Col span={8}>
-            <div
-              onClick={() => setCurrentItem(item)}
-              style={{
-                display: 'flex',
-                justifyContent: 'flex-start',
-                alignItems: 'center',
-                border: item == currnetItem ? '1px solid #1890FF' : '1px solid #aaa',
-                width: '100%',
-                padding: '4px 12px',
-                cursor: 'pointer',
-                margin: '10px 0',
-              }}
-            >
-              {item.icon}
-              <span style={{ marginLeft: 8 }}>{item.props.label}</span>
-            </div>
-          </Col>
-        ))}
+        {COMPONENT_LIST.map(item => {
+          if (addToTable && item.componentName === 'DIYTable') {
+            return null;
+          }
+          return (
+            <Col span={8}>
+              <div
+                onClick={() => setCurrentItem(item)}
+                style={{
+                  display: 'flex',
+                  justifyContent: 'flex-start',
+                  alignItems: 'center',
+                  border: item === currentItem ? '1px solid #1890FF' : '1px solid #aaa',
+                  width: '100%',
+                  padding: '4px 12px',
+                  cursor: 'pointer',
+                  margin: '10px 0',
+                }}
+              >
+                {item.icon}
+                <span style={{ marginLeft: 8 }}>{item.props.label}</span>
+              </div>
+            </Col>
+          );
+        })}
       </Row>
     </Modal>
   );

+ 125 - 15
src/components/AuditForm/FormContent.js

@@ -1,9 +1,14 @@
-import { Form } from 'antd';
+import { Button, Form } from 'antd';
 import React, { useState } from 'react';
-import { ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined } from '@ant-design/icons';
+import {
+  ArrowUpOutlined,
+  ArrowDownOutlined,
+  DeleteOutlined,
+  PlusOutlined,
+} from '@ant-design/icons';
 
 function FormContent(props) {
-  const { list, onChange, onSelect } = props;
+  const { list, onChange, onSelect, onTableColumnChange } = props;
   const [currentItem, setCurrentItem] = useState(null);
   const handleDelete = index => {
     let _list = [...list];
@@ -25,9 +30,9 @@ function FormContent(props) {
     _list[index] = temp;
     onChange(_list);
   };
-  const handleSelect = index => {
-    setCurrentItem(index);
-    onSelect(index);
+  const handleFormItemClick = id => {
+    setCurrentItem(id[0]);
+    onSelect(id);
   };
   return (
     <div style={{ width: 300 }}>
@@ -54,9 +59,10 @@ function FormContent(props) {
         );
         return (
           <FormItem
-            key={item.id}
-            active={index == currentItem}
-            onClick={() => handleSelect(index)}
+            key={item.props?.id}
+            active={item.props?.id === currentItem}
+            onClick={handleFormItemClick}
+            onTableColumnChange={onTableColumnChange}
             item={item}
             btns={btns}
           />
@@ -67,24 +73,128 @@ function FormContent(props) {
 }
 
 function FormItem(props) {
-  const { item, btns, active, onClick } = props;
+  const { item, btns, active, onClick, onTableColumnChange } = props;
   const { label, placeholder, required } = item.props;
+
+  // 子控件激活id
+  const [selectColumnID, setSelectColumnID] = useState('');
+
+  // 新增列时通过id定位
+  const addTableColumn = event => {
+    // 记录当前表格uuid
+    onTableColumnChange(item.props.id);
+  };
+
+  // 修改表格内部的控件顺序
+  const changeIndex = (index, operate) => {
+    const newCol = [...item.columns];
+    const prev = newCol[index - 1];
+    const next = newCol[index + 1];
+    switch (operate) {
+      case 'up':
+        newCol[index - 1] = newCol[index];
+        newCol[index] = prev;
+        break;
+      case 'down':
+        newCol[index + 1] = newCol[index];
+        newCol[index] = next;
+        break;
+      case 'delete':
+        newCol.splice(index, 1);
+        break;
+      default:
+        break;
+    }
+    onTableColumnChange(item.props.id, newCol);
+  };
   return (
     <div
       style={{
         marginBottom: 20,
         padding: '4px 12px',
         border: '1px solid #666',
-        borderLeft: active ? '10px solid #1890FF' : '1px solid #666',
+        borderLeft: active && !item.isTable ? '10px solid #1890FF' : '1px solid #666',
+      }}
+      onClick={e => {
+        e.stopPropagation();
+        if (item.isColumn === undefined) {
+          onClick([item.props.id]);
+        } else {
+          onClick();
+        }
       }}
-      onClick={onClick}
     >
-      <div style={{ fontSzie: 24, color: '#000', fontWeight: 'bold', position: 'relative' }}>
+      <div
+        style={{
+          fontSize: 16,
+          color: '#000',
+          fontWeight: 'bold',
+          position: 'relative',
+        }}
+      >
         {required && <i style={{ color: 'red' }}>*</i>}
         {label}
-        <div style={{ position: 'absolute', right: 0, top: 0, padding: '5px 10px' }}>{btns}</div>
+        <div
+          style={{
+            position: 'absolute',
+            right: 0,
+            top: 0,
+            padding: '5px 10px',
+          }}
+        >
+          {btns}
+        </div>
       </div>
-      <div style={{ color: '#999', fontSize: 16 }}>{placeholder}</div>
+      {item.isTable ? (
+        <div style={{ padding: '10px 0 5px 0' }}>
+          {item.columns.map((column, index) => {
+            // column的按钮和外部的控件按钮不一样
+            const colBtns = (
+              <>
+                {index !== 0 && (
+                  <ArrowUpOutlined
+                    style={{ marginLeft: 5, cursor: 'pointer' }}
+                    onClick={() => {
+                      changeIndex(index, 'up');
+                    }}
+                  />
+                )}
+                {index !== item.columns.length - 1 && (
+                  <ArrowDownOutlined
+                    style={{ marginLeft: 5, cursor: 'pointer' }}
+                    onClick={() => {
+                      changeIndex(index, 'down');
+                    }}
+                  />
+                )}
+                <DeleteOutlined
+                  style={{ marginLeft: 5, cursor: 'pointer' }}
+                  onClick={() => {
+                    changeIndex(index, 'delete');
+                  }}
+                />
+              </>
+            );
+            return (
+              <FormItem
+                key={column.props?.id}
+                item={column}
+                active={active && column.props?.id === selectColumnID}
+                onClick={() => {
+                  setSelectColumnID(column.props.id);
+                  onClick([item.props.id, column.props.id]);
+                }}
+                btns={colBtns}
+              />
+            );
+          })}
+          <Button type="dashed" block onClick={addTableColumn} icon={<PlusOutlined />}>
+            点击添加列
+          </Button>
+        </div>
+      ) : (
+        <div style={{ color: '#999', fontSize: 16 }}>{placeholder}</div>
+      )}
     </div>
   );
 }

+ 28 - 5
src/components/AuditForm/ItemAttribute.js

@@ -2,8 +2,8 @@ import { Form, Button, Switch, Input, Radio, Space, Row } from 'antd';
 import React, { useMemo, useState, useEffect } from 'react';
 import { DeleteOutlined } from '@ant-design/icons';
 function ItemAttribute(props) {
-  const { item, onChange } = props;
-
+  const { item, onChange, onRelClick, onFormulaClick } = props;
+  if (!item) return null;
   const renderForm = () => {
     let FormContent;
     const formProps = {
@@ -45,13 +45,16 @@ function ItemAttribute(props) {
       case 'DDDateField':
         FormContent = <DDDateField {...formProps} />;
         break;
+      case 'DIYTable':
+        FormContent = <DIYTableField {...formProps} />;
+        break;
+      default:
+        FormContent = null;
+        break;
     }
-
     return FormContent;
   };
 
-  if (!item) return null;
-
   return (
     <div
       style={{
@@ -412,3 +415,23 @@ function NumberField(props) {
     </Form>
   );
 }
+
+function DIYTableField(props) {
+  const { item, btns, onFinish } = props;
+  const [form] = Form.useForm();
+  return (
+    <Form
+      form={form}
+      labelCol={{ span: 6 }}
+      wrapperCol={{ span: 18 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={onFinish}
+    >
+      <Form.Item label="表格名称" name="label">
+        <Input />
+      </Form.Item>
+      {btns}
+    </Form>
+  );
+}

+ 9 - 0
src/components/AuditForm/constant.js

@@ -7,6 +7,7 @@ import {
   BlockOutlined,
   FieldNumberOutlined,
   InsertRowAboveOutlined,
+  TableOutlined,
 } from '@ant-design/icons';
 
 export const COMPONENT_LIST = [
@@ -88,4 +89,12 @@ export const COMPONENT_LIST = [
       unit: '',
     },
   },
+  {
+    componentName: 'DIYTable',
+    icon: <TableOutlined />,
+    props: {
+      label: 'DIY表格',
+      required: false,
+    },
+  },
 ];

+ 125 - 20
src/components/AuditForm/index.js

@@ -1,42 +1,133 @@
 import React, { useState, useEffect } from 'react';
+import { uuidv4 } from '@antv/xflow';
+import { Button } from 'antd';
 import FormContent from './FormContent';
 import ComponentLibrary from './ComponentLibrary';
 import ItemAttribute from './ItemAttribute';
-import { uuidv4 } from '@antv/xflow';
-import { Button } from 'antd';
 
 function AuditForm(props) {
   const { value, onChange } = props;
   const [formList, setFormList] = useState([]);
   const [select, setSelect] = useState(-1);
+  const [selectList, setSelectList] = useState([]);
   const [visible, setVisible] = useState(false);
-
-  const handleAddItem = item => {
-    const formItem = generateItem(item);
-    handleChangeList([...formList, formItem]);
-    setVisible(false);
-  };
+  const [addToTable, setAddToTable] = useState(false);
+  const [currentTableID, setCurrentTableID] = useState('');
 
   const generateItem = item => {
-    let newItem = {
+    const newItem = {
       ...item,
       props: { ...item.props, id: `${item.componentName}_${uuidv4()}` },
     };
+    // 如果是表格的话
+    if (item.componentName === 'DIYTable') {
+      newItem.columns = [];
+      newItem.isTable = true;
+    }
     delete newItem.icon;
     return newItem;
   };
 
-  const onChangeAttribute = newItem => {
-    let oldValue = formList[select].props;
-    formList[select].props = { ...oldValue, ...newItem };
-    handleChangeList([...formList]);
-  };
-
   const handleChangeList = list => {
     setFormList(list);
     onChange?.(list);
   };
 
+  const handleAddItem = item => {
+    if (addToTable) {
+      const column = generateItem(item);
+      // 找到对应的表格
+      const tableItem = formList.find(tItem => tItem.props.id === currentTableID);
+      column.isColumn = true;
+      // 把新增的列加入到表格中
+      tableItem.columns.push(column);
+      // 把新增列的表格放回
+      const newFormList = [];
+      for (const item of formList) {
+        if (item.props.id !== currentTableID) {
+          newFormList.push(item);
+        } else {
+          newFormList.push(tableItem);
+        }
+      }
+      handleChangeList(newFormList);
+      setCurrentTableID('');
+    } else {
+      const formItem = generateItem(item);
+      handleChangeList([...formList, formItem]);
+    }
+    setAddToTable(false);
+    setVisible(false);
+  };
+
+  const findFormItem = () => {
+    const formItem = formList.find(item => item.props.id === selectList[0]);
+
+    if (formItem?.isTable) {
+      // 如果是表格的话,还要寻找内部的被点击的col
+      if (selectList.length === 1) {
+        return formItem || null;
+      }
+      return (
+        formItem.columns.find(item => item.props.id === selectList[selectList.length - 1]) || null
+      );
+    } else {
+      return formList.find(item => item.props.id === select) || null;
+    }
+  };
+
+  const onChangeAttribute = newItemProps => {
+    const oldFormItem = findFormItem();
+    const newFormList = [];
+    if (oldFormItem.isColumn) {
+      // 找到表格和col然后改掉属性
+      for (const item of formList) {
+        if (item.isTable) {
+          for (const column of item.columns) {
+            if (column.props.id === selectList[selectList.length - 1]) {
+              column.props = { ...column.props, ...newItemProps };
+            }
+          }
+        }
+        newFormList.push(item);
+      }
+    } else {
+      for (const item of formList) {
+        if (item.props.id === select) {
+          item.props = { ...item.props, ...newItemProps };
+        }
+        newFormList.push(item);
+      }
+    }
+    handleChangeList(newFormList);
+  };
+
+  // 表格列变化时(新增,调整顺序)
+  const handleTableColumnChange = (id, newCole = []) => {
+    if (newCole.length) {
+      // 调整col顺序
+      const tableItem = formList.find(item => item.props.id === id);
+      tableItem.columns = newCole;
+      const newFormList = [];
+      for (const item of formList) {
+        if (item.props.id !== currentTableID) {
+          newFormList.push(item);
+        } else {
+          newFormList.push(tableItem);
+        }
+      }
+      handleChangeList(newFormList);
+    } else {
+      setCurrentTableID(id);
+      setAddToTable(true);
+    }
+  };
+
+  const handleFormContentSelect = ids => {
+    setSelectList(ids);
+    setSelect(ids[0]);
+  };
+
   useEffect(() => {
     if (value instanceof Array) {
       setFormList([...value]);
@@ -56,14 +147,28 @@ function AuditForm(props) {
           marginTop: 20,
         }}
       >
-        <FormContent onSelect={setSelect} onChange={handleChangeList} list={formList}></FormContent>
-        <ItemAttribute item={formList[select]} onChange={onChangeAttribute}></ItemAttribute>
+        <FormContent
+          onSelect={handleFormContentSelect}
+          onChange={handleChangeList}
+          onTableColumnChange={handleTableColumnChange}
+          list={formList}
+        />
+        <ItemAttribute
+          formList={formList}
+          key={selectList[selectList.length - 1]}
+          item={findFormItem()}
+          onChange={onChangeAttribute}
+        />
       </div>
       <ComponentLibrary
+        addToTable={addToTable}
         onOk={handleAddItem}
-        visible={visible}
-        onCancel={() => setVisible(false)}
-      ></ComponentLibrary>
+        visible={visible || addToTable}
+        onCancel={() => {
+          setVisible(false);
+          setAddToTable(false);
+        }}
+      />
     </div>
   );
 }

+ 7 - 0
src/components/DDComponents/DIYTable/index.css

@@ -0,0 +1,7 @@
+.hidden {
+  display: none;
+}
+
+.p-8 {
+  padding: 10px !important;
+}

+ 203 - 0
src/components/DDComponents/DIYTable/index.tsx

@@ -0,0 +1,203 @@
+import { PlusOutlined } from '@ant-design/icons';
+import { Button, Input, Table } from 'antd';
+import { ColumnsType } from 'antd/lib/table';
+import React, { useEffect, useState } from 'react';
+import DDDateField from '@/components/DDComponents/DDDateField';
+import DDSelectField from '@/components/DDComponents/DDSelectField';
+import NumberField from '@/components/DDComponents/NumberField';
+import TextNote from '@/components/DDComponents/TextNote';
+import './index.css';
+
+interface IProps {
+  table?: any; // 整个表格
+  columns?: any[]; // 当前列配置
+  onChange?: (e?: any, id?: string, label?: string) => void; // 表格修改后的值
+  displayOnly?: boolean; // 是否仅用于展示
+}
+
+interface TableDataType {
+  index: number;
+  id?: string;
+  col1?: any;
+  col2?: any;
+  col3?: any;
+  col4?: any;
+  col5?: any;
+}
+
+function DIYTable(props: IProps) {
+  const { table, columns, displayOnly, onChange } = props;
+  // table数据
+  const [tableData, setTableData] = useState<TableDataType[]>([{ index: 1 }]);
+  // table 列配置
+  const [tableColumnDef, setTableColumnDef] = useState<ColumnsType<any>>([
+    {
+      title: '序号',
+      dataIndex: 'index',
+      className: 'hidden',
+    },
+  ]);
+
+  // 表单填写时的表格生成
+  const handleGenerateTable = () => {
+    if (columns !== undefined && columns.length) {
+      for (let index = 0; index < columns.length; index++) {
+        const column = columns[index];
+        const columnID = column.props.id;
+        const columnLabel = column.props.label;
+        const colDef: any = {
+          dataIndex: `col${index + 1}`,
+          title: columnLabel || column.name,
+          className: 'p-8',
+        };
+        switch (column.componentName) {
+          case 'DDSelectField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              const id = `${rowIndex},${index};${columnID}>${table.props.id}`;
+              return (
+                // eslint-disable-next-line react/jsx-filename-extension
+                <DDSelectField
+                  id={id}
+                  label={`${columnLabel}>${table.props.label}`}
+                  style={{ padding: '0', margin: '0' }}
+                  options={column.props.options}
+                  disabled={column.props.disabled}
+                  onChange={onChange}
+                />
+              );
+            };
+            break;
+          case 'DDDateField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              const id = `${rowIndex},${index};${columnID}>${table.props.id}`;
+              return (
+                <DDDateField
+                  id={id}
+                  label={`${columnLabel}>${table.props.label}`}
+                  key={`${index + rowIndex}`}
+                  style={{ padding: '0', margin: '0' }}
+                  placeholder={column.props.placeholder}
+                  format={column.props.format}
+                  disabled={column.props.disabled}
+                  onChange={onChange}
+                />
+              );
+            };
+            break;
+          case 'NumberField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              const id = `${rowIndex},${index};${columnID}>${table.props.id}`;
+              return (
+                <NumberField
+                  id={id}
+                  label={`${columnLabel}>${table.props.label}`}
+                  size="small"
+                  width="50%"
+                  style={{ padding: '4px 11px' }}
+                  disabled={column.props.disabled}
+                  unit={column.props.unit}
+                  onChange={onChange}
+                />
+              );
+            };
+            break;
+          case 'TextField':
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              const id = `${rowIndex},${index};${columnID}>${table.props.id}`;
+              return (
+                <Input
+                  disabled={column.props.disabled}
+                  placeholder={column.props.placeholder}
+                  onChange={e =>
+                    onChange?.(e.target.value, id, `${columnLabel}>${table.props.label}`)
+                  }
+                />
+              );
+            };
+            break;
+          case 'TextNote':
+            colDef.title = '说明';
+            colDef.render = (_: any, __: any, rowIndex: number) => {
+              const id = `${rowIndex},${index};${columnID}>${table.props.id}`;
+              return (
+                <TextNote
+                  id={id}
+                  style={{ padding: '0', margin: '0' }}
+                  value={column.props.placeholder}
+                />
+              );
+            };
+            break;
+          default:
+            break;
+        }
+        tableColumnDef.push(colDef);
+      }
+    }
+  };
+
+  // 当仅用作展示时
+  const handleDisplayOnly = () => {
+    const rows = columns;
+    const newTableData = [];
+    const newColumnDef: ColumnsType<any> = [];
+    if (rows && columns.length) {
+      for (let index = 0; index < rows.length; index++) {
+        // 把每一行的数据提出来到一个对象里
+        if (rows) {
+          const row = rows[index];
+
+          if (index === 0) {
+            // 列配置
+            row.forEach((col: any) => {
+              newColumnDef.push({ title: col.name, dataIndex: col.type });
+            });
+          }
+          const rowData: any = {};
+          row.forEach((col: any) => {
+            rowData[col.type] = col.value[0];
+            rowData.key = col.id + index;
+          });
+          newTableData.push(rowData);
+        }
+      }
+      setTableColumnDef(newColumnDef);
+      setTableData(newTableData);
+    }
+  };
+
+  const handleRowChange = () => {
+    setTableData([...tableData, { index: tableData.length }]);
+  };
+
+  useEffect(() => {
+    if (displayOnly) {
+      handleDisplayOnly();
+    } else {
+      handleGenerateTable();
+    }
+  }, []);
+
+  return (
+    <>
+      {table.name ? table.name : table.props.label}
+      <Table
+        style={displayOnly ? { margin: '10px 24px 10px 0' } : {}}
+        columns={tableColumnDef}
+        dataSource={tableData}
+        pagination={false}
+      />
+      <Button
+        type="dashed"
+        icon={<PlusOutlined />}
+        block
+        onClick={handleRowChange}
+        style={displayOnly ? { display: 'none' } : {}}
+      >
+        新增行
+      </Button>
+    </>
+  );
+}
+
+export default DIYTable;

+ 14 - 0
src/components/DDComponents/FormulaField/index.js

@@ -0,0 +1,14 @@
+import React, { useEffect, useState } from 'react';
+import { Input } from 'antd';
+
+function FormulaField(props) {
+  const { evalStr, onChange } = props;
+  useEffect(() => {
+    const value = eval(evalStr);
+    onChange?.(value);
+  }, [evalStr]);
+
+  return <Input value={eval(evalStr)} />;
+}
+
+export default FormulaField;

+ 9 - 0
src/components/DDComponents/TextNote/index.js

@@ -0,0 +1,9 @@
+import React from 'react';
+
+function TextNote(props) {
+  const { value } = props;
+
+  return <div>{value}</div>;
+}
+
+export default TextNote;

+ 67 - 40
src/components/DDComponents/index.js

@@ -1,4 +1,5 @@
-import {Input, InputNumber, Select, DatePicker, Rate} from 'antd';
+import React from 'react';
+import { Input, InputNumber, Select, DatePicker, Rate } from 'antd';
 import TableField from './TableField';
 import PhoneField from './PhoneField';
 import InnerContactField from './InnerContactField';
@@ -9,13 +10,16 @@ import DDPhotoField from './DDPhotoField';
 import DDSelectField from './DDSelectField';
 import DDDateField from './DDDateField';
 import DDDateRangeField from './DDDateRangeField';
-import DDAttachment from './DDAttachment';
+// import DDAttachment from './DDAttachment';
+import FormulaField from './FormulaField';
+import DIYTable from './DIYTable/index.tsx';
+import TextNode from './TextNote';
 
-const {Option} = Select;
-const {RangePicker} = DatePicker;
+const { Option } = Select;
+const { RangePicker } = DatePicker;
 
 export default function DDComponents(props) {
-  const {item, onChange} = props;
+  const { evalStr = '', item, onChange } = props;
   const {
     id,
     label,
@@ -47,7 +51,7 @@ export default function DDComponents(props) {
   } = item.props;
   let component = null;
   switch (item.componentName) {
-    case 'TextField': //单行输入
+    case 'TextField': // 单行输入
       component = (
         <Input
           defaultValue={defaultValue}
@@ -57,7 +61,7 @@ export default function DDComponents(props) {
         />
       );
       break;
-    case 'TextareaField': //多行输入
+    case 'TextareaField': // 多行输入
       component = (
         <Input.TextArea
           defaultValue={defaultValue}
@@ -67,60 +71,83 @@ export default function DDComponents(props) {
         />
       );
       break;
-    case 'NumberField': //数字输入
-      component = <NumberField defaultValue={defaultValue} disabled={disabled} unit={unit} onChange={onChange}/>;
+    case 'NumberField': // 数字输入
+      component = (
+        <NumberField
+          defaultValue={defaultValue}
+          disabled={disabled}
+          unit={unit}
+          onChange={onChange}
+        />
+      );
       break;
-    case 'DDSelectField': //单选框
-      component =
-        <DDSelectField defaultValue={defaultValue} options={options} onChange={onChange} disabled={disabled}/>;
+    case 'DDSelectField': // 单选框
+      component = (
+        <DDSelectField
+          defaultValue={defaultValue}
+          options={options}
+          onChange={onChange}
+          disabled={disabled}
+        />
+      );
       break;
-    case 'DDMultiSelectField': //多选框
-      component = <DDMultiSelectField disabled={disabled} options={options} onChange={onChange}/>;
+    case 'DDMultiSelectField': // 多选框
+      component = <DDMultiSelectField disabled={disabled} options={options} onChange={onChange} />;
       break;
-    case 'DDDateField': //日期控件
-      component = <DDDateField format={format} disabled={disabled} onChange={onChange}/>;
+    case 'DDDateField': // 日期控件
+      component = <DDDateField format={format} disabled={disabled} onChange={onChange} />;
       break;
-    case 'DDDateRangeField': //时间区间控件
-      component = <DDDateRangeField format={format} disabled={disabled} onChange={onChange}/>;
+    case 'DDDateRangeField': // 时间区间控件
+      component = <DDDateRangeField format={format} disabled={disabled} onChange={onChange} />;
       break;
-    case 'TextNote': //文本说明控件
+    case 'TextNote': // 文本说明控件
       console.info('文本说明控件!');
+      component = <TextNode value={placeholder} />;
       console.log(item);
       break;
-    case 'PhoneField': //电话控件
-      component = <PhoneField onChange={onChange}/>;
+    case 'PhoneField': // 电话控件
+      component = <PhoneField onChange={onChange} />;
       break;
-    case 'DDPhotoField': //图片控件
-      component = <DDPhotoField/>;
+    case 'DDPhotoField': // 图片控件
+      component = <DDPhotoField />;
       break;
-    case 'MoneyField': //金额控件
-      component = <Input defaultValue={defaultValue} placeholder={placeholder} onChange={onChange}/>;
+    case 'MoneyField': // 金额控件
+      component = (
+        <Input defaultValue={defaultValue} placeholder={placeholder} onChange={onChange} />
+      );
       break;
-    case 'TableField': //明细控件
-      component = <TableField item={item}/>;
+    case 'TableField': // 明细控件
+      component = <TableField item={item} />;
       break;
-    case 'DDAttachment': //附件
+    case 'DDAttachment': // 附件
       // component = <DDAttachment />
       // component = '附件控件未渲染!'
       console.info('附件控件未渲染!');
       break;
-    case 'InnerContactField': //联系人控件
-      component = <InnerContactField onChange={onChange}></InnerContactField>;
+    case 'InnerContactField': // 联系人控件
+      component = <InnerContactField onChange={onChange} />;
+      break;
+    case 'DepartmentField': // 部门控件
+      component = <DepartmentField onChange={onChange} />;
+      break;
+    case 'DIYTable': // 可自定义表格控件
+      component = <DIYTable table={item} columns={item.columns} onChange={onChange} />;
       break;
-    case 'DepartmentField': //部门控件
-      component = <DepartmentField onChange={onChange}/>;
+    case 'FormulaField':
+      component = <FormulaField evalStr={evalStr} onChange={onChange} />;
+    case 'RelateField': // 关联审批单
+      component = '关联审批单控件未渲染!';
       break;
-    case 'RelateField': //关联审批单
-      component = '关联审批单控件未渲染!'
+    case 'AddressField': // 省市区控件
+      component = '省市区控件未渲染!';
       break;
-    case 'AddressField': //省市区控件
-      component = '省市区控件未渲染!'
+    case 'StarRatingField': // 评分控件
+      component = '评分控件未渲染!';
       break;
-    case 'StarRatingField': //评分控件
-      component = '评分控件未渲染!'
+    case 'FormRelateField': // 关联控件
+      component = '关联控件未渲染!';
       break;
-    case 'FormRelateField': //关联控件
-      component = '关联控件未渲染!'
+    default:
       break;
   }