基于SpringBoot+VUE(PC端+小程序端)的智能在线考试系统毕业设计_基于vue的在线考试应用的设计与实现整体流程框图

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新大数据全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上大数据知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注大数据)
img

正文

| 考试记录 | 查看答卷记录和试卷信息 |
| 错题本 | 答错题目会自动进入错题本,显示题目基本信息 |
| 个人信息 | 显示学生个人资料 |
| 更新信息 | 修改个人资料、头像 |
| 个人动态 | 显示用户最近的个人动态 |
| 消息中心 | 用于接收管理员发送的消息 |

五,数据库设计

仅展示部分数据库字段设计

5.1 试卷表

字段名类型注释
idint
namevarchar试卷名称
subject_idint学科
paper_typeint试卷类型( 1.固定试卷 4.时段试卷 6.任务试卷 )
grade_levelint年级
scoreint试卷总分(千分制)
question_countint题目数量
suggest_timeint建议时长(分钟)
limit_start_timedatetime时段试卷 开始时间
limit_end_timedatetime时段试卷 结束时间
frame_text_content_idint试卷框架 内容为JSON
create_userint
create_timedatetime
deletedbit
task_exam_idint

5.2 试卷答案表

字段名类型注释
idint
exam_paper_idint
paper_namevarchar试卷名称
paper_typeint试卷类型( 1.固定试卷 4.时段试卷 6.任务试卷 )
subject_idint学科
system_scoreint系统判定得分
user_scoreint最终得分(千分制)
paper_scoreint试卷总分
question_correctint做对题目数量
question_countint题目总数量
do_timeint做题时间(秒)
statusint试卷状态(1待判分 2完成)
create_userint学生
create_timedatetime提交时间
task_exam_idint

5.3 题目表

字段名类型注释
idint
question_typeint1.单选题 2.多选题 3.判断题 4.填空题 5.简答题
subject_idint学科
scoreint题目总分(千分制)
grade_levelint级别
difficultint题目难度
correcttext正确答案
info_text_content_idint题目 填空、 题干、解析、答案等信息
create_userint创建人
statusint1.正常
create_timedatetime创建时间
deletedbit

5.4 学科表

字段名类型注释
idint
namevarchar语文 数学 英语 等
levelint年级 (1-12) 小学 初中 高中 大学
level_namevarchar一年级、二年级等
item_orderint排序
deletedbit

5.5 用户表

字段名类型注释
idint
user_uuidvarchar
user_namevarchar用户名
passwordvarchar
real_namevarchar真实姓名
ageint
sexint1.男 2女
birth_daydatetime
user_levelint学生年级(1-12)
phonevarchar
roleint1.学生 3.管理员
statusint1.启用 2禁用
image_pathvarchar头像地址
create_timedatetime
modify_timedatetime
last_active_timedatetime
deletedbit是否删除
wx_open_idvarchar微信openId

5.6 用户日志表

字段名类型注释
idint
user_idint用户id
user_namevarchar用户名
real_namevarchar真实姓名
contenttext内容
create_timedatetime时间

其他表的设计省略…

六,系统展示

6.1 后台管理

主页

用户管理

试卷管理

题目管理

添加题目

添加试卷

任务管理

教育管理

成绩管理

6.2 学生端

首页登录与注册

学生端首页

试卷中心

考试记录

错题本

个人中心

6.3 小程序端

登录与注册

首页

试卷考试

考试记录

我的

七,核心代码展示



@Service
public class TaskExamServiceImpl extends BaseServiceImpl<TaskExam> implements TaskExamService {

    protected final static ModelMapper modelMapper = ModelMapperSingle.Instance();
    private final TaskExamMapper taskExamMapper;
    private final TextContentService textContentService;
    private final ExamPaperMapper examPaperMapper;

    @Autowired
    public TaskExamServiceImpl(TaskExamMapper taskExamMapper, TextContentService textContentService, ExamPaperMapper examPaperMapper) {
        super(taskExamMapper);
        this.taskExamMapper = taskExamMapper;
        this.textContentService = textContentService;
        this.examPaperMapper = examPaperMapper;
    }

    @Override
    public PageInfo<TaskExam> page(TaskPageRequestVM requestVM) {
        return PageHelper.startPage(requestVM.getPageIndex(), requestVM.getPageSize(), "id desc").doSelectPageInfo(() ->
                taskExamMapper.page(requestVM)
        );
    }

