riku
2024-11-04 069da66fbe2748d51b1f3bc63f9ae00e660083c6
场景报告模块(暂存)
已修改7个文件
已添加2个文件
479 ■■■■ 文件已修改
src/assets/image/unchange.png 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/FYImageSelectDialog.vue 193 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/check/components/ArbitraryPhoto.vue 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/data-product/ProdDailyReport.vue 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/data-product/ProdSceneReport.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/data-product/components/CompImgInfo.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/data-product/components/CompProblemPicSelect.vue 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/data-product/components/CompProblemTable.vue 132 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/image/unchange.png
src/components.d.ts
@@ -19,6 +19,7 @@
    ElBreadcrumbItem: typeof import('element-plus/es')['ElBreadcrumbItem']
    ElButton: typeof import('element-plus/es')['ElButton']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCascader: typeof import('element-plus/es')['ElCascader']
    ElCol: typeof import('element-plus/es')['ElCol']
    ElCollapse: typeof import('element-plus/es')['ElCollapse']
    ElCollapseItem: typeof import('element-plus/es')['ElCollapseItem']
@@ -43,6 +44,8 @@
    ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup']
    ElOption: typeof import('element-plus/es')['ElOption']
    ElPopover: typeof import('element-plus/es')['ElPopover']
    ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
    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']
@@ -56,6 +59,7 @@
    ElTabs: typeof import('element-plus/es')['ElTabs']
    ElTag: typeof import('element-plus/es')['ElTag']
    ElText: typeof import('element-plus/es')['ElText']
    ElTooltip: typeof import('element-plus/es')['ElTooltip']
    ElTree: typeof import('element-plus/es')['ElTree']
    ElUpload: typeof import('element-plus/es')['ElUpload']
    Footer: typeof import('./components/core/Footer.vue')['default']
src/components/FYImageSelectDialog.vue
@@ -1,23 +1,25 @@
<template>
  <el-dialog
    v-model="anyPhotoDialog"
    :model-value="dialogVisible"
    @opened="$emit('update:dialogVisible', true)"
    @closed="$emit('update:dialogVisible', false)"
    width="66%"
    title="任意图片"
    destroy-on-close
  >
    <div class="main">
      <el-row justify="end" class="btns" v-if="!readonly">
      <el-row justify="end" v-if="!readonly">
        <el-text size="small" type="info" class="m-r-8"
          >最多选择{{ maxSelect }}张图片</el-text
        >
        <el-button
          size="small"
          type="primary"
          @click="sendSelectedImg(true)"
          @click="handleSubmit"
          :disabled="selectedImgUrlList.length == 0"
          >确定</el-button
        >
        <el-button size="small" type="primary" @click="sendSelectedImg(false)"
        <el-button size="small" type="primary" @click="handleCancel"
          >取消</el-button
        >
      </el-row>
@@ -34,8 +36,10 @@
          >
          </el-tab-pane>
        </el-tabs>
        <el-empty v-if="isEmpty" description="暂无记录" />
        <el-scrollbar class="imgs">
        <el-scrollbar
          v-if="typeImgMap.get(activeId) && typeImgMap.get(activeId).length > 0"
          class="imgs"
        >
          <el-image
            v-for="(img, i) in typeImgMap.get(activeId)"
            :key="i"
@@ -46,6 +50,9 @@
            @click="onSelect(img, i)"
          />
        </el-scrollbar>
        <el-row v-else justify="space-between">
          <el-empty description="暂无记录" />
        </el-row>
      </div>
    </div>
  </el-dialog>
