<template> <view class="view-container"> <view class="box"> <view class="header"> <view class="wd-font-800">执法签到</view> <view class="refresh" @tap="refresh"> <image src="/static/images/icon/refresh.png" mode="aspectFit" style="width: 16px; height: 16px" ></image> 刷新 </view> </view> <view class="row codeview"> <image :src="miniCode" mode="aspectFill" class="code"></image> <view class="info"> <view class=""> <view class="wd-font-800">执法协同人员请</view> <view class="wd-font-800">扫描二维码签到</view> <view class="wd-font-800 wd-mt-8" style="color: #f8285a"> (要求2人以上) </view> </view> <view class="wd-font-800" style="color: #17c653; text-decoration: underline" @tap="showTip = true" > 无法正常签到? </view> </view> </view> <view class="row" v-if="list.length == 0"> <view class="emty"> <image class="image" src="/static/images/emty.png" mode="aspectFill" ></image> <text class="wd-text-14" style="color: #99a1b7"> 暂无处理结果 </text> </view> </view> <view class="locate-record row" v-for="item in list" :key="item.id"> <view class="info"> <u-avatar :src="item.avtar" size="40px" shape="circle" ></u-avatar> <view> <view style="margin-bottom: 4px"> <text style="font-weight: 800">{{ item.realName }}</text> <text style="font-size: 13px; color: #4b5675"> {{ item.deptName }} </text> </view> <view style="font-size: 13px; color: #4b5675"> {{ $util.formatDate(item.time, 'YYYY年M月D日 hh:mm') }} </view> </view> </view> <view class="wd-flex wd-flex-center" style="gap: 4px"> <u-icon name="checkmark-circle-fill" size="16" color="#17C653" ></u-icon> <text class="wd-text-13">已签到</text> </view> </view> </view> <cs-bottom-wrapper v-if="!isLocate"> <view class="operation"> <button class="btn green" v-if="distance < radius" @tap="locate" :loading="loading" > 确认签到 </button> <view class="btn grey" v-else>不在签到范围</view> </view> </cs-bottom-wrapper> <cs-bottom-wrapper v-if="isLocate && isLeadLocate"> <view class="operation"> <view class="btn grey" v-if="list.length < 2">开始执法</view> <button class="btn green" v-else :loading="loading" @tap="goNext"> 开始执法 </button> </view> </cs-bottom-wrapper> <u-modal :show="showTip" width="295px" closeOnClickOverlay @close="showTip = false" > <view class="tip"> <view class="header"> <view>如无法签到 请确认以下</view> <view>功能是否正常启用?</view> </view> <view class="info"> <view class="msg"> <u-icon name="wifi" color="#17C653" size="20"></u-icon> 开启手机设置GPS定位功能 </view> <view class="msg"> <u-icon name="wifi" color="#17C653" size="20"></u-icon> 开启手机授权微信定位功能 </view> <view class="msg"> <u-icon name="wifi" color="#17C653" size="20"></u-icon> 开启右上角小程序定位功能 </view> </view> </view> <template #confirmButton> <view class="wd-flex wd-flex-center"> <view class="confirm-btn" @tap="showTip = false">确认</view> </view> </template> </u-modal> <van-action-sheet :show="showModel"> <view class="model-view"> <image class="image" src="/static/images/task/position.png" mode="aspectFill" ></image> <view class="open-setting" @tap="openSetting()">开启定位</view> </view> </van-action-sheet> </view> </template> <script> import { getMiniCode } from '@/utils/getCode.js' import { InspectionsApi } from '@/api/inspections/index.js' import { getEnterPrise } from '@/api/enterprise/index.js' import { getMiniCode as getMiniappCode } from '@/api/login.js' export default { data() { return { showModel: false, inspectionsId: '', miniCode: '', enterpriseGps: '', location: {}, distance: 10000, radius: 100, // 打卡范围 showTip: false, list: [], loading: false, share: { title: '', path: '', imageUrl: '' }, isLeadLocate: false, isLocate: true, timer: null, time: 0 } }, onLoad(res) { if (res.scene) { const data = decodeURIComponent(res.scene) const obj = {} data.split('&').forEach(i => { const arr = i.split('=') obj[arr[0]] = arr[1] }) this.inspectionsId = obj.aId this.enterpriseId = obj.bId } else { this.inspectionsId = res.inspectionsId this.enterpriseId = res.enterpriseId } this.share = { title: '', path: `/sub/task/locate?inspectionsId=${this.inspectionsId}&enterpriseId=${this.enterpriseId}`, imageUrl: 'http://82.156.141.150:9001/api/v1/download-shared-object/aHR0cDovL2xvY2FsaG9zdDo5MDAwL2h1YW5iYW8vbWluaWFwcC9pbnZhdGUucG5nP1gtQW16LUFsZ29yaXRobT1BV1M0LUhNQUMtU0hBMjU2JlgtQW16LUNyZWRlbnRpYWw9QUQxODY1RVA2NEczMEdEUUhDVTglMkYyMDI1MDIxOCUyRnVzLWVhc3QtMSUyRnMzJTJGYXdzNF9yZXF1ZXN0JlgtQW16LURhdGU9MjAyNTAyMThUMDcyMDI0WiZYLUFtei1FeHBpcmVzPTQzMTk5JlgtQW16LVNlY3VyaXR5LVRva2VuPWV5SmhiR2NpT2lKSVV6VXhNaUlzSW5SNWNDSTZJa3BYVkNKOS5leUpoWTJObGMzTkxaWGtpT2lKQlJERTROalZGVURZMFJ6TXdSMFJSU0VOVk9DSXNJbVY0Y0NJNk1UY3pPVGt3TmpJME55d2ljR0Z5Wlc1MElqb2lZV1J0YVc0aWZRLmp6djBhdEY5QVBYXzVjYWg4c18yeXhVV3oxek9BekFzSVdzemVrUmZwcXlHd0RPWkptazlUSGJRUnBDdVNmLVMyU0otWTI1cldUd2hpNUlrY0xBSThRJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCZ2ZXJzaW9uSWQ9bnVsbCZYLUFtei1TaWduYXR1cmU9MjcxZTkzOTE1MDkwYzUzYmRjYTg0MjQ1MTJhYjk3ZWQxZWMyN2QzM2MwM2U3NGUwYmRhNTBmYjQyNWI0N2MyOQ' } this.init() }, onShareAppMessage() { return this.share }, onShareTimeline() { return this.share }, onShow() { this.useAuth() // this.refresh() // this.echoQueset() }, onHide() { this.timer && clearInterval(this.timer) }, onUnload() { this.timer && clearInterval(this.timer) }, onBackPress() { this.timer && clearInterval(this.timer) return false }, watch: { list: { handler: function (val) { if (val.length >= 2) { this.timer && clearInterval(this.timer) } }, immediate: true, deep: true } }, methods: { async init() { const res = await getMiniappCode({ scene: `aId=${this.inspectionsId}&bId=${this.enterpriseId}`, path: 'sub/task/locate', checkPath: false, envVersion: 'trial', isHyaline: true }) this.miniCode = `data:image/jpeg;base64,${res.data}` const enterprise = await getEnterPrise(this.enterpriseId) this.enterprisesName = enterprise.data.enterprisesName this.enterpriseGps = enterprise.data.gpsLocation uni.setNavigationBarTitle({ title: this.enterprisesName }) this.share.title = `执法签到-${this.enterprisesName}` this.getLocateList() this.echoQueset() }, async getLocateList() { const res = await InspectionsApi.getLocate(this.inspectionsId) const locate = res.data.find(i => { return i.userId == this.$store.getters.userId }) if (locate) { // 签到状态 this.isLocate = true // 专管员签到状态 if (locate.isInspect) this.isLeadLocate = true } else { this.isLocate = false } console.log(this.isLocate, this.isLeadLocate) this.list = res.data }, useAuth() { const that = this uni.getSetting({ success: res => { // 如果有授权直接获取位置,没有则拉起授权 res.authSetting['scope.userLocation'] ? _getLocation() : _getAuth() }, fail: err => { uni.showToast({ icon: 'none', title: '获取设置失败' }) console.log(err) } }) /** * 打开微信设置 */ function _getAuth() { uni.authorize({ scope: 'scope.userLocation', success: res => { _getLocation() }, fail: () => { that.showModel = true } }) } function _getLocation() { uni.getLocation({ type: 'gcj02', success: res => { console.log('location', res) that.location = { latitude: res.latitude, longitude: res.longitude } that.getDistance() }, fail: err => { that.showTip = true uni.showToast({ icon: 'none', title: '获取定位失败' }) } }) } }, openSetting() { const that = this uni.openSetting({ success: res => { that.showModel = false that.useAuth() } }) }, getDistance() { const that = this this.$map.calculateDistance({ mode: 'straight', form: this.location, to: this.enterpriseGps, success: res => { that.distance = res.result.elements[0].distance console.log('distance', that.distance) } }) }, refresh() { this.getDistance() this.getLocateList() this.echoQueset() }, async locate() { this.loading = true const res = await InspectionsApi.locate({ inspectionsId: this.inspectionsId }) this.loading = false uni.showToast({ icon: 'none', title: res.data }) this.refresh() }, echoQueset() { const timeout = 3 * 60 * 1000 // const timeout = 10 * 1000 this.timer && clearInterval(this.timer) this.timer = setInterval(() => { this.getLocateList() this.time += 5000 if (this.time > timeout) { console.log('timeout') clearInterval(this.timer) uni.navigateBack({ delta: 1 }) } }, 5 * 1000) }, goNext() { InspectionsApi.beginEnforce({ inspectionsId: this.inspectionsId }).then(res => { uni.navigateBack({ delta: 1 }) }) } } } </script> <style lang="scss" scoped> .view-container { height: 100vh; padding: 12px; .box { background-color: #fff; border-radius: $cs-border-radius; padding: 16px; display: flex; flex-flow: column nowrap; gap: 12px; } .header { display: flex; align-items: center; justify-content: space-between; .refresh { display: flex; align-items: center; gap: 4px; color: $cs-color-main; font-weight: bold; } } .row { border-radius: var(--Number-8px, 8px); border: 1px solid var(--LightMode-Grey-Grey-100, #f9f9f9); background: var(--LightMode-Light-Light, #fff); padding: 16px; } .codeview { display: flex; justify-content: space-between; .code { width: 320rpx; height: 320rpx; } .info { display: flex; flex-direction: column; justify-content: space-between; gap: 80rpx; } } } .locate-record { display: flex; justify-content: space-between; .info { display: flex; justify-content: space-between; align-items: center; gap: 12px; } } .emty { display: flex; flex-direction: column; align-items: center; gap: 12px; padding: 24px 12px; border-radius: 8px; .image { width: 64px; height: 64px; } } .operation { padding: 12px; display: flex; align-items: center; justify-content: center; gap: 12px; .btn { flex: 1; border-radius: 8px; display: flex; padding: 12px 0; align-items: center; justify-content: center; } .green { background-color: $cs-color-main; color: #fff; } .grey { background: #f1f1f4; color: #99a1b7; } } .model-view { height: 700rpx; display: flex; flex-direction: column; align-items: center; gap: 24px; .image { width: 470rpx; height: 420rpx; } .open-setting { padding: var(--Number-12px, 12px) var(--Number-48px, 48px); gap: 10px; border-radius: var(--Number-120px, 120px); background: var(--LightMode-Success-Success, #17c653); color: #fff; font-size: 16px; font-weight: 500; /* Widget Shadow */ box-shadow: 0px 3px 4px 0px rgba(0, 0, 0, 0.03); } } .confirm-btn { background-color: $cs-color-main; padding: 12px 40px; color: #fff; font-size: 16px; font-weight: 600; border-radius: 120px; } .tip { display: flex; flex-flow: column nowrap; gap: 24px; .header { display: flex; flex-flow: column nowrap; justify-content: center; align-items: center; color: #17c653; font-style: italic; font-weight: bold; } .info { display: flex; flex-flow: column nowrap; justify-content: center; align-items: center; color: #071437; gap: 16px; .msg { display: flex; justify-content: center; align-items: center; gap: 4px; } } } </style>