Commit a67357e5 by tangyi

#I16LRM 支持多选题、判断题

parent 56bc7c05
Version v3.6.0 (2020-02-22)
--------------------------
新功能:
* 支持多选题、不定项选择题、判断题
改进:
* 完善题目管理、成绩批改
* 优化后台样式,如:侧边栏、按钮等样色
* 新用户注册支持默认头像
Version v3.5.0 (2020-02-03)
--------------------------
新功能:
* 后台首页dashboard,支持监控考试记录数
改进:
* 优化题目管理
* 优化后台样式、路由管理等
* 升级spring boot版本为2.2.2.RELEASE、spring cloud版本为Hoxton.SR1
Version v3.5.0 (2020-01-19) Version v3.5.0 (2020-01-19)
-------------------------- --------------------------
......
...@@ -9,7 +9,9 @@ ...@@ -9,7 +9,9 @@
</a> </a>
</p> </p>
> 硕果云,基于Spring Cloud搭建的新一代微服务教学管理平台,提供多租户、权限管理、考试、练习等功能。 > 硕果云,基于Spring Cloud搭建的新一代微服务教学管理平台,提供多租户、权限管理、在线考试、练习等功能
>
> 题型支持单选题、多选题、不定项选择题、判断题、简答题等
### 🏠 [主页](https://gitee.com/wells2333/spring-microservice-exam) ### 🏠 [主页](https://gitee.com/wells2333/spring-microservice-exam)
...@@ -49,8 +51,8 @@ ...@@ -49,8 +51,8 @@
| 名称 | 版本 | | 名称 | 版本 |
| --------- | -------- | | --------- | -------- |
| `Spring Boot` | `2.1.11.RELEASE` | | `Spring Boot` | `2.2.2.RELEASE` |
| `Spring Cloud` | `Greenwich.SR4` | | `Spring Cloud` | `Hoxton.SR1` |
## 系统架构 ## 系统架构
...@@ -62,7 +64,9 @@ ...@@ -62,7 +64,9 @@
前台主要提供在线考试、在线学习功能 前台主要提供在线考试、在线学习功能
后台管理分为:系统管理、系统监控、考务管理、附件管理、个人管理 后台管理分为:首页监控、系统管理、系统监控、考务管理、附件管理、个人管理
首页监控:提供系统租户数、用户数、考试数、近七天考试记录数等监控
系统管理:提供用户、部门、角色、权限等基础管理 系统管理:提供用户、部门、角色、权限等基础管理
- 用户管理:用户信息增删改查、导入导出 - 用户管理:用户信息增删改查、导入导出
...@@ -81,9 +85,9 @@ ...@@ -81,9 +85,9 @@
考务管理:提供课程、考试、题库、成绩等管理 考务管理:提供课程、考试、题库、成绩等管理
- 课程管理:课程信息增删改查 - 课程管理:课程信息增删改查
- 考试管理:考试信息增删改查、题目管理、发布回收,题目管理支持简单文本、富文本输入、从题库添加等 - 考试管理:考试信息增删改查、题目管理、发布回收,题目管理支持简单文本、富文本输入、从题库添加等,题型支持单选题、多选题、不定项选择题、判断题、简答题
- 题库管理:题目分类增删改查、题目信息增删改查 - 题库管理:题目分类增删改查、题目信息增删改查,题型支持单选题、多选题、不定项选择题、判断题、简答题
- 成绩管理:查看成绩、导出成绩 - 成绩管理:查看成绩、成绩批改、导出等功能
- 知识库:知识库增删改查、上传附件 - 知识库:知识库增删改查、上传附件
附件管理:项目的所有附件存储在`fastDfs`里,提供统一的管理入口 附件管理:项目的所有附件存储在`fastDfs`里,提供统一的管理入口
...@@ -93,26 +97,53 @@ ...@@ -93,26 +97,53 @@
- 个人资料:姓名、头像等基本信息的修改 - 个人资料:姓名、头像等基本信息的修改
- 修改密码:修改密码 - 修改密码:修改密码
## 系统截图 ## 系统截图(点击查看大图)
### 前台功能 ### 前台功能
1. 首页 <table>
![image](docs/images/image_web.png) <tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_web_login.png" alt="登录"/></td>
2. 考试 <td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_web.png" alt="首页"/></td>
![image](docs/images/image_web_exam.png) </tr>
<tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_web_exams.png" alt="考试列表"/></td>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_web_exam.png" alt="考试"/></td>
</tr>
<tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_web_record.png" alt="考试记录"/></td>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_web_incorrect_answer.png" alt="错题列表"/></td>
</tr>
</table>
### 后台功能 ### 后台功能
1. 总体功能 <table>
![image](docs/images/image_ui_menu.png) <tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_login.png" alt="登录"/></td>
2. 考试管理 <td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_exam.png" alt="首页"/></td>
![image](docs/images/image_ui_exam.png) </tr>
<tr>
3. 题目管理 <td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_menu.png" alt="菜单"/></td>
![image](docs/images/image_ui_subjects_rich_edit.png) <td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_menu_manage.png" alt="菜单管理"/></td>
</tr>
<tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_menu_role_manage.png" alt="角色管理"/></td>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_route_manage.png" alt="路由管理"/></td>
</tr>
<tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_subjects_manage.png" alt="题库管理"/></td>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_subjects_rich_edit.png" alt="题目编辑"/></td>
</tr>
<tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_score_manage.png" alt="成绩管理"/></td>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_score_detail.png" alt="成绩详情"/></td>
</tr>
<tr>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_log_manage.png" alt="日志监控"/></td>
<td><img src="https://gitee.com/wells2333/spring-microservice-exam/raw/master/docs/images/image_ui_consul.png" alt="服务监控"/></td>
</tr>
</table>
## 部署文档 ## 部署文档
......
...@@ -186,5 +186,10 @@ public class CommonConstant { ...@@ -186,5 +186,10 @@ public class CommonConstant {
* 女 * 女
*/ */
public static final Integer GENDER_WOMEN = 1; public static final Integer GENDER_WOMEN = 1;
/**
* 逗号
*/
public static final String COMMA = ",";
} }
...@@ -67,6 +67,11 @@ public class BaseEntity<T> implements Serializable { ...@@ -67,6 +67,11 @@ public class BaseEntity<T> implements Serializable {
*/ */
protected boolean isNewRecord; protected boolean isNewRecord;
/**
* 扩展字段
*/
protected String ext;
public BaseEntity(Long id) { public BaseEntity(Long id) {
this(); this();
this.id = id; this.id = id;
...@@ -112,5 +117,18 @@ public class BaseEntity<T> implements Serializable { ...@@ -112,5 +117,18 @@ public class BaseEntity<T> implements Serializable {
this.applicationCode = applicationCode; this.applicationCode = applicationCode;
this.tenantCode = tenantCode; this.tenantCode = tenantCode;
} }
/**
* 置空属性
*/
public void clearCommonValue() {
this.creator = null;
this.createDate = null;
this.modifier = null;
this.modifyDate = null;
this.delFlag = null;
this.applicationCode = null;
this.tenantCode = null;
}
} }
...@@ -2,11 +2,9 @@ package com.github.tangyi.common.core.utils; ...@@ -2,11 +2,9 @@ package com.github.tangyi.common.core.utils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.time.Instant; import java.time.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date; import java.util.Date;
/** /**
...@@ -18,9 +16,11 @@ import java.util.Date; ...@@ -18,9 +16,11 @@ import java.util.Date;
@Slf4j @Slf4j
public class DateUtils { public class DateUtils {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter FORMATTER_MILLIS = DateTimeFormatter.ofPattern("yyyyMMddhhmmssSSS"); public static final DateTimeFormatter FORMATTER_DAY = DateTimeFormatter.ofPattern("MM-dd");
public static final DateTimeFormatter FORMATTER_MILLIS = DateTimeFormatter.ofPattern("yyyyMMddhhmmssSSS");
/** /**
* 日期转string * 日期转string
...@@ -131,4 +131,24 @@ public class DateUtils { ...@@ -131,4 +131,24 @@ public class DateUtils {
} }
return seconds; return seconds;
} }
/**
* 获得周几日期,上一周或下一周,依此类推
* @param week 指定周几
* @param whichWeek 那一周
* @return string 日期 年-月-日
*/
public static String getDayOfWhichWeek(DayOfWeek week, int whichWeek) {
LocalDate day = LocalDate.now().with(TemporalAdjusters.previous(week)).minusWeeks(whichWeek -1);
return day.format(FORMATTER_DAY);
}
/**
* 天数累加
* @param plusDay plusDay
* @return LocalDateTime
*/
public static LocalDateTime plusDay(int plusDay) {
return LocalDateTime.now().plusDays(plusDay);
}
} }
...@@ -109,7 +109,7 @@ qiniu: ...@@ -109,7 +109,7 @@ qiniu:
sys: sys:
adminUser: ${ADMIN_USER:admin} # 管理员账号,默认是admin adminUser: ${ADMIN_USER:admin} # 管理员账号,默认是admin
uploadUrl: api/user/v1/attachment/upload uploadUrl: api/user/v1/attachment/upload
defaultAvatar: https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif?imageView2/1/w/80/h/80 defaultAvatar: /static/img/avatar/
key: '1234567887654321' key: '1234567887654321'
cacheExpire: 86400 # 缓存失效时间,单位秒,默认一天 cacheExpire: 86400 # 缓存失效时间,单位秒,默认一天
......
docs/images/image_ui_exam.png

245 KB | W: | H:

docs/images/image_ui_exam.png

210 KB | W: | H:

docs/images/image_ui_exam.png
docs/images/image_ui_exam.png
docs/images/image_ui_exam.png
docs/images/image_ui_exam.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/image_ui_menu.png

273 KB | W: | H:

docs/images/image_ui_menu.png

279 KB | W: | H:

docs/images/image_ui_menu.png
docs/images/image_ui_menu.png
docs/images/image_ui_menu.png
docs/images/image_ui_menu.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/image_ui_msg.png

332 KB | W: | H:

docs/images/image_ui_msg.png

388 KB | W: | H:

docs/images/image_ui_msg.png
docs/images/image_ui_msg.png
docs/images/image_ui_msg.png
docs/images/image_ui_msg.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/image_web_exam.png

248 KB | W: | H:

docs/images/image_web_exam.png

176 KB | W: | H:

docs/images/image_web_exam.png
docs/images/image_web_exam.png
docs/images/image_web_exam.png
docs/images/image_web_exam.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/image_web_exams.png

297 KB | W: | H:

docs/images/image_web_exams.png

302 KB | W: | H:

docs/images/image_web_exams.png
docs/images/image_web_exams.png
docs/images/image_web_exams.png
docs/images/image_web_exams.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/image_web_record.png

248 KB | W: | H:

docs/images/image_web_record.png

196 KB | W: | H:

