首页 > 其他分享 >地址识别(纯前端)

地址识别(纯前端)

时间:2022-09-28 10:00:28浏览次数:50  
标签:val 前端 地址 let forEach push 识别 data

最近有一个需求,是要在前端做一个地址识别功能。。。确认不交给后台调接口去用ai识别吗?

看需求图:(识别出来的地址要给勾选上,这是个四级联动)

 

 

 

说一下解决方案:先将输入的地址格式化,去掉空格,统一把中文标点转换成英文,去掉换行符等。。。然后对字符串进行切割,进行强匹配,输出匹配上的数组。

地址识别组件:

 

  

import React, { FC, useState } from "react";
import { FormShape, createForm } from "@components/Form";
import { Textarea } from "@components/Input";
import Tooltip from "@components/Tooltip";
import { errorTip, successTip } from "@components/Tips";

type DistinguishProps = {
    form: FormShape;
    addressCheck?: (...args) => void;
    addressData: any;
};

const Distinguish: FC<DistinguishProps> = ({ form, addressCheck, addressData }) => {
    const [successAdd, setSuccessAdd] = useState([]);
    const [isSuccess, setIsSuccess] = useState("");
    const re1 = /[;]/;
    const re2 = /[:]/;

    // 处理识别数据
    const dealText = value => {
        if (!value) return;
        // 格式化,转换成英文字符,方便切割
        let str = value
            .replace(/:/g, ":")
            .replace(/;/g, ";")
            .replace(/[\r\n]/g, "")
            .replace(/\t/g, " ");
        let newData1 = [];
        let newData2 = [];
        let newData3 = [];
        try {
            if (re1.test(str)) {
                newData1 = str.split(";");
                newData1.forEach(item1 => {
                    item1 ? newData2.push(item1) : " ";
                });
                newData2.forEach(item2 => {
                    if (re2.test(item2)) {
                        newData3.push({
                            [item2.split(":")[0]]: item2.split(":")[1].split(" "),
                        });
                    } else {
                        newData3.push({ [item2]: [] });
                    }
                });
            } else {
                if (re2.test(str)) {
                    newData1 = str.split(":");
                    newData1.forEach(item1 => {
                        item1 ? newData2.push(item1) : " ";
                    });
                    newData3.push({
                        [newData2[0]]: newData2[1].split(" "),
                    });
                } else {
                    newData3.push({ [str]: [] });
                }
            }
            return newData3;
        } catch (e) {
            errorTip("地址识别失败!请按照提示的格式输入地址信息。");
            setSuccessAdd([]);
        }
    };

    // 数组对象去重,合并
    const mergeData = value => {
        let initArr = [];
        let initData = {};
        let data = xt.cloneDeep(value); //深拷贝
        if (data.length > 0) {
            data.forEach(item => {
                if (typeof item == "string") {
                    initArr.push(item);
                } else {
                    let map = item;
                    for (let k in map) {
                        if (k != null && k != "null") {
                            if (initData.hasOwnProperty(k)) {
                                initData[k] += "," + map[k];
                            } else {
                                initData[k] = map[k];
                            }
                        }
                    }
                }
            });
        }
        Object.keys(initData).forEach(key => {
            if (initData[key]) {
                let a = Array.from(new Set(initData[key].split(","))).join(",");
                initArr.push({ [key]: a });
            } else {
                initArr.push(key);
            }
        });
        return initArr;
    };

    // 地址匹配
    const addressPick = (val: any) => {
        let errAddress = []; // 识别失败地址
        let sucessAddress = []; // 识别成功地址
        let inputAddress = val; // 输入的地址
        let propsData = xt.cloneDeep(addressData); // 识别选中的地址
        try {
            inputAddress.forEach(item => {
                // @ts-ignore
                if (Object.values(item)?.flat().length) {
                    // 选中区下面的街道
                    Object.values(item)
                        // @ts-ignore
                        .flat()
                        .forEach(address => {
                            propsData.forEach(data => {
                                // @ts-ignore
                                if (data.nameCN == xt.nesGame(Object.keys(item)?.flat()[0])) {
                                    data?.childrenStreet.forEach(a => {
                                        if (a.nameCN == xt.nesGame(address)) {  // xt.nesGame去掉空格
                                            sucessAddress.push({ [data.nameCN]: address });
                                            a.choose = true;
                                        }
                                    });
                                }
                            });
                        });
                } else {
                    // 直接选中区以及下面所有的街道
                    propsData.forEach(data => {
                        // @ts-ignore
                        if (data.nameCN == xt.nesGame(Object.keys(item)?.flat()[0])) {
                            data.choose = true;
                            data?.childrenStreet.forEach(a => {
                                a.choose = true;
                            });
                            // @ts-ignore
                            sucessAddress.push(xt.nesGame(Object.keys(item)?.flat()[0]));
                        }
                    });
                }
            });
            if (sucessAddress.length > 0) {
                setIsSuccess("识别成功地址");
                successTip("识别成功");
                addressCheck(Array.from(new Set(sucessAddress)));
                setSuccessAdd(mergeData(sucessAddress)); // 识别成功地址
            } else {
                setIsSuccess("地址识别失败!请检查后再试");
                setSuccessAdd([]);
            }
        } catch (e) {
            errorTip("地址匹配失败!请检查后再试");
            setSuccessAdd([]);
        }
    };

    // 提交给父组件
    // 宝安区:福永街道 石岩街道  航城街道  福海街道 西乡街道 西乡街道;罗湖区
    const submit = () => {
        setIsSuccess("");
        form.validateFields((error, value: any) => {
            if (error) return;
            addressPick(dealText(value.note));
        });
    };

    const cancel = () => {
        form.resetFields();
        setSuccessAdd([]);
        setIsSuccess("");
    };

    return (
        <div
            className="pb-20"
            style={{ border: "1px solid #eaedf3", borderRadius: "4px", backgroundColor: "#fff" }}
        >
            <Textarea
                form={form}
                fieldName="note"
                textareaStyle={{ border: "none" }}
                placeholder={
                    "请粘贴文本至此处,自动识别区、县、街道名称并选中,若有多个街道请以区名或县名加冒号开头,多个街道以空格隔开,以分号结束,若需选中整个区或县所有街道则直接输入区名或县名以分号结束。\n例:坪山区:坪山街道 坑梓街道;南山区;"
                }
                style={{ width: "100%", border: "none" }}
                maxLength={300}
                showError="down"
                rules={false}
                normalize={(val, prev) => {
                    if (val.length > 300) return prev.trim();
                    if (!val.trim().length || val.length === 300) return val.trim();
                    return val;
                }}
            />
            <div className="mt-20  pr-20 flex-align-center" style={{ paddingLeft: "15px" }}>
                <button className="button-primary mr-20" onClick={submit}>
                    识别文本
                </button>
                <button className="button-default" onClick={cancel}>
                    清空
                </button>
                <div className="ml-30">
                    <span
                        className="mr-5 font12 c-606266"
                        style={{ color: isSuccess == "识别成功地址" ? "" : "#FF6666" }}
                    >
                        {isSuccess}
                    </span>
                    {!!successAdd.length && (
                        <Tooltip
                            overlay={
                                <>
                                    {successAdd.map((val, index) => {
                                        if (typeof val === "string") {
                                            return <p>{val};</p>;
                                        } else {
                                            return (
                                                <p>
                                                    {Object.keys(val)[0]}:
                                                    {Array.from(new Set(Object.values(val))).join(
                                                        ","
                                                    )}
                                                </p>
                                            );
                                        }
                                    })}
                                </>
                            }
                        >
                            <i className={"wsf-icon-question"} />
                        </Tooltip>
                    )}
                </div>
            </div>
        </div>
    );
};

