0%

cc-develop-note-iv

评教模块

image-20201214162924955

教学中心,新增评教一栏,教师可以查看研究生的评教结果(选课人数、评教人数、分项平均分、总平均分、学生文字评价)

backend/modules/api/v1/models/lessonVote/AcademicMasterStudentVote.php

前端

src\views\teacher\TeachingCenter.vue

src\router\fullpath.js中设置路径、组件

1
2
3
4
5
6
7
8
{
path: "/vote-result/:lessonID",
name: "评教结果查看",
component: resolve =>
require([
"@/views/lesson/AllStudentHomeworkInfoList"
], resolve)
},

404:路由需要设置权限,路由需要对应到菜单/vote-result/:LessonID

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
getTableData(){
// 获取评教选课人数、评教人数、分项平均分、总平均分、学生文字评价
this.axios.get('/lesson-vote/get-vote-analysis', {
params: {
LessonID: this.$route.params.lessonID
}
}).then(res => {
if (res.data.success) {
this.tableData.totalStudentNum=res.data.SelectNum
this.tableData.votedStudentNum=res.data.voteNum
this.tableData.eachTermAvgScore=res.data.SGScoreArr
this.tableData.allTermAvgScore=res.data.avgScore
this.tableData.allVoteText=res.data.proposal
console.log(this.tableData)
} else {
this.$message({
type: "error",
message: res.data
})
}
}).catch(util.catchError)
}

数据库

重新设计数据库表 cc_academic_master_lesson_vote_analysis 和 cc_academic_master_sg_lesson_avgscore,把评教的分析结果存起来,前端查询时直接查表,如果没有该项课程的分析结果,再去执行类似models/lessonVote/AcademicMasterStudentVote.php里的sql语句。

文字评价直接查 cc_academic_master_student_vote 表

是否查表:LID 是否已存在

后端

编写Model

分项平均分

backend/modules/api/v1/models/lessonVote/AcademicMasterSGLessonAvgScore.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//获取21项SG的平均分,data 以字典存储,key:SGName,value:AvgScore
public function getSGVoteItemAvgArray($LessonID)
{
// 21条记录
$SGLessonAvgScore=AcademicMasterSGLessonAvgScore::findAll(['LessonID'=>$LessonID]);
$res=[];
if($SGLessonAvgScore===null) {
// 需要先进行平均分计算
$StudentVoteIDArr=AcademicMasterStudentVote::findAll(['LessonID'=>$LessonID])['StudentVoteID'];
$SGItemScoreArr=AcademicMasterSGItemScore::find()->where(['in','StudentVoteID',$StudentVoteIDArr])->all();
$avgScoreArr=[];
for ($i=1;$i<22;$i++)
{
$avgScore[$i]=0.0;
}
$count=count($SGItemScoreArr)/21.0;
foreach ($SGItemScoreArr as $SGItem){
$avgScoreArr[$SGItem['SGVoteID']]+=$SGItem['Score'];
}
for ($i=1;$i<22;$i++)
{
$avgScore[$i]=$avgScoreArr[$i]/$count;
}
// 保存21条记录
$transaction=Yii::$app->db->beginTransaction('SERIALIZABLE');
try {
for ($i = 1; $i < 22; $i++)
{
$model = new AcademicMasterSGLessonAvgScore();
$model['LessonID']=$LessonID;
$model['SGVoteID']=$i;
$model['SGVoteItemAvg']=$avgScoreArr[$i];

if (!$model->save()){
$res['success'] = false;
throw new \Exception('毕业状态保存失败!');
}
}
$transaction->commit();
} catch (\Exception $exception) {
$transaction->rollBack();
$res['data'] = $exception->getMessage();
return $res;
}
}
foreach ($SGLessonAvgScore as $item) {
$SGVoteName=AcademicMasterSGVote::findOne($item['SGVoteID'])['SGVoteName'];
$SGVoteItemAvg=$item['SGVoteItemAvg'];
$res['data'][$SGVoteName]=$SGVoteItemAvg;
}
$res['success'] = true;
return $res;
}
人数及总平均分

backend/modules/api/v1/models/lessonVote/AcademicMasterLessonVoteAnalysis.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
public static function getAcademicMasterLessonVoteAnalysis($LessonID)
{
// 获取评教计算结果
$LessonVoteAnalysis=AcademicMasterLessonVoteAnalysis::findOne(['LessonID'=>$LessonID]);
$res['success'] = false;
if($LessonVoteAnalysis===null)
{ // 需要进行计算
$sql = "
SELECT
count(cc_lesson_student.StudentID) AS 'SelectNum',
c.`VoteNum`,
c.`avgScore`
FROM
(
SELECT
count( k.sum ) AS 'VoteNum',
sum( k.sum ) / count( k.sum ) AS 'avgScore'
FROM
(
SELECT
t.StudentID,
sum( Score ) / 105 * 100 AS sum
FROM
(
SELECT
cc_lesson_student.StudentID,
cc_academic_master_student_vote.StudentVoteID
FROM
cc_lesson_student
LEFT OUTER JOIN cc_academic_master_student_vote ON cc_lesson_student.StudentID = cc_academic_master_student_vote.StudentID
WHERE
cc_lesson_student.LessonID=:LessonID and cc_academic_master_student_vote.LessonID=:LessonID
) AS t,
cc_academic_master_sg_item_score
WHERE
t.StudentVoteID = cc_academic_master_sg_item_score.StudentVoteID
GROUP BY
t.StudentVoteID
) AS k
)as c, cc_lesson_student
WHERE cc_lesson_student.LessonID=:LessonID";
$db = Yii::$app->db;
$data = $db->createCommand($sql)
->bindValue(':LessonID', $LessonID)
->queryAll();
$model=new AcademicMasterLessonVoteAnalysis();
$model['LessonID']=$LessonID;
$model['SelectNum']=$data['SelectNum'];
$model['VoteNum']=$data['VoteNum'];
$model['AvgScore']=$data['AvgScore'];
if (!$model->save()) {
$res['success'] = false;
$res['data'] = $model->errors;
}
$LessonVoteAnalysis=AcademicMasterLessonVoteAnalysis::findOne(['LessonID'=>$LessonID]);
}
$res['data']=$LessonVoteAnalysis;
$res['success'] = true;
return $res;
}

