无人机管理后台前端(已迁走)
张含笑
2025-10-30 02b07aa1314da966a8a07ff0257fc6b240dfeb1a
feat:文件夹
4 files modified
1 files added
325 ■■■■■ changed files
src/styles/element-ui.scss 53 ●●●●● patch | view | raw | blame | history
src/views/layerManagement/components/folderFile.vue 237 ●●●●● patch | view | raw | blame | history
src/views/layerManagement/components/leftList.vue 24 ●●●●● patch | view | raw | blame | history
src/views/layerManagement/components/rightEdit.vue 4 ●●●● patch | view | raw | blame | history
src/views/layerManagement/index.vue 7 ●●●● patch | view | raw | blame | history
src/styles/element-ui.scss
@@ -182,6 +182,7 @@
  color: #fff !important;
}
.ztzf-layer-search {
  color: #fff !important;
  background-color: transparent !important;
  .el-select__wrapper {
    background-color: transparent !important;
@@ -192,6 +193,58 @@
  .el-popper.is-light {
    background-color: transparent !important;
  }
  // .el-select__placeholder {
  // color: #fff !important;}
}
.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;
    }
}
//======以下针对表格功能 增删查改样式和弹窗=========
src/views/layerManagement/components/folderFile.vue
New file
@@ -0,0 +1,237 @@
<template>
  <div class="rightContainer">
    <div class="contenttitle">文件夹信息</div>
    <div class="centerBox">
      <div class="itemRow">
        <div class="label">文件夹名称</div>
        <div>
          <el-input class="ztzf-input inputName" v-model="formData.name" placeholder="请输入" />
        </div>
      </div>
      <div class="itemRow">
        <div class="label">关联算法</div>
        <div>
          <el-select
            class="ztzf-layer-search filter-item"
            popper-class="ztzf-select-popper"
            @change="handleTypeChange"
            v-model="formData.type"
            placeholder="请选择"
          >
            <el-option
              v-for="item in types"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
          <el-select
            v-model="formData.algorithm"
            popper-class="ztzf-select-popper"
            class="ztzf-layer-search"
            placeholder="请选择"
            :disabled="!formData.type"
          >
            <el-option
              v-for="item in algorithms"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </div>
      </div>
    </div>
    <div class="detailInfo">
      <div class="infpItem">
        <div class="itemData">
          <div class="title">围栏总数量</div>
          <div class="num"><span>{{totalCount}}</span>个</div>
        </div>
        <div class="itemData">
          <div class="title">围栏总面积</div>
          <div class="num"><span>{{totalArea}}</span>m²</div>
        </div>
      </div>
      <div class="infpItem">
        <div class="itemData">
          <div class="title">创建时间</div>
          <div class="num"><span>{{formData?.create_time}}</span></div>
        </div>
        <div class="itemData">
          <div class="title">创建人</div>
          <div class="num"><span>{{formData?.create_name}}</span></div>
        </div>
      </div>
    </div>
    <div class="btnGroups">
      <img src="/src/assets/images/layerManagement/savebtn.svg" alt="" @click="submitHandle" />
      <img src="/src/assets/images/layerManagement/cancelbtn.svg" @click="cancelHandel" alt="" />
    </div>
  </div>
