1.升级了element-plus版本
2.对外支持模块新设备匹配工地功能完成
3.新增设备匹配模块单挑匹配记录编辑功能(未完成)
已修改19个文件
已删除1个文件
已添加8个文件
已重命名1个文件
1151 ■■■■ 文件已修改
package-lock.json 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/userApi.js 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SearchBar.vue 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/core/SiderMenu.vue 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemScene.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/list-item/ItemUser.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/search-option/CompQuickSet.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/search-option/FYOptionScene.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/search-option/FYSearchBar.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/table/FYList.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/table/FYTable.vue 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/dialog.js 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/event.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/pagination.js 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/enum/scene.js 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/config/DeviceMatch.vue 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/config/device/CompDeviceMatchEdit.vue 202 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/config/device/CompInfoSearch.vue 131 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/EvalutationRecord.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/CompReport.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckArea.vue 65 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/support/NewDevice.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/support/components/DeviceMatch.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/support/components/ItemScene.vue 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -13,7 +13,7 @@
        "@vueuse/core": "^9.7.0",
        "axios": "^1.2.1",
        "dayjs": "^1.11.10",
        "element-plus": "^2.4.3",
        "element-plus": "^2.8.3",
        "js-base64": "^3.7.5",
        "md5": "^2.3.0",
        "pinia": "^2.0.26",
@@ -3782,9 +3782,9 @@
      "license": "ISC"
    },
    "node_modules/element-plus": {
      "version": "2.4.3",
      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.4.3.tgz",
      "integrity": "sha512-b3q26j+lM4SBqiyzw8HybybGnP2pk4MWgrnzzzYW5qKQUgV6EG1Zg7nMCfgCVccI8tNvZoTiUHb2mFaiB9qT8w==",
      "version": "2.8.3",
      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.8.3.tgz",
      "integrity": "sha512-BXQOyDf0s7JHyNEV8iaO+iaOzTZPsBXVKMzMI967vLCodUBDLrtiY5vglAn1YEebQcUOEUMhGcttTpIvEkcBjQ==",
      "dependencies": {
        "@ctrl/tinycolor": "^3.4.1",
        "@element-plus/icons-vue": "^2.3.1",
@@ -10069,9 +10069,9 @@
      "dev": true
    },
    "element-plus": {
      "version": "2.4.3",
      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.4.3.tgz",
      "integrity": "sha512-b3q26j+lM4SBqiyzw8HybybGnP2pk4MWgrnzzzYW5qKQUgV6EG1Zg7nMCfgCVccI8tNvZoTiUHb2mFaiB9qT8w==",
      "version": "2.8.3",
      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.8.3.tgz",
      "integrity": "sha512-BXQOyDf0s7JHyNEV8iaO+iaOzTZPsBXVKMzMI967vLCodUBDLrtiY5vglAn1YEebQcUOEUMhGcttTpIvEkcBjQ==",
      "requires": {
        "@ctrl/tinycolor": "^3.4.1",
        "@element-plus/icons-vue": "^2.3.1",
package.json
@@ -18,7 +18,7 @@
    "@vueuse/core": "^9.7.0",
    "axios": "^1.2.1",
    "dayjs": "^1.11.10",
    "element-plus": "^2.4.3",
    "element-plus": "^2.8.3",
    "js-base64": "^3.7.5",
    "md5": "^2.3.0",
    "pinia": "^2.0.26",
src/api/fysp/userApi.js
@@ -27,5 +27,19 @@
   */
  autoCreateAccount(sId) {
    return $fysp.post(`userinfo/create?sceneId=${sId}`).then((res) => res.data);
  },
  /**
   * ç”¨æˆ·æ¨¡ç³Šæœç´¢
   * @param {object} area åŒºåŸŸèŒƒå›´æ¡ä»¶
   * @param {String} keyword æœç´¢å…³é”®å­—
   * @param {Number} userType ç”¨æˆ·ç±»åž‹ï¼Œé»˜è®¤3:企业
   * @returns
   */
  searchUser(area, keyword, page = 1, perPage = 20, userType = 3) {
    const param = `?keyword=${keyword}&userType=${userType}&page=${page}&per_page=${perPage}`
    return $fysp
      .post(`userinfo/search${param}`, area)
      .then((res) => res.data);
  }
};
src/api/index.js
@@ -11,9 +11,9 @@
let ip2_file = 'https://fyami.com.cn/';
if (debug) {
  ip1 = 'http://192.168.0.138:8082/';
  // ip1_file = 'http://47.100.191.150:9005/';
  ip2 = 'http://192.168.0.138:8080/';
  ip1 = 'http://192.168.0.138:9091/';
  // ip1_file = 'http://192.168.0.138:8080/';
  // ip2 = 'http://192.168.0.138:8080/';
  // ip2_file = 'https://fyami.com.cn/';
}
src/components.d.ts
@@ -9,6 +9,7 @@
  export interface GlobalComponents {
    BaseContentLayout: typeof import('./components/core/BaseContentLayout.vue')['default']
    BasePanelLayout: typeof import('./components/core/BasePanelLayout.vue')['default']
    CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default']
    Content: typeof import('./components/core/Content.vue')['default']
    ElAside: typeof import('element-plus/es')['ElAside']
    ElAvatar: typeof import('element-plus/es')['ElAvatar']
@@ -52,7 +53,6 @@
    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScorllbar: typeof import('element-plus/es')['ElScorllbar']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSelect: typeof import('element-plus/es')['ElSelect']
    ElSpace: typeof import('element-plus/es')['ElSpace']
@@ -76,6 +76,7 @@
    FYBgTaskDialog: typeof import('./components/bg-task/FYBgTaskDialog.vue')['default']
    FYBgTaskItem: typeof import('./components/bg-task/FYBgTaskItem.vue')['default']
    FYForm: typeof import('./components/form/FYForm.vue')['default']
    FYList: typeof import('./components/table/FYList.vue')['default']
    FYOptionLocation: typeof import('./components/search-option/FYOptionLocation.vue')['default']
    FYOptionOnlineStatus: typeof import('./components/search-option/FYOptionOnlineStatus.vue')['default']
    FYOptionScene: typeof import('./components/search-option/FYOptionScene.vue')['default']
@@ -87,6 +88,8 @@
    FYSearchBar: typeof import('./components/search-option/FYSearchBar.vue')['default']
    FYTable: typeof import('./components/table/FYTable.vue')['default']
    Header: typeof import('./components/core/Header.vue')['default']
    ItemScene: typeof import('./components/list-item/ItemScene.vue')['default']
    ItemUser: typeof import('./components/list-item/ItemUser.vue')['default']
    MenuItems: typeof import('./components/core/MenuItems.vue')['default']
    RouterLink: typeof import('vue-router')['RouterLink']
    RouterView: typeof import('vue-router')['RouterView']
src/components/SearchBar.vue
@@ -4,23 +4,18 @@
      <el-form :inline="true" :model="formSearch">
        <el-form-item label="总任务">
          <!-- <el-input v-model="formSearch.topTaskId" placeholder="总任务" /> -->
          <el-select v-model="formSearch.topTaskId" placeholder="总任务">
            <el-option
              v-for="s in topTasks"
              :key="s.value"
              :label="s.label"
              :value="s.value"
            />
          <el-select v-model="formSearch.topTaskId" placeholder="总任务" style="width: 260px">
            <el-option v-for="s in topTasks" :key="s.value" :label="s.label" :value="s.value" />
          </el-select>
        </el-form-item>
        <!-- <FYOptionScene
          :allOption="false"
          :type="2"
          v-model:value="formSearch.scenetype"
        ></FYOptionScene> -->
        <el-form-item label="场景类型">
          <el-select v-model="formSearch.sceneTypeId" placeholder="场景类型">
            <el-option
              v-for="s in sceneTypes"
              :key="s.value"
              :label="s.label"
              :value="s.value"
            />
          <el-select v-model="formSearch.sceneTypeId" placeholder="场景类型" style="width: 150px">
            <el-option v-for="s in sceneTypes" :key="s.value" :label="s.label" :value="s.value" />
          </el-select>
        </el-form-item>
        <el-form-item>
@@ -38,7 +33,7 @@
<script>
import taskApi from '@/api/fysp/taskApi';
import { enumScene } from "@/enum/scene";
import { enumScene } from '@/enum/scene';
export default {
  emits: ['onSubmit'],
@@ -48,8 +43,8 @@
      sceneTypes: enumScene(2, false),
      formSearch: {
        topTaskId: '',
        sceneTypeId: '',
      },
        sceneTypeId: ''
      }
    };
  },
  methods: {
@@ -63,7 +58,7 @@
            label: r.name,
            towncode: r.towncode,
            districtCode: r.districtcode,
            month: r.starttime.slice(0, 7),
            month: r.starttime.slice(0, 7)
          });
        });
        this.topTasks = list;
