增加考勤打卡记录页面的导出和同步

This commit is contained in:
BianLzhaoMin 2026-01-04 11:03:06 +08:00
parent e06985f423
commit 6c9c009630
5 changed files with 417 additions and 8 deletions

View File

@ -41,6 +41,7 @@
"clipboard": "2.0.8",
"core-js": "3.25.3",
"crypto-js": "^4.2.0",
"dayjs": "^1.11.19",
"echarts": "5.4.0",
"element-ui": "2.15.14",
"file-saver": "2.0.5",

View File

@ -160,3 +160,12 @@ export function getNoEntryAttendanceRecordListAPI(params) {
params,
})
}
// 同步考勤记录
export function syncAttendanceRecordAPI(data) {
return request({
url: '/bmw/kqManager/getDevAttr',
method: 'post',
data,
})
}

View File

@ -364,9 +364,15 @@ export default {
/* 生成查询参数 */
this.formLabel.map((e) => {
if (e.f_type === 'dateRange') {
this.$set(this.queryParams, e.dateType[0], '')
this.$set(this.queryParams, e.dateType[1], '')
this.typeList = e.dateType
if (e.initValue && Array.isArray(e.initValue) && e.initValue.length === 2) {
this.$set(this.queryParams, e.dateType[0], e.initValue[0])
this.$set(this.queryParams, e.dateType[1], e.initValue[1])
this.$set(this.queryParams, e.f_model, e.initValue)
} else {
this.$set(this.queryParams, e.dateType[0], '')
this.$set(this.queryParams, e.dateType[1], '')
}
if (this.isOneMonth) {
this.pickerOptions = {

View File

@ -12,22 +12,94 @@
:isIndexShow="false"
ref="tableRef"
:pageSizes="[100, 200, 500]"
@selection-change="handleSelectionChange"
>
<template slot="btn" slot-scope="{ queryParams }">
<el-button
size="mini"
type="success"
plain
icon="el-icon-download"
@click="onHandleExport(queryParams)"
>
导出
</el-button>
<el-button
size="mini"
type="primary"
plain
icon="el-icon-refresh"
@click="onHandleSync"
>
同步
</el-button>
</template>
</TableModel>
</div>
</el-card>
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseSyncDialog"
>
<template slot="outerContent">
<el-form
:model="syncForm"
label-width="120px"
ref="syncFormRef"
:rules="syncFormRules"
>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
type="date"
style="width: 100%"
value-format="yyyy-MM-dd"
v-model="syncForm.startTime"
placeholder="选择开始时间"
@change="handleStartTimeChange"
/>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
type="date"
style="width: 100%"
value-format="yyyy-MM-dd"
v-model="syncForm.endTime"
placeholder="选择结束时间"
@change="handleEndTimeChange"
/>
</el-form-item>
</el-form>
<el-row class="dialog-footer-btn">
<el-button size="medium" @click="handleCloseSyncDialog">
取消
</el-button>
<el-button
size="medium"
type="primary"
@click="handleSyncSubmit"
>
确定
</el-button>
</el-row>
</template>
</DialogModel>
</div>
</template>
<script>
import TableModel from '@/components/TableModel'
import { getAttendanceRecordListAPI } from '@/api/system/attMacManage.js'
import DialogModel from '@/components/DialogModel'
import dayjs from 'dayjs'
import {
getAttendanceRecordListAPI,
syncAttendanceRecordAPI,
} from '@/api/system/attMacManage.js'
export default {
name: 'TaskHistoryList',
components: {
TableModel,
DialogModel,
},
props: {
macNo: {
@ -53,6 +125,10 @@ export default {
f_label: '打卡时间',
f_model: 'time',
dateType: ['startTime', 'endTime'],
initValue: [
dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
dayjs().format('YYYY-MM-DD'),
],
f_type: 'dateRange',
f_width: '240px',
},
@ -88,6 +164,44 @@ export default {
t_props: 'userName',
},
],
dialogConfig: {
outerVisible: false,
outerTitle: '同步考勤记录',
outerWidth: '50%',
minHeight: '40vh',
maxHeight: '50%',
},
syncForm: {
startTime: dayjs().subtract(7, 'day').format('YYYY-MM-DD'), //
endTime: dayjs().format('YYYY-MM-DD'), //
deviceCode: this.macNo || '',
},
syncFormRules: {
startTime: [
{
required: true,
message: '请选择开始时间',
trigger: 'blur',
},
{
validator: this.validateStartTime,
trigger: 'change',
},
],
endTime: [
{
required: true,
message: '请选择结束时间',
trigger: 'blur',
},
{
validator: this.validateEndTime,
trigger: 'change',
},
],
},
}
},
computed: {
@ -128,6 +242,90 @@ export default {
this.$refs.tableRef.getTableList()
}
},
onHandleExport(queryParams) {
const params = { ...queryParams }
delete params.time
Object.keys(params).forEach((key) => {
if (key.startsWith('time[') || key === 'time') {
delete params[key]
}
})
this.download(
'/bmw/kqManager/exportAttrExcel',
params,
'考勤打卡记录.xlsx',
)
},
//
onHandleSync() {
if (!this.macNo) {
this.$modal.msgWarning('请选择考勤机')
return
}
this.dialogConfig.outerVisible = true
},
//
handleCloseSyncDialog() {
this.$refs.syncFormRef.resetFields()
this.dialogConfig.outerVisible = false
},
validateStartTime(rule, value, callback) {
if (!value) {
callback()
return
}
if (this.syncForm.endTime && value > this.syncForm.endTime) {
callback(new Error('开始时间不能大于结束时间'))
} else {
callback()
}
},
validateEndTime(rule, value, callback) {
if (!value) {
callback()
return
}
if (this.syncForm.startTime && value < this.syncForm.startTime) {
callback(new Error('结束时间不能小于开始时间'))
} else {
callback()
}
},
handleStartTimeChange() {
if (this.$refs.syncFormRef) {
this.$refs.syncFormRef.validateField('endTime')
}
},
handleEndTimeChange() {
if (this.$refs.syncFormRef) {
this.$refs.syncFormRef.validateField('startTime')
}
},
handleSyncSubmit() {
this.$refs.syncFormRef.validate((valid) => {
if (valid) {
syncAttendanceRecordAPI(this.syncForm)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('同步成功')
this.handleCloseSyncDialog()
this.getTableList()
} else {
this.$modal.msgError(res.msg || '同步失败')
}
})
.catch((error) => {
this.$modal.msgError(
error.message || '同步失败,请稍后重试',
)
})
}
})
},
},
}
</script>

View File

@ -12,22 +12,94 @@
:isIndexShow="false"
ref="tableRef"
:pageSizes="[100, 200, 500]"
@selection-change="handleSelectionChange"
>
<template slot="btn" slot-scope="{ queryParams }">
<el-button
size="mini"
type="success"
plain
icon="el-icon-download"
@click="onHandleExport(queryParams)"
>
导出
</el-button>
<el-button
size="mini"
type="primary"
plain
icon="el-icon-refresh"
@click="onHandleSync"
>
同步
</el-button>
</template>
</TableModel>
</div>
</el-card>
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseSyncDialog"
>
<template slot="outerContent">
<el-form
:model="syncForm"
label-width="120px"
ref="syncFormRef"
:rules="syncFormRules"
>
<el-form-item label="开始时间" prop="startTime">
<el-date-picker
type="date"
style="width: 100%"
value-format="yyyy-MM-dd"
v-model="syncForm.startTime"
placeholder="选择开始时间"
@change="handleStartTimeChange"
/>
</el-form-item>
<el-form-item label="结束时间" prop="endTime">
<el-date-picker
type="date"
style="width: 100%"
value-format="yyyy-MM-dd"
v-model="syncForm.endTime"
placeholder="选择结束时间"
@change="handleEndTimeChange"
/>
</el-form-item>
</el-form>
<el-row class="dialog-footer-btn">
<el-button size="medium" @click="handleCloseSyncDialog">
取消
</el-button>
<el-button
size="medium"
type="primary"
@click="handleSyncSubmit"
>
确定
</el-button>
</el-row>
</template>
</DialogModel>
</div>
</template>
<script>
import TableModel from '@/components/TableModel'
import { getAttendanceRecordListAPI } from '@/api/system/attMacManage.js'
import DialogModel from '@/components/DialogModel'
import dayjs from 'dayjs'
import {
getAttendanceRecordListAPI,
syncAttendanceRecordAPI,
} from '@/api/system/attMacManage.js'
export default {
name: 'TaskHistoryList',
components: {
TableModel,
DialogModel,
},
props: {
macNo: {
@ -53,6 +125,10 @@ export default {
f_label: '打卡时间',
f_model: 'time',
dateType: ['startTime', 'endTime'],
initValue: [
dayjs().subtract(7, 'day').format('YYYY-MM-DD'),
dayjs().format('YYYY-MM-DD'),
],
f_type: 'dateRange',
f_width: '240px',
},
@ -88,6 +164,44 @@ export default {
t_props: 'userName',
},
],
dialogConfig: {
outerVisible: false,
outerTitle: '同步考勤记录',
outerWidth: '50%',
minHeight: '40vh',
maxHeight: '50%',
},
syncForm: {
startTime: dayjs().subtract(7, 'day').format('YYYY-MM-DD'), //
endTime: dayjs().format('YYYY-MM-DD'), //
deviceCode: this.macNo || '',
},
syncFormRules: {
startTime: [
{
required: true,
message: '请选择开始时间',
trigger: 'blur',
},
{
validator: this.validateStartTime,
trigger: 'change',
},
],
endTime: [
{
required: true,
message: '请选择结束时间',
trigger: 'blur',
},
{
validator: this.validateEndTime,
trigger: 'change',
},
],
},
}
},
computed: {
@ -107,6 +221,7 @@ export default {
macNo: {
handler() {
//
//
if (!this.macNo) {
this.$modal.msgWarning('请选择考勤机')
return
@ -128,8 +243,88 @@ export default {
}
},
handleSelectionChange(val) {
this.selectedData = val
onHandleExport(queryParams) {
const params = { ...queryParams }
delete params.time
Object.keys(params).forEach((key) => {
if (key.startsWith('time[') || key === 'time') {
delete params[key]
}
})
this.download(
'/bmw/kqManager/exportAttrExcel',
params,
'考勤打卡记录.xlsx',
)
},
//
onHandleSync() {
if (!this.macNo) {
this.$modal.msgWarning('请选择考勤机')
return
}
this.dialogConfig.outerVisible = true
},
//
handleCloseSyncDialog() {
this.$refs.syncFormRef.resetFields()
this.dialogConfig.outerVisible = false
},
validateStartTime(rule, value, callback) {
if (!value) {
callback()
return
}
if (this.syncForm.endTime && value > this.syncForm.endTime) {
callback(new Error('开始时间不能大于结束时间'))
} else {
callback()
}
},
validateEndTime(rule, value, callback) {
if (!value) {
callback()
return
}
if (this.syncForm.startTime && value < this.syncForm.startTime) {
callback(new Error('结束时间不能小于开始时间'))
} else {
callback()
}
},
handleStartTimeChange() {
if (this.$refs.syncFormRef) {
this.$refs.syncFormRef.validateField('endTime')
}
},
handleEndTimeChange() {
if (this.$refs.syncFormRef) {
this.$refs.syncFormRef.validateField('startTime')
}
},
handleSyncSubmit() {
this.$refs.syncFormRef.validate((valid) => {
if (valid) {
syncAttendanceRecordAPI(this.syncForm)
.then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess('同步成功')
this.handleCloseSyncDialog()
this.getTableList()
} else {
this.$modal.msgError(res.msg || '同步失败')
}
})
.catch((error) => {
this.$modal.msgError(
error.message || '同步失败,请稍后重试',
)
})
}
})
},
},
}