master
yujialong 4 years ago
commit 92daa966b2
  1. 3
      .browserslistrc
  2. 22
      .gitignore
  3. 6
      .prettierrc
  4. 21
      LICENSE
  5. 197
      README.md
  6. 196
      README_EN.md
  7. 5
      babel.config.js
  8. 13497
      package-lock.json
  9. 38
      package.json
  10. 5
      postcss.config.js
  11. 17
      public/index.html
  12. BIN
      screenshots/wms1.png
  13. BIN
      screenshots/wms2.png
  14. BIN
      screenshots/wms3.png
  15. 32
      src/App.vue
  16. 123
      src/api/index.js
  17. 28
      src/assets/css/color-dark.css
  18. 4
      src/assets/css/icon.css
  19. 384
      src/assets/css/main.css
  20. 29
      src/assets/css/theme-green/color-green.css
  21. BIN
      src/assets/css/theme-green/fonts/element-icons.ttf
  22. BIN
      src/assets/css/theme-green/fonts/element-icons.woff
  23. 1
      src/assets/css/theme-green/index.css
  24. 539
      src/assets/icon/demo.css
  25. 446
      src/assets/icon/demo_index.html
  26. 71
      src/assets/icon/iconfont.css
  27. BIN
      src/assets/icon/iconfont.eot
  28. 1
      src/assets/icon/iconfont.js
  29. 93
      src/assets/icon/iconfont.json
  30. 62
      src/assets/icon/iconfont.svg
  31. BIN
      src/assets/icon/iconfont.ttf
  32. BIN
      src/assets/icon/iconfont.woff
  33. BIN
      src/assets/icon/iconfont.woff2
  34. 1
      src/assets/img/edit.svg
  35. BIN
      src/assets/img/icon-weigouxuan.png
  36. BIN
      src/assets/img/icon-xiangyou.png
  37. BIN
      src/assets/img/icon-yigouxuan.png
  38. BIN
      src/assets/img/icon_.png
  39. BIN
      src/assets/img/icon_1.png
  40. BIN
      src/assets/img/images/back_02.png
  41. BIN
      src/assets/img/img.jpg
  42. BIN
      src/assets/img/login-bg.png
  43. BIN
      src/assets/img/login-input.png
  44. BIN
      src/assets/img/login_bg.png
  45. BIN
      src/assets/img/logo-fill.png
  46. BIN
      src/assets/img/logo.png
  47. BIN
      src/assets/img/message.png
  48. 159
      src/components/achiStatistics/index.vue
  49. 264
      src/components/doReview/index.vue
  50. 72
      src/components/messageBoard/index.vue
  51. 173
      src/components/quill/index.vue
  52. 16
      src/components/quill/options.js
  53. 254
      src/components/testPaperDetail/index.vue
  54. 30
      src/i18n/index.js
  55. 152
      src/layouts/header/index.vue
  56. 78
      src/layouts/home/index.vue
  57. 136
      src/layouts/navbar/index.vue
  58. 186
      src/layouts/tags/index.vue
  59. 26
      src/libs/auth/generateBtnPermission.js
  60. 6
      src/libs/bus.js
  61. 10
      src/libs/random_str.js
  62. 16
      src/libs/resize/index.js
  63. 34
      src/libs/route/addRoutes.js
  64. 26
      src/libs/route/generateRoutes.js
  65. 6
      src/libs/route/resetRouter.js
  66. 43
      src/libs/util.cookies.js
  67. 82
      src/libs/util.db.js
  68. 54
      src/libs/util.js
  69. 45
      src/main.js
  70. 11
      src/mixins/app.js
  71. 8
      src/mixins/setBackground/index.js
  72. 252
      src/pages/account/login/index.vue
  73. 195
      src/pages/achievement/list/examResults.vue
  74. 42
      src/pages/achievement/list/index.vue
  75. 257
      src/pages/achievement/list/practiceResults.vue
  76. 182
      src/pages/achievement/list/wrongBook.vue
  77. 264
      src/pages/assessment/add/index.vue
  78. 311
      src/pages/assessment/list/index.vue
  79. 204
      src/pages/assessment/monitor/index.vue
  80. 138
      src/pages/assessment/review/index.vue
  81. 141
      src/pages/assessment/scoreQuery/index.vue
  82. 56
      src/pages/exception/error/403/index.vue
  83. 56
      src/pages/exception/error/404/index.vue
  84. 46
      src/pages/exception/i18n/index.vue
  85. 225
      src/pages/exception/icon/index.vue
  86. 156
      src/pages/quesBank/list/globalQuesBank.vue
  87. 41
      src/pages/quesBank/list/index.vue
  88. 550
      src/pages/quesBank/list/myQuesBank.vue
  89. 361
      src/pages/quesBank/list/quesDialog.vue
  90. 752
      src/pages/setting/person/index.vue
  91. 550
      src/pages/student/list/index.vue
  92. 515
      src/pages/student/list/studentSide.vue
  93. 284
      src/pages/student/list/studentTree.vue
  94. 82
      src/pages/system/list/index.vue
  95. 296
      src/pages/system/list/role.vue
  96. 610
      src/pages/system/list/staff.vue
  97. 489
      src/pages/system/list/staffSide.vue
  98. 239
      src/pages/system/list/stafftree.vue
  99. 923
      src/pages/testPaper/add/index.vue
  100. 193
      src/pages/testPaper/list/allTestPaper.vue
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,3 @@
> 1%
last 2 versions
not ie <= 8

22
.gitignore vendored

@ -0,0 +1,22 @@
.DS_Store
node_modules
/dist
example.html
favicon.ico
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

@ -0,0 +1,6 @@
{
"tabWidth": 4,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 140
}

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2016-2019 vue-manage-system
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,197 @@
# vue-manage-system
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg" alt="element-ui">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/releases">
<img src="https://img.shields.io/github/release/lin-xin/vue-manage-system.svg" alt="GitHub release">
</a>
<a href="https://lin-xin.gitee.io/example/work/#/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
</a>
基于 Vue + Element UI 的后台管理系统解决方案。[线上地址](https://lin-xin.gitee.io/example/work/)
> React + Ant Design 的版本正在开发中,仓库地址:[react-manage-system](https://github.com/lin-xin/react-manage-system)
[English document](https://github.com/lin-xin/manage-system/blob/master/README_EN.md)
## 项目截图
### 登录
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms3.png)
### 默认皮肤
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png)
### 浅绿色皮肤
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms2.png)
## 赞赏
请作者喝杯咖啡吧!(微信号:linxin_20)
![微信扫一扫](https://lin-xin.gitee.io/images/weixin.jpg)
## 特别鸣谢
- [实验楼](https://www.shiyanlou.com?source=vue-manage-system)
## 前言
该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(Web Management System)开发。基于 vue.js,使用 vue-cli3 脚手架,引用 Element UI 组件库,方便开发快速简洁好看的组件。分离颜色样式,支持手动切换主题色,而且很方便使用自定义主题色。
## 功能
- [x] Element UI
- [x] 登录/注销
- [x] Dashboard
- [x] 表格
- [x] Tab 选项卡
- [x] 表单
- [x] 图表 :bar_chart:
- [x] 富文本编辑器
- [x] markdown 编辑器
- [x] 图片拖拽/裁剪上传
- [x] 支持切换主题色 :sparkles:
- [x] 列表拖拽排序
- [x] 权限测试
- [x] 404 / 403
- [x] 三级菜单
- [x] 自定义图标
- [x] 可拖拽弹窗
- [x] 国际化
## 安装步骤
```
git clone https://github.com/lin-xin/vue-manage-system.git // 把模板下载到本地
cd vue-manage-system // 进入模板目录
npm install // 安装项目依赖,等待安装完成之后,安装失败可用 cnpm 或 yarn
// 开启服务器,浏览器访问 http://localhost:8080
npm run serve
// 执行构建命令,生成的dist文件夹放在服务器下即可访问
npm run build
```
## 组件使用说明与演示
### vue-schart
vue.js 封装 sChart.js 的图表组件。访问地址:[vue-schart](https://github.com/linxin/vue-schart)
<p><a href="https://www.npmjs.com/package/vue-schart"><img src="https://img.shields.io/npm/dm/vue-schart.svg" alt="Downloads"></a></p>
```html
<template>
<div>
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart>
</div>
</template>
<script>
import Schart from 'vue-schart'; // 导入Schart组件
export default {
data() {
return {
options: {
type: 'bar',
title: {
text: '最近一周各品类销售图'
},
labels: ['周一', '周二', '周三', '周四', '周五'],
datasets: [
{
label: '家电',
data: [234, 278, 270, 190, 230]
},
{
label: '百货',
data: [164, 178, 190, 135, 160]
},
{
label: '食品',
data: [144, 198, 150, 235, 120]
}
]
}
};
},
components: {
Schart
}
};
</script>
<style>
.wrapper {
width: 7rem;
height: 5rem;
}
</style>
```
## 其他注意事项
### 一、如果我不想用到上面的某些组件呢,那我怎么在模板中删除掉不影响到其他功能呢?
举个栗子,我不想用 Vue-Quill-Editor 这个组件,那我需要分四步走。
第一步:删除该组件的路由,在目录 src/router/index.js 中,找到引入改组件的路由,删除下面这段代码。
```JavaScript
{
// 富文本编辑器组件
path: '/editor',
component: resolve => require(['../components/page/VueEditor.vue'], resolve)
},
```
第二步:删除引入该组件的文件。在目录 src/components/page/ 删除 VueEditor.vue 文件。
第三步:删除该页面的入口。在目录 src/components/common/Sidebar.vue 中,找到该入口,删除下面这段代码。
```js
{
index: 'editor',
title: '富文本编辑器'
},
```
第四步:卸载该组件。执行以下命令:
npm un vue-quill-editor -S
完成。
### 二、如何切换主题色呢?
第一步:打开 src/main.js 文件,找到引入 element 样式的地方,换成浅绿色主题。
```javascript
import 'element-ui/lib/theme-default/index.css'; // 默认主题
// import './assets/css/theme-green/index.css'; // 浅绿色主题
```
第二步:打开 src/App.vue 文件,找到 style 标签引入样式的地方,切换成浅绿色主题。
```javascript
@import "./assets/css/main.css";
@import "./assets/css/color-dark.css"; /*深色主题*/
/*@import "./assets/css/theme-green/color-green.css"; !*浅绿色主题*!*/
```
第三步:打开 src/components/common/Sidebar.vue 文件,找到 el-menu 标签,把 background-color/text-color/active-text-color 属性去掉即可。
## License
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)

@ -0,0 +1,196 @@
# vue-manage-system
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.8.2-brightgreen.svg" alt="element-ui">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE">
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
</a>
<a href="https://github.com/lin-xin/vue-manage-system/releases">
<img src="https://img.shields.io/github/release/lin-xin/vue-manage-system.svg" alt="GitHub release">
</a>
<a href="https://lin-xin.gitee.io/example/work/#/donate">
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
</a>
The web management system solution based on Vue2 and Element-UI。[live demo](https://lin-xin.gitee.io/example/work/)
## Donation
![WeChat](https://lin-xin.gitee.io/images/weixin.jpg)
## Preface
The scheme as a set of multi-function background frame templates, suitable for most of the WEB management system development. Convenient development fast simple good components based on Vue2 and Element-UI. Color separation of color style, support manual switch themes, and it is convenient to use a custom theme color.
## Function
- [x] Element-UI
- [x] Login/Logout
- [x] Dashboard
- [x] Table
- [x] Tabs
- [x] From
- [x] Chart :bar_chart:
- [x] Editor
- [x] Markdown
- [x] Upload pictures by clipping or dragging
- [x] Support manual switch themes :sparkles:
- [x] List drag sort
- [x] Permission
- [x] 404 / 403
- [x] Three level menu
- [x] Custom icon
## Installation steps
git clone https://github.com/lin-xin/vue-manage-system.git // Clone templates
cd vue-manage-system // Enter template directory
npm install // Installation dependency
## Local development
// Open server and access http://localhost:8080 in browser
npm run serve
## Constructing production
// Constructing project
npm run build
## Component description and presentation
### vue-schart
Vue.js wrapper for sChart.js. Github : [vue-schart](https://github.com/linxin/vue-schart)
```html
<template>
<div>
<schart class="wrapper" canvasId="myCanvas" :options="options"></schart>
</div>
</template>
<script>
import Schart from 'vue-schart'; // 导入Schart组件
export default {
data() {
return {
options: {
type: 'bar',
title: {
text: '最近一周各品类销售图'
},
labels: ['周一', '周二', '周三', '周四', '周五'],
datasets: [
{
label: '家电',
data: [234, 278, 270, 190, 230]
},
{
label: '百货',
data: [164, 178, 190, 135, 160]
},
{
label: '食品',
data: [144, 198, 150, 235, 120]
}
]
}
};
},
components: {
Schart
}
};
</script>
<style>
.wrapper {
width: 7rem;
height: 5rem;
}
</style>
```
### element-ui
A desktop component library based on vue.js2.0 . Github : [element](http://element.eleme.io/#/zh-CN/component/layout)
### Vue-Quill-Editor
Quill editor component for Vue2. Github : [vue-quill-editor](https://github.com/surmon-china/vue-quill-editor)
### mavonEditor
A markdown editor based on Vue that supports a variety of personalized features. Github: [mavonEditor](https://github.com/hinesboy/mavonEditor)
### vue-cropperjs
A Vue wrapper component for cropperjs. Github: [vue-cropperjs](https://github.com/Agontuk/vue-cropperjs)
## Notice
### 一、If I don't want to use some components, how can I delete it?
For example, I don't want to use the Vue-Quill-Editor component, I need to take four steps.
The first step to remove the component of the routing. Enter 'src/router/index.js' and delete the code below.
```JavaScript
{
path: '/editor',
component: resolve => require(['../components/page/VueEditor.vue'], resolve)
},
```
Second,delete the component files. Enter 'src/components/page/' and delete 'VueEditor.vue' file.
The third step is to delete the entry. Enter 'src/components/common/Sidebar.vue' and delete the code below.
```js
{
index: 'editor',
title: '富文本编辑器'
},
```
Finally, uninstall this component.
npm un vue-quill-editor -S
Complete!
### 二、How to switch themes?
The first step to enter 'src/main.js' and change into green theme.
```javascript
import 'element-ui/lib/theme-default/index.css'; // default theme
// import '../static/css/theme-green/index.css'; // green theme
```
The second step to enter 'src/App.vue' and change into green theme.
```javascript
@import "../static/css/main.css";
@import "../static/css/color-dark.css"; /*深色主题*/
/*@import "../static/css/theme-green/color-green.css"; !*浅绿色主题*!*/
```
Finally,enter 'src/components/common/Sidebar.vue' and find el-menu Tags,delete 'background-color/text-color/active-text-color'。
## Screenshot
### Default theme
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms1.png)
### Green theme
![Image text](https://github.com/lin-xin/manage-system/raw/master/screenshots/wms2.png)
## License
[MIT](https://github.com/lin-xin/vue-manage-system/blob/master/LICENSE)

@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/app'
]
}

13497
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,38 @@
{
"name": "vue-manage-system",
"version": "4.2.0",
"private": true,
"scripts": {
"dev": "npm run serve",
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"axios": "^0.18.0",
"babel-polyfill": "^6.26.0",
"echarts": "^4.9.0",
"element-theme": "^2.0.1",
"element-ui": "^2.13.0",
"js-cookie": "^2.2.1",
"lodash": "^4.17.20",
"mavon-editor": "^2.6.17",
"postcss-px2rem": "^0.3.0",
"px2rem-loader": "^0.1.9",
"vue": "^2.6.10",
"vue-cropperjs": "^3.0.0",
"vue-i18n": "^8.10.0",
"vue-quill-editor": "^3.0.6",
"vue-router": "^3.0.3",
"vue-schart": "^2.0.0",
"vuedraggable": "^2.17.0",
"vuex": "^3.1.2"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.9.0",
"@vue/cli-service": "^3.9.0",
"element-theme-chalk": "^2.13.0",
"node-sass": "^4.14.1",
"sass-loader": "^8.0.0",
"vue-template-compiler": "^2.6.10"
}
}

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="//at.alicdn.com/t/font_830376_qzecyukz0s.css">
<title>电子竞技在线教学资源管理平台</title>
</head>
<body>
<noscript>
<strong>We're sorry but vms doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

@ -0,0 +1,32 @@
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script>
import Setting from '@/setting';
import util from '@/libs/util';
export default {
name: 'App',
created () {
//sessionStorage
if (util.session.get(Setting.storeKey) ) {
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(util.session.get(Setting.storeKey))))
}
//vuexsessionStorage
window.addEventListener("beforeunload",()=>{
util.session.get(Setting.usernameKey) && util.session.set(Setting.storeKey,JSON.stringify(this.$store.state))
})
}
}
</script>
<style>
@import "./assets/css/main.css";
/* @import "./assets/css/color-dark.css"; */
/*深色主题*/
@import "./assets/css/theme-green/color-green.css";
/* 浅绿色主题 */
</style>

@ -0,0 +1,123 @@
import Setting from '@/setting';
// let host = Setting.apiBaseURL
let host = 'http://192.168.31.152:8001'//刘本地
// let host = 'http://192.168.31.117'//宁本地
export default {
logins: `${host}/management/userInfo/login`, //登录 
// 查询省份城市
queryProvince: `${host}/enterprise/province/queryProvince`,
queryCity: `${host}/enterprise/city/queryCity`,
queryClient: `${host}/enterprise/client/list`,
userinfoUpdate:`${host}/management/userInfo/update`,//个人中心信息修改
userinfo:`${host}/management/userInfo/getUserInfo`,//个人中心信息展示
getAccount:`${host}/management/userInfo/getAccount`,//账号判重
// 学生班级
addClass: `${host}/management/class/addClass`,
deleteClass: `${host}/management/class/deleteClass`,
queryClass: `${host}/management/class/queryClass`,
updateClass: `${host}/management/class/updateClass`,
// 学生年级
addGrade: `${host}/management/grade/addGrade`,
deleteGrade: `${host}/management/grade/deleteGrade`,
queryGrade: `${host}/management/grade/queryGrade`,
updateGrade: `${host}/management/grade/updateGrade`,
// 学生专业组织
addStudentProfessionalArchitecture: `${host}/management/studentProfessionalArchitecture/addStudentProfessionalArchitecture`,
deleteStaffProfessionalArchitecture: `${host}/management/studentProfessionalArchitecture/deleteStaffProfessionalArchitecture`,
queryStudentProfessionalArchitecture: `${host}/management/studentProfessionalArchitecture/queryStudentProfessionalArchitecture`,
updateStaffProfessionalArchitecture: `${host}/management/studentProfessionalArchitecture/updateStaffProfessionalArchitecture`,
// 学生管理
addStudent: `${host}/management/student/addStudent`,
deleteStudents: `${host}/management/student/deleteStudents`,
getStudent: `${host}/management/student/getStudent`,
queryStudent: `${host}/management/student/list`,
updateStudent: `${host}/management/student/updateStudent`,
studentGetWorkNumber: `${host}/management/student/getWorkNumber`,
exportFailureStudent: `${host}/management/student/exportFailure`,
uploadFileStudent: `${host}/management/student/uploadFile`,
downloadStudentTemp: 'http://liuwanr.oss-cn-shenzhen.aliyuncs.com/xlsx/20201102/1604658660956.xlsx',
// 一级部门
addStaffPro: `${host}/management/staffProfessionalArchitecture/addStaffProfessionalArchitecture`,
deleteStaffPro: `${host}/management/staffProfessionalArchitecture/deleteStaffProfessionalArchitecture`,
queryStaffPAN: `${host}/management/staffProfessionalArchitecture/queryStaffPAN`,
queryStaffPro: `${host}/management/staffProfessionalArchitecture/queryStaffProfessionalArchitecture`,
updateStaffPro: `${host}/management/staffProfessionalArchitecture/updateStaffProfessionalArchitecture`,
// 二级部门
addStaffGrade: `${host}/management/staffGrade/addStaffGrade`,
deleteStaffGrade: `${host}/management/staffGrade/deleteStaffGrade`,
queryStaffGrade: `${host}/management/staffGrade/queryStaffGrade`,
queryStaffName: `${host}/management/staffGrade/queryStaffName`,
updateStaffGrade: `${host}/management/staffGrade/updateStaffGrade`,
// 员工管理
addStaff: `${host}/management/staff/addStaff`,
deleteStaffs: `${host}/management/staff/deleteStaffs`,
getStaff: `${host}/management/staff/getStaff`,
queryStaff: `${host}/management/staff/managementList`,
updateStaff: `${host}/management/staff/updateStaff`,
getWorkNumber: `${host}/management/staff/getWorkNumber`,
exportFailureStaff: `${host}/management/staff/exportFailure`,
uploadFileStaff: `${host}/management/staff/uploadFile`,
downloadStaffTemp: `http://liuwanr.oss-cn-shenzhen.aliyuncs.com/xlsx/20201102/1604658763812.xlsx`,
// 角色管理
getRole: `${host}/management/role/get`,
queryRoles: `${host}/management/role/list`,
removeRole: `${host}/management/role/batchRemove`,
saveOrUpdate: `${host}/management/role/saveOrUpdate`,
// 权限菜单管理
doAssign: `${host}/management/permission/doAssign`,
queryPermissionMenu: `${host}/management/permission/queryManagementPermissionMenu`,
toAssign: `${host}/management/permission/toAssign`,
// 视频管理
fileDeletion: `${host}/oss/manage/fileDeletion`, //批量删除文件
fileupload: `${host}/oss/manage/fileupload`, //文件上传
getPlayAuth: `${host}/oss/manage/getPlayAuth`, //获取播放凭证
removeMoreVideo: `${host}/oss/manage/removeMoreVideo`, //批量删除视频文件
removeVideo: `${host}/oss/manage/removeVideo`, //删除视频文件
getTypeByOneLever:`${host}/enterprise/questionBank/getTypeByOneLever`,
typesList:`${host}/enterprise/questionTypes/typesList`,
// 共享相关
deleteBySharing:`${host}/management/questionSharing/deleteBySharing`,
detailSharing:`${host}/management/questionSharing/detail`,
getMeSharingInfo:`${host}/management/questionSharing/getMeSharingInfo`,
pageByConditionSharing:`${host}/management/questionSharing/pageByConditionSharing`,
saveSharing:`${host}/management/questionSharing/save`,
// 试卷管理
copyPaper:`${host}/management/testPaper/copyPaper`,
delByMyTestPaper:`${host}/management/testPaper/delByMyTestPaper`,
detailtestPaper:`${host}/management/testPaper/detail`,
pageBySchoolTestPaper:`${host}/management/testPaper/pageBySchoolTestPaper`,
pageBygetMeTestPaper:`${host}/management/testPaper/pageBygetMeTestPaper`,
previewtestPaper:`${host}/management/testPaper/preview`,
saveOrUpdatetestPaper:`${host}/management/testPaper/saveOrUpdate`,
getModifyByList:`${host}/management/testPaper/getModifyByList`,
// 试题信息相关
addQuestions:`${host}/management/questions/addQuestions`,
fuzzyQuery:`${host}/management/questions/fuzzyQuery`,
getSelectInfo:`${host}/management/questions/getSelectInfo`,
pageByChoiceList:`${host}/management/questions/pageByChoiceList`,
statistical:`${host}/management/questions/statistical`,
getQuestionListBySelect:`${host}/management/questions/getQuestionListBySelect`,
// 考核管理
addAssessment:`${host}/management/gz-assessment/addAssessment`,
deleteAssessment:`${host}/management/gz-assessment/deleteAssessment`,
queryAssessment:`${host}/management/gz-assessment/queryAssessment`,
updateAssessment:`${host}/management/gz-assessment/updateAssessment`,
}

@ -0,0 +1,28 @@
.header{
background-color: #242f42;
}
.login-wrap{
background: #324157;
}
.plugins-tips{
background: #eef1f6;
}
.plugins-tips a{
color: #20a0ff;
}
.el-upload--text em {
color: #20a0ff;
}
.pure-button{
background: #20a0ff;
}
.tags-li.active {
border: 1px solid #409EFF;
background-color: #409EFF;
}
.message-title{
color: #20a0ff;
}
.collapse-btn:hover{
background: rgb(40,52,70);
}

@ -0,0 +1,4 @@
[class*=" icon-"], [class^=icon-] {
font-family: iconfont!important;
}

@ -0,0 +1,384 @@
* {
margin: 0;
padding: 0;
}
html,
body,
#app,
.wrapper {
width: 100%;
height: 100%;
}
body {
font-family: 'PingFang SC', "Helvetica Neue", Helvetica, "microsoft yahei", arial, STHeiTi, sans-serif;
font-size: 14px;
background: #f0f0f0;
}
a {
text-decoration: none
}
i{
font-style: normal;
}
li {
list-style-type:none;
}
.required{
margin-right: 5px;
color: #F56C6C;
}
.content-box {
-webkit-transition: left .3s ease-in-out;
transition: left .3s ease-in-out;
}
.content {
width: auto;
height: 100%;
padding: 20px;
box-sizing: border-box;
}
.content-collapse {
left: 65px;
}
.container {
padding: 30px;
background: #fff;
border: 1px solid #ddd;
border-radius: 5px;
}
.crumbs {
margin: 10px 0;
}
.el-table th {
background-color: #f5f7fa !important;
}
.pagination {
margin: 20px 0;
text-align: right;
}
.plugins-tips {
padding: 20px 10px;
margin-bottom: 20px;
}
.el-button+.el-tooltip {
margin-left: 10px;
}
.el-table tr:hover {
background: #f6faff;
}
.orderTable td .el-input{
width: 60%;
}
.orderTable .el-select>.el-input{
display: inline-block;
}
.mgb20 {
margin-bottom: 20px;
}
.move-enter-active,
.move-leave-active {
transition: opacity .5s;
}
.move-enter,
.move-leave {
opacity: 0;
}
/*BaseForm*/
.form-box {
width: 600px;
}
.form-box .line {
text-align: center;
}
.el-time-panel__content::after,
.el-time-panel__content::before {
margin-top: -7px;
}
.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default) {
padding-bottom: 0;
}
/*Upload*/
.pure-button {
width: 150px;
height: 40px;
line-height: 40px;
text-align: center;
color: #fff;
border-radius: 3px;
}
.g-core-image-corp-container .info-aside {
height: 45px;
}
.avatar-uploader .el-upload--text {
background-color: #fff;
border: 1px dashed #d9d9d9;
border-radius: 6px;
box-sizing: border-box;
width: 360px;
height: 180px;
text-align: center;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload--text .el-icon-upload {
font-size: 67px;
color: #97a8be;
margin: 40px 0 16px;
line-height: 50px;
}
.avatar-uploader .el-upload--text {
color: #97a8be;
font-size: 14px;
text-align: center;
}
.avatar-uploader .el-upload--text em {
font-style: normal;
}
/* .link_upload .el-upload-list{
width: 30%;
} */
/*VueEditor*/
.ql-container {
min-height: 400px;
}
.ql-snow .ql-tooltip {
transform: translateX(117.5px) translateY(10px) !important;
}
.editor-btn {
margin-top: 20px;
}
/*markdown*/
.v-note-wrapper .v-note-panel {
min-height: 500px;
}
.ms-login .el-tabs__nav-wrap::after{
background-color: #fff;
opacity: 0;
}
.ms-login .el-tabs__item{
padding: 0 90px;
color: #999;
}
.ms-login .el-tabs__item:hover{
color: #000;
}
.ms-login .el-tabs__item.is-active{
color: #333;
font-weight: bold;
}
.ms-login .el-tabs__active-bar{
background-color: #000;
border-radius:2px;
}
.ms-login .el-tabs__nav-scroll{
display: flex;
justify-content: center;
}
.ms-login .el-input__inner{
height: 80px;
line-height: 80px;
border:1px solid rgba(220,220,220,1);
border-radius:2px;
}
.el-row {
margin-bottom: 20px;
}
.mgb20 {
margin-bottom: 20px;
}
#app .el-table thead{
color: #fff;
}
#app .el-table th{
background-color: #cb221c!important;
font-size: 16px;
font-weight: normal;
}
#app .el-select{
display: unset;
}
/*flex*/
.flex-center{
display: flex;
align-items: center;
}
.flex-between{
display: flex;
align-items: center;
justify-content: space-between;
}
.flex-around{
display: flex;
align-items: center;
justify-content: space-around;
}
.flex-start-around{
display: flex;
align-items: flex-start;
justify-content: center;
}
.flex-end-around{
display: flex;
align-items: flex-end;
justify-content: center;
}
.flex-column{
display: flex;
align-items: center;
flex-direction: column;
}
.flex-start{
display: flex;
align-items: flex-start;
}
.flex-end{
display: flex;
align-items: flex-end;
}
.flex-justify-end{
display: flex;
justify-content: flex-end;
}
.hr_tag{
background-color: #cb221c;
width: 3px;
height: 15px;
margin-right: 5px;
}
.user_header{
padding: 20px 0;
border-bottom: 1px dashed #eee;
}
.addhr_tag{
background-color: #666;
width: 6px;
height: 17px;
margin-right: 5px;
}
.per_title span{
font-size: 16px;
font-weight: bold;
}
.per_back{
margin-left: 5px;
}
.per_school{
margin-left: 30px;
}
.per_title:hover{
cursor:pointer;
}
/* 溢出省略号 */
.ellipsis{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tabs{
display: flex;
align-items: center;
padding: 20px 1.5% 20px;
margin-bottom: 20px;
z-index: 999;
background-color: #fff;
}
.tabs .item{
padding: 12px 20px;
margin-right: 10px;
color:#606266;
line-height: 1;
border-radius: 4px;
background-color: #fff;
border: 1px solid #dcdfe6;
cursor: pointer;
}
.tabs .active{
color: #fff;
background-color: #cb221c;
border-color: #cb221c;
}
.btns{
display: flex;
justify-content: center;
margin-top: 20px;
}
.btns button{
height: 30px;
padding: 0 30px;
margin: 0 15px;
font-size: 14px;
color: #333;
line-height: 30px;
background-color: #fff;
border: 1px solid #ededed;
border-radius: 4px;
cursor: pointer;
}
.btns .submit{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
.btns button:hover{
opacity: .8;
}
.btns button:focus{
outline: none;
}
.userRadio .el-radio{
margin-right: 10px!important;
}
.userRadio .el-radio__input{
display: none!important;
}

@ -0,0 +1,29 @@
.header{
background-color: #fff;
}
.login-wrap{
background: rgba(56, 157, 170, 0.82);;
}
.plugins-tips{
background: #f2f2f2;
}
.plugins-tips a{
color: #cb221c;
}
.el-upload--text em {
color: #cb221c;
}
.pure-button{
background: #cb221c;
}
.pagination > .active > a, .pagination > .active > a:hover, .pagination > .active > a:focus, .pagination > .active > span, .pagination > .active > span:hover, .pagination > .active > span:focus {
background-color: #cb221c !important;
border-color: #cb221c !important;
}
.tags-li.active {
border: 1px solid #cb221c;
background-color: #cb221c;
}
.collapse-btn:hover{
background: #cb221c;
}

File diff suppressed because one or more lines are too long

@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}
.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* tabs */
.nav-tabs {
position: relative;
}
.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}
#tabs {
border-bottom: 1px solid #eee;
}
#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}
#tabs .active {
border-bottom-color: #f00;
color: #222;
}
.tab-container .content {
display: none;
}
/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}
.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}
.main .logo a {
font-size: 160px;
color: #333;
}
.helps {
margin-top: 40px;
}
.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}
.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}
.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}
.icon_lists li .code-name {
line-height: 1.2;
}
.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}
.icon_lists .icon:hover {
font-size: 100px;
}
.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}
.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}
/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}
.highlight {
line-height: 1.5;
}
.markdown img {
vertical-align: middle;
max-width: 100%;
}
.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}
.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}
.markdown h1 {
font-size: 28px;
}
.markdown h2 {
font-size: 22px;
}
.markdown h3 {
font-size: 16px;
}
.markdown h4 {
font-size: 14px;
}
.markdown h5 {
font-size: 12px;
}
.markdown h6 {
font-size: 12px;
}
.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}
.markdown p {
margin: 1em 0;
}
.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}
.markdown ul>li {
list-style: circle;
}
.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}
.markdown ol>li {
list-style: decimal;
}
.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}
.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}
.markdown strong,
.markdown b {
font-weight: 600;
}
.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}
.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}
.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}
.markdown>table th {
background: #F7F7F7;
}
.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}
.markdown blockquote p {
margin: 0;
}
.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}
.markdown .waiting {
color: #ccc;
}
.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}
.markdown>br,
.markdown>p>br {
clear: both;
}
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}
/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}

