Compare commits

..

5 Commits

@ -12,21 +12,12 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
*
*/
@Configuration
public class IntercepterConfig implements WebMvcConfigurer {
/**
* LoginInterceptor
*/
@Autowired
private LoginInterceptor loginInterceptor;
/**
*
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 拦截user下的api

@ -7,22 +7,12 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
/**
* Servlet
*/
@Configuration
public class ServletConfig {
/**
* WebServerFactoryCustomizer beanWeb
* @return WebServerFactoryCustomizer<ConfigurableWebServerFactory>
*/
@Bean
public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
// 返回一个lambda表达式用于自定义Web服务器的工厂
return factory -> {
// 创建一个ErrorPage对象用于处理404错误
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/");
// 将ErrorPage对象添加到Web服务器的工厂中
factory.addErrorPages(error404Page);
};
}

@ -23,18 +23,12 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;
/**
* Swagger2
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
/**
* Docket bean
* @return Docket
*/
@Bean
public Docket api() {
ParameterBuilder ticketPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
ticketPar.name("Access-Token").description("Rest接口权限认证token,无需鉴权可为空")
@ -54,10 +48,6 @@ public class Swagger2Config {
.globalOperationParameters(pars);
}
/**
* ApiInfo
* @return ApiInfo
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("online exam by springboot")
@ -67,4 +57,4 @@ public class Swagger2Config {
.contact(new Contact("liangshanguang", "https://github.com/lsgwr/spring-boot-online-exam", "liangshanguang2@gmail.com"))
.build();
}
}
}

@ -40,79 +40,51 @@ public class UploadDownloadController {
// return FileTransUtil.uploadFile(uploadfile, "/root/" + File.separator + uploadfile.getOriginalFilename());
// }
/**
*
*
* @param dir
* @param uploadfile
* @return String
*/
@ApiOperation("单文件上传,支持同时传入参数")
@PostMapping("/api/upload/singleAndparas")
public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) {
// 单文件上传。
public String uploadFileSingle(@RequestParam("dir") String dir, @RequestParam("file") MultipartFile uploadfile) {
// 调用FileTransUtil工具类中的uploadFile方法将上传的文件和目录作为参数传入。
return FileTransUtil.uploadFile(uploadfile, dir);
}
/**
* Model
*
* @param model UploadModel2
* @return String
*/
// 单文件上传支持同时传入参数Model。
@ApiOperation("单文件上传,支持同时传入参数,Model")
@PostMapping("/upload/single/model")
public String singleUploadFileModel(@ModelAttribute("model") UploadModel2 model) {
// 调用FileTransUtil工具类中的uploadFile方法将上传的文件和目录作为参数传入。
return FileTransUtil.uploadFile(model.getFile(), model.getDir());
}
/**
*
*
* @param dir
* @param uploadfiles
* @return String
*/
// 多文件上传,支持同时传入参数。
@ApiOperation("多文件上传,支持同时传入参数")
@PostMapping("upload/multiAndparas")
public String uploadFileMulti(@RequestParam("dir") String dir, @RequestParam("files") MultipartFile[] uploadfiles) {
// 调用FileTransUtil工具类中的uploadFiles方法将上传的文件数组和目录作为参数传入。
return FileTransUtil.uploadFiles(uploadfiles, dir);
}
/**
*
*
* @param model UploadModel
* @return String
*/
// 多文件上传,支持同时传入参数。
@ApiOperation("多文件上传,支持同时传入参数")
@PostMapping(value = "/upload/multi/model")
public String multiUploadFileModel(@ModelAttribute(("model")) UploadModel model) {
// 调用FileTransUtil工具类中的uploadFiles方法将上传的文件数组和目录作为参数传入。
return FileTransUtil.uploadFiles(model.getFiles(), model.getDir());
}
/**
* Get
*
* @param filePath
* @return ResponseEntity<InputStreamResource>
* @throws IOException
*/
// Get下载文件
@ApiOperation("Get下载文件")
@GetMapping(value = "/download/get")
public ResponseEntity<InputStreamResource> downloadFileGet(@RequestParam String filePath) throws IOException {
// 调用FileTransUtil工具类中的downloadFile方法将文件路径作为参数传入。
return FileTransUtil.downloadFile(filePath);
}
/**
* Post
*
* @param downloadQo DownloadQo
* @return ResponseEntity<InputStreamResource>
* @throws IOException
*/
// Post下载文件
@ApiOperation("Post下载文件")
@PostMapping(value = "/download/post")
public ResponseEntity<InputStreamResource> downloadFilePost(@RequestBody DownloadQo downloadQo) throws IOException {
// 调用FileTransUtil工具类中的downloadFile方法将文件路径作为参数传入。
return FileTransUtil.downloadFile(downloadQo.getPath());
}
}

@ -29,12 +29,6 @@ public class UserController {
@Autowired
private UserService userService;
/**
*
*
* @param registerDTO RegisterDTO
* @return ResultVO<User>
*/
@PostMapping("/register")
@ApiOperation("注册")
ResultVO<User> register(@RequestBody RegisterDTO registerDTO) {
@ -50,12 +44,6 @@ public class UserController {
return resultVO;
}
/**
* ,token
*
* @param loginQo LoginQo
* @return ResultVO<String>
*/
@PostMapping("/login")
@ApiOperation("根据用户名或邮箱登录,登录成功返回token")
ResultVO<String> login(@RequestBody LoginQo loginQo) { // 这里不用手机号是因为手机号和用户名难以进行格式区分,而用户名和
@ -72,12 +60,6 @@ public class UserController {
return resultVO;
}
/**
*
*
* @param request HttpServletRequest
* @return ResultVO<UserVo>
*/
@GetMapping("/user-info")
@ApiOperation("获取用户信息")
// 根据请求获取用户信息
@ -90,12 +72,6 @@ public class UserController {
return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userVo);
}
/**
*
*
* @param request HttpServletRequest
* @return ResultVO<UserInfoVo>
*/
@GetMapping("/info")
@ApiOperation("获取用户的详细信息,包括个人信息页面和操作权限")
// 获取用户信息的接口
@ -110,12 +86,6 @@ public class UserController {
return new ResultVO<>(ResultEnum.GET_INFO_SUCCESS.getCode(), ResultEnum.GET_INFO_SUCCESS.getMessage(), userInfoVo);
}
/**
*
*
* @param request HttpServletRequest
* @return String
*/
@GetMapping("/test")
@ApiOperation("测试接口")
String test(HttpServletRequest request) {

@ -8,26 +8,11 @@ package lsgwr.exam.dto;
import lombok.Data;
/**
*
*/
@Data
public class RegisterDTO {
/**
*
*/
private String email;
/**
*
*/
private String password;
/**
*
*/
private String password2;
/**
*
*/
private String mobile;
/**
*

@ -23,85 +23,37 @@ import java.util.Date;
@Entity
@Data
@DynamicUpdate
/**
*
*/
public class Exam {
// 使用JPA的@Id注解声明该字段为主键
/**
* ID
*/
@Id
private String examId;
/**
*
*/
private String examName;
/**
*
*/
private String examAvatar;
/**
*
*/
private String examDescription;
/**
* IDID
*/
private String examQuestionIds;
/**
* ID
*/
private String examQuestionIdsRadio;
/**
* ID
*/
private String examQuestionIdsCheck;
/**
* ID
*/
private String examQuestionIdsJudge;
/**
*
*/
private Integer examScore;
/**
*
*/
private Integer examScoreRadio;
/**
*
*/
private Integer examScoreCheck;
/**
*
*/
private Integer examScoreJudge;
/**
* ID
*/
private String examCreatorId;
/**
*
*/
private Integer examTimeLimit;
/**
* 使Jackson@JsonFormat
*/
private String examId;// 考试ID唯一标识一场考试
private String examName;// 考试名称
private String examAvatar; // 考试头像或图标
private String examDescription;// 考试描述或简介
private String examQuestionIds;// 存储所有问题ID的字符串可能是逗号分隔的ID列表
private String examQuestionIdsRadio;// 存储所有单选题ID的字符串
private String examQuestionIdsCheck;// 存储所有多选题ID的字符串
private String examQuestionIdsJudge;// 存储所有判断题ID的字符串
private Integer examScore;// 考试总分
private Integer examScoreRadio;// 单选题总分
private Integer examScoreCheck;// 多选题总分
private Integer examScoreJudge;// 判断题总分
private String examCreatorId;// 创建者ID标识谁创建了这场考试
private Integer examTimeLimit;// 考试时间限制,单位可能是分钟
// 考试开始时间使用Jackson的@JsonFormat注解自定义日期格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examStartDate;
/**
*
*/
// 考试结束时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date examEndDate;
/**
/**
* Java
* 使Jackson@JsonFormat便
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
/**
* Java
* 使Hibernate@DynamicUpdate

@ -16,22 +16,13 @@ import javax.persistence.Id;// 引入JPA中的@Id注解标识实体类的主
@Data
// 使用@Entity注解标识这是一个JPA实体类
@Entity
/**
*
*/
public class ExamRecordLevel {
/**
* ID@Id@GeneratedValue
*/
public class ExamRecordLevel {
// 考试记录等级的ID是主键通过@Id注解标识并通过@GeneratedValue注解指定主键生成策略
@Id
@GeneratedValue
private Integer examRecordLevelId;
/**
*
*/
// 考试记录等级的名称,用于标识等级,如“优秀”、“良好”等
private String examRecordLevelName;
/**
*
*/
// 考试记录等级的描述,用于对等级进行更详细的说明
private String examRecordLevelDescription;
}

@ -12,28 +12,16 @@ import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
*
*/
@Data
@Entity
public class Page {
/**
* ID@Id@GeneratedValue
*/
@Id
@GeneratedValue
private Integer pageId;
/**
*
*/
private String pageName;
/**
*
*/
private String pageDescription;
/**
* ID
*/
private String actionIds;
}

@ -9,34 +9,20 @@ package lsgwr.exam.exception;
import lsgwr.exam.enums.ResultEnum;
import lombok.Getter;
/**
*
*/
@Getter
public class ExamException extends RuntimeException {
/**
*
*/
// 定义异常码
private Integer code;
/**
*
*
* @param resultEnum ResultEnum
*/
// 构造函数,传入枚举类型
public ExamException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
}
/**
*
*
* @param code
* @param message
*/
// 构造函数,传入异常码和异常信息
public ExamException( Integer code, String message) {
super(message);
this.code = code;
}
}
}

@ -23,10 +23,6 @@ import java.io.PrintWriter;
*
* @author liangshanguang
*/
/**
* Token
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@ -88,9 +84,9 @@ public class LoginInterceptor implements HandlerInterceptor {
/**
*
*
* @param response
* @param obj
* @throws Exception
* @param response
* @param obj
* @throws Exception
*/
public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception {
Gson g = new Gson();

@ -10,9 +10,6 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
*
*/
@Data
@AllArgsConstructor
@NoArgsConstructor

@ -11,10 +11,7 @@ import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
/**
*
*/
@Data
@AllArgsConstructor
@NoArgsConstructor

@ -12,9 +12,6 @@ import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
/**
*
*/
@Data
@AllArgsConstructor
@NoArgsConstructor

@ -9,8 +9,6 @@ package lsgwr.exam.repository;
import lsgwr.exam.entity.ExamRecordLevel;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* ExamRecordLevelRepositoryJpaRepositoryExamRecordLevel
*/
// ExamRecordLevelRepository接口继承JpaRepository接口用于操作ExamRecordLevel实体类
public interface ExamRecordLevelRepository extends JpaRepository<ExamRecordLevel, Integer> {
}

@ -5,9 +5,6 @@ import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
*
*/
public interface ExamRecordRepository extends JpaRepository<ExamRecord, String> {
/**
*

@ -12,9 +12,7 @@ import org.springframework.data.jpa.repository.Query;
import java.util.List;
/**
* ExamRepositoryJpaRepositoryExam
*/
// ExamRepository接口继承JpaRepository接口用于操作Exam实体类
public interface ExamRepository extends JpaRepository<Exam, String> {
// 使用JPQL查询语句查询Exam实体类按照updateTime降序排列
@Query("select e from Exam e order by e.updateTime desc")

@ -15,18 +15,7 @@ import java.util.List;
*
*/
public interface QuestionRepository extends JpaRepository<Question, String> {
/**
* ID
*
* @param id ID
* @return
*/
List<Question> findByQuestionTypeId(Integer id);
/**
*
*
* @return
*/
@Query("select q from Question q order by q.updateTime desc")
List<Question> findAll();
}

@ -19,9 +19,6 @@ import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.*;
/**
*
*/
@Service
@Transactional
public class ExamServiceImpl implements ExamService {
@ -42,17 +39,6 @@ public class ExamServiceImpl implements ExamService {
private final QuestionOptionRepository questionOptionRepository;
/**
*
* @param questionRepository
* @param userRepository
* @param questionLevelRepository
* @param questionTypeRepository
* @param questionCategoryRepository
* @param questionOptionRepository
* @param examRepository
* @param examRecordRepository
*/
public ExamServiceImpl(QuestionRepository questionRepository, UserRepository userRepository, QuestionLevelRepository questionLevelRepository, QuestionTypeRepository questionTypeRepository, QuestionCategoryRepository questionCategoryRepository, QuestionOptionRepository questionOptionRepository, ExamRepository examRepository, ExamRecordRepository examRecordRepository) {
this.questionRepository = questionRepository;//
this.userRepository = userRepository;//
@ -64,22 +50,12 @@ public class ExamServiceImpl implements ExamService {
this.examRecordRepository = examRecordRepository;
}
/**
* @decription :
* return List<QuestionVo>
*/
@Override
public List<QuestionVo> getQuestionAll() {
List<Question> questionList = questionRepository.findAll();
return getQuestionVos(questionList);
}
/**
* Vo
*
* @param questionList
* @return Vo
*/
private List<QuestionVo> getQuestionVos(List<Question> questionList) {
// 需要自定义的question列表
List<QuestionVo> questionVoList = new ArrayList<>();

@ -86,12 +86,6 @@ public class UserServiceImpl implements UserService {
}
}
/**
*
*
* @param loginQo
* @return tokennull
*/
@Override
public String login(LoginQo loginQo) {
User user;

@ -5,7 +5,7 @@ spring:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: aA111111
url: jdbc:mysql://localhost:3306/exam?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&&allowPublicKeyRetrieval=true
url: jdbc:mysql://localhost:3306/exam?characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
jpa:
# 调试的时候用用于打印完成SQL语句(但是不打印参数),联合下面的logging.level一同打印最完整的SQL信息(语句+参数)
show-sql: false

File diff suppressed because one or more lines are too long

@ -1,6 +1,4 @@
<template>
<!-- 进入层展示一个通知消息组件透过点击设置触发展示-->
<!-- 通过 <a-popover> 实现通知消息框配置消息流和点击事件-->
<a-popover
v-model="visible"
trigger="click"
@ -11,40 +9,23 @@
:overlayStyle="{ width: '300px', top: '50px' }"
>
<template slot="content">
<!-- 透过加载线段和标签分类显示通知 -->
<a-spin :spinning="loadding">
<a-tabs>
<a-tab-pane tab="通知" key="1">
<!-- 显示通知列表具体消息以组件形式显示 -->
<a-list>
<a-list-item>
<a-list-item-meta
title="你收到了 14 份新周报"
description="一年前">
<a-avatar
style="background-color: white"
slot="avatar"
src="https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png"/>
<a-list-item-meta title="你收到了 14 份新周报" description="一年前">
<a-avatar style="background-color: white" slot="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/ThXAXghbEsBCCSDihZxY.png"/>
</a-list-item-meta>
</a-list-item>
<a-list-item>
<a-list-item-meta
title="你推荐的 曲妮妮 已通过第三轮面试"
description="一年前">
<a-avatar
style="background-color: white"
slot="avatar"
src="https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png"/>
<a-list-item-meta title="你推荐的 曲妮妮 已通过第三轮面试" description="一年前">
<a-avatar style="background-color: white" slot="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/OKJXDXrmkNshAMvwtvhu.png"/>
</a-list-item-meta>
</a-list-item>
<a-list-item>
<a-list-item-meta
title="这种模板可以区分多种通知类型"
description="一年前">
<a-avatar
style="background-color: white"
slot="avatar"
src="https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png"/>
<a-list-item-meta title="这种模板可以区分多种通知类型" description="一年前">
<a-avatar style="background-color: white" slot="avatar" src="https://gw.alipayobjects.com/zos/rmsportal/kISTdvpyTAhtGxpovNWd.png"/>
</a-list-item-meta>
</a-list-item>
</a-list>
@ -58,7 +39,6 @@
</a-tabs>
</a-spin>
</template>
<!-- 点击回调消息分类加载功能 -->
<span @click="fetchNotice" class="header-notice">
<a-badge count="12">
<a-icon style="font-size: 16px; padding: 4px" type="bell" />
@ -69,45 +49,41 @@
<script>
export default {
name: 'HeaderNotice', //
name: 'HeaderNotice',
data () {
return {
loadding: false, //
visible: false //
loadding: false,
visible: false
}
},
methods: {
//
fetchNotice () {
if (!this.visible) {
this.loadding = true
//
setTimeout(() => {
this.loadding = false
}, 2000)
} else {
this.loadding = false
}
this.visible = !this.visible //
this.visible = !this.visible
}
}
}
</script>
<style lang="css">
/* 通知框样式配置 */
.header-notice-wrapper {
top: 50px !important;
}
.header-notice-wrapper {
top: 50px !important;
}
</style>
<style lang="less" scoped>
/* 层级框样式 */
.header-notice{
display: inline-block;
transition: all 0.3s;
.header-notice{
display: inline-block;
transition: all 0.3s;
span {
vertical-align: initial;
span {
vertical-align: initial;
}
}
}
</style>

@ -1,15 +1,12 @@
import enquireJs from 'enquire.js'
// 定义设备类型的常量
export const DEVICE_TYPE = {
DESKTOP: 'desktop',
TABLET: 'tablet',
MOBILE: 'mobile'
}
// 检测设备类型的函数
export const deviceEnquire = function (callback) {
// 定义每个设备类型的匹配函数
const matchDesktop = {
match: () => {
callback && callback(DEVICE_TYPE.DESKTOP)
@ -28,7 +25,6 @@ export const deviceEnquire = function (callback) {
}
}
// 为每个设备类型注册媒体查询
// screen and (max-width: 1087.99px)
enquireJs
.register('screen and (max-width: 576px)', matchMobile)

@ -1,8 +1,8 @@
import Vue from 'vue' // 引入Vue
import moment from 'moment' // 引入moment库
import 'moment/locale/zh-cn' // 引入moment的中文语言包
import $ from 'jquery' // 引入jQuery
moment.locale('zh-cn') // 设置moment的语言为中文
import Vue from 'vue'
import moment from 'moment'
import 'moment/locale/zh-cn'
import $ from 'jquery'
moment.locale('zh-cn')
Vue.filter('NumberFormat', function (value) {
if (!value) {

@ -1,4 +1,3 @@
// 定义权限枚举
const PERMISSION_ENUM = {
'add': { key: 'add', label: '新增' },
'delete': { key: 'delete', label: '删除' },
@ -11,30 +10,21 @@ const PERMISSION_ENUM = {
'export': { key: 'export', label: '导出' }
}
// 定义插件
function plugin (Vue) {
// 如果插件已经安装,则返回
if (plugin.installed) {
return
}
// 如果Vue实例中没有$auth属性则定义$auth属性
!Vue.prototype.$auth && Object.defineProperties(Vue.prototype, {
$auth: {
get () {
// 获取当前实例
const _this = this
// 返回一个函数,用于判断权限
return (permissions) => {
// 将权限字符串分割成permission和action
const [permission, action] = permissions.split('.')
// 获取当前用户的权限列表
const permissionList = _this.$store.getters.roles.permissions
// 在权限列表中查找对应的permission
return permissionList.find((val) => {
return val.permissionId === permission
}).actionList.findIndex((val) => {
// 在actionList中查找对应的action
return val === action
}) > -1
}
@ -42,21 +32,15 @@ function plugin (Vue) {
}
})
// 如果Vue实例中没有$enum属性则定义$enum属性
!Vue.prototype.$enum && Object.defineProperties(Vue.prototype, {
$enum: {
get () {
// const _this = this;
// 返回一个函数,用于获取枚举值
return (val) => {
// 初始化result为PERMISSION_ENUM
let result = PERMISSION_ENUM
// 如果val存在则将val按'.'分割成数组
val && val.split('.').forEach(v => {
// 在result中查找对应的值
result = result && result[v] || null
})
// 返回result
return result
}
}
@ -64,5 +48,4 @@ function plugin (Vue) {
})
}
// 导出插件
export default plugin

@ -1,13 +1,9 @@
// import Vue from 'vue'
// 引入Vue
import { deviceEnquire, DEVICE_TYPE } from '../utils/device'
// 引入设备检测工具和设备类型
import { mapState } from 'vuex'
// 引入Vuex的mapState方法
// const mixinsComputed = Vue.config.optionMergeStrategies.computed
// const mixinsMethods = Vue.config.optionMergeStrategies.methods
// 定义Vue的computed和methods的合并策略
const mixin = {
computed: {
@ -76,5 +72,5 @@ const AppDeviceEnquire = {
})
}
}
// 导出mixin、AppDeviceEnquire、mixinDevice
export { mixin, AppDeviceEnquire, mixinDevice }

@ -1,12 +1,8 @@
// 导出一个函数将json字符串转换为对象
export function actionToObject (json) {
try {
// 尝试将json字符串转换为对象
return JSON.parse(json)
} catch (e) {
// 如果转换失败,打印错误信息
console.log('err', e.message)
}
// 返回一个空数组
return []
}

@ -15,7 +15,6 @@ const service = axios.create({
timeout: 6000 // 请求超时时间
})
// 错误处理函数
const err = (error) => {
if (error.response) {
const data = error.response.data

@ -6,22 +6,17 @@
* @param maxAge
*/
export const setStore = (name, content, maxAge = null) => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) {
return
}
// 如果content不是字符串则将其转换为字符串
if (typeof content !== 'string') {
content = JSON.stringify(content)
}
// 获取localStorage对象
const storage = global.window.localStorage
// 将content存储到localStorage中
storage.setItem(name, content)
// 如果maxAge存在且为数字则将过期时间存储到localStorage中
if (maxAge && !isNaN(parseInt(maxAge))) {
const timeout = parseInt(new Date().getTime() / 1000)
storage.setItem(`${name}_expire`, timeout + maxAge)
@ -35,17 +30,13 @@ export const setStore = (name, content, maxAge = null) => {
* @returns {*}
*/
export const getStore = name => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) {
return
}
// 获取localStorage中存储的content
const content = window.localStorage.getItem(name)
// 获取localStorage中存储的过期时间
const _expire = window.localStorage.getItem(`${name}_expire`)
// 如果过期时间存在,则判断当前时间是否超过过期时间
if (_expire) {
const now = parseInt(new Date().getTime() / 1000)
if (now > _expire) {
@ -53,11 +44,9 @@ export const getStore = name => {
}
}
// 尝试将content解析为JSON对象
try {
return JSON.parse(content)
} catch (e) {
// 如果解析失败则返回content
return content
}
}
@ -68,14 +57,11 @@ export const getStore = name => {
* @param name
*/
export const clearStore = name => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) {
return
}
// 从localStorage中移除content
window.localStorage.removeItem(name)
// 从localStorage中移除过期时间
window.localStorage.removeItem(`${name}_expire`)
}
@ -83,11 +69,9 @@ export const clearStore = name => {
* Clear all storage
*/
export const clearAll = () => {
// 如果没有全局window对象或者没有传入name则返回
if (!global.window || !name) {
return
}
// 清空localStorage
window.localStorage.clear()
}
}

@ -1,11 +1,9 @@
// 导出一个函数,用于获取当前时间并返回相应的问候语
export function timeFix () {
const time = new Date()
const hour = time.getHours()
return hour < 9 ? '早上好' : hour <= 11 ? '上午好' : hour <= 13 ? '中午好' : hour < 20 ? '下午好' : '晚上好'
}
// 导出一个函数,用于随机返回一个问候语
export function welcome () {
const arr = ['休息一会儿吧', '准备吃什么呢?', '要不要打一把 DOTA', '我猜你可能累了']
const index = Math.floor(Math.random() * arr.length)
@ -15,7 +13,6 @@ export function welcome () {
/**
* 触发 window.resize
*/
// 导出一个函数,用于触发 window.resize 事件
export function triggerWindowResizeEvent () {
const event = document.createEvent('HTMLEvents')
event.initEvent('resize', true, true)
@ -23,7 +20,6 @@ export function triggerWindowResizeEvent () {
window.dispatchEvent(event)
}
// 导出一个函数,用于监听页面滚动事件
export function handleScrollHeader (callback) {
let timer = 0
@ -54,7 +50,6 @@ export function handleScrollHeader (callback) {
* @param id parent element id or class
* @param timeout
*/
// 导出一个函数,用于移除加载动画
export function removeLoadingAnimate (id = '', timeout = 1500) {
if (id === '') {
return

@ -1,14 +1,11 @@
<template>
<!-- 这是 Vue 组件的模板部分 -->
<exception-page type="403" />
</template>
<script>
// components ExceptionPage
import { ExceptionPage } from '../../components'
export default {
// ExceptionPage
components: {
ExceptionPage
}

@ -1,28 +1,18 @@
<template>
<div class="card-list" ref="content">
<!-- 使用a-list组件设置grid属性gutter为24lg为3md为2sm为1xs为1 -->
<a-list
:grid="{gutter: 24, lg: 3, md: 2, sm: 1, xs: 1}"
:dataSource="dataSource"
>
<!-- 使用a-list-item组件设置slot为renderItemslot-scope为item -->
<a-list-item slot="renderItem" slot-scope="item">
<!-- 使用a-card组件设置hoverable为true点击事件为joinExam -->
<a-card :hoverable="true" @click="joinExam(item.id)">
<!-- 使用a-card-meta组件设置slot为titleavatardescription -->
<a-card-meta>
<!-- 设置title为item.title -->
<div style="margin-bottom: 3px" slot="title">{{ item.title }}</div>
<!-- 设置avatar为item.avatar使用imgSrcFilter过滤器 -->
<a-avatar class="card-avatar" slot="avatar" :src="item.avatar | imgSrcFilter" size="large" />
<!-- 设置description为item.content -->
<div class="meta-content" slot="description">{{ item.content }}</div>
</a-card-meta>
<!-- 使用template组件设置slot为actions -->
<template class="ant-card-actions" slot="actions">
<!-- 设置a为满分item.score分 -->
<a>满分{{ item.score }}</a>
<!-- 设置a为限时item.elapse分钟 -->
<a>限时{{ item.elapse }}分钟</a>
</template>
</a-card>
@ -44,7 +34,6 @@ export default {
}
},
methods: {
//
joinExam (id) {
const routeUrl = this.$router.resolve({
path: `/exam/${id}`

@ -85,15 +85,15 @@ export default {
},
data () {
return {
//
//
examDetail: {},
// id, currentQuestion(answersidids),
// id, currentQuestion(answersidids),
answersMap: {},
//
currentQuestion: '',
// answersMap
// answersMap
radioValue: '',
// answersMap
// answersMap
checkValues: [],
optionStyle: {
display: 'block',
@ -106,7 +106,7 @@ export default {
mounted () {
this.answersMap = new Map()
const that = this
//
//
getExamDetail(this.$route.params.id)
.then(res => {
if (res.code === 0) {
@ -122,26 +122,26 @@ export default {
})
},
methods: {
//
// ,
...mapGetters(['nickname', 'avatar']),
getQuestionDetail (questionId) {
// content
// content
const that = this
//
//
this.radioValue = ''
this.checkValues = []
getQuestionDetail(questionId)
.then(res => {
if (res.code === 0) {
//
//
that.currentQuestion = res.data
// answersMapid
// answersMapid
if (that.answersMap.get(that.currentQuestion.id)) {
//
//
if (that.currentQuestion.type === '单选题' || that.currentQuestion.type === '判断题') {
that.radioValue = that.answersMap.get(that.currentQuestion.id)[0]
} else if (that.currentQuestion.type === '多选题') {
//
//
Object.assign(that.checkValues, that.answersMap.get(that.currentQuestion.id))
}
}

Loading…
Cancel
Save