2025.7.18 监管任务模块
1. 监管场景样式优化;
2. 新增监管场景GIS地图展示(待完成);
已修改14个文件
已添加12个文件
600 ■■■■ 文件已修改
index.html 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_15.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_16.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_17.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_18.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_19.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_20.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_4.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_5.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/scene_6.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/scene-icon.js 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemMonitorObj.vue 93 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/map/BaseMap.vue 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/map/SceneMap.vue 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/index.js 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/map/marks.js 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/MonitorObjEdit.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/TaskManage.vue 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompMonitorObj.vue 70 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompMonitorObjEdit.vue 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompMonitorPlan.vue 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/components/CompTaskMap.vue 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 27 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html
@@ -9,12 +9,12 @@
  <body>
    <div id="app"></div>
  </body>
  <!-- <script type="text/javascript">
  <script type="text/javascript">
    window._AMapSecurityConfig = {
      serviceHost: 'http://47.100.191.150:8083/_AMapService'
    };
  </script>
  <script
  <!-- <script
    type="text/javascript"
    src="https://webapi.amap.com/maps?v=1.4.5&key=520c5e5cf44c7793104e500cbf0ed711&plugin=Map3D,ElasticMarker,AMap.ControlBar,AMap.Geocoder"
  ></script> -->
