前言
最近就在开发帮助教师统计分数的功能
一、统计分数功能设想
1、学生最后的分数由三部分组成:讨论分数,作业分数,考试分数
2、教师通过拖动滑动条设置这三部分成绩占比
3、教师上传学生考试成绩单
4、生成总的成绩表
5、导出成绩表
6、根据总成绩绘制学生成绩分布图
二、部分代码展示
<template>
<div id="classes">
<el-row :gutter="20">
<el-col :span="12" :offset="1">
<span class="demonstration">
请依次为讨论、作业和期末考试赋予相应的权重,且和不超过100
</span>
</el-col>
<el-col :span="16" :offset="1">
<div class="block2">
<el-slider
v-model="value0"
show-input>
</el-slider>
</div>
</el-col>
<el-col :span="16" :offset="1">
<div class="block2">
<el-slider
v-model="value1"
show-input>
</el-slider>
</div>
</el-col>
<el-col :span="16" :offset="1">
<div class="block2">
<el-slider
v-model="value2"
show-input>
</el-slider>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="3" :offset="1">
<el-button
type="primary" plain
icon="el-icon-edit"
class="filter-item"
@click="calculate()">计算得分
</el-button>
</el-col>
</el-row>
<el-divider>
</el-divider>
<el-button class="btn-seal" @click="uploadTestScore()">
上传考试分数
</el-button>
<el-button class="btn-seal" @click="getExportList()">
导出成绩单
</el-button>
<el-button class="btn-seal" @click="hh()">
画成绩分布图
</el-button>
<div class="body">
<template>
<el-table
id="student-table"
:data="tableData"
stripe
style="width: 100%">
<el-table-column
prop="sid"
label="学号"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="discussion_score"
label="讨论分数"
width="180">
</el-table-column>
<el-table-column
prop="homework_score"
label="作业分数"
width="180">
</el-table-column>
<el-table-column
prop="test_score"
label="考试分数"
width="180">
</el-table-column>
<el-table-column
prop="final_score"
label="总得分"
width="180">
</el-table-column>
</el-table>
</template>
</div>
<!--这是要上传考试成绩单 -->
<el-dialog :visible.sync="dialogFormVisible">
<el-form
:model="questionForm"
ref="dataForm"
label-position="left"
label-width="90px"
style="width: 400px; margin-left:50px;"
>
<el-form-item label="课程号" prop="cid">
<el-input v-model="questionForm.cid" />
</el-form-item>
<el-form-item label="课程名" prop="classname">
<el-input v-model="questionForm.classname" />
</el-form-item>
<el-form-item label="教工号" prop="tid">
<el-input v-model="questionForm.tid" />
</el-form-item>
<el-form-item label="考试成绩单" prop="cid">
<div class="upset">
<el-upload drag
:limit=limitNum
:auto-upload="false"
accept=".xlsx"
:action="UploadUrl()"
:before-upload="beforeUploadFile"
:on-change="fileChange"
:on-exceed="exceedFile"
:on-success="handleSuccess"
:on-error="handleError"
:file-list="fileList">
<i class="el-icon-upload">
</i>
<div class="el-upload__text">
将xlsx文件拖到此处,或<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
格式要求
</div>
</el-upload>
<br/>
</div>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">
取消
</el-button>
<el-button type="primary" @click=" createData() ">
确定
</el-button>
</div>
</el-dialog>
<el-divider>
</el-divider>
<!--这是要画成绩分布图 -->
<div id="myChart123" :style="{width: '800px', height: '550px'}"></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import {onMounted} from "vue";
export default {
name: "score",
props: ['cid'],
data() {
return{
score_y : [],//新建的数值型数组
//到这里都是负责上传考试成绩的功能
questionForm: {
cid: "",
classname: "",
tid: "",
},
dialogFormVisible: false,
limitNum: 1, // 上传excell时,同时允许上传的最大数
fileList: [], // excel文件列表
//考试成绩功能上传结束
value0: 0,
value1: 0,
value2: 0,
my_user:'',
class_id:'',
tableData:[] ,//cid,name
input: "",
classname:'',
drawscorelist:[],
};
},
created() {
},
methods: {
//这里是上传考试成绩的代码
uploadTestScore() {
this.questionForm = {
cid: "",
classname: "",
tid: "",
};
this.dialogFormVisible = true;
},
beforeUpload(file){
var formdata = new FormData();
formdata.append('file',file);
this.$axios.post('http://127.0.0.1:8080/excel',formdata,{ headers : { 'Content-type':'multipart/form-data'}});
},
// 文件超出个数限制时的钩子
exceedFile(files, fileList) {
this.$message.warning(`只能选择 ${this.limitNum} 个文件,当前共选择了 ${files.length + fileList.length} 个`);
},
// 文件状态改变时的钩子
fileChange(file, fileList) {
console.log(file.raw);
this.fileList.push(file.raw) ;
console.log(this.fileList);
},
// 上传文件之前的钩子, 参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传
beforeUploadFile(file) {
console.log('before upload');
console.log(file);
let extension = file.name.substring(file.name.lastIndexOf('.')+1);
let size = file.size / 1024 / 1024;
if(extension !== 'xlsx') {
this.$message.warning('只能上传后缀是.xlsx的文件');
}
if(size > 10) {
this.$message.warning('文件大小不得超过10M');
}
},
// 文件上传成功时的钩子
handleSuccess(res, file, fileList) {
this.$message.success('文件上传成功');
},
// 文件上传失败时的钩子
handleError(err, file, fileList) {
this.$message.error('文件上传失败');
},
UploadUrl:function(){
// 因为action参数是必填项,我们使用二次确认进行文件上传时,直接填上传文件的url会因为没有参数导致api报404,所以这里将action设置为一个返回为空的方法就行,避免抛错
return ""
},
uploadFile() {
if (this.fileList.length === 0){
this.$message.warning('请上传文件');
} else {
let form = new FormData();
form.append('file', this.fileList[0]);
this.axios({
method:"post",
url: "/teacher/upload_score",
headers:{
'Content-type': 'multipart/form-data'
},
data:form
}).then(
res=>{
},err =>{
});
}
},
async createData() {
if (this.fileList.length === 0){
this.$message.warning('请上传文件');
} else {
let form = new FormData();
form.append('file', this.fileList[0]);
form.append('cid', this.questionForm.cid);
form.append('classname', this.questionForm.classname);
form.append('tid', this.questionForm.tid);
this.axios({
method:"post",
url: "/teacher/upload_score",
headers:{
'Content-type': 'multipart/form-data'
},
data:form
}).then(
res=>{
},err =>{
});
}
//如果需要调用接口,请打开注释
// const res = await saveSubject(params);
// console.log(res);
// if (res.code === "0000") {
// this.$message({
// type: "info",
// message: "保存成功",
// });
// this.dialogFormVisible = false;
// this.getQuerySubjectList();
// return;
// }
// this.$message({
// type: "error",
// message: "保存失败",
// });
this.dialogFormVisible = false;
},
//和上传考试成绩相关的代码结束
calculate() {
console.log(this.cid)
console.log("cccc")
this.class_id=this.cid
this.my_user=this.$store.getters.id
if(this.my_user===''){
this.my_user=sessionStorage.getItem('teacher_id')
}
console.log("qwqwqwqwqwqw")
console.log(this.value0/100)
console.log(this.value1/100)
console.log(this.value2/100)
console.log("qwqwqwqwqwqw")
this.axios({
url: '/teacher/checkscore',
method: 'get',
params: {
teacher_id: this.my_user,
class_id: this.class_id,
value0:this.value0/100,
value1:this.value1/100,
value2:this.value2/100,
},
}).then(
(res) => {
console.log(res)
this.tableData = res.data
},
function (res) {
console.log(res)
console.log('啊呀,出错啦')
}
)
},
//试一试导出excel表格
getExportList() {
const _self=this
let jsonData = {
trade:{
tHeader: ["学号","姓名","讨论分数","作业分数","考试分数","总得分"],
filterVal: ["sid","name","discussion_score","homework_score","test_score","final_score"],
list: _self.tableData
}
}
_self.exportPathMethod(jsonData)// 调用exportPathMethod对数据进行处理导出
_self.exportShow=false
},
exportPathMethod(data) {
/*
*注:csv文件:","逗号换列,\n换行,\t防止excel将长数字变科学计算法等样式
*/
//要导出的json数据
let mainLists = data.trade //主表
let _self = this
//## 数据处理
//一级表
let mainTitle = mainLists.tHeader;//一级标题
let mainTitleForKey = mainLists.filterVal;//一级过滤
let mainList = mainLists.list;//一级数据
let mainStr = [];
mainStr.push(mainTitle.join("\t,")+"\n"); //标题添加上换列转成字符串并存进数组
for(let i=0;i<mainList.length;i++){
let temp = [];
for(let j=0;j<mainTitleForKey.length;j++){
temp.push(mainList[i][mainTitleForKey[j]]); //根据过滤器拿出对应的值
}
mainStr.push(temp.join("\t,")+"\n"); //取出来的值加上逗号换列转字符串存数组
}
// console.log(JSON.stringify(mainStr.join("")));//打印文本
//两个表数组转成字符串合并
let merged = mainStr.join("")
//console.log(JSON.stringify(merged));//打印结果
//## 导出操作
// encodeURIComponent解决中文乱码
const uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(merged)
// 通过创建a标签实现
let link = document.createElement('a')
link.href = uri
//这里需要查询根据课程号查询出课程名
this.axios({
url: '/teacher/checkClassname',
method: 'get',
params: {
cid: this.class_id
},
}).then(
(res) => {
console.log(res)
this.classname = res.data
},
function (res) {
console.log(res)
console.log('啊呀,出错啦')
}
)
// 对下载的文件命名
link.download = `${_self.class_id}-${_self.classname}.csv`
document.body.appendChild(link)
link.click()
},
//下面是负责画成绩折线图的
async hh(){
//先是要获得五个区间的人数都分别是多少
await this.axios({
url: '/teacher/drawscore',
method: 'get',
params: {
teacher_id: this.my_user,
class_id: this.class_id,
value0:this.value0/100,
value1:this.value1/100,
value2:this.value2/100,
},
}).then(
(res) => {
console.log(res)
this.drawscorelist = res.data
},
function (res) {
console.log(res)
console.log('啊呀,出错啦')
}
)
console.log("这到底是是第几变数")
for(var i=0;i<this.drawscorelist.length;i++){
console.log(this.drawscorelist[i])
this.score_y.push(parseInt(this.drawscorelist[i]))
}
console.log("ssssssssssss")
console.log(this.score_y.length)
let myChart = echarts.init(document.getElementById("myChart123"));
// 绘制图表
myChart.setOption({
xAxis: {
data: ["[0,60)", "[60,65)", "[65-70)", "[70-75)", "[75-80)", "[80-85)", "[85-90)", "[90,95)","[95-100]"]
},
yAxis:{},
series: [
{
name: "成绩统计",
type: "line",
data: this.score_y
}
]
});
}
},
}
</script>
由于后端的代码不是整块的,这里就不做展示了