Vue使用百度地图以及实现轨迹回放 附完整代码

百度地图开放平台 https://lbs.baidu.com/index.php?title=%E9%A6%96%E9%A1%B5
javaScript API https://lbs.baidu.com/index.php?title=jspopularGL
百度地图实例 https://lbsyun.baidu.com/index.php?title=open/jsdemo
Vue Baidu Map文档 https://dafrok.github.io/vue-baidu-map/#/zh/index

效果图:

image.png

支持放大缩小 调动播放进度 搜索轨迹时段 调整播放速度等。

image.png

步骤1:准备工作

1.1 获取百度地图API密钥

首先,你需要在百度地图开放平台注册一个开发者账号,并创建一个应用,以获取API密钥。API密钥是用于标识你的应用身份的重要凭证。
1701942229175.png
1701942117490.png

步骤2:引入百度地图JavaScript API 在index.html添加以下代码

1.3 引入百度地图API和样式表

在项目的public/index.html文件中引入百度地图API和样式表:

<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=换成自己的API秘钥"></script>
  <script type="text/javascript" src="https://api.map.baidu.com/library/TextIconOverlay/1.2/src/TextIconOverlay_min.js"></script>
  <script type="text/javascript" src="https://api.map.baidu.com/library/MarkerClusterer/1.2/src/MarkerClusterer_min.js"></script>

常用API表格:

API描述使用示例
BMap.Map(container [, opts])创建地图实例new BMap.Map(“map-container”);
BMap.Point(lng, lat)创建地理坐标点实例new BMap.Point(114.161291, 22.644619);
BMap.Marker(point [, opts])创建标记点实例new BMap.Marker(point);
BMap.Icon(url, size [, opts])创建标记点图标实例new BMap.Icon(“marker.png”, new BMap.Size(30, 30));
BMap.Polyline(points [, opts])创建折线实例new BMap.Polyline([point1, point2]);
BMap.InfoWindow(content [, opts])创建信息窗口实例new BMap.InfoWindow(“内容”);
BMap.NavigationControl(opts)创建地图缩放控件实例new BMap.NavigationControl();
BMapLib.MarkerClusterer(map, opts)创建点聚合实例new BMapLib.MarkerClusterer(map, { markers: markers });
map.centerAndZoom(center, zoom)设置地图中心点和缩放级别map.centerAndZoom(point, 15);
map.addOverlay(overlay)添加覆盖物到地图map.addOverlay(marker);
map.clearOverlays()清除地图上的所有覆盖物map.clearOverlays();
map.enableScrollWheelZoom()启用鼠标滚轮缩放map.enableScrollWheelZoom();
map.getDistance(point1, point2)计算两点间的直线距离map.getDistance(point1, point2);
marker.addEventListener(type, handler)为标记点添加事件监听器marker.addEventListener(“click”, function() { console.log(“点击标记点”); });
polyline.getPath()获取折线的路径polyline.getPath();
InfoWindow.setContent(content)设置信息窗口的内容infoWindow.setContent(“新内容”);

注意:

  • opts 为选项参数,具体可参考官方文档。
  • 示例中的 point1point2 等是 BMap.Point 的实例。
  • 在示例中可能使用了一些虚拟的数据,具体情况根据项目实际需求来设置。

以上是一些基础的API,百度地图提供了丰富的功能,可以根据实际需求查阅百度地图JavaScript API官方文档获取更多详细信息。

步骤3:编写

父组件:BaiduMap.vue

