This commit is contained in:
wangjinlei
2020-11-06 16:55:29 +08:00
parent 0b21db11dc
commit 3c2f2de6de
80 changed files with 22382 additions and 27 deletions

View File

@@ -0,0 +1,231 @@
<template>
<div class="header">
<!-- 折叠按钮 -->
<div class="collapse-btn" @click="collapseChage">
<i v-if="!collapse" class="el-icon-s-fold"></i>
<i v-else class="el-icon-s-unfold"></i>
</div>
<div class="logo">
<img src="../../assets/img/logo.png" />
{{$t('system.title')}}
</div>
<div class="header-right">
<div class="header-user-con">
<div class="changelang">
<el-dropdown trigger="click" @command="chengelang">
<span class="el-dropdown-link">
language
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="en">english</el-dropdown-item>
<el-dropdown-item command="zh">中文简体</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<!-- 全屏显示 -->
<div class="btn-fullscreen" @click="handleFullScreen">
<el-tooltip
effect="dark"
:content="fullscreen?$t('system.noscreen'):$t('system.screen')"
placement="bottom"
>
<i class="el-icon-rank"></i>
</el-tooltip>
</div>
<!-- 消息中心 -->
<!-- 用户头像 -->
<div class="user-avator">
<img src="../../assets/img/img.jpg" />
</div>
<!-- 用户名下拉菜单 -->
<el-dropdown class="user-name" trigger="click" @command="handleCommand">
<span class="el-dropdown-link">
{{username}}
<i class="el-icon-caret-bottom"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item divided command="loginout">{{$t('system.loyout')}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</div>
</template>
<script>
import bus from '../common/bus';
export default {
data() {
return {
collapse: false,
fullscreen: false,
name: 'unknown user',
message: 2,
langArr: [
{ value: 'zh', label: '中文' },
{ value: 'en', label: 'English' }
]
};
},
computed: {
username() {
let username = localStorage.getItem('ms_username');
return username ? username : this.name;
},
userrole(){
let userrole = localStorage.getItem('ms_userrole');
if(userrole==1){
return this.$t('total.author');
}else if(userrole==2){
return this.$t('total.editor');
}else if(userrole=='admin'){
return this.$t('total.admin');
}else{
return this.$t('total.reviewers');
}
}
},
methods: {
// 用户名下拉菜单选择事件
handleCommand(command) {
if (command == 'loginout') {
localStorage.removeItem('ms_username');
localStorage.removeItem('ms_userrole');
this.$router.push('/login');
}
},
// 侧边栏折叠
collapseChage() {
this.collapse = !this.collapse;
bus.$emit('collapse', this.collapse);
},
// 全屏事件
handleFullScreen() {
let element = document.documentElement;
if (this.fullscreen) {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.webkitCancelFullScreen) {
document.webkitCancelFullScreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
} else {
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.webkitRequestFullScreen) {
element.webkitRequestFullScreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.msRequestFullscreen) {
// IE11
element.msRequestFullscreen();
}
}
this.fullscreen = !this.fullscreen;
},
//切换语言
chengelang(commond){
localStorage.setItem('langs',commond);
this.$router.go(0);
}
},
mounted() {
if (document.body.clientWidth < 1000) {
this.collapseChage();
}
}
};
</script>
<style scoped>
.header {
position: relative;
box-sizing: border-box;
width: 100%;
height: 70px;
font-size: 22px;
color: #fff;
}
.collapse-btn {
float: left;
padding: 0 21px;
cursor: pointer;
line-height: 70px;
}
.header .logo {
float: left;
width: 350px;
vertical-align: middle;
line-height: 70px;
}
.header .logo img {
width: 90px;
height: 25px;
vertical-align: middle;
}
.header-right {
float: right;
padding-right: 50px;
}
.header-user-con {
display: flex;
height: 70px;
align-items: center;
}
.btn-fullscreen {
transform: rotate(45deg);
margin-right: 5px;
font-size: 24px;
}
.changelang {
position: relative;
width: 90px;
height: 30px;
}
.btn-fullscreen {
position: relative;
width: 30px;
height: 30px;
text-align: center;
border-radius: 15px;
cursor: pointer;
}
.btn-bell-badge {
position: absolute;
right: 0;
top: -2px;
width: 8px;
height: 8px;
border-radius: 4px;
background: #f56c6c;
color: #fff;
}
.btn-bell .el-icon-bell {
color: #fff;
}
.user-name {
margin-left: 10px;
}
.user-avator {
margin-left: 20px;
}
.user-avator img {
display: block;
width: 40px;
height: 40px;
border-radius: 50%;
}
.el-dropdown-link {
color: #fff;
cursor: pointer;
}
.el-dropdown-menu__item {
text-align: center;
}
#colgreen{
color: rgb(142, 150, 74);
}
</style>