@ -0,0 +1,446 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>IconFont Demo</title>
<link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/>
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
<link rel="stylesheet" href="demo.css">
<link rel="stylesheet" href="iconfont.css">
<script src="iconfont.js"></script>
<!-- jQuery -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
<!-- 代码高亮 -->
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
</head>
<body>
<div class="main">
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">&#xe86b;</a></h1>
<div class="nav-tabs">
<ul id="tabs" class="dib-box">
<li class="dib active"><span>Unicode</span></li>
<li class="dib"><span>Font class</span></li>
<li class="dib"><span>Symbol</span></li>
</ul>
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1540265" target="_blank" class="nav-more">查看项目</a>
</div>
<div class="tab-container">
<div class="content unicode" style="display: block;">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont">&#xe63d;</span>
<div class="name">已勾选32</div>
<div class="code-name">&amp;#xe63d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe63e;</span>
<div class="name">未勾选32</div>
<div class="code-name">&amp;#xe63e;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64a;</span>
<div class="name">未勾选40</div>
<div class="code-name">&amp;#xe64a;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe64b;</span>
<div class="name">已勾选40</div>
<div class="code-name">&amp;#xe64b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe626;</span>
<div class="name">实 向右箭头-01</div>
<div class="code-name">&amp;#xe626;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe625;</span>
<div class="name">实 向下箭头-01</div>
<div class="code-name">&amp;#xe625;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe72d;</span>
<div class="name">加号-填充</div>
<div class="code-name">&amp;#xe72d;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe769;</span>
<div class="name">42指向上、上箭头</div>
<div class="code-name">&amp;#xe769;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe76b;</span>
<div class="name">44指向下、下箭头</div>
<div class="code-name">&amp;#xe76b;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe6e9;</span>
<div class="name">群蜂删除-充</div>
<div class="code-name">&amp;#xe6e9;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe614;</span>
<div class="name">qq</div>
<div class="code-name">&amp;#xe614;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe68a;</span>
<div class="name">微信-36</div>
<div class="code-name">&amp;#xe68a;</div>
</li>
</ul>
<div class="article markdown">
<h2 id="unicode-">Unicode 引用</h2>
<hr>
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
<ul>
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li>
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li>
</ul>
<blockquote>
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式</p>
</blockquote>
<p>Unicode 使用步骤如下:</p>
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
<pre><code class="language-css"
>@font-face {
font-family: 'iconfont';
src: url('iconfont.eot');
src: url('iconfont.eot?#iefix') format('embedded-opentype'),
url('iconfont.woff2') format('woff2'),
url('iconfont.woff') format('woff'),
url('iconfont.ttf') format('truetype'),
url('iconfont.svg#iconfont') format('svg');
}
</code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
<pre><code class="language-css"
>.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
<pre>
<code class="language-html"
>&lt;span class="iconfont"&gt;&amp;#x33;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content font-class">
<ul class="icon_lists dib-box">
<li class="dib">
<span class="icon iconfont icon-yigouxuan"></span>
<div class="name">
已勾选32
</div>
<div class="code-name">.icon-yigouxuan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weigouxuan"></span>
<div class="name">
未勾选32
</div>
<div class="code-name">.icon-weigouxuan
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weigouxuan1"></span>
<div class="name">
未勾选40
</div>
<div class="code-name">.icon-weigouxuan1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-yigouxuan1"></span>
<div class="name">
已勾选40
</div>
<div class="code-name">.icon-yigouxuan1
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shixiangyoujiantou-"></span>
<div class="name">
实 向右箭头-01
</div>
<div class="code-name">.icon-shixiangyoujiantou-
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-shixiangxiajiantou-"></span>
<div class="name">
实 向下箭头-01
</div>
<div class="code-name">.icon-shixiangxiajiantou-
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-jiahao"></span>
<div class="name">
加号-填充
</div>
<div class="code-name">.icon-jiahao
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-up"></span>
<div class="name">
42指向上、上箭头
</div>
<div class="code-name">.icon-up
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-down"></span>
<div class="name">
44指向下、下箭头
</div>
<div class="code-name">.icon-down
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-delete"></span>
<div class="name">
群蜂删除-充
</div>
<div class="code-name">.icon-delete
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-qq"></span>
<div class="name">
qq
</div>
<div class="code-name">.icon-qq
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-weixin"></span>
<div class="name">
微信-36
</div>
<div class="code-name">.icon-weixin
</div>
</li>
</ul>
<div class="article markdown">
<h2 id="font-class-">font-class 引用</h2>
<hr>
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
<p>与 Unicode 使用方式相比,具有如下特点:</p>
<ul>
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li>
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
<pre><code class="language-html">&lt;link rel="stylesheet" href="./iconfont.css"&gt;
</code></pre>
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;span class="iconfont icon-xxx"&gt;&lt;/span&gt;
</code></pre>
<blockquote>
<p>"
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
</blockquote>
</div>
</div>
<div class="content symbol">
<ul class="icon_lists dib-box">
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yigouxuan"></use>
</svg>
<div class="name">已勾选32</div>
<div class="code-name">#icon-yigouxuan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weigouxuan"></use>
</svg>
<div class="name">未勾选32</div>
<div class="code-name">#icon-weigouxuan</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weigouxuan1"></use>
</svg>
<div class="name">未勾选40</div>
<div class="code-name">#icon-weigouxuan1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-yigouxuan1"></use>
</svg>
<div class="name">已勾选40</div>
<div class="code-name">#icon-yigouxuan1</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shixiangyoujiantou-"></use>
</svg>
<div class="name">实 向右箭头-01</div>
<div class="code-name">#icon-shixiangyoujiantou-</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-shixiangxiajiantou-"></use>
</svg>
<div class="name">实 向下箭头-01</div>
<div class="code-name">#icon-shixiangxiajiantou-</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-jiahao"></use>
</svg>
<div class="name">加号-填充</div>
<div class="code-name">#icon-jiahao</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-up"></use>
</svg>
<div class="name">42指向上、上箭头</div>
<div class="code-name">#icon-up</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-down"></use>
</svg>
<div class="name">44指向下、下箭头</div>
<div class="code-name">#icon-down</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-delete"></use>
</svg>
<div class="name">群蜂删除-充</div>
<div class="code-name">#icon-delete</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-qq"></use>
</svg>
<div class="name">qq</div>
<div class="code-name">#icon-qq</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-weixin"></use>
</svg>
<div class="name">微信-36</div>
<div class="code-name">#icon-weixin</div>
</li>
</ul>
<div class="article markdown">
<h2 id="symbol-">Symbol 引用</h2>
<hr>
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
<ul>
<li>支持多色图标了,不再受单色限制。</li>
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
</ul>
<p>使用步骤如下:</p>
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
<pre><code class="language-html">&lt;script src="./iconfont.js"&gt;&lt;/script&gt;
</code></pre>
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
<pre><code class="language-html">&lt;style&gt;
.icon {
width: 1em;
height: 1em;
vertical-align: -0.15em;
fill: currentColor;
overflow: hidden;
}
&lt;/style&gt;
</code></pre>
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
<pre><code class="language-html">&lt;svg class="icon" aria-hidden="true"&gt;
&lt;use xlink:href="#icon-xxx"&gt;&lt;/use&gt;
&lt;/svg&gt;
</code></pre>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.tab-container .content:first').show()
$('#tabs li').click(function (e) {
var tabContent = $('.tab-container .content')
var index = $(this).index()
if ($(this).hasClass('active')) {
return
} else {
$('#tabs li').removeClass('active')
$(this).addClass('active')
tabContent.hide().eq(index).fadeIn()
}
})
})
</script>
</body>
</html>

@ -0,0 +1,71 @@
@font-face {font-family: "iconfont";
src: url('iconfont.eot?t=1589437921018'); /* IE9 */
src: url('iconfont.eot?t=1589437921018#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAdgAAsAAAAADwwAAAcTAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCESgqOeIt2ATYCJAM0CxwABCAFhG0HgTMbpQxRlHBSFNlX2JThXqSJ4cz0aLyxzNkVgYOP2N97wQhUeQbPDZA1QByDeHha+9+5M7PrD1FpdI8mCSqJLulDJPFDxCQTvUQS6Qtka3ukU0/kuK8wfBBwMr1kmeTIb8hUohVh6lTeCHDCrRPPf5v6f+sQfS+QqgmpiZLNw+ZI6zMXZGL3nXY47elJFnjALaE4zjzyjJN773yuzM/7H4oZ9NV+v/q1g1ddvP1QmE5JlPRM7uAv5klMk0vWTBWTLpoJEUIja6hWSkNhOklN/ds4n0BvhyLMuZ6hKdArLC1Q4a4iG0Gfi1JaHEMbXtfsW8S8SpsepzuAJ+HLx28hoSepMmvby3e6LdC2EN2eV0ykW36MR/MlQFiJjGNAEej7WvtLgB6aM6evXtwH1glnTloW1snRYnBhky+LxyuL9glaGNmaDbRsJYR1tl+seImrgUGtEtLc//GMeo1WR9QYfUSrp7nohWgXDRrJBqpBcoAqkGagAGkBSiADQBlkEKiAbAI/N/mCYHoWi1HDEgWoBbGjlg7M/OpbgEMgnUf0fxab8kjK0tvq8cZ6/dpKwk4bNsXFx4bHR4RHcty4LVnR4xp/2TFxDN42tgefhUpEMeeqppXCU50JyT/gkVCD+EiEgl56LOkMN+6cAfyKs3dvomHU7fvnq96Uc/duIXMMqWmhNRoax1m8jNWfPorp2jlqumvHrolfe/2TcuIPCt3K589dhUNiT5OSEh4KoM9Jp1vK2GMnFjDdyaeFMrd06ki1gn9CmEz3OErpebmp+GzyAN+lMLw6dwkKh6Ve5dOnzp4W0+Y25TTfhHB10isXpxIB5GHDKcggnof+NCpCD+okAFyTPNGuRVgahmhLjZo1rnqnMlpD0ORJSluuY6jT+gPWHtaIeDKOaoradNDPruOQzulPGcBtz0C2YdbLrSFPIMGTrcNRDGC3YnJOm1JLceYK2sCWY5lqxICXIEU0gki2nkPFUteBwoqLMyTdKE7ZlOzE3yHfdSyOU2shl8RoxPJlx1bQ6C0Li3DLg+Sdi+c5evEkhtF3rBdfXpe0IiNcfW27+x6u5U4vs8zZZdu1R7Gblyc6AV9OB4Xp65HRDqcvw0Pi1DGbddntOKzYgkbhXJq+Y4bRVqszl746KdRPFV5FxSUb6XmKomd1yCb0nJbpz+aOIZskx0phXx8sHfNKyRjPsM8LGU/xJ9Qrv2JugdVBkBg/ZpUIDvpN0jfHD550XPKNDgkKEZ46l4dwq0sOxIecJlX2pxxA8GTwkCGMFqxVFf5PRZplCky9uCIQL/s/RFabTYZNkhtkQXFR28vKXwKUP5rZbFg+s3VAFTu5dBZG4G07t5tHuM2cFirh2BisrHKYoE8lzO1h/LkwjSD+VZF0qs1hQVK+d0xHOLN80q4B/P9utxQDmGt4DaEKE6Lc5lnI6VxDf/35owQHCAuKw95VG6l1bvXPY3J1slpepPBXdCx8EM+ubbd2tV48b2UtWLtYb89PZhvg2jsq5+zkBdIVVTFHfhEwNv0CxNiT02LKVxGSus1dt9VsXDZulogOJB1AkGQVg4e833uzaWatx7bPrLKyhBeBqlC3xGqNoe3MVQHmDmBs4jm+xFjW/sjcAgOiPOFawwe3bUeTa20vGNZgbV6tCtL/qEL/fmiFLjqCCDpZdQpkdKgx6tSuzlCdqnrMFsLMhWn9sKH4ezmjmvpp9Selw9oCS0Vtcbox4f967yYpc1lNwUzPAUT3N0R32yz0bof5Wblw2jzkuw4VkWFptzoKckHRUwszvHJS8IgkAfys2IvKr/LtZBa1LzvfHBmFD6/V9enLD7LLJD2tz7n3E8BkFcwVyA/DL8P0fCpXAdLntBfy9tQCpuUP2QBAWkwyYccYGYFWWc/HS8Of6pVNf1r8p8n48bn+wPLzm5gyWoneAh3ivzATiiRKljoz8hQTN3S0itSojpnbgvjFod7uBf2Rtsa7dej63gKVRdenkDS2Q9baZyzWY1AZnIBa6yT0juo9eLCWhhOlwxFrCYRVjkKywhfIVrlrLNa3UNngB9RWBQe9mxF1zMGBUFCnRoyUWLBpCStm1SU5sRRFFSeI7HUYtawUeswQzaNk4PKSsmJBL3ERbY4dPD65glIJS5rqxD3kYsThULFbU23ETEuslLobSkuluh1LzKoTkLM0hBH1A1pgJku2CjOVizQ+hUrPP4GQeTkYaS0tarYzCI2HMnusXImyHsZe3dWrxb1U9/CRVaBMggS79TUqJ6yHSSAcdq4Kc9evZUOYUSWsI7LdGpQy7Ul99ZL1qfObT4CedX+zSJGjRBV1NNFGF30MMcYsVugeKLLqDXiNLuQnSQjRvRwtrRzlsSoBxeiSl1SvLVQoF1FcZj0Jqi46odWosl43b1H9Lp2FOAgl7OKibs6cgOICAA==') format('woff2'),
url('iconfont.woff?t=1589437921018') format('woff'),
url('iconfont.ttf?t=1589437921018') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('iconfont.svg?t=1589437921018#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-yigouxuan:before {
content: "\e63d";
}
.icon-weigouxuan:before {
content: "\e63e";
}
.icon-weigouxuan1:before {
content: "\e64a";
}
.icon-yigouxuan1:before {
content: "\e64b";
}
.icon-shixiangyoujiantou-:before {
content: "\e626";
}
.icon-shixiangxiajiantou-:before {
content: "\e625";
}
.icon-jiahao:before {
content: "\e72d";
}
.icon-up:before {
content: "\e769";
}
.icon-down:before {
content: "\e76b";
}
.icon-delete:before {
content: "\e6e9";
}
.icon-qq:before {
content: "\e614";
font-size: 60px;
color: #22aaf8;
margin-left: 32px;
}
.icon-weixin:before {
content: "\e68a";
font-size: 60px;
color: #10b747;
margin-right: 32px;
}

Binary file not shown.

File diff suppressed because one or more lines are too long

@ -0,0 +1,93 @@
{
"id": "1540265",
"name": "education",
"font_family": "iconfont",
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "2716513",
"name": "已勾选32",
"font_class": "yigouxuan",
"unicode": "e63d",
"unicode_decimal": 58941
},
{
"icon_id": "2716516",
"name": "未勾选32",
"font_class": "weigouxuan",
"unicode": "e63e",
"unicode_decimal": 58942
},
{
"icon_id": "2892929",
"name": "未勾选40",
"font_class": "weigouxuan1",
"unicode": "e64a",
"unicode_decimal": 58954
},
{
"icon_id": "2892954",
"name": "已勾选40",
"font_class": "yigouxuan1",
"unicode": "e64b",
"unicode_decimal": 58955
},
{
"icon_id": "5979965",
"name": "实 向右箭头-01",
"font_class": "shixiangyoujiantou-",
"unicode": "e626",
"unicode_decimal": 58918
},
{
"icon_id": "5979966",
"name": "实 向下箭头-01",
"font_class": "shixiangxiajiantou-",
"unicode": "e625",
"unicode_decimal": 58917
},
{
"icon_id": "8349103",
"name": "加号-填充",
"font_class": "jiahao",
"unicode": "e72d",
"unicode_decimal": 59181
},
{
"icon_id": "6129078",
"name": "42指向上、上箭头",
"font_class": "up",
"unicode": "e769",
"unicode_decimal": 59241
},
{
"icon_id": "6129081",
"name": "44指向下、下箭头",
"font_class": "down",
"unicode": "e76b",
"unicode_decimal": 59243
},
{
"icon_id": "410692",
"name": "群蜂删除-充",
"font_class": "delete",
"unicode": "e6e9",
"unicode_decimal": 59113
},
{
"icon_id": "468193",
"name": "qq",
"font_class": "qq",
"unicode": "e614",
"unicode_decimal": 58900
},
{
"icon_id": "7009153",
"name": "微信-36",
"font_class": "weixin",
"unicode": "e68a",
"unicode_decimal": 59018
}
]
}

@ -0,0 +1,62 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<!--
2013-9-30: Created.
-->
<svg>
<metadata>
Created by iconfont
</metadata>
<defs>
<font id="iconfont" horiz-adv-x="1024" >
<font-face
font-family="iconfont"
font-weight="500"
font-stretch="normal"
units-per-em="1024"
ascent="896"
descent="-128"
/>
<missing-glyph />
<glyph glyph-name="yigouxuan" unicode="&#58941;" d="M196.923077 896h630.153846a196.923077 196.923077 0 0 0 196.923077-196.923077v-630.153846a196.923077 196.923077 0 0 0-196.923077-196.923077H196.923077a196.923077 196.923077 0 0 0-196.923077 196.923077V699.076923a196.923077 196.923077 0 0 0 196.923077 196.923077z m0-78.769231a118.153846 118.153846 0 0 1-118.153846-118.153846v-630.153846a118.153846 118.153846 0 0 1 118.153846-118.153846h630.153846a118.153846 118.153846 0 0 1 118.153846 118.153846V699.076923a118.153846 118.153846 0 0 1-118.153846 118.153846H196.923077z m584.900923-258.205538a36.509538 36.509538 0 0 0 1.260308-51.633231l-299.480616-313.107692c-0.118154-0.157538-0.393846-0.236308-0.630154-0.472616l-0.393846-0.551384c-2.166154-2.126769-4.726154-3.229538-7.207384-4.726154-1.575385-0.866462-2.796308-2.166154-4.411077-2.835692a35.800615 35.800615 0 0 0-27.490462-0.07877c-1.260308 0.512-2.284308 1.614769-3.544615 2.284308-2.756923 1.457231-5.592615 2.835692-8.034462 5.12-0.196923 0.157538-0.275692 0.433231-0.512 0.669538-0.196923 0.118154-0.393846 0.196923-0.551384 0.354462l-150.843077 156.593231a36.430769 36.430769 0 0 0 0.945231 51.633231 36.391385 36.391385 0 0 0 51.63323-0.945231l124.455385-129.102769 273.092923 285.61723a36.548923 36.548923 0 0 0 51.712 1.181539z" horiz-adv-x="1024" />
<glyph glyph-name="weigouxuan" unicode="&#58942;" d="M196.923077 817.230769a118.153846 118.153846 0 0 1-118.153846-118.153846v-630.153846a118.153846 118.153846 0 0 1 118.153846-118.153846h630.153846a118.153846 118.153846 0 0 1 118.153846 118.153846V699.076923a118.153846 118.153846 0 0 1-118.153846 118.153846H196.923077z m0 78.769231h630.153846a196.923077 196.923077 0 0 0 196.923077-196.923077v-630.153846a196.923077 196.923077 0 0 0-196.923077-196.923077H196.923077a196.923077 196.923077 0 0 0-196.923077 196.923077V699.076923a196.923077 196.923077 0 0 0 196.923077 196.923077z" horiz-adv-x="1024" />
<glyph glyph-name="weigouxuan1" unicode="&#58954;" d="M256 768a128 128 0 0 1-128-128v-512a128 128 0 0 1 128-128h512a128 128 0 0 1 128 128V640a128 128 0 0 1-128 128H256z m0 51.2h512a179.2 179.2 0 0 0 179.2-179.2v-512a179.2 179.2 0 0 0-179.2-179.2H256a179.2 179.2 0 0 0-179.2 179.2V640a179.2 179.2 0 0 0 179.2 179.2z" horiz-adv-x="1024" />
<glyph glyph-name="yigouxuan1" unicode="&#58955;" d="M796.912941 598.437647L407.491765 203.294118l-156.611765 172.272941a30.177882 30.177882 0 0 1-44.574118-40.658824L361.411765 161.430588a60.235294 60.235294 0 0 1 85.232941-3.915294l2.409412 2.409412 390.927058 396.348235a30.117647 30.117647 0 1 1-43.068235 42.164706zM813.176471 896H210.823529a210.823529 210.823529 0 0 1-210.823529-210.823529v-602.352942a210.823529 210.823529 0 0 1 210.823529-210.823529h602.352942a210.823529 210.823529 0 0 1 210.823529 210.823529V685.176471a210.823529 210.823529 0 0 1-210.823529 210.823529z m150.588235-813.176471a150.588235 150.588235 0 0 0-150.588235-150.588235H210.823529a150.588235 150.588235 0 0 0-150.588235 150.588235V685.176471a150.588235 150.588235 0 0 0 150.588235 150.588235h602.352942a150.588235 150.588235 0 0 0 150.588235-150.588235z" horiz-adv-x="1024" />
<glyph glyph-name="shixiangyoujiantou-" unicode="&#58918;" d="M701.44 384L322.56 99.413V668.587L701.44 384z" horiz-adv-x="1024" />
<glyph glyph-name="shixiangxiajiantou-" unicode="&#58917;" d="M512 194.56L227.413 573.44h569.174L512 194.56z" horiz-adv-x="1024" />
<glyph glyph-name="jiahao" unicode="&#59181;" d="M512 864C246.4 864 32 649.6 32 384s214.4-480 480-480 480 214.4 480 480S777.6 864 512 864z m256-512h-224v-224c0-19.2-12.8-32-32-32s-32 12.8-32 32v224H256c-19.2 0-32 12.8-32 32s12.8 32 32 32h224V640c0 19.2 12.8 32 32 32s32-12.8 32-32v-224h224c19.2 0 32-12.8 32-32s-12.8-32-32-32z" horiz-adv-x="1024" />
<glyph glyph-name="up" unicode="&#59241;" d="M508.4 445.9l1.8 1.8-1.8-1.8zM508.2 447.9l2.2-2.2c-0.7 0.8-1.4 1.5-2.2 2.2zM511.1 485l1.8-1.8-1.8 1.8zM510.9 483l2.2 2.2c-0.8-0.7-1.5-1.4-2.2-2.2zM544 521.3v-336c0-17.6-14.4-32-32-32s-32 14.4-32 32v336c0 17.6 14.4 32 32 32s32-14.4 32-32zM511.9 614.7c-8.3 0-15.8-3.1-21.5-8.3l-2.2-2.2-21.5-21.5L291 407c-12.4-12.4-12.4-32.8 0-45.3 12.4-12.4 32.8-12.4 45.3 0L512 537.5l175.8-175.7c12.4-12.4 32.8-12.4 45.3 0 12.4 12.4 12.4 32.8-0.1 45.2L557.3 582.7l-21.8 21.8-1.8 1.8c-5.7 5.3-13.4 8.5-21.8 8.4z" horiz-adv-x="1024" />
<glyph glyph-name="down" unicode="&#59243;" d="M515.6 322.1l-1.8-1.8 1.8 1.8zM515.8 320.1l-2.2 2.2c0.7-0.8 1.4-1.5 2.2-2.2zM512.9 283l-1.8 1.8 1.8-1.8zM513.1 285l-2.2-2.2c0.8 0.7 1.5 1.4 2.2 2.2zM480 246.70000000000005v336c0 17.6 14.4 32 32 32s32-14.4 32-32v-336c0-17.6-14.4-32-32-32s-32 14.4-32 32zM512.1 153.29999999999995c8.3 0 15.8 3.1 21.5 8.3l2.2 2.2 21.5 21.5L733 361c12.4 12.4 12.4 32.8 0 45.3-12.4 12.4-32.8 12.4-45.3 0L512 230.5 336.2 406.2c-12.4 12.4-32.8 12.4-45.3 0-12.4-12.4-12.4-32.8 0.1-45.2l175.7-175.7 21.8-21.8 1.8-1.8c5.7-5.3 13.4-8.5 21.8-8.4z" horiz-adv-x="1024" />
<glyph glyph-name="delete" unicode="&#59113;" d="M512.019034 896C229.689856 896 0 666.310144 0 383.98096599999997c0-282.306337 229.689856-511.980966 512.019034-511.980966 282.321564 0 512.01142 229.67463 512.01142 511.980966C1024.030454 666.310144 794.340597 896 512.019034 896zM713.257467 174.96921199999997c-0.007613-22.109428-17.92965-40.107599-39.955331-40.107599L352.936215 134.86161200000004c-22.02568 0-39.940104 17.990558-39.940104 40.107599L312.996111 493.911419c0 7.704801 6.265861 13.978275 13.978275 13.978275 7.704801 0 13.970661-6.273474 13.970661-13.978275l0-318.942208c0-6.70744 5.382702-12.158663 11.991167-12.158663l320.365921 0c6.608465 0 11.991167 5.451223 11.991167 12.158663L685.293303 493.911419c0 7.704801 6.265861 13.978275 13.978275 13.978275s13.978275-6.273474 13.978275-13.978275L713.249853 174.96921199999997zM431.956104 216.02087700000004L431.956104 493.911419c0 7.704801 6.265861 13.978275 13.970661 13.978275 7.712414 0 13.978275-6.273474 13.978275-13.978275l0-277.882928c0-7.712414-6.265861-13.978275-13.978275-13.978275C438.229578 202.05021599999998 431.956104 208.31607699999995 431.956104 216.02087700000004zM566.340924 216.02087700000004L566.340924 493.911419c0 7.704801 6.265861 13.978275 13.978275 13.978275 7.704801 0 13.970661-6.273474 13.970661-13.978275l0-277.882928c0-7.712414-6.265861-13.978275-13.970661-13.978275C572.606785 202.05021599999998 566.340924 208.31607699999995 566.340924 216.02087700000004zM762.059614 549.002268L615.554197 549.002268c-3.730585 0-7.240381 1.454167-9.882244 4.09603l-52.08354 52.08354L471.987569 605.181838l-62.17896-52.844884c-2.497208-2.139377-5.717693-3.334687-9.044766-3.334687L261.978453 549.002268c-7.712414 0-13.978275 6.273474-13.978275 13.978275s6.265861 13.978275 13.978275 13.978275l133.653931 0 62.171347 52.844884c2.535275 2.14699 5.748147 3.327073 9.05238 3.327073l92.518517 0c3.730585 0 7.240381-1.454167 9.882244-4.09603l52.08354-52.08354 140.711589 0c7.712414 0 13.978275-6.265861 13.978275-13.970661C776.037889 555.275742 769.764415 549.002268 762.059614 549.002268z" horiz-adv-x="1025" />
<glyph glyph-name="qq" unicode="&#58900;" d="M512-128C229.226667-128 0 101.22666700000002 0 384 0 666.773333 229.226667 896 512 896 794.773333 896 1024 666.773333 1024 384 1024 101.22666700000002 794.773333-128 512-128ZM693.333333 437.333333C689.024 457.365333 682.666667 469.333333 682.666667 469.333333 682.666667 469.333333 682.944 498.666667 650.666667 565.333333 618.389333 632 522.666667 640 522.666667 640L512 640C512 640 416.277333 632 384 565.333333 351.722667 498.666667 352 469.333333 352 469.333333 352 469.333333 345.642667 457.365333 341.333333 437.333333 337.024 417.301333 341.333333 405.333333 341.333333 405.333333 341.333333 405.333333 286.656 349.578667 288 309.33333300000004 289.344 269.08799999999997 299.221333 243.45600000000002 320 266.66666699999996 340.778667 289.877333 341.333333 288 341.333333 288 341.333333 288 340.970667 270.66666699999996 352 256 363.029333 241.33333300000004 373.333333 234.66666699999996 373.333333 234.66666699999996 373.333333 234.66666699999996 317.386667 206.965333 330.666667 170.66666699999996 343.946667 134.36800000000005 384.874667 127.71199999999999 416 128 447.125333 128.288 512 149.33333300000004 512 149.33333300000004L522.666667 149.33333300000004C522.666667 149.33333300000004 587.541333 128.288 618.666667 128 649.792 127.71199999999999 690.72 134.36800000000005 704 170.66666699999996 717.28 206.965333 661.333333 234.66666699999996 661.333333 234.66666699999996 661.333333 234.66666699999996 671.637333 241.33333300000004 682.666667 256 693.696 270.66666699999996 693.333333 288 693.333333 288 693.333333 288 693.888 289.877333 714.666667 266.66666699999996 735.445333 243.45600000000002 745.322667 269.08799999999997 746.666667 309.33333300000004 748.010667 349.578667 693.333333 405.333333 693.333333 405.333333 693.333333 405.333333 697.642667 417.301333 693.333333 437.333333Z" horiz-adv-x="1024" />
<glyph glyph-name="weixin" unicode="&#59018;" d="M512-128C229.2-128 0 101.20000000000005 0 384S229.2 896 512 896s512-229.2 512-512-229.2-512-512-512z m105.6 582.1c-91.1 0-164.9-63.6-164.9-139.3 0-81.5 73.8-145.1 164.9-148.6 25.8 3.5 50.1 8.7 73.3 18.6l45.8-27.9-9.2 46.4c32.6 26.8 54.9 65.4 54.9 111.4 0.1 75.7-73.7 139.4-164.8 139.4z m-54.9-111.4c-17.2 0-27.5 10.4-27.5 27.9 0 8.2 10.3 18.6 27.5 18.6 8.1 0 18.3-10.4 18.3-18.6 0-17.5-10.2-27.9-18.3-27.9z m109.9 0c-8 0-18.3 10.4-18.3 27.9 0 8.2 10.3 18.6 18.3 18.6 17.2 0 27.5-10.4 27.5-18.6 0-17.5-10.2-27.9-27.5-27.9z m-55 130c2.5-3.1 5.9-3.4 9.2 0-13.7 77.2-94 139.3-192.4 139.3C328.6 612 242 537.1 242 444.9c0-53 28.3-99.9 73.3-130l-18.3-65 64.1 37.1c25.5-5.2 49.4-9.5 73.3-9.3 4-0.2 6.8 0 9.2 0-3 12-5 24.4-9.2 37.1 4.2 85.6 84 154.8 183.2 157.9z m-109.9 55.7c17.2 0 27.5-10.4 27.5-18.6 0-17.5-10.3-27.9-27.5-27.9-8 0-18.3 10.4-18.3 27.9 0 8.2 10.2 18.6 18.3 18.6z m-174.1-18.5c0 8.2 10.3 18.6 18.3 18.6 17.2 0 27.5-10.4 27.5-18.6 0-17.5-10.3-27.9-27.5-27.9-8 0-18.3 10.4-18.3 27.9z" horiz-adv-x="1024" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1 @@
<svg t="1604370117041" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9029" width="16" height="16"><path d="M511.979 30.125c-266.13 0-481.871 215.741-481.871 481.871s215.741 481.871 481.871 481.871S993.85 778.126 993.85 511.996 778.109 30.125 511.979 30.125zM459.644 693.015c-15.876 18.135-22.818 22.486-44.972 30.657-34.111 12.787-96.687 36.27-137.374 51.515-7.706 3.056-36.735 1.495-24.578-27.036 13.784-39.757 34.045-98.414 45.636-131.894 8.436-23.615 11.758-29.76 28.73-45.603l175.271-175.271 124.055 124.088C626.413 519.471 508.469 642.264 459.644 693.015zM653.084 492.867 528.996 368.779l26.605-26.605 124.088 124.121L653.084 492.867zM759.469 386.482l-53.176 53.209L582.205 315.569l53.209-53.176c19.596-19.596 51.316-19.596 70.912 0l53.209 53.176C779.065 335.166 779.065 366.919 759.469 386.482z" p-id="9030" fill="#cb221c"></path></svg>

After

Width:  |  Height:  |  Size: 875 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 918 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 659 B

@ -0,0 +1,159 @@
<template>
<div class="box">
<div class="left">
<div class="title">基本信息</div>
<div class="info">
<div class="item">
<p class="key">考试名称</p>
<p class="val">期末考</p>
</div>
<div class="item">
<p class="key">开始时间</p>
<p class="val">2020.10.12</p>
</div>
<div class="item">
<p class="key">总分</p>
<p class="val">100</p>
</div>
<div class="items">
<div class="item">
<p class="key">最高分</p>
<p class="val">期末考</p>
</div>
<div class="item">
<p class="key">应考人数</p>
<p class="val">10</p>
</div>
</div>
<div class="items">
<div class="item">
<p class="key">最低分</p>
<p class="val">期末考</p>
</div>
<div class="item">
<p class="key">实考人数</p>
<p class="val">10</p>
</div>
</div>
<div class="item">
<p class="key">平均分</p>
<p class="val">20</p>
</div>
</div>
</div>
<div class="right">
<div class="title">成绩分布图</div>
<div class="info">
<div class="chart" id="chart"></div>
</div>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground';
import echarts from 'echarts'
export default {
mixins: [ mixins ],
data() {
return {
};
},
mounted() {
this.getData()
this.getChart()
},
methods: {
getData() {
this.$get(`${this.api.getCourse}/${this.id}`)
.then(res => {
let data = res.data.course
this.name = data.name
this.classificationId = data.classificationId
this.description = data.description
this.coverUrl = data.coverUrl
this.uploadList.push({
name: 'cover.jpg',
url: this.coverUrl
})
})
.catch(err => {
});
},
getChart(){
let myChart = echarts.init(document.getElementById('chart'))
myChart.setOption({
title: { text: '成绩分布图' },
tooltip: {},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
areaStyle: {}
}]
});
}
},
};
</script>
<style lang="scss" scoped>
.box{
display: flex;
justify-content: space-between;
width: 90%;
margin: 0 auto;
.title{
padding-left: 5px;
border-left: 5px solid #cb221c;
margin: 20px 0 40px;
line-height: 1;
font-size: 16px;
}
.left,.right{
width: 48%;
box-sizing: border-box;
}
.info{
height: 450px;
padding: 30px 30px;
background-color: #efefef;
box-sizing: border-box;
.item,.items{
display: flex;
align-items: center;
margin: 20px 0;
font-size: 14px;
}
.key{
color: #333;
font-weight: bold;
font-size: 14px;
}
.val{
font-size: #757575;
font-size: 14px;
}
.items{
.item{
margin: 0;
}
.item:first-child{
margin-right: 20px;
}
}
}
.chart{
height: 400px;
}
}
</style>

