openlayers系列:加载arcgis和geoserver在线离线切片

https://www.freesion.com/article/1751396517/

1.背景

有个项目需要使用openlayer加载各种服务上发布的数据,坐标系也不同,我们都知道openalyer默认可以加载EPAG:3857,要加载4490的坐标系的数据需要重新定义一下,之后再加载。一想起要重新定义坐标系感觉很难,就想放弃,其实静下心了做一下也没那么难。在此做个简单的记录,要加载的数据如下:

1.1 arcgis 服务 

1.2 本地切好的瓦片服务

1.3结果 加载好天地图、4490arcgisserver 服务、本地影像切片

 

2.解决思路

2.1 原理

使用proj4js 给所有坐标和范围提供视图投影系(默认是EPAG:3857),给每个要加载的图层设置此坐标系即可正常加载。

2.2 资源

(1).API   OpenLayers v7.4.0 API 

  (2)epsg  ​​​​​​​EPSG.io: Coordinate Systems Worldwide 

   了解有关各种投影的参数定义

  (3)proj4js proj4js (v2.9.0)   https://www.bootcdn.cn/proj4js/

2.3 重新定义坐标系步骤​​​​​​​

(1)proj4引用 前端添加Proj4js有三种方式:

  • 从​ ​http://trac.osgeo.org/proj4js/wiki/Download​​下载,获取产品包中dist/proj4.js文件。
  • 引入CDN上的Proj4js:​ ​https://cdnjs.com/libraries/proj4js​​
  • 本地有Node.js,可以直接使用​​npm install proj4 --save进行安装。

(2)基础使用

proj4.js中预定义了三个坐标系,其他的坐标系则需要自己定义了,下面以从WGS84(4326)到Web墨卡托(3857)的转换为例

function Wgs84ToMector2(lat,lng) {
    const proj4 = require('proj4');
   return proj4(proj4('EPSG:4326'), proj4('EPSG:3857'), [lng, lat])
}

 定义坐标系:

function init4490(){
    proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");
//4490的坐标系注册进openlayer的projection中
    register(proj4);
//重写projection4490,地图投影
    var projection = new Projection({
        code: 'EPSG:4490',
        units: 'degrees',
        axisOrientation: 'neu'
    });
    addProjection(projection);
    projection.setExtent([-180, -90, 180, 90]);
    projection.setWorldExtent([-180, -90, 180, 90]);
    projection.getMetersPerUnit = function(){
       return 2 * Math.PI * 6378137 / 360;
    };
    addCoordinateTransforms( "EPSG:4326","EPSG:4490", function( coordinate){
            return proj4("EPSG:4490", "EPSG:4326",coordinate);},
        function(coordinate){
            return proj4("ERSG:4490" , "EPSG:4326" , coordinate);
        }
    );
}

其中 proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");是从epsg的网站上获取的参数,如下图:【输入4490坐标系】---【选择proj4js】---【复制】即可。

 

定义好4490坐标系后,需要注册和重写projection 

3.加载多源不同坐标系的地图

3.1加载arcgis server wmts服务

function getWMTSLayer(options) {

    const projections = options.projection?options.projection:projection4326;
    const res = getResolutionsAndMids(projections);

    return new TileLayer({
        source: new WMTS({
            name: "中国",
            url: options.url,
            layer: options.layer, // 图层名
            version: '1.0.0',// WMTS版本
            style: options.style?options.style:"default",
            matrixSet: options.matrixSet?options.matrixSet:"c", // 投影坐标系矩阵集,一定要和WMTS capabilities文档中一致,否则会加载失败
            format: options.format?options.format:"tiles",   // 图片格式
            wrapX: true,
            tileGrid: new WMTSTileGrid({// 投影坐标系
                origin: getTopLeft(projections.getExtent()),
                resolutions: res.resolutions,
                matrixIds: res.matrixIds,
            }),
            projection: projections // 投影坐标系
        }),
    })
}

3.2加载切好的本地图层

function getXYZLayer(options) {
    const projections = options.projection?options.projection:projection4326;
    return new TileLayer({
        title: '泾阳',
        source:  new XYZ({
            url: options.url,
            projection: projections
        })
    })
}