View File

@@ -0,0 +1,51 @@
<template>
<div class="wrapper">
<v-head></v-head>
<v-sidebar></v-sidebar>
<div class="content-box" :class="{'content-collapse':collapse}">
<v-tags></v-tags>
<div class="content">
<transition name="move" mode="out-in">
<keep-alive :include="tagsList">
<router-view></router-view>
</keep-alive>
</transition>
<el-backtop target=".content"></el-backtop>
</div>
</div>
</div>
</template>
<script>
import vHead from './Header.vue';
import vSidebar from './Sidebar.vue';
import vTags from './Tags.vue';
import bus from './bus';
export default {
data() {
return {
tagsList: [],
collapse: false
};
},
components: {
vHead,
vSidebar,
vTags
},
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>

View File

@@ -0,0 +1,272 @@
<template>
<div class="sidebar">
<el-menu
class="sidebar-el-menu"
:default-active="onRoutes"
:collapse="collapse"
background-color="#324157"
text-color="#bfcbd9"
active-text-color="#20a0ff"
unique-opened
router
>
<template v-for="item in items">
<template v-if="item.subs">
<el-submenu :index="item.index" :key="item.index">
<template slot="title">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</template>
<template v-for="subItem in item.subs">
<el-submenu
v-if="subItem.subs"
:index="subItem.index"
:key="subItem.index"
>
<template slot="title">{{ subItem.title }}</template>
<el-menu-item
v-for="(threeItem,i) in subItem.subs"
:key="i"
:index="threeItem.index"
>{{ threeItem.title }}</el-menu-item>
</el-submenu>
<el-menu-item
v-else
:index="subItem.index"
:key="subItem.index"
>{{ subItem.title }}</el-menu-item>
</template>
</el-submenu>
</template>
<template v-else>
<el-menu-item :index="item.index" :key="item.index">
<i :class="item.icon"></i>
<span slot="title">{{ item.title }}</span>
</el-menu-item>
</template>
</template>
</el-menu>
</div>
</template>
<script>
import bus from '../common/bus';
export default {
data() {
return {
collapse: false,
userrole:localStorage.getItem('ms_userrole'),
items:[],
author_items: [
{
icon: 'el-icon-lx-home',
index: 'dashboard',
title: this.$t('sidebar.main')
},
{
icon: 'el-icon-lx-cascades',
index: '1',
title: this.$t('sidebar.author'),
subs:[
{
index:'articleList',
title:this.$t('sidebar.author1')
},
{
index:'articleAdd',
title:this.$t('sidebar.author2')
}
]
},
{
icon: 'el-icon-user',
index: '2',
title: this.$t('sidebar.reviewerArticle'),
subs:[
{
index:'authorApplyReviewer',
title:this.$t('sidebar.authorApplyReviewer')
}
]
}
],
editor_items:[
{
icon: 'el-icon-lx-home',
index: 'dashboard',
title: this.$t('sidebar.main')
},
{
icon: 'el-icon-lx-copy',
index: '2',
title: this.$t('sidebar.editor'),
subs:[
{
index:'articleListEditor',
title:this.$t('sidebar.editor1')
}
]
},
{
icon:'el-icon-s-custom',
index:'3',
title:this.$t('sidebar.reviewer'),
subs:[
{
index:'reviewerApplyList',
title:this.$t('sidebar.reviewer1')
},
{
index:'reviewerList',
title:this.$t('sidebar.reviewer2')
},
{
index:'reviewerImport',
title:this.$t('sidebar.reviewer3')
}
]
}
],
admin_items:[
{
icon: 'el-icon-lx-home',
index: 'dashboard',
title: this.$t('sidebar.main')
},
{
icon: 'el-icon-user',
index: '2',
title: this.$t('sidebar.editormanage'),
subs:[
{
index:'editorList',
title:this.$t('sidebar.editormanage1')
},
{
index:'editorAdd',
title:this.$t('sidebar.editormanage2')
}
]
},
{
icon:'el-icon-notebook-1',
index:'3',
title:this.$t('sidebar.journal'),
subs:[
{
index:'journalList',
title:this.$t('sidebar.journal1')
},
{
index:'journalAdd',
title:this.$t('sidebar.journal2')
}
]
},
{
icon:'el-icon-search',
index:'4',
title:this.$t('sidebar.monitor'),
subs:[
{
index:'monitorManuscript',
title:this.$t('sidebar.monitor1')
},
]
}
// {
// icon:'el-icon-user-solid',
// index:'4',
// title:this.$t('sidebar.reviewer'),
// subs:[
// {
// index:'adminImportReviewer',
// title:this.$t('sidebar.reviewerimport')
// },
// {
// index:'adminImportreviewerError',
// title:this.$t('sidebar.reviewerimporterror')
// }
// ]
// }
],
reviewer_items:[
{
icon: 'el-icon-lx-home',
index: 'dashboard',
title: this.$t('sidebar.main')
},
{
icon: 'el-icon-lx-cascades',
index: '1',
title: this.$t('sidebar.author'),
subs:[
{
index:'articleList',
title:this.$t('sidebar.author1')
},
{
index:'articleAdd',
title:this.$t('sidebar.author2')
}
]
},
{
icon: 'el-icon-user',
index: '2',
title: this.$t('sidebar.reviewerArticle'),
subs:[
{
index:'reviewerArticleList',
title:this.$t('sidebar.reviewerArticle1')
}
]
}
]
};
},
computed: {
onRoutes() {
return this.$route.path.replace('/', '');
}
},
created() {
if(this.userrole==1){
this.items = this.author_items;
}else if(this.userrole ==2){
this.items = this.editor_items;
}else if(this.userrole=='admin'){
this.items = this.admin_items;
}else if(this.userrole=='reviewer'){
this.items = this.reviewer_items;
}
// 通过 Event Bus 进行组件间通信,来折叠侧边栏
bus.$on('collapse', msg => {
this.collapse = msg;
bus.$emit('collapse-content', msg);
});
}
};
</script>
<style scoped>
.sidebar {
display: block;
position: absolute;
left: 0;
top: 70px;
bottom: 0;
overflow-y: scroll;
}
.sidebar::-webkit-scrollbar {
width: 0;
}
.sidebar-el-menu:not(.el-menu--collapse) {
width: 250px;
}
.sidebar > ul {
height: 100%;
}
</style>

View File

@@ -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">
{{$t('system.label')}}<i class="el-icon-arrow-down el-icon--right"></i>
</el-button>
<el-dropdown-menu size="small" slot="dropdown">
<el-dropdown-item command="other">{{$t('system.labelother')}}</el-dropdown-item>
<el-dropdown-item command="all">{{$t('system.labelall')}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
<script>
import bus from './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: 120px;
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>

View File

@@ -0,0 +1,6 @@
import Vue from 'vue';
// 使用 Event Bus
const bus = new Vue();
export default bus;

View File

@@ -0,0 +1,10 @@
<script>
// const baseUrl = '/';
// const mediaUrl = 'http://api.tmrjournals.com/public/';
const mediaUrl = 'http://www.tougao.com/';
const baseUrl = 'http://www.tougao.com/';
export default {
baseUrl,
mediaUrl
}
</script>

View File

@@ -0,0 +1,80 @@
import Vue from 'vue';
// v-dialogDrag: 弹窗拖拽属性
Vue.directive('dialogDrag', {
bind(el, binding, vnode, oldVnode) {
const dialogHeaderEl = el.querySelector('.el-dialog__header');
const dragDom = el.querySelector('.el-dialog');
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
const sty = (() => {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr];
} else {
return (dom, attr) => getComputedStyle(dom, false)[attr];
}
})()
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft;
const disY = e.clientY - dialogHeaderEl.offsetTop;
const screenWidth = document.body.clientWidth; // body当前宽度
const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度可某些环境下无法获取)
const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
const dragDomheight = dragDom.offsetHeight; // 对话框高度
const minDragDomLeft = dragDom.offsetLeft;
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
const minDragDomTop = dragDom.offsetTop;
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
// 获取到的值带px 正则匹配替换
let styL = sty(dragDom, 'left');
let styT = sty(dragDom, 'top');
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
} else {
styL = +styL.replace(/\px/g, '');
styT = +styT.replace(/\px/g, '');
};
document.onmousemove = function (e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX;
let top = e.clientY - disY;
// 边界处理
if (-(left) > minDragDomLeft) {
left = -(minDragDomLeft);
} else if (left > maxDragDomLeft) {
left = maxDragDomLeft;
}
if (-(top) > minDragDomTop) {
top = -(minDragDomTop);
} else if (top > maxDragDomTop) {
top = maxDragDomTop;
}
// 移动当前元素
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
};
document.onmouseup = function (e) {
document.onmousemove = null;
document.onmouseup = null;
};
}
}
})

