手摸手系列之SpringBoot+Vue2项目整合高德地图实现车辆实时定位功能

news2024/11/29 22:43:09
前言

最近在做一个物流内陆运输的项目,其中的一个关键功能是根据车辆的GPS数据在页面上实时显示车辆位置信息。由于我们已经获得了第三方提供的GPS数据,所以接下来的任务是将这些数据整合到我们的系统中,并利用高德地图API来展示车辆的实时位置。接下来,来看看怎么样来一步步实现吧。

一、后端工作:将第三方提供的GPS数据进一步整合优化后,再返回给前端
1. 第三方提供的接口文档

image.png
image.png
第三方的返回数据示例:

{
  "status": 1001,
  "result": {
    "firstVcl": {
      "lat": "22088888",
      "lon": "96332278",
      "adr": "山东省济南市历城区中电四齐鲁安替制药临建区,西南方向,159.0米",
      "utc": "1703843972000",
      "spd": "0.0",
      "drc": "278",
      "province": "山东省",
      "city": "济南市",
      "country": "历城区",
      "mil": "488206.2",
      "vno": "鲁AL8560",
      "status": "1001",
      "offlineState": false,
      "offlineTime": "",
      "runDistance": "",
      "remainDistance": "",
      "estimateArriveTime": ""
    },
    "others": []
  }
}
2. 后端主要代码

需要先将第三方提供的SDK包整合进项目里。在resources下新建目录sdk,然后将sdk.jar拷贝进去:
image.png
然后在pom.xml中加入依赖:

<dependency>
  <groupId>com.openapi.sdk</groupId>
  <artifactId>openapi-sdk</artifactId>
  <version>6.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/src/main/resources/sdk/openapi-sdk-6.0.jar</systemPath>
</dependency>

最后重要的一步,在spring-boot-maven-plugin插件设置加上includeSystemScope
image.png

  • includeSystemScope:scope为system的maven默认是不打包进去的,所以导致上面说的,项目打包完成后,对应的lib目录下并没有外部提供的xxx-api-sdk。使用该配置,将指定maven把scope为system的依赖 同样打到jar包中去。

然后就可以直接使用SDK中的postHttps(url, map)等方法了。
下面是主要的Java代码:

/**
 * 厂外物流-在途监控类服务
 *
 * 运输节点服务
 *
 * @param vnos 车牌号_车牌颜色,多
 * 个车辆以英文逗号分
 * 隔(最多 100 台车,
 * 颜色:1 蓝色、2 黄
 * 色、3 黄绿)京 A78601_1,京
 * A78602_2, 京 A78603_3
 * @return 陆运单列表
 */
@ApiOperation(value = "运输节点服务", notes = "运输节点服务")
@RequestMapping(value = "/getDataV2")
public Result<?> getDataV2(@RequestParam("vnos") String vnos,
                           @RequestParam(value = "timeNearby", required = false) String timeNearby) {
    return dispatchTransportService.getDataV2(vnos, timeNearby);
}
/**
 * 厂外物流-在途监控类服务
 * <p>
 * 运输节点服务
 *
 * @param vnos       车牌号_车牌颜色,多
 *                   个车辆以英文逗号分
 *                   隔(最多 100 台车,
 *                   颜色:1 蓝色、2 黄
 *                   色、3 黄绿)京 A78601_1,京
 *                   A78602_2, 京 A78603_3
 * @param timeNearby
 * @return 陆运单列表
 */
