Ver código fonte

feat: 新增补卡功能,支持上班和下班补卡操作。更新考勤历史页面,添加补卡对话框和相关表单验证,优化用户体验。

master
lizhuang 4 dias atrás
pai
commit
c6bc5950c3

+ 12
- 1
src/api/oa/attendance/history.js Ver arquivo

@@ -18,4 +18,15 @@ export function queryList(query) {
})
}


/**
* 补卡
* @param {*} data
* @returns
*/
export function editRecord(data) {
return request({
url: '/dk/record',
method: 'put',
data: data
})
}

+ 207
- 29
src/views/oa/attendance/history/index.vue Ver arquivo

@@ -9,13 +9,29 @@
>
<el-form-item label="考勤日期" prop="strDay">
<el-date-picker
type="date"
v-model="queryParams.strDay"
type="date"
format="yyyy 年 MM 月 dd 日"
value-format="yyyy-MM-dd"
placeholder="选择日期"
/>
</el-form-item>

<el-form-item label="考勤组" prop="attendanceGroupId">
<el-select
v-model="queryParams.attendanceGroupIds"
placeholder="请选择考勤组"
clearable
multiple
style="width: 100%"
>
</el-date-picker>
<el-option
v-for="dict in attendanceGroups"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>

<el-form-item label="员工编号" prop="sysUserName">
@@ -41,6 +57,7 @@
/>
</el-select>
</el-form-item>

<el-form-item>
<el-button
type="primary"
@@ -61,40 +78,31 @@
</el-form>

<el-table v-loading="loading" :data="resultList">
<el-table-column label="序号" type="index" width="100"> </el-table-column>
<el-table-column label="序号" type="index" width="100" />
<el-table-column label="打卡日期" width="120" prop="checkInTime">
<template slot-scope="scope">
{{ formatDate(scope.row.checkInTime) }}
</template>
</el-table-column>
<el-table-column label="员工编号" width="120" prop="sysUserName">
</el-table-column>
<el-table-column
label="员工姓名"
prop="nickName"
width="120"
></el-table-column>
<el-table-column
label="考勤组"
prop="attendanceGroupName"
width="120"
></el-table-column>
<el-table-column label="员工编号" width="120" prop="sysUserName" />
<el-table-column label="员工姓名" prop="nickName" width="120" />
<el-table-column label="考勤组" prop="attendanceGroupName" width="120" />
<el-table-column label="上班" width="200">
<template slot-scope="scope">
<span style="color: #909399" v-if="scope.row.checkInStatus == '0'">
<span v-if="scope.row.checkInStatus == '0'" style="color: #909399">
<!-- 上班未打卡 -->
未打卡
</span>
<span
style="color: #409eff"
v-else-if="scope.row.clockInStatus == '1'"
style="color: #409eff"
>
<!--上班已打卡-->
正常 {{ formatTime(scope.row.clockIn) }}</span
>
<span
style="color: #f56c6c"
v-else-if="scope.row.clockInStatus == '3'"
style="color: #f56c6c"
>
迟到 {{ formatTime(scope.row.clockIn) }}
</span>
@@ -105,26 +113,26 @@
</el-table-column>
<el-table-column label="下班" width="200">
<template slot-scope="scope">
<span style="color: #909399" v-if="scope.row.clockOutStatus == '0'">
<span v-if="scope.row.clockOutStatus == '0'" style="color: #909399">
<!-- 下班未打卡 -->
未打卡
</span>
<span
style="color: #409eff"
v-else-if="scope.row.clockOutStatus == '2'"
style="color: #409eff"
>
<!--下班已打卡-->
正常 {{ formatTime(scope.row.clockOut) }}</span
>
<span
style="color: #f56c6c"
v-else-if="scope.row.clockOutStatus == '4'"
style="color: #f56c6c"
>
早退 {{ formatTime(scope.row.clockOut) }}
</span>
<span
style="color: #f56c6c"
v-else-if="scope.row.clockOutStatus == '5'"
style="color: #f56c6c"
>
更新 {{ formatTime(scope.row.clockOut) }}
</span>
@@ -133,8 +141,30 @@
</span>
</template>
</el-table-column>
<el-table-column label="最后更新时间" prop="updateTime" width="200"></el-table-column>
<el-table-column label="备注" prop="description"></el-table-column>
<el-table-column label="最后更新时间" prop="updateTime" width="200" />
<el-table-column label="备注" prop="description" />

<el-table-column
label="操作"
width="200"
align="center"
v-hasPermi="['attendance:history:edit']"
>
<template slot-scope="scope">
<el-button
v-hasPermi="['attendance:history:edit']"
type="text"
@click="handleEdit(scope.row, 0)"
>上班补卡</el-button
>
<el-button
v-hasPermi="['attendance:history:edit']"
type="text"
@click="handleEdit(scope.row, 1)"
>下班补卡</el-button
>
</template>
</el-table-column>
</el-table>

<pagination
@@ -152,9 +182,9 @@
append-to-body
>
<el-form
ref="exportFormRef"
:model="exportFormData"
label-position="top"
ref="exportFormRef"
size="small"
:rules="exportFormRules"
>
@@ -180,8 +210,7 @@
value-format="yyyy-MM"
placeholder="选择月"
style="width: 100%"
>
</el-date-picker>
/>
</el-form-item>
<el-form-item label="选择考勤组(支持多选)" prop="attendanceGroupIds">
<el-select
@@ -211,11 +240,79 @@
>
</span>
</el-dialog>

