riku
2025-03-25 642d31285d7aff59415a5eb37f87a79f41d308a8
新增自动评估扬尘监测数据统计结果上传功能(待完成)
已修改4个文件
已添加2个文件
334 ■■■■ 文件已修改
src/api/fysp/monitordataApi.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/EvalutationRecord.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/CompDataResultEdit.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/CompPreCheck.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/monitordataApi.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
import { $fysp } from '../index';
/**
 * ç›‘测数据统计相关API
 */
export default {
  /**
   * ä¸Šä¼ æ‰¬å°˜ç›‘测数据月度统计结果
   * @param {Array} dataList æ‰¬å°˜ç›‘测数据统计结果数组
   * @returns {Promise}
   */
  uploadDustDataResult(dataList) {
    return $fysp
      .put(`monitor/data/result/construction/upload`, dataList)
      .then((res) => res.data);
  },
  /**
   * èŽ·å–æ‰¬å°˜ç›‘æµ‹æ•°æ®æœˆåº¦ç»Ÿè®¡ç»“æžœ
   * @param {Object} area æŸ¥è¯¢æ¡ä»¶è¡Œæ”¿åŒºåˆ’、时间、场景类型
   * @returns
   */
  fetchDustDataResult(area) {
    return $fysp
      .post(`monitor/data/result/construction/get`, area)
      .then((res) => res.data);
  }
};
src/api/index.js
@@ -1,7 +1,7 @@
import axios from 'axios';
import { ElMessage } from 'element-plus';
const debug = false;
const debug = true;
let ip1 = 'http://47.100.191.150:9005/';
let ip1_file = 'http://47.100.191.150:9005/';
src/views/fysp/evaluation/EvalutationRecord.vue
@@ -278,6 +278,12 @@
            if (typeof func === 'function') {
              func({ data: this.tableData });
            }
          } else {
            this.tableData = [];
            this.orginData = [];
            if (typeof func === 'function') {
              func({ data: this.tableData });
            }
          }
        });
      });
src/views/fysp/evaluation/components/CompDataResultEdit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,105 @@
<template>
  <el-row align="top">
    <el-upload
      ref="upload"
      class="upload-file"
      :limit="1"
      :on-change="handleChange"
      :on-exceed="handleExceed"
      :auto-upload="false"
    >
      <template #trigger>
        <el-button type="primary">上传监测数据统计结果</el-button>
      </template>
    </el-upload>
    <el-text>{{ loadTxt }}</el-text>
  </el-row>
  <el-table
    ref="tableRef"
    :data="data"
    v-loading="loading"
    table-layout="fixed"
    :stripe="true"
    size="small"
    height="60vh"
    border
  >
    <el-table-column
      :show-overflow-tooltip="true"
      prop="drSceneName"
      label="名称"
      width="300"
    />
    <el-table-column prop="drDeviceCode" label="设备号" width="130" />
    <el-table-column prop="drTime" label="时间" width="100">
      <template #default="{ row }">
        <span>{{ $fm.formatYMD(row.drTime) }}</span>
      </template>
    </el-table-column>
    <el-table-column prop="drExceedTimes" label="超标次数" />
    <el-table-column prop="drAvg" label="平均值" />
    <el-table-column prop="drMax" label="最大值" />
    <el-table-column prop="drMin" label="最小值" />
    <el-table-column prop="drOverAvgPer" label="超区均值百分比" />
    <el-table-column prop="drDataNum" label="数据量" />
    <el-table-column prop="drEffectiveRate" label="有效率" />
  </el-table>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue';
