移动端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

543 lines
14 KiB

<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: 1000, // 打卡范围
showTip: false,
list: [],
loading: false,
share: {
title: '',
path: '',
imageUrl: ''
},
isLeadLocate: false,
isLocate: true,
timer: null,
time: 0
}
},
async 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'
}
await 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: 'develop',
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
}
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.latitude, res.longitude)
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()
}
})
},
async getDistance() {
if (this.enterpriseGps) {
uni.showLoading({
title: '正在计算位置...'
})
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)
uni.hideLoading()
},
fail: err => {
console.log('获取定位失败', err)
uni.hideLoading()
}
})
} else {
await this.init()
this.getDistance()
}
},
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>