| | |
| | | import { Page } from '#/packages/effects/common-ui/src'; |
| | | import { downloadFileFromBlobPart } from '#/packages/utils/src'; |
| | | |
| | | import { message, Modal, Form, FormItem, DatePicker, TreeSelect, Table, InputNumber, Alert, Tag } from 'ant-design-vue'; |
| | | import { message, Modal, Form, FormItem, DatePicker, TreeSelect, Table, Input, InputNumber, Alert, Tag } from 'ant-design-vue'; |
| | | |
| | | import { DICT_TYPE } from '#/packages/constants/src'; |
| | | import { getDictLabel } from '#/packages/effects/hooks/src'; |
| | |
| | | previewSalaryCalculation, |
| | | revokeSalaryCalculation, |
| | | saveSalaryCalculation, |
| | | updateSalaryCalculation, |
| | | } from '#/api/hrm/salary/calculation'; |
| | | import { getDeptList } from '#/api/system/dept'; |
| | | import { handleTree } from '#/packages/utils/src'; |
| | |
| | | |
| | | // 核算弹窗相关 |
| | | const formModalRef = ref(); |
| | | const saving = ref(false); |
| | | const calculateVisible = ref(false); |
| | | const calculatePeriod = ref<string>(); |
| | | const calculateDeptId = ref<number>(); |
| | |
| | | async function handleExport() { |
| | | const data = await exportSalaryCalculation(await gridApi.formApi.getValues()); |
| | | downloadFileFromBlobPart({ fileName: '薪酬核算表.xls', source: data }); |
| | | } |
| | | |
| | | /** 列表可编辑的数值字段 */ |
| | | const EDITABLE_NUMBER_FIELDS = [ |
| | | 'baseSalary', |
| | | 'performanceSalary', |
| | | 'overtimePay', |
| | | 'mealAllowance', |
| | | 'transportAllowance', |
| | | 'otherAllowance', |
| | | 'socialSecurityDeduction', |
| | | 'housingFundDeduction', |
| | | 'taxDeduction', |
| | | 'otherDeduction', |
| | | 'leaveDeduction', |
| | | 'workDays', |
| | | 'overtimeHours', |
| | | ]; |
| | | |
| | | /** 文本输入转数字(空值按 0) */ |
| | | function toNumberOrZero(val: any) { |
| | | if (val === '' || val === null || val === undefined) { |
| | | return 0; |
| | | } |
| | | const num = Number(String(val).replace(/,/g, '')); |
| | | return Number.isNaN(num) ? 0 : num; |
| | | } |
| | | |
| | | /** 保存列表内联修改(仅待确认状态) */ |
| | | async function handleSaveEdits() { |
| | | const rows = (gridApi.grid.getData() as any[]).filter((r) => r.status === 0); |
| | | if (rows.length === 0) { |
| | | message.warning('当前页没有待确认的记录可修改'); |
| | | return; |
| | | } |
| | | saving.value = true; |
| | | try { |
| | | for (const row of rows) { |
| | | const payload: any = { ...row }; |
| | | EDITABLE_NUMBER_FIELDS.forEach((f) => { |
| | | payload[f] = toNumberOrZero(payload[f]); |
| | | }); |
| | | await updateSalaryCalculation(payload); |
| | | } |
| | | message.success(`已保存 ${rows.length} 条核算记录`); |
| | | handleRefresh(); |
| | | } finally { |
| | | saving.value = false; |
| | | } |
| | | } |
| | | |
| | | const [Grid, gridApi] = useVbenVxeGrid({ |
| | |
| | | onClick: handleBatchSave, |
| | | }, |
| | | { |
| | | label: '保存修改', |
| | | type: 'primary', |
| | | auth: ['hrm:salary-calculation:calculate'], |
| | | loading: saving, |
| | | onClick: handleSaveEdits, |
| | | }, |
| | | { |
| | | label: $t('ui.actionTitle.export'), |
| | | type: 'primary', |
| | | icon: ACTION_ICON.DOWNLOAD, |
| | |
| | | ]" |
| | | /> |
| | | </template> |
| | | <template #editableCell="{ row, column }"> |
| | | <Input |
| | | v-if="row.status === 0" |
| | | v-model:value="row[column.field]" |
| | | size="small" |
| | | :style="{ width: '100%' }" |
| | | /> |
| | | <span v-else>{{ row[column.field] ?? '' }}</span> |
| | | </template> |
| | | <template #status="{ row }"> |
| | | <Tag :color="row.status === 0 ? 'warning' : row.status === 10 ? 'success' : 'processing'"> |
| | | {{ getDictLabel(DICT_TYPE.HRM_SALARY_STATUS, row.status) }} |