243 lines
5.9 KiB
Vue
243 lines
5.9 KiB
Vue
<template>
|
|
<view class="px-base">
|
|
<CuNavbar title="考勤打卡">
|
|
<template #right>
|
|
<view
|
|
@click="goPage('/pages/clockout/logs')"
|
|
class="text-24rpx text-white"
|
|
>打卡记录</view
|
|
>
|
|
</template>
|
|
</CuNavbar>
|
|
<view class="card-shadow px-base mt-base">
|
|
<uv-form
|
|
labelPosition="left"
|
|
:model="form"
|
|
:rules="rules"
|
|
ref="formRef"
|
|
labelWidth="160rpx"
|
|
errorType="toast"
|
|
>
|
|
<uv-form-item :label="form.sign_time" @click="openPicker" prop="sign">
|
|
<view class="w-full">
|
|
<view class="text-hex-999" v-if="!form.sign_time">
|
|
请选择打卡时间
|
|
</view>
|
|
<!-- <uv-input
|
|
:border="`none`"
|
|
readonly
|
|
v-model="form.sign_time"
|
|
placeholder="请选择打卡时间"
|
|
></uv-input> -->
|
|
</view>
|
|
<template v-slot:right>
|
|
<uv-icon name="arrow-right"></uv-icon>
|
|
</template>
|
|
</uv-form-item>
|
|
<uv-line color="#f5f5f5"></uv-line>
|
|
<uv-form-item label="外勤" prop="type">
|
|
<view class="flex flex-1 justify-end">
|
|
<uv-switch
|
|
size="20"
|
|
:activeValue="2"
|
|
:inactiveValue="1"
|
|
v-model="form.type"
|
|
></uv-switch>
|
|
</view>
|
|
</uv-form-item>
|
|
<uv-line color="#f5f5f5"></uv-line>
|
|
<uv-form-item v-if="form.type == 2" label="事由" prop="remarks">
|
|
<uv-input
|
|
v-model="form.remarks"
|
|
count
|
|
inputAlign="right"
|
|
placeholder="请输入外勤事由"
|
|
:border="`none`"
|
|
:maxlength="200"
|
|
></uv-input>
|
|
</uv-form-item>
|
|
</uv-form>
|
|
|
|
<view class="h-40vh flex-center flex-col">
|
|
<view
|
|
:disabled="!(Check && isType)"
|
|
@click="clockIn"
|
|
class="w-220rpx h-220rpx rounded-full overflow-hidden card-shadow1 flex-center btn"
|
|
>
|
|
<view class="text-white text-center">
|
|
<view class="text-40rpx">打卡</view>
|
|
<view class="mt-1">{{ timeFormat(newTime, 'hh:MM:ss') }}</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="mt-40rpx text-center flex-center flex-col">
|
|
<!-- <view v-if="isGPS === false" class="text-primary text-26rpx"
|
|
>定位失败,请检查手机定位权限是否开启</view
|
|
> -->
|
|
|
|
<view class="text-hex-999 text-26rpx">{{ detail.description }}</view>
|
|
<view
|
|
@click="getLoca"
|
|
class="flex items-center mt-10rpx text-hex-9397df text-28rpx"
|
|
>
|
|
<uv-icon size="28rpx" color="#9397df" name="map-fill"></uv-icon>
|
|
<view>重新获取定位</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<uv-picker
|
|
ref="timePicker"
|
|
:columns="timeList"
|
|
keyName="name"
|
|
@confirm="timeConfirm"
|
|
></uv-picker>
|
|
</view>
|
|
</template>
|
|
<script setup>
|
|
import CuNavbar from '@/components/cu-navbar/index'
|
|
import { ref, onMounted, reactive, computed } from 'vue'
|
|
import { http } from '@/utils/request'
|
|
import { timeFormat } from '@climblee/uv-ui/libs/function'
|
|
import { onLoad } from '@dcloudio/uni-app'
|
|
const loading = ref(false)
|
|
const isGPS = ref(true)
|
|
const timePicker = ref(null)
|
|
const timeList = ref([
|
|
[
|
|
{
|
|
name: '上班打卡',
|
|
value: 1,
|
|
},
|
|
{
|
|
name: '下班打卡',
|
|
value: 2,
|
|
},
|
|
],
|
|
])
|
|
const position = ref({})
|
|
const newTime = ref('')
|
|
const detail = ref({})
|
|
const form = reactive({
|
|
time: null,
|
|
type: 1,
|
|
remarks: '',
|
|
sign_time: '',
|
|
})
|
|
const rules = ref({})
|
|
|
|
const Check = computed(() => {
|
|
return detail.value.enable
|
|
})
|
|
const isType = computed(() => {
|
|
if (detail.value.type == 2) {
|
|
if (form.type == 2) {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
|
|
const maxDistance = computed(() => {
|
|
return detail.value.maxDistance
|
|
})
|
|
|
|
const timeConfirm = ({ value }) => {
|
|
form.time = value[0].value
|
|
form.sign_time = value[0].name
|
|
}
|
|
|
|
onLoad(() => {
|
|
getLoca()
|
|
setInterval(() => {
|
|
newTime.value = new Date()
|
|
}, 1000)
|
|
})
|
|
|
|
const getLoca = async () => {
|
|
// uni.openLocation
|
|
uni.getLocation({
|
|
type: 'gcj02',
|
|
fail: (err) => {
|
|
isGPS.value = false
|
|
// uni.showToast({
|
|
// icon: 'none',
|
|
// title: '定位失败,请检查手机定位权限是否开启',
|
|
// })
|
|
},
|
|
success: (res) => {
|
|
isGPS.value = true
|
|
},
|
|
complete: async (e) => {
|
|
position.value = {
|
|
lat: e.latitude,
|
|
lon: e.longitude,
|
|
...e,
|
|
}
|
|
initLo()
|
|
},
|
|
})
|
|
}
|
|
|
|
const initLo = async () => {
|
|
const resdata = await http.get('/hr/sign/info', {
|
|
params: {
|
|
...position.value,
|
|
},
|
|
})
|
|
detail.value = resdata
|
|
form.time = resdata.time || 1
|
|
form.sign_time = timeList.value[0].find((e) => e.value == form.time)?.name
|
|
}
|
|
|
|
const openPicker = () => {
|
|
timePicker.value.open()
|
|
}
|
|
|
|
const clockIn = async () => {
|
|
if (!form.time) {
|
|
return uni.showToast({ title: '请选择打卡时间', icon: 'none' })
|
|
}
|
|
if (form.type == 2 && !form.remarks) {
|
|
return uni.showToast({ title: '请填写外勤事由', icon: 'none' })
|
|
}
|
|
|
|
if (loading.value) return
|
|
loading.value = true
|
|
|
|
try {
|
|
await http.post('/hr/sign', {
|
|
time: form.time,
|
|
type: form.type,
|
|
remarks: form.remarks,
|
|
position: position.value,
|
|
})
|
|
form.remarks = ''
|
|
uni.showToast({ title: '打卡成功', icon: 'none' })
|
|
// uni.navigateTo({ url: '/pages/clockout/logs' })
|
|
} catch (error) {
|
|
} finally {
|
|
initLo()
|
|
loading.value = false
|
|
}
|
|
}
|
|
const goPage = (url) => {
|
|
uni.navigateTo({ url: url })
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.card-shadow1 {
|
|
background: #3678f7;
|
|
box-shadow: 0px 0px 16px 0px rgba(0, 0, 0, 0.2);
|
|
}
|
|
|
|
.btn {
|
|
&[disabled='true'] {
|
|
@apply bg-hex-999 pointer-events-none;
|
|
}
|
|
}
|
|
</style>
|