View File

@@ -0,0 +1,7 @@
import en from './langs/en';
import zh from './langs/zh';
export const messages = {
'zh': zh,
'en': en
}

View File

@@ -0,0 +1,68 @@
const en = {
system: {
title: 'Submission System',
repassword:'Forgot your password?',
register:'Register now',
login:'Log in',
forgetpwd:'Find Your Password',
screen:'full screen',
noscreen:'Cancel full screen',
loyout:'Log out',
langbtn:'language',
label:'Label options',
labelother:'close other',
labelall:'close all'
},
total:{
author:'author',
editor:'editor',
reviewers:'reviewer',
admin:'admin'
},
sidebar:{
main:'Home Page',
author:'Author',
author1:'My manuscript',
author2:'Submit manuscript',
editor:'Editor',
editor1:'Manuscript list',
editormanage:'Editor Management',
editormanage1:'Editor list',
editormanage2:'Add editor',
journal:'Journal Management',
journal1:'Journal list',
journal2:'Add journal',
reviewer:'Reviewer Management',
reviewer1:'Reviewer application list',
reviewer2:'Reviewer list',
reviewer3:'Reviewer import',
reviewer4:'Import error',
reviewerArticle:'Reviewer',
reviewerArticle1:'Manuscript list',
authorApplyReviewer:'Become reviewer',
reviewerimport:'Reviewer import',
reviewerimporterror:'import error',
monitor:'Monitor',
monitor1:'Manuscript situation'
},
home:{
authortop:'Author guide',
usermsg:'New messages',
},
artstate:{
state0:'Received',
state1:'With editor',
state2:'Under review',
state3:'Reject',
state4:'Revision',
state5:'Accepted ',
act1:'Dealing',
act2:'Finished'
},
}
export default en;

