riku
2024-04-24 da51e7d5bbf5ff1610209510571e94d0523b515c
完善自动评估模块,规范性分析报告的后台任务和结果下载逻辑
已修改13个文件
已添加3个文件
322 ■■■■ 文件已修改
src/api/fysp/evaluateApi.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bg-task/FYBgTaskCard.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/head/FYPageHeader.vue 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/EvalutationEdit.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/EvalutationRecord.vue 29 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/CompQuickSet.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/CompReport.vue 102 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/scene/CompSceneBaseInfo.vue 88 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/scene/SceneEdit.vue 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/scene/SceneInfo.vue 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fytz/user/UserInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fytz/user/components/CompUserInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fytz/user/components/CompUserInfoAddDrawer.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/evaluateApi.js
@@ -10,6 +10,11 @@
  },
  /**
   * æ ¹æ®å·¡æŸ¥ä»»åŠ¡èŽ·å–è¯„åˆ†ç»†åˆ™
   */
  /**
   * æŸ¥è¯¢è¯„估总规则
   * @param {Object} param
   * @returns
@@ -22,9 +27,12 @@
    return $fysp.post(`evaluation/auto`, param).then((res) => res.data);
  },
  downloadAutoEvaluation(param) {
  /**
   * ä¸‹è½½è§„范性评估与分析报告
   */
  downloadAutoEvaluation(param, forceUpdate) {
    return $fysp
      .post(`evaluation/auto/record/download`, param, { responseType: 'blob' })
      .post(`evaluation/auto/record/download?forceUpdate=${forceUpdate}`, param, { responseType: 'blob' })
      .then((res) => {
        // æ–‡æ¡£æœªç”Ÿæˆï¼Œå·²å¯åŠ¨æ–‡æ¡£ç”ŸæˆåŽå°ä»»åŠ¡
        if (res.data.type == 'application/json') {
src/api/index.js
@@ -3,8 +3,10 @@
const debug = true;
let ip1 = 'http://47.100.191.150:9005/';
let ip1_file = 'http://47.100.191.150:9005/';
// let ip1 = 'http://47.100.191.150:9005/';
// let ip1_file = 'http://47.100.191.150:9005/';
let ip1 = 'https://fyami.com.cn:447/';
let ip1_file = 'https://fyami.com.cn:447/';
let ip2 = 'https://fyami.com.cn/';
let ip2_file = 'https://fyami.com.cn/';
src/components.d.ts
@@ -20,6 +20,7 @@
    ElButtonGroup: typeof import('element-plus/es')['ElButtonGroup']
    ElCard: typeof import('element-plus/es')['ElCard']
    ElCascader: typeof import('element-plus/es')['ElCascader']
    ElCheckbox: typeof import('element-plus/es')['ElCheckbox']
    ElCol: typeof import('element-plus/es')['ElCol']
    ElConfigProvider: typeof import('element-plus/es')['ElConfigProvider']
    ElContainer: typeof import('element-plus/es')['ElContainer']
@@ -80,6 +81,7 @@
    FYOptionText: typeof import('./components/search-option/base/FYOptionText.vue')['default']
    FYOptionTime: typeof import('./components/search-option/FYOptionTime.vue')['default']
    FYOptionUserType: typeof import('./components/search-option/FYOptionUserType.vue')['default']
    FYPageHeader: typeof import('./components/head/FYPageHeader.vue')['default']
    FYReconfrimButton: typeof import('./components/button/FYReconfrimButton.vue')['default']
    FYSearchBar: typeof import('./components/search-option/FYSearchBar.vue')['default']
    FYTable: typeof import('./components/table/FYTable.vue')['default']
src/components/bg-task/FYBgTaskCard.vue
@@ -150,6 +150,12 @@
      });
    },
    gotoResult(index) {}
  },
  mounted() {
    this.fetchTask();
    // setInterval(() => {
    //   this.fetchTask();
    // }, 10000);
  }
};
</script>
src/components/head/FYPageHeader.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
<template>
  <el-page-header @back="onBack" class="page-header">
    <template #content>
      <span> {{ title }} </span>
    </template>
  </el-page-header>
  <el-divider />
