暂存主页+报警

This commit is contained in:
2024-08-01 15:59:13 +08:00
parent c3d6b87151
commit 69aaacb1c7
29 changed files with 2339 additions and 458 deletions

View File

@@ -0,0 +1,167 @@
<template>
<div class="navbar">
<div class="logo-container">
<img
src="../../../assets/images/cnbm.png"
style="
width: 34px;
height: 34px;
position: relative;
top: 9px;
margin-right: 8px;
"
alt="" />
MES产品化重构
</div>
<top-nav id="homemenu-container" class="homemenu-container" v-if="topNav" />
<div style="padding-top: 5px; padding-right: 38px">
<navbar-right :blackTitle="true" />
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import TopNav from './TopNav';
import Hamburger from '@/components/Hamburger';
import Screenfull from '@/components/Screenfull';
import SizeSelect from '@/components/SizeSelect';
import Search from '@/components/HeaderSearch';
import NotifyMessage from '@/layout/components/Message';
// import {getPath} from "@/utils/ruoyi";
import NavbarRight from './NavbarRight.vue';
export default {
components: {
TopNav,
Hamburger,
Screenfull,
SizeSelect,
Search,
NotifyMessage,
NavbarRight,
},
computed: {
...mapGetters(['sidebar', 'avatar', 'nickname', 'device']),
setting: {
get() {
return this.$store.state.settings.showSettings;
},
set(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'showSettings',
value: val,
});
},
},
topNav: {
get() {
return this.$store.state.settings.topNav;
},
},
},
methods: {
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar');
},
async logout() {
this.$modal
.confirm('确定注销并退出系统吗?', '提示')
.then(() => {
this.$store.dispatch('LogOut').then(() => {
location.href = getPath('/');
});
})
.catch(() => {});
},
},
};
</script>
<style lang="scss" scoped>
.navbar {
height: 84px; // 56/48
overflow: hidden;
position: relative;
.logo-container {
color: #fff;
line-height: 84px;
height: 100%;
float: left;
cursor: pointer;
font-size: 26px;
padding-left: 40px;
font-weight: 500;
}
.homemenu-container {
position: absolute;
left: 290px;
}
.errLog-container {
display: inline-block;
vertical-align: top;
}
.right-menu {
float: right;
height: 100%;
line-height: 56px;
&:focus {
outline: none;
}
.right-menu-item {
display: inline-block;
padding: 0 8px;
height: 100%;
font-size: 18px;
color: #5a5e66;
vertical-align: text-bottom;
&.hover-effect {
cursor: pointer;
transition: background 0.3s;
&:hover {
background: rgba(0, 0, 0, 0.025);
}
}
}
.avatar-container {
margin-right: 30px;
.avatar-wrapper {
display: flex;
justify-content: center;
align-items: center;
position: relative;
.user-avatar {
cursor: pointer;
width: 35px;
height: 35px;
border-radius: 50%;
}
.user-nickname {
margin-left: 5px;
font-size: 14px;
}
.el-icon-caret-bottom {
cursor: pointer;
position: absolute;
right: -20px;
top: 25px;
font-size: 12px;
}
}
}
}
}
</style>

View File

