huminmin
4 小时以前 7c430ce110eca877841f3dcb372f3a5f7bdc4918
修改社保工资计算
已修改2个文件
198 ■■■■ 文件已修改
src/api/personnelManagement/staffSalaryMain.js 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/personnelManagement/monthlyStatistics/components/formDia.vue 189 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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,
  });
}
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");
  };