| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |