83ac952bb66518e7ce190b08741fdef28edcfd4f..dc16b68e74c18b617c8f79d82fd3c3306badbcbe
2024-11-21 riku
修复场景报告中设备图片选择弹框错误问题
dc16b6 对比 | 目录
2024-11-21 riku
问题整改界面 1. 优化各项状态展示效果 2. 新增左侧关键字筛选功能
55bd7f 对比 | 目录
2024-11-21 riku
Merge remote-tracking branch 'supervisionVue/hc-procheck-1121' into lsf-dat...
6d5eb3 对比 | 目录
2024-11-21 riku
Merge remote-tracking branch 'supervisionVue/hc-dataproduct-v1112' into lsf...
c4bcc6 对比 | 目录
2024-11-21 riku
1. 修改审核后左侧列表状态和顶部统计数据的
9b2b08 对比 | 目录
2024-11-21 hcong
1. 审核撤回的按钮显示逻辑修改 2. 通过改为审核通过 3. 审核驳回隐藏
95ac43 对比 | 目录
2024-11-21 hcong
弹窗,抽屉关闭的操作放在统一包裹组件中
55d42c 对比 | 目录
2024-11-21 riku
Merge branch 'hc-dataproduct-v1112' into lsf-dataproduct-1024
af5a8d 对比 | 目录
2024-11-21 riku
Merge remote-tracking branch 'supervisionVue/hc-dataproduct-v1112' into lsf...
f37d45 对比 | 目录
2024-11-21 hcong
1. 图片选择组件移动到全局组件文件夹 2. 涉及到使用图片选择组件添加图片区域loading 3. 无用页面删除
87958d 对比 | 目录
2024-11-21 riku
1. 修改问题整改界面中左侧列表的状态图标
0bd8b4 对比 | 目录
2024-11-20 hcong
fixme 子组件初始化时机问题
0cac9e 对比 | 目录
2024-11-20 hcong
问题新增与修改页面初始化逻辑修改
d7932d 对比 | 目录
2024-11-20 hcong
1. 问题新增与修改页面表单中建议修正v-show去掉 2. 问题新增与修改页面初始化逻辑修改
ccbb66 对比 | 目录
2024-11-20 hcong
问题和整改的新增以及修改页面点击取消按钮添加取消事件
0e5f14 对比 | 目录
2024-11-20 riku
1. 修复场景信息内默认展示的工地信息样式
bf333d 对比 | 目录
2024-11-20 hcong
多写了一个emits选项
546d07 对比 | 目录
2024-11-20 hcong
子组件刷新父组件不刷新页面,表单验证,upload组件预览图片,弹窗放在组件内部,bug修复
f21388 对比 | 目录
已修改19个文件
已删除6个文件
已添加1个文件
3478 ■■■■■ 文件已修改
src/components.d.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/CompGenericWrapper.vue 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FYImageSelectDialog.vue 105 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/SideList.vue 227 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ToolBar.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/core/BaseContentLayout.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/ProCheck.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/ProCheckProxy.js 234 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/ArbitraryPhoto.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/ComChangeEdit.vue 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompDevicePhono.vue 262 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompDevicePhoto.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompDeviceShow.vue 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompDeviceShowTest.vue 317 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompLedgerPhoto.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompLedgerPic.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompProRecent.vue 128 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompProblemAddOrUpd.vue 704 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompProblemCard.vue 173 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompSubTaskStatistic.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/js/dataMonitorDeviceType.js 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/js/dataProductionDeviceType.js 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/js/dataTreatmentDeviceType.js 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/data-product/ProdSceneReport.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/scene/SceneEdit.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/task/TaskManage.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts
@@ -10,6 +10,7 @@
    BaseContentLayout: typeof import('./components/core/BaseContentLayout.vue')['default']
    BaseMap: typeof import('./components/map/BaseMap.vue')['default']
    BasePanelLayout: typeof import('./components/core/BasePanelLayout.vue')['default']
    CompGenericWrapper: typeof import('./components/CompGenericWrapper.vue')['default']
    CompQuickSet: typeof import('./components/search-option/CompQuickSet.vue')['default']
    Content: typeof import('./components/core/Content.vue')['default']
    ElAffix: typeof import('element-plus/es')['ElAffix']
@@ -44,6 +45,7 @@
    ElHeader: typeof import('element-plus/es')['ElHeader']
    ElIcon: typeof import('element-plus/es')['ElIcon']
    ElImage: typeof import('element-plus/es')['ElImage']
    ElImageViewer: typeof import('element-plus/es')['ElImageViewer']
    ElInput: typeof import('element-plus/es')['ElInput']
    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
    ElLink: typeof import('element-plus/es')['ElLink']
src/components/CompGenericWrapper.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,52 @@
<template>
  <!-- dialog包裹 -->
  <el-dialog v-if="currType == 'dialog'" :title="title" :model-value="visible" @opened="$emit('update:visible', true)"
    @closed="$emit('update:visible', false)" destroy-on-close>
    <div v-if="visible">
      <slot name="content"></slot>
    </div>
  </el-dialog>
  <!-- drawer包裹 -->
  <el-drawer v-if="currType == 'drawer'" :title="title" size="45%" direction="ltr" :model-value="visible"
    @opened="$emit('update:visible', true)" @closed="$emit('update:visible', false)" destroy-on-close>
    <slot name="content"></slot>
  </el-drawer>
  <!-- é»˜è®¤æ— åŒ…裹 -->
  <div v-if="currType == 'normal'">
    <slot></slot>
  </div>
</template>
<script setup>
import { ref, defineEmits, watch } from 'vue';
const props = defineProps({
  visible: Boolean,
  title: String,
  type: {
    type: String,
    default: 'normal'
  }
});
const typeOptions = ref([
  { id: '0', label: 'dialog' },
  { id: '1', label: 'drawer' },
  { id: '10', label: '' }
]);
const currType = ref('');
const emit = defineEmits(['update:visible']);
watch(
  () => props.type,
  (nValue) => {
    currType.value = nValue;
  },
  { immediate: true }
);
</script>
<style scoped>
::v-deep .el-drawer__body {
  padding-top: 0;
}
::v-deep .el-drawer__header {
  margin-bottom: 16px;
}
</style>
src/components/FYImageSelectDialog.vue
@@ -1,13 +1,12 @@
<template>
  <el-dialog
    :title="title"
    :model-value="dialogVisible"
    @opened="$emit('update:dialogVisible', true)"
    @closed="$emit('update:dialogVisible', false)"
    @opened="handleOpen"
    @closed="handleClose"
    width="66%"
    destroy-on-close
  >
    <div class="main" v-loading="loading">
    <div class="main">
      <el-row justify="end" v-if="!readonly">
        <el-text size="small" type="info" class="m-r-8"
          >最多选择{{ maxSelect }}张图片</el-text
@@ -41,14 +40,15 @@
          class="imgs"
        >
          <el-image
            v-loading="img.loading"
            v-for="(img, i) in typeImgMap.get(activeId)"
            :key="i"
            :class="[img.isSelect ? 'selected' : 'noActive', 'image']"
            fit="cover"
            :src="img.url"
            @click="onSelect(img, i)"
            @load="onOneImgLoadSuccess"
            @error="onOneImgLoadError"
            @load="onOneImgLoadSuccess(img)"
            @error="onOneImgLoadError(img)"
          />
        </el-scrollbar>
        <el-row v-else justify="space-between">
@@ -59,11 +59,9 @@
  </el-dialog>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