@@ -0,0 +1,143 @@
<template>
<div class="right-msg" :style="blackTitle ? 'color: #000' : 'color: #fff'">
<div class="home-icon" v-if="blackTitle">
<!-- <svg-icon
icon-class="home"
style="font-size: 24px; cursor: pointer"
@click="toHome" /> -->
<svg-icon
icon-class="home-alarm-white"
style="font-size: 24px; cursor: pointer"
@click="toHome" />
</div>
<!-- <div class="time-msg">
<div class="line1">{{timeZone}}&nbsp;&nbsp;&nbsp;&nbsp;{{topTime}}</div>
<div class="line2">{{topDate}}</div>
</div> -->
<div class="base-msg">
<div class="avatar">
<el-dropdown>
<img
:src="require(`../../../assets/images/choicepart/avatar.png`)"
alt=""
width="42"
height="42"
style="position: relative; top: 4px" />
<el-dropdown-menu slot="dropdown">
<!-- <el-dropdown-item>
<svg-icon icon-class="helpbtn" />
帮助文档
</el-dropdown-item> -->
<el-dropdown-item @click.native="logout">
<svg-icon icon-class="exitbtn" />
退出登录
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<div class="use-msg">
<div class="line1">{{ nickname }}</div>
<div class="line2">{{ dept }}</div>
</div>
</div>
</div>
</template>
<script>
import moment from 'moment';
import { getUser } from '@/api/system/user.js';
import { getPath } from '@/utils/ruoyi';
export default {
name: 'navRight',
data() {
return {
// topDate: '',
// topTime: '',
// timeZone: '',
timer: '',
dept: ' ',
nickname: this.$store.getters.nickname,
};
},
props: {
blackTitle: {
type: Boolean,
default: () => {
return false;
},
},
},
created() {
this.getUserMsg();
// this.getTime();
},
beforeDestroy() {
clearInterval(this.timer);
},
methods: {
// getTime() {
// let _this = this;
// this.timer = setInterval(function () {
// _this.topDate = moment().format('YYYY/MM/DD');
// let temp = moment().format('A-hh:mm').split('-');
// _this.timeZone = temp[0];
// _this.topTime = temp[1];
// }, 1000);
// },
getUserMsg() {
let id = this.$store.getters.userId;
getUser(id).then((res) => {
this.dept = res.data.dept ? res.data.dept.name : '';
});
},
async logout() {
this.$modal
.confirm('确定注销并退出系统吗?', '提示')
.then(() => {
this.$store.dispatch('LogOut').then(() => {
location.href = getPath('/');
});
})
.catch(() => {});
},
toHome() {
this.$router.push({ path: '/' });
},
},
};
</script>
<style lang="scss" scoped>
.right-msg {
float: right;
height: 84px;
font-size: 14px;
.time-msg {
display: inline-block;
margin-right: 30px;
}
.home-icon {
display: inline-block;
margin-right: 20px;
vertical-align: top;
line-height: 84px;
}
.base-msg {
display: inline-block;
padding-top: 10px;
.avatar {
display: inline-block;
margin-right: 10px;
}
.use-msg {
display: inline-block;
color: #fff;
}
}
.line1 {
height: 19px;
}
.line2 {
height: 19px;
opacity: 0.65;
}
}
</style>

View File