@ -0,0 +1,264 @@
<template>
<div class="box">
<h1 class="title">期中测评</h1>
<div class="metas">
<div>
<span class="name">学生姓名</span>
<span class="val">张裕</span>
</div>
<div>
<span class="name">学生得分</span>
<span class="val">112</span>
</div>
<div>
<span class="name">试卷总分</span>
<span class="val">212</span>
</div>
<div>
<span class="name">练习时长</span>
<span class="val">60min</span>
</div>
</div>
<div class="wrap">
<div class="select">
<el-radio v-model="look" label="1">查看全部</el-radio>
<el-radio v-model="look" label="2">只看错题</el-radio>
</div>
<div class="item">
<div class="status">简答题待阅</div>
<p class="name">1测试测试测试测试测试测试测试</p>
<div class="answer">
<p class="key">学生答案</p>
<p class="val">测试测试测试测试测试测试测试</p>
</div>
<div class="meta">
<span class="key">知识点</span>
<span class="val">测试测试</span>
</div>
<div class="meta">
<span class="key">答案解析</span>
<span class="val">测试测试</span>
</div>
<div class="meta">
<span class="key">考试得分</span>
<div class="val">
<input type="text">
</div>
</div>
</div>
<div class="item">
<div class="status done">客观题已阅</div>
<p class="name">1测试测试测试测试测试测试测试</p>
<div class="answer">
<p class="key">学生答案</p>
<p class="val">测试测试测试测试测试测试测试</p>
</div>
<div class="meta">
<span class="key">知识点</span>
<span class="val">测试测试</span>
</div>
<div class="meta">
<span class="key">答案解析</span>
<span class="val">测试测试</span>
</div>
<div class="meta">
<span class="key">考试得分</span>
<div class="val">
<input type="text">
</div>
</div>
</div>
</div>
<div class="btns">
<button type="button" class="submit">提交</button>
<button type="button">保存</button>
<button type="button">返回</button>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground';
export default {
mixins: [ mixins ],
data() {
return {
schoolId: this.$store.state.schoolId,
id: '',
look: '1',
page: 1,
pageSize: 10,
total: 0,
isDetail: Boolean(this.$route.query.show),
userId: this.$store.state.userLoginId,
username: this.$store.state.name,
classificationId: '',
coverUrl: '',
name: '',
classificationList: [],
uploadList: [],
description: '',
selectVisible: false
};
},
mounted() {
this.id = this.$route.query.id
this.id && this.getData()
},
methods: {
save() {
if(!this.name) return this.$message.warning('请填写课程名称')
if(!this.classificationId) return this.$message.warning('请选择课程分类')
if(!this.coverUrl) return this.$message.warning('请上传课程封面')
let data = {
id: this.id,
classificationId: this.classificationId,
coverUrl: this.coverUrl,
description: this.description,
name: this.name,
founderId: this.userId,
schoolId: this.schoolId,
founderName: this.username
}
if(this.id){
this.$put(this.api.editCourse, data).then(res => {
this.$message.success('修改成功');
this.$router.back()
})
.catch(err => {
});
}else{
this.$post(this.api.addCourse, data).then(res => {
this.$message.success('创建成功');
this.$router.back()
})
.catch(err => {
});
}
},
getData() {
this.$get(`${this.api.getCourse}/${this.id}`)
.then(res => {
let data = res.data.course
this.name = data.name
this.classificationId = data.classificationId
this.description = data.description
this.coverUrl = data.coverUrl
this.uploadList.push({
name: 'cover.jpg',
url: this.coverUrl
})
})
.catch(err => {
});
},
goback() {
if(this.isDetail){
this.$router.back()
}else{
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', {
type: 'warning'
})
.then(() => {
this.$router.back()
})
.catch(() => {});
}
},
},
};
</script>
<style lang="scss" scoped>
.title{
text-align: center;
font-size: 18px;
font-weight: 600;
}
.metas{
display: flex;
justify-content: space-between;
margin: 20px 0 30px;
.name{
font-size: 12px;
color: #717171;
}
.val{
font-size: 12px;
color: #929292;
}
}
.wrap{
padding: 20px;
background-color: #fbfbfb;
.select{
padding: 10px;
margin-bottom: 20px;
border-bottom: 1px solid #f4f4f4;
}
.item{
padding-bottom: 30px;
margin-bottom: 30px;
border-bottom: 1px dashed #f4f4f4;
.status{
color: #cb221c;
&.done{
color: #56d5bf;
}
}
.name{
margin-top: 15px;
font-size: 14px;
color: #555555;
}
.key{
font-weight: bold;
color: #333;
}
.val{
color: #757575;
}
.answer{
display: flex;
align-items: center;
padding: 15px;
margin: 15px 0;
font-size: 12px;
border: 1px solid #e8e8e8;
background-color: #f3f2f2;
}
.meta{
display: flex;
align-items: center;
padding-left: 10px;
margin: 10px 0;
font-size: 12px;
.key{
width: 70px;
margin-right: 10px;
text-align: right;
}
input{
width: 60px;
height: 28px;
padding: 0 5px;
margin-right: 5px;
background-color: #fff;
border: 1px solid #ebebeb;
box-sizing: border-box;
&:focus{
outline: none;
}
}
}
}
}
</style>

@ -0,0 +1,72 @@
<template>
<div>
<div class="message" @click="showMessage">
<img src="../../assets/img/message.png">
留言板
</div>
<el-dialog title="留言内容" :visible.sync="messageVisible" width="30%" @close="closeMessage" :close-on-click-modal="false" :modal-append-to-body="false" :modal="true">
<div class="message-wrap">
<div class="people">张三提问于2020-12-11</div>
<el-input type="textarea" rows="3"></el-input>
<div class="btn-wrap">
<el-button type="primary" size="small">回复</el-button>
<el-button type="error" size="small">删除</el-button>
</div>
<!-- <quill :border="true" :height="100"></quill> -->
<el-input type="textarea" rows="3"></el-input>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="messageVisible = false" size="small">取消</el-button>
<el-button type="primary" size="small">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import Setting from '@/setting';
import quill from '@/components/quill';
export default {
data() {
return {
messageVisible: false
};
},
components: {quill},
methods: {
closeMessage(){
},
showMessage(){
this.messageVisible = true
}
},
};
</script>
<style lang="scss" scoped>
.message{
display: inline-flex;
align-items: center;
margin-right: 20px;
color: #666;
font-size: 12px;
cursor: pointer;
&:hover{
opacity: .8;
}
img{
margin-right: 5px;
}
}
.message-wrap{
.people{
margin-bottom: 10px;
font-size: 12px;
color: #333;
}
.btn-wrap{
margin: 10px 0;
text-align: right;
}
}
</style>

@ -0,0 +1,173 @@
<template>
<div class="quill" :class="classes">
<div ref="editor" :style="styles" v-loading="loading"></div>
<el-upload :action="this.api.fileupload" :before-upload="beforeUpload" :on-success="editorUploadSuccess" style="display: none">
<el-button class="editorUpload" size="small" type="primary">点击上传</el-button>
</el-upload>
</div>
</template>
<script>
import Quill from 'quill';
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';
import toolbarOptions from './options'
export default {
name: 'quill',
props: {
value: {
type: String,
default: ''
},
readonly: {
type: Boolean,
default: false
},
border: {
type: Boolean,
default: false
},
height: {
type: Number
},
minHeight: {
type: Number
}
},
data () {
return {
Quill: null,
currentValue: '',
options: {
theme: 'snow',
bounds: document.body,
debug: 'warn',
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
'image': function (value) {
if (value) {
// iview
document.querySelector('.editorUpload').click()
} else {
this.Quill.format('image', false);
}
}
}
}
},
placeholder: '',
readOnly: this.readonly
},
loading: false
}
},
computed: {
classes () {
return [
{
'quill-no-border': !this.border
}
];
},
styles () {
let style = {};
if (this.minHeight) {
style.minHeight = `${this.minHeight}px`;
}
if (this.height) {
style.height = `${this.height}px`;
}
return style;
}
},
watch: {
value: {
handler (val) {
if (val !== this.currentValue) {
this.currentValue = val;
if (this.Quill) {
this.Quill.pasteHTML(this.value);
}
}
},
immediate: true
}
},
mounted () {
this.init();
},
beforeDestroy () {
//
this.Quill = null;
},
methods: {
init () {
const editor = this.$refs.editor;
//
this.Quill = new Quill(editor, this.options);
//
this.Quill.pasteHTML(this.currentValue);
this.$nextTick(() => {
window.scrollTo(0,0)
})
//
this.Quill.on('text-change', (delta, oldDelta, source) => {
const html = this.$refs.editor.children[0].innerHTML;
const text = this.Quill.getText();
const quill = this.Quill;
//
this.currentValue = html;
// v-model
this.$emit('input', html);
//
this.$emit('on-change', { html, text, quill });
});
// quill
this.Quill.on('text-change', (delta, oldDelta, source) => {
this.$emit('on-text-change', delta, oldDelta, source);
});
this.Quill.on('selection-change', (range, oldRange, source) => {
this.$emit('on-selection-change', range, oldRange, source);
});
this.Quill.on('editor-change', (eventName, ...args) => {
this.$emit('on-editor-change', eventName, ...args);
});
},
beforeUpload(file){
this.loading = true
},
editorUploadSuccess (res) {
//
let quill = this.Quill
//
if (res.data.filesResult.fileUrl) {
//
let length = quill.getSelection().index;
// res
quill.insertEmbed(length, 'image', res.data.filesResult.fileUrl)
//
quill.setSelection(length + 1)
} else {
this.$message.success('图片插入失败')
}
this.loading = false
},
}
}
</script>
<style lang="scss" scoped>
.quill-no-border{
.ql-toolbar.ql-snow{
border: none;
border-bottom: 1px solid #e8eaec;
}
.ql-container.ql-snow{
border: none;
}
}
</style>

@ -0,0 +1,16 @@
export default [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'size': ['small', false, 'large', 'huge'] }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': [] }],
[{ 'align': [] }],
['clean'],
['link', 'image', 'video']
]

@ -0,0 +1,254 @@
<template>
<div class="box">
<h1 class="title">期中测评</h1>
<div class="metas">
<div style="margin-right: 20px;">
<span class="name">总分</span>
<span class="val">100</span>
</div>
<div>
<span class="name">考试时长</span>
<span class="val">2分钟</span>
</div>
</div>
<ul class="tab">
<li v-for="(item,index) in tabs" :key="index" :class="{active: active == item.id}" @click="tabChange(item.id)">{{item.name}}</li>
</ul>
<div class="wrap">
<div class="item" v-for="(item,index) in curType" :key="index">
<div class="answer">
<div class="info">
<p class="key">序号</p>
<p class="val">{{index+1}}</p>
</div>
<div class="info" v-if="item.point">
<p class="key">得分</p>
<p class="val">{{item.point}}</p>
</div>
</div>
<div class="meta">
<p class="key">题干</p>
<p class="val" v-html="item.questionStem"></p>
</div>
<div class="meta">
<p class="key">选项</p>
<div class="val">
<p v-for="(option,i) in item.options" :key="i">{{i}}.{{option[i]}}</p>
</div>
</div>
<div class="meta ans">
<div class="info">
<p class="key">正确答案</p>
<p class="val">{{item.answer}}</p>
</div>
<div class="info" v-if="item.studentAnswer">
<p class="key">学生答案</p>
<p class="val">{{item.studentAnswer}}</p>
</div>
</div>
<div class="meta">
<p class="key">答案解析</p>
<p class="val" v-html="item.answerAnalysis"></p>
</div>
</div>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground';
export default {
mixins: [ mixins ],
data() {
return {
id: this.$route.query.id,
selectVisible: false,
tabs: [
{
id: 1,
name: '单选题'
},{
id: 2,
name: '多选题'
},{
id: 3,
name: '填空题'
},{
id: 4,
name: '判断题'
},{
id: 5,
name: '简答题'
}
],
active: 1,
curType: []
};
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$post(`${this.api.previewtestPaper}?id=${1}`)
.then(res => {
this.allData = res.data
this.curType = this.allData.list1
this.handleOptions()
})
.catch(err => {
});
},
tabChange(id){
this.active = id
this.curType = this.allData[`list${id}`]
this.handleOptions()
},
handleOptions(){
let curType = this.curType
curType.forEach(n => {
if(!n.options){
let options = {}
for(let i in n){
if(i.includes('option') && n[i]){
console.log(i.replace('option',''))
options[i.replace('option','')] = {
[i.replace('option','')]: n[i]
}
}
}
n.options = options
}
})
this.curType = curType
console.log(22,this.curType)
}
},
};
</script>
<style lang="scss" scoped>
.box{
width: 90%;
margin: 0 auto;
}
.title{
text-align: center;
font-size: 18px;
font-weight: 600;
}
.metas{
display: flex;
justify-content: center;
margin: 20px 0 30px;
.name{
font-size: 12px;
color: #717171;
}
.val{
font-size: 12px;
color: #929292;
}
}
.tab{
display: flex;
align-items: center;
margin-bottom: 10px;
li{
position: relative;
padding: 0 44px;
margin-right: 7px;
font-size: 13px;
line-height: 46px;
text-align: center;
color: #444;
border: 1px solid #ececec;
cursor: pointer;
&:hover{
opacity: .8;
}
&.active:after{
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background-color: #e80909;
}
}
}
.wrap{
.item{
padding-bottom: 30px;
margin-bottom: 30px;
border-bottom: 1px dashed #f4f4f4;
.key{
font-weight: bold;
color: #333;
font-size: 14px;
}
.val{
color: #757575;
font-size: 14px;
}
.answer{
display: flex;
align-items: center;
padding: 15px;
margin: 15px 0;
font-size: 12px;
border: 1px solid #e8e8e8;
background-color: #f3f2f2;
.info{
display: inline-flex;
align-items: center;
margin-right: 30px;
}
}
.meta{
padding-left: 10px;
margin: 20px 0;
font-size: 12px;
&.ans{
display: flex;
align-items: center;
.info{
margin-right: 20px;
}
}
.key{
margin-bottom: 5px;
}
}
}
}
.btns{
display: flex;
justify-content: center;
margin-top: 20px;
button{
height: 30px;
padding: 0 30px;
margin: 0 15px;
font-size: 14px;
color: #333;
line-height: 30px;
background-color: #fff;
border: 1px solid #ededed;
border-radius: 4px;
cursor: pointer;
&.submit{
color: #fff;
background-color: #e80909;
border-color: #e80909;
}
&:hover{
opacity: .8;
}
}
}
</style>

@ -0,0 +1,30 @@
export const messages = {
'zh': {
i18n: {
breadcrumb: '国际化产品',
tips: '通过切换语言按钮,来改变当前内容的语言。',
btn: '切换英文',
title1: '常用用法',
p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。',
p2: '没有什么比信念更能支撑我们度过艰难的时光了。',
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。',
title2: '组件插值',
info: 'Element组件需要国际化,请参考 {action}。',
value: '文档'
}
},
'en': {
i18n: {
breadcrumb: 'International Products',
tips: 'Click on the button to change the current language. ',
btn: 'Switch Chinese',
title1: 'Common usage',
p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.",
p2: "Nothing can help us endure dark times better than our faith. ",
p3: "If you can do what you do best and be happy, you're further along in life than most people.",
title2: 'Component interpolation',
info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.',
value: 'documentation'
}
}
}

@ -0,0 +1,152 @@
<template>
<div class="header flex-between">
<div v-if="showBack" class="goBack" v-throttle @click="back"><i class="el-icon-arrow-left"></i>返回</div>
<div v-else class="logo">
<img src="../../assets/img/logo-fill.png">
</div>
<div class="header-right">
<div class="header-user-con">
<message-board></message-board>
<div class="user" @click="toPerson">
<el-avatar :size="40" :src="circleUrl"></el-avatar>
<span class="user-avator">{{username}}</span>
</div>
<el-divider class="ml20" direction="vertical"></el-divider>
<el-button type="text" class="ml20" @click="loginout">退出</el-button>
</div>
</div>
</div>
</template>
<script>
import bus from '@/libs/bus';
import Setting from '@/setting';
import messageBoard from '@/components/messageBoard';
export default {
data() {
return {
collapse: false,
fullscreen: false,
name: 'huoran',
message: 2,
circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
showBackList: Setting.layout.hideNavList,
messageVisible: false
};
},
components: {messageBoard},
computed: {
username() {
let username = sessionStorage.getItem(Setting.usernameKey);
return username ? username : this.name;
},
showBack(){
let route = this.$route.name
if(this.showBackList.includes(route)) return true
return false
}
},
methods: {
toPerson(){
this.$router.push('/setting/person')
},
loginout() {
sessionStorage.removeItem(Setting.usernameKey);
sessionStorage.removeItem(Setting.storeKey);
location.reload()
},
back(){
this.$router.back()
},
closeMessage(){
},
showMessage(){
this.messageVisible = true
}
},
};
</script>
<style lang="scss" scoped>
.goBack{
cursor: pointer;
line-height: 60px;
height: 60px;
font-size: 16px;
font-weight: bold;
margin-left: 20px;
}
.goBack i{
color: #cb221c;
font-size: 20px;
}
.header {
position: relative;
box-sizing: border-box;
width: 100%;
height: 60px;
font-size: 16px;
color: #333;
border-bottom: 1px solid #efefef;
box-shadow: 0 0 1.5625rem 0.125rem rgba(255, 45, 45, 0.14);
}
.header .logo {
float: left;
width: 170px;
height: 40px;
margin-left: 20px;
}
.header .logo img{
height: 100%;
}
.header-right {
float: right;
padding-right: 50px;
}
.header-user-con {
display: flex;
height: 70px;
align-items: center;
.user{
display: inline-flex;
align-items: center;
cursor: pointer;
}
}
.user-avator {
margin-left: 10px;
}
.ml20{
margin-left: 20px;
}
.user-avator img {
display: block;
width: 40px;
height: 40px;
border-radius: 50%;
}
.header-right .el-button--text{
color: #333;
}
.header-right .el-divider--vertical{
width: 2px;
height: 15px;
}
.header-right .el-divider{
background-color: #333;
}
.message{
display: inline-flex;
align-items: center;
margin-right: 20px;
color: #666;
font-size: 12px;
cursor: pointer;
&:hover{
opacity: .8;
}
img{
margin-right: 5px;
}
}
</style>

@ -0,0 +1,78 @@
<template>
<div class="wrapper">
<div class="placeholder" :class="{mini: !hideNavbar}"></div>
<div class="fixed">
<v-head></v-head>
<v-navbar v-show="hideNavbar"></v-navbar>
</div>
<div class="content-box" :class="{'content-collapse':collapse}">
<!-- <v-tags></v-tags> -->
<div class="content">
<transition name="move" mode="out-in">
<keep-alive :include="tagsList">
<router-view></router-view>
</keep-alive>
</transition>
<el-backtop target=".content"></el-backtop>
</div>
</div>
</div>
</template>
<script>
import vHead from '../header/index.vue';
import vNavbar from '../navbar/index.vue';
import vTags from '../tags/index.vue';
import bus from '@/libs/bus';
import Setting from '@/setting';
export default {
data() {
return {
tagsList: [],
collapse: false,
hideNavList: Setting.layout.hideNavList
};
},
components: {
vHead,
vNavbar,
vTags
},
computed: {
hideNavbar() {
let route = this.$route.name
if(this.hideNavList.includes(route)) return false
return true
}
},
created() {
bus.$on('collapse-content', msg => {
this.collapse = msg;
});
// 使keep-alive
bus.$on('tags', msg => {
let arr = [];
for (let i = 0, len = msg.length; i < len; i++) {
msg[i].name && arr.push(msg[i].name);
}
this.tagsList = arr;
});
}
};
</script>
<style lang="scss" scoped>
.fixed{
z-index: 10;
position: fixed;
top: 0;
width: 100%;
background-color: #fff;
}
.placeholder{
height: 120px;
&.mini{
height: 60px;
}
}
</style>

@ -0,0 +1,136 @@
<template>
<div>
<el-menu
class="sidebar-el-menu"
:default-active="onRoutes"
:collapse="collapse"
background-color="#324157"
text-color="#bfcbd9"
active-text-color="#cb221c"
unique-opened
mode="horizontal"
router
>
<template v-for="item in menus">
<template v-if="item.subs">
<el-submenu :index="item.index" :key="item.index">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs">
<el-submenu
v-if="subItem.subs"
:index="subItem.index"
:key="subItem.index"
>
<template slot="title">{{ subItem.title }}</template>
<el-menu-item
v-for="(threeItem,i) in subItem.subs"
:key="i"
:index="threeItem.index"
>{{ threeItem.title }}</el-menu-item>
</el-submenu>
<el-menu-item
v-else
:index="subItem.index"
:key="subItem.index"
>{{ subItem.title }}</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.index" :key="item.index">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</div>
</template>
<script>
import bus from '@/libs/bus';
import Setting from '@/setting';
export default {
data() {
return {
collapse: false,
defaultMenus: [
{
icon: 'el-icon-monitor',
index: '/index/list',
title: '学生管理'
},
{
icon: 'el-icon-news',
index: '/quesBank/list',
title: '题库管理'
},
{
icon: 'el-icon-user',
index: '/testPaper/list',
title: '试卷管理'
},
{
icon: 'el-icon-user',
index: '/assessment/list',
title: '考核管理'
},
{
icon: 'el-icon-user',
index: '/achievement/list',
title: '成绩管理'
},
{
icon: 'el-icon-takeaway-box',
index: '/system/list',
title: '系统设置'
}
],
menus: []
};
},
computed: {
onRoutes() {
return this.$route.path
}
},
created() {
this.initMenu()
// Event Bus
bus.$on('collapse', msg => {
this.collapse = msg;
bus.$emit('collapse-content', msg);
});
},
methods: {
initMenu(){
if(Setting.dynamicRoute){
let routes = this.$store.state.routes[1].children
let menus = []
this.defaultMenus.map(e => {
routes.find(n => n.path == e.index) && menus.push(e)
})
this.menus = menus
}else{
this.menus = this.defaultMenus
}
}
}
};
</script>
<style lang="scss" scoped>
.sidebar::-webkit-scrollbar {
width: 0;
}
.sidebar-el-menu:not(.el-menu--collapse) {
width: 100%;
}
.sidebar > ul {
height: 100%;
}
</style>

@ -0,0 +1,186 @@
<template>
<div class="tags" v-if="showTags">
<ul>
<li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index">
<router-link :to="item.path" class="tags-li-title">
{{item.title}}
</router-link>
<span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span>
</li>
</ul>
<div class="tags-close-box">
<el-dropdown @command="handleTags">
<el-button size="mini" type="primary">
标签选项<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu size="small" slot="dropdown">
<el-dropdown-item command="other">关闭其他</el-dropdown-item>
<el-dropdown-item command="all">关闭所有</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import bus from '@/libs/bus';
export default {
data() {
return {
tagsList: []
}
},
methods: {
isActive(path) {
return path === this.$route.fullPath;
},
//
closeTags(index) {
const delItem = this.tagsList.splice(index, 1)[0];
const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];
if (item) {
delItem.path === this.$route.fullPath && this.$router.push(item.path);
}else{
this.$router.push('/dashboard');
}
},
//
closeAll(){
this.tagsList = [];
this.$router.push('/dashboard');
},
//
closeOther(){
const curItem = this.tagsList.filter(item => {
return item.path === this.$route.fullPath;
})
this.tagsList = curItem;
},
//
setTags(route){
const isExist = this.tagsList.some(item => {
return item.path === route.fullPath;
})
if(!isExist){
if(this.tagsList.length >= 8){
this.tagsList.shift();
}
this.tagsList.push({
title: route.meta.title,
path: route.fullPath,
name: route.matched[1].components.default.name
})
}
bus.$emit('tags', this.tagsList);
},
handleTags(command){
command === 'other' ? this.closeOther() : this.closeAll();
}
},
computed: {
showTags() {
return this.tagsList.length > 0;
}
},
watch:{
$route(newValue, oldValue){
this.setTags(newValue);
}
},
created(){
this.setTags(this.$route);
//
bus.$on('close_current_tags', () => {
for (let i = 0, len = this.tagsList.length; i < len; i++) {
const item = this.tagsList[i];
if(item.path === this.$route.fullPath){
if(i < len - 1){
this.$router.push(this.tagsList[i+1].path);
}else if(i > 0){
this.$router.push(this.tagsList[i-1].path);
}else{
this.$router.push('/');
}
this.tagsList.splice(i, 1);
break;
}
}
})
}
}
</script>
<style>
.tags {
position: relative;
height: 30px;
overflow: hidden;
background: #fff;
padding-right: 120px;
box-shadow: 0 5px 10px #ddd;
}
.tags ul {
box-sizing: border-box;
width: 100%;
height: 100%;
}
.tags-li {
float: left;
margin: 3px 5px 2px 3px;
border-radius: 3px;
font-size: 12px;
overflow: hidden;
cursor: pointer;
height: 23px;
line-height: 23px;
border: 1px solid #e9eaec;
background: #fff;
padding: 0 5px 0 12px;
vertical-align: middle;
color: #666;
-webkit-transition: all .3s ease-in;
-moz-transition: all .3s ease-in;
transition: all .3s ease-in;
}
.tags-li:not(.active):hover {
background: #f8f8f8;
}
.tags-li.active {
color: #fff;
}
.tags-li-title {
float: left;
max-width: 80px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-right: 5px;
color: #666;
}
.tags-li.active .tags-li-title {
color: #fff;
}
.tags-close-box {
position: absolute;
right: 0;
top: 0;
box-sizing: border-box;
padding-top: 1px;
text-align: center;
width: 110px;
height: 30px;
background: #fff;
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1);
z-index: 10;
}
</style>

@ -0,0 +1,26 @@
/**
* @description 生成按钮级别权限组
* */
import store from '@/store';
export default function(data){
let result = []
data.map(e => {
if(e.select){
e.children.map(n => {
if(n.select){
if(n.children.length){
result.push(`${e.name}:${n.name}`)
n.children.map(j => {
j.select && (e.component ? result.push(`${e.component}:${n.name}:${j.name}`) : result.push(`${n.component}:${j.name}`))
})
}else{
result.push(`${e.component}:${n.name}`)
}
}
})
}
})
store.commit('addBtnPerData',{btnPermissions: result})
// console.log('geneBtn:',result)
}

@ -0,0 +1,6 @@
import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;

@ -0,0 +1,10 @@
// 生成随机字符串
export default function (len = 32) {
const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
const maxPos = $chars.length;
let str = '';
for (let i = 0; i < len; i++) {
str += $chars.charAt(Math.floor(Math.random() * maxPos));
}
return str;
}

@ -0,0 +1,16 @@
// rem等比适配配置文件
// 基准大小
const baseSize = 16
// 设置 rem 函数
function setRem () {
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
const scale = document.documentElement.clientWidth / 1920
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px'
}
// 初始化
setRem()
// 改变窗口大小时重新设置 rem
window.onresize = function () {
setRem()
}

@ -0,0 +1,34 @@
import store from '@/store';
import router from '@/router';
import generateBtnPermission from '../auth/generateBtnPermission';
const newRoutes = []
function createMeta(item){
let meta = { title: item.name }
return meta
}
function createRoute(data){
data.map(e => {
if(e.select && e.component){
let meta = createMeta(e)
newRoutes.push({
name: e.component,
path: e.component,
component: () => import(`@/pages/${e.component}.vue`),
meta
})
}
e.children && e.children.length && createRoute(e.children)
})
}
export default function(data,path){
generateBtnPermission(data)
createRoute(data)
let routes = router.options.routes
routes[1].children = [...routes[1].children,...newRoutes]
store.commit("addRoutesData", { routes })
router.addRoutes(routes)
}

@ -0,0 +1,26 @@
import store from '@/store';
import router from '@/router';
export default function(){
setTimeout(() => {
let routes = store.state.routes
routes.forEach(e => {
if(e.path == '/'){
e.component = () => import('@/layouts/home/index.vue')
}else{
e.component = () => import(`@/pages/${e.path}.vue`)
}
e.children && e.children.forEach(n => {
n.path && (n.component = () => import(`@/pages/${n.path}.vue`))
})
})
routes.push({
path: '*',
redirect: '404'
})
router.addRoutes(routes)
},500)
}

@ -0,0 +1,6 @@
import router from '@/router';
export default function(){
const newRouter = createRouter()
router.matcher = newRouter.matcher
}

@ -0,0 +1,43 @@
import Cookies from 'js-cookie';
import Setting from '@/setting';
const cookies = {};
/**
* @description 存储 cookie
* @param {String} name cookie name
* @param {String} value cookie value
* @param {Object} cookieSetting cookie setting
*/
cookies.set = function (name = 'default', value = '', cookieSetting = {}) {
let currentCookieSetting = {
expires: Setting.cookiesExpires
};
Object.assign(currentCookieSetting, cookieSetting);
Cookies.set(`admin-${name}`, value, currentCookieSetting);
};
/**
* @description 拿到 cookie
* @param {String} name cookie name
*/
cookies.get = function (name = 'default') {
return Cookies.get(`admin-${name}`);
};
/**
* @description 拿到 cookie 全部的值
*/
cookies.getAll = function () {
return Cookies.get();
};
/**
* @description 删除 cookie
* @param {String} name cookie name
*/
cookies.remove = function (name = 'default') {
return Cookies.remove(`admin-${name}`);
};
export default cookies;

@ -0,0 +1,82 @@
/**
* localStorage
* @调用_local.set('access_token', '123456', 5000);
* @调用_local.get('access_token');
*/
var _local = {
//存储,可设置过期时间
set(key, value, expires) {
let params = { key, value, expires };
if (expires) {
// 记录何时将值存入缓存,毫秒级
var data = Object.assign(params, { startTime: new Date().getTime() });
localStorage.setItem(key, JSON.stringify(data));
} else {
if (Object.prototype.toString.call(value) == '[object Object]') {
value = JSON.stringify(value);
}
if (Object.prototype.toString.call(value) == '[object Array]') {
value = JSON.stringify(value);
}
localStorage.setItem(key, value);
}
},
//取出
get(key) {
let item = localStorage.getItem(key);
// 先将拿到的试着进行json转为对象的形式
try {
item = JSON.parse(item);
} catch (error) {
// eslint-disable-next-line no-self-assign
item = item;
}
// 如果有startTime的值,说明设置了失效时间
if (item && item.startTime) {
let date = new Date().getTime();
// 如果大于就是过期了,如果小于或等于就还没过期
if (date - item.startTime > item.expires) {
localStorage.removeItem(name);
return false;
} else {
return item.value;
}
} else {
return item;
}
},
// 删除
remove(key) {
localStorage.removeItem(key);
},
// 清除全部
clear() {
localStorage.clear();
}
}
/**
* sessionStorage
*/
var _session = {
get: function (key) {
var data = sessionStorage[key];
if (!data || data === "null") {
return null;
}
return data;
},
set: function (key, value) {
sessionStorage[key] = value;
},
// 删除
remove(key) {
sessionStorage.removeItem(key);
},
// 清除全部
clear() {
sessionStorage.clear();
}
}
export { _local, _session }

@ -0,0 +1,54 @@
import cookies from './util.cookies';
import {_local,_session} from './util.db';
const util = {
cookies,
local: _local,
session: _session,
// 传入身份证获取生日
getBirth(idCard) {
var birthday = "";
if(idCard != null && idCard != ""){
if(idCard.length == 15){
birthday = "19"+idCard.slice(6,12);
} else if(idCard.length == 18){
birthday = idCard.slice(6,14);
}
birthday = birthday.replace(/(.{4})(.{2})/,"$1-$2-");
//通过正则表达式来指定输出格式为:1990-01-01
}
return birthday;
},
// new Date('2020-11-12 00:00:00') 在IE下失效,因此把-替换成/
dateCompatible(date) {
return date.replace(/\-/g, '/')
},
// 日期时间前面补零
formateTime(num) {
return num < 10 ? `0${num}` : num
},
//返回格式化时间,传参例如:"yyyy-MM-dd hh:mm:ss"
formatDate(fmt,date) {
var date = date ? date : new Date()
var o = {
"M+" : date.getMonth()+1, //月份
"d+" : date.getDate(), //日
"h+" : date.getHours(), //小时
"m+" : date.getMinutes(), //分
"s+" : date.getSeconds(), //秒
"q+" : Math.floor((date.getMonth()+3)/3), //季度
"S" : date.getMilliseconds() //毫秒
};
if(/(y+)/.test(fmt)) {
fmt=fmt.replace(RegExp.$1, (date.getFullYear()+"").substr(4 - RegExp.$1.length));
}
for(var k in o) {
if(new RegExp("("+ k +")").test(fmt)){
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
}
}
return fmt;
},
};
export default util;

@ -0,0 +1,45 @@
import Vue from 'vue';
import App from '@/App.vue';
import router from '@/router';
import ElementUI from 'element-ui';
import mixinApp from '@/mixins/app';
import VueI18n from 'vue-i18n';
import { messages } from '@/i18n';
// import 'element-ui/lib/theme-chalk/index.css'; // 默认主题
import './assets/css/theme-green/index.css'; // 浅绿色主题
import './assets/css/icon.css';
import './assets/icon/iconfont.css';
import 'babel-polyfill';
import '@/libs/resize';
import api from '@/api';
import {post,get,del,put} from '@/plugins/requests/index.js';
import store from '@/store'
import permission from '@/router/permission';
import Setting from '@/setting';
// 插件
import plugins from '@/plugins';
Vue.use(plugins);
Vue.prototype.api = api;
Vue.prototype.$get = get;
Vue.prototype.$post = post;
Vue.prototype.$del = del;
Vue.prototype.$put = put;
Vue.config.productionTip = false;
Vue.use(VueI18n);
Vue.use(ElementUI);
const i18n = new VueI18n({
locale: Setting.i18n.default,
messages
});
new Vue({
mixins: [mixinApp],
router,
store,
i18n,
render: h => h(App)
}).$mount('#app');

@ -0,0 +1,11 @@
/**
* 通用混合
* */
export default {
methods: {
// 当 $route 更新时触发
appRouteChange (to, from) {
}
}
}

@ -0,0 +1,8 @@
export default {
beforeCreate() {
document.querySelector('body').setAttribute('style', 'background-color:#fff')
},
beforeDestroy() {
document.body.removeAttribute('style')
}
}