import { ref, watch, computed, onMounted, onUnmounted } from 'vue';
const props = defineProps({
  // æ ‡é¢˜
  title: String,
  dialogVisible: Boolean,
  /**
   * å›¾ç‰‡åˆ†ç±»
@@ -111,10 +109,12 @@
    loadedImgCount.value
  );
});
function onOneImgLoadError(e) {
function onOneImgLoadError(img) {
  img.loading = false
  loadedImgCount.value++;
}
function onOneImgLoadSuccess(e) {
function onOneImgLoadSuccess(img) {
  img.loading = false
  loadedImgCount.value++;
}
watch(
@@ -151,7 +151,28 @@
    img.isSelect = false;
  }
}
function handleOpen() {
  // if (props.typeImgMap.get(activeId.value) == undefined) {
  //     return;
  //   }
  //   props.typeImgMap.get(activeId.value).forEach((i) => {
  //     if (i.isSelect == true) {
  //       return;
  //     }
  //     props.defaultFile.forEach((imgItem) => {
  //       if (imgItem.url == i.url) {
  //         i.isSelect = true;
  //         selectedImgUrlList.value.push(i);
  //       }
  //     });
  //   });
  emit('update:dialogVisible', true)
}
function handleClose() {
  selectedImgUrlList.value.forEach(item => item.isSelect = false)
  selectedImgUrlList.value = []
  emit('update:dialogVisible', false)
}
function handleSubmit() {
  emit('submit', selectedImgUrlList.value);
  emit('update:dialogVisible', false);
@@ -171,27 +192,47 @@
  },
  { immediate: true }
);
// watch(
//   () => props.defaultFile,
//   (nV, oV) => {
//     if (props.typeImgMap.get(activeId.value) == undefined) {
//       return;
//     }
//     props.typeImgMap.get(activeId.value).forEach((i) => {
//       if (i.isSelect == true) {
//         return;
//       }
//       nV.forEach((imgItem) => {
//         if (imgItem.url == i.url) {
//           i.isSelect = true;
//           selectedImgUrlList.value.push(i);
//         }
//       });
//     });
//   },
//   { deep: true, immediate: true }
// );
watch(
  () => props.typeImgMap,
  (newMap, oldMap) => {
    if (newMap.get(activeId.value) == undefined) {
      return;
    }
    newMap.get(activeId.value).forEach((i) => {
      if (i.isSelect == true) {
        return;
      }
      props.defaultFile.forEach((imgItem) => {
        if (imgItem.url == i.url) {
          i.isSelect = true;
          selectedImgUrlList.value.push(i);
        }
      });
    });
  },
  { deep: true, immediate: true }
);
// watch(
//   () => props.typeImgMap,
//   (newMap, oldMap) => {
//     if (newMap.get(activeId.value) == undefined) {
//       return;
//     }
//     newMap.get(activeId.value).forEach((i) => {
//       if (i.isSelect == true) {
//         return;
//       }
//       props.defaultFile.forEach((imgItem) => {
//         if (imgItem.url == i.url) {
//           i.isSelect = true;
//           selectedImgUrlList.value.push(i);
//         }
//       });
//     });
//   },
//   { immediate: true }
// );
</script>
<style scoped>
.center {
src/components/SideList.vue
@@ -1,10 +1,55 @@
<template>
  <div v-if="legend" class="state-label">
    <el-input
      v-model="filterText"
      icon="Search"
      style="width: 200px"
      placeholder="关键字筛选"
      clearable
    />
    <el-tooltip placement="bottom-start" effect="dark">
      <template #content>
        <el-space>
          <el-space v-for="(item, index) in stateLabels" :key="index" :size="1">
            <el-icon :color="item.color">
              <component :is="item.icon"></component>
            </el-icon>
            {{ item.name }}
            <!-- <el-text size="small">{{ item.name }}</el-text> -->
          </el-space>
        </el-space>
        <br />
        <el-space>
          <el-space :size="1">
            <el-icon :size="16" color="var(--el-color-success)">
              <Avatar />
            </el-icon>
            æ­£åœ¨æ‰§è¡Œå·¡æŸ¥
          </el-space>
          <el-space :size="1">
            <el-icon :size="16" color="var(--el-color-info)">
              <Avatar />
            </el-icon>
            æœªæ‰§è¡Œ
          </el-space>
        </el-space>
      </template>
      <el-space>
        <el-icon class="cursor-p" :size="16" color="var(--el-color-primary)"
          ><QuestionFilled
        /></el-icon>
        <el-text size="small" class="cursor-p">审核状态图例</el-text>
      </el-space>
    </el-tooltip>
  </div>
  <el-tree
    ref="treeRef"
    class="el-tree"
    v-loading="isLoading"
    :data="dataList"
    :props="defaultProps"
    @node-click="handleNodeClick"
    :filter-node-method="filterNode"
    default-expand-all
    highlight-current
    check-on-click-node
@@ -19,16 +64,80 @@
              : 'custom-tree-node'
          "
        >
          <el-icon v-if="data.type == 2" color="var(--el-color-success)"
            ><SuccessFilled
          /></el-icon>
          <el-icon v-else-if="data.type == 1" color="var(--el-color-warning)"
            ><WarningFilled
          /></el-icon>
          <el-icon v-else-if="data.type == 0" color="var(--el-color-danger)"
            ><WarningFilled
          /></el-icon>
          <div>{{ node.label }}</div>
          <el-icon
            v-if="data.status == '正在执行'"
            :size="16"
            color="var(--el-color-success)"
            style="margin-left: -16px"
          >
            <Avatar />
          </el-icon>
          <el-icon
            v-if="data.status == '未执行'"
            :size="16"
            color="var(--el-color-info)"
            style="margin-left: -16px"
          >
            <Avatar />
          </el-icon>
          <!-- <el-icon :color="stateLabels[data.type].color">
            <component :is="stateLabels[data.type].icon"></component>
          </el-icon> -->
          <el-icon
            v-if="data.type == 0"
            :size="16"
            color="var(--el-color-info)"
          >
            <SuccessFilled />
          </el-icon>
          <el-icon
            v-else-if="data.type == 1"
            :size="16"
            color="var(--el-color-danger)"
          >
            <QuestionFilled />
          </el-icon>
          <el-icon
            v-else-if="data.type == 2"
            :size="16"
            color="var(--el-color-warning)"
          >
            <QuestionFilled />
          </el-icon>
          <el-icon
            v-else-if="data.type == 3"
            :size="16"
            color="var(--el-color-danger)"
          >
            <WarnTriangleFilled />
          </el-icon>
          <el-icon
            v-else-if="data.type == 4"
            :size="16"
            color="var(--el-color-danger)"
          >
            <WarningFilled />
          </el-icon>
          <el-icon
            v-else-if="data.type == 5"
            :size="16"
            color="var(--el-color-warning)"
          >
            <WarningFilled />
          </el-icon>
          <el-icon
            v-else-if="data.type == 6"
            :size="16"
            color="var(--el-color-success)"
          >
            <SuccessFilled />
          </el-icon>
          <!-- <el-text>{{ node.label }}</el-text> -->
          {{ node.label }}
          <span v-if="data.count">
            {{ '_(' + data.count + ')' }}
            <!-- <el-text size="small">点次</el-text>) -->
          </span>
        </div>
      </slot>
    </template>
@@ -49,16 +158,59 @@
        }
      ]
    },
    loading: Boolean
    loading: Boolean,
    // æ˜¯å¦å±•示图例
    legend: {
      type: Boolean,
      default: false
    }
  },
  emits: ['itemClick'],
  data() {
    return {
      filterText: '',
      defaultProps: {
        children: 'children',
        label: 'title'
      },
      isLoading: this.loading
      isLoading: this.loading,
      stateLabels: [
        {
          color: 'var(--el-color-info)',
          name: '无问题',
          icon: 'SuccessFilled'
        },
        {
          color: 'var(--el-color-danger)',
          name: '问题未审核',
          icon: 'QuestionFilled'
        },
        {
          color: 'var(--el-color-warning)',
          name: '问题部分审核',
          icon: 'QuestionFilled'
        },
        {
          color: 'var(--el-color-danger)',
          name: '未整改',
          icon: 'WarnTriangleFilled'
        },
        {
          color: 'var(--el-color-danger)',
          name: '整改未审核',
          icon: 'WarningFilled'
        },
        {
          color: 'var(--el-color-warning)',
          name: '整改部分审核',
          icon: 'WarningFilled'
        },
        {
          color: 'var(--el-color-success)',
          name: '审核完成',
          icon: 'SuccessFilled'
        }
      ]
    };
  },
  computed: {
@@ -77,6 +229,7 @@
      for (const [key, value] of itemMap) {
        const i = {
          title: key,
          count: value.length,
          children: []
        };
        value.forEach((v) => {
@@ -97,6 +250,9 @@
    }
  },
  watch: {
    filterText(val) {
      this.$refs.treeRef.filter(val);
    },
    loading(nValue) {
      this.isLoading = nValue;
    },
@@ -104,17 +260,17 @@
    dataList(nValue) {
      if (this.isLoading) {
        if (nValue.length > 0) {
          this.dataList.forEach((d) => {
            d.children.forEach((c) => {
              c.selected = false;
            });
          });
          // this.dataList.forEach((d) => {
          //   d.children.forEach((c) => {
          //     c.selected = false;
          //   });
          // });
          if (nValue[0].children.length > 0) {
            const c = nValue[0].children[0];
            c.selected = true;
            // c.selected = true;
            this.$emit('itemClick', c);
          } else {
            nValue[0].selected = true;
            // nValue[0].selected = true;
          }
        }
        this.isLoading = false;
@@ -123,22 +279,32 @@
  },
  methods: {
    handleNodeClick(data) {
      this.dataList.forEach((d) => {
        d.children.forEach((c) => {
          c.selected = false;
        });
      });
      data.selected = true;
      // this.dataList.forEach((d) => {
      //   d.children.forEach((c) => {
      //     c.selected = false;
      //   });
      // });
      // data.selected = true;
      //父节点的点击事件不做传递
      if (data.children == undefined) {
        this.$emit('itemClick', data);
      }
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.title.includes(value);
    }
  }
};
</script>
<style lang="scss" scoped>
.el-tree {
  // background-color: aliceblue;
  // width: var(--el-aside-width, 200px)
}
.custom-tree-node {
  display: flex;
  align-items: center;
@@ -146,4 +312,15 @@
.selected-tree-node {
  color: var(--el-color-primary);
}
.state-label {
  position: sticky;
  z-index: 1;
  top: 0;
  background-color: white;
  // box-shadow: var(--el-box-shadow-light);
  border-bottom: var(--el-border);
  display: flex;
  padding-bottom: 4px;
}
</style>
src/components/ToolBar.vue
@@ -9,6 +9,7 @@
            :key="i"
            :type="b.color ? b.color : 'primary'"
            size="small"
            plain
            @click="b.click"
            >{{ b.name }}</el-button
          >
@@ -17,7 +18,7 @@
    </el-row>
    <el-row class="tag-group" v-if="title">
      <el-space>
        <el-tag v-for="(d, i) in descriptions" :key="i" type="info" size="small">{{
        <el-tag v-for="(d, i) in descriptions" :key="i" :type="d.type" size="small">{{
          d.name + ': ' + d.value
        }}</el-tag>
      </el-space>
src/components/core/BaseContentLayout.vue
@@ -5,7 +5,7 @@
    </el-header>
    <el-container>
      <el-aside class="el-aside" :style="'height: ' + mainHeight">
        <el-scrollbar>
        <el-scrollbar :noresize="true" style="position: relative;">
          <slot name="aside"></slot>
        </el-scrollbar>
      </el-aside>
@@ -47,6 +47,7 @@
<style scoped>
.el-aside {
  /* width: initial; */
  /* overflow-x: auto; */
  position: relative;
  /* height: calc(100vh - 60px * 2 - 20px * 2); */
  /* background-color: aqua; */
src/views/fysp/check/ProCheck.vue
@@ -9,6 +9,7 @@
    </template>
    <template #aside>
      <SideList
        legend
        :items="subtasks"
        :loading="sideLoading"
        @item-click="chooseSubtask"
@@ -26,36 +27,30 @@
        class="el-scrollbar"
        v-loading="mainLoading"
      >
        <template v-if="compProblemCardVisible">
          <CompProblemCard
            :key="i"
            v-for="(p, i) in curProList"
            :index="i + 1"
            :problem="p"
            :subtask="curSubtask.data"
            :topTask="topTask"
            @updated="onProSubmited"
            @submit="updateSubtask"
          ></CompProblemCard>
        </template>
        <CompProblemCard
          :key="i"
          v-for="(p, i) in curProList"
          :index="i + 1"
          :problem="p"
          :subtask="curSubtask.data"
          :topTask="topTask"
          @submit="updateSubtask"
          @check="handleProblemCheck"
        ></CompProblemCard>
      </el-scrollbar>
      <el-empty v-else description="暂无记录" v-loading="mainLoading" />
      <el-empty v-else description="暂无问题" v-loading="mainLoading" />
    </template>
  </BaseContentLayout>
  <el-dialog
    v-model="proAddOrUpdDialogVisible"
    :before-close="proAddOrUpdDialogClose"
    width="50%"
  <CompProblemAddOrUpd
    title="新增问题"
  >
    <CompProblemAddOrUpd
      v-if="proAddOrUpdDialogVisible"
      :subtask="curSubtask.data"
      :topTask="topTask"
      ref="compProblemAddOrUpdRef"
      @submited="newProSubmit"
    />
  </el-dialog>
    v-if="proAddOrUpdDialogVisible"
    v-model:visible="proAddOrUpdDialogVisible"
    :subtask="curSubtask.data"
    :topTask="topTask"
    ref="compProblemAddOrUpdRef"
    @cancel="onAddProCanceled"
    @submit="updateSubtask"
  />
  <ArbitraryPhoto
    v-if="anyPhotoDialog"
    v-model:dialog-visible="anyPhotoDialog"
@@ -63,16 +58,13 @@
    :subtask="curSubtask.data"
    ref="arbitraryPhotoRef"
  ></ArbitraryPhoto>
  <el-drawer
    direction="ltr"
    v-model="deviceShowDialog"
    :before-close="beforeDeviceShowDialogclose"
  <CompDeviceShowTest
    title="设施设备"
    size="45%"
    v-model:visible="deviceShowDialog"
    v-if="deviceShowDialog"
    ref="deviceShowRef"
  >
    <CompDeviceShowTest v-if="deviceShowDialog" ref="deviceShowRef">
    </CompDeviceShowTest>
  </el-drawer>
  </CompDeviceShowTest>
</template>
<script>
@@ -93,7 +85,6 @@
  },
  data() {
    return {
      compProblemCardVisible: true,
      // è®¾å¤‡å›¾
      deviceShowDialog: false,
      // ä»»æ„å›¾
@@ -116,21 +107,23 @@
      buttons: [
        {
          name: '新增问题',
          color: 'success',
          // color: 'success',
          color: 'primary',
          click: () => {
            this.proAddOrUpdDialogVisible = true;
          }
        },
        {
          name: '场景图片',
          color: 'warning',
          // color: 'warning',
          color: 'primary',
          click: () => {
            this.anyPhotoDialog = true;
          }
        },
        {
          name: '设施设备',
          color: 'info',
          color: 'primary',
          click: () => {
            this.openDeviceShowDialog();
          }
@@ -232,21 +225,6 @@
        this.$refs.deviceShowRef.init(this.curSubtask.data.scene);
      });
    },
    // å…³é—­è®¾å¤‡å›¾å¼¹çª—
    beforeDeviceShowDialogclose(done) {
      // this.deviceShowDialog = false;
      done();
    },
    // å…³é—­ä»»æ„å›¾ç‰‡å¼¹çª—
    beforeAnyPhotoDialogclose() {
      this.anyPhotoDialog = false;
    },
    handleCloseCheckAnyPhono() {
      this.beforeAnyPhotoDialogclose();
    },
    proAddOrUpdDialogClose() {
      this.proAddOrUpdDialogVisible = false;
    },
    //查询子任务统计信息
    search(formSearch) {
      this.topTask = formSearch.topTask;
@@ -261,8 +239,9 @@
      taskApi.getSubtaskSummary(param).then((res) => {
        const list = [];
        res.forEach((s) => {
          const t = this.getSubtaskType(s);
          const t = ProCheckProxy.getSubtaskType(s);
          list.push({
            status: s.subtask.status,
            type: t,
            title: s.stName,
            categoly: s.stPlanTime.split('T')[0],
@@ -275,20 +254,6 @@
          this.mainLoading = false;
        }
      });
    },
    //获取任务问题的审核情况
    getSubtaskType(s) {
      let type = 0;
      if (s.proNum == 0) {
        type = 2;
      } else if (s.proCheckedNum == 0) {
        type = 0;
      } else if (s.proCheckedNum < s.proNum) {
        type = 1;
      } else {
        type = 2;
      }
      return type;
    },
    //点击左侧菜单任务事件
    chooseSubtask(s) {
@@ -306,45 +271,54 @@
          this.mainLoading = false;
        });
    },
    onAddProCanceled() {
    },
    // é—®é¢˜å¡ç‰‡ç»„件主动发起刷新父组件数据
    updateSubtask(refresh = true) {
    updateSubtask(refresh = false) {
      this.curSubtask.data.proCheckedNum++;
      this.curSubtask.type = this.getSubtaskType(this.curSubtask.data);
      if (refresh) {
        this.refreshCurrSubtask();
      this.curSubtask.type = ProCheckProxy.getSubtaskType(this.curSubtask.data);
      if (this.proAddOrUpdDialogVisible) {
        this.proAddOrUpdDialogVisible = false;
      }
    },
    onProSubmited(isOk) {
      this.proAddOrUpdDialogClose();
      if (!isOk) {
        return;
      }
      this.updateSubtask();
    },
    newProSubmit(isOk) {
      this.proAddOrUpdDialogVisible = false;
      if (!isOk) {
        return;
      }
      this.refreshCurrSubtask();
      this.refreshCurrSubtask(refresh);
    },
    // åˆ·æ–°å½“前选中子任务
    refreshCurrSubtask() {
      this.compProblemCardVisible = false;
    refreshCurrSubtask(refresh) {
      this.sideLoading = false;
      this.mainLoading = true;
      // this.mainLoading = true;
      setTimeout(() => {
        taskApi
          .getProBySubtask(this.curSubtask.data.stGuid)
          .then((res) => {
            this.curProList = res;
            if (refresh) {
              this.curProList = res;
              return;
            }
            const currProLen = this.curProList.length;
            // ä¸æ”¹å˜æ•°ç»„对像引用的前提下重新赋值
            for (let index = 0; index < res.length; index++) {
              const element = res[index];
              if (currProLen < index + 1) {
                this.curProList.push(element);
              } else {
                this.curProList[index] = element;
              }
            }
            // this.curSubtask = s;
          })
          .finally(() => {
            this.mainLoading = false;
            this.compProblemCardVisible = true;
            // this.mainLoading = false;
          });
      }, 150);
    },
    // é—®é¢˜å®¡æ ¸å®ŒæˆåŽï¼Œæ›´æ–°å·¦ä¾§åˆ—表对应子任务状态
    handleProblemCheck(){
      const status = ProCheckProxy.calProStatus(this.curProList)
      this.curSubtask.data.proNum = status.proNum
      this.curSubtask.data.proCheckedNum = status.proCheckedNum
      this.curSubtask.data.changeNum = status.changeNum
      this.curSubtask.data.changeCheckedNum = status.changeCheckedNum
      this.curSubtask.type = ProCheckProxy.getSubtaskType(this.curSubtask.data)
    }
  },
  mounted() {}
src/views/fysp/check/ProCheckProxy.js
@@ -1,4 +1,4 @@
import { $fysp } from '@/api/index'
import { $fysp } from '@/api/index';
//问题状态
const proStatus = {
@@ -8,7 +8,7 @@
  change_unCheck: 'change_unCheck',
  change_fail: 'change_fail',
  change_pass: 'change_pass'
}
};
export default {
  //统计问题
@@ -16,8 +16,12 @@
    const status = {
      //问题数量
      proNum: proList.length,
      // é—®é¢˜å®¡æ ¸æ•°
      proCheckedNum: 0,
      //整改数量
      changeNum: 0,
      //整改审核数量
      changeCheckedNum: 0,
      //待审核数量
      uncheckNum: 0,
      //已审核通过数量
@@ -30,56 +34,98 @@
      passPer: '0%',
      //审核率
      checkPer: '0%'
    }
    };
    proList.forEach((p) => {
      if (p.ischanged) status.changeNum++
      if (p.ischanged) status.changeNum++;
      if (p.extension3 == 'fail' || p.extension3 == 'change_fail') status.unpassNum++
      if (p.extension3 == 'fail' || p.extension3 == 'change_fail')
        status.unpassNum++;
      else if (
        p.extension3 == 'unCheck' ||
        p.extension3 == 'change_unCheck' ||
        (p.extension3 == 'pass' && p.ischanged)
      )
        status.uncheckNum++
      else status.passNum++
        status.uncheckNum++;
      else status.passNum++;
      if (p.extension3 == proStatus.pass) {
        status.proCheckedNum++;
      }
      if (p.extension3 == proStatus.change_pass) {
        status.changeCheckedNum++;
      }
      status.changePer =
        String(
          (status.changeNum / status.proNum) * 100
            ? ((status.changeNum / status.proNum) * 100).toFixed(1)
            : 0
        ) + '%'
        ) + '%';
      status.passPer =
        String(
          (status.passNum / status.proNum) * 100
            ? ((status.passNum / status.proNum) * 100).toFixed(1)
            : 0
        ) + '%'
        ) + '%';
      status.checkPer =
        String(
          ((status.passNum + status.unpassNum) / status.proNum) * 100
            ? (((status.passNum + status.unpassNum) / status.proNum) * 100).toFixed(1)
            ? (
                ((status.passNum + status.unpassNum) / status.proNum) *
                100
              ).toFixed(1)
            : 0
        ) + '%'
    })
        ) + '%';
    });
    return status
    return status;
  },
  //统计问题,返回数组形式
  proStatusArray(proList) {
    const status = this.calProStatus(proList)
    const status = this.calProStatus(proList);
    return [
      { name: '问题数', value: status.proNum },
      { name: '整改数', value: status.changeNum },
      { name: '待审核', value: status.uncheckNum },
      { name: '已审核', value: status.passNum },
      { name: '未通过', value: status.unpassNum },
      { name: '整改率', value: status.changePer },
      { name: '通过率', value: status.passPer },
      { name: '审核率', value: status.checkPer }
    ]
      { name: '问题数', value: status.proNum, type: 'info' },
      {
        name: '整改数',
        value: status.changeNum,
        type: status.changeNum < status.proNum ? 'danger' : 'info'
      },
      {
        name: '待审核',
        value: status.uncheckNum,
        type: status.uncheckNum > 0 ? 'danger' : 'info'
      },
      { name: '已审核', value: status.passNum, type: 'info' },
      // {
      //   name: '未通过',
      //   value: status.unpassNum,
      //   type: status.unpassNum > 0 ? 'danger' : 'info'
      // },
      {
        name: '整改率',
        value: status.changePer,
        type:
          status.proNum > 0 && status.changePer != '100.0%'
            ? 'danger'
            : 'success'
      },
      // {
      //   name: '通过率',
      //   value: status.passPer,
      //   type:
      //     status.proNum > 0 && status.passPer != '100.0%' ? 'danger' : 'success'
      // },
      {
        name: '审核率',
        value: status.checkPer,
        type:
          status.proNum > 0 && status.checkPer != '100.0%'
            ? 'danger'
            : 'success'
      }
    ];
  },
  //问题图片和整改图片
