瀏覽代碼

feat: 增加公式计算插件配置

ZhaoJun 1 年之前
父節點
當前提交
9eb3994f2f

+ 145 - 0
src/components/AuditForm/FormulaModal.js

@@ -0,0 +1,145 @@
+import React, { useEffect, useMemo, useState } from 'react';
+import { Divider, Input, Modal, message, Button } from 'antd';
+
+const { TextArea } = Input;
+
+export const FormulaType = {
+  Filed: 'filed',
+  Symbol: 'symbol',
+  Number: 'number',
+};
+
+const FormulaModal = props => {
+  const { item, numFiledList = [], visible, onCancel, onChange } = props;
+  const symbolList = ['+', '-', '*', '/', '(', ')'];
+  const numberList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '.'];
+
+  const [formula, setFormula] = useState([]);
+
+  useEffect(() => {
+    if (!visible) setFormula([]);
+    if (item?.props) setFormula(item.props.formula || []);
+  }, [visible, item]);
+
+  const value = useMemo(() => {
+    const strList = formula.map(fItem =>
+      fItem.type === FormulaType.Filed ? `【${fItem.label}】` : fItem.label
+    );
+    return `计算公式=${strList.join('')}`;
+  }, [formula]);
+  console.log('-----------------', formula);
+
+  const isSameBeforItem = type => {
+    return formula.length > 0 && formula[formula.length - 1].type == type;
+  };
+
+  const handlerChange = (type, item) => {
+    let obj = {};
+    console.log(formula[formula.length - 1]);
+    switch (type) {
+      case FormulaType.Filed:
+        if (isSameBeforItem(FormulaType.Filed)) {
+          message.error('不能选择连续两个组件');
+        }
+        obj = {
+          type: FormulaType.Filed,
+          id: item.props.id,
+          label: item.props.label,
+        };
+        setFormula([...formula, obj]);
+        break;
+      case FormulaType.Symbol:
+        if (isSameBeforItem(FormulaType.Symbol)) {
+          message.error('不能选择连续两个符号');
+        }
+        obj = { type: FormulaType.Symbol, label: item };
+        setFormula([...formula, obj]);
+        break;
+      case FormulaType.Number:
+        // 如果前一个选择的也是数字则合并数字 否则直接添加
+        if (isSameBeforItem(FormulaType.Number)) {
+          const len = formula.length - 1;
+          const label = formula[len].label + item;
+          obj = { type: FormulaType.Number, label };
+          const result = [...formula];
+          result[len] = obj;
+          setFormula(result);
+        } else {
+          obj = { type: FormulaType.Number, label: item };
+          setFormula([...formula, obj]);
+        }
+        break;
+      default:
+        break;
+    }
+  };
+
+  return (
+    <Modal
+      title="编辑计算公式"
+      open={visible}
+      onCancel={onCancel}
+      onOk={() => {
+        onChange?.({ ...item.props, formula, formulaLabel: value });
+      }}
+      width={1000}
+      pagination={false}
+    >
+      <Divider />
+
+      <Button type="primary" style={{ marginBottom: '20px' }} onClick={() => setFormula([])}>
+        清空
+      </Button>
+      <TextArea value={value} />
+      <div style={{ margin: '20px 20px 20px 0' }}>
+        计算对象:
+        {numFiledList.map((nItem, idx) => (
+          <span
+            style={{
+              padding: '6px 10px',
+              border: '1px solid #e5e5e5',
+              borderRadius: '2px',
+              marginRight: '10px',
+            }}
+            onClick={() => handlerChange(FormulaType.Filed, nItem)}
+          >
+            {nItem.props.label}
+          </span>
+        ))}
+      </div>
+      <div style={{ margin: '0 20px 20px 0' }}>
+        计算符号:
+        {symbolList.map((sItem, idx) => (
+          <span
+            style={{
+              padding: '6px 10px',
+              border: '1px solid #e5e5e5',
+              borderRadius: '2px',
+              marginRight: '10px',
+            }}
+            onClick={() => handlerChange(FormulaType.Symbol, sItem)}
+          >
+            {sItem}
+          </span>
+        ))}
+      </div>
+      <div style={{ margin: '0 20px 20px 0' }}>
+        数字键盘:
+        {numberList.map((nItem, idx) => (
+          <span
+            style={{
+              padding: '6px 10px',
+              border: '1px solid #e5e5e5',
+              borderRadius: '2px',
+              marginRight: '10px',
+            }}
+            onClick={() => handlerChange(FormulaType.Number, nItem)}
+          >
+            {nItem}
+          </span>
+        ))}
+      </div>
+    </Modal>
+  );
+};
+export default FormulaModal;

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