@@ -0,0 +1,267 @@
<template>
<el-menu
:default-active="activeMenu"
mode="horizontal"
@select="handleSelect">
<template v-for="(item, index) in topMenus">
<el-menu-item
:style="{ '--theme': theme }"
:index="item.path"
:key="index"
v-if="index < visibleNumber">
<!-- <svg-icon :icon-class="item.meta.icon" /> -->
<span class="menu-box">
<span class="menu-dot"></span>
{{ item.meta.title }}
</span>
</el-menu-item>
</template>
<!-- 顶部菜单超出数量折叠 -->
<el-submenu
:style="{ '--theme': theme }"
index="more"
v-if="topMenus.length > visibleNumber">
<template slot="title">更多菜单</template>
<template v-for="(item, index) in topMenus">
<el-menu-item
:index="item.path"
:key="index"
v-if="index >= visibleNumber">
<!-- <svg-icon :icon-class="item.meta.icon" /> -->
<span class="menu-box">
<span class="menu-dot"></span>
{{ item.meta.title }}
</span>
</el-menu-item>
</template>
</el-submenu>
</el-menu>
</template>
<script>
import { mapGetters } from 'vuex';
import { constantRoutes } from '@/router';
// 隐藏侧边栏路由
const hideList = ['/index', '/user/profile'];
export default {
data() {
return {
// 顶部栏初始数
visibleNumber: 5,
// 当前激活菜单的 index
// currentIndex: undefined,
};
},
computed: {
...mapGetters(['choicepart']),
currentIndex() {
return this.choicepart;
},
theme() {
return this.$store.state.settings.theme;
},
// 顶部显示菜单
topMenus() {
let topMenus = [];
this.routers.map((menu) => {
if (menu.hidden !== true) {
// 兼容顶部栏一级菜单内部跳转
if (menu.path === '/') {
topMenus.push(menu.children[0]);
} else {
topMenus.push(menu);
}
}
});
console.log('topMenus:', topMenus);
return topMenus;
},
// 所有的路由信息
routers() {
return this.$store.state.permission.topbarRouters;
},
// 设置子路由
childrenMenus() {
const childrenMenus = [];
this.routers.map((router) => {
for (let item in router.children) {
if (router.children[item].parentPath === undefined) {
if (router.path === '/') {
router.children[item].path = '/' + router.children[item].path;
} else {
if (!this.ishttp(router.children[item].path)) {
router.children[item].path =
router.path + '/' + router.children[item].path;
}
}
router.children[item].parentPath = router.path;
}
childrenMenus.push(router.children[item]);
}
});
return constantRoutes.concat(childrenMenus);
},
// 默认激活的菜单
activeMenu() {
const path = this.$route.path;
let activePath = path;
if (
path !== undefined &&
path.lastIndexOf('/') > 0 &&
hideList.indexOf(path) === -1
) {
const tmpPath = path.substring(1, path.length);
activePath = '/' + tmpPath.substring(0, tmpPath.indexOf('/'));
if (!this.$route.meta.link) {
this.$store.dispatch('app/toggleSideBarHide', false);
}
} else if (!this.$route.children) {
activePath = path;
this.$store.dispatch('app/toggleSideBarHide', true);
}
this.activeRoutes(activePath);
return activePath;
},
},
beforeMount() {
window.addEventListener('resize', this.setVisibleNumber);
},
beforeDestroy() {
window.removeEventListener('resize', this.setVisibleNumber);
},
mounted() {
this.setVisibleNumber();
},
methods: {
// 根据宽度计算设置显示栏数
setVisibleNumber() {
const width = window.innerWidth - 700;
console.log(width);
console.log('window.innerWidth:', window.innerWidth);
this.visibleNumber = parseInt(width / 120);
console.log('this.visibleNumber:', this.visibleNumber);
},
// 菜单选择事件
handleSelect(key, keyPath) {
// this.currentIndex = key;
const route = this.routers.find((item) => item.path === key);
console.log('route:', route);
this.$store.dispatch('app/setChoicepart', key);
this.toRouter(route);
// if (this.ishttp(key)) {
// // http(s):// 路径新窗口打开
// window.open(key, '_blank');
// console.log('aaaaaaaaaaaaaa');
// } else if (!route || !route.children) {
// // 没有子路由路径内部打开
// this.$router.push({ path: key });
// this.$store.dispatch('app/toggleSideBarHide', true);
// console.log('bbbbbbbbbbbbbbb');
// } else {
// // 显示左侧联动菜单
// this.activeRoutes(key);
// if (!this.$route.meta.link) {
// this.$store.dispatch('app/toggleSideBarHide', false);
// }
// console.log('cccccccccccccccc');
// }
},
toRouter(item) {
console.log(item);
if (item.children) {
this.toRouter(item.children[0]);
} else {
this.$router.push({ name: item.name });
}
},
// 当前激活的路由
activeRoutes(key) {
const routes = [];
if (this.childrenMenus && this.childrenMenus.length > 0) {
this.childrenMenus.map((item) => {
if (
key === item.parentPath ||
(key === 'index' && '' === item.path)
) {
routes.push(item);
}
});
}
if (routes.length > 0) {
this.$store.commit('SET_SIDEBAR_ROUTERS', routes);
} else {
this.$store.dispatch('app/toggleSideBarHide', true);
}
},
ishttp(url) {
return url.indexOf('http://') !== -1 || url.indexOf('https://') !== -1;
},
},
};
</script>
<style lang="scss">
.homemenu-container.el-menu--horizontal > .el-menu-item {
float: left;
height: 84px !important;
line-height: 84px !important;
color: #999093 !important;
padding: 0 5px !important;
font-size: 18px;
.menu-box {
color: #fff;
}
}
.homemenu-container.el-menu--horizontal
> .el-menu-item:not(.is-disabled):hover {
background-color: transparent;
}
.homemenu-container.el-menu {
background-color: transparent;
}
.homemenu-container.el-menu.el-menu--horizontal {
border: none;
}
.homemenu-container.el-menu--horizontal > .el-menu-item.is-active,
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
border-bottom: 2px solid #{'var(--theme)'} !important;
color: #303133;
}
/* submenu item */
.homemenu-container.el-menu--horizontal > .el-submenu .el-submenu__title {
float: left;
height: 84px !important;
line-height: 91px !important;
color: #fff !important;
padding: 0 5px !important;
margin: 0 10px !important;
font-size: 18px;
}
.homemenu-container.el-menu--horizontal > .el-submenu .el-submenu__title:hover {
background-color: transparent;
}
.homemenu-container.el-menu--horizontal > .el-submenu .el-submenu__title i {
color: #fff;
}
</style>
<style lang="scss" scoped>
.menu-box {
padding: 3px 10px 5px 10px;
border-radius: 30px;
color: #000;
}
.menu-dot {
display: inline-block;
width: 5px;
height: 5px;
border-radius: 50%;
background: #0b58ff;
margin-right: 3px;
margin-bottom: 2px;
opacity: 0;
}
</style>

416
src/views/home/index.vue Normal file
View File

