吉安感知网项目-前端
罗广辉
2026-01-08 31d0fc3caacc159faddf0c4f3bb4f84bf7a00c69
Merge remote-tracking branch 'origin/master'
12 files modified
11 files added
3870 ■■■■ changed files
applications/drone-command/env/.env.development 12 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/fzsb.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/title-bg.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/zcsb.png patch | view | raw | blame | history
applications/drone-command/src/styles/element-ui.scss 1724 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/EquipmentWarning.vue 61 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/HistoryWarning.vue 136 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/LeftContainer.vue 95 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/MapContainer.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/RealWarning.vue 76 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/RightContainer.vue 204 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/EquipmentTemplate.vue 171 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/HistoryTemplate.vue 110 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealEquipmentTemplate.vue 199 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue 204 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/TitleTemplate.vue 43 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/index.vue 4 ●●● patch | view | raw | blame | history
uniapps/work-app/src/pages.json 261 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/pages/login/index.vue 20 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/pages/work/index.vue 199 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/subPackages/workDetail/index.vue 322 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/subPackages/workDetail/mapWork/index.vue 13 ●●●● patch | view | raw | blame | history
applications/drone-command/env/.env.development
@@ -1,3 +1,13 @@
###
 # @Author       : yuan
 # @Date         : 2026-01-07 14:58:30
 # @LastEditors  : yuan
 # @LastEditTime : 2026-01-08 15:14:52
 # @FilePath     : \applications\drone-command\env\.env.development
 # @Description  :
 # Copyright 2026 OBKoro1, All Rights Reserved.
 # 2026-01-07 14:58:30
