From 83b85ebe8d7c5cd66e88d61d5bbc95c9e256a352 Mon Sep 17 00:00:00 2001
From: longz <longzhaoz@qq.com>
Date: 星期二, 21 七月 2026 21:38:22 +0800
Subject: [PATCH] 充电时段统计fix

---
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java               |  243 ++++++++++++++-------
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java                   |   30 +-
 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml                      |   31 ++
 ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java      |   52 ++++
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java                |    5 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java            |   22 ++
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java |   20 +
 ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml                  |   53 ++++
 ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java          |    2 
 ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java |    6 
 ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml                           |    2 
 ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml                  |   31 ++
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java         |   12 +
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java     |    5 
 ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java                   |    6 
 ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java          |    9 
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java            |   47 ++++
 ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java               |   38 +++
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java             |    2 
 ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java                        |    3 
 20 files changed, 510 insertions(+), 109 deletions(-)

diff --git a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
index fd2bb96..2373bea 100644
--- a/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
+++ b/ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/controller/TAppUserController.java
@@ -748,6 +748,12 @@
 
         UserDetailDto userDetailDto =  new UserDetailDto();
         BeanUtils.copyProperties(user,userDetailDto);
+        Map<Long, BigDecimal> exchangeCodeBalanceMap = otherClient
+                .getExchangeCodeBalanceMap(Collections.singletonList(id))
+                .getData();
+        userDetailDto.setExchangeCodeBalance(exchangeCodeBalanceMap == null
+                ? BigDecimal.ZERO
+                : exchangeCodeBalanceMap.getOrDefault(id, BigDecimal.ZERO));
 
         //获取累计充电数量
         R<Long> useOrderCount = chargingOrderClient.useOrderCount(user.getId());
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java
index 1145ae3..857b9d3 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/controller/PartnerController.java
@@ -64,7 +64,7 @@
 	
 	
 	
-	@RequiresPermissions(value = {"/balanceSheetRecord", "/partners", "/parkingRecord", "/chargingPile/add", "/chargingPile/select", "/chargingPile/update", "/invoiceManagement"}, logical = Logical.OR)
+	@RequiresPermissions(value = {"/balanceSheetRecord", "/partners", "/parkingRecord", "/chargingPile/add", "/chargingPile/select", "/chargingPile/update", "/invoiceManagement", "/faultInformationList"}, logical = Logical.OR)
 	@ResponseBody
 	@GetMapping("/getPartnerList")
 	@ApiOperation(value = "获取合作商列表", tags = {"管理后台-合作商管理"})
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
index d663f00..5298ef0 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/SiteServiceImpl.java
@@ -50,6 +50,7 @@
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
@@ -179,7 +180,13 @@
 			throw new ServiceException("请选择要导入的Excel文件");
 		}
 		ExcelUtil<SiteExcelDTO> util = new ExcelUtil<>(SiteExcelDTO.class);
-		List<SiteExcelDTO> rows = util.importExcel(file.getInputStream(), 0);
+		List<SiteExcelDTO> rows;
+		try (InputStream inputStream = file.getInputStream()) {
+			rows = util.importExcel(inputStream, 0);
+		} catch (Exception e) {
+			throw new ServiceException("Excel文件已损坏或格式不正确,请重新下载站点导入模板后填写")
+					.setDetailMessage(e.getMessage());
+		}
 		if (rows == null || rows.isEmpty()) {
 			throw new ServiceException("导入文件没有数据");
 		}
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
index a685641..7a7cf30 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/java/com/ruoyi/chargingPile/service/impl/TChargingPileServiceImpl.java
@@ -423,6 +423,12 @@
 		ChargingPileBatchBuildResultDTO result = new ChargingPileBatchBuildResultDTO();
 		TChargingPile pileTemplate = dto.getChargingPile();
 		TChargingGunDTO gunTemplate = dto.getChargingGun();
