计算机毕业设计266—基于Springboot+Vue3的共享单车管理系统(源代码+数据库)

毕设所有选题:
https://blog.csdn.net/2303_76227485/article/details/131104075

基于Springboot+Vue3的共享单车管理系统(源代码+数据库)

项目编号:266

一、系统介绍

本项目前后端分离,分为用户、管理员、运营人员3种角色(角色菜单可自行分配)。

1、用户:

  • 注册登录、立即用车、查看附件单车、我的订单、评价、问题反馈

2、维修员:

  • 首页大屏数据图表统计
  • 单车管理:报修、维修管理

3、运营人员:

  • 报修、维修管理、区域规划管理(电子围栏)、投放策略、热点分析、订单列表、异常列表、用户管理、用户反馈

4、管理员:

  • 首页大屏数据图表统计:用户数、订单数、今日订单数、单车总量、订单趋势曲线图、收入柱状图、区域订单排行柱状图、订单状态分布环状图
  • 用户管理
  • 单车管理:报修、维修管理、区域规划管理(电子围栏)、投放策略、热点分析、订单列表、异常列表、用户管理、用户反馈
  • 数据分析:订单总量、活跃用户、日均订单、总订单、单车使用趋势、收入分析、骑行时段分布
  • 单车费用设置、个人信息、管理员管理、角色管理、菜单管理

5、亮点:

  • 使用redis缓存token,既简化业务开发,又能支撑高并发、高可用的系统需求
  • 后台首页大屏使用echarts图表统计,更直观的看出系统的运行数据
  • 高德地图引入单车电子围栏

二、所用技术

后端技术栈:

  • Springboot3
  • mybatisPlus
  • Jwt
  • Spring Security
  • Mysql
  • Maven

前端技术栈:

  • Vue3
  • Vue-router
  • axios
  • elementPlus
  • echarts

三、环境介绍

基础环境 :IDEA/eclipse, JDK17或以上, Mysql5.7及以上, Maven3.6, node14, navicat, 高德地图api秘钥

所有项目以及源代码本人均调试运行无问题 可支持远程调试运行

四、页面截图

文档截图:

1、用户:












2、维修员:





3、运营人员:










4、管理员:














五、浏览地址

前台地址:http://localhost:4000

  • 用户账号密码:user1/123456

后台地址:http://localhost:4000

  • 维修员账号密码:maintainer/123456

  • 运营人员账号密码:operator/123456

  • 管理员账户密码:admin/123456

六、部署教程

  1. 使用Navicat或者其它工具,在mysql中创建对应名称的数据库,并执行项目的sql文件

  2. 使用IDEA/Eclipse导入backend项目,若为maven项目请选择maven,等待依赖下载完成

  3. 修改application.yml里面的数据库配置,启动redis后

    src/main/java/com/bikesharing/BikeApplication.java启动后端项目

  4. vscode或idea打开client项目

  5. 在编译器中打开terminal,执行npm install 依赖下载完成后执行 npm run serve,执行成功后会显示访问地址

  6. vscode或idea打开frontend项目

  7. 在编译器中打开terminal,执行npm install 依赖下载完成后执行 npm run serve,执行成功后会显示访问地址

七、部分代码