export default createForm()(Distinguish);

  

 

标签:val,前端,地址,let,forEach,push,识别,data
From: https://www.cnblogs.com/tristers/p/16736997.html

相关文章

  • linux 测试对方地址通不通
    1. pingxxxxx  如没返回就不通 2.telnet172.25.97.1018088或 telnet172.25.97.101如果返回telnet:commandnotfound说明未安装  解决方法:安装te......
  • 前端基础面试题
    1.前端如何进行性能优化?前端进行性能优化的方案很多,这里只列举部分。在实际应用中不要贪多,想着都用上,要对网站的主要用户群体进行针对性优化。降低请求量合并资源,......
  • 前端重点复习笔记
    JavaScriptJS特点不主动开启新的线程的情况下单线程如何开启新线程varworker=newWorker('js文件路径')js是弱类型语言所有的声明都是通过var在赋值的时......
  • 前端生成二维码
    往常我们二维码可能都是后端去处理,构建一个image对象,最后输出image二进制流,然后前端定义一个img控件去展示。但这有个弊端,就是流传输的比较大,当流量大的时候,不仅浪费流量......
  • 【前端必会】使用indexedDB,降低环境搭建成本
    背景学习前端新框架、新技术。如果需要做一些数据库的操作来增加demo的体验(CURD流程可以让演示的体验根据丝滑)最开始的时候一个演示程序我们会调用后台,这样其实有一点弊......
  • 前端三件套 HTML+CSS+JS基础知识内容笔记
    HTML基础目录HTML基础HTML5标签doctype标签html标签head标签meta标签title标签body标签文本和超链接标签标题标签段落标签换行标签水平标签强调标签图片标签与超链接标签......
  • 代码狗必看:前端开发3大坑
    0x0000 第一大坑:浏览器兼容性第一次浏览器大战桌面端浏览器大战的硝烟尚未散尽,移动端纷争又起。大厂神仙打架,码农苦不堪言。各种CSS、JS不兼容,坑得码农尽白头。在兼容性这......
  • 前端开发工程师
    精通前端,熟悉后端5年工作经验,编写艺术般的代码,做好现在,技术只是为了改变生活!专业技能·Web·IT行业的学习需要持之以恒,知识深度与广度都很重要。而前端开发......
  • 前端加密算法之MD5
    1、简介1.1、隶属于单向加密算法1.2、不可逆的加密算法、不能从密文反推出明文,除非做碰撞测试1.3、一种摘要算法、哈希算法、散列算法(通过一个函数,把任意......
  • 前端面试总结10-WebApi-事件
    1.事件绑定通用函数(包括事件代理)functionbindEvent(elem,type,selector,fn){if(fn==null){fn=selector;selector=null;}elem.addEventListener(type,event=>{con......