+		if (gunTemplate.getAuxPower() == null) {
+			throw new ServiceException("辅助电源不能为空");
+		}
+		if (gunTemplate.getOpreateStatus() == null) {
+			throw new ServiceException("运营状态不能为空");
+		}
 		String namePrefix = StringUtils.isEmpty(dto.getNamePrefix()) ? "" : dto.getNamePrefix().trim();
 		for (int i = 0; i < codes.size(); i++) {
 			TChargingPile chargingPile = new TChargingPile();
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
index bc5523d..1cd169b 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/SiteMapper.xml
@@ -258,7 +258,7 @@
 		</where>
 	</select>
 		<select id="getSiteListGun" resultType="com.ruoyi.chargingPile.api.model.Site">
-		select id, `name`, partner_id
+		select id, `name`, partner_id, venue_partner_id
 		from t_site
 		<where>
 			<if test="null != ids and ids.size()>0">
diff --git a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml
index f8e3e7e..37a4987 100644
--- a/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml
+++ b/ruoyi-service/ruoyi-chargingPile/src/main/resources/mapper/chargingPile/TFaultMessageMapper.xml
@@ -34,7 +34,6 @@
         from t_fault_message a
         left join t_charging_pile b on (a.charging_pile_id = b.id)
         left join t_site c on (a.site_id = c.id)
-        left join t_partner d on (c.partner_id = d.id)
         where a.del_flag = 0
         <if test="null != siteIds and siteIds.size() > 0">
             and a.site_id in
@@ -42,12 +41,30 @@
                 #{item}
             </foreach>
         </if>
-        <if test="partnerId != null">
-            and c.partner_id = #{partnerId}
-        </if>
-        <if test="partnerType != null">
-            and d.partner_type = #{partnerType}
-        </if>
+        <choose>
+            <when test="partnerType != null and partnerType == 2">
+                <if test="partnerId != null">
+                    and c.venue_partner_id = #{partnerId}
+                </if>
+                and exists (
+                    select 1 from t_partner venue_partner
+                    where venue_partner.id = c.venue_partner_id
+                      and venue_partner.partner_type = 2
+                )
+            </when>
+            <otherwise>
+                <if test="partnerId != null">
+                    and c.partner_id = #{partnerId}
+                </if>
+                <if test="partnerType != null">
+                    and exists (
+                        select 1 from t_partner owner_partner
+                        where owner_partner.id = c.partner_id
+                          and owner_partner.partner_type = #{partnerType}
+                    )
+                </if>
+            </otherwise>
+        </choose>
         order by a.create_time desc
     </select>
 </mapper>
diff --git a/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java b/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java
new file mode 100644
index 0000000..97f9162
--- /dev/null
+++ b/ruoyi-service/ruoyi-chargingPile/src/test/java/com/ruoyi/chargingPile/service/impl/SiteImportExcelTest.java
@@ -0,0 +1,52 @@
+package com.ruoyi.chargingPile.service.impl;
+
+import com.ruoyi.chargingPile.dto.SiteExcelDTO;
+import com.ruoyi.common.core.exception.ServiceException;
+import com.ruoyi.common.core.utils.poi.ExcelUtil;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.junit.jupiter.api.Test;
+import org.springframework.mock.web.MockHttpServletResponse;
+import org.springframework.mock.web.MockMultipartFile;
+
+import java.io.ByteArrayInputStream;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class SiteImportExcelTest {
+
+    @Test
+    void generatedTemplateCanBeOpenedAsXlsx() throws Exception {
+        MockHttpServletResponse response = new MockHttpServletResponse();
+        ExcelUtil<SiteExcelDTO> util = new ExcelUtil<>(SiteExcelDTO.class);
+
+        util.importTemplateExcel(response, "站点导入模板", "填写说明");
+
+        byte[] content = response.getContentAsByteArray();
+        assertTrue(content.length > 4);
+        assertEquals('P', content[0]);
+        assertEquals('K', content[1]);
+        assertDoesNotThrow(() -> {
+            try (Workbook ignored = WorkbookFactory.create(new ByteArrayInputStream(content))) {
+                // Opening and closing the generated workbook verifies the complete XLSX ZIP structure.
+            }
+        });
+    }
+
+    @Test
+    void corruptWorkbookReturnsReadableBusinessError() {
+        SiteServiceImpl service = new SiteServiceImpl();
+        MockMultipartFile file = new MockMultipartFile(
+                "file", "站点导入模板.xlsx",
+                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+                new byte[]{'P', 'K', 3, 4, 1, 2, 3});
+
+        ServiceException error = assertThrows(ServiceException.class,
+                () -> service.importSites(file, false));
+
+        assertEquals("Excel文件已损坏或格式不正确,请重新下载站点导入模板后填写", error.getMessage());
+    }
+}
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java
index a6fda40..37cf4b7 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/controller/ChargingBillController.java
@@ -145,20 +145,7 @@
     @PostMapping(value = "/accountBillList")
     @ApiOperation(value = "列表查询", tags = {"管理后台-账户结算账单"})
     public R<AccountListVO> accountBillList(@RequestBody ChargingListQuery dto) {
-        AccountListVO accountListVO = new AccountListVO();
-        ChargingBillVO res = chargingBillService.chargingBillList1(dto);
-        List<ChargingBillListVO> records = res.getList().getRecords();
-        accountListVO.setBillCount(records.size());
-        accountListVO.setTotalAmount(res.getPaymentAmount().subtract(res.getCommissionAmount()).subtract(res.getSharingAmount()).setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setPaymentAmount(res.getPaymentAmount().setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setRefundAmount(res.getRefundAmount().setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setCommissionAmount(res.getCommissionAmount().setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setSharingAmount(res.getSharingAmount().setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setPlatformIncome(res.getPlatformIncome().setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setPartnerIncome(res.getPartnerIncome().setScale(2, BigDecimal.ROUND_DOWN));
-        accountListVO.setList(res.getList());
-        accountListVO.setOrderList(res.getExportList());
-        return R.ok(accountListVO);
+        return R.ok(chargingBillService.accountSettlementBillList(dto));
     }
 
 
@@ -262,7 +249,9 @@
     @PutMapping("/exportAccount")
     public void exportAccount(@RequestBody ChargingListQuery dto)
     {
-        ChargingBillVO res = chargingBillService.chargingBillList1(dto);
+        dto.setPageCurr(1);
+        dto.setPageSize(100000);
+        AccountListVO res = chargingBillService.accountSettlementBillList(dto);
         List<ChargingBillListVO> list = res.getList().getRecords();
         List<TChargingBillExport> tChargingBillExports = new ArrayList<>();
         for (ChargingBillListVO orderInvoiceVO : list) {
@@ -285,7 +274,7 @@
             tChargingBillExport.setElectrovalence(orderInvoiceVO.getElectrovalence());
             tChargingBillExport.setServiceCharge(orderInvoiceVO.getServiceCharge());
             tChargingBillExport.setChargingCapacity(orderInvoiceVO.getChargingCapacity());
-            Integer chargingSecond = orderInvoiceVO.getChargingSecond();
+            Integer chargingSecond = Optional.ofNullable(orderInvoiceVO.getChargingSecond()).orElse(0);
             // 根据秒数 转换为xx小时xx分钟xx秒 如果小时为0不展示 如果分钟为0则不展示
             // 计算小时、分钟和秒
             int hours = chargingSecond / 60 / 60;
@@ -304,7 +293,8 @@
             }
             tChargingBillExport.setChargingTime(result.toString());
             tChargingBillExport.setOrderCount(orderInvoiceVO.getOrderCount());
-            tChargingBillExport.setBillTime(orderInvoiceVO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+            tChargingBillExport.setBillTime(orderInvoiceVO.getCreateTime() == null ? "-"
+                    : orderInvoiceVO.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
             tChargingBillExports.add(tChargingBillExport);
         }
         Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), TChargingBillExport.class, tChargingBillExports);
@@ -313,7 +303,7 @@
         response.setCharacterEncoding("utf-8");
         ServletOutputStream outputStream = null;
         try {
-            String fileName = URLEncoder.encode("月账单-"+res.getCategory()+"-"+res.getBillWeek()+"-"+res.getSiteName()+".xls", "utf-8");
+            String fileName = URLEncoder.encode("账户结算账单.xls", "utf-8");
             response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
             response.setContentType("application/vnd.ms-excel;charset=UTF-8");
             response.setHeader("Pragma", "no-cache");
@@ -324,7 +314,9 @@
             e.printStackTrace();
         } finally {
             try {
-                outputStream.close();
+                if (outputStream != null) {
+                    outputStream.close();
+                }
             } catch (IOException e) {
                 e.printStackTrace();
             }
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java
index f6ab633..b37752f 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TAccountSettlementStatementMapper.java
@@ -1,7 +1,29 @@
 package com.ruoyi.order.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.order.api.model.ChargingListQuery;
 import com.ruoyi.order.api.model.TAccountSettlementStatement;
+import com.ruoyi.order.api.vo.AccountListVO;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 
+import java.time.LocalDate;
+import java.util.List;
+
+@Mapper
 public interface TAccountSettlementStatementMapper extends BaseMapper<TAccountSettlementStatement> {
+
+    List<TAccountSettlementStatement> selectStatementPage(
+            @Param("pageInfo") PageInfo<TAccountSettlementStatement> pageInfo,
+            @Param("req") ChargingListQuery req,
+            @Param("siteIds") List<Integer> siteIds,
+            @Param("startCycle") LocalDate startCycle,
+            @Param("endCycle") LocalDate endCycle);
+
+    AccountListVO selectStatementSummary(
+            @Param("req") ChargingListQuery req,
+            @Param("siteIds") List<Integer> siteIds,
+            @Param("startCycle") LocalDate startCycle,
+            @Param("endCycle") LocalDate endCycle);
 }
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java
index a6c0d80..6b9cdfa 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/mapper/TChargingSettlementBillMapper.java
@@ -23,6 +23,11 @@
                                         @Param("status") Integer status, @Param("dateRange") List<String> dateRange,
                                         @Param("statisticalDateType") Integer statisticalDateType, @Param("siteIds") List<Integer> siteIds);
 
+    List<Map<String, Object>> queryIncomeList(@Param("status") Integer status,
+                                              @Param("dateRange") List<String> dateRange,
+                                              @Param("statisticalDateType") Integer statisticalDateType,
+                                              @Param("siteIds") List<Integer> siteIds);
+
 
     /**
      * 获取汇总数据
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java
index c6e8a17..557c67f 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITAccountSettlementStatementService.java
@@ -1,7 +1,19 @@
 package com.ruoyi.order.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.order.api.model.ChargingListQuery;
 import com.ruoyi.order.api.model.TAccountSettlementStatement;
+import com.ruoyi.order.api.vo.AccountListVO;
+
+import java.time.LocalDate;
+import java.util.List;
 
 public interface ITAccountSettlementStatementService extends IService<TAccountSettlementStatement> {
+
+    PageInfo<TAccountSettlementStatement> queryPage(ChargingListQuery req, List<Integer> siteIds,
+                                                     LocalDate startCycle, LocalDate endCycle);
+
+    AccountListVO querySummary(ChargingListQuery req, List<Integer> siteIds,
+                               LocalDate startCycle, LocalDate endCycle);
 }
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java
index 0a1f973..c79c2c8 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/ITChargingSettlementBillService.java
@@ -20,6 +20,8 @@
      */
     List<Map<String, Object>> queryList(PageInfo<Map<String, Object>> page, Integer type, Integer status, List<String> dateRange, Integer statisticalDateType, List<Integer> siteIds);
 
+    List<Map<String, Object>> queryIncomeList(Integer status, List<String> dateRange, Integer statisticalDateType, List<Integer> siteIds);
+
 
     /**
      * 获取汇总数据
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java
index c8ec84f..4d8ee6e 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/TChargingBillService.java
@@ -4,6 +4,7 @@
 import com.ruoyi.order.api.model.TChargingBill;
 import com.ruoyi.order.api.vo.ChargingBillVO;
 import com.ruoyi.order.api.model.ChargingListQuery;
+import com.ruoyi.order.api.vo.AccountListVO;
 import com.ruoyi.order.api.vo.ChargingBillWapper;
 
 /**
@@ -24,6 +25,8 @@
 
     ChargingBillVO chargingBillList1(ChargingListQuery dto);
 
+    AccountListVO accountSettlementBillList(ChargingListQuery dto);
+
 
     ChargingBillVO chargingBillListExport(ChargingListQuery dto);
 
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java
index 6c71f13..379940d 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TAccountSettlementStatementServiceImpl.java
@@ -1,11 +1,31 @@
 package com.ruoyi.order.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.web.page.PageInfo;
+import com.ruoyi.order.api.model.ChargingListQuery;
 import com.ruoyi.order.api.model.TAccountSettlementStatement;
+import com.ruoyi.order.api.vo.AccountListVO;
 import com.ruoyi.order.mapper.TAccountSettlementStatementMapper;
 import com.ruoyi.order.service.ITAccountSettlementStatementService;
 import org.springframework.stereotype.Service;
 
+import java.time.LocalDate;
+import java.util.List;
+
 @Service
 public class TAccountSettlementStatementServiceImpl extends ServiceImpl<TAccountSettlementStatementMapper, TAccountSettlementStatement> implements ITAccountSettlementStatementService {
+
+    @Override
+    public PageInfo<TAccountSettlementStatement> queryPage(ChargingListQuery req, List<Integer> siteIds,
+                                                            LocalDate startCycle, LocalDate endCycle) {
+        PageInfo<TAccountSettlementStatement> page = new PageInfo<>(req.getPageCurr(), req.getPageSize());
+        page.setRecords(baseMapper.selectStatementPage(page, req, siteIds, startCycle, endCycle));
+        return page;
+    }
+
+    @Override
+    public AccountListVO querySummary(ChargingListQuery req, List<Integer> siteIds,
+                                      LocalDate startCycle, LocalDate endCycle) {
+        return baseMapper.selectStatementSummary(req, siteIds, startCycle, endCycle);
+    }
 }
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java
index 9562cc2..5df6900 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingBillServiceImpl.java
@@ -23,6 +23,7 @@
 import com.ruoyi.order.api.vo.ChargingBillListVO;
 import com.ruoyi.order.api.vo.ChargingBillVO;
 import com.ruoyi.order.api.vo.ChargingBillWapper;
+import com.ruoyi.order.api.vo.AccountListVO;
 import com.ruoyi.order.mapper.TChargingBillMapper;
 import com.ruoyi.order.mapper.TChargingOrderMapper;
 import com.ruoyi.order.service.*;
@@ -87,6 +88,137 @@
     private TChargingOrderService chargingOrderService;
     @Resource
     private ITChargingSettlementBillService chargingSettlementBillService;
+    @Resource
+    private ITAccountSettlementStatementService accountSettlementStatementService;
+
+    @Override
+    public AccountListVO accountSettlementBillList(ChargingListQuery dto) {
+        SysUser sysUser = sysUserClient.getSysUser(tokenService.getLoginUser().getUserid()).getData();
+        List<Integer> siteIds = resolveAccountStatementSiteIds(dto, sysUser);
+        LocalDate[] cycleRange = resolveBillingCycleRange(dto.getDateRange());
+
+        PageInfo<TAccountSettlementStatement> statementPage = accountSettlementStatementService.queryPage(
+                dto, siteIds, cycleRange[0], cycleRange[1]);
+        AccountListVO result = accountSettlementStatementService.querySummary(
+                dto, siteIds, cycleRange[0], cycleRange[1]);
+        if (result == null) {
+            result = new AccountListVO();
+        }
+
+        Set<Integer> pageSiteIds = statementPage.getRecords().stream()
+                .map(TAccountSettlementStatement::getSiteId)
+                .filter(siteId -> siteId != null && siteId > 0)
+                .collect(Collectors.toSet());
+        Map<Integer, String> siteNameMap = pageSiteIds.isEmpty() ? Collections.emptyMap()
+                : safeData(siteClient.getSiteByIds(new ArrayList<>(pageSiteIds))).stream()
+                .collect(Collectors.toMap(Site::getId, Site::getName, (first, ignored) -> first));
+
+        List<ChargingBillListVO> records = statementPage.getRecords().stream()
+                .map(statement -> toAccountStatementVO(statement, siteNameMap))
+                .collect(Collectors.toList());
+        PageInfo<ChargingBillListVO> page = new PageInfo<>(statementPage.getCurrent(), statementPage.getSize());
+        page.setTotal(statementPage.getTotal());
+        page.setRecords(records);
+        result.setList(page);
+        result.setOrderList(Collections.emptyList());
+        result.setBillCount(result.getBillCount() == null ? 0 : result.getBillCount());
+        result.setTotalAmount(zeroIfNull(result.getTotalAmount()));
+        result.setPaymentAmount(zeroIfNull(result.getPaymentAmount()));
+        result.setRefundAmount(zeroIfNull(result.getRefundAmount()));
+        result.setCommissionAmount(zeroIfNull(result.getCommissionAmount()));
+        result.setSharingAmount(zeroIfNull(result.getSharingAmount()));
+        result.setPlatformIncome(zeroIfNull(result.getPlatformIncome()));
+        result.setPartnerIncome(zeroIfNull(result.getPartnerIncome()));
+        return result;
+    }
+
+    private List<Integer> resolveAccountStatementSiteIds(ChargingListQuery dto, SysUser sysUser) {
+        List<Integer> siteIds = new ArrayList<>();
+        if (dto.getSiteId() != null) {
+            siteIds.add(dto.getSiteId());
+        } else {
+            List<GetSiteListDTO> sites = safeData(siteClient.getSiteListByUserId(tokenService.getLoginUser().getUserid()));
+            siteIds.addAll(sites.stream().map(GetSiteListDTO::getId).filter(Objects::nonNull).collect(Collectors.toList()));
+        }
+        if (Integer.valueOf(2).equals(sysUser.getRoleType())) {
+            siteIds = siteIds.stream().filter(siteId -> {
+                List<Boolean> permissions = safeData(partnerClient.getAccountMenu(sysUser.getObjectId(), siteId));
+                return permissions.size() > 1 && Boolean.TRUE.equals(permissions.get(1));
+            }).collect(Collectors.toList());
+        }
+        if (Integer.valueOf(1).equals(sysUser.getRoleType())) {
+            siteIds.add(0);
+        }
+        if (siteIds.isEmpty()) {
+            siteIds.add(-1);
+        }
+        return siteIds.stream().distinct().collect(Collectors.toList());
+    }
+
+    private LocalDate[] resolveBillingCycleRange(List<String> dateRange) {
+        LocalDate start = null;
+        LocalDate end = null;
+        if (dateRange != null && !dateRange.isEmpty()) {
+            start = parseBillingMonth(dateRange.get(0));
+            String endValue = dateRange.size() > 1 ? dateRange.get(1) : dateRange.get(0);
+            LocalDate endMonth = parseBillingMonth(endValue);
+            end = endMonth == null ? null : endMonth.plusMonths(1);
+        }
+        return new LocalDate[]{start, end};
+    }
+
+    private LocalDate parseBillingMonth(String value) {
+        if (!StringUtils.hasLength(value) || value.length() < 7) {
+            return null;
+        }
+        return LocalDate.parse(value.substring(0, 7) + "-01");
+    }
+
+    private ChargingBillListVO toAccountStatementVO(TAccountSettlementStatement statement,
+                                                      Map<Integer, String> siteNameMap) {
+        ChargingBillListVO vo = new ChargingBillListVO();
+        vo.setId(statement.getId());
+        vo.setUid(String.valueOf(statement.getId()));
+        vo.setCode(statement.getCode());
+        vo.setType(Integer.valueOf(0).equals(statement.getSiteId()) ? 1 : 2);
+        vo.setSiteId(statement.getSiteId());
+        vo.setSiteName(Integer.valueOf(0).equals(statement.getSiteId())
+                ? "全站" : siteNameMap.getOrDefault(statement.getSiteId(), "-"));
+        vo.setStatus(statement.getStatus());
+        vo.setOrderState(2);
+        vo.setPayType(statement.getAccountType());
+        vo.setPayTypeName(accountTypeName(statement.getAccountType()));
+        vo.setBillWeek(statement.getBillingCycle() == null
+                ? null : statement.getBillingCycle().format(DateTimeFormatter.ofPattern("yyyy-MM")));
+        vo.setBillTime(statement.getCreateTime());
+        vo.setCreateTime(statement.getCreateTime());
+        vo.setPaymentAmount(zeroIfNull(statement.getRechargeAmount()));
+        vo.setRefundAmount(zeroIfNull(statement.getRefundAmount()));
+        vo.setCommissionAmount(zeroIfNull(statement.getPlatformFee()));
+        vo.setSharingAmount(zeroIfNull(statement.getTripartiteCommission()));
+        vo.setBillMoney(zeroIfNull(statement.getRecordedAmount()));
+        vo.setPlatformIncome(BigDecimal.ZERO);
+        vo.setPartnerIncome(BigDecimal.ZERO);
+        vo.setAuthDownLoad(false);
+        return vo;
+    }
+
+    private String accountTypeName(Integer accountType) {
+        if (Integer.valueOf(1).equals(accountType)) {
+            return "微信商户";
+        }
+        if (Integer.valueOf(2).equals(accountType)) {
+            return "支付宝商户";
+        }
+        if (Integer.valueOf(3).equals(accountType)) {
+            return "工商银行商户";
+        }
+        return "-";
+    }
+
+    private BigDecimal zeroIfNull(BigDecimal value) {
+        return value == null ? BigDecimal.ZERO : value;
+    }
 
 
     @Override
@@ -1063,6 +1195,7 @@
         Integer roleType = sysUser.getRoleType();
         //如果没传siteId,获取当前登陆人所有的siteIds
         List<Integer> siteIds = new ArrayList<>();
+        Map<Integer, List<Boolean>> chargingBillPermissionMap = new HashMap<>();
         List<GetSiteListDTO> data = siteClient.getSiteListByUserId(userId).getData();
         for (GetSiteListDTO datum : data) {
             siteIds.add(datum.getId());
@@ -1074,10 +1207,9 @@
                 List<Integer> integers = new ArrayList<>();
                 for (Integer siteId : siteIds) {
                     // 校验有没有这个站点的权限
-                    List<Boolean> t1= partnerClient.getChargingBillMenu(sysUser.getObjectId(),siteId).getData();
-
-                    Boolean b = t1.get(1);
-                    if (b){
+                    List<Boolean> permissions = safeData(partnerClient.getChargingBillMenu(sysUser.getObjectId(), siteId));
+                    chargingBillPermissionMap.put(siteId, permissions);
+                    if (permissions.size() > 1 && Boolean.TRUE.equals(permissions.get(1))){
                         integers.add(siteId);
                     }
                 }
@@ -1098,9 +1230,9 @@
         ChargingBillWapper chargingBillVO = new ChargingBillWapper();
         List<Map<String, Object>> pageList = new ArrayList<>();
         Map<Integer, BigDecimal> siteServiceShareRatioMap = loadSiteServiceShareRatioMap();
-        PageInfo<Map<String, Object>> sumPageInfo = new PageInfo<>(1, 100000);
-        List<Map<String, Object>> sumList = chargingSettlementBillService.queryList(sumPageInfo, dto.getType(), dto.getState(), dto.getDateRange(), statisticalDateType, dto.getSiteIds());
-        Map<String, Map<String, BigDecimal>> incomeIndex = buildChargingBillIncomeIndex(sumList, siteServiceShareRatioMap);
+        List<Map<String, Object>> incomeRows = chargingSettlementBillService.queryIncomeList(
+                dto.getState(), dto.getDateRange(), statisticalDateType, dto.getSiteIds());
+        Map<String, Map<String, BigDecimal>> incomeIndex = buildChargingBillIncomeIndex(incomeRows, siteServiceShareRatioMap);
 		Set<Integer> settlementSiteIds = new HashSet<>();
 		if (list != null) {
 			list.stream().map(item -> item.get("site_id")).filter(Objects::nonNull)
@@ -1147,9 +1279,8 @@
                 data1.put("serviceCharge", serviceCharge);
                 data1.put("authDownLoad", true);
                 if (roleType == 2 && 0 != site_id){
-                    // 校验有没有这个站点的权限
-                    List<Boolean> t1= partnerClient.getChargingBillMenu(sysUser.getObjectId(),site_id).getData();
-                    data1.put("authDownLoad", t1.get(0));
+                    List<Boolean> permissions = chargingBillPermissionMap.getOrDefault(site_id, Collections.emptyList());
+                    data1.put("authDownLoad", !permissions.isEmpty() && Boolean.TRUE.equals(permissions.get(0)));
                 }
                 pageList.add(data1);
             }
@@ -1167,8 +1298,8 @@
         BigDecimal discount = (null == map || null == map.get("couponDeduction")) ? BigDecimal.ZERO : new BigDecimal(map.get("couponDeduction").toString());
         BigDecimal platformIncome = BigDecimal.ZERO;
         BigDecimal partnerIncome = BigDecimal.ZERO;
-        if (sumList != null) {
-            for (Map<String, Object> row : sumList) {
+        if (incomeRows != null) {
+            for (Map<String, Object> row : incomeRows) {
                 Integer siteId = Integer.valueOf(row.get("site_id").toString());
                 String billingCycle = row.get("billingCycle").toString();
                 Map<String, BigDecimal> incomeMap = getChargingBillIncome(incomeIndex, siteId, billingCycle);
@@ -1192,86 +1323,40 @@
         return chargingBillVO;
     }
 
-    private Map<String, Map<String, BigDecimal>> buildChargingBillIncomeIndex(List<Map<String, Object>> billRows,
-                                                                               Map<Integer, BigDecimal> siteServiceShareRatioMap) {
+    Map<String, Map<String, BigDecimal>> buildChargingBillIncomeIndex(List<Map<String, Object>> billRows,
+                                                                      Map<Integer, BigDecimal> siteServiceShareRatioMap) {
         Map<String, Map<String, BigDecimal>> incomeIndex = new HashMap<>();
         if (billRows == null || billRows.isEmpty()) {
             return incomeIndex;
         }
-        Set<String> billingCycles = billRows.stream()
-                .map(row -> row.get("billingCycle"))
-                .filter(Objects::nonNull)
-                .map(Object::toString)
-                .collect(Collectors.toSet());
-        if (billingCycles.isEmpty()) {
-            return incomeIndex;
-        }
-        LocalDate firstMonth = billingCycles.stream()
-                .map(cycle -> LocalDate.parse(cycle + "-01"))
-                .min(LocalDate::compareTo)
-                .orElse(null);
-        LocalDate lastMonth = billingCycles.stream()
-                .map(cycle -> LocalDate.parse(cycle + "-01"))
-                .max(LocalDate::compareTo)
-                .orElse(null);
-        if (firstMonth == null || lastMonth == null) {
-            return incomeIndex;
-        }
-
-        List<TChargingOrder> orders = chargingOrderList.selectList(new LambdaQueryWrapper<>(TChargingOrder.class)
-                .select(TChargingOrder::getId, TChargingOrder::getSiteId, TChargingOrder::getPayTime, TChargingOrder::getOrderSource)
-                .ge(TChargingOrder::getPayTime, firstMonth.atStartOfDay())
-                .lt(TChargingOrder::getPayTime, lastMonth.plusMonths(1).atStartOfDay()));
-        if (orders == null || orders.isEmpty()) {
-            return incomeIndex;
-        }
-
-        Map<Long, BigDecimal[]> strategyAmountMap = new HashMap<>();
-        List<Long> orderIds = orders.stream().map(TChargingOrder::getId).filter(Objects::nonNull).collect(Collectors.toList());
-        final int batchSize = 1000;
-        for (int from = 0; from < orderIds.size(); from += batchSize) {
-            List<Long> batchIds = orderIds.subList(from, Math.min(from + batchSize, orderIds.size()));
-            List<TChargingOrderAccountingStrategy> strategies = chargingOrderAccountingStrategyService.list(
-                    new LambdaQueryWrapper<TChargingOrderAccountingStrategy>()
-                            .select(TChargingOrderAccountingStrategy::getChargingOrderId,
-                                    TChargingOrderAccountingStrategy::getPeriodElectricPrice,
-                                    TChargingOrderAccountingStrategy::getPeriodServicePrice)
-                            .in(TChargingOrderAccountingStrategy::getChargingOrderId, batchIds));
-            for (TChargingOrderAccountingStrategy strategy : strategies) {
-                BigDecimal[] amounts = strategyAmountMap.computeIfAbsent(strategy.getChargingOrderId(), key -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
-                amounts[0] = amounts[0].add(strategy.getPeriodElectricPrice() == null ? BigDecimal.ZERO : strategy.getPeriodElectricPrice());
-                amounts[1] = amounts[1].add(strategy.getPeriodServicePrice() == null ? BigDecimal.ZERO : strategy.getPeriodServicePrice());
-            }
-        }
-
-        for (TChargingOrder order : orders) {
-            if (order.getPayTime() == null || order.getSiteId() == null) {
+        for (Map<String, Object> row : billRows) {
+            if (row == null || row.get("site_id") == null || row.get("billingCycle") == null) {
                 continue;
             }
-            String billingCycle = order.getPayTime().format(DateTimeFormatter.ofPattern("yyyy-MM"));
-            if (!billingCycles.contains(billingCycle)) {
-                continue;
-            }
-            BigDecimal[] amounts = strategyAmountMap.getOrDefault(order.getId(), new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
-            BigDecimal paymentAmount;
+            Integer siteId = Integer.valueOf(row.get("site_id").toString());
+            String billingCycle = row.get("billingCycle").toString();
+            BigDecimal electricAmount = decimalValue(row.get("total_electricity_charge"));
+            BigDecimal serviceAmount = decimalValue(row.get("total_service_fee"));
+            BigDecimal tripartiteCommission = decimalValue(row.get("tripartite_commission"));
+            BigDecimal paymentAmount = electricAmount.add(serviceAmount).subtract(tripartiteCommission);
+            BigDecimal tripartiteServiceAmount = tripartiteCommission.multiply(new BigDecimal("5"));
+            BigDecimal commissionableServiceAmount = serviceAmount.subtract(tripartiteServiceAmount).max(BigDecimal.ZERO);
             BigDecimal partnerIncome = BigDecimal.ZERO;
-            if (Integer.valueOf(2).equals(order.getOrderSource())) {
-                paymentAmount = amounts[0].add(amounts[1].multiply(new BigDecimal("0.8")).setScale(2, RoundingMode.DOWN));
-            } else {
-                paymentAmount = amounts[0].add(amounts[1]);
-                if (Integer.valueOf(1).equals(order.getOrderSource())) {
-                    BigDecimal serviceShareRatio = siteServiceShareRatioMap.get(order.getSiteId());
-                    if (serviceShareRatio != null && serviceShareRatio.compareTo(BigDecimal.ZERO) > 0) {
-                        partnerIncome = amounts[1].multiply(serviceShareRatio).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
-                    }
-                }
+            BigDecimal serviceShareRatio = siteServiceShareRatioMap.get(siteId);
+            if (serviceShareRatio != null && serviceShareRatio.compareTo(BigDecimal.ZERO) > 0) {
+                partnerIncome = commissionableServiceAmount.multiply(serviceShareRatio)
+                        .divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
             }
             addChargingBillIncome(incomeIndex, chargingBillIncomeKey(0, billingCycle), paymentAmount, partnerIncome);
-            addChargingBillIncome(incomeIndex, chargingBillIncomeKey(order.getSiteId(), billingCycle), paymentAmount, partnerIncome);
+            addChargingBillIncome(incomeIndex, chargingBillIncomeKey(siteId, billingCycle), paymentAmount, partnerIncome);
         }
         return incomeIndex;
     }
 
+    private BigDecimal decimalValue(Object value) {
+        return value == null ? BigDecimal.ZERO : new BigDecimal(value.toString());
+    }
+
     private void addChargingBillIncome(Map<String, Map<String, BigDecimal>> incomeIndex, String key,
                                        BigDecimal paymentAmount, BigDecimal partnerIncome) {
         Map<String, BigDecimal> income = incomeIndex.computeIfAbsent(key, ignored -> {
diff --git a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java
index 194880f..050b52f 100644
--- a/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java
+++ b/ruoyi-service/ruoyi-order/src/main/java/com/ruoyi/order/service/impl/TChargingSettlementBillServiceImpl.java
@@ -28,6 +28,11 @@
         return this.baseMapper.queryList(page, type, status, dateRange, statisticalDateType, siteIds);
     }
 
+    @Override
+    public List<Map<String, Object>> queryIncomeList(Integer status, List<String> dateRange, Integer statisticalDateType, List<Integer> siteIds) {
+        return this.baseMapper.queryIncomeList(status, dateRange, statisticalDateType, siteIds);
+    }
+
 
     /**
      * 获取汇总数据
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml
index 2d66002..a03ea0c 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TAccountSettlementStatementMapper.xml
@@ -2,5 +2,56 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.ruoyi.order.mapper.TAccountSettlementStatementMapper">
 
+    <sql id="statementWhere">
+        <where>
+            <if test="req.type != null and req.type == 1">
+                AND site_id = 0
+            </if>
+            <if test="req.type != null and req.type == 2">
+                AND site_id &gt; 0
+            </if>
+            <if test="req.state != null">
+                AND status = #{req.state}
+            </if>
+            <if test="req.payType != null and req.payType != 0">
+                AND account_type = #{req.payType}
+            </if>
+            <if test="req.uid != null and req.uid != ''">
+                AND id = #{req.uid}
+            </if>
+            <if test="startCycle != null">
+                AND billing_cycle &gt;= #{startCycle}
+            </if>
+            <if test="endCycle != null">
+                AND billing_cycle &lt; #{endCycle}
+            </if>
+            AND site_id IN
+            <foreach collection="siteIds" open="(" close=")" separator="," item="siteId">
+                #{siteId}
+            </foreach>
+        </where>
+    </sql>
 
-</mapper>
\ No newline at end of file
+    <select id="selectStatementPage" resultType="com.ruoyi.order.api.model.TAccountSettlementStatement">
+        SELECT id, site_id, billing_cycle, status, code, account_type,
+               recharge_amount, refund_amount, platform_fee,
+               tripartite_commission, recorded_amount, create_time
+        FROM t_account_settlement_statement
+        <include refid="statementWhere"/>
+        ORDER BY billing_cycle DESC, account_type ASC, site_id ASC
+    </select>
+
+    <select id="selectStatementSummary" resultType="com.ruoyi.order.api.vo.AccountListVO">
+        SELECT COUNT(*) AS billCount,
+               COALESCE(SUM(recorded_amount), 0) AS totalAmount,
+               COALESCE(SUM(recharge_amount), 0) AS paymentAmount,
+               COALESCE(SUM(refund_amount), 0) AS refundAmount,
+               COALESCE(SUM(platform_fee), 0) AS commissionAmount,
+               COALESCE(SUM(tripartite_commission), 0) AS sharingAmount,
+               0 AS platformIncome,
+               0 AS partnerIncome
+        FROM t_account_settlement_statement
+        <include refid="statementWhere"/>
+    </select>
+
+</mapper>
diff --git a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml
index 86cb279..e403a10 100644
--- a/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml
+++ b/ruoyi-service/ruoyi-order/src/main/resources/mapper/order/TChargingSettlementBillMapper.xml
@@ -37,6 +37,37 @@
         order by a.site_id
     </select>
 
+    <select id="queryIncomeList" resultType="map">
+        select
+        site_id,
+        DATE_FORMAT(billing_cycle, '%Y-%m') as billingCycle,
+        total_electricity_charge,
+        total_service_fee,
+        tripartite_commission
+        from t_charging_settlement_bill
+        <where>
+            and site_id != 0
+            <if test="null != status">
+                and `status` = #{status}
+            </if>
+            <if test="null != statisticalDateType">
+                and statistical_date_type = #{statisticalDateType}
+            </if>
+            <if test="null != dateRange and dateRange.size() > 0">
+                and DATE_FORMAT(billing_cycle, '%Y-%m') in
+                <foreach collection="dateRange" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+            <if test="null != siteIds and siteIds.size() > 0">
+                and site_id in
+                <foreach collection="siteIds" item="item" open="(" separator="," close=")">
+                    #{item}
+                </foreach>
+            </if>
+        </where>
+    </select>
+
 
     <select id="queryListSum" resultType="map">
         select
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java
new file mode 100644
index 0000000..9ba9fd4
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingBillIncomeIndexTest.java
@@ -0,0 +1,47 @@
+package com.ruoyi.order.service.impl;
+
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ChargingBillIncomeIndexTest {
+
+    @Test
+    void calculatesIncomeFromSettlementRowsWithoutSharingThirdPartyServiceFees() {
+        TChargingBillServiceImpl service = new TChargingBillServiceImpl();
+        Map<Integer, BigDecimal> ratios = new HashMap<>();
+        ratios.put(1, new BigDecimal("15"));
+        ratios.put(2, new BigDecimal("50"));
+
+        Map<String, Map<String, BigDecimal>> incomeIndex = service.buildChargingBillIncomeIndex(
+                Arrays.asList(
+                        settlementRow(1, "2026-06", "6.12", "1.85", "0.00"),
+                        settlementRow(2, "2026-06", "1.00", "1.00", "0.20")
+                ),
+                ratios
+        );
+
+        assertEquals(new BigDecimal("7.69"), incomeIndex.get("1|2026-06").get("platformIncome"));
+        assertEquals(new BigDecimal("0.28"), incomeIndex.get("1|2026-06").get("partnerIncome"));
+        assertEquals(new BigDecimal("1.80"), incomeIndex.get("2|2026-06").get("platformIncome"));
+        assertEquals(new BigDecimal("0.00"), incomeIndex.get("2|2026-06").get("partnerIncome"));
+        assertEquals(new BigDecimal("9.49"), incomeIndex.get("0|2026-06").get("platformIncome"));
+        assertEquals(new BigDecimal("0.28"), incomeIndex.get("0|2026-06").get("partnerIncome"));
+    }
+
+    private Map<String, Object> settlementRow(Integer siteId, String billingCycle, String electricAmount,
+                                               String serviceAmount, String tripartiteCommission) {
+        Map<String, Object> row = new HashMap<>();
+        row.put("site_id", siteId);
+        row.put("billingCycle", billingCycle);
+        row.put("total_electricity_charge", new BigDecimal(electricAmount));
+        row.put("total_service_fee", new BigDecimal(serviceAmount));
+        row.put("tripartite_commission", new BigDecimal(tripartiteCommission));
+        return row;
+    }
+}
diff --git a/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java
new file mode 100644
index 0000000..00d47d2
--- /dev/null
+++ b/ruoyi-service/ruoyi-order/src/test/java/com/ruoyi/order/service/impl/ChargingPeriodIncomeTest.java
@@ -0,0 +1,38 @@
+package com.ruoyi.order.service.impl;
+
+import com.ruoyi.order.api.vo.ChargingOrderListVO;
+import org.junit.jupiter.api.Test;
+
+import java.math.BigDecimal;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+class ChargingPeriodIncomeTest {
+
+    @Test
+    void usesActualChargingOrderShareIncome() {
+        TChargingOrderServiceImpl service = new TChargingOrderServiceImpl();
+        ChargingOrderListVO item = new ChargingOrderListVO();
+        Map<String, Object> row = new HashMap<>();
+        row.put("platformIncome", new BigDecimal("0.73"));
+        row.put("partnerIncome", new BigDecimal("0.27"));
+
+        service.applyChargingPeriodShareIncome(item, row);
+
+        assertEquals(new BigDecimal("0.73"), item.getPlatformIncome());
+        assertEquals(new BigDecimal("0.27"), item.getPartnerIncome());
+    }
+
+    @Test
+    void usesZeroIncomeWhenNoEffectiveShareRecordExists() {
+        TChargingOrderServiceImpl service = new TChargingOrderServiceImpl();
+        ChargingOrderListVO item = new ChargingOrderListVO();
+
+        service.applyChargingPeriodShareIncome(item, null);
+
+        assertEquals(BigDecimal.ZERO, item.getPlatformIncome());
+        assertEquals(BigDecimal.ZERO, item.getPartnerIncome());
+    }
+}

--
Gitblit v1.7.1