new function: output csv file

Signed-off-by: Chenx221 <chenx221@yandex.com>
This commit is contained in:
Chenx221 2023-06-12 14:41:29 +08:00
parent 885e2651ed
commit f5a85585d2
14 changed files with 303 additions and 12 deletions

View File

@ -46,6 +46,8 @@
<element id="library" level="project" name="Maven: org.springframework:spring-web:5.3.27" /> <element id="library" level="project" name="Maven: org.springframework:spring-web:5.3.27" />
<element id="library" level="project" name="Maven: org.springframework:spring-webmvc:5.3.27" /> <element id="library" level="project" name="Maven: org.springframework:spring-webmvc:5.3.27" />
<element id="library" level="project" name="Maven: taglibs:standard:1.1.2" /> <element id="library" level="project" name="Maven: taglibs:standard:1.1.2" />
<element id="library" level="project" name="Maven: org.apache.commons:commons-csv:1.10.0" />
<element id="library" level="project" name="Maven: commons-io:commons-io:2.12.0" />
</element> </element>
</element> </element>
</root> </root>

View File

@ -23,6 +23,8 @@
<security:intercept-url pattern="/dashboard" access="hasRole('admin')"/> <security:intercept-url pattern="/dashboard" access="hasRole('admin')"/>
<security:intercept-url pattern="/student/**" access="hasRole('admin')"/> <security:intercept-url pattern="/student/**" access="hasRole('admin')"/>
<security:intercept-url pattern="/course/**" access="hasRole('admin')"/> <security:intercept-url pattern="/course/**" access="hasRole('admin')"/>
<security:intercept-url pattern="/score/**" access="hasRole('admin')"/>
<security:intercept-url pattern="/output/**" access="hasRole('admin')"/>
<!-- 未登录状态下会自动跳转到/login登录页--> <!-- 未登录状态下会自动跳转到/login登录页-->
<security:form-login login-page="/login" <security:form-login login-page="/login"
default-target-url="/dashboard" default-target-url="/dashboard"

View File

