Compare commits

..

No commits in common. "91492960f758c9ffe12be940347b2805719f5811" and "b350e933d3d5c4c59da0d5d71ca1ab081753dc8c" have entirely different histories.

8 changed files with 8 additions and 118 deletions

View File

@ -43,6 +43,14 @@ CREATE TABLE teams
created_time DATETIME DEFAULT CURRENT_TIMESTAMP 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 CREATE TABLE devices
( (

View File

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

View File

@ -1,28 +1,15 @@
package github.benjamin.equipreservebackend.controller; package github.benjamin.equipreservebackend.controller;
import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import github.benjamin.equipreservebackend.constant.ReservationStatus;
import github.benjamin.equipreservebackend.entity.Reservation; import github.benjamin.equipreservebackend.entity.Reservation;
import github.benjamin.equipreservebackend.response.ResponseResult; import github.benjamin.equipreservebackend.response.ResponseResult;
import github.benjamin.equipreservebackend.service.ReservationService; 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.ReservationVO;
import github.benjamin.equipreservebackend.vo.UserReservationVO; import github.benjamin.equipreservebackend.vo.UserReservationVO;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; 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 @RestController
@RequestMapping("/reservation") @RequestMapping("/reservation")
@RequiredArgsConstructor @RequiredArgsConstructor
@ -55,32 +42,4 @@ public class ReservationController {
return ResponseResult.success(reservationService.getReservationVO(id, page, size)); 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,13 +2,8 @@ package github.benjamin.equipreservebackend.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import github.benjamin.equipreservebackend.entity.Reservation; import github.benjamin.equipreservebackend.entity.Reservation;
import github.benjamin.equipreservebackend.vo.ReservationStatsVO;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import java.time.LocalDate;
import java.util.List;
@Repository @Repository
public interface ReservationMapper extends BaseMapper<Reservation> { public interface ReservationMapper extends BaseMapper<Reservation> {
List<ReservationStatsVO> getReservationStats(LocalDate start, LocalDate end);
} }

View File

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

View File

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

View File

@ -1,33 +0,0 @@
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

@ -1,28 +0,0 @@
<?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>