From 5b2222922a23a307a97204a01d7c2ca951855c6f Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期一, 19 十月 2026 10:44:23 +0800
Subject: [PATCH] feat(hrm): 薪酬核算列表新增「修改」,支持自定义各金额字段
---
src/views/hrm/salary/calculation/data.ts | 2
src/views/hrm/salary/calculation/modules/form.vue | 120 ++++++++++++++++++++++++++++++++++++++++
src/views/hrm/salary/calculation/index.vue | 10 +++
3 files changed, 131 insertions(+), 1 deletions(-)
diff --git a/src/views/hrm/salary/calculation/data.ts b/src/views/hrm/salary/calculation/data.ts
index bd96225..c02d031 100644
--- a/src/views/hrm/salary/calculation/data.ts
+++ b/src/views/hrm/salary/calculation/data.ts
@@ -101,7 +101,7 @@
},
{
title: '鎿嶄綔',
- width: 120,
+ width: 220,
fixed: 'right',
slots: {
default: 'actions',
diff --git a/src/views/hrm/salary/calculation/index.vue b/src/views/hrm/salary/calculation/index.vue
index 33a1f36..d07d3ea 100644
--- a/src/views/hrm/salary/calculation/index.vue
+++ b/src/views/hrm/salary/calculation/index.vue
@@ -28,8 +28,10 @@
import { $t } from '#/locales';
import { useGridColumns, useGridFormSchema, usePreviewColumns } from './data';
+import FormModal from './modules/form.vue';
// 鏍哥畻寮圭獥鐩稿叧
+const formModalRef = ref();
const calculateVisible = ref(false);
const calculatePeriod = ref<string>();
const calculateDeptId = ref<number>();
@@ -469,6 +471,7 @@
</div>
</Modal>
+ <FormModal ref="formModalRef" @success="handleRefresh" />
<Grid table-title="钖叕鏍哥畻鍒楄〃">
<template #toolbar-tools>
<TableAction
@@ -511,6 +514,13 @@
<TableAction
:actions="[
{
+ label: '淇敼',
+ type: 'link',
+ auth: ['hrm:salary-calculation:calculate'],
+ ifShow: row.status === 0,
+ onClick: () => formModalRef.value?.open(row),
+ },
+ {
label: '纭',
type: 'link',
auth: ['hrm:salary-calculation:confirm'],
diff --git a/src/views/hrm/salary/calculation/modules/form.vue b/src/views/hrm/salary/calculation/modules/form.vue
new file mode 100644
index 0000000..6369f76
--- /dev/null
+++ b/src/views/hrm/salary/calculation/modules/form.vue
@@ -0,0 +1,120 @@
+<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: '鍏朵粬琛ヨ创' },
+];
+
+/** 鎵i櫎椤� */
+const deductionFields = [
+ { key: 'socialSecurityDeduction', label: '绀句繚鎵f' },
+ { key: 'housingFundDeduction', label: '鍏Н閲戞墸娆�' },
+ { key: 'taxDeduction', label: '涓◣鎵f' },
+ { key: 'otherDeduction', label: '鍏朵粬鎵f' },
+ { key: 'leaveDeduction', label: '璇峰亣鎵f' },
+];
+
+/** 瀹炲彂宸ヨ祫锛堝疄鏃惰绠楋紝涓庡悗绔彛寰勪竴鑷达級 */
+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">鎵i櫎椤�</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>
--
Gitblit v1.9.3