@ -0,0 +1,252 @@
<template>
<div class="wrap">
<div class="header">
<div class="inner">
<img class="logo" src="../../../assets/img/logo.png" alt="">
</div>
</div>
<div class="main">
<div class="left">
<div class="text">
<p>欢迎进入</p>
<p>电子竞技<br>数字化考试系统</p>
</div>
</div>
<div class="right">
<h2>密码登录</h2>
<el-form :model="loginForm" :rules="loginRules" ref="login" label-width="0px">
<el-form-item prop="username">
<p class="label">用户名</p>
<el-input v-model="loginForm.username" placeholder="请输入账号/手机号" @keyup.enter.native="submitForm()"></el-input>
</el-form-item>
<el-form-item prop="password">
<p class="label">密码</p>
<el-input
type="password"
placeholder="请输入密码"
v-model="loginForm.password"
@keyup.enter.native="submitForm()"
>
</el-input>
</el-form-item>
<el-button class="submit" type="primary" @click="submitForm">登录</el-button>
<!-- <div class="links flex-between">
<el-button type="text" class="ques" @click="toReg">前往注册</el-button>
<el-button type="text" class="forget">忘记密码</el-button>
</div> -->
<!-- <p class="login-tips">其他登陆方式</p>
<div class="thirdParty">
<div class="item">
<img src="../../../assets/img/icon_wechat.png" alt="">
微信扫码登录
</div>
<div class="item">
<img src="../../../assets/img/icon_qq.png" alt="">
QQ一键登录
</div>
</div> -->
</el-form>
</div>
</div>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
data: function() {
return {
loginForm: {
// username: '18818574533',
username: '123456',
password: '123456',
},
loginRules: {
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
},
roleDialog: false,
userId: '',
schoolId: '',
schoolName: '',
roleId: '',
roleList: []
};
},
mounted(){
},
methods: {
...mapActions('user', [
'login'
]),
updateInfo(data){
this.loginForm.username = data.username
this.loginForm.password = data.password
},
submitForm() {
this.$refs.login.validate(valid => {
if (valid) {
let data = {
username: this.loginForm.username,
password: this.loginForm.password
}
this.login(data).then(() => {
this.$router.replace('/index')
})
.catch(() => {
})
}
});
}
},
};
</script>
<style scoped lang="scss">
.header{
display: flex;
justify-content: center;
align-items: center;
background-color: #333;
.inner{
display: inline-flex;
justify-content: space-between;
align-items: center;
width: 65%;
padding: 5px 0;
font-size: 16px;
color: #fff;
.logo{
width: 200px;
}
.reg{
cursor: pointer;
}
}
}
.wrap {
position: relative;
width: 100%;
height: 100%;
background: url(../../../assets/img/login_bg.png) 0 0/100% 100% no-repeat;
overflow: hidden;
.mask{
z-index: -1;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,1);
}
.main{
height: calc(100% - 60px);
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0,0,0,.4);
}
.left{
margin-top: -200px;
margin-right: 10%;
img{
width: 447px;;
margin-bottom: 30px;
}
.text{
font-size: 52px;
color: #fff;
p:first-child{
margin-bottom: 30px;
}
}
}
.right{
width: 580px;
padding: 40px 70px 50px;
background-color: #fff;
box-sizing: border-box;
box-shadow: 0 1px 20px rgba(0,0,0,0.16);
h2{
padding-bottom: 10px;
font-size: 24px;
font-weight: 400;
color: #303d4c;
text-align: center;
border-bottom: 1px solid #E5E5E5;
}
.el-form{
margin-top: 30px;
.label{
margin-bottom: 10px;
color: #105CB2;
}
/deep/.el-input__inner{
height: 46px;
padding: 0 23px;
line-height: 46px;
border: 1px solid #AFB5BB;
border-radius: 23px !important;
}
/deep/.el-form-item__error{
top: 105%;
left: auto;
right: 0;
color: #FFA94E;
}
.submit{
width: 100%;
height: 48px;
margin-top: 60px;
line-height: 48px;
padding: 0;
font-size: 20px;
background-color: #cb221c;
border-radius: 23px;
border: 0;
}
.links{
margin: 20px 0 20px;
}
.ques{
color: #cb221c;
font-size: 14px;
}
.forget{
color: #ffa94e;
font-size: 14px;
}
.login-tips{
margin-bottom: 20px;
font-size: 16px;
color: #105CB2;
text-align: center;
}
.thirdParty{
.item{
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 20px;
padding: 10px 0;
color: #AFB5BB;
font-size: 16px;
background-color: #eff0f1;
border-radius: 36px;
cursor: pointer;
img{
width: 40px;
margin-right: 10px;
}
}
}
}
}
}
</style>

@ -0,0 +1,195 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="publishStatus" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="考试名称">
<el-select v-model="publishStatus" clearable placeholder="请选择考试名称" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名或学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
</el-col>
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>考试成绩</span>
</div>
<div>
<el-button
type="primary"
size="small"
round
@click="toStat"
>成绩统计</el-button>
<el-button
type="primary"
size="small"
round
@click="showBatchUpload"
>导出</el-button>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="得分" align="center"></el-table-column>
<el-table-column prop="name" label="用时(分钟)" align="center"></el-table-column>
<el-table-column prop="name" label="考试时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {
listData: [{}],
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
closeTopics() {
this.isShowTopics = false
this.resetForm()
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
show(row){
this.$router.push('/testPaper/show')
},
toStat(){
this.$router.push('statistics')
}
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
/deep/.el-radio{
margin-right: 15px;
}
::v-deep .el-checkbox-group{
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
</style>

@ -0,0 +1,42 @@
<template>
<div>
<div class="tabs mgb20">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a>
</div>
<practice-results v-if="active == 'practice'"></practice-results>
<exam-results v-else-if="active == 'exam'"></exam-results>
<wrong-book v-else></wrong-book>
</div>
</template>
<script>
import practiceResults from './practiceResults'
import examResults from './examResults'
import wrongBook from './wrongBook'
export default {
data() {
return {
active: 'practice',
tabs: {
practice: '练习成绩',
exam: '考试成绩',
wrong: '错题管理'
}
};
},
components: {
practiceResults,
examResults,
wrongBook,
},
methods: {
tabChange(index){
this.active = index
}
}
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,257 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex-between">
<el-form label-width="80px">
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="publishStatus" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名或学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
</el-col>
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>练习成绩</span>
</div>
<div>
<el-button
type="primary"
size="small"
round
@click="showBatchUpload"
>导出</el-button>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="最高分" align="center"></el-table-column>
<el-table-column prop="name" label="最低分" align="center"></el-table-column>
<el-table-column prop="name" label="平均分" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</el-card>
</el-col>
</el-row>
<el-dialog title="练习成绩详情" :visible.sync="detailVisible" width="40%" @close="closeSelect" :close-on-click-modal="false">
<div class="flex-justify-end">
<div class="mgb20">
<el-input
placeholder="请输入练习项目名称"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
<el-table
:data="projectData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="练习试卷名称" align="center"></el-table-column>
<el-table-column prop="name" label="开始时间" align="center"></el-table-column>
<el-table-column prop="name" label="得分" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showQues(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="detailVisible = false">取消</el-button>
<el-button type="primary" @click="uploadSure">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
keyword: '',
listData: [{}],
subjectList: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '单选题'
},
{
id: 2,
name: '多选题'
},
{
id: 3,
name: '判断题'
}
],
total: 0, // ()
page: 1,
pageSize: 10,
multipleSelection: [],
isShowTopics: false,
topicsTitle: '',
uploadList: [],
uploadDataList: [],
searchTimer: null,
detailVisible: false
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
closeTopics() {
this.isShowTopics = false
this.resetForm()
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
show(row){
this.detailVisible = true
}
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
/deep/.el-radio{
margin-right: 15px;
}
::v-deep .el-checkbox-group{
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
</style>

@ -0,0 +1,182 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="错题来源">
<el-select v-model="publishStatus" clearable placeholder="请选择错题来源" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="试卷名称">
<el-select v-model="publishStatus" clearable placeholder="请选择试卷名称" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名或学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
</el-col>
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>错题管理</span>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="错题来源" align="center"></el-table-column>
<el-table-column prop="name" label="试卷名称" align="center"></el-table-column>
<el-table-column prop="name" label="所需知识点" align="center"></el-table-column>
<el-table-column prop="name" label="教学班级" align="center"></el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="错题数" align="center"></el-table-column>
<el-table-column prop="name" label="重做正确率" align="center"></el-table-column>
<el-table-column prop="name" label="知识点掌握程度" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看详情</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
data() {
return {
listData: [{}],
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
closeTopics() {
this.isShowTopics = false
this.resetForm()
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
show(row){
this.$router.push('/testPaper/show')
},
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
/deep/.el-radio{
margin-right: 15px;
}
::v-deep .el-checkbox-group{
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
</style>

@ -0,0 +1,264 @@
<template>
<div>
<el-form :disabled="isDetail">
<el-card shadow="hover" class="mgb20">
<div class="flex-between">
<div class="per_title" v-throttle @click="goback()">
<i class="el-icon-arrow-left"></i>
<span class="per_back">返回</span>
<span class="per_school">{{isDetail ? '查看' : (id ? '更新' : '创建')}}考核</span>
</div>
<div>
<el-button type="primary" size="small" round v-throttle @click="save" v-show="!isDetail">{{id ? '更新' : '创建'}}</el-button>
</div>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div>
<p class="mgb20">考核名称</p>
<el-input
placeholder="请输入考核名称"
v-model="assessmentName"
clearable
maxlength="25"
class="inline_input"
></el-input>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div>
<p class="mgb20">考核类型</p>
<div class="inline_input">
<el-select v-model="classificationId" placeholder="请选择考核类型">
<el-option
v-for="item in classificationList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</div>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div>
<p class="mgb20">考核时间</p>
<el-date-picker
size="small"
v-model="date"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
></el-date-picker>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div>
<p class="mgb20">试卷选择</p>
<div class="inline_input">
<el-button type="primary" @click="openSelect">试卷选择</el-button>
</div>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div>
<p class="mgb20">发布班级</p>
<div class="inline_input">
<div class="per-wrap">
<el-tree
ref="per"
:data="permissions"
show-checkbox
node-key="id"
:default-expanded-keys="checkedIds"
:default-checked-keys="checkedIds"
:props="defaultProps">
</el-tree>
</div>
</div>
</div>
</el-card>
</el-form>
<el-dialog title="试卷选择" :visible.sync="selectVisible" width="40%" @close="closeSelect" :close-on-click-modal="false">
<div class="flex-justify-end">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="所属考核">
<el-select v-model="publishStatus" clearable placeholder="请选择所属考核" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb">
<el-input
placeholder="请输入试卷名称"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</el-form-item>
</el-form>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column width="60" label="选择" align="center">
<template slot-scope="scope">
<el-radio v-model="projectId" :label="scope.row.projectId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="试卷名称" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showQues(scope.row)">预览</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="importVisible = false">取消</el-button>
<el-button type="primary" @click="uploadSure">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
id: '',
assessmentName: '',
classId: '',
date: [],
startTime: '',
endTime: '',
state: '',
testPaperId: '',
type: '',
page: 1,
pageSize: 10,
total: 0,
isDetail: Boolean(this.$route.query.show),
selectVisible: false
};
},
computed: {
...mapState('user', [
'userId','clientId'
])
},
watch: {
date: function(val){
if(val){
this.startTime = val[0]
this.endTime = val[1]
}else{
this.startTime = ''
this.endTime = ''
}
this.getData()
}
},
mounted() {
this.id = this.$route.query.id
this.id && this.getData()
},
methods: {
save() {
if(this.assessmentName === '') return this.$message.warning('请填写考核名称')
if(this.type === '') return this.$message.warning('请选择考核类型')
if(this.startTime === '') return this.$message.warning('请选择考核时间')
if(this.testPaperId === '') return this.$message.warning('请选择试卷')
let data = {
id: this.id,
userId: this.userId,
assessmentName: this.assessmentName,
type: this.type,
startTime: this.startTime,
endTime: this.endTime,
}
if(this.id){
this.$put(this.api.editCourse, data).then(res => {
this.$message.success('修改成功');
this.$router.back()
})
.catch(err => {
});
}else{
this.$post(this.api.addCourse, data).then(res => {
this.$message.success('创建成功');
this.$router.back()
})
.catch(err => {
});
}
},
getData() {
this.$get(`${this.api.getCourse}/${this.id}`)
.then(res => {
})
.catch(err => {
});
},
goback() {
if(this.isDetail){
this.$router.back()
}else{
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', {
type: 'warning'
})
.then(() => {
this.$router.back()
})
.catch(() => {});
}
},
openSelect(){
this.selectVisible = true
}
},
};
</script>
<style lang="scss" scoped>
.inline_input {
width: 300px;
}
.per-wrap{
max-height: 400px;
overflow: auto;
}
</style>

@ -0,0 +1,311 @@
<template>
<div>
<el-card shadow="hover" class="mgb20">
<div>
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex-between no-mb">
<div>
<el-form label-width="80px" inline>
<el-form-item label="考核类型" class="no-mb">
<el-select v-model="type" clearable placeholder="请选择考核类型" @change="getData">
<el-option v-for="(item,index) in typeList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="考试状态" class="no-mb">
<el-select v-model="state" clearable placeholder="请选择考试状态" @change="getData">
<el-option v-for="(item,index) in stateList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div>
<el-input placeholder="请输入考核名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div>
</div>
</div>
</div>
</el-card>
<el-card shadow="hover">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>考核列表</span>
</div>
<div>
<el-button type="primary" size="small" round @click="addAss" v-auth>创建考核</el-button>
</div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" row-key="id">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="assessmentName" label="考核名称" align="center"></el-table-column>
<el-table-column prop="name" label="考核类型" align="center"></el-table-column>
<el-table-column prop="startTime" label="考试开始时间" align="center"></el-table-column>
<el-table-column prop="endTime" label="考试结束时间" align="center"></el-table-column>
<el-table-column prop="name" label="考核状态" align="center"></el-table-column>
<el-table-column prop="name" label="考试班级" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)" v-auth>查看</el-button>
<el-button type="text" @click="edit(scope.row)" v-auth>修改</el-button>
<el-button type="text" @click="monitor(scope.row)" v-auth>监控</el-button>
<el-button type="text" @click="review(scope.row)" v-auth>批阅</el-button>
<el-button type="text" @click="finish(scope.row)" v-auth>结束考试</el-button>
<el-button type="text" @click="scoreQuery(scope.row)" v-auth>成绩查询</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="handleCurrentChange" :current-page="page" layout="total, prev, pager, next" :total="total">
</el-pagination>
</div>
</el-card>
<el-dialog title="创建考核" :visible.sync="addVisible" width="50%" @close="closeAdd" :close-on-click-modal="false">
<el-form ref="form" label-width="100px">
<el-form-item prop="account" label="考核名称">
<el-input v-model="account" placeholder="请输入考核名称"></el-input>
</el-form-item>
<el-form-item prop="userName" label="考核类型">
<el-select v-model="classificationId" placeholder="请选择考核类型">
<el-option
v-for="item in classificationList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item prop="account" label="考核时间">
<el-date-picker
size="small"
v-model="time"
value-format="yyyy-MM-dd HH:mm:ss"
type="datetimerange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
:picker-options="pickerOptions"
></el-date-picker>
</el-form-item>
<el-form-item prop="account" label="试卷选择">
<el-button type="primary" @click="openSelect">试卷选择</el-button>
</el-form-item>
<el-form-item prop="account" label="发布班级">
<el-tree
ref="per"
:data="permissions"
show-checkbox
node-key="id"
:default-expanded-keys="checkedIds"
:default-checked-keys="checkedIds"
:props="defaultProps">
</el-tree>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="addVisible = false">取消</el-button>
<el-button type="primary" @click="uploadSure">确定</el-button>
</span>
</el-dialog>
<el-dialog title="试卷选择" :visible.sync="selectVisible" width="40%" @close="closeSelect" :close-on-click-modal="false">
<div class="flex-justify-end">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="所属课程">
<el-select v-model="publishStatus" clearable placeholder="请选择所属课程" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb">
<el-input
placeholder="请输入试卷名称"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</el-form-item>
</el-form>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column width="60" label="选择" align="center">
<template slot-scope="scope">
<el-radio v-model="projectId" :label="scope.row.projectId">&nbsp;</el-radio>
</template>
</el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="试卷名称" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="showQues(scope.row)">预览</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="selectVisible = false">取消</el-button>
<el-button type="primary" @click="uploadSure">确定</el-button>
</span>
</el-dialog>
<el-dialog title="详情" :visible.sync="detailVisible" width="40%" @close="closeDetail" :close-on-click-modal="false">
<div class="details">
<div class="line">
<span class="key">考核内容</span>
<p class="val">测试</p>
</div>
<div class="line">
<span class="key">考核题数</span>
<p class="val">12000</p>
</div>
<div class="line">
<span class="key">考核人数</span>
<p class="val">211</p>
</div>
<div class="line">
<span class="key">考核总分</span>
<p class="val">100</p>
</div>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
listData: [],
keyword: '',
type: '',
typeList: [],
state: '',
stateList: [],
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
addVisible: false,
selectVisible: false,
detailVisible: false
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
this.$get(this.api.queryAssessment, {
page: this.page,
size: this.pageSize,
type: this.type,
state: this.state,
assessmentName: this.keyword
})
.then(res => {
this.listData = res.data.Assessment
this.total = res.data.total
})
.catch(err => {})
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
edit(row){
this.$router.push('add')
},
monitor(row){
this.$router.push('monitor')
},
finish(row){
},
scoreQuery(){
this.$router.push('scoreQuery')
},
review(row){
this.$router.push('review')
},
addAss(){
this.addVisible = true
},
closeAdd(){
},
openSelect(){
this.selectVisible = true
},
closeSelect(){
},
show(row){
this.detailVisible = true
},
closeDetail(){
},
}
}
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
.details{
.line{
display: flex;
align-items: center;
margin: 10px 0;
&:first-child{
margin-top: 0;
}
.key{
font-weight: bold;
color: #333;
font-size: 14px;
}
.val{
color: #757575;
font-size: 14px;
}
}
}
</style>