@@ -75,12 +70,12 @@
    onSubmit() {
      // console.log(this.formSearch.sceneTypeId)
      this.$emit('onSubmit', this.formSearch);
    },
    }
  },
  mounted() {
    this.formSearch.sceneTypeId = this.sceneTypes[0].value;
    this.getOptions();
  },
  }
};
</script>
src/components/core/SiderMenu.vue
@@ -27,15 +27,18 @@
    >
      <template #reference>
        <div class="fy-button-div" @click="popVisible = !popVisible">
          <div style="font-size: 12px; color: gray; margin-left: 24px; margin-bottom: 4px">
          <div
            v-show="!collapse"
            style="font-size: 12px; color: gray; margin-left: 24px; margin-bottom: 4px;"
          >
            å½“前系统
          </div>
          <el-row justify="space-between" align="middle">
          <el-row justify="space-between" align="middle" style="flex-wrap: nowrap;">
            <el-space>
              <el-icon :size="16"><Open /></el-icon>
              <span>{{ sysName }}</span>
              <span v-show="!collapse">{{ sysName }}</span>
            </el-space>
            <el-icon><ArrowRight /></el-icon>
            <el-icon v-show="!collapse"><ArrowRight /></el-icon>
          </el-row>
        </div>
      </template>
@@ -60,7 +63,7 @@
</template>
<script>
import { MENU_FYSP, MENU_FYTZ, MENU_FYPW } from '@/constants/index'
import { MENU_FYSP, MENU_FYTZ, MENU_FYPW } from '@/constants/index';
export default {
  name: 'CoreSiderMenu',
@@ -83,61 +86,61 @@
        { name: '飞羽环境', des: '' },
        { name: '排污抽运', des: '' }
      ]
    }
    };
  },
  computed: {
    homePage() {
      const paths = this.menuPath(this.menus[0])
      return paths[paths.length - 1].path
      const paths = this.menuPath(this.menus[0]);
      return paths[paths.length - 1].path;
    },
    sysName() {
      return this.sysNames[this.sysIndex].name
      return this.sysNames[this.sysIndex].name;
    },
    menus() {
      return [MENU_FYSP, MENU_FYTZ, MENU_FYPW][this.sysIndex]
      return [MENU_FYSP, MENU_FYTZ, MENU_FYPW][this.sysIndex];
    }
  },
  methods: {
    handleOpen() {},
    handleClose() {},
    choseSys(i) {
      this.sysIndex = i
      const paths = this.menuPath(this.menus[0])
      this.navPage(...paths)
      const p = paths[paths.length - 1].path
      this.$router.push(p)
      this.popVisible = false
      this.sysIndex = i;
      const paths = this.menuPath(this.menus[0]);
      this.navPage(...paths);
      const p = paths[paths.length - 1].path;
      this.$router.push(p);
      this.popVisible = false;
    },
    navPage(...item) {
      const titles = item.map((value) => {
        return value.name
      })
      this.$emit('navPage', titles)
        return value.name;
      });
      this.$emit('navPage', titles);
    },
    calMenuHeight() {
      const h1 = this.$refs.headerRef.$el.offsetHeight
      const h2 = this.$refs.header2Ref.$el.offsetHeight
      const h3 = this.$refs.subTitleRef.$el.offsetHeight
      return `calc(100vh - ${h1}px - ${h2}px - ${h3}px)`
      const h1 = this.$refs.headerRef.$el.offsetHeight;
      const h2 = this.$refs.header2Ref.$el.offsetHeight;
      const h3 = this.$refs.subTitleRef.$el.offsetHeight;
      return `calc(100vh - ${h1}px - ${h2}px - ${h3}px)`;
    },
    menuPath(m) {
      if (m.children) {
        const arr = this.menuPath(m.children)
        arr.shift(m)
        return arr
        const arr = this.menuPath(m.children);
        arr.shift(m);
        return arr;
      } else {
        return [m]
        return [m];
      }
    }
  },
  created() {
    this.$router.push(this.homePage)
    this.navPage(...this.menuPath(this.menus[0]))
    this.$router.push(this.homePage);
    this.navPage(...this.menuPath(this.menus[0]));
  },
  mounted() {
    this.menuHeight = this.calMenuHeight()
    this.menuHeight = this.calMenuHeight();
  }
}
};
</script>
<style scoped>
@@ -181,4 +184,8 @@
.el-menu--collapse {
  min-height: 100vh;
}
.fy-button-div {
  white-space: nowrap;
}
</style>
src/components/list-item/ItemScene.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
<template>
  <!-- <el-card shadow="hover"> -->
  <div class="wrapper">
    <div>
      <el-text>{{ item.index }}、</el-text>
      <el-text>{{ item.name }}</el-text>
    </div>
    <!-- <div>
      <el-text>地址:{{ item.location }}</el-text>
    </div> -->
    <el-row justify="space-between" style="margin-top: 4px">
      <el-space>
        <el-tag type="primary" effect="plain" size="small">
          {{ item.districtname }}
        </el-tag>
        <el-tag type="primary" effect="plain" size="small">
          {{ item.type }}
        </el-tag>
      </el-space>
      <el-button size="small" type="success" @click="add">添加</el-button>
    </el-row>
  </div>
  <!-- </el-card> -->
