引言
项目中需要对用户的操作记录备份起来,如果后端出现任何问题,可以从前端把用户操作记录提取出来,然后后期把数据导入到数据库
功能
网络监测
1.监测每条记录的提交情况,分辨出是客户端和服务器问题;
2.呼吸灯动态显示当前整体提交状况;
3.监控中心可以查看每条记录的提交情况;
4.监控中心可以控制对每条记录的监控状态;
5.监控中心可以切换网络监测的开闭模式;
智能提交
1.监控中心每隔10秒监测一次提交情况,如果发现有没有提交成功的内容,会在监听到有提交成功的时刻,自动提交所有没有提交成功的记录;
2.监控中心可以切换智能提交的开闭模式;
自动备份
1.监控中心会在最后的时刻将所有用户的操作记录下载到本地;
2.监控中心可以切换自动备份的开闭模式;
设计思路
1.首先各个题型组件在调取服务之后,通过服务返回的值来判断提交情况,并记录操作,如果有问题则为服务端故障,同时更新网络状态;
2.如果调取服务出现任何异常导致无法获取返回值,则为客户端问题,记录操作并标记,同时更新网络状态;
3.呼吸灯实时监测网络状态,累计3次故障后客户端报警;
4..进入监控中心,读取所有操作记录及其标记,显示提交情况,同时根据具体情况选择性的关闭对应的记录的监测(否则会一直报警);
5.在操作的过程中,如果发现有没有提交成功的操作,同时监测到最近有提交成功,那么就把之前没有提交成功的操作重新自动提交;
6..监控中心如果出现很多问题或者关键性问题,可以开启备份操作下载功能,用户操作完成之后会把操作自动下载到本地;
代码说明
各题目组件 ts
/* 向后台提交学生答案 */
public @H_404_51@updateStudentAnswerToBackend(answer: Answer) {
let url: string = "examinationEvaluation-web/onlineExam/updatePaperRecordByRecord" + this.authGuardService.getTicket();
let body: string = JSON.stringify(answer);
this.exampapaerservice.post(url,body).subscribe(
res => {
if (res.json().code == "1111" || res.json().data != true) {
this.backupAnswer(answer,1); //备份答案
} else {
this.backupAnswer(answer,0); //备份答案
}
}
);
console.log("学生提交答案-radio");
}
/* 备份用户答案 */
private @H_404_51@backupAnswer(answer: Answer,status: number) {
//备份答案记录
console.log("answer-backup-log---"+ExamPaperService.userOperationAmount);
ExamPaperService.userOperationAmount++; //操作序号递增
localStorage.setItem("userOperationAmount",ExamPaperService.userOperationAmount.toString()); //记录操作序号
localStorage.setItem(answer.studentId + ExamPaperService.userOperationAmount,JSON.stringify(answer) + status); //记录操作内容
//记录提交情况
let flag: boolean = true;
let ns: string[] = JSON.parse(localStorage.getItem("NetWorkState"));
for (var i = 0; i < ns.length; i++) {
if (answer.questionMainId == ns[i]) { flag = false; }
}
if (status != 0 && flag) {
ns[0] = (parseInt(ns[0]) + 1).toString();
localStorage.setItem("NetWorkState",JSON.stringify(ns));
}
}
公共服务 ts
/* 处理失败提交 */
public @H_404_51@handleUpdateAnswerError(error: Response) {
//保存用户答案到localStorage
let answer: Answer = <Answer>(JSON.parse(ExamPaperService.studentAnswer));
this.backupAnswer(answer,2);
return Observable.throw(error.json().error || '网络问题:server error');
}
/* 备份用户答案 */
private @H_404_51@backupAnswer(answer: Answer,status: number) {
//备份答案记录
console.log("answer-backup-log---" + ExamPaperService.userOperationAmount);
ExamPaperService.userOperationAmount++; //操作序号递增
localStorage.setItem("userOperationAmount",JSON.stringify(ns));
}
}
监控中心 ts
ngOnInit() {
//获得当前操作数量
this.getUserOperationAmount();
//初始化网络状态
let networkList: string[] = [];
networkList.push("0");
localStorage.setItem("NetWorkState",JSON.stringify(networkList));
//初始化备份模式
localStorage.setItem("NetWorkBackupPattern","0");
//开始监测
this.startMonitorNetworkStatus();
}
/* 开始监测网络状态 */
startMonitorNetworkStatus() {
this.timer = setInterval(() => { this.networkState = parseInt(JSON.parse(localStorage.getItem("NetWorkState"))[0]); let el: Element = document.getElementById("networkstate"); if (this.networkState == 1) { el.setAttribute("class","breathe-yellow-btn"); } else if (this.networkState == 3) { el.setAttribute("class","breathe-red-btn"); } else if (this.networkState > 3) { this.display_error = true; let ns: string[] = JSON.parse(localStorage.getItem("NetWorkState")); ns[0] = "3"; localStorage.setItem("NetWorkState",JSON.stringify(ns)); } },1000); } /* 刷新状态 */ @H_404_51@refreshStatus() { @H_404_51@this.@H_404_51@getAnswerStatus(); @H_404_51@this.@H_404_51@getMonitorStatus(); } /* 清除缓存 */ @H_404_51@clearLocalStorage() { @H_404_51@localStorage.@H_404_51@clear(); } /* 获得题目提交状态 */ @H_404_51@getAnswerStatus() { @H_404_51@console.@H_404_51@log("Start-getAnswerStatus-------"); @H_404_51@for (var i = 0; i < parseInt(localStorage.getItem("userOperationAmount")); i++) { @H_404_51@let @H_404_51@answerLog: @H_404_51@string = @H_404_51@localStorage.@H_404_51@getItem(localStorage.getItem("userId") + i); @H_404_51@let @H_404_51@answerStatus = @H_404_51@answerLog.@H_404_51@substring(answerLog.length - 1); @H_404_51@let @H_404_51@answer: @H_404_51@Answer = @H_404_51@JSON.@H_404_51@parse(answerLog.substring(0,answerLog.length - 1)); @H_404_51@if (answerStatus == "0") { @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("network" + answer.questionMainId); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","badge badge-success badge_postion"); @H_404_51@el.@H_404_51@innerHTML = "成功提交"; } } @H_404_51@if (answerStatus == "1") { @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("network" + answer.questionMainId); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","badge badge-warning badge_postion"); @H_404_51@el.@H_404_51@innerHTML = "客户端故障"; } } @H_404_51@if (answerStatus == "2") { @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("network" + answer.questionMainId); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","badge badge-important badge_postion"); @H_404_51@el.@H_404_51@innerHTML = "服务器故障"; } } } } /* 获得检测状态 */ @H_404_51@getMonitorStatus() { @H_404_51@console.@H_404_51@log("Start-getMonitorStatus-------"); @H_404_51@let @H_404_51@idList: @H_404_51@string[] = @H_404_51@JSON.@H_404_51@parse(localStorage.getItem("NetWorkState")); @H_404_51@for (var i = 1; i < idList.length; i++) { @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("monitor" + idList[i]); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","btn btn-danger btn-xs pull-right"); @H_404_51@el.@H_404_51@innerHTML = "监测已停止"; } } } /* 获得操作记录数量 */ @H_404_51@getUserOperationAmount() { @H_404_51@let @H_404_51@amount: @H_404_51@number = 1; @H_404_51@while (localStorage.getItem("userId" + amount)!=null) { @H_404_51@amount++; } @H_404_51@localStorage.@H_404_51@setItem("userOperationAmount",(amount-1).toString()); } /* 切换监测状态 */ @H_404_51@changeMonitorStatus(monitorId: string) { @H_404_51@console.@H_404_51@log("Start-changeMonitorStatus-------"); @H_404_51@let @H_404_51@exitFlag: @H_404_51@boolean = @H_404_51@true; @H_404_51@let @H_404_51@questionId = @H_404_51@monitorId.@H_404_51@substring(7,monitorId.length); @H_404_51@let @H_404_51@idList: @H_404_51@string[] = @H_404_51@JSON.@H_404_51@parse(localStorage.getItem("NetWorkState")); @H_404_51@for (var i = 0; i < idList.length; i++) { @H_404_51@if (questionId == idList[i]) { //切换为开始 @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("monitor" + idList[i]); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","btn btn-primary btn-xs pull-right"); @H_404_51@el.@H_404_51@innerHTML = "正在监测中"; } @H_404_51@idList.@H_404_51@splice(i,1); @H_404_51@localStorage.@H_404_51@setItem("NetWorkState",JSON.stringify(idList)); @H_404_51@exitFlag = @H_404_51@false; } } //切换为停止 @H_404_51@if (exitFlag) { @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById(monitorId); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","btn btn-danger btn-xs pull-right"); @H_404_51@el.@H_404_51@innerHTML = "监测已停止"; } @H_404_51@idList.@H_404_51@push(questionId); @H_404_51@localStorage.@H_404_51@setItem("NetWorkState",JSON.stringify(idList)); } } @H_404_51@private @H_404_51@backupPatternStatus: @H_404_51@boolean = @H_404_51@false; //备份模式状态 /* 切换备份模式 */ @H_404_51@changeBackupPattern() { @H_404_51@if (this.backupPatternStatus) { //切换为不备份 @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("networkbackuppattern"); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","btn btn-info pull-left"); @H_404_51@el.@H_404_51@innerHTML = "非备份模式"; @H_404_51@localStorage.@H_404_51@setItem("NetWorkBackupPattern","0"); @H_404_51@this.@H_404_51@backupPatternStatus = @H_404_51@false; } } @H_404_51@else { //切换为开始备份 @H_404_51@let @H_404_51@el = @H_404_51@document.@H_404_51@getElementById("networkbackuppattern"); @H_404_51@if (el != null) { @H_404_51@el.@H_404_51@setAttribute("class","btn btn-warning pull-left"); @H_404_51@el.@H_404_51@innerHTML = "备份模式中"; @H_404_51@localStorage.@H_404_51@setItem("NetWorkBackupPattern","1"); @H_404_51@this.@H_404_51@backupPatternStatus = @H_404_51@true; } } } /* --------------------------------------------------------- */ @H_404_51@private @H_404_51@openNum: @H_404_51@number = 0;//点击三次可以打开 /* 打开模态框 */ @H_404_51@openModal(modal: HTMLElement) { @H_404_51@this.@H_404_51@openNum++; @H_404_51@if (this.openNum > 2) { @H_404_51@this.@H_404_51@refreshStatus(); @H_404_51@modal.@H_404_51@style.@H_404_51@visibility = '@H_404_51@visible'; @H_404_51@this.@H_404_51@openNum = 0; } } /* 关闭模态框 */ @H_404_51@close(modal: HTMLElement) { @H_404_51@modal.@H_404_51@style.@H_404_51@visibility = '@H_404_51@hidden'; } /* 拖动模态框 */ @H_404_51@draggable() { @H_404_51@$('.modal-dialog').@H_404_51@draggable(); }
本地备份下载 ts
/* 创建备份文本并下载 */
createBackupText() {
let userLog: string = "";
for (var i = 0; i < parseInt(localStorage.getItem("userOperationAmount")); i++){
userLog = userLog +localStorage.getItem(localStorage.getItem("userId")+i);
}
let data = new Blob([userLog],{ type: 'application/json' })
var link = document.createElement("a");
link.setAttribute("href",window.URL.createObjectURL(data));
link.setAttribute("download",localStorage.getItem("userId") + '.json');
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
console.log("------ Start Create File And Download --------");
}
小结
要针对不同的业务场景采取不同的解决方案,尽可能考虑全面