<el-dialog
:title="`${checkStatus == 0 ? '上班' : '下班'}补卡`"
:visible.sync="editDialogVisible"
width="460px"
append-to-body
>
<el-descriptions border :column="2" style="margin-bottom: 20px">
<el-descriptions-item label="打卡日期">{{
formatDate(editFormData.checkInTime)
}}</el-descriptions-item>
<el-descriptions-item label="考勤组">{{
editFormData.attendanceGroupName
}}</el-descriptions-item>
<el-descriptions-item label="员工姓名">{{
editFormData.nickName
}}</el-descriptions-item>
<el-descriptions-item label="员工编号">{{
editFormData.sysUserName
}}</el-descriptions-item>
</el-descriptions>
<el-form
ref="editFormRef"
:model="editFormData"
label-position="top"
size="small"
:rules="editFormRules"
>
<el-row :gutter="20">
<el-col v-if="checkStatus == 0" :span="12">
<el-form-item label="上班打卡时间" prop="clockIn">
<el-date-picker
v-model="editFormData.clockIn"
type="datetime"
placeholder="请选择上班时间"
style="width: 100%"
value-format="yyyy-MM-dd HH:mm:ss"
/>
</el-form-item>
</el-col>
<el-col v-if="checkStatus == 1" :span="12">
<el-form-item label="下班打卡时间" prop="clockOut">
<el-date-picker
v-model="editFormData.clockOut"
type="datetime"
placeholder="请选择下班时间"
style="width: 100%"
value-format="yyyy-MM-dd HH:mm:ss"
/>
</el-form-item>
</el-col>
</el-row>

<el-form-item label="补卡备注" prop="description">
<el-input
v-model="editFormData.description"
placeholder="请输入打卡备注"
type="textarea"
:rows="3"
/>
</el-form-item>
</el-form>

<span slot="footer" class="dialog-footer">
<el-button @click="handleEditCancel">取 消</el-button>
<el-button type="primary" @click="handleEditSubmit">确 定</el-button>
</span>
</el-dialog>
</div>
</template>

<script>
import { queryList } from "@/api/oa/attendance/history";
import { queryList, editRecord } from "@/api/oa/attendance/history";
import { queryAttendanceGroup } from "@/api/oa/attendance/group";
import { formatTime, formatDate } from "@/utils/filters";

@@ -239,7 +336,7 @@ export default {
pageSize: 50,
sysUserName: undefined,
checkInStatus: undefined,
strDay: undefined,
strDay: new Date(),
flag: "all",
},
exportFormData: {
@@ -272,6 +369,23 @@ export default {
{ required: true, message: "请选择考勤组", trigger: "change" },
],
},
editDialogVisible: false,
editFormData: {
checkInTime: undefined,
checkInStatus: undefined,
clockIn: undefined,
clockOut: undefined,
description: undefined,
},
editFormRules: {
clockIn: [
{ required: true, message: "请选择上班时间", trigger: "change" },
],
clockOut: [
{ required: true, message: "请选择下班时间", trigger: "change" },
],
},
checkStatus: 0,
};
},
created() {
@@ -281,6 +395,69 @@ export default {
methods: {
formatDate,
formatTime,
handleEditCancel() {
this.editDialogVisible = false;
this.editFormData = {
checkInTime: undefined,
checkInStatus: undefined,
clockIn: undefined,
clockOut: undefined,
description: undefined,
};
this.$nextTick(() => {
this.$refs.editFormRef.resetFields();
});
},
handleEditSubmit() {
this.$refs.editFormRef.validate((valid) => {
if (valid) {
if (this.checkStatus == 0) {
// 上班补卡
this.editFormData.clockOut = undefined;
this.editFormData.clockOutStatus = undefined;
this.editFormData.clockInStatus = 1;
this.editFormData.checkInStatus = 1;
} else {
// 下班补卡
this.editFormData.clockIn = undefined;
this.editFormData.clockInStatus = undefined;
this.editFormData.clockOutStatus = 2;
this.editFormData.checkInStatus = 2;
}
editRecord({
id: this.editFormData.id,
sysUserId: this.editFormData.sysUserId,
clockIn: this.editFormData.clockIn,
clockOut: this.editFormData.clockOut,
description: this.editFormData.description
})
.then((response) => {
this.$message.success("补卡成功");
this.editDialogVisible = false;
this.getList();
})
.catch(() => {
this.$message.error("补卡失败");
});
} else {
console.log("error submit!!");
return false;
}
});
},
handleEdit(row, checkStatus) {
this.editDialogVisible = true;
this.editFormData = row;
if (!this.editFormData.clockIn) {
this.editFormData.clockIn =
formatDate(this.editFormData.checkInTime) + " 00:00:00";
}
if (!this.editFormData.clockOut) {
this.editFormData.clockOut =
formatDate(this.editFormData.checkInTime) + " 00:00:00";
}
this.checkStatus = checkStatus;
},
handleExportSet() {
this.open = true;
this.reset();
@@ -297,6 +474,7 @@ export default {
/** 查询结果列表 */
getList() {
this.loading = true;
this.queryParams.strDay = formatDate(this.queryParams.strDay);
queryList(this.queryParams).then((response) => {
this.resultList = response.rows;
this.total = response.total;

+ 2
- 1
src/views/sales-analysis/reports/OverallAnalysis.vue Ver arquivo

@@ -273,7 +273,7 @@ export default {
},
filters: {
jpMoney(value) {
if (value === 0) {
if (value === 0 || value === null) {
return "0";
}
if (value < 10000) {
@@ -433,6 +433,7 @@ export default {
} catch (error) {
console.error("获取数据失败:", error);
this.$message.error("获取数据失败");
this.loading = false;
} finally {
this.loading = false;
}

Carregando…
Cancelar
Salvar