From 6011e29abf218c73cafd69133b8a8680b368b4d7 Mon Sep 17 00:00:00 2001 From: gaoxq <376340421@qq.com> Date: Mon, 23 Mar 2026 17:38:35 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/apps/Module/ChartDataItem.java | 124 ++++ .../modules/apps/web/ErpScreenController.java | 168 ++++++ .../erp/entity/ErpTransactionFlow.java | 4 +- .../modules/utils/BigDecimalUtils.java | 16 + .../packages/core/layouts/screen/index.vue | 11 +- .../welcome/Erp/components/ChartV03.vue | 494 ++++++++-------- .../welcome/Erp/components/ChartV04.vue | 429 +++++++------- .../welcome/Erp/components/ChartV05.vue | 429 +++++++------- .../welcome/Erp/components/ChartV06.vue | 559 +++++++++--------- .../welcome/Erp/components/ChartV07.vue | 360 +++++------ .../views/screen/welcome/Erp/index.vue | 6 +- web-vue/packages/erp/api/erp/screen.ts | 62 ++ 12 files changed, 1554 insertions(+), 1108 deletions(-) create mode 100644 web-api/src/main/java/com/jeesite/modules/apps/Module/ChartDataItem.java create mode 100644 web-api/src/main/java/com/jeesite/modules/apps/web/ErpScreenController.java create mode 100644 web-vue/packages/erp/api/erp/screen.ts diff --git a/web-api/src/main/java/com/jeesite/modules/apps/Module/ChartDataItem.java b/web-api/src/main/java/com/jeesite/modules/apps/Module/ChartDataItem.java new file mode 100644 index 0000000..b2dc39c --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/Module/ChartDataItem.java @@ -0,0 +1,124 @@ +package com.jeesite.modules.apps.Module; + +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; + +@Data +public class ChartDataItem implements Serializable { + /** + * 项目编号 + */ + private String itemCode; + + /** + * 序号 + */ + private Long soring; + + /** + * X轴名称 + */ + private String axisName; + + /** + * 指标01 + */ + private String value01; + + /** + * 指标02 + */ + private String value02; + + /** + * 指标03 + */ + private String value03; + + /** + * 指标04 + */ + private String value04; + + /** + * 指标05 + */ + private String value05; + + /** + * 指标06 + */ + private String value06; + + /** + * 指标07 + */ + private String value07; + + /** + * 指标08 + */ + private String value08; + + /** + * 指标09 + */ + private String value09; + + /** + * 指标10 + */ + private String value10; + + /** + * 指标11 + */ + private String value11; + + /** + * 指标12 + */ + private String value12; + + /** + * 指标13 + */ + private String value13; + + /** + * 指标14 + */ + private String value14; + + /** + * 指标15 + */ + private String value15; + + /** + * 业务主键编号 + */ + private String bizKey; + + /** + * 指标求和 + */ + private BigDecimal indexSum; + + /** + * 指标平均 + */ + private BigDecimal indexAvg; + + /** + * 指标最大 + */ + private BigDecimal indexMax; + + /** + * 指标最小 + */ + private BigDecimal indexMin; +} diff --git a/web-api/src/main/java/com/jeesite/modules/apps/web/ErpScreenController.java b/web-api/src/main/java/com/jeesite/modules/apps/web/ErpScreenController.java new file mode 100644 index 0000000..241a12e --- /dev/null +++ b/web-api/src/main/java/com/jeesite/modules/apps/web/ErpScreenController.java @@ -0,0 +1,168 @@ +package com.jeesite.modules.apps.web; + +import com.jeesite.modules.apps.Module.ChartDataItem; +import com.jeesite.modules.erp.entity.ErpTransactionFlow; +import com.jeesite.modules.erp.service.ErpTransactionFlowService; +import com.jeesite.modules.utils.BigDecimalUtils; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Controller +@RequestMapping(value = "${adminPath}/erp/screen") +public class ErpScreenController { + + private final ErpTransactionFlowService erpTransactionFlowService; + + + public ErpScreenController(ErpTransactionFlowService erpTransactionFlowService) { + this.erpTransactionFlowService = erpTransactionFlowService; + } + + + /** + * 账号收支 + */ + @RequestMapping(value = "getErpAccountChart") + @ResponseBody + public List getErpAccountChart(ErpTransactionFlow erpTransactionFlow) { + List chartDataItems = new ArrayList<>(); + List flowList = erpTransactionFlowService.findList(erpTransactionFlow); + Map> accountMap = flowList.stream() + .collect(Collectors.groupingBy( + ErpTransactionFlow::getAccountName, + Collectors.collectingAndThen(Collectors.toList(), list -> { + String accountId = list.stream() + .findFirst() + .map(ErpTransactionFlow::getAccountId) + .orElse(""); + BigDecimal sumValue01 = list.stream() + .filter(flow -> flow.getFlowType().equals("2")) + .map(ErpTransactionFlow::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal sumValue02 = list.stream() + .filter(flow -> flow.getFlowType().equals("1")) + .map(ErpTransactionFlow::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal sumValue03 = BigDecimalUtils.subtract(sumValue01, sumValue02); + + return Map.of( + "accountId", accountId, + "sumValue01", sumValue01, + "sumValue02", sumValue02, + "sumValue03", sumValue03 + ); + }) + )); + for (Map.Entry> entry : accountMap.entrySet()) { + String accountName = entry.getKey(); + Map map = entry.getValue(); + ChartDataItem item = new ChartDataItem(); + item.setItemCode("CHART"); + item.setAxisName(accountName); + item.setValue01(map.get("sumValue01").toString()); + item.setValue02(map.get("sumValue02").toString()); + item.setValue03(map.get("sumValue03").toString()); + item.setBizKey(map.get("accountId").toString()); + chartDataItems.add(item); + } + return chartDataItems; + } + + /** + * 月份收支 + */ + @RequestMapping(value = "getErpMonthChart") + @ResponseBody + public List getErpMonthChart(ErpTransactionFlow erpTransactionFlow) { + List chartDataItems = new ArrayList<>(); + List flowList = erpTransactionFlowService.findList(erpTransactionFlow); + Map> accountMap = flowList.stream() + .collect(Collectors.groupingBy( + ErpTransactionFlow::getMonthDate, + Collectors.collectingAndThen(Collectors.toList(), list -> { + BigDecimal sumValue01 = list.stream() + .filter(flow -> flow.getFlowType().equals("2")) + .map(ErpTransactionFlow::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal sumValue02 = list.stream() + .filter(flow -> flow.getFlowType().equals("1")) + .map(ErpTransactionFlow::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal sumValue04 = BigDecimalUtils.subtract(sumValue01, sumValue02); + BigDecimal sumValue03 = BigDecimalUtils.percent(sumValue04, sumValue01); + return Map.of( + "sumValue01", sumValue01, + "sumValue02", sumValue02, + "sumValue03", sumValue03, + "sumValue04", sumValue04 + ); + }) + )); + for (Map.Entry> entry : accountMap.entrySet()) { + String monthDate = entry.getKey(); + Map map = entry.getValue(); + ChartDataItem item = new ChartDataItem(); + item.setAxisName(monthDate); + item.setValue01(map.get("sumValue01").toString()); + item.setValue02(map.get("sumValue02").toString()); + item.setValue03(map.get("sumValue03").toString()); + item.setValue04(map.get("sumValue04").toString()); + chartDataItems.add(item); + } + return chartDataItems; + } + + + /** + * 分类收支 + */ + @RequestMapping(value = "getCategoryChart") + @ResponseBody + public List getCategoryChart(ErpTransactionFlow erpTransactionFlow) { + List chartDataItems = new ArrayList<>(); + List flowList = erpTransactionFlowService.findList(erpTransactionFlow); + BigDecimal totalAmount = flowList.stream() + .map(ErpTransactionFlow::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + Map> accountMap = flowList.stream() + .collect(Collectors.groupingBy( + ErpTransactionFlow::getCategoryName, + Collectors.collectingAndThen(Collectors.toList(), list -> { + BigDecimal sumValue01 = list.stream() + .map(ErpTransactionFlow::getAmount) + .reduce(BigDecimal.ZERO, BigDecimal::add); + BigDecimal sumValue02 = BigDecimalUtils.percent(sumValue01, totalAmount); + return Map.of( + "sumValue01", sumValue01, + "sumValue02", sumValue02 + ); + }) + )); + List>> sortedList = new ArrayList<>(accountMap.entrySet()); + sortedList.sort((e1, e2) -> { + BigDecimal v1 = (BigDecimal) e1.getValue().get("sumValue02"); + BigDecimal v2 = (BigDecimal) e2.getValue().get("sumValue02"); + return v2.compareTo(v1); + }); + long soring = 1; + for (Map.Entry> entry : sortedList) { + String categoryName = entry.getKey(); + Map map = entry.getValue(); + ChartDataItem item = new ChartDataItem(); + item.setSoring(soring++); + item.setAxisName(categoryName); + item.setValue01(map.get("sumValue01").toString()); + item.setValue02(map.get("sumValue02").toString()); + chartDataItems.add(item); + } + return chartDataItems; + } + +} diff --git a/web-api/src/main/java/com/jeesite/modules/erp/entity/ErpTransactionFlow.java b/web-api/src/main/java/com/jeesite/modules/erp/entity/ErpTransactionFlow.java index 48015a8..071811d 100644 --- a/web-api/src/main/java/com/jeesite/modules/erp/entity/ErpTransactionFlow.java +++ b/web-api/src/main/java/com/jeesite/modules/erp/entity/ErpTransactionFlow.java @@ -42,8 +42,8 @@ import java.io.Serial; @Column(name = "remark", attrName = "remark", label = "交易备注", isQuery = false), @Column(name = "update_time", attrName = "updateTime", label = "更新时间", isQuery = false, isUpdateForce = true), @Column(name = "business_id", attrName = "businessId", label = "业务标识"), - @Column(name = "year_date", attrName = "yearDate", label = "业务标识"), - @Column(name = "month_date", attrName = "monthDate", label = "业务标识"), + @Column(name = "year_date", attrName = "yearDate", label = "年份"), + @Column(name = "month_date", attrName = "monthDate", label = "月份"), }, joinTable = { @JoinTable(type = Type.LEFT_JOIN, entity = ErpAccount.class, alias = "b", on = "a.account_id = b.account_id", attrName = "this", diff --git a/web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java b/web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java index 14eca71..ecb1525 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java +++ b/web-api/src/main/java/com/jeesite/modules/utils/BigDecimalUtils.java @@ -48,6 +48,22 @@ public class BigDecimalUtils { return num1.divide(num2, SCALE, ROUND_MODE); } + /** + * 百分比 + */ + public static BigDecimal percent(BigDecimal num1, BigDecimal num2) { + num1 = defaultIfNull(num1); + num2 = defaultIfNull(num2); + + if (num2.compareTo(BigDecimal.ZERO) == 0) { + return BigDecimal.ZERO; + } + // 先除 → 再 ×100 → 保留2位 + return num1.divide(num2, 4, ROUND_MODE) + .multiply(new BigDecimal("100")) + .setScale(SCALE, ROUND_MODE); + } + private static BigDecimal defaultIfNull(BigDecimal num) { return num == null ? BigDecimal.ZERO : num; } diff --git a/web-vue/packages/core/layouts/screen/index.vue b/web-vue/packages/core/layouts/screen/index.vue index 68ee9e0..09586f5 100644 --- a/web-vue/packages/core/layouts/screen/index.vue +++ b/web-vue/packages/core/layouts/screen/index.vue @@ -73,8 +73,9 @@ const switchTabByRoute = (item) => { router.push({ path: item.path, query: { - year: queryDate.value, - ...route.query + ...route.query, + yearDate: queryDate.value, + } }).catch(err => { ElMessage.error('页面切换失败,请重试'); @@ -90,7 +91,7 @@ const handleQuery = () => { path: route.path, query: { ...route.query, - year: queryDate.value + yearDate: queryDate.value, } }); }; @@ -112,8 +113,8 @@ async function getList() { onMounted(() => { getList(); router.afterEach((to) => { - if (to.query.year) { - queryDate.value = to.query.year; + if (to.query.yearDate) { + queryDate.value = to.query.yearDate; } }); }); diff --git a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV03.vue b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV03.vue index efa082c..6b6e374 100644 --- a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV03.vue +++ b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV03.vue @@ -7,197 +7,201 @@ - \ No newline at end of file + .bar-line-chart-container { + flex: 1; + width: 100%; + height: calc(100% - 40px); + } + diff --git a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV04.vue b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV04.vue index 60672dd..90b0b35 100644 --- a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV04.vue +++ b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV04.vue @@ -7,222 +7,245 @@ - \ No newline at end of file + :deep(.ec-label-line) { + stroke: #e0e6ff !important; + stroke-width: 1px !important; + } + diff --git a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV05.vue b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV05.vue index 3cf706d..c01acc1 100644 --- a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV05.vue +++ b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV05.vue @@ -7,222 +7,245 @@ - \ No newline at end of file + :deep(.ec-label-line) { + stroke: #e0e6ff !important; + stroke-width: 1px !important; + } + diff --git a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV06.vue b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV06.vue index 7a5c7ca..1499888 100644 --- a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV06.vue +++ b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV06.vue @@ -7,225 +7,236 @@ - \ No newline at end of file + .bar-line-chart-container { + flex: 1; + width: 100%; + height: calc(100% - 40px); + } + diff --git a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV07.vue b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV07.vue index 6bb65aa..15dc0ca 100644 --- a/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV07.vue +++ b/web-vue/packages/core/layouts/views/screen/welcome/Erp/components/ChartV07.vue @@ -7,202 +7,208 @@ - \ No newline at end of file + :deep(.echarts-tooltip) { + background-color: rgba(145, 200, 255, 0.9) !important; + border-color: #409eff !important; + color: #0a3b70 !important; + border-radius: 6px !important; + } + diff --git a/web-vue/packages/core/layouts/views/screen/welcome/Erp/index.vue b/web-vue/packages/core/layouts/views/screen/welcome/Erp/index.vue index 6a5f7db..c68aafb 100644 --- a/web-vue/packages/core/layouts/views/screen/welcome/Erp/index.vue +++ b/web-vue/packages/core/layouts/views/screen/welcome/Erp/index.vue @@ -93,7 +93,7 @@ const route = useRoute(); // 1. 完善类型定义,避免 any 类型 const FormValues = ref({ - reqParam: route.query.year || '' + yearDate: route.query.yearDate || '' }); // 2. 定义组件映射的类型 @@ -143,9 +143,9 @@ async function getChartList() { // 7. 监听路由参数变化 watch( - () => route.query.year, + () => route.query.yearDate, (newVal) => { - FormValues.value.reqParam = newVal || ''; + FormValues.value.yearDate = newVal || ''; }, { deep: true, diff --git a/web-vue/packages/erp/api/erp/screen.ts b/web-vue/packages/erp/api/erp/screen.ts new file mode 100644 index 0000000..d426977 --- /dev/null +++ b/web-vue/packages/erp/api/erp/screen.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) 2013-Now https://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + * @author gaoxq + */ +import { defHttp } from '@jeesite/core/utils/http/axios'; +import { useGlobSetting } from '@jeesite/core/hooks/setting'; +import { BasicModel } from '@jeesite/core/api/model/baseModel'; + +const { adminPath } = useGlobSetting(); + +export interface ErpTransactionFlow extends BasicModel { + createTime?: string; // 记录时间 + flowId?: string; // 流水 + flowName: string; // 交易名称 + flowType: string; // 交易类型 + amount: number; // 交易金额 + tradeTime: string; // 交易时间 + accountId: string; // 交易账户 + categoryId: string; // 交易分类 + remark?: string; // 交易备注 + updateTime?: string; // 更新时间 + businessId: string; // 业务标识 + yearDate: string; //年份 + monthDate: string; //月份 +} + + +export interface ChartDataItem extends BasicModel { + itemCode: string; // 项目编号 + soring: number; // 序号 + axisName: string; // X轴名称 + value01: string; // 指标01 + value02: string; // 指标02 + value03: string; // 指标03 + value04: string; // 指标04 + value05: string; // 指标05 + value06: string; // 指标06 + value07: string; // 指标07 + value08: string; // 指标08 + value09: string; // 指标09 + value10: string; // 指标10 + value11: string; // 指标11 + value12: string; // 指标12 + value13: string; // 指标13 + value14: string; // 指标14 + value15: string; // 指标15 + bizKey: string; // 业务主键编号 + indexSum: number; // 指标求和 + indexAvg: number; // 指标平均 + indexMax: number; // 指标最大 + indexMin: number; // 指标最小 +} + +export const ErpMonthChart = (params?: ErpTransactionFlow | any) => + defHttp.get({ url: adminPath + '/erp/screen/getErpMonthChart', params }); + +export const CategoryChart = (params?: ErpTransactionFlow | any) => + defHttp.get({ url: adminPath + '/erp/screen/getCategoryChart', params }); + +export const ErpAccountChart = (params?: ErpTransactionFlow | any) => + defHttp.get({ url: adminPath + '/erp/screen/getErpAccountChart', params });