</template>
<script>
export default {
  props: {
    title: {
      type: String,
      default: '当前为默认页面标题,请传入标题名字'
    }
  },
  methods: {
    // å›žé€€é¡µé¢
    onBack() {
      this.$router.back();
    }
  }
};
</script>
src/router/index.js
@@ -92,6 +92,12 @@
    meta: { keepAlive: true }
  },
  {
    //评估结果详情
    name: 'fyspEvalutationEdit',
    path: '/fysp/evaluation/evalutationEdit/:subTaskId',
    component: () => import('@/views/fysp/evaluation/EvalutationEdit.vue'),
  },
  {
    //场景信息
    name: 'fyspSceneInfo',
    path: '/fysp/sceneInfo',
src/views/fysp/evaluation/EvalutationEdit.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
<template>
  <FYPageHeader title="评估结果详情"></FYPageHeader>
</template>
<script>
export default {
  data() {
    return {};
  },
  methods: {}
};
</script>
<style scoped></style>
src/views/fysp/evaluation/EvalutationRecord.vue
@@ -1,6 +1,4 @@
<template>
  <!-- <CompPreCheck @pre-check="autoEvaluate"></CompPreCheck> -->
  <FYTable @search="onSearch" :pagination="false" ref="tableRef">
    <template #options>
      <!-- åŒºåŽ¿ -->
@@ -18,6 +16,16 @@
      ></FYOptionScene>
      <!-- æ—¶é—´ -->
      <FYOptionTime :initValue="false" type="month" v-model:value="formSearch.time"></FYOptionTime>
    </template>
    <template #buttons>
      <!-- <el-button icon="Download" size="default" type="success" @click="download"
        >规范性评估与分析报告</el-button
      > -->
      <CompReport
        :locations="formSearch.locations"
        :scenetype="formSearch.scenetype"
        :time="formSearch.time"
      ></CompReport>
    </template>
    <template #options-expand>
@@ -71,11 +79,11 @@
      <!-- <el-table-column prop="biArea" label="集中区" width="110" />
      <el-table-column prop="biManagementCompany" label="物业" min-width="110"/> -->
      <el-table-column fixed="right" align="right" label="操作" width="160">
        <template #header>
          <el-button icon="Download" size="default" type="success" @click="download"
            >下载结果</el-button
        <!-- <template #header>
          <el-button icon="Download" size="default" type="success" @click="exportExcel"
            >导出结果</el-button
          >
        </template>
        </template> -->
        <template #default="{ row }">
          <el-button type="primary" size="small" @click="editRow(row)">查看</el-button>
        </template>
@@ -89,10 +97,11 @@
import evaluateApi from '@/api/fysp/evaluateApi';
import { envCreditCode } from '@/constants/index';
import CompQuickSet from './components/CompQuickSet.vue';
import CompReport from './components/CompReport.vue';
export default {
  name: 'ResultManage',
  components: { CompQuickSet },
  components: { CompQuickSet, CompReport },
  data() {
    return {
      formSearch: {
@@ -117,6 +126,9 @@
        scensetypeid: scenetype.value
      };
    },
    editRow(row) {
      this.$router.push(`evalutationEdit/${row.subTaskId}`);
    },
    setOptions(param) {
      this.formSearch.locations = param.locations;
      this.formSearch.scenetype = param.scenetype;
@@ -134,6 +146,7 @@
        }
      });
    },
    // è§„范性评估与分析报告后台生成任务
    download() {
      const area = this._getParam();
      evaluateApi.downloadAutoEvaluation(area).then((res) => {
@@ -143,6 +156,8 @@
        }
      });
    },
    // å¯¼å‡ºè¡¨æ ¼ä¸ºexcel格式
    exportExcel() {},
    getFilters(data) {
      const townList = [];
      data.forEach((e) => {
src/views/fysp/evaluation/components/CompQuickSet.vue
@@ -6,14 +6,6 @@
    }}</el-button>
    </el-space>
  </el-form-item>
  <!-- <el-row class="row">
    <el-space>
    <el-text>快捷选择</el-text>
    <el-button v-for="(v, i) in quickSetting" :key="i" type="primary" size="small" @click="quickSet(v)">{{
      v.name
    }}</el-button>
    </el-space>
  </el-row> -->
</template>
<script>
export default {
src/views/fysp/evaluation/components/CompReport.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,102 @@
<template>
  <el-button icon="Download" type="success" @click="dialogVisible = true"
    >规范性评估与分析报告</el-button
  >
  <el-dialog
    v-model="dialogVisible"
    title="规范性评估与分析报告生成"
    width="500"
    :before-close="handleClose"
  >
    <el-text tag="b" size="large">数据范围确认</el-text>
    <el-text tag="div">区域:{{ locationText }}</el-text>
    <el-text tag="div">类型:{{ scenetype.label }}</el-text>
    <el-text tag="div">时间:{{ timeText }}</el-text>
    <template #footer>
      <div class="dialog-footer">
        <el-row align="middle">
          <el-checkbox v-model="forceUpdate" label="强制生成新报告" />
          <el-tooltip placement="bottom-start" effect="light">
            <template #content>
              <el-text tag="b" size="small">不勾选:</el-text><br />
              <el-text size="small"
                >不勾选时,如果已生成过相同区域的报告,则直接获取该份报告记录</el-text
              ><br />
              <el-text tag="b" size="small">勾选:</el-text><br />
              <el-text size="small"
                >勾选时,无论是否有历史记录,都会启动报告生成任务覆盖旧记录,可在后台任务界面查看任务进度</el-text
              ><br />
            </template>
            <el-icon class="m-l-8 cursor-p" :size="16" color="var(--el-color-warning)"
              ><QuestionFilled
            /></el-icon>
          </el-tooltip>
        </el-row>
        <div>
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="download">确定</el-button>
        </div>
      </div>
    </template>
  </el-dialog>
</template>
<script>
import dayjs from 'dayjs';
import evaluateApi from '@/api/fysp/evaluateApi';
export default {
  props: ['locations', 'time', 'scenetype'],
  data() {
    return {
      dialogVisible: false,
      forceUpdate: false
    };
  },
  computed: {
    locationText() {
      const loc = this.locations;
      let text = '';
      text = loc.pName == loc.cName ? loc.pName : loc.pName + loc.cName;
      text += loc.dName;
      return text;
    },
    timeText() {
      return dayjs(this.time).format('YYYYå¹´MM月');
    }
  },
  methods: {
    // è§„范性评估与分析报告后台生成任务
    download() {
      const locations = this.locations;
      const time = this.time;
      const scenetype = this.scenetype;
      const area = {
        provincecode: locations.pCode,
        provincename: locations.pName,
        citycode: locations.cCode,
        cityname: locations.cName,
        districtcode: locations.dCode,
        districtname: locations.dName,
        starttime: dayjs(this.time).format('YYYY-MM-DD HH:mm:ss'),
        scensetypeid: scenetype.value
      };
      evaluateApi.downloadAutoEvaluation(area, this.forceUpdate).then((res) => {
        if (res == false) {
          // æœªä¸‹è½½æ–‡æ¡£ï¼Œè€Œæ˜¯å¼€å¯äº†æ–‡æ¡£ç”ŸæˆåŽå°ä»»åŠ¡
          this.$parent;
        }
        this.dialogVisible = false;
      });
    }
  }
};
</script>
<style scoped>
.dialog-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 2px;
}
</style>
src/views/fysp/scene/CompSceneBaseInfo.vue
@@ -5,20 +5,25 @@
      <el-form-item label="场景名称" prop="name">
        <el-input clearable show-word-limit v-model="formObj.name" placeholder="场景名称" />
      </el-form-item>
      <el-form-item label="场景类型" prop="_typeObj">
        <el-select v-model="formObj._typeObj" placeholder="场景类型">
      <!-- <el-form-item label="场景类型" prop="_scenetype">
        <el-select v-model="formObj._scenetype" placeholder="场景类型">
          <el-option v-for="s in sceneTypes" :key="s.value" :label="s.label" :value="s" />
        </el-select>
      </el-form-item>
      <el-form-item label="省/市/区/镇" prop="_locations">
        <el-cascader
          v-model="formObj._locations"
          :options="locations"
          placeholder="省/市/区/镇"
          style="width: 300px"
          :props="cascaderProps"
        />
      </el-form-item>
      </el-form-item> -->
      <!-- åœºæ™¯ç±»åž‹ -->
      <FYOptionScene
        :allOption="false"
        :type="2"
        v-model:value="formObj._scenetype"
      ></FYOptionScene>
      <!-- åŒºåŽ¿ -->
      <FYOptionLocation
        :allOption="false"
        :level="4"
        :initValue="false"
        :checkStrictly="true"
        v-model:value="formObj._locations"
      ></FYOptionLocation>
      <el-form-item label="地址" prop="location">
        <el-input show-word-limit clearable v-model="formObj.location" placeholder="地址" />
      </el-form-item>
@@ -64,9 +69,8 @@
</template>
<script setup>
import { defineProps, defineEmits, reactive, ref, watch, computed } from 'vue';
import { defineProps, defineEmits, reactive, ref, unref, watch, computed } from 'vue';
import { enumScene } from '@/enum/scene';
import { enumLocation } from '@/enum/location';
import sceneApi from '@/api/fysp/sceneApi';
const props = defineProps({
@@ -88,11 +92,7 @@
const emit = defineEmits(['onSubmit', 'onCancel']);
const sceneTypes = reactive(enumScene(2, false));
const locations = reactive(enumLocation(false));
const cascaderProps = reactive({
  checkStrictly: true
});
const sceneTypes = ref(enumScene(2, false));
const rules = reactive({
  name: [
    {
@@ -101,7 +101,7 @@
      trigger: 'blur'
    }
  ],
  _typeObj: [
  _scenetype: [
    {
      required: true,
      message: '场景类型不能为空',
@@ -136,19 +136,23 @@
 * å¯¹åœºæ™¯ç±»åž‹ã€åœºæ™¯è¡Œæ”¿åŒºåˆ’和场景可用状态进行格式化
 * @param {*} s åœºæ™¯ä¿¡æ¯
 */
function parseSceneBaseInfo(s) {
  s._typeObj = {
function parseSceneBaseInfo(param) {
  const s = unref(param);
  s._scenetype = {
    label: s.type,
    value: s.typeid + ''
  };
  s._locations = [];
  if (s.provincecode && s.provincecode.length > 0)
    s._locations.push([s.provincecode, s.provincename]);
  if (s.citycode && s.citycode.length > 0) s._locations.push([s.citycode, s.cityname]);
  if (s.districtcode && s.districtcode.length > 0)
    s._locations.push([s.districtcode, s.districtname]);
  if (s.towncode && s.towncode.length > 0) s._locations.push([s.towncode, s.townname]);
  s._locations = {
    pCode: s.provincecode,
    pName: s.provincename,
    cCode: s.citycode,
    cName: s.cityname,
    dCode: s.districtcode,
    dName: s.districtname,
    tCode: s.towncode,
    tName: s.townname
  };
  s.online = s.extension1 != '0';
@@ -181,25 +185,17 @@
function submit(v, success, fail) {
  // è¡Œæ”¿åŒºåˆ’信息填充
  const a = v.value._locations;
  if (a[0]) {
    v.value.provincecode = a[0][0];
    v.value.provincename = a[0][1];
  }
  if (a[1]) {
    v.value.citycode = a[1][0];
    v.value.cityname = a[1][1];
  }
  if (a[2]) {
    v.value.districtcode = a[2][0];
    v.value.districtname = a[2][1];
  }
  if (a[3]) {
    v.value.towncode = a[3][0];
    v.value.townname = a[3][1];
  }
  v.value.provincecode = a.pCode;
  v.value.provincename = a.pName;
  v.value.citycode     = a.cCode;
  v.value.cityname     = a.cName;
  v.value.districtcode = a.dCode;
  v.value.districtname = a.dName;
  v.value.towncode     = a.tCode;
  v.value.townname     = a.tName;
  // åœºæ™¯ç±»åž‹ä¿¡æ¯å¡«å……
  const b = v.value._typeObj;
  const b = v.value._scenetype;
  v.value.typeid = b.value;
  v.value.type = b.label;
src/views/fysp/scene/SceneEdit.vue
@@ -1,5 +1,5 @@
<template>
  <el-page-header @back="onBack">
  <el-page-header @back="onBack" class="page-header">
    <template #content>
      <span> åœºæ™¯ä¿¡æ¯ç¼–辑 </span>
    </template>
@@ -110,4 +110,7 @@
  margin-bottom: 30px;
  margin-left: 20px;
}
.page-header {
  /* position: absolute; */
}
</style>
src/views/fysp/scene/SceneInfo.vue
@@ -6,10 +6,15 @@
        :level="4"
        v-model:value="formSearch._locations"
      ></FYOptionLocation>
      <FYOptionText
        label="场景名称"
        placeholder="输入名称关键字"
        v-model:value="formSearch.searchText"
      ></FYOptionText>
      <FYOptionScene
        :allOption="true"
        :type="2"
        v-model:value="formSearch.scensetype"
        v-model:value="formSearch._scenetype"
      ></FYOptionScene>
      <FYOptionOnlineStatus
        :allOption="true"
@@ -79,7 +84,8 @@
    return {
      formSearch: {
        _locations: {},
        scensetype: {},
        searchText: '',
        _scenetype: {},
        online: {}
      }
    };
@@ -97,10 +103,12 @@
      area.districtcode = f._locations.dCode;
      area.towncode = f._locations.tCode;
      // åœºæ™¯ç±»åž‹
      area.scensetypeid = f.scensetype.value;
      area.scensetypeid = f._scenetype.value;
      if (area.scensetypeid == '0') area.scensetypeid = null;
      // ä¸Šä¸‹çº¿çŠ¶æ€
      area.online = f.online.value;
      // æŸ¥è¯¢å…³é”®å­—(场景名称)
      area.sceneName = f.searchText
      return sceneApi.searchScene(area, page.currentPage, page.pageSize).then((res) => {
        if (res.success) {
src/views/fytz/user/UserInfo.vue
@@ -7,7 +7,7 @@
        v-model:value="formSearch._locations"
      ></FYOptionLocation>
      <FYOptionText
        label="关键字"
        label="场景名称"
        placeholder="输入名称关键字"
        v-model:value="formSearch.searchText"
      ></FYOptionText>
src/views/fytz/user/components/CompUserInfo.vue
@@ -5,7 +5,7 @@
    :doClear="active"
    :useCancel="create"
    :useReset="!create"
    @updateEdit="(v) => $emit('updateEdit', v)"
    @update:isEdit="(v) => $emit('updateEdit', v)"
    @submit="submit"
    @cancel="$emit('onCancel')"
  >
src/views/fytz/user/components/CompUserInfoAddDrawer.vue
@@ -39,7 +39,7 @@
        // å¼¹å‡ºç¡®è®¤æ¡†
        useMessageBox({
          confirmMsg: '是否放弃已编辑的内容?',
          confirmTitle: '取消',
          confirmTitle: '关闭弹出框',
          onConfirm: () => {
            done();
          }