|
|
@ -33,12 +33,11 @@ |
|
|
|
<span v-else-if="record.morningStatus === 3" class="text-blue-500 font-bold"> |
|
|
|
{{ $moment(record.morning - 0).format('HH:mm') }} |
|
|
|
</span> |
|
|
|
<span v-else-if="today !== list.dateTime">未打卡</span> |
|
|
|
<span v-else-if="today < list.dateTime">未打卡</span> |
|
|
|
<a-button |
|
|
|
v-else |
|
|
|
type="primary" |
|
|
|
size="small" |
|
|
|
:loading="morningLoading" |
|
|
|
@click="checkTime(listIndex, index, 0, record.id, record.memberId, record.checkerId, list.dateTime)" |
|
|
|
> |
|
|
|
打卡 |
|
|
@ -119,12 +118,11 @@ |
|
|
|
<span v-else-if="record.nightStatus === 3" class="text-blue-500 font-bold"> |
|
|
|
{{ $moment(record.night - 0).format('HH:mm') }} |
|
|
|
</span> |
|
|
|
<span v-else-if="today !== list.dateTime">未打卡</span> |
|
|
|
<span v-else-if="today < list.dateTime">未打卡</span> |
|
|
|
<a-button |
|
|
|
v-else |
|
|
|
type="primary" |
|
|
|
size="small" |
|
|
|
:loading="nightLoading" |
|
|
|
@click="checkTime(listIndex, index, 1, record.id, record.memberId, record.checkerId, list.dateTime)" |
|
|
|
> |
|
|
|
打卡 |
|
|
@ -186,7 +184,7 @@ |
|
|
|
<!-- 审核人 --> |
|
|
|
<template slot="checkerName" slot-scope="text, record"> |
|
|
|
<div class="px-2"> |
|
|
|
<div v-if="!record.isMine || (record.isMine && record.morningStatus && record.nightStatus) || today !== list.dateTime"> |
|
|
|
<div v-if="!record.isMine || (record.isMine && record.morningStatus && record.nightStatus)"> |
|
|
|
{{ record.checkerName || checkers[0].name }} |
|
|
|
</div> |
|
|
|
<a-select |
|
|
@ -203,6 +201,45 @@ |
|
|
|
</template> |
|
|
|
</a-table> |
|
|
|
</div> |
|
|
|
|
|
|
|
<a-modal :visible="visible" :centered="true" :closable="false" @ok="handleOk" @cancel="handleCancel"> |
|
|
|
<div class="modal-title">打卡</div> |
|
|
|
<div class="modal-con flex justify-between items-center"> |
|
|
|
<div class="mr-3 flex-shrink-0">打卡原因</div> |
|
|
|
<a-input class="text-right focus:outline-none" type="text" v-model="remark" placeholder="请输入打卡原因" /> |
|
|
|
</div> |
|
|
|
<div class="modal-con flex justify-between items-center"> |
|
|
|
<div class="mr-3 flex-shrink-0">打卡时间</div> |
|
|
|
<!-- 修改时间 --> |
|
|
|
<a-time-picker |
|
|
|
placeholder="请选择" |
|
|
|
format="HH:mm" |
|
|
|
@change="timeChange" |
|
|
|
@openChange=" |
|
|
|
openChange( |
|
|
|
$event, |
|
|
|
recordInfo, |
|
|
|
punchTimeType === 0 ? 'showMorningTime' : 'showNightTime', |
|
|
|
punchTimeType === 0 ? 'morning' : 'night', |
|
|
|
) |
|
|
|
" |
|
|
|
/> |
|
|
|
</div> |
|
|
|
<div class="modal-con flex justify-between items-center"> |
|
|
|
<div class="mr-3 flex-shrink-0">审核人</div> |
|
|
|
<a-select |
|
|
|
style="width: 100px" |
|
|
|
:default-value=" |
|
|
|
recordInfo.lastCheckerId ? recordInfo.lastCheckerId : recordInfo.checkerId ? recordInfo.checkerId : checkers[0].memberId |
|
|
|
" |
|
|
|
@change="chooseChecker" |
|
|
|
> |
|
|
|
<a-select-option :value="member.memberId" v-for="member in checkers" :key="member.memberId"> |
|
|
|
{{ member.name }} |
|
|
|
</a-select-option> |
|
|
|
</a-select> |
|
|
|
</div> |
|
|
|
</a-modal> |
|
|
|
</div> |
|
|
|
<a-empty class="mt-8 mb-8" description="暂无打卡信息" v-else /> |
|
|
|
</div> |
|
|
@ -238,10 +275,15 @@ export default { |
|
|
|
timer: null, |
|
|
|
chooseTime: '', |
|
|
|
auditOptions: null, |
|
|
|
morningLoading: false, |
|
|
|
nightLoading: false, |
|
|
|
// morningLoading: false, |
|
|
|
// nightLoading: false, |
|
|
|
today: this.$moment(new Date()).format('YYYY-MM-DD'), |
|
|
|
selectedDate: '', // 当前选择的日期 |
|
|
|
visible: false, |
|
|
|
punchParams: {}, // 打卡参数 |
|
|
|
recordInfo: {}, // 当前点击的打卡信息 |
|
|
|
punchTimeType: 0, // 打卡时间是上午还是下午 0 早打卡 1 晚打卡 |
|
|
|
remark: '', // 打卡原因 |
|
|
|
}; |
|
|
|
}, |
|
|
|
|
|
|
@ -279,6 +321,22 @@ export default { |
|
|
|
await this.getClockQuery(params); |
|
|
|
}, |
|
|
|
|
|
|
|
showModal() { |
|
|
|
this.visible = true; |
|
|
|
}, |
|
|
|
|
|
|
|
handleOk(e) { |
|
|
|
this.handleClockPunch(this.punchParams); |
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
|
this.visible = false; |
|
|
|
}, 2000); |
|
|
|
}, |
|
|
|
|
|
|
|
handleCancel(e) { |
|
|
|
this.visible = false; |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
|
* 查询考勤信息 |
|
|
|
* @param {string} projectId |
|
|
@ -317,6 +375,9 @@ export default { |
|
|
|
|
|
|
|
// 打卡 |
|
|
|
checkTime(listIndex, index, clockType, id, memberId, checkerId, clockTime) { |
|
|
|
this.auditOptions = { id, clockType }; |
|
|
|
|
|
|
|
this.showModal(); |
|
|
|
const time = Date.now(); |
|
|
|
const selectTime = this.$moment(time).format('HH:mm'); |
|
|
|
if (clockType === 0) { |
|
|
@ -324,9 +385,13 @@ export default { |
|
|
|
} else { |
|
|
|
this.clockInfos[listIndex].recordList[index].night = selectTime; |
|
|
|
} |
|
|
|
this.recordInfo = this.clockInfos[listIndex].recordList[index]; |
|
|
|
this.punchTimeType = clockType; |
|
|
|
this.selectedDate = clockTime; |
|
|
|
const dateTime = this.$moment(`${clockTime} ${selectTime}`).format('x') - 0; |
|
|
|
const params = { param: { checkerId: this.checkerId || checkerId || this.checkers[0].memberId, clockType, dateTime, id, memberId } }; |
|
|
|
this.handleClockPunch(params); |
|
|
|
this.punchParams = params; |
|
|
|
// this.handleClockPunch(params); |
|
|
|
}, |
|
|
|
|
|
|
|
/** |
|
|
@ -339,11 +404,19 @@ export default { |
|
|
|
*/ |
|
|
|
async handleClockPunch(params) { |
|
|
|
try { |
|
|
|
if (params.param.clockType === 0) { |
|
|
|
this.morningLoading = true; |
|
|
|
} else { |
|
|
|
this.nightLoading = true; |
|
|
|
// if (params.param.clockType === 0) { |
|
|
|
// this.morningLoading = true; |
|
|
|
// } else { |
|
|
|
// this.nightLoading = true; |
|
|
|
// } |
|
|
|
if (this.checkerId) { |
|
|
|
params.param.checkerId = this.checkerId; |
|
|
|
} |
|
|
|
|
|
|
|
if (this.remark) { |
|
|
|
params.param.remark = this.remark; |
|
|
|
} |
|
|
|
|
|
|
|
const res = await clockPunch(params); |
|
|
|
const { code, msg } = res.data; |
|
|
|
if (code === 200) { |
|
|
@ -354,17 +427,17 @@ export default { |
|
|
|
this.$message.error(msg || '打卡失败'); |
|
|
|
throw msg; |
|
|
|
} |
|
|
|
if (params.param.clockType === 0) { |
|
|
|
this.morningLoading = false; |
|
|
|
} else { |
|
|
|
this.nightLoading = false; |
|
|
|
} |
|
|
|
// if (params.param.clockType === 0) { |
|
|
|
// this.morningLoading = false; |
|
|
|
// } else { |
|
|
|
// this.nightLoading = false; |
|
|
|
// } |
|
|
|
} catch (error) { |
|
|
|
if (params.param.clockType === 0) { |
|
|
|
this.morningLoading = false; |
|
|
|
} else { |
|
|
|
this.nightLoading = false; |
|
|
|
} |
|
|
|
// if (params.param.clockType === 0) { |
|
|
|
// this.morningLoading = false; |
|
|
|
// } else { |
|
|
|
// this.nightLoading = false; |
|
|
|
// } |
|
|
|
throw error || '打卡失败'; |
|
|
|
} |
|
|
|
}, |
|
|
@ -395,14 +468,36 @@ export default { |
|
|
|
this.selectedDate = selectedDate; |
|
|
|
this.auditOptions = { id, type }; |
|
|
|
}, |
|
|
|
|
|
|
|
// 选择修改时间 |
|
|
|
timeChange(time) { |
|
|
|
let updateTime = this.$moment(time).format('HH:mm:ss'); |
|
|
|
let updateDate = this.selectedDate + ' ' + updateTime; |
|
|
|
this.chooseTime = this.$moment(updateDate).format('x'); |
|
|
|
this.chooseTime = this.$moment(updateDate).format('x') - 0; |
|
|
|
}, |
|
|
|
|
|
|
|
async openChange(open, record, show, timeType) { |
|
|
|
if (!open && this.chooseTime) { |
|
|
|
if (this.punchTimeType === 0) { |
|
|
|
let clockType = 0; |
|
|
|
if (timeType === 'morning') { |
|
|
|
clockType = 0; |
|
|
|
} else { |
|
|
|
clockType = 1; |
|
|
|
} |
|
|
|
const params = { |
|
|
|
param: { |
|
|
|
checkerId: this.checkerId || record.checkerId || this.checkers[0].memberId, |
|
|
|
clockType, |
|
|
|
dateTime: this.chooseTime, |
|
|
|
id: record.id, |
|
|
|
memberId: record.memberId, |
|
|
|
}, |
|
|
|
}; |
|
|
|
|
|
|
|
this.punchParams = params; |
|
|
|
} |
|
|
|
|
|
|
|
if (!open && this.chooseTime && this.punchTimeType === 1) { |
|
|
|
this.auditOptions[timeType] = this.chooseTime; |
|
|
|
this.auditOptions.projectId = this.projectId; |
|
|
|
const params = { param: this.auditOptions }; |
|
|
@ -531,6 +626,81 @@ img { |
|
|
|
background-color: #10b981 !important; |
|
|
|
color: #fff; |
|
|
|
} |
|
|
|
|
|
|
|
>>> .ant-modal-body { |
|
|
|
padding: 16px; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-title { |
|
|
|
font-size: 17px; |
|
|
|
font-weight: bold; |
|
|
|
height: 56px; |
|
|
|
line-height: 56px; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con { |
|
|
|
height: 48px; |
|
|
|
border-bottom: 1px solid rgba(0, 0, 0, 0.1); |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con .ant-input, |
|
|
|
.modal-con .ant-input:hover, |
|
|
|
.modal-con .ant-input:focus, |
|
|
|
.modal-con >>> .ant-time-picker-input { |
|
|
|
padding: 0; |
|
|
|
border: none; |
|
|
|
box-shadow: none; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con >>> .ant-time-picker { |
|
|
|
width: 130px; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con >>> .ant-time-picker-input { |
|
|
|
text-align: right; |
|
|
|
padding-right: 20px; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con >>> .ant-time-picker-icon, |
|
|
|
.modal-con >>> .ant-time-picker-clear, |
|
|
|
.modal-con >>> .ant-select-arrow { |
|
|
|
right: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con >>> .ant-select-selection, |
|
|
|
.modal-con >>> .ant-select-selection:hover { |
|
|
|
border: none; |
|
|
|
} |
|
|
|
|
|
|
|
.modal-con >>> .ant-select-selection-selected-value { |
|
|
|
float: unset; |
|
|
|
text-align: right; |
|
|
|
} |
|
|
|
|
|
|
|
>>> .ant-modal-footer { |
|
|
|
margin-top: 16px; |
|
|
|
padding: 0; |
|
|
|
} |
|
|
|
|
|
|
|
>>> .ant-modal-footer div { |
|
|
|
display: flex; |
|
|
|
} |
|
|
|
|
|
|
|
>>> .ant-modal-footer div .ant-btn { |
|
|
|
width: 50%; |
|
|
|
height: 56px; |
|
|
|
margin: 0; |
|
|
|
border: 0; |
|
|
|
border-radius: 0; |
|
|
|
font-size: 17px; |
|
|
|
} |
|
|
|
|
|
|
|
>>> .ant-modal-footer div .ant-btn.ant-btn-primary { |
|
|
|
background: transparent; |
|
|
|
color: #1890ff; |
|
|
|
border-left: 1px solid #e8e8e8; |
|
|
|
} |
|
|
|
</style> |
|
|
|
|
|
|
|
<style> |
|
|
|