高德地图在vue3项目中使用:实现画矢量图、编辑矢量图

使用高德地图实现画多边形、矩形、圆,并进行编辑保存和回显。

1、准备工作

参考高德地图官网,进行项目key申请,链接: 准备

2、项目安装依赖

npm i @amap/amap-jsapi-loader --save

3、地图容器

html

<template>
    <!-- 绘制地图区域组件(圆、矩形、多边形) -->
    <el-dialog
        v-model="state.showDialog"
        :title="props.title"
        @close="handleClose"
        destroy-on-close
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        align-center
        draggable
        :style="{ padding: 0, width: dialogWidth, height: dialogHeight }">
        <div class="position" v-if="state.showDialog">
            <div class="hover-txt" :style="{left: state.pointX+'px', top: state.pointY+'px'}">{{ hoverTxt }}</div>
            <div ref="mapRef" id="container"></div>
            <div class="search_box">
                <div class="change-btn">
                    <el-button :type="state.stateLayer === 0 ? '' : 'primary'" @click="changeMap"> 卫星图 </el-button>
                    <el-button :type="state.stateLayer === 1 ? '' : 'primary'" @click="changeMap"> 标准地图 </el-button>
                </div>
                <div class="btn">
                    <el-button
                        type="primary"
                        @click="handleEditor(1)"
                        :disabled="state.drawType === 2 || state.drawType === 3 || props.isView">
                        {{ state.areaLayer && state.drawType === 1 ? '编辑圆' : '添加圆' }}
                    </el-button>
                    <el-button
                        type="primary"
                        @click="handleEditor(2)"
                        :disabled="state.drawType === 1 || state.drawType === 3 || props.isView">
                        {{ state.areaLayer && state.drawType === 2 ? '编辑矩形' : '添加矩形' }}
                    </el-button>
                    <el-button
                        type="primary"
                        @click="handleEditor(3)"
                        :disabled="state.drawType === 1 || state.drawType === 2 || props.isView">
                        {{ state.areaLayer && state.drawType === 3 ? '编辑多边形' : '添加多边形' }}
                    </el-button>
                    <el-button type="danger" @click="handleClear" :disabled="props.isView">清除</el-button>
                    <el-button type="primary" @click="handleEmit" :disabled="props.isView">完成</el-button>
                </div>
            </div>
        </div>
    </el-dialog>
</template>

css

<style lang="scss" scoped>
    .position {
        box-sizing: border-box;
        padding: 0 20px;
        width: 100%;
        height: 100%;
        position: relative;
        #container {
            width: 100%;
            height: 100%;
        }
        .hover-txt {
            position: absolute;
            z-index: 50;
            border: 1px solid #303133;
            background: #fff;
            color: #303133;
            padding: 2px 4px;
        }
        .search_box {
            width: 100%;
            height: 50px;
            background-color: #fff;
            position: absolute;
            top: 0;
            left: 20px;
            .change-btn {
                position: absolute;
                right: 40px;
            }
            .btn {
                margin-right: 20px;
                display: flex;
                align-items: center;
                .search_input {
                    width: 100px;
                    margin-right: 10px;
                }
            }
        }
    }
</style>

4、业务逻辑

需求是只画多边形、矩形、圆三者中的一个,保存完之后再进行编辑。如果实现画多个图形,须把保存图层变量换成数组,每次编辑完之后,drawState要恢复为新增状态,让按钮可点击。