@@ -54,9 +61,18 @@
import { ref, watch } from 'vue';
const props = defineProps({
  dialogVisible: Boolean,
  /**
   * å›¾ç‰‡åˆ†ç±»
   * ç»“æž„{ typeId, typeName }
   */
  typeList: {
    type: Array,
    default: () => []
  },
  typeImgMap: {
    type: Array,
    default: () => new Map()
  },
  // æ˜¯å¦ä»¥åªè¯»çš„形式查看当前页面
  readonly: {
@@ -74,26 +90,169 @@
  }
});
const activeId = ref('');
const typeImgMap = ref(new Map());
const selectedImgList = ref([]);
const emit = defineEmits(['submit', 'cancel', 'update:dialogVisible']);
watch(typeImgMap, (newMap, oldMap) => {
  if (newMap.get(activeId.value) == undefined) {
const activeId = ref('');
// const typeImgMap = ref(new Map());
const selectedImgUrlList = ref([]);
function onSelect(img, i) {
  if (props.readonly) {
    return;
  }
  newMap.get(activeId.value).forEach(
    (i) => {
  const imgList = selectedImgUrlList.value;
  const index = imgList.indexOf(img);
  if (index == -1) {
    if (props.maxSelect == 1) {
      img.isSelect = true;
      imgList.push(img);
      if (imgList.length > 1) {
        imgList.splice(0, 1).forEach((e) => {
          e.isSelect = false;
        });
      }
    } else if (props.maxSelect > 1) {
      if (imgList.length < props.maxSelect) {
        img.isSelect = true;
        imgList.push(img);
      }
    }
  } else {
    imgList.splice(index, 1);
    img.isSelect = false;
  }
}
function handleSubmit() {
  emit('submit', selectedImgUrlList.value);
  emit('update:dialogVisible', false);
}
function handleCancel() {
  emit('cancel');
  emit('update:dialogVisible', false);
}
watch(
  () => props.typeList,
  (nV, oV) => {
    if (nV != oV && nV.length > 0) {
      activeId.value = nV[0].typeId;
    }
  },
  { 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 }
);
</script>
<style scoped>
.center {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.text {
  padding: 20px;
}
.main {
  margin: 0 auto; /* ä½¿çˆ¶å…ƒç´ å±…中 */
  height: 100%;
  width: 100%;
}
.imgs {
  height: 50vh;
  width: 100%;
  min-height: 100px !important;
  /* border-style:solid;
    border-radius: 1px; */
  /* height: 100%; */
  flex-grow: 1 !important;
  overflow-y: auto !important;
  /* å†…容的内边距 */
  display: flex !important;
  flex-wrap: wrap !important;
  /* overflow: hidden; */
}
.image {
  margin: 5px;
  height: 210px;
  width: 200px;
  border-radius: 4px;
}
.active {
  padding: 5px;
  width: 20%;
  height: 200px;
  border: 0.5rem outset rgb(52, 155, 4);
}
.selected {
  margin: 3px;
  color: #4abe84;
  box-shadow: 0 2px 7px 0 rgba(85, 110, 97, 0.35);
  border: 2px solid rgba(74, 190, 132, 1);
}
.selected:before {
  content: '';
  position: absolute;
  right: 0;
  bottom: 0;
  border: 17px solid #4abe84;
  border-top-color: transparent;
  border-left-color: transparent;
}
.selected:after {
  content: '';
  width: 5px;
  height: 12px;
  position: absolute;
  right: 6px;
  bottom: 6px;
  border: 2px solid #fff;
  border-top-color: transparent;
  border-left-color: transparent;
  transform: rotate(45deg);
}
.noActive {
  /* padding: 5px; */
}
.blurry {
  filter: blur(3px);
}
.filters {
  display: flex;
  padding: 5px;
}
::v-deep .el-dialog__body {
  height: 60vh;
  padding: 10px calc(var(--el-dialog-padding-primary) + 10px) !important;
}
</style>
src/views/fysp/check/components/ArbitraryPhoto.vue
@@ -134,12 +134,11 @@
          this.defaultFile.forEach((imgItem) => {
            if (imgItem.url == i.url) {
              i.isSelect = true;
              this.selectedImgUrlList.push(i);
            }
          });
        });
      },
      deep: true
    }
  },
  mounted() {
@@ -160,6 +159,9 @@
      // }
      this.typeImgMap.clear();
      this.typeList = [];
      const imgMap = new Map();
      const _typeList = [];
      mediafileApi.getRoutineByStGuid(this.subtask.stGuid).then((res) => {
        this.isEmpty = false;
        let data = res.data;
@@ -171,7 +173,7 @@
          let businesstypeid = e.businesstypeid;
          let businesstype = e.businesstype;
          let hasThisType = false;
          this.typeImgMap.forEach((v, k, m) => {
          imgMap.forEach((v, k, m) => {
            if (k == businesstypeid) {
              hasThisType = true;
              var isAlreadyHas = false;
@@ -190,14 +192,16 @@
            }
          });
          if (!hasThisType) {
            this.typeImgMap.set(businesstypeid, Array.of(e));
            this.typeList.push(e);
            imgMap.set(businesstypeid, Array.of(e));
            _typeList.push(e);
          }
          this.imgUrlList.push(e);
          // TODO imgUrl全局配置
          e.url = $fysp.imgUrl + e.extension1 + e.guid + '.jpg';
          e.isSelect = false;
        }
        this.typeImgMap = imgMap;
        this.typeList = _typeList;
        this.initSelectedTab();
      });
    },
@@ -263,14 +267,15 @@
      let result = [];
      if (!isOk) {
        this.$emit('selectByAnyPhonoEvent', result);
      }
      for (const item of this.imgUrlList) {
        if (item.isSelect == true) {
          result.push(item);
      } else {
        for (const item of this.imgUrlList) {
          if (item.isSelect == true) {
            result.push(item);
          }
        }
        this.isClose = true;
        this.$emit('selectByAnyPhonoEvent', result);
      }
      this.isClose = true;
      this.$emit('selectByAnyPhonoEvent', result);
    }
  }
};
src/views/fysp/data-product/ProdDailyReport.vue
@@ -246,7 +246,7 @@
      handler(nV, oV) {
        // this.getCanClickDay();
      },
      deep: true,
      deep: true
      // immediate: true
    }
  },
