Explorar o código

Merge branch 'master' of http://git.xt.wenhq.top:8083/wenhongquan/khyznh-ui

liwei19941102 hai 1 ano
pai
achega
f1fa98a13c
Modificáronse 34 ficheiros con 3306 adicións e 2265 borrados
  1. 3 0
      index.html
  2. 0 0
      public/jess/decoder.js
  3. BIN=BIN
      public/jess/decoder.wasm
  4. 190 0
      public/jess/demo.html
  5. 637 0
      public/jess/jessibuca.d.ts
  6. 0 0
      public/jess/jessibuca.js
  7. 33 3
      src/api/gpsData/index.ts
  8. 2 3
      src/components/HomeComponents/countPage.vue
  9. 30 30
      src/components/HomeComponents/messageTable.vue
  10. 3 5
      src/components/HomeComponents/pieEcharts.vue
  11. 282 264
      src/components/HomeComponents/stationPie.vue
  12. 49 34
      src/components/HomeComponents/warnTable.vue
  13. 2 4
      src/components/HomeStatics/countPage.vue
  14. 28 20
      src/components/HomeStatics/messageTable.vue
  15. 4 5
      src/components/HomeStatics/pieEcharts.vue
  16. 71 36
      src/components/HomeStatics/stationPie.vue
  17. 43 21
      src/components/HomeStatics/warnTable.vue
  18. 4 9
      src/components/Map/editMap.vue
  19. 9 12
      src/components/Map/index.vue
  20. 5 9
      src/components/Map/map.vue
  21. 2 3
      src/components/Map/videoMap.vue
  22. 304 388
      src/views/car/carInfo/add.vue
  23. 12 11
      src/views/car/carInfo/index.vue
  24. 41 43
      src/views/car/people/index.vue
  25. 41 43
      src/views/car/people/yonghu.vue
  26. 119 127
      src/views/car/work/addCarWork.vue
  27. 12 6
      src/views/car/work/schedule.vue
  28. 2 4
      src/views/home.vue
  29. 1 2
      src/views/index.vue
  30. 191 0
      src/views/statics/index.vue
  31. 1 2
      src/views/statics/passengerFlow.vue
  32. 330 331
      src/views/yunying/kdg/index.vue
  33. 596 588
      src/views/yunying/scheduling/index.vue
  34. 259 262
      src/views/yunying/sties/index.vue

+ 3 - 0
index.html

@@ -6,6 +6,9 @@
     <meta name="renderer" content="webkit" />
     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
     <link rel="icon" href="/favicon.ico" />
+
+     <script src="/jess/jessibuca.js"></script>
+
     <title>农村客运信息化管理系统</title>
     <!--[if lt IE 11
       ]><script>

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
public/jess/decoder.js


BIN=BIN
public/jess/decoder.wasm


+ 190 - 0
public/jess/demo.html

@@ -0,0 +1,190 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+    <script src="./jessibuca.js"></script>
+    <style>
+        .root {
+            display: flex;
+            place-content: center;
+            margin-top: 3rem;
+        }
+
+        .container-shell {
+            backdrop-filter: blur(5px);
+            background: hsla(0, 0%, 50%, 0.5);
+            padding: 30px 4px 10px 4px;
+            /* border: 2px solid black; */
+            width: auto;
+            position: relative;
+            border-radius: 5px;
+            box-shadow: 0 10px 20px;
+        }
+
+        .container-shell:before {
+            content: "jessibuca demo player";
+            position: absolute;
+            color: darkgray;
+            top: 4px;
+            left: 10px;
+            text-shadow: 1px 1px black;
+        }
+
+        #container {
+            background: rgba(13, 14, 27, 0.7);
+            width: 640px;
+            height: 398px;
+        }
+
+        .input {
+            display: flex;
+            margin-top: 10px;
+            color: white;
+            place-content: stretch;
+        }
+
+        .input2 {
+            bottom: 0px;
+        }
+
+        .input input {
+            flex: auto;
+        }
+
+        .err {
+            position: absolute;
+            top: 40px;
+            left: 10px;
+            color: red;
+        }
+
+        .option {
+            position: absolute;
+            top: 4px;
+            right: 10px;
+            display: flex;
+            place-content: center;
+            font-size: 12px;
+        }
+
+        .option span {
+            color: white;
+        }
+
+        .page {
+            background: url('./bg.jpg');
+            background-repeat: no-repeat;
+            background-position: top;
+        }
+
+        @media (max-width: 720px) {
+            #container {
+                width: 90vw;
+                height: 52.7vw;
+            }
+        }
+    </style>
+</head>
+<body class="page">
+<div class="root">
+    <div class="container-shell">
+        <div id="container"></div>
+        <div class="input">
+            <div>输入URL:</div>
+            <input
+                autocomplete="on"
+                id="playUrl"
+                value=""
+            />
+            <button id="play">播放</button>
+            <button id="pause" style="display: none">停止</button>
+        </div>
+        <div class="input" style="line-height: 30px">
+            <button id="destroy">销毁</button>
+        </div>
+    </div>
+</div>
+
+<script>
+    var $player = document.getElementById('play');
+    var $pause = document.getElementById('pause');
+    var $playHref = document.getElementById('playUrl');
+    var $container = document.getElementById('container');
+    var $destroy = document.getElementById('destroy');
+
+    var showOperateBtns = false; // 是否显示按钮
+    var forceNoOffscreen = true; //
+    var jessibuca = null;
+
+    function create() {
+        jessibuca = null;
+        jessibuca = new Jessibuca({
+            container: $container,
+            videoBuffer: 0.2, // 缓存时长
+            isResize: false,
+            text: "",
+            loadingText: "",
+            useMSE: false,
+            debug: true,
+            showBandwidth: showOperateBtns, // 显示网速
+            operateBtns: {
+                fullscreen: showOperateBtns,
+                screenshot: showOperateBtns,
+                play: showOperateBtns,
+                audio: false,
+                recorder: false
+            },
+            forceNoOffscreen: forceNoOffscreen,
+            isNotMute: false,
+        },);
+
+        jessibuca.on('audioInfo', function (audioInfo) {
+            console.log('audioInfo',audioInfo);
+        })
+
+        jessibuca.on('videoInfo', function (videoInfo) {
+            console.log('videoInfo',videoInfo);
+        })
+
+        $player.style.display = 'inline-block';
+        $pause.style.display = 'none';
+        $destroy.style.display = 'none';
+    }
+
+
+    create();
+
+    $player.addEventListener('click', function () {
+        var href = $playHref.value;
+        if (href) {
+            jessibuca.play(href);
+            $player.style.display = 'none';
+            $pause.style.display = 'inline-block';
+            $destroy.style.display = 'inline-block';
+        }
+    }, false)
+
+
+    $pause.addEventListener('click', function () {
+        $player.style.display = 'inline-block';
+        $pause.style.display = 'none';
+        jessibuca.pause();
+    })
+
+    $destroy.addEventListener('click', function () {
+        if (jessibuca) {
+            jessibuca.destroy().then(()=>{
+                create();
+            });
+        }
+        else {
+            create();
+        }
+    })
+
+</script>
+
+</body>
+</html>
+

+ 637 - 0
public/jess/jessibuca.d.ts

@@ -0,0 +1,637 @@
+declare namespace Jessibuca {
+
+    /** 超时信息 */
+    enum TIMEOUT {
+        /** 当play()的时候,如果没有数据返回 */
+        loadingTimeout = 'loadingTimeout',
+        /** 当播放过程中,如果超过timeout之后没有数据渲染 */
+        delayTimeout = 'delayTimeout',
+    }
+
+    /** 错误信息 */
+    enum ERROR {
+        /** 播放错误,url 为空的时候,调用 play 方法 */
+        playError = 'playError',
+        /** http 请求失败 */
+        fetchError = 'fetchError',
+        /** websocket 请求失败 */
+        websocketError = 'websocketError',
+        /** webcodecs 解码 h265 失败 */
+        webcodecsH265NotSupport = 'webcodecsH265NotSupport',
+        /** mediaSource 解码 h265 失败 */
+        mediaSourceH265NotSupport = 'mediaSourceH265NotSupport',
+        /** wasm 解码失败 */
+        wasmDecodeError = 'wasmDecodeError',
+    }
+
+    interface Config {
+        /**
+         * 播放器容器
+         * *  若为 string ,则底层调用的是 document.getElementById('id')
+         * */
+        container: HTMLElement | string;
+        /**
+         * 设置最大缓冲时长,单位秒,播放器会自动消除延迟
+         */
+        videoBuffer?: number;
+        /**
+         * worker地址
+         * *  默认引用的是根目录下面的decoder.js文件 ,decoder.js 与 decoder.wasm文件必须是放在同一个目录下面。 */
+        decoder?: string;
+        /**
+         * 是否不使用离屏模式(提升渲染能力)
+         */
+        forceNoOffscreen?: boolean;
+        /**
+         * 是否开启当页面的'visibilityState'变为'hidden'的时候,自动暂停播放。
+         */
+        hiddenAutoPause?: boolean;
+        /**
+         * 是否有音频,如果设置`false`,则不对音频数据解码,提升性能。
+         */
+        hasAudio?: boolean;
+        /**
+         * 设置旋转角度,只支持,0(默认),180,270 三个值
+         */
+        rotate?: boolean;
+        /**
+         * 1. 当为`true`的时候:视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边。 等同于 `setScaleMode(1)`
+         * 2. 当为`false`的时候:视频画面完全填充canvas区域,画面会被拉伸。等同于 `setScaleMode(0)`
+         */
+        isResize?: boolean;
+        /**
+         * 1. 当为`true`的时候:视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全。等同于 `setScaleMode(2)`
+         */
+        isFullResize?: boolean;
+        /**
+         * 1. 当为`true`的时候:ws协议不检验是否以.flv为依据,进行协议解析。
+         */
+        isFlv?: boolean;
+        /**
+         * 是否开启控制台调试打
+         */
+        debug?: boolean;
+        /**
+         * 1. 设置超时时长, 单位秒
+         * 2. 在连接成功之前(loading)和播放中途(heart),如果超过设定时长无数据返回,则回调timeout事件
+         */
+        timeout?: number;
+        /**
+         * 1. 设置超时时长, 单位秒
+         * 2. 在连接成功之前,如果超过设定时长无数据返回,则回调timeout事件
+         */
+        heartTimeout?: number;
+        /**
+         * 1. 设置超时时长, 单位秒
+         * 2. 在连接成功之前,如果超过设定时长无数据返回,则回调timeout事件
+         */
+        loadingTimeout?: number;
+        /**
+         * 是否支持屏幕的双击事件,触发全屏,取消全屏事件
+         */
+        supportDblclickFullscreen?: boolean;
+        /**
+         * 是否显示网
+         */
+        showBandwidth?: boolean;
+        /**
+         * 配置操作按钮
+         */
+        operateBtns?: {
+            /** 是否显示全屏按钮 */
+            fullscreen?: boolean;
+            /** 是否显示截图按钮 */
+            screenshot?: boolean;
+            /** 是否显示播放暂停按钮 */
+            play?: boolean;
+            /** 是否显示声音按钮 */
+            audio?: boolean;
+            /** 是否显示录制按 */
+            record?: boolean;
+        };
+        /**
+         * 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮
+         */
+        keepScreenOn?: boolean;
+        /**
+         * 是否开启声音,默认是关闭声音播放的
+         */
+        isNotMute?: boolean;
+        /**
+         * 加载过程中文案
+         */
+        loadingText?: string;
+        /**
+         * 背景图片
+         */
+        background?: string;
+        /**
+         * 是否开启MediaSource硬解码
+         * * 视频编码只支持H.264视频(Safari on iOS不支持)
+         * * 不支持 forceNoOffscreen 为 false (开启离屏渲染)
+         */
+        useMSE?: boolean;
+        /**
+         * 是否开启Webcodecs硬解码
+         * *  视频编码只支持H.264视频 (需在chrome 94版本以上,需要https或者localhost环境)
+         * *  支持 forceNoOffscreen 为 false (开启离屏渲染)
+         * */
+        useWCS?: boolean;
+        /**
+         * 是否开启键盘快捷键
+         * 目前支持的键盘快捷键有:esc -> 退出全屏;arrowUp -> 声音增加;arrowDown -> 声音减少;
+         */
+        hotKey?: boolean;
+        /**
+         *  在使用MSE或者Webcodecs 播放H265的时候,是否自动降级到wasm模式。
+         *  设置为false 则直接关闭播放,抛出Error 异常,设置为true 则会自动切换成wasm模式播放。
+         */
+        autoWasm?: boolean;
+        /**
+         * heartTimeout 心跳超时之后自动再播放,不再抛出异常,而直接重新播放视频地址。
+         */
+        heartTimeoutReplay?: boolean,
+        /**
+         * heartTimeoutReplay 从试次数,超过之后,不再自动播放
+         */
+        heartTimeoutReplayTimes?: number,
+        /**
+         * loadingTimeout loading之后自动再播放,不再抛出异常,而直接重新播放视频地址。
+         */
+        loadingTimeoutReplay?: boolean,
+        /**
+         * heartTimeoutReplay 从试次数,超过之后,不再自动播放
+         */
+        loadingTimeoutReplayTimes?: number
+        /**
+         * wasm解码报错之后,不再抛出异常,而是直接重新播放视频地址。
+         */
+        wasmDecodeErrorReplay?: boolean,
+        /**
+         * https://github.com/langhuihui/jessibuca/issues/152 解决方案
+         * 例如:WebGL图像预处理默认每次取4字节的数据,但是540x960分辨率下的U、V分量宽度是540/2=270不能被4整除,导致绿屏。
+         */
+        openWebglAlignment?: boolean
+    }
+}
+
+
+declare class Jessibuca {
+
+    constructor(config?: Jessibuca.Config);
+
+    /**
+     * 是否开启控制台调试打印
+     @example
+     // 开启
+     jessibuca.setDebug(true)
+     // 关闭
+     jessibuca.setDebug(false)
+     */
+    setDebug(flag: boolean): void;
+
+    /**
+     * 静音
+     @example
+     jessibuca.mute()
+     */
+    mute(): void;
+
+    /**
+     * 取消静音
+     @example
+     jessibuca.cancelMute()
+     */
+    cancelMute(): void;
+
+    /**
+     * 留给上层用户操作来触发音频恢复的方法。
+     *
+     * iPhone,chrome等要求自动播放时,音频必须静音,需要由一个真实的用户交互操作来恢复,不能使用代码。
+     *
+     * https://developers.google.com/web/updates/2017/09/autoplay-policy-changes
+     */
+    audioResume(): void;
+
+    /**
+     *
+     * 设置超时时长, 单位秒
+     * 在连接成功之前和播放中途,如果超过设定时长无数据返回,则回调timeout事件
+
+     @example
+     jessibuca.setTimeout(10)
+
+     jessibuca.on('timeout',function(){
+        //
+    });
+     */
+    setTimeout(): void;
+
+    /**
+     * @param mode
+     *      0 视频画面完全填充canvas区域,画面会被拉伸  等同于参数 `isResize` 为false
+     *
+     *      1 视频画面做等比缩放后,高或宽对齐canvas区域,画面不被拉伸,但有黑边 等同于参数 `isResize` 为true
+     *
+     *      2 视频画面做等比缩放后,完全填充canvas区域,画面不被拉伸,没有黑边,但画面显示不全 等同于参数 `isFullResize` 为true
+     @example
+     jessibuca.setScaleMode(0)
+
+     jessibuca.setScaleMode(1)
+
+     jessibuca.setScaleMode(2)
+     */
+    setScaleMode(mode: number): void;
+
+    /**
+     * 暂停播放
+     *
+     * 可以在pause 之后,再调用 `play()`方法就继续播放之前的流。
+     @example
+     jessibuca.pause().then(()=>{
+        console.log('pause success')
+
+        jessibuca.play().then(()=>{
+
+        }).catch((e)=>{
+
+        })
+
+    }).catch((e)=>{
+        console.log('pause error',e);
+    })
+     */
+    pause(): Promise<void>;
+
+    /**
+     * 关闭视频,不释放底层资源
+     @example
+     jessibuca.close();
+     */
+    close(): void;
+
+    /**
+     * 关闭视频,释放底层资源
+     @example
+     jessibuca.destroy()
+     */
+    destroy(): void;
+
+    /**
+     * 清理画布为黑色背景
+     @example
+     jessibuca.clearView()
+     */
+    clearView(): void;
+
+    /**
+     * 播放视频
+     @example
+
+     jessibuca.play('url').then(()=>{
+        console.log('play success')
+    }).catch((e)=>{
+        console.log('play error',e)
+    })
+     //
+     jessibuca.play()
+     */
+    play(url?: string): Promise<void>;
+
+    /**
+     * 重新调整视图大小
+     */
+    resize(): void;
+
+    /**
+     * 设置最大缓冲时长,单位秒,播放器会自动消除延迟。
+     *
+     * 等同于 `videoBuffer` 参数。
+     *
+     @example
+     // 设置 200ms 缓冲
+     jessibuca.setBufferTime(0.2)
+     */
+    setBufferTime(time: number): void;
+
+    /**
+     * 设置旋转角度,只支持,0(默认) ,180,270 三个值。
+     *
+     * > 可用于实现监控画面小窗和全屏效果,由于iOS没有全屏API,此方法可以模拟页面内全屏效果而且多端效果一致。   *
+     @example
+     jessibuca.setRotate(0)
+
+     jessibuca.setRotate(90)
+
+     jessibuca.setRotate(270)
+     */
+    setRotate(deg: number): void;
+
+    /**
+     *
+     * 设置音量大小,取值0 — 1
+     *
+     * > 区别于 mute 和 cancelMute 方法,虽然设置setVolume(0) 也能达到 mute方法,但是mute 方法是不调用底层播放音频的,能提高性能。而setVolume(0)只是把声音设置为0 ,以达到效果。
+     * @param volume 当为0时,完全无声;当为1时,最大音量,默认值
+     @example
+     jessibuca.setVolume(0.2)
+
+     jessibuca.setVolume(0)
+
+     jessibuca.setVolume(1)
+     */
+    setVolume(volume: number): void;
+
+    /**
+     * 返回是否加载完毕
+     @example
+     var result = jessibuca.hasLoaded()
+     console.log(result) // true
+     */
+    hasLoaded(): boolean;
+
+    /**
+     * 开启屏幕常亮,在手机浏览器上, canvas标签渲染视频并不会像video标签那样保持屏幕常亮。
+     * H5目前在chrome\edge 84, android chrome 84及以上有原生亮屏API, 需要是https页面
+     * 其余平台为模拟实现,此时为兼容实现,并不保证所有浏览器都支持
+     @example
+     jessibuca.setKeepScreenOn()
+     */
+    setKeepScreenOn(): boolean;
+
+    /**
+     * 全屏(取消全屏)播放视频
+     @example
+     jessibuca.setFullscreen(true)
+     //
+     jessibuca.setFullscreen(false)
+     */
+    setFullscreen(flag: boolean): void;
+
+    /**
+     *
+     * 截图,调用后弹出下载框保存截图
+     * @param filename 可选参数, 保存的文件名, 默认 `时间戳`
+     * @param format   可选参数, 截图的格式,可选png或jpeg或者webp ,默认 `png`
+     * @param quality  可选参数, 当格式是jpeg或者webp时,压缩质量,取值0 ~ 1 ,默认 `0.92`
+     * @param type 可选参数, 可选download或者base64或者blob,默认`download`
+
+     @example
+
+     jessibuca.screenshot("test","png",0.5)
+
+     const base64 = jessibuca.screenshot("test","png",0.5,'base64')
+
+     const fileBlob = jessibuca.screenshot("test",'blob')
+     */
+    screenshot(filename?: string, format?: string, quality?: number, type?: string): void;
+
+    /**
+     * 开始录制。
+     * @param fileName 可选,默认时间戳
+     * @param fileType 可选,默认webm,支持webm 和mp4 格式
+
+     @example
+     jessibuca.startRecord('xxx','webm')
+     */
+    startRecord(fileName: string, fileType: string): void;
+
+    /**
+     * 暂停录制并下载。
+     @example
+     jessibuca.stopRecordAndSave()
+     */
+    stopRecordAndSave(): void;
+
+    /**
+     * 返回是否正在播放中状态。
+     @example
+     var result = jessibuca.isPlaying()
+     console.log(result) // true
+     */
+    isPlaying(): boolean;
+
+    /**
+     *   返回是否静音。
+     @example
+     var result = jessibuca.isMute()
+     console.log(result) // true
+     */
+    isMute(): boolean;
+
+    /**
+     * 返回是否正在录制。
+     @example
+     var result = jessibuca.isRecording()
+     console.log(result) // true
+     */
+    isRecording(): boolean;
+
+
+    /**
+     * 监听 jessibuca 初始化事件
+     * @example
+     * jessibuca.on("load",function(){console.log('load')})
+     */
+    on(event: 'load', callback: () => void): void;
+
+    /**
+     * 视频播放持续时间,单位ms
+     * @example
+     * jessibuca.on('timeUpdate',function (ts) {console.log('timeUpdate',ts);})
+     */
+    on(event: 'timeUpdate', callback: () => void): void;
+
+    /**
+     * 当解析出视频信息时回调,2个回调参数
+     * @example
+     * jessibuca.on("videoInfo",function(data){console.log('width:',data.width,'height:',data.width)})
+     */
+    on(event: 'videoInfo', callback: (data: {
+        /** 视频宽 */
+        width: number;
+        /** 视频高 */
+        height: number;
+    }) => void): void;
+
+    /**
+     * 当解析出音频信息时回调,2个回调参数
+     * @example
+     * jessibuca.on("audioInfo",function(data){console.log('numOfChannels:',data.numOfChannels,'sampleRate',data.sampleRate)})
+     */
+    on(event: 'audioInfo', callback: (data: {
+        /** 声频通道 */
+        numOfChannels: number;
+        /** 采样率 */
+        sampleRate: number;
+    }) => void): void;
+
+    /**
+     * 信息,包含错误信息
+     * @example
+     * jessibuca.on("log",function(data){console.log('data:',data)})
+     */
+    on(event: 'log', callback: () => void): void;
+
+    /**
+     * 错误信息
+     * @example
+     * jessibuca.on("error",function(error){
+        if(error === Jessibuca.ERROR.fetchError){
+            //
+        }
+        else if(error === Jessibuca.ERROR.webcodecsH265NotSupport){
+            //
+        }
+        console.log('error:',error)
+    })
+     */
+    on(event: 'error', callback: (err: Jessibuca.ERROR) => void): void;
+
+    /**
+     * 当前网速, 单位KB 每秒1次,
+     * @example
+     * jessibuca.on("kBps",function(data){console.log('kBps:',data)})
+     */
+    on(event: 'kBps', callback: (value: number) => void): void;
+
+    /**
+     * 渲染开始
+     * @example
+     * jessibuca.on("start",function(){console.log('start render')})
+     */
+    on(event: 'start', callback: () => void): void;
+
+    /**
+     * 当设定的超时时间内无数据返回,则回调
+     * @example
+     * jessibuca.on("timeout",function(error){console.log('timeout:',error)})
+     */
+    on(event: 'timeout', callback: (error: Jessibuca.TIMEOUT) => void): void;
+
+    /**
+     * 当play()的时候,如果没有数据返回,则回调
+     * @example
+     * jessibuca.on("loadingTimeout",function(){console.log('timeout')})
+     */
+    on(event: 'loadingTimeout', callback: () => void): void;
+
+    /**
+     * 当播放过程中,如果超过timeout之后没有数据渲染,则抛出异常。
+     * @example
+     * jessibuca.on("delayTimeout",function(){console.log('timeout')})
+     */
+    on(event: 'delayTimeout', callback: () => void): void;
+
+    /**
+     * 当前是否全屏
+     * @example
+     * jessibuca.on("fullscreen",function(flag){console.log('is fullscreen',flag)})
+     */
+    on(event: 'fullscreen', callback: () => void): void;
+
+    /**
+     * 触发播放事件
+     * @example
+     * jessibuca.on("play",function(flag){console.log('play')})
+     */
+    on(event: 'play', callback: () => void): void;
+
+    /**
+     * 触发暂停事件
+     * @example
+     * jessibuca.on("pause",function(flag){console.log('pause')})
+     */
+    on(event: 'pause', callback: () => void): void;
+
+    /**
+     * 触发声音事件,返回boolean值
+     * @example
+     * jessibuca.on("mute",function(flag){console.log('is mute',flag)})
+     */
+    on(event: 'mute', callback: () => void): void;
+
+    /**
+     * 流状态统计,流开始播放后回调,每秒1次。
+     * @example
+     * jessibuca.on("stats",function(s){console.log("stats is",s)})
+     */
+    on(event: 'stats', callback: (stats: {
+        /** 当前缓冲区时长,单位毫秒 */
+        buf: number;
+        /** 当前视频帧率 */
+        fps: number;
+        /** 当前音频码率,单位byte */
+        abps: number;
+        /** 当前视频码率,单位byte */
+        vbps: number;
+        /** 当前视频帧pts,单位毫秒 */
+        ts: number;
+    }) => void): void;
+
+    /**
+     * 渲染性能统计,流开始播放后回调,每秒1次。
+     * @param performance 0: 表示卡顿,1: 表示流畅,2: 表示非常流程
+     * @example
+     * jessibuca.on("performance",function(performance){console.log("performance is",performance)})
+     */
+    on(event: 'performance', callback: (performance: 0 | 1 | 2) => void): void;
+
+    /**
+     * 录制开始的事件
+
+     * @example
+     * jessibuca.on("recordStart",function(){console.log("record start")})
+     */
+    on(event: 'recordStart', callback: () => void): void;
+
+    /**
+     * 录制结束的事件
+
+     * @example
+     * jessibuca.on("recordEnd",function(){console.log("record end")})
+     */
+    on(event: 'recordEnd', callback: () => void): void;
+
+    /**
+     * 录制的时候,返回的录制时长,1s一次
+
+     * @example
+     * jessibuca.on("recordingTimestamp",function(timestamp){console.log("recordingTimestamp is",timestamp)})
+     */
+    on(event: 'recordingTimestamp', callback: (timestamp: number) => void): void;
+
+    /**
+     * 监听调用play方法 经过 初始化-> 网络请求-> 解封装 -> 解码 -> 渲染 一系列过程的时间消耗
+     * @param event
+     * @param callback
+     */
+    on(event: 'playToRenderTimes', callback: (times: {
+        playInitStart: number, // 1 初始化
+        playStart: number, // 2 初始化
+        streamStart: number, // 3 网络请求
+        streamResponse: number, // 4 网络请求
+        demuxStart: number, // 5 解封装
+        decodeStart: number, // 6 解码
+        videoStart: number, // 7 渲染
+        playTimestamp: number,// playStart- playInitStart
+        streamTimestamp: number,// streamStart - playStart
+        streamResponseTimestamp: number,// streamResponse - streamStart
+        demuxTimestamp: number, // demuxStart - streamResponse
+        decodeTimestamp: number, // decodeStart - demuxStart
+        videoTimestamp: number,// videoStart - decodeStart
+        allTimestamp: number // videoStart - playInitStart
+    }) => void): void
+
+    /**
+     * 监听方法
+     *
+     @example
+
+     jessibuca.on("load",function(){console.log('load')})
+     */
+    on(event: string, callback: Function): void;
+
+}
+
+export default Jessibuca;

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
public/jess/jessibuca.js