<script lang="ts" setup>
    import { onBeforeUnmount, onMounted, reactive, shallowRef, computed } from 'vue';
    import AMapLoader from '@amap/amap-jsapi-loader';
    import { getCompanyInfo } from '@/api/base/enterpriseInfo';
    import { ElMessage } from 'element-plus';

    const props = defineProps({
        // 区域范围
        areaRangeInfo: {
            type: String,
            default: '',
        },
        // 弹窗大小
        size: {
            type: Number,
            default: 2,
        },
        // 查看定位
        isView: {
            type: Boolean,
            default: false,
        },
        // 弹窗标题
        title: {
            type: String,
            default: '选取区域',
        },
    });

    //一定要加上密钥,否则服务类插件会失效,个人账户每天只有5000次提示机会
    (window as any)._AMapSecurityConfig = {
        key: 'xxxxxxxxxxxxxxxxxxxxxxxxx',
        securityJsCode: 'xxxxxxxxxx',
    };

    onBeforeUnmount(() => {
        // 移除监听
        map.off('click', (e: any) => {
            console.log('移除点击事件');
        });
        // 移除悬浮事件
        if(state.mousemoveEvent) {
            state.mousemoveEvent.removeEventListener('mousemove', (e:any) => {
                state.pointX = -500;
                state.pointY = -500;
            });
        }
    });

    onMounted(async () => {
        if(props.areaRangeInfo) {
            state.areaLayerInfo = JSON.parse(props.areaRangeInfo);
        }
        if (state.areaLayerInfo && state.areaLayerInfo.type && state.areaLayerInfo.type != 0) {
            state.drawType = Number(state.areaLayerInfo.type);
            state.drawState = 1;
            state.lng = state.areaLayerInfo.center[0];
            state.lat = state.areaLayerInfo.center[1];
        } else {
            state.drawState = -1;
            await getCompanyInfo('').then((res: any) => {
                if (res.code == 0) {
                    if (!res.data.dzLng || !res.data.dzLat) {
                        state.lng = 116.397935;
                        state.lat = 39.900402;
                    } else {
                        state.lng = Number(res.data.dzLng);
                        state.lat = Number(res.data.dzLat);
                    }
                }
            });
        }
        await initMap();
    });

    let map = shallowRef(null as any);  // 高德地图实例
    const state = reactive({
        pointX: -500,
        pointY: -500,
        lng: 0 as number,               // 经度
        lat: 0 as number,               // 纬度
        AMap: null as any,              // 高德地图对象
        showDialog: true,               // 控制弹窗状态
        stateLayer: 1 as number,        // 0 街道 1 卫星
        drawType: 0 as number,          // 绘制图形类型 0 未绘制 1 圆 2 矩形 3 多边形
        drawState: -1 as number,        // -1 未绘制或已结束绘制 0 新增状态 1 编辑状态
        areaEditor: null as any,        // 画圆、矩形、多边形的map实例对象
        linePoints: [] as any,          // 点位坐标
        areaLayer: null as any,         // 画的图层实例
        mouseTool: null as any,         // 绘图工具
        mousemoveEvent: null as any,
        areaLayerInfo: null as any,     // 图层位置信息
    });

    const emits = defineEmits(['submit', 'handleClose']);
    const dialogWidth = computed(() => {
        if (props.size == 1) {
            return '86%';
        } else if (props.size == 2) {
            return '78%';
        } else {
            return '72%';
        }
    });
    const dialogHeight = computed(() => {
        if (props.size == 1) {
            return '90vh';
        } else if (props.size == 2) {
            return '82vh';
        } else {
            return '76vh';
        }
    });

    let satelliteLayer: any = null;
    let defaultStreet: any = null;
    // 初始化地图
    const initMap = () => {
        AMapLoader.load({
            key: '1e7b6041cfc63f32e8eafdf98005e45f',
            version: '2.0',
            plugins: [
                'AMap.ToolBar',         // 工具条,控制地图的缩放、平移
                'AMap.Scale',           // 比例尺
                'AMap.ControlBar',      // 组合了旋转、倾斜、复位在内的地图控件
                'AMap.Geolocation',     // 定位插件
            ],
        }).then((AMap: any) => {
            state.AMap = AMap;
            map = new AMap.Map('container', {
                viewMode: '2D',
                zoom: 17,
                center: [state.lng, state.lat],
            });

            // 添加卫星图覆盖
            satelliteLayer = new AMap.TileLayer.Satellite();
            // 默认矢量街道图
            defaultStreet = new AMap.TileLayer();
            map.add([satelliteLayer]);

            // 加载工具类插件
            map.addControl(new AMap.ToolBar({position:{right: '40px', top: '160px'}}));
            map.addControl(new AMap.Scale());
            map.addControl(new AMap.ControlBar({position:{right: '10px', top: '60px'}}));
            map.addControl(new AMap.Geolocation());

            // 判断当前区域类型
            if(state.areaLayerInfo && state.areaLayerInfo.type) {
                // 绘制图形类型 0 未绘制 1 圆 2 矩形 3 多边形
                state.drawType = Number(state.areaLayerInfo.type);
                if(state.drawType == 1) {
                    state.areaLayer = new AMap.Circle({
                        center: state.areaLayerInfo.path,
                        radius: state.areaLayerInfo.radius, //半径
                        strokeColor: '#1791FC',
                        strokeOpacity: 1,
                        strokeWeight: 2,
                        fillColor: '#1791FC',
                        fillOpacity: 0.4,
                        cursor:'pointer',
                        strokeStyle: 'solid'
                    });
                    map.add(state.areaLayer);
                } else if(state.drawType == 2) {
                    let southWest:any = new AMap.LngLat(state.areaLayerInfo.southWest[0], state.areaLayerInfo.southWest[1])
                    let northEast:any = new AMap.LngLat(state.areaLayerInfo.northEast[0], state.areaLayerInfo.northEast[1])
                    let bounds:any = new AMap.Bounds(southWest, northEast)
                    state.areaLayer = new AMap.Rectangle({
                        bounds: bounds,
                        strokeColor: '#1791FC',
                        strokeOpacity: 1,
                        strokeWeight: 2,
                        fillColor: '#1791FC',
                        fillOpacity: 0.4,
                        cursor:'pointer',
                        strokeStyle: 'solid'
                    });
                    map.add(state.areaLayer);
                } else if(state.drawType == 3) {
                    state.areaLayer = new AMap.Polygon({
                        path: state.areaLayerInfo.path,
                        strokeColor: '#1791FC',
                        strokeOpacity: 1,
                        strokeWeight: 2,
                        fillColor: '#1791FC',
                        fillOpacity: 0.4,
                        cursor:'pointer',
                        strokeStyle: 'solid'
                    });
                    map.add(state.areaLayer);
                }
            }
            // 地图点击事件
            map.on('click', (e: any) => {
                // console.log(e)
            });
            let domEvent:any = document.getElementById('container');
            state.mousemoveEvent = domEvent.addEventListener('mousemove', (e:any) => {
                if(state.drawType !== 0 && state.drawState !== -1) {
                    state.pointX = e.offsetX + 30;
                    state.pointY = e.offsetY + 15;
                }
            });

        })
    };

    // 获取图层位置信息
    const getAreaLayerInfo = () => {
        let centerInfo:any = map.getCenter();
        if(state.drawType === 1) {
            // 圆
            let centerPoint:any = state.areaLayer.getCenter();
            let radius:any = state.areaLayer.getRadius();
            state.areaLayerInfo = {
                type: '1',
                path: [centerPoint.lng, centerPoint.lat],
                radius: radius,
                center: [centerInfo.lng, centerInfo.lat]
            }
        } else if(state.drawType === 2) {
            let pathObj:any = state.areaLayer.getBounds();
            state.areaLayerInfo = {
                type: state.drawType,
                path: [[pathObj.southWest.lng,pathObj.southWest.lat],[pathObj.northEast.lng,pathObj.northEast.lat]],
                southWest: [pathObj.southWest.lng,pathObj.southWest.lat],
                northEast: [pathObj.northEast.lng,pathObj.northEast.lat],
                center: [centerInfo.lng, centerInfo.lat]
            }
        } else if(state.drawType === 3) {
            // 多边形
            let pathArr:Array<any> = state.areaLayer.getPath();
            let pointArr:Array<any> = [];
            if(pathArr.length > 0) {
                pathArr.map((point:any) => {
                    pointArr.push([point.lng, point.lat])
                });
                state.areaLayerInfo = {
                    type: state.drawType,
                    path: pointArr,
                    center: [centerInfo.lng, centerInfo.lat]
                }
            } else {
                state.areaLayerInfo = {
                    type: '0',
                    path: [],
                    center: []
                }
            }
        } else {
            state.areaLayerInfo = {
                type: '0',
                path: []
            }
        }
        emits('submit', state.areaLayerInfo);
        state.showDialog = false;
    };

    // 开始画区域
    const handleEditor = (type: number) => {
        if(state.areaLayer) {
            state.drawState = 1;
        } else {
            state.drawState = 0;
        }
        state.AMap.plugin('AMap.MouseTool', () => {
            // 异步加载插件
            state.mouseTool = new state.AMap.MouseTool(map);
            state.drawType = type;
            switch (state.drawType) {
                case 1:
                    if(state.drawState === 0) {
                        // 新增圆
                        handleCircleDraw();
                    } else {
                        // 编辑圆
                        handleCircleEditor();
                    }
                    break;
                case 2:
                    if(state.drawState === 0) {
                        // 新增矩形
                        handleRectangleDraw();
                    } else {
                        // 编辑矩形
                        handleRectangleEditor();
                    }
                    break;
                case 3:
                    if(state.drawState === 0) {
                        // 新增多边形
                        handlePolygonDraw();
                    } else {
                        // 编辑多边形
                        handlePolygonEditor();
                    }
                    break;
            }
            state.mouseTool.on('draw',(e:any) => {
                // 绘制结束
                state.mouseTool.close(false); // 关闭
                state.drawState = -1;
                state.pointX = -500;
                state.pointY = -500;
                map.setDefaultCursor('pointer');
                if(state.drawType === 1) {
                    state.areaLayer = map.getAllOverlays('circle')[0];
                } else if(state.drawType === 2) {
                    state.areaLayer = map.getAllOverlays('rectangle')[0];
                } else if(state.drawType === 3) {
                    state.areaLayer = map.getAllOverlays('polygon')[0];
                }
            })
        });
    };

    // 开始画圆
    const handleCircleDraw = () => {
        map.setDefaultCursor('crosshair');
        state.mouseTool.circle({
            strokeColor: '#1791FC',
            strokeOpacity: 1,
            strokeWeight: 2,
            fillColor: '#1791FC',
            fillOpacity: 0.4,
            cursor:'pointer',
            strokeStyle: 'solid'
        });
    };

    // 开始编辑圆
    const handleCircleEditor = () => {
        state.AMap.plugin('AMap.CircleEditor', () => {
            // 异步加载插件
            if (state.areaLayer) {
                state.areaEditor = new state.AMap.CircleEditor(map, state.areaLayer);
                state.areaEditor.open();
            }
        });
    };

    // 开始画矩形
    const handleRectangleDraw = () => {
        map.setDefaultCursor('crosshair');
        state.mouseTool.rectangle({
            strokeColor: '#1791FC',
            strokeOpacity: 1,
            strokeWeight: 2,
            fillColor: '#1791FC',
            fillOpacity: 0.4,
            cursor:'pointer',
            strokeStyle: 'solid'
        });
    };

    // 开始编辑矩形
    const handleRectangleEditor = () => {
        state.AMap.plugin('AMap.RectangleEditor', () => {
            // 异步加载插件
            if (state.areaLayer) {
                state.areaEditor = new state.AMap.RectangleEditor(map, state.areaLayer);
                state.areaEditor.open();
            }
        });
    };

    // 开始画多边形
    const handlePolygonDraw = () => {
        map.setDefaultCursor('pointer');
        state.mouseTool.polygon({
            strokeColor: '#1791FC',
            strokeOpacity: 1,
            strokeWeight: 2,
            fillColor: '#1791FC',
            fillOpacity: 0.4,
            cursor:'pointer',
            strokeStyle: 'solid'
        });
    };

    // 开始编辑多边形
    const handlePolygonEditor = () => {
        state.AMap.plugin('AMap.PolyEditor', () => {
            // 异步加载插件
            if (state.areaLayer) {
                state.areaEditor = new state.AMap.PolyEditor(map, state.areaLayer);
                state.areaEditor.open();
            }
        });
    };

    // 清除矢量图形
    const handleClear = () => {
        // 清除画区域实例对象
        if(state.areaEditor) {
            state.areaEditor.close();
        }
        // 清除图层
        if(state.areaLayer) {
            map.clearMap();
        }

        state.areaEditor = null;
        state.linePoints = [];
        state.areaLayer = null;
        state.drawState = 0;
        state.drawType = 0;
    };

    // 完成
    const handleEmit = () => {
        // 退出编辑状态
        if(state.areaEditor) {
            state.areaEditor.close();
            state.areaEditor = null;
        }
        state.pointX = -500;
        state.pointY = -500;
        state.drawState = -1;
        getAreaLayerInfo();
    };

    // 关闭弹窗
    const handleClose = () => {
        emits('handleClose');
    };

    // 切换地图
    const changeMap = () => {
        if (state.stateLayer == 0) {
            map.remove([defaultStreet]);
            map.add([satelliteLayer]);
            state.stateLayer = 1;
        } else {
            map.remove([satelliteLayer]);
            map.add([defaultStreet]);
            state.stateLayer = 0;
        }
    };

    // 悬浮提示
    const hoverTxt = computed(() => {
        if (state.drawType === 1) {
            return state.areaLayer ? '点击完成结束编辑圆' : '按住左键并拖拽绘制圆';
        } else if (state.drawType === 2) {
            return state.areaLayer ? '点击完成结束编辑矩形' : '按住左键并拖拽绘制矩形';
        } else if (state.drawType === 3) {
            return state.areaLayer ? '点击完成结束编辑多边形' : '点击地图选择拐点,右键结束绘制多边形';
        } else {
            return ''
        }
    });
