liding
5 天以前 92d4fac0b58498efc6be7764f00364535beb3d71
1.首页数据 2.装备数据
已修改11个文件
已添加12个文件
832 ■■■■■ 文件已修改
main-business/src/main/java/com/ruoyi/business/controller/EquipmentManagementController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/controller/EquipmentUsageRecordController.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/controller/HomePageController.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/EquipmentUsageRecordDto.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/HomePageDto.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/dto/YearlyQueryDto.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/entity/EquipmentUsageRecord.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/mapper/EquipmentUsageRecordMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/mapper/SalesRecordMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/EquipmentManagementService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/EquipmentUsageRecordService.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/OfficialInventoryService.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/SalesRecordService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentUsageRecordServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/OfficialInventoryServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java 286 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/vo/EquipmentManagementVo.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/resources/db/migration/postgresql/V20250707155600__create_table_equipment_usage_record.sql 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/resources/mapper/EquipmentUsageRecordMapper.xml 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/resources/mapper/SalesRecordMapper.xml 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main-business/src/main/java/com/ruoyi/business/controller/EquipmentManagementController.java
@@ -7,9 +7,13 @@
import com.ruoyi.business.entity.EquipmentManagement;
import com.ruoyi.business.entity.Production;
import com.ruoyi.business.service.EquipmentManagementService;
import com.ruoyi.business.vo.EquipmentManagementVo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.web.bind.annotation.*;
import lombok.AllArgsConstructor;
import java.util.List;
/**
 * <p>
@@ -52,5 +56,12 @@
        return R.ok(equipmentManagementService.delByIds(ids));
    }
    /**
     * è®¾å¤‡list
     */
    @GetMapping("/equipmentList")
    public R<List<EquipmentManagementVo>> selectEquipmentList() {
        List<EquipmentManagementVo> equipmentManagementVo = equipmentManagementService.selectEquipmentList();
        return R.ok(equipmentManagementVo);
    }
}
main-business/src/main/java/com/ruoyi/business/controller/EquipmentUsageRecordController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.ruoyi.business.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.business.dto.EquipmentManagementDto;
import com.ruoyi.business.dto.EquipmentUsageRecordDto;
import com.ruoyi.business.entity.EquipmentManagement;
import com.ruoyi.business.entity.EquipmentUsageRecord;
import com.ruoyi.business.service.EquipmentUsageRecordService;
import com.ruoyi.common.core.domain.R;
import org.springframework.web.bind.annotation.*;
import lombok.AllArgsConstructor;
/**
 * <p>
 * è®¾å¤‡ä½¿ç”¨è®°å½•表 å‰ç«¯æŽ§åˆ¶å™¨
 * </p>
 *
 * @author ld
 * @since 2025-07-07
 */
