教务管理系统工作总结
1.数据库设计阶段
1.参与数据库字段的设计,外键的存储方式,以及表之间的引用关系
2.根据建成的数据库,编写数据库设计文档。
2.概要设计阶段
1.参与编写《教务系统-概要设计说明书》,分析教师权限功能并设计功能流程图。
用到的技术
使用visio完成功能流程图的设计
3.编码阶段
我主要负责课程管理模块,选择题题库模块,技能完善模块,企业报名和报名结果模块,学生注册功能,个人生涯,班级历史变更
1.管理员:课程管理模块
1.点击新增课程按钮,弹出课程添加模态框。填写合理的课程名称后点击确定进行添加(如果是添加过的但是被删除了,则将被删除的记录重新修改为可用状态)
2.点击修改按钮,弹出模态框。填写正确的课程名称后点击确定按钮进行修改(如果修改的名称已经存在且处于可用状态,提示修改失败。如果修改的名称已经存在但处于不可用状态,将其状态改为可用,将修改之前的设置为不可用状态)
3.点击删除(如果课程在被别处引用,提示不可删除)
2.教师:选择题题库管理模块
1.点击查看大题题库 转向大题题库管理页面
2.点击添加单选题 弹出模态框
3.可根据 课程名和题干进行模糊查询
4.点击导出选择题表头,下载excel格式的表头
5.选择所属科目后点击导入选择题,可以批量导入选择题
接口:/**
*
*/
package com.hpe.ts.utils.other;
/**
* @Description:TODO描述:
* @author: 何思勇
* @date: 2018年11月7日 上午10:05:28
*/
public interface QuestionRedis <T>{
/**
*
* @Description:TODO描述: Question存入redis
* @author: 何思勇
* @date: 2018年11月7日 上午11:47:36
* @param question
* @return
*/
void putQuestion(T question);
/**
*
* @Description:TODO描述: 从redis取出单个题
* @author: 何思勇
* @date: 2018年11月7日 上午10:10:57
* @param question
* @return
*/
T getQuestion(T question);
}
实现:
package com.hpe.ts.utils.other;
import java.util.List;
import java.util.Set;
import javax.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import com.hpe.ts.enums.CommonStatus;
import com.hpe.ts.pojo.ChoiceQuestion;
/**
*
* @Description:TODO描述: 选择题redis操作类
* @author: 何思勇
* @date: 2018年11月6日 下午7:01:53
*/
@Component
public class ChoiceQuestionRedis implements QuestionRedis<ChoiceQuestion> {
@Resource(name = "redisTemplate")
private RedisTemplate<String, Object> redisTemplate;
@Override
public void putQuestion(ChoiceQuestion choiceQuestion) {
redisTemplate.opsForValue().set("c:" + choiceQuestion.getCourseId() + ":" + choiceQuestion.getDifficulty() + ":"
+ choiceQuestion.getDisable() + ":" + choiceQuestion.getChoiceId(), choiceQuestion);
}
@Override
public ChoiceQuestion getQuestion(ChoiceQuestion choiceQuestion) {
return (ChoiceQuestion) redisTemplate.opsForValue()
.get("c" + ":" + choiceQuestion.getCourseId() + ":" + choiceQuestion.getDifficulty() + ":"
+ choiceQuestion.getDisable() + ":" + choiceQuestion.getChoiceId());
}
/**
*
* @Description:TODO描述: 通配方法获取key集合根据课程号和难度进行模糊搜索
* @author: 何思勇
* @date: 2018年11月7日 下午2:10:49
* @param courseId
* @param difficulty
* @param questionId
* @param disable
* @return
*/
public Set<String> keys(Integer courseId, Integer difficulty, CommonStatus disable, Integer questionId) {
String str = null;
if (questionId != null) {
str = "c" + ":" + "*" + questionId;
} else {
str = "c" + ":" + courseId + ":" + difficulty + ":" + disable + "*";
}
return redisTemplate.keys(str);
}
/**
*
* @Description:TODO描述: 通配方法获取value集合根据课程号和难度进行模糊搜索时题号赋值null
* @author: 何思勇
* @date: 2018年11月7日 上午11:28:17
* @param courseId
* @param difficulty
* @param questionId
* @return
*/
public List<Object> getQuestions(Integer courseId, Integer difficulty, Integer questionId) {
Set<String> keys = keys(courseId, difficulty, CommonStatus.ENABLE, questionId);
return redisTemplate.opsForValue().multiGet(keys);
}
/**
*
* @Description:TODO描述: 更新redis中选择题的value
* @author: 何思勇
* @date: 2018年11月7日 下午9:35:11
* @param str
* @param cq
*/
public void updataChoiceValue(String str, ChoiceQuestion cq) {
redisTemplate.opsForValue().set(str, cq);
}
/**
* @Description:TODO描述: 更新redis中选择题的key
* @author: 何思勇
* @date: 2018年11月7日 下午10:13:59
* @param str
* @param str1
*/
public void updataKey(String oldKey, String newKey) {
redisTemplate.rename(oldKey, newKey);
}
}
遇到的问题:
1.导入选择题时 如果导入出错 无法将错误定位到单元格。
2.上传文件的同时传递其他参数
3.MySql5.7group by 问题[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'information_schema.PROFILING.SEQ' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
解决:
1.使用孙士林修改后的导入工具类(思路为将异常信息获取,在工具类中接收后获取需要的信息 (第i行j列出现…),然后放到map中,输出到导入失败前端提示中)
2.创建一个空的FormData对象,然后再用append方法逐个添加键值对:
var data = new FormData();
data.append(‘uploadpic’, $(’#licensefile’)[0].files[0]);//可以是文件
data.append(‘type’,“license”);
// 导入选择题题库
function uploadCQ() {
var data = new FormData();
var courseId = vm.courseId;
var difficulty = vm.difficulty;
if (!checkFileExt(($('#uploadCQ')[0].files[0]).name)) {
alert('文件格式有误,请导入.xls或.xlsx后缀文件。');
return;
}
data.append('CQFile', $('#uploadCQ')[0].files[0]);
data.append('courseId', vm.courseId);
data.append('difficulty', vm.difficulty);
$.ajax({
type : "post",
url : baseURL + "/teacher/choiceQuestion/uploadCQBatch",
processData : false,
contentType : false,
data : data,
success : function(data1) {
if (data1.result > 0) {
layer.msg('上传成功!');
$("#jqGrid").jqGrid("setGridParam").trigger("reloadGrid");
} else {
alert(data1.err);
}
$('#uploadCQ').val('');
}
});
}
3.去掉ONLY_FULL_GROUP_BY,重新设置值。
set @@global.sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,
NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
学生
1.完善技能模块
1.点击完善技能 进入技能完善标签页。左侧显示教师添加的技能名称全部词条;点击技能词条可将技能加入到个人技能框中,下拉选择好难度(难度最大为教师添加技能时设置的最大级别) 点击提交按钮,将技能存储到个人技能中(可回显 也可以在个人生涯标签页中查看)
2.在技能框中点击(x)可直接移除技能,在技能等级下拉中选择级别然后点击提交按钮 可以修改技能的等级。
遇到的问题
1.词条用span标签实现,开始只能存技能名称,并不能将技能的最大等级隐藏在词条中。
解决
1.用html5中新增的data-xxx属性,将最大等级存储在词条的span标签中然后在js中用var level = $("#spanid").attr(“data-xxx”)来获取。
2.查看班级模块
点开此标签页可以查看学生自己的班级变动历史和当前所在班级
3.企业报名模块
1.点击企业报名 弹出标签页
展示学生所选方向跟企业发布的招聘信息方向一致的招聘信息(对于过期的招聘信息 只显示过期未超过两周的信息)
2.对于招聘已经开始的招聘 选择岗位后可以点击报名 进行对相关招聘的报名。招聘未开始 和 招聘结束均不能点击
遇到的问题
1.sql语句出现问题
问题sql:
select r.*,e.name eName,e.introduce eIntroduce,e.address
eAddress,d.name dName,s.sign_up_id sId,s.pass,s.position_id spid from recruitment r
LEFT
JOIN
direction d ON r.direction_id = d.direction_id
LEFT JOIN enterprise
e
ON e.enterprise_id = r.enterprise_id
LEFT JOIN sign_up s ON
s.recruitment_id = r.recruitment_id
where s.student_id = #{stuId}
解决:
select r.*,e.name eName,e.introduce eIntroduce,e.address
eAddress,d.name dName,s.sign_up_id sId,s.pass,s.position_id spid from recruitment r
LEFT
JOIN
direction d ON r.direction_id = d.direction_id
LEFT JOIN enterprise
e
ON e.enterprise_id = r.enterprise_id
LEFT JOIN sign_up s ON
s.recruitment_id = r.recruitment_id and s.student_id = #{stuId}
4.报名结果
1.点开标签页可以查看自己报名的企业以及录取结果(已经录取,未录取,等待录取),根据请求的数据通过js进行显示。
5.学生注册
完成学生注册功能,注册后跳转到登录页面。
6.个人生涯
function download() {
$('#download').hide();
$('.father').removeClass('father');
$('#father').attr('style', 'background-color: #ffffff;');
$('.breadcrumb').hide();
$('#hr').hide();
var w = $("#father").width();
var h = $("#father").height();
//要将 canvas 的宽高设置成容器宽高的 2 倍
var canvas = document.createElement("canvas");
canvas.width = w * 2;
canvas.height = h * 2;
canvas.style.width = w + "px";
canvas.style.height = h + "px";
var context = canvas.getContext("2d");
//然后将画布缩放,将图像放大两倍画到画布上
context.scale(2,2);
html2canvas(document.querySelector("#father"), {
canvas: canvas,
onrendered : function(canvas) {
var contentWidth = canvas.width;
var contentHeight = canvas.height;
// 一页pdf显示html页面生成的canvas高度;
var pageHeight = contentWidth / 592.28 * 841.89;
// 未生成pdf的html页面高度
var leftHeight = contentHeight;
// 页面偏移
var position = 0;
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的宽高
var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0);
var pdf = new jsPDF('', 'pt', 'a4');
// 有两个高度需要区分,一个是html页面的实际高度,和生成pdf的页面高度(841.89)
// 当内容未超过pdf一页显示的范围,无需分页
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight);
} else {
while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth,
imgHeight)
leftHeight -= pageHeight;
position -= 841.89;
// 避免添加空白页
if (leftHeight > 0) {
pdf.addPage();
}
}
}
pdf.save(stu.student.stuName+'个人生涯.pdf');
}
});
使用到的技术:
jQuery,SSM,Vue.js,Ajax
MySql,Html2canvas
收获与不足
通过这个项目的磨练,意识到团队协作的重要性。从项目一开始的不从下手,到最后项目成功完成。少不了团队每个人的努力。
在这个过程中,我学到了很多新东西,一开始对于网站开发,完全是用jsp进行页面渲染,这个项目教会我怎么使用js和html完成来更高效的完成界面的渲染与值传递。对ssm框架有了更深一层的理解。
同时,也感到了压力,很多东西都从未接触过,生怕自己完不成而耽误项目进度。幸运的是有一帮乐于助人的队员,互相帮忙,共度难关。