feat(oa): 添加仪表板功能模块
- 新增仪表板控制器、服务接口及其实现类- 创建仪表板相关的数据传输对象(DTO) - 设计并实现仪表板数据的获取和统计逻辑 - 添加仪表板数据的数据库访问接口和映射文件
This commit is contained in:
@@ -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<DashboardOverviewVO> getDashboardOverview() {
|
||||||
|
DashboardOverviewVO overview = dashboardService.getDashboardOverview();
|
||||||
|
return R.ok(overview);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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<StockRankingVO> stockRanking;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 其他统计数据
|
||||||
|
*/
|
||||||
|
private OtherStatisticsVO otherStatistics;
|
||||||
|
}
|
||||||
@@ -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<DailyTrendVO> weeklyTrend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订单总金额(本周)
|
||||||
|
*/
|
||||||
|
private BigDecimal weekTotalAmount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与上周对比增长率
|
||||||
|
*/
|
||||||
|
private BigDecimal growthRate;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<DailyTrendVO> weeklyTrend;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 与上周对比增长率
|
||||||
|
*/
|
||||||
|
private BigDecimal growthRate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 平均日薪资支出
|
||||||
|
*/
|
||||||
|
private BigDecimal avgDailySalary;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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<Map<String, Object>> getWeeklyOrderTrend();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取今日薪资支出
|
||||||
|
*/
|
||||||
|
BigDecimal getTodaySalary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本周薪资支出
|
||||||
|
*/
|
||||||
|
BigDecimal getWeekSalary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本月薪资支出
|
||||||
|
*/
|
||||||
|
BigDecimal getMonthSalary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取上周薪资支出
|
||||||
|
*/
|
||||||
|
BigDecimal getLastWeekSalary();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取近一周薪资趋势
|
||||||
|
*/
|
||||||
|
List<Map<String, Object>> getWeeklySalaryTrend();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取库存排行(前10)
|
||||||
|
*/
|
||||||
|
List<StockRankingVO> getStockRanking();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取活跃客户数
|
||||||
|
*/
|
||||||
|
Integer getActiveCustomerCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取待处理订单数
|
||||||
|
*/
|
||||||
|
Integer getPendingOrderCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取库存预警数量
|
||||||
|
*/
|
||||||
|
Integer getLowStockCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取本月营收
|
||||||
|
*/
|
||||||
|
BigDecimal getMonthlyRevenue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取员工总数
|
||||||
|
*/
|
||||||
|
Integer getTotalEmployeeCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取今日出勤率
|
||||||
|
*/
|
||||||
|
BigDecimal getTodayAttendanceRate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取产品总数
|
||||||
|
*/
|
||||||
|
Integer getTotalProductCount();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取供应商总数
|
||||||
|
*/
|
||||||
|
Integer getTotalSupplierCount();
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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<Map<String, Object>> 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<Map<String, Object>> 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<StockRankingVO> getStockRanking() {
|
||||||
|
List<StockRankingVO> 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<DailyTrendVO> convertToTrendList(List<Map<String, Object>> data) {
|
||||||
|
List<DailyTrendVO> trends = new ArrayList<>();
|
||||||
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
|
||||||
|
|
||||||
|
for (Map<String, Object> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
230
gear-oa/src/main/resources/mapper/oa/GearDashboardMapper.xml
Normal file
230
gear-oa/src/main/resources/mapper/oa/GearDashboardMapper.xml
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.gear.oa.mapper.GearDashboardMapper">
|
||||||
|
|
||||||
|
<!-- 获取今日订单数 -->
|
||||||
|
<select id="getTodayOrderCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE DATE(create_time) = CURDATE()
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取本周订单数 -->
|
||||||
|
<select id="getWeekOrderCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE YEARWEEK(create_time, 1) = YEARWEEK(CURDATE(), 1)
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取本月订单数 -->
|
||||||
|
<select id="getMonthOrderCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE YEAR(create_time) = YEAR(CURDATE())
|
||||||
|
AND MONTH(create_time) = MONTH(CURDATE())
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取上周订单数 -->
|
||||||
|
<select id="getLastWeekOrderCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE YEARWEEK(create_time, 1) = YEARWEEK(CURDATE(), 1) - 1
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取本周订单总金额 -->
|
||||||
|
<select id="getWeekOrderAmount" resultType="java.math.BigDecimal">
|
||||||
|
SELECT COALESCE(SUM(tax_amount), 0)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE YEARWEEK(create_time, 1) = YEARWEEK(CURDATE(), 1)
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取近一周订单趋势 -->
|
||||||
|
<select id="getWeeklyOrderTrend" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
DATE(create_time) as date,
|
||||||
|
COUNT(*) as value
|
||||||
|
FROM gear_order
|
||||||
|
WHERE create_time >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
|
||||||
|
AND create_time < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
||||||
|
AND del_flag = 0
|
||||||
|
GROUP BY DATE(create_time)
|
||||||
|
ORDER BY DATE(create_time)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取今日薪资支出 -->
|
||||||
|
<select id="getTodaySalary" resultType="java.math.BigDecimal">
|
||||||
|
SELECT COALESCE(SUM(wage), 0)
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE DATE(record_date) = CURDATE()
|
||||||
|
AND del_flag = 0
|
||||||
|
AND wage IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取本周薪资支出 -->
|
||||||
|
<select id="getWeekSalary" resultType="java.math.BigDecimal">
|
||||||
|
SELECT COALESCE(SUM(wage), 0)
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE YEARWEEK(record_date, 1) = YEARWEEK(CURDATE(), 1)
|
||||||
|
AND del_flag = 0
|
||||||
|
AND wage IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取本月薪资支出 -->
|
||||||
|
<select id="getMonthSalary" resultType="java.math.BigDecimal">
|
||||||
|
SELECT COALESCE(SUM(wage), 0)
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE YEAR(record_date) = YEAR(CURDATE())
|
||||||
|
AND MONTH(record_date) = MONTH(CURDATE())
|
||||||
|
AND del_flag = 0
|
||||||
|
AND wage IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取上周薪资支出 -->
|
||||||
|
<select id="getLastWeekSalary" resultType="java.math.BigDecimal">
|
||||||
|
SELECT COALESCE(SUM(wage), 0)
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE YEARWEEK(record_date, 1) = YEARWEEK(CURDATE(), 1) - 1
|
||||||
|
AND del_flag = 0
|
||||||
|
AND wage IS NOT NULL
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取近一周薪资趋势 -->
|
||||||
|
<select id="getWeeklySalaryTrend" resultType="java.util.Map">
|
||||||
|
SELECT
|
||||||
|
DATE(record_date) as date,
|
||||||
|
COALESCE(SUM(wage), 0) as value
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE record_date >= DATE_SUB(CURDATE(), INTERVAL 6 DAY)
|
||||||
|
AND record_date < DATE_ADD(CURDATE(), INTERVAL 1 DAY)
|
||||||
|
AND del_flag = 0
|
||||||
|
GROUP BY DATE(record_date)
|
||||||
|
ORDER BY DATE(record_date)
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取库存排行(前10) -->
|
||||||
|
<select id="getStockRanking" resultType="com.gear.oa.domain.vo.dashboard.StockRankingVO">
|
||||||
|
SELECT
|
||||||
|
s.item_id,
|
||||||
|
s.item_type,
|
||||||
|
s.quantity,
|
||||||
|
s.unit,
|
||||||
|
w.warehouse_name,
|
||||||
|
CASE
|
||||||
|
WHEN s.item_type = 'product' THEN p.product_name
|
||||||
|
WHEN s.item_type = 'raw_material' THEN rm.material_name
|
||||||
|
ELSE '未知'
|
||||||
|
END as item_name,
|
||||||
|
CASE
|
||||||
|
WHEN s.item_type = 'product' THEN p.product_code
|
||||||
|
WHEN s.item_type = 'raw_material' THEN rm.material_code
|
||||||
|
ELSE ''
|
||||||
|
END as item_code,
|
||||||
|
CASE
|
||||||
|
WHEN s.item_type = 'product' THEN pc.category_name
|
||||||
|
ELSE NULL
|
||||||
|
END as category_name,
|
||||||
|
CASE
|
||||||
|
WHEN s.item_type = 'product' THEN p.owner
|
||||||
|
ELSE NULL
|
||||||
|
END as owner
|
||||||
|
FROM gear_stock s
|
||||||
|
LEFT JOIN gear_warehouse w ON s.warehouse_id = w.warehouse_id
|
||||||
|
LEFT JOIN gear_product p ON s.item_type = 'product' AND s.item_id = p.product_id
|
||||||
|
LEFT JOIN gear_product_category pc ON p.category_id = pc.category_id
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT product_id as material_id, product_name as material_name, product_code as material_code
|
||||||
|
FROM gear_product
|
||||||
|
WHERE type = 'raw'
|
||||||
|
) rm ON s.item_type = 'raw_material' AND s.item_id = rm.material_id
|
||||||
|
WHERE s.del_flag = 0
|
||||||
|
AND s.quantity > 0
|
||||||
|
ORDER BY s.quantity DESC
|
||||||
|
LIMIT 10
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取活跃客户数(本月有订单的客户) -->
|
||||||
|
<select id="getActiveCustomerCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(DISTINCT customer_id)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE YEAR(create_time) = YEAR(CURDATE())
|
||||||
|
AND MONTH(create_time) = MONTH(CURDATE())
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取待处理订单数 -->
|
||||||
|
<select id="getPendingOrderCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE order_status IN (0, 1)
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取库存预警数量(假设库存小于10为预警) -->
|
||||||
|
<select id="getLowStockCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_stock
|
||||||
|
WHERE quantity < 10
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取本月营收 -->
|
||||||
|
<select id="getMonthlyRevenue" resultType="java.math.BigDecimal">
|
||||||
|
SELECT COALESCE(SUM(tax_amount), 0)
|
||||||
|
FROM gear_order
|
||||||
|
WHERE YEAR(create_time) = YEAR(CURDATE())
|
||||||
|
AND MONTH(create_time) = MONTH(CURDATE())
|
||||||
|
AND order_status = 2
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取员工总数(从考勤记录中统计活跃用户) -->
|
||||||
|
<select id="getTotalEmployeeCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(DISTINCT user_id)
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE record_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
|
||||||
|
AND del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取今日出勤率 -->
|
||||||
|
<select id="getTodayAttendanceRate" resultType="java.math.BigDecimal">
|
||||||
|
SELECT
|
||||||
|
CASE
|
||||||
|
WHEN total_employees.total = 0 THEN 0
|
||||||
|
ELSE ROUND((attended_employees.attended * 100.0 / total_employees.total), 2)
|
||||||
|
END as attendance_rate
|
||||||
|
FROM
|
||||||
|
(SELECT COUNT(DISTINCT user_id) as total
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE record_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
|
||||||
|
AND del_flag = 0) total_employees
|
||||||
|
CROSS JOIN
|
||||||
|
(SELECT COUNT(DISTINCT user_id) as attended
|
||||||
|
FROM gear_attendance_record
|
||||||
|
WHERE DATE(record_date) = CURDATE()
|
||||||
|
AND record_type = 'attendance'
|
||||||
|
AND del_flag = 0) attended_employees
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取产品总数 -->
|
||||||
|
<select id="getTotalProductCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_product
|
||||||
|
WHERE del_flag = 0
|
||||||
|
AND is_enabled = 1
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<!-- 获取供应商总数 -->
|
||||||
|
<select id="getTotalSupplierCount" resultType="java.lang.Integer">
|
||||||
|
SELECT COUNT(*)
|
||||||
|
FROM gear_supplier
|
||||||
|
WHERE del_flag = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</mapper>
|
||||||
Reference in New Issue
Block a user