Browse Source

feat: 考勤明细支持出勤情况多选筛选:/hr/attendance/daily 改 POST 传数组 statusList,筛选区补下拉并抽出默认值

- api/hr/attendance.js:getDailyAttendanceDetailPage 由 GET query 改为 POST body,新增 statusList(后端按 List<String> 接收,空数组不传即不筛选)
- 筛选区新增「出勤情况」多选下拉(编码对齐后端 DAILY_STATUS_NAMES),change 即查询
- filter 默认值抽成 defaultFilter(),重置与初始化共用,避免两处口径漂移
lucw 16 hours ago
parent
commit
386f7b6c85
2 changed files with 46 additions and 19 deletions
  1. 8 4
      src/api/hr/attendance.js
  2. 38 15
      src/views/attendance/daily/index.vue

+ 8 - 4
src/api/hr/attendance.js

@@ -1990,11 +1990,11 @@ export async function importDailyAttendance(file) {
 
 /**
  * 分页查询每日考勤(夜班归属班次开始日)
- * GET /hr/attendance/daily
- * query: dateEnd, dateStart, deptId, employeeKeyword, keyword, pageNum, periodId, punchMethod, size, status, userId
+ * POST /hr/attendance/daily
+ * body: dateEnd, dateStart, deptId, employeeKeyword, keyword, pageNum, periodId, punchMethod, size, status, statusList, userId
  */
 export const getDailyAttendanceDetailPage = async (params = {}) => {
-  const query = compact({
+  const body = compact({
     dateEnd: params.dateEnd || undefined,
     dateStart: params.dateStart || undefined,
     deptId: keepBigIntId(params.deptId),
@@ -2005,8 +2005,12 @@ export const getDailyAttendanceDetailPage = async (params = {}) => {
     punchMethod: params.punchMethod || undefined,
     size: params.size != null ? Number(params.size) : 20,
     status: params.status || undefined,
+    /* 出勤情况多选:后端按 List<String> 接收,POST 直接传数组;空数组不传 */
+    statusList: Array.isArray(params.statusList) && params.statusList.length
+      ? params.statusList
+      : undefined,
     userId: keepBigIntId(params.userId),
   });
-  return pageResult(await unwrap(await request.get('/hr/attendance/daily', { params: query })));
+  return pageResult(await unwrap(await request.post('/hr/attendance/daily', body)));
 };
 

+ 38 - 15
src/views/attendance/daily/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="ele-body">
     <el-card shadow="never" class="daily-card">
-      <!-- 筛选区:所属机构 / 所属部门 / 姓名 / 日期 -->
+      <!-- 筛选区:所属机构 / 所属部门 / 姓名 / 日期 / 出勤情况 -->
       <el-form inline :model="filter" class="daily-filter" @submit.native.prevent>
         <el-form-item label="所属机构">
           <el-select v-model="filter.orgId" placeholder="请选择" clearable filterable style="width: 220px"
@@ -23,6 +23,12 @@
           <el-date-picker v-model="filter.dateRange" type="daterange" value-format="yyyy-MM-dd" range-separator="-"
             start-placeholder="开始日期" end-placeholder="结束日期" style="width: 260px" @change="search" />
         </el-form-item>
+        <el-form-item label="出勤情况">
+          <el-select v-model="filter.statusList" multiple collapse-tags clearable filterable placeholder="全部"
+            style="width: 220px" @change="search">
+            <el-option v-for="item in statusOptions" :key="item.value" :label="item.label" :value="item.value" />
+          </el-select>
+        </el-form-item>
         <el-form-item>
           <el-button type="primary" icon="el-icon-search" @click="search">查询</el-button>
           <el-button icon="el-icon-refresh" @click="reset">重置</el-button>
@@ -184,6 +190,31 @@ function currentMonthRange() {
   return [start, end];
 }
 
+/* 筛选默认值:机构取登录缓存,日期默认当月,出勤情况不筛选 */
+function defaultFilter() {
+  return {
+    orgId: getCurrentOrgId() || '',
+    deptId: '',
+    employeeKeyword: '',
+    dateRange: currentMonthRange(),
+    statusList: [],
+  };
+}
+
+/* 出勤情况选项:编码与后端 AttendanceStatusNames.DAILY_STATUS_NAMES 一致,查询直接传编码 */
+const STATUS_OPTIONS = [
+  { value: 'NORMAL', label: '正常' },
+  { value: 'LATE', label: '迟到' },
+  { value: 'EARLY_LEAVE', label: '早退' },
+  { value: 'MISSING_IN', label: '缺上班卡' },
+  { value: 'MISSING_OUT', label: '缺下班卡' },
+  { value: 'ABSENT', label: '旷工' },
+  { value: 'LEAVE', label: '请假' },
+  { value: 'BUSINESS_TRIP', label: '出差' },
+  { value: 'OUTING', label: '外出' },
+  { value: 'OVERTIME', label: '加班' },
+];
+
 export default {
   name: 'AttendanceDaily',
   components: {
@@ -191,13 +222,8 @@ export default {
   },
   data() {
     return {
-      filter: {
-        /* 所属机构:登录缓存 orgVO,默认当前机构 */
-        orgId: getCurrentOrgId() || '',
-        deptId: '',
-        employeeKeyword: '',
-        dateRange: currentMonthRange(),
-      },
+      filter: defaultFilter(),
+      statusOptions: STATUS_OPTIONS,
       filterOrgOptions: [],
       allDeptOptions: [],
       orgTreeNodes: [],
@@ -260,12 +286,7 @@ export default {
       this.search();
     },
     reset() {
-      this.filter = {
-        orgId: getCurrentOrgId() || '',
-        deptId: '',
-        employeeKeyword: '',
-        dateRange: currentMonthRange(),
-      };
+      this.filter = defaultFilter();
       this.search();
     },
     /* 筛选「所属机构」选项:登录缓存机构列表,与其他页面口径一致 */
@@ -297,7 +318,7 @@ export default {
       return null;
     },
     async fetchPage({ page, limit }) {
-      // GET /hr/attendance/daily —— 接口只有一个组织参数 deptId:
+      // POST /hr/attendance/daily —— 接口只有一个组织参数 deptId:
       // 选了部门传部门 id,否则传所属机构 id(机构也是组织树节点,服务端按数据权限校验)
       const data = await getDailyAttendanceDetailPage({
         pageNum: page,
@@ -306,6 +327,8 @@ export default {
         deptId: this.filter.deptId || this.filter.orgId || undefined,
         dateStart: (this.filter.dateRange || [])[0] || undefined,
         dateEnd: (this.filter.dateRange || [])[1] || undefined,
+        /* 出勤情况多选:空数组时接口层不传该字段,后端即不筛选 */
+        statusList: this.filter.statusList,
       });
       /* 姓名/岗位/部门/机构/状态/地址等字段均直取 daily 接口返回(后端已补中文与姓名岗位字段) */
       this.currentRows = (data.list || []).map((raw) => adaptDailyAttendance(raw));