Selaa lähdekoodia

表单控件开发

xujunjie 2 vuotta sitten
vanhempi
commit
db2fefabda

+ 49 - 0
src/components/AuditForm/ComponentLibrary.js

@@ -0,0 +1,49 @@
+import { message, Col, Modal, Row } from 'antd';
+import React, { useState } from 'react';
+import { COMPONENT_LIST } from './constant';
+
+function ComponentLibrary(props) {
+  const { visible, onCancel, onOk } = props;
+  const [currnetItem, setCurrentItem] = useState(null);
+
+  const handleOk = () => {
+    if (!currnetItem) {
+      message.error('请选择控件');
+      return;
+    }
+    setCurrentItem(null);
+    onOk?.(currnetItem);
+  };
+  const handleCancel = () => {
+    setCurrentItem(null);
+    onCancel?.();
+  };
+  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>
+        ))}
+      </Row>
+    </Modal>
+  );
+}
+
+export default ComponentLibrary;

+ 92 - 0
src/components/AuditForm/FormContent.js

@@ -0,0 +1,92 @@
+import { Form } from 'antd';
+import React, { useState } from 'react';
+import { ArrowUpOutlined, ArrowDownOutlined, DeleteOutlined } from '@ant-design/icons';
+
+function FormContent(props) {
+  const { list, onChange, onSelect } = props;
+  const [currentItem, setCurrentItem] = useState(null);
+  const handleDelete = index => {
+    let _list = [...list];
+    _list.splice(index, 1);
+    onChange(_list);
+  };
+  const handleUp = index => {
+    let _list = [...list];
+    // 跟上一位置换位置
+    const temp = _list[index - 1];
+    _list[index - 1] = _list[index];
+    _list[index] = temp;
+    onChange(_list);
+  };
+  const handleDown = index => {
+    let _list = [...list];
+    const temp = _list[index + 1];
+    _list[index + 1] = _list[index];
+    _list[index] = temp;
+    onChange(_list);
+  };
+  const handleSelect = index => {
+    setCurrentItem(index);
+    onSelect(index);
+  };
+  return (
+    <div style={{ width: 300 }}>
+      {list.map((item, index) => {
+        const btns = (
+          <>
+            {index != 0 && (
+              <ArrowUpOutlined
+                style={{ marginLeft: 5, cursor: 'pointer' }}
+                onClick={() => handleUp(index)}
+              />
+            )}
+            {index != list.length - 1 && (
+              <ArrowDownOutlined
+                style={{ marginLeft: 5, cursor: 'pointer' }}
+                onClick={() => handleDown(index)}
+              />
+            )}
+            <DeleteOutlined
+              style={{ marginLeft: 5, cursor: 'pointer' }}
+              onClick={() => handleDelete(index)}
+            />
+          </>
+        );
+        return (
+          <FormItem
+            key={item.id}
+            active={index == currentItem}
+            onClick={() => handleSelect(index)}
+            item={item}
+            btns={btns}
+          />
+        );
+      })}
+    </div>
+  );
+}
+
+function FormItem(props) {
+  const { item, btns, active, onClick } = props;
+  const { label, placeholder, require } = item.props;
+  return (
+    <div
+      style={{
+        marginBottom: 20,
+        padding: '4px 12px',
+        border: '1px solid #666',
+        borderLeft: active ? '10px solid #1890FF' : '1px solid #666',
+      }}
+      onClick={onClick}
+    >
+      <div style={{ fontSzie: 24, color: '#000', fontWeight: 'bold', position: 'relative' }}>
+        {require && <i style={{ color: 'red' }}>*</i>}
+        {label}
+        <div style={{ position: 'absolute', right: 0, top: 0, padding: '5px 10px' }}>{btns}</div>
+      </div>
+      <div style={{ color: '#999', fontSize: 16 }}>{placeholder}</div>
+    </div>
+  );
+}
+
+export default FormContent;

+ 194 - 0
src/components/AuditForm/ItemAttribute.js

