@ -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> |