打卡定位
This commit is contained in:
+11
-4
@@ -6,14 +6,15 @@
|
||||
<view v-else class="body">
|
||||
<view class="day">
|
||||
<text class="date">{{ dateLabel }}</text>
|
||||
<text class="shift">班次 {{ rules.workStart }}–{{ rules.workEnd }}</text>
|
||||
<text class="shift">弹性 09:00–09:30 / 18:00–18:30</text>
|
||||
</view>
|
||||
<view class="lieu">多出工时记调休 {{ lieuText }}</view>
|
||||
|
||||
<view class="slots">
|
||||
<view class="slot">
|
||||
<view class="dot" :class="{ on: inRec }" />
|
||||
<view class="slot-m">
|
||||
<text class="lab">上班 {{ rules.workStart }}</text>
|
||||
<text class="lab">上班 09:00–09:30</text>
|
||||
<text class="val" :class="{ ok: inRec }">{{ inRec ? (inRec.time || '') + ' 已打卡' : '未打卡' }}</text>
|
||||
</view>
|
||||
<text class="tiny">{{ inRec ? (inRec.status || '正常') : '' }}</text>
|
||||
@@ -21,7 +22,7 @@
|
||||
<view class="slot">
|
||||
<view class="dot" :class="{ on: outRec }" />
|
||||
<view class="slot-m">
|
||||
<text class="lab">下班 {{ rules.workEnd }}</text>
|
||||
<text class="lab">下班 18:00–18:30</text>
|
||||
<text class="val" :class="{ ok: outRec }">{{ outRec ? (outRec.time || '') + ' 已打卡' : '未打卡' }}</text>
|
||||
</view>
|
||||
<text class="tiny">{{ outRec ? (outRec.status || '正常') : '' }}</text>
|
||||
@@ -80,7 +81,7 @@
|
||||
import FyHeader from '../../components/fy-header.vue'
|
||||
import FyScroll from '../../components/fy-scroll.vue'
|
||||
import { store } from '../../utils/store.js'
|
||||
import { clockText, toast } from '../../utils/format.js'
|
||||
import { clockText, flexCreditMinutes, flexCreditText, toast } from '../../utils/format.js'
|
||||
|
||||
export default {
|
||||
components: { FyHeader, FyScroll },
|
||||
@@ -111,6 +112,11 @@ export default {
|
||||
},
|
||||
outRec() {
|
||||
return this.records.find((r) => /下班|out/i.test(String(r.title || r.kind || r.type || '')))
|
||||
},
|
||||
lieuText() {
|
||||
const inn = this.inRec && (this.inRec.time || this.inRec.punchTime)
|
||||
const out = this.outRec && (this.outRec.time || this.outRec.punchTime)
|
||||
return flexCreditText(flexCreditMinutes(inn, out))
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
@@ -150,6 +156,7 @@ export default {
|
||||
.day { display: flex; justify-content: space-between; align-items: baseline; padding: 8rpx 8rpx 20rpx; }
|
||||
.date { font-size: 32rpx; font-weight: 650; color: #111827; }
|
||||
.shift { font-size: 24rpx; color: #6B7280; }
|
||||
.lieu { margin: 0 8rpx 16rpx; font-size: 24rpx; color: #1677FF; }
|
||||
.slots { background: #fff; border-radius: 20rpx; padding: 8rpx 8rpx; border: 1rpx solid rgba(17,24,39,0.06); }
|
||||
.slot { display: flex; align-items: center; padding: 22rpx 20rpx; }
|
||||
.slot + .slot { border-top: 1rpx solid #F0F2F5; }
|
||||
|
||||
@@ -92,6 +92,35 @@ export function pad2(n) {
|
||||
return String(n).padStart(2, '0')
|
||||
}
|
||||
|
||||
/** 弹性:9:00–9:30 上班,18:00–18:30 下班。早于 9:00、晚于 18:30 的分钟计入调休。 */
|
||||
export function flexCreditMinutes(inTime, outTime) {
|
||||
const inn = hmMinutes(inTime)
|
||||
const out = hmMinutes(outTime)
|
||||
let extra = 0
|
||||
if (inn != null && inn < 9 * 60) extra += 9 * 60 - inn
|
||||
if (out != null && out > 18 * 60 + 30) extra += out - (18 * 60 + 30)
|
||||
return extra
|
||||
}
|
||||
|
||||
export function flexCreditText(minutes) {
|
||||
const n = Math.max(0, Math.round(Number(minutes) || 0))
|
||||
if (!n) return '0 分钟'
|
||||
const h = Math.floor(n / 60)
|
||||
const m = n % 60
|
||||
if (h && m) return h + ' 小时 ' + m + ' 分钟'
|
||||
if (h) return h + ' 小时'
|
||||
return m + ' 分钟'
|
||||
}
|
||||
|
||||
function hmMinutes(value) {
|
||||
const m = String(value || '').match(/(\d{1,2}):(\d{2})/)
|
||||
if (!m) return null
|
||||
const h = Number(m[1])
|
||||
const min = Number(m[2])
|
||||
if (h > 23 || min > 59) return null
|
||||
return h * 60 + min
|
||||
}
|
||||
|
||||
export function clockText(date) {
|
||||
const d = date || new Date()
|
||||
return `${pad2(d.getHours())}:${pad2(d.getMinutes())}:${pad2(d.getSeconds())}`
|
||||
|
||||
+25
-20
@@ -867,30 +867,35 @@ export const store = {
|
||||
this.emit()
|
||||
},
|
||||
|
||||
punch() {
|
||||
_locate() {
|
||||
let type = 'gcj02'
|
||||
// #ifdef H5
|
||||
type = 'wgs84'
|
||||
// #endif
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.getLocation({
|
||||
type: 'gcj02',
|
||||
isHighAccuracy: true,
|
||||
success: async (pos) => {
|
||||
try {
|
||||
const rec = await api.oaPost('/profile/attendance/punch', {
|
||||
source: 'mobile',
|
||||
latitude: pos.latitude,
|
||||
longitude: pos.longitude,
|
||||
accuracyM: pos.accuracy
|
||||
}, this.token)
|
||||
await this.refreshAttendance()
|
||||
resolve((rec && rec.title) || '打卡成功')
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
type,
|
||||
isHighAccuracy: false,
|
||||
timeout: 8000,
|
||||
success: resolve,
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
},
|
||||
fail() {
|
||||
reject(new Error('需要定位权限才能打卡'))
|
||||
|
||||
async punch() {
|
||||
const body = { source: 'mobile' }
|
||||
try {
|
||||
const pos = await this._locate()
|
||||
body.latitude = pos.latitude
|
||||
body.longitude = pos.longitude
|
||||
body.accuracyM = pos.accuracy
|
||||
} catch (_) {
|
||||
// 桌面浏览器经常没有定位;坐标缺省时仍提交,由服务端决定是否允许
|
||||
}
|
||||
})
|
||||
})
|
||||
const rec = await api.oaPost('/profile/attendance/punch', body, this.token)
|
||||
await this.refreshAttendance()
|
||||
return (rec && rec.title) || '打卡成功'
|
||||
},
|
||||
|
||||
async audit(no, action, comment) {
|
||||
|
||||
Reference in New Issue
Block a user