@@ -93,34 +139,118 @@
        title: '整改图片',
        path: []
      }
    ]
    ];
    if (pro.mediafileList) {
      pro.mediafileList.forEach((m) => {
        pics[m.ischanged ? 1 : 0].path.push(`${$fysp.imgUrl}${m.extension1}${m.guid}.jpg`)
      })
        pics[m.ischanged ? 1 : 0].path.push(
          `${$fysp.imgUrl}${m.extension1}${m.guid}.jpg`
        );
      });
    }
    return pics
    return pics;
  },
  //问题审核状态转换中文
  proStatusMap(p) {
    switch (p) {
      case proStatus.unCheck:
        return { name: '问题未审核', type: 'warning', index: 0, checkable: true, deletable: true, changeable: false }
        return {
          name: '问题未审核',
          type: 'warning',
          index: 0,
          checkable: true,
          deletable: true,
          changeable: false
        };
      case proStatus.pass:
        return { name: '问题通过', type: 'success', index: 1, checkable: false, deletable: true, changeable: false }
        return {
          name: '问题通过',
          type: 'success',
          index: 1,
          checkable: false,
          deletable: true,
          changeable: false
        };
      case proStatus.fail:
        return { name: '问题不通过', type: 'danger', index: 1, checkable: false, deletable: true, changeable: false }
        return {
          name: '问题不通过',
          type: 'danger',
          index: 1,
          checkable: false,
          deletable: true,
          changeable: false
        };
      case proStatus.change_unCheck:
        return { name: '整改未审核', type: 'warning', index: 2, checkable: true, deletable: false, changeable: true }
        return {
          name: '整改未审核',
          type: 'warning',
          index: 2,
          checkable: true,
          deletable: false,
          changeable: true
        };
      case proStatus.change_fail:
        return { name: '整改不通过', type: 'danger', index: 3, checkable: false, deletable: false, changeable: true }
        return {
          name: '整改不通过',
          type: 'danger',
          index: 3,
          checkable: false,
          deletable: false,
          changeable: true
        };
      case proStatus.change_pass:
        return { name: '整改通过', type: 'success', index: 3, checkable: false, deletable: false, changeable: true }
        return {
          name: '整改通过',
          type: 'success',
          index: 3,
          checkable: false,
          deletable: false,
          changeable: true
        };
      default:
        return { name: '问题未审核', type: 'warning', index: 0, checkable: true, deletable: true }
        return {
          name: '问题未审核',
          type: 'warning',
          index: 0,
          checkable: true,
          deletable: true
        };
    }
  },
  //获取任务问题的审核情况
  getSubtaskType(s) {
    let type = 0;
    // æ— é—®é¢˜
    if (s.proNum == 0) {
      type = 0;
    }
    // é—®é¢˜æœªå®¡æ ¸
    else if (s.proCheckedNum == 0) {
      type = 1;
    }
    // é—®é¢˜éƒ¨åˆ†å®¡æ ¸
    else if (s.proCheckedNum < s.proNum) {
      type = 2;
    }
    // æœªæ•´æ”¹
    else if (s.changeNum < s.proNum) {
      type = 3;
    }
    // æ•´æ”¹æœªå®¡æ ¸
    else if (s.changeCheckedNum == 0) {
      type = 4;
    }
    // æ•´æ”¹éƒ¨åˆ†å®¡æ ¸
    else if (s.changeCheckedNum < s.changeNum) {
      type = 5;
    }
    // å®Œå…¨å®¡æ ¸
    else {
      type = 6;
    }
    return type;
  },
  /**
@@ -130,18 +260,18 @@
   * @returns ä¸‹ä¸€ä¸ªé—®é¢˜çŠ¶æ€
   */
  proNextStatus(s, isPass) {
    let status, action
    let status, action;
    switch (s) {
      case proStatus.unCheck:
        status = isPass ? proStatus.pass : proStatus.fail
        action = isPass ? 0 : 1
        break
        status = isPass ? proStatus.pass : proStatus.fail;
        action = isPass ? 0 : 1;
        break;
      case proStatus.change_unCheck:
        status = isPass ? proStatus.change_pass : proStatus.change_fail
        action = isPass ? 2 : 3
        break
        status = isPass ? proStatus.change_pass : proStatus.change_fail;
        action = isPass ? 2 : 3;
        break;
    }
    return { status: status, action: action }
    return { status: status, action: action };
  },
  /**
@@ -150,19 +280,19 @@
   * @returns ä¸‹ä¸€ä¸ªé—®é¢˜çŠ¶æ€
   */
  proBeforeStatus(s) {
    let status, action
    let status, action;
    switch (s) {
      case proStatus.fail:
      case proStatus.pass:
        status = proStatus.unCheck
        action = 4
        break
      case proStatus.change_fail:
        status = proStatus.unCheck;
        action = 4;
        break;
      case proStatus.change_fail:
      case proStatus.change_pass:
        status = proStatus.change_unCheck
        action = 5
        break
        status = proStatus.change_unCheck;
        action = 5;
        break;
    }
    return { status: status, action: action }
    return { status: status, action: action };
  }
}
};
src/views/fysp/check/components/ArbitraryPhoto.vue
@@ -1,5 +1,6 @@
<template>
  <FYImageSelectDialog
    v-loading="loading"
    title="场景图片"
    :typeList="typesList"
    :typeImgMap="typesMap"
@@ -20,6 +21,7 @@
      // æ— æ•°æ®
      typesList: [],
      typesMap: new Map(),
      loading: true,
    };
  },
  mounted() {
@@ -29,21 +31,9 @@
    // å›¾ç‰‡åˆ†ç±»
    getGroupImgs() {
      mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => {
        this.loading = true
        let typeList = [];
        let typeMap = new Map();
        function hasThisTypeName(typeName) {
          return typeList.map((item) => item.typeName).indexOf(typeName) != -1;
        }
        function addNewType(typeId, typeName, img) {
          typeList.push({
            typeId: typeId,
            typeName: typeName
          });
          typeMap.set(typeId, [img]);
        }
        function addToThisType(typeId, img) {
          typeMap.get(typeId).push(img);
        }
        const data = res.data;
        for (const e of data) {
          let img = {
@@ -51,18 +41,24 @@
          };
          const businesstype = e.businesstype;
          const businesstypeid = e.businesstypeid;
          if (hasThisTypeName(businesstype)) {
            addToThisType(businesstypeid, img);
          if (
            typeList.find((item) => item.typeName == businesstype) != undefined
          ) {
            typeMap.get(businesstypeid).push(img);
          } else {
            addNewType(businesstypeid, businesstype, img);
            typeList.push({
              typeId: businesstypeid,
              typeName: businesstype
            });
            typeMap.set(businesstypeid, [img]);
          }
        }
        this.typesList = typeList;
        this.typesMap = typeMap;
      });
      }).finally(() => (this.loading = false));
    }
  }
};
</script>
<style scoped></style>
src/views/fysp/check/components/ComChangeEdit.vue
@@ -1,88 +1,82 @@
<template>
  <div>
    <div class="t-card_item">
      æ•´æ”¹å›¾ç‰‡&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
      <div>
        <el-button @click="choseChangePic" :disabled="fileList.length >= 3">从文件夹选取</el-button>
  <CompGenericWrapper type="dialog">
    <template #content>
      <el-row>
        <el-col>
          <el-form-item label="整改图片">
            <el-button @click="choseChangePic" :disabled="fileList.length >= 3"
              >从文件夹选取</el-button
            >
          </el-form-item>
        </el-col>
        <el-col v-if="!fileList || fileList.length <= 0">
          <el-empty style="height: 145px" description="请添加图片" />
        </el-col>
        <el-col>
          <el-upload
            class="img-upload"
            ref="uploadRef"
            v-model:file-list="fileList"
            list-type="picture-card"
            multiple
            :auto-upload="false"
            crossorigin="Anonymous"
            :before-remove="beforeRemoveFile"
            :on-preview="handlePictureCardPreview"
            :disabled="readonly"
            accept="image/*"
          >
            <template #trigger v-if="fileList.length < 3 && !readonly">
              <el-button
                v-if="fileList.length < 3"
                type="primary"
                id="uploadBtnId"
                style="display: none"
              ></el-button>
              <el-icon>
                <Plus />
              </el-icon>
            </template>
            <template #tip>
              <div style="color: #f56c6c">
                æœ€å°‘上传一张图片,最多选择三张图片
              </div>
            </template>
          </el-upload>
        </el-col>
      </el-row>
      <div class="flex-div">
        <el-button type="primary" @click="onSubmit">保存</el-button>
        <el-button @click="onCancel">取消</el-button>
      </div>
    </div>
    <el-upload
      class="img-upload"
      ref="uploadRef"
      v-model:file-list="fileList"
      list-type="picture-card"
      multiple
      :auto-upload="false"
      crossorigin="Anonymous"
      :before-remove="beforeRemoveFile"
      :on-preview="handlePictureCardPreview"
      :disabled="readonly"
      accept="image/*"
    >
      <template #trigger v-if="fileList.length < 3 && !readonly">
        <el-button
          v-if="fileList.length < 3"
          type="primary"
          id="uploadBtnId"
          style="display: none"
        ></el-button>
        <el-icon>
          <Plus />
        </el-icon>
      </template>
      <template #tip>
        <div style="color: #f56c6c">最少上传一张图片,最多选择三张图片</div>
      </template>
    </el-upload>
    <div class="flex-div">
      <el-button type="primary" @click="onSubmit">保存</el-button>
      <el-button @click="this.$emit('submited', false)">取消</el-button>
    </div>
    <ArbitraryPhoto
      :max-select="maxSelectImgCount - fileList.length"
      v-if="anyPhotoDialog"
      v-model:dialog-visible="anyPhotoDialog"
      @submit="handleSelectedAnyPhono"
      :subtask="subtask"
      :defaultFile="fileList"
      ref="arbitraryPhotoRef"
    >
    </ArbitraryPhoto>
    <el-dialog
      title="台账图片"
      width="80%"
      v-model="ledgerPicDialog"
      :before-close="beforeLedgerPicDialogclose"
    >
      <LedgerPic
        v-if="ledgerPicDialog"
        @selectByLedgerPicEvent="handleLedgerPicPhono"
        :month="month"
        :subtask="subtask"
        ref="ledgerPicRef"
      >
      </LedgerPic>
    </el-dialog>
  </div>
  <el-dialog v-model="previewDialogVisible">
    <img w-full :src="previewDialogImageUrl" alt="预览" class="preview-pic" />
  </el-dialog>
      <el-image-viewer
          v-if="previewDialogVisible"
          :url-list="fileList.map((item) => item.url)"
          :initial-index="initialIndex"
          @close="previewDialogVisible = false"
          alt="预览"
          class="preview-pic"
        />
    </template>
  </CompGenericWrapper>