</script>

5、实现效果如图

在这里插入图片描述

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

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

相关文章

GNSS 地球自转改正算例分析

文章目录 Part.I IntroductionPart.II 由地球自转引起的误差的概念和改正方法Chap.I 误差概念Chap.II 改正方法 Part.II 算例分析Chap.I 基础数据Chap.II 计算过程 AppendixReference Part.I Introduction 为了更好地理解 地球自转改正&#xff0c;本文将介绍一个算例。 Part.…

手动交互式选点提取三维点云轮廓边界线 附python代码

一种新的三维点云轮廓边界提取方案: 1 手动选择一个边界或者其附近的点 2 自动搜索临近区域,并找到附近的平面和进行平面分割 3 提取平面的交点 4 该交点就是点云的轮廓边界点,把它往两边延展,就是完整的点云轮廓边界 import open3d as o3d import numpy as np import …

Java模块化系统:引领代码革命与性能飞跃

JDK工程结构的问题 在说Java模块化系统之前&#xff0c;先来说说Java9之前的JDK在工程结构上的问题&#xff0c;从JDK本身的问题说起&#xff0c;Java从1996年发布第一版到2017年发布Java9&#xff0c;中间经历了近20年的时间&#xff0c;在这期间发布了无数个大大小小的版本用…

RESTFul风格设计和实战