</template>
<script setup>
const props = defineProps({
  item: {
    type: Object,
    default: () => {}
  }
});
const emit = defineEmits(['add']);
function add() {
  emit('add', props.item);
}
</script>
<style scoped>
.wrapper {
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  padding: 4px 8px;
}
</style>
src/components/list-item/ItemUser.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
<template>
  <!-- <el-card shadow="hover"> -->
  <div class="wrapper">
    <div>
      <el-text>{{ item.realname }}</el-text>
      <el-divider direction="vertical" />
      <el-text>账号:{{ item.acountname }}</el-text>
    </div>
    <!-- <div>
      <el-text>地址:{{ item.location }}</el-text>
    </div> -->
    <el-row justify="space-between" style="margin-top: 4px">
      <el-space>
        <el-tag type="primary" effect="plain" size="small">
          {{ item.district }}
        </el-tag>
        <!-- <el-tag type="primary" effect="plain" size="small">
          {{ item.usertype }}
        </el-tag> -->
      </el-space>
      <el-button size="small" type="success" @click="add">添加</el-button>
    </el-row>
  </div>
  <!-- </el-card> -->
</template>
<script setup>
const props = defineProps({
  item: {
    type: Object,
    default: () => {}
  }
});
const emit = defineEmits(['add']);
function add() {
  emit('add', props.item);
}
</script>
<style scoped>
.wrapper {
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  padding: 4px 8px;
}
</style>
src/components/search-option/CompQuickSet.vue
ÎļþÃû´Ó src/views/fysp/evaluation/components/CompQuickSet.vue ÐÞ¸Ä
@@ -1,9 +1,14 @@
<template>
  <el-form-item label="快捷选择">
    <el-space>
    <el-button v-for="(v, i) in quickSetting" :key="i" type="primary" size="small" @click="quickSet(v)">{{
      v.name
    }}</el-button>
      <el-button
        v-for="(v, i) in quickSetting"
        :key="i"
        type="primary"
        size="small"
        @click="quickSet(v)"
        >{{ v.name }}</el-button
      >
    </el-space>
  </el-form-item>
</template>
@@ -22,10 +27,10 @@
              cCode: '3100',
              cName: '上海市',
              dCode: '310106',
              dName: '静安区',
              dName: '静安区'
            },
            scenetype: { label: '工地', value: '1' },
            sourceType: 2,
            sourceType: 2
          },
          {
            name: '徐汇餐饮',
@@ -38,7 +43,7 @@
              dName: '徐汇区'
            },
            scenetype: { label: '餐饮', value: '5' },
            sourceType: 2,
            sourceType: 2
          },
          {
            name: '金山工地',
@@ -51,7 +56,7 @@
              dName: '金山区'
            },
            scenetype: { label: '工地', value: '1' },
            sourceType: 2,
            sourceType: 2
          },
          {
            name: '金山码头',
@@ -64,7 +69,7 @@
              dName: '金山区'
            },
            scenetype: { label: '码头', value: '2' },
            sourceType: 2,
            sourceType: 2
          },
          {
            name: '金山搅拌站',
@@ -77,8 +82,8 @@
              dName: '金山区'
            },
            scenetype: { label: '搅拌站', value: '3' },
            sourceType: 2,
          },
            sourceType: 2
          }
          // {
          //   name: '徐汇汽修',
          //   locations: {
@@ -92,7 +97,7 @@
          //   scenetype: { label: '汽修', value: '7' },
          //   sourceType: 1,
          // }
        ]
        ];
      }
    }
  },
@@ -106,10 +111,10 @@
      // this.formSearch.locations = set.locations
      // this.formSearch.scenetype = set.scenetype
      this.$emit('quickSet', set)
      this.$emit('quickSet', set);
    }
  }
}
};
</script>
<style scoped>
.row {
src/components/search-option/FYOptionScene.vue
@@ -23,7 +23,7 @@
    },
    // 1:飞羽环境系统;2:飞羽监管系统;
    type: {
      type: Number,
      type: Number || String,
      default: 1
    },
    // è¿”回结果
src/components/search-option/FYSearchBar.vue
@@ -1,5 +1,5 @@
<template>
  <el-form :inline="true">
  <el-form :inline="true" :size="size">
    <slot name="options"></slot>
    <el-form-item>
      <el-button icon="Search" type="primary" :loading="loading" @click="search">{{ btnText }}</el-button>
