renkang
2025-01-03 ccf28d1fed1aa2e5437dbe64b5133ba1cbde6ec7
h5/pages/polling/detail.vue
@@ -1,59 +1,207 @@
<template>
   <view class="main_app">
      <view class="head_bg"></view>
      <view class="info">
         <image v-if="true" class="icon" src="@/static/side/ic_dabiaoed.png" mode=""></image>
         <image v-else class="icon" src="@/static/side/ic_dabiao.png" mode=""></image>
      <view v-if="info.status || info.status == 0" class="head_bg" :style="{
         background: `linear-gradient(180deg, ${statusM[info.status].color} 0%, rgba(247, 247, 247, 0) 100%)`
      }"></view>
      <view class="info">
         <image v-if="info.status == 2" class="icon" src="@/static/side/ic_dabiaoed.png" mode=""></image>
         <image v-if="info.status == 3" class="icon" src="@/static/side/ic_dabiao.png" mode=""></image>
         <view class="head">
            <view class="name">巡检计划</view>
            <view class="status">待开始</view>
            <view class="name">{{ info.title || info.planTitle }}</view>
            <view class="status" v-if="info.status || info.status == 0" :style="{color: statusM[info.status].color}">
               {{statusM[info.status].name}}
            </view>
         </view>
         <view class="line">
            <view class="la">任务日期:</view>
            <view class="val">2023-23-23</view>
            <view class="val" v-if="info.startDate">{{ info.startDate.slice(0, 10) }}</view>
         </view>
         <view class="line">
            <view class="la">执行时间:</view>
            <view class="val">2023-23-23</view>
            <view class="val" v-if="info.startDate && info.endDate">{{ info.startDate.slice(11,16) }} 至
               {{ info.endDate.slice(11, 16) }}
            </view>
         </view>
         <view class="line">
            <view class="la">完成情况:</view>
            <view class="val">2023-23-23</view>
            <view class="val">{{info.finishNum || 0}}/{{info.patrolNum}}</view>
         </view>
      </view>
      <view class="title">巡检点列表(1)</view>
      <view class="title">巡检点列表({{list.length}})</view>
      <view class="list">
         <view class="item" v-for="i in 10" @click="itemClick()">
         <view class="item" v-for="item in list" @click="itemClick(item)">
            <view class="icon"></view>
            <view class="content">
               <view class="head">
                  <view>巡检点10</view>
                  <view class="status">待巡检</view>
                  <view>{{item.pointName}}</view>
                  <view class="status" :class="{ gray: item.status == 1 }">
                     <image v-if="item.status == 1" src="@/static/plan_ic_finish@2x.png" class="icon" mode=""></image>
                     <text>{{ item.status == 1 ? '已巡检' : '待巡检' }}</text>
                  </view>
               </view>
               <view class="desc">巡检内容最多展示两行,多的省略巡检内容最多展示两行,多的省略巡检内容最多展示两行,多的省略巡检内容最多展示两行,多的省略巡检内容最多展示两行,多的省略巡检内容最多展示两行,多的省略
               </view>
               <template v-if="item.status == 1">
                  <view class="line">
                     <view class="la">巡检结果:</view>
                     <view class="val" :class="{ red: item.dealStatus == 1 }">{{ item.dealStatus == 0 ? '正常' : '异常' }}</view>
                  </view>
                  <view class="line">
                     <view class="la">巡检时间:</view>
                     <view class="val">
                        <text>{{item.dealDate}}</text>
                        <text v-if="item.status == 1" class="detail">查看详情</text>
                     </view>
                  </view>
               </template>
               <view class="desc" v-else>{{item.content}}</view>
            </view>
         </view>
      </view>
      <view class="footer">
         <view class="sub_btn">扫码巡检</view>
      <view class="footer" @click="openSc" v-if="flag">
         <view class="sub_btn">扫码巡检</view>
      </view>
      <!--  -->
      <view class="reader-box" @click="stopScan" v-if="isScaning">
         <view class="reader" id="reader"></view>
      </view>
   </view>