###
NODE_ENV = 'development'
#开发环境配置
@@ -6,7 +16,7 @@
#开发环境代理地址(推荐本地新建文件 .env.development.local 来进行覆盖)
# VITE_APP_URL = https://wrj.shuixiongit.com/api
VITE_APP_URL= http://192.168.1.33:81
VITE_APP_URL= http://192.168.1.33
#新大屏地址
VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/'
applications/drone-command/src/assets/images/dataCockpit/fzsb.png
applications/drone-command/src/assets/images/dataCockpit/title-bg.png
applications/drone-command/src/assets/images/dataCockpit/zcsb.png
applications/drone-command/src/styles/element-ui.scss
@@ -1,736 +1,1022 @@
.el-card.is-always-shadow {
    box-shadow: none;
    border: none !important;
  }
  .el-menu {
    border-right: none;
  }
  .el-message__icon,
  .el-message__content {
    display: inline-block;
  }
  .el-date-editor .el-range-input,
  .el-date-editor .el-range-separator {
    height: auto;
    overflow: hidden;
  }
  .el-dialog__wrapper {
    z-index: 2048;
  }
  .el-col {
    margin-bottom: 8px;
  }
  .el-main {
    padding: 0 !important;
  }
  .el-dropdown-menu__item--divided:before,
  .el-menu,
  .el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,
  .el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,
  .el-menu--horizontal>.el-sub-menu .el-sub-menu__title:hover {
    background-color: transparent;
  }
  .el-dropdown-menu__item--divided:before,
  .el-menu,
  .el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,
  .el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,
  .el-menu--horizontal>.el-sub-menu .el-sub-menu__title:hover {
    background-color: transparent !important;
  }
  .el-collapse-item__header {
    height: auto;
    overflow: hidden;
  }
  .el-button.is-text:not(.is-disabled):active {
    background-color: transparent;
  }
  .el-button.is-text:not(.is-disabled):focus,
  .el-button.is-text:not(.is-disabled):hover {
    background-color: transparent;
  }
  .avue-icon i,
  .avue-icon svg {
    line-height: 20px;
  }
  .avue--detail .el-form-item {
    background-color: #fafafa;
  }
  .showFullScreenDlg {
    display: flex;
    justify-content: space-between;
    .el-dialog {
      position: relative;
      padding: 0;
      overflow: hidden;
      .el-dialog__body {
        width: 100%;
        height: 100%;
        iframe {
          width: 100%;
          height: 100%;
        }
      }
      .el-dialog__header {
        height: 0;
        overflow: hidden;
        padding: 0;
        .el-dialog__headerbtn {
          position: absolute;
          left: 0;
          //top: 14px;
          .el-dialog__close {
            color: #fff;
            font-size: 35px;
            z-index: 99;
          }
        }
      }
    }
  }
  .ztzf-drawer-body-basic-container {
    .el-drawer__header {
      margin-bottom: 0;
    }
    .el-drawer__body {
      display: flex;
      flex-direction: column;
    }
  }
  .ztzf-el-card__body {
     .el-card__body {
      .avue-form{
      padding: 0;}}
  }
  .ztzf-public-general-avue-crud {
    .el-table {
      tr {
        min-height: 30px !important;
        line-height: 30px !important;
        box-sizing: border-box !important;
      }
      tr th,
      tr td {
        padding: 6px 0 !important;
        min-height: 30px !important;
        line-height: 30px !important;
        box-sizing: border-box !important;
        div.cell {
          min-height: 30px !important;
          line-height: 30px !important;
        }
      }
    }
  }
  .ztzf-layer-input {
      .el-input__wrapper {
          padding: 0 8px !important;
          // background: #2D2D2D;
      background-color: transparent !important;
          box-shadow: none !important;
          border: 1px solid #fff;
          .el-input__inner {
              color: #ffffff;
              &::placeholder {
          color: rgba(255,255,255,0.37);
              }
          }
      }
      &.is-disabled {
          .el-input__wrapper {
              background-color: #012a50;
          }
      }
  }
  .ztzf-button {
    background-color: transparent !important;
    color: #fff !important;
  }
  .ztzf-el-tree {
    background-color: transparent !important;
    --el-tree-node-hover-bg-color:transparent !important;
    color: #fff !important;
  }
  .ztzf-layer-search {
    color: #fff !important;
    background-color: transparent !important;
    .el-select__wrapper {
      background-color: transparent !important;
    }
    .el-select__popper.el-popper {
      background-color: transparent !important;
    }
    .el-popper.is-light {
      background-color: transparent !important;
    }
    .el-select__placeholder {
      &.is-transparent {
        color: rgba(255,255,255,0.37) !important;
      }
      &.is-disabled {
        color: rgba(255,255,255,0.37) !important;
      }
    }
    .el-select__selected-item {
      color: #ffffff !important;
      &.is-disabled {
        color: rgba(255,255,255,0.37) !important;
        z-index: 99;
      }
    }
  }
  .ztzf-select-popper.el-select__popper {
      border:#2D2D2D !important;
      .el-select-dropdown {
          overflow-x: hidden !important;
          .el-scrollbar {
              .el-select-dropdown__wrap {
                  background: linear-gradient(180deg, rgba(13, 53, 86, 0.85) 0%, rgba(1, 35, 80, 0.85) 100%);
                  border-radius: 0px 0px 8px 8px;
                  border: 1px solid;
          border-image: linear-gradient(180deg, #fff, #fff) 1 1;
                  overflow-x: hidden !important;
                  margin-right: 0 !important;
                  .el-select-dropdown__list {
                      padding: 0 !important;
                      .el-select-dropdown__item {
                          background: #2D2D2D !important;
                          color: white;
                          &.hover {
                              background-color: #2D2D2D !important;
                              color: white;
                          }
                          &.selected {
                              color: #fff !important;
                              font-weight: 700;
                          }
                      }
                  }
              }
          }
          .el-select-dropdown__empty {
              background: #2D2D2D;
              border-radius: 0px 0px 8px 8px;
              border: 1px solid;
              border-image: linear-gradient(180deg, #fff, #fff) 1 1;
          }
      }
      .el-popper__arrow::before {
          background: #2D2D2D !important;
          border: 1px solid #fff !important;
      }
  }
  //时间日期选择器
  .ztzf-layer-date-picker {
      box-shadow: none !important;
      background: transparent;
      border: 1px solid #fff;
      border-radius: 5px;
      .el-range-editor.is-disabled input {
          background-color: transparent !important;
      }
      .el-range-editor.is-disabled {
          background-color: transparent !important;
      }
      .el-input__wrapper {
          box-shadow: none !important;
          background-color: transparent !important;
      width: 300px;
          &.is-focus {
              box-shadow: none !important;
          }
      }
      .el-range-input {
          color: #fff;
          &::placeholder {
              color: rgba(255, 255, 255, 0.37);
          }
      }
      .el-range-separator {
          color: #ffffff;
      }
  }
  // 日期下拉框
  .ztzf-layer-date-picker-popper {
      background: #012350 !important;
      border: 1px solid !important;
      border-radius: 0px 0px 8px 8px;
      border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
      .el-picker-panel .el-time-panel{
          background: #012350 !important;
      }
      .el-time-spinner__item {
      color: #fff !important;}
      .el-time-spinner__item:hover:not(.is-disabled):not(.is-active){
          background: transparent !important;
      }
      .el-picker-panel {
          .el-picker-panel__body-wrapper {
              .el-picker-panel__body {
                  background: #012350 !important;
                  color: #fff !important;
                  .el-date-picker__time-header {
                      border: none;
                      .el-date-picker__editor-wrap {
                          .el-time-panel {
                              background: #012350 !important;
                              border-radius: 0px 0px 8px 8px;
                              border: 1px solid !important;
                              border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
                              // 将 time-picker-popper 的样式移到这里
                              .el-time-panel__header {
                                  background: #012350 !important;
                                  color: #ffffff !important;
                                  border-bottom: 1px solid rgba(255, 255, 255, 0.37) !important;
                              }
                              .el-time-panel__content {
                                  .el-time-spinner__item {
                                      color: #e6e6e6 !important;
                                      &:hover {
                                          background: #012350 !important;
                                      }
                                      &.active {
                                          color: #479dff !important;
                                          font-weight: bold;
                                      }
                                  }
                              }
                              .el-time-panel__footer {
                                  background: #012350 !important;
                                  border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
                                  .el-button {
                                      color: #fff !important;
                                      &:hover {
                                          color: #479dff !important;
                                      }
                                  }
                                  .el-time-panel__btn.cancel {
                                      color: #fff !important;
                                      &:hover {
                                          color: #fff !important;
                                      }
                                  }
                              }
                          }
                      }
                  }
                  .el-picker-panel__content {
                      .el-date-range-picker__header {
                          .el-picker-panel__icon-btn {
                              color: #fff !important;
                              &:hover {
                                  color: var(--el-color-primary) !important;
                              }
                              .el-icon {
                                  &::before {
                                      color: inherit !important;
                                  }
                              }
                          }
                          & > div {
                              span {
                                  color: #fff !important;
                              }
                          }
                      }
                      .el-date-table {
                          th {
                              color: #fff !important;
                          }
                          td.disabled div {
                              background-color: #00193b !important;
                              color: #505050 !important;
                              cursor: not-allowed;
                          }
                          // td:hover,
                          // td.current:not(.disabled) {
                          //     background: rgba(60, 121, 202) !important;
                          //     color: white !important;
                          // }
                          td.start-date span,
                          td.start-date span,
                          td.end-date span {
                              background-color: #012350 !important;
                          }
                          td.in-range div,
                          td.in-range div:hover,
                          &.is-week-mode .el-date-table__row.current div,
                          &.is-week-mode .el-date-table__row:hover div {
                              background-color: rgba(60, 121, 202) !important;
                          }
                      }
                  }
              }
          }
      }
      .el-popper__arrow {
          &::before {
              background: #0d3556 !important;
              border: 1px solid #0d3556 !important;
              box-sizing: border-box;
          }
      }
      .el-picker-panel__sidebar {
          background: #012350;
          color: #fff;
          .el-picker-panel__shortcut {
              color: #ffffff;
          }
      }
      .el-picker-panel__body {
          .el-input.is-disabled .el-input__wrapper {
              background: #012350;
              box-shadow: 0 0 0 0.1rem#409eff;
              color: #fff;
              .el-input__inner {
                  color: #fff !important;
              }
          }
          .el-button.is-disabled,
          .el-button.is-disabled:hover {
              background: #012350;
          }
          .el-input__wrapper {
              background: #012350;
              box-shadow: 0 0 0 0.1rem#409eff;
              color: #fff;
              .el-input__inner {
                  color: #fff !important;
              }
          }
      }
      .el-picker-panel__footer {
          background: #012350;
          color: #fff;
          border-top: none;
          .el-button--small {
              box-shadow: 0 0 0 0.1rem#409eff;
              background-color: #012350;
              color: #fff;
              border: none;
              &:hover {
                  background-color: #012350;
                  color: #fff;
                  border-color: #409eff;
              }
          }
      }
  }
  .ztzf-layer-time-picker-popper {
    background: rgba(0,0,0,0.8) !important;
      border-radius: 0px 0px 8px 8px;
      border: 1px solid !important;
      border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
      .el-popper__arrow::before {
          background: rgba(0,0,0,0.8) !important;
          border: 1px solid #479dff !important;
      }
      .el-time-panel__header {
          background: rgba(0,0,0,0.8) !important;
          color: #ffffff !important;
          border-bottom: 1px solid rgba(71, 157, 255, 0.3) !important;
      }
      .el-time-panel__content {
          // background: #012350 !important;
          .el-time-spinner__item {
              color: #e6e6e6 !important;
              &:hover {
                  background: rgba(71, 157, 255, 0.3) !important;
              }
              &.active {
                  color: #479dff !important;
                  font-weight: bold;
              }
          }
      }
      .el-time-panel__footer {
          background: rgba(0,0,0,0.8) !important;
          border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
          .el-button {
              color: #fff !important;
              &:hover {
                  color: #479dff !important;
              }
          }
          .el-time-panel__btn.cancel {
              color: #fff !important;
              &:hover {
                  color: #fff !important;
              }
          }
      }
  }
    box-shadow: none;
    border: none !important;
}
.el-menu {
    border-right: none;
}
.el-message__icon,
.el-message__content {
    display: inline-block;
}
.el-date-editor .el-range-input,
.el-date-editor .el-range-separator {
    height: auto;
    overflow: hidden;
}
.el-dialog__wrapper {
    z-index: 2048;
}
.el-col {
    margin-bottom: 8px;
}
.el-main {
    padding: 0 !important;
}
.el-dropdown-menu__item--divided:before,
.el-menu,
.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal>.el-sub-menu .el-sub-menu__title:hover {
    background-color: transparent;
}
.el-dropdown-menu__item--divided:before,
.el-menu,
.el-menu--horizontal>.el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal>.el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal>.el-sub-menu .el-sub-menu__title:hover {
    background-color: transparent !important;
}
.el-collapse-item__header {
    height: auto;
    overflow: hidden;
}
.el-button.is-text:not(.is-disabled):active {
    background-color: transparent;
}
.el-button.is-text:not(.is-disabled):focus,
.el-button.is-text:not(.is-disabled):hover {
    background-color: transparent;
}
.avue-icon i,
.avue-icon svg {
    line-height: 20px;
}
.avue--detail .el-form-item {
    background-color: #fafafa;
}
.showFullScreenDlg {
    display: flex;
    justify-content: space-between;
    .el-dialog {
        position: relative;
        padding: 0;
        overflow: hidden;
        .el-dialog__body {
            width: 100%;
            height: 100%;
            iframe {
                width: 100%;
                height: 100%;
            }
        }
        .el-dialog__header {
            height: 0;
            overflow: hidden;
            padding: 0;
            .el-dialog__headerbtn {
                position: absolute;
                left: 0;
                //top: 14px;
                .el-dialog__close {
                    color: #fff;
                    font-size: 35px;
                    z-index: 99;
                }
            }
        }
    }
}
.ztzf-drawer-body-basic-container {
    .el-drawer__header {
        margin-bottom: 0;
    }
    .el-drawer__body {
        display: flex;
        flex-direction: column;
    }
}
.ztzf-el-card__body {
    .el-card__body {
        .avue-form {
            padding: 0;
        }
    }
}
.ztzf-public-general-avue-crud {
    .el-table {
        tr {
            min-height: 30px !important;
            line-height: 30px !important;
            box-sizing: border-box !important;
        }
        tr th,
        tr td {
            padding: 6px 0 !important;
            min-height: 30px !important;
            line-height: 30px !important;
            box-sizing: border-box !important;
            div.cell {
                min-height: 30px !important;
                line-height: 30px !important;
            }
        }
    }
}
.ztzf-layer-input {
    .el-input__wrapper {
        padding: 0 8px !important;
        // background: #2D2D2D;
        background-color: transparent !important;
        box-shadow: none !important;
        border: 1px solid #fff;
        .el-input__inner {
            color: #ffffff;
            &::placeholder {
                color: rgba(255, 255, 255, 0.37);
            }
        }
    }
    &.is-disabled {
        .el-input__wrapper {
            background-color: #012a50;
        }
    }
}
.ztzf-button {
    background-color: transparent !important;
    color: #fff !important;
}
.ztzf-el-tree {
    background-color: transparent !important;
    --el-tree-node-hover-bg-color: transparent !important;
    color: #fff !important;
}
.ztzf-layer-search {
    color: #fff !important;
    background-color: transparent !important;
    .el-select__wrapper {
        background-color: transparent !important;
    }
    .el-select__popper.el-popper {
        background-color: transparent !important;
    }
    .el-popper.is-light {
        background-color: transparent !important;
    }
    .el-select__placeholder {
        &.is-transparent {
            color: rgba(255, 255, 255, 0.37) !important;
        }
        &.is-disabled {
            color: rgba(255, 255, 255, 0.37) !important;
        }
    }
    .el-select__selected-item {
        color: #ffffff !important;
        &.is-disabled {
            color: rgba(255, 255, 255, 0.37) !important;
            z-index: 99;
        }
    }
}
.ztzf-select-popper.el-select__popper {
    border: #2D2D2D !important;
    .el-select-dropdown {
        overflow-x: hidden !important;
        .el-scrollbar {
            .el-select-dropdown__wrap {
                background: linear-gradient(180deg, rgba(13, 53, 86, 0.85) 0%, rgba(1, 35, 80, 0.85) 100%);
                border-radius: 0px 0px 8px 8px;
                border: 1px solid;
                border-image: linear-gradient(180deg, #fff, #fff) 1 1;
                overflow-x: hidden !important;
                margin-right: 0 !important;
                .el-select-dropdown__list {
                    padding: 0 !important;
                    .el-select-dropdown__item {
                        background: #2D2D2D !important;
                        color: white;
                        &.hover {
                            background-color: #2D2D2D !important;
                            color: white;
                        }
                        &.selected {
                            color: #fff !important;
                            font-weight: 700;
                        }
                    }
                }
            }
        }
        .el-select-dropdown__empty {
            background: #2D2D2D;
            border-radius: 0px 0px 8px 8px;
            border: 1px solid;
            border-image: linear-gradient(180deg, #fff, #fff) 1 1;
        }
    }
    .el-popper__arrow::before {
        background: #2D2D2D !important;
        border: 1px solid #fff !important;
    }
}
//时间日期选择器
.ztzf-layer-date-picker {
    box-shadow: none !important;
    background: transparent;
    border: 1px solid #fff;
    border-radius: 5px;
    .el-range-editor.is-disabled input {
        background-color: transparent !important;
    }
    .el-range-editor.is-disabled {
        background-color: transparent !important;
    }
    .el-input__wrapper {
        box-shadow: none !important;
        background-color: transparent !important;
        width: 300px;
        &.is-focus {
            box-shadow: none !important;
        }
    }
    .el-range-input {
        color: #fff;
        &::placeholder {
            color: rgba(255, 255, 255, 0.37);
        }
    }
    .el-range-separator {
        color: #ffffff;
    }
}
// 日期下拉框
.ztzf-layer-date-picker-popper {
    background: #012350 !important;
    border: 1px solid !important;
    border-radius: 0px 0px 8px 8px;
    border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
    .el-picker-panel .el-time-panel {
        background: #012350 !important;
    }
    .el-time-spinner__item {
        color: #fff !important;
    }
    .el-time-spinner__item:hover:not(.is-disabled):not(.is-active) {
        background: transparent !important;
    }
    .el-picker-panel {
        .el-picker-panel__body-wrapper {
            .el-picker-panel__body {
                background: #012350 !important;
                color: #fff !important;
                .el-date-picker__time-header {
                    border: none;
                    .el-date-picker__editor-wrap {
                        .el-time-panel {
                            background: #012350 !important;
                            border-radius: 0px 0px 8px 8px;
                            border: 1px solid !important;
                            border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
                            // 将 time-picker-popper 的样式移到这里
                            .el-time-panel__header {
                                background: #012350 !important;
                                color: #ffffff !important;
                                border-bottom: 1px solid rgba(255, 255, 255, 0.37) !important;
                            }
                            .el-time-panel__content {
                                .el-time-spinner__item {
                                    color: #e6e6e6 !important;
                                    &:hover {
                                        background: #012350 !important;
                                    }
                                    &.active {
                                        color: #479dff !important;
                                        font-weight: bold;
                                    }
                                }
                            }
                            .el-time-panel__footer {
                                background: #012350 !important;
                                border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
                                .el-button {
                                    color: #fff !important;
                                    &:hover {
                                        color: #479dff !important;
                                    }
                                }
                                .el-time-panel__btn.cancel {
                                    color: #fff !important;
                                    &:hover {
                                        color: #fff !important;
                                    }
                                }
                            }
                        }
                    }
                }
                .el-picker-panel__content {
                    .el-date-range-picker__header {
                        .el-picker-panel__icon-btn {
                            color: #fff !important;
                            &:hover {
                                color: var(--el-color-primary) !important;
                            }
                            .el-icon {
                                &::before {
                                    color: inherit !important;
                                }
                            }
                        }
                        &>div {
                            span {
                                color: #fff !important;
                            }
                        }
                    }
                    .el-date-table {
                        th {
                            color: #fff !important;
                        }
                        td.disabled div {
                            background-color: #00193b !important;
                            color: #505050 !important;
                            cursor: not-allowed;
                        }
                        // td:hover,
                        // td.current:not(.disabled) {
                        //     background: rgba(60, 121, 202) !important;
                        //     color: white !important;
                        // }
                        td.start-date span,
                        td.start-date span,
                        td.end-date span {
                            background-color: #012350 !important;
                        }
                        td.in-range div,
                        td.in-range div:hover,
                        &.is-week-mode .el-date-table__row.current div,
                        &.is-week-mode .el-date-table__row:hover div {
                            background-color: rgba(60, 121, 202) !important;
                        }
                    }
                }
            }
        }
    }
    .el-popper__arrow {
        &::before {
            background: #0d3556 !important;
            border: 1px solid #0d3556 !important;
            box-sizing: border-box;
        }
    }
    .el-picker-panel__sidebar {
        background: #012350;
        color: #fff;
        .el-picker-panel__shortcut {
            color: #ffffff;
        }
    }
    .el-picker-panel__body {
        .el-input.is-disabled .el-input__wrapper {
            background: #012350;
            box-shadow: 0 0 0 0.1rem#409eff;
            color: #fff;
            .el-input__inner {
                color: #fff !important;
            }
        }
        .el-button.is-disabled,
        .el-button.is-disabled:hover {
            background: #012350;
        }
        .el-input__wrapper {
            background: #012350;
            box-shadow: 0 0 0 0.1rem#409eff;
            color: #fff;
            .el-input__inner {
                color: #fff !important;
            }
        }
    }
    .el-picker-panel__footer {
        background: #012350;
        color: #fff;
        border-top: none;
        .el-button--small {
            box-shadow: 0 0 0 0.1rem#409eff;
            background-color: #012350;
            color: #fff;
            border: none;
            &:hover {
                background-color: #012350;
                color: #fff;
                border-color: #409eff;
            }
        }
    }
}
.ztzf-layer-time-picker-popper {
    background: rgba(0, 0, 0, 0.8) !important;
    border-radius: 0px 0px 8px 8px;
    border: 1px solid !important;
    border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
    .el-popper__arrow::before {
        background: rgba(0, 0, 0, 0.8) !important;
        border: 1px solid #479dff !important;
    }
    .el-time-panel__header {
        background: rgba(0, 0, 0, 0.8) !important;
        color: #ffffff !important;
        border-bottom: 1px solid rgba(71, 157, 255, 0.3) !important;
    }
    .el-time-panel__content {
        // background: #012350 !important;
        .el-time-spinner__item {
            color: #e6e6e6 !important;
            &:hover {
                background: rgba(71, 157, 255, 0.3) !important;
            }
            &.active {
                color: #479dff !important;
                font-weight: bold;
            }
        }
    }
    .el-time-panel__footer {
        background: rgba(0, 0, 0, 0.8) !important;
        border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
        .el-button {
            color: #fff !important;
            &:hover {
                color: #479dff !important;
            }
        }
        .el-time-panel__btn.cancel {
            color: #fff !important;
            &:hover {
                color: #fff !important;
            }
        }
    }
}
.ztzf-custom-qrcode-popover {
    //background: url("@/assets/images/home/eventOverviewDetail/qrCodeBg.png") no-repeat center center !important;
    //background-size: cover !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 5px;
    min-width: 173px !important;
    height: 180px !important;
    //background: url("@/assets/images/home/eventOverviewDetail/qrCodeBg.png") no-repeat center center !important;
    //background-size: cover !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 5px;
    min-width: 173px !important;
    height: 180px !important;
    /* 隐藏默认箭头 */
    .el-popper__arrow {
        display: none !important;
    }
    /* 隐藏默认箭头 */
    .el-popper__arrow {
        display: none !important;
    }
    /* 调整二维码内容区域样式 */
    .qrcode-content {
        background: #fff;
        padding: 5px;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 146px;
        height: 130px;
        margin-top: 12px;
    /* 调整二维码内容区域样式 */
    .qrcode-content {
        background: #fff;
        padding: 5px;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 146px;
        height: 130px;
        margin-top: 12px;
        .close-btn {
            position: absolute;
            top: 3px;
            right: 3px;
            width: 20px;
            height: 20px;
        .close-btn {
            position: absolute;
            top: 3px;
            right: 3px;
            width: 20px;
            height: 20px;
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 100;
        }
    }
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 100;
        }
    }
}
.ztzf-dialog-video {
    background: #0f1929;
    box-shadow: inset 0px -50px 50px 0px rgba(27, 148, 255, 0.13);
    border-radius: 20px 0px 0px 0px;
    border: 2px solid;
    padding: 0 !important;
    background: #0f1929;
    box-shadow: inset 0px -50px 50px 0px rgba(27, 148, 255, 0.13);
    border-radius: 20px 0px 0px 0px;
    border: 2px solid;
    padding: 0 !important;
    border-image: linear-gradient(180deg,
                    rgba(81, 168, 255, 0),
                    rgba(48, 111, 202, 1),
                    rgba(255, 255, 255, 1),
                    rgba(27, 148, 255, 1)) 2 2;
    border-image: linear-gradient(180deg,
            rgba(81, 168, 255, 0),
            rgba(48, 111, 202, 1),
            rgba(255, 255, 255, 1),
            rgba(27, 148, 255, 1)) 2 2;
    .el-dialog__header {
        width: 100%;
        height: 47px;
        //padding: 0;
        margin-bottom: 14px;
        //background: url("/src/assets/images/home/inspection-vector.png") no-repeat center;
        //background-size: 100% 100%;
        font-weight: bold;
        font-size: 16px;
        line-height: 47px;
    }
    .el-dialog__header {
        width: 100%;
        height: 47px;
        //padding: 0;
        margin-bottom: 14px;
        //background: url("/src/assets/images/home/inspection-vector.png") no-repeat center;
        //background-size: 100% 100%;
        font-weight: bold;
        font-size: 16px;
        line-height: 47px;
    }
    .el-dialog__title {
        width: 112px;
    .el-dialog__title {
        width: 112px;
        font-family: Segoe UI, Segoe UI;
        font-weight: bold;
        font-size: 16px;
        font-family: Segoe UI, Segoe UI;
        font-weight: bold;
        font-size: 16px;
        text-shadow: 0px 0px 5px rgba(154, 218, 255, 0.6);
        text-align: left;
        font-style: normal;
        text-transform: none;
        background: linear-gradient(90deg, #fbfdff 0%, #86d4ff 100%);
        margin-left: 16px;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
    }
        text-shadow: 0px 0px 5px rgba(154, 218, 255, 0.6);
        text-align: left;
        font-style: normal;
        text-transform: none;
        background: linear-gradient(90deg, #fbfdff 0%, #86d4ff 100%);
        margin-left: 16px;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
    }
    .el-dialog .el-dialog__header {
        padding: 0px !important;
        padding-left: 0px !important;
    }
    .el-dialog .el-dialog__header {
        padding: 0px !important;
        padding-left: 0px !important;
    }
    .el-scrollbar__thumb {
        background: #13c6ff !important;
    }
    .el-scrollbar__thumb {
        background: #13c6ff !important;
    }
}
  //======以下针对表格功能 增删查改样式和弹窗=========
  .ztzf-dialog-mange {
    .el-dialog__body {
      padding: 2rem 2rem 4rem;
      flex: 1;
      overflow: scroll;
      border-top: 0.1rem solid #f0f0f0;
    }
    .el-dialog__footer {
      z-index: 2;
      display: block;
      padding: 1rem 1.6rem;
      box-sizing: border-box;
      border-top: 0.1rem solid #f0f0f0;
      width: 100%;
      position: absolute;
      left: 0;
      bottom: 0;
      background-color: #fff;
      text-align: right;
    }
  }
  .ztzf-search-mange {
    height: 40px;
    .search-contain {
      display: flex;justify-content: space-between;
    }
  }
  .ztzf-form-mange {
    .el-form-item {
      width: 300px;
      .el-form-item__content {
        width: 100%;
      }
      .el-form-item__label {
        width: 120px;
      }
    }
  }
  .ztzf-form-search {
    .el-form-item {
      width: 100%;
      .el-form-item__label {
        width: 80px;
      }
      .el-form-item__content {
        display: flex;
        flex: 1;
      }
    }
  }
  .ztzf-table-mange {
    th.el-table__cell  {
      color: rgba(0, 0, 0, .85);
      background-color: #fafafa;
    }
  }
  .table-view-mange {
    width: 100%;
    border-top: 0.1rem solid #ebeef5;
    border-left: 0.1rem solid #ebeef5;
    margin-left: 0;
    margin-right: 0;
    .el-col {
      padding-left: 0;
      padding-right: 0;
      margin-bottom: 0;
      height: 32px;
      line-height: 32px;
      border-right: 0.1rem solid #ebeef5;
      text-align: center;
      align-items: center;
      .el-input__wrapper {
        box-shadow: none !important;
        border-bottom: 0.1rem solid #ebeef5;
      }
    }
    .label {
      color: #909399;
      box-sizing: border-box;
      background: #fafafa;
    }
  }
//======以下针对表格功能 增删查改样式和弹窗=========
.ztzf-dialog-mange {
    .el-dialog__body {
        padding: 2rem 2rem 4rem;
        flex: 1;
        overflow: scroll;
        border-top: 0.1rem solid #f0f0f0;
    }
    .el-dialog__footer {
        z-index: 2;
        display: block;
        padding: 1rem 1.6rem;
        box-sizing: border-box;
        border-top: 0.1rem solid #f0f0f0;
        width: 100%;
        position: absolute;
        left: 0;
        bottom: 0;
        background-color: #fff;
        text-align: right;
    }
}
.ztzf-search-mange {
    height: 40px;
    .search-contain {
        display: flex;
        justify-content: space-between;
    }
}
.ztzf-form-mange {
    .el-form-item {
        width: 300px;
        .el-form-item__content {
            width: 100%;
        }
        .el-form-item__label {
            width: 120px;
        }
    }
}
.ztzf-form-search {
    .el-form-item {
        width: 100%;
        .el-form-item__label {
            width: 80px;
        }
        .el-form-item__content {
            display: flex;
            flex: 1;
        }
    }
}
.ztzf-table-mange {
    th.el-table__cell {
        color: rgba(0, 0, 0, .85);
        background-color: #fafafa;
    }
}
.table-view-mange {
    width: 100%;
    border-top: 0.1rem solid #ebeef5;
    border-left: 0.1rem solid #ebeef5;
    margin-left: 0;
    margin-right: 0;
    .el-col {
        padding-left: 0;
        padding-right: 0;
        margin-bottom: 0;
        height: 32px;
        line-height: 32px;
        border-right: 0.1rem solid #ebeef5;
        text-align: center;
        align-items: center;
        .el-input__wrapper {
            box-shadow: none !important;
            border-bottom: 0.1rem solid #ebeef5;
        }
    }
    .label {
        color: #909399;
        box-sizing: border-box;
        background: #fafafa;
    }
}
.ztzf-data-cockpit-search-input {
    .el-input__wrapper {
        padding: 0 8px !important;
        background: #161B2C;
        box-shadow: none !important;
        border: none;
        .el-input__inner {
            color: #ffffff;
            &::placeholder {
                color: #86909C;
            }
        }
    }
    &.is-disabled {
        .el-input__wrapper {
            background-color: #161B2C;
        }
    }
}
.ztzf-data-cockpit-date-picker {
    box-shadow: none !important;
    background: #161B2C;
    border: none;
    border-radius: 5px;
    box-sizing: border-box !important;
    .el-input__wrapper {
        box-shadow: none !important;
        background-color: transparent !important;
        &.is-focus {
            box-shadow: none !important;
        }
    }
    .el-range-input {
        color: #fff;
        &::placeholder {
            color: #86909C;
        }
    }
    .el-range-separator {
        color: #ffffff;
    }
}
.ztzf-data-cockpit-date-picker-popper {
    background: #161B2C !important;
    border: 1px solid !important;
    border-radius: 0px 0px 8px 8px;
    border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
    .el-date-picker__prev-btn,
    .el-date-picker__next-btn {
        .el-icon {
            color: #fff !important;
        }
    }
    .el-date-picker__header-label {
        color: #fff !important;
    }
    .el-picker-panel {
        .el-picker-panel__body-wrapper {
            .el-picker-panel__body {
                background: #161B2C !important;
                color: #fff !important;
                .el-date-picker__time-header {
                    border: none;
                    .el-date-picker__editor-wrap {
                        .el-time-panel {
                            background: #161B2C !important;
                            border-radius: 0px 0px 8px 8px;
                            border: 1px solid !important;
                            border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
                            // 将 time-picker-popper 的样式移到这里
                            .el-time-panel__header {
                                background: #161B2C !important;
                                color: #ffffff !important;
                                border-bottom: 1px solid rgba(71, 157, 255, 0.3) !important;
                            }
                            .el-time-panel__content {
                                .el-time-spinner__item {
                                    color: #e6e6e6 !important;
                                    &:hover {
                                        background: rgba(71, 157, 255, 0.3) !important;
                                    }
                                    &.active {
                                        color: #479dff !important;
                                        font-weight: bold;
                                    }
                                }
                            }
                            .el-time-panel__footer {
                                background: #012350 !important;
                                border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
                                .el-button {
                                    color: #fff !important;
                                    &:hover {
                                        color: #479dff !important;
                                    }
                                }
                                .el-time-panel__btn.cancel {
                                    color: #fff !important;
                                    &:hover {
                                        color: #fff !important;
                                    }
                                }
                            }
                        }
                    }
                }
                .el-picker-panel__content {
                    .el-date-range-picker__header {
                        .el-picker-panel__icon-btn {
                            color: #fff !important;
                            &:hover {
                                color: var(--el-color-primary) !important;
                            }
                            .el-icon {
                                &::before {
                                    color: inherit !important;
                                }
                            }
                        }
                        &>div {
                            span {
                                color: #fff !important;
                            }
                        }
                    }
                    .el-date-table {
                        th {
                            color: #fff !important;
                        }
                        td.disabled div {
                            background-color: #00193b !important;
                            color: #505050 !important;
                            cursor: not-allowed;
                        }
                        // td:hover,
                        // td.current:not(.disabled) {
                        //     background: rgba(60, 121, 202) !important;
                        //     color: white !important;
                        // }
                        td.start-date span,
                        td.start-date span,
                        td.end-date span {
                            background-color: #012350 !important;
                        }
                        td.in-range div,
                        td.in-range div:hover,
                        &.is-week-mode .el-date-table__row.current div,
                        &.is-week-mode .el-date-table__row:hover div {
                            background-color: rgba(60, 121, 202) !important;
                        }
                    }
                }
            }
        }
    }
    .el-popper__arrow {
        &::before {
            background: #161B2C !important;
            border: 1px solid #161B2C !important;
            box-sizing: border-box;
        }
    }
    .el-picker-panel__sidebar {
        background: #012350;
        color: #fff;
        .el-picker-panel__shortcut {
            color: #ffffff;
        }
    }
    .el-picker-panel__body {
        .el-input.is-disabled .el-input__wrapper {
            background: #012350;
            box-shadow: 0 0 0 0.1rem#409eff;
            color: #fff;
            .el-input__inner {
                color: #fff !important;
            }
        }
        .el-button.is-disabled,
        .el-button.is-disabled:hover {
            background: #012350;
        }
        .el-input__wrapper {
            background: #012350;
            box-shadow: 0 0 0 0.1rem#409eff;
            color: #fff;
            .el-input__inner {
                color: #fff !important;
            }
        }
    }
    .el-picker-panel__footer {
        background: #012350;
        color: #fff;
        border-top: none;
        .el-button--small {
            box-shadow: 0 0 0 0.1rem#409eff;
            background-color: #012350;
            color: #fff;
            border: none;
            &:hover {
                background-color: #012350;
                color: #fff;
                border-color: #409eff;
            }
        }
    }
}
applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue
@@ -1,4 +1,4 @@
<template>
<template>
    <div class="center-container">
        <div class="left-box">
            <div class="logo">
@@ -6,7 +6,7 @@
            </div>
            <div class="list">
                <div class="item" v-for="item, ind in warningList" :key="ind">
                <div class="item" v-for="(item, ind) in warningList" :key="ind">
                    <div class="val" @click="warningTypeClick(item.type)">
                        {{ item.value }}
                    </div>
@@ -24,7 +24,7 @@
            </div>
            <div class="list">
                <div class="item" v-for="item, ind in equipmentList" :key="ind">
                <div class="item" v-for="(item, ind) in equipmentList" :key="ind">
                    <div class="val" :class="{highlight: item.isHighlight}" @click="equipmentClick(item.isHighlight)">
                        {{ item.value }}
                    </div>
@@ -39,9 +39,9 @@
</template>
<script setup>
import { ref } from 'vue'
import warningLogo from '@/assets/images/dataCockpit/warning.png'
import equipmentLogo from '@/assets/images/dataCockpit/equipment.png'
let warningList = ref([
    {
@@ -82,12 +82,12 @@
])
const warningTypeClick = (type) => {
    console.log('点击了告警类型:', type);
    console.log('点击了告警类型:', type)
}
const equipmentClick = (isHighlight) => {
    if (isHighlight) {
        console.log('点击了设备统计');
        console.log('点击了设备统计')
    }
}
</script>
@@ -196,4 +196,4 @@
        }
    }
}
</style>
</style>
applications/drone-command/src/views/dataCockpit/components/EquipmentWarning.vue
New file
@@ -0,0 +1,61 @@
<!--
 * @Author       : yuan
 * @Date         : 2026-01-08 09:29:07
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-08 14:49:25
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\EquipmentWarning.vue
 * @Description  :
 * Copyright 2026 OBKoro1, All Rights Reserved.
 * 2026-01-08 09:29:07
-->
<template>
    <div class="equipment-warning">
        <EquipmentTemplate v-for="(item, ind) in equipmentWarningData" :key="ind" :data="item" @click="onCardClick" />
    </div>
</template>
<script setup>
import EquipmentTemplate from './templateComponents/EquipmentTemplate.vue'
const equipmentWarningData = ref([
    {
        id: 'dev_001',
        name: '反制设备名称',
        status: '离线',
        statusType: 'offline', // offline | fault | online
        type: '察打一体',
        vendor: '厂商名称',
        azimuth: 14,          // 方位角(°)
        pitch: 14,            // 俯仰角(°)
        range: '1.2KM',       // 有效范围
        model: 'TDOAX1A',     // 设备型号
        longitude: 113.877571,
        latitude: 22.547155
    },
    {
        id: 'dev_002',
        name: '反制设备名称',
        status: '故障',
        statusType: 'fault',
        type: '察打一体',
        vendor: '厂商名称',
        azimuth: 14,
        pitch: 14,
        range: '1.2KM',
        model: 'TDOAX1A',
        longitude: 113.877571,
        latitude: 22.547155
    }
])
const onCardClick = (item) => {
    console.log('点击设备卡片:', item.id)
}
</script>
<style lang="scss" scoped>
.equipment-warning {
    width: 100%;
    height: 100%;
}
</style>
applications/drone-command/src/views/dataCockpit/components/HistoryWarning.vue
New file
@@ -0,0 +1,136 @@
<template>
    <div class="history-warning">
        <!-- 搜索区(设计稿红框) -->
        <div class="search-box">
            <!-- 关键字 -->
            <el-input v-model="query.keyword" class="ztzf-data-cockpit-search-input" placeholder="请输入数据名称" clearable
                @keyup.enter="onSearch">
            </el-input>
            <!-- 日期范围 -->
            <el-date-picker v-model="query.dateRange"
                  class="ztzf-data-cockpit-date-picker"
                 popper-class="ztzf-data-cockpit-date-picker-popper"
                type="daterange"
                range-separator="~"
                start-placeholder="创建开始日期" end-placeholder="结束日期" format="YYYY年MM月DD日" value-format="YYYY-MM-DD"
                :clearable="true" @change="onSearch">
            </el-date-picker>
        </div>
        <!-- 列表 -->
        <div class="list-content">
            <HistoryTemplate v-for="(item, ind) in filteredList" :key="item.id || ind" :data="item"
                @click="onCardClick" />
        </div>
    </div>
</template>
<script setup>
import { ref, computed } from 'vue'
import HistoryTemplate from './templateComponents/HistoryTemplate.vue'
// 原始数据(别动它,过滤用 computed)
const historyWarningData = ref([
    {
        id: 'drone_001',
        name: '无人机名称',
        serialNumber: 'XLH78945645456',
        dataSource: '侦测反制设备名称',
        frequency: '5800MHZ',
        discoveredAt: { date: '2025年12月30日', time: '14:55:06' },
        stayTime: '00:10:50',
        counterMethod: '信号干扰'
    },
    {
        id: 'drone_002',
        name: '无人机名称',
        serialNumber: 'XLH78945645456',
        dataSource: '侦测反制设备名称',
        frequency: '2400MHZ',
        discoveredAt: { date: '2025年12月30日', time: '15:08:12' },
        stayTime: '00:03:21',
        counterMethod: '诱导驱离'
    }
])
// 查询条件:keyword + dateRange(YYYY-MM-DD数组)
const query = ref({
    keyword: '',
    dateRange: [] // [start, end]
})
const onSearch = () => {
    // 目前是本地过滤:computed 会自动更新
    // 后续如果你要走接口,这里换成 fetchList(query.value) 即可
}
const onCardClick = (item) => {
    console.log('点击无人机卡片:', item.id)
}
// "2025年12月30日" -> "2025-12-30"
const cnDateToISO = (cn) => {
    if (!cn) return ''
    const m = cn.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/)
    if (!m) return ''
    const y = m[1]
    const mm = String(m[2]).padStart(2, '0')
    const dd = String(m[3]).padStart(2, '0')
    return `${y}-${mm}-${dd}`
}
const inRange = (targetISO, startISO, endISO) => {
    if (!targetISO) return false
    const t = new Date(`${targetISO}T00:00:00`).getTime()
    const s = startISO ? new Date(`${startISO}T00:00:00`).getTime() : null
    const e = endISO ? new Date(`${endISO}T23:59:59`).getTime() : null
    if (s !== null && t < s) return false
    if (e !== null && t > e) return false
    return true
}
const filteredList = computed(() => {
    const kw = (query.value.keyword || '').trim().toLowerCase()
    const [start, end] = query.value.dateRange || []
    return historyWarningData.value.filter((item) => {
        // 1) 关键字:name / serialNumber / dataSource
        const hitKeyword = !kw
            ? true
            : [item.name, item.serialNumber, item.dataSource]
                .filter(Boolean)
                .some((v) => String(v).toLowerCase().includes(kw))
        if (!hitKeyword) return false
        // 2) 日期范围:按 discoveredAt.date
        if (!start && !end) return true
        const itemISO = cnDateToISO(item?.discoveredAt?.date)
        return inRange(itemISO, start, end)
    })
})
</script>
<style scoped lang="scss">
.history-warning {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    .search-box {
        display: flex;
        flex-direction: column;
        gap: 10px;
        ::v-deep(.ztzf-data-cockpit-date-picker) {
            width: 100% !important;
        }
    }
    .list-content {
        height: 0;
        flex: 1;
    }
}
</style>
applications/drone-command/src/views/dataCockpit/components/LeftContainer.vue
@@ -1,15 +1,108 @@
<template>
    <div class="left-container">
        <div class="wrapper">
            <TitleTemplate>异常情况告警</TitleTemplate>
            <div class="category-container">
                <div class="category-item" v-for="(item, ind) in categoryList" :key="ind" @click="activeId = item.id"
                    :class="{ active: activeId === item.id }">
                    {{ item.name }}
                </div>
            </div>
            <div class="content">
                <component :is="currentComponent" />
            </div>
        </div>
    </div>
</template>
<script setup>
import TitleTemplate from './templateComponents/TitleTemplate.vue'
import RealWarning from './RealWarning.vue'
import EquipmentWarning from './EquipmentWarning.vue'
import HistoryWarning from './HistoryWarning.vue'
const activeId = ref(1)
const categoryList = ref([
    {
        id: 1,
        name: '实时告警',
        component: RealWarning
    },
    {
        id: 2,
        name: '设备告警',
        component: EquipmentWarning
    },
    {
        id: 3,
        name: '历史告警',
        component: HistoryWarning
    }
])
const currentComponent = computed(() => {
    return categoryList.value.find(i => i.id === activeId.value)?.component
})
</script>
<style lang="scss" scoped>
.category-container {
    display: flex;
    justify-content: space-between;
    .category-item {
        position: relative;
        width: 0;
        flex: 1;
        margin-left: 26px;
        height: 68px;
        line-height: 68px;
        font-family: Source Code Pro, Source Code Pro;
        font-weight: 400;
        font-size: 14px;
        color: #86909C;
        text-align: center;
        font-style: normal;
        text-transform: none;
        cursor: pointer;
        &:first-child {
            margin-left: 0;
        }
        &.active {
            font-weight: normal;
            color: #FFFFFF;
        }
        &::after {
            content: '';
            position: absolute;
            left: 0;
            bottom: 0;
            width: 100%;
            height: 1px;
            background: #333355;
        }
        &.active::after {
            height: 3px;
            background: #284FE3;
            box-shadow: 0px 3px 2px 0px rgba(15, 89, 255, 0.1), 0px 7px 5px 0px rgba(15, 89, 255, 0.15), 0px 13px 10px 0px rgba(15, 89, 255, 0.18), 0px 22px 18px 0px rgba(15, 89, 255, 0.21), 0px 42px 33px 0px rgba(15, 89, 255, 0.26), 0px 100px 80px 0px rgba(15, 89, 255, 0.36);
            border-radius: 5px 5px 0px 0px;
        }
    }
}
.content {
    height: 0;
    flex: 1;
    margin-top: 20px;
    overflow-x: hidden;
    overflow-y: auto;
}
</style>
applications/drone-command/src/views/dataCockpit/components/MapContainer.vue
@@ -22,7 +22,7 @@
onBeforeUnmount(() => {
    if (viewInstance) {
        viewInstance.destroy()
        viewInstance?.destroy()
        viewInstance = null
    }
applications/drone-command/src/views/dataCockpit/components/RealWarning.vue
New file
@@ -0,0 +1,76 @@
<!--
 * @Author       : yuan
 * @Date         : 2026-01-08 09:29:07
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-08 14:49:09
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\RealWarning.vue
 * @Description  :
 * Copyright 2026 OBKoro1, All Rights Reserved.
 * 2026-01-08 09:29:07
-->
<template>
    <div class="real-warning">
        <RealTemplate v-for="(item, ind) in realWarningData" :key="ind" :data="item"
            @signal="() => console.log('信号干扰', item.id)" @counter="() => console.log('诱导驱离', item.id)"
            @favorite="() => console.log('收藏', item.id)" />
    </div>
</template>
<script setup>
import RealTemplate from './templateComponents/RealTemplate.vue'
const realWarningData = ref([
    {
        "id": "drone_001",
        "name": "无人机A-01",
        "status": "侦测中",
        "statusType": "detecting",
        "serialNumber": "XLH789456456",
        "dataSource": "侦测反制设备名称",
        "longitude": 113.99238,
        "latitude": 22.541819,
        "frequency": "5800MHz",
        "discoverTime": "14:56:04",
        "altitude": "150m",
        "speed": "5.01m/s",
        "isFavorite": false
    },
    {
        "id": "drone_002",
        "name": "无人机B-07",
        "status": "反制中",
        "statusType": "countering",
        "serialNumber": "XLH789456789",
        "dataSource": "反制设备A区",
        "longitude": 113.99312,
        "latitude": 22.542031,
        "frequency": "2400MHz",
        "discoverTime": "15:02:41",
        "altitude": "120m",
        "speed": "3.86m/s",
        "isFavorite": true
    },
    {
        "id": "drone_002",
        "name": "无人机B-07",
        "status": "反制中",
        "statusType": "countering",
        "serialNumber": "XLH789456789",
        "dataSource": "反制设备A区",
        "longitude": 113.99312,
        "latitude": 22.542031,
        "frequency": "2400MHz",
        "discoverTime": "15:02:41",
        "altitude": "120m",
        "speed": "3.86m/s",
        "isFavorite": true
    }
])
</script>
<style lang="scss" scoped>
.real-warning {
    width: 100%;
    height: 100%;
}
</style>
applications/drone-command/src/views/dataCockpit/components/RightContainer.vue
@@ -1,15 +1,217 @@
<!--
 * @Author       : yuan
 * @Date         : 2026-01-07 15:17:54
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-08 15:58:15
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\RightContainer.vue
 * @Description  :
 * Copyright 2026 OBKoro1, All Rights Reserved.
 * 2026-01-07 15:17:54
-->
<template>
    <div class="right-container">
        <div class="wrapper">
            <TitleTemplate>侦测反制设备</TitleTemplate>
            <div class="category-container">
                <div class="category-item" v-for="(item, ind) in categoryList" :key="ind">
                    <div class="category-item-logo">
                        <img :src="item.logo" alt="">
                    </div>
                    <div class="category-item-content">
                        <span class="name">{{ item.name }}</span>
                        <span class="val">{{ item.val }}</span>
                    </div>
                </div>
            </div>
            <div class="content">
                <RealEquipmentTemplate v-for="item in counterDeviceStatusList" :key="item.id" :data="item"
                    @history="onHistory" @click="onCardClick" />
            </div>
        </div>
    </div>
</template>
<script setup>
import TitleTemplate from './templateComponents/TitleTemplate.vue'
import RealEquipmentTemplate from './templateComponents/RealEquipmentTemplate.vue'
import zcsbLogo from '@/assets/images/dataCockpit/zcsb.png'
import fzsbLogo from '@/assets/images/dataCockpit/fzsb.png'
const categoryList = ref([
    {
        id: 1,
        name: '侦测设备',
        val: 169,
        logo: zcsbLogo
    },
    {
        id: 2,
        name: '反制设备',
        val: 169,
        logo: fzsbLogo
    }
])
const counterDeviceStatusList = ref([
    {
        id: 'cd_001',
        name: '反制设备名称',
        actionText: '侦测中',          // 胶囊文案
        actionType: 'detecting',       // detecting | jamming | idle
        type: '察打一体',
        battery: 100,                  // 电量 %
        azimuth: 14,                   // 方位角
        pitch: 14,                     // 俯仰角
        statusText: '在线',            // 状态
        vendor: '厂商名称',            // 厂商
        targetCount: 10,               // 侦测目标
        range: '1.2KM'                 // 有效范围
    },
    {
        id: 'cd_002',
        name: '反制设备名称',
        actionText: '信号干扰中',
        actionType: 'jamming',
        type: '察打一体',
        battery: 100,
        azimuth: 14,
        pitch: 14,
        statusText: '在线',
        vendor: '厂商名称',
        targetCount: 10,
        range: '1.2KM'
    }
])
const onHistory = (item) => {
    console.log('历史数据:', item.id)
}
const onCardClick = (item) => {
    console.log('点击卡片:', item.id)
}
</script>
<style lang="scss" scoped>
.category-container {
    margin-top: 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 28px;
    box-sizing: border-box;
    .category-item {
        position: relative;
        width: 0;
        flex: 1;
        display: flex;
        height: 64px;
        &-logo {
            display: flex;
            align-items: center;
            img {
                width: 40px;
                height: 40px;
            }
        }
        &-content {
            width: 0;
            flex: 1;
            display: flex;
            flex-direction: column;
            border-bottom: 1px solid #6C6C89;
            span {
                margin-left: 8px;
            }
            .name {
                font-family: Open Sans, Open Sans;
                font-weight: 400;
                font-size: 16px;
                color: #C3C3DD;
                line-height: 20px;
                text-align: left;
                font-style: normal;
                text-transform: none;
            }
            .val {
                margin-top: 10px;
                font-family: DIN, DIN;
                font-weight: bold;
                font-size: 22px;
                color: #FFFFFF;
                line-height: 20px;
                text-align: left;
                font-style: normal;
                text-transform: none;
            }
        }
    }
}
.content {
    height: 0;
    flex: 1;
    margin-top: 20px;
    overflow-x: hidden;
    overflow-y: auto;
}
.right-container {
    transition: transform 0.3s ease-in-out;
    /* position: relative; Removed to avoid conflict with parent absolute positioning */
    &.collapsed {
        transform: translateX(100%);
    }
}
.collapse-btn {
    position: absolute;
    top: 50%;
    left: -24px;
    width: 24px;
    height: 60px;
    background: rgba(17, 23, 34, 0.8);
    border: 1px solid #333355;
    border-right: none;
    border-radius: 4px 0 0 4px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    transform: translateY(-50%);
    z-index: 10;
    backdrop-filter: blur(5px);
    .arrow {
        border: solid #fff;
        border-width: 0 2px 2px 0;
        display: inline-block;
        padding: 3px;
        transition: transform 0.3s;
        &.left {
            transform: rotate(135deg);
        }
        &.right {
            transform: rotate(-45deg);
        }
    }
    &:hover {
        background: rgba(40, 79, 227, 0.6);
    }
}
</style>
applications/drone-command/src/views/dataCockpit/components/templateComponents/EquipmentTemplate.vue
New file
@@ -0,0 +1,171 @@
<template>
    <div class="device-card" @click="emit('click', data)">
        <div class="header">
            <div class="title">
                <span class="name">{{ data.name }}</span>
                <span class="status">
                    <span :class="data.statusType">
                    </span>
                    <span>
                        {{ data.status }}
                    </span>
                </span>
            </div>
        </div>
        <div class="content">
            <div class="row">
                <div class="col">
                    <span class="label">类型</span>
                    {{ data.type }}
                </div>
                <div class="col">
                    <span class="label">厂商</span>
                    {{ data.vendor }}
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">方位角</span>
                    {{ data.azimuth }}°
                </div>
                <div class="col">
                    <span class="label">俯仰角</span>
                    {{ data.pitch }}°
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">有效范围</span>
                    {{ data.range }}
                </div>
                <div class="col">
                    <span class="label">设备型号</span>
                    {{ data.model }}
                </div>
            </div>
            <div>
                <span class="label">部署位置</span>
                <span class="value">{{ data.longitude }},{{ data.latitude }}</span>
            </div>
        </div>
    </div>
</template>
<script setup>
const props = defineProps({
    data: {
        type: Object,
        required: true,
        default: () => ({})
    }
})
const emit = defineEmits(['click'])
</script>
<style scoped lang="scss">
.device-card {
    margin-top: 10px;
    padding: 10px;
    color: #fff;
    background: #191933;
    border-radius: 6px 6px 6px 6px;
    &:first-child {
        margin-top: 0;
    }
    .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        .title {
            display: flex;
            align-items: center;
            gap: 6px;
            .name {
                font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: bold;
                font-size: 14px;
                color: #FFFFFF;
                text-align: left;
                font-style: normal;
                text-transform: none;
            }
            .status {
                padding: 0 10px;
                display: flex;
                align-items: center;
                justify-content: space-between;
                height: 21px;
                background: #303041;
                border-radius: 10px;
                gap: 6px;
                span {
                    font-family: Source Han Sans CN, Source Han Sans CN;
                    font-weight: 400;
                    font-size: 10px;
                    color: #FFFFFF;
                    text-align: center;
                    font-style: normal;
                    text-transform: none;
                }
                span.offline {
                    width: 4px;
                    height: 4px;
                    background: #939393;
                    border-radius: 50%;
                }
                span.fault {
                    width: 4px;
                    height: 4px;
                    background: #FF4444;
                    border-radius: 50%;
                }
            }
        }
    }
    .content {
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 12px;
        color: #9E9EBA;
        text-align: left;
        font-style: normal;
        text-transform: none;
        &>div {
            margin-top: 10px;
            line-height: 22px;
            span.label {
                margin-right: 10px;
                color: #D4D5D7;
            }
        }
        .row {
            display: flex;
            &>div {
                width: 0;
                flex: 1;
            }
        }
    }
}
</style>
applications/drone-command/src/views/dataCockpit/components/templateComponents/HistoryTemplate.vue
New file
@@ -0,0 +1,110 @@
<template>
    <div class="drone-info-card" @click="emit('click', data)">
        <div class="title">
            <span class="name">
                {{ data.name }}
            </span>
        </div>
        <div class="rows">
            <div class="row">
                <span class="label">序列号</span>
                <span class="value">{{ data.serialNumber }}</span>
            </div>
            <div class="row">
                <span class="label">数据源</span>
                <span class="value">{{ data.dataSource }}</span>
            </div>
            <div class="row">
                <span class="label">信号频段</span>
                <span class="value">{{ data.frequency }}</span>
            </div>
            <div class="row">
                <span class="label">发现时间</span>
                <span class="value">
                    <span class="date">{{ data.discoveredAt?.date }}</span>
                    <span class="time">{{ data.discoveredAt?.time }}</span>
                </span>
            </div>
            <div class="row">
                <span class="label">停留时间</span>
                <span class="value">{{ data.stayTime }}</span>
            </div>
            <div class="row">
                <span class="label">反制方式</span>
                <span class="value">{{ data.counterMethod }}</span>
            </div>
        </div>
    </div>
</template>
<script setup>
defineProps({
    data: {
        type: Object,
        required: true,
        default: () => ({})
    }
})
const emit = defineEmits(['click'])
</script>
<style scoped lang="scss">
.drone-info-card {
    margin-top: 10px;
    padding: 10px;
    color: #fff;
    background: #191933;
    border-radius: 6px 6px 6px 6px;
    &:hover {
        filter: brightness(1.05);
    }
    .title {
        display: flex;
        align-items: center;
        gap: 6px;
        .name {
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: bold;
            font-size: 14px;
            color: #FFFFFF;
            text-align: left;
            font-style: normal;
            text-transform: none;
        }
    }
    .rows {
        margin-top: 10px;
        display: flex;
        flex-direction: column;
        gap: 10px;
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 12px;
        color: #9E9EBA;
        text-align: left;
        font-style: normal;
        text-transform: none;
        .row {
            line-height: 22px;
            .label {
                margin-right: 10px;
                color: #D4D5D7;
            }
        }
    }
}
</style>
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealEquipmentTemplate.vue
New file
@@ -0,0 +1,199 @@
<script setup>
defineProps({
    data: {
        type: Object,
        required: true,
        default: () => ({})
    }
})
const emit = defineEmits(['history', 'click'])
</script>
<template>
    <div class="counter-card" @click="emit('click', data)">
        <!-- 头部 -->
        <div class="header">
            <div class="title">
                <span class="name">{{ data.name }}</span>
                <span class="status">
                    <span :class="data.actionType">
                    </span>
                    <span>
                        {{ data.actionText }}
                    </span>
                </span>
            </div>
        </div>
        <!-- 字段区:两列 -->
        <div class="content">
            <div class="row">
                <div class="col">
                    <span class="label">类型</span>
                    {{ data.type }}
                </div>
                <div class="col">
                    <span class="label">电量</span>
                    {{ data.battery }}%
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">方位角</span>
                    {{ data.azimuth }}°
                </div>
                <div class="col">
                    <span class="label">俯仰角</span>
                    {{ data.pitch }}°
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">状态</span>
                    {{ data.statusText }}
                </div>
                <div class="col">
                    <span class="label">厂商</span>
                    {{ data.vendor }}
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">侦测目标</span>
                    {{ data.targetCount }}台
                </div>
                <div class="col">
                    <span class="label">有效范围</span>
                    {{ data.range }}KM
                </div>
            </div>
        </div>
        <!-- 底部按钮 -->
        <div class="footer">
            <el-button color="#284FE3" type="primary" @click.stop="emit('history', data)">历史数据</el-button>
        </div>
    </div>
</template>
<style scoped lang="scss">
.counter-card {
    margin-top: 10px;
    padding: 10px;
    color: #fff;
    background: #191933;
    border-radius: 6px 6px 6px 6px;
    &:first-child {
        margin-top: 0;
    }
    .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        .title {
            display: flex;
            align-items: center;
            gap: 6px;
            .name {
                font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: bold;
                font-size: 14px;
                color: #FFFFFF;
                text-align: left;
                font-style: normal;
                text-transform: none;
            }
            .status {
                padding: 0 10px;
                display: flex;
                align-items: center;
                justify-content: space-between;
                height: 21px;
                background: #303041;
                border-radius: 10px;
                gap: 6px;
                span {
                    font-family: Source Han Sans CN, Source Han Sans CN;
                    font-weight: 400;
                    font-size: 10px;
                    color: #FFFFFF;
                    text-align: center;
                    font-style: normal;
                    text-transform: none;
                }
                span.detecting {
                    width: 4px;
                    height: 4px;
                    background: #18FF4A;
                    border-radius: 50%;
                }
                span.jamming {
                    width: 4px;
                    height: 4px;
                    background: #FF4444;
                    border-radius: 50%;
                }
            }
        }
    }
    .content {
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 12px;
        color: #9E9EBA;
        text-align: left;
        font-style: normal;
        text-transform: none;
        &>div {
            margin-top: 10px;
            line-height: 22px;
            span.label {
                margin-right: 10px;
                color: #D4D5D7;
            }
        }
        .row {
            display: flex;
            &>div {
                width: 0;
                flex: 1;
            }
        }
    }
    .footer {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        margin-top: 10px;
        ::v-deep(.el-button) {
            width: 96px;
            height: 36px;
        }
    }
}
</style>
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
New file
@@ -0,0 +1,204 @@
<template>
    <div class="drone-card">
        <div class="header">
            <div class="title">
                <span class="name">{{ data.name }}</span>
                <span class="status">
                    <span :class="data.statusType">
                    </span>
                    <span>
                        {{ data.status }}
                    </span>
                </span>
            </div>
            <div class="actions">
                <span class="star" @click="emit('favorite')">
                    {{ data.isFavorite ? '★' : '☆' }}
                </span>
            </div>
        </div>
        <div class="content">
            <div>
                <span class="label">序列号</span>
                {{ data.serialNumber }}
            </div>
            <div>
                <span class="label">数据源</span>
                {{ data.dataSource }}
            </div>
            <div>
                <span class="label">经纬度</span>
                {{ data.longitude }}, {{ data.latitude }}
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">信号频段</span>
                    {{ data.frequency }}
                </div>
                <div class="col">
                    <span class="label">发现时间</span>
                    {{ data.discoverTime }}
                </div>
            </div>
            <div class="row">
                <div class="col">
                    <span class="label">飞行高度</span>
                    {{ data.altitude }}
                </div>
                <div class="col">
                    <span class="label">飞行速度</span>
                    {{ data.speed }}
                </div>
            </div>
        </div>
        <div class="footer">
            <el-button class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
            <el-button color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
        </div>
    </div>
</template>
<script setup>
const props = defineProps({
    data: {
        type: Object,
        required: true,
        default: () => ({})
    }
})
const emit = defineEmits(['signal', 'counter', 'favorite'])
</script>
<style scoped lang="scss">
.drone-card {
    margin-top: 10px;
    padding: 10px;
    color: #fff;
    background: #191933;
    border-radius: 6px 6px 6px 6px;
    &:hover {
        background: #29294D;
        ;
    }
    &:first-child {
        margin-top: 0;
    }
    .header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        .title {
            display: flex;
            align-items: center;
            gap: 6px;
            .name {
                font-family: Source Han Sans CN, Source Han Sans CN;
                font-weight: bold;
                font-size: 14px;
                color: #FFFFFF;
                text-align: left;
                font-style: normal;
                text-transform: none;
            }
            .status {
                padding: 0 10px;
                display: flex;
                align-items: center;
                justify-content: space-between;
                height: 21px;
                background: #303041;
                border-radius: 10px;
                gap: 6px;
                span {
                    font-family: Source Han Sans CN, Source Han Sans CN;
                    font-weight: 400;
                    font-size: 10px;
                    color: #FFFFFF;
                    text-align: center;
                    font-style: normal;
                    text-transform: none;
                }
                span.detecting {
                    width: 4px;
                    height: 4px;
                    background: #18FF4A;
                    border-radius: 50%;
                }
                span.countering {
                    width: 4px;
                    height: 4px;
                    background: #FF4444;
                    border-radius: 50%;
                }
            }
        }
        .actions {
            display: flex;
            gap: 8px;
            font-size: 16px;
            cursor: pointer;
        }
    }
    .content {
        font-family: Source Han Sans CN, Source Han Sans CN;
        font-weight: 400;
        font-size: 12px;
        color: #9E9EBA;
        text-align: left;
        font-style: normal;
        text-transform: none;
        &>div {
            margin-top: 10px;
            line-height: 22px;
            span.label {
                margin-right: 10px;
                color: #D4D5D7;
            }
        }
        .row {
            display: flex;
            justify-content: space-between;
        }
    }
    .footer {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 10px;
        margin-top: 10px;
        ::v-deep(.el-button) {
            width: 96px;
            height: 36px;
            &.general.el-button {
                border-radius: 4px 4px 4px 4px;
                border: 1px solid rgba(255, 255, 255, 0.5);
            }
        }
    }
}
</style>
applications/drone-command/src/views/dataCockpit/components/templateComponents/TitleTemplate.vue
New file
@@ -0,0 +1,43 @@
<!--
 * @Author       : yuan
 * @Date         : 2026-01-08 09:32:52
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-08 09:43:00
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\templateComponents\TitleTemplate.vue
 * @Description  :
 * Copyright 2026 OBKoro1, All Rights Reserved.
 * 2026-01-08 09:32:52
-->
<template>
    <div class="title-box">
        <div class="title">
            <slot></slot>
        </div>
    </div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.title-box {
    padding-left: 26px;
    background: url('@/assets/images/dataCockpit/title-bg.png') center / 100% 100% no-repeat;
    height: 34px;
    .title {
        height: 25px;
        line-height: 25px;
        font-family: PangMen;
        font-weight: 400;
        font-size: 18px;
        color: #FFFFFF;
        letter-spacing: 1px;
        text-align: left;
        font-style: normal;
        text-transform: none;
    }
}
</style>
applications/drone-command/src/views/dataCockpit/index.vue
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2026-01-06 16:35:50
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-07 17:33:02
 * @LastEditTime : 2026-01-08 09:45:25
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\index.vue
 * @Description  : 
 * Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -41,6 +41,8 @@
    backdrop-filter: blur(5px);
    ::v-deep(.wrapper) {
      display: flex;
      flex-direction: column;
      position: absolute;
      top: 17px;
      bottom: 20px;
uniapps/work-app/src/pages.json
@@ -1,137 +1,130 @@
{
    "easycom": {
        "custom": {
            "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
            "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
            "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue",
            "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue"
        }
    },
    "pages": [
        {
            "path": "pages/work/index",
            "style": {
                "navigationBarTitleText": "事件工单",
                "navigationStyle": "custom"
            }
        },
        {
            "path": "pages/voiceCall/index",
            "style": {
                "navigationBarTitleText": "通话",
                "navigationStyle": "custom"
            }
        },
        {
            "path": "pages/map/index",
            "style": {
                "navigationBarTitleText": "地图",
                "navigationStyle": "custom"
            }
        },
  "easycom": {
    "custom": {
      "^u--(.*)": "uview-plus/components/u-$1/u-$1.vue",
      "^up-(.*)": "uview-plus/components/u-$1/u-$1.vue",
      "^u-([^-].*)": "uview-plus/components/u-$1/u-$1.vue",
      "^(?!z-paging-refresh|z-paging-load-more)z-paging(.*)": "z-paging/components/z-paging$1/z-paging$1.vue"
    }
  },
  "pages": [
    {
      "path": "pages/work/index",
      "style": {
        "navigationBarTitleText": "事件工单",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/voiceCall/index",
      "style": {
        "navigationBarTitleText": "通话",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/map/index",
      "style": {
        "navigationBarTitleText": "地图",
        "navigationStyle": "custom"
      }
    },
        {
            "path": "pages/user/index",
            "style": {
                "navigationBarTitleText": "我的",
                "navigationStyle": "custom"
            }
        },
        {
            "path": "pages/login/index",
            "style": {
                "navigationBarTitleText": "登录页",
                "navigationStyle": "custom"
            }
        }
    ],
    "subPackages": [
        {
            "root": "subPackages",
            "pages": [
                {
                    "path": "404/index",
                    "style": {
                        "navigationBarTitleText": "404",
                        "navigationStyle": "custom"
                    }
                },
                {
                    "path": "workDetail/index",
                    "style": {
                        "navigationBarTitleText": "工单详情"
                    }
                },
                {
                    "path": "workDetail/addWork/index",
                    "style": {
                        "navigationBarTitleText": "新建工单"
                    }
                },
                {
                    "path": "workDetail/mapWork/index",
                    "style": {
                        "navigationBarTitleText": "地图展示",
                        "navigationStyle": "custom"
                    }
                },
                {
                    "path": "userDetail/infos/index",
                    "style": {
                        "navigationBarTitleText": "个人资料"
                    }
                },
                {
                    "path": "userDetail/password/index",
                    "style": {
                        "navigationBarTitleText": "修改密码"
                    }
                },
                {
                    "path": "browser/index",
                    "style": {
                        "navigationBarTitleText": "地图"
                    }
                }
            ]
        }
    ],
    "tabBar": {
        "color": "#8c8c8c",
        "selectedColor": "#1D6FE9",
        "borderStyle": "black",
        "backgroundColor": "#ffffff",
        "list": [
            {
                "iconPath": "static/images/tabbar/icon_order.png",
                "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
                "pagePath": "pages/work/index",
                "text": "工单"
            },
            {
                "iconPath": "static/images/tabbar/icon_order.png",
                "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
                "pagePath": "pages/voiceCall/index",
                "text": "通话"
            },
            {
                "iconPath": "static/images/tabbar/icon_home1.png",
                "selectedIconPath": "static/images/tabbar/icon_home_selected.png",
                "pagePath": "pages/map/index",
                "text": "地图"
            },
            {
                "iconPath": "static/images/tabbar/icon_me.png",
                "selectedIconPath": "static/images/tabbar/icon_me_selected.png",
                "pagePath": "pages/user/index",
                "text": "我的"
            }
        ]
    },
    "globalStyle": {
        "navigationBarTextStyle": "black",
        "navigationBarTitleText": "uni-app",
        "navigationBarBackgroundColor": "#F8F8F8",
        "backgroundColor": "#F8F8F8"
    }
    {
      "path": "pages/user/index",
      "style": {
        "navigationBarTitleText": "我的",
        "navigationStyle": "custom"
      }
    },
    {
      "path": "pages/login/index",
      "style": {
        "navigationBarTitleText": "登录页",
        "navigationStyle": "custom"
      }
    }
  ],
  "subPackages": [
    {
      "root": "subPackages",
      "pages": [
        {
          "path": "404/index",
          "style": {
            "navigationBarTitleText": "404",
            "navigationStyle": "custom"
          }
        },
        {
          "path": "workDetail/index",
          "style": {
            "navigationBarTitleText": "工单详情"
          }
        },
        {
          "path": "workDetail/mapWork/index",
          "style": {
            "navigationBarTitleText": "工单位置"
          }
        },
        {
          "path": "userDetail/infos/index",
          "style": {
            "navigationBarTitleText": "个人资料"
          }
        },
        {
          "path": "userDetail/password/index",
          "style": {
            "navigationBarTitleText": "修改密码"
          }
        },
        {
          "path": "browser/index",
          "style": {
            "navigationBarTitleText": "地图"
          }
        }
      ]
    }
  ],
  "tabBar": {
    "color": "#8c8c8c",
    "selectedColor": "#1D6FE9",
    "borderStyle": "black",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "iconPath": "static/images/tabbar/icon_order.png",
        "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
        "pagePath": "pages/work/index",
        "text": "工单管理"
      },
      {
        "iconPath": "static/images/tabbar/icon_order.png",
        "selectedIconPath": "static/images/tabbar/icon_order_selected.png",
        "pagePath": "pages/voiceCall/index",
        "text": "语音通话"
      },
      {
        "iconPath": "static/images/tabbar/icon_home1.png",
        "selectedIconPath": "static/images/tabbar/icon_home_selected.png",
        "pagePath": "pages/map/index",
        "text": "地图"
      },
      {
        "iconPath": "static/images/tabbar/icon_me.png",
        "selectedIconPath": "static/images/tabbar/icon_me_selected.png",
        "pagePath": "pages/user/index",
        "text": "我的"
      }
    ]
  },
  "globalStyle": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "uni-app",
    "navigationBarBackgroundColor": "#F8F8F8",
    "backgroundColor": "#F8F8F8"
  }
}
uniapps/work-app/src/pages/login/index.vue
@@ -201,7 +201,9 @@
    text-align: center;
    margin-bottom: 168rpx;
  }
.user-name{
  margin-bottom: 40rpx;
}
  .user-name,
  .pass-word {
    display: flex;
@@ -209,8 +211,10 @@
    align-items: center;
    margin-left: 62rpx;
    margin-right: 58rpx;
    height: 118rpx;
    border-bottom: 2rpx solid #e3e3e3;
    height: 100rpx;
    background: #F1F4F9;
    border-radius: 8rpx 8rpx 8rpx 8rpx;
    padding: 0 22rpx;
    image {
      width: 40rpx;
@@ -321,4 +325,14 @@
    color: $u-warning;
  }
}
.agreement {
  position: absolute;
  bottom: 40rpx;
  left: 0;
  right: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}
</style>
uniapps/work-app/src/pages/work/index.vue
@@ -1,16 +1,207 @@
<template>
  <view class="eventTickets">
    工单
  </view>
  <div class="eventTickets" :style="{ paddingTop: topMargin + 'px' }">
    <div class="searchTop">
      <up-search placeholder="请输入关键字搜索"  :animation="true"  v-model="listParams.keyword" :show-action="false"></up-search>
    </div>
    <div class="listBox">
      <div class="tabs-container">
        <up-tabs :list="tabList" @click="handleClick"></up-tabs>
      </div>
      <div class="eventBox">
        <div class="eventItem"  v-for="(item,index) in dataList" :key="index">
          <img :src="item.photo_url" alt="" @click="detailHandle(item)" />
          <div class="informationDisplay">
            <div class="itemTitle">{{item.event_name}}</div>
            <div class="itemContent">{{formatDate(item.create_time) }}</div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script setup>
import { useUserStore } from '@/store/index.js'
import {getList,getstatusCount} from '/src/api/work/index.js'
import dayjs from 'dayjs';
import { getStatusBarHeight } from '@/utils/common';
const userStore = useUserStore()
const userInfo = userStore.userInfo
const dataList = ref([])
const currentTab=ref('all')
const tabList = ref([
  {
    name: '全部工单',
    key: 'all',
    badge: {
      value: 2
    },
    status: null
  },
  {
    name: '我的工单',
    key: 'myTickets',
    badge: {
      value: 1
    }
  },
])
const formatDate = (dateString) => {
  return dayjs(dateString).format('MM/DD HH:mm');
};
const listParams = ref({
  status: null,
  current: 1,
  size: 9999,
  source: 1,
  department:'',
  keyword:''
})
const getDataList = () => {
  const params = {
    current: 1,
    size: 9999,
    source: 1,
    status:listParams.value.status,
    event_name:listParams.value.keyword,
    user_id:currentTab.value=== 'myTickets' ?userInfo.user_id : undefined
  }
  getList(params).then(res => {
    const response = res.data.data.records
    dataList.value = response
  })
}
// const getstatusCountData=()=>{
//     getstatusCount().then(res=>{
//         const response = res.data.data
//          const { statusCount, totalCount, userCount } = response
//         tabList.value.forEach(tab=>{
//
//             if(tab.key === 'all'){
//                 tab.badge.value = totalCount || 0
//
//             }else if(tab.key === 'myTickets'){
//                 tab.badge.value = userCount || 0
//             }else{
//                 tab.badge.value=statusCount[String(tab.status)] || 0
//             }
//         })
//
//     })
// }
const handleClick = (item) => {
  currentTab.value = item.key
  listParams.value.status = item.status
  getDataList()
}
const detailHandle = (val) => {
  uni.navigateTo({
    url: `/subPackages/workDetail/index?eventNum=${val.event_num}`,
  })
}
const topMargin = getStatusBarHeight()
onShow(() => {
  getDataList()
})
</script>
<style scoped lang="scss">
.eventTickets {
  width: 100%;
  padding: 0 20rpx;
  display: flex;
  flex-direction: column;
  height: 100%;
  box-sizing: border-box;
  .searchTop {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-right: 24rpx;
    width: 100%;
    height: 108rpx;
  }
  :deep(){
    .u-tabs__wrapper__nav__line{
      width: 80rpx !important;
      background: #1D6FE9 !important;
    }
    .u-badge {
      background-color: #1d6fe9 !important;
    }
  }
  .tabs-container{
    display: flex;
    justify-content: center;
    height: 98rpx;
  }
  .listBox {
    position: relative;
    display: flex;
    flex-direction: column;
    flex: 1;
  }
  .eventBox {
    display: flex;
    flex-wrap: wrap;
    gap: 20rpx;
    padding: 20rpx 0;
    overflow-y: auto;
    height: 0;
    flex-grow: 1;
    align-content: flex-start;
    .eventItem {
      width: calc(50% - 10rpx);
      background-color: #fff;
      border-radius: 12rpx;
      overflow: hidden;
      img {
        width: 341rpx;
        height: 196rpx;
        border-radius: 12rpx;
        overflow: hidden;
      }
      .informationDisplay{
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 10rpx 20rpx 10rpx 12rpx;
        .itemTitle {
          width: 144rpx;
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: 500;
          font-size: 28rpx;
          color: #000000;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
        .itemContent {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: 400;
          font-size: 24rpx;
          color: rgba(0,0,0,0.5);
        }
      }
    }
  }
}
</style>
uniapps/work-app/src/subPackages/workDetail/index.vue
@@ -1,68 +1,282 @@
<!-- 工单详情 - 包含待审核、待处理、处理中、已完成 -->
<!-- 工单详情 -->
<template>
  <div class="workDetailContainer">
    <WebViewPlus
      ref="sWebViewRef"
      :src="`${viewUrl}`"
      @webMessage="onPostMessage"
    />
    <div class="detailTop">
      <div class="image-container">
        <u-swiper
          class="detailImage"
          :list="getImageList"
          mode="round"
          indicator
          indicatorMode="dot"
          indicatorActiveColor="#4C85FF"
          indicatorInactiveColor="#fff"
          indicatorPosition="center"
          height="410rpx"
          @click="previewImage"
        ></u-swiper>
        <!--                <div class="detailTitle">-->
        <!--                    <div class="titleText">-->
        <!--                        <div class="itemName">{{workDetailData.event_name}}</div>-->
        <!--                        <div class="itemTime">{{formatDate(workDetailData.create_time)}}</div>-->
        <!--                    </div>-->
        <!--                </div>-->
      </div>
    </div>
    <!-- 工单内容 -->
    <div class="worderContainer">
      <div class="workOrderContent">
        <div class="workOrderTitle">工单内容</div>
        <div class="workOrderContainer">
          <div class="orderRow">
            <div class="rowTitle">工单编号</div>
            <div>{{workDetailData.event_num}}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">工单处置人</div>
            <div>{{workDetailData.event_num?.slice(0, 2) === 'AI' ? 'AI 小飞':workDetailData.creator}}
            </div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">处置部门</div>
            <div>{{ workDetailData.dept_name }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">拍摄时间</div>
            <div>{{ workDetailData.create_time }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">分发人员</div>
            <div>{{ workDetailData.remark }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">分发部门</div>
            <div>{{ workDetailData.remark }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">分发时间</div>
            <div>{{ workDetailData.create_time }}</div>
          </div>
          <div class="orderRow">
            <div class="rowTitle">工单位置</div>
            <div class="rowAddress" @click="jumpMap(workDetailData)">{{ workDetailData.address }}</div>
          </div>
        </div>
      </div>
    </div>
    <!-- 操作按钮 -->
    <div class="actionButton">
      <div class="btngroups" >
        <up-button type="primary" color="#AEAEAE" text="退回"></up-button>
        <up-button type="primary" color="#1D6FE9" text="确认"></up-button>
      </div>
    </div>
  </div>
</template>
<script setup>
import { getWebViewUrl } from "@/utils/index.js";
import { onLoad } from "@dcloudio/uni-app";
import { useUserStore } from "@/store/index.js";
const userStore = useUserStore();
const userInfo = userStore.userInfo;
const sWebViewRef = ref(null);
const viewUrl = ref("");
onLoad((options) => {
  const eventNum = options.eventNum;
  viewUrl.value = getWebViewUrl("/workDetail", {
    eventNum: eventNum,
    totalNum: options.totalNum,
    keyword: options.keyword,
    aiType: options.aiType,
    wLJobInfoId: options.wLJobInfoId,
    status: options.status,
    current: options.current,
  });
// import { getShowImg, getSmallImg } from '@/utils/util'
import {getList,flowEvent} from '/src/api/work/index.js'
import dayjs from 'dayjs'
const formatDate = dateString => {
  return dayjs(dateString).format('MM/DD HH:mm')
}
const eventNum = ref('');
// 工单内容
const workDetailData = ref({})
onLoad(async (options) => {
  eventNum.value = options.eventNum;
  await getDataList(eventNum.value);
});
function onPostMessage(data) {
  if (data.type === "workback") {
    // #ifdef MP-WEIXIN
    if ("fun" in data && data.fun === "add") {
      uni.setStorageSync("joinParams", {
        type: "add",
      });
    }
    // #endif
    // #ifndef MP-WEIXIN
    uni.setStorageSync("joinParams", {
      type: "add",
    });
    uni.switchTab({
      url: `/pages/work/index?addLog=111`,
      // url: '/pages/work/index'
    });
    // #endif
  } else if (data.type === "jumpMapNav") {
    // #ifndef MP-WEIXIN
    uni.navigateTo({
      url: `/subPackages/workDetail/mapWork/index?currentItem=${data.eventNum}`,
    });
    // #endif
const getDataList = async (val) => {
  const params = {
    current: 1,
    size: 9999,
    source: 1,
    event_name: val
  }
  const res = await getList(params);
  const response = res.data.data.records;
  workDetailData.value = response[0];
  console.log('详情',response);
}
// 图片预览
const previewImage = (index) => {
  if (getImageList.value.length === 0) return;
  const currentIndex = typeof index === 'number' ? index : 0;
  uni.previewImage({
    urls: getImageList.value,
    current: currentIndex
  });
};
const getImageList =computed(()=>{
  const imageArr = []
  const detail = workDetailData.value
  if (detail.photo_url) {
    const smallUrl = detail.photo_url
    imageArr.push(smallUrl)
  }
  if (detail.update_photo_url) {
    const smallUrl =detail.update_photo_url
    imageArr.push(smallUrl)
  }
  return imageArr
})
// 跳转地图
const jumpMap = item => {
  uni.navigateTo({
    url: `/subPackages/workDetail/mapWork/index?eventNum=${item.event_num}`,
  })
}
</script>
<style lang="scss" scoped>
.workDetailContainer {
  width: 100%;
  height: 100%;
  background-size: cover;
  .detailTop {
    .image-container {
      position: relative;
      width: 100%;
      height: 410rpx;
      .detailImage {
        width: 100%;
        height: 100%;
        display: block;
        object-fit: cover;
      }
      // 轮播图容器
      :deep(.u-swiper) {
        // 指示器容器 - 修改为居中对齐
        .u-swiper__indicator {
          position: absolute;
          left: 50%;
          transform: translateX(-50%);
          bottom: 20rpx;
          display: flex;
          justify-content: center;
          align-items: center;
          z-index: 10;
        }
        .u-swiper-indicator__wrapper__dot--active{
          width: 5px !important;
        }
      }
      .detailTitle {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 60rpx;
        line-height: 60rpx;
        background: rgba(7, 7, 7, 0.4);
      }
      .titleText {
        display: flex;
        width: 100%;
        justify-content: space-between;
        align-items: center;
        color: #fff;
        .itemName, .itemTime {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: 400;
          font-size: 28rpx;
          color: #FFFFFF;
        }
        .itemName {
          padding-left: 20rpx;
        }
        .itemTime{
          padding-right: 20rpx;
        }
      }
    }
  }
  .worderContainer {
    padding: 0 24rpx;
    padding-bottom: 4rpx;
    background: #f6f6f6;
    margin-top: 20rpx;
  }
  .workOrderContent {
    margin-top: 30epx;
    background-color: #fff;
    border-radius: 12rpx;
    padding: 20rpx;
    margin-bottom: 34rpx;
    .workOrderTitle {
      font-family: Source Han Sans CN, Source Han Sans CN;
      font-weight: bold;
      font-size: 32rpx;
      color: #222324;
    }
    .workOrderContainer {
      .orderRow {
        display: flex;
        justify-content: space-between;
        align-items: center;
        min-height: 96rpx;
        border-bottom: 1px solid #f5f5f5;
        color: #7b7b7b;
        .rowTitle {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: 400;
          font-size: 30rpx;
          color: #222324;
          white-space: nowrap;
        }
        .rowAddress {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: 400;
          font-size: 28rpx;
          color: #1D6FE9;
          //white-space: nowrap;
          ///* 禁止换行 */
          //overflow: hidden;
          //text-overflow: ellipsis;
          // max-width: 74%;
          padding-top: 1px;
          padding-left: 5px;
          padding-right: 2px;
        }
      }
    }
  }
  .actionButton {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    height: 61px;
    border-radius: 6px 6px 6px 6px;
    .btngroups {
      display: flex;
      justify-content: space-between;
      align-items: center;
      :deep(.u-button){
        width: 276rpx !important;
        height: 100rpx !important;
        &:last-child {
          margin-left: 30rpx;
        }
      }
    }
  }
}
</style>
uniapps/work-app/src/subPackages/workDetail/mapWork/index.vue
@@ -1,13 +1,4 @@
<!--
 * @Author       : yuan
 * @Date         : 2025-10-22 14:59:10
 * @LastEditors  : yuan
 * @LastEditTime : 2025-12-19 14:52:54
 * @FilePath     : \src\subPackages\workDetail\mapWork\index.vue
 * @Description  :
 * Copyright 2025 OBKoro1, All Rights Reserved.
 * 2025-10-22 14:59:10
-->
<!-- 地图展示 -->
<template>
  <WebViewPlus
@@ -25,7 +16,7 @@
const viewUrl = ref("");
onLoad((options) => {
  const currentItem = options.currentItem;
  const currentItem = options.eventNum;
  viewUrl.value = getWebViewUrl("/mapWork", { currentItem: currentItem });
});
function onPostMessage(data) {