diff --git a/gear-oa/src/main/java/com/gear/oa/controller/GearDashboardController.java b/gear-oa/src/main/java/com/gear/oa/controller/GearDashboardController.java new file mode 100644 index 0000000..bb7977f --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/controller/GearDashboardController.java @@ -0,0 +1,35 @@ +package com.gear.oa.controller; + +import com.gear.common.core.controller.BaseController; +import com.gear.common.core.domain.R; +import com.gear.oa.domain.vo.dashboard.DashboardOverviewVO; +import com.gear.oa.service.IGearDashboardService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 仪表板控制器 + * + * @author Joshi + * @date 2025-09-17 + */ +@RequiredArgsConstructor +@RestController +@RequestMapping("/oa/dashboard") +public class GearDashboardController extends BaseController { + + private final IGearDashboardService dashboardService; + + /** + * 获取仪表板总览数据 + * + * @return 仪表板总览数据 + */ + @GetMapping("/overview") + public R getDashboardOverview() { + DashboardOverviewVO overview = dashboardService.getDashboardOverview(); + return R.ok(overview); + } +} diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/DailyTrendVO.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/DailyTrendVO.java new file mode 100644 index 0000000..9f8e71b --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/DailyTrendVO.java @@ -0,0 +1,43 @@ +package com.gear.oa.domain.vo.dashboard; + +import lombok.Data; +import java.math.BigDecimal; + +/** + * 日趋势数据VO + * + * @author Joshi + * @date 2025-09-17 + */ +@Data +public class DailyTrendVO { + + /** + * 日期(格式:MM-dd) + */ + private String date; + + /** + * 数值(订单数量或薪资金额) + */ + private BigDecimal value; + + /** + * 标签(用于显示) + */ + private String label; + + public DailyTrendVO() {} + + public DailyTrendVO(String date, BigDecimal value) { + this.date = date; + this.value = value; + this.label = date; + } + + public DailyTrendVO(String date, BigDecimal value, String label) { + this.date = date; + this.value = value; + this.label = label; + } +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/DashboardOverviewVO.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/DashboardOverviewVO.java new file mode 100644 index 0000000..226c4c9 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/DashboardOverviewVO.java @@ -0,0 +1,35 @@ +package com.gear.oa.domain.vo.dashboard; + +import lombok.Data; +import java.math.BigDecimal; +import java.util.List; + +/** + * 仪表板总览VO + * + * @author Joshi + * @date 2025-09-17 + */ +@Data +public class DashboardOverviewVO { + + /** + * 订单统计数据 + */ + private OrderStatisticsVO orderStatistics; + + /** + * 薪资支出统计数据 + */ + private SalaryStatisticsVO salaryStatistics; + + /** + * 库存排行数据 + */ + private List stockRanking; + + /** + * 其他统计数据 + */ + private OtherStatisticsVO otherStatistics; +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/OrderStatisticsVO.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/OrderStatisticsVO.java new file mode 100644 index 0000000..2f5a3d2 --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/OrderStatisticsVO.java @@ -0,0 +1,45 @@ +package com.gear.oa.domain.vo.dashboard; + +import lombok.Data; +import java.math.BigDecimal; +import java.util.List; + +/** + * 订单统计VO + * + * @author Joshi + * @date 2025-09-17 + */ +@Data +public class OrderStatisticsVO { + + /** + * 今日订单数 + */ + private Integer todayOrderCount; + + /** + * 本周订单数 + */ + private Integer weekOrderCount; + + /** + * 本月订单数 + */ + private Integer monthOrderCount; + + /** + * 近一周订单数量趋势(7天数据) + */ + private List weeklyTrend; + + /** + * 订单总金额(本周) + */ + private BigDecimal weekTotalAmount; + + /** + * 与上周对比增长率 + */ + private BigDecimal growthRate; +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/OtherStatisticsVO.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/OtherStatisticsVO.java new file mode 100644 index 0000000..91a307b --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/OtherStatisticsVO.java @@ -0,0 +1,54 @@ +package com.gear.oa.domain.vo.dashboard; + +import lombok.Data; +import java.math.BigDecimal; + +/** + * 其他统计数据VO + * + * @author Joshi + * @date 2025-09-17 + */ +@Data +public class OtherStatisticsVO { + + /** + * 活跃客户数 + */ + private Integer activeCustomerCount; + + /** + * 待处理订单数 + */ + private Integer pendingOrderCount; + + /** + * 库存预警数量 + */ + private Integer lowStockCount; + + /** + * 本月营收 + */ + private BigDecimal monthlyRevenue; + + /** + * 员工总数 + */ + private Integer totalEmployeeCount; + + /** + * 今日出勤率 + */ + private BigDecimal todayAttendanceRate; + + /** + * 产品总数 + */ + private Integer totalProductCount; + + /** + * 供应商总数 + */ + private Integer totalSupplierCount; +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/SalaryStatisticsVO.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/SalaryStatisticsVO.java new file mode 100644 index 0000000..2d6521d --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/SalaryStatisticsVO.java @@ -0,0 +1,45 @@ +package com.gear.oa.domain.vo.dashboard; + +import lombok.Data; +import java.math.BigDecimal; +import java.util.List; + +/** + * 薪资统计VO + * + * @author Joshi + * @date 2025-09-17 + */ +@Data +public class SalaryStatisticsVO { + + /** + * 今日薪资支出 + */ + private BigDecimal todaySalary; + + /** + * 本周薪资支出 + */ + private BigDecimal weekSalary; + + /** + * 本月薪资支出 + */ + private BigDecimal monthSalary; + + /** + * 近一周薪资支出趋势(7天数据) + */ + private List weeklyTrend; + + /** + * 与上周对比增长率 + */ + private BigDecimal growthRate; + + /** + * 平均日薪资支出 + */ + private BigDecimal avgDailySalary; +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/StockRankingVO.java b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/StockRankingVO.java new file mode 100644 index 0000000..7ae86ee --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/domain/vo/dashboard/StockRankingVO.java @@ -0,0 +1,69 @@ +package com.gear.oa.domain.vo.dashboard; + +import lombok.Data; +import java.math.BigDecimal; + +/** + * 库存排行VO + * + * @author Joshi + * @date 2025-09-17 + */ +@Data +public class StockRankingVO { + + /** + * 排名 + */ + private Integer rank; + + /** + * 物品ID + */ + private Long itemId; + + /** + * 物品名称 + */ + private String itemName; + + /** + * 物品编号 + */ + private String itemCode; + + /** + * 物品类型(raw_material/product) + */ + private String itemType; + + /** + * 物品类型名称 + */ + private String itemTypeName; + + /** + * 库存数量 + */ + private BigDecimal quantity; + + /** + * 单位 + */ + private String unit; + + /** + * 仓库名称 + */ + private String warehouseName; + + /** + * 产品分类(如果是产品) + */ + private String categoryName; + + /** + * 负责人 + */ + private String owner; +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/mapper/GearDashboardMapper.java b/gear-oa/src/main/java/com/gear/oa/mapper/GearDashboardMapper.java new file mode 100644 index 0000000..aa1e46c --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/mapper/GearDashboardMapper.java @@ -0,0 +1,118 @@ +package com.gear.oa.mapper; + +import com.gear.oa.domain.vo.dashboard.StockRankingVO; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * 仪表板数据访问层 + * + * @author Joshi + * @date 2025-09-17 + */ +@Mapper +public interface GearDashboardMapper { + + /** + * 获取今日订单数 + */ + Integer getTodayOrderCount(); + + /** + * 获取本周订单数 + */ + Integer getWeekOrderCount(); + + /** + * 获取本月订单数 + */ + Integer getMonthOrderCount(); + + /** + * 获取上周订单数 + */ + Integer getLastWeekOrderCount(); + + /** + * 获取本周订单总金额 + */ + BigDecimal getWeekOrderAmount(); + + /** + * 获取近一周订单趋势 + */ + List> getWeeklyOrderTrend(); + + /** + * 获取今日薪资支出 + */ + BigDecimal getTodaySalary(); + + /** + * 获取本周薪资支出 + */ + BigDecimal getWeekSalary(); + + /** + * 获取本月薪资支出 + */ + BigDecimal getMonthSalary(); + + /** + * 获取上周薪资支出 + */ + BigDecimal getLastWeekSalary(); + + /** + * 获取近一周薪资趋势 + */ + List> getWeeklySalaryTrend(); + + /** + * 获取库存排行(前10) + */ + List getStockRanking(); + + /** + * 获取活跃客户数 + */ + Integer getActiveCustomerCount(); + + /** + * 获取待处理订单数 + */ + Integer getPendingOrderCount(); + + /** + * 获取库存预警数量 + */ + Integer getLowStockCount(); + + /** + * 获取本月营收 + */ + BigDecimal getMonthlyRevenue(); + + /** + * 获取员工总数 + */ + Integer getTotalEmployeeCount(); + + /** + * 获取今日出勤率 + */ + BigDecimal getTodayAttendanceRate(); + + /** + * 获取产品总数 + */ + Integer getTotalProductCount(); + + /** + * 获取供应商总数 + */ + Integer getTotalSupplierCount(); +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/service/IGearDashboardService.java b/gear-oa/src/main/java/com/gear/oa/service/IGearDashboardService.java new file mode 100644 index 0000000..3b3901f --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/IGearDashboardService.java @@ -0,0 +1,19 @@ +package com.gear.oa.service; + +import com.gear.oa.domain.vo.dashboard.DashboardOverviewVO; + +/** + * 仪表板服务接口 + * + * @author Joshi + * @date 2025-09-17 + */ +public interface IGearDashboardService { + + /** + * 获取仪表板总览数据 + * + * @return 仪表板总览数据 + */ + DashboardOverviewVO getDashboardOverview(); +} \ No newline at end of file diff --git a/gear-oa/src/main/java/com/gear/oa/service/impl/GearDashboardServiceImpl.java b/gear-oa/src/main/java/com/gear/oa/service/impl/GearDashboardServiceImpl.java new file mode 100644 index 0000000..eca4b3c --- /dev/null +++ b/gear-oa/src/main/java/com/gear/oa/service/impl/GearDashboardServiceImpl.java @@ -0,0 +1,211 @@ +package com.gear.oa.service.impl; + +import com.gear.oa.domain.vo.dashboard.*; +import com.gear.oa.mapper.GearDashboardMapper; +import com.gear.oa.service.IGearDashboardService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 仪表板服务实现类 + * + * @author Joshi + * @date 2025-09-17 + */ +@Service +@RequiredArgsConstructor +public class GearDashboardServiceImpl implements IGearDashboardService { + + private final GearDashboardMapper dashboardMapper; + + @Override + public DashboardOverviewVO getDashboardOverview() { + DashboardOverviewVO overview = new DashboardOverviewVO(); + + // 获取订单统计数据 + overview.setOrderStatistics(getOrderStatistics()); + + // 获取薪资统计数据 + overview.setSalaryStatistics(getSalaryStatistics()); + + // 获取库存排行数据 + overview.setStockRanking(getStockRanking()); + + // 获取其他统计数据 + overview.setOtherStatistics(getOtherStatistics()); + + return overview; + } + + /** + * 获取订单统计数据 + */ + private OrderStatisticsVO getOrderStatistics() { + OrderStatisticsVO statistics = new OrderStatisticsVO(); + + // 获取今日、本周、本月订单数 + statistics.setTodayOrderCount(dashboardMapper.getTodayOrderCount()); + statistics.setWeekOrderCount(dashboardMapper.getWeekOrderCount()); + statistics.setMonthOrderCount(dashboardMapper.getMonthOrderCount()); + + // 获取本周订单总金额 + statistics.setWeekTotalAmount(dashboardMapper.getWeekOrderAmount()); + + // 获取近一周订单趋势 + List> weeklyData = dashboardMapper.getWeeklyOrderTrend(); + statistics.setWeeklyTrend(convertToTrendList(weeklyData)); + + // 计算增长率 + Integer lastWeekCount = dashboardMapper.getLastWeekOrderCount(); + statistics.setGrowthRate(calculateGrowthRate(statistics.getWeekOrderCount(), lastWeekCount)); + + return statistics; + } + + /** + * 获取薪资统计数据 + */ + private SalaryStatisticsVO getSalaryStatistics() { + SalaryStatisticsVO statistics = new SalaryStatisticsVO(); + + // 获取今日、本周、本月薪资支出 + statistics.setTodaySalary(dashboardMapper.getTodaySalary()); + statistics.setWeekSalary(dashboardMapper.getWeekSalary()); + statistics.setMonthSalary(dashboardMapper.getMonthSalary()); + + // 获取近一周薪资趋势 + List> weeklyData = dashboardMapper.getWeeklySalaryTrend(); + statistics.setWeeklyTrend(convertToTrendList(weeklyData)); + + // 计算增长率 + BigDecimal lastWeekSalary = dashboardMapper.getLastWeekSalary(); + statistics.setGrowthRate(calculateGrowthRate(statistics.getWeekSalary(), lastWeekSalary)); + + // 计算平均日薪资 + if (statistics.getWeekSalary() != null) { + statistics.setAvgDailySalary(statistics.getWeekSalary().divide(new BigDecimal(7), 2, RoundingMode.HALF_UP)); + } + + return statistics; + } + + /** + * 获取库存排行数据 + */ + private List getStockRanking() { + List rankings = dashboardMapper.getStockRanking(); + + // 设置排名 + for (int i = 0; i < rankings.size(); i++) { + rankings.get(i).setRank(i + 1); + + // 设置物品类型名称 + String itemType = rankings.get(i).getItemType(); + if ("product".equals(itemType)) { + rankings.get(i).setItemTypeName("产品"); + } else if ("raw_material".equals(itemType)) { + rankings.get(i).setItemTypeName("原材料"); + } + } + + return rankings; + } + + /** + * 获取其他统计数据 + */ + private OtherStatisticsVO getOtherStatistics() { + OtherStatisticsVO statistics = new OtherStatisticsVO(); + + statistics.setActiveCustomerCount(dashboardMapper.getActiveCustomerCount()); + statistics.setPendingOrderCount(dashboardMapper.getPendingOrderCount()); + statistics.setLowStockCount(dashboardMapper.getLowStockCount()); + statistics.setMonthlyRevenue(dashboardMapper.getMonthlyRevenue()); + statistics.setTotalEmployeeCount(dashboardMapper.getTotalEmployeeCount()); + statistics.setTodayAttendanceRate(dashboardMapper.getTodayAttendanceRate()); + statistics.setTotalProductCount(dashboardMapper.getTotalProductCount()); + statistics.setTotalSupplierCount(dashboardMapper.getTotalSupplierCount()); + + return statistics; + } + + /** + * 转换趋势数据 + */ + private List convertToTrendList(List> data) { + List trends = new ArrayList<>(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd"); + + for (Map item : data) { + DailyTrendVO trend = new DailyTrendVO(); + + // 处理日期 + Object dateObj = item.get("date"); + if (dateObj instanceof LocalDate) { + trend.setDate(((LocalDate) dateObj).format(formatter)); + } else if (dateObj instanceof String) { + trend.setDate((String) dateObj); + } + + // 处理数值 + Object valueObj = item.get("value"); + if (valueObj instanceof BigDecimal) { + trend.setValue((BigDecimal) valueObj); + } else if (valueObj instanceof Integer) { + trend.setValue(new BigDecimal((Integer) valueObj)); + } else if (valueObj instanceof Long) { + trend.setValue(new BigDecimal((Long) valueObj)); + } + + trend.setLabel(trend.getDate()); + trends.add(trend); + } + + return trends; + } + + /** + * 计算增长率 + */ + private BigDecimal calculateGrowthRate(Object current, Object previous) { + if (current == null || previous == null) { + return BigDecimal.ZERO; + } + + BigDecimal currentValue = convertToBigDecimal(current); + BigDecimal previousValue = convertToBigDecimal(previous); + + if (previousValue.compareTo(BigDecimal.ZERO) == 0) { + return currentValue.compareTo(BigDecimal.ZERO) > 0 ? new BigDecimal(100) : BigDecimal.ZERO; + } + + return currentValue.subtract(previousValue) + .divide(previousValue, 4, RoundingMode.HALF_UP) + .multiply(new BigDecimal(100)) + .setScale(2, RoundingMode.HALF_UP); + } + + /** + * 转换为BigDecimal + */ + private BigDecimal convertToBigDecimal(Object value) { + if (value instanceof BigDecimal) { + return (BigDecimal) value; + } else if (value instanceof Integer) { + return new BigDecimal((Integer) value); + } else if (value instanceof Long) { + return new BigDecimal((Long) value); + } else if (value instanceof String) { + return new BigDecimal((String) value); + } + return BigDecimal.ZERO; + } +} \ No newline at end of file diff --git a/gear-oa/src/main/resources/mapper/oa/GearDashboardMapper.xml b/gear-oa/src/main/resources/mapper/oa/GearDashboardMapper.xml new file mode 100644 index 0000000..6901102 --- /dev/null +++ b/gear-oa/src/main/resources/mapper/oa/GearDashboardMapper.xml @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file