import { genFileId } from 'element-plus';
import monitordataApi from '@/api/fysp/monitordataApi';
import * as XLSX from 'xlsx';
const props = defineProps({
  areaInfo: { type: Object }
});
let workbook;
const data = ref([]);
const upload = ref();
const loadTxt = ref('');
// èŽ·å–åŽ†å²ç»Ÿè®¡ç»“æžœ
function fetchDustDataResult() {
  monitordataApi.fetchDustDataResult(props.areaInfo).then((res) => {
    data.value = res.data;
  });
}
function handleExceed(files, uploadFiles) {
  upload.value.clearFiles();
  const file = files[0];
  file.uid = genFileId();
  upload.value.handleStart(file);
}
function handleChange(uploadFile, uploadFiles) {
  // console.log(uploadFile, uploadFiles);
  const fileReader = new FileReader();
  fileReader.onload = (file) => {
    const data = file.target.result;
    workbook = XLSX.read(data, { type: 'array' });
    console.log(workbook.SheetNames);
  };
  fileReader.readAsArrayBuffer(uploadFile.raw);
}
// ä¸Šä¼ ç»Ÿè®¡ç»“果文档
function uploadFile() {}
onMounted(() => {
  fetchDustDataResult();
});
</script>
<style scoped>
.upload-file {
  /* background-color: aliceblue; */
  width: 300px;
  min-height: 60px;
}
:deep(.el-text) {
  align-self: auto;
}
</style>
src/views/fysp/evaluation/components/precheck/CompPreCheck.vue
@@ -72,6 +72,7 @@
        towncode: v._locations.tCode,
        townname: v._locations.tName,
        starttime: this.$fm.formatYMDH(v.time),
        endtime: this.$fm.formatYMDH(v.time),
        scensetypeid: v._scenetype.value,
        online: true,
        sourceType: v.sourceType
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue
@@ -1,68 +1,91 @@
<template>
  <el-card shadow="never">
    <template #header>
      <div><el-text tag="b" size="large">数据源检查</el-text></div>
      <el-text size="small" type="info">检查评估所需数据源是否完整</el-text>
    </template>
    <FormCol>
      <template v-for="(v, i) in checkResults" :key="i">
        <el-row class="h-small" align="middle">
          <el-col :span="14">
            <el-row align="middle">
              <el-text size="default" :class="v.required ? 'required' : 'not-required'">*</el-text>
              <el-text size="default" class="m-l-4">{{ v.name }}</el-text>
            </el-row>
          </el-col>
          <el-col :span="5">
            <el-row align="middle">
              <el-space>
                <template v-if="v.loading">
                  <el-icon class="is-loading"><Loading /></el-icon>
                  <el-text size="default" type="default">检查中...</el-text>
                </template>
                <template v-else-if="v.pass == true">
                  <el-icon color="var(--el-color-success)"><Check /></el-icon>
                  <el-text size="default" type="success">通过</el-text>
                </template>
                <template v-else-if="v.pass == false">
                  <el-icon color="var(--el-color-danger)"><Close /></el-icon>
                  <el-text size="default" type="danger">缺失</el-text>
                </template>
                <template v-else>
                  <el-icon color="var(--el-color-warning)"><Warning /></el-icon>
                  <el-text size="default" type="warning">暂略过</el-text>
                </template>
              </el-space>
            </el-row>
          </el-col>
          <el-col :span="5">
            <el-button
              v-show="!v.loading"
              :type="v.pass ? '' : 'danger'"
              size="small"
              @click="goto(v.path)"
              :disabled="v.path == ''"
            >
              {{ v.pass ? '去修改' : '去完善' }}
              <el-icon class="m-l-4"><Right /></el-icon>
            </el-button>
          </el-col>
        </el-row>
        <el-row align="middle" class="m-b-16">
          <el-text size="small" class="not-required">*</el-text>
          <el-text size="small" class="m-l-4 color-i">{{ v.des }}</el-text>
  <div>
    <el-card shadow="never">
      <template #header>
        <div><el-text tag="b" size="large">数据源检查</el-text></div>
        <el-text size="small" type="info">检查评估所需数据源是否完整</el-text>
      </template>
      <FormCol>
        <template v-for="(v, i) in checkResults" :key="i">
          <el-row class="h-small" align="middle">
            <el-col :span="14">
              <el-row align="middle">
                <el-text
                  size="default"
                  :class="v.required ? 'required' : 'not-required'"
                  >*</el-text
                >
                <el-text size="default" class="m-l-4">{{ v.name }}</el-text>
              </el-row>
            </el-col>
            <el-col :span="5">
              <el-row align="middle">
                <el-space>
                  <template v-if="v.loading">
                    <el-icon class="is-loading"><Loading /></el-icon>
                    <el-text size="default" type="default">检查中...</el-text>
                  </template>
                  <template v-else-if="v.pass == true">
                    <el-icon color="var(--el-color-success)"><Check /></el-icon>
                    <el-text size="default" type="success">通过</el-text>
                  </template>
                  <template v-else-if="v.pass == false">
                    <el-icon color="var(--el-color-danger)"><Close /></el-icon>
                    <el-text size="default" type="danger">缺失</el-text>
                  </template>
                  <template v-else>
                    <el-icon color="var(--el-color-warning)"
                      ><Warning
                    /></el-icon>
                    <el-text size="default" type="warning">暂略过</el-text>
                  </template>
                </el-space>
              </el-row>
            </el-col>
            <el-col :span="5">
              <el-button
                v-show="!v.loading"
                :type="v.pass ? '' : 'danger'"
                size="small"
                @click="goto(v.path)"
                :disabled="v.path == ''"
              >
                {{ v.pass ? '去修改' : '去完善' }}
                <el-icon class="m-l-4"><Right /></el-icon>
              </el-button>
            </el-col>
          </el-row>
          <el-row align="middle" class="m-b-16">
            <el-text size="small" class="not-required">*</el-text>
            <el-text size="small" class="m-l-4 color-i">{{ v.des }}</el-text>
          </el-row>
        </template>
      </FormCol>
      <template #footer>
        <el-row justify="space-around">
          <el-button type="primary" size="default" @click="lastStep"
            >上一步</el-button
          >
          <el-button
            :disabled="!checkPass"
            type="primary"
            size="default"
            @click="nextStep"
            >下一步</el-button
          >
        </el-row>
      </template>
    </FormCol>
    <template #footer>
      <el-row justify="space-around">
        <el-button type="primary" size="default" @click="lastStep">上一步</el-button>
        <el-button :disabled="!checkPass" type="primary" size="default" @click="nextStep"
          >下一步</el-button
        >
      </el-row>
    </template>
  </el-card>
    </el-card>
    <el-dialog
      title="扬尘监测数据月度统计管理"
      v-model="dialog1"
      destroy-on-close
      width="90%"
    >
      <CompDataResultEdit :areaInfo="areaInfo"></CompDataResultEdit>
      <template #footer> </template>
    </el-dialog>
  </div>
