添加工资查看功能
This commit is contained in:
@@ -52,6 +52,11 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="name" label="姓名" width="100" show-overflow-tooltip fixed="left" />
|
||||
<el-table-column prop="baseSalary" label="基本工资" width="120" align="right" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ formatMoney(scope.row.baseSalary) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="workDays" label="工作天数" width="100" align="center" />
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
@@ -82,8 +87,36 @@
|
||||
<el-table-column prop="annualPerformance" label="年度绩效" width="100" align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="monthlyPerformance" label="月度绩效" width="100" align="center" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column prop="penaltyAmount" label="违纪扣奖" width="100" align="center" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="120" fixed="right" align="center">
|
||||
<el-table-column label="签名" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<div class="signature-cell">
|
||||
<el-image
|
||||
v-if="scope.row.signatureImg"
|
||||
:src="scope.row.signatureImg"
|
||||
fit="contain"
|
||||
style="width: 40px; height: 40px; cursor: pointer;"
|
||||
@click="handlePreviewSignature(scope.row.signatureImg)"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<el-icon><Picture /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
<span v-else>无签名</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="240" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
size="small"
|
||||
@click="handleViewDetail(scope.row)"
|
||||
>
|
||||
查看详情
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
link
|
||||
@@ -150,19 +183,142 @@
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 工资条详情对话框 -->
|
||||
<el-dialog
|
||||
v-model="detailDialogVisible"
|
||||
title="考勤详情"
|
||||
width="800px"
|
||||
>
|
||||
<div v-if="currentDetail" class="attendance-detail">
|
||||
<div class="detail-header">
|
||||
<div class="employee-info">
|
||||
<el-avatar :size="64" :src="currentDetail.avatar" />
|
||||
<div class="info-content">
|
||||
<h3>{{ currentDetail.name }}</h3>
|
||||
<p>{{ currentDetail.position }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="attendance-period">
|
||||
{{ currentDetail.year }}年{{ currentDetail.month }}月考勤
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="基本工资">{{ formatMoney(currentDetail.baseSalary) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="工作天数">{{ currentDetail.workDays }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag :type="currentDetail.status === 0 ? 'success' : 'warning'" size="small">
|
||||
{{ currentDetail.status === 0 ? '正式' : '试用' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="事假">{{ currentDetail.personalLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="病假">{{ currentDetail.sickLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="产假">{{ currentDetail.maternityLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="陪产假">{{ currentDetail.paternityLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="婚假">{{ currentDetail.marriageLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="丧假">{{ currentDetail.bereavementLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年休假">{{ currentDetail.annualLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年休假(管理岗)">{{ currentDetail.managementAnnualLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="调休假">{{ currentDetail.compensatoryLeave }}</el-descriptions-item>
|
||||
<el-descriptions-item label="早退次数">{{ currentDetail.early }}</el-descriptions-item>
|
||||
<el-descriptions-item label="迟到次数">{{ currentDetail.late }}</el-descriptions-item>
|
||||
<el-descriptions-item label="严重迟到">{{ currentDetail.seriousLate }}</el-descriptions-item>
|
||||
<el-descriptions-item label="旷工次数">{{ currentDetail.absenteeism }}</el-descriptions-item>
|
||||
<el-descriptions-item label="缺卡次数">{{ currentDetail.missedCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="缺勤次数">{{ currentDetail.absenceCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="未提交日志">{{ currentDetail.missingLogCount }}</el-descriptions-item>
|
||||
<el-descriptions-item label="工作日加班">{{ currentDetail.workdayOvertime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="休息日加班">{{ currentDetail.restdayOvertime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="节假日加班">{{ currentDetail.holidayOvertime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="年度绩效">{{ currentDetail.annualPerformance }}</el-descriptions-item>
|
||||
<el-descriptions-item label="月度绩效">{{ currentDetail.monthlyPerformance }}</el-descriptions-item>
|
||||
<el-descriptions-item label="违纪扣奖">{{ formatMoney(currentDetail.penaltyAmount) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div class="detail-footer">
|
||||
<div class="signature-section">
|
||||
<div class="signature-item">
|
||||
<div class="label">员工签名:</div>
|
||||
<div class="signature-image" v-if="currentDetail.signatureImg">
|
||||
<el-image
|
||||
:src="currentDetail.signatureImg"
|
||||
fit="contain"
|
||||
style="width: 100%; height: 100%;"
|
||||
@click="handlePreviewSignature(currentDetail.signatureImg)"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<el-icon><Picture /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="no-signature" v-else>未签名</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 签名预览对话框 -->
|
||||
<el-dialog
|
||||
v-model="signaturePreviewVisible"
|
||||
title="签名预览"
|
||||
width="500px"
|
||||
:show-close="true"
|
||||
:close-on-click-modal="true"
|
||||
:close-on-press-escape="true"
|
||||
class="signature-preview-dialog"
|
||||
>
|
||||
<div class="signature-preview-content">
|
||||
<el-image
|
||||
v-if="currentSignatureImg"
|
||||
:src="currentSignatureImg"
|
||||
fit="contain"
|
||||
style="width: 100%; height: 300px;"
|
||||
>
|
||||
<template #error>
|
||||
<div class="image-slot">
|
||||
<el-icon><Picture /></el-icon>
|
||||
</div>
|
||||
</template>
|
||||
</el-image>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { Search } from '@element-plus/icons-vue';
|
||||
import { Search, Picture } from '@element-plus/icons-vue';
|
||||
import dayjs from 'dayjs';
|
||||
import {
|
||||
getFinanceAttendanceList,
|
||||
getAbnormalAttendanceDetail,
|
||||
} from "../../../../api/modules/index";
|
||||
|
||||
// 格式化金额
|
||||
const formatMoney = (value) => {
|
||||
if (value === undefined || value === null) return '0.00';
|
||||
|
||||
// 将输入转换为数字
|
||||
const num = Number(value);
|
||||
|
||||
// 检查是否为有效数字
|
||||
if (isNaN(num)) return '0.00';
|
||||
|
||||
// 使用toFixed(2)保留两位小数
|
||||
const fixedNum = num.toFixed(2);
|
||||
|
||||
// 添加千分位分隔符
|
||||
const parts = fixedNum.split('.');
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
|
||||
return parts.join('.');
|
||||
};
|
||||
|
||||
// 权限检查
|
||||
const userInfo = JSON.parse(sessionStorage.getItem("userInfo") || "{}");
|
||||
// if (userInfo.role !== 3) {
|
||||
@@ -175,6 +331,10 @@ const attendanceList = ref([]);
|
||||
const originalList = ref([]);
|
||||
const searchKeyword = ref('');
|
||||
|
||||
// 详情对话框
|
||||
const detailDialogVisible = ref(false);
|
||||
const currentDetail = ref(null);
|
||||
|
||||
// 日期范围
|
||||
const dateRange = ref(null);
|
||||
const defaultTime = new Date(2000, 1, 1, 0, 0, 0);
|
||||
@@ -330,6 +490,24 @@ const handleViewAbnormal = async (row) => {
|
||||
}
|
||||
};
|
||||
|
||||
// 查看详情
|
||||
const handleViewDetail = (row) => {
|
||||
currentDetail.value = row;
|
||||
detailDialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 签名预览
|
||||
const signaturePreviewVisible = ref(false);
|
||||
const currentSignatureImg = ref('');
|
||||
|
||||
const handlePreviewSignature = (url) => {
|
||||
if (!url) return;
|
||||
const img = new Image();
|
||||
img.src = url;
|
||||
const newWindow = window.open('');
|
||||
newWindow.document.write(img.outerHTML);
|
||||
};
|
||||
|
||||
// 页面加载时设置默认日期范围并获取数据
|
||||
onMounted(() => {
|
||||
setDefaultDateRange();
|
||||
@@ -387,11 +565,13 @@ onMounted(() => {
|
||||
.el-table__fixed-right {
|
||||
height: 100% !important;
|
||||
box-shadow: -2px 0 8px rgba(0, 0, 0, 0.15);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.el-table__fixed {
|
||||
height: 100% !important;
|
||||
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.15);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,6 +595,39 @@ onMounted(() => {
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.signature-cell {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__wrapper) {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__mask) {
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__btn) {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__actions) {
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__canvas) {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
:deep(.el-dialog__wrapper) {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
:deep(.el-dialog) {
|
||||
z-index: 2001;
|
||||
}
|
||||
}
|
||||
|
||||
.abnormal-date-group {
|
||||
@@ -472,4 +685,193 @@ onMounted(() => {
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.image-slot {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
color: #909399;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.signature-image {
|
||||
height: 100px;
|
||||
border: 1px solid var(--el-border-color);
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
z-index: 3000;
|
||||
|
||||
:deep(.el-image) {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
z-index: 3000;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__wrapper) {
|
||||
z-index: 3000;
|
||||
|
||||
.el-image-viewer__canvas {
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-dialog) {
|
||||
.el-dialog__body {
|
||||
position: relative;
|
||||
z-index: 2000;
|
||||
}
|
||||
}
|
||||
|
||||
.signature-cell {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:deep(.el-table) {
|
||||
.el-table__fixed-right {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
.el-table__fixed {
|
||||
z-index: 2000;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__wrapper) {
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
:deep(.el-image-viewer__mask) {
|
||||
z-index: 9998;
|
||||
}
|
||||
|
||||
.signature-preview-dialog {
|
||||
:deep(.el-dialog__body) {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.signature-preview-content {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: #ffffff;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-dialog__wrapper) {
|
||||
z-index: 2000;
|
||||
}
|
||||
|
||||
:deep(.el-dialog) {
|
||||
z-index: 2001;
|
||||
}
|
||||
|
||||
.attendance-detail {
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
.employee-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
|
||||
.info-content {
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 4px 0 0;
|
||||
font-size: 14px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.attendance-period {
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.detail-footer {
|
||||
margin-top: 20px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid #ebeef5;
|
||||
|
||||
.signature-section {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 40px;
|
||||
|
||||
.signature-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
|
||||
.label {
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.signature-image {
|
||||
width: 120px;
|
||||
height: 60px;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-color: #409eff;
|
||||
}
|
||||
}
|
||||
|
||||
.no-signature {
|
||||
width: 120px;
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #909399;
|
||||
font-size: 14px;
|
||||
border: 1px dashed #dcdfe6;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-descriptions) {
|
||||
.el-descriptions__label {
|
||||
width: 120px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.el-descriptions__content {
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user