@@ -0,0 +1,416 @@
<template>
<div class="home-page">
<div>
<navbar />
</div>
<div class="date-tabs">
<el-tabs v-model="activeName" :stretch="true">
<el-tab-pane
:label="'\u2002\u2002日\u2002\u2002'"
name="日"></el-tab-pane>
<el-tab-pane
:label="'\u2002\u2002周\u2002\u2002'"
name="周"></el-tab-pane>
<el-tab-pane
:label="'\u2002\u2002月\u2002\u2002'"
name="月"></el-tab-pane>
<el-tab-pane
:label="'\u2002\u2002年\u2002\u2002'"
name="年"></el-tab-pane>
</el-tabs>
<div class="current-date">(6.13-6.20)</div>
<div class="current-time">
<span style="display: inline-block; margin-right: 16px">03:12AM</span>
<span>2020.12.24</span>
</div>
</div>
<el-row class="main-top" :gutter="16">
<el-col :span="12" style="position: relative">
<div class="title">
<svg-icon icon-class="home-produce" />
<span class="title-inner">生产总览</span>
</div>
<el-row class="box">
<el-col :span="6" class="num-box shadow">
<div class="num-style">9,301.01</div>
<div class="unit-style">产量/千片</div>
</el-col>
<el-col :span="4" class="num-box shadow">
<div class="num-style">94.34</div>
<div class="unit-style">良品率/%</div>
</el-col>
<el-col :span="8" class="num-box shadow">
<div class="num-style">29,301.01</div>
<div class="unit-style">完成工单数量/千片</div>
</el-col>
<el-col :span="6" class="num-box">
<div class="num-style">1,340</div>
<div class="unit-style">完成订单数量/</div>
</el-col>
</el-row>
</el-col>
<el-col :span="12" style="position: relative">
<div class="title">
<svg-icon icon-class="home-device" />
<span class="title-inner">设备总览</span>
</div>
<el-row class="box">
<el-col :span="6" class="num-box shadow">
<div class="num-style">2,931</div>
<div class="unit-style">设备总数/</div>
</el-col>
<el-col :span="6" class="num-box shadow">
<div class="num-style">931</div>
<div class="unit-style">在线设备总数/</div>
</el-col>
<el-col :span="6" class="num-box shadow">
<div class="num-style">7</div>
<div class="unit-style">故障设备总数/</div>
</el-col>
<el-col :span="6" class="num-box">
<div class="num-style">0</div>
<div class="unit-style">停机设备总数/</div>
</el-col>
</el-row>
</el-col>
</el-row>
<div class="main-middle">
<div
class="item"
:class="{ shadow: index !== middleMenu.length - 1 }"
v-for="(item, index) in middleMenu"
:key="index">
<div style="width: 160px; margin: 0 auto; padding-top: 20px">
<svg-icon :icon-class="item.icon" style="font-size: 56px" />
<div class="title-box">
<div class="title">{{ item.name }}</div>
<div class="triangle">
<span class="c1"></span>
<span class="c2"></span>
<span class="c3"></span>
</div>
</div>
</div>
</div>
</div>
<el-row class="main-bottom" :gutter="16">
<el-col :span="12">
<div class="box">
<div class="title-box">
<svg-icon icon-class="home-order-monitor" />
<span class="title">工单监控</span>
</div>
<div class="order-box">
<div
class="order-item"
v-for="(item, index) in orderList"
:key="index">
<div>
<span class="order-name">{{ item.name }}</span>
<span class="order-value">{{ item.value }}%</span>
</div>
<el-progress
:percentage="item.value"
:text-inside="false"
:stroke-width="15"
:show-text="false"></el-progress>
</div>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="box">
<div class="title-box">
<svg-icon icon-class="home-device-alarm" />
<span class="title">设备告警</span>
</div>
<base-table
:page="1"
:limit="100000"
:table-props="tableProps"
:table-data="list"
:max-height="tableH" />
</div>
</el-col>
</el-row>
<div
class="main-footer"
style="
color: #c7c7c7;
user-select: none;
font-size: 14px;
letter-spacing: 1px;
height: 30px;
display: grid;
place-content: center;
">
&copy; 中建材智能自动化研究院有限公司
</div>
</div>
</template>
<script>
import Navbar from './components/Navbar';
import moment from 'moment';
import tableHeightMixin from '@/mixins/tableHeightMixin';
export default {
name: 'Home',
mixins: [tableHeightMixin],
components: { Navbar },
computed: {
gradientBackground() {
return {
'background-image':
'linear-gradient(90deg, #f0f0f0 25%, rgba(255, 255, 255, 0) 25%, rgba(255, 255, 255, 0) 50%, #f0f0f0 50%, #f0f0f0 75%, rgba(255, 255, 255, 0) 75%, rgba(255, 255, 255, 0))',
'background-size': '100px 100px', // 调整条纹的大小
};
},
},
data() {
return {
activeName: '日',
middleMenu: [
{ name: '工单管理', url: '', icon: 'home-work-menu' },
{ name: '订单管理', url: '', icon: 'home-order-menu' },
{ name: '设备管理', url: '', icon: 'home-device-menu' },
{ name: '质量管理', url: '', icon: 'home-quality-menu' },
{ name: '仓库管理', url: '', icon: 'home-store-menu' },
],
orderList: [
{ name: '工单1', value: 50 },
{ name: '工单2', value: 60 },
{ name: '工单3', value: 30 },
{ name: '工单4', value: 60 },
{ name: '工单5', value: 10 },
{ name: '工单6', value: 60 },
{ name: '工单7', value: 40 },
{ name: '工单8', value: 70 },
{ name: '工单9', value: 90 },
],
heightNum: 640,
tableProps: [
{
prop: 'productionLineName',
label: '设备名称',
showOverflowtooltip: true,
},
{
prop: 'sectionName',
label: '告警内容',
showOverflowtooltip: true,
},
{
prop: 'createTime',
label: '告警时间',
width: 180,
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
},
],
list: [
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
{ productionLineName: 1 },
],
};
},
created() {},
methods: {},
};
</script>
<style lang="scss" scoped>
.home-page {
background-image: url('~@/assets/img/home-bg.png');
background-size: cover;
background-repeat: no-repeat;
background-position: center;
height: 300px;
width: 100%;
}
.date-tabs {
padding-left: 24px;
padding-top: 20px;
position: relative;
}
:deep(.date-tabs) {
.el-tabs__header {
margin-bottom: 8px;
display: inline-block;
transform: translateY(-12px);
}
.el-tabs__content {
overflow: visible;
}
.el-tabs__item {
font-size: 18px;
color: #fff;
padding-left: 0 !important;
padding-right: 0 !important;
line-height: 36px !important;
height: 36px;
}
.el-tabs__item.is-active {
color: #0b58ff;
}
}
.current-date {
color: #fff;
font-size: 18px;
position: absolute;
left: 260px;
top: 14px;
}
.current-time {
color: #fff;
font-size: 18px;
position: absolute;
right: 24px;
top: 14px;
}
.main-top {
width: 100%;
padding: 0 8px 0 24px;
.title {
position: absolute;
left: 34px;
top: 20px;
width: 180px;
font-size: 32px;
z-index: 10;
.title-inner {
position: absolute;
left: 42px;
top: 5px;
font-size: 24px;
}
}
.box {
background-color: #fff;
border-radius: 24px;
height: 192px;
padding: 40px 24px 32px 24px;
.num-box {
height: 120px;
padding-top: 26px;
text-align: center;
.num-style {
color: #000;
font-size: 40px;
}
.unit-style {
color: rgba(0, 0, 0, 0.7);
font-size: 18px;
}
}
.shadow {
background: linear-gradient(90deg, #ffffff 80%, #f2f4f9 100%);
}
}
}
.main-middle {
display: flex;
flex-flow: row nowrap;
background-color: #fff;
border-radius: 24px;
height: 133px;
margin: 16px 24px;
padding-top: 15px;
.item {
width: 20%;
height: 100px;
cursor: pointer;
.title-box {
display: inline-block;
padding-left: 20px;
vertical-align: bottom;
.title {
height: 35px;
font-size: 18px;
color: #000;
padding-top: 6px;
letter-spacing: 2px;
}
.triangle {
height: 15px;
span {
display: inline-block;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
}
.c1 {
border-left: 12px solid rgba(11, 88, 255, 1);
margin-right: 5px;
}
.c2 {
border-left: 12px solid rgba(11, 88, 255, 0.5);
margin-right: 5px;
}
.c3 {
border-left: 12px solid rgba(11, 88, 255, 0.2);
}
}
}
}
.shadow {
background: linear-gradient(90deg, #ffffff 90%, #f2f4f9 100%);
}
}
.main-bottom {
width: 100%;
padding: 0 8px 0 24px;
.box {
background-color: #fff;
border-radius: 24px;
height: calc(100vh - 534px);
padding: 24px;
.title-box {
position: relative;
font-size: 32px;
margin-bottom: 16px;
.title {
position: absolute;
left: 44px;
top: 6px;
font-size: 24px;
}
}
.order-box {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
font-size: 18px;
padding: 0 30px;
.order-item {
width: 48%;
margin-bottom: 16px;
position: relative;
.order-name {
color: #000000;
}
.order-value {
position: absolute;
right: 0;
color: #0b58ff;
}
}
}
}
}
</style>