1236 lines
42 KiB
Vue
1236 lines
42 KiB
Vue
<template>
|
||
<div class="fullHeight whiteBlock">
|
||
<div class="searchBox whiteBlock">
|
||
<el-button
|
||
v-permission="{ key: 'add', menuPath: '/project/labor/newAttendanceRules' }"
|
||
size="medium"
|
||
type="primary"
|
||
@click="addBefore(1)"
|
||
>{{ $t("message.workType.add") }}</el-button
|
||
>
|
||
<div class="operate-clear">
|
||
<el-button
|
||
size="medium"
|
||
type="primary"
|
||
plain
|
||
@click="operateClear"
|
||
style="margin-right: 5px"
|
||
v-permission="{ key: 'zeroing2', menuPath: '/project/labor/newAttendanceRules' }"
|
||
>手动清零</el-button
|
||
>
|
||
<el-popover
|
||
placement="bottom-start"
|
||
width="350"
|
||
:visible-arrow="false"
|
||
trigger="hover"
|
||
content="有设备断电或者服务器关机的情况下,系统无法自动清零历史未出场人员记录时,可以点击手动清零进行清除。"
|
||
>
|
||
<div slot="reference" class="question-icon">?</div>
|
||
</el-popover>
|
||
</div>
|
||
<div
|
||
class="search-box"
|
||
v-permission="{ key: 'zeroing', menuPath: '/project/labor/newAttendanceRules' }"
|
||
>
|
||
<div>
|
||
<span>是否清零</span>
|
||
<el-popover
|
||
placement="bottom-start"
|
||
width="365"
|
||
:visible-arrow="false"
|
||
trigger="hover"
|
||
content="选择零点清零(是)之后,每晚00:00:00点自动清零历史未出场的人员记录,只统计今日出勒和今日在场人员;选择零点清零(否)之后,人员出勤和人员在场将会统计所有历史未出场人员记录以及今日出勤人员和今日在场人员记录。"
|
||
>
|
||
<div slot="reference" class="question-icon">?</div>
|
||
</el-popover>
|
||
</div>
|
||
<el-radio-group v-model="radioVal" @change="changeSelect">
|
||
<el-radio :label="1">是</el-radio>
|
||
<el-radio :label="0">否</el-radio>
|
||
</el-radio-group>
|
||
</div>
|
||
<div class="search-box">
|
||
<div>
|
||
<span>是否启用APP打卡</span>
|
||
<el-popover
|
||
placement="bottom-start"
|
||
width="365"
|
||
:visible-arrow="false"
|
||
trigger="hover"
|
||
content="启用APP打卡后,管理人员和劳务人员的可以通过APP上传考勤记录。关闭APP打卡后,管理人员和劳务人员从APP端上传考勤点击打卡按钮提示“APP考勤已关闭,请联系管理员”。"
|
||
>
|
||
<div slot="reference" class="question-icon">?</div>
|
||
</el-popover>
|
||
</div>
|
||
<el-radio-group v-model="isMobileAttendance" @change="changeConfig">
|
||
<el-radio :label="1">是</el-radio>
|
||
<el-radio :label="0">否</el-radio>
|
||
</el-radio-group>
|
||
</div>
|
||
</div>
|
||
<div class="table_wrap whiteBlock">
|
||
<el-table class="tables" :data="workerList">
|
||
<el-table-column
|
||
align="center"
|
||
prop="planName"
|
||
label="考勤计划名称"
|
||
></el-table-column>
|
||
<el-table-column
|
||
align="center"
|
||
prop="hourType"
|
||
label="工时计算方式"
|
||
>
|
||
<template slot-scope="scope">
|
||
{{ scope.row.hourType == 1 ? "末减初" : scope.row.hourType == 2 ? "时间段累加" : "--" }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
align="center"
|
||
prop="dayType"
|
||
label="工日计算方式"
|
||
>
|
||
<template slot-scope="scope">
|
||
{{ scope.row.dayType == 1 ? "一天一打卡" : scope.row.dayType == 2 ? "一天两打卡" : scope.row.dayType == 3 ? "工时段换算工日" : scope.row.dayType == 4 ? "比例换算工日" : "--" }}
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
align="center"
|
||
prop="isOpenOvertime"
|
||
label="加班是否开启"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span class="open" v-if="scope.row.isOpenOvertime == 1">
|
||
已开启
|
||
</span>
|
||
<span class="notopen" v-else>未开启</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column align="center" label="操作">
|
||
<div slot class="operate" slot-scope="scope">
|
||
<div class="tableBtns">
|
||
<el-button v-permission="{
|
||
key: 'examine',
|
||
menuPath: '/project/labor/newAttendanceRules',
|
||
}" @click="editBefore(3,scope.row)" class="operationText" type="text" icon="el-icon-view"
|
||
>查看</el-button
|
||
>
|
||
<div
|
||
v-permission="{
|
||
key: 'edit',
|
||
menuPath: '/project/labor/newAttendanceRules',
|
||
}"
|
||
@click="editBefore(2, scope.row)"
|
||
class="operationText"
|
||
>
|
||
<img src="@/assets/images/icon-edit.png" width="15px" height="15px" />
|
||
<span>{{ $t("message.workType.edit") }}</span>
|
||
</div>
|
||
<div
|
||
v-permission="{
|
||
key: 'delete',
|
||
menuPath: '/project/labor/newAttendanceRules',
|
||
}"
|
||
@click="deleteWorker(scope.row)"
|
||
class="operationText"
|
||
>
|
||
<img src="@/assets/images/icon-delete.png" width="15px" height="15px" />
|
||
<span>{{ $t("message.workType.delete") }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</el-table-column>
|
||
</el-table>
|
||
<el-pagination
|
||
class="pagerBox"
|
||
@size-change="handleSizeChange"
|
||
@current-change="handleCurrentChange"
|
||
:current-page="pageInfo.pageNo"
|
||
:page-sizes="$store.state.PAGESIZRS"
|
||
:page-size="pageInfo.pageSize"
|
||
layout="total, sizes, prev, pager, next"
|
||
:total="Number(pageInfo.total)"
|
||
background
|
||
></el-pagination>
|
||
</div>
|
||
<!--:title="type==='add'?'新增考勤规则':type==='edit'?'编辑考勤规则':type==='delete'?'删除考勤规则':''"-->
|
||
<el-dialog
|
||
:modal-append-to-body="false"
|
||
:title="title"
|
||
:visible.sync="dialogVisible"
|
||
width="1697px"
|
||
>
|
||
<div class="dialog_content">
|
||
<el-form
|
||
:rules="rules"
|
||
:model="workerInfo"
|
||
ref="form"
|
||
label-width="140px"
|
||
size="medium"
|
||
:inline="true"
|
||
class="dialogFormBox"
|
||
:disabled="batchSettingType == 3"
|
||
>
|
||
<el-form-item prop="planName" label="考勤计划名称">
|
||
<el-input
|
||
v-model="workerInfo.planName"
|
||
:placeholder="$t('message.workType.placeholder')"
|
||
></el-input>
|
||
</el-form-item>
|
||
<el-form-item label="应用考勤组">
|
||
<el-select v-model="workerInfo.groupV2Id">
|
||
<el-option v-for="item in workerAttendanceGroupList" :key="item.id" :value="item.id" :label="item.groupName"></el-option>
|
||
</el-select>
|
||
</el-form-item>
|
||
<div class="rules-box">
|
||
<div class="box-header">工时计算方式<span>(不选择则不计算工时)</span></div>
|
||
<div class="box-contaniner">
|
||
<div>
|
||
<el-radio v-model="workerInfo.hourType" :label="1">末减初</el-radio>
|
||
<div class="box-content">
|
||
<div>
|
||
使用一天内末次打卡时间-首次打卡时间计算当日出勤工时(打卡不区分进场还是出场)
|
||
</div>
|
||
<p>
|
||
例如:张三当天第一条打卡记录为9:00,最后一次打卡记录为18:00,则张三今日工时为9个小时算法:9=18-9
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<el-radio v-model="workerInfo.hourType" :label="2"
|
||
>时间段累加</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>按在场/出场时间段累加计算当日出勒工时</div>
|
||
<p>
|
||
例如:张三早上9:00进场打卡,中午12点出场打卡,下午14:00进场打卡,晚上19:00出场打卡。此工人今日工时为8小时
|
||
</p>
|
||
<p>算法:9=(12-9)+(19-14)</p>
|
||
<el-radio-group v-model="workerInfo.hourOvernightType">
|
||
<el-radio :label="1">
|
||
跨夜工时按零点结算到前后两天
|
||
<el-popover
|
||
placement="bottom-start"
|
||
width="350"
|
||
:visible-arrow="false"
|
||
trigger="hover"
|
||
content="跨夜工时按零点结算到前后两天:当天最后一次打卡记录为“进场”,第天第一条打卡记录为“出场”,则00:00自动补充一条虚拟的进场、出场记录,两天都会有工时计算。"
|
||
>
|
||
<div slot="reference" class="question-icon">?</div>
|
||
</el-popover>
|
||
</el-radio>
|
||
<el-radio :label="2">
|
||
跨夜工时结算到前一天
|
||
<el-popover
|
||
placement="bottom-start"
|
||
width="350"
|
||
:visible-arrow="false"
|
||
trigger="hover"
|
||
content="跨夜工时结算到前一天:当天最后一次打卡记录为“进场”,第二天第一条打卡记录为“出场”,则将第二天第一条的出场记录,纳入到前一天,结算工时。"
|
||
>
|
||
<div slot="reference" class="question-icon">?</div>
|
||
</el-popover>
|
||
</el-radio>
|
||
<el-radio :label="3">
|
||
不做跨夜结算
|
||
<el-popover
|
||
placement="bottom-start"
|
||
width="350"
|
||
:visible-arrow="false"
|
||
trigger="hover"
|
||
content="不做跨夜结算:当天针对有跨夜进出场的情况,不做任何处理,严格按照当天进出场配对的方式进行计算工时。"
|
||
>
|
||
<div slot="reference" class="question-icon">?</div>
|
||
</el-popover>
|
||
</el-radio>
|
||
</el-radio-group>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="rules-box">
|
||
<div class="box-header">工日计算方式<span>(不选择则不计算工日)</span></div>
|
||
<div class="box-contaniner">
|
||
<div>
|
||
<el-radio v-model="workerInfo.dayType" :label="1"
|
||
>一天已打卡</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>一天只要有一次打卡记录即算出勤1工日,没有则算0工日</div>
|
||
<p>注:此处的打卡不区分进出场</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<el-radio v-model="workerInfo.dayType" :label="2"
|
||
>一天两打卡</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>
|
||
一天上午、下午有两次打卡记录计算出勤1工日,只有上午或下午打卡记录则算0.5工日,没有则是0工日
|
||
</div>
|
||
<p>注:此处的打卡不区分进出场</p>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<el-radio v-model="workerInfo.dayType" :label="3"
|
||
>工时段换算工日</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>根据不同工时段换算工日</div>
|
||
<p>例:可设置0~~6工时(包含6工时)算0.5工日:6~~24工时算1工日</p>
|
||
<div class="progress-time">
|
||
<div @click="onClickPitch(index, 1)" v-for="(item, index) in 25">
|
||
<div v-if="activePitchUp(hour2dayList, index)" class="progress-active">{{ index }}</div>
|
||
<div class="progress-bj"></div>
|
||
<div class="progress-wz">{{ index }}</div>
|
||
</div>
|
||
</div>
|
||
<div class="rulebox" v-for="(item, index) in workerInfo.hour2dayJson">
|
||
<div>规则</div>
|
||
<el-input-number
|
||
:disabled="index == 0"
|
||
v-model="item.hourMin"
|
||
controls-position="right"
|
||
@change="onHour2dayChange"
|
||
:min="0"
|
||
:max="item.hourMax ? item.hourMax : 24"
|
||
></el-input-number>
|
||
<p>工时至</p>
|
||
<el-input-number
|
||
:disabled="index == workerInfo.hour2dayJson.length - 1"
|
||
v-model="item.hourMax"
|
||
controls-position="right"
|
||
@change="onHour2dayChange"
|
||
:min="item.hourMin ? item.hourMin : 0"
|
||
:max="24"
|
||
></el-input-number>
|
||
<p>工时等于</p>
|
||
<el-input-number
|
||
v-model="item.day"
|
||
controls-position="right"
|
||
:min="0"
|
||
></el-input-number>
|
||
<p>工日</p>
|
||
<i v-if="index != 0" @click="onDeletePitch(index, 1)" class="el-icon-error"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<el-radio v-model="workerInfo.dayType" :label="4"
|
||
>比例换算工日</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>根据工时比例计算工日,结果最多保留两位小数</div>
|
||
<p>
|
||
例:设置规则:13工时=1工日,实际工时为24工时,那工日计算则为24/13=1.85,1.85工日
|
||
</p>
|
||
<div class="rulebox">
|
||
<el-input-number
|
||
v-model="workerInfo.ratio2dayHour"
|
||
controls-position="right"
|
||
:min="0"
|
||
:max="24"
|
||
></el-input-number>
|
||
<p>工时等于</p>
|
||
<el-input-number
|
||
v-model="workerInfo.ratio2dayDay"
|
||
controls-position="right"
|
||
:min="0"
|
||
></el-input-number>
|
||
<p>工日</p>
|
||
</div>
|
||
<div class="checkbox">
|
||
<el-checkbox v-model="workerInfo.ratio2dayLess1">
|
||
计算后工日不能超过1
|
||
<span
|
||
>勾选后工时超出比例值,工日为1,如13工时=1工日,实际工时为34,那工日为1</span
|
||
>
|
||
</el-checkbox>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="switch-box">
|
||
<div>是否开启加班</div>
|
||
<el-switch v-model="workerInfo.isOpenOvertime"> </el-switch>
|
||
<div>{{workerInfo.isOpenOvertime ? '是': '否'}}</div>
|
||
</div>
|
||
<template v-if="workerInfo.isOpenOvertime">
|
||
<div class="rules-box">
|
||
<div class="box-header">加班工时计算方法</span></div>
|
||
<div class="box-contaniner">
|
||
<div>
|
||
<el-radio v-model="workerInfo.overtimeHourType" :label="1">超出规定工作时间的工时</el-radio>
|
||
<div class="box-content">
|
||
<div>
|
||
公司考勤制度规定每日工时为8小时,则超出8小时的工时算加班工时
|
||
</div>
|
||
<div class="rulebox">
|
||
<div>设置每日规定工时:</div>
|
||
<el-input-number
|
||
v-model="workerInfo.dailyHour"
|
||
controls-position="right"
|
||
:min="0"
|
||
:max="24"
|
||
></el-input-number>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<el-radio v-model="workerInfo.overtimeHourType" :label="2"
|
||
>特定时间内的工时</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>在设置的特点时间段内工作,算加班工时</div>
|
||
<div class="timing">
|
||
<div>设置特定时间范围:</div>
|
||
<el-time-picker
|
||
value-format="HH:mm"
|
||
v-model="workerInfo.overtimeHourStart"
|
||
placeholder="时间点">
|
||
</el-time-picker>
|
||
<p>-</p>
|
||
<el-time-picker
|
||
value-format="HH:mm"
|
||
v-model="workerInfo.overtimeHourEnd"
|
||
placeholder="时间点">
|
||
</el-time-picker>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="rules-box">
|
||
<div class="box-header">工时段换算工日</div>
|
||
<div class="box-contaniner">
|
||
<div>
|
||
<el-radio v-model="workerInfo.overtimeDayType" :label="1"
|
||
>工时段换算工日</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>根据不同工时段换算工日</div>
|
||
<p>例:可设置0~~6工时(包含6工时)算0.5工日:6~~24工时算1工日</p>
|
||
<div class="progress-time">
|
||
<div @click="onClickPitch(index, 2)" v-for="(item, index) in 25">
|
||
<div v-if="activePitchUp(overtimeHour2dayList, index)" class="progress-active">{{ index }}</div>
|
||
<div class="progress-bj"></div>
|
||
<div class="progress-wz">{{ index }}</div>
|
||
</div>
|
||
</div>
|
||
<div class="rulebox" v-for="(item, index) in workerInfo.overtimeHour2dayJson">
|
||
<div>规则</div>
|
||
<el-input-number
|
||
:disabled="index == 0"
|
||
v-model="item.hourMin"
|
||
controls-position="right"
|
||
:min="0"
|
||
@change="onOvertimeHour2dayChange"
|
||
:max="item.hourMax ? item.hourMax : 24"
|
||
></el-input-number>
|
||
<p>工时至</p>
|
||
<el-input-number
|
||
:disabled="index == workerInfo.overtimeHour2dayJson.length - 1"
|
||
v-model="item.hourMax"
|
||
@change="onOvertimeHour2dayChange"
|
||
controls-position="right"
|
||
:min="item.hourMin ? item.hourMin : 0"
|
||
:max="24"
|
||
></el-input-number>
|
||
<p>工时等于</p>
|
||
<el-input-number
|
||
v-model="item.day"
|
||
controls-position="right"
|
||
:min="0"
|
||
></el-input-number>
|
||
<p>工日</p>
|
||
<i v-if="index != 0" @click="onDeletePitch(index, 2)" class="el-icon-error"></i>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<el-radio v-model="workerInfo.overtimeDayType" :label="2"
|
||
>比例换算工日</el-radio
|
||
>
|
||
<div class="box-content">
|
||
<div>根据工时比例计算工日,结果最多保留两位小数</div>
|
||
<p>
|
||
例:设置规则:13工时=1工日,实际工时为24工时,那工日计算则为24/13=1.85,1.85工日
|
||
</p>
|
||
<div class="rulebox">
|
||
<el-input-number
|
||
v-model="workerInfo.overtimeRatio2dayHour"
|
||
controls-position="right"
|
||
:min="0"
|
||
:max="24"
|
||
></el-input-number>
|
||
<p>工时等于</p>
|
||
<el-input-number
|
||
v-model="workerInfo.overtimeRatio2dayDay"
|
||
controls-position="right"
|
||
:min="0"
|
||
></el-input-number>
|
||
<p>工日</p>
|
||
</div>
|
||
<div class="checkbox">
|
||
<el-checkbox v-model="workerInfo.overtimeRatio2dayLess1">
|
||
计算后工日不能超过1
|
||
<span
|
||
>勾选后工时超出比例值,工日为1,如13工时=1工日,实际工时为34,那工日为1</span
|
||
>
|
||
</el-checkbox>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
<div class="dialog-footer" v-if="batchSettingType != 3">
|
||
<el-button
|
||
class="cancleBtn"
|
||
@click="closeBtn"
|
||
icon="el-icon-circle-close"
|
||
size="medium"
|
||
>{{ $t("message.personnelPosition.cancel") }}
|
||
</el-button>
|
||
<el-button
|
||
type="primary"
|
||
icon="el-icon-circle-check"
|
||
@click="Submit"
|
||
size="medium"
|
||
>{{ $t("message.personnelPosition.determine") }}
|
||
</el-button>
|
||
</div>
|
||
</el-form>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import {
|
||
getWorkerAttendanceRuleV2PageApi,
|
||
addWorkerAttendanceRuleV2Api,
|
||
editWorkerAttendanceRuleV2Api,
|
||
deleteWorkerAttendanceRuleV2Api,
|
||
getWorkerAttendanceGroupV2ListApi
|
||
} from "@/assets/js/api/laborPerson";
|
||
|
||
import {
|
||
getProjectDetail,
|
||
editProjectInfo,
|
||
editClearData,
|
||
} from "@/assets/js/api/baseInfo";
|
||
import {
|
||
getProjectConfigListApi,
|
||
editProjectConfigListApi,
|
||
} from "@/assets/js/api/project.js";
|
||
import { isJSON } from '@/util/nowDate';
|
||
import dayjs from "dayjs";
|
||
export default {
|
||
data() {
|
||
return {
|
||
radioVal: 0,
|
||
isMobileAttendance: 0,
|
||
title: "新增考勤计划",
|
||
dialogVisible: false,
|
||
workerList: [],
|
||
workerInfo: {
|
||
ruleName: "",
|
||
isRest: "",
|
||
startTime: "",
|
||
endTime: "",
|
||
notLater: "",
|
||
yesLater: "",
|
||
notAdvance: "",
|
||
yesAdvance: "",
|
||
yesOrNotOvertime: "",
|
||
onceAttendance: undefined,
|
||
},
|
||
tempWorkerInfo: {
|
||
notLater: "",
|
||
yesLater: "",
|
||
notAdvance: "",
|
||
yesAdvance: "",
|
||
},
|
||
rules: {
|
||
planName: [
|
||
{
|
||
required: true,
|
||
message: this.$t("message.workType.placeholder"),
|
||
trigger: "change",
|
||
},
|
||
],
|
||
startTime: [
|
||
{
|
||
required: true,
|
||
message: this.$t("message.workType.placeholder_select"),
|
||
trigger: "change",
|
||
},
|
||
],
|
||
endTime: [
|
||
{
|
||
required: true,
|
||
message: this.$t("message.workType.placeholder_select"),
|
||
trigger: "change",
|
||
},
|
||
],
|
||
},
|
||
pageInfo: {
|
||
total: 0,
|
||
pageNo: 1,
|
||
pageSize: 10,
|
||
},
|
||
workerAttendanceGroupList: [],
|
||
batchSettingType: "",
|
||
hour2dayList: [0, 24],
|
||
overtimeHour2dayList: [0, 24],
|
||
};
|
||
},
|
||
mounted() {
|
||
this.getProjectConfigList();
|
||
this.getWorker();
|
||
this.getProjectDetailFn();
|
||
},
|
||
methods: {
|
||
onHour2dayChange(currentValue, oldValue) {
|
||
const findIndex = this.hour2dayList.findIndex(item => item == oldValue);
|
||
if(findIndex != -1) {
|
||
this.hour2dayList.splice(findIndex, 1, currentValue);
|
||
this.generateHour2dayJson();
|
||
}
|
||
},
|
||
onOvertimeHour2dayChange(currentValue, oldValue) {
|
||
const findIndex = this.overtimeHour2dayList.findIndex(item => item == oldValue);
|
||
if(findIndex != -1) {
|
||
this.overtimeHour2dayList.splice(findIndex, 1, currentValue);
|
||
this.generateOvertimeHour2dayJson();
|
||
}
|
||
},
|
||
onClickPitch(item, type) {
|
||
if(type == 1) {
|
||
this.hour2dayList.push(item);
|
||
this.generateHour2dayJson();
|
||
} else if(type == 2) {
|
||
this.overtimeHour2dayList.push(item);
|
||
this.generateOvertimeHour2dayJson();
|
||
}
|
||
|
||
},
|
||
onDeletePitch(eIndex, type) {
|
||
if(type == 1) {
|
||
const findIndex = this.hour2dayList.findIndex(item => item == this.workerInfo.hour2dayJson[eIndex].hourMin);
|
||
if(findIndex != -1) {
|
||
this.hour2dayList.splice(findIndex, 1);
|
||
this.generateHour2dayJson();
|
||
}
|
||
} else if (type == 2) {
|
||
const findIndex = this.overtimeHour2dayList.findIndex(item => item == this.workerInfo.overtimeHour2dayJson[eIndex].hourMin);
|
||
if(findIndex != -1) {
|
||
this.overtimeHour2dayList.splice(findIndex, 1);
|
||
this.generateOvertimeHour2dayJson();
|
||
}
|
||
}
|
||
},
|
||
generateHour2dayJson() {
|
||
const resultSortList = this.hour2dayList.sort((a,b) => a - b);
|
||
const oldSelectionList = this.workerInfo.hour2dayJson;
|
||
this.workerInfo.hour2dayJson = [];
|
||
resultSortList.forEach((ele, index) => {
|
||
if(index == 0) return;
|
||
this.workerInfo.hour2dayJson.push({
|
||
hourMin: resultSortList[index-1],
|
||
hourMax: ele,
|
||
day: oldSelectionList[index-1] ? oldSelectionList[index-1].day : 0,
|
||
})
|
||
})
|
||
},
|
||
generateOvertimeHour2dayJson() {
|
||
const resultSortList = this.overtimeHour2dayList.sort((a,b) => a - b);
|
||
const oldSelectionList = this.workerInfo.overtimeHour2dayJson;
|
||
this.workerInfo.overtimeHour2dayJson = [];
|
||
resultSortList.forEach((ele, index) => {
|
||
if(index == 0) return;
|
||
this.workerInfo.overtimeHour2dayJson.push({
|
||
hourMin: resultSortList[index-1],
|
||
hourMax: ele,
|
||
day: oldSelectionList[index-1] ? oldSelectionList[index-1].day : 0,
|
||
})
|
||
})
|
||
},
|
||
getWorkerAttendanceGroupV2List() {
|
||
getWorkerAttendanceGroupV2ListApi({
|
||
projectSn: this.$store.state.projectSn,
|
||
ruleIdIsNullOrRuleId: this.workerInfo.id ? this.workerInfo.id : 1,
|
||
}).then((res) => {
|
||
if(res.code == 200) {
|
||
this.workerAttendanceGroupList = res.result;
|
||
}
|
||
})
|
||
},
|
||
//查看条数
|
||
handleSizeChange(val) {
|
||
this.pageInfo.pageSize = val;
|
||
this.getDataList();
|
||
},
|
||
//查看页
|
||
handleCurrentChange(val) {
|
||
this.pageInfo.pageNo = val;
|
||
this.getDataList();
|
||
},
|
||
async getProjectConfigList() {
|
||
const res = await getProjectConfigListApi({
|
||
projectSn: this.$store.state.projectSn,
|
||
});
|
||
if (res.success) {
|
||
this.isMobileAttendance = res.result[0].isMobileAttendance || 0;
|
||
}
|
||
},
|
||
async changeConfig() {
|
||
const res = await editProjectConfigListApi({
|
||
projectSn: this.$store.state.projectSn,
|
||
isMobileAttendance: this.isMobileAttendance,
|
||
});
|
||
if (res.success) {
|
||
this.$message.success("操作成功");
|
||
}
|
||
},
|
||
// 手动清零
|
||
operateClear() {
|
||
// promptToDelete此操作将永久删除该数据 tips提示 determine确 定 cancel取 消
|
||
this.$confirm("此操作将清零,请确认是否继续?", this.$t("message.lifter.tips"), {
|
||
confirmButtonText: this.$t("message.lifter.determine"),
|
||
cancelButtonText: this.$t("message.lifter.cancel"),
|
||
type: "warning",
|
||
})
|
||
.then(() => {
|
||
let data = {
|
||
projectSn: this.$store.state.projectSn,
|
||
};
|
||
editClearData(data).then((res) => {
|
||
if (res.success) {
|
||
this.$message.success("操作成功");
|
||
}
|
||
});
|
||
})
|
||
.catch(() => {
|
||
this.$message({
|
||
type: "info",
|
||
message: "已取消",
|
||
});
|
||
});
|
||
},
|
||
// 切换清零配置
|
||
changeSelect() {
|
||
let reqeustData = {
|
||
projectSn: this.$store.state.projectSn,
|
||
enableWorkerAttendanceZero: this.radioVal,
|
||
};
|
||
editProjectInfo(reqeustData).then((res) => {
|
||
if (res.success) {
|
||
this.$message.success("操作成功");
|
||
}
|
||
});
|
||
},
|
||
// 查询是否清零配置
|
||
getProjectDetailFn() {
|
||
let reqeustData = {
|
||
projectSn: this.$store.state.projectSn,
|
||
};
|
||
getProjectDetail(reqeustData).then((res) => {
|
||
if (res && res.result) {
|
||
this.radioVal = res.result.enableWorkerAttendanceZero;
|
||
}
|
||
});
|
||
},
|
||
getWorker() {
|
||
getWorkerAttendanceRuleV2PageApi({
|
||
projectSn: this.$store.state.projectSn,
|
||
pageNo: this.pageInfo.pageNo,
|
||
pageSize: this.pageInfo.pageSize,
|
||
}).then(
|
||
(result) => {
|
||
if (result.success) {
|
||
console.log("考勤列表", result);
|
||
this.workerList = result.result.records;
|
||
this.pageInfo.total = result.result.total;
|
||
}
|
||
}
|
||
);
|
||
},
|
||
initWorkerInfo() {
|
||
this.workerInfo = {
|
||
planName: "",
|
||
groupV2Id: "",
|
||
hourType: "",
|
||
hourOvernightType: "",
|
||
dayType: "",
|
||
hour2dayStart: "",
|
||
hour2dayEnd: "",
|
||
hour2dayDay: "",
|
||
hour2dayJson: [{
|
||
hourMin: 0,
|
||
hourMax: 24,
|
||
day: 0,
|
||
}],
|
||
ratio2dayHour: "",
|
||
ratio2dayDay: "",
|
||
overtimeHour2dayJson: [{
|
||
hourMin: 0,
|
||
hourMax: 24,
|
||
day: 0,
|
||
}],
|
||
ratio2dayLess1: "",
|
||
isOpenOvertime: false,
|
||
overtimeHourType: "",
|
||
dailyHour: "",
|
||
overtimeHourStart: "",
|
||
overtimeHourEnd: "",
|
||
overtimeDayType: "",
|
||
overtimeHour2dayStart: "",
|
||
overtimeHour2dayEnd: "",
|
||
overtimeRatio2dayHour: "",
|
||
overtimeRatio2dayDay: "",
|
||
}
|
||
this.hour2dayList = [0, 24];
|
||
this.overtimeHour2dayList= [0, 24];
|
||
},
|
||
addBefore(type) {
|
||
this.batchSettingType = type;
|
||
this.title = "新增考勤规则";
|
||
this.dialogVisible = true;
|
||
this.initWorkerInfo();
|
||
this.tempWorkerInfo = {
|
||
notLater: "",
|
||
yesLater: "",
|
||
notAdvance: "",
|
||
yesAdvance: "",
|
||
};
|
||
this.getWorkerAttendanceGroupV2List();
|
||
this.$nextTick(() => {
|
||
this.$refs.form.clearValidate();
|
||
});
|
||
},
|
||
editBefore(type,worker) {
|
||
this.batchSettingType = type;
|
||
this.title = "编辑考勤规则";
|
||
this.dialogVisible = true;
|
||
this.tempWorkerInfo = {
|
||
notLater: "",
|
||
yesLater: "",
|
||
notAdvance: "",
|
||
yesAdvance: "",
|
||
};
|
||
|
||
this.$nextTick(() => {
|
||
this.$refs.form.clearValidate();
|
||
});
|
||
// console.log('编辑前的内容', worker)
|
||
this.workerInfo = JSON.parse(JSON.stringify({
|
||
...worker,
|
||
overtimeHourStart: worker.overtimeHourStart ? dayjs(worker.overtimeHourStart).format('HH:mm') : "",
|
||
overtimeHourEnd: worker.overtimeHourStart ? dayjs(worker.overtimeHourEnd).format('HH:mm') : "",
|
||
isOpenOvertime: worker.isOpenOvertime == 1 ? true : false,
|
||
ratio2dayLess1: worker.ratio2dayLess1 == 1 ? true : false,
|
||
overtimeRatio2dayLess1: worker.overtimeRatio2dayLess1 == 1 ? true : false,
|
||
hour2dayJson: isJSON(worker.hour2dayJson) && worker.hour2dayJson ? JSON.parse(worker.hour2dayJson) : [{
|
||
hourMin: 0,
|
||
hourMax: 24,
|
||
day: 0,
|
||
}],
|
||
overtimeHour2dayJson: isJSON(worker.overtimeHour2dayJson) && worker.overtimeHour2dayJson ? JSON.parse(worker.overtimeHour2dayJson) : [{
|
||
hourMin: 0,
|
||
hourMax: 24,
|
||
day: 0,
|
||
}],
|
||
}));
|
||
if(this.workerInfo.hour2dayJson.length > 2) {
|
||
this.workerInfo.hour2dayJson.forEach(item => {
|
||
if(!this.hour2dayList.includes(item.hourMin)) {
|
||
this.hour2dayList.push(item.hourMin)
|
||
}
|
||
if(!this.hour2dayList.includes(item.hourMax)) {
|
||
this.hour2dayList.push(item.hourMax)
|
||
}
|
||
})
|
||
} else {
|
||
this.hour2dayList = [0, 24];
|
||
}
|
||
if(this.workerInfo.overtimeHour2dayJson.length > 2) {
|
||
this.workerInfo.overtimeHour2dayJson.forEach(item => {
|
||
if(!this.overtimeHour2dayList.includes(item.hourMin)) {
|
||
this.overtimeHour2dayList.push(item.hourMin)
|
||
}
|
||
if(!this.overtimeHour2dayList.includes(item.hourMax)) {
|
||
this.overtimeHour2dayList.push(item.hourMax)
|
||
}
|
||
})
|
||
}else {
|
||
this.overtimeHour2dayList= [0, 24];
|
||
}
|
||
|
||
this.getWorkerAttendanceGroupV2List();
|
||
},
|
||
deleteBefore(worker) {},
|
||
deleteWorker(worker) {
|
||
this.$confirm(
|
||
this.$t("message.personnelPosition.beaconManage.table.confirmText") +
|
||
"【" +
|
||
worker.planName +
|
||
"】?",
|
||
this.$t("message.personnelPosition.beaconManage.table.Tips"),
|
||
{
|
||
confirmButtonText: this.$t("message.personnelPosition.confirmButtonText"),
|
||
cancelButtonText: this.$t("message.personnelPosition.cancelButtonText"),
|
||
type: "warning",
|
||
}
|
||
)
|
||
.then(() => {
|
||
deleteWorkerAttendanceRuleV2Api({ id: worker.id }).then((result) => {
|
||
if (result.success) {
|
||
console.log("删除成功", result);
|
||
this.getWorker();
|
||
this.dialogVisible = false;
|
||
this.$message.success(result.message);
|
||
}
|
||
});
|
||
this.getWorker();
|
||
})
|
||
.catch(() => {});
|
||
},
|
||
closeBtn() {
|
||
this.dialogVisible = false;
|
||
this.workerInfo = {};
|
||
},
|
||
Submit() {
|
||
this.$refs.form.validate((valid) => {
|
||
if (valid) {
|
||
const defaultTime = dayjs().format('YYYY-MM-DD');
|
||
const params = {
|
||
...this.workerInfo,
|
||
projectSn : this.$store.state.projectSn,
|
||
overtimeHourStart: this.workerInfo.overtimeHourStart ? dayjs(defaultTime + this.workerInfo.overtimeHourStart + ':00').format('YYYY-MM-DD HH:mm:ss') : "",
|
||
overtimeHourEnd: this.workerInfo.overtimeHourEnd ? dayjs(defaultTime + this.workerInfo.overtimeHourEnd + ':00').format('YYYY-MM-DD HH:mm:ss') : "",
|
||
hour2dayJson: JSON.stringify(this.workerInfo.hour2dayJson),
|
||
overtimeHour2dayJson: JSON.stringify(this.workerInfo.overtimeHour2dayJson),
|
||
isOpenOvertime: this.workerInfo.isOpenOvertime ? 1 : 0,
|
||
ratio2dayLess1: this.workerInfo.ratio2dayLess1 ? 1 : 0,
|
||
overtimeRatio2dayLess1: this.workerInfo.overtimeRatio2dayLess1 ? 1 : 0,
|
||
}
|
||
if (this.title === "新增考勤规则") {
|
||
addWorkerAttendanceRuleV2Api(params).then((result) => {
|
||
this.$message.success(result.message);
|
||
this.initWorkerInfo();
|
||
this.dialogVisible = false;
|
||
this.getWorker();
|
||
});
|
||
} else if (this.title === "编辑考勤规则") {
|
||
editWorkerAttendanceRuleV2Api(params).then((result) => {
|
||
if (result.success) {
|
||
this.getWorker();
|
||
this.initWorkerInfo();
|
||
this.dialogVisible = false;
|
||
this.$message.success(result.message);
|
||
}
|
||
});
|
||
}
|
||
} else {
|
||
console.log("用户注册信息未全部完成填写", valid);
|
||
return false;
|
||
}
|
||
});
|
||
},
|
||
},
|
||
computed: {
|
||
activePitchUp() {
|
||
return (dataList, index) => {
|
||
return dataList.includes(index);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
<style lang="less" scoped>
|
||
/deep/ .el-dialog {
|
||
margin-top: 2vh !important;
|
||
}
|
||
.open {
|
||
padding: 3px 5px;
|
||
background: #72CB40;
|
||
font-size: 12px;
|
||
color: #FFFFFF;
|
||
}
|
||
.notopen{
|
||
padding: 3px 5px;
|
||
background: #C2C2C2;
|
||
font-size: 12px;
|
||
color: #FFFFFF;
|
||
}
|
||
.switch-box {
|
||
margin-top: 20px;
|
||
font-size: 14px;
|
||
color: #272d45;
|
||
display: flex;
|
||
/deep/.el-switch {
|
||
height: 14px;
|
||
margin-left: 12px;
|
||
margin-right: 10px;
|
||
.el-switch__core {
|
||
width: 30px !important;
|
||
height: 16px;
|
||
}
|
||
.el-switch__core:after {
|
||
width: 12px;
|
||
height: 12px;
|
||
}
|
||
}
|
||
/deep/ .el-switch.is-checked .el-switch__core::after {
|
||
margin-left: -14px;
|
||
}
|
||
}
|
||
.rules-box {
|
||
margin-top: 20px;
|
||
.box-contaniner {
|
||
margin-top: 20px;
|
||
border: 1px solid #d8dbe8;
|
||
padding: 20px;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
flex-wrap: wrap;
|
||
> div:nth-child(n + 3) {
|
||
margin-top: 20px;
|
||
}
|
||
> div {
|
||
width: calc(50% - 10px);
|
||
.box-content {
|
||
margin-top: 20px;
|
||
padding: 20px;
|
||
border: 1px dashed #d8dbe8;
|
||
height: calc(100% - 40px - 20px - 17px);
|
||
.timing {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-top: 10px;
|
||
/deep/ .el-date-editor {
|
||
width: 84px !important;
|
||
height: 24px;
|
||
.el-input__inner {
|
||
width: 84px;
|
||
height: 24px;
|
||
font-size: 13px;
|
||
padding-right: 0;
|
||
}
|
||
.el-input__icon {
|
||
line-height: 24px;
|
||
}
|
||
}
|
||
> p {
|
||
margin: 0 4px;
|
||
}
|
||
}
|
||
.progress-time {
|
||
display: flex;
|
||
margin-top: 34px;
|
||
position: relative;
|
||
> div:not(:first-child) {
|
||
> .progress-wz {
|
||
padding-left: 18px;
|
||
}
|
||
}
|
||
> div {
|
||
font-size: 13px;
|
||
color: #c9c9c9;
|
||
position: relative;
|
||
|
||
> .progress-bj {
|
||
background-color: #3594ff;
|
||
height: 10px;
|
||
}
|
||
}
|
||
.progress-active {
|
||
position: absolute;
|
||
top: -26px;
|
||
right: 0;
|
||
transform: translateX(4px);
|
||
width: 18px;
|
||
height: 14px;
|
||
background: #3594ff;
|
||
font-size: 12px;
|
||
color: #ffffff;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.progress-active::after {
|
||
position: absolute;
|
||
content: "";
|
||
left: 0;
|
||
bottom: -10px;
|
||
border-top: solid 10px #3594ff;
|
||
border-right: solid 9px transparent;
|
||
border-left: solid 9px transparent;
|
||
}
|
||
}
|
||
.rulebox {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-top: 10px;
|
||
> div:first-child {
|
||
margin-right: 10px;
|
||
}
|
||
> div:not(:first-child) {
|
||
margin-left: 10px;
|
||
}
|
||
> p {
|
||
color: #a2a4af;
|
||
margin-left: 10px;
|
||
}
|
||
> i {
|
||
color: #a2a4af;
|
||
margin-left: 10px;
|
||
}
|
||
/deep/ .el-input-number {
|
||
width: 80px;
|
||
line-height: 24px;
|
||
.el-input {
|
||
width: 80px !important;
|
||
}
|
||
.el-input-number__decrease {
|
||
height: 12px;
|
||
line-height: 12px;
|
||
}
|
||
.el-input-number__increase {
|
||
height: 11px;
|
||
line-height: 12px;
|
||
}
|
||
.el-input__inner {
|
||
width: 80px;
|
||
height: 24px;
|
||
padding-left: 6px;
|
||
padding-right: 46px;
|
||
}
|
||
}
|
||
}
|
||
.checkbox {
|
||
margin-top: 20px;
|
||
/deep/ .el-checkbox {
|
||
display: flex;
|
||
.el-checkbox__label {
|
||
font-size: 14px;
|
||
color: #a2a4af;
|
||
display: flex;
|
||
flex-direction: column;
|
||
}
|
||
}
|
||
}
|
||
> div {
|
||
color: #272d45;
|
||
font-size: 14px;
|
||
line-height: 24px;
|
||
}
|
||
> p {
|
||
font-size: 14px;
|
||
color: #a2a4af;
|
||
line-height: 24px;
|
||
}
|
||
.el-radio-group {
|
||
margin-top: 20px;
|
||
display: flex;
|
||
.el-radio,
|
||
/deep/ .el-radio__label {
|
||
display: flex;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
.tables {
|
||
.el-button {
|
||
/deep/ span {
|
||
color: #262d49;
|
||
}
|
||
}
|
||
}
|
||
.box-header {
|
||
font-family: ABeeZee, ABeeZee;
|
||
font-weight: normal;
|
||
font-size: 16px;
|
||
color: #272d45;
|
||
position: relative;
|
||
padding-left: 12px;
|
||
font-weight: bold;
|
||
> span {
|
||
font-size: 13px;
|
||
color: #c9c9c9;
|
||
font-weight: 400;
|
||
}
|
||
}
|
||
.box-header::after {
|
||
content: "";
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 0px;
|
||
transform: translateY(-50%);
|
||
width: 3px;
|
||
height: 60%;
|
||
border-radius: 3px;
|
||
background-color: #5c81ee;
|
||
}
|
||
::v-deep .el-input__inner {
|
||
line-height: 1px !important;
|
||
}
|
||
.flex() {
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.operate-clear {
|
||
.flex();
|
||
margin-left: 10px;
|
||
}
|
||
.question-icon {
|
||
border: 1px solid #676c7c;
|
||
border-radius: 50%;
|
||
width: 10px;
|
||
height: 10px;
|
||
text-align: center;
|
||
line-height: 10px;
|
||
font-size: 12px;
|
||
}
|
||
.search-box {
|
||
.flex();
|
||
margin-left: 30px;
|
||
> div {
|
||
.flex();
|
||
margin-right: 10px;
|
||
> span {
|
||
margin-right: 2px;
|
||
font-size: 14px;
|
||
}
|
||
.question-icon {
|
||
border: 1px solid #676c7c;
|
||
border-radius: 50%;
|
||
width: 10px;
|
||
height: 10px;
|
||
text-align: center;
|
||
line-height: 10px;
|
||
font-size: 12px;
|
||
}
|
||
}
|
||
/deep/.el-radio-group {
|
||
margin-top: 2px;
|
||
}
|
||
}
|
||
/deep/ .el-dialog__body {
|
||
padding: 20px;
|
||
.dialog_content {
|
||
padding: 0;
|
||
}
|
||
}
|
||
|
||
.dialogFormBox {
|
||
width: 100%;
|
||
.el-form-item {
|
||
margin-bottom: 0;
|
||
}
|
||
}
|
||
</style>
|