基于Spring Boot和Vue的高校竞赛平台设计与开发
3系统分析
3.1可行性分析
通过对本高校竞赛管理平台的目的进行初步调研和分析,提出了可行性方案并逐一进行论证。主要从技术可行性、经济可行性和操作可行性等方面进行评估。
3.1.1技术可行性
本高校竞赛管理平台采用Spring Boot框架,Java作为开发语言,是基于Web平台的B/S架构系统。
(1)Java语言提供了稳定的性能、良好的扩展性、快速的开发周期、便捷的管理机制以及现代化的语言特性。整个系统为用户处理了大量繁琐的底层工作。
(2)基于B/S模式的系统开发技术已经相当成熟,有丰富的技术支持和解决方案。
(3)Java作为面向对象的编程语言,开发人员可以在IntelliJ IDEA等平台上方便地利用已有的解决方案和组件库。
因此,高校竞赛管理平台在技术上具有很高的可行性,且开发团队具备相应的技术能力,所以该系统的开发技术方案是可行的。
3.1.2经济可行性
本高校竞赛管理平台采用的软件均为开源技术,这样可以节省大量资源和精力,降低开发成本。同时,对计算机配置要求较低,即使是较旧的设备也能满足基本需求,因此,本系统在经济上完全可行,具有较高的性价比。
3.1.3操作可行性
本高校竞赛管理平台的界面设计简洁直观,用户只要具备基本的计算机操作能力,即可轻松访问和操作系统。本系统具有易操作、易管理、交互性好的特点,操作流程简单直观,因此在操作上具有很高的可行性。
综上所述,该平台开发目标明确,在技术、经济和操作方面均具有很高的可行性,且投入少、功能完善、管理便捷,因此系统的开发是完全可行的。
3.2系统性能分析
3.2.1 系统安全性
此高校竞赛管理平台需要严格控制访问权限,具体要求如下:
(1)用户必须通过账号和密码登录系统才能进行管理操作,无权限用户无法通过任何方式登录系统或查看系统中的任何信息和数据,确保系统的安全可靠性和数据准确性。
(2)在具体实现中对不同角色权限进行精细化设置,不同权限的用户登录后不能越权操作。
3.2.2 数据完整性
(1)所有记录信息必须完整,信息记录内容不允许为空。
(2)各种数据之间的关联关系必须保持正确。
(3)相同数据在不同记录中必须保持一致。
3.3系统界面分析
当前,界面设计已成为软件质量评价的关键指标之一,优秀的用户界面能够增强用户使用系统的信心和兴趣,从而提高工作效率。Vue.js作为前端框架,提供了组件化的开发方式,能够方便地构建动态交互界面。用户界面是软件系统与用户交互的接口,通常包括输出、输入、人机对话的界面格式等。
1.输出设计
输出设计是指计算机对输入的基本信息进行处理,生成高质量的有效信息,并按照特定格式提供给管理者使用。这是输出设计的主要责任和目标。
系统开发的过程与实施过程相反,不是从输入设计到输出设计,而是从输出设计到输入设计。这是因为输出表格与使用者直接相关,设计的目标应确保使用者能够方便地使用输出表格,并及时反映各部门的有用信息。输出设计的原则既要全面考虑不同管理层的需求,又要简洁,避免向用户提供不必要的信息。
2.输入设计
输入数据的收集和录入是比较繁琐的过程,需要大量人力和设备,且容易出错。一旦输入系统的数据不正确,处理后的输出会放大这些错误,因此输入数据的准确性对整个系统的性能起着决定性作用。
输入设计有以下几点原则:
1)输入量应保持在满足处理要求的最低限度。输入量越少,错误率越低,数据准备时间也越少。
2)应尽可能使输入的准备和输入过程简便,以降低错误发生率。
3)应尽早检查输入数据(尽量接近数据源),以便及时更正错误。
4)输入数据应尽早记录成其处理所需的形式,防止数据在不同介质间转换时可能出现的转录错误。
3.4系统流程和逻辑
图3-3登录流程图
图3-4修改密码流程图
4系统概要设计
4.1概述
本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务的架构模式,是一个适用于互联网环境的应用模型。只要用户能接入互联网,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示:
图4-1系统工作原理图
4.2系统结构
本系统是基于B/S架构的Web应用,设计的功能结构图如下图所示:
图4-2功能结构图
4.3数据库设计
4.3.1数据库实体
概念设计的目标是设计出反映组织信息需求的数据库概念模式,该模式独立于数据库系统的逻辑结构、独立于DBMS、独立于计算机系统。
概念模式的设计方法是在需求分析的基础上,用概念数据模型(如E-R模型)表示数据及其相互关系,设计出反映用户信息需求和处理需求的数据库概念模式。概念设计的目标是准确描述应用领域的信息模式,支持用户的各种应用,这样既容易转换为数据库逻辑模式,又容易被用户理解。数据库概念模式是面向现实世界的数据模型,不能直接用于数据库实现。在此阶段,用户可以参与和评价数据库设计,从而确保数据库设计与用户需求相吻合。在概念模式设计中,E-R模型是最常见的方法。本系统的E-R图如下:
(1)管理员信息的实体属性图如下:
图4.12 管理员信息实体属性图
(2)学生信息实体属性图如图4.13所示:
图4.13 学生信息实体属性图
(3)班级类型信息实体属性图如图4.14所示:
图4.14 班级类型信息实体属性图
4.3.2数据库设计表
高校竞赛管理平台需要后台数据库,下面介绍数据库中的各个表的详细信息:
表4.1 班级类型
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 创建时间 |
| type_name | varchar(200) | 是 | NULL | 类型名称 |
表4.2 教师
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 创建时间 |
| employee_id | varchar(200) | 否 | 工号 | |
| password | varchar(200) | 否 | 密码 | |
| teacher_name | varchar(200) | 否 | 教师姓名 | |
| gender | varchar(200) | 是 | NULL | 性别 |
| college | varchar(200) | 是 | NULL | 学院名称 |
| title | varchar(200) | 是 | NULL | 职称 |
| phone | varchar(200) | 是 | NULL | 手机 |
| varchar(200) | 是 | NULL | 邮箱 | |
| photo | varchar(200) | 是 | NULL | 照片 |
表4.3 竞赛报名
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 创建时间 |
| employee_id | varchar(200) | 是 | NULL | 工号 |
| teacher_name | varchar(200) | 是 | NULL | 教师姓名 |
| competition_name | varchar(200) | 是 | NULL | 竞赛名称 |
| competition_type | varchar(200) | 是 | NULL | 竞赛类型 |
| participation_type | varchar(200) | 是 | NULL | 参赛类型 |
| team_members | varchar(200) | 是 | NULL | 参赛人员 |
| submission_work | varchar(200) | 是 | NULL | 参赛作品 |
| declaration | longtext | 是 | NULL | 参赛宣言 |
| apply_date | date | 是 | NULL | 申请日期 |
| student_id | varchar(200) | 是 | NULL | 学号 |
| student_name | varchar(200) | 是 | NULL | 学生姓名 |
| review_status | varchar(200) | 是 | 否 | 审核状态 |
| review_comment | longtext | 是 | NULL | 审核回复 |
| payment_status | varchar(200) | 是 | 未支付 | 支付状态 |
表4.4 竞赛信息
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 创建时间 |
| competition_name | varchar(200) | 是 | NULL | 竞赛名称 |
| competition_type | varchar(200) | 是 | NULL | 竞赛类型 |
| competition_venue | varchar(200) | 是 | NULL | 竞赛地点 |
| competition_rules | longtext | 是 | NULL | 竞赛规则 |
| competition_rewards | longtext | 是 | NULL | 竞赛奖励 |
| competition_time | datetime | 是 | NULL | 竞赛时间 |
| mode | varchar(200) | 是 | NULL | 模式 |
| cover_image | varchar(200) | 是 | NULL | 封面图片 |
| employee_id | varchar(200) | 是 | NULL | 工号 |
| teacher_name | varchar(200) | 是 | NULL | 教师姓名 |
表4.5 管理员表
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| username | varchar(100) | 否 | 用户名 | |
| password | varchar(100) | 否 | 密码 | |
| role | varchar(100) | 是 | 管理员 | 角色 |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 新增时间 |
表4.6 学生
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 创建时间 |
| student_id | varchar(200) | 否 | 学号 | |
| password | varchar(200) | 否 | 密码 | |
| student_name | varchar(200) | 否 | 学生姓名 | |
| gender | varchar(200) | 是 | NULL | 性别 |
| college | varchar(200) | 是 | NULL | 学院名称 |
| class_name | varchar(200) | 是 | NULL | 班级 |
| phone | varchar(200) | 是 | NULL | 手机 |
| varchar(200) | 是 | NULL | 邮箱 | |
| photo | varchar(200) | 是 | NULL | 照片 |
表4.7作品评分
| 字段 | 类型 | 空 | 默认 | 注释 |
|---|---|---|---|---|
| id (主键) | bigint(20) | 否 | 主键 | |
| addtime | timestamp | 否 | CURRENT_TIMESTAMP | 创建时间 |
| student_id | varchar(200) | 是 | NULL | 学号 |
| student_name | varchar(200) | 是 | NULL | 学生姓名 |
| competition_name | varchar(200) | 是 | NULL | 竞赛名称 |
| competition_type | varchar(200) | 是 | NULL | 竞赛类型 |
| work_score | int(11) | 是 | NULL | 作品评分 |
| review_content | longtext | 是 | NULL | 评价内容 |
| review_time | date | 是 | NULL | 评价时间 |
| employee_id | varchar(200) | 是 | NULL | 工号 |
| teacher_name | varchar(200) | 是 | NULL | 教师姓名 |
5系统详细实现
5.1 管理员模块的实现
5.1.1 学生信息管理
高校竞赛管理平台的管理员可以管理用户信息,对学生信息进行修改、删除和查询操作。具体界面展示如图5.1所示。
图5.1 学生信息管理界面
后端代码
@IgnoreAuth
@RequestMapping("/register")
public R register(@RequestBody StudentEntity student) {
StudentEntity existingUser = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_id", student.getStudentId()));
if (existingUser != null) {
return R.error("注册用户已存在");
}
Long userId = System.currentTimeMillis();
student.setId(userId);
studentService.insert(student);
return R.ok();
}
/**
* 退出登录
*/
@RequestMapping("/logout")
public R logout(HttpServletRequest request) {
request.getSession().invalidate();
return R.ok("退出成功");
}
/**
* 获取当前用户信息
*/
@RequestMapping("/session")
public R getCurrUser(HttpServletRequest request) {
Long id = (Long) request.getSession().getAttribute("userId");
StudentEntity user = studentService.selectById(id);
return R.ok().put("data", user);
}
/**
* 密码重置
*/
@IgnoreAuth
@RequestMapping(value = "/resetPass")
public R resetPass(String username, HttpServletRequest request) {
StudentEntity user = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_id", username));
if (user == null) {
return R.error("账号不存在");
}
user.setPassword("123456");
studentService.updateById(user);
return R.ok("密码已重置为:123456");
}
/**
* 后端列表
*/
@RequestMapping("/page")
public R page(@RequestParam Map<String, Object> params, StudentEntity student, HttpServletRequest request) {
EntityWrapper<StudentEntity> ew = new EntityWrapper<StudentEntity>();
PageUtils page = studentService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, student), params), params));
return R.ok().put("data", page);
}
/**
* 前端列表
*/
@RequestMapping("/list")
public R list(@RequestParam Map<String, Object> params, StudentEntity student, HttpServletRequest request) {
EntityWrapper<StudentEntity> ew = new EntityWrapper<StudentEntity>();
PageUtils page = studentService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, student), params), params));
return R.ok().put("data", page);
}
/**
* 列表查询
*/
@RequestMapping("/lists")
public R list(StudentEntity student) {
EntityWrapper<StudentEntity> ew = new EntityWrapper<StudentEntity>();
ew.allEq(MPUtil.allEQMapPre(student, "student"));
return R.ok().put("data", studentService.selectListView(ew));
}
/**
* 详情查询
*/
@RequestMapping("/query")
public R query(StudentEntity student) {
EntityWrapper<StudentEntity> ew = new EntityWrapper<StudentEntity>();
ew.allEq(MPUtil.allEQMapPre(student, "student"));
StudentView studentView = studentService.selectView(ew);
return R.ok("查询学生成功").put("data", studentView);
}
/**
* 后端详情
*/
@RequestMapping("/info/{id}")
public R info(@PathVariable("id") Long id) {
StudentEntity student = studentService.selectById(id);
return R.ok().put("data", student);
}
/**
* 前端详情
*/
@RequestMapping("/detail/{id}")
public R detail(@PathVariable("id") Long id) {
StudentEntity student = studentService.selectById(id);
return R.ok().put("data", student);
}
/**
* 后端保存
*/
@RequestMapping("/save")
public R save(@RequestBody StudentEntity student, HttpServletRequest request) {
student.setId(System.currentTimeMillis() + (long) (Math.random() * 1000));
StudentEntity existingUser = studentService.selectOne(new EntityWrapper<StudentEntity>().eq("student_id", student.getStudentId()));
if (existingUser != null) {
return R.error("用户已存在");
}
student.setId(System.currentTimeMillis());
studentService.insert(student);
return R.ok();
}
前端代码
<template>
<div class="addEdit-block">
<el-form
class="detail-form-content"
ref="ruleForm"
:model="ruleForm"
:rules="rules"
label-width="80px"
:style="{backgroundColor:addEditForm.addEditBoxColor}"
>
<el-row>
<el-col :span="12">
<el-form-item class="input" v-if="type!='info'" label="学号" prop="student_id">
<el-input v-model="ruleForm.student_id"
placeholder="学号" clearable :readonly="ro.student_id"></el-input>
</el-form-item>
<div v-else>
<el-form-item class="input" label="学号" prop="student_id">
<el-input v-model="ruleForm.student_id"
placeholder="学号" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="input" v-if="type!='info'" label="密码" prop="password">
<el-input v-model="ruleForm.password"
placeholder="密码" clearable :readonly="ro.password"></el-input>
</el-form-item>
<div v-else>
<el-form-item class="input" label="密码" prop="password">
<el-input v-model="ruleForm.password"
placeholder="密码" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="input" v-if="type!='info'" label="学生姓名" prop="student_name">
<el-input v-model="ruleForm.student_name"
placeholder="学生姓名" clearable :readonly="ro.student_name"></el-input>
</el-form-item>
<div v-else>
<el-form-item class="input" label="学生姓名" prop="student_name">
<el-input v-model="ruleForm.student_name"
placeholder="学生姓名" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="select" v-if="type!='info'" label="性别" prop="gender">
<el-select v-model="ruleForm.gender" placeholder="请选择性别">
<el-option
v-for="(item,index) in genderOptions"
v-bind:key="index"
:label="item"
:value="item">
</el-option>
</el-select>
</el-form-item>
<div v-else>
<el-form-item class="input" label="性别" prop="gender">
<el-input v-model="ruleForm.gender"
placeholder="性别" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="input" v-if="type!='info'" label="学院名称" prop="college">
<el-input v-model="ruleForm.college"
placeholder="学院名称" clearable :readonly="ro.college"></el-input>
</el-form-item>
<div v-else>
<el-form-item class="input" label="学院名称" prop="college">
<el-input v-model="ruleForm.college"
placeholder="学院名称" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="select" v-if="type!='info'" label="班级" prop="class_name">
<el-select v-model="ruleForm.class_name" placeholder="请选择班级">
<el-option
v-for="(item,index) in classOptions"
v-bind:key="index"
:label="item"
:value="item">
</el-option>
</el-select>
</el-form-item>
<div v-else>
<el-form-item class="input" label="班级" prop="class_name">
<el-input v-model="ruleForm.class_name"
placeholder="班级" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="input" v-if="type!='info'" label="手机" prop="phone">
<el-input v-model="ruleForm.phone"
placeholder="手机" clearable :readonly="ro.phone"></el-input>
</el-form-item>
<div v-else>
<el-form-item class="input" label="手机" prop="phone">
<el-input v-model="ruleForm.phone"
placeholder="手机" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="12">
<el-form-item class="input" v-if="type!='info'" label="邮箱" prop="email">
<el-input v-model="ruleForm.email"
placeholder="邮箱" clearable :readonly="ro.email"></el-input>
</el-form-item>
<div v-else>
<el-form-item class="input" label="邮箱" prop="email">
<el-input v-model="ruleForm.email"
placeholder="邮箱" readonly></el-input>
</el-form-item>
</div>
</el-col>
<el-col :span="24">
<el-form-item class="upload" v-if="type!='info' && !ro.photo" label="照片" prop="photo">
<file-upload
tip="点击上传照片"
action="file/upload"
:limit="3"
:multiple="true"
:fileUrls="ruleForm.photo?ruleForm.photo:''"
@change="photoUploadChange"
></file-upload>
</el-form-item>
<div v-else>
<el-form-item v-if="ruleForm.photo" label="照片" prop="photo">
![]()
</el-form-item>
</div>
</el-col>
</el-row>
<el-form-item class="btn">
<el-button v-if="type!='info'" type="primary" class="btn-success" @click="onSubmit">提交</el-button>
<el-button v-if="type!='info'" class="btn-close" @click="back()">取消</el-button>
<el-button v-if="type=='info'" class="btn-close" @click="back()">返回</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import { isNumber, isIntNumer, isEmail, isPhone, isMobile, isURL, checkIdCard } from "@/utils/validate";
export default {
data() {
let self = this;
var validateIdCard = (rule, value, callback) => {
if (!value) {
callback();
} else if (!checkIdCard(value)) {
callback(new Error("请输入正确的身份证号码"));
} else {
callback();
}
};
var validateUrl = (rule, value, callback) => {
if (!value) {
callback();
} else if (!isURL(value)) {
callback(new Error("请输入正确的URL地址"));
} else {
callback();
}
};
var validateMobile = (rule, value, callback) => {
if (!value) {
callback();
} else if (!isMobile(value)) {
callback(new Error("请输入正确的手机号码"));
} else {
callback();
}
};
var validatePhone = (rule, value, callback) => {
if (!value) {
callback();
} else if (!isPhone(value)) {
callback(new Error("请输入正确的电话号码"));
} else {
callback();
}
};
var validateEmail = (rule, value, callback) => {
if (!value) {
callback();
} else if (!isEmail(value)) {
callback(new Error("请输入正确的邮箱地址"));
} else {
callback();
}
};
var validateNumber = (rule, value, callback) => {
if (!value) {
callback();
} else if (!isNumber(value)) {
callback(new Error("请输入数字"));
} else {
callback();
}
};
var validateIntNumber = (rule, value, callback) => {
if (!value) {
callback();
} else if (!isIntNumer(value)) {
callback(new Error("请输入整数"));
} else {
callback();
}
};
return {
addEditForm: {
"btnSaveFontColor": "rgba(34, 32, 32, 1)",
"selectFontSize": "14px",
"btnCancelBorderColor": "#DCDFE6",
"inputBorderRadius": "16px",
"inputFontSize": "14px",
"textareaBgColor": "rgba(207, 199, 199, 0.13)",
"btnSaveFontSize": "14px",
"textareaBorderRadius": "16px",
"uploadBgColor": "rgba(207, 199, 199, 0.13)",
"textareaBorderStyle": "solid",
"btnCancelWidth": "88px",
"textareaHeight": "120px",
"dateBgColor": "rgba(207, 199, 199, 0.13)",
"btnSaveBorderRadius": "16px",
"uploadLableFontSize": "14px",
"textareaBorderWidth": "1px",
"inputLableColor": "#606266",
"addEditBoxColor": "rgba(238, 221, 221, 0.32)",
"dateIconFontSize": "14px",
"btnSaveBgColor": "#409EFF",
"uploadIconFontColor": "#8c939d",
"textareaBorderColor": "#DCDFE6",
"btnCancelBgColor": "rgba(84, 244, 185, 1)",
"selectLableColor": "#606266",
"btnSaveBorderStyle": "solid",
"dateBorderWidth": "1px",
"dateBorderRadius": "16px",
"btnCancelBorderStyle": "solid",
"selectLableFontSize": "14px",
"selectBorderStyle": "solid",
"selectIconFontColor": "#C0C4CC",
"btnCancelHeight": "44px",
"inputHeight": "40px",
"btnCancelFontColor": "rgba(23, 23, 24, 1)",
"dateBorderColor": "#DCDFE6",
"dateIconFontColor": "#C0C4CC",
"uploadBorderStyle": "solid",
"dateBorderStyle": "solid",
"dateLableFontSize": "14px",
"dateLableColor": "#606266",
"dateFontSize": "14px",
"inputBorderWidth": "1px",
"uploadIconFontSize": "28px",
"selectHeight": "40px",
"inputFontColor": "rgba(25, 26, 27, 1)",
"uploadHeight": "148px",
"textareaLableColor": "#606266",
"textareaLableFontSize": "14px",
"btnCancelFontSize": "14px",
"inputBorderStyle": "solid",
"btnCancelBorderRadius": "16px",
"inputBgColor": "rgba(207, 199, 199, 0.13)",
"inputLableFontSize": "14px",
"uploadLableColor": "#606266",
"uploadBorderRadius": "16px",
"btnSaveHeight": "44px",
"selectBgColor": "rgba(207, 199, 199, 0.13)",
"btnSaveWidth": "88px",
"selectIconFontSize": "14px",
"dateHeight": "40px",
"selectBorderColor": "#DCDFE6",
"inputBorderColor": "#DCDFE6",
"uploadBorderColor": "#DCDFE6",
"textareaFontColor": "rgba(25, 26, 27, 1)",
"selectBorderWidth": "1px",
"dateFontColor": "rgba(255, 69, 0, 0.66)",
"btnCancelBorderWidth": "1px",
"uploadBorderWidth": "1px",
"textareaFontSize": "14px",
"selectBorderRadius": "16px",
"selectFontColor": "rgba(25, 26, 27, 1)",
"btnSaveBorderColor": "#409EFF",
"btnSaveBorderWidth": "1px"
},
id: '',
type: '',
ro: {
student_id: false,
password: false,
student_name: false,
gender: false,
college: false,
class_name: false,
phone: false,
email: false,
photo: false,
},
ruleForm: {
student_id: '',
password: '',
student_name: '',
gender: '',
college: '',
class_name: '',
phone: '',
email: '',
photo: '',
},
genderOptions: [],
classOptions: [],
rules: {
student_id: [
{ required: true, message: '学号不能为空', trigger: 'blur' },
],
password: [
{ required: true, message: '密码不能为空', trigger: 'blur' },
],
student_name: [
{ required: true, message: '学生姓名不能为空', trigger: 'blur' },
],
gender: [
],
college: [
],
class_name: [
],
phone: [
{ validator: validateMobile, trigger: 'blur' },
],
email: [
{ validator: validateEmail, trigger: 'blur' },
],
photo: [
],
}
};
},
props: ["parent"],
computed: {
},
created() {
this.addEditStyleChange()
this.addEditUploadStyleChange()
},
methods: {
// 下载
download(file) {
window.open(`${file}`)
},
// 初始化
init(id, type) {
if (id) {
this.id = id;
this.type = type;
}
if (this.type == 'info' || this.type == 'else') {
this.info(id);
} else if (this.type == 'cross') {
var obj = this.$storage.getObj('crossObj');
for (var o in obj) {
if (o == 'student_id') {
this.ruleForm.student_id = obj[o];
this.ro.student_id = true;
continue;
}
if (o == 'password') {
this.ruleForm.password = obj[o];
this.ro.password = true;
continue;
}
if (o == 'student_name') {
this.ruleForm.student_name = obj[o];
this.ro.student_name = true;
continue;
}
if (o == 'gender') {
this.ruleForm.gender = obj[o];
this.ro.gender = true;
continue;
}
if (o == 'college') {
this.ruleForm.college = obj[o];
this.ro.college = true;
continue;
}
if (o == 'class_name') {
this.ruleForm.class_name = obj[o];
this.ro.class_name = true;
continue;
}
if (o == 'phone') {
this.ruleForm.phone = obj[o];
this.ro.phone = true;
continue;
}
if (o == 'email') {
this.ruleForm.email = obj[o];
this.ro.email = true;
continue;
}
if (o == 'photo') {
this.ruleForm.photo = obj[o];
this.ro.photo = true;
continue;
}
}
}
// 获取用户信息
this.$http({
url: `${this.$storage.get('sessionTable')}/session`,
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
var json = data.data;
} else {
this.$message.error(data.msg);
}
});
this.genderOptions = "男,女".split(',')
this.$http({
url: `option/classType/type`,
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
this.classOptions = data.data;
} else {
this.$message.error(data.msg);
}
});
},
// 多级联动参数
info(id) {
this.$http({
url: `student/info/${id}`,
method: "get"
}).then(({ data }) => {
if (data && data.code === 0) {
this.ruleForm = data.data;
//解决前台上传图片后台不显示的问题
let reg = new RegExp('../../../upload', 'g') //g代表全部
} else {
this.$message.error(data.msg);
}
});
},
// 提交
onSubmit() {
this.$refs["ruleForm"].validate(valid => {
if (valid) {
this.$http({
url: `student/${!this.ruleForm.id ? "save" : "update"}`,
method: "post",
data: this.ruleForm
}).then(({ data }) => {
if (data && data.code === 0) {
this.$message({
message: "操作成功",
type: "success",
duration: 1500,
onClose: () => {
this.parent.showFlag = true;
this.parent.addOrUpdateFlag = false;
this.parent.studentCrossAddOrUpdateFlag = false;
this.parent.search();
this.parent.contentStyleChange();
}
});
} else {
this.$message.error(data.msg);
}
});
}
});
},
// 获取uuid
getUUID() {
return new Date().getTime();
},
// 返回
back() {
this.parent.showFlag = true;
this.parent.addOrUpdateFlag = false;
this.parent.studentCrossAddOrUpdateFlag = false;
this.parent.contentStyleChange();
},
photoUploadChange(fileUrls) {
this.ruleForm.photo = fileUrls;
this.addEditUploadStyleChange()
},
addEditStyleChange() {
this.$nextTick(() => {
// input
document.querySelectorAll('.addEdit-block .input .el-input__inner').forEach(el => {
el.style.height = this.addEditForm.inputHeight
el.style.color = this.addEditForm.inputFontColor
el.style.fontSize = this.addEditForm.inputFontSize
el.style.borderWidth = this.addEditForm.inputBorderWidth
el.style.borderStyle = this.addEditForm.inputBorderStyle
el.style.borderColor = this.addEditForm.inputBorderColor
el.style.borderRadius = this.addEditForm.inputBorderRadius
el.style.backgroundColor = this.addEditForm.inputBgColor
})
document.querySelectorAll('.addEdit-block .input .el-form-item__label').forEach(el => {
el.style.lineHeight = this.addEditForm.inputHeight
el.style.color = this.addEditForm.inputLableColor
el.style.fontSize = this.addEditForm.inputLableFontSize
})
// select
document.querySelectorAll('.addEdit-block .select .el-input__inner').forEach(el => {
el.style.height = this.addEditForm.selectHeight
el.style.color = this.addEditForm.selectFontColor
el.style.fontSize = this.addEditForm.selectFontSize
el.style.borderWidth = this.addEditForm.selectBorderWidth
el.style.borderStyle = this.addEditForm.selectBorderStyle
el.style.borderColor = this.addEditForm.selectBorderColor
el.style.borderRadius = this.addEditForm.selectBorderRadius
el.style.backgroundColor = this.addEditForm.selectBgColor
})
document.querySelectorAll('.addEdit-block .select .el-form-item__label').forEach(el => {
el.style.lineHeight = this.addEditForm.selectHeight
el.style.color = this.addEditForm.selectLableColor
el.style.fontSize = this.addEditForm.selectLableFontSize
})
document.querySelectorAll('.addEdit-block .select .el-select__caret').forEach(el => {
el.style.color = this.addEditForm.selectIconFontColor
el.style.fontSize = this.addEditForm.selectIconFontSize
})
// date
document.querySelectorAll('.addEdit-block .date .el-input__inner').forEach(el => {
el.style.height = this.addEditForm.dateHeight
el.style.color = this.addEditForm.dateFontColor
el.style.fontSize = this.addEditForm.dateFontSize
el.style.borderWidth = this.addEditForm.dateBorderWidth
el.style.borderStyle = this.addEditForm.dateBorderStyle
el.style.borderColor = this.addEditForm.dateBorderColor
el.style.borderRadius = this.addEditForm.dateBorderRadius
el.style.backgroundColor = this.addEditForm.dateBgColor
})
document.querySelectorAll('.addEdit-block .date .el-form-item__label').forEach(el => {
el.style.lineHeight = this.addEditForm.dateHeight
el.style.color = this.addEditForm.dateLableColor
el.style.fontSize = this.addEditForm.dateLableFontSize
})
document.querySelectorAll('.addEdit-block .date .el-input__icon').forEach(el => {
el.style.color = this.addEditForm.dateIconFontColor
el.style.fontSize = this.addEditForm.dateIconFontSize
el.style.lineHeight = this.addEditForm.dateHeight
})
// upload
let iconLineHeight = parseInt(this.addEditForm.uploadHeight) - parseInt(this.addEditForm.uploadBorderWidth) * 2 + 'px'
document.querySelectorAll('.addEdit-block .upload .el-upload--picture-card').forEach(el => {
el.style.width = this.addEditForm.uploadHeight
el.style.height = this.addEditForm.uploadHeight
el.style.borderWidth = this.addEditForm.uploadBorderWidth
el.style.borderStyle = this.addEditForm.uploadBorderStyle
el.style.borderColor = this.addEditForm.uploadBorderColor
el.style.borderRadius = this.addEditForm.uploadBorderRadius
el.style.backgroundColor = this.addEditForm.uploadBgColor
})
document.querySelectorAll('.addEdit-block .upload .el-form-item__label').forEach(el => {
el.style.lineHeight = this.addEditForm.uploadHeight
el.style.color = this.addEditForm.uploadLableColor
el.style.fontSize = this.addEditForm.uploadLableFontSize
})
document.querySelectorAll('.addEdit-block .upload .el-icon-plus').forEach(el => {
el.style.color = this.addEditForm.uploadIconFontColor
el.style.fontSize = this.addEditForm.uploadIconFontSize
el.style.lineHeight = iconLineHeight
el.style.display = 'block'
})
// 多文本输入框
document.querySelectorAll('.addEdit-block .textarea .el-textarea__inner').forEach(el => {
el.style.height = this.addEditForm.textareaHeight
el.style.color = this.addEditForm.textareaFontColor
el.style.fontSize = this.addEditForm.textareaFontSize
el.style.borderWidth = this.addEditForm.textareaBorderWidth
el.style.borderStyle = this.addEditForm.textareaBorderStyle
el.style.borderColor = this.addEditForm.textareaBorderColor
el.style.borderRadius = this.addEditForm.textareaBorderRadius
el.style.backgroundColor = this.addEditForm.textareaBgColor
})
document.querySelectorAll('.addEdit-block .textarea .el-form-item__label').forEach(el => {
el.style.color = this.addEditForm.textareaLableColor
el.style.fontSize = this.addEditForm.textareaLableFontSize
})
// 保存
document.querySelectorAll('.addEdit-block .btn .btn-success').forEach(el => {
el.style.width = this.addEditForm.btnSaveWidth
el.style.height = this.addEditForm.btnSaveHeight
el.style.color = this.addEditForm.btnSaveFontColor
el.style.fontSize = this.addEditForm.btnSaveFontSize
el.style.borderWidth = this.addEditForm.btnSaveBorderWidth
el.style.borderStyle = this.addEditForm.btnSaveBorderStyle
el.style.borderColor = this.addEditForm.btnSaveBorderColor
el.style.borderRadius = this.addEditForm.btnSaveBorderRadius
el.style.backgroundColor = this.addEditForm.btnSaveBgColor
})
// 返回
document.querySelectorAll('.addEdit-block .btn .btn-close').forEach(el => {
el.style.width = this.addEditForm.btnCancelWidth
el.style.height = this.addEditForm.btnCancelHeight
el.style.color = this.addEditForm.btnCancelFontColor
el.style.fontSize = this.addEditForm.btnCancelFontSize
el.style.borderWidth = this.addEditForm.btnCancelBorderWidth
el.style.borderStyle = this.addEditForm.btnCancelBorderStyle
el.style.borderColor = this.addEditForm.btnCancelBorderColor
el.style.borderRadius = this.addEditForm.btnCancelBorderRadius
el.style.backgroundColor = this.addEditForm.btnCancelBgColor
})
})
},
addEditUploadStyleChange() {
this.$nextTick(() => {
document.querySelectorAll('.addEdit-block .upload .el-upload-list--picture-card .el-upload-list__item').forEach(el => {
el.style.width = this.addEditForm.uploadHeight
el.style.height = this.addEditForm.uploadHeight
el.style.borderWidth = this.addEditForm.uploadBorderWidth
el.style.borderStyle = this.addEditForm.uploadBorderStyle
el.style.borderColor = this.addEditForm.uploadBorderColor
el.style.borderRadius = this.addEditForm.uploadBorderRadius
el.style.backgroundColor = this.addEditForm.uploadBgColor
})
})
},
}
};
</script>
<style lang="scss">
.editor {
height: 500px;
& /deep/ .ql-container {
height: 310px;
}
}
.amap-wrapper {
width: 100%;
height: 500px;
}
.search-box {
position: absolute;
}
.addEdit-block {
margin: -10px;
}
.detail-form-content {
padding: 12px;
}
.btn .el-button {
padding: 0;
}
</style>
5.1.2 教师信息管理
系统管理员可以对教师信息进行添加、修改、删除和查询操作。界面如图5.2所示。
图5.2 教师信息管理界面
5.2 教师模块的实现
5.2.1 竞赛报名审核
教师可以对学生提交的竞赛报名进行审核操作。界面如下图所示:
图5.3 竞赛报名审核界面
5.2.2 竞赛信息管理
教师可以对竞赛信息进行添加、修改和删除操作。界面如下图所示:
图5.4 竞赛信息管理界面
5.3 学生模块的实现
5.3.1 竞赛信息管理
学生可以在竞赛信息管理模块中查看竞赛详情并进行报名操作。界面如下图所示:
图5.5 竞赛信息界面
5.3.2 竞赛报名管理
学生可以在竞赛报名模块中查看自己的报名情况。界面如下图所示:
图5.6 竞赛报名界面