project init
This commit is contained in:
198
src/page/index/index.vue
Normal file
198
src/page/index/index.vue
Normal file
@@ -0,0 +1,198 @@
|
||||
<template>
|
||||
<div class="avue-contail" :class="{ 'avue--collapse': isCollapse }" v-if="isRouterAlive">
|
||||
<div class="avue-header">
|
||||
<!-- 顶部导航栏 -->
|
||||
<top ref="top" />
|
||||
<div class="avue-helpText" v-if="helpShow" :class="{'avue-helpText-active':helpTag}" @click="jlHelpChange">
|
||||
<div class="text">
|
||||
<img src="../../../public/img/help/icon.png" height="20" width="20"/>
|
||||
|
||||
<span>帮助中心</span>
|
||||
</div>
|
||||
<img v-if="!helpTag" src="../../../public/img/help/zuo_jiantou.png" height="16" width="16"/>
|
||||
<img v-else src="../../../public/img/help/right_jiantou.png" height="16" width="16"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="avue-layout">
|
||||
<div class="avue-left">
|
||||
<!-- 左侧导航栏 -->
|
||||
<sidebar />
|
||||
</div>
|
||||
<div class="avue-main" :class="{'avue-main-active':helpTag}">
|
||||
<!-- 顶部标签卡 -->
|
||||
<tags />
|
||||
<transition name="fade-scale">
|
||||
<search class="avue-view" v-show="isSearch"></search>
|
||||
</transition>
|
||||
<!-- 主体视图层 -->
|
||||
<div style="height: 100%; overflow-y: auto; overflow-x: hidden" id="avue-view" v-show="!isSearch">
|
||||
<keep-alive :include="include" max="10">
|
||||
<router-view class="avue-view" v-if="$route.meta.$keepAlive" />
|
||||
</keep-alive>
|
||||
<router-view class="avue-view" v-if="!$route.meta.$keepAlive" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 侧边栏 -->
|
||||
<jl-help></jl-help>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="avue-shade" @click="showCollapse"></div>
|
||||
<set-sign-pwd ref="setSignPwd"></set-sign-pwd>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters, mapState} from "vuex";
|
||||
import tags from "./tags";
|
||||
import search from "./search";
|
||||
import top from "./top/";
|
||||
import sidebar from "./sidebar/";
|
||||
import admin from "@/util/admin";
|
||||
import { validatenull } from "@/util/validate";
|
||||
import { calcDate } from "@/util/date.js";
|
||||
import { getStore } from "@/util/store.js";
|
||||
import { resetRouter } from "@/router/router";
|
||||
import {whetherSetSignPwd } from '@/api/manage/econtract';
|
||||
import setSignPwd from './setSignPwd'
|
||||
import jlHelp from '@/components/jl-help'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
top,
|
||||
tags,
|
||||
search,
|
||||
sidebar,
|
||||
setSignPwd,
|
||||
jlHelp
|
||||
},
|
||||
name: "index",
|
||||
provide() {
|
||||
return {
|
||||
index: this,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
//搜索控制
|
||||
isSearch: false,
|
||||
//刷新token锁
|
||||
refreshLock: false,
|
||||
//刷新token的时间
|
||||
refreshTime: "",
|
||||
isRouterAlive: true,
|
||||
hasPass:'',
|
||||
};
|
||||
},
|
||||
created() {
|
||||
//实时检测刷新token
|
||||
this.refreshToken();
|
||||
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
this.getSignatureStatus();//获取企业是否设置了签章密码
|
||||
},
|
||||
activated() { },
|
||||
computed: {
|
||||
...mapGetters([
|
||||
"isMenu",
|
||||
"isLock",
|
||||
"isCollapse",
|
||||
"website",
|
||||
"menu",
|
||||
"trial",
|
||||
"tagList",
|
||||
]),
|
||||
...mapState({
|
||||
helpTag: state => state.common.helpTag,
|
||||
helpShow: state => state.common.helpShow
|
||||
}),
|
||||
include() {
|
||||
const arr = [];
|
||||
Array.prototype.forEach.call(this.tagList, (item) => {
|
||||
arr.push(item.code);
|
||||
});
|
||||
return arr;
|
||||
},
|
||||
},
|
||||
props: [],
|
||||
methods: {
|
||||
jlHelpChange () {
|
||||
this.$store.dispatch('jlHelpTag', !this.helpTag)
|
||||
},
|
||||
showCollapse() {
|
||||
this.$store.commit("SET_COLLAPSE");
|
||||
},
|
||||
// 初始化
|
||||
init() {
|
||||
this.$store.commit("SET_SCREEN", admin.getScreen());
|
||||
window.onresize = () => {
|
||||
setTimeout(() => {
|
||||
this.$store.commit("SET_SCREEN", admin.getScreen());
|
||||
}, 0);
|
||||
};
|
||||
this.$store.dispatch("FlowRoutes").then(() => { });
|
||||
this.$store.dispatch("InitArea");
|
||||
},
|
||||
getSignatureStatus() {
|
||||
whetherSetSignPwd().then(res => {
|
||||
this.hasPass=res.data.data;
|
||||
if(!this.hasPass){
|
||||
this.$refs.setSignPwd.open();
|
||||
}
|
||||
|
||||
})
|
||||
},
|
||||
//打开菜单
|
||||
openMenu(item = {}) {
|
||||
if (this.$store.state.user.auth === "2") {
|
||||
this.$store.dispatch("GetMenu", item.id).then((data) => {
|
||||
resetRouter();
|
||||
this.$router.$avueRouter.formatRoutes(data, true);
|
||||
});
|
||||
}
|
||||
},
|
||||
// 定时检测token
|
||||
refreshToken() {
|
||||
this.refreshTime = setInterval(() => {
|
||||
const token =
|
||||
getStore({
|
||||
name: "token",
|
||||
debug: true,
|
||||
}) || {};
|
||||
const date = calcDate(token.datetime, new Date().getTime());
|
||||
if (validatenull(date)) return;
|
||||
if (date.seconds >= this.website.tokenTime && !this.refreshLock) {
|
||||
this.refreshLock = true;
|
||||
this.$store
|
||||
.dispatch("refreshToken")
|
||||
.then(() => {
|
||||
this.refreshLock = false;
|
||||
})
|
||||
.catch(() => {
|
||||
this.refreshLock = false;
|
||||
});
|
||||
}
|
||||
}, 10000);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
trial() {
|
||||
this.$jlEvent("trialCheck").then(
|
||||
() => { },
|
||||
() => { }
|
||||
);
|
||||
},
|
||||
isSearch(val) {
|
||||
if (!val) {
|
||||
this.isRouterAlive = false;
|
||||
this.$nextTick(() => {
|
||||
this.isRouterAlive = true;
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
8
src/page/index/layout.vue
Normal file
8
src/page/index/layout.vue
Normal file
@@ -0,0 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<keep-alive>
|
||||
<router-view class="avue-view" v-if="$route.meta.$keepAlive" />
|
||||
</keep-alive>
|
||||
<router-view class="avue-view" v-if="!$route.meta.$keepAlive" />
|
||||
</div>
|
||||
</template>
|
||||
87
src/page/index/logo.vue
Normal file
87
src/page/index/logo.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="avue-logo">
|
||||
<transition name="fade">
|
||||
<span v-if="keyCollapse" class="avue-logo_subtitle" key="0">{{website.logo}}</span>
|
||||
</transition>
|
||||
<transition-group name="fade">
|
||||
<template v-if="!keyCollapse">
|
||||
<span v-if="loginType !== 'Type-S'" class="avue-logo_title" style=" display: flex !important;
|
||||
align-items: center !important;" key="1">
|
||||
<!-- <img height="26px" width="140px" src="/manage/svg/logo_dark2.png" alt /> -->
|
||||
德阳市智慧就业服务平台
|
||||
</span>
|
||||
<span v-if="loginType === 'Type-S'" class="avue-logo_title" key="1">
|
||||
德阳市智慧就业服务平台
|
||||
<!-- <img height="26px" width="140px" src="/manage/svg/logo_dark2.png" alt /> -->
|
||||
</span>
|
||||
</template>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
export default {
|
||||
name: "logo",
|
||||
data () {
|
||||
return {};
|
||||
},
|
||||
created () { },
|
||||
computed: {
|
||||
...mapState({
|
||||
loginType: (state) => state.user.userInfo.login_type,
|
||||
}),
|
||||
...mapGetters(["website", "keyCollapse"])
|
||||
},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.avue-logo_title {
|
||||
height: 100% !important;
|
||||
/*display: flex !important;*/
|
||||
/*align-items: center !important;*/
|
||||
img {
|
||||
margin-left: 20px;
|
||||
}
|
||||
}
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
.fade-enter-active {
|
||||
transition: opacity 2.5s;
|
||||
}
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
.avue-logo {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 240px;
|
||||
height: 64px;
|
||||
line-height: 64px;
|
||||
background-color: #20222a;
|
||||
font-size: 20px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
z-index: 1024;
|
||||
&_title {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-weight: 300;
|
||||
font-size: 20px;
|
||||
}
|
||||
&_subtitle {
|
||||
display: block;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
197
src/page/index/search.vue
Normal file
197
src/page/index/search.vue
Normal file
@@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="avue-searchs">
|
||||
<i class="avue-searchs__closeBtn el-icon-close" @click="handleEsc"></i>
|
||||
<div class="avue-searchs__title">菜单搜索</div>
|
||||
<div class="avue-searchs__content">
|
||||
<div class="avue-searchs__form">
|
||||
<el-input :placeholder="$t('search')"
|
||||
v-model="value"
|
||||
@keydown.esc.native="handleEsc">
|
||||
<el-button slot="append"
|
||||
icon="el-icon-search"></el-button>
|
||||
</el-input>
|
||||
<p>
|
||||
<el-tag>你可以使用快捷键esc 关闭</el-tag>
|
||||
</p>
|
||||
</div>
|
||||
<div class="avue-searchs__list">
|
||||
<el-scrollbar class="avue-searchs__scrollbar">
|
||||
<div class="avue-searchs__item"
|
||||
v-for="(item,index) in menus"
|
||||
:key="index"
|
||||
@click="handleSelect(item)">
|
||||
<i :class="[item[iconKey],'avue-searchs__item-icon']"></i>
|
||||
<span class="avue-searchs__item-title">{{item[labelKey]}}</span>
|
||||
<div class="avue-searchs__item-path">
|
||||
{{item[pathKey]}}
|
||||
</div>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from './sidebar/config.js'
|
||||
import {mapGetters} from "vuex";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
config: config,
|
||||
value: "",
|
||||
menus: [],
|
||||
menuList: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getMenuList();
|
||||
},
|
||||
watch: {
|
||||
value() {
|
||||
this.querySearch();
|
||||
},
|
||||
menu() {
|
||||
this.getMenuList();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labelKey() {
|
||||
return this.website.menu.props.label || this.config.propsDefault.label;
|
||||
},
|
||||
pathKey() {
|
||||
return this.website.menu.props.path || this.config.propsDefault.path;
|
||||
},
|
||||
iconKey() {
|
||||
return this.website.menu.props.icon || this.config.propsDefault.icon;
|
||||
},
|
||||
childrenKey() {
|
||||
return (
|
||||
this.website.menu.props.children || this.config.propsDefault.children
|
||||
);
|
||||
},
|
||||
...mapGetters(["menu", "website"])
|
||||
},
|
||||
methods: {
|
||||
handleEsc() {
|
||||
this.$parent.isSearch = false;
|
||||
},
|
||||
getMenuList() {
|
||||
const findMenu = list => {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const ele = Object.assign({}, list[i]);
|
||||
if (this.validatenull(ele[this.childrenKey])) {
|
||||
this.menuList.push(ele);
|
||||
} else {
|
||||
findMenu(ele[this.childrenKey]);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.menuList = [];
|
||||
findMenu(this.menu);
|
||||
this.menus = this.menuList;
|
||||
},
|
||||
querySearch() {
|
||||
var restaurants = this.menuList;
|
||||
var queryString = this.value
|
||||
this.menus = queryString
|
||||
? this.menuList.filter(this.createFilter(queryString))
|
||||
: restaurants;
|
||||
},
|
||||
createFilter(queryString) {
|
||||
return restaurant => {
|
||||
return (
|
||||
restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) ===
|
||||
0
|
||||
);
|
||||
};
|
||||
},
|
||||
handleSelect(item) {
|
||||
this.handleEsc();
|
||||
this.value = "";
|
||||
this.$router.push({
|
||||
path: this.$router.$avueRouter.getPath({
|
||||
name: item[this.labelKey],
|
||||
src: item[this.pathKey]
|
||||
}, item.meta),
|
||||
query: item.query
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.avue-searchs {
|
||||
padding-top: 50px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
z-index: 1024;
|
||||
|
||||
&__title {
|
||||
margin-bottom: 60px;
|
||||
text-align: center;
|
||||
font-size: 42px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 2px;
|
||||
text-indent: 2px;
|
||||
}
|
||||
&__closeBtn{
|
||||
float: right;
|
||||
font-size: 30px;
|
||||
cursor: pointer;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
&__form {
|
||||
margin: 0 auto 50px auto;
|
||||
width: 50%;
|
||||
text-align: center;
|
||||
|
||||
p {
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&__scrollbar {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
&__list {
|
||||
box-sizing: border-box;
|
||||
padding: 20px 30px;
|
||||
margin: 0 auto;
|
||||
width: 70%;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebeef5;
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
color: #303133;
|
||||
transition: 0.3s;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&__item {
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px dashed #eee;
|
||||
|
||||
&-icon {
|
||||
margin-right: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&-path {
|
||||
line-height: 30px;
|
||||
color: #666;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
141
src/page/index/setSignPwd.vue
Normal file
141
src/page/index/setSignPwd.vue
Normal file
@@ -0,0 +1,141 @@
|
||||
<template>
|
||||
<!--重置密码dialog-->
|
||||
<el-dialog title="设置签章密码" :visible.sync="dialogFormVisible" :close-on-click-modal="false" :show-close="false"
|
||||
:close-on-press-escape="false" width="30%">
|
||||
<el-form :model="form" :rules="rules" ref="resetPwdForm" class="resetPwd-form">
|
||||
<el-form-item label="手机号码:" :label-width="formLabelWidth" prop="account">
|
||||
<span>{{phone}}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="请输入验证码:" :label-width="formLabelWidth" prop="code">
|
||||
<el-input v-model="form.code" autocomplete="off" style="width: 50%;"></el-input>
|
||||
<el-button :disabled="msgKey" type="primary" @click="getCode">{{msgText}}</el-button>
|
||||
</el-form-item>
|
||||
<el-form-item label="请设置新密码:" :label-width="formLabelWidth" prop="pwd">
|
||||
<el-input type="number" maxlength="6" onKeypress="return(/^[0-9]*$/.test(String.fromCharCode(event.keyCode)))" v-model="form.pwd" autocomplete="off" show-password placeholder="请输入六位数字密码"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="请再次输入新密码:" :label-width="formLabelWidth" prop="pwd2">
|
||||
<el-input type="number" maxlength="6" onKeypress="return(/^[0-9]*$/.test(String.fromCharCode(event.keyCode)))" v-model="form.pwd2" autocomplete="off" show-password placeholder="请再次输入六位数字密码"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="submitResetPwd">确 定</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
import {getCode,resetPwd} from '@/api/manage/econtract'
|
||||
export default {
|
||||
data() {
|
||||
const validatePwd = (rule, value, callback) => {
|
||||
if (value != this.form.pwd) {
|
||||
callback(new Error('两次输入密码不一致'));
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const validPwdNums = (rule, value, callback) => {
|
||||
if (value.length != 6 || isNaN(Number(value))) {
|
||||
callback(new Error('请输入6位数的数字密码'));
|
||||
}
|
||||
else {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
return {
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
code: '',
|
||||
pwd: '',
|
||||
pwd2: '',
|
||||
},
|
||||
formLabelWidth: '150px',
|
||||
dialogFormVisible: false,
|
||||
msgKey: false,
|
||||
msgText: '获取验证码',
|
||||
msgTime: 120,
|
||||
phone: '',
|
||||
rules: {
|
||||
code: [
|
||||
{
|
||||
required: true, message: '请输入验证码', trigger: 'blur'
|
||||
}
|
||||
],
|
||||
pwd: [
|
||||
{
|
||||
required: true, message: '请输入密码', trigger: 'blur'
|
||||
},
|
||||
{
|
||||
validator: validPwdNums, trigger: 'blur'
|
||||
}
|
||||
],
|
||||
pwd2: [
|
||||
{
|
||||
required: true, message: '请输入确认密码', trigger: 'blur'
|
||||
},
|
||||
{
|
||||
validator: validatePwd, trigger: 'blur'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open() {
|
||||
this.phone = this.userInfo.account;
|
||||
var pat = /(\d{3})\d*(\d{4})/;
|
||||
this.phone = this.phone.replace(pat, '$1****$2');
|
||||
this.dialogFormVisible = true;
|
||||
},
|
||||
/*获取验证码*/
|
||||
getCode() {
|
||||
this.msgKey = true;
|
||||
this.msgText = "发送中...";
|
||||
getCode(this.userInfo.account)
|
||||
.then(() => {
|
||||
this.msgText = "剩余" + 120 + "s";
|
||||
this.msgKey = true;
|
||||
const time = setInterval(() => {
|
||||
this.msgTime--;
|
||||
this.msgText = "剩余" + this.msgTime + "s";
|
||||
if (this.msgTime <= 0) {
|
||||
this.msgTime = 120;
|
||||
this.msgText = "重新获取";
|
||||
this.msgKey = false;
|
||||
clearInterval(time);
|
||||
}
|
||||
}, 1000);
|
||||
})
|
||||
.catch(() => {
|
||||
this.msgText = "重新获取";
|
||||
this.msgKey = false;
|
||||
});
|
||||
|
||||
},
|
||||
/*设置签章密码*/
|
||||
submitResetPwd() {
|
||||
this.$refs.resetPwdForm.validate(valid => {
|
||||
if (valid) {
|
||||
resetPwd(this.userInfo.account, this.form.pwd, this.form.code).then(() => {
|
||||
this.$message.success('签章密码设置成功');
|
||||
this.dialogFormVisible = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
this.$message.error(err);
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['userInfo'])
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.resetPwd-form .el-form-item {
|
||||
margin-bottom: 30px!important;
|
||||
}
|
||||
</style>
|
||||
8
src/page/index/sidebar/config.js
Normal file
8
src/page/index/sidebar/config.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export default {
|
||||
propsDefault: {
|
||||
label: 'label',
|
||||
path: 'path',
|
||||
icon: 'icon',
|
||||
children: 'children'
|
||||
}
|
||||
}
|
||||
60
src/page/index/sidebar/index.vue
Normal file
60
src/page/index/sidebar/index.vue
Normal file
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="avue-sidebar">
|
||||
<logo></logo>
|
||||
<el-scrollbar style="height:100%">
|
||||
<div v-if="validatenull(menu)" class="avue-sidebar--tip">{{$t('menuTip')}}</div>
|
||||
<el-menu
|
||||
unique-opened
|
||||
:default-active="nowTagValue"
|
||||
mode="vertical"
|
||||
:show-timeout="200"
|
||||
:collapse="keyCollapse"
|
||||
>
|
||||
<sidebar-item
|
||||
:menu="menu"
|
||||
:screen="screen"
|
||||
first
|
||||
:props="website.menu.props"
|
||||
:collapse="keyCollapse"
|
||||
></sidebar-item>
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
import logo from "../logo";
|
||||
import sidebarItem from "./sidebarItem";
|
||||
|
||||
export default {
|
||||
name: "sidebar",
|
||||
components: { sidebarItem, logo },
|
||||
inject: ["index"],
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {
|
||||
this.index.openMenu(this.menuId);
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
"website",
|
||||
"menu",
|
||||
"tag",
|
||||
"keyCollapse",
|
||||
"screen",
|
||||
"menuId",
|
||||
]),
|
||||
nowTagValue: function () {
|
||||
return this.$router.$avueRouter.getValue(this.$route);
|
||||
},
|
||||
},
|
||||
mounted() {},
|
||||
methods: {},
|
||||
watch: {},
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
|
||||
146
src/page/index/sidebar/sidebarItem.vue
Normal file
146
src/page/index/sidebar/sidebarItem.vue
Normal file
@@ -0,0 +1,146 @@
|
||||
<template>
|
||||
<div class="menu-wrapper">
|
||||
<template v-for="item in menu">
|
||||
<el-menu-item v-if="validatenull(item[childrenKey]) && vaildRoles(item)"
|
||||
:index="item[pathKey]"
|
||||
@click="open(item)"
|
||||
:key="item[labelKey]"
|
||||
:class="{'is-active':vaildAvtive(item)}">
|
||||
<i :class="item[iconKey]"></i>
|
||||
<span slot="title"
|
||||
:alt="item[pathKey]">{{generateTitle(item)}}</span>
|
||||
</el-menu-item>
|
||||
<el-submenu v-else-if="!validatenull(item[childrenKey])&&vaildRoles(item)"
|
||||
:index="item[pathKey]"
|
||||
:key="item[labelKey]">
|
||||
<template slot="title">
|
||||
<i :class="item[iconKey]"></i>
|
||||
<span slot="title"
|
||||
:class="{'el-menu--display':collapse && first}">{{generateTitle(item)}}</span>
|
||||
</template>
|
||||
<template v-for="(child,cindex) in item[childrenKey]">
|
||||
<el-menu-item :index="child[pathKey],cindex"
|
||||
@click="open(child)"
|
||||
:class="{'is-active':vaildAvtive(child)}"
|
||||
v-if="validatenull(child[childrenKey])"
|
||||
:key="child[labelKey]">
|
||||
<i :class="child[iconKey]"></i>
|
||||
<span slot="title">{{generateTitle(child)}}</span>
|
||||
</el-menu-item>
|
||||
<sidebar-item v-else
|
||||
:menu="[child]"
|
||||
:key="cindex"
|
||||
:props="props"
|
||||
:screen="screen"
|
||||
:collapse="collapse"></sidebar-item>
|
||||
</template>
|
||||
</el-submenu>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {mapGetters} from "vuex";
|
||||
import {validatenull} from "@/util/validate";
|
||||
import config from "./config.js";
|
||||
|
||||
export default {
|
||||
name: "sidebarItem",
|
||||
data() {
|
||||
return {
|
||||
config: config
|
||||
};
|
||||
},
|
||||
props: {
|
||||
menu: {
|
||||
type: Array
|
||||
},
|
||||
screen: {
|
||||
type: Number
|
||||
},
|
||||
first: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
props: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
collapse: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["roles"]),
|
||||
labelKey() {
|
||||
return this.props.label || this.config.propsDefault.label;
|
||||
},
|
||||
pathKey() {
|
||||
return this.props.path || this.config.propsDefault.path;
|
||||
},
|
||||
iconKey() {
|
||||
return this.props.icon || this.config.propsDefault.icon;
|
||||
},
|
||||
childrenKey() {
|
||||
return this.props.children || this.config.propsDefault.children;
|
||||
},
|
||||
nowTagValue() {
|
||||
return this.$router.$avueRouter.getValue(this.$route);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generateTitle(item) {
|
||||
return this.$router.$avueRouter.generateTitle(
|
||||
item[this.labelKey],
|
||||
(item.meta || {}).i18n
|
||||
);
|
||||
},
|
||||
vaildAvtive(item) {
|
||||
const groupFlag = (item["group"] || []).some(ele =>
|
||||
this.$route.path.includes(ele)
|
||||
);
|
||||
return this.nowTagValue === item[this.pathKey] || groupFlag;
|
||||
},
|
||||
vaildRoles(item) {
|
||||
item.meta = item.meta || {};
|
||||
return item.meta.roles ? item.meta.roles.includes(this.roles) : true;
|
||||
},
|
||||
validatenull(val) {
|
||||
return validatenull(val);
|
||||
},
|
||||
open (item) {
|
||||
if (this.screen <= 1) this.$store.commit("SET_COLLAPSE");
|
||||
this.$router.$avueRouter.group = item.group;
|
||||
this.$router.$avueRouter.meta = item.meta;
|
||||
var query = {}
|
||||
if (item.isShow === 1) {
|
||||
var obj = {
|
||||
isShow: item.isShow,
|
||||
id: item.id,
|
||||
}
|
||||
query = {
|
||||
obj: JSON.stringify(obj),
|
||||
...item.query
|
||||
}
|
||||
} else {
|
||||
query = {
|
||||
...item.query
|
||||
}
|
||||
}
|
||||
this.$router.push({
|
||||
path: this.$router.$avueRouter.getPath({
|
||||
name: item[this.labelKey],
|
||||
src: item[this.pathKey],
|
||||
}, item.meta),
|
||||
query: query,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
188
src/page/index/tags.vue
Normal file
188
src/page/index/tags.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<div class="avue-tags" v-if="showTag">
|
||||
<!-- tag盒子 -->
|
||||
<div
|
||||
v-if="contextmenuFlag"
|
||||
class="avue-tags__contentmenu"
|
||||
:style="{left:contentmenuX+'px',top:contentmenuY+'px'}"
|
||||
>
|
||||
<!-- <div class="item" @click="clearCacheTags">{{$t('tagsView.clearCache')}}</div>
|
||||
<div class="item" @click="closeOthersTags">{{$t('tagsView.closeOthers')}}</div>
|
||||
<div class="item" @click="closeAllTags">{{$t('tagsView.closeAll')}}</div> -->
|
||||
</div>
|
||||
<div class="avue-tags__box" :class="{'avue-tags__box--close':!website.isFirstPage}">
|
||||
<el-tabs
|
||||
v-model="active"
|
||||
type="card"
|
||||
@contextmenu.native="handleContextmenu"
|
||||
:closable="tagLen!==1"
|
||||
@tab-click="openTag"
|
||||
@edit="menuTag"
|
||||
>
|
||||
<el-tab-pane
|
||||
:key="item.value"
|
||||
v-for="item in tagList"
|
||||
:label="generateTitle(item)"
|
||||
:name="item.value"
|
||||
></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-dropdown class="avue-tags__menu">
|
||||
<el-button type="text" size="mini">
|
||||
{{$t('tagsView.menu')}}
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item @click.native="$parent.isSearch=true">{{$t('tagsView.search')}}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="closeOthersTags">{{$t('tagsView.closeOthers')}}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="closeAllTags">{{$t('tagsView.closeAll')}}</el-dropdown-item>
|
||||
<el-dropdown-item @click.native="clearCacheTags">{{$t('tagsView.clearCache')}}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
import { clearCache } from "@/api/user";
|
||||
import {removeStore} from '@/util/store'
|
||||
|
||||
export default {
|
||||
name: "tags",
|
||||
data () {
|
||||
return {
|
||||
active: "",
|
||||
contentmenuX: "",
|
||||
contentmenuY: "",
|
||||
contextmenuFlag: false
|
||||
};
|
||||
},
|
||||
created () {
|
||||
},
|
||||
mounted () {
|
||||
this.setActive();
|
||||
},
|
||||
watch: {
|
||||
tag () {
|
||||
this.setActive();
|
||||
},
|
||||
contextmenuFlag () {
|
||||
window.addEventListener("mousedown", this.watchContextmenu);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["tagWel", "tagList", "tag", "website"]),
|
||||
...mapState({
|
||||
showTag: state => state.common.showTag
|
||||
}),
|
||||
tagLen () {
|
||||
return this.tagList.length || 0;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generateTitle (item) {
|
||||
return this.$router.$avueRouter.generateTitle(
|
||||
item.label,
|
||||
(item.meta || {}).i18n
|
||||
);
|
||||
},
|
||||
watchContextmenu (event) {
|
||||
if (!this.$el.contains(event.target) || event.button !== 0) {
|
||||
this.contextmenuFlag = false;
|
||||
}
|
||||
window.removeEventListener("mousedown", this.watchContextmenu);
|
||||
},
|
||||
handleContextmenu (event) {
|
||||
let target = event.target;
|
||||
// 解决 https://github.com/d2-projects/d2-admin/issues/54
|
||||
let flag = false;
|
||||
if (target.className.indexOf("el-tabs__item") > -1) flag = true;
|
||||
else if (target.parentNode.className.indexOf("el-tabs__item") > -1) {
|
||||
target = target.parentNode;
|
||||
flag = true;
|
||||
}
|
||||
if (flag) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.contentmenuX = event.clientX;
|
||||
this.contentmenuY = event.clientY;
|
||||
this.tagName = target.getAttribute("aria-controls").slice(5);
|
||||
this.contextmenuFlag = true;
|
||||
}
|
||||
},
|
||||
//激活当前选项
|
||||
setActive () {
|
||||
this.active = this.tag.value;
|
||||
},
|
||||
menuTag (value, action) {
|
||||
if (action === "remove") {
|
||||
let { tag, key } = this.findTag(value);
|
||||
if (value === '/workstation/task/index') {
|
||||
removeStore({name: 'taskStatus', type: 'session'})
|
||||
}
|
||||
if (value === '/workstation/enterprise/index') {
|
||||
removeStore({name: 'enterpriseStatus', type: 'session'})
|
||||
}
|
||||
this.$store.commit("DEL_TAG", tag);
|
||||
if (tag.value === this.tag.value) {
|
||||
tag = this.tagList[key === 0 ? key : key - 1]; //如果关闭本标签让前推一个
|
||||
this.openTag(tag);
|
||||
}
|
||||
}
|
||||
},
|
||||
openTag (item) {
|
||||
let tag;
|
||||
if (item.name) {
|
||||
tag = this.findTag(item.name).tag;
|
||||
} else {
|
||||
tag = item;
|
||||
}
|
||||
this.$router.push({
|
||||
path: this.$router.$avueRouter.getPath({
|
||||
name: tag.label,
|
||||
src: tag.value
|
||||
}, tag.meta),
|
||||
query: tag.query
|
||||
});
|
||||
},
|
||||
closeOthersTags () {
|
||||
this.contextmenuFlag = false;
|
||||
this.$store.commit("DEL_TAG_OTHER");
|
||||
},
|
||||
findTag (value) {
|
||||
let tag, key;
|
||||
this.tagList.map((item, index) => {
|
||||
if (item.value === value) {
|
||||
tag = item;
|
||||
key = index;
|
||||
}
|
||||
});
|
||||
return { tag: tag, key: key };
|
||||
},
|
||||
closeAllTags () {
|
||||
this.contextmenuFlag = false;
|
||||
this.$store.commit("DEL_ALL_TAG");
|
||||
removeStore({name: 'taskStatus', type: 'session'})
|
||||
removeStore({name: 'enterpriseStatus', type: 'session'})
|
||||
this.$router.push({
|
||||
path: this.$router.$avueRouter.getPath({
|
||||
src: this.tagWel.value
|
||||
}),
|
||||
query: this.tagWel.query
|
||||
});
|
||||
},
|
||||
clearCacheTags () {
|
||||
this.$confirm("是否需要清除缓存?", {
|
||||
confirmButtonText: "确定",
|
||||
cancelButtonText: "取消",
|
||||
type: "warning"
|
||||
}).then(() => {
|
||||
clearCache().then(() => {
|
||||
this.$message.success('清除完毕');
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
167
src/page/index/top/index.vue
Normal file
167
src/page/index/top/index.vue
Normal file
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div class="avue-top">
|
||||
<div class="top-bar__left">
|
||||
<div
|
||||
class="avue-breadcrumb"
|
||||
:class="[{ 'avue-breadcrumb--active': isCollapse }]"
|
||||
v-if="showCollapse"
|
||||
>
|
||||
<i v-if="showNavIcon" class="icon-navicon" @click="setCollapse"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-bar__title">
|
||||
<div class="top-bar__item top-bar__item--show" v-if="showMenu">
|
||||
<top-menu ref="topMenu"></top-menu>
|
||||
</div>
|
||||
</div>
|
||||
<div class="top-bar__right">
|
||||
<top-theme></top-theme>
|
||||
<router-link to="/tenant/news/index" v-if="$store.state.user.auth === '2'">
|
||||
<div class="top-bar__item top-bar__item--show">
|
||||
<el-button type="text" style="padding:0;color:#fff;font-weight: 400;">
|
||||
<i v-if="notice.count > 0" class="el-icon-bell" style="color:red"></i>
|
||||
<i v-else class="el-icon-bell"></i>
|
||||
<span>客户消息 </span>
|
||||
<span v-if="notice.count > 0">({{notice.count}})</span>
|
||||
<span v-else-if="notice.count > 10">(99+)</span>
|
||||
</el-button>
|
||||
</div>
|
||||
</router-link>
|
||||
<div style="margin-top:2px">
|
||||
<img class="top-bar__img" src="/manage/img/head.png" />
|
||||
<span class="top-bar__name">{{userInfo.real_name}}</span>
|
||||
<el-dropdown>
|
||||
<span class="el-dropdown-link">
|
||||
<i class="el-icon-arrow-down el-icon--right"></i>
|
||||
</span>
|
||||
<el-dropdown-menu slot="dropdown" style="margin-top:-5px">
|
||||
|
||||
<!-- <el-dropdown-item>
|
||||
<router-link to="/">{{$t('navbar.dashboard')}}</router-link>
|
||||
</el-dropdown-item>-->
|
||||
<!-- <el-dropdown-item>
|
||||
<router-link to="/info/index">{{$t('navbar.userinfo')}}</router-link>
|
||||
</el-dropdown-item>-->
|
||||
<el-dropdown-item>
|
||||
<router-link to="/tenant/account/index">{{$t('navbar.accountsafe')}}</router-link>
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item v-if="auth === '2' && loginType === 'Type-S'" divided>
|
||||
<a href="http://www.jlhrms.com/#/" target="_blank">{{$t('navbar.experienceEntrance')}}</a>
|
||||
</el-dropdown-item>
|
||||
<!-- <el-dropdown-item>
|
||||
<router-link to="/tenant/set/index">{{$t('navbar.set')}}</router-link>
|
||||
</el-dropdown-item>-->
|
||||
<!-- <el-dropdown-item>
|
||||
<router-link to="/tenant/company/index">{{$t('navbar.companyindex')}}</router-link>
|
||||
</el-dropdown-item>-->
|
||||
<el-dropdown-item @click.native="logout" divided>{{$t('navbar.logOut')}}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { resetRouter } from "@/router/router";
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
import { fullscreenToggel, listenfullscreen } from "@/util/util";
|
||||
import topLock from "./top-lock";
|
||||
import topMenu from "./top-menu";
|
||||
import topSearch from "./top-search";
|
||||
import topTheme from "./top-theme";
|
||||
import topLogs from "./top-logs";
|
||||
import topColor from "./top-color";
|
||||
import topNotice from "./top-notice";
|
||||
import topLang from "./top-lang";
|
||||
let interval;
|
||||
|
||||
export default {
|
||||
components: {
|
||||
topLock,
|
||||
topMenu,
|
||||
topSearch,
|
||||
topTheme,
|
||||
topLogs,
|
||||
topColor,
|
||||
topNotice,
|
||||
topLang,
|
||||
},
|
||||
name: "top",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
filters: {},
|
||||
created() {},
|
||||
mounted() {
|
||||
listenfullscreen(this.setScreen);
|
||||
if (this.loginType === 'Type-S') {
|
||||
this.$store.dispatch("workGetUnreadCount");
|
||||
} else {
|
||||
this.$store.dispatch("getUnreadCount");
|
||||
}
|
||||
interval = setInterval(() => {
|
||||
if (this.loginType === 'Type-S') {
|
||||
this.$store.dispatch("workGetUnreadCount");
|
||||
} else {
|
||||
this.$store.dispatch("getUnreadCount");
|
||||
}
|
||||
}, 60000);
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
showDebug: (state) => state.common.showDebug,
|
||||
showTheme: (state) => state.common.showTheme,
|
||||
showLock: (state) => state.common.showLock,
|
||||
showFullScren: (state) => state.common.showFullScren,
|
||||
showCollapse: (state) => state.common.showCollapse,
|
||||
showSearch: (state) => state.common.showSearch,
|
||||
showMenu: (state) => state.common.showMenu,
|
||||
showColor: (state) => state.common.showColor,
|
||||
showNavIcon: (state) => state.user.auth === "2" || !state.notPc,
|
||||
auth: (state) => state.user.auth,
|
||||
loginType: (state) => state.user.userInfo.login_type,
|
||||
}),
|
||||
...mapGetters([
|
||||
"userInfo",
|
||||
"isFullScren",
|
||||
"tagWel",
|
||||
"tagList",
|
||||
"isCollapse",
|
||||
"tag",
|
||||
"logsLen",
|
||||
"logsFlag",
|
||||
"notice",
|
||||
]),
|
||||
},
|
||||
methods: {
|
||||
handleScreen() {
|
||||
fullscreenToggel();
|
||||
},
|
||||
setCollapse() {
|
||||
this.$store.commit("SET_COLLAPSE");
|
||||
},
|
||||
setScreen() {
|
||||
this.$store.commit("SET_FULLSCREN");
|
||||
},
|
||||
logout() {
|
||||
this.$confirm(this.$t("logoutTip"), this.$t("tip"), {
|
||||
confirmButtonText: this.$t("submitText"),
|
||||
cancelButtonText: this.$t("cancelText"),
|
||||
type: "warning",
|
||||
}).then(() => {
|
||||
this.$store.dispatch("LogOut").then(() => {
|
||||
resetRouter();
|
||||
this.$store.dispatch('jlHelpShow', false)
|
||||
this.$router.push({ path: "/login" });
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
destroyed() {
|
||||
clearInterval(interval);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
30
src/page/index/top/top-color.vue
Normal file
30
src/page/index/top/top-color.vue
Normal file
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<el-color-picker size="mini"
|
||||
style="padding-top:18px;"
|
||||
class="theme-picker"
|
||||
popper-class="theme-picker-dropdown"
|
||||
v-model="themeVal"></el-color-picker>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import color from "@/mixins/color";
|
||||
export default {
|
||||
name: "topColor",
|
||||
mixins: [color()],
|
||||
data() {
|
||||
return {
|
||||
chalk: ""
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.theme-picker .el-color-picker__trigger {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.theme-picker-dropdown .el-color-dropdown__link-btn {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
49
src/page/index/top/top-lang.vue
Normal file
49
src/page/index/top/top-lang.vue
Normal file
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<el-dropdown trigger="click"
|
||||
@command="handleSetLanguage">
|
||||
<i class="icon-zhongyingwen"></i>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item :disabled="language==='zh'"
|
||||
command="zh">中文
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="language==='en'"
|
||||
command="en">English
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {mapGetters} from "vuex";
|
||||
|
||||
export default {
|
||||
name: "top-lang",
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {
|
||||
},
|
||||
mounted() {
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["language", "tag"])
|
||||
},
|
||||
props: [],
|
||||
methods: {
|
||||
handleSetLanguage(lang) {
|
||||
this.$i18n.locale = lang;
|
||||
this.$store.commit("SET_LANGUAGE", lang);
|
||||
let tag = this.tag;
|
||||
let title = this.$router.$avueRouter.generateTitle(
|
||||
tag.label,
|
||||
(tag.meta || {}).i18n
|
||||
);
|
||||
//根据当前的标签也获取label的值动态设置浏览器标题
|
||||
this.$router.$avueRouter.setTitle(title);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
72
src/page/index/top/top-lock.vue
Normal file
72
src/page/index/top/top-lock.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<span>
|
||||
<i class="icon-suoping"
|
||||
@click="handleLock"></i>
|
||||
<el-dialog title="设置锁屏密码"
|
||||
:visible.sync="box"
|
||||
width="30%"
|
||||
append-to-body>
|
||||
<el-form :model="form"
|
||||
ref="form"
|
||||
label-width="80px">
|
||||
<el-form-item label="锁屏密码"
|
||||
prop="passwd"
|
||||
:rules="[{ required: true, message: '锁屏密码不能为空'}]">
|
||||
<el-input v-model="form.passwd"
|
||||
placeholder="请输入锁屏密码" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer"
|
||||
class="dialog-footer">
|
||||
<el-button type="primary"
|
||||
@click="handleSetLock">确 定</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { validatenull } from "@/util/validate";
|
||||
import { mapGetters } from "vuex";
|
||||
export default {
|
||||
name: "top-lock",
|
||||
data() {
|
||||
return {
|
||||
box: false,
|
||||
form: {
|
||||
passwd: ""
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
computed: {
|
||||
...mapGetters(["lockPasswd"])
|
||||
},
|
||||
props: [],
|
||||
methods: {
|
||||
handleSetLock() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
if (valid) {
|
||||
this.$store.commit("SET_LOCK_PASSWD", this.form.passwd);
|
||||
this.handleLock();
|
||||
}
|
||||
});
|
||||
},
|
||||
handleLock() {
|
||||
if (validatenull(this.lockPasswd)) {
|
||||
this.box = true;
|
||||
return;
|
||||
}
|
||||
this.$store.commit("SET_LOCK");
|
||||
setTimeout(() => {
|
||||
this.$router.push({ path: "/lock" });
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
components: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
43
src/page/index/top/top-logs.vue
Normal file
43
src/page/index/top/top-logs.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<span @click="logsFlag?'':handleOpen()">
|
||||
<el-badge :value="logsFlag?'':logsLen"
|
||||
:max="99">
|
||||
<i class="icon-rizhi1"></i>
|
||||
</el-badge>
|
||||
<el-dialog title="日志"
|
||||
fullscreen
|
||||
:visible.sync="box"
|
||||
width="100%"
|
||||
append-to-body>
|
||||
<logs></logs>
|
||||
</el-dialog>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
import logs from "@/page/logs/index";
|
||||
export default {
|
||||
name: "top-logs",
|
||||
components: { logs },
|
||||
data() {
|
||||
return {
|
||||
box: false
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
mounted() {},
|
||||
computed: {
|
||||
...mapGetters(["logsFlag", "logsLen"])
|
||||
},
|
||||
props: [],
|
||||
methods: {
|
||||
handleOpen() {
|
||||
this.box = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
93
src/page/index/top/top-menu.vue
Normal file
93
src/page/index/top/top-menu.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<template>
|
||||
<div class="top-menu">
|
||||
<el-menu :default-active="activeIndex" mode="horizontal" text-color="#333">
|
||||
<el-menu-item index="0" @click.native="openHome(itemHome)" key="0">
|
||||
<template slot="title" v-if="loginType !== 'Type-S'">
|
||||
<span>{{generateTitle(itemHome)}}</span>
|
||||
</template>
|
||||
<template slot="title" v-if="loginType === 'Type-S'">
|
||||
<span class="workTitle">{{nickName}}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
<template v-for="(item,index) in items">
|
||||
<el-menu-item :index="item.id+''" @click.native="openMenu(item)" :key="index">
|
||||
<template slot="title">
|
||||
<i :class="item.source" style="padding-right: 5px;"></i>
|
||||
<span>{{generateTitle(item)}}</span>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
</el-menu>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapState } from "vuex";
|
||||
|
||||
export default {
|
||||
name: "top-menu",
|
||||
data () {
|
||||
return {
|
||||
itemHome: {
|
||||
code: "wel",
|
||||
name: '欢迎进入德阳市智慧就业服务平台(零工市场服务系统)',
|
||||
source: 'iconfont iconhome',
|
||||
},
|
||||
activeIndex: "0",
|
||||
items: [],
|
||||
};
|
||||
},
|
||||
inject: ["index"],
|
||||
created () {
|
||||
this.getMenu();
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
nickName: (state) => state.user.userInfo.nick_name,
|
||||
loginType: (state) => state.user.userInfo.login_type,
|
||||
}),
|
||||
...mapGetters(["tagCurrent", "menu"])
|
||||
},
|
||||
methods: {
|
||||
openHome (itemHome) {
|
||||
this.index.openMenu(itemHome);
|
||||
this.$router.push({
|
||||
path: this.$router.$avueRouter.getPath({ name: itemHome.name, src: '' }, {})
|
||||
});
|
||||
},
|
||||
openMenu (item) {
|
||||
this.index.openMenu(item)
|
||||
},
|
||||
getMenu () {
|
||||
this.$store.dispatch("GetTopMenu").then(res => {
|
||||
this.items = res;
|
||||
});
|
||||
},
|
||||
generateTitle (item) {
|
||||
return this.$router.$avueRouter.generateTitle(
|
||||
item.name,
|
||||
(item.meta || {}).i18n
|
||||
);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.el-menu-item [class^="iconfont"] {
|
||||
margin-right: 5px;
|
||||
width: 24px;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
vertical-align: middle;
|
||||
color: rgb(51, 51, 51);
|
||||
}
|
||||
.workTitle{
|
||||
width: 217px;
|
||||
height: 30px;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
line-height: 30px;
|
||||
}
|
||||
</style>
|
||||
87
src/page/index/top/top-notice.vue
Normal file
87
src/page/index/top/top-notice.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<el-popover placement="bottom"
|
||||
width="350"
|
||||
trigger="click">
|
||||
|
||||
<el-tabs v-model="activeName">
|
||||
<el-tab-pane label="邮件(1)"
|
||||
name="first"></el-tab-pane>
|
||||
<el-tab-pane label="消息(2)"
|
||||
name="second"></el-tab-pane>
|
||||
<el-tab-pane label="通知"
|
||||
name="third"></el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-scrollbar style="height:300px">
|
||||
<avue-notice :data="data"
|
||||
:option="option"
|
||||
@page-change="pageChange"></avue-notice>
|
||||
</el-scrollbar>
|
||||
<div slot="reference">
|
||||
<el-badge is-dot>
|
||||
<i class="el-icon-bell"></i>
|
||||
</el-badge>
|
||||
</div>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
let list = [{
|
||||
img: 'https://avue.jobslinkX.vip/images/logo-bg.jpg',
|
||||
title: '史蒂夫·乔布斯 关注了你',
|
||||
subtitle: '05-08 15:08',
|
||||
tag: '已经开始',
|
||||
status: 0
|
||||
}, {
|
||||
img: 'https://avue.jobslinkX.vip/images/logo-bg.jpg',
|
||||
title: '斯蒂夫·沃兹尼亚克 关注了你',
|
||||
subtitle: '05-08 15:08',
|
||||
tag: '未开始',
|
||||
status: 1
|
||||
}, {
|
||||
img: 'https://avue.jobslinkX.vip/images/logo-bg.jpg',
|
||||
title: '蒂姆·库克 关注了你',
|
||||
subtitle: '05-08 15:08',
|
||||
status: 3,
|
||||
tag: '有错误'
|
||||
}, {
|
||||
img: 'https://avue.jobslinkX.vip/images/logo-bg.jpg',
|
||||
title: '比尔·费尔南德斯 关注了你',
|
||||
subtitle: '05-08 15:08',
|
||||
status: 4,
|
||||
tag: '已完成'
|
||||
}];
|
||||
export default {
|
||||
name: "top-notice",
|
||||
data () {
|
||||
return {
|
||||
activeName: 'first',
|
||||
option: {
|
||||
props: {
|
||||
img: 'img',
|
||||
title: 'title',
|
||||
subtitle: 'subtitle',
|
||||
tag: 'tag',
|
||||
status: 'status'
|
||||
},
|
||||
},
|
||||
data: list,
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
pageChange (page, done) {
|
||||
setTimeout(() => {
|
||||
this.$message.success('页码' + page)
|
||||
this.data = this.data.concat(list);
|
||||
done();
|
||||
}, 1000)
|
||||
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
131
src/page/index/top/top-search.vue
Normal file
131
src/page/index/top/top-search.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<el-autocomplete class="top-search"
|
||||
popper-class="my-autocomplete"
|
||||
v-model="value"
|
||||
:fetch-suggestions="querySearch"
|
||||
:placeholder="$t('search')"
|
||||
@select="handleSelect">
|
||||
|
||||
<template slot-scope="{ item }">
|
||||
<i :class="[item[iconKey],'icon']"></i>
|
||||
<div class="name">{{ item[labelKey] }}</div>
|
||||
<div class="addr">{{ item[pathKey] }}</div>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import config from "../sidebar/config.js";
|
||||
import {mapGetters} from "vuex";
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
config: config,
|
||||
value: "",
|
||||
menuList: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getMenuList();
|
||||
},
|
||||
|
||||
watch: {
|
||||
menu() {
|
||||
this.getMenuList();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
labelKey() {
|
||||
return this.website.menu.props.label || this.config.propsDefault.label;
|
||||
},
|
||||
pathKey() {
|
||||
return this.website.menu.props.path || this.config.propsDefault.path;
|
||||
},
|
||||
iconKey() {
|
||||
return this.website.menu.props.icon || this.config.propsDefault.icon;
|
||||
},
|
||||
childrenKey() {
|
||||
return (
|
||||
this.website.menu.props.children || this.config.propsDefault.children
|
||||
);
|
||||
},
|
||||
...mapGetters(["menu", "website"])
|
||||
},
|
||||
methods: {
|
||||
getMenuList() {
|
||||
const findMenu = list => {
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
const ele = Object.assign({}, list[i]);
|
||||
if (this.validatenull(ele[this.childrenKey])) {
|
||||
this.menuList.push(ele);
|
||||
} else {
|
||||
findMenu(ele[this.childrenKey]);
|
||||
}
|
||||
}
|
||||
};
|
||||
this.menuList = [];
|
||||
findMenu(this.menu);
|
||||
},
|
||||
querySearch(queryString, cb) {
|
||||
var restaurants = this.menuList;
|
||||
var results = queryString
|
||||
? restaurants.filter(this.createFilter(queryString))
|
||||
: restaurants;
|
||||
// 调用 callback 返回建议列表的数据
|
||||
cb(results);
|
||||
},
|
||||
createFilter(queryString) {
|
||||
return restaurant => {
|
||||
return (
|
||||
restaurant.name.toLowerCase().indexOf(queryString.toLowerCase()) ===
|
||||
0
|
||||
);
|
||||
};
|
||||
},
|
||||
handleSelect(item) {
|
||||
this.value = "";
|
||||
this.$router.push({
|
||||
path: this.$router.$avueRouter.getPath({
|
||||
name: item[this.labelKey],
|
||||
src: item[this.pathKey]
|
||||
}, item.meta),
|
||||
query: item.query
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.my-autocomplete {
|
||||
li {
|
||||
line-height: normal;
|
||||
padding: 7px;
|
||||
|
||||
.icon {
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.name {
|
||||
display: inline-block;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.addr {
|
||||
padding-top: 5px;
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
color: #b4b4b4;
|
||||
}
|
||||
|
||||
.highlighted .addr {
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
72
src/page/index/top/top-theme.vue
Normal file
72
src/page/index/top/top-theme.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-dialog title="选择"
|
||||
append-to-body
|
||||
:visible.sync="box"
|
||||
width="50%">
|
||||
<el-radio-group v-model="text"
|
||||
class="list">
|
||||
<el-row :span="24">
|
||||
<el-col v-for="(item,index) in list"
|
||||
:key="index"
|
||||
:md="4"
|
||||
:xs="12"
|
||||
:sm="4">
|
||||
<el-radio :label="item.value">{{item.name}}</el-radio>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-radio-group>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { setTheme } from "@/util/util";
|
||||
import { mapGetters } from "vuex";
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
box: false,
|
||||
text: "",
|
||||
list: [
|
||||
{
|
||||
name: "默认主题",
|
||||
value: "default"
|
||||
},
|
||||
{
|
||||
name: "白色主题",
|
||||
value: "theme-white"
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
text: function (val) {
|
||||
val = "theme-white";
|
||||
this.$store.commit("SET_THEME_NAME", val);
|
||||
setTheme(val);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["themeName"])
|
||||
},
|
||||
mounted () {
|
||||
this.text = this.themeName;
|
||||
if (!this.text) {
|
||||
this.text = "";
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open () {
|
||||
this.box = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.list {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user