@@ -0,0 +1,194 @@
+import { Form, Button, Switch, Input } from 'antd';
+import React from 'react';
+
+function ItemAttribute(props) {
+  const { item, onChange } = props;
+
+  const renderForm = () => {
+    let FormContent;
+    switch (item.componentName) {
+      case 'InnerContactField':
+        FormContent = <InnerContactField item={item} onChange={onChange} />;
+        break;
+      case 'DepartmentField':
+        FormContent = <DepartmentField item={item} onChange={onChange} />;
+        break;
+      case 'TextField':
+        FormContent = <TextField item={item} onChange={onChange} />;
+        break;
+      case 'TextareaField':
+        FormContent = <TextareaField item={item} onChange={onChange} />;
+        break;
+      case 'DDSelectField':
+        FormContent = <DDSelectField item={item} onChange={onChange} />;
+        break;
+      case 'DDMultiSelectField':
+        FormContent = <DDMultiSelectField item={item} onChange={onChange} />;
+        break;
+      case 'NumberField':
+        FormContent = <NumberField item={item} onChange={onChange} />;
+        break;
+    }
+
+    return FormContent;
+  };
+
+  if (!item) return null;
+
+  return (
+    <div
+      style={{
+        // position: 'absolute',
+        // top: 0,
+        // right: 0,
+        width: 300,
+        height: '100%',
+        overflowY: 'auto',
+      }}
+    >
+      {renderForm()}
+    </div>
+  );
+}
+
+export default ItemAttribute;
+
+function InnerContactField(props) {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off">
+      <Form.Item label="标题">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字">
+        <Input />
+      </Form.Item>
+      {/* <Form.Item label="默认值">
+        <Input />
+      </Form.Item> */}
+    </Form>
+  );
+}
+function DepartmentField(props) {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off">
+      <Form.Item label="标题">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字">
+        <Input />
+      </Form.Item>
+      {/* <Form.Item label="默认值">
+        <Input />
+      </Form.Item> */}
+    </Form>
+  );
+}
+function TextField(props) {
+  const { item, onChange } = props;
+  const [form] = Form.useForm();
+
+  const onReset = () => {
+    form.resetFields();
+  };
+  const onFinish = values => {
+    console.log(values);
+    onChange?.(values);
+  };
+  return (
+    <Form
+      form={form}
+      labelCol={{ span: 8 }}
+      wrapperCol={{ span: 16 }}
+      onFinish={onFinish}
+      autoComplete="off"
+      initialValues={item.props}
+    >
+      <Form.Item label="标题" name="label">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字" name="placeholder">
+        <Input />
+      </Form.Item>
+      <Form.Item label="默认值" name="defaultValue">
+        <Input />
+      </Form.Item>
+      <Form.Item label="必填" valuePropName="checked" name="require">
+        <Switch />
+      </Form.Item>
+      <Form.Item>
+        <Button type="primary" htmlType="submit" style={{ marginRight: 20 }}>
+          保存
+        </Button>
+        <Button htmlType="button" onClick={onReset}>
+          重置
+        </Button>
+      </Form.Item>
+    </Form>
+  );
+}
+function TextareaField(props) {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off">
+      <Form.Item label="标题">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字">
+        <Input />
+      </Form.Item>
+      {/* <Form.Item label="默认值">
+        <Input />
+      </Form.Item> */}
+    </Form>
+  );
+}
+function DDSelectField(props) {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off">
+      <Form.Item label="标题">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字">
+        <Input />
+      </Form.Item>
+      {/* <Form.Item label="默认值">
+        <Input />
+      </Form.Item> */}
+    </Form>
+  );
+}
+function DDMultiSelectField(props) {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off">
+      <Form.Item label="标题">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字">
+        <Input />
+      </Form.Item>
+      {/* <Form.Item label="默认值">
+        <Input />
+      </Form.Item> */}
+    </Form>
+  );
+}
+function NumberField(props) {
+  const [form] = Form.useForm();
+  return (
+    <Form form={form} labelCol={{ span: 8 }} wrapperCol={{ span: 16 }} autoComplete="off">
+      <Form.Item label="标题">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字">
+        <Input />
+      </Form.Item>
+      {/* <Form.Item label="默认值">
+        <Input />
+      </Form.Item> */}
+    </Form>
+  );
+}

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

