From ae78dbf9e82cd344a4fea693c2d4c5ca2f92bed6 Mon Sep 17 00:00:00 2001 From: chenkainan Date: Thu, 6 Mar 2025 14:33:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=BC=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/calendar.vue | 9 +- pages/index/index.vue | 271 ++++++++++++++++++++++++++++++---------- 2 files changed, 214 insertions(+), 66 deletions(-) diff --git a/components/calendar.vue b/components/calendar.vue index 3919347..d1a9127 100644 --- a/components/calendar.vue +++ b/components/calendar.vue @@ -66,7 +66,12 @@ isShowBeforeDate: { type: Boolean, default: true - } + }, + // 是否可点击日期 + isCanChangeDate: { + type: Boolean, + default: false + }, }, data() { return { @@ -94,6 +99,8 @@ methods: { // 选中日期 changeDate(item) { + // 只有VIP导游才可以点击其他日期排班 + if(!this.isCanChangeDate) return; if(this.nowDay > item && this.isShowBeforeDate) return; this.year = Number(item.slice(0, 4)); this.month = Number(item.slice(5, 7)); diff --git a/pages/index/index.vue b/pages/index/index.vue index 143b7f5..3f491b8 100644 --- a/pages/index/index.vue +++ b/pages/index/index.vue @@ -15,28 +15,50 @@ - - - ·我的排班 - - - - {{item.title}} - + + ·我的打卡 + 打卡规则 + + 上线打卡 + {{currentTime}} + + + + {{isCanPunch ? '您已进入打卡范围:' + userPunch.clock_address[nearestFenceIndex].title : '您当前不在可打卡范围内'}} + 审批打卡 + + + + 打卡时间:{{currentTime.slice(0,5)}} + {{timeSuccess}}s后自动进入排班页面 - - - - - - {{item.title}} - + + ·我的排班 + + + {{item.title}} + + + + + + + + + + {{item.title}} + + + + + + + @@ -85,21 +107,24 @@ isChecked: false }], isAllChecked: false, - // 打卡中心点经纬度 - fenceCenter: [ - {latitude: 31.267166, longitude: 120.632449}, // 丽丰广场麦当劳 - {latitude: 31.266902, longitude: 120.630162}, // - {latitude: 31.266841, longitude: 120.628526}, - {latitude: 31.26576, longitude: 120.629256} - ], // 最近的打卡点索引 nearestFenceIndex: null, // 打卡点半径(单位:米) fenceRadius: 500, - // 用户与打卡坐标的距离 - distance: null, // 用于存储 watchPosition 的返回值,方便后续清除监听 - watchId: null + watchId: null, + ruleContent: '', + currentTime: '', + timeInterval: null, + isCanPunch: false, // 是否可打卡, + punchSuccess: false, // 打卡成功 + timeSuccess: 3, + isShowClasses: true, // 是否显示排班表 + userPunch: {}, + myLonLat: { + lng: '', + lat: '' + } } }, onLoad() { @@ -107,16 +132,76 @@ this.getList() }, onShow() { - // 开始监听用户位置 - this.watchLocation() + // 获取用户打卡信息 + this.Post({},'/api/Merchants/getGuideClockStatus').then(res => { + this.userPunch = res.data + + if(this.userPunch.clock_address.length == 0) return; + + // 用户是否需要打卡、及打卡状态:0不需要打卡,1未打卡,2已打卡或审批打卡成功,3审批打卡审核中,4审批拒绝 + switch (this.userPunch.is_clock){ + case 0: + this.isShowClasses = true + break; + case 1: + this.isShowClasses = false + break; + case 2: + this.isShowClasses = true + break; + case 3: + this.isShowClasses = false + break; + case 4: + this.isShowClasses = false + break; + default: + break; + } + + this.watchLocation(); // 开始监听用户位置 + this.startTimeUpdate(); + }) }, onHide() { // 页面隐藏时清除位置监听 if (this.watchId) { navigator.geolocation.clearWatch(this.watchId) } + + // 页面隐藏时清除时间更新定时器 + if (this.timeInterval) { + clearInterval(this.timeInterval); + } }, methods: { + // 点击打卡 + punch() { + if (this.nearestFenceIndex === null) { + uni.showToast({ + title: '您当前不在可打卡范围内,无法打卡', + icon: 'none' + }); + return; + } + this.Post({ + address_id: this.userPunch.clock_address[this.nearestFenceIndex].id, + lon: this.myLonLat.lng, + lat: this.myLonLat.lat + }, '/api/Merchants/guideClockLocate').then(res => { + if(res.code == 200) { + this.punchSuccess = true + clearInterval(this.timeInterval); // 打卡成功后清除时间定时器 + let timer = setInterval(() => { + this.timeSuccess--; + if (this.timeSuccess == 0) { + clearInterval(timer); + this.isShowClasses = true + } + }, 1000); + } + }) + }, // 监听用户位置变化 watchLocation() { if (navigator.geolocation) { @@ -124,22 +209,23 @@ (position) => { let coords = position.coords; let [gcj02Lng, gcj02Lat] = this.wgs84ToGcj02(coords.longitude, coords.latitude); - console.log('自身坐标',gcj02Lat,gcj02Lng) - // 计算用户与每个打卡点的距离,找出最近的打卡点 - let minDistance = Infinity; - let nearestIndex = null; - this.fenceCenter.forEach((item,index) => { - const distance = this.calculateDistance(item.latitude,item.longitude, gcj02Lat, gcj02Lng) - console.log(distance) - if (distance < minDistance) { - minDistance = distance; - nearestIndex = index; + this.myLonLat = { + lng: gcj02Lng, + lat: gcj02Lat + } + // 初始化是否可打卡为 false + this.isCanPunch = false; + // 遍历每个打卡点 + for (let i = 0; i < this.userPunch.clock_address.length; i++) { + const item = this.userPunch.clock_address[i]; + const distance = this.calculateDistance(item.latitude, item.longitude, gcj02Lat, gcj02Lng); + console.log(`与打卡点 ${item.title} 的距离:`, distance); + if (distance <= item.range) { + this.isCanPunch = true; + this.nearestFenceIndex = i; + break; // 找到满足条件的打卡点后结束循环 } - }) - this.distance = minDistance; - this.nearestFenceIndex = nearestIndex; - console.log('用户与最近打卡点之间的距离',this.distance) - console.log('最近的打卡点索引', this.nearestFenceIndex); + } }, (error) => { let locationStatus = '' @@ -283,28 +369,50 @@ }) }, // 获取当前日期 + formatDate(date, format = 'YYYY/MM/DD') { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hour = String(date.getHours()).padStart(2, '0'); + const minute = String(date.getMinutes()).padStart(2, '0'); + const second = String(date.getSeconds()).padStart(2, '0'); + + return format + .replace('YYYY', year) + .replace('MM', month) + .replace('DD', day) + .replace('HH', hour) + .replace('mm', minute) + .replace('ss', second); + }, getNowTime(time, type) { - var date = time, - year = date.getFullYear(), - month = date.getMonth() + 1, - day = date.getDate(), - hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(), - minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(), - second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(); - month >= 1 && month <= 9 ? (month = "0" + month) : ""; - day >= 0 && day <= 9 ? (day = "0" + day) : ""; - if (type == 1) { - if (uni.getSystemInfoSync().platform == 'ios') { - var timer = year + '/' + month + '/' + day + ' ' + hour + ':' + minute + ':' + second; - } else { - var timer = year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second; - } - } else { - var timer = year + '/' + month + '/' + day; - } - - return timer; + const format = type === 1 ? (uni.getSystemInfoSync().platform === 'ios' ? 'YYYY/MM/DD HH:mm:ss' : 'YYYY-MM-DD HH:mm:ss') : 'YYYY/MM/DD'; + return this.formatDate(time, format); + }, + // 打卡规则 + openRule() { + this.Post({ + id: 7 + },'/api/article/getArticleById').then(res => { + this.ruleContent = res.data.content + this.$refs.popup.open() + }) + }, + // 开始更新时间 + startTimeUpdate() { + this.updateTime(); + this.timeInterval = setInterval(() => { + this.updateTime(); + }, 1000); }, + // 更新时间 + updateTime() { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + this.currentTime = `${hours}:${minutes}:${seconds}`; + } } } @@ -336,6 +444,39 @@ color: #96684F; text-align: right; } + + .punch-box { + width: 267rpx; + height: 267rpx; + background: #CCCCCC; + box-shadow: 0rpx 0rpx 29rpx 0rpx rgba(153,153,153,0.6); + border-radius: 50%; + justify-content: center; + align-items: center; + font-weight: bold; + font-size: 32rpx; + color: #FFFFFF; + margin: 200rpx auto 0; + } + + .punch-text { + font-weight: bold; + font-size: 30rpx; + color: #111111; + margin: 40rpx auto; + text-align: center; + } + + .examine-btn { + width: 257rpx; + height: 80rpx; + border-radius: 13rpx; + border: 1rpx solid #96684F; + font-weight: 500; + font-size: 31rpx; + color: #96684F; + margin: 0 auto; + } .nav-item { font-weight: 500;