riku
2024-01-09 023ea35893ed047887a43555509335eec7a8b161
1. 编写评估任务模块中
已修改13个文件
已删除3个文件
已添加4个文件
已重命名2个文件
1013 ■■■■■ 文件已修改
src/api/fysp/evaluateApi.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/taskApi.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components.d.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/bg-task/FYBgTaskCard.vue 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/form/FYForm.vue 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/search-option/FYOptionScene.vue 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/search-option/FYOptionTime.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/timer.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/composables/timer2.js 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/styles/element/base.scss 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/DataSource.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/CompPreCheck.vue 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/CompQuickSet.vue 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/CompCheckArea.vue 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/CompCheckSource.vue 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/CompPreCheck.vue 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckArea.vue 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckExemption.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/notice/CompNoticeAdd.vue 71 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/notice/NoticeManage.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/fysp/evaluateApi.js
@@ -6,5 +6,14 @@
   */
  fetchAutoEvaluation(param) {
    return $fysp.post(`evaluation/auto/record`, param).then((res) => res.data);
  },
  /**
   * æŸ¥è¯¢è¯„估总规则
   * @param {Object} param
   * @returns
   */
  fetchEvaluationRule(param) {
    return $fysp.post(`evaluationrule/find`, param).then((res) => res.data);
  }
};
src/api/fysp/taskApi.js
@@ -9,6 +9,15 @@
  },
  /**
   * æŸ¥è¯¢æ€»ä»»åŠ¡
   * @param {Object} param
   * @returns
   */
  fetchTopTasks(param) {
    return $fysp.post('task/find', param).then((res) => res.data);
  },
  /**
   * èŽ·å–å­ä»»åŠ¡ç»Ÿè®¡ä¿¡æ¯
   */
  getSubtaskSummary({ topTaskId = undefined, sceneTypeId = undefined }) {
src/components.d.ts
@@ -61,6 +61,7 @@
    ElTag: typeof import('element-plus/es')['ElTag']
    ElText: typeof import('element-plus/es')['ElText']
    ElTooltip: typeof import('element-plus/es')['ElTooltip']
    ElTransfer: typeof import('element-plus/es')['ElTransfer']
    ElTree: typeof import('element-plus/es')['ElTree']
    Footer: typeof import('./components/core/Footer.vue')['default']
    FormCol: typeof import('./components/layout/FormCol.vue')['default']
src/components/bg-task/FYBgTaskCard.vue
@@ -21,7 +21,7 @@
      </el-col>
      <el-col :span="20" class="p-l-8">
        <el-row justify="space-between">
          <el-text class="m-l-4px w-150px" tag="b" size="large" truncated>{{ model.name }}</el-text>
          <el-text class="m-l-4px w-300px" tag="b" size="large" truncated>{{ model.name }}</el-text>
          <el-tag>{{ nameToLabel(model.type) }}</el-tag>
        </el-row>
        <el-row class="p-v-8" align="bottom">
@@ -91,12 +91,13 @@
</template>
<script>
import { nTlBgTask, BG_TASK_STATUS } from '@/enum/bgTask';
import { useTimer } from '../../composables/timer';
import { useTimer } from '@/composables/timer';
// import { useTimer } from '@/composables/timer2';
export default {
  setup() {
    const { time, startTimer, pauseTimer, stopTimer } = useTimer();
    return { time, startTimer, pauseTimer, stopTimer };
    const { time, startTimer, pauseTimer, stopTimer, count } = useTimer();
    return { time, startTimer, pauseTimer, stopTimer, count };
  },
  props: {
    model: Object,
@@ -110,6 +111,30 @@
      removeConfirm: false
    };
  },
  watch: {
    'model.status': {
      handler(nV) {
        switch (nV) {
          case BG_TASK_STATUS.WAITING.name:
            this.stopTimer();
            break;
          case BG_TASK_STATUS.RUNNING.name:
            this.startTimer();
            break;
          case BG_TASK_STATUS.SUCCESS.name:
          case BG_TASK_STATUS.FAIL.name:
          case BG_TASK_STATUS.SHUTDOWN.name:
            this.pauseTimer();
            break;
          default:
            this.stopTimer();
            break;
        }
        this.count = this.model.runTime
      },
      immediate: true
    }
  },
  computed: {
    waiting() {
      return this.model.status == BG_TASK_STATUS.WAITING.name;
src/components/form/FYForm.vue
@@ -69,13 +69,6 @@
      required: true,
      message: '行政区划不能为空',
      trigger: 'change'
      // validator: (rule, value, callback) => {
      //   if (!value) {
      //     callback(new Error('Please input the age'));
      //   } else {
      //     callback()
      //   }
      // }
    }
  ],
  _scenetype: [
@@ -83,13 +76,6 @@
      required: true,
      message: '场景类型不能为空',
      trigger: 'change'
      // validator: (rule, value, callback) => {
      //   if (!value) {
      //     callback(new Error('Please input the age'));
      //   } else {
      //     callback()
      //   }
      // }
    }
  ]
});
src/components/search-option/FYOptionScene.vue
@@ -6,12 +6,7 @@
      placeholder="场景类型"
      style="width: 150px"
    >
      <el-option
        v-for="s in sceneTypes"
        :key="s.value"
        :label="s.label"
        :value="s"
      />
      <el-option v-for="s in sceneTypes" :key="s.value" :label="s.label" :value="s" />
    </el-select>
  </el-form-item>