</template>
<script>
import ArbitraryPhoto from './ArbitraryPhoto.vue';
import LedgerPic from './CompLedgerPic.vue';
import problemApi from '@/api/fysp/problemApi.js';
import { $fysp } from '@/api/index.js';
import fileUtil from '@/utils/fileUtils.js';
import { useCloned } from '@vueuse/core';
import { ElMessage } from 'element-plus';
export default {
  emits: ['submit', 'cancel'],
  components: {
    ArbitraryPhoto,
    LedgerPic
  },
  watch: {
    oldChangeFileList: {
      handler(nv, ov) {
        this.initParams();
      },
      immediate: true
    },
    fileList: {
      handler(newFileList, oldFileList) {
        this.pictureValidate();
@@ -112,6 +106,8 @@
  },
  data() {
    return {
      // åˆå§‹å›¾ç‰‡é¢„览index
      initialIndex: -1,
      // å›¾ç‰‡é€‰æ‹©æœ€å¤§æ•°é‡
      maxSelectImgCount: 3,
      previewDialogImageUrl: '',
@@ -124,9 +120,7 @@
      anyPhotoDialog: false
    };
  },
  mounted() {
    this.initParams();
  },
  mounted() {},
  methods: {
    pictureValidate() {
      if (this.changeType == 1 && this.fileList.length < 1) {
@@ -146,7 +140,7 @@
      return true;
    },
    initParams() {
      if (this.changeType == 0) {
      if (!this.changeType || this.changeType == 0) {
        return;
      }
      let beforeEditImgList = [];
@@ -165,6 +159,10 @@
      );
      this.fileList = useCloned(beforeEditImgList).cloned.value;
      this.oldFileList = useCloned(beforeEditImgList).cloned.value;
    },
    onCancel() {
      this.$emit("cancel")
      this.$emit('update:visible', false)
    },
    onSubmit() {
      if (!this.pictureValidate()) {
@@ -205,7 +203,7 @@
          problemApi.updateChange(data).then((res) => {});
        });
        that.$emit('submited', true);
        that.$emit('submit', true);
      } else {
        fileUtil.getImageFiles(picUrls, function (files) {
          data.append('problemId', that.problemId);
@@ -213,7 +211,7 @@
            data.append('images', image);
          });
          problemApi.changeProblem(data).then((res) => {});
          that.$emit('submited', true);
          that.$emit('submit', true);
        });
      }
    },
@@ -224,48 +222,9 @@
      }
    },
    handlePictureCardPreview(uploadFile) {
      this.initialIndex = this.fileList.indexOf(uploadFile)
      this.previewDialogVisible = true;
      this.previewDialogImageUrl = uploadFile.url;
    },
    handleSelectedAnyPhono(data) {
      this.beforeAnyPhotoDialogclose();
      let isExist = false;
      for (const item of data) {
        for (const already of this.fileList) {
          if (item.url == already.url) {
            isExist = true;
          }
        }
        if (!isExist) {
          this.fileList.push({
            url: item.url,
            name: '1'
          });
        }
        isExist = false;
      }
    },
    handleLedgerPicPhono(data) {
      let isExist = false;
      for (const item of data) {
        for (const already of this.fileList) {
          if (item.url == already.url) {
            isExist = true;
          }
        }
        if (!isExist) {
          this.fileList.push({
            url: item.url,
            name: '1'
          });
        }
        isExist = false;
      }
      this.beforeAnyPhotoDialogclose();
    },
    chosePicFromAnyPic() {
      this.anyPhotoDialog = true;
    },
    // ä»Žæ–‡ä»¶å¤¹ä¸­
    choseChangePic() {
@@ -276,24 +235,6 @@
        // è§¦å‘点击事件
        btnElement.click();
      }
    },
    chosePicFromLedgerPic() {
      // ä½¿ç”¨Date对象解析日期字符串
      var date = new Date(this.subtask.subtask.planstarttime.splice(0, 7));
      // èŽ·å–æœˆä»½ä¿¡æ¯ï¼Œæœˆä»½æ˜¯ä»Ž0开始的,所以需要加1
      this.month = date.getMonth() + 1;
      if (String(this.month).length == 1) {
        this.month = `0${this.month}`;
      }
      var year = date.getFullYear();
      this.month = `${year}-${this.month}`;
      this.ledgerPicDialog = true;
    },
    beforeAnyPhotoDialogclose() {
      this.anyPhotoDialog = false;
    },
    beforeLedgerPicDialogclose() {
      this.ledgerPicDialog = false;
    }
  }
};
@@ -323,6 +264,10 @@
  height: 100%;
}
::v-deep .el-upload--picture-card {
  border: 0 !important;
  display: none;
}
/* éšè—el-upload上传成功组件 */
::v-deep .el-upload-list__item-status-label {
  display: none !important;
}
</style>
src/views/fysp/check/components/CompDevicePhono.vue
ÎļþÒÑɾ³ý
src/views/fysp/check/components/CompDevicePhoto.vue
@@ -1,5 +1,6 @@
<template>
  <FYImageSelectDialog
    v-loading="loading"
    title="设备图片"
    :typeList="typeList"
    :typeImgMap="typeImgMap"
@@ -10,6 +11,7 @@
import deviceApi from '@/api/fysp/deviceApi';
import { useCloned } from '@vueuse/core';
import { $fysp } from '@/api/index.js';
const loading = ref(true)
const props = defineProps({
  // å±•示模式
  mode: {
@@ -64,6 +66,7 @@
    const topTypeId = deviceTopTypeElement.typeId;
    deviceImgMap.set(topTypeId, []);
    deviceApi.fetchDevices(props.subtask.sceneId, topTypeId).then((result) => {
      loading.value = true;
      // æ ‡å‡†åŒ–属性名
      for (let i = 0; i < result.data.length; i++) {
        var element = convertKeys(result.data[i]);
@@ -92,7 +95,7 @@
              deviceImgMap.get(topTypeId).push(newDevice);
            }
          }
        });
        }).finally(() => (loading.value = false));
      }
    });
  }
src/views/fysp/check/components/CompDeviceShow.vue
ÎļþÒÑɾ³ý
src/views/fysp/check/components/CompDeviceShowTest.vue
@@ -1,163 +1,170 @@
<template>
  <div>
    <!-- é€‰é¡¹ -->
    <!-- è®¾å¤‡ç±»åž‹  -->
    <el-row>
      <el-col>
        <el-tabs
          class="child_select"
          placeholder="设备类型"
          v-model="currSelect.topDeviceTypeId"
        >
          <el-tab-pane
            v-for="item in deviceTopTypes"
            :key="item.id"
            :name="item.id"
  <CompGenericWrapper type="drawer">
    <template #content>
      <!-- é€‰é¡¹ -->
      <!-- è®¾å¤‡ç±»åž‹  -->
      <el-row>
        <el-col>
          <el-tabs
            class="child_select"
            placeholder="设备类型"
            v-model="currSelect.topDeviceTypeId"
          >
            <template #label>
              <el-badge
                :value="item.count"
                :type="item.count == 0 ? 'danger' : 'primary'"
              >
                <span class="custom-tabs-label">
                  <span>{{ item.label }}</span>
                </span>
              </el-badge>
            </template>
          </el-tab-pane>
        </el-tabs>
      </el-col>
    </el-row>
    <el-collapse v-model="activeNames" style="border: 4px">
      <el-collapse-item
        v-for="item in formInfo"
        :key="item.id"
        :name="item.id"
        class="collapse-item-class"
      >
        <template #title>
          <div
            style="display: flex; width: 100%; justify-content: space-between"
          >
            <div style="">
              <el-descriptions style="" :column="3" size="small" border>
                <el-descriptions-item width="64px" :label="currSelect.topDeviceTypeId == 0 ? '站点名称' : '设备名称'" :span="3">{{
                  item.name || '无'
                }}</el-descriptions-item>
                <el-descriptions-item label="供应商">{{
                  item.supplier || '无'
                }}</el-descriptions-item>
                <el-descriptions-item label="运维商">{{
                  item.maintainer || '无'
                }}</el-descriptions-item>
                <el-descriptions-item label="运维频次">
                  <el-select
                    v-model="item.maintainFrequency"
                    :disabled="isDisabled"
                    style="width: 150px"
                  >
                    <el-option
                      v-for="frequency of maintainFrequencysArray"
                      :key="frequency.key"
                      :label="frequency.value"
                      :value="frequency.key"
                    ></el-option>
                  </el-select>
                </el-descriptions-item>
                <el-descriptions-item label="运维人员">{{
                  item.maintainStaff || '无'
                }}</el-descriptions-item>
                <el-descriptions-item label="运维联系方式">{{
                  item.maintainTel || '无'
                }}</el-descriptions-item>
                <el-descriptions-item label="品牌型号">{{
                  item.brandModel || '无'
                }}</el-descriptions-item>
                <el-descriptions-item label="运行状态">
                  <el-select
                    v-model="item.runningStatus"
                    :disabled="isDisabled"
                    style="width: 150px"
                  >
                    <el-option
                      v-for="status of runStatusArray"
                      :key="status.key"
                      :label="status.value"
                      :value="status.key"
                    ></el-option>
                  </el-select>
                </el-descriptions-item>
                <el-descriptions-item label="类型">
                  {{ item._typename || '无' }}
                </el-descriptions-item>
              </el-descriptions>
            </div>
            <div style="display: flex">
              <!-- <div class="sub-title">{{ item.name }}</div> -->
              <!-- å›¾ç‰‡ -->
              <div class="image-container">
                <div
                  class="block-div"
                  @click="onClickPic($event)"
                  v-for="(status, index) in item._statusList"
                  :key="index"
            <el-tab-pane
              v-for="item in deviceTopTypes"
              :key="item.id"
              :name="item.id"
            >
              <template #label>
                <el-badge
                  :value="item.count"
                  :type="item.count == 0 ? 'danger' : 'primary'"
                >
                  <el-image
                    v-if="index == 0"
                    fit="cover"
                    class="pic-style"
                    :src="status._picUrl"
                    :preview-src-list="Array.of(status._picUrl)"
                  />
                  <span class="abstract_pic_text" v-if="index == 0">{{
                    `最新状态图片 ${status.dlCreateTime.slice(0, 10)}`
                  }}</span>
                  <span class="custom-tabs-label">
                    <span>{{ item.label }}</span>
                  </span>
                </el-badge>
              </template>
            </el-tab-pane>
          </el-tabs>
        </el-col>
      </el-row>
      <el-collapse v-model="activeNames" style="border: 4px">
        <el-collapse-item
          v-for="item in formInfo"
          :key="item.id"
          :name="item.id"
          class="collapse-item-class"
        >
          <template #title>
            <div
              style="display: flex; width: 100%; justify-content: space-between"
            >
              <div style="">
                <el-descriptions style="" :column="3" size="small" border>
                  <el-descriptions-item
                    width="64px"
                    :label="
                      currSelect.topDeviceTypeId == 0 ? '站点名称' : '设备名称'
                    "
                    :span="3"
                    >{{ item.name || '无' }}</el-descriptions-item
                  >
                  <el-descriptions-item label="供应商">{{
                    item.supplier || '无'
                  }}</el-descriptions-item>
                  <el-descriptions-item label="运维商">{{
                    item.maintainer || '无'
                  }}</el-descriptions-item>
                  <el-descriptions-item label="运维频次">
                    <el-select
                      v-model="item.maintainFrequency"
                      :disabled="isDisabled"
                      style="width: 150px"
                    >
                      <el-option
                        v-for="frequency of maintainFrequencysArray"
                        :key="frequency.key"
                        :label="frequency.value"
                        :value="frequency.key"
                      ></el-option>
                    </el-select>
                  </el-descriptions-item>
                  <el-descriptions-item label="运维人员">{{
                    item.maintainStaff || '无'
                  }}</el-descriptions-item>
                  <el-descriptions-item label="运维联系方式">{{
                    item.maintainTel || '无'
                  }}</el-descriptions-item>
                  <el-descriptions-item label="品牌型号">{{
                    item.brandModel || '无'
                  }}</el-descriptions-item>
                  <el-descriptions-item label="运行状态">
                    <el-select
                      v-model="item.runningStatus"
                      :disabled="isDisabled"
                      style="width: 150px"
                    >
                      <el-option
                        v-for="status of runStatusArray"
                        :key="status.key"
                        :label="status.value"
                        :value="status.key"
                      ></el-option>
                    </el-select>
                  </el-descriptions-item>
                  <el-descriptions-item label="类型">
                    {{ item._typename || '无' }}
                  </el-descriptions-item>
                </el-descriptions>
              </div>
              <div style="display: flex">
                <!-- <div class="sub-title">{{ item.name }}</div> -->
                <!-- å›¾ç‰‡ -->
                <div class="image-container">
                  <div
                    class="block-div"
                    @click="onClickPic($event)"
                    v-for="(status, index) in item._statusList"
                    :key="index"
                  >
                    <el-image
                      v-if="index == 0"
                      fit="cover"
                      class="pic-style"
                      :src="status._picUrl"
                      :preview-src-list="Array.of(status._picUrl)"
                    />
                    <span class="abstract_pic_text" v-if="index == 0">{{
                      `最新状态图片 ${status.dlCreateTime.slice(0, 10)}`
                    }}</span>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </template>
        <!-- è¯¦ç»†å†…容开始 -->
        <el-form :model="item" class="form_class">
          <el-form-item label="状态">
            <el-tabs tab-position="top">
              <el-tab-pane
                v-for="(status, i) in item._statusList"
                :label="status.dlCreateTime.slice(0, 10)"
                :key="i"
              >
                <el-form :model="status" class="form-class">
                  <el-form-item label="位置" style="margin-bottom: 10px">
                    {{ status.dlLocation }}
                  </el-form-item>
                  <el-form-item label="图片">
                    <!-- å›¾ç‰‡ -->
                    <el-space>
                      <div v-if="status._paths && status._paths.length > 0">
                        <el-image
                          v-for="(path, i) in status._paths"
                          fit="cover"
                          class="pic-style"
                          :src="path"
                          :preview-src-list="Array.of(path)"
                          :key="i"
                        />
                      </div>
                      <el-empty v-else></el-empty>
                    </el-space>
                  </el-form-item>
                </el-form>
              </el-tab-pane>
            </el-tabs>
          </el-form-item>
        </el-form>
        <!-- è¯¦ç»†å†…容结束 -->
      </el-collapse-item>
    </el-collapse>
    <!-- ç©ºçŠ¶æ€ -->
    <el-empty v-if="isEmpty" />
  </div>
          </template>
          <!-- è¯¦ç»†å†…容开始 -->
          <el-form :model="item" class="form_class">
            <el-form-item label="状态">
              <el-tabs tab-position="top">
                <el-tab-pane
                  v-for="(status, i) in item._statusList"
                  :label="status.dlCreateTime.slice(0, 10)"
                  :key="i"
                >
                  <el-form :model="status" class="form-class">
                    <el-form-item label="位置" style="margin-bottom: 10px">
                      {{ status.dlLocation }}
                    </el-form-item>
                    <el-form-item label="图片">
                      <!-- å›¾ç‰‡ -->
                      <el-space>
                        <div v-if="status._paths && status._paths.length > 0">
                          <el-image
                            v-for="(path, i) in status._paths"
                            fit="cover"
                            class="pic-style"
                            :src="path"
                            :preview-src-list="Array.of(path)"
                            :key="i"
                          />
                        </div>
                        <el-empty v-else></el-empty>
                      </el-space>
                    </el-form-item>
                  </el-form>
                </el-tab-pane>
              </el-tabs>
            </el-form-item>
          </el-form>
          <!-- è¯¦ç»†å†…容结束 -->
        </el-collapse-item>
      </el-collapse>
      <!-- ç©ºçŠ¶æ€ -->
      <el-empty v-if="isEmpty"
    /></template>
  </CompGenericWrapper>
