小程序实现定位城市切换且城市根据首字母A-Z排序后端数据实现逻辑

news2025/2/28 0:04:44

场景:

话不多说后端提供数据实现步骤:

1.controller层

@Api(tags = {"[地区]-城市相关接口"})
@RestController
@RequestMapping("region")
@Slf4j
public class RegionController extends BaseController {

    @Resource
    private RegionService regionService;

	@ApiOperation("城市列表[A-Z]")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "condition", value = "城市名称", required = false, paramType = "query")})
    @GetMapping("cityList")
    public JsonResult<List<AppletCityListVO>> cityList(@RequestParam(value = "condition", required = false) String condition) {
        return JsonResult.ok(this.regionService.smallProgramCityDisplayList(condition));
    }

	@ApiOperation("城市列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "condition", value = "城市名称", required = false, paramType = "query")})
    @GetMapping("queryCityList")
    public JsonResult<List<AppletCityListVO.CityItem>> queryCityList(@RequestParam(value = "condition", required = false) String condition) {
        return JsonResult.ok(this.regionService.queryCityList(condition));
    }

    @Resource
    private TencentMapUtil tencentMapUtil;

    @ApiOperation("根据经纬度查询地址")
    @GetMapping("tencent/map/reGeoCoder")
    public JsonResult<JSONObject> reGeoCoder(String lat, String lng) {
        AssertUtil.notBlank(lat, "纬度不能为空");
        AssertUtil.notBlank(lng, "经度不能为空");
        JSONObject jsonObject = tencentMapUtil.reGeoCoder(lat, lng);
        if (EntityConstant.INVALID != jsonObject.getInteger("status")) {
            log.error("定位授权失败 , errorMsg = {}", jsonObject.getString("message"));
            throw SimpleException.getInstance("定位授权失败");
        }
        JSONObject adInfo = jsonObject.getJSONObject("result").getJSONObject("ad_info");
        String city_code = adInfo.getString("city_code");
        String nation_code = adInfo.getString("nation_code");
        jsonObject.getJSONObject("result").getJSONObject("ad_info").put("cityCode", city_code.replaceAll(nation_code, ""));
        return JsonResult.ok(jsonObject);
    }
}

2.service层

@Service
@Slf4j
@Primary
public class RegionServiceImpl extends BaseApplicationService implements RegionService {

    @Resource
    private RegionMapper regionMapper;


    private static final char[] alphabet = new char[26];

    static {
        // 使用循环填充数组元素
        for (int i = 0; i < alphabet.length; i++) {
            alphabet[i] = (char) ('A' + i);
        }
    }

    @Override
    public List<AppletCityListVO> smallProgramCityDisplayList(String condition) {
        List<Region> regionList = this.regionMapper.selectByExample(
                new ExampleLambda<>(Region.class)
                        .andEqualTo(Region::getStatus, EntityConstant.NORMAL)
                        .andEqualTo(Region::getLevel, 2)
                        .andLike(Objects.nonNull(condition), Region::getName, condition)
                        .end()
        );
        Map<String, List<Region>> cityMap = regionList.stream().collect(Collectors.groupingBy(Region::getInitial));
        List<AppletCityListVO> cityListVOList = new ArrayList<>(this.alphabet.length);
        for (char c : this.alphabet) {
            List<AppletCityListVO.CityItem> tempList = cityMap.containsKey(String.valueOf(c)) ? cityMap.get(String.valueOf(c)).stream().map(item -> {
                AppletCityListVO.CityItem cityItem = new AppletCityListVO.CityItem();
                cityItem.setCode(item.getCode());
                cityItem.setName(item.getName());
                return cityItem;
            }).collect(Collectors.toList()) : new ArrayList<>(0);
            cityListVOList.add(AppletCityListVO.builder().initial(String.valueOf(c)).itemList(tempList).build());
        }
        return cityListVOList;
    }

    @Override
    public List<AppletCityListVO.CityItem> queryCityList(String condition) {
        List<Region> regionList = this.regionMapper.selectByExample(
                new ExampleLambda<>(Region.class)
                        .andEqualTo(Region::getStatus, EntityConstant.NORMAL)
                        .andEqualTo(Region::getLevel, 2)
                        .andLike(Objects.nonNull(condition), Region::getName, condition)
                        .end()
        );
        return regionList.stream().map(item -> {
            AppletCityListVO.CityItem cityItem = new AppletCityListVO.CityItem();
            cityItem.setCode(item.getCode());
            cityItem.setName(item.getName());
            return cityItem;
        }).collect(Collectors.toList());
    }

}