@@ -255,16 +255,29 @@
  },
  methods: {
    disabledDate(time) {
      this.getCanClickDay()
      this.getCanClickDay();
      let disabled =
        this.canClickDay.filter((item) => {
          let date = dayjs(time)
          let itemDay = new Date(item)
          console.log("curr preview time canClickDay", itemDay.getFullYear(), itemDay.getMonth(), itemDay.getDate());
          console.log("curr preview time date", date.year(), date.month(), date.date());
          return date.year() == itemDay.getFullYear() && date.month() == itemDay.getMonth() && date.date() == itemDay.getDate()
        })
          .length == 0;
          let date = dayjs(time);
          let itemDay = new Date(item);
          console.log(
            'curr preview time canClickDay',
            itemDay.getFullYear(),
            itemDay.getMonth(),
            itemDay.getDate()
          );
          console.log(
            'curr preview time date',
            date.year(),
            date.month(),
            date.date()
          );
          return (
            date.year() == itemDay.getFullYear() &&
            date.month() == itemDay.getMonth() &&
            date.date() == itemDay.getDate()
          );
        }).length == 0;
      return !disabled;
    },
    getSelectedCityname() {
@@ -301,13 +314,15 @@
          .map((topTask) => {
            taskApi.fetchDayTasks(topTask.tguid).then((res) => {
              res.forEach((r) => {
                let formSearchDate = dayjs(this.formSearch.time)
                let date = new Date()
                dayjs(date).year(formSearchDate.year()).month(formSearchDate.month()).date(Number(r.date.slice(8, 10)))
                let formSearchDate = dayjs(this.formSearch.time);
                let date = new Date();
                dayjs(date)
                  .year(formSearchDate.year())
                  .month(formSearchDate.month())
                  .date(Number(r.date.slice(8, 10)));
                this.canClickDay.push(date);
              });
              console.log("this.canClickDay", this.canClickDay);
              console.log('this.canClickDay', this.canClickDay);
            });
          });
      });
src/views/fysp/data-product/ProdSceneReport.vue
@@ -36,6 +36,15 @@
        </el-space>
        <el-divider />
        <el-text tag="h1">C、现场污染问题与整改情况</el-text>
        <el-space wrap>
          <CompProblemTable
            v-for="(item, i) in curProList"
            :key="i"
            :problem="item"
          ></CompProblemTable>
        </el-space>
        <el-text tag="h1">D、扬尘污染防治建议</el-text>
      </el-scrollbar>
    </template>
  </BaseContentLayout>