View File

@@ -0,0 +1,68 @@
const zh = {
system: {
title: '投稿系统',
repassword:'忘记密码',
register:'注册',
login:'登录',
forgetpwd:'找回密码',
screen:'全屏',
noscreen:'取消全屏',
loyout:'退出登录',
langbtn:'语言选择',
label:'标签选项',
labelother:'关闭其他',
labelall:'关闭所有'
},
total:{
author:'作者',
editor:'编辑',
reviewers:'审稿人',
admin:'管理员'
},
sidebar:{
main:'系统首页',
author:'作者',
author1:'我的稿件',
author2:'新增稿件',
editor:'编辑',
editor1:'待审稿件',
editormanage:'编辑管理',
editormanage1:'编辑列表',
editormanage2:'添加编辑',
journal:'期刊管理',
journal1:'期刊列表',
journal2:'添加期刊',
reviewer:'审稿人管理',
reviewer1:'申请列表',
reviewer2:'审稿人列表',
reviewer3:'审稿人导入',
reviewer4:'导入失败列表',
reviewerArticle:'审稿人',
reviewerArticle1:'待审文章',
authorApplyReviewer:'成为审稿人',
reviewerimport:'审稿人导入',
reviewerimporterror:'导入失败列表',
monitor:'总监',
monitor1:'稿件情况'
},
home:{
authortop:'用户指南',
usermsg:'新消息',
},
artstate:{
state0:'投稿中',
state1:'已受理',
state2:'送审中',
state3:'拒稿',
state4:'退修',
state5:'接收 ',
act1:'审查中',
act2:'已完结'
},
}
export default zh;