四、RESTFul风格设计和实战 4.1 RESTFul风格概述 4.1.1 RESTFul风格简介 RESTful&#xff08;Representational State Transfer&#xff09;是一种软件架构风格&#xff0c;用于设计网络应用程序和服务之间的通信。它是一种基于标准 HTTP 方法的简单和轻量级的通信协议&#x…

YAML如何操作Kubernetes核心对象

Pod Kubernetes 最核心对象Pod Pod 是对容器的“打包”&#xff0c;里面的容器&#xff08;多个容器&#xff09;是一个整体&#xff0c;总是能够一起调度、一起运行&#xff0c;绝不会出现分离的情况&#xff0c;而且 Pod 属于 Kubernetes&#xff0c;可以在不触碰下层容器的…

存储或读取时转换JSON数据

一、 数据库类型 二、使用Hutool工具 存储时将数据转换为JSON数据 获取时将JSON数据转换为对象 发现问题&#xff1a; 原本数据对象是Address 和 Firend但是转换完成后数据变成了JSONArray和JSONObject 三、自定义TypeHandler继承Mybatis的BaseTypeHandler处理器 package …

Feign 和 OpenFeign 的区别

Feign 和 OpenFeign 都是用来进行服务间调用的客户端库&#xff0c;它们旨在简化HTTP API客户端的编写过程&#xff0c;使得编写对外部服务的接口就像调用本地方法一样简单。尽管它们有相似之处&#xff0c;但也存在一些关键差异&#xff1a; 归属和演进&#xff1a; Feign 最初…

