修复了成绩查询界面当无数据时显示错误的bug、基本完成了上传附件的功能、调整了报告提交界面的部分查询逻辑。
写了一个暂时无用的下载方法,可以后续查看是否使用。 上传文件方法部分写的后端接口貌似支持在本地文件(AUTO-SCORE)自动生成一个upload文件并上传相应文件,可以后续调整下载位置。
This commit is contained in:
parent
dca09393fe
commit
9afac81d92
|
|
@ -34,6 +34,21 @@ export default {
|
||||||
|
|
||||||
getPostProblemInfo:(config) => request.get('/problem/getPostProblemInfo', config),//获取当前报告布置信息
|
getPostProblemInfo:(config) => request.get('/problem/getPostProblemInfo', config),//获取当前报告布置信息
|
||||||
|
|
||||||
findProblemById1:(config)=>request.get('/problem/findProblemById1',config)//获取当前报告具体信息
|
findProblemById1:(config)=>request.get('/problem/findProblemById1',config),//获取当前报告具体信息
|
||||||
|
|
||||||
|
getSubmitReport:(config) => request.get('/problem/getSubmitReport', config),//获取学生已上传报告信息
|
||||||
|
|
||||||
|
//文件处理部分
|
||||||
|
uploadFiles: (data) =>
|
||||||
|
request({
|
||||||
|
url: '/importClassStudentsFile/uploadFiles',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
}), //学生上传文件
|
||||||
|
|
||||||
|
downloadFile: (fileName) =>
|
||||||
|
request({
|
||||||
|
url: `/downloadFile/downloadFile/${fileName}`,
|
||||||
|
method: 'get',
|
||||||
|
}), // 文件下载
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,29 +12,59 @@
|
||||||
<div slot="header" class="clearfix card-header">
|
<div slot="header" class="clearfix card-header">
|
||||||
<span class="subtitle">实验提交</span>
|
<span class="subtitle">实验提交</span>
|
||||||
</div>
|
</div>
|
||||||
<el-input
|
<br>
|
||||||
type="textarea"
|
<el-button size="small" type="success" @click="showUploadDialog">上传附件</el-button>
|
||||||
:rows="4"
|
<div v-if="fileUrls.length > 0" class="file-list">
|
||||||
placeholder="请输入你的实验报告"
|
<span class="file-list-title">已上传文件:</span>
|
||||||
v-model="reportText"
|
<ul>
|
||||||
class="submit-textarea"
|
<li v-for="(file, index) in fileUrls" :key="index">
|
||||||
></el-input>
|
{{ file.name }}
|
||||||
<el-button size="small" type="success">上传附件</el-button>
|
</li>
|
||||||
|
</ul>
|
||||||
</el-card>
|
|
||||||
</div>
|
</div>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<!-- 文件上传弹窗 -->
|
||||||
|
<el-dialog :title="'上传附件'" v-model="uploadDialogVisible" width="60%">
|
||||||
|
<el-upload
|
||||||
|
ref="uploadComponent"
|
||||||
|
:auto-upload="false"
|
||||||
|
:on-change="handleFileChange"
|
||||||
|
:on-success="handleUploadSuccess"
|
||||||
|
:on-error="handleUploadError"
|
||||||
|
v-model:file-list="fileList"
|
||||||
|
drag
|
||||||
|
accept=".txt,.doc,.docx,.pdf"
|
||||||
|
>
|
||||||
|
<i class="el-icon-upload"></i>
|
||||||
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
</el-upload>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="uploadDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="uploadFile">确定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<ReportActions class="bottom" />
|
||||||
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted } from 'vue';
|
import { ref, onMounted } from 'vue';
|
||||||
import api from '@/api/user';
|
import api from '@/api/user';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
|
import { ElMessage } from 'element-plus';
|
||||||
|
import ReportActions from "@/views/user/report-submit/components/report-actions.vue";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const ProblemId = route.params.examId;
|
const ProblemId = route.params.examId;
|
||||||
const description = ref(""); // 实验描述
|
const description = ref(""); // 实验描述
|
||||||
const reportText = ref(""); // 实验报告文本
|
const reportText = ref(""); // 实验报告文本
|
||||||
|
const uploadDialogVisible = ref(false); // 控制上传弹窗的显示
|
||||||
|
const fileList = ref([]); // 上传的文件列表
|
||||||
|
const fileUrls = ref([]); // 文件的URL列表
|
||||||
|
const uploadComponent = ref(null); // 用于引用el-upload组件
|
||||||
|
|
||||||
const getProblemInfo = async () => {
|
const getProblemInfo = async () => {
|
||||||
// 查询作业信息
|
// 查询作业信息
|
||||||
|
|
@ -46,12 +76,79 @@ const getProblemInfo = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 显示上传弹窗
|
||||||
|
const showUploadDialog = () => {
|
||||||
|
uploadDialogVisible.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理文件选择变化
|
||||||
|
const handleFileChange = (file, fileList) => {
|
||||||
|
console.log('File list updated:', fileList);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理文件上传成功
|
||||||
|
const handleUploadSuccess = (response, file, fileList) => {
|
||||||
|
if (response.success) {
|
||||||
|
ElMessage.success('文件上传成功');
|
||||||
|
// 更新文件URL列表
|
||||||
|
fileUrls.value.push({ url: response.urls, name: response.data });
|
||||||
|
uploadDialogVisible.value = false;
|
||||||
|
fileList.value = [];
|
||||||
|
} else {
|
||||||
|
ElMessage.error('文件上传失败');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 处理文件上传失败
|
||||||
|
const handleUploadError = (err, file, fileList) => {
|
||||||
|
console.error("Failed to upload files:", err);
|
||||||
|
ElMessage.error('文件上传失败');
|
||||||
|
};
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
const uploadFile = async () => {
|
||||||
|
if (fileList.value.length === 0) {
|
||||||
|
ElMessage.error('请选择要上传的文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const formData = new FormData();
|
||||||
|
fileList.value.forEach(file => {
|
||||||
|
formData.append('files', file.raw); // 添加文件到FormData
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await api.uploadFiles(formData); // 调用上传文件的方法
|
||||||
|
console.log('Response from server:', response); // 打印响应内容
|
||||||
|
if (response.code === 0) {
|
||||||
|
ElMessage.success('文件上传成功');
|
||||||
|
// 更新文件URL列表
|
||||||
|
fileUrls.value.push({ url: response.urls, name: response.data });
|
||||||
|
uploadDialogVisible.value = false;
|
||||||
|
fileList.value = [];
|
||||||
|
} else {
|
||||||
|
ElMessage.error('文件上传失败1');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to upload files:", error);
|
||||||
|
ElMessage.error('文件上传失败2');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 下载文件
|
||||||
|
const downloadFile = (url) => {
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.target = '_blank';
|
||||||
|
link.download = url.split('/').pop(); // 提取文件名
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
};
|
||||||
|
|
||||||
// 生命周期钩子
|
// 生命周期钩子
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getProblemInfo(); // 挂载时查询作业信息
|
getProblemInfo(); // 挂载时查询作业信息
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
@ -84,5 +181,25 @@ onMounted(() => {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-upload-dragger {
|
||||||
|
width: 100%;
|
||||||
|
height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list-title {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.file-list li {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
<n-button type="primary" size="medium" @click="onSave">保存</n-button>
|
<n-button type="primary" size="small" @click="onSave">保存</n-button>
|
||||||
<n-button type="success" size="medium" @click="onSaveAndSubmit">保存并提交</n-button>
|
<n-button type="success" size="small" @click="onSaveAndSubmit">保存并提交</n-button>
|
||||||
<n-button type="warning" size="medium" @click="onWithdraw">申请撤回</n-button>
|
<n-button type="warning" size="small" @click="onWithdraw">申请撤回</n-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ const plagiarismStatus = ref(0); // 初始化抄袭状态
|
||||||
const getJudgeInfo = async () => {
|
const getJudgeInfo = async () => {
|
||||||
// 查询批阅相关信息
|
// 查询批阅相关信息
|
||||||
try {
|
try {
|
||||||
const res = await api.getStudentRank({ params: { examId } });
|
const res = await api.getSubmitReport({ params: { examId } });
|
||||||
comment.value = res.data.comment; // 更新教师评语
|
comment.value = res.data.comment; // 更新教师评语
|
||||||
plagiarismStatus.value = res.data.plagiarismStatus; // 更新抄袭状态
|
plagiarismStatus.value = res.data.plagiarismStatus; // 更新抄袭状态
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -14,21 +14,20 @@
|
||||||
<Rightparts class="rightparts" />
|
<Rightparts class="rightparts" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<ReportActions class="bottom" />
|
|
||||||
</CommonPage>
|
</CommonPage>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import api from '@/api/user';
|
import api from '@/api/user';
|
||||||
import {useRoute} from 'vue-router';
|
import {useRoute} from 'vue-router';
|
||||||
import ReportActions from "@/views/user/report-submit/components/report-actions.vue";
|
|
||||||
import Leftparts from "@/views/user/report-submit/components/leftparts.vue";
|
import Leftparts from "@/views/user/report-submit/components/leftparts.vue";
|
||||||
import Rightparts from "@/views/user/report-submit/components/rightparts.vue";
|
import Rightparts from "@/views/user/report-submit/components/rightparts.vue";
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const examId = route.params.examId;
|
const examId = route.params.examId;
|
||||||
|
const ProblemId = route.params.examId;
|
||||||
const classId = route.params.classId;
|
const classId = route.params.classId;
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const title = ref(""); // 从API获取的作业名称
|
const title = ref(""); // 从API获取的作业名称
|
||||||
|
|
@ -36,36 +35,17 @@ const countdown = ref(""); // 用于显示倒计时
|
||||||
// 将结束时间转换为Date对象
|
// 将结束时间转换为Date对象
|
||||||
let endTime = null; // 结束时间初始化为null
|
let endTime = null; // 结束时间初始化为null
|
||||||
|
|
||||||
const paginationReactive = reactive({
|
|
||||||
page: 1,
|
|
||||||
pageSize: 50,
|
|
||||||
showSizePicker: true,
|
|
||||||
pageSizes: [50, 100, 150],
|
|
||||||
itemCount: 0,
|
|
||||||
prefix: () => {
|
|
||||||
return '查询出 ' + total + '条记录';
|
|
||||||
},
|
|
||||||
onChange: (page) => {
|
|
||||||
paginationReactive.page = page;
|
|
||||||
queryExamScores()
|
|
||||||
},
|
|
||||||
onUpdatePageSize: (pageSize) => {
|
|
||||||
paginationReactive.pageSize = pageSize;
|
|
||||||
paginationReactive.page = 1;
|
|
||||||
queryExamScores()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const queryExamScores = async () => {
|
|
||||||
//查询作业名称信息(直接复用查询排名)
|
|
||||||
try {
|
|
||||||
//查询作业名称信息(直接复用查询排名)
|
|
||||||
const res1 = await api.getStudentRank({ params: { examId } });
|
|
||||||
//查询作业时间等信息
|
|
||||||
const res = await api.getPostProblemInfo({ params: { classId, examId } });
|
|
||||||
|
|
||||||
|
const queryExamName = async () => {
|
||||||
|
//查询作业名称
|
||||||
|
const res1 = await api.findProblemById1({ params: { ProblemId } });
|
||||||
title.value = res1.data.title; // 更新作业名称
|
title.value = res1.data.title; // 更新作业名称
|
||||||
|
|
||||||
|
};
|
||||||
|
const getProblemTime = async () => {
|
||||||
|
//查询作业时间等信息
|
||||||
|
try {
|
||||||
|
const res = await api.getPostProblemInfo({ params: { classId, examId } });
|
||||||
// 将结束时间转换为Date对象
|
// 将结束时间转换为Date对象
|
||||||
endTime = new Date(res.data.endTime[0], res.data.endTime[1] - 1, res.data.endTime[2], res.data.endTime[3], res.data.endTime[4]);
|
endTime = new Date(res.data.endTime[0], res.data.endTime[1] - 1, res.data.endTime[2], res.data.endTime[3], res.data.endTime[4]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -96,7 +76,8 @@ const updateCountdown = () => {
|
||||||
// 使用setInterval来每秒更新倒计时
|
// 使用setInterval来每秒更新倒计时
|
||||||
let intervalId = null;
|
let intervalId = null;
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await queryExamScores(); // 确保在挂载时查询数据
|
await queryExamName(); // 确保在挂载时查询数据
|
||||||
|
await getProblemTime(); // 查询剩余时间
|
||||||
if (endTime) {
|
if (endTime) {
|
||||||
updateCountdown(); // 初始更新
|
updateCountdown(); // 初始更新
|
||||||
intervalId = setInterval(updateCountdown, 1000); // 设置定时器
|
intervalId = setInterval(updateCountdown, 1000); // 设置定时器
|
||||||
|
|
@ -114,11 +95,6 @@ const rowKey = (rowData) => {
|
||||||
return rowData.id;
|
return rowData.id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 生命周期钩子
|
|
||||||
onMounted(() => {
|
|
||||||
queryExamScores(); // 挂载时查询作业名
|
|
||||||
});
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
@ -160,4 +136,5 @@ onMounted(() => {
|
||||||
width: 100%; /* 宽度占满整个容器 */
|
width: 100%; /* 宽度占满整个容器 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ const examId = route.params.examId;
|
||||||
const classId = route.params.classId;
|
const classId = route.params.classId;
|
||||||
const title = ref(""); // 从API获取的作业名称
|
const title = ref(""); // 从API获取的作业名称
|
||||||
const score = ref(0); // 个人得分
|
const score = ref(0); // 个人得分
|
||||||
const rank = ref(0); // 个人排名
|
const rank = ref("-"); // 个人排名,默认为 "-"
|
||||||
const totalStudents = ref(0); // 班级总人数
|
const totalStudents = ref(0); // 班级总人数
|
||||||
|
|
||||||
const paginationReactive = reactive({
|
const paginationReactive = reactive({
|
||||||
|
|
@ -53,18 +53,20 @@ const queryExamScores = async () => {
|
||||||
const res = await api.getStudentRank({
|
const res = await api.getStudentRank({
|
||||||
params: { examId }
|
params: { examId }
|
||||||
});
|
});
|
||||||
|
title.value = res.data.title; // 更新作业名称
|
||||||
|
score.value = res.data.score; // 更新个人得分
|
||||||
|
rank.value = res.data.rank || "-"; // 更新个人排名,如果rank为空则显示 "-"
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryClassStudents = async () => {
|
||||||
//查询班级总人数
|
//查询班级总人数
|
||||||
const res1 = await api.getClassStudents({
|
const res1 = await api.getClassStudents({
|
||||||
params: { classId }
|
params: { classId }
|
||||||
});
|
});
|
||||||
|
console.log(res1);
|
||||||
title.value = res.data.title; // 更新作业名称
|
|
||||||
score.value = res.data.score; // 更新个人得分
|
|
||||||
rank.value = res.data.rank; // 更新个人排名
|
|
||||||
totalStudents.value = res1.data;// 更新班级总人数
|
totalStudents.value = res1.data;// 更新班级总人数
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 行键函数
|
// 行键函数
|
||||||
const rowKey = (rowData) => {
|
const rowKey = (rowData) => {
|
||||||
return rowData.id;
|
return rowData.id;
|
||||||
|
|
@ -73,6 +75,7 @@ const rowKey = (rowData) => {
|
||||||
// 生命周期钩子
|
// 生命周期钩子
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
queryExamScores(); // 挂载时查询成绩
|
queryExamScores(); // 挂载时查询成绩
|
||||||
|
queryClassStudents();// 同时查询班级人数
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -359,7 +359,22 @@ public class ProblemController {
|
||||||
if (ureportsubmitted != null) {
|
if (ureportsubmitted != null) {
|
||||||
return RespBean.ok("查询成绩排名成功!", ureportsubmitted);
|
return RespBean.ok("查询成绩排名成功!", ureportsubmitted);
|
||||||
} else {
|
} else {
|
||||||
return RespBean.error("查询成绩排名失败!");
|
return RespBean.error("尚未提交作业!暂时无法查看排名!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据作业id和学生id获取学生当前报告成绩排名,与上一方法基本类似,处理空搜索时的输出
|
||||||
|
@GetMapping("/getSubmitReport")
|
||||||
|
public RespBean getSubmitReport(Integer examId, HttpServletRequest request) {
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String UserId = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(UserId);
|
||||||
|
UReportSubmitted ureportsubmitted =
|
||||||
|
problemServiceI.findScoreAndRankByIds(examId, userId);
|
||||||
|
if (ureportsubmitted != null) {
|
||||||
|
return RespBean.ok("查询成绩排名成功!", ureportsubmitted);
|
||||||
|
} else {
|
||||||
|
return RespBean.ok("尚未提交作业!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,15 @@ package com.example.aes.user.controller;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.resource.UrlResource;
|
||||||
import com.example.aes.global.model.RespBean;
|
import com.example.aes.global.model.RespBean;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
|
@ -13,6 +18,8 @@ import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipOutputStream;
|
import java.util.zip.ZipOutputStream;
|
||||||
|
|
||||||
|
|
@ -139,4 +146,25 @@ public class DownLoadFileController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 提供文件下载的方法
|
||||||
|
@GetMapping("/downloadFile/{fileName:.+}")
|
||||||
|
public ResponseEntity<javax.annotation.Resource> downloadFile(@PathVariable String fileName) {
|
||||||
|
try {
|
||||||
|
String root = System.getProperty("user.dir") + File.separator + "upload";
|
||||||
|
Path filePath = Paths.get(root).toAbsolutePath().normalize().resolve(fileName);
|
||||||
|
javax.annotation.Resource resource = (javax.annotation.Resource) new UrlResource(filePath.toUri());
|
||||||
|
String contentType = "application/octet-stream";
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.contentType(MediaType.parseMediaType(contentType))
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.name() + "\"")
|
||||||
|
.body(resource);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.example.aes.user.controller;
|
package com.example.aes.user.controller;
|
||||||
|
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.resource.UrlResource;
|
||||||
import com.example.aes.global.model.RespBean;
|
import com.example.aes.global.model.RespBean;
|
||||||
import com.example.aes.user.dao.AdminusersDaoI;
|
import com.example.aes.user.dao.AdminusersDaoI;
|
||||||
import com.example.aes.user.dao.ClassesDaoI;
|
import com.example.aes.user.dao.ClassesDaoI;
|
||||||
|
|
@ -11,19 +12,21 @@ import com.example.aes.user.model.PMUser;
|
||||||
import com.example.aes.user.model.Users;
|
import com.example.aes.user.model.Users;
|
||||||
import com.example.aes.user.service.UserServiceI;
|
import com.example.aes.user.service.UserServiceI;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
|
@ -374,4 +377,79 @@ public class importClassStudentsFileController{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/uploadFiles") // 学生上传文件并提供其URL
|
||||||
|
public ResponseEntity<Map<String, Object>> uploadFiles(MultipartFile[] files) {
|
||||||
|
Map<String, Object> response = new HashMap<>();
|
||||||
|
try {
|
||||||
|
// 获取文件存储根目录
|
||||||
|
String root = System.getProperty("user.dir") + File.separator + "upload";
|
||||||
|
if (!new File(root).exists()) {
|
||||||
|
new File(root).mkdirs();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 用于存储所有上传文件的名称和URL
|
||||||
|
StringBuilder fileNames = new StringBuilder();
|
||||||
|
StringBuilder fileUrls = new StringBuilder();
|
||||||
|
|
||||||
|
for (MultipartFile file : files) {
|
||||||
|
// 获取文件原始名
|
||||||
|
String uploadFileName = file.getOriginalFilename();
|
||||||
|
|
||||||
|
// 检查文件类型
|
||||||
|
if (!uploadFileName.endsWith(".txt") && !uploadFileName.endsWith(".doc") &&
|
||||||
|
!uploadFileName.endsWith(".docx") && !uploadFileName.endsWith(".pdf")) {
|
||||||
|
throw new IllegalArgumentException("不支持的文件类型: " + uploadFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取主要名称
|
||||||
|
String mainName = FileUtil.mainName(uploadFileName);
|
||||||
|
// 获取文件后缀名
|
||||||
|
String extName = FileUtil.extName(uploadFileName);
|
||||||
|
// 用当前时间避免重复
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
Date date1 = new Date();
|
||||||
|
String timeStamp = formatter.format(date1);
|
||||||
|
|
||||||
|
// 构造新的文件名
|
||||||
|
String newFileName = mainName + "_" + timeStamp + "." + extName;
|
||||||
|
|
||||||
|
// 构造文件保存路径
|
||||||
|
String filePath = root + File.separator + newFileName;
|
||||||
|
|
||||||
|
// 保存文件到服务器
|
||||||
|
File dest = new File(filePath);
|
||||||
|
file.transferTo(dest);
|
||||||
|
|
||||||
|
// 构造文件访问URL
|
||||||
|
String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
|
||||||
|
.path("/downloadFile/")
|
||||||
|
.path(newFileName)
|
||||||
|
.toUriString();
|
||||||
|
|
||||||
|
// 添加文件名和URL到返回信息中
|
||||||
|
fileNames.append(newFileName).append(", ");
|
||||||
|
fileUrls.append(fileDownloadUri).append(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 移除最后一个逗号和空格
|
||||||
|
if (fileNames.length() > 0) {
|
||||||
|
fileNames.setLength(fileNames.length() - 2);
|
||||||
|
}
|
||||||
|
if (fileUrls.length() > 0) {
|
||||||
|
fileUrls.setLength(fileUrls.length() - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.put("code", 0);
|
||||||
|
response.put("message", "文件上传成功");
|
||||||
|
response.put("data", fileNames.toString());
|
||||||
|
response.put("urls", fileUrls.toString());
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
response.put("code", 1);
|
||||||
|
response.put("message", "文件上传异常: " + e.getMessage());
|
||||||
|
return ResponseEntity.badRequest().body(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
智能手机在当代社会的作用不可小觑,它不仅使得人们的通讯变得极为便捷,还提供了多样化的娱乐和工作功能。在我国,智能手机的普及率不断上升,几乎成了每个人生活中的必需品。它的多功能性和便携性,使其成为了现代科技的一个标志性产物。无论是通讯、娱乐还是学习,都离不开这款电子设备。
|
||||||
|
在城市边缘的那所著名大学的操场上,一场几千人参加的批斗会已经进行了近两个小时。
|
||||||
|
“爱因斯坦是反动的学术权威,他有奶便是娘,跑去为美帝国主义造原子弹!要建立起革命的科学,就要打倒以相对论为代表的资产阶级理论黑旗!”
|
||||||
|
然后在法文词下列出同义的上海方言词语,再尽可能详尽地列出近义的上海方言词语、短语或句子。这种编写方式,对中法两国学习者或词典使用者尽可能多地掌握法汉词汇,显然是很有意义的。
|
||||||
Loading…
Reference in New Issue