+ 33 - 3
src/api/gpsData/index.ts

@@ -34,7 +34,6 @@ export function playdevice(codes): AxiosPromise<any> {
   });
 }
 
-
 export function liststaticFlow(query): AxiosPromise<any> {
   return request({
     url: `/system/carInfo/liststaticFlow`,
@@ -43,11 +42,42 @@ export function liststaticFlow(query): AxiosPromise<any> {
   });
 }
 
-
 export function listsitesFlow(query): AxiosPromise<any> {
   return request({
     url: `/system/sites/flow`,
     params: query,
     method: 'get'
   });
-}
+}
+
+export function cabinetboxstatic(): AxiosPromise<any> {
+  return request({
+    url: `/system/common/cabinet/boxstatic`,
+    data: {},
+    method: 'post'
+  });
+}
+
+export function devicestatic(): AxiosPromise<any> {
+  return request({
+    url: `/system/common/station/devs`,
+    data: {},
+    method: 'post'
+  });
+}
+
+export function playlist(): AxiosPromise<any> {
+  return request({
+    url: `/system/common/playlist/static`,
+    data: {},
+    method: 'post'
+  });
+}
+
+export function offlinelist(): AxiosPromise<any> {
+  return request({
+    url: `/system/common/devicemsg`,
+    data: {},
+    method: 'post'
+  });
+}

+ 2 - 3
src/components/HomeComponents/countPage.vue

@@ -54,7 +54,6 @@ const getCountDataList = () => {
             endtime: endDate
         }
     }
-    console.log(obj)
     getCountData(obj).then(res => {
         people.value = res.data.totalin
     })
