yuanmingze пре 5 месеци
родитељ
комит
bb233428de


+ 1 - 0
package.json

@@ -51,6 +51,7 @@
     "vue-enum": "^1.0.5",
     "vue-json-editor": "^1.4.3",
     "vue-json-tree-view": "^2.1.6",
+    "vue-masonry": "^0.16.0",
     "vue-quill-editor": "^3.0.6",
     "vue-router": "^3.6.5",
     "vue-template-compiler": "^2.6.14",

+ 71 - 0
pnpm-lock.yaml

@@ -128,6 +128,9 @@ importers:
       vue-json-tree-view:
         specifier: ^2.1.6
         version: 2.1.6
+      vue-masonry:
+        specifier: ^0.16.0
+        version: 0.16.0(vue@2.7.16)
       vue-quill-editor:
         specifier: ^3.0.6
         version: 3.0.6
@@ -2108,6 +2111,9 @@ packages:
     resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
     engines: {node: '>= 0.8'}
 
+  desandro-matches-selector@2.0.2:
+    resolution: {integrity: sha512-+1q0nXhdzg1IpIJdMKalUwvvskeKnYyEe3shPRwedNcWtnhEKT3ZxvFjzywHDeGcKViIxTCAoOYQWP1qD7VNyg==}
+
   destroy@1.2.0:
     resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
     engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -2355,6 +2361,9 @@ packages:
     resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
     engines: {node: '>= 0.6'}
 
+  ev-emitter@1.1.1:
+    resolution: {integrity: sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q==}
+
   event-emitter@0.3.5:
     resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==}
 
@@ -2451,6 +2460,9 @@ packages:
     resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
     engines: {node: '>=8'}
 
+  fizzy-ui-utils@2.0.7:
+    resolution: {integrity: sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg==}
+
   flat-cache@3.2.0:
     resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
     engines: {node: ^10.12.0 || >=12.0.0}
@@ -2533,6 +2545,9 @@ packages:
     resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==}
     engines: {node: '>= 0.4'}
 
+  get-size@2.0.3:
+    resolution: {integrity: sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q==}
+
   get-stream@3.0.0:
     resolution: {integrity: sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==}
     engines: {node: '>=4'}
@@ -2732,6 +2747,9 @@ packages:
     engines: {node: '>=0.10.0'}
     hasBin: true
 
+  imagesloaded@4.1.4:
+    resolution: {integrity: sha512-ltiBVcYpc/TYTF5nolkMNsnREHW+ICvfQ3Yla2Sgr71YFwQ86bDwV9hgpFhFtrGPuwEx5+LqOHIrdXBdoWwwsA==}
+
   immutable@5.0.3:
     resolution: {integrity: sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==}
 
@@ -3084,6 +3102,9 @@ packages:
     resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
     engines: {node: '>=8'}
 
+  masonry-layout@4.2.2:
+    resolution: {integrity: sha512-iGtAlrpHNyxaR19CvKC3npnEcAwszXoyJiI8ARV2ePi7fmYhIud25MHK8Zx4P0LCC4d3TNO9+rFa1KoK1OEOaA==}
+
   material-colors@1.2.6:
     resolution: {integrity: sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==}
 
@@ -3170,6 +3191,9 @@ packages:
     resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
     engines: {node: '>=8'}
 
+  mitt@3.0.1:
+    resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==}
+
   mkdirp@0.5.6:
     resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==}
     hasBin: true
@@ -3359,6 +3383,9 @@ packages:
     resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==}
     engines: {node: '>=10'}
 
+  outlayer@2.1.1:
+    resolution: {integrity: sha512-+GplXsCQ3VrbGujAeHEzP9SXsBmJxzn/YdDSQZL0xqBmAWBmortu2Y9Gwdp9J0bgDQ8/YNIPMoBM13nTwZfAhw==}
+
   p-finally@1.0.0:
     resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==}
     engines: {node: '>=4'}