</template>
<script setup>
import { deitFenceApi } from '@/api/layer/index';
import {
  getTicketInfo,
} from '@/api/tickets/ticket';
const layerParams = inject('layerParams');
const types = ref([]) //工单类型
const allAlgorithms = ref([])
const algorithms = ref([])
const formData = ref({
  folder_id: '',
  name: '',
  description: '',
  is_enabled: false,
  area: '',
  altitude: '',
  control_start_time: '',
  control_end_time: '',
  geo_data: '',
  algorithm:'',
  type: '',
});
const detailData = ref(null)
const totalArea = ref(null)
const totalCount = ref(null)
detailData.value = layerParams.value.editDetailData
totalArea.value = layerParams.value.total_area
totalCount.value = layerParams.value.total_count
const getTicketInfoData = async () => {
  const response = await getTicketInfo()
  const { dept_data, event_type, ai_type, info } = response.data.data
  allAlgorithms.value = info
  types.value = Object.entries(event_type).map(([key, value]) => ({
    label: value,
    value: key,
  }))
}
const handleTypeChange=(typeValue)=>{
  const matchedCategory = allAlgorithms.value.find(category => category.dict_key === typeValue)
  if (!matchedCategory || !matchedCategory.algorithms || matchedCategory.algorithms.length === 0) {
    // 无匹配的算法时清空
    algorithms.value = []
    return
  }
  algorithms.value = matchedCategory.algorithms.map(algo => ({
    label: algo.dict_value,
    value: algo.dict_key,
    dict_key: algo.dict_key,
    dict_value: algo.dict_value,
  }))
  console.log(' algorithms.value ', algorithms.value );
}
const clearAllData = () => {
  detailData.value = {}
  // 清空回显相关数据
  detailData.value = {};
  totalArea.value = null;
  totalCount.value = null;
  // 重置判断状态(可选,根据业务需求是否需要)
  layerParams.value.decideWhetherToAddOrEdit = 1;
  // 重置面板状态和缓存数据
  layerParams.value.addFolder = false;
  layerParams.value.editFolder = false;
  layerParams.value.editDetailData = null;
  layerParams.value.polygonPosition = null;
};
const cancelHandel = () => {
  clearAllData()
};
const submitHandle = () => {
  clearAllData()
};
onMounted(() => {
  getTicketInfoData()
});
</script>
<style scoped lang="scss">
.rightContainer {
  position: absolute;
  top: 0;
  right: 0;
  height: 95%;
  z-index: 99;
  width: 324px;
  overflow: hidden;
  background: rgba(0, 0, 0, 0.8);
  border-radius: 8px 8px 8px 8px;
  padding: 16px 12px;
  :deep(.el-textarea__inner) {
    background: transparent !important;
    color: #ffffff !important;
  }
  .contenttitle {
    font-family: Source Han Sans CN, Source Han Sans CN;
    font-weight: bold;
    font-size: 16px;
    color: #ffffff;
    margin-bottom: 20px;
  }
  .centerBox {
    font-family: Source Han Sans CN, Source Han Sans CN;
    font-weight: 400;
    font-size: 14px;
    color: #ffffff;
    .itemRow {
      margin-bottom: 35px;
    }
    .label {
      margin-bottom: 5px;
    }
  }
  .detailInfo {
    .infpItem {
      display: flex;
      justify-content: space-between;
      align-items: center;
      font-family: Source Han Sans CN, Source Han Sans CN;
      font-weight: 400;
      font-size: 14px;
      color: #ffffff;
      margin-bottom: 23px;
      .num {
        span {
          font-family: Source Han Sans CN, Source Han Sans CN;
          font-weight: bold;
          font-size: 20px;
          color: #ffffff;
        }
      }
      .itemData {
        width: 50%;
      }
    }
  }
  .btnGroups {
    display: flex;
    justify-content: center;
    position: absolute;
    bottom: 59px;
    left: 0;
    right: 0;
    img {
      width: 125px;
      height: 39px;
      cursor: pointer;
    }
  }
}
.filter-item {
  margin-bottom: 12px;
}
</style>
src/views/layerManagement/components/leftList.vue
@@ -159,12 +159,14 @@
  layerParams.value.addNest = true;
   layerParams.value.decideWhetherToAddOrEdit = 1
   emit('newFencesMethods');
  console.log('layerParams.value',layerParams.value);
  
};
// 新增文件夹
const addFolder = () => {};
const addFolder = () => {
  layerParams.value.addFolder = true
  layerParams.value.addAnEditingFolder =1
};
onMounted(() => {
  gettreeDataApi();
});
@@ -233,11 +235,29 @@
  display: flex;
}
.tableListBox {
  //:deep(.el-tree-node__content) {
  //  // 奇数行背景色
  //  &:nth-child(odd) {
  //    background-color: rgba(13, 43, 56, 0.5) !important;
  //  }
  //  // 偶数行背景色
  //  &:nth-child(even) {
  //    background-color: rgba(30, 45, 81, 0.5) !important;
  //  }
  //}
  :deep(){
    .el-checkbox{
      --el-checkbox-bg-color: transparent !important;
    }
  }
  .tree-node {
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
  }
  .tree-node-actions {
src/views/layerManagement/components/rightEdit.vue
@@ -5,7 +5,7 @@
      <div class="itemRow">
        <div class="label">文件夹名称</div>
        <div>
          <el-select class="ztzf-layer-search" v-model="formData.area" placeholder="Select">
          <el-select class="ztzf-layer-search" popper-class="ztzf-select-popper" v-model="formData.area" placeholder="请选择">
            <el-option
              v-for="item in options"
              :key="item.value"
@@ -18,7 +18,7 @@
      <div class="itemRow">
        <div class="label">围栏名称</div>
        <div>
          <el-input class="ztzf-input inputName" v-model="formData.name" placeholder="围栏名称" />
          <el-input class="ztzf-input inputName" v-model="formData.name" placeholder="请输入" />
        </div>
      </div>
      <div class="itemRow">
src/views/layerManagement/index.vue
@@ -11,7 +11,7 @@
      <div class="mapContainer">
        <div id="layMap" class="ztzf-cesium"></div>
        <leftList
          v-if="!layerParams.addNest && !layerParams.editNest && activeType !== '2'"
          v-if="!layerParams.addNest && !layerParams.editNest&& !layerParams.addFolder && activeType !== '2'"
          @update:coverData="handleCoverDataUpdate"
          @update:deitData="handleEdit"
          :activeName="activeName"
@@ -21,6 +21,7 @@
          v-if="layerParams.addNest || layerParams.editNest && activeType !== '2'"
          @callParentMethod="parentMethod"
        ></rightEdit>
        <folderFile  v-if="layerParams.addFolder || layerParams.editFolder && activeType !== '2'"></folderFile>
        <nationalSpatialPlanning v-if="activeType === '2'" />
      </div>
    </div>
@@ -28,6 +29,7 @@
</template>
<script setup>
import folderFile from '@/views/layerManagement/components/folderFile.vue'
import { parseGeoDataToPositions } from '@/utils/geoParseUtil';
import { flyVisual } from '@/utils/cesium/mapUtil';
import rightEdit from '@/views/layerManagement/components/rightEdit.vue';
@@ -65,6 +67,9 @@
  total_area: 0,
  polygonPosition:null,
  decideWhetherToAddOrEdit:null,//新增or编辑围栏
  addAnEditingFolder:null,//新增or编辑文件夹
  addFolder:false,
  editFolder:false,
});
provide('layerParams', layerParams);
const handleClick = tab => {