模板部分:
<div ref="map" class="map-container"></div>:地图容器。
<a-modal>:断油电操作的模态框,包括确认按钮和输入备注的文本框。
<a-modal>:恢复油电操作的模态框,同样包括确认按钮和输入备注的文本框。
<a-modal>:轨迹回放的模态框,包含了子组件 <run-map> 来展示实际的轨迹。
数据:
map:百度地图实例。
markers:存储标记的数组。
infoWindows:存储信息窗口的数组。
markerCluster:MarkerClusterer 实例,用于标记点聚合。
devices:设备信息数据。
modalBreak和modalRestore:控制断油电和恢复油电的模态框显示。
modaldrivingTrajectory:控制轨迹回放的模态框显示。
url:包含一些后端接口的URL。
deviceNum、optRemark、numberplate:一些操作所需的参数。
方法:
initMap():初始化地图,设置中心点和缩放级别,添加控件,并加载地图标点数据。
loadRandomDevices():加载地图标点数据,清除之前的标记、信息窗口和点聚合,添加新的标记、信息窗口和点聚合。
createPopupContent(point):根据设备信息创建信息窗口内容。
handleBreakOk()和handleRestoreOk():处理断油电和恢复油电的确认事件。
cancellation():关闭轨迹回放的模态框。
<template>
  <div class="parent-container">
    <div ref="map" class="map-container"></div>
    <!-- <button @click="loadRandomDevices">加载随机设备</button> -->

    <a-modal v-model="modalBreak" title="断油电" @ok="handleBreakOk">

      <div style="font-size: 16px; font-weight: bolder;"><img src="../../assets/jingao.png" width="40px"
          height="40px"></img>您确定要下发<span style="font-size: 18px; color: red;"> 断油电</span> 指令吗?</div>
      <!-- <a-radio-group v-model="triggerType" style="margin-top: 30px;"> -->
      <!-- <a-radio :value="合同未交款断油电">合同未交款断油电</a-radio>
        <a-radio :value="违竟断油电">违竟断油电</a-radio>
        <a-radio :value="其他">其他:</a-radio> -->
      <!-- </a-radio-group> -->
      <a-input v-model="optRemark" placeholder="请输入备注" style="margin-top: 30px;">
      </a-input>
    </a-modal>
    <a-modal v-model="modalRestore" title="恢复油电" @ok="handleRestoreOk">

      <div style="font-size: 16px; font-weight: bolder;"><img src="../../assets/jingao.png" width="40px"
          height="40px"></img>您确定要执行<span style="font-size: 18px; color: red;"> 恢复油电</span> 指令吗?</div>
      <a-input v-model="optRemark" placeholder="请输入备注" style="margin-top: 30px;">
      </a-input>
    </a-modal>
    
    
    <a-modal   width="100%" height="100%" v-model="modaldrivingTrajectory" title="轨迹回放" >
        <run-map :deviceNum="deviceNum"></run-map>
      <template slot="footer">
        <a-button @click="cancellation">关闭</a-button>
       
      </template>
    </a-modal>
   
  
  </div>
</template>

