From 8a0d57c6edb61940cdce72862548f30aae1380c9 Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期一, 09 三月 2026 09:21:17 +0800
Subject: [PATCH] yys 员工工资生成逻辑

---
 src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java             |    3 
 src/main/java/com/ruoyi/staff/service/impl/BankServiceImpl.java                  |   20 +
 src/main/java/com/ruoyi/staff/controller/StaffSalaryDetailController.java        |   18 +
 src/main/resources/mapper/system/SysUserDeptMapper.xml                           |   18 
 src/main/java/com/ruoyi/staff/mapper/BankMapper.java                             |   18 +
 src/main/java/com/ruoyi/staff/service/StaffSalaryDetailService.java              |   16 
 src/main/resources/mapper/staff/BankMapper.xml                                   |   11 
 src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java                        |  102 +++++
 src/main/resources/mapper/staff/StaffSalaryDetailMapper.xml                      |   31 +
 src/main/java/com/ruoyi/staff/service/BankService.java                           |   16 
 src/main/java/com/ruoyi/staff/mapper/StaffSalaryDetailMapper.java                |   18 +
 src/main/java/com/ruoyi/staff/mapper/StaffSalaryMainMapper.java                  |   18 +
 src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java            |   16 
 src/main/java/com/ruoyi/staff/controller/BankController.java                     |   61 +++
 src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java                          |   93 +++++
 src/main/resources/mapper/staff/StaffSalaryMainMapper.xml                        |   19 +
 src/main/java/com/ruoyi/staff/pojo/Bank.java                                     |   33 +
 src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml                  |   48 +
 src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java          |   72 ++++
 src/main/java/com/ruoyi/staff/service/impl/StaffSalaryDetailServiceImpl.java     |   20 +
 src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java       |  142 +++++++
 src/main/java/com/ruoyi/staff/controller/TaxCalculator.java                      |  102 +++++
 src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java                |   29 +
 src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java |  140 +++++++
 24 files changed, 1,036 insertions(+), 28 deletions(-)

diff --git a/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java b/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
index d6bed98..8c0ca53 100644
--- a/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
+++ b/src/main/java/com/ruoyi/project/system/mapper/SysUserDeptMapper.java
@@ -7,9 +7,12 @@
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Map;
 
 @Mapper
 public interface SysUserDeptMapper extends BaseMapper<SysUserDept> {
 
     List<SysUserDeptVo> userLoginFacotryList(@Param("userDeptVo") SysUserDeptVo userDeptVo);
+
+    List<Map<String, Object>> setSchemeApplicableStaffUserInfo(@Param("ids") List<Long> ids);
 }
