子组件刷新父组件不刷新页面,表单验证,upload组件预览图片,弹窗放在组件内部,bug修复
已修改10个文件
已添加1个文件
789 ■■■■■ 文件已修改
src/components.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FYImageSelectDialog.vue 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/ProCheck.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/ArbitraryPhoto.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/ComChangeEdit.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompDeviceShowTest.vue 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompGenericWrapper.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompLedgerPhoto.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompProRecent.vue 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompProblemAddOrUpd.vue 246 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/CompProblemCard.vue 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts
@@ -24,6 +24,7 @@
    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
    ElContainer: typeof import('element-plus/es')['ElContainer']
    ElDatePicker: typeof import('element-plus/es')['ElDatePicker']
    ElDescriptions: typeof import('element-plus/es')['ElDescriptions']
    ElDescriptionsItem: typeof import('element-plus/es')['ElDescriptionsItem']
    ElDialog: typeof import('element-plus/es')['ElDialog']
@@ -35,6 +36,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']
    ElMain: typeof import('element-plus/es')['ElMain']
    ElMenu: typeof import('element-plus/es')['ElMenu']
@@ -42,6 +44,8 @@
    ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElPopover: typeof import('element-plus/es')['ElPopover']
    ElRadio: typeof import('element-plus/es')['ElRadio']
    ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
    ElRow: typeof import('element-plus/es')['ElRow']
    ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
    ElSelect: typeof import('element-plus/es')['ElSelect']
src/components/FYImageSelectDialog.vue
@@ -1,6 +1,5 @@
<template>
  <el-dialog
    :title="title"
    :model-value="dialogVisible"
    @opened="$emit('update:dialogVisible', true)"
    @closed="$emit('update:dialogVisible', false)"