docs/images/image_web_record.png
docs/images/image_web_record.png
docs/images/image_web_record.png
docs/images/image_web_record.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>系统演示</title> <title>硕果云-sg-admin</title>
</head> </head>
<body> <body>
<script src=/static/tinymce4.7.5/tinymce.min.js></script> <script src=/static/tinymce4.7.5/tinymce.min.js></script>
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
"driver.js": "0.5.2", "driver.js": "0.5.2",
"dropzone": "5.2.0", "dropzone": "5.2.0",
"echarts": "4.1.0", "echarts": "4.1.0",
"element-ui": "2.4.6", "element-ui": "2.13.0",
"es6-promise": "^4.1.1", "es6-promise": "^4.1.1",
"eslint-plugin-html": "^5.0.0", "eslint-plugin-html": "^5.0.0",
"express": "^4.14.1", "express": "^4.14.1",
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
"jsonlint": "1.6.3", "jsonlint": "1.6.3",
"jszip": "3.1.5", "jszip": "3.1.5",
"mockjs": "1.0.1-beta3", "mockjs": "1.0.1-beta3",
"moment": "^2.24.0",
"normalize.css": "7.0.0", "normalize.css": "7.0.0",
"nprogress": "0.2.0", "nprogress": "0.2.0",
"screenfull": "3.3.3", "screenfull": "3.3.3",
......
...@@ -35,7 +35,7 @@ export function getDownloadUrl (id) { ...@@ -35,7 +35,7 @@ export function getDownloadUrl (id) {
return request({ return request({
url: baseAttachmentUrl + '/download', url: baseAttachmentUrl + '/download',
method: 'get', method: 'get',
params: {id: id} params: { id: id }
}) })
} }
......
...@@ -16,3 +16,14 @@ export function getDashboard () { ...@@ -16,3 +16,14 @@ export function getDashboard () {
method: 'get' method: 'get'
}) })
} }
/**
* 过去一周考试记录数据
*/
export function getExamRecordTendency (query) {
return request({
url: '/api/user/v1/dashboard/examRecordTendency',
method: 'get',
params: query
})
}
...@@ -66,6 +66,14 @@ export function putAnswer (obj) { ...@@ -66,6 +66,14 @@ export function putAnswer (obj) {
}) })
} }
export function markAnswer (obj) {
return request({
url: baseAnswerUrl + 'mark',
method: 'put',
data: obj
})
}
export function delAnswer (id) { export function delAnswer (id) {
return request({ return request({
url: baseAnswerUrl + id, url: baseAnswerUrl + id,
......
...@@ -12,7 +12,7 @@ export function fetchList (query) { ...@@ -12,7 +12,7 @@ export function fetchList (query) {
export function fetchSubjectListById (query) { export function fetchSubjectListById (query) {
return request({ return request({
url: baseExaminationUrl + query.examinationId + '/subjectList', url: baseExaminationUrl + 'subjectList',
method: 'get', method: 'get',
params: query params: query
}) })
......
...@@ -73,3 +73,11 @@ export function exportObj (obj) { ...@@ -73,3 +73,11 @@ export function exportObj (obj) {
data: obj data: obj
}) })
} }
// 查询成绩详情
export function examRecordDetails (id) {
return request({
url: baseExamRecordUrl + id + '/details',
method: 'get'
})
}
<template>
<el-row>
<el-col :span="4">
<el-card class="tree-box-card" style="margin-right: 5px;">
<div slot="header">
<span>题目分类</span>
</div>
<el-row>
<div class="tree-container">
<el-tree
:data="treeData"
:props="defaultProps"
class="filter-tree"
node-key="id"
highlight-current
accordion
@node-click="getNodeData"
/>
</div>
</el-row>
</el-card>
</el-col>
<el-col :span="20">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>题目列表</span>
</div>
<el-table
v-loading="listLoading"
:data="list"
:default-sort="{ prop: 'id', order: 'ascending' }"
highlight-current-row
style="width: 100%;">
<el-table-column :label="$t('table.subjectName')" prop="subject_name" property="subjectName" min-width="120">
<template slot-scope="scope">
<span>{{ scope.row.subjectName | simpleStrFilter }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.subject.type')">
<template slot-scope="scope">
<el-tag type="success">{{ scope.row.type | subjectTypeFilter }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('table.subject.score')">
<template slot-scope="scope">
<span>{{ scope.row.score }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.actions')" width="100">
<template slot-scope="scope">
<el-button type="text" @click="handleSelectSubject(scope.row)" icon="el-icon-check">{{ $t('table.select') }}</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination v-show="total>0" :current-page="listQuery.pageNum" :page-sizes="[10,20,30, 50]" :page-size="listQuery.pageSize" :total="total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"/>
</div>
</el-card>
</el-col>
</el-row>
</template>
<script>
import Tinymce from '@/components/Tinymce'
import { fetchCategoryTree } from '@/api/exam/subjectCategory'
import { fetchSubjectListById } from '@/api/exam/exam'
import { getSubject } from '@/api/exam/subject'
export default {
name: 'CategorySubjects',
components: {
Tinymce
},
data () {
return {
listLoading: false,
list: [],
total: 0,
dialogVisible: false,
// 题目列表查询参数
listQuery: {
subjectName: undefined,
categoryId: undefined,
examinationId: undefined,
sort: 'id',
order: 'ascending'
},
// 分类树数据
treeData: [],
// 题目分类数据
defaultProps: {
children: 'children',
label: 'categoryName'
},
tempSubject: undefined
}
},
created () {
this.handleCreateSubjectFromSubjectBank()
},
methods: {
getList () {
this.listLoading = true
fetchSubjectListById(this.listQuery).then(response => {
if (response.data.list.length > 0) {
response.data.list.map(subject => {
subject.type = parseInt(subject.type)
subject.level = parseInt(subject.level)
})
this.list = response.data.list
} else {
this.list = []
}
this.total = parseInt(response.data.total)
setTimeout(() => {
this.listLoading = false
}, 500)
})
},
handleSizeChange (val) {
this.limit = val
this.handleSubjectManagement()
},
handleCurrentChange (val) {
this.pageNum = val
this.handleSubjectManagement()
},
// 从题库新增
handleCreateSubjectFromSubjectBank () {
// 加载分类树
fetchCategoryTree(this.listQuery).then(response => {
this.treeData = response.data
})
this.dialogVisible = true
// 加载题目列表
},
// 点击分类
getNodeData (data) {
// 获取分类ID
this.listQuery.categoryId = data.id
// 获取题目信息
this.getList()
},
// 选择题目
handleSelectSubject (selected) {
// 加载题目信息
getSubject(selected.id, { type: selected.type }).then(response => {
this.tempSubject = response.data.data
this.$emit('selected', this.tempSubject)
})
},
getSubjectInfo () {
return this.tempSubject
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../styles/subject.scss";
</style>
...@@ -31,43 +31,32 @@ ...@@ -31,43 +31,32 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-collapse v-model="optionCollapseActives"> <el-row>
<el-collapse-item title="选项列表" name="1"> <el-col :span="24">
<el-row class="collapse-top"> <el-divider>选项列表</el-divider>
<el-col :span="24"> <el-form-item v-for="(option, index) in options" :label="option.optionName" :key="option.optionName"
<el-form-item v-for="(option, index) in options" :label="option.optionName" :key="option.optionName" :prop="'options.' + index + '.optionContent'">
:prop="'options.' + index + '.optionContent'"> <el-row :gutter="5">
<el-row :gutter="5"> <el-col :span="4">
<el-col :span="2"> <el-input v-model="option.optionName"/>
<el-input v-model="option.optionName"></el-input> </el-col>
</el-col> <el-col :span="18">
<el-col :span="20"> <el-input v-model="option.optionContent" @input="updateTinymceContent(option.optionContent, index, '1')">
<el-input v-model="option.optionContent" @input="updateTinymceContent(option.optionContent, index, '1')"> <el-button slot="append" @click.prevent="removeOption(option)">删除</el-button>
<el-button slot="append" @click.prevent="removeOption(option)">删除</el-button> </el-input>
</el-input> </el-col>
</el-col> </el-row>
</el-row> </el-form-item>
</el-form-item> <el-button type="success" @click.prevent="addOption()" style="display:block;margin:0 auto">新增选项</el-button>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-button @click.prevent="addOption()" style="display:block;margin:0 auto">新增选项</el-button> <el-form-item :label="$t('table.subject.analysis')" prop="analysis" class="analysis-form-item">
</el-col> <el-input v-model="subjectInfo.analysis" @input="updateTinymceContent(subjectInfo.analysis, tinymceEdit.analysis)"/>
</el-row> </el-form-item>
</el-collapse-item> </el-col>
</el-collapse> </el-row>
<el-collapse v-model="analysisCollapseActives">
<el-collapse-item title="解析" name="2">
<el-row>
<el-col :span="24">
<el-form-item :label="$t('table.subject.analysis')" prop="analysis">
<el-input v-model="subjectInfo.analysis" @input="updateTinymceContent(subjectInfo.analysis, tinymceEdit.analysis)"/>
</el-form-item>
</el-col>
</el-row>
</el-collapse-item>
</el-collapse>
</div> </div>
</el-col> </el-col>
<el-col :span="14"> <el-col :span="14">
...@@ -95,16 +84,16 @@ export default { ...@@ -95,16 +84,16 @@ export default {
default: function () { default: function () {
return { return {
id: '', id: '',
examinationId: '', examinationId: undefined,
categoryId: 0, categoryId: undefined,
subjectName: '', subjectName: '',
type: 0, type: 0,
choicesType: 0, choicesType: 0,
options: [ options: [
{subjectChoicesId: '', optionName: 'A', optionContent: ''}, { subjectChoicesId: '', optionName: 'A', optionContent: '' },
{subjectChoicesId: '', optionName: 'B', optionContent: ''}, { subjectChoicesId: '', optionName: 'B', optionContent: '' },
{subjectChoicesId: '', optionName: 'C', optionContent: ''}, { subjectChoicesId: '', optionName: 'C', optionContent: '' },
{subjectChoicesId: '', optionName: 'D', optionContent: ''} { subjectChoicesId: '', optionName: 'D', optionContent: '' }
], ],
answer: { answer: {
subjectId: '', subjectId: '',
...@@ -139,7 +128,7 @@ export default { ...@@ -139,7 +128,7 @@ export default {
type: 1, // 类型 0:题目名称,1:选项 type: 1, // 类型 0:题目名称,1:选项
dialogTinymceVisible: false, dialogTinymceVisible: false,
tempValue: '', tempValue: '',
currentEdit: -1, currentEdit: -1
}, },
// 编辑对象 // 编辑对象
tinymceEdit: { tinymceEdit: {
...@@ -168,10 +157,10 @@ export default { ...@@ -168,10 +157,10 @@ export default {
methods: { methods: {
initDefaultOptions () { initDefaultOptions () {
this.options = [ this.options = [
{subjectChoicesId: '', optionName: 'A', optionContent: ''}, { subjectChoicesId: '', optionName: 'A', optionContent: '' },
{subjectChoicesId: '', optionName: 'B', optionContent: ''}, { subjectChoicesId: '', optionName: 'B', optionContent: '' },
{subjectChoicesId: '', optionName: 'C', optionContent: ''}, { subjectChoicesId: '', optionName: 'C', optionContent: '' },
{subjectChoicesId: '', optionName: 'D', optionContent: ''} { subjectChoicesId: '', optionName: 'D', optionContent: '' }
] ]
}, },
setSubjectInfo (subject) { setSubjectInfo (subject) {
...@@ -236,8 +225,8 @@ export default { ...@@ -236,8 +225,8 @@ export default {
resetTempSubject (score) { resetTempSubject (score) {
this.subjectInfo = { this.subjectInfo = {
id: '', id: '',
examinationId: '', examinationId: undefined,
categoryId: 0, categoryId: undefined,
subjectName: '', subjectName: '',
type: 0, type: 0,
choicesType: 0, choicesType: 0,
...@@ -263,7 +252,7 @@ export default { ...@@ -263,7 +252,7 @@ export default {
} }
this.initDefaultOptions() this.initDefaultOptions()
}, },
addOption() { addOption () {
// 校验 // 校验
if (this.options.length > 0) { if (this.options.length > 0) {
let option = this.options[this.options.length - 1] let option = this.options[this.options.length - 1]
...@@ -271,25 +260,24 @@ export default { ...@@ -271,25 +260,24 @@ export default {
message(this, '请先输入选项再添加', 'warning') message(this, '请先输入选项再添加', 'warning')
return return
} }
this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' }); this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' })
} else { } else {
this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' }); this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' })
} }
}, },
removeOption(item) { removeOption (item) {
let index = this.options.indexOf(item) let index = this.options.indexOf(item)
if (index !== -1) { if (index !== -1) {
this.options.splice(index, 1) this.options.splice(index, 1)
} }
}, },
// 点击事件回调 // 点击事件回调
hasClick(hasClick) { hasClick (hasClick) {
this.editType = 1 this.editType = 1
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
...@@ -297,4 +285,7 @@ export default { ...@@ -297,4 +285,7 @@ export default {
.el-rate { .el-rate {
margin-top: 8px; margin-top: 8px;
} }
.analysis-form-item {
margin-top: 20px;
}
</style> </style>
<template>
<el-form ref="dataSubjectForm" :rules="subjectRules" :model="subjectInfo" :label-position="labelPosition" label-width="100px">
<el-row>
<el-col :span="10">
<div class="subject-info">
<el-row>
<el-col :span="12">
<el-form-item :label="$t('table.subject.score')" prop="score">
<el-input v-model="subjectInfo.score"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('table.subject.level')" prop="level">
<el-rate v-model="subjectInfo.level" :max="4" :texts="['简单', '一般', '略难', '非常难']" show-text/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item :label="$t('table.subjectName')" prop="subjectName">
<el-input v-model="subjectInfo.subjectName" @focus="updateTinymceContent(subjectInfo.subjectName, tinymceEdit.subjectName)"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item :label="$t('table.subject.answer')" prop="answer">
<el-radio-group v-model="subjectInfo.answer.answer">
<el-radio v-for="(option) in options" :label="option.optionName" :key="option.optionName">{{ option.optionName }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item :label="$t('table.subject.analysis')" prop="analysis" class="analysis-form-item">
<el-input v-model="subjectInfo.analysis" @input="updateTinymceContent(subjectInfo.analysis, tinymceEdit.analysis)"/>
</el-form-item>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="14">
<div class="subject-tinymce">
<tinymce ref="choicesEditor" :height="350" v-model="choicesContent" @hasClick="hasClick"/>
</div>
</el-col>
</el-row>
</el-form>
</template>
<script>
import Tinymce from '@/components/Tinymce'
import { isNotEmpty, message } from '@/utils/util'
export default {
name: 'Judgement',
components: {
Tinymce
},
props: {
subject: {
type: Object,
default: function () {
return {
id: '',
examinationId: undefined,
categoryId: undefined,
subjectName: '',
type: 0,
choicesType: 0,
options: [
{ subjectChoicesId: '', optionName: '正确', optionContent: '正确' },
{ subjectChoicesId: '', optionName: '错误', optionContent: '错误' }
],
answer: {
subjectId: '',
answer: '',
answerType: '',
score: ''
},
score: 5,
analysis: '',
level: 2,
editType: 0 // 0: 输入框,1:富文本
}
}
},
choices: {
type: String,
default: ''
}
},
data () {
return {
subjectInfo: this.subject,
choicesContent: this.choices,
labelPosition: 'right',
// 表单校验规则
subjectRules: {
subjectName: [{ required: true, message: '请输入题目名称', trigger: 'change' }],
score: [{ required: true, message: '请输入题目分值', trigger: 'change' }],
answer: [{ required: true, message: '请输入答案', trigger: 'change' }]
},
tinymce: {
type: 1, // 类型 0:题目名称,1:选项
dialogTinymceVisible: false,
tempValue: '',
currentEdit: -1
},
// 编辑对象
tinymceEdit: {
subjectName: -1,
answer: 4,
analysis: 5
},
options: []
}
},
watch: {
// 监听富文本编辑器的输入
choicesContent: {
handler: function (choicesContent) {
if (isNotEmpty(this.$refs.choicesEditor)) {
if (this.editType === 1 && this.$refs.choicesEditor.getHasClick()) {
this.saveTinymceContent(choicesContent)
}
}
},
immediate: true
}
},
methods: {
initDefaultOptions () {
this.options = [
{ subjectChoicesId: '', optionName: '正确', optionContent: '正确' },
{ subjectChoicesId: '', optionName: '错误', optionContent: '错误' }
]
},
setSubjectInfo (subject) {
this.subjectInfo = subject
this.initDefaultOptions()
},
getSubjectInfo () {
return this.subjectInfo
},
// 绑定富文本的内容
updateTinymceContent (content, currentEdit, type) {
// 重置富文本
this.choicesContent = ''
// 绑定当前编辑的对象
this.tinymce.currentEdit = currentEdit
this.tinymce.type = type
this.$refs.choicesEditor.setContent(content || '')
this.editType = 0
this.$refs.choicesEditor.setHashClick(false)
},
saveTinymceContent (content) {
switch (this.tinymce.currentEdit) {
case this.tinymceEdit.subjectName:
this.subjectInfo.subjectName = content
break
case this.tinymceEdit.answer:
this.subjectInfo.answer.answer = content
break
case this.tinymceEdit.analysis:
this.subjectInfo.analysis = content
break
}
},
// 表单校验
validate () {
let valid = false
this.$refs['dataSubjectForm'].validate((validate) => {
valid = validate
})
return valid
},
clearValidate () {
this.$refs['dataSubjectForm'].clearValidate()
},
resetTempSubject (score) {
this.subjectInfo = {
id: '',
examinationId: undefined,
categoryId: undefined,
subjectName: '',
type: 0,
choicesType: 0,
answer: {
subjectId: '',
answer: '',
answerType: '',
score: ''
},
score: 5,
analysis: '',
level: 2
}
// 默认分数
if (isNotEmpty(score)) {
this.subjectInfo.score = score
}
this.initDefaultOptions()
},
// 点击事件回调
hasClick (hasClick) {
this.editType = 1
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../styles/subject.scss";
.el-rate {
margin-top: 8px;
}
.analysis-form-item {
margin-top: 20px;
}
</style>
...@@ -32,43 +32,43 @@ ...@@ -32,43 +32,43 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-collapse v-model="optionCollapseActives"> <el-row>
<el-collapse-item title="选项列表" name="1"> <el-col :span="24">
<el-row class="collapse-top"> <el-collapse v-model="optionCollapseActives">
<el-col :span="24"> <el-collapse-item title="选项列表" name="1">
<el-form-item v-for="(option, index) in options" :label="option.optionName" :key="option.optionName" <el-row class="collapse-top">
:prop="'options.' + index + '.optionContent'"> <el-col :span="24">
<el-row :gutter="5"> <el-form-item v-for="(option, index) in options" :label="option.optionName" :key="option.optionName"
<el-col :span="2"> :prop="'options.' + index + '.optionContent'">
<el-input v-model="option.optionName"></el-input> <el-row :gutter="5">
</el-col> <el-col :span="4">
<el-col :span="20"> <el-input v-model="option.optionName"/>
<el-input v-model="option.optionContent" @input="updateTinymceContent(option.optionContent, index, '1')"> </el-col>
<el-button slot="append" @click.prevent="removeOption(option)">删除</el-button> <el-col :span="18">
</el-input> <el-input v-model="option.optionContent" @input="updateTinymceContent(option.optionContent, index, '1')">
</el-col> <el-button slot="append" @click.prevent="removeOption(option)">删除</el-button>
</el-row> </el-input>
</el-form-item> </el-col>
</el-col> </el-row>
</el-row> </el-form-item>
<el-row> </el-col>
<el-col :span="24"> </el-row>
<el-button @click.prevent="addOption()" style="display:block;margin:0 auto">新增选项</el-button> <el-row>
</el-col> <el-col :span="24">
</el-row> <el-button type="success" @click.prevent="addOption()" style="display:block;margin:0 auto">新增选项</el-button>
</el-collapse-item> </el-col>
</el-collapse> </el-row>
<el-collapse v-model="analysisCollapseActives"> </el-collapse-item>
<el-collapse-item title="解析" name="2"> </el-collapse>
<el-row> </el-col>
<el-col :span="24"> </el-row>
<el-form-item :label="$t('table.subject.analysis')" prop="analysis"> <el-row>
<el-input v-model="subjectInfo.analysis" @input="updateTinymceContent(subjectInfo.analysis, tinymceEdit.analysis)"/> <el-col :span="24">
</el-form-item> <el-form-item :label="$t('table.subject.analysis')" prop="analysis" class="analysis-form-item">
</el-col> <el-input v-model="subjectInfo.analysis" @input="updateTinymceContent(subjectInfo.analysis, tinymceEdit.analysis)"/>
</el-row> </el-form-item>
</el-collapse-item> </el-col>
</el-collapse> </el-row>
</div> </div>
</el-col> </el-col>
<el-col :span="14"> <el-col :span="14">
...@@ -82,7 +82,7 @@ ...@@ -82,7 +82,7 @@
<script> <script>
import Tinymce from '@/components/Tinymce' import Tinymce from '@/components/Tinymce'
import { isNotEmpty } from '@/utils/util' import { isNotEmpty, message } from '@/utils/util'
export default { export default {
name: 'MultipleChoices', name: 'MultipleChoices',
...@@ -95,8 +95,8 @@ export default { ...@@ -95,8 +95,8 @@ export default {
default: function () { default: function () {
return { return {
id: '', id: '',
examinationId: '', examinationId: undefined,
categoryId: 0, categoryId: undefined,
subjectName: '', subjectName: '',
choicesContent: this.choices, choicesContent: this.choices,
answer: { answer: {
...@@ -131,7 +131,7 @@ export default { ...@@ -131,7 +131,7 @@ export default {
type: 1, // 类型 0:题目名称,1:选项 type: 1, // 类型 0:题目名称,1:选项
dialogTinymceVisible: false, dialogTinymceVisible: false,
tempValue: '', tempValue: '',
currentEdit: -1, currentEdit: -1
}, },
// 编辑对象 // 编辑对象
tinymceEdit: { tinymceEdit: {
...@@ -161,10 +161,10 @@ export default { ...@@ -161,10 +161,10 @@ export default {
methods: { methods: {
initDefaultOptions () { initDefaultOptions () {
this.options = [ this.options = [
{subjectChoicesId: '', optionName: 'A', optionContent: ''}, { subjectChoicesId: '', optionName: 'A', optionContent: '' },
{subjectChoicesId: '', optionName: 'B', optionContent: ''}, { subjectChoicesId: '', optionName: 'B', optionContent: '' },
{subjectChoicesId: '', optionName: 'C', optionContent: ''}, { subjectChoicesId: '', optionName: 'C', optionContent: '' },
{subjectChoicesId: '', optionName: 'D', optionContent: ''} { subjectChoicesId: '', optionName: 'D', optionContent: '' }
] ]
}, },
setSubjectInfo (subject) { setSubjectInfo (subject) {
...@@ -231,8 +231,8 @@ export default { ...@@ -231,8 +231,8 @@ export default {
resetTempSubject (serialNumber, score) { resetTempSubject (serialNumber, score) {
this.subjectInfo = { this.subjectInfo = {
id: '', id: '',
examinationId: '', examinationId: undefined,
categoryId: 0, categoryId: undefined,
subjectName: '', subjectName: '',
type: 0, type: 0,
choicesType: 0, choicesType: 0,
...@@ -258,7 +258,7 @@ export default { ...@@ -258,7 +258,7 @@ export default {
} }
this.initDefaultOptions() this.initDefaultOptions()
}, },
addOption() { addOption () {
// 校验 // 校验
if (this.options.length > 0) { if (this.options.length > 0) {
let option = this.options[this.options.length - 1] let option = this.options[this.options.length - 1]
...@@ -266,27 +266,27 @@ export default { ...@@ -266,27 +266,27 @@ export default {
message(this, '请先输入选项再添加', 'warning') message(this, '请先输入选项再添加', 'warning')
return return
} }
this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' }); this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' })
} else { } else {
this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' }); this.options.push({ subjectChoicesId: '', optionName: '', optionContent: '' })
} }
}, },
removeOption(item) { removeOption (item) {
let index = this.options.indexOf(item) let index = this.options.indexOf(item)
if (index !== -1) { if (index !== -1) {
this.options.splice(index, 1) this.options.splice(index, 1)
} }
}, },
// 点击事件回调 // 点击事件回调
hasClick(hasClick) { hasClick (hasClick) {
this.editType = 1 this.editType = 1
}, },
initMultipleAnswers() { initMultipleAnswers () {
if (isNotEmpty(this.subjectInfo.answer)) { if (isNotEmpty(this.subjectInfo.answer)) {
this.multipleAnswers = this.subjectInfo.answer.answer.split(',') this.multipleAnswers = this.subjectInfo.answer.answer.split(',')
} }
}, },
getMultipleAnswers() { getMultipleAnswers () {
if (this.multipleAnswers.length > 0) { if (this.multipleAnswers.length > 0) {
return this.multipleAnswers.join(',') return this.multipleAnswers.join(',')
} }
...@@ -297,26 +297,13 @@ export default { ...@@ -297,26 +297,13 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
.editor-content{
margin-top: 20px;
}
.subject-info { .subject-info {
padding-right: 12px; padding-right: 12px;
} }
.subject-tinymce { .subject-tinymce {
padding-left: 12px; padding-left: 12px;
} }
.analysis-form-item {
margin-top: 20px;
}
</style> </style>
...@@ -35,7 +35,6 @@ ...@@ -35,7 +35,6 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
</div>
</el-col> </el-col>
<el-col :span="14"> <el-col :span="14">
<div class="subject-tinymce"> <div class="subject-tinymce">
...@@ -62,8 +61,8 @@ export default { ...@@ -62,8 +61,8 @@ export default {
return { return {
id: '', id: '',
serialNumber: 1, serialNumber: 1,
examinationId: '', examinationId: -1,
categoryId: 0, categoryId: -1,
subjectName: '', subjectName: '',
type: 1, type: 1,
answer: { answer: {
...@@ -159,9 +158,8 @@ export default { ...@@ -159,9 +158,8 @@ export default {
resetTempSubject (serialNumber, score) { resetTempSubject (serialNumber, score) {
this.subjectInfo = { this.subjectInfo = {
id: '', id: '',
serialNumber: 1, examinationId: undefined,
examinationId: '', categoryId: undefined,
categoryId: 0,
subjectName: '', subjectName: '',
type: 1, type: 1,
choicesType: 0, choicesType: 0,
...@@ -180,7 +178,7 @@ export default { ...@@ -180,7 +178,7 @@ export default {
this.subjectInfo.score = score this.subjectInfo.score = score
} }
}, },
initDefaultOptions() { initDefaultOptions () {
} }
} }
......
export const nextSubjectType = {
last: 1,
next: 0,
current: 2
}
export const answerType = {
'true': 'right',
'false': 'incorrect'
}
import { formatDate, commonFilter, isNotEmpty } from '../utils/util' import { formatDate, commonFilter, isNotEmpty } from '../utils/util'
import { statusType, examType, subjectType } from '../utils/constant' import { statusType, examType, subjectType, subjectTypeTag } from '../utils/constant'
/** /**
* 日期格式化 * 日期格式化
...@@ -31,6 +30,9 @@ export function statusTypeFilter (status) { ...@@ -31,6 +30,9 @@ export function statusTypeFilter (status) {
* @returns {string} * @returns {string}
*/ */
export function simpleStrFilter (str, length) { export function simpleStrFilter (str, length) {
if (length === undefined) {
length = 20
}
return commonFilter(str, length) return commonFilter(str, length)
} }
...@@ -48,8 +50,8 @@ export function examTypeFilter (type) { ...@@ -48,8 +50,8 @@ export function examTypeFilter (type) {
* @param status * @param status
* @returns {string} * @returns {string}
*/ */
export function examStatusFilter (status) { export function publicStatusFilter (status) {
return status === 0 ? '已发布' : '未发布' return parseInt(status) === 0 ? '已发布' : '草稿'
} }
/** /**
...@@ -61,3 +63,36 @@ export function subjectTypeFilter (type) { ...@@ -61,3 +63,36 @@ export function subjectTypeFilter (type) {
return subjectType[type] return subjectType[type]
} }
/**
* 题目标签
* @param type
* @returns {*}
*/
export function subjectTypeTagFilter (type) {
return subjectTypeTag[type]
}
/**
* 考试提交状态
* @param type
* @returns {*}
*/
export function submitStatusFilter (type) {
const typeMap = {
0: '待批改',
1: '已批改',
2: '待批改',
3: '统计完成'
}
return typeMap[type]
}
/**
* success状态
* @param status, 自动传入
* @param expectStatus
* @returns {string}
*/
export function simpleTagStatusFilter (status, expectStatus) {
return status === expectStatus ? 'success' : 'warning'
}
...@@ -139,12 +139,14 @@ export default { ...@@ -139,12 +139,14 @@ export default {
actions: '操作', actions: '操作',
edit: '修改', edit: '修改',
view: '查看', view: '查看',
preview: '预览',
publish: '发布', publish: '发布',
draft: '草稿', draft: '草稿',
delete: '删除', delete: '删除',
cancel: '取 消', cancel: '取 消',
confirm: '确 定', confirm: '确 定',
save: '保存', save: '保存',
select: '选择',
saveAndAdd: '保存并添加', saveAndAdd: '保存并添加',
username: '账号', username: '账号',
name: '姓名', name: '姓名',
...@@ -179,10 +181,17 @@ export default { ...@@ -179,10 +181,17 @@ export default {
attention: '注意事项', attention: '注意事项',
startTime: '开始时间', startTime: '开始时间',
endTime: '结束时间', endTime: '结束时间',
totalScore: '考试总分', examTime: '考试时间',
totalScore: '总分',
totalSubject: '题目数', totalSubject: '题目数',
subjectManagement: '题目管理', subjectManagement: '题目管理',
subjectName: '题目名称', subjectName: '题目名称',
userAnswer: '考生答案',
correct: '正确',
inCorrect: '错误',
time: '耗时',
answerCorrectType: '答题结果',
score: '得分',
subject: { subject: {
serialNumber: '序号', serialNumber: '序号',
type: '类型', type: '类型',
...@@ -202,7 +211,7 @@ export default { ...@@ -202,7 +211,7 @@ export default {
modifier: '修改人' modifier: '修改人'
}, },
public: '发布', public: '发布',
retrieve: '回收', withdraw: '撤回',
categoryName: '分类名称', categoryName: '分类名称',
categoryDesc: '分类描述', categoryDesc: '分类描述',
sort: '排序号', sort: '排序号',
...@@ -214,7 +223,8 @@ export default { ...@@ -214,7 +223,8 @@ export default {
examTime: '考试时间', examTime: '考试时间',
submitStatus: '状态', submitStatus: '状态',
details: '详情', details: '详情',
marking: '批改' marking: '批改',
markStatus: '批改状态'
}, },
knowledge: { knowledge: {
knowledgeName: '名称', knowledgeName: '名称',
...@@ -241,8 +251,8 @@ export default { ...@@ -241,8 +251,8 @@ export default {
clientSecretPlainText: '密钥明文', clientSecretPlainText: '密钥明文',
scope: '授权范围', scope: '授权范围',
authorizedGrantTypes: '授权类型', authorizedGrantTypes: '授权类型',
accessTokenValidity: 'token有效期', accessTokenValidity: 'token有效期/秒',
refreshTokenValidity: 'refresh_token有效期' refreshTokenValidity: 'refresh_token有效期/秒'
}, },
route: { route: {
routeId: '路由ID', routeId: '路由ID',
......
...@@ -18,6 +18,7 @@ import VueParticles from 'vue-particles' ...@@ -18,6 +18,7 @@ import VueParticles from 'vue-particles'
import { loadStyle } from './utils/util' import { loadStyle } from './utils/util'
import * as urls from '@/config/env' import * as urls from '@/config/env'
import Spinner from 'vue-spinkit' import Spinner from 'vue-spinkit'
import moment from 'moment'
const iconfontVersion = ['567566_r22zi6t8noas8aor', '599693_0b5sleso3f1j1yvi', '667895_xte3dcfrvbo6r'] const iconfontVersion = ['567566_r22zi6t8noas8aor', '599693_0b5sleso3f1j1yvi', '667895_xte3dcfrvbo6r']
const iconfontUrl = `//at.alicdn.com/t/font_$key.css` const iconfontUrl = `//at.alicdn.com/t/font_$key.css`
...@@ -30,6 +31,8 @@ Vue.use(Element, { ...@@ -30,6 +31,8 @@ Vue.use(Element, {
// 使用登录页粒子效果插件 // 使用登录页粒子效果插件
Vue.use(VueParticles) Vue.use(VueParticles)
Vue.prototype.moment = moment
// loading效果 // loading效果
Vue.component('Spinner', Spinner) Vue.component('Spinner', Spinner)
......
...@@ -114,7 +114,7 @@ export const constantExamRouterMap = [ ...@@ -114,7 +114,7 @@ export const constantExamRouterMap = [
component: Layout, component: Layout,
children: [ children: [
{ {
path: '/exam/exam/subjects/:id', path: '/exam/subjects/:id',
component: () => import('@/views/exam/examSubjects'), component: () => import('@/views/exam/examSubjects'),
name: '题目管理', name: '题目管理',
title: '题目管理', title: '题目管理',
...@@ -127,13 +127,39 @@ export const constantExamRouterMap = [ ...@@ -127,13 +127,39 @@ export const constantExamRouterMap = [
component: Layout, component: Layout,
children: [ children: [
{ {
path: '/exam/:examinationId/subjects/:id/:type', path: '/exam/subjects/detail/:id',
component: () => import('@/views/exam/subjectDetails'), component: () => import('@/views/exam/subjectDetails'),
name: '题目详情', name: '题目详情',
title: '题目详情', title: '题目详情',
noCache: true noCache: true
} }
] ]
},
{
path: '',
component: Layout,
children: [
{
path: '/exam/score/detail/:id',
component: () => import('@/views/exam/scoreDetails'),
name: '成绩详情',
title: '成绩详情',
noCache: true
}
]
},
{
path: '',
component: Layout,
children: [
{
path: '/exam/mark/:id',
component: () => import('@/views/exam/markExam'),
name: '成绩批改',
title: '成绩批改',
noCache: true
}
]
} }
] ]
......
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
body { body {
height: 100%; height: 100%;
-moz-osx-font-smoothing: grayscale; font-family: -apple-system,system-ui,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;
-webkit-font-smoothing: antialiased; font-size: 1rem;
text-rendering: optimizeLegibility; font-weight: 400;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; line-height: 1.5;
color: #292b2c;
background-color: #fff;
} }
label { label {
...@@ -33,7 +35,7 @@ html { ...@@ -33,7 +35,7 @@ html {
} }
.no-padding { .no-padding {
padding: 0px !important; padding: 0 !important;
} }
.padding-content { .padding-content {
...@@ -117,7 +119,6 @@ code { ...@@ -117,7 +119,6 @@ code {
background: rgba(66,185,131,.1); background: rgba(66,185,131,.1);
border-radius: 2px; border-radius: 2px;
padding: 16px; padding: 16px;
padding: 1rem;
line-height: 1.6rem; line-height: 1.6rem;
word-spacing: .05rem; word-spacing: .05rem;
a{ a{
...@@ -128,7 +129,7 @@ code { ...@@ -128,7 +129,7 @@ code {
//main-container全局样式 //main-container全局样式
.app-container { .app-container {
padding: 20px; padding: 12px;
} }
.components-container { .components-container {
...@@ -201,3 +202,7 @@ code { ...@@ -201,3 +202,7 @@ code {
.avatar-uploader .el-upload:hover { .avatar-uploader .el-upload:hover {
border-color: #409EFF; border-color: #409EFF;
} }
.dialog-footer {
text-align: center;
}
...@@ -21,5 +21,4 @@ ...@@ -21,5 +21,4 @@
padding-left: 12px; padding-left: 12px;
} }
.collapse-top { .collapse-top {
margin-top: 20px;
} }
...@@ -8,6 +8,6 @@ $yellow:#FEC171; ...@@ -8,6 +8,6 @@ $yellow:#FEC171;
$panGreen: #30B08F; $panGreen: #30B08F;
//sidebar //sidebar
$menuBg:#304156; $menuBg:#282828;
$subMenuBg:#1f2d3d; $subMenuBg:#282828;
$menuHover:#001528; $menuHover:#282828;
...@@ -19,6 +19,14 @@ export const examType = { ...@@ -19,6 +19,14 @@ export const examType = {
// 题目类型 // 题目类型
export const subjectType = { export const subjectType = {
0: '单选题', 0: '单选题',
2: '判断题',
1: '简答题', 1: '简答题',
3: '多选题' 3: '多选题'
} }
export const subjectTypeTag = {
0: 'success',
1: 'info',
2: 'warning',
3: 'default'
}
...@@ -237,7 +237,7 @@ export const checkMultipleSelect = (multipleSelection, obj) => { ...@@ -237,7 +237,7 @@ export const checkMultipleSelect = (multipleSelection, obj) => {
* 设置浏览器头部标题 * 设置浏览器头部标题
*/ */
export const setTitle = function (title) { export const setTitle = function (title) {
title = title ? `${title}——系统演示` : '系统演示' title = title ? `${title}——硕果云` : '硕果云'
window.document.title = title window.document.title = title
} }
...@@ -319,6 +319,15 @@ export const messageSuccess = (obj, message) => { ...@@ -319,6 +319,15 @@ export const messageSuccess = (obj, message) => {
} }
/** /**
* 警告消息提示
* @param obj
* @param message
*/
export const messageWarn = (obj, message) => {
obj.$message({ message: message, type: 'warning' })
}
/**
* 失败消息提示 * 失败消息提示
* @param obj * @param obj
* @param message * @param message
...@@ -389,3 +398,7 @@ export const commonFilter = (str, length) => { ...@@ -389,3 +398,7 @@ export const commonFilter = (str, length) => {
export const isCreate = (status) => { export const isCreate = (status) => {
return status === 'create' return status === 'create'
} }
export const trimComma = (str) => {
return str.replace(new RegExp('^,*|,*$', 'gm'), '')
}
...@@ -73,7 +73,6 @@ import { fetchList, addObj, putObj, delAttachment, getDownloadUrl } from '@/api/ ...@@ -73,7 +73,6 @@ import { fetchList, addObj, putObj, delAttachment, getDownloadUrl } from '@/api/
import waves from '@/directive/waves' import waves from '@/directive/waves'
import { getToken } from '@/utils/auth' // getToken from cookie import { getToken } from '@/utils/auth' // getToken from cookie
import { notifySuccess, messageSuccess, isNotEmpty, formatDate } from '@/utils/util' import { notifySuccess, messageSuccess, isNotEmpty, formatDate } from '@/utils/util'
import { mapState } from 'vuex'
import SpinnerLoading from '@/components/SpinnerLoading' import SpinnerLoading from '@/components/SpinnerLoading'
export default { export default {
......
<template>
<div :class="className" :style="{height:height,width:width}"/>
</template>
<script>
import echarts from 'echarts' // echarts theme
import { debounce } from '@/utils'
require('echarts/theme/macarons')
export default {
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '350px'
}
},
data () {
return {
chart: null
}
},
mounted () {
this.initChart()
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
},
beforeDestroy () {
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHandler)
this.chart.dispose()
this.chart = null
},
methods: {
initChart () {
this.chart = echarts.init(this.$el, 'macarons')
this.chart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
bottom: '10',
left: 'center',
data: ['4级', '5级', '6级']
},
series: [
{
name: '难度等级分布',
type: 'pie',
selectedMode: 'single',
radius: [0, '30%'],
label: {
position: 'inner'
},
labelLine: {
show: false
},
data: [
]
},
{
name: '难度等级分布',
type: 'pie',
radius: ['40%', '55%'],
label: {
normal: {
formatter: function (param) {
return param.name + '\n' + Math.round(param.percent) + '%'
}
}
},
data: [
{ value: 12, name: '4级' },
{ value: 11, name: '5级' },
{ value: 7, name: '6级' }
],
animationEasing: 'cubicInOut',
animationDuration: 2600
}
]
})
}
}
}
</script>
...@@ -21,7 +21,7 @@ export default { ...@@ -21,7 +21,7 @@ export default {
}, },
height: { height: {
type: String, type: String,
default: '300px' default: '350px'
} }
}, },
data () { data () {
...@@ -66,7 +66,7 @@ export default { ...@@ -66,7 +66,7 @@ export default {
}, },
xAxis: [{ xAxis: [{
type: 'category', type: 'category',
data: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'], data: ['初级', '中级', '高级'],
axisTick: { axisTick: {
alignWithLabel: true alignWithLabel: true
} }
...@@ -78,25 +78,15 @@ export default { ...@@ -78,25 +78,15 @@ export default {
} }
}], }],
series: [{ series: [{
name: 'pageA', name: '考生水平分布',
type: 'bar', type: 'bar',
stack: 'vistors', stack: 'vistors',
barWidth: '60%', barWidth: '30%',
data: [79, 52, 200, 334, 390, 330, 220], data: [14, 4, 3],
animationDuration label: {
}, { show: true,
name: 'pageB', position: 'top'
type: 'bar', },
stack: 'vistors',
barWidth: '60%',
data: [80, 52, 200, 334, 390, 330, 220],
animationDuration
}, {
name: 'pageC',
type: 'bar',
stack: 'vistors',
barWidth: '60%',
data: [30, 52, 200, 334, 390, 330, 220],
animationDuration animationDuration
}] }]
}) })
......
...@@ -19,7 +19,7 @@ export default { ...@@ -19,7 +19,7 @@ export default {
}, },
height: { height: {
type: String, type: String,
default: '350px' default: '400px'
}, },
autoResize: { autoResize: {
type: Boolean, type: Boolean,
...@@ -78,10 +78,10 @@ export default { ...@@ -78,10 +78,10 @@ export default {
this.__resizeHandler() this.__resizeHandler()
} }
}, },
setOptions ({ expectedData, actualData } = {}) { setOptions ({ examRecordDate, examRecordData } = {}) {
this.chart.setOption({ this.chart.setOption({
xAxis: { xAxis: {
data: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'], data: examRecordDate,
boundaryGap: false, boundaryGap: false,
axisTick: { axisTick: {
show: false show: false
...@@ -107,27 +107,10 @@ export default { ...@@ -107,27 +107,10 @@ export default {
} }
}, },
legend: { legend: {
data: ['预期', '实际'] data: ['考试记录数']
}, },
series: [{ series: [{
name: '预期', name: '考试记录数',
itemStyle: {
normal: {
color: '#FF005A',
lineStyle: {
color: '#FF005A',
width: 2
}
}
},
smooth: true,
type: 'line',
data: expectedData,
animationDuration: 2800,
animationEasing: 'cubicInOut'
},
{
name: '实际',
smooth: true, smooth: true,
type: 'line', type: 'line',
itemStyle: { itemStyle: {
...@@ -142,7 +125,7 @@ export default { ...@@ -142,7 +125,7 @@ export default {
} }
} }
}, },
data: actualData, data: examRecordData,
animationDuration: 2800, animationDuration: 2800,
animationEasing: 'quadraticOut' animationEasing: 'quadraticOut'
}] }]
...@@ -155,4 +138,3 @@ export default { ...@@ -155,4 +138,3 @@ export default {
} }
} }
</script> </script>
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
<svg-icon icon-class="chart" class-name="card-panel-icon" /> <svg-icon icon-class="chart" class-name="card-panel-icon" />
</div> </div>
<div class="card-panel-description"> <div class="card-panel-description">
<div class="card-panel-text">课程</div> <div class="card-panel-text">考试次</div>
<count-to :start-val="0" :end-val="13600" :duration="2600" class="card-panel-num"/> <count-to :start-val="0" :end-val="examinationRecordNumber" :duration="2600" class="card-panel-num"/>
</div> </div>
</div> </div>
</el-col> </el-col>
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
<script> <script>
import CountTo from 'vue-count-to' import CountTo from 'vue-count-to'
import { getDashboard } from '@/api/admin/sys' import { getDashboard } from '@/api/admin/sys'
import { isNotEmpty, isSuccess, messageFail } from '@/utils/util' import { isNotEmpty, isSuccess } from '@/utils/util'
export default { export default {
components: { components: {
...@@ -61,7 +61,8 @@ export default { ...@@ -61,7 +61,8 @@ export default {
onlineUserNumber: 0, onlineUserNumber: 0,
examinationNumber: 0, examinationNumber: 0,
examUserNumber: 0, examUserNumber: 0,
tenantNumber: 0 tenantNumber: 0,
examinationRecordNumber: 0
} }
}, },
created () { created () {
...@@ -88,6 +89,9 @@ export default { ...@@ -88,6 +89,9 @@ export default {
if (isNotEmpty(data.tenantCount)) { if (isNotEmpty(data.tenantCount)) {
this.tenantNumber = parseInt(data.tenantCount) this.tenantNumber = parseInt(data.tenantCount)
} }
if (isNotEmpty(data.examinationRecordNumber)) {
this.examinationRecordNumber = parseInt(data.examinationRecordNumber)
}
} }
}).catch(error => { }).catch(error => {
console.error(error) console.error(error)
...@@ -113,7 +117,6 @@ export default { ...@@ -113,7 +117,6 @@ export default {
box-shadow: 0 2px 12px 0 rgba(0,0,0,.1); box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
border-color: rgba(0, 0, 0, .05); border-color: rgba(0, 0, 0, .05);
border-radius: 6px; border-radius: 6px;
border-top: 3px solid #40c9c6;
&:hover { &:hover {
.card-panel-icon-wrapper { .card-panel-icon-wrapper {
color: #fff; color: #fff;
......
...@@ -19,7 +19,7 @@ export default { ...@@ -19,7 +19,7 @@ export default {
}, },
height: { height: {
type: String, type: String,
default: '300px' default: '350px'
} }
}, },
data () { data () {
...@@ -47,7 +47,6 @@ export default { ...@@ -47,7 +47,6 @@ export default {
methods: { methods: {
initChart () { initChart () {
this.chart = echarts.init(this.$el, 'macarons') this.chart = echarts.init(this.$el, 'macarons')
this.chart.setOption({ this.chart.setOption({
tooltip: { tooltip: {
trigger: 'item', trigger: 'item',
...@@ -56,25 +55,37 @@ export default { ...@@ -56,25 +55,37 @@ export default {
legend: { legend: {
left: 'center', left: 'center',
bottom: '10', bottom: '10',
data: ['语文', '数学', '英语', '化学', '物理'] data: ['越南', '泰国', '苏丹', '蒙古', '老挝', '韩国', '哈萨克斯坦', '俄罗斯', '阿塞拜疆', '阿富汗']
}, },
calculable: true, calculable: true,
series: [ series: [
{ {
name: 'WEEKLY WRITE ARTICLES', name: '考生分布图',
type: 'pie', type: 'pie',
roseType: 'radius', roseType: 'radius',
radius: [15, 95], radius: [15, 95],
center: ['50%', '38%'], center: ['50%', '38%'],
data: [ data: [
{ value: 320, name: '语文' }, { value: 1, name: '越南' },
{ value: 240, name: '数学' }, { value: 3, name: '泰国' },
{ value: 149, name: '英语' }, { value: 1, name: '苏丹' },
{ value: 100, name: '化学' }, { value: 1, name: '蒙古' },
{ value: 59, name: '物理' } { value: 3, name: '老挝' },
{ value: 1, name: '韩国' },
{ value: 3, name: '哈萨克斯坦' },
{ value: 5, name: '俄罗斯' },
{ value: 1, name: '阿塞拜疆' },
{ value: 1, name: '阿富汗' }
], ],
animationEasing: 'cubicInOut', animationEasing: 'cubicInOut',
animationDuration: 2600 animationDuration: 2600,
label: {
normal: {
formatter: function (param) {
return param.name + '\n' + Math.round(param.percent) + '%'
}
}
}
} }
] ]
}) })
......
...@@ -21,7 +21,7 @@ export default { ...@@ -21,7 +21,7 @@ export default {
}, },
height: { height: {
type: String, type: String,
default: '300px' default: '350px'
} }
}, },
data () { data () {
......
...@@ -5,28 +5,37 @@ ...@@ -5,28 +5,37 @@
<el-row class="chart-wrapper" style="background:#fff;padding:16px 16px 0;margin-bottom:32px;"> <el-row class="chart-wrapper" style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
<div class="chart-wrapper-header"> <div class="chart-wrapper-header">
<div>趋势</div> <div>考试记录数</div>
<div class="chart-wrapper-header-select">
<el-select v-model="query.pastDays" placeholder="请选择" size="mini" @change="getExamRecordData">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</div> </div>
<div class="chart-wrapper-body"> <div class="chart-wrapper-body">
<line-chart :chart-data="lineChartData"/> <line-chart :chart-data="lineChartData"/>
</div> </div>
</el-row> </el-row>
<el-row :gutter="32"> <el-row :gutter="32">
<el-col :xs="24" :sm="24" :lg="8"> <el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper"> <div class="chart-wrapper">
<div class="chart-wrapper-header"> <div class="chart-wrapper-header">
<div>趋势</div> <div>难度等级分布</div>
</div> </div>
<div class="chart-wrapper-body"> <div class="chart-wrapper-body">
<raddar-chart/> <another-pie-chart/>
</div> </div>
</div> </div>
</el-col> </el-col>
<el-col :xs="24" :sm="24" :lg="8"> <el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper"> <div class="chart-wrapper">
<div class="chart-wrapper-header"> <div class="chart-wrapper-header">
<div>趋势</div> <div>考生分布图</div>
</div> </div>
<div class="chart-wrapper-body"> <div class="chart-wrapper-body">
<pie-chart/> <pie-chart/>
...@@ -36,7 +45,7 @@ ...@@ -36,7 +45,7 @@
<el-col :xs="24" :sm="24" :lg="8"> <el-col :xs="24" :sm="24" :lg="8">
<div class="chart-wrapper"> <div class="chart-wrapper">
<div class="chart-wrapper-header"> <div class="chart-wrapper-header">
<div>趋势</div> <div>考生水平分布</div>
</div> </div>
<div class="chart-wrapper-body"> <div class="chart-wrapper-body">
<bar-chart/> <bar-chart/>
...@@ -44,7 +53,6 @@ ...@@ -44,7 +53,6 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</template> </template>
...@@ -53,24 +61,23 @@ import PanelGroup from './components/PanelGroup' ...@@ -53,24 +61,23 @@ import PanelGroup from './components/PanelGroup'
import LineChart from './components/LineChart' import LineChart from './components/LineChart'
import RaddarChart from './components/RaddarChart' import RaddarChart from './components/RaddarChart'
import PieChart from './components/PieChart' import PieChart from './components/PieChart'
import AnotherPieChart from './components/AnotherPieChart'
import BarChart from './components/BarChart' import BarChart from './components/BarChart'
import { getExamRecordTendency } from '@/api/admin/sys'
const lineChartData = { const dashboardData = {
newVisitis: { examRecordData: {
expectedData: [100, 120, 161, 134, 105, 160, 165], data: [120, 82, 91, 154, 162, 140, 145],
actualData: [120, 82, 91, 154, 162, 140, 145] date: ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日']
}, },
messages: { messages: {
expectedData: [200, 192, 120, 144, 160, 130, 140], examRecordData: [180, 160, 151, 106, 145, 150, 130]
actualData: [180, 160, 151, 106, 145, 150, 130]
}, },
purchases: { purchases: {
expectedData: [80, 100, 121, 104, 105, 90, 100], examRecordData: [120, 90, 100, 138, 142, 130, 130]
actualData: [120, 90, 100, 138, 142, 130, 130]
}, },
shoppings: { shoppings: {
expectedData: [130, 140, 141, 142, 145, 150, 160], examRecordData: [120, 82, 91, 154, 162, 140, 130]
actualData: [120, 82, 91, 154, 162, 140, 130]
} }
} }
...@@ -81,16 +88,41 @@ export default { ...@@ -81,16 +88,41 @@ export default {
LineChart, LineChart,
RaddarChart, RaddarChart,
PieChart, PieChart,
AnotherPieChart,
BarChart BarChart
}, },
created () {
this.getExamRecordData()
},
data () { data () {
return { return {
lineChartData: lineChartData.newVisitis query: {
pastDays: 7
},
lineChartData: {
examRecordData: [],
examRecordDate: []
},
options: [{
value: 7,
label: '过去7天'
}, {
value: 15,
label: '过去15天'
}, {
value: 30,
label: '过去30天'
}]
} }
}, },
methods: { methods: {
handleSetLineChartData (type) { handleSetLineChartData (type) {
this.lineChartData = lineChartData[type] this.lineChartData = dashboardData[type]
},
getExamRecordData () {
getExamRecordTendency(this.query).then(response => {
this.lineChartData = response.data.data
})
} }
} }
} }
...@@ -98,7 +130,7 @@ export default { ...@@ -98,7 +130,7 @@ export default {
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.dashboard-editor-container { .dashboard-editor-container {
padding: 20px; padding: 12px;
.chart-wrapper { .chart-wrapper {
background: #fff; background: #fff;
padding: 16px 16px 0; padding: 16px 16px 0;
...@@ -110,6 +142,12 @@ export default { ...@@ -110,6 +142,12 @@ export default {
border-bottom: 1px solid #EBEEF5; border-bottom: 1px solid #EBEEF5;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
.chart-wrapper-header-select {
position: absolute;
right: 0;
top: 6px;
padding: 8px 12px;
}
} }
.chart-wrapper-body { .chart-wrapper-body {
padding-top: 20px; padding-top: 20px;
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
<div class="filter-container"> <div class="filter-container">
<el-input v-model="listQuery.courseName" placeholder="课程名称" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input v-model="listQuery.courseName" placeholder="课程名称" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button v-if="course_btn_add" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button v-if="course_btn_add" class="filter-item" type="primary" style="margin-left: 10px;" icon="el-icon-check" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button v-if="course_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="course_btn_del" class="filter-item" type="danger" icon="el-icon-delete" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<el-table <el-table
...@@ -40,8 +40,8 @@ ...@@ -40,8 +40,8 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="course_btn_edit" type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="course_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="course_btn_del" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete">{{ $t('table.delete') }}</el-button> <el-button v-if="course_btn_del" type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -275,8 +275,6 @@ export default { ...@@ -275,8 +275,6 @@ export default {
this.getList() this.getList()
notifySuccess(this, '删除成功') notifySuccess(this, '删除成功')
}) })
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}).catch(() => {}) }).catch(() => {})
}, },
// 批量删除 // 批量删除
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
<div class="filter-container"> <div class="filter-container">
<el-input :placeholder="$t('table.examinationName')" v-model="listQuery.examinationName" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input :placeholder="$t('table.examinationName')" v-model="listQuery.examinationName" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button v-if="exam_btn_add" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button v-if="exam_btn_add" class="filter-item" type="primary" style="margin-left: 10px;" icon="el-icon-check" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button v-if="exam_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="exam_btn_del" class="filter-item" type="danger" icon="el-icon-delete" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<!--考试列表--> <!--考试列表-->
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
<span>{{ scope.row.examinationName | simpleStrFilter }}</span> <span>{{ scope.row.examinationName | simpleStrFilter }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.type')"> <el-table-column :label="$t('table.examinationType')">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.type | examTypeFilter }}</span> <span>{{ scope.row.type | examTypeFilter }}</span>
</template> </template>
...@@ -33,14 +33,9 @@ ...@@ -33,14 +33,9 @@
<span>{{ scope.row | courseFilter }}</span> <span>{{ scope.row | courseFilter }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.startTime')"> <el-table-column :label="$t('table.examTime')" width="300">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.startTime | fmtDate('yyyy-MM-dd hh:mm') }}</span> <span>{{ scope.row.startTime | fmtDate('yyyy-MM-dd hh:mm') }}~{{ scope.row.endTime | fmtDate('yyyy-MM-dd hh:mm') }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.endTime')">
<template slot-scope="scope">
<span>{{ scope.row.endTime | fmtDate('yyyy-MM-dd hh:mm') }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.totalScore')"> <el-table-column :label="$t('table.totalScore')">
...@@ -50,16 +45,16 @@ ...@@ -50,16 +45,16 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.status')"> <el-table-column :label="$t('table.status')">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.status | statusTypeFilter ">{{ scope.row.status | examStatusFilter }}</el-tag> <el-tag :type="scope.row.status | statusTypeFilter " effect="dark" size="small">{{ scope.row.status | publicStatusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="400">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="exam_btn_edit" type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="exam_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="exam_btn_edit && scope.row.status == 1" type="text" @click="handlePublic(scope.row, 0)" icon="el-icon-check">{{ $t('table.public') }}</el-button> <el-button v-if="exam_btn_edit && scope.row.status == 1" type="success" size="mini" @click="handlePublic(scope.row, 0)">{{ $t('table.public') }}</el-button>
<el-button v-if="exam_btn_edit && scope.row.status == 0" type="text" @click="handlePublic(scope.row, 1)" icon="el-icon-remove-outline">{{ $t('table.retrieve') }}</el-button> <el-button v-if="exam_btn_edit && scope.row.status == 0" type="info" size="mini" @click="handlePublic(scope.row, 1)">{{ $t('table.withdraw') }}</el-button>
<el-button v-if="exam_btn_subject" type="text" @click="handleSubjectManagement(scope.row)" icon="el-icon-document">{{ $t('table.subjectManagement') }}</el-button> <el-button v-if="exam_btn_subject" type="success" size="mini" @click="handleSubjectManagement(scope.row)">{{ $t('table.subjectManagement') }}</el-button>
<el-button v-if="exam_btn_del" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete">{{ $t('table.delete') }}</el-button> <el-button v-if="exam_btn_del" type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -377,7 +372,7 @@ export default { ...@@ -377,7 +372,7 @@ export default {
endTime: '', endTime: '',
duration: '', duration: '',
totalScore: '', totalScore: '',
status: 0, status: 1,
avatar: '', avatar: '',
collegeId: '', collegeId: '',
majorId: '', majorId: '',
...@@ -460,8 +455,6 @@ export default { ...@@ -460,8 +455,6 @@ export default {
this.getList() this.getList()
notifySuccess(this, '删除成功') notifySuccess(this, '删除成功')
}) })
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}).catch(() => {}) }).catch(() => {})
}, },
// 批量删除 // 批量删除
...@@ -502,7 +495,7 @@ export default { ...@@ -502,7 +495,7 @@ export default {
// 加载题目 // 加载题目
handleSubjectManagement (row) { handleSubjectManagement (row) {
this.$router.push({ this.$router.push({
path: `/exam/exam/subjects/${row.id}`, path: `/exam/subjects/${row.id}`
}) })
}, },
// 发布考试 // 发布考试
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
<div class="filter-container"> <div class="filter-container">
<el-input v-model="listQuery.knowledgeName" placeholder="知识名称" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input v-model="listQuery.knowledgeName" placeholder="知识名称" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button class="filter-item" style="margin-left: 10px;" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button class="filter-item" type="primary" style="margin-left: 10px;" icon="el-icon-check" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button class="filter-item" type="danger" icon="el-icon-delete" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<el-table <el-table
...@@ -30,15 +30,15 @@ ...@@ -30,15 +30,15 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.knowledge.status')" min-width="90"> <el-table-column :label="$t('table.knowledge.status')" min-width="90">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.status | statusTypeFilter">{{ scope.row.status | statusFilter }}</el-tag> <el-tag :type="scope.row.status | statusTypeFilter" effect="dark" size="small">{{ scope.row.status | publicStatusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300px"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300px">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="scope.row.status == 1" type="text" @click="handlePublic(scope.row, 0)" icon="el-icon-check">{{ $t('table.public') }}</el-button> <el-button type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="scope.row.status == 0" type="text" @click="handlePublic(scope.row, 1)" icon="el-icon-remove-outline">{{ $t('table.retrieve') }}</el-button> <el-button v-if="scope.row.status == 1" type="success" size="mini" @click="handlePublic(scope.row, 0)">{{ $t('table.public') }}</el-button>
<el-button type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="scope.row.status == 0" type="info" size="mini" @click="handlePublic(scope.row, 1)">{{ $t('table.withdraw') }}</el-button>
<el-button type="text" @click="handleDelete(scope.row)" icon="el-icon-delete">{{ $t('table.delete') }}</el-button> <el-button type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
<el-row> <el-row>
<el-col :span="24"> <el-col :span="24">
<el-upload <el-upload
v-show="temp.id !== undefined"
:show-file-list="showFileList" :show-file-list="showFileList"
:on-success="handleUploadSuccess" :on-success="handleUploadSuccess"
:on-exceed="handleExceed" :on-exceed="handleExceed"
...@@ -134,7 +135,7 @@ export default { ...@@ -134,7 +135,7 @@ export default {
order: 'descending' order: 'descending'
}, },
temp: { temp: {
id: '', id: undefined,
knowledgeName: '', knowledgeName: '',
knowledgeDesc: '', knowledgeDesc: '',
attachmentId: '', attachmentId: '',
...@@ -223,7 +224,7 @@ export default { ...@@ -223,7 +224,7 @@ export default {
}, },
resetTemp () { resetTemp () {
this.temp = { this.temp = {
id: '', id: undefined,
knowledgeName: '', knowledgeName: '',
knowledgeDesc: '', knowledgeDesc: '',
attachmentId: '', attachmentId: '',
...@@ -285,8 +286,6 @@ export default { ...@@ -285,8 +286,6 @@ export default {
this.getList() this.getList()
notifySuccess(this, '删除成功') notifySuccess(this, '删除成功')
}) })
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}).catch(() => {}) }).catch(() => {})
}, },
// 批量删除 // 批量删除
......
<template>
<div class="details-container">
<el-row :gutter="40">
<el-col :span="24">
<el-card class="score-info">
<div slot="header">
<span>成绩详情</span>
</div>
<el-row>
<el-col :span="6">
<div class="user-info">
<span class="user-info-item" :title="examRecord.examinationName">考试名称:{{ examRecord.examinationName | simpleStrFilter }}</span>
<br>
<span class="user-info-item" v-show="examRecord.userName !== undefined && examRecord.userName !== ''">考生姓名:{{ examRecord.userName }}</span>
<br>
<span class="user-info-item" v-show="examRecord.deptName !== undefined && examRecord.deptName !== ''">所属部门:{{ examRecord.deptName }}</span>
<br>
<span class="user-info-item" v-show="examRecord.startTime !== undefined && examRecord.startTime !== ''">考试时间:
<el-tag type="info" >{{ examRecord.startTime | fmtDate('yyyy.MM.dd hh:mm') }}</el-tag>
~
<el-tag type="info">{{ examRecord.endTime | fmtDate('yyyy.MM.dd hh:mm') }}</el-tag>
</span>
<br>
</div>
</el-col>
<el-col :span="3">
<div class="description">
<div>成绩</div>
<div class="description-score">{{ examRecord.score }}</div>
</div>
</el-col>
<el-col :span="3">
<div class="description">
<div>耗时</div>
<div class="description-score">{{ examRecord.duration }}</div>
</div>
</el-col>
<el-col :span="6">
<div class="score-chart">
<div class="chart" ref="chart" style="height: 150px; width: 100%;"></div>
</div>
</el-col>
</el-row>
</el-card>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-card class="subject-list">
<el-table
ref="multipleTable"
:key="tableKey"
:data="list"
:default-sort="{ prop: 'id', order: 'descending' }"
highlight-current-row
style="width: 100%;">
<el-table-column :label="$t('table.subjectName')" min-width="120">
<template slot-scope="scope">
<span>{{ scope.row.subject.subjectName | simpleStrFilter(15) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.subject.type')" min-width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.subject.type | subjectTypeTagFilter" effect="dark" size="small">{{ scope.row.subject.type | subjectTypeFilter }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('table.userAnswer')" min-width="120">
<template slot-scope="scope">
<span>{{ scope.row.answer | simpleStrFilter(15) }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.subject.answer')" min-width="120">
<template slot-scope="scope">
<span>{{ scope.row.subject.answer.answer | simpleStrFilter }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.examRecord.markStatus')" min-width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.markStatus | simpleTagStatusFilter(1)" effect="dark" size="small">{{ scope.row.markStatus | submitStatusFilter }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('table.answerCorrectType')" min-width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.answerType | simpleTagStatusFilter(0)" effect="dark" size="small">{{ scope.row.answerType | correctTypeFilter }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('table.time')" min-width="90">
<template slot-scope="scope">
<span>{{ scope.row.duration }}</span>
</template>
</el-table-column>
<el-table-column :label="$t('table.score')" min-width="90">
<template slot-scope="scope">
<span>{{ scope.row.score }}</span>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import CountTo from 'vue-count-to'
import waves from '@/directive/waves'
import { mapGetters } from 'vuex'
import SpinnerLoading from '@/components/SpinnerLoading'
import echarts from 'echarts'
import { examRecordDetails } from '@/api/exam/examRecord'
import { messageFail } from '@/utils/util'
require('echarts/theme/macarons')
export default {
name: 'ScoreDetails',
components: { SpinnerLoading, CountTo },
directives: {
waves
},
filters: {
correctTypeFilter (type) {
const correctTypeMap = {
0: '正确',
1: '错误'
}
return correctTypeMap[type]
}
},
data () {
return {
score: 90,
time: '50分钟',
chart: null,
chartData: [],
tableKey: 0,
list: [],
examRecordId: undefined,
examRecord: {
examinationName: '',
userName: '',
deptName: '',
score: 0,
startTime: '',
endTime: '',
duration: ''
}
}
},
created () {
this.examRecordId = this.$route.params.id
this.getExamRecord()
},
computed: {
...mapGetters([
'elements',
'permissions'
])
},
methods: {
getExamRecord () {
examRecordDetails(this.examRecordId).then(response => {
if (response.data.data === null) {
messageFail(this, '加载成绩失败')
return
}
this.examRecord = response.data.data
const { inCorrectNumber, correctNumber, answers } = this.examRecord
this.chartData.push({ name: '错误数', value: inCorrectNumber })
this.chartData.push({ name: '正确数', value: correctNumber })
this.list = answers
this.initChart()
}).catch(() => {
messageFail(this, '加载成绩失败')
})
},
initChart () {
this.chart = echarts.init(this.$refs.chart, 'macarons')
this.chart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
series: [
{
name: '答题统计',
type: 'pie',
radius: ['50%', '70%'],
avoidLabelOverlap: false,
animationEasing: 'cubicInOut',
animationDuration: 2600,
label: {
normal: {
formatter: function (param) {
return param.name + ': ' + Math.round(param.value)
}
}
},
data: this.chartData
}
]
})
}
}
}
</script>
<style lang="scss" scoped>
.dialog-footer {
margin-top: 20px;
}
.details-container {
padding: 12px;
.score-info {
height: 250px;
}
}
.user-info {
font-size: 13px;
.user-info-item {
display:inline-block;
padding:5px 10px;
cursor:pointer;
}
}
.description {
display: inline-block;
padding: 20px 0 0 20px;
font-size: 18px;
opacity: .9;
.description-score {
padding-top: 8px;
font-size: 24px;
}
}
.subject-list {
padding: 12px;
margin-top: 12px;
}
</style>
...@@ -3,18 +3,38 @@ ...@@ -3,18 +3,38 @@
<el-tabs v-model="activeName" @tab-click="handleTabChange"> <el-tabs v-model="activeName" @tab-click="handleTabChange">
<!-- 单选题 --> <!-- 单选题 -->
<el-tab-pane label="单选题" name="0" :disabled="tempSubject.type !== 0 && dialogStatus !== dialogStatusType.create"> <el-tab-pane label="单选题" name="0" :disabled="tempSubject.type !== 0 && dialogStatus !== dialogStatusType.create">
<choices ref="choices" subjectInfo="tempSubject"></choices> <transition name="el-fade-in">
<choices ref="choices" subjectInfo="tempSubject"/>
</transition>
</el-tab-pane> </el-tab-pane>
<!-- 多选题 --> <!-- 多选题 -->
<el-tab-pane label="多选题" name="3" :disabled="tempSubject.type !== 3 && dialogStatus !== dialogStatusType.create"> <el-tab-pane label="多选题" name="3" :disabled="tempSubject.type !== 3 && dialogStatus !== dialogStatusType.create">
<multiple-choices ref="multipleChoices" subjectInfo="tempSubject"></multiple-choices> <transition name="el-fade-in">
<multiple-choices ref="multipleChoices" subjectInfo="tempSubject"/>
</transition>
</el-tab-pane>
<!-- 判断题 -->
<el-tab-pane label="判断题" name="2" :disabled="tempSubject.type !== 2 && dialogStatus !== dialogStatusType.create">
<transition name="el-fade-in">
<judgement ref="judgement" subjectInfo="tempSubject"/>
</transition>
</el-tab-pane> </el-tab-pane>
<!-- 简答题 --> <!-- 简答题 -->
<el-tab-pane label="简答题" name="1" :disabled="tempSubject.type !== 1 && dialogStatus !== dialogStatusType.create"> <el-tab-pane label="简答题" name="1" :disabled="tempSubject.type !== 1 && dialogStatus !== dialogStatusType.create">
<short-answer ref="shortAnswer" subjectInfo="tempSubject"></short-answer> <transition name="el-fade-in">
<short-answer ref="shortAnswer" subjectInfo="tempSubject"/>
</transition>
</el-tab-pane>
<!-- 从题库新增 -->
<el-tab-pane name="4" v-if="subjectsType === '0'" :disabled="dialogStatus !== dialogStatusType.create">
<span slot="label"><i class="el-icon-document"/> 从题库新增</span>
<transition name="el-fade-in">
<category-subjects ref="addFromSubjects" @selected="handleSelectSubject"/>
</transition>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<div slot="footer" class="dialog-footer collapse-top"> <div slot="footer" class="dialog-footer collapse-top" v-show="activeName !== '4'">
<el-button @click="dialogSubjectFormVisible = false">{{ $t('table.cancel') }}</el-button> <el-button @click="dialogSubjectFormVisible = false">{{ $t('table.cancel') }}</el-button>
<el-button v-if="dialogStatus === dialogStatusType.create" type="primary" @click="createSubjectData">{{ $t('table.save') }}</el-button> <el-button v-if="dialogStatus === dialogStatusType.create" type="primary" @click="createSubjectData">{{ $t('table.save') }}</el-button>
<el-button v-else type="primary" @click="updateSubjectData">{{ $t('table.save') }}</el-button> <el-button v-else type="primary" @click="updateSubjectData">{{ $t('table.save') }}</el-button>
...@@ -26,7 +46,7 @@ ...@@ -26,7 +46,7 @@
<script> <script>
import waves from '@/directive/waves' import waves from '@/directive/waves'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import { getSubject, addSubject, putSubject, delSubject, exportSubject } from '@/api/exam/subject' import { getSubject, addSubject, putSubject } from '@/api/exam/subject'
import { notifySuccess, isNotEmpty, isCreate } from '@/utils/util' import { notifySuccess, isNotEmpty, isCreate } from '@/utils/util'
import { dialogStatusConstant } from '@/utils/constant' import { dialogStatusConstant } from '@/utils/constant'
import SpinnerLoading from '@/components/SpinnerLoading' import SpinnerLoading from '@/components/SpinnerLoading'
...@@ -34,10 +54,12 @@ import Tinymce from '@/components/Tinymce' ...@@ -34,10 +54,12 @@ import Tinymce from '@/components/Tinymce'
import Choices from '@/components/Subjects/Choices' import Choices from '@/components/Subjects/Choices'
import MultipleChoices from '@/components/Subjects/MultipleChoices' import MultipleChoices from '@/components/Subjects/MultipleChoices'
import ShortAnswer from '@/components/Subjects/ShortAnswer' import ShortAnswer from '@/components/Subjects/ShortAnswer'
import Judgement from '@/components/Subjects/Judgement'
import CategorySubjects from '@/components/Subjects/CategorySubjects'
export default { export default {
name: 'CourseManagement', name: 'SubjectDetails',
components: { Tinymce, SpinnerLoading, Choices, MultipleChoices, ShortAnswer }, components: { Tinymce, SpinnerLoading, Choices, MultipleChoices, ShortAnswer, Judgement, CategorySubjects },
directives: { directives: {
waves waves
}, },
...@@ -47,12 +69,13 @@ export default { ...@@ -47,12 +69,13 @@ export default {
activeName: '0', activeName: '0',
dialogStatus: '', dialogStatus: '',
dialogStatusType: { ...dialogStatusConstant }, dialogStatusType: { ...dialogStatusConstant },
examinationId: '', examinationId: undefined,
categoryId: undefined,
// 题目临时信息 // 题目临时信息
tempSubject: { tempSubject: {
id: '', id: '',
examinationId: '', examinationId: undefined,
categoryId: 0, categoryId: undefined,
subjectName: '', subjectName: '',
type: 0, type: 0,
choicesType: 0, choicesType: 0,
...@@ -72,10 +95,23 @@ export default { ...@@ -72,10 +95,23 @@ export default {
analysis: '', analysis: '',
level: 2 level: 2
}, },
// 0:试卷的题目,1:题库的题目
subjectsType: '0'
} }
}, },
created () { created () {
this.getSubject() let subjectInfo = this.$route.params.id
if (isNotEmpty(subjectInfo)) {
let subjectInfoArr = subjectInfo.split('-')
// 0:试卷的题目,1:题库的题目
this.subjectsType = subjectInfoArr[3]
if (subjectInfoArr[3] === '0') {
this.examinationId = subjectInfoArr[0]
} else {
this.categoryId = subjectInfoArr[0]
}
this.getSubject(subjectInfoArr[1], subjectInfoArr[2])
}
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
...@@ -84,12 +120,10 @@ export default { ...@@ -84,12 +120,10 @@ export default {
]) ])
}, },
methods: { methods: {
getSubject() { getSubject (id, type) {
let subjectId = this.$route.params.id if (isNotEmpty(id)) {
this.examinationId = this.$route.params.examinationId
if (isNotEmpty(subjectId)) {
// 加载选项信息 // 加载选项信息
getSubject(subjectId, { type: this.$route.params.type }).then(response => { getSubject(id, { type: type }).then(response => {
const subjectInfo = response.data.data const subjectInfo = response.data.data
this.tempSubject = subjectInfo this.tempSubject = subjectInfo
this.dialogStatus = dialogStatusConstant.update this.dialogStatus = dialogStatusConstant.update
...@@ -133,6 +167,7 @@ export default { ...@@ -133,6 +167,7 @@ export default {
if (ref.validate()) { if (ref.validate()) {
const subjectInfo = ref.getSubjectInfo() const subjectInfo = ref.getSubjectInfo()
subjectInfo.examinationId = this.examinationId subjectInfo.examinationId = this.examinationId
subjectInfo.categoryId = this.categoryId
putSubject(subjectInfo).then(() => { putSubject(subjectInfo).then(() => {
this.dialogSubjectFormVisible = false this.dialogSubjectFormVisible = false
notifySuccess(this, '更新成功') notifySuccess(this, '更新成功')
...@@ -146,13 +181,13 @@ export default { ...@@ -146,13 +181,13 @@ export default {
const subjectInfo = ref.getSubjectInfo() const subjectInfo = ref.getSubjectInfo()
// 绑定考试ID // 绑定考试ID
subjectInfo.examinationId = this.examinationId subjectInfo.examinationId = this.examinationId
subjectInfo.categoryId = this.categoryId
// 创建 // 创建
if (isCreate(this.dialogStatus)) { if (isCreate(this.dialogStatus)) {
addSubject(subjectInfo).then(() => { addSubject(subjectInfo).then(() => {
this.resetTempSubject(subjectInfo.score) this.resetTempSubject(subjectInfo.score)
this.dialogStatus = dialogStatusConstant.create this.dialogStatus = dialogStatusConstant.create
ref.clearValidate() ref.clearValidate()
this.getSubject()
notifySuccess(this, '创建成功') notifySuccess(this, '创建成功')
}) })
} else { } else {
...@@ -186,6 +221,9 @@ export default { ...@@ -186,6 +221,9 @@ export default {
case '1': case '1':
ref = this.$refs['shortAnswer'] ref = this.$refs['shortAnswer']
break break
case '2':
ref = this.$refs['judgement']
break
case '3': case '3':
ref = this.$refs['multipleChoices'] ref = this.$refs['multipleChoices']
break break
...@@ -199,25 +237,87 @@ export default { ...@@ -199,25 +237,87 @@ export default {
let subjectInfo = ref.getSubjectInfo() let subjectInfo = ref.getSubjectInfo()
// 绑定考试ID // 绑定考试ID
subjectInfo.examinationId = this.examinationId subjectInfo.examinationId = this.examinationId
addSubject(subjectInfo).then(() => { subjectInfo.categoryId = this.categoryId
addSubject(subjectInfo).then((response) => {
this.dialogSubjectFormVisible = false this.dialogSubjectFormVisible = false
this.getSubject() // 获取题目
const { id, type } = response.data.data
this.updateRouteSubjectId(id, type)
notifySuccess(this, '创建成功') notifySuccess(this, '创建成功')
}) })
} }
}, },
// 切换题目类型 // 切换题目类型
changeSubjectType (value) { changeSubjectType (value) {
console.log(value)
}, },
resetActiveName () { resetActiveName () {
// 重置选项卡至单选题 // 重置选项卡至单选题
this.activeName = '0' this.activeName = '0'
}, },
resetTempSubject (score) { resetTempSubject (score) {
const ref = this.getSubjectRef() this.tempSubject = {
if (isNotEmpty(ref)) { id: '',
ref.resetTempSubject(score) examinationId: undefined,
categoryId: undefined,
subjectName: '',
type: 0,
choicesType: 0,
options: [
{ subjectChoicesId: '', optionName: 'A', optionContent: '' },
{ subjectChoicesId: '', optionName: 'B', optionContent: '' },
{ subjectChoicesId: '', optionName: 'C', optionContent: '' },
{ subjectChoicesId: '', optionName: 'D', optionContent: '' }
],
answer: {
subjectId: '',
answer: '',
answerType: '',
score: ''
},
score: score,
analysis: '',
level: 2
}
this.$refs['choices'].resetTempSubject(score)
this.$refs['shortAnswer'].resetTempSubject(score)
this.$refs['multipleChoices'].resetTempSubject(score)
this.$refs['judgement'].resetTempSubject(score)
},
updateRouteSubjectId (subjectId, type) {
let subjectInfoArr = this.$route.params.id.split('-')
// 当subjectId为undefined时才刷新页面
if (subjectInfoArr[1] !== subjectId) {
this.$router.push({
path: `/exam/subjects/detail/${subjectInfoArr[0]}-${subjectId}-${type}-${subjectInfoArr[3]}`
})
}
},
// 选择题目回调
handleSelectSubject (selected) {
if (isNotEmpty(selected)) {
this.resetSubject(selected)
this.tempSubject = selected
this.categoryId = selected.categoryId
// 切换到对应的题型选项卡
this.updateCurrentTag(selected.type)
setTimeout(() => {
const ref = this.getSubjectRef()
if (isNotEmpty(ref)) {
this.$nextTick(() => {
ref.clearValidate()
ref.setSubjectInfo(selected)
})
}
}, 200)
}
},
resetSubject (subjected) {
subjected.id = undefined
subjected.examinationId = undefined
if (isNotEmpty(subjected.options)) {
subjected.options.forEach(option => {
option.id = ''
})
} }
} }
} }
...@@ -225,7 +325,7 @@ export default { ...@@ -225,7 +325,7 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.collapse-top { .dialog-footer {
margin-top: 20px; margin-top: 20px;
} }
</style> </style>
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div class="right-menu"> <div class="right-menu">
<template v-if="device!=='mobile'"> <template v-if="device!=='mobile'">
<a class="animated fadeIn hi">{{ $t('navbar.hi') }}{{ userInfo.name }}</a> <a class="animated fadeIn hi">{{ tip }},{{ userInfo.name }}</a>
<el-tooltip :content="$t('navbar.lock')" effect="dark" placement="bottom"> <el-tooltip :content="$t('navbar.lock')" effect="dark" placement="bottom">
<lock class="lock right-menu-item"/> <lock class="lock right-menu-item"/>
...@@ -72,11 +72,13 @@ export default { ...@@ -72,11 +72,13 @@ export default {
}, },
data () { data () {
return { return {
avatarUrl: '' avatarUrl: '',
tip: ''
} }
}, },
created () { created () {
this.userInfo.sex = parseInt(this.userInfo.sex) this.userInfo.sex = parseInt(this.userInfo.sex)
this.getTip()
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
...@@ -97,6 +99,17 @@ export default { ...@@ -97,6 +99,17 @@ export default {
this.$store.dispatch('LogOut').then(() => { this.$store.dispatch('LogOut').then(() => {
location.reload()// In order to re-instantiate the vue-router object to avoid bugs location.reload()// In order to re-instantiate the vue-router object to avoid bugs
}) })
},
getTip () {
let self = this
let date = new Date()
if (date.getHours() >= 0 && date.getHours() < 12) {
self.tip = '上午好'
} else if (date.getHours() >= 12 && date.getHours() < 18) {
self.tip = '下午好'
} else {
self.tip = '晚上好'
}
} }
} }
} }
...@@ -152,7 +165,7 @@ export default { ...@@ -152,7 +165,7 @@ export default {
.user-avatar { .user-avatar {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 10px; border-radius: 50% !important;
} }
.el-icon-caret-bottom { .el-icon-caret-bottom {
position: absolute; position: absolute;
......
<template> <template>
<div class="menu-wrapper"> <div class="menu-wrapper">
<div style="background-color: rgb(48, 65, 86);"> <div style="background-color: #282828;">
<div class="ams-block-component ams-block" style="color: rgb(255, 255, 255); font-size: 30px; text-align: center; margin-bottom: 8px; font-family: Roboto; padding-top: 10px;"> <div class="logo">
硕果云<div class="ams-operations el-form--inline"></div> <span>sg-</span>admin<div class="el-form--inline"></div>
</div> </div>
</div> </div>
<template v-for="(item, index) in menu"> <template v-for="(item, index) in menu">
...@@ -58,3 +58,16 @@ export default { ...@@ -58,3 +58,16 @@ export default {
} }
} }
</script> </script>
<style lang="scss" scoped>
.logo {
color: #fff;
font-size: 24px;
text-align: center;
margin-bottom: 8px;
font-family: Roboto,sans-serif;
padding-top: 10px;
span {
color: #00abff;
}
}
</style>
...@@ -5,9 +5,9 @@ ...@@ -5,9 +5,9 @@
:default-active="$route.path" :default-active="$route.path"
:collapse="isCollapse" :collapse="isCollapse"
mode="vertical" mode="vertical"
background-color="#304156" background-color="#282828"
text-color="#bfcbd9" text-color="#FFF"
active-text-color="#409EFF" active-text-color="#00abff"
> >
<sidebar-item :menu="menu" :is-collapse="isCollapse"/> <sidebar-item :menu="menu" :is-collapse="isCollapse"/>
</el-menu> </el-menu>
......
...@@ -163,10 +163,10 @@ export default { ...@@ -163,10 +163,10 @@ export default {
margin-left: 5px; margin-left: 5px;
margin-top: 4px; margin-top: 4px;
&:first-of-type { &:first-of-type {
margin-left: 15px; margin-left: 12px;
} }
&:last-of-type { &:last-of-type {
margin-right: 15px; margin-right: 12px;
} }
&.active { &.active {
background-color: #42b983; background-color: #42b983;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<div class="filter-container"> <div class="filter-container">
<el-input :placeholder="$t('table.title')" v-model="listQuery.title" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input :placeholder="$t('table.title')" v-model="listQuery.title" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button v-if="log_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="log_btn_del" class="filter-item" type="danger" icon="el-icon-delete" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<el-table <el-table
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<el-table-column type="selection" width="55"/> <el-table-column type="selection" width="55"/>
<el-table-column :label="$t('table.log.type')" width="120px" align="center"> <el-table-column :label="$t('table.log.type')" width="120px" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.type | statusTypeFilter">{{ scope.row.type | statusFilter }}</el-tag> <el-tag :type="scope.row.type | statusTypeFilter" effect="dark" size="small">{{ scope.row.type | statusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.log.title')" prop="title"> <el-table-column :label="$t('table.log.title')" prop="title">
...@@ -51,14 +51,14 @@ ...@@ -51,14 +51,14 @@
<span>{{ scope.row.creator }}</span> <span>{{ scope.row.creator }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.log.createDate')" sortable prop="createDate"> <el-table-column :label="$t('table.log.createDate')" prop="createDate" min-width="100">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.createDate | timeFilter }}</span> <span>{{ scope.row.createDate | timeFilter }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col"> <el-table-column :label="$t('table.actions')" class-name="status-col">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="log_btn_del" type="text" @click="handleDelete(scope.row)">{{ $t('table.delete') }} <el-button v-if="log_btn_del" type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
<div class="filter-container"> <div class="filter-container">
<el-input :placeholder="$t('table.client.clientId')" v-model="listQuery.clientId" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input :placeholder="$t('table.client.clientId')" v-model="listQuery.clientId" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button v-if="client_btn_add" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button v-if="client_btn_add" type="primary" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button v-if="client_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="client_btn_del" type="danger" class="filter-item" icon="el-icon-delete" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<el-table <el-table
...@@ -39,8 +39,8 @@ ...@@ -39,8 +39,8 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300px"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300px">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="client_btn_edit" type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="client_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="client_btn_del" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete">{{ $t('table.delete') }}</el-button> <el-button v-if="client_btn_del" type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -324,8 +324,6 @@ export default { ...@@ -324,8 +324,6 @@ export default {
this.getList() this.getList()
notifySuccess(this, '删除成功') notifySuccess(this, '删除成功')
}) })
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}).catch(() => {}) }).catch(() => {})
}, },
// 批量删除 // 批量删除
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<div class="tab-container"> <div class="tab-container">
<div class="filter-container"> <div class="filter-container">
<el-button v-if="dept_btn_add" icon="el-icon-check" type="primary" @click="handlerAdd">添加</el-button> <el-button v-if="dept_btn_add" icon="el-icon-check" type="primary" @click="handlerAdd">添加</el-button>
<el-button v-if="dept_btn_del" icon="el-icon-delete" plain @click="handleDelete">删除</el-button> <el-button v-if="dept_btn_del" icon="el-icon-delete" type="danger" @click="handleDelete">删除</el-button>
<el-row> <el-row>
<el-col :span="5" style ="margin-top:10px;"> <el-col :span="5" style ="margin-top:10px;">
......
...@@ -3,9 +3,9 @@ ...@@ -3,9 +3,9 @@
<div class="filter-container"> <div class="filter-container">
<el-button v-if="menu_btn_add" icon="el-icon-check" type="primary" @click="handlerAddSuper">添加顶级菜单</el-button> <el-button v-if="menu_btn_add" icon="el-icon-check" type="primary" @click="handlerAddSuper">添加顶级菜单</el-button>
<el-button v-if="menu_btn_add" icon="el-icon-check" type="primary" @click="handlerAdd">添加子菜单</el-button> <el-button v-if="menu_btn_add" icon="el-icon-check" type="primary" @click="handlerAdd">添加子菜单</el-button>
<el-button v-if="menu_btn_del" icon="el-icon-delete" plain @click="handleDelete">{{ $t('table.del') }}</el-button> <el-button v-if="menu_btn_del" icon="el-icon-delete" type="danger" @click="handleDelete">{{ $t('table.del') }}</el-button>
<el-button v-if="menu_btn_import" icon="el-icon-upload2" plain @click="handleImport">{{ $t('table.import') }}</el-button> <el-button v-if="menu_btn_import" icon="el-icon-upload2" type="success" @click="handleImport">{{ $t('table.import') }}</el-button>
<el-button v-if="menu_btn_export" icon="el-icon-download" plain @click="handleExport">{{ $t('table.export') }}</el-button> <el-button v-if="menu_btn_export" icon="el-icon-download" type="success" @click="handleExport">{{ $t('table.export') }}</el-button>
<el-row> <el-row>
<el-col :span="4" style ="margin-top:10px;"> <el-col :span="4" style ="margin-top:10px;">
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
<div class="filter-container"> <div class="filter-container">
<el-input :placeholder="$t('table.roleName')" v-model="listQuery.roleName" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input :placeholder="$t('table.roleName')" v-model="listQuery.roleName" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button v-if="role_btn_add" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button v-if="role_btn_add" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" type="primary" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button v-if="role_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="role_btn_del" class="filter-item" icon="el-icon-delete" type="danger" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<el-table <el-table
...@@ -40,14 +40,14 @@ ...@@ -40,14 +40,14 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.status')" width="80"> <el-table-column :label="$t('table.status')" width="80">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.status | statusTypeFilter">{{ scope.row.status | statusFilter }}</el-tag> <el-tag :type="scope.row.status | statusTypeFilter" effect="dark" size="small">{{ scope.row.status | statusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300px"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300px">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="role_btn_edit" type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="role_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="role_btn_del" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete">{{ $t('table.delete') }}</el-button> <el-button v-if="role_btn_auth" type="success" size="mini" @click="handlePermission(scope.row)">{{ $t('table.permission') }}</el-button>
<el-button v-if="role_btn_auth" type="text" @click="handlePermission(scope.row)" icon="el-icon-circle-plus-outline">{{ $t('table.permission') }}</el-button> <el-button v-if="role_btn_del" type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -301,8 +301,6 @@ export default { ...@@ -301,8 +301,6 @@ export default {
this.getList() this.getList()
notifySuccess(this, '删除成功') notifySuccess(this, '删除成功')
}) })
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}).catch(() => {}) }).catch(() => {})
}, },
// 批量删除 // 批量删除
......
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
<div class="filter-container"> <div class="filter-container">
<el-input placeholder="输入姓名查询" v-model="listQuery.name" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input placeholder="输入姓名查询" v-model="listQuery.name" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.query') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.query') }}</el-button>
<el-button v-if="user_btn_add" class="filter-item" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button v-if="user_btn_add" class="filter-item" icon="el-icon-check" type="primary" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button v-if="user_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="user_btn_del" class="filter-item" icon="el-icon-delete" type="danger" @click="handleDeletes">{{ $t('table.del') }}</el-button>
<el-button v-if="user_btn_import" class="filter-item" icon="el-icon-upload2" plain @click="handleImport">{{ $t('table.import') }}</el-button> <el-button v-if="user_btn_import" class="filter-item" icon="el-icon-upload2" type="success" @click="handleImport">{{ $t('table.import') }}</el-button>
<el-button v-if="user_btn_export" class="filter-item" icon="el-icon-download" plain @click="handleExport">{{ $t('table.export') }}</el-button> <el-button v-if="user_btn_export" class="filter-item" icon="el-icon-download" type="success" @click="handleExport">{{ $t('table.export') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<el-table <el-table
...@@ -46,15 +46,15 @@ ...@@ -46,15 +46,15 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.status')"> <el-table-column :label="$t('table.status')">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.status | statusTypeFilter">{{ scope.row.status | statusFilter }}</el-tag> <el-tag :type="scope.row.status | statusTypeFilter" effect="dark" size="small">{{ scope.row.status | statusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300px"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300px">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="user_btn_edit" type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="user_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="user_btn_edit && scope.row.status === 0" type="text" @click="handleEnableOrDisable(scope.row, 1)" icon="el-icon-remove-outline">{{ $t('table.disable') }}</el-button> <el-button v-if="user_btn_edit" type="warning" size="mini" @click="handleResetPassword(scope.row)">{{ $t('table.resetPassword') }}</el-button>
<el-button v-else type="text" @click="handleEnableOrDisable(scope.row, 0)" icon="el-icon-check">{{ $t('table.enable') }}</el-button> <el-button v-if="user_btn_edit && scope.row.status === 0" type="danger" size="mini" @click="handleEnableOrDisable(scope.row, 1)">{{ $t('table.disable') }}</el-button>
<el-button v-if="user_btn_edit" type="text" @click="handleResetPassword(scope.row)" icon="el-icon-refresh">{{ $t('table.resetPassword') }}</el-button> <el-button v-else type="success" size="mini" @click="handleEnableOrDisable(scope.row, 0)">{{ $t('table.enable') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -264,14 +264,6 @@ export default { ...@@ -264,14 +264,6 @@ export default {
} }
}, },
data () { data () {
// 校验手机号码
const checkPhone = (rule, value, callback) => {
if (!(/^1[34578]\d{9}$/.test(value))) {
callback(new Error('请输入正确的手机号码!'))
} else {
callback()
}
}
return { return {
tableKey: 0, tableKey: 0,
list: null, list: null,
...@@ -311,9 +303,7 @@ export default { ...@@ -311,9 +303,7 @@ export default {
create: '新建' create: '新建'
}, },
rules: { rules: {
name: [{ required: true, message: '请输入账号', trigger: 'change' }], identifier: [{ required: true, message: '请输入账号', trigger: 'change' }]
username: [{ required: true, message: '请输入姓名', trigger: 'change' }],
phone: [{ required: true, message: '请输入手机号码', trigger: 'change' }, { validator: checkPhone, trigger: 'change' }]
}, },
downloadLoading: false, downloadLoading: false,
treeDeptData: [], treeDeptData: [],
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
<div class="filter-container"> <div class="filter-container">
<el-input :placeholder="$t('table.tenant.tenantCode')" v-model="listQuery.tenantCode" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/> <el-input :placeholder="$t('table.tenant.tenantCode')" v-model="listQuery.tenantCode" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter"/>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button> <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">{{ $t('table.search') }}</el-button>
<el-button v-if="tenant_btn_add" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" plain @click="handleCreate">{{ $t('table.add') }}</el-button> <el-button v-if="tenant_btn_add" type="primary" class="filter-item" style="margin-left: 10px;" icon="el-icon-check" @click="handleCreate">{{ $t('table.add') }}</el-button>
<el-button v-if="tenant_btn_del" class="filter-item" icon="el-icon-delete" plain @click="handleDeletes">{{ $t('table.del') }}</el-button> <el-button v-if="tenant_btn_del" type="danger" class="filter-item" icon="el-icon-delete" @click="handleDeletes">{{ $t('table.del') }}</el-button>
</div> </div>
<spinner-loading v-if="listLoading"/> <spinner-loading v-if="listLoading"/>
<el-table <el-table
...@@ -34,13 +34,13 @@ ...@@ -34,13 +34,13 @@
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.tenant.status')"> <el-table-column :label="$t('table.tenant.status')">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.status | statusTypeFilter">{{ scope.row.status | statusFilter }}</el-tag> <el-tag :type="scope.row.status | statusTypeFilter" effect="dark" size="small">{{ scope.row.status | statusFilter }}</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('table.actions')" class-name="status-col" width="300"> <el-table-column :label="$t('table.actions')" class-name="status-col" width="300">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="tenant_btn_edit" type="text" @click="handleUpdate(scope.row)" icon="el-icon-edit">{{ $t('table.edit') }}</el-button> <el-button v-if="tenant_btn_edit" type="primary" size="mini" @click="handleUpdate(scope.row)">{{ $t('table.edit') }}</el-button>
<el-button v-if="tenant_btn_del" type="text" @click="handleDelete(scope.row)" icon="el-icon-delete">{{ $t('table.delete') }}</el-button> <el-button v-if="tenant_btn_del" type="danger" size="mini" @click="handleDelete(scope.row)">{{ $t('table.delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
...@@ -276,8 +276,6 @@ export default { ...@@ -276,8 +276,6 @@ export default {
this.getList() this.getList()
notifySuccess(this, '删除成功') notifySuccess(this, '删除成功')
}) })
const index = this.list.indexOf(row)
this.list.splice(index, 1)
}).catch(() => {}) }).catch(() => {})
}, },
// 批量删除 // 批量删除
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -17,10 +17,11 @@ export function fetchSubjectList (query) { ...@@ -17,10 +17,11 @@ export function fetchSubjectList (query) {
}) })
} }
export function getObj (id) { export function getObj (id, query) {
return request({ return request({
url: baseSubjectUrl + id, url: baseSubjectUrl + id,
method: 'get' method: 'get',
params: query
}) })
} }
......
<template>
<div>
<div class="subject-exam-title">{{exam.examinationName}}(共{{subjectCount}}题,合计{{exam.totalScore}}分)</div>
<div class="subject-content">
<div class="subject-title">
{{ index }}
<span class="subject-title-content" v-html="subjectInfo.subjectName"/>
<span class="subject-title-content">&nbsp;({{subjectInfo.score}})分</span>
</div>
<ul class="subject-options" v-for="option in options" :key="option.id">
<li class="subject-option">
<input class="toggle" type="checkbox" :checked="userAnswer === option.optionName" :id="'option' + option.id" @change="toggleOption(option)">
<label :for="'option' + option.id">
<span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span>
<span v-html="option.optionContent" class="subject-option-prefix" />
</label>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'Choices',
data () {
return {
exam: {
examinationName: '',
totalScore: ''
},
subjectCount: 0,
subjectInfo: {
subjectName: '',
score: 0
},
options: [],
userAnswer: '',
index: ''
}
},
methods: {
getAnswer () {
return this.userAnswer
},
setAnswer (answer) {
this.userAnswer = answer
},
setSubjectInfo (exam, subject, subjectCount, index) {
this.exam = exam
this.subjectCount = subjectCount
this.subjectInfo = subject
if (subject.hasOwnProperty('options')) {
this.options = subject.options
}
if (subject.hasOwnProperty('answer')) {
this.setAnswer(subject.answer.answer)
}
this.index = index + '.'
},
getSubjectInfo () {
this.subjectInfo.options = this.options
return this.subjectInfo
},
// 选中选项
toggleOption (option) {
this.userAnswer = option.optionName
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../styles/subject.scss";
</style>
<template>
<div>
<div class="subject-exam-title">{{exam.examinationName}}(共{{subjectCount}}题,合计{{exam.totalScore}}分)</div>
<div class="subject-content">
<div class="subject-title">
{{ index }}
<span class="subject-title-content" v-html="subjectInfo.subjectName"/>
<span class="subject-title-content">&nbsp;({{subjectInfo.score}})分</span>
</div>
<ul class="subject-options" v-for="option in options" :key="option.id">
<li class="subject-option">
<input class="toggle" type="checkbox" :checked="userAnswer === option.optionName" :id="'option' + option.id" @change="toggleOption(option)">
<label :for="'option' + option.id">
<span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span>
</label>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'Judgement',
data () {
return {
exam: {
examinationName: '',
totalScore: ''
},
subjectCount: 0,
subjectInfo: {
subjectName: '',
score: 0
},
options: [
{ id: 1, optionName: '正确' },
{ id: 2, optionName: '错误' }
],
userAnswer: '',
index: ''
}
},
methods: {
getAnswer () {
return this.userAnswer
},
setAnswer (answer) {
this.userAnswer = answer
},
setSubjectInfo (exam, subject, subjectCount, index) {
this.exam = exam
this.subjectCount = subjectCount
this.subjectInfo = subject
if (subject.hasOwnProperty('answer')) {
this.setAnswer(subject.answer.answer)
}
this.index = index + '.'
},
getSubjectInfo () {
this.subjectInfo.options = this.options
return this.subjectInfo
},
// 选中选项
toggleOption (option) {
this.userAnswer = option.optionName
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../styles/subject.scss";
</style>
<template>
<div>
<div class="subject-exam-title">{{exam.examinationName}}(共{{subjectCount}}题,合计{{exam.totalScore}}分)</div>
<div class="subject-content">
<div class="subject-title">
{{ index }}
<span class="subject-title-content" v-html="subjectInfo.subjectName"/>
<span class="subject-title-content">&nbsp;({{subjectInfo.score}})分</span>
</div>
<ul class="subject-options" v-for="option in options" :key="option.id">
<li class="subject-option">
<input class="toggle" type="checkbox" :checked="isChecked(option.optionName)" :id="'option' + option.id" @change="toggleOption($event, option)">
<label :for="'option' + option.id">
<span class="subject-option-prefix">{{ option.optionName }}&nbsp;</span>
<span v-html="option.optionContent" class="subject-option-prefix" />
</label>
</li>
</ul>
</div>
</div>
</template>
<script>
import { isNotEmpty } from '@/utils/util'
export default {
name: 'MultipleChoices',
data () {
return {
exam: {
examinationName: '',
totalScore: ''
},
subjectCount: 0,
subjectInfo: {
subjectName: '',
score: 0
},
options: [],
userAnswer: [],
index: ''
}
},
watch: {
},
methods: {
getAnswer () {
return this.userAnswer.join(',')
},
setAnswer (answer) {
if (isNotEmpty(answer)) {
this.userAnswer = answer.split(',')
}
},
setSubjectInfo (exam, subject, subjectCount, index) {
this.exam = exam
this.subjectCount = subjectCount
this.subjectInfo = subject
if (subject.hasOwnProperty('options')) {
this.options = subject.options
}
if (subject.hasOwnProperty('answer')) {
this.setAnswer(subject.answer.answer)
}
this.index = index + '.'
},
getSubjectInfo () {
this.subjectInfo.options = this.options
return this.subjectInfo
},
// 选中选项
toggleOption ($event, option) {
if ($event.target.checked) {
if (!this.userAnswer.includes(option.optionName)) {
this.userAnswer.push(option.optionName)
}
} else {
this.userAnswer.splice(this.userAnswer.findIndex(item => item === option.optionName), 1)
}
},
isChecked (optionName) {
return this.userAnswer.includes(optionName)
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../styles/subject.scss";
</style>
<template>
<div>
<div class="subject-exam-title">{{exam.examinationName}}(共{{subjectCount}}题,合计{{exam.totalScore}}分)</div>
<div class="subject-content">
<div class="subject-title">
{{ index }}
<span class="subject-title-content" v-html="subjectInfo.subjectName"/>
<span class="subject-title-content">&nbsp;({{subjectInfo.score}})分</span>
<div class="subject-tinymce">
<tinymce ref="editor" :height="300" v-model="userAnswer"/>
</div>
</div>
</div>
</div>
</template>
<script>
import Tinymce from '@/components/Tinymce'
export default {
name: 'ShortAnswer',
components: {
Tinymce
},
data () {
return {
exam: {
examinationName: '',
totalScore: ''
},
subjectCount: 0,
subjectInfo: {
subjectName: '',
score: 0
},
userAnswer: '',
index: ''
}
},
methods: {
getAnswer () {
return this.userAnswer
},
setAnswer (answer) {
this.userAnswer = answer
},
setSubjectInfo (exam, subject, subjectCount, index) {
this.exam = exam
this.subjectCount = subjectCount
this.subjectInfo = subject
if (subject.hasOwnProperty('answer')) {
this.setAnswer(subject.answer.answer)
}
this.index = index + '.'
},
getSubjectInfo () {
return this.subjectInfo
}
}
}
</script>
<style lang="scss" scoped>
@import "../../../styles/subject.scss";
.subject-tinymce {
margin: 12px;
}
</style>
export const nextSubjectType = {
last: 1,
next: 0,
current: 2
}
export const answerType = {
'true': 'right',
'false': 'incorrect'
}
...@@ -46,7 +46,7 @@ export const constantRouterMap = [ ...@@ -46,7 +46,7 @@ export const constantRouterMap = [
component: () => import('@/views/exam/exams') component: () => import('@/views/exam/exams')
}, },
{ {
path: '/start', path: '/start/:id',
name: 'start', name: 'start',
component: () => import('@/views/exam/startExam') component: () => import('@/views/exam/startExam')
}, },
......
.subject-exam-title{
font-size: 18px;
line-height: 25px;
padding: 18px 20px;
border-bottom: 1px solid #DEDEDE;
margin-bottom: 12px;
}
.subject {
padding-left: 30px;
padding-right: 75px;
}
.subject-content{
margin-top: 18px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
background: #fff;
z-index: 1;
position: relative;
}
/* 题目 */
.subject-title {
font-size: 18px;
line-height: 22px;
.subject-title-number {
display: inline-block;
line-height: 22px;
}
.subject-title-content {
display: inline-block;
}
}
.subject-options {
margin: 0;
padding: 0;
list-style: none;
> li {
position: relative;
font-size: 24px;
.toggle {
opacity: 0;
text-align: center;
width: 35px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none;
/* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.toggle+label {
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
background-size: 30px;
}
.toggle:checked+label {
background-size: 30px;
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
}
label {
word-break: break-all;
padding: 10px 10px 10px 45px;
display: block;
line-height: 1.0;
transition: color 0.4s;
}
/* 选项名称 */
.subject-option-prefix {
font-size: 16px;
display: inline-block
}
}
}
.subject-answer {
padding: 16px;
}
...@@ -149,7 +149,7 @@ export const isNotEmpty = (obj) => { ...@@ -149,7 +149,7 @@ export const isNotEmpty = (obj) => {
* @param duration * @param duration
*/ */
export const notify = (obj, title, msg, type, duration) => { export const notify = (obj, title, msg, type, duration) => {
obj.$notify({ title: title, message: msg, type: type, duration: duration, offset: 70}) obj.$notify({ title: title, message: msg, type: type, duration: duration, offset: 70 })
} }
/** /**
...@@ -180,6 +180,43 @@ export const notifyFail = (obj, msg) => { ...@@ -180,6 +180,43 @@ export const notifyFail = (obj, msg) => {
} }
/** /**
* 消息提示
* @param obj
* @param message
* @param type
*/
export const message = (obj, message, type) => {
obj.$message({ message: message, type: type, offset: 70 })
}
/**
* 成功消息提示
* @param obj
* @param message
*/
export const messageSuccess = (obj, message) => {
obj.$message({ message: message, type: 'success', offset: 70 })
}
/**
* 警告消息提示
* @param obj
* @param message
*/
export const messageWarn = (obj, message) => {
obj.$message({ message: message, type: 'warning', offset: 70 })
}
/**
* 失败消息提示
* @param obj
* @param message
*/
export const messageFail = (obj, message) => {
obj.$message({ message: message, type: 'error', offset: 70 })
}
/**
* 手机号验证 * 手机号验证
* @param str * @param str
* @returns {boolean} * @returns {boolean}
......
...@@ -18,7 +18,7 @@ export default { ...@@ -18,7 +18,7 @@ export default {
}, },
methods: { methods: {
// 提交考试 // 提交考试
handleSubmitExam() { handleSubmitExam () {
debugger debugger
this.$refs.mainRef.handleSubmitExam() this.$refs.mainRef.handleSubmitExam()
} }
......
...@@ -3,28 +3,29 @@ ...@@ -3,28 +3,29 @@
<div class="container"> <div class="container">
<div class="site-info"> <div class="site-info">
<el-row> <el-row>
<el-col :span="4" :offset="2" class="footer-col"> <el-col :span="3" :offset="2" class="footer-col">
<h4>链接</h4> <h4>链接</h4>
<a target="_blank" href="https://gitee.com/wells2333/spring-microservice-exam">码云</a> <a target="_blank" href="https://gitee.com/wells2333/spring-microservice-exam">码云</a>
<a target="_blank" href="https://github.com/">GITHUB</a> <a target="_blank" href="https://github.com/">GITHUB</a>
<a target="_blank" href="http://118.25.138.130:81">管理后台</a> <a target="_blank" href="http://118.25.138.130:81">管理后台</a>
<a target="_blank" href="https://gitee.com/wells2333/spring-microservice-exam/blob/master/CHANGELOG.md">更新日志</a> <a target="_blank" href="https://gitee.com/wells2333/spring-microservice-exam/blob/master/CHANGELOG.md">更新日志</a>
</el-col> </el-col>
<el-col :span="4" class="footer-col"> <el-col :span="3" class="footer-col">
<h4>工具</h4> <h4>工具</h4>
<a target="_blank" href="http://element-cn.eleme.io">Element Ui</a> <a target="_blank" href="http://element-cn.eleme.io">Element Ui</a>
<a target="_blank" href="https://cn.vuejs.org/">Vue</a> <a target="_blank" href="https://cn.vuejs.org/">Vue</a>
</el-col> </el-col>
<el-col :span="4" class="footer-col"> <el-col :span="3" class="footer-col">
<h4>社区</h4> <h4>社区</h4>
<a target="_blank" href="https://www.kancloud.cn/tangyi/spring-microservice-exam/1322864">看云</a> <a target="_blank" href="https://www.kancloud.cn/tangyi/spring-microservice-exam/1322864">看云</a>
<a target="_blank" href="https://gitee.com/wells2333/spring-microservice-exam/issues">反馈建议</a> <a target="_blank" href="https://gitee.com/wells2333/spring-microservice-exam/issues">反馈建议</a>
</el-col> </el-col>
<el-col :span="4" class="footer-col"> <el-col :span="7" class="footer-col">
<div class="we-chat"> <div class="we-chat">
</div>
<div class="we-chat-new">
加入技术交流群,请扫二维码 加入技术交流群,请扫二维码
<br>
(Spring Cloud技术交流群)
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
...@@ -173,11 +174,25 @@ export default { ...@@ -173,11 +174,25 @@ export default {
.we-chat { .we-chat {
position: absolute; position: absolute;
right: 0; right: 0;
top: 80px; top: 60px;
width: 216px;
z-index: 2;
padding-top: 260px;
background-image: url("../../../static/images/home/qq.png");
background-repeat: no-repeat;
background-position: top;
text-align: center;
color: #bdb8ce;
line-height: 22px;
}
.we-chat-new {
position: absolute;
top: 60px;
width: 216px; width: 216px;
z-index: 2; z-index: 2;
padding-top: 232px; padding-top: 260px;
background-image: url("../../../static/images/home/WechatIMG4.png"); background-image: url("../../../static/images/home/qq_new.png");
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: top; background-position: top;
text-align: center; text-align: center;
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
<template slot="title">功能</template> <template slot="title">功能</template>
<el-menu-item index="exams" @click="open('/exams')">在线考试</el-menu-item> <el-menu-item index="exams" @click="open('/exams')">在线考试</el-menu-item>
<el-menu-item index="practices" @click="open('/practices')">在线学习</el-menu-item> <el-menu-item index="practices" @click="open('/practices')">在线学习</el-menu-item>
<el-menu-item index="exam-record" @click="open('/exam-record')">考试记录</el-menu-item>
<el-menu-item index="incorrect" @click="open('/incorrect')">错题本</el-menu-item> <el-menu-item index="incorrect" @click="open('/incorrect')">错题本</el-menu-item>
</el-submenu> </el-submenu>
<el-submenu index="/u"> <el-submenu index="/u">
...@@ -74,17 +75,16 @@ ...@@ -74,17 +75,16 @@
<script> <script>
import { mapState } from 'vuex' import { mapState } from 'vuex'
import { fetchList } from '@/api/exam/exam'
import { isNotEmpty } from '@/utils/util' import { isNotEmpty } from '@/utils/util'
export default { export default {
mounted () { mounted () {
// handleScroll为页面滚动的监听回调 // handleScroll为页面滚动的监听回调
window.addEventListener("scroll", this.handleScroll); window.addEventListener('scroll', this.handleScroll)
}, },
destroyed() { destroyed () {
//同时在destroyed回调中移除监听: // 同时在destroyed回调中移除监听:
window.removeEventListener("scroll", this.handleScroll); window.removeEventListener('scroll', this.handleScroll)
}, },
computed: { computed: {
// 获取用户信息 // 获取用户信息
...@@ -113,7 +113,7 @@ export default { ...@@ -113,7 +113,7 @@ export default {
// 导航栏切换 // 导航栏切换
open (path) { open (path) {
if (path !== this.$route.fullPath) { if (path !== this.$route.fullPath) {
if ('/start' === this.$route.fullPath) { if (this.$route.fullPath === '/start') {
this.$confirm('是否要结束当前考试?', '提示', { this.$confirm('是否要结束当前考试?', '提示', {
confirmButtonText: '确定', confirmButtonText: '确定',
cancelButtonText: '取消', cancelButtonText: '取消',
...@@ -163,7 +163,7 @@ export default { ...@@ -163,7 +163,7 @@ export default {
this.$store.dispatch('LogOut').then(() => { this.$store.dispatch('LogOut').then(() => {
this.login = false this.login = false
this.$router.push('/home') this.$router.push('/home')
}).catch(error => { }).catch(() => {
this.login = false this.login = false
this.$router.push('/home') this.$router.push('/home')
}) })
...@@ -174,7 +174,7 @@ export default { ...@@ -174,7 +174,7 @@ export default {
this.login = true this.login = true
} }
}, },
search() { search () {
if (isNotEmpty(this.query)) { if (isNotEmpty(this.query)) {
this.$router.push({name: 'exams', query: {query: this.query}}) this.$router.push({name: 'exams', query: {query: this.query}})
} }
...@@ -208,7 +208,7 @@ export default { ...@@ -208,7 +208,7 @@ export default {
vertical-align: top; vertical-align: top;
cursor: pointer; cursor: pointer;
.home-link { .home-link {
margin-right: -30px; margin-right: -100px;
} }
.site-name { .site-name {
display: inline-block; display: inline-block;
...@@ -217,7 +217,6 @@ export default { ...@@ -217,7 +217,6 @@ export default {
height: 32px; height: 32px;
background-size: 100%; background-size: 100%;
margin: 17px 0 0 33px; margin: 17px 0 0 33px;
background-image: url("../../../static/images/home/scloud-logo.png");
} }
} }
.nav-bar { .nav-bar {
......
...@@ -20,7 +20,7 @@ export default { ...@@ -20,7 +20,7 @@ export default {
}, },
methods: { methods: {
// TODO 提交考试 // TODO 提交考试
handleSubmitExam() { handleSubmitExam () {
console.log('handleSubmitExam') console.log('handleSubmitExam')
} }
} }
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
style="width: 100%;"> style="width: 100%;">
<el-table-column label="考试名称" align="center"> <el-table-column label="考试名称" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span :title="scope.row.examinationName">{{ scope.row.examinationName | examinationNameFilter }}</span> <span :title="scope.row.examinationName">{{ scope.row.examinationName }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="考试类型" min-width="90" align="center"> <el-table-column label="考试类型" min-width="90" align="center">
...@@ -109,7 +109,7 @@ export default { ...@@ -109,7 +109,7 @@ export default {
timeFilter (time) { timeFilter (time) {
return formatDate(new Date(time), 'yyyy-MM-dd hh:mm') return formatDate(new Date(time), 'yyyy-MM-dd hh:mm')
}, },
examinationNameFilter(name) { examinationNameFilter (name) {
return cropStr(name, 8) return cropStr(name, 8)
} }
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment