src/views/hrm/salary/payment/index.vue
@@ -2,56 +2,79 @@
import type { VxeTableGridOptions } from '#/adapter/vxe-table';
import type { HrmSalaryPaymentApi } from '#/api/hrm/salary/payment';
import { Page } from '#/packages/effects/common-ui/src';
import { ref } from 'vue';
import { Page, useVbenModal } from '#/packages/effects/common-ui/src';
import { downloadFileFromBlobPart } from '#/packages/utils/src';
import { message } from 'ant-design-vue';
import { message, Tag, DatePicker } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  exportSalaryPayment,
  generateSalaryPayment,
  getSalaryPaymentPage,
  paySalary,
  revokeSalaryPayment,
} from '#/api/hrm/salary/payment';
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema } from './data';
import DetailModal from './modules/detail.vue';
const [DetailModalComp, detailModalApi] = useVbenModal({
  connectedComponent: DetailModal,
  destroyOnClose: true,
});
// 生成台账弹窗
const generateVisible = ref(false);
const generatePeriod = ref<string>();
const generateLoading = ref(false);
/** 刷新表格 */
function handleRefresh() {
  gridApi.query();
}
/** 执行薪资发放 */
async function handlePay() {
  const records = gridApi.grid.getCheckboxRecords() as HrmSalaryPaymentApi.SalaryPayment[];
  if (records.length === 0) {
    message.warning('请选择要发放的记录');
    return;
  }
  const unpaidRecords = records.filter((r) => r.status === 10);
  if (unpaidRecords.length === 0) {
    message.warning('所选记录中没有待发放状态的记录');
    return;
  }
  const ids = unpaidRecords.map((r) => r.id!);
  await paySalary(ids);
  message.success('发放成功');
  handleRefresh();
/** 打开生成台账弹窗 */
function openGenerateModal() {
  generatePeriod.value = undefined;
  generateVisible.value = true;
}
/** 撤销薪资发放 */
async function handleRevoke(row: HrmSalaryPaymentApi.SalaryPayment) {
  await revokeSalaryPayment(row.id!);
  message.success('撤销成功');
/** 生成发放台账 */
async function handleGenerate() {
  if (!generatePeriod.value) {
    message.warning('请选择发放周期');
    return;
  }
  generateLoading.value = true;
  try {
    await generateSalaryPayment(generatePeriod.value);
    message.success('生成发放台账成功');
    generateVisible.value = false;
    handleRefresh();
  } finally {
    generateLoading.value = false;
  }
}
/** 查看明细 */
function handleViewDetail(row: HrmSalaryPaymentApi.SalaryPayment) {
  detailModalApi.setData({ paymentId: row.id, period: row.period, status: row.status }).open();
}
/** 发放薪资 */
async function handlePay(row: HrmSalaryPaymentApi.SalaryPayment) {
  await paySalary(row.id!);
  message.success('发放成功');
  handleRefresh();
}
/** 导出薪资发放 */
async function handleExport() {
  const data = await exportSalaryPayment(await gridApi.formApi.getValues());
  downloadFileFromBlobPart({ fileName: '薪资发放表.xls', source: data });
  downloadFileFromBlobPart({ fileName: '薪资发放台账.xls', source: data });
}
const [Grid, gridApi] = useVbenVxeGrid({
@@ -62,10 +85,6 @@
    columns: useGridColumns(),
    height: 'auto',
    keepSource: true,
    checkboxConfig: {
      highlight: true,
      reserve: true,
    },
    proxyConfig: {
      ajax: {
        query: async ({ page }, formValues) =>
@@ -90,16 +109,45 @@
<template>
  <Page auto-content-height>
    <Grid table-title="薪资发放列表">
    <DetailModalComp @success="handleRefresh" />
    <!-- 生成台账弹窗 -->
    <Modal
      v-model:open="generateVisible"
      title="生成发放台账"
      width="400px"
      :maskClosable="false"
    >
      <Form layout="vertical">
        <FormItem label="发放周期" required>
          <DatePicker
            v-model:value="generatePeriod"
            picker="month"
            format="YYYY-MM"
            valueFormat="YYYY-MM"
            placeholder="请选择发放周期"
            style="width: 100%"
          />
        </FormItem>
      </Form>
      <template #footer>
        <a-button @click="generateVisible = false">取消</a-button>
        <a-button type="primary" :loading="generateLoading" @click="handleGenerate">
          确定
        </a-button>
      </template>
    </Modal>
    <Grid table-title="薪资发放台账">
      <template #toolbar-tools>
        <TableAction
          :actions="[
            {
              label: '发放',
              label: '生成台账',
              type: 'primary',
              icon: ACTION_ICON.EDIT,
              auth: ['hrm:salary-payment:pay'],
              onClick: handlePay,
              icon: ACTION_ICON.ADD,
              auth: ['hrm:salary-payment:generate'],
              onClick: openGenerateModal,
            },
            {
              label: $t('ui.actionTitle.export'),
@@ -111,17 +159,28 @@
          ]"
        />
      </template>
      <template #status="{ row }">
        <Tag :color="row.status === 0 ? 'warning' : 'success'">
          {{ row.status === 0 ? '待发放' : '已发放' }}
        </Tag>
      </template>
      <template #actions="{ row }">
        <TableAction
          :actions="[
            {
              label: '撤销',
              label: '查看明细',
              type: 'link',
              auth: ['hrm:salary-payment:revoke'],
              ifShow: row.status === 20,
              onClick: handleViewDetail.bind(null, row),
            },
            {
              label: '发放',
              type: 'link',
              icon: ACTION_ICON.EDIT,
              auth: ['hrm:salary-payment:pay'],
              ifShow: row.status === 0,
              popConfirm: {
                title: '确认撤销该发放记录吗?',
                confirm: handleRevoke.bind(null, row),
                title: '确认发放该周期的薪资吗?',
                confirm: handlePay.bind(null, row),
              },
            },
          ]"