From 4238c31d9d45eaee342f2a67a934ee7d831d051f Mon Sep 17 00:00:00 2001 From: caojia <1301869380@qq.com> Date: Tue, 27 Oct 2026 16:47:08 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=8D=E6=A0=B8?= =?UTF-8?q?=E9=94=80=E6=8C=89=E9=92=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bms-front/src/views/ar/bill/index.vue | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/bms-front/src/views/ar/bill/index.vue b/bms-front/src/views/ar/bill/index.vue index f40d8d0c..f7fa3bc3 100644 --- a/bms-front/src/views/ar/bill/index.vue +++ b/bms-front/src/views/ar/bill/index.vue @@ -45,6 +45,7 @@ 作废 导出明细 去核销 + 反核销 @@ -150,7 +151,7 @@ const columns = [ { label: '账单截止日', prop: 'billPeriodEnd', minWidth: 120, formatter: row => `截至 ${date(row.billPeriodEnd)}` }, { label: '订单数', prop: 'orderCount', width: 80 }, { label: '应收总额', prop: 'totalAmount', width: 120, align: 'right', slot: 'totalAmount' }, { label: '已核销', prop: 'writtenOffAmount', width: 110, align: 'right', slot: 'writtenOffAmount' }, { label: '未核销', prop: 'unwrittenAmount', width: 110, align: 'right', slot: 'unwrittenAmount' }, { label: '状态', prop: 'status', width: 110, slot: 'status' }, - { label: '账单日期', prop: 'billDate', width: 120, formatter: row => date(row.billDate) }, { label: '操作', prop: 'action', width: 330, fixed: 'right', slot: 'action', showInToolbar: false } + { label: '账单日期', prop: 'billDate', width: 120, formatter: row => date(row.billDate) }, { label: '操作', prop: 'action', width: 380, fixed: 'right', slot: 'action', showInToolbar: false } ] const searchColumns = [ { label: '账单号', prop: 'billNo', component: 'input', placeholder: '账单号', width: '180px' }, { label: '账单名称', prop: 'billName', component: 'input', placeholder: '账单名称', width: '180px' }, { label: '客户名称', prop: 'customerId', component: 'input', placeholder: '请选择客户', width: '220px' }, @@ -392,8 +393,20 @@ function canGoWriteoff(row) { || row.status === AR_BILL_STATUS.PARTIAL_WRITTEN_OFF return canWriteoffStatus && Number(row.unwrittenAmount) > 0 } +function canGoReverseWriteoff(row) { + if (!row?.customerId || !(Number(row.writtenOffAmount) > 0)) return false + return row.status === AR_BILL_STATUS.PARTIAL_WRITTEN_OFF + || row.status === AR_BILL_STATUS.WRITTEN_OFF +} function goWriteoff(row) { if (!canGoWriteoff(row)) return + goCustomerBillWriteoff(row) +} +function goReverseWriteoff(row) { + if (!canGoReverseWriteoff(row)) return + goCustomerBillWriteoff(row) +} +function goCustomerBillWriteoff(row) { router.push({ path: '/customersupplier/customer-money/index', query: { From b4e696b27ce2357674a6db964259884ff9e1df66 Mon Sep 17 00:00:00 2001 From: caojia <1301869380@qq.com> Date: Tue, 27 Oct 2026 17:04:22 +0800 Subject: [PATCH 2/3] =?UTF-8?q?:sparkles:=20=E5=BA=94=E6=94=B6=E8=B4=A6?= =?UTF-8?q?=E5=8D=95=E5=88=97=E8=A1=A8=E5=A2=9E=E5=8A=A0=E7=AD=9B=E9=80=89?= =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/ar/ArBillController.java | 20 ++++++ .../bms/ar/domain/vo/ArBillListExportRow.java | 66 +++++++++++++++++++ bms-front/src/views/ar/bill/index.vue | 20 +++++- 3 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillListExportRow.java diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java index b2595d2a..06b8d2c9 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/ar/ArBillController.java @@ -1,5 +1,6 @@ package com.bms.web.controller.ar; +import java.util.ArrayList; import java.util.List; import java.util.Date; @@ -31,6 +32,7 @@ import com.bms.ar.domain.ArBillLog; import com.bms.ar.domain.vo.ArBillActionRequest; import com.bms.ar.domain.vo.ArBillGenerateQuery; import com.bms.ar.domain.vo.ArBillGenerateRequest; +import com.bms.ar.domain.vo.ArBillListExportRow; import com.bms.ar.domain.vo.ArBillQuery; import com.bms.ar.service.IArBillService; import com.bms.common.annotation.Log; @@ -40,6 +42,7 @@ import com.bms.common.core.page.TableDataInfo; import com.bms.common.exception.ServiceException; import com.bms.common.enums.BusinessType; import com.bms.common.utils.StringUtils; +import com.bms.common.utils.poi.ExcelUtil; import com.bms.common.utils.uuid.IdUtils; import com.bms.price.domain.PrcOrderBill; @@ -78,6 +81,23 @@ public class ArBillController extends BaseController { return getDataTable(list); } + /** + * 按当前筛选条件导出全部应收账单,不受列表分页参数影响。 + */ + @PreAuthorize("@ss.hasPermi('ar:bill:export')") + @Log(title = "应收账单", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, ArBillQuery query, HttpServletRequest request) { + rejectMultiValueParameter(request, "customerId"); + List bills = billService.selectArBillList(query == null ? new ArBillQuery() : query); + List rows = new ArrayList<>(bills.size()); + for (ArBill bill : bills) { + rows.add(ArBillListExportRow.from(bill)); + } + ExcelUtil util = new ExcelUtil<>(ArBillListExportRow.class); + util.exportExcel(response, rows, "应收账单"); + } + /** * 查询账单头信息;账单明细通过独立分页接口按需加载。 */ diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillListExportRow.java b/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillListExportRow.java new file mode 100644 index 00000000..5c156e73 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillListExportRow.java @@ -0,0 +1,66 @@ +package com.bms.ar.domain.vo; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +import com.bms.ar.domain.ArBill; +import com.bms.ar.enums.ArBillStatus; +import com.bms.common.annotation.Excel; +import lombok.Data; + +/** 应收账单列表 Excel 导出行。 */ +@Data +public class ArBillListExportRow implements Serializable { + private static final long serialVersionUID = 1L; + + @Excel(name = "账单号", sort = 0, width = 22) + private String billNo; + + @Excel(name = "账单名称", sort = 1, width = 24) + private String billName; + + @Excel(name = "客户名称", sort = 2, width = 24) + private String customerName; + + @Excel(name = "客户编码", sort = 3, width = 16) + private String customerCode; + + @Excel(name = "账单截止日", sort = 4, dateFormat = "yyyy-MM-dd", width = 16) + private Date billPeriodEnd; + + @Excel(name = "订单数", sort = 5, width = 12) + private Integer orderCount; + + @Excel(name = "应收总额", sort = 6, scale = 2, width = 16) + private BigDecimal totalAmount; + + @Excel(name = "已核销", sort = 7, scale = 2, width = 16) + private BigDecimal writtenOffAmount; + + @Excel(name = "未核销", sort = 8, scale = 2, width = 16) + private BigDecimal unwrittenAmount; + + @Excel(name = "状态", sort = 9, width = 14) + private String status; + + @Excel(name = "账单日期", sort = 10, dateFormat = "yyyy-MM-dd", width = 16) + private Date billDate; + + public static ArBillListExportRow from(ArBill bill) { + ArBillListExportRow row = new ArBillListExportRow(); + row.setBillNo(bill.getBillNo()); + row.setBillName(bill.getBillName()); + row.setCustomerName(bill.getCustomerName()); + row.setCustomerCode(bill.getCustomerCode()); + row.setBillPeriodEnd(bill.getBillPeriodEnd()); + row.setOrderCount(bill.getOrderCount()); + row.setTotalAmount(bill.getTotalAmount()); + row.setWrittenOffAmount(bill.getWrittenOffAmount()); + row.setUnwrittenAmount(bill.getUnwrittenAmount()); + ArBillStatus billStatus = ArBillStatus.of(bill.getStatus()); + row.setStatus(billStatus == null ? bill.getStatus() : billStatus.getLabel()); + row.setBillDate(bill.getBillDate()); + return row; + } +} diff --git a/bms-front/src/views/ar/bill/index.vue b/bms-front/src/views/ar/bill/index.vue index f7fa3bc3..e9462e3b 100644 --- a/bms-front/src/views/ar/bill/index.vue +++ b/bms-front/src/views/ar/bill/index.vue @@ -32,6 +32,9 @@ 生成账单 清除客户条件 + + 导出 + @@ -159,7 +162,22 @@ const searchColumns = [ ] // 将页面日期范围转换为后端查询字段,其他筛选条件原样透传。 -function queryList(params) { const query = { ...params }; if (query.billDateRange?.length === 2) { query.billDateStart = query.billDateRange[0]; query.billDateEnd = query.billDateRange[1] }; delete query.billDateRange; return listArBill(query) } +function normalizeBillQuery(params) { + const query = { ...params } + if (query.billDateRange?.length === 2) { + query.billDateStart = query.billDateRange[0] + query.billDateEnd = query.billDateRange[1] + } + delete query.billDateRange + return query +} +function queryList(params) { return listArBill(normalizeBillQuery(params)) } +function handleExport() { + const query = normalizeBillQuery(tableRef.value?.getQueryParams() || defaultSearchParams.value) + delete query.pageNum + delete query.pageSize + proxy.download('/ar/bill/export', query, `ar_bill_${Date.now()}.xlsx`) +} // 生成弹窗只提交任务,账单明细由后台异步批量写入;这里负责刷新列表并开始轮询。 function handleGenerateSuccess(task) { tableRef.value?.refresh() From db787ec7f7aa7c0bab71026d5acfac43932718cd Mon Sep 17 00:00:00 2001 From: caojia <1301869380@qq.com> Date: Tue, 27 Oct 2026 17:21:12 +0800 Subject: [PATCH 3/3] =?UTF-8?q?:sparkles:=20=E5=AE=A2=E6=88=B7=E8=B4=A6?= =?UTF-8?q?=E5=8D=95=E5=BC=B9=E7=AA=97=E5=A2=9E=E5=8A=A0=E6=B1=87=E6=80=BB?= =?UTF-8?q?=E5=92=8C=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../customermoney/CustomerBillController.java | 44 +++++++++++++-- .../com/bms/ar/domain/vo/ArBillSummary.java | 16 ++++++ .../java/com/bms/ar/mapper/ArBillMapper.java | 3 ++ .../com/bms/ar/service/IArBillService.java | 3 ++ .../ar/service/impl/ArBillServiceImpl.java | 9 ++++ .../main/resources/mapper/ar/ArBillMapper.xml | 22 +++++++- bms-front/src/components/BasicTable/index.vue | 31 +++++++---- .../customermoney/CustomerBillListDialog.vue | 54 ++++++++++++++++++- 8 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillSummary.java diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customermoney/CustomerBillController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customermoney/CustomerBillController.java index 2ed695b2..fc2e6063 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customermoney/CustomerBillController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/customer/customermoney/CustomerBillController.java @@ -1,7 +1,9 @@ package com.bms.web.controller.customer.customermoney; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.GetMapping; @@ -13,7 +15,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.bms.ar.domain.ArBill; import com.bms.ar.domain.ArBalanceWriteoff; +import com.bms.ar.domain.vo.ArBillListExportRow; import com.bms.ar.domain.vo.ArBillQuery; +import com.bms.ar.domain.vo.ArBillSummary; import com.bms.ar.service.IArBalanceWriteoffService; import com.bms.ar.service.IArBillService; import com.bms.common.annotation.Log; @@ -21,6 +25,7 @@ import com.bms.common.core.controller.BaseController; import com.bms.common.core.domain.AjaxResult; import com.bms.common.core.page.TableDataInfo; import com.bms.common.enums.BusinessType; +import com.bms.common.utils.poi.ExcelUtil; /** * 客户余额账单查询与核销 Controller @@ -43,17 +48,50 @@ public class CustomerBillController extends BaseController */ @PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:list')") @GetMapping("/list/{customerId}") - public TableDataInfo billList(@PathVariable("customerId") Long customerId, ArBillQuery query) + public AjaxResult billList(@PathVariable("customerId") Long customerId, ArBillQuery query) { if (customerId == null || customerId <= 0L) { - return getDataTable(Collections.emptyList()); + AjaxResult result = success(); + result.put("rows", Collections.emptyList()); + result.put("total", 0L); + result.put("summary", new ArBillSummary()); + return result; } ArBillQuery billQuery = query == null ? new ArBillQuery() : query; billQuery.setCustomerId(customerId); startPage(); List list = billService.selectArBillList(billQuery); - return getDataTable(list); + TableDataInfo pageData = getDataTable(list); + AjaxResult result = success(); + result.put("rows", pageData.getRows()); + result.put("total", pageData.getTotal()); + result.put("summary", billService.selectArBillSummary(billQuery)); + return result; + } + + /** + * 按当前筛选条件导出指定客户的全部应收账单,不受列表分页参数影响。 + */ + @PreAuthorize("@ss.hasPermi('customersupplier:customerinfo:export')") + @Log(title = "客户账单", businessType = BusinessType.EXPORT) + @PostMapping("/export/{customerId}") + public void export(HttpServletResponse response, @PathVariable("customerId") Long customerId, ArBillQuery query) + { + List rows = new ArrayList<>(); + if (customerId != null && customerId > 0L) + { + ArBillQuery billQuery = query == null ? new ArBillQuery() : query; + // 客户ID固定取自路径,忽略请求参数中可能出现的 customerId。 + billQuery.setCustomerId(customerId); + List bills = billService.selectArBillList(billQuery); + for (ArBill bill : bills) + { + rows.add(ArBillListExportRow.from(bill)); + } + } + ExcelUtil util = new ExcelUtil<>(ArBillListExportRow.class); + util.exportExcel(response, rows, "客户账单"); } /** diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillSummary.java b/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillSummary.java new file mode 100644 index 00000000..0c76a186 --- /dev/null +++ b/bms-back/bms-system/src/main/java/com/bms/ar/domain/vo/ArBillSummary.java @@ -0,0 +1,16 @@ +package com.bms.ar.domain.vo; + +import java.io.Serializable; +import java.math.BigDecimal; + +import lombok.Data; + +/** 应收账单列表按筛选条件汇总的金额。 */ +@Data +public class ArBillSummary implements Serializable { + private static final long serialVersionUID = 1L; + + private BigDecimal totalAmount = BigDecimal.ZERO; + private BigDecimal writtenOffAmount = BigDecimal.ZERO; + private BigDecimal unwrittenAmount = BigDecimal.ZERO; +} diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/mapper/ArBillMapper.java b/bms-back/bms-system/src/main/java/com/bms/ar/mapper/ArBillMapper.java index be476768..2b0b16d3 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/mapper/ArBillMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/mapper/ArBillMapper.java @@ -7,10 +7,13 @@ import java.util.List; import org.apache.ibatis.annotations.Param; import com.bms.ar.domain.ArBill; import com.bms.ar.domain.vo.ArBillQuery; +import com.bms.ar.domain.vo.ArBillSummary; public interface ArBillMapper { List selectArBillList(ArBillQuery query); + ArBillSummary selectArBillSummary(ArBillQuery query); + ArBill selectArBillById(Long arBillId); ArBill selectArBillByBillNo(String billNo); diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java b/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java index 46fca5b6..609cc1dd 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/service/IArBillService.java @@ -14,6 +14,7 @@ import com.bms.ar.domain.vo.ArBillGenerateRequest; import com.bms.ar.domain.vo.ArBillGenerateQuery; import com.bms.ar.domain.vo.ArBillActionRequest; import com.bms.ar.domain.vo.ArBillQuery; +import com.bms.ar.domain.vo.ArBillSummary; import com.bms.price.domain.PrcOrderBill; /** @@ -25,6 +26,8 @@ public interface IArBillService { List selectArBillList(ArBillQuery query); + ArBillSummary selectArBillSummary(ArBillQuery query); + ArBill selectArBillById(Long arBillId); List selectArBillDetails(Long arBillId); diff --git a/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java index 9259d29c..16d18791 100644 --- a/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/ar/service/impl/ArBillServiceImpl.java @@ -79,6 +79,7 @@ import com.bms.ar.domain.vo.ArBillActionRequest; import com.bms.ar.domain.vo.ArBillGenerateQuery; import com.bms.ar.domain.vo.ArBillGenerateRequest; import com.bms.ar.domain.vo.ArBillQuery; +import com.bms.ar.domain.vo.ArBillSummary; import com.bms.common.config.BmsConfig; import com.bms.common.exception.ServiceException; import com.bms.common.utils.DateUtils; @@ -223,6 +224,14 @@ public class ArBillServiceImpl implements IArBillService { return bills; } + /** + * 汇总当前筛选条件下的全部账单金额,不受列表分页影响。 + */ + @Override + public ArBillSummary selectArBillSummary(ArBillQuery query) { + return billMapper.selectArBillSummary(query); + } + /** * 查询账单头信息;导出记录随账单头返回,明细由独立分页接口查询。 */ diff --git a/bms-back/bms-system/src/main/resources/mapper/ar/ArBillMapper.xml b/bms-back/bms-system/src/main/resources/mapper/ar/ArBillMapper.xml index aa835a73..e695f45e 100644 --- a/bms-back/bms-system/src/main/resources/mapper/ar/ArBillMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/ar/ArBillMapper.xml @@ -35,6 +35,12 @@ + + + + + + select ar_bill_id, bill_no, @@ -67,8 +73,7 @@ from ar_bill - - + and (generation_status is null or generation_status = 'READY') and bill_no like concat('%', #{billNo}, '%') @@ -86,9 +91,22 @@ and bill_date <= #{billDateEnd} and bill_period_end = #{billPeriodEnd} + + + + + order by create_time desc, ar_bill_id desc + + select coalesce(sum(total_amount), 0) as total_amount, + coalesce(sum(written_off_amount), 0) as written_off_amount, + coalesce(sum(unwritten_amount), 0) as unwritten_amount + from ar_bill + + + where ar_bill_id = #{arBillId} diff --git a/bms-front/src/components/BasicTable/index.vue b/bms-front/src/components/BasicTable/index.vue index 107d10cc..7562a7dd 100644 --- a/bms-front/src/components/BasicTable/index.vue +++ b/bms-front/src/components/BasicTable/index.vue @@ -126,15 +126,18 @@ - - + + + + + @@ -727,6 +730,16 @@ onBeforeUnmount(() => { .basic-table { width: 100%; } +.basic-table-pagination--with-extra { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + flex-wrap: wrap; +} +.basic-table-pagination--with-extra :deep(.pagination-container) { + margin-left: auto; +} .basic-table-virtual { width: 100%; min-height: 240px; diff --git a/bms-front/src/views/customersuppliermanagement/customerinfo/customermoney/CustomerBillListDialog.vue b/bms-front/src/views/customersuppliermanagement/customerinfo/customermoney/CustomerBillListDialog.vue index d888b2b1..274e27d8 100644 --- a/bms-front/src/views/customersuppliermanagement/customerinfo/customermoney/CustomerBillListDialog.vue +++ b/bms-front/src/views/customersuppliermanagement/customerinfo/customermoney/CustomerBillListDialog.vue @@ -16,8 +16,24 @@ :border="true" :max-height="560" :page-size="10" + ref="tableRef" row-key="arBillId" > + + 导出 + + + + 应收总额:{{ money(billSummary.totalAmount) }} + 已核销:{{ money(billSummary.writtenOffAmount) }} + 未核销:{{ money(billSummary.unwrittenAmount) }} + + {{ statusText(row.status) }} @@ -38,7 +54,7 @@