gaoluyang
3 天以前 7a5c5250b66cc6faffbcac9e192073473c50f79f
src/views/hrm/salary/calculation/index.vue
@@ -7,15 +7,20 @@
import { Page } from '#/packages/effects/common-ui/src';
import { downloadFileFromBlobPart } from '#/packages/utils/src';
import { message, Modal, Form, FormItem, DatePicker, TreeSelect, Table, InputNumber, Alert } from 'ant-design-vue';
import { message, Modal, Form, FormItem, DatePicker, TreeSelect, Table, InputNumber, Alert, Tag } from 'ant-design-vue';
import { DICT_TYPE } from '#/packages/constants/src';
import { getDictLabel } from '#/packages/effects/hooks/src';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  calculateSalary,
  confirmSalary,
  deleteSalaryCalculation,
  exportSalaryCalculation,
  getSalaryCalculationPage,
  previewSalaryCalculation,
  revokeSalaryCalculation,
  saveSalaryCalculation,
} from '#/api/hrm/salary/calculation';
import { getDeptList } from '#/api/system/dept';
@@ -102,7 +107,8 @@
  const deduction = (record.socialSecurityDeduction || 0) +
    (record.housingFundDeduction || 0) +
    (record.taxDeduction || 0) +
    (record.otherDeduction || 0);
    (record.otherDeduction || 0) +
    (record.leaveDeduction || 0);
  return income - deduction;
}
@@ -149,7 +155,7 @@
  handleRefresh();
}
/** 批量确认 */
/** 批量确认选中的记录 */
async function handleBatchConfirm() {
  const records = gridApi.grid.getCheckboxRecords() as HrmSalaryCalculationApi.SalaryCalculation[];
  if (records.length === 0) {
@@ -160,6 +166,58 @@
  await confirmSalary(ids);
  message.success('确认成功');
  handleRefresh();
}
/** 批量保存选中的核算记录(仅待确认状态) */
async function handleBatchSave() {
  const records = gridApi.grid.getCheckboxRecords() as HrmSalaryCalculationApi.SalaryCalculation[];
  if (records.length === 0) {
    message.warning('请选择要保存的记录');
    return;
  }
  const pending = records.filter((r) => r.status === 0);
  if (pending.length === 0) {
    message.warning('选中的记录均非待确认状态,无需保存');
    return;
  }
  const first = pending[0];
  if (!first?.period) {
    message.warning('缺少核算周期');
    return;
  }
  await saveSalaryCalculation({ period: first.period, list: pending });
  message.success('批量保存成功');
  handleRefresh();
}
/** 撤销确认(已确认 → 待确认,可重新核算) */
async function handleRevoke(row: HrmSalaryCalculationApi.SalaryCalculation) {
  Modal.confirm({
    title: '撤销确认',
    content: `确定撤销【${row.no}】的确认吗?撤销后可重新核算。`,
    okText: '确定',
    cancelText: '取消',
    onOk: async () => {
      await revokeSalaryCalculation([row.id!]);
      message.success('撤销成功');
      handleRefresh();
    },
  });
}
/** 删除待确认的核算记录 */
async function handleDelete(row: HrmSalaryCalculationApi.SalaryCalculation) {
  Modal.confirm({
    title: '确认删除',
    content: `确定删除【${row.no}】的核算记录吗?删除后需重新核算。`,
    okText: '确定',
    cancelText: '取消',
    onOk: async () => {
      await deleteSalaryCalculation(row.id!);
      message.success('删除成功');
      handleRefresh();
    },
  });
}
/** 导出薪酬核算 */
@@ -178,7 +236,6 @@
    keepSource: true,
    checkboxConfig: {
      highlight: true,
      reserve: true,
    },
    proxyConfig: {
      ajax: {
@@ -189,6 +246,10 @@
            ...formValues,
          }),
      },
    },
    pagingConfig: {
      pageSize: 20,
      pageSizes: [20, 50, 100],
    },
    rowConfig: {
      keyField: 'id',
@@ -257,7 +318,7 @@
        v-if="previewData.length > 0"
        :columns="usePreviewColumns()"
        :data-source="previewData"
        :pagination="false"
        :pagination="{ pageSize: 20, showSizeChanger: true, showTotal: (t) => `共 ${t} 人` }"
        :scroll="{ x: 1800, y: 400 }"
        size="small"
        row-key="userId"
@@ -365,6 +426,16 @@
              @change="(val: number) => updateFieldValue(record, 'otherDeduction', val)"
            />
          </template>
          <template v-else-if="column.dataIndex === 'leaveDeduction'">
            <InputNumber
              v-model:value="record.leaveDeduction"
              :min="0"
              :precision="2"
              size="small"
              style="width: 90px"
              @change="(val: number) => updateFieldValue(record, 'leaveDeduction', val)"
            />
          </template>
          <template v-else-if="column.dataIndex === 'actualSalary'">
            <span class="font-bold text-green-600">{{ record.actualSalary?.toFixed(2) }}</span>
          </template>
@@ -416,6 +487,12 @@
              onClick: handleBatchConfirm,
            },
            {
              label: '批量保存',
              type: 'primary',
              auth: ['hrm:salary-calculation:save'],
              onClick: handleBatchSave,
            },
            {
              label: $t('ui.actionTitle.export'),
              type: 'primary',
              icon: ACTION_ICON.DOWNLOAD,
@@ -424,6 +501,11 @@
            },
          ]"
        />
      </template>
      <template #status="{ row }">
        <Tag :color="row.status === 0 ? 'warning' : row.status === 10 ? 'success' : 'processing'">
          {{ getDictLabel(DICT_TYPE.HRM_SALARY_STATUS, row.status) }}
        </Tag>
      </template>
      <template #actions="{ row }">
        <TableAction
@@ -435,6 +517,21 @@
              ifShow: row.status === 0,
              onClick: handleConfirm.bind(null, row),
            },
            {
              label: '删除',
              type: 'link',
              danger: true,
              auth: ['hrm:salary-calculation:delete'],
              ifShow: row.status === 0,
              onClick: handleDelete.bind(null, row),
            },
            {
              label: '撤销确认',
              type: 'link',
              auth: ['hrm:salary-calculation:confirm'],
              ifShow: row.status === 10,
              onClick: handleRevoke.bind(null, row),
            },
          ]"
        />
      </template>