</template>
@@ -24,30 +19,45 @@
    // æ˜¯å¦åœ¨é¦–选项处添加“全部”选项
    allOption: {
      type: Boolean,
      default: true,
      default: true
    },
    // 1:飞羽环境系统;2:飞羽监管系统;
    type: {
      type: Number,
      default: 1,
      default: 1
    },
    // è¿”回结果
    value: Object,
    // æ˜¯å¦é»˜è®¤è¿”回初始选项
    initValue: {
      type: Boolean,
      default: true,
      default: true
    },
    // form表单绑定属性名
    prop: {
      type: String,
      default: '_scenetype'
    },
    // åˆ‡æ¢ type åŽï¼Œå½“前选项是否清空
    sourceInit: {
      type: Boolean,
      default: true
    }
  },
  emits: ['update:value'],
  data() {
    return {
      sceneTypes: enumScene(this.type, this.allOption),
      // sceneTypes: enumScene(this.type, this.allOption),
    };
  },
  computed: {
    sceneTypes() {
      if (this.sourceInit) {
        // å½“因为type或者allOption参数变化引起选项变更时,清空当前选项
        this.handleChange();
      }
      return enumScene(this.type, this.allOption);
    }
  },
  methods: {
    handleChange(value) {
@@ -58,6 +68,6 @@
    if (this.initValue) {
      this.handleChange(this.sceneTypes[0]);
    }
  },
  }
};
</script>
src/components/search-option/FYOptionTime.vue
@@ -1,9 +1,9 @@
<template>
  <el-form-item label="时间" :prop="prop">
    <el-date-picker
      :model-value="value"
      v-model="date"
      @change="handleChange"
      type="month"
      :type="type"
      placeholder="选择时间"
      style="width: 150px"
    />
@@ -32,7 +32,11 @@
  },
  emits: ['update:value'],
  data() {
    return {};
    return {
      date: this.value
    };
  },
  computed:{
  },
  methods: {
    handleChange(value) {
@@ -49,7 +53,8 @@
  },
  mounted() {
    if (this.initValue) {
      this.handleChange(new Date());
      this.date = new Date()
      this.handleChange(this.date);
    }
  }
};
src/composables/timer.js
@@ -38,5 +38,5 @@
    count.value = 0;
  }
  return { time, startTimer, pauseTimer, stopTimer, running };
  return { time, startTimer, pauseTimer, stopTimer, running, count };
}
src/composables/timer2.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,95 @@
import { ref, computed, watch } from 'vue';
import { useNow } from '@vueuse/core';
/**
 * ç§’表计时器
 */