硬件设计计划与APQP

硬件设计的关键节点: 大的里程碑milestone分为: Kickoff->A Samples->做出第一批B样总成件->B Samples/OTS->C Samples->PPAP->SOP 具体到硬件,A/B/C sample阶段,又可细分为: 关键器件选型&硬件系统方案设计原理图绘制PCB LayoutA_BOM输出PCB制板…

3. 深度学习笔记--优化函数

深度学习——优化器算法Optimizer详解&#xff08;BGD、SGD、MBGD、Momentum、Adagrad、Adadelta、RMSprop、Adam、Nadam、AdaMax、AdamW &#xff09; 0. GD &#xff08;梯度下降&#xff09; Gradient Descent&#xff08;梯度下降&#xff09;是一种迭代优化算法&#xf…

FreeRTOS内存管理(1-20)

FreeRTOS内存管理简介 在使用FreeRTOS创建任务&#xff0c;队列&#xff0c;信号量等对象时&#xff0c;一般都提供两种方法 1&#xff1a;动态创建任务&#xff08;方法&#xff09;自动地从FreeRTOS管理的内存堆中申请创建对象所需要的内存&#xff0c;并且在删除对象后可以…

九州金榜|孩子沉迷于网络:家庭教育的挑战与对策

随着时代的进步&#xff0c;科技的发展&#xff0c;网络现在成为了我们日常生活不可分割的一部分。然而&#xff0c;随着网络的普及也出现了一些列的问题&#xff0c;其中孩子沉迷于网络就是当前家长最为关心的问题&#xff0c;对于这种情况的发生&#xff0c;家庭教育就显得尤…

