21 分钟以前 5960d731989c58e887b6cca103edfe23dec5e06b
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 { HrmSalaryPaymentApi } from '#/api/hrm/salary/payment';
 
import { ref, computed } from 'vue';
 
import { useVbenModal } from '#/packages/effects/common-ui/src';
 
import { message, Table, Tag, InputNumber, Alert } from 'ant-design-vue';
 
import { ACTION_ICON, TableAction } from '#/adapter/vxe-table';
import { getSalaryPaymentDetailList, paySalaryDetail } from '#/api/hrm/salary/payment';
import { $t } from '#/locales';
 
const emit = defineEmits(['success']);
 
const paymentId = ref<number>();
const period = ref<string>();
const status = ref<number>();
const detailList = ref<HrmSalaryPaymentApi.SalaryPaymentDetail[]>([]);
const loading = ref(false);
const selectedIds = ref<number[]>([]);
const payLoading = ref(false);
 
const isPaid = computed(() => status.value === 10);
 
const columns = [
  { title: '员工姓名', dataIndex: 'userName', width: 100, fixed: 'left' },
  { title: '部门', dataIndex: 'deptName', width: 120 },
  { title: '基本工资', dataIndex: 'baseSalary', width: 100 },
  { title: '绩效工资', dataIndex: 'performanceSalary', width: 100 },
  { title: '社保扣款', dataIndex: 'socialSecurityDeduction', width: 100 },
  { title: '公积金扣款', dataIndex: 'housingFundDeduction', width: 100 },
  { title: '个税扣款', dataIndex: 'taxDeduction', width: 100 },
  { title: '请假扣款', dataIndex: 'leaveDeduction', width: 100 },
  { title: '发放时间', dataIndex: 'paymentTime', width: 160 },
  { title: '实发工资', dataIndex: 'actualSalary', width: 100, fixed: 'right' },
  {
    title: '状态',
    dataIndex: 'status',
    width: 80,
    fixed: 'right',
    key: 'status',
  },
];
 
/** 批量发放 */
async function handleBatchPay() {
  if (selectedIds.value.length === 0) {
    message.warning('请选择要发放的明细');
    return;
  }
  payLoading.value = true;
  try {
    await paySalaryDetail(selectedIds.value);
    message.success('发放成功');
    emit('success');
    // 刷新明细列表
    detailList.value = await getSalaryPaymentDetailList(paymentId.value!);
    selectedIds.value = [];
  } finally {
    payLoading.value = false;
  }
}
 
/** 单条发放 */
async function handlePayDetail(row: HrmSalaryPaymentApi.SalaryPaymentDetail) {
  await paySalaryDetail([row.id!]);
  message.success('发放成功');
  emit('success');
  // 刷新明细列表
  detailList.value = await getSalaryPaymentDetailList(paymentId.value!);
}
 
/** 选择行 */
function onSelectChange(selectedRowKeys: number[]) {
  selectedIds.value = selectedRowKeys;
}
 
const [Modal, modalApi] = useVbenModal({
  async onOpenChange(isOpen: boolean) {
    if (!isOpen) {
      detailList.value = [];
      selectedIds.value = [];
      return;
    }
    const data = modalApi.getData<{ paymentId: number; period: string; status: number }>();
    paymentId.value = data.paymentId;
    period.value = data.period;
    status.value = data.status;
    loading.value = true;
    try {
      detailList.value = await getSalaryPaymentDetailList(data.paymentId);
    } finally {
      loading.value = false;
    }
  },
});
</script>
 
<template>
  <Modal :title="`${period} - 薪资发放明细`" class="w-[1100px]" :footer="null">
    <Alert
      v-if="!isPaid"
      message="勾选需要发放的员工明细,点击批量发放按钮进行发放"
      type="info"
      show-icon
      style="margin-bottom: 16px"
    />
 
    <div v-if="!isPaid" class="mb-3">
      <a-button type="primary" :loading="payLoading" :disabled="selectedIds.length === 0" @click="handleBatchPay">
        批量发放 (已选 {{ selectedIds.length }} 条)
      </a-button>
    </div>
 
    <Table
      :columns="columns"
      :data-source="detailList"
      :loading="loading"
      :pagination="false"
      :scroll="{ x: 1200, y: 400 }"
      :row-selection="!isPaid ? { selectedRowKeys: selectedIds, onChange: onSelectChange } : undefined"
      size="small"
      row-key="id"
      bordered
    >
      <template #bodyCell="{ column, record }">
        <template v-if="column.key === 'status'">
          <Tag :color="record.status === 0 ? 'warning' : 'success'">
            {{ record.status === 0 ? '待发放' : '已发放' }}
          </Tag>
        </template>
        <template v-else-if="column.dataIndex === 'actualSalary'">
          <span class="font-bold text-green-600">{{ record.actualSalary?.toFixed(2) }}</span>
        </template>
        <template v-else-if="column.dataIndex && ['baseSalary', 'performanceSalary', 'socialSecurityDeduction', 'housingFundDeduction', 'taxDeduction', 'leaveDeduction'].includes(column.dataIndex)">
          {{ (record[column.dataIndex] || 0).toFixed(2) }}
        </template>
      </template>
    </Table>
  </Modal>
</template>