riku
2025-09-20 0796eebe3520fafb0ac5d36ee584af81506d7e9c
src/views/fysp/data-product/ProdSceneReport.vue
@@ -5,6 +5,7 @@
    </template>
    <template #aside>
      <SideList
        legend
        :items="subtasks"
        :loading="sideLoading"
        @item-click="chooseSubtask"
@@ -12,13 +13,15 @@
    </template>
    <template #main>
      <el-scrollbar class="el-scrollbar" v-loading="mainLoading">
        <div></div>
        <CompSceneConstructionInfo
          title="A、工地基本信息"
          title="A、基本信息"
          :scene="formScene"
          :form-info="formSubScene"
        />
        <div><el-text type="">附图片:</el-text></div>
        <CompImgInfo
          title="施工铭牌"
          v-model:title="imgTitle"
          :img-src="sceneImg.url"
          @change="anyPhotoDialog = true"
        ></CompImgInfo>
@@ -29,32 +32,65 @@
            v-for="(item, i) in deviceList"
            :key="i"
            down-title
            :title="item._deviceTypeName"
            v-model:title="item._deviceTypeName"
            :img-src="item._showStatusPic"
            @change="showDevicePhotoDialog(item)"
            @change="showDevicePhotoDialog(item, i)"
          ></CompImgInfo>
        </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"
            @change="(value) => handleProPicSelect(value, i)"
          ></CompProblemTable>
        </el-space>
        <el-divider />
        <el-text tag="h1">D、扬尘污染防治建议</el-text>
        <div class="p-b-8">
          针对该工地本期巡查发现的问题,评估为扬尘污染防治
          <el-radio-group v-model="radioStandard" size="default">
            <el-radio value="规范" border>规范</el-radio>
            <el-radio value="基本规范" border>基本规范</el-radio>
            <el-radio value="不规范" border>不规范</el-radio>
            <el-radio value="严重不规范" border>严重不规范</el-radio>
          </el-radio-group>
          工地,建议该工地严格按照《扬尘防治方案》、《扬尘防治承诺书》、《文明施工管理规范》、《精细化管理指标》等相关文件落实整改。
        </div>
        <el-row justify="center" style="height: 200px">
          <el-button
            icon="Download"
            type="primary"
            :loading="docLoading"
            :disabled="!sceneImg.url"
            @click="genWord()"
          >
            生成报告
          </el-button>
        </el-row>
      </el-scrollbar>
    </template>
  </BaseContentLayout>
  <el-dialog
    v-model="anyPhotoDialog"
    width="66%"
    title="任意图片"
    destroy-on-close
  >
    <ArbitraryPhoto
      :max-select="1"
      :readonly="false"
      :subtask="curSubtask.data"
      @selectByAnyPhonoEvent="handleSelectAnyPhoto"
      :defaultFile="[sceneImg]"
    >
    </ArbitraryPhoto>
  </el-dialog>
  <el-dialog
  <ArbitraryPhoto
    v-if="anyPhotoDialog"
    v-model:dialog-visible="anyPhotoDialog"
    :max-select="1"
    :readonly="false"
    :subtask="curSubtask.data"
    @submit="handleSelectAnyPhoto"
    :defaultFile="[sceneImg]"
  ></ArbitraryPhoto>
  <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"
@@ -62,25 +98,31 @@
  >
    <CompDevicePhono
      @selectPhonoEvent="handleSelectDevicePhoto"
      :imgPathsDataSource="showDeviceImgList"
      :imgPathsDataSource="showDeviceImgMap"
    >
    </CompDevicePhono>
  </el-dialog>
  </el-dialog> -->