4.图层顺序

        在 openlayer 中,图层是使用 layer 对象表示的,主要有 WebGLPoints Layer、 热度图(HeatMap Layer)、图片图层(lmage Layer)、切片图层(Tile Layer)和 矢量图层(Vector Layer)五种类型,它们都是继承 Layer 类的。
常用参数

  • source,指定了图层的数据来源,图层作用是以一定的样式渲染数据,source则指定了数据visible ,是否可见;
  • zlndex,图层的叠加次序,默认是0,最底层,如果使用setMap方法添加的图层,zlndex值是Infinity,在最上层:
  • extent,图层消染的区域,即浏览器窗口中可见的地图区域。extent是一个矩形范用,格式是number, number,number, numberl 分别代表[left,botom.right.top]。为了提升染效率和加载速度,extent范用之外的瓦片是不会请求的,当然也不会演染className,图层各个元素的样式:
  • opacity,透明度,默认为 1,即完全透明:

找到新建Map对象的时候,调整layers的顺序,layer越往右,图层越往上显示。

var layer = new Vector({
    source: new Vector({
        projection: 'EPSG:4326',
        format: new GeoJSON()
    }),
    style: styleFunction,
    zIndex:9999
});

6.整体demo

openalyer.vue

<template lang="pug">
#map
</template>
<script setup>
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import {onMounted, onUnmounted, reactive} from "vue";
import {img_c} from "./map.js";
import {fromLonLat} from 'ol/proj'
onMounted(()=>{
    const layers1 = img_c()
    const map = new Map({
        layers: layers1,
        target: 'map',
        view: new View({
            center: fromLonLat([108.68, 34.6]),//地图中心
          // extent : [ 119.54811, 29.92294, 120.50942, 30.69748 ],
            zoom: 12,
        }),
    });

})

</script>
<style scoped lang="less">
#map {
    position: absolute;
    width: 100%;
    height: 900px;
}
</style>

map.js


import {register} from 'ol/proj/proj4'
import {Projection,addProjection,addCoordinateTransforms,get} from 'ol/proj';
import TileLayer from 'ol/layer/Tile.js';
import {WMTS,XYZ} from 'ol/source.js';
import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
import {getWidth,getTopLeft} from 'ol/extent';
import proj4 from 'proj4';

function init4490(){
    proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");
//4490的坐标系注册进openlayer的projection中
    register(proj4);
//重写projection4490,地图投影
    var projection = new Projection({
        code: 'EPSG:4490',
        units: 'degrees',
        axisOrientation: 'neu'
    });
    addProjection(projection);
    projection.setExtent([-180, -90, 180, 90]);
    projection.setWorldExtent([-180, -90, 180, 90]);
    projection.getMetersPerUnit = function(){
       return 2 * Math.PI * 6378137 / 360;
    };
    addCoordinateTransforms( "EPSG:4326","EPSG:4490", function( coordinate){
            return proj4("EPSG:4490", "EPSG:4326",coordinate);},
        function(coordinate){
            return proj4("ERSG:4490" , "EPSG:4326" , coordinate);
        }
    );
}

init4490()
//transform([118,32] , 'EPSG:4326' , 'EPSG:4490 ');
const projection4490 = new get('EPSG:4490' );
const projection4326 = new get('EPSG:4326' );
const projection3857 = new get('EPSG:3857' );


function getResolutionsAndMids(projection) {
    const projections = projection?projection:projection4326;
    let projectionExtent = projections.getExtent();
    let size = getWidth(projectionExtent) / 256; //size就是一个像素代表的经纬度
    let matrixIds = [];

    let resolutions = [];
    for (let z = 0; z < 20; ++z) {
        resolutions[z] = size / Math.pow(2, z);
        matrixIds[z] = z;
    }
    return {"resolutions":resolutions,"matrixIds":matrixIds};
}