Linux主机重启后报错:[FAILED] Failed to start Switch Root.

一、问题描述 某次云主机因计费问题&#xff0c;导致批量重启&#xff0c;重启后发现某台云主机竟进入紧急救援模式&#xff08;emergency模式&#xff09;&#xff0c;如下所示&#xff1a; 二、原因及处理 1&#xff09;原因&#xff1a;加载根分区失败&#xff0c;导致无…

Libcity笔记:原子文件

1 介绍 Libcity中的数据以原子文件的形式存在 2 原子文件类别 对于不同的交通预测任务&#xff0c;可能用到不同的原子文件&#xff0c;同一个数据集不一定包含全部六种原子文件 网格数据需要按照先行后列的顺序遍历OD数据需要按照先起点后终点的顺序遍历 2.1 geo 存储地理…

Netty 实现dubbo rpc

一、RPC 的基本介绍 RPC (Remote Procedure Call) 远程过程调用&#xff0c;是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机的子程序&#xff0c;而程序员无需额外的为这个交互编程。也就是说可以达到两个或者多个应用程序部署在不同的服务器上&…

OpenCV 入门(七)—— 身份证识别

OpenCV 入门系列&#xff1a; OpenCV 入门&#xff08;一&#xff09;—— OpenCV 基础 OpenCV 入门&#xff08;二&#xff09;—— 车牌定位 OpenCV 入门&#xff08;三&#xff09;—— 车牌筛选 OpenCV 入门&#xff08;四&#xff09;—— 车牌号识别 OpenCV 入门&#xf…

德国韦纳WENAROLL滚压刀,液压缸,滚光刀,挤压刀,滚轧刀

德国韦纳WENAROLL滚压刀,液压缸&#xff0c;滚光刀,挤压刀&#xff0c;滚轧刀&#xff08;百度一下&#xff0c;西安尚融&#xff09; 德国韦纳&#xff08;WENAROLL&#xff09;的滚压刀、液压缸、滚光刀、挤压刀和滚轧刀在工业领域享有很高的声誉&#xff0c;这些产品因其高…

SM618卡件SM480模块和利时

SM618卡件❗电:183-6998-1851❗SM480模块和利时。自动化程度的提高&#xff0c;I/O点数大幅增 加&#xff0c;传统单一配线的方式已经无法满足发展的需 要SM618卡件SM480模块和利时。&#xff0e;对简单、可靠的配线方式的需求日益强烈&#xff0e; 传统接线 - 以并联方式连 接…

C# WinForm —— 12 ListBox绑定数据

ListBox加载大量数据时&#xff0c;避免窗体闪烁的方法&#xff1a; 在加载语句的前后分别加上 BeginUpdate()方法 和 EndUpdate()方法 指定一个集合为绑定的数据源 1. 首先&#xff0c;右键项目&#xff0c;添加类 2. 在新建的类文件中添加属性值信息 3. 构建初始化的对象…

访问学者在外访学期间,是否可以中途回国?

在全球化的今天&#xff0c;访问学者制度已成为促进国际学术交流与合作的重要桥梁。然而&#xff0c;对于许多国外访问学者来说&#xff0c;一个常见的问题是&#xff1a;在访学期间&#xff0c;我是否可以中途回国&#xff1f;这个问题涉及到多个方面&#xff0c;包括政策法规…

7步教程从零开始搭建跨境电商平台开发

跨境电商平台开发一直是创业者们追逐的热门领域之一。本文将为您提供一个7步教程&#xff0c;帮助您从零开始搭建跨境电商平台&#xff0c;让您在这个充满机遇的领域中抢占先机。 步骤一&#xff1a;市场调研和定位 在开始搭建跨境电商平台之前&#xff0c;第一步是进行充分的…