董国庆
2025-04-07 5c2e3e0b4a4b4714c9a64a57ec10af7a1ef941a2
首页逻辑
2个文件已修改
1个文件已添加
234 ■■■■ 已修改文件
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/home/index.vue 208 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/view/home/service.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json
@@ -17,6 +17,7 @@
    "echarts": "^5.5.0",
    "element-ui": "^2.15.14",
    "ezuikit-js": "^7.7.10",
    "flv.js": "^1.6.2",
    "html2canvas": "^1.4.1",
    "moment": "^2.29.4",
    "qs": "^6.11.2",
src/view/home/index.vue
@@ -208,9 +208,11 @@
import * as echarts from "echarts";
import html2canvas from "html2canvas";
import AMapLoader from "@amap/amap-jsapi-loader";
import flvjs from "flv.js";
export default {
  data() {
    return {
      flvPlayer: null,
      activeIndex: "1",
      activeIndex2: "1",
      countList: [1, 2, 3], //预警情况统计数据
@@ -417,6 +419,7 @@
        autoMove: true,
        anchor: "top-center",
      });
      if (arr.length > 0) {
        const iconMap = {
          出租车: {
@@ -451,90 +454,163 @@
        arr.forEach((item, index) => {
          const iconConfig = iconMap[item.vehicleType];
          let marker = new AMap.Marker({
            position: [Number(item.longitude), Number(item.latitude)], //经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
            position: [Number(item.longitude), Number(item.latitude)],
            map: this.map,
            zooms: [13, 20],
            icon: new AMap.Icon({
              size: iconConfig.size,
              image: iconConfig.icon,
              imageSize: iconConfig.size,
              // 图标取图偏移量
              imageOffset: new AMap.Pixel(0, 0),
            }),
          });
          marker.content = this.listRender(item);
          marker.on("click", (e) => {
            infoWindow.setContent(e.target.content);
          // 添加点击事件
          marker.on("click", async (e) => {
            // 显示loading
            infoWindow.setContent(
              '<div style="padding: 20px;text-align: center;">加载中...</div>'
            );
            infoWindow.open(this.map, e.target.getPosition());
            try {
              // 并行请求车辆信息和视频地址
              const [carInfoRes, videoRes] = await Promise.all([
                this.getCarInfo(item.id),
                this.getVideoUrl(item.id),
              ]);
              // 更新弹窗内容
              infoWindow.setContent(
                this.listRender({
                  ...item,
                  ...carInfoRes.data,
                  videoUrl: videoRes.data.url,
                })
              );
            } catch (error) {
              console.error("获取车辆信息失败:", error);
              infoWindow.setContent(
                '<div style="padding: 20px;text-align: center;color: red;">获取车辆信息失败</div>'
              );
            }
          });
          // // 监听地图缩放事件
          // map.on("zoomchange", ()=> {
          //   var zoom = map.getZoom();
          //   var size = 30 + (zoom - 3) * 2; // 根据缩放级别计算 marker 大小
          //   var size1 = 20 + (zoom - 3) * 2;
          //   marker.setIcon({
          //     // image: "https://example.com/marker.png",
          //     size: new AMap.Size(size, size1),
          //   });
          // });
        });
      }
    },
    // <img
    //   style="width: 460px; height: 330px; border-radius: 9px" id="monitoringCard"
    //   src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
    // />
    // 获取车辆信息
    async getCarInfo(carId) {
      // TODO: 替换为实际的API调用
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({
            data: {
              licensePlate: "川A88888",
              driver: "李雷",
              location: "涪江文化广场",
              coordinates: "104.004284,30.579328",
              speed: "104km/h",
              drivingTime: "5小时15分钟",
            },
          });
        }, 500);
      });
    },
    // 获取视频地址
    async getVideoUrl(carId) {
      // TODO: 替换为实际的API调用
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({
            data: {
              url: "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4",
            },
          });
        }, 500);
      });
    },
    listRender(record) {
      if (flvjs.isSupported()) {
        flvPlayer = flvjs.createPlayer({
          type: "flv",
          isLive: true,
          cors: true,
          hasAudio: true,
          hasVideo: true,
          url: res.data.flv, // 后端拿到的视频路径
          enableWorker: true, //启用 Web Worker 进程来加速视频的解码和处理过程
          enableStashBuffer: false, // 启用数据缓存机制,提高视频的流畅度和稳定性。
          // stashInitialSize: 1024, // 初始缓存大小。单位:字节。建议针对直播:调整为1024kb
          // stashInitialTime: 0.2, // 缓存初始时间。单位:秒。建议针对直播:调整为200毫秒
          seekType: "range", // 建议将其设置为“range”模式,以便更快地加载视频数据,提高视频的实时性。
          // lazyLoad: false, //关闭懒加载模式,从而提高视频的实时性。建议针对直播:调整为false
          // lazyLoadMaxDuration: 0.2, // 懒加载的最大时长。单位:秒。建议针对直播:调整为200毫秒
          // deferLoadAfterSourceOpen: false // 不预先加载视频数据,在 MSE(Media Source Extensions)打开后立即加载数据,提高视频的实时性。建议针对直播:调整为false
        });
        let video = document.getElementById("monitoringCard");
        flvPlayer.attachMediaElement(video); // 你的video容器
        flvPlayer.load();
        flvPlayer.play();
      }
      return `<div style="background: #ffffff; padding: 24px 20px;z-index: 999">
          <div style="position: relative; width: 460px; height: 330px">
              <canvas ref="canvas" id="myCanvas" style="width: 460px; height: 330px;display:none" crossOrigin="anonymous"></canvas>
              <video
              ref="video"
               crossorigin="anonymous"
               style="width: 460px; height: 330px; border-radius: 9px"
               id="monitoringCard"
               ref="monitoringCard"
                :controls="false"
                autoPlay
                src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
                width="620">
              </video>
            <div style="position: absolute; right: 11px; top: 10px">
              <!-- 全屏 -->
              <div
                style=" display: flex;flex-direction: column;align-items: center;justify-content: center;
                  background: #ffffff; padding: 3px 10px; border-radius: 6px;margin-bottom: 10px;" onclick="fullScreen()" >
                <img
                  style="width: 20px; height: 20px" src="${require("../../assets//homeImg/full.png")}" />
                <div style="font-size: 12px;font-weight: 400; line-height: 17px; color: rgba(0, 0, 0, 0.88); " > 全屏</div>
              </div>
              <!-- 截屏 -->
              <div
                style="display: flex;flex-direction: column;align-items: center; justify-content: center;
                  background: #ffffff;padding: 3px 10px;border-radius: 6px; " onclick="shotScreen()">
                <img style="width: 20px; height: 20px" src="${require("../../assets//homeImg/slot.png")}" />
                <div  style="font-size: 12px;  font-weight: 400; line-height: 17px; color: rgba(0, 0, 0, 0.88);"> 截屏</div>
              </div>
        <div style="position: relative; width: 460px; height: 330px">
          <video
            crossorigin="anonymous"
            style="width: 460px; height: 330px; border-radius: 9px"
            id="monitoringCard"
            :controls="false"
            autoplay
            src="${record.videoUrl}"
            width="620">
          </video>
          <div style="position: absolute; right: 11px; top: 10px">
            <div style="display: flex;flex-direction: column;align-items: center;justify-content: center;
              background: #ffffff; padding: 3px 10px; border-radius: 6px;margin-bottom: 10px;" onclick="fullScreen()">
              <img style="width: 20px; height: 20px" src="${require("../../assets//homeImg/full.png")}" />
              <div style="font-size: 12px;font-weight: 400; line-height: 17px; color: rgba(0, 0, 0, 0.88);">全屏</div>
            </div>
            <div style="display: flex;flex-direction: column;align-items: center; justify-content: center;
              background: #ffffff;padding: 3px 10px;border-radius: 6px;" onclick="shotScreen()">
              <img style="width: 20px; height: 20px" src="${require("../../assets//homeImg/slot.png")}" />
              <div style="font-size: 12px; font-weight: 400; line-height: 17px; color: rgba(0, 0, 0, 0.88);">截屏</div>
            </div>
          </div>
          <div style="display: flex;justify-content: space-between;margin-top: 15px;margin-bottom: 12px;">
            <div style=" font-weight: 500;font-size: 18px;color: rgba(0, 0, 0, 0.85);line-height: 25px; "> 车牌号:川A 88888 </div>
            <div style="font-weight: 500; font-size: 18px;color: rgba(0, 0, 0, 0.85);line-height: 25px;" > 驾驶员:李雷</div>
          </div>
          <div style="display: flex; justify-content: space-between">
            <div  style=" font-weight: 500; font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">位置:涪江文化广场</div>
            <div  style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px; "> 经纬度:104.004284.30.579328</div>
          </div>
          <div style="display: flex; justify-content: space-between">
            <div  style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px; " > 当前时速:104km/h </div>
            <div style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px; "> 驾驶时长:5小时15分钟 </div>
          </div>
          <div style="margin-top: 14px;display: flex;justify-content: flex-end;align-items: center;cursor: pointer;" onclick="toCarDetail(${"111"})" >
            <div style="font-weight: 400;font-size: 18px; color: rgba(22, 119, 255, 1);line-height: 25px; ">车辆详情</div>
            <img style="width:18px;height: 18px;margin-left: 8px;" src="${require("../../assets//homeImg/right.png")}" />
          </div>
        </div>`;
        </div>
        <div style="display: flex;justify-content: space-between;margin-top: 15px;margin-bottom: 12px;">
          <div style="font-weight: 500;font-size: 18px;color: rgba(0, 0, 0, 0.85);line-height: 25px;">车牌号:${
            record.licensePlate
          }</div>
          <div style="font-weight: 500; font-size: 18px;color: rgba(0, 0, 0, 0.85);line-height: 25px;">驾驶员:${
            record.driver
          }</div>
        </div>
        <div style="display: flex; justify-content: space-between">
          <div style="font-weight: 500; font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">位置:${
            record.location
          }</div>
          <div style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">经纬度:${
            record.coordinates
          }</div>
        </div>
        <div style="display: flex; justify-content: space-between">
          <div style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">当前时速:${
            record.speed
          }</div>
          <div style="font-weight: 500;font-size: 14px; color: rgba(0, 0, 0, 0.65);line-height: 26px;">驾驶时长:${
            record.drivingTime
          }</div>
        </div>
        <div style="margin-top: 14px;display: flex;justify-content: flex-end;align-items: center;cursor: pointer;" onclick="toCarDetail(${
          record.id
        })">
          <div style="font-weight: 400;font-size: 18px; color: rgba(22, 119, 255, 1);line-height: 25px;">车辆详情</div>
          <img style="width:18px;height: 18px;margin-left: 8px;" src="${require("../../assets//homeImg/right.png")}" />
        </div>
      </div>`;
    },
    // 获取预警情况统计
    getCountList() {
src/view/home/service.js
New file
@@ -0,0 +1,25 @@
import axios from '@/utils/request';
// 获取各种车辆类型车辆总数
export const getCarCount = (data) => {
    return axios.get('/car/getCarCount', data)
}
// 获取车辆状态汇总和公司总数量
export const getCarStatusCount = (data) => {
    return axios.get('/car/getCarStatusCount', data)
}
// 获取地图司机数据
export const getMapCarList = (data) => {
    return axios.get('/car/getMapCarList', data)
}
// 获取车辆预警列表
export const getCarWarnList = (data) => {
    return axios.get('/warn/getCarWarnList', data)
}
// 获取车辆预警情况统计
export const getWarnGroupCount = (data) => {
    return axios.get('/warn/getWarnGroupCount', data)
}
// 获取预警排行统计前10
export const getWarnGroupCountTop10 = (data) => {
    return axios.get('/warn/getWarnGroupCountTop10', data)
}