export function getProjection() {
    return projection4490
}
// WMTS 形式
function getWMTSLayer(options) {

    const projections = options.projection?options.projection:projection4326;
    const res = getResolutionsAndMids(projections);

    return new TileLayer({
        source: new WMTS({
            name: "中国",
            url: options.url,
            layer: options.layer, // 图层名
            version: '1.0.0',// WMTS版本
            style: options.style?options.style:"default",
            matrixSet: options.matrixSet?options.matrixSet:"c", 
// 投影坐标系矩阵集,一定要和WMTS capabilities文档中一致,否则会加载失败
            format: options.format?options.format:"tiles",   // 图片格式
            wrapX: true,
            tileGrid: new WMTSTileGrid({// 投影坐标系
                origin: getTopLeft(projections.getExtent()),
                resolutions: res.resolutions,
                matrixIds: res.matrixIds,
            }),
            projection: projections // 投影坐标系
        }),
    })
}
function getXYZLayer(options) {
    const projections = options.projection?options.projection:projection4326;
    return new TileLayer({
        title: '泾阳',
        source:  new XYZ({
            url: options.url,
            projection: projections
        })
    })
}
const key ='b9031f80391e6b65bd1dd80dcde1b097';
/**
 \* 矢量底图 + 矢量注记
 */
export function vec_c() {
    return [
        getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/vec_c/wmts?tk=' + key, "layer":'vec',"projection":projection4490}),
        getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cva_c/wmts?tk=' + key, "layer":'cva',"projection":projection4490}),
    ]
}

/**
 \* 影像底图 + 影像注记
 */
export function img_c() {
    return [
      //  getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/img_c/wmts?tk=' + key, "layer":'img',"projection":projection4490}), getXYZLayer({"url":'https://xxxx/jingyang/imgyx/jyx/{z}/{x}/{y}.png',"projection":projection3857}),
  getWMTSLayer({"url":'http://xxxx:6080/arcgis/rest/services/jingyang/jingyang1/MapServer/WMTS?',"layer":'jingyang_jingyang1',"projection":projection4490}),
        getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cia_c/wmts?tk=' + key, "layer":'cia'}),
      //  getXYZLayer({"url":'http://xxxx:6080/arcgis/rest/services/jingyang/jingyang1/MapServer/tiles/{z}/{x}/{y}.png',"projection":projection4490}),
 ]
}
/**
 \* 地形底图 + 地形注记
 */
export function ter_c() {
    return [
        getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/ter_c/wmts?tk=' + key, "layer":'ter',"projection":projection4490}),
        getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cta_c/wmts?tk=' + key, "layer":'cta',"projection":projection4490}),
    ]
}

7.其他

7.1 Layer分类

  • TitleLayer: 切片图层,用于加载切片数据。切片是指利用网格将一幅地图切成大小相等的小正方形。切片尺寸一般是256*256或者512*512
  • ImageLayer:图片图层,主要用于服务器渲染的图像,
  • VectorLayer:矢量图层,是指在客户端渲染的图层类型
  • VectorTileLayer:矢量切片图层,和栅格切片一样的思路。

7.2 source类型

source 是 Layer 的重要组成部分,表示图层的来源,也就是服务地址。除了在构造函数中制定外,可以使用 layer.setSource(source) 稍后指定。

基类(不能被实例化,只负责被继承):

  • ol.source.Image,提供单一图片数据的类型,直接继承自 ol.source.Source;
  • ol.source.Tile,提供被切分为网格切片的图片数据,继承自 ol.source.Source;
  • ol.source.Vector,提供矢量图层数据,继承自 ol.source.Source;

