一个简单的轮子,实现简单,但是不好想

29 篇文章 1 订阅

需求背景

要做一个计算公式输入框(可下拉出数据可自己输入符号),输入对应的汉字模糊搜索出对应的数据,可输入计算符号,可选计算项。显示的是汉字的公式但是最后传给后端的是映射之后的code值公式,而且数据源可能有重复
在这里插入图片描述

实现

  1. 下拉框
  2. 输入符号
  3. 解决数据源重复

代码

/**
 * 计算公式标签
 * 下拉选择
 * 仿excel 计算公式功能
 */
import React, {useEffect, useState} from "react"
import {Mentions, Input  } from 'antd';
import { AutoComplete } from 'antd';

const { TextArea } = Input;
const { Option } = Mentions ;

let data = [{value: 'code1', text: '代码'},
{value: 'code2', text: '李三代码'},
{value: 'code3', text: '王五代码1'},
{value: 'code4', text: '赵六代码2'},
{value: 'code5', text: '孙七代码3'},
{value: 'code6', text: '李八代码4'},
{value: 'code7', text: '孙九代码5'},
{value: 'code7_1', text: '孙九代码5 '}
]
const coins = ["+", "-", "*", "/", "(", ")", "="]
export default () => {
    let [dataSource, setDataSource] = useState([]);
    const [open, setOpen] = useState(false);
    useEffect(() => {
        document.getElementById('auto_inp').addEventListener('keyup', onChnage)
        return () => {
            document.getElementById('auto_inp').removeEventListener('keyup', onChnage)
        }
    }, [])
    function onSelect1(value) {
        setOpen(false)
      }
    function handleSearch(value) {
        if (!(/[a-zA-Z]/i.test(value))) {
            setOpen(true)
            const end_point = document.getElementById('auto_inp').selectionEnd; //结束点
            const par_val = value.substring(0, end_point); 
            
            let start_i = 0; //开始点
            for (let i = par_val.length - 1; i >  0; i--) {
                if (coins.indexOf(par_val[i]) > -1) {
                    start_i = i;
                    break;
                }
            }
            let new_arr = [];
            data.map(t=>{
                if (t.text.indexOf(value.substring(start_i, end_point).replace(/[^\u4e00-\u9fa5]/gi, "")) > -1) {
                    new_arr.push(value.substring(0, start_i) + (coins.indexOf(par_val[start_i]) > -1 ? par_val[start_i] : '')  + t.text + value.substring(end_point).trim());
                }
            })
            setDataSource(new_arr);
            
        } else {
            setOpen(false)
            setDataSource([]);
        }
      };
    function onChnage(e) {
        if (coins.indexOf(e.key) > -1) { 
            setOpen(false)
        }
    }
    function onKeyDown(e) {
        const keys = [65, 67, 83, 86, 13, 32]
        if(keys.indexOf(e.keyCode) > -1){
            e.preventDefault();
            return;
        }
    }
    return (
        <>
        <AutoComplete
            dataSource={dataSource}
            backfill = {true}
            style={{ width: 575 }}
            onSelect={onSelect1}
            onSearch={handleSearch}
            open = {open}
        >
            <TextArea
            id="auto_inp"
            placeholder="请选择需要内容"
            className="custom"
            onKeyDown={(e)=>onKeyDown(e)} 
            style={{ height: 50, whiteApace: 'text-overflow' }}
            />
        </AutoComplete>
        </>
    )
}

代码优化

中文计算公式与英文计算公式互相转换。

  1. 中文计算转英文计算公式并根据映射关系计算出结果
    思路:先确定计算符号,使用一个开始指针和当前的i位置,遍历就好了,时间复杂度为O(N)。然后使用eval()计算公式,就计算出结果了
// 中文和空格正则表达式
                let regex = /[\u4e00-\u9fa5]/;
                let compute_str = ""; //计算公式映射
                let compute_codes = "";
                for (let i = 0; i < arr.length; i ++) {
                    if (!regex.test(arr[i])) {
                        if (i > start_i) {
                            let new_obj = source.find(t=>t.text === arr.substring(start_i, i))
                            compute_str += billing_basis_map[new_obj?.value];
                            compute_codes += new_obj?.value;
                        }
                        start_i = i+1;
                        compute_str += arr[i]; 
                        compute_codes += arr[i]; 
                    } else if (i == arr.length - 1) {
                        let new_obj = source.find(t=>t.text === arr.substring(start_i == 0 ? 0 :start_i, arr.length))
                        compute_str += billing_basis_map[new_obj?.value];
                        compute_codes += new_obj?.value;
                    }
                }
                this.setState({compute_codes})
                try {
                    event_money = eval(compute_str)
                  } catch (error) {
                    message.error('请按要求输入完整公式')
                  }
  1. 英文转中文实现思路一样
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值