@@ -48,6 +48,9 @@ function ItemAttribute(props) {
       case 'DIYTable':
         FormContent = <DIYTableField {...formProps} />;
         break;
+      case 'FormulaField':
+        FormContent = <FormulaField {...formProps} onFormulaClick={onFormulaClick} />;
+        break;
       default:
         FormContent = null;
         break;
@@ -435,3 +438,35 @@ function DIYTableField(props) {
     </Form>
   );
 }
+
+function FormulaField(props) {
+  const { item, btns, onFinish, onFormulaClick } = props;
+  const [form] = Form.useForm();
+  const value = useMemo(() => {
+    return item.props.formulaLabel;
+  }, [item.props]);
+  return (
+    <Form
+      form={form}
+      labelCol={{ span: 6 }}
+      wrapperCol={{ span: 18 }}
+      autoComplete="off"
+      initialValues={item.props}
+      onFinish={values => onFinish({ ...item.props, ...values })}
+    >
+      <Form.Item label="标题" name="label">
+        <Input />
+      </Form.Item>
+      <Form.Item label="提示文字" name="placeholder">
+        <Input />
+      </Form.Item>
+      <Form.Item label="计算公式">
+        <Input value={value} onClick={onFormulaClick} />
+      </Form.Item>
+      <Form.Item label="必填" name="required" valuePropName="checked">
+        <Switch />
+      </Form.Item>
+      {btns}
+    </Form>
+  );
+}

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

@@ -8,6 +8,7 @@ import {
   FieldNumberOutlined,
   InsertRowAboveOutlined,
   TableOutlined,
+  LaptopOutlined,
 } from '@ant-design/icons';
 
 export const COMPONENT_LIST = [
@@ -97,4 +98,13 @@ export const COMPONENT_LIST = [
       required: false,
     },
   },
+  {
+    componentName: 'FormulaField',
+    icon: <LaptopOutlined />,
+    props: {
+      label: '计算公式',
+      placeholder: '自动计算数值',
+      required: false,
+    },
+  },
 ];

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

@@ -4,6 +4,7 @@ import { Button } from 'antd';
 import FormContent from './FormContent';
 import ComponentLibrary from './ComponentLibrary';
 import ItemAttribute from './ItemAttribute';
+import FormulaModal from './FormulaModal';
 
 function AuditForm(props) {
   const { value, onChange } = props;
@@ -11,6 +12,7 @@ function AuditForm(props) {
   const [select, setSelect] = useState(-1);
   const [selectList, setSelectList] = useState([]);
   const [visible, setVisible] = useState(false);
+  const [forVisible, setForVisible] = useState(false); // 计算公式弹窗
   const [addToTable, setAddToTable] = useState(false);
   const [currentTableID, setCurrentTableID] = useState('');
 
@@ -157,6 +159,9 @@ function AuditForm(props) {
           formList={formList}
           key={selectList[selectList.length - 1]}
           item={findFormItem()}
+          onFormulaClick={() => {
+            setForVisible(true);
+          }}
           onChange={onChangeAttribute}
         />
       </div>
@@ -169,6 +174,16 @@ function AuditForm(props) {
           setAddToTable(false);
         }}
       />
+      <FormulaModal
+        item={formList.find(item => item.props.id === select)}
+        numFiledList={formList.filter(item => item.componentName === 'NumberField')}
+        visible={forVisible}
+        onCancel={() => setForVisible(false)}
+        onChange={formula => {
+          setForVisible(false);
+          onChangeAttribute(formula);
+        }}
+      />
     </div>
   );
 }

+ 1 - 0
src/components/DDComponents/index.js

@@ -135,6 +135,7 @@ export default function DDComponents(props) {
       break;
     case 'FormulaField':
       component = <FormulaField evalStr={evalStr} onChange={onChange} />;
+      break;
     case 'RelateField': // 关联审批单
       component = '关联审批单控件未渲染!';
       break;