<script>
  import Vue from 'vue'
  import {
    getAction,
    httpAction,
    postAction
  } from '../../api/manage'
  
       import RunMap from './GjMap.vue'

  export default {
    props: {
      gpsInfo: {
        type: Object,
      }
    },
    components: {
      RunMap
    },
    data() {
      return {
        map: null,
        markers: [], // 存储标记
        infoWindows: [], // 存储信息窗口
        markerCluster: null, // MarkerClusterer 实例
        devices: [],
        modalBreak: false, // 模态框可见状态
        modaldrivingTrajectory:false,//轨迹回放
        modalRestore: false,
        url: {
          //断油电 恢复油电
          executeCmd: '/jeecg-customers/car/carCheXiaoGpsController/executeCmd',
          //获取轨迹url
          trajectory: '/jeecg-customers/ car/carCheXiaoGpsController/trajectory',
         
        },
        //设备编号
        deviceNum: null,
        optRemark: null,
        numberplate: null,
      };
    },
    mounted() {
      this.initMap();
    },
    methods: {
      initMap() {
        // 创建地图实例
        this.map = new BMap.Map(this.$refs.map);

        // 设置地图中心点和缩放级别
        const point = new BMap.Point(114.16129136801659, 22.64461948509109);
        this.map.centerAndZoom(point, 10);

        // 添加地图缩放控件
        const navigationControl = new BMap.NavigationControl();
        this.map.addControl(navigationControl);

        // 启用鼠标滚轮缩放
        this.map.enableScrollWheelZoom();

        //加载地图点数据
        this.loadRandomDevices();
      },
      createPopupContent(point) {
        // 创建信息窗口内容,包括设备属性
        return `
       <div class="popup-container">
         <div class="popup-header">设备信息</div>
         <div class="popup-content">
         <p>设备号:<spen id="deviceNum"> ${point.deviceNum}</spen></p>
          <p>车牌号码:<spen id="licenseName"> ${point.licenseName}</spen></p>
          <p>最近定位位置: ${point.address}</p>
          
          <p>经度: ${point.lng}</p>
          <p>纬度: ${point.lat}</p>
           <p>设备状态: ${point.deviceState}</p>
         <span id="handleBreak" style="color: red; font-size: 15px;" οnmοuseοver="this.style.backgroundColor='lightgray'" οnmοuseοut="this.style.backgroundColor='initial'">断油电</span>
         <span id="handleRestore" style="color: blue; font-size: 15px;" οnmοuseοver="this.style.backgroundColor='lightgray'" οnmοuseοut="this.style.backgroundColor='initial'">恢复油电</span>
         <span id="drivingTrajectory" style="color: green; font-size: 15px;" οnmοuseοver="this.style.backgroundColor='lightgray'" οnmοuseοut="this.style.backgroundColor='initial'">行驶轨迹</span>

         </div>
       </div>
      `;
      },
      /**
       * 加载地图标点数据
       */
      loadRandomDevices() {
        // 清除之前的标记、信息窗口和点聚合
        this.map.clearOverlays();
        this.markers = [];
        this.infoWindows = [];
        if (this.markerCluster) {
          this.markerCluster.clearMarkers();
        }
        // 定义自定义图标的样式
        // const myIcon = new BMap.Icon(require("@/assets/car.png"), new BMap.Size(32, 32), {
        //   anchor: new BMap.Size(16, 32), // 图标的定位点相对于图标左上角的偏移
        //   imageSize: new BMap.Size(32, 32) // 图标的大小
        // });
        // 根据 gpsInfo 的经纬度设置地图中心点
        const gpsInfo = this.gpsInfo;
        const centerPoint = new BMap.Point(gpsInfo.lng, gpsInfo.lat);
        this.map.setCenter(centerPoint);
        // 设置缩放级别
        this.map.setZoom(18);

        const point = new BMap.Point(gpsInfo.lng, gpsInfo.lat);
        // const marker = new BMap.Marker(point, {
        //   icon: myIcon
        // });

        const marker = new BMap.Marker(point);
        //创建信息窗口
        const infoWindow = new BMap.InfoWindow(this.createPopupContent(gpsInfo));
        //添加单击事件侦听器以打开信息窗口

        marker.addEventListener("click", () => {
          this.map.openInfoWindow(infoWindow, point);

          const deviceIdElement = document.getElementById("deviceNum");
          const deviceNum = deviceIdElement.textContent.trim();

          const licenseNameElement = document.getElementById("licenseName");
          const licenseName = licenseNameElement.textContent.trim();

          this.deviceNum = deviceNum;
          this.numberplate = licenseName

          // 获取按钮元素并添加点击事件
          const handleBreak = document.getElementById("handleBreak");
          handleBreak.addEventListener("click", () => {
            this.modalBreak = true; // 打开模态框
            // console.log("执行断油电操作");
            console.log("设备编号:", deviceNum);
          });

          const handleRestore = document.getElementById("handleRestore");
          handleRestore.addEventListener("click", () => {
            console.log("执行恢复油电操作");
            this.modalRestore=true;
          })
          
          const drivingTrajectory = document.getElementById("drivingTrajectory");
          drivingTrajectory.addEventListener("click", () => {
            console.log("行驶轨迹执行事件");
              this.modaldrivingTrajectory=true
          })
        });
        // 将标记和信息窗口添加到各自的数组中
        this.markers.push(marker);
        this.infoWindows.push(infoWindow);

        // 添加标记到地图
        this.map.addOverlay(marker);

        // });
        // 点聚合
        this.markerCluster = new BMapLib.MarkerClusterer(this.map, {
          markers: this.markers,
          gridSize: 80, // 根据需要进行调整
          maxZoom: 18,
        });
      },
      cancellation(){
        this.modaldrivingTrajectory=false
        
      },
      /**
       * 确定断油电事件
       */
      handleBreakOk() {
        if (this.optRemark == null) {
          this.$message.info("备注不能为空")
          return
        }
        httpAction(this.url.executeCmd, {
          "deviceNum": this.deviceNum,
          "switchKey": "14",
          "remark": this.optRemark,
          "numberplate": this.numberplate
        }, 'post').then((res) => {
          if (res) {
            console.log(res)
            this.$message.info(res.result)
          }
        })
        this.modalBreak = false; // 关闭模态框
      },
      /**
       * 确定恢复油电事件
       */
      handleRestoreOk() {
        if (this.optRemark == null) {
          this.$message.info("备注不能为空")
          return
        }
        httpAction(this.url.executeCmd, {
          "deviceNum": this.deviceNum,
          "switchKey": "15",
          "remark": this.optRemark,
          "numberplate": this.numberplate,
        }, 'post').then((res) => {
          if (res) {
            console.log(res)
            this.$message.info(res.result)
          }
        })
        this.modalRestore = false; // 关闭模态框
      },
    },
  };