@ -130,7 +130,19 @@
style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;"> style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;">
<div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);"> <div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);">
<div class="container d-flex justify-content-center"> <div class="container d-flex justify-content-center">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回</button> <div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="exportCSV()">导出</button>
</div>
</div>
</div>
<div class="table-container rounded-4 shadow-3-strong" <div class="table-container rounded-4 shadow-3-strong"
style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;"> style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;">
<table class="table table-striped table-hover border-primary"> <table class="table table-striped table-hover border-primary">
@ -166,7 +178,18 @@
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script>
<script>
function exportCSV() {
// 构造请求 URL根据需要导出的类型传递参数
var exportUrl = '/output/export-csv?type=course'; // 示例:导出学生数据
var link = document.createElement('a');
link.href = exportUrl;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body> </body>

View File

@ -130,7 +130,20 @@
style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;"> style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;">
<div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);"> <div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);">
<div class="container d-flex justify-content-center"> <div class="container d-flex justify-content-center">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回</button> <div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="exportCSV()">导出</button>
</div>
</div>
</div>
<div class="table-container rounded-4 shadow-3-strong" <div class="table-container rounded-4 shadow-3-strong"
style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;"> style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;">
<table class="table table-striped table-hover border-primary"> <table class="table table-striped table-hover border-primary">
@ -138,6 +151,8 @@
<tr> <tr>
<th scope="col">成绩ID</th> <th scope="col">成绩ID</th>
<th scope="col">学号</th> <th scope="col">学号</th>
<th scope="col">学生姓名</th>
<th scope="col">课程ID</th>
<th scope="col">课程名</th> <th scope="col">课程名</th>
<th scope="col">成绩</th> <th scope="col">成绩</th>
</tr> </tr>
@ -147,6 +162,8 @@
<tr> <tr>
<td>${score.scoreID}</td> <td>${score.scoreID}</td>
<td>${score.student.id}</td> <td>${score.student.id}</td>
<td>${score.student.name}</td>
<td>${score.course.courseID}</td>
<td>${score.course.courseName}</td> <td>${score.course.courseName}</td>
<td>${score.score}</td> <td>${score.score}</td>
</tr> </tr>
@ -168,7 +185,18 @@
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script>
<script>
function exportCSV() {
// 构造请求 URL根据需要导出的类型传递参数
var exportUrl = '/output/export-csv?type=score'; // 示例:导出学生数据
var link = document.createElement('a');
link.href = exportUrl;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body> </body>

View File

@ -130,7 +130,19 @@
style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;"> style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;">
<div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);"> <div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);">
<div class="container d-flex justify-content-center"> <div class="container d-flex justify-content-center">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回</button> <div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="exportCSV()">导出</button>
</div>
</div>
</div>
<div class="table-container rounded-4 shadow-3-strong" <div class="table-container rounded-4 shadow-3-strong"
style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;"> style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;">
<table class="table table-striped table-hover border-primary"> <table class="table table-striped table-hover border-primary">
@ -172,7 +184,18 @@
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script>
<script>
function exportCSV() {
// 构造请求 URL根据需要导出的类型传递参数
var exportUrl = '/output/export-csv?type=student'; // 示例:导出学生数据
var link = document.createElement('a');
link.href = exportUrl;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body> </body>

View File

@ -156,5 +156,15 @@
<artifactId>log4j-core</artifactId> <artifactId>log4j-core</artifactId>
<version>2.12.4</version> <version>2.12.4</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.10.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.12.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -0,0 +1,127 @@
package cyou.chenx221.controller;
import cyou.chenx221.pojo.Course;
import cyou.chenx221.pojo.Score;
import cyou.chenx221.pojo.Student;
import cyou.chenx221.service.CourseService;
import cyou.chenx221.service.ScoreService;
import cyou.chenx221.service.StudentService;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("/output")
public class OutputController {
@Autowired
private StudentService studentService;
@Autowired
private CourseService courseService;
@Autowired
private ScoreService scoreService;
@GetMapping("/export-csv")
public void exportCSV(HttpServletResponse response, @RequestParam("type") String type) throws IOException {
response.setHeader("Content-Disposition", "attachment; filename=export.csv");
response.setContentType("text/csv; charset=UTF-8"); // 设置字符编码为UTF-8
response.setCharacterEncoding("UTF-8"); // 设置响应字符编码为UTF-8
List<String> headers;
List<List<String>> data;
switch (type) {
case "student" -> {
headers = Arrays.asList("学生ID", "学生姓名", "性别", "出生日期", "联系方式", "班级");
List<Student> students = studentService.getAllStudents(); // 根据实际情况获取学生数据
data = transformStudentsToData(students);
}
case "course" -> {
headers = Arrays.asList("课程ID", "课程名", "课程描述");
List<Course> courses = courseService.getAllCourses(); // 根据实际情况获取课程数据
data = transformCoursesToData(courses);
}
case "score" -> {
headers = Arrays.asList("成绩ID", "学生ID", "学生姓名", "课程ID", "课程名称", "成绩");
List<Score> scores = scoreService.getAllScores(); // 根据实际情况获取成绩数据
data = transformScoresToData(scores);
}
default -> throw new IllegalArgumentException("Invalid export type: " + type);
}
// 使用 Apache Commons CSV 构建 CSV 输出
try (OutputStream outputStream = response.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream, StandardCharsets.UTF_8);
CSVPrinter csvPrinter = new CSVPrinter(outputStreamWriter, CSVFormat.DEFAULT)) {
csvPrinter.printRecord(headers);
for (List<String> row : data) {
csvPrinter.printRecord(row);
}
csvPrinter.flush();
}
}
// 辅助方法将学生对象列表转换为数据列表
private List<List<String>> transformStudentsToData(List<Student> students) {
List<List<String>> data = new ArrayList<>();
for (Student student : students) {
List<String> rowData = Arrays.asList(
String.valueOf(student.getId()),
student.getName(),
student.getSex(),
student.getBirthday().toString(),
String.valueOf(student.getPhone()),
String.valueOf(student.getClasses())
);
data.add(rowData);
}
return data;
}
// 辅助方法将课程对象列表转换为数据列表
private List<List<String>> transformCoursesToData(List<Course> courses) {
List<List<String>> data = new ArrayList<>();
for (Course course : courses) {
List<String> rowData = Arrays.asList(
String.valueOf(course.getCourseID()),
course.getCourseName(),
course.getDescription()
);
data.add(rowData);
}
return data;
}
// 辅助方法将成绩对象列表转换为数据列表
private List<List<String>> transformScoresToData(List<Score> scores) {
List<List<String>> data = new ArrayList<>();
for (Score score : scores) {
List<String> rowData = Arrays.asList(
String.valueOf(score.getScoreID()),
String.valueOf(score.getStudent().getId()),
score.getStudent().getName(),
String.valueOf(score.getCourse().getCourseID()),
score.getCourse().getCourseName(),
String.valueOf(score.getScore())
);
data.add(rowData);
}
return data;
}
}

View File

