@ -0,0 +1,3 @@ |
||||
> 1% |
||||
last 2 versions |
||||
not ie <= 8 |
@ -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,5 @@ |
||||
module.exports = { |
||||
presets: [ |
||||
'@vue/app' |
||||
] |
||||
} |
@ -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.8.0", |
||||
"element-theme": "^2.0.1", |
||||
"element-ui": "^2.13.0", |
||||
"js-cookie": "^2.2.1", |
||||
"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-pdf": "^4.2.0", |
||||
"vue-quill-editor": "^3.0.6", |
||||
"vue-router": "^3.0.3", |
||||
"vue-schart": "^2.0.0", |
||||
"vuedraggable": "^2.17.0", |
||||
"vuex": "^3.4.0" |
||||
}, |
||||
"devDependencies": { |
||||
"@vue/cli-plugin-babel": "^3.9.0", |
||||
"@vue/cli-service": "^3.9.0", |
||||
"element-theme-chalk": "^2.13.0", |
||||
"node-sass": "^4.14.0", |
||||
"sass-loader": "^8.0.0", |
||||
"vue-template-compiler": "^2.6.10" |
||||
} |
||||
} |
@ -0,0 +1,5 @@ |
||||
module.exports = { |
||||
plugins: { |
||||
autoprefixer: {} |
||||
} |
||||
} |
@ -0,0 +1,18 @@ |
||||
<!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> |
@ -0,0 +1,24 @@ |
||||
<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 () { |
||||
//在页面加载时读取localStorage里的状态信息 |
||||
if (util.local.get(Setting.storeKey) ) { |
||||
this.$store.replaceState(Object.assign({}, this.$store.state,util.local.get(Setting.storeKey))) |
||||
} |
||||
|
||||
//在页面刷新时将vuex里的信息保存到localStorage里 |
||||
window.addEventListener("beforeunload",()=>{ |
||||
util.local.get(Setting.tokenKey) && util.local.set(Setting.storeKey,this.$store.state) |
||||
}) |
||||
} |
||||
} |
||||
</script> |
After Width: | Height: | Size: 8.1 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 499 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 829 B |
After Width: | Height: | Size: 683 B |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 1.5 MiB |
After Width: | Height: | Size: 106 KiB |
After Width: | Height: | Size: 18 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 1.2 MiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 8.8 KiB |
@ -0,0 +1,124 @@ |
||||
<template> |
||||
<div> |
||||
<el-dialog |
||||
custom-class="pdf-dia" |
||||
:close-on-click-modal="false" |
||||
:visible.sync="visible" |
||||
@close="closePdf" |
||||
:fullscreen="true" |
||||
:modal="false" |
||||
:append-to-body="true"> |
||||
<div> |
||||
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="closePdf"><i class="el-dialog__close el-icon el-icon-close"></i></button> |
||||
<div class="pdf"> |
||||
<p class="arrow"> |
||||
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span> |
||||
{{currentPage}} / {{pageCount}} |
||||
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span> |
||||
</p> |
||||
<pdf |
||||
class="pdf-wrap" |
||||
:src="src" |
||||
:page="currentPage" |
||||
@num-pages="pageCount=$event" |
||||
@page-loaded="currentPage=$event" |
||||
@loaded="loadPdfHandler" |
||||
> |
||||
</pdf> |
||||
</div> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import pdf from "vue-pdf"; |
||||
export default { |
||||
props: ['visible','src'], |
||||
data() { |
||||
return { |
||||
pdfVisible: false, |
||||
pdfSrc: '', |
||||
currentPage: 0, |
||||
pageCount: 0, |
||||
fileType: 'pdf', |
||||
}; |
||||
}, |
||||
components: { pdf }, |
||||
mounted(){ |
||||
this.addEvent() |
||||
}, |
||||
methods: { |
||||
closePdf(){ |
||||
this.$emit('update:visible',false) |
||||
this.$emit('update:src','') |
||||
this.currentPage = 1 |
||||
}, |
||||
changePdfPage (val) { |
||||
if (val === 0 && this.currentPage > 1) { |
||||
this.currentPage-- |
||||
} |
||||
if (val === 1 && this.currentPage < this.pageCount) { |
||||
this.currentPage++ |
||||
} |
||||
}, |
||||
loadPdfHandler (e) { |
||||
this.currentPage = 1 |
||||
}, |
||||
addEvent(){ |
||||
document.onkeydown = e => { |
||||
let key = window.event.keyCode |
||||
if(key == 37){ |
||||
this.changePdfPage(0) |
||||
}else if(key == 39){ |
||||
this.changePdfPage(1) |
||||
} |
||||
} |
||||
this.$once('hook:beforeDestroy',() => { |
||||
document.onkeydown = null |
||||
}) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
/deep/.pdf-dia{ |
||||
border-radius: 0 !important; |
||||
.el-dialog__header{ |
||||
display: none; |
||||
} |
||||
.el-dialog__body{ |
||||
padding: 0; |
||||
} |
||||
.el-dialog__headerbtn{ |
||||
top: 10px; |
||||
.el-dialog__close{ |
||||
color: #fff; |
||||
font-size: 16px; |
||||
} |
||||
} |
||||
|
||||
.pdf{ |
||||
.arrow{ |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
width: 100%; |
||||
padding: 10px 0; |
||||
font-size: 16px; |
||||
color: #fff; |
||||
background-color: #333; |
||||
.turn{ |
||||
margin: 0 10px; |
||||
font-size: 18px; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
.pdf-wrap{ |
||||
height: calc(100vh - 45px); |
||||
margin: 0 auto; |
||||
overflow: auto; |
||||
} |
||||
} |
||||
} |
||||
|
||||
</style> |
@ -0,0 +1,206 @@ |
||||
<template> |
||||
<div class="quill" ref="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 |
||||
}, |
||||
toTop: { |
||||
type: Boolean, |
||||
default:true |
||||
}, |
||||
border: { |
||||
type: Boolean, |
||||
default:false |
||||
}, |
||||
height: { |
||||
type: Number |
||||
}, |
||||
minHeight: { |
||||
type: Number |
||||
}, |
||||
/* |
||||
* 原本的readOnly失效,对比其他项目,发现是quill版本不同导致, |
||||
* 使用props传入elseRead = 'true',手动隐藏工具栏 |
||||
*/ |
||||
elseRead:{ |
||||
type:String,default:'false' |
||||
} |
||||
}, |
||||
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 |
||||
} |
||||
}, |
||||
created(){ |
||||
}, |
||||
mounted () { |
||||
this.init(); |
||||
// 处理工具栏隐藏样式 |
||||
if(this.elseRead==='true'){ |
||||
let children = this.$refs.quill.children[0].style |
||||
children.padding = '0' |
||||
children.overflow = 'hidden' |
||||
children.height = '0' |
||||
children.borderTop = '0' |
||||
} |
||||
}, |
||||
beforeDestroy () { |
||||
// 在组件销毁后销毁实例 |
||||
this.Quill = null; |
||||
}, |
||||
methods: { |
||||
init () { |
||||
const editor = this.$refs.editor; |
||||
// 初始化编辑器 |
||||
this.Quill = new Quill(editor, this.options); |
||||
// 默认值 |
||||
this.Quill.pasteHTML(this.currentValue); |
||||
if(this.toTop){ |
||||
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; |
||||
} |
||||
} |
||||
.else{ |
||||
.ql-toolbar.ql-snow{ |
||||
height: 0; |
||||
overflow: hidden; |
||||
padding: 0; |
||||
border-top: 0; |
||||
} |
||||
} |
||||
|
||||
</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,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,43 @@ |
||||
<template> |
||||
<div> |
||||
<div class="copyright"> |
||||
<a href="https://beian.miit.gov.cn/#/Integrated/index" target="_blank">粤ICP备20072679号</a> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
|
||||
}; |
||||
}, |
||||
mounted(){ |
||||
|
||||
}, |
||||
methods: { |
||||
|
||||
}, |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.copyright{ |
||||
padding: 20px 0; |
||||
color: rgba(0, 0, 0, 0.45); |
||||
font-size: 12px; |
||||
text-align: center; |
||||
background-color: #333; |
||||
p{ |
||||
margin-bottom: 10px; |
||||
color: #fff; |
||||
font-size: 12px; |
||||
} |
||||
a{ |
||||
color:#fff; |
||||
font-size: 12px; |
||||
&:hover{ |
||||
opacity: .8; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,84 @@ |
||||
<template> |
||||
<div class="header"> |
||||
<img class="logo hh" v-if="isHh" src="@/assets/img/logo-hh.png" /> |
||||
<img class="logo" v-else src="@/assets/img/logo.png" /> |
||||
<div class="action"> |
||||
<div class="user" @click="toPersonal"> |
||||
<el-avatar :size="40" :src="avatar"></el-avatar> |
||||
<span class="m-l-10">{{userName}}</span> |
||||
</div> |
||||
<el-divider direction="vertical"></el-divider> |
||||
<el-button type="text" class="ml20" @click="logout">退出</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import { mapState, mapActions } from 'vuex' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data() { |
||||
return { |
||||
isHh: Setting.isHh, |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'avatar','userName' |
||||
]), |
||||
...mapState('auth', [ |
||||
'routes' |
||||
]) |
||||
}, |
||||
mounted(){ |
||||
|
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'logout' |
||||
]), |
||||
toPersonal(){ |
||||
this.$router.push('/setting/person') |
||||
}, |
||||
}, |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.header { |
||||
position: relative; |
||||
height: 60px; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
font-size: 16px; |
||||
color: #333; |
||||
background-color: #fff; |
||||
.logo { |
||||
height: 50px; |
||||
margin-left: 20px; |
||||
&.hh{ |
||||
width: 220px; |
||||
} |
||||
} |
||||
.action { |
||||
display: flex; |
||||
padding-right: 50px; |
||||
align-items: center; |
||||
.user{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
cursor: pointer; |
||||
} |
||||
.el-button--text{ |
||||
margin-left: 20px; |
||||
color: #333; |
||||
} |
||||
.el-divider{ |
||||
width: 2px; |
||||
height: 15px; |
||||
margin-left: 20px; |
||||
background-color: #333; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,66 @@ |
||||
<template> |
||||
<div class="main"> |
||||
<v-head></v-head> |
||||
<div class="layout"> |
||||
<navbar></navbar> |
||||
<div class="content"> |
||||
<transition name="move" mode="out-in"> |
||||
<router-view class="view"></router-view> |
||||
</transition> |
||||
<el-backtop target=".content"></el-backtop> |
||||
</div> |
||||
<v-footer ref="footer"></v-footer> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import vHead from '../header' |
||||
import navbar from '../navbar' |
||||
import vFooter from '../footer' |
||||
import { mapState, mapActions } from 'vuex' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data() { |
||||
return { |
||||
|
||||
}; |
||||
}, |
||||
components: { |
||||
vHead, |
||||
navbar, |
||||
vFooter |
||||
}, |
||||
mounted() { |
||||
this.autoLogout() |
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'logout' |
||||
]), |
||||
autoLogout(){ |
||||
let lastTime = new Date().getTime() |
||||
document.onmousedown = () => { |
||||
lastTime = new Date().getTime() |
||||
} |
||||
|
||||
setInterval(() => { |
||||
if(util.local.get(Setting.tokenKey) && (new Date().getTime() - lastTime) > Setting.autoLogoutTime){ |
||||
util.errorMsg('用户登录过期,请重新登录') |
||||
setTimeout(this.logout,1500) |
||||
} |
||||
},1000) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.main{ |
||||
min-height: 100%; |
||||
.content{ |
||||
min-height: calc(100vh - 176px); |
||||
padding: 24px 24px 0; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,127 @@ |
||||
<template> |
||||
<div> |
||||
<el-menu class="sidebar-el-menu" :default-active="active" background-color="#324157" text-color="#bfcbd9" active-text-color="#9278FF" 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 { mapState,mapActions } from 'vuex' |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
export default { |
||||
data() { |
||||
return { |
||||
active: this.$route.path, |
||||
defaultMenus: [ |
||||
{ |
||||
icon: 'el-icon-takeaway-box', |
||||
index: '/assessment/list', |
||||
title: '考核管理' |
||||
}, |
||||
{ |
||||
icon: 'el-icon-collection', |
||||
index: '/achievement/list', |
||||
title: '成绩管理' |
||||
}, |
||||
{ |
||||
icon: 'el-icon-receiving', |
||||
index: '/evaluation/list', |
||||
title: '测评管理' |
||||
}, |
||||
{ |
||||
icon: 'el-icon-postcard', |
||||
index: '/project/list', |
||||
title: '实验项目管理' |
||||
}, |
||||
{ |
||||
icon: 'el-icon-user', |
||||
index: '/student/list', |
||||
title: '学生管理' |
||||
}, |
||||
{ |
||||
icon: 'el-icon-setting', |
||||
index: '/system/list', |
||||
title: '系统设置' |
||||
} |
||||
], |
||||
menus: [], |
||||
actives: { |
||||
dashboard: ['add'], |
||||
achievement: ['experiment','experimentVir','experimentTeach','addexperiment','addexperimentoptions','showExperiment','showExperimentoption','showExperimentoptions'], |
||||
project: ['addproject','program','programOption','programOptions'], |
||||
backstage: ['report'] |
||||
} |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('auth', [ |
||||
'routes' |
||||
]) |
||||
}, |
||||
watch: { |
||||
'$route'(to,from) { |
||||
let actives = this.actives |
||||
for(let i in this.actives){ |
||||
if(actives[i].includes(this.$route.name)) this.active = `/${i}/list` |
||||
} |
||||
this.active = this.$route.path |
||||
} |
||||
}, |
||||
created() { |
||||
this.initMenu() |
||||
}, |
||||
methods: { |
||||
initMenu(){ |
||||
if(Setting.dynamicRoute){ |
||||
let routes = this.routes |
||||
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%; |
||||
} |
||||
.el-menu.el-menu--horizontal{ |
||||
border-bottom: none; |
||||
} |
||||
.sidebar > ul { |
||||
height: 100%; |
||||
} |
||||
</style> |
@ -0,0 +1,25 @@ |
||||
/** |
||||
* @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.path ? result.push(`${e.path}:${n.name}:${j.name}`) : result.push(`${n.path}:${j.name}`)) |
||||
}) |
||||
}else{ |
||||
result.push(`${e.path}:${n.name}`) |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
}) |
||||
store.dispatch('auth/addBtnAuth',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,32 @@ |
||||
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.path){ |
||||
let meta = createMeta(e) |
||||
newRoutes.push({ |
||||
name: e.path, |
||||
path: e.path, |
||||
path: () => import(`@/pages/${e.path}.vue`), |
||||
meta |
||||
}) |
||||
} |
||||
e.children && e.children.length && createRoute(e.children) |
||||
}) |
||||
} |
||||
|
||||
export default function(data,path){ |
||||
generateBtnPermission(data) |
||||
createRoute(data) |
||||
store.dispatch('auth/addRoutes',newRoutes) |
||||
// router.addRoutes(routes)
|
||||
} |
@ -0,0 +1,26 @@ |
||||
import store from '@/store'; |
||||
import router from '@/router'; |
||||
|
||||
export default function(){ |
||||
setTimeout(() => { |
||||
let routes = store.state.auth.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,83 @@ |
||||
/** |
||||
* 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(key); |
||||
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,184 @@ |
||||
import cookies from './util.cookies' |
||||
import {_local,_session} from './util.db' |
||||
import { Message } from 'element-ui' |
||||
import store from '@/store' |
||||
import axios from 'axios' |
||||
import api from '@/api' |
||||
import Setting from '@/setting' |
||||
|
||||
let logout = false |
||||
const roleList = { |
||||
'1': '超级管理员', |
||||
'13': '管理员', |
||||
'14': '老师', |
||||
'4': '学生' |
||||
} |
||||
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;
|
||||
}, |
||||
// 移除数组中指定值
|
||||
removeByValue(arr, val) { |
||||
for(var i=0; i<arr.length; i++) { |
||||
if(arr[i] == val) { |
||||
arr.splice(i, 1); |
||||
break; |
||||
} |
||||
} |
||||
}, |
||||
// 传入文件后缀判断是否是视频
|
||||
isVideo(ext) { |
||||
if('mp4,3gp,mov,m4v,avi,dat,mkv,flv,vob,rmvb,rm,qlv'.includes(ext)) return true |
||||
return false |
||||
}, |
||||
// 传入文件后缀判断是否是音频
|
||||
isAudio(ext) { |
||||
if('mp3,aac,ape,flac,wav,wma,amr,mid'.includes(ext)) return true |
||||
return false |
||||
}, |
||||
// 传入文件后缀判断是否是图片
|
||||
isImg(ext) { |
||||
if('jpg,jpeg,png,gif,svg,psd'.includes(ext)) return true |
||||
return false |
||||
}, |
||||
// 传入文件后缀判断是否是pdf以外的文档
|
||||
isDoc(ext) { |
||||
if(!util.isVideo(ext) && !util.isAudio(ext) && !util.isImg(ext) && ext != 'pdf') return true |
||||
return false |
||||
}, |
||||
// 循环去除html标签
|
||||
removeHtmlTag(list,attr) { |
||||
list.map(n => { |
||||
n[attr] = n[attr].replace(/<\/?.+?>/gi,'') |
||||
}) |
||||
return list |
||||
}, |
||||
// 传入文件名获取文件后缀
|
||||
getFileExt(fileName) { |
||||
return fileName.substring(fileName.lastIndexOf('.') + 1) |
||||
}, |
||||
// 传入文件名和路径,下载图片视频,支持跨域,a标签加download不支持跨域
|
||||
downloadFile(fileName,url) { |
||||
var x = new XMLHttpRequest() |
||||
x.open("GET", url, true) |
||||
x.responseType = 'blob' |
||||
x.onload=function(e) { |
||||
var url = window.URL.createObjectURL(x.response) |
||||
var a = document.createElement('a') |
||||
a.href = url |
||||
a.download = fileName |
||||
a.click() |
||||
} |
||||
x.send() |
||||
}, |
||||
// 传入文件名和数据,下载文件
|
||||
downloadFileDirect(fileName,data) { |
||||
if ('download' in document.createElement('a')) { // 非IE下载
|
||||
const elink = document.createElement('a') |
||||
elink.download = fileName |
||||
elink.style.display = 'none' |
||||
elink.href = URL.createObjectURL(data) |
||||
document.body.appendChild(elink) |
||||
elink.click() |
||||
URL.revokeObjectURL(elink.href) // 释放URL 对象
|
||||
document.body.removeChild(elink) |
||||
} else { // IE10+下载
|
||||
navigator.msSaveBlob(data, fileName) |
||||
} |
||||
}, |
||||
// 传入字符串,返回去除[]后的字符串,因为通过get请求带入方括号的话会有问题
|
||||
encodeStr(str) { |
||||
if(str.includes('[') || str.includes(']')){ |
||||
let newStr = '' |
||||
for(let i of str){ |
||||
if(i == '[' || i == ']'){ |
||||
newStr += encodeURI(i) |
||||
}else{ |
||||
newStr += i |
||||
} |
||||
} |
||||
return newStr |
||||
} |
||||
return str |
||||
}, |
||||
// 成功提示
|
||||
successMsg(message,duration = 3000) { |
||||
return Message.success({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) |
||||
}, |
||||
// 警告提示
|
||||
warningMsg(message,duration = 3000) { |
||||
return Message.warning({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) |
||||
}, |
||||
// 错误提示
|
||||
errorMsg(message,duration = 3000) { |
||||
return Message.error({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) |
||||
}, |
||||
// 传入roleId,返回角色名称
|
||||
getRoleName(roleId){ |
||||
return roleList[roleId] || '未知状态' |
||||
}, |
||||
// 登录互踢
|
||||
getToken(){ |
||||
if(process.env.NODE_ENV != 'production'){ |
||||
if(store.state.user.dataTime && !logout){ |
||||
axios.get(`${api.queryToken}?token=${_local.get(Setting.tokenKey)}`).then(res => { |
||||
if(store.state.user.dataTime && (res.data.message != store.state.user.dataTime)){ |
||||
logout || Message.error('您已在另一台设备登录,本次登录已下线!') |
||||
logout = true |
||||
setTimeout(() => { |
||||
_local.remove(Setting.storeKey) |
||||
_local.remove(Setting.tokenKey) |
||||
location.reload() |
||||
},1500) |
||||
} |
||||
}).catch(err => {}) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
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 '@/styles/index.scss' |
||||
import VueI18n from 'vue-i18n'; |
||||
import mixinApp from '@/mixins/app'; |
||||
import { messages } from '@/i18n'; |
||||
import 'babel-polyfill'; |
||||
import '@/libs/resize'; |
||||
import {post,get,del,put} from '@/plugins/requests/index.js'; |
||||
import api from '@/api'; |
||||
import store from '@/store' |
||||
import Setting from '@/setting'; |
||||
import permission from '@/router/permission'; |
||||
|
||||
// 插件
|
||||
import plugins from '@/plugins'; |
||||
import filters from '@/plugins/filters' |
||||
|
||||
Vue.use(plugins); |
||||
|
||||
Object.keys(filters).forEach(item => Vue.filter(item,filters[item])) |
||||
|
||||
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, |
||||
i18n, |
||||
store, |
||||
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,201 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
<div class="header"> |
||||
<img class="logo hh" v-if="isHh" src="@/assets/img/logo-hh.png" /> |
||||
<img class="logo" v-else src="@/assets/img/logo.png" /> |
||||
</div> |
||||
|
||||
<div class="main"> |
||||
<div class="box"> |
||||
<el-tabs v-model="type"> |
||||
<el-tab-pane label="账号登录" name="0"> |
||||
<el-form :model="param" :rules="rules" ref="param" label-width="0px" style="margin-top: 40px"> |
||||
<el-form-item prop="username"> |
||||
<el-input v-model="param.username" placeholder="请输入账号"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="password"> |
||||
<el-input |
||||
type="password" |
||||
placeholder="请输入密码" |
||||
v-model="param.password" |
||||
@keyup.enter.native="submitForm('param')" |
||||
> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-button class="btn" type="primary" @click="submitForm('param')">马上登录</el-button> |
||||
</el-form> |
||||
</el-tab-pane> |
||||
|
||||
<el-tab-pane label="手机号/邮箱登录" name="1"> |
||||
<el-form :model="phoneParam" :rules="phoneRules" ref="phoneParam" label-width="0px" style="margin-top: 40px"> |
||||
<el-form-item prop="userphone"> |
||||
<el-input v-model="phoneParam.userphone" placeholder="请输入手机号/邮箱"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="phonePassword"> |
||||
<el-input |
||||
type="password" |
||||
placeholder="请输入密码" |
||||
v-model="phoneParam.phonePassword" |
||||
@keyup.enter.native="submitForm('phoneParam')" |
||||
> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-button class="btn" type="primary" @click="submitForm('phoneParam')">马上登录</el-button> |
||||
</el-form> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</div> |
||||
</div> |
||||
|
||||
<v-footer class="footer"></v-footer> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions } from 'vuex' |
||||
import vFooter from '@/layouts/footer' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data: function() { |
||||
return { |
||||
isHh: Setting.isHh, |
||||
param: { |
||||
username: '', |
||||
password: '' |
||||
}, |
||||
rules: { |
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], |
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], |
||||
}, |
||||
phoneParam: { |
||||
userphone: '', |
||||
phonePassword: '' |
||||
}, |
||||
phoneRules: { |
||||
userphone: [{ required: true, message: '请输入手机号/邮箱', trigger: 'blur' }], |
||||
phonePassword: [{ required: true, message: '请输入密码', trigger: 'blur' }], |
||||
}, |
||||
type: '0' |
||||
}; |
||||
}, |
||||
components: { |
||||
vFooter, |
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'login' |
||||
]), |
||||
submitForm(form) { |
||||
this.$refs[form].validate(valid => { |
||||
if (valid) { |
||||
let data = { |
||||
account: this.type == '0' ? this.param.username : this.phoneParam.userphone, |
||||
password: this.type == '0' ? this.param.password : this.phoneParam.phonePassword, |
||||
source: this.type |
||||
} |
||||
this.login(data).then(() => { |
||||
let redirect = this.$route.query.redirect ? decodeURIComponent(this.$route.query.redirect) : '/index' |
||||
this.$router.replace(redirect) |
||||
}).catch(res => {}) |
||||
} else { |
||||
return util.errorMsg('请输入账号和密码') |
||||
} |
||||
}); |
||||
}, |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.wrap{ |
||||
position: relative; |
||||
width: 100%; |
||||
height: 100%; |
||||
background-image: url(../../../assets/img/login-bg.png); |
||||
background-size: 100%; |
||||
.header{ |
||||
width: 100%; |
||||
height: 60px; |
||||
position: absolute; |
||||
top: 0; |
||||
left: 0; |
||||
background-color: #fff; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
font-size: 18px; |
||||
.logo{ |
||||
width: 150px; |
||||
margin-left: 20px; |
||||
&.hh{ |
||||
width: 220px; |
||||
} |
||||
} |
||||
} |
||||
/deep/.main{ |
||||
position: absolute; |
||||
left: 50%; |
||||
top: 42px; |
||||
transform: translate(-50%,0); |
||||
width: 1200px; |
||||
height: 82%; |
||||
margin-top: 60px; |
||||
background-image: url(../../../assets/img/login-input.png); |
||||
box-shadow:0px 0px 79px 0px rgba(11,15,65,0.36); |
||||
overflow: hidden; |
||||
.box { |
||||
width: 548px; |
||||
position: absolute; |
||||
left: 50%; |
||||
top: 50px; |
||||
transform: translate(-50%,0); |
||||
.el-tabs__nav-scroll{ |
||||
display: flex; |
||||
justify-content: center; |
||||
} |
||||
.el-tabs__nav-wrap::after{ |
||||
background-color: #fff; |
||||
opacity: 0; |
||||
.el-tabs__active-bar{ |
||||
background-color: #000; |
||||
border-radius:2px; |
||||
} |
||||
.el-tabs__item{ |
||||
padding: 0 90px; |
||||
color: #999; |
||||
&:hover{ |
||||
color: #000; |
||||
} |
||||
&.is-active{ |
||||
color: #333; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-input__inner{ |
||||
height: 80px; |
||||
line-height: 80px; |
||||
border:1px solid rgba(220,220,220,1); |
||||
border-radius:2px; |
||||
} |
||||
.btn { |
||||
width: 100%; |
||||
height: 88px; |
||||
margin-bottom: 50px; |
||||
font-weight: bold; |
||||
background:linear-gradient(90deg,rgba(94,206,253,1),rgba(91,67,231,1)); |
||||
box-shadow:0px 7px 27px 0px rgba(50,129,255,0.51); |
||||
border-radius:10px; |
||||
} |
||||
} |
||||
} |
||||
.footer{ |
||||
position: absolute; |
||||
bottom: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,299 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-10"> |
||||
<el-page-header @back="goBack" :content="experimentalName"></el-page-header> |
||||
</div> |
||||
<el-form label-width="100px"> |
||||
<div class="flex-between"> |
||||
<div></div> |
||||
<div> |
||||
<el-input placeholder="请输入学校/学生姓名" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</div> |
||||
</div> |
||||
</el-form> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="stat"> |
||||
<div class="nums"> |
||||
<div class="item"> |
||||
<p class="name">实验总人数</p> |
||||
<p class="val">{{total}}</p> |
||||
</div> |
||||
<div class="item"> |
||||
<p class="name">实验平均分</p> |
||||
<p class="val">{{avg}}</p> |
||||
</div> |
||||
</div> |
||||
<div class="chart" id="chart"></div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-20"> |
||||
<div></div> |
||||
<div> |
||||
<el-button type="primary" size="small" @click="delAllData">批量删除</el-button> |
||||
<el-button type="primary" size="small" @click="exportData">导出</el-button> |
||||
</div> |
||||
</div> |
||||
<el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="reportId"> |
||||
<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="schoolName" label="学校" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalName" label="考核名称" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{experimentalName}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column v-if="className" prop="class" label="班级" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userName" label="学生姓名" align="center"></el-table-column> |
||||
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column> |
||||
<el-table-column prop="score" label="分数" align="center"></el-table-column> |
||||
<el-table-column prop="submitTime" label="提交时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="220"> |
||||
<template slot-scope="scope"> |
||||
<!-- <el-button type="text" @click="edit(scope.row)">修改分数</el-button> --> |
||||
<el-button type="text" @click="show(scope.row)">查看成绩报告</el-button> |
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"> |
||||
</el-pagination> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import echarts from 'echarts' |
||||
export default { |
||||
data() { |
||||
return { |
||||
systemId: this.$route.query.systemId, |
||||
id: this.$route.query.id, |
||||
projectId: this.$route.query.projectId, |
||||
projectName: this.$route.query.name, |
||||
experimentalName: this.$route.query.experimentalName, |
||||
className: this.$route.query.class, |
||||
keyword: '', |
||||
listData: [], |
||||
multipleSelection: [], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
avg: 0, |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
systemId: this.systemId, |
||||
page: this.page, |
||||
size: this.pageSize, |
||||
searchContant: this.keyword, |
||||
projectId: this.id |
||||
} |
||||
this.$get(this.api.queryEvaluationReport,data).then(res => { |
||||
let list = res.data.list |
||||
let score = 0 |
||||
list.map(n => { |
||||
n.class = this.className |
||||
score += n.score |
||||
}) |
||||
this.listData = list |
||||
this.total = res.data.totalCount |
||||
this.avg = score ? (score / res.data.totalCount).toFixed(2) : 0 |
||||
this.getChart() |
||||
}).catch(res => {}); |
||||
}, |
||||
edit(row){ |
||||
if(this.systemId == 2 || this.systemId == 3){ |
||||
this.$router.push(`addexperiment?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else{ |
||||
this.$router.push(`addexperiment?id=${row.reportId}`) |
||||
} |
||||
}, |
||||
show(row){ |
||||
if(this.systemId == 2){ |
||||
this.$router.push(`showexperimentOption?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else if(this.systemId == 3){ |
||||
this.$router.push(`showexperimentOptions?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else{ |
||||
if(this.className){ |
||||
this.$router.push(`show?id=${row.recordId}&projectId=${this.id}&reportId=${row.reportId}&studentId=${row.studentId}`) |
||||
}else{ |
||||
this.$router.push(`show?id=${row.recordId}&type=1`) |
||||
} |
||||
} |
||||
}, |
||||
exportData(){ |
||||
if(!this.listData.length) return false |
||||
let selected = this.multipleSelection |
||||
let exportList = [] |
||||
if(selected.length){ |
||||
exportList = selected.map(item => { |
||||
return item.recordId |
||||
}) |
||||
}else{ |
||||
exportList = this.listData.map(item => { |
||||
return item.recordId |
||||
}) |
||||
} |
||||
window.open(`${this.api.exportAchievement}?ids=${exportList.join(',')}&projectId=${this.projectId}&source=2`) |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReport}?reportId=${row.reportId}&recordId=${row.recordId}`).then(res => { |
||||
this.$message.success('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return `reportId=${item.reportId}` |
||||
}) |
||||
let delList1 = newArr.map(item => { |
||||
return `recordId=${item.recordId}` |
||||
}) |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReport}?${delList.join('&')}&${delList1.join('&')}`).then(res => { |
||||
this.$message.success('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !') |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val; |
||||
this.getData(); |
||||
}, |
||||
getChart(){ |
||||
let data = [0,0,0,0,0,0,0,0,0,0] |
||||
let list = this.listData |
||||
list.map(n => { |
||||
n.score |
||||
if(n.score >= 0 && n.score <= 10){ |
||||
data[0]++ |
||||
}else if(n.score > 10 && n.score <= 20){ |
||||
data[1]++ |
||||
}else if(n.score > 20 && n.score <= 30){ |
||||
data[2]++ |
||||
}else if(n.score > 30 && n.score <= 40){ |
||||
data[3]++ |
||||
}else if(n.score > 40 && n.score <= 50){ |
||||
data[4]++ |
||||
}else if(n.score > 50 && n.score <= 60){ |
||||
data[5]++ |
||||
}else if(n.score > 60 && n.score <= 70){ |
||||
data[6]++ |
||||
}else if(n.score > 70 && n.score <= 80){ |
||||
data[7]++ |
||||
}else if(n.score > 80 && n.score <= 90){ |
||||
data[8]++ |
||||
}else if(n.score > 90 && n.score <= 100){ |
||||
data[9]++ |
||||
} |
||||
}) |
||||
let myChart = echarts.init(document.getElementById('chart')) |
||||
myChart.setOption({ |
||||
title: { text: '实验分数分布图' }, |
||||
tooltip: {}, |
||||
xAxis: { |
||||
name: '分数', |
||||
type: 'category', |
||||
boundaryGap: false, |
||||
data: ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61-70', '71-80','81-90','91-100'] |
||||
}, |
||||
yAxis: { |
||||
name: '人数', |
||||
type: 'value' |
||||
}, |
||||
series: [{ |
||||
data, |
||||
type: 'line', |
||||
areaStyle: {}, |
||||
color: ['#8191fd'] |
||||
}] |
||||
}) |
||||
}, |
||||
goBack() { |
||||
this.$router.back() |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.el-tabs__nav-wrap::after{ |
||||
display: none; |
||||
} |
||||
.stat{ |
||||
display: flex; |
||||
.nums { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-right: 20px; |
||||
.item:nth-child(1) { |
||||
background-image: url('../../../assets/img/total.png'); |
||||
} |
||||
.item:nth-child(2) { |
||||
background-image: url('../../../assets/img/avg.png'); |
||||
} |
||||
|
||||
.item { |
||||
width: 300px; |
||||
padding: 30px 30px; |
||||
margin: 0 10px; |
||||
box-sizing: border-box; |
||||
border-radius: 8px; |
||||
background-size: 100% 100%; |
||||
background-repeat: no-repeat; |
||||
p { |
||||
font-size: 18px; |
||||
color: #ffffff; |
||||
} |
||||
.val{ |
||||
margin-top: 10px; |
||||
color: #ffffff; |
||||
font-size: 36px; |
||||
} |
||||
} |
||||
} |
||||
.chart{ |
||||
flex: 1; |
||||
height: 300px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,368 @@ |
||||
<template> |
||||
<div> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="24"> |
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="flex-between"> |
||||
<div class="per_title" @click="goback()"> |
||||
<i class="el-icon-arrow-left"></i> |
||||
<span class="per_back">返回</span> |
||||
<span class="per_school">修改分数</span> |
||||
</div> |
||||
<div> |
||||
<el-button type="success" size="small" round class="mag" @click="saveAdd('form')">预览</el-button> |
||||
<el-button type="primary" size="small" round class="mag" @click="saveAdd('form')">发布成绩</el-button> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<h6 style="text-align: center;font-size: 20px">实验成绩报告</h6> |
||||
<div class="flex-center mgb20 user_header"> |
||||
<p class="addhr_tag"></p> |
||||
<span>基本信息</span> |
||||
</div> |
||||
|
||||
<div> |
||||
<el-table :data="infoData" class="table" stripe header-align="center"> |
||||
<el-table-column prop="projectName" label="实验名称" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="period" label="实验学时" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userName" label="学生姓名" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="number" label="学生学号" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="class" label="学生班级" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="content" label="实验内容" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="desc" label="实验数据与结果分析" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="result" label="实验结论" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experience" label="实验与心得体会" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="total" label="总分" align="center"> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">一、实验项目名称</p> |
||||
</div> |
||||
<el-input v-model="form.projectName" type="textarea" :disabled="true" rows="5"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">二、实验目的</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input v-model="form.experimentGoal" type="textarea" :disabled="true" rows="5"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">三、实验原理</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input v-model="form.principle" type="textarea" :disabled="true" rows="5"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">四、实验内容</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input v-model="form.content" type="textarea" :disabled="true" rows="5"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">五、实验步骤</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input v-model="form.step" type="textarea" :disabled="true" rows="5"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">六、实验数据</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-table :data="expData" class="table" stripe header-align="center"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.$index + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="module" label="模块" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="judgmentPointsName" label="考核点" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userAnswer" label="学生答案" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="answer" label="参考答案" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="codeScore" label="得分" align="center"> |
||||
</el-table-column> |
||||
</el-table> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">七、实验结论</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input type="textarea" v-model="form.conclusion" rows="5"></el-input> |
||||
<div class="flex-between" style="margin-top: 10px"> |
||||
<span>教师评分</span> |
||||
<div> |
||||
<el-input style="display: inline-block;width: auto;" placeholder="请输入"></el-input> (10分) |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">八、总结及心得体会</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input type="textarea" v-model="form.summarize" rows="5"></el-input> |
||||
<div class="flex-between" style="margin-top: 10px"> |
||||
<span>教师评分</span> |
||||
<div> |
||||
<el-input style="display: inline-block;width: auto;" placeholder="请输入"></el-input> (10分) |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">九、对本实验过程及方法、手段的改进建议</p> |
||||
<span>得分:50/60</span> |
||||
</div> |
||||
<el-input type="textarea" rows="5" v-model="form.improvement"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<div class="flex-between mgb20"> |
||||
<span>老师寄语</span> |
||||
</div> |
||||
<el-input type="textarea" rows="5"></el-input> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgb20"> |
||||
<p class="mgb20">教师签名</p> |
||||
<div class="mgb20"> |
||||
<el-radio v-model="autograph" label="1">不使用</el-radio> |
||||
<el-radio v-model="autograph" label="2">已有签名</el-radio> |
||||
<el-radio v-model="autograph" label="3">重新上传</el-radio> |
||||
</div> |
||||
<el-row v-if="autograph != 1"> |
||||
<el-col :span="6"> |
||||
<el-select class="sign-select" v-model="signId" placeholder="请选择签名" size="mini" v-show="autograph == 2"> |
||||
<el-option |
||||
v-for="item in signList" |
||||
:key="item.id" |
||||
:label="item.signatureName" |
||||
:value="item.id" |
||||
> |
||||
</el-option> |
||||
</el-select> |
||||
<el-upload |
||||
:data="{userId: userId}" |
||||
:limit="1" |
||||
:action="api.uploadSignature" |
||||
list-type="picture-card" |
||||
:on-remove="handleRemove" |
||||
:on-exceed="handleExceed" |
||||
:on-success="uploadSuccess"> |
||||
<i class="el-icon-plus"></i> |
||||
</el-upload> |
||||
</el-col> |
||||
</el-row> |
||||
</el-card> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data (){ |
||||
return { |
||||
userId: this.$store.state.userLoginId, |
||||
id: this.$route.query.id, |
||||
infoData: [], |
||||
accountData: [], |
||||
analysisContent: '', |
||||
showData: '1', |
||||
autograph: '1', |
||||
form: { |
||||
projectName: '', |
||||
period: '', |
||||
userName: '', |
||||
content: '', |
||||
conclusion: '', |
||||
score: '', |
||||
}, |
||||
pages: 1, |
||||
ipVisible: false, |
||||
configId : this.$store.state.configId, |
||||
keyword: '', |
||||
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}], |
||||
isEdit: false, |
||||
signList: [], |
||||
signId: '' |
||||
} |
||||
}, |
||||
mounted(){ |
||||
this.getData() |
||||
this.getSgin() |
||||
}, |
||||
methods: { |
||||
getData(){ |
||||
let data = { |
||||
// reportId: this.id |
||||
reportId: 97 |
||||
} |
||||
this.$get(this.api.queryReport,data).then(res => { |
||||
this.form = res.data.report |
||||
this.form.score = res.data.record.score |
||||
let form = this.form |
||||
this.infoData.push({ |
||||
projectName: form.projectName, |
||||
period: form.period, |
||||
userName: form.userName, |
||||
content: form.content, |
||||
conclusion: form.conclusion, |
||||
score: form.score, |
||||
analysis: form.analysis |
||||
}) |
||||
}).catch(res => {}); |
||||
}, |
||||
getSgin(){ |
||||
let data = { |
||||
userId: this.userId |
||||
} |
||||
this.$get(this.api.querySignature,data).then(res => { |
||||
this.signList = res.data |
||||
}).catch(res => {}); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
console.log(file, fileList); |
||||
}, |
||||
saveAdd(){ |
||||
let data = { |
||||
systemId: this.configId, |
||||
systemName: this.form.systemName, |
||||
systemType: this.form.systemType, |
||||
systemAttribution: this.form.systemAttribution, |
||||
} |
||||
if(this.configId){ |
||||
this.$post(this.api.updateServiceConfig,data).then((res) => { |
||||
util.successMsg('编辑成功'); |
||||
this.$router.back() |
||||
}).catch((res) => { |
||||
}) |
||||
}else{ |
||||
this.$post(this.api.updateServiceConfig,data).then((res) => { |
||||
util.successMsg('添加成功'); |
||||
this.$router.back() |
||||
}).catch((res) => { |
||||
}) |
||||
} |
||||
}, |
||||
SpanMethod({ row, column, rowIndex, columnIndex }) { |
||||
if (rowIndex % 2 === 0) { |
||||
if (columnIndex === 6) { |
||||
if(!row.Intranet){ |
||||
return [1, 2]; |
||||
} |
||||
} |
||||
// else if (columnIndex === 1) { |
||||
// return [0, 0]; |
||||
// } |
||||
} |
||||
}, |
||||
editMsg(){ |
||||
this.isEdit = true |
||||
}, |
||||
handleExceed(files, fileList) { |
||||
this.$message.warning( |
||||
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||
); |
||||
}, |
||||
uploadSuccess(res,file){ |
||||
if(res.status == 200){ |
||||
util.successMsg('上传成功') |
||||
this.getSgin() |
||||
}else{ |
||||
util.errorMsg(res.errmessage) |
||||
} |
||||
}, |
||||
goback() { |
||||
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$router.back() |
||||
}) |
||||
.catch(() => {}); |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.meta-title{ |
||||
margin-bottom: 10px; |
||||
font-size: 20px; |
||||
} |
||||
.step-title{ |
||||
margin-bottom: 10px; |
||||
font-size: 16px; |
||||
color: #9278ff; |
||||
} |
||||
.border_lf{ |
||||
border-left: 1px dashed #eee; |
||||
padding: 0 60px; |
||||
} |
||||
.border_lf label{ |
||||
width: 120px; |
||||
} |
||||
.pad_none{ |
||||
padding: 0 0 0 60px; |
||||
} |
||||
.edit-msg{ |
||||
font-size: 16px; |
||||
cursor: pointer; |
||||
} |
||||
.sign-select{ |
||||
/deep/.el-input{ |
||||
width: 150px; |
||||
margin-bottom: 10px; |
||||
} |
||||
} |
||||
.meta-title-wrap{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
} |
||||
.meta-title{ |
||||
margin-bottom: 10px; |
||||
font-size: 14px; |
||||
} |
||||
.step-title{ |
||||
margin-bottom: 10px; |
||||
font-size: 16px; |
||||
color: #9278ff; |
||||
} |
||||
.bd-title{ |
||||
padding-top: 20px; |
||||
border-top: 1px dashed #ccc; |
||||
} |
||||
</style> |
@ -0,0 +1,276 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<h6 class="p-title">筛选</h6> |
||||
<div class="tool mul"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>时间</label> |
||||
<el-radio-group size="small" v-model="month" @change="initData"> |
||||
<el-radio v-for="(item,index) in dateList" :key="index" :label="item.id" border>{{item.name}}</el-radio> |
||||
</el-radio-group> |
||||
<el-date-picker size="small" 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> |
||||
</li> |
||||
<li> |
||||
<label>实验项目分类</label> |
||||
<el-radio-group size="small" v-model="projectPermissions" @change="initData"> |
||||
<el-radio v-for="(item,index) in projectType" :key="index" :label="item.id" border>{{item.name}}</el-radio> |
||||
</el-radio-group> |
||||
</li> |
||||
<li> |
||||
<label>系统</label> |
||||
<el-select size="small" v-model="systemId" placeholder="请选择" @change="initData"> |
||||
<el-option |
||||
v-for="item in systemList" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.id" |
||||
></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<el-input size="small" placeholder="请输入实验项目名称/班级名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" @click="delAllData">批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="selection" width="55" align="center" :reserve-selection="true" :selectable="disabledSelection"></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> |
||||
<template v-if="projectPermissions == 1"> |
||||
<el-table-column prop="experimentalClassName" label="班级" align="center"></el-table-column> |
||||
<el-table-column prop="experimentalName" label="实验名称" align="center"></el-table-column> |
||||
</template> |
||||
<el-table-column prop="projectName" label="项目名称" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="projectPermissions" label="分类" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.row.projectPermissions == 2 ? '竞赛' : projectType.find(n => n.id === scope.row.projectPermissions).name}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="number" label="成绩报告数量" align="center"></el-table-column> |
||||
<el-table-column prop="creationTime" label="创建时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="entry(scope.row)" v-auth>成绩管理</el-button> |
||||
<el-button type="text" @click="handleDelete(scope.row)" :disabled="!scope.row.isdel">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"></el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState, mapActions } from 'vuex' |
||||
import { Loading } from 'element-ui' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
name: 'achievement', |
||||
data() { |
||||
return { |
||||
systemId: '', |
||||
systemList: Setting.systemList, |
||||
projectPermissions: this.$route.query.per ? Number(this.$route.query.per) : 0, |
||||
keyword: '', |
||||
startingtime: '', |
||||
endTime: '', |
||||
month: '', |
||||
listData: [], |
||||
multipleSelection: [], |
||||
dateList: [ |
||||
{ |
||||
id: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '近一个月' |
||||
}, |
||||
{ |
||||
id: 6, |
||||
name: '近六个月' |
||||
} |
||||
], |
||||
projectType: [ |
||||
{ |
||||
id: 0, |
||||
name: '练习' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '考核' |
||||
} |
||||
], |
||||
date: '', |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
loadIns: null, |
||||
listDataAll: [] |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId' |
||||
]), |
||||
...mapState('project', [ |
||||
'lastSystemId' |
||||
]), |
||||
}, |
||||
watch: { |
||||
month: function(val){ |
||||
if(val){ |
||||
let unit = 24 * 60 * 60 * 1000 |
||||
this.date = [util.formatDate('yyyy-MM-dd',new Date(new Date().getTime() - unit * 30 * val)),util.formatDate('yyyy-MM-dd',new Date(new Date().getTime() + unit))] |
||||
}else{ |
||||
this.date = [] |
||||
} |
||||
}, |
||||
date: function(val){ |
||||
if(val){ |
||||
this.startingtime = val[0] |
||||
this.endTime = val[1] |
||||
}else{ |
||||
this.startingtime = '' |
||||
this.endTime = '' |
||||
} |
||||
this.initData() |
||||
}, |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.systemId = this.lastSystemId ? this.lastSystemId : Setting.systemId |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
...mapActions('project', [ |
||||
'setSystemId' |
||||
]), |
||||
getData() { |
||||
this.loadIns = Loading.service({ |
||||
background: 'rgba(255,255,255,.6)' |
||||
}) |
||||
let data = { |
||||
searchContant: util.encodeStr(this.keyword), |
||||
startTime: this.startingtime, |
||||
endTime: this.endTime, |
||||
month: this.month, |
||||
page: this.page, |
||||
size: this.pageSize, |
||||
userId: this.userId |
||||
} |
||||
let url = this.api.queryAchievement |
||||
if(this.projectPermissions){ |
||||
data.systemId = this.systemId |
||||
url = this.api.queryAchievementNew |
||||
}else{ |
||||
data.systemId = this.systemId |
||||
data.projectPermissions = this.projectPermissions |
||||
} |
||||
this.$get(url,data).then(res => { |
||||
this.listData = res.data.list |
||||
this.total = res.data.total |
||||
this.$nextTick(() => { |
||||
this.loadIns.close() |
||||
}) |
||||
}).catch(res => { |
||||
this.loadIns.close() |
||||
}) |
||||
}, |
||||
handlePage(){ |
||||
let list = this.listDataAll |
||||
let result = [] |
||||
list.map(n => { |
||||
if(!n.projectHiddenEntity) result.push(n) |
||||
}) |
||||
this.listData = result.slice((this.page - 1) * this.pageSize,this.page * this.pageSize) |
||||
this.total = result.length |
||||
}, |
||||
initData(){ |
||||
this.$refs.table.clearSelection() |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
disabledSelection(row,index){ |
||||
if(row.isdel == 0) return false |
||||
return true |
||||
}, |
||||
entry(row){ |
||||
this.setSystemId(this.systemId) |
||||
if(this.projectPermissions){ |
||||
this.$router.push(`teach?id=${row.id}&name=${row.experimentalName}&class=${row.experimentalClassName}&projectId=${row.projectId}&systemId=${this.systemId}`) |
||||
}else{ |
||||
this.$router.push(`vir?id=${row.projectId}&name=${row.projectName}&class=${row.experimentalClassName}&systemId=${this.systemId}`) |
||||
} |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('该项目下的所有成绩报告将会删除,是否继续?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReportById}?projectIds=${row.projectId}&projectPermissions=${row.projectPermissions}&ids=${row.id ? row.id : ''}`).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}) |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return `projectIds=${item.projectId}` |
||||
}) |
||||
let delList1 = newArr[0].id ? newArr.map(item => { |
||||
return `ids=${item.id}` |
||||
}) : [] |
||||
|
||||
this.$confirm('该项目下的所有成绩报告将会删除,是否继续?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = `${delList.join('&')}&projectPermissions=${this.projectPermissions}&${delList1.length ? delList1.join('&') : ''}` |
||||
this.$post(`${this.api.deleteReportById}?${data}`).then(res => { |
||||
this.multipleSelection = []; |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}) |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !') |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val |
||||
this.getData() |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.el-radio.is-bordered+.el-radio.is-bordered{ |
||||
margin-left: 0; |
||||
} |
||||
</style> |
@ -0,0 +1,419 @@ |
||||
<template> |
||||
<div class="box"> |
||||
<el-row :gutter="24"> |
||||
<el-col :span="24"> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" content="查看报告"></el-page-header> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<div id="pdfDom"> |
||||
<h6 style="text-align: center;font-size: 20px">标准实验报告</h6> |
||||
<div class="flex-center m-b-20 user_header"> |
||||
<p class="addhr_tag"></p> |
||||
<span style="font-size: 18px">基本信息</span> |
||||
</div> |
||||
|
||||
<div> |
||||
<el-table :data="infoData" class="info-table" stripe header-align="center"> |
||||
<el-table-column prop="userName" label="学生姓名" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="workNumber" label="学生学号" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalClassName" label="学生班级" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="instructor" label="指导老师" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="period" label="实验学时" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="submitTime" label="实验时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="score" label="实验成绩" align="center"> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
|
||||
<div class="m-b-20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title"><img src="@/assets/img/cup.png" alt=""> 实验项目名称</p> |
||||
</div> |
||||
<el-input v-model="form.proName" type="textarea" :disabled="true" rows="5"></el-input> |
||||
</div> |
||||
|
||||
<div class="m-b-20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">实验目的</p> |
||||
</div> |
||||
<!-- <el-input v-model="form.purpose" type="textarea" :disabled="true" rows="5"></el-input> --> |
||||
<div class="pre-wrap" v-html="form.purpose"></div> |
||||
</div> |
||||
|
||||
<div class="m-b-20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">实验数据</p> |
||||
</div> |
||||
<el-table :data="expData" class="table" stripe header-align="center"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.$index + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="judgmentPointsName" label="任务名称" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userAnswer" label="学生答案" align="center"> |
||||
<template slot-scope="scope"> |
||||
<pre v-html="scope.row.userAnswer" style="white-space: pre-wrap"></pre> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="answer" label="参考答案" align="center"> |
||||
<template slot-scope="scope"> |
||||
<pre v-html="scope.row.answer" style="white-space: pre-wrap"></pre> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="codeScore" label="得分" align="center"> |
||||
</el-table-column> |
||||
</el-table> |
||||
</div> |
||||
|
||||
<div class="m-b-20"> |
||||
<div class="meta-title-wrap"> |
||||
<p class="meta-title">实验总结与体会</p> |
||||
</div> |
||||
<el-input type="textarea" v-model="form.summarize" rows="5" disabled></el-input> |
||||
</div> |
||||
</div> |
||||
</el-col> |
||||
</el-row> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState, mapActions } from 'vuex' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data (){ |
||||
return { |
||||
title: '实验报告', |
||||
form: { |
||||
analysis: '', |
||||
conclusion: '', |
||||
content: ``, |
||||
data: '', |
||||
purpose: ``, |
||||
experimentId: '', |
||||
experimentalClassName: '', |
||||
improvement: '', |
||||
laboratory: '', |
||||
period: '', |
||||
principle: '', |
||||
proName: '', |
||||
score: 0, |
||||
step: ``, |
||||
submitTime: '', |
||||
summarize: '', |
||||
instructor: '', |
||||
userId: this.userId, |
||||
userName: '', |
||||
workNumber: '', |
||||
}, |
||||
type: this.$route.query.type, |
||||
id: this.$route.query.id, |
||||
recordId: this.$route.query.recordId, |
||||
reportId: this.$route.query.reportId, |
||||
projectId: this.$route.query.projectId, |
||||
studentId: this.$route.query.studentId, |
||||
infoData: [], |
||||
expData: [], |
||||
accountData: [], |
||||
showData: '1', |
||||
autograph: '1', |
||||
pages: 1, |
||||
ipVisible: false, |
||||
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}], |
||||
conclusionOptions: [ |
||||
{ |
||||
value: 1, |
||||
label: '结论符合预期' |
||||
} |
||||
], |
||||
} |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId' |
||||
]), |
||||
}, |
||||
mounted(){ |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData(){ |
||||
if(this.type){ |
||||
let data = { |
||||
recordId: this.id, |
||||
} |
||||
this.$get(this.api.queryVirtualReport,data).then(res => { |
||||
this.form = res.data.report |
||||
let expData = res.data.data |
||||
let form = this.form |
||||
let score = form.score |
||||
|
||||
if(expData){ |
||||
if(score){ |
||||
expData.map(n => { |
||||
if(n.isError){ |
||||
score -= n.codeScore |
||||
n.codeScore = 0 |
||||
} |
||||
}) |
||||
form.score = score |
||||
} |
||||
|
||||
this.expData = expData |
||||
} |
||||
|
||||
this.infoData.push({ |
||||
workNumber: form.workNumber, |
||||
experimentalClassName: form.experimentalClassName, |
||||
instructor: form.instructor, |
||||
period: form.period, |
||||
laboratory: form.laboratory, |
||||
submitTime: form.submitTime, |
||||
score: form.score, |
||||
userName: form.userName |
||||
}) |
||||
}).catch(res => {}); |
||||
}else{ |
||||
let data = { |
||||
studentId: this.studentId, |
||||
projectId: this.projectId, |
||||
recordId: this.id, |
||||
reportId: this.reportId |
||||
} |
||||
this.$get(this.api.queryArchievement,data).then(res => { |
||||
this.form = res.data.report ? res.data.report : {} |
||||
let expData = res.data.data |
||||
let form = this.form |
||||
let score = form.score |
||||
|
||||
if(expData){ |
||||
if(score){ |
||||
expData.map(n => { |
||||
if(n.isError){ |
||||
score -= n.codeScore |
||||
n.codeScore = 0 |
||||
} |
||||
}) |
||||
form.score = score |
||||
} |
||||
|
||||
this.expData = expData |
||||
} |
||||
this.infoData.push({ |
||||
workNumber: form.workNumber, |
||||
experimentalClassName: form.experimentalClassName, |
||||
instructor: form.instructor, |
||||
period: form.period, |
||||
laboratory: form.laboratory, |
||||
submitTime: form.submitTime, |
||||
score: form.score, |
||||
userName: form.userName |
||||
}) |
||||
}).catch(res => {}); |
||||
} |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
console.log(file, fileList); |
||||
}, |
||||
handlePreview(file) { |
||||
console.log(file); |
||||
}, |
||||
saveAdd(){ |
||||
let data = { |
||||
systemId: this.configId, |
||||
systemName: this.form.systemName, |
||||
systemType: this.form.systemType, |
||||
systemAttribution: this.form.systemAttribution, |
||||
} |
||||
if(this.configId){ |
||||
this.$post(this.api.updateServiceConfig,data).then((res) => { |
||||
util.successMsg('编辑成功'); |
||||
this.goBack() |
||||
}).catch((res) => { |
||||
}) |
||||
}else{ |
||||
this.$post(this.api.updateServiceConfig,data).then((res) => { |
||||
util.successMsg('添加成功'); |
||||
this.goBack() |
||||
}).catch((res) => { |
||||
}) |
||||
} |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
console.log(file, fileList); |
||||
}, |
||||
handlePictureCardPreview(file) { |
||||
this.dialogImageUrl = file.url; |
||||
this.dialogVisible = true; |
||||
}, |
||||
SpanMethod({ row, column, rowIndex, columnIndex }) { |
||||
if (rowIndex % 2 === 0) { |
||||
if (columnIndex === 6) { |
||||
if(!row.Intranet){ |
||||
return [1, 2]; |
||||
} |
||||
} |
||||
// else if (columnIndex === 1) { |
||||
// return [0, 0]; |
||||
// } |
||||
} |
||||
}, |
||||
goBack(){ |
||||
this.$router.go(-1) |
||||
}, |
||||
exportPage(){ |
||||
var title = this.title; |
||||
html2Canvas(document.querySelector('#pdfDom'), { |
||||
allowTaint: true |
||||
}).then(function (canvas) { |
||||
let contentWidth = canvas.width |
||||
let contentHeight = canvas.height |
||||
let pageHeight = contentWidth / 592.28 * 841.89 |
||||
let leftHeight = contentHeight |
||||
let position = 0 |
||||
let imgWidth = 595.28 |
||||
let imgHeight = 592.28 / contentWidth * contentHeight |
||||
let pageData = canvas.toDataURL('image/jpeg', 1.0) |
||||
let PDF = new JsPDF('', 'pt', 'a4') |
||||
if (leftHeight < pageHeight) { |
||||
PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight) |
||||
} else { |
||||
while (leftHeight > 0) { |
||||
PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) |
||||
leftHeight -= pageHeight |
||||
position -= 841.89 |
||||
if (leftHeight > 0) { |
||||
PDF.addPage() |
||||
} |
||||
} |
||||
} |
||||
PDF.save(title + '.pdf') |
||||
} |
||||
) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.box{ |
||||
padding: 0 50px; |
||||
background-color: #fff; |
||||
} |
||||
/deep/.el-textarea.is-disabled .el-textarea__inner{ |
||||
color: #777; |
||||
background-color: #e5dfff; |
||||
} |
||||
.pre-wrap{ |
||||
min-height: 117px; |
||||
padding: 5px 15px; |
||||
color: #777; |
||||
background-color: #e5dfff; |
||||
} |
||||
#pdfDom{ |
||||
padding: 50px; |
||||
/deep/.info-table{ |
||||
margin-bottom: 40px; |
||||
border: 0; |
||||
th{ |
||||
background-color: #fff !important; |
||||
.cell{ |
||||
color: #444; |
||||
} |
||||
} |
||||
tr{ |
||||
border: 0; |
||||
} |
||||
tr:hover,tr:hover>td{ |
||||
background-color: #e5dfff !important; |
||||
} |
||||
td{ |
||||
border: { |
||||
left: 4px solid #fff; |
||||
right: 4px solid #fff; |
||||
} |
||||
&:first-child{ |
||||
border-left: 0; |
||||
} |
||||
&:last-child{ |
||||
border-right: 0; |
||||
} |
||||
background-color: #e5dfff; |
||||
border-bottom: 0; |
||||
} |
||||
} |
||||
/deep/.table th{ |
||||
background-color: #e1eaff !important; |
||||
.cell{ |
||||
color: #555555; |
||||
} |
||||
} |
||||
} |
||||
|
||||
/deep/.cell{ |
||||
font-size: 12px; |
||||
} |
||||
/deep/.el-row{ |
||||
padding-top: 20px; |
||||
margin: 0 !important; |
||||
} |
||||
.form-item{ |
||||
display: flex; |
||||
align-items: center; |
||||
} |
||||
.form-item .el-input{ |
||||
width: auto; |
||||
} |
||||
.form-item span{ |
||||
margin-right: 10px; |
||||
} |
||||
.meta-title-wrap{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
span{ |
||||
font-size: 13px; |
||||
color: #444; |
||||
} |
||||
} |
||||
.flex-between{ |
||||
span{ |
||||
font-size: 13px; |
||||
color: #444; |
||||
} |
||||
} |
||||
.meta-title{ |
||||
display: flex; |
||||
align-items: center; |
||||
padding: 10px 20px; |
||||
margin-bottom: 10px; |
||||
font-size: 16px; |
||||
color: #fff; |
||||
background-color: #9278ff; |
||||
img{ |
||||
width: 20px; |
||||
margin-right: 10px; |
||||
} |
||||
} |
||||
.step-title{ |
||||
margin-bottom: 10px; |
||||
font-size: 16px; |
||||
color: #9278ff; |
||||
} |
||||
.bd-title{ |
||||
padding-top: 20px; |
||||
border-top: 1px dashed #ccc; |
||||
} |
||||
</style> |
@ -0,0 +1,304 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-10"> |
||||
<el-page-header @back="goBack" :content="experimentalName"></el-page-header> |
||||
</div> |
||||
<el-form label-width="100px"> |
||||
<div class="flex-between"> |
||||
<div></div> |
||||
<div> |
||||
<el-input size="small" placeholder="请输入学校/学生姓名" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</div> |
||||
</div> |
||||
</el-form> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="stat"> |
||||
<div class="nums"> |
||||
<div class="item"> |
||||
<p class="name">实验总人数</p> |
||||
<p class="val">{{total}}</p> |
||||
</div> |
||||
<div class="item"> |
||||
<p class="name">实验平均分</p> |
||||
<p class="val">{{avg}}</p> |
||||
</div> |
||||
</div> |
||||
<div class="chart" id="chart"></div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-20"> |
||||
<div> |
||||
|
||||
</div> |
||||
<div> |
||||
<el-button type="primary" size="small" @click="delAllData">批量删除</el-button> |
||||
<el-button type="primary" size="small" @click="exportData">导出</el-button> |
||||
</div> |
||||
</div> |
||||
<el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="reportId"> |
||||
<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="schoolName" label="学校" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalName" label="考核名称" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{experimentalName}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column v-if="className" prop="class" label="班级" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userName" label="学生姓名" align="center"></el-table-column> |
||||
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column> |
||||
<el-table-column prop="score" label="分数" align="center"></el-table-column> |
||||
<el-table-column prop="submitTime" label="提交时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="220"> |
||||
<template slot-scope="scope"> |
||||
<!-- <el-button type="text" @click="edit(scope.row)">修改分数</el-button> --> |
||||
<el-button type="text" @click="show(scope.row)">查看成绩报告</el-button> |
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"> |
||||
</el-pagination> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import echarts from 'echarts' |
||||
export default { |
||||
data() { |
||||
return { |
||||
systemId: this.$route.query.systemId, |
||||
id: this.$route.query.id, |
||||
experimentalName: this.$route.query.name, |
||||
className: this.$route.query.class, |
||||
projectId: this.$route.query.projectId, |
||||
keyword: '', |
||||
listDataAll: [], |
||||
listData: [], |
||||
multipleSelection: [], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
avg: 0, |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
id: this.id |
||||
} |
||||
this.$get(this.api.getTeachAchievement,data).then(res => { |
||||
let list = res.data |
||||
let score = 0 |
||||
list.map(n => { |
||||
n.class = this.className |
||||
score += n.score |
||||
}) |
||||
this.listDataAll = list |
||||
this.handlePage() |
||||
this.total = list.length |
||||
this.avg = score ? (score / list.length).toFixed(2) : 0 |
||||
this.getChart() |
||||
}).catch(res => {}); |
||||
}, |
||||
handlePage(){ |
||||
let list = this.listDataAll |
||||
this.listData = list.slice((this.page - 1) * this.pageSize,this.page * this.pageSize) |
||||
this.total = list.length |
||||
}, |
||||
edit(row){ |
||||
if(this.systemId == 2 || this.systemId == 3){ |
||||
this.$router.push(`addexperiment?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else{ |
||||
this.$router.push(`addexperiment?id=${row.reportId}`) |
||||
} |
||||
}, |
||||
show(row){ |
||||
if(this.systemId == 2){ |
||||
this.$router.push(`showexperimentOption?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else if(this.systemId == 3){ |
||||
this.$router.push(`showexperimentOptions?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else{ |
||||
if(this.className){ |
||||
this.$router.push(`show?id=${row.recordId}&projectId=${row.projectId}&reportId=${row.reportId}&studentId=${row.studentId}`) |
||||
}else{ |
||||
this.$router.push(`show?id=${row.recordId}&type=1`) |
||||
} |
||||
} |
||||
}, |
||||
exportData(){ |
||||
if(!this.listData.length) return false |
||||
let selected = this.multipleSelection |
||||
let exportList = [] |
||||
if(selected.length){ |
||||
exportList = selected.map(item => { |
||||
return item.recordId |
||||
}) |
||||
}else{ |
||||
exportList = this.listData.map(item => { |
||||
return item.recordId |
||||
}) |
||||
} |
||||
console.log(exportList.join(','),this.id,this.projectId) |
||||
window.open(`${this.api.exportAchievement}?ids=${exportList.join(',')}&projectId=${this.projectId}&source=2`) |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReport}?reportId=${row.reportId}&recordId=${row.recordId}`).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return `reportId=${item.reportId}` |
||||
}) |
||||
let delList1 = newArr.map(item => { |
||||
return `recordId=${item.recordId}` |
||||
}) |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReport}?${delList.join('&')}&${delList1.join('&')}`).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !') |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val; |
||||
this.handlePage(); |
||||
}, |
||||
getChart(){ |
||||
let data = [0,0,0,0,0,0,0,0,0,0] |
||||
let list = this.listData |
||||
list.map(n => { |
||||
n.score |
||||
if(n.score >= 0 && n.score <= 10){ |
||||
data[0]++ |
||||
}else if(n.score > 10 && n.score <= 20){ |
||||
data[1]++ |
||||
}else if(n.score > 20 && n.score <= 30){ |
||||
data[2]++ |
||||
}else if(n.score > 30 && n.score <= 40){ |
||||
data[3]++ |
||||
}else if(n.score > 40 && n.score <= 50){ |
||||
data[4]++ |
||||
}else if(n.score > 50 && n.score <= 60){ |
||||
data[5]++ |
||||
}else if(n.score > 60 && n.score <= 70){ |
||||
data[6]++ |
||||
}else if(n.score > 70 && n.score <= 80){ |
||||
data[7]++ |
||||
}else if(n.score > 80 && n.score <= 90){ |
||||
data[8]++ |
||||
}else if(n.score > 90 && n.score <= 100){ |
||||
data[9]++ |
||||
} |
||||
}) |
||||
let myChart = echarts.init(document.getElementById('chart')) |
||||
myChart.setOption({ |
||||
title: { text: '实验分数分布图' }, |
||||
tooltip: {}, |
||||
xAxis: { |
||||
name: '分数', |
||||
type: 'category', |
||||
boundaryGap: false, |
||||
data: ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61-70', '71-80','81-90','91-100'] |
||||
}, |
||||
yAxis: { |
||||
name: '人数', |
||||
type: 'value' |
||||
}, |
||||
series: [{ |
||||
data, |
||||
type: 'line', |
||||
areaStyle: {}, |
||||
color: ['#8191fd'] |
||||
}] |
||||
}) |
||||
}, |
||||
goBack() { |
||||
this.$router.push('list?per=1') |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.el-tabs__nav-wrap::after{ |
||||
display: none; |
||||
} |
||||
.stat{ |
||||
display: flex; |
||||
.nums { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-right: 20px; |
||||
.item:nth-child(1) { |
||||
background-image: url('../../../assets/img/total.png'); |
||||
} |
||||
.item:nth-child(2) { |
||||
background-image: url('../../../assets/img/avg.png'); |
||||
} |
||||
|
||||
.item { |
||||
width: 300px; |
||||
padding: 30px 30px; |
||||
margin: 0 10px; |
||||
box-sizing: border-box; |
||||
border-radius: 8px; |
||||
background-size: 100% 100%; |
||||
background-repeat: no-repeat; |
||||
p { |
||||
font-size: 18px; |
||||
color: #ffffff; |
||||
} |
||||
.val{ |
||||
margin-top: 10px; |
||||
color: #ffffff; |
||||
font-size: 36px; |
||||
} |
||||
} |
||||
} |
||||
.chart{ |
||||
flex: 1; |
||||
height: 300px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,297 @@ |
||||
<template> |
||||
<div> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-10"> |
||||
<el-page-header @back="goBack" :content="experimentName"></el-page-header> |
||||
</div> |
||||
<el-form label-width="100px"> |
||||
<div class="flex-between"> |
||||
<div></div> |
||||
<div> |
||||
<el-input size="small" placeholder="请输入学校/学生姓名" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</div> |
||||
</div> |
||||
</el-form> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="stat"> |
||||
<div class="nums"> |
||||
<div class="item"> |
||||
<p class="name">实验总人数</p> |
||||
<p class="val">{{total}}</p> |
||||
</div> |
||||
<div class="item"> |
||||
<p class="name">实验平均分</p> |
||||
<p class="val">{{avg}}</p> |
||||
</div> |
||||
</div> |
||||
<div class="chart" id="chart"></div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-20"> |
||||
<div> |
||||
|
||||
</div> |
||||
<div> |
||||
<el-button type="primary" size="small" @click="delAllData">批量删除</el-button> |
||||
<el-button type="primary" size="small" @click="exportData">导出</el-button> |
||||
</div> |
||||
</div> |
||||
<el-table :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="reportId"> |
||||
<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="schoolName" label="学校" align="center"> |
||||
</el-table-column> |
||||
<el-table-column v-if="className" prop="class" label="班级" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userName" label="学生姓名" align="center"></el-table-column> |
||||
<el-table-column prop="workNumber" label="学号" align="center"></el-table-column> |
||||
<el-table-column prop="score" label="分数" align="center"></el-table-column> |
||||
<el-table-column prop="submitTime" label="提交时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="220"> |
||||
<template slot-scope="scope"> |
||||
<!-- <el-button type="text" @click="edit(scope.row)">修改分数</el-button> --> |
||||
<el-button type="text" @click="show(scope.row)">查看成绩报告</el-button> |
||||
<el-button type="text" @click="handleDelete(scope.row)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"> |
||||
</el-pagination> |
||||
</div> |
||||
</el-card> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import echarts from 'echarts' |
||||
export default { |
||||
data() { |
||||
return { |
||||
systemId: this.$route.query.systemId, |
||||
projectId: this.$route.query.id, |
||||
experimentName: this.$route.query.name, |
||||
className: this.$route.query.class, |
||||
keyword: '', |
||||
listDataAll: [], |
||||
listData: [], |
||||
multipleSelection: [], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
avg: 0, |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
projectId: this.projectId |
||||
} |
||||
this.$get(this.api.getImitationAchievement,data).then(res => { |
||||
let list = res.data |
||||
let score = 0 |
||||
list.map(n => { |
||||
n.class = this.className |
||||
score += n.score |
||||
}) |
||||
this.listDataAll = list |
||||
this.handlePage() |
||||
this.total = list.length |
||||
this.avg = score ? (score / list.length).toFixed(2) : 0 |
||||
this.getChart() |
||||
}).catch(res => {}); |
||||
}, |
||||
handlePage(){ |
||||
let list = this.listDataAll |
||||
this.listData = list.slice((this.page - 1) * this.pageSize,this.page * this.pageSize) |
||||
this.total = list.length |
||||
}, |
||||
edit(row){ |
||||
if(this.systemId == 2 || this.systemId == 3){ |
||||
this.$router.push(`addexperiment?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else{ |
||||
this.$router.push(`addexperiment?id=${row.reportId}`) |
||||
} |
||||
}, |
||||
show(row){ |
||||
if(this.systemId == 2){ |
||||
this.$router.push(`showexperimentOption?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else if(this.systemId == 3){ |
||||
this.$router.push(`showexperimentOptions?id=${row.reportId}&stuId=${row.userId}&studentName=${row.studentName}&class=${row.class}`) |
||||
}else{ |
||||
if(this.class){ |
||||
this.$router.push(`show?id=${row.recordId}&projectId=${this.projectId}&reportId=${row.reportId}`) |
||||
}else{ |
||||
this.$router.push(`show?id=${row.recordId}&type=1`) |
||||
} |
||||
} |
||||
}, |
||||
exportData(){ |
||||
if(!this.listData.length) return false |
||||
let selected = this.multipleSelection |
||||
let exportList = [] |
||||
if(selected.length){ |
||||
exportList = selected.map(item => { |
||||
return item.recordId |
||||
}) |
||||
}else{ |
||||
exportList = this.listData.map(item => { |
||||
return item.recordId |
||||
}) |
||||
} |
||||
window.open(`${this.api.exportAchievement}?ids=${exportList.join(',')}&projectId=${this.projectId}&source=1`) |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReport}?reportId=${row.reportId}&recordId=${row.recordId}`).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return `reportId=${item.reportId}` |
||||
}) |
||||
let delList1 = newArr.map(item => { |
||||
return `recordId=${item.recordId}` |
||||
}) |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(`${this.api.deleteReport}?${delList.join('&')}&${delList1.join('&')}`).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val; |
||||
this.handlePage(); |
||||
}, |
||||
getChart(){ |
||||
let data = [0,0,0,0,0,0,0,0,0,0] |
||||
let list = this.listData |
||||
list.map(n => { |
||||
n.score |
||||
if(n.score >= 0 && n.score <= 10){ |
||||
data[0]++ |
||||
}else if(n.score > 10 && n.score <= 20){ |
||||
data[1]++ |
||||
}else if(n.score > 20 && n.score <= 30){ |
||||
data[2]++ |
||||
}else if(n.score > 30 && n.score <= 40){ |
||||
data[3]++ |
||||
}else if(n.score > 40 && n.score <= 50){ |
||||
data[4]++ |
||||
}else if(n.score > 50 && n.score <= 60){ |
||||
data[5]++ |
||||
}else if(n.score > 60 && n.score <= 70){ |
||||
data[6]++ |
||||
}else if(n.score > 70 && n.score <= 80){ |
||||
data[7]++ |
||||
}else if(n.score > 80 && n.score <= 90){ |
||||
data[8]++ |
||||
}else if(n.score > 90 && n.score <= 100){ |
||||
data[9]++ |
||||
} |
||||
}) |
||||
let myChart = echarts.init(document.getElementById('chart')) |
||||
myChart.setOption({ |
||||
title: { text: '实验分数分布图' }, |
||||
tooltip: {}, |
||||
xAxis: { |
||||
name: '分数', |
||||
type: 'category', |
||||
boundaryGap: false, |
||||
data: ['0-10', '11-20', '21-30', '31-40', '41-50', '51-60', '61-70', '71-80','81-90','91-100'] |
||||
}, |
||||
yAxis: { |
||||
name: '人数', |
||||
type: 'value' |
||||
}, |
||||
series: [{ |
||||
data, |
||||
type: 'line', |
||||
areaStyle: {}, |
||||
color: ['#8191fd'] |
||||
}] |
||||
}) |
||||
}, |
||||
goBack() { |
||||
this.$router.back() |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.el-tabs__nav-wrap::after{ |
||||
display: none; |
||||
} |
||||
.stat{ |
||||
display: flex; |
||||
.nums { |
||||
display: flex; |
||||
align-items: center; |
||||
margin-right: 20px; |
||||
.item:nth-child(1) { |
||||
background-image: url('../../../assets/img/total.png'); |
||||
} |
||||
.item:nth-child(2) { |
||||
background-image: url('../../../assets/img/avg.png'); |
||||
} |
||||
|
||||
.item { |
||||
width: 300px; |
||||
padding: 30px 30px; |
||||
margin: 0 10px; |
||||
box-sizing: border-box; |
||||
border-radius: 8px; |
||||
background-size: 100% 100%; |
||||
background-repeat: no-repeat; |
||||
p { |
||||
font-size: 18px; |
||||
color: #ffffff; |
||||
} |
||||
.val{ |
||||
margin-top: 10px; |
||||
color: #ffffff; |
||||
font-size: 36px; |
||||
} |
||||
} |
||||
} |
||||
.chart{ |
||||
flex: 1; |
||||
height: 300px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,492 @@ |
||||
<template> |
||||
<div> |
||||
<el-form :disabled="isDetail"> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between"> |
||||
<el-page-header @back="goBack" :content="isDetail ? '查看' : (id ? '更新' : '创建') + '教学实验'"></el-page-header> |
||||
<div> |
||||
<el-button type="primary" size="small" @click="upload" v-show="!isDetail">{{id ? '更新' : '创建'}}</el-button> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgr20 m-b-20"> |
||||
<div> |
||||
<p class="m-b-20">考核名称</p> |
||||
<el-input |
||||
placeholder="请输入考核名称" |
||||
v-model="experimentalName" |
||||
clearable |
||||
maxlength="15" |
||||
class="inline-input" |
||||
@change="judgeExpName" |
||||
></el-input> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgr20 m-b-20"> |
||||
<div> |
||||
<p class="m-b-20">班级名称</p> |
||||
<el-input |
||||
placeholder="请输入班级名称" |
||||
v-model="experimentalClassName" |
||||
clearable |
||||
maxlength="15" |
||||
class="inline-input" |
||||
></el-input> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div> |
||||
<p class="m-b-20">发布方式</p> |
||||
<el-radio :disabled="id ? true : false" v-model="type" label="1" class="fons">手动发布</el-radio> |
||||
<el-radio :disabled="id ? true : false" v-model="type" label="2" class="fons">定时发布</el-radio> |
||||
</div> |
||||
</el-card> |
||||
<!-- 根据发布方式判断时间的显示 --> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div> |
||||
<p class="m-b-20">实验时间</p> |
||||
<!-- 手动发布显示 --> |
||||
<div class="date-inputs" v-if="type==1"> |
||||
实验时长: |
||||
<el-input size="small" v-model="duration.day" placeholder></el-input> 天 |
||||
<el-input size="small" v-model="duration.hour" placeholder></el-input> 小时 |
||||
<el-input size="small" v-model="duration.minute" placeholder></el-input> 分 |
||||
</div> |
||||
|
||||
<!-- 定时发布显示 --> |
||||
<div v-if="type==2" class="addAssess"> |
||||
<span class="mgr10">开始时间:</span> |
||||
<el-date-picker |
||||
size="small" |
||||
v-model="date" |
||||
type="datetimerange" |
||||
range-separator="-" |
||||
start-placeholder="开始日期" |
||||
end-placeholder="结束日期" |
||||
:picker-options="pickerOptions" |
||||
></el-date-picker> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<el-card shadow="hover" class="mgr20 m-b-20"> |
||||
<div> |
||||
<p class="m-b-20">系统</p> |
||||
<div class="inline-input"> |
||||
<el-select v-model="systemId" placeholder="请选择" @change="initData"> |
||||
<el-option |
||||
v-for="item in systemList" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.id" |
||||
></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<!-- 实训项目模块 --> |
||||
<el-card shadow="hover" class="m-b-20"> |
||||
<div class="flex-between m-b-20"> |
||||
<span>实训项目</span> |
||||
<div style="display: inline-flex;"> |
||||
<div> |
||||
<el-input size="small" placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</div> |
||||
<el-button style="margin-left: 5px" type="primary" size="small" round @click="toProject">自定义实验项目</el-button> |
||||
</div> |
||||
</div> |
||||
<!-- 实训项目表格 --> |
||||
<el-table :data="projectData" class="table" stripe header-align="center"> |
||||
<!-- 单选实训项目ID --> |
||||
<el-table-column width="60" label="选择" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-radio v-model="projectId" :label="scope.row.projectId"> </el-radio> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="projectName" label="项目名称" align="center"></el-table-column> |
||||
<el-table-column prop="auth" label="项目权限" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{projectPermissionsList[scope.row.projectPermissions]}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="creater" label="创建人" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{roleStatus(scope.row.founder)}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="creationTime" label="创建时间" align="center"></el-table-column> |
||||
<el-table-column label="操作" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="showProject(scope.row)">查看</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination |
||||
background |
||||
:page-size="pageSize" |
||||
@current-change="handleCurrentChange" |
||||
layout="total,prev, pager, next" |
||||
:total="total" |
||||
></el-pagination> |
||||
</div> |
||||
</el-card> |
||||
|
||||
<!-- 邀请码 --> |
||||
<el-card shadow="hover"> |
||||
<div style="margin-bottom: 10px"> |
||||
<p class="m-b-20">设置邀请码</p> |
||||
<el-radio v-model="isCode" label="0">是</el-radio> |
||||
<el-radio v-model="isCode" label="1">否</el-radio> |
||||
</div> |
||||
<div v-show="isCode == 0"> |
||||
<el-input style="display: inline-block;width: auto;margin-right: 10px" v-model.number="invitationCode" maxlength="6" placeholder="请设置6个数字"></el-input> |
||||
<el-button type="text" @click="createInv">随机</el-button> |
||||
</div> |
||||
</el-card> |
||||
</el-form> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
export default { |
||||
data() { |
||||
return { |
||||
id: '', |
||||
roleStatus: util.getRoleName, |
||||
systemId: Setting.systemId, |
||||
systemList: Setting.systemList, |
||||
isDetail: true, |
||||
duration: { |
||||
day: '', |
||||
hour: '', |
||||
minute: '' |
||||
}, |
||||
keyword: '', |
||||
searchTimer: null, |
||||
date: '', |
||||
experimentDuration: '0d0h0m', |
||||
experimentalNumber: 0, |
||||
projectId: '', |
||||
projectName: '', |
||||
status: '', |
||||
surplusTime: '', |
||||
experimentalName: '',//考核名称 |
||||
experimentalClassName: '', //班级名称 |
||||
type: '1', |
||||
isCode: '0', //是否设置邀请码 |
||||
startTime: '0000-00-00 00:00:00', //开始时间 |
||||
stopTime: '0000-00-00 00:00:00', //结束时间 |
||||
invitationCode: '', |
||||
currPage: 1, |
||||
projectDataAll: [], |
||||
projectData: [], |
||||
invRepeat: false, |
||||
pickerOptions: { |
||||
disabledDate: time => { |
||||
return time.getTime() < new Date().getTime() - 86400000 |
||||
} |
||||
}, |
||||
|
||||
projectPermissionsList: ['练习','考核','竞赛'], |
||||
projectQueryData: { |
||||
userId: this.userId, |
||||
systemId: this.systemId |
||||
}, |
||||
page: 1, |
||||
pageSize: 5, |
||||
total: 0, |
||||
multipleSelection: [], |
||||
isToProject: false, |
||||
expNameRepeat: false |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId' |
||||
]), |
||||
...mapState('project', [ |
||||
'assFields' |
||||
]), |
||||
}, |
||||
mounted() { |
||||
console.log(22,this.assFields) |
||||
this.date = [util.formatDate("yyyy-MM-dd hh:mm:ss",new Date(new Date().getTime() + 300000)),util.formatDate("yyyy-MM-dd hh:mm:ss",new Date(new Date().getTime() + 300000))] |
||||
this.id = this.$route.query.id |
||||
this.isDetail = Boolean(this.$route.query.show) |
||||
this.id && this.getData() |
||||
this.getProjectData() |
||||
this.recoveryData() |
||||
}, |
||||
beforeDestroy(){ |
||||
if(!this.isToProject) this.setAss({}) |
||||
}, |
||||
watch: { |
||||
date: function(val){ |
||||
if(val[0] != '0000-00-00 00:00:00'){ |
||||
this.startTime = util.formatDate("yyyy-MM-dd hh:mm:ss",new Date(val[0])) |
||||
this.stopTime = util.formatDate("yyyy-MM-dd hh:mm:ss",new Date(val[1])) |
||||
} |
||||
}, |
||||
duration: { |
||||
handler(n,o){ |
||||
this.experimentDuration = `${n.day ? n.day : 0}d${n.hour ? n.hour : 0}h${n.minute ? n.minute : 0}m` |
||||
}, |
||||
deep: true |
||||
}, |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
methods: { |
||||
...mapActions('project', [ |
||||
'setAss' |
||||
]), |
||||
getProjectData(){ |
||||
let data = { |
||||
pageNo: this.page, |
||||
pageSize: 10000, |
||||
userId: this.userId, |
||||
systemId: this.systemId, |
||||
projectName: this.keyword, |
||||
projectPermissions: 1, |
||||
} |
||||
this.$get(this.api.queryAllManagements,data).then(res => { |
||||
let list = res.pageInfo.list |
||||
let result = [] |
||||
list.map(n => { |
||||
n.enable || result.push(n) |
||||
}) |
||||
this.projectDataAll = result |
||||
this.total = result.length |
||||
this.handlePage() |
||||
}).catch(res => {}); |
||||
}, |
||||
handlePage(){ |
||||
let list = this.projectDataAll |
||||
let result = list.slice((this.page - 1) * this.pageSize,this.page * this.pageSize) |
||||
this.projectData = result |
||||
}, |
||||
initData(){ |
||||
this.page = 1 |
||||
this.getProjectData() |
||||
}, |
||||
recoveryData(){ |
||||
if(JSON.stringify(this.assFields) != '{}'){ |
||||
let info = this.assFields |
||||
this.experimentDuration = info.experimentDuration |
||||
this.experimentalClassName = info.experimentalClassName |
||||
this.experimentalName = info.experimentalName |
||||
this.invitationCode = info.invitationCode |
||||
this.isCode = String(info.isCode) |
||||
this.projectId = info.projectId |
||||
this.startTime = info.startTime |
||||
this.stopTime = info.stopTime |
||||
this.surplusTime = info.surplusTime |
||||
this.type = String(info.type) |
||||
this.expNameRepeat = info.expNameRepeat |
||||
|
||||
this.formatDuration() |
||||
} |
||||
}, |
||||
upload() { |
||||
if(!this.experimentalName) return this.$message.warning('请填写考核名称') |
||||
if(this.expNameRepeat) return this.$message.warning('考核名称重复,请重新输入') |
||||
if(!this.experimentalClassName) return this.$message.warning('请填写班级名称') |
||||
if(this.type == 1){ |
||||
this.status = 1 |
||||
}else{ |
||||
if(new Date().getTime() > new Date(this.startTime).getTime()) return this.$message.warning('开始时间不能早于当前时间') |
||||
this.status = 1 |
||||
let timestamp = new Date(new Date(this.stopTime).getTime() - new Date(this.startTime).getTime()) |
||||
let minute = 1000 * 60 |
||||
let hour = minute * 60 |
||||
let day = hour * 24 |
||||
this.experimentDuration = `${Math.floor(timestamp / day)}d${Math.floor(timestamp % day / hour)}h${Math.floor(timestamp % day % hour / minute)}m` |
||||
} |
||||
if(this.type == 1 && this.experimentDuration == '0d0h0m') return this.$message.warning('请填写实验时长') |
||||
if(this.type == 2 && this.startTime == '0000-00-00 00:00:00') return this.$message.warning('请填写实验时间') |
||||
if(!this.projectId) return this.$message.warning('请选择实训项目') |
||||
this.projectName = this.projectData.find(n => n.projectId == this.projectId).projectName |
||||
if(this.isCode == 0){ |
||||
if(!this.invitationCode) return this.$message.warning('请设置邀请码') |
||||
if(!this.invitationCode || String(this.invitationCode).length < 6 || isNaN(this.invitationCode)) return this.$message.warning('请输入6位纯数字邀请码') |
||||
// if(this.invRepeat) return this.$message.warning('邀请码重复,请重新输入') |
||||
} |
||||
|
||||
let data = { |
||||
id: this.id, |
||||
experimentDuration: this.experimentDuration, |
||||
creationTime: this.id ? this.creationTime : util.formatDate("yyyy-MM-dd hh:mm:ss"), |
||||
experimentalClassName: this.experimentalClassName, |
||||
experimentalName: this.experimentalName, |
||||
experimentalNumber: this.experimentalNumber, |
||||
invitationCode: this.invitationCode, |
||||
isCode: this.isCode, |
||||
projectId: this.projectId, |
||||
projectName: this.projectName, |
||||
status: Number(this.status), |
||||
surplusTime: this.surplusTime, |
||||
type: Number(this.type), |
||||
userId: this.userId, |
||||
systemId: this.systemId |
||||
} |
||||
if(this.type == 2){ |
||||
data.startTime = this.startTime |
||||
data.stopTime = this.stopTime |
||||
}else{ |
||||
data.startTime = '0000-00-00 00:00:00' |
||||
data.stopTime = '0000-00-00 00:00:00' |
||||
} |
||||
if(this.id){ |
||||
this.$post(this.api.expUpdate, data).then(res => { |
||||
util.successMsg('修改成功'); |
||||
this.$router.back() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
}else{ |
||||
this.$post(this.api.expSave, data).then(res => { |
||||
util.successMsg('创建成功'); |
||||
this.$router.back() |
||||
}) |
||||
.catch(err => { |
||||
}); |
||||
} |
||||
}, |
||||
getData() { |
||||
this.$get(this.api.expInfo + this.id) |
||||
.then(res => { |
||||
if(res.errmessage == 'success'){ |
||||
let info = res.ExperimentalTeaching |
||||
this.creationTime = info.creationTime |
||||
this.experimentDuration = info.experimentDuration |
||||
this.experimentalClassName = info.experimentalClassName |
||||
this.experimentalName = info.experimentalName |
||||
this.experimentalNumber = info.experimentalNumber |
||||
this.invitationCode = info.invitationCode |
||||
this.isCode = String(info.isCode) |
||||
this.projectId = info.projectId |
||||
this.projectName = info.projectName |
||||
this.startTime = info.startTime |
||||
this.status = info.status |
||||
this.stopTime = info.stopTime |
||||
this.surplusTime = info.surplusTime |
||||
this.type = String(info.type) |
||||
|
||||
this.formatDuration() |
||||
}else{ |
||||
util.errorMsg('查询失败'); |
||||
} |
||||
}) |
||||
.catch(err => { |
||||
|
||||
}); |
||||
}, |
||||
formatDuration(){ |
||||
let duration = this.experimentDuration.replace(/\D+/g,',').split(',') |
||||
this.duration = { |
||||
day: duration[0], |
||||
hour: duration[1], |
||||
minute: duration[2] |
||||
} |
||||
this.date = [this.startTime,this.stopTime] |
||||
}, |
||||
handleCacheData(){ |
||||
let data = { |
||||
id: this.id, |
||||
experimentDuration: this.experimentDuration, |
||||
experimentalClassName: this.experimentalClassName, |
||||
experimentalName: this.experimentalName, |
||||
invitationCode: this.invitationCode, |
||||
isCode: this.isCode, |
||||
projectId: this.projectId, |
||||
startTime: this.startTime, |
||||
stopTime: this.stopTime, |
||||
surplusTime: this.surplusTime, |
||||
type: this.type, |
||||
expNameRepeat: this.expNameRepeat |
||||
} |
||||
this.setAss(data) |
||||
this.isToProject = true |
||||
}, |
||||
toProject(){ |
||||
this.handleCacheData() |
||||
this.$router.push('/project') |
||||
}, |
||||
showProject(row){ |
||||
this.handleCacheData() |
||||
this.$router.push(`/addproject?id=${row.projectId}&show=1`) |
||||
}, |
||||
goBack() { |
||||
if(this.isDetail){ |
||||
this.$router.back() |
||||
}else{ |
||||
this.$confirm('确定返回?未更新的信息将不会保存。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$router.back() |
||||
}) |
||||
.catch(() => {}); |
||||
} |
||||
}, |
||||
varifyInv() { |
||||
this.$get(this.api.getInvitationCode, { invitationCode: this.invitationCode }) |
||||
.then(res => { |
||||
if(res.InvitationCode) { |
||||
this.$message.warning('邀请码重复,请重新输入') |
||||
this.invRepeat = true |
||||
}else{ |
||||
this.invRepeat = false |
||||
} |
||||
}) |
||||
.catch(err => {}); |
||||
}, |
||||
createInv() { |
||||
let result = '' |
||||
for(let i=0; i<6; i++){ |
||||
result += Math.floor(Math.random()*10) |
||||
} |
||||
this.invitationCode = result |
||||
// this.varifyInv() |
||||
}, |
||||
handleCurrentChange(val){ |
||||
this.page = val |
||||
this.handlePage() |
||||
}, |
||||
judgeExpName(){ |
||||
this.$get(this.api.expCheck, { experimentalName: util.encodeStr(this.experimentalName) }) |
||||
.then(res => { |
||||
if(res.errmessage != 'success') { |
||||
this.$message.warning('考核名称重复,请重新输入') |
||||
this.expNameRepeat = true |
||||
}else{ |
||||
this.expNameRepeat = false |
||||
} |
||||
}) |
||||
.catch(err => {}); |
||||
}, |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.inline-input{ |
||||
width: 300px; |
||||
} |
||||
.date-inputs{ |
||||
.el-input{ |
||||
width: 100px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,389 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<h6 class="p-title">筛选</h6> |
||||
<div class="tool mul"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>实验时间</label> |
||||
<el-radio-group size="small" v-model="form.month" @change="initData"> |
||||
<el-radio v-for="(item,index) in dateList" :key="index" :label="item.id" border>{{item.name}}</el-radio> |
||||
</el-radio-group> |
||||
<el-date-picker size="small" v-model="date" align="right" unlink-panels type="daterange" style="margin-left: 10px;" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable></el-date-picker> |
||||
</li> |
||||
<li> |
||||
<label>发布类型</label> |
||||
<el-select size="small" v-model="form.type" clearable placeholder="请选择发布类型" @change="initData"> |
||||
<el-option v-for="(item,index) in typeList" :key="index" :label="item.name" :value="item.value"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>实验状态</label> |
||||
<el-select size="small" v-model="form.status" clearable placeholder="请选择实验状态" @change="initData"> |
||||
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>系统</label> |
||||
<el-select size="small" v-model="systemId" placeholder="请选择" @change="initData"> |
||||
<el-option label="不限" value=""></el-option> |
||||
<el-option |
||||
v-for="item in systemList" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.id" |
||||
></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<el-input size="small" placeholder="请输入实验班级/项目名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" round @click="add" v-auth>创建实验</el-button> |
||||
<el-button type="primary" size="small" round @click="delAllData" v-auth>批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table ref="table" :data="listData" class="table" stripe header-align="center" @selection-change="handleSelectionChange" row-key="id"> |
||||
<el-table-column type="selection" :selectable="row => row.status!=2" width="50" align="center" :reserve-selection="true"></el-table-column> |
||||
<el-table-column type="index" width="60" label="序号" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.$index + (page - 1) * pageSize + 1}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalClassName" label="实验班级" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalName" label="考核名称" min-width="120" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="projectName" label="项目名称" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalNumber" label="实验人数" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentDuration" label="实验时长" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="邀请码" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{scope.row.isCode == 0 ? scope.row.invitationCode : ''}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="adminName" label="发布类型" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{types[scope.row.type]}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="creationTime" width="150" label="创建时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="startTime" width="150" label="起始时间" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{transferTime(scope.row.startTime,scope.row.type)}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="stopTime" width="150" label="结束时间" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{transferTime(scope.row.stopTime,scope.row.type)}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="surplusTime" label="倒计时" align="center"> |
||||
<!-- <template slot-scope="scope"> |
||||
<span v-if="scope.row.status == 2" v-countdown="scope.row.surplusTime">{{scope.row.surplusTime}}</span> |
||||
<span v-else>00:00:00</span> |
||||
</template> --> |
||||
</el-table-column> |
||||
<el-table-column label="实验状态" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span>{{status[scope.row.status]}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center" width="170"> |
||||
<template slot-scope="scope"> |
||||
<template v-if="scope.row.status == 1"> |
||||
<el-button type="text" @click="start(scope.row)" v-auth>启动</el-button> |
||||
<el-button type="text" @click="edit(scope.row)" v-auth>修改</el-button> |
||||
</template> |
||||
<template v-else-if="scope.row.status == 2"> |
||||
<el-button type="text" @click="finish(scope.row)" v-auth>提前结束</el-button> |
||||
</template> |
||||
<template v-else-if="scope.row.status == 3"> |
||||
<el-button type="text" @click="show(scope.row)" v-auth>查看成绩</el-button> |
||||
</template> |
||||
<el-button v-if="scope.row.status == 1 || scope.row.status == 3" type="text" @click="delData(scope.row)" v-auth>删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="total" @current-change="handleCurrentChange" :current-page="page"></el-pagination> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
export default { |
||||
data() { |
||||
return { |
||||
systemList: Setting.systemList, |
||||
systemId: '', |
||||
keyword: '', |
||||
typeList: [ |
||||
{ |
||||
value: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
value: 1, |
||||
name: '手动发布' |
||||
}, |
||||
{ |
||||
value: 2, |
||||
name: '定时发布' |
||||
} |
||||
], |
||||
status: ['','待开始','进行中','已完成'], |
||||
types: ['','手动发布','定时发布'], |
||||
statusList: [ |
||||
{ |
||||
value: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
value: 1, |
||||
name: '待开始' |
||||
}, |
||||
{ |
||||
value: 2, |
||||
name: '进行中' |
||||
}, |
||||
{ |
||||
value: 3, |
||||
name: '已完成' |
||||
} |
||||
], |
||||
listData: [], |
||||
form: { |
||||
type: '', |
||||
status: '', |
||||
startTime: '', |
||||
stopTime: '', |
||||
month: '', |
||||
searchContent: '' |
||||
}, |
||||
multipleSelection: [], |
||||
dateList: [ |
||||
{ |
||||
id: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '近一个月' |
||||
}, |
||||
{ |
||||
id: 3, |
||||
name: '近三个月' |
||||
}, |
||||
{ |
||||
id: 6, |
||||
name: '近六个月' |
||||
} |
||||
], |
||||
date: [], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
ruleIds: [], |
||||
timer: null |
||||
}; |
||||
}, |
||||
directives: { |
||||
countdown: { |
||||
bind: function(el,binding,vnode) { |
||||
let that = vnode.context |
||||
let time = binding.value |
||||
let timer = setInterval(() => { |
||||
let timeList = time.split(':') |
||||
let total = Number.parseInt(timeList[0] * 60 * 60) + Number.parseInt(timeList[1] * 60) + Number.parseInt(timeList[2]) |
||||
if(total > 0){ |
||||
--total |
||||
let hours = Math.floor(total / (60 * 60)) |
||||
let minutes = Math.floor(total % (60 * 60) / 60) |
||||
let seconds = Math.floor(total % (60 * 60) % 60) |
||||
time = `${util.formateTime(hours)}:${util.formateTime(minutes)}:${util.formateTime(seconds)}` |
||||
}else{ |
||||
clearInterval(timer) |
||||
} |
||||
el.innerHTML = time |
||||
},1000) |
||||
that.timerList.push(timer) |
||||
} |
||||
} |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'schoolId' |
||||
]), |
||||
}, |
||||
watch: { |
||||
'form.month': function(val){ |
||||
if(val){ |
||||
let unit = 24 * 60 * 60 * 1000 |
||||
this.date = [this.formatDate('yyyy-MM-dd',new Date(new Date().getTime() - unit * 30 * val)),this.formatDate('yyyy-MM-dd',new Date(new Date().getTime() + unit))] |
||||
}else{ |
||||
this.date = [] |
||||
} |
||||
}, |
||||
date: function(val){ |
||||
if(val){ |
||||
this.form.startTime = val[0] |
||||
this.form.stopTime = val[1] |
||||
}else{ |
||||
this.form.startTime = '' |
||||
this.form.stopTime = '' |
||||
} |
||||
this.initData() |
||||
}, |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
computed: { |
||||
role() { |
||||
return this.name === 'admin' ? '超级管理员' : '普通用户'; |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
this.timer = setInterval(this.getData,1000) |
||||
this.$once('hook:beforeDestroy',() => { |
||||
clearInterval(this.timer) |
||||
}) |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
type: this.form.type, |
||||
startTime: this.form.startTime, |
||||
stopTime: this.form.stopTime, |
||||
month: this.form.month, |
||||
searchContent: util.encodeStr(this.keyword), |
||||
status: this.form.status, |
||||
page: this.page, |
||||
size: this.pageSize, |
||||
systemId: this.systemId, |
||||
schoolId: this.schoolId ? this.schoolId : '' |
||||
} |
||||
this.$get(this.api.expList,data).then(res => { |
||||
this.listData = res.list.list |
||||
this.total = res.list.totalCount |
||||
}).catch(res => {}); |
||||
}, |
||||
initData(){ |
||||
this.$refs.table.clearSelection() |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
add(){ |
||||
this.$router.push('add') |
||||
}, |
||||
edit(row){ |
||||
this.$router.push(`add?id=${row.id}`) |
||||
}, |
||||
show(row){ |
||||
this.$router.push(`/achievement/ass?systemId=${this.systemId}&id=${row.id}&projectId=${row.projectId}&name=${row.projectName}&experimentalName=${row.experimentalName}&class=${row.experimentalClassName}`) |
||||
}, |
||||
start(row){ |
||||
let data = { |
||||
id: row.id, |
||||
startTime: this.formatDate("yyyy-MM-dd hh:mm:ss",new Date()), |
||||
status: 2 |
||||
} |
||||
this.$post(this.api.expUpdate,data).then(res => { |
||||
if(res.errmessage == 'success') { |
||||
util.successMsg('启动成功!') |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
finish(row){ |
||||
this.$confirm('确定要提前结束吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
id: row.id, |
||||
stopTime: this.formatDate("yyyy-MM-dd hh:mm:ss",new Date()), |
||||
status: 3 |
||||
} |
||||
this.$post(this.api.expUpdate,data).then(res => { |
||||
if(res.errmessage == 'success') { |
||||
util.successMsg('提前结束成功!') |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}) |
||||
}, |
||||
delData(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(this.api.expDelete,[row.id]).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
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.expDelete,data).then(res => { |
||||
this.multipleSelection = []; |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
onSearch(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val; |
||||
this.getData(); |
||||
}, |
||||
transferTime(date,type){ |
||||
if(date == '0000-00-00 00:00:00') return '---' |
||||
return date |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.el-radio-group{ |
||||
white-space: nowrap; |
||||
} |
||||
</style> |
@ -0,0 +1,59 @@ |
||||
<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" @click="toIndex">返回首页</el-button> |
||||
</router-link> |
||||
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
methods: { |
||||
toIndex(){ |
||||
this.$router.push('/') |
||||
}, |
||||
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,59 @@ |
||||
<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" @click="toIndex">返回首页</el-button> |
||||
</router-link> |
||||
<el-button class="error-btn" type="primary" size="large" @click="goBack">返回上一页</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
methods: { |
||||
toIndex(){ |
||||
this.$router.push('/') |
||||
}, |
||||
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><i class="el-icon-lx-redpacket_fill"></i></span> |
||||
</p> |
||||
<p class="example-p"> |
||||
<i class="el-icon-lx-weibo" style="font-size: 30px;color:#fd5656"></i> |
||||
<span><i class="el-icon-lx-weibo"></i></span> |
||||
</p> |
||||
<p class="example-p"> |
||||
<i class="el-icon-lx-emojifill" style="font-size: 30px;color: #ffc300"></i> |
||||
<span><i class="el-icon-lx-emojifill"></i></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,393 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<el-page-header class="m-b-20" content="实验项目管理" @back="goBack"></el-page-header> |
||||
|
||||
|
||||
<h6 class="p-title">筛选</h6> |
||||
<div class="tool mul"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>创建人</label> |
||||
<el-select size="small" v-model="queryData.founder" clearable placeholder="请选择创建人" @change="initData"> |
||||
<el-option v-for="(item,index) in founder" :key="index" :label="item.label" :value="item.value"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>状态</label> |
||||
<el-select size="small" v-model="queryData.state" clearable placeholder="请选择状态" @change="initData"> |
||||
<el-option v-for="(item,index) in state" :key="index" :label="item.label" :value="item.value"></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>权限</label> |
||||
<el-select size="small" v-model="queryData.projectPermissions" placeholder="请选择" @change="initData"> |
||||
<el-option |
||||
v-for="item in projectPermissions" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<label>系统</label> |
||||
<el-select size="small" v-model="systemId" placeholder="请选择" @change="initData"> |
||||
<el-option |
||||
v-for="item in systemList" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.id" |
||||
></el-option> |
||||
</el-select> |
||||
</li> |
||||
<li> |
||||
<el-input size="small" placeholder="请输入项目名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" @click="add" v-auth>新增项目</el-button> |
||||
<el-button type="primary" size="small" @click="delAllData" v-auth>批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="listData" class="table" ref="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" width="100" label="序号" align="center"> |
||||
<template slot-scope="scope">{{scope.$index + (page - 1) * pageSize + 1}}</template> |
||||
</el-table-column> |
||||
<el-table-column prop="projectName" label="实验项目名称" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="founder" label="创建人" align="center"></el-table-column> |
||||
<el-table-column label="权限" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.row.projectPermissions == 2 ? '竞赛' : projectPermissions.find(n => n.value === scope.row.projectPermissions).label}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="creationTime" label="创建时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="status" label="状态" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{transferStatus(scope.row.state)}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="edit(scope.row)" v-auth v-if="roleId == 1 || (roleId == 13 && scope.row.founder != '超级管理员') || (roleId == 14 && scope.row.founder == '老师')">编辑</el-button> |
||||
<el-button type="text" @click="delData(scope.row)" v-auth v-if="roleId == 1 || (roleId == 13 && scope.row.founder != '超级管理员') || (roleId == 14 && scope.row.founder == '老师')">删除</el-button> |
||||
<el-button type="text" @click="copyData(scope.row)" v-auth>复制</el-button> |
||||
<el-switch |
||||
v-model="scope.row.enable" |
||||
:active-text="scope.row.enable ? '关闭' : '启用'" |
||||
:active-value="0" |
||||
:inactive-value="1" |
||||
style="margin: 0 10px 0 10px" |
||||
@change="switchOff($event,scope.row,scope.$index)" |
||||
></el-switch> |
||||
</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-dialog title="复制" :visible.sync="copyVisible" width="24%" center :close-on-click-modal="false"> |
||||
<el-form> |
||||
<el-form-item> |
||||
<el-input placeholder="请输入项目名称" v-model="projectName" @change="projectNameExistis"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="copyVisible = false">取 消</el-button> |
||||
<el-button type="primary" @click="copySubmit">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
export default { |
||||
data() { |
||||
return { |
||||
showBack: JSON.stringify(this.assFields) == '{}' ? false : true, |
||||
roleIdEd: this.roleId ? 13 : this.roleId,// 管理员的roleId是13,老师的roleId是14,1个用户也可能是两个角色,就是13,14,当一个用户是两个角色的话,就取权重大的一个,就是管理员,即13.管理员>老师 |
||||
systemId: '', |
||||
systemList: Setting.systemList, |
||||
queryData: { |
||||
projectPermissions: "", |
||||
founder: "", |
||||
state: "", |
||||
projectName: "", |
||||
}, |
||||
keyword: '', |
||||
status: '', |
||||
listData:[], |
||||
total: 0, |
||||
projectPermissions: [ |
||||
{ |
||||
value: "", |
||||
label: "不限" |
||||
}, |
||||
{ |
||||
value: 0, |
||||
label: "练习" |
||||
}, |
||||
{ |
||||
value: 1, |
||||
label: "考核" |
||||
}, |
||||
// { |
||||
// value: 2, |
||||
// label: "竞赛" |
||||
// } |
||||
], |
||||
founder: [ |
||||
{ |
||||
value: "", |
||||
label: "不限" |
||||
}, |
||||
{ |
||||
value: 1, |
||||
label: "超级管理员" |
||||
}, |
||||
{ |
||||
value: 13, |
||||
label: "管理员" |
||||
}, |
||||
{ |
||||
value: 14, |
||||
label: "老师" |
||||
} |
||||
], |
||||
state: [ |
||||
{ |
||||
value: "", |
||||
label: "不限" |
||||
}, |
||||
{ |
||||
value: 0, |
||||
label: "草稿箱" |
||||
}, |
||||
{ |
||||
value: 1, |
||||
label: "已发布" |
||||
} |
||||
], |
||||
page: 1, |
||||
pageSize: 10, |
||||
multipleSelection: [], |
||||
copyVisible: false, |
||||
projectName: '', |
||||
projectNameRepeat: false, |
||||
currentRow: {}, |
||||
listDataAll: [] |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','roleId' |
||||
]), |
||||
...mapState('project', [ |
||||
'lastSystemId','assFields' |
||||
]), |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.systemId = this.lastSystemId ? this.lastSystemId : Setting.systemId |
||||
console.log(this.systemId,'外面的sysid'); |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
...mapActions('project', [ |
||||
'setSystemId' |
||||
]), |
||||
getData(){ |
||||
this.setSystemId(this.systemId) |
||||
let data = this.queryData |
||||
data.userId = this.userId |
||||
data.systemId = this.systemId |
||||
data.pageNo = this.page |
||||
data.pageSize = this.pageSize |
||||
data.projectName = util.encodeStr(this.keyword) |
||||
data.systemId = this.systemId |
||||
this.$get(this.api.queryAllManagements,data).then(res => { |
||||
let list = res.pageInfo.list |
||||
let newList = [] |
||||
list.map(n => { |
||||
if(n.founder.includes(',')){ |
||||
n.founder = '管理员' |
||||
}else{ |
||||
n.founder = util.getRoleName(n.founder) |
||||
} |
||||
}) |
||||
this.listData = list |
||||
this.total = res.pageInfo.total |
||||
}).catch(res => {}); |
||||
}, |
||||
initData(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
handlePage(){ |
||||
let list = this.listDataAll |
||||
let result = list.slice((this.page - 1) * this.pageSize,this.page * this.pageSize) |
||||
this.listData = result |
||||
}, |
||||
transferStatus(status){ |
||||
return status == 1 ? '已发布' : '草稿箱' |
||||
}, |
||||
handleCurrentChange(val){ |
||||
this.page = val |
||||
this.getData() |
||||
}, |
||||
add(){ |
||||
this.setSystemId(this.systemId) |
||||
this.$router.push('add') |
||||
}, |
||||
edit(row){ |
||||
console.log(row,'编辑触发'); |
||||
this.setSystemId(row.systemId) |
||||
this.$router.push(`add?id=${row.projectId}`) |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
delData(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(this.api.removeProjectManagement,[row.projectId]).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
delAllData() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.projectId |
||||
}) |
||||
|
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(this.api.removeProjectManagement,delList).then(res => { |
||||
this.multipleSelection = []; |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择项目 !'); |
||||
} |
||||
}, |
||||
projectNameExistis(){ |
||||
let data = { |
||||
projectName: util.encodeStr(this.projectName) |
||||
} |
||||
this.$get(this.api.isNameExistis,data).then(res => { |
||||
if(res.status != 200){ |
||||
this.projectNameRepeat = true |
||||
this.$message.warning('该项目名称已存在') |
||||
}else{ |
||||
this.projectNameRepeat = false |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
copyData(row){ |
||||
this.currentRow.management = { |
||||
caseDescription: row.caseDescription, |
||||
experimentSuggests: row.experimentSuggests, |
||||
experimentalGoal: row.experimentalGoal, |
||||
founder: row.founder, |
||||
isstartexperimentSuggests: row.isstartexperimentSuggests, |
||||
isstartexperimental: row.isstartexperimental, |
||||
projectName: row.projectName, |
||||
projectPermissions: row.projectPermissions, |
||||
state: row.state, |
||||
systemId: row.systemId, |
||||
userId: row.userId, |
||||
knowledgePoints: row.knowledgePoints, |
||||
experimentIntroduction: row.experimentIntroduction |
||||
} |
||||
this.currentRow.founder = row.founder |
||||
this.projectName = row.projectName |
||||
this.projectNameRepeat = true |
||||
this.copyVisible = true |
||||
let data = { |
||||
projectId: row.projectId |
||||
} |
||||
this.$get(this.api.getZZJudgmentPoints,data).then((res) => { |
||||
this.currentRow.roleId = res.message.roleList.map(n => n.roleId) |
||||
let scoreList = res.message.scoreIndexList |
||||
let scores = [] |
||||
for(let i in scoreList){ |
||||
scores = scores.concat(scoreList[i]) |
||||
} |
||||
let point = res.message.judgmentPointsList |
||||
point.map(n => { |
||||
let same = scores.find(e => e.judgmentPointsId == n.judgmentPointsId) |
||||
if(same) n.score = same.score |
||||
}) |
||||
this.currentRow.pooints = point |
||||
this.$message.warning('请修改项目名称') |
||||
}) |
||||
}, |
||||
copySubmit(){ |
||||
if(!this.projectName.length) return this.$message.warning('请填写项目名称') |
||||
if(this.projectNameRepeat) return this.$message.warning('该项目名称已存在') |
||||
let data = this.currentRow |
||||
data.management.projectName = this.projectName |
||||
data.founder = this.roleId |
||||
data.management.founder = this.roleId |
||||
data.management.userId = this.userId |
||||
data.pooints.map(n => { |
||||
n.userId = this.userId |
||||
}) |
||||
let systemId = this.currentRow.management.systemId |
||||
let url = this.api.addProjectManagement |
||||
if(systemId == 2 || systemId == 3) url = this.api.addProjectManagementTrad |
||||
this.$post(url,data).then((res) => { |
||||
util.successMsg('复制成功'); |
||||
this.copyVisible = false |
||||
this.getData() |
||||
}) |
||||
}, |
||||
switchOff(val,row,index) { |
||||
this.$get(this.api.enableProject,{ |
||||
id: row.projectId, |
||||
enable: row.enable |
||||
}) |
||||
.then(res => { |
||||
if(res.status != 200){ |
||||
util.errorMsg(res.errmessage) |
||||
row.enable = row.enable == 1 ? 0 : 1 |
||||
} |
||||
}) |
||||
.catch(err => {}); |
||||
}, |
||||
goBack() { |
||||
this.$router.back() |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,527 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<h6 class="p-title">筛选</h6> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<el-input style="width: 250px;" size="small" placeholder="请输入学生账号/姓名/学校名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" v-auth @click="addStudent">新增学生</el-button> |
||||
<el-button type="primary" size="small" v-auth @click="batchImport">批量导入</el-button> |
||||
<el-button type="primary" size="small" v-auth @click="delAllSelection">批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="listData" class="table" ref="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="account" label="账号" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="schoolName" label="院校" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="workNumber" label="学号" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userName" label="学生姓名" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="countries" 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" width="300"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" v-auth @click="editStudent(scope.row,true)">查看</el-button> |
||||
<el-button type="text" v-auth @click="editStudent(scope.row,false)">编辑</el-button> |
||||
<el-button type="text" v-auth @click="resetPassword(scope.row)">重置密码</el-button> |
||||
<el-button type="text" v-auth @click="handleDelete(scope.row)">删除</el-button> |
||||
<el-switch |
||||
v-model="scope.row.disableAccount" |
||||
:active-value="0" |
||||
:inactive-value="1" |
||||
style="margin: 0 5px" |
||||
@change="switchOff($event,scope.row,scope.$index)" |
||||
v-auth="'学生管理:禁用'" |
||||
></el-switch> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next" :total="total"></el-pagination> |
||||
</div> |
||||
|
||||
<el-dialog :title="isDetail ? '查看学生' : (isAdd ? '新增学生' : '编辑学生')" :visible.sync="studentVisible" width="30%" @close="closeStudent" class="dialog" :close-on-click-modal="false"> |
||||
<el-form ref="form" :model="form" :rules="rules" :disabled="isDetail" label-width="100px"> |
||||
<el-form-item prop="account" label="学生账号"> |
||||
<el-input v-model="form.account" placeholder="请输入学生账号" @change="accountChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="userName" label="学生姓名"> |
||||
<el-input v-model="form.userName" placeholder="请输入学生姓名"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="roleId" label="账号角色"> |
||||
学生 |
||||
</el-form-item> |
||||
<el-form-item prop="workNumber" label="学生学号"> |
||||
<el-input v-model="form.workNumber" placeholder="" @change="worknumberChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="phone" label="手机号"> |
||||
<el-input v-model="form.phone" placeholder="可用于登录平台,以及找回密码" maxlength="11" @change="phoneChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="email" label="邮箱"> |
||||
<el-input v-model="form.email" placeholder="可用于登录平台,以及找回密码"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="schoolId" label="所在院校"> |
||||
<el-select v-model="form.schoolId" placeholder="默认为当前院校(可修改)" filterable disabled @change="worknumberChange"> |
||||
<el-option v-for="(item,index) in schoolList" :key="index" :label="item.schoolName" :value="item.schoolId"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识"> |
||||
<el-input disabled v-model="form.uniqueIdentificationAccount"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||
<el-button size="small" @click="studentVisible = false">取消</el-button> |
||||
<el-button size="small" type="primary" @click="saveData">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :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.uploadFile" |
||||
: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 size="small" @click="importVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="uploadSure">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<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 size="small" @click="passwordVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="editPassword">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
export default { |
||||
data() { |
||||
return { |
||||
isDetail: false, |
||||
keyword: '', |
||||
schoolId: Setting.schoolId, |
||||
form: { |
||||
userName: '', |
||||
account: '', |
||||
phone: '', |
||||
uniqueIdentificationAccount: '', |
||||
workNumber: '', |
||||
email: '', |
||||
account: '', |
||||
roleId: 4, |
||||
schoolId: this.schoolId, |
||||
schoolAppellationId: this.schoolId |
||||
}, |
||||
rules: { |
||||
account: [ |
||||
{ required: true, message: '请输入账号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[A-Za-z0-9]*$/, |
||||
message: '请输入正确的账号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
userName: [ |
||||
{ required: true, message: '请输入学生姓名', trigger: 'blur' } |
||||
], |
||||
schoolId: [ |
||||
{ required: true, message: '请选择所在院校', trigger: 'change' } |
||||
], |
||||
// uniqueIdentificationAccount: [ |
||||
// { required: true, message: '请输入唯一标识', trigger: 'blur' }, |
||||
// ], |
||||
workNumber: [ |
||||
{ required: true, message: '请输入学生学号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[A-Za-z0-9]*$/, |
||||
message: '请输入正确的学号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
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' |
||||
} |
||||
] |
||||
}, |
||||
listData:[], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
multipleSelection: [], |
||||
uploadList: [], |
||||
importVisible: false, |
||||
isAdd: true, |
||||
studentVisible: false, |
||||
accountReapeat: false, |
||||
phoneRepeat: false, |
||||
workNumberReapeat: false, |
||||
isDetail: false, |
||||
resetVisible: false, |
||||
passwordVisible: false, |
||||
passwordForm: { |
||||
password: '', |
||||
newPassword: '', |
||||
reNewPassword: '' |
||||
}, |
||||
schoolList: [], |
||||
uploadFaild: false, |
||||
token: '', |
||||
accountMsg: '' |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.form.schoolId = this.schoolId |
||||
this.form.schoolAppellationId = this.schoolId |
||||
this.getData() |
||||
this.getSchoolData() |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
schoolId: this.schoolId, |
||||
seachContent: util.encodeStr(this.keyword), |
||||
page: this.page, |
||||
size: this.pageSize |
||||
} |
||||
this.$get(this.api.queryStudent,data).then(res => { |
||||
this.listData = res.data.list |
||||
this.total = res.data.totalCount |
||||
}).catch(res => {}); |
||||
}, |
||||
initData(){ |
||||
this.$refs.table.clearSelection() |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
saveData() { |
||||
this.$refs.form.validate((valid) => { |
||||
if (valid) { |
||||
if(this.accountReapeat) return this.$message.warning(this.accountMsg) |
||||
if(this.workNumberReapeat) return this.$message.warning('该学生学号已存在') |
||||
if(this.phoneRepeat) return this.$message.warning('该手机号已存在') |
||||
this.form.schoolName = this.schoolList.find(n => n.schoolId == this.form.schoolId).schoolName |
||||
if(this.form.studentId) { |
||||
this.$put(this.api.updateStudent,this.form).then(res => { |
||||
if(res.errmessage == 'success') { |
||||
util.successMsg('提交成功!'); |
||||
this.studentVisible = false |
||||
this.getData() |
||||
}else{ |
||||
util.errorMsg(res.message); |
||||
} |
||||
}).catch(res => {}); |
||||
}else{ |
||||
this.form.uniqueIdentificationAccount = new Date().getTime() |
||||
this.$post(this.api.addStudent,this.form).then(res => { |
||||
if(res.errmessage == 'success') { |
||||
util.successMsg('提交成功!'); |
||||
this.studentVisible = false |
||||
this.getData() |
||||
}else{ |
||||
util.errorMsg(res.message); |
||||
} |
||||
}).catch(res => {}); |
||||
} |
||||
}else{ |
||||
return false; |
||||
} |
||||
}) |
||||
}, |
||||
async accountChange(){ |
||||
let res = await this.$get(this.api.queryAccountIsExist, { |
||||
account: util.encodeStr(this.form.account), |
||||
schoolId: this.schoolId |
||||
}); |
||||
if(res.message.user.length){ |
||||
let roleId = res.message.user[0].roleId |
||||
if(roleId){ |
||||
this.accountMsg = roleId == 4 ? '该账号已存在' : (roleId.includes(',') ? '该账号已绑定老师和管理员' : `该账号已绑定${util.getRoleName(roleId)}`) |
||||
}else{ |
||||
this.accountMsg = '该账号已存在' |
||||
} |
||||
this.$message.warning(this.accountMsg) |
||||
this.accountReapeat = true |
||||
}else{ |
||||
this.accountReapeat = false |
||||
} |
||||
}, |
||||
async worknumberChange(){ |
||||
let res = await this.$get(this.api.queryWorkNumberIsExist, { |
||||
workNumber: util.encodeStr(this.form.workNumber), |
||||
roleId: 4, |
||||
schoolId: this.schoolId |
||||
}); |
||||
if(JSON.stringify(res.message) != '{}'){ |
||||
this.$message.warning('该学生学号已存在'); |
||||
this.workNumberReapeat = true |
||||
}else{ |
||||
this.workNumberReapeat = false |
||||
} |
||||
}, |
||||
async phoneChange(){ |
||||
let res = await this.$get(this.api.queryPhone, { phone: this.regForm.phone }); |
||||
if(res.message.length != 0){ |
||||
this.$message.warning('该手机号已存在'); |
||||
this.phoneRepeat = true |
||||
}else{ |
||||
this.phoneRepeat = false |
||||
} |
||||
}, |
||||
batchImport(){ |
||||
this.importVisible = true |
||||
this.uploadList = [] |
||||
this.uploadFaild = false |
||||
}, |
||||
// 获取学校/客户名称 |
||||
getSchool(){ |
||||
this.clearcity() |
||||
this.getSchoolData() |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
getSchoolData(){ |
||||
let data = { |
||||
schoolName: '', |
||||
provinceId: '', |
||||
cityId: '' |
||||
} |
||||
this.$get(this.api.querySchool,data).then(res => { |
||||
this.schoolList = res.message |
||||
}).catch(res => {}); |
||||
}, |
||||
closeStudent(){ |
||||
this.isDetail = false |
||||
this.$refs.form.clearValidate() |
||||
this.form = { |
||||
schoolId: this.schoolId, |
||||
userName: '', |
||||
account: '', |
||||
phone: '', |
||||
uniqueIdentificationAccount: '', |
||||
workNumber: '', |
||||
email: '', |
||||
account: '', |
||||
roleId: 4, |
||||
schoolAppellationId: this.schoolId |
||||
} |
||||
}, |
||||
currentChange(val) { |
||||
this.page = val; |
||||
this.getData(); |
||||
}, |
||||
addStudent(){ |
||||
this.isAdd = true |
||||
this.studentVisible = true |
||||
}, |
||||
editStudent(row,isDetail){ |
||||
this.isAdd = false |
||||
this.isDetail = isDetail |
||||
this.studentVisible = true |
||||
this.form = Object.assign({},row) |
||||
this.$nextTick(() => { |
||||
this.$refs.form.clearValidate() |
||||
}) |
||||
}, |
||||
downLoad(){ |
||||
location.href = this.api.studentTemplate |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(this.api.daleteStudent,[row.studentId]).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
getRowKeys(row) { |
||||
return row.userId; |
||||
}, |
||||
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.$post(this.api.daleteStudent,data).then(res => { |
||||
this.multipleSelection = []; |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}).catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !'); |
||||
} |
||||
}, |
||||
resetPassword(row){ |
||||
this.$confirm(`重置后的密码为:${this.$config.initialPassword},确定重置?`, '提示', { |
||||
}).then(() => { |
||||
this.$put(this.api.reSetPassword,[row.userId]).then(res => { |
||||
if(res.errmessage == 'success') util.successMsg('重置成功') |
||||
}).catch(res => {}); |
||||
}).catch(() => { |
||||
}); |
||||
}, |
||||
switchOff(val,row,index) { |
||||
console.log(11,val,row) |
||||
let data = { |
||||
studentId: row.studentId, |
||||
disableAccount: row.disableAccount ? 0 : 1 |
||||
} |
||||
this.$put(this.api.disableAccount,data) |
||||
.then(res => {}) |
||||
.catch(err => {}); |
||||
}, |
||||
closePassword() { |
||||
this.passwordForm = { |
||||
password: '', |
||||
newPassword: '', |
||||
reNewPassword: '' |
||||
} |
||||
}, |
||||
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.passwordForm.password === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致') |
||||
|
||||
let data = this.passwordForm |
||||
data.userid = this.userId |
||||
this.$put(this.api.reSetPassword,data) |
||||
.then(res => { |
||||
if(res.errmessage == 'success'){ |
||||
util.successMsg('更换成功') |
||||
this.passwordVisible = false |
||||
} |
||||
}) |
||||
.catch(err => { |
||||
console.log(err); |
||||
}); |
||||
}, |
||||
// 上传文件 |
||||
handleExceed(files, fileList) { |
||||
this.$message.warning( |
||||
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||
); |
||||
}, |
||||
showFaild(){ |
||||
location.href = `${this.api.export_failureStudent}?token=${this.token}` |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
this.uploadFaild = false |
||||
if(res.errmessage == 'success'){ |
||||
if(res.data.token){ |
||||
this.token = res.data.token |
||||
this.uploadFaild = true |
||||
}else{ |
||||
util.successMsg('上传成功') |
||||
} |
||||
}else{ |
||||
res.message ? util.errorMsg(res.message) : util.errorMsg('上传失败,请检查数据') |
||||
} |
||||
}, |
||||
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.keyword = '' |
||||
this.getData() |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,61 @@ |
||||
<template> |
||||
<div class="page" style="padding: 0"> |
||||
<div class="tabs"> |
||||
<a class="item" v-for="(item,index) in tabs" :key="index" :class="{active: index == active}" @click="tabChange(index)">{{item}}</a> |
||||
</div> |
||||
|
||||
<staff v-if="active == 'staff'" v-auth="'系统设置:员工管理'"></staff> |
||||
<role v-else v-auth="'系统设置:角色权限'"></role> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import { mapState } from 'vuex' |
||||
import staff from './staff' |
||||
import role from './role' |
||||
export default { |
||||
data() { |
||||
return { |
||||
active: 'staff', |
||||
tabs: { |
||||
staff: '员工管理', |
||||
role: '角色权限' |
||||
}, |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('auth', [ |
||||
'btns' |
||||
]) |
||||
}, |
||||
components: { |
||||
staff, |
||||
role |
||||
}, |
||||
created() { |
||||
Setting.dynamicRoute && this.initTabs() |
||||
}, |
||||
methods: { |
||||
tabChange(index){ |
||||
this.active = index |
||||
}, |
||||
initTabs(){ |
||||
let btnPermissions = this.routes |
||||
let tab1 = btnPermissions.includes('系统设置:员工管理') |
||||
let tab2 = btnPermissions.includes('系统设置:角色权限') |
||||
|
||||
if(!tab1){ |
||||
delete this.tabs.staff |
||||
} |
||||
if(!tab2){ |
||||
delete this.tabs.role |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,307 @@ |
||||
<template> |
||||
<div class="page"> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<el-input size="small" placeholder="请输入角色名称" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</li> |
||||
</ul> |
||||
<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="listData" class="table" ref="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="name" label="角色名称" align="center" width="100"> |
||||
</el-table-column> |
||||
<el-table-column label="角色描述" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-input placeholder="该角色用于管理全部功能权限" v-model="scope.row.description" disabled></el-input> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="showRole(scope.row)" v-auth="'system:角色权限:查看'">查看</el-button> |
||||
<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> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next" :total="total"></el-pagination> |
||||
</div> |
||||
|
||||
<el-dialog :title="isDetail ? '查看角色' : (isAdd ? '新增角色' : '编辑角色')" :visible.sync="roleVisible" width="30%" @close="closeRole" class="dialog" :close-on-click-modal="false"> |
||||
<el-form ref="form" label-width="100px" :disabled="isDetail"> |
||||
<el-form-item label="角色名称"> |
||||
<el-input v-model="form.name " ref="account" placeholder="请输入角色名称"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="角色描述"> |
||||
<el-input v-model="form.description " 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 size="small" @click="roleVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="saveData">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
export default { |
||||
data() { |
||||
return { |
||||
keyword: '', |
||||
searchTimer: null, |
||||
isDetail: false, |
||||
form: { |
||||
roleId: '', |
||||
name: '', |
||||
description: '', |
||||
}, |
||||
listData:[], |
||||
data: [{ |
||||
id: 1, |
||||
label: '一级 1', |
||||
children: [{ |
||||
id: 4, |
||||
label: '二级 1-1', |
||||
children: [{ |
||||
id: 9, |
||||
label: '三级 1-1-1' |
||||
}, { |
||||
id: 10, |
||||
label: '三级 1-1-2' |
||||
}] |
||||
}] |
||||
}, { |
||||
id: 2, |
||||
label: '一级 2', |
||||
children: [{ |
||||
id: 5, |
||||
label: '二级 2-1' |
||||
}, { |
||||
id: 6, |
||||
label: '二级 2-2' |
||||
}] |
||||
}, { |
||||
id: 3, |
||||
label: '一级 3', |
||||
children: [{ |
||||
id: 7, |
||||
label: '二级 3-1' |
||||
}, { |
||||
id: 8, |
||||
label: '二级 3-2' |
||||
}] |
||||
}], |
||||
defaultProps: { |
||||
children: 'children', |
||||
label: 'name' |
||||
}, |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
multipleSelection: [], |
||||
isAdd: true, |
||||
roleVisible: false, |
||||
permissions: [], |
||||
checkedIds: [] |
||||
}; |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.getData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
name: util.encodeStr(this.keyword), |
||||
page: this.page, |
||||
size: this.pageSize |
||||
} |
||||
this.$get(this.api.rolePermissionList,data).then(res => { |
||||
this.listData = res.data.list |
||||
this.total = res.data.totalCount |
||||
}).catch(res => {}); |
||||
}, |
||||
currentChange(val) { |
||||
this.page = val; |
||||
this.getData(); |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
roleIds: [row.roleId] |
||||
} |
||||
this.$post(`${this.api.delRolePermission}`,data).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}) |
||||
}, |
||||
getRowKeys(row) { |
||||
return row.roleId; |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
delAllSelection() { |
||||
if(this.multipleSelection.length){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.roleId |
||||
}) |
||||
|
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
roleIds: delList |
||||
} |
||||
this.$post(`${this.api.delRolePermission}`,data).then(res => { |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}) |
||||
}else{ |
||||
util.errorMsg('请先选择数据!') |
||||
} |
||||
}, |
||||
closeRole(){ |
||||
this.isDetail = false |
||||
this.form = { |
||||
roleId: '', |
||||
name: '', |
||||
description: '' |
||||
} |
||||
this.checkedIds = [] |
||||
this.permissions = [] |
||||
}, |
||||
getPer(row){ |
||||
if(!this.permissions.length){ |
||||
this.$get(this.api.roleTree).then(res => { |
||||
let data = res.data |
||||
let yw = data.findIndex(n => n.name == '业务后台') |
||||
yw != -1 && data.splice(yw,1) |
||||
try { |
||||
let system = data.findIndex(n => n.name == '系统设置') |
||||
|
||||
if(system != -1){ |
||||
data[system].children[1].children.splice(4,1) |
||||
data[system].children[1].children.splice(1,1) |
||||
data[system].children[1].children.splice(0,1) |
||||
} |
||||
} catch (error) {} |
||||
this.permissions = data |
||||
if(row){ |
||||
this.getDetail(row) |
||||
} |
||||
}).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){ |
||||
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id),1) |
||||
} |
||||
e.children && e.children.length && this.handleRolePer(data,e.children) |
||||
}) |
||||
} |
||||
return result |
||||
}, |
||||
async getDetail(row){ |
||||
let res = await this.$get(`${this.api.queryPermissionArrById}?roleId=${row.roleId}`) |
||||
if(res.success){ |
||||
this.form = res.data |
||||
this.form.roleId = row.roleId |
||||
this.checkedIds = this.handleRolePer(res.data.permissionIds,this.permissions) |
||||
this.$refs.per.setCheckedNodes(this.checkedIds) |
||||
} |
||||
}, |
||||
showRole(row){ |
||||
this.isDetail = true |
||||
this.isAdd = false |
||||
this.getPer(row) |
||||
this.roleVisible = true |
||||
}, |
||||
editRole(row){ |
||||
this.isAdd = false |
||||
this.getPer(row) |
||||
this.roleVisible = true |
||||
}, |
||||
async saveData() { |
||||
if(!this.form.name) return this.$message.warning('请填写角色名称') |
||||
if(!this.form.description) return this.$message.warning('请填写角色描述') |
||||
if(!this.$refs.per.getCheckedKeys().length) return this.$message.warning('请选择角色权限') |
||||
let permissionIds = [...this.$refs.per.getHalfCheckedKeys(),...this.$refs.per.getCheckedKeys()] |
||||
let data = { |
||||
roleId: this.form.roleId, |
||||
name: this.form.name, |
||||
description: this.form.description, |
||||
permissionIds |
||||
} |
||||
if(this.form.roleId){ |
||||
this.$post(this.api.updateRolePermission,data).then(res => { |
||||
util.successMsg('修改成功') |
||||
this.getData() |
||||
this.roleVisible = false |
||||
}).catch(res => {}) |
||||
}else{ |
||||
this.$post(this.api.saveRolePermission,data).then(res => { |
||||
util.successMsg('新增成功') |
||||
this.getData() |
||||
this.roleVisible = false |
||||
}).catch(res => {}) |
||||
} |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -0,0 +1,864 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
<div class="side"> |
||||
<TeacherSide ref="getSelectData" @fircheck="fircheck" @twocheck="twocheck" @getData="getData" @delDep="delDep"></TeacherSide> |
||||
</div> |
||||
|
||||
<div class="right"> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<el-input size="small" placeholder="请输入员工账号/姓名/工号" prefix-icon="el-icon-search" v-model="keyword" clearable></el-input> |
||||
</li> |
||||
</ul> |
||||
<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" ref="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="account" label="账号" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="userName" 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="NewaccountRole" label="账号角色" align="center"> |
||||
</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="操作" width="200" align="center"> |
||||
<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="page" @current-change="handleCurrentChange" :total="total"></el-pagination> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-dialog :title="isDetail ? '查看员工' : (isAddteacher ? '新增员工' : '编辑员工')" :visible.sync="teacherVisible" width="30%" @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-checkbox-group v-model="teacherForm.roleValue"> |
||||
<el-checkbox label="老师"></el-checkbox> |
||||
<el-checkbox label="管理员"></el-checkbox> |
||||
<!-- <el-checkbox label="学生" disabled></el-checkbox> --> |
||||
</el-checkbox-group> |
||||
</el-form-item> |
||||
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识"> |
||||
<el-input disabled v-model="teacherForm.uniqueIdentificationAccount" placeholder="请输入职工工号获取唯一标识"></el-input> |
||||
</el-form-item> |
||||
<template v-if="teacherForm.roleValue.some((n) => n == '老师')"> |
||||
<el-form-item prop="teacherWorkNumber" label="老师职工工号"> |
||||
<el-input v-model="teacherForm.teacherWorkNumber" placeholder="请输入老师职工工号" @change="OnlyId(14)"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="teacherMajor" label="老师一级部门"> |
||||
<el-select v-model="teacherForm.teacherMajor" placeholder="请选择一级部门" @change="getDepartment(14)"> |
||||
<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="teacherDepartment" label="老师二级部门"> |
||||
<el-select v-model="teacherForm.teacherDepartment" placeholder="请选择二级部门" :disabled="teacherForm.teacherMajor ? false : true"> |
||||
<el-option v-for="(item,index) in teacherDepartmentList" :key="index" |
||||
:label="item.staffGradeName" :value="item.staffGradeId"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</template> |
||||
<template v-if="teacherForm.roleValue.some((n) => n == '管理员')"> |
||||
<el-form-item prop="managerWorkNumber" label="管理员职工工号"> |
||||
<el-input v-model="teacherForm.managerWorkNumber" placeholder="请输入管理员职工工号" @change="OnlyId(13)"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="managerMajor" label="管理员一级部门"> |
||||
<el-select v-model="teacherForm.managerMajor" placeholder="请选择一级部门" @change="getDepartment(13)"> |
||||
<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="managerDepartment" label="管理员二级部门"> |
||||
<el-select v-model="teacherForm.managerDepartment" placeholder="请选择二级部门" :disabled="teacherForm.managerMajor ? false : true"> |
||||
<el-option v-for="(item,index) in managerDepartmentList" :key="index" |
||||
:label="item.staffGradeName" :value="item.staffGradeId"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</template> |
||||
|
||||
<el-form-item prop="phone" label="手机号"> |
||||
<el-input v-model="teacherForm.phone" placeholder="请输入手机号" maxlength="11" @change="phoneChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="email" label="邮箱"> |
||||
<el-input v-model="teacherForm.email" placeholder="请输入邮箱" @change="emailChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="schoolId" label="所在院校"> |
||||
<el-select v-model="teacherForm.schoolId" placeholder="默认为当前院校(可修改)" filterable disabled> |
||||
<el-option v-for="(item,index) in schoolList" :key="index" :label="item.schoolName" :value="item.schoolId"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||
<el-button size="small" @click="teacherVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="saveSure('teacherForm')">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" :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 size="small" @click="importVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="uploadSure">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
import TeacherSide from './staffSide' |
||||
export default { |
||||
data() { |
||||
return { |
||||
isDetail: false, |
||||
isAddteacher: false, |
||||
teacherVisible: false, |
||||
schoolId: Setting.schoolId, |
||||
teacherForm: { |
||||
teacherId: '', |
||||
userName: '', |
||||
roleValue: [], |
||||
tearcherAccount: '', |
||||
phone: '', |
||||
uniqueIdentificationAccount: '', |
||||
teacherWorkNumber: '', |
||||
managerWorkNumber: '', |
||||
email: '', |
||||
teacherMajor: '', |
||||
teacherDepartment: '', |
||||
managerMajor: '', |
||||
managerDepartment: '', |
||||
userAccount: '', |
||||
major: '', |
||||
schoolId: Setting.schoolId |
||||
}, |
||||
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' } |
||||
], |
||||
tearcherAccount: [ |
||||
{ required: true, message: '请输入老师职工工号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[0-9]*$/, |
||||
message: '职工工号必须为数字', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
uniqueIdentificationAccount: [ |
||||
// { required: true, message: '请输入唯一标识', trigger: 'blur' }, |
||||
], |
||||
teacherWorkNumber: [ |
||||
{ required: true, message: '请输入老师职工工号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[A-Za-z0-9]+$/, |
||||
message: '请输入正确的职工工号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
teacherDepartment: [ |
||||
{ required: true, message: '请选择老师二级部门', trigger: 'change' } |
||||
], |
||||
managerMajor: [ |
||||
{ required: true, message: '请选择管理员一级部门', trigger: 'change' } |
||||
], |
||||
managerWorkNumber: [ |
||||
{ required: true, message: '请输入管理员职工工号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[A-Za-z0-9]+$/, |
||||
message: '请输入正确的职工工号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
managerDepartment: [ |
||||
{ required: true, message: '请选择管理员二级部门', trigger: 'change' } |
||||
], |
||||
teacherMajor: [ |
||||
{ 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' } |
||||
], |
||||
}, |
||||
listData: [], |
||||
importVisible: false, |
||||
keyword: '', |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
managerDepartmentList: [], |
||||
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: '', |
||||
emailNoAdd: '', |
||||
managerNumberNoAdd: true, |
||||
teacherNumberNoAdd: true, |
||||
platformId: this.$store.state.platformId, |
||||
isManager: false, |
||||
isTeacher: false, |
||||
isNewUser: 1, |
||||
schoolList: [], |
||||
uploadFaild: false, |
||||
token: '', |
||||
accountMsg: '' |
||||
}; |
||||
}, |
||||
components: { |
||||
TeacherSide |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.getData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted(){ |
||||
this.getData() |
||||
this.teacherForm.schoolId = Setting.schoolId |
||||
console.log(33,this.schoolId,this.teacherForm.schoolId) |
||||
this.getSchoolData() |
||||
}, |
||||
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){ |
||||
val.ischeck = !val.ischeck |
||||
val2.map( e => { |
||||
e.children.map( r => { |
||||
if(r.staffGradeId == val.staffGradeId){ |
||||
if(e.children.every(i => i.ischeck)){ |
||||
e.ischeck = true |
||||
}else{ |
||||
e.ischeck = false |
||||
} |
||||
} |
||||
}) |
||||
}) |
||||
this.handleCheck(val2) |
||||
}, |
||||
delDep(val,val2){ |
||||
this.handleCheck(val2) |
||||
}, |
||||
getData(){ |
||||
let data = { |
||||
staffProfessionalArchitectureIds: (this.oneDepartmentIds && this.twoDepartmentIds) ? '' : this.oneDepartmentIds, |
||||
staffGradeIds: this.twoDepartmentIds, |
||||
searchContent: util.encodeStr(this.keyword), |
||||
page: this.page, |
||||
size: this.pageSize, |
||||
schoolId: this.schoolId |
||||
} |
||||
this.$post(this.api.queryStaff,data).then(res => { |
||||
this.listData = res.data.list |
||||
this.total = res.data.totalCount |
||||
this.listData.forEach(e => { |
||||
if(e.roleId.length > 1) { |
||||
let NewaccountRole = [] |
||||
let roleIds = e.roleId.split(',') |
||||
roleIds.forEach((n,k) => { |
||||
NewaccountRole.push(util.getRoleName(n)) |
||||
}) |
||||
e.NewaccountRole = NewaccountRole.join(',') |
||||
}else{ |
||||
e.NewaccountRole = util.getRoleName(e.roleId) |
||||
} |
||||
}) |
||||
}).catch(res => {}); |
||||
}, |
||||
getSchoolData(){ |
||||
let data = { |
||||
schoolName: '', |
||||
provinceId: '', |
||||
cityId: '' |
||||
} |
||||
this.$get(this.api.querySchool,data).then(res => { |
||||
this.schoolList = res.message |
||||
}).catch(res => {}); |
||||
}, |
||||
closeTeacher(){ |
||||
this.teacherForm= { |
||||
teacherId: '', |
||||
userName: '', |
||||
roleValue: [], |
||||
tearcherAccount: '', |
||||
phone: '', |
||||
uniqueIdentificationAccount: '', |
||||
teacherWorkNumber: '', |
||||
managerWorkNumber: '', |
||||
email: '', |
||||
teacherMajor: '', |
||||
teacherDepartment: '', |
||||
managerMajor: '', |
||||
managerDepartment: '', |
||||
userAccount: '', |
||||
major: '', |
||||
schoolId: this.schoolId |
||||
} |
||||
this.isManager = false |
||||
this.isTeacher = false |
||||
this.$refs.teacherForm.clearValidate() |
||||
}, |
||||
addTeacher(){ |
||||
this.isDetail = false |
||||
this.teacherVisible = true |
||||
this.isAddteacher = true |
||||
this.teacherForm.teacherId = '' |
||||
this.majorList = this.$refs.getSelectData.majorList |
||||
this.$refs.teacherForm.clearValidate() |
||||
}, |
||||
getStaffDetail(userId){ |
||||
let data = { |
||||
userId: userId |
||||
} |
||||
this.$get(this.api.querystaffDetail,data).then(res => { |
||||
let user = res.data.userInfo; |
||||
let or = res.data.staffInfo; |
||||
this.teacherForm.userName = user.userName |
||||
this.teacherForm.phone = user.phone |
||||
this.teacherForm.email = user.email |
||||
this.teacherForm.userAccount = user.account |
||||
this.teacherForm.userId = user.userId |
||||
this.teacherForm.schoolId = user.schoolId |
||||
this.teacherForm.uniqueIdentificationAccount = user.uniqueIdentificationAccount |
||||
or.forEach((n,i) => { |
||||
this.teacherForm.roleValue.push(util.getRoleName(n.roleId)) |
||||
if(n.roleId == 13) { |
||||
this.teacherForm.managerMajor = n.staffProfessionalArchitectureId |
||||
this.teacherForm.managerDepartment = n.staffGradeId |
||||
this.teacherForm.managerWorkNumber = n.workNumber |
||||
this.isManager = true |
||||
this.teacherForm.managerStaffId = n.staffId |
||||
this.getDepartment(13) |
||||
}else if(n.roleId == 14){ |
||||
this.teacherForm.teacherMajor = n.staffProfessionalArchitectureId |
||||
this.teacherForm.teacherDepartment = n.staffGradeId |
||||
this.teacherForm.teacherWorkNumber = n.workNumber |
||||
this.isTeacher = true |
||||
this.teacherForm.teacherStaffId = n.staffId |
||||
this.getDepartment(14) |
||||
} |
||||
}) |
||||
}).catch(res => {}); |
||||
}, |
||||
editTeacher(row){ |
||||
this.isDetail = false |
||||
this.teacherVisible = true |
||||
this.isAddteacher = false |
||||
this.AccountNoAdd = false |
||||
this.teacherForm.teacherId = row.userId |
||||
this.majorList = this.$refs.getSelectData.majorList |
||||
this.isNewUser = 0 |
||||
this.getStaffDetail(row.userId) |
||||
}, |
||||
resetPassword(row){ |
||||
this.$confirm(`重置后的密码为:${this.$config.initialPassword},确定重置?`, '提示', { |
||||
}).then(() => { |
||||
let data = { |
||||
newPwd: this.$config.initialPassword, |
||||
userId: row.userId, |
||||
} |
||||
this.$get(this.api.resetPwd,data).then(res => { |
||||
if(res.errmessage == 'success'){ |
||||
util.successMsg('重置成功') |
||||
}else{ |
||||
util.errorMsg('重置失败') |
||||
} |
||||
}).catch(res => {}); |
||||
}).catch(() => { |
||||
}); |
||||
}, |
||||
showTeacher(row){ |
||||
this.isDetail = true |
||||
this.teacherVisible = true |
||||
this.isAddteacher = false |
||||
this.AccountNoAdd = false |
||||
this.teacherForm.teacherId = row.userId |
||||
this.majorList = this.$refs.getSelectData.majorList |
||||
this.isNewUser = 0 |
||||
this.getStaffDetail(row.userId) |
||||
}, |
||||
getDepartment(type){ |
||||
let data = { |
||||
staffProfessionalArchitectureId: type == 13 ? this.teacherForm.managerMajor : this.teacherForm.teacherMajor |
||||
} |
||||
this.$get(this.api.queryStaffGrade,data).then(res => { |
||||
if(type == 13){ |
||||
this.managerDepartmentList = res.message |
||||
}else{ |
||||
this.teacherDepartmentList = res.message |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
async phoneChange(){ |
||||
let res = await this.$get(this.api.queryPhone, { phone: this.teacherForm.phone }); |
||||
if(res.message.length != 0){ |
||||
this.$message.warning('该手机号已存在'); |
||||
this.NoAdd = false |
||||
}else{ |
||||
this.NoAdd = true |
||||
} |
||||
}, |
||||
async emailChange(){ |
||||
let res = await this.$get(this.api.queryEmail, { email: this.teacherForm.email }); |
||||
if(res.message.length != 0){ |
||||
this.$message.warning('该邮箱已存在'); |
||||
this.emailNoAdd = false |
||||
}else{ |
||||
this.emailNoAdd = true |
||||
} |
||||
}, |
||||
async accountChange(){ |
||||
let res = await this.$get(this.api.queryAccountIsExist, { |
||||
account: util.encodeStr(this.teacherForm.userAccount), |
||||
schoolId: this.schoolId |
||||
}); |
||||
if(this.isAddteacher){ |
||||
this.isManager = false |
||||
this.isTeacher = false |
||||
} |
||||
if(res.message.user.length != 0){ |
||||
let user = res.message.user[0]; |
||||
let or = res.message.OR; |
||||
if(user.roleId){ |
||||
this.accountMsg = user.roleId.includes(',') ? '该账号已绑定老师和管理员' : `该账号已绑定${util.getRoleName(user.roleId)}` |
||||
}else{ |
||||
this.accountMsg = '该账号已存在' |
||||
} |
||||
|
||||
this.$message.warning(this.accountMsg) |
||||
this.teacherForm.email = user.email |
||||
this.teacherForm.phone = user.phone |
||||
this.teacherForm.uniqueIdentificationAccount = user.uniqueIdentificationAccount |
||||
this.teacherForm.userName = user.userName |
||||
// this.teacherForm.schoolId = user.schoolId |
||||
this.teacherForm.userId = user.userId |
||||
this.isNewUser = 0 |
||||
or.forEach((n,i) => { |
||||
this.teacherForm.roleValue.push(util.getRoleName(n.roleId)) |
||||
if(n.roleId == 13) { |
||||
this.teacherForm.managerMajor = n.oneDepartmentId |
||||
this.teacherForm.managerDepartment = n.twoDepartmentId |
||||
this.teacherForm.managerWorkNumber = n.workNumber |
||||
this.teacherForm.managerSchoolId = n.schoolId |
||||
this.teacherForm.managerSchoolName = n.schoolName |
||||
this.isManager = true |
||||
this.getDepartment(13) |
||||
}else if(n.roleId == 14){ |
||||
this.teacherForm.teacherMajor = n.oneDepartmentId |
||||
this.teacherForm.teacherDepartment = n.twoDepartmentId |
||||
this.teacherForm.teacherWorkNumber = n.workNumber |
||||
this.teacherForm.teacherSchoolId = n.schoolId |
||||
this.teacherForm.tacherSchoolName = n.schoolName |
||||
this.isTeacher = true |
||||
this.getDepartment(14) |
||||
} |
||||
}) |
||||
this.AccountNoAdd = false |
||||
}else{ |
||||
this.isNewUser = 1 |
||||
this.AccountNoAdd = true |
||||
this.teacherForm.userName = '' |
||||
} |
||||
}, |
||||
async submitOnlyId(){ |
||||
if(this.teacherForm.managerWorkNumber != ''){ |
||||
this.OnlyId(13) |
||||
}else if(this.teacherForm.teacherWorkNumber != ''){ |
||||
this.OnlyId(14) |
||||
} |
||||
}, |
||||
async OnlyId(type){ |
||||
let data = {}; |
||||
let msg = ''; |
||||
if(type == 13){ |
||||
data = { |
||||
workNumber: util.encodeStr(this.teacherForm.managerWorkNumber), |
||||
roleId: 13, |
||||
schoolId: this.teacherForm.schoolId |
||||
} |
||||
msg = '该管理员工号已存在' |
||||
}else if(type == 14){ |
||||
data = { |
||||
workNumber: util.encodeStr(this.teacherForm.teacherWorkNumber), |
||||
roleId: 14, |
||||
schoolId: this.teacherForm.schoolId |
||||
} |
||||
msg = '该老师工号已存在' |
||||
} |
||||
let res = await this.$get(this.api.queryWorkNumberIsExist, data); |
||||
if(JSON.stringify(res.message) != '{}'){ |
||||
this.$message.warning(msg); |
||||
type == 13 ? (this.managerNumberNoAdd = false) : (this.teacherNumberNoAdd = false) |
||||
}else{ |
||||
let timestamp = Date.parse(new Date()); |
||||
this.teacherForm.uniqueIdentificationAccount = `${this.schoolId}${this.teacherForm.uniqueIdentificationAccount}${timestamp}` |
||||
type == 13 ? (this.managerNumberNoAdd = true) : (this.teacherNumberNoAdd = true) |
||||
} |
||||
}, |
||||
async saveSure(teacherForm){ |
||||
this.$refs[teacherForm].validate((valid) => { |
||||
if (valid) { |
||||
if(this.isAddteacher) { |
||||
if(this.isManager && this.isTeacher) return this.$message.warning('该用户已经是老师和管理员,请重新添加'); |
||||
if(this.isManager && !this.teacherForm.roleValue.some((n) => n == '老师')) return this.$message.warning('该用户已经是管理员'); |
||||
if(this.isTeacher && !this.teacherForm.roleValue.some((n) => n == '管理员')) return this.$message.warning('该用户已经是老师'); |
||||
if(!this.AccountNoAdd) return this.$message.warning(this.accountMsg) |
||||
if(this.NoAdd == '' && this.teacherForm.phone){ |
||||
this.phoneChange() |
||||
if(!this.NoAdd) return false |
||||
}else if(this.NoAdd === false){ |
||||
return this.$message.warning('该手机号已存在') |
||||
}else if(this.emailNoAdd === false){ |
||||
return this.$message.warning('该邮箱已存在') |
||||
} |
||||
} |
||||
if(!this.managerNumberNoAdd) return this.$message.warning('该管理员工号已存在'); |
||||
if(!this.teacherNumberNoAdd) return this.$message.warning('该老师工号已存在'); |
||||
|
||||
let roleId = [] |
||||
this.teacherForm.roleValue.includes('管理员') && roleId.push(13) |
||||
this.teacherForm.roleValue.includes('老师') && roleId.push(14) |
||||
let data = { |
||||
userName: this.teacherForm.userName, |
||||
account: this.teacherForm.userAccount, |
||||
schoolId: this.teacherForm.schoolId, |
||||
roleId: roleId.join(','), |
||||
phone: this.teacherForm.phone, |
||||
email: this.teacherForm.email, |
||||
uniqueIdentificationAccount: this.teacherForm.uniqueIdentificationAccount ? this.teacherForm.uniqueIdentificationAccount : Date.parse(new Date()), |
||||
userId: this.teacherForm.userId ? this.teacherForm.userId : '' |
||||
} |
||||
data.staff = []; |
||||
|
||||
if((!this.isAddteacher && this.teacherForm.managerWorkNumber && roleId.includes(13)) || (this.isAddteacher && !this.isManager && this.teacherForm.managerWorkNumber)){ |
||||
let oneDepartmentName = ''; |
||||
for(let i in this.majorList){ |
||||
if(this.majorList[i].staffProfessionalArchitectureId == this.teacherForm.managerMajor) { |
||||
oneDepartmentName = this.majorList[i].staffProfessionalArchitectureName |
||||
break; |
||||
} |
||||
} |
||||
let twoDepartmentName = this.managerDepartmentList.find((n) => { |
||||
return n.staffGradeId == this.teacherForm.managerDepartment |
||||
}).staffGradeName; |
||||
let orList = { |
||||
roleId: 13, |
||||
staffId: this.teacherForm.managerStaffId, |
||||
workNumber: this.teacherForm.managerWorkNumber, |
||||
staffProfessionalArchitectureId: this.teacherForm.managerMajor, |
||||
staffGradeId: this.teacherForm.managerDepartment, |
||||
staffProfessionalArchitectureName: oneDepartmentName, |
||||
staffGradeName: twoDepartmentName, |
||||
}; |
||||
data.staff.push(orList) |
||||
} |
||||
if((!this.isAddteacher && this.teacherForm.teacherWorkNumber && roleId.includes(14)) || (this.isAddteacher && !this.isTeacher && this.teacherForm.teacherWorkNumber)){ |
||||
let oneDepartmentName = ''; |
||||
for(let i in this.majorList){ |
||||
if(this.majorList[i].staffProfessionalArchitectureId == this.teacherForm.teacherMajor) { |
||||
oneDepartmentName = this.majorList[i].staffProfessionalArchitectureName |
||||
break; |
||||
} |
||||
} |
||||
let twoDepartmentName = this.teacherDepartmentList.find((n) => { |
||||
return n.staffGradeId == this.teacherForm.teacherDepartment |
||||
}).staffGradeName; |
||||
let orList = { |
||||
roleId: 14, |
||||
staffId: this.teacherForm.teacherStaffId, |
||||
workNumber: this.teacherForm.teacherWorkNumber, |
||||
staffProfessionalArchitectureId: this.teacherForm.teacherMajor, |
||||
staffGradeId: this.teacherForm.teacherDepartment, |
||||
staffProfessionalArchitectureName: oneDepartmentName, |
||||
staffGradeName: twoDepartmentName, |
||||
}; |
||||
data.staff.push(orList) |
||||
} |
||||
if(this.teacherForm.teacherId){ |
||||
this.$put(this.api.updateStaff,data).then(res => { |
||||
this.teacherVisible = false |
||||
util.successMsg('编辑成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}else{ |
||||
this.$post(this.api.addStaff,data).then(res => { |
||||
this.teacherVisible = false |
||||
util.successMsg('添加成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
} |
||||
}else{ |
||||
return false; |
||||
} |
||||
}) |
||||
}, |
||||
delTeacher(row){ |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$post(this.api.daleteBatchStaff,[row.userId]).then(res => { |
||||
util.successMsg('删除成功') |
||||
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.userId |
||||
}) |
||||
// 批量删除 |
||||
this.$confirm('确定要删除吗?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = delList |
||||
this.$post(this.api.daleteBatchStaff,data).then(res => { |
||||
this.$refs.table.clearSelection() |
||||
this.multipleSelection = []; |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}).catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择员工 !') |
||||
} |
||||
}, |
||||
batchImport(){ |
||||
this.importVisible = true |
||||
this.uploadList = [] |
||||
this.uploadFaild = false |
||||
}, |
||||
searchTeacher(){ |
||||
this.page = 1; |
||||
this.getData() |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val; |
||||
this.getData(); |
||||
}, |
||||
downLoad(){ |
||||
location.href = this.api.staffTemplate |
||||
}, |
||||
showFaild(){ |
||||
location.href = `${this.api.export_failureStaff}?token=${this.token}` |
||||
}, |
||||
// 上传文件 |
||||
handleExceed(files, fileList) { |
||||
this.$message.warning( |
||||
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||
); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
this.uploadFaild = false |
||||
if(res.errmessage == 'success'){ |
||||
if(res.data.token){ |
||||
this.token = res.data.token |
||||
this.uploadFaild = true |
||||
}else{ |
||||
util.successMsg('上传成功') |
||||
} |
||||
}else{ |
||||
res.message ? util.errorMsg(res.message) : util.errorMsg('上传失败,请检查数据') |
||||
} |
||||
}, |
||||
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.keyword = '' |
||||
this.getData() |
||||
}, |
||||
// 获取学科类别 |
||||
getSubject(){ |
||||
this.$get(this.api.queryCourseDiscipline).then(res => { |
||||
this.subjectList = res.message |
||||
}).catch(res => {}); |
||||
}, |
||||
// 清除学科类别 |
||||
clearClass(){ |
||||
this.teacherForm.professionalClassId = '', |
||||
this.teacherForm.professionalId = '' |
||||
}, |
||||
// 获取专业类 |
||||
getProfessionalClass(){ |
||||
this.clearClass() |
||||
if(this.teacherForm.disciplineId){ |
||||
this.getProfessionalClassData() |
||||
} |
||||
}, |
||||
getProfessionalClassData(){ |
||||
let data = { |
||||
disciplineId: this.teacherForm.disciplineId |
||||
} |
||||
this.$get(this.api.queryCourseProfessionalClass,data).then(res => { |
||||
this.ProfessionalClassList = res.message |
||||
}).catch(res => {}); |
||||
}, |
||||
// 清除专业类 |
||||
clearProfess(){ |
||||
this.teacherForm.professionalId = '' |
||||
}, |
||||
// 获取专业 |
||||
getProfessional(){ |
||||
this.clearProfess() |
||||
if(this.teacherForm.professionalClassId){ |
||||
this.getProfessionalData() |
||||
} |
||||
}, |
||||
getProfessionalData(){ |
||||
let data = { |
||||
professionalClassId: this.teacherForm.professionalClassId |
||||
} |
||||
this.$get(this.api.queryCourseProfessional,data).then(res => { |
||||
this.ProfessionalList = res.message |
||||
}).catch(res => {}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.wrap{ |
||||
display: flex; |
||||
padding: 24px; |
||||
.side{ |
||||
width: 350px; |
||||
margin-right: 24px; |
||||
} |
||||
.right{ |
||||
width: calc(100% - 374px); |
||||
padding: 24px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,363 @@ |
||||
<template> |
||||
<div> |
||||
<div> |
||||
<lctree :data="majorList" |
||||
@addMajor="addMajor" @editMajor="editMajor" @delMajor="delMajor" |
||||
@addDepartment="addDepartment" @editDepartment="editDepartment" @delDepartment="delDepartment" |
||||
@fircheckitem="fircheckitem" @twocheckitem="twocheckitem" |
||||
></lctree> |
||||
</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" :rules="rules"> |
||||
<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" :rules="rules"> |
||||
<el-form-item prop="departmentName"> |
||||
<el-input placeholder="请输入部门名称" v-model="Form.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('Form')">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
import { mapState, mapActions } from 'vuex' |
||||
import lctree from './stafftree' |
||||
export default { |
||||
props:["Data"], |
||||
data() { |
||||
return { |
||||
majorList: [], |
||||
firactive: 0, |
||||
twoactive: 0, |
||||
isaddMajor: false, |
||||
isAddDepartment: false, |
||||
schoolId: Setting.schoolId, |
||||
Form: { |
||||
MajorId: '', |
||||
majorName: '', |
||||
departmentId: '', |
||||
departmentName: '' |
||||
}, |
||||
rules: { |
||||
majorName: [ |
||||
{ required: true, message: '请输入专业名称', trigger: 'blur' } |
||||
], |
||||
departmentName: [ |
||||
{ required: true, message: '请输入部门名称', trigger: 'blur' } |
||||
] |
||||
}, |
||||
staffstateProfessId: '', |
||||
staffstateId: '', |
||||
majorNoAdd: true |
||||
}; |
||||
}, |
||||
components: { |
||||
lctree |
||||
}, |
||||
mounted(){ |
||||
this.getStaff() |
||||
}, |
||||
methods: { |
||||
getStaff(){ |
||||
let data = { |
||||
schoolId: this.schoolId |
||||
} |
||||
this.$get(this.api.queryStaffPro,data).then(res => { |
||||
if(res.message){ |
||||
res.message.map(e => { |
||||
(e.ifVisible = false), (e.ischeck = false), (e.label = e.staffProfessionalArchitectureName); |
||||
let data = { |
||||
staffProfessionalArchitectureId: e.staffProfessionalArchitectureId |
||||
} |
||||
this.$get(this.api.queryStaffGrade,data).then(res => { |
||||
res.message.map(e => { |
||||
(e.ischeck = false), (e.label = e.staffGradeName); |
||||
}) |
||||
e.children = res.message |
||||
}).catch(res => {}); |
||||
}) |
||||
} |
||||
setTimeout(() => { |
||||
this.majorList = res.message |
||||
}, 500); |
||||
}).catch(res => {}); |
||||
}, |
||||
// 选择专业 |
||||
fircheckitem(item){ |
||||
this.$emit("fircheck",item,this.majorList) |
||||
}, |
||||
// 选择部门 |
||||
twocheckitem(item){ |
||||
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.schoolId }); |
||||
if(res.message.length != 0){ |
||||
this.$message.warning('该一级部门已存在'); |
||||
this.majorNoAdd = false |
||||
}else{ |
||||
this.majorNoAdd = true |
||||
} |
||||
}, |
||||
sure(Form){ |
||||
this.$refs[Form].validate((valid) => { |
||||
if (valid) { |
||||
if(!this.majorNoAdd) return this.$message.warning('该一级部门已存在'); |
||||
let data = { |
||||
staffProfessionalArchitectureName: this.Form.majorName, |
||||
staffProfessionalArchitectureId: this.Form.MajorId, |
||||
schoolId: this.schoolId, |
||||
} |
||||
if(this.Form.MajorId){ |
||||
this.$post(this.api.updateStaffPro,data).then(res => { |
||||
util.successMsg('编辑成功'); |
||||
this.isaddMajor = false |
||||
this.majorList.map(e =>{ |
||||
if(e.staffProfessionalArchitectureId == this.Form.MajorId){ |
||||
e.staffProfessionalArchitectureName = this.Form.majorName |
||||
e.label = this.Form.majorName |
||||
} |
||||
}) |
||||
this.$emit('getData') |
||||
}).catch(res => {}); |
||||
}else{ |
||||
this.$post(this.api.addStaffPro,data).then(res => { |
||||
util.successMsg('添加成功'); |
||||
this.isaddMajor = false |
||||
let newData = { |
||||
staffProfessionalArchitectureId: res.message, |
||||
staffProfessionalArchitectureName: this.Form.majorName, |
||||
label: this.Form.majorName, |
||||
ifVisible: false, |
||||
ischeck: false, |
||||
children: [] |
||||
} |
||||
this.majorList.push(newData) |
||||
}).catch(res => {}); |
||||
} |
||||
}else{ |
||||
return false; |
||||
} |
||||
}) |
||||
}, |
||||
// 新增编辑部门 |
||||
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].staffGradeName == item.staffGradeName){ |
||||
this.Form.MajorId = this.majorList[j].staffProfessionalArchitectureId |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
sureDepartment(Form){ |
||||
this.$refs[Form].validate((valid) => { |
||||
if (valid) { |
||||
let data = { |
||||
staffGradeName: this.Form.departmentName, |
||||
staffProfessionalArchitectureId: this.Form.MajorId, |
||||
staffGradeId: this.Form.departmentId |
||||
} |
||||
if(this.Form.departmentId){ |
||||
this.$post(this.api.updateStaffGrade,data).then(res => { |
||||
util.successMsg('编辑成功'); |
||||
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{ |
||||
this.$post(this.api.addStaffGrade,data).then(res => { |
||||
util.successMsg('添加成功'); |
||||
this.isAddDepartment = false |
||||
let newData = { |
||||
staffGradeId: res.message, |
||||
staffGradeName: this.Form.departmentName, |
||||
label: this.Form.departmentName, |
||||
ifVisible: false, |
||||
ischeck: false |
||||
} |
||||
this.majorList.map(e =>{ |
||||
if(e.staffProfessionalArchitectureId == this.Form.MajorId){ |
||||
e.ifVisible = true |
||||
e.children.push(newData) |
||||
} |
||||
}) |
||||
}).catch(res => {}); |
||||
} |
||||
}else{ |
||||
return false; |
||||
} |
||||
}) |
||||
}, |
||||
delMajor(item,index){ |
||||
this.$confirm('确定要删除该专业吗?该操作将会删除该组织下的用户账号。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
staffProfessionalArchitectureId: item.staffProfessionalArchitectureId |
||||
} |
||||
this.$post(this.api.deleteStaffPro,data).then(res => { |
||||
util.successMsg('删除成功'); |
||||
this.majorList.splice(index, 1) |
||||
this.$emit('getData') |
||||
this.$get(`${this.api.dalStaffByProfessionalId}?staffProfessionalArchitectureId=${item.staffProfessionalArchitectureId}`).then(res => {}).catch(res => {}) |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
delDepartment(item,indx){ |
||||
this.$confirm('确定要删除该部门吗?该操作将会删除该组织下的用户账号。', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
staffGradeId: item.staffGradeId |
||||
} |
||||
this.$post(this.api.deleteStaffGrade,data).then(res => { |
||||
util.successMsg('删除成功'); |
||||
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 |
||||
} |
||||
} |
||||
}) |
||||
}) |
||||
this.$emit("delDep",item,this.majorList) |
||||
this.$emit('getData') |
||||
this.$get(`${this.api.dalStaffByStaffGradeId}?staffGradeId=${item.staffGradeId}`).then(res => {}).catch(res => {}) |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
<style 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: 20px; |
||||
color: #9278FF; |
||||
} |
||||
.side_tree{ |
||||
width: 100%; |
||||
font-size: 14px; |
||||
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: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: 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,251 @@ |
||||
<template> |
||||
<div class="side_view"> |
||||
<p class="side_icon mab20"> |
||||
<i class="icon-jiahao mar20" @click="addMajor"></i> |
||||
</p> |
||||
<div class="side_tree" v-for="(item,index) in data" :key="index"> |
||||
<div class="item" @click.stop="open(item,1)"> |
||||
<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>{{item.label}}</span> |
||||
<svg t="1604370117041" class="icon edit ft" @click.stop="editMajor(item)" 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="#9076ff"></path></svg> |
||||
<i class="el-icon-circle-plus ft fz" @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,2)"> |
||||
<i :class="item1.ischeck ? 'icon-yigouxuan' : 'icon-weigouxuan'" @click.stop="twocheckitem(item1)"></i> |
||||
<span>{{item1.label}}</span> |
||||
<svg t="1604370117041" class="icon edit ft" @click.stop="editDepartment(item1)" 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="#9076ff"></path></svg> |
||||
<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,type) { |
||||
item.ifVisible = !item.ifVisible; |
||||
type == 1 ? this.$emit('fircheckitem',item) : this.$emit('twocheckitem',item) |
||||
}, |
||||
|
||||
//选中叶子节点时将选中的叶子节点添加进数组,如果叶子节点存在则删除,removeByvalue函数定义在main.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: 18px; |
||||
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; |
||||
} |
||||
.item .empty{ |
||||
width: 20px; |
||||
} |
||||
.edit{ |
||||
width: 18px !important; |
||||
height: 18px !important; |
||||
margin-left: 10px; |
||||
} |
||||
.item2 { |
||||
@include public; |
||||
margin-top: 20px; |
||||
margin-left:60px |
||||
} |
||||
.item2:hover{ |
||||
color: #9278FF; |
||||
} |
||||
|
||||
//清除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: #9278FF; |
||||
} |
||||
} |
||||
.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; |
||||
} |
||||
} |
||||
.fz{ |
||||
font-size: 20px; |
||||
} |
||||
</style> |
@ -0,0 +1,25 @@ |
||||
/** |
||||
* @description 鉴权指令 |
||||
* 当传入的权限当前用户没有时,会移除该组件 |
||||
* 用例:<Tag v-auth>text</Tag> 或者:<Tag v-auth="'user:编辑'">text</Tag> |
||||
* */ |
||||
import store from '@/store' |
||||
|
||||
export default { |
||||
inserted (el, binding, vnode) { |
||||
let btnText = '' |
||||
if(binding.value){ |
||||
btnText = binding.value |
||||
}else{ |
||||
btnText = `${vnode.context.$route.path}:${el.innerText}` |
||||
} |
||||
const btnPermissions = store.state.auth.btns |
||||
|
||||
if (btnText && btnPermissions && btnPermissions.length) { |
||||
const isPermission = btnPermissions.includes(btnText) |
||||
if (!isPermission) { |
||||
el.parentNode && el.parentNode.removeChild(el) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
/** |
||||
* @description 返回缺省值 |
||||
* 传入的如果是null,就返回'--' |
||||
* 用例:<Tag :default="val">text</Tag> 或者:<Tag>{{val | default}}</Tag> |
||||
* */ |
||||
const defaultShow = (val) => { |
||||
return val == null ? '--' : val |
||||
} |
||||
|
||||
module.exports = { |
||||
defaultShow |
||||
} |
@ -0,0 +1,14 @@ |
||||
/** |
||||
* 插件 |
||||
* */ |
||||
|
||||
import directiveAuth from '@/plugins/auth'; |
||||
import throttle from '@/plugins/throttle'; |
||||
|
||||
export default { |
||||
async install (Vue, options) { |
||||
// 指令
|
||||
Vue.directive('auth', directiveAuth); |
||||
Vue.directive('throttle', throttle); |
||||
} |
||||
} |
@ -0,0 +1,140 @@ |
||||
import axios from 'axios' |
||||
import util from '@/libs/util' |
||||
import router from '@/router/index' |
||||
import Setting from '@/setting' |
||||
|
||||
const service = axios.create({ |
||||
baseURL: Setting.apiBaseURL, |
||||
timeout: 10000000 |
||||
}) |
||||
// post请求头
|
||||
service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' |
||||
|
||||
// 请求拦截器
|
||||
service.interceptors.request.use(config => { |
||||
util.getToken() |
||||
let token = util.local.get(Setting.tokenKey) |
||||
if(token) config.headers.token = token |
||||
return config |
||||
},err => { |
||||
util.errorMsg({ |
||||
message: '退出登陆', |
||||
onClose: function () { |
||||
router.push({name: '/login'}) |
||||
} |
||||
}) |
||||
return Promise.reject(err) |
||||
}) |
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use( |
||||
response => { |
||||
const res = response.data |
||||
if(res.status == 200 || res.status == 10000) { |
||||
return Promise.resolve(res).catch(e => {}) |
||||
}else if(!res.status){ |
||||
return Promise.resolve(res).catch(e => {}) |
||||
}else { |
||||
util.errorMsg(res.errmessage) |
||||
return Promise.reject(res) |
||||
} |
||||
}, |
||||
// 服务器状态码不是200的情况
|
||||
error => { |
||||
if (error.response.status) { |
||||
switch (error.response.status) { |
||||
// 401: 未登录
|
||||
// 未登录则跳转登录页面,并携带当前页面的路径
|
||||
// 在登录成功后返回当前页面,这一步需要在登录页操作。
|
||||
case 401: |
||||
util.local.remove(Setting.storeKey) |
||||
util.local.remove(Setting.tokenKey) |
||||
util.errorMsg('登录过期,请重新登录') |
||||
setTimeout(() => { |
||||
router.replace({ |
||||
path: '/login', |
||||
query: { |
||||
redirect: router.currentRoute.fullPath |
||||
} |
||||
}) |
||||
}, 1000) |
||||
break |
||||
case 500: |
||||
util.errorMsg('网络错误') |
||||
break |
||||
// 403 token过期
|
||||
// 登录过期对用户进行提示
|
||||
// 清除本地token和清空vuex中token对象
|
||||
// 跳转登录页面
|
||||
case 403: |
||||
util.local.remove(Setting.storeKey) |
||||
util.local.remove(Setting.tokenKey) |
||||
util.errorMsg('登录过期,请重新登录') |
||||
// 清除token
|
||||
// store.commit('loginSuccess', null);
|
||||
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
|
||||
setTimeout(() => { |
||||
router.replace({ |
||||
path: '/login', |
||||
query: { |
||||
redirect: router.currentRoute.fullPath |
||||
} |
||||
}) |
||||
}, 1000) |
||||
break |
||||
// 404请求不存在
|
||||
case 404: |
||||
util.errorMsg('网络请求不存在!') |
||||
break |
||||
// 其他错误,直接抛出错误提示
|
||||
default: |
||||
util.errorMsg(error.response.data.message) |
||||
Promise.reject(res) |
||||
} |
||||
return Promise.reject(error.response) |
||||
} |
||||
} |
||||
); |
||||
|
||||
function get(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.get(url, {params: params}).then(res => { |
||||
resolve(res) |
||||
}).catch(err => { |
||||
reject(err) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
function post(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.post(url,params).then(res => { |
||||
resolve(res) |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
function del(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.delete(url, { |
||||
params |
||||
}).then(res => { |
||||
resolve(res) |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
function put(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.put(url, params).then(res => { |
||||
resolve(res) |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
export { get,post,del,put } |
@ -0,0 +1,18 @@ |
||||
/** |
||||
* @description 节流指令 |
||||
* 限制连续快速点击按钮 |
||||
* 用例:<Tag v-throttle>text</Tag> |
||||
* */ |
||||
|
||||
export default{ |
||||
inserted (el, binding, vnode) { |
||||
el.addEventListener('click', () => { |
||||
if (!el.disabled) { |
||||
el.disabled = true |
||||
setTimeout(() => { |
||||
el.disabled = false |
||||
}, binding.value || 1000) |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'achievement-' |
||||
|
||||
export default { |
||||
path: '/achievement', |
||||
name: 'achievement', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/achievement/list'), |
||||
meta: { title: '成绩管理' } |
||||
},{ |
||||
name: `${pre}vir`, |
||||
path: `vir`, |
||||
component: () => import('@/pages/achievement/vir'), |
||||
meta: { title: '成绩管理' } |
||||
},{ |
||||
name: `${pre}teach`, |
||||
path: `teach`, |
||||
component: () => import('@/pages/achievement/teach'), |
||||
meta: { title: '成绩管理' } |
||||
},{ |
||||
name: `${pre}ass`, |
||||
path: `ass`, |
||||
component: () => import('@/pages/achievement/ass'), |
||||
meta: { title: '成绩管理' } |
||||
},{ |
||||
name: `${pre}show`, |
||||
path: `show`, |
||||
component: () => import('@/pages/achievement/show'), |
||||
meta: { title: '实验报告' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,29 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'assessment-' |
||||
|
||||
export default { |
||||
path: '/assessment', |
||||
name: 'assessment', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/assessment/list'), |
||||
meta: { title: '考核管理' } |
||||
}, |
||||
{ |
||||
name: `${pre}add`, |
||||
path: `add`, |
||||
component: () => import('@/pages/assessment/add/index.vue'), |
||||
meta: { title: '添加考核' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'evaluation-' |
||||
|
||||
export default { |
||||
path: '/evaluation', |
||||
name: 'evaluation', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/evaluation/list'), |
||||
meta: { title: '测评管理' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,29 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'project-' |
||||
|
||||
export default { |
||||
path: '/project', |
||||
name: 'project', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/project/list'), |
||||
meta: { title: '实验项目管理' } |
||||
}, |
||||
{ |
||||
name: `${pre}add`, |
||||
path: `add`, |
||||
component: () => import('@/pages/project/add'), |
||||
meta: { title: '新增项目' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'setting-' |
||||
|
||||
export default { |
||||
path: '/setting', |
||||
name: 'setting', |
||||
redirect: { |
||||
name: `${pre}person` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}person`, |
||||
path: `person`, |
||||
component: () => import('@/pages/setting/person'), |
||||
meta: { title: '个人中心' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'student-' |
||||
|
||||
export default { |
||||
path: '/student', |
||||
name: 'student', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/student/list'), |
||||
meta: { title: '学生管理' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const meta = {} |
||||
|
||||
const pre = 'system-' |
||||
|
||||
export default { |
||||
path: '/system', |
||||
name: 'system', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/system/list'), |
||||
meta: { title: '系统设置' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,27 @@ |
||||
import router from './index' |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
|
||||
router.beforeEach((to, from, next) => { |
||||
document.title = Setting.titleSuffix |
||||
const role = util.local.get(Setting.tokenKey) |
||||
if (!role && to.path !== '/login') { |
||||
next('/login') |
||||
} else if(role && to.path == '/login') { |
||||
next('/index') |
||||
} else { |
||||
let mg = from.query.mg |
||||
if(mg){ |
||||
if(!to.query.mg){ |
||||
next({ |
||||
path: to.path, |
||||
query: {mg} |
||||
}) |
||||
}else{ |
||||
next() |
||||
} |
||||
}else{ |
||||
next() |
||||
} |
||||
} |
||||
}); |
@ -0,0 +1,82 @@ |
||||
import assessment from './modules/assessment' |
||||
import achievement from './modules/achievement' |
||||
import evaluation from './modules/evaluation' |
||||
import project from './modules/project' |
||||
import student from './modules/student' |
||||
import system from './modules/system' |
||||
import setting from './modules/setting' |
||||
|
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const frameIn = [ |
||||
{ |
||||
path: '/', |
||||
redirect: '/login', |
||||
}, |
||||
{ |
||||
path: '/index', |
||||
redirect: '/assessment', |
||||
}, |
||||
{ |
||||
path: '/', |
||||
component: () => BasicLayout, |
||||
meta: { title: '首页' }, |
||||
children: [] |
||||
}, |
||||
assessment, |
||||
achievement, |
||||
evaluation, |
||||
project, |
||||
student, |
||||
system, |
||||
setting, |
||||
] |
||||
|
||||
/** |
||||
* 在主框架之外显示 |
||||
*/ |
||||
|
||||
const frameOut = [ |
||||
// 登录
|
||||
{ |
||||
path: '/login', |
||||
name: 'login', |
||||
meta: { |
||||
title: '登录' |
||||
}, |
||||
component: () => import('@/pages/account/login') |
||||
} |
||||
]; |
||||
|
||||
/** |
||||
* 错误页面 |
||||
*/ |
||||
|
||||
const errorPage = [ |
||||
{ |
||||
path: '/403', |
||||
name: '403', |
||||
meta: { |
||||
title: '403' |
||||
}, |
||||
component: () => import('@/pages/exception/error/403') |
||||
}, |
||||
{ |
||||
path: '*', |
||||
name: '404', |
||||
meta: { |
||||
title: '404' |
||||
}, |
||||
component: () => import('@/pages/exception/error/404') |
||||
} |
||||
]; |
||||
|
||||
// 导出需要显示菜单的
|
||||
export const frameInRoutes = frameIn; |
||||
|
||||
// 重新组织后导出
|
||||
export default [ |
||||
...frameIn, |
||||
...frameOut, |
||||
...errorPage |
||||
]; |
@ -0,0 +1,21 @@ |
||||
/** |
||||
* 开发配置 |
||||
* */ |
||||
|
||||
const env = process.env.NODE_ENV; |
||||
|
||||
const Setting = { |
||||
// 是否使用 Mock 的数据,默认 开发环境为 true,生产环境为 false
|
||||
isMock: true, |
||||
// 部署应用包时的基本 URL
|
||||
publicPath: env === 'development' ? './' : '', |
||||
// 生产环境构建文件的目录名
|
||||
outputDir: 'dist', |
||||
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
|
||||
assetsDir: 'static', |
||||
// 开发环境每次保存时 lint 代码,会将 lint 错误输出为编译警告
|
||||
// true || false || error
|
||||
lintOnSave: true, |
||||
}; |
||||
|
||||
module.exports = Setting; |