Compare commits

...

2 Commits

8 changed files with 118 additions and 8 deletions

View File

@ -43,14 +43,6 @@ CREATE TABLE teams
created_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 团队成员表
CREATE TABLE team_members
(
team_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
PRIMARY KEY (team_id, user_id)
);
-- 设备表
CREATE TABLE devices
(

View File

@ -23,6 +23,7 @@ public class CorsConfig {
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setMaxAge(3600L);
config.addExposedHeader("Content-Disposition");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);

View File

@ -1,15 +1,28 @@
package github.benjamin.equipreservebackend.controller;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import github.benjamin.equipreservebackend.constant.ReservationStatus;
import github.benjamin.equipreservebackend.entity.Reservation;
import github.benjamin.equipreservebackend.response.ResponseResult;
import github.benjamin.equipreservebackend.service.ReservationService;
import github.benjamin.equipreservebackend.vo.DeviceStatsVO;
import github.benjamin.equipreservebackend.vo.ReservationStatsVO;
import github.benjamin.equipreservebackend.vo.ReservationVO;
import github.benjamin.equipreservebackend.vo.UserReservationVO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
@RestController
@RequestMapping("/reservation")
@RequiredArgsConstructor
@ -42,4 +55,32 @@ public class ReservationController {
return ResponseResult.success(reservationService.getReservationVO(id, page, size));
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/stats")
public ResponseResult<List<ReservationStatsVO>> getReservationStats(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) {
return ResponseResult.success(reservationService.getReservationStats(start, end));
}
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/stats/export")
public void exportReservationStats(@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start,
@RequestParam @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end,
HttpServletResponse response) throws IOException {
String fileName = String.format("使用人统计_%s-%s.xlsx", start.format(DateTimeFormatter.ISO_DATE), end.format(DateTimeFormatter.ISO_DATE));
String encodedName = URLEncoder.encode(fileName, StandardCharsets.UTF_8);
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-Disposition", "attachment;filename=" + encodedName);
// 查询数据
List<ReservationStatsVO> data = reservationService.getReservationStats(start, end);
// 使用EasyExcel写入response流
EasyExcel.write(response.getOutputStream(), ReservationStatsVO.class)
.sheet("使用人统计")
.doWrite(data);
}
}

View File

@ -2,8 +2,13 @@ package github.benjamin.equipreservebackend.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import github.benjamin.equipreservebackend.entity.Reservation;
import github.benjamin.equipreservebackend.vo.ReservationStatsVO;
import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;
@Repository
public interface ReservationMapper extends BaseMapper<Reservation> {
List<ReservationStatsVO> getReservationStats(LocalDate start, LocalDate end);
}

View File

@ -2,10 +2,12 @@ package github.benjamin.equipreservebackend.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import github.benjamin.equipreservebackend.entity.Reservation;
import github.benjamin.equipreservebackend.vo.ReservationStatsVO;
import github.benjamin.equipreservebackend.vo.ReservationVO;
import github.benjamin.equipreservebackend.vo.TimeRangeVO;
import github.benjamin.equipreservebackend.vo.UserReservationVO;
import java.time.LocalDate;
import java.util.List;
public interface ReservationService {
@ -19,4 +21,6 @@ public interface ReservationService {
List<TimeRangeVO> getUnavailableTimes(Long id);
Page<ReservationVO> getReservationVO(Long userId, Integer page, Integer size);
List<ReservationStatsVO> getReservationStats(LocalDate start, LocalDate end);
}

View File

@ -8,6 +8,7 @@ import github.benjamin.equipreservebackend.exception.ApiException;
import github.benjamin.equipreservebackend.mapper.*;
import github.benjamin.equipreservebackend.service.ReservationService;
import github.benjamin.equipreservebackend.utils.PageUtil;
import github.benjamin.equipreservebackend.vo.ReservationStatsVO;
import github.benjamin.equipreservebackend.vo.ReservationVO;
import github.benjamin.equipreservebackend.vo.TimeRangeVO;
import github.benjamin.equipreservebackend.vo.UserReservationVO;
@ -146,4 +147,9 @@ public class ReservationServiceImpl implements ReservationService {
.toList());
return res;
}
@Override
public List<ReservationStatsVO> getReservationStats(LocalDate start, LocalDate end) {
return reservationMapper.getReservationStats(start, end);
}
}

View File

@ -0,0 +1,33 @@
package github.benjamin.equipreservebackend.vo;
import com.alibaba.excel.annotation.ExcelIgnore;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.write.style.ColumnWidth;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import lombok.Data;
@Data
public class ReservationStatsVO {
@JsonSerialize(using = ToStringSerializer.class)
@ExcelIgnore
private Long deviceId;
@ExcelProperty("设备名称")
@ColumnWidth(15)
private String deviceName;
@ExcelProperty("使用人")
@ColumnWidth(15)
private String applicantName;
@ExcelProperty("所属团队")
@ColumnWidth(15)
private String applicantTeam;
@ExcelProperty("使用次数")
@ColumnWidth(15)
private Integer usageCount;
}

View File

@ -0,0 +1,28 @@
<?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="github.benjamin.equipreservebackend.mapper.ReservationMapper">
<select id="getReservationStats" resultType="github.benjamin.equipreservebackend.vo.ReservationStatsVO">
SELECT
r.device_id,
d.name AS deviceName,
r.applicant_name,
r.applicant_team,
COUNT(*) AS usageCount
FROM
reservations r
JOIN
devices d ON r.device_id = d.id
WHERE
r.status IN ('APPROVED', 'APPROVED_ASSIST')
AND r.start_time >= #{start}
AND r.end_time &lt;= #{end}
GROUP BY
r.device_id, r.applicant_name, r.applicant_team, d.name
ORDER BY
d.name, r.applicant_name;
</select>
</mapper>