@@ -64,7 +63,7 @@ const getlistGoodsOrder = () =>{
     var gotime =  moment(new Date()).format('YYYY-MM-DD 00:00:00')
     listGoodsOrder({pageSize:1000,gotime:gotime}).then(res=>{
           goods.value = res.rows.length
-    }) 
+    })
 }
 
 onMounted(() => {
@@ -152,4 +151,4 @@ onMounted(() => {
         text-transform: none;
     }
 }
-</style>
+</style>

+ 30 - 30
src/components/HomeComponents/messageTable.vue

@@ -1,22 +1,22 @@
 <template>
-    <div class="messagePageClass">
-        <div class="titleBg">
-            <div class="titleFont">设备报警</div>
-        </div>
-        <div class="divContent">
-            <div style="margin-left: 1vw;max-height: 30vh;overflow-y: scroll;" class="tableClass">
-                <div v-for="(item, index) in messageList">
-                    <div style="display: flex;flex-direction: row;justify-content: space-around;margin-top: 20px;">
-                        <div :class="item.type == 1 ? 'carClass' : 'goodClass'">{{ item.carNum }}</div>
-                        <div class="contentClass">{{ item.content }}</div>
-                        <div class="stationClass">{{ item.station }}</div>
-                        <div class="timeClass">{{ item.time }}</div>
-                    </div>
-                    <el-divider />
-                </div>
-            </div>
+  <div class="messagePageClass">
+    <div class="titleBg">
+      <div class="titleFont">车辆报站</div>
+    </div>
+    <div class="divContent">
+      <div style="margin-left: 1vw;max-height: 30vh;overflow-y: scroll;" class="tableClass">
+        <div v-for="(item, index) in messageList" :key="index">
+          <div style="display: flex;flex-direction: row;justify-content: space-around;margin-top: 20px;">
+            <div :class="item.type == 1 ? 'carClass' : 'goodClass'">{{ item.carNum }}</div>
+            <div class="contentClass">{{ "即将到达" }}</div>
+            <div class="stationClass">{{ item.station }}</div>
+            <div class="timeClass">{{ moment(item.time).format("MM/DD HH:mm") }}</div>
+          </div>
+          <el-divider />
         </div>
-        <!-- <div>
+      </div>
+    </div>
+    <!-- <div>
             <div class="title" style="padding-left: 0.5vw;">到站提醒</div>
             <div style="margin-left: 1vw;max-height: 20vh;overflow-y: scroll;" class="tableClass">
                 <div v-for="(item, index) in messageList">
@@ -30,25 +30,25 @@
                 </div>
             </div>
         </div> -->
-    </div>
+  </div>
 </template>
 
 <script setup name="CarInfo" lang="ts">
+import moment from 'moment';
+import { playlist } from '@/api/gpsData';
 
-const messageList = ref([{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 }
+const messageList = ref([
 ]);
 
+const getList = () => {
+    playlist().then(res => {
+        messageList.value = res;
+    });
+};
+
+
 onMounted(() => {
-    // getList();
+    getList();
 });
 </script>
 <style scoped lang="scss">
@@ -164,4 +164,4 @@ onMounted(() => {
     height: 24px;
     line-height: 24px;
 }
-</style>
+</style>

+ 3 - 5
src/components/HomeComponents/pieEcharts.vue

@@ -24,7 +24,6 @@ const initData = async () => {
     var total = carTotal.total
     const data = await getDicts('tbl_car_type')
     carTypeList.value = data.data
-    console.log(carTypeList.value)
     var label = {
         normal: {
             formatter: '{c|{c}}' + "\n\n" + '{b|{b}} ',
@@ -50,12 +49,11 @@ const initData = async () => {
         length2: 50
     }
     for (var index in carTypeList.value) {
-        console.log(carTypeList.value[0])
+
         var obj = {
             pageSize: 1000,
             carType: carTypeList.value[index].dictValue
         }
-        console.log(obj)
         const res = await listCarInfo(obj);
         total = total - res.total
         var cObj = {
@@ -73,7 +71,7 @@ const initData = async () => {
 const getDictsData = (param, obj) => {
     getDicts(param).then(res => {
         obj.value = res.data;
-        console.log(carTypeList.value)
+
     })
 }
 
@@ -177,4 +175,4 @@ onMounted(() => {
         height: 22vh;
     }
 }
-</style>
+</style>

+ 282 - 264
src/components/HomeComponents/stationPie.vue

@@ -1,77 +1,58 @@
 <template>
-    <div class="stationEchartsClass">
-        <div class="lineEchartsClass">
-            <div class="titleBg">
-                <div class="titleFont">电子站台统计</div>
+  <div class="stationEchartsClass">
+    <div class="lineEchartsClass">
+      <div class="titleBg">
+        <div class="titleFont">电子站台统计</div>
+      </div>
+      <div class="divContent" style="display: flex;flex-direction: row;justify-content: space-around;align-items: center;padding-right: 1vw;">
+        <div style="display: flex;flex-direction: row;margin-top: 1vh;padding-left: 1vw;">
+          <div ref="stationchart" style="width:10vw;height: 20vh;"></div>
+          <div style="display: flex;flex-direction: column;">
+            <div class="countDiv" style="display: flex;flex-direction: column;justify-content: space-between;position:relative;">
+              <div><img style="width: 2vw;height: 1vh;;position:absolute;top:0" src="@/assets/images/homeImages/up.png" /></div>
+              <div style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
+                <div class="typeClass">总设备数</div>
+                <div class="countClass" style="color: #FEF822;">
+                  {{totaldevice }}
+                </div>
+              </div>
+              <div style="margin-left: 6vw;">
+                <img style="width: 2vw;height: 1vh;position:absolute; bottom:0;right:0" src="@/assets/images/homeImages/bottom.png" />
+              </div>
             </div>
-            <div class="divContent"
-                style="display: flex;flex-direction: row;justify-content: space-around;align-items: center;padding-right: 1vw;">
-                <div style="display: flex;flex-direction: row;margin-top: 1vh;padding-left: 1vw;">
-                    <div ref="stationchart" style="width:10vw;height: 20vh;"></div>
-                    <div style="display: flex;flex-direction: column;">
-                        <div class="countDiv"
-                            style="display: flex;flex-direction: column;justify-content: space-between;">
-                            <div><img style="width: 2vw;height: 1vh;" src="@/assets/images/homeImages/up.png"></div>
-                            <div
-                                style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
-                                <div class="typeClass">
-                                    总设备数
-                                </div>
-                                <div class="countClass" style="color: #FEF822;">
-                                    {{device.total}}
-                                </div>
-                            </div>
-                            <div style="margin-left: 6vw;"><img style="width: 2vw;height: 1vh;"
-                                    src="@/assets/images/homeImages/bottom.png"></div>
-                        </div>
-                        <div class="countDiv"
-                            style="display: flex;flex-direction: column;justify-content: space-between;margin-top: 0.5vh;">
-                            <div><img style="width: 2vw;height: 1vh;" src="@/assets/images/homeImages/up.png"></div>
-                            <div
-                                style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
-                                <div class="typeClass">
-                                    在线设备
-                                </div>
-                                <div class="countClass" style="color: #22FE31;">
-                                    1
-                                </div>
-                            </div>
-                            <div style="margin-left: 6vw;"><img style="width: 2vw;height: 1vh;"
-                                    src="@/assets/images/homeImages/bottom.png"></div>
-                        </div>
-                        <div class="countDiv"
-                            style="display: flex;flex-direction: column;justify-content: space-between;margin-top: 0.5vh;">
-                            <div><img style="width: 2vw;height: 1vh;" src="@/assets/images/homeImages/up.png"></div>
-                            <div
-                                style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
-                                <div class="typeClass">
-                                    箱体总数
-                                </div>
-                                <div class="countClass" style="color: #FEF822;">
-                                    3200
-                                </div>
-                            </div>
-                            <div style="margin-left: 6vw;"><img style="width: 2vw;height: 1vh;"
-                                    src="@/assets/images/homeImages/bottom.png"></div>
-                        </div>
-                        <div class="countDiv"
-                            style="display: flex;flex-direction: column;justify-content: space-between;margin-top: 0.5vh;">
-                            <div><img style="width: 2vw;height: 1vh;" src="@/assets/images/homeImages/up.png"></div>
-                            <div
-                                style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
-                                <div class="typeClass">
-                                    空闲箱体
-                                </div>
-                                <div class="countClass" style="color: #22FE31;">
-                                    3100
-                                </div>
-                            </div>
-                            <div style="margin-left: 6vw;"><img style="width: 2vw;height: 1vh;"
-                                    src="@/assets/images/homeImages/bottom.png"></div>
-                        </div>
-                    </div>
+            <div class="countDiv" style="display: flex;flex-direction: column;justify-content: space-between;margin-top: 0.5vh;position:relative;">
+              <div><img style="width: 2vw;height: 1vh;position:absolute;top:0" src="@/assets/images/homeImages/up.png" /></div>
+              <div style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
+                <div class="typeClass">在线设备</div>
+                <div class="countClass" style="color: #22FE31;">{{ onlinedevice }}</div>
+              </div>
+              <div style="margin-left: 6vw;">
+                <img style="width: 2vw;height: 1vh;position:absolute; bottom:0;right:0" src="@/assets/images/homeImages/bottom.png" />
+              </div>
+            </div>
+            <div class="countDiv" style="display: flex;flex-direction: column;justify-content: space-between;margin-top: 0.5vh;position:relative;">
+              <div><img style="width: 2vw;height: 1vh;position:absolute;top:0" src="@/assets/images/homeImages/up.png" /></div>
+              <div style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
+                <div class="typeClass">箱体总数</div>
+                <div class="countClass" style="color: #FEF822;">{{ totalcabinet }}</div>
+              </div>
+              <div style="margin-left: 6vw;">
+                <img style="width: 2vw;height: 1vh;position:absolute; bottom:0;right:0" src="@/assets/images/homeImages/bottom.png" />
+              </div>
+            </div>
+            <div class="countDiv" style="display: flex;flex-direction: column;justify-content: space-between;margin-top: 0.5vh;position:relative;">
+              <div><img style="width: 2vw;height: 1vh;position:absolute;top:0" src="@/assets/images/homeImages/up.png" /></div>
+              <div style="display: flex;flex-direction: row;justify-content: space-between;padding-left: 0.5vw;padding-right: 1vw;">
+                <div class="typeClass">空闲箱体</div>
+                <div class="countClass" style="color: #22FE31;">{{ kxcabinet }}</div>
+              </div>
+              <div style="margin-left: 6vw;">
+                <img style="width: 2vw;height: 1vh; position:absolute; bottom:0;right:0" src="@/assets/images/homeImages/bottom.png" />
+              </div>
+            </div>
+          </div>
 
-                    <!-- <div style="width:10vw;margin-left: 1vw;padding-right: 1vw;">
+          <!-- <div style="width:10vw;margin-left: 1vw;padding-right: 1vw;">
                         <div
                             style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;">
                             <div class="stationkeyClass">设备总数</div>
@@ -101,239 +82,276 @@
                         </div>
                         <img class="imageDiv" src="@/assets/images/home/Bg(6).png" />
                     </div> -->
-                </div>
-            </div>
         </div>
+      </div>
     </div>
+  </div>
 </template>
 <script setup name="Index" lang="ts">
-    import * as echarts from 'echarts';
-    import { getDicts } from '@/api/system/dict/data'
-    import { getInfo, getInfoWait, getBoxInfo, getLock, openall } from "@/api/data"
+import * as echarts from 'echarts';
+import { getDicts } from '@/api/system/dict/data'
+import { getInfo, getInfoWait, getBoxInfo, getLock, openall } from "@/api/data"
+import { cabinetboxstatic,devicestatic } from '@/api/gpsData';
 
-    const stationchart = ref();
+const stationchart = ref();
 
-    const device = ref({
-        total: 0,
-        online: 0,
-        boxs: 0,
-        kongxian: 0
-    })
 
-    const getDeviceData = () => {
-        getDicts('tbl_sites').then(res => {
-            initSiteData(res)
-        })
+const totalcabinet = ref(0);
+const kxcabinet = ref(0);
+
+const totaldevice = ref(0);
+const onlinedevice = ref(0);
+
+const getBoxs = () => {
+  cabinetboxstatic().then((res) => {
+    totalcabinet.value = 0;
+    kxcabinet.value = 0;
+    for (let key in res) {
+      totalcabinet.value += res[key].total ?? 0;
+      kxcabinet.value += res[key].unuse ?? 0;
     }
+  });
+}
 
-    const isJSON = (str) => {
-        if (typeof str == 'string') {
-            try {
-                var obj = JSON.parse(str);
-                if (typeof obj == 'object' && obj) {
-                    return true;
-                } else {
-                    return false;
-                }
+const getdevices = () => {
+  devicestatic().then((res) => {
+    totaldevice.value = 0;
+    onlinedevice.value = 0;
+    for (let key in res) {
+      if (res[key]["name"] == "快递柜") {
+         totaldevice.value += 1;
+         onlinedevice.value += res[key].offline =="1"?0:1;
+      }
+
+    }
+    drawEchart()
+  });
+}
+
+
+const device = ref({
+    total: 0,
+    online: 0,
+    boxs: 0,
+    kongxian: 0
+})
 
-            } catch (e) {
+const getDeviceData = () => {
+    getDicts('tbl_sites').then(res => {
+        initSiteData(res)
+    })
+}
+
+const isJSON = (str) => {
+    if (typeof str == 'string') {
+        try {
+            var obj = JSON.parse(str);
+            if (typeof obj == 'object' && obj) {
+                return true;
+            } else {
                 return false;
             }
+
+        } catch (e) {
+            return false;
         }
     }
+}
 
-    const initSiteData = async (res) => {
-        console.log(device.value.total);
-        var total = 0
-        for (var index in res.data) {
-            // console.log(isNull(res.data[index].remark))
-            if (res.data[index].remark != null && res.data[index].remark != '' && isJSON(res.data[index].remark)) {
-                var devices = JSON.parse(res.data[index].remark)
-                total += devices.length
-                for (var i in devices) {
-                    if (devices[i].type == 'cabinet') {
-                        let boxinfo = null
-                        try {
-                             boxinfo =  await getInfo(devices[i].code);
-                        }
-                        catch (e) {
-                            // TODO sth with e
-                        }
-                        if(boxinfo != null){
-                             console.log(boxinfo);
-                        }
+const initSiteData = async (res) => {
+    console.log(device.value.total);
+    var total = 0
+    for (var index in res.data) {
+        // console.log(isNull(res.data[index].remark))
+        if (res.data[index].remark != null && res.data[index].remark != '' && isJSON(res.data[index].remark)) {
+            var devices = JSON.parse(res.data[index].remark)
+            total += devices.length
+            for (var i in devices) {
+                if (devices[i].type == 'cabinet') {
+                    let boxinfo = null
+                    try {
+                         boxinfo =  await getInfo(devices[i].code);
+                    }
+                    catch (e) {
+                        // TODO sth with e
+                    }
+                    if(boxinfo != null){
+                         console.log(boxinfo);
                     }
                 }
             }
         }
-        // device.value.total = total
     }
+    // device.value.total = total
+}
 
-    const drawEchart = () => {
-        let echartsObj = echarts.init(stationchart.value, "macarons");
-        var dateArray = getRecentDays();
-        var option = {
-            color: ['#707070', '#0EEFFF'],
-            title: {
-                // 图形标题(如果想要换行则使用ES6 `` 模板字符串)
-                // 例如: `示例
-                //   这里的文字会变为第二行(因为会保留格式)
-                text: '75%',
-                subtext: "在线率",
-                left: "center",//对齐方式居中
-                top: "40%",//距离顶部
-                textStyle: {//文字配置
-                    color: "#ffffff",//文字颜色
-                    fontSize: 30,//字号
-                    align: "center"//对齐方式
-                },
-                subtextStyle: {
-                    color: "#C1D2E4"
-                }
+const drawEchart = () => {
+    let echartsObj = echarts.init(stationchart.value, "macarons");
+    var dateArray = getRecentDays();
+    var option = {
+        color: ['#707070', '#0EEFFF'],
+        title: {
+            // 图形标题(如果想要换行则使用ES6 `` 模板字符串)
+            // 例如: `示例
+            //   这里的文字会变为第二行(因为会保留格式)
+            text: `${((onlinedevice.value/totaldevice.value)*100).toFixed(0)}%`,
+            subtext: "在线率",
+            left: "center",//对齐方式居中
+            top: "40%",//距离顶部
+            textStyle: {//文字配置
+                color: "#ffffff",//文字颜色
+                fontSize: 30,//字号
+                align: "center"//对齐方式
             },
-            series: [
-                {
-                    name: 'Access From',
-                    type: 'pie',
-                    radius: ['65%', '80%'],
-                    avoidLabelOverlap: false,
-                    label: {
-                        show: false,
-                        position: 'center'
-                    },
-                    labelLine: {
-                        show: false
-                    },
-                    data: [
-                        { value: 25, name: 'Search Engine' },
-                        { value: 75, name: 'Direct' },
-                    ]
-                }
-            ]
-        };
-        echartsObj.setOption(option);
-    }
+            subtextStyle: {
+                color: "#C1D2E4"
+            }
+        },
+        series: [
+            {
+                name: 'Access From',
+                type: 'pie',
+                radius: ['65%', '80%'],
+                avoidLabelOverlap: false,
+                label: {
+                    show: false,
+                    position: 'center'
+                },
+                labelLine: {
+                    show: false
+                },
+                data: [
+                    { value: totaldevice.value-onlinedevice.value, name: '在线' },
+                    { value: onlinedevice.value, name: '不在线' },
+                ]
+            }
+        ]
+    };
+    echartsObj.setOption(option);
+}
 
-    const getRecentDays = () => {
-        const oneDay = 24 * 60 * 60 * 1000; // 这里定义一天的毫秒数
-        const resultArray = [];
-        for (let i = 6; i >= 0; i--) {
-            const currentDate = new Date(Date.now() - i * oneDay); // 计算出每天的日期
-            const year = currentDate.getFullYear();
-            const month = String(currentDate.getMonth() + 1).padStart(2, "0"); // 月份需要补零
-            const day = String(currentDate.getDate()).padStart(2, "0"); // 日期也需要补零
-            const formattedDate = `${month}-${day}`; // 格式化日期为 yyyy-mm-dd 的形式
-            resultArray.push(formattedDate);
-        }
-        return resultArray;
+const getRecentDays = () => {
+    const oneDay = 24 * 60 * 60 * 1000; // 这里定义一天的毫秒数
+    const resultArray = [];
+    for (let i = 6; i >= 0; i--) {
+        const currentDate = new Date(Date.now() - i * oneDay); // 计算出每天的日期
+        const year = currentDate.getFullYear();
+        const month = String(currentDate.getMonth() + 1).padStart(2, "0"); // 月份需要补零
+        const day = String(currentDate.getDate()).padStart(2, "0"); // 日期也需要补零
+        const formattedDate = `${month}-${day}`; // 格式化日期为 yyyy-mm-dd 的形式
+        resultArray.push(formattedDate);
     }
+    return resultArray;
+}
 
 
-    onMounted(() => {
-        getDeviceData();
-        drawEchart();
-    })
+onMounted(() => {
+    getBoxs();
+  getdevices();
+    getDeviceData();
+    drawEchart();
+})
 </script>
 <style lang="scss">
-    .stationEchartsClass {
-        height: 20vh;
-        width: 20vw;
-
-        .titleBg {
-            background: url("@/assets/images/homeImages/titleBg.png") no-repeat;
-            background-size: 100% 100%;
-        }
-
-        .titleFont {
-            font-family: Source Han Sans CN, Source Han Sans CN;
-            font-weight: 400;
-            font-size: 18px;
-            color: #FFFFFF;
-            line-height: 4vh;
-            text-shadow: 0px 4px 0px rgba(10, 40, 95, 0.69);
-            text-align: left;
-            font-style: normal;
-            text-transform: none;
-            margin-left: 2vw;
-            letter-spacing: 5px;
-        }
-
-        .divContent {
-            background: url("@/assets/images/homeImages/contentBg.png") no-repeat;
-            background-size: 100% 100%;
-            width: 20vw;
-            height: 22vh;
-        }
+.stationEchartsClass {
+    height: 20vh;
+    width: 20vw;
 
+    .titleBg {
+        background: url("@/assets/images/homeImages/titleBg.png") no-repeat;
+        background-size: 100% 100%;
     }
 
-    .countDiv {
-        width: 8vw;
-        height: 4vh;
-        background-color: #375785;
-    }
-
-    .countClass {
+    .titleFont {
         font-family: Source Han Sans CN, Source Han Sans CN;
-        font-weight: bold;
+        font-weight: 400;
         font-size: 18px;
-        letter-spacing: 5px;
-        text-align: right;
-        font-style: normal;
-        text-transform: none;
-        line-height: 1vh;
-        height: 1vh;
-    }
-
-    .typeClass {
-        font-family: SourceHanSansCN-Regular, SourceHanSansCN-Regular;
-        font-weight: normal;
-        font-size: 14px;
-        color: #FFFFFE;
-        line-height: 1vh;
-        height: 1vh;
-        letter-spacing: 2px;
+        color: #FFFFFF;
+        line-height: 4vh;
+        text-shadow: 0px 4px 0px rgba(10, 40, 95, 0.69);
         text-align: left;
         font-style: normal;
         text-transform: none;
+        margin-left: 2vw;
+        letter-spacing: 5px;
     }
 
-    .stationkeyClass {
-        font-family: Source Han Sans CN, Source Han Sans CN;
-        font-weight: 400;
-        font-size: 14px;
-        color: #000000;
-        line-height: 1vh;
-        height: 1vh;
-        text-align: left;
-        font-style: normal;
-        text-transform: none;
+    .divContent {
+        background: url("@/assets/images/homeImages/contentBg.png") no-repeat;
+        background-size: 100% 100%;
+        width: 20vw;
+        height: 22vh;
     }
 
-    .stationvalueClass {
-        font-family: Source Han Sans CN, Source Han Sans CN;
-        font-weight: bold;
-        font-size: 24px;
-        color: #000000;
-        line-height: 11px;
-        text-align: right;
-        font-style: normal;
-        text-transform: none;
-    }
+}
 
-    .stationunitClass {
-        font-family: Source Han Sans CN, Source Han Sans CN;
-        font-weight: 400;
-        font-size: 12px;
-        color: #000000;
-        line-height: 11px;
-        text-align: left;
-        font-style: normal;
-        text-transform: none;
-    }
+.countDiv {
+    width: 8vw;
+    height: 4vh;
+    background-color: #375785;
+}
 
-    .imageDiv {
-        width: 9vw;
-        margin-top: 1vh;
-    }
+.countClass {
+    font-family: Source Han Sans CN, Source Han Sans CN;
+    font-weight: bold;
+    font-size: 18px;
+    letter-spacing: 5px;
+    text-align: right;
+    font-style: normal;
+    text-transform: none;
+    line-height: 1vh;
+    height: 1vh;
+}
+
+.typeClass {
+    font-family: SourceHanSansCN-Regular, SourceHanSansCN-Regular;
+    font-weight: normal;
+    font-size: 14px;
+    color: #FFFFFE;
+    line-height: 1vh;
+    height: 1vh;
+    letter-spacing: 2px;
+    text-align: left;
+    font-style: normal;
+    text-transform: none;
+}
+
+.stationkeyClass {
+    font-family: Source Han Sans CN, Source Han Sans CN;
+    font-weight: 400;
+    font-size: 14px;
+    color: #000000;
+    line-height: 1vh;
+    height: 1vh;
+    text-align: left;
+    font-style: normal;
+    text-transform: none;
+}
+
+.stationvalueClass {
+    font-family: Source Han Sans CN, Source Han Sans CN;
+    font-weight: bold;
+    font-size: 24px;
+    color: #000000;
+    line-height: 11px;
+    text-align: right;
+    font-style: normal;
+    text-transform: none;
+}
+
+.stationunitClass {
+    font-family: Source Han Sans CN, Source Han Sans CN;
+    font-weight: 400;
+    font-size: 12px;
+    color: #000000;
+    line-height: 11px;
+    text-align: left;
+    font-style: normal;
+    text-transform: none;
+}
+
+.imageDiv {
+    width: 9vw;
+    margin-top: 1vh;
+}
 </style>

+ 49 - 34
src/components/HomeComponents/warnTable.vue

@@ -1,46 +1,61 @@
 <template>
-    <div class="warnPageClass">
-        <div class="messagePageClass">
-            <div class="titleBg">
-                <div class="titleFont">设备报警</div>
-            </div>
-            <div class="divContent">
-                <div style="padding-left: 1vw;max-height: 30vh;overflow-y: scroll;" class="tableClass">
-                    <div v-for="(item, index) in messageList" style="margin-top:20px;">
-                        <div
-                            style="display: flex;flex-direction: row;justify-content: space-around;align-items: center;">
-                            <div>
-                                <img v-if="item.type == 1" src="@/assets/images/home/Rectangle8.png" />
-                                <img v-if="item.type == 2" src="@/assets/images/home/Rectangle8(1).png" />
-                            </div>
-                            <div class="contentClass">{{ item.content }}</div>
-                            <div class="timeClass">{{ item.time }}</div>
-                        </div>
-                        <el-divider />
-                    </div>
-                </div>
+  <div class="warnPageClass">
+    <div class="messagePageClass">
+      <div class="titleBg">
+        <div class="titleFont">设备告警</div>
+      </div>
+      <div class="divContent">
+        <div style="padding-left: 1vw;max-height: 30vh;overflow-y: scroll;" class="tableClass">
+          <div v-for="(item, index) in messageList" style="margin-top:20px;" :key="index">
+            <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: center;">
+              <div>
+                <img v-if="item.type == 1" src="@/assets/images/home/Rectangle8.png" />
+                <img v-if="item.type == 2" src="@/assets/images/home/Rectangle8(1).png" />
+              </div>
+              <div class="contentClass">{{ item.content }}</div>
+              <div class="timeClass">{{moment(item.time).format("MM/DD HH:mm") }}</div>
             </div>
+            <el-divider />
+          </div>
         </div>
-        <!-- <div class="title">告警信息</div>-->
+      </div>
     </div>
+    <!-- <div class="title">告警信息</div>-->
+  </div>
 </template>
 
 <script setup name="CarInfo" lang="ts">
+import { offlinelist } from '@/api/gpsData';
+import moment from 'moment';
+
+const messageList = ref([]);
+
+const getList = () => {
+  offlinelist().then(res => {
+    let msg: any[] = [];
+    Object.keys(res).forEach(i => {
+      let d = res[i];
+      if (d["station"].indexOf("闽") != -1) {
+        d["type"] = 1;
+        d["content"] = d["station"] + "Gps离线,请及时处理!";
+      } else {
+        d["type"] = 2;
+         d["content"] = d["station"] + "快递柜离线,请及时处理!";
+      }
+      msg.push(res[i]);
+    })
+    //排序
+    msg = msg.sort((a, b) => {
+      return moment(a.time).unix() - moment(b.time).unix();
+    })
+    messageList.value = msg;
+
+  })
+};
 
-const messageList = ref([{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 }
-]);
 
 onMounted(() => {
-    // getList();
+    getList();
 });
 </script>
 <style scoped lang="scss">
@@ -165,4 +180,4 @@ onMounted(() => {
     width: 5vw;
     text-align: center;
 }
-</style>
+</style>

+ 2 - 4
src/components/HomeStatics/countPage.vue

@@ -38,9 +38,7 @@ const getCountDataList = () => {
             endtime: endDate
         }
     }
-    console.log(obj)
     getCountData(obj).then(res=>{
-        console.log(res)
         people.value = res.data.totalin
     })
 }
@@ -49,7 +47,7 @@ const getlistGoodsOrder = () =>{
     var gotime =  moment(new Date()).format('YYYY-MM-DD 00:00:00')
     listGoodsOrder({pageSize:1000,gotime:gotime}).then(res=>{
         goods.value = res.rows.length
-    }) 
+    })
 }
 
 
@@ -140,4 +138,4 @@ onMounted(() => {
     font-style: normal;
     text-transform: none;
 }
-</style>
+</style>

+ 28 - 20
src/components/HomeStatics/messageTable.vue

@@ -1,32 +1,40 @@
 <template>
-    <div class="countPageClass" style="padding-left: 1vw;padding-top: 1.5vh;padding-right: 2vw;">
-        <div> 
-            <div class="title" style="padding-left: 0.5vw;">设备报警</div>
-            <div style="margin-left: 1vw;max-height: 20vh;overflow-y: scroll;" class="tableClass">
-                <div v-for="(item, index) in messageList">
-                    <div style="display: flex;flex-direction: row;justify-content: space-around;margin-top: 20px;">
-                        <div :class="item.type == 1 ? 'carClass' : 'goodClass'">{{ item.carNum }}</div>
-                        <div class="contentClass">{{ item.content }}</div>
-                        <div class="stationClass">{{ item.station }}</div>
-                        <div class="timeClass">{{ item.time }}</div>
-                    </div>
-                    <el-divider />
-                </div>
-            </div>
+  <div class="countPageClass" style="padding-left: 1vw;padding-top: 1.5vh;padding-right: 2vw;">
+    <div>
+      <div class="title" style="padding-left: 0.5vw;">车辆报站</div>
+      <div style="margin-left: 1vw;max-height: 20vh;overflow-y: scroll;" class="tableClass">
+        <div v-for="(item, index) in messageList" :key="index">
+          <div style="display: flex;flex-direction: row;justify-content: space-around;margin-top: 20px;">
+            <div :class="item.type == '1' ? 'carClass' : 'goodClass'">{{ item.carNum }}</div>
+            <div class="contentClass">{{ "即将到达" }}</div>
+            <div class="stationClass">{{ item.station }}</div>
+            <div class="timeClass">{{ moment(item.time).format("MM/DD HH:mm") }}</div>
+          </div>
+          <el-divider />
         </div>
+      </div>
     </div>
+  </div>
 </template>
 
 <script setup name="CarInfo" lang="ts">
+import moment from 'moment';
+import { playlist } from '@/api/gpsData';
 
-const messageList = ref([{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '即将到达', station: '铁湖站', time: '5/10 17:26', type: 1 }
+
+const messageList = ref([
 ]);
 
+const getList = () => {
+    playlist().then(res => {
+        console.log(res);
+        messageList.value = res;
+    });
+};
+
+
 onMounted(() => {
-    // getList();
+    getList();
 });
 </script>
 <style scoped lang="scss">
@@ -123,4 +131,4 @@ onMounted(() => {
     height: 24px;
     line-height: 24px;
 }
-</style>
+</style>

+ 4 - 5
src/components/HomeStatics/pieEcharts.vue

@@ -20,7 +20,7 @@ const initData = async () => {
     var total = carTotal.total
     const data = await getDicts('tbl_car_type')
     carTypeList.value = data.data
-    console.log(carTypeList.value)
+
     var label = {
         normal: {
             formatter: '{c|{c}}'+"\n\n"+'{b|{b}} ',
@@ -46,12 +46,11 @@ const initData = async () => {
         length2: 50
     }
     for (var index in carTypeList.value) {
-        console.log(carTypeList.value[0])
+
         var obj = {
             pageSize: 1000,
             carType: carTypeList.value[index].dictValue
         }
-        console.log(obj)
         const res = await listCarInfo(obj);
         total = total - res.total
         var cObj = {
@@ -69,7 +68,7 @@ const initData = async () => {
 const getDictsData = (param, obj) => {
     getDicts(param).then(res => {
         obj.value = res.data;
-        console.log(carTypeList.value)
+
     })
 }
 
@@ -160,4 +159,4 @@ onMounted(() => {
         text-transform: none;
     }
 }
-</style>
+</style>

+ 71 - 36
src/components/HomeStatics/stationPie.vue

@@ -1,52 +1,85 @@
 <template>
-    <div class="lineEchartsClass" style="padding-left: 1vw;padding-top: 1vh;">
-        <div class="title">电子站台统计</div>
-        <div style="display: flex;flex-direction: row;margin-top: 1vh;padding-left: 1vw;">
-            <div ref="stationchart" style="width:11vw;height: 20vh;"></div>
-            <div style="width:10vw;margin-left: 1vw;padding-right: 1vw;height: 20vh;justify-content: center;display: flex;flex-direction: column;">
-                <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;">
-                    <div class="stationkeyClass">设备总数</div>
-                    <div class="stationvalueClass">80</div>
-                    <div class="stationunitClass">台</div>
-                </div>
-                <img class="imageDiv" src="@/assets/images/home/Bg(4).png"/>
-                <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;margin-top: 1vh;">
-                    <div class="stationkeyClass">在线设备</div>
-                    <div class="stationvalueClass">1</div>
-                    <div class="stationunitClass">台</div>
-                </div>
-                <img class="imageDiv" src="@/assets/images/home/Bg(7).png"/>
-                <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;margin-top: 1vh;">
-                    <div class="stationkeyClass">箱体总数</div>
-                    <div class="stationvalueClass">3200</div>
-                    <div class="stationunitClass">台</div>
-                </div>
-                <img class="imageDiv" src="@/assets/images/home/Bg(5).png"/>
-                <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;margin-top: 1vh;">
-                    <div class="stationkeyClass">空闲箱体</div>
-                    <div class="stationvalueClass">3100</div>
-                    <div class="stationunitClass">台</div>
-                </div>
-                <img class="imageDiv" src="@/assets/images/home/Bg(6).png"/>
-            </div>
+  <div class="lineEchartsClass" style="padding-left: 1vw;padding-top: 1vh;">
+    <div class="title">电子站台统计</div>
+    <div style="display: flex;flex-direction: row;margin-top: 1vh;padding-left: 1vw;">
+      <div ref="stationchart" style="width:11vw;height: 20vh;"></div>
+      <div style="width:10vw;margin-left: 1vw;padding-right: 1vw;height: 20vh;justify-content: center;display: flex;flex-direction: column;">
+        <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;">
+          <div class="stationkeyClass">设备总数</div>
+          <div class="stationvalueClass">{{ totaldevice }}</div>
+          <div class="stationunitClass">台</div>
         </div>
+        <img class="imageDiv" src="@/assets/images/home/Bg(4).png" />
+        <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;margin-top: 1vh;">
+          <div class="stationkeyClass">在线设备</div>
+          <div class="stationvalueClass">{{ onlinedevice }}</div>
+          <div class="stationunitClass">台</div>
+        </div>
+        <img class="imageDiv" src="@/assets/images/home/Bg(7).png" />
+        <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;margin-top: 1vh;">
+          <div class="stationkeyClass">箱体总数</div>
+          <div class="stationvalueClass">{{ totalcabinet }}</div>
+          <div class="stationunitClass">台</div>
+        </div>
+        <img class="imageDiv" src="@/assets/images/home/Bg(5).png" />
+        <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: start;margin-top: 1vh;">
+          <div class="stationkeyClass">空闲箱体</div>
+          <div class="stationvalueClass">{{ kxcabinet }}</div>
+          <div class="stationunitClass">台</div>
+        </div>
+        <img class="imageDiv" src="@/assets/images/home/Bg(6).png" />
+      </div>
     </div>
+  </div>
 </template>
-<script setup name="Index" lang="ts">
+<script setup name="Index">
+import { cabinetboxstatic,devicestatic } from '@/api/gpsData';
 import * as echarts from 'echarts';
 
 const stationchart = ref();
 
+const totalcabinet = ref(0);
+const kxcabinet = ref(0);
+
+const totaldevice = ref(0);
+const onlinedevice = ref(0);
+
+
+const getBoxs = () => {
+  cabinetboxstatic().then((res) => {
+    totalcabinet.value = 0;
+    kxcabinet.value = 0;
+    for (let key in res) {
+      totalcabinet.value += res[key].total ?? 0;
+      kxcabinet.value += res[key].unuse ?? 0;
+    }
+  });
+}
+
+const getdevices = () => {
+  devicestatic().then((res) => {
+    totaldevice.value = 0;
+    onlinedevice.value = 0;
+    for (let key in res) {
+      if (res[key]["name"] == "快递柜") {
+         totaldevice.value += 1;
+         onlinedevice.value += res[key].offline =="1"?0:1;
+      }
+    }
+    drawEchart()
+  });
+}
+
+
 const drawEchart = () => {
     let echartsObj = echarts.init(stationchart.value, "macarons");
-    var dateArray = getRecentDays();
     var option = {
         color:['#707070','#26EB96'],
         title: {
             // 图形标题(如果想要换行则使用ES6 `` 模板字符串)
             // 例如: `示例
             //   这里的文字会变为第二行(因为会保留格式)
-            text: '75%',
+            text: `${((onlinedevice.value/totaldevice.value)*100).toFixed(0)}%`,
             subtext: "在线率",
             left: "center",//对齐方式居中
             top: "35%",//距离顶部
@@ -73,8 +106,8 @@ const drawEchart = () => {
                     show: false
                 },
                 data: [
-                    { value: 25, name: 'Search Engine' },
-                    { value: 75, name: 'Direct' },
+                    { value: totaldevice.value-onlinedevice.value, name: '在线' },
+                    { value: onlinedevice.value, name: '不在线' },
                 ]
             }
         ]
@@ -98,6 +131,8 @@ const getRecentDays = () => {
 
 
 onMounted(() => {
+  getBoxs();
+  getdevices();
     drawEchart();
 })
 </script>
@@ -158,4 +193,4 @@ onMounted(() => {
     width: 9vw;
     margin-top: 1vh;
 }
-</style>
+</style>

+ 43 - 21
src/components/HomeStatics/warnTable.vue

@@ -1,32 +1,54 @@
 <template>
-    <div class="countPageClass" style="padding-left: 1vw;padding-top: 1.5vh;padding-right: 2vw;">
-        <div class="title">告警信息</div>
-        <div style="padding-left: 1vw;max-height: 20vh;overflow-y: scroll;" class="tableClass">
-            <div v-for="(item, index) in messageList" style="margin-top:20px;" >
-                <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: center;">
-                    <div>
-                        <img v-if="item.type == 1" src="@/assets/images/home/Rectangle8.png" />
-                        <img v-if="item.type == 2" src="@/assets/images/home/Rectangle8(1).png" />
-                    </div>
-                    <div class="contentClass">{{ item.content }}</div>
-                    <div class="timeClass">{{ item.time }}</div>
-                </div>
-                <el-divider />
-            </div>
+  <div class="countPageClass" style="padding-left: 1vw;padding-top: 1.5vh;padding-right: 2vw;">
+    <div class="title">设备告警</div>
+    <div style="padding-left: 1vw;max-height: 20vh;overflow-y: scroll;" class="tableClass">
+      <div v-for="(item, index) in messageList" style="margin-top:20px;" :key="index">
+        <div style="display: flex;flex-direction: row;justify-content: space-around;align-items: center;">
+          <div>
+            <img v-if="item.type == 1" src="@/assets/images/home/Rectangle8.png" />
+            <img v-if="item.type == 2" src="@/assets/images/home/Rectangle8(1).png" />
+          </div>
+          <div class="contentClass">{{ item.content }}</div>
+          <div class="timeClass">{{moment(item.time).format("MM/DD HH:mm") }}</div>
         </div>
+        <el-divider />
+      </div>
     </div>
+  </div>
 </template>
 
 <script setup name="CarInfo" lang="ts">
+import { offlinelist} from '@/api/gpsData';
+import moment from 'moment';
+
+const messageList = ref([]);
+
+const getList = () => {
+  offlinelist().then(res => {
+    let msg: any[] = [];
+    Object.keys(res).forEach(i => {
+      let d = res[i];
+      if (d["station"].indexOf("闽") != -1) {
+        d["type"] = 1;
+        d["content"] = d["station"] + "Gps离线,请及时处理!";
+      } else {
+        d["type"] = 2;
+         d["content"] = d["station"] + "快递柜离线,请及时处理!";
+      }
+      msg.push(res[i]);
+    })
+    //排序
+    msg = msg.sort((a, b) => {
+      return moment(a.time).unix() - moment(b.time).unix();
+    })
+    messageList.value = msg;
+
+  })
+};
 
-const messageList = ref([{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 2 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 },
-{ carNum: '闽JY3013', content: '闽J-Y3013车辆未到站报警,请及时处理。', station: '铁湖站', time: '5/10 17:26', type: 1 }
-]);
 
 onMounted(() => {
-    // getList();
+    getList();
 });
 </script>
 <style scoped lang="scss">
@@ -120,4 +142,4 @@ onMounted(() => {
     width: 5vw;
     text-align: center;
 }
-</style>
+</style>

+ 4 - 9
src/components/Map/editMap.vue

@@ -61,7 +61,6 @@ const iconImage = new URL("@/assets/images/home/Point.png", import.meta.url);
 
 const getCarInfoList = () => {
     listCarInfo({ pageSzie: 1000 }).then(res => {
-        console.log(res)
         for (var index in res.rows) {
             var obj = res.rows[index].location;
             // console.log(obj.toString())
@@ -97,7 +96,6 @@ const getDictsData = (param) => {
 
 const getGpsDataList = (param) => {
     getGpsData(param).then(res => {
-        console.log(res);
         addLine(res.rows);
         if (singleMarker.value != null) {
             mapObj.value.remove(singleMarker.value);
@@ -149,10 +147,7 @@ const initMap = () => {
             center: [119.807462, 26.958413], //初始化地图中心点位置
         });
 
-        console.log(11111111111);
-        console.log(map)
         mapObj.value = map;
-        console.log(map)
         if (props.darkType) {
             var styleName = "amap://styles/darkblue";
             map.setMapStyle(styleName);
@@ -284,8 +279,8 @@ const formatGCJ = (lng, lat) => {
 
     /**
      * 纬度转换
-     * @param { Number } lng 
-     * @param { Number } lat 
+     * @param { Number } lng
+     * @param { Number } lat
      */
     function transformlng(lng, lat) {
         var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
@@ -297,8 +292,8 @@ const formatGCJ = (lng, lat) => {
 
     /**
      * 判断是否在国内,不在国内则不做偏移
-     * @param {*} lng 
-     * @param {*} lat 
+     * @param {*} lng
+     * @param {*} lat
      */
     function outOfChina(lng, lat) {
         return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false)

+ 9 - 12
src/components/Map/index.vue

@@ -52,7 +52,6 @@
 
     const getGpsDataList = (param) => {
         getGpsData(param).then(res => {
-            console.log(res);
             addLine(res.rows);
             if (singleMarker.value != null) {
                 mapObj.value.remove(singleMarker.value);
@@ -85,15 +84,13 @@
                 zoom: 13,           //初始化地图级别
                 center: [119.807462, 26.958413], //初始化地图中心点位置
             });
-            console.log(11111111111);
-            console.log(props.darkType)
+
             if (props.darkType) {
                 var styleName = "amap://styles/darkblue";
                 map.setMapStyle(styleName);
             }
-            console.log(map)
+
             mapObj.value = map;
-            console.log(map)
             // 添加插件
             // AMap.plugin(["AMap.ToolBar", "AMap.Scale", "AMap.HawkEye", "AMap.Geolocation", "AMap.MapType", "AMap.MouseTool"], function () {
             //     //异步同时加载多个插件
@@ -155,9 +152,9 @@
                     var styleName = "amap://styles/darkblue";
                     map.setMapStyle(styleName);
                 }
-                console.log(map)
+
                 mapObj.value = map;
-                console.log(map)
+
                 // 添加插件
                 // AMap.plugin(["AMap.ToolBar", "AMap.Scale", "AMap.HawkEye", "AMap.Geolocation", "AMap.MapType", "AMap.MouseTool"], function () {
                 //     //异步同时加载多个插件
@@ -292,8 +289,8 @@
 
         /**
          * 纬度转换
-         * @param { Number } lng 
-         * @param { Number } lat 
+         * @param { Number } lng
+         * @param { Number } lat
          */
         function transformlng(lng, lat) {
             var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
@@ -305,8 +302,8 @@
 
         /**
          * 判断是否在国内,不在国内则不做偏移
-         * @param {*} lng 
-         * @param {*} lat 
+         * @param {*} lng
+         * @param {*} lat
          */
         function outOfChina(lng, lat) {
             return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false)
@@ -336,4 +333,4 @@
     background-color: transparent;
     color: #ffffff;
 } */
-</style>
+</style>

+ 5 - 9
src/components/Map/map.vue

@@ -44,7 +44,6 @@ const iconImage = new URL("@/assets/images/home/Point.png",import.meta.url);
 
 const getCarInfoList = () => {
     listCarInfo({pageSzie:1000}).then(res=>{
-            console.log(res)
             for (var index in res.rows) {
             var obj = res.rows[index].location;
             // console.log(obj.toString())
@@ -70,7 +69,6 @@ const getDictsData = (param) => {
 
 const getGpsDataList = (param) => {
     getGpsData(param).then(res => {
-        console.log(res);
         addLine(res.rows);
         if (singleMarker.value != null) {
             mapObj.value.remove(singleMarker.value);
@@ -103,10 +101,8 @@ const initMap = () => {
             zoom: 13,           //初始化地图级别
             center: [119.807462, 26.958413], //初始化地图中心点位置
         });
-        console.log(11111111111);
-        console.log(map)
         mapObj.value = map;
-        console.log(map)
+
         if (props.darkType) {
             var styleName = "amap://styles/8b9b98f3e261fb3096f4425490da9c5d";
             map.setMapStyle(styleName);
@@ -253,8 +249,8 @@ const formatGCJ = (lng, lat) => {
 
     /**
      * 纬度转换
-     * @param { Number } lng 
-     * @param { Number } lat 
+     * @param { Number } lng
+     * @param { Number } lat
      */
     function transformlng(lng, lat) {
         var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng))
@@ -266,8 +262,8 @@ const formatGCJ = (lng, lat) => {
 
     /**
      * 判断是否在国内,不在国内则不做偏移
-     * @param {*} lng 
-     * @param {*} lat 
+     * @param {*} lng
+     * @param {*} lat
      */
     function outOfChina(lng, lat) {
         return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false)

+ 2 - 3
src/components/Map/videoMap.vue

@@ -66,7 +66,6 @@ const closeVideo = () =>{
 
 const getGpsDataList = (param) => {
     getGpsData(param).then(res => {
-        console.log(res);
         addLine(res.rows);
         if (singleMarker.value != null) {
             mapObj.value.remove(singleMarker.value);
@@ -87,10 +86,10 @@ const setDataList = (data) => {
 
 const initMap = () => {
     window._AMapSecurityConfig = {
-        securityJsCode: '8e920f73eb2e6880a92ea6662eefc476',
+        securityJsCode: 'b16e0ff6d065a3b8a87e6c448e982ca4',
     }
     AMapLoader.load({
-        key: "88d0fc14bcd5921a4e5a09ef1a3ab31a", // 申请好的Web端开发者Key,首次调用 load 时必填
+        key: "c60c1af6d4f39c5220f3ad36298a8830", // 申请好的Web端开发者Key,首次调用 load 时必填
         version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
         // plugins:[''], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
     }).then(async (AMap) => {

+ 304 - 388
src/views/car/carInfo/add.vue

@@ -1,390 +1,308 @@
 <template>
-    <div style="padding: 10px 15px">
-        <el-card class="box-card">
-            <template #header>
-                <div class="card-header">
-                    <span>车辆信息</span>
-                    <div>
-                        <el-button type="warning" @click="goBack()">取消</el-button>
-                        <el-button :loading="buttonLoading" type="primary" @click="submit()">保存</el-button>
-                    </div>
+  <div style="padding: 10px 15px">
+    <el-card class="box-card">
+      <template #header>
+        <div class="card-header">
+          <span>车辆信息</span>
+          <div>
+            <el-button type="warning" @click="goBack()">取消</el-button>
+            <el-button :loading="buttonLoading" type="primary" @click="submit()">保存</el-button>
+          </div>
+        </div>
+      </template>
+      <el-row>
+        <el-col :span="24">
+          <el-descriptions :column="3">
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 车牌</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="form.carNum" placeholder="请输入车牌" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 车辆分类</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="form.carType" filterable placeholder="车辆分类">
+                  <el-option v-for="item in carTypeList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 业务分类</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="formParams.bussinessType" filterable placeholder="业务分类">
+                  <el-option v-for="item in bussinessTypeList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 所属网格</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="formParams.wangge" placeholder="请输入网格" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 能耗类型</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="formParams.energyType" filterable placeholder="业务分类">
+                  <el-option v-for="item in energyTypeList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 所属单位</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="formParams.dept" placeholder="请输入所属单位" />
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">车辆编号</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="formParams.carNo" placeholder="请输入车牌编号" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">车辆识别号</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.Identification" placeholder="请输入车牌识别号" />
                 </div>
-
-            </template>
-            <el-row>
-                <el-col :span="24">
-                    <el-descriptions :column="3">
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 车牌
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="form.carNum" placeholder="请输入车牌" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 车辆分类
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="form.carType" filterable placeholder="车辆分类">
-                                    <el-option v-for="item in carTypeList" :key="item.dictValue" :label="item.dictLabel"
-                                        :value="item.dictValue" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 业务分类
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="formParams.bussinessType" filterable placeholder="业务分类">
-                                    <el-option v-for="item in bussinessTypeList" :key="item.dictValue"
-                                        :label="item.dictLabel" :value="item.dictValue" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 所属网格
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="formParams.wangge" placeholder="请输入网格" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 能耗类型
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="formParams.energyType" filterable placeholder="业务分类">
-                                    <el-option v-for="item in energyTypeList" :key="item.dictValue"
-                                        :label="item.dictLabel" :value="item.dictValue" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 所属单位
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="formParams.dept" placeholder="请输入所属单位" />
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    车辆编号
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="formParams.carNo" placeholder="请输入车牌编号" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    车辆识别号
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.Identification" placeholder="请输入车牌识别号" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    发动机号
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.fdj" placeholder="请输入发动机" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    行驶证编号
-                                </div>
-
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="formParams.xszbh" placeholder="请输入行驶证编号" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    行驶证保管人
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.xszbgr" placeholder="请输入行驶证保管人" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    采购审批单号
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.cgsp" placeholder="请输入采购审批单号" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    车辆品牌
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="formParams.clpp" placeholder="请输入车牌品牌" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    车辆信号
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.clxx" placeholder="请输入车辆信号" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    购置日期
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-date-picker value-format="YYYY-MM-DD HH:mm:ss" v-model="formParams.gzrq"
-                                        type="date" placeholder="请选择购置日期" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    购置金额
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="formParams.gzje" placeholder="请输入购置金额" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    使用年限
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.synx" placeholder="请输入使用年限" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    额定载重
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.edzz" placeholder="请输入额定载重" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    使用单位
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <div class="content-w">
-                                    <el-input v-model="formParams.sydw" placeholder="请输入使用单位" />
-                                </div>
-                            </div>
-                        </el-descriptions-item>
-                    </el-descriptions>
-
-                    <el-descriptions :column="3">
-                        <el-descriptions-item>
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 路线
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="ext2.pathId" filterable placeholder="业务分类">
-                                    <el-option v-for="item in carPathList" :key="item.id" :label="item.name"
-                                        :value="item.id" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red">*</span> 司机
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="ext2.driverInfo" class="m-2" placeholder="请选择司机"
-                                    style="width: 240px">
-                                    <el-option v-for="item in sjList" :key="item.userId" :label="item.nickName"
-                                        :value="item.userId" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-
-                        <el-descriptions-item>
-                            <template #label>
-                                <div style="display: inline-block;min-width: 100px;text-align: right">
-                                    <span style="color: red"></span> 跟车人员
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="ext2.attendantInfo" class="m-2" placeholder="请选择跟车人员"
-                                    style="width: 240px">
-                                    <el-option v-for="item in ckList" :key="item.userId" :label="item.nickName"
-                                        :value="item.userId" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-                    </el-descriptions>
-
-                </el-col>
-
-                <div style="margin-left: auto;margin-right: 20px;" v-if="carId != 0 && carId != null"><el-button
-                        type="primary" @click="addObj()">新增</el-button></div>
-
-                <el-col :span="24" v-if="carId != 0 && carId != null">
-                    <el-tabs type="card" class="demo-tabs" v-model="activeName" @tab-click="tabClick">
-                        <el-tab-pane label="车辆设备" name="1">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 1" :columns="columns[0]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                        <el-tab-pane label="维修记录" name="2">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 2" :columns="columns[1]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                        <el-tab-pane label="保养记录" name="3">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 3" :columns="columns[2]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                        <el-tab-pane label="保险记录" name="4">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 4" :columns="columns[3]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                        <el-tab-pane label="年检记录" name="5">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 5" :columns="columns[4]"
-                                ref="table">
-                            </tableElm>
-
-                        </el-tab-pane>
-                        <el-tab-pane label="交通事故记录" name="6">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 6" :columns="columns[5]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                        <el-tab-pane label="违章记录" name="7">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 7" :columns="columns[6]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                        <el-tab-pane label="车辆变更记录" name="8">
-                            <tableElm @childToParent='childrenClick' v-if="activeName == 8" :columns="columns[7]"
-                                ref="table">
-                            </tableElm>
-                        </el-tab-pane>
-                    </el-tabs>
-                </el-col>
-            </el-row>
-        </el-card>
-
-        <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-            <el-form ref="" :model="form" :rules="rules" label-width="120px">
-                <el-form-item v-for="(item, index) in formList" :label="item.label" prop="carNum">
-                    <el-input v-if="item.type == 'input'" v-model="addForm[item.prop]"
-                        :placeholder="item.placeholder" />
-                    <el-date-picker v-if="item.type == 'date'" value-format="YYYY-MM-DD HH:mm:ss"
-                        v-model="addForm[item.prop]" type="date" :placeholder="item.placeholder" />
-                    <el-upload v-if="item.type == 'image'" v-model:file-list="fileList"
-                        :headers="headers"
-                        :action="uploadImgUrl" list-type="picture-card"
-                        :on-remove="handleRemove"  :on-success="handleUploadSuccess">
-                        <el-icon>
-                            <Plus />
-                        </el-icon>
-                    </el-upload>
-                </el-form-item>
-            </el-form>
-
-            <template #footer>
-                <div class="dialog-footer">
-                    <el-button type="primary" @click="submitForm">确 定</el-button>
-                    <el-button @click="dialog.visible = false">取 消</el-button>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">发动机号</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.fdj" placeholder="请输入发动机" />
+                </div>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">行驶证编号</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="formParams.xszbh" placeholder="请输入行驶证编号" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">行驶证保管人</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.xszbgr" placeholder="请输入行驶证保管人" />
+                </div>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">采购审批单号</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.cgsp" placeholder="请输入采购审批单号" />
+                </div>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">车辆品牌</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="formParams.clpp" placeholder="请输入车牌品牌" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">车辆信号</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.clxx" placeholder="请输入车辆信号" />
+                </div>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">购置日期</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-date-picker value-format="YYYY-MM-DD HH:mm:ss" v-model="formParams.gzrq" type="date" placeholder="请选择购置日期" />
                 </div>
-            </template>
-        </el-dialog>
-    </div>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">购置金额</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="formParams.gzje" placeholder="请输入购置金额" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">使用年限</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.synx" placeholder="请输入使用年限" />
+                </div>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">额定载重</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.edzz" placeholder="请输入额定载重" />
+                </div>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right">使用单位</div>
+              </template>
+              <div class="content-w">
+                <div class="content-w">
+                  <el-input v-model="formParams.sydw" placeholder="请输入使用单位" />
+                </div>
+              </div>
+            </el-descriptions-item>
+          </el-descriptions>
+
+          <el-descriptions :column="3">
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 路线</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="ext2.pathId" filterable placeholder="业务分类">
+                  <el-option v-for="item in carPathList" :key="item.id" :label="item.name" :value="item.id" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red">*</span> 司机</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="ext2.driverInfo" class="m-2" placeholder="请选择司机" style="width: 240px">
+                  <el-option v-for="item in sjList" :key="item.userId" :label="item.nickName" :value="item.userId" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 100px;text-align: right"><span style="color: red"></span> 跟车人员</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="ext2.attendantInfo" class="m-2" placeholder="请选择跟车人员" style="width: 240px">
+                  <el-option v-for="item in ckList" :key="item.userId" :label="item.nickName" :value="item.userId" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+          </el-descriptions>
+        </el-col>
+
+        <div style="margin-left: auto;margin-right: 20px;" v-if="carId != 0 && carId != null">
+          <el-button type="primary" @click="addObj()">新增</el-button>
+        </div>
+
+        <el-col :span="24" v-if="carId != 0 && carId != null">
+          <el-tabs type="card" class="demo-tabs" v-model="activeName" @tab-click="tabClick">
+            <el-tab-pane label="车辆设备" name="1">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 1" :columns="columns[0]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="维修记录" name="2">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 2" :columns="columns[1]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="保养记录" name="3">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 3" :columns="columns[2]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="保险记录" name="4">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 4" :columns="columns[3]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="年检记录" name="5">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 5" :columns="columns[4]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="交通事故记录" name="6">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 6" :columns="columns[5]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="违章记录" name="7">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 7" :columns="columns[6]" ref="table"> </tableElm>
+            </el-tab-pane>
+            <el-tab-pane label="车辆变更记录" name="8">
+              <tableElm @childToParent="childrenClick" v-if="activeName == 8" :columns="columns[7]" ref="table"> </tableElm>
+            </el-tab-pane>
+          </el-tabs>
+        </el-col>
+      </el-row>
+    </el-card>
+
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
+      <el-form ref="" :model="form" :rules="rules" label-width="120px">
+        <el-form-item v-for="(item, index) in formList" :label="item.label" prop="carNum">
+          <el-input v-if="item.type == 'input'" v-model="addForm[item.prop]" :placeholder="item.placeholder" />
+          <el-date-picker
+            v-if="item.type == 'date'"
+            value-format="YYYY-MM-DD HH:mm:ss"
+            v-model="addForm[item.prop]"
+            type="date"
+            :placeholder="item.placeholder"
+          />
+          <el-upload
+            v-if="item.type == 'image'"
+            v-model:file-list="fileList"
+            :headers="headers"
+            :action="uploadImgUrl"
+            list-type="picture-card"
+            :on-remove="handleRemove"
+            :on-success="handleUploadSuccess"
+          >
+            <el-icon>
+              <Plus />
+            </el-icon>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="dialog.visible = false">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
 </template>
 
 <script setup name="CarInfo" lang="ts">
@@ -603,7 +521,7 @@ const handleUploadSuccess = (response, file, fileList) =>{
             url:response.data.url.replaceAll("http://127.0.0.1:9000","https://khy.xiaole.vip/khyfile").split('?')[0],
             ossId:response.data.ossId
         }
-     } 
+     }
      fileData.value.push(obj)
 }
 
@@ -734,7 +652,6 @@ const setTableData = (tab) => {
 
 const setData = async (id) => {
     const res = await getCarInfo(id);
-    console.log(res)
     formParams.value = JSON.parse(res.data.ext1)
     if (res.data.ext2 != null) {
         ext2.value = JSON.parse(res.data.ext2)
@@ -795,7 +712,6 @@ reset();
 setTimeout(() => {
     getData();
 }, 100);
-
 </script>
 
 <style lang="scss" scoped>
@@ -809,4 +725,4 @@ setTimeout(() => {
     display: inline-flex;
     max-width: 160px;
 }
-</style>
+</style>

+ 12 - 11
src/views/car/carInfo/index.vue

@@ -9,24 +9,26 @@
               <el-input v-model="queryParams.carNum" placeholder="请输入车牌号" clearable style="width: 160px"
                 @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="驾驶员" prop="carNum">
-              <el-input v-model="queryParams.carNum" placeholder="请输入驾驶员" clearable style="width: 160px"
+            <el-form-item label="驾驶员" prop="people">
+              <el-input v-model="queryParams.people" placeholder="请输入驾驶员" clearable style="width: 160px"
                 @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="业务类型" prop="carNum">
-              <el-input v-model="queryParams.carNum" placeholder="请输入业务类型" clearable style="width: 160px"
+            <!-- TODO @李伟 -->
+            <el-form-item label="业务类型" prop="ext1">
+              <el-input v-model="queryParams.ext1" placeholder="请输入业务类型" clearable style="width: 160px"
                 @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="能耗类型" prop="carNum">
-              <el-input v-model="queryParams.carNum" placeholder="请输入能耗类型" clearable style="width: 160px"
+            <!-- TODO @李伟 -->
+            <el-form-item label="能耗类型" prop="ext1">
+              <el-input v-model="queryParams.ext1" placeholder="请输入能耗类型" clearable style="width: 160px"
                 @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="网格" prop="carNum">
-              <el-input v-model="queryParams.carNum" placeholder="请输入网格" clearable style="width: 160px"
+            <el-form-item label="网格" prop="wangge">
+              <el-input v-model="queryParams.wangge" placeholder="请输入网格" clearable style="width: 160px"
                 @keyup.enter="handleQuery" />
             </el-form-item>
-            <el-form-item label="单位" prop="carNum">
-              <el-input v-model="queryParams.carNum" placeholder="请输入单位" clearable style="width: 160px"
+            <el-form-item label="单位" prop="dept">
+              <el-input v-model="queryParams.dept" placeholder="请输入单位" clearable style="width: 160px"
                 @keyup.enter="handleQuery" />
             </el-form-item>
           </el-form>
@@ -284,7 +286,6 @@ const openMapDiv = (data) => {
 const getList = async () => {
   loading.value = true;
   const res = await listCarInfo(queryParams.value);
-  console.log(res)
   table.value.setDataList(res.rows);
   total.value = res.total;
   loading.value = false;

+ 41 - 43
src/views/car/people/index.vue

@@ -19,7 +19,7 @@
                       @keyup.enter="handleQuery"
                     />
                   </el-form-item>
-  
+
                   <el-form-item label="状态" prop="status">
                     <el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
                       <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
@@ -43,7 +43,7 @@
               </el-card>
             </div>
           </transition>
-  
+
           <el-card shadow="hover">
             <template #header>
               <el-row :gutter="10">
@@ -78,7 +78,7 @@
                 <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns" :search="true"></right-toolbar>
               </el-row>
             </template>
-  
+
             <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
               <el-table-column type="selection" width="50" align="center" />
               <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
@@ -100,13 +100,13 @@
                   <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
                 </template>
               </el-table-column>
-  
+
               <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
                 <template #default="scope">
                   <span>{{ scope.row.createTime }}</span>
                 </template>
               </el-table-column>
-  
+
               <el-table-column label="操作" fixed="right" width="180" class-name="small-padding fixed-width">
                 <template #default="scope">
                   <el-tooltip content="修改" placement="top" v-if="scope.row.userId !== 1">
@@ -115,18 +115,18 @@
                   <el-tooltip content="删除" placement="top" v-if="scope.row.userId !== 1">
                     <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']"></el-button>
                   </el-tooltip>
-  
+
                   <el-tooltip content="重置密码" placement="top" v-if="scope.row.userId !== 1">
                     <el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['system:user:resetPwd']"></el-button>
                   </el-tooltip>
-  
+
                   <el-tooltip content="分配角色" placement="top" v-if="scope.row.userId !== 1">
                     <el-button link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
                   </el-tooltip>
                 </template>
               </el-table-column>
             </el-table>
-  
+
             <pagination
               v-show="total > 0"
               :total="total"
@@ -137,7 +137,7 @@
           </el-card>
         </el-col>
       </el-row>
-  
+
       <!-- 添加或修改用户配置对话框 -->
       <el-dialog ref="formDialogRef" :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="closeDialog">
         <el-form :model="form" :rules="rules" ref="userFormRef" label-width="80px">
@@ -247,7 +247,7 @@
           </div>
         </template>
       </el-dialog>
-  
+
       <!-- 用户导入对话框 -->
       <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
         <el-upload
@@ -283,7 +283,7 @@
       </el-dialog>
     </div>
   </template>
-  
+
   <script setup name="User" lang="ts">
   import api from "@/api/system/user"
   import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
@@ -293,11 +293,11 @@
   import { PostVO } from "@/api/system/post/types";
   import { to } from "await-to-js";
   import { globalHeaders } from "@/utils/request";
-  
+
   const router = useRouter();
   const { proxy } = getCurrentInstance() as ComponentInternalInstance
   const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex'));
-  
+
   const userList = ref<UserVO[]>();
   const loading = ref(true);
   const showSearch = ref(true)
@@ -336,19 +336,19 @@
     { key: 5, label: `状态`, visible: true,children: [] },
     { key: 6, label: `创建时间`, visible: true,children: [] }
   ])
-  
-  
+
+
   const deptTreeRef = ref<ElTreeInstance>();
   const queryFormRef = ref<ElFormInstance>();
   const userFormRef = ref<ElFormInstance>();
   const uploadRef = ref<ElUploadInstance>();
   const formDialogRef = ref<ElDialogInstance>();
-  
+
   const dialog = reactive<DialogOption>({
     visible: false,
     title: ''
   });
-  
+
   const initFormData: UserForm = {
     userId: undefined,
     deptId: undefined,
@@ -384,9 +384,9 @@
       phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
     }
   })
-  
+
   const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data)
-  
+
   /** 通过条件过滤节点  */
   const filterNode = (value: string, data: any) => {
     if (!value) return true
@@ -399,30 +399,29 @@
       flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
     }
   );
-  
+
   /** 查询部门下拉树结构 */
   const getTreeSelect = async () => {
     const res = await api.deptTreeSelect();
     deptOptions.value = res.data;
   };
-  
+
   /** 查询用户列表 */
   const getList = async () => {
     loading.value = true;
     const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
-    console.log(res)
     loading.value = false;
     userList.value = res.rows;
     total.value = res.total;
   }
-  
+
   /** 节点单击事件 */
   const handleNodeClick = (data: DeptVO) => {
     queryParams.value.deptId = data.id;
     handleQuery()
   }
-  
-  
+
+
   /** 搜索按钮操作 */
   const handleQuery = () => {
     queryParams.value.pageNum = 1
@@ -437,7 +436,7 @@
     deptTreeRef.value?.setCurrentKey(undefined);
     handleQuery();
   }
-  
+
   /** 删除按钮操作 */
   const handleDelete = async (row?: UserVO) => {
     const userIds = row?.userId || ids.value;
@@ -448,7 +447,7 @@
       proxy?.$modal.msgSuccess("删除成功");
     }
   }
-  
+
   /** 用户状态修改  */
   const handleStatusChange = async (row: UserVO) => {
     let text = row.status === "0" ? "启用" : "停用"
@@ -465,7 +464,7 @@
     const userId = row.userId;
     router.push("/system/user-auth/role/" + userId);
   }
-  
+
   /** 重置密码按钮操作 */
   const handleResetPwd = async (row: UserVO) => {
     const [err, res] = await to(ElMessageBox.prompt('请输入"' + row.userName + '"的新密码', "提示", {
@@ -480,14 +479,14 @@
       proxy?.$modal.msgSuccess("修改成功,新密码是:" + res.value);
     }
   }
-  
+
   /** 选择条数  */
   const handleSelectionChange = (selection: UserVO[]) => {
     ids.value = selection.map((item) => item.userId);
     single.value = selection.length != 1;
     multiple.value = !selection.length;
   }
-  
+
   /** 导入按钮操作 */
   const handleImport = () => {
     upload.title = "用户导入";
@@ -504,7 +503,7 @@
     proxy?.download("system/user/importTemplate", {
     }, `user_template_${new Date().getTime()}.xlsx`);
   }
-  
+
   /**文件上传中处理 */
   const handleFileUploadProgress = () => {
     upload.isUploading = true;
@@ -517,12 +516,12 @@
     ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
     getList();
   }
-  
+
   /** 提交上传文件 */
   function submitFileForm() {
     uploadRef.value?.submit();
   }
-  
+
   /** 初始化部门数据 */
   const initTreeData = async () => {
     // 判断部门的数据是否存在,存在不获取,不存在则获取
@@ -531,8 +530,8 @@
       deptOptions.value = data;
     }
   }
-  
-  
+
+
   /** 重置操作表单 */
   const reset = () => {
     form.value = { ...initFormData };
@@ -543,7 +542,7 @@
     dialog.visible = false;
     reset();
   }
-  
+
   /** 新增按钮操作 */
   const handleAdd = async () => {
     reset();
@@ -570,7 +569,7 @@
     form.value.roleIds = data.roleIds;
     form.value.password = "";
   }
-  
+
   /** 提交按钮 */
   const submitForm = () => {
     userFormRef.value?.validate(async (valid: boolean) => {
@@ -582,8 +581,8 @@
       }
     })
   }
-  
-  
+
+
   /**
    * 关闭用户弹窗
    */
@@ -591,14 +590,14 @@
     dialog.visible = false;
     resetForm();
   }
-  
+
   /**
    * 重置表单
    */
   const resetForm = () => {
     userFormRef.value?.resetFields();
     userFormRef.value?.clearValidate();
-  
+
     form.value.id = undefined;
     form.value.status = '1';
   }
@@ -610,6 +609,5 @@
     });
   });
   </script>
-  
+
   <style lang="scss" scoped></style>
-  

+ 41 - 43
src/views/car/people/yonghu.vue

@@ -19,7 +19,7 @@
                       @keyup.enter="handleQuery"
                     />
                   </el-form-item>
-  
+
                   <el-form-item label="状态" prop="status">
                     <el-select v-model="queryParams.status" placeholder="用户状态" clearable style="width: 240px">
                       <el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
@@ -43,7 +43,7 @@
               </el-card>
             </div>
           </transition>
-  
+
           <el-card shadow="hover">
             <template #header>
               <el-row :gutter="10">
@@ -78,7 +78,7 @@
                 <right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns" :search="true"></right-toolbar>
               </el-row>
             </template>
-  
+
             <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
               <el-table-column type="selection" width="50" align="center" />
               <el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
@@ -100,13 +100,13 @@
                   <el-switch v-model="scope.row.status" active-value="0" inactive-value="1" @change="handleStatusChange(scope.row)"></el-switch>
                 </template>
               </el-table-column>
-  
+
               <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
                 <template #default="scope">
                   <span>{{ scope.row.createTime }}</span>
                 </template>
               </el-table-column>
-  
+
               <el-table-column label="操作" fixed="right" width="180" class-name="small-padding fixed-width">
                 <template #default="scope">
                   <el-tooltip content="修改" placement="top" v-if="scope.row.userId !== 1">
@@ -115,18 +115,18 @@
                   <el-tooltip content="删除" placement="top" v-if="scope.row.userId !== 1">
                     <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:user:remove']"></el-button>
                   </el-tooltip>
-  
+
                   <el-tooltip content="重置密码" placement="top" v-if="scope.row.userId !== 1">
                     <el-button link type="primary" icon="Key" @click="handleResetPwd(scope.row)" v-hasPermi="['system:user:resetPwd']"></el-button>
                   </el-tooltip>
-  
+
                   <el-tooltip content="分配角色" placement="top" v-if="scope.row.userId !== 1">
                     <el-button link type="primary" icon="CircleCheck" @click="handleAuthRole(scope.row)" v-hasPermi="['system:user:edit']"></el-button>
                   </el-tooltip>
                 </template>
               </el-table-column>
             </el-table>
-  
+
             <pagination
               v-show="total > 0"
               :total="total"
@@ -137,7 +137,7 @@
           </el-card>
         </el-col>
       </el-row>
-  
+
       <!-- 添加或修改用户配置对话框 -->
       <el-dialog ref="formDialogRef" :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body @close="closeDialog">
         <el-form :model="form" :rules="rules" ref="userFormRef" label-width="80px">
@@ -247,7 +247,7 @@
           </div>
         </template>
       </el-dialog>
-  
+
       <!-- 用户导入对话框 -->
       <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
         <el-upload
@@ -283,7 +283,7 @@
       </el-dialog>
     </div>
   </template>
-  
+
   <script setup name="User" lang="ts">
   import api from "@/api/system/user"
   import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
@@ -293,11 +293,11 @@
   import { PostVO } from "@/api/system/post/types";
   import { to } from "await-to-js";
   import { globalHeaders } from "@/utils/request";
-  
+
   const router = useRouter();
   const { proxy } = getCurrentInstance() as ComponentInternalInstance
   const { sys_normal_disable, sys_user_sex } = toRefs<any>(proxy?.useDict('sys_normal_disable', 'sys_user_sex'));
-  
+
   const userList = ref<UserVO[]>();
   const loading = ref(true);
   const showSearch = ref(true)
@@ -336,19 +336,19 @@
     { key: 5, label: `状态`, visible: true,children: [] },
     { key: 6, label: `创建时间`, visible: true,children: [] }
   ])
-  
-  
+
+
   const deptTreeRef = ref<ElTreeInstance>();
   const queryFormRef = ref<ElFormInstance>();
   const userFormRef = ref<ElFormInstance>();
   const uploadRef = ref<ElUploadInstance>();
   const formDialogRef = ref<ElDialogInstance>();
-  
+
   const dialog = reactive<DialogOption>({
     visible: false,
     title: ''
   });
-  
+
   const initFormData: UserForm = {
     userId: undefined,
     deptId: undefined,
@@ -384,9 +384,9 @@
       phonenumber: [{ pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/, message: "请输入正确的手机号码", trigger: "blur" }]
     }
   })
-  
+
   const { queryParams, form, rules } = toRefs<PageData<UserForm, UserQuery>>(data)
-  
+
   /** 通过条件过滤节点  */
   const filterNode = (value: string, data: any) => {
     if (!value) return true
@@ -399,30 +399,29 @@
       flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
     }
   );
-  
+
   /** 查询部门下拉树结构 */
   const getTreeSelect = async () => {
     const res = await api.deptTreeSelect();
     deptOptions.value = res.data;
   };
-  
+
   /** 查询用户列表 */
   const getList = async () => {
     loading.value = true;
     const res = await api.listUser(proxy?.addDateRange(queryParams.value, dateRange.value));
-    console.log(res)
     loading.value = false;
     userList.value = res.rows;
     total.value = res.total;
   }
-  
+
   /** 节点单击事件 */
   const handleNodeClick = (data: DeptVO) => {
     queryParams.value.deptId = data.id;
     handleQuery()
   }
-  
-  
+
+
   /** 搜索按钮操作 */
   const handleQuery = () => {
     queryParams.value.pageNum = 1
@@ -437,7 +436,7 @@
     deptTreeRef.value?.setCurrentKey(undefined);
     handleQuery();
   }
-  
+
   /** 删除按钮操作 */
   const handleDelete = async (row?: UserVO) => {
     const userIds = row?.userId || ids.value;
@@ -448,7 +447,7 @@
       proxy?.$modal.msgSuccess("删除成功");
     }
   }
-  
+
   /** 用户状态修改  */
   const handleStatusChange = async (row: UserVO) => {
     let text = row.status === "0" ? "启用" : "停用"
@@ -465,7 +464,7 @@
     const userId = row.userId;
     router.push("/system/user-auth/role/" + userId);
   }
-  
+
   /** 重置密码按钮操作 */
   const handleResetPwd = async (row: UserVO) => {
     const [err, res] = await to(ElMessageBox.prompt('请输入"' + row.userName + '"的新密码', "提示", {
@@ -480,14 +479,14 @@
       proxy?.$modal.msgSuccess("修改成功,新密码是:" + res.value);
     }
   }
-  
+
   /** 选择条数  */
   const handleSelectionChange = (selection: UserVO[]) => {
     ids.value = selection.map((item) => item.userId);
     single.value = selection.length != 1;
     multiple.value = !selection.length;
   }
-  
+
   /** 导入按钮操作 */
   const handleImport = () => {
     upload.title = "用户导入";
@@ -504,7 +503,7 @@
     proxy?.download("system/user/importTemplate", {
     }, `user_template_${new Date().getTime()}.xlsx`);
   }
-  
+
   /**文件上传中处理 */
   const handleFileUploadProgress = () => {
     upload.isUploading = true;
@@ -517,12 +516,12 @@
     ElMessageBox.alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
     getList();
   }
-  
+
   /** 提交上传文件 */
   function submitFileForm() {
     uploadRef.value?.submit();
   }
-  
+
   /** 初始化部门数据 */
   const initTreeData = async () => {
     // 判断部门的数据是否存在,存在不获取,不存在则获取
@@ -531,8 +530,8 @@
       deptOptions.value = data;
     }
   }
-  
-  
+
+
   /** 重置操作表单 */
   const reset = () => {
     form.value = { ...initFormData };
@@ -543,7 +542,7 @@
     dialog.visible = false;
     reset();
   }
-  
+
   /** 新增按钮操作 */
   const handleAdd = async () => {
     reset();
@@ -570,7 +569,7 @@
     form.value.roleIds = data.roleIds;
     form.value.password = "";
   }
-  
+
   /** 提交按钮 */
   const submitForm = () => {
     userFormRef.value?.validate(async (valid: boolean) => {
@@ -582,8 +581,8 @@
       }
     })
   }
-  
-  
+
+
   /**
    * 关闭用户弹窗
    */
@@ -591,14 +590,14 @@
     dialog.visible = false;
     resetForm();
   }
-  
+
   /**
    * 重置表单
    */
   const resetForm = () => {
     userFormRef.value?.resetFields();
     userFormRef.value?.clearValidate();
-  
+
     form.value.id = undefined;
     form.value.status = '1';
   }
@@ -610,6 +609,5 @@
     });
   });
   </script>
-  
+
   <style lang="scss" scoped></style>
-  

+ 119 - 127
src/views/car/work/addCarWork.vue

@@ -1,62 +1,51 @@
 <template>
-    <div style="padding: 10px 15px">
-        <el-card class="box-card">
-            <template #header>
-                <div class="card-header">
-                    <div style="display: flex;flex-direction: row;">
-                        <div style="width: 8px;height: 19px;opacity: 1;background: #409EFF"></div>
-                        <span
-                            style="font-family: PingFang SC;font-size: 14px;font-weight: normal;line-height: 19px;height: 19px;margin-left: 8px;">路线作业</span>
-                    </div>
-                    <div>
-                        <el-button type="warning" @click="goBack()">取消</el-button>
-                        <el-button type="primary" @click="submit()">保存</el-button>
-                    </div>
-                </div>
-
-            </template>
-            <el-row>
-                <el-col :span="24">
-                    <el-descriptions :column="3">
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 60px;text-align: right">
-                                    <span style="color: red">*</span> 作业名称
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="form.name" placeholder="请输入作业名称" />
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 60px;text-align: right">
-                                    <span style="color: red">*</span> 作业类型
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-select v-model="extObj.type" class="m-2" placeholder="请选择作业类型" style="width: 240px">
-                                    <el-option v-for="item in workTypeList" :key="item.dictValue"
-                                        :label="item.dictLabel" :value="item.dictValue" />
-                                </el-select>
-                            </div>
-                        </el-descriptions-item>
-                        <el-descriptions-item>
-
-                            <template #label>
-                                <div style="display: inline-block;min-width: 60px;text-align: right">
-                                    <span style="color: red">*</span> 所属网格
-                                </div>
-                            </template>
-                            <div class="content-w">
-                                <el-input v-model="extObj.wangge" placeholder="请输入网格" />
-                            </div>
-                        </el-descriptions-item>
-
-                    </el-descriptions>
-                    <!-- <el-descriptions :column="4" style="width: 100%;">
+  <div style="padding: 10px 15px">
+    <el-card class="box-card">
+      <template #header>
+        <div class="card-header">
+          <div style="display: flex;flex-direction: row;">
+            <div style="width: 8px;height: 19px;opacity: 1;background: #409EFF"></div>
+            <span style="font-family: PingFang SC;font-size: 14px;font-weight: normal;line-height: 19px;height: 19px;margin-left: 8px;"
+              >路线作业</span
+            >
+          </div>
+          <div>
+            <el-button type="warning" @click="goBack()">取消</el-button>
+            <el-button type="primary" @click="submit()">保存</el-button>
+          </div>
+        </div>
+      </template>
+      <el-row>
+        <el-col :span="24">
+          <el-descriptions :column="3">
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 60px;text-align: right"><span style="color: red">*</span> 作业名称</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="form.name" placeholder="请输入作业名称" />
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 60px;text-align: right"><span style="color: red">*</span> 作业类型</div>
+              </template>
+              <div class="content-w">
+                <el-select v-model="extObj.type" class="m-2" placeholder="请选择作业类型" style="width: 240px">
+                  <el-option v-for="item in workTypeList" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue" />
+                </el-select>
+              </div>
+            </el-descriptions-item>
+            <el-descriptions-item>
+              <template #label>
+                <div style="display: inline-block;min-width: 60px;text-align: right"><span style="color: red">*</span> 所属网格</div>
+              </template>
+              <div class="content-w">
+                <el-input v-model="extObj.wangge" placeholder="请输入网格" />
+              </div>
+            </el-descriptions-item>
+          </el-descriptions>
+          <!-- <el-descriptions :column="4" style="width: 100%;">
                         <el-descriptions-item>
 
                             <template #label>
@@ -103,77 +92,81 @@
                             </div>
                         </el-descriptions-item>
                     </el-descriptions> -->
-                    <!-- <tableElm :columns="columns" ref="table"></tableElm> -->
-                </el-col>
-            </el-row>
-        </el-card>
-        <el-card class="box-card">
-
-            <template #header>
-                <div class="card-header">
-                    <div style="display: flex;flex-direction: row;">
-                        <div style="width: 8px;height: 19px;opacity: 1;background: #409EFF"></div>
-                        <span
-                            style="font-family: PingFang SC;font-size: 14px;font-weight: normal;line-height: 19px;height: 19px;margin-left: 8px;">路线站点</span>
-                    </div>
-                </div>
-            </template>
-            <div style="display: flex;flex-direction: row;width: 100%;">
-                <div style="width:25%">
-                    <el-timeline>
-                        <el-timeline-item v-for="(activity, index) in activities" :key="index" :icon="activity.icon"
-                            :type="activity.type" :color="activity.color" :size="activity.size"
-                            :hollow="activity.hollow">
-                            <!-- {{ activity.content }} -->
-                            <div style="display: flex;flex-direction: column;" v-show="!activity.isadd">
-                                <div v-if="activity.rank == 1 || activity.rank == 999">{{ activity.content }}</div>
-                                <div v-if="activity.data != null">{{ activity.data.dictLabel }}</div>
-                                <div v-if="activity.timeObj != null">{{ activity.timeObj.startTime }}</div>
-                                <div style="display: flex;flex-direction: row;">
-                                    <el-button style="width: 80px;" @click="selectSite(index)">选择地点</el-button>
-                                    <el-button style="width: 80px;" @click="selectTime(index)">选择时间</el-button>
-                                    <div style="margin-left:5px" @click="deleteItem(activity)">
-                                        <el-icon :size="20" style="color:red;padding-top: 10px;">
-                                            <CircleClose />
-                                        </el-icon>
-                                    </div>
-                                </div>
-                            </div>
-                            <div v-show="activity.isadd">
-                                <el-button type="primary" style="width: 80px;" @click="addSite()">新增站点</el-button>
-                            </div>
-                        </el-timeline-item>
-                    </el-timeline>
+          <!-- <tableElm :columns="columns" ref="table"></tableElm> -->
+        </el-col>
+      </el-row>
+    </el-card>
+    <el-card class="box-card">
+      <template #header>
+        <div class="card-header">
+          <div style="display: flex;flex-direction: row;">
+            <div style="width: 8px;height: 19px;opacity: 1;background: #409EFF"></div>
+            <span style="font-family: PingFang SC;font-size: 14px;font-weight: normal;line-height: 19px;height: 19px;margin-left: 8px;"
+              >路线站点</span
+            >
+          </div>
+        </div>
+      </template>
+      <div style="display: flex;flex-direction: row;width: 100%;">
+        <div style="width:25%">
+          <el-timeline>
+            <el-timeline-item
+              v-for="(activity, index) in activities"
+              :key="index"
+              :icon="activity.icon"
+              :type="activity.type"
+              :color="activity.color"
+              :size="activity.size"
+              :hollow="activity.hollow"
+            >
+              <!-- {{ activity.content }} -->
+              <div style="display: flex;flex-direction: column;" v-show="!activity.isadd">
+                <div v-if="activity.rank == 1 || activity.rank == 999">{{ activity.content }}</div>
+                <div v-if="activity.data != null">{{ activity.data.dictLabel }}</div>
+                <div v-if="activity.timeObj != null">{{ activity.timeObj.startTime }}</div>
+                <div style="display: flex;flex-direction: row;">
+                  <el-button style="width: 80px;" @click="selectSite(index)">选择地点</el-button>
+                  <el-button style="width: 80px;" @click="selectTime(index)">选择时间</el-button>
+                  <div style="margin-left:5px" @click="deleteItem(activity)">
+                    <el-icon :size="20" style="color:red;padding-top: 10px;">
+                      <CircleClose />
+                    </el-icon>
+                  </div>
                 </div>
-                <div style="width: 75%;">
-                    <!-- <mapDiv></mapDiv> -->
-                    <!-- <img style="width:90%" src="@/assets/images/map.png"/> -->
-                    <mapDiv style="width:90%;height: 100%;" @childToParent='childrenClick'></mapDiv>
-                </div>
-            </div>
-        </el-card>
-
-        <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-            <el-form ref="carInfoFormRef" :model="dateObj" :rules="rules" label-width="80px">
-                <el-form-item label="时间">
-                    <el-time-select v-model="dateObj.startTime" style="width: 240px" start="00:00" step="00:15"
-                        end="23:59" placeholder="时间" />
-                </el-form-item>
-                <!-- <el-form-item label="出站时间">
+              </div>
+              <div v-show="activity.isadd">
+                <el-button type="primary" style="width: 80px;" @click="addSite()">新增站点</el-button>
+              </div>
+            </el-timeline-item>
+          </el-timeline>
+        </div>
+        <div style="width: 75%;">
+          <!-- <mapDiv></mapDiv> -->
+          <!-- <img style="width:90%" src="@/assets/images/map.png"/> -->
+          <mapDiv style="width:90%;height: 100%;" @childToParent="childrenClick"></mapDiv>
+        </div>
+      </div>
+    </el-card>
+
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
+      <el-form ref="carInfoFormRef" :model="dateObj" :rules="rules" label-width="80px">
+        <el-form-item label="时间">
+          <el-time-select v-model="dateObj.startTime" style="width: 240px" start="00:00" step="00:15" end="23:59" placeholder="时间" />
+        </el-form-item>
+        <!-- <el-form-item label="出站时间">
                     <el-time-select v-model="dateObj.endTime" style="width: 240px" start="00:00" step="00:15"
                         end="23:59" placeholder="出站时间" />
                 </el-form-item> -->
-            </el-form>
-
-            <template #footer>
-                <div class="dialog-footer">
-                    <el-button :loading="buttonLoading" type="primary" @click="submitTime">确 定</el-button>
-                    <el-button @click="dialog.visible = false">取 消</el-button>
-                </div>
-            </template>
-        </el-dialog>
-
-    </div>
+      </el-form>
+
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button :loading="buttonLoading" type="primary" @click="submitTime">确 定</el-button>
+          <el-button @click="dialog.visible = false">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
 </template>
 
 <script setup lang="ts">
@@ -495,7 +488,6 @@ const goBack = () => {
 onMounted(() => {
     initData()
 });
-
 </script>
 
 <style lang="scss" scoped>
@@ -509,4 +501,4 @@ onMounted(() => {
     display: inline-flex;
     max-width: 160px;
 }
-</style>
+</style>

+ 12 - 6
src/views/car/work/schedule.vue

@@ -45,8 +45,8 @@
         v-model:limit="queryParams.pageSize" @pagination="getList" />
     </el-card>
 
-    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
-      <el-form ref="carInfoFormRef" :model="dateObj" :rules="rules" label-width="80px">
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="50vw" append-to-body>
+      <el-form ref="carInfoFormRef" :model="dateObj" :rules="rules" label-width="120px">
         <el-form-item label="出发时间">
           <el-time-picker v-model="startTime" :picker-options="{
             selectableRange: '00:00:00 - 23:59:59'
@@ -73,6 +73,9 @@
             <el-option v-for="item in ckList" :key="item.userId" :label="item.nickName" :value="item.userId" />
           </el-select>
         </el-form-item>
+        <el-form-item label="是否自动排班">
+           <el-switch v-model="formParams.isauto" />
+        </el-form-item>
       </el-form>
 
       <template #footer>
@@ -150,7 +153,8 @@ const table = ref(tableElm)
 
 const formParams = ref({
   driverInfo: null,
-  attendantInfo: null
+  attendantInfo: null,
+  isauto:false
 });
 
 const data = reactive<PageData<CarScheduleForm, CarScheduleQuery>>({
@@ -209,7 +213,6 @@ const getScheduleData = () => {
     endtime: year + "-12-31"
   }
   listCarSchedule({ pageSize: 1000, params: obj }).then(res => {
-    console.log(res)
     scheduleList.value = res.rows
     proxy?.$forceUpdate
 
@@ -346,7 +349,8 @@ const reset = () => {
   form.value = { ...initFormData };
   formParams.value = {
     driverInfo: null,
-    attendantInfo: null
+    attendantInfo: null,
+    isauto:false
   }
   line.value = null;
   carPathObj.value = null;
@@ -392,6 +396,7 @@ const handleUpdate = async (row?: CarScheduleVO) => {
   form.value.carId = getCarId(row.carNum);
   formParams.value.driverInfo = data.driverInfo
   formParams.value.attendantInfo = data.attendantInfo
+  formParams.value.isauto = JSON.parse(row.ext2==""||row.ext2==null?'{"isauto":false}':row.ext2).isauto
   line.value = data.lineID
   dialog.visible = true;
   dialog.title = "修改车及人员排班";
@@ -463,6 +468,7 @@ const submitSchedule = async () => {
   lineobj.pathLine = dataList
   form.value.pathInfo = JSON.stringify(lineobj);
   form.value.carNum = getCarNum(form.value.carId);
+  form.value.ext2 = JSON.stringify({isauto:lineobj.isauto}  )
   if (form.value.id) {
     await updateCarSchedule(form.value).finally(() => buttonLoading.value = false);
   } else {
@@ -526,4 +532,4 @@ onMounted(() => {
   height: 40px;
 
 }
-</style>
+</style>

+ 2 - 4
src/views/home.vue

@@ -9,9 +9,7 @@
     <pieEchartsS style="position: absolute;top: 10vh;right: 1vw;z-index: 1000;"></pieEchartsS>
     <stationPieS style="position: absolute;top:37vh;right: 1vw;z-index: 1000;"></stationPieS>
     <warnTableS style="position: absolute;top: 65vh;right: 1vw;z-index: 1000;"></warnTableS>
-    <mapDiv :showMarket="showMarket" :darkType="darkType" style="width:100%;height:100vh;padding: 0 0 0 0" ref="mapElm">
-    </mapDiv>
-
+    <mapDiv :showMarket="showMarket" :darkType="darkType" style="width:100%;height:100vh;padding: 0 0 0 0" ref="mapElm"> </mapDiv>
   </div>
 </template>
 
@@ -62,4 +60,4 @@ const goTarget = (url: string) => {
     text-transform: none;
   }
 }
-</style>
+</style>

+ 1 - 2
src/views/index.vue

@@ -7,8 +7,7 @@
         <messageTable style="width: 100%;margin-top: 1vh;"></messageTable>
       </div>
       <div style="width: 50%;margin-left: 1%;">
-        <mapDiv :showMarket="showMarket" :darkType="darkType" style="width:100%;height:86vh;padding: 0 0 0 0"
-          ref="mapElm"></mapDiv>
+        <mapDiv :showMarket="showMarket" :darkType="darkType" style="width:100%;height:86vh;padding: 0 0 0 0" ref="mapElm"></mapDiv>
       </div>
       <div style="width:24%;margin-left: 1%;">
         <pieEcharts></pieEcharts>

+ 191 - 0
src/views/statics/index.vue

@@ -0,0 +1,191 @@
+<!-- eslint-disable prettier/prettier -->
+<template>
+  <div class="p-2" style="padding: 10px">
+    <div style="display: flex; flex-direction: row">
+      <div style="width: 20%;">
+        <div class="card-header">
+          <div style="display: flex; flex-direction: row">
+            <div style="width: 4px; height: 19px; opacity: 1; background: #409eff"></div>
+            <span style="
+                font-family: PingFang SC;
+                font-size: 14px;
+                font-weight: normal;
+                line-height: 19px;
+                height: 19px;
+                margin-left: 5px;
+              ">车辆列表</span>
+          </div>
+        </div>
+        <div style="margin-top: 20px; padding-left: 10px;">
+          <el-input style="margin-top: 10px;" v-model="filterText" placeholder="输入关键字" />
+          <el-tree-v2 v-if="showTree" style="margin-top: 10px;" ref="treeRef" class="filter-tree"
+            :height="gettreeheight()" :data="data" :indent="treeIndent" :props="defaultProps"
+            :filter-method="filterNode" @node-click="treeclick">
+            <template v-slot:default="{ node }">
+              <element-tree-line :node="node" :treeData="data" :showLabelLine="false" :indent="treeIndent">
+              </element-tree-line>
+            </template>
+          </el-tree-v2>
+        </div>
+      </div>
+      <div style="width: 77%; margin-left: 2%">
+        <div class="card-header">
+          <div style="display: flex; flex-direction: row;position: relative">
+            <div style="width: 4px; height: 19px; opacity: 1; background: #409eff"></div>
+            <span style="
+                font-family: PingFang SC;
+                font-size: 14px;
+                font-weight: normal;
+                line-height: 19px;
+                height: 19px;
+                margin-left: 5px;
+              ">车辆视频</span>
+            <span style="margin-left: 30px; font-size: 14px">{{ currentdata?.label }}</span>
+             <div style="margin-top: 20px" >
+
+
+
+             </div>
+
+
+          </div>
+
+        </div>
+        <div id="container" style="margin-top: 20px;width:100%;height:80vh"></div>
+
+      </div>
+    </div>
+
+  </div>
+</template>
+
+<script setup>
+import { listCarInfo } from '@/api/carInfo';
+
+
+const carlist = ref([]);
+
+const showTree = ref(true)
+
+const filterText = ref("");
+const treeRef = ref(null);
+
+const gettreeheight = () => {
+  return document.body.clientHeight - 300;
+}
+
+
+const initData = async () => {
+  listCarInfo({ pageSize: 1000000 }).then(res => {
+    carlist.value = res.rows.filter(i => {
+      var hsin = false;
+      if (i.deviceInfos) {
+        JSON.parse(i.deviceInfos).forEach(item => {
+          if (item.type == "camera") {
+            hsin = true;
+            return true;
+          }
+        })
+      }
+      return hsin;
+
+    });
+
+  }
+  );
+}
+
+
+const defaultProps = {
+  children: "children",
+  label: "label",
+  value: 'id',
+};
+const treeIndent = ref(40);
+
+watch(filterText, (val) => {
+  if (treeRef.value) {
+    treeRef.value.filter(val);
+  }
+});
+
+const currenturl = ref("");
+
+
+const filterNode = (value, node) => {
+  if (node.id == 1) return true;
+  return node.label.indexOf(value) != -1;
+};
+
+const currentdata = ref(null)
+
+
+const treeclick = (data, node) => {
+  if (data.deviceInfos) {
+    JSON.parse(data.deviceInfos).forEach(item => {
+
+          if (item.type == "camera") {
+            currenturl.value = item.code;
+            jessibuca.play(currenturl.value);
+          }
+        })
+    }
+}
+
+
+const data = computed(() => {
+  let index = 0;
+  return carlist.value.map(i => { return { id: ++index, label: i.carNum,deviceInfos:i.deviceInfos } })
+});
+var jessibuca = null;
+onMounted(() => {
+  initData();
+
+  var $container = document.getElementById('container');
+   jessibuca = new Jessibuca({
+            container: $container,
+            videoBuffer: 0.2, // 缓存时长
+            isResize: false,
+           text: "",
+            decoder:"/jess/decoder.js",
+            loadingText: "",
+            useMSE: false,
+            debug: true,
+            showBandwidth: true, // 显示网速
+            operateBtns: {
+                fullscreen: true,
+                screenshot: false,
+                play: true,
+                audio: false,
+                recorder: false
+            },
+            forceNoOffscreen: true,
+            isNotMute: false,
+        },);
+  // if (treeRef.value) {
+  //   setTimeout(() => {
+  //     treeRef.value.expandNode(treeRef.value.getNode(1))
+  //   }, 100);
+  //   getSites();
+  //   initData();
+  //   // treeRef.value.expandNode(treeRef.value.getNode(1))
+  // }
+});
+</script>
+
+<style lang="scss" scoped>
+ #container {
+            background: rgba(13, 14, 27, 0.7);
+            width: 50vw;
+            height: 398px;
+        }
+.card-header {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+
+.boxunused {
+  background: #3333332d;
+}
+</style>

+ 1 - 2
src/views/statics/passengerFlow.vue

@@ -510,7 +510,6 @@ const searchSite = () => {
         params: params
     }
     listsitesFlow(obj).then(res => {
-        console.log(res)
         total2.value = res.total
         for (var index in res.rows) {
             res.rows[index].startTime = moment(dataValue.value[0]).format("YYYY-MM-DD HH:mm:ss")
@@ -586,4 +585,4 @@ onMounted(() => {
 </script>
 
 
-<style></style>
+<style></style>

+ 330 - 331
src/views/yunying/kdg/index.vue

@@ -391,182 +391,66 @@
 </template>
 
 <script setup name="CarInfo" lang="ts">
-  import { TreeNode } from "element-plus";
-  import { useRoute, useRouter } from "vue-router";
-  import EZUIKit from 'ezuikit-js';
-  import { ElMessage, ElMessageBox } from 'element-plus'
-  import { getCameraPlayerConfig } from '@/api/gpsData';
-  import { listCarPath, getCarPath, delCarPath, addCarPath, updateCarPath } from '@/api/carPath';
-  import { updateData, listData } from "@/api/system/dict/data";
-  import imgulock from "@/assets/images/unlock@2x.png";
-  import { getBoxInfo, getLock, openall } from "@/api/data"
+import { TreeNode } from "element-plus";
+import { useRoute, useRouter } from "vue-router";
+import EZUIKit from 'ezuikit-js';
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { getCameraPlayerConfig } from '@/api/gpsData';
+import { listCarPath, getCarPath, delCarPath, addCarPath, updateCarPath } from '@/api/carPath';
+import { updateData, listData } from "@/api/system/dict/data";
+import imgulock from "@/assets/images/unlock@2x.png";
+import { getBoxInfo, getLock, openall } from "@/api/data"
 
-  const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
-  const sites = ref([]);
+const sites = ref([]);
 
-  const showTree = ref(true)
+const showTree = ref(true)
 
-  const type = ref([])
+const type = ref([])
 
-  const boxData = ref([])
-  const boxCode = ref(null)
-  const showKdg = ref(false)
+const boxData = ref([])
+const boxCode = ref(null)
+const showKdg = ref(false)
 
 
-  const formdata = ref({
-    name: "",
-    type: "",
-    code: ""
-  })
+const formdata = ref({
+  name: "",
+  type: "",
+  code: ""
+})
 
 
-  const route = useRoute();
-  const router = useRouter();
+const route = useRoute();
+const router = useRouter();
 
-  const tableData = ref([]);
-  const carPathList = ref([]);
-  const line = ref([]);
+const tableData = ref([]);
+const carPathList = ref([]);
+const line = ref([]);
 
-  const activeName = ref("camera")
-
-  const filterText = ref("");
-  const treeRef = ref(null);
-  const dialogVisible = ref(false);
-
-  const gettreeheight = () => {
-    return document.body.clientHeight - 100;
-  }
+const activeName = ref("camera")
 
-  const goAdd = () => {
-    dialogVisible.value = true
-    formdata.value = {
-      name: "",
-      type: "",
-      code: ""
-    }
-  }
+const filterText = ref("");
+const treeRef = ref(null);
+const dialogVisible = ref(false);
 
-  const openBox = (value, lockCode) => {
-    if (res.code == 0) {
-      ElMessageBox.confirm(
-        '是否打开' + value + "号柜",
-        '提示',
-        {
-          confirmButtonText: '是',
-          cancelButtonText: '否',
-          type: 'warning',
-        }
-      )
-        .then(() => {
-          getLock(boxCode.value, lockCode).then(res => {
-            console.log(res.code)
-            ElMessage.success(value + "号柜远程开启成功");
-          })
-          // ElMessage({
-          //   type: 'success',
-          //   message: 'Delete completed',
-          // })
-        })
-        .catch(() => {
-          // ElMessage({
-          //   type: 'info',
-          //   message: 'Delete canceled',
-          // })
-        })
-    }
-  }
-
-  const clickCabinet = (value, lockCode) => {
-    for (var index in boxData.value) {
-      if (boxData.value[index].box_name == value) {
-        //  console.log(boxData.value[index].box_lock_address)
-        openBox(value, boxData.value[index].box_lock_address);
-      }
-    }
-    // ElMessage.success(value + "号柜远程开启成功");
-  }
-
-  const initData = async () => {
-    const res = await listCarPath({ pageSize: 1000 });
-    carPathList.value = res.rows;
-  }
-
-
-  const defaultProps = {
-    children: "children",
-    label: "label",
-    value: 'id',
-  };
-  const treeIndent = ref(40);
-
-  watch(filterText, (val) => {
-    if (treeRef.value) {
-      treeRef.value.filter(val);
-    }
-  });
-
-  const savedata = () => {
-    //保存数据
-    var data = {
-      dictCode: currentdata.value.dictCode,
-      dictValue: currentdata.value.dictValue,
-      dictLabel: currentdata.value.dictLabel,
-      dictType: "tbl_sites",
-      remark: JSON.stringify(tableData.value)
-    }
-    updateData(data).then(res => {
-      ElMessage.success("成功!");
-      getSites();
-
-    })
-  }
-
-  const getLineSites = () => {
-    console.log(line.value)
-    var sitesList = []
-    for (var index in carPathList.value) {
-      if (carPathList.value[index].id == line.value) {
-        sitesList = JSON.parse(carPathList.value[index].stationList)
-      }
-    }
-    console.log(sitesList)
-    var sites = []
-    for (var i in sitesList) {
-      sites.push({ id: i, label: sitesList[i].data.dictLabel })
-    }
-    console.log(sites)
-    data.value = [{
-      id: 1,
-      label: "站点",
-    },];
-    data.value[0].children = sites
-    console.log(data.value)
-    showTree.value = false;
-    setTimeout(() => {
-      showTree.value = true
-    }, 100);
+const gettreeheight = () => {
+  return document.body.clientHeight - 300;
+}
 
+const goAdd = () => {
+  dialogVisible.value = true
+  formdata.value = {
+    name: "",
+    type: "",
+    code: ""
   }
+}
 
+const openBox = (value, lockCode) => {
 
-  const getSites = () => {
-    listData({ dictType: "tbl_sites" }).then(res2 => {
-      sites.value = res2.rows;
-
-      var index = 1;
-      data.value = [{
-        id: 1,
-        label: "站点",
-        children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
-      },];
-    });
-  }
-
-  const openAllBox = () => {
-    let code = boxCode.value
     ElMessageBox.confirm(
-      '是否打开所有柜子',
+      '是否打开' + value + "号柜",
       '提示',
       {
         confirmButtonText: '是',
@@ -575,11 +459,9 @@
       }
     )
       .then(() => {
-        openall(code).then(res => {
-          console.log(res)
-          if (res.code == 0) {
-            ElMessage.success("打开所有柜子成功");
-          }
+        getLock(boxCode.value, lockCode).then(res => {
+          console.log(res.code)
+          ElMessage.success(value + "号柜远程开启成功");
         })
         // ElMessage({
         //   type: 'success',
@@ -592,206 +474,323 @@
         //   message: 'Delete canceled',
         // })
       })
-  }
 
-  const deleteDevice = (datac) => {
-    tableData.value = tableData.value.filter(i => i.type != datac.type);
-    var data = {
-      dictCode: currentdata.value.dictCode,
-      dictValue: currentdata.value.dictValue,
-      dictLabel: currentdata.value.dictLabel,
-      dictType: "tbl_sites",
-      remark: JSON.stringify(tableData.value)
-    }
-    updateData(data).then(res => {
-      ElMessage.success("成功!");
-    })
-  }
-
-  const handleTabClick = () => {
-
-  }
+}
 
-  const filterNode = (value: string, node: TreeNode) => {
-    if (node.id == 1) return true;
-    console.log(node.label.indexOf(value) != -1)
-    return node.label.indexOf(value) != -1;
-  };
-
-  const currentdata = ref(null)
-
-  const treeclick = (data: TreeNodeData, node: TreeNode) => {
-
-    currentdata.value = sites.value.filter(i => {
-      return i.dictLabel == data.label
-    })[0];
-    // console.log(currentdata.value)
-    tableData.value = JSON.parse(currentdata.value.remark)
-    if (currentdata.value) {
-      var cabinets = tableData.value.filter(i => i.type == 'cabinet');
-      // console.log(cabinets)
-      boxCode.value = cabinets[0].code
-      getBoxInfoData(cabinets[0].code)
-      if (cabinets.length > 0) {
-        type.value = cabinets[0].cabinetType
-      } else {
-        type.value = 4
-      }
+const clickCabinet = (value, lockCode) => {
+  for (var index in boxData.value) {
+    if (boxData.value[index].box_name == value) {
+      //  console.log(boxData.value[index].box_lock_address)
+      openBox(value, boxData.value[index].box_lock_address);
     }
-
   }
+  // ElMessage.success(value + "号柜远程开启成功");
+}
 
-  const getBoxInfoData = (code) => {
-    showKdg.value = false
-    getBoxInfo(code).then(res => {
-      boxData.value = res.data.list
-      showKdg.value = true
-      console.log(boxData.value)
-    })
-  }
+const initData = async () => {
+  const res = await listCarPath({ pageSize: 1000 });
+  carPathList.value = res.rows;
+}
 
-  const addDevice = () => {
-    dialogVisible.value = false;
-    if (formdata.value.name == "") {
-      ElMessage.warning("设备名称未填写");
-      return;
-    }
-    if (formdata.value.type == "") {
-      ElMessage.warning("设备类型未填写");
-      return;
-    }
-    if (formdata.value.code == "") {
-      ElMessage.warning("设备序列号未填写");
-      return;
-    }
-    if (tableData.value.filter(i => i.type == formdata.value.type).length > 0) {
-      ElMessage.warning("存在相同类型的设备");
-      return;
-    }
-    tableData.value.push(formdata.value);
-    var data = {
-      dictCode: currentdata.value.dictCode,
-      dictValue: currentdata.value.value,
-      dictLabel: currentdata.value.label,
-      dictType: "tbl_sites",
-      remark: JSON.stringify(tableData.value)
-    }
-    updateData(data).then(res => {
-      ElMessage.success("成功!");
-    })
 
+const defaultProps = {
+  children: "children",
+  label: "label",
+  value: 'id',
+};
+const treeIndent = ref(40);
 
+watch(filterText, (val) => {
+  if (treeRef.value) {
+    treeRef.value.filter(val);
+  }
+});
+
+const savedata = () => {
+  //保存数据
+  var data = {
+    dictCode: currentdata.value.dictCode,
+    dictValue: currentdata.value.dictValue,
+    dictLabel: currentdata.value.dictLabel,
+    dictType: "tbl_sites",
+    remark: JSON.stringify(tableData.value)
   }
+  updateData(data).then(res => {
+    ElMessage.success("成功!");
+    getSites();
 
-  const currentCabinet = ref({
-    total: 40,
-    unused: 10,
-    boxlist: []
   })
-  const SycCabinet = (code) => {
-    //TODO 获取格数
-    // var toalnum
-    currentCabinet.value.boxlist = [];
-    for (var i = 0; i < currentCabinet.value.total; i++) {
-      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-      //@ts-ignore
-      currentCabinet.value.boxlist.push({
-        box_id: 1,
-        box_name: (i + 1) + "",
-        box_status: i % 2
-      }
-      )
+}
+
+const getLineSites = () => {
+  console.log(line.value)
+  var sitesList = []
+  for (var index in carPathList.value) {
+    if (carPathList.value[index].id == line.value) {
+      sitesList = JSON.parse(carPathList.value[index].stationList)
     }
   }
-  // const openbox = (code) => {
-  //   setTimeout(() => {
-  //     ElMessage.success("指令已发送!");
-  //   }, 1000);
-  // }
-
-  const formatIndex = (value) => {
-    if (value < 10) {
-      return '0' + value
-    } else {
-      return value
-    }
+  console.log(sitesList)
+  var sites = []
+  for (var i in sitesList) {
+    sites.push({ id: i, label: sitesList[i].data.dictLabel })
   }
+  console.log(sites)
+  data.value = [{
+    id: 1,
+    label: "站点",
+  },];
+  data.value[0].children = sites
+  console.log(data.value)
+  showTree.value = false;
+  setTimeout(() => {
+    showTree.value = true
+  }, 100);
 
-  const getStatus = (index) => {
-    console.log(boxData.value.length)
-    if (index - 1 < boxData.value.length) {
-      if (boxData.value[index - 1].box_use_status == 0) {
-        return '空闲中'
-      } else {
-        return '使用中'
-      }
-    }else{
-      return '暂无'
-    }
+}
 
-  }
 
-  const data = computed(() => {
+const getSites = () => {
+  listData({ dictType: "tbl_sites" }).then(res2 => {
+    sites.value = res2.rows;
 
     var index = 1;
-
-    return [{
+    data.value = [{
       id: 1,
       label: "站点",
       children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
-    },]
+    },];
   });
-  onMounted(() => {
-    if (treeRef.value) {
-      setTimeout(() => {
-        treeRef.value.expandNode(treeRef.value.getNode(1))
-      }, 100);
-      getSites();
-      initData();
-      // treeRef.value.expandNode(treeRef.value.getNode(1))
+}
+
+const openAllBox = () => {
+  let code = boxCode.value
+  ElMessageBox.confirm(
+    '是否打开所有柜子',
+    '提示',
+    {
+      confirmButtonText: '是',
+      cancelButtonText: '否',
+      type: 'warning',
     }
-  });
+  )
+    .then(() => {
+      openall(code).then(res => {
+        if (res.code == 0) {
+          ElMessage.success("打开所有柜子成功");
+        }
+      })
+      // ElMessage({
+      //   type: 'success',
+      //   message: 'Delete completed',
+      // })
+    })
+    .catch(() => {
+      // ElMessage({
+      //   type: 'info',
+      //   message: 'Delete canceled',
+      // })
+    })
+}
+
+const deleteDevice = (datac) => {
+  tableData.value = tableData.value.filter(i => i.type != datac.type);
+  var data = {
+    dictCode: currentdata.value.dictCode,
+    dictValue: currentdata.value.dictValue,
+    dictLabel: currentdata.value.dictLabel,
+    dictType: "tbl_sites",
+    remark: JSON.stringify(tableData.value)
+  }
+  updateData(data).then(res => {
+    ElMessage.success("成功!");
+  })
+}
+
+const handleTabClick = () => {
+
+}
+
+const filterNode = (value: string, node: TreeNode) => {
+  if (node.id == 1) return true;
+  console.log(node.label.indexOf(value) != -1)
+  return node.label.indexOf(value) != -1;
+};
+
+const currentdata = ref(null)
+
+const treeclick = (data: TreeNodeData, node: TreeNode) => {
+
+  currentdata.value = sites.value.filter(i => {
+    return i.dictLabel == data.label
+  })[0];
+  // console.log(currentdata.value)
+  tableData.value = JSON.parse((currentdata.value.remark==''?"[]":currentdata.value.remark)??"[]")
+  if (currentdata.value) {
+    var cabinets = tableData.value.filter(i => i.type == 'cabinet');
+    if (cabinets.length > 0) {
+       boxCode.value = cabinets[0].code
+    getBoxInfoData(cabinets[0].code)
+    if (cabinets.length > 0) {
+      type.value = cabinets[0].cabinetType
+    } else {
+      type.value = 4
+    }
+    }
+    // console.log(cabinets)
 
+  }
 
+}
 
-</script>
+const getBoxInfoData = (code) => {
+  showKdg.value = false
+  getBoxInfo(code).then(res => {
+    boxData.value = res.data.list
+    showKdg.value = true
+    console.log(boxData.value)
+  })
+}
 
-<style lang="scss" scoped>
-  .card-header {
-    display: flex;
-    flex-direction: row;
-    justify-content: space-between;
+const addDevice = () => {
+  dialogVisible.value = false;
+  if (formdata.value.name == "") {
+    ElMessage.warning("设备名称未填写");
+    return;
   }
+  if (formdata.value.type == "") {
+    ElMessage.warning("设备类型未填写");
+    return;
+  }
+  if (formdata.value.code == "") {
+    ElMessage.warning("设备序列号未填写");
+    return;
+  }
+  if (tableData.value.filter(i => i.type == formdata.value.type).length > 0) {
+    ElMessage.warning("存在相同类型的设备");
+    return;
+  }
+  tableData.value.push(formdata.value);
+  var data = {
+    dictCode: currentdata.value.dictCode,
+    dictValue: currentdata.value.value,
+    dictLabel: currentdata.value.label,
+    dictType: "tbl_sites",
+    remark: JSON.stringify(tableData.value)
+  }
+  updateData(data).then(res => {
+    ElMessage.success("成功!");
+  })
+
 
-  .boxunused {
-    background: #3333332d;
+}
+
+const currentCabinet = ref({
+  total: 40,
+  unused: 10,
+  boxlist: []
+})
+const SycCabinet = (code) => {
+  //TODO 获取格数
+  // var toalnum
+  currentCabinet.value.boxlist = [];
+  for (var i = 0; i < currentCabinet.value.total; i++) {
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    //@ts-ignore
+    currentCabinet.value.boxlist.push({
+      box_id: 1,
+      box_name: (i + 1) + "",
+      box_status: i % 2
+    }
+    )
   }
+}
+// const openbox = (code) => {
+//   setTimeout(() => {
+//     ElMessage.success("指令已发送!");
+//   }, 1000);
+// }
+
+const formatIndex = (value) => {
+  if (value < 10) {
+    return '0' + value
+  } else {
+    return value
+  }
+}
 
-  .indexDiv {
-    background-color: white;
-    width: 20px;
-    height: 10px;
-    color: #000;
-    font-weight: 600;
-    position: absolute;
-    right: 2px;
-    bottom: 1px;
-    z-index: 1000;
-    font-size: 10px;
-    text-align: center;
+const getStatus = (index) => {
+  console.log(boxData.value.length)
+  if (index - 1 < boxData.value.length) {
+    if (boxData.value[index - 1].box_use_status == 0) {
+      return '空闲中'
+    } else {
+      return '使用中'
+    }
+  }else{
+    return '暂无'
   }
 
-  .indexDivLeft {
-    background-color: white;
-    width: 40px;
-    height: 10px;
-    color: #000;
-    font-weight: 600;
-    position: absolute;
-    left: 2px;
-    bottom: 1px;
-    z-index: 1000;
-    font-size: 10px;
-    text-align: center;
+}
+
+const data = computed(() => {
+
+  var index = 1;
+
+  return [{
+    id: 1,
+    label: "站点",
+    children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
+  },]
+});
+onMounted(() => {
+  if (treeRef.value) {
+    setTimeout(() => {
+      treeRef.value.expandNode(treeRef.value.getNode(1))
+    }, 100);
+    getSites();
+    initData();
+    // treeRef.value.expandNode(treeRef.value.getNode(1))
   }
-</style>
+});
+</script>
+
+<style lang="scss" scoped>
+.card-header {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+
+.boxunused {
+  background: #3333332d;
+}
+
+.indexDiv {
+  background-color: white;
+  width: 20px;
+  height: 10px;
+  color: #000;
+  font-weight: 600;
+  position: absolute;
+  right: 2px;
+  bottom: 1px;
+  z-index: 1000;
+  font-size: 10px;
+  text-align: center;
+}
+
+.indexDivLeft {
+  background-color: white;
+  width: 40px;
+  height: 10px;
+  color: #000;
+  font-weight: 600;
+  position: absolute;
+  left: 2px;
+  bottom: 1px;
+  z-index: 1000;
+  font-size: 10px;
+  text-align: center;
+}
+</style>

+ 596 - 588
src/views/yunying/scheduling/index.vue

@@ -1,23 +1,21 @@
 <template>
-    <div class="p-2">
-        <transition :enter-active-class="proxy?.animate.searchAnimate.enter"
-            :leave-active-class="proxy?.animate.searchAnimate.leave">
-            <div class="search" v-show="showSearch" style="display: flex;flex-direction: row;">
-                <div style="width: 55%;">
-                    <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
-                        <el-form-item label="车牌" prop="carNum">
-                            <el-input v-model="queryParams.carNum" placeholder="请输入车牌号" clearable style="width: 160px"
-                                @keyup.enter="handleQuery" />
-                        </el-form-item>
-                        <!-- <el-form-item label="状态" prop="carNum">
-                            <el-input v-model="queryParams.carNum" placeholder="请输入车牌号" clearable style="width: 160px"
-                                @keyup.enter="handleQuery" />
-                        </el-form-item> -->
-                        <el-form-item label="站点" prop="station">
-                            <el-input v-model="queryParams.station" placeholder="请输入站点" clearable style="width: 160px"
-                                @keyup.enter="handleQuery" />
-                        </el-form-item>
-                        <!-- <el-form-item label="司机" prop="carNum">
+  <div class="p-2">
+    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
+      <div class="search" v-show="showSearch" style="display: flex;flex-direction: row;">
+        <div style="width: 75%;">
+          <el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
+            <el-form-item label="车牌" prop="carNum">
+              <el-input v-model="queryParams.carNum" placeholder="请输入车牌号" clearable style="width: 160px" @keyup.enter="handleQuery" />
+            </el-form-item>
+
+            <el-form-item label="站点" prop="station">
+              <el-input v-model="queryParams.station" placeholder="请输入站点" clearable style="width: 160px" @keyup.enter="handleQuery" />
+            </el-form-item>
+
+            <el-form-item label="日期" prop="queryParams.params.scheduleDate">
+              <el-date-picker v-model="queryParams.params.scheduleDate" type="date" placeholder="选择日期" />
+            </el-form-item>
+            <!-- <el-form-item label="司机" prop="carNum">
                             <el-input v-model="queryParams.carNum" placeholder="请输入车牌号" clearable style="width: 160px"
                                 @keyup.enter="handleQuery" />
                         </el-form-item>
@@ -25,225 +23,252 @@
                             <el-date-picker v-model="value2" type="datetimerange" :shortcuts="shortcuts"
                                 range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间" />
                         </el-form-item> -->
-                    </el-form>
-                </div>
-                <div style="width: 45%;">
-                    <el-form-item>
-                        <!-- <el-button type="primary" @click="goadd">新增</el-button> -->
-                        <el-button type="primary" @click="resetQuery">查询</el-button>
-                    </el-form-item>
-                </div>
-            </div>
-        </transition>
-        <div style="text-align: center;margin-bottom:10px">
-            <el-tag type="success" effect="dark" round>正常作业</el-tag>
-            <el-tag style="margin-left: 40px;" type="danger" effect="dark" round>异常作业</el-tag>
+          </el-form>
         </div>
+        <div style="width: 25%;">
+          <el-form-item>
+            <!-- <el-button type="primary" @click="goadd">新增</el-button> -->
+            <el-button type="primary" @click="resetQuery">查询</el-button>
+          </el-form-item>
+        </div>
+      </div>
+    </transition>
+    <div style="text-align: center;margin-bottom:10px">
+      <el-tag type="success" effect="dark" round>正常作业</el-tag>
+      <el-tag style="margin-left: 40px;" type="danger" effect="dark" round>异常作业</el-tag>
+    </div>
 
-        <div v-if="reloadData">
-            <div v-for="(item, index) in carScheduleList">
-                <el-card shadow="never">
-                    <div class="carDiv" style="position: relative;">
-                        <div
-                            style="width: 18%;background: #7BC932;text-align: center;display: flex;flex-direction: column;justify-content: center;align-items:center;">
-                            <div class="carDetail">{{ item.carNum }}</div>
-                            <div class="carFont" style="font-size: 12px;">{{ getTimeFormat(item.pathInfo) }}</div>
-                            <div class="carFont" style="font-size: 12px;margin-top:8px;">{{ getAddr(item.pathInfo) }}
-                            </div>
-                            <!-- <div class="carFont">{{ JSON.parse(item.pathInfo).driver_info.nickName }}</div> -->
-                            <div class="carFont" style="font-size: 12px;margin-top:8px;color:rgba(255,255,255,0.9)">
-                                司机:{{ getUserName(JSON.parse(item.pathInfo).driverInfo) }}
-                            </div>
-                            <div class="carFont" style="font-size: 12px;margin-top:8px">{{ getCatInfo(item.carNum) }}
-                            </div>
-                        </div>
-                        <div style="width: 80%;">
-                            <el-scrollbar ref="scrollbarRef" height="400px" always @scroll="scroll">
-                                <timeLineDiv :list="JSON.parse(item.pathInfo).pathLine" :parentdata="item"
-                                    :stationInfo="JSON.parse(item.stationInfo)"></timeLineDiv>
-                            </el-scrollbar>
-                        </div>
-                        <div style="position:absolute;top:10px;right:6px">
-                            <div style="width: 30px;height: 30px; cursor: pointer;" @click="openMapDiv(item)">
-                                <img style="width: 28px;height: 28px;" src="@/assets/images/icon/map1.png" />
-                            </div>
-                            <div style="width: 30px;height: 20px; cursor: pointer;" @click="openVideo(item)">
-                                <img style="width: 28px;height: 28px;" src="@/assets/images/icon/cam.png" />
-                            </div>
-                        </div>
-                        <div style="position:absolute;bottom:10px;right:6px;font-size:10px">
-                            <span>客流:{{ gettotalpeople(item, 11) }}人 </span> <span style="margin-left: 10px;">乘客:{{
-                                gettotalpeople(item, 0) }}人 </span> <span style="margin-left: 10px;">货物:11个</span>
-                        </div>
-                    </div>
-                </el-card>
+    <div v-if="reloadData">
+      <div v-for="(item, index) in carScheduleList" :key="index">
+        <el-card shadow="never">
+          <div class="carDiv" style="position: relative;">
+            <div
+              style="width: 18%;background: #7BC932;text-align: center;display: flex;flex-direction: column;justify-content: center;align-items:center;"
+            >
+              <div class="carDetail">{{ item.carNum }}</div>
+              <div class="carFont" style="font-size: 12px;">{{ getTimeFormat(item.pathInfo) }}</div>
+              <div class="carFont" style="font-size: 12px;margin-top:8px;">{{ getAddr(item.pathInfo) }}</div>
+              <!-- <div class="carFont">{{ JSON.parse(item.pathInfo).driver_info.nickName }}</div> -->
+              <div class="carFont" style="font-size: 12px;margin-top:8px;color:rgba(255,255,255,0.9)">
+                司机:{{ getUserName(JSON.parse(item.pathInfo).driverInfo) }}
+              </div>
+              <div class="carFont" style="font-size: 12px;margin-top:8px">{{ getCatInfo(item.carNum) }}</div>
             </div>
-        </div>
+            <div style="width: 80%;">
+              <el-scrollbar ref="scrollbarRef" height="400px" always @scroll="scroll">
+                <timeLineDiv :list="JSON.parse(item.pathInfo).pathLine" :parentdata="item" :stationInfo="JSON.parse(item.stationInfo)"></timeLineDiv>
+              </el-scrollbar>
+            </div>
+            <div style="position:absolute;top:10px;right:6px">
+              <div style="width: 30px;height: 30px; cursor: pointer;" @click="openMapDiv(item)">
+                <img style="width: 28px;height: 28px;" src="@/assets/images/icon/map1.png" />
+              </div>
+              <div style="width: 30px;height: 20px; cursor: pointer;" @click="openVideo(item)">
+                <img style="width: 28px;height: 28px;" src="@/assets/images/icon/cam.png" />
+              </div>
+            </div>
+            <div style="position:absolute;bottom:10px;right:6px;font-size:10px">
+              <span>客流:{{ gettotalpeople(item, 11) }}人 </span>
+              <span style="margin-left: 10px;"
+                >乘客:{{
+                                gettotalpeople(item, 0)
+
+
+
 
-        <el-dialog v-if="dialogMap.visible" :title="dialogMap.title" v-model="dialogMap.visible" width="40vw"
-            append-to-body>
-            <mapDiv style="width:40vw;height:40vh;" ref="mapElmDiv"></mapDiv>
-        </el-dialog>
 
-        <el-dialog :title="dialog.title" v-model="dialog.visible" width="40vw" append-to-body
-            before-close="destoryVideo">
-            <video style="width: 99%;margin-left: 0.5%;" ref="videoElement" class="centeredVideo" controls autoplay
-                muted></video>
-        </el-dialog>
+
+
+
+
+                }}人
+              </span>
+              <span style="margin-left: 10px;">货物:11个</span>
+            </div>
+          </div>
+        </el-card>
+      </div>
     </div>
+
+    <el-dialog v-if="dialogMap.visible" :title="dialogMap.title" v-model="dialogMap.visible" width="40vw" append-to-body>
+      <mapDiv style="width:40vw;height:40vh;" ref="mapElmDiv"></mapDiv>
+    </el-dialog>
+
+    <el-dialog :title="dialog.title" v-model="dialog.visible" width="40vw" append-to-body before-close="destoryVideo">
+      <video style="width: 99%;margin-left: 0.5%;" ref="videoElement" class="centeredVideo" controls autoplay muted></video>
+    </el-dialog>
+  </div>
 </template>
 
 <script setup name="CarInfo" lang="ts">
-    import api from "@/api/system/user"
-    import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
-    import { listCarInfo, getCarInfo, delCarInfo, addCarInfo, updateCarInfo } from '@/api/carInfo';
-    import { CarInfoVO, CarInfoQuery, CarInfoForm } from '@/api/carInfo/types';
-    import { useRoute, useRouter } from "vue-router";
-    import timeLineDiv from "@/components/Public/timeline";
-    import { getDicts } from '@/api/system/dict/data'
-    import useTagsViewStore from '@/store/modules/tagsView';
-    import mapDiv from "@/components/Map/index.vue"
-    import { listCarSchedule, getCarSchedule, delCarSchedule, addCarSchedule, updateCarSchedule } from '@/api/carSchedule';
-    import { CarScheduleVO, CarScheduleQuery, CarScheduleForm } from '@/api/carSchedule/types';
-    import moment from 'moment';
-    import { getCountData } from '@/api/gpsData';
-    import { countData } from '@/api/gpsData/type';
-
-
-
-    import flvjs from "flv.js";
-    import { values } from "video.js/dist/types/utils/obj";
-
-
-
-    const route = useRoute();
-    const router = useRouter();
-
-    const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-    const carInfoList = ref < CarInfoVO[] > ([]);
-    // const videoElement = ref(video)
-    const buttonLoading = ref(false);
-    const loading = ref(true);
-    const showSearch = ref(true);
-    const ids = ref < Array < string | number >> ([]);
-    const single = ref(true);
-    const multiple = ref(true);
-    const total = ref(0);
-    const value2 = ref('')
-    const flvPlayer = ref(null);
-    const carScheduleList = ref < CarScheduleVO[] > ([]);
-    const timer = ref(null);
-    const mapTimer = ref(null);
-
-    const queryFormRef = ref < ElFormInstance > ();
-    const carInfoFormRef = ref < ElFormInstance > ();
-
-
-    const gettotalpeople = (item, type) => {
-        if (item.peoplecount != undefined && item.peoplecount != null) {
-            var totalpeople = item.peoplecount['total'];
-            if (type == 1) {
-                return totalpeople.totalin - totalpeople.totalout > 0 ? totalpeople.totalin - totalpeople.totalout : 0;
-            }
-            if (type == 0) {
-                return totalpeople.totalin;
-            }
-
+import api from "@/api/system/user"
+import { UserForm, UserQuery, UserVO } from '@/api/system/user/types';
+import { listCarInfo, getCarInfo, delCarInfo, addCarInfo, updateCarInfo } from '@/api/carInfo';
+import { CarInfoVO, CarInfoQuery, CarInfoForm } from '@/api/carInfo/types';
+import { useRoute, useRouter } from "vue-router";
+import timeLineDiv from "@/components/Public/timeline";
+import { getDicts } from '@/api/system/dict/data'
+import useTagsViewStore from '@/store/modules/tagsView';
+import mapDiv from "@/components/Map/index.vue"
+import { listCarSchedule, getCarSchedule, delCarSchedule, addCarSchedule, updateCarSchedule } from '@/api/carSchedule';
+import { CarScheduleVO, CarScheduleQuery, CarScheduleForm } from '@/api/carSchedule/types';
+import moment from 'moment';
+import { getCountData } from '@/api/gpsData';
+import { countData } from '@/api/gpsData/type';
+
+
+
+import flvjs from "flv.js";
+import { values } from "video.js/dist/types/utils/obj";
+
+
+
+const route = useRoute();
+const router = useRouter();
+
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+
+const carInfoList = ref <CarInfoVO[]> ([]);
+// const videoElement = ref(video)
+const buttonLoading = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref < Array < string | number >> ([]);
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const value2 = ref('')
+const flvPlayer = ref(null);
+const carScheduleList = ref < CarScheduleVO[] > ([]);
+const timer = ref(null);
+const mapTimer = ref(null);
+
+const queryFormRef = ref < ElFormInstance > ();
+const carInfoFormRef = ref < ElFormInstance > ();
+
+
+const gettotalpeople = (item, type) => {
+    if (item.peoplecount != undefined && item.peoplecount != null) {
+        var totalpeople = item.peoplecount['total'];
+        if (type == 1) {
+            return totalpeople.totalin - totalpeople.totalout > 0 ? totalpeople.totalin - totalpeople.totalout : 0;
         }
-        return 0;
-    }
-
-    const flvLoad = (url) => {
-        console.log(flvjs.isSupported())
-        if (flvjs.isSupported()) {
-            let videoElement = proxy.$refs.videoElement;
-            flvPlayer.value = flvjs.createPlayer(
-                {
-                    type: "flv", //媒体类型
-                    url: url || '', //flv格式媒体URL
-                    isLive: true, //数据源是否为直播流
-                    hasAudio: false, //数据源是否包含有音频
-                    hasVideo: true, //数据源是否包含有视频
-                    enableStashBuffer: false, //是否启用缓存区
-                },
-                {
-                    enableWorker: false, // 是否启用分离的线程进行转换
-                    enableStashBuffer: false, //关闭IO隐藏缓冲区
-                    autoCleanupSourceBuffer: true, //自动清除缓存
-                }
-            );
-            flvPlayer.value.attachMediaElement(videoElement); //将播放实例注册到节点
-            flvPlayer.value.load(); //加载数据流
-            flvPlayer.value.play(); //播放数据流
+        if (type == 0) {
+            return totalpeople.totalin;
         }
-    }
 
-    const openVideo = (item) => {
-        var findVideo = false
-        for (var index in carInfoList.value) {
-            if (carInfoList.value[index].carNum == item.carNum) {
-                if (carInfoList.value[index].deviceInfos != null && carInfoList.value[index].deviceInfos != '') {
-                    var drivesInfo = JSON.parse(carInfoList.value[index].deviceInfos)
-                    console.log(drivesInfo)
-                    for(var j in drivesInfo){
-                          if(drivesInfo[j].type == "摄像头"){
-                            findVideo = true
-                            dialog.visible = true;
-                            setTimeout(() => {
-                                flvLoad(drivesInfo[j].code)
-                            }, 1000);
-                          }
-                    }
+    }
+    return 0;
+}
+
+const flvLoad = (url) => {
+    console.log(flvjs.isSupported())
+    if (flvjs.isSupported()) {
+        let videoElement = proxy.$refs.videoElement;
+        flvPlayer.value = flvjs.createPlayer(
+            {
+                type: "flv", //媒体类型
+                url: url || '', //flv格式媒体URL
+                isLive: true, //数据源是否为直播流
+                hasAudio: false, //数据源是否包含有音频
+                hasVideo: true, //数据源是否包含有视频
+                enableStashBuffer: false, //是否启用缓存区
+            },
+            {
+                enableWorker: false, // 是否启用分离的线程进行转换
+                enableStashBuffer: false, //关闭IO隐藏缓冲区
+                autoCleanupSourceBuffer: true, //自动清除缓存
+            }
+        );
+        flvPlayer.value.attachMediaElement(videoElement); //将播放实例注册到节点
+        flvPlayer.value.load(); //加载数据流
+        flvPlayer.value.play(); //播放数据流
+    }
+}
+
+const openVideo = (item) => {
+    var findVideo = false
+    for (var index in carInfoList.value) {
+        if (carInfoList.value[index].carNum == item.carNum) {
+            if (carInfoList.value[index].deviceInfos != null && carInfoList.value[index].deviceInfos != '') {
+                var drivesInfo = JSON.parse(carInfoList.value[index].deviceInfos)
+                console.log(drivesInfo)
+                for(var j in drivesInfo){
+                      if(drivesInfo[j].type == "摄像头"){
+                        findVideo = true
+                        dialog.visible = true;
+                        setTimeout(() => {
+                            flvLoad(drivesInfo[j].code)
+                        }, 1000);
+                      }
                 }
             }
         }
-        if (!findVideo) {
-            ElMessage({
-                message: '该车辆未配置摄像头',
-                type: 'warning',
-            })
-        }
     }
-
-    const destoryVideo = () => {
-        if (flvPlayer.value) {
-            flvPlayer.value.pause();
-            flvPlayer.value.unload();
-            flvPlayer.value.detachMediaElement();
-            flvPlayer.value.destroy();
-            flvPlayer.value = null;
-        }
+    if (!findVideo) {
+        ElMessage({
+            message: '该车辆未配置摄像头',
+            type: 'warning',
+        })
     }
-
-
-    const dialogMap = reactive < DialogOption > ({
-        visible: false,
-        title: '地图'
-    });
-
-    const dialog = reactive < DialogOption > ({
-        visible: false,
-        title: '在线视频'
-    });
-
-    const mapElmDiv = ref(mapDiv)
-
-    const columns = ref([
-        // {label: '上层位置', prop: 'v', visible: true},
-        { label: '姓名', prop: 'carNum', visible: true, isTemplate: false },
-        { label: '身份证', prop: 'workTime', visible: true, isTemplate: false, },
-        { label: '手机号', prop: 'workName', pprop: "ext1", visible: true, isTemplate: false },
-        { label: '设备号', prop: 'type', pprop: "ext1", visible: true, isTemplate: false, },
-        { label: '车辆', prop: 'wangge', pprop: "ext1", visible: true, isTemplate: false, },
-        { label: '工作小组', prop: 'gpeople', pprop: "ext1", visible: true, isTemplate: false, },
-        { label: '类型', prop: 'people', pprop: "ext1", visible: true, isTemplate: false, },
-    ])
-
-    const reloadData = ref(true)
-
-    const initFormData: CarInfoForm = {
-        id: undefined,
+}
+
+const destoryVideo = () => {
+    if (flvPlayer.value) {
+        flvPlayer.value.pause();
+        flvPlayer.value.unload();
+        flvPlayer.value.detachMediaElement();
+        flvPlayer.value.destroy();
+        flvPlayer.value = null;
+    }
+}
+
+
+const dialogMap = reactive < DialogOption > ({
+    visible: false,
+    title: '地图'
+});
+
+const dialog = reactive < DialogOption > ({
+    visible: false,
+    title: '在线视频'
+});
+
+const mapElmDiv = ref(mapDiv)
+
+const columns = ref([
+    // {label: '上层位置', prop: 'v', visible: true},
+    { label: '姓名', prop: 'carNum', visible: true, isTemplate: false },
+    { label: '身份证', prop: 'workTime', visible: true, isTemplate: false, },
+    { label: '手机号', prop: 'workName', pprop: "ext1", visible: true, isTemplate: false },
+    { label: '设备号', prop: 'type', pprop: "ext1", visible: true, isTemplate: false, },
+    { label: '车辆', prop: 'wangge', pprop: "ext1", visible: true, isTemplate: false, },
+    { label: '工作小组', prop: 'gpeople', pprop: "ext1", visible: true, isTemplate: false, },
+    { label: '类型', prop: 'people', pprop: "ext1", visible: true, isTemplate: false, },
+])
+
+const reloadData = ref(true)
+
+const initFormData: CarInfoForm = {
+    id: undefined,
+    carNum: undefined,
+    carType: undefined,
+    deviceInfos: undefined,
+    repairInfo: undefined,
+    maintenanceInfo: undefined,
+    insuranceInfo: undefined,
+    inspectionInfo: undefined,
+    trafficAccidentInfo: undefined,
+    violationInfo: undefined,
+    changeInfo: undefined,
+    ext1: undefined,
+    ext2: undefined
+}
+const data = reactive <PageData<CarInfoForm, CarInfoQuery>> ({
+    form: { ...initFormData },
+    queryParams: {
+        pageNum: 1,
+        pageSize: 10,
         carNum: undefined,
         carType: undefined,
         deviceInfos: undefined,
@@ -255,406 +280,389 @@
         violationInfo: undefined,
         changeInfo: undefined,
         ext1: undefined,
-        ext2: undefined
-    }
-    const data = reactive < PageData < CarInfoForm, CarInfoQuery>> ({
-        form: { ...initFormData },
-        queryParams: {
-            pageNum: 1,
-            pageSize: 10,
-            carNum: undefined,
-            carType: undefined,
-            deviceInfos: undefined,
-            repairInfo: undefined,
-            maintenanceInfo: undefined,
-            insuranceInfo: undefined,
-            inspectionInfo: undefined,
-            trafficAccidentInfo: undefined,
-            violationInfo: undefined,
-            changeInfo: undefined,
-            ext1: undefined,
-            ext2: undefined,
-            params: {
-            }
-        },
-        rules: {
-            id: [
-                { required: true, message: "编号不能为空", trigger: "blur" }
-            ],
-            carNum: [
-                { required: true, message: "车牌号不能为空", trigger: "blur" }
-            ],
-            carType: [
-                { required: true, message: "车类型不能为空", trigger: "change" }
-            ],
-            deviceInfos: [
-                { required: true, message: "所有车载设备信息不能为空", trigger: "blur" }
-            ],
-            repairInfo: [
-                { required: true, message: "维修信息不能为空", trigger: "blur" }
-            ],
-            maintenanceInfo: [
-                { required: true, message: "保养信息不能为空", trigger: "blur" }
-            ],
-            insuranceInfo: [
-                { required: true, message: "保险信息不能为空", trigger: "blur" }
-            ],
-            inspectionInfo: [
-                { required: true, message: "年检信息不能为空", trigger: "blur" }
-            ],
-            trafficAccidentInfo: [
-                { required: true, message: "交通事故信息不能为空", trigger: "blur" }
-            ],
-            violationInfo: [
-                { required: true, message: "违章信息不能为空", trigger: "blur" }
-            ],
-            changeInfo: [
-                { required: true, message: "车辆变更信息不能为空", trigger: "blur" }
-            ],
-            ext1: [
-                { required: true, message: "扩展1不能为空", trigger: "blur" }
-            ],
-            ext2: [
-                { required: true, message: "扩展2不能为空", trigger: "blur" }
-            ]
+        ext2: undefined,
+      params: {
+          scheduleDate:moment().format('YYYY-MM-DD')
         }
-    });
-
-    const { queryParams, form, rules } = toRefs(data);
-
-    const carTypeList = ref([]);
-    const energyTypeList = ref([])
-    const bussinessTypeList = ref([])
-
-    const userList = ref < UserVO[] > ();
-
-    const goadd = () => {
-        useTagsViewStore().delView(route);
-        router.push("/car/work/addWork")
+    },
+    rules: {
+        id: [
+            { required: true, message: "编号不能为空", trigger: "blur" }
+        ],
+        carNum: [
+            { required: true, message: "车牌号不能为空", trigger: "blur" }
+        ],
+        carType: [
+            { required: true, message: "车类型不能为空", trigger: "change" }
+        ],
+        deviceInfos: [
+            { required: true, message: "所有车载设备信息不能为空", trigger: "blur" }
+        ],
+        repairInfo: [
+            { required: true, message: "维修信息不能为空", trigger: "blur" }
+        ],
+        maintenanceInfo: [
+            { required: true, message: "保养信息不能为空", trigger: "blur" }
+        ],
+        insuranceInfo: [
+            { required: true, message: "保险信息不能为空", trigger: "blur" }
+        ],
+        inspectionInfo: [
+            { required: true, message: "年检信息不能为空", trigger: "blur" }
+        ],
+        trafficAccidentInfo: [
+            { required: true, message: "交通事故信息不能为空", trigger: "blur" }
+        ],
+        violationInfo: [
+            { required: true, message: "违章信息不能为空", trigger: "blur" }
+        ],
+        changeInfo: [
+            { required: true, message: "车辆变更信息不能为空", trigger: "blur" }
+        ],
+        ext1: [
+            { required: true, message: "扩展1不能为空", trigger: "blur" }
+        ],
+        ext2: [
+            { required: true, message: "扩展2不能为空", trigger: "blur" }
+        ]
     }
-
-    const getScheduleList = async () => {
-        console.log(value2.value)
-        var startTime = moment(value2.value[0]).format('YYYY-MM-DD')
-        var endTime = moment(value2.value[1]).format('YYYY-MM-DD')
-        reloadData.value = false;
-        var date = new Date();
-        var param = {
-            params: {
-                scheduleDate: moment(date).format('YYYY-MM-DD'),
-                carNum: queryParams.value.carNum,
-                station: queryParams.value.station
-                // starttime:startTime,
-                // endtime:endTime
-                // scheduleDate: '2024-03-16'
-            },
-            pageSize: "1000"
-        }
-        carScheduleList.value = [];
-        const res = await listCarSchedule(param);
-        // carScheduleList.value = res.rows;
-        res.rows.map(i => {
-            var pathLine = JSON.parse(i.pathInfo).pathLine
-            var endTime = moment(date).format('YYYY-MM-DD') + ' ' + pathLine[pathLine.length - 1].planInTime
-            // console.log(new Date().getTime() )
-            // console.log(new Date(endTime).getTime())
-            if (new Date().getTime() < new Date(endTime).getTime()) {
-                if (i.ext1 != undefined && i.ext1 != null) {
-                    var datajson = JSON.parse(i.ext1)
-                    var times = Object.values(datajson).map(j => {
-                        return j.intime + "|" + j.outtime
-                    }).join("$");
-                    times += "$" + i.scheduleDate + "|" + moment().format("YYYY-MM-DD HH:mm:ss")
-                    getCountData({ "params[times]": `${times}` }).then(res1 => {
-                        var pcount = {}
-                        var index = 0;
-                        Object.keys(datajson).map(j => {
-                            pcount[j] = res1.data[index++]
-                        })
-                        pcount['total'] = res1.data[index]
-                        i['peoplecount'] = pcount;
-                    });
-                }
-                carScheduleList.value.push(i)
-            }
-        })
-        //测试用
-        // carScheduleList.value = res.rows;
-        reloadData.value = true
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+const carTypeList = ref([]);
+const energyTypeList = ref([])
+const bussinessTypeList = ref([])
+
+const userList = ref < UserVO[] > ();
+
+const goadd = () => {
+    useTagsViewStore().delView(route);
+    router.push("/car/work/addWork")
+}
+
+const getScheduleList = async () => {
+    var startTime = moment(value2.value[0]).format('YYYY-MM-DD')
+    var endTime = moment(value2.value[1]).format('YYYY-MM-DD')
+    reloadData.value = false;
+    var date = new Date();
+    var param = {
+        params: {
+            scheduleDate: moment(queryParams.value.params.scheduleDate).format('YYYY-MM-DD'),
+            carNum: queryParams.value.carNum,
+            station: queryParams.value.station
+            // starttime:startTime,
+            // endtime:endTime
+            // scheduleDate: '2024-03-16'
+        },
+        pageSize: "1000"
     }
-
-    const getTimeFormat = (data) => {
-        var value = JSON.parse(data).pathLine
-        if (value.length > 0) {
-            if (value[0].planInTime && value[value.length - 1].planInTime) {
-                return value[0].planInTime + '-' + value[value.length - 1].planInTime
-            } else {
-                return "请填写路线时间"
+    carScheduleList.value = [];
+    const res = await listCarSchedule(param);
+  // carScheduleList.value = res.rows;
+
+    res.rows.map(i => {
+        var pathLine = JSON.parse(i.pathInfo).pathLine
+        var endTime = moment(date).format('YYYY-MM-DD') + ' ' + pathLine[pathLine.length - 1].planInTime
+        // console.log(new Date().getTime() )
+      // console.log(new Date(endTime).getTime())
+
+        if (new Date().getTime() < new Date(endTime).getTime()) {
+            if (i.ext1 != undefined && i.ext1 != null) {
+                var datajson = JSON.parse(i.ext1)
+                var times = Object.values(datajson).map(j => {
+                    return j.intime + "|" + j.outtime
+                }).join("$");
+                times += "$" + i.scheduleDate + "|" + moment().format("YYYY-MM-DD HH:mm:ss")
+                getCountData({ "params[times]": `${times}` }).then(res1 => {
+                    var pcount = {}
+                    var index = 0;
+                    Object.keys(datajson).map(j => {
+                        pcount[j] = res1.data[index++]
+                    })
+                    pcount['total'] = res1.data[index]
+                    i['peoplecount'] = pcount;
+                });
             }
+            carScheduleList.value.push(i)
+        }
+    })
+    //测试用
+    // carScheduleList.value = res.rows;
+    reloadData.value = true
+}
+
+const getTimeFormat = (data) => {
+    var value = JSON.parse(data).pathLine
+    if (value.length > 0) {
+        if (value[0].planInTime && value[value.length - 1].planInTime) {
+            return value[0].planInTime + '-' + value[value.length - 1].planInTime
         } else {
             return "请填写路线时间"
         }
+    } else {
+        return "请填写路线时间"
     }
+}
 
-    const getAddr = (data) => {
-        var value = JSON.parse(data).pathLine
-        if (value.length > 0) {
-            return value[0].stationName + '-' + value[value.length - 1].stationName
-        }
-    }
-
-    const getList = async () => {
-        console.log(value2.value)
-        // queryParams.value.starttime = value2.value
-        const res = await listCarInfo({ pageSize: 1000 });
-        carInfoList.value = res.rows
-        //   console.log(res);
-    }
-
-    const getDictsData = (param, obj) => {
-        getDicts(param).then(res => {
-            obj.value = res.data;
-        })
+const getAddr = (data) => {
+    var value = JSON.parse(data).pathLine
+    if (value.length > 0) {
+        return value[0].stationName + '-' + value[value.length - 1].stationName
     }
+}
+
+const getList = async () => {
+    console.log(value2.value)
+    // queryParams.value.starttime = value2.value
+    const res = await listCarInfo({ pageSize: 1000 });
+    carInfoList.value = res.rows
+}
+
+const getDictsData = (param, obj) => {
+    getDicts(param).then(res => {
+        obj.value = res.data;
+    })
+}
 
-    /** 取消按钮 */
-    const cancel = () => {
-        reset();
-        dialog.visible = false;
-    }
+/** 取消按钮 */
+const cancel = () => {
+    reset();
+    dialog.visible = false;
+}
 
-    const getUserList = () => {
-        api.listUser({ pageSize: 1000 }).then(res => {
-            userList.value = res.rows;
-        });
-    }
+const getUserList = () => {
+    api.listUser({ pageSize: 1000 }).then(res => {
+        userList.value = res.rows;
+    });
+}
 
-    const getUserName = (value) => {
-        for (var index in userList.value) {
-            if (value == userList.value[index].userId) {
-                return userList.value[index].nickName
-            }
+const getUserName = (value) => {
+    for (var index in userList.value) {
+        if (value == userList.value[index].userId) {
+            return userList.value[index].nickName
         }
     }
-
-    /** 表单重置 */
-    const reset = () => {
-        form.value = { ...initFormData };
-        carInfoFormRef.value?.resetFields();
-    }
-
-    /** 搜索按钮操作 */
-    const handleQuery = () => {
-        queryParams.value.pageNum = 1;
-        getList();
+}
+
+/** 表单重置 */
+const reset = () => {
+    form.value = { ...initFormData };
+    carInfoFormRef.value?.resetFields();
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+    queryParams.value.pageNum = 1;
+    getList();
+}
+
+const openMapDiv = (data) => {
+    dialogMap.visible = true;
+    const info = getCatInfoData(data.carNum);
+    console.log(info)
+    var deviceInfo = JSON.parse(info.deviceInfos)
+    console.log(deviceInfo)
+    var code = '';
+    for (var index in deviceInfo) {
+        if (deviceInfo[index].type == 'gps') {
+            code = deviceInfo[index].code
+        }
     }
-
-    const openMapDiv = (data) => {
-        dialogMap.visible = true;
-        const info = getCatInfoData(data.carNum);
-        console.log(info)
-        var deviceInfo = JSON.parse(info.deviceInfos)
-        console.log(deviceInfo)
-        var code = '';
-        for (var index in deviceInfo) {
-            if (deviceInfo[index].type == 'gps') {
-                code = deviceInfo[index].code
+    var value = JSON.parse(data.pathInfo).pathLine
+    var date = moment(new Date()).format('YYYY-MM-DD')
+    if (value[0].planInTime && value[value.length - 1].planInTime) {
+        var param = {
+            devicecode: code,
+            params: {
+                starttime: date + ' ' + value[0].planInTime,
+                endtime: date + ' ' + value[value.length - 1].planInTime,
             }
         }
-        var value = JSON.parse(data.pathInfo).pathLine
-        var date = moment(new Date()).format('YYYY-MM-DD')
-        if (value[0].planInTime && value[value.length - 1].planInTime) {
-            var param = {
-                devicecode: code,
-                params: {
-                    starttime: date + ' ' + value[0].planInTime,
-                    endtime: date + ' ' + value[value.length - 1].planInTime,
+        // console.log(mapElm.value);
+        // mapElm.value.getGpsDataList(param);
+        setTimeout(() => {
+            mapElmDiv.value.getGpsDataList(param);
+            mapTimer.value = setInterval(() => {
+                console.log(2222222222222)
+                console.log(dialogMap.visible)
+                if (dialogMap.visible) {
+                    console.log(222222)
+                    mapElmDiv.value.getGpsDataList(param);
                 }
-            }
-            // console.log(mapElm.value);
-            // mapElm.value.getGpsDataList(param);
-            setTimeout(() => {
-                mapElmDiv.value.getGpsDataList(param);
-                mapTimer.value = setInterval(() => {
-                    console.log(2222222222222)
-                    console.log(dialogMap.visible)
-                    if (dialogMap.visible) {
-                        console.log(222222)
-                        mapElmDiv.value.getGpsDataList(param);
-                    }
-                }, 30000);
-            }, 1000);
-        }
+            }, 30000);
+        }, 1000);
     }
-
-    /** 重置按钮操作 */
-    const resetQuery = () => {
-        //queryFormRef.value?.resetFields();
-        //handleQuery();
-        getScheduleList();
-        // reloadData.value = false;
-        // setTimeout(() => {
-        //     reloadData.value = true;
-        // }, 500);
-    }
-
-    /** 多选框选中数据 */
-    const handleSelectionChange = (selection: CarInfoVO[]) => {
-        ids.value = selection.map(item => item.id);
-        single.value = selection.length != 1;
-        multiple.value = !selection.length;
-    }
-
-    /** 新增按钮操作 */
-    const handleAdd = () => {
-        reset();
-        dialog.visible = true;
-        dialog.title = "添加车辆信息";
-    }
-
-    /** 修改按钮操作 */
-    const handleUpdate = async (row?: CarInfoVO) => {
-        reset();
-        const _id = row?.id || ids.value[0]
-        const res = await getCarInfo(_id);
-        Object.assign(form.value, res.data);
-        dialog.visible = true;
-        dialog.title = "修改车辆信息";
-    }
-
-    /** 提交按钮 */
-    const submitForm = () => {
-        carInfoFormRef.value?.validate(async (valid: boolean) => {
-            if (valid) {
-                buttonLoading.value = true;
-                if (form.value.id) {
-                    await updateCarInfo(form.value).finally(() => buttonLoading.value = false);
-                } else {
-                    await addCarInfo(form.value).finally(() => buttonLoading.value = false);
-                }
-                proxy?.$modal.msgSuccess("修改成功");
-                dialog.visible = false;
-                await getList();
-            }
-        });
-    }
-
-    /** 删除按钮操作 */
-    const handleDelete = async (row?: CarInfoVO) => {
-        const _ids = row?.id || ids.value;
-        await proxy?.$modal.confirm('是否确认删除车辆信息编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
-        await delCarInfo(_ids);
-        proxy?.$modal.msgSuccess("删除成功");
-        await getList();
-    }
-
-    /** 导出按钮操作 */
-    const handleExport = () => {
-        proxy?.download('system/carInfo/export', {
-            ...queryParams.value
-        }, `carInfo_${new Date().getTime()}.xlsx`)
-    }
-
-    const initData = async () => {
-        await getDictsData('tbl_car_type', carTypeList);
-        await getDictsData('energy_type', energyTypeList);
-        await getDictsData('business_type', bussinessTypeList);
-        await getList();
-        await getUserList();
-        getScheduleList();
-    }
-
-    const getDictLabel = (value, list) => {
-        for (var index in list.value) {
-            // console.log(list[index])
-            if (list.value[index].dictValue == value) {
-                return list.value[index].dictLabel
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+    //queryFormRef.value?.resetFields();
+    //handleQuery();
+    getScheduleList();
+    // reloadData.value = false;
+    // setTimeout(() => {
+    //     reloadData.value = true;
+    // }, 500);
+}
+
+/** 多选框选中数据 */
+const handleSelectionChange = (selection: CarInfoVO[]) => {
+    ids.value = selection.map(item => item.id);
+    single.value = selection.length != 1;
+    multiple.value = !selection.length;
+}
+
+/** 新增按钮操作 */
+const handleAdd = () => {
+    reset();
+    dialog.visible = true;
+    dialog.title = "添加车辆信息";
+}
+
+/** 修改按钮操作 */
+const handleUpdate = async (row?: CarInfoVO) => {
+    reset();
+    const _id = row?.id || ids.value[0]
+    const res = await getCarInfo(_id);
+    Object.assign(form.value, res.data);
+    dialog.visible = true;
+    dialog.title = "修改车辆信息";
+}
+
+/** 提交按钮 */
+const submitForm = () => {
+    carInfoFormRef.value?.validate(async (valid: boolean) => {
+        if (valid) {
+            buttonLoading.value = true;
+            if (form.value.id) {
+                await updateCarInfo(form.value).finally(() => buttonLoading.value = false);
+            } else {
+                await addCarInfo(form.value).finally(() => buttonLoading.value = false);
             }
+            proxy?.$modal.msgSuccess("修改成功");
+            dialog.visible = false;
+            await getList();
+        }
+    });
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (row?: CarInfoVO) => {
+    const _ids = row?.id || ids.value;
+    await proxy?.$modal.confirm('是否确认删除车辆信息编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
+    await delCarInfo(_ids);
+    proxy?.$modal.msgSuccess("删除成功");
+    await getList();
+}
+
+/** 导出按钮操作 */
+const handleExport = () => {
+    proxy?.download('system/carInfo/export', {
+        ...queryParams.value
+    }, `carInfo_${new Date().getTime()}.xlsx`)
+}
+
+const initData = async () => {
+    await getDictsData('tbl_car_type', carTypeList);
+    await getDictsData('energy_type', energyTypeList);
+    await getDictsData('business_type', bussinessTypeList);
+    await getList();
+    await getUserList();
+    getScheduleList();
+}
+
+const getDictLabel = (value, list) => {
+    for (var index in list.value) {
+        // console.log(list[index])
+        if (list.value[index].dictValue == value) {
+            return list.value[index].dictLabel
         }
     }
+}
 
-    const getCatInfo = (value) => {
-        for (var index in carInfoList.value) {
-            if (carInfoList.value[index].carNum == value) {
-                var data = JSON.parse(carInfoList.value[index].ext1)
-                return getDictLabel(data.energyType, energyTypeList).replaceAll("车", "") + getDictLabel(data.bussinessType, bussinessTypeList)
-            }
+const getCatInfo = (value) => {
+    for (var index in carInfoList.value) {
+        if (carInfoList.value[index].carNum == value) {
+            var data = JSON.parse(carInfoList.value[index].ext1)
+            return getDictLabel(data.energyType, energyTypeList).replaceAll("车", "") + getDictLabel(data.bussinessType, bussinessTypeList)
         }
     }
+}
 
-    const getCatInfoData = (value) => {
-        for (var index in carInfoList.value) {
-            if (carInfoList.value[index].carNum == value) {
-                return carInfoList.value[index]
-            }
+const getCatInfoData = (value) => {
+    for (var index in carInfoList.value) {
+        if (carInfoList.value[index].carNum == value) {
+            return carInfoList.value[index]
         }
     }
+}
 
-    onUnmounted(() => {
+onUnmounted(() => {
 
-    })
+})
 
-    onBeforeUnmount(() => {
-        clearInterval(timer.value)
-        clearInterval(mapTimer.value)
-        timer.value = null;
-        mapTimer.value = null;
-    })
+onBeforeUnmount(() => {
+    clearInterval(timer.value)
+    clearInterval(mapTimer.value)
+    timer.value = null;
+    mapTimer.value = null;
+})
 
-    onMounted(() => {
-        initData();
-        //每5s刷新数据
-        timer.value = setInterval(() => {
-            console.log(11111)
-            getScheduleList();
-            reloadData.value = false;
-            setTimeout(() => {
-                reloadData.value = true;
-            }, 500);
-        }, 30000);
-        // mapTimer.value = setInterval(() => {
-        //     console.log(2222222222222)
-        //     console.log(dialog.visible)
-        //     if (dialog.visible) {
-        //         console.log(222222)
-        //         mapElmDiv.value.getGpsDataList(param);
-        //     }
-        // }, 2000);
-    });
+onMounted(() => {
+    initData();
+    //每5s刷新数据
+    timer.value = setInterval(() => {
+        console.log(11111)
+        getScheduleList();
+        reloadData.value = false;
+        setTimeout(() => {
+            reloadData.value = true;
+        }, 500);
+    }, 30000);
+    // mapTimer.value = setInterval(() => {
+    //     console.log(2222222222222)
+    //     console.log(dialog.visible)
+    //     if (dialog.visible) {
+    //         console.log(222222)
+    //         mapElmDiv.value.getGpsDataList(param);
+    //     }
+    // }, 2000);
+});
 </script>
 
 <style lang="scss" scoped>
-    .carDiv {
-        border-radius: 7px;
-        opacity: 1;
-        box-sizing: border-box;
-        border: 1px solid #7BC932;
-        height: 25vh;
-        display: flex;
-        flex-direction: row;
-    }
-
-    .carDetail {
-        width: 135px;
-        padding: 5px 10px;
-        border-radius: 22px;
-        opacity: 1;
-        background: #FFFFFF;
-        font-family: 思源黑体;
-        font-size: 18px;
-        font-weight: bold;
-        margin-bottom: 6px;
-        color: #7BC932;
-    }
-
-    .carFont {
-        font-family: 思源黑体;
-        font-size: 16px;
-        font-weight: bold;
-        line-height: normal;
-        align-items: center;
-        letter-spacing: 0px;
-        font-feature-settings: "kern" on;
-        color: #FFFFFF;
-    }
-</style>
+.carDiv {
+    border-radius: 7px;
+    opacity: 1;
+    box-sizing: border-box;
+    border: 1px solid #7BC932;
+    height: 25vh;
+    display: flex;
+    flex-direction: row;
+}
+
+.carDetail {
+    width: 135px;
+    padding: 5px 10px;
+    border-radius: 22px;
+    opacity: 1;
+    background: #FFFFFF;
+    font-family: 思源黑体;
+    font-size: 18px;
+    font-weight: bold;
+    margin-bottom: 6px;
+    color: #7BC932;
+}
+
+.carFont {
+    font-family: 思源黑体;
+    font-size: 16px;
+    font-weight: bold;
+    line-height: normal;
+    align-items: center;
+    letter-spacing: 0px;
+    font-feature-settings: "kern" on;
+    color: #FFFFFF;
+}
+</style>

+ 259 - 262
src/views/yunying/video/index.vue → src/views/yunying/sties/index.vue

@@ -2,7 +2,7 @@
 <template>
   <div class="p-2" style="padding: 10px">
     <div style="display: flex; flex-direction: row">
-      <div style="width: 20%">
+      <div style="width: 20%;">
         <div class="card-header">
           <div style="display: flex; flex-direction: row">
             <div style="width: 4px; height: 19px; opacity: 1; background: #409eff"></div>
@@ -16,12 +16,12 @@
               ">站点列表</span>
           </div>
         </div>
-        <div style="margin-top: 20px; padding-left: 10px">
+        <div style="margin-top: 20px; padding-left: 10px;">
           <el-select v-model="line" placeholder="请选择路线" style="width: 240px" @change="getLineSites()">
             <el-option v-for="item in carPathList" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
           <el-input style="margin-top: 10px;" v-model="filterText" placeholder="输入关键字" />
-          <el-tree-v2 v-if="showTree" style="margin-top: 10px" ref="treeRef" class="filter-tree"
+          <el-tree-v2 v-if="showTree" style="margin-top: 10px;" ref="treeRef" class="filter-tree"
             :height="gettreeheight()" :data="data" :indent="treeIndent" :props="defaultProps"
             :filter-method="filterNode" @node-click="treeclick">
             <template v-slot:default="{ node }">
@@ -47,7 +47,7 @@
 
 
           </div>
-          <el-button v-if="tableData.length > 0 && tableData.length < 4" type="primary"
+          <el-button v-if="tableData.length < 4" type="primary"
             style="position: absolute;right: 20px;" @click="goAdd">添加设备</el-button>
         </div>
         <div style="margin-top: 20px">
@@ -153,311 +153,308 @@
 </template>
 
 <script setup name="CarInfo" lang="ts">
-  import { TreeNode } from "element-plus";
-  import { useRoute, useRouter } from "vue-router";
-  import EZUIKit from 'ezuikit-js';
-  import { getCameraPlayerConfig } from '@/api/gpsData';
-  import { listCarPath, getCarPath, delCarPath, addCarPath, updateCarPath } from '@/api/carPath';
-  import { updateData, listData } from "@/api/system/dict/data";
-  import imgulock from "@/assets/images/unlock@2x.png";
+import { TreeNode } from "element-plus";
+import { useRoute, useRouter } from "vue-router";
+import EZUIKit from 'ezuikit-js';
+import { getCameraPlayerConfig } from '@/api/gpsData';
+import { listCarPath, getCarPath, delCarPath, addCarPath, updateCarPath } from '@/api/carPath';
+import { updateData, listData } from "@/api/system/dict/data";
+import imgulock from "@/assets/images/unlock@2x.png";
 
-  const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+const { proxy } = getCurrentInstance() as ComponentInternalInstance;
 
-  const sites = ref([]);
+const sites = ref([]);
 
-  const showTree = ref(true)
+const showTree = ref(true)
 
 
-  const formdata = ref({
-    name: "",
-    type: "",
-    code: "",
-    cabinetType: ''
-  })
+const formdata = ref({
+  name: "",
+  type: "",
+  code: "",
+  cabinetType: ''
+})
 
 
-  const route = useRoute();
-  const router = useRouter();
+const route = useRoute();
+const router = useRouter();
 
-  const tableData = ref([]);
-  const carPathList = ref([]);
-  const line = ref([]);
+const tableData = ref([]);
+const carPathList = ref([]);
+const line = ref([]);
 
-  const activeName = ref("camera")
+const activeName = ref("camera")
 
-  const filterText = ref("");
-  const treeRef = ref(null);
-  const dialogVisible = ref(false);
+const filterText = ref("");
+const treeRef = ref(null);
+const dialogVisible = ref(false);
 
-  const gettreeheight = () => {
-    return document.body.clientHeight - 100;
-  }
+const gettreeheight = () => {
+  return document.body.clientHeight - 300;
+}
 
-  const goAdd = () => {
-    dialogVisible.value = true
-    formdata.value = {
-      name: "",
-      type: "",
-      code: ""
-    }
-  }
-
-  const getTypeName = (data) => {
-    var type = data.cabinetType
-    if (type == 1) {
-      return '一主'
-    } else if (type == 2) {
-      return '一主一副'
-    } else {
-      return '一主二副'
-    }
+const goAdd = () => {
+  dialogVisible.value = true
+  formdata.value = {
+    name: "",
+    type: "",
+    code: ""
   }
-
-  const initData = async () => {
-    const res = await listCarPath({ pageSize: 1000 });
-    carPathList.value = res.rows;
+}
+
+const getTypeName = (data) => {
+  var type = data.cabinetType
+  if (type == 1) {
+    return '一主'
+  } else if (type == 2) {
+    return '一主一副'
+  } else {
+    return '一主二副'
   }
+}
 
+const initData = async () => {
+  const res = await listCarPath({ pageSize: 1000 });
+  carPathList.value = res.rows;
+}
 
-  const defaultProps = {
-    children: "children",
-    label: "label",
-    value: 'id',
-  };
-  const treeIndent = ref(40);
-
-  watch(filterText, (val) => {
-    if (treeRef.value) {
-      treeRef.value.filter(val);
-    }
-  });
 
-  const savedata = () => {
-    //保存数据
-    var data = {
-      dictCode: currentdata.value.dictCode,
-      dictValue: currentdata.value.dictValue,
-      dictLabel: currentdata.value.dictLabel,
-      dictType: "tbl_sites",
-      remark: JSON.stringify(tableData.value)
-    }
-    updateData(data).then(res => {
-      ElMessage.success("成功!");
-      getLineSites();
+const defaultProps = {
+  children: "children",
+  label: "label",
+  value: 'id',
+};
+const treeIndent = ref(40);
 
-    })
+watch(filterText, (val) => {
+  if (treeRef.value) {
+    treeRef.value.filter(val);
   }
+});
+
+const savedata = () => {
+  //保存数据
+  var data = {
+    dictCode: currentdata.value.dictCode,
+    dictValue: currentdata.value.dictValue,
+    dictLabel: currentdata.value.dictLabel,
+    dictType: "tbl_sites",
+    remark: JSON.stringify(tableData.value)
+  }
+  updateData(data).then(res => {
+    ElMessage.success("成功!");
+    getLineSites();
 
-  const getLineSites = () => {
-    console.log(line.value)
-    var sitesList = []
-    for (var index in carPathList.value) {
-      if (carPathList.value[index].id == line.value) {
-        sitesList = JSON.parse(carPathList.value[index].stationList)
-      }
-    }
-    console.log(sitesList)
-    var sites = []
-    for (var i in sitesList) {
-      sites.push({ id: i, label: sitesList[i].data.dictLabel })
+  })
+}
+
+const getLineSites = () => {
+  console.log(line.value)
+  var sitesList = []
+  for (var index in carPathList.value) {
+    if (carPathList.value[index].id == line.value) {
+      sitesList = JSON.parse(carPathList.value[index].stationList)
     }
-    console.log(sites)
+  }
+  console.log(sitesList)
+  var sites = []
+  for (var i in sitesList) {
+    sites.push({ id: i, label: sitesList[i].data.dictLabel })
+  }
+  console.log(sites)
+  data.value = [{
+    id: 1,
+    label: "站点",
+  },];
+  data.value[0].children = sites
+  console.log(data.value)
+  showTree.value = false;
+  setTimeout(() => {
+    showTree.value = true
+  }, 100);
+
+}
+
+const getSites = () => {
+  listData({ dictType: "tbl_sites" }).then(res2 => {
+    sites.value = res2.rows;
+    var index = 1;
     data.value = [{
       id: 1,
       label: "站点",
+      children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
     },];
-    data.value[0].children = sites
-    console.log(data.value)
-    showTree.value = false;
-    setTimeout(() => {
-      showTree.value = true
-    }, 100);
-
+  });
+}
+
+const deleteDevice = (datac) => {
+  tableData.value = tableData.value.filter(i => i.type != datac.type);
+  var data = {
+    dictCode: currentdata.value.dictCode,
+    dictValue: currentdata.value.dictValue,
+    dictLabel: currentdata.value.dictLabel,
+    dictType: "tbl_sites",
+    remark: JSON.stringify(tableData.value)
   }
+  updateData(data).then(res => {
+    ElMessage.success("成功!");
+  })
+}
 
-  const getSites = () => {
-    listData({ dictType: "tbl_sites" }).then(res2 => {
-      sites.value = res2.rows;
-      var index = 1;
-      data.value = [{
-        id: 1,
-        label: "站点",
-        children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
-      },];
-    });
-  }
+const handleTabClick = () => {
 
-  const deleteDevice = (datac) => {
-    tableData.value = tableData.value.filter(i => i.type != datac.type);
-    var data = {
-      dictCode: currentdata.value.dictCode,
-      dictValue: currentdata.value.dictValue,
-      dictLabel: currentdata.value.dictLabel,
-      dictType: "tbl_sites",
-      remark: JSON.stringify(tableData.value)
-    }
-    updateData(data).then(res => {
-      ElMessage.success("成功!");
-    })
-  }
+}
 
-  const handleTabClick = () => {
+const filterNode = (value: string, node: TreeNode) => {
+  if (node.id == 1) return true;
+  console.log(node.label.indexOf(value) != -1)
+  return node.label.indexOf(value) != -1;
+};
 
-  }
+const currentdata = ref(null)
 
-  const filterNode = (value: string, node: TreeNode) => {
-    if (node.id == 1) return true;
-    console.log(node.label.indexOf(value) != -1)
-    return node.label.indexOf(value) != -1;
-  };
-
-  const currentdata = ref(null)
-
-  const isJSON = (str) => {
-    if (typeof str == 'string') {
-      try {
-        var obj = JSON.parse(str);
-        if (typeof obj == 'object' && obj) {
-          return true;
-        } else {
-          return false;
-        }
-
-      } catch (e) {
+const isJSON = (str) => {
+  if (typeof str == 'string') {
+    try {
+      var obj = JSON.parse(str);
+      if (typeof obj == 'object' && obj) {
+        return true;
+      } else {
         return false;
       }
+
+    } catch (e) {
+      return false;
     }
   }
-
-  const treeclick = (data: TreeNodeData, node: TreeNode) => {
-
-    currentdata.value = sites.value.filter(i => {
-      return i.dictLabel == data.label
-    })[0];
-    tableData.value = [];
-    if (currentdata.value) {
-      if (isJSON(currentdata.value.remark)) {
-        tableData.value = JSON.parse(currentdata.value.remark);
-        var cameras = tableData.value.filter(i => i.type == 'camera');
-        if (cameras.length > 0) {
-          var cameracode = cameras[0].code;
-          //存在视频播放视频
-          // getCameraPlayerConfig(cameracode).then(res => {
-          //   console.log(res.data);
-          //   var player = new EZUIKit.EZUIKitPlayer({
-          //     template: "pcLive",
-          //     id: 'video-container', // 视频容器ID
-          //     ...res.data
-          //   })
-          // })
-        }
-
-        var cabinets = tableData.value.filter(i => i.type == 'cabinet');
-        if (cabinets.length > 0) {
-          var cabinetcode = cameras[0].code;
-          SycCabinet(cabinetcode);
-        }
-      }else{
-        ElMessage.warning("站点设备配置错误");
+}
+
+const treeclick = (data: TreeNodeData, node: TreeNode) => {
+
+  currentdata.value = sites.value.filter(i => {
+    return i.dictLabel == data.label
+  })[0];
+  tableData.value = [];
+  if (currentdata.value) {
+    // if (isJSON(currentdata.value.remark)) {
+      tableData.value = JSON.parse((currentdata.value.remark==''?"[]":currentdata.value.remark)??"[]");
+      var cameras = tableData.value.filter(i => i.type == 'camera');
+      if (cameras.length > 0) {
+        var cameracode = cameras[0].code;
+        //存在视频播放视频
+        // getCameraPlayerConfig(cameracode).then(res => {
+        //   console.log(res.data);
+        //   var player = new EZUIKit.EZUIKitPlayer({
+        //     template: "pcLive",
+        //     id: 'video-container', // 视频容器ID
+        //     ...res.data
+        //   })
+        // })
       }
-    }
 
+      var cabinets = tableData.value.filter(i => i.type == 'cabinet');
+      if (cabinets.length > 0) {
+        var cabinetcode = cameras[0].code;
+        SycCabinet(cabinetcode);
+      }
+    // }else{
+    //   ElMessage.warning("站点设备配置错误");
+    // }
   }
 
-
-  const addDevice = () => {
-    dialogVisible.value = false;
-    if (formdata.value.name == "") {
-      ElMessage.warning("设备名称未填写");
-      return;
-    }
-    if (formdata.value.type == "") {
-      ElMessage.warning("设备类型未填写");
-      return;
-    }
-    if (formdata.value.code == "") {
-      ElMessage.warning("设备序列号未填写");
-      return;
-    }
-    if (tableData.value.filter(i => i.type == formdata.value.type).length > 0) {
-      ElMessage.warning("存在相同类型的设备");
-      return;
-    }
-    tableData.value.push(formdata.value);
-    var data = {
-      dictCode: currentdata.value.dictCode,
-      dictValue: currentdata.value.dictValue,
-      dictLabel: currentdata.value.dictLabel,
-      dictType: "tbl_sites",
-      remark: JSON.stringify(tableData.value)
-    }
-    updateData(data).then(res => {
-      ElMessage.success("成功!");
-    })
+}
 
 
+const addDevice = () => {
+  dialogVisible.value = false;
+  if (formdata.value.name == "") {
+    ElMessage.warning("设备名称未填写");
+    return;
   }
-
-  const currentCabinet = ref({
-    total: 40,
-    unused: 10,
-    boxlist: []
-  })
-  const SycCabinet = (code) => {
-    //TODO 获取格数
-    // var toalnum
-    currentCabinet.value.boxlist = [];
-    for (var i = 0; i < currentCabinet.value.total; i++) {
-      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
-      //@ts-ignore
-      currentCabinet.value.boxlist.push({
-        box_id: 1,
-        box_name: (i + 1) + "",
-        box_status: i % 2
-      }
-      )
-    }
+  if (formdata.value.type == "") {
+    ElMessage.warning("设备类型未填写");
+    return;
   }
-  const openbox = (code) => {
-    setTimeout(() => {
-      ElMessage.success("指令已发送!");
-    }, 1000);
+  if (formdata.value.code == "") {
+    ElMessage.warning("设备序列号未填写");
+    return;
   }
+  if (tableData.value.filter(i => i.type == formdata.value.type).length > 0) {
+    ElMessage.warning("存在相同类型的设备");
+    return;
+  }
+  tableData.value.push(formdata.value);
+  var data = {
+    dictCode: currentdata.value.dictCode,
+    dictValue: currentdata.value.dictValue,
+    dictLabel: currentdata.value.dictLabel,
+    dictType: "tbl_sites",
+    remark: JSON.stringify(tableData.value)
+  }
+  updateData(data).then(res => {
+    ElMessage.success("成功!");
+  })
 
 
-  const data = computed(() => {
-
-    var index = 1;
-
-    return [{
-      id: 1,
-      label: "站点",
-      children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
-    },]
-  });
-  onMounted(() => {
-    if (treeRef.value) {
-      setTimeout(() => {
-        treeRef.value.expandNode(treeRef.value.getNode(1))
-      }, 100);
-      getSites();
-      initData();
-      // treeRef.value.expandNode(treeRef.value.getNode(1))
+}
+
+const currentCabinet = ref({
+  total: 40,
+  unused: 10,
+  boxlist: []
+})
+const SycCabinet = (code) => {
+  //TODO 获取格数
+  // var toalnum
+  currentCabinet.value.boxlist = [];
+  for (var i = 0; i < currentCabinet.value.total; i++) {
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    //@ts-ignore
+    currentCabinet.value.boxlist.push({
+      box_id: 1,
+      box_name: (i + 1) + "",
+      box_status: i % 2
     }
-  });
-
-
-
+    )
+  }
+}
+const openbox = (code) => {
+  setTimeout(() => {
+    ElMessage.success("指令已发送!");
+  }, 1000);
+}
+
+
+const data = computed(() => {
+
+  var index = 1;
+
+  return [{
+    id: 1,
+    label: "站点",
+    children: sites.value.map(i => { return { id: ++index, label: i.dictLabel } }),
+  },]
+});
+onMounted(() => {
+  if (treeRef.value) {
+    setTimeout(() => {
+      treeRef.value.expandNode(treeRef.value.getNode(1))
+    }, 100);
+    getSites();
+    initData();
+    // treeRef.value.expandNode(treeRef.value.getNode(1))
+  }
+});
 </script>
 
 <style lang="scss" scoped>
-  .card-header {
-    display: flex;
-    flex-direction: row;
-    justify-content: space-between;
-  }
-
-  .boxunused {
-    background: #3333332d;
-  }
-</style>
+.card-header {
+  display: flex;
+  flex-direction: row;
+  justify-content: space-between;
+}
+
+.boxunused {
+  background: #3333332d;
+}
+</style>

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio