xiaoyi
5 天以前 27c8277d717b34b55f3ea967027b53b067f77df3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<script lang="ts" setup>
  import type { VxeTableGridOptions } from '#/adapter/vxe-table';
  import type { HrmWorkHourStatisticsApi } from '#/api/hrm/work-hour-statistics';
 
  import { onBeforeUnmount, onMounted, ref, useTemplateRef } from 'vue';
 
  import { Page } from '@vben/common-ui';
  import { useVbenVxeGrid } from '#/adapter/vxe-table';
 
  import { Tabs } from 'ant-design-vue';
 
  import {
    getEmployeeWorkHourSummary,
    getTeamWorkHourSummary,
  } from '#/api/hrm/work-hour-statistics';
 
  /** HRM 工时统计(考勤口径 + 报工口径) */
  defineOptions({ name: 'HrmWorkHourStatistics' });
 
  const activeTab = ref<'employee' | 'team'>('employee');
 
  const contentRef = useTemplateRef('contentRef');
  let resizeObserver: ResizeObserver | undefined;
 
  /** 计算表格高度:内容区可用高度 - Tabs 导航等固定开销,表格撑满页面 */
  function calcTableHeight() {
    const el = contentRef.value;
    if (!el) return;
    const height = Math.max(el.clientHeight - 115, 240);
    employeeGridApi.setGridOptions({ height });
    teamGridApi.setGridOptions({ height });
  }
 
  onMounted(() => {
    calcTableHeight();
    resizeObserver = new ResizeObserver(calcTableHeight);
    if (contentRef.value) resizeObserver.observe(contentRef.value);
  });
 
  onBeforeUnmount(() => {
    resizeObserver?.disconnect();
  });
 
  const [EmployeeGrid, employeeGridApi] = useVbenVxeGrid({
    formOptions: {
      schema: [
        {
          fieldName: 'dateRange',
          label: '日期范围',
          component: 'RangePicker',
          componentProps: {
            class: '!w-full',
            valueFormat: 'YYYY-MM-DD',
            placeholder: ['开始日期', '结束日期'],
          },
        },
      ],
    },
    gridOptions: {
      columns: [
        { field: 'userName', title: '员工姓名', minWidth: 140 },
        { field: 'deptName', title: '部门', minWidth: 140 },
        { field: 'workDays', title: '出勤天数', width: 110 },
        { field: 'workHours', title: '正常工时(人时)', width: 150 },
        { field: 'overtimeHours', title: '加班工时(人时)', width: 150 },
      ],
      height: 400,
      keepSource: true,
      // 返回裸数组,需关闭分页
      pagerConfig: { enabled: false },
      proxyConfig: {
        ajax: {
          query: async (_params, formValues) => {
            const range = formValues?.dateRange ?? [];
            return await getEmployeeWorkHourSummary({
              startDate: range?.[0],
              endDate: range?.[1],
            });
          },
        },
      },
      rowConfig: { keyField: 'userId', isHover: true },
      toolbarConfig: { refresh: true, search: true },
    } as VxeTableGridOptions<HrmWorkHourStatisticsApi.EmployeeWorkHour>,
  });
 
  const [TeamGrid, teamGridApi] = useVbenVxeGrid({
    formOptions: {
      schema: [
        {
          fieldName: 'timeRange',
          label: '日期范围',
          component: 'RangePicker',
          componentProps: {
            class: '!w-full',
            valueFormat: 'YYYY-MM-DD HH:mm:ss',
            placeholder: ['开始时间', '结束时间'],
          },
        },
      ],
    },
    gridOptions: {
      columns: [
        { field: 'teamName', title: '班组名称', minWidth: 160 },
        { field: 'taskCount', title: '任务数', width: 100 },
        { field: 'totalDuration', title: '总生产时长(人日)', width: 160 },
        { field: 'workHours', title: '总工时(人时)', width: 150 },
      ],
      height: 400,
      keepSource: true,
      pagerConfig: { enabled: false },
      proxyConfig: {
        ajax: {
          query: async (_params, formValues) => {
            const range = formValues?.timeRange ?? [];
            return await getTeamWorkHourSummary({
              startTime: range?.[0],
              endTime: range?.[1],
            });
          },
        },
      },
      rowConfig: { keyField: 'teamId', isHover: true },
      toolbarConfig: { refresh: true, search: true },
    } as VxeTableGridOptions<HrmWorkHourStatisticsApi.TeamWorkHour>,
  });
</script>
 
<template>
  <Page auto-content-height>
    <div ref="contentRef" class="flex h-full w-full flex-col">
      <Tabs v-model:active-key="activeTab" class="min-h-0 flex-1">
        <Tabs.TabPane key="employee" tab="员工工时(考勤口径)">
          <EmployeeGrid table-title="员工工时统计" />
        </Tabs.TabPane>
        <Tabs.TabPane key="team" tab="班组工时(报工口径)">
          <TeamGrid table-title="班组工时统计" />
        </Tabs.TabPane>
      </Tabs>
    </div>
  </Page>
</template>