From 7c430ce110eca877841f3dcb372f3a5f7bdc4918 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期五, 12 六月 2026 15:29:07 +0800
Subject: [PATCH] 修改社保工资计算
---
src/api/personnelManagement/staffSalaryMain.js | 9 ++
src/views/personnelManagement/monthlyStatistics/components/formDia.vue | 189 ++++++++++++++++++++++++++++++++++-------------
2 files changed, 145 insertions(+), 53 deletions(-)
diff --git a/src/api/personnelManagement/staffSalaryMain.js b/src/api/personnelManagement/staffSalaryMain.js
index a42f96b..08de85c 100644
--- a/src/api/personnelManagement/staffSalaryMain.js
+++ b/src/api/personnelManagement/staffSalaryMain.js
@@ -17,6 +17,14 @@
});
}
+export function staffSalaryMainCalculateByEmployeeId(data) {
+ return request({
+ url: "/staffSalaryMain/calculateByEmployeeId",
+ method: "post",
+ data,
+ });
+}
+
export function staffSalaryMainAdd(data) {
return request({
url: "/staffSalaryMain/add",
@@ -40,4 +48,3 @@
data: ids,
});
}
-
diff --git a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
index 8bb63e9..808c817 100644
--- a/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
+++ b/src/views/personnelManagement/monthlyStatistics/components/formDia.vue
@@ -137,7 +137,7 @@
type="number"
placeholder="0"
size="small"
- @input="row.basicSalary = parseNum(row.basicSalary)" />
+ @input="handleSalaryInput(row)" />
</template>
</el-table-column>
<el-table-column label="璁′欢宸ヨ祫"
@@ -169,7 +169,7 @@
type="number"
placeholder="0"
size="small"
- @input="row.otherIncome = parseNum(row.otherIncome)" />
+ @input="handleSalaryInput(row)" />
</template>
</el-table-column>
<el-table-column label="绀句繚涓汉"
@@ -203,6 +203,16 @@
size="small"
disabled
@input="row.otherDeduct = parseNum(row.otherDeduct)" />
+ </template>
+ </el-table-column>
+ <el-table-column label="绀句繚琛ョ即"
+ minWidth="120">
+ <template #default="{ row }">
+ <el-input v-model.number="row.socialSupplementAmount"
+ type="number"
+ placeholder="0"
+ size="small"
+ @input="handleSalaryInput(row)" />
</template>
</el-table-column>
<el-table-column label="宸ヨ祫涓◣"
@@ -344,6 +354,7 @@
staffSalaryMainAdd,
staffSalaryMainUpdate,
staffSalaryMainCalculateSalary,
+ staffSalaryMainCalculateByEmployeeId,
} from "@/api/personnelManagement/staffSalaryMain.js";
import { userListNoPageByTenantId } from "@/api/system/user.js";
@@ -372,6 +383,8 @@
const selectedEmployees = ref([]);
const bankOptions = ref([]);
const userList = ref([]);
+ const recalcTimers = new Map();
+ const recalcVersions = new Map();
const taxTableData = ref([
{ level: 1, range: "涓嶈秴杩�36000鍏�", rate: 3, quickDeduction: 0 },
{ level: 2, range: "瓒呰繃36000-144000鍏�", rate: 10, quickDeduction: 2520 },
@@ -387,6 +400,115 @@
const n = Number(v);
return isNaN(n) ? 0 : n;
}
+
+ function parseNullableNum(v) {
+ if (v === "" || v == null) return null;
+ const n = Number(v);
+ return isNaN(n) ? null : n;
+ }
+
+ const createEmployeeRow = () => ({
+ staffOnJobId: undefined,
+ id: undefined,
+ staffName: "",
+ postName: "",
+ deptName: "",
+ basicSalary: 0,
+ pieceSalary: 0,
+ hourlySalary: 0,
+ otherIncome: 0,
+ socialPersonal: 0,
+ fundPersonal: 0,
+ otherDeduct: 0,
+ socialSupplementAmount: null,
+ salaryTax: 0,
+ grossSalary: 0,
+ deductSalary: 0,
+ netSalary: 0,
+ remark: "",
+ });
+
+ const normalizeEmployeeRow = (source, fallback = {}) => ({
+ ...createEmployeeRow(),
+ ...fallback,
+ ...source,
+ staffOnJobId: source?.staffOnJobId ?? source?.staffId ?? source?.id ?? fallback.staffOnJobId ?? fallback.id,
+ id: source?.staffOnJobId ?? source?.staffId ?? source?.id ?? fallback.staffOnJobId ?? fallback.id,
+ staffName: source?.staffName ?? fallback.staffName ?? "",
+ postName: source?.postName ?? fallback.postName ?? "",
+ deptName: source?.deptName ?? fallback.deptName ?? "",
+ basicSalary: parseNum(source?.basicSalary ?? fallback.basicSalary),
+ pieceSalary: parseNum(source?.pieceSalary ?? fallback.pieceSalary),
+ hourlySalary: parseNum(source?.hourlySalary ?? fallback.hourlySalary),
+ otherIncome: parseNum(source?.otherIncome ?? fallback.otherIncome),
+ socialPersonal: parseNum(source?.socialPersonal ?? fallback.socialPersonal),
+ fundPersonal: parseNum(source?.fundPersonal ?? fallback.fundPersonal),
+ otherDeduct: parseNum(source?.otherDeduct ?? fallback.otherDeduct),
+ socialSupplementAmount:
+ source?.socialSupplementAmount ?? fallback.socialSupplementAmount ?? null,
+ salaryTax: parseNum(source?.salaryTax ?? fallback.salaryTax),
+ grossSalary: parseNum(source?.grossSalary ?? fallback.grossSalary),
+ deductSalary: parseNum(source?.deductSalary ?? fallback.deductSalary),
+ netSalary: parseNum(source?.netSalary ?? fallback.netSalary),
+ remark: source?.remark ?? fallback.remark ?? "",
+ });
+
+ const applyBackendRow = (targetRow, sourceRow) => {
+ Object.assign(targetRow, normalizeEmployeeRow(sourceRow, targetRow));
+ };
+
+ const clearRowRecalcState = row => {
+ const key = String(row?.staffOnJobId ?? row?.id ?? "");
+ if (!key) return;
+ clearTimeout(recalcTimers.get(key));
+ recalcTimers.delete(key);
+ recalcVersions.delete(key);
+ };
+
+ const resetRecalcState = () => {
+ recalcTimers.forEach(timer => clearTimeout(timer));
+ recalcTimers.clear();
+ recalcVersions.clear();
+ };
+
+ const requestEmployeeRecalculate = row => {
+ const key = String(row?.staffOnJobId ?? row?.id ?? "");
+ if (!key || !form.value.salaryMonth) return;
+ const version = (recalcVersions.get(key) || 0) + 1;
+ recalcVersions.set(key, version);
+ clearTimeout(recalcTimers.get(key));
+ const payload = {
+ staffOnJobId: row.staffOnJobId ?? row.id,
+ salaryMonth: form.value.salaryMonth,
+ staffName: row.staffName ?? "",
+ postName: row.postName ?? "",
+ deptName: row.deptName ?? "",
+ basicSalary: parseNum(row.basicSalary),
+ pieceSalary: parseNum(row.pieceSalary),
+ hourlySalary: parseNum(row.hourlySalary),
+ otherIncome: parseNum(row.otherIncome),
+ socialPersonal: parseNum(row.socialPersonal),
+ fundPersonal: parseNum(row.fundPersonal),
+ otherDeduct: parseNum(row.otherDeduct),
+ socialSupplementAmount: parseNullableNum(row.socialSupplementAmount),
+ remark: row.remark ?? "",
+ };
+ recalcTimers.set(
+ key,
+ setTimeout(() => {
+ staffSalaryMainCalculateByEmployeeId(payload).then(res => {
+ if (recalcVersions.get(key) !== version) return;
+ applyBackendRow(row, res?.data || {});
+ });
+ }, 250)
+ );
+ };
+
+ const handleSalaryInput = row => {
+ row.basicSalary = parseNum(row.basicSalary);
+ row.otherIncome = parseNum(row.otherIncome);
+ requestEmployeeRecalculate(row);
+ };
// 鍩虹璧勬枡琛ㄥ崟
const data = reactive({
@@ -498,6 +620,7 @@
const openDialog = (type, row) => {
nextTick(() => {
+ resetRecalcState();
loadDeptOptions();
loadBankOptions();
loadUserList();
@@ -529,25 +652,7 @@
// 濡傛灉鏈夊憳宸ユ槑缁嗘暟鎹紝鐩存帴鍙嶆樉
if (row.staffSalaryDetailList && row.staffSalaryDetailList.length > 0) {
- employeeList.value = row.staffSalaryDetailList.map(e => ({
- staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
- id: e.staffOnJobId ?? e.staffId ?? e.id,
- staffName: e.staffName ?? "",
- postName: e.postName ?? "",
- deptName: e.deptName ?? "",
- basicSalary: parseNum(e.basicSalary),
- pieceSalary: parseNum(e.pieceSalary),
- hourlySalary: parseNum(e.hourlySalary),
- otherIncome: parseNum(e.otherIncome),
- socialPersonal: parseNum(e.socialPersonal),
- fundPersonal: parseNum(e.fundPersonal),
- otherDeduct: parseNum(e.otherDeduct),
- salaryTax: parseNum(e.salaryTax),
- grossSalary: parseNum(e.grossSalary),
- deductSalary: parseNum(e.deductSalary),
- netSalary: parseNum(e.netSalary),
- remark: e.remark ?? "",
- }));
+ employeeList.value = row.staffSalaryDetailList.map(e => normalizeEmployeeRow(e));
}
}
});
@@ -576,30 +681,23 @@
const id = node.staffId ?? node.id;
if (existIds.has(id)) return;
existIds.add(id);
- employeeList.value.push({
+ const newRow = normalizeEmployeeRow({
staffOnJobId: id,
id,
staffName: node.label,
postName: node.postName ?? node.post ?? "",
deptName: node.deptName ?? "",
- basicSalary: 0,
- pieceSalary: 0,
- hourlySalary: 0,
- otherIncome: 0,
- socialPersonal: 0,
- fundPersonal: 0,
- otherDeduct: 0,
- salaryTax: 0,
- grossSalary: 0,
- deductSalary: 0,
- netSalary: 0,
remark: "",
+ socialSupplementAmount: null,
});
+ employeeList.value.push(newRow);
+ requestEmployeeRecalculate(newRow);
});
addPersonVisible.value = false;
};
const removeEmployee = row => {
+ clearRowRecalcState(row);
employeeList.value = employeeList.value.filter(
e => (e.staffOnJobId || e.id) !== (row.staffOnJobId || row.id)
);
@@ -615,6 +713,7 @@
return;
}
const ids = new Set(selectedEmployees.value.map(e => e.staffOnJobId || e.id));
+ selectedEmployees.value.forEach(item => clearRowRecalcState(item));
employeeList.value = employeeList.value.filter(
e => !ids.has(e.staffOnJobId || e.id)
);
@@ -639,25 +738,8 @@
proxy.$modal.msgWarning("鏈绠楀埌宸ヨ祫鏁版嵁");
return;
}
- employeeList.value = list.map(e => ({
- ...e,
- staffOnJobId: e.staffOnJobId ?? e.staffId ?? e.id,
- staffName: e.staffName,
- postName: e.postName,
- deptName: e.deptName,
- basicSalary: parseNum(e.basicSalary),
- pieceSalary: parseNum(e.pieceSalary),
- hourlySalary: parseNum(e.hourlySalary),
- otherIncome: parseNum(e.otherIncome),
- socialPersonal: parseNum(e.socialPersonal),
- fundPersonal: parseNum(e.fundPersonal),
- otherDeduct: parseNum(e.otherDeduct),
- salaryTax: parseNum(e.salaryTax),
- grossSalary: parseNum(e.grossSalary),
- deductSalary: parseNum(e.deductSalary),
- netSalary: parseNum(e.netSalary),
- remark: e.remark ?? "",
- }));
+ resetRecalcState();
+ employeeList.value = list.map(e => normalizeEmployeeRow(e));
proxy.$modal.msgSuccess("鐢熸垚鎴愬姛");
});
};
@@ -666,6 +748,7 @@
proxy.$modal
.confirm("纭畾娓呯┖褰撳墠鍛樺伐鍒楄〃鍚楋紵")
.then(() => {
+ resetRecalcState();
employeeList.value = [];
})
.catch(() => {});
@@ -712,6 +795,7 @@
socialPersonal: parseNum(e.socialPersonal),
fundPersonal: parseNum(e.fundPersonal),
otherDeduct: parseNum(e.otherDeduct),
+ socialSupplementAmount: parseNum(e.socialSupplementAmount),
salaryTax: parseNum(e.salaryTax),
grossSalary: parseNum(e.grossSalary),
deductSalary: parseNum(e.deductSalary),
@@ -733,6 +817,7 @@
};
const closeDia = () => {
+ resetRecalcState();
dialogVisible.value = false;
emit("close");
};
--
Gitblit v1.9.3