当前位置: 首页 > news >正文

PostGis -基础、Springboot 整合、电子围栏处理

目的: 为什么要用PostgreSQL?

  • 因为有时候我们需要存储 空间数据,如:存储一个 多边形 到数据。
  • PostGis中 geometrygeography :基本空间数据类型,用于表达点线面等空间要素,具体类型涵盖了OGC的简单对象模型
  • 在这里插入图片描述

说明:PostGIS是PostgreSQL对象关系数据库的空间数据库扩展。它增加了对地理对象的支持,允许在SQL中运行位置查询。

特点:

  • PostGIS是在对象关系型数据库PostgreSQL上增加了存储管理空间数据的能力的开源空间数据库,空间数据库像存储和操作数据库中其他任何对象一样去存储和操作空间对象。
  • 它是PostgreSQL的扩展插件,在PostgreSQL的core(存储、检索、事务等)层之上实现GIS层的功能,它不能独立于PostgreSQL运行。

常见名词:

  • WKT(Well-known text) 是开放地理空间联盟OGC(Open GIS Consortium )制定的一种文本标记语言,用于表示矢量几何对象、空间参照系统及空间参照系统之间的转换
    • POINT(1 2)
    • 常见描述: Point 点 、LineString 线、 Polygon 多边形 …在这里插入图片描述> - WKB(well-known binary) 是WKT的二进制表示形式,解决了WKT表达方式冗余的问题,便于传输和在数据库中存储相同的信息> - "01020000800200000097E5880801845C404D064F3AF4AE36400000000000000000290A915F01845C40DC90B1A051AE36400000000000000000"> - pg库中 geometry 类型字段,默认存储的就是wkb
  • GeoJson :{[“type": “Point", “coordinates”: [30, 10]}

常见安装:

官网下载地址:
https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

扩展插件,空间数据处理 postgis安装
https://www.postgresql.org/ftp/postgis/
http://download.osgeo.org/postgis/windows/pg10/

docker安装

version: "3.1"
services:postgresql:image: postgres:12-alpinecontainer_name: postgresqlenvironment:POSTGRES_DB: postgresPOSTGRES_USER: "root"POSTGRES_PASSWORD: "root"ports:- 5432:5432volumes:- ./data:/var/lib/postgresql/data

常见函数

-- 创建扩展函数
CREATE EXTENSION postgis;--  读取wkt字符串为geometry
ST_GeomFromTextST_GeometryFromText--  转换为wkt
ST_AsText
--  转换为geojson
ST_AsGeoJSON

转换函数

  • 运行这个sql https://gitcode.net/mirrors/geocompass/pg-coordtransform/-/blob/master/geoc-pg-coordtransform.sql
-- 坐标系转换
-- WGS84坐标系:地球坐标系,国际通用坐标系
-- GCJ02坐标系:火星坐标系,WGS84坐标系加密后的坐标系;Google国内地图、高德、QQ地图 使用
-- BD09坐标系:    百度坐标系,GCJ02坐标系加密后的坐标系
-- CGCS坐标系:国家2000大地坐标系-- WGS84转GCJ02
select ST_AsText(geoc_wgs84togcj02(geom)) from md_geom_space-- GCJ02转WGS84
select geoc_gcj02towgs84(geom) from md_geom_space-- WGS84转BD09
select geoc_wgs84tobd09(geom) from md_geom_space-- BD09转WGS84
select geoc_bd09towgs84(geom) from md_geom_space-- CGCS2000转GCJ02
select geoc_cgcs2000togcj02(geom) from md_geom_space-- GCJ02转CGCS2000
select geoc_gcj02tocgcs2000(geom) from md_geom_space-- CGCS2000转BD09
select geoc_cgcs2000tobd09(geom) from md_geom_space-- BD09转CGCS2000
select geoc_bd09tocgcs2000(geom) from md_geom_space-- GCJ02转BD09
select geoc_gcj02tobd09(geom) from md_geom_space-- BD09转GCJ02
select geoc_bd09togcj02(geom) from md_geom_space

代码整合

pom

		<dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.3.8</version></dependency><!-- GeoTools --><dependency><groupId>org.geolatte</groupId><artifactId>geolatte-geom</artifactId><version>1.6.0</version></dependency><!-- https://mvnrepository.com/artifact/org.geolatte/geolatte-geojson --><dependency><groupId>org.geolatte</groupId><artifactId>geolatte-geojson</artifactId><version>1.6.0</version></dependency><dependency><groupId>net.postgis</groupId><artifactId>postgis-jdbc</artifactId><version>2.5.0</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>28-SNAPSHOT</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-geojson</artifactId><version>28-SNAPSHOT</version></dependency><!-- geotools的远程库 --><repositories><repository><id>osgeo</id><name>OSGeo Release Repository</name><url>https://repo.osgeo.org/repository/release/</url><snapshots><enabled>false</enabled></snapshots><releases><enabled>true</enabled></releases></repository><repository><id>osgeo-snapshot</id><name>OSGeo Snapshot Repository</name><url>https://repo.osgeo.org/repository/snapshot/</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>false</enabled></releases></repository></repositories>

mybatisplus 自定义类型处理

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import org.postgis.Geometry;
import org.postgis.PGgeometry;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;@MappedTypes({String.class})
public class MyGeometryTypeHandler extends BaseTypeHandler<String> {@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {PGgeometry pGgeometry = new PGgeometry(parameter);Geometry geometry = pGgeometry.getGeometry();//坐标系geometry.setSrid(4326);ps.setObject(i, pGgeometry);}@Overridepublic String getNullableResult(ResultSet rs, String columnName) throws SQLException {PGgeometry pGgeometry = new PGgeometry(rs.getString(columnName));return pGgeometry.getValue().replace("SRID=4326;","");}@Overridepublic String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {PGgeometry pGgeometry = new PGgeometry(rs.getString(columnIndex));return pGgeometry.toString();}@Overridepublic String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {PGgeometry pGgeometry = new PGgeometry(cs.getString(columnIndex));return pGgeometry.toString();}
}
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.typeHandler.MyGeometryTypeHandler;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;/*** xxx** @author heyonghao* @date 2023/7/17*/
@TableName(autoResultMap = true)
@ApiModel(value = "电子围栏")
@Accessors(chain = true)
@Data
public class GeomSpace implements Serializable {@ApiModelProperty(value = "主键")private Long id;//对应数据库 geometry 类型@ApiModelProperty(value = "围栏geo参数- 返回wkt")@TableField(typeHandler = MyGeometryTypeHandler.class)private String geom;@ApiModelProperty(value = "电子围栏名称")private String title;@ApiModelProperty(value = "其它组成参数 eg: 圆 半径 {\\\"radius\\\":0.00030345730927194836,\\\"radiusTrue\\\":29.068128024579657}")private String other;}

新增空间类型数据

@ApiModel(value = "围栏点位参数")
@Accessors(chain = true)
@Data
public class GeoJsonVo implements Serializable {@ApiModelProperty(value = "类型: POINT、MULTIPOINT、LINESTRING、MULTILINESTRING、POLYGON、MULTIPOLYGON")private String type;@ApiModelProperty(value = "点位 eg: [ [\"106.29384466232433\",\"31.2648657606391\"] ]")private List<List<String>> coordinates;public String getGeomStr(){String coordinate="SRID=4326;%s(%s)";String collect = this.coordinates.stream().map(s -> s.stream().map(String::valueOf).collect(Collectors.joining(" "))).collect(Collectors.joining(","));coordinate=String.format(coordinate,this.getType(),collect);return coordinate;}}
@ApiModel(value = "围栏新增VO")
@Data
public class MdGeomSpaceSaveVo implements Serializable {@ApiModelProperty(value = "围栏信息")private GeomSpace mdGeomSpace;@ApiModelProperty(value = "围栏点位信息")private GeoJsonVo geoJsonVo;}
@ApiOperation(value = "添加围栏")
@PostMapping("/save")
public R<Boolean> save(@RequestBody MdGeomSpaceSaveVo geomSpaceSaveVo){GeoJsonVo geoJsonVo = geomSpaceSaveVo.getGeoJsonVo();String geomStr = geoJsonVo.getGeomStr();GeomSpace mdGeomSpace = geomSpaceSaveVo.getMdGeomSpace();mdGeomSpace.setGeom(geomStr);mdGeomSpace.setId(IdUtil.getSnowflakeNextId());boolean save = mdGeomSpaceService.save(mdGeomSpace);return R.ok(save);
}

电子围栏:

  • 用一个虚拟的栅栏围出一个虚拟地理边界;
  • 在地图上 圈出一个圆形范围、或多边形范围;绑定特点规则,如 超速滞留偏离聚集等,做出相应告警
  • 传入空间数据,存入PG库

表:

-- ----------------------------
DROP TABLE IF EXISTS "public"."geom_space";
CREATE TABLE "public"."geom_space" ("id" int8 NOT NULL DEFAULT nextval('testgeomobj_id_seq'::regclass),"geom" geometry(GEOMETRY) NOT NULL,"title" varchar(255) COLLATE "pg_catalog"."default","other" varchar(255) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "public"."geom_space"."id" IS '主键';
COMMENT ON COLUMN "public"."geom_space"."geom" IS '围栏geo参数';
COMMENT ON COLUMN "public"."geom_space"."title" IS '电子围栏名称';
COMMENT ON COLUMN "public"."geom_space"."other" IS '其它组成参数 eg: 圆 半径';-- ----------------------------
-- Primary Key structure for table geom_space
-- ----------------------------
ALTER TABLE "public"."geom_space" ADD CONSTRAINT "md_geom_space_pkey" PRIMARY KEY ("id");-- ----------------------------
DROP TABLE IF EXISTS "public"."geom_space_rule";
CREATE TABLE "public"."geom_space_rule" ("id" int8 NOT NULL,"name" varchar(255) COLLATE "pg_catalog"."default","type" int2,"rule" varchar(255) COLLATE "pg_catalog"."default"
)
;
COMMENT ON COLUMN "public"."geom_space_rule"."id" IS '主键';
COMMENT ON COLUMN "public"."geom_space_rule"."name" IS '规则名称';
COMMENT ON COLUMN "public"."geom_space_rule"."type" IS '规则类型 1-超速 2-聚焦 3-规矩偏离 4-滞留';
COMMENT ON COLUMN "public"."geom_space_rule"."rule" IS '规则JSON';-- ----------------------------
-- Records of geom_space_rule
-- ----------------------------
INSERT INTO "public"."geom_space_rule" VALUES (1685206843057606656, '超速', 1, '{"speed":60,"duration":10}');-- ----------------------------
-- Primary Key structure for table geom_space_rule
-- ----------------------------
ALTER TABLE "public"."geom_space_rule" ADD CONSTRAINT "geom_space_rule_pkey" PRIMARY KEY ("id");-- ----------------------------
DROP TABLE IF EXISTS "public"."geom_space_bind";
CREATE TABLE "public"."geom_space_bind" ("id" int8 NOT NULL,"space_id" int8,"rule_id" int8
)
;
COMMENT ON COLUMN "public"."geom_space_bind"."id" IS '主键';
COMMENT ON COLUMN "public"."geom_space_bind"."space_id" IS '围栏id';
COMMENT ON COLUMN "public"."geom_space_bind"."rule_id" IS '规则id';-- ----------------------------
-- Records of geom_space_bind
-- ----------------------------
INSERT INTO "public"."geom_space_bind" VALUES (1685206981247340544, 1685205995128717312, 1685206843057606656);-- ----------------------------
-- Primary Key structure for table geom_space_bind
-- ----------------------------
ALTER TABLE "public"."geom_space_bind" ADD CONSTRAINT "geom_space_bind_pkey" PRIMARY KEY ("id");

相关文章:

PostGis -基础、Springboot 整合、电子围栏处理

目的&#xff1a; 为什么要用PostgreSQL? 因为有时候我们需要存储 空间数据&#xff0c;如&#xff1a;存储一个 多边形 到数据。PostGis中 geometry、geography &#xff1a;基本空间数据类型&#xff0c;用于表达点线面等空间要素&#xff0c;具体类型涵盖了OGC的简单对象模…...

【Linux】多线程的补充

1 线程安全的单例模式 1.1 什么是单例模式 单例模式是一种 "经典的, 常用的, 常考的" 设计模式. 1.2 什么是设计模式 IT行业这么火, 涌入的人很多. 俗话说林子大了啥鸟都有. 大佬和菜鸡们两极分化的越来越严重. 为了让菜鸡们不太拖大佬的后腿, 于是大佬们针对一些…...

【MySQL】表的操作

今天我们来谈谈MySQL下对表的操作 目录 一、创建表 二、查看表 2.1 查看库中存有的表 2.2 查看表结构 2.3 查看表的创建语句 三、修改表 3.1 重命名表名 3.2 新增列 3.3 修改列的数据类型 3.4 删除列 3.5 重命名列 3.6 向表中插入数据 四、删除表 一、创建表 我…...

自动化测试 selenium(测试系列7)

目录 前言&#xff1a; 1.什么是自动化测试 2.Selenium是什么 3.Selenium原理 4.SeleniumJava环境搭建 5.Selenium常用的API使用 5.1定位元素findElement 5.1.1css选择器 5.1.2id选择器 5.1.3类选择器 5.1.4xpath选择器 5.2操作测试对象 5.2.1click点击对象 5.2.…...

小研究 - JVM 垃圾回收方式性能研究(二)

本文从几种JVM垃圾回收方式及原理出发&#xff0c;研究了在 SPEC jbb2015基准测试中不同垃圾回收方式对于JVM 性能的影响&#xff0c;并通过最终测试数据对比&#xff0c;给出了不同应用场景下如何选择垃圾回收策略的方法。 目录 3 几种垃圾回收器 3.1 串行回收器 3.2 并行回…...

【网络安全带你练爬虫-100练】第15练:模拟用户登录

目录 一、目标1&#xff1a;理清逻辑 二、目标2&#xff1a;将每一步用代码进行表示 三、网络安全O 一、目标1&#xff1a;理清逻辑 模拟登录的基本流程 1、进入入口程序 2、读取目标URL 3、请求加上线程 4、确定请求数据包 5、请求格式的确认 6、数据的处理与判断 二、目标…...

Ansible

Ansible 文章目录 Ansible一、概念1.简介2.特性 二、ansible模块1.命令行格式2.模块1.command 模块2.shell 模块3.cron 模块4.user 模块5.group 模块6.copy 模块7.file 模块8.hostname 模块9.ping 模块10.yum 模块11.service/systemd 模块12.script 模块13.mount 模块14.archiv…...

kafka:消费者从指定时间的偏移开始消费(二)

我的前一篇博客《kafka:AdminClient获取指定主题的所有消费者的消费偏移(一)》为了忽略忽略掉上线之前的所有消息&#xff0c;从获取指定主题的所有消费者的消费偏移并计算出最大偏移来解决此问题。 但这个方案需要使用不常用的AdminClient类&#xff0c;而且如果该主题如果是第…...

Spring的加载配置文件、容器和获取bean的方式

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaweb 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 Spring配置文件和容器相关 一、加载properties文件1.1加载…...

(二)利用Streamlit创建第一个app——单页面、多页面

1 单页面app Step1&#xff1a;创建一个新的Python脚本。我们称之为uber_pickups.py。 Step2&#xff1a;在您喜爱的IDE或文本编辑器中打开uber_pickups.py&#xff0c;然后添加以下行&#xff1a; import streamlit as st import pandas as pd import numpy as npStep3&…...

一条sql查询语句在mysql中的执行过程是什么

mysql的连接器 我们想要在mysql中执行一条sql查询语句&#xff0c;首先需要连接到mysql服务&#xff0c;那么客户端首先要向mysql服务端发起连接请求&#xff0c;我们可以在客户端用mysql -h [ip] -P [port] -u 用户名 -p 密码 命令向服务端发起连接请求&#xff0c;这个连接请…...

网络互联究竟是需要什么协议相同,什么协议不同?

混淆概念的几个说法&#xff1a; 说法1&#xff1a; “以太网交换机不可以实现采用不同网络层协议的互联” 原因&#xff1a;以太网交换机是数据链路层的设备&#xff0c;不懂网络层的知识 说法2&#xff1a; “网桥可互联不同的物理层、不同的MAC子层以及不同速率的以太网”…...

ajax axios json

目录 一、ajax概述 1. 概念 2. 实现方式 &#xff08;1&#xff09;原生的JS实现方式&#xff08;了解&#xff09; &#xff08;2&#xff09; JQeury实现方式 二、axios 介绍 三、axios使用 1. axios 发送get/post请求 2. axios验证用户名称是否存在 四、json 1. …...

外观模式——提供统一入口

1、简介 1.1、概述 在软件开发中&#xff0c;有时候为了完成一项较为复杂的功能&#xff0c;一个类需要和多个其他业务类交互&#xff0c;而这些需要交互的业务类经常会作为一个完整的整体出现&#xff0c;由于涉及的类比较多&#xff0c;导致使用时代码较为复杂。此时&#…...

Vue中导入并读取Excel数据

在工作中遇到需要前端上传excel文件获取到相应数据处理之后传给后端并且展示上传文件的数据. 一、引入依赖 npm install -S file-saver xlsxnpm install -D script-loadernpm install xlsx二、在main.js中引入 import XLSX from xlsx三、创建vue文件 <div><el-uplo…...

CUDA常用函数

cudaDeviceSynchronize cudaDeviceSynchronize是一个CUDA函数&#xff0c;用于同步当前设备上的所有CUDA流。它会阻塞调用它的线程&#xff0c;直到所有设备上的CUDA流都执行完为止。这可以确保在进行后续的CUDA操作时&#xff0c;先前的操作已经完成。 在CUDA程序中&#xff0…...

72. ElasticSearch常用命令

索引管理 1新建索引 curl -XPUT http://10.42.172.35:9200/index012 读写权限 curl -XPUT -d {"blocks.read":false} http://10.42.172.35:9200/index01/_settings3 查看索引 单个 curl -XGET http://10.42.172.35:9200/index01/_settings多个 curl -XGET http…...

2023.7.26(同余方程的通解与特解)

Water(扩欧求特解与通解) 题意&#xff1a;给容量分别为A与B的水杯&#xff0c;问确切喝到C水的最小操作次数 有4种操作&#xff1a;选一杯全喝&#xff0c;选一杯全部倒掉&#xff0c;选一杯装满&#xff0c;将一杯的水尽量倒到另一杯中 思路&#xff1a;只有AxByC有解时才能确…...

Diffusion扩散模型学习3——Stable Diffusion结构解析-以图像生成图像(图生图,img2img)为例

Diffusion扩散模型学习3——Stable Diffusion结构解析-以图像生成图像&#xff08;图生图&#xff0c;img2img&#xff09;为例 学习前言源码下载地址网络构建一、什么是Stable Diffusion&#xff08;SD&#xff09;二、Stable Diffusion的组成三、img2img生成流程1、输入图片编…...

LangChain||什么是LangChain? LangChain有什么用?

从Auto-GPT说起&#xff1a; Auto-GPT可以调用本地电脑工具处理复杂信息;Auto-GPT可以围绕目标查阅资 料、“独立思考”、及时反馈、并 及时调整下一步操作…Auto-GPT的诞生&#xff0c;创造了大家 对“将LLM作为智慧大脑来高效 处理综合复杂任务”的想象;首次尝试串联大语言模…...

别再手动调了!用Visio这个隐藏的字体设置窗口,一键切换泳道图标题横竖排

Visio高效技巧&#xff1a;解锁泳道图标题排版的隐藏技能 每次在Visio中调整泳道图标题方向时&#xff0c;你是否还在反复右键点击、寻找格式选项&#xff1f;其实Visio内置了一个被多数用户忽略的高效设置窗口——"字体"对话框。这个看似普通的设置面板&#xff0c;…...

AssetRipper终极指南:如何免费快速提取Unity游戏资源

AssetRipper终极指南&#xff1a;如何免费快速提取Unity游戏资源 【免费下载链接】AssetRipper GUI Application to work with engine assets, asset bundles, and serialized files 项目地址: https://gitcode.com/GitHub_Trending/as/AssetRipper AssetRipper是一款强…...

如何让Windows高效识别苹果设备?极简驱动安装工具3分钟解决连接难题

如何让Windows高效识别苹果设备&#xff1f;极简驱动安装工具3分钟解决连接难题 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitco…...

【Visual Leak Detector】跨平台 QT 项目集成 VLD 的便携式部署方案

1. Visual Leak Detector 与 QT 开发的那些事儿 做 C 开发的朋友应该都遇到过内存泄漏这个头疼的问题。特别是用 QT 开发跨平台应用时&#xff0c;随着项目规模扩大&#xff0c;内存管理就变得格外棘手。Visual Leak Detector&#xff08;简称 VLD&#xff09;这个轻量级工具简…...

NaViL-9B参数详解教程:max_new_tokens与temperature协同调优

NaViL-9B参数详解教程&#xff1a;max_new_tokens与temperature协同调优 1. 认识NaViL-9B多模态大模型 NaViL-9B是上海人工智能实验室研发的原生多模态大语言模型&#xff0c;它不仅能处理纯文本问答&#xff0c;还能理解图片内容。这个模型特别适合需要同时处理文字和图像信…...

当AI走进柴米油盐:我们的生活正在发生怎样的改变?

当清晨的AI闹钟根据你的睡眠周期轻声唤醒&#xff0c;通勤导航提前规避了突发拥堵的路段&#xff0c;办公软件里的AI一键生成了会议纪要与数据报表&#xff0c;回家路上智能家电已提前调好室温与灯光&#xff0c;睡前AI陪练帮孩子巩固了当天的知识点&#xff0c;也为独居的父母…...

Cursor Pro免费激活指南:3步解锁AI编程工具的完整功能

Cursor Pro免费激活指南&#xff1a;3步解锁AI编程工具的完整功能 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached your tri…...

洛雪音乐音源项目:免费高品质音乐资源获取的终极方案

洛雪音乐音源项目&#xff1a;免费高品质音乐资源获取的终极方案 【免费下载链接】lxmusic- lxmusic(洛雪音乐)全网最新最全音源 项目地址: https://gitcode.com/gh_mirrors/lx/lxmusic- 1 价值定位&#xff1a;重新定义音乐资源获取体验 洛雪音乐音源项目作为一款开源…...

LPDDR4X引脚功能详解:从CK到DQS,这些信号线你都用对了吗?

LPDDR4X引脚功能深度解析&#xff1a;信号完整性设计与实战避坑指南 在移动设备和高性能嵌入式系统中&#xff0c;LPDDR4X内存已成为主流选择。但许多硬件工程师在实际设计中常陷入"信号连通即可"的误区&#xff0c;导致系统稳定性问题频发。本文将带您深入理解每个…...

3大焕新方案:老旧iOS设备性能重生全指南

3大焕新方案&#xff1a;老旧iOS设备性能重生全指南 【免费下载链接】Legacy-iOS-Kit An all-in-one tool to downgrade/restore, save SHSH blobs, and jailbreak legacy iOS devices 项目地址: https://gitcode.com/gh_mirrors/le/Legacy-iOS-Kit 老旧iOS设备随着系统…...