export function useTimer() {
  const startTime = ref(new Date());
  const endTime = ref(new Date());
  const { now, pause, resume } = useNow({ controls: true });
  // æ—¶é—´åç§»é‡ï¼ˆå½“初始时间从服务器等外部设备获取时,浏览器所在设备的时间会与其有误差,为了计时器严格在0秒启动,记录其之间的偏移量)
  const offset = ref(0)
  // è¿è¡ŒçŠ¶æ€ï¼Œ0:停止;1:运行中;2:暂停
  const status = ref(0);
  const time = computed(() => {
    if (status.value == 0) {
      return `00:00:00`;
    }
    let seconds = 0;
    if (status.value == 2) {
      seconds = endTime.value.getTime() - startTime.value.getTime();
    } else {
      seconds = now.value.getTime() - startTime.value.getTime();
    }
    seconds = (seconds + offset.value) / 1000
    const hour = Math.floor(seconds / 3600);
    const min = Math.floor((seconds - hour * 3600) / 60);
    const sec = Math.floor(seconds - hour * 3600 - min * 60);
    // console.log(seconds);
    // console.log(hour);
    // console.log(min);
    // console.log(sec);
    return `${hour.toString().padStart(2, '0')}:${min.toString().padStart(2, '0')}:${sec
      .toString()
      .padStart(2, '0')}`;
  });
  watch(startTime, (nV)=>{
  })
  /**
   * å¯åŠ¨è®¡æ—¶å™¨
   * @param {Date} s åˆå§‹æ—¶é—´
   */
  function startTimer(s) {
    status.value = 1;
    if (s) {
      startTime.value = new Date(s);
    } else {
      startTime.value = new Date();
    }
    resumeTimer();
  }
  /**
   * ç»§ç»­è®¡æ—¶å™¨
   */
  function resumeTimer() {
    // now.value = startTime.value;
    offset.value = startTime.value.getTime() - now.value.getTime()
    resume();
  }
  /**
   * æš‚停计时器
   */
  function pauseTimer(s, e) {
    status.value = 2;
    if (s) {
      startTime.value = new Date(s);
    }
    if (e) {
      endTime.value = new Date(e);
    } else {
      endTime.value = new Date();
    }
    offset.value = 0
    pause();
  }
  /**
   * åœæ­¢è®¡æ—¶å™¨
   */
  function stopTimer() {
    pauseTimer();
    status.value = 0;
  }
  return { time, startTimer, resumeTimer, pauseTimer, stopTimer, status, startTime };
}
src/styles/element/base.scss
@@ -51,25 +51,42 @@
  background-color: aqua;
}
//
.p-l-8 {
  padding-left: 8px;
/************************************** å†…外边距 **************************************/
$direction: (
  l: 'left',
  t: 'top',
  r: 'right',
  b: 'bottom'
);
$size: (4, 8, 10, 16);
@each $dName, $dValue in $direction {
  @each $i in $size {
    .p-#{$dName}-#{$i} {
      padding-#{$dValue}: #{$i}px;
    }
    .m-#{$dName}-#{$i} {
      margin-#{$dValue}: #{$i}px;
    }
  }
}
.p-v-8 {
  padding: 8px 0;
@each $i in $size {
  .p-v-#{$i} {
    padding: #{$i}px 0;
  }
  .p-h-#{$i} {
    padding: 0 #{$i}px;
  }
  .m-v-#{$i} {
    margin: #{$i}px 0;
  }
  .m-h-#{$i} {
    margin: 0 #{$i}px;
  }
}
.m-b-8 {
  margin-bottom: 8px;
}
.m-l-4 {
  margin-left: 4px;
}
.w-150px {
  width: 290px;
.w-300px {
  width: 300px;
}
//
src/views/fysp/evaluation/DataSource.vue
@@ -11,7 +11,7 @@
<script>
import CompEvaTask from './components/CompEvaTask.vue';
import CompPreCheck from './components/CompPreCheck.vue';
import CompPreCheck from './components/precheck/CompPreCheck.vue';
export default {
  name: 'DataSource',
  components: { CompPreCheck, CompEvaTask },
src/views/fysp/evaluation/components/CompPreCheck.vue
ÎļþÒÑɾ³ý
src/views/fysp/evaluation/components/CompQuickSet.vue
@@ -32,7 +32,8 @@
              dCode: '310106',
              dName: '静安区',
            },
            scenetype: { label: '工地', value: '1' }
            scenetype: { label: '工地', value: '1' },
            sourcetype: false,
          },
          {
            name: '徐汇餐饮',
@@ -44,7 +45,8 @@
              dCode: '310104',
              dName: '徐汇区'
            },
            scenetype: { label: '餐饮', value: '5' }
            scenetype: { label: '餐饮', value: '5' },
            sourcetype: false,
          },
          {
            name: '金山工地',
@@ -56,7 +58,8 @@
              dCode: '310116',
              dName: '金山区'
            },
            scenetype: { label: '工地', value: '1' }
            scenetype: { label: '工地', value: '1' },
            sourcetype: false,
          },
          {
            name: '金山码头',
@@ -68,7 +71,8 @@
              dCode: '310116',
              dName: '金山区'
            },
            scenetype: { label: '码头', value: '2' }
            scenetype: { label: '码头', value: '2' },
            sourcetype: false,
          },
          {
            name: '金山搅拌站',
@@ -80,7 +84,21 @@
              dCode: '310116',
              dName: '金山区'
            },
            scenetype: { label: '搅拌站', value: '3' }
            scenetype: { label: '搅拌站', value: '3' },
            sourcetype: false,
          },
          {
            name: '徐汇汽修',
            locations: {
              pCode: '31',
              pName: '上海市',
              cCode: '3100',
              cName: '上海市',
              dCode: '310104',
              dName: '徐汇区'
            },
            scenetype: { label: '汽修', value: '7' },
            sourcetype: true,
          }
        ]
      }
