Compare commits
21 Commits
a9837d2128
...
3091fbb7dd
| Author | SHA1 | Date |
|---|---|---|
|
|
3091fbb7dd | |
|
|
60eb127de1 | |
|
|
f53d9efe79 | |
|
|
5fd14d4684 | |
|
|
2ef40a7f53 | |
|
|
7548ed3b2f | |
|
|
378f47e8a1 | |
|
|
9088f3742b | |
|
|
3335505400 | |
|
|
42243c0dd3 | |
|
|
42705cf3a8 | |
|
|
0ad286ad0c | |
|
|
14658c8b39 | |
|
|
10d180e7f2 | |
|
|
0e2ce0008a | |
|
|
621b40fb5e | |
|
|
3794933261 | |
|
|
4522512654 | |
|
|
12bd542196 | |
|
|
9ced850b88 | |
|
|
a30ecee6a5 |
|
|
@ -0,0 +1,53 @@
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
**/.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Editor / local tooling
|
||||||
|
.cursor/
|
||||||
|
.idea/inspectionProfiles/
|
||||||
|
*.swp
|
||||||
|
AES-front/.npmrc
|
||||||
|
AES-front/pnpm-workspace.yaml
|
||||||
|
|
||||||
|
# Dependencies and build output
|
||||||
|
node_modules/
|
||||||
|
**/node_modules/
|
||||||
|
AES/target/
|
||||||
|
**/target/
|
||||||
|
dist/
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Unrelated local documents
|
||||||
|
211310132.pdf
|
||||||
|
211310509.pdf
|
||||||
|
docs/需求说明.mp4
|
||||||
|
docs/通用语音识别_需求说明.mp4 (1).txt
|
||||||
|
docs/自动评分系统/
|
||||||
|
|
||||||
|
# Binary / media files (keep already-tracked assets)
|
||||||
|
*.pdf
|
||||||
|
*.mp4
|
||||||
|
*.mp3
|
||||||
|
*.wav
|
||||||
|
*.zip
|
||||||
|
*.rar
|
||||||
|
*.7z
|
||||||
|
*.doc
|
||||||
|
*.docx
|
||||||
|
*.xls
|
||||||
|
*.xlsx
|
||||||
|
*.ppt
|
||||||
|
*.pptx
|
||||||
|
*.jar
|
||||||
|
*.war
|
||||||
|
|
||||||
|
# Runtime uploads and empty local dumps
|
||||||
|
upload/
|
||||||
|
dependency-tree.txt
|
||||||
|
AES/停用词.txt
|
||||||
|
|
||||||
|
# Logs and Python cache
|
||||||
|
*.log
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
@ -38,7 +38,9 @@ export default {
|
||||||
|
|
||||||
getSubmitReport:(config) => request.get('/problem/getSubmitReport', config),//获取学生已上传报告信息
|
getSubmitReport:(config) => request.get('/problem/getSubmitReport', config),//获取学生已上传报告信息
|
||||||
|
|
||||||
//文件处理部分
|
pickExam: (data) => request.post('/problem/pickExam', data),
|
||||||
|
|
||||||
|
//文件处理部分
|
||||||
uploadFiles: (data) =>
|
uploadFiles: (data) =>
|
||||||
request({
|
request({
|
||||||
url: '/importClassStudentsFile/uploadFiles',
|
url: '/importClassStudentsFile/uploadFiles',
|
||||||
|
|
@ -51,4 +53,17 @@ export default {
|
||||||
url: `/downloadFile/downloadFile/${fileName}`,
|
url: `/downloadFile/downloadFile/${fileName}`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
}), // 文件下载
|
}), // 文件下载
|
||||||
|
|
||||||
|
|
||||||
|
runPlagiarism:(data) => request.post('/plagiarism/runPlagiarism', data),//运行查重算法
|
||||||
|
|
||||||
|
autoScore:(data) => request.post('/problem/autoscore', data),//运行自动批阅
|
||||||
|
//保存文件名到数据库
|
||||||
|
saveInfoToProps: (data) => request.post('/problem/saveInfoToProps', data),
|
||||||
|
|
||||||
|
submitInfoToProps: (data) => request.post('/problem/submitInfoToProps', data),
|
||||||
|
|
||||||
|
withdrawInfoToProps: (data) => request.post('/problem/withdrawInfoToProps', data),
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<footer f-c-c flex-col text-14 color="#6a6a6a">
|
<footer f-c-c flex-col text-14 color="#6a6a6a">
|
||||||
<p>Online Judge 2.0</p>
|
<p>报告自动批阅系统</p>
|
||||||
<p>Copyright © 2023-2024 . All Rights Reserved.</p>
|
<p>Copyright © 2023-2024 . All Rights Reserved.</p>
|
||||||
<p>技术支持:Turbo Email:11249242@qq.com</p>
|
<p>技术支持:Turbo Email:11249242@qq.com</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
>
|
>
|
||||||
<LoginForm
|
<LoginForm
|
||||||
:login="api.login"
|
:login="api.login"
|
||||||
:title="isAdminEnd() ? '报告自动评测系统 - 管理端' : '报告自动评测系统 - 登录'"
|
:title="isAdminEnd() ? '报告自动批阅系统 - 管理端' : '报告自动批阅系统 - 登录'"
|
||||||
@close="userStore.closeLoginModal"
|
@close="userStore.closeLoginModal"
|
||||||
/>
|
/>
|
||||||
</n-modal>
|
</n-modal>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// 控制“进入”按钮在短时间内只能被点击一次,该按钮若短时间内多次点击会出现
|
// 控制“进入”按钮在短时间内只能被点击一次,该按钮若短时间内多次点击会出现
|
||||||
// “Redis未启动”、“提交本题不能过快,请稍后重试”等错误
|
|
||||||
const isClicked = ref(false)
|
const isClicked = ref(false)
|
||||||
|
|
||||||
const emit = defineEmits(['clickStart', 'clickGrade'])
|
const emit = defineEmits(['clickStart', 'clickGrade'])
|
||||||
|
|
|
||||||
|
|
@ -40,8 +40,18 @@ const paginationReactive = reactive({
|
||||||
|
|
||||||
const onStartExam = async (exam) => {//点击进入控件的逻辑
|
const onStartExam = async (exam) => {//点击进入控件的逻辑
|
||||||
try {
|
try {
|
||||||
|
|
||||||
const examId = exam.id
|
const examId = exam.id
|
||||||
const classId = exam.classId
|
const classId = exam.classId
|
||||||
|
const adminuserId = classId //这里先暂时用classid替换,在方法内修改为老师id
|
||||||
|
const problemId = examId
|
||||||
|
const submitReport = {
|
||||||
|
problemId,
|
||||||
|
adminuserId
|
||||||
|
};
|
||||||
|
if(exam.submissionStatus==null) {
|
||||||
|
const res = await api.pickExam(submitReport)//领取作业
|
||||||
|
}
|
||||||
router.push({ name: 'ReportSubmit', params: { examId,classId }, query: { fromclient: false } })
|
router.push({ name: 'ReportSubmit', params: { examId,classId }, query: { fromclient: false } })
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err)
|
console.log(err)
|
||||||
|
|
@ -110,12 +120,12 @@ const columns = [
|
||||||
|
|
||||||
{
|
{
|
||||||
key: 'status',
|
key: 'status',
|
||||||
title: '状态',
|
title: '状态(分数标红为疑似抄袭)',
|
||||||
width: '116',
|
width: '116',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render: (row) => {
|
render: (row) => {
|
||||||
const statusText = row.status; // 假设分数存储在row.status
|
const statusText = row.status; // 假设分数存储在row.status
|
||||||
const isPlagiarized = row.plagiarismStatus === "2";//疑似抄袭
|
const isPlagiarized = row.plagiarismStatus === "疑似抄袭";
|
||||||
// 使用内联样式标红
|
// 使用内联样式标红
|
||||||
const style = isPlagiarized ? { color: 'red' } : {};
|
const style = isPlagiarized ? { color: 'red' } : {};
|
||||||
// 如果使用内联样式
|
// 如果使用内联样式
|
||||||
|
|
@ -156,17 +166,8 @@ const queryByPage = async (currentPage) => {//进入页面加载逻辑
|
||||||
paginationReactive.itemCount = total
|
paginationReactive.itemCount = total
|
||||||
examList.value = list
|
examList.value = list
|
||||||
|
|
||||||
// 添加倒计时控制
|
|
||||||
examList.value.forEach((exam) => {
|
} catch (err) {
|
||||||
// 距离考试不到1h,开始倒计时
|
|
||||||
if (exam.status.startsWith('还有')) {
|
|
||||||
// 格式:"还有" + minute + ":" + second
|
|
||||||
const [minute, second] = exam.status.replace('还有', '').split(':')
|
|
||||||
countdownControllers[exam.id] = useCountdown()
|
|
||||||
countdownControllers[exam.id].startCountdown(Number(minute) * 60 + Number(second))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
console.log(err)
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false
|
loading.value = false
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<!-- 整个页面外层container -->
|
<!-- 整个页面外层container -->
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<!-- 测试标题 -->
|
<!-- 测试标题 -->
|
||||||
<p id="indexTitle" class="lead">在线报告评测系统(首页)</p>
|
<p id="indexTitle" class="lead">在线报告批阅系统(首页)</p>
|
||||||
<!-- 图片和文字说明的外层容器 -->
|
<!-- 图片和文字说明的外层容器 -->
|
||||||
<div class="index-content">
|
<div class="index-content">
|
||||||
<!-- 图片 -->
|
<!-- 图片 -->
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
<template>
|
|
||||||
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "index"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -12,10 +12,18 @@
|
||||||
<div slot="header" class="clearfix card-header">
|
<div slot="header" class="clearfix card-header">
|
||||||
<span class="subtitle">实验提交</span>
|
<span class="subtitle">实验提交</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="attachment" class="file-list">
|
||||||
|
<span class="file-list-title">已保存的文件:</span>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
{{ attachment }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<el-button size="small" type="success" @click="showUploadDialog">上传附件</el-button>
|
<el-button size="small" type="success" @click="showUploadDialog">上传附件</el-button>
|
||||||
<div v-if="fileUrls.length > 0" class="file-list">
|
<div v-if="fileUrls.length > 0" class="file-list">
|
||||||
<span class="file-list-title">已上传文件:</span>
|
<span class="file-list-title">已上传文件(保存过的文件将被覆盖保存):</span>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="(file, index) in fileUrls" :key="index">
|
<li v-for="(file, index) in fileUrls" :key="index">
|
||||||
{{ file.name }}
|
{{ file.name }}
|
||||||
|
|
@ -35,6 +43,8 @@
|
||||||
v-model:file-list="fileList"
|
v-model:file-list="fileList"
|
||||||
drag
|
drag
|
||||||
accept=".txt,.doc,.docx,.pdf"
|
accept=".txt,.doc,.docx,.pdf"
|
||||||
|
:limit="1"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
>
|
>
|
||||||
<i class="el-icon-upload"></i>
|
<i class="el-icon-upload"></i>
|
||||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||||
|
|
@ -44,7 +54,15 @@
|
||||||
<el-button type="primary" @click="uploadFile">确定</el-button>
|
<el-button type="primary" @click="uploadFile">确定</el-button>
|
||||||
</span>
|
</span>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<ReportActions class="bottom" />
|
<ReportActions
|
||||||
|
:fileUrls="fileUrls"
|
||||||
|
:ProblemId="ProblemId"
|
||||||
|
:adminuserId="adminuserId"
|
||||||
|
:attachment="attachment"
|
||||||
|
:disabled="isReportActionsDisabled"
|
||||||
|
@refreshAttachment="refreshAttachmentInfo"
|
||||||
|
class="bottom"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -59,18 +77,24 @@ import ReportActions from "@/views/user/report-submit/components/report-actions.
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const ProblemId = route.params.examId;
|
const ProblemId = route.params.examId;
|
||||||
|
const examId = route.params.examId;
|
||||||
const description = ref(""); // 实验描述
|
const description = ref(""); // 实验描述
|
||||||
|
const adminuserId = ref(""); //布置实验的教师id
|
||||||
const reportText = ref(""); // 实验报告文本
|
const reportText = ref(""); // 实验报告文本
|
||||||
const uploadDialogVisible = ref(false); // 控制上传弹窗的显示
|
const uploadDialogVisible = ref(false); // 控制上传弹窗的显示
|
||||||
const fileList = ref([]); // 上传的文件列表
|
const fileList = ref([]); // 上传的文件列表
|
||||||
const fileUrls = ref([]); // 文件的URL列表
|
const fileUrls = ref([]); // 文件的URL列表
|
||||||
|
const attachment = ref(null);//已保存的文件信息
|
||||||
|
const isReportActionsDisabled = ref(false); // 控制ReportActions组件的禁用状态
|
||||||
const uploadComponent = ref(null); // 用于引用el-upload组件
|
const uploadComponent = ref(null); // 用于引用el-upload组件
|
||||||
|
const plagiarismStatus = ref(0); // 初始化抄袭状态
|
||||||
|
|
||||||
const getProblemInfo = async () => {
|
const getProblemInfo = async () => {
|
||||||
// 查询作业信息
|
// 查询作业信息
|
||||||
try {
|
try {
|
||||||
const res = await api.findProblemById1({ params: { ProblemId } });
|
const res = await api.findProblemById1({ params: { ProblemId } });
|
||||||
description.value = res.data.description; // 更新作业名称
|
description.value = res.data.description; // 更新作业名称
|
||||||
|
adminuserId.value = res.data.adminuserId.toString(); // 更新教师id
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch problem info:", error);
|
console.error("Failed to fetch problem info:", error);
|
||||||
}
|
}
|
||||||
|
|
@ -78,6 +102,10 @@ const getProblemInfo = async () => {
|
||||||
|
|
||||||
// 显示上传弹窗
|
// 显示上传弹窗
|
||||||
const showUploadDialog = () => {
|
const showUploadDialog = () => {
|
||||||
|
if (fileUrls.value.length > 0) {
|
||||||
|
ElMessage.warning('您已经上传了文件,不能再次上传。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
uploadDialogVisible.value = true;
|
uploadDialogVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -89,11 +117,11 @@ const handleFileChange = (file, fileList) => {
|
||||||
// 处理文件上传成功
|
// 处理文件上传成功
|
||||||
const handleUploadSuccess = (response, file, fileList) => {
|
const handleUploadSuccess = (response, file, fileList) => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
ElMessage.success('文件上传成功');
|
|
||||||
// 更新文件URL列表
|
// 更新文件URL列表
|
||||||
fileUrls.value.push({ url: response.urls, name: response.data });
|
fileUrls.value.push({ url: response.urls, name: response.data });
|
||||||
uploadDialogVisible.value = false;
|
uploadDialogVisible.value = false;
|
||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
|
ElMessage.success('文件上传成功');
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error('文件上传失败');
|
ElMessage.error('文件上传失败');
|
||||||
}
|
}
|
||||||
|
|
@ -105,6 +133,11 @@ const handleUploadError = (err, file, fileList) => {
|
||||||
ElMessage.error('文件上传失败');
|
ElMessage.error('文件上传失败');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 处理文件数量超出限制
|
||||||
|
const handleExceed = (files, fileList) => {
|
||||||
|
ElMessage.error('只能上传一个附件');
|
||||||
|
};
|
||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
const uploadFile = async () => {
|
const uploadFile = async () => {
|
||||||
if (fileList.value.length === 0) {
|
if (fileList.value.length === 0) {
|
||||||
|
|
@ -119,38 +152,59 @@ const uploadFile = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await api.uploadFiles(formData); // 调用上传文件的方法
|
const response = await api.uploadFiles(formData); // 调用上传文件的方法
|
||||||
console.log('Response from server:', response); // 打印响应内容
|
console.log('Response from server:', response); // 打印响应内容
|
||||||
if (response.code === 0) {
|
|
||||||
ElMessage.success('文件上传成功');
|
ElMessage.success('文件上传成功');
|
||||||
// 更新文件URL列表
|
// 更新文件URL列表
|
||||||
fileUrls.value.push({ url: response.urls, name: response.data });
|
fileUrls.value.push({ url: response.urls, name: response.data });
|
||||||
uploadDialogVisible.value = false;
|
uploadDialogVisible.value = false;
|
||||||
fileList.value = [];
|
fileList.value = [];
|
||||||
} else {
|
|
||||||
ElMessage.error('文件上传失败1');
|
}catch (error) {
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Failed to upload files:", error);
|
console.error("Failed to upload files:", error);
|
||||||
ElMessage.error('文件上传失败2');
|
ElMessage.error('文件上传失败2');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 下载文件
|
|
||||||
const downloadFile = (url) => {
|
const getSubmitReportInfo = async () => {
|
||||||
const link = document.createElement('a');
|
// 查询已保存的文件信息
|
||||||
link.href = url;
|
try {
|
||||||
link.target = '_blank';
|
const res = await api.getSubmitReport({ params: { examId } });
|
||||||
link.download = url.split('/').pop(); // 提取文件名
|
if (res.data.attachment) {
|
||||||
document.body.appendChild(link);
|
attachment.value = res.data.attachment; // 更新附件信息
|
||||||
link.click();
|
} else {
|
||||||
document.body.removeChild(link);
|
attachment.value = null;
|
||||||
|
}
|
||||||
|
plagiarismStatus.value = res.data.plagiarismStatus; // 更新抄袭状态
|
||||||
|
if(plagiarismStatus.value ==="2") {//疑似抄袭,允许再次提交
|
||||||
|
isReportActionsDisabled.value = false; // 启用ReportActions组件
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (res.data.score !== null && res.data.score !== undefined) {
|
||||||
|
isReportActionsDisabled.value = true; // 禁用ReportActions组件
|
||||||
|
} else {
|
||||||
|
isReportActionsDisabled.value = false; // 启用ReportActions组件
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const refreshAttachmentInfo = async () => {
|
||||||
|
//更新已上传的文件信息
|
||||||
|
await getSubmitReportInfo();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 生命周期钩子
|
// 生命周期钩子
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getProblemInfo(); // 挂载时查询作业信息
|
getProblemInfo(); // 挂载时查询作业信息
|
||||||
|
getSubmitReportInfo();//查询已保存的文件信息
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.card-header {
|
.card-header {
|
||||||
background-color: #f5f5f5; /* 加深灰色背景 */
|
background-color: #f5f5f5; /* 加深灰色背景 */
|
||||||
|
|
@ -187,7 +241,7 @@ onMounted(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-list {
|
.file-list {
|
||||||
margin-top: 20px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-list-title {
|
.file-list-title {
|
||||||
|
|
|
||||||
|
|
@ -1,32 +1,193 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
<n-button type="primary" size="small" @click="onSave">保存</n-button>
|
<n-button type="primary" size="small" @click="onSave" :disabled="props.disabled">保存</n-button>
|
||||||
<n-button type="success" size="small" @click="onSaveAndSubmit">保存并提交</n-button>
|
<n-button type="success" size="small" @click="onSaveAndSubmit" :disabled="props.disabled">保存并提交</n-button>
|
||||||
<n-button type="warning" size="small" @click="onWithdraw">申请撤回</n-button>
|
<n-button type="warning" size="small" @click="onWithdraw" :disabled="props.disabled">撤回提交</n-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import api from '@/api/user';
|
||||||
|
import {ElMessage, ElMessageBox} from "element-plus";
|
||||||
|
import {longRequest} from "@/utils";
|
||||||
|
|
||||||
|
const route = useRoute();
|
||||||
const isClicked = ref(false);
|
const isClicked = ref(false);
|
||||||
|
const ProblemId = route.params.examId;
|
||||||
|
|
||||||
const emit = defineEmits(['clickSave', 'clickSaveAndSubmit', 'clickWithdraw']);
|
const isCheckingPlagiarism = ref(false); // 查重状态
|
||||||
|
|
||||||
const onSave = () => {
|
const props = defineProps({
|
||||||
// TODO: 实现保存逻辑
|
fileUrls: Array,
|
||||||
emit('clickSave');
|
adminuserId: [String],
|
||||||
|
attachment: [String],
|
||||||
|
disabled:Boolean
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits(['clickSave', 'clickSaveAndSubmit', 'clickWithdraw', 'refreshAttachment']);
|
||||||
|
|
||||||
|
const onSave = async () => { //保存
|
||||||
|
// 检查是否有文件信息且数组不为空
|
||||||
|
if (props.fileUrls && props.fileUrls.length > 0) {
|
||||||
|
|
||||||
|
|
||||||
|
// 调用 API 保存提交信息到数据库,包括文件名、题目id,学生id,老师id,
|
||||||
|
try {
|
||||||
|
const attachment = props.fileUrls[0].name;
|
||||||
|
const adminuserId =props.adminuserId;
|
||||||
|
const problemId = ProblemId;
|
||||||
|
const submitReport = {
|
||||||
|
attachment,
|
||||||
|
problemId,
|
||||||
|
adminuserId
|
||||||
|
};
|
||||||
|
const res = await api.saveInfoToProps(submitReport);
|
||||||
|
// 处理成功逻辑
|
||||||
|
emit('clickSave');
|
||||||
|
emit('refreshAttachment');
|
||||||
|
ElMessage.success('保存成功!');
|
||||||
|
} catch (error) {
|
||||||
|
// 处理错误逻辑
|
||||||
|
console.error("Failed to save Files:", error);
|
||||||
|
ElMessage.error('保存文件时发生错误!');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 如果没有文件信息,在这里处理
|
||||||
|
ElMessage.error('尚未上传新的文件!');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onSaveAndSubmit = () => {
|
const onSaveAndSubmit = async () => {//保存并提交
|
||||||
// TODO: 实现保存并提交逻辑
|
let shouldSubmit = false;
|
||||||
emit('clickSaveAndSubmit');
|
|
||||||
|
// 检查是否有新上传的文件
|
||||||
|
const hasNewFiles = props.fileUrls && props.fileUrls.length > 0;
|
||||||
|
|
||||||
|
if (props.attachment && !hasNewFiles) {
|
||||||
|
// 如果attachment不为空且没有新文件,准备提交
|
||||||
|
shouldSubmit = true;
|
||||||
|
} else if (hasNewFiles) {
|
||||||
|
// 如果有新上传的文件,无论attachment是否为空,都先保存新文件
|
||||||
|
await onSave(); // 先调用保存逻辑
|
||||||
|
shouldSubmit = true;
|
||||||
|
} else {
|
||||||
|
ElMessage.error('尚未上传文件!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSubmit) {
|
||||||
|
// 弹出确认提交的对话框
|
||||||
|
ElMessageBox.confirm('确定要提交吗?提交时将以当下已保存的文件为准。', '确认提交', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {//提交逻辑
|
||||||
|
const adminuserId =props.adminuserId;
|
||||||
|
const problemId = ProblemId;
|
||||||
|
const submitReport1 = {
|
||||||
|
problemId,
|
||||||
|
adminuserId
|
||||||
|
};
|
||||||
|
const res = await api.submitInfoToProps(submitReport1);
|
||||||
|
|
||||||
|
// 提交成功后,调用查重函数与自动批阅并后台挂起
|
||||||
|
checkPlagiarismInBackground();
|
||||||
|
autoScoreBackground();
|
||||||
|
emit('clickSaveAndSubmit');
|
||||||
|
emit('refreshAttachment');
|
||||||
|
ElMessage.success('提交成功!正在后台进行查重...');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// 用户取消提交
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const onWithdraw = () => { //撤回提交
|
||||||
|
ElMessageBox.confirm('确定撤回已提交的报告吗?', '确认撤回', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {//撤回逻辑
|
||||||
|
const adminuserId =props.adminuserId;
|
||||||
|
const problemId = ProblemId;
|
||||||
|
const submitReport2 = {
|
||||||
|
problemId,
|
||||||
|
adminuserId
|
||||||
|
};
|
||||||
|
const res = await api.withdrawInfoToProps(submitReport2);
|
||||||
|
emit('clickWithdraw');
|
||||||
|
ElMessage.success('撤回成功!');
|
||||||
|
} catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}).catch(() => {
|
||||||
|
// 用户取消撤回
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onWithdraw = () => {
|
// 查重函数
|
||||||
// TODO: 实现申请撤回逻辑
|
const checkPlagiarismInBackground = async () => {
|
||||||
emit('clickWithdraw');
|
isCheckingPlagiarism.value = true; // 开始查重,更新状态
|
||||||
|
try{
|
||||||
|
// 获取文件名
|
||||||
|
const attachment = props.attachment;
|
||||||
|
const adminuserId =props.adminuserId;
|
||||||
|
const problemId = ProblemId;
|
||||||
|
const submitReport = {
|
||||||
|
adminuserId,
|
||||||
|
problemId,
|
||||||
|
attachment
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调用查重接口,使用永不超时longRequest
|
||||||
|
const res = await longRequest.post('/plagiarism/runPlagiarism', submitReport);
|
||||||
|
console.log('查重结果:', res);
|
||||||
|
|
||||||
|
// 查重完成,更新状态
|
||||||
|
isCheckingPlagiarism.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('查重过程中发生错误!');
|
||||||
|
isCheckingPlagiarism.value = false; // 查重失败,也要更新状态
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 监听查重状态变化,用于通知用户
|
||||||
|
watch(isCheckingPlagiarism, (newValue) => {
|
||||||
|
if (!newValue) {
|
||||||
|
// 查重完成,可以在这里通知用户
|
||||||
|
ElMessage.success('查重操作已完成!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 自动批阅函数
|
||||||
|
const autoScoreBackground = async () => {
|
||||||
|
try{
|
||||||
|
// 获取文件名
|
||||||
|
const attachment = props.attachment;
|
||||||
|
const adminuserId =props.adminuserId;
|
||||||
|
const problemId = ProblemId;
|
||||||
|
const submitReport = {
|
||||||
|
adminuserId,
|
||||||
|
problemId,
|
||||||
|
attachment
|
||||||
|
};
|
||||||
|
|
||||||
|
// 调用自动批阅接口,同样使用永不超时longRequest
|
||||||
|
const res1 = await longRequest.post('/problem/autoscore', submitReport);
|
||||||
|
console.log('查重结果:', res1);
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('自动批阅过程中发生错误!');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
<span class="subtitle">教师评语</span>
|
<span class="subtitle">教师评语</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="description-content">
|
<div class="description-content">
|
||||||
<span v-if="plagiarismStatus === '2'" class="plagiarism-warning">疑似抄袭!!<br></span>
|
|
||||||
<span v-if="comment" class="comment-text">{{ comment }}</span>
|
<span v-if="comment" class="comment-text">{{ comment }}</span>
|
||||||
<span v-else class="no-comment-text">暂无评价</span>
|
<span v-else class="no-comment-text">暂无评价</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -18,6 +17,7 @@
|
||||||
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";
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const examId = route.params.examId;
|
const examId = route.params.examId;
|
||||||
|
|
@ -28,8 +28,14 @@ const getJudgeInfo = async () => {
|
||||||
// 查询批阅相关信息
|
// 查询批阅相关信息
|
||||||
try {
|
try {
|
||||||
const res = await api.getSubmitReport({ params: { examId } });
|
const res = await api.getSubmitReport({ params: { examId } });
|
||||||
comment.value = res.data.comment; // 更新教师评语
|
if(res.data==null){
|
||||||
plagiarismStatus.value = res.data.plagiarismStatus; // 更新抄袭状态
|
ElMessage.warning("尚未提交作业!")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// 更新教师或AI评语,如果教师评语为空,则使用AI评语
|
||||||
|
comment.value = res.data.comment || res.data.autocomment;
|
||||||
|
plagiarismStatus.value = res.data.plagiarismStatus; // 更新抄袭状态
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch problem info:", error);
|
console.error("Failed to fetch problem info:", error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ const queryExamScores = async () => {
|
||||||
params: { examId }
|
params: { examId }
|
||||||
});
|
});
|
||||||
title.value = res.data.title; // 更新作业名称
|
title.value = res.data.title; // 更新作业名称
|
||||||
score.value = res.data.score; // 更新个人得分
|
score.value = res.data.score || res.data.autoscore; // 更新个人得分
|
||||||
rank.value = res.data.rank || "-"; // 更新个人排名,如果rank为空则显示 "-"
|
rank.value = res.data.rank || "-"; // 更新个人排名,如果rank为空则显示 "-"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
50
AES/pom.xml
50
AES/pom.xml
|
|
@ -144,15 +144,12 @@
|
||||||
<scope>system</scope>
|
<scope>system</scope>
|
||||||
<systemPath>${project.basedir}/src/main/WEB-INF/lib/jave-1.0.2.jar</systemPath>
|
<systemPath>${project.basedir}/src/main/WEB-INF/lib/jave-1.0.2.jar</systemPath>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 执行外部命令-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.poi</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>apache-poi</artifactId>
|
<artifactId>commons-exec</artifactId>
|
||||||
<version>2.0.0</version>
|
<version>1.3</version>
|
||||||
<scope>system</scope>
|
|
||||||
<systemPath>${project.basedir}/src/main/WEB-INF/lib/poi-3.6-20091214.jar</systemPath>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
|
|
@ -180,6 +177,45 @@
|
||||||
<version>2.5.29</version>
|
<version>2.5.29</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.huaban</groupId>
|
||||||
|
<artifactId>jieba-analysis</artifactId>
|
||||||
|
<version>1.0.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hankcs</groupId>
|
||||||
|
<artifactId>hanlp</artifactId>
|
||||||
|
<version>portable-1.7.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Apache POI 用于读取 .doc 文件 前后版本保持一致,为4.1.0-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi</artifactId>
|
||||||
|
<version>4.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml</artifactId>
|
||||||
|
<version>4.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-scratchpad</artifactId>
|
||||||
|
<version>4.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Apache PDFBox 用于读取 .pdf 文件 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.pdfbox</groupId>
|
||||||
|
<artifactId>pdfbox</artifactId>
|
||||||
|
<version>2.0.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
package com.example.aes.problem.controller;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.text.BreakIterator;
|
||||||
|
import java.util.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import com.example.aes.global.model.DecodeToken;
|
||||||
|
import com.example.aes.global.model.RespBean;
|
||||||
|
import com.example.aes.problem.model.PMScoringRubric;
|
||||||
|
import com.example.aes.problem.model.PlagiarismResult;
|
||||||
|
import com.example.aes.problem.model.SubmitReport;
|
||||||
|
import com.example.aes.problem.service.PlagiarismServiceI;
|
||||||
|
import com.example.aes.problem.service.ProblemServiceI;
|
||||||
|
import com.hankcs.hanlp.HanLP;
|
||||||
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
|
import com.hankcs.hanlp.tokenizer.IndexTokenizer;
|
||||||
|
|
||||||
|
import org.apache.poi.hwpf.HWPFDocument;
|
||||||
|
import org.apache.poi.hwpf.usermodel.Range;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.text.PDFTextStripper;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/plagiarism")
|
||||||
|
@Transactional
|
||||||
|
public class PlagiarismController {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlagiarismServiceI plagiarismServiceI;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ProblemServiceI problemServiceI;
|
||||||
|
|
||||||
|
@PostMapping("/runPlagiarism")
|
||||||
|
public RespBean runPlagiarism(@RequestBody SubmitReport submitReport, HttpServletRequest request) {
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String UserId = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(UserId);
|
||||||
|
submitReport.setStudentId(userId);
|
||||||
|
// 构建文件路径
|
||||||
|
String uploadDirectory = System.getProperty("user.dir") + File.separator + "upload";
|
||||||
|
Path filePath = Paths.get(uploadDirectory,submitReport.getAttachment());
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (!Files.exists(filePath)) {
|
||||||
|
return RespBean.error("文件不存在");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 调用Service层进行查重
|
||||||
|
PlagiarismResult result = plagiarismServiceI.checkPlagiarism(filePath.toString(), uploadDirectory);
|
||||||
|
|
||||||
|
submitReport.setSimilardocs(result.getArticleName());
|
||||||
|
submitReport.setSimularity(result.getSimilarity());
|
||||||
|
if(result.getSimilarity()>0.3){//如果文章相似度大于0.3,判定为疑似抄袭并保存到数据库中
|
||||||
|
submitReport.setPlagiarismStatus("疑似抄袭");
|
||||||
|
}
|
||||||
|
boolean saveresult = problemServiceI.savePlagiarismResultToProps(submitReport);
|
||||||
|
|
||||||
|
// 返回查重结果
|
||||||
|
if (result != null) {
|
||||||
|
return RespBean.ok("查重成功",saveresult);
|
||||||
|
} else {
|
||||||
|
return RespBean.error("查重失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -6,12 +6,22 @@ import com.example.aes.global.model.RespBean;
|
||||||
import com.example.aes.problem.model.*;
|
import com.example.aes.problem.model.*;
|
||||||
import com.example.aes.problem.model.DataGrid;
|
import com.example.aes.problem.model.DataGrid;
|
||||||
import com.example.aes.problem.service.ProblemServiceI;
|
import com.example.aes.problem.service.ProblemServiceI;
|
||||||
|
import com.example.aes.user.model.Classes;
|
||||||
import com.example.aes.user.model.Classstudents;
|
import com.example.aes.user.model.Classstudents;
|
||||||
|
import com.example.aes.user.model.PMUser;
|
||||||
import com.example.aes.user.service.ClassesServiceI;
|
import com.example.aes.user.service.ClassesServiceI;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
@ -297,7 +307,7 @@ public class ProblemController {
|
||||||
//根据班级id查询所有作业
|
//根据班级id查询所有作业
|
||||||
List<PMProblem> pMproblems = problemServiceI.getProblemsByClassIds(classIds);
|
List<PMProblem> pMproblems = problemServiceI.getProblemsByClassIds(classIds);
|
||||||
|
|
||||||
// 根据学生ID和作业列表查询提交报告的状态,分为提交状态和查重状态,并更新到pmproblem中
|
// 根据学生ID和作业列表查询提交报告的状态,分为提交状态和查重状态,并更新到pMproblems中
|
||||||
problemServiceI.findStatusByStudentIdAndProblems(Integer.parseInt(userId), pMproblems);
|
problemServiceI.findStatusByStudentIdAndProblems(Integer.parseInt(userId), pMproblems);
|
||||||
|
|
||||||
//分页处理
|
//分页处理
|
||||||
|
|
@ -382,7 +392,7 @@ public class ProblemController {
|
||||||
UReportSubmitted ureportsubmitted =
|
UReportSubmitted ureportsubmitted =
|
||||||
problemServiceI.findScoreAndRankByIds(examId, userId);
|
problemServiceI.findScoreAndRankByIds(examId, userId);
|
||||||
if (ureportsubmitted != null) {
|
if (ureportsubmitted != null) {
|
||||||
return RespBean.ok("查询成绩排名成功!", ureportsubmitted);
|
return RespBean.ok("查询作业信息成功!", ureportsubmitted);
|
||||||
} else {
|
} else {
|
||||||
return RespBean.ok("尚未提交作业!");
|
return RespBean.ok("尚未提交作业!");
|
||||||
}
|
}
|
||||||
|
|
@ -411,4 +421,159 @@ public class ProblemController {
|
||||||
return RespBean.error("获取教师布置实验具体信息失败!");
|
return RespBean.error("获取教师布置实验具体信息失败!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
//学生保存报告
|
||||||
|
@PostMapping("/saveInfoToProps")
|
||||||
|
public RespBean saveInfoToProps(@RequestBody SubmitReport submitReport,HttpServletRequest request) {
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String UserId = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(UserId);
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
|
||||||
|
submitReport.setStudentId(userId);
|
||||||
|
if(problemServiceI.findReportSubmitted(submitReport)){//如果之前保存过数据,更新数据
|
||||||
|
submitReport.setSubmissionTime(now);
|
||||||
|
boolean result = problemServiceI.updateSubmitInfoToProps(submitReport);
|
||||||
|
if (result) {
|
||||||
|
return RespBean.ok("信息更新成功");
|
||||||
|
} else {
|
||||||
|
return RespBean.error("信息更新失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //新生成一条数据
|
||||||
|
submitReport.setPlagiarismStatus("未查重");//查重状态默认为未查重
|
||||||
|
submitReport.setSubmissionStatus("未提交");//提交状态在保存时设置为未提交
|
||||||
|
submitReport.setSubmissionTime(now);
|
||||||
|
boolean result = problemServiceI.saveSubmitInfoToProps(submitReport);
|
||||||
|
if (result) {
|
||||||
|
return RespBean.ok("信息添加成功");
|
||||||
|
} else {
|
||||||
|
return RespBean.error("信息添加失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//学生提交报告
|
||||||
|
@PostMapping("/submitInfoToProps")
|
||||||
|
public RespBean submitInfoToProps(@RequestBody SubmitReport submitReport,HttpServletRequest request) {
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String UserId = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(UserId);
|
||||||
|
submitReport.setStudentId(userId);
|
||||||
|
|
||||||
|
if (problemServiceI.findReportSubmitted(submitReport)) {
|
||||||
|
String submissionStatus=problemServiceI.findReportSubmittedStatus(submitReport);
|
||||||
|
if(submissionStatus.equals("已提交")){
|
||||||
|
return RespBean.error("请勿重复提交!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
boolean result = problemServiceI.updateSubmitInfoForSubmission(submitReport);
|
||||||
|
if (result) {
|
||||||
|
return RespBean.ok("提交信息更新成功");
|
||||||
|
} else {
|
||||||
|
return RespBean.error("提交信息更新失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return RespBean.error("未找到该学生提交信息!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//学生撤回报告
|
||||||
|
@PostMapping("/withdrawInfoToProps")
|
||||||
|
public RespBean withdrawInfoToProps(@RequestBody SubmitReport submitReport,HttpServletRequest request) {
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String UserId = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(UserId);
|
||||||
|
submitReport.setStudentId(userId);
|
||||||
|
if (problemServiceI.findReportSubmitted(submitReport)) {
|
||||||
|
String submissionstatus=problemServiceI.findReportSubmittedStatus(submitReport);
|
||||||
|
if(submissionstatus.equals("已撤回")){
|
||||||
|
return RespBean.error("实验报告已撤回!");
|
||||||
|
}
|
||||||
|
else if(submissionstatus.equals("未提交")){
|
||||||
|
return RespBean.error("尚未提交实验报告!");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
boolean result = problemServiceI.withdrawSubmitInfo(submitReport);
|
||||||
|
if (result) {
|
||||||
|
return RespBean.ok("撤回信息更新成功");
|
||||||
|
} else {
|
||||||
|
return RespBean.error("撤回信息更新失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return RespBean.error("未找到该学生提交信息!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//学生领取作业
|
||||||
|
@PostMapping("/pickExam")
|
||||||
|
public RespBean pickExam(@RequestBody SubmitReport submitReport,HttpServletRequest request) {
|
||||||
|
// if (problemServiceI.findReportSubmitted(submitReport)) {//如果数据库中已有数据,说明已经领取
|
||||||
|
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String UserId = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(UserId);
|
||||||
|
Classes classes=classesServiceI.findClassById(submitReport.getAdminuserId());//这里存放的还是classid
|
||||||
|
int AdminuserId=classes.getTeacherId();
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
submitReport.setStudentId(userId);
|
||||||
|
submitReport.setAdminuserId(AdminuserId);
|
||||||
|
submitReport.setSubmissionStatus("已领取");
|
||||||
|
submitReport.setReadTime(now);
|
||||||
|
|
||||||
|
|
||||||
|
boolean result = problemServiceI.saveSubmitInfoToProps(submitReport);//直接调用保存逻辑
|
||||||
|
if (result) {
|
||||||
|
return RespBean.ok("领取成功");
|
||||||
|
} else {
|
||||||
|
return RespBean.error("领取失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//自动批改作业返回分数
|
||||||
|
@PostMapping("/autoscore")
|
||||||
|
public RespBean autoscore(@RequestBody SubmitReport submitReport, HttpServletRequest request) {
|
||||||
|
DecodeToken decodeToken = new DecodeToken(request);
|
||||||
|
String userIdStr = decodeToken.getUserId();
|
||||||
|
int userId = Integer.parseInt(userIdStr);
|
||||||
|
submitReport.setStudentId(userId);
|
||||||
|
|
||||||
|
// 构建文件路径
|
||||||
|
String uploadDirectory = System.getProperty("user.dir") + File.separator + "upload";
|
||||||
|
Path filePath = Paths.get(uploadDirectory, submitReport.getAttachment());
|
||||||
|
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (!Files.exists(filePath)) {
|
||||||
|
return RespBean.error("文件不存在");
|
||||||
|
}
|
||||||
|
// 调用Service层进行批改
|
||||||
|
AutoScoreResult autoScoreResult =new AutoScoreResult();
|
||||||
|
autoScoreResult.setTotalScore(-1.0);
|
||||||
|
// 调用Service层进行批改
|
||||||
|
autoScoreResult = problemServiceI.getAutoScore(filePath, submitReport.getProblemId());
|
||||||
|
//自动批阅结果存数据库
|
||||||
|
Float autoScore =(float) autoScoreResult.getTotalScore();
|
||||||
|
submitReport.setAutoscore(autoScore);
|
||||||
|
// 将所有的评语合并为一句,中间用分号隔开
|
||||||
|
List<String> remarks = autoScoreResult.getRemarks();
|
||||||
|
String combinedRemarks = String.join("; ", remarks);
|
||||||
|
submitReport.setAutocomment(combinedRemarks);
|
||||||
|
|
||||||
|
boolean saveresult = problemServiceI.saveAutoScoreResultToProps(submitReport);
|
||||||
|
|
||||||
|
if(saveresult) {
|
||||||
|
return RespBean.ok("批改完成,已保存数据!");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
return RespBean.error("批改过程中发生错误!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,14 @@ public interface SubmitReportDaoI extends BaseDaoI<SubmitReport> {
|
||||||
public List<SubmitReport> findSimilardocs(PMStudentSubmit pmStudentSubmit);
|
public List<SubmitReport> findSimilardocs(PMStudentSubmit pmStudentSubmit);
|
||||||
public List<Integer> findNextId(int problemId);
|
public List<Integer> findNextId(int problemId);
|
||||||
|
|
||||||
|
|
||||||
|
public boolean saveSubmitInfo(SubmitReport submitReport);
|
||||||
|
public boolean getReportSubmitted(SubmitReport submitReport);
|
||||||
|
public boolean updateReportSubmitted(SubmitReport submitReport);
|
||||||
|
public boolean updateReportSubmittedForSubmission(SubmitReport submitReport);
|
||||||
|
public boolean withdrawReportSubmitted(SubmitReport submitReport);
|
||||||
|
public String getReportSubmittedStatus(SubmitReport submitReport);
|
||||||
|
public boolean savePlagiarismResult(SubmitReport submitReport);
|
||||||
|
public boolean saveAutoScoreResult(SubmitReport submitReport);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import com.example.aes.problem.model.SubmitReport;
|
||||||
import com.example.aes.user.dao.impl.BaseDaoImpl;
|
import com.example.aes.user.dao.impl.BaseDaoImpl;
|
||||||
import com.example.aes.user.model.Course;
|
import com.example.aes.user.model.Course;
|
||||||
import org.hibernate.Query;
|
import org.hibernate.Query;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
|
@ -17,24 +19,29 @@ import java.util.List;
|
||||||
@Repository("SubmitReportDao")
|
@Repository("SubmitReportDao")
|
||||||
public class SubmitReportDaoImpl extends BaseDaoImpl<SubmitReport> implements SubmitReportDaoI {
|
public class SubmitReportDaoImpl extends BaseDaoImpl<SubmitReport> implements SubmitReportDaoI {
|
||||||
@Override
|
@Override
|
||||||
public List<Object[]> findWeijiaoList(PMStudentSubmit pmStudentSubmit){
|
public List<Object[]> findWeijiaoList(PMStudentSubmit pmStudentSubmit) {
|
||||||
int classId= pmStudentSubmit.getClassId();
|
int classId = pmStudentSubmit.getClassId();
|
||||||
int problemId= pmStudentSubmit.getProblemId();
|
int problemId = pmStudentSubmit.getProblemId();
|
||||||
String studentNo=
|
String studentNo =
|
||||||
'%'+pmStudentSubmit.getStudentNo()+'%';
|
'%' + pmStudentSubmit.getStudentNo() + '%';
|
||||||
String chineseName=
|
String chineseName =
|
||||||
'%'+pmStudentSubmit.getChineseName()+'%';
|
'%' + pmStudentSubmit.getChineseName() + '%';
|
||||||
String hql="SELECT u.chineseName," +
|
String hql = "SELECT u.chineseName," +
|
||||||
"u.studentNo, sr" +
|
"u.studentNo, sr" +
|
||||||
".readTime," +
|
".readTime," +
|
||||||
"sr.submissionStatus,u.id " +
|
"sr.submissionStatus,u.id " +
|
||||||
"FROM Classstudents cs left " +
|
"FROM Classstudents cs left " +
|
||||||
"join Users u on cs" +
|
"join Users u on cs" +
|
||||||
".userId=u.id "+
|
".userId=u.id " +
|
||||||
"left join PostProblem pp on cs" +
|
"left join PostProblem pp on cs" +
|
||||||
".classId=pp.classId "+
|
".classId=pp.classId "+
|
||||||
"left JOIN"+
|
"left JOIN"+
|
||||||
" SubmitReport sr on (sr.problemId = pp.problemId and sr.studentId=u.id)"+
|
" SubmitReport sr on (sr.problemId = pp.problemId and sr.studentId=u.id)"+
|
||||||
|
".classId=pp.classId " +
|
||||||
|
"left JOIN" +
|
||||||
|
" SubmitReport sr ON " +
|
||||||
|
"sr" +
|
||||||
|
".studentId=u.id" +
|
||||||
" WHERE cs.classId=:classId " +
|
" WHERE cs.classId=:classId " +
|
||||||
"and " +
|
"and " +
|
||||||
"pp.problemId " +
|
"pp.problemId " +
|
||||||
|
|
@ -47,14 +54,14 @@ String chineseName=
|
||||||
"and u" +
|
"and u" +
|
||||||
".chineseName like :chineseName";
|
".chineseName like :chineseName";
|
||||||
Query<Object[]> query =
|
Query<Object[]> query =
|
||||||
this.getCurrentSession().createQuery(hql,Object[].class);
|
this.getCurrentSession().createQuery(hql, Object[].class);
|
||||||
query.setParameter("classId", classId);
|
query.setParameter("classId", classId);
|
||||||
query.setParameter("problemId", problemId);
|
query.setParameter("problemId", problemId);
|
||||||
query.setParameter("studentNo",studentNo);
|
query.setParameter("studentNo", studentNo);
|
||||||
query.setParameter("chineseName",
|
query.setParameter("chineseName",
|
||||||
chineseName);
|
chineseName);
|
||||||
int page= pmStudentSubmit.getPageNum();
|
int page = pmStudentSubmit.getPageNum();
|
||||||
int rows= pmStudentSubmit.getPageSize();
|
int rows = pmStudentSubmit.getPageSize();
|
||||||
// 设置分页
|
// 设置分页
|
||||||
query.setFirstResult((page - 1) * rows); // 计算起始行
|
query.setFirstResult((page - 1) * rows); // 计算起始行
|
||||||
query.setMaxResults(rows); // 设置每页行数
|
query.setMaxResults(rows); // 设置每页行数
|
||||||
|
|
@ -95,11 +102,11 @@ String chineseName=
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public int editScoreAndComment(PMReviewMessage pmReviewMessage){
|
public int editScoreAndComment(PMReviewMessage pmReviewMessage) {
|
||||||
Float score= pmReviewMessage.getScore();
|
Float score = pmReviewMessage.getScore();
|
||||||
String comment=
|
String comment =
|
||||||
pmReviewMessage.getComment();
|
pmReviewMessage.getComment();
|
||||||
String hql= "UPDATE SubmitReport sr SET" +
|
String hql = "UPDATE SubmitReport sr SET" +
|
||||||
" sr.score= :score,sr" +
|
" sr.score= :score,sr" +
|
||||||
".comment=:comment,sr" +
|
".comment=:comment,sr" +
|
||||||
".submissionStatus='已批阅' "
|
".submissionStatus='已批阅' "
|
||||||
|
|
@ -107,8 +114,8 @@ String chineseName=
|
||||||
":problemId" +
|
":problemId" +
|
||||||
" AND sr.studentId= :studentId";
|
" AND sr.studentId= :studentId";
|
||||||
Query q = this.getCurrentSession().createQuery(hql);
|
Query q = this.getCurrentSession().createQuery(hql);
|
||||||
q.setParameter("score",score);
|
q.setParameter("score", score);
|
||||||
q.setParameter("comment",comment);
|
q.setParameter("comment", comment);
|
||||||
q.setParameter("problemId",
|
q.setParameter("problemId",
|
||||||
pmReviewMessage.getProblemId());
|
pmReviewMessage.getProblemId());
|
||||||
q.setParameter("studentId",
|
q.setParameter("studentId",
|
||||||
|
|
@ -116,9 +123,10 @@ String chineseName=
|
||||||
int num = q.executeUpdate();
|
int num = q.executeUpdate();
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int redoReport(PMReviewMessage pmReviewMessage){
|
public int redoReport(PMReviewMessage pmReviewMessage) {
|
||||||
String hql= "UPDATE SubmitReport sr set" +
|
String hql = "UPDATE SubmitReport sr set" +
|
||||||
" sr.submissionStatus='已领取'," +
|
" sr.submissionStatus='已领取'," +
|
||||||
"sr.submissionTime=null " +
|
"sr.submissionTime=null " +
|
||||||
"WHERE sr.problemId = " +
|
"WHERE sr.problemId = " +
|
||||||
|
|
@ -132,15 +140,16 @@ String chineseName=
|
||||||
int num = q.executeUpdate();
|
int num = q.executeUpdate();
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Object[]> findYijiaoList(PMStudentSubmit pmStudentSubmit){
|
public List<Object[]> findYijiaoList(PMStudentSubmit pmStudentSubmit) {
|
||||||
int classId= pmStudentSubmit.getClassId();
|
int classId = pmStudentSubmit.getClassId();
|
||||||
int problemId= pmStudentSubmit.getProblemId();
|
int problemId = pmStudentSubmit.getProblemId();
|
||||||
String studentNo=
|
String studentNo =
|
||||||
'%'+pmStudentSubmit.getStudentNo()+'%';
|
'%' + pmStudentSubmit.getStudentNo() + '%';
|
||||||
String chineseName=
|
String chineseName =
|
||||||
'%'+pmStudentSubmit.getChineseName()+'%';
|
'%' + pmStudentSubmit.getChineseName() + '%';
|
||||||
String hql="SELECT u.chineseName," +
|
String hql = "SELECT u.chineseName," +
|
||||||
"u.studentNo, sr" +
|
"u.studentNo, sr" +
|
||||||
".submissionTime," +
|
".submissionTime," +
|
||||||
"sr.submissionStatus," +
|
"sr.submissionStatus," +
|
||||||
|
|
@ -150,7 +159,7 @@ String chineseName=
|
||||||
".simularity,sr.similardocs " +
|
".simularity,sr.similardocs " +
|
||||||
"FROM Classstudents cs left " +
|
"FROM Classstudents cs left " +
|
||||||
"join Users u on cs" +
|
"join Users u on cs" +
|
||||||
".userId=u.id "+
|
".userId=u.id " +
|
||||||
"left join PostProblem pp on cs" +
|
"left join PostProblem pp on cs" +
|
||||||
".classId=pp.classId "+
|
".classId=pp.classId "+
|
||||||
"left JOIN"+
|
"left JOIN"+
|
||||||
|
|
@ -168,20 +177,21 @@ String chineseName=
|
||||||
"and u" +
|
"and u" +
|
||||||
".chineseName like :chineseName";
|
".chineseName like :chineseName";
|
||||||
Query<Object[]> query =
|
Query<Object[]> query =
|
||||||
this.getCurrentSession().createQuery(hql,Object[].class);
|
this.getCurrentSession().createQuery(hql, Object[].class);
|
||||||
query.setParameter("classId", classId);
|
query.setParameter("classId", classId);
|
||||||
query.setParameter("problemId", problemId);
|
query.setParameter("problemId", problemId);
|
||||||
query.setParameter("studentNo",studentNo);
|
query.setParameter("studentNo", studentNo);
|
||||||
query.setParameter("chineseName",
|
query.setParameter("chineseName",
|
||||||
chineseName);
|
chineseName);
|
||||||
int page= pmStudentSubmit.getPageNum();
|
int page = pmStudentSubmit.getPageNum();
|
||||||
int rows= pmStudentSubmit.getPageSize();
|
int rows = pmStudentSubmit.getPageSize();
|
||||||
// 设置分页
|
// 设置分页
|
||||||
query.setFirstResult((page - 1) * rows); // 计算起始行
|
query.setFirstResult((page - 1) * rows); // 计算起始行
|
||||||
query.setMaxResults(rows); // 设置每页行数
|
query.setMaxResults(rows); // 设置每页行数
|
||||||
|
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Object[]> findScoreList(PMStudentSubmit pmStudentSubmit){
|
public List<Object[]> findScoreList(PMStudentSubmit pmStudentSubmit){
|
||||||
int classId= pmStudentSubmit.getClassId();
|
int classId= pmStudentSubmit.getClassId();
|
||||||
|
|
@ -195,10 +205,10 @@ String chineseName=
|
||||||
"AS finalScore ,u.id " +
|
"AS finalScore ,u.id " +
|
||||||
"FROM Classstudents cs left " +
|
"FROM Classstudents cs left " +
|
||||||
"join Users u on cs" +
|
"join Users u on cs" +
|
||||||
".userId=u.id "+
|
".userId=u.id " +
|
||||||
"left join PostProblem pp on cs" +
|
"left join PostProblem pp on cs" +
|
||||||
".classId=pp.classId "+
|
".classId=pp.classId " +
|
||||||
"left JOIN"+
|
"left JOIN" +
|
||||||
" SubmitReport sr on (sr" +
|
" SubmitReport sr on (sr" +
|
||||||
".problemId = pp.problemId and sr.studentId=u.id)"+
|
".problemId = pp.problemId and sr.studentId=u.id)"+
|
||||||
" WHERE cs.classId=:classId " +
|
" WHERE cs.classId=:classId " +
|
||||||
|
|
@ -209,7 +219,7 @@ String chineseName=
|
||||||
" and sr" +
|
" and sr" +
|
||||||
".submissionTime is not null";
|
".submissionTime is not null";
|
||||||
Query<Object[]> query =
|
Query<Object[]> query =
|
||||||
this.getCurrentSession().createQuery(hql,Object[].class);
|
this.getCurrentSession().createQuery(hql, Object[].class);
|
||||||
query.setParameter("classId", classId);
|
query.setParameter("classId", classId);
|
||||||
query.setParameter("problemId", problemId);
|
query.setParameter("problemId", problemId);
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
|
|
@ -241,14 +251,15 @@ String chineseName=
|
||||||
" " +
|
" " +
|
||||||
"p.id=:problemId";
|
"p.id=:problemId";
|
||||||
Query<Object[]> query =
|
Query<Object[]> query =
|
||||||
this.getCurrentSession().createQuery(hql,Object[].class);
|
this.getCurrentSession().createQuery(hql, Object[].class);
|
||||||
query.setParameter("studentId", studentId);
|
query.setParameter("studentId", studentId);
|
||||||
query.setParameter("problemId", problemId);
|
query.setParameter("problemId", problemId);
|
||||||
return query.getResultList();
|
return query.getResultList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Integer> findNextId(int problemId){
|
public List<Integer> findNextId(int problemId) {
|
||||||
String hql="SELECT " +
|
String hql = "SELECT " +
|
||||||
"sr.studentId " +
|
"sr.studentId " +
|
||||||
"FROM Users u " +
|
"FROM Users u " +
|
||||||
"INNER JOIN " +
|
"INNER JOIN " +
|
||||||
|
|
@ -265,4 +276,180 @@ String chineseName=
|
||||||
q.setParameter("problemId", problemId);
|
q.setParameter("problemId", problemId);
|
||||||
return q.list();
|
return q.list();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public boolean saveSubmitInfo(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
try {
|
||||||
|
session.save(submitReport);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getReportSubmitted(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
boolean isSubmitted = false;
|
||||||
|
try {
|
||||||
|
// 构建查询语句 可能报错但不影响
|
||||||
|
String hql = "FROM SubmitReport WHERE problemId = :problemId AND studentId = :studentId AND adminuserId = :adminuserId";
|
||||||
|
|
||||||
|
Query<SubmitReport> query = session.createQuery(hql, SubmitReport.class);
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
SubmitReport result = query.uniqueResult();
|
||||||
|
isSubmitted = (result != null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return isSubmitted;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateReportSubmitted(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
try {
|
||||||
|
|
||||||
|
//只更新submissionTime和attachment
|
||||||
|
String hql = "UPDATE SubmitReport SET submissionTime = :submissionTime, attachment = :attachment " +
|
||||||
|
"WHERE problemId = :problemId AND adminuserId = :adminuserId AND studentId = :studentId";
|
||||||
|
|
||||||
|
Query query = session.createQuery(hql);
|
||||||
|
|
||||||
|
query.setParameter("submissionTime", submitReport.getSubmissionTime());
|
||||||
|
query.setParameter("attachment", submitReport.getAttachment());
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
|
||||||
|
int result = query.executeUpdate();
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateReportSubmittedForSubmission(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
try {
|
||||||
|
|
||||||
|
String hql = "UPDATE SubmitReport SET submissionStatus = '已提交' " +
|
||||||
|
"WHERE problemId = :problemId " +
|
||||||
|
"AND adminuserId = :adminuserId " +
|
||||||
|
"AND studentId = :studentId";
|
||||||
|
|
||||||
|
Query query = session.createQuery(hql);
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
|
||||||
|
int result = query.executeUpdate();
|
||||||
|
return result > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean withdrawReportSubmitted(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
try {
|
||||||
|
|
||||||
|
String hql = "UPDATE SubmitReport SET submissionStatus = '已撤回' " +
|
||||||
|
"WHERE problemId = :problemId " +
|
||||||
|
"AND adminuserId = :adminuserId " +
|
||||||
|
"AND studentId = :studentId";
|
||||||
|
|
||||||
|
Query query = session.createQuery(hql);
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
|
||||||
|
int result = query.executeUpdate();
|
||||||
|
return result > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getReportSubmittedStatus(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
String submissionStatus = null; // 默认为 null,表示没有找到状态或发生错误
|
||||||
|
try {
|
||||||
|
// 构建查询语句
|
||||||
|
String hql = "SELECT submissionStatus FROM SubmitReport WHERE problemId = :problemId AND studentId = :studentId AND adminuserId = :adminuserId";
|
||||||
|
|
||||||
|
Query<String> query = session.createQuery(hql, String.class);
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
|
||||||
|
submissionStatus = query.uniqueResult();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return submissionStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean savePlagiarismResult(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
try {
|
||||||
|
String hql = "UPDATE SubmitReport SET plagiarismStatus = :plagiarismStatus, " +
|
||||||
|
"simularity = :simularity, " +
|
||||||
|
"similardocs = :similardocs " +
|
||||||
|
"WHERE problemId = :problemId " +
|
||||||
|
"AND adminuserId = :adminuserId " +
|
||||||
|
"AND studentId = :studentId";
|
||||||
|
|
||||||
|
Query query = session.createQuery(hql);
|
||||||
|
query.setParameter("plagiarismStatus", submitReport.getPlagiarismStatus());
|
||||||
|
query.setParameter("simularity", submitReport.getSimularity());
|
||||||
|
query.setParameter("similardocs", submitReport.getSimilardocs());
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
|
||||||
|
int result = query.executeUpdate();
|
||||||
|
return result > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveAutoScoreResult(SubmitReport submitReport) {
|
||||||
|
Session session = this.getCurrentSession();
|
||||||
|
try {
|
||||||
|
String hql = "UPDATE SubmitReport SET autoscore = :autoscore, " +
|
||||||
|
"autocomment = :autocomment " +
|
||||||
|
"WHERE problemId = :problemId " +
|
||||||
|
"AND adminuserId = :adminuserId " +
|
||||||
|
"AND studentId = :studentId";
|
||||||
|
|
||||||
|
Query query = session.createQuery(hql);
|
||||||
|
query.setParameter("autoscore", submitReport.getAutoscore());
|
||||||
|
query.setParameter("autocomment", submitReport.getAutocomment());
|
||||||
|
query.setParameter("problemId", submitReport.getProblemId());
|
||||||
|
query.setParameter("adminuserId", submitReport.getAdminuserId());
|
||||||
|
query.setParameter("studentId", submitReport.getStudentId());
|
||||||
|
|
||||||
|
int result = query.executeUpdate();
|
||||||
|
return result > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.example.aes.problem.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AutoScoreResult {
|
||||||
|
private double totalScore;
|
||||||
|
private List<String> remarks;
|
||||||
|
|
||||||
|
public AutoScoreResult(double totalScore, List<String> remarks) {
|
||||||
|
this.totalScore = totalScore;
|
||||||
|
this.remarks = remarks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AutoScoreResult() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,6 @@ public class PMProblem extends Problem implements java.io.Serializable{//继承P
|
||||||
private String submissionStatus;//提交状态,来自submitproblem
|
private String submissionStatus;//提交状态,来自submitproblem
|
||||||
private LocalDateTime startTime;//开始时间,来自postproblem
|
private LocalDateTime startTime;//开始时间,来自postproblem
|
||||||
private LocalDateTime endTime;//结束时间
|
private LocalDateTime endTime;//结束时间
|
||||||
private String submissonStatus;//提交状态,来自submitproblem
|
|
||||||
private String plagiarismStatus;//查重状态
|
private String plagiarismStatus;//查重状态
|
||||||
private float score;//最终分数
|
private float score;//最终分数
|
||||||
private String status;//最后在页面显示的状态,取决于上面三个参数。
|
private String status;//最后在页面显示的状态,取决于上面三个参数。
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.example.aes.problem.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class PlagiarismResult {//用于存放查重算法的结果(最大值)
|
||||||
|
|
||||||
|
private String articleName;
|
||||||
|
private Float similarity;
|
||||||
|
|
||||||
|
public PlagiarismResult(String articleName, Float similarity) {
|
||||||
|
this.articleName = articleName;
|
||||||
|
this.similarity = similarity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,9 +39,8 @@ public class SubmitReport {
|
||||||
private String comment;
|
private String comment;
|
||||||
@Column(name = "addTime")
|
@Column(name = "addTime")
|
||||||
private LocalDateTime addTime;
|
private LocalDateTime addTime;
|
||||||
@Column(name="simularity")
|
@Column(name = "simularity")
|
||||||
private float simularity;
|
private Float simularity;
|
||||||
@Column(name = "similardocs")
|
@Column(name = "similardocs")
|
||||||
private String similardocs;
|
private String similardocs;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,382 @@
|
||||||
|
package com.example.aes.problem.service.Impl;
|
||||||
|
|
||||||
|
import com.example.aes.problem.dao.ProblemDaoI;
|
||||||
|
import com.example.aes.problem.model.PlagiarismResult;
|
||||||
|
import com.example.aes.problem.service.PlagiarismServiceI;
|
||||||
|
import com.hankcs.hanlp.HanLP;
|
||||||
|
import com.hankcs.hanlp.seg.common.Term;
|
||||||
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
||||||
|
import org.apache.pdfbox.text.PDFTextStripper;
|
||||||
|
import org.apache.poi.hwpf.HWPFDocument;
|
||||||
|
import org.apache.poi.hwpf.usermodel.Range;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFDocument;
|
||||||
|
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class PlagiarismServiceImpl implements PlagiarismServiceI {
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlagiarismResult checkPlagiarism(String fileName, String uploadDirectory) {
|
||||||
|
|
||||||
|
// 构建文件路径
|
||||||
|
Path filePath = Paths.get(fileName);
|
||||||
|
|
||||||
|
// 读取上传的文件内容
|
||||||
|
String article1 = readFile(filePath.toString());
|
||||||
|
|
||||||
|
// 读取upload目录下的所有文件
|
||||||
|
List<Path> filePaths = listFilesInDirectory(uploadDirectory);
|
||||||
|
|
||||||
|
Float highestSimilarity = (float)0.0;
|
||||||
|
String similarFileName = "";
|
||||||
|
|
||||||
|
// 遍历每个文件
|
||||||
|
for (Path path : filePaths) {
|
||||||
|
if (!path.equals(filePath)) {//除了原本的文件
|
||||||
|
String article2 = readFile(path.toString());
|
||||||
|
|
||||||
|
// 分别对两篇文章进行断句
|
||||||
|
List<String> sentences1 = splitIntoSentences(article1);
|
||||||
|
List<String> sentences2 = splitIntoSentences(article2);
|
||||||
|
|
||||||
|
double totalSimilarityChars = 0.0; // 疑似抄袭的句子字符总数
|
||||||
|
int totalChars = 0; // 被测文本中的总字符数
|
||||||
|
|
||||||
|
// // 使用余弦相似度方法对每对句子进行查重比对
|
||||||
|
// for (String sentence1 : sentences1) {
|
||||||
|
// double maxSimilarity = 0.0;
|
||||||
|
// String mostSimilarSentence = "";
|
||||||
|
// for (String sentence2 : sentences2) {
|
||||||
|
// double similarity = calculateSentenceSimilarity1(sentence1, sentence2); // 使用余弦相似度计算方法
|
||||||
|
// if (similarity > maxSimilarity) {
|
||||||
|
// maxSimilarity = similarity;
|
||||||
|
// mostSimilarSentence = sentence2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// // 重复率高的句子
|
||||||
|
// if (maxSimilarity > 0.5) { // 假设阈值为0.5
|
||||||
|
// totalSimilarityChars += sentence1.length(); // 累加疑似抄袭句子的字符数
|
||||||
|
// }
|
||||||
|
// totalChars += sentence1.length(); // 累加文本1中的字符数
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 输出文本的相似度
|
||||||
|
// // 确保totalChars不为0,避免除以0的情况
|
||||||
|
// if (totalChars > 0) {
|
||||||
|
// System.out.printf("文章编码:%d,疑似抄袭句总相似度(疑似抄袭句在被检测文本占比):%.2f%%%n", i + 1, (totalSimilarityChars / totalChars) * 100);
|
||||||
|
// } else {
|
||||||
|
// System.out.println("文章编码:" + (i + 1) + " 被检测文本为空。");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
// 使用 Jaccard 相似度计算方法对每对句子进行查重比对
|
||||||
|
for (String sentence1 : sentences1) {
|
||||||
|
double maxSimilarity = 0.0;
|
||||||
|
String mostSimilarSentence = "";
|
||||||
|
for (String sentence2 : sentences2) {
|
||||||
|
double similarity = calculateSentenceSimilarity2(sentence1, sentence2);//使用Jaccards相似度计算方法
|
||||||
|
if (similarity > maxSimilarity) {
|
||||||
|
maxSimilarity = similarity;
|
||||||
|
mostSimilarSentence = sentence2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 输出重复率高的句子
|
||||||
|
if (maxSimilarity > 0.5) { // 假设阈值为0.5
|
||||||
|
// System.out.println("被检测文段中疑似抄袭句:");
|
||||||
|
// System.out.println(sentence1);
|
||||||
|
// System.out.println("原文相似句:");
|
||||||
|
// System.out.println(mostSimilarSentence);
|
||||||
|
// System.out.println("该句词语jaccards相似度:" + maxSimilarity);
|
||||||
|
totalSimilarityChars += sentence1.length(); // 累加疑似抄袭句子的字符数
|
||||||
|
}
|
||||||
|
totalChars += sentence1.length(); // 累加文本1中的字符数
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算整体相似度
|
||||||
|
Float similarity = (float)totalSimilarityChars / totalChars;
|
||||||
|
if (similarity > highestSimilarity) {
|
||||||
|
highestSimilarity = similarity;
|
||||||
|
similarFileName = path.getFileName().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new PlagiarismResult(similarFileName,highestSimilarity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************///读取文件部分
|
||||||
|
// 列出指定文件夹中的所有文件
|
||||||
|
public List<Path> listFilesInDirectory(String directoryPath) {
|
||||||
|
try (Stream<Path> paths = Files.walk(Paths.get(directoryPath))) {
|
||||||
|
return paths.filter(Files::isRegularFile).collect(Collectors.toList());
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 读取文件内容,支持 .txt, .doc, .pdf 文件,并作空白字符清理
|
||||||
|
public String readFile(String filePath) {
|
||||||
|
String fileExtension = getFileExtension(filePath).toLowerCase();
|
||||||
|
String content = "";
|
||||||
|
|
||||||
|
if (fileExtension.equals("txt")) {
|
||||||
|
content = cleanText(readTextFile(filePath));
|
||||||
|
} else if (fileExtension.equals("doc")||fileExtension.equals("docx")) {
|
||||||
|
content = cleanText(readDocFile(filePath));
|
||||||
|
} else if (fileExtension.equals("pdf")) {
|
||||||
|
content = cleanText(readPdfFile(filePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
public String readFileWithoutClean(String filePath) {
|
||||||
|
String fileExtension = getFileExtension(filePath).toLowerCase();
|
||||||
|
String content = "";
|
||||||
|
|
||||||
|
if (fileExtension.equals("txt")) {
|
||||||
|
content = readTextFile(filePath);
|
||||||
|
} else if (fileExtension.equals("doc")||fileExtension.equals("docx")) {
|
||||||
|
content = readDocFile(filePath);
|
||||||
|
} else if (fileExtension.equals("pdf")) {
|
||||||
|
content = readPdfFile(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
//读取.txt文件
|
||||||
|
public String readTextFile(String filePath) {
|
||||||
|
StringBuilder contentBuilder = new StringBuilder();
|
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
|
||||||
|
String currentLine;
|
||||||
|
while ((currentLine = br.readLine()) != null) {
|
||||||
|
contentBuilder.append(currentLine).append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return contentBuilder.toString();
|
||||||
|
}
|
||||||
|
// 读取.doc文件并返回文本内容
|
||||||
|
public String readDocFile(String docFilePath) {
|
||||||
|
try (FileInputStream fis = new FileInputStream(docFilePath)) {
|
||||||
|
String fileExtension = Files.probeContentType(Paths.get(docFilePath));
|
||||||
|
if (fileExtension.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
|
||||||
|
// 处理 .docx 文件
|
||||||
|
XWPFDocument docx = new XWPFDocument(fis);
|
||||||
|
List<XWPFParagraph> paragraphs = docx.getParagraphs();
|
||||||
|
StringBuilder textBuilder = new StringBuilder();
|
||||||
|
for (XWPFParagraph paragraph : paragraphs) {
|
||||||
|
textBuilder.append(paragraph.getText());
|
||||||
|
textBuilder.append("\n");
|
||||||
|
}
|
||||||
|
return textBuilder.toString();
|
||||||
|
} else if (fileExtension.equals("application/msword")) {
|
||||||
|
// 处理 .doc 文件
|
||||||
|
HWPFDocument doc = new HWPFDocument(fis);
|
||||||
|
Range range = doc.getRange();
|
||||||
|
return range.text();
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Unsupported file type: " + fileExtension);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取.pdf文件并返回文本内容
|
||||||
|
public String readPdfFile(String pdfFilePath) {
|
||||||
|
try (PDDocument document = PDDocument.load(new File(pdfFilePath));
|
||||||
|
StringWriter writer = new StringWriter()) {
|
||||||
|
PDFTextStripper stripper = new PDFTextStripper();
|
||||||
|
stripper.writeText(document, writer);
|
||||||
|
return writer.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件扩展名
|
||||||
|
public String getFileExtension(String fileName) {
|
||||||
|
int lastDotIndex = fileName.lastIndexOf('.');
|
||||||
|
if (lastDotIndex > 0) {
|
||||||
|
return fileName.substring(lastDotIndex + 1);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
/**********************************///数据清洗部分
|
||||||
|
|
||||||
|
// 添加一个静态的停用词集合
|
||||||
|
private static final Set<String> STOP_WORDS = new HashSet<>();//过滤停用词
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
// 获取项目根目录路径
|
||||||
|
String projectRootDirectory = System.getProperty("user.dir");
|
||||||
|
// 构建停用词文件的路径
|
||||||
|
String stopwordsFilePath = projectRootDirectory + File.separator + "停用词.txt";
|
||||||
|
// 读取文件中的每一行
|
||||||
|
Files.readAllLines(Paths.get(stopwordsFilePath), StandardCharsets.UTF_8)
|
||||||
|
.forEach(STOP_WORDS::add);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 使用正则表达式移除所有空白字符
|
||||||
|
private static String cleanText(String text) {//用于分句时去除空白
|
||||||
|
return text.replaceAll("\\s+", "");
|
||||||
|
}
|
||||||
|
// 移除句子中的标点
|
||||||
|
private static String cleanSentences(String text) {//用于句中文本标点清洗
|
||||||
|
return text.replaceAll("[,。!?;:“”‘’()《》【】〔〕…—~、\\\\s+]+", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************///文本处理
|
||||||
|
public List<String> splitIntoSentences(String text) {//断句
|
||||||
|
// 使用 HanLP 进行分词,获取词元列表
|
||||||
|
List<Term> termList = HanLP.segment(text);
|
||||||
|
// 存储断好的句子
|
||||||
|
List<String> sentences = new ArrayList<>();
|
||||||
|
// 使用 StringBuilder 来构建句子
|
||||||
|
StringBuilder sentenceBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
// 遍历词元列表,根据标点符号进行断句
|
||||||
|
for (Term term : termList) {
|
||||||
|
String word = term.word;
|
||||||
|
// 如果当前词是标点符号,并且不是句子内部的标点(如顿号、逗号等),则断句
|
||||||
|
if (Pattern.matches("[。!?;:]$", word)) {
|
||||||
|
sentenceBuilder.append(word);
|
||||||
|
sentences.add(sentenceBuilder.toString());
|
||||||
|
sentenceBuilder.setLength(0); // 清空 StringBuilder 以便构建下一个句子
|
||||||
|
} else {
|
||||||
|
sentenceBuilder.append(word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查 StringBuilder 中是否还有剩余的文本,如果有,则添加到最后一个句子
|
||||||
|
if (sentenceBuilder.length() > 0) {
|
||||||
|
sentences.add(sentenceBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sentences;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************///计算相似度部分
|
||||||
|
// 计算两个句子之间的余弦相似度
|
||||||
|
public double calculateSentenceSimilarity1(String sentence1, String sentence2) {
|
||||||
|
// 分词并创建词频向量
|
||||||
|
Map<String, Integer> vector1 = buildWordFrequencyVector(sentence1);
|
||||||
|
Map<String, Integer> vector2 = buildWordFrequencyVector(sentence2);
|
||||||
|
|
||||||
|
// // 输出两个句子的词频向量
|
||||||
|
// System.out.println("Sentence 1 Vector: " + vector1);
|
||||||
|
// System.out.println("Sentence 2 Vector: " + vector2);
|
||||||
|
|
||||||
|
// 计算余弦相似度
|
||||||
|
double similarity = calculateCosineSimilarity(vector1, vector2);
|
||||||
|
// //输出
|
||||||
|
// System.out.println("Cosine Similarity: " + similarity);
|
||||||
|
|
||||||
|
return similarity;
|
||||||
|
}
|
||||||
|
// 计算两个句子之间的 Jaccard 相似度
|
||||||
|
public double calculateSentenceSimilarity2(String sentence1, String sentence2) {
|
||||||
|
// 分词并创建词集合
|
||||||
|
Set<String> setA = buildWordSet(sentence1);
|
||||||
|
Set<String> setB = buildWordSet(sentence2);
|
||||||
|
|
||||||
|
// 计算 Jaccard 相似度
|
||||||
|
return calculateJaccardSimilarity(setA, setB);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建词频向量 用于余弦相似度计算
|
||||||
|
public Map<String, Integer> buildWordFrequencyVector(String sentence) {
|
||||||
|
Map<String, Integer> wordFrequency = new HashMap<>();
|
||||||
|
String cleanedSentence = cleanSentences(sentence);
|
||||||
|
// 分词
|
||||||
|
List<Term> termList = HanLP.segment(cleanedSentence);
|
||||||
|
for (Term term : termList) {
|
||||||
|
String word = term.word;
|
||||||
|
// 过滤停用词
|
||||||
|
if (!STOP_WORDS.contains(word)) {
|
||||||
|
wordFrequency.put(word, wordFrequency.getOrDefault(word, 0) + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// for (Term term : termList) {
|
||||||
|
// String word = term.word;
|
||||||
|
// wordFrequency.put(word, wordFrequency.getOrDefault(word, 0) + 1);
|
||||||
|
// }
|
||||||
|
return wordFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建词集合 用于Jaccard相似度计算
|
||||||
|
public Set<String> buildWordSet(String sentence) {
|
||||||
|
Set<String> wordSet = new HashSet<>();
|
||||||
|
String cleanedSentence = cleanSentences(sentence);
|
||||||
|
// 分词
|
||||||
|
List<Term> termList = HanLP.segment(cleanedSentence);
|
||||||
|
for (Term term : termList) {
|
||||||
|
String word = term.word;
|
||||||
|
// 过滤停用词
|
||||||
|
if (!STOP_WORDS.contains(word)) {
|
||||||
|
wordSet.add(word);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return wordSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算余弦相似度
|
||||||
|
public double calculateCosineSimilarity(Map<String, Integer> vectorA, Map<String, Integer> vectorB) {
|
||||||
|
Set<String> uniqueWords = new HashSet<>(vectorA.keySet());
|
||||||
|
uniqueWords.addAll(vectorB.keySet());
|
||||||
|
|
||||||
|
double dotProduct = 0.0;
|
||||||
|
double normA = 0.0;
|
||||||
|
double normB = 0.0;
|
||||||
|
|
||||||
|
for (String word : uniqueWords) {
|
||||||
|
int countA = vectorA.getOrDefault(word, 0);
|
||||||
|
int countB = vectorB.getOrDefault(word, 0);
|
||||||
|
dotProduct += countA * countB;
|
||||||
|
normA += Math.pow(countA, 2);
|
||||||
|
normB += Math.pow(countB, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normA == 0.0 || normB == 0.0) {
|
||||||
|
return 0.0; // 如果任一向量为零向量,则相似度为0
|
||||||
|
}
|
||||||
|
|
||||||
|
return dotProduct / (Math.sqrt(normA) * Math.sqrt(normB));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算两个集合之间的 Jaccard 相似度
|
||||||
|
public double calculateJaccardSimilarity(Set<String> setA, Set<String> setB) {
|
||||||
|
Set<String> intersection = new HashSet<>(setA);
|
||||||
|
intersection.retainAll(setB);
|
||||||
|
Set<String> union = new HashSet<>(setA);
|
||||||
|
union.addAll(setB);
|
||||||
|
|
||||||
|
// 避免除以零的情况
|
||||||
|
if (union.size() == 0) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (double) intersection.size() / union.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@ package com.example.aes.problem.service.Impl;
|
||||||
|
|
||||||
import com.example.aes.problem.dao.*;
|
import com.example.aes.problem.dao.*;
|
||||||
import com.example.aes.problem.model.*;
|
import com.example.aes.problem.model.*;
|
||||||
|
import com.example.aes.problem.service.PlagiarismServiceI;
|
||||||
import com.example.aes.problem.service.ProblemServiceI;
|
import com.example.aes.problem.service.ProblemServiceI;
|
||||||
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;
|
||||||
|
|
@ -9,6 +10,10 @@ import com.example.aes.user.model.DataGrid;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
@ -26,6 +31,10 @@ public class ProblemServiceImpl implements ProblemServiceI {
|
||||||
private AdminusersDaoI adminusersDao;
|
private AdminusersDaoI adminusersDao;
|
||||||
private PostProblemDaoI postProblemDao;
|
private PostProblemDaoI postProblemDao;
|
||||||
private ClassesDaoI classesDao;
|
private ClassesDaoI classesDao;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PlagiarismServiceI plagiarismServiceI;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public void setClassesDao(ClassesDaoI classesDao) {
|
public void setClassesDao(ClassesDaoI classesDao) {
|
||||||
this.classesDao = classesDao;
|
this.classesDao = classesDao;
|
||||||
|
|
@ -149,23 +158,32 @@ public class ProblemServiceImpl implements ProblemServiceI {
|
||||||
for (PMProblem pmProblem : pMproblems) {
|
for (PMProblem pmProblem : pMproblems) {
|
||||||
// 从Map中获取对应的ReportSubmitted对象
|
// 从Map中获取对应的ReportSubmitted对象
|
||||||
ReportSubmitted reportStatus = reportStatusMap.get(pmProblem.getId());
|
ReportSubmitted reportStatus = reportStatusMap.get(pmProblem.getId());
|
||||||
|
//如果学生尚未提交过任何报告
|
||||||
|
if(reportStatus == null){
|
||||||
|
pmProblem.setStatus("未提交");
|
||||||
|
}
|
||||||
// 确保reportStatus不为null并且studentId匹配
|
// 确保reportStatus不为null并且studentId匹配
|
||||||
if (reportStatus != null && studentId.equals(reportStatus.getStudentId())) {
|
if (reportStatus != null && studentId.equals(reportStatus.getStudentId())) {
|
||||||
pmProblem.setSubmissionStatus(reportStatus.getSubmissionStatus());
|
pmProblem.setSubmissionStatus(reportStatus.getSubmissionStatus());
|
||||||
pmProblem.setPlagiarismStatus(reportStatus.getPlagiarismStatus());
|
pmProblem.setPlagiarismStatus(reportStatus.getPlagiarismStatus());
|
||||||
pmProblem.setScore(reportStatus.getScore());
|
if (reportStatus.getScore() != null) {
|
||||||
|
pmProblem.setScore(reportStatus.getScore());
|
||||||
// 根据submissionStatus设置status
|
|
||||||
if ("0".equals(reportStatus.getSubmissionStatus())) {
|
|
||||||
pmProblem.setStatus("未提交");
|
|
||||||
} else if ("1".equals(reportStatus.getSubmissionStatus())) {
|
|
||||||
pmProblem.setStatus("已提交");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果score不为空,则将status设置为score的具体值
|
String submissionStatus = reportStatus.getSubmissionStatus();
|
||||||
|
if ("未领取".equals(submissionStatus) || "已领取".equals(submissionStatus) || submissionStatus == null) {
|
||||||
|
pmProblem.setStatus("未提交");
|
||||||
|
} else if ("已提交".equals(submissionStatus)) {
|
||||||
|
pmProblem.setStatus("已提交");
|
||||||
|
} else if ("已撤回".equals(submissionStatus)) {
|
||||||
|
pmProblem.setStatus("已撤回");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果score或者autoscore不为空,则将status设置为score的具体值
|
||||||
if (reportStatus.getScore() != null) {
|
if (reportStatus.getScore() != null) {
|
||||||
pmProblem.setStatus(String.format("%.2f", reportStatus.getScore()));
|
pmProblem.setStatus(String.format("%.2f", reportStatus.getScore()));
|
||||||
|
} else if (reportStatus.getAutoscore() != null) {
|
||||||
|
pmProblem.setStatus(String.format("%.2f", reportStatus.getAutoscore()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -482,6 +500,105 @@ public int redoReport(PMReviewMessage pmReviewMessage){
|
||||||
return studentSubmitDao.findNextId(problemId).get(0);
|
return studentSubmitDao.findNextId(problemId).get(0);
|
||||||
else return 0;
|
else return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveSubmitInfoToProps(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.saveSubmitInfo(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean findReportSubmitted(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.getReportSubmitted(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSubmitInfoToProps(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.updateReportSubmitted(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean updateSubmitInfoForSubmission(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.updateReportSubmittedForSubmission(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean withdrawSubmitInfo(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.withdrawReportSubmitted(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String findReportSubmittedStatus(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.getReportSubmittedStatus(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean savePlagiarismResultToProps(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.savePlagiarismResult(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AutoScoreResult getAutoScore(Path filePath, int problemId) {
|
||||||
|
// 读取报告文件内容
|
||||||
|
String reportContent = (plagiarismServiceI.readFileWithoutClean(filePath.toString()));
|
||||||
|
|
||||||
|
// 从数据库获取评分标准
|
||||||
|
List<ScoringStandard> standards = scoringStandardDao.getStandardIdByProblemId(problemId);
|
||||||
|
double totalScore = 0.0;
|
||||||
|
List<String> remarks = new ArrayList<>(); // 用于存储评语
|
||||||
|
|
||||||
|
for (ScoringStandard standard : standards) {
|
||||||
|
String dimension = standard.getDimension();
|
||||||
|
// 根据standardId获取评分细则
|
||||||
|
List<ScoringRubric> rubrics = scoringRubricDao.getScoringRubricByStandardId(standard.getId());
|
||||||
|
// 如果找到了评分细则,格式化dimension字符串
|
||||||
|
if (rubrics != null && !rubrics.isEmpty()) {
|
||||||
|
StringBuilder dimensionBuilder = new StringBuilder(dimension + ":");
|
||||||
|
for (int i = 0; i < rubrics.size(); i++) {
|
||||||
|
ScoringRubric rubric = rubrics.get(i);
|
||||||
|
if (i > 0) {
|
||||||
|
dimensionBuilder.append(";"); // 分隔不同的细则
|
||||||
|
}
|
||||||
|
dimensionBuilder.append(rubric.getLowerLimit())
|
||||||
|
.append("分~")
|
||||||
|
.append(rubric.getUpperLimit())
|
||||||
|
.append("分,")
|
||||||
|
.append(rubric.getDescription());
|
||||||
|
}
|
||||||
|
dimension = dimensionBuilder.toString();
|
||||||
|
}
|
||||||
|
double weight = standard.getWeight();
|
||||||
|
String scoreStr = null;
|
||||||
|
try { // 调用Python脚本进行评分
|
||||||
|
scoreStr = executePythonScript(reportContent, dimension);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
// 使用逗号分割评分和评语
|
||||||
|
String[] scoreAndReason = scoreStr.split("\n");
|
||||||
|
if (scoreAndReason.length < 2) {
|
||||||
|
throw new RuntimeException("Python脚本输出格式不正确");
|
||||||
|
}
|
||||||
|
double score = Double.parseDouble(scoreAndReason[0].replace("score: ", "").trim());
|
||||||
|
String reason = scoreAndReason[1].replace("reason: ", "").trim();
|
||||||
|
|
||||||
|
// 存储评语
|
||||||
|
remarks.add(reason);
|
||||||
|
// 计算加权分数
|
||||||
|
totalScore += score * weight;
|
||||||
|
}
|
||||||
|
// 将总分转换为100分制
|
||||||
|
totalScore *= 10;
|
||||||
|
// 返回评分和评语
|
||||||
|
return new AutoScoreResult(totalScore, remarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean saveAutoScoreResultToProps(SubmitReport submitReport) {
|
||||||
|
return studentSubmitDao.saveAutoScoreResult(submitReport);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int editPostProblem(int classId,
|
public int editPostProblem(int classId,
|
||||||
int problemId,LocalDateTime startTime,LocalDateTime endTime,boolean allow){
|
int problemId,LocalDateTime startTime,LocalDateTime endTime,boolean allow){
|
||||||
|
|
@ -611,4 +728,33 @@ public int redoReport(PMReviewMessage pmReviewMessage){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private String executePythonScript(String content, String dim) throws IOException, InterruptedException {
|
||||||
|
// 构建Python命令
|
||||||
|
String pythonCommand = String.format("python original.py \"%s\" \"%s\"", content, dim);
|
||||||
|
|
||||||
|
// 执行Python脚本
|
||||||
|
Process process = Runtime.getRuntime().exec(pythonCommand);
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
|
||||||
|
if (exitCode != 0) {
|
||||||
|
throw new RuntimeException("Python脚本执行失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取输出
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
StringBuilder output = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
output.append(line).append("\n");
|
||||||
|
}
|
||||||
|
reader.close();
|
||||||
|
|
||||||
|
String scoreAndReason = output.toString().trim();
|
||||||
|
|
||||||
|
if (scoreAndReason == null || scoreAndReason.isEmpty()) {
|
||||||
|
throw new RuntimeException("Python脚本输出为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
return scoreAndReason;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.example.aes.problem.service;
|
||||||
|
|
||||||
|
|
||||||
|
import com.example.aes.problem.model.*;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface PlagiarismServiceI {
|
||||||
|
|
||||||
|
public PlagiarismResult checkPlagiarism(String toString, String uploadDirectory);
|
||||||
|
public String readFileWithoutClean(String filePath);
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import com.example.aes.problem.model.DataGrid;
|
||||||
import com.example.aes.user.model.*;
|
import com.example.aes.user.model.*;
|
||||||
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
import javax.persistence.criteria.CriteriaBuilder;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
@ -56,4 +57,14 @@ public interface ProblemServiceI {
|
||||||
public List<Float> findScoreList(PMStudentSubmit pmStudentSubmit);
|
public List<Float> findScoreList(PMStudentSubmit pmStudentSubmit);
|
||||||
public List<SubmitReport> findSimilardocs(PMStudentSubmit pmStudentSubmit);
|
public List<SubmitReport> findSimilardocs(PMStudentSubmit pmStudentSubmit);
|
||||||
public int findNextId(int problemId);
|
public int findNextId(int problemId);
|
||||||
|
|
||||||
|
public boolean saveSubmitInfoToProps(SubmitReport submitReport);//学生保存报告(保存,之前未保存过)
|
||||||
|
public boolean findReportSubmitted(SubmitReport submitReport);//查询该学生之前是否已经提交过该问题的报告
|
||||||
|
public boolean updateSubmitInfoToProps(SubmitReport submitReport);//学生更新报告信息(保存,之前保存过)
|
||||||
|
public boolean updateSubmitInfoForSubmission(SubmitReport submitReport);//学生提交报告
|
||||||
|
public boolean withdrawSubmitInfo(SubmitReport submitReport);//学生撤回报告
|
||||||
|
public String findReportSubmittedStatus(SubmitReport submitReport);//查询该学生之前已经提交过该问题的报告状态
|
||||||
|
public boolean savePlagiarismResultToProps(SubmitReport submitReport);//保存查重信息
|
||||||
|
public AutoScoreResult getAutoScore(Path filePath, int problemId);//自动批阅
|
||||||
|
public boolean saveAutoScoreResultToProps(SubmitReport submitReport);//保存自动批阅信息
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,7 @@ import org.springframework.core.io.ResourceLoader;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
import javax.servlet.ServletOutputStream;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ server.port=8082
|
||||||
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
|
||||||
jdbc_url=jdbc:mysql://localhost:3306/aes?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=True
|
jdbc_url=jdbc:mysql://localhost:3306/aes?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=True
|
||||||
jdbc_username=root
|
jdbc_username=root
|
||||||
jdbc_password=13661744518xh
|
jdbc_password=123456
|
||||||
#spring.datasource.url=jdbc:mysql://localhost:3306/aes?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=True
|
#spring.datasource.url=jdbc:mysql://localhost:3306/aes?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=false&allowPublicKeyRetrieval=True
|
||||||
#spring.datasource.username=root
|
#spring.datasource.username=root
|
||||||
#spring.datasource.password=123456
|
#spring.datasource.password=123456
|
||||||
|
|
@ -43,4 +43,8 @@ spring.servlet.multipart.max-request-size=50MB
|
||||||
spring.main.allow-bean-definition-overriding=true
|
spring.main.allow-bean-definition-overriding=true
|
||||||
|
|
||||||
spring.jackson.serialization-inclusion=non_null
|
spring.jackson.serialization-inclusion=non_null
|
||||||
|
|
||||||
|
spring.redis.host=127.0.0.1
|
||||||
|
spring.redis.port=6379
|
||||||
|
spring.redis.password=hqb@1234
|
||||||
#??null?
|
#??null?
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
https://www.springframework.org/schema/context/spring-context.xsd
|
https://www.springframework.org/schema/context/spring-context.xsd
|
||||||
http://cxf.apache.org/jaxws
|
http://cxf.apache.org/jaxws
|
||||||
http://cxf.apache.org/schemas/jaxws.xsd">
|
http://cxf.apache.org/schemas/jaxws.xsd">
|
||||||
<context:property-placeholder location="classpath:redis.properties"/>
|
<context:property-placeholder location="classpath:application.properties,classpath:redis.properties"/>
|
||||||
|
|
||||||
|
|
||||||
<!-- 配置数据源 -->
|
<!-- 配置数据源 -->
|
||||||
|
|
@ -125,7 +125,7 @@
|
||||||
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
|
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
|
||||||
<property name="hostName" value="${redis.host}"/>
|
<property name="hostName" value="${redis.host}"/>
|
||||||
<property name="port" value="${redis.port}"/>
|
<property name="port" value="${redis.port}"/>
|
||||||
<!-- <property name="password" value="${redis.pass}"/>-->
|
<property name="password" value="${redis.pass}"/>
|
||||||
<property name="poolConfig" ref="poolConfig"/>
|
<property name="poolConfig" ref="poolConfig"/>
|
||||||
</bean>
|
</bean>
|
||||||
</beans>
|
</beans>
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,54 @@
|
||||||
|
import openai
|
||||||
|
import time
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
model = "Qwen/Qwen3-8B"
|
||||||
|
max_tokens = 500
|
||||||
|
|
||||||
|
output_format = """
|
||||||
|
score:
|
||||||
|
reason:
|
||||||
|
"""
|
||||||
|
|
||||||
|
def getDim(content, dim):
|
||||||
|
client = openai.OpenAI(base_url='https://api.siliconflow.cn/v1',
|
||||||
|
api_key="xxx")
|
||||||
|
time.sleep(3)
|
||||||
|
messages = []
|
||||||
|
messages.append({
|
||||||
|
"role": "system",
|
||||||
|
"content": "你是一位评分老师,请根据提供给你的评分标准对文本进行评分,结果仅仅输出分数,满分为10分,分数允许小数点后保留两位,并就当前维度给出评语,评语文本不要过长。"
|
||||||
|
"输出格式:"
|
||||||
|
f"{output_format}"
|
||||||
|
|
||||||
|
})
|
||||||
|
messages.append({
|
||||||
|
"role": "user",
|
||||||
|
"content": f"待评分内容:{content}"
|
||||||
|
f"评分标准:{dim}"
|
||||||
|
})
|
||||||
|
response = client.chat.completions.create(
|
||||||
|
model=model,
|
||||||
|
messages=messages,
|
||||||
|
max_tokens=max_tokens,
|
||||||
|
temperature=0.1
|
||||||
|
)
|
||||||
|
|
||||||
|
# print(response.choices[0].message.content)
|
||||||
|
# match = re.search(r'\d+', response.choices[0].message.content)
|
||||||
|
# if match:
|
||||||
|
# score = match.group()
|
||||||
|
# else:
|
||||||
|
# score = response.choices[0].message.content
|
||||||
|
# print(score)
|
||||||
|
|
||||||
|
# 去除多余的换行符
|
||||||
|
content = response.choices[0].message.content.strip()
|
||||||
|
return content
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
content = sys.argv[1]
|
||||||
|
dim = sys.argv[2]
|
||||||
|
result = getDim(content, dim)
|
||||||
|
print(result)
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
智能手机在当代社会的作用不可小觑,它不仅使得人们的通讯变得极为便捷,还提供了多样化的娱乐和工作功能。在我国,智能手机的普及率不断上升,几乎成了每个人生活中的必需品。它的多功能性和便携性,使其成为了现代科技的一个标志性产物。无论是通讯、娱乐还是学习,都离不开这款电子设备。
|
|
||||||
在城市边缘的那所著名大学的操场上,一场几千人参加的批斗会已经进行了近两个小时。
|
|
||||||
“爱因斯坦是反动的学术权威,他有奶便是娘,跑去为美帝国主义造原子弹!要建立起革命的科学,就要打倒以相对论为代表的资产阶级理论黑旗!”
|
|
||||||
然后在法文词下列出同义的上海方言词语,再尽可能详尽地列出近义的上海方言词语、短语或句子。这种编写方式,对中法两国学习者或词典使用者尽可能多地掌握法汉词汇,显然是很有意义的。
|
|
||||||
Loading…
Reference in New Issue