@ -0,0 +1,204 @@
<template>
<div class="box">
<div class="left">
<div class="title">考试信息</div>
<div class="info">
<div class="item">
<p class="key">试卷名称</p>
<p class="val">测试</p>
</div>
<div class="item">
<p class="key">试卷总分</p>
<p class="val">发布考试的名称</p>
</div>
<div class="item">
<p class="key">剩余时间</p>
<p class="val">发布考试的名称</p>
</div>
<div class="item">
<p class="key">应考人数</p>
<p class="val">发布考试的名称</p>
</div>
<div class="item">
<p class="key">在考人数</p>
<p class="val">发布考试的名称</p>
</div>
<div class="item">
<p class="key">已考人数</p>
<p class="val">发布考试的名称</p>
</div>
<div class="item">
<p class="key">未考人数</p>
<p class="val">发布考试的名称</p>
</div>
</div>
</div>
<div class="right">
<div class="filter">
<div class="item">
<p class="key">考试状态</p>
<el-select v-model="purpose" placeholder="请选择考试状态" size="small">
<el-option v-for="(item,index) in purposeList" :key="index" :label="item.label" :value="item.id"></el-option>
</el-select>
</div>
<div class="item">
<p class="key">试卷用途</p>
<el-input placeholder="请输入学生姓名/学号" prefix-icon="el-icon-search" v-model="keyword" clearable size="small"></el-input>
</div>
</div>
<div class="table">
<div class="flex-justify-end">
<el-button type="primary" size="small" round>强制收卷</el-button>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="所属班级" align="center"></el-table-column>
<el-table-column prop="name" label="考试状态" align="center"></el-table-column>
<el-table-column prop="name" label="开始时间" align="center"></el-table-column>
<el-table-column prop="name" label="提交时间" align="center"></el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</div>
</div>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground';
export default {
mixins: [ mixins ],
data() {
return {
keyword: '',
listData: [],
page: 1,
pageSize: 10,
total: 0
};
},
mounted() {
this.getData()
},
methods: {
getData() {
this.$get(`${this.api.getCourse}/${this.id}`)
.then(res => {
})
.catch(err => {
});
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
},
};
</script>
<style lang="scss" scoped>
.box{
display: flex;
width: 90%;
margin: 0 auto;
border: 1px solid #e8e8e8;
.left{
width: 25%;
padding: 30px;
border-right: 1px solid #e8e8e8;
box-sizing: border-box;
.title{
font-size: 14px;
color: #444;
}
.info{
.item{
display: flex;
align-items: center;
margin: 10px 0;
.key{
color: #555;
font-size: 14px;
}
.val{
flex: 1;
margin-left: 20px;
color: #333;
text-align: center;
line-height: 36px;
font-size: 14px;
background-color: #f4f4f4;
border: 1px solid #e8e8e8;
box-sizing: border-box;
}
}
}
}
.right{
width: 70%;
padding: 20px;
box-sizing: border-box;
.filter{
display: flex;
justify-content: flex-end;
padding: 10px;
background-color: #efefef;
.item{
display: inline-flex;
align-items: center;
margin-left: 20px;
/deep/.el-select{
flex: 1;
}
.key{
margin-right: 20px;
white-space: nowrap;
font-size: 14px;
color: #555;
}
&.lg .key{
width: 220px;
margin-right: 10px;
text-align: right;
}
}
}
.table{
padding: 10px;
margin-top: 10px;
background-color: #efefef;
}
}
}
</style>

@ -0,0 +1,138 @@
<template>
<div>
<el-card shadow="hover" class="mgb20">
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="批阅状态">
<el-select v-model="publishStatus" clearable placeholder="请选择授课专业" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入真实姓名/学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>考试批阅</span>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="交卷时间" align="center"></el-table-column>
<el-table-column prop="name" label="答题用时(分钟)" align="center"></el-table-column>
<el-table-column prop="name" label="考试状态" align="center"></el-table-column>
<el-table-column prop="name" label="批阅状态" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看</el-button>
<el-button type="text" @click="review(scope.row)">批阅</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
listData: [{}],
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
show(row){
this.$router.push('/testPaper/doReview')
},
review(row){
this.$router.push('/testPaper/doReview')
}
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
</style>

@ -0,0 +1,141 @@
<template>
<div>
<el-card shadow="hover" class="mgb20">
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div class="flex-between">
<el-form label-width="80px" inline>
<el-form-item class="no-mb" label="教学班级">
<el-select v-model="publishStatus" clearable placeholder="请选择教学班级" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="考试名称">
<el-select v-model="publishStatus" clearable placeholder="请选择考试名称" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入学生姓名/学号"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>成绩查询</span>
</div>
<div>
<el-button type="primary" size="small" round @click="stat">成绩统计</el-button>
<el-button type="primary" size="small" round>导出</el-button>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="真实姓名" align="center"></el-table-column>
<el-table-column prop="name" label="学号" align="center"></el-table-column>
<el-table-column prop="name" label="得分" align="center"></el-table-column>
<el-table-column prop="name" label="用时(分钟)" align="center"></el-table-column>
<el-table-column prop="name" label="考试时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<el-button type="text" @click="show(scope.row)">查看</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
</el-card>
</div>
</template>
<script>
export default {
data() {
return {
listData: [{}],
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.total = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
stat(row){
this.$router.push('/achievement/statistics')
}
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
</style>

@ -0,0 +1,56 @@
<template>
<div class="error-page">
<div class="error-code">4<span>0</span>3</div>
<div class="error-desc">啊哦~ 你没有权限访问该页面哦</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button>
</div>
</div>
</template>
<script>
export default {
methods: {
goBack(){
this.$router.go(-1);
}
}
}
</script>
<style scoped>
.error-page{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code{
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #f02d2d;
}
.error-code span{
color: #00a854;
}
.error-desc{
font-size: 30px;
color: #777;
}
.error-handle{
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn{
margin-left: 100px;
}
</style>

@ -0,0 +1,56 @@
<template>
<div class="error-page">
<div class="error-code">4<span>0</span>4</div>
<div class="error-desc">啊哦~ 你所访问的页面不存在</div>
<div class="error-handle">
<router-link to="/">
<el-button type="primary" size="large">返回首页</el-button>
</router-link>
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button>
</div>
</div>
</template>
<script>
export default {
methods: {
goBack(){
this.$router.go(-1);
}
}
}
</script>
<style scoped>
.error-page{
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
width: 100%;
height: 100%;
background: #f3f3f3;
box-sizing: border-box;
}
.error-code{
line-height: 1;
font-size: 250px;
font-weight: bolder;
color: #2d8cf0;
}
.error-code span{
color: #00a854;
}
.error-desc{
font-size: 30px;
color: #777;
}
.error-handle{
margin-top: 30px;
padding-bottom: 200px;
}
.error-btn{
margin-left: 100px;
}
</style>

@ -0,0 +1,46 @@
<template>
<section class="main">
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item><i class="el-icon-lx-global"></i> {{$t('i18n.breadcrumb')}}</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<span>{{$t('i18n.tips')}}</span>
<el-button type="primary" @click="$i18n.locale = $i18n.locale === 'zh'?'en':'zh';">{{$t('i18n.btn')}}</el-button>
<div class="list">
<h2>{{$t('i18n.title1')}}</h2>
<p>{{$t('i18n.p1')}}</p>
<p>{{$t('i18n.p2')}}</p>
<p>{{$t('i18n.p3')}}</p>
</div>
<h2>{{$t('i18n.title2')}}</h2>
<div>
<i18n path="i18n.info" tag="p">
<a place="action" href="https://element.eleme.cn/2.0/#/zh-CN/component/i18n">{{ $t('i18n.value') }}</a>
</i18n>
</div>
</div>
</section>
</template>
<script>
export default {
data(){
return {
}
}
}
</script>
<style scoped>
.list{
padding: 30px 0;
}
.list p{
margin-bottom: 20px;
}
a{
color: #cb221c;
}
</style>

@ -0,0 +1,225 @@
<template>
<div>
<div class="crumbs">
<el-breadcrumb separator="/">
<el-breadcrumb-item><i class="el-icon-lx-emoji"></i> 自定义图标</el-breadcrumb-item>
</el-breadcrumb>
</div>
<div class="container">
<h2>使用方法</h2>
<p style="line-height: 50px;">
直接通过设置类名为 el-icon-lx-iconName 来使用即可例如{{iconList.length}}个图标
</p>
<p class="example-p">
<i class="el-icon-lx-redpacket_fill" style="font-size: 30px;color: #ff5900"></i>
<span>&lt;i class=&quot;el-icon-lx-redpacket_fill&quot;&gt;&lt;/i&gt;</span>
</p>
<p class="example-p">
<i class="el-icon-lx-weibo" style="font-size: 30px;color:#fd5656"></i>
<span>&lt;i class=&quot;el-icon-lx-weibo&quot;&gt;&lt;/i&gt;</span>
</p>
<p class="example-p">
<i class="el-icon-lx-emojifill" style="font-size: 30px;color: #ffc300"></i>
<span>&lt;i class=&quot;el-icon-lx-emojifill&quot;&gt;&lt;/i&gt;</span>
</p>
<br>
<h2>图标</h2>
<div class="search-box">
<el-input class="search" size="large" v-model="keyword" clearable placeholder="请输入图标名称"></el-input>
</div>
<ul>
<li class="icon-li" v-for="(item,index) in list" :key="index">
<div class="icon-li-content">
<i :class="`el-icon-lx-${item}`"></i>
<span>{{item}}</span>
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
data: function(){
return {
keyword: '',
iconList: [
'attentionforbid',
'attentionforbidfill',
'attention',
'attentionfill',
'tag',
'tagfill',
'people',
'peoplefill',
'notice',
'noticefill',
'mobile',
'mobilefill',
'voice',
'voicefill',
'unlock',
'lock',
'home',
'homefill',
'delete',
'deletefill',
'notification',
'notificationfill',
'notificationforbidfill',
'like',
'likefill',
'comment',
'commentfill',
'camera',
'camerafill',
'warn',
'warnfill',
'time',
'timefill',
'location',
'locationfill',
'favor',
'favorfill',
'skin',
'skinfill',
'news',
'newsfill',
'record',
'recordfill',
'emoji',
'emojifill',
'message',
'messagefill',
'goods',
'goodsfill',
'crown',
'crownfill',
'move',
'add',
'hot',
'hotfill',
'service',
'servicefill',
'present',
'presentfill',
'pic',
'picfill',
'rank',
'rankfill',
'male',
'female',
'down',
'top',
'recharge',
'rechargefill',
'forward',
'forwardfill',
'info',
'infofill',
'redpacket',
'redpacket_fill',
'roundadd',
'roundaddfill',
'friendadd',
'friendaddfill',
'cart',
'cartfill',
'more',
'moreandroid',
'back',
'right',
'shop',
'shopfill',
'question',
'questionfill',
'roundclose',
'roundclosefill',
'roundcheck',
'roundcheckfill',
'global',
'mail',
'punch',
'exit',
'upload',
'read',
'file',
'link',
'full',
'group',
'friend',
'profile',
'addressbook',
'calendar',
'text',
'copy',
'share',
'wifi',
'vipcard',
'weibo',
'remind',
'refresh',
'filter',
'settings',
'scan',
'qrcode',
'cascades',
'apps',
'sort',
'searchlist',
'search',
'edit'
]
}
},
computed: {
list(){
return this.iconList.filter((item) => {
return item.indexOf(this.keyword) !== -1;
})
}
}
}
</script>
<style scoped>
.example-p{
height: 45px;
display: flex;
align-items: center;
}
.search-box{
text-align: center;
margin-top: 10px;
}
.search{
width: 300px;
}
ul,li{
list-style: none;
}
.icon-li{
display: inline-block;
padding: 10px;
width: 120px;
height: 120px;
}
.icon-li-content{
display: flex;
height: 100%;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
}
.icon-li-content i{
font-size: 36px;
color: #606266;
}
.icon-li-content span{
margin-top: 10px;
color: #787878;
}
</style>

@ -0,0 +1,156 @@
<template>
<div>
<el-card shadow="hover" class="mgb20">
<div>
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="flex-between no-mb">
<div>
<el-form label-width="80px" inline>
<el-form-item label="创建人">
<el-select v-model="publishStatus" clearable placeholder="请选择创建人" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="试题类型">
<el-select v-model="publishStatus" clearable placeholder="请选择试题类型" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<div>
<el-input placeholder="请输入题库名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div>
</div>
</div>
</div>
</el-card>
<el-card shadow="hover">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>分类管理</span>
</div>
<div>
<el-button type="primary" size="small" round @click="delAllSelection" v-auth>批量删除</el-button>
</div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" row-key="id">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="题干" align="center"></el-table-column>
<el-table-column prop="name" label="试题类型" align="center"></el-table-column>
<el-table-column prop="name" label="对应课程" align="center"></el-table-column>
<el-table-column prop="name" label="所属题库" align="center"></el-table-column>
<el-table-column prop="name" label="知识点" align="center"></el-table-column>
<el-table-column prop="name" label="使用次数" align="center"></el-table-column>
<el-table-column prop="name" label="共享时间" align="center"></el-table-column>
<el-table-column prop="name" label="创建人" align="center"></el-table-column>
<el-table-column label="操作" align="center" width="300">
<template slot-scope="scope">
<el-button type="text" @click="editFirst(scope.row)" v-auth>修改</el-button>
<el-button type="text" @click="handleDelete(scope.row)" v-auth>删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="handleCurrentChange" :current-page="page" layout="total, prev, pager, next" :total="total">
</el-pagination>
</div>
</el-card>
<el-dialog :title="firstId ? '编辑一级分类' : '添加一级分类'" :visible.sync="firstVisible" width="24%" center :close-on-click-modal="false">
<el-form>
<el-form-item>
<el-input placeholder="请输入题库分类名称" v-model="firstName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="firstVisible = false">取消</el-button>
<el-button type="primary" @click="firstSubmit">确定</el-button>
</span>
</el-dialog>
<el-dialog :title="secondId ? '编辑二级分类' : '添加二级分类'" :visible.sync="secondVisible" width="24%" center :close-on-click-modal="false">
<el-form>
<el-form-item>
<el-input placeholder="请输入题库分类名称" v-model="secondName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="secondVisible = false">取消</el-button>
<el-button type="primary" @click="secondSubmit">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
listData: [],
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
firstVisible: false,
firstId: '',
firstName: '',
secondVisible: false,
secondName: '',
secondId: ''
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.dataTotal = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.orderData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
handleDelete(row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$del(`${this.api.deleteColumn}/${row.id}`).then(res => {
this.$message.success('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
},
}
}
</script>

@ -0,0 +1,41 @@
<template>
<div>
<div class="tabs mgb20">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a>
</div>
<my-ques-bank v-if="active == 'my'"></my-ques-bank>
<global-ques-bank v-else></global-ques-bank>
</div>
</template>
<script>
import myQuesBank from './myQuesBank'
import globalQuesBank from './globalQuesBank'
export default {
data() {
return {
active: 'my',
tabs: {
my: '我上传的题库',
global: '公共题库'
}
};
},
components: {
myQuesBank,
globalQuesBank,
},
mounted() {
},
methods: {
tabChange(index){
this.active = index
}
}
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,550 @@
<template>
<div>
<el-row :gutter="20">
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>测评题库</span>
</div>
<div class="flex-between">
<el-form label-width="80px">
<el-form-item class="no-mb" label="试题类型">
<el-select v-model="publishStatus" clearable placeholder="请选择试题类型" @change="getData">
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
placeholder="请输入题干"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</el-card>
</el-col>
<el-col :span="24">
<el-card shadow="hover" class="mgb20">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>题目列表</span>
</div>
<div>
<el-button
type="primary"
size="small"
round
@click="addTopics"
>单题上传</el-button>
<el-button
type="primary"
size="small"
round
@click="showBatchUpload"
>批量上传</el-button>
<el-button
type="primary"
size="small"
round
@click="showBatchUpload"
>共享</el-button>
<el-button
type="primary"
size="small"
round
@click="showBatchUpload"
>取消共享</el-button>
<el-button
type="primary"
size="small"
round
@click="delAllData"
>批量删除</el-button>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55"
align="center"
:reserve-selection="true"
></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="name" label="题干" align="center"></el-table-column>
<el-table-column prop="name" label="试题类型" align="center"></el-table-column>
<el-table-column prop="name" label="对应课程" align="center"></el-table-column>
<el-table-column prop="name" label="所属题库" align="center"></el-table-column>
<el-table-column prop="name" label="知识点" align="center"></el-table-column>
<el-table-column prop="name" label="使用次数" align="center"></el-table-column>
<el-table-column prop="name" label="上传时间" align="center"></el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<template v-if="scope.row.isEnable">
<el-button type="text" @click="showQues(scope.row)">查看</el-button>
</template>
<template v-else>
<el-button type="text" @click="editQues(scope.row)">修改</el-button>
</template>
<el-switch
v-model="scope.row.isEnable"
:active-text="scope.row.isEnable ? '关闭' : '启用'"
:active-value="1"
:inactive-value="0"
style="margin: 0 10px 0 5px"
@change="switchQues($event,scope.row,scope.$index)"
></el-switch>
<el-button type="text" @click="delData(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="dataTotal"
></el-pagination>
</div>
</el-card>
</el-col>
</el-row>
<el-dialog :title="topicsTitle" :visible.sync="NewTopics" width="30%" @close="closeTopics" :close-on-click-modal="false">
<ques-dialog></ques-dialog>
<div slot="footer" class="dialog-footer" v-show="!isShowTopics">
<el-button v-throttle @click="NewTopics = false">取消</el-button>
<el-button type="primary" @click="saveTopics" v-throttle>确定</el-button>
</div>
</el-dialog>
<el-dialog title="批量上传" :visible.sync="BatchUpload" width="30%" @close="closeUpload" :close-on-click-modal="false">
<el-card shadow="hover" class="card_m" v-show="this.label=1">
<div class="Upload">
<div class="bt" @click="downloadTem">
<el-link :underline="false">
1.请下载模板
<i class="el-icon-download"></i>
</el-link>
</div>
<div class="bt">
<el-upload
accept=".xls,.xlsx"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.upload"
:file-list="uploadList"
name="file"
>
<el-link :underline="false">
2.请点击上传模板
<i class="el-icon-upload"></i>
</el-link>
</el-upload>
</div>
<div>
<el-upload
accept=".xls,.xlsx"
:on-remove="handleDataRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.import"
:file-list="uploadDataList"
name="file"
>
<el-link :underline="false">
3.请点击批量导入
<i class="el-icon-upload"></i>
</el-link>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">导入失败查看原因</el-link>
</div>
</div>
</el-card>
<span slot="footer" class="dialog-footer">
<el-button @click="BatchUpload = false">取消</el-button>
<el-button type="primary" v-throttle @click="uploadSure">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import quesDialog from './quesDialog';
export default {
data() {
return {
topicForm: {
answer: '',
questionType : '单选题',
questionStem : '',
optionA:'',
optionB:'',
optionC:'',
optionD:'',
optionE:'',
optionF:'',
aisTrue: false,
bisTrue: false,
cisTrue: false,
disTrue: false,
eisTrue: false,
fisTrue: false,
answerAnalysis: ''
},
rules: {
questionType: [{ required: true, message: '请选择题型', trigger: 'change' }],
questionStem: [{ required: true, message: '请填写题干', trigger: 'blur' }],
// optionA: [{ required: true, message: '', trigger: 'change' }],
// optionB: [{ required: true, message: '', trigger: 'change' }]
},
value: true,
subject: '', //
keyword: '',
listData: [],
subjectList: [
{
id: '',
name: '不限'
},
{
id: 1,
name: '单选题'
},
{
id: 2,
name: '多选题'
},
{
id: 3,
name: '判断题'
}
],
dataTotal: 0, // ()
page: 1,
pageSize: 10,
currentPage: 1,
SetEvaluation: false,
radio: '1', //
topicsNumber: '', //
topicsTime: '', //
random: true,
custom: false,
info: {},
NewTopics: false, //
BatchUpload: false, //
questionType: ['','单选题','多选题','判断题'],
multipleSelection: [],
isShowTopics: false,
topicsTitle: '',
uploadList: [],
uploadDataList: [],
searchTimer: null,
uploadFaild: false,
token: '',
};
},
mounted() {
this.getData()
},
components: {quesDialog},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.dataTotal = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.listData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
resetForm() {
this.topicForm = {
answer: '',
questionType : '',
questionStem : '',
optionA:'',
optionB:'',
optionC:'',
optionD:'',
optionE:'',
optionF:'',
aisTrue: false,
bisTrue: false,
cisTrue: false,
disTrue: false,
eisTrue: false,
fisTrue: false,
answerAnalysis: ''
}
this.$nextTick(() => {
this.$refs.topicForm.clearValidate()
})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
addTopics() {
this.topicForm.id = ''
this.topicsTitle = '新增题目'
this.NewTopics = true
},
getDetail(id) {
this.$get(this.api.infoId + id).then(res => {
this.topicForm = res.questions
this.topicForm.id = id
this.topicForm.questionType = this.questionType[this.topicForm.questionType]
this.NewTopics = true
}).catch(res => {});
},
editQues(row) {
this.topicsTitle = '编辑题目'
this.getDetail(row.id)
},
showQues(row) {
this.topicsTitle = '查看题目'
this.isShowTopics = true
this.getDetail(row.id)
},
closeTopics() {
this.isShowTopics = false
this.resetForm()
},
delData(row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(this.api.delete,[row.id]).then(res => {
this.$message.success('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllData() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return item.id
})
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = delList
this.$post(this.api.delete,data).then(res => {
this.multipleSelection = [];
this.$message.success('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
}else{
this.$message.error('请先选择题目 !');
}
},
downloadTem() {
location.href = this.api.download
},
questionTypeChange() {
for(let i in this.topicForm){
if(i.includes('isTrue')) this.topicForm[i] = false
}
},
saveTopics() {
this.$refs.topicForm.validate((valid) => {
if (valid) {
let topicForm = this.topicForm
let optionCount = 0
let answer = ''
let isInvalidAnswer = false
for(let n in topicForm) {
if(n.includes('option')) {
topicForm[n] != '' && ++optionCount
}
if(n.includes('isTrue') && topicForm[n]) {
let curOpt = n.replace('isTrue','')
answer += curOpt
if(!topicForm[`option${curOpt.toUpperCase()}`].length) isInvalidAnswer = true
}
}
if(optionCount < 2) return this.$message.warning('请至少添加两个选项!');
if(!answer) return this.$message.warning('请设置正确答案!');
if(topicForm.questionType != '多选题' && answer.length > 1) return this.$message.warning('单选题、判断题只能设置一个正确答案!');
if(isInvalidAnswer) return this.$message.warning('正确答案选项为空,请重新设置!');
this.topicForm.questionType = this.questionType.indexOf(this.topicForm.questionType)
this.topicForm.answer = answer.toUpperCase()
if(this.topicForm.id) {
this.$put(this.api.questionsUpdate,this.topicForm).then(res => {
if(res.errmessage == 'success') {
this.$message.success('提交成功!');
this.NewTopics = false
this.getData()
}else{
this.$message.error(res.message);
}
}).catch(res => {});
}else{
this.$post(this.api.save,this.topicForm).then(res => {
if(res.errmessage == 'success') {
this.$message.success('提交成功!');
this.NewTopics = false
this.getData()
}else{
this.$message.error(res.message);
}
}).catch(res => {});
}
}else{
return false;
}
})
},
showBatchUpload() {
this.BatchUpload = true
},
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
this.uploadFaild = false
if(res.data.token){
this.token = res.data.token
this.uploadFaild = true
}
},
showFaild(){
location.href = `${this.api.export_failure}?token=${this.token}`
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.uploadList = fileList
},
handleDataRemove(file, fileList) {
this.uploadList = fileList
},
uploadSure(){
this.BatchUpload = false
this.page = 1
this.keyword = ''
this.getData()
},
closeUpload() {
this.uploadList = []
this.uploadDataList = []
},
addFill(){
this.fillList.push('')
},
delFill(index){
this.fillList.splice(index,1)
},
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
/deep/.el-radio{
margin-right: 15px;
}
::v-deep .el-checkbox-group{
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
.input-wrap{
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input{
display: inline-block;
width: 250px;
}
i{
margin-left: 5px;
font-size: 22px;
cursor: pointer;
}
}
</style>

@ -0,0 +1,361 @@
<template>
<div>
<el-form
:model="topicForm"
:rules="rules"
:disabled="isShowTopics"
ref="topicForm"
label-width="100px"
class="demo-topicForm"
>
<el-form-item label="题型" prop="questionType">
<el-radio-group v-model="topicForm.questionType" @change="questionTypeChange">
<el-radio label="单选题"></el-radio>
<el-radio label="多选题"></el-radio>
<el-radio label="判断题"></el-radio>
<el-radio label="填空题"></el-radio>
<el-radio label="简答题"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="上传" prop="questionStem">
<el-upload
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.uploadFileUser"
:file-list="uploadList"
name="file"
>
<el-button type="primary" class="ml20">上传视频/音频</el-button>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">导入失败查看原因</el-link>
</el-form-item>
<el-form-item label="题干" prop="questionStem">
<el-input type="textarea" v-model="topicForm.questionStem"></el-input>
</el-form-item>
<el-form-item label="选项" prop="optionA" v-if="topicForm.questionType != '填空题' && topicForm.questionType != '简答题'">
<div class="input flex_around bt">
<span>A</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionA"></el-input>
<el-checkbox v-model="topicForm.aisTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<span>B</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionB"></el-input>
<el-checkbox v-model="topicForm.bisTrue">设为正确答案</el-checkbox>
</div>
<template v-if="topicForm.questionType != '判断题'">
<div class="input flex_around bt">
<span>C</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionC"></el-input>
<el-checkbox v-model="topicForm.cisTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<span>D</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionD"></el-input>
<el-checkbox v-model="topicForm.disTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around bt">
<span>E</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionE"></el-input>
<el-checkbox v-model="topicForm.eisTrue">设为正确答案</el-checkbox>
</div>
<div class="input flex_around">
<span>F</span>
<el-input placeholder="请输入题目" v-model="topicForm.optionF"></el-input>
<el-checkbox v-model="topicForm.fisTrue">设为正确答案</el-checkbox>
</div>
</template>
</el-form-item>
<el-form-item label="正确答案" prop="optionA" v-if="topicForm.questionType == '填空题'">
<div class="bt">
<div class="input-wrap" v-for="(item,index) in fillList" :key="index">
<el-input
placeholder="请输入题目"
v-model="fillList[index]"
></el-input>
<template v-if="index == 0">
<i class="el-icon-circle-plus-outline" @click="addFill"></i>
</template>
<template v-if="fillList.length > 1">
<i class="el-icon-close" @click="delFill(index)"></i>
</template>
</div>
</div>
</el-form-item>
<el-form-item label="答案解析" prop="answerAnalysis">
<el-input type="textarea" v-model="topicForm.answerAnalysis"></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
topicForm: {
answer: '',
questionType : '单选题',
questionStem : '',
optionA:'',
optionB:'',
optionC:'',
optionD:'',
optionE:'',
optionF:'',
aisTrue: false,
bisTrue: false,
cisTrue: false,
disTrue: false,
eisTrue: false,
fisTrue: false,
answerAnalysis: ''
},
rules: {
questionType: [{ required: true, message: '请选择题型', trigger: 'change' }],
questionStem: [{ required: true, message: '请填写题干', trigger: 'blur' }],
// optionA: [{ required: true, message: '', trigger: 'change' }],
// optionB: [{ required: true, message: '', trigger: 'change' }]
},
questionType: ['','单选题','多选题','判断题'],
fillList: ['']
};
},
mounted() {
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData() {
// this.$get(this.api.list, {
// page: this.page,
// size: this.pageSize,
// questionStem: this.keyword,
// questionType: this.subject
// })
// .then(res => {
// this.dataTotal = res.page.totalCount; //
// this.page = res.page.currPage; //
// this.orderData = res.page.list;
// this.$refs.table.clearSelection()
// })
// .catch(err => {})
},
resetForm() {
this.topicForm = {
answer: '',
questionType : '',
questionStem : '',
optionA:'',
optionB:'',
optionC:'',
optionD:'',
optionE:'',
optionF:'',
aisTrue: false,
bisTrue: false,
cisTrue: false,
disTrue: false,
eisTrue: false,
fisTrue: false,
answerAnalysis: ''
}
this.$nextTick(() => {
this.$refs.topicForm.clearValidate()
})
},
handleCurrentChange(val) {
this.page = val
this.getData()
},
addTopics() {
this.topicForm.id = ''
this.topicsTitle = '新增题目'
this.NewTopics = true
},
getDetail(id) {
this.$get(this.api.infoId + id).then(res => {
this.topicForm = res.questions
this.topicForm.id = id
this.topicForm.questionType = this.questionType[this.topicForm.questionType]
this.NewTopics = true
}).catch(res => {});
},
editQues(row) {
this.topicsTitle = '编辑题目'
this.getDetail(row.id)
},
showQues(row) {
this.topicsTitle = '查看题目'
this.isShowTopics = true
this.getDetail(row.id)
},
closeTopics() {
this.isShowTopics = false
this.resetForm()
},
delData(row) {
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(this.api.delete,[row.id]).then(res => {
this.$message.success('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllData() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return item.id
})
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = delList
this.$post(this.api.delete,data).then(res => {
this.multipleSelection = [];
this.$message.success('删除成功');
this.getData()
}).catch(res => {});
})
.catch(() => {});
}else{
this.$message.error('请先选择题目 !');
}
},
downloadTem() {
location.href = this.api.download
},
questionTypeChange() {
for(let i in this.topicForm){
if(i.includes('isTrue')) this.topicForm[i] = false
}
},
saveTopics() {
this.$refs.topicForm.validate((valid) => {
if (valid) {
let topicForm = this.topicForm
let optionCount = 0
let answer = ''
let isInvalidAnswer = false
for(let n in topicForm) {
if(n.includes('option')) {
topicForm[n] != '' && ++optionCount
}
if(n.includes('isTrue') && topicForm[n]) {
let curOpt = n.replace('isTrue','')
answer += curOpt
if(!topicForm[`option${curOpt.toUpperCase()}`].length) isInvalidAnswer = true
}
}
if(optionCount < 2) return this.$message.warning('请至少添加两个选项!');
if(!answer) return this.$message.warning('请设置正确答案!');
if(topicForm.questionType != '多选题' && answer.length > 1) return this.$message.warning('单选题、判断题只能设置一个正确答案!');
if(isInvalidAnswer) return this.$message.warning('正确答案选项为空,请重新设置!');
this.topicForm.questionType = this.questionType.indexOf(this.topicForm.questionType)
this.topicForm.answer = answer.toUpperCase()
if(this.topicForm.id) {
this.$put(this.api.questionsUpdate,this.topicForm).then(res => {
if(res.errmessage == 'success') {
this.$message.success('提交成功!');
this.NewTopics = false
this.getData()
}else{
this.$message.error(res.message);
}
}).catch(res => {});
}else{
this.$post(this.api.save,this.topicForm).then(res => {
if(res.errmessage == 'success') {
this.$message.success('提交成功!');
this.NewTopics = false
this.getData()
}else{
this.$message.error(res.message);
}
}).catch(res => {});
}
}else{
return false;
}
})
},
addFill(){
this.fillList.push('')
},
delFill(index){
this.fillList.splice(index,1)
},
}
};
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
/deep/.el-radio{
margin-right: 15px;
}
::v-deep .el-checkbox-group{
font-size: 2px;
}
.Upload {
text-align: center;
}
.bt {
margin-bottom: 15px;
}
.flex_around {
display: flex;
justify-content: space-around;
align-items: center;
}
.card_m {
margin: 10px 0 20px 0;
}
.input ::v-deep .el-input {
width: 50%;
}
.radio {
margin: 0 15px 0 30px;
font-weight: 600;
}
.input-wrap{
display: flex;
align-items: center;
margin-bottom: 10px;
.el-input{
display: inline-block;
width: 250px;
}
i{
margin-left: 5px;
font-size: 22px;
cursor: pointer;
}
}
</style>

@ -0,0 +1,752 @@
<template>
<div
style="width:100%;height:100%;display:flex;
align-items: center;flex-direction:column "
>
<!-- 头像部分 -->
<div class="header">
<img :src="avatar" class="HeadPortrait" />
<div style="color:#cb221c;font-size:14px;font-family:MicrosoftYaHei;margin-top:5px;">
<el-upload
class="upload-demo"
action="http://www.liuwanr.cn:8080/user/uploadUserAvatars"
:data="{userId:this.userId}"
name="file"
:limit="3"
:on-success="getRes"
>
<div>点击更改头像</div>
</el-upload>
</div>
</div>
<!-- 用户信息 -->
<div class="card">
<p class="block-title" style="display: flex;justify-content: space-between;align-items: center;">
用户信息
<el-button type="success" size="small" v-throttle @click="save">更新资料</el-button>
</p>
<p class="meta-title">个人信息</p>
<div class="information">
<div class="block">
<p class="block-left">姓名</p>
<div class="block-right">
<input
id="username"
type="text"
v-model="personalInformation.userName"
/>
<div class="ii">
<label for="username">
<i class="el-icon-edit" style="color:rgba(255, 255, 255, 1)"></i>
</label>
</div>
</div>
</div>
<div class="block">
<p class="block-left">性别</p>
<el-select
v-model="personalInformation.sex"
placeholder
>
<el-option
v-for="item in sexList"
:key="item.value"
:label="item.name"
:value="item.value"
></el-option>
</el-select>
</div>
<div class="block">
<p class="block-left">所在国家</p>
<el-select
v-model="personalInformation.countries"
placeholder
>
<el-option
v-for="item in countryList"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</div>
<div class="block">
<p class="block-left">所在省份</p>
<el-select
v-model="personalInformation.provinceId"
placeholder
@change="id => getCity(id,1)"
>
<el-option
v-for="item in provinceList"
:key="item.provinceId"
:label="item.provinceName"
:value="item.provinceId"
></el-option>
</el-select>
</div>
<div class="block">
<p class="block-left">所在省市</p>
<el-select
v-model="personalInformation.cityId"
placeholder
:disabled="personalInformation.provinceId ? false : true"
>
<el-option
v-for="item in cityList"
:key="item.cityId"
:label="item.cityName"
:value="item.cityId"
></el-option>
</el-select>
</div>
<div class="block">
<p class="block-left">出生年月日</p>
<el-date-picker
v-model="personalInformation.dateBirth"
:clearable="false"
class="block-right"
type="date">
</el-date-picker>
</div>
<div class="block">
<p class="block-left">证件</p>
<div class="block-right">
<input
id="idnumber"
type="text"
v-model="personalInformation.idnumber"
/>
<div class="ii">
<label for="idnumber">
<i class="el-icon-edit" style="color:rgba(255, 255, 255, 1)"></i>
</label>
</div>
</div>
</div>
<div class="block">
<p class="block-left">教育程度</p>
<el-select
v-model="personalInformation.educationDegree"
placeholder="请选择教育程度"
>
<el-option
v-for="(item,index) in educationDegreeList"
:key="index"
:label="item.name"
:value="item.value"
></el-option>
</el-select>
</div>
<div class="block">
<p class="block-left">当前所在学校</p>
<el-select v-model="personalInformation.clientId" filterable placeholder="请选择学校">
<el-option v-for="(item,index) in schoolList" :key="index" :label="item.clientName" :value="item.id"></el-option>
</el-select>
</div>
</div>
</div>
<div class="card mgb20">
<p class="block-title">账号信息</p>
<div class="information">
<div class="block">
<p class="block-left">用户账号</p>
<div class="block-right">
<input
id="account"
type="text"
v-model="personalInformation.account"
@change="accountChange"
/>
<div class="ii">
<label for="account">
<i class="el-icon-edit" style="color:rgba(255, 255, 255, 1)"></i>
</label>
</div>
</div>
</div>
<div class="block">
<p class="block-left">手机号</p>
<div class="block-right">
<input
id="phone"
type="text"
maxlength="11"
v-model="personalInformation.phone"
/>
<div class="ii">
<label for="phone">
<i class="el-icon-edit" style="color:rgba(255, 255, 255, 1)"></i>
</label>
</div>
</div>
<!-- <div class="near-right">
{{personalInformation.phone}}
<el-button size="small" @click="bindPhone">更换</el-button>
</div> -->
</div>
<div class="block">
<p class="block-left">邮箱</p>
<div class="block-right">
<input
id="email"
type="text"
class="block-right"
v-model="personalInformation.email"
/>
<div class="ii">
<label for="email">
<i class="el-icon-edit" style="color:rgba(255, 255, 255, 1)"></i>
</label>
</div>
</div>
<!-- <div class="near-right"> -->
<!-- {{personalInformation.email}} -->
<!-- <el-button size="small" @click="bindEmail">绑定</el-button> -->
<!-- </div> -->
</div>
<!-- <div class="block">
<p class="block-left">微信</p> -->
<!-- <input
id="wechat"
type="text"
class="block-right"
v-model="personalInformation.weChatID"
/>
<div class="ii">
<label for="wechat">
<i class="el-icon-edit" style="color:rgba(255, 255, 255, 1)"></i>
</label>
</div> -->
<!-- <div class="near-right">
{{personalInformation.weChatID}}
<el-button size="small">绑定</el-button>
</div>
</div> -->
<div class="block">
<p class="block-left">密码</p>
<div class="near-right">
<el-button size="small" @click="bindPassword">更换密码</el-button>
</div>
</div>
</div>
</div>
<el-dialog
title="更换密码"
:visible.sync="passwordVisible"
:close-on-click-modal="false"
@close="closePassword"
width="30%">
<el-form ref="passwordForm" :model="form" label-width="60px">
<el-form-item label="原密码">
<el-input type="password" v-model="passwordForm.password" placeholder="请输入原密码"></el-input>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" v-model="passwordForm.newPassword" placeholder="请输入新密码" @keyup.enter.native="editPassword"></el-input>
</el-form-item>
<el-form-item label="新密码">
<el-input type="password" v-model="passwordForm.reNewPassword" placeholder="请确认新密码" @keyup.enter.native="editPassword"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="passwordVisible = false"> </el-button>
<el-button type="primary" @click="editPassword"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState,mapActions } from 'vuex';
export default {
data() {
return {
personalInformation: {
name:'',
workNumber:'',
password:"",
phone:'',
email:'',
provinceName:'',
cityName:'',
schoolName:'',
professionalName:'',
},
passwordVisible: false,
passwordForm: {
password: '',
newPassword: '',
reNewPassword: ''
},
sexList: [
{
name: '男',
value: 1
},
{
name: '女',
value: 2
}
],
countryList: [
{
label: '中国'
}
],
form: {},
provinceList: [], //
cityList: [], //
//
educationDegreeList: [
{
name: '专科',
value: 1
},
{
name: '本科',
value: 2
},
{
name: '硕士',
value: 3
},
{
name: '博士',
value: 4
},
{
name: '其他',
value: 5
}
],
schoolList: [],
curPassword: '',
accountRepeat: false
};
},
computed: {
...mapState('user', [
'userId','avatar'
])
},
mounted() {
this.getdata();
this.getProvince()
this.getSchoolData()
},
methods: {
...mapActions('user', [
'setAvatar'
]),
getProvince(){
this.$get(this.api.queryProvince).then(res => {
this.provinceList = res.data.list
}).catch(res => {});
},
//
getCity(id,type){
this.personalInformation.cityId = 1
this.getCityData()
},
getCityData(index){
let provinceId = this.personalInformation.provinceId
this.$get(this.api.queryCity,{provinceId}).then(res => {
this.cityList = res.data.list
}).catch(res => {});
},
//
getSchoolData(){
let data = {
searchContent: '',
provinceId: '',
cityId: ''
}
this.$get(`${this.api.queryClient}/1/1000`,data).then(res => {
this.schoolList = res.data.list
}).catch(res => {});
},
accountChange(){
this.$get(`${this.api.getAccount}?account=${this.form.account}`).then(res => {
if(res.data.userInfo){
this.accountRepeat = true
this.$message.warning('该账号已存在')
}else{
this.accountRepeat = false
}
}).catch(res => {});
},
//
getRes(res) {
this.setAvatar(res.message)
},
uploadHeadImg: function() {
this.$el.querySelector('.hiddenInput').click();
},
getdata() {
this.$get(`${this.api.userinfo}?userId=${this.userId}`)
.then(res => {
this.personalInformation = res.data.userInfo
this.personalInformation.countries = '中国'
this.curPassword = this.personalInformation.password
this.$nextTick(() => {
if(this.personalInformation.provinceId){
this.getCityData(1)
}
})
})
.catch(err => {
console.log(err);
});
},
bindPassword() {
this.passwordVisible = true
},
editPassword() {
if(!this.passwordForm.password) return this.$message.warning('请输入原密码')
if(!this.passwordForm.newPassword) return this.$message.warning('请输入新密码')
if(!this.passwordForm.reNewPassword) return this.$message.warning('请确认新密码')
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.$message.warning('请输入6位数以上的密码')
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.$message.warning('输入的新密码不一致,请重新确认')
if(this.curPassword === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致')
let data = {
userId: this.personalInformation.userId,
password: this.passwordForm.password
}
this.$post(this.api.userinfoUpdate,data)
.then(res => {
if(res.success){
this.$message.success('更换成功')
this.curPassword = this.passwordForm.newPassword
this.passwordVisible = false
}else{
this.$message.error('更换失败')
}
})
.catch(err => {
console.log(err);
});
},
closePassword() {
this.passwordForm = {
password: '',
newPassword: '',
reNewPassword: ''
}
},
save() {
if(this.personalInformation.idnumber && !/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)/.test(this.personalInformation.idnumber)) return this.$message.warning('请输入正确的证件号码')
if(this.accountRepeat) return this.$message.warning('该账号已存在')
if(this.personalInformation.phone && !/^1[3456789]\d{9}$/.test(this.personalInformation.phone)) return this.$message.warning('请输入正确的手机号')
if(this.personalInformation.email && !/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.personalInformation.email)) return this.$message.warning('请输入正确的邮箱')
let personalInformation = this.personalInformation
let userInfoEntity = {
idnumber: personalInformation.idnumber,
account: personalInformation.account,
cityId: personalInformation.cityId,
countries: personalInformation.countries,
dateBirth: personalInformation.dateBirth,
educationDegree: personalInformation.educationDegree,
email: personalInformation.email,
phone: personalInformation.phone,
provinceId: personalInformation.provinceId,
clientId: personalInformation.clientId,
clientName: this.schoolList.find(n => n.id == personalInformation.clientId).clientName,
sex: personalInformation.sex,
userId: personalInformation.userId,
userName: personalInformation.userName,
}
let data = userInfoEntity
this.$post(this.api.userinfoUpdate,data).then(res => {
if(res.success){
this.$message.success('提交成功')
this.$router.back()
}else{
this.$message.error('提交失败')
}
}).catch(res => {});
}
}
};
</script>
<style lang="scss" scoped>
.header{
text-align: center;
}
.header /deep/.el-upload-list__item-name {
display: none;
}
.header /deep/.el-icon-upload-success{
display: none;
}
.header /deep/.el-upload-list__item-status-label{
display: none;
}
.header /deep/ .el-upload-list{
display: none;
}
/deep/.el-input__inner{
height: 32px !important;
}
/deep/.el-select .el-input .el-select__caret{
line-height: 32px;
}
input:focus {
outline: 0;
}
.header {
background: #f0f0f0;
}
.openfile {
cursor: pointer;
}
.HeadPortrait {
margin-top: 10px;
width: 80px;
height: 80px;
background: url('../../../assets/img/img.jpg');
border-radius: 50%;
.head {
width: 34px;
height: 34px;
background: rgba(255, 255, 255, 1);
border-radius: 50%;
display: flex;
align-items: center;
flex-direction: column;
justify-content: center;
position: relative;
.eee {
height: 10px;
width: 16px;
background-color: rgba(255, 255, 255, 1);
margin-bottom: -10px;
position: absolute;
top: 8px;
z-index: 2;
}
.Semicircle {
width: 12px;
height: 12px;
border: 2px solid #cb221c;
border-radius: 50px;
margin-bottom: 10px;
position: absolute;
}
}
.body {
color: #cb221c;
width: 30px;
height: 20px;
border: 3px solid #f5f5f5;
border-radius: 100%;
margin-top: 5px;
margin-bottom: -10px;
}
.body::after {
content: '';
width: 40px;
height: 30px;
display: inline-block;
background-color: #cb221c;
margin-top: 8px;
margin-left: -6px;
}
}
input {
height: 50px;
width: 300px;
border: 0;
text-align: right;
outline: none;
}
.card {
margin-top: 10px;
width: 750px;
padding: 20px;
background: rgba(255, 255, 255, 1);
box-shadow: 0px 0px 21px 0px rgba(48, 115, 248, 0.1);
border-radius: 10px;
position: relative;
.block-title{
font-weight: bold;
font-size: 20px;
}
.meta-title{
margin: 10px 0 0;
color: #cdbcec;
font-size: 15px;
}
.el-icon-document {
color: #cb221c;
font-size: 30px;
}
.el-icon-collection {
color: #cb221c;
position: absolute;
left: 31px;
top: 31px;
font-size: 30px;
}
span {
color: #333333;
font-size: 20px;
}
.plus{
display: flex;
justify-content: space-between;
i{
font-size: 22px;
color: #21d749;
cursor: pointer;
}
}
.archives{
padding: 10px 20px;
margin-top: 20px;
border: 1px dashed #bbb;
border-radius: 12px;
&.default-arch{
margin-bottom: 20px;
/deep/.el-select{
width: 10rem;
}
/deep/input{
background-color: transparent;
}
}
}
.archives-wrap{
.block{
display: flex;
align-items: center;
margin-bottom: 8px;
&:last-child{
margin-bottom: 0;
}
.block-left{
width: 30%;
font-family: MicrosoftYaHei;
font-size: 14px;
color: #101010;
}
/deep/.el-input__inner{
border-radius: 8px !important;
}
}
}
.information {
.block {
line-height: 38px;
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
.block-left {
font-family: MicrosoftYaHei;
font-size: 14px;
color: #101010;
}
input{
font-size: 16px;
}
/deep/.el-date-editor .el-input__prefix{
line-height: 32px;
}
/deep/.el-input__prefix,/deep/.el-input__suffix{
left: auto;
right: 0;
}
.block-right,.near-right {
display: inline-flex;
align-items: center;
margin: 0;
padding: 0;
color: #333333ff;
font-size: 18px;
}
.near-right{
right: 0;
font-size: 18px;
}
.ii {
display: flex;
justify-content: center;
align-items: center;
width: 22px;
height: 22px;
margin-left: 10px;
border-radius: 50%;
background-color: #cb221c;
i{
font-size: 12px;
}
}
/deep/.el-input__inner {
padding-right: 1.8rem;
margin-right: 5px;
color: #333333ff;
font-size: 16px;
text-align: right;
border: 0px;
}
/deep/.el-input__icon {
background: #cb221c;
width: 22px;
height: 22px;
line-height: 22px;
color: rgba(255, 255, 255, 1);
border-radius: 50%;
&.el-icon-date{
font-size: 14px;
}
}
/deep/.el-icon-arrow-up:before {
content: '\e6e1';
margin-top: 5px;
}
&.readonly .block-left{
color: #a5a7adff;
}
}
}
.fold{
margin-top: 20px;
text-align: center;
i{
font-size: 22px;
color: #8e8e8e;
cursor: pointer;
&:hover{
opacity: .8;
}
}
}
}
</style>

@ -0,0 +1,550 @@
<template>
<div>
<el-container>
<el-aside width="350px">
<StudentSide ref="getSelectData" @fircheck="fircheck" @twocheck="twocheck" @threecheck="threecheck"></StudentSide>
</el-aside>
<el-main style="padding-top: 0">
<el-col :span="24">
<el-card shadow="hover" class="mgb20 student_tab">
<div class="flex-between mgb20">
<div>
<el-input placeholder="请输入学生名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div>
<div>
<el-button type="primary" size="small" round @click="addstudent">新增学生</el-button>
<el-button type="primary" size="small" round class="mag" @click="batchImport">批量导入</el-button>
<el-button type="primary" size="small" round @click="delAllSelection">批量删除</el-button>
</div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" label="序号" width="55" align="center">
</el-table-column>
<el-table-column prop="studentName" label="学生姓名" align="center">
</el-table-column>
<el-table-column prop="workNumber" label="学生学号" align="center">
</el-table-column>
<el-table-column prop="professionalName" label="专业" align="center">
</el-table-column>
<el-table-column prop="gradeName" label="年级" align="center">
</el-table-column>
<el-table-column prop="className" label="班级" align="center">
</el-table-column>
<el-table-column prop="roleId" label="账号角色" align="center">
<template slot-scope="scope">
学生
</template>
</el-table-column>
<el-table-column prop="loginNumber" label="登录次数" align="center">
</el-table-column>
<el-table-column prop="lastLoginTime" label="上次登录时间" align="center">
</el-table-column>
<el-table-column label="操作" align="center">
<template slot-scope="scope">
<!-- <el-button type="text">查看</el-button> -->
<el-button type="text" @click="editstudent(scope.row)">编辑</el-button>
<el-button type="text" @click="delstudent(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="prev, pager, next" :current-page="page" @current-change="handleCurrentChange" :total="total">
</el-pagination>
</div>
</el-card>
</el-col>
</el-main>
</el-container>
<el-dialog :title="isAdd ? '新增学生' : '编辑学生'" :visible.sync="studentVisible"
width="30%" center @close="closestudent" class="dialog" :close-on-click-modal="false">
<el-form ref="studentForm" :model="studentForm" :rules="rules" label-width="80px">
<el-form-item prop="account" label="账号">
<el-input v-model="studentForm.account" placeholder="请输入学生账号" @change="accountChange"></el-input>
</el-form-item>
<el-form-item prop="userName" label="学生姓名">
<el-input v-model="studentForm.userName" placeholder="请输入学生姓名"></el-input>
</el-form-item>
<el-form-item label="账号角色">
学生
</el-form-item>
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识">
<el-input disabled v-model="studentForm.uniqueIdentificationAccount" placeholder="请输入学生学号获取唯一标识"></el-input>
</el-form-item>
<el-form-item prop="workNumber" label="学生学号">
<el-input v-model="studentForm.workNumber" placeholder="请输入学生学号" @change="workNumberChange"></el-input>
</el-form-item>
<el-form-item prop="professionalId" label="专业">
<el-select v-model="studentForm.professionalId" placeholder="请选择专业" @change="getGrade">
<el-option v-for="(item,index) in majorList" :key="index"
:label="item.stuProfessionalArchitectureName" :value="item.stuProfessionalArchitectureId"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="gradeId" label="年级">
<el-select v-model="studentForm.gradeId" placeholder="请选择年级" :disabled="studentForm.professionalId ? false : true" @change="getClass">
<el-option v-for="(item,index) in gradeList" :key="index"
:label="item.gradeName" :value="item.gradeId"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="classId" label="班级">
<el-select v-model="studentForm.classId" placeholder="请选择班级" :disabled="studentForm.gradeId ? false : true">
<el-option v-for="(item,index) in classList" :key="index"
:label="item.className" :value="item.classId"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="phone" label="手机号">
<el-input v-model="studentForm.phone" placeholder="可以用于登录平台,以及找回密码" maxlength="11"></el-input>
</el-form-item>
<el-form-item prop="email" label="邮箱">
<el-input v-model="studentForm.email" placeholder="可以用于登录平台,以及找回密码"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="studentVisible = false">取消</el-button>
<el-button type="primary" @click="saveSure('studentForm')">确定</el-button>
</span>
</el-dialog>
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" center :close-on-click-modal="false">
<div style="text-align: center">
<div style="margin-bottom: 10px;"><el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button></div>
<el-upload
accept=".xls,.xlsx"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.uploadFileStudent"
:file-list="uploadList"
name="file"
>
<el-button type="primary" class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">导入失败查看原因</el-link>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="importVisible = false">取消</el-button>
<el-button type="primary" @click="uploadSure">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import StudentSide from './studentSide'
import { mapState,mapGetters } from 'vuex'
export default {
data() {
return {
studentVisible: false,
studentForm: {
clientId: this.clientId,
clientName: this.clientName,
studentId: '',
userName: '',
workNumber: '',
phone: '',
email: '',
professionalId: '',
gradeId: '',
classId: '' ,
uniqueIdentificationAccount: '',
account: ''
},
rules: {
userName: [
{ required: true, message: '请输入学生姓名', trigger: 'blur' }
],
workNumber: [
{ required: true, message: '请输入学生学号', trigger: 'blur' },
{
pattern: /^[A-Za-z0-9]+$/,
message: '请输入正确的学生学号',
trigger: 'blur'
}
],
account: [
{ required: true, message: '请输入账号', trigger: 'blur' },
{
pattern: /^[A-Za-z0-9]*$/,
message: '请输入正确的账号',
trigger: 'blur'
}
],
professionalId: [
{ required: true, message: '请选择专业', trigger: 'change' }
],
gradeId: [
{ required: true, message: '请选择年级', trigger: 'change' }
],
classId: [
// { required: true, message: '', trigger: 'change' }
],
phone: [
{
pattern: /^1[3456789]\d{9}$/,
message: '请输入正确的手机号',
trigger: 'blur'
}
],
email: [
{
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/,
message: '请输入正确的邮箱',
trigger: 'blur'
}
]
},
listData: [],
importVisible: false,
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
majorList: [],
gradeList: [],
classList: [],
professionalIds: '',
professionalStudentIds: '',
gradeIds: '',
classIds: '',
multipleSelection: [],
uploadList: [],
parmData: [],
uploadFaild: false,
token: '',
schooldId: 1,
isAdd: true,
accountRepeat: false,
workNumberRepeat: false
};
},
computed: {
...mapState('user', [
'userId','clientId','clientName'
])
},
components: {
StudentSide
},
mounted(){
this.studentForm.clientId = this.clientId
this.studentForm.clientName = this.clientName
this.getData()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
methods: {
getData(){
let data = {
searchContent: this.keyword,
professionalId: this.professionalStudentIds,
gradeIds: this.gradeIds,
classIds: this.classIds,
schoolId: this.clientId
}
this.$get(`${this.api.queryStudent}/${this.page}/${this.pageSize}`,data).then(res => {
this.listData = res.data.studentList
this.total = res.data.total
}).catch(res => {});
},
fircheck(val){
val.ischeck = !val.ischeck
val.children.map(e => {
e.children.map(r => {
if(val.ischeck){
e.ischeck = true
r.ischeck = true
this.parmData.push(r.classId)
}else{
e.ischeck = false
r.ischeck = false
this.core.removeByValue(this.parmData, r.classId);
}
})
})
this.classIds = this.parmData.toString()
this.getData()
},
twocheck(val,val2){
const twoStatus = val.ischeck
val.ischeck = !twoStatus
val2.map(e => {
e.children.map(r => {
r.children.map(k =>{
if(r.gradeId == val.gradeId){
if(r.ischeck){
e.ischeck = true
k.ischeck = true
this.parmData.push(k.classId)
} else {
e.ischeck = false
k.ischeck = false
this.core.removeByValue(this.parmData, k.classId);
}
}
})
})
})
this.classIds = this.parmData.toString()
this.getData()
},
threecheck(val,val2){
const threeStatus = val.ischeck
val.ischeck = !threeStatus
val2.map(e => {
e.children.map(r => {
r.children.map(k =>{
if(k.classId == val.classId){
if(k.ischeck){
e.ischeck = true
r.ischeck = true
this.parmData.push(val.classId)
} else {
e.ischeck = false
r.ischeck = false
this.core.removeByValue(this.parmData,val.classId);
}
}
})
})
})
this.classIds = this.parmData.toString()
this.getData()
},
closestudent(){
this.$refs.studentForm.resetFields()
},
addstudent(){
this.studentForm.studentId = ''
this.studentVisible = true
this.isAdd = true
this.majorList = this.$refs.getSelectData.majorList
},
editstudent(row){
this.studentVisible = true
this.isAdd = false
this.studentForm.studentId = row.studentId
this.majorList = this.$refs.getSelectData.majorList
console.log(12,row)
this.$get(`${this.api.getStudent}/${row.studentId}`).then(res => {
let student = res.data.student
let userInfo = res.data.userInfo
this.studentForm.userName = userInfo.userName,
this.studentForm.workNumber = student.workNumber,
this.studentForm.uniqueIdentificationAccount = userInfo.uniqueIdentificationAccount,
this.studentForm.professionalId = student.professionalId,
this.studentForm.gradeId = student.gradeId,
this.studentForm.classId = student.classId,
this.studentForm.phone = userInfo.phone,
this.studentForm.email = userInfo.email,
this.studentForm.account = userInfo.account
this.getGradeData()
this.getClassData()
}).catch(res => {});
},
//
getGrade(){
this.studentForm.gradeId = ''
this.studentForm.classId = ''
this.getGradeData()
},
getGradeData(){
let data = {
stuProfessionalArchitectureId: this.studentForm.professionalId
}
this.$get(this.api.queryGrade,data).then(res => {
this.gradeList = res.data.Grade
}).catch(res => {});
},
//
getClass(){
this.studentForm.classId = ''
this.getClassData()
},
getClassData(){
let data = {
classId: this.studentForm.gradeId
}
this.$get(this.api.queryClass,data).then(res => {
this.classList = res.data.Class
}).catch(res => {});
},
async accountChange(){
this.$get(`${this.api.getAccount}?account=${this.studentForm.account}`).then(res => {
if(res.data.userInfo){
this.accountRepeat = true
this.$message.warning('该账号已存在')
}else{
this.accountRepeat = false
}
}).catch(res => {});
},
workNumberChange(){
this.$get(`${this.api.studentGetWorkNumber}?workNumber=${this.studentForm.workNumber}`).then(res => {
if(res.data.student){
this.workNumberRepeat = true
this.$message.warning('该学号已存在')
}else{
this.workNumberRepeat = false
}
}).catch(res => {});
},
saveSure(studentForm){
this.$refs[studentForm].validate((valid) => {
if (valid) {
if(this.accountRepeat) return this.$message.warning('该账号已存在')
if(this.workNumberRepeat) return this.$message.warning('该学号已存在')
let data = {
userInfo: {
isPort: 2,
roleId: 4,
clientId: this.studentForm.clientId,
clientName: this.studentForm.clientName,
userName: this.studentForm.userName,
account: this.studentForm.account,
phone: this.studentForm.phone,
email: this.studentForm.email,
uniqueIdentificationAccount: this.studentForm.uniqueIdentificationAccount,
userId: this.studentForm.userId ? this.studentForm.userId : ''
},
student: {
roleId: 4,
isPort: 2,
professionalId: this.studentForm.professionalId,
gradeId: this.studentForm.gradeId,
classId: this.studentForm.classId,
workNumber: this.studentForm.workNumber,
schoolId: this.clientId
}
}
if(this.studentForm.studentId){
this.$post(this.api.updateStudent,data).then(res => {
this.studentVisible = false
this.$message.success('编辑成功')
this.getData()
}).catch(res => {});
}else{
this.$post(this.api.addStudent,data).then(res => {
this.studentVisible = false
this.$message.success('添加成功')
this.getData()
}).catch(res => {});
}
}else{
return false;
}
})
},
delstudent(row){
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = [row.studentId]
this.$del(this.api.deleteStudents,data).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {});
})
.catch(() => {});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllSelection() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return item.studentId
})
//
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = delList
this.$del(this.api.deleteStudents,data).then(res => {
this.multipleSelection = []
this.$message.success('删除成功')
this.getData()
}).catch(res => {});
}).catch(() => {});
}else{
this.$message.error('请先选择学生')
}
},
batchImport(){
this.importVisible = true
},
searchstudent(){
this.page = 1
this.getData()
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
downLoad(){
location.href = this.api.downloadStudentTemp
},
//
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
showFaild(){
location.href = `${this.api.exportFailureStudent}?token=${this.token}`
},
uploadSuccess(res, file, fileList) {
this.uploadFaild = false
if(res.success){
if(res.data.data.token){
this.token = res.data.data.token
this.uploadFaild = true
}else{
this.$message.success('上传成功')
}
}else{
res.data.message ? this.$message.error(res.data.message) : this.$message.error('上传失败,请检查数据')
}
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.uploadList = fileList
this.uploadFaild = false
},
uploadSure(){
this.importVisible = false
this.page = 1
this.classIds = ''
this.keyword = ''
this.getData()
}
}
};
</script>
<style lang="scss" scoped>
</style>