</template>
<script>
@@ -165,7 +172,7 @@
import { $fysp } from '@/api/index';
import { toLabel } from '@/enum/device/device';
export default {
  components: {},
  components: {  },
  watch: {
    // é€‰æ‹©æ”¹å˜ç›‘听
    currSelect: {
src/views/fysp/check/components/CompLedgerPhoto.vue
@@ -1,5 +1,6 @@
<template>
  <FYImageSelectDialog
    v-loading="loading"
    title="台账图片"
    :typeList="typeList"
    :typeImgMap="typeImgMap"
@@ -11,7 +12,7 @@
import userApi from '@/api/fysp/userApi.js';
import { svToTz } from '@/enum/scene';
import { $fytz } from '@/api/index';
import { useCloned } from '@vueuse/core';
const loading = ref(true)
const props = defineProps({
  // å±•示模式
  mode: {
@@ -27,6 +28,7 @@
const typeImgMap = ref(new Map());
function getList() {
  userApi.getTzId(props.subtask.sceneId).then((res) => {
    loading.value = true
    let tzUserId = res.tzUserId;
    problemApiFytz
@@ -62,7 +64,7 @@
            typeImgMap.value.get(type.typeId).push(item);
          });
        }
      });
      }).finally(() => loading.value = false);
  });
}
function getMonth() {
src/views/fysp/check/components/CompLedgerPic.vue
ÎļþÒÑɾ³ý
src/views/fysp/check/components/CompProRecent.vue
@@ -1,15 +1,24 @@
<template>
  <div>
    <el-tabs v-model="activeName" type="card">
      <el-tab-pane v-for="(item, i) in ranges" :key="i" :label="item" :name="item"> </el-tab-pane>
    </el-tabs>
    <div class="proList">
      <el-card class="card-style" shadow="hover">
        <el-descriptions v-loading="loading">
          <el-descriptions-item label="总出现次数">{{ curProList.length }}</el-descriptions-item>
          <!-- <el-descriptions-item label="复现率">{{ repeteRate }}%</el-descriptions-item> -->
        </el-descriptions>
        <!-- <el-descriptions v-loading="loading" column="3">
  <CompGenericWrapper type="dialog">
    <template #content>
      <el-tabs v-model="activeName" type="card">
        <el-tab-pane
          v-for="(item, i) in ranges"
          :key="i"
          :label="item"
          :name="item"
        >
        </el-tab-pane>
      </el-tabs>
      <div class="proList">
        <el-card class="card-style" shadow="hover" v-loading="loading">
          <el-descriptions>
            <el-descriptions-item label="总出现次数">{{
              curProList.length
            }}</el-descriptions-item>
            <!-- <el-descriptions-item label="复现率">{{ repeteRate }}%</el-descriptions-item> -->
          </el-descriptions>
          <!-- <el-descriptions v-loading="loading" column="3">
          <div v-for="pro in curProList">
            <el-descriptions-item>{{ pro.problemname }}</el-descriptions-item>
            <el-descriptions-item label="任务名称">{{ pro._stName }}</el-descriptions-item>
@@ -18,34 +27,32 @@
            </el-descriptions-item>
          </div>
        </el-descriptions> -->
        <el-table :data="curProList" style="width: 100%">
          <el-table-column type="index" width="50" />
          <el-table-column prop="problemname" label="问题"/>
          <el-table-column prop="_time" label="时间" width="250" />
          <el-table-column label="操作" width="180">
            <template v-slot="scope">
              <el-button link type="primary" @click="info(scope.row)">详情</el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-card>
      <el-dialog
          <el-table :data="curProList" style="width: 100%">
            <el-table-column type="index" width="50" />
            <el-table-column prop="problemname" label="问题" />
            <el-table-column prop="_time" label="时间" width="250" />
            <el-table-column label="操作" width="180">
              <template v-slot="scope">
                <el-button link type="primary" @click="info(scope.row)"
                  >详情</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </div>
      <CompProblemAddOrUpd
        v-model:visible="proAddOrUpdDialogVisible"
        title="预览"
        v-model="proAddOrUpdDialogVisible"
        :before-close="proAddOrUpdDialogClose"
        width="80%"
      >
        <CompProblemAddOrUpd
          v-if="proAddOrUpdDialogVisible"
          :subtask="subtask"
          :topTask="topTask"
          :problem="previewPro"
          :readonly="true"
          ref="compProblemAddOrUpdRef"
        />
      </el-dialog>
    </div>
  </div>
        :subtask="subtask"
        :topTask="topTask"
        :problem="previewPro"
        :readonly="true"
        ref="compProblemAddOrUpdRef"
      />
      <el-dialog destroy-on-close> </el-dialog>
    </template>
  </CompGenericWrapper>
</template>
<script>
import CompProblemAddOrUpd from './CompProblemAddOrUpd.vue';
@@ -54,7 +61,7 @@
export default {
  computed: {
    // repeteRate() {
    //   return this.curProList.length !== 0 ? (this.curProList.length - 1) / this.subtaskCount * 1.0 : 0
    //   return this.curProList.length !== 0 ? (this.curProList.length - 1) / this.subtaskCount * 1.0 : 0
    // },
  },
  props: {
@@ -80,16 +87,19 @@
      handler(newObj, oldObj) {
        this.handleClick();
      }
    },
    problem: {
      handler(nv, ov) {
        this.deepCopyPro = useCloned(this.problem).cloned.value;
        this.getRecentPros();
      },
      immediate: true
    }
  },
  components: {
    CompProblemAddOrUpd
    CompProblemAddOrUpd,
  },
  mounted() {
    this.deepCopyPro = useCloned(this.problem).cloned.value;
    this.getRecentPros();
  },
  mounted() {},
  data() {
    return {
      proAddOrUpdDialogVisible: false,
@@ -114,10 +124,6 @@
    info(pro) {
      this.previewPro = pro;
      this.proAddOrUpdDialogVisible = true;
    },
    // å…³é—­è¯¦æƒ…弹窗
    proAddOrUpdDialogClose() {
      this.proAddOrUpdDialogVisible = false;
    },
    // åˆ‡æ¢æ—¶é—´èŒƒå›´
    handleClick() {
@@ -153,17 +159,19 @@
     * */
    async getRecentPros() {
      this.loading = true;
      this.subtaskCount = 0
      this.subtaskCount = 0;
      // èŽ·å–å­ä»»åŠ¡åˆ—è¡¨
      await taskApi.getSubtaskByScene(this.generateQueryParam()).then((subtasks) => {
        this.curProList = [];
        if (subtasks) {
          subtasks.forEach((subtask) => {
            // èŽ·å–é—®é¢˜åˆ—è¡¨
            this.getProBySubtask(subtask);
          });
        }
      });
      await taskApi
        .getSubtaskByScene(this.generateQueryParam())
        .then((subtasks) => {
          this.curProList = [];
          if (subtasks) {
            subtasks.forEach((subtask) => {
              // èŽ·å–é—®é¢˜åˆ—è¡¨
              this.getProBySubtask(subtask);
            });
          }
        });
      // é¢å¤–处理
      this.curProList.sort((o1, o2) => o2.getDate() - o1.getDate());
      this.loading = false;
@@ -175,7 +183,7 @@
          pros.forEach((pro) => {
            if (pro.ptguid == this.deepCopyPro.ptguid) {
              pro._stName = subtask.stName;
              pro._time = this.$fm.formatYMD(subtask.stPlanTime)
              pro._time = this.$fm.formatYMD(subtask.stPlanTime);
              this.curProList.push(pro);
            }
          });
src/views/fysp/check/components/CompProblemAddOrUpd.vue
@@ -1,210 +1,236 @@
<template>
  <div class="main-container">
    <el-form :model="problem" label-width="auto" style="max-width: 95%">
      <el-form-item label="问题位置" prop="locationid">
        <el-select
          v-model="deepCopyProblem.locationid"
          @change="onProLocationChange"
          class="row"
          :disabled="readonly"
  <CompGenericWrapper type="dialog">
    <template #content>
      <div class="main-container">
        <el-form
          :rules="rules"
          :model="deepCopyProblem"
          label-width="auto"
          style="max-width: 95%"
          ref="formRef"
        >
          <el-option
            v-for="item in posList"
            :key="item.index"
            :label="item.text"
            :value="item.index"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="问题类型" prop="proType">
        <el-select
          v-model="proType"
          @change="onProTypeChange"
          class="row"
          :disabled="readonly"
          <el-form-item label="问题位置" prop="locationid">
            <el-select
              v-model="deepCopyProblem.locationid"
              @change="onProLocationChange"
              class="row"
              :disabled="readonly"
            >
              <el-option
                v-for="item in posList"
                :key="item.index"
                :label="item.text"
                :value="item.index"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="问题类型" prop="_proType">
            <el-select
              v-model="deepCopyProblem._proType"
              @change="onProTypeChange"
              class="row"
              :disabled="readonly"
            >
              <el-option
                v-for="item in problemTypeOptions"
                :key="item.typeid"
                :label="item.typename"
                :value="item.typename"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="问题描述" prop="description">
            <el-select
              v-model="deepCopyProblem.description"
              @change="onProDesChange"
              class="row"
              :disabled="readonly"
            >
              <el-option
                v-for="item in descriptionOptions"
                :key="item.guid"
                :label="item.description"
                :value="item.description"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="补充说明" :disabled="readonly" prop="proRemark">
            <el-input
              v-model="proRemark"
              type="textarea"
              @change="onProRemarkChange"
              class="row"
              placeholder="请输入"
              :disabled="readonly"
            />
          </el-form-item>
          <el-form-item label="问题建议" prop="advice">
            <el-select
              v-model="deepCopyProblem.advice"
              class="row"
              :disabled="readonly"
              @change="onProAdviseChange"
            >
              <el-option
                v-for="item in adviseOptions"
                :key="item.adGuid"
                :label="item.adName"
                :value="item.adName"
              />
            </el-select>
          </el-form-item>
          <el-form-item
            label="问题建议修正"
            prop="_adviseEdit"
            :disabled="false"
          >
            <el-input
              v-model="deepCopyProblem._adviseEdit"
              type="textarea"
              @change="onProAdviseEditChange"
              class="row"
              placeholder="请输入问题建议修正"
              :disabled="readonly"
            />
          </el-form-item>
          <el-form-item label="问题图片">
            <el-row>
              <el-col>
                <el-button
                  @click="chosePicFromAnyPic"
                  v-show="!readonly"
                  :disabled="fileList.length >= 3"
                  >从场景图片选取</el-button
                >
                <el-button
                  @click="chosePicFromDevicePic"
                  v-show="!readonly"
                  :disabled="fileList.length >= 3"
                  >从设备图片选取</el-button
                >
                <el-button
                  @click="chosePicFromLedgerPic"
                  v-show="!readonly"
                  :disabled="fileList.length >= 3"
                  >从台账选取</el-button
                >
                <el-button
                  @click="choseChangePic"
                  v-show="!readonly"
                  :disabled="fileList.length >= 3"
                  >从文件夹选取</el-button
                >
              </el-col>
              <el-col v-if="!fileList || fileList.length <= 0">
                <el-empty
                  style="height: 145px"
                  class="img-upload"
                  description="请添加图片"
                />
              </el-col>
              <el-col>
                <el-upload
                  v-show="fileList && fileList.length > 0"
                  class="img-upload"
                  ref="uploadRef"
                  v-model:file-list="fileList"
                  list-type="picture-card"
                  multiple
                  :auto-upload="false"
                  crossorigin="Anonymous"
                  :before-remove="beforeRemoveFile"
                  :on-preview="handlePictureCardPreview"
                  :disabled="readonly"
                  accept="image/*"
                >
                  <template #trigger v-if="fileList.length < 3 && !readonly">
                    <el-button
                      v-if="fileList.length < 3"
                      type="primary"
                      id="uploadBtnId"
                      style="display: none"
                    ></el-button>
                    <el-icon>
                      <Plus />
                    </el-icon>
                  </template>
                  <template #tip>
                    <div style="color: #f56c6c">
                      æœ€å°‘上传一张图片,最多选择三张图片
                    </div>
                  </template>
                </el-upload>
              </el-col>
            </el-row>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onSubmit" v-show="!readonly"
              >保存</el-button
            >
            <el-button @click="onCancel" v-show="!readonly"
              >取消</el-button
            >
          </el-form-item>
        </el-form>
        <ArbitraryPhoto
          :max-select="maxSelectImgCount - fileList.length"
          v-model:dialog-visible="anyPhotoDialog"
          @submit="handleSelectedAnyPhono"
          :subtask="subtask"
          :defaultFile="fileList"
          ref="arbitraryPhotoRef"
        >
          <el-option
            v-for="item in problemTypeOptions"
            :key="item.typeid"
            :label="item.typename"
            :value="item.typename"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="问题描述" prop="description">
        <el-select
          v-model="deepCopyProblem.description"
          @change="onProDesChange"
          class="row"
          :disabled="readonly"
        </ArbitraryPhoto>
        <CompLedgerPhoto
          :max-select="maxSelectImgCount - fileList.length"
          v-model:dialog-visible="ledgerPicDialog"
          @submit="handleLedgerPicPhono"
          :subtask="subtask"
          :defaultFile="fileList"
          ref="ledgerPhotoRef"
        ></CompLedgerPhoto>
        <CompDevicePhoto
          :max-select="maxSelectImgCount - fileList.length"
          v-model:dialog-visible="deiveceImgDialog"
          @submit="handleSelectedDevicePhono"
          :subtask="subtask"
          :defaultFile="fileList"
          ref="deiveceImgDialogRef"
        >
          <el-option
            v-for="item in descriptionOptions"
            :key="item.guid"
            :label="item.description"
            :value="item.description"
          />
        </el-select>
      </el-form-item>
      <el-form-item label="补充说明" :disabled="readonly" prop="proRemark">
        <el-input
          v-model="proRemark"
          type="textarea"
          @change="onProRemarkChange"
          class="row"
          placeholder="请输入"
          :disabled="readonly"
        </CompDevicePhoto>
        <el-image-viewer
          v-if="previewDialogVisible"
          :url-list="fileList.map((item) => item.url)"
          :initial-index="initialIndex"
          @close="previewDialogVisible = false"
          alt="预览"
          class="preview-pic"
        />
      </el-form-item>
      <el-form-item label="问题建议" prop="advise">
        <el-select
          v-model="deepCopyProblem.advise"
          class="row"
          :disabled="readonly"
          @change="onProAdviseChange"
        >
          <el-option
            v-for="item in adviseOptions"
            :key="item.adGuid"
            :label="item.adName"
            :value="item.adName"
          />
        </el-select>
      </el-form-item>
      <el-form-item
        v-show="deepCopyProblem.advise && deepCopyProblem.advise != ''"
        label="问题建议修正"
        prop="_adviseEdit"
        :disabled="false"
      >
        <el-input
          v-model="deepCopyProblem._adviseEdit"
          type="textarea"
          @change="onProAdviseEditChange"
          class="row"
          placeholder="请输入问题建议修正"
          :disabled="readonly"
        />
      </el-form-item>
      <div class="t-card_item">
        é—®é¢˜å›¾ç‰‡&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        <div>
          <el-button
            @click="chosePicFromAnyPic"
            v-show="!readonly"
            :disabled="fileList.length >= 3"
            >从场景图片选取</el-button
          >
          <el-button
            @click="chosePicFromDevicePic"
            v-show="!readonly"
            :disabled="fileList.length >= 3"
            >从设备图片选取</el-button
          >
          <el-button
            @click="chosePicFromLedgerPic"
            v-show="!readonly"
            :disabled="fileList.length >= 3"
            >从台账选取</el-button
          >
          <el-button
            @click="choseChangePic"
            v-show="!readonly"
            :disabled="fileList.length >= 3"
            >从文件夹选取</el-button
          >
        </div>
        <!-- <el-dialog v-model="previewDialogVisible">
        </el-dialog> -->
      </div>
      <el-upload
        class="img-upload"
        ref="uploadRef"
        v-model:file-list="fileList"
        list-type="picture-card"
        multiple
        :auto-upload="false"
        crossorigin="Anonymous"
        :before-remove="beforeRemoveFile"
        :on-preview="handlePictureCardPreview"
        :disabled="readonly"
        accept="image/*"
      >
        <template #trigger v-if="fileList.length < 3 && !readonly">
          <el-button
            v-if="fileList.length < 3"
            type="primary"
            id="uploadBtnId"
            style="display: none"
          ></el-button>
          <el-icon>
            <Plus />
          </el-icon>
        </template>
        <template #tip>
          <div style="color: #f56c6c">最少上传一张图片,最多选择三张图片</div>
        </template>
      </el-upload>
      <el-form-item>
        <el-button type="primary" @click="onSubmit" v-show="!readonly"
          >保存</el-button
        >
        <el-button @click="this.$emit('submited', false)" v-show="!readonly"
          >取消</el-button
        >
      </el-form-item>
    </el-form>
    <ArbitraryPhoto
      :max-select="maxSelectImgCount - fileList.length"
      v-if="anyPhotoDialog"
      v-model:dialog-visible="anyPhotoDialog"
      @submit="handleSelectedAnyPhono"
      :subtask="subtask"
      :defaultFile="fileList"
      ref="arbitraryPhotoRef"
    >
    </ArbitraryPhoto>
    <CompLedgerPhoto
      :max-select="maxSelectImgCount - fileList.length"
      v-if="ledgerPicDialog"
      v-model:dialog-visible="ledgerPicDialog"
      @submit="handleLedgerPicPhono"
      :subtask="subtask"
      :defaultFile="fileList"
      ref="ledgerPhotoRef"
    ></CompLedgerPhoto>
    <CompDevicePhoto
      :max-select="maxSelectImgCount - fileList.length"
      v-if="deiveceImgDialog"
      v-model:dialog-visible="deiveceImgDialog"
      @submit="handleSelectedDevicePhono"
      :subtask="subtask"
      :defaultFile="fileList"
      ref="deiveceImgDialogRef"
    >
    </CompDevicePhoto>
    <el-dialog v-model="previewDialogVisible">
      <img w-full :src="previewDialogImageUrl" alt="预览" class="preview-pic" />
    </el-dialog>
  </div>
    </template>
  </CompGenericWrapper>
</template>
<script>
import ArbitraryPhoto from './ArbitraryPhoto.vue';
import LedgerPic from './CompLedgerPic.vue';
import CompLedgerPhoto from './CompLedgerPhoto.vue';
import CompDevicePhoto from './CompDevicePhoto.vue';
import problemApi from '@/api/fysp/problemApi.js';
import { $fysp } from '@/api/index.js';
import fileUtil from '@/utils/fileUtils.js';
import {  useCloned } from '@vueuse/core';
import { useCloned } from '@vueuse/core';
import { ElMessage } from 'element-plus';
import deviceApi from '@/api/fysp/deviceApi';
import { useFormConfirm } from '@/composables/formConfirm';
export default {
  emits: ['submit', 'cancel'],
  components: {
    ArbitraryPhoto,
    CompDevicePhoto,
    CompLedgerPhoto
    CompLedgerPhoto,
  },
  props: {
    readonly: {
@@ -235,6 +261,10 @@
  },
  data() {
    return {
      // fixme 2024.11.20 å­ç»„件初始化时机问题
      initPropsCount: 0,
      // åˆå§‹é¢„览图片index
      initialIndex: -1,
      // å›¾ç‰‡é€‰æ‹©æœ€å¤§æ•°é‡
      maxSelectImgCount: 3,
      previewDialogVisible: false,
@@ -261,7 +291,7 @@
      month: -1,
      ledgerPicDialog: false,
      rules: {
        proType: {
        _proType: {
          required: true,
          message: '问题类型不能为空',
          trigger: 'change'
@@ -276,14 +306,9 @@
          message: '问题位置不能为空',
          trigger: 'change'
        },
        advise: {
        advice: {
          required: true,
          message: '问题建议不能为空',
          trigger: 'change'
        },
        proRemark: {
          required: true,
          message: '补充说明不能为空',
          trigger: 'change'
        }
      },
@@ -302,13 +327,37 @@
      },
      deep: true
    },
    // å½“问题建议改变时问题建议修正跟着改变
    deepCopyProblem: {
    initPropsCount: {
      handler(nv, ov) {
        // å›¾ç‰‡æ ¡éªŒ
        nv._adviseEdit = ov.advise;
        if (nv >= 3) {
          this.initOptions();
        }
      },
      deep: true
      immediate: true
    },
    problem: {
      handler(nv, ov) {
        if (nv != null && nv != undefined) {
          this.initPropsCount++;
        }
      },
      immediate: true
    },
    topTask: {
      handler(nv, ov) {
        if (nv != null && nv != undefined) {
          this.initPropsCount++;
        }
      },
      immediate: true
    },
    subtask: {
      handler(nv, ov) {
        if (nv != null && nv != undefined) {
          this.initPropsCount++;
        }
      },
      immediate: true
    }
  },
  computed: {
@@ -316,7 +365,7 @@
      const descriptions = [];
      this.problemTypeList.forEach((item) => {
        if (item.typename == this.proType) {
        if (item.typename == this.deepCopyProblem._proType) {
          descriptions.push(item);
        }
      });
@@ -333,123 +382,37 @@
      }, []);
    },
    adviseOptions() {
      console.log(this.currProTypeGuid, this.problem.guid, this.suggestions);
      let problemGuid = this.currProTypeGuid || this.problem.guid;
      let array = this.suggestions.filter(
        (item) => item.adProblemtypeguid == problemGuid
      );
      console.log(
        this.suggestions.filter(
          (item) => item.adProblemtypeguid == problemGuid
        ),
        this.adviseOptions
      );
      return array;
    }
  },
  mounted() {
    this.initOptions();
    this.getDeviceImgList();
  },
  mounted() {},
  methods: {
    onProAdviseChange(value) {
      this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advise;
      this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advice;
    },
    handlePictureCardPreview(uploadFile) {
      this.initialIndex = this.fileList.indexOf(uploadFile);
      this.previewDialogVisible = true;
      this.previewDialogImageUrl = uploadFile.url;
    },
    beforeDeiveceImgDialogclose() {
      this.deiveceImgDialog = false;
    },
    // æ ‡å‡†åŒ–属性名
    convertKeys(obj) {
      // å°†ä¸€ä¸ªjs对象中所有di,wi,pi开头的属性全部改成去掉这些前缀并且重新变为驼峰式命名
      const newObj = {};
      for (const key in obj) {
        let newKey = key;
        if (key.startsWith('di')) {
          newKey = key.substring(2);
        } else if (key.startsWith('wi')) {
          newKey = key.substring(2);
        } else if (key.startsWith('pi')) {
          newKey = key.substring(2);
        }
        newKey = newKey.charAt(0).toLowerCase() + newKey.slice(1);
        newObj[newKey] = obj[key];
      }
      return newObj;
    },
    // ä¿å­˜çŠ¶æ€ä¿¡æ¯
    saveStatus(device, status) {
      var _picUrl = $fysp.imgUrl + status.dlPicUrl;
      device._picUrl = _picUrl;
      status._picUrl = _picUrl;
      if ('_statusList' in device) {
        device._statusList.push(status);
      } else {
        device._statusList = Array.of(status);
      }
      // æŽ’序
      device._statusList.sort(function (x, y) {
        return new Date(x.dlCreateTime) - new Date(y.dlCreateTime); //    é™åºï¼Œå‡åºåˆ™åä¹‹
      });
    },
    async getDeviceImgList() {
      this.deviceImgObjList = [];
      for (const deviceTopTypeElement of this.deviceTopTypes) {
        const topTypeId = deviceTopTypeElement.id;
        await deviceApi
          .fetchDevices(this.subtask.sceneId, topTypeId)
          .then((result) => {
            // æ ‡å‡†åŒ–属性名
            for (let i = 0; i < result.data.length; i++) {
              var element = this.convertKeys(result.data[i]);
              // èŽ·å–è®¾å¤‡çŠ¶æ€ä¿¡æ¯
              let data = {
                deviceId: element.id,
                sceneId: element.sceneGuid,
                deviceTypeId: topTypeId
              };
              deviceApi
                .fetchDeviceStatus(data)
                .then((status) => {
                  var statusData = status.data;
                  var imgPaths = [];
                  if (statusData) {
                    if (statusData.length == 0) {
                      this.deviceImgObjList.push(element);
                      return;
                    }
                    element = this.convertKeys(result.data[i]);
                    for (let j = 0; j < statusData.length; j++) {
                      // å¤åˆ¶å‡ºä¸€ä¸ªè®¾å¤‡å¯¹è±¡
                      var newDevice = useCloned(element).cloned.value;
                      const statusItem = statusData[j];
                      // è®¾å¤‡å¯¹è±¡æ·»åŠ ä¸€ä¸ªå±žæ€§åˆ—è¡¨å±žæ€§ç”¨æ¥ä¿å­˜è®¾å¤‡çŠ¶æ€
                      this.saveStatus(newDevice, statusItem);
                      newDevice.dlLocation = statusItem.dlLocation;
                      newDevice.topTypeId = topTypeId;
                      this.deviceImgObjList.push(newDevice);
                    }
                  }
                })
                .catch((err) => {});
            }
          });
      }
    },
    initOptions() {
      if (!this.problem || !this.subtask || !this.topTask) {
        return;
      }
      if (this.problem == undefined || this.problem == null) {
        this.deepCopyProblem = {};
      } else {
        this.deepCopyProblem = useCloned(this.problem).cloned.value;
        this.currProTypeGuid = this.problem.guid;
        this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advise;
        this.deepCopyProblem.advice = this.deepCopyProblem.advise;
        this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advice;
      }
      this.type = 'guid' in this.deepCopyProblem ? 1 : 0;
@@ -471,7 +434,7 @@
            currDescription = currProName;
            this.problemTypeList.forEach((item) => {
              if (item.description == currDescription) {
                this.proType = item.typename;
                this.deepCopyProblem._proType = item.typename;
              }
            });
            this.deepCopyProblem.description = currDescription;
@@ -484,7 +447,7 @@
            this.problemTypeList.forEach((item) => {
              if (item.description === currDescription) {
                this.proType = item.typename;
                this.deepCopyProblem._proType = item.typename;
              }
            });
            this.deepCopyProblem.description = currDescription;
@@ -531,6 +494,7 @@
      }
    },
    handleLedgerPicPhono(data) {
      this.beforeLedgerPicDialogclose();
      let isExist = false;
      for (const item of data) {
        for (const already of this.fileList) {
@@ -572,8 +536,9 @@
      // é»˜è®¤é—®é¢˜æè¿°å’Œé—®é¢˜å»ºè®®ä¸ºç¬¬ä¸€ä¸ª
      this.currProTypeGuid = this.descriptionOptions[0].guid;
      this.deepCopyProblem.description = this.descriptionOptions[0].description;
      this.deepCopyProblem.advise = this.adviseOptions[0].adName;
      this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advise;
      this.onProDesChange(this.deepCopyProblem.description);
      this.deepCopyProblem.advice = this.adviseOptions[0].adName;
      this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advice;
    },
    findProByProDesName(name) {
      let result;
@@ -586,15 +551,15 @@
    },
    onProDesChange(value) {
      let currPro = this.findProByProDesName(value);
      this.deepCopyProblem.advise = '';
      this.currProTypeGuid = currPro.guid;
      // this.deepCopyProblem.description = currPro.description;
      this.changeProblemname();
      this.deepCopyProblem.advise = '';
      var adName =
        this.adviseOptions.length == 0 ? '' : this.adviseOptions[0].adName;
      this.deepCopyProblem.advise = adName;
      this.deepCopyProblem.advice = adName;
      this.$nextTick(() => {
        this.deepCopyProblem._adviseEdit = this.deepCopyProblem.advice;
      });
    },
    onProLocationChange(value) {
      this.posList.forEach((item) => {
@@ -620,70 +585,78 @@
      }
      return true;
    },
    // TODO
    validateForm() {},
    onCancel() {
      this.$emit("cancel")
      this.$emit('update:visible', false)
    },
    onSubmit() {
      this.validateForm();
      // å›¾ç‰‡æ ¡éªŒ
      if (!this.pictureValidate()) {
        return;
      }
      // æ•°æ®å‡†å¤‡
      let deepCopyPro = useCloned(this.deepCopyProblem).cloned.value;
      let data = new FormData();
      var picUrls = [];
      this.fileList.forEach((item) => {
        if (!('guid' in item)) {
          // æ–°çš„
          let exclude = false;
          for (let index = 0; index < this.oldFileList.length; index++) {
            const element = this.oldFileList[index];
            if (item.url == element.url) {
              exclude = true;
              break;
      this.$refs.formRef.validate((valid) => {
        if (valid && this.pictureValidate()) {
          // æ•°æ®å‡†å¤‡
          let deepCopyPro = useCloned(this.deepCopyProblem).cloned.value;
          let data = new FormData();
          var picUrls = [];
          this.fileList.forEach((item) => {
            if (!('guid' in item)) {
              // æ–°çš„
              let exclude = false;
              for (let index = 0; index < this.oldFileList.length; index++) {
                const element = this.oldFileList[index];
                if (item.url == element.url) {
                  exclude = true;
                  break;
                }
              }
              if (!exclude) {
                picUrls.push(item.url);
              }
              exclude = false;
              // picUrls.push(item)
            }
          });
          if (this.type == 1) {
            let deleteImgCopy = this.deleteImg;
            fileUtil.getImageFiles(picUrls, function (files) {
              data.append('deleteImg', deleteImgCopy);
              deepCopyPro.advise = deepCopyPro.advice;
              delete deepCopyPro['advice'];
              delete deepCopyPro['mediafileList'];
              delete deepCopyPro['description'];
              delete deepCopyPro['_adviseEdit'];
              delete deepCopyPro['_proType'];
              delete deepCopyPro['proType'];
              data.append('problem', JSON.stringify(deepCopyPro));
              files.forEach((image) => {
                data.append('images', image);
              });
              problemApi.updateProblem(data).then((res) => {});
            });
            this.$emit('submit', false);
          } else {
            const deepCopySubTask = useCloned(this.subtask).cloned.value;
            const that = this;
            fileUtil.getImageFiles(picUrls, function (files) {
              deepCopyPro.insGuid = deepCopySubTask.insGuid;
              delete deepCopyPro['description'];
              deepCopyPro.proName = deepCopyPro.problemname;
              delete deepCopyPro['problemname'];
              deepCopyPro.ptGuid = that.findProTypeByGuid(
                that.currProTypeGuid
              ).guid;
              deepCopyPro.locationId = deepCopyPro.locationid;
              delete deepCopyPro['locationid'];
              delete deepCopyPro['_adviseEdit'];
              delete deepCopyPro['_proType'];
              data.append('problemVo', JSON.stringify(deepCopyPro));
              files.forEach((image) => {
                data.append('images', image);
              });
              problemApi.newProblem(data).then((res) => {});
            });
            this.$emit('submit', true);
          }
          if (!exclude) {
            picUrls.push(item.url);
          }
          exclude = false;
          // picUrls.push(item)
        }
      });
      if (this.type == 1) {
        let deleteImgCopy = this.deleteImg;
        fileUtil.getImageFiles(picUrls, function (files) {
          data.append('deleteImg', deleteImgCopy);
          delete deepCopyPro['mediafileList'];
          delete deepCopyPro['description'];
          data.append('problem', JSON.stringify(deepCopyPro));
          files.forEach((image) => {
            data.append('images', image);
          });
          problemApi.updateProblem(data).then((res) => {});
        });
      } else {
        const deepCopySubTask = useCloned(this.subtask).cloned.value;
        const that = this;
        fileUtil.getImageFiles(picUrls, function (files) {
          deepCopyPro.insGuid = deepCopySubTask.insGuid;
          delete deepCopyPro['advise'];
          delete deepCopyPro['description'];
          deepCopyPro.proName = deepCopyPro.problemname;
          delete deepCopyPro['problemname'];
          deepCopyPro.ptGuid = that.findProTypeByGuid(
            that.currProTypeGuid
          ).guid;
          deepCopyPro.locationId = deepCopyPro.locationid;
          delete deepCopyPro['locationid'];
          data.append('problemVo', JSON.stringify(deepCopyPro));
          files.forEach((image) => {
            data.append('images', image);
          });
          problemApi.newProblem(data).then((res) => {});
        });
      }
      this.$emit('submited', true);
    },
    handleSelectedAnyPhono(data) {
      this.beforeAnyPhotoDialogclose();
@@ -753,10 +726,6 @@
    },
    beforeLedgerPicDialogclose() {
      this.ledgerPicDialog = false;
    },
    destoryMyself() {
      this.$destroy();
    }
  }
};
@@ -778,7 +747,6 @@
.img-upload {
  margin-top: 30px;
  margin-bottom: 30px;
  margin-left: 63px;
}
.row {
  width: 100%;
@@ -792,6 +760,10 @@
  height: 100%;
}
::v-deep .el-upload--picture-card {
  border: 0 !important;
  display: none;
}
/* éšè—el-upload上传成功组件 */
::v-deep .el-upload-list__item-status-label {
  display: none !important;
}
</style>
src/views/fysp/check/components/CompProblemCard.vue
@@ -89,91 +89,92 @@
            type="danger"
            size="small"
            @click="deletePro"
            :disabled="!proStatus.deletable"
            disabled
            >删除</el-button
          >
          <el-button
          <!-- <el-button
            type="danger"
            size="small"
            @click="beforePro"
            @click="deletePro"
            :disabled="!proStatus.deletable"
            >删除</el-button
          > -->
          <!-- å®¡æ ¸é©³å›žæ“ä½œ -->
          <!-- <el-button
            v-if="
              this.problem.extension3 == 'fail' ||
              this.problem.extension3 == 'change_fail'
            "
            type="danger"
            size="small"
            @click="revokePro"
            :disabled="proStatus.checkable"
            >撤销</el-button
            >撤销驳回</el-button
          >
          <el-button
            v-else
            type="warning"
            size="small"
            @click="rejectPro"
            :disabled="!proStatus.checkable"
            >驳回</el-button
            >审核驳回</el-button
          > -->
          <el-button
            v-if="
              this.problem.extension3 == 'pass' ||
              this.problem.extension3 == 'change_pass'
            "
            type="danger"
            size="small"
            @click="revokePro"
            :disabled="proStatus.checkable"
            >撤销通过</el-button
          >
          <el-button
            v-else
            type="success"
            size="small"
            @click="passPro"
            :disabled="!proStatus.checkable"
            >通过</el-button
            >审核通过</el-button
          >
        </el-row>
      </el-col>
    </el-row>
  </el-card>
  <div class="dialog-wrapper">
    <el-dialog
      title="问题更正"
      width="50%"
      v-model="proAddOrUpdDialogVisible"
      :before-close="proAddOrUpdDialogClose"
    >
      <CompProblemAddOrUpd
        v-if="proAddOrUpdDialogVisible"
        :problem="deepCopyPro"
        :subtask="deepCopySubtask"
        :topTask="deepCopyTopTask"
        ref="compProblemAddOrUpdRef"
        @submited="onProSubmited"
      />
    </el-dialog>
  </div>
  <el-dialog width="80%" title="整改提交" v-model="addChangeDialogVisible">
    <ComChangeEdit
      :changeType="0"
      v-if="addChangeDialogVisible"
      :problemId="problem.guid"
      :subtask="subtask"
      :month="month"
      @submited="onAddChangeSubmited"
    />
  </el-dialog>
  <el-dialog
    width="50%"
    title="整改检验"
    v-model="changeEditDialogVisible"
    :before-close="changeEditDialogClose"
  >
    <ComChangeEdit
      :changeType="1"
      v-if="changeEditDialogVisible"
      :problemId="problem.guid"
      :oldChangeFileList="problem.mediafileList"
      :subtask="subtask"
      :month="month"
      @submited="onChangeSubmited"
    />
  </el-dialog>
  <CompProblemAddOrUpd
    title="问题更正"
    v-if="proAddOrUpdDialogVisible"
    v-model:visible="proAddOrUpdDialogVisible"
    :problem="deepCopyPro"
    :subtask="subtask"
    :topTask="topTask"
    ref="compProblemAddOrUpdRef"
    @cancel="onProCanceled"
    @submit="onProSubmited"
  />
  <!-- æ•´æ”¹ -->
  <ComChangeEdit
    :title="changeType == 1 ? '整改检验' : '整改提交'"
    v-if="changeDialogVisible"
    v-model:visible="changeDialogVisible"
    :changeType="changeType"
    :problemId="problem.guid"
    :subtask="subtask"
    :month="month"
    :oldChangeFileList="problem.mediafileList"
    @cancel="onChangeCanceled"
    @submit="onChangeSubmited"
  />
  <!-- é—®é¢˜å¤çް -->
  <el-dialog
    width="50%"
  <CompProRecent
    title="问题复现"
    v-model="proRecentDialogVisible"
    :before-close="proRecentDialogClose"
  >
    <CompProRecent
      v-if="proRecentDialogVisible"
      :subtask="subtask"
      :topTask="topTask"
      :problem="problem"
    />
  </el-dialog>
    v-if="proRecentDialogVisible"
    v-model:visible="proRecentDialogVisible"
    :subtask="subtask"
    :topTask="topTask"
    :problem="problem"
  />
</template>
<script>
@@ -185,6 +186,7 @@
import CompProRecent from './CompProRecent.vue';
import { useCloned } from '@vueuse/core';
export default {
  emits: ['check', 'submit', 'cancel'],
  components: {
    CompProblemAddOrUpd,
    ComChangeEdit,
@@ -221,9 +223,10 @@
      default: 1
    }
  },
  emits: ['submit'],
  data() {
    return {
      changeDialogVisible: false,
      changeType: -1,
      addChangeDialogVisible: false,
      // è¿‘期情况
      proRecentDialogVisible: false,
@@ -291,30 +294,18 @@
    }
  },
  methods: {
    onAddChangeSubmited() {
      this.$emit('updated', true);
      this.addChangeDialogVisible = false;
    },
    // è¿‘期情况弹窗关闭
    proRecentDialogClose() {
      this.proRecentDialogVisible = false;
    },
    newProblem() {
      this.proAddOrUpdDialogVisible = true;
    onProCanceled() {
      this.proAddOrUpdDialogVisible = false;
    },
    onProSubmited(isOk) {
      this.$emit('updated', isOk);
      this.$emit('submit', isOk);
      this.proAddOrUpdDialogVisible = false;
    },
    onChangeCanceled() {
    },
    onChangeSubmited(isOk) {
      this.$emit('updated', isOk);
      this.changeEditDialogVisible = false;
    },
    proAddOrUpdDialogClose() {
      this.proAddOrUpdDialogVisible = false;
    },
    changeEditDialogClose() {
      this.changeEditDialogVisible = false;
      this.$emit('submit', isOk);
      this.changeDialogVisible = false;
    },
    deletePro() {
      useMessageBoxTip({
@@ -339,7 +330,7 @@
    passPro() {
      this.checkPro(true);
    },
    beforePro() {
    revokePro() {
      const pro = this.problem;
      let status = this.proStatus;
      let doneMsg;
@@ -359,8 +350,8 @@
            .checkProblem({ pId: pro.guid, action: action })
            .then((res) => {
              if (res.success) {
                pro.extension3 = status;
                this.$emit('submit', false);
                pro.extension3 = status
                this.$emit('check');
              }
            });
        }
@@ -381,20 +372,15 @@
            .checkProblem({ pId: pro.guid, action: action })
            .then((res) => {
              if (res.success) {
                pro.extension3 = status;
                this.$emit('submit', false);
                pro.extension3 = status
                this.$emit('check');
              }
            });
        }
      });
    },
    addChange() {
      this.addChangeDialogVisible = true;
    },
    updatePro() {
      this.deepCopyPro = useCloned(this.problem).cloned.value;
      this.deepCopySubtask = useCloned(this.subtask).cloned.value;
      this.deepCopyTopTask = useCloned(this.topTask).cloned.value;
      this.$nextTick(() => {
        this.proAddOrUpdDialogVisible = true;
      });
@@ -414,10 +400,11 @@
    updateChange() {
      this.getCurrentMouth();
      if (!this.problem.ischanged) {
        this.addChange();
        this.changeType = 0;
      } else {
        this.changeEditDialogVisible = true;
        this.changeType = 1;
      }
      this.changeDialogVisible = true;
    },
    currProRecent() {
      this.proRecentDialogVisible = true;
src/views/fysp/check/components/CompSubTaskStatistic.vue
@@ -1,43 +1,76 @@
<template>
  <el-space>
    <el-descriptions :column="3" size="small" border direction="vertical">
      <el-descriptions-item label="问题数">{{
        summary.proCount
      }}</el-descriptions-item>
      <el-descriptions-item label="整改数">{{
        summary.changeCount
      }}</el-descriptions-item>
      <el-descriptions-item label="整改率">{{
        summary.changePer
      }}</el-descriptions-item>
      <el-descriptions-item
        label="问题数"
        label-class-name="problem-label"
        class-name="secondary-content"
        >{{ summary.proCount }}</el-descriptions-item
      >
      <el-descriptions-item
        label="整改数"
        label-class-name="problem-label"
        class-name="secondary-content"
        >{{ summary.changeCount }}</el-descriptions-item
      >
      <el-descriptions-item
        label="整改率"
        label-class-name="problem-label"
        :class-name="summary.changePer < 0.6 ? 'danger-content' : 'secondary-content'"
        >{{ formatPercent(summary.changePer) }}</el-descriptions-item
      >
    </el-descriptions>
    <el-descriptions :column="8" size="small" border direction="vertical">
      <el-descriptions-item label="巡查点次">{{
        summary.total
      }}</el-descriptions-item>
      <el-descriptions-item label="问题未审核">{{
        summary.proUnCheck
      }}</el-descriptions-item>
      <el-descriptions-item label="部分审核">{{
        summary.proPartCheck
      }}</el-descriptions-item>
      <el-descriptions-item label="全部审核">{{
        summary.proAllCheck
      }}</el-descriptions-item>
      <el-descriptions-item
        label="巡查点次"
        label-class-name="pro-check-label"
        class-name="secondary-content"
        >{{ summary.total }}</el-descriptions-item
      >
      <el-descriptions-item
        label="问题未审核"
        label-class-name="pro-check-label"
        :class-name="summary.proUnCheck > 0 ? 'danger-content' : 'secondary-content'"
        >{{ summary.proUnCheck }}</el-descriptions-item
      >
      <el-descriptions-item
        label="部分审核"
        label-class-name="pro-check-label"
        :class-name="summary.proPartCheck > 0 ? 'danger-content' : 'secondary-content'"
        >{{ summary.proPartCheck }}</el-descriptions-item
      >
      <el-descriptions-item
        label="全部审核"
        label-class-name="pro-check-label"
        class-name="secondary-content"
        >{{ summary.proAllCheck }}</el-descriptions-item
      >
    </el-descriptions>
    <el-descriptions :column="8" size="small" border direction="vertical">
      <el-descriptions-item label="未整改">{{
        summary.UnChange
      }}</el-descriptions-item>
      <el-descriptions-item label="整改未审核">{{
        summary.changeUnCheck
      }}</el-descriptions-item>
      <el-descriptions-item label="部分审核">{{
        summary.changePartCheck
      }}</el-descriptions-item>
      <el-descriptions-item label="全部审核">{{
        summary.changeAllCheck
      }}</el-descriptions-item>
      <el-descriptions-item
        label="未整改"
        label-class-name="change-check-label"
        :class-name="summary.UnChange > 0 ? 'danger-content' : 'secondary-content'"
        >{{ summary.UnChange }}</el-descriptions-item
      >
      <el-descriptions-item
        label="整改未审核"
        label-class-name="change-check-label"
        :class-name="summary.changeUnCheck > 0 ? 'danger-content' : 'secondary-content'"
        >{{ summary.changeUnCheck }}</el-descriptions-item
      >
      <el-descriptions-item
        label="部分审核"
        label-class-name="change-check-label"
        :class-name="summary.changePartCheck > 0 ? 'danger-content' : 'secondary-content'"
        >{{ summary.changePartCheck }}</el-descriptions-item
      >
      <el-descriptions-item
        label="全部审核"
        label-class-name="change-check-label"
        class-name="secondary-content"
        >{{ summary.changeAllCheck }}</el-descriptions-item
      >
    </el-descriptions>
  </el-space>
  <!-- <el-space>
@@ -68,7 +101,7 @@
        changeAllCheck: 0,
        proCount: 0,
        changeCount: 0,
        changePer: '0%'
        changePer: 0
      };
      this.subtasks.forEach((s) => {
        _summary.total++;
@@ -106,19 +139,14 @@
      });
      if (_summary.proCount != 0) {
        _summary.changePer =
          Math.round((_summary.changeCount / _summary.proCount) * 1000) / 10 +
          '%';
        _summary.changePer = _summary.changeCount / _summary.proCount;
      }
      // _summary.forEach((s, i) => {
      //   if (i > 0) {
      //     let per = Math.round((s.value / _summary[0].value) * 1000) / 10
      //     if (isNaN(per)) per = 0
      //     s.value = `${s.value}(${per}%)`
      //   }
      // })
      return _summary;
    }
  },
  methods: {
    formatPercent(value) {
      return Math.round(value * 1000) / 10 + '%';
    }
  }
};
@@ -128,4 +156,34 @@
  padding: 0px 4px !important;
  /* font-size: 13px !important; */
}
:deep(.problem-label) {
  background: var(--el-color-primary-light-7) !important;
}
:deep(.problem-content) {
  /* background: var(--el-color-danger-light-9); */
}
:deep(.pro-check-label) {
  background: var(--el-color-success-light-7) !important;
}
:deep(.pro-check-content) {
}
:deep(.change-check-label) {
  background: var(--el-color-warning-light-7) !important;
}
:deep(.change-check-content) {
}
:deep(.danger-content) {
  color: var(--el-color-danger) !important;
  font-weight: 600 !important;
  font-size: 17px !important;
}
:deep(.secondary-content) {
  color: var(--el-text-color-regular) !important;
  font-size: 12px !important;
}
</style>
src/views/fysp/check/components/js/dataMonitorDeviceType.js
ÎļþÒÑɾ³ý
src/views/fysp/check/components/js/dataProductionDeviceType.js
ÎļþÒÑɾ³ý
src/views/fysp/check/components/js/dataTreatmentDeviceType.js
ÎļþÒÑɾ³ý
src/views/fysp/data-product/ProdSceneReport.vue
@@ -5,6 +5,7 @@
    </template>
    <template #aside>
      <SideList
        legend
        :items="subtasks"
        :loading="sideLoading"
        @item-click="chooseSubtask"
@@ -12,6 +13,7 @@
    </template>
    <template #main>
      <el-scrollbar class="el-scrollbar" v-loading="mainLoading">
        <div></div>
        <CompSceneConstructionInfo
          title="A、基本信息"
          :scene="formScene"
@@ -80,7 +82,15 @@
    @submit="handleSelectAnyPhoto"
    :defaultFile="[sceneImg]"
  ></ArbitraryPhoto>
  <el-dialog
  <FYImageSelectDialog
    v-model:dialog-visible="deiveceImgDialog"
    title="设备图片"
    :max-select="1"
    :typeList="showDeviceTypeList"
    :typeImgMap="showDeviceImgMap"
    @submit="handleSelectDevicePhoto"
  ></FYImageSelectDialog>
  <!-- <el-dialog
    title="设备图片"
    width="66%"
    v-model="deiveceImgDialog"
@@ -88,10 +98,10 @@
  >
    <CompDevicePhono
      @selectPhonoEvent="handleSelectDevicePhoto"
      :imgPathsDataSource="showDeviceImgList"
      :imgPathsDataSource="showDeviceImgMap"
    >
    </CompDevicePhono>
  </el-dialog>
  </el-dialog> -->
</template>
<script setup>
import { ref, computed } from 'vue';
@@ -105,10 +115,10 @@
import { enumDevice, toLabel } from '@/enum/device/device';
import { exportDocx } from '@/utils/doc';
import right_triangle from '@/assets/image/right_triangle.png';
import ProCheckProxy from '@/views/fysp/check/ProCheckProxy';
import CompSceneConstructionInfo from '@/views/fysp/scene/CompSceneConstructionInfo.vue';
import ArbitraryPhoto from '@/views/fysp/check/components/ArbitraryPhoto.vue';
import CompDevicePhono from '@/views/fysp/check/components/CompDevicePhono.vue';
import CompImgInfo from '@/views/fysp/data-product/components/CompImgInfo.vue';
import CompProblemTable from './components/CompProblemTable.vue';
import dayjs from 'dayjs';
@@ -146,8 +156,9 @@
  taskApi.getSubtaskSummary(param).then((res) => {
    const list = [];
    res.forEach((s) => {
      const t = getSubtaskType(s);
      const t = ProCheckProxy.getSubtaskType(s);
      list.push({
        status: s.subtask.status,
        type: t,
        title: s.stName,
        categoly: s.stPlanTime.split('T')[0],
@@ -210,36 +221,37 @@
// è®¾å¤‡å›¾ç‰‡é€‰æ‹©å¯¹è¯æ¡†
const deiveceImgDialog = ref(false);
const showDeviceIndex = ref(0);
const showDeviceImgList = ref([]);
const showDeviceTypeList = ref([]);
const showDeviceImgMap = ref(new Map());
// è®¾å¤‡å›¾ç‰‡åˆ—表
const deviceList = ref([]);
function showDevicePhotoDialog(device, index) {
  showDeviceIndex.value = index;
  deiveceImgDialog.value = true;
  showDeviceImgList.value = [];
  showDeviceTypeList.value = [
    { typeId: device.topTypeId, typeName: device._deviceTypeName }
  ];
  showDeviceImgMap.value.clear();
  let imgList = [];
  device._status
    .map((s) => s._picUrls)
    .forEach((pics) => {
      imgList = imgList.concat(
        pics.map((p) => {
          return {
            topTypeId: device.topTypeId,
            _picUrl: p
          };
          return { url: p };
        })
      );
    });
  // console.log(imgList);
  showDeviceImgList.value = imgList;
  showDeviceImgMap.value.set(device.topTypeId, imgList);
}
function handleSelectDevicePhoto(data) {
  deiveceImgDialog.value = false;
  if (data.length > 0) {
    deviceList.value[showDeviceIndex.value]._showStatusPic = data[0]._picUrl;
    deviceList.value[showDeviceIndex.value]._showStatusPic = data[0].url;
  }
}
@@ -354,8 +366,12 @@
      _showStatusPic_1: d1._showStatusPic ? d1._showStatusPic : right_triangle,
      _deviceTypeName_1: d1._deviceTypeName,
      // hasPic2: d2 ? true : false,
      _showStatusPic_2: d2 ? (d2._showStatusPic ? d2._showStatusPic : right_triangle) : right_triangle,
      _deviceTypeName_2: d2 ? d2._deviceTypeName : '',
      _showStatusPic_2: d2
        ? d2._showStatusPic
          ? d2._showStatusPic
          : right_triangle
        : right_triangle,
      _deviceTypeName_2: d2 ? d2._deviceTypeName : ''
    });
  }
  const param = {
src/views/fysp/scene/SceneEdit.vue
@@ -23,7 +23,7 @@
    <div class="sub-title">工地信息</div>
    <el-row>
      <FormCol>
        <CompSceneConstructionInfo :form-info="formSubScene" />
        <CompSceneConstructionInfo showStyle="form" :form-info="formSubScene" />
      </FormCol>
    </el-row>
    <el-divider />
src/views/fysp/task/TaskManage.vue
@@ -229,10 +229,10 @@
          type = 0;
          break;
        case '正在执行':
          type = 1;
          type = 5;
          break;
        case '已结束':
          type = 2;
          type = 6;
          break;
        default:
          type = 0;