src/api/index.js
@@ -13,7 +13,7 @@
let ip2_file = 'https://fyami.com.cn/';
if (debug) {
  ip1 = 'http://192.168.0.103:8080/';
  ip1 = 'http://192.168.0.103:9001/';
  // ip1_file = 'http://192.168.0.138:8080/';
  // ip2 = 'http://192.168.0.138:8080/';
  // ip2_file = 'https://fyami.com.cn/';
src/assets/image/scene_1.png
src/assets/image/scene_15.png
src/assets/image/scene_16.png
src/assets/image/scene_17.png
src/assets/image/scene_18.png
src/assets/image/scene_19.png
src/assets/image/scene_20.png
src/assets/image/scene_4.png
src/assets/image/scene_5.png
src/assets/image/scene_6.png
src/assets/scene-icon.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,43 @@
import scene_1 from '@/assets/image/scene_1.png';
import scene_4 from '@/assets/image/scene_4.png';
import scene_5 from '@/assets/image/scene_5.png';
import scene_6 from '@/assets/image/scene_6.png';
import scene_15 from '@/assets/image/scene_15.png';
import scene_16 from '@/assets/image/scene_16.png';
import scene_17 from '@/assets/image/scene_17.png';
import scene_18 from '@/assets/image/scene_18.png';
import scene_19 from '@/assets/image/scene_19.png';
import scene_20 from '@/assets/image/scene_20.png';
function sceneIcon(type) {
  switch (type + '') {
    case '1':
      return scene_1;
    case '2':
      return scene_1;
    case '3':
      return scene_1;
    case '4':
      return scene_4;
    case '5':
      return scene_5;
    case '6':
      return scene_6;
    case '15':
      return scene_15;
    case '16':
      return scene_16;
    case '17':
      return scene_17;
    case '18':
      return scene_18;
    case '19':
      return scene_19;
    case '20':
      return scene_20;
    default:
      return scene_1;
  }
}
export { sceneIcon };
src/components.d.ts
@@ -63,6 +63,7 @@
    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScroll: typeof import('element-plus/es')['ElScroll']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSegmented: typeof import('element-plus/es')['ElSegmented']
    ElSelect: typeof import('element-plus/es')['ElSelect']
src/components/list-item/ItemMonitorObj.vue
@@ -1,24 +1,53 @@
<template>
  <!-- <el-card shadow="hover"> -->
  <div class="wrapper">
  <div :class="statusClass + ' wrapper'">
    <div>
      <el-text>{{ item.displayid }}、</el-text>
      <el-text truncated class="w-250px">{{ item.sensename }}</el-text>
      <!-- <el-text>{{ item.displayid }}、</el-text> -->
      <el-text tag="b" class="text-line-2">
        {{ item.displayid + '、' + item.sensename }}
      </el-text>
    </div>
    <!-- <div>
      <el-text>地址:{{ item.location }}</el-text>
    </div> -->
    <div>
      <el-text truncated class="w-250px" type="info">
        <el-icon><LocationInformation /></el-icon>
        {{ item.scene.location }}
      </el-text>
    </div>
    <el-row justify="space-between" style="margin-top: 4px">
      <el-space>
        <el-tag type="info" effect="plain" size="small">
        <el-tag
          v-if="item.extension1 == '1'"
          type="success"
          effect="plain"
          size="small"
        >
          <el-icon :size="8"><Select /></el-icon>
          <span>已监管</span>
        </el-tag>
        <el-tag
          v-else-if="!item.extension1 || item.extension1 == '0'"
          type="danger"
          effect="plain"
          size="small"
        >
          <el-icon :size="8"><CloseBold /></el-icon>
          <span>未监管</span>
        </el-tag>
        <el-tag v-else type="primary" effect="plain" size="small">
          <el-icon :size="8"><Select /></el-icon>
          <span>已复核</span>
        </el-tag>
        <!-- <el-tag type="info" effect="plain" size="small">
          {{ item.sceneType }}
        </el-tag>
        <el-tag type="info" effect="plain" size="small">
          è®¡åˆ’监管:{{ item.monitornum }}
        </el-tag>
        <el-tag type="info" effect="plain" size="small">
          å·²ç›‘管:{{ item.extension1 ? item.extension1 : '0' }}
        </el-tag>
        </el-tag> -->
        <el-space>
          <el-tag type="info" size="small">
            è®¡åˆ’:{{ item.monitornum }}次
          </el-tag>
          <el-tag type="info" size="small">
            ç›‘管:{{ item.extension1 ? item.extension1 : '0' }}次
          </el-tag>
        </el-space>
      </el-space>
      <slot :item="item"></slot>
      <!-- <el-button size="small" type="success" @click="add">添加</el-button> -->
@@ -30,7 +59,7 @@
/**
 * ç›‘管对象
 */
import { computed } from 'vue';
const props = defineProps({
  item: {
@@ -40,6 +69,16 @@
});
const emit = defineEmits(['add']);
const statusClass = computed(() => {
  if (!props.item.extension1 || props.item.extension1 == '0') {
    return 'border-bottom-danger';
  } else if (props.item.extension1 == '1') {
    return 'border-bottom-success';
  } else {
    return 'border-bottom-primary';
  }
});
function add() {
  emit('add', props.item);
@@ -51,5 +90,29 @@
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  padding: 4px 8px;
  box-shadow: var(--el-box-shadow-light);
}
.text-line-2 {
  width: 300px;
  height: 40px;
  display: -webkit-box;
  line-clamp: 2;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-overflow: ellipsis;
}
.border-bottom-success {
  border-left: 3px solid var(--el-color-success);
}
.border-bottom-danger {
  border-left: 3px solid var(--el-color-danger);
}
.border-bottom-primary {
  border-left: 3px solid var(--el-color-primary);
}
</style>
src/components/map/BaseMap.vue
@@ -3,12 +3,15 @@
</template>
<script setup>
import { onMounted } from 'vue';
import { createMap } from '@/utils/map/index_old';
import { onMounted, onUnmounted } from 'vue';
import { createMap, map } from '@/utils/map/index';
onMounted(() => {
  // é«˜å¾·åœ°å›¾åˆå§‹åŒ–
  createMap('container');
});
onUnmounted(() => {
  map?.destroy();
});
</script>
<style>
#container {
src/components/map/SceneMap.vue
@@ -1,12 +1,42 @@
<template>
  <div style="width: 70vw; height: 500px; background-color: aliceblue">
    <BaseMap></BaseMap>
  </div>
  <BaseMap></BaseMap>
</template>
<script setup>
import { watch } from 'vue';
import { map, onMapMounted } from '@/utils/map/index';
import marks from '@/utils/map/marks';
import { sceneIcon } from '@/assets/scene-icon';
const props = defineProps({
  // åœºæ™¯ç‚¹ä½ä¿¡æ¯
  data: Array
});
var markViewList = [];
watch(
  () => props.data,
  (nV, oV) => {
    if (nV != oV) {
      drawSceneMarks();
    }
  },
  { immediate: true }
);
function drawSceneMarks() {
  onMapMounted(() => {
    markViewList = [];
    props.data.forEach((d) => {
      const mark = marks.createMarker({
        position: [d.longitude, d.latitude],
        icon: sceneIcon(d.typeid),
        label: d.name,
        extData: d.guid
      });
      markViewList.push(mark);
    });
    map.setFitView(markViewList);
  });
}
</script>
<style scoped></style>
src/utils/map/index.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,114 @@
import AMapLoader from '@amap/amap-jsapi-loader';
var mapInitDone = false;
var onMapMountedEvents = [];
var AMap;
// åœ°å›¾å¯¹è±¡
var map;
// å«æ˜Ÿå›¾å±‚
var satellite;
// é¼ æ ‡ç»˜å›¾
var mouseTool;
// 3D图层
var object3Dlayer;
// åœ°å›¾æ‹–动状态
var isDragging = false;
// åœ°å›¾åŠ è½½å®Œæˆè§¦å‘
function onMapMounted(...events) {
  if (mapInitDone) {
    events.forEach((e) => {
      e();
    });
  } else {
    onMapMountedEvents = onMapMountedEvents.concat(events);
  }
}
function createMap(id) {
  AMapLoader.load({
    key: '520c5e5cf44c7793104e500cbf0ed711', // ç”³è¯·å¥½çš„Web端开发者Key,首次调用 load æ—¶å¿…å¡«
    version: '2.0', // æŒ‡å®šè¦åŠ è½½çš„ JS API çš„版本,缺省时默认为 1.4.15
    // éœ€è¦ä½¿ç”¨çš„的插件列表,如比例尺'AMap.Scale'等
    plugins: [
      'AMap.ElasticMarker',
      'AMap.ControlBar',
      'AMap.ToolBar',
      'AMap.Scale',
      // 'AMap.DragRoute',
      // 'AMap.MouseTool',
      // 'AMap.PolygonEditor'
    ]
  })
    .then((_AMap) => {
      AMap = _AMap;
      _initMap(id);
      mapInitDone = true;
      onMapMountedEvents.forEach((e) => {
        e();
      });
      onMapMountedEvents = [];
    })
    .catch((e) => {
      console.log(e);
    });
}
function _initMap(elementId) {
  map = new AMap.Map(elementId, {
    // mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a',
    features: ['bg', 'road'],
    pitch: 45, // åœ°å›¾ä¿¯ä»°è§’度,有效范围 0 åº¦- 83 åº¦
    viewMode: '2D', // åœ°å›¾æ¨¡å¼
    resizeEnable: true,
    center: [121.6039283, 31.25295567],
    zooms: [2, 26],
    zoom: 14
  });
  // map = new AMap.Map(elementId);
  // æ·»åŠ å«æ˜Ÿåœ°å›¾
  satellite = new AMap.TileLayer.Satellite();
  satellite.hide();
  map.add([satellite]);
  // _initMouseTool();
  // _init3DLayer();
  // _initDragEvent();
}
// é¼ æ ‡ç»˜å›¾åˆå§‹åŒ–
function _initMouseTool() {
  mouseTool = new AMap.MouseTool(map);
}
// 3D图层初始化
function _init3DLayer() {
  object3Dlayer = new AMap.Object3DLayer();
  map.add(object3Dlayer);
}
// è®¾ç½®åœ°å›¾æ‹–拽监听事件
function _initDragEvent() {
  let dragEndEvent;
  map.on('dragstart', () => {
    clearTimeout(dragEndEvent);
    isDragging = true;
  });
  map.on('dragend', function () {
    dragEndEvent = setTimeout(() => {
      isDragging = false;
    }, 8000);
  });
}
export {
  createMap,
  onMapMounted,
  map,
  AMap,
  mouseTool,
  object3Dlayer,
  isDragging
};
src/utils/map/marks.js
@@ -2,7 +2,7 @@
 * é«˜å¾·åœ°å›¾ç‚¹æ ‡è®°ç»˜åˆ¶ç›¸å…³
 */
import { map } from './index_old';
import { map, AMap } from './index';
import { useToolboxStore } from '@/stores/toolbox';
const toolboxStore = useToolboxStore();
@@ -25,7 +25,7 @@
    for (let i = 0; i < lnglats.length; i++) {
      data.push({
        lnglat: lnglats[i], //点标记位置
        name: `${fDatas.times[i]}<br/>${_factor.factorName}: ${_factor.datas[i].factorData} mg/m³`,
        name: `${fDatas.times[i]}<br/>${_factor.factorName}: ${_factor.datas[i].factorData} Î¼g/m³`,
        id: i
      });
    }
@@ -34,12 +34,12 @@
    var styleObject = {
      url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png',
      // url: './asset/mipmap/ic_up_white.png', // å›¾æ ‡åœ°å€
      // eslint-disable-next-line no-undef
      size: new AMap.Size(11, 11), // å›¾æ ‡å¤§å°
      // eslint-disable-next-line no-undef
      anchor: new AMap.Pixel(5, 5) // å›¾æ ‡æ˜¾ç¤ºä½ç½®åç§»é‡ï¼ŒåŸºå‡†ç‚¹ä¸ºå›¾æ ‡å·¦ä¸Šè§’
    };
    // eslint-disable-next-line no-undef
    var massMarks = new AMap.MassMarks(data, {
      zIndex: 5, // æµ·é‡ç‚¹å›¾å±‚叠加的顺序
      zooms: [15, 18], // åœ¨æŒ‡å®šåœ°å›¾ç¼©æ”¾çº§åˆ«èŒƒå›´å†…展示海量点图层
@@ -50,11 +50,11 @@
      // 3. è‡ªå®šä¹‰ç‚¹å‡»äº‹ä»¶
      onClick(i);
    });
    // eslint-disable-next-line no-undef
    var marker = new AMap.Marker({
      content: ' ',
      map: map,
      // eslint-disable-next-line no-undef
      offset: new AMap.Pixel(13, 12)
    });
    var timeout;
@@ -86,8 +86,7 @@
   * @param {boolean} collision æ ‡æ³¨é¿è®©
   * @returns
   */
  createLabelMarks(img, dataList, collision = true) {
    // eslint-disable-next-line no-undef
  createLabelMarks(img, dataList, collision = true, showTxt = true) {
    const layer = new AMap.LabelsLayer({
      zooms: [3, 20],
      zIndex: 1000,
@@ -119,7 +118,7 @@
          retina: true
        },
        text: {
          content: data.name,
          content: showTxt ? data.name : '',
          direction: 'top',
          offset: [0, -5],
          style: {
@@ -136,7 +135,6 @@
        index: i
      };
      // eslint-disable-next-line no-undef
      var labelMarker = new AMap.LabelMarker(curData);
      // markers.push(labelMarker);
@@ -145,5 +143,21 @@
    }
    return layer;
  },
  createMarker({ position, icon, label, extData }) {
    const marker = new AMap.Marker({
      position: position,
      offset: new AMap.Pixel(-10, -10),
      icon: icon, //添加 icon å›¾æ ‡ URL
      title: label,
      label: {
        content: label,
        direction: 'bottom'
      },
      extData
    });
    map.add(marker);
    return marker;
  }
};
src/views/fysp/task/MonitorObjEdit.vue
@@ -1,5 +1,5 @@
<template>
  <el-affix :offset="60" target=".el-main">
  <!-- <el-affix :offset="60" target=".el-main"> -->
    <div class="page-header">
      <el-page-header @back="goBack">
        <template #content>
@@ -19,7 +19,7 @@
      </el-page-header>
      <el-divider />
    </div>
  </el-affix>
  <!-- </el-affix> -->
  <CompMonitorObjEdit
    ref="objEditRef"
    :task="task"
src/views/fysp/task/TaskManage.vue
@@ -43,6 +43,7 @@
                  <CompMonitorPlan
                    ref="planRef"
                    :task="curTask.data"
                    :day-task-list="dayTaskList"
                    @date-change="onDateChange"
                  ></CompMonitorPlan>
                </el-col>
@@ -51,7 +52,7 @@
                    create
                    v-model="curSubTaskList"
                    :loading="subTaskLoading"
                    :create-loading="daytaskLoading"
                    :create-loading="daytaskCreateLoading"
                    height="56vh"
                    @add="handleAddSubtask"
                    @submit="handleSubtaskSubmit"
@@ -59,9 +60,9 @@
                </el-col>
              </el-row>
            </el-tab-pane>
            <!-- <el-tab-pane label="监管地图" name="second">
              <CompTaskMap></CompTaskMap>
            </el-tab-pane> -->
            <el-tab-pane label="监管地图" name="second">
              <CompTaskMap :plans="curMonitorObjList"></CompTaskMap>
            </el-tab-pane>
          </el-tabs>
        </el-row>
        <el-divider></el-divider>
@@ -167,6 +168,9 @@
      showMonitorObjList: [],
      //当前选中的任务
      curTask: {},
      //当前选中的日任务
      curDayTaskList: [],
      daytaskLoading: false,
      //操作按钮
      buttons: [
        {
@@ -186,7 +190,7 @@
      // å½“前选择的日任务
      curDayTask: {},
      curDay: undefined,
      daytaskLoading: false,
      daytaskCreateLoading: false,
      // å½“前选择的日任务下的子任务
      curSubTaskList: undefined,
      subTaskLoading: false,
@@ -270,7 +274,18 @@
        })
        .finally(() => {
          this.mainLoading = false;
          this.fetchDayTasks();
        });
    },
    fetchDayTasks() {
      // èŽ·å–æ—¥ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
      this.dayTaskLoading = true;
      return taskApi
        .fetchDayTasks(this.curTask.data.tguid)
        .then((res) => {
          this.dayTaskList = res;
        })
        .finally(() => (this.dayTaskLoading = false));
    },
    editTask() {
      this.$router.push({
@@ -340,7 +355,7 @@
        _dayTask.settime = dayjs().toDate();
        _dayTask.t1stverifytime = dayjs().toDate();
        _dayTask.runingstatus = '未执行';
        this.daytaskLoading = true;
        this.daytaskCreateLoading = true;
        taskApi
          .putTask(_dayTask)
          .then((res) => {
@@ -356,7 +371,7 @@
            this.subTaskDrawer = true;
            this.handleSubtaskSubmit();
          })
          .finally(() => (this.daytaskLoading = false));
          .finally(() => (this.daytaskCreateLoading = false));
      }
    }
  },
src/views/fysp/task/components/CompMonitorObj.vue
@@ -1,21 +1,45 @@
<template>
  <div class="monitor-obj-wrapper">
    <el-affix v-if="affix" :offset="60" target=".monitor-obj-wrapper">
      <div>
        <el-segmented
      <el-scrollbar class="p-b-8" always>
        <!-- <el-segmented
          :model-value="activeName"
          :options="activeTabs"
          @change="tabChange"
        />
      </div>
        /> -->
        <el-tabs v-model="activeName" @tab-change="tabChange">
          <el-tab-pane
            v-for="item in activeTabs"
            :key="item"
            :label="item"
            :name="item"
          ></el-tab-pane>
        </el-tabs>
      </el-scrollbar>
    </el-affix>
    <div v-else>
      <el-segmented
    <el-scrollbar class="" always v-else>
      <!-- <el-segmented
        :model-value="activeName"
        :options="activeTabs"
        @change="tabChange"
      />
    </div>
      /> -->
      <el-tabs v-model="activeName" @tab-change="tabChange">
        <el-tab-pane
          v-for="item in activeTabs"
          :key="item"
          :label="item"
          :name="item"
        ></el-tab-pane>
      </el-tabs>
    </el-scrollbar>
    <el-space size="large">
      <el-tag type="info"> æ€»æ•°ï¼š{{ activeData.length }} </el-tag>
      <el-checkbox-group v-model="checkList">
        <el-checkbox label="未监管" :value="0" />
        <el-checkbox label="已监管" :value="1" />
        <el-checkbox label="已复核" :value="2" />
      </el-checkbox-group>
    </el-space>
    <el-scrollbar :height="height">
      <el-space wrap>
        <ItemMonitorObj v-for="obj in activeData" :key="obj.movid" :item="obj">
@@ -60,7 +84,7 @@
    },
    btnType: {
      type: String,
      default: 'danger'
      default: 'default'
    },
    // å¤´éƒ¨é€‰é¡¹æ˜¯å¦å¸é¡¶
    affix: Boolean,
@@ -70,16 +94,34 @@
  data() {
    return {
      activeName: defaultTabName,
      tabs: []
      tabs: [],
      checkList: [0, 1, 2]
    };
  },
  computed: {
    activeData() {
      const list = this.data.filter((v) => {
        return (
          this.activeName == defaultTabName || v.sceneType == this.activeName
        );
        // return this.tabName == defaultTabName || v.sceneType == this.tabName;
        // ç­›é€‰å½“前选择的标签页对应的场景类型
        const b1 =
          this.activeName == defaultTabName || v.sceneType == this.activeName;
        // è®¡ç®—场景的监管状态
        let status;
        if (v.extension1 == undefined || null) {
          // æœªç›‘管
          status = 0;
        } else {
          const num = parseInt(v.extension1);
          if (num >= 2) {
            // å·²å¤æ ¸
            status = 2;
          } else {
            // å·²ç›‘管(1次)
            status = num;
          }
        }
        const b2 = this.checkList.indexOf(status) != -1;
        return b1 && b2;
      });
      this.$emit('update:showData', list);
      return list;
src/views/fysp/task/components/CompMonitorObjEdit.vue
@@ -10,7 +10,7 @@
      </div>
      <el-divider />
      <CompMonitorObj
        height="68vh"
        height="62vh"
        :data="curMonitorObjList"
        show-btn
        v-model:tabName="curSceneType"
@@ -21,14 +21,22 @@
      </CompMonitorObj>
    </el-col>
    <el-col :span="8">
      <el-affix :offset="140">
      <!-- <el-affix :offset="140"> -->
        <div>
          <el-text>可选场景</el-text>
        </div>
        <el-divider />
        <div>
          <el-segmented v-model="curSceneType" :options="sceneTypeOptions" />
        </div>
        <el-scrollbar class="scrollbar-flex-content" always >
          <!-- <el-segmented v-model="curSceneType" :options="sceneTypeOptions" /> -->
          <el-tabs v-model="curSceneType">
            <el-tab-pane
              v-for="item in sceneTypeOptions"
              :key="item"
              :label="item"
              :name="item"
            ></el-tab-pane>
          </el-tabs>
        </el-scrollbar>
        <FYInfoSearch
          placeholder="请输入场景名称关键字"
          :data="showSceneList"
@@ -56,7 +64,7 @@
            </ItemScene>
          </template>
        </FYInfoSearch>
      </el-affix>
      <!-- </el-affix> -->
    </el-col>
  </el-row>
@@ -245,7 +253,7 @@
      const total = this.curMonitorObjList.length;
      const map = new Map();
      this.curMonitorObjList.forEach((e) => {
        const d = e.scene
        const d = e.scene;
        if (!map.has(d.type)) {
          map.set(d.type, { num: 0 });
        }
@@ -274,7 +282,13 @@
      });
    },
    deleteMov(item) {
      if (!(item.extension1 == null || item.extension1 == undefined || item.extension1 == '0')) {
      if (
        !(
          item.extension1 == null ||
          item.extension1 == undefined ||
          item.extension1 == '0'
        )
      ) {
        ElMessage({
          message: '已监管场景无法移除',
          type: 'error'
@@ -448,4 +462,10 @@
};
</script>
<style scoped></style>
<style scoped>
.scrollbar-flex-content {
  display: flex;
  /* width: fit-content; */
  height: min-content;
}
</style>
src/views/fysp/task/components/CompMonitorPlan.vue
@@ -1,6 +1,5 @@
<template>
  <el-calendar
    v-loading="dayTaskLoading"
    v-model="dateValue"
    :range="dateRange"
    @update:model-value="onDateChange"
@@ -53,6 +52,10 @@
  task: {
    type: Object,
    default: () => {}
  },
  dayTaskList: {
    type: Array,
    default: () => []
  }
});
const emit = defineEmits(['dateChange']);
@@ -98,22 +101,32 @@
/********************** ä»»åŠ¡æ•°æ® *********************************/
// èŽ·å–æ—¥ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
const dayTaskLoading = ref(false);
const dayTaskList = ref([]);
function fetchDayTasks() {
  dayTaskLoading.value = true;
  return taskApi
    .fetchDayTasks(props.task.tguid)
    .then((res) => {
      dayTaskList.value = res;
      // å¦‚果已选日期存在,在重新获取日任务统计信息后,再次触发点击事件
      if (dateValue.value) {
        onDateChange(dateValue.value)
      }
    })
    .finally(() => (dayTaskLoading.value = false));
}
watch(
  () => props.dayTaskList,
  (nV, oV) => {
    if (nV != oV && dateValue.value) {
      onDateChange(dateValue.value);
    }
  },
  { immediate: false }
);
// // èŽ·å–æ—¥ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
// const dayTaskLoading = ref(false);
// const dayTaskList = ref([]);
// function fetchDayTasks() {
//   dayTaskLoading.value = true;
//   return taskApi
//     .fetchDayTasks(props.task.tguid)
//     .then((res) => {
//       dayTaskList.value = res;
//       // å¦‚果已选日期存在,在重新获取日任务统计信息后,再次触发点击事件
//       if (dateValue.value) {
//         onDateChange(dateValue.value);
//       }
//     })
//     .finally(() => (dayTaskLoading.value = false));
// }
// æ—¥ä»»åŠ¡æ•°æ®å±•ç¤º
const compMap = new Map();
@@ -123,7 +136,7 @@
    return compMap.get(key).value;
  }
  const result = computed(() => {
    return dayTaskList.value.find((v) => {
    return props.dayTaskList.find((v) => {
      return dayjs(v.date).isSame(dayjs(day));
    });
  });
@@ -142,7 +155,7 @@
// æ€»ä»»åŠ¡ç»Ÿè®¡
const taskStatistic = computed(() => {
  const res = { total: 0, complete: 0, changed: 0 };
  dayTaskList.value.forEach((e) => {
  props.dayTaskList.forEach((e) => {
    res.total += e.totalTaskNum;
    res.complete += e.completeTaskNum;
    res.changed += e.changedTaskNum;
@@ -151,17 +164,17 @@
});
/********************** åˆå§‹åŒ– *********************************/
watch(
  () => props.task,
  (nV) => {
    if (nV && nV.tguid) {
      fetchDayTasks();
    }
  },
  { immediate: true }
);
// watch(
//   () => props.task,
//   (nV) => {
//     if (nV && nV.tguid) {
//       fetchDayTasks();
//     }
//   },
//   { immediate: true }
// );
defineExpose({ fetchDayTasks });
// defineExpose({ fetchDayTasks });
</script>
<style scoped>
.li-01 {
src/views/fysp/task/components/CompTaskMap.vue
@@ -1,8 +1,25 @@
<template>
  <SceneMap></SceneMap>
  <div style="width: 70vw; height: 600px; background-color: aliceblue">
    <SceneMap :data="scenes"></SceneMap>
  </div>
</template>
<script setup>
import { computed } from 'vue';
const props = defineProps({
  // åœºæ™¯è®¡åˆ’
  plans: {
    type: Array,
    default: () => []
  },
  dayTasks: {
    type: Array,
    default: () => []
  }
});
</script>
const scenes = computed(() => {
  return props.plans.map((p) => {
    return p.scene;
  });
});
</script>
vite.config.js
@@ -24,10 +24,10 @@
      resolvers: [
        ElementPlusResolver({
          importStyle: 'sass'
        }),
        })
      ],
      dts: 'src/components.d.ts',
    }),
      dts: 'src/components.d.ts'
    })
    // ElementPlus({
    //   useSource: true,
    // }),
@@ -42,8 +42,8 @@
    alias: [
      { find: /^@\//, replacement: `${pathSrc}/` },
      { find: /^~/, replacement: `` },
    ],
      { find: /^~/, replacement: `` }
    ]
    // extensions: ['.js', '.mjs', '.vue', '.json', '.less', '.css']
  },
  build: {
@@ -52,14 +52,14 @@
      input: path.resolve(__dirname, 'index.html'),
      output: {
        chunkFileNames: 'js/[name].[hash].js',
        entryFileNames: 'js/[name].[hash].js',
        entryFileNames: 'js/[name].[hash].js'
        // assetFileNames: "assets/[name].[hash].[ext]",
      },
    },
      }
    }
  },
  css: {
    postcss: {
      plugins: [autoprefixer],
      plugins: [autoprefixer]
    },
    preprocessorOptions: {
      // less: {
@@ -67,11 +67,12 @@
      //   additionalData: `@import "${path.resolve(__dirname, 'src/styles/variable.less')}";`
      // },
      scss: {
        additionalData: `@use "@/styles/element/index.scss" as *;`,
      },
    },
        additionalData: `@use "@/styles/element/index.scss" as *;`
      }
    }
  },
  server: {
    host: '0.0.0.0'
    host: '0.0.0.0',
    // port: 5174
  }
});