@@ -11,6 +11,10 @@
<script>
export default {
  props: {
    size: {
      type: String,
      default: 'default'
    },
    btnText: {
      type: String,
      default: '查询'
src/components/table/FYList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
<template>
  <el-scrollbar>
    <!-- <div v-for="(item, index) in data" :key="index">
    </div> -->
    <slot></slot>
  </el-scrollbar>
  <el-pagination
    v-if="pageShow"
    ref="paginationRef"
    class="el-pagination"
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="pageSizes"
    :background="true"
    layout="total, sizes, prev, pager, next, jumper"
    :total="total"
  />
</template>
<script>
import { usePagination } from '@/composables/pagination';
export default {
  setup() {
    // åˆ†é¡µé€»è¾‘
    const { currentPage, pageSize, addPageEvent } = usePagination();
    return { currentPage, pageSize, addPageEvent };
  },
  props: {
    data: {
      type: Array,
      default: () => {
        return [];
      }
    },
    // æ˜¯å¦æ˜¾ç¤ºåˆ†é¡µ
    pageShow: {
      type: Boolean,
      default: true
    },
    // æ¯é¡µå¯é€‰æ•°é‡
    pageSizes: {
      type: Array,
      default: () => {
        return [10, 20, 50, 100];
      }
    },
    // æ€»æ•°æ®é‡
    total: {
      type: Number,
      default: 0
    }
  },
  emits: ['pageChange'],
  methods: {
    search() {
      this.$emit('pageChange', this.currentPage, this.pageSize);
    }
  },
  mounted() {
    this.addPageEvent(this.search);
  }
};
</script>
<style scoped>
.el-pagination {
  background-color: var(--el-color-white);
  padding-top: 20px;
  border-top: 1px solid rgba(0, 0, 0, 0.096);
  /* margin-top: 2px; */
}
</style>
src/components/table/FYTable.vue
@@ -9,18 +9,34 @@
      </template>
    </FYSearchBar>
  </el-row>
  <el-row ref="expandRef">
  <el-row ref="expandRef" justify="space-between">
    <el-col span="22">
    <slot name="options-expand"></slot>
    </el-col>
    <el-col span="2">
      <el-space :wrap="false">
        <el-text size="small">字体</el-text>
        <el-radio-group v-model="fontSize" size="small">
          <el-radio-button value="small">小</el-radio-button>
          <el-radio-button value="default">中</el-radio-button>
          <el-radio-button value="large">大</el-radio-button>
        </el-radio-group>
      </el-space>
    </el-col>
  </el-row>
  <div ref="expand2Ref">
    <slot name="options-expand2"></slot>
  </div>
  <el-table
    :data="tableData"
    v-loading="loading"
    table-layout="fixed"
    :row-class-name="tableRowClassName"
    :height="tableHeight"
    :size="fontSize"
    border
  >
    <slot name="table-column"></slot>
    <slot name="table-column" :size="fontSize"></slot>
  </el-table>
  <el-pagination
@@ -51,6 +67,11 @@
    pagination: {
      type: Boolean,
      default: true
    },
    // '' | 'small' | 'default' | 'large'
    size: {
      type: String,
      default: 'default'
    }
  },
  data() {
@@ -60,7 +81,8 @@
      total: 0,
      currentPage: 1,
      pageSize: 20,
      loading: false
      loading: false,
      fontSize: 'default'
    };
  },
  emits: ['search'],
@@ -73,6 +95,30 @@
    pageSize(nValue, oValue) {
      if (nValue != oValue) {
        this.onSearch();
      }
    },
    size: {
      handler(nValue, oValue) {
        if (nValue != oValue) {
          this.fontSize = nValue;
        }
      },
      immediate: true
    }
  },
  computed: {
    cTableHeight() {
      if (this.$refs.searchRef) {
        const h1 = this.$refs.searchRef.$el.offsetHeight;
        const h2 = this.$refs.paginationRef ? this.$refs.paginationRef.$el.offsetHeight : 0;
        const h3 = this.$refs.expandRef.$el.offsetHeight;
        const h4 = this.$refs.expand2Ref.offsetHeight;
        const h = h1 + h2 + h3 + h4;
        // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`;
        return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`;
      } else {
        return '500';
      }
    }
  },
@@ -101,7 +147,9 @@
      const h1 = this.$refs.searchRef.$el.offsetHeight;
      const h2 = this.$refs.paginationRef ? this.$refs.paginationRef.$el.offsetHeight : 0;
      const h3 = this.$refs.expandRef.$el.offsetHeight;
      const h = h1 + h2 + h3;
      const h4 = this.$refs.expand2Ref.offsetHeight;
      const h = h1 + h2 + h3 + h4;
      // return `calc(100vh - ${h1}px - ${h2}px - var(--el-main-padding) * 2 - var(--el-header-height))`;
      return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`;
    },
src/composables/dialog.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
import { ref, watch } from 'vue';
import { useMessageBoxTip, useMessageBox } from './messageBox';
// å„类弹出框开关逻辑
export function useDialog() {
  const show = ref(false);
  function confirmClick() {
    if (options.tip) {
      useMessageBoxTip({
        confirmMsg: options.confrim.msg,
        confirmTitle: options.confrim.title,
        onConfirm: async () => {
          const res = options.confrim.do();
          show.value = false;
          return res;
        }
      });
    } else {
      useMessageBox({
        confirmMsg: options.cancel.msg,
        confirmTitle: options.cancel.title,
        onConfirm: () => {
          const res = options.cancel.do();
          show.value = false;
          return res;
        }
      });
    }
  }
  function cancelClick() {
    show.value = false;
  }
  const options = {
    tip: false,
    cancel: {
      title: '取消',
      msg: '是否放弃已编辑的内容?',
      do: () => {}
    },
    confirm: {
      title: '提交',
      msg: '确认是否提交?',
      do: () => {}
    }
  };
  return { show, confirmClick, cancelClick, options };
}
src/composables/event.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
// å»¶è¿Ÿäº‹ä»¶ç®¡ç†
export function useEvent() {
  // äº‹ä»¶åˆ—表
  let eventList = [];
  // æ·»åŠ äº‹ä»¶
  function addEvent(event) {
    eventList.push(event);
  }
  // æ‰§è¡Œäº‹ä»¶
  function invokeEvent() {
    eventList.forEach((e) => {
      if (typeof e === 'function') {
        e();
      }
    });
  }
  // æ¸…空事件
  function clearEvent() {
    eventList = []
  }
  return { addEvent, invokeEvent, clearEvent };
}
src/composables/pagination.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
// åˆ†é¡µé€»è¾‘管理
import { ref, watch } from 'vue';
import { useEvent } from './event';
/**
 * åˆ†é¡µç›‘听逻辑
 * 1. ç›‘听页码和单页数据量变换
 * 2. å¯æ·»åŠ å“åº”è§¦å‘äº‹ä»¶
 */
export function usePagination() {
  const { invokeEvent, addEvent: addPageEvent } = useEvent();
  const currentPage = ref(1);
  const pageSize = ref(20);
  watch(currentPage, (nValue, oValue) => {
    if (nValue != oValue) {
      invokeEvent();
    }
  });
  watch(pageSize, (nValue, oValue) => {
    if (nValue != oValue) {
      invokeEvent();
    }
  });
  return { currentPage, pageSize, addPageEvent };
}
src/enum/scene.js
@@ -5,7 +5,7 @@
 */
function enumScene(type, allOption = true) {
  let l;
  switch (type) {
  switch (parseInt(type)) {
    case 1:
      l = _enumScene_1();
      break;
@@ -36,44 +36,44 @@
  return [
    {
      label: '全部',
      value: null,
      value: null
    },
    {
      label: '餐饮',
      value: '1',
      value: '1'
    },
    {
      label: '工地',
      value: '2',
      value: '2'
    },
    {
      label: '码头',
      value: '3',
      value: '3'
    },
    {
      label: '堆场',
      value: '4',
      value: '4'
    },
    {
      label: '搅拌站',
      value: '5',
      value: '5'
    },
    {
      label: '工业企业',
      value: '6',
      value: '6'
    },
    {
      label: '汽修',
      value: '7',
      value: '7'
    },
    {
      label: '实验室',
      value: '8',
      value: '8'
    },
    {
      label: '医疗机构',
      value: '9',
    },
      value: '9'
    }
  ];
}
@@ -82,45 +82,62 @@
  return [
    {
      label: '全部',
      value: null,
      value: null
    },
    {
      label: '工地',
      value: '1',
      value: '1'
    },
    {
      label: '码头',
      value: '2',
      value: '2'
    },
    {
      label: '搅拌站',
      value: '3',
      value: '3'
    },
    {
      label: '工业企业',
      value: '4',
      value: '4'
    },
    {
      label: '餐饮',
      value: '5',
      value: '5'
    },
    {
      label: '汽修',
      value: '6',
      value: '6'
    },
    {
      label: '道路扬尘监测点',
      value: '9',
      value: '9'
    },
    {
      label: '道路',
      value: '10',
      value: '10'
    },
    {
      label: '堆场',
      value: '14',
    },
      value: '14'
    }
  ];
}
export { enumScene, getSceneName };
/**
 * é£žç¾½ç›‘管系统 åœºæ™¯ç±»åž‹è½¬ é£žç¾½çŽ¯å¢ƒç³»ç»Ÿ
 * @param {*} sceneTypeId
 */
function svToTz(sceneTypeId) {
  const sv = _enumScene_2();
  const tz = _enumScene_1();
  const scType = sv.find((v) => {
    return v.value == sceneTypeId + '';
  });
  const tzType = tz.find((v) => {
    return v.label == scType.label;
  });
  return tzType ? tzType : scType;
}
export { enumScene, getSceneName, svToTz };
src/router/index.js
@@ -88,7 +88,7 @@
    name: 'fyspEvalutationTask',
    path: '/fysp/evaluation/evalutationTask',
    component: () => import('@/views/fysp/evaluation/EvalutationTask.vue'),
    meta: { keepAlive: true }
    meta: { keepAlive: false }
  },
  {
    //评估管理
src/views/fysp/config/DeviceMatch.vue
@@ -1,5 +1,5 @@
<template>
  <FYTable @search="onSearch" :pagination="true" ref="tableRef">
  <FYTable @search="onSearch" :pagination="false" ref="tableRef" size="small">
    <template #options>
      <!-- åŒºåŽ¿ -->
      <FYOptionLocation
@@ -24,11 +24,48 @@
      </el-form>
    </template>
    <!-- <template #options-expand2>
      <CompDeviceMatchEdit :area="area"></CompDeviceMatchEdit>
    </template> -->
    <template #table-column> 
      <el-table-column prop="sceneName" :show-overflow-tooltip="true" label="名称">
      <el-table-column fixed="left" type="index" label="#" width="40" index="1"></el-table-column>
      <el-table-column
        prop="deviceCode"
        :show-overflow-tooltip="true"
        label="监测设备编号"
        width="160"
      >
      </el-table-column>
      <el-table-column prop="deviceName" :show-overflow-tooltip="true" label="监测设备名称">
      </el-table-column>
      <el-table-column prop="svUserName" :show-overflow-tooltip="true" label="监管用户名称">
      </el-table-column>
      <el-table-column prop="tzUserName" :show-overflow-tooltip="true" label="守法自助用户名称">
      </el-table-column>
      <el-table-column
        prop="createTime"
        :show-overflow-tooltip="true"
        label="创建时间"
        :formatter="timeFormat"
      >
      </el-table-column>
      <el-table-column fixed="right" label="操作" width="100">
        <template #default="{ row }">
          <el-button type="primary" size="small" @click="itemEdit(row)">编辑</el-button>
        </template>
      </el-table-column>
    </template>
  </FYTable>
  <el-drawer
    v-model="drawerShow"
    title="设备匹配记录编辑"
    direction="btt"
    size="80%"
    destroy-on-close
  >
    <CompDeviceMatchEdit :data="selectedItem" :area="area"></CompDeviceMatchEdit>
  </el-drawer>
</template>
<script setup>
/**
@@ -37,10 +74,13 @@
import dayjs from 'dayjs';
import { ref, reactive, computed, getCurrentInstance } from 'vue';
import userMapApi from '@/api/fysp/userMapApi';
import CompQuickSet from '@/views/fysp/evaluation/components/CompQuickSet.vue';
import CompDeviceMatchEdit from '@/views/fysp/config/device/CompDeviceMatchEdit.vue';
// fixme 2024.9.26 åŽç»­å¯ä»¥ç”¨vueuse中的时间格式化方法来代替
const { $fm } = getCurrentInstance().appContext.config.globalProperties;
/******** åŒ¹é…è®°å½•查询 ********/
const tableRef = ref();
const formSearch = reactive({
  locations: {},
@@ -78,4 +118,21 @@
  // formSearch.sourceType = param.sourceType;
  tableRef.value.onSearch();
}
function timeFormat(row) {
  const time = row.createTime;
  if (time) {
    return $fm.formatYMDH(time);
  } else {
    return '';
  }
}
/******** åŒ¹é…è®°å½•编辑 ********/
const drawerShow = ref(false);
const selectedItem = ref(null);
function itemEdit(row) {
  selectedItem.value = row;
  drawerShow.value = true;
}
</script>
src/views/fysp/config/device/CompDeviceMatchEdit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,202 @@
<template>
  <el-row :gutter="20">
    <el-col :span="8">
      <CompInfoSearch
        v-model="device"
        label="设备"
        placeholder="输入设备MN码或名称"
        @search="searchDevice"
      >
        <template #selected="{ row }">
          <div>
            <el-text>编号:{{ row.deviceCode }}</el-text>
          </div>
          <div>
            <el-text>名称:{{ row.deviceName }}</el-text>
          </div>
        </template>
        <template #default="{ row, click }">
          <el-text>deviceInfo</el-text>
        </template>
      </CompInfoSearch>
    </el-col>
    <el-col :span="8">
      <CompInfoSearch
        v-model="svUser"
        label="监管用户"
        placeholder="输入用户名称"
        @search="searchSVUser"
      >
        <template #selected="{ row }">
          <div>
            <el-text>编号:{{ row.svUserId }}</el-text>
          </div>
          <div>
            <el-text>名称:{{ row.svUserName }}</el-text>
          </div>
        </template>
        <template #default="{ row, click }">
          <ItemUser :item="row" @add="selectSVUser(row, click)" />
        </template>
      </CompInfoSearch>
    </el-col>
    <el-col :span="8">
      <CompInfoSearch
        v-model="tzUser"
        label="环境用户"
        placeholder="输入用户名称"
        @search="searchTZUser"
      >
        <template #selected="{ row }">
          <div>
            <el-text>编号:{{ row.tzUserId }}</el-text>
          </div>
          <div>
            <el-text>名称:{{ row.tzUserName }}</el-text>
          </div>
        </template>
        <template #default="{ row, click }">
          <ItemUser :item="row" @add="selectTZUser(row, click)" />
        </template>
      </CompInfoSearch>
    </el-col>
  </el-row>
</template>
<script>
import { useCloned } from '@vueuse/core';
import CompInfoSearch from './CompInfoSearch.vue';
import tzUserApi from '@/api/fytz/userApi';
import svUserApi from '@/api/fysp/userApi';
import { svToTz } from '@/enum/scene';
export default {
  components: { CompInfoSearch },
  props: {
    // è®¾å¤‡è´¦æˆ·åŒ¹é…ä¿¡æ¯
    data: Object,
    // æ£€ç´¢èŒƒå›´ï¼ˆåŒ…含行政区划、场景类型)
    area: Object
  },
  data() {
    return {
      // ç›‘测设备
      device: {},
      // ç›‘管用户
      svUser: {},
      // çŽ¯å¢ƒç”¨æˆ·
      tzUser: {}
    };
  },
  watch: {
    data: {
      handler(nValue, oValue) {
        if (nValue != oValue) {
          this.device = {
            deviceCode: nValue.deviceCode,
            deviceName: nValue.deviceName
          };
          this.svUser = {
            svUserId: nValue.svUserId,
            svUserName: nValue.svUserName
          };
          this.tzUser = {
            tzUserId: nValue.tzUserId,
            tzUserName: nValue.tzUserName
          };
        }
      },
      immediate: true
    }
  },
  methods: {
    // æŸ¥è¯¢ç›‘测设备
    searchDevice() {},
    // æŸ¥è¯¢ç›‘管用户
    searchSVUser(param, callback) {
      const { text, page, pageSize } = param;
      const { cloned: area } = useCloned(this.area);
      area.value.sceneName = text;
      return svUserApi
        .searchUser(area.value, text, page, pageSize)
        .then((res) => {
          if (res.success) {
            const l = res.data.map((value) => {
              return {
                guid: value.guid,
                realname: value.realname,
                acountname: value.acountname,
                district: value.remark
              };
            });
            callback({
              data: l,
              total: res.head.totalCount
            });
          }
        })
        .finally(() => {
          callback();
        });
    },
    // æŸ¥è¯¢çŽ¯å¢ƒï¼ˆå®ˆæ³•è‡ªåŠ©å°ç¨‹åºï¼‰ç”¨æˆ·
    searchTZUser(param, callback) {
      const { text, page, pageSize } = param;
      const area = {};
      // è¡Œæ”¿åŒºåˆ’
      area.provinceCode = this.area.provincecode;
      area.provinceName = this.area.provincename;
      area.cityCode = this.area.citycode;
      area.cityName = this.area.cityname;
      area.districtCode = this.area.districtcode;
      area.districtName = this.area.districtname;
      area.townCode = this.area.towncode;
      area.townName = this.area.townname;
      // åœºæ™¯ç±»åž‹
      const tzSceneType = svToTz(this.area.scensetypeid)
      area.sceneTypes = [tzSceneType.value];
      // ä¸Šä¸‹çº¿çŠ¶æ€
      area.online = this.area.online;
      // å…³é”®å­—
      area.searchText = text;
      tzUserApi
        .fetchUser(page, pageSize, area)
        .then((res) => {
          if (res) {
            const l = res.data.map((value) => {
              return {
                guid: value.userInfo.guid,
                realname: value.userInfo.realname,
                acountname: value.userInfo.acountname,
                district: value.userInfo.extension1
              };
            });
            callback({
              data: l,
              total: res.head.totalCount
            });
          }
        })
        .finally(() => {
          callback();
        });
    },
    selectDevice() {},
    selectSVUser(row, click) {
      const p = {
        svUserId: row.guid,
        svUserName: row.realname
      };
      click(p);
    },
    selectTZUser(row, click) {
      const p = {
        tzUserId: row.guid,
        tzUserName: row.realname
      };
      click(p);
    }
  }
};
</script>
src/views/fysp/config/device/CompInfoSearch.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,131 @@
<template>
  <!-- <div v-if="modelValue"> -->
    <el-divider content-position="left">选择{{ label }}</el-divider>
    <div class="select-box">
      <div>
        <el-text size="small" type="info">当前选择</el-text>
      </div>
      <slot name="selected" :row="modelValue"></slot>
    </div>
  <!-- </div> -->
  <el-divider content-position="left">{{ label }}检索</el-divider>
  <FYSearchBar @search="search" :loading="loading">
    <template #options>
      <FYOptionText
        label=""
        :placeholder="placeholder"
        v-model:value="searchText"
        width="200px"
      ></FYOptionText>
    </template>
  </FYSearchBar>
  <div>
    <el-scrollbar v-if="dataList.length > 0" height="38vh" class="item-box">
      <el-space direction="vertical" alignment="start" fill>
        <div v-for="(item, index) in dataList" :key="index">
          <slot :row="item" :click="select"></slot>
        </div>
      </el-space>
    </el-scrollbar>
  </div>
  <el-pagination
    v-if="pageShow && dataList.length > 0"
    size="small"
    ref="paginationRef"
    class="el-pagination"
    v-model:current-page="currentPage"
    v-model:page-size="pageSize"
    :page-sizes="pageSizes"
    :background="true"
    layout="total, sizes, prev, pager, next"
    :total="total"
  />
</template>
<script>
import { usePagination } from '@/composables/pagination';
/**
 * ä¿¡æ¯æ£€ç´¢åŠé€‰æ‹©æ¡†
 */
export default {
  setup() {
    // åˆ†é¡µé€»è¾‘
    const { currentPage, pageSize, addPageEvent } = usePagination();
    return { currentPage, pageSize, addPageEvent };
  },
  props: {
    modelValue: Object,
    label: {
      type: String,
      default: '检索项'
    },
    placeholder: {
      type: String,
      default: '输入关键字检索'
    },
    // æ˜¯å¦æ˜¾ç¤ºåˆ†é¡µ
    pageShow: {
      type: Boolean,
      default: true
    },
    // æ¯é¡µå¯é€‰æ•°é‡
    pageSizes: {
      type: Array,
      default: () => {
        return [10, 20, 50, 100];
      }
    }
  },
  emits: ['search', 'update:modelValue'],
  data() {
    return {
      searchText: '',
      dataList: [],
      total: 0,
      loading: false
    };
  },
  watch: {},
  methods: {
    search() {
      this.loading = true;
      const param = {
        text: this.searchText,
        page: this.currentPage,
        pageSize: this.pageSize
      };
      this.$emit('search', param, (res) => {
        if (res) {
          this.dataList = res.data;
          this.total = res.total ? res.total : 0;
        }
        this.loading = false;
      });
    },
    select(e) {
      this.$emit('update:modelValue', e);
    }
  },
  mounted() {
    this.addPageEvent(this.search);
  }
};
</script>
<style scoped>
.select-box {
  border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  padding: 0 8px;
}
.item-box {
  /* border: 1px solid var(--el-border-color);
  border-radius: var(--el-border-radius-base);
  margin-top: 20px; */
}
.el-pagination {
  /* background-color: var(--el-color-white); */
  border-top: 1px solid rgba(0, 0, 0, 0.096);
  /* background-color: aliceblue; */
}
</style>
src/views/fysp/evaluation/EvalutationRecord.vue
@@ -88,12 +88,11 @@
import dayjs from 'dayjs';
import evaluateApi from '@/api/fysp/evaluateApi';
import { envCreditCode } from '@/constants/index';
import CompQuickSet from './components/CompQuickSet.vue';
import CompReport from './components/CompReport.vue';
export default {
  name: 'ResultManage',
  components: { CompQuickSet, CompReport },
  components: { CompReport },
  data() {
    return {
      formSearch: {
src/views/fysp/evaluation/components/CompReport.vue
@@ -6,7 +6,6 @@
    v-model="dialogVisible"
    title="规范性评估与分析报告生成"
    width="500"
    :before-close="handleClose"
  >
    <el-text tag="b" size="large">数据范围确认</el-text>
    <el-text tag="div">区域:{{ locationText }}</el-text>
src/views/fysp/evaluation/components/precheck/components/CompCheckArea.vue
@@ -8,6 +8,36 @@
      <FYForm ref="formRef" :rules="evaConditionRules" :showButtons="false" @submit="nextStep">
        <template #form-item="{ formObj }">
          <CompQuickSet @quick-set="setOptions"></CompQuickSet>
          <el-form-item label="主数据源" prop="sourceType">
            <el-radio-group
              v-model="formObj.sourceType"
              size="small"
              @change="sceneOptionSourceInit = true"
            >
              <el-radio-button :value="1">守法服务记录</el-radio-button>
              <el-radio-button :value="2">现场巡查记录</el-radio-button>
            </el-radio-group>
            <el-tooltip placement="bottom-start" effect="light">
              <template #content>
                <el-text tag="i" size="default" type="warning"
                  >该选项是用于决定评估主体对象的获取方式</el-text
                ><br />
                <el-text tag="b" size="small">守法服务记录:</el-text><br />
                <el-text size="small"
                  >表示在评估时,评估对象是从守法服务小程序系统中获取的当前可用的用户;<br />
                  ä¸€èˆ¬æƒ…况下,当评估对象没有进行现场巡查,只有守法服务相关记录时,采用此选项;</el-text
                ><br />
                <el-text tag="b" size="small">现场巡查记录:</el-text><br />
                <el-text size="small"
                  >表示在评估时,评估对象是从现场巡查监管系统中获取的总任务下的所有监管场景;<br />
                  ä¸€èˆ¬æƒ…况下,当评估对象有进行现场巡查,采用此选项; </el-text
                ><br />
              </template>
              <el-icon class="m-l-8 cursor-p" :size="16" color="var(--el-color-warning)"
                ><QuestionFilled
              /></el-icon>
            </el-tooltip>
          </el-form-item>
          <!-- åŒºåŽ¿ -->
          <FYOptionLocation
            :allOption="false"
@@ -31,39 +61,6 @@
            type="month"
            v-model:value="formObj.time"
          ></FYOptionTime>
          <el-form-item label="主数据源" prop="sourceType">
            <!-- <el-switch v-model="formObj.sourceType" @change="sceneOptionSourceInit = true" /> -->
            <el-radio-group
              v-model="formObj.sourceType"
              size="small"
              @change="sceneOptionSourceInit = true"
            >
              <el-radio-button label="1">守法服务记录</el-radio-button>
              <el-radio-button label="2">现场巡查记录</el-radio-button>
            </el-radio-group>
            <!-- <span class="m-l-16">{{ formObj.sourceType ? '守法服务记录' : '现场巡查记录' }}</span> -->
            <el-tooltip placement="bottom-start" effect="light">
              <template #content>
                <!-- <el-text tag="b" size="default">说明</el-text><br /> -->
                <el-text tag="i" size="default" type="warning"
                  >该选项是用于决定评估主体对象的获取方式</el-text
                ><br />
                <el-text tag="b" size="small">守法服务记录:</el-text><br />
                <el-text size="small"
                  >表示在评估时,评估对象是从守法服务小程序系统中获取的当前可用的用户;<br />
                  ä¸€èˆ¬æƒ…况下,当评估对象没有进行现场巡查,只有守法服务相关记录时,采用此选项;</el-text
                ><br />
                <el-text tag="b" size="small">现场巡查记录:</el-text><br />
                <el-text size="small"
                  >表示在评估时,评估对象是从现场巡查监管系统中获取的总任务下的所有监管场景;<br />
                  ä¸€èˆ¬æƒ…况下,当评估对象有进行现场巡查,采用此选项; </el-text
                ><br />
              </template>
              <el-icon class="m-l-8 cursor-p" :size="16" color="var(--el-color-warning)"
                ><QuestionFilled
              /></el-icon>
            </el-tooltip>
          </el-form-item>
        </template>
      </FYForm>
    </FormCol>
@@ -78,13 +75,11 @@
</template>
<script>
import CompQuickSet from '../../CompQuickSet.vue';
/**
 * è¯„估范围合规性检查
 */
export default {
  components: { CompQuickSet },
  props: {
    // æ­¥éª¤ä¸‹æ ‡
    modelValue: Number
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue
@@ -3,7 +3,6 @@
    <template #header>
      <div><el-text tag="b" size="large">数据源检查</el-text></div>
      <el-text size="small" type="info">检查评估所需数据源是否完整</el-text>
      <el-text size="small" type="info">检查评估所需数据源是否完整</el-text>
    </template>
    <FormCol>
      <template v-for="(v, i) in checkResults" :key="i">
@@ -91,10 +90,24 @@
    async fetch() {
      this.loading = true;
      setTimeout(async () => {
        const res = await _fetch();
        if (_fetch != undefined) {
          _fetch()
            .then((res) => {
        this.pass = res ? res.pass : undefined;
        this.des = res ? res.des : undefined;
            })
            .catch(() => {
              this.pass = false;
              this.des = '网络链接错误';
            })
            .finally(() => {
        this.loading = false;
            });
        } else {
          this.pass = undefined;
          this.des = undefined;
          this.loading = false;
        }
      }, 1000);
    }
  };
@@ -160,7 +173,7 @@
          });
        }),
        // åŒºåŸŸèŒƒå›´å†…的监测数据是否存在、数据时间跨度是否完整、数据的初步分析是否完成
        baseCheckItem('现场监测数据', '', () => {}),
        baseCheckItem('现场监测数据', ''),
        // åŒºåŸŸèŒƒå›´å†…的每个监管点位与监测仪器的匹配记录是否存在,缺失情况等
        baseCheckItem('监管点位与监测点匹配', '', () => {
          return userMapApi.fetchDeviceMap(this.areaInfo).then((res) => {
@@ -192,14 +205,12 @@
            return { pass, des };
          });
        }),
        // åŒºåŸŸèŒƒå›´å†…的信访投诉记录是否存在,可随时补充
        baseCheckItem('信访投诉', '', () => {
          // complaintApi.fetchComplaints();
        }),
        // åŒºåŸŸèŒƒå›´å†…的行政处罚记录是否存在,可随时补充
        baseCheckItem('行政处罚', '', () => {
        // åŒºåŸŸèŒƒå›´å†…的信访投诉记录是否存在,可随时补充
        baseCheckItem('信访投诉', ''),
          // complaintApi.fetchPunishment();
        })
        // åŒºåŸŸèŒƒå›´å†…的行政处罚记录是否存在,可随时补充
        baseCheckItem('行政处罚', '')
      ]
    };
  },