@ -0,0 +1,515 @@
<template>
<div>
<div>
<!-- <p class="side_icon mab20">
<i class="icon-jiahao mar20" @click="addMajor()"></i> -->
<!-- <i class="icon-delete"></i> -->
<!-- </p> -->
<lctree :data="majorList"
@addMajor="addMajor" @editmajorClass="editmajorClass" @delClassDepartment="delClassDepartment"
@addClassDepartment="addClassDepartment" @editDepartment="editDepartment" @delDepart="delDepart"
@addClass="addClass" @editClass="editClass" @delClass="delClass"
@fircheckitem="fircheckitem" @twocheckitem="twocheckitem" @threecheckitem="threecheckitem"
></lctree>
</div>
<!-- 添加专业 -->
<el-dialog :title="Form.classmajorId ? '编辑专业' : '新增专业'" :visible.sync="isaddClassMajor" width="24%" center @close="closeAddClass" :close-on-click-modal="false">
<el-form ref="Form" :model="Form" :rules="rules">
<el-form-item prop="classmajorName">
<el-input placeholder="请输入专业名称" v-model="Form.classmajorName" @change="majorChange"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="isaddClassMajor = false"> </el-button>
<el-button type="primary" @click="sure"> </el-button>
</span>
</el-dialog>
<!-- 添加年级 -->
<el-dialog :title="Form2.departmentId ? '编辑年级' : '新增年级'" :visible.sync="isAddDepartment" width="24%" center @close="closeAddClass2" :close-on-click-modal="false">
<el-form ref="Form2" :model="Form2" :rules="rules">
<el-form-item prop="departmentName">
<el-input placeholder="请输入年级名称" v-model="Form2.departmentName"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="isAddDepartment = false"> </el-button>
<el-button type="primary" @click="sureDepartment"> </el-button>
</span>
</el-dialog>
<!-- 添加班级 -->
<el-dialog :title="Form3.classId ? '编辑班级' : '新增班级'" :visible.sync="isAddClass" width="24%" center @close="closeAddClass3" :close-on-click-modal="false">
<el-form ref="Form3" :model="Form3" :rules="rules">
<el-form-item prop="className">
<el-input placeholder="请输入班级名称" v-model="Form3.className"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="isAddClass = false"> </el-button>
<el-button type="primary" @click="sureClass('Form3')"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import lctree from './studentTree'
import { mapState } from 'vuex'
export default {
props:["Data"],
data() {
return {
majorList: [],
firactive: 0,
twoactive: 0,
threeactive: 0,
isaddClassMajor: false,
isAddDepartment: false,
isAddClass: false,
Form: {
classmajorId: '',
classmajorName: '',
},
Form2: {
departmentId: '',
departmentName: '',
},
Form3: {
classId: '',
className: ''
},
rules: {
departmentName: [
{ required: true, message: '请输入年级名称', trigger: 'blur' },
{
pattern: /^[0-9]*$/,
message: '年级名称必须为数字',
trigger: 'blur'
}
],
className: [
{ required: true, message: '请输入班级名称', trigger: 'blur' },
{
pattern: /^[0-9]*$/,
message: '班级名称必须为数字',
trigger: 'blur'
}
]
},
majorNoAdd: true,
};
},
computed: {
...mapState('user', [
'userId','clientId'
])
},
components: {
lctree
},
mounted(){
this.getStaff()
},
methods: {
getStaff(){
let data = {
schoolId: this.clientId
}
this.$get(this.api.queryStudentProfessionalArchitecture,data).then(res => {
let StaffProfessionalArchitectureList = res.data.StaffProfessionalArchitectureList
StaffProfessionalArchitectureList.map(e => {
(e.ifVisible = false), (e.ischeck = false), (e.label = e.stuProfessionalArchitectureName);
let data = {
stuProfessionalArchitectureId: e.stuProfessionalArchitectureId
}
this.$get(this.api.queryGrade,data).then(res => {
e.children = res.data.Grade
e.children.map(e => {
(e.ifVisible = false), (e.ischeck = false), (e.label = e.gradeName);
let data = {
classId: e.gradeId
}
this.$get(this.api.queryClass,data).then(res => {
res.data.Class.map(e => {
(e.ifVisible = false), (e.ischeck = false), (e.label = e.className);
})
e.children = res.message
}).catch(res => {});
})
}).catch(res => {});
})
setTimeout(() => {
this.majorList = StaffProfessionalArchitectureList
}, 500);
}).catch(res => {});
},
//
fircheckitem(item){
this.$emit("fircheck",item)
},
//
twocheckitem(item){
this.$emit("twocheck",item,this.majorList)
},
threeClick(index){
this.threeactive = index
},
//
threecheckitem(three){
this.$emit("threecheck",three,this.majorList)
},
closeAddClass(){
this.$refs.Form.resetFields()
},
closeAddClass2(){
this.$refs.Form2.resetFields()
},
closeAddClass3(){
this.$refs.Form3.resetFields()
},
//
addMajor(){
this.Form.classmajorId = ''
this.Form.classmajorName = ''
this.isaddClassMajor = true
},
editmajorClass(item){
console.log(item)
this.Form.classmajorId = item.stuProfessionalArchitectureId,
this.Form.classmajorName = item.stuProfessionalArchitectureName
this.isaddClassMajor = true
},
delClassDepartment(item,index){
this.$confirm('确定要删除该专业吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(`${this.api.deleteStaffProfessionalArchitecture}?staffProfessionalArchitectureIds=${item.stuProfessionalArchitectureId}`).then(res => {
this.$message.success('删除成功');
this.majorList.splice(index, 1)
}).catch(res => {});
})
.catch(() => {});
},
sure(){
if(!this.Form.classmajorName) return this.$message.warning('请输入专业名称');
if(!this.majorNoAdd) return this.$message.warning('该一级部门已存在');
let data = {
stuProfessionalArchitectureName: this.Form.classmajorName,
stuProfessionalArchitectureId: this.Form.classmajorId,
schoolId: this.clientId
}
if(this.Form.classmajorId){
this.$post(this.api.updateStaffProfessionalArchitecture,data).then(res => {
this.$message.success('编辑成功');
this.isaddClassMajor = false
this.majorList.map(e =>{
if(e.stuProfessionalArchitectureId == this.Form.classmajorId){
e.stuProfessionalArchitectureName = this.Form.classmajorName
e.label = this.Form.classmajorName
}
})
}).catch(res => {});
}else{
this.$post(this.api.addStudentProfessionalArchitecture,data).then(res => {
this.$message.success('添加成功');
this.isaddClassMajor = false
let newData = {
stuProfessionalArchitectureId: res.data.stuProfessionalArchitectureId,
stuProfessionalArchitectureName : this.Form.classmajorName,
label: this.Form.classmajorName,
ifVisible: false,
ischeck: false,
children: []
}
this.majorList.push(newData)
}).catch(res => {});
}
},
//
addClassDepartment(item){
this.Form2.departmentId = ''
this.Form2.departmentName = ''
this.isAddDepartment = true
this.Form.classmajorId = item.stuProfessionalArchitectureId
},
editDepartment(item){
this.Form2.departmentId = item.gradeId,
this.Form2.departmentName = item.gradeName
this.isAddDepartment = true
for (let j = 0; j < this.majorList.length; j++) {
for (let k = 0; k < this.majorList[j].children.length; k++) {
if(this.majorList[j].children[k].gradeName == item.gradeName){
this.Form.classmajorId = this.majorList[j].stuProfessionalArchitectureId
}
}
}
},
delDepart(item,index){
console.log(item)
this.$confirm('确定要删除该年级吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(`${this.api.deleteGrade}?gradeIds=${item.gradeId}`).then(res => {
this.$message.success('删除成功');
this.majorList.map(e =>{
e.children.map(r =>{
if(r.gradeId == item.gradeId){
e.children.splice(index,1)
if(e.children.length == 0){
e.ifVisible = false
}
}
})
})
}).catch(res => {});
})
.catch(() => {});
},
sureDepartment(){
if(!this.Form2.departmentName) return this.$message.warning('请输入年级名称');
let data = {
gradeName: this.Form2.departmentName,
gradeId: this.Form2.departmentId,
stuProfessionalArchitectureId: this.Form.classmajorId,
}
if(this.Form2.departmentId){
this.$post(this.api.updateGrade,data).then(res => {
this.$message.success('编辑成功');
this.isAddDepartment = false
this.majorList.map(e =>{
e.children.map(r =>{
if(r.gradeId == this.Form2.departmentId){
r.gradeName = this.Form2.departmentName
r.label = this.Form2.departmentName
}
})
})
}).catch(res => {});
}else{
this.$post(this.api.addGrade,data).then(res => {
this.$message.success('添加成功');
this.isAddDepartment = false
let newData = {
gradeId: res.data.gradeId,
gradeName: this.Form2.departmentName,
label: this.Form2.departmentName,
ifVisible: false,
ischeck: false,
children: []
}
this.majorList.map(e =>{
if(e.stuProfessionalArchitectureId == this.Form.classmajorId){
e.ifVisible = true
e.children.push(newData)
}
})
}).catch(res => {});
}
},
async majorChange(){
let res = await this.$get(this.api.queryStaffPAN, { name: this.Form.classmajorName,schoolId: this.clientId });
if(res.data.StaffProfessionalArchitecture != null){
this.$message.warning('该专业组织已存在');
this.majorNoAdd = false
}else{
this.majorNoAdd = true
}
},
//
addClass(two){
this.Form3.classId = ''
this.Form3.className = ''
this.isAddClass = true
this.Form2.departmentId = two.gradeId
},
editClass(three){
this.Form3.classId = three.classId,
this.Form3.className = three.className
this.isAddClass = true
for (let j = 0; j < this.majorList.length; j++) {
for (let k = 0; k < this.majorList[j].children.length; k++) {
for(let l = 0; l < this.majorList[j].children[k].children.length; l++){
if(this.majorList[j].children[k].children[l].className == three.className){
this.Form2.departmentId = this.majorList[j].gradeId
}
}
}
}
},
delClass(item,index){
this.$confirm('确定要删除该班级吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(`${this.api.deleteClass}?classIds=${item.classId}`).then(res => {
this.$message.success('删除成功');
this.majorList.map(e =>{
e.children.map(r =>{
r.children.map(c =>{
if(c.classId == item.classId){
r.children.splice(index,1)
if(r.children.length == 0){
r.ifVisible = false
}
}
})
})
})
}).catch(res => {});
})
.catch(() => {});
},
sureClass(){
if(!this.Form3.className) return this.$message.warning('请输入班级名称');
let data = {
className: this.Form3.className,
classId: this.Form3.classId,
gradeId: this.Form2.departmentId
}
if(this.Form3.classId){
this.$post(this.api.updateClass,data).then(res => {
this.$message.success('编辑成功');
this.isAddClass = false
this.majorList.map(e =>{
e.children.map(r =>{
r.children.map(c =>{
if(c.classId == this.Form3.classId){
c.className = this.Form3.className
c.label = this.Form3.className
}
})
})
})
}).catch(res => {});
}else{
this.$post(this.api.addClass,data).then(res => {
this.$message.success('添加成功');
this.isAddClass = false
let newData = {
classId: res.data.classId,
className: this.Form3.className,
label: this.Form3.className,
ifVisible: false,
ischeck: false
}
this.majorList.map(e =>{
e.children.map(r =>{
if(r.gradeId == this.Form2.departmentId){
r.ifVisible = true
if(r.children.length == 0){
let arr = []
arr.push(newData)
r.children = arr
}else{
r.children.push(newData)
}
}
})
})
}).catch(res => {});
}
}
}
};
</script>
<style lang="scss" scoped>
.side_view{
height: 800px;
padding: 40px 20px;
background-color: #fff;
box-shadow:-2px 0px 57px 0px rgba(192,189,216,0.39);
}
.side_icon{
text-align: right;
}
.side_icon i{
cursor:pointer;
font-size: 30px;
color: #9278FF;
}
.side_tree{
width: 100%;
font-size: 18px;
color: #333;
}
.side_tree i{
color: #9278FF;
margin-left: 10px;
}
.fir_back{
width: 100%;
padding: 15px 0;
background:rgba(255,255,255,1);
/* box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19); */
border-radius:10px;
text-align: left;
}
.fir_back:first-child{
margin-top: 20px;
}
.fir_back:hover{
box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19);
cursor:pointer;
}
.fir_back span{
margin-left: 10px;
}
.two_active{
color: #9278FF;
}
/* .two_active:hover{
color: #9278FF;
cursor:pointer;
} */
.two_back{
width: 100%;
margin-top: 20px;
text-align: left;
}
.two_back:hover{
cursor:pointer;
color: #9278FF;
}
.three_back{
width: 100%;
margin-top: 20px;
text-align: left;
}
.three_back:hover{
cursor:pointer;
color: #9278FF;
}
.mar_top{
margin-top: 20px;
}
.back_active{
box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19);
}
.bor_lef{
padding: 10px 0;
margin-left: 40px;
}
.three_lef{
margin-left: 60px;
padding: 20px 0;
}
.three_text{
font-size: 18px;
margin-top: 10px;
}
.teacher_tab{
margin-left: 20px;
}
.icon_select:before{
transform: rotate(180deg);
}
.list-enter-active, .list-leave-active { transition: all 1s; }
.list-enter, .list-leave-to { opacity: 0; transform: translateY(-30px); }
</style>

@ -0,0 +1,284 @@
<template>
<div class="side_view">
<p class="side_icon mab20">
<i class="icon-jiahao mar20" @click="addMajor()"></i>
<!-- <i class="icon-delete"></i> -->
</p>
<div class="side_tree" @click.stop="open(item)" v-for="(item,index) in data" :key="index">
<div class="item" @click.stop="open(item)">
<!-- <i :class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}" class="icon-shixiangyoujiantou-"></i> -->
<img
:class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}"
src="../../../assets/img/icon-xiangyou.png"
alt
/>
<i :class="item.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="fircheckitem(item)"></i>
<span>{{item.label}}</span>
<i class="edit ft" @click.stop="editmajorClass(item)"></i>
<i class="el-icon-circle-plus ft" @click.stop="addClassDepartment(item)"></i>
<i class="icon-delete ft" @click.stop="delClassDepartment(item,index)"></i>
</div>
<div v-show="item.ifVisible" v-if="item.children&&item.children.length!=0">
<div v-for="(item1,index1) in item.children" :key="index1">
<div class="item1" @click.stop="open(item1)">
<img
:class="{ 'arrowTransform': !item1.ifVisible, 'arrowTransformReturn': item1.ifVisible}"
src="../../../assets/img/icon-xiangyou.png"
alt
style="margin-left:30px"
/>
<i :class="item1.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="twocheckitem(item1)"></i>
<span>{{item1.label}}年级</span>
<i class="edit ft" @click.stop="editDepartment(item1)"></i>
<i class="el-icon-circle-plus ft" @click.stop="addClass(item1)"></i>
<i class="icon-delete ft" @click.stop="delDepart(item1,index1)"></i>
</div>
<div v-show="item1.ifVisible" v-if="item1.children&&item1.children.length!=0">
<div v-for="(item2,index2) in item1.children" :key="index2">
<div class="item2" @click.stop="open(item2)">
<i :class="item2.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="threecheckitem(item2)"></i>
<span>{{item2.label}}</span>
<i class="edit ft" @click.stop="editClass(item2)"></i>
<i class="icon-delete ft" @click.stop="delClass(item2,index2)"></i>
</div>
<!-- <div
v-show="item2.ifVisible"
v-if="item2.children&&item2.children.length!=0"
>
<div
class="item4"
@click.stop="choose(item3)"
v-for="(item3,index3) in item2.children"
:key="index3"
>
<span :class="{checkBox:true,isActive:item3.ifVisible}"></span>
{{item3.label}}
</div>
</div> -->
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (JSON.stringify(this[i]).indexOf(JSON.stringify(val)) != -1) {
this.splice(i, 1);
break;
}
}
};
export default {
data() {
return {
chooseList: []
};
},
watch: {
chooseList(n, o) {
this.$emit('chooseNode', n);
}
},
props: {
data: {
type: Array
}
},
methods: {
//
open(item) {
item.ifVisible = !item.ifVisible;
},
//removeByvaluemain.js
choose(item) {
item.ifVisible = !item.ifVisible;
if (item.ifVisible) {
this.chooseList.push(item);
} else {
this.chooseList.removeByValue(item);
}
},
fircheckitem(item){
this.$emit('fircheckitem',item);
},
twocheckitem(item){
this.$emit('twocheckitem',item);
},
threecheckitem(item){
this.$emit('threecheckitem',item);
},
//
addMajor(){
this.$emit('addMajor');
},
editmajorClass(item){
this.$emit('editmajorClass',item);
},
delClassDepartment(item,index){
this.$emit('delClassDepartment',item,index);
},
//
addClassDepartment(item){
this.$emit('addClassDepartment',item);
},
editDepartment(item){
this.$emit('editDepartment',item);
},
delDepart(item,index){
this.$emit('delDepart',item,index);
},
//
addClass(item){
this.$emit('addClass',item);
},
editClass(item){
this.$emit('editClass',item);
},
delClass(item,index){
this.$emit('delClass',item,index);
},
//
isHasObj(arr, val) {
var flag = 0; //1 0
for (var i = 0; i < arr.length; i++) {
if (JSON.stringify(arr[i]).indexOf(JSON.stringify(val)) != -1) {
flag = 1;
}
}
if (flag == 1) {
return true;
} else {
return false;
}
}
}
};
</script>
<style lang="scss" scoped>
$insideColor: rgba(245, 242, 255, 0.8); //
$outColor: rgba(255, 255, 255, 0.8); //
//,item
@mixin public {
cursor: pointer;
font-size: 14px;
color: #333333;
display: flex;
align-items: center;
img {
height: 20px;
width: 20px;
margin-left: 10px;
}
}
.main {
width: 100%;
}
.item {
@include public;
width: 100%;
padding: 15px 0;
background:rgba(255,255,255,1);
box-shadow:1px 14px 29px 0px rgba(255,69,69,0.19);
border-radius:10px;
text-align: left;
margin-top: 20px;
}
.item:first{
margin-top: 0;
}
.item1 {
@include public;
margin-top: 20px;
}
.item2 {
@include public;
margin-top: 20px;
margin-left:60px
}
.item2:hover{
color: #cb221c;
}
.edit{
display: inline-block;
width: 17px;
height: 17px;
background: url(../../../assets/img/edit.svg) 0 0/cover no-repeat;
}
//ul,li
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
// 使
.arrowTransform {
transition: 0.4s;
transform-origin: center;
transform: rotateZ(0deg);
}
.arrowTransformReturn {
transition: 0.4s;
transform-origin: center;
transform: rotateZ(90deg);
}
//
.checkBox {
width: 14px;
height: 14px;
border-radius: 7px;
margin-left: 10px;
margin-right: 10px;
border: 2px solid rgba(146, 120, 255, 1);
}
//
.isActive {
background: url('../../../assets/img/icon-yigouxuan.png');
background-size: 14px 14px; /*按比例缩放*/
}
.side_view{
// height: 800px;
padding: 40px 20px;
background-color: #fff;
box-shadow:-2px 0px 57px 0px rgba(192,189,216,0.39);
i {
color: #cb221c;
}
}
.side_icon{
text-align: right;
}
.side_icon i{
cursor:pointer;
font-size: 20px;
}
.side_tree{
width: 100%;
font-size: 14px;
color: #333;
i{
margin-left: 5px;
font-size: 17px;
}
span{
margin-left: 5px;
font-size: 14px;
}
}
</style>

@ -0,0 +1,82 @@
<template>
<div>
<div class="tabs" v-if="showTabs">
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == activeName}" @click="tabChange(index)">{{item}}</a>
</div>
<div class="score-table" v-if="activeName == 'staff'" v-auth="'系统设置:员工管理'">
<staff></staff>
</div>
<div class="score-table" v-else v-auth="'系统设置:角色权限'">
<role></role>
</div>
</div>
</template>
<script>
import Setting from '@/setting';
import staff from './staff.vue';
import role from './role.vue';
export default {
data() {
return {
activeName: 'staff',
userId: this.$store.state.userId,
tabs: {
staff: '员工管理',
role: '角色权限'
},
showTabs: true
};
},
components: {
staff,
role
},
created() {
Setting.dynamicRoute && this.initTabs()
},
methods: {
tabChange(index){
this.activeName = index
},
initTabs(){
let btnPermissions = this.$store.state.btnPermissions
let showStaff = btnPermissions.includes('系统设置:员工管理')
let showRole = btnPermissions.includes('系统设置:角色权限')
if(!showStaff || !showRole){
this.showTabs = false
}
!showStaff && showRole && (this.activeName = 'role')
}
}
};
</script>
<style lang="scss" scopted>
.tabs{
display: flex;
align-items: center;
padding: 20px 1.5% 20px;
margin-bottom: 20px;
z-index: 999;
background-color: #fff;
.item{
padding: 12px 20px;
margin-right: 10px;
color:#606266;
line-height: 1;
border-radius: 4px;
background-color: #fff;
border: 1px solid #dcdfe6;
cursor: pointer;
&.active{
color: #fff;
background-color: #cb221c;
border-color: #cb221c;
}
}
}
</style>

