@ -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 () { |
||||||
|
//在页面加载时读取localStorage里的状态信息 |
||||||
|
if (util.local.get(Setting.storeKey) ) { |
||||||
|
this.$store.replaceState(Object.assign({}, this.$store.state,util.local.get(Setting.storeKey))) |
||||||
|
} |
||||||
|
|
||||||
|
//在页面刷新时将vuex里的信息保存到localStorage里 |
||||||
|
window.addEventListener("beforeunload",()=>{ |
||||||
|
util.local.get(Setting.tokenKey) && util.local.set(Setting.storeKey,this.$store.state) |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
After Width: | Height: | Size: 9.4 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 9.0 KiB |
After Width: | Height: | Size: 280 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 667 KiB |
After Width: | Height: | Size: 207 KiB |
After Width: | Height: | Size: 38 KiB |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 488 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 2.6 MiB |
After Width: | Height: | Size: 558 KiB |
After Width: | Height: | Size: 308 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 3.2 MiB |
After Width: | Height: | Size: 47 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 204 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 41 KiB |
After Width: | Height: | Size: 28 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 8.3 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 6.8 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 45 KiB |
After Width: | Height: | Size: 754 B |
After Width: | Height: | Size: 879 B |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 694 B |
@ -0,0 +1,124 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-dialog |
||||||
|
custom-class="pdf-dia" |
||||||
|
:close-on-click-modal="false" |
||||||
|
:visible.sync="visible" |
||||||
|
@close="closePdf" |
||||||
|
:fullscreen="true" |
||||||
|
:modal="false" |
||||||
|
:append-to-body="true"> |
||||||
|
<div> |
||||||
|
<button type="button" aria-label="Close" class="el-dialog__headerbtn" @click="closePdf"><i class="el-dialog__close el-icon el-icon-close"></i></button> |
||||||
|
<div class="pdf"> |
||||||
|
<p class="arrow"> |
||||||
|
<span @click="changePdfPage(0)" class="turn el-icon-arrow-left" :class="{grey: currentPage==1}"></span> |
||||||
|
{{currentPage}} / {{pageCount}} |
||||||
|
<span @click="changePdfPage(1)" class="turn el-icon-arrow-right" :class="{grey: currentPage==pageCount}"></span> |
||||||
|
</p> |
||||||
|
<pdf |
||||||
|
class="pdf-wrap" |
||||||
|
:src="src" |
||||||
|
:page="currentPage" |
||||||
|
@num-pages="pageCount=$event" |
||||||
|
@page-loaded="currentPage=$event" |
||||||
|
@loaded="loadPdfHandler" |
||||||
|
> |
||||||
|
</pdf> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import pdf from "vue-pdf"; |
||||||
|
export default { |
||||||
|
props: ['visible','src'], |
||||||
|
data() { |
||||||
|
return { |
||||||
|
pdfVisible: false, |
||||||
|
pdfSrc: '', |
||||||
|
currentPage: 0, |
||||||
|
pageCount: 0, |
||||||
|
fileType: 'pdf', |
||||||
|
}; |
||||||
|
}, |
||||||
|
components: { pdf }, |
||||||
|
mounted(){ |
||||||
|
this.addEvent() |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
closePdf(){ |
||||||
|
this.$emit('update:visible',false) |
||||||
|
this.$emit('update:src','') |
||||||
|
this.currentPage = 1 |
||||||
|
}, |
||||||
|
changePdfPage (val) { |
||||||
|
if (val === 0 && this.currentPage > 1) { |
||||||
|
this.currentPage-- |
||||||
|
} |
||||||
|
if (val === 1 && this.currentPage < this.pageCount) { |
||||||
|
this.currentPage++ |
||||||
|
} |
||||||
|
}, |
||||||
|
loadPdfHandler (e) { |
||||||
|
this.currentPage = 1 |
||||||
|
}, |
||||||
|
addEvent(){ |
||||||
|
document.onkeydown = e => { |
||||||
|
let key = window.event.keyCode |
||||||
|
if(key == 37){ |
||||||
|
this.changePdfPage(0) |
||||||
|
}else if(key == 39){ |
||||||
|
this.changePdfPage(1) |
||||||
|
} |
||||||
|
} |
||||||
|
this.$once('hook:beforeDestroy',() => { |
||||||
|
document.onkeydown = null |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
/deep/.pdf-dia{ |
||||||
|
border-radius: 0 !important; |
||||||
|
.el-dialog__header{ |
||||||
|
display: none; |
||||||
|
} |
||||||
|
.el-dialog__body{ |
||||||
|
padding: 0; |
||||||
|
} |
||||||
|
.el-dialog__headerbtn{ |
||||||
|
top: 10px; |
||||||
|
.el-dialog__close{ |
||||||
|
color: #fff; |
||||||
|
font-size: 16px; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
.pdf{ |
||||||
|
.arrow{ |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 100%; |
||||||
|
padding: 10px 0; |
||||||
|
font-size: 16px; |
||||||
|
color: #fff; |
||||||
|
background-color: #333; |
||||||
|
.turn{ |
||||||
|
margin: 0 10px; |
||||||
|
font-size: 18px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
.pdf-wrap{ |
||||||
|
height: calc(100vh - 45px); |
||||||
|
margin: 0 auto; |
||||||
|
overflow: auto; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
</style> |
@ -0,0 +1,179 @@ |
|||||||
|
<template> |
||||||
|
<div class="quill" :class="classes"> |
||||||
|
<div ref="editor" :style="styles" v-loading="loading"></div> |
||||||
|
|
||||||
|
<el-upload :action="this.api.fileupload" :before-upload="beforeUpload" :on-success="editorUploadSuccess" style="display: none"> |
||||||
|
<el-button class="editorUpload" size="small" type="primary">点击上传</el-button> |
||||||
|
</el-upload> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Quill from 'quill'; |
||||||
|
import 'quill/dist/quill.core.css'; |
||||||
|
import 'quill/dist/quill.snow.css'; |
||||||
|
import 'quill/dist/quill.bubble.css'; |
||||||
|
import toolbarOptions from './options' |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'quill', |
||||||
|
props: { |
||||||
|
value: { |
||||||
|
type: String, |
||||||
|
default: '' |
||||||
|
}, |
||||||
|
readonly: { |
||||||
|
type: Boolean, |
||||||
|
default: false |
||||||
|
}, |
||||||
|
toTop: { |
||||||
|
type: Boolean, |
||||||
|
default: true |
||||||
|
}, |
||||||
|
border: { |
||||||
|
type: Boolean, |
||||||
|
default: false |
||||||
|
}, |
||||||
|
height: { |
||||||
|
type: Number |
||||||
|
}, |
||||||
|
minHeight: { |
||||||
|
type: Number |
||||||
|
} |
||||||
|
}, |
||||||
|
data () { |
||||||
|
return { |
||||||
|
Quill: null, |
||||||
|
currentValue: '', |
||||||
|
options: { |
||||||
|
theme: 'snow', |
||||||
|
bounds: document.body, |
||||||
|
debug: 'warn', |
||||||
|
modules: { |
||||||
|
toolbar: { |
||||||
|
container: toolbarOptions, |
||||||
|
handlers: { |
||||||
|
'image': function (value) { |
||||||
|
if (value) { |
||||||
|
// 调用iview图片上传 |
||||||
|
document.querySelector('.editorUpload').click() |
||||||
|
} else { |
||||||
|
this.Quill.format('image', false); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
placeholder: '', |
||||||
|
readOnly: this.readonly |
||||||
|
}, |
||||||
|
loading: false |
||||||
|
} |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
classes () { |
||||||
|
return [ |
||||||
|
{ |
||||||
|
'quill-no-border': !this.border |
||||||
|
} |
||||||
|
]; |
||||||
|
}, |
||||||
|
styles () { |
||||||
|
let style = {}; |
||||||
|
if (this.minHeight) { |
||||||
|
style.minHeight = `${this.minHeight}px`; |
||||||
|
} |
||||||
|
if (this.height) { |
||||||
|
style.height = `${this.height}px`; |
||||||
|
} |
||||||
|
return style; |
||||||
|
} |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
value: { |
||||||
|
handler (val) { |
||||||
|
if (val !== this.currentValue) { |
||||||
|
this.currentValue = val; |
||||||
|
if (this.Quill) { |
||||||
|
this.Quill.pasteHTML(this.value); |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
immediate: true |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted () { |
||||||
|
this.init(); |
||||||
|
}, |
||||||
|
beforeDestroy () { |
||||||
|
// 在组件销毁后销毁实例 |
||||||
|
this.Quill = null; |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
init () { |
||||||
|
const editor = this.$refs.editor; |
||||||
|
// 初始化编辑器 |
||||||
|
this.Quill = new Quill(editor, this.options); |
||||||
|
// 默认值 |
||||||
|
this.Quill.pasteHTML(this.currentValue); |
||||||
|
if(this.toTop){ |
||||||
|
this.$nextTick(() => { |
||||||
|
window.scrollTo(0,0) |
||||||
|
}) |
||||||
|
} |
||||||
|
// 绑定事件 |
||||||
|
this.Quill.on('text-change', (delta, oldDelta, source) => { |
||||||
|
const html = this.$refs.editor.children[0].innerHTML; |
||||||
|
const text = this.Quill.getText(); |
||||||
|
const quill = this.Quill; |
||||||
|
// 更新内部的值 |
||||||
|
this.currentValue = html; |
||||||
|
// 发出事件 v-model |
||||||
|
this.$emit('input', html); |
||||||
|
// 发出事件 |
||||||
|
this.$emit('on-change', { html, text, quill }); |
||||||
|
}); |
||||||
|
// 将一些 quill 自带的事件传递出去 |
||||||
|
this.Quill.on('text-change', (delta, oldDelta, source) => { |
||||||
|
this.$emit('on-text-change', delta, oldDelta, source); |
||||||
|
}); |
||||||
|
this.Quill.on('selection-change', (range, oldRange, source) => { |
||||||
|
this.$emit('on-selection-change', range, oldRange, source); |
||||||
|
}); |
||||||
|
this.Quill.on('editor-change', (eventName, ...args) => { |
||||||
|
this.$emit('on-editor-change', eventName, ...args); |
||||||
|
}); |
||||||
|
}, |
||||||
|
beforeUpload(file){ |
||||||
|
this.loading = true |
||||||
|
}, |
||||||
|
editorUploadSuccess (res) { |
||||||
|
// 获取富文本组件实例 |
||||||
|
let quill = this.Quill |
||||||
|
// 如果上传成功 |
||||||
|
if (res.data.filesResult.fileUrl) { |
||||||
|
// 获取光标所在位置 |
||||||
|
let length = quill.getSelection().index; |
||||||
|
// 插入图片,res为服务器返回的图片链接地址 |
||||||
|
quill.insertEmbed(length, 'image', res.data.filesResult.fileUrl) |
||||||
|
// 调整光标到最后 |
||||||
|
quill.setSelection(length + 1) |
||||||
|
} else { |
||||||
|
this.$message.success('图片插入失败') |
||||||
|
} |
||||||
|
this.loading = false |
||||||
|
}, |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.quill-no-border{ |
||||||
|
.ql-toolbar.ql-snow{ |
||||||
|
border: none; |
||||||
|
border-bottom: 1px solid #e8eaec; |
||||||
|
} |
||||||
|
.ql-container.ql-snow{ |
||||||
|
border: none; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,16 @@ |
|||||||
|
export default [ |
||||||
|
['bold', 'italic', 'underline', 'strike'], |
||||||
|
['blockquote', 'code-block'], |
||||||
|
[{ 'header': 1 }, { 'header': 2 }], |
||||||
|
[{ 'list': 'ordered' }, { 'list': 'bullet' }], |
||||||
|
[{ 'script': 'sub' }, { 'script': 'super' }], |
||||||
|
[{ 'indent': '-1' }, { 'indent': '+1' }], |
||||||
|
[{ 'direction': 'rtl' }], |
||||||
|
[{ 'size': ['small', false, 'large', 'huge'] }], |
||||||
|
[{ 'header': [1, 2, 3, 4, 5, 6, false] }], |
||||||
|
[{ 'color': [] }, { 'background': [] }], |
||||||
|
[{ 'font': [] }], |
||||||
|
[{ 'align': [] }], |
||||||
|
['clean'], |
||||||
|
['link', 'image', 'video'] |
||||||
|
] |
@ -0,0 +1,30 @@ |
|||||||
|
export const messages = { |
||||||
|
'zh': { |
||||||
|
i18n: { |
||||||
|
breadcrumb: '国际化产品', |
||||||
|
tips: '通过切换语言按钮,来改变当前内容的语言。', |
||||||
|
btn: '切换英文', |
||||||
|
title1: '常用用法', |
||||||
|
p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。', |
||||||
|
p2: '没有什么比信念更能支撑我们度过艰难的时光了。', |
||||||
|
p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。', |
||||||
|
title2: '组件插值', |
||||||
|
info: 'Element组件需要国际化,请参考 {action}。', |
||||||
|
value: '文档' |
||||||
|
} |
||||||
|
}, |
||||||
|
'en': { |
||||||
|
i18n: { |
||||||
|
breadcrumb: 'International Products', |
||||||
|
tips: 'Click on the button to change the current language. ', |
||||||
|
btn: 'Switch Chinese', |
||||||
|
title1: 'Common usage', |
||||||
|
p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.", |
||||||
|
p2: "Nothing can help us endure dark times better than our faith. ", |
||||||
|
p3: "If you can do what you do best and be happy, you're further along in life than most people.", |
||||||
|
title2: 'Component interpolation', |
||||||
|
info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.', |
||||||
|
value: 'documentation' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,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,50 @@ |
|||||||
|
<template> |
||||||
|
<div class="header"> |
||||||
|
<div class="inner"> |
||||||
|
<div class="logo" @click="toIndex"> |
||||||
|
<img src="../../assets/img/logo.png" alt=""> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<script> |
||||||
|
import { mapState,mapActions } from 'vuex' |
||||||
|
import Setting from '@/setting' |
||||||
|
import util from '@/libs/util' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
token: util.local.get(Setting.tokenKey), |
||||||
|
}; |
||||||
|
}, |
||||||
|
mounted(){ |
||||||
|
|
||||||
|
}, |
||||||
|
methods: { |
||||||
|
toIndex(){ |
||||||
|
this.$refs.nav.jump({ |
||||||
|
index: '/index/list', |
||||||
|
title: '首页' |
||||||
|
}) |
||||||
|
}, |
||||||
|
}, |
||||||
|
}; |
||||||
|
</script> |
||||||
|
<style lang="scss" scoped> |
||||||
|
.header{ |
||||||
|
z-index: 1; |
||||||
|
display: flex; |
||||||
|
align-items: center; |
||||||
|
position: relative; |
||||||
|
height: 68px; |
||||||
|
background-color: #fff; |
||||||
|
.logo{ |
||||||
|
width: 500px; |
||||||
|
margin-left: 42px; |
||||||
|
cursor: pointer; |
||||||
|
img{ |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,62 @@ |
|||||||
|
<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%; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,123 @@ |
|||||||
|
<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,mapActions } from 'vuex' |
||||||
|
import addRoutes from '@/libs/route/addRoutes' |
||||||
|
import Setting from '@/setting' |
||||||
|
import util from '@/libs/util' |
||||||
|
export default { |
||||||
|
data() { |
||||||
|
return { |
||||||
|
managerStr: this.$route.query.mg, |
||||||
|
isManager: false, |
||||||
|
active: this.$route.path, |
||||||
|
defaultMenus: [ |
||||||
|
{ |
||||||
|
index: '/index/list', |
||||||
|
title: '首页' |
||||||
|
},{ |
||||||
|
index: '/data/list', |
||||||
|
title: '数据' |
||||||
|
} |
||||||
|
], |
||||||
|
managerMenus: [ |
||||||
|
{ |
||||||
|
index: '/stat/list', |
||||||
|
title: '数据统计' |
||||||
|
},{ |
||||||
|
index: '/user/list', |
||||||
|
title: '用户管理' |
||||||
|
},{ |
||||||
|
index: '/role/list', |
||||||
|
title: '角色权限' |
||||||
|
} |
||||||
|
], |
||||||
|
menus: [], |
||||||
|
actives: {} |
||||||
|
}; |
||||||
|
}, |
||||||
|
computed: { |
||||||
|
...mapState('auth', [ |
||||||
|
'routes' |
||||||
|
]) |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
'$route'(to,from) { |
||||||
|
let actives = this.actives |
||||||
|
for(let i in this.actives){ |
||||||
|
if(actives[i].includes(this.$route.name)) this.active = `/${i}/list` |
||||||
|
} |
||||||
|
this.active = this.$route.path |
||||||
|
} |
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
if(util.local.get(Setting.tokenKey)){ |
||||||
|
this.getPer() |
||||||
|
if(this.managerStr && atob(decodeURI(this.managerStr)) === 'true'){ |
||||||
|
this.isManager = true |
||||||
|
this.setManager(false) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
methods: { |
||||||
|
...mapActions('user', [ |
||||||
|
'setManager' |
||||||
|
]), |
||||||
|
initMenu(){ |
||||||
|
if(this.isManager){ |
||||||
|
this.defaultMenus = this.managerMenus |
||||||
|
if(Setting.dynamicRoute){ |
||||||
|
let routes = this.routes |
||||||
|
let menus = [] |
||||||
|
this.defaultMenus.map(e => { |
||||||
|
routes.find(n => n.name == e.index) && menus.push(e) |
||||||
|
}) |
||||||
|
this.menus = menus |
||||||
|
}else{ |
||||||
|
this.menus = this.defaultMenus |
||||||
|
} |
||||||
|
}else{ |
||||||
|
this.menus = this.defaultMenus |
||||||
|
} |
||||||
|
}, |
||||||
|
jump(item){ |
||||||
|
this.active = item.index |
||||||
|
this.$router.push(item.index).catch(err => {}) |
||||||
|
}, |
||||||
|
getPer(){ |
||||||
|
this.$post(this.api.getPermissions).then(res => { |
||||||
|
let routes = res.permissions[0].children |
||||||
|
Setting.dynamicRoute && addRoutes(routes) |
||||||
|
this.initMenu() |
||||||
|
}).catch(err => {}) |
||||||
|
}, |
||||||
|
} |
||||||
|
}; |
||||||
|
</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,25 @@ |
|||||||
|
/** |
||||||
|
* @description 生成按钮级别权限组 |
||||||
|
* */ |
||||||
|
|
||||||
|
import store from '@/store'; |
||||||
|
export default function(data){ |
||||||
|
let result = [] |
||||||
|
data.map(e => { |
||||||
|
if(e.select){ |
||||||
|
e.children.map(n => { |
||||||
|
if(n.select){ |
||||||
|
if(n.children.length){ |
||||||
|
result.push(`${e.name}:${n.name}`) |
||||||
|
n.children.map(j => { |
||||||
|
j.select && (e.path ? result.push(`${e.path}:${n.name}:${j.name}`) : result.push(`${n.path}:${j.name}`)) |
||||||
|
}) |
||||||
|
}else{ |
||||||
|
result.push(`${e.path}:${n.name}`) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
}) |
||||||
|
store.dispatch('auth/addBtnAuth',result) |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
import Vue from 'vue'; |
||||||
|
|
||||||
|
// 使用 Event Bus
|
||||||
|
const bus = new Vue(); |
||||||
|
|
||||||
|
export default bus; |
@ -0,0 +1,10 @@ |
|||||||
|
// 生成随机字符串
|
||||||
|
export default function (len = 32) { |
||||||
|
const $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'; |
||||||
|
const maxPos = $chars.length; |
||||||
|
let str = ''; |
||||||
|
for (let i = 0; i < len; i++) { |
||||||
|
str += $chars.charAt(Math.floor(Math.random() * maxPos)); |
||||||
|
} |
||||||
|
return str; |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
// rem等比适配配置文件
|
||||||
|
// 基准大小
|
||||||
|
const baseSize = 16 |
||||||
|
// 设置 rem 函数
|
||||||
|
function setRem () { |
||||||
|
// 当前页面宽度相对于 1920宽的缩放比例,可根据自己需要修改。
|
||||||
|
const scale = document.documentElement.clientWidth / 1920 |
||||||
|
// 设置页面根节点字体大小(“Math.min(scale, 2)” 指最高放大比例为2,可根据实际业务需求调整)
|
||||||
|
document.documentElement.style.fontSize = baseSize * Math.min(scale, 2) + 'px' |
||||||
|
} |
||||||
|
// 初始化
|
||||||
|
setRem() |
||||||
|
// 改变窗口大小时重新设置 rem
|
||||||
|
window.onresize = function () { |
||||||
|
setRem() |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
import store from '@/store'; |
||||||
|
import router from '@/router'; |
||||||
|
import generateBtnPermission from '../auth/generateBtnPermission'; |
||||||
|
|
||||||
|
const newRoutes = [] |
||||||
|
|
||||||
|
function createMeta(item){ |
||||||
|
let meta = { title: item.name } |
||||||
|
return meta |
||||||
|
} |
||||||
|
|
||||||
|
function createRoute(data){ |
||||||
|
data.map(e => { |
||||||
|
if(e.select && e.path){ |
||||||
|
let meta = createMeta(e) |
||||||
|
newRoutes.push({ |
||||||
|
name: e.path, |
||||||
|
path: e.path, |
||||||
|
path: () => import(`@/pages/${e.path}.vue`), |
||||||
|
meta |
||||||
|
}) |
||||||
|
} |
||||||
|
e.children && e.children.length && createRoute(e.children) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
export default function(data,path){ |
||||||
|
generateBtnPermission(data) |
||||||
|
createRoute(data) |
||||||
|
store.dispatch('auth/addRoutes',newRoutes) |
||||||
|
// router.addRoutes(routes)
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
import store from '@/store'; |
||||||
|
import router from '@/router'; |
||||||
|
|
||||||
|
export default function(){ |
||||||
|
setTimeout(() => { |
||||||
|
let routes = store.state.auth.routes |
||||||
|
routes.forEach(e => { |
||||||
|
if(e.path == '/'){ |
||||||
|
e.component = () => import('@/layouts/home/index.vue') |
||||||
|
}else{ |
||||||
|
e.component = () => import(`@/pages/${e.path}.vue`) |
||||||
|
} |
||||||
|
|
||||||
|
e.children && e.children.forEach(n => { |
||||||
|
n.path && (n.component = () => import(`@/pages/${n.path}.vue`)) |
||||||
|
}) |
||||||
|
}) |
||||||
|
|
||||||
|
routes.push({ |
||||||
|
path: '*', |
||||||
|
redirect: '404' |
||||||
|
}) |
||||||
|
|
||||||
|
router.addRoutes(routes) |
||||||
|
},500) |
||||||
|
} |
@ -0,0 +1,6 @@ |
|||||||
|
import router from '@/router'; |
||||||
|
|
||||||
|
export default function(){ |
||||||
|
const newRouter = createRouter() |
||||||
|
router.matcher = newRouter.matcher |
||||||
|
} |
@ -0,0 +1,43 @@ |
|||||||
|
import Cookies from 'js-cookie'; |
||||||
|
import Setting from '@/setting'; |
||||||
|
|
||||||
|
const cookies = {}; |
||||||
|
|
||||||
|
/** |
||||||
|
* @description 存储 cookie 值 |
||||||
|
* @param {String} name cookie name |
||||||
|
* @param {String} value cookie value |
||||||
|
* @param {Object} cookieSetting cookie setting |
||||||
|
*/ |
||||||
|
cookies.set = function (name = 'default', value = '', cookieSetting = {}) { |
||||||
|
let currentCookieSetting = { |
||||||
|
expires: Setting.cookiesExpires |
||||||
|
}; |
||||||
|
Object.assign(currentCookieSetting, cookieSetting); |
||||||
|
Cookies.set(`admin-${name}`, value, currentCookieSetting); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* @description 拿到 cookie 值 |
||||||
|
* @param {String} name cookie name |
||||||
|
*/ |
||||||
|
cookies.get = function (name = 'default') { |
||||||
|
return Cookies.get(`admin-${name}`); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* @description 拿到 cookie 全部的值 |
||||||
|
*/ |
||||||
|
cookies.getAll = function () { |
||||||
|
return Cookies.get(); |
||||||
|
}; |
||||||
|
|
||||||
|
/** |
||||||
|
* @description 删除 cookie |
||||||
|
* @param {String} name cookie name |
||||||
|
*/ |
||||||
|
cookies.remove = function (name = 'default') { |
||||||
|
return Cookies.remove(`admin-${name}`); |
||||||
|
}; |
||||||
|
|
||||||
|
export default cookies; |
@ -0,0 +1,83 @@ |
|||||||
|
/** |
||||||
|
* localStorage |
||||||
|
* @调用:_local.set('access_token', '123456', 5000); |
||||||
|
* @调用:_local.get('access_token'); |
||||||
|
*/ |
||||||
|
|
||||||
|
var _local = { |
||||||
|
//存储,可设置过期时间
|
||||||
|
set(key, value, expires) { |
||||||
|
let params = { key, value, expires }; |
||||||
|
if (expires) { |
||||||
|
// 记录何时将值存入缓存,毫秒级
|
||||||
|
var data = Object.assign(params, { startTime: new Date().getTime() }); |
||||||
|
localStorage.setItem(key, JSON.stringify(data)); |
||||||
|
} else { |
||||||
|
if (Object.prototype.toString.call(value) == '[object Object]') { |
||||||
|
value = JSON.stringify(value); |
||||||
|
} |
||||||
|
if (Object.prototype.toString.call(value) == '[object Array]') { |
||||||
|
value = JSON.stringify(value); |
||||||
|
} |
||||||
|
localStorage.setItem(key, value); |
||||||
|
} |
||||||
|
}, |
||||||
|
//取出
|
||||||
|
get(key) { |
||||||
|
let item = localStorage.getItem(key); |
||||||
|
// 先将拿到的试着进行json转为对象的形式
|
||||||
|
try { |
||||||
|
item = JSON.parse(item); |
||||||
|
} catch (error) { |
||||||
|
// eslint-disable-next-line no-self-assign
|
||||||
|
item = item; |
||||||
|
} |
||||||
|
// 如果有startTime的值,说明设置了失效时间
|
||||||
|
if (item && item.startTime) { |
||||||
|
let date = new Date().getTime(); |
||||||
|
|
||||||
|
// 如果大于就是过期了,如果小于或等于就还没过期
|
||||||
|
if (date - item.startTime > item.expires) { |
||||||
|
localStorage.removeItem(key); |
||||||
|
return false; |
||||||
|
} else { |
||||||
|
return item.value; |
||||||
|
} |
||||||
|
} else { |
||||||
|
return item; |
||||||
|
} |
||||||
|
}, |
||||||
|
// 删除
|
||||||
|
remove(key) { |
||||||
|
localStorage.removeItem(key); |
||||||
|
}, |
||||||
|
// 清除全部
|
||||||
|
clear() { |
||||||
|
localStorage.clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* sessionStorage |
||||||
|
*/ |
||||||
|
var _session = { |
||||||
|
get: function (key) { |
||||||
|
var data = sessionStorage[key]; |
||||||
|
if (!data || data === "null") { |
||||||
|
return null; |
||||||
|
} |
||||||
|
return data; |
||||||
|
}, |
||||||
|
set: function (key, value) { |
||||||
|
sessionStorage[key] = value; |
||||||
|
}, |
||||||
|
// 删除
|
||||||
|
remove(key) { |
||||||
|
sessionStorage.removeItem(key); |
||||||
|
}, |
||||||
|
// 清除全部
|
||||||
|
clear() { |
||||||
|
sessionStorage.clear(); |
||||||
|
} |
||||||
|
} |
||||||
|
export { _local, _session } |
@ -0,0 +1,136 @@ |
|||||||
|
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() |
||||||
|
}, |
||||||
|
// 传入文件名和数据,下载文件
|
||||||
|
downloadFileDirect(fileName,data) { |
||||||
|
if ('download' in document.createElement('a')) { // 非IE下载
|
||||||
|
const elink = document.createElement('a') |
||||||
|
elink.download = fileName |
||||||
|
elink.style.display = 'none' |
||||||
|
elink.href = URL.createObjectURL(data) |
||||||
|
document.body.appendChild(elink) |
||||||
|
elink.click() |
||||||
|
URL.revokeObjectURL(elink.href) // 释放URL 对象
|
||||||
|
document.body.removeChild(elink) |
||||||
|
} else { // IE10+下载
|
||||||
|
navigator.msSaveBlob(data, fileName) |
||||||
|
} |
||||||
|
}, |
||||||
|
// 成功提示
|
||||||
|
successMsg(message,duration = 3000) { |
||||||
|
return Message.success({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) |
||||||
|
}, |
||||||
|
// 警告提示
|
||||||
|
warningMsg(message,duration = 3000) { |
||||||
|
return Message.warning({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) |
||||||
|
}, |
||||||
|
// 错误提示
|
||||||
|
errorMsg(message,duration = 3000) { |
||||||
|
return Message.error({message,showClose: true,offset: (document.documentElement.clientHeight - 40) / 2,duration}) |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
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,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,404 @@ |
|||||||
|
<template> |
||||||
|
<div class="wrap"> |
||||||
|
<img class="sth bg" src="@/assets/img/integrated-counter-bg.png" alt=""> |
||||||
|
<img class="sth guide" src="@/assets/img/guide.png" alt=""> |
||||||
|
<img class="sth man" src="@/assets/img/man.png" alt=""> |
||||||
|
<img class="sth counter" src="@/assets/img/counter.png" alt=""> |
||||||
|
<img class="sth glass" src="@/assets/img/glass.png" alt=""> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper"> |
||||||
|
<div slot="content"> |
||||||
|
<img style="height: 145px" src="@/assets/img/tooltip/system.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth computer cp" src="@/assets/img/computer.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="50"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/cpl.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth summons cp" src="@/assets/img/summons.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top-start" popper-class="sth-popper" offset="250"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/ptpzx.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth voucher-box cp" src="@/assets/img/voucher-box.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
|
||||||
|
<el-tooltip placement="top-start" popper-class="sth-popper" offset="250"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/zk.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth important cp" src="@/assets/img/important.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="left-start" popper-class="sth-popper"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/qx.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth money-box cp" src="@/assets/img/money-box.png" alt="" @click="showData('钱箱')"> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="-100"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/yzh.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth seal-box cp" src="@/assets/img/seal-box.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="-100"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/ycj.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth currency-detector cp" src="@/assets/img/currency-detector.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="-400"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/dyj.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth printer cp" src="@/assets/img/printer.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="50"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/mmq.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth cipher-machine cp" src="@/assets/img/cipher-machine.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<img class="sth employee" src="@/assets/img/employee.png" alt=""> |
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="50"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/skj.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth card-machine cp" src="@/assets/img/card-machine.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<el-tooltip placement="top" popper-class="sth-popper" offset="-100"> |
||||||
|
<div slot="content"> |
||||||
|
<img src="@/assets/img/tooltip/sfz.png" alt=""> |
||||||
|
</div> |
||||||
|
<img class="sth idCard-scanner cp" src="@/assets/img/idCard-scanner.png" alt=""> |
||||||
|
</el-tooltip> |
||||||
|
|
||||||
|
<div class="goods-dia" :class="{active: showGoods}"> |
||||||
|
<img src="@/assets/img/idCard.png" alt=""> |
||||||
|
<img src="@/assets/img/open-account.png" alt=""> |
||||||
|
<img src="@/assets/img/cash.png" alt=""> |
||||||
|
</div> |
||||||
|
<div class="goods" :class="{active: showGoods}" @click="toggleGoods"> |
||||||
|
<span>物品栏</span> |
||||||
|
<img class="icon" src="@/assets/svg/arrow-right.svg" alt=""> |
||||||
|
</div> |
||||||
|
|
||||||
|
<el-dialog :visible.sync="dataVisible" width="1280px" @close="closeData" :close-on-click-modal="false" :show-close="false" custom-class="data-dia"> |
||||||
|
<div slot="title" class="dia-header"> |
||||||
|
<div class="data-title">{{dataTitle}}</div> |
||||||
|
<img class="close" src="@/assets/svg/close.svg" alt="" @click="closeDataDia"> |
||||||
|
</div> |
||||||
|
<p class="tips">- 请单击选中所需材料、双击可放大预览 -</p> |
||||||
|
<ul class="list"> |
||||||
|
<li :class="{checked: checkList.includes(1)}" @click="checkData(1)"> |
||||||
|
<img src="@/assets/img/idCard-sm.png" alt=""> |
||||||
|
<p>身份证</p> |
||||||
|
</li> |
||||||
|
<li :class="{checked: checkList.includes(2)}" @click="checkData(2)"> |
||||||
|
<img src="@/assets/img/idCard-copy-sm.png" alt=""> |
||||||
|
<p>身份证复印件</p> |
||||||
|
</li> |
||||||
|
<li :class="{checked: checkList.includes(3)}" @click="checkData(3)"> |
||||||
|
<img style="margin-top: 0" src="@/assets/img/open-account-apply-sm.png" alt=""> |
||||||
|
<p>开户申请书</p> |
||||||
|
</li> |
||||||
|
<li :class="{checked: checkList.includes(4)}" @click="checkData(4)"> |
||||||
|
<img style="margin-top: 32px" src="@/assets/img/cash-sm.png" alt=""> |
||||||
|
<p>现金</p> |
||||||
|
</li> |
||||||
|
</ul> |
||||||
|
<div class="dia-footer"> |
||||||
|
<button type="button">确定</button> |
||||||
|
</div> |
||||||
|
</el-dialog> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import { mapState } from 'vuex' |
||||||
|
export default { |
||||||
|
name: 'index', |
||||||
|
data() { |
||||||
|
return { |
||||||
|
showGoods: false, |
||||||
|
dataTitle: '', |
||||||
|
dataVisible: false, |
||||||
|
checkList: [] |
||||||
|
} |
||||||
|
}, |
||||||
|
watch: { |
||||||
|
|
||||||
|
}, |
||||||
|
mounted() { |
||||||
|
|
||||||
|
}, |
||||||
|
methods: { |
||||||
|
toggleGoods(){ |
||||||
|
this.showGoods = !this.showGoods |
||||||
|
}, |
||||||
|
showData(type){ |
||||||
|
this.dataTitle = type |
||||||
|
this.dataVisible = true |
||||||
|
}, |
||||||
|
checkData(id){ |
||||||
|
this.checkList.includes(id) ? this.checkList.splice(this.checkList.indexOf(id),1) : this.checkList.push(id) |
||||||
|
}, |
||||||
|
closeDataDia(){ |
||||||
|
this.dataVisible = false |
||||||
|
}, |
||||||
|
closeData(){ |
||||||
|
this.checkList = [] |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.wrap{ |
||||||
|
// position: relative; |
||||||
|
// min-height: calc(100vh - 68px); |
||||||
|
|
||||||
|
.sth{ |
||||||
|
position: absolute; |
||||||
|
&.cp{ |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
.guide{ |
||||||
|
top: 90px; |
||||||
|
left: 0; |
||||||
|
width: 222px; |
||||||
|
cursor: pointer; |
||||||
|
&:hover{ |
||||||
|
opacity: .9; |
||||||
|
} |
||||||
|
} |
||||||
|
.bg{ |
||||||
|
top: 0; |
||||||
|
left: 0; |
||||||
|
width: 100%; |
||||||
|
} |
||||||
|
.counter{ |
||||||
|
top: 116px; |
||||||
|
left: 357px; |
||||||
|
width: 1555px; |
||||||
|
} |
||||||
|
.glass{ |
||||||
|
top: -135px; |
||||||
|
left: 956px; |
||||||
|
width: 50%; |
||||||
|
} |
||||||
|
.employee{ |
||||||
|
top: 371px; |
||||||
|
left: 920px; |
||||||
|
width: 388px; |
||||||
|
} |
||||||
|
.man{ |
||||||
|
top: 82px; |
||||||
|
right: 150px; |
||||||
|
width: 262px; |
||||||
|
} |
||||||
|
.money-box{ |
||||||
|
top: 406px; |
||||||
|
left: 445px; |
||||||
|
width: 197px; |
||||||
|
} |
||||||
|
.important{ |
||||||
|
top: 372px; |
||||||
|
left: 582px; |
||||||
|
width: 175px; |
||||||
|
} |
||||||
|
.voucher-box{ |
||||||
|
top: 216px; |
||||||
|
left: 718px; |
||||||
|
width: 160px; |
||||||
|
} |
||||||
|
.summons{ |
||||||
|
top: 250px; |
||||||
|
left: 844px; |
||||||
|
width: 139px; |
||||||
|
} |
||||||
|
.computer{ |
||||||
|
top: 120px; |
||||||
|
left: 955px; |
||||||
|
width: 219px; |
||||||
|
} |
||||||
|
.card-machine{ |
||||||
|
top: 377px; |
||||||
|
left: 1147px; |
||||||
|
width: 110px; |
||||||
|
} |
||||||
|
.idCard-scanner{ |
||||||
|
top: 443px; |
||||||
|
left: 1229px; |
||||||
|
width: 82px; |
||||||
|
} |
||||||
|
.seal-box{ |
||||||
|
top: 486px; |
||||||
|
left: 1340px; |
||||||
|
width: 97px; |
||||||
|
} |
||||||
|
.currency-detector{ |
||||||
|
top: 492px; |
||||||
|
left: 1421px; |
||||||
|
width: 151px; |
||||||
|
} |
||||||
|
.printer{ |
||||||
|
top: 550px; |
||||||
|
left: 1531px; |
||||||
|
width: 205px; |
||||||
|
} |
||||||
|
.cipher-machine{ |
||||||
|
top: 324px; |
||||||
|
left: 1298px; |
||||||
|
width: 100px; |
||||||
|
} |
||||||
|
|
||||||
|
.goods{ |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
display: flex; |
||||||
|
flex-direction: column; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 94px; |
||||||
|
height: 200px; |
||||||
|
cursor: pointer; |
||||||
|
background: url(../../../assets/img/sth-bg.png) 0 0/cover no-repeat; |
||||||
|
span{ |
||||||
|
width: 30px; |
||||||
|
margin-bottom: 10px; |
||||||
|
color: #fff; |
||||||
|
font-size: 30px; |
||||||
|
text-align: center; |
||||||
|
} |
||||||
|
.icon{ |
||||||
|
width: 30px; |
||||||
|
transition: all .5s; |
||||||
|
} |
||||||
|
&:hover{ |
||||||
|
opacity: .9; |
||||||
|
} |
||||||
|
&.active{ |
||||||
|
.icon{ |
||||||
|
transform: rotate(180deg); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.goods-dia{ |
||||||
|
display: flex; |
||||||
|
position: fixed; |
||||||
|
bottom: 0; |
||||||
|
left: -100%; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
width: 100%; |
||||||
|
padding: 20px 0; |
||||||
|
transition: all .5s; |
||||||
|
background-color: rgba(255,255,255,.7); |
||||||
|
&.active{ |
||||||
|
left: 0; |
||||||
|
} |
||||||
|
img{ |
||||||
|
margin-right: 50px; |
||||||
|
&:last-child{ |
||||||
|
margin-right: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
/deep/.data-dia{ |
||||||
|
border-radius: 16px; |
||||||
|
.el-dialog__header{ |
||||||
|
padding: 0; |
||||||
|
border-bottom: 0; |
||||||
|
.dia-header{ |
||||||
|
position: relative; |
||||||
|
.data-title{ |
||||||
|
width: 300px; |
||||||
|
margin: 0 auto; |
||||||
|
line-height: 72px; |
||||||
|
text-align: center; |
||||||
|
color: #fff; |
||||||
|
font-size: 24px; |
||||||
|
background: url(../../../assets/img/dia-title.png) 0 0/cover no-repeat; |
||||||
|
} |
||||||
|
.close{ |
||||||
|
position: absolute; |
||||||
|
top: 15px; |
||||||
|
right: 15px; |
||||||
|
cursor: pointer; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.tips{ |
||||||
|
margin: 20px 0 100px; |
||||||
|
text-align: center; |
||||||
|
font-size: 20px; |
||||||
|
color: #000; |
||||||
|
} |
||||||
|
.list{ |
||||||
|
width: 940px; |
||||||
|
margin: 0 auto; |
||||||
|
display: flex; |
||||||
|
justify-content: space-between; |
||||||
|
align-items: center; |
||||||
|
li{ |
||||||
|
position: relative; |
||||||
|
width: 204px; |
||||||
|
height: 204px; |
||||||
|
text-align: center; |
||||||
|
background: url(../../../assets/img/data-frame.png) 0 0/cover no-repeat; |
||||||
|
cursor: pointer; |
||||||
|
img{ |
||||||
|
margin-top: 45px; |
||||||
|
} |
||||||
|
p{ |
||||||
|
position: absolute; |
||||||
|
bottom: 0; |
||||||
|
width: 100%; |
||||||
|
line-height: 54px; |
||||||
|
text-align: center; |
||||||
|
font-size: 18px; |
||||||
|
color: #000; |
||||||
|
} |
||||||
|
&.checked{ |
||||||
|
background: url(../../../assets/img/data-frame-checked.png) 0 0/cover no-repeat, |
||||||
|
url(../../../assets/svg/checked.svg) 165px 7%/auto no-repeat; |
||||||
|
p{ |
||||||
|
color: #fff; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
.dia-footer{ |
||||||
|
margin-top: 140px; |
||||||
|
text-align: center; |
||||||
|
button{ |
||||||
|
width: 300px; |
||||||
|
line-height: 60px; |
||||||
|
color: #fff; |
||||||
|
font-size: 24px; |
||||||
|
background-color: rgb(81,147,255); |
||||||
|
border: 0; |
||||||
|
border-radius: 20px; |
||||||
|
cursor: pointer; |
||||||
|
&:hover{ |
||||||
|
opacity: .9; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,25 @@ |
|||||||
|
/** |
||||||
|
* @description 鉴权指令 |
||||||
|
* 当传入的权限当前用户没有时,会移除该组件 |
||||||
|
* 用例:<Tag v-auth>text</Tag> 或者:<Tag v-auth="'user:编辑'">text</Tag> |
||||||
|
* */ |
||||||
|
import store from '@/store' |
||||||
|
|
||||||
|
export default { |
||||||
|
inserted (el, binding, vnode) { |
||||||
|
let btnText = '' |
||||||
|
if(binding.value){ |
||||||
|
btnText = binding.value |
||||||
|
}else{ |
||||||
|
btnText = `${vnode.context.$route.path}:${el.innerText}` |
||||||
|
} |
||||||
|
const btnPermissions = store.state.auth.btns |
||||||
|
|
||||||
|
if (btnText && btnPermissions && btnPermissions.length) { |
||||||
|
const isPermission = btnPermissions.includes(btnText) |
||||||
|
if (!isPermission) { |
||||||
|
el.parentNode && el.parentNode.removeChild(el) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
/** |
||||||
|
* @description 返回缺省值 |
||||||
|
* 传入的如果是null,就返回'--' |
||||||
|
* 用例:<Tag :default="val">text</Tag> 或者:<Tag>{{val | default}}</Tag> |
||||||
|
* */ |
||||||
|
const defaultShow = (val) => { |
||||||
|
return val == null ? '--' : val |
||||||
|
} |
||||||
|
|
||||||
|
module.exports = { |
||||||
|
defaultShow |
||||||
|
} |
@ -0,0 +1,14 @@ |
|||||||
|
/** |
||||||
|
* 插件 |
||||||
|
* */ |
||||||
|
|
||||||
|
import directiveAuth from '@/plugins/auth'; |
||||||
|
import throttle from '@/plugins/throttle'; |
||||||
|
|
||||||
|
export default { |
||||||
|
async install (Vue, options) { |
||||||
|
// 指令
|
||||||
|
Vue.directive('auth', directiveAuth); |
||||||
|
Vue.directive('throttle', throttle); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,146 @@ |
|||||||
|
import axios from 'axios' |
||||||
|
import util from '@/libs/util' |
||||||
|
import router from '@/router/index' |
||||||
|
import Setting from '@/setting' |
||||||
|
import store from '@/store' |
||||||
|
|
||||||
|
const service = axios.create({ |
||||||
|
baseURL: Setting.apiBaseURL, |
||||||
|
timeout: 10000000 |
||||||
|
}) |
||||||
|
// post请求头
|
||||||
|
service.defaults.headers.post['Content-Type'] = 'application/json;charset=UTF-8' |
||||||
|
|
||||||
|
// 请求拦截器
|
||||||
|
service.interceptors.request.use(config => { |
||||||
|
let token = util.local.get(Setting.tokenKey) |
||||||
|
if(token) config.headers.token = token |
||||||
|
let storeSchoolId = store.state.user.schoolId |
||||||
|
let routeSchoolId = router.app._route.query.schoolId |
||||||
|
if(routeSchoolId) routeSchoolId = atob(decodeURI(routeSchoolId)) |
||||||
|
config.headers.schoolId = storeSchoolId ? storeSchoolId : routeSchoolId |
||||||
|
return config |
||||||
|
},err => { |
||||||
|
util.errorMsg({ |
||||||
|
message: '退出登陆', |
||||||
|
onClose: function () { |
||||||
|
router.push({name: '/login'}) |
||||||
|
} |
||||||
|
}) |
||||||
|
return Promise.reject(err) |
||||||
|
}) |
||||||
|
|
||||||
|
// 响应拦截器
|
||||||
|
service.interceptors.response.use( |
||||||
|
response => { |
||||||
|
const res = response.data |
||||||
|
if(res.status == 200) { |
||||||
|
return Promise.resolve(res).catch(e => {}) |
||||||
|
}else if(!res.status){ |
||||||
|
return Promise.resolve(res).catch(e => {}) |
||||||
|
}else { |
||||||
|
util.errorMsg(res.message) |
||||||
|
return Promise.reject(res) |
||||||
|
} |
||||||
|
}, |
||||||
|
// 服务器状态码不是200的情况
|
||||||
|
error => { |
||||||
|
if (error.response.status) { |
||||||
|
switch (error.response.status) { |
||||||
|
// 401: 未登录
|
||||||
|
// 未登录则跳转登录页面,并携带当前页面的路径
|
||||||
|
// 在登录成功后返回当前页面,这一步需要在登录页操作。
|
||||||
|
case 401: |
||||||
|
util.local.remove(Setting.storeKey) |
||||||
|
util.local.remove(Setting.tokenKey) |
||||||
|
util.errorMsg('登录过期,请重新登录') |
||||||
|
setTimeout(() => { |
||||||
|
router.replace({ |
||||||
|
path: '/login', |
||||||
|
query: { |
||||||
|
redirect: router.currentRoute.fullPath |
||||||
|
} |
||||||
|
}) |
||||||
|
}, 1000) |
||||||
|
break |
||||||
|
case 500: |
||||||
|
util.errorMsg('网络错误') |
||||||
|
break |
||||||
|
// 403 token过期
|
||||||
|
// 登录过期对用户进行提示
|
||||||
|
// 清除本地token和清空vuex中token对象
|
||||||
|
// 跳转登录页面
|
||||||
|
case 403: |
||||||
|
util.local.remove(Setting.storeKey) |
||||||
|
util.local.remove(Setting.tokenKey) |
||||||
|
util.errorMsg('登录过期,请重新登录') |
||||||
|
// 清除token
|
||||||
|
// store.commit('loginSuccess', null);
|
||||||
|
// 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
|
||||||
|
setTimeout(() => { |
||||||
|
router.replace({ |
||||||
|
path: '/login', |
||||||
|
query: { |
||||||
|
redirect: router.currentRoute.fullPath |
||||||
|
} |
||||||
|
}) |
||||||
|
}, 1000) |
||||||
|
break |
||||||
|
// 404请求不存在
|
||||||
|
case 404: |
||||||
|
util.errorMsg('网络请求不存在!') |
||||||
|
break |
||||||
|
// 其他错误,直接抛出错误提示
|
||||||
|
default: |
||||||
|
util.errorMsg(error.response.data.message) |
||||||
|
Promise.reject(res) |
||||||
|
} |
||||||
|
return Promise.reject(error.response) |
||||||
|
} |
||||||
|
} |
||||||
|
); |
||||||
|
|
||||||
|
function get(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
service.get(url, {params: params}).then(res => { |
||||||
|
resolve(res) |
||||||
|
}).catch(err => { |
||||||
|
reject(err) |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function post(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
service.post(url,params).then(res => { |
||||||
|
resolve(res) |
||||||
|
}).catch(err => { |
||||||
|
reject(err.data) |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function del(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
service.delete(url, { |
||||||
|
params |
||||||
|
}).then(res => { |
||||||
|
resolve(res) |
||||||
|
}).catch(err => { |
||||||
|
reject(err.data) |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
function put(url, params){ |
||||||
|
return new Promise((resolve, reject) =>{ |
||||||
|
service.put(url, { |
||||||
|
params |
||||||
|
}).then(res => { |
||||||
|
resolve(res) |
||||||
|
}).catch(err => { |
||||||
|
reject(err.data) |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
export { get,post,del,put } |
@ -0,0 +1,18 @@ |
|||||||
|
/** |
||||||
|
* @description 节流指令 |
||||||
|
* 限制连续快速点击按钮 |
||||||
|
* 用例:<Tag v-throttle>text</Tag> |
||||||
|
* */ |
||||||
|
|
||||||
|
export default{ |
||||||
|
inserted (el, binding, vnode) { |
||||||
|
el.addEventListener('click', () => { |
||||||
|
if (!el.disabled) { |
||||||
|
el.disabled = true |
||||||
|
setTimeout(() => { |
||||||
|
el.disabled = false |
||||||
|
}, binding.value || 1000) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,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: '数据统计' } |
||||||
|
}, |
||||||
|
] |
||||||
|
}; |