@Builder
@Data
public class AppletCityListVO  implements Serializable {

    @ApiModelProperty(value = "首字母")
    private String initial;
    @ApiModelProperty(value = "城市列表")
    private List<CityItem> itemList;

    @Data
    public static class CityItem {

        @ApiModelProperty(value = "code")
        private String code;

        @ApiModelProperty(value = "名称")
        private String name;

        public CityItem(String code, String name) {
            this.code = code;
            this.name = name;
        }

        public CityItem() {

        }
    }

}

3.mapper层

public interface RegionMapper extends CrudMapper<Region, Long> {


}


4.实体类

@Table(name = "`region`")
@Data
public class Region extends BaseEntity<Long> implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * Id
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    /**
     * 1
     */
    @Column(name = "level")
    private Integer level;
    /**
     * code
     */
    @Column(name = "code")
    private String code;
    /**
     * 父级code
     */
    @Column(name = "parent_code")
    private String parentCode;
    /**
     * 名称
     */
    @Column(name = "name")
    private String name;
    /**
     * 名称拼音
     */
    @Column(name = "pinyin")
    private String pinyin;
    /**
     * 首字母
     */
    @Column(name = "initial")
    private String initial;
    /**
     * 状态
     */
    @Column(name = "status")
    private Integer status;
    /**
     * 创建时间
     */
    @Column(name = "gmt_created")
    @JsonFormat(locale = "zh", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date gmtCreated;
    /**
     * ModifyUser
     */
    @Column(name = "modify_user")
    private String modifyUser;
    /**
     * CreateUser
     */
    @Column(name = "create_user")
    private String createUser;
    /**
     * 更新时间
     */
    @Column(name = "gmt_modified")
    @JsonFormat(locale = "zh", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date gmtModified;
    /**
     * 是否删除
     */
    @Column(name = "deleted")
    private Integer deleted;
}


5.腾讯地图处理工具类

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Objects;

@Slf4j
@Component
public class TencentMapUtil {

    private String qqAk = "xxxxx-xxxxx-xxxxx-xxxxx-xxxxx-xxxxx";
    private String geoCoder = "https://apis.map.qq.com/ws/geocoder/v1/";
    private String distance = "https://apis.map.qq.com/ws/distance/v1/";
    private String translate = "https://apis.map.qq.com/ws/coord/v1/translate";
    private String reGeoCoder = "https://apis.map.qq.com/ws/geocoder/v1/?location=";

    /**
     * 通过地址查询经纬度
     *
     * @param addr 地址
     * @return
     */
    public String geoCoder(String addr) {
        JSONObject jsonObject = geoCoderRequest(addr);
        if (null == jsonObject) {
            return null;
        }
        JSONObject location = JSONUtil.parseObj(JSONUtil.toJsonStr(jsonObject.get("location")));
        if (Objects.nonNull(location) && Objects.nonNull(location.get("lat")) && Objects.nonNull(location.get("lng"))) {
            return location.get("lat").toString() + "," + location.get("lng").toString();
        }
        return null;
    }

    public JSONObject geoCoderRequest(String addr) {
        try {
            if (StringUtils.isNotEmpty(addr)) {
                String url = geoCoder +
                        "?address=" + addr +
                        "&key=" + qqAk;// 腾讯地图ak
                String resultStr = HttpUtil.get(url);
                JSONObject tencentGeo = JSONUtil.parseObj(resultStr);
                log.info("地址转坐标响应结果:" + JSONUtil.toJsonStr(tencentGeo));
                if (Objects.nonNull(tencentGeo) && Objects.equals(0, tencentGeo.get("status"))) {
                    return JSONUtil.parseObj(JSONUtil.toJsonStr(tencentGeo.get("result")));
                }
            }
        } catch (Exception e) {
            log.error("地址转坐标失败,地址:" + addr + ", e: " + e);
        }
        return null;
    }

    /**
     * 根据经纬度查询地址
     *
     * @param lat 纬度
     * @param lng 经度
     * @return
     */
    public JSONObject reGeoCoder(String lat, String lng) {
        StringBuilder url = new StringBuilder(reGeoCoder)
                .append(lat).append(",").append(lng)
                .append("&key=").append(qqAk);
        String resultStr = HttpUtil.get(url.toString());
        return JSONUtil.parseObj(resultStr);
    }

    /**
     * 将微信小程序经纬度转换成腾讯地图经纬度
     *
     * @param lat 纬度
     * @param lng 经度
     * @return
     */
    public JSONObject translate(String lat, String lng) {
        StringBuilder url = new StringBuilder(translate)
                .append("?key=").append(qqAk)// 腾讯地图ak
                .append("&type=1")// 1.GPS坐标 2.sogou经纬度 3.baidu经纬度 4.mapbar经纬度 5.[默认]腾讯、google、高德坐标 6.sogou墨卡托
                .append("&&locations=").append(lat).append(",").append(lng);
        String resultStr = HttpUtil.get(url.toString());
        return JSONUtil.parseObj(resultStr);
    }

}
6.region.sql文件 

 链接: https://pan.baidu.com/s/1m1WEgQPGXbUzgZ4qusvegQ 提取码: ztr6 复制这段内容后打开百度网盘手机App,操作更方便哦

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1477154.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

车载电子电器架构 —— 基础技术开发概述

车载电子电器架构 —— 基础技术开发概述 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 屏蔽力是信息过载时代一个人的特殊竞争力&#xff0c;任何消耗…

【数据结构】单链表解析+完整代码(插入、删除、尾插法、头插法、按值和按位查找、前插和后插)带头结点和不带两种实现

文章目录 3.1 单链表3.1.1 单链表的定义3.1.2 单链表的插入A.按位序插入&#xff08;带头结点&#xff09;B.按位序插入&#xff08;不带头结点&#xff09;C.指定结点的后插操作D.指定结点的前插操作 3.1.3 单链表的删除A.按位序删除B.删除指定结点 3.1.4 单链表的查找A.按位查…

jetson nano——编译安装opencv-python==4.3.0.38

目录 1.下载源码&#xff0c;我提供的链接如下&#xff1a;2.解压文件3.安装依赖scikit4.安装opencv-python5.查看opencv-python版本 系统&#xff1a;jetson-nano-jp451-sd-card-image ubuntu 18.04 1.下载源码&#xff0c;我提供的链接如下&#xff1a; 链接&#xff1a;http…

使用 OpenCV 通过 SIFT 算法进行对象跟踪

本文介绍如何使用 SIFT 算法跟踪对象 在当今世界&#xff0c;当涉及到对象检测和跟踪时&#xff0c;深度学习模型是最常用的&#xff0c;但有时传统的计算机视觉技术也可能有效。在本文中&#xff0c;我将尝试使用 SIFT 算法创建一个对象跟踪器。 为什么人们会选择使用传统的计…

如何对比 MySQL 主备数据的一致性?

随着业务范围的扩大&#xff0c;很多企业为了保障核心业务的高可用性&#xff0c;选择了 MySQL 主从架构&#xff0c;这一套方案通常具备主备数据同步、数据备份与恢复、读写分离、高可用切换等特性&#xff0c;是一种相当成熟可靠的数据库架构方案。然而这套方案在特定情况下可…

数电学习笔记——逻辑代数的基本定理

目录 一、带入定理 二、反演定理 三、对偶定理 一、带入定理 在任何一个包含变量A的逻辑等式中&#xff0c;若以另外一个逻辑式代入式中所有A的位置&#xff0c;则等式仍然成立。 例1&#xff1a;&#xff08;AB&#xff09;AB 将&#xff08;BC&#xff09;带入等式中所…

阿里云2024年服务器2核4G配置评测_CPU内存带宽_优惠价格

阿里云2核4G服务器多少钱一年&#xff1f;2核4G服务器1个月费用多少&#xff1f;2核4G服务器30元3个月、85元一年&#xff0c;轻量应用服务器2核4G4M带宽165元一年&#xff0c;企业用户2核4G5M带宽199元一年。本文阿里云服务器网整理的2核4G参加活动的主机是ECS经济型e实例和u1…

Python实现时间序列分析进行平稳性检验(ADF和KPSS)和差分去趋势(adfuller和kpss算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 时间序列分析中的平稳性检验是评估一个时间序列是否具有稳定的均值和方差。在经济学、金融学以及其他诸…

计算机专业电影推荐

1、《盗梦空间》 上映时间&#xff1a;2010-09-01 故事讲述了一群专业盗梦人的冒险旅程&#xff0c;他们试图在梦境中窃取最珍贵的秘密。但是&#xff0c;在这个精心设计的梦境中&#xff0c;他们面临着越来越多的挑战和危险。 这部电影不仅有令人难以置信的故事情节&#xf…

nvm安装和使用保姆级教程(详细)

一、 nvm是什么 &#xff1a; nvm全英文也叫node.js version management&#xff0c;是一个nodejs的版本管理工具。nvm和npm都是node.js版本管理工具&#xff0c;为了解决node.js各种版本存在不兼容现象可以通过它可以安装和切换不同版本的node.js。 二、卸载之前安装的node: …

Linux的gdb调试

文章目录 一、编译有调试信息的目标文件二、启动gdb调试文件1、查看内容list/l&#xff1a;l 文件名:行号/函数名&#xff0c;l 行号/函数名2、打断点b&#xff1a;b文件名:行号/函数名&#xff0c;b 行号/函数名 与 查看断点info/i&#xff1a;info b3、删除断点d&#xff1a;…

字节面试问题

实现三列布局的方法 第一种&#xff1a;可以使用浮动margin 第二种&#xff1a;浮动BFC <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, in…

每日OJ题_牛客DD1 连续最大和(IO型OJ)

目录 牛客DD1 连续最大和 解析代码 牛客DD1 连续最大和 连续最大和_牛客题霸_牛客网 解析代码 #include <climits> #include <iostream> #include <vector> using namespace std; int main() {int n 0;cin >> n;vector<int> arr(n);for (in…

通过大语言模型理解运维故障:评估和总结

张圣林 南开大学软件学院副教授、博士生导师 第六届CCF国际AIOps挑战赛程序委员会主席 在ATC、WWW、VLDB、KDD、SIGMETRICS等国际会议和JSAC、TC、TSC等国际期刊发表高水平论文50余篇。主持国家自然科学基金项目2项&#xff0c;横向项目13项&#xff08;与华为、字节跳动、腾讯…

【C++11】C++11新特性(上)

1、C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合并…

基于MQTT协议实现微服务架构事件总线

一、场景描述 昨天在博客《客户端订阅服务端事件的实现方法》中提出了利用websocket、服务端EventEmitter和客户端mitt实现客户端订阅服务端事件&#xff0c;大大简化了客户端对服务端数据实时响应的逻辑。上述方案适用于单服务节点的情形。 对于由服务集群支撑的微服务架构&…

前端-DOM树

dom树描述网页元素关系的一个专有名词&#xff0c;如html内包含了head、body&#xff0c;而head内包含meta、title、script等&#xff0c;body内包含div等元素&#xff1b;网页所有内容都在document里面&#xff0c;网页内容以树状形式排列&#xff0c;所以称之为dom树 dom树内…

进制转换md5绕过 [安洵杯 2019]easy_web1

打开题目 在查看url的时候得到了一串类似编码的东西&#xff0c;源码那里也是一堆base64&#xff0c;但是转换成图片就是网页上我们看见的那个表情包 ?imgTXpVek5UTTFNbVUzTURabE5qYz0&cmd 我们可以先试把前面的img那串解码了 解码的时候发现长度不够&#xff0c;那我们…

【Prometheus】基于Altertmanager发送告警到多个接收方、监控各种服务、pushgateway

基于Altertmanager发送报警到多个接收方 一、配置alertmanager-发送告警到qq邮箱1.1、告警流程1.2、告警设置【1】邮箱配置【2】告警规则配置【3】 部署prometheus【4】部署service 二、配置alertmanager-发送告警到钉钉三、配置alertmanager-发送告警到企业微信3.1、注册企业微…

DTD、XML阐述、XML的两种文档类型约束和DTD的使用

目录 ​编辑 一、DTD 什么是DTD&#xff1f; 为什么要使用 DTD&#xff1f; 内部 DTD 声明 具有内部 DTD 的 XML 文档 外部 DTD 声明 引用外部 DTD 的 XML 文档 二、XML 什么是XML&#xff1f; XML 不执行任何操作 XML 和 HTML 之间的区别 XML 不使用预定义的标记…