</template>
<script>
   import {
      ywPatrolDetail,
      ywPatrolTaskRecord,
      getPointRecordByCode
   } from '@/api'
   import dayjs from 'dayjs';
   import {
      Html5Qrcode
   } from 'html5-qrcode';
   export default {
      data() {
         return {
            id: '',
            info: {},
            list: [],
            flag: false,
            statusM: [{
                  color: '#4593f7',
                  name: '待开始'
               },
               {
                  color: '#73e09a',
                  name: '进行中'
               },
               {
                  color: '#f1a93f',
                  name: '已超期'
               },
               {
                  color: '#b9b9b9',
                  name: '已处理'
               },
            ],
            html5Qrcode: null,
            isScaning: false,
         };
      },
      methods: {
         itemClick() {
            uni.navigateTo({
               url: '/pages/polling/point'
            })
         }
      },
      onLoad(option) {
         this.id = option.id
         // this.getDetail()
      },
      onShow() {
         this.getDetail()
      },
      methods: {
         openSc() {
            this.isScaning = true;
            Html5Qrcode.getCameras().then((devices) => {
               if (devices && devices.length) {
                  this.html5Qrcode = new Html5Qrcode('reader');
                  this.html5Qrcode.start({
                        facingMode: 'environment'
                     }, {
                        focusMode: 'continuous', //设置连续聚焦模式
                        fps: 5, //设置扫码识别速度
                        qrbox: 280 //设置二维码扫描框大小
                     },
                     (decodeText, decodeResult) => {
                        if (decodeText) { //这里decodeText就是通过扫描二维码得到的内容
                           this.stopScan(); //关闭扫码功能
                           getPointRecordByCode({
                              taskId: this.id,
                              pointCode: decodeText
                           }).then(ress => {
                              if (ress.data) {
                                 uni.navigateTo({
                                    url: '/pages/polling/point?id=' + ress.data.id
                                 })
                              } else {
                                 this.showToast('未匹配到巡检点,请重新扫描')
                              }
                           })
                        }
                     },
                     (err) => {
                        // console.log(err);  //错误信息
                     }
                  );
               }
            });
         },
         stopScan() {
            console.log('停止扫码')
            this.isScaning = false;
            if (this.html5Qrcode) {
               this.html5Qrcode.stop();
            }
         },
         itemClick(item) {
            if (!this.flag) return
            uni.navigateTo({
               url: '/pages/polling/point?id=' + item.id
            })
         },
         getDetail() {
            const {
               id
            } = this
            ywPatrolDetail(id).then(res => {
               this.info = res.data
               let time = new Date(res.data.startDate).getTime()
               console.log('res.data.startDate', new Date().getTime());
               this.flag = new Date().getTime() > time && (this.info.status == 0 || this.info.status == 1)
            })
            ywPatrolTaskRecord({
               capacity: 999,
               page: 1,
               model: {
                  taskId: id
               }
            }).then(res => {
               this.list = res.data.records
            })
         },
         async startScan() {
            try {
               const video = document.getElementById('video');
               const stream = await navigator.mediaDevices.getUserMedia({
                  video: {
                     facingMode: "environment"
                  }
               });
               video.srcObject = stream;
               // 使用 QrScanner 解析
               const qrScanner = new QrScanner(video, result => {
                  alert(`扫描结果: ${result}`);
                  qrScanner.stop(); // 停止扫码
               });
               qrScanner.start();
            } catch (err) {
               console.error('打开摄像头失败:', err);
            }
         }
      }
   }