src/views/fysp/evaluation/components/precheck/CompCheckArea.vue
ÎļþÒÑɾ³ý
src/views/fysp/evaluation/components/precheck/CompCheckSource.vue
ÎļþÒÑɾ³ý
src/views/fysp/evaluation/components/precheck/CompPreCheck.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,57 @@
<template>
  <el-steps :active="stepIndex" finish-status="success" style="" align-center>
    <el-step title="评估范围" />
    <el-step title="数据源检查" />
    <el-step title="豁免条目" />
    <el-step title="自动评估" />
  </el-steps>
  <CompCheckArea v-show="stepIndex == 0" v-model="stepIndex" @change="onAreaChange"></CompCheckArea>
  <CompCheckSource
    v-show="stepIndex == 1"
    v-model="stepIndex"
    ref="refSource"
  ></CompCheckSource>
  <CompCheckExemption v-show="stepIndex == 2" v-model="stepIndex"></CompCheckExemption>
  <CompCheckConfirm v-show="stepIndex == 3" v-model="stepIndex"></CompCheckConfirm>
</template>
<script>
import dayjs from 'dayjs';
import CompCheckArea from './components/CompCheckArea.vue';
import CompCheckSource from './components/CompCheckSource.vue';
import CompCheckExemption from './components/CompCheckExemption.vue';
import CompCheckConfirm from './components/CompCheckConfirm.vue';
/**
 * è‡ªåŠ¨è¯„ä¼°æ¡ä»¶åˆè§„æ€§æ£€æŸ¥
 */
export default {
  name: 'CompPreCheck',
  components: { CompCheckArea, CompCheckSource, CompCheckExemption, CompCheckConfirm },
  props: {},
  emits: ['preCheck'],
  data() {
    return {
      // æ“ä½œæ­¥éª¤ä¸‹æ ‡
      stepIndex: 0,
      area: {}
    };
  },
  methods: {
    /**
     * ç›‘听评估范围变更
     */
    onAreaChange(v) {
      // this.area = v;
      this.$refs.refSource.startCheck(v);
    },
    /**
     * è‡ªåŠ¨è¯„ä¼°å‰ç½®åˆè§„æ€§æ£€æŸ¥
     * æ£€æŸ¥æ‰€é€‰èŒƒå›´å†…各项评估数据源是否完整
     */
    preCheck() {
      // this.$emit('preCheck', param)
    }
  }
};
</script>
src/views/fysp/evaluation/components/precheck/components/CompCheckArea.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,128 @@
<template>
  <el-card shadow="never">
    <template #header>
      <div><el-text tag="b" size="large">选择评估范围</el-text></div>
      <el-text size="small" type="info">包括区县、场景类型以及月份</el-text>
    </template>
    <FormCol>
      <FYForm ref="formRef" :rules="evaConditionRules" :showButtons="false" @submit="nextStep">
        <template #form-item="{ formObj }">
          <CompQuickSet @quick-set="setOptions"></CompQuickSet>
          <!-- åŒºåŽ¿ -->
          <FYOptionLocation
            :allOption="false"
            :level="3"
            :initValue="false"
            :checkStrictly="false"
            v-model:value="formObj._locations"
          ></FYOptionLocation>
          <!-- åœºæ™¯ç±»åž‹ -->
          <FYOptionScene
            :allOption="false"
            :initValue="false"
            :sourceInit="sceneOptionSourceInit"
            :type="formObj.sourcetype ? 1 : 2"
            v-model:value="formObj._scenetype"
          ></FYOptionScene>
          <!-- æ—¶é—´ -->
          <FYOptionTime
            prop="time"
            :initValue="true"
            type="month"
            v-model:value="formObj.time"
          ></FYOptionTime>
          <el-form-item label="主数据源" prop="sourcetype">
            <el-switch v-model="formObj.sourcetype" @change="sceneOptionSourceInit = true" />
            <span class="m-l-16">{{ formObj.sourcetype ? '守法服务记录' : '现场巡查记录' }}</span>
            <el-tooltip placement="bottom-start" effect="light">
              <template #content>
                <!-- <el-text tag="b" size="default">说明</el-text><br /> -->
                <el-text tag="i" size="default" type="warning"
                  >该选项是用于决定评估主体对象的获取方式</el-text
                ><br />
                <el-text tag="b" size="small">守法服务记录:</el-text><br />
                <el-text size="small"
                  >表示在评估时,评估对象是从守法服务小程序系统中获取的当前可用的用户;<br />
                  ä¸€èˆ¬æƒ…况下,当评估对象没有进行现场巡查,只有守法服务相关记录时,采用此选项;</el-text
                ><br />
                <el-text tag="b" size="small">现场巡查记录:</el-text><br />
                <el-text size="small"
                  >表示在评估时,评估对象是从现场巡查监管系统中获取的总任务下的所有监管场景;<br />
                  ä¸€èˆ¬æƒ…况下,当评估对象有进行现场巡查,采用此选项; </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-form-item>
        </template>
      </FYForm>
    </FormCol>
    <template #footer>
      <el-row justify="space-around">
        <el-button type="primary" size="default" :loading="loading" @click="submit"
          >下一步</el-button
        >
      </el-row>
    </template>
  </el-card>
