feat(attendance): 优化考勤记录导出功能支持部门选择
- 修改后端接口参数名称从 deptname 改为 enames - 实现前端多员工选择下拉框组件 - 添加部门联动员工动态加载功能 - 重构导出逻辑支持按员工列表精确过滤 - 修复数组参数序列化导致的逗号编码问题 - 新增获取部门列表和按部门查询员工的API接口 - 实现导出表单验证和异步处理机制
This commit is contained in:
@@ -63,6 +63,19 @@ export function exportAttendanceReport(params) {
|
|||||||
url: '/wms/attendanceRecords/exportReport',
|
url: '/wms/attendanceRecords/exportReport',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
params: params,
|
params: params,
|
||||||
responseType: 'blob'
|
responseType: 'blob',
|
||||||
|
// enames 是数组,需要特殊序列化避免逗号被二次编码
|
||||||
|
paramsSerializer: params => {
|
||||||
|
const searchParams = new URLSearchParams();
|
||||||
|
Object.keys(params).forEach(key => {
|
||||||
|
const val = params[key];
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
searchParams.append(key, val.join(','));
|
||||||
|
} else if (val !== undefined && val !== null && val !== '') {
|
||||||
|
searchParams.append(key, val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return searchParams.toString();
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,3 +42,20 @@ export function delEmployeeInfo(infoId) {
|
|||||||
method: 'delete'
|
method: 'delete'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取所有不重复的部门名称
|
||||||
|
export function getDepts() {
|
||||||
|
return request({
|
||||||
|
url: '/wms/employeeInfo/depts',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据部门查询在职员工
|
||||||
|
export function getEmployeesByDept(dept) {
|
||||||
|
return request({
|
||||||
|
url: '/wms/employeeInfo/employeesByDept',
|
||||||
|
method: 'get',
|
||||||
|
params: { dept }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -211,7 +211,14 @@
|
|||||||
<el-input v-model="exportFormData.ename" placeholder="请输入姓名(可选)" clearable />
|
<el-input v-model="exportFormData.ename" placeholder="请输入姓名(可选)" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="部门" prop="deptname">
|
<el-form-item label="部门" prop="deptname">
|
||||||
<el-input v-model="exportFormData.deptname" placeholder="请输入部门(可选)" clearable />
|
<el-select v-model="exportFormData.deptname" placeholder="请选择部门(可选)" clearable filterable @change="handleDeptChange" style="width: 100%">
|
||||||
|
<el-option v-for="dept in deptList" :key="dept" :label="dept" :value="dept" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="员工" prop="enames" v-if="exportFormData.deptname">
|
||||||
|
<el-select v-model="exportFormData.enames" placeholder="请选择员工(可选,不选则导出整个部门)" multiple clearable filterable style="width: 100%">
|
||||||
|
<el-option v-for="emp in employeeList" :key="emp.name" :label="emp.name + ' (' + emp.jobType + ')'" :value="emp.name" />
|
||||||
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
@@ -224,6 +231,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { listRecords, getRecords, delRecords, addRecords, updateRecords, syncRecords, exportAttendanceReport } from "@/api/wms/attendance";
|
import { listRecords, getRecords, delRecords, addRecords, updateRecords, syncRecords, exportAttendanceReport } from "@/api/wms/attendance";
|
||||||
|
import { getDepts, getEmployeesByDept } from "@/api/wms/employeeInfo";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Records",
|
name: "Records",
|
||||||
@@ -247,12 +255,17 @@ export default {
|
|||||||
exportDialogVisible: false,
|
exportDialogVisible: false,
|
||||||
// 导出loading
|
// 导出loading
|
||||||
exportLoading: false,
|
exportLoading: false,
|
||||||
|
// 部门列表
|
||||||
|
deptList: [],
|
||||||
|
// 员工列表(根据部门动态加载)
|
||||||
|
employeeList: [],
|
||||||
// 导出表单
|
// 导出表单
|
||||||
exportFormData: {
|
exportFormData: {
|
||||||
dateRange: [],
|
dateRange: [],
|
||||||
pin: "",
|
pin: "",
|
||||||
ename: "",
|
ename: "",
|
||||||
deptname: ""
|
deptname: "",
|
||||||
|
enames: []
|
||||||
},
|
},
|
||||||
// 导出表单校验
|
// 导出表单校验
|
||||||
exportRules: {
|
exportRules: {
|
||||||
@@ -474,6 +487,12 @@ export default {
|
|||||||
this.exportFormData.pin = "";
|
this.exportFormData.pin = "";
|
||||||
this.exportFormData.ename = "";
|
this.exportFormData.ename = "";
|
||||||
this.exportFormData.deptname = "";
|
this.exportFormData.deptname = "";
|
||||||
|
this.exportFormData.enames = [];
|
||||||
|
this.employeeList = [];
|
||||||
|
// 加载部门列表
|
||||||
|
getDepts().then(res => {
|
||||||
|
this.deptList = res.data || [];
|
||||||
|
});
|
||||||
this.exportDialogVisible = true;
|
this.exportDialogVisible = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.exportForm && this.$refs.exportForm.clearValidate();
|
this.$refs.exportForm && this.$refs.exportForm.clearValidate();
|
||||||
@@ -484,35 +503,66 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
/** 部门变更时加载对应员工 */
|
||||||
|
handleDeptChange(dept) {
|
||||||
|
this.exportFormData.enames = [];
|
||||||
|
if (dept) {
|
||||||
|
getEmployeesByDept(dept).then(res => {
|
||||||
|
this.employeeList = res.data || [];
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.employeeList = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
/** 执行导出考勤记录表 */
|
/** 执行导出考勤记录表 */
|
||||||
doExportReport() {
|
async doExportReport() {
|
||||||
this.$refs.exportForm.validate(valid => {
|
const valid = await this.$refs.exportForm.validate().catch(() => false);
|
||||||
if (!valid) return;
|
if (!valid) return;
|
||||||
const [startDate, endDate] = this.exportFormData.dateRange;
|
|
||||||
this.exportLoading = true;
|
const [startDate, endDate] = this.exportFormData.dateRange;
|
||||||
exportAttendanceReport({
|
this.exportLoading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
let enames = undefined;
|
||||||
|
|
||||||
|
if (this.exportFormData.deptname) {
|
||||||
|
// 选了部门:通过 wms_employee_info 查员工姓名来过滤
|
||||||
|
if (this.exportFormData.enames && this.exportFormData.enames.length > 0) {
|
||||||
|
enames = this.exportFormData.enames;
|
||||||
|
} else {
|
||||||
|
const res = await getEmployeesByDept(this.exportFormData.deptname);
|
||||||
|
const allEmps = res.data || [];
|
||||||
|
enames = allEmps.map(e => e.name);
|
||||||
|
if (enames.length === 0) {
|
||||||
|
this.$modal.msgWarning('该部门下没有在职员工');
|
||||||
|
this.exportLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await exportAttendanceReport({
|
||||||
startTime: startDate,
|
startTime: startDate,
|
||||||
endTime: endDate,
|
endTime: endDate,
|
||||||
pin: this.exportFormData.pin || undefined,
|
pin: !enames ? (this.exportFormData.pin || undefined) : undefined,
|
||||||
ename: this.exportFormData.ename || undefined,
|
ename: !enames ? (this.exportFormData.ename || undefined) : undefined,
|
||||||
deptname: this.exportFormData.deptname || undefined
|
enames: enames
|
||||||
}).then(res => {
|
|
||||||
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.download = `考勤记录表_${startDate}_${endDate}.xlsx`;
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
window.URL.revokeObjectURL(url);
|
|
||||||
this.$modal.msgSuccess("导出成功");
|
|
||||||
this.exportLoading = false;
|
|
||||||
this.exportDialogVisible = false;
|
|
||||||
}).catch(() => {
|
|
||||||
this.exportLoading = false;
|
|
||||||
});
|
});
|
||||||
});
|
const blob = new Blob([res], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = `考勤记录表_${startDate}_${endDate}.xlsx`;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
this.$modal.msgSuccess("导出成功");
|
||||||
|
this.exportLoading = false;
|
||||||
|
this.exportDialogVisible = false;
|
||||||
|
} catch (e) {
|
||||||
|
this.exportLoading = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ public class AttendanceRecordsController extends BaseController {
|
|||||||
@RequestParam String endTime,
|
@RequestParam String endTime,
|
||||||
@RequestParam(required = false) String pin,
|
@RequestParam(required = false) String pin,
|
||||||
@RequestParam(required = false) String ename,
|
@RequestParam(required = false) String ename,
|
||||||
@RequestParam(required = false) String deptname,
|
@RequestParam(required = false) String enames,
|
||||||
HttpServletResponse response) {
|
HttpServletResponse response) {
|
||||||
iAttendanceRecordsService.exportReport(startTime, endTime, pin, ename, deptname, response);
|
iAttendanceRecordsService.exportReport(startTime, endTime, pin, ename, enames, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
|||||||
@@ -96,4 +96,20 @@ public class WmsEmployeeInfoController extends BaseController {
|
|||||||
@PathVariable Long[] infoIds) {
|
@PathVariable Long[] infoIds) {
|
||||||
return toAjax(iWmsEmployeeInfoService.deleteWithValidByIds(Arrays.asList(infoIds), true));
|
return toAjax(iWmsEmployeeInfoService.deleteWithValidByIds(Arrays.asList(infoIds), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有不重复的部门名称
|
||||||
|
*/
|
||||||
|
@GetMapping("/depts")
|
||||||
|
public R<List<String>> getDepts() {
|
||||||
|
return R.ok(iWmsEmployeeInfoService.getDistinctDepts());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据部门查询在职员工
|
||||||
|
*/
|
||||||
|
@GetMapping("/employeesByDept")
|
||||||
|
public R<List<WmsEmployeeInfoVo>> getEmployeesByDept(@RequestParam String dept) {
|
||||||
|
return R.ok(iWmsEmployeeInfoService.getEmployeesByDept(dept));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,5 +33,5 @@ public interface IAttendanceRecordsService {
|
|||||||
/**
|
/**
|
||||||
* 导出考勤记录表(复杂格式)
|
* 导出考勤记录表(复杂格式)
|
||||||
*/
|
*/
|
||||||
void exportReport(String startTime, String endTime, String pin, String ename, String deptname, HttpServletResponse response);
|
void exportReport(String startTime, String endTime, String pin, String ename, String enames, HttpServletResponse response);
|
||||||
}
|
}
|
||||||
@@ -46,4 +46,14 @@ public interface IWmsEmployeeInfoService {
|
|||||||
* 校验并批量删除员工信息信息
|
* 校验并批量删除员工信息信息
|
||||||
*/
|
*/
|
||||||
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有不重复的部门名称
|
||||||
|
*/
|
||||||
|
List<String> getDistinctDepts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据部门查询在职员工信息
|
||||||
|
*/
|
||||||
|
List<WmsEmployeeInfoVo> getEmployeesByDept(String dept);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class AttendanceRecordsServiceImpl implements IAttendanceRecordsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exportReport(String startTime, String endTime, String pin, String ename, String deptname, HttpServletResponse response) {
|
public void exportReport(String startTime, String endTime, String pin, String ename, String enames, HttpServletResponse response) {
|
||||||
try {
|
try {
|
||||||
// 1. 解析时间范围
|
// 1. 解析时间范围
|
||||||
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||||
@@ -119,14 +119,17 @@ public class AttendanceRecordsServiceImpl implements IAttendanceRecordsService {
|
|||||||
LambdaQueryWrapper<AttendanceRecords> lqw = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<AttendanceRecords> lqw = Wrappers.lambdaQuery();
|
||||||
lqw.ge(AttendanceRecords::getChecktime, startDatetime);
|
lqw.ge(AttendanceRecords::getChecktime, startDatetime);
|
||||||
lqw.le(AttendanceRecords::getChecktime, endDatetime);
|
lqw.le(AttendanceRecords::getChecktime, endDatetime);
|
||||||
if (StringUtils.isNotBlank(pin)) {
|
// 如果传入了员工姓名列表,优先按姓名列表过滤
|
||||||
lqw.eq(AttendanceRecords::getPin, pin);
|
if (StringUtils.isNotBlank(enames)) {
|
||||||
}
|
List<String> enameList = Arrays.asList(enames.split(","));
|
||||||
if (StringUtils.isNotBlank(ename)) {
|
lqw.in(AttendanceRecords::getEname, enameList);
|
||||||
lqw.like(AttendanceRecords::getEname, ename);
|
} else {
|
||||||
}
|
if (StringUtils.isNotBlank(pin)) {
|
||||||
if (StringUtils.isNotBlank(deptname)) {
|
lqw.eq(AttendanceRecords::getPin, pin);
|
||||||
lqw.eq(AttendanceRecords::getDeptname, deptname);
|
}
|
||||||
|
if (StringUtils.isNotBlank(ename)) {
|
||||||
|
lqw.like(AttendanceRecords::getEname, ename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lqw.orderByAsc(AttendanceRecords::getPin).orderByAsc(AttendanceRecords::getChecktime);
|
lqw.orderByAsc(AttendanceRecords::getPin).orderByAsc(AttendanceRecords::getChecktime);
|
||||||
List<AttendanceRecords> records = baseMapper.selectList(lqw);
|
List<AttendanceRecords> records = baseMapper.selectList(lqw);
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ import com.klp.service.IWmsEmployeeInfoService;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 员工信息Service业务层处理
|
* 员工信息Service业务层处理
|
||||||
@@ -145,4 +147,33 @@ public class WmsEmployeeInfoServiceImpl implements IWmsEmployeeInfoService {
|
|||||||
}
|
}
|
||||||
return baseMapper.deleteBatchIds(ids) > 0;
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有不重复的部门名称(仅在职员工)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getDistinctDepts() {
|
||||||
|
LambdaQueryWrapper<WmsEmployeeInfo> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(WmsEmployeeInfo::getIsLeave, 0);
|
||||||
|
List<WmsEmployeeInfoVo> list = baseMapper.selectVoList(lqw);
|
||||||
|
return list.stream()
|
||||||
|
.map(WmsEmployeeInfoVo::getDept)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.filter(org.apache.commons.lang3.StringUtils::isNotBlank)
|
||||||
|
.distinct()
|
||||||
|
.sorted()
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据部门查询在职员工信息
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<WmsEmployeeInfoVo> getEmployeesByDept(String dept) {
|
||||||
|
LambdaQueryWrapper<WmsEmployeeInfo> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(WmsEmployeeInfo::getDept, dept)
|
||||||
|
.eq(WmsEmployeeInfo::getIsLeave, 0)
|
||||||
|
.orderByAsc(WmsEmployeeInfo::getName);
|
||||||
|
return baseMapper.selectVoList(lqw);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user