</script>

<style scoped>
  .parent-container {
    width: 100%;
    height: 800px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }

  .map-container {
    width: 100%;
    height: 100%;
  }

  button {
    margin-top: 10px;
  }
</style>

轨迹回放组件:RunMap.vue

模板部分:
<div ref="mapContainer" style="width: 100%; height: 100vh;"></div>:地图容器。
控制面板:包含轨迹时段选择、搜索、播放、暂停、进度调节等功能。
数据:
dateData:轨迹时段的日期数据。
startDate和endDate:选择的开始和结束日期时间。
map:百度地图实例。
pathData:轨迹点的数据。
marker:地图上的标记点。
currentIndex:当前轨迹点索引。
speed:轨迹播放速度。
isPlaying:是否正在播放。
progressPercent:轨迹播放进度百分比。
url:包含后端接口的URL。
totalPoints:轨迹点总数。
方法:
handleDateFilterChange():处理日期范围变化。
searchData():执行搜索轨迹数据的操作。
decreaseProgress()和increaseProgress():调整轨迹播放进度。
updateMarkerPosition():更新标记的位置。
pauseAnimation()和startAnimation():暂停和播放轨迹动画。
generatePathData():生成轨迹点数据。
initMap():初始化地图,添加标记、标点、路径等,并开始动画。
animateMarker():播放轨迹动画的主要逻辑。
calculateZoomLevel():根据距离计算新的缩放级别。
clearMap()和clearMapAndSearch():清除地图上的标记和地图实例。
<template>
  <div>
    <div ref="mapContainer" style="width: 100%; height: 100vh;"></div>

    <!-- 包含轨迹时段和控制按钮的浮动层 -->
    <div class="control-panel">
      轨迹时段: <a-range-picker :value="dateData" @change="handleDateFilterChange" :show-time="true"
        :disabledDate="disabledDate">
      </a-range-picker>

      <!-- 搜索按钮 -->
      <a-button @click="clearMapAndSearch">搜索</a-button>

      <a-button @click="startAnimation">播放</a-button>

      <a-button @click="pauseAnimation">暂停</a-button>

      <a-button @click="decreaseProgress" style="margin-left: 20px;">-</a-button>
      <a-button @click="increaseProgress">+</a-button>

      <a-row>
        <a-col :span="12">
          播放速度:
          <a-radio-group v-model="speed">
            <a-radio :value="100">慢速</a-radio>
            <a-radio :value="500">正常</a-radio>
            <a-radio :value="1000">快速</a-radio>
            <a-radio :value="1500">最快速</a-radio>
          </a-radio-group>
        </a-col>
      </a-row>

      <a-slider v-model="progressPercent" :min="0" :max="100" />
    </div>
  </div>