</script>
@@ -67,7 +215,7 @@
      padding: 30rpx;
      .head_bg {
         background: linear-gradient(180deg, #008BFF 0%, rgba(247, 247, 247, 0) 100%);
         // background: linear-gradient(180deg, #008BFF 0%, rgba(247, 247, 247, 0) 100%);
         height: 240rpx;
         width: 750rpx;
         position: absolute;
@@ -83,14 +231,16 @@
         padding: 30rpx 30rpx 10rpx;
         margin-bottom: 40rpx;
         background: linear-gradient(#FFFFFF 0%, #FFFFFF 48%, #F0F5FF 100%);
         position: relative;
         .icon{
            position: absolute;
            right: 30rpx;
            bottom: 30rpx;
            width: 160rpx;
            height: 122rpx;
         position: relative;
         .icon {
            position: absolute;
            right: 30rpx;
            bottom: 30rpx;
            width: 160rpx;
            height: 122rpx;
         }
         .head {
            display: flex;
            justify-content: space-between;
@@ -104,16 +254,12 @@
            .status {
               color: $primaryColor;
            }
         }
         .line {
            display: flex;
            margin-bottom: 20rpx;
            .la {
               color: #666666;
            .gray {
               color: gray;
            }
         }
      }
      .title {
@@ -123,9 +269,20 @@
         margin-bottom: 30rpx;
      }
      .list {
         height: calc( 100vh - 720rpx ) ;
         overflow: auto;
      .line {
         display: flex;
         margin-bottom: 20rpx;
         .la {
            color: #666666;
         }
      }
      .list {
         height: calc(100vh - 490rpx);
         overflow: auto;
         padding-bottom: 160rpx;
         .item {
            width: 690rpx;
            height: 188rpx;
@@ -136,6 +293,21 @@
            display: flex;
            padding: 20rpx 30rpx 0 16rpx;
            margin-bottom: 20rpx;
            .line {
               margin-bottom: 10rpx;
               width: 100%;
               .val{
                  display: flex;
                  justify-content: space-between;
                  align-items: center;
                  flex: 1;
                  .detail{
                     color: $primaryColor;
                     font-size: 26rpx;
                  }
               }
            }
            .icon {
               width: 10rpx;
@@ -157,9 +329,23 @@
                  margin-bottom: 16rpx;
                  .status {
                     offset-anchor: 28rpx;
                     font-size: 28rpx;
                     color: $primaryColor;
                     font-weight: 400;
                     font-weight: 400;
                     display: flex;
                     align-items: center;
                     .icon{
                        width: 40rpx;
                        height: 40rpx;
                        // border-radius: 50%;
                        // overflow: hidden;
                        background: none;
                     }
                  }
                  .gray {
                     color: #999999;
                  }
               }
@@ -176,29 +362,50 @@
            }
         }
      }
      .footer{
         position: fixed;
         bottom: 0rpx;
         left: 0rpx;
         width: 750rpx;
         height: 172rpx;
         background-color: #fff;
         padding: 20rpx 40rpx;
         .sub_btn {
            width: 670rpx;
            height: 88rpx;
            background: $primaryColor;
            box-shadow: 0rpx 8rpx 20rpx 0rpx rgba(0, 104, 255, 0.3);
            border-radius: 44rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 500;
            font-size: 32rpx;
            color: #FFFFFF;
         }
      .footer {
         position: fixed;
         bottom: 0rpx;
         left: 0rpx;
         width: 750rpx;
         height: 172rpx;
         background-color: #fff;
         padding: 20rpx 40rpx;
         .sub_btn {
            width: 670rpx;
            height: 88rpx;
            background: $primaryColor;
            box-shadow: 0rpx 8rpx 20rpx 0rpx rgba(0, 104, 255, 0.3);
            border-radius: 44rpx;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: 500;
            font-size: 32rpx;
            color: #FFFFFF;
         }
      }
   }
   .reader-box {
      position: fixed;
      top: 0;
      bottom: 0;
      left: 0;
      right: 0;
      background-color: rgba(0, 0, 0, 0.5);
   }
   .reader {
      width: 100%;
      // width: 540rpx;
      // height: 540rpx;
      position: absolute;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
   }
</style>