</template>
<script>
@@ -70,14 +93,16 @@
import taskApi from '@/api/fysp/taskApi';
import userMapApi from '@/api/fysp/userMapApi';
import problemApi from '@/api/fysp/problemApi';
import monitordataApi from '@/api/fysp/monitordataApi';
import complaintApi from '@/api/fytz/complaintApi';
import CompDataResultEdit from '../../CompDataResultEdit.vue';
/**
 * ç”Ÿæˆä¸€é¡¹æ•°æ®æºæ£€æŸ¥è®°å½•
 * @param {*} _name
 * @param {*} _path
 * @param {*} _fetch
 * @param {*} _required
 * ç”Ÿæˆä¸€é¡¹æ•°æ®æºæ£€æŸ¥æ¡ç›®
 * @param {*} _name æ¡ç›®åç§°
 * @param {*} _path è·³è½¬é¡µé¢URL
 * @param {*} _fetch æ¡ç›®çš„网络请求函数
 * @param {*} _required æ˜¯å¦å¿…选
 */
function baseCheckItem(_name, _path, _fetch, _required) {
  return {
@@ -90,7 +115,7 @@
    async fetch() {
      this.loading = true;
      setTimeout(async () => {
        if (_fetch != undefined) {
        if (typeof _fetch === 'function') {
          _fetch()
            .then((res) => {
              this.pass = res ? res.pass : undefined;
@@ -117,6 +142,9 @@
 * è¯„估数据源完整性检查
 */
export default {
  components: {
    CompDataResultEdit
  },
  props: {
    // æ­¥éª¤ä¸‹æ ‡
    modelValue: Number
@@ -173,7 +201,26 @@
          });
        }),
        // åŒºåŸŸèŒƒå›´å†…的监测数据是否存在、数据时间跨度是否完整、数据的初步分析是否完成
        baseCheckItem('现场监测数据', ''),
        baseCheckItem(
          '现场监测数据',
          () => {
            this.dialog1 = true;
          },
          () => {
            return monitordataApi
              .fetchDustDataResult(this.areaInfo)
              .then((res) => {
                const pass = res.data.length > 0;
                let des = '';
                if (pass) {
                  des = `找到月度统计共${res.data.length}条`;
                } else {
                  des = '未找到相关记录';
                }
                return { pass, des };
              });
          }
        ),
        // åŒºåŸŸèŒƒå›´å†…的每个监管点位与监测仪器的匹配记录是否存在,缺失情况等
        baseCheckItem('监管点位与监测点匹配', '', () => {
          return userMapApi.fetchDeviceMap(this.areaInfo).then((res) => {
@@ -211,7 +258,8 @@
        // complaintApi.fetchPunishment();
        // åŒºåŸŸèŒƒå›´å†…的行政处罚记录是否存在,可随时补充
        baseCheckItem('行政处罚', '')
      ]
      ],
      dialog1: false
    };
  },
  computed: {
@@ -243,8 +291,10 @@
    },
    // è·³è½¬æ£€æŸ¥é¡¹çš„链接
    goto(path) {
      if (path && path != '') {
      if (typeof path === 'string' && path != '') {
        this.$router.push(path);
      } else if (typeof path === 'function') {
        path();
      }
    },
    // å¼€å§‹æ£€æŸ¥ä»»åŠ¡