@@ -4523,6 +4550,15 @@ packages:
       vue:
         optional: true
 
+  vue-masonry@0.16.0:
+    resolution: {integrity: sha512-0Wi/BH4iYYRrAAFY/wokczz0lWWPg1vmOvFW4aC2nKybKf6kVqUvFfR9/+izDfzG657/vY+Om0gqOB5YPxPxuQ==}
+    peerDependencies:
+      '@vue/composition-api': ^1.0.0-rc.1
+      vue: ^2.0.0 || >=3.0.0
+    peerDependenciesMeta:
+      '@vue/composition-api':
+        optional: true
+
   vue-quill-editor@3.0.6:
     resolution: {integrity: sha512-g20oSZNWg8Hbu41Kinjd55e235qVWPLfg4NvsLW6d+DhgBTFbEuMpcWlUdrD6qT3+Noim6DRu18VLM9lVShXOQ==}
     engines: {node: '>= 4.0.0', npm: '>= 3.0.0'}
@@ -7074,6 +7110,8 @@ snapshots:
 
   depd@2.0.0: {}
 
+  desandro-matches-selector@2.0.2: {}
+
   destroy@1.2.0: {}
 
   detect-libc@1.0.3:
@@ -7347,6 +7385,8 @@ snapshots:
 
   etag@1.8.1: {}
 
+  ev-emitter@1.1.1: {}
+
   event-emitter@0.3.5:
     dependencies:
       d: 1.0.2
@@ -7501,6 +7541,10 @@ snapshots:
       locate-path: 5.0.0
       path-exists: 4.0.0
 
+  fizzy-ui-utils@2.0.7:
+    dependencies:
+      desandro-matches-selector: 2.0.2
+
   flat-cache@3.2.0:
     dependencies:
       flatted: 3.3.2
@@ -7573,6 +7617,8 @@ snapshots:
       dunder-proto: 1.0.1
       es-object-atoms: 1.0.0
 
+  get-size@2.0.3: {}
+
   get-stream@3.0.0: {}
 
   get-stream@4.1.0:
@@ -7772,6 +7818,10 @@ snapshots:
   image-size@0.5.5:
     optional: true
 
+  imagesloaded@4.1.4:
+    dependencies:
+      ev-emitter: 1.1.1
+
   immutable@5.0.3: {}
 
   import-fresh@3.3.0:
@@ -8083,6 +8133,11 @@ snapshots:
     dependencies:
       semver: 6.3.1
 
+  masonry-layout@4.2.2:
+    dependencies:
+      get-size: 2.0.3
+      outlayer: 2.1.1
+
   material-colors@1.2.6: {}
 
   math-intrinsics@1.1.0: {}
@@ -8148,6 +8203,8 @@ snapshots:
     dependencies:
       yallist: 4.0.0
 
+  mitt@3.0.1: {}
+
   mkdirp@0.5.6:
     dependencies:
       minimist: 1.2.8
@@ -8327,6 +8384,12 @@ snapshots:
       strip-ansi: 6.0.1
       wcwidth: 1.0.1
 
+  outlayer@2.1.1:
+    dependencies:
+      ev-emitter: 1.1.1
+      fizzy-ui-utils: 2.0.7
+      get-size: 2.0.3
+
   p-finally@1.0.0: {}
 
   p-limit@2.3.0:
@@ -9558,6 +9621,14 @@ snapshots:
       '@vue/compiler-sfc': 3.5.13
       vue: 2.7.16
 
+  vue-masonry@0.16.0(vue@2.7.16):
+    dependencies:
+      imagesloaded: 4.1.4
+      masonry-layout: 4.2.2
+      mitt: 3.0.1
+      vue: 2.7.16
+      vue-demi: 0.13.11(vue@2.7.16)
+
   vue-quill-editor@3.0.6:
     dependencies:
       object-assign: 4.1.1

+ 10 - 0
src/api/serviceManagement/servicesToBeReviewed/index.js