diff --git a/src/main/java/com/ruoyi/staff/controller/BankController.java b/src/main/java/com/ruoyi/staff/controller/BankController.java
new file mode 100644
index 0000000..5d3a9fc
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/controller/BankController.java
@@ -0,0 +1,61 @@
+package com.ruoyi.staff.controller;
+
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.staff.pojo.Bank;
+import com.ruoyi.staff.service.BankService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 閾惰绠$悊琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 03:40:54
+ */
+@Api(tags = "閾惰绠$悊琛�")
+@RestController
+@RequestMapping("/bank")
+public class BankController {
+
+    @Autowired
+    private BankService bankService;
+
+    @GetMapping("/list")
+    public AjaxResult list() {
+        return AjaxResult.success(bankService.list());
+    }
+
+    @PostMapping("/add")
+    @ApiOperation("鏂板閾惰绠$悊琛�")
+    @Transactional(rollbackFor = Exception.class)
+    @Log(title = "閾惰绠$悊琛�", businessType = BusinessType.INSERT)
+    public AjaxResult add(@RequestBody Bank bank) {
+        return AjaxResult.success(bankService.save(bank));
+    }
+
+    @PostMapping("/update")
+    @ApiOperation("鏇存柊閾惰绠$悊琛�")
+    @Transactional(rollbackFor = Exception.class)
+    @Log(title = "閾惰绠$悊琛�", businessType = BusinessType.UPDATE)
+    public AjaxResult update(@RequestBody Bank bank) {
+        return AjaxResult.success(bankService.updateById(bank));
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("鍒犻櫎閾惰绠$悊琛�")
+    @Transactional(rollbackFor = Exception.class)
+    @Log(title = "閾惰绠$悊琛�", businessType = BusinessType.DELETE)
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        return AjaxResult.success(bankService.removeBatchByIds(ids));
+    }
+
+}
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffSalaryDetailController.java b/src/main/java/com/ruoyi/staff/controller/StaffSalaryDetailController.java
new file mode 100644
index 0000000..b0b2553
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/controller/StaffSalaryDetailController.java
@@ -0,0 +1,18 @@
+package com.ruoyi.staff.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫鏄庣粏琛� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:24:35
+ */
+@RestController
+@RequestMapping("/staffSalaryDetail")
+public class StaffSalaryDetailController {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java b/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
new file mode 100644
index 0000000..51e8002
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/controller/StaffSalaryMainController.java
@@ -0,0 +1,72 @@
+package com.ruoyi.staff.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.aspectj.lang.annotation.Log;
+import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.staff.pojo.StaffSalaryMain;
+import com.ruoyi.staff.service.StaffSalaryMainService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.aspectj.weaver.loadtime.Aj;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫涓昏〃 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:22:05
+ */
+@Api(tags = "鍛樺伐宸ヨ祫涓昏〃")
+@RestController
+@RequestMapping("/staffSalaryMain")
+public class StaffSalaryMainController {
+
+    @Autowired
+    private StaffSalaryMainService staffSalaryMainService;
+
+    @GetMapping("/listPage")
+    @ApiOperation("鍛樺伐宸ヨ祫涓昏〃鍒嗛〉鏌ヨ")
+    public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) {
+        return staffSalaryMainService.listPage(page, staffSalaryMain);
+    }
+
+    @ApiOperation("閫氳繃閮ㄩ棬ids鑾峰彇鐢ㄦ埛淇℃伅璁$畻姣忎釜鍛樺伐鐨勫伐璧�")
+    @PostMapping("/calculateSalary")
+    public AjaxResult calculateSalary(@RequestBody List<Long> ids) {
+        return staffSalaryMainService.calculateSalary(ids);
+    }
+
+    @PostMapping("/add")
+    @ApiOperation("鏂板缓宸ヨ祫琛�")
+    @Log(title = "鏂板缓宸ヨ祫琛�", businessType = BusinessType.INSERT)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult add(@RequestBody StaffSalaryMain staffSalaryMain) {
+        return staffSalaryMainService.add(staffSalaryMain);
+    }
+
+    @PostMapping("/update")
+    @ApiOperation("淇敼宸ヨ祫琛�")
+    @Log(title = "淇敼宸ヨ祫琛�", businessType = BusinessType.UPDATE)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult updateStaffSalaryMain(@RequestBody StaffSalaryMain staffSalaryMain) {
+        return staffSalaryMainService.updateStaffSalaryMain(staffSalaryMain);
+    }
+
+    @DeleteMapping("/delete")
+    @ApiOperation("鍒犻櫎宸ヨ祫琛�")
+    @Log(title = "鍒犻櫎宸ヨ祫琛�", businessType = BusinessType.DELETE)
+    @Transactional(rollbackFor = Exception.class)
+    public AjaxResult delete(@RequestBody List<Long> ids) {
+        return staffSalaryMainService.delete(ids);
+    }
+
+
+
+}
diff --git a/src/main/java/com/ruoyi/staff/controller/TaxCalculator.java b/src/main/java/com/ruoyi/staff/controller/TaxCalculator.java
new file mode 100644
index 0000000..cbe9742
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/controller/TaxCalculator.java
@@ -0,0 +1,102 @@
+package com.ruoyi.staff.controller;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鏈堝害涓◣璁$畻宸ュ叿绫伙紙浠呴渶鏈堝害鏀跺叆銆佺ぞ淇濅釜浜恒�佸叕绉噾涓汉涓変釜鍙傛暟锛�
+ */
+public class TaxCalculator {
+    // 鏈堝害鍏嶅緛棰濓紙5000鍏冿級
+    private static final BigDecimal MONTHLY_EXEMPTION = new BigDecimal("5000");
+
+    // 鏈堝害涓◣绋庣巼琛細[搴旂撼绋庢墍寰楅涓婇檺, 绋庣巼, 閫熺畻鎵i櫎鏁癩
+    private static final List<TaxBracket> MONTHLY_TAX_BRACKETS = new ArrayList<>();
+
+    // 闈欐�佸垵濮嬪寲绋庣巼琛紙鎸夋湀搴︽崲绠楋紝瀵瑰簲鍏ㄥ勾琛�/12锛�
+    static {
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("3000"),  new BigDecimal("0.03"),  new BigDecimal("0")));
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("12000"), new BigDecimal("0.10"),  new BigDecimal("210")));
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("25000"), new BigDecimal("0.20"),  new BigDecimal("1410")));
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("35000"), new BigDecimal("0.25"),  new BigDecimal("2660")));
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("55000"), new BigDecimal("0.30"),  new BigDecimal("4410")));
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("80000"), new BigDecimal("0.35"),  new BigDecimal("7160")));
+        MONTHLY_TAX_BRACKETS.add(new TaxBracket(new BigDecimal("999999"), new BigDecimal("0.45"), new BigDecimal("15160")));
+    }
+
+    // 绋庣巼琛ㄥ唴閮ㄧ被
+    private static class TaxBracket {
+        final BigDecimal max;       // 璇ユ。浣嶅簲绾崇◣鎵�寰楅涓婇檺
+        final BigDecimal rate;      // 绋庣巼
+        final BigDecimal deduction; // 閫熺畻鎵i櫎鏁�
+
+        TaxBracket(BigDecimal max, BigDecimal rate, BigDecimal deduction) {
+            this.max = max;
+            this.rate = rate;
+            this.deduction = deduction;
+        }
+    }
+
+    /**
+     * 璁$畻鍗曟湀涓汉鎵�寰楃◣锛堜粎闇�涓変釜鍙傛暟锛�
+     * @param monthlyIncome 鏈堝害鏀跺叆锛堢◣鍓嶏級
+     * @param socialSecurity 绀句繚涓汉缂寸撼閲戦
+     * @param fund 鍏Н閲戜釜浜虹即绾抽噾棰�
+     * @return 鏈堝害搴旂即涓◣锛堜繚鐣�2浣嶅皬鏁帮級
+     */
+    public static BigDecimal calculateMonthlyTax(
+            BigDecimal monthlyIncome,
+            BigDecimal socialSecurity,
+            BigDecimal fund
+    ) {
+        // 1. 绌哄��/璐熸暟澶勭悊锛氬弬鏁颁负null鎴栬礋鏁版椂鎸�0璁$畻
+        monthlyIncome = (monthlyIncome == null || monthlyIncome.compareTo(BigDecimal.ZERO) < 0) ? BigDecimal.ZERO : monthlyIncome;
+        socialSecurity = (socialSecurity == null || socialSecurity.compareTo(BigDecimal.ZERO) < 0) ? BigDecimal.ZERO : socialSecurity;
+        fund = (fund == null || fund.compareTo(BigDecimal.ZERO) < 0) ? BigDecimal.ZERO : fund;
+
+        // 2. 璁$畻鏈堝害搴旂撼绋庢墍寰楅 = 鏈堝害鏀跺叆 - 5000鍏嶅緛棰� - 绀句繚涓汉 - 鍏Н閲戜釜浜�
+        BigDecimal taxableIncome = monthlyIncome
+                .subtract(MONTHLY_EXEMPTION)
+                .subtract(socialSecurity)
+                .subtract(fund);
+
+        // 3. 搴旂撼绋庢墍寰楅鈮�0鏃讹紝涓◣涓�0
+        if (taxableIncome.compareTo(BigDecimal.ZERO) <= 0) {
+            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
+        }
+
+        // 4. 鍖归厤绋庣巼妗d綅璁$畻涓◣
+        for (TaxBracket bracket : MONTHLY_TAX_BRACKETS) {
+            if (taxableIncome.compareTo(bracket.max) <= 0) {
+                return taxableIncome.multiply(bracket.rate)
+                        .subtract(bracket.deduction)
+                        .setScale(2, RoundingMode.HALF_UP);
+            }
+        }
+
+        // 5. 瓒呰繃鏈�楂樻。浣嶏紙80000鍏冿級鐨勬儏鍐�
+        TaxBracket lastBracket = MONTHLY_TAX_BRACKETS.get(MONTHLY_TAX_BRACKETS.size() - 1);
+        return taxableIncome.multiply(lastBracket.rate)
+                .subtract(lastBracket.deduction)
+                .setScale(2, RoundingMode.HALF_UP);
+    }
+
+    // 娴嬭瘯绀轰緥
+    public static void main(String[] args) {
+        // 绀轰緥1锛氭湀鏀跺叆10000锛岀ぞ淇濅釜浜�800锛屽叕绉噾涓汉500
+        BigDecimal income1 = new BigDecimal("10000");
+        BigDecimal social1 = new BigDecimal("800");
+        BigDecimal fund1 = new BigDecimal("500");
+        BigDecimal tax1 = calculateMonthlyTax(income1, social1, fund1);
+        System.out.println("鏈堟敹鍏�10000锛岀ぞ淇�800锛屽叕绉噾500锛屼釜绋庯細" + tax1 + " 鍏�"); // 璁$畻缁撴灉锛�111.00 鍏�
+
+        // 绀轰緥2锛氭湀鏀跺叆5000锛岀ぞ淇�500锛屽叕绉噾200
+        BigDecimal income2 = new BigDecimal("5000");
+        BigDecimal social2 = new BigDecimal("500");
+        BigDecimal fund2 = new BigDecimal("200");
+        BigDecimal tax2 = calculateMonthlyTax(income2, social2, fund2);
+        System.out.println("鏈堟敹鍏�5000锛岀ぞ淇�500锛屽叕绉噾200锛屼釜绋庯細" + tax2 + " 鍏�"); // 璁$畻缁撴灉锛�0.00 鍏�
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ruoyi/staff/mapper/BankMapper.java b/src/main/java/com/ruoyi/staff/mapper/BankMapper.java
new file mode 100644
index 0000000..0752746
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/mapper/BankMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.staff.mapper;
+
+import com.ruoyi.staff.pojo.Bank;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 閾惰绠$悊琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 03:40:54
+ */
+@Mapper
+public interface BankMapper extends BaseMapper<Bank> {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java b/src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java
index ebb385d..f58b76a 100644
--- a/src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java
+++ b/src/main/java/com/ruoyi/staff/mapper/SchemeApplicableStaffMapper.java
@@ -2,7 +2,11 @@
 
 import com.ruoyi.staff.pojo.SchemeApplicableStaff;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.staff.pojo.SchemeInsuranceDetail;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * <p>
@@ -14,5 +18,17 @@
  */
 @Mapper
 public interface SchemeApplicableStaffMapper extends BaseMapper<SchemeApplicableStaff> {
+    /**
+     * 鏍规嵁浜哄憳ID鏌ヨ瀵瑰簲鐨勭ぞ淇濇柟妗堬紙鏍稿績鏂规硶锛�
+     * @param staffId 浜哄憳ID
+     * @return 璇ヤ汉鍛橀�傜敤鐨勬墍鏈夌ぞ淇濇柟妗堝垪琛�
+     */
+    List<SchemeApplicableStaff> selectSchemeByStaffId(@Param("staffId") Long staffId);
 
+    /**
+     * 鏍规嵁绀句繚鏂规ID鏌ヨ瀵瑰簲鐨勬槑缁嗗垪琛�
+     * @param schemeId 绀句繚鏂规ID
+     * @return 鏂规鏄庣粏鍒楄〃
+     */
+    List<SchemeInsuranceDetail> selectDetailBySchemeId(@Param("schemeId") Long schemeId);
 }
diff --git a/src/main/java/com/ruoyi/staff/mapper/StaffSalaryDetailMapper.java b/src/main/java/com/ruoyi/staff/mapper/StaffSalaryDetailMapper.java
new file mode 100644
index 0000000..bc4b9a9
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/mapper/StaffSalaryDetailMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.staff.mapper;
+
+import com.ruoyi.staff.pojo.StaffSalaryDetail;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫鏄庣粏琛� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:24:35
+ */
+@Mapper
+public interface StaffSalaryDetailMapper extends BaseMapper<StaffSalaryDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/mapper/StaffSalaryMainMapper.java b/src/main/java/com/ruoyi/staff/mapper/StaffSalaryMainMapper.java
new file mode 100644
index 0000000..eca5dbe
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/mapper/StaffSalaryMainMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.staff.mapper;
+
+import com.ruoyi.staff.pojo.StaffSalaryMain;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫涓昏〃 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:22:05
+ */
+@Mapper
+public interface StaffSalaryMainMapper extends BaseMapper<StaffSalaryMain> {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/pojo/Bank.java b/src/main/java/com/ruoyi/staff/pojo/Bank.java
new file mode 100644
index 0000000..482703b
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/pojo/Bank.java
@@ -0,0 +1,33 @@
+package com.ruoyi.staff.pojo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 閾惰绠$悊琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 03:40:54
+ */
+@Getter
+@Setter
+@TableName("bank")
+@ApiModel(value = "Bank瀵硅薄", description = "閾惰绠$悊琛�")
+public class Bank implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("閾惰鍚嶇О")
+    private String bankName;
+}
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
new file mode 100644
index 0000000..1ab10ab
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryDetail.java
@@ -0,0 +1,102 @@
+package com.ruoyi.staff.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫鏄庣粏琛�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:24:35
+ */
+@Getter
+@Setter
+@TableName("staff_salary_detail")
+@ApiModel(value = "StaffSalaryDetail瀵硅薄", description = "鍛樺伐宸ヨ祫鏄庣粏琛�")
+public class StaffSalaryDetail implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty("涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("鍏宠仈宸ヨ祫涓昏〃ID")
+    private Long mainId;
+
+    @ApiModelProperty("鍏宠仈staff_on_job琛ㄤ富閿甀D")
+    private Long staffOnJobId;
+
+    @ApiModelProperty("鍛樺伐濮撳悕")
+    private String staffName;
+
+    @ApiModelProperty("鑱屼綅鍚嶇О")
+    private String postName;
+
+    @ApiModelProperty("閮ㄩ棬鍚嶇О")
+    private String deptName;
+
+    @ApiModelProperty("鍩烘湰宸ヨ祫")
+    private BigDecimal basicSalary;
+
+    @ApiModelProperty("璁′欢宸ヨ祫")
+    private BigDecimal pieceSalary;
+
+    @ApiModelProperty("璁℃椂宸ヨ祫")
+    private BigDecimal hourlySalary;
+
+    @ApiModelProperty("鍏朵粬鏀跺叆")
+    private BigDecimal otherIncome;
+
+    @ApiModelProperty("绀句繚涓汉")
+    private BigDecimal socialPersonal;
+
+    @ApiModelProperty("鍏Н閲戜釜浜�")
+    private BigDecimal fundPersonal;
+
+    @ApiModelProperty("鍏朵粬鏀嚭")
+    private BigDecimal otherDeduct;
+
+    @ApiModelProperty("宸ヨ祫涓◣")
+    private BigDecimal salaryTax;
+
+    @ApiModelProperty("搴斿彂宸ヨ祫")
+    private BigDecimal grossSalary;
+
+    @ApiModelProperty("搴旀墸宸ヨ祫")
+    private BigDecimal deductSalary;
+
+    @ApiModelProperty("瀹炲彂宸ヨ祫")
+    private BigDecimal netSalary;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @ApiModelProperty("淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+}
diff --git a/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java
new file mode 100644
index 0000000..191406b
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/pojo/StaffSalaryMain.java
@@ -0,0 +1,93 @@
+package com.ruoyi.staff.pojo;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫涓昏〃
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:22:05
+ */
+@Getter
+@Setter
+@TableName("staff_salary_main")
+@ApiModel(value = "StaffSalaryMain瀵硅薄", description = "鍛樺伐宸ヨ祫涓昏〃")
+public class StaffSalaryMain implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableField(exist = false)
+    private List<StaffSalaryDetail> staffSalaryDetailList;
+
+    @ApiModelProperty("涓婚敭ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty("瀹℃牳浜篒d")
+    private Long auditUserId;
+
+    @ApiModelProperty("瀹℃牳浜哄悕绉�")
+    private String auditUserName;
+
+    @ApiModelProperty("宸ヨ祫涓婚")
+    private String salaryTitle;
+
+    @ApiModelProperty("鍏宠仈閮ㄩ棬ID锛屽涓敤閫楀彿鍒嗛殧")
+    private String deptIds;
+
+    @ApiModelProperty("宸ヨ祫鏈堜唤锛屾牸寮忥細yyyy-MM")
+    private String salaryMonth;
+
+    @ApiModelProperty("澶囨敞")
+    private String remark;
+
+    @ApiModelProperty("鐘舵�侊細1-鑽夌 2-瀹℃牳鏈�氳繃 3-寰呭鏍� 4-寰呭彂鏀� 5-宸插彂鏀�")
+    private Integer status;
+
+    @ApiModelProperty("宸ヨ祫鎬婚")
+    private BigDecimal totalSalary;
+
+    @ApiModelProperty("鏀粯閾惰")
+    private String payBank;
+
+    @TableField(exist = false)
+    @ApiModelProperty("鍒涘缓浜�")
+    private String createUserName;
+
+    @ApiModelProperty("鍙戞斁鏃堕棿")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING)
+    private LocalDateTime payTime;
+
+    @ApiModelProperty("鍒涘缓鏃堕棿")
+    @TableField(fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8",shape = JsonFormat.Shape.STRING)
+    private LocalDateTime createTime;
+
+    @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUser;
+
+    @ApiModelProperty("淇敼鏃堕棿")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty("淇敼鐢ㄦ埛")
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private Long updateUser;
+}
diff --git a/src/main/java/com/ruoyi/staff/service/BankService.java b/src/main/java/com/ruoyi/staff/service/BankService.java
new file mode 100644
index 0000000..98c229a
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/BankService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.staff.service;
+
+import com.ruoyi.staff.pojo.Bank;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 閾惰绠$悊琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 03:40:54
+ */
+public interface BankService extends IService<Bank> {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/service/StaffSalaryDetailService.java b/src/main/java/com/ruoyi/staff/service/StaffSalaryDetailService.java
new file mode 100644
index 0000000..f600c56
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/StaffSalaryDetailService.java
@@ -0,0 +1,16 @@
+package com.ruoyi.staff.service;
+
+import com.ruoyi.staff.pojo.StaffSalaryDetail;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫鏄庣粏琛� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:24:35
+ */
+public interface StaffSalaryDetailService extends IService<StaffSalaryDetail> {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java b/src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java
new file mode 100644
index 0000000..bb90d61
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/StaffSalaryMainService.java
@@ -0,0 +1,29 @@
+package com.ruoyi.staff.service;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.staff.pojo.StaffSalaryMain;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫涓昏〃 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:22:05
+ */
+public interface StaffSalaryMainService extends IService<StaffSalaryMain> {
+
+    AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain);
+
+    AjaxResult add(StaffSalaryMain staffSalaryMain);
+
+    AjaxResult updateStaffSalaryMain(StaffSalaryMain staffSalaryMain);
+
+    AjaxResult delete(List<Long> ids);
+
+    AjaxResult calculateSalary(List<Long> ids);
+}
diff --git a/src/main/java/com/ruoyi/staff/service/impl/BankServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/BankServiceImpl.java
new file mode 100644
index 0000000..74ab302
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/impl/BankServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.staff.service.impl;
+
+import com.ruoyi.staff.pojo.Bank;
+import com.ruoyi.staff.mapper.BankMapper;
+import com.ruoyi.staff.service.BankService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 閾惰绠$悊琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 03:40:54
+ */
+@Service
+public class BankServiceImpl extends ServiceImpl<BankMapper, Bank> implements BankService {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
index f06704d..e8d3982 100644
--- a/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
+++ b/src/main/java/com/ruoyi/staff/service/impl/SchemeApplicableStaffServiceImpl.java
@@ -10,19 +10,24 @@
 import com.ruoyi.project.system.mapper.SysDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserDeptMapper;
 import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.staff.controller.TaxCalculator;
+import com.ruoyi.staff.dto.StaffOnJobDto;
 import com.ruoyi.staff.mapper.SchemeInsuranceDetailMapper;
+import com.ruoyi.staff.mapper.StaffOnJobMapper;
 import com.ruoyi.staff.pojo.SchemeApplicableStaff;
 import com.ruoyi.staff.mapper.SchemeApplicableStaffMapper;
 import com.ruoyi.staff.pojo.SchemeInsuranceDetail;
+import com.ruoyi.staff.pojo.StaffOnJob;
+import com.ruoyi.staff.service.IStaffOnJobService;
 import com.ruoyi.staff.service.SchemeApplicableStaffService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
+import javax.annotation.Resource;
+import java.math.BigDecimal;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -50,6 +55,9 @@
 
     @Autowired
     private SysDeptMapper sysDeptMapper;
+
+    @Autowired
+    private StaffOnJobMapper staffOnJobMapper;
 
 
     @Override
@@ -88,22 +96,19 @@
 
     public void setSchemeApplicableStaffUserInfo(SchemeApplicableStaff schemeApplicableStaff) {
         // 閫氳繃閮ㄩ棬鑾峰彇浜哄憳id
-        List<SysUserDept> sysUserDepts = sysUserDeptMapper.selectList(new LambdaQueryWrapper<SysUserDept>()
-                .in(SysUserDept::getDeptId, schemeApplicableStaff.getDeptIds()));
-        if(CollectionUtils.isEmpty(sysUserDepts)){
+        String[] split = schemeApplicableStaff.getDeptIds().split(",");
+        List<StaffOnJob> staffOnJobs = staffOnJobMapper.selectList(new LambdaQueryWrapper<StaffOnJob>()
+                .in(StaffOnJob::getSysDeptId, Arrays.stream(split).map(Long::valueOf).collect(Collectors.toList())));
+        if(CollectionUtils.isEmpty(staffOnJobs)){
             throw new IllegalArgumentException("閮ㄩ棬涓嬫棤鍛樺伐");
         }
-        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(sysUserDepts.stream().map(SysUserDept::getUserId).collect(Collectors.toList()));
-        if(CollectionUtils.isEmpty(sysUsers)){
-            throw new IllegalArgumentException("閮ㄩ棬涓嬫棤鍛樺伐");
-        }
-        schemeApplicableStaff.setStaffIds(sysUsers
+        schemeApplicableStaff.setStaffIds(staffOnJobs
                 .stream()
-                .map(SysUser::getUserId)
+                .map(StaffOnJob::getId)
                 .filter(Objects::nonNull)         // 杩囨护鎺� null 鍊�
                 .map(String::valueOf)
                 .collect(Collectors.joining( ",")));
-        schemeApplicableStaff.setStaffNames(sysUsers.stream().map(SysUser::getNickName).collect(Collectors.joining(",")));
+        schemeApplicableStaff.setStaffNames(staffOnJobs.stream().map(StaffOnJob::getStaffName).collect(Collectors.joining(",")));
     }
 
     @Override
@@ -150,4 +155,113 @@
                 .in(SchemeInsuranceDetail::getSchemeId, ids));
         return AjaxResult.success(delete);
     }
+
+    /**
+     * 閫氳繃鍛樺伐id璁$畻绀句繚鏂规
+     * @param id
+     */
+    public void calculateByEmployeeId(Integer id,Map<String, Object> map) {
+        // 1. 鍏ュ弬鏍¢獙
+        if (id == null) {
+            return; // 鎴栬繑鍥炵┖鍒楄〃锛屾牴鎹笟鍔¢渶姹傝皟鏁�
+        }
+        Long staffId = id.longValue();
+        // 绀句繚閲戦
+        BigDecimal schemeAmount = new BigDecimal("0.00");
+        // 鍏Н閲戦噾棰�
+        BigDecimal gjj = new BigDecimal("0.00");
+        // 鍩烘湰宸ヨ祫
+        BigDecimal basicSalary = new BigDecimal("0.00");
+        map.put("gjj", gjj); // 鍏Н閲�
+        map.put("schemeAmount", schemeAmount); // 绀句繚閲戦
+        map.put("basicSalary", basicSalary); // 鍩烘湰宸ヨ祫
+        // 涓◣閲戦
+        BigDecimal salaryTax = new BigDecimal("0.00");
+        map.put("salaryTax", salaryTax);
+        // 璁′欢宸ヨ祫
+        BigDecimal pieceSalary = new BigDecimal("0.00");
+        map.put("pieceSalary", pieceSalary);
+        // 璁℃椂宸ヨ祫
+        BigDecimal hourlySalary = new BigDecimal("0.00");
+        map.put("hourlySalary", hourlySalary);
+        // 鍏朵粬鏀跺叆
+        BigDecimal otherIncome = new BigDecimal("0.00");
+        map.put("otherIncome", otherIncome);
+        // 鍏朵粬鏀嚭
+        BigDecimal otherDeduct = new BigDecimal("0.00");
+        map.put("otherDeduct", otherDeduct);
+        // 搴斿彂宸ヨ祫
+        BigDecimal grossSalary = new BigDecimal("0.00");
+        map.put("grossSalary", grossSalary);
+        // 搴旀墸宸ヨ祫
+        BigDecimal deductSalary = new BigDecimal("0.00");
+        map.put("deductSalary", deductSalary);
+        // 瀹炲彂宸ヨ祫
+        BigDecimal netSalary = new BigDecimal("0.00");
+        map.put("netSalary", netSalary);
+        // 璋冪敤鍩烘湰宸ヨ祫
+        StaffOnJob staffOnJobDto = staffOnJobMapper.selectById(staffId);
+        if(staffOnJobDto == null){
+            return;
+        }
+        basicSalary = staffOnJobDto.getBasicSalary();
+        map.put("basicSalary", basicSalary);
+        // 搴斿彂宸ヨ祫
+        map.put("grossSalary", basicSalary);
+        // 涓◣閲戦锛堟棤绀句繚鐗堬級
+        BigDecimal bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, schemeAmount, gjj);
+        map.put("salaryTax", bigDecimal);
+        // 2. 鏌ヨ璇ヤ汉鍛樺搴旂殑绀句繚鏂规
+        List<SchemeApplicableStaff> schemeList = schemeApplicableStaffMapper.selectSchemeByStaffId(staffId);
+        if (CollectionUtils.isEmpty(schemeList)) {
+            return; // 鏃犲尮閰嶆柟妗堬紝杩斿洖绌哄垪琛�
+        }
+        // 3. 涓烘瘡涓柟妗堝叧鑱旀槑缁嗗垪琛�
+        for (SchemeApplicableStaff scheme : schemeList) {
+            List<SchemeInsuranceDetail> detailList = schemeApplicableStaffMapper.selectDetailBySchemeId(scheme.getId());
+            // 鏍规嵁鏄庣粏鍒楄〃璁$畻绀句繚缂磋垂閲戦
+            if(CollectionUtils.isEmpty(detailList)){
+                continue;
+            }
+            for (SchemeInsuranceDetail detail : detailList) {
+                if("浣忔埧鍏Н閲�".equals(detail.getInsuranceType())){
+                    gjj = gjj.add(calculateByEmployeeIdType(detail.getInsuranceType(),gjj, staffOnJobDto, detail));
+                }else{
+                    schemeAmount = schemeAmount.add(calculateByEmployeeIdType(detail.getInsuranceType(),schemeAmount, staffOnJobDto, detail));
+                }
+            }
+        }
+        map.put("schemeAmount", schemeAmount);
+        map.put("gjj", gjj);
+        // 涓◣閲戦锛堢ぞ淇濈増锛�
+        bigDecimal = TaxCalculator.calculateMonthlyTax(basicSalary, schemeAmount, gjj);
+        map.put("salaryTax", bigDecimal);
+        // 搴旀墸宸ヨ祫
+        map.put("deductSalary", bigDecimal.add(gjj).add(schemeAmount));
+        // 瀹炲彂宸ヨ祫
+        map.put("netSalary", basicSalary.subtract(bigDecimal).subtract(gjj).subtract(schemeAmount));
+
+    }
+
+    /**
+     * 璁$畻
+     * @param type
+     * @param bigDecimal
+     * @param staffOnJobDto
+     * @param detail
+     * @return
+     */
+    public BigDecimal calculateByEmployeeIdType(String type,BigDecimal bigDecimal, StaffOnJob staffOnJobDto,SchemeInsuranceDetail detail) {
+        // 鍒ゆ柇鏄惁璋冪敤鍩烘湰宸ヨ祫
+        if (detail.getUseBasicSalary() == 1) {
+            BigDecimal divide = detail.getPaymentBase().multiply(detail.getPersonalRatio()).divide(new BigDecimal("100"), 2);
+            bigDecimal = bigDecimal.add(divide);
+        }else{
+            // 璋冪敤鍩烘湰宸ヨ祫
+            BigDecimal multiply = staffOnJobDto.getBasicSalary().multiply(detail.getPersonalRatio().divide(new BigDecimal("100"), 2));
+            bigDecimal = bigDecimal.add(multiply);
+        }
+        bigDecimal = bigDecimal.add(detail.getPersonalFixed());
+        return bigDecimal;
+    }
 }
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryDetailServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryDetailServiceImpl.java
new file mode 100644
index 0000000..3a60a7a
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryDetailServiceImpl.java
@@ -0,0 +1,20 @@
+package com.ruoyi.staff.service.impl;
+
+import com.ruoyi.staff.pojo.StaffSalaryDetail;
+import com.ruoyi.staff.mapper.StaffSalaryDetailMapper;
+import com.ruoyi.staff.service.StaffSalaryDetailService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫鏄庣粏琛� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:24:35
+ */
+@Service
+public class StaffSalaryDetailServiceImpl extends ServiceImpl<StaffSalaryDetailMapper, StaffSalaryDetail> implements StaffSalaryDetailService {
+
+}
diff --git a/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
new file mode 100644
index 0000000..f299b95
--- /dev/null
+++ b/src/main/java/com/ruoyi/staff/service/impl/StaffSalaryMainServiceImpl.java
@@ -0,0 +1,142 @@
+package com.ruoyi.staff.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.domain.AjaxResult;
+import com.ruoyi.project.system.domain.SysUser;
+import com.ruoyi.project.system.domain.SysUserDept;
+import com.ruoyi.project.system.mapper.SysUserDeptMapper;
+import com.ruoyi.project.system.mapper.SysUserMapper;
+import com.ruoyi.staff.mapper.StaffSalaryDetailMapper;
+import com.ruoyi.staff.pojo.SchemeApplicableStaff;
+import com.ruoyi.staff.pojo.StaffSalaryDetail;
+import com.ruoyi.staff.pojo.StaffSalaryMain;
+import com.ruoyi.staff.mapper.StaffSalaryMainMapper;
+import com.ruoyi.staff.service.StaffSalaryDetailService;
+import com.ruoyi.staff.service.StaffSalaryMainService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鍛樺伐宸ヨ祫涓昏〃 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃
+ * @since 2026-03-06 01:22:05
+ */
+@Service
+public class StaffSalaryMainServiceImpl extends ServiceImpl<StaffSalaryMainMapper, StaffSalaryMain> implements StaffSalaryMainService {
+
+    @Autowired
+    private StaffSalaryMainMapper staffSalaryMainMapper;
+
+    @Autowired
+    private StaffSalaryDetailService staffSalaryDetailService;
+
+    @Autowired
+    private StaffSalaryDetailMapper staffSalaryDetailMapper;
+
+    @Autowired
+    private SchemeApplicableStaffServiceImpl schemeApplicableStaffService;
+
+    @Autowired
+    private SysUserDeptMapper sysUserDeptMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Override
+    public AjaxResult listPage(Page page, StaffSalaryMain staffSalaryMain) {
+        LambdaQueryWrapper<StaffSalaryMain> staffSalaryMainLambdaQueryWrapper = new LambdaQueryWrapper<>();
+        if(staffSalaryMain != null){
+            if(StringUtils.isNotEmpty(staffSalaryMain.getSalaryTitle())){
+                staffSalaryMainLambdaQueryWrapper.like(StaffSalaryMain::getSalaryTitle, staffSalaryMain.getSalaryTitle());
+            }
+            if(StringUtils.isNotEmpty(staffSalaryMain.getSalaryMonth())){
+                staffSalaryMainLambdaQueryWrapper.like(StaffSalaryMain::getSalaryMonth, staffSalaryMain.getSalaryMonth());
+            }
+            if(staffSalaryMain.getStatus() != null){
+                staffSalaryMainLambdaQueryWrapper.eq(StaffSalaryMain::getStatus, staffSalaryMain.getStatus());
+            }
+        }
+        Page<StaffSalaryMain> page1 = staffSalaryMainMapper.selectPage(page, staffSalaryMainLambdaQueryWrapper);
+        page1.getRecords().forEach(main -> {
+            List<StaffSalaryDetail> staffSalaryDetailList = staffSalaryDetailMapper.selectList(new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, main.getId()));
+            main.setStaffSalaryDetailList(staffSalaryDetailList);
+        });
+        return AjaxResult.success(page1);
+    }
+
+    @Override
+    public AjaxResult add(StaffSalaryMain staffSalaryMain) {
+        staffSalaryMainMapper.insert(staffSalaryMain);
+        staffSalaryMain.getStaffSalaryDetailList().forEach(detail -> {
+            detail.setMainId(staffSalaryMain.getId());
+        });
+        staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList());
+        return AjaxResult.success("鏂板鎴愬姛");
+    }
+
+    @Override
+    public AjaxResult updateStaffSalaryMain(StaffSalaryMain staffSalaryMain) {
+        if(staffSalaryMain == null){
+            return AjaxResult.error("鍙傛暟閿欒");
+        }
+        StaffSalaryMain staffSalaryMain1 = staffSalaryMainMapper.selectById(staffSalaryMain.getId());
+        if(staffSalaryMain1 == null){
+            return AjaxResult.error("鍙傛暟閿欒");
+        }
+        // 寰呭鏍镐笉鍙紪杈�
+        if(staffSalaryMain1.getStatus() > 2){
+            return AjaxResult.error("寰呭鏍镐笉鍙紪杈�");
+        }
+        staffSalaryMainMapper.updateById(staffSalaryMain);
+        staffSalaryDetailMapper.delete(new LambdaQueryWrapper<StaffSalaryDetail>().eq(StaffSalaryDetail::getMainId, staffSalaryMain.getId()));
+        staffSalaryMain.getStaffSalaryDetailList().forEach(detail -> {
+            detail.setMainId(staffSalaryMain.getId());
+        });
+        staffSalaryDetailService.saveBatch(staffSalaryMain.getStaffSalaryDetailList());
+        return AjaxResult.success("淇敼鎴愬姛");
+    }
+
+    @Override
+    public AjaxResult delete(List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return AjaxResult.error("鍙傛暟閿欒");
+        }
+        staffSalaryMainMapper.deleteBatchIds(ids);
+        staffSalaryDetailMapper.delete(new LambdaQueryWrapper<StaffSalaryDetail>().in(StaffSalaryDetail::getMainId, ids));
+        return AjaxResult.success("鍒犻櫎鎴愬姛");
+    }
+
+    @Override
+    public AjaxResult calculateSalary(List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return AjaxResult.error("鍙傛暟閿欒");
+        }
+        List<Map<String, Object>> longs = setSchemeApplicableStaffUserInfo(ids); // 閫氳繃閮ㄩ棬ids鑾峰彇鐢ㄦ埛淇℃伅
+        if(CollectionUtils.isEmpty(longs)){
+            return AjaxResult.error("鏃犲憳宸�");
+        }
+        for (Map<String, Object> id : longs) {
+            schemeApplicableStaffService.calculateByEmployeeId((Integer) id.get("id"),id);
+        }
+        return AjaxResult.success(longs);
+    }
+
+    public List<Map<String, Object>> setSchemeApplicableStaffUserInfo(List<Long> ids) {
+        if(CollectionUtils.isEmpty(ids)){
+            return new ArrayList<>();
+        }
+        // 閫氳繃閮ㄩ棬鑾峰彇浜哄憳id
+        return sysUserDeptMapper.setSchemeApplicableStaffUserInfo(ids);
+    }
+}
diff --git a/src/main/resources/mapper/staff/BankMapper.xml b/src/main/resources/mapper/staff/BankMapper.xml
new file mode 100644
index 0000000..605f2bf
--- /dev/null
+++ b/src/main/resources/mapper/staff/BankMapper.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.staff.mapper.BankMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.Bank">
+        <id column="id" property="id" />
+        <result column="bank_name" property="bankName" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml b/src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml
index 4f2952d..1652dd6 100644
--- a/src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml
+++ b/src/main/resources/mapper/staff/SchemeApplicableStaffMapper.xml
@@ -2,19 +2,39 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.staff.mapper.SchemeApplicableStaffMapper">
 