    @Override
    @Transactional
    public void edit(TaskRequestVM model, User user) {
        ActionEnum actionEnum = (model.getId() == null) ? ActionEnum.ADD : ActionEnum.UPDATE;
        TaskExam taskExam = null;
        if (actionEnum == ActionEnum.ADD) {
            Date now = new Date();
            taskExam = modelMapper.map(model, TaskExam.class);
            taskExam.setCreateUser(user.getId());
            taskExam.setCreateUserName(user.getUserName());
            taskExam.setCreateTime(now);
            taskExam.setDeleted(false);

            //保存任务结构
            TextContent textContent = textContentService.jsonConvertInsert(model.getPaperItems(), now, p -> {
                TaskItemObject taskItemObject = new TaskItemObject();
                taskItemObject.setExamPaperId(p.getId());
                taskItemObject.setExamPaperName(p.getName());
                return taskItemObject;
            });
            textContentService.insertByFilter(textContent);
            taskExam.setFrameTextContentId(textContent.getId());
            taskExamMapper.insertSelective(taskExam);

        } else {
            taskExam = taskExamMapper.selectByPrimaryKey(model.getId());
            modelMapper.map(model, taskExam);

            TextContent textContent = textContentService.selectById(taskExam.getFrameTextContentId());
            //清空试卷任务的试卷Id,后面会统一设置
            List<Integer> paperIds = JsonUtil.toJsonListObject(textContent.getContent(), TaskItemObject.class)
                    .stream()
                    .map(d -> d.getExamPaperId())
                    .collect(Collectors.toList());
            examPaperMapper.clearTaskPaper(paperIds);

            //更新任务结构
            textContentService.jsonConvertUpdate(textContent, model.getPaperItems(), p -> {
                TaskItemObject taskItemObject = new TaskItemObject();
                taskItemObject.setExamPaperId(p.getId());
                taskItemObject.setExamPaperName(p.getName());
                return taskItemObject;
            });
            textContentService.updateByIdFilter(textContent);
            taskExamMapper.updateByPrimaryKeySelective(taskExam);
        }

        //更新试卷的taskId
        List<Integer> paperIds = model.getPaperItems().stream().map(d -> d.getId()).collect(Collectors.toList());
        examPaperMapper.updateTaskPaper(taskExam.getId(), paperIds);
        model.setId(taskExam.getId());
    }

    @Override
    public TaskRequestVM taskExamToVM(Integer id) {
        TaskExam taskExam = taskExamMapper.selectByPrimaryKey(id);
        TaskRequestVM vm = modelMapper.map(taskExam, TaskRequestVM.class);
        TextContent textContent = textContentService.selectById(taskExam.getFrameTextContentId());
        List<ExamResponseVM> examResponseVMS = JsonUtil.toJsonListObject(textContent.getContent(), TaskItemObject.class).stream().map(tk -> {
            ExamPaper examPaper = examPaperMapper.selectByPrimaryKey(tk.getExamPaperId());
            ExamResponseVM examResponseVM = modelMapper.map(examPaper, ExamResponseVM.class);
            examResponseVM.setCreateTime(DateTimeUtil.dateFormat(examPaper.getCreateTime()));
            return examResponseVM;
        }).collect(Collectors.toList());
        vm.setPaperItems(examResponseVMS);
        return vm;
    }

    @Override
    public List<TaskExam> getByGradeLevel(Integer gradeLevel) {
        return taskExamMapper.getByGradeLevel(gradeLevel);
    }
}




@Service
public class AuthenticationServiceImpl implements AuthenticationService {


    private final UserService userService;
    private final SystemConfig systemConfig;

    @Autowired
    public AuthenticationServiceImpl(UserService userService, SystemConfig systemConfig) {
        this.userService = userService;
        this.systemConfig = systemConfig;
    }


    /**
     * @param username username
     * @param password password
     * @return boolean
     */
    @Override
    public boolean authUser(String username, String password) {
        User user = userService.getUserByUserName(username);
        return authUser(user, username, password);
    }


    @Override
    public boolean authUser(User user, String username, String password) {
        if (user == null) {
            return false;
        }
        String encodePwd = user.getPassword();
        if (null == encodePwd || encodePwd.length() == 0) {
            return false;
        }
        String pwd = pwdDecode(encodePwd);
        return pwd.equals(password);
    }

    @Override
    public String pwdEncode(String password) {
        return RsaUtil.rsaEncode(systemConfig.getPwdKey().getPublicKey(), password);
    }

    @Override
    public String pwdDecode(String encodePwd) {
        return RsaUtil.rsaDecode(systemConfig.getPwdKey().getPrivateKey(), encodePwd);
    }


}