编写SQL语句时结合Navicat视图

文字评教

backend/modules/api/v1/models/lessonVote/AcademicMasterStudentVote.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 根据LessonID返回文字评价
public static function getVoteProposal($LessonID)
{
$proposal=[];
$sql = "
SELECT
cc_academic_master_student_vote.Proposal1,
cc_academic_master_student_vote.Proposal2
FROM
cc_academic_master_student_vote
WHERE
cc_academic_master_student_vote.LessonID =:LessonID";
$db = Yii::$app->db;
$data = $db->createCommand($sql)
->bindValue(':LessonID', $LessonID)
->queryAll();
return array_filter(array_merge($data['Proposal1'],$data['Proposal2']));
}

PHP 要过滤数组中的所有值为空的元素(false、null、’’、0),可直接用 array_filter() 函数。

编写controller

backend/modules/api/v1/controllers/LessonVoteController.php

路由/lesson-vote默认对应LessonVoteController,在main.php里写是为了美化url,路由就是 lesson-votes 了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 获取评教分析
public function actionGetVoteAnalysis()
{
$request = \Yii::$app->request;
if ($request->getIsOptions()) {
return $this->ResponseOptions($this->verbs()['get-vote-analysis']);
}
$LessonID = $request->get("LessonID");
// 获取SG分项平均分
$SGVoteItemAvgArray=AcademicMasterSGLessonAvgScore::getSGVoteItemAvgArray($LessonID);
// 获取评教总平均分及人数
$LessonVoteAnalysis=AcademicMasterLessonVoteAnalysis::getAcademicMasterLessonVoteAnalysis($LessonID);
// 获取文字评价
$proposal=AcademicMasterStudentVote::getVoteProposal($LessonID);

$res['success']=true;
if(!$LessonVoteAnalysis['success']||!$SGVoteItemAvgArray['success']){
$res['success']=false;
$res['data']='LessonVoteAnalysis/SGVoteItemAvgArray';
}
$res['data']=array_merge($LessonVoteAnalysis['data'],$SGVoteItemAvgArray['data']);
$res['data']['proposal']=$proposal;
return $res;
}

image-20201216220627346

请求后端 API 之前也需要给基础教师加入权限

或者在backend/modules/api/v1/controllers/base/BaseController.php中去掉注释

image-20201218114223567

需要注意 Divided by 0 的情况, == 0=== 0的区别

毕业设计模块

学生账户登录,本科毕业设计模块(需要管理员先修改“毕业设计“的进度),学生打印表格时保留文档样式,以word格式导出。

解决方案

  • 在后端生成 word 文件,传输到前端。src\views\graduateProject\ExportGraduateFile.vue
  • 在前端拿到表格数据,生成 word。backend/modules/api/v1/controllers/GraduateProjectController.php 的 actionExportGraduateFile($fid) 函数

    <el-main> :主要区域容器。\ :底栏容器。

参考https://www.shuzhiduo.com/A/gVdneg9N5W/

需要的插件:docxtemplater、jszip-utils、jszip、FileSaver。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// 下载题目审批表
downloadTopicApprovalForm(i) {
let _this = this;
// 判断有无附加商品来选择word模版
// 读取并获得模板文件的二进制内容
let filePath="";
switch(i){
case 1:
filePath="static/file/TopicApprovalForm.docx";
break;
case 2:
filePath="static/file/MidtermCheckForm.docx";
break;
case 3:
filePath="static/file/TeacherScoreForm.docx";
break;
case 4:
filePath="static/file/ReplyRecordForm.docx";
break;
}
JSZipUtils.getBinaryContent(filePath, function (error, content) {
// console.log("-----", content);
// input.docx是模板。我们在导出的时候,会根据此模板来导出对应的数据
// 抛出异常
if (error) {
throw error;
}
// 创建一个JSZip实例,内容为模板的内容
let zip = new JSZip(content);
// console.log("+++++", zip);
// 创建并加载docxtemplater实例对象
let doc = new Docxtemplater();
// console.log("/////", doc);
doc.loadZip(zip);
// console.log("=====", doc);
// 设置模板变量的值
doc.setData({
// 导出价格表全部信息
..._this.studentInfoForm,
// 导出价格表商品信息
..._this.infoForm,
});
try {
// 用模板变量的值替换所有模板变量
doc.render();
} catch (error) {
// 抛出异常
let e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties,
};
console.log(JSON.stringify({ error: e }));
throw error;
}
// 生成一个代表docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
let out = doc.getZip().generate({
type: "blob",
mimeType:
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
});
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, _this.studentInfoForm.StudentName + "-题目审批表.docx");
});
},

undefined问题在前端解决;

学院由后端传值时判断backend/modules/api/v1/models/graduateProject/GraduateProjectStudentModel.php getStudentInfo($id)

实验室网站

mstsc /admin /v:192.168.190.191

dbis_atd_record表

backend\models\AttendanceRule\Attendance.php

backend\controllers\attendance\AtdOffdaysController.php

time-insert\time_insert.php

frontend\controllers\TimingInsertController.php

考勤管理导入节假日

新增页面导入数据库数据

脚本:\192.168.190.206\Personal\xulicheng\XLC-DELL-530\DBISWork\DBISWEB