</template>
<script setup>
import { ref, computed } from 'vue';
import { $fysp } from '@/api/index';
import problemApi from '@/api/fysp/problemApi';
import taskApi from '@/api/fysp/taskApi';
import sceneApi from '@/api/fysp/sceneApi';
import deviceApi from '@/api/fysp/deviceApi';
import evaluateApi from '@/api/fysp/evaluateApi';
import { formatDeviceList } from '@/model/fysp/device';
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';
/************************* 左侧巡查任务选单 **********************************/
const curSubtask = ref({});
@@ -115,8 +157,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],
@@ -140,15 +183,20 @@
    mainLoading.value = false;
  });
  fetchDeviceList(s);
  fetchProblems(s)
  fetchProblems(s);
  fetchEvaluation(s);
}
/************************* 场景基本信息 **********************************/
const imgTitle = ref('施工铭牌');
const formScene = ref({});
const formSubScene = ref({});
function fetchSceneInfo(sceneId) {
  formSubScene.value = {};
  sceneImg.value = {};
  return sceneApi.getSceneDetail(sceneId).then((res) => {
    //场景
    // if (res.data.scense) formScene = res.data.scense;
    if (res.data.scense) formScene.value = res.data.scense;
    formSubScene.value = res.data.subScene ? res.data.subScene : {};
    // if (res.data.sceneDevice) {
    //   formSceneDevice = res.data.sceneDevice;
@@ -166,43 +214,45 @@
function handleSelectAnyPhoto(data) {
  anyPhotoDialog.value = false;
  if (data.length > 0) {
    sceneImg.value = { url: data[0].url };
    sceneImg.value = data[0];
  }
}
/************************* 场景设备信息 **********************************/
// 设备图片选择对话框
const deiveceImgDialog = ref(false);
const showDeviceImg = ref({});
const showDeviceImgList = ref([]);
const showDeviceIndex = ref(0);
const showDeviceTypeList = ref([]);
const showDeviceImgMap = ref(new Map());
// 设备图片列表
const deviceList = ref([]);
function showDevicePhotoDialog(device) {
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);
  // console.log(imgList);
  showDeviceImgList.value = imgList;
  showDeviceImgMap.value.set(device.topTypeId, imgList);
}
function handleSelectDevicePhoto(data) {
  deiveceImgDialog.value = false;
  if (data.length > 0) {
    showDeviceImg.value = { url: data[0].url };
    deviceList.value[showDeviceIndex.value]._showStatusPic = data[0].url;
  }
}
@@ -259,13 +309,123 @@
  }
}
/************************* 现场巡查情况(问题与整改) **********************************/
const problemDesc = ref('');
//当前任务的问题列表
const curProList = ref([]);
const month = ref('');
const selectedProList = ref([]);
function fetchProblems(s) {
  taskApi.getProBySubtask(s.data.stGuid).then((res) => {
  curProList.value = [];
  problemApi.getProBySubtask(s.data.stGuid).then((res) => {
    curProList.value = res;
    // 生成巡查描述文本
    month.value = dayjs(s.data.stPlanTime).month() + 1;
    const proCount = curProList.value.length;
    problemDesc.value = `${month.value}月巡查共计发现${proCount}个问题`;
    if (proCount > 0) {
      problemDesc.value += ':';
      curProList.value.forEach((p, i) => {
        problemDesc.value += `${i + 1}、${p.problemname};`;
      });
      problemDesc.value += '如下图所示:';
    } else {
      problemDesc.value += '。';
    }
    // 生成选中的问题和整改图片描述
    selectedProList.value = curProList.value.map((v) => {
      return {};
    });
  });
}
function handleProPicSelect(value, index) {
  selectedProList.value[index] = value;
}
/************************* 扬尘防治建议 **********************************/
const radioStandard = ref('规范');
function fetchEvaluation(s) {
  evaluateApi.fetchItemEvaluation(s.data.stGuid).then((res) => {
    radioStandard.value = res.data.grade;
  });
}
/************************* 生成报告 **********************************/
const docLoading = ref(false);
// 生成word报告
function genWord() {
  const _deviceList = [];
  for (let i = 0; i < deviceList.value.length; i += 2) {
    const d1 = deviceList.value[i];
    const d2 =
      i + 1 < deviceList.value.length ? deviceList.value[i + 1] : undefined;
    _deviceList.push({
      _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 : ''
    });
  }
  const param = {
    index: formScene.value.index,
    sceneName: formScene.value.name,
    projectType: formSubScene.value.csProjectType,
    stage: formSubScene.value.siExtension1,
    startTime: formSubScene.value.csStartTime,
    endTime: formSubScene.value.csEndTime,
    leftTime: formSubScene.value.csLeftTime,
    location: formScene.value.location,
    floorSpace: formSubScene.value.csFloorSpace,
    constructionArea: formSubScene.value.csConstructionArea,
    constructionAreaPerMonth: formSubScene.value.csConstructionAreaPerMonth,
    contacts: formScene.value.contacts,
    contactst: formScene.value.contactst,
    securityOfficer: formSubScene.value.csSecurityOfficer,
    securityOfficerTel: formSubScene.value.csSecurityOfficerTel,
    constructionUnit: formSubScene.value.csConstructionUnit,
    employerUnit: formSubScene.value.csEmployerUnit,
    sceneType: formScene.value.type,
    imgTitle: imgTitle.value,
    imgTitle_url: sceneImg.value.url,
    deviceList: _deviceList,
    problemDesc: problemDesc.value,
    problemList: selectedProList.value.map((v) => {
      return {
        month: month.value,
        ...v
      };
    }),
    standard_1: radioStandard.value == '规范',
    standard_2: radioStandard.value == '基本规范',
    standard_3: radioStandard.value == '不规范',
    standard_4: radioStandard.value == '严重规范'
  };
  for (const key in param) {
    if (param[key] == undefined) {
      param[key] = '';
    }
  }
  const date = dayjs(curSubtask.value.data.stPlanTime).format('MM月DD日');
  docLoading.value = true;
  exportDocx(
    '/单体模版-v1.0.docx',
    param,
    `${param.sceneName}单体(${date}).docx`,
    {
      horizontalHeight: 368,
      verticalWidth: 266,
      scale: 1.367
    }
  ).finally(() => (docLoading.value = false));
}
</script>