可以实例化的类:

  • ol.source.BingMaps ,必应地图的切片数据,继承自ol.source.TileImage;
  • ol.source.Cluster,聚簇矢量数据,继承自ol.source.Vector;
  • ol.source.ImageCanvas,数据来源是一个 canvas 元素,其中的数据是图片,继承自 ol.source.Image;
  • ol.source.ImageMapGuide,Mapguide 服务器提供的图片地图数据,继承自 ol.source.Image,fire ol.source.ImageEvent;
  • ol.source.ImageStatic,提供单一的静态图片地图,继承自ol.source.Image;
  • ol.source.ImageVector,数据来源是一个 canvas 元素,但是其中的数据是矢量来源 ol.source.Vector,继承自 ol.source.ImageCanvas;
  • ol.source.ImageWMS,WMS 服务提供的单一的图片数据,继承自 ol.source.Image,触发 ol.source.ImageEvent;
  • ol.source.MapQuest,MapQuest 提供的切片数据,继承自 ol.source.XYZ;
  • ol.source.OSM,OpenStreetMap 提供的切片数据,继承自 ol.source.XYZ;
  • ol.source.Stamen,Stamen 提供的地图切片数据,继承自 ol.source.XYZ;
  • ol.source.TileVector,被切分为网格的矢量数据,继承自 ol.source.Vector;
  • ol.source.TileDebug,并不从服务器获取数据,而是为切片渲染一个网格,继承自 ol.source.Tile;
  • ol.source.TileImage,提供切分成切片的图片数据,继承自 ol.source.Tile,触发 ol.source.TileEvent;
  • ol.source.TileUTFGrid,TileJSON 格式 的 UTFGrid 交互数据,继承自 ol.source.Tile;
  • ol.source.TileJSON,TileJSON 格式的切片数据,继承自 ol.source.TileImage;
  • ol.source.TileArcGISRest,ArcGIS Rest 服务提供的切片数据,继承自 ol.source.TileImage;
  • ol.source.WMTS,WMTS 服务提供的切片数据。继承自 ol.source.TileImage;
  • ol.source.XYZ,XYZ 格式的切片数据,继承自 ol.source.TileImage;
  • ol.source.Zoomify,Zoomify 格式的切片数据,继承自 ol.source.TileImage。

7.3 proj常见方法

(1)ol.proj.addCoordinateTransforms(source, destination, forward, inverse)
注册坐标转换函数来转换源投影和目标投影之间的坐标。正、反函数转换坐标对;此函数将这些转换为内部使用的处理区段和坐标数组的函数

source:源投影
destination:目标投影
forward:接受ol的正向变换函数(即从源投影到目标投影)。作为参数,并返回转换后的ol.Coordinate
inverse:接受ol的逆变换函数(即从目标投影到源投影)。作为参数,并返回转换后的ol.Coordinate
(2)ol.proj.addEquivalentProjections(projections)
注册不改变坐标的转换函数。它们允许在具有相同含义的投影之间进行转换。

(3)ol.proj.addProjection(projection)
将投影对象添加到受支持的投影列表中,这些投影可以通过它们的SRS码进行查找。

(4)ol.proj.equivalent(projection1, projection2)
检查两个投影是否相同,即一个投影中的每个坐标确实表示另一个投影中的相同地理点。

(5)ol.proj.fromLonLat(coordinate, opt_projection)
将经纬度坐标转换为不同的投影

coordinate:经纬度数组,经度在前,纬度在后
projection:目标投影。默认是Web Mercator,即“EPSG: 3857”
(6)ol.proj.get(projectionLike)
获取指定代码的投影对象。

(7)ol.proj.getTransform(source, destination)
给定类似于投影的对象,搜索转换函数将坐标数组从源投影转换为目标投影。

(8)ol.proj.setProj4(proj4)
proj4注册。如果没有显式注册,则假定proj4js将加载在全局名称空间中

ol.proj.setProj4(proj4);
(9)ol.proj.toLonLat(coordinate, opt_projection)
将坐标转换为经度/纬度

coordinate:投影坐标
projection:坐标的投影,默认是Web Mercator,即“EPSG: 3857”
(10)ol.proj.transform(coordinate, source, destination)
将坐标从源投影转换为目标投影,这将返回一个新的坐标(并且不修改原始坐标)。

coordinate:坐标
source:源投影
destination:目标投影
(11)ol.proj.transformExtent
将范围从源投影转换为目标投影,这将返回一个新范围(并且不修改原始范围)。

(12)ol.proj.Units{string}
投影单位:'degrees', 'ft', 'm', 'pixels', 'tile-pixels' or 'us-ft'

8. 参考文章