java 复制代码
 public class BikeOrderServiceImpl extends ServiceImpl<BikeOrderMapper, BikeOrder> implements BikeOrderService {

    @Autowired
    private BikeMapper bikeMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BikeService bikeService;

    @Autowired
    private SystemSettingsMapper systemSettingsMapper;

    @Override
    public PageResult<OrderDTO> getOrderPage(Map<String, Object> params) {
        Integer page = params.get("page") != null ? Integer.parseInt(params.get("page").toString()) : 1;
        Integer size = params.get("size") != null ? Integer.parseInt(params.get("size").toString()) : 10;

        // 创建分页对象
        Page<OrderDTO> pageParam = new Page<>(page, size);

        // 提取查询参数
        String orderNo = params.get("orderNo") != null ? params.get("orderNo").toString() : null;
        String userAccount = params.get("userAccount") != null ? params.get("userAccount").toString() : null;
        String bikeNo = params.get("bikeNo") != null ? params.get("bikeNo").toString() : null;
        Integer status = params.get("status") != null ? Integer.parseInt(params.get("status").toString()) : null;
        String startDate = params.get("startDate") != null ? params.get("startDate").toString() : null;
        String endDate = params.get("endDate") != null ? params.get("endDate").toString() : null;

        // 查询订单列表
        IPage<OrderDTO> orderIPage = baseMapper.selectOrderPage(pageParam, orderNo, userAccount, bikeNo, status, startDate, endDate);

        // 封装分页结果
        return new PageResult<OrderDTO>(orderIPage.getTotal(), orderIPage.getRecords());
    }

    @Override
    public BikeOrder getOrderById(Long id) {
        return baseMapper.selectById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createOrder(BikeOrder order) {
        // 设置订单编号
        order.setOrderNo(generateOrderNo());
        // 设置创建时间和更新时间
        LocalDateTime now = LocalDateTime.now();
        order.setCreateTime(now);
        order.setUpdateTime(now);

        // 设置订单状态为进行中
        order.setStatus(1);

        // 更新单车状态为使用中
        bikeService.updateBikeStatus(order.getBikeId(), 2);

        return baseMapper.insert(order) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean completeOrder(Long id, Double endLng, Double endLat,String endLocation) {
        // 查询订单信息
        BikeOrder order = baseMapper.selectById(id);
        if (order == null || order.getStatus() != 1) {
            return false;
        }

        // 设置结束时间
        LocalDateTime now = LocalDateTime.now();
        order.setEndTime(now);

        // 设置结束经纬度位置
        order.setEndLng(new BigDecimal(endLng));
        order.setEndLat(new BigDecimal(endLat));

        // 设置结束位置描述
        order.setEndLocation(endLocation);

        // 计算骑行时长(核心修改:不满1分钟按1分钟算,超过1分钟向上取整)
        Duration duration = Duration.between(order.getStartTime(), now);
        long totalSeconds = duration.getSeconds(); // 获取总秒数
        long minutes;

        if (totalSeconds <= 0) {
            // 极端情况:时长为0秒(立即结束),按1分钟算
            minutes = 1;
        } else if (totalSeconds < 60) {
            // 不满1分钟(1-59秒),按1分钟算
            minutes = 1;
        } else {
            // 超过1分钟:先取整分钟数,有余数则+1(向上取整)
            long integerMinutes = totalSeconds / 60; // 整数部分(比如70秒=1,130秒=2)
            long remainderSeconds = totalSeconds % 60; // 余数部分(比如70秒=10,130秒=10)
            minutes = remainderSeconds > 0 ? integerMinutes + 1 : integerMinutes;
        }
        order.setRideTime((int) minutes);

        // 计算骑行距离(千米)模拟一分钟走0.2千米(同步适配新的分钟数)
        BigDecimal distance = BigDecimal.valueOf(order.getRideTime() * 0.2);
        order.setRideDistance(distance);

        // 获取系统配置(取第一条记录)
        LambdaQueryWrapper<SystemSettings> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByAsc(SystemSettings::getId).last("LIMIT 1");
        SystemSettings settings = systemSettingsMapper.selectOne(queryWrapper);

        // 定义默认计费参数(兜底值)
        BigDecimal unlockFee = BigDecimal.valueOf(1.00);  // 默认解锁费1元
        BigDecimal rideRate = BigDecimal.valueOf(0.10);   // 默认费率0.1元/分钟

        // 如果获取到配置,使用配置值
        if (settings != null) {
            unlockFee = settings.getUnlockFee() != null ? settings.getUnlockFee() : unlockFee;
            rideRate = settings.getRideRate() != null ? settings.getRideRate() : rideRate;
        }

        // 计算订单金额:解锁费 + 骑行分钟数 × 每分钟费率(使用新的分钟数)
        // 使用BigDecimal精确计算,避免浮点数误差
        BigDecimal minutesBig = BigDecimal.valueOf(minutes);
        BigDecimal amount = unlockFee.add(rideRate.multiply(minutesBig));

        // 保留2位小数(精确到分),四舍五入(银行家舍入法)
        amount = amount.setScale(2, RoundingMode.HALF_UP);
        order.setAmount(amount);

        // 设置订单状态为已完成
        order.setStatus(2);

        // 更新单车状态为可用
        bikeService.updateBikeStatus(order.getBikeId(), 1);

        return baseMapper.updateById(order) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelOrder(Long id) {
        // 查询订单信息
        BikeOrder order = baseMapper.selectById(id);
        if (order == null || order.getStatus() != 1) {
            return false;
        }

        // 设置订单状态为已取消
        order.setStatus(3);

        // 更新单车状态为可用
        bikeService.updateBikeStatus(order.getBikeId(), 1);

        return baseMapper.updateById(order) > 0;
    }

    @Override
    public int getTodayOrderCount() {
        return baseMapper.selectTodayOrderCount();
    }

    @Override
    public Long getUserCount() {
        return userMapper.selectCount(null);
    }

    @Override
    public Map<String, Object> getOrderTrend(Integer days, Integer type, String startDate) {
        Map<String, Object> result = new HashMap<>();
        List<String> dates = new ArrayList<>();
        List<Integer> orders = new ArrayList<>();
        List<BigDecimal> incomes = new ArrayList<>();

        LocalDate endDate = LocalDate.now();
        LocalDate startLocalDate;
        DateTimeFormatter formatter;

        // 如果提供了startDate参数,则使用它作为开始日期
        if (startDate != null && !startDate.isEmpty()) {
            startLocalDate = LocalDate.parse(startDate);
            // 根据类型计算结束日期
            if (type == 2) { // 月
                endDate = startLocalDate.plusMonths(days - 1);
            } else if (type == 3) { // 年
                endDate = startLocalDate.plusYears(days - 1);
            } else { // 日
                endDate = startLocalDate.plusDays(days - 1);
            }
        } else {
            // 根据类型确定开始日期和日期格式
            switch (type) {
                case 2: // 月
                    startLocalDate = endDate.minusMonths(days - 1).withDayOfMonth(1);
                    break;
                case 3: // 年
                    startLocalDate = endDate.minusYears(days - 1).withDayOfYear(1);
                    break;
                case 1: // 日(默认)
                default:
                    startLocalDate = endDate.minusDays(days - 1);
                    break;
            }
        }

        // 确定日期格式
        switch (type) {
            case 2: // 月
                formatter = DateTimeFormatter.ofPattern("yyyy-MM");
                break;
            case 3: // 年
                formatter = DateTimeFormatter.ofPattern("yyyy");
                break;
            case 1: // 日(默认)
            default:
                formatter = DateTimeFormatter.ofPattern("MM-dd");
                break;
        }

        // 查询订单趋势数据
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", startLocalDate.toString());
        params.put("endDate", endDate.toString());
        params.put("type", type);

        System.out.println("订单趋势SQL参数: startDate=" + startLocalDate + ", endDate=" + endDate + ", type=" + type);

        List<Map<String, Object>> trendData = baseMapper.selectOrderTrend(params);

        System.out.println("订单趋势SQL查询结果: " + trendData);

        // 处理查询结果
        if (type == 3) { // 年
            for (int i = 0; i < days; i++) {
                LocalDate date = startLocalDate.plusYears(i);
                String dateStr = date.format(formatter);
                dates.add(dateStr);

                Map<String, Object> yearData = findDataByDateFormat(trendData, dateStr, "year");
                orders.add(yearData != null ? ((Number) yearData.get("orders")).intValue() : 0);
                incomes.add(yearData != null ? (BigDecimal) yearData.get("income") : BigDecimal.ZERO);
            }
        } else if (type == 2) { // 月
            for (int i = 0; i < days; i++) {
                LocalDate date = startLocalDate.plusMonths(i);
                String dateStr = date.format(formatter);
                dates.add(dateStr);

                Map<String, Object> monthData = findDataByDateFormat(trendData, dateStr, "month");
                orders.add(monthData != null ? ((Number) monthData.get("orders")).intValue() : 0);
                incomes.add(monthData != null ? (BigDecimal) monthData.get("income") : BigDecimal.ZERO);
            }
        } else { // 日
            for (int i = 0; i < days; i++) {
                LocalDate date = startLocalDate.plusDays(i);
                String dateStr = date.format(formatter);
                dates.add(dateStr);

                Map<String, Object> dayData = findDataByDateFormat(trendData, dateStr, "day");
                System.out.println("日期: " + dateStr + ", 查找结果: " + dayData);
                orders.add(dayData != null ? ((Number) dayData.get("orders")).intValue() : 0);
                incomes.add(dayData != null ? (BigDecimal) dayData.get("income") : BigDecimal.ZERO);
            }
        }

        result.put("dates", dates);
        result.put("orders", orders);
        result.put("incomes", incomes.stream().map(BigDecimal::doubleValue).collect(Collectors.toList()));

        return result;
    }

    /**
     * 根据日期格式查找数据
     */
    private Map<String, Object> findDataByDateFormat(List<Map<String, Object>> dataList, String dateStr, String dateField) {
        for (Map<String, Object> data : dataList) {
            Object dateObj = data.get(dateField);
            if (dateObj != null && dateStr.equals(dateObj.toString())) {
                return data;
            }
        }
        return null;
    }

    @Override
    public List<Map<String, Object>> getAreaRanking() {
        return baseMapper.selectAreaRanking();
    }

    @Override
    public List<Map<String, Object>> getLatestOrders(int limit) {
        return baseMapper.selectLatestOrders(limit);
    }

    @Override
    public List<Map<String, Object>> getAbnormalOrders(int limit) {
        return baseMapper.selectAbnormalOrders(limit);
    }

    @Override
    public Integer getOrderCount(String startDate, String endDate, Long areaId) {
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", startDate);
        params.put("endDate", endDate);
        params.put("areaId", areaId);
        return baseMapper.selectOrderCount(params);
    }

    @Override
    public Double getOrderCountTrend(String startDate, String endDate, Long areaId) {
        // 计算同期时间
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        long days = ChronoUnit.DAYS.between(start, end) + 1;

        LocalDate lastStart = start.minusDays(days);
        LocalDate lastEnd = end.minusDays(days);

        // 查询当前时间段订单数
        Integer currentCount = getOrderCount(startDate, endDate, areaId);

        // 查询同期时间段订单数
        Integer lastCount = getOrderCount(lastStart.toString(), lastEnd.toString(), areaId);

        // 计算增长率
        if (lastCount == 0) {
            return 100.0; // 上期为0,本期有数据,增长率为100%
        }

        double result = (double) (currentCount - lastCount) * 100 / lastCount;
        return BigDecimal.valueOf(result).setScale(1, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public Integer getActiveUserCount(String startDate, String endDate, Long areaId) {
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", startDate);
        params.put("endDate", endDate);
        params.put("areaId", areaId);
        return baseMapper.selectActiveUserCount(params);
    }

    @Override
    public Double getActiveUserCountTrend(String startDate, String endDate, Long areaId) {
        // 计算同期时间
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        long days = ChronoUnit.DAYS.between(start, end) + 1;

        LocalDate lastStart = start.minusDays(days);
        LocalDate lastEnd = end.minusDays(days);

        // 查询当前时间段活跃用户数
        Integer currentCount = getActiveUserCount(startDate, endDate, areaId);

        // 查询同期时间段活跃用户数
        Integer lastCount = getActiveUserCount(lastStart.toString(), lastEnd.toString(), areaId);

        // 计算增长率
        if (lastCount == 0) {
            return 100.0; // 上期为0,本期有数据,增长率为100%
        }

        double result = (double) (currentCount - lastCount) * 100 / lastCount;
        return BigDecimal.valueOf(result).setScale(1, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public Double getDailyOrderAvg(String startDate, String endDate, Long areaId) {
        Integer totalOrders = getOrderCount(startDate, endDate, areaId);

        // 计算天数
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        long days = ChronoUnit.DAYS.between(start, end) + 1;

        if (days == 0) {
            return 0.0;
        }

        double result = (double) totalOrders / days;
        return BigDecimal.valueOf(result).setScale(1, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public Double getDailyOrderAvgTrend(String startDate, String endDate, Long areaId) {
        // 计算当前时间段日均订单
        Double currentAvg = getDailyOrderAvg(startDate, endDate, areaId);

        // 计算同期时间
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        long days = ChronoUnit.DAYS.between(start, end) + 1;

        LocalDate lastStart = start.minusDays(days);
        LocalDate lastEnd = end.minusDays(days);

        // 计算同期时间段日均订单
        Double lastAvg = getDailyOrderAvg(lastStart.toString(), lastEnd.toString(), areaId);

        // 计算增长率
        if (lastAvg == 0) {
            return 100.0; // 上期为0,本期有数据,增长率为100%
        }

        double result = (currentAvg - lastAvg) * 100 / lastAvg;
        return BigDecimal.valueOf(result).setScale(1, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public Double getTotalIncome(String startDate, String endDate, Long areaId) {
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", startDate);
        params.put("endDate", endDate);
        params.put("areaId", areaId);
        BigDecimal totalIncome = baseMapper.selectTotalIncome(params);
        double result = totalIncome == null ? 0.0 : totalIncome.doubleValue();
        return BigDecimal.valueOf(result).setScale(1, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public Double getTotalIncomeTrend(String startDate, String endDate, Long areaId) {
        // 计算当前时间段总收入
        Double currentIncome = getTotalIncome(startDate, endDate, areaId);

        // 计算同期时间
        LocalDate start = LocalDate.parse(startDate);
        LocalDate end = LocalDate.parse(endDate);
        long days = ChronoUnit.DAYS.between(start, end) + 1;

        LocalDate lastStart = start.minusDays(days);
        LocalDate lastEnd = end.minusDays(days);

        // 计算同期时间段总收入
        Double lastIncome = getTotalIncome(lastStart.toString(), lastEnd.toString(), areaId);

        // 计算增长率
        if (lastIncome == 0) {
            return 100.0; // 上期为0,本期有数据,增长率为100%
        }

        double result = (currentIncome - lastIncome) * 100 / lastIncome;
        return BigDecimal.valueOf(result).setScale(1, RoundingMode.HALF_UP).doubleValue();
    }

    @Override
    public Map<String, Object> getIncomeAnalysis(String startDate, String endDate, Long areaId) {
        Map<String, Object> result = new HashMap<>();

        // 处理日期参数
        LocalDate start = startDate == null ? LocalDate.now().minusDays(6) : LocalDate.parse(startDate);
        LocalDate end = endDate == null ? LocalDate.now() : LocalDate.parse(endDate);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");

        // 生成日期列表
        List<String> dates = new ArrayList<>();
        List<LocalDate> dateList = new ArrayList<>();

        for (LocalDate date = start; !date.isAfter(end); date = date.plusDays(1)) {
            dates.add(date.format(formatter));
            dateList.add(date);
        }

        // 查询收入数据
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", start.toString());
        params.put("endDate", end.toString());
        params.put("areaId", areaId);

        List<Map<String, Object>> incomeData = baseMapper.selectIncomeAnalysis(params);

        // 处理收入数据
        List<Double> total = new ArrayList<>();
        List<Double> electric = new ArrayList<>();
        List<Double> normal = new ArrayList<>();

        for (LocalDate date : dateList) {
            String dateStr = date.format(formatter);

            // 查找当天数据
            Map<String, Object> dayData = findDataByDateStr(incomeData, dateStr);

            if (dayData != null) {
                double totalValue = ((BigDecimal) dayData.get("total_income")).doubleValue();
                double electricValue = ((BigDecimal) dayData.get("electric_income")).doubleValue();
                double normalValue = ((BigDecimal) dayData.get("normal_income")).doubleValue();

                total.add(BigDecimal.valueOf(totalValue).setScale(1, RoundingMode.HALF_UP).doubleValue());
                electric.add(BigDecimal.valueOf(electricValue).setScale(1, RoundingMode.HALF_UP).doubleValue());
                normal.add(BigDecimal.valueOf(normalValue).setScale(1, RoundingMode.HALF_UP).doubleValue());
            } else {
                total.add(0.0);
                electric.add(0.0);
                normal.add(0.0);
            }
        }

        result.put("dates", dates);
        result.put("total", total);
        result.put("electric", electric);
        result.put("normal", normal);

        return result;
    }

    /**
     * 根据日期字符串查找数据(适用于date_str字段)
     */
    private Map<String, Object> findDataByDateStr(List<Map<String, Object>> dataList, String dateStr) {
        for (Map<String, Object> data : dataList) {
            Object dateObj = data.get("date_str");
            if (dateObj != null && dateStr.equals(dateObj.toString())) {
                return data;
            }
        }
        return null;
    }

    @Override
    public List<Integer> getTimeDistribution(String startDate, String endDate, Long areaId) {
        // 处理日期参数
        LocalDate start = startDate == null ? LocalDate.now().minusDays(6) : LocalDate.parse(startDate);
        LocalDate end = endDate == null ? LocalDate.now() : LocalDate.parse(endDate);

        // 查询时段分布数据
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", start.toString());
        params.put("endDate", end.toString());
        params.put("areaId", areaId);

        List<Map<String, Object>> timeDistData = baseMapper.selectTimeDistribution(params);

        // 初始化24小时的数据,默认为0
        List<Integer> result = IntStream.range(0, 24)
                .mapToObj(i -> 0)
                .collect(Collectors.toList());

        // 填充查询结果
        for (Map<String, Object> data : timeDistData) {
            int hour = (int) data.get("hour");
            int count = ((Number) data.get("count")).intValue();

            if (hour >= 0 && hour < 24) {
                result.set(hour, count);
            }
        }

        return result;
    }

    @Override
    public List<Map<String, Object>> getHotRoutes(String startDate, String endDate, Long areaId) {
        // 处理日期参数
        LocalDate start = startDate == null ? LocalDate.now().minusDays(6) : LocalDate.parse(startDate);
        LocalDate end = endDate == null ? LocalDate.now() : LocalDate.parse(endDate);

        // 查询热门路线数据
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", start.toString());
        params.put("endDate", end.toString());
        params.put("areaId", areaId);
        params.put("limit", 10); // 限制返回前10条

        List<Map<String, Object>> hotRoutes = baseMapper.selectHotRoutes(params);

        // 处理结果,添加排名
        int rank = 1;
        for (Map<String, Object> route : hotRoutes) {
            route.put("rank", rank++);

            // 计算趋势值(示例:使用骑行次数占比作为趋势值,范围0-100)
            int count = ((Number) route.get("count")).intValue();
            int totalCount = hotRoutes.stream()
                    .mapToInt(r -> ((Number) r.get("count")).intValue())
                    .sum();

            double trend = totalCount > 0 ? (double) count * 100 / totalCount : 0;
            route.put("trend", Math.min(100, (int) trend));
        }

        return hotRoutes;
    }

    @Override
    public Map<String, Object> getIncomeData(Integer month) {
        Map<String, Object> result = new HashMap<>();
        List<String> days = new ArrayList<>();
        List<BigDecimal> income = new ArrayList<>();

        // 获取指定月份的第一天和最后一天
        LocalDate now = LocalDate.now();
        LocalDate firstDay = now.withMonth(month).withDayOfMonth(1);
        LocalDate lastDay = firstDay.with(TemporalAdjusters.lastDayOfMonth());

        // 如果是当前月份,则只统计到当前日期
        if (month == now.getMonthValue()) {
            lastDay = now;
        }

        // 查询收入数据
        Map<String, Object> params = new HashMap<>();
        params.put("startDate", firstDay.toString());
        params.put("endDate", lastDay.toString());
        params.put("month", month);
        params.put("year", now.getYear());

        List<Map<String, Object>> incomeData = baseMapper.selectIncomeData(params);

        // 处理查询结果
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd");
        for (int i = 1; i <= lastDay.getDayOfMonth(); i++) {
            LocalDate date = firstDay.withDayOfMonth(i);
            String dayStr = formatter.format(date);
            days.add(dayStr);

            // 查找当天收入
            BigDecimal dayIncome = BigDecimal.ZERO;
            for (Map<String, Object> data : incomeData) {
                if (dayStr.equals(data.get("day").toString())) {
                    dayIncome = (BigDecimal) data.get("income");
                    break;
                }
            }
            income.add(dayIncome);
        }

        result.put("days", days);
        result.put("income", income);

        return result;
    }

    /**
     * 生成订单编号
     */
    private String generateOrderNo() {
        return "O" + System.currentTimeMillis();
    }

    /**
     * 根据日期查找数据
     */
    private Map<String, Object> findDataByDate(List<Map<String, Object>> dataList, String dateStr) {
        for (Map<String, Object> data : dataList) {
            Object dateObj = data.get("date");
            if (dateObj != null && dateStr.equals(dateObj.toString())) {
                return data;
            }
        }
        return null;
    }
}
相关推荐
a285281 小时前
nginx的重定向
大数据·数据库·nginx
m***06682 小时前
SpringBoot项目中读取resource目录下的文件(六种方法)
spring boot·python·pycharm
蒂法就是我2 小时前
mysql主键索引和其他索引区别在哪里?
数据库·mysql
前路不黑暗@2 小时前
Java项目:Java脚手架项目的公共模块的实现(二)
java·开发语言·spring boot·学习·spring cloud·maven·idea
人道领域2 小时前
Spring核心注解全解析
java·开发语言·spring boot
eWidget2 小时前
数据可视化进阶:Seaborn 柱状图、散点图与相关性分析
数据库·python·信息可视化·kingbase·数据库平替用金仓·金仓数据库
X54先生(人文科技)2 小时前
20260211_AdviceForTraditionalProgrammers
数据库·人工智能·ai编程
金牌归来发现妻女流落街头3 小时前
日志级别是摆设吗?
java·spring boot·日志