计算机毕业设计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;
    }
}
相关推荐
wanhengidc21 小时前
跨境云手机适用于哪些场景
大数据·运维·服务器·数据库·科技·智能手机
Bdygsl21 小时前
MySQL(6)—— 视图
数据库·mysql
oradh21 小时前
数据库入门概述
数据库·oracle·数据库基础·数据库入门
BullSmall21 小时前
一套定制化高级 payload 合集
数据库·安全性测试
zbdx不知名菜鸡1 天前
postgre sql 数据库查询优化
数据库·postgresql
9稳1 天前
基于PLC的生产线自动升降机设计
开发语言·网络·数据库·嵌入式硬件·plc
zb200641201 天前
spring security 超详细使用教程(接入springboot、前后端分离)
java·spring boot·spring
Mephisto1805021 天前
Vue 3 变量声明和调用
vue
四七伵1 天前
Spring Boot项目中varchar字段为什么不用NULL?告别空指针从建表开始
数据库·后端
Mr.45671 天前
JDK17+Druid+SpringBoot3+ShardingSphere5 多表分库分表完整实践(MySQL+PostgreSQL)
java·数据库·spring boot·mysql·postgresql