</template>
<script>
import CompQuickSet from '../../CompQuickSet.vue';
/**
 * è¯„估范围合规性检查
 */
export default {
  components: { CompQuickSet },
  props: {
    // æ­¥éª¤ä¸‹æ ‡
    modelValue: Number
  },
  emits: ['update:modelValue', 'change'],
  data() {
    return {
      loading: false,
      evaConditionRules: {
        time: [
          {
            required: true,
            message: '时间不能为空',
            trigger: 'change'
          }
        ]
      },
      // å½“场景选项切换数据源时,是否清空当前选项值
      sceneOptionSourceInit: true
    };
  },
  methods: {
    setOptions(param) {
      this.sceneOptionSourceInit = false;
      this.$refs.formRef.formObj._locations = param.locations;
      this.$refs.formRef.formObj._scenetype = param.scenetype;
      this.$refs.formRef.formObj.sourcetype = param.sourcetype;
    },
    submit() {
      this.$refs.formRef.onSubmit(false);
    },
    // è·³è½¬ä¸‹ä¸€æ­¥
    nextStep(formObj, success, fail) {
      // todo: æ£€æŸ¥æ˜¯å¦å·²æœ‰è¯„估记录,提示用户可直接跳转查看或继续下一步
      this.loading = true;
      return new Promise((reslove, reject) => {
        setTimeout(() => {
          this.$emit('change', formObj);
          this.$emit('update:modelValue', this.modelValue + 1);
          this.loading = false;
          success();
          reslove();
        }, 1000);
      });
    }
  }
};
</script>
src/views/fysp/evaluation/components/precheck/components/CompCheckConfirm.vue
src/views/fysp/evaluation/components/precheck/components/CompCheckExemption.vue
src/views/fysp/evaluation/components/precheck/components/CompCheckSource.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,182 @@
<template>
  <el-card shadow="never">
    <template #header>
      <div><el-text tag="b" size="large">数据源检查</el-text></div>
      <el-text size="small" type="info">检查评估所需数据源是否完整</el-text>
    </template>
    <FormCol>
      <el-form-item align="middle" v-for="(v, i) in checkResults" :key="i">
        <el-col :span="14">
          <el-row align="middle">
            <el-text size="default" :class="v.required ? 'required' : 'not-required'">*</el-text>
            <el-text size="default" class="m-l-4">{{ v.name }}</el-text>
          </el-row>
        </el-col>
        <el-col :span="5">
          <el-row align="middle">
            <el-space>
              <template v-if="v.loading">
                <el-icon class="is-loading"><Loading /></el-icon>
                <el-text size="default" type="default">检查中...</el-text>
              </template>
              <template v-else-if="v.pass == true">
                <el-icon color="var(--el-color-success)"><Check /></el-icon>
                <el-text size="default" type="success">通过</el-text>
              </template>
              <template v-else-if="v.pass == false">
                <el-icon color="var(--el-color-danger)"><Close /></el-icon>
                <el-text size="default" type="danger">缺失</el-text>
              </template>
              <template v-else>
                <el-icon color="var(--el-color-warning)"><Warning /></el-icon>
                <el-text size="default" type="warning">暂略过</el-text>
              </template>
            </el-space>
          </el-row>
        </el-col>
        <el-col :span="5">
          <el-button
            v-if="!v.pass"
            type="primary"
            size="small"
            @click="goto(v.path)"
            :disabled="v.path == ''"
          >
            åŽ»å®Œå–„
            <el-icon class="m-l-4"><Right /></el-icon>
          </el-button>
        </el-col>
      </el-form-item>
    </FormCol>
    <template #footer>
      <el-row justify="space-around">
        <el-button type="primary" size="default" @click="lastStep">上一步</el-button>
        <el-button :disabled="!checkPass" type="primary" size="default" @click="nextStep"
          >下一步</el-button
        >
      </el-row>
    </template>
  </el-card>