<view class="exam-page">
  <view class="view-wrap">
    <view class="exam-count-down">{{remainTimeStr}}</view>
  </view>
  <view class="view-wrap-hidden">
  </view>

  <view>
    <view class="exam-name-title">
      <h1>{{form.name}}</h1>
    </view>
    <form bindsubmit='formSubmit'>
      <i-panel title="{{titleItem.name}}" wx:for="{{form.titleItems}}" wx:for-item="titleItem" wx:key="{{titleItem.name}}" i-class="exam-panel-title">
        <i-cell-group i-class="exam-cell">
          <i-cell wx:for="{{titleItem.questionItems}}" wx:key="{{titleItem.id}}" wx:for-item="questionItem">

            <view wx:if="{{questionItem.questionType === 1}}">
              <rich-text nodes="{{questionItem.itemOrder}}. {{questionItem.title}}" />
              <radio-group class="radio-group" name="{{questionItem.itemOrder}}_{{questionItem.id}}_{{questionItem.questionType}}">
                <label class="radio" wx:for="{{questionItem.items}}" wx:key="{{questionItem.prefix}}" wx:for-item="radioItem" class="exam-radio-item-label">
                  <radio color="#2d8cf0" value="{{radioItem.prefix}}" checked="{{radioItem.checked}}" class="exam-item-left" />
                  <rich-text nodes="{{radioItem.prefix}}. {{radioItem.content}}" class="exam-item-left" />
                </label>
              </radio-group>
            </view>
            <view wx:elif="{{questionItem.questionType === 2}}">
              <rich-text nodes="{{questionItem.itemOrder}}. {{questionItem.title}}" class="exam-item-left" style="line-height:35px" />
              <checkbox-group class="exam-item-left" style="margin-left:10px" name="{{questionItem.itemOrder}}_{{questionItem.id}}_{{questionItem.questionType}}">
                <label wx:for="{{questionItem.items}}" wx:key="{{questionItem.prefix}}" wx:for-item="radioItem" class="exam-radio-item-label">
                  <checkbox color="#2d8cf0" value="{{radioItem.prefix}}" checked="{{radioItem.checked}}" class="exam-item-left" />
                  <rich-text nodes="{{radioItem.prefix}}. {{radioItem.content}}" class="exam-item-left" />
                </label>
              </checkbox-group>
            </view>
            <view wx:elif="{{questionItem.questionType === 3}}">
              <rich-text nodes="{{questionItem.itemOrder}}. {{questionItem.title}}" class="exam-item-left" style="line-height:35px" />
              <radio-group class="radio-group" class="exam-item-left" style="margin-left:10px" name="{{questionItem.itemOrder}}_{{questionItem.id}}_{{questionItem.questionType}}">
                <label class="radio" wx:for="{{questionItem.items}}" wx:key="{{questionItem.prefix}}" wx:for-item="radioItem" class="exam-radio-item-label">
                  <radio color="#2d8cf0" value="{{radioItem.prefix}}" checked="{{radioItem.checked}}" class="exam-item-left" />
                  <rich-text nodes="{{radioItem.content}}" class="exam-item-left" />
                </label>
              </radio-group>
            </view>
            <view wx:elif="{{questionItem.questionType === 4}}">
              <rich-text nodes="{{questionItem.itemOrder}}. {{questionItem.title}}" />
              <view class="exam-input-contain" wx:for="{{questionItem.items}}" wx:key="{{questionItem.prefix}}" wx:for-item="inputItem" wx:for-index="idx">
                <view class="exam-input-contain-label">{{inputItem.prefix}}</view>
                <input class="exam-input-contain-content" maxlength="-1" name="{{questionItem.itemOrder}}_{{questionItem.id}}_{{questionItem.questionType}}_{{idx}}" />
              </view>
            </view>
            <view wx:else>
              <rich-text nodes="{{questionItem.itemOrder}}. {{questionItem.title}}" />
              <view class="exam-textarea-contain">
                <textarea placeholder="答案" maxlength="-1" name="{{questionItem.itemOrder}}_{{questionItem.id}}_{{questionItem.questionType}}"></textarea>
              </view>
            </view>
          </i-cell>
        </i-cell-group>
      </i-panel>

      <view>
        <button class="i-btn  i-btn-primary i-btn-square" form-type='submit'>提交</button>
      </view>

      <i-action-sheet visible="true" visible="{{timeOutShow}}" mask-closable="{{ false }}">
        <view slot="header" style="padding: 16px">
          <view class="exam-timeout-title">考试试卷结束,请提交试卷!</view>
          <button class="i-btn  i-btn-primary i-btn-square" form-type='submit'>提交</button>
        </view>
      </i-action-sheet>
    </form>

    <i-modal title="考试结果" visible="{{modalShow}}" bind:ok="returnRecord" bind:cancel="returnRecord">
      <view>得分:{{result}}</view>


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
![img](https://img-blog.csdnimg.cn/img_convert/3d0689a772f111e1e8a097d44c645a1e.png)

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

exam-timeout-title">考试试卷结束,请提交试卷!</view>
          <button class="i-btn  i-btn-primary i-btn-square" form-type='submit'>提交</button>
        </view>
      </i-action-sheet>
    </form>

    <i-modal title="考试结果" visible="{{modalShow}}" bind:ok="returnRecord" bind:cancel="returnRecord">
      <view>得分:{{result}}</view>


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注大数据)**
[外链图片转存中...(img-Zxj9391w-1713387388273)]

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值