</template>

<script>
  import Vue from 'vue';
  import {
    getAction,
    httpAction,
    postAction
  } from '../../api/manage';
  import moment from 'dayjs'


  export default {
    props: {
      deviceNum: {
        type: String, // 参数的数据类型
        required: true // 参数是否必需
      },

    },
    watch: {
      progressPercent(newProgress) {
        // 在进度变化时更新标记的位置
        this.updateMarkerPosition();
      },
    },

    data() {

      return {
        dateData: [],

        startDate: null, // 开始日期时间
        endDate: null, // 结束日期时间

        map: null,
        pathData: [],
        marker: null,
        currentIndex: 0,
        speed: 100,

        //是否播放
        isPlaying: false,
        progressPercent: 0,
        url: {
          trajectory: '/jeecg-customers/car/carCheXiaoGpsController/trajectory',
        },
        totalPoints: 0,
      };
    },
    mounted() {



      const startDate = moment().subtract(5, 'hours').format('YYYY-MM-DD HH:mm:ss');
      console.log(startDate, '开始时间');

      const endDate = moment().format('YYYY-MM-DD HH:mm:ss');
      console.log(endDate, '结束时间');


      this.dateData = [startDate, endDate]
      this.startDate = startDate
      this.endDate = endDate

      this.searchData();
    },
    methods: {
      disabledDate(current) {
        // 禁用日期的函数
        if (!this.startDate || !this.endDate) {
          // 如果没有选择日期范围,不禁用任何日期
          return false;
        }

        const maxDate = moment(this.startDate).add(3, 'days'); // 允许选择日期范围的最大结束日期

        return current && (current < this.startDate || current > maxDate);
      },

      handleDateFilterChange(dates, dateString) {
        this.dateData = dates;
        this.startDate = dateString[0]
        this.endDate = dateString[1]
        console.log(this.startDate, this.endDate)
      },
      searchData() {
        // 获取开始日期时间和结束日期时间
        if (!this.startDate || !this.endDate) {
          // 显示错误消息或进行其他处理
          this.$message.warning('请选择时间');
        }

        this.generatePathData().then((res) => {
          if (res) {
            this.initMap();
          }
        });

      },

      decreaseProgress() {
        if (this.progressPercent > 0) {
          this.progressPercent -= 1;
          this.updateMarkerPosition();
        }
      },

      increaseProgress() {
        if (this.progressPercent < 100) {
          this.progressPercent += 1;
          this.updateMarkerPosition();
        }
      },
      updateMarkerPosition() {
        const newIndex = Math.round((this.progressPercent / 100) * (this.totalPoints - 1));
        if (newIndex !== this.currentIndex) {
          this.currentIndex = newIndex;
          const point = this.pathData[newIndex];
          const position = new BMap.Point(point.lng, point.lat);
          this.marker.setPosition(position);
          this.map.panTo(position);
        }
      },

      pauseAnimation() {
        this.isPlaying = false;
      },
      startAnimation() {
        this.isPlaying = true;
        this.animateMarker();
      },
      generatePathData() {
        console.log(this.startDate)
        console.log(this.endDate)
        return new Promise((resolve) => {
          getAction(this.url.trajectory, {
            // deviceNum: "10213134933",
            deviceNum: this.deviceNum,
            baseStateLBS: "1",
            startTime: this.startDate,
            endTime: this.endDate,
            stopPoint: "0",
            stopPointTime: "10",
          }).then((res) => {
            resolve(res);
            this.pathData = res.result;
            this.totalPoints = this.pathData.length; // Set totalPoints
          });
        });
      },
      initMap() {
        this.map = new BMap.Map(this.$refs.mapContainer);

        const firstPoint = this.pathData[0];

        // 添加缩放控件        
        this.map.addControl(new BMap.NavigationControl());
        this.map.centerAndZoom(new BMap.Point(firstPoint.lng, firstPoint.lat), 15);

        // 启用鼠标滚轮缩放
        this.map.enableScrollWheelZoom();

        // 遍历pathData添加图标覆盖物
        for (let i = 0; i < this.pathData.length; i++) {
          const point = this.pathData[i];
          const myIcon = new BMap.Icon(require("@/assets/stop.png"), new BMap.Size(20, 20), {
            // anchor: new BMap.Size(25, 25), // 图标的定位点相对于图标左上角的偏移
            imageSize: new BMap.Size(20, 20) // 图标的大小
          });
          const marker = new BMap.Marker(new BMap.Point(point.lng, point.lat), {
            icon: myIcon,
          });

          // 根据sp的值判断是否添加覆盖物
          if (point.sp === "0.0") {
            this.map.addOverlay(marker);
          }
        }

        const myIcon = new BMap.Icon(require("@/assets/carrun.png"), new BMap.Size(50, 50), {
          anchor: new BMap.Size(25, 25), // 图标的定位点相对于图标左上角的偏移
          imageSize: new BMap.Size(50, 50) // 图标的大小
        });

        // const myIcon = new BMap.Icon("https://webapi.amap.com/images/car.png", new BMap.Size(60, 30), {
        //   // anchor: new BMap.Size(25, 25), // 图标的定位点相对于图标左上角的偏移
        //   imageSize: new BMap.Size(60, 30) // 图标的大小
        // });

        this.marker = new BMap.Marker(new BMap.Point(firstPoint.lng, firstPoint.lat), {
          icon: myIcon

        });

        this.map.addOverlay(this.marker);

        const polyline = new BMap.Polyline(
          this.pathData.map((point) => new BMap.Point(point.lng, point.lat)), {
            enableEditing: false,
            enableClicking: true,
            strokeWeight: '8',
            strokeOpacity: 0.8,
            strokeColor: "#18a45b",
          }
        );
        this.map.addOverlay(polyline);

        // 开始动画
        this.animateMarker();
      },
      animateMarker() {
        if (this.currentIndex < this.totalPoints - 1 && this.isPlaying) {
          const currentPoint = this.pathData[this.currentIndex];
          const nextPoint = this.pathData[this.currentIndex + 1];
          const startPosition = new BMap.Point(currentPoint.lng, currentPoint.lat);
          const endPosition = new BMap.Point(nextPoint.lng, nextPoint.lat);

          const distance = this.map.getDistance(startPosition, endPosition);

          // 基于速度和两个点之间的距离来计算时长
          const duration = (distance / this.speed) * 1000;

          const angle = this.calculateAngle(startPosition, endPosition);

          this.marker.setRotation(angle);

          // 调整地图的缩放级别以使标点可见
          // const newZoomLevel = this.calculateZoomLevel(distance); // 自定义函数来计算缩放级别
          // this.map.centerAndZoom(endPosition, newZoomLevel);

          this.progressPercent = Math.round((this.currentIndex / (this.totalPoints - 1)) * 100);

          if (this.isPlaying) {
            setTimeout(() => {
              this.marker.setPosition(endPosition);
              this.currentIndex++;
              requestAnimationFrame(this.animateMarker);
            }, duration);
          }
        }
      },

      calculateZoomLevel(distance) {
        // 根据距离或其他条件来计算新的缩放级别
        if (distance < 1000) {
          return 19;
        } else {
          return 14;
        }
      },

      clearMap() {
        if (this.map) {
          this.map.clearOverlays(); // 清除地图上的所有标记点
          this.map = null; // 销毁地图实例
        }
      },

      clearMapAndSearch() {
        // 清除地图上的标点和地图实例
        this.clearMap();

        // 执行搜索并加载标点的逻辑
        this.searchData();
      },


      /**根据点位旋转角度
       * @param {Object} point1
       * @param {Object} point2
       */
      calculateAngle(point1, point2) {
        // 计算两点之间的方向(角度)
        const lat1 = point1.lat * (Math.PI / 180);
        const lng1 = point1.lng * (Math.PI / 180);
        const lat2 = point2.lat * (Math.PI / 180);
        const lng2 = point2.lng * (Math.PI / 180);

        const y = Math.sin(lng2 - lng1) * Math.cos(lat2);
        const x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lng2 - lng1);
        let angle = Math.atan2(y, x);

        angle = (angle * 180) / Math.PI;

        // 调整角度以匹配图标朝向
        angle -= 90;

        return angle;
      }
    },
  };