</template>
<script>
import evaluateApi from '@/api/fysp/evaluateApi';
import taskApi from '@/api/fysp/taskApi';
/**
 * ç”Ÿæˆä¸€é¡¹æ•°æ®æºæ£€æŸ¥è®°å½•
 * @param {*} _name
 * @param {*} _path
 * @param {*} _fetch
 * @param {*} _required
 */
function baseCheckItem(_name, _path, _fetch, _required) {
  return {
    required: _required,
    name: _name,
    loading: true,
    pass: false,
    path: _path,
    async fetch() {
      this.loading = true;
      setTimeout(async () => {
        this.pass = await _fetch();
        this.loading = false;
      }, 1000);
    }
  };
}
/**
 * è¯„估数据源完整性检查
 */
export default {
  props: {
    // æ­¥éª¤ä¸‹æ ‡
    modelValue: Number
  },
  emits: ['update:modelValue'],
  data() {
    return {
      areaInfo: {
        _locations: '',
        _scenetype: '',
        time: '',
        sourcetype: ''
      },
      // æ•°æ®æºæ£€æŸ¥è®°å½•
      checkResults: [
        baseCheckItem(
          '自动评估规则表',
          '',
          () => {
            const param = {
              taskTypeId: 99,
              scensetypeid: this.areaInfo._scenetype.value
            };
            return evaluateApi.fetchEvaluationRule(param).then((res) => {
              return res.data.length > 0;
            });
          },
          true
        ),
        baseCheckItem('现场监管巡查总任务', '', () => {}),
        baseCheckItem('现场监测数据', '', () => {}),
        baseCheckItem('监管点位与监测点匹配', '', () => {}),
        baseCheckItem('现场监管问题类型', '', () => {}),
        baseCheckItem('信访投诉', '', () => {}),
        baseCheckItem('行政处罚', '', () => {})
      ]
    };
  },
  computed: {
    /**
     * åˆ¤æ–­æ•°æ®æºæ£€æŸ¥æ˜¯å¦é€šè¿‡
     * å…¨éƒ¨åŠ è½½å®ŒæˆåŽï¼Œå¿…è¦é¡¹å¿…é¡»é€šè¿‡ï¼Œå¯é€‰é¡¹éžå¿…é¡»é€šè¿‡
     */
    checkPass() {
      let res = true;
      this.checkResults.forEach((e) => {
        if (e.loading) {
          res = res && false;
        } else if (e.required) {
          res = res && e.pass;
        }
      });
      return res;
    }
  },
  methods: {
    // è·³è½¬ä¸‹ä¸€æ­¥
    nextStep() {
      this.$emit('update:modelValue', this.modelValue + 1);
    },
    // è·³è½¬ä¸Šä¸€æ­¥
    lastStep() {
      this.$emit('update:modelValue', this.modelValue - 1);
    },
    // è·³è½¬æ£€æŸ¥é¡¹çš„链接
    goto(path) {
      if (path && path != '') {
        this.$router.push(path);
      }
    },
    // å¼€å§‹æ£€æŸ¥ä»»åŠ¡
    startCheck(v) {
      this.areaInfo = v;
      this.checkResults.forEach((e) => {
        e.fetch();
      });
    }
  }
};
</script>
<style scoped>
.required {
  color: var(--el-color-danger);
}
.not-required {
  color: transparent;
}
</style>
src/views/notice/CompNoticeAdd.vue
@@ -1,11 +1,5 @@
<template>
  <el-form
    :inline="false"
    :model="form"
    ref="formRef"
    :rules="rules"
    label-position="top"
  >
  <el-form :inline="false" :model="form" ref="formRef" :rules="rules" label-position="top">
    <el-form-item label="通知标题" prop="title">
      <el-input v-model="form.title" placeholder="通知标题" />
    </el-form-item>
