riku
2025-07-03 e895212fa4215c50ce79ce4b448e064caf394776
src/views/sourcetrace/SourceTrace.vue
@@ -18,17 +18,30 @@
    <el-col v-show="show" span="10">
      <BaseCard>
        <template #content>
          <el-checkbox-group v-model="selectedMsgTypes" size="default" :min="1">
            <el-space>
              <el-checkbox value="1">异常切片</el-checkbox>
              <el-checkbox value="2">污染线索</el-checkbox>
            </el-space>
          </el-checkbox-group>
          <el-row
            justify="space-between"
            align="middle"
            style="border-bottom: 1px solid white"
          >
            <!-- 数据切片筛选条件 -->
            <SourceTraceFilter
              v-model:data-slice="selectedMsgTypes"
              v-model:factor-type="selectedFactorTypes"
              :factor-options="factorOptions"
              v-model:scene-type="selectedSceneTypes"
              :scene-options="sceneOptions"
            ></SourceTraceFilter>
            <!-- <el-divider direction="vertical"></el-divider> -->
            <!-- 数据切片统计 -->
            <div style="border-left: 1px solid white" class="p-l-8">
              <el-space direction="vertical">
                <el-text type="primary">溯源:{{ countMsg1.type1 }}条</el-text>
                <el-text type="primary">线索:{{ countMsg1.type2 }}条</el-text>
                <el-text type="primary">提醒:{{ countMsg1.type3 }}条</el-text>
              </el-space>
            </div>
          </el-row>
          <el-scrollbar ref="scrollbarRef" class="scrollbar">
            <!-- <div
              ref="scrollContentRef"
              style="display: flex; width: fit-content"
            > -->
            <TransitionGroup name="list">
              <div
                v-for="item in filterStreams"
@@ -40,7 +53,6 @@
                ></ClueRecordItem>
              </div>
            </TransitionGroup>
            <!-- </div> -->
          </el-scrollbar>
        </template>
      </BaseCard>
@@ -72,6 +84,9 @@
import PollutedExceptionItem from './component/PollutedExceptionItem.vue';
import ClueRecordItem from './component/ClueRecordItem.vue';
import PollutedClueItem from '@/views/sourcetrace/component/PollutedClueItem.vue';
import SourceTraceFilter from '@/views/sourcetrace/component/SourceTraceFilter.vue';
const NO_SCENE = 'no_scene';
const props = defineProps({
  factorType: String
@@ -89,7 +104,11 @@
const selectedException = ref();
const selectedClue = ref();
const selectedMsgTypes = ref(['1', '2']);
const selectedMsgTypes = ref(['1', '2', '3']);
const selectedFactorTypes = ref([]);
const factorOptions = ref([]);
const selectedSceneTypes = ref([]);
const sceneOptions = ref([]);
function scrollToBottom() {
  const h1 = scrollContentRef.value.clientHeight + 100;
@@ -107,8 +126,57 @@
const streams = reactive([]);
const filterStreams = computed(() => {
  return streams.filter((v) => {
    return selectedMsgTypes.value.indexOf(v._type) != -1;
    // 判断消息类型是否选中
    const b1 = selectedMsgTypes.value.indexOf(v._type) != -1;
    let b2, b3;
    switch (v._type) {
      case '1':
      case '3':
        // 判断监测因子类型是否选中
        b2 = selectedFactorTypes.value.indexOf(v.pollutedData.factorId) != -1;
        // 判断场景类型是否选中
        if (v.pollutedSource.sceneList.length == 0) {
          b3 = selectedSceneTypes.value.indexOf(NO_SCENE) != -1;
        } else {
          b3 =
            v.pollutedSource.sceneList.findIndex(
              (v) => selectedSceneTypes.value.indexOf(v.typeId) != -1
            ) != -1;
        }
        break;
      case '2':
        b2 = true;
        b3 =
          v.sortedSceneList.findIndex(
            (v) => selectedSceneTypes.value.indexOf(v.first.typeId) != -1
          ) != -1;
        break;
    }
    return b1 && b2 && b3;
  });
});
// 统计各类型消息的数量
const countMsg1 = computed(() => {
  const count = {
    type1: 0,
    type2: 0,
    type3: 0
  };
  streams.forEach((v) => {
    switch (v._type) {
      case '1':
        count.type1++;
        break;
      case '2':
        count.type2++;
        break;
      case '3':
        count.type3++;
        break;
    }
  });
  return count;
});
const inputVal = ref('');
@@ -116,27 +184,16 @@
  websocket.send(inputVal.value);
};
let showFirstClueTask;
function dealMsg(data) {
  const { type, content } = websocketMsgParser.parseMsg(data);
  const obj = reactive(JSON.parse(content));
  obj._type = type;
  // 污染线索 PollutedClue
  if (type == '1') {
    const obj = reactive(JSON.parse(content));
    obj._type = type;
    // obj.showMore = true;
    obj.showMore = false;
    console.log('污染异常切片: ', obj);
    // if (streams.length == 0) {
    //   streams.push(obj);
    // } else {
    //   // streams.forEach((s) => {
    //   //   showMarksAndPolygon(s);
    //   // });
    //   // hideAll();
    //   streams.unshift(obj);
    // }
    addNewMsg(obj);
    show.value = true;
@@ -144,20 +201,61 @@
    // scrollToTop();
    // drawPolygon(obj.pollutedArea);
    parseChartData(obj);
    // if (showFirstClueTask) {
    //   clearTimeout(showFirstClueTask);
    // }
    // showFirstClueTask = setTimeout(() => {
    //   showMarksAndPolygon(obj);
    // }, 1000);
  } else if (type == '2') {
    const obj = JSON.parse(content);
    obj._type = type;
    // const obj = JSON.parse(content);
    // obj._type = type;
    console.log('污染线索结果: ', obj);
    obj._timestr = timeFormatter(obj.time);
    // streams.unshift(obj);
    addNewMsg(obj);
  } else if (type == '3') {
    console.log('污染提醒切片: ', obj);
    addNewMsg(obj);
    parseChartData(obj);
  }
  optionsFilte(obj);
}
// 对数据进行筛选,包括监测因子和场景类型
function optionsFilte(objData) {
  switch (objData._type) {
    case '1':
    case '3':
      // 筛选监测因子类型
      if (
        factorOptions.value.findIndex(
          (v) => v.value == objData.pollutedData.factorId
        ) == -1
      ) {
        factorOptions.value.push({
          label: objData.pollutedData.factorName,
          value: objData.pollutedData.factorId
        });
        selectedFactorTypes.value.push(objData.pollutedData.factorId);
      }
      // 筛选场景类型
      if (objData.pollutedSource.sceneList.length == 0) {
        // 若没有找到风险源时,将该分类设定为null
        if (sceneOptions.value.findIndex((v) => v.value == NO_SCENE) == -1) {
          sceneOptions.value.push({
            label: '无',
            value: NO_SCENE
          });
          selectedSceneTypes.value.push(NO_SCENE);
        }
      } else {
        objData.pollutedSource.sceneList.forEach((s) => {
          if (sceneOptions.value.findIndex((v) => v.value == s.typeId) == -1) {
            sceneOptions.value.push({
              label: s.type,
              value: s.typeId
            });
            selectedSceneTypes.value.push(s.typeId);
          }
        });
      }
    // case '2':
    //   break;
  }
}
@@ -202,6 +300,7 @@
function handleOpen(item) {
  switch (item._type) {
    case '1':
    case '3':
      if (selectedException.value) {
        selectedException.value._selected = false;
      }