<script lang="ts" setup>
|
import type { HrmSalaryCalculationApi } from '#/api/hrm/salary/calculation';
|
|
import { computed, ref } from 'vue';
|
|
import { message, Modal, Form, FormItem, Input, InputNumber } from 'ant-design-vue';
|
|
import { updateSalaryCalculation } from '#/api/hrm/salary/calculation';
|
|
const emit = defineEmits(['success']);
|
|
const visible = ref(false);
|
const loading = ref(false);
|
/** 当前编辑的记录(含所有可编辑字段) */
|
const current = ref<Record<string, any>>({});
|
|
/** 收入项 */
|
const incomeFields = [
|
{ key: 'baseSalary', label: '基本工资' },
|
{ key: 'performanceSalary', label: '绩效工资' },
|
{ key: 'overtimePay', label: '加班费' },
|
{ key: 'mealAllowance', label: '餐补' },
|
{ key: 'transportAllowance', label: '交通补贴' },
|
{ key: 'otherAllowance', label: '其他补贴' },
|
];
|
|
/** 扣除项 */
|
const deductionFields = [
|
{ key: 'socialSecurityDeduction', label: '社保扣款' },
|
{ key: 'housingFundDeduction', label: '公积金扣款' },
|
{ key: 'taxDeduction', label: '个税扣款' },
|
{ key: 'otherDeduction', label: '其他扣款' },
|
{ key: 'leaveDeduction', label: '请假扣款' },
|
];
|
|
/** 实发工资(实时计算,与后端口径一致) */
|
const actualSalary = computed(() => {
|
const num = (v: any) => (v === undefined || v === null || v === '' ? 0 : Number(v));
|
const income = incomeFields.reduce((sum, f) => sum + num(current.value[f.key]), 0);
|
const deduction = deductionFields.reduce((sum, f) => sum + num(current.value[f.key]), 0);
|
return Number((income - deduction).toFixed(2));
|
});
|
|
function open(row: HrmSalaryCalculationApi.SalaryCalculation) {
|
current.value = { ...row };
|
visible.value = true;
|
}
|
|
async function handleOk() {
|
loading.value = true;
|
try {
|
await updateSalaryCalculation({
|
...(current.value as HrmSalaryCalculationApi.SalaryCalculation),
|
actualSalary: actualSalary.value,
|
});
|
message.success('修改成功');
|
visible.value = false;
|
emit('success');
|
} finally {
|
loading.value = false;
|
}
|
}
|
|
defineExpose({ open });
|
</script>
|
|
<template>
|
<Modal
|
v-model:open="visible"
|
:title="`修改薪酬核算${current.no ? ' - ' + current.no : ''}`"
|
:width="760"
|
:confirm-loading="loading"
|
ok-text="保存"
|
cancel-text="取消"
|
@ok="handleOk"
|
>
|
<Form layout="vertical" class="mt-2">
|
<div class="mb-2 text-sm font-semibold text-gray-700">收入项</div>
|
<div class="grid grid-cols-3 gap-x-4">
|
<FormItem v-for="f in incomeFields" :key="f.key" :label="f.label">
|
<InputNumber
|
v-model:value="current[f.key]"
|
:min="0"
|
:precision="2"
|
style="width: 100%"
|
/>
|
</FormItem>
|
</div>
|
|
<div class="mb-2 mt-2 text-sm font-semibold text-gray-700">扣除项</div>
|
<div class="grid grid-cols-3 gap-x-4">
|
<FormItem v-for="f in deductionFields" :key="f.key" :label="f.label">
|
<InputNumber
|
v-model:value="current[f.key]"
|
:min="0"
|
:precision="2"
|
style="width: 100%"
|
/>
|
</FormItem>
|
</div>
|
|
<div class="mb-2 mt-2 text-sm font-semibold text-gray-700">考勤 / 其他</div>
|
<div class="grid grid-cols-3 gap-x-4">
|
<FormItem label="出勤天数">
|
<InputNumber v-model:value="current.workDays" :min="0" :max="31" :precision="0" style="width: 100%" />
|
</FormItem>
|
<FormItem label="加班时长(h)">
|
<InputNumber v-model:value="current.overtimeHours" :min="0" :precision="1" style="width: 100%" />
|
</FormItem>
|
<FormItem label="实发工资(自动计算)">
|
<Input :value="actualSalary.toFixed(2)" disabled class="font-bold text-green-600" />
|
</FormItem>
|
</div>
|
|
<FormItem label="备注">
|
<Input.TextArea v-model:value="current.remark" :rows="2" placeholder="请输入备注" />
|
</FormItem>
|
</Form>
|
</Modal>
|
</template>
|