@@ -77,3 +77,13 @@ export function getPkgV2Api() {
     method: 'get'
   });
 }
+
+// 获取平铺的任务
+
+export function getTaskV2PageTileApi(params) {
+  return request({
+    url: ' /admin/task/v2/page/tile',
+    method: 'get',
+    params: params
+  });
+}

+ 2 - 0
src/main.js

@@ -29,6 +29,7 @@ import Enum from 'vue-enum';
 import enumInfo from '@/const/constants';
 import Avue from '@smallwei/avue';
 import '@smallwei/avue/lib/index.css';
+import { VueMasonryPlugin } from 'vue-masonry';
 
 Vue.use(ElementUI, {
   size: 'small',
@@ -46,6 +47,7 @@ Vue.use(VueAxios, axios);
 Vue.use(AvueUeditor);
 Vue.use(VueCropper);
 Vue.use(AvueMap);
+Vue.use(VueMasonryPlugin);
 
 Vue.use(ViewUI); //iview
 

+ 0 - 2
src/router/axios.js

@@ -91,8 +91,6 @@ axios.interceptors.response.use(
     }
 
     if (status !== 200 || res.data.code === 1) {
-      console.log('qaqcc');
-
       Message({
         message: message,
         type: 'error'

+ 406 - 8
src/views/serviceManagement/quickReview/index.vue

@@ -1,5 +1,10 @@
 <template>
   <div>
+    <basic-container class="cardTitle">
+      <p>
+        <el-button type="primary" @click="backPage" style="width: 80px">返回</el-button>
+      </p>
+    </basic-container>
     <basic-container>
       <div class="search-content">
         <el-form :model="searchFrom" label-width="140px">
@@ -81,15 +86,133 @@
         </el-form>
       </div>
     </basic-container>
-    <basic-container>测试qaq</basic-container>
+    <basic-container>
+      <div class="card-list">
+        <div v-infinite-scroll="getList" style="overflow: auto">
+          <div class="cards" v-masonry :gutter="20">
+            <div v-for="curr in list" class="card" v-masonry-tile :key="curr.info.taskId">
+              <div class="task-info">
+                <div class="task-type-info">服务类型: {{ getName(curr?.info.taskTypeId) }}</div>
+                <div class="info">
+                  <p>任务ID:{{ curr?.info.taskId }}</p>
+                  <p>任务编号:{{ curr?.info.taskNumber }}</p>
+                </div>
+                <div class="info">
+                  <p>服务积分:{{ curr?.info.taskScore }}</p>
+                  <p>代表姓名:{{ curr?.info.salesName }}</p>
+                </div>
+                <div class="info">
+                  <p>产品名称:{{ curr?.info.skuName }}</p>
+                  <p>生产企业:{{ curr?.info.mahName }}</p>
+                </div>
+                <div class="info">
+                  <p>执行包名称:{{ curr?.info.pkgName }}</p>
+                  <p>起止时间:{{ curr?.info.pkgStartTime }} ~ {{ curr?.info.pkgEndTime }}</p>
+                </div>
+              </div>
+              <div class="detail">服务详情</div>
+              <template v-if="curr?.info?.configs">
+                <div v-for="(item, index) in curr?.info?.configs" :key="index" class="field-box">
+                  <template v-if="item.taskFiledType == 'domain' || item.taskFiledType == 'select'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value" v-show="!(item.taskTypeId == '19' && item.taskFiledKey == 'temp3')">
+                      {{ getDesc(curr.info, item) }}
+                    </div>
+                  </template>
+                  <!-- 城市选择 -->
+                  <template v-if="item.taskFiledType === 'area'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value">
+                      {{ curr.info.taskContent[item.taskFiledKey] || '--' }}
+                    </div>
+                  </template>
+                  <!-- 文字输入 -->
+                  <template v-if="item.taskFiledType == 'text' || item.taskFiledType == 'inputautoselect' || item.taskFiledType == 'map' || item.taskFiledType == 'mapwithimg'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value">
+                      {{ curr.info.taskContent[item.taskFiledKey] || '--' }}
+                    </div>
+                  </template>
+                  <!-- 时间 -->
+                  <template v-if="item.taskFiledType == 'datetime'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value">
+                      {{ curr.info.taskContent[item.taskFiledKey] || '--' }}
+                    </div>
+                  </template>
+                  <!-- 日期范围 -->
+                  <template v-if="item.taskFiledType == 'datatimerange'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value">
+                      {{ curr.info.taskContent[item.taskFiledKey] || '--' }}
+                    </div>
+                  </template>
+                  <!-- 图片上传 -->
+                  <div v-if="item.taskFiledType == 'img'" class="divline" style="width: 100%; height: 15px; background-color: #e9e9e9; margin-bottom: 5px"></div>
+                  <template v-if="item.taskFiledType == 'img'">
+                    <div class="upload-field">
+                      <div class="field-text" :class="{ required: item.isMustfill == '1' }">{{ item.taskFiledValue }}:</div>
+                      <!-- 上传组件 -->
+                      <div class="img-box" v-if="item.imgList">
+                        <div v-for="(iItem, index) in item.imgList" :key="index" class="img-box-content">
+                          <span class="type">{{ iItem.type }}</span>
+                          <el-image class="img-item" lazy :src="iItem.url" :preview-src-list="getPreviewList(item.previewList, index)" />
+                        </div>
+                      </div>
+                    </div>
+                  </template>
+                  <!-- 金额 -->
+                  <template v-if="item.taskFiledType == 'money'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value">
+                      {{ curr.info.taskContent[item.taskFiledKey] || '--' }}
+                    </div>
+                  </template>
+                  <!-- 数字 -->
+                  <template v-if="item.taskFiledType == 'number'">
+                    <div class="title-value">{{ item.taskFiledValue }}:</div>
+                    <div class="desc-value">
+                      {{ curr.info.taskContent[item.taskFiledKey] || '--' }}
+                    </div>
+                  </template>
+                  <!-- 长文本 -->
+                  <template v-if="item.taskFiledType == 'longtext'">
+                    <div class="longtext-box">
+                      <div class="field-text" :class="{ required: item.isMustfill == '1' }">{{ item.taskFiledValue }}:</div>
+                      <textarea class="textarea-box" :disabled="true" :value="curr.info.taskContent[item.taskFiledKey] || '--'" :maxlength="item.taskFiledMaxsize" />
+                    </div>
+                  </template>
+                </div>
+              </template>
+
+              <div class="btns">
+                <el-button class="btn" type="danger" @click="passClick(curr, true)">不通过</el-button>
+                <el-button class="btn" type="primary" @click="passClick(curr, true)">通过</el-button>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </basic-container>
   </div>
 </template>
 
 <script>
-import { getTaskV2PageApi, getTaskTypeAvailApi, getDeptv2Avail, getDrug2Avail, getUserV2Avail, getTaskV2TokenApi } from '@/api/serviceManagement/servicesToBeReviewed/index.js';
+import {
+  getTaskV2PageApi,
+  getTaskTypeAvailApi,
+  getDeptv2Avail,
+  getDrug2Avail,
+  getUserV2Avail,
+  getTaskV2TokenApi,
+  taskV2CheckBatchApi,
+  checkSingleApi,
+  getTaskV2PageTileApi
+} from '@/api/serviceManagement/servicesToBeReviewed/index.js';
 import { getDictType } from '@/api/common';
 import abbreviationsProvinces from '@/const/abbreviationsProvinces.js';
 import dayjs from 'dayjs';
+import { mapGetters } from 'vuex';
 
 export default {
   data() {
@@ -105,9 +228,9 @@ export default {
       abbreviationsProvincesList: abbreviationsProvinces,
       nodeId: '',
       searchFrom: {
-        year: '2024',
+        year: '',
         taskTypeId: '',
-        quarter: '4',
+        quarter: '',
         createTime: '',
         provAbbr: '',
         mahName: '',
@@ -115,12 +238,62 @@ export default {
         salesId: '',
         skuId: '',
         taskStatus: 3
-      }
+      },
+      page: {
+        current: 1,
+        size: 50
+      },
+      nodeId: '',
+      list: []
     };
   },
-  created() {
-    this.getDict();
+  async created() {
+    await this.getDict();
+    this.getList();
+  },
+  computed: {
+    ...mapGetters(['userInfo'])
+  },
+  mounted() {
+    const roles = this.userInfo.roles;
+
+    let nodeId = '';
+    switch (true) {
+      // 43	地市管理员
+      case roles.includes(43):
+        nodeId = 1;
+        break;
+      // 4	区域管理员
+      case roles.includes(4):
+        nodeId = 2;
+        break;
+      // 42	市场管理员: 获取审核节点为3和9   nodeid为12
+      case roles.includes(42):
+        nodeId = 12;
+        break;
+      // 40	商务管理员: 获取审核节点为3和8   nodeid为11
+      case roles.includes(40):
+        nodeId = 11;
+        break;
+      // 41	事业部分管领导
+      case roles.includes(41):
+        nodeId = 9;
+        break;
+      // 39	事业部总经理
+      case roles.includes(39):
+        nodeId = 15;
+        break;
+      default:
+        nodeId = 1;
+    }
+
+    const currentYear = dayjs().format('YYYY');
+    this.searchFrom.year = currentYear;
+    this.nodeId = nodeId;
+    this.searchFrom.nodeId = nodeId;
+    this.getList();
   },
+
   methods: {
     getDict() {
       getDictType({ type: 'task_status' }).then((res) => {
@@ -143,7 +316,32 @@ export default {
         this.drugListArr = res.data.data;
       });
     },
-    getList() {},
+    mahNameChange(e) {
+      if (e) {
+        const curr = this.drugListArr[e];
+        this.currDrugList = curr;
+
+        this.drugDisabled = false;
+      } else {
+        this.searchFrom.skuId = '';
+        this.currDrugList = [];
+        this.drugDisabled = true;
+      }
+    },
+    async getList() {
+      const obj = Object.assign(
+        {
+          current: this.page.currentPage,
+          size: this.page.pageSize
+        },
+        this.searchFrom
+      );
+      const res = await getTaskV2PageTileApi(obj);
+      if (res.data.code === 0) {
+        this.list = res.data.data.records;
+      }
+    },
+
     clickBtn() {
       this.tableData = [];
       this.page.currentPage = 1;
@@ -163,6 +361,86 @@ export default {
         taskStatus: 3
       };
       this.searchFrom.nodeId = this.nodeId;
+    },
+    getName(taskType) {
+      let curr = this.taskTypeAvailArr.find((item) => item.id == taskType);
+      return curr.name;
+    },
+    getDesc(curr, item) {
+      // 拜访类任务
+      const arr = ['51', '52', '53'];
+      if (arr.includes(item.taskTypeId) && item.taskFiledKey === 'temp24') {
+        return curr.taskContent['temp24label'];
+      }
+      // 获取需要转换的字符串(例如 '1,2,3')
+      const contentValue = curr.taskContent[item.taskFiledKey];
+      if (!contentValue) return '--';
+      // 获取字典表对应数组
+      const itemList = curr.dict[item.dictGroupName] || [];
+      // 按逗号拆分成数组
+      const valueArray = contentValue.split(',');
+      // 将每个拆分值找到对应的 label
+      const result = valueArray.map((val) => {
+        const foundItem = itemList.find((dictItem) => dictItem.value === val);
+        return foundItem ? foundItem.label : null;
+      });
+      // 如果有任意一个值无法找到对应的 label,则直接返回 '--'
+      if (result.some((label) => label === null)) {
+        return '--';
+      }
+      // 否则,使用逗号拼接并返回
+      return result.join(',');
+    },
+    async passClick(item, flag) {
+      let nodeId = '';
+      const roles = this.userInfo.roles;
+      switch (true) {
+        // 43	地市管理员
+        case roles.includes(43):
+          nodeId = 2;
+          break;
+        // 4	区域管理员
+        case roles.includes(4):
+          nodeId = 3;
+          break;
+        // 42	市场管理员
+        case roles.includes(42):
+          nodeId = 8;
+          break;
+        // 40	商务管理员
+        case roles.includes(40):
+          nodeId = 9;
+          break;
+        // 39	事业部总经理
+        case roles.includes(39):
+          nodeId = 6;
+          break;
+        // 41	事业部分管领导
+        case roles.includes(41):
+          nodeId = 5;
+          break;
+        default:
+          nodeId = 1;
+      }
+      console.log('item', item);
+      let obj = {
+        token: item.token.token,
+        taskId: item.token.value,
+        checkResult: flag,
+        checkMessage: '',
+        nodeId: nodeId
+      };
+      try {
+        res = await checkSingleApi(obj);
+        console.log('res', res);
+      } catch (err) {
+        console.log('err', err);
+      }
+    },
+
+    backPage() {
+      this.$router.$avueRouter.closeTag();
+      this.$router.back();
     }
   }
 };
@@ -174,4 +452,124 @@ export default {
   display: flex;
   justify-content: space-between;
 }
+
+.card-list {
+  height: calc(100vh - 550px);
+  .cards {
+    width: 100%;
+    padding: 10px;
+  }
+
+  .card {
+    border-radius: 4px;
+    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.2);
+    border: 1px solid #ebeef5;
+    background-color: #fff;
+    color: #303133;
+    transition: 0.3s;
+    min-height: 300px;
+    width: 49%;
+    min-width: 500px;
+    margin-bottom: 10px;
+
+    padding: 10px;
+  }
+
+  .task-type-info {
+    font-size: 16px;
+    color: #333;
+    font-weight: 600;
+    margin-bottom: 5px;
+  }
+  .info {
+    display: flex;
+    font-size: 12px;
+    color: #7f7f7f;
+    margin-bottom: 5px;
+
+    p {
+      flex: 1;
+      margin-right: 30px;
+    }
+  }
+
+  .detail {
+    font-size: 14px;
+    font-weight: 500;
+    color: #333333;
+    border-bottom: 2px solid #d7d6d5;
+    line-height: 30px;
+    margin: 5px 0;
+  }
+}
+
+.field-box {
+  padding: 0 10px 5px;
+  overflow: hidden;
+  .title-value {
+    //width: 50%;
+    float: left;
+  }
+  .desc-value {
+    float: left;
+  }
+  .upload-field {
+    .img-box {
+      padding-top: 5px;
+      display: flex;
+    }
+    .file-box {
+      .file-item {
+        padding: 2px 8px;
+        cursor: pointer;
+        &:hover {
+          background-color: #f5f7fa;
+          color: #2d8cf0;
+        }
+      }
+    }
+  }
+  .img-box-content {
+    padding-top: 15px;
+    position: relative;
+    .type {
+      font-size: 12px;
+      position: absolute;
+      top: 0;
+    }
+  }
+  .img-item {
+    width: 100px;
+    height: 100px;
+    margin-right: 5px;
+  }
+  .longtext-box {
+    .textarea-box {
+      margin-top: 5px !important;
+      width: 100%;
+      padding: 3px;
+    }
+  }
+  .divline {
+    width: 100%;
+    height: 5px;
+    background-color: #e9e9e9;
+    margin-bottom: 5px;
+  }
+  .img-iten {
+    height: 60px;
+    margin-right: 5px;
+    width: 50px;
+    cursor: pointer;
+  }
+}
+.btns {
+  padding: 0 20px;
+  padding-top: 5px;
+  display: flex;
+  justify-content: space-between;
+  .btn {
+    width: 48%;
+  }
+}
 </style>