@Override
public Result<?> getDataV2(String vnos, String timeNearby) {
    try {
        Map<String, String> map = new HashMap<>();
        map.put("cid", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
        map.put("srt", "yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"); // 私钥用于 SDK 生成签名,不会在请求中传输
        map.put("vnos", vnos);
        if (isNotBlank(timeNearby)) {
            map.put("timeNearby", timeNearby);
        }
        String url = "https://aaaaaaaaa.99999.com/bbbbb/ccccc/getDataV2";
        DataExchangeService des = new DataExchangeService(5000, 8000);
        log.info("请求地址:" + url);
        // 通过 https 方式调用,此方法内部会使用私钥生成签名参数 sign,私钥不会发送
        String res = des.postHttps(url, map);
        log.info("返回:" + res);
        JSONObject returnJson = new JSONObject();
        if (isNotBlank(res)) {
            JSONObject jsonObject = JSONObject.parseObject(res);
            if (jsonObject.containsKey("status")) {
                String code = jsonObject.getString("status");
                if (code.equals("1001")) {
                    String data = jsonObject.getString("result");
                    returnJson = JSONObject.parseObject(data);
                } else {
                    return Result.error("未获取到车辆" + (vnos.substring(0, vnos.indexOf("_"))) + "位置信息!");
                }
            }
        }
        return Result.ok(returnJson);
    } catch (Exception e) {
        log.error("e:" + e.getMessage());
        return Result.error("获取车辆定位出现异常:" + e.getMessage());
    }
}

返回前端的数据格式如下:

{
  "status": 1001,
  "result": {
    "firstVcl": {
      "lat": "2968514",
      "lon": "85692278",
      "adr": "山东省济南市历城区中电四齐鲁安替制药临建区,西南方向,159.0米",
      "utc": "1703843972000",
      "spd": "0.0",
      "drc": "278",
      "province": "山东省",
      "city": "济南市",
      "country": "历城区",
      "mil": "488206.2",
      "vno": "鲁AX9999",
      "status": "1001",
      "offlineState": false,
      "offlineTime": "",
      "runDistance": "",
      "remainDistance": "",
      "estimateArriveTime": ""
    },
    "others": []
  }
}
二、前端工作:接收后端返回数据,整合高德地图展示数据
1. 先去高德开放平台申请key

image.png
image.png
image.png
👉高德的地图JS API 2.0非常详细,只需要看文档就可以完成各种需要的功能,不需要再看其他人的博客了,以免被误导。

2. 新建地图组件MapContainer.vue
<template>
  <div>
    <div id="container"></div>
    <div class="info">
      <h3>
        {{ firstVcl.vno }} <a-switch style='margin-left: 80px' size="small" checked-children="开" un-checked-children="关" default-checked @change='isRealtime'/>实时刷新
          <a-tooltip slot="suffix" title="开启后默认每15秒获取最新位置信息!">
            <a-icon type="question-circle" theme="twoTone"/>
          </a-tooltip>
        </h3><hr>
          <p style='margin-top: 3px'><span style='font-weight: bold'>定位时间:</span>{{ this.formatDate(firstVcl.utc?Number(firstVcl.utc):new Date().getTime(), 'yyyy-MM-dd hh:mm:ss') }}</p>
          <p><span style='font-weight: bold'>最后定位经度:</span>{{ firstVcl.lon.toFixed(6) }}</p>
          <p><span style='font-weight: bold'>最后定位纬度:</span>{{ firstVcl.lat.toFixed(6) }}</p>
          <p><span style='font-weight: bold'>地理位置名称:</span>{{ firstVcl.adr }}</p>
          <p><span style='font-weight: bold'>方向:</span>{{ getDrc() }}</p>
          <p><span style='font-weight: bold'>里程:</span>{{ firstVcl.mil ? firstVcl.mil : 0 }} km</p>
          <p><span style='font-weight: bold'>速度:</span>{{ firstVcl.spd ? firstVcl.spd : 0 }} km/h</p>
          <!--			<p><span style='font-weight: bold'>已行驶距离:</span>{{ firstVcl.runDistance ? firstVcl.runDistance : 0 }} km</p>-->
          <!--			<p><span style='font-weight: bold'>剩余运距:</span>{{ firstVcl.remainDistance ? firstVcl.remainDistance : 0 }} km</p>-->
          <!--			<p><span style='font-weight: bold'>预计到达时间:</span>{{ firstVcl.estimateArriveTime ? this.formatDate(Number(firstVcl.estimateArriveTime), 'yyyy-MM-dd hh:mm:ss') : '' }}</p>-->
          <p><span style='font-weight: bold'>离线状态:</span>{{ getOfflineState() }}</p>
          <p><span style='font-weight: bold'>离线时长:</span>{{ firstVcl.offlineTime }}</p>
        </div>
  </div>
</template>
<script>
  import AMapLoader from "@amap/amap-jsapi-loader";
  import { getAction } from '@/api/manage'
  import BigNumber from 'bignumber.js'
  // 设置安全密钥
  window._AMapSecurityConfig = {
    securityJsCode: 'xxxxxxxxxxxxxxxxxxxx0704b5080',
  }
  export default {
    name: "MapContainer",
    props: {
      carModel: {
        type: Object,
        default: {}
      }
    },
    data() {
      return {
        firstVcl: {},
        map : null,
        marker : null,
        overlays : [],
        myTimer : null,
        placeSearch : null,
        stopTimer: false,
        url: {
          getDataV2: '/business/dispatch/getDataV2'
        }
      }
    },
    mounted() {
      this.initAMap()
      // 通过 $once 来监听定时器,在 beforeDestroy 钩子可以被清除。
      this.$once('hook:beforeDestroy', () => {
        clearInterval(this.myTimer)
      })
    },
    unmounted() {
      this.stopTimer = true
      this.map.destroy()
    },
    beforeDestroy() {
      this.stopTimer = true
      this.map.destroy()
    },
    methods: {
      isRealtime(value) {
        if (value === true) {
          this.stopTimer = false
          this.realtimeRefresh(this.firstVcl.vno)
        } else if (value === false) {
          this.stopTimer = true
        }
      },
      /**
		 * 实时刷新
		 */
      realtimeRefresh(carNum) {
        this.myTimer = setInterval(() => {
          // 停止定时器
          if (this.stopTimer === true) {
            console.log('停止实时刷新!!!')
            clearInterval(this.myTimer)
            return
          }
          const carType = '2' // 默认黄牌车
          let params = {
            vnos: carNum + '_' + carType,
					timeNearby: '30'
				}
				getAction(this.url.getDataV2, params)
					.then((res) => {
						if (res.success) {
							console.log(res.result.records || res.result)
							let data = res.result.records || res.result
							this.firstVcl = data.firstVcl
							if (data.firstVcl && data.firstVcl.lon) {
								this.firstVcl.lon = new BigNumber(data.firstVcl.lon).div(600000.0).toNumber()
							}
							if (data.firstVcl && data.firstVcl.lat) {
								this.firstVcl.lat = new BigNumber(data.firstVcl.lat).div(600000.0).toNumber()
							}
							var position = new AMap.LngLat(this.firstVcl.lon, this.firstVcl.lat) //传入经纬度
							this.map.setCenter(position) //设置地图中心点
							if (this.marker) {
								this.marker.setPosition([this.firstVcl.lon, this.firstVcl.lat]); //更新点标记位置
							}
						} else {
							// 失败
							this.$message.warning(res.message || res)
						}
					})
					.finally(() => {
					})
			},15000)
		},
    initAMap() {
			this.firstVcl = Object.assign({}, this.carModel.firstVcl)
			this.realtimeRefresh(this.firstVcl.vno)
      AMapLoader.load({
        key: "yyyyyyyyyyyyyyyyyybe1b7dae4", // 申请好的Web端开发者Key,首次调用 load 时必填
        version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: ['AMap.ToolBar', 'AMap.Scale', 'AMap.MapType'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      })
        .then((AMap) => {
          this.map = new AMap.Map("container", {
						mapStyle: "amap://styles/fresh", // 设置地图的显示样式
            // 设置地图容器id
            viewMode: "3D", // 是否为3D地图模式
            zoom: 13, // 初始化地图级别
            center: [this.firstVcl.lon, this.firstVcl.lat], // 初始化地图中心点位置
						resizeEnable: true
          });
					this.map.addControl(new AMap.ToolBar()); // 缩略地图控件
					this.map.addControl(new AMap.Scale()); // 比例尺
					this.map.addControl(new AMap.MapType()); // 图层切换

					// 创建一个 Icon
					var startIcon = new AMap.Icon({
						// 图标尺寸
						size: new AMap.Size(32, 32),
						// 图标的取图地址
						image: require("../../../assets/汽车1.png"),
						// 图标所用图片大小
						imageSize: new AMap.Size(32, 32),
						// 图标取图偏移量
						// imageOffset: new AMap.Pixel(-9, -3)
					});

					// 将 Icon 实例添加到 marker 上:
					this.marker = new AMap.Marker({
						position: [this.firstVcl.lon, this.firstVcl.lat], //点标记的位置
						offset: new AMap.Pixel(0, 0), //设置点标记偏移量
						anchor: "bottom-center", //设置锚点方位
						icon: startIcon, //添加 Icon 实例
						zooms: [2, 18], //点标记显示的层级范围,超过范围不显示
					});
					// 设置鼠标划过点标记显示的文字提示
					this.marker.setTitle(this.firstVcl.vno);

					// 设置label标签
					// label默认蓝框白底左上角显示,样式className为:amap-marker-label
					this.marker.setLabel({
						direction:'top',
						offset: new AMap.Pixel(0, 0),  //设置文本标注偏移量
						content: `<div>${this.firstVcl.vno}</div>`, //设置文本标注内容
					});
					// 加入到map对象中绘制
					this.map.add(this.marker);
				})
        .catch((e) => {
          console.log(e);
        });
    },
		/**
		 * 正北,大于 0 且小于 90:东北,
		 * 等于 90:正东,大于 90 且小于
		 * 180:东南,等于 180:正南,大于
		 * 180 且小于 270:西南,
		 *  * 等于 270:正西,大于 270
		 * 且小于等于 359:西北,其他:未
		 * 知
		 * @returns {string}
		 */
		getDrc() {
			if (this.firstVcl.drc) {
				let drc = Number(this.firstVcl.drc);
				if (drc > 0 && drc < 90) {
					return '东北'
				} else if (drc === 90) {
					return '正东'
				} else if (drc > 90 && drc < 180) {
					return '东南'
				} else if (drc === 180) {
					return '正南'
				} else if (drc > 180 && drc < 270) {
					return '西南'
				} else if (drc === 270) {
					return '正西'
				} else if (drc > 270 && drc <= 359) {
					return '西北'
				}
			}
			return '未知'
		},
		getOfflineState() {
			if (this.firstVcl.offlineState) {
				return '离线'
			} else {
				return '在线'
			}
		},
		/**
		 * 时间格式化
		 * @param value
		 * @param fmt
		 * @returns {*}
		 */
		formatDate (value, fmt) {
			let regPos = /^\d+(\.\d+)?$/
			if (regPos.test(value)) {
				//如果是数字
				let getDate = new Date(value)
				let o = {
					'M+': getDate.getMonth() + 1,
					'd+': getDate.getDate(),
					'h+': getDate.getHours(),
					'm+': getDate.getMinutes(),
					's+': getDate.getSeconds(),
					'q+': Math.floor((getDate.getMonth() + 3) / 3),
					'S': getDate.getMilliseconds()
				}
				if (/(y+)/.test(fmt)) {
					fmt = fmt.replace(RegExp.$1, (getDate.getFullYear() + '').substr(4 - RegExp.$1.length))
				}
				for (let k in o) {
					if (new RegExp('(' + k + ')').test(fmt)) {
						fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
					}
				}
				return fmt
			} else {
				//TODO
				value = value.trim()
				return value.substr(0, fmt.length)
			}
		}
	}
};
</script>
<style scoped>
#container {
  width: 100%;
  height: 800px;
}
.info {
	position: absolute;
	width: 300px;
	top: 75px;
	left: 20px;
	z-index: 1000; /* 为确保 info 在地图上方 */
	padding: 10px;
	background-color: rgba(255, 255, 255, 0.9); /* 设置一个半透明的背景色 */
}
.info p {
	margin: 2px;
}
</style>

3. 在父组件VehicleLocationAndTrackingModal中引入地图组件
<template>
	<z-c-modal
		:title="'陆运单 ' + title"
		:width="width"
		:visible="visible"
		@cancel="handleCancel"
		switchFullscreen
		:destroyOnClose="true"
		cancelText="关闭"
	>
		<template slot='footer'>
			<a-button type="primary" @click="handleCancel">关闭</a-button>
		</template>
		<a-card :body-style='{padding: 0}' :bordered='false'>
			<a-tabs v-model='activeKey' default-active-key='1' @change='callbacktab'>
				<a-tab-pane key='1' :forceRender='true' tab='车辆定位'>
					<map-container ref='carLocationRef' :car-model='transport.carModel'/>
				</a-tab-pane>
				<a-tab-pane key='2' :forceRender='true' tab='轨迹回放'>
<!--					<aexg-list ref='aexgList' />-->
				</a-tab-pane>
			</a-tabs>
		</a-card>
	</z-c-modal>
</template>
<script>
import CarLocationMap from '@/views/dispatchManage/component/CarLocationMap.vue'
import ZCModal from '@/components/jeecg/ZCModal/index.vue'
import MapContainer from '@/views/dispatchManage/component/MapContainer.vue'
import BigNumber from 'bignumber.js'
export default {
	name: 'VehicleLocationAndTrackingModal',
	components: { ZCModal, CarLocationMap, MapContainer },
	data() {
		return {
			activeKey: '1',
			transport: {},
			title: '',
			width: 1180,
			visible: false,
			confirmLoading: false,
			disableSubmit: false
		}
	},
	methods: {
		add(record) {
			this.transport = Object.assign({}, record)
			if (this.transport.carModel) {
				let lon = 116.397428
				if (this.transport.carModel.firstVcl && this.transport.carModel.firstVcl.lon) {
					lon = new BigNumber(this.transport.carModel.firstVcl.lon).div(600000.0).toNumber();
				}
				this.transport.carModel.firstVcl.lon = lon
				let lat = 39.90923
				if (this.transport.carModel.firstVcl && this.transport.carModel.firstVcl.lat) {
					lat = new BigNumber(this.transport.carModel.firstVcl.lat).div(600000.0).toNumber();
				}
				this.transport.carModel.firstVcl.lat = lat
			}
			this.visible = true
		},
		callbacktab(key) {
			console.log(key)
		},
		close() {
			this.visible = false
		},
		handleCancel () {
			this.close()
		}
	}
}
</script>

<style scoped lang='less'>
@import '~@assets/less/common.less';
/deep/ .ant-modal-body {
	padding:0 12px !important;
}
/deep/ .ant-tabs-nav-wrap {
	margin-top: -5px;
}
</style>
三、最终的展示效果:

image.png

总结

Vue整合高德地图总的来说还是非常简单的,下一篇我们继续来介绍如何实现展示车辆的某段时间的运行轨迹。

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

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

相关文章

机器学习分类

1. 监督学习 监督学习指的是人们给机器一大堆标记好的数据&#xff0c;比如&#xff1a; 一大堆照片&#xff0c;标记出哪些是猫的照片&#xff0c;哪些是狗的照片 让机器自己学习归纳出算法或模型 使用该算法或模型判断出其他没有标记的照片是否是猫或狗 上述流程如下图所…

解决windows系统找不到msvcr100.dll问题,vcomp100.dll缺失的5个解决方法

在日常使用计算机的过程中&#xff0c;我们可能会遇到一些错误提示&#xff0c;其中之一就是“找不到vcomp100.dll”的错误。那么&#xff0c;vcomp100.dll究竟是什么文件&#xff1f;为什么会出现丢失的情况&#xff1f;本文将为您详细解析vcomp100.dll的作用、丢失原因以及提…

C++的面向对象学习(9):文件操作

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、类的封装的多文件实现回顾二、文件操作1.对文件进行操作需要头文件<fstream>2.操作文件的三大类方法&#xff1a;读、写、读写 三、实现文本文件的读、写…

【STM32F103】SysTick系统定时器延时函数

SysTick SysTick是Cortex-M3内核中的一个外设&#xff0c;内嵌在NVIC中&#xff0c;叫系统定时器。 当处理器在调试期间被喊停时&#xff0c;SysTick也将暂停运作。 一共有四个寄存器&#xff0c;不过我们通常用前三个&#xff0c;不需要校准。下图出自《STM32F10xxx Cortex…

小兔鲜儿 uniapp - SKU 模块

目录 存货单位&#xff08;SKU&#xff09;​ 插件市场​ 下载 SKU 插件​ 使用 SKU 插件​ 插件类型问题​ 核心业务​ 渲染商品规格​ 打开弹窗交互​ 渲染被选中的值​ 存货单位&#xff08;SKU&#xff09;​ SKU 概念 存货单位&#xff08;Stock Keeping Unit&a…

【教学类-43-11】 20231231 3*3宫格数独提取单元格坐标数字的通用模板(做成2*2=4套、3*2=6套)

背景需求&#xff1a; 1、以前做单元格填充&#xff0c;都是制作N个分开的单元格 &#xff08;表格8&#xff09; 2、这次做五宫格数独的Word模板&#xff0c;我图方便&#xff0c;就只用了一个大表格&#xff0c;第六行第六列隐藏框线&#xff0c;看上去就是分开的&#xff…

Linux | 解决问题Ubuntu重启无法进入系统以及网络无法连接【图文详解】

Ubuntu18.04重启无法进入系统&#xff0c;重开后如图 一直在加载系统内核4.15.0-213-generic,无法加载 错误原因 原本的系统是Ubuntu16.04,使用命令升级到Ubuntu18.04版本&#xff0c;升级重启后&#xff0c;远程无法连接&#xff01; 错误解决 第一步&#xff1a;进入GRUB…

ZigBee案例笔记 - 无线点灯

文章目录 无线点灯实验概述工程关键字工程文件夹介绍Basic RF软件设计框图简单说明工程操作Basic RF启动流程Basic RF发送流程Basic RF接收流程 无线点灯案例无线点灯现象 无线点灯实验概述 ZigBee无线点灯实验&#xff08;即Basic RF工程&#xff09;&#xff0c;由TI公司提供…

neovim调试linux内核过程中索引不到对应头文件问题

大家好&#xff0c;我叫徐锦桐&#xff0c;个人博客地址为www.xujintong.com&#xff0c;github地址为https://github.com/jintongxu。平时记录一下学习计算机过程中获取的知识&#xff0c;还有日常折腾的经验&#xff0c;欢迎大家访问。 一、环境 neovim–0.9.4 mason的clang…

中小微医院机构云服务(云HIS)平台源码

云HIS&#xff08;Cloud-Based Healthcare Information System&#xff09;重新定义了HIS&#xff0c;目标是为中小型医疗卫生机构提供优质经济的医疗卫生信息化产品及服务&#xff1b;是以健康档案为主线、以电子病历为核心、以云计算技术为基础的医疗卫生系统。云HIS作为基于…

GoogleNetv1:Going deeper with convolutions更深的卷积神经网络

文章目录 GoogleNetv1全文翻译论文结构摘要1 引言2 相关工作3 动机和高层考虑稀疏矩阵 4 结构细节引入1x1卷积核可以减少通道数 5 GoogleNet6 训练方法7 ILSVRC 2014 分类挑战赛设置和结果8 ILSVRC 2014检测挑战赛设置和结果9 总结 论文研究背景、成果及意义论文图表 GoogleNet…

【小沐学Python】Python实现免费天气预报获取(OpenWeatherMap)

文章目录 1、简介1.1 工具简介1.2 费用1.3 注册1.4 申请key 2、接口说明2.1 One Call 3.02.2 Current Weather and Forecasts collection2.2.1 API 调用2.2.2 API 参数 2.3 Historical Weather collection2.4 Weather Maps collection2.5 Other weather APIs 3、接口测试3.1 例…

无监督学习(下)

1.高斯混合模型(GMM) (1)简单概念 高斯混合模型是一种概率模型&#xff0c;它假定实例是由多个参数未知的高斯分布的混合生成的。从单个高斯分布生成的所有实例都形成一个集群&#xff0c;通常看起来像一个椭圆。每个集群都可以由不同的椭圆形状&#xff0c;大小&#xff0c;密…

【C# 技术】 C# 常用排序方式——自定义数据排序

C# 常用排序方式——自定义数据排序 前言 在最近的项目中经常会对C#中的数据进行排序&#xff0c;对于基本数据类型&#xff0c;其排序方式比较简单&#xff0c;只需要调用内置算法即可实现&#xff0c;但对于自定义数据类型以及自定义排序规则的情况实现起来就比较麻烦&…

美团到店终端从标准化到数字化的演进之路

总第580篇 | 2023年第032篇 本文整理自美团技术沙龙第76期《大前端研发协同效能提升与实践》。前端团队在产研多角色协同形式上存在不同阶段&#xff0c;而大前端多技术栈在各阶段都有其独特的实践&#xff0c;同时又有类似的演进路线。本文从到店终端团队移动端和前端技术栈持…

最详细GIT学习笔记

1. Git简介 1.1. Git介绍 Git(读音为/gɪt/) 是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理。 Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。 1.2. 主流的版本控制器 Git(分布式…

金融帝国实验室(Capitalism Lab)官方正版游戏『2024新年特卖优惠』

「金融帝国实验室」&#xff08;Capitalism Lab&#xff09;Enlight 官方正版游戏「2024新年特卖」 ■优惠时限&#xff1a;2024.01.01&#xff5e;01.31 ■游戏开发商&#xff1a;Enlight Software Ltd. 请您认准以下官方正版游戏购买链接&#xff1a;支持“支付宝&am…

【数据结构-单链表】(C语言版本)

今天分享的是数据结构有关单链表的操作和实践&#xff08;图解法&#xff0c;图变化更利于理解&#xff09; 记录宗旨&#x1f4dd;&#xff1a; 眼&#xff08;脑&#xff09;过千遍&#xff0c;不如手过一遍。 我们都知道单链表是一种常见的链表数据结构&#xff0c;由一系列…

【Delphi】IOS上架踩坑记 - 2024年第一天

目录 一、前言&#xff1a; 二、IOS程序上架网址 三、踩坑记 1. 关于版本中的 CFBundleIdentifier 参数&#xff08;Transporter 提示&#xff09; 2. IOS APP 程序图标要求&#xff08;Transporter 提示&#xff09; 3. 关于版本中的 CFBundleShortVersionString 参数&a…

小波理论与应用:理解小波

1 简介 来自源的信号通常处于时域。例如正弦信号、生物医学信号等。任何时域信号都可以使用数学变换进行处理或变换到频域&#xff08;谱域&#xff09;。傅里叶变换是一种流行或著名的变换&#xff0c;它将时域信号转换为频域信号&#xff0c;而不失一般性。 在绘制时域信号…