@ -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,40 @@ |
||||
{ |
||||
"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", |
||||
"html2canvas": "^1.2.1", |
||||
"js-cookie": "^2.2.1", |
||||
"jspdf": "^2.3.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.13.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: 7.6 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 3.0 KiB |
After Width: | Height: | Size: 1.0 MiB |
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 848 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: 26 KiB |
After Width: | Height: | Size: 24 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 709 B |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 632 B |
After Width: | Height: | Size: 918 B |
After Width: | Height: | Size: 499 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 683 B |
After Width: | Height: | Size: 556 B |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 539 B |
After Width: | Height: | Size: 29 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: 5.1 KiB |
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 2.9 KiB |
After Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.2 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: 722 B |
@ -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,179 @@ |
||||
<template> |
||||
<div class="quill" :class="classes"> |
||||
<div ref="editor" :style="styles" v-loading="loading"></div> |
||||
|
||||
<el-upload :action="this.api.fileupload" :before-upload="beforeUpload" :on-success="editorUploadSuccess" style="display: none"> |
||||
<el-button class="editorUpload" size="small" type="primary">点击上传</el-button> |
||||
</el-upload> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import Quill from 'quill'; |
||||
import 'quill/dist/quill.core.css'; |
||||
import 'quill/dist/quill.snow.css'; |
||||
import 'quill/dist/quill.bubble.css'; |
||||
import toolbarOptions from './options' |
||||
|
||||
export default { |
||||
name: 'quill', |
||||
props: { |
||||
value: { |
||||
type: String, |
||||
default: '' |
||||
}, |
||||
readonly: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
toTop: { |
||||
type: Boolean, |
||||
default: true |
||||
}, |
||||
border: { |
||||
type: Boolean, |
||||
default: false |
||||
}, |
||||
height: { |
||||
type: Number |
||||
}, |
||||
minHeight: { |
||||
type: Number |
||||
} |
||||
}, |
||||
data () { |
||||
return { |
||||
Quill: null, |
||||
currentValue: '', |
||||
options: { |
||||
theme: 'snow', |
||||
bounds: document.body, |
||||
debug: 'warn', |
||||
modules: { |
||||
toolbar: { |
||||
container: toolbarOptions, |
||||
handlers: { |
||||
'image': function (value) { |
||||
if (value) { |
||||
// 调用iview图片上传 |
||||
document.querySelector('.editorUpload').click() |
||||
} else { |
||||
this.Quill.format('image', false); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}, |
||||
placeholder: '', |
||||
readOnly: this.readonly |
||||
}, |
||||
loading: false |
||||
} |
||||
}, |
||||
computed: { |
||||
classes () { |
||||
return [ |
||||
{ |
||||
'quill-no-border': !this.border |
||||
} |
||||
]; |
||||
}, |
||||
styles () { |
||||
let style = {}; |
||||
if (this.minHeight) { |
||||
style.minHeight = `${this.minHeight}px`; |
||||
} |
||||
if (this.height) { |
||||
style.height = `${this.height}px`; |
||||
} |
||||
return style; |
||||
} |
||||
}, |
||||
watch: { |
||||
value: { |
||||
handler (val) { |
||||
if (val !== this.currentValue) { |
||||
this.currentValue = val; |
||||
if (this.Quill) { |
||||
this.Quill.pasteHTML(this.value); |
||||
} |
||||
} |
||||
}, |
||||
immediate: true |
||||
} |
||||
}, |
||||
mounted () { |
||||
this.init(); |
||||
}, |
||||
beforeDestroy () { |
||||
// 在组件销毁后销毁实例 |
||||
this.Quill = null; |
||||
}, |
||||
methods: { |
||||
init () { |
||||
const editor = this.$refs.editor; |
||||
// 初始化编辑器 |
||||
this.Quill = new Quill(editor, this.options); |
||||
// 默认值 |
||||
this.Quill.pasteHTML(this.currentValue); |
||||
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; |
||||
} |
||||
} |
||||
</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,121 @@ |
||||
<template> |
||||
<div class="header"> |
||||
<div v-if="this.$route.path=='/setting/person'" class="goBack" @click="back"><i class="el-icon-arrow-left"></i>返回</div> |
||||
<template v-else> |
||||
<img class="logo hh" v-if="isHh" src="@/assets/img/logo-hh.png" /> |
||||
<img class="logo" v-else src="@/assets/img/logo.png"> |
||||
</template> |
||||
<div class="header-right"> |
||||
<div class="header-user-con"> |
||||
<div class="user" @click="toPersonal"> |
||||
<el-avatar :size="40" :src="avatar"></el-avatar> |
||||
<span class="user-avator">{{userName}}</span> |
||||
</div> |
||||
<el-divider class="ml20" direction="vertical"></el-divider> |
||||
<el-button type="text" class="ml20" @click="logout">退出</el-button> |
||||
</div> |
||||
</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' |
||||
]), |
||||
}, |
||||
mounted(){ |
||||
|
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'logout' |
||||
]), |
||||
toPersonal(){ |
||||
this.$router.push('/setting/person') |
||||
}, |
||||
back(){ |
||||
if(this.$route.path == '/addassessment'){ |
||||
this.$router.push({ path: '/teacherhome', query: { active: true }}) |
||||
}else{ |
||||
this.$router.go(-1) |
||||
} |
||||
} |
||||
}, |
||||
}; |
||||
</script> |
||||
<style scoped lang="scss"> |
||||
.goBack{ |
||||
cursor: pointer; |
||||
line-height: 60px; |
||||
height: 60px; |
||||
font-size: 16px; |
||||
font-weight: bold; |
||||
margin-left: 20px; |
||||
} |
||||
.goBack i{ |
||||
color: #9278ff; |
||||
font-size: 20px; |
||||
} |
||||
.header { |
||||
position: relative; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
box-sizing: border-box; |
||||
width: 100%; |
||||
height: 60px; |
||||
font-size: 16px; |
||||
color: #333; |
||||
} |
||||
.header .logo { |
||||
width: 150px; |
||||
margin-left: 20px; |
||||
&.hh{ |
||||
width: 500px; |
||||
} |
||||
} |
||||
.header-right { |
||||
padding-right: 50px; |
||||
} |
||||
.header-user-con { |
||||
display: flex; |
||||
align-items: center; |
||||
|
||||
.user{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
.user-avator { |
||||
margin-left: 10px; |
||||
} |
||||
.ml20{ |
||||
margin-left: 20px; |
||||
} |
||||
.user-avator img { |
||||
display: block; |
||||
width: 40px; |
||||
height: 40px; |
||||
border-radius: 50%; |
||||
} |
||||
.header-right .el-button--text{ |
||||
color: #333; |
||||
} |
||||
.header-right .el-divider--vertical{ |
||||
width: 2px; |
||||
height: 15px; |
||||
} |
||||
.header-right .el-divider{ |
||||
background-color: #333; |
||||
} |
||||
</style> |
@ -0,0 +1,69 @@ |
||||
<template> |
||||
<div class="main"> |
||||
<v-head></v-head> |
||||
<div class="layout"> |
||||
<navbar v-if="!hideNavList.includes($route.path)"></navbar> |
||||
<div class="content"> |
||||
<transition name="move" mode="out-in"> |
||||
<router-view class="view"></router-view> |
||||
</transition> |
||||
<el-backtop target=".content"></el-backtop> |
||||
<v-footer ref="footer"></v-footer> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState, mapActions } from 'vuex' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
import vHead from '../header' |
||||
import navbar from '../navbar' |
||||
import vFooter from '../footer' |
||||
export default { |
||||
data() { |
||||
return { |
||||
hideNavList: ['/record/show','/setting/person'] |
||||
}; |
||||
}, |
||||
components: { |
||||
vHead, |
||||
navbar, |
||||
vFooter |
||||
}, |
||||
computed: { |
||||
|
||||
}, |
||||
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%; |
||||
.view{ |
||||
min-height: calc(100vh - 175px); |
||||
padding: 24px; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,69 @@ |
||||
<template> |
||||
<div> |
||||
<el-tabs v-model="active" @tab-click="jump"> |
||||
<el-tab-pane v-for="(item,index) in menus" :key="index" :label="item.label" :name="item.index"></el-tab-pane> |
||||
</el-tabs> |
||||
</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, |
||||
menus: [ |
||||
{ |
||||
index: '/preview/list', |
||||
label: '课前预习' |
||||
}, |
||||
{ |
||||
index: '/station/list', |
||||
label: '实验台' |
||||
}, |
||||
{ |
||||
index: '/ass/list', |
||||
label: '考核列表' |
||||
}, |
||||
{ |
||||
index: '/record/list', |
||||
label: '实验记录' |
||||
}, |
||||
], |
||||
}; |
||||
}, |
||||
watch: { |
||||
'$route'(to,from) { |
||||
this.active = this.$route.path |
||||
} |
||||
}, |
||||
mounted() { |
||||
|
||||
}, |
||||
methods: { |
||||
jump(tab){ |
||||
this.active = tab.name |
||||
this.$router.push(tab.name).catch(err => {}) |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.el-tabs__header{ |
||||
z-index: 2; |
||||
padding: 20px 60px 0; |
||||
margin: 0; |
||||
box-shadow:0px 0px 25px 2px rgba(48,115,248,0.14); |
||||
background-color: #fff; |
||||
.el-tabs__nav-wrap::after{ |
||||
background-color: #fff; |
||||
.el-tabs__item{ |
||||
padding: 0 30px; |
||||
outline: none; |
||||
} |
||||
} |
||||
} |
||||
</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,159 @@ |
||||
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 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) |
||||
} |
||||
}, |
||||
// 成功提示
|
||||
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}) |
||||
}, |
||||
// 登录互踢
|
||||
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,574 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
<div class="header" v-if="!isHh"> |
||||
<img class="logo" src="@/assets/img/logo.png" /> |
||||
</div> |
||||
|
||||
<div class="bg"> |
||||
<div class="left"> |
||||
<div class="text" v-if="isHh"> |
||||
<p>欢迎使用</p> |
||||
<p style="margin-bottom: 15px">商学院金融工程</p> |
||||
<p>与大数据实验平台</p> |
||||
</div> |
||||
<div class="text" v-else> |
||||
<p>欢迎使用</p> |
||||
<p>Occupation Lab</p> |
||||
</div> |
||||
</div> |
||||
<div class="right"></div> |
||||
</div> |
||||
|
||||
<div class="right-form"> |
||||
<img v-if="isHh" class="logo" src="@/assets/img/logo-hh1.png" /> |
||||
|
||||
<div class="form"> |
||||
<div class="back" v-show="isReg" @click="toReg(false)"> |
||||
<i class="el-icon-back"></i> |
||||
</div> |
||||
<div v-if="!isReg"> |
||||
<el-tabs v-model="activeName"> |
||||
<el-tab-pane label="账号登录" name="0"> |
||||
<el-form :model="loginForm" :rules="loginRules" ref="loginForm" style="margin-top: 20px"> |
||||
<el-form-item label="用户名" prop="username"> |
||||
<el-input v-model="loginForm.username" placeholder="请输入账号"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="密码" prop="password"> |
||||
<el-input |
||||
type="password" |
||||
placeholder="请输入密码" |
||||
v-model="loginForm.password" |
||||
@keyup.enter.native="getSchool('loginForm')" |
||||
> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-button class="submit" type="primary" @click="getSchool('loginForm')">登录</el-button> |
||||
</el-form> |
||||
</el-tab-pane> |
||||
|
||||
<el-tab-pane label="手机号/邮箱登录" name="1"> |
||||
<el-form :model="phoneParam" :rules="phoneRules" ref="phoneParam" style="margin-top: 20px"> |
||||
<el-form-item label="手机号/邮箱" prop="userphone"> |
||||
<el-input v-model="phoneParam.userphone" placeholder="请输入手机号/邮箱"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="密码" prop="phonePassword"> |
||||
<el-input |
||||
type="password" |
||||
placeholder="请输入密码" |
||||
v-model="phoneParam.phonePassword" |
||||
@keyup.enter.native="getSchool('phoneParam')" |
||||
> |
||||
</el-input> |
||||
</el-form-item> |
||||
<el-button class="submit" type="primary" @click="getSchool('phoneParam')">登录</el-button> |
||||
</el-form> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
<div class="links"> |
||||
<!-- <el-button type="text" class="ques" @click="toReg(true)">前往注册</el-button> --> |
||||
<el-button type="text" class="forget" @click="forget">忘记密码?</el-button> |
||||
</div> |
||||
</div> |
||||
<register v-else :isReg.sync="isReg" @updateInfo="updateInfo"></register> |
||||
</div> |
||||
</div> |
||||
|
||||
<v-footer ref="footer"></v-footer> |
||||
|
||||
<el-dialog title="选择角色" :visible.sync="roleDialog" width="24%" center :close-on-click-modal="false"> |
||||
<div> |
||||
<el-select v-model="roleId" placeholder="请选择角色"> |
||||
<el-option v-for="(item,index) in roleList" :key="index" :label="item.roleName" :value="item.roleId"></el-option> |
||||
</el-select> |
||||
</div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="cancleRoleDia">取 消</el-button> |
||||
<el-button v-if="activeName == '0'" type="primary" @click="roleSure('loginForm')">确 定</el-button> |
||||
<el-button v-else type="primary" @click="roleSure('phoneParam')">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog :title="phoneReset ? '手机重置密码' : '邮箱重置密码'" :visible.sync="forgetVisible" :close-on-click-modal="false" @close="closeForget" width="30%"> |
||||
<template v-if="phoneReset"> |
||||
<el-form ref="form" label-width="60px"> |
||||
<el-form-item label="手机号"> |
||||
<el-input placeholder="请输入手机号" v-model.number="phone" maxlength="11"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="验证码"> |
||||
<div class="flex-between"> |
||||
<el-input v-model.number="phoneCode" placeholder="请输入验证码" maxlength="6"></el-input> |
||||
<el-button style="margin-left: 10px" type="text" @click="sendPhoneCode" :disabled="phoneDisabled">{{phoneBtnText}}</el-button> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="新密码"> |
||||
<el-input type="password" placeholder="请输入新密码" v-model="newPassword"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div class="switch" @click="switchType(false)"><span>邮箱重置密码</span></div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="forgetVisible = false">取 消</el-button> |
||||
<el-button type="primary" @click="updatePassword(1)">确 定</el-button> |
||||
</span> |
||||
</template> |
||||
<template v-else> |
||||
<el-form ref="form" label-width="60px"> |
||||
<el-form-item label="邮箱"> |
||||
<el-input placeholder="请输入邮箱" v-model="email"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="验证码"> |
||||
<div class="flex-between"> |
||||
<el-input v-model.number="emailCode" placeholder="请输入验证码" maxlength="6"></el-input> |
||||
<el-button style="margin-left: 10px" type="text" @click="sendEmailCode" :disabled="emailDisabled">{{emailBtnText}}</el-button> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="新密码"> |
||||
<el-input type="password" placeholder="请输入新密码" v-model="newPassword"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div class="switch" @click="switchType(true)"><span>手机重置密码</span></div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="forgetVisible = false">取 消</el-button> |
||||
<el-button type="primary" @click="updatePassword">确 定</el-button> |
||||
</span> |
||||
</template> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import register from '../register' |
||||
import vFooter from '@/layouts/footer' |
||||
import { mapState, mapActions } from 'vuex' |
||||
import util from '@/libs/util' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data: function() { |
||||
return { |
||||
isHh: Setting.isHh, |
||||
schoolId: Setting.schoolId, |
||||
activeName: '0', |
||||
isReg: false, |
||||
loginForm: { |
||||
username: '', |
||||
password: '', |
||||
}, |
||||
loginRules: { |
||||
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' }], |
||||
}, |
||||
roleDialog: false, |
||||
userId: '', |
||||
roleId: '', |
||||
roleList: [], |
||||
forgetVisible: false, |
||||
phoneReset: true, |
||||
email: '', |
||||
emailBtnText: '发送验证码', |
||||
emailCode: '', |
||||
emailDisabled: false, |
||||
emailTimer: null, |
||||
phone: '', |
||||
phoneBtnText: '发送验证码', |
||||
phoneCode: '', |
||||
phoneDisabled: false, |
||||
phoneTimer: null, |
||||
newPassword: '', |
||||
emailOpener: '', |
||||
phoneOpener: '' |
||||
}; |
||||
}, |
||||
components: { |
||||
register, |
||||
vFooter |
||||
}, |
||||
mounted(){ |
||||
this.$once('hook:beforeDestroy', function () { |
||||
clearInterval(this.phoneTimer) |
||||
this.phoneTimer = null |
||||
clearInterval(this.emailTimer) |
||||
this.emailTimer = null |
||||
}) |
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'setInfo' |
||||
]), |
||||
getSchool(form) { |
||||
this.$refs[form].validate(valid => { |
||||
if (valid) { |
||||
let data = { |
||||
account: this.activeName == '0' ? this.loginForm.username : this.phoneParam.userphone, |
||||
password: this.activeName == '0' ? this.loginForm.password : this.phoneParam.phonePassword, |
||||
schoolId: this.schoolId, |
||||
source: this.activeName |
||||
}; |
||||
this.$get(this.api.loginSchool, data) |
||||
.then(res => { |
||||
this.schoolList = [...res.message.staffList,...res.message.studentList] |
||||
let indexs = {} |
||||
this.schoolList = this.schoolList.reduce((cur,next) => { |
||||
indexs[next.schoolId] ? '' : indexs[next.schoolId] = true && cur.push(next) |
||||
return cur |
||||
},[]) |
||||
if(this.schoolList.length >= 1) { |
||||
this.schoolId = this.schoolList[0].schoolId |
||||
this.userId = this.schoolList[0].userId |
||||
this.studentId = this.schoolList[0].studentId |
||||
this.getRole(form) |
||||
}else{ |
||||
util.errorMsg('账号不存在') |
||||
} |
||||
}) |
||||
.catch(res => {}) |
||||
} else { |
||||
util.errorMsg('请输入账号和密码') |
||||
return false |
||||
} |
||||
}); |
||||
}, |
||||
getRole(form) { |
||||
let data = { |
||||
userId: this.userId, |
||||
schoolId: this.schoolId |
||||
}; |
||||
this.$get(this.api.loginRole, data) |
||||
.then(res => { |
||||
this.roleList = [...res.message.staffList,...res.message.studentList] |
||||
let indexs = {} |
||||
this.roleList = this.roleList.reduce((cur,next) => { |
||||
indexs[next.roleId] ? '' : indexs[next.roleId] = true && cur.push(next) |
||||
return cur |
||||
},[]) |
||||
this.roleList.forEach((n,k) => { |
||||
switch(n.roleId){ |
||||
case 2: |
||||
n.roleName = '管理员' |
||||
break |
||||
case 3: |
||||
n.roleName = '老师' |
||||
break |
||||
case 4: |
||||
n.roleName = '学生' |
||||
break |
||||
} |
||||
}) |
||||
if(this.roleList.length > 1) { |
||||
this.roleDialog = true |
||||
}else{ |
||||
this.roleId = this.roleList[0].roleId |
||||
this.submitForm(form) |
||||
} |
||||
}) |
||||
.catch(res => {}); |
||||
}, |
||||
updateInfo(data){ |
||||
this.loginForm.username = data.username |
||||
this.loginForm.password = data.password |
||||
}, |
||||
roleSure(form){ |
||||
if(this.roleId){ |
||||
this.submitForm(form) |
||||
}else{ |
||||
util.errorMsg('请选择角色!') |
||||
} |
||||
}, |
||||
submitForm(form) { |
||||
this.$refs[form].validate(valid => { |
||||
if (valid) { |
||||
let data = { |
||||
roleId: this.roleId, |
||||
userId: this.userId, |
||||
schoolId: this.schoolId |
||||
} |
||||
this.$get(this.api.logins,data).then(res => { |
||||
this.$post(this.api.updateLogInNumber,{userId: this.userId}).then(res => {}).catch(res => {}) |
||||
let data = res.message.user |
||||
util.local.set(Setting.tokenKey,data.token,Setting.tokenExpires) |
||||
this.setInfo({ |
||||
userId: this.userId, |
||||
roleId: this.roleId, |
||||
studentId: this.studentId, |
||||
schoolId: this.schoolId, |
||||
avatar: data.userAvatars, |
||||
userName: data.userName, |
||||
dataTime: data.dataTime, |
||||
}) |
||||
util.successMsg('登录成功') |
||||
let redirect = decodeURIComponent(this.$route.query.redirect || '/index') |
||||
this.$router.replace(redirect) |
||||
}).catch(res => {}); |
||||
} |
||||
}); |
||||
}, |
||||
cancleRoleDia() { |
||||
this.roleId = '' |
||||
this.roleDialog = false |
||||
}, |
||||
toReg(status) { |
||||
this.isReg = status |
||||
}, |
||||
forget(){ |
||||
this.forgetVisible = true |
||||
}, |
||||
emailCountdown(){ |
||||
let count = 60 |
||||
if(!this.emailTimer){ |
||||
this.emailDisabled = true |
||||
this.emailTimer = setInterval(() => { |
||||
if(count > 0){ |
||||
count-- |
||||
this.emailBtnText = `${count}秒后重试` |
||||
}else{ |
||||
this.emailDisabled = false |
||||
clearInterval(this.emailTimer) |
||||
this.emailTimer = null |
||||
this.emailBtnText = `发送验证码` |
||||
} |
||||
},1000) |
||||
} |
||||
}, |
||||
phoneCountdown(){ |
||||
let count = 60 |
||||
if(!this.phoneTimer){ |
||||
this.phoneDisabled = true |
||||
this.phoneTimer = setInterval(() => { |
||||
if(count > 0){ |
||||
count-- |
||||
this.phoneBtnText = `${count}秒后重试` |
||||
}else{ |
||||
this.phoneDisabled = false |
||||
clearInterval(this.phoneTimer) |
||||
this.phoneTimer = null |
||||
this.phoneBtnText = `发送验证码` |
||||
} |
||||
},1000) |
||||
} |
||||
}, |
||||
closeForget(){ |
||||
this.phoneCode = '' |
||||
this.emailCode = '' |
||||
this.userId = '' |
||||
this.newPassword = '' |
||||
}, |
||||
sendEmailCode(){ |
||||
if(!this.email) return util.warningMsg('请输入邮箱') |
||||
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return util.warningMsg('请输入正确的邮箱') |
||||
let data = { |
||||
email: this.email |
||||
} |
||||
this.$get(this.api.findPasswordByEmail,data).then(res => { |
||||
if(res.errmessage == 'success'){ |
||||
util.successMsg('发送成功') |
||||
this.emailCountdown() |
||||
this.userId = res.data.userId |
||||
this.emailOpener = res.data.opener |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
sendPhoneCode(){ |
||||
if(!this.phone) return util.warningMsg('请输入手机号') |
||||
if(!/^1[3456789]\d{9}$/.test(this.phone)) return util.warningMsg('请输入正确的手机号') |
||||
let data = { |
||||
phone: this.phone |
||||
} |
||||
this.$get(this.api.findPasswordByPhone,data).then(res => { |
||||
if(res.errmessage == 'success'){ |
||||
util.successMsg('发送成功') |
||||
this.phoneCountdown() |
||||
this.userId = res.data.userId |
||||
this.phoneOpener = res.data.opener |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
async updatePassword(type){ |
||||
if(type == 1){ |
||||
if(!this.phone) return util.warningMsg('请输入手机号') |
||||
if(!/^1[3456789]\d{9}$/.test(this.phone)) return util.warningMsg('请输入正确的手机号') |
||||
if(!this.phoneCode) return util.warningMsg('请输入验证码') |
||||
}else{ |
||||
if(!this.email) return util.warningMsg('请输入邮箱') |
||||
if(!/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.email)) return util.warningMsg('请输入正确的邮箱') |
||||
if(!this.emailCode) return util.warningMsg('请输入验证码') |
||||
} |
||||
if(!this.newPassword) return util.warningMsg('请输入新密码') |
||||
|
||||
let checkData = { |
||||
code: type == 1 ? this.phoneCode : this.emailCode, |
||||
opener: type == 1 ? this.phoneOpener : this.emailOpener |
||||
} |
||||
let checkRes = await this.$post(this.api.checkCode,checkData) |
||||
if(checkRes.errmessage == 'success'){ |
||||
let resetData = { |
||||
userId: this.userId, |
||||
password: this.newPassword |
||||
} |
||||
let resetRes = await this.$post(this.api.resetPassword,resetData) |
||||
if(resetRes.errmessage == 'success'){ |
||||
util.successMsg('重置成功') |
||||
this.forgetVisible = false |
||||
} |
||||
} |
||||
}, |
||||
switchType(type){ |
||||
this.phoneReset = type |
||||
} |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.wrap { |
||||
position: relative; |
||||
width: 100%; |
||||
height: 100%; |
||||
overflow: hidden; |
||||
|
||||
.header { |
||||
width: 100%; |
||||
height: 60px; |
||||
background-color: #fff; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
font-size: 18px; |
||||
box-shadow: 1px 1px 3px 2px #ececec; |
||||
.logo { |
||||
width: 150px; |
||||
margin-left: 20px; |
||||
} |
||||
} |
||||
.bg{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
height: calc(100% - 116px); |
||||
.left{ |
||||
position: relative; |
||||
width: 40%; |
||||
height: 100%; |
||||
background: url(../../../assets/img/bg_2.png) 0 0/100% 100% no-repeat; |
||||
.text{ |
||||
position: absolute; |
||||
top: 35%; |
||||
left: 15%; |
||||
color: #fff; |
||||
font-size: 46px; |
||||
font-weight: bold; |
||||
p:first-child{ |
||||
margin-bottom: 20px; |
||||
} |
||||
} |
||||
} |
||||
.right{ |
||||
width: 50%; |
||||
height: 100%; |
||||
background: url(../../../assets/img/bg_1.png) center center/80% auto no-repeat; |
||||
} |
||||
} |
||||
|
||||
|
||||
/deep/.right-form{ |
||||
position: absolute; |
||||
top: 47%; |
||||
right: 12%; |
||||
transform: translateY(-50%); |
||||
width: 30%; |
||||
|
||||
.logo{ |
||||
width: 100%; |
||||
margin-bottom: 40px; |
||||
} |
||||
.form{ |
||||
padding: 50px 20px 20px; |
||||
background-color: #fff; |
||||
border-radius: 16px; |
||||
box-sizing: border-box; |
||||
box-shadow: 0 1px 20px rgba(146,120,255,0.3); |
||||
} |
||||
.back{ |
||||
position: absolute; |
||||
top: 20px; |
||||
left: 20px; |
||||
font-size: 24px; |
||||
color: #9278ff; |
||||
cursor: pointer; |
||||
|
||||
&:hover{ |
||||
opacity: .8; |
||||
} |
||||
} |
||||
.el-tabs__nav-scroll{ |
||||
display: flex; |
||||
justify-content: center; |
||||
} |
||||
|
||||
h2{ |
||||
padding-bottom: 10px; |
||||
font-size: 20px; |
||||
font-weight: 400; |
||||
color: #8F73FF; |
||||
text-align: center; |
||||
border-bottom: 1px solid #f3f3f3; |
||||
} |
||||
.el-form{ |
||||
width: 70%; |
||||
margin: 30px auto 0; |
||||
.label{ |
||||
line-height: 1.8; |
||||
color: #929292; |
||||
} |
||||
/deep/.el-input__inner{ |
||||
height: 46px; |
||||
padding: 0 23px; |
||||
line-height: 46px; |
||||
border: 1px solid #E5E5E5; |
||||
border-radius: 8px !important; |
||||
} |
||||
/deep/.el-form-item__error{ |
||||
top: 105%; |
||||
left: auto; |
||||
right: 0; |
||||
color: #FFA94E; |
||||
} |
||||
.submit{ |
||||
width: 100%; |
||||
height: 48px; |
||||
margin-top: 40px; |
||||
line-height: 48px; |
||||
padding: 0; |
||||
font-size: 18px; |
||||
background-color: #9278ff; |
||||
border-radius: 6px; |
||||
border: 0; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.switch{ |
||||
span{ |
||||
cursor: pointer; |
||||
color: #9076FF; |
||||
} |
||||
} |
||||
.links{ |
||||
width: 70%; |
||||
margin: 20px auto 0; |
||||
text-align: right; |
||||
} |
||||
.ques{ |
||||
color: #9278ff; |
||||
font-size: 14px; |
||||
} |
||||
.forget{ |
||||
color: #ffa94e; |
||||
font-size: 14px; |
||||
} |
||||
</style> |
@ -0,0 +1,237 @@ |
||||
<template> |
||||
<div> |
||||
<!-- <h2><div class="back" @click="toLogin"><i class="el-icon-arrow-left">返回</i></div> 学生注册</h2> --> |
||||
<h2>账号注册</h2> |
||||
|
||||
<el-form class="register" :model="regForm" :rules="regRules" ref="reg" label-width="0px"> |
||||
<div class="line"> |
||||
<el-form-item prop="userName"> |
||||
<p class="label">*学生姓名</p> |
||||
<el-input v-model="regForm.userName" placeholder="姓名"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="workNumber" style="margin-right: 5%"> |
||||
<p class="label">学生学号</p> |
||||
<el-input v-model="regForm.workNumber" placeholder="学生学号" @change="worknumberChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="phone"> |
||||
<p class="label">*手机号</p> |
||||
<el-input v-model="regForm.phone" placeholder="手机号" maxlength="11" @change="phoneChange"></el-input> |
||||
</el-form-item> |
||||
</div> |
||||
|
||||
<p class="label">*学校</p> |
||||
<div class="line"> |
||||
<el-form-item prop="provinceId"> |
||||
<p class="prop">省份</p> |
||||
<el-select v-model="regForm.provinceId" placeholder="省份" @change="getCity"> |
||||
<el-option |
||||
v-for="item in provinceList" |
||||
:key="item.value" |
||||
:label="item.provinceName" |
||||
:value="item.provinceId" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item prop="cityId" style="margin-right: 5%"> |
||||
<p class="prop">城市</p> |
||||
<el-select v-model="regForm.cityId" placeholder="城市" @change="getSchoolData"> |
||||
<el-option |
||||
v-for="item in cityList" |
||||
:key="item.value" |
||||
:label="item.cityName" |
||||
:value="item.cityId" |
||||
></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item prop="schoolAppellationId"> |
||||
<p class="prop">学校</p> |
||||
<el-select v-model="regForm.schoolAppellationId" placeholder="学校名称"> |
||||
<el-option v-for="(item,index) in schoolList" :key="index" :label="item.schoolName" :value="item.schoolId"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</div> |
||||
<!-- <div class="line"> |
||||
<el-form-item prop="phone"> |
||||
<p class="label">手机号</p> |
||||
<el-input v-model="regForm.phone" placeholder="请输入手机号"></el-input> |
||||
</el-form-item> |
||||
<el-form-item style="margin-right: 5%"> |
||||
<button type="button" class="code-btn">发送验证码</button> |
||||
</el-form-item> |
||||
<el-form-item prop="code"> |
||||
<el-input v-model="regForm.code" placeholder="输入验证码"></el-input> |
||||
</el-form-item> |
||||
</div> --> |
||||
<div class="line"> |
||||
<el-form-item prop="password"> |
||||
<p class="label">*密码设置</p> |
||||
<el-input type="password" v-model="regForm.password" placeholder="请输入密码"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="rePassword"> |
||||
<el-input type="password" v-model="regForm.rePassword" placeholder="请再次输入密码" @keyup.enter.native="registerForm"></el-input> |
||||
</el-form-item> |
||||
</div> |
||||
|
||||
<el-button class="submit" type="primary" @click="registerForm">注册</el-button> |
||||
</el-form> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data: function() { |
||||
return { |
||||
regForm: { |
||||
userName: '', |
||||
workNumber: '', |
||||
provinceId: '', |
||||
cityId: '', |
||||
schoolAppellationId: '', |
||||
phone: '', |
||||
password: '', |
||||
rePassword: '', |
||||
roleId: 4, |
||||
schoolId: this.$config.schoolId |
||||
}, |
||||
regRules: { |
||||
userName: [{ required: true, message: '请输入学生姓名', trigger: 'blur' }], |
||||
workNumber: [{ required: true, message: '请输入学生学号', trigger: 'blur' }], |
||||
provinceId: [{ required: true, message: '请选择省份', trigger: 'change' }], |
||||
cityId: [{ required: true, message: '请选择城市', trigger: 'change' }], |
||||
schoolAppellationId: [{ required: true, message: '请选择学校', trigger: 'change' }], |
||||
phone: [ |
||||
{ required: true, message: '请输入手机号', trigger: 'blur' }, |
||||
{ pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' } |
||||
], |
||||
password: [ |
||||
{ required: true, message: '请输入密码', trigger: 'blur' }, |
||||
{ pattern: /^.{6,}$/, message: '请输入6位数以上的密码', trigger: 'blur' } |
||||
], |
||||
rePassword: [ |
||||
{ required: true, message: '请再次输入密码', trigger: 'blur' }, |
||||
{ pattern: /^.{6,}$/, message: '请输入6位数以上的密码', trigger: 'blur' } |
||||
] |
||||
}, |
||||
provinceList: this.$store.state.provinceList, //省份 |
||||
cityList: [], //城市 |
||||
schoolList: [], |
||||
phoneRepeat: false, |
||||
workNumberReapeat: false |
||||
}; |
||||
}, |
||||
mounted() { |
||||
this.getProvince() |
||||
this.getSchoolData() |
||||
}, |
||||
methods: { |
||||
getProvince(){ |
||||
this.$get(this.api.queryProvince).then(res => { |
||||
this.provinceList = res.message |
||||
this.$store.commit("provinceData", { provinceList : this.provinceList}); |
||||
}).catch(res => {}); |
||||
}, |
||||
// 获取城市 |
||||
getCity(){ |
||||
this.regForm.cityId = '' |
||||
this.$get(this.api.queryCity,{provinceId: this.regForm.provinceId}).then(res => { |
||||
this.cityList = res.message |
||||
this.getSchoolData() |
||||
}).catch(res => {}) |
||||
}, |
||||
// 获取学校名称 |
||||
getSchoolData(){ |
||||
this.regForm.schoolAppellationId = '' |
||||
this.$get(this.api.querySchoolData,{provinceId: this.regForm.provinceId,cityId: this.regForm.cityId,schoolName: ''}).then(res => { |
||||
this.schoolList = res.message |
||||
}).catch(res => {}); |
||||
}, |
||||
registerForm() { |
||||
this.$refs.reg.validate(valid => { |
||||
if (valid) { |
||||
if(this.phoneRepeat) return util.warningMsg('该手机号已存在') |
||||
if(this.workNumberReapeat) return util.warningMsg('该学生学号已存在') |
||||
if(this.regForm.password !== this.regForm.rePassword) return util.warningMsg('两次输入的密码不一致,请重新输入') |
||||
|
||||
let data = this.regForm |
||||
data.account = data.phone |
||||
data.uniqueIdentificationAccount = new Date().getTime() |
||||
this.$post(`${this.api.save}?workNumber=${this.regForm.workNumber}`,data).then(res => { |
||||
util.successMsg('注册成功') |
||||
this.$emit('update:isReg',false) |
||||
this.$emit('updateInfo',{username: this.regForm.phone,password: this.regForm.password}) |
||||
this.$refs.reg.resetFields() |
||||
}).catch(res => {}); |
||||
} else { |
||||
// util.errorMsg('请输入账号和密码'); |
||||
return false; |
||||
} |
||||
}); |
||||
}, |
||||
async phoneChange(){ |
||||
let res = await this.$get(this.api.queryPhone, { phone: this.regForm.phone }); |
||||
if(res.message.length != 0){ |
||||
util.warningMsg('该手机号已存在'); |
||||
this.phoneRepeat = true |
||||
}else{ |
||||
this.phoneRepeat = false |
||||
} |
||||
}, |
||||
async worknumberChange(){ |
||||
let res = await this.$get(this.api.queryWorkNumberIsExist, { |
||||
workNumber: this.regForm.workNumber, |
||||
roleId: 4, |
||||
schoolAppellationId: this.regForm.schoolAppellationId |
||||
}); |
||||
if(JSON.stringify(res.message) != '{}'){ |
||||
util.warningMsg('该学生学号已存在'); |
||||
this.workNumberReapeat = true |
||||
}else{ |
||||
this.workNumberReapeat = false |
||||
} |
||||
}, |
||||
toLogin() { |
||||
this.$emit('update:isReg',false) |
||||
} |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.wrap { |
||||
.form{ |
||||
.register{ |
||||
width: 90% !important; |
||||
.line{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: flex-end; |
||||
} |
||||
.el-form-item{ |
||||
&:first-child{ |
||||
margin-right: 5%; |
||||
} |
||||
} |
||||
.label{ |
||||
margin-bottom: 0; |
||||
} |
||||
.prop{ |
||||
color: #929292; |
||||
} |
||||
.code-btn{ |
||||
min-width: 120px; |
||||
height: 46px; |
||||
padding: 0 10px; |
||||
line-height: 46px; |
||||
color: #fff; |
||||
font-size: 14px; |
||||
border-radius: 23px; |
||||
border: 0; |
||||
background-color: #105cb2; |
||||
} |
||||
.submit{ |
||||
margin-bottom: 20px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,369 @@ |
||||
<template> |
||||
<div> |
||||
<div class="page"> |
||||
<h6 class="p-title">筛选</h6> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>考核时间</label> |
||||
<el-radio-group size="small" v-model="form.month" @change="getData"> |
||||
<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-select size="small" v-model="form.status" placeholder="请选择实验状态" @change="getData"> |
||||
<el-option v-for="(item,index) in statusList" :key="index" :label="item.name" :value="item.value"></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-table :data="listData" class="table" stripe header-align="center" :row-key="getRowKeys"> |
||||
<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="experimentalName" label="考核名称" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="experimentalClassName" 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 prop="creationTime" label="创建时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="startTime" label="起始时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="stopTime" label="结束时间" align="center"> |
||||
</el-table-column> |
||||
<el-table-column label="倒计时" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span v-countdown="scope.row.surplusTime">{{scope.row.surplusTime}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="实验状态" align="center"> |
||||
<template slot-scope="scope"> |
||||
<span class="ellipsis">{{status[scope.row.status]}}</span> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button v-if="scope.row.status == 3 && !scope.row.done" type="text" disabled>未参加</el-button> |
||||
<el-button v-if="scope.row.status != 3 && !scope.row.done" type="text" @click="entry(scope.row)" :disabled="scope.row.status != 2">进入</el-button> |
||||
<el-button v-if="scope.row.status == 2 && scope.row.done" type="text" disabled>已提交</el-button> |
||||
<el-button v-if="scope.row.status == 3 && scope.row.done" type="text" @click="show(scope.row)">查看成绩</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total, prev, pager, next" :total="totals" @current-change="handleCurrentChange" :current-page="page"></el-pagination> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-dialog title="请输入邀请码" :visible.sync="icVisible" width="30%" @close="closeIc" center :close-on-click-modal="false"> |
||||
<el-input v-model="invitationCode" placeholder="邀请码" maxlength="6"></el-input> |
||||
<div slot="footer" class="dialog-footer"> |
||||
<el-button type="primary" @click="saveIc">确 定</el-button> |
||||
</div> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState,mapActions } from 'vuex' |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'ass', |
||||
data() { |
||||
return { |
||||
host: Setting.host, |
||||
status: ['','待开始','进行中','已完成'], |
||||
statusList: [{ |
||||
name:'不限', |
||||
value: 0 |
||||
},{ |
||||
name:'待开始', |
||||
value: 1 |
||||
},{ |
||||
name:'进行中', |
||||
value: 2 |
||||
},{ |
||||
name:'已完成', |
||||
value: 3 |
||||
}], |
||||
listData: [], |
||||
date: [], |
||||
form: { |
||||
month:'', |
||||
startTime: '', |
||||
endTime: '', |
||||
status: 0, |
||||
}, |
||||
keyword: '', |
||||
dateList: [ |
||||
{ |
||||
id: '', |
||||
name: '不限' |
||||
}, |
||||
{ |
||||
id: 1, |
||||
name: '近一个月' |
||||
}, |
||||
{ |
||||
id: 3, |
||||
name: '近三个月' |
||||
}, |
||||
{ |
||||
id: 6, |
||||
name: '近六个月' |
||||
} |
||||
], |
||||
page: 1, |
||||
pageSize: 10, |
||||
totals: 0, |
||||
icVisible: false, |
||||
invitationCode: '', |
||||
searchTimer: null, |
||||
timerList: [], |
||||
curRow: {} |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','schoolId','studentId','userName' |
||||
]), |
||||
}, |
||||
watch: { |
||||
'form.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.form.startTime = val[0] |
||||
this.form.endTime = val[1] |
||||
}else{ |
||||
this.form.startTime = '' |
||||
this.form.endTime = '' |
||||
} |
||||
this.getData() |
||||
}, |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.getData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
this.$once('hook:beforeDestroy', function () { |
||||
this.timerList.forEach((n,k) => { |
||||
clearInterval(n) |
||||
}) |
||||
this.timerList = [] |
||||
}) |
||||
}, |
||||
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 = `${that.core.formateTime(hours)}:${that.core.formateTime(minutes)}:${that.core.formateTime(seconds)}` |
||||
}else{ |
||||
clearInterval(timer) |
||||
} |
||||
el.innerHTML = time |
||||
},1000) |
||||
that.timerList.push(timer) |
||||
} |
||||
} |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
schoolId: this.schoolId, |
||||
month: this.form.month, |
||||
startTime: this.form.startTime, |
||||
endTime: this.form.endTime, |
||||
condition: this.keyword, |
||||
status: this.form.status, |
||||
page: this.page, |
||||
size: this.pageSize, |
||||
rowId: '', |
||||
projectId: '' |
||||
} |
||||
this.$get(this.api.userRecord,data).then(res => { |
||||
let list = res.page.list |
||||
this.totals = res.page.totalCount |
||||
let doneNum = 0 |
||||
let recordList = [] |
||||
for(let i = 1; i < 11; i++){ |
||||
if(i != 2 && i != 3){ |
||||
this.$get(this.api.experimentRecord, { |
||||
userid: this.userId, |
||||
page: 1, |
||||
size: 10000, |
||||
systemId: i |
||||
}).then(res => { |
||||
doneNum++ |
||||
recordList = recordList.concat(res.data.list) |
||||
if(doneNum == 8){ |
||||
list.map(n => { |
||||
let same = recordList.find(e => e.id == n.id) |
||||
if(same){ |
||||
n.done = true |
||||
n.recordid = same.recordid |
||||
n.reportId = same.reportId |
||||
} |
||||
}) |
||||
this.listData = list |
||||
} |
||||
}).catch(err => {}) |
||||
} |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
add(){ |
||||
this.$store.commit("listData", { customer_id : ''}); |
||||
this.$router.push('/addclass'); |
||||
}, |
||||
edit(row){ |
||||
this.$store.commit("listData", { customer_id : row.customerId }); |
||||
this.$router.push('/addcustomer'); |
||||
}, |
||||
getRowKeys(row) { |
||||
return row.customerId; |
||||
}, |
||||
onSearch(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val |
||||
this.getData() |
||||
}, |
||||
entry(row) { |
||||
if(row.status == 1){ |
||||
return util.warningMsg('该实验尚未开始') |
||||
}else if(row.status == 3){ |
||||
return util.warningMsg('该实验已经结束') |
||||
}else{ |
||||
this.curRow = row |
||||
if(row.isCode == 1){ |
||||
this.goSubSystem() |
||||
}else{ |
||||
this.$get(this.api.checkInvitationCode,{ |
||||
userId: this.userId, |
||||
id: row.id |
||||
}).then(res => { |
||||
if(res.errmessage == 'false'){ |
||||
this.icVisible = true |
||||
}else{ |
||||
this.goSubSystem() |
||||
} |
||||
}).catch(res => {}); |
||||
} |
||||
} |
||||
}, |
||||
show(row) { |
||||
this.$router.push(`/showExperiment?id=${row.id}&recordId=${row.recordid}&reportId=${row.reportId}`) |
||||
}, |
||||
saveIc() { |
||||
if(!this.invitationCode) return util.warningMsg('请输入邀请码') |
||||
if(!this.invitationCode || String(this.invitationCode).length < 6 || isNaN(this.invitationCode)) return util.warningMsg('请输入6位纯数字邀请码') |
||||
let data = { |
||||
id: this.curRow.id, |
||||
userId: this.userId, |
||||
invitationCode: Number(this.invitationCode) |
||||
} |
||||
this.$post(this.api.joinPractice,data).then(res => { |
||||
if(res.errmessage == 'success') { |
||||
util.successMsg('验证成功!') |
||||
this.icVisible = false |
||||
setTimeout(() => { |
||||
this.goSubSystem() |
||||
},1000) |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
closeIc() { |
||||
this.invitationCode = '' |
||||
}, |
||||
goback() { |
||||
this.$router.back() |
||||
}, |
||||
goSubSystem(){ |
||||
let host = this.host |
||||
util.cookies.set("assessmentId",this.curRow.id) |
||||
util.cookies.set("studentId",this.studentId) |
||||
util.cookies.set("userId",this.userId) |
||||
util.cookies.set("projectId",this.curRow.projectId) |
||||
util.cookies.set("startTime",this.curRow.startTime) |
||||
util.cookies.set("stopTime",this.curRow.stopTime) |
||||
let systemId = this.curRow.systemId |
||||
let href = '' |
||||
switch(systemId){ |
||||
case 1: |
||||
href = `${host}pyTrials/#/` |
||||
break; |
||||
case 4: |
||||
href = `${host}pyFinance/#/` |
||||
break; |
||||
case 5: |
||||
href = `${host}pyProjects/#/` |
||||
break; |
||||
case 6: |
||||
href = `${host}pyRandom/#/` |
||||
break; |
||||
case 7: |
||||
href = `${host}pyQuantification/#/` |
||||
break; |
||||
case 8: |
||||
href = `${host}pyAnalysis/#/` |
||||
break; |
||||
case 9: |
||||
href = `${host}pyDataclean/#/` |
||||
break; |
||||
case 10: |
||||
href = `${host}pyAcquisition/#/` |
||||
break; |
||||
} |
||||
if(!href) return util.errorMsg('该考核非Python考核,请选择其他考核') |
||||
location.href = href |
||||
// location.href = 'http://192.168.31.154:8080/' |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.el-tabs__nav-wrap::after{ |
||||
display: none; |
||||
} |
||||
.no-mb /deep/.el-form-item{ |
||||
margin-bottom: 0; |
||||
} |
||||
.el-radio.is-bordered+.el-radio.is-bordered{ |
||||
margin-left: 0; |
||||
} |
||||
</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,31 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
|
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState } from 'vuex' |
||||
export default { |
||||
name: 'index', |
||||
data() { |
||||
return { |
||||
|
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getHot() |
||||
}, |
||||
methods: { |
||||
getData(){ |
||||
|
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.wrap{ |
||||
|
||||
} |
||||
</style> |