考勤审核以及考勤统计模块完善

This commit is contained in:
BianLzhaoMin 2025-08-18 13:48:25 +08:00
parent 4132c24d63
commit 2f675cea74
16 changed files with 527 additions and 934 deletions

View File

@ -30,8 +30,8 @@ export const getCardReplacementPersonCheckRecordAPI = (data) => {
// 修改补卡申请
export const editCardReplacementApplyAPI = (data) => {
return request({
url: '/bmw/pmAttDevice/updatePmAttDevice',
return requestFormData({
url: '/bmw/cardApply/updateRepairCardApply',
method: 'POST',
data,
})

View File

@ -0,0 +1,28 @@
import request from '@/utils/request'
// 获取补卡统计列表
export const getCardReplacementCountListAPI = (data) => {
return request({
url: '/bmw/cardApply/cardStatistics',
method: 'GET',
params: data,
})
}
// 获取补卡审核详情
export const getCardReplacementAuditDetailAPI = (data) => {
return request({
url: '/bmw/cardApply/getRepairCardDetails',
method: 'GET',
params: data,
})
}
// 补卡审核接口
export const cardReplacementAuditAPI = (data) => {
return request({
url: '/bmw/cardApply/audit',
method: 'POST',
data,
})
}

View File

@ -296,7 +296,9 @@ export default {
)
.map((j) => j.id)
params.fileIdList = fileIdList
if (fileIdList.length > 0) {
params.fileIdList = fileIdList
}
}
if (fileMsg.length > 0) {

View File

@ -1,22 +1,23 @@
<template>
<!--补卡申请表单 -->
<div style="width: 100%">
<el-row>
<el-row style="display: flex; align-items: center">
<el-col :span="20">
<TitleTip
borderBottom="none"
padding="24px 10px"
padding="12px 10px"
titleText="补卡人员清单"
justifyContent="flex-start"
>
<template name="right">
<span>{{ selectProjectName }}</span>
<span class="tip-text">{{ selectProjectName }}</span>
</template>
</TitleTip>
</el-col>
<el-col :span="4">
<el-col :span="4" style="text-align: right">
<el-button
type="primary"
size="mini"
size="medium"
icon="el-icon-plus"
@click="handleSelectPerson"
>
@ -80,7 +81,7 @@
maxlength="30"
type="textarea"
show-word-limit
placeholder="请输入考勤机编码"
placeholder="请输入补卡说明"
v-model="addParams.repairRemark"
:autosize="{ minRows: 4, maxRows: 8 }"
/>
@ -142,7 +143,11 @@
import DialogModel from '@/components/DialogModel'
import UploadFileFormData from '@/components/UploadFileFormData'
import SelectPersonAndDate from './select-person-and-date.vue'
import { addCardReplacementApplyAPI } from '@/api/construction-person/attendance-manage/card-replacement-apply'
import {
addCardReplacementApplyAPI,
editCardReplacementApplyAPI,
} from '@/api/construction-person/attendance-manage/card-replacement-apply'
import { getCardReplacementAuditDetailAPI } from '@/api/construction-person/attendance-manage/card-replacement-audit'
export default {
name: 'AddApplyForm',
props: {
@ -154,6 +159,10 @@ export default {
type: [Number, String],
default: () => '',
},
queryDetailsId: {
type: [Number, String],
default: () => '',
},
},
components: {
DialogModel,
@ -185,11 +194,11 @@ export default {
},
editRow: {}, //
editUploadFileList: [], //
}
},
methods: {
handleSelectPerson() {
// console.log(this.addApplyForm)
this.dialogConfig.outerVisible = true
},
handleCloseDialogOuter() {
@ -215,7 +224,6 @@ export default {
//
onHandleEdit(row) {
console.log(row)
this.editRow = row
this.dialogConfig.outerTitle = '修改补卡人员以及补卡日期'
this.dialogConfig.outerVisible = true
@ -226,7 +234,7 @@ export default {
this.tableData.splice(index, 1)
},
//
//
async onHandleConfirmFinishFun() {
return new Promise(async (resolve, reject) => {
//
@ -234,6 +242,7 @@ export default {
const repairNum = this.tableData.length
const formData = new FormData()
const fileMsg = []
let fileIdList = []
const repairDay = this.tableData.reduce((acc, curr) => {
return acc + curr.repairDay
}, 0)
@ -257,22 +266,48 @@ export default {
}),
}
if (this.queryDetailsId) {
params.id = this.queryDetailsId
const reserveFileList = fileList
.filter((e) => e.id)
.map((j) => j.id)
fileIdList = this.editUploadFileList
.filter((item) => !reserveFileList.includes(item.id))
.map((j) => j.id)
if (fileIdList.length > 0) {
params.fileIdList = fileIdList
}
}
if (fileList.length > 0) {
fileList.forEach((e) => {
fileMsg.push({
type: 1,
name: '附件',
})
if (!e.id) {
fileMsg.push({
type: 1,
name: '附件',
})
formData.append('file', e.raw)
formData.append('file', e.raw)
}
})
}
formData.append('fileMsg', JSON.stringify(fileMsg))
formData.append('params', JSON.stringify(params))
const res = await addCardReplacementApplyAPI(formData)
const API = this.queryDetailsId
? editCardReplacementApplyAPI
: addCardReplacementApplyAPI
const res = await API(formData)
if (res.code === 200) {
this.$modal.msgSuccess('补卡信息新增成功')
this.$modal.msgSuccess(
this.queryDetailsId
? '补卡信息修改成功'
: '补卡信息新增成功',
)
resolve()
} else {
this.$modal.msgError(res.msg)
@ -280,6 +315,38 @@ export default {
}
})
},
//
async getCardReplacementAuditDetail() {
const { data: res } = await getCardReplacementAuditDetailAPI({
id: this.queryDetailsId,
})
const { files } = res
this.editUploadFileList = files
if (files.length > 0) {
this.addParams.fileList = files.map((e) => {
return {
id: e.id,
url: e.lsUrl,
name: e.originFileName,
}
})
}
this.tableData = res.repairCardDetails
this.addParams.repairRemark = res.repairRemark
},
},
watch: {
queryDetailsId: {
handler(newVal) {
if (newVal) {
this.getCardReplacementAuditDetail()
}
},
deep: true,
immediate: true,
},
},
}
</script>

View File

@ -3,19 +3,33 @@ export const formLabel = [
isShow: false, // 是否展示label
f_type: 'ipt',
f_label: '姓名',
f_model: 'name',
f_model: 'applyUser',
},
{
isShow: false, // 是否展示label
f_type: 'ipt',
f_type: 'sel',
f_label: '工程',
f_model: 'deviceName',
f_model: 'proId',
},
{
isShow: false, // 是否展示label
f_type: 'ipt',
f_type: 'sel',
f_label: '状态',
f_model: 'proName',
f_model: 'checkStatus',
f_selList: [
{
label: '审核中',
value: 0,
},
{
label: '通过',
value: 1,
},
{
label: '驳回',
value: 2,
},
],
},
]

View File

@ -109,9 +109,15 @@
</el-row>
</template>
<template v-if="dialogConfig.outerTitle === '新增补卡申请'">
<template
v-if="
dialogConfig.outerTitle === '新增补卡申请' ||
dialogConfig.outerTitle === '修改补卡申请'
"
>
<AddApplyForm
ref="addApplyFormRef"
:queryDetailsId="queryDetailsId"
:selectProjectId="selectProjectId"
:selectProjectName="selectProjectName"
/>
@ -147,7 +153,6 @@ import {
deleteCardReplacementApplyAPI,
getCardReplacementApplyListAPI,
} from '@/api/construction-person/attendance-manage/card-replacement-apply'
import { getLotProjectSelectListCommonFun } from '@/utils/getCommonData'
export default {
name: 'CardReplacementApply',
@ -169,27 +174,36 @@ export default {
lotProjectOptions: [],
selectProjectId: '',
selectProjectName: '',
queryDetailsId: '',
}
},
methods: {
//
onHandleExportCardReplacementApply(queryParams) {
// this.download(
// '/bmw/pmAttDevice/export',
// {
// ...queryParams,
// },
// `.xlsx`,
// )
this.download(
'/bmw/cardApply/export',
{
...queryParams,
},
`补卡审请列表.xlsx`,
)
},
//
onHandleEditCardReplacementApply(data) {
console.log(data)
this.queryDetailsId = data.id
this.selectProjectId = data.proId
this.selectProjectName = data.proName
this.dialogConfig.outerTitle = '修改补卡申请'
this.dialogConfig.outerWidth = '80%'
this.dialogConfig.minHeight = '80vh'
this.dialogConfig.maxHeight = '80h'
this.dialogConfig.outerVisible = true
},
//
onHandleAddCardReplacementApply(type, data) {
this.queryDetailsId = ''
this.dialogConfig.outerTitle = '选择补卡工程'
this.dialogConfig.outerWidth = '30%'
this.dialogConfig.minHeight = ''
@ -262,6 +276,7 @@ export default {
value: item.id,
label: item.proName,
}))
this.formLabel[1].f_selList = this.lotProjectOptions
},
}
</script>

View File

@ -91,7 +91,7 @@
: '#999',
}"
:class="{
'item-active': item.isChecked,
'item-active': item.isChecked && item.isActive === 0,
}"
>
{{ item.date }}

View File

@ -9,7 +9,7 @@
justifyContent="flex-start"
>
<template name="right">
<span>{{ selectProjectName }}</span>
<span class="tip-text">{{ selectProjectName }}</span>
</template>
</TitleTip>
</el-col>
@ -29,25 +29,6 @@
<el-table-column align="center" label="补卡工程" prop="proName" />
<el-table-column align="center" label="联系方式" prop="phone" />
<el-table-column align="center" label="所属班组" prop="teamName" />
<el-table-column align="center" label="操作" width="160">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="onHandleEdit(scope.row)"
>
修改
</el-button>
<el-button
size="mini"
type="text"
style="color: #f56c6c"
@click="onHandleDelete($scope.index, scope)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<TitleTip
@ -60,18 +41,17 @@
<el-form
label-width="140px"
ref="addOrEditFormRef"
:model="addApplyForm"
:model="detailsParams"
>
<el-row>
<el-col :span="12">
<el-form-item label="补卡说明" prop="repairRemark">
<el-form-item label="补卡说明">
<el-input
clearable
maxlength="30"
disabled
type="textarea"
show-word-limit
placeholder="请输入考勤机编码"
v-model="addParams.repairRemark"
v-model="detailsParams.repairRemark"
:autosize="{ minRows: 4, maxRows: 8 }"
/>
</el-form-item>
@ -117,29 +97,11 @@ export default {
data() {
return {
addApplyForm: {
reason: '',
},
dialogConfig: {
outerTitle: '选择补卡人员以及补卡日期',
outerWidth: '',
minHeight: '90vh',
maxHeight: '90vh',
outerVisible: false,
},
tableData: [],
addParams: {
// proId: '', // id
// repairNum: '', //
// repairDay: '', //
detailsParams: {
repairRemark: '', //
repairMonth: '2025-08', //
repairCardRecords: [],
fileList: [],
},
editRow: {}, //
}
},
methods: {
@ -148,7 +110,8 @@ export default {
const { data: res } = await getCardReplacementAuditDetailAPI({
id: this.queryDetailsId,
})
console.log(res)
this.tableData = res.repairCardDetails
this.detailsParams.repairRemark = res.repairRemark
},
},

View File

@ -3,19 +3,33 @@ export const formLabel = [
isShow: false, // 是否展示label
f_type: 'ipt',
f_label: '姓名',
f_model: 'deviceCode',
f_model: 'applyUser',
},
{
isShow: false, // 是否展示label
f_type: 'ipt',
f_type: 'sel',
f_label: '工程',
f_model: 'deviceName',
f_model: 'proId',
},
{
isShow: false, // 是否展示label
f_type: 'ipt',
f_type: 'sel',
f_label: '状态',
f_model: 'proName',
f_model: 'checkStatus',
f_selList: [
{
label: '待审核',
value: 0,
},
{
label: '通过',
value: 1,
},
{
label: '驳回',
value: 2,
},
],
},
]

View File

@ -27,17 +27,18 @@
size="mini"
type="warning"
icon="el-icon-check"
v-if="data.checkStatus === 0"
v-hasPermi="['attendance:machine:unbind']"
@click="onHandleAudit(data)"
@click="onHandleAuditAndDetail(data, 1, '补卡审核')"
>
审核
审核
</el-button>
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
type="primary"
icon="el-icon-view"
@click="onHandleAuditAndDetail(data, 2, '补卡详情')"
v-hasPermi="['attendance:machine:delete']"
@click="onHandleDetail(data)"
>
详情
</el-button>
@ -49,7 +50,7 @@
type="warning"
v-if="data.checkStatus === 0"
>
审核
审核
</el-tag>
<el-tag
size="mini"
@ -76,7 +77,10 @@
:selectProjectName="selectProjectName"
/>
<el-row class="dialog-footer-btn">
<el-row
class="dialog-footer-btn"
v-if="dialogConfig.outerTitle === '补卡审核'"
>
<el-button
size="medium"
type="danger"
@ -136,6 +140,7 @@ import {
getCardReplacementAuditListAPI,
cardReplacementAuditAPI,
} from '@/api/construction-person/attendance-manage/card-replacement-audit'
import { getLotProjectSelectListCommonFun } from '@/utils/getCommonData'
export default {
name: 'CardReplacementAudit',
@ -152,7 +157,6 @@ export default {
dialogConfig,
editFormData: {}, //
getCardReplacementAuditListAPI,
lotProjectOptions: [],
queryDetailsId: '',
selectProjectName: '',
@ -163,26 +167,22 @@ export default {
//
onHandleExportCardReplacementAudit(queryParams) {
this.download(
'/bmw/pmAttDevice/export',
'/bmw/cardApply/export',
{
...queryParams,
},
`考勤机列表.xlsx`,
`补卡审核列表.xlsx`,
)
},
//
onHandleAudit(data) {
//
onHandleAuditAndDetail(data, type, title) {
this.selectProjectName = data.proName
this.queryDetailsId = data.id
this.dialogConfig.outerTitle = title
this.dialogConfig.outerVisible = true
},
//
onHandleDetail(data) {
console.log(data)
},
//
onHandleReject() {
this.dialogConfig.innerVisible = true
@ -221,7 +221,7 @@ export default {
// console.log('')
})
.finally(() => {
if (checkStatus === 0) {
if (checkStatus === 2) {
this.refuseRemark = ''
this.dialogConfig.innerVisible = false
}
@ -239,5 +239,13 @@ export default {
this.dialogConfig.innerVisible = false
},
},
async created() {
const lot = await getLotProjectSelectListCommonFun()
this.formLabel[1].f_selList = lot.map((item) => ({
value: item.id,
label: item.proName,
}))
},
}
</script>

View File

@ -1,285 +0,0 @@
<template>
<div style="width: 100%">
<el-row>
<el-col :span="20">
<TitleTip
borderBottom="none"
padding="24px 10px"
titleText="补卡人员清单"
justifyContent="flex-start"
>
<template name="right">
<span>{{ selectProjectName }}</span>
</template>
</TitleTip>
</el-col>
<el-col :span="4">
<el-button
type="primary"
size="mini"
icon="el-icon-plus"
@click="handleSelectPerson"
>
选择补卡人员
</el-button>
</el-col>
</el-row>
<el-table :data="tableData">
<el-table-column align="center" label="姓名" prop="name" />
<el-table-column align="center" label="身份证" prop="idNumber" />
<el-table-column align="center" label="补卡天数" prop="repairDay" />
<el-table-column
align="center"
width="300"
label="补卡日期"
prop="repairDate"
show-overflow-tooltip
/>
<el-table-column align="center" label="补卡工程" prop="proName" />
<el-table-column align="center" label="联系方式" prop="phone" />
<el-table-column align="center" label="所属班组" prop="teamName" />
<el-table-column align="center" label="操作" width="160">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="onHandleEdit(scope.row)"
>
修改
</el-button>
<el-button
size="mini"
type="text"
style="color: #f56c6c"
@click="onHandleDelete($scope.index, scope)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<TitleTip
borderBottom="none"
padding="24px 10px"
titleText="补卡说明"
justifyContent="flex-start"
/>
<el-form
label-width="140px"
ref="addOrEditFormRef"
:model="addApplyForm"
>
<el-row>
<el-col :span="12">
<el-form-item label="补卡说明" prop="repairRemark">
<el-input
clearable
maxlength="30"
type="textarea"
show-word-limit
placeholder="请输入考勤机编码"
v-model="addParams.repairRemark"
:autosize="{ minRows: 4, maxRows: 8 }"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件">
<UploadFileFormData
:limit="3"
:file-size="20"
:multiple="true"
uploadTip="补卡说明附件上传"
:file-list.sync="addParams.fileList"
:file-type="[
'jpg',
'png',
'jpeg',
'pdf',
'doc',
'docx',
]"
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter"
>
<template slot="outerContent">
<SelectPersonAndDate
:editRow="editRow"
ref="selectPersonAndDateRef"
@onPersonSubmit="onPersonSubmit"
:selectProjectId="selectProjectId"
:selectProjectName="selectProjectName"
/>
<el-row class="dialog-footer-btn">
<el-button size="medium" @click="handleCloseDialogOuter">
取消
</el-button>
<el-button
size="medium"
type="primary"
@click="onHandleConfirm"
>
确定
</el-button>
</el-row>
</template>
</DialogModel>
</div>
</template>
<script>
import DialogModel from '@/components/DialogModel'
import UploadFileFormData from '@/components/UploadFileFormData'
import SelectPersonAndDate from './select-person-and-date.vue'
import { addCardReplacementApplyAPI } from '@/api/construction-person/attendance-manage/card-replacement-apply'
export default {
name: 'AddApplyForm',
props: {
selectProjectName: {
type: String,
default: () => '',
},
selectProjectId: {
type: [Number, String],
default: () => '',
},
},
components: {
DialogModel,
SelectPersonAndDate,
UploadFileFormData,
},
data() {
return {
addApplyForm: {
reason: '',
},
dialogConfig: {
outerTitle: '选择补卡人员以及补卡日期',
outerWidth: '',
minHeight: '90vh',
maxHeight: '90vh',
outerVisible: false,
},
tableData: [],
addParams: {
// proId: '', // id
// repairNum: '', //
// repairDay: '', //
repairRemark: '', //
repairMonth: '2025-08', //
repairCardRecords: [],
fileList: [],
},
editRow: {}, //
}
},
methods: {
handleSelectPerson() {
// console.log(this.addApplyForm)
this.dialogConfig.outerVisible = true
},
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
// ----
onHandleConfirm() {
this.$refs.selectPersonAndDateRef.onPersonSubmit()
this.dialogConfig.outerVisible = false
},
//
onPersonSubmit(val) {
//
if (val && val.length > 0) {
val.forEach((item) => {
console.log(item, 'item----')
this.tableData.push(item)
})
}
},
//
onHandleEdit(row) {
console.log(row)
this.editRow = row
this.dialogConfig.outerTitle = '修改补卡人员以及补卡日期'
this.dialogConfig.outerVisible = true
},
//
onHandleDelete(index, row) {
this.tableData.splice(index, 1)
},
//
async onHandleConfirmFinishFun() {
return new Promise(async (resolve, reject) => {
//
const { repairMonth, repairRemark, fileList } = this.addParams
const repairNum = this.tableData.length
const formData = new FormData()
const fileMsg = []
const repairDay = this.tableData.reduce((acc, curr) => {
return acc + curr.repairDay
}, 0)
const params = {
proId: this.selectProjectId,
repairMonth,
repairRemark,
repairNum,
repairDay,
repairCardRecords: this.tableData.map((e) => {
return {
name: e.name,
phone: e.phone,
proId: e.proId,
teamId: e.teamId,
idNumber: e.idNumber,
workerId: e.workerId,
repairDay: e.repairDay,
repairDate: e.repairDate,
}
}),
}
if (fileList.length > 0) {
fileList.forEach((e) => {
fileMsg.push({
type: 1,
name: '附件',
})
formData.append('file', e.raw)
})
}
formData.append('fileMsg', JSON.stringify(fileMsg))
formData.append('params', JSON.stringify(params))
const res = await addCardReplacementApplyAPI(formData)
if (res.code === 200) {
this.$modal.msgSuccess('补卡信息新增成功')
resolve()
} else {
this.$modal.msgError(res.msg)
reject()
}
})
},
},
}
</script>

View File

@ -0,0 +1,130 @@
<template>
<div style="width: 100%">
<el-row>
<el-col :span="20">
<TitleTip
borderBottom="none"
padding="24px 10px"
titleText="补卡人员清单"
justifyContent="flex-start"
>
<template name="right">
<span class="tip-text">{{ selectProjectName }}</span>
</template>
</TitleTip>
</el-col>
</el-row>
<el-table :data="tableData">
<el-table-column align="center" label="姓名" prop="name" />
<el-table-column align="center" label="身份证" prop="idNumber" />
<el-table-column align="center" label="补卡天数" prop="repairDay" />
<el-table-column
align="center"
width="300"
label="补卡日期"
prop="repairDate"
show-overflow-tooltip
/>
<el-table-column align="center" label="补卡工程" prop="proName" />
<el-table-column align="center" label="联系方式" prop="phone" />
<el-table-column align="center" label="所属班组" prop="teamName" />
</el-table>
<TitleTip
borderBottom="none"
padding="24px 10px"
titleText="补卡说明"
justifyContent="flex-start"
/>
<el-form
label-width="140px"
ref="addOrEditFormRef"
:model="detailsParams"
>
<el-row>
<el-col :span="12">
<el-form-item label="补卡说明">
<el-input
clearable
disabled
type="textarea"
placeholder="请输入考勤机编码"
v-model="detailsParams.repairRemark"
:autosize="{ minRows: 4, maxRows: 8 }"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="附件">
<!-- <UploadFileFormData
:limit="3"
:file-size="20"
:multiple="true"
uploadTip="补卡说明附件上传"
:file-list.sync="addParams.fileList"
:file-type="[
'jpg',
'png',
'jpeg',
'pdf',
'doc',
'docx',
]"
/> -->
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
import { getCardReplacementAuditDetailAPI } from '@/api/construction-person/attendance-manage/card-replacement-audit'
export default {
name: 'AddApplyForm',
props: {
selectProjectName: {
type: String,
default: () => '',
},
queryDetailsId: {
type: [Number, String],
default: () => '',
},
},
data() {
return {
tableData: [],
detailsParams: {
repairRemark: '', //
fileList: [],
},
}
},
methods: {
//
async getCardReplacementAuditDetail() {
const { data: res } = await getCardReplacementAuditDetailAPI({
id: this.queryDetailsId,
})
this.tableData = res.repairCardDetails
this.detailsParams.repairRemark = res.repairRemark
},
},
watch: {
queryDetailsId: {
handler(newVal) {
if (newVal) {
this.getCardReplacementAuditDetail()
}
},
deep: true,
immediate: true,
},
},
}
</script>

View File

@ -1,27 +1,28 @@
export const formLabel = [
{
isShow: false, // 是否展示label
f_type: 'ipt',
f_type: 'sel',
f_label: '工程',
f_model: 'deviceName',
f_model: 'proId',
f_selList: [], // 工程列表
},
]
export const columnsList = [
{ t_props: 'deviceCode', t_label: '工程名称' },
{ t_props: 'deviceName', t_label: '申请补卡次数' },
{ t_props: 'proName', t_label: '申请补卡人数' },
{ t_slot: 'isShanghai', t_label: '申请补卡天数' },
{ t_props: 'proName', t_label: '工程名称' },
{ t_props: 'num', t_label: '申请补卡次数' },
{ t_props: 'personNum', t_label: '申请补卡人数' },
{ t_props: 'days', t_label: '累计补卡天数' },
{
t_label: '最后申请时间',
t_slot: 'onLine',
t_props: 'createTime',
},
]
export const dialogConfig = {
outerTitle: '',
minHeight: '',
maxHeight: '',
outerWidth: '40%',
minHeight: '90vh',
maxHeight: '90vh',
outerWidth: '80%',
outerVisible: false,
}

View File

@ -6,8 +6,7 @@
:showOperation="true"
:showRightTools="true"
:columnsList="columnsList"
ref="cardReplacementApplyTableRef"
:request-api="getCardReplacementApplyListAPI"
:request-api="getCardReplacementCountListAPI"
>
<template slot="btn" slot-scope="{ queryParams }">
<el-button
@ -15,42 +14,20 @@
size="mini"
type="success"
icon="el-icon-download"
@click="onHandleExportAttendanceMachine(queryParams)"
@click="onHandleExportCardReplacementCount(queryParams)"
>
导出
</el-button>
<el-button
plain
size="mini"
type="primary"
icon="el-icon-plus"
v-hasPermi="['attendance:machine:add']"
@click="onHandleAddCardReplacementApply(1, null)"
>
新增
</el-button>
</template>
<template slot="handle" slot-scope="{ data }">
<!-- <el-button
plain
size="mini"
type="warning"
icon="el-icon-edit"
v-hasPermi="['attendance:machine:unbind']"
@click="onHandleUnBindAttendanceMachine(data)"
>
解绑
</el-button> -->
<el-button
size="mini"
type="danger"
icon="el-icon-delete"
v-hasPermi="['attendance:machine:delete']"
@click="onHandleDeleteSubBaseInfo(data)"
type="primary"
icon="el-icon-view"
@click="onHandleViewDetail(data)"
>
删除
详情
</el-button>
</template>
</TableModel>
@ -60,58 +37,7 @@
@closeDialogOuter="handleCloseDialogOuter"
>
<template slot="outerContent">
<template v-if="dialogConfig.outerTitle === '选择补卡工程'">
<el-form label-width="100px">
<el-form-item label="补卡工程">
<el-select
style="width: 100%"
placeholder="请选择"
v-model="selectProjectId"
@change="handleSelectProject"
>
<el-option
:key="item.value"
:label="item.label"
:value="item.value"
v-for="item in lotProjectOptions"
/>
</el-select>
</el-form-item>
</el-form>
<el-row class="dialog-footer-btn">
<el-button
size="medium"
type="primary"
@click="onHandleNextStep"
>
下一步
</el-button>
</el-row>
</template>
<template v-if="dialogConfig.outerTitle === '新增补卡申请'">
<AddApplyForm
ref="addApplyFormRef"
:selectProjectId="selectProjectId"
:selectProjectName="selectProjectName"
/>
<el-row class="dialog-footer-btn">
<el-button
size="medium"
@click="handleCloseDialogOuter"
>
取消
</el-button>
<el-button
size="medium"
type="primary"
@click="onHandleConfirmFinish"
>
确定
</el-button>
</el-row>
</template>
<!-- <ProjectDetails :proId="proId" /> -->
</template>
</DialogModel>
</div>
@ -120,22 +46,16 @@
<script>
import TableModel from '@/components/TableModel'
import DialogModel from '@/components/DialogModel'
import AddApplyForm from './add-apply-form.vue'
// import ProjectDetails from './project-details.vue'
import { formLabel, columnsList, dialogConfig } from './config'
import {
deleteAttendanceMachineAPI,
getCardReplacementApplyListAPI,
} from '@/api/construction-person/attendance-manage/card-replacement-apply'
import { getCardReplacementCountListAPI } from '@/api/construction-person/attendance-manage/card-replacement-count'
import { getLotProjectSelectListCommonFun } from '@/utils/getCommonData'
export default {
name: 'CardReplacementCount',
components: {
TableModel,
DialogModel,
AddApplyForm,
// ProjectDetails,
},
data() {
@ -144,121 +64,40 @@ export default {
columnsList,
dialogConfig,
editFormData: {}, //
getCardReplacementApplyListAPI,
getCardReplacementCountListAPI,
lotProjectOptions: [],
selectProjectId: '',
selectProjectName: '',
proId: '',
}
},
methods: {
//
onHandleExportAttendanceMachine(queryParams) {
this.download(
'/bmw/pmAttDevice/export',
{
...queryParams,
},
`考勤机列表.xlsx`,
)
onHandleExportCardReplacementCount(queryParams) {
// this.download(
// '/bmw/pmAttDevice/export',
// {
// ...queryParams,
// },
// `.xlsx`,
// )
},
//
onHandleAddOrBindAttendanceMachine(type, data) {
this.dialogConfig.outerTitle =
type === 1 ? '新增考勤机' : '绑定考勤机'
if (type === 2) {
const { proId, deviceCode, deviceName } = data
this.editFormData = {
isUpdate: true,
proId,
deviceCode,
deviceName,
}
} else {
this.editFormData = {}
}
//
onHandleViewDetail(data) {
this.selectProjectName = data.proName
this.proId = data.proId
this.dialogConfig.outerVisible = true
},
//
onHandleAddCardReplacementApply(type, data) {
this.dialogConfig.outerTitle = '选择补卡工程'
this.dialogConfig.outerWidth = '30%'
this.dialogConfig.minHeight = ''
this.dialogConfig.maxHeight = ''
this.dialogConfig.outerVisible = true
},
//
onHandleDeleteSubBaseInfo(data) {
this.$confirm('确定删除该考勤机吗?', '温馨提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
const res = await deleteAttendanceMachineAPI({
deviceCode: data.deviceCode,
})
if (res.code === 200) {
this.$modal.msgSuccess('删除成功')
this.$refs.attendanceMachineTableRef.getTableList() //
}
})
.catch(() => {
// console.log('')
})
},
//
onHandleConfirm() {
console.log('确定')
},
//
async onHandleConfirmFinish() {
try {
await this.$refs.addApplyFormRef.onHandleConfirmFinishFun()
this.handleCloseDialogOuter()
this.$refs.cardReplacementApplyTableRef.getTableList()
} catch (error) {
// console.log('', error)
}
},
//
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
//
onHandleNextStep() {
if (!this.selectProjectId) {
this.$modal.msgError('请选择补卡工程')
return
}
this.dialogConfig.outerTitle = '新增补卡申请'
this.dialogConfig.outerWidth = '80%'
this.dialogConfig.minHeight = '80vh'
this.dialogConfig.maxHeight = '80h'
this.dialogConfig.outerVisible = true
},
//
handleSelectProject() {
this.selectProjectName = this.lotProjectOptions.find(
(item) => item.value === this.selectProjectId,
).label
},
},
async created() {
const lot = await getLotProjectSelectListCommonFun()
this.lotProjectOptions = lot.map((item) => ({
this.formLabel[0].f_selList = lot.map((item) => ({
value: item.id,
label: item.proName,
}))

View File

@ -0,0 +1,146 @@
<template>
<!-- 施工人员 ---- 考勤管理 ---- 补卡审核-->
<div class="app-container">
<TableModel
:formLabel="formLabel"
:showOperation="true"
:showRightTools="true"
:columnsList="columnsList"
:sendParams="{ proId: proId }"
:request-api="getCardReplacementApplyListAPI"
>
<template slot="btn" slot-scope="{ queryParams }">
<el-button
plain
size="mini"
type="success"
icon="el-icon-download"
@click="onHandleExportCardReplacementAudit(queryParams)"
>
导出
</el-button>
</template>
<template slot="handle" slot-scope="{ data }">
<el-button
size="mini"
type="primary"
icon="el-icon-view"
@click="onHandleAuditAndDetail(data)"
>
详情
</el-button>
</template>
<template slot="checkStatus" slot-scope="{ data }">
<el-tag
size="mini"
type="warning"
v-if="data.checkStatus === 0"
>
待审核
</el-tag>
<el-tag
size="mini"
type="success"
v-if="data.checkStatus === 1"
>
通过
</el-tag>
<el-tag size="mini" type="danger" v-if="data.checkStatus === 2">
驳回
</el-tag>
</template>
</TableModel>
<DialogModel
:dialogConfig="dialogConfig"
@closeDialogOuter="handleCloseDialogOuter"
>
<template slot="outerContent"> </template>
</DialogModel>
</div>
</template>
<script>
import TableModel from '@/components/TableModel'
import DialogModel from '@/components/DialogModel'
import { dialogConfig } from './config'
import { getCardReplacementApplyListAPI } from '@/api/construction-person/attendance-manage/card-replacement-apply'
export default {
name: 'CardReplacementAudit',
components: {
TableModel,
DialogModel,
AuditForm,
},
props: {
proId: {
type: [String, Number],
default: '',
},
},
data() {
return {
formLabel: [
{
isShow: false, // label
f_type: 'ipt',
f_label: '姓名',
f_model: 'applyUser',
},
],
columnsList: [
{ t_props: 'proName', t_label: '工程名称' },
{ t_props: 'repairNum', t_label: '补卡人数' },
{ t_props: 'repairDay', t_label: '补卡天数' },
{ t_props: 'repairRemark', t_label: '补卡说明' },
{
t_label: '申请人',
t_props: 'applyUser',
},
{ t_label: '申请时间', t_props: 'applyTime' },
{
t_label: '审核状态',
t_slot: 'checkStatus',
},
{
t_label: '审核人',
t_props: 'checkUser',
},
{
t_label: '审核时间',
t_props: 'checkTime',
},
],
dialogConfig,
getCardReplacementApplyListAPI,
}
},
methods: {
//
onHandleExportCardReplacementAudit(queryParams) {
this.download(
'/bmw/cardApply/export',
{
...queryParams,
},
`补卡申请列表.xlsx`,
)
},
//
onHandleAuditAndDetail(data) {
this.dialogConfig.outerTitle = '补卡详情'
this.dialogConfig.outerVisible = true
},
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
},
}
</script>

View File

@ -1,349 +0,0 @@
<template>
<!-- 选择补卡人员及补卡日期页面 -->
<div style="width: 100%">
<el-form :model="queryPersonForm" :inline="true" size="mini">
<el-form-item prop="reason">
<el-select
style="width: 100%"
placeholder="请选择人员"
@change="onChangePerson"
v-model="queryPersonForm.selectPersonId"
>
<el-option
:key="item.value"
:label="item.label"
:value="item.value"
v-for="item in personOptions"
/>
</el-select>
</el-form-item>
<el-form-item prop="reason">
<el-date-picker
type="daterange"
style="width: 240px"
range-separator="至"
value-format="yyyy-MM-dd"
start-placeholder="开始日期"
end-placeholder="结束日期"
v-model="queryPersonForm.time"
/>
</el-form-item>
<el-form-item prop="reason">
<el-button
type="primary"
icon="el-icon-search"
@click="handleQuery"
>
查询
</el-button>
<el-button
plain
type="warning"
icon="el-icon-refresh"
@click="resetQuery"
>
重置
</el-button>
</el-form-item>
</el-form>
<div v-if="idNumber">
<span>
{{ name }}
</span>
<span> ({{ idNumber }}) </span>
</div>
<!-- 补卡日历 -->
<div class="date-ist" v-if="cardReplacementDateList.length > 0">
<div
:key="item.currentDate"
v-for="(item, index) in cardReplacementDateList"
style="
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
"
>
<span
style="
padding: 4px 0;
font-size: 16px;
font-weight: bold;
font-family: 'PingFang SC';
"
>
{{ item.month }}
</span>
<div
class="item"
:ref="`item${index}`"
:style="{
height: initHeight + 'px',
backgroundColor: item.inRange
? item.isActive == 1
? '#19be6b'
: '#f56c6c'
: '#999',
}"
:class="{
'item-active': item.isChecked,
}"
>
{{ item.date }}
<el-checkbox
class="check-box-item"
v-model="item.isChecked"
v-if="item.isActive == 0 && item.inRange"
/>
</div>
</div>
</div>
</div>
</template>
<script>
import {
getCardReplacementPersonListAPI,
getCardReplacementPersonCheckRecordAPI,
} from '@/api/construction-person/attendance-manage/card-replacement-apply'
export default {
name: 'SelectPersonAndDate',
props: {
selectProjectId: {
type: [Number, String],
default: () => '',
},
selectProjectName: {
type: String,
default: () => '',
},
editRow: {
type: Object,
default: () => {},
},
},
components: {
// AttendanceCalendar,
},
data() {
return {
queryPersonForm: {
selectPersonId: '',
time: [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
],
},
personOptions: [],
name: '',
idNumber: '',
workerId: '',
initHeight: 0,
//
dateList: [],
//
cardReplacementDateList: [],
//
editRepairDateList: [],
}
},
methods: {
handleCloseDialogOuter() {
this.dialogConfig.outerVisible = false
},
//
async getCardReplacementPersonList() {
const { data: res } = await getCardReplacementPersonListAPI({
proId: this.selectProjectId,
})
this.personOptions = res.map((item) => ({
...item,
value: item.id,
label: item.name,
}))
},
//
handleQuery() {
this.getCardReplacementPersonCheckRecord()
},
resetQuery() {
this.queryPersonForm.selectPersonId = ''
this.queryPersonForm.time = [
new Date().toISOString().split('T')[0],
new Date().toISOString().split('T')[0],
]
this.getCardReplacementPersonCheckRecord()
},
//
onPersonSubmit() {
const tempList = this.cardReplacementDateList.filter(
(item) => item.isChecked,
)
if (tempList.length > 0) {
const repairDate = tempList.map((item) => item.currentDate)
this.dateList[0].repairDate = repairDate.join(',')
this.dateList[0].repairDay = repairDate.length
this.$emit('onPersonSubmit', this.dateList)
}
},
//
async getCardReplacementPersonCheckRecord() {
// const workerId = this.personOptions.find(
// (item) => item.value === this.queryPersonForm.selectPersonId,
// ).id
const { data: res } = await getCardReplacementPersonCheckRecordAPI({
workerId: this.workerId,
proId: this.selectProjectId,
startTime: this.queryPersonForm.time[0],
endTime: this.queryPersonForm.time[1],
})
const tempList = []
if (Object.keys(res).length > 0) {
if (this.editRepairDateList.length > 0) {
for (const key in res) {
tempList.push({
month: key.split('-')[1],
date: key.split('-')[2],
inRange: res[key].inRange,
isActive: res[key].isActive,
currentDate: key,
isChecked: this.editRepairDateList.includes(key),
})
}
} else {
for (const key in res) {
tempList.push({
month: key.split('-')[1],
date: key.split('-')[2],
inRange: res[key].inRange,
isActive: res[key].isActive,
currentDate: key,
isChecked: false,
})
}
}
}
this.cardReplacementDateList = tempList.sort((a, b) => {
return a.date - b.date
})
this.$nextTick(() => {
this.getInitHeight()
})
},
//
onChangePerson(val) {
if (!val) {
this.dateList = []
return
}
const personInfo = this.personOptions.find(
(item) => item.value === val,
)
console.log(personInfo, 'personInfo')
const { name, idNumber, phone, teamName, id, teamId } = personInfo
this.workerId = id
this.dateList = []
this.dateList.push({
teamName, //
name, //
phone, //
idNumber, //
repairDay: '', //
repairDate: '', //
workerId: id, // id
teamId, // id
proName: this.selectProjectName, //
proId: this.selectProjectId, // id
})
},
getInitHeight() {
const item = this.$refs[`item0`][0]
if (item) {
this.initHeight = item.offsetWidth
}
},
},
created() {
this.getCardReplacementPersonList()
},
watch: {
editRow: {
handler(newVal) {
if (Object.keys(newVal).length > 0) {
const { workerId, idNumber, name, repairDate } = newVal
this.queryPersonForm.selectPersonId = workerId
this.workerId = workerId
this.idNumber = idNumber
this.name = name
const repairDateList = repairDate.split(',')
this.editRepairDateList = repairDateList
this.queryPersonForm.time = [
repairDateList[0],
repairDateList[repairDateList.length - 1],
]
this.getCardReplacementPersonCheckRecord()
}
},
deep: true,
immediate: true,
},
},
}
</script>
<style scoped lang="scss">
.date-ist {
width: 80%;
margin: 0 auto;
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 10px;
.item {
width: 100%;
position: relative;
padding: 10px;
display: flex;
border-radius: 5px;
align-items: center;
border-radius: 6px;
justify-content: center;
color: #fff;
font-size: 18px;
.check-box-item {
position: absolute;
right: 6px;
top: 6px;
}
}
.item-active {
background-color: #b58bae !important;
}
}
</style>