-    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
-    <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.SchemeApplicableStaff">
-        <id column="id" property="id" />
-        <result column="title" property="title" />
-        <result column="dept_ids" property="deptIds" />
-        <result column="staff_names" property="staffNames" />
-        <result column="staff_ids" property="staffIds" />
-        <result column="insurance_types" property="insuranceTypes" />
-        <result column="remark" property="remark" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
-        <result column="create_user" property="createUser" />
-        <result column="update_user" property="updateUser" />
-    </resultMap>
+    <!-- 鍩虹瀛楁鏌ヨ -->
+    <sql id="schemeColumns">
+        id, title, dept_ids, staff_names, staff_ids,
+        insurance_types, remark, create_time, update_time,
+        create_user, update_user
+    </sql>
+
+    <!-- 鏍规嵁浜哄憳ID鏌ヨ绀句繚鏂规 -->
+    <select id="selectSchemeByStaffId" resultType="com.ruoyi.staff.pojo.SchemeApplicableStaff">
+        SELECT
+        <include refid="schemeColumns"/>
+        FROM
+        scheme_applicable_staff
+        WHERE
+        1 = 1
+        <!-- 鏍稿績锛氬尮閰峴taff_ids涓寘鍚洰鏍囦汉鍛業D鐨勮褰� -->
+        AND FIND_IN_SET(#{staffId}, staff_ids)
+        <!-- 鍙�夛細澧炲姞鏈夋晥鐘舵�佽繃婊わ紙濡傛灉琛ㄤ腑鏈夌姸鎬佸瓧娈碉級 -->
+        <!-- AND status = 1 -->
+        ORDER BY
+        create_time DESC
+    </select>
+
+    <!-- 鏌ヨ鏂规瀵瑰簲鐨勬槑缁� -->
+    <select id="selectDetailBySchemeId" resultType="com.ruoyi.staff.pojo.SchemeInsuranceDetail">
+        SELECT
+            id, scheme_id, insurance_type, payment_base,
+            use_basic_salary, personal_ratio, personal_fixed,
+            create_time, update_time, create_user, update_user
+        FROM
+            scheme_insurance_detail
+        WHERE
+            scheme_id = #{schemeId}
+    </select>
 
 </mapper>
diff --git a/src/main/resources/mapper/staff/StaffSalaryDetailMapper.xml b/src/main/resources/mapper/staff/StaffSalaryDetailMapper.xml
new file mode 100644
index 0000000..7c8004a
--- /dev/null
+++ b/src/main/resources/mapper/staff/StaffSalaryDetailMapper.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.staff.mapper.StaffSalaryDetailMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.StaffSalaryDetail">
+        <id column="id" property="id" />
+        <result column="main_id" property="mainId" />
+        <result column="staff_on_job_id" property="staffOnJobId" />
+        <result column="staff_name" property="staffName" />
+        <result column="post_name" property="postName" />
+        <result column="dept_name" property="deptName" />
+        <result column="basic_salary" property="basicSalary" />
+        <result column="piece_salary" property="pieceSalary" />
+        <result column="hourly_salary" property="hourlySalary" />
+        <result column="other_income" property="otherIncome" />
+        <result column="social_personal" property="socialPersonal" />
+        <result column="fund_personal" property="fundPersonal" />
+        <result column="other_deduct" property="otherDeduct" />
+        <result column="salary_tax" property="salaryTax" />
+        <result column="gross_salary" property="grossSalary" />
+        <result column="deduct_salary" property="deductSalary" />
+        <result column="net_salary" property="netSalary" />
+        <result column="remark" property="remark" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_user" property="updateUser" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/staff/StaffSalaryMainMapper.xml b/src/main/resources/mapper/staff/StaffSalaryMainMapper.xml
new file mode 100644
index 0000000..c3f0c62
--- /dev/null
+++ b/src/main/resources/mapper/staff/StaffSalaryMainMapper.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.staff.mapper.StaffSalaryMainMapper">
+
+    <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+    <resultMap id="BaseResultMap" type="com.ruoyi.staff.pojo.StaffSalaryMain">
+        <id column="id" property="id" />
+        <result column="salary_title" property="salaryTitle" />
+        <result column="dept_ids" property="deptIds" />
+        <result column="salary_month" property="salaryMonth" />
+        <result column="remark" property="remark" />
+        <result column="status" property="status" />
+        <result column="create_time" property="createTime" />
+        <result column="create_user" property="createUser" />
+        <result column="update_time" property="updateTime" />
+        <result column="update_user" property="updateUser" />
+    </resultMap>
+
+</mapper>
diff --git a/src/main/resources/mapper/system/SysUserDeptMapper.xml b/src/main/resources/mapper/system/SysUserDeptMapper.xml
index 7caa57e..498442d 100644
--- a/src/main/resources/mapper/system/SysUserDeptMapper.xml
+++ b/src/main/resources/mapper/system/SysUserDeptMapper.xml
@@ -3,7 +3,23 @@
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.project.system.mapper.SysUserDeptMapper">
-    
+    <select id="setSchemeApplicableStaffUserInfo" resultType="java.util.Map">
+        SELECT
+        T1.id as id,
+        T1.staff_no as staffNo,
+        T1.staff_name as staffName,
+        T2.dept_id as deptId,
+        T2.dept_name as deptName
+        FROM
+        staff_on_job T1
+        LEFT JOIN sys_dept T2 ON T1.sys_dept_id = T2.dept_id
+        <where>
+            T1.sys_dept_id in<foreach collection="ids" item="id" separator="," close=")" open="(">#{id}</foreach>
+        </where>
+        GROUP BY
+        T1.id
+    </select>
+
     <select id="userLoginFacotryList" resultType="com.ruoyi.project.system.domain.vo.SysUserDeptVo">
         SELECT
             T1.user_id,

--
Gitblit v1.9.3