@@ -253,7 +264,7 @@
      //   online: true,
      //   sourceType: v.sourceType
      // };
      this.areaInfo = value
      this.areaInfo = value;
      this.checkResults.forEach((e) => {
        e.fetch();
src/views/fysp/support/NewDevice.vue
@@ -17,7 +17,7 @@
      </el-scrollbar>
    </el-col>
    <el-col :span="8">
      <DeviceMatch :device="selectedDevice" :scene="selectedScene"></DeviceMatch>
      <DeviceMatch :device="selectedDevice" :scene="selectedScene" @success="onUploadSuccess"></DeviceMatch>
    </el-col>
    <el-col :span="8">
      <el-text>监管工地</el-text>
@@ -48,7 +48,6 @@
import { useFetchData } from '@/composables/fetchData';
import ItemDevice from './components/ItemDevice.vue';
import ItemScene from './components/ItemScene.vue';
import DeviceMatch from './components/DeviceMatch.vue';
const { loading, fetchData } = useFetchData();
@@ -92,6 +91,17 @@
function addScene(item) {
  selectedScene.value = item;
}
/**
 * ä¸Šä¼ è®¾å¤‡å®Œæˆ
 */
function onUploadSuccess() {
  const i = deviceList.value.indexOf(selectedDevice.value)
  deviceList.value.splice(i, 1)
  selectedDevice.value = null
  selectedScene.value = null
}
</script>
<style scoped>
.device-scene-wrap {
src/views/fysp/support/components/DeviceMatch.vue
@@ -15,7 +15,9 @@
            >录入设备信息</el-button
          >
        </div>
        <el-button type="danger" :disabled="!enabled">上传匹配信息</el-button>
        <el-button type="danger" :disabled="!enabled" @click="uploadMatchScene"
          >上传匹配信息</el-button
        >
      </el-row>
      <div v-if="newDevice">
        <el-text>新增设备</el-text>
@@ -31,6 +33,9 @@
<script setup>
import { ref, computed, watch } from 'vue';
import deviceApi from '@/api/fysp/deviceApi';
import constructionApi from '@/api/additional-jingan/constructionApi';
import { useFetchData } from '@/composables/fetchData';
import { ElMessage } from 'element-plus';
import FormDevice from './FormDevice.vue';
@@ -38,6 +43,8 @@
  device: Object,
  scene: Object
});
const emit = defineEmits(['success']);
// æ–°å¢žè®¾å¤‡ä¿¡æ¯
const newDevice = ref();
@@ -52,7 +59,7 @@
  () => props.scene,
  (nV, oV) => {
    if (nV != oV) {
      fetchDeviceInfo();
      // fetchDeviceInfo();
    }
  }
);
@@ -74,4 +81,30 @@
    diRemoved: false
  };
}
const { loading, fetchData } = useFetchData();
/**
 * ä¸Šä¼ è®¾å¤‡å…³è”工地
 */
function uploadMatchScene() {
  const param = {
    name: props.scene.name,
    address: props.scene.location,
    street: props.scene.townname,
    lon: props.device.lon,
    lat: props.device.lat,
    sbCode: props.device.code,
    sbName: props.device.name
  };
  fetchData(() => {
    return constructionApi.uploadConstructionDevice(param).then((res) => {
      ElMessage({
        message: res.message,
        type: 'success'
      });
      emit('success');
    });
  });
}
</script>
src/views/fysp/support/components/ItemScene.vue
ÎļþÒÑɾ³ý