@@ -81,6 +90,7 @@
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';
/************************* å·¦ä¾§å·¡æŸ¥ä»»åŠ¡é€‰å• **********************************/
const curSubtask = ref({});
@@ -140,12 +150,14 @@
    mainLoading.value = false;
  });
  fetchDeviceList(s);
  fetchProblems(s)
  fetchProblems(s);
}
/************************* åœºæ™¯åŸºæœ¬ä¿¡æ¯ **********************************/
const formSubScene = ref({});
function fetchSceneInfo(sceneId) {
  formSubScene.value = {};
  sceneImg.value = {};
  return sceneApi.getSceneDetail(sceneId).then((res) => {
    //场景
    // if (res.data.scense) formScene = res.data.scense;
@@ -166,7 +178,7 @@
function handleSelectAnyPhoto(data) {
  anyPhotoDialog.value = false;
  if (data.length > 0) {
    sceneImg.value = { url: data[0].url };
    sceneImg.value = data[0];
  }
}
/************************* åœºæ™¯è®¾å¤‡ä¿¡æ¯ **********************************/
@@ -263,6 +275,7 @@
const curProList = ref([]);
function fetchProblems(s) {
  curProList.value = [];
  taskApi.getProBySubtask(s.data.stGuid).then((res) => {
    curProList.value = res;
  });
src/views/fysp/data-product/components/CompImgInfo.vue
@@ -20,7 +20,15 @@
            :initial-index="0"
            fit="cover"
            lazy
          />
          >
            <template #error>
              <div class="image-slot">
                <el-button type="primary" size="small" @click="$emit('change')"
                  >选择图片</el-button
                >
              </div>
            </template>
          </el-image>
        </td>
      </tr>
      <tr v-if="downTitle">
@@ -50,6 +58,8 @@
  }
});
// const unchangeImg = '../../../../assets/image/unchange.png'
const emit = defineEmits(['change']);
</script>
<style scoped>
@@ -77,4 +87,13 @@
  border-style: solid;
  border-color: #666666; */
}
.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: var(--el-fill-color-light);
}
</style>
src/views/fysp/data-product/components/CompProblemPicSelect.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
<template>
  <FYImageSelectDialog
    :typeList="typeList"
    :typeImgMap="typeImgMap"
    :maxSelect="1"
  ></FYImageSelectDialog>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