</script>

<style>
  .control-panel {
    position: absolute;
    top: 10px;
    /* 调整 bottom 属性来控制浮动层距离底部的距离 */
    left: 10px;
    /* 调整 left 属性来控制浮动层距离左侧的距离 */
    background-color: white;
    padding: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
  }
</style>

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

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

相关文章

【环境搭建】ubuntu22安装ros2

基于某种特殊需求&#xff0c;从Ubuntu16到22目前都尝试过安装ros、ros2 参考1&#xff1a;http://t.csdnimg.cn/DzvSe 参考2&#xff1a;http://t.csdnimg.cn/sOzr1 1.设置locale sudo apt update && sudo apt install locales sudo locale-gen en_US en_US.UTF-8 s…

基于ssm vue协同过滤算法的图书推荐系统源码和论文

基于ssm vue协同过滤算法的图书推荐系统源码和论文742 idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 环境&#xff1a; jdk8 tomcat8.5 开发技术 ssm 摘 要 “互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多行业…

[原创][6]探究C#多线程开发细节-“ConcurrentDictionary<T,T>解决多线程的无顺序性的问题“

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…

Matlab 点云曲线探测(算法不稳定,仅用于学习)

文章目录 一、简介二、实现代码三、实现效果参考文献一、简介 这是一个很有趣的曲线探测的方法,不过我没有复现出论文中那样的效果,可能是理解有误,但这个算法仍然是很有意思,故这里也对其进行记录。 按照论文中的思路,首先我们需要通过一种线性强度图来计算确定每个点的法…