开源GIS(二)——openlayers加载Arcgis和geoserver在线离线切片 - 灰信网(软件开发博客聚合)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

脑电信号处理与特征提取——4.脑电信号的预处理及数据分析要点(彭微微)

目录 四、脑电信号的预处理及数据分析要点 4.1 脑电基础知识回顾 4.2 伪迹 4.3 EEG预处理 4.3.1 滤波 4.3.2 重参考 4.3.3 分段和基线校正 4.3.4 坏段剔除 4.3.5 坏导剔除/插值 4.3.6 独立成分分析ICA 4.4 事件相关电位&#xff08;ERPs&#xff09; 4.4.1 如何获…

【STM32】 强大的 STM32Cube 生态 STM32CubeIDE 无伤速通

本文介绍的软件&#xff0c;均可以在ST官网st.com免费下载&#xff08;你需要注册登录&#xff09;&#xff0c;首选官网下载最新版本&#xff0c;如果有问题&#xff0c;可以在我的公众号回复&#xff1a;Cube&#xff0c;获取截止今日的最新版本软件安装包。 目录 一、STM32C…

什么是框架?为什么要学框架?

一、什么是框架 框架是整个或部分应用的可重用设计&#xff0c;是可定制化的应用骨架。它可以帮开发人员简化开发过程&#xff0c;提高开发效率。 项目里有一部分代码&#xff1a;和业务无关&#xff0c;而又不得不写的代码>框架 项目里剩下的部分代码&#xff1a;实现业务…

Maven-----进阶

目录 1 分模块开发1.1 分模块开发的意义1.2 分模块开发实现 2 依赖管理2.1 依赖传递2.2 依赖传递冲突问题2.3 可选依赖和排除依赖 3 继承与聚合3.1 聚合3.2 继承3.2 聚合与继承的区别 4 属性4.1 属性4.2 资源文件引用属性4.3 版本管理 5 多环境配置与使用5.1 多环境开发5.2 跳过…

22matlab数据分析 拉格朗日插值(matlab程序)

1.简述 第一部分&#xff1a;问题分析 &#xff08;1&#xff09;实验题目&#xff1a;拉格朗日插值算法 具体实验要求&#xff1a;要求学生运用拉格朗日插值算法通过给定的平面上的n个数据点&#xff0c;计算拉格朗日多项式Pn(x)的值&#xff0c;并将其作为实际函数f(x)的估…

idea 设置了 vm options后无法启动

今天想扩展ideaj的JVM 设置了 vm options后无法启动 找了很久&#xff0c;重新卸载后安装也没有用 后面直接打开idea的bat文件 找到自己idea使用的.vmoptions文件&#xff0c;我是因为之前idea有缓存&#xff0c;一直用的我修改的文件&#xff0c;后面删了就可以启动了

基于机器视觉工具箱和形态学处理的视频中目标形状检测算法matlab仿真

目录 1.算法理论概述 2.部分核心程序 3.算法运行软件版本 4.算法运行效果图预览 5.算法完整程序工程 1.算法理论概述 目标形状检测是计算机视觉领域的重要任务之一&#xff0c;旨在从视频序列中自动检测和识别特定目标的形状。本文介绍一种基于机器视觉工具箱和形态学处理…

【计算机网络】网络基础

文章目录 1. 网络的发展2. 认识网络协议2.1 协议栈在所有操作系统中是统一的2.2 协议分层2.3 协议各层的功能2.4 协议分层的好处 3. 具体的网络协议栈3.1 OSI七层模型3.2 TCP/IP五层模型 4. 网络通信基本流程4.1 同局域网的两台主机通信4.2 跨局域网的两台主机通信 5. 网络中的…

JavaScript基础篇(31-40题)

此文章&#xff0c;来源于印客学院的资料【第一部分&#xff1a;基础篇(105题)】&#xff0c;也有一些从网上查找的补充。 这里只是分享&#xff0c;便于学习。 诸君可以根据自己实际情况&#xff0c;自行衡量&#xff0c;看看哪里需要加强。 概述如下&#xff1a; javascri…

Flink简介及部署模式

