@ -0,0 +1,3 @@ |
||||
> 1% |
||||
last 2 versions |
||||
not ie <= 8 |
@ -0,0 +1,22 @@ |
||||
.DS_Store |
||||
node_modules |
||||
/dist |
||||
example.html |
||||
favicon.ico |
||||
# local env files |
||||
.env.local |
||||
.env.*.local |
||||
|
||||
# Log files |
||||
npm-debug.log* |
||||
yarn-debug.log* |
||||
yarn-error.log* |
||||
|
||||
# Editor directories and files |
||||
.idea |
||||
.vscode |
||||
*.suo |
||||
*.ntvs* |
||||
*.njsproj |
||||
*.sln |
||||
*.sw* |
@ -0,0 +1,6 @@ |
||||
{ |
||||
"tabWidth": 4, |
||||
"singleQuote": true, |
||||
"trailingComma": "none", |
||||
"printWidth": 140 |
||||
} |
@ -0,0 +1,21 @@ |
||||
MIT License |
||||
|
||||
Copyright (c) 2016-2019 vue-manage-system |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -0,0 +1,5 @@ |
||||
module.exports = { |
||||
presets: [ |
||||
'@vue/app' |
||||
] |
||||
} |
@ -0,0 +1,38 @@ |
||||
{ |
||||
"name": "vue-manage-system", |
||||
"version": "4.2.0", |
||||
"private": true, |
||||
"scripts": { |
||||
"dev": "npm run serve", |
||||
"serve": "vue-cli-service serve", |
||||
"build": "vue-cli-service build" |
||||
}, |
||||
"dependencies": { |
||||
"axios": "^0.18.0", |
||||
"babel-polyfill": "^6.26.0", |
||||
"echarts": "^4.8.0", |
||||
"element-theme": "^2.0.1", |
||||
"element-ui": "^2.13.0", |
||||
"js-cookie": "^2.2.1", |
||||
"mavon-editor": "^2.6.17", |
||||
"postcss-px2rem": "^0.3.0", |
||||
"px2rem-loader": "^0.1.9", |
||||
"vue": "^2.6.10", |
||||
"vue-cropperjs": "^3.0.0", |
||||
"vue-i18n": "^8.10.0", |
||||
"vue-pdf": "^4.2.0", |
||||
"vue-quill-editor": "^3.0.6", |
||||
"vue-router": "^3.0.3", |
||||
"vue-schart": "^2.0.0", |
||||
"vuedraggable": "^2.17.0", |
||||
"vuex": "^3.4.0" |
||||
}, |
||||
"devDependencies": { |
||||
"@vue/cli-plugin-babel": "^3.9.0", |
||||
"@vue/cli-service": "^3.9.0", |
||||
"element-theme-chalk": "^2.13.0", |
||||
"node-sass": "^4.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 () { |
||||
//在页面加载时读取sessionStorage里的状态信息 |
||||
if (util.session.get(Setting.storeKey) ) { |
||||
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(util.session.get(Setting.storeKey)))) |
||||
} |
||||
|
||||
//在页面刷新时将vuex里的信息保存到sessionStorage里 |
||||
window.addEventListener("beforeunload",()=>{ |
||||
util.session.get(Setting.usernameKey) && util.session.set(Setting.storeKey,JSON.stringify(this.$store.state)) |
||||
}) |
||||
} |
||||
} |
||||
</script> |
After Width: | Height: | Size: 268 B |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 2.4 MiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
After Width: | Height: | Size: 452 B |
After Width: | Height: | Size: 534 B |
After Width: | Height: | Size: 506 B |
After Width: | Height: | Size: 6.2 KiB |
After Width: | Height: | Size: 5.4 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 6.3 KiB |
After Width: | Height: | Size: 306 B |
After Width: | Height: | Size: 209 B |
After Width: | Height: | Size: 247 B |
@ -0,0 +1,30 @@ |
||||
<template> |
||||
<div class="breadcrumb"> |
||||
<span class="cur">当前位置:</span> |
||||
<el-breadcrumb separator="/"> |
||||
<el-breadcrumb-item :to="{ path: '/' }">超竞学生端</el-breadcrumb-item> |
||||
<el-breadcrumb-item v-for="(item,index) in pages" :key="index" :to="{ path: index == pages.length - 1 ? curRoute : path }">{{item}}</el-breadcrumb-item> |
||||
</el-breadcrumb> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
props: ['data','route'], |
||||
data() { |
||||
return { |
||||
pages: this.data.split('/'), |
||||
curRoute: this.$route.path, |
||||
path: this.route ? this.route : 'list' |
||||
}; |
||||
}, |
||||
methods: { |
||||
update(data){ |
||||
this.pages = data.split('/') |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
|
||||
</style> |
@ -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,28 @@ |
||||
<template> |
||||
<div> |
||||
<div class="copyright">广州超竞教育投资有限公司版权所有</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; |
||||
} |
||||
</style> |
@ -0,0 +1,102 @@ |
||||
<template> |
||||
<div class="header"> |
||||
<div class="inner"> |
||||
<img class="logo" src="../../assets/img/logo.png" alt=""> |
||||
<div style="height: 80px;"></div> |
||||
<navbar></navbar> |
||||
<div class="action"> |
||||
<img class="search" src="../../assets/img/search.png" alt=""> |
||||
<el-dropdown class="user-wrap" @command="userCommand"> |
||||
<div class="user"> |
||||
<el-avatar :size="40" :src="avatar"></el-avatar> |
||||
<span class="username">{{userName}}</span> |
||||
</div> |
||||
<el-dropdown-menu slot="dropdown"> |
||||
<el-dropdown-item command="person">个人资料</el-dropdown-item> |
||||
<el-dropdown-item command="logout">退出登录</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import navbar from '../navbar' |
||||
import { mapState,mapActions } from 'vuex' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data() { |
||||
return { |
||||
showBackList: Setting.layout.hideNavList, |
||||
}; |
||||
}, |
||||
components: { navbar }, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','avatar','userName' |
||||
]), |
||||
showBack(){ |
||||
let route = this.$route.name |
||||
if(this.showBackList.includes(route)) return true |
||||
return false |
||||
} |
||||
}, |
||||
mounted(){ |
||||
|
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'logout' |
||||
]), |
||||
userCommand(command){ |
||||
console.log(command) |
||||
if(command == 'person'){ |
||||
this.$router.push('/setting/person') |
||||
}else{ |
||||
this.logout() |
||||
} |
||||
} |
||||
}, |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.header{ |
||||
position: relative; |
||||
height: 80px; |
||||
background-color: #fff; |
||||
.inner{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
width: $inner-width; |
||||
margin: 0 auto; |
||||
} |
||||
.logo{ |
||||
width: 180px; |
||||
} |
||||
|
||||
.action{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
.search{ |
||||
margin-right: 30px; |
||||
cursor: pointer; |
||||
} |
||||
.user-wrap { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
|
||||
.user{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
cursor: pointer; |
||||
.username{ |
||||
margin-left: 10px; |
||||
color: #000; |
||||
font-size: 16px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,68 @@ |
||||
<template> |
||||
<div class="main"> |
||||
<v-head></v-head> |
||||
<div class="layout"> |
||||
<div class="content"> |
||||
<transition name="move" mode="out-in"> |
||||
<keep-alive :include="tagsList"> |
||||
<router-view class="view"></router-view> |
||||
</keep-alive> |
||||
</transition> |
||||
<el-backtop target=".content"></el-backtop> |
||||
<!-- <v-footer ref="footer"></v-footer> --> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import vHead from '../header' |
||||
import vFooter from '../footer' |
||||
import bus from '@/libs/bus' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data() { |
||||
return { |
||||
tagsList: [], |
||||
collapse: false, |
||||
hideNavList: Setting.layout.hideNavList |
||||
}; |
||||
}, |
||||
components: { |
||||
vHead, |
||||
vFooter |
||||
}, |
||||
computed: { |
||||
hideNavbar() { |
||||
let route = this.$route.name |
||||
if(this.hideNavList.includes(route)) return false |
||||
return true |
||||
} |
||||
}, |
||||
created() { |
||||
bus.$on('collapse-content', msg => { |
||||
this.collapse = msg; |
||||
}); |
||||
|
||||
// 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。 |
||||
bus.$on('tags', msg => { |
||||
let arr = []; |
||||
for (let i = 0, len = msg.length; i < len; i++) { |
||||
msg[i].name && arr.push(msg[i].name) |
||||
} |
||||
this.tagsList = arr |
||||
}); |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
.main{ |
||||
min-height: 100%; |
||||
background: url(../../assets/img/login-bg.png) 0 0/100% 100% no-repeat; |
||||
.view{ |
||||
width: $inner-width; |
||||
padding: 20px 0; |
||||
margin: 0 auto; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,105 @@ |
||||
<template> |
||||
<div> |
||||
<ul class="nav"> |
||||
<li v-for="(item,index) in menus" :key="index" :class="{active: active == item.index}" @click="jump(item)">{{item.title}}</li> |
||||
</ul> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState } from 'vuex' |
||||
import bus from '@/libs/bus' |
||||
import Setting from '@/setting' |
||||
export default { |
||||
data() { |
||||
return { |
||||
active: this.$route.path, |
||||
defaultMenus: [ |
||||
{ |
||||
index: '/index/list', |
||||
title: '首页' |
||||
},{ |
||||
index: '/data/list', |
||||
title: '数据' |
||||
},{ |
||||
index: '/stat/list', |
||||
title: '数据统计' |
||||
},{ |
||||
index: '/user/list', |
||||
title: '用户管理' |
||||
},{ |
||||
index: '/role/list', |
||||
title: '角色权限' |
||||
}, |
||||
], |
||||
menus: [], |
||||
actives: { |
||||
practice: ['practice-do','practice-randomDo'], |
||||
exam: ['exam-do'], |
||||
achievement: ['achievement-practice','achievement-assessment'], |
||||
wrongBook: ['wrongBook-do'], |
||||
} |
||||
}; |
||||
}, |
||||
computed: { |
||||
onRoutes() { |
||||
let actives = this.actives |
||||
for(let i in this.actives){ |
||||
if(actives[i].includes(this.$route.name)) return `/${i}/list` |
||||
} |
||||
return this.$route.path |
||||
}, |
||||
...mapState('auth', [ |
||||
'routes' |
||||
]) |
||||
}, |
||||
created() { |
||||
this.initMenu() |
||||
// 通过 Event Bus 进行组件间通信,来折叠侧边栏 |
||||
bus.$on('collapse', msg => { |
||||
this.collapse = msg; |
||||
bus.$emit('collapse-content', msg); |
||||
}); |
||||
}, |
||||
methods: { |
||||
initMenu(){ |
||||
if(Setting.dynamicRoute){ |
||||
let routes = this.routes |
||||
let menus = [] |
||||
this.defaultMenus.map(e => { |
||||
routes.find(n => n.path == e.index) && menus.push(e) |
||||
}) |
||||
this.menus = menus |
||||
this.active = menus[0].index |
||||
}else{ |
||||
this.menus = this.defaultMenus |
||||
} |
||||
}, |
||||
jump(item){ |
||||
this.active = item.index |
||||
this.$router.push(item.index) |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.nav{ |
||||
position: absolute; |
||||
top: 0; |
||||
left: 50%; |
||||
transform: translateX(-50%); |
||||
display: flex; |
||||
padding-bottom: 10px; |
||||
li{ |
||||
padding: 25px; |
||||
font-size: 16px; |
||||
color: #0d0d0d; |
||||
cursor: pointer; |
||||
&.active{ |
||||
color: #fff; |
||||
background-color: #568df2; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,186 @@ |
||||
<template> |
||||
<div class="tags" v-if="showTags"> |
||||
<ul> |
||||
<li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index"> |
||||
<router-link :to="item.path" class="tags-li-title"> |
||||
{{item.title}} |
||||
</router-link> |
||||
<span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span> |
||||
</li> |
||||
</ul> |
||||
<div class="tags-close-box"> |
||||
<el-dropdown @command="handleTags"> |
||||
<el-button size="mini" type="primary"> |
||||
标签选项<i class="el-icon-arrow-down el-icon--right"></i> |
||||
</el-button> |
||||
<el-dropdown-menu size="small" slot="dropdown"> |
||||
<el-dropdown-item command="other">关闭其他</el-dropdown-item> |
||||
<el-dropdown-item command="all">关闭所有</el-dropdown-item> |
||||
</el-dropdown-menu> |
||||
</el-dropdown> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import bus from '@/libs/bus'; |
||||
export default { |
||||
data() { |
||||
return { |
||||
tagsList: [] |
||||
} |
||||
}, |
||||
methods: { |
||||
isActive(path) { |
||||
return path === this.$route.fullPath; |
||||
}, |
||||
// 关闭单个标签 |
||||
closeTags(index) { |
||||
const delItem = this.tagsList.splice(index, 1)[0]; |
||||
const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1]; |
||||
if (item) { |
||||
delItem.path === this.$route.fullPath && this.$router.push(item.path); |
||||
}else{ |
||||
this.$router.push('/'); |
||||
} |
||||
}, |
||||
// 关闭全部标签 |
||||
closeAll(){ |
||||
this.tagsList = []; |
||||
this.$router.push('/'); |
||||
}, |
||||
// 关闭其他标签 |
||||
closeOther(){ |
||||
const curItem = this.tagsList.filter(item => { |
||||
return item.path === this.$route.fullPath; |
||||
}) |
||||
this.tagsList = curItem; |
||||
}, |
||||
// 设置标签 |
||||
setTags(route){ |
||||
const isExist = this.tagsList.some(item => { |
||||
return item.path === route.fullPath; |
||||
}) |
||||
if(!isExist){ |
||||
if(this.tagsList.length >= 8){ |
||||
this.tagsList.shift(); |
||||
} |
||||
this.tagsList.push({ |
||||
title: route.meta.title, |
||||
path: route.fullPath, |
||||
name: route.matched[1].components.default.name |
||||
}) |
||||
} |
||||
bus.$emit('tags', this.tagsList); |
||||
}, |
||||
handleTags(command){ |
||||
command === 'other' ? this.closeOther() : this.closeAll(); |
||||
} |
||||
}, |
||||
computed: { |
||||
showTags() { |
||||
return this.tagsList.length > 0; |
||||
} |
||||
}, |
||||
watch:{ |
||||
$route(newValue, oldValue){ |
||||
this.setTags(newValue); |
||||
} |
||||
}, |
||||
created(){ |
||||
this.setTags(this.$route); |
||||
// 监听关闭当前页面的标签页 |
||||
bus.$on('close_current_tags', () => { |
||||
for (let i = 0, len = this.tagsList.length; i < len; i++) { |
||||
const item = this.tagsList[i]; |
||||
if(item.path === this.$route.fullPath){ |
||||
if(i < len - 1){ |
||||
this.$router.push(this.tagsList[i+1].path); |
||||
}else if(i > 0){ |
||||
this.$router.push(this.tagsList[i-1].path); |
||||
}else{ |
||||
this.$router.push('/'); |
||||
} |
||||
this.tagsList.splice(i, 1); |
||||
break; |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
</script> |
||||
|
||||
|
||||
<style> |
||||
.tags { |
||||
position: relative; |
||||
height: 30px; |
||||
overflow: hidden; |
||||
background: #fff; |
||||
padding-right: 120px; |
||||
box-shadow: 0 5px 10px #ddd; |
||||
} |
||||
|
||||
.tags ul { |
||||
box-sizing: border-box; |
||||
width: 100%; |
||||
height: 100%; |
||||
} |
||||
|
||||
.tags-li { |
||||
float: left; |
||||
margin: 3px 5px 2px 3px; |
||||
border-radius: 3px; |
||||
font-size: 12px; |
||||
overflow: hidden; |
||||
cursor: pointer; |
||||
height: 23px; |
||||
line-height: 23px; |
||||
border: 1px solid #e9eaec; |
||||
background: #fff; |
||||
padding: 0 5px 0 12px; |
||||
vertical-align: middle; |
||||
color: #666; |
||||
-webkit-transition: all .3s ease-in; |
||||
-moz-transition: all .3s ease-in; |
||||
transition: all .3s ease-in; |
||||
} |
||||
|
||||
.tags-li:not(.active):hover { |
||||
background: #f8f8f8; |
||||
} |
||||
|
||||
.tags-li.active { |
||||
color: #fff; |
||||
} |
||||
|
||||
.tags-li-title { |
||||
float: left; |
||||
max-width: 80px; |
||||
overflow: hidden; |
||||
white-space: nowrap; |
||||
text-overflow: ellipsis; |
||||
margin-right: 5px; |
||||
color: #666; |
||||
} |
||||
|
||||
.tags-li.active .tags-li-title { |
||||
color: #fff; |
||||
} |
||||
|
||||
.tags-close-box { |
||||
position: absolute; |
||||
right: 0; |
||||
top: 0; |
||||
box-sizing: border-box; |
||||
padding-top: 1px; |
||||
text-align: center; |
||||
width: 110px; |
||||
height: 30px; |
||||
background: #fff; |
||||
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1); |
||||
z-index: 10; |
||||
} |
||||
|
||||
</style> |
@ -0,0 +1,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.component ? result.push(`${e.component}:${n.name}:${j.name}`) : result.push(`${n.component}:${j.name}`)) |
||||
}) |
||||
}else{ |
||||
result.push(`${e.component}:${n.name}`) |
||||
} |
||||
} |
||||
}) |
||||
} |
||||
}) |
||||
store.commit('addBtnPerData',{btnPermissions: result}) |
||||
} |
@ -0,0 +1,6 @@ |
||||
import Vue from 'vue'; |
||||
|
||||
// 使用 Event Bus
|
||||
const bus = new Vue(); |
||||
|
||||
export default bus; |
@ -0,0 +1,10 @@ |
||||
// 生成随机字符串
|
||||
export default function (len = 32) { |
||||
const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; |
||||
const maxPos = $chars.length; |
||||
let str = ''; |
||||
for (let i = 0; i < len; i++) { |
||||
str += $chars.charAt(Math.floor(Math.random() * maxPos)); |
||||
} |
||||
return str; |
||||
} |
@ -0,0 +1,16 @@ |
||||
// rem等比适配配置文件
|
||||
// 基准大小
|
||||
const baseSize = 16 |
||||
// 设置 rem 函数
|
||||
function setRem () { |
||||
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
|
||||
const scale = document.documentElement.clientWidth / 1920 |
||||
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
|
||||
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px' |
||||
} |
||||
// 初始化
|
||||
setRem() |
||||
// 改变窗口大小时重新设置 rem
|
||||
window.onresize = function () { |
||||
setRem() |
||||
} |
@ -0,0 +1,34 @@ |
||||
import store from '@/store'; |
||||
import router from '@/router'; |
||||
import generateBtnPermission from '../auth/generateBtnPermission'; |
||||
|
||||
const newRoutes = [] |
||||
|
||||
function createMeta(item){ |
||||
let meta = { title: item.name } |
||||
return meta |
||||
} |
||||
|
||||
function createRoute(data){ |
||||
data.map(e => { |
||||
if(e.select && e.component){ |
||||
let meta = createMeta(e) |
||||
newRoutes.push({ |
||||
name: e.component, |
||||
path: e.component, |
||||
component: () => import(`@/pages/${e.component}.vue`), |
||||
meta |
||||
}) |
||||
} |
||||
e.children && e.children.length && createRoute(e.children) |
||||
}) |
||||
} |
||||
|
||||
export default function(data,path){ |
||||
generateBtnPermission(data) |
||||
createRoute(data) |
||||
let routes = router.options.routes |
||||
routes[1].children = [...routes[1].children,...newRoutes] |
||||
store.commit("addRoutesData", { routes }) |
||||
router.addRoutes(routes) |
||||
} |
@ -0,0 +1,26 @@ |
||||
import store from '@/store'; |
||||
import router from '@/router'; |
||||
|
||||
export default function(){ |
||||
setTimeout(() => { |
||||
let routes = store.state.routes |
||||
routes.forEach(e => { |
||||
if(e.path == '/'){ |
||||
e.component = () => import('@/layouts/home/index.vue') |
||||
}else{ |
||||
e.component = () => import(`@/pages/${e.path}.vue`) |
||||
} |
||||
|
||||
e.children && e.children.forEach(n => { |
||||
n.path && (n.component = () => import(`@/pages/${n.path}.vue`)) |
||||
}) |
||||
}) |
||||
|
||||
routes.push({ |
||||
path: '*', |
||||
redirect: '404' |
||||
}) |
||||
|
||||
router.addRoutes(routes) |
||||
},500) |
||||
} |
@ -0,0 +1,6 @@ |
||||
import router from '@/router'; |
||||
|
||||
export default function(){ |
||||
const newRouter = createRouter() |
||||
router.matcher = newRouter.matcher |
||||
} |
@ -0,0 +1,43 @@ |
||||
import Cookies from 'js-cookie'; |
||||
import Setting from '@/setting'; |
||||
|
||||
const cookies = {}; |
||||
|
||||
/** |
||||
* @description 存储 cookie 值 |
||||
* @param {String} name cookie name |
||||
* @param {String} value cookie value |
||||
* @param {Object} cookieSetting cookie setting |
||||
*/ |
||||
cookies.set = function (name = 'default', value = '', cookieSetting = {}) { |
||||
let currentCookieSetting = { |
||||
expires: Setting.cookiesExpires |
||||
}; |
||||
Object.assign(currentCookieSetting, cookieSetting); |
||||
Cookies.set(`admin-${name}`, value, currentCookieSetting); |
||||
}; |
||||
|
||||
/** |
||||
* @description 拿到 cookie 值 |
||||
* @param {String} name cookie name |
||||
*/ |
||||
cookies.get = function (name = 'default') { |
||||
return Cookies.get(`admin-${name}`); |
||||
}; |
||||
|
||||
/** |
||||
* @description 拿到 cookie 全部的值 |
||||
*/ |
||||
cookies.getAll = function () { |
||||
return Cookies.get(); |
||||
}; |
||||
|
||||
/** |
||||
* @description 删除 cookie |
||||
* @param {String} name cookie name |
||||
*/ |
||||
cookies.remove = function (name = 'default') { |
||||
return Cookies.remove(`admin-${name}`); |
||||
}; |
||||
|
||||
export default cookies; |
@ -0,0 +1,82 @@ |
||||
/** |
||||
* localStorage |
||||
* @调用:_local.set('access_token', '123456', 5000); |
||||
* @调用:_local.get('access_token'); |
||||
*/ |
||||
|
||||
var _local = { |
||||
//存储,可设置过期时间
|
||||
set(key, value, expires) { |
||||
let params = { key, value, expires }; |
||||
if (expires) { |
||||
// 记录何时将值存入缓存,毫秒级
|
||||
var data = Object.assign(params, { startTime: new Date().getTime() }); |
||||
localStorage.setItem(key, JSON.stringify(data)); |
||||
} else { |
||||
if (Object.prototype.toString.call(value) == '[object Object]') { |
||||
value = JSON.stringify(value); |
||||
} |
||||
if (Object.prototype.toString.call(value) == '[object Array]') { |
||||
value = JSON.stringify(value); |
||||
} |
||||
localStorage.setItem(key, value); |
||||
} |
||||
}, |
||||
//取出
|
||||
get(key) { |
||||
let item = localStorage.getItem(key); |
||||
// 先将拿到的试着进行json转为对象的形式
|
||||
try { |
||||
item = JSON.parse(item); |
||||
} catch (error) { |
||||
// eslint-disable-next-line no-self-assign
|
||||
item = item; |
||||
} |
||||
// 如果有startTime的值,说明设置了失效时间
|
||||
if (item && item.startTime) { |
||||
let date = new Date().getTime(); |
||||
// 如果大于就是过期了,如果小于或等于就还没过期
|
||||
if (date - item.startTime > item.expires) { |
||||
localStorage.removeItem(name); |
||||
return false; |
||||
} else { |
||||
return item.value; |
||||
} |
||||
} else { |
||||
return item; |
||||
} |
||||
}, |
||||
// 删除
|
||||
remove(key) { |
||||
localStorage.removeItem(key); |
||||
}, |
||||
// 清除全部
|
||||
clear() { |
||||
localStorage.clear(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* sessionStorage |
||||
*/ |
||||
var _session = { |
||||
get: function (key) { |
||||
var data = sessionStorage[key]; |
||||
if (!data || data === "null") { |
||||
return null; |
||||
} |
||||
return data; |
||||
}, |
||||
set: function (key, value) { |
||||
sessionStorage[key] = value; |
||||
}, |
||||
// 删除
|
||||
remove(key) { |
||||
sessionStorage.removeItem(key); |
||||
}, |
||||
// 清除全部
|
||||
clear() { |
||||
sessionStorage.clear(); |
||||
} |
||||
} |
||||
export { _local, _session } |
@ -0,0 +1,121 @@ |
||||
import cookies from './util.cookies' |
||||
import {_local,_session} from './util.db' |
||||
import { Message } from 'element-ui' |
||||
|
||||
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() |
||||
}, |
||||
// 成功提示
|
||||
successMsg(message) { |
||||
Message.success({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration: 3000}) |
||||
}, |
||||
// 警告提示
|
||||
warningMsg(message) { |
||||
Message.warning({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration: 3000}) |
||||
}, |
||||
// 错误提示
|
||||
errorMsg(message) { |
||||
Message.error({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration: 3000}) |
||||
}, |
||||
} |
||||
|
||||
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,176 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
<vHead></vHead> |
||||
<div class="login"> |
||||
<div class="names"> |
||||
<img class="logo" src="../../../assets/img/three.png" alt=""> |
||||
<p class="text">或然数据网</p> |
||||
</div> |
||||
<div class="form"> |
||||
<div class="title"><span>登录</span></div> |
||||
<el-form :model="loginForm" :rules="loginRules" ref="login" label-width="0px"> |
||||
<el-form-item prop="username"> |
||||
<label class="account"></label> |
||||
<el-input v-model="loginForm.username" placeholder="请输入账号/手机号" @keyup.enter.native="submitForm()"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="password"> |
||||
<label class="password"></label> |
||||
<el-input type="password" placeholder="请输入密码" v-model="loginForm.password" @keyup.enter.native="submitForm()"></el-input> |
||||
</el-form-item> |
||||
<div class="check"> |
||||
<el-checkbox v-model="remember">15天免费登录</el-checkbox> |
||||
</div> |
||||
<el-button class="submit" type="primary" @click="submitForm">登录</el-button> |
||||
</el-form> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapActions } from 'vuex' |
||||
import vHead from '@/layouts/header' |
||||
export default { |
||||
data: function() { |
||||
return { |
||||
loginForm: { |
||||
username: '20204400194', |
||||
password: '111aaa', |
||||
}, |
||||
loginRules: { |
||||
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }], |
||||
password: [{ required: true, message: '请输入密码', trigger: 'blur' }], |
||||
}, |
||||
remember: false |
||||
}; |
||||
}, |
||||
components: {vHead}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'login' |
||||
]), |
||||
submitForm() { |
||||
this.$refs.login.validate(valid => { |
||||
if (valid) { |
||||
let data = { |
||||
username: this.loginForm.username, |
||||
password: this.loginForm.password |
||||
} |
||||
this.login(data).then(() => { |
||||
let redirect = this.$route.query.redirect ? decodeURIComponent(this.$route.query.redirect) : '/index' |
||||
this.$router.replace(redirect) |
||||
}).catch(() => {}) |
||||
} |
||||
}) |
||||
}, |
||||
}, |
||||
}; |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.wrap { |
||||
min-height: 100%; |
||||
background: url(../../../assets/img/login-bg.png) 0 0/100% 100% no-repeat; |
||||
overflow: hidden; |
||||
|
||||
.login{ |
||||
width: 500px; |
||||
margin: 0 auto; |
||||
text-align: center; |
||||
.names{ |
||||
margin: 70px 0; |
||||
.text{ |
||||
margin-top: 10px; |
||||
font-size: 20px; |
||||
color: #fff; |
||||
} |
||||
} |
||||
|
||||
.form{ |
||||
padding: 30px; |
||||
margin-top: 30px; |
||||
border-radius: 10px; |
||||
background-color: #fff; |
||||
.title{ |
||||
position: relative; |
||||
margin-bottom: 30px; |
||||
text-align: center; |
||||
span{ |
||||
display: inline-block; |
||||
padding: 9px 20px; |
||||
color: #555; |
||||
border-bottom: 2px solid $main-color; |
||||
} |
||||
&:after{ |
||||
content: ''; |
||||
position: absolute; |
||||
left: 0; |
||||
bottom: -1px; |
||||
width: 100%; |
||||
height: 1px; |
||||
background-color: #e0e0e0; |
||||
} |
||||
} |
||||
.el-form{ |
||||
padding: 0 70px; |
||||
} |
||||
.label{ |
||||
margin-bottom: 10px; |
||||
color: #105CB2; |
||||
} |
||||
/deep/.el-input__inner{ |
||||
position: relative; |
||||
height: 46px; |
||||
padding: 0 20px 0 40px; |
||||
line-height: 46px; |
||||
border: 0; |
||||
border-bottom: 1px solid #e4e4e4; |
||||
border-radius: 0 !important; |
||||
} |
||||
.account,.password{ |
||||
z-index: 10; |
||||
position: absolute; |
||||
top: 11px; |
||||
left: 8px; |
||||
width: 24px; |
||||
height: 28px; |
||||
background: url(../../../assets/img/account.png) 0 0/100% 100% no-repeat; |
||||
} |
||||
.password{ |
||||
width: 22px; |
||||
height: 24px; |
||||
background-image: url(../../../assets/img/password.png); |
||||
} |
||||
.check{ |
||||
text-align: left; |
||||
} |
||||
/deep/.el-form-item__error{ |
||||
top: 105%; |
||||
left: auto; |
||||
right: 0; |
||||
color: #FFA94E; |
||||
} |
||||
.submit{ |
||||
width: 100%; |
||||
height: 48px; |
||||
margin-top: 30px; |
||||
line-height: 48px; |
||||
padding: 0; |
||||
font-size: 20px; |
||||
background-color: $main-color; |
||||
border-radius: 8px; |
||||
border: 0; |
||||
} |
||||
.links{ |
||||
margin: 20px 0 20px; |
||||
} |
||||
.login-tips{ |
||||
margin-bottom: 20px; |
||||
font-size: 16px; |
||||
color: #105CB2; |
||||
text-align: center; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,285 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
<div class="left"> |
||||
<el-menu class="menu" @open="handleOpen" @close="handleClose" :default-active="active"> |
||||
<template v-for="item in typeList"> |
||||
<!-- 如果第一层有子菜单,则继续循环 --> |
||||
<template v-if="item.subs"> |
||||
<el-submenu :index="item.index" :key="item.index"> |
||||
<template slot="title"> |
||||
<i :class="item.icon"></i> |
||||
<span slot="title">{{ item.title }}</span> |
||||
</template> |
||||
<!-- 第二层 --> |
||||
<template v-for="subItem in item.subs"> |
||||
<!-- 如果第二层有子菜单,则继续循环 --> |
||||
<template v-if="subItem.subs"> |
||||
<el-submenu :index="subItem.index" :key="subItem.index"> |
||||
<template slot="title"> |
||||
<span slot="title">{{ subItem.title }}</span> |
||||
</template> |
||||
<!-- <el-menu-item v-for="(threeItem,i) in subItem.subs" :key="i" :index="threeItem.index">{{ threeItem.title }}</el-menu-item> --> |
||||
<!-- 第三层 --> |
||||
<template v-for="subItem2 in subItem.subs"> |
||||
<!-- 如果第三层有子菜单,则继续循环 --> |
||||
<template v-if="subItem2.subs"> |
||||
<el-submenu :index="subItem2.index" :key="subItem2.index"> |
||||
<template slot="title"> |
||||
<span slot="title">{{ subItem2.title }}</span> |
||||
</template> |
||||
<!-- <el-menu-item v-for="(fourItem,i) in subItem2.subs" :key="i" :index="fourItem.index">{{ fourItem.title }}</el-menu-item> --> |
||||
<!-- 第四层 --> |
||||
<template v-for="subItem3 in subItem2.subs"> |
||||
<!-- 如果第四层有子菜单,则继续循环 --> |
||||
<template v-if="subItem3.subs"> |
||||
<el-submenu :index="subItem3.index" :key="subItem3.index"> |
||||
<template slot="title"> |
||||
<!-- <i :class="item.icon"></i> --> |
||||
<!-- <span slot="title">{{ subItem2.title }}</span> --> |
||||
{{ subItem3.title }} |
||||
</template> |
||||
<el-menu-item v-for="(fiveItem,i) in subItem3.subs" :key="i" :index="fiveItem.index">{{ fiveItem.title }}</el-menu-item> |
||||
</el-submenu> |
||||
</template> |
||||
<!-- 如果第四层没有子菜单 --> |
||||
<el-menu-item v-else :index="subItem3.index" :key="subItem3.index">{{ subItem3.title }}</el-menu-item> |
||||
</template> |
||||
</el-submenu> |
||||
</template> |
||||
<!-- 如果第三层没有子菜单 --> |
||||
<el-menu-item v-else :index="subItem2.index" :key="subItem2.index">{{ subItem2.title }}</el-menu-item> |
||||
</template> |
||||
</el-submenu> |
||||
</template> |
||||
<!-- 如果第二层没有子菜单 --> |
||||
<el-menu-item v-else :index="subItem.index" :key="subItem.index">{{ subItem.title }}</el-menu-item> |
||||
</template> |
||||
</el-submenu> |
||||
</template> |
||||
<!-- 如果第一层没有子菜单 --> |
||||
<template v-else> |
||||
<el-menu-item :index="item.index" :key="item.index"> |
||||
<i :class="item.icon"></i> |
||||
<span slot="title">{{ item.title }}</span> |
||||
</el-menu-item> |
||||
</template> |
||||
</template> |
||||
</el-menu> |
||||
</div> |
||||
<div class="right"> |
||||
<div class="block"> |
||||
<h6 class="title">数据介绍</h6> |
||||
<div class="desc"> |
||||
测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试测试 |
||||
</div> |
||||
|
||||
<el-table :data="listData" class="table" stripe header-align="center" row-key="id"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> |
||||
<el-table-column prop="practiseName" label="数据表名称" align="center"></el-table-column> |
||||
<el-table-column prop="paperName" label="数据总量" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="数据大小" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="更新时间" align="center"></el-table-column> |
||||
<el-table-column label="操作" width="220" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="preview(scope.row)">预览</el-button> |
||||
<el-button type="text" @click="download(scope.row)">下载</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="handleCurrentChange" :current-page="page" layout="total, prev, pager, next" :total="total"></el-pagination> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="block"> |
||||
<h6 class="title">数据预览</h6> |
||||
|
||||
<el-table :data="previewData" class="table" stripe header-align="center" row-key="id"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> |
||||
<el-table-column prop="practiseName" label="代码" align="center"></el-table-column> |
||||
<el-table-column prop="paperName" label="名称" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="最新价" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="涨跌额" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="涨跌幅" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="今开" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="最高" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="最低" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="昨结" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="成交量" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="成交额" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="买盘(外盘)" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="买盘(内盘)" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="持仓量" align="center"></el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="handlePreviewCurrentChange" :current-page="pagePreview" layout="total, prev, pager, next" :total="totalPreview"></el-pagination> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-dialog title="下载" :visible.sync="downloadVisible" width="540px" @close="closeDownload" :close-on-click-modal="false"> |
||||
<el-form ref="form" label-width="100px" label-suffix=":"> |
||||
<el-form-item label="数据筛选"> |
||||
<div class="checkboxs"> |
||||
<el-checkbox-group v-model="field"> |
||||
<el-checkbox v-for="(item,index) in fieldList" :key="index" :label="item.name"></el-checkbox> |
||||
</el-checkbox-group> |
||||
</div> |
||||
</el-form-item> |
||||
<el-form-item label="开始时间"> |
||||
<el-date-picker v-model="startTime" type="date" placeholder="请选择开始时间" size="small"></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="结束时间"> |
||||
<el-date-picker v-model="endTime" type="date" placeholder="请选择结束时间" size="small"></el-date-picker> |
||||
</el-form-item> |
||||
<el-form-item label="数据频率"> |
||||
<el-select v-model="frequency" placeholder="请选择数据频率" size="small"> |
||||
<el-option v-for="(item,index) in frequencyList" :key="index" :label="item.name" :value="item.id"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-form> |
||||
|
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="downloadVisible = false">取消</el-button> |
||||
<el-button size="small" type="primary" @click="confirmDown">确定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
typeList: [ |
||||
{ |
||||
icon: 'menu-icon icon-index', |
||||
index: '1', |
||||
title: '股票数据' |
||||
},{ |
||||
icon: 'menu-icon icon-index', |
||||
index: '2', |
||||
title: '期货数据', |
||||
}, |
||||
], |
||||
active: '1', |
||||
listData: [ |
||||
{} |
||||
], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
previewData: [], |
||||
pagePreview: 1, |
||||
pageSizePreview: 10, |
||||
totalPreview: 0, |
||||
downloadVisible: false, |
||||
field: [], |
||||
startTime: '', |
||||
endTime: '', |
||||
frequency: '', |
||||
frequencyList: [ |
||||
{ |
||||
id: 1, |
||||
name: '日频' |
||||
},{ |
||||
id: 2, |
||||
name: '周频' |
||||
},{ |
||||
id: 3, |
||||
name: '月频' |
||||
},{ |
||||
id: 4, |
||||
name: '季频' |
||||
},{ |
||||
id: 5, |
||||
name: '年频' |
||||
}, |
||||
], |
||||
fieldList: [ |
||||
{ |
||||
id: 1, |
||||
name: '代码' |
||||
},{ |
||||
id: 2, |
||||
name: '名称' |
||||
} |
||||
], |
||||
} |
||||
}, |
||||
mounted() { |
||||
|
||||
}, |
||||
methods: { |
||||
getData(){ |
||||
|
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val |
||||
this.$refs.table.clearSelection() |
||||
this.getData() |
||||
}, |
||||
handlePreviewCurrentChange(val) { |
||||
this.pagePreview = val |
||||
this.$refs.table.clearSelection() |
||||
this.getData() |
||||
}, |
||||
preview(row){ |
||||
|
||||
}, |
||||
download(row){ |
||||
this.downloadVisible = true |
||||
}, |
||||
closeDownload(){ |
||||
|
||||
}, |
||||
handleOpen(){ |
||||
|
||||
}, |
||||
handleClose(){ |
||||
|
||||
}, |
||||
confirmDown(){ |
||||
|
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.wrap{ |
||||
display: flex; |
||||
.left{ |
||||
margin-right: 20px; |
||||
|
||||
.menu{ |
||||
width: 200px; |
||||
padding: 10px 0; |
||||
border-radius: 8px; |
||||
overflow: hidden; |
||||
.el-menu-item.is-active{ |
||||
color: #fff; |
||||
background-color: $main-color; |
||||
} |
||||
} |
||||
} |
||||
.block{ |
||||
padding: 34px; |
||||
margin-bottom: 20px; |
||||
background-color: #fff; |
||||
border-radius: 8px; |
||||
.title{ |
||||
padding-left: 11px; |
||||
margin-bottom: 20px; |
||||
font-size: 17px; |
||||
color: $main-color; |
||||
line-height: 1.8; |
||||
border-left: 6px solid; |
||||
} |
||||
.desc{ |
||||
margin-bottom: 30px; |
||||
color: #333; |
||||
} |
||||
} |
||||
} |
||||
</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,70 @@ |
||||
<template> |
||||
<div> |
||||
<div class="title">欢迎来到<br>或然数据网</div> |
||||
<div class="search"> |
||||
<div class="input"> |
||||
<img src="../../../assets/img/search-white.png" alt=""> |
||||
<input type="text" placeholder="请输入关键词"> |
||||
</div> |
||||
<img src="../../../assets/img/remove.png" alt="" class="remove"> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: 'index', |
||||
data() { |
||||
return { |
||||
|
||||
} |
||||
}, |
||||
mounted() { |
||||
|
||||
}, |
||||
methods: { |
||||
|
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.title{ |
||||
margin: 70px 0 130px; |
||||
font-size: 50px; |
||||
color: #fff; |
||||
text-align: center; |
||||
} |
||||
.search{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
width: 930px; |
||||
padding: 7px 20px; |
||||
margin: 0 auto; |
||||
border-bottom: 2px solid #fff; |
||||
.input{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
} |
||||
input{ |
||||
padding-left: 20px; |
||||
margin-left: 30px; |
||||
font-size: 24px; |
||||
color: #fff; |
||||
background-color: transparent; |
||||
border: 0; |
||||
border-left: 2px solid #fff; |
||||
&::-webkit-input-placeholder{color: #fff} |
||||
&::-moz-placeholder{color: #fff} |
||||
&:-moz-placeholder{color: #fff} |
||||
&:focus{ |
||||
outline: none; |
||||
} |
||||
} |
||||
.remove{ |
||||
cursor: pointer; |
||||
} |
||||
} |
||||
</style> |
||||
|
@ -0,0 +1,295 @@ |
||||
<template> |
||||
<div> |
||||
<div class="page"> |
||||
<div class="page-content"> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>搜索:</label> |
||||
<el-input placeholder="请输入角色名称" v-model="keyword" suffix-icon="el-icon-search" clearable size="small"></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" round @click="addRole" v-auth="'/system/list:角色权限:新增角色'">新增角色</el-button> |
||||
<el-button type="primary" size="small" round @click="delAllSelection" v-auth="'/system/list:角色权限:批量删除'">批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="roleData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" :row-key="getRowKeys"> |
||||
<el-table-column type="selection" width="80" align="center" :reserve-selection="true"></el-table-column> |
||||
<el-table-column type="index" width="100" label="序号" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="roleName" label="角色名称" align="center" width="100"> |
||||
</el-table-column> |
||||
<el-table-column label="角色描述" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-input disabled placeholder="该角色用于管理全部功能权限" v-model="scope.row.remark "></el-input> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="操作" width="180" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="showRole(scope.row)" v-auth="'/system/list:角色权限:查看'">查看</el-button> |
||||
<template v-if="scope.row.id != 1"> |
||||
<el-button type="text" @click="editRole(scope.row)" v-auth="'/system/list:角色权限:编辑'">编辑</el-button> |
||||
<el-button type="text" @click="handleDelete(scope.row)" v-auth="'/system/list:角色权限:删除'">删除</el-button> |
||||
</template> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next" :total="total"> |
||||
</el-pagination> |
||||
</div> |
||||
|
||||
<el-dialog :title="isDetail ? '查看角色' : (isAdd ? '新增角色' : '编辑角色')" :visible.sync="roleVisible" width="500px" @close="closeRole" class="dialog" :close-on-click-modal="false"> |
||||
<el-form ref="form" :model="form" label-width="100px" label-suffix=":" :disabled="isDetail"> |
||||
<el-form-item label="角色名称"> |
||||
<el-input v-model="form.roleName " ref="account" placeholder="请输入角色名称"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="角色描述"> |
||||
<el-input v-model="form.remark " placeholder="请输入角色描述" type="textarea" rows="5"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="role" label="角色权限"> |
||||
<div class="per-wrap"> |
||||
<el-tree |
||||
ref="per" |
||||
:data="permissions" |
||||
show-checkbox |
||||
node-key="id" |
||||
:default-expanded-keys="checkedIds" |
||||
:default-checked-keys="checkedIds" |
||||
:props="defaultProps"> |
||||
</el-tree> |
||||
</div> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||
<el-button size="small" @click="roleVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="saveData">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState } from 'vuex' |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'role', |
||||
data() { |
||||
return { |
||||
keyword: '', |
||||
form: { |
||||
roleName : '', |
||||
remark : '', |
||||
id: '' |
||||
}, |
||||
isDetail: false, |
||||
roleData:[], |
||||
defaultProps: { |
||||
children: 'children', |
||||
label: 'name' |
||||
}, |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
multipleSelection: [], |
||||
importVisible: false, |
||||
isAdd: true, |
||||
roleVisible: false, |
||||
searchTimer: null, |
||||
permissions: [], |
||||
checkedIds: [] |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','clientId' |
||||
]) |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
clientId: this.clientId |
||||
} |
||||
if(this.keyword.length){ |
||||
data.name = this.keyword |
||||
} |
||||
this.$get(`${this.api.queryRoles}/${this.page}/${this.pageSize}`,data).then(res => { |
||||
this.roleData = res.data.items |
||||
this.total = res.data.total |
||||
if(!this.roleData.length && this.total){ |
||||
this.page-- |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
initData(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
closeRole(){ |
||||
this.isDetail = false |
||||
this.form = { |
||||
roleName : '', |
||||
remark : '', |
||||
id: '' |
||||
} |
||||
this.checkedIds = [] |
||||
this.permissions = [] |
||||
}, |
||||
currentChange(val) { |
||||
this.page = val |
||||
this.$refs.table.clearSelection() |
||||
this.getData() |
||||
}, |
||||
getPer(){ |
||||
if(!this.permissions.length){ |
||||
this.$get(this.api.queryPermissionMenu).then(res => { |
||||
this.permissions = res.data.children[0].children |
||||
}).catch(res => {}) |
||||
} |
||||
}, |
||||
addRole(){ |
||||
this.isAdd = true |
||||
this.getPer() |
||||
this.checkedIds = [] |
||||
this.permissions.length && this.$refs.per.setCheckedNodes([]) |
||||
this.roleVisible = true |
||||
}, |
||||
handleRolePer(data,permissions){ |
||||
let result = data |
||||
if(permissions.length){ |
||||
permissions.map(e => { |
||||
if(result.includes(e.id) && e.children.length){ |
||||
e.children.every(n => result.includes(n)) || result.splice(result.indexOf(e.id),1) |
||||
} |
||||
e.children.length && this.handleRolePer(data,e.children) |
||||
}) |
||||
} |
||||
return result |
||||
}, |
||||
async getDetail(row){ |
||||
this.getPer() |
||||
let roleRes = await this.$get(`${this.api.getRole}/${row.id}`) |
||||
if(roleRes.success){ |
||||
this.form = roleRes.data.item |
||||
let perRes = await this.$get(`${this.api.toAssign}/${row.id}`) |
||||
if(perRes.success){ |
||||
this.checkedIds = this.handleRolePer(perRes.data.rolePermissions,this.permissions) |
||||
this.$refs.per.setCheckedNodes(this.checkedIds) |
||||
} |
||||
} |
||||
}, |
||||
showRole(row){ |
||||
this.isDetail = true |
||||
this.isAdd = false |
||||
this.getDetail(row) |
||||
this.roleVisible = true |
||||
}, |
||||
editRole(row){ |
||||
this.isAdd = false |
||||
this.getDetail(row) |
||||
this.roleVisible = true |
||||
}, |
||||
async saveData() { |
||||
if(!this.form.roleName) return util.warningMsg('请填写角色名称') |
||||
if(!this.form.remark) return util.warningMsg('请填写角色描述') |
||||
// if(!this.$refs.per.getCheckedKeys().length) return util.warningMsg('请选择角色权限') |
||||
let roleData = { |
||||
clientId: this.clientId, |
||||
id: this.form.id, |
||||
roleName: this.form.roleName, |
||||
remark: this.form.remark, |
||||
isPort: 2 |
||||
} |
||||
let roleRes = await this.$post(this.api.saveOrUpdate,roleData) |
||||
if(roleRes.success){ |
||||
let permissionId = [...this.$refs.per.getHalfCheckedKeys(),...this.$refs.per.getCheckedKeys()] |
||||
let perData = { |
||||
clientId: this.clientId, |
||||
roleId: roleRes.data.roleId, |
||||
permissionId, |
||||
isPort: 2 |
||||
} |
||||
let perRes = await this.$post(this.api.doAssign,perData) |
||||
if(perRes.success){ |
||||
util.successMsg('新增成功') |
||||
this.getData() |
||||
this.roleVisible = false |
||||
} |
||||
} |
||||
}, |
||||
handleDelete(row) { |
||||
this.$confirm('该角色下已有账号,删除角色会将该角色下的账号一并删除,是否继续删除?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.removeRole}?roleIds=${row.id}`).then(res => { |
||||
if(res.success){ |
||||
util.successMsg('删除成功'); |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}) |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
getRowKeys(row) { |
||||
return row.id; |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
delAllSelection() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.id |
||||
}) |
||||
// 批量删除 |
||||
this.$confirm(`此批量删除操作不可逆,是否确认删除${util.ellipsisStr(newArr[0].roleName)}等${newArr.length}个选中项?`, '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
this.$del(`${this.api.removeRole}?roleIds=${delList.join()}`).then(res => { |
||||
if(res.success){ |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}) |
||||
}).catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !') |
||||
} |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.no-mb /deep/.el-form-item{ |
||||
margin-bottom: 0; |
||||
} |
||||
/deep/.el-row{ |
||||
padding: 0 !important; |
||||
margin-bottom: 0; |
||||
} |
||||
.per-wrap{ |
||||
max-height: 400px; |
||||
overflow: auto; |
||||
} |
||||
</style> |
@ -0,0 +1,108 @@ |
||||
<template> |
||||
<div> |
||||
<div class="block"> |
||||
<ul class="filter m-b-20"> |
||||
<li> |
||||
<label>搜索:</label> |
||||
<el-input placeholder="请输入名称" v-model="keyword" suffix-icon="el-icon-search" clearable size="small"></el-input> |
||||
</li> |
||||
</ul> |
||||
|
||||
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange"> |
||||
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="数据名称" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="数据表名称" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="数据总量" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="数据大小" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="更新时间" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="下载时间" align="center"></el-table-column> |
||||
<el-table-column label="操作" width="180" align="center"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="showRole(scope.row)">再次下载</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background @current-change="currentChange" :current-page="page" layout="total, prev, pager, next" :total="total"></el-pagination> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState } from 'vuex' |
||||
import util from '@/libs/util' |
||||
export default { |
||||
name: 'role', |
||||
data() { |
||||
return { |
||||
keyword: '', |
||||
searchTimer: null, |
||||
isDetail: false, |
||||
listData:[], |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
multipleSelection: [], |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','clientId' |
||||
]) |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted() { |
||||
this.getData() |
||||
}, |
||||
methods: { |
||||
getData() { |
||||
let data = { |
||||
clientId: this.clientId |
||||
} |
||||
if(this.keyword.length){ |
||||
data.name = this.keyword |
||||
} |
||||
this.$get(`${this.api.queryRoles}/${this.page}/${this.pageSize}`,data).then(res => { |
||||
this.listData = res.data.items |
||||
this.total = res.data.total |
||||
if(!this.listData.length && this.total){ |
||||
this.page-- |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
initData(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.block{ |
||||
padding: 34px; |
||||
margin-bottom: 20px; |
||||
background-color: #fff; |
||||
border-radius: 8px; |
||||
.title{ |
||||
padding-left: 11px; |
||||
margin-bottom: 20px; |
||||
font-size: 17px; |
||||
color: $main-color; |
||||
line-height: 1.8; |
||||
border-left: 6px solid; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,100 @@ |
||||
<template> |
||||
<div> |
||||
<div class="wrap"> |
||||
<div class="left"> |
||||
<div class="inner"> |
||||
<div class="text-center"> |
||||
<img :src="avatar" class="avatar" /> |
||||
<el-upload :action="this.api.fileupload" :data="{userId: this.userId}" name="file" :limit="1" :on-success="changeAvatar"> |
||||
<el-button type="text" size="small">上传头像</el-button> |
||||
</el-upload> |
||||
</div> |
||||
|
||||
<el-menu class="menu" :default-active="active" @select="handleSelect"> |
||||
<el-menu-item v-for="item in typeList" :index="item.index" :key="item.index"> |
||||
<i :class="item.icon"></i> |
||||
<span slot="title">{{ item.title }}</span> |
||||
</el-menu-item> |
||||
</el-menu> |
||||
</div> |
||||
</div> |
||||
<div class="right"> |
||||
<info v-if="active == 1"></info> |
||||
<download v-else></download> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState,mapActions } from 'vuex' |
||||
import info from './info' |
||||
import download from './download' |
||||
export default { |
||||
data() { |
||||
return { |
||||
typeList: [ |
||||
{ |
||||
index: '1', |
||||
title: '用户信息' |
||||
},{ |
||||
index: '2', |
||||
title: '我的下载', |
||||
}, |
||||
], |
||||
active: '1', |
||||
}; |
||||
}, |
||||
components: { info,download }, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','avatar','userName' |
||||
]), |
||||
}, |
||||
mounted() { |
||||
|
||||
}, |
||||
methods: { |
||||
//取得头像地址 |
||||
changeAvatar(res) { |
||||
this.setAvatar(res.data.filesResult.fileUrl) |
||||
}, |
||||
uploadHeadImg: function() { |
||||
this.$el.querySelector('.hiddenInput').click(); |
||||
}, |
||||
handleSelect(key, keyPath){ |
||||
console.log(key, keyPath) |
||||
this.active = key |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
/deep/.wrap{ |
||||
display: flex; |
||||
.left{ |
||||
margin-right: 20px; |
||||
.inner{ |
||||
width: 200px; |
||||
padding: 30px 0; |
||||
border-radius: 8px; |
||||
background-color: #fff; |
||||
} |
||||
.avatar{ |
||||
width: 80px; |
||||
height: 80px; |
||||
border-radius: 50%; |
||||
} |
||||
.menu{ |
||||
.el-menu-item.is-active{ |
||||
color: #fff; |
||||
background-color: $main-color; |
||||
} |
||||
} |
||||
} |
||||
.right{ |
||||
flex: 1; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,551 @@ |
||||
<template> |
||||
<div> |
||||
<div class="block"> |
||||
<h6 class="title">用户信息</h6> |
||||
<ul class="list"> |
||||
<li> |
||||
<label>姓名</label> |
||||
<div> |
||||
<el-input v-model="personalInformation.userName" clearable></el-input> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>性别</label> |
||||
<div> |
||||
<el-select v-model="personalInformation.sex"> |
||||
<el-option v-for="item in sexList" :key="item.value" :label="item.name" :value="item.value"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>出生年月日</label> |
||||
<div> |
||||
<el-date-picker |
||||
v-model="personalInformation.dateBirth" |
||||
:clearable="false" |
||||
class="block-right" |
||||
type="date"> |
||||
</el-date-picker> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>所在国家</label> |
||||
<div class="mul"> |
||||
<div class="child"> |
||||
<span>国家</span> |
||||
<div> |
||||
<el-select v-model="personalInformation.countries" placeholder> |
||||
<el-option |
||||
v-for="item in countryList" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
<div class="child"> |
||||
<span>省份</span> |
||||
<div> |
||||
<el-select v-model="personalInformation.provinceId" placeholder @change="id => getCity(id,1)"> |
||||
<el-option |
||||
v-for="item in provinceList" |
||||
:key="item.provinceId" |
||||
:label="item.provinceName" |
||||
:value="item.provinceId" |
||||
></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
<div class="child"> |
||||
<span>城市</span> |
||||
<div> |
||||
<el-select v-model="personalInformation.cityId" placeholder :disabled="personalInformation.provinceId ? false : true"> |
||||
<el-option |
||||
v-for="item in cityList" |
||||
:key="item.cityId" |
||||
:label="item.cityName" |
||||
:value="item.cityId" |
||||
></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>证件</label> |
||||
<div> |
||||
<el-input v-model="personalInformation.idnumber" clearable></el-input> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>教育程度</label> |
||||
<div> |
||||
<el-select v-model="personalInformation.educationDegree" placeholder="请选择教育程度"> |
||||
<el-option |
||||
v-for="(item,index) in educationDegreeList" |
||||
:key="index" |
||||
:label="item.name" |
||||
:value="item.value" |
||||
></el-option> |
||||
</el-select> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div class="block"> |
||||
<div class="flex j-between a-center m-b-20"> |
||||
<h6 class="title" style="margin-bottom: 0;">个人档案</h6> |
||||
<el-button type="text" icon="el-icon-plus" @click="addArch">新增</el-button> |
||||
</div> |
||||
|
||||
<div class="information"> |
||||
<div class="archives" v-for="(archive,index) in archivesList" :key="index" v-show="index == 0 || showArch"> |
||||
<ul class="list"> |
||||
<li> |
||||
<label>职业</label> |
||||
<div> |
||||
<el-select v-model="archive.personalCareerId" placeholder="选择职业"> |
||||
<el-option v-for="item in occupationList" :key="item.value" :label="item.label" :value="item.value"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>国家</label> |
||||
<div> |
||||
<el-select v-model="personalInformation.countries" placeholder> |
||||
<el-option v-for="item in countryList" :key="item.value" :label="item.label" :value="item.value" ></el-option> |
||||
</el-select> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>学校名称</label> |
||||
<div> |
||||
<el-select v-model="archive.schoolId" filterable placeholder="选择学校" @change="id => getSchoolName(id,index)"> |
||||
<el-option v-for="item in schoolList" :key="item.value" :label="item.schoolName" :value="item.schoolId"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</li> |
||||
|
||||
<li> |
||||
<label>专业</label> |
||||
<div class="mul"> |
||||
<div class="child"> |
||||
<span>专业学科</span> |
||||
<div> |
||||
<el-select v-model="archive.disciplineId" placeholder="选择专业学科" @change="id => getItemProfessionalClass(id,index)" @clear="() => clearItemClass(index)"> |
||||
<el-option v-for="item in subjectList" :key="item.value" :label="item.disciplineName" :value="item.disciplineId"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
<div class="child"> |
||||
<span>专业类</span> |
||||
<div> |
||||
<el-select v-model="archive.professionalClassId" placeholder="选择专业类" :disabled="archive.disciplineId ? false : true" @change="id => getItemProfessional(id,index)" @clear="() => clearItemProfess(index)"> |
||||
<el-option v-for="item in archive.ProfessionalClassList" :key="item.professionalClassId" :label="item.professionalClassName" :value="item.professionalClassId"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
<div class="child"> |
||||
<span>专业</span> |
||||
<div> |
||||
<el-select v-model="archive.professionalId" placeholder="选择专业" :disabled="archive.professionalClassId ? false : true" @change="getItemStuGrade"> |
||||
<el-option v-for="item in archive.ProfessionalList" :key="item.professionalId" :label="item.professionalName" :value="item.professionalId"></el-option> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div class="block"> |
||||
<h6 class="title">账号信息</h6> |
||||
<ul class="list"> |
||||
<li> |
||||
<label>用户账号</label> |
||||
<div> |
||||
<el-input v-model="personalInformation.account" clearable></el-input> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>手机号</label> |
||||
<div> |
||||
<el-input v-model="personalInformation.phone" clearable></el-input> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>邮箱</label> |
||||
<div> |
||||
<el-input v-model="personalInformation.email" clearable></el-input> |
||||
</div> |
||||
</li> |
||||
<li> |
||||
<label>密码</label> |
||||
<div> |
||||
<el-button size="small" @click="bindPassword">更换密码</el-button> |
||||
</div> |
||||
</li> |
||||
</ul> |
||||
<div class="text-right"> |
||||
<el-button type="primary" size="small" v-throttle @click="save">更新</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
|
||||
<el-dialog title="更换密码" :visible.sync="passwordVisible" :close-on-click-modal="false" @close="closePassword" width="30%"> |
||||
<el-form ref="passwordForm" :model="form" label-width="60px"> |
||||
<el-form-item label="原密码"> |
||||
<el-input type="password" v-model="passwordForm.password" placeholder="请输入原密码"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="新密码"> |
||||
<el-input type="password" v-model="passwordForm.newPassword" placeholder="请输入新密码" @keyup.enter.native="editPassword"></el-input> |
||||
</el-form-item> |
||||
<el-form-item label="新密码"> |
||||
<el-input type="password" v-model="passwordForm.reNewPassword" placeholder="请确认新密码" @keyup.enter.native="editPassword"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button @click="passwordVisible = false">取 消</el-button> |
||||
<el-button type="primary" @click="editPassword">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
import { mapState,mapActions } from 'vuex' |
||||
import util from '@/libs/util' |
||||
export default { |
||||
data() { |
||||
return { |
||||
personalInformation: { |
||||
name:'', |
||||
workNumber:'', |
||||
password:"", |
||||
phone:'', |
||||
email:'', |
||||
provinceName:'', |
||||
cityName:'', |
||||
schoolName:'', |
||||
professionalName:'', |
||||
}, |
||||
emailVisible: false, |
||||
passwordVisible: false, |
||||
phoneVisible: false, |
||||
showArch: false, |
||||
passwordForm: { |
||||
password: '', |
||||
newPassword: '', |
||||
reNewPassword: '' |
||||
}, |
||||
sexList: [ |
||||
{ |
||||
name: '男', |
||||
value: 1 |
||||
}, |
||||
{ |
||||
name: '女', |
||||
value: 2 |
||||
} |
||||
], |
||||
countryList: [ |
||||
{ |
||||
label: '中国' |
||||
} |
||||
], |
||||
form: {}, |
||||
provinceList:[], |
||||
cityList: [], |
||||
educationDegreeList: [ |
||||
{ |
||||
name: '专科', |
||||
value: 1 |
||||
}, |
||||
{ |
||||
name: '本科', |
||||
value: 2 |
||||
}, |
||||
{ |
||||
name: '硕士', |
||||
value: 3 |
||||
}, |
||||
{ |
||||
name: '博士', |
||||
value: 4 |
||||
}, |
||||
{ |
||||
name: '其他', |
||||
value: 5 |
||||
} |
||||
], |
||||
schoolList: [], |
||||
curPassword: '', |
||||
accountRepeat: false, |
||||
|
||||
archivesList: [], |
||||
archivesForm: { |
||||
//个人档案 |
||||
personalCareerId: '', //职业 |
||||
schoolId: '', //院校 |
||||
schoolName: '', //院校名称 |
||||
professionalClassId: '', //专业类 |
||||
professionalClassName: '', //专业类名称 |
||||
disciplineId: '', //专业学科 |
||||
disciplineName: '', //专业学科名称 |
||||
professionalId: '', //专业 |
||||
professionalName: '', //专业名称 |
||||
userId: this.userId |
||||
}, |
||||
email: '', |
||||
emailBtnText: '发送验证码', |
||||
emailCode: '', |
||||
emailDisabled: false, |
||||
emailTimer: null, |
||||
phone: '', |
||||
phoneBtnText: '发送验证码', |
||||
phoneCode: '', |
||||
phoneDisabled: false, |
||||
phoneTimer: null |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'userId','avatar','userName' |
||||
]), |
||||
}, |
||||
mounted() { |
||||
this.getdata(); |
||||
this.getProvince() |
||||
this.getSchoolData() |
||||
}, |
||||
methods: { |
||||
...mapActions('user', [ |
||||
'setAvatar','setUserName' |
||||
]), |
||||
tabChange(index){ |
||||
this.active = index |
||||
}, |
||||
getProvince(){ |
||||
this.$get(this.api.queryProvince).then(res => { |
||||
this.provinceList = res.data.list |
||||
}).catch(res => {}); |
||||
}, |
||||
// 获取城市 |
||||
getCity(id,type){ |
||||
this.personalInformation.cityId = 1 |
||||
this.getCityData() |
||||
}, |
||||
getCityData(index){ |
||||
let provinceId = this.personalInformation.provinceId |
||||
this.$get(this.api.queryCity,{provinceId}).then(res => { |
||||
this.cityList = res.data.list |
||||
}).catch(res => {}); |
||||
}, |
||||
// 获取学校名称 |
||||
getSchoolData(){ |
||||
let data = { |
||||
searchContent: '', |
||||
provinceId: '', |
||||
cityId: '' |
||||
} |
||||
this.$get(`${this.api.queryClient}/1/1000`,data).then(res => { |
||||
this.schoolList = res.data.list |
||||
}).catch(res => {}); |
||||
}, |
||||
accountChange(){ |
||||
this.$get(`${this.api.getAccount}?account=${this.form.account}`).then(res => { |
||||
if(res.data.userInfo){ |
||||
this.accountRepeat = true |
||||
util.warningMsg('该账号已存在') |
||||
}else{ |
||||
this.accountRepeat = false |
||||
} |
||||
}).catch(res => {}); |
||||
}, |
||||
getdata() { |
||||
this.$get(`${this.api.userinfo}?userId=${this.userId}`) |
||||
.then(res => { |
||||
this.personalInformation = res.data.userInfo |
||||
this.personalInformation.countries = '中国' |
||||
this.curPassword = this.personalInformation.password |
||||
this.$nextTick(() => { |
||||
if(this.personalInformation.provinceId){ |
||||
this.getCityData(1) |
||||
} |
||||
}) |
||||
}) |
||||
.catch(err => { |
||||
console.log(err); |
||||
}); |
||||
}, |
||||
save() { |
||||
if(this.personalInformation.idnumber && !/(^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)/.test(this.personalInformation.idnumber)) return util.warningMsg('请输入正确的证件号码') |
||||
if(this.accountRepeat) return util.warningMsg('该账号已存在') |
||||
if(this.personalInformation.phone && !/^1[3456789]\d{9}$/.test(this.personalInformation.phone)) return util.warningMsg('请输入正确的手机号') |
||||
if(this.personalInformation.email && !/^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/.test(this.personalInformation.email)) return util.warningMsg('请输入正确的邮箱') |
||||
let personalInformation = this.personalInformation |
||||
let userInfoEntity = { |
||||
idnumber: personalInformation.idnumber, |
||||
account: personalInformation.account, |
||||
cityId: personalInformation.cityId, |
||||
countries: personalInformation.countries, |
||||
dateBirth: personalInformation.dateBirth, |
||||
educationDegree: personalInformation.educationDegree, |
||||
email: personalInformation.email, |
||||
phone: personalInformation.phone, |
||||
provinceId: personalInformation.provinceId, |
||||
clientId: personalInformation.clientId, |
||||
clientName: personalInformation.clientName, |
||||
sex: personalInformation.sex, |
||||
userId: personalInformation.userId, |
||||
userName: personalInformation.userName, |
||||
} |
||||
let data = userInfoEntity |
||||
this.$post(this.api.userinfoUpdate,data).then(res => { |
||||
if(res.success){ |
||||
this.setUserName(personalInformation.userName) |
||||
util.successMsg('提交成功') |
||||
this.$router.back() |
||||
}else{ |
||||
util.errorMsg('提交失败') |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
|
||||
concatArch(isLoadData) { |
||||
this.archivesList = this.archivesList.concat({ |
||||
isNew: true, |
||||
personalCareerId: '', //职业 |
||||
schoolId: '', //院校 |
||||
schoolName: '', //院校名称 |
||||
subjectList: this.subjectList, //专业学科 |
||||
disciplineId: '', //专业学科 |
||||
disciplineName: '', //专业学科名称 |
||||
ProfessionalClassList: [], //专业类 |
||||
professionalClassId: '', //专业类 |
||||
professionalClassName: '', //专业类名称 |
||||
ProfessionalList: [], //专业 |
||||
professionalId: '', //专业 |
||||
professionalName: '', //专业名称 |
||||
userId: this.userId, |
||||
personalFileId: '' |
||||
}) |
||||
if(!isLoadData){ |
||||
this.$nextTick(() => { |
||||
document.body.scrollTop = document.querySelector('.content-box').scrollHeight |
||||
document.documentElement.scrollTop = document.querySelector('.content-box').scrollHeight |
||||
}) |
||||
} |
||||
}, |
||||
addArch() { |
||||
let isEmpty = false |
||||
this.archivesList.forEach((n,k) => { |
||||
if(!n.personalCareerId) isEmpty = true |
||||
}) |
||||
if(isEmpty) return this.$message.warning('请选择职业') |
||||
this.showArch = true |
||||
this.concatArch() |
||||
}, |
||||
bindEmail() { |
||||
this.email = this.personalInformation.email |
||||
this.emailVisible = true |
||||
}, |
||||
bindPhone() { |
||||
this.phone = this.personalInformation.phone |
||||
this.phoneVisible = true |
||||
}, |
||||
bindPassword() { |
||||
this.passwordVisible = true |
||||
}, |
||||
editPassword() { |
||||
if(!this.passwordForm.password) return this.$message.warning('请输入原密码') |
||||
if(!this.passwordForm.newPassword) return this.$message.warning('请输入新密码') |
||||
if(!this.passwordForm.reNewPassword) return this.$message.warning('请确认新密码') |
||||
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.$message.warning('请输入6位数以上的密码') |
||||
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.$message.warning('输入的新密码不一致,请重新确认') |
||||
if(this.passwordForm.password === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致') |
||||
|
||||
let data = this.passwordForm |
||||
data.userid = this.userId |
||||
this.$post(this.api.examinePassword,data) |
||||
.then(res => { |
||||
if(res.errmessage == 'success'){ |
||||
this.$message.success('更换成功') |
||||
this.passwordVisible = false |
||||
} |
||||
}) |
||||
.catch(err => { |
||||
console.log(err); |
||||
}); |
||||
}, |
||||
closePassword() { |
||||
this.passwordForm = { |
||||
password: '', |
||||
newPassword: '', |
||||
reNewPassword: '' |
||||
} |
||||
}, |
||||
foldArch() { |
||||
this.showArch = !this.showArch |
||||
this.$nextTick(() => { |
||||
document.body.scrollTop = document.querySelector('.content-box').scrollHeight |
||||
document.documentElement.scrollTop = document.querySelector('.content-box').scrollHeight |
||||
}) |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.block{ |
||||
padding: 34px; |
||||
margin-bottom: 20px; |
||||
background-color: #fff; |
||||
border-radius: 8px; |
||||
.title{ |
||||
padding-left: 11px; |
||||
margin-bottom: 20px; |
||||
font-size: 17px; |
||||
color: $main-color; |
||||
line-height: 1.8; |
||||
border-left: 6px solid; |
||||
} |
||||
.list{ |
||||
li{ |
||||
display: flex; |
||||
flex-direction: column; |
||||
margin-bottom: 30px; |
||||
&>label{ |
||||
margin-bottom: 5px; |
||||
font-size: 16px; |
||||
color: #4c4c4c; |
||||
} |
||||
.el-input{ |
||||
width: 300px; |
||||
.el-input__inner{ |
||||
border-color: #999; |
||||
} |
||||
} |
||||
.mul{ |
||||
display: inline-flex; |
||||
margin-top: 10px; |
||||
.child{ |
||||
display: inline-flex; |
||||
flex-direction: column; |
||||
margin-right: 20px; |
||||
&>span{ |
||||
margin-bottom: 5px; |
||||
font-size: 14px; |
||||
color: #575757; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,250 @@ |
||||
<template> |
||||
<div class="wrap"> |
||||
<div class="left"> |
||||
<div class="inner"> |
||||
<div class="date"> |
||||
<span class="name">使用期限:</span> |
||||
<div class="val"> |
||||
2021-05-01<br>至<br>2021-10-01 |
||||
</div> |
||||
</div> |
||||
<p class="surplus"><span class="name">剩余期限:</span><span class="num">300</span> 天</p> |
||||
</div> |
||||
</div> |
||||
<div class="right"> |
||||
<div class="block"> |
||||
<h6 class="title">平台数据统计</h6> |
||||
<ul class="stat"> |
||||
<li> |
||||
<p class="people"> |
||||
<span class="num">4</span>人 |
||||
</p> |
||||
<p class="text">本校累计用户数量</p> |
||||
</li> |
||||
<li> |
||||
<p class="people"> |
||||
<span class="num">2</span>人 |
||||
</p> |
||||
<p class="text">平均日访客量</p> |
||||
</li> |
||||
<li> |
||||
<p class="people"> |
||||
<span class="num">4</span> |
||||
</p> |
||||
<p class="text">累计下载</p> |
||||
</li> |
||||
<li> |
||||
<p class="people"> |
||||
<span class="num">4</span>人 |
||||
</p> |
||||
<p class="text">当前在线人数</p> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div class="block"> |
||||
<div class="flex m-b-20"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>查询时间区域:</label> |
||||
<el-date-picker v-model="date" align="right" unlink-panels type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" format="yyyy-MM-dd" value-format="yyyy-MM-dd" clearable size="small"></el-date-picker> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
<div class="flex j-between"> |
||||
<h6 class="title">按数据库统计使用概况</h6> |
||||
|
||||
<div> |
||||
<el-button type="primary" size="small" v-auth="'/system/list:员工管理:批量导入'">导出数据</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="listData" class="table" stripe header-align="center" row-key="id" @selection-change="handleSelectionChange"> |
||||
<el-table-column type="selection" width="80" align="center"></el-table-column> |
||||
<el-table-column type="index" width="100" label="序号" align="center"></el-table-column> |
||||
<el-table-column prop="practiseName" label="数据分类" align="center"></el-table-column> |
||||
<el-table-column prop="paperName" label="数据库类别" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="下载量" align="center"></el-table-column> |
||||
<el-table-column prop="peopleNum" label="点击量" align="center"></el-table-column> |
||||
</el-table> |
||||
</div> |
||||
|
||||
<div class="block"> |
||||
<div class="flex j-between"> |
||||
<h6 class="title">按月份统计数据库使用概况</h6> |
||||
|
||||
<div> |
||||
<el-button type="primary" size="small" v-auth="'/system/list:员工管理:批量导入'">导出数据</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="monthData" class="table" stripe header-align="center" row-key="id" :span-method="objectSpanMethod" @selection-change="handleSelectionChange1"> |
||||
<el-table-column type="selection" width="80" align="center"></el-table-column> |
||||
<el-table-column prop="year" label="年份" align="center"></el-table-column> |
||||
<el-table-column prop="type" label="类别" align="center"></el-table-column> |
||||
<el-table-column prop="month1" label="1月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="2月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="3月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="4月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="5月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="6月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="7月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="8月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="9月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="10月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="11月" align="center"></el-table-column> |
||||
<el-table-column prop="questionsNum" label="12月" align="center"></el-table-column> |
||||
</el-table> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
data() { |
||||
return { |
||||
date: [], |
||||
startTime: '', |
||||
endTime: '', |
||||
listData: [], |
||||
multipleSelection: [], |
||||
monthData: [ |
||||
{ |
||||
year: 2020, |
||||
type: '登录量', |
||||
month1: 1 |
||||
},{ |
||||
year: 2020, |
||||
type: '下载量', |
||||
month1: 1 |
||||
},{ |
||||
year: 2020, |
||||
type: '点击量', |
||||
month1: 1 |
||||
}, |
||||
], |
||||
multipleSelection1: [], |
||||
} |
||||
}, |
||||
watch: { |
||||
date: function(val){ |
||||
if(val){ |
||||
this.startTime = val[0] |
||||
this.endTime = val[1] |
||||
}else{ |
||||
this.startTime = '' |
||||
this.endTime = '' |
||||
} |
||||
this.getData() |
||||
} |
||||
}, |
||||
mounted() { |
||||
|
||||
}, |
||||
methods: { |
||||
getData(){ |
||||
|
||||
}, |
||||
objectSpanMethod({ row, column, rowIndex, columnIndex }) { |
||||
if (columnIndex === 0) { |
||||
if (rowIndex % 2 === 0) { |
||||
return { |
||||
rowspan: 3, |
||||
colspan: 1 |
||||
}; |
||||
} |
||||
} |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val |
||||
}, |
||||
handleSelectionChange1(val) { |
||||
this.multipleSelection1 = val |
||||
}, |
||||
} |
||||
}; |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.wrap{ |
||||
display: flex; |
||||
.left{ |
||||
margin-right: 20px; |
||||
.inner{ |
||||
width: 200px; |
||||
padding: 15px; |
||||
background-color: #fff; |
||||
border-radius: 8px; |
||||
.date{ |
||||
display: flex; |
||||
align-items: center; |
||||
.val{ |
||||
text-align: center; |
||||
line-height: 1.8; |
||||
font-size: 15px; |
||||
color: $main-color; |
||||
} |
||||
} |
||||
.surplus{ |
||||
margin-top: 15px; |
||||
.num{ |
||||
font-size: 24px; |
||||
color: $main-color; |
||||
font-weight: bold; |
||||
} |
||||
} |
||||
.name{ |
||||
font-size: 14px; |
||||
color: #404040; |
||||
} |
||||
} |
||||
} |
||||
.block{ |
||||
padding: 34px; |
||||
margin-bottom: 20px; |
||||
background-color: #fff; |
||||
border-radius: 8px; |
||||
.title{ |
||||
padding-left: 11px; |
||||
margin-bottom: 20px; |
||||
font-size: 17px; |
||||
color: $main-color; |
||||
line-height: 1.8; |
||||
border-left: 6px solid; |
||||
} |
||||
.stat{ |
||||
display: flex; |
||||
li{ |
||||
flex: 1; |
||||
height: 120px; |
||||
padding: 28px 0 18px; |
||||
margin-right: 27px; |
||||
text-align: center; |
||||
background: url(../../../assets/img/stat1.png) 0 0/100% 100% no-repeat; |
||||
&:nth-child(2){ |
||||
background-image: url(../../../assets/img/stat2.png); |
||||
} |
||||
&:nth-child(3){ |
||||
background-image: url(../../../assets/img/stat3.png); |
||||
} |
||||
&:last-child{ |
||||
margin-right: 0; |
||||
background-image: url(../../../assets/img/stat4.png); |
||||
} |
||||
.people{ |
||||
color: #fff; |
||||
font-size: 24px; |
||||
.num{ |
||||
font-size: 41px; |
||||
} |
||||
} |
||||
.text{ |
||||
color: #fff; |
||||
font-size: 15px; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,627 @@ |
||||
<template> |
||||
<div> |
||||
<div class="page"> |
||||
<div class="page-content"> |
||||
<div class="tool"> |
||||
<ul class="filter"> |
||||
<li> |
||||
<label>搜索:</label> |
||||
<el-input style="width: 250px" placeholder="请输入员工姓名/工号/角色名称" v-model="keyword" suffix-icon="el-icon-search" clearable size="small"></el-input> |
||||
</li> |
||||
</ul> |
||||
<div> |
||||
<el-button type="primary" size="small" round @click="addTeacher" v-auth="'/system/list:员工管理:新增员工'">新增员工</el-button> |
||||
<el-button type="primary" size="small" round @click="batchImport" v-auth="'/system/list:员工管理:批量导入'">批量导入</el-button> |
||||
<el-button type="primary" size="small" round @click="delAllSelection" v-auth="'/system/list:员工管理:批量删除'">批量删除</el-button> |
||||
</div> |
||||
</div> |
||||
|
||||
<el-table :data="listData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange"> |
||||
<el-table-column type="selection" width="80" align="center"></el-table-column> |
||||
<el-table-column type="index" label="序号" width="55" align="center"> |
||||
</el-table-column> |
||||
<el-table-column prop="account" label="账号" align="center"></el-table-column> |
||||
<el-table-column prop="userName" label="姓名" align="center"></el-table-column> |
||||
<el-table-column prop="workNumber" label="工号/学号" align="center"></el-table-column> |
||||
<el-table-column prop="roleName" label="账号角色" align="center"></el-table-column> |
||||
<el-table-column prop="loginNumber" label="登录次数" align="center"> |
||||
<template slot-scope="scope"> |
||||
{{scope.row.loginNumber ? scope.row.loginNumber : 0}} |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="lastLoginTime" label="上次登录时间" width="160" align="center"></el-table-column> |
||||
<el-table-column label="操作" align="center" width="200"> |
||||
<template slot-scope="scope"> |
||||
<el-button type="text" @click="showTeacher(scope.row)" v-auth="'/system/list:员工管理:查看'">查看</el-button> |
||||
<el-button type="text" @click="editTeacher(scope.row)" v-auth="'/system/list:员工管理:编辑'">编辑</el-button> |
||||
<el-button type="text" @click="resetPassword(scope.row)" v-auth="'/system/list:员工管理:重置密码'">重置密码</el-button> |
||||
<el-button type="text" @click="delTeacher(scope.row)" v-auth="'/system/list:员工管理:删除'">删除</el-button> |
||||
<el-switch v-model="scope.row.isDisable" :active-value="0" :inactive-value="1" style="margin: 0 10px 0 5px" :active-text="scope.row.isDisable ? '关' : '开'" @change="switchOff($event,scope.row,scope.$index)"></el-switch> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<div class="pagination"> |
||||
<el-pagination background layout="total,prev, pager, next" :current-page="page" @current-change="handleCurrentChange" :total="total"></el-pagination> |
||||
</div> |
||||
|
||||
<el-dialog :title="isDetail ? '查看员工' : (isAddteacher ? '新增员工' : '编辑员工')" :visible.sync="teacherVisible" width="500px" @close="closeTeacher" class="dialog" :close-on-click-modal="false"> |
||||
<el-form ref="teacherForm" :model="teacherForm" :rules="rules" label-width="110px" label-suffix=":" :disabled="isDetail"> |
||||
<el-form-item prop="userAccount" label="账号"> |
||||
<el-input v-model="teacherForm.userAccount" ref="account" placeholder="请输入职工账号" @change="accountChange"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="userName" label="用户姓名"> |
||||
<el-input v-model="teacherForm.userName" placeholder="请输入员工姓名"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="roleValue" label="账号角色"> |
||||
<el-select v-model="teacherForm.roleValue" placeholder="请选择账号角色" :disabled="!isAddteacher"> |
||||
<el-option v-for="(item,index) in roleList" :key="index" :label="item.roleName" :value="item.id"></el-option> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识"> |
||||
<el-input disabled v-model="teacherForm.uniqueIdentificationAccount" placeholder="请输入工号/学号获取唯一标识"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="phone" label="手机号"> |
||||
<el-input v-model="teacherForm.phone" placeholder="请输入手机号" maxlength="11"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="email" label="邮箱"> |
||||
<el-input v-model="teacherForm.email" placeholder="请输入邮箱"></el-input> |
||||
</el-form-item> |
||||
<el-form-item prop="workNumber" label="工号/学号"> |
||||
<el-input v-model="teacherForm.workNumber" placeholder="请输入职工工号" @change="workNumberChange"></el-input> |
||||
</el-form-item> |
||||
</el-form> |
||||
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
||||
<el-button size="small" @click="teacherVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="saveSure('teacherForm')">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
|
||||
<el-dialog title="批量导入" :visible.sync="importVisible" width="400px" @close="closeImport" :close-on-click-modal="false"> |
||||
<div class="upload-wrap" :class="{lg: uploadFaild}"> |
||||
<el-button class="download" size="small" @click="downLoad"><img src="../../../assets/img/download.png" alt=""> 模板下载</el-button> |
||||
<el-upload accept=".xls,.xlsx" :on-remove="handleRemove" :on-error="uploadError" :on-success="uploadSuccess" :before-remove="beforeRemove" :limit="1" :on-exceed="handleExceed" :action="this.api.uploadFileStaff" :file-list="uploadList" :data="{schoolId: this.clientId}" name="file"> |
||||
<el-button size="small"><img src="../../../assets/img/upload.png" alt=""> 上传文件</el-button> |
||||
</el-upload> |
||||
<div class="link" v-if="uploadFaild"> |
||||
<el-link type="primary" @click="showFaild">导入失败,查看原因</el-link> |
||||
</div> |
||||
</div> |
||||
<span slot="footer" class="dialog-footer"> |
||||
<el-button size="small" @click="importVisible = false">取 消</el-button> |
||||
<el-button size="small" type="primary" @click="uploadSure">确 定</el-button> |
||||
</span> |
||||
</el-dialog> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<script> |
||||
import Setting from '@/setting'; |
||||
import { mapState } from 'vuex'; |
||||
import util from '@/libs/util' |
||||
export default { |
||||
data() { |
||||
return { |
||||
pages: 10, |
||||
isDetail: false, |
||||
props: { multiple: true }, |
||||
orgList: [], |
||||
isAddteacher: false, |
||||
teacherVisible: false, |
||||
staffShowVisible: false, |
||||
roleList: [], |
||||
teacherForm: { |
||||
teacherId: '', |
||||
userName: '', |
||||
roleValue: '', |
||||
phone: '', |
||||
uniqueIdentificationAccount: '', |
||||
workNumber: '', |
||||
email: '', |
||||
major: '', |
||||
department: '', |
||||
userAccount: '', |
||||
major: '', |
||||
clientId: this.clientId, |
||||
clientName: this.clientName, |
||||
}, |
||||
rules: { |
||||
userAccount: [ |
||||
{ required: true, message: '请输入账号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[A-Za-z0-9]+$/, |
||||
message: '请输入正确的账号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
userName: [ |
||||
{ required: true, message: '请输入用户姓名', trigger: 'blur' } |
||||
], |
||||
roleValue: [ |
||||
{ required: true, message: '请选择账号角色', trigger: 'change' } |
||||
], |
||||
uniqueIdentificationAccount: [ |
||||
// { required: true, message: '请输入唯一标识', trigger: 'blur' }, |
||||
], |
||||
major: [ |
||||
{ required: true, message: '请选择一级部门', trigger: 'change' } |
||||
], |
||||
workNumber: [ |
||||
{ required: true, message: '请输入职工工号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^[A-Za-z0-9]+$/, |
||||
message: '请输入正确的职工工号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
department: [ |
||||
{ required: true, message: '请选择二级部门', trigger: 'change' } |
||||
], |
||||
phone: [ |
||||
// { required: true, message: '请输入职工手机号', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^1[3456789]\d{9}$/, |
||||
message: '请输入正确的手机号', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
email: [ |
||||
// { required: true, message: '请输入邮箱', trigger: 'blur' }, |
||||
{ |
||||
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/, |
||||
message: '请输入正确的邮箱', |
||||
trigger: 'blur' |
||||
} |
||||
], |
||||
// schoolId: [ |
||||
// { required: true, message: '请选择所在院校', trigger: 'change' } |
||||
// ], |
||||
}, |
||||
listData: [], |
||||
importVisible: false, |
||||
keyword: '', |
||||
page: 1, |
||||
pageSize: 10, |
||||
total: 0, |
||||
departmentList: [], |
||||
teacherDepartmentList: [], |
||||
staffstateProfessId: '', |
||||
staffGradeId: '', |
||||
multipleSelection: [], |
||||
uploadList: [], |
||||
provinceId: this.$store.state.provinceId, |
||||
cityId: this.$store.state.cityId, |
||||
userId: this.$store.state.userId, |
||||
oneDepartmentIds: '', |
||||
twoDepartmentIds: '', |
||||
ProfessionalClassList: [], |
||||
subjectList: [], |
||||
ProfessionalList: [], |
||||
NoAdd: '', |
||||
AccountNoAdd: '', |
||||
NumberNoAdd: '', |
||||
platformId: this.$store.state.platformId, |
||||
schoolList: [], |
||||
uploadFaild: false, |
||||
token: '', |
||||
accountRepeat: false, |
||||
workNumberRepeat: false, |
||||
originalAccount: '', |
||||
originalWorkNumber: '', |
||||
password: Setting.initialPassword |
||||
}; |
||||
}, |
||||
computed: { |
||||
...mapState('user', [ |
||||
'clientId','clientName' |
||||
]), |
||||
...mapState('layout', [ |
||||
'isIE' |
||||
]) |
||||
}, |
||||
watch: { |
||||
keyword: function(val) { |
||||
clearTimeout(this.searchTimer) |
||||
this.searchTimer = setTimeout(() => { |
||||
this.initData() |
||||
},500) |
||||
} |
||||
}, |
||||
mounted(){ |
||||
this.getOrg() |
||||
this.teacherForm.clientId = this.clientId |
||||
this.teacherForm.clientName = this.clientName |
||||
this.getData() |
||||
this.getRoles() |
||||
}, |
||||
methods: { |
||||
getOrg(){ |
||||
let data = { |
||||
schoolId: this.clientId |
||||
} |
||||
this.$get(this.api.queryStaffPro,data).then(res => { |
||||
let firList = res.data.StaffProfessionalArchitectureList |
||||
if(firList){ |
||||
firList.map(e => { |
||||
e.isParent = true |
||||
e.value = e.staffProfessionalArchitectureId |
||||
e.label = e.staffProfessionalArchitectureName |
||||
let data = { |
||||
staffProfessionalArchitectureId: e.staffProfessionalArchitectureId |
||||
} |
||||
this.$get(this.api.queryStaffGrade,data).then(res1 => { |
||||
res1.data.staffGradeList.map(e => { |
||||
e.value = e.staffGradeId |
||||
e.label = e.staffGradeName |
||||
}) |
||||
e.children = res1.data.staffGradeList |
||||
}).catch(res => {}) |
||||
}) |
||||
setTimeout(() => { |
||||
this.orgList = firList |
||||
},500) |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
getData(){ |
||||
let totalPage = Math.ceil((this.total - 1) / this.pageSize) |
||||
let currentPage = this.page > totalPage ? totalPage : this.page |
||||
this.page = currentPage < 1 ? 1 : currentPage |
||||
let data = { |
||||
staffProfessionalArchitectureIds: this.oneDepartmentIds, |
||||
staffGradeIds: this.twoDepartmentIds, |
||||
searchContent: this.keyword, |
||||
schoolId: this.clientId, |
||||
pageNum: this.page, |
||||
pageSize: this.pageSize |
||||
} |
||||
this.$get(`${this.api.queryStaff}/${this.page}/${this.pageSize}`,data).then(res => { |
||||
this.listData = res.data.staffList.list |
||||
this.total = res.data.staffList.totalCount |
||||
if(!this.listData.length && this.total){ |
||||
this.page-- |
||||
this.getData() |
||||
} |
||||
}).catch(res => {}) |
||||
}, |
||||
initData(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
orgChange(node){ |
||||
this.twoDepartmentIds = node.map(n => n[1]).toString() |
||||
this.initData() |
||||
}, |
||||
getRoles(){ |
||||
let data = { |
||||
clientId: this.clientId |
||||
} |
||||
this.$get(`${this.api.queryRoles}/1/100`,data).then(res => { |
||||
this.roleList = res.data.items |
||||
}).catch(res => {}) |
||||
}, |
||||
resetPassword(row){ |
||||
this.$confirm(`重置后的密码为:${Setting.initialPassword},确定重置?`, '提示', { |
||||
type: 'info', |
||||
customClass: 'normal' |
||||
}).then(() => { |
||||
let data = { |
||||
userId: row.userId, |
||||
password: Setting.initialPassword |
||||
} |
||||
this.$post(this.api.userinfoUpdate,data).then(res => { |
||||
if(res.success){ |
||||
util.successMsg('重置成功') |
||||
}else{ |
||||
util.errorMsg('重置失败') |
||||
} |
||||
}).catch(res => {}) |
||||
}).catch(() => {}) |
||||
}, |
||||
accountChange(){ |
||||
if(this.teacherForm.userAccount !== this.originalAccount){ |
||||
this.$get(`${this.api.getAccount}?account=${this.teacherForm.userAccount}`).then(res => { |
||||
if(res.data.userInfo){ |
||||
this.accountRepeat = true |
||||
util.warningMsg('该账号已存在') |
||||
}else{ |
||||
this.accountRepeat = false |
||||
} |
||||
}).catch(res => {}) |
||||
}else{ |
||||
this.accountRepeat = false |
||||
} |
||||
}, |
||||
workNumberChange(){ |
||||
if(this.teacherForm.workNumber !== this.originalWorkNumber){ |
||||
this.$get(`${this.api.getWorkNumber}?workNumber=${this.teacherForm.workNumber}`).then(res => { |
||||
if(res.data.staff){ |
||||
this.workNumberRepeat = true |
||||
util.warningMsg('该工号已存在') |
||||
}else{ |
||||
this.workNumberRepeat = false |
||||
} |
||||
}).catch(res => {}) |
||||
}else{ |
||||
this.workNumberRepeat = false |
||||
} |
||||
}, |
||||
closeTeacher(){ |
||||
this.$refs.teacherForm.resetFields() |
||||
this.teacherForm.clientId = this.clientId |
||||
this.teacherForm.clientName = this.clientName |
||||
this.teacherForm.department = '' |
||||
this.teacherForm.major = '' |
||||
this.teacherForm.workNumber = '' |
||||
this.teacherForm.userId = '' |
||||
this.teacherForm.staffId = '' |
||||
}, |
||||
addTeacher(){ |
||||
this.isDetail = false |
||||
this.teacherVisible = true |
||||
this.isAddteacher = true |
||||
this.teacherForm.teacherId = '' |
||||
}, |
||||
getStaffDetail(userId){ |
||||
this.$get(`${this.api.getStaff}/${userId}`).then(res => { |
||||
let user = res.data.userInfo; |
||||
let or = res.data.staff; |
||||
this.teacherForm.uniqueIdentificationAccount = user.uniqueIdentificationAccount |
||||
this.teacherForm.clientId = user.clientId |
||||
this.teacherForm.clientName = user.clientName |
||||
this.teacherForm.userName = user.userName |
||||
this.teacherForm.phone = user.phone |
||||
this.teacherForm.email = user.email |
||||
this.teacherForm.userAccount = user.account |
||||
this.originalAccount = user.account |
||||
this.teacherForm.userId = user.userId |
||||
this.teacherForm.schoolId = user.schoolId |
||||
this.teacherForm.roleValue = user.roleId |
||||
|
||||
this.teacherForm.major = or.staffProfessionalArchitectureId |
||||
this.teacherForm.department = or.staffGradeId |
||||
this.teacherForm.workNumber = or.workNumber |
||||
this.originalWorkNumber = or.workNumber |
||||
this.isManager = true |
||||
this.teacherForm.staffId = or.staffId |
||||
this.getDepartment() |
||||
}).catch(res => {}); |
||||
}, |
||||
editTeacher(row){ |
||||
this.isDetail = false |
||||
this.teacherVisible = true |
||||
this.isAddteacher = false |
||||
this.AccountNoAdd = false |
||||
this.teacherForm.teacherId = row.staffId |
||||
this.getStaffDetail(row.staffId) |
||||
}, |
||||
showTeacher(row){ |
||||
this.staffShowVisible = true |
||||
this.isDetail = true |
||||
this.isAddManage = false |
||||
this.AccountNoAdd = false |
||||
this.teacherForm.manageId = row.staffId |
||||
this.getStaffDetail(row.staffId) |
||||
}, |
||||
getDepartment(){ |
||||
let data = { |
||||
staffProfessionalArchitectureId: this.teacherForm.major |
||||
} |
||||
this.$get(this.api.queryStaffGrade,data).then(res => { |
||||
this.departmentList = res.data.staffGradeList |
||||
}).catch(res => {}); |
||||
}, |
||||
async saveSure(teacherForm){ |
||||
this.$refs[teacherForm].validate((valid) => { |
||||
if (valid) { |
||||
if(this.accountRepeat) return util.warningMsg('该账号已存在') |
||||
if(this.workNumberRepeat) return util.warningMsg('该工号已存在') |
||||
let isTeacher = false |
||||
let isManager = false |
||||
let data = { |
||||
userInfo: { |
||||
userId: this.teacherForm.userId, |
||||
userName: this.teacherForm.userName, |
||||
account: this.teacherForm.userAccount, |
||||
clientId: this.teacherForm.clientId, |
||||
clientName: this.teacherForm.clientName, |
||||
roleId: this.teacherForm.roleValue, |
||||
phone: this.teacherForm.phone, |
||||
email: this.teacherForm.email, |
||||
isPort: 2, |
||||
uniqueIdentificationAccount: this.teacherForm.uniqueIdentificationAccount ? this.teacherForm.uniqueIdentificationAccount : Date.parse(new Date()), |
||||
} |
||||
} |
||||
let oneDepartmentName = ''; |
||||
for(let i in this.orgList){ |
||||
if(this.orgList[i].staffProfessionalArchitectureId == this.teacherForm.major) { |
||||
oneDepartmentName = this.orgList[i].staffProfessionalArchitectureName |
||||
break; |
||||
} |
||||
} |
||||
let twoDepartmentName = this.departmentList.find((n) => { |
||||
return n.staffGradeId == this.teacherForm.department |
||||
}).staffGradeName; |
||||
data.staff = { |
||||
roleId: this.teacherForm.roleValue, |
||||
isPort: 2, |
||||
schoolId: this.teacherForm.clientId, |
||||
staffId: this.teacherForm.staffId, |
||||
userId: this.teacherForm.userId, |
||||
workNumber: this.teacherForm.workNumber, |
||||
staffProfessionalArchitectureId: this.teacherForm.major, |
||||
staffGradeId: this.teacherForm.department, |
||||
staffProfessionalArchitectureName: oneDepartmentName, |
||||
staffGradeName: twoDepartmentName, |
||||
}; |
||||
if(this.teacherForm.teacherId){ |
||||
this.$post(this.api.updateStaff,data).then(res => { |
||||
this.teacherVisible = false |
||||
util.successMsg('编辑成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}else{ |
||||
this.$post(this.api.addStaff,data).then(res => { |
||||
this.teacherVisible = false |
||||
util.successMsg('添加成功'); |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
} |
||||
}else{ |
||||
return false; |
||||
} |
||||
}) |
||||
}, |
||||
delTeacher(row){ |
||||
this.$confirm('此删除操作不可逆,是否确认删除选中项?', '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
staffIds: row.staffId |
||||
} |
||||
this.$del(this.api.deleteStaffs,data).then(res => { |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}) |
||||
.catch(() => {}); |
||||
}, |
||||
switchOff(val,row,index) { |
||||
let data = { |
||||
id: row.id, |
||||
isDisable: val |
||||
} |
||||
this.$post(this.api.updateClient,data).then((res) => { |
||||
val == 1 ? util.warningMsg('该院校系统使用权限已关闭') : util.successMsg('该院校系统使用权限已激活') |
||||
}).catch((res) => { |
||||
}) |
||||
}, |
||||
handleSelectionChange(val) { |
||||
this.multipleSelection = val; |
||||
}, |
||||
delAllSelection() { |
||||
if(this.multipleSelection.length != ''){ |
||||
let newArr = this.multipleSelection |
||||
let delList = newArr.map(item => { |
||||
return item.staffId |
||||
}) |
||||
// 批量删除 |
||||
this.$confirm(`此批量删除操作不可逆,是否确认删除${util.ellipsisStr(newArr[0].userName)}等${newArr.length}个选中项?`, '提示', { |
||||
type: 'warning' |
||||
}) |
||||
.then(() => { |
||||
let data = { |
||||
staffIds: delList.join(',') |
||||
} |
||||
this.$del(this.api.deleteStaffs,data).then(res => { |
||||
this.$refs.table.clearSelection() |
||||
util.successMsg('删除成功') |
||||
this.getData() |
||||
}).catch(res => {}); |
||||
}).catch(() => {}); |
||||
}else{ |
||||
util.errorMsg('请先选择数据 !') |
||||
} |
||||
}, |
||||
batchImport(){ |
||||
this.importVisible = true |
||||
this.uploadList = [] |
||||
this.uploadFaild = false |
||||
}, |
||||
searchTeacher(){ |
||||
this.page = 1 |
||||
this.getData() |
||||
}, |
||||
handleCurrentChange(val) { |
||||
this.page = val |
||||
this.$refs.table.clearSelection() |
||||
this.getData() |
||||
}, |
||||
downLoad(){ |
||||
location.href = this.api.downloadStaffTemp |
||||
}, |
||||
showFaild(){ |
||||
location.href = `${this.api.exportFailureStaff}?token=${this.token}` |
||||
}, |
||||
// 上传文件 |
||||
handleExceed(files, fileList) { |
||||
util.warningMsg( |
||||
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
||||
); |
||||
}, |
||||
uploadSuccess(res, file, fileList) { |
||||
this.uploadFaild = false |
||||
if(res.success){ |
||||
if(res.data.data.token){ |
||||
this.token = res.data.data.token |
||||
this.uploadFaild = true |
||||
}else{ |
||||
util.successMsg('上传成功') |
||||
} |
||||
}else{ |
||||
res.data.message ? util.errorMsg(res.data.message) : util.errorMsg('上传失败,请检查数据') |
||||
} |
||||
}, |
||||
uploadError(err, file, fileList) { |
||||
this.$message({ |
||||
message: "上传出错,请重试!", |
||||
type: "error", |
||||
center: true |
||||
}); |
||||
}, |
||||
beforeRemove(file, fileList) { |
||||
return this.$confirm(`确定移除 ${file.name}?`); |
||||
}, |
||||
handleRemove(file, fileList) { |
||||
this.uploadList = fileList |
||||
this.uploadFaild = false |
||||
}, |
||||
closeImport(){ |
||||
this.uploadList = [] |
||||
}, |
||||
uploadSure(){ |
||||
this.importVisible = false |
||||
this.page = 1 |
||||
this.keyword = '' |
||||
this.getData() |
||||
} |
||||
} |
||||
}; |
||||
</script> |
||||
<style lang="scss" scoped> |
||||
/deep/.dialog{ |
||||
.el-form-item{ |
||||
.el-form-item__label{ |
||||
font-size: 16px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
&:before{ |
||||
margin-right: 0; |
||||
color: #CC221C; |
||||
} |
||||
} |
||||
} |
||||
.el-input,.el-select{ |
||||
width: 100%; |
||||
} |
||||
} |
||||
.list{ |
||||
li{ |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
margin: 32px 0; |
||||
.name,.val{ |
||||
font-size: 16px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
} |
||||
.name{ |
||||
width: 45%; |
||||
text-align: right; |
||||
} |
||||
.val{ |
||||
width: 55%; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,25 @@ |
||||
/** |
||||
* @description 鉴权指令 |
||||
* 当传入的权限当前用户没有时,会移除该组件 |
||||
* 用例:<Tag v-auth">text</Tag> 或者:<Tag v-auth="'user:编辑'">text</Tag> |
||||
* */ |
||||
import store from '@/store'; |
||||
|
||||
export default { |
||||
inserted (el, binding, vnode) { |
||||
let btnText = '' |
||||
if(binding.value){ |
||||
btnText = binding.value |
||||
}else{ |
||||
btnText = `${vnode.context.$route.name}:${el.innerText}` |
||||
} |
||||
const btnPermissions = store.state.btnPermissions; |
||||
|
||||
if (btnText && btnPermissions && btnPermissions.length) { |
||||
const isPermission = btnPermissions.includes(btnText); |
||||
if (!isPermission) { |
||||
el.parentNode && el.parentNode.removeChild(el); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
/** |
||||
* @description 返回缺省值 |
||||
* 传入的如果是null,就返回'--' |
||||
* 用例:<Tag :default="val">text</Tag> 或者:<Tag>{{val | default}}</Tag> |
||||
* */ |
||||
const defaultShow = (val) => { |
||||
return val == null ? '--' : val |
||||
} |
||||
|
||||
module.exports = { |
||||
defaultShow |
||||
} |
@ -0,0 +1,14 @@ |
||||
/** |
||||
* 插件 |
||||
* */ |
||||
|
||||
import directiveAuth from '@/plugins/auth'; |
||||
import throttle from '@/plugins/throttle'; |
||||
|
||||
export default { |
||||
async install (Vue, options) { |
||||
// 指令
|
||||
Vue.directive('auth', directiveAuth); |
||||
Vue.directive('throttle', throttle); |
||||
} |
||||
} |
@ -0,0 +1,161 @@ |
||||
import axios from 'axios' |
||||
import util from '@/libs/util' |
||||
import router from '@/router/index' |
||||
import Setting from '@/setting' |
||||
|
||||
const service = axios.create({ |
||||
baseURL: Setting.apiBaseURL, |
||||
timeout: 50000 |
||||
}) |
||||
|
||||
// post请求头
|
||||
service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8'; |
||||
|
||||
// 请求拦截器
|
||||
// service.interceptors.request.use(config => {
|
||||
// if (sessionStorage.getItem('token')) {
|
||||
// // 存在将token写入 request header
|
||||
// config.headers.Authorization = `${sessionStorage.getItem('token')}`;
|
||||
// }
|
||||
// return config;
|
||||
// }, err => {
|
||||
// util.errorMsg({
|
||||
// message: '退出登陆',
|
||||
// onClose: function () {
|
||||
// router.push({name: 'login'});
|
||||
// }
|
||||
// })
|
||||
// return Promise.reject(err);
|
||||
// })
|
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use( |
||||
response => { |
||||
const res = response.data |
||||
if (res.success) { |
||||
return Promise.resolve(res).catch(e => {}) |
||||
} else { |
||||
switch (res.code) { |
||||
case 201: |
||||
util.errorMsg(res.message ? res.message : '数据请求异常') |
||||
break; |
||||
default: |
||||
Promise.reject(res).catch(e => {}) |
||||
} |
||||
return Promise.reject(res).catch(e => {}) |
||||
} |
||||
}, |
||||
// 服务器状态码不是200的情况
|
||||
error => { |
||||
if (error.res.status) { |
||||
switch (error.res.status) { |
||||
// 401: 未登录
|
||||
// 未登录则跳转登录页面,并携带当前页面的路径
|
||||
// 在登录成功后返回当前页面,这一步需要在登录页操作。
|
||||
case 500: |
||||
router.replace({ |
||||
path: '/login', |
||||
// query: { redirect: router.currentRoute.fullPath }
|
||||
}); |
||||
break; |
||||
// 403 token过期
|
||||
// 登录过期对用户进行提示
|
||||
// 清除本地token和清空vuex中token对象
|
||||
// 跳转登录页面
|
||||
case 403: |
||||
// Toast({
|
||||
// message: '登录过期,请重新登录',
|
||||
// duration: 1000,
|
||||
// forbidClick: true
|
||||
// });
|
||||
// 清除token
|
||||
// store.commit('loginSuccess', null);
|
||||
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
|
||||
setTimeout(() => { |
||||
router.replace({ |
||||
path: '/login', |
||||
query: { |
||||
redirect: router.currentRoute.fullPath |
||||
} |
||||
}); |
||||
}, 1000); |
||||
break; |
||||
// 404请求不存在
|
||||
case 404: |
||||
router.replace({ |
||||
path: '/404', |
||||
}); |
||||
break; |
||||
// 其他错误,直接抛出错误提示
|
||||
default: |
||||
Promise.reject(res) |
||||
} |
||||
return Promise.reject(error.res); |
||||
} |
||||
} |
||||
); |
||||
|
||||
function get(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.get(url, {params: params}) |
||||
.then(res => { |
||||
if(res){ |
||||
resolve(res) |
||||
}else{ |
||||
reject() |
||||
} |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
function post(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.post(url,params) |
||||
.then(res => { |
||||
if(res){ |
||||
resolve(res) |
||||
}else{ |
||||
reject() |
||||
} |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
function del(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.delete(url, { |
||||
params |
||||
}) |
||||
.then(res => { |
||||
if(res){ |
||||
resolve(res) |
||||
}else{ |
||||
reject() |
||||
} |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
|
||||
function put(url, params){ |
||||
return new Promise((resolve, reject) =>{ |
||||
service.put(url, { |
||||
params |
||||
}) |
||||
.then(res => { |
||||
if(res){ |
||||
resolve(res) |
||||
}else{ |
||||
reject() |
||||
} |
||||
}).catch(err => { |
||||
reject(err.data) |
||||
}) |
||||
}) |
||||
} |
||||
export { get,post,del,put } |
@ -0,0 +1,18 @@ |
||||
/** |
||||
* @description 节流指令 |
||||
* 限制连续快速点击按钮 |
||||
* 用例:<Tag v-throttle>text</Tag> |
||||
* */ |
||||
|
||||
export default{ |
||||
inserted (el, binding, vnode) { |
||||
el.addEventListener('click', () => { |
||||
if (!el.disabled) { |
||||
el.disabled = true |
||||
setTimeout(() => { |
||||
el.disabled = false |
||||
}, binding.value || 1000) |
||||
} |
||||
}) |
||||
} |
||||
} |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'data-'; |
||||
|
||||
export default { |
||||
path: '/data', |
||||
name: 'data', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/data/list'), |
||||
meta: { title: '数据' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'index-'; |
||||
|
||||
export default { |
||||
path: '/index', |
||||
name: 'index', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/index/list'), |
||||
meta: { title: '首页' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'role-'; |
||||
|
||||
export default { |
||||
path: '/role', |
||||
name: 'role', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/role/list'), |
||||
meta: { title: '角色管理' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'setting-'; |
||||
|
||||
export default { |
||||
path: '/setting', |
||||
name: 'setting', |
||||
redirect: { |
||||
name: `${pre}person` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}person`, |
||||
path: `person`, |
||||
component: () => import('@/pages/setting/person'), |
||||
meta: { title: '个人中心' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'stat-'; |
||||
|
||||
export default { |
||||
path: '/stat', |
||||
name: 'stat', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/stat/list'), |
||||
meta: { title: '数据统计' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,23 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'user-'; |
||||
|
||||
export default { |
||||
path: '/user', |
||||
name: 'user', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/user/list'), |
||||
meta: { title: '用户管理' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,28 @@ |
||||
import BasicLayout from '@/layouts/home'; |
||||
|
||||
const meta = {}; |
||||
|
||||
const pre = 'wrongBook-'; |
||||
|
||||
export default { |
||||
path: '/wrongBook', |
||||
name: 'wrongBook', |
||||
redirect: { |
||||
name: `${pre}list` |
||||
}, |
||||
meta, |
||||
component: BasicLayout, |
||||
children: [ |
||||
{ |
||||
name: `${pre}list`, |
||||
path: `list`, |
||||
component: () => import('@/pages/wrongBook/list'), |
||||
meta: { title: '我的错题本' } |
||||
},{ |
||||
name: `${pre}do`, |
||||
path: `do`, |
||||
component: () => import('@/pages/wrongBook/do'), |
||||
meta: { title: '错题练习' } |
||||
}, |
||||
] |
||||
}; |
@ -0,0 +1,15 @@ |
||||
import router from './index' |
||||
import Setting from '@/setting' |
||||
import util from '@/libs/util' |
||||
|
||||
router.beforeEach((to, from, next) => { |
||||
document.title = Setting.titleSuffix; |
||||
const role = util.session.get(Setting.usernameKey); |
||||
if (!role && to.path !== '/login') { |
||||
next('/login') |
||||
} else if(role && to.path == '/login') { |
||||
next('/index') |
||||
} else { |
||||
next() |
||||
} |
||||
}); |
@ -0,0 +1,76 @@ |
||||
import index from './modules/index' |
||||
import data from './modules/data' |
||||
import stat from './modules/stat' |
||||
import user from './modules/user' |
||||
import role from './modules/role' |
||||
import setting from './modules/setting' |
||||
|
||||
import BasicLayout from '@/layouts/home' |
||||
|
||||
const frameIn = [ |
||||
{ |
||||
path: '/', |
||||
redirect: '/login', |
||||
}, |
||||
{ |
||||
path: '/', |
||||
component: () => BasicLayout, |
||||
meta: { title: '首页' }, |
||||
children: [] |
||||
}, |
||||
index, |
||||
data, |
||||
stat, |
||||
user, |
||||
role, |
||||
setting |
||||
] |
||||
|
||||
/** |
||||
* 在主框架之外显示 |
||||
*/ |
||||
|
||||
const frameOut = [ |
||||
// 登录
|
||||
{ |
||||
path: '/login', |
||||
name: 'login', |
||||
meta: { |
||||
title: '登录' |
||||
}, |
||||
component: () => import('@/pages/account/login') |
||||
} |
||||
]; |
||||
|
||||
/** |
||||
* 错误页面 |
||||
*/ |
||||
|
||||
const errorPage = [ |
||||
{ |
||||
path: '/403', |
||||
name: '403', |
||||
meta: { |
||||
title: '403' |
||||
}, |
||||
component: () => import('@/pages/exception/error/403') |
||||
}, |
||||
{ |
||||
path: '*', |
||||
name: '404', |
||||
meta: { |
||||
title: '404' |
||||
}, |
||||
component: () => import('@/pages/exception/error/404') |
||||
} |
||||
]; |
||||
|
||||
// 导出需要显示菜单的
|
||||
export const frameInRoutes = frameIn; |
||||
|
||||
// 重新组织后导出
|
||||
export default [ |
||||
...frameIn, |
||||
...frameOut, |
||||
...errorPage |
||||
]; |
@ -0,0 +1,21 @@ |
||||
/** |
||||
* 开发配置 |
||||
* */ |
||||
|
||||
const env = process.env.NODE_ENV; |
||||
|
||||
const Setting = { |
||||
// 是否使用 Mock 的数据,默认 开发环境为 true,生产环境为 false
|
||||
isMock: true, |
||||
// 部署应用包时的基本 URL
|
||||
publicPath: env === 'development' ? './' : '', |
||||
// 生产环境构建文件的目录名
|
||||
outputDir: 'dist', |
||||
// 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
|
||||
assetsDir: 'static', |
||||
// 开发环境每次保存时 lint 代码,会将 lint 错误输出为编译警告
|
||||
// true || false || error
|
||||
lintOnSave: true, |
||||
}; |
||||
|
||||
module.exports = Setting; |
@ -0,0 +1,68 @@ |
||||
/** |
||||
* 业务配置 |
||||
* */ |
||||
|
||||
const env = process.env.NODE_ENV; |
||||
|
||||
const Setting = { |
||||
/** |
||||
* 基础配置 |
||||
* */ |
||||
// 网页标题的后缀
|
||||
titleSuffix: '或然数据平台', |
||||
// 路由模式,可选值为 history 或 hash
|
||||
routerMode: 'hash', |
||||
// 页面切换时,是否显示模拟的进度条
|
||||
showProgressBar: true, |
||||
// 接口请求地址
|
||||
// apiBaseURL: env === 'development' ? 'http://192.168.31.151:8001' : 'http://39.108.250.202:8000',
|
||||
apiBaseURL: env === 'development' ? 'http://39.108.250.202:9000' : 'http://39.108.250.202:9000', |
||||
// 接口请求返回错误时,弹窗的持续时间,单位:秒
|
||||
modalDuration: 3, |
||||
// 接口请求返回错误时,弹窗的类型,可选值为 Message 或 Notice
|
||||
errorModalType: 'Message', |
||||
// Cookies 默认保存时间,单位:天
|
||||
cookiesExpires: 1, |
||||
/** |
||||
* sessionStorage里state的key |
||||
*/ |
||||
storeKey: 'data_store', |
||||
/** |
||||
* sessionStorage里username的key |
||||
*/ |
||||
usernameKey: 'data_username', |
||||
/** |
||||
* 默认密码 |
||||
*/ |
||||
initialPassword: '111aaa', |
||||
/** |
||||
* 多语言配置 |
||||
* */ |
||||
i18n: { |
||||
// 默认语言
|
||||
default: 'zh', |
||||
// 是否根据用户电脑配置自动设置语言(仅第一次有效)
|
||||
auto: false |
||||
}, |
||||
/** |
||||
* 布局配置 |
||||
* */ |
||||
layout: { |
||||
// 需要隐藏顶栏的页面路径
|
||||
hideNavList: ['practice-do','practice-randomDo','setting-person','achievement-assessment','achievement-practice','exam-do','exam-detail','wrongBook-do'], |
||||
}, |
||||
/** |
||||
* 功能配置 |
||||
* */ |
||||
// 相同路由,不同参数间进行切换,是否强力更新
|
||||
sameRouteForceUpdate: false, |
||||
// 是否使用动态路由
|
||||
dynamicRoute: false, |
||||
// 文件上传
|
||||
upload: { |
||||
apiURL: 'http://8.134.8.197:8001', |
||||
maxSize: 30, |
||||
}, |
||||
}; |
||||
|
||||
export default Setting; |
@ -0,0 +1,10 @@ |
||||
const getters = { |
||||
userId: state => state.user.info.userId, |
||||
roleId: state => state.user.info.roleId, |
||||
userName: state => state.user.info.userName, |
||||
account: state => state.user.info.account, |
||||
phone: state => state.user.info.phone, |
||||
clientId: state => state.user.info.clientId, |
||||
clientName: state => state.user.info.clientName, |
||||
} |
||||
export default getters |
@ -0,0 +1,25 @@ |
||||
import Vue from 'vue'; |
||||
import Vuex from 'vuex'; |
||||
import getters from './getters' |
||||
|
||||
Vue.use(Vuex); |
||||
|
||||
// https://webpack.js.org/guides/dependency-management/#requirecontext
|
||||
const modulesFiles = require.context('./modules', true, /\.js$/) |
||||
|
||||
// you do not need `import app from './modules/app'`
|
||||
// it will auto require all vuex module from modules file
|
||||
const modules = modulesFiles.keys().reduce((modules, modulePath) => { |
||||
// set './app.js' => 'app'
|
||||
const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1') |
||||
const value = modulesFiles(modulePath) |
||||
modules[moduleName] = value.default |
||||
return modules |
||||
}, {}) |
||||
|
||||
const store = new Vuex.Store({ |
||||
modules, |
||||
getters |
||||
}) |
||||
|
||||
export default store |
@ -0,0 +1,32 @@ |
||||
/** |
||||
* 成绩管理 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
id: '', |
||||
assessmentId: '', |
||||
assessmentName: '', |
||||
classId: '', |
||||
score: 0, |
||||
timeSpent: 0 |
||||
}, |
||||
getters: { |
||||
|
||||
}, |
||||
mutations: { |
||||
SET_INFO: (state, info) => { |
||||
state.id = info.id |
||||
state.assessmentId = info.assessmentId |
||||
state.assessmentName = info.assessmentName |
||||
state.classId = info.classId |
||||
state.score = info.score |
||||
state.timeSpent = info.timeSpent |
||||
}, |
||||
}, |
||||
actions: { |
||||
setInfo({ commit },info) { |
||||
commit('SET_INFO',info) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,19 @@ |
||||
/** |
||||
* 客户管理 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
provinceList: [] |
||||
}, |
||||
mutations: { |
||||
SET_PROVINCE: (state, provinceList) => { |
||||
state.provinceList = provinceList |
||||
}, |
||||
}, |
||||
actions: { |
||||
setProvince({ commit, state, dispatch },provinceList) { |
||||
commit('SET_PROVINCE',provinceList) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
/** |
||||
* 通用 |
||||
* */ |
||||
|
||||
const roleList = { |
||||
'1': '超级管理员', |
||||
'2': '管理员', |
||||
'3': '老师', |
||||
'4': '学生' |
||||
} |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
|
||||
}, |
||||
mutations: { |
||||
|
||||
}, |
||||
actions: { |
||||
getRole (id) { |
||||
return roleList[id] || '未知状态' |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,97 @@ |
||||
/** |
||||
* 试卷管理 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
typeList: [ |
||||
{ |
||||
id: 1, |
||||
name: '期中考试' |
||||
},{ |
||||
id: 2, |
||||
name: '期末考试' |
||||
},{ |
||||
id: 3, |
||||
name: '模拟考' |
||||
} |
||||
], |
||||
stateList: [ |
||||
{ |
||||
id: 0, |
||||
name: '待开始' |
||||
},{ |
||||
id: 1, |
||||
name: '进行中' |
||||
},{ |
||||
id: 2, |
||||
name: '已提交' |
||||
} |
||||
], |
||||
assessmentStateList: [ |
||||
{ |
||||
id: 1, |
||||
name: '待开始' |
||||
},{ |
||||
id: 2, |
||||
name: '进行中' |
||||
},{ |
||||
id: 3, |
||||
name: '已结束' |
||||
}
|
||||
], |
||||
degreeList: [ |
||||
{ |
||||
id: 0, |
||||
label: '简单' |
||||
},{ |
||||
id: 1, |
||||
label: '一般' |
||||
},{ |
||||
id: 2, |
||||
label: '较难' |
||||
},{ |
||||
id: 3, |
||||
label: '很难' |
||||
}, |
||||
], |
||||
assessmentName: '', |
||||
testPaperId: '', |
||||
assessmentId: '', |
||||
teacherId: '', |
||||
classId: '', |
||||
paperName: '', |
||||
countdown: '', |
||||
assessmentName: '' |
||||
}, |
||||
getters: { |
||||
getDegreeName: state => id => { |
||||
return id != null ? state.degreeList.find(n => n.id == id).label : '' |
||||
}, |
||||
getTypeName: state => id => { |
||||
return id != null ? state.typeList.find(n => n.id == id).name : '' |
||||
}, |
||||
getStateName: state => id => { |
||||
return id != null ? state.stateList.find(n => n.id == id).name : '' |
||||
}, |
||||
getAssessmentStateName: state => id => { |
||||
return id != null ? state.assessmentStateList.find(n => n.id == id).name : '' |
||||
}, |
||||
}, |
||||
mutations: { |
||||
SET_INFO: (state, info) => { |
||||
state.assessmentName = info.assessmentName |
||||
state.assessmentId = info.assessmentId |
||||
state.teacherId = info.teacherId |
||||
state.classId = info.classId |
||||
state.testPaperId = info.testPaperId |
||||
state.countdown = info.countdown |
||||
state.assessmentName = info.assessmentName |
||||
}, |
||||
}, |
||||
actions: { |
||||
setInfo({ commit },info) { |
||||
commit('SET_INFO',info) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
/** |
||||
* 布局管理 |
||||
* */ |
||||
|
||||
// 是否IE
|
||||
function isIE() { |
||||
if (!!window.ActiveXObject || "ActiveXObject" in window) return true |
||||
return false |
||||
} |
||||
|
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
isIE: isIE() |
||||
}, |
||||
mutations: { |
||||
SET_IE: (state, val) => { |
||||
state.isIE = val |
||||
}, |
||||
}, |
||||
actions: { |
||||
|
||||
} |
||||
} |
@ -0,0 +1,47 @@ |
||||
/** |
||||
* 试卷管理 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
degreeList: [ |
||||
{ |
||||
id: 0, |
||||
label: '简单' |
||||
},{ |
||||
id: 1, |
||||
label: '一般' |
||||
},{ |
||||
id: 2, |
||||
label: '较难' |
||||
},{ |
||||
id: 3, |
||||
label: '很难' |
||||
}, |
||||
], |
||||
practiseId: '', |
||||
paperId: '', |
||||
practiseName: '', |
||||
isContinue: '', |
||||
identification: '', |
||||
}, |
||||
getters: { |
||||
getDegreeName: state => id => { |
||||
return id != null ? state.degreeList.find(n => n.id == id).label : '' |
||||
} |
||||
}, |
||||
mutations: { |
||||
SET_INFO: (state, info) => { |
||||
state.practiseId = info.practiseId |
||||
state.paperId = info.paperId |
||||
state.practiseName = info.practiseName |
||||
state.isContinue = info.isContinue |
||||
state.identification = info.identification |
||||
}, |
||||
}, |
||||
actions: { |
||||
setInfo({ commit },info) { |
||||
commit('SET_INFO',info) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,108 @@ |
||||
import addRoutes from '@/libs/route/addRoutes'; |
||||
import Setting from '@/setting'; |
||||
import util from '@/libs/util'; |
||||
import { Message } from 'element-ui'; |
||||
import {post,get,del,put} from '@/plugins/requests/index.js' |
||||
import api from '@/api'; |
||||
|
||||
/** |
||||
* 用户信息 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
avatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', |
||||
token: '', |
||||
userId: '', |
||||
roleId: '', |
||||
userName: '', |
||||
account: '', |
||||
phone: '', |
||||
clientId: '', |
||||
clientName: '', |
||||
}, |
||||
mutations: { |
||||
SET_INFO: (state, info) => { |
||||
info.avatar && (state.avatar = info.avatar) |
||||
state.userId = info.userId |
||||
state.roleId = info.roleId |
||||
state.userName = info.userName |
||||
state.account = info.account |
||||
state.phone = info.phone |
||||
state.clientId = info.clientId |
||||
state.clientName = info.clientName |
||||
}, |
||||
SET_TOKEN: (state, token) => { |
||||
state.token = token |
||||
}, |
||||
SET_AVATAR: (state, avatar) => { |
||||
state.avatar = avatar |
||||
}, |
||||
SET_USERNAME: (state, userName) => { |
||||
state.userName = userName |
||||
}, |
||||
SET_ROLEID: (state, roleId) => { |
||||
state.roleId = roleId |
||||
}, |
||||
SET_CLIENTID: (state, clientId) => { |
||||
state.clientId = clientId |
||||
}, |
||||
SET_CLIENTNAME: (state, clientName) => { |
||||
state.clientName = clientName |
||||
} |
||||
}, |
||||
actions: { |
||||
login({ state,commit }, userInfo) { |
||||
const { username, password } = userInfo |
||||
return new Promise((resolve, reject) => { |
||||
get(api.logins,{ account: username.trim(), password: password }).then(res => { |
||||
if(res.success){ |
||||
let user = res.data.userInfo |
||||
if(user.roleId == 4){ |
||||
let routes = res.data.permissions[0].children |
||||
commit('SET_INFO',{ |
||||
avatar: user.userAvatars, |
||||
userId: user.userId, |
||||
roleId: user.roleId, |
||||
userName: user.userName, |
||||
account: user.account, |
||||
phone: user.phone, |
||||
clientId: user.clientId, |
||||
clientName: user.clientName, |
||||
}) |
||||
Setting.dynamicRoute && addRoutes(routes) |
||||
util.session.set(Setting.usernameKey, user.userName) |
||||
util.successMsg('登录成功'); |
||||
resolve() |
||||
}else{ |
||||
util.errorMsg('该用户没有权限') |
||||
} |
||||
}else{ |
||||
util.errorMsg(res.message) |
||||
} |
||||
}).catch(error => { |
||||
reject(error) |
||||
}) |
||||
}) |
||||
}, |
||||
logout({ commit, state, dispatch }) { |
||||
return new Promise((resolve, reject) => { |
||||
util.session.remove(Setting.usernameKey); |
||||
util.session.remove(Setting.storeKey); |
||||
location.reload() |
||||
resolve() |
||||
}) |
||||
}, |
||||
setAvatar({ state,commit },avatar) { |
||||
commit('SET_AVATAR',avatar) |
||||
let data = { |
||||
userId: state.userId, |
||||
userAvatars: avatar |
||||
} |
||||
post(api.userinfoUpdate,data).then(res => {}).catch(res => {}) |
||||
}, |
||||
setUserName({ state,commit },userName) { |
||||
commit('SET_USERNAME',userName) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
/** |
||||
* 我的错题本 |
||||
* */ |
||||
export default { |
||||
namespaced: true, |
||||
state: { |
||||
qid: '', |
||||
type: 1 |
||||
}, |
||||
getters: { |
||||
|
||||
}, |
||||
mutations: { |
||||
SET_INFO: (state, info) => { |
||||
state.qid = info.qid |
||||
state.type = info.type |
||||
}, |
||||
}, |
||||
actions: { |
||||
setInfo({ commit },info) { |
||||
commit('SET_INFO',info) |
||||
}, |
||||
} |
||||
} |
@ -0,0 +1,373 @@ |
||||
@import "./default/index.scss"; |
||||
|
||||
@font-face{ |
||||
font-family: youshe; |
||||
src: url('font/YouSheBiaoTiHei.ttf'); |
||||
} |
||||
|
||||
[v-cloak] { |
||||
display: none; |
||||
} |
||||
|
||||
::-webkit-scrollbar { |
||||
width: 8px; |
||||
height: 8px; |
||||
} |
||||
::-webkit-scrollbar-thumb { |
||||
width: 5px; |
||||
border-radius: 6px; |
||||
background: rgba(86,141,242,.7); |
||||
} |
||||
|
||||
.required{ |
||||
font-size: 16px; |
||||
color: $--color-primary; |
||||
font-style: normal; |
||||
} |
||||
|
||||
.breadcrumb{ |
||||
display: flex; |
||||
align-items: center; |
||||
margin-bottom: 20px; |
||||
.cur,.el-breadcrumb__inner,.el-breadcrumb__separator{ |
||||
color: rgba(0,0,0,.45) !important; |
||||
font-weight: 400 !important; |
||||
font-size: 12px; |
||||
} |
||||
.el-breadcrumb__item:last-of-type .el-breadcrumb__inner{ |
||||
color: rgba(0,0,0,.85) !important; |
||||
} |
||||
} |
||||
|
||||
.el-button--primary.action-btn{ |
||||
color: $--color-primary !important; |
||||
font-size: 14px !important; |
||||
background-color: #fff !important; |
||||
border-radius: 4px !important; |
||||
} |
||||
|
||||
.el-input{ |
||||
.el-input__inner{ |
||||
border-color: rgba(0, 0, 0, 0.15); |
||||
} |
||||
} |
||||
|
||||
.filter{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
flex: 1; |
||||
li{ |
||||
display: inline-flex; |
||||
align-items: center; |
||||
margin-right: 30px; |
||||
label{ |
||||
font-size: 14px; |
||||
line-height: 14px; |
||||
color: rgba(0,0,0,.65); |
||||
white-space: nowrap; |
||||
} |
||||
} |
||||
} |
||||
.page{ |
||||
position: relative; |
||||
background-color: #fff; |
||||
border-radius: 8px; |
||||
.p-title{ |
||||
padding-left: 24px; |
||||
line-height: 56px; |
||||
font-size: 16px; |
||||
color: rgba(0, 0, 0, 0.85); |
||||
border-bottom: 1px solid rgba(0,0,0,.06); |
||||
} |
||||
.page-content{ |
||||
padding: 24px; |
||||
.tool{ |
||||
display: flex; |
||||
justify-content: space-between; |
||||
margin-bottom: 24px; |
||||
|
||||
.single-choice{ |
||||
dl { |
||||
display: flex; |
||||
line-height: 30px; |
||||
dt { |
||||
color: rgba(0,0,0,.65); |
||||
font-size: 14px; |
||||
white-space: nowrap; |
||||
} |
||||
dd { |
||||
display: inline-flex; |
||||
align-items: center; |
||||
flex-wrap: wrap; |
||||
span { |
||||
padding: 0 10px; |
||||
margin: 0 10px; |
||||
color: #333; |
||||
font-size: 14px; |
||||
line-height: 1.8; |
||||
white-space: nowrap; |
||||
|
||||
cursor: pointer; |
||||
&:hover { |
||||
color: $--color-primary; |
||||
} |
||||
&.active { |
||||
border-radius: 4px; |
||||
color: #fff; |
||||
background-color: $--color-primary; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
.el-button--primary{ |
||||
@extend .action-btn; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.pagination { |
||||
margin: 20px 0; |
||||
text-align: center; |
||||
button,.number{ |
||||
color: rgba(0,0,0,.65) !important; |
||||
background-color: transparent !important; |
||||
border: 1px solid rgba(0, 0, 0, 0.15) !important; |
||||
border-radius: 4px !important; |
||||
} |
||||
button i{ |
||||
color: #333; |
||||
} |
||||
.active{ |
||||
color: #fff !important; |
||||
background-color: $--color-primary !important; |
||||
} |
||||
} |
||||
|
||||
.el-table{ |
||||
border-radius: 8px; |
||||
border: 1px solid rgba(0, 0, 0, 0.06); |
||||
border-bottom: 0; |
||||
.cell{ |
||||
font-size: 14px; |
||||
.el-checkbox{ |
||||
&:before{ |
||||
content: '全选'; |
||||
margin-right: 5px; |
||||
color: #fff; |
||||
font-size: 14px; |
||||
opacity: 0; |
||||
} |
||||
} |
||||
} |
||||
th{ |
||||
background: $--color-primary !important; |
||||
.cell{ |
||||
color: #fff; |
||||
font-size: 14px; |
||||
font-weight: normal; |
||||
.el-checkbox{ |
||||
&:before{ |
||||
opacity: 1; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-checkbox__inner{ |
||||
border-radius: 4px; |
||||
transition: none !important; |
||||
} |
||||
.el-checkbox__input.is-indeterminate .el-checkbox__inner{ |
||||
background-color: #FFFFFF; |
||||
border-color: #DCDFE6; |
||||
} |
||||
.el-switch__core{ |
||||
background-color: #bfbfbf; |
||||
} |
||||
.el-switch__label--right{ |
||||
z-index: 2; |
||||
position: absolute; |
||||
right: 8px; |
||||
margin-left: 0; |
||||
color: #fff !important; |
||||
} |
||||
.el-switch__label--right.is-active{ |
||||
left: 8px; |
||||
right: auto; |
||||
} |
||||
.el-switch__label--right span{ |
||||
font-size: 12px; |
||||
} |
||||
} |
||||
|
||||
.tabs{ |
||||
display: flex; |
||||
align-items: center; |
||||
padding: 0 24px; |
||||
border-bottom: 1px solid rgba(0,0,0,.06); |
||||
.item{ |
||||
position: relative; |
||||
padding: 20px 0; |
||||
margin-right: 40px; |
||||
font-size: 16px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
cursor: pointer; |
||||
&:after{ |
||||
content: ''; |
||||
position: absolute; |
||||
bottom: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
height: 3px; |
||||
border-bottom: 3px solid transparent; |
||||
border-radius: 2px; |
||||
} |
||||
&.active{ |
||||
font-weight: 500; |
||||
color: rgba(0, 0, 0, 0.85); |
||||
} |
||||
&.active:after{ |
||||
border-bottom-color: $--color-primary; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-message{ |
||||
padding: 11px 20px; |
||||
.el-message__icon{ |
||||
font-size: 16px; |
||||
} |
||||
.el-message__content{ |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
} |
||||
.el-icon-close{ |
||||
font-size: 14px; |
||||
color: #92998d; |
||||
} |
||||
.el-message--success{ |
||||
border: 1px solid #B7EB8F; |
||||
background: #F6FFED; |
||||
.el-message__icon{ |
||||
color: #00c700; |
||||
} |
||||
} |
||||
.el-message--warning{ |
||||
border: 1px solid #FFE58F; |
||||
background: #FFFBE6; |
||||
.el-message__icon{ |
||||
color: #ffa900; |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-message-box{ |
||||
padding-bottom: 24px; |
||||
.el-message-box__header{ |
||||
padding: 32px 32px 12px 50px; |
||||
span{ |
||||
font-size: 16px; |
||||
color: rgba(0, 0, 0, 0.85); |
||||
font-weight: 500; |
||||
} |
||||
} |
||||
.el-message-box__status{ |
||||
top: -30px; |
||||
} |
||||
.el-message-box__status + .el-message-box__message{ |
||||
font-size: 14px; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
} |
||||
.el-message-box__btns{ |
||||
padding-right: 32px; |
||||
&.el-icon-warning{ |
||||
color: #ffa900; |
||||
} |
||||
} |
||||
&:not(.normal){ |
||||
.el-button--primary{ |
||||
color: #606266; |
||||
background: #fff; |
||||
border-color: #DCDFE6; |
||||
&:hover{ |
||||
color: $--color-primary; |
||||
border-color: #efbdbb; |
||||
background-color: #fae9e8; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.el-dialog__wrapper{ |
||||
.el-dialog{ |
||||
border-radius: 4px; |
||||
.el-dialog__header{ |
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06); |
||||
.el-dialog__title{ |
||||
font-size: 16px; |
||||
color: rgba(0, 0, 0, 0.85); |
||||
} |
||||
} |
||||
.el-dialog__footer{ |
||||
padding: 10px 16px; |
||||
border-top: 1px solid rgba(0, 0, 0, 0.06); |
||||
.el-button{ |
||||
font-size: 14px; |
||||
border-radius: 4px; |
||||
border-color: rgba(0, 0, 0, 0.15); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.upload-wrap{ |
||||
position: relative; |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
padding: 34px 0; |
||||
.el-button{ |
||||
span{ |
||||
display: flex; |
||||
align-items: center; |
||||
color: rgba(0, 0, 0, 0.65); |
||||
font-size: 14px; |
||||
img{ |
||||
margin-right: 8px; |
||||
} |
||||
} |
||||
} |
||||
&>.el-button{ |
||||
margin-right: 32px; |
||||
} |
||||
.el-upload-list{ |
||||
position: absolute; |
||||
bottom: 0; |
||||
left: 0; |
||||
width: 100%; |
||||
} |
||||
.link{ |
||||
position: absolute; |
||||
bottom: -20px; |
||||
left: 0; |
||||
width: 100%; |
||||
text-align: center; |
||||
} |
||||
&.lg{ |
||||
padding-bottom: 50px; |
||||
} |
||||
} |
||||
|
||||
.el-tooltip__popper{ |
||||
width: 300px; |
||||
} |
||||
|
||||
@media(max-width: 1600px){ |
||||
.el-table{ |
||||
.el-switch__label--right.is-active{ |
||||
left: 8px; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,7 @@ |
||||
/* 改变主题色变量 */ |
||||
|
||||
$--color-primary: #568DF2; |
||||
|
||||
/* 改变 icon 字体路径变量,必需 */ |
||||
$--font-path: '~element-ui/lib/theme-chalk/fonts'; |
||||
@import "~element-ui/packages/theme-chalk/src/index"; |
@ -0,0 +1,539 @@ |
||||
/* Logo 字体 */ |
||||
@font-face { |
||||
font-family: "iconfont logo"; |
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834'); |
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'), |
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'), |
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'), |
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg'); |
||||
} |
||||
|
||||
.logo { |
||||
font-family: "iconfont logo"; |
||||
font-size: 160px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
/* tabs */ |
||||
.nav-tabs { |
||||
position: relative; |
||||
} |
||||
|
||||
.nav-tabs .nav-more { |
||||
position: absolute; |
||||
right: 0; |
||||
bottom: 0; |
||||
height: 42px; |
||||
line-height: 42px; |
||||
color: #666; |
||||
} |
||||
|
||||
#tabs { |
||||
border-bottom: 1px solid #eee; |
||||
} |
||||
|
||||
#tabs li { |
||||
cursor: pointer; |
||||
width: 100px; |
||||
height: 40px; |
||||
line-height: 40px; |
||||
text-align: center; |
||||
font-size: 16px; |
||||
border-bottom: 2px solid transparent; |
||||
position: relative; |
||||
z-index: 1; |
||||
margin-bottom: -1px; |
||||
color: #666; |
||||
} |
||||
|
||||
|
||||
#tabs .active { |
||||
border-bottom-color: #f00; |
||||
color: #222; |
||||
} |
||||
|
||||
.tab-container .content { |
||||
display: none; |
||||
} |
||||
|
||||
/* 页面布局 */ |
||||
.main { |
||||
padding: 30px 100px; |
||||
width: 960px; |
||||
margin: 0 auto; |
||||
} |
||||
|
||||
.main .logo { |
||||
color: #333; |
||||
text-align: left; |
||||
margin-bottom: 30px; |
||||
line-height: 1; |
||||
height: 110px; |
||||
margin-top: -50px; |
||||
overflow: hidden; |
||||
*zoom: 1; |
||||
} |
||||
|
||||
.main .logo a { |
||||
font-size: 160px; |
||||
color: #333; |
||||
} |
||||
|
||||
.helps { |
||||
margin-top: 40px; |
||||
} |
||||
|
||||
.helps pre { |
||||
padding: 20px; |
||||
margin: 10px 0; |
||||
border: solid 1px #e7e1cd; |
||||
background-color: #fffdef; |
||||
overflow: auto; |
||||
} |
||||
|
||||
.icon_lists { |
||||
width: 100% !important; |
||||
overflow: hidden; |
||||
*zoom: 1; |
||||
} |
||||
|
||||
.icon_lists li { |
||||
width: 100px; |
||||
margin-bottom: 10px; |
||||
margin-right: 20px; |
||||
text-align: center; |
||||
list-style: none !important; |
||||
cursor: default; |
||||
} |
||||
|
||||
.icon_lists li .code-name { |
||||
line-height: 1.2; |
||||
} |
||||
|
||||
.icon_lists .icon { |
||||
display: block; |
||||
height: 100px; |
||||
line-height: 100px; |
||||
font-size: 42px; |
||||
margin: 10px auto; |
||||
color: #333; |
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear; |
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear; |
||||
transition: font-size 0.25s linear, width 0.25s linear; |
||||
} |
||||
|
||||
.icon_lists .icon:hover { |
||||
font-size: 100px; |
||||
} |
||||
|
||||
.icon_lists .svg-icon { |
||||
/* 通过设置 font-size 来改变图标大小 */ |
||||
width: 1em; |
||||
/* 图标和文字相邻时,垂直对齐 */ |
||||
vertical-align: -0.15em; |
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */ |
||||
fill: currentColor; |
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示 |
||||
normalize.css 中也包含这行 */ |
||||
overflow: hidden; |
||||
} |
||||
|
||||
.icon_lists li .name, |
||||
.icon_lists li .code-name { |
||||
color: #666; |
||||
} |
||||
|
||||
/* markdown 样式 */ |
||||
.markdown { |
||||
color: #666; |
||||
font-size: 14px; |
||||
line-height: 1.8; |
||||
} |
||||
|
||||
.highlight { |
||||
line-height: 1.5; |
||||
} |
||||
|
||||
.markdown img { |
||||
vertical-align: middle; |
||||
max-width: 100%; |
||||
} |
||||
|
||||
.markdown h1 { |
||||
color: #404040; |
||||
font-weight: 500; |
||||
line-height: 40px; |
||||
margin-bottom: 24px; |
||||
} |
||||
|
||||
.markdown h2, |
||||
.markdown h3, |
||||
.markdown h4, |
||||
.markdown h5, |
||||
.markdown h6 { |
||||
color: #404040; |
||||
margin: 1.6em 0 0.6em 0; |
||||
font-weight: 500; |
||||
clear: both; |
||||
} |
||||
|
||||
.markdown h1 { |
||||
font-size: 28px; |
||||
} |
||||
|
||||
.markdown h2 { |
||||
font-size: 22px; |
||||
} |
||||
|
||||
.markdown h3 { |
||||
font-size: 16px; |
||||
} |
||||
|
||||
.markdown h4 { |
||||
font-size: 14px; |
||||
} |
||||
|
||||
.markdown h5 { |
||||
font-size: 12px; |
||||
} |
||||
|
||||
.markdown h6 { |
||||
font-size: 12px; |
||||
} |
||||
|
||||
.markdown hr { |
||||
height: 1px; |
||||
border: 0; |
||||
background: #e9e9e9; |
||||
margin: 16px 0; |
||||
clear: both; |
||||
} |
||||
|
||||
.markdown p { |
||||
margin: 1em 0; |
||||
} |
||||
|
||||
.markdown>p, |
||||
.markdown>blockquote, |
||||
.markdown>.highlight, |
||||
.markdown>ol, |
||||
.markdown>ul { |
||||
width: 80%; |
||||
} |
||||
|
||||
.markdown ul>li { |
||||
list-style: circle; |
||||
} |
||||
|
||||
.markdown>ul li, |
||||
.markdown blockquote ul>li { |
||||
margin-left: 20px; |
||||
padding-left: 4px; |
||||
} |
||||
|
||||
.markdown>ul li p, |
||||
.markdown>ol li p { |
||||
margin: 0.6em 0; |
||||
} |
||||
|
||||
.markdown ol>li { |
||||
list-style: decimal; |
||||
} |
||||
|
||||
.markdown>ol li, |
||||
.markdown blockquote ol>li { |
||||
margin-left: 20px; |
||||
padding-left: 4px; |
||||
} |
||||
|
||||
.markdown code { |
||||
margin: 0 3px; |
||||
padding: 0 5px; |
||||
background: #eee; |
||||
border-radius: 3px; |
||||
} |
||||
|
||||
.markdown strong, |
||||
.markdown b { |
||||
font-weight: 600; |
||||
} |
||||
|
||||
.markdown>table { |
||||
border-collapse: collapse; |
||||
border-spacing: 0px; |
||||
empty-cells: show; |
||||
border: 1px solid #e9e9e9; |
||||
width: 95%; |
||||
margin-bottom: 24px; |
||||
} |
||||
|
||||
.markdown>table th { |
||||
white-space: nowrap; |
||||
color: #333; |
||||
font-weight: 600; |
||||
} |
||||
|
||||
.markdown>table th, |
||||
.markdown>table td { |
||||
border: 1px solid #e9e9e9; |
||||
padding: 8px 16px; |
||||
text-align: left; |
||||
} |
||||
|
||||
.markdown>table th { |
||||
background: #F7F7F7; |
||||
} |
||||
|
||||
.markdown blockquote { |
||||
font-size: 90%; |
||||
color: #999; |
||||
border-left: 4px solid #e9e9e9; |
||||
padding-left: 0.8em; |
||||
margin: 1em 0; |
||||
} |
||||
|
||||
.markdown blockquote p { |
||||
margin: 0; |
||||
} |
||||
|
||||
.markdown .anchor { |
||||
opacity: 0; |
||||
transition: opacity 0.3s ease; |
||||
margin-left: 8px; |
||||
} |
||||
|
||||
.markdown .waiting { |
||||
color: #ccc; |
||||
} |
||||
|
||||
.markdown h1:hover .anchor, |
||||
.markdown h2:hover .anchor, |
||||
.markdown h3:hover .anchor, |
||||
.markdown h4:hover .anchor, |
||||
.markdown h5:hover .anchor, |
||||
.markdown h6:hover .anchor { |
||||
opacity: 1; |
||||
display: inline-block; |
||||
} |
||||
|
||||
.markdown>br, |
||||
.markdown>p>br { |
||||
clear: both; |
||||
} |
||||
|
||||
|
||||
.hljs { |
||||
display: block; |
||||
background: white; |
||||
padding: 0.5em; |
||||
color: #333333; |
||||
overflow-x: auto; |
||||
} |
||||
|
||||
.hljs-comment, |
||||
.hljs-meta { |
||||
color: #969896; |
||||
} |
||||
|
||||
.hljs-string, |
||||
.hljs-variable, |
||||
.hljs-template-variable, |
||||
.hljs-strong, |
||||
.hljs-emphasis, |
||||
.hljs-quote { |
||||
color: #df5000; |
||||
} |
||||
|
||||
.hljs-keyword, |
||||
.hljs-selector-tag, |
||||
.hljs-type { |
||||
color: #a71d5d; |
||||
} |
||||
|
||||
.hljs-literal, |
||||
.hljs-symbol, |
||||
.hljs-bullet, |
||||
.hljs-attribute { |
||||
color: #0086b3; |
||||
} |
||||
|
||||
.hljs-section, |
||||
.hljs-name { |
||||
color: #63a35c; |
||||
} |
||||
|
||||
.hljs-tag { |
||||
color: #333333; |
||||
} |
||||
|
||||
.hljs-title, |
||||
.hljs-attr, |
||||
.hljs-selector-id, |
||||
.hljs-selector-class, |
||||
.hljs-selector-attr, |
||||
.hljs-selector-pseudo { |
||||
color: #795da3; |
||||
} |
||||
|
||||
.hljs-addition { |
||||
color: #55a532; |
||||
background-color: #eaffea; |
||||
} |
||||
|
||||
.hljs-deletion { |
||||
color: #bd2c00; |
||||
background-color: #ffecec; |
||||
} |
||||
|
||||
.hljs-link { |
||||
text-decoration: underline; |
||||
} |
||||
|
||||
/* 代码高亮 */ |
||||
/* PrismJS 1.15.0 |
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */ |
||||
/** |
||||
* prism.js default theme for JavaScript, CSS and HTML |
||||
* Based on dabblet (http://dabblet.com) |
||||
* @author Lea Verou |
||||
*/ |
||||
code[class*="language-"], |
||||
pre[class*="language-"] { |
||||
color: black; |
||||
background: none; |
||||
text-shadow: 0 1px white; |
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; |
||||
text-align: left; |
||||
white-space: pre; |
||||
word-spacing: normal; |
||||
word-break: normal; |
||||
word-wrap: normal; |
||||
line-height: 1.5; |
||||
|
||||
-moz-tab-size: 4; |
||||
-o-tab-size: 4; |
||||
tab-size: 4; |
||||
|
||||
-webkit-hyphens: none; |
||||
-moz-hyphens: none; |
||||
-ms-hyphens: none; |
||||
hyphens: none; |
||||
} |
||||
|
||||
pre[class*="language-"]::-moz-selection, |
||||
pre[class*="language-"] ::-moz-selection, |
||||
code[class*="language-"]::-moz-selection, |
||||
code[class*="language-"] ::-moz-selection { |
||||
text-shadow: none; |
||||
background: #b3d4fc; |
||||
} |
||||
|
||||
pre[class*="language-"]::selection, |
||||
pre[class*="language-"] ::selection, |
||||
code[class*="language-"]::selection, |
||||
code[class*="language-"] ::selection { |
||||
text-shadow: none; |
||||
background: #b3d4fc; |
||||
} |
||||
|
||||
@media print { |
||||
|
||||
code[class*="language-"], |
||||
pre[class*="language-"] { |
||||
text-shadow: none; |
||||
} |
||||
} |
||||
|
||||
/* Code blocks */ |
||||
pre[class*="language-"] { |
||||
padding: 1em; |
||||
margin: .5em 0; |
||||
overflow: auto; |
||||
} |
||||
|
||||
:not(pre)>code[class*="language-"], |
||||
pre[class*="language-"] { |
||||
background: #f5f2f0; |
||||
} |
||||
|
||||
/* Inline code */ |
||||
:not(pre)>code[class*="language-"] { |
||||
padding: .1em; |
||||
border-radius: .3em; |
||||
white-space: normal; |
||||
} |
||||
|
||||
.token.comment, |
||||
.token.prolog, |
||||
.token.doctype, |
||||
.token.cdata { |
||||
color: slategray; |
||||
} |
||||
|
||||
.token.punctuation { |
||||
color: #999; |
||||
} |
||||
|
||||
.namespace { |
||||
opacity: .7; |
||||
} |
||||
|
||||
.token.property, |
||||
.token.tag, |
||||
.token.boolean, |
||||
.token.number, |
||||
.token.constant, |
||||
.token.symbol, |
||||
.token.deleted { |
||||
color: #905; |
||||
} |
||||
|
||||
.token.selector, |
||||
.token.attr-name, |
||||
.token.string, |
||||
.token.char, |
||||
.token.builtin, |
||||
.token.inserted { |
||||
color: #690; |
||||
} |
||||
|
||||
.token.operator, |
||||
.token.entity, |
||||
.token.url, |
||||
.language-css .token.string, |
||||
.style .token.string { |
||||
color: #9a6e3a; |
||||
background: hsla(0, 0%, 100%, .5); |
||||
} |
||||
|
||||
.token.atrule, |
||||
.token.attr-value, |
||||
.token.keyword { |
||||
color: #07a; |
||||
} |
||||
|
||||
.token.function, |
||||
.token.class-name { |
||||
color: #DD4A68; |
||||
} |
||||
|
||||
.token.regex, |
||||
.token.important, |
||||
.token.variable { |
||||
color: #e90; |
||||
} |
||||
|
||||
.token.important, |
||||
.token.bold { |
||||
font-weight: bold; |
||||
} |
||||
|
||||
.token.italic { |
||||
font-style: italic; |
||||
} |
||||
|
||||
.token.entity { |
||||
cursor: help; |
||||
} |
@ -0,0 +1,446 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<head> |
||||
<meta charset="utf-8"/> |
||||
<title>IconFont Demo</title> |
||||
<link rel="shortcut icon" href="https://img.alicdn.com/tps/i4/TB1_oz6GVXXXXaFXpXXJDFnIXXX-64-64.ico" type="image/x-icon"/> |
||||
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css"> |
||||
<link rel="stylesheet" href="demo.css"> |
||||
<link rel="stylesheet" href="iconfont.css"> |
||||
<script src="iconfont.js"></script> |
||||
<!-- jQuery --> |
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script> |
||||
<!-- 代码高亮 --> |
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script> |
||||
</head> |
||||
<body> |
||||
<div class="main"> |
||||
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank"></a></h1> |
||||
<div class="nav-tabs"> |
||||
<ul id="tabs" class="dib-box"> |
||||
<li class="dib active"><span>Unicode</span></li> |
||||
<li class="dib"><span>Font class</span></li> |
||||
<li class="dib"><span>Symbol</span></li> |
||||
</ul> |
||||
|
||||
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=1540265" target="_blank" class="nav-more">查看项目</a> |
||||
|
||||
</div> |
||||
<div class="tab-container"> |
||||
<div class="content unicode" style="display: block;"> |
||||
<ul class="icon_lists dib-box"> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">已勾选32</div> |
||||
<div class="code-name">&#xe63d;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">未勾选32</div> |
||||
<div class="code-name">&#xe63e;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">未勾选40</div> |
||||
<div class="code-name">&#xe64a;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">已勾选40</div> |
||||
<div class="code-name">&#xe64b;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">实 向右箭头-01</div> |
||||
<div class="code-name">&#xe626;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">实 向下箭头-01</div> |
||||
<div class="code-name">&#xe625;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">加号-填充</div> |
||||
<div class="code-name">&#xe72d;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">42指向上、上箭头</div> |
||||
<div class="code-name">&#xe769;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">44指向下、下箭头</div> |
||||
<div class="code-name">&#xe76b;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">群蜂删除-充</div> |
||||
<div class="code-name">&#xe6e9;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">qq</div> |
||||
<div class="code-name">&#xe614;</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont"></span> |
||||
<div class="name">微信-36</div> |
||||
<div class="code-name">&#xe68a;</div> |
||||
</li> |
||||
|
||||
</ul> |
||||
<div class="article markdown"> |
||||
<h2 id="unicode-">Unicode 引用</h2> |
||||
<hr> |
||||
|
||||
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p> |
||||
<ul> |
||||
<li>兼容性最好,支持 IE6+,及所有现代浏览器。</li> |
||||
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li> |
||||
<li>但是因为是字体,所以不支持多色。只能使用平台里单色的图标,就算项目里有多色图标也会自动去色。</li> |
||||
</ul> |
||||
<blockquote> |
||||
<p>注意:新版 iconfont 支持多色图标,这些多色图标在 Unicode 模式下将不能使用,如果有需求建议使用symbol 的引用方式</p> |
||||
</blockquote> |
||||
<p>Unicode 使用步骤如下:</p> |
||||
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3> |
||||
<pre><code class="language-css" |
||||
>@font-face { |
||||
font-family: 'iconfont'; |
||||
src: url('iconfont.eot'); |
||||
src: url('iconfont.eot?#iefix') format('embedded-opentype'), |
||||
url('iconfont.woff2') format('woff2'), |
||||
url('iconfont.woff') format('woff'), |
||||
url('iconfont.ttf') format('truetype'), |
||||
url('iconfont.svg#iconfont') format('svg'); |
||||
} |
||||
</code></pre> |
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> |
||||
<pre><code class="language-css" |
||||
>.iconfont { |
||||
font-family: "iconfont" !important; |
||||
font-size: 16px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
</code></pre> |
||||
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3> |
||||
<pre> |
||||
<code class="language-html" |
||||
><span class="iconfont">&#x33;</span> |
||||
</code></pre> |
||||
<blockquote> |
||||
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p> |
||||
</blockquote> |
||||
</div> |
||||
</div> |
||||
<div class="content font-class"> |
||||
<ul class="icon_lists dib-box"> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-yigouxuan"></span> |
||||
<div class="name"> |
||||
已勾选32 |
||||
</div> |
||||
<div class="code-name">.icon-yigouxuan |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-weigouxuan"></span> |
||||
<div class="name"> |
||||
未勾选32 |
||||
</div> |
||||
<div class="code-name">.icon-weigouxuan |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-weigouxuan1"></span> |
||||
<div class="name"> |
||||
未勾选40 |
||||
</div> |
||||
<div class="code-name">.icon-weigouxuan1 |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-yigouxuan1"></span> |
||||
<div class="name"> |
||||
已勾选40 |
||||
</div> |
||||
<div class="code-name">.icon-yigouxuan1 |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-shixiangyoujiantou-"></span> |
||||
<div class="name"> |
||||
实 向右箭头-01 |
||||
</div> |
||||
<div class="code-name">.icon-shixiangyoujiantou- |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-shixiangxiajiantou-"></span> |
||||
<div class="name"> |
||||
实 向下箭头-01 |
||||
</div> |
||||
<div class="code-name">.icon-shixiangxiajiantou- |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-jiahao"></span> |
||||
<div class="name"> |
||||
加号-填充 |
||||
</div> |
||||
<div class="code-name">.icon-jiahao |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-up"></span> |
||||
<div class="name"> |
||||
42指向上、上箭头 |
||||
</div> |
||||
<div class="code-name">.icon-up |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-down"></span> |
||||
<div class="name"> |
||||
44指向下、下箭头 |
||||
</div> |
||||
<div class="code-name">.icon-down |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-delete"></span> |
||||
<div class="name"> |
||||
群蜂删除-充 |
||||
</div> |
||||
<div class="code-name">.icon-delete |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-qq"></span> |
||||
<div class="name"> |
||||
qq |
||||
</div> |
||||
<div class="code-name">.icon-qq |
||||
</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<span class="icon iconfont icon-weixin"></span> |
||||
<div class="name"> |
||||
微信-36 |
||||
</div> |
||||
<div class="code-name">.icon-weixin |
||||
</div> |
||||
</li> |
||||
|
||||
</ul> |
||||
<div class="article markdown"> |
||||
<h2 id="font-class-">font-class 引用</h2> |
||||
<hr> |
||||
|
||||
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p> |
||||
<p>与 Unicode 使用方式相比,具有如下特点:</p> |
||||
<ul> |
||||
<li>兼容性良好,支持 IE8+,及所有现代浏览器。</li> |
||||
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li> |
||||
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li> |
||||
<li>不过因为本质上还是使用的字体,所以多色图标还是不支持的。</li> |
||||
</ul> |
||||
<p>使用步骤如下:</p> |
||||
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3> |
||||
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css"> |
||||
</code></pre> |
||||
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
<pre><code class="language-html"><span class="iconfont icon-xxx"></span> |
||||
</code></pre> |
||||
<blockquote> |
||||
<p>" |
||||
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p> |
||||
</blockquote> |
||||
</div> |
||||
</div> |
||||
<div class="content symbol"> |
||||
<ul class="icon_lists dib-box"> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-yigouxuan"></use> |
||||
</svg> |
||||
<div class="name">已勾选32</div> |
||||
<div class="code-name">#icon-yigouxuan</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-weigouxuan"></use> |
||||
</svg> |
||||
<div class="name">未勾选32</div> |
||||
<div class="code-name">#icon-weigouxuan</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-weigouxuan1"></use> |
||||
</svg> |
||||
<div class="name">未勾选40</div> |
||||
<div class="code-name">#icon-weigouxuan1</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-yigouxuan1"></use> |
||||
</svg> |
||||
<div class="name">已勾选40</div> |
||||
<div class="code-name">#icon-yigouxuan1</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-shixiangyoujiantou-"></use> |
||||
</svg> |
||||
<div class="name">实 向右箭头-01</div> |
||||
<div class="code-name">#icon-shixiangyoujiantou-</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-shixiangxiajiantou-"></use> |
||||
</svg> |
||||
<div class="name">实 向下箭头-01</div> |
||||
<div class="code-name">#icon-shixiangxiajiantou-</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-jiahao"></use> |
||||
</svg> |
||||
<div class="name">加号-填充</div> |
||||
<div class="code-name">#icon-jiahao</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-up"></use> |
||||
</svg> |
||||
<div class="name">42指向上、上箭头</div> |
||||
<div class="code-name">#icon-up</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-down"></use> |
||||
</svg> |
||||
<div class="name">44指向下、下箭头</div> |
||||
<div class="code-name">#icon-down</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-delete"></use> |
||||
</svg> |
||||
<div class="name">群蜂删除-充</div> |
||||
<div class="code-name">#icon-delete</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-qq"></use> |
||||
</svg> |
||||
<div class="name">qq</div> |
||||
<div class="code-name">#icon-qq</div> |
||||
</li> |
||||
|
||||
<li class="dib"> |
||||
<svg class="icon svg-icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-weixin"></use> |
||||
</svg> |
||||
<div class="name">微信-36</div> |
||||
<div class="code-name">#icon-weixin</div> |
||||
</li> |
||||
|
||||
</ul> |
||||
<div class="article markdown"> |
||||
<h2 id="symbol-">Symbol 引用</h2> |
||||
<hr> |
||||
|
||||
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a> |
||||
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p> |
||||
<ul> |
||||
<li>支持多色图标了,不再受单色限制。</li> |
||||
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li> |
||||
<li>兼容性较差,支持 IE9+,及现代浏览器。</li> |
||||
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li> |
||||
</ul> |
||||
<p>使用步骤如下:</p> |
||||
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3> |
||||
<pre><code class="language-html"><script src="./iconfont.js"></script> |
||||
</code></pre> |
||||
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3> |
||||
<pre><code class="language-html"><style> |
||||
.icon { |
||||
width: 1em; |
||||
height: 1em; |
||||
vertical-align: -0.15em; |
||||
fill: currentColor; |
||||
overflow: hidden; |
||||
} |
||||
</style> |
||||
</code></pre> |
||||
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3> |
||||
<pre><code class="language-html"><svg class="icon" aria-hidden="true"> |
||||
<use xlink:href="#icon-xxx"></use> |
||||
</svg> |
||||
</code></pre> |
||||
</div> |
||||
</div> |
||||
|
||||
</div> |
||||
</div> |
||||
<script> |
||||
$(document).ready(function () { |
||||
$('.tab-container .content:first').show() |
||||
|
||||
$('#tabs li').click(function (e) { |
||||
var tabContent = $('.tab-container .content') |
||||
var index = $(this).index() |
||||
|
||||
if ($(this).hasClass('active')) { |
||||
return |
||||
} else { |
||||
$('#tabs li').removeClass('active') |
||||
$(this).addClass('active') |
||||
|
||||
tabContent.hide().eq(index).fadeIn() |
||||
} |
||||
}) |
||||
}) |
||||
</script> |
||||
</body> |
||||
</html> |
@ -0,0 +1,71 @@ |
||||
@font-face {font-family: "iconfont"; |
||||
src: url('iconfont.eot?t=1589437921018'); /* IE9 */ |
||||
src: url('iconfont.eot?t=1589437921018#iefix') format('embedded-opentype'), /* IE6-IE8 */ |
||||
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAdgAAsAAAAADwwAAAcTAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCESgqOeIt2ATYCJAM0CxwABCAFhG0HgTMbpQxRlHBSFNlX2JThXqSJ4cz0aLyxzNkVgYOP2N97wQhUeQbPDZA1QByDeHha+9+5M7PrD1FpdI8mCSqJLulDJPFDxCQTvUQS6Qtka3ukU0/kuK8wfBBwMr1kmeTIb8hUohVh6lTeCHDCrRPPf5v6f+sQfS+QqgmpiZLNw+ZI6zMXZGL3nXY47elJFnjALaE4zjzyjJN773yuzM/7H4oZ9NV+v/q1g1ddvP1QmE5JlPRM7uAv5klMk0vWTBWTLpoJEUIja6hWSkNhOklN/ds4n0BvhyLMuZ6hKdArLC1Q4a4iG0Gfi1JaHEMbXtfsW8S8SpsepzuAJ+HLx28hoSepMmvby3e6LdC2EN2eV0ykW36MR/MlQFiJjGNAEej7WvtLgB6aM6evXtwH1glnTloW1snRYnBhky+LxyuL9glaGNmaDbRsJYR1tl+seImrgUGtEtLc//GMeo1WR9QYfUSrp7nohWgXDRrJBqpBcoAqkGagAGkBSiADQBlkEKiAbAI/N/mCYHoWi1HDEgWoBbGjlg7M/OpbgEMgnUf0fxab8kjK0tvq8cZ6/dpKwk4bNsXFx4bHR4RHcty4LVnR4xp/2TFxDN42tgefhUpEMeeqppXCU50JyT/gkVCD+EiEgl56LOkMN+6cAfyKs3dvomHU7fvnq96Uc/duIXMMqWmhNRoax1m8jNWfPorp2jlqumvHrolfe/2TcuIPCt3K589dhUNiT5OSEh4KoM9Jp1vK2GMnFjDdyaeFMrd06ki1gn9CmEz3OErpebmp+GzyAN+lMLw6dwkKh6Ve5dOnzp4W0+Y25TTfhHB10isXpxIB5GHDKcggnof+NCpCD+okAFyTPNGuRVgahmhLjZo1rnqnMlpD0ORJSluuY6jT+gPWHtaIeDKOaoradNDPruOQzulPGcBtz0C2YdbLrSFPIMGTrcNRDGC3YnJOm1JLceYK2sCWY5lqxICXIEU0gki2nkPFUteBwoqLMyTdKE7ZlOzE3yHfdSyOU2shl8RoxPJlx1bQ6C0Li3DLg+Sdi+c5evEkhtF3rBdfXpe0IiNcfW27+x6u5U4vs8zZZdu1R7Gblyc6AV9OB4Xp65HRDqcvw0Pi1DGbddntOKzYgkbhXJq+Y4bRVqszl746KdRPFV5FxSUb6XmKomd1yCb0nJbpz+aOIZskx0phXx8sHfNKyRjPsM8LGU/xJ9Qrv2JugdVBkBg/ZpUIDvpN0jfHD550XPKNDgkKEZ46l4dwq0sOxIecJlX2pxxA8GTwkCGMFqxVFf5PRZplCky9uCIQL/s/RFabTYZNkhtkQXFR28vKXwKUP5rZbFg+s3VAFTu5dBZG4G07t5tHuM2cFirh2BisrHKYoE8lzO1h/LkwjSD+VZF0qs1hQVK+d0xHOLN80q4B/P9utxQDmGt4DaEKE6Lc5lnI6VxDf/35owQHCAuKw95VG6l1bvXPY3J1slpepPBXdCx8EM+ubbd2tV48b2UtWLtYb89PZhvg2jsq5+zkBdIVVTFHfhEwNv0CxNiT02LKVxGSus1dt9VsXDZulogOJB1AkGQVg4e833uzaWatx7bPrLKyhBeBqlC3xGqNoe3MVQHmDmBs4jm+xFjW/sjcAgOiPOFawwe3bUeTa20vGNZgbV6tCtL/qEL/fmiFLjqCCDpZdQpkdKgx6tSuzlCdqnrMFsLMhWn9sKH4ezmjmvpp9Selw9oCS0Vtcbox4f967yYpc1lNwUzPAUT3N0R32yz0bof5Wblw2jzkuw4VkWFptzoKckHRUwszvHJS8IgkAfys2IvKr/LtZBa1LzvfHBmFD6/V9enLD7LLJD2tz7n3E8BkFcwVyA/DL8P0fCpXAdLntBfy9tQCpuUP2QBAWkwyYccYGYFWWc/HS8Of6pVNf1r8p8n48bn+wPLzm5gyWoneAh3ivzATiiRKljoz8hQTN3S0itSojpnbgvjFod7uBf2Rtsa7dej63gKVRdenkDS2Q9baZyzWY1AZnIBa6yT0juo9eLCWhhOlwxFrCYRVjkKywhfIVrlrLNa3UNngB9RWBQe9mxF1zMGBUFCnRoyUWLBpCStm1SU5sRRFFSeI7HUYtawUeswQzaNk4PKSsmJBL3ERbY4dPD65glIJS5rqxD3kYsThULFbU23ETEuslLobSkuluh1LzKoTkLM0hBH1A1pgJku2CjOVizQ+hUrPP4GQeTkYaS0tarYzCI2HMnusXImyHsZe3dWrxb1U9/CRVaBMggS79TUqJ6yHSSAcdq4Kc9evZUOYUSWsI7LdGpQy7Ul99ZL1qfObT4CedX+zSJGjRBV1NNFGF30MMcYsVugeKLLqDXiNLuQnSQjRvRwtrRzlsSoBxeiSl1SvLVQoF1FcZj0Jqi46odWosl43b1H9Lp2FOAgl7OKibs6cgOICAA==') format('woff2'), |
||||
url('iconfont.woff?t=1589437921018') format('woff'), |
||||
url('iconfont.ttf?t=1589437921018') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ |
||||
url('iconfont.svg?t=1589437921018#iconfont') format('svg'); /* iOS 4.1- */ |
||||
} |
||||
|
||||
.iconfont { |
||||
font-family: "iconfont" !important; |
||||
font-size: 16px; |
||||
font-style: normal; |
||||
-webkit-font-smoothing: antialiased; |
||||
-moz-osx-font-smoothing: grayscale; |
||||
} |
||||
|
||||
.icon-yigouxuan:before { |
||||
content: "\e63d"; |
||||
} |
||||
|
||||
.icon-weigouxuan:before { |
||||
content: "\e63e"; |
||||
} |
||||
|
||||
.icon-weigouxuan1:before { |
||||
content: "\e64a"; |
||||
} |
||||
|
||||
.icon-yigouxuan1:before { |
||||
content: "\e64b"; |
||||
} |
||||
|
||||
.icon-shixiangyoujiantou-:before { |
||||
content: "\e626"; |
||||
} |
||||
|
||||
.icon-shixiangxiajiantou-:before { |
||||
content: "\e625"; |
||||
} |
||||
|
||||
.icon-jiahao:before { |
||||
content: "\e72d"; |
||||
} |
||||
|
||||
.icon-up:before { |
||||
content: "\e769"; |
||||
} |
||||
|
||||
.icon-down:before { |
||||
content: "\e76b"; |
||||
} |
||||
|
||||
.icon-delete:before { |
||||
content: "\e6e9"; |
||||
} |
||||
|
||||
.icon-qq:before { |
||||
content: "\e614"; |
||||
font-size: 60px; |
||||
color: #22aaf8; |
||||
margin-left: 32px; |
||||
} |
||||
|
||||
.icon-weixin:before { |
||||
content: "\e68a"; |
||||
font-size: 60px; |
||||
color: #10b747; |
||||
margin-right: 32px; |
||||
} |
||||
|
@ -0,0 +1,93 @@ |
||||
{ |
||||
"id": "1540265", |
||||
"name": "education", |
||||
"font_family": "iconfont", |
||||
"css_prefix_text": "icon-", |
||||
"description": "", |
||||
"glyphs": [ |
||||
{ |
||||
"icon_id": "2716513", |
||||
"name": "已勾选32", |
||||
"font_class": "yigouxuan", |
||||
"unicode": "e63d", |
||||
"unicode_decimal": 58941 |
||||
}, |
||||
{ |
||||
"icon_id": "2716516", |
||||
"name": "未勾选32", |
||||
"font_class": "weigouxuan", |
||||
"unicode": "e63e", |
||||
"unicode_decimal": 58942 |
||||
}, |
||||
{ |
||||
"icon_id": "2892929", |
||||
"name": "未勾选40", |
||||
"font_class": "weigouxuan1", |
||||
"unicode": "e64a", |
||||
"unicode_decimal": 58954 |
||||
}, |
||||
{ |
||||
"icon_id": "2892954", |
||||
"name": "已勾选40", |
||||
"font_class": "yigouxuan1", |
||||
"unicode": "e64b", |
||||
"unicode_decimal": 58955 |
||||
}, |
||||
{ |
||||
"icon_id": "5979965", |
||||
"name": "实 向右箭头-01", |
||||
"font_class": "shixiangyoujiantou-", |
||||
"unicode": "e626", |
||||
"unicode_decimal": 58918 |
||||
}, |
||||
{ |
||||
"icon_id": "5979966", |
||||
"name": "实 向下箭头-01", |
||||
"font_class": "shixiangxiajiantou-", |
||||
"unicode": "e625", |
||||
"unicode_decimal": 58917 |
||||
}, |
||||
{ |
||||
"icon_id": "8349103", |
||||
"name": "加号-填充", |
||||
"font_class": "jiahao", |
||||
"unicode": "e72d", |
||||
"unicode_decimal": 59181 |
||||
}, |
||||
{ |
||||
"icon_id": "6129078", |
||||
"name": "42指向上、上箭头", |
||||
"font_class": "up", |
||||
"unicode": "e769", |
||||
"unicode_decimal": 59241 |
||||
}, |
||||
{ |
||||
"icon_id": "6129081", |
||||
"name": "44指向下、下箭头", |
||||
"font_class": "down", |
||||
"unicode": "e76b", |
||||
"unicode_decimal": 59243 |
||||
}, |
||||
{ |
||||
"icon_id": "410692", |
||||
"name": "群蜂删除-充", |
||||
"font_class": "delete", |
||||
"unicode": "e6e9", |
||||
"unicode_decimal": 59113 |
||||
}, |
||||
{ |
||||
"icon_id": "468193", |
||||
"name": "qq", |
||||
"font_class": "qq", |
||||
"unicode": "e614", |
||||
"unicode_decimal": 58900 |
||||
}, |
||||
{ |
||||
"icon_id": "7009153", |
||||
"name": "微信-36", |
||||
"font_class": "weixin", |
||||
"unicode": "e68a", |
||||
"unicode_decimal": 59018 |
||||
} |
||||
] |
||||
} |