@ -0,0 +1,296 @@
<template>
<div>
<el-card shadow="hover" class="mgb20">
<div>
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div style="display: flex;">
<div>
<el-input placeholder="请输入角色名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div>
</div>
</div>
</div>
</el-card>
<el-card shadow="hover">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>角色列表</span>
</div>
<div>
<el-button type="primary" size="small" round @click="addRole" v-auth="'system:角色权限:新增角色'">新增角色</el-button>
<el-button type="primary" size="small" round @click="delAllSelection" v-auth="'system:角色权限:批量删除'">批量删除</el-button>
</div>
</div>
<el-table :data="roleData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" :row-key="getRowKeys">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
</el-table-column>
<el-table-column prop="roleName" label="角色名称" align="center" width="100">
</el-table-column>
<el-table-column label="角色描述" align="center">
<template slot-scope="scope">
<el-input disabled placeholder="该角色用于管理全部功能权限" v-model="scope.row.remark "></el-input>
</template>
</el-table-column>
<el-table-column label="操作" width="180">
<template slot-scope="scope">
<el-button type="text" @click="showRole(scope.row)" v-auth="'system:角色权限:查看'">查看</el-button>
<template v-if="scope.row.id != 1">
<el-button type="text" @click="editRole(scope.row)" v-auth="'system:角色权限:编辑'">编辑</el-button>
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'system:角色权限:删除'">删除</el-button>
</template>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="currentChange" :current-page="pageNo" layout="total, prev, pager, next" :total="totals">
</el-pagination>
</div>
</el-card>
<el-dialog :title="isDetail ? '查看角色' : (isAdd ? '新增角色' : '编辑角色')" :visible.sync="roleVisible"
width="30%" center @close="closeRole" class="dialog" :close-on-click-modal="false">
<el-form ref="form" :model="form" label-width="100px" :disabled="isDetail">
<el-form-item label="角色名称">
<el-input v-model="form.roleName " ref="account" placeholder="请输入角色名称"></el-input>
</el-form-item>
<el-form-item label="角色描述">
<el-input v-model="form.remark " placeholder="请输入角色描述" type="textarea" rows="5"></el-input>
</el-form-item>
<el-form-item prop="role" label="角色权限">
<div class="per-wrap">
<el-tree
ref="per"
:data="permissions"
show-checkbox
node-key="id"
:default-expanded-keys="checkedIds"
:default-checked-keys="checkedIds"
:props="defaultProps">
</el-tree>
</div>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer" v-if="!isDetail">
<el-button @click="roleVisible = false"> </el-button>
<el-button type="primary" @click="saveData"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
name: 'role',
data() {
return {
keyword: '',
form: {
roleName : '',
remark : '',
id: ''
},
isDetail: false,
roleData:[],
defaultProps: {
children: 'children',
label: 'name'
},
pageNo: 1,
pageSize: 10,
totals: 0,
multipleSelection: [],
importVisible: false,
isAdd: true,
roleVisible: false,
searchTimer: null,
permissions: [],
checkedIds: []
};
},
computed: {
...mapState('user', [
'clientId','clientName'
])
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
mounted() {
this.getData()
},
methods: {
getData() {
let data = {
clientId: this.clientId
}
if(this.keyword.length){
data.name = this.keyword
}
this.$get(`${this.api.queryRoles}/${this.pageNo}/${this.pageSize}`,data).then(res => {
this.roleData = res.data.items
this.totals = res.data.total
}).catch(res => {});
},
closeRole(){
this.isDetail = false
this.form = {
roleName : '',
remark : '',
id: ''
}
this.checkedIds = []
this.permissions = []
},
currentChange(val) {
this.pageNo = val;
this.getData();
},
getPer(){
if(!this.permissions.length){
this.$get(this.api.queryPermissionMenu).then(res => {
this.permissions = res.data.children[0].children
}).catch(res => {})
}
},
addRole(){
this.isAdd = true
this.getPer()
this.checkedIds = []
this.permissions.length && this.$refs.per.setCheckedNodes([])
this.roleVisible = true
},
handleRolePer(data,permissions){
let result = data
if(permissions.length){
permissions.map(e => {
if(result.includes(e.id) && e.children.length){
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id),1)
}
e.children.length && this.handleRolePer(data,e.children)
})
}
return result
},
async getDetail(row){
this.getPer()
let roleRes = await this.$get(`${this.api.getRole}/${row.id}`)
if(roleRes.success){
this.form = roleRes.data.item
let perRes = await this.$get(`${this.api.toAssign}/${row.id}`)
if(perRes.success){
this.checkedIds = this.handleRolePer(perRes.data.rolePermissions,this.permissions)
this.$refs.per.setCheckedNodes(this.checkedIds)
}
}
},
showRole(row){
this.isDetail = true
this.isAdd = false
this.getDetail(row)
this.roleVisible = true
},
editRole(row){
this.isAdd = false
this.getDetail(row)
this.roleVisible = true
},
async saveData() {
if(!this.form.roleName) return this.$message.warning('请填写角色名称')
if(!this.form.remark) return this.$message.warning('请填写角色描述')
// if(!this.$refs.per.getCheckedKeys().length) return this.$message.warning('')
let roleData = {
clientId: this.clientId,
id: this.form.id,
roleName: this.form.roleName,
remark: this.form.remark,
isPort: 2
}
let roleRes = await this.$post(this.api.saveOrUpdate,roleData)
if(roleRes.success){
let permissionId = [...this.$refs.per.getHalfCheckedKeys(),...this.$refs.per.getCheckedKeys()]
let perData = {
clientId: this.clientId,
roleId: roleRes.data.roleId,
permissionId,
isPort: 2
}
let perRes = await this.$post(this.api.doAssign,perData)
if(perRes.success){
this.$message.success('新增成功')
this.getData()
this.roleVisible = false
}
}
},
handleDelete(row) {
this.$confirm('该角色下已有账号,删除角色会将该角色下的账号一并删除,是否继续删除?', '提示', {
type: 'warning'
})
.then(() => {
this.$del(`${this.api.removeRole}?roleIds=${row.id}`).then(res => {
if(res.success){
this.$message.success('删除成功');
this.getData()
}
}).catch(res => {})
})
.catch(() => {});
},
getRowKeys(row) {
return row.id;
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllSelection() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return item.id
})
//
this.$confirm('确定要删除选中角色吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$del(`${this.api.removeRole}?roleIds=${delList.join()}`).then(res => {
if(res.success){
this.$message.success('删除成功');
this.getData()
}
}).catch(res => {})
}).catch(() => {});
}else{
this.$message.error('请先选择数据 !');
}
}
}
};
</script>
<style lang="scss" scoped>
.no-mb /deep/.el-form-item{
margin-bottom: 0;
}
/deep/.el-row{
padding: 0 !important;
margin-bottom: 0;
}
.per-wrap{
max-height: 400px;
overflow: auto;
}
</style>