文章目录 1、Flink简介2、Flink部署2.1 本地模式2.1 Standalone模式部署2.2 Standalone模式下的高可用2.3 Yarn模式Yarn模式的高可用配置&#xff1a;yarn模式中三种子模式的区别&#xff1a; 3、并行度4、提交命令执行指定任务Application Mode VS yarn per-job 5、注意事项5、…

硬件系统工程师宝典(33)-----EEPROM电路如何设计?

各位同学大家好&#xff0c;欢迎继续做客电子工程学习圈&#xff0c;今天我们继续来讲这本书&#xff0c;硬件系统工程师宝典。 上篇我们了解了嵌入式应用中应用领域不同&#xff0c;所采用的CPU也不同&#xff0c;不过CPU部分电路的设计过程都较为相似。并且&#xff0c;我们…

5. Bean 的作用域和生命周期

目录 1. Bean 被修改的案例 2. 作用域定义 2.1 Bean 的 6 种作用域 singleton prototype request session application&#xff08;了解&#xff09; websocket &#xff08;了解&#xff09; 单例作用域&#xff08;singleton&#xff09;VS 全局作用域&#xff08;…

JVM堆内存介绍

一&#xff1a;JVM中内存 JVM中内存通常划分为两个部分&#xff0c;分别为堆内存与栈内存&#xff0c;栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址。 JVM全部的对象信息都 存放在堆内存中。相比栈内存&#xff0c;堆内存能够所大的多&am…

web-vim信息泄露

&#xff08;1&#xff09;知识补充 vim 交换文件名 在使用vim时会创建临时缓存文件&#xff0c;关闭vim时缓存文件则会被删除&#xff0c;当vim异常退出后&#xff0c;因为未处理缓存文件&#xff0c;导致可以通过缓存文件恢复原始文件内容   以 index.php 为例&#xff1…

Windows 10, version 22H2 (updated Jul 2023) 中文版、英文版下载

Windows 10, version 22H2 (updated Jul 2023) 中文版、英文版下载 Windows 10 22H2 企业版 arm64 x64 请访问原文链接&#xff1a;https://sysin.org/blog/windows-10/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Window…

基于C++的QT基础教程学习笔记

文章目录&#xff1a; 来源 教程社区 一&#xff1a;QT下载安装 二&#xff1a;注意事项 1.在哪里写程序 2.如何看手册 3.技巧 三&#xff1a;常用函数 1.窗口 2.相关 3.按钮 4.信号与槽函数 5.常用栏 菜单栏 工具栏 状态栏 6.铆接部件 7.文本编辑 8…

postman接口测试实战讲解

目录 背景描述 创建一个GET请求 在pre-request scripts构建签名 脚本写在环境变量中 postman console的用法 Collection Runner 自动化API测试 创建接口的测试用例 选择并运行自动化接口测试 测试结果 有还不懂的同学可以找我拿演示视频喔 背景描述 有一个项目要使…

10分钟内入门 ArcGIS Pro

本文来源&#xff1a;GIS荟 大家好&#xff0c;这篇文章大概会花费你10分钟的时间&#xff0c;带你入门 ArcGIS Pro 的使用&#xff0c;不过前提是你有 ArcMap 使用经验。 我将从工程文件组织方式、软件界面、常用功能、编辑器、制图这5个维度给大家介绍。 演示使用的 ArcGI…

element-ui 表格没有内容点击插入数据,有内容点击删除(vue)

记录一下&#xff0c;希望能够帮到大家。 <template><div><div class"tabs" style"display: flex;line-height: 20px"><button href"javascript:;" :class"{active: dialogFormVisible3}" click"dialogForm…

[uni-app] 微信小程序 - 组件找不到/导入报错 (分包问题导致)

文章目录 问题表现问题原因 问题表现 切换了个路径下的组件, 导入失败, 尝试了清缓存\重启\删项目等一些列操作均无效 上面两个路径中, 都存在一模一样的videItem.vue Main路径是可以导入的 Main路径是无法导入的 问题原因 后来发现, 是 分包的问题导致. 我们先来假设一个场…