@@ -22,22 +16,19 @@
    </el-form-item>
    <el-form-item label="区县类型" prop="district">
      <el-select v-model="form.district" placeholder="区县类型">
        <el-option
          v-for="s in districts"
          :key="s.value"
          :label="s.label"
          :value="s.value"
        />
        <el-option v-for="s in districts" :key="s.value" :label="s.label" :value="s.value" />
      </el-select>
    </el-form-item>
    <el-form-item label="场景类型" prop="receiverType">
      <el-select v-model="form.receiverType" placeholder="场景类型">
        <el-option
          v-for="s in sceneTypes"
          :key="s.value"
          :label="s.label"
          :value="s.value"
        />
    <!-- <FYOptionScene
        prop="receiverType"
        :allOption="true"
        :type="1"
        :initValue="true"
        v-model:value="form.receiverType"
      ></FYOptionScene> -->
    <el-form-item label="场景类型" prop="_receiverType">
      <el-select v-model="form._receiverType" placeholder="场景类型">
        <el-option v-for="s in sceneTypes" :key="s.value" :label="s.label" :value="s.value" />
      </el-select>
    </el-form-item>
    <el-form-item label="是否需要签收" prop="needSigned">
@@ -45,9 +36,7 @@
      <span style="margin-left: 16px">{{ form.needSigned ? '是' : '否' }}</span>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit" :loading="loading"
        >提交</el-button
      >
      <el-button type="primary" @click="onSubmit" :loading="loading">提交</el-button>
      <el-button @click="onCancel">取消</el-button>
    </el-form-item>
  </el-form>
@@ -62,10 +51,10 @@
  props: {
    active: {
      type: Boolean,
      default: false,
      default: false
    },
    edit: Boolean,
    loading: Boolean,
    loading: Boolean
  },
  emits: ['update:edit', 'onSubmit', 'onCancel'],
  data() {
@@ -98,35 +87,36 @@
        //是否需要签收
        needSigned: false,
        //接受用户场景类型
        _receiverType: null,
        receiverType: '0',
        //接受用户区县
        district: '0',
        //接受用户id
        receiverId: null,
        receiverId: null
      },
      rules: {
        title: [
          {
            required: true,
            message: '请输入通知标题',
            trigger: 'blur',
          },
            trigger: 'blur'
          }
        ],
        content: [
          {
            required: true,
            message: '请输入通知内容',
            trigger: 'blur',
          },
            trigger: 'blur'
          }
        ],
        _typeArray: [
          {
            required: true,
            message: '请选择通知类型',
            trigger: 'change',
          },
        ],
      },
            trigger: 'change'
          }
        ]
      }
    };
  },
  watch: {
@@ -149,8 +139,8 @@
        }
        this.isReset = false;
      },
      deep: true,
    },
      deep: true
    }
  },
  computed: {},
  methods: {
@@ -170,6 +160,9 @@
            this.form.typeId = a[0];
            this.form.subTypeId = 0;
          }
          if (this.form._receiverType == null) {
            this.form.receiverType = '0';
          }
          this.$emit('onSubmit', this.form);
        } else {
          console.log('error submit!', fields);
@@ -179,10 +172,10 @@
    onCancel() {
      // this.reset();
      this.$emit('onCancel');
    },
    }
  },
  mounted() {
    this.noticeTypes[0].disabled = true;
  },
  }
};
</script>
src/views/notice/NoticeManage.vue
@@ -118,7 +118,7 @@
    />
    <el-table-column width="160" prop="ecCreator" label="创建人" />
    <!-- <el-table-column prop="ecPicurl" label="图片" /> -->
    <el-table-column prop="ecReceiverid" label="签收人" />
    <!-- <el-table-column prop="ecReceiverid" label="签收人" /> -->
  </el-table>
  <!-- <el-affix :offset="0" position="bottom"> -->
  <el-pagination