@@ -0,0 +1,76 @@
+import {
+  UserOutlined,
+  TeamOutlined,
+  ItalicOutlined,
+  FontSizeOutlined,
+  BorderOutlined,
+  BlockOutlined,
+  FieldNumberOutlined,
+} from '@ant-design/icons';
+
+export const COMPONENT_LIST = [
+  {
+    componentName: 'InnerContactField',
+    icon: <UserOutlined />,
+    props: {
+      label: '联系人',
+      placeholder: '请选择联系人',
+      require: false,
+    },
+  },
+  {
+    componentName: 'DepartmentField',
+    icon: <TeamOutlined />,
+    props: {
+      label: '部门',
+      placeholder: '请选择部门',
+      require: false,
+    },
+  },
+  {
+    componentName: 'TextField',
+    icon: <ItalicOutlined />,
+    props: {
+      label: '单行输入框',
+      placeholder: '请输入',
+      require: false,
+    },
+  },
+  {
+    componentName: 'TextareaField',
+    icon: <FontSizeOutlined />,
+    props: {
+      label: '多行输入框',
+      placeholder: '请输入',
+      require: false,
+    },
+  },
+  {
+    componentName: 'DDSelectField',
+    icon: <BorderOutlined />,
+    props: {
+      label: '单选框',
+      placeholder: '请选择',
+      require: false,
+      options: [],
+    },
+  },
+  {
+    componentName: 'DDMultiSelectField',
+    icon: <BlockOutlined />,
+    props: {
+      label: '多选框',
+      placeholder: '请选择',
+      require: false,
+    },
+  },
+  {
+    componentName: 'NumberField',
+    icon: <FieldNumberOutlined />,
+    props: {
+      label: '数字输入框',
+      placeholder: '请输入',
+      require: false,
+    },
+  },
+];

+ 57 - 0
src/components/AuditForm/index.js

@@ -0,0 +1,57 @@
+import React, { useState } from 'react';
+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 [formList, setFormList] = useState([]);
+  const [select, setSelect] = useState(-1);
+  const [visible, setVisible] = useState(false);
+
+  const handleAddItem = item => {
+    const formItem = generateItem(item);
+    setFormList([...formList, formItem]);
+    setVisible(false);
+  };
+
+  const generateItem = item => {
+    return {
+      ...item,
+      id: `${item.componentName}_${uuidv4()}`,
+      icon: null,
+    };
+  };
+
+  const onChangeAttribute = newItem => {
+    let oldValue = formList[select].props;
+    formList[select].props = { ...oldValue, ...newItem };
+    setFormList([...formList]);
+  };
+
+  return (
+    <div>
+      <Button onClick={() => setVisible(true)}>增加控件</Button>
+      <div
+        style={{
+          display: 'flex',
+          justifyContent: 'space-between',
+          alignItems: 'flex-start',
+          width: 800,
+          marginTop: 20,
+        }}
+      >
+        <FormContent onSelect={setSelect} onChange={setFormList} list={formList}></FormContent>
+        <ItemAttribute item={formList[select]} onChange={onChangeAttribute}></ItemAttribute>
+      </div>
+      <ComponentLibrary
+        onOk={handleAddItem}
+        visible={visible}
+        onCancel={() => setVisible(false)}
+      ></ComponentLibrary>
+    </div>
+  );
+}
+
+export default AuditForm;

+ 2 - 0
src/pages/PurchaseAdmin/PurchaseList/List/NewList.js

@@ -6,6 +6,7 @@ import FlowModal from '../Detail/FlowModal';
 import { queryBoomFlowDetail, queryRecordSheet } from '@/services/boom';
 import { async } from '@antv/x6/es/registry/marker/async';
 import { getToken } from '@/utils/utils';
+import AuditForm from '@/components/AuditForm';
 
 function List(props) {
   const { excel, loading, project, dispatch } = props;
@@ -134,6 +135,7 @@ function List(props) {
 
   return (
     <div>
+      {/* <AuditForm /> */}
       <Table
         loading={loading || loading2}
         rowKey="id"