@@ -62,8 +61,6 @@
import { ref, watch, computed } from 'vue';
const props = defineProps({
  // æ ‡é¢˜
  title: String,
  dialogVisible: Boolean,
  /**
   * å›¾ç‰‡åˆ†ç±»
src/views/fysp/check/ProCheck.vue
@@ -26,7 +26,6 @@
        class="el-scrollbar"
        v-loading="mainLoading"
      >
        <template v-if="compProblemCardVisible">
          <CompProblemCard
            :key="i"
            v-for="(p, i) in curProList"
@@ -34,28 +33,21 @@
            :problem="p"
            :subtask="curSubtask.data"
            :topTask="topTask"
            @updated="onProSubmited"
            @submit="updateSubtask"
          ></CompProblemCard>
        </template>
      </el-scrollbar>
      <el-empty v-else description="暂无记录" v-loading="mainLoading" />
    </template>
  </BaseContentLayout>
  <el-dialog
    v-model="proAddOrUpdDialogVisible"
    :before-close="proAddOrUpdDialogClose"
    width="50%"
    title="新增问题"
  >
    <CompProblemAddOrUpd
    title="新增问题"
      v-if="proAddOrUpdDialogVisible"
    v-model:visible="proAddOrUpdDialogVisible"
      :subtask="curSubtask.data"
      :topTask="topTask"
      ref="compProblemAddOrUpdRef"
      @submited="newProSubmit"
    @submit="updateSubtask"
    />
  </el-dialog>
  <ArbitraryPhoto
    v-if="anyPhotoDialog"
    v-model:dialog-visible="anyPhotoDialog"
@@ -63,16 +55,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>
</template>
<script>
@@ -93,7 +82,6 @@
  },
  data() {
    return {
      compProblemCardVisible: true,
      // è®¾å¤‡å›¾
      deviceShowDialog: false,
      // ä»»æ„å›¾
@@ -232,21 +220,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;
@@ -307,42 +280,40 @@
        });
    },
    // é—®é¢˜å¡ç‰‡ç»„件主动发起刷新父组件数据
    updateSubtask(refresh = true) {
    updateSubtask(refresh = false) {
      this.curSubtask.data.proCheckedNum++;
      this.curSubtask.type = this.getSubtaskType(this.curSubtask.data);
      if (refresh) {
        this.refreshCurrSubtask();
      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;
      setTimeout(() => {
        taskApi
          .getProBySubtask(this.curSubtask.data.stGuid)
          .then((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;
          });
      }, 150);
    }
src/views/fysp/check/components/ArbitraryPhoto.vue
@@ -19,7 +19,7 @@
    return {
      // æ— æ•°æ®
      typesList: [],
      typesMap: new Map(),
      typesMap: new Map()
    };
  },
  mounted() {
@@ -31,19 +31,6 @@
      mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => {
        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,13 +38,18 @@
          };
          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;
      });
src/views/fysp/check/components/ComChangeEdit.vue
@@ -1,11 +1,18 @@
<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>
      </div>
    </div>
  <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"
@@ -31,58 +38,47 @@
        </el-icon>
      </template>
      <template #tip>
        <div style="color: #f56c6c">最少上传一张图片,最多选择三张图片</div>
              <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="this.$emit('submited', false)">取消</el-button>
        <el-button @click="$emit('submit', 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 CompGenericWrapper from './CompGenericWrapper.vue';
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'],
  components: {
    ArbitraryPhoto,
    LedgerPic
    CompGenericWrapper
  },
  watch: {
    oldChangeFileList: {
      handler(nv, ov) {
        this.initParams();
      },
      immediate: true
    },
    fileList: {
      handler(newFileList, oldFileList) {
        this.pictureValidate();
@@ -112,6 +108,8 @@
  },
  data() {
    return {
      // åˆå§‹å›¾ç‰‡é¢„览index
      initialIndex: -1,
      // å›¾ç‰‡é€‰æ‹©æœ€å¤§æ•°é‡
      maxSelectImgCount: 3,
      previewDialogImageUrl: '',
@@ -124,9 +122,7 @@
      anyPhotoDialog: false
    };
  },
  mounted() {
    this.initParams();
  },
  mounted() {},
  methods: {
    pictureValidate() {
      if (this.changeType == 1 && this.fileList.length < 1) {
@@ -146,7 +142,7 @@
      return true;
    },
    initParams() {
      if (this.changeType == 0) {
      if (!this.changeType || this.changeType == 0) {
        return;
      }
      let beforeEditImgList = [];
@@ -205,7 +201,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 +209,7 @@
            data.append('images', image);
          });
          problemApi.changeProblem(data).then((res) => {});
          that.$emit('submited', true);
          that.$emit('submit', true);
        });
      }
    },
@@ -224,48 +220,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 +233,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 +262,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/CompDeviceShowTest.vue
@@ -1,5 +1,6 @@
<template>
  <div>
  <CompGenericWrapper type="drawer">
    <template #content>
    <!-- é€‰é¡¹ -->
    <!-- è®¾å¤‡ç±»åž‹  -->
    <el-row>
@@ -41,9 +42,14 @@
          >
            <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
                    width="64px"
                    :label="
                      currSelect.topDeviceTypeId == 0 ? '站点名称' : '设备名称'
                    "
                    :span="3"
                    >{{ item.name || '无' }}</el-descriptions-item
                  >
                <el-descriptions-item label="供应商">{{
                  item.supplier || '无'
                }}</el-descriptions-item>
@@ -156,16 +162,18 @@
      </el-collapse-item>
    </el-collapse>
    <!-- ç©ºçŠ¶æ€ -->
    <el-empty v-if="isEmpty" />
  </div>
      <el-empty v-if="isEmpty"
    /></template>
  </CompGenericWrapper>
</template>
<script>
import CompGenericWrapper from './CompGenericWrapper.vue';
import deviceApi from '@/api/fysp/deviceApi';
import { $fysp } from '@/api/index';
import { toLabel } from '@/enum/device/device';
export default {
  components: {},
  components: { CompGenericWrapper },
  watch: {
    // é€‰æ‹©æ”¹å˜ç›‘听
    currSelect: {
src/views/fysp/check/components/CompGenericWrapper.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,67 @@
<template>
  <!-- dialog包裹 -->
  <div v-if="currType == 'dialog'">
    <el-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>
  </div>
  <!-- drawer包裹 -->
  <div v-if="currType == 'drawer'">
    <el-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>
  <!-- é»˜è®¤æ— åŒ…裹 -->
  <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/views/fysp/check/components/CompLedgerPhoto.vue
@@ -11,7 +11,6 @@
import userApi from '@/api/fysp/userApi.js';
import { svToTz } from '@/enum/scene';
import { $fytz } from '@/api/index';
import { useCloned } from '@vueuse/core';
const props = defineProps({
  // å±•示模式
  mode: {
src/views/fysp/check/components/CompProRecent.vue
@@ -1,12 +1,21 @@
<template>
  <div>
  <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-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-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">
@@ -24,30 +33,29 @@
          <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>
                <el-button link type="primary" @click="info(scope.row)"
                  >详情</el-button
                >
            </template>
          </el-table-column>
        </el-table>
      </el-card>
      <el-dialog
        title="预览"
        v-model="proAddOrUpdDialogVisible"
        :before-close="proAddOrUpdDialogClose"
        width="80%"
      >
      </div>
        <CompProblemAddOrUpd
          v-if="proAddOrUpdDialogVisible"
        v-model:visible="proAddOrUpdDialogVisible"
        title="预览"
          :subtask="subtask"
          :topTask="topTask"
          :problem="previewPro"
          :readonly="true"
          ref="compProblemAddOrUpdRef"
        />
      </el-dialog>
    </div>
  </div>
      <el-dialog destroy-on-close> </el-dialog>
    </template>
  </CompGenericWrapper>
</template>
<script>
import CompGenericWrapper from './CompGenericWrapper.vue';
import CompProblemAddOrUpd from './CompProblemAddOrUpd.vue';
import taskApi from '@/api/fysp/taskApi';
import { useCloned } from '@vueuse/core';
@@ -80,16 +88,20 @@
      handler(newObj, oldObj) {
        this.handleClick();
      }
    }
  },
  components: {
    CompProblemAddOrUpd
  },
  mounted() {
    problem: {
      handler(nv, ov) {
    this.deepCopyPro = useCloned(this.problem).cloned.value;
    this.getRecentPros();
  },
      immediate: true
    }
  },
  components: {
    CompProblemAddOrUpd,
    CompGenericWrapper
  },
  mounted() {},
  data() {
    return {
      proAddOrUpdDialogVisible: false,
@@ -114,10 +126,6 @@
    info(pro) {
      this.previewPro = pro;
      this.proAddOrUpdDialogVisible = true;
    },
    // å…³é—­è¯¦æƒ…弹窗
    proAddOrUpdDialogClose() {
      this.proAddOrUpdDialogVisible = false;
    },
    // åˆ‡æ¢æ—¶é—´èŒƒå›´
    handleClick() {
@@ -153,9 +161,11 @@
     * */
    async getRecentPros() {
      this.loading = true;
      this.subtaskCount = 0
      this.subtaskCount = 0;
      // èŽ·å–å­ä»»åŠ¡åˆ—è¡¨
      await taskApi.getSubtaskByScene(this.generateQueryParam()).then((subtasks) => {
      await taskApi
        .getSubtaskByScene(this.generateQueryParam())
        .then((subtasks) => {
        this.curProList = [];
        if (subtasks) {
          subtasks.forEach((subtask) => {
@@ -175,7 +185,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,6 +1,14 @@
<template>
  <CompGenericWrapper type="dialog">
    <template #content>
  <div class="main-container">
    <el-form :model="problem" label-width="auto" style="max-width: 95%">
        <el-form
          :rules="rules"
          :model="deepCopyProblem"
          label-width="auto"
          style="max-width: 95%"
          ref="formRef"
        >
      <el-form-item label="问题位置" prop="locationid">
        <el-select
          v-model="deepCopyProblem.locationid"
@@ -16,9 +24,9 @@
          />
        </el-select>
      </el-form-item>
      <el-form-item label="问题类型" prop="proType">
          <el-form-item label="问题类型" prop="_proType">
        <el-select
          v-model="proType"
              v-model="deepCopyProblem._proType"
          @change="onProTypeChange"
          class="row"
          :disabled="readonly"
@@ -56,9 +64,9 @@
          :disabled="readonly"
        />
      </el-form-item>
      <el-form-item label="问题建议" prop="advise">
          <el-form-item label="问题建议" prop="advice">
        <el-select
          v-model="deepCopyProblem.advise"
              v-model="deepCopyProblem.advice"
          class="row"
          :disabled="readonly"
          @change="onProAdviseChange"
@@ -72,7 +80,12 @@
        </el-select>
      </el-form-item>
      <el-form-item
        v-show="deepCopyProblem.advise && deepCopyProblem.advise != ''"
            v-show="
              problem &&
              problem.guid &&
              deepCopyProblem.advice &&
              deepCopyProblem.advice != ''
            "
        label="问题建议修正"
        prop="_adviseEdit"
        :disabled="false"
@@ -86,9 +99,9 @@
          :disabled="readonly"
        />
      </el-form-item>
      <div class="t-card_item">
        é—®é¢˜å›¾ç‰‡&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
        <div>
          <el-form-item label="问题图片">
            <el-row>
              <el-col>
          <el-button
            @click="chosePicFromAnyPic"
            v-show="!readonly"
@@ -113,9 +126,17 @@
            :disabled="fileList.length >= 3"
            >从文件夹选取</el-button
          >
        </div>
      </div>
              </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"
@@ -140,22 +161,25 @@
          </el-icon>
        </template>
        <template #tip>
          <div style="color: #f56c6c">最少上传一张图片,最多选择三张图片</div>
                    <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="this.$emit('submited', false)" v-show="!readonly"
            <el-button @click="$emit('submit', 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"
@@ -165,7 +189,6 @@
    </ArbitraryPhoto>
    <CompLedgerPhoto
      :max-select="maxSelectImgCount - fileList.length"
      v-if="ledgerPicDialog"
      v-model:dialog-visible="ledgerPicDialog"
      @submit="handleLedgerPicPhono"
      :subtask="subtask"
@@ -174,7 +197,6 @@
    ></CompLedgerPhoto>
    <CompDevicePhoto
      :max-select="maxSelectImgCount - fileList.length"
      v-if="deiveceImgDialog"
      v-model:dialog-visible="deiveceImgDialog"
      @submit="handleSelectedDevicePhono"
      :subtask="subtask"
@@ -182,15 +204,24 @@
      ref="deiveceImgDialogRef"
    >
    </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-dialog v-model="previewDialogVisible">
    <el-dialog v-model="previewDialogVisible">
      <img w-full :src="previewDialogImageUrl" alt="预览" class="preview-pic" />
    </el-dialog>
        </el-dialog> -->
  </div>
</template>
  </CompGenericWrapper>
</template>
<script>
import CompGenericWrapper from './CompGenericWrapper.vue';
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';
@@ -200,11 +231,14 @@
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'],
  components: {
    ArbitraryPhoto,
    CompDevicePhoto,
    CompLedgerPhoto
    CompLedgerPhoto,
    CompGenericWrapper
  },
  props: {
    readonly: {
@@ -235,6 +269,8 @@
  },
  data() {
    return {
      // åˆå§‹é¢„览图片index
      initialIndex: -1,
      // å›¾ç‰‡é€‰æ‹©æœ€å¤§æ•°é‡
      maxSelectImgCount: 3,
      previewDialogVisible: false,
@@ -261,7 +297,7 @@
      month: -1,
      ledgerPicDialog: false,
      rules: {
        proType: {
        _proType: {
          required: true,
          message: '问题类型不能为空',
          trigger: 'change'
@@ -276,14 +312,9 @@
          message: '问题位置不能为空',
          trigger: 'change'
        },
        advise: {
        advice: {
          required: true,
          message: '问题建议不能为空',
          trigger: 'change'
        },
        proRemark: {
          required: true,
          message: '补充说明不能为空',
          trigger: 'change'
        }
      },
@@ -301,14 +332,6 @@
        this.pictureValidate();
      },
      deep: true
    },
    // å½“问题建议改变时问题建议修正跟着改变
    deepCopyProblem: {
      handler(nv, ov) {
        // å›¾ç‰‡æ ¡éªŒ
        nv._adviseEdit = ov.advise;
      },
      deep: true
    }
  },
  computed: {
@@ -316,7 +339,7 @@
      const descriptions = [];
      this.problemTypeList.forEach((item) => {
        if (item.typename == this.proType) {
        if (item.typename == this.deepCopyProblem._proType) {
          descriptions.push(item);
        }
      });
@@ -333,123 +356,39 @@
      }, []);
    },
    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();
  },
  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);
    initOptions() {
      if (!this.problem || !this.subtask || !this.topTask) {
                      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 == 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 +410,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 +423,7 @@
            this.problemTypeList.forEach((item) => {
              if (item.description === currDescription) {
                this.proType = item.typename;
                this.deepCopyProblem._proType = item.typename;
              }
            });
            this.deepCopyProblem.description = currDescription;
@@ -531,6 +470,7 @@
      }
    },
    handleLedgerPicPhono(data) {
      this.beforeLedgerPicDialogclose();
      let isExist = false;
      for (const item of data) {
        for (const already of this.fileList) {
@@ -572,8 +512,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 +527,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,14 +561,9 @@
      }
      return true;
    },
    // TODO
    validateForm() {},
    onSubmit() {
      this.validateForm();
      // å›¾ç‰‡æ ¡éªŒ
      if (!this.pictureValidate()) {
        return;
      }
      this.$refs.formRef.validate((valid) => {
        if (valid && this.pictureValidate()) {
      // æ•°æ®å‡†å¤‡
      let deepCopyPro = useCloned(this.deepCopyProblem).cloned.value;
      let data = new FormData();
@@ -654,20 +590,25 @@
        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['advise'];
          delete deepCopyPro['description'];
          deepCopyPro.proName = deepCopyPro.problemname;
          delete deepCopyPro['problemname'];
@@ -676,14 +617,18 @@
          ).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);
      }
      this.$emit('submited', true);
        }
      });
    },
    handleSelectedAnyPhono(data) {
      this.beforeAnyPhotoDialogclose();
@@ -753,10 +698,6 @@
    },
    beforeLedgerPicDialogclose() {
      this.ledgerPicDialog = false;
    },
    destoryMyself() {
      this.$destroy();
    }
  }
};
@@ -778,7 +719,6 @@
.img-upload {
  margin-top: 30px;
  margin-bottom: 30px;
  margin-left: 63px;
}
.row {
  width: 100%;
@@ -792,6 +732,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
@@ -93,13 +93,15 @@
            >删除</el-button
          >
          <el-button
            v-if="proStatus.name.indexOf('不通过') != -1"
            type="danger"
            size="small"
            @click="beforePro"
            @click="revokePro"
            :disabled="proStatus.checkable"
            >撤销</el-button
            >撤销驳回</el-button
          >
          <el-button
            v-else
            type="warning"
            size="small"
            @click="rejectPro"
@@ -107,6 +109,18 @@
            >驳回</el-button
          >
          <el-button
            v-if="
              proStatus.name.indexOf('不通过') == -1 &&
              proStatus.name.indexOf('通过') != -1
            "
            type="danger"
            size="small"
            @click="revokePro"
            :disabled="proStatus.checkable"
            >撤销通过</el-button
          >
          <el-button
            v-else
            type="success"
            size="small"
            @click="passPro"
@@ -117,63 +131,37 @@
      </el-col>
    </el-row>
  </el-card>
  <div class="dialog-wrapper">
    <el-dialog
      title="问题更正"
      width="50%"
      v-model="proAddOrUpdDialogVisible"
      :before-close="proAddOrUpdDialogClose"
    >
      <CompProblemAddOrUpd
    title="问题更正"
        v-if="proAddOrUpdDialogVisible"
    v-model:visible="proAddOrUpdDialogVisible"
        :problem="deepCopyPro"
        :subtask="deepCopySubtask"
        :topTask="deepCopyTopTask"
    :subtask="subtask"
    :topTask="topTask"
        ref="compProblemAddOrUpdRef"
        @submited="onProSubmited"
    @submit="onProSubmited"
      />
    </el-dialog>
  </div>
  <el-dialog width="80%" title="整改提交" v-model="addChangeDialogVisible">
  <!-- æ•´æ”¹ -->
    <ComChangeEdit
      :changeType="0"
      v-if="addChangeDialogVisible"
    :title="changeType == 1 ? '整改检验' : '整改提交'"
    v-if="changeDialogVisible"
    v-model:visible="changeDialogVisible"
    :changeType="changeType"
      :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"
    @submit="onChangeSubmited"
    />
  </el-dialog>
  <!-- é—®é¢˜å¤çް -->
  <el-dialog
    width="50%"
    title="问题复现"
    v-model="proRecentDialogVisible"
    :before-close="proRecentDialogClose"
  >
    <CompProRecent
    title="问题复现"
      v-if="proRecentDialogVisible"
    v-model:visible="proRecentDialogVisible"
      :subtask="subtask"
      :topTask="topTask"
      :problem="problem"
    />
  </el-dialog>
</template>
<script>
@@ -185,6 +173,7 @@
import CompProRecent from './CompProRecent.vue';
import { useCloned } from '@vueuse/core';
export default {
  emits: ['submmit'],
  components: {
    CompProblemAddOrUpd,
    ComChangeEdit,
@@ -221,9 +210,11 @@
      default: 1
    }
  },
  emits: ['submit'],
  emits: ['submit', 'updated'],
  data() {
    return {
      changeDialogVisible: false,
      changeType: -1,
      addChangeDialogVisible: false,
      // è¿‘期情况
      proRecentDialogVisible: false,
@@ -291,30 +282,13 @@
    }
  },
  methods: {
    onAddChangeSubmited() {
      this.$emit('updated', true);
      this.addChangeDialogVisible = false;
    },
    // è¿‘期情况弹窗关闭
    proRecentDialogClose() {
      this.proRecentDialogVisible = false;
    },
    newProblem() {
      this.proAddOrUpdDialogVisible = true;
    },
    onProSubmited(isOk) {
      this.$emit('updated', isOk);
      this.$emit('submit', isOk);
      this.proAddOrUpdDialogVisible = false;
    },
    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 +313,7 @@
    passPro() {
      this.checkPro(true);
    },
    beforePro() {
    revokePro() {
      const pro = this.problem;
      let status = this.proStatus;
      let doneMsg;
@@ -359,7 +333,6 @@
            .checkProblem({ pId: pro.guid, action: action })
            .then((res) => {
              if (res.success) {
                pro.extension3 = status;
                this.$emit('submit', false);
              }
            });
@@ -381,20 +354,14 @@
            .checkProblem({ pId: pro.guid, action: action })
            .then((res) => {
              if (res.success) {
                pro.extension3 = status;
                this.$emit('submit', false);
              }
            });
        }
      });
    },
    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 +381,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;