@ -0,0 +1,610 @@
<template>
<div>
<el-container>
<el-aside width="350px">
<TeacherSide ref="getSelectData" @fircheck="fircheck" @twocheck="twocheck" @getData="getData"></TeacherSide>
</el-aside>
<el-main style="padding-top: 0">
<el-col :span="24">
<el-card shadow="hover" class="mgb20 teacher_tab">
<div class="flex-between mgb20">
<div>
<el-input placeholder="请输入员工姓名/工号" v-model="keyword" prefix-icon="el-icon-search" clearable></el-input>
</div>
<div>
<el-button type="primary" size="small" round @click="addTeacher" v-auth="'system:员工管理:新增员工'">新增员工</el-button>
<el-button type="primary" size="small" round @click="batchImport" v-auth="'system:员工管理:批量导入'">批量导入</el-button>
<el-button type="primary" size="small" round @click="delAllSelection" v-auth="'system:员工管理:批量删除'">批量删除</el-button>
</div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center"></el-table-column>
<el-table-column type="index" label="序号" width="55" align="center">
</el-table-column>
<el-table-column prop="userName" label="职工姓名" align="center">
</el-table-column>
<el-table-column prop="account" label="账号" align="center">
</el-table-column>
<el-table-column prop="workNumber" label="职工工号" align="center">
</el-table-column>
<el-table-column prop="staffProfessionalArchitectureName" label="一级部门" align="center">
</el-table-column>
<el-table-column prop="staffGradeName" label="二级部门" align="center">
</el-table-column>
<el-table-column prop="roleName" label="账号角色" align="center">
</el-table-column>
<el-table-column prop="loginNumber" label="登录次数" align="center">
<template slot-scope="scope">
{{scope.row.loginNumber ? scope.row.loginNumber : 0}}
</template>
</el-table-column>
<el-table-column prop="lastLoginTime" label="上次登录时间" width="160" align="center">
</el-table-column>
<el-table-column label="操作" align="center" width="200">
<template slot-scope="scope">
<el-button type="text" @click="showTeacher(scope.row)" v-auth="'system:员工管理:查看'">查看</el-button>
<el-button type="text" @click="editTeacher(scope.row)" v-auth="'system:员工管理:编辑'">编辑</el-button>
<el-button type="text" @click="resetPassword(scope.row)" v-auth="'system:员工管理:重置密码'">重置密码</el-button>
<el-button type="text" @click="delTeacher(scope.row)" v-auth="'system:员工管理:删除'">删除</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background layout="total,prev, pager, next" :current-page="pageNo" @current-change="handleCurrentChange" :total="total">
</el-pagination>
</div>
</el-card>
</el-col>
</el-main>
</el-container>
<!-- 新增用户 -->
<el-dialog :title="isDetail ? '查看员工' : (isAddteacher ? '新增员工' : '编辑员工')" :visible.sync="teacherVisible"
width="30%" :center="!isIE" @close="closeTeacher" class="dialog" :close-on-click-modal="false">
<el-form ref="teacherForm" :model="teacherForm" :rules="rules" label-width="120px" :disabled="isDetail">
<el-form-item prop="userAccount" label="账号">
<el-input v-model="teacherForm.userAccount" ref="account" placeholder="请输入职工账号" @change="accountChange"></el-input>
</el-form-item>
<el-form-item prop="userName" label="用户姓名">
<el-input v-model="teacherForm.userName" placeholder="请输入员工姓名"></el-input>
</el-form-item>
<el-form-item prop="roleValue" label="账号角色">
<el-select v-model="teacherForm.roleValue" placeholder="请选择账号角色" :disabled="!isAddteacher">
<el-option v-for="(item,index) in roleList" :key="index" :label="item.roleName" :value="item.id"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识">
<el-input disabled v-model="teacherForm.uniqueIdentificationAccount" placeholder="请输入职工工号获取唯一标识"></el-input>
</el-form-item>
<el-form-item prop="workNumber" label="职工工号">
<el-input v-model="teacherForm.workNumber" placeholder="请输入职工工号" @change="workNumberChange"></el-input>
</el-form-item>
<el-form-item prop="major" label="一级部门">
<el-select v-model="teacherForm.major" placeholder="请选择一级部门" @change="getDepartment">
<el-option v-for="(item,index) in majorList" :key="index"
:label="item.staffProfessionalArchitectureName" :value="item.staffProfessionalArchitectureId"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="department" label="二级部门">
<el-select v-model="teacherForm.department" placeholder="请选择二级部门" :disabled="teacherForm.major ? false : true">
<el-option v-for="(item,index) in departmentList" :key="index"
:label="item.staffGradeName" :value="item.staffGradeId"></el-option>
</el-select>
</el-form-item>
<el-form-item prop="phone" label="手机号">
<el-input v-model="teacherForm.phone" placeholder="请输入手机号" maxlength="11"></el-input>
</el-form-item>
<el-form-item prop="email" label="邮箱">
<el-input v-model="teacherForm.email" placeholder="请输入邮箱"></el-input>
</el-form-item>
<el-form-item prop="email" label="默认密码">
<el-input v-model="password" disabled></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer" v-if="!isDetail">
<el-button @click="teacherVisible = false"> </el-button>
<el-button type="primary" @click="saveSure('teacherForm')"> </el-button>
</span>
</el-dialog>
<!-- 批量导入 -->
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" center :close-on-click-modal="false">
<div style="text-align: center">
<div style="margin-bottom: 10px;"><el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button></div>
<el-upload
accept=".xls,.xlsx"
:on-remove="handleRemove"
:on-error="uploadError"
:on-success="uploadSuccess"
:before-remove="beforeRemove"
:limit="1"
:on-exceed="handleExceed"
:action="this.api.uploadFileStaff"
:file-list="uploadList"
name="file"
>
<el-button type="primary" class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button>
</el-upload>
<el-link v-if="uploadFaild" type="primary" @click="showFaild">导入失败查看原因</el-link>
</div>
<span slot="footer" class="dialog-footer">
<el-button @click="importVisible = false"> </el-button>
<el-button type="primary" @click="uploadSure"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import TeacherSide from './staffSide.vue';
import Setting from '@/setting';
import { mapState } from 'vuex';
export default {
data() {
return {
isDetail: false,
isAddteacher: false,
teacherVisible: false,
roleList: [],
teacherForm: {
teacherId: '',
userName: '',
roleValue: '',
phone: '',
uniqueIdentificationAccount: '',
workNumber: '',
email: '',
major: '',
department: '',
userAccount: '',
major: '',
schoolId: this.clientId
},
rules: {
userAccount: [
{ required: true, message: '请输入账号', trigger: 'blur' },
{
pattern: /^[A-Za-z0-9]+$/,
message: '请输入正确的账号',
trigger: 'blur'
}
],
userName: [
{ required: true, message: '请输入用户姓名', trigger: 'blur' }
],
roleValue: [
{ required: true, message: '请选择账号角色', trigger: 'change' }
],
uniqueIdentificationAccount: [
// { required: true, message: '', trigger: 'blur' },
],
major: [
{ required: true, message: '请选择一级部门', trigger: 'change' }
],
workNumber: [
{ required: true, message: '请输入职工工号', trigger: 'blur' },
{
pattern: /^[A-Za-z0-9]+$/,
message: '请输入正确的职工工号',
trigger: 'blur'
}
],
department: [
{ required: true, message: '请选择二级部门', trigger: 'change' }
],
phone: [
// { required: true, message: '', trigger: 'blur' },
{
pattern: /^1[3456789]\d{9}$/,
message: '请输入正确的手机号',
trigger: 'blur'
}
],
email: [
// { required: true, message: '', trigger: 'blur' },
{
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/,
message: '请输入正确的邮箱',
trigger: 'blur'
}
],
// schoolId: [
// { required: true, message: '', trigger: 'change' }
// ],
},
majorList: [],
listData: [],
importVisible: false,
keyword: '',
pageNo: 1,
pageSize: 10,
total: 0,
departmentList: [],
teacherDepartmentList: [],
staffstateProfessId: '',
staffGradeId: '',
multipleSelection: [],
uploadList: [],
provinceId: this.$store.state.provinceId,
cityId: this.$store.state.cityId,
userId: this.$store.state.userId,
oneDepartmentIds: '',
twoDepartmentIds: '',
ProfessionalClassList: [],
subjectList: [],
ProfessionalList: [],
NoAdd: '',
AccountNoAdd: '',
NumberNoAdd: '',
platformId: this.$store.state.platformId,
schoolList: [],
uploadFaild: false,
token: '',
accountRepeat: false,
workNumberRepeat: false,
originalAccount: '',
originalWorkNumber: '',
password: Setting.initialPassword
};
},
computed: {
...mapState('user', [
'clientId','clientName'
]),
...mapState('layout', [
'isIE'
])
},
components: {
TeacherSide
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
}
},
mounted(){
this.getData()
this.getRoles()
},
methods: {
handleCheck(data){
let oneDepartmentIds = []
let twoDepartmentIds = []
data.forEach( e => {
if(e.ischeck){
oneDepartmentIds.push(e.staffProfessionalArchitectureId)
}else{
this.removeByValue(oneDepartmentIds, e.staffProfessionalArchitectureId);
}
e.children.forEach( r => {
if(r.ischeck){
twoDepartmentIds.push(r.staffGradeId)
}else{
this.removeByValue(twoDepartmentIds, r.staffGradeId);
}
})
})
this.oneDepartmentIds = oneDepartmentIds.toString()
this.twoDepartmentIds = twoDepartmentIds.toString()
this.getData()
},
fircheck(val,val2){
val.ischeck = !val.ischeck
val.children.map( e => e.ischeck = val.ischeck)
this.handleCheck(val2)
},
twocheck(val,val2){
this.handleCheck(val2)
},
getData(){
let data = {
staffProfessionalArchitectureIds: this.oneDepartmentIds,
staffGradeIds: this.twoDepartmentIds,
searchContent: this.keyword,
schoolId: this.clientId
}
this.$get(`${this.api.queryStaff}/${this.pageNo}/${this.pageSize}`,data).then(res => {
this.listData = res.data.staffList
this.total = res.data.total
}).catch(res => {});
},
getRoles(){
let data = {
clientId: this.clientId
}
this.$get(`${this.api.queryRoles}/1/100`,data).then(res => {
this.roleList = res.data.items
}).catch(res => {});
},
resetPassword(row){
this.$confirm(`重置后的密码为:${Setting.initialPassword},确定重置?`, '提示', {
}).then(() => {
let data = {
userId: row.userId,
password: Setting.initialPassword
}
this.$post(this.api.userinfoUpdate,data).then(res => {
if(res.success){
this.$message.success('重置成功')
}else{
this.$message.error('重置失败')
}
}).catch(res => {});
}).catch(() => {
});
},
accountChange(){
if(this.teacherForm.userAccount !== this.originalAccount){
this.$get(`${this.api.getAccount}?account=${this.teacherForm.userAccount}`).then(res => {
if(res.data.userInfo){
this.accountRepeat = true
this.$message.warning('该账号已存在')
}else{
this.accountRepeat = false
}
}).catch(res => {});
}else{
this.accountRepeat = false
}
},
workNumberChange(){
if(this.teacherForm.workNumber !== this.originalWorkNumber){
this.$get(`${this.api.getWorkNumber}?workNumber=${this.teacherForm.workNumber}`).then(res => {
if(res.data.staff){
this.workNumberRepeat = true
this.$message.warning('该工号已存在')
}else{
this.workNumberRepeat = false
}
}).catch(res => {});
}else{
this.workNumberRepeat = false
}
},
closeTeacher(){
this.$refs.teacherForm.resetFields()
this.teacherForm.clientId = this.$store.state.schoolId
this.teacherForm.clientName = this.$store.state.schoolName
this.teacherForm.department = ''
this.teacherForm.major = ''
this.teacherForm.workNumber = ''
this.teacherForm.userId = ''
this.teacherForm.staffId = ''
},
addTeacher(){
this.isDetail = false
this.teacherVisible = true
this.isAddteacher = true
this.teacherForm.teacherId = ''
this.majorList = this.$refs.getSelectData.majorList
},
getStaffDetail(userId){
this.$get(`${this.api.getStaff}/${userId}`).then(res => {
let user = res.data.userInfo;
let or = res.data.staff;
this.teacherForm.uniqueIdentificationAccount = user.uniqueIdentificationAccount
this.teacherForm.clientId = user.clientId
this.teacherForm.clientName = user.clientName
this.teacherForm.userName = user.userName
this.teacherForm.phone = user.phone
this.teacherForm.email = user.email
this.teacherForm.userAccount = user.account
this.originalAccount = Number(user.account)
this.teacherForm.userId = user.userId
this.teacherForm.schoolId = user.schoolId
this.teacherForm.roleValue = user.roleId
this.teacherForm.major = or.staffProfessionalArchitectureId
this.teacherForm.department = or.staffGradeId
this.teacherForm.workNumber = or.workNumber
this.originalWorkNumber = or.workNumber
this.isManager = true
this.teacherForm.staffId = or.staffId
this.getDepartment()
}).catch(res => {});
},
editTeacher(row){
this.isDetail = false
this.teacherVisible = true
this.isAddteacher = false
this.AccountNoAdd = false
this.teacherForm.teacherId = row.staffId
this.majorList = this.$refs.getSelectData.majorList
this.getStaffDetail(row.staffId)
},
showTeacher(row){
this.isDetail = true
this.teacherVisible = true
this.isAddteacher = false
this.AccountNoAdd = false
this.teacherForm.teacherId = row.staffId
this.majorList = this.$refs.getSelectData.majorList
this.getStaffDetail(row.staffId)
},
getDepartment(){
let data = {
staffProfessionalArchitectureId: this.teacherForm.major
}
this.$get(this.api.queryStaffGrade,data).then(res => {
this.departmentList = res.data.staffGradeList
}).catch(res => {});
},
async saveSure(teacherForm){
this.$refs[teacherForm].validate((valid) => {
if (valid) {
if(this.accountRepeat) return this.$message.warning('该账号已存在')
if(this.workNumberRepeat) return this.$message.warning('该工号已存在')
let isTeacher = false
let isManager = false
let data = {
userInfo: {
userId: this.teacherForm.userId,
userName: this.teacherForm.userName,
account: this.teacherForm.userAccount,
schoolId: this.teacherForm.schoolId,
clientId: this.teacherForm.clientId,
clientName: this.teacherForm.clientName,
roleId: this.teacherForm.roleValue,
phone: this.teacherForm.phone,
email: this.teacherForm.email,
isPort: 2,
uniqueIdentificationAccount: this.teacherForm.uniqueIdentificationAccount ? this.teacherForm.uniqueIdentificationAccount : Date.parse(new Date()),
}
}
let oneDepartmentName = '';
for(let i in this.majorList){
if(this.majorList[i].staffProfessionalArchitectureId == this.teacherForm.major) {
oneDepartmentName = this.majorList[i].staffProfessionalArchitectureName
break;
}
}
let twoDepartmentName = this.departmentList.find((n) => {
return n.staffGradeId == this.teacherForm.department
}).staffGradeName;
data.staff = {
roleId: this.teacherForm.roleValue,
isPort: 2,
schoolId: this.schoolId,
staffId: this.teacherForm.staffId,
userId: this.teacherForm.userId,
workNumber: this.teacherForm.workNumber,
staffProfessionalArchitectureId: this.teacherForm.major,
staffGradeId: this.teacherForm.department,
staffProfessionalArchitectureName: oneDepartmentName,
staffGradeName: twoDepartmentName,
};
if(this.teacherForm.teacherId){
this.$post(this.api.updateStaff,data).then(res => {
this.teacherVisible = false
this.$message.success('编辑成功');
this.getData()
}).catch(res => {});
}else{
this.$post(this.api.addStaff,data).then(res => {
this.teacherVisible = false
this.$message.success('添加成功');
this.getData()
}).catch(res => {});
}
}else{
return false;
}
})
},
delTeacher(row){
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = {
staffIds: row.staffId
}
this.$del(this.api.deleteStaffs,data).then(res => {
this.$message.success('删除成功')
this.getData()
}).catch(res => {});
})
.catch(() => {});
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
delAllSelection() {
if(this.multipleSelection.length != ''){
let newArr = this.multipleSelection
let delList = newArr.map(item => {
return item.staffId
})
//
this.$confirm('确定要删除吗?', '提示', {
type: 'warning'
})
.then(() => {
let data = {
staffIds: delList.join(',')
}
this.$del(this.api.deleteStaffs,data).then(res => {
this.multipleSelection = [];
this.$message.success('删除成功')
this.getData()
}).catch(res => {});
}).catch(() => {});
}else{
this.$message.error('请先选择数据 !')
}
},
batchImport(){
this.importVisible = true
this.uploadList = []
this.uploadFaild = false
},
searchTeacher(){
this.pageNo = 1;
this.getData()
},
handleCurrentChange(val) {
this.pageNo = val;
this.getData();
},
downLoad(){
location.href = this.api.downloadStaffTemp
},
showFaild(){
location.href = `${this.api.exportFailureStaff}?token=${this.token}`
},
//
handleExceed(files, fileList) {
this.$message.warning(
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!`
);
},
uploadSuccess(res, file, fileList) {
this.uploadFaild = false
if(res.success){
if(res.data.data.token){
this.token = res.data.data.token
this.uploadFaild = true
}else{
this.$message.success('上传成功')
}
}else{
res.data.message ? this.$message.error(res.data.message) : this.$message.error('上传失败,请检查数据')
}
},
uploadError(err, file, fileList) {
this.$message({
message: "上传出错,请重试!",
type: "error",
center: true
});
},
beforeRemove(file, fileList) {
return this.$confirm(`确定移除 ${file.name}`);
},
handleRemove(file, fileList) {
this.uploadList = fileList
this.uploadFaild = false
},
uploadSure(){
this.importVisible = false
this.pageNo = 1
this.keyword = ''
this.getData()
}
}
};
</script>
<style lang="scss" scoped>
.el-container{
background-color: #f0f0f0;
}
.mag{
margin-right: 20px;
margin-left: 20px;
}
</style>

@ -0,0 +1,489 @@
<template>
<div>
<div>
<div class="side_view">
<p class="side_icon mab20">
<i class="icon-jiahao mar20" @click="addMajor"></i>
<!-- <i class="icon-delete"></i> -->
</p>
<div class="side_tree" @click.stop="open(item)" v-for="(item,index) in majorList" :key="index">
<div class="item" @click.stop="open(item)">
<!-- <i :class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}" class="icon-shixiangyoujiantou-"></i> -->
<img
v-if="item.children&&item.children.length!=0"
:class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}"
src="../../../assets/img/icon-xiangyou.png"
alt
/>
<i v-else class="empty"></i>
<i :class="item.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="fircheckitem(item)"></i>
<span @click.stop="fircheckitem(item)">{{item.staffProfessionalArchitectureName}}</span>
<i class="edit ft" @click.stop="editMajor(item)"></i>
<i class="el-icon-circle-plus ft" @click.stop="addDepartment(item)"></i>
<i class="icon-delete ft" @click.stop="delMajor(item,index)"></i>
</div>
<div v-show="item.ifVisible" v-if="item.children&&item.children.length!=0">
<div v-for="(item1,index1) in item.children" :key="index1">
<div class="item2" @click.stop="open(item1)">
<i :class="item1.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="twocheckitem(item1)"></i>
<span @click.stop="twocheckitem(item1)">{{item1.label}}</span>
<i class="edit ft" @click.stop="editDepartment(item1)"></i>
<i class="icon-delete ft" @click.stop="delDepartment(item1,index1)"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 添加专业 -->
<el-dialog :title="Form.MajorId ? '编辑专业' : '新增专业'" :visible.sync="isaddMajor" width="24%" center @close="closeAdd" :close-on-click-modal="false">
<el-form ref="Form" :model="Form">
<el-form-item prop="majorName">
<el-input placeholder="请输入专业名称" v-model="Form.majorName" @change="majorChange"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="isaddMajor = false"> </el-button>
<el-button type="primary" @click="sure('Form')"> </el-button>
</span>
</el-dialog>
<!-- 添加部门 -->
<el-dialog :title="Form.departmentId ? '编辑部门' : '新增部门'" :visible.sync="isAddDepartment" width="24%" center @close="closeAdd" :close-on-click-modal="false">
<el-form ref="Form" :model="Form">
<el-form-item prop="departmentName">
<el-input placeholder="请输入部门名称" v-model="Form.departmentName" @change="depChange"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="isAddDepartment = false"> </el-button>
<el-button type="primary" @click="sureDepartment('Form')"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
props:["Data"],
data() {
return {
majorList: [],
firactive: 0,
twoactive: 0,
isaddMajor: false,
isAddDepartment: false,
Form: {
MajorId: '',
majorName: '',
departmentId: '',
departmentName: ''
},
staffstateProfessId: '',
staffstateId: '',
majorNoAdd: true,
depNoAdd: true
};
},
computed: {
...mapState('user', [
'clientId','clientName'
])
},
mounted(){
this.getStaff()
},
methods: {
getStaff(majorIds){
let data = {
schoolId: this.clientId
}
this.$get(this.api.queryStaffPro,data).then(res => {
let firList = res.data.StaffProfessionalArchitectureList
if(firList){
firList.map(e => {
(e.ifVisible = false), (e.ischeck = false), (e.label = e.staffProfessionalArchitectureName);
majorIds && majorIds.includes(e.staffProfessionalArchitectureId) && (e.ifVisible = true)
let data = {
staffProfessionalArchitectureId: e.staffProfessionalArchitectureId
}
this.$get(this.api.queryStaffGrade,data).then(res1 => {
res1.data.staffGradeList.map(e => {
(e.ischeck = false), (e.label = e.staffGradeName);
})
e.children = res1.data.staffGradeList
}).catch(res1 => {});
})
}
setTimeout(() => {
this.majorList = firList
majorIds || (this.majorList[0].ifVisible = true)
}, 500);
}).catch(res => {});
},
//
open(item) {
item.ifVisible = !item.ifVisible;
},
//removeByvaluemain.js
choose(item) {
item.ifVisible = !item.ifVisible;
if (item.ifVisible) {
this.chooseList.push(item);
} else {
this.chooseList.removeByValue(item);
}
},
//
fircheckitem(item){
this.$emit("fircheck",item,this.majorList)
},
//
twocheckitem(item){
item.ischeck = !item.ischeck
this.majorList.forEach( e => {
e.children.forEach( r => {
if(r.staffGradeId == item.staffGradeId){
if(e.children.every(i => i.ischeck)){
e.ischeck = true
}else{
e.ischeck = false
}
}
})
})
this.$emit("twocheck",item,this.majorList)
},
closeAdd(){
this.$refs.Form.resetFields()
},
//
addMajor(){
this.Form.MajorId = ''
this.Form.majorName = ''
this.isaddMajor = true
},
editMajor(item){
this.Form.MajorId = item.staffProfessionalArchitectureId,
this.Form.majorName = item.staffProfessionalArchitectureName
this.isaddMajor = true
},
async majorChange(){
let res = await this.$get(this.api.queryStaffPAN, { name: this.Form.majorName,schoolId: this.clientId });
if(res.data.StaffProfessionalArchitecture != null){
this.$message.warning('该一级部门已存在');
this.majorNoAdd = false
}else{
this.majorNoAdd = true
}
},
async depChange(){
let res = await this.$get(this.api.queryStaffName, { staffGradeName: this.Form.departmentName,staffProfessionalArchitectureId: this.Form.MajorId });
if(res.data.staffGrade != null){
this.$message.warning('该二级部门已存在');
this.depNoAdd = false
}else{
this.depNoAdd = true
}
},
sure(Form){
if(!this.Form.majorName) return this.$message.warning('请输入专业名称');
if(!this.majorNoAdd) return this.$message.warning('该一级部门已存在');
let data = {
staffProfessionalArchitectureName: this.Form.majorName,
staffProfessionalArchitectureId: this.Form.MajorId,
schoolId: this.clientId,
}
if(this.Form.MajorId){
this.$post(this.api.updateStaffPro,data).then(res => {
this.$message.success('编辑成功');
this.isaddMajor = false
this.getStaff()
this.$emit('getData')
}).catch(res => {});
}else{
this.$post(this.api.addStaffPro,data).then(res => {
this.$message.success('添加成功');
this.isaddMajor = false
this.getStaff()
}).catch(res => {});
}
},
//
addDepartment(item){
this.Form.departmentId = ''
this.Form.departmentName = ''
this.isAddDepartment = true
this.Form.MajorId = item.staffProfessionalArchitectureId
},
editDepartment(item){
this.Form.departmentId = item.staffGradeId,
this.Form.departmentName = item.staffGradeName
this.isAddDepartment = true
for (let j = 0; j < this.majorList.length; j++) {
for (let k = 0; k < this.majorList[j].children.length; k++) {
if(this.majorList[j].children[k].staffGradeId == item.staffGradeId){
this.Form.MajorId = this.majorList[j].staffProfessionalArchitectureId
}
}
}
},
sureDepartment(Form){
if(!this.Form.departmentName) return this.$message.warning('请输入部门名称');
if(!this.depNoAdd) return this.$message.warning('该二级部门已存在');
let data = {
schoolId: this.clientId,
staffGradeName: this.Form.departmentName,
staffProfessionalArchitectureId: this.Form.MajorId,
staffGradeId: this.Form.departmentId
}
if(this.Form.departmentId){
this.$post(this.api.updateStaffGrade,data).then(res => {
this.$message.success('编辑成功');
this.isAddDepartment = false
this.majorList.map(e =>{
e.children.map(r =>{
if(r.staffGradeId == this.Form.departmentId){
r.staffGradeName = this.Form.departmentName
r.label = this.Form.departmentName
}
})
})
}).catch(res => {});
}else{
let showMajorIds = this.majorList.map(e => {if(e.ifVisible) return e.staffProfessionalArchitectureId}).filter(n => n)
this.$post(this.api.addStaffGrade,data).then(res => {
this.$message.success('添加成功');
this.isAddDepartment = false
this.getStaff(showMajorIds)
}).catch(res => {});
}
},
delMajor(item,index){
this.$confirm('确定要删除该专业吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(`${this.api.deleteStaffPro}?staffProfessionalArchitectureIds=${item.staffProfessionalArchitectureId}`).then(res => {
this.$message.success('删除成功');
this.majorList.splice(index, 1)
}).catch(res => {});
})
.catch(() => {});
},
delDepartment(item,indx){
this.$confirm('确定要删除该部门吗?', '提示', {
type: 'warning'
})
.then(() => {
this.$post(`${this.api.deleteStaffGrade}?staffGradeIds=${item.staffGradeId}`).then(res => {
this.$message.success('删除成功');
this.majorList.map(e =>{
e.children.map(r =>{
if(r.staffGradeId == item.staffGradeId){
e.children.splice(indx,1)
if(e.children.length == 0){
e.ifVisible = false
}
}
})
})
}).catch(res => {});
})
.catch(() => {});
}
}
};
</script>
<style lang="scss" scoped>
$insideColor: rgba(245, 242, 255, 0.8); //
$outColor: rgba(255, 255, 255, 0.8); //
//,item
@mixin public {
cursor: pointer;
font-size: 16px;
color: #333333;
display: flex;
align-items: center;
img {
height: 20px;
width: 20px;
margin-left: 10px;
}
}
.main {
width: 100%;
}
.item {
@include public;
width: 100%;
padding: 15px 0;
background:rgba(255,255,255,1);
box-shadow:1px 14px 29px 0px rgba(255,69,69,0.19);
border-radius:10px;
text-align: left;
margin-top: 20px;
}
.item:first{
margin-top: 0;
}
.item2 {
@include public;
margin-top: 20px;
margin-left:50px
}
.item2:hover{
color: #cb221c;
}
.item .empty{
width: 20px;
}
.edit{
display: inline-block;
width: 17px;
height: 17px;
background: url(../../../assets/img/edit.svg) 0 0/cover no-repeat;
}
//ul,li
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
// 使
.arrowTransform {
transition: 0.4s;
transform-origin: center;
transform: rotateZ(0deg);
}
.arrowTransformReturn {
transition: 0.4s;
transform-origin: center;
transform: rotateZ(90deg);
}
//
.checkBox {
width: 14px;
height: 14px;
border-radius: 7px;
margin-left: 10px;
margin-right: 10px;
border: 2px solid rgba(146, 120, 255, 1);
}
//
.isActive {
background: url('../../../assets/img/icon-yigouxuan.png');
background-size: 14px 14px; /*按比例缩放*/
}
.side_view{
padding: 40px 20px;
background-color: #fff;
i {
color: #cb221c;
}
}
.side_icon{
text-align: right;
}
.side_icon i{
cursor:pointer;
font-size: 16px;
}
.side_tree{
width: 100%;
font-size: 14px;
color: #333;
i{
color: #cb221c;
margin-left: 5px;
font-size: 17px;
}
span{
margin-left: 5px;
font-size: 14px;
}
}
.side_view{
height: 800px;
padding: 40px 20px;
background-color: #fff;
overflow: auto;
}
.side_icon{
text-align: right;
}
.side_icon i{
cursor:pointer;
font-size: 20px;
color: #cb221c;
}
.fir_back{
width: 100%;
padding: 15px 0;
background:rgba(255,255,255,1);
/* box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19); */
border-radius:10px;
text-align: left;
}
.fir_back:first-child{
margin-top: 20px;
}
.fir_back:hover{
box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19);
cursor:pointer;
}
.fir_back span{
margin-left: 10px;
}
.two_active{
color: #cb221c;
}
/* .two_active:hover{
color: #cb221c;
cursor:pointer;
} */
.two_back:hover{
cursor:pointer;
color: #cb221c;
}
.mar_top{
margin-top: 20px;
}
.back_active{
box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19);
}
.bor_lef{
padding: 20px 0 0 0;
margin-left: 40px;
}
.three_lef{
margin-left: 60px;
padding: 20px 0;
}
.three_text{
font-size: 14px;
margin-top: 10px;
}
.teacher_tab{
margin-left: 20px;
}
.icon_select:before{
transform: rotate(180deg);
}
.list-enter-active, .list-leave-active { transition: all 1s; }
.list-enter, .list-leave-to { opacity: 0; transform: translateY(-30px); }
</style>

@ -0,0 +1,239 @@
<template>
<div class="side_view">
<p class="side_icon mab20">
<i class="icon-jiahao mar20" @click="addMajor"></i>
<!-- <i class="icon-delete"></i> -->
</p>
<div class="side_tree" @click.stop="open(item)" v-for="(item,index) in data" :key="index">
<div class="item" @click.stop="open(item)">
<!-- <i :class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}" class="icon-shixiangyoujiantou-"></i> -->
<img
:class="{ 'arrowTransform': !item.ifVisible, 'arrowTransformReturn': item.ifVisible}"
src="../../../assets/img/icon-xiangyou.png"
alt
/>
<i :class="item.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="fircheckitem(item)"></i>
<span>{{item.staffProfessionalArchitectureName}}</span>
<i class="el-icon-info ft" @click.stop="editMajor(item)"></i>
<i class="el-icon-circle-plus ft" @click.stop="addDepartment(item)"></i>
<i class="icon-delete ft" @click.stop="delMajor(item,index)"></i>
</div>
<div v-show="item.ifVisible" v-if="item.children&&item.children.length!=0">
<div v-for="(item1,index1) in item.children" :key="index1">
<div class="item2" @click.stop="open(item1)">
<i :class="item1.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="twocheckitem(item1)"></i>
<span>{{item1.label}}</span>
<i class="el-icon-info ft" @click.stop="editDepartment(item1)"></i>
<i class="icon-delete ft" @click.stop="delDepartment(item1,index1)"></i>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
Array.prototype.removeByValue = function (val) {
for (var i = 0; i < this.length; i++) {
if (JSON.stringify(this[i]).indexOf(JSON.stringify(val)) != -1) {
this.splice(i, 1);
break;
}
}
};
export default {
data() {
return {
chooseList: []
};
},
watch: {
chooseList(n, o) {
this.$emit('chooseNode', n);
}
},
props: {
data: {
type: Array
}
},
methods: {
//
open(item) {
item.ifVisible = !item.ifVisible;
},
//removeByvaluemain.js
choose(item) {
item.ifVisible = !item.ifVisible;
if (item.ifVisible) {
this.chooseList.push(item);
} else {
this.chooseList.removeByValue(item);
}
},
fircheckitem(item){
this.$emit('fircheckitem',item);
},
twocheckitem(item){
this.$emit('twocheckitem',item);
},
//
addMajor(){
this.$emit('addMajor');
},
editMajor(item){
this.$emit('editMajor',item);
},
delMajor(item,index){
this.$emit('delMajor',item,index);
},
//
addDepartment(item){
this.$emit('addDepartment',item);
},
editDepartment(item){
this.$emit('editDepartment',item);
},
delDepart(item,index){
this.$emit('delDepart',item,index);
},
//
addClass(item){
this.$emit('addClass',item);
},
editDepartment(item){
this.$emit('editDepartment',item);
},
delDepartment(item,index){
this.$emit('delDepartment',item,index);
},
//
isHasObj(arr, val) {
var flag = 0; //1 0
for (var i = 0; i < arr.length; i++) {
if (JSON.stringify(arr[i]).indexOf(JSON.stringify(val)) != -1) {
flag = 1;
}
}
if (flag == 1) {
return true;
} else {
return false;
}
}
}
};
</script>
<style lang="scss" scoped>
$insideColor: rgba(245, 242, 255, 0.8); //
$outColor: rgba(255, 255, 255, 0.8); //
//,item
@mixin public {
cursor: pointer;
font-size: 14px;
color: #333333;
display: flex;
align-items: center;
img {
height: 20px;
width: 20px;
margin-left: 10px;
}
}
.main {
width: 100%;
}
.item {
@include public;
width: 100%;
padding: 15px 0;
background:rgba(255,255,255,1);
box-shadow:1px 14px 29px 0px rgba(138,97,250,0.19);
border-radius:10px;
text-align: left;
margin-top: 20px;
}
.item:first{
margin-top: 0;
}
.item2 {
@include public;
margin-top: 20px;
margin-left:60px
}
.item2:hover{
color: #cb221c;
}
//ul,li
ul,
li {
padding: 0;
margin: 0;
list-style: none;
}
// 使
.arrowTransform {
transition: 0.4s;
transform-origin: center;
transform: rotateZ(0deg);
}
.arrowTransformReturn {
transition: 0.4s;
transform-origin: center;
transform: rotateZ(90deg);
}
//
.checkBox {
width: 14px;
height: 14px;
border-radius: 7px;
margin-left: 10px;
margin-right: 10px;
border: 2px solid rgba(146, 120, 255, 1);
}
//
.isActive {
background: url('../../../assets/img/icon-yigouxuan.png');
background-size: 14px 14px; /*按比例缩放*/
}
.side_view{
// height: 800px;
padding: 40px 20px;
background-color: #fff;
box-shadow:-2px 0px 57px 0px rgba(192,189,216,0.39);
i {
color: #cb221c;
}
}
.side_icon{
text-align: right;
}
.side_icon i{
cursor:pointer;
font-size: 20px;
}
.side_tree{
width: 100%;
font-size: 14px;
color: #333;
i{
margin-left: 10px;
}
span{
margin-left: 5px;
font-size: 14px;
}
}
</style>

@ -0,0 +1,923 @@
<template>
<div class="box">
<div class="form">
<div class="line">
<div class="item">
<p class="key">试卷名称</p>
<el-input v-model="name"></el-input>
</div>
</div>
<div class="line">
<div class="item">
<p class="key">试卷用途</p>
<el-select v-model="effect" placeholder="请选择试卷用途">
<el-option v-for="(item,index) in effectList" :key="index" :label="item.label" :value="item.id"></el-option>
</el-select>
</div>
<div class="item lg">
<p class="key">所属课程</p>
<el-input v-model="courses"></el-input>
</div>
</div>
<div class="line">
<div class="item">
<p class="key">难易程度</p>
<el-select v-model="degree" placeholder="请选择难易程度">
<el-option v-for="(item,index) in degreeList" :key="index" :label="item.label" :value="item.id"></el-option>
</el-select>
</div>
<div class="item lg">
<p class="key">建议时长分钟</p>
<el-input v-model.number="duration"></el-input>
</div>
</div>
<div class="line">
<div class="item">
<p class="key">组卷方式</p>
<div>
<el-radio v-for="(item,index) in typeList" :key="index" v-model="type" :label="item.id">{{item.label}}</el-radio>
</div>
</div>
</div>
<div class="line">
<div class="item">
<p class="key">组卷方式</p>
<div>
<el-button type="primary" @click="selectQues">选择试题</el-button>
<el-button type="primary" @click="removeQues">移除试题</el-button>
<el-button type="primary" @click="preview">试卷预览</el-button>
</div>
</div>
</div>
</div>
<div class="testpaper">
<el-table :data="selectedData" ref="selectedTable" class="table" stripe header-align="center" row-key="id" @selection-change="handleSelecteChange">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="questionSource" label="题库来源" align="center"></el-table-column>
<el-table-column prop="questionStem" label="题干" align="center">
<template slot-scope="scope">
<div v-html="scope.row.questionStem"></div>
</template>
</el-table-column>
<el-table-column prop="name" label="试题类型" align="center"></el-table-column>
<el-table-column prop="courses" label="对应课程" align="center"></el-table-column>
<el-table-column prop="knowledgePoints" label="知识点" align="center"></el-table-column>
<el-table-column prop="useNum" label="使用次数" align="center"></el-table-column>
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
<el-table-column prop="createUser" label="创建人" align="center"></el-table-column>
</el-table>
<div class="point">
<p class="key">设置分值</p>
<div class="inputs">
<div class="line">
<div class="item">
<p class="label">单选题</p>
<input type="text" :disabled="type == 1" v-model.number="singleCount">
<input type="text" v-model.number="singleChoiceScore"> /
</div>
<div class="item">
<p class="label">多选题</p>
<input type="text" :disabled="type == 1" v-model.number="multipleCount">
<input type="text" v-model.number="multipleChoiceScore"> /
</div>
<div class="item">
<p class="label">填空题</p>
<input type="text" :disabled="type == 1" v-model.number="fillBlankCount">
<input type="text" v-model.number="fillBlanksScore"> /
</div>
</div>
<div class="line">
<div class="item">
<p class="label">判断题</p>
<input type="text" :disabled="type == 1" v-model.number="judgeCount">
<input type="text" v-model.number="judgeScore"> /
</div>
<div class="item">
<p class="label">简答题</p>
<input type="text" :disabled="type == 1" v-model.number="briefCount">
<input type="text" v-model.number="briefAnswerScore"> /
</div>
<div class="item">
<p class="label">总分</p>
<input type="text" disabled v-model.number="totalScore">
</div>
</div>
</div>
</div>
</div>
<div class="btns">
<button type="button" v-throttle @click="save(0)">保存</button>
<button type="button" v-throttle class="submit" @click="save(1)">完成并发布</button>
</div>
<el-dialog title="选择试题" :visible.sync="manualVisible" width="60%" @close="closeManual" :close-on-click-modal="false">
<div class="mini-form">
<el-form label-width="80px" inline size="mini">
<el-form-item class="no-mb" label="课程名称">
<el-select v-model="selectManual.courses" clearable placeholder="请选择课程名称" @change="getManualData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in courseList" :key="index" :label="item.courses" :value="item.courses"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="知识点">
<el-select v-model="selectManual.knowledgePoints" clearable placeholder="请选择知识点" @change="getManualData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in pointList" :key="index" :label="item.knowledgePoint" :value="item.knowledgePoint"></el-option>
</el-select>
</el-form-item>
</el-form>
<div class="flex-between" style="align-items: flex-start">
<el-form label-width="80px" inline size="mini">
<el-form-item class="no-mb" label="试题类型">
<el-select v-model="selectManual.name" clearable placeholder="请选择试题类型" @change="getManualData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in nameList" :key="index" :label="item.name" :value="item.name"></el-option>
</el-select>
</el-form-item>
<el-form-item class="no-mb" label="所属题库">
<el-select v-model="selectManual.typeName" clearable placeholder="请选择所属题库" @change="getManualData">
<el-option label="不限" value=""></el-option>
<el-option v-for="(item,index) in quesBankList" :key="index" :label="item.typeName" :value="item.cid"></el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-input
size="mini"
placeholder="请输入题干名称"
prefix-icon="el-icon-search"
v-model="keyword"
clearable
></el-input>
</div>
</div>
</div>
<el-table
:data="listData"
ref="table"
row-key="id"
class="table"
stripe
header-align="center"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center">
<template
slot-scope="scope"
>{{scope.$index + (page - 1) * pageSize + 1}}</template>
</el-table-column>
<el-table-column prop="questionSource" label="题库来源" align="center"></el-table-column>
<el-table-column prop="questionStem" label="题干" align="center">
<template slot-scope="scope">
<div v-html="scope.row.questionStem"></div>
</template>
</el-table-column>
<el-table-column prop="name" label="试题类型" align="center"></el-table-column>
<el-table-column prop="courses" label="对应课程" align="center"></el-table-column>
<el-table-column prop="knowledgePoints" label="知识点" align="center"></el-table-column>
<el-table-column prop="useNum" label="使用次数" align="center"></el-table-column>
<el-table-column prop="createTime" label="上传时间" align="center"></el-table-column>
<el-table-column prop="createUser" label="创建人" align="center"></el-table-column>
</el-table>
<div class="pagination">
<el-pagination
background
@current-change="handleCurrentChange"
:current-page="page"
:page-size="pageSize"
layout="total,prev, pager, next"
:total="total"
></el-pagination>
</div>
<span slot="footer" class="dialog-footer">
<el-button v-throttle @click="manualVisible = false">取消</el-button>
<el-button v-throttle type="primary" @click="submitManual">确定</el-button>
</span>
</el-dialog>
<el-dialog title="选择试题" :visible.sync="inteVisible" width="60%" @close="closeInte" :close-on-click-modal="false">
<div class="select-wrap">
<div class="block" style="margin-bottom: 30px;">
<p class="key">试题课程</p>
<el-transfer v-model="course" :data="inteListData" :props="courseProps" filterable filter-placeholder="请输入课程名称" :titles="['未选', '已选']" @change="courseChange"></el-transfer>
</div>
<div class="block">
<p class="key">题型配置</p>
<div class="types">
<div class="item">
<el-checkbox v-model="countCheck.countCheck1">单选题</el-checkbox>
<input type="text" v-model.number="countNumberInput1" :disabled="!countCheck.countCheck1"> 可选{{countNumber1}}
</div>
<div class="item">
<el-checkbox v-model="countCheck.countCheck2">多选题</el-checkbox>
<input type="text" v-model.number="countNumberInput2" :disabled="!countCheck.countCheck2"> 可选{{countNumber2}}
</div>
<div class="item">
<el-checkbox v-model="countCheck.countCheck5">填空题</el-checkbox>
<input type="text" v-model.number="countNumberInput5" :disabled="!countCheck.countCheck5"> 可选{{countNumber5}}
</div>
<div class="item">
<el-checkbox v-model="countCheck.countCheck3">判断题</el-checkbox>
<input type="text" v-model.number="countNumberInput3" :disabled="!countCheck.countCheck3"> 可选{{countNumber3}}
</div>
<div class="item">
<el-checkbox v-model="countCheck.countCheck4">简答题</el-checkbox>
<input type="text" v-model.number="countNumberInput4" :disabled="!countCheck.countCheck4"> 可选{{countNumber4}}
</div>
</div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<el-button v-throttle @click="inteVisible = false">取消</el-button>
<el-button type="primary" v-throttle @click="submitInte">确定</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import mixins from '@/mixins/setBackground';
import { mapState } from 'vuex'
export default {
mixins: [ mixins ],
data() {
return {
id: this.$route.query.id,
isDetail: Boolean(this.$route.query.show),
name: '',
courses: '',
type: 0,
effect: '',
degree: '',
duration: '',
qid: '',
singleCount: '',
multipleCount: '',
fillBlankCount: '',
judgeCount: '',
briefCount: '',
singleChoiceScore: '',
multipleChoiceScore: '',
judgeScore: '',
fillBlanksScore: '',
briefAnswerScore: '',
multipleSelected: [],
typeNameList: ['单选题','多选题','判断题','简答题','填空题'],
//
manualVisible: false,
multipleSelection: [],
listData: [],
page: 1,
pageSize: 10,
total: 0,
keyword: '',
searchTimer: null,
selectManual: {
courses: '',
name: '',
questionStem: '',
typeName: '',
knowledgePoints: '',
},
courseList: [],
pointList: [],
nameList: [],
quesBankList: [],
//
inteVisible: false,
inteListData: [],
course: [],
courseProps: {
key: 'courses',
label: 'courses'
},
countNumber1: 0,
countNumber2: 0,
countNumber3: 0,
countNumber4: 0,
countNumber5: 0,
countNumberInput1: '',
countNumberInput2: '',
countNumberInput3: '',
countNumberInput4: '',
countNumberInput5: '',
countCheck: {
countCheck1: false,
countCheck2: false,
countCheck3: false,
countCheck4: false,
countCheck5: false,
},
pointRules: [30,20,10,2,10],
selectedData: []
};
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapState('testpaper', [
'degreeList','effectList','typeList'
]),
totalScore(){
let totalScore = this.singleCount * this.singleChoiceScore + this.multipleCount * this.multipleChoiceScore + this.fillBlankCount * this.fillBlanksScore + this.judgeCount * this.judgeScore + this.briefCount * this.briefAnswerScore
return totalScore ? totalScore : ''
}
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getManualData()
},500)
}
},
mounted() {
this.id && this.getInfo()
},
methods: {
getInfo() {
this.$post(`${this.api.detailtestPaper}?id=${this.id}`)
.then(res => {
let list = res.data.list
this.name = list.name
this.effect = list.effect
this.courses = list.courses
this.degree = list.degree
this.duration = list.duration
this.type = list.type
this.qid = list.qid
this.singleChoiceScore = list.singleChoiceScore
this.multipleChoiceScore = list.multipleChoiceScore
this.fillBlanksScore = list.fillBlanksScore
this.judgeScore = list.judgeScore
this.briefAnswerScore = list.briefAnswerScore
this.getQuesList()
})
.catch(err => {
});
},
getQuesList(){
if(this.qid){
let data = {
ids: this.qid.split(','),
schoolId: this.clientId,
userId: this.userId
}
this.$post(this.api.getModifyByList, data).then(res => {
this.selectedData = res.data.list
this.computeTypeCount()
})
.catch(err => {
});
}
},
defaultZero(val){
return val === '' ? 0 : val
},
save(status) {
if(!this.name) return this.$message.warning('请填写试卷名称')
let qid = this.selectedData.map(n => n.id).join()
if(status == 1){
if(this.effect === '') return this.$message.warning('请选择试卷用途')
if(this.courses === '') return this.$message.warning('请填写所属课程')
if(this.degree === '') return this.$message.warning('请选择难易程度')
if(this.duration === '') return this.$message.warning('请填写建议时长')
if(qid === '') return this.$message.warning('请选择试题')
if(this.totalScore < 100) return this.$message.warning('总分值未满100分,请重新设置')
if(this.totalScore > 100) return this.$message.warning('总分值超过100分,请重新设置')
}
let data = {
id: this.id,
schoolId: this.clientId,
userId: this.userId,
name: this.name,
effect: this.effect,
courses: this.courses,
degree: this.degree,
duration: this.duration,
qid: qid,
state: status,
type: this.type,
singleChoiceScore : this.defaultZero(this.singleChoiceScore),
multipleChoiceScore : this.defaultZero(this.multipleChoiceScore),
fillBlanksScore : this.defaultZero(this.fillBlanksScore),
judgeScore : this.defaultZero(this.judgeScore),
briefAnswerScore : this.defaultZero(this.briefAnswerScore)
}
if(this.id){
this.$post(this.api.saveOrUpdatetestPaper, data).then(res => {
this.$message.success('修改成功')
this.$router.back()
})
.catch(err => {
});
}else{
this.$post(this.api.saveOrUpdatetestPaper, data).then(res => {
this.$message.success('创建成功')
this.$router.back()
})
.catch(err => {
});
}
},
selectQues(){
if(this.type == 0){
this.getSelectFilter()
this.getType()
this.getQuesBank()
this.getManualData()
this.manualVisible = true
}else{
this.getInteData()
this.inteVisible = true
}
},
getManualData() {
let data = {
courses: this.selectManual.courses,
knowledgePoints: this.selectManual.knowledgePoints,
name: this.selectManual.name,
pageNum: this.page,
pageSize: this.pageSize,
questionStem: this.keyword,
typeName: this.selectManual.typeName,
userId: this.userId,
}
this.$post(this.api.pageByChoiceList,data)
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
})
.catch(err => {});
},
handleSelecteChange(val){
this.multipleSelected = val;
},
removeQues(){
if(this.multipleSelected.length){
this.$confirm('确定要移除吗?', '提示', {
type: 'warning'
})
.then(() => {
let newData = []
this.selectedData.forEach((n,i) => {
this.multipleSelected.every(e => e.id != n.id) && newData.push(n)
})
console.log(33,newData,this.selectedData,this.multipleSelected)
this.selectedData = newData
this.computeTypeCount()
this.$refs.selectedTable.clearSelection()
this.$message.success('移除成功')
})
.catch(() => {})
}else{
this.$message.error('请先选择数据')
}
},
preview(){
if(this.multipleSelected.length == 1){
this.$router.push(`show?id=${this.multipleSelected[0].id}`)
}else{
this.$message.error('请选择一条数据')
}
},
handleCurrentChange(val) {
this.page = val;
this.getManualData();
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
getSelectFilter(){
this.$post(`${this.api.getSelectInfo}?type=1`)
.then(res => {
this.pointList = res.data.pointList
})
.catch(err => {});
this.$post(`${this.api.getSelectInfo}?type=2`)
.then(res => {
this.courseList = res.data.pointList
})
.catch(err => {});
},
getType() {
this.$get(this.api.typesList)
.then(res => {
this.nameList = res.data.list
})
.catch(err => {})
},
getQuesBank() {
this.$get(this.api.getTypeByOneLever)
.then(res => {
this.quesBankList = res.data.list
})
.catch(err => {})
},
computeTypeCount(){
let selected = this.selectedData
this.singleCount = selected.filter(n => n.name == '单项选择').length
this.multipleCount = selected.filter(n => n.name == '多项选择').length
this.fillBlankCount = selected.filter(n => n.name == '填空题').length
this.judgeCount = selected.filter(n => n.name == '判断题').length
this.briefCount = selected.filter(n => n.name == '简答题').length
},
submitManual(){
if(this.multipleSelection.length){
this.selectedData = this.multipleSelection
this.computeTypeCount()
this.manualVisible = false
}else{
this.$message.error('请选择试题')
}
},
closeManual(){
this.selectManual = {
courses: '',
name: '',
questionStem: '',
typeName: '',
knowledgePoints: '',
}
this.$refs.selectedTable.clearSelection()
this.keyword = ''
this.page = 1
},
getInteData() {
let data = {
// courses: '',
// schoolId: this.clientId,
// userId: this.userId,
schoolId: 2,
userId: 2,
}
this.$post(this.api.fuzzyQuery,data)
.then(res => {
this.inteListData = res.data.fuzzyList
})
.catch(err => {});
},
courseChange(val,dir,allData){
console.log(val,dir,allData)
let data = {
coursesList: val,
// schoolId: this.clientId,
// userId: this.userId,
schoolId: 2,
userId: 2,
}
this.$post(this.api.statistical,data)
.then(res => {
let data = res.data.count
this.countNumber1 = data.countNumber1
this.countNumber2 = data.countNumber2
this.countNumber3 = data.countNumber3
this.countNumber4 = data.countNumber4
this.countNumber5 = data.countNumber5
})
.catch(err => {});
},
typeValid(index){
return this.countCheck[`countCheck${index}`] && this[`countNumberInput${index}`] && this[`countNumber${index}`]
},
countValid(index){
if(this[`countNumberInput${index}`] > this[`countNumber${index}`]){
this.$message.error(`${this.typeNameList[index-1]}输入题数不能大于可选题数`)
return false
}
return true
},
submitInte(){
// return false
let invalid = false
let everyUnchecked = true
let everyIsZero = true
for(let i in this.countCheck){
if(this.countCheck[i]){
everyUnchecked = false
let index = i.replace('countCheck','')
// console.log(33,this[`countNumberInput${index}`])
if(this[`countNumberInput${index}`]){
everyIsZero = false
// if(this[`countNumberInput${index}`] !== ''){
if(this[`countNumberInput${index}`] < this.pointRules[index-1]){
invalid = true
}else if(this[`countNumberInput${index}`] > this.pointRules[index-1]){
this.$message.error('题目数量不能大于可选题数')
return false
}
// }
}
}else{
invalid = true
}
}
// console.log(11,everyIsZero)
if(everyUnchecked) return this.$message.error('请选择题型')
if(everyIsZero) return this.$message.error('请输入题目数量')
let totalCount = 0
if(invalid){
for(let i in this.countCheck){
let index = i.replace('countCheck','')
if(this.countCheck[i]) totalCount += this[`countNumberInput${index}`]
}
let remainder = 100 % totalCount
let avgPoint = 100 / totalCount
if(remainder) avgPoint = (100 - remainder) / totalCount
this.singleCount = ''
this.multipleCount = ''
this.fillBlankCount = ''
this.judgeCount = ''
this.briefCount = ''
this.singleChoiceScore = ''
this.multipleChoiceScore = ''
this.judgeScore = ''
this.fillBlanksScore = ''
this.briefAnswerScore = ''
if(this.typeValid(1)){
if(this.countValid(1)){
this.singleCount = this.countNumberInput1
this.singleChoiceScore = avgPoint
}else{
return false
}
}
if(this.typeValid(2)){
if(this.countValid(2)){
this.multipleCount = this.countNumberInput2
this.multipleChoiceScore = avgPoint
}else{
return false
}
}
if(this.typeValid(5)){
if(this.countValid(5)){
this.fillBlankCount = this.countNumberInput5
this.fillBlanksScore = avgPoint
}else{
return false
}
}
if(this.typeValid(3)){
if(this.countValid(3)){
this.judgeCount = this.countNumberInput3
this.judgeScore = avgPoint
}else{
return false
}
}
if(this.typeValid(4)){
if(this.countValid(4)){
this.briefCount = this.countNumberInput4
this.briefAnswerScore = avgPoint
}else{
return false
}
}
if(remainder){
let remainScore = 0
let remainPlusAvg = remainder + avgPoint
let invalid = false
if(this.typeValid(4)){
remainScore = this.briefCount * avgPoint + remainder
console.log(11,remainScore,remainScore % this.briefCount)
if(remainScore % this.briefCount){
invalid = true
}else{
this.briefAnswerScore = remainScore / this.briefCount
invalid = false
}
}else{
invalid = true
}
if(invalid){
if(this.typeValid(3)){
remainScore = this.judgeCount * avgPoint + remainder
if(remainScore % this.judgeCount){
invalid = true
}else{
this.judgeScore = remainScore / this.judgeCount
invalid = false
}
}else{
invalid = true
}
if(invalid){
if(this.typeValid(5)){
remainScore = this.fillBlankCount * avgPoint + remainder
if(remainScore % this.fillBlankCount){
invalid = true
}else{
this.fillBlanksScore = remainScore / this.fillBlankCount
invalid = false
}
}else{
invalid = true
}
if(invalid){
if(this.typeValid(2)){
remainScore = this.multipleCount * avgPoint + remainder
if(remainScore % this.multipleCount){
invalid = true
}else{
this.multipleChoiceScore = remainScore / this.multipleCount
invalid = false
}
}else{
invalid = true
}
if(invalid){
if(this.typeValid(1)){
remainScore = this.singleCount * avgPoint + remainder
if(remainScore % this.singleCount){
invalid = true
}else{
this.singleChoiceScore = remainScore / this.singleCount
invalid = false
}
}else{
invalid = true
}
}
}
}
}
}
}
let data = {
coursesList: this.course,
// schoolId: this.clientId,
// userId: this.userId,
schoolId: 2,
userId: 2,
}
this.$post(this.api.getQuestionListBySelect,data)
.then(res => {
this.selectedData = res.data.count.splice(0,totalCount)
this.inteVisible = false
})
.catch(err => {});
},
closeInte(){
this.course = [],
this.countNumber1 = 0
this.countNumber2 = 0
this.countNumber3 = 0
this.countNumber4 = 0
this.countNumber5 = 0
this.countNumberInput1 = ''
this.countNumberInput2 = ''
this.countNumberInput3 = ''
this.countNumberInput4 = ''
this.countNumberInput5 = ''
this.countCheck = {
countCheck1: false,
countCheck2: false,
countCheck3: false,
countCheck4: false,
countCheck5: false,
}
},
},
};
</script>
<style lang="scss" scoped>
.box{
width: 90%;
margin: 0 auto;
.form{
.line{
display: flex;
align-items: center;
margin-bottom: 20px;
.item{
display: inline-flex;
align-items: center;
flex: 1;
/deep/.el-select{
flex: 1;
}
.key{
margin-right: 20px;
white-space: nowrap;
font-size: 14px;
color: #555;
}
&.lg .key{
width: 220px;
margin-right: 10px;
text-align: right;
}
}
}
}
.testpaper{
padding: 10px;
background-color: #f7f7f7;
.point{
display: flex;
margin-top: 20px;
.key{
margin: 8px 20px 0 10px;
font-size: 13px;
color: #444;
}
.line{
display: flex;
align-items: center;
margin-bottom: 13px;
.item{
display: inline-flex;
align-items: center;
margin-right: 30px;
color: #444;
font-size: 12px;
input{
width: 80px;
height: 30px;
padding: 0 10px;
margin: 0 10px;
line-height: 30px;
border: 1px solid #e8e8e8;
background-color: #fff;
box-sizing: border-box;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
}
}
}
}
.mini-form{
/deep/.el-form-item__content{
width: 150px;
}
}
.select-wrap{
width: 90%;
margin: 0 auto;
.block{
display: flex;
.key{
margin-right: 20px;
font-size: 14px;
color: #555;
}
.types{
.item{
display: flex;
align-items: center;
margin-bottom: 10px;
color: #444;
font-size: 12px;
/deep/.el-checkbox__label{
color: #444;
font-size: 12px;
}
input{
width: 80px;
height: 24px;
padding: 0 10px;
margin: 0 10px;
line-height: 24px;
color: #333;
font-size: 12px;
background-color: #fff;
border: 1px solid #eaeaea;
&:focus{
outline: none;
}
&:disabled{
background-color: #e8e8e8;
cursor: not-allowed;
}
}
}
}
}
}
</style>

@ -0,0 +1,193 @@
<template>
<div>
<el-card shadow="hover" class="mgb20">
<div>
<div class="flex-center mgb20">
<p class="hr_tag"></p>
<span>筛选</span>
</div>
<div>
<div class="no-mb">
<el-form label-width="80px" inline>
<el-form-item label="所属课程" class="userRadio">
<el-select v-model="cid" clearable placeholder="请选择所属题库">
<el-option v-for="(item,index) in quesBankList" :key="index" :label="item.typeName" :value="item.cid"></el-option>
</el-select>
</el-form-item>
<el-form-item label="试卷状态" class="userRadio">
<el-radio-group v-model="statusId" @change="getData">
<el-radio label="" border>全部</el-radio>
<el-radio v-for="(item,index) in statusList" :key="index" :label="item.id" border>{{item.name}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div class="flex-between">
<el-form label-width="80px" inline>
<el-form-item label="试卷用途" class="userRadio no-mb">
<el-radio-group v-model="purposeId" @change="getData">
<el-radio label="" border>全部</el-radio>
<el-radio v-for="(item,index) in effectList" :key="index" :label="item.id" border>用于{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="创建时间" class="userRadio no-mb">
<el-date-picker v-model="date" align="right" unlink-panels type="daterange"
start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker>
</el-form-item>
</el-form>
<div>
<el-input placeholder="请输入试卷名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input>
</div>
</div>
</div>
</div>
</div>
</el-card>
<el-card shadow="hover">
<div class="flex-between mgb20">
<div class="flex-center">
<p class="hr_tag"></p>
<span>所有试卷</span>
</div>
</div>
<el-table :data="listData" class="table" stripe header-align="center" row-key="id" @selection-change="handleSelecteChange">
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column>
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column>
<el-table-column prop="name" label="试卷名称" align="center"></el-table-column>
<el-table-column prop="courses" label="所属课程" align="center"></el-table-column>
<el-table-column prop="name" label="试卷用途" align="center">
<template slot-scope="scope">
{{getEffectName(scope.row.effect)}}
</template>
</el-table-column>
<el-table-column prop="name" label="难易程度" align="center">
<template slot-scope="scope">
{{getDegreeName(scope.row.degree)}}
</template>
</el-table-column>
<el-table-column prop="name" label="组卷方式" align="center">
<template slot-scope="scope">
{{getTypeName(scope.row.type)}}
</template>
</el-table-column>
<el-table-column prop="duration" label="时长(分钟)" align="center"></el-table-column>
<el-table-column prop="createTime" label="创建时间" align="center"></el-table-column>
<el-table-column prop="releaseTime" label="发布时间" align="center"></el-table-column>
<el-table-column prop="name" label="试卷状态" align="center">
<template slot-scope="scope">
{{getStatusName(scope.row.state)}}
</template>
</el-table-column>
<el-table-column label="操作" width="120">
<template slot-scope="scope">
<el-button type="text" v-if="scope.row.state == 0 && userId == scope.row.userId" @click="publish(scope.row)" v-auth>发布</el-button>
<el-button type="text" @click="preview(scope.row)" v-auth>预览</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination">
<el-pagination background @current-change="handleCurrentChange" :current-page="page" layout="total, prev, pager, next" :total="total">
</el-pagination>
</div>
</el-card>
</div>
</template>
<script>
import { mapState,mapGetters } from 'vuex'
export default {
data() {
return {
listData: [],
multipleSelection: [],
date: [],
startTime: '',
endTime: '',
cid: '',
quesBankList: [],
statusId: '',
purposeId: '',
keyword: '',
page: 1,
pageSize: 10,
total: 0,
searchTimer: null,
};
},
computed: {
...mapState('user', [
'userId','clientId'
]),
...mapState('testpaper', [
'statusList','effectList'
]),
...mapGetters('testpaper', [
'getStatusName','getEffectName','getDegreeName','getTypeName'
])
},
mounted() {
this.getData()
this.getQuesBank()
},
watch: {
keyword: function(val) {
clearTimeout(this.searchTimer)
this.searchTimer = setTimeout(() => {
this.getData()
},500)
},
date: function(val){
if(val){
this.startTime = val[0]
this.endTime = val[1]
}else{
this.startTime = ''
this.endTime = ''
}
this.getData()
}
},
methods: {
getData() {
this.$post(this.api.pageBySchoolTestPaper, {
pageNum: this.page,
pageSize: this.pageSize,
userId: this.userId,
schoolId: this.clientId,
questionStem: this.keyword,
})
.then(res => {
this.listData = res.data.list.list
this.total = res.data.list.totalCount
this.$refs.table.clearSelection()
})
.catch(err => {})
},
handleSelecteChange(val){
this.multipleSelection = val;
},
getQuesBank() {
this.$get(this.api.getTypeByOneLever)
.then(res => {
this.quesBankList = res.data.list
})
.catch(err => {})
},
handleCurrentChange(val) {
this.page = val;
this.getData();
},
preview(row){
this.$router.push(`show?id=${row.id}`)
},
review(row){
this.$router.push('review')
},
}
}
</script>
<style lang="scss" scoped>
/deep/.no-mb.el-form-item{
margin-bottom: 0;
}
</style>

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save