学好操作系统需要的前置知识

1. 态度&#xff1a;不要等一切都准备好了再前行 如果把一切你可能会说&#xff0c;没有这些基础知识&#xff0c;我每看一篇文章&#xff0c;知识就铺天盖地席卷过来&#xff0c;仿佛每一个知识点都准确地打在了自己的盲点上&#xff0c;这该怎么办呢&#xff1f; 我非常能理…

一对多群聊

服务端 import java.io.*; import java.net.*; import java.util.ArrayList; public class Server{public static ServerSocket server_socket;public static ArrayList<Socket> socketListnew ArrayList<Socket>(); public static void main(String []args){try{…

第二十一章总结博客

网络程序设计基础 局域网与互联网 为了实现两台计算机的通信&#xff0c;必须用一个网络线路连接两台计算机。如下图所示 网络协议 1.IP协议 IP是Internet Protocol的简称&#xff0c;是一种网络协议。Internet 网络采用的协议是TCP/IP协议&#xff0c;其全称是Transmission …

Docker架构及常用的命令

一、初识Docker 1、 docker是一个快速交付应用、运行应用的技术&#xff0c;具备下列优势&#xff1a; 可以将程序及其依赖、运行环境一起打包为一个镜像&#xff0c;可以迁移到任意Linux操作系统运行时利用沙箱机制形成隔离容器&#xff0c;各个应用互不干扰启动、移除都可以…

linux搭建nacos集群

准备 检查是否安装jdk [roothao /usr/local/software/elk/logstash]# java -version java version "1.8.0_341" Java(TM) SE Runtime Environment (build 1.8.0_341-b10) Java HotSpot(TM) 64-Bit Server VM (build 25.341-b10, mixed mode)配置nacos 去github下载…

一文3000字从0到1用Python进行gRPC接口测试!

gRPC 是一个高性能、通用的开源RPC框架&#xff0c;其由 Google 主要面向移动应用开发并基于HTTP/2 协议标准而设计&#xff0c;基于 ProtoBuf(Protocol Buffers) 序列化协议开发&#xff0c;且支持众多开发语言。 自gRPC推出以来&#xff0c;已经广泛应用于各种服务之中。在测…

Vue2脚手架搭建+项目基础依赖安装

文章目录 1. 安装 node.js2. 安装 vue-cli 脚手架3. 创建 vue2 项目4. 安装基础依赖 1. 安装 node.js 可以参考这篇文章 https://blog.csdn.net/weixin_43721000/article/details/134284418 2. 安装 vue-cli 脚手架 安装 vue-clinpm install -g vue/cli查看是否安装成功vue -…

用23种设计模式打造一个cocos creator的游戏框架----(七)代理模式

1、模式标准 模式名称&#xff1a;代理模式 模式分类&#xff1a;结构型 模式意图&#xff1a;为其他对象提供一种代理以控制对这个对象的访问。 结构图&#xff1a; ​ 适用于&#xff1a; 远程代理&#xff1a;也称为大使&#xff0c;这是最常见的类型&#xff0c;在分…

Data Mining数据挖掘—2. Classification分类

3. Classification Given a collection of records (training set) – each record contains a set of attributes – one of the attributes is the class (label) that should be predicted Find a model for class attribute as a function of the values of other attribu…

vuepress-----14、保护私密信息

秘钥存储文件 使用秘钥 忽略提交

通过异步序列化提高图表性能 Diagramming for WPF

通过异步序列化提高图表性能 2023 年 12 月 6 日 MindFusion.Diagramming for WPF 4.0.0 添加了异步加载和保存文件的功能&#xff0c;从而提高了响应能力。 MindFusion.Diagramming for WPF 提供了一个全面的工具集&#xff0c;用于创建各种图表&#xff0c;包括组织结构图、图…

『PyTorch学习笔记』如何快速下载huggingface模型/数据—全方法总结

如何快速下载huggingface模型/数据—全方法总结 文章目录 一. 如何快速下载huggingface大模型1.1. IDM(Windows)下载安装连接1.2. 推荐 huggingface 镜像站1.3. 管理huggingface_hub cache-system(缓存系统) 二. 参考文献 一. 如何快速下载huggingface大模型 推荐 huggingface…

苹果mac电脑如何彻底删除卸载软件?

在苹果电脑上安装和使用软件非常容易&#xff0c;但是卸载软件却可能会变得复杂和困难。不像在Windows上&#xff0c;你不能简单地在控制面板中找到已安装的程序并卸载它们。因此&#xff0c;在这篇文章中&#xff0c;我们将讨论苹果电脑怎么彻底删除软件。 CleanMyMac X全新版…

通信线缆是什么

通信线缆 电子元器件百科 文章目录 通信线缆前言一、通信线缆是什么二、通信线缆的类别三、通信线缆应用实例四、通信线缆的作用原理总结前言 每种线缆都有其特定的特性和用途。通信线缆起到连接和传输信号的作用,是实现通信和数据传输的重要组成部分。 一、通信线缆是什么 …

高级搜索——ST表,离线RMQ问题

文章目录 前言可重复贡献问题ST表的定义ST表的存储结构ST表的预处理预处理的实现 ST表的区间查询对于k的获取区间查询的实现 OJ链接 前言 对于查询区间最值的方法&#xff0c;我们常用的就是线段树&#xff0c;树状数组&#xff0c;单调队列&#xff0c;而树状数组更适合用于快…

AI报告专题:创造性和生成式人工智能

今天分享的AI系列深度研究报告&#xff1a;《AI报告专题&#xff1a;创造性和生成式人工智能》。 &#xff08;报告出品方&#xff1a;Capgemini&#xff09; 报告共计&#xff1a;64页 AI一代 生成式人工智能 (AI)正在迅速改变我们与技术的交互方式&#xff0c;使机器能够创…