@ -23,6 +23,8 @@
<security:intercept-url pattern="/dashboard" access="hasRole('admin')"/> <security:intercept-url pattern="/dashboard" access="hasRole('admin')"/>
<security:intercept-url pattern="/student/**" access="hasRole('admin')"/> <security:intercept-url pattern="/student/**" access="hasRole('admin')"/>
<security:intercept-url pattern="/course/**" access="hasRole('admin')"/> <security:intercept-url pattern="/course/**" access="hasRole('admin')"/>
<security:intercept-url pattern="/score/**" access="hasRole('admin')"/>
<security:intercept-url pattern="/output/**" access="hasRole('admin')"/>
<!-- 未登录状态下会自动跳转到/login登录页--> <!-- 未登录状态下会自动跳转到/login登录页-->
<security:form-login login-page="/login" <security:form-login login-page="/login"
default-target-url="/dashboard" default-target-url="/dashboard"

View File

@ -130,7 +130,19 @@
style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;"> style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;">
<div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);"> <div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);">
<div class="container d-flex justify-content-center"> <div class="container d-flex justify-content-center">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回</button> <div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="exportCSV()">导出</button>
</div>
</div>
</div>
<div class="table-container rounded-4 shadow-3-strong" <div class="table-container rounded-4 shadow-3-strong"
style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;"> style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;">
<table class="table table-striped table-hover border-primary"> <table class="table table-striped table-hover border-primary">
@ -166,7 +178,18 @@
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script>
<script>
function exportCSV() {
// 构造请求 URL根据需要导出的类型传递参数
var exportUrl = '/output/export-csv?type=course'; // 示例:导出学生数据
var link = document.createElement('a');
link.href = exportUrl;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body> </body>

View File

@ -130,7 +130,20 @@
style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;"> style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;">
<div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);"> <div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);">
<div class="container d-flex justify-content-center"> <div class="container d-flex justify-content-center">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回</button> <div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="exportCSV()">导出</button>
</div>
</div>
</div>
<div class="table-container rounded-4 shadow-3-strong" <div class="table-container rounded-4 shadow-3-strong"
style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;"> style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;">
<table class="table table-striped table-hover border-primary"> <table class="table table-striped table-hover border-primary">
@ -138,6 +151,8 @@
<tr> <tr>
<th scope="col">成绩ID</th> <th scope="col">成绩ID</th>
<th scope="col">学号</th> <th scope="col">学号</th>
<th scope="col">学生姓名</th>
<th scope="col">课程ID</th>
<th scope="col">课程名</th> <th scope="col">课程名</th>
<th scope="col">成绩</th> <th scope="col">成绩</th>
</tr> </tr>
@ -147,6 +162,8 @@
<tr> <tr>
<td>${score.scoreID}</td> <td>${score.scoreID}</td>
<td>${score.student.id}</td> <td>${score.student.id}</td>
<td>${score.student.name}</td>
<td>${score.course.courseID}</td>
<td>${score.course.courseName}</td> <td>${score.course.courseName}</td>
<td>${score.score}</td> <td>${score.score}</td>
</tr> </tr>
@ -168,7 +185,18 @@
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script>
<script>
function exportCSV() {
// 构造请求 URL根据需要导出的类型传递参数
var exportUrl = '/output/export-csv?type=score'; // 示例:导出学生数据
var link = document.createElement('a');
link.href = exportUrl;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body> </body>

View File

@ -130,7 +130,19 @@
style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;"> style="background-image: url('${pageContext.request.contextPath}/resources/img/jason-blackeye-nyL-rzwP-Mk-unsplash.jpg'); margin-top: -58.59px;">
<div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);"> <div class="mask d-flex align-items-center h-100" style="background-color: hsla(0, 0%, 100%, 0.5);">
<div class="container d-flex justify-content-center"> <div class="container d-flex justify-content-center">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回</button> <div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="location.href='../dashboard'">返回
</button>
</div>
</div>
<div class="row">
<div class="col-12">
<button type="button" class="btn btn-primary" onclick="exportCSV()">导出</button>
</div>
</div>
</div>
<div class="table-container rounded-4 shadow-3-strong" <div class="table-container rounded-4 shadow-3-strong"
style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;"> style="background-color: rgba(255,255,255,0.9); overflow-y: auto; max-height: 400px;">
<table class="table table-striped table-hover border-primary"> <table class="table table-striped table-hover border-primary">
@ -172,7 +184,18 @@
<script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/resources/js/mdb.min.js"></script>
<script>
function exportCSV() {
// 构造请求 URL根据需要导出的类型传递参数
var exportUrl = '/output/export-csv?type=student'; // 示例:导出学生数据
var link = document.createElement('a');
link.href = exportUrl;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body> </body>