const props = defineProps({
  // å±•示模式,problem:问题图片;change:整改图片
  mode: {
    type: String,
    default: 'problem'
  },
  pics: Array
});
const typeList = computed(() => {
  if (props.mode == 'problem') {
    return [{ typeId: 1, typeName: '问题' }];
  } else if (props.mode == 'change') {
    return [{ typeId: 1, typeName: '整改' }];
  } else {
    return [{ typeId: 1, typeName: '未指定' }];
  }
});
const typeImgMap = ref(new Map());
watch(
  () => props.pics,
  (nV, oV) => {
    typeImgMap.value.set(
      1,
      nV.map((v) => {
        return { url: v };
      })
    );
  },
  { immediate: true }
);
</script>
src/views/fysp/data-product/components/CompProblemTable.vue
@@ -2,56 +2,100 @@
  <table>
    <tbody>
      <tr>
        <td>{{ title }}</td>
        <td colspan="2">{{ title }}</td>
      </tr>
      <tr>
        <td>
        <td style="position: relative">
          <el-image
            class="image"
            :src="seletcedProblemPic"
            :preview-src-list="[seletcedProblemPic]"
            :preview-src-list="seletcedProblemPic ? [seletcedProblemPic] : []"
            :initial-index="0"
            fit="cover"
            lazy
          />
          >
            <template #error v-if="!seletcedProblemPic">
              <div class="image-slot">
                <el-text>问题图片未上传</el-text>
              </div>
            </template>
          </el-image>
          <el-button
            class="pop-button"
            size="small"
            @click="proDialog = true"
            >{{ btnName }}</el-button
          >
        </td>
        <td>
        <td style="position: relative">
          <el-image
            class="image"
            :src="seletcedChangePic"
            :preview-src-list="[seletcedChangePic]"
            :src="seletcedChangePic ? seletcedChangePic : unchangeImg"
            :preview-src-list="seletcedChangePic ? [seletcedChangePic] : []"
            :initial-index="0"
            fit="cover"
            lazy
          />
          <el-button
            class="pop-button"
            size="small"
            @click="changeDialog = true"
            >{{ btnName }}</el-button
          >
        </td>
      </tr>
      <tr>
        <td>
          <el-row justify="space-between" align="middle">
            <div>位置:{{ problem.location }}</div>
            <div>描述:{{ problem.problemname }}</div>
            <el-button size="small" @click="$emit('change')">{{
              btnName
            }}</el-button>
          </el-row>
          <div>位置:{{ problem.location }}</div>
          <div>
            æè¿°ï¼š
            <el-input
              size="small"
              v-model="problemDes"
              placeholder="问题描述"
              style="width: 150px"
            />
          </div>
        </td>
        <td>
          <el-row justify="space-between" align="middle">
            <div>位置:{{ problem.location }}</div>
            <div>描述:{{ problem.problemname }}</div>
            <el-button size="small" @click="$emit('change')">{{
              btnName
            }}</el-button>
          </el-row>
          <div>位置:{{ problem.location }}</div>
          <div>
            æè¿°ï¼š
            <el-input
              size="small"
              v-model="changeDes"
              placeholder="整改描述"
              style="width: 150px"
            />
          </div>
        </td>
      </tr>
    </tbody>
  </table>
  <CompProblemPicSelect
    v-if="pics.length > 0"
    v-model:dialog-visible="proDialog"
    mode="problem"
    :pics="pics[0].path"
    :defaultFile="[{ url: seletcedProblemPic }]"
    @submit="handleProPicSelect"
  ></CompProblemPicSelect>
  <CompProblemPicSelect
    v-if="pics.length > 1"
    v-model:dialog-visible="changeDialog"
    mode="change"
    :pics="pics[1].path"
    :defaultFile="[{ url: seletcedChangePic }]"
    @submit="handleChangePicSelect"
  ></CompProblemPicSelect>
</template>
<script setup>
import { ref, watch } from 'vue';
import ProCheckProxy from '@/views/check/ProCheckProxy';
import { ref, watch, computed } from 'vue';
import dayjs from 'dayjs';
import ProCheckProxy from '@/views/fysp/check/ProCheckProxy';
import unchangeImg from '@/assets/image/unchange.png';
import CompProblemPicSelect from './CompProblemPicSelect.vue';
const props = defineProps({
  problem: {
@@ -59,14 +103,27 @@
    default: () => {
      return {};
    }
  },
  btnName: {
    type: String,
    default: '修改'
  }
});
const emit = defineEmits(['change']);
const pics = ref([]);
const proDialog = ref(false);
const seletcedProblemPic = ref();
const changeDialog = ref(false);
const seletcedChangePic = ref();
const problemDes = ref('');
const changeDes = ref('未整改');
const title = computed(() => {
  const time = dayjs(props.problem.time).format('M月');
  return `${time}现场问题及整改图片`;
});
function getPics() {
  pics.value = ProCheckProxy.proPics(props.problem);
@@ -78,11 +135,25 @@
  }
}
function handleProPicSelect(imgList) {
  if (imgList && imgList.length > 0) {
    seletcedProblemPic.value = imgList[0].url;
  }
}
function handleChangePicSelect(imgList) {
  if (imgList && imgList.length > 0) {
    seletcedChangePic.value = imgList[0].url;
  }
}
watch(
  () => props.problem,
  (nV, oV) => {
    if (nV != oV) {
      getPics();
      problemDes.value = nV.problemname;
      changeDes.value = nV.ischanged ? '已整改' : '未整改';
    }
  },
  { immediate: true }
@@ -113,4 +184,19 @@
  border-style: solid;
  border-color: #666666; */
}
.pop-button {
  position: absolute;
  bottom: 0;
  right: 0;
}
.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: var(--el-fill-color-light);
}
</style>