@RestController
@AllArgsConstructor
@RequestMapping("/equipmentUsageRecord")
public class EquipmentUsageRecordController {
    private EquipmentUsageRecordService equipmentUsageRecordService;
    /**
     * è®¾å¤‡ä½¿ç”¨è®°å½•表查询
     */
    @GetMapping("/list")
    public R<IPage<EquipmentUsageRecordDto>> list(Page<EquipmentUsageRecord> page, EquipmentUsageRecordDto equipmentUsageRecordDto) {
        IPage<EquipmentUsageRecordDto> list = equipmentUsageRecordService.selectUsageRecordList(page, equipmentUsageRecordDto);
        return R.ok(list);
    }
    /**
     * è®¾å¤‡ä½¿ç”¨è®°å½•表新增修改
     */
    @PostMapping("/addOrEditUsageRecord")
    public R addOrEditUsageRecord(@RequestBody EquipmentUsageRecordDto equipmentUsageRecordDto) {
        return R.ok(equipmentUsageRecordService.addOrEditUsageRecord(equipmentUsageRecordDto));
    }
}
main-business/src/main/java/com/ruoyi/business/controller/HomePageController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.ruoyi.business.controller;
import com.ruoyi.business.dto.HomePageDto;
import com.ruoyi.business.dto.YearlyQueryDto;
import com.ruoyi.business.service.OfficialInventoryService;
import com.ruoyi.business.service.SalesRecordService;
import com.ruoyi.common.core.domain.R;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@RestController
@AllArgsConstructor
@RequestMapping("/homePage")
public class HomePageController {
    private SalesRecordService salesRecordService;
    private OfficialInventoryService officialInventoryService;
    @GetMapping("/allInfo")
    private R<HomePageDto> homePageDto() {
        HomePageDto homePageDto = new HomePageDto();
        Map<String, Object> map = salesRecordService.selectAllInfo();
        //营收金额
        homePageDto.setRevenueAmount((BigDecimal) map.get("revenueAmount"));
        homePageDto.setChangeRate(map.get("changeRate").toString());
        homePageDto.setTrend(map.get("trend").toString());
        //供应量
        homePageDto.setSaleQuantity((BigDecimal) map.get("saleQuantity"));
        homePageDto.setSaleQuantityRate(map.get("saleQuantityRate").toString());
        homePageDto.setTrendQuantity(map.get("trendQuantity").toString());
        //营收分布
        homePageDto.setRevenueDistribution((Map<String, BigDecimal>) map.get("revenueDistribution"));
        //库存统计
        Map<String, BigDecimal> maps = officialInventoryService.selectOfficialAllInfo();
        homePageDto.setInventory(maps);
        //月度统计
        //销售数据
        homePageDto.setSalesResults((List<Map<String, Object>>) map.get("salesResults"));
        return R.ok(homePageDto);
    }
    @PostMapping("/yearlySales")
    public R<Map<String, Object>> getYearlyMonthlySales(@RequestBody YearlyQueryDto query) {
        Map<String, Object> data = salesRecordService.getYearlyMonthlySales(query);
        return R.ok(data);
    }
}
main-business/src/main/java/com/ruoyi/business/dto/EquipmentUsageRecordDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,12 @@
package com.ruoyi.business.dto;
import com.ruoyi.business.entity.EquipmentUsageRecord;
import lombok.Data;
@Data
public class EquipmentUsageRecordDto extends EquipmentUsageRecord {
    private String equipmentNo; //设备编号
    private String equipmentName; //设备名称
}
main-business/src/main/java/com/ruoyi/business/dto/HomePageDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,31 @@
package com.ruoyi.business.dto;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@Data
public class HomePageDto {
    //营收金额
    private BigDecimal revenueAmount;
    //营收金额较昨日
    private String changeRate;
    //营收趋势
    private String trend;
    //销售数量,供应量
    private BigDecimal saleQuantity;
    //供应量较昨日
    private String saleQuantityRate;
    //供应趋势
    private String trendQuantity;
    //营收分布
    private Map<String, BigDecimal> revenueDistribution;
    //库存统计
    private Map<String, BigDecimal> inventory;
    //销售数据
    private List<Map<String, Object>> salesResults;
}
main-business/src/main/java/com/ruoyi/business/dto/YearlyQueryDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
package com.ruoyi.business.dto;
import jakarta.validation.constraints.*;
import lombok.Data;
import static com.ruoyi.common.utils.DateUtils.parseDate;
@Data
public class YearlyQueryDto {
    @Size(min = 2, max = 2, message = "时间范围必须包含开始和结束日期")
    private String[] timeRange;
    @AssertTrue(message = "日期格式必须为YYYY-MM")
    public boolean isTimeRangeValid() {
        try {
            if (timeRange == null || timeRange.length != 2) return false;
            parseDate(timeRange[0]);
            parseDate(timeRange[1]);
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}
main-business/src/main/java/com/ruoyi/business/entity/EquipmentManagement.java
@@ -28,8 +28,8 @@
    /**
     * è®¾å¤‡ç¼–号
     */
    @TableField(value = "equipment_id")
    private String equipmentId;
    @TableField(value = "equipment_no")
    private String equipmentNo;
    /**
     * è®¾å¤‡åç§°
     */
main-business/src/main/java/com/ruoyi/business/entity/EquipmentUsageRecord.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
package com.ruoyi.business.entity;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import com.ruoyi.common.core.domain.MyBaseEntity;
import java.time.LocalDate;
/**
 * è®¾å¤‡ä½¿ç”¨è®°å½•表 å®žä½“ç±»
 *
 * @author ld
 * @date 2025-07-07
 */
@Data
@TableName("equipment_usage_record")
public class EquipmentUsageRecord extends MyBaseEntity {
    private static final long serialVersionUID = 1L;
    /**
     * ä¸»é”®ID
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * è®¾å¤‡ID
     */
    @TableField(value = "equipment_id")
    private Long equipmentId;
    /**
     * ä½¿ç”¨æ•°é‡
     */
    @TableField(value = "usage_quantity")
    private Integer usageQuantity;
    /**
     * ä½¿ç”¨äººID
     */
    @TableField(value = "user_id")
    private Long userId;
    /**
     * éƒ¨é—¨ID
     */
    @TableField(value = "department_id")
    private Long departmentId;
    /**
     * è®¾å¤‡çŠ¶æ€ï¼ˆæ­£å¸¸/故障/维修中)
     */
    @TableField(value = "equipment_status")
    private String equipmentStatus;
    /**
     * ä½¿ç”¨å¼€å§‹æ—¶é—´
     */
    @TableField(value = "usage_start_time")
    private LocalDate usageStartTime;
    /**
     * ä½¿ç”¨ç»“束时间
     */
    @TableField(value = "usage_end_time")
    private LocalDate usageEndTime;
    /**
     * å¤‡æ³¨ä¿¡æ¯
     */
    @TableField(value = "remarks")
    private String remarks;
}
main-business/src/main/java/com/ruoyi/business/mapper/EquipmentUsageRecordMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.business.entity.EquipmentUsageRecord;
import org.apache.ibatis.annotations.Mapper;
/**
 * <p>
 * è®¾å¤‡ä½¿ç”¨è®°å½•表 Mapper æŽ¥å£
 * </p>
 *
 * @author ld
 * @since 2025-07-07
 */
@Mapper
public interface EquipmentUsageRecordMapper extends BaseMapper<EquipmentUsageRecord> {
}
main-business/src/main/java/com/ruoyi/business/mapper/SalesRecordMapper.java
@@ -1,8 +1,13 @@
package com.ruoyi.business.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.business.dto.SalesRecordDto;
import com.ruoyi.business.entity.SalesRecord;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.time.LocalDate;
import java.util.List;
/**
 * <p>
@@ -15,4 +20,5 @@
@Mapper
public interface SalesRecordMapper extends BaseMapper<SalesRecord> {
    List<SalesRecord> findByDateRange(@Param("startDate")LocalDate startDate, @Param("endDate") LocalDate endDate);
}
main-business/src/main/java/com/ruoyi/business/service/EquipmentManagementService.java
@@ -5,6 +5,9 @@
import com.ruoyi.business.dto.EquipmentManagementDto;
import com.ruoyi.business.entity.EquipmentManagement;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.business.vo.EquipmentManagementVo;
import java.util.List;
/**
 * <p>
@@ -21,4 +24,6 @@
    int addOrEditEquipment(EquipmentManagementDto equipmentManagementDto);
    int delByIds(Long[] ids);
    List<EquipmentManagementVo> selectEquipmentList();
}
main-business/src/main/java/com/ruoyi/business/service/EquipmentUsageRecordService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
package com.ruoyi.business.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.business.dto.EquipmentUsageRecordDto;
import com.ruoyi.business.entity.EquipmentManagement;
import com.ruoyi.business.entity.EquipmentUsageRecord;
import com.baomidou.mybatisplus.extension.service.IService;
/**
 * <p>
 * è®¾å¤‡ä½¿ç”¨è®°å½•表 æœåŠ¡ç±»
 * </p>
 *
 * @author ld
 * @since 2025-07-07
 */
public interface EquipmentUsageRecordService extends IService<EquipmentUsageRecord> {
    IPage<EquipmentUsageRecordDto> selectUsageRecordList(Page<EquipmentUsageRecord> page, EquipmentUsageRecordDto equipmentUsageRecordDto);
    int addOrEditUsageRecord(EquipmentUsageRecordDto equipmentUsageRecordDto);
}
main-business/src/main/java/com/ruoyi/business/service/OfficialInventoryService.java
@@ -7,7 +7,9 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.business.vo.OfficialInventoryVo;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
 * <p>
@@ -28,4 +30,6 @@
    List<OfficialInventoryVo> selectOfficialList(OfficialInventoryVo officialInventoryVo);
    List<OfficialInventory> selectOfficialAll();
    Map<String, BigDecimal> selectOfficialAllInfo();
}
main-business/src/main/java/com/ruoyi/business/service/SalesRecordService.java
@@ -4,7 +4,11 @@
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.business.dto.SalesRecordDto;
import com.ruoyi.business.dto.YearlyQueryDto;
import com.ruoyi.business.entity.SalesRecord;
import jakarta.validation.Valid;
import java.util.Map;
/**
 * <p>
@@ -21,4 +25,8 @@
    int addOrEditSalesRecord(SalesRecordDto salesRecordDto);
    int delByIds(Long[] ids);
    Map<String, Object> selectAllInfo();
    Map<String, Object> getYearlyMonthlySales(@Valid YearlyQueryDto query);
}
main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentManagementServiceImpl.java
@@ -10,11 +10,13 @@
import com.ruoyi.business.mapper.EquipmentManagementMapper;
import com.ruoyi.business.service.EquipmentManagementService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.business.vo.EquipmentManagementVo;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
/**
@@ -35,7 +37,6 @@
        Page<EquipmentManagement> entityPage = equipmentManagementMapper.selectPage(page, null);
        IPage<EquipmentManagementDto> dtoPage = new Page<>();
        BeanUtils.copyProperties(entityPage, dtoPage);
        return dtoPage;
    }
@@ -51,6 +52,20 @@
    }
    @Override
    public List<EquipmentManagementVo> selectEquipmentList() {
        List<EquipmentManagement> equipmentManagements = equipmentManagementMapper.selectList(null);
        return equipmentManagements.stream()
                .map(equipment -> {
                    EquipmentManagementVo vo = new EquipmentManagementVo();
                    vo.setId(equipment.getId());               // è®¾å¤‡id
                    vo.setEquipmentName(equipment.getEquipmentName()); // è®¾å¤‡åç§°
                    vo.setQuantity(equipment.getQuantity());    // æ•°é‡
                    return vo;
                })
                .toList();
    }
    @Override
    public int delByIds(Long[] ids) {
        return equipmentManagementMapper.deleteByIds(Arrays.asList(ids));
    }
main-business/src/main/java/com/ruoyi/business/service/impl/EquipmentUsageRecordServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,84 @@
package com.ruoyi.business.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.entity.Supply;
import com.ruoyi.business.dto.EquipmentManagementDto;
import com.ruoyi.business.dto.EquipmentUsageRecordDto;
import com.ruoyi.business.entity.EquipmentManagement;
import com.ruoyi.business.entity.EquipmentUsageRecord;
import com.ruoyi.business.mapper.EquipmentManagementMapper;
import com.ruoyi.business.mapper.EquipmentUsageRecordMapper;
import com.ruoyi.business.service.EquipmentUsageRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.bean.BeanUtils;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
 * <p>
 * è®¾å¤‡ä½¿ç”¨è®°å½•表 æœåŠ¡å®žçŽ°ç±»
 * </p>
 *
 * @author ld
 * @since 2025-07-07
 */
@Service
@RequiredArgsConstructor
public class EquipmentUsageRecordServiceImpl extends ServiceImpl<EquipmentUsageRecordMapper, EquipmentUsageRecord> implements EquipmentUsageRecordService {
    private final EquipmentUsageRecordMapper equipmentUsageRecordMapper;
    private  final EquipmentManagementMapper equipmentManagementMapper;
    @Override
    public IPage<EquipmentUsageRecordDto> selectUsageRecordList(Page<EquipmentUsageRecord> page, EquipmentUsageRecordDto equipmentUsageRecordDto) {
        Page<EquipmentUsageRecord> entityPage = equipmentUsageRecordMapper.selectPage(page, null);
        IPage<EquipmentUsageRecordDto> dtoPage = new Page<>();
        BeanUtils.copyProperties(entityPage, dtoPage);
        List<Long> eqIds = entityPage.getRecords().stream().map(EquipmentUsageRecord::getEquipmentId).toList();
        //批量查询
        Map<Long, EquipmentManagement> equipmentManagementMap;
        if (!eqIds.isEmpty()) {
            List<EquipmentManagement> infos = equipmentManagementMapper.selectList(new LambdaQueryWrapper<EquipmentManagement>().in(EquipmentManagement::getId, eqIds));
            equipmentManagementMap = infos.stream().collect(Collectors.toMap(EquipmentManagement::getId, Function.identity()));
        } else {
            equipmentManagementMap = new HashMap<>();
        }
        //匹配数据
        List<EquipmentUsageRecordDto> dtoRecords = entityPage.getRecords().stream().map(entity -> {
            EquipmentUsageRecordDto dto = new EquipmentUsageRecordDto();
            BeanUtils.copyProperties(entity, dto);
            EquipmentManagement equipment = equipmentManagementMap.get(entity.getEquipmentId());
            if (equipment != null) {
                dto.setEquipmentNo(equipment.getEquipmentNo());
                dto.setEquipmentName(equipment.getEquipmentName());
            }
            return dto;
        }).toList();
        dtoPage.setRecords(dtoRecords);
        return dtoPage;
    }
    @Override
    public int addOrEditUsageRecord(EquipmentUsageRecordDto equipmentUsageRecordDto) {
        EquipmentUsageRecord equipmentUsageRecord = new EquipmentUsageRecord();
        BeanUtils.copyProperties(equipmentUsageRecordDto, equipmentUsageRecord);
        if (Objects.isNull(equipmentUsageRecordDto.getId())) {
            return equipmentUsageRecordMapper.insert(equipmentUsageRecord);
        } else {
            return equipmentUsageRecordMapper.updateById(equipmentUsageRecord);
        }
    }
}
main-business/src/main/java/com/ruoyi/business/service/impl/OfficialInventoryServiceImpl.java
@@ -26,7 +26,9 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -330,4 +332,26 @@
        }
    }
    @Override
    public Map<String, BigDecimal> selectOfficialAllInfo() {
        // 1. æŸ¥è¯¢ official_inventory è¡¨æ•°æ®
        List<OfficialInventory> officialInventories = officialInventoryMapper.selectList(null);
        // ç”¨äºŽå­˜å‚¨æœ€ç»ˆç»“果,key ä¸ºç…¤ç§åç§°ï¼Œvalue ä¸ºåº“存数量拼接“吨”
        Map<String, BigDecimal> resultMap = new LinkedHashMap<>();
        // 2. éåŽ†æŸ¥è¯¢ç»“æžœï¼Œå…³è” coalInfo èŽ·å–ç…¤ç§åç§°å¹¶ç»„è£…æ•°æ®
        for (OfficialInventory inventory : officialInventories) {
            Long coalId = inventory.getCoalId();
            // æ ¹æ® coalId åˆ° coalInfoMapper æŸ¥è¯¢ç…¤ç§åç§°
            CoalInfo coalInfo = coalInfoMapper.selectById(coalId);
            if (coalInfo != null) {
                String coalName = coalInfo.getCoal(); // å‡è®¾ CoalInfo æœ‰ getCoalName æ–¹æ³•获取煤种名称
                BigDecimal quantity = inventory.getInventoryQuantity();
                resultMap.put(coalName, quantity);
            }
        }
        return resultMap;
    }
}
main-business/src/main/java/com/ruoyi/business/service/impl/SalesRecordServiceImpl.java
@@ -1,6 +1,7 @@
package com.ruoyi.business.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -10,6 +11,7 @@
import com.ruoyi.basic.mapper.CoalInfoMapper;
import com.ruoyi.basic.mapper.CustomerMapper;
import com.ruoyi.business.dto.SalesRecordDto;
import com.ruoyi.business.dto.YearlyQueryDto;
import com.ruoyi.business.entity.OfficialInventory;
import com.ruoyi.business.entity.SalesRecord;
import com.ruoyi.business.mapper.OfficialInventoryMapper;
@@ -23,12 +25,21 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalAdjusters;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.*;
/**
 * <p>
@@ -218,4 +229,279 @@
        // æ‰§è¡Œæ‰¹é‡é€»è¾‘删除
        return salesRecordMapper.update(null, updateWrapper);
    }
    @Override
    public Map<String, Object> getYearlyMonthlySales(YearlyQueryDto query) {
        // 1. å¤„理默认查询(不传参数时)
        if (query == null || query.getTimeRange() == null || query.getTimeRange().length == 0) {
            query = getDefaultQuery();
        }
        // 2. è§£æžæ—¶é—´èŒƒå›´
        LocalDate[] dateRange = parseAndValidateDateRange(query.getTimeRange());
        LocalDate startDate = dateRange[0];
        LocalDate endDate = dateRange[1];
        // 3. æŸ¥è¯¢æ•°æ®
        List<SalesRecord> records = salesRecordMapper.findByDateRange(
                startDate.withDayOfMonth(1),
                endDate.withDayOfMonth(1).with(TemporalAdjusters.lastDayOfMonth())
        );
        // 4. æž„建响应
        return buildResponse(query.getTimeRange(), records, startDate, endDate);
    }
    // èŽ·å–é»˜è®¤æŸ¥è¯¢ï¼ˆå½“å‰å¹´åº¦æœ€è¿‘6个月)
    private YearlyQueryDto getDefaultQuery() {
        LocalDate now = LocalDate.now();
        LocalDate startDate = now.minusMonths(5).withDayOfMonth(1);
        String[] timeRange = {
                startDate.format(DateTimeFormatter.ofPattern("yyyy-MM")),
                now.format(DateTimeFormatter.ofPattern("yyyy-MM"))
        };
        YearlyQueryDto defaultQuery = new YearlyQueryDto();
        defaultQuery.setTimeRange(timeRange);
        return defaultQuery;
    }
    // è§£æžå¹¶éªŒè¯æ—¥æœŸèŒƒå›´
    private LocalDate[] parseAndValidateDateRange(String[] timeRange) {
        if (timeRange == null || timeRange.length != 2) {
            throw new IllegalArgumentException("时间范围参数格式不正确");
        }
        LocalDate startDate = parseDate(timeRange[0]);
        LocalDate endDate = parseDate(timeRange[1]);
        if (startDate.isAfter(endDate)) {
            throw new IllegalArgumentException("开始日期不能晚于结束日期");
        }
        return new LocalDate[]{startDate, endDate};
    }
    // è§£æžæ—¥æœŸï¼ˆæ ¼å¼ï¼šyyyy-MM)
    private LocalDate parseDate(String dateStr) {
        try {
            return YearMonth.parse(dateStr).atDay(1);
        } catch (DateTimeParseException e) {
            throw new IllegalArgumentException("日期格式不正确,应为 yyyy-MM", e);
        }
    }
    // æž„建响应数据
    private Map<String, Object> buildResponse(String[] timeRange,
                                              List<SalesRecord> records,
                                              LocalDate startDate,
                                              LocalDate endDate) {
        Map<String, Object> response = new LinkedHashMap<>();
        response.put("timeRange", timeRange);
        response.put("data", formatMonthlyData(records, startDate, endDate));
        response.put("isDefaultQuery", timeRange.equals(getDefaultQuery().getTimeRange()));
        return response;
    }
    // æ ¼å¼åŒ–月度数据
    private Map<String, Integer> formatMonthlyData(List<SalesRecord> records,
                                                   LocalDate startDate,
                                                   LocalDate endDate) {
        // é¢„定义格式化器
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
        // ä½¿ç”¨ TreeMap è‡ªåŠ¨æŒ‰é”®æŽ’åº
        Map<String, Integer> monthlyData = records.stream()
                .collect(Collectors.groupingBy(
                        r -> r.getSaleDate().format(monthFormatter),
                        TreeMap::new,
                        // å…³é”®ä¿®æ”¹ï¼šå¤„理 saleQuantity ä¸º null çš„æƒ…况,默认按 0 è®¡ç®—
                        Collectors.summingInt(r -> {
                            BigDecimal quantity = r.getSaleQuantity();
                            return quantity != null ? quantity.intValue() : 0; // ä¸‰ç›®è¿ç®—符判断
                        })
                ));
        // å¡«å……缺失月份
        YearMonth start = YearMonth.from(startDate);
        YearMonth end = YearMonth.from(endDate);
        for (YearMonth month = start; !month.isAfter(end); month = month.plusMonths(1)) {
            String monthKey = month.format(monthFormatter);
            monthlyData.putIfAbsent(monthKey, 0);
        }
        return monthlyData;
    }
    @Override
    public Map<String, Object> selectAllInfo() {
        Map<String, Object> result = new LinkedHashMap<>();
        //营收金额
        LocalDate today = LocalDate.now();
        LocalDate yesterday = today.minusDays(1);
        BigDecimal revenueAmount;
        List<SalesRecord> salesRecords = salesRecordMapper.selectList(null);
        revenueAmount = salesRecords.stream()
                .map(SalesRecord::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        //今日营收
        BigDecimal todayRevenue = salesRecords.stream()
                .filter(record -> today.equals(record.getSaleDate()))
                .map(SalesRecord::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        //昨日营收
        BigDecimal yesterdayRevenue = salesRecords.stream()
                .filter(record -> yesterday.equals(record.getSaleDate()))
                .map(SalesRecord::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // è®¡ç®—增长百分比
        BigDecimal increases = BigDecimal.ZERO;
        String trend = "+";
        if (yesterdayRevenue.compareTo(BigDecimal.ZERO) != 0) {
            increases = todayRevenue.subtract(yesterdayRevenue)
                    .divide(yesterdayRevenue, 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal(100));
            if (increases.compareTo(BigDecimal.ZERO) > 0) {
                trend = "+";
            } else if (increases.compareTo(BigDecimal.ZERO) < 0) {
                trend = "—";
            }
        }
        // 6. æ ¼å¼åŒ–百分比显示
        DecimalFormat formatNo = new DecimalFormat("0.00%");
        String changeRate = formatNo.format(increases.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP));
        //供应量
        BigDecimal saleQuantity = salesRecords.stream()
                .map(SalesRecord::getSaleQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        //今日供应量
        BigDecimal todaySaleQuantity = salesRecords.stream()
                .filter(record -> today.equals(record.getSaleDate()))
                .map(SalesRecord::getSaleQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        //昨日供应量
        BigDecimal yesterdaySaleQuantity = salesRecords.stream()
                .filter(record -> yesterday.equals(record.getSaleDate()))
                .map(SalesRecord::getSaleQuantity)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // è®¡ç®—增长百分比
        BigDecimal increasesQuantity = BigDecimal.ZERO;
        String trendQuantity = "+";
        if (yesterdaySaleQuantity.compareTo(BigDecimal.ZERO) != 0) {
            increasesQuantity = todaySaleQuantity.subtract(yesterdaySaleQuantity)
                    .divide(yesterdaySaleQuantity, 4, RoundingMode.HALF_UP)
                    .multiply(new BigDecimal(100));
            if (increasesQuantity.compareTo(BigDecimal.ZERO) > 0) {
                trendQuantity = "+";
            } else if (increasesQuantity.compareTo(BigDecimal.ZERO) < 0) {
                trendQuantity = "—";
            }
        }
        // æ ¼å¼åŒ–数量百分比显示
        DecimalFormat formatNoQuantity = new DecimalFormat("0.00%");
        String saleQuantityRate = formatNoQuantity.format(increasesQuantity.divide(new BigDecimal(100), 4, RoundingMode.HALF_UP));
        //营收分布
        //获取所有煤种信息(id和名称的映射)
        Map<Long, String> coalIdToNameMap = coalInfoMapper.selectList(null).stream()
                .collect(Collectors.toMap(
                        CoalInfo::getId,
                        CoalInfo::getCoal
                ));
        // 3. æŒ‰ç…¤ç§ID统计总金额
        Map<Long, BigDecimal> revenueByCoalId = salesRecords.stream()
                .collect(Collectors.groupingBy(
                        SalesRecord::getCoalId,
                        Collectors.reducing(
                                BigDecimal.ZERO,
                                SalesRecord::getTotalAmount,
                                BigDecimal::add
                        )
                ));
        // ç…¤ç§é”€å”®åˆ†å¸ƒï¼ˆå•独作为一个子Map)
        Map<String, BigDecimal> revenueDistribution = new LinkedHashMap<>();
        coalIdToNameMap.forEach((id, name) -> {
            BigDecimal amount = revenueByCoalId.getOrDefault(id, BigDecimal.ZERO)
                    .setScale(2, RoundingMode.HALF_UP);
            if (amount.compareTo(BigDecimal.ZERO) > 0) {
                revenueDistribution.put(name, amount);
            }
        });
        //销售数据
        // æŒ‰coalId分组并合并数量和金额
        Map<Long, Map<String, Object>> resultMap = new LinkedHashMap<>();
        for (SalesRecord record : salesRecords) {
            Long coalId = record.getCoalId();
            // å°†æ•°é‡å’Œé‡‘额转换为BigDecimal
            BigDecimal quantity = record.getInventoryQuantity();
            BigDecimal amount = record.getTotalAmount();
            if (resultMap.containsKey(coalId)) {
                Map<String, Object> existing = resultMap.get(coalId);
                // èŽ·å–çŽ°æœ‰çš„BigDecimal值
                BigDecimal existingQuantity = (BigDecimal) existing.get("inventoryQuantity");
                BigDecimal existingAmount = (BigDecimal) existing.get("totalAmount");
                // ä½¿ç”¨BigDecimal进行加法运算
                existing.put("inventoryQuantity", existingQuantity.add(quantity));
                existing.put("totalAmount", existingAmount.add(amount));
            } else {
                Map<String, Object> newRecord = new HashMap<>();
                newRecord.put("coalId", coalId);
                newRecord.put("inventoryQuantity", quantity);
                newRecord.put("totalAmount", amount);
                resultMap.put(coalId, newRecord);
            }
        }
        // 3. èŽ·å–æ‰€æœ‰æ¶‰åŠçš„coalId
        List<Long> coalIds = new ArrayList<>(resultMap.keySet());
        // 4. æ‰¹é‡æŸ¥è¯¢ç…¤ç§ä¿¡æ¯å¹¶å¡«å……到结果中
        if (!coalIds.isEmpty()) {
            List<CoalInfo> coalInfos = coalInfoMapper.selectBatchIds(coalIds);
            for (CoalInfo coalInfo : coalInfos) {
                Map<String, Object> record = resultMap.get(coalInfo.getId());
                if (record != null) {
                    record.put("coalName", coalInfo.getCoal());
                }
            }
        }
        // æœ€ç»ˆç»“果是一个List<Map>,每个Map包含合并后的销售数据和对应的煤种信息
        List<Map<String, Object>> results = new ArrayList<>(resultMap.values());
        result.put("revenueAmount", revenueAmount.setScale(2, RoundingMode.HALF_UP));
        result.put("changeRate", changeRate);
        result.put("trend", trend);
        result.put("saleQuantity", saleQuantity);
        result.put("saleQuantityRate", saleQuantityRate);
        result.put("trendQuantity", trendQuantity);
        result.put("revenueDistribution", revenueDistribution);
        result.put("salesResults", results);
        return result;
    }
}
main-business/src/main/java/com/ruoyi/business/vo/EquipmentManagementVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
package com.ruoyi.business.vo;
import lombok.Data;
@Data
public class EquipmentManagementVo {
    private Long id; //设备id
    private String equipmentName; //设备名称
    private Integer quantity; //数量
}
main-business/src/main/resources/db/migration/postgresql/V20250701142700__create_table_equipment_management.sql
@@ -3,7 +3,7 @@
CREATE TABLE equipment_management
(
    id               BIGSERIAL PRIMARY KEY,           -- ä¸»é”® ID
    equipment_id     VARCHAR(50)  NOT NULL,           -- è®¾å¤‡ç¼–号
    equipment_no     VARCHAR(50)  NOT NULL,           -- è®¾å¤‡ç¼–号
    equipment_name   VARCHAR(100) NOT NULL,           -- è®¾å¤‡åç§°
    quantity         INT          NOT NULL DEFAULT 0, -- æ•°é‡
    specification    VARCHAR(50)  NOT NULL,           -- è§„格型号
@@ -27,7 +27,7 @@
COMMENT
ON COLUMN equipment_management.id IS ' ä¸»é”® ID';
COMMENT
ON COLUMN equipment_management.equipment_id IS ' è®¾å¤‡ç¼–号 ';
ON COLUMN equipment_management.equipment_no IS ' è®¾å¤‡ç¼–号 ';
COMMENT
ON COLUMN equipment_management.equipment_name IS ' è®¾å¤‡åç§° ';
COMMENT
main-business/src/main/resources/db/migration/postgresql/V20250707155600__create_table_equipment_usage_record.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
-- åˆ›å»ºè®¾å¤‡ä½¿ç”¨è®°å½•表 equipment_usage_record
CREATE TABLE equipment_usage_record
(
id                   BIGSERIAL          PRIMARY KEY,        -- ä¸»é”®ID,自动递增
    equipment_id         BIGINT         NOT NULL,           -- è®¾å¤‡ID,关联设备信息表,不允许为空
    usage_quantity       INT            NOT NULL,           -- ä½¿ç”¨æ•°é‡ï¼Œä¸å…è®¸ä¸ºç©º
    user_id              BIGINT         NOT NULL,           -- ä½¿ç”¨äººID,关联用户表,不允许为空
    department_id        BIGINT         ,                   -- éƒ¨é—¨ID,关联部门表,不允许为空
    equipment_status     VARCHAR(50)    NOT NULL,           -- è®¾å¤‡çŠ¶æ€ï¼ˆå¦‚ï¼šæ­£å¸¸ã€æ•…éšœã€ç»´ä¿®ä¸­ï¼‰ï¼Œä¸å…è®¸ä¸ºç©º
    usage_start_time     TIMESTAMP      NOT NULL,           -- ä½¿ç”¨å¼€å§‹æ—¶é—´ï¼Œä¸å…è®¸ä¸ºç©º
    usage_end_time       TIMESTAMP,                         -- ä½¿ç”¨ç»“束时间,可为空(未归还时)
    remarks              VARCHAR(1000),                     -- å¤‡æ³¨ä¿¡æ¯ï¼Œå¯ä¸ºç©º
    deleted              INT            NOT NULL DEFAULT 0, -- è½¯åˆ é™¤æ ‡å¿—:0=未删除,1=已删除
    create_by            VARCHAR(255),                      -- åˆ›å»ºäººç”¨æˆ·å
    create_time          TIMESTAMP WITHOUT TIME ZONE,       -- åˆ›å»ºæ—¶é—´ï¼Œé»˜è®¤å½“前时间
    update_by            VARCHAR(255),                      -- æœ€åŽæ›´æ–°äººç”¨æˆ·å
    update_time          TIMESTAMP WITHOUT TIME ZONE        -- æœ€åŽæ›´æ–°æ—¶é—´
);
-- ä¸ºè¡¨æ·»åŠ æ³¨é‡Š
COMMENT ON TABLE equipment_usage_record IS '设备使用记录表';
-- ä¸ºå­—段添加注释
COMMENT ON COLUMN equipment_usage_record.id IS '主键ID';
COMMENT ON COLUMN equipment_usage_record.equipment_id IS '设备ID';
COMMENT ON COLUMN equipment_usage_record.usage_quantity IS '使用数量';
COMMENT ON COLUMN equipment_usage_record.user_id IS '使用人ID';
COMMENT ON COLUMN equipment_usage_record.department_id IS '部门ID';
COMMENT ON COLUMN equipment_usage_record.equipment_status IS '设备状态(正常/故障/维修中)';
COMMENT ON COLUMN equipment_usage_record.usage_start_time IS '使用开始时间';
COMMENT ON COLUMN equipment_usage_record.usage_end_time IS '使用结束时间';
COMMENT ON COLUMN equipment_usage_record.remarks IS '备注信息';
COMMENT ON COLUMN equipment_usage_record.deleted IS '软删除标志,0=未删除,1=已删除';
COMMENT ON COLUMN equipment_usage_record.create_by IS '创建该记录的用户';
COMMENT ON COLUMN equipment_usage_record.create_time IS '记录创建时间';
COMMENT ON COLUMN equipment_usage_record.update_by IS '最后修改该记录的用户';
COMMENT ON COLUMN equipment_usage_record.update_time IS '记录最后更新时间';
main-business/src/main/resources/mapper/EquipmentUsageRecordMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,33 @@
<?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.ruoyi.business.mapper.EquipmentUsageRecordMapper">
        <!-- é€šç”¨æŸ¥è¯¢æ˜ å°„结果 -->
        <resultMap id="BaseResultMap" type="com.ruoyi.business.entity.EquipmentUsageRecord">
                    <id column="id" property="id" />
                <result column="deleted" property="deleted" />
                <result column="create_by" property="createBy" />
                <result column="create_time" property="createTime" />
                <result column="update_by" property="updateBy" />
                <result column="update_time" property="updateTime" />
                    <result column="equipment_id" property="equipmentId" />
                    <result column="usage_quantity" property="usageQuantity" />
                    <result column="user_id" property="userId" />
                    <result column="department_id" property="departmentId" />
                    <result column="equipment_status" property="equipmentStatus" />
                    <result column="usage_start_time" property="usageStartTime" />
                    <result column="usage_end_time" property="usageEndTime" />
                    <result column="remarks" property="remarks" />
        </resultMap>
        <!-- é€šç”¨æŸ¥è¯¢ç»“果列 -->
        <sql id="Base_Column_List">
                deleted,
                create_by,
                create_time,
                update_by,
                update_time,
            id, equipment_id, usage_quantity, user_id, department_id, equipment_status, usage_start_time, usage_end_time, remarks
        </sql>
</mapper>
main-business/src/main/resources/mapper/SalesRecordMapper.xml
@@ -14,7 +14,6 @@
                    <result column="customer_id" property="customerId" />
                    <result column="customer" property="customer" />
                    <result column="coal_id" property="coalId" />
                    <result column="coal" property="coal" />
                    <result column="price_including_tax" property="priceIncludingTax" />
                    <result column="inventory_quantity" property="inventoryQuantity" />
                    <result column="unit" property="unit" />
@@ -39,5 +38,18 @@
                deleted,
            id, sale_date, customer_id, customer, coal_id, coal, price_including_tax, inventory_quantity, unit, sale_quantity, sale_price, total_amount, tax_coal, tax_trans, gross_profit, net_profit, registrant_id, registrant, registration_date
        </sql>
    <select id="findByDateRange" resultType="com.ruoyi.business.entity.SalesRecord">
        SELECT
            sale_date,
            SUM(sale_quantity) AS saleQuantity
        FROM
            sales_record
        WHERE
            sale_date BETWEEN #{startDate}::date AND #{endDate}::date
        GROUP BY
            sale_date
        ORDER BY
            sale_date ASC
    </select>
</mapper>