lb #30
BIN
src/assets/images/factory-icon.png
Normal file
BIN
src/assets/images/factory-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 710 B |
BIN
src/assets/images/no-data-bg.png
Normal file
BIN
src/assets/images/no-data-bg.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 205 KiB |
BIN
src/assets/images/tree-icon-1.png
Normal file
BIN
src/assets/images/tree-icon-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
BIN
src/assets/images/tree-icon-2.png
Normal file
BIN
src/assets/images/tree-icon-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
@ -6,11 +6,12 @@
|
||||
@import './btn.scss';
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
|
||||
height: 100%;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
|
||||
Microsoft YaHei, Arial, sans-serif;
|
||||
}
|
||||
|
||||
// label {
|
||||
@ -27,170 +28,195 @@ body {
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
*,
|
||||
*:before,
|
||||
*:after {
|
||||
box-sizing: inherit;
|
||||
box-sizing: inherit;
|
||||
}
|
||||
|
||||
.no-padding {
|
||||
padding: 0px !important;
|
||||
padding: 0px !important;
|
||||
}
|
||||
|
||||
.padding-content {
|
||||
padding: 4px 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
a:focus,
|
||||
a:active {
|
||||
outline: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
a,
|
||||
a:focus,
|
||||
a:hover {
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
div:focus {
|
||||
outline: none;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.fr {
|
||||
float: right;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.fl {
|
||||
float: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.pr-5 {
|
||||
padding-right: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.pl-5 {
|
||||
padding-left: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.pointer {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.inlineBlock {
|
||||
display: block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
&:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: " ";
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
&:after {
|
||||
visibility: hidden;
|
||||
display: block;
|
||||
font-size: 0;
|
||||
content: ' ';
|
||||
clear: both;
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
aside {
|
||||
background: #eef1f6;
|
||||
padding: 8px 24px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
||||
color: #2c3e50;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
background: #eef1f6;
|
||||
padding: 8px 24px;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 2px;
|
||||
display: block;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
color: #2c3e50;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
a {
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
a {
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: rgb(32, 160, 255);
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
color: rgb(32, 160, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//main-container全局样式
|
||||
.app-container {
|
||||
padding: 16px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.components-container {
|
||||
margin: 30px 50px;
|
||||
position: relative;
|
||||
margin: 30px 50px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.sub-navbar {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
padding-right: 20px;
|
||||
transition: 600ms ease position;
|
||||
background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
padding-right: 20px;
|
||||
transition: 600ms ease position;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(32, 182, 249, 1) 0%,
|
||||
rgba(32, 182, 249, 1) 0%,
|
||||
rgba(33, 120, 241, 1) 100%,
|
||||
rgba(33, 120, 241, 1) 100%
|
||||
);
|
||||
|
||||
.subtitle {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
.subtitle {
|
||||
font-size: 20px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
&.draft {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
&.draft {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
|
||||
&.deleted {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
&.deleted {
|
||||
background: #d0d0d0;
|
||||
}
|
||||
}
|
||||
|
||||
.link-type,
|
||||
.link-type:focus {
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
color: #337ab7;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: rgb(32, 160, 255);
|
||||
}
|
||||
&:hover {
|
||||
color: rgb(32, 160, 255);
|
||||
}
|
||||
}
|
||||
|
||||
.filter-container {
|
||||
padding-bottom: 10px;
|
||||
padding-bottom: 10px;
|
||||
|
||||
.filter-item {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.filter-item {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
//refine vue-multiselect plugin
|
||||
.multiselect {
|
||||
line-height: 16px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.multiselect--active {
|
||||
z-index: 1000 !important;
|
||||
z-index: 1000 !important;
|
||||
}
|
||||
|
||||
.no-data-bg {
|
||||
height: 240px;
|
||||
background: url(../images/no-data-bg.png) 50% 100% / contain
|
||||
no-repeat;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '暂无数据';
|
||||
position: absolute;
|
||||
bottom: 12px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
color: #ccc;
|
||||
font-size: 18px;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
}
|
||||
|
@ -5,110 +5,123 @@
|
||||
|
||||
/** 基础通用 **/
|
||||
.pt5 {
|
||||
padding-top: 5px;
|
||||
padding-top: 5px;
|
||||
}
|
||||
.pr5 {
|
||||
padding-right: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.pb5 {
|
||||
padding-bottom: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
.mt5 {
|
||||
margin-top: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.mr5 {
|
||||
margin-right: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.mb5 {
|
||||
margin-bottom: 5px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.mb8 {
|
||||
margin-bottom: 8px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.ml5 {
|
||||
margin-left: 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.mt10 {
|
||||
margin-top: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.mr10 {
|
||||
margin-right: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.mb10 {
|
||||
margin-bottom: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ml10 {
|
||||
margin-left: 10px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.mt20 {
|
||||
margin-top: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.mr20 {
|
||||
margin-right: 20px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.mb20 {
|
||||
margin-bottom: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.ml20 {
|
||||
margin-left: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
.h1,
|
||||
.h2,
|
||||
.h3,
|
||||
.h4,
|
||||
.h5,
|
||||
.h6,
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: inherit;
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.el-message-box__status + .el-message-box__message{
|
||||
word-break: break-word;
|
||||
.el-message-box__status + .el-message-box__message {
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.el-dialog:not(.is-fullscreen) {
|
||||
margin-top: 6vh !important;
|
||||
// margin-top: 6vh !important;
|
||||
margin-top: 12vh !important;
|
||||
}
|
||||
|
||||
.el-dialog__wrapper.scrollbar .el-dialog .el-dialog__body {
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 70vh;
|
||||
padding: 10px 20px 0;
|
||||
overflow: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: 70vh;
|
||||
padding: 10px 20px 0;
|
||||
}
|
||||
|
||||
.el-dialog{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: calc(100% - 30px);
|
||||
max-height: calc(100% - 70px);
|
||||
.el-dialog__body {
|
||||
overflow: auto;
|
||||
}
|
||||
.el-dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: calc(100% - 30px);
|
||||
max-height: calc(100% - 70px);
|
||||
.el-dialog__body {
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table {
|
||||
.el-table__header-wrapper, .el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9;
|
||||
color: #515a6e;
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.el-table__body-wrapper {
|
||||
.el-button [class*="el-icon-"] + span {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
.el-table__header-wrapper,
|
||||
.el-table__fixed-header-wrapper {
|
||||
th {
|
||||
word-break: break-word;
|
||||
background-color: #f8f8f9;
|
||||
color: #515a6e;
|
||||
height: 40px;
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
.el-table__body-wrapper {
|
||||
.el-button [class*='el-icon-'] + span {
|
||||
margin-left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 表单布局 **/
|
||||
.form-header {
|
||||
font-size:15px;
|
||||
color:#6379bb;
|
||||
border-bottom:1px solid #ddd;
|
||||
margin:8px 10px 25px 10px;
|
||||
padding-bottom:5px
|
||||
font-size: 15px;
|
||||
color: #6379bb;
|
||||
border-bottom: 1px solid #ddd;
|
||||
margin: 8px 10px 25px 10px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
/** 表格布局 **/
|
||||
@ -122,169 +135,171 @@
|
||||
|
||||
/* tree border */
|
||||
.tree-border {
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #FFFFFF none;
|
||||
border-radius:4px;
|
||||
margin-top: 5px;
|
||||
border: 1px solid #e5e6e7;
|
||||
background: #ffffff none;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.pagination-container .el-pagination {
|
||||
right: 0;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
@media ( max-width : 768px) {
|
||||
.pagination-container .el-pagination > .el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||
display: none !important;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.pagination-container .el-pagination > .el-pagination__jump {
|
||||
display: none !important;
|
||||
}
|
||||
.pagination-container .el-pagination > .el-pagination__sizes {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
.el-table .fixed-width .el-button--mini {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: inherit;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
width: inherit;
|
||||
}
|
||||
|
||||
/** 表格更多操作下拉样式 */
|
||||
.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine {
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
.el-table .el-dropdown-link,
|
||||
.el-table .el-dropdown-selfdefine {
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.el-table .el-dropdown, .el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
.el-table .el-dropdown,
|
||||
.el-icon-arrow-down {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.el-tree-node__content > .el-checkbox {
|
||||
margin-right: 8px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.list-group-striped > .list-group-item {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
border-radius: 0;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
}
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid #e7eaec;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
// border-bottom: 1px solid #e7eaec;
|
||||
// border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
// border-bottom: 1px solid #e7eaec;
|
||||
// border-top: 1px solid #e7eaec;
|
||||
margin-bottom: -1px;
|
||||
padding: 11px 0px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.pull-right {
|
||||
float: right !important;
|
||||
float: right !important;
|
||||
}
|
||||
|
||||
.el-card__header {
|
||||
padding: 14px 15px 7px;
|
||||
min-height: 40px;
|
||||
padding: 14px 15px 7px;
|
||||
min-height: 40px;
|
||||
}
|
||||
|
||||
.el-card__body {
|
||||
padding: 15px 20px 20px 20px;
|
||||
padding: 15px 20px 20px 20px;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* button color */
|
||||
.el-button--cyan.is-active,
|
||||
.el-button--cyan:active {
|
||||
background: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
background: #20b2aa;
|
||||
border-color: #20b2aa;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.el-button--cyan:focus,
|
||||
.el-button--cyan:hover {
|
||||
background: #48D1CC;
|
||||
border-color: #48D1CC;
|
||||
color: #FFFFFF;
|
||||
background: #48d1cc;
|
||||
border-color: #48d1cc;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.el-button--cyan {
|
||||
background-color: #20B2AA;
|
||||
border-color: #20B2AA;
|
||||
color: #FFFFFF;
|
||||
background-color: #20b2aa;
|
||||
border-color: #20b2aa;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/* text color */
|
||||
.text-navy {
|
||||
color: #1ab394;
|
||||
color: #1ab394;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: inherit;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: #1c84c6;
|
||||
color: #1c84c6;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: #23c6c8;
|
||||
color: #23c6c8;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: #f8ac59;
|
||||
color: #f8ac59;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: #ed5565;
|
||||
color: #ed5565;
|
||||
}
|
||||
|
||||
.text-muted {
|
||||
color: #888888;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
/* image */
|
||||
.img-circle {
|
||||
border-radius: 50%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.img-lg {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.avatar-upload-preview {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate(50%, -50%);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 4px #ccc;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 拖拽列样式 */
|
||||
.sortable-ghost{
|
||||
opacity: .8;
|
||||
color: #fff!important;
|
||||
background: #42b983!important;
|
||||
.sortable-ghost {
|
||||
opacity: 0.8;
|
||||
color: #fff !important;
|
||||
background: #42b983 !important;
|
||||
}
|
||||
|
||||
.top-right-btn {
|
||||
position: relative;
|
||||
float: right;
|
||||
position: relative;
|
||||
float: right;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import moment from 'moment';
|
||||
|
||||
/**
|
||||
* 用于动态表结构的 tableProps 生成
|
||||
* @param {*} nameData
|
||||
@ -16,10 +18,9 @@ export function handleNameData(nameData) {
|
||||
function step1(tree1) {
|
||||
return Array.from(new Set(tree1.map((item) => item.name)))
|
||||
.sort()
|
||||
.map((item) => ({
|
||||
prop: item,
|
||||
label: item,
|
||||
align: 'center',
|
||||
.map((time) => ({
|
||||
prop: time,
|
||||
label: moment(time).format('YYYY-MM-DD HH:mm:ss'),
|
||||
children: [],
|
||||
}));
|
||||
}
|
||||
@ -33,7 +34,6 @@ function step2(firstTierProps, tree2) {
|
||||
parent.children.push({
|
||||
label: nd.name,
|
||||
prop: `${parent.prop}-${nd.name}`,
|
||||
align: 'center',
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -85,12 +86,11 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'equipmentName', label: '设备', align: 'center' },
|
||||
{ prop: 'groupName', label: '分组', align: 'center' },
|
||||
{ prop: 'equipmentName', label: '设备' },
|
||||
{ prop: 'groupName', label: '分组' },
|
||||
{
|
||||
_action: 'equipment-bind-group-show-alert',
|
||||
label: '分组报警',
|
||||
align: 'center',
|
||||
subcomponent: {
|
||||
props: ['injectData'],
|
||||
render: function (h) {
|
||||
@ -98,7 +98,7 @@ export default {
|
||||
return h(
|
||||
'el-button',
|
||||
{
|
||||
props: { type: 'text', size: 'mini' },
|
||||
props: { type: 'text' },
|
||||
on: {
|
||||
click: function () {
|
||||
console.log('inejctdata', _this.injectData);
|
||||
@ -162,6 +162,9 @@ export default {
|
||||
label: '设备',
|
||||
url: '/base/equipment/page?pageNo=1&pageSize=100',
|
||||
prop: 'equipmentId',
|
||||
bind: {
|
||||
filterable: true,
|
||||
},
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
@ -173,6 +176,9 @@ export default {
|
||||
// depends: '__product_line', // 依赖产线获取数据
|
||||
// depends: 'productionLineId',
|
||||
prop: 'groupId',
|
||||
bind: {
|
||||
filterable: true,
|
||||
},
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
@ -223,7 +229,7 @@ export default {
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
_// 执行查询
|
||||
_; // 执行查询
|
||||
getEquipmentBindGroupPage(this.queryParams).then((response) => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -83,28 +84,26 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'productionLine', label: '产线名称', align: 'center' },
|
||||
{ prop: 'workshopSection', label: '工段名称', align: 'center' },
|
||||
{ prop: 'equipment', label: '设备名称', align: 'center' },
|
||||
{ prop: 'sort', label: '工段中排序', align: 'center' },
|
||||
{ prop: 'productionLine', label: '产线名称' },
|
||||
{ prop: 'workshopSection', label: '工段名称' },
|
||||
{ prop: 'equipment', label: '设备名称' },
|
||||
{ prop: 'sort', label: '工段中排序' },
|
||||
{
|
||||
prop: 'lineDataType',
|
||||
label: '产线数据类型',
|
||||
align: 'center',
|
||||
filter: (val) =>
|
||||
val != null ? ['无类型', '进口计数', '出口计数'][val] : '-',
|
||||
},
|
||||
{
|
||||
prop: 'sectionDataType',
|
||||
label: '工段数据类型',
|
||||
align: 'center',
|
||||
filter: (val) =>
|
||||
val != null ? ['无类型', '进口计数', '出口计数'][val] : '-',
|
||||
},
|
||||
// {
|
||||
// action: 'show-alert',
|
||||
// label: '报警',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// subcomponent: {
|
||||
// props: ['injectData'],
|
||||
// render: function (h) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -84,13 +85,12 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'name', label: '设备分组名称', align: 'center' },
|
||||
{ prop: 'code', label: '检测分组编码', align: 'center' },
|
||||
{ prop: 'remark', label: '备注', align: 'center' },
|
||||
{ prop: 'name', label: '设备分组名称' },
|
||||
{ prop: 'code', label: '设备分组编码' },
|
||||
{ prop: 'remark', label: '备注' },
|
||||
{
|
||||
_action: 'equipment-group-show-alert',
|
||||
label: '报警',
|
||||
align: 'center',
|
||||
subcomponent: {
|
||||
props: ['injectData'],
|
||||
render: function (h) {
|
||||
@ -98,7 +98,7 @@ export default {
|
||||
return h(
|
||||
'el-button',
|
||||
{
|
||||
props: { type: 'text', size: 'mini' },
|
||||
props: { type: 'text' },
|
||||
on: {
|
||||
click: function () {
|
||||
console.log('inejctdata', _this.injectData);
|
||||
@ -127,7 +127,7 @@ export default {
|
||||
type: 'input',
|
||||
label: '分组编码',
|
||||
placeholder: '请输入设备分组编码',
|
||||
param: 'codes',
|
||||
param: 'code',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
@ -172,6 +172,7 @@ export default {
|
||||
label: '分组编码',
|
||||
prop: 'code',
|
||||
url: '/base/equipment-group/getCode',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
[
|
||||
@ -302,11 +303,7 @@ export default {
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm(
|
||||
'是否确认删除设备分组(用于同类型不同厂家的设备区分)编号为"' +
|
||||
id +
|
||||
'"的数据项?'
|
||||
)
|
||||
.confirm('是否确认删除设备分组 "' + row.name + '"?')
|
||||
.then(function () {
|
||||
return deleteEquipmentGroup(id);
|
||||
})
|
||||
|
177
src/views/base/equipmentGroupAlarm/dialogForm.vue
Normal file
177
src/views/base/equipmentGroupAlarm/dialogForm.vue
Normal file
@ -0,0 +1,177 @@
|
||||
<!--
|
||||
filename: dialogForm.vue
|
||||
author: liubin
|
||||
date: 2023-09-11 15:55:13
|
||||
description: DialogForm for equipmentBindSection only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="dataForm"
|
||||
label-width="100px"
|
||||
v-loading="formLoading">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
label="报警编码"
|
||||
prop="code"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-input
|
||||
v-model="dataForm.code"
|
||||
@change="$emit('update', dataForm)"
|
||||
placeholder="请输入工段排序" />
|
||||
</el-form-item>
|
||||
<!--
|
||||
<el-form-item
|
||||
label="报警编码"
|
||||
prop="code"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-select
|
||||
v-model="dataForm.code"
|
||||
placeholder="请选择产线"
|
||||
@change="handleProductlineChange">
|
||||
<el-option
|
||||
v-for="opt in productionLineList"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
label="报警类型"
|
||||
prop="type"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-select
|
||||
v-model="dataForm.type"
|
||||
placeholder="请选择报警类型"
|
||||
@change="$emit('update', dataForm)">
|
||||
<el-option
|
||||
v-for="opt in [
|
||||
{ label: '布尔型', value: 2 },
|
||||
{ label: '字符型', value: 1 },
|
||||
]"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
label="报警级别"
|
||||
prop="grade"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-select
|
||||
v-model="dataForm.grade"
|
||||
placeholder="请选择报警级别"
|
||||
@change="$emit('update', dataForm)">
|
||||
<el-option
|
||||
v-for="opt in getDictDatas(DICT_TYPE.EQU_ALARM_LEVEL)"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
v-if="+dataForm.type == 1"
|
||||
label="设备报警编码"
|
||||
prop="alarmCode">
|
||||
<el-input
|
||||
v-model="dataForm.alarmCode"
|
||||
@change="$emit('update', dataForm)"
|
||||
placeholder="请输入设备报警编码" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
label="参数列名"
|
||||
prop="plcParamName"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-input
|
||||
v-model="dataForm.plcParamName"
|
||||
placeholder="请输入参数列名"
|
||||
@change="$emit('update', dataForm)"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item
|
||||
label="报警内容"
|
||||
prop="alarmContent"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-input
|
||||
v-model="dataForm.alarmContent"
|
||||
placeholder="请输入报警内容"
|
||||
@change="$emit('update', dataForm)"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DialogForm',
|
||||
model: {
|
||||
prop: 'dataForm',
|
||||
event: 'update',
|
||||
},
|
||||
emits: ['update'],
|
||||
components: {},
|
||||
props: {
|
||||
dataForm: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formLoading: true,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getCode('/base/equipment-group-alarm/getCode').then((code) => {
|
||||
this.formLoading = false;
|
||||
this.$emit('update', {
|
||||
...this.dataForm,
|
||||
code,
|
||||
});
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
/** 模拟透传 ref */
|
||||
validate(cb) {
|
||||
return this.$refs.form.validate(cb);
|
||||
},
|
||||
resetFields(args) {
|
||||
return this.$refs.form.resetFields(args);
|
||||
},
|
||||
async handleProductlineChange(id) {
|
||||
await this.getWorksectionList(id);
|
||||
this.dataForm.workshopSectionId = null;
|
||||
this.$emit('update', this.dataForm);
|
||||
},
|
||||
async getCode(url) {
|
||||
const response = await this.$axios(url);
|
||||
return response.data;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-date-editor,
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -37,7 +38,7 @@
|
||||
@close="cancel"
|
||||
@cancel="cancel"
|
||||
@confirm="submitForm">
|
||||
<DialogForm v-if="open" ref="form" :dataForm="form" :rows="rows" />
|
||||
<DialogForm v-if="open" ref="form" v-model="form" :rows="rows" />
|
||||
</base-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@ -54,10 +55,11 @@ import {
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import moment from 'moment';
|
||||
import { publicFormatter } from '@/utils/dict';
|
||||
import DialogForm from './dialogForm.vue';
|
||||
|
||||
export default {
|
||||
name: 'EquipmentGroupAlarm',
|
||||
components: {},
|
||||
components: { DialogForm },
|
||||
mixins: [basicPageMixin],
|
||||
data() {
|
||||
return {
|
||||
@ -84,22 +86,27 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'code', label: '报警编码', align: 'center' },
|
||||
{ prop: 'type', label: '报警类型', align: 'center' },
|
||||
{ width: 240, prop: 'code', label: '报警编码' },
|
||||
{
|
||||
prop: 'type',
|
||||
label: '报警类型',
|
||||
filter: (val) =>
|
||||
val != null ? ['-', '字符型', '布尔型', '-'][val] : '-',
|
||||
},
|
||||
{
|
||||
prop: 'grade',
|
||||
label: '报警级别',
|
||||
align: 'center',
|
||||
filter: publicFormatter(this.DICT_TYPE.EQU_ALARM_LEVEL),
|
||||
},
|
||||
{ prop: 'alarmCode', label: '设备报警编码', align: 'center' },
|
||||
{ prop: 'plcParamName', label: '参数列名', align: 'center' },
|
||||
{ prop: 'alarmContent', label: '报警内容', align: 'center' },
|
||||
{ prop: 'alarmCode', label: '设备报警编码' },
|
||||
{ prop: 'plcParamName', label: '参数列名' },
|
||||
{ prop: 'alarmContent', label: '报警内容' },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'input',
|
||||
label: '设备分组编码',
|
||||
width: '220',
|
||||
placeholder: '/',
|
||||
param: 'equipmentGroupCode',
|
||||
defaultSelect: null,
|
||||
@ -181,14 +188,14 @@ export default {
|
||||
},
|
||||
// 表单参数
|
||||
form: {
|
||||
id: undefined,
|
||||
equipmentGroupId: undefined,
|
||||
code: undefined,
|
||||
type: undefined,
|
||||
grade: undefined,
|
||||
alarmCode: undefined,
|
||||
alarmContent: undefined,
|
||||
plcParamName: undefined,
|
||||
id: null,
|
||||
equipmentGroupId: null,
|
||||
code: null,
|
||||
type: null,
|
||||
grade: null,
|
||||
alarmCode: null,
|
||||
alarmContent: null,
|
||||
plcParamName: null,
|
||||
},
|
||||
// // 表单校验
|
||||
// rules: {
|
||||
@ -249,14 +256,14 @@ export default {
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
equipmentGroupId: undefined,
|
||||
code: undefined,
|
||||
type: undefined,
|
||||
grade: undefined,
|
||||
alarmCode: undefined,
|
||||
alarmContent: undefined,
|
||||
plcParamName: undefined,
|
||||
id: null,
|
||||
equipmentGroupId: null,
|
||||
code: null,
|
||||
type: null,
|
||||
grade: null,
|
||||
alarmCode: null,
|
||||
alarmContent: null,
|
||||
plcParamName: null,
|
||||
};
|
||||
this.resetForm('form');
|
||||
},
|
||||
@ -321,7 +328,7 @@ export default {
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除设备分组报警明细编号为"' + id + '"的数据项?')
|
||||
.confirm('是否确认删除该报警?')
|
||||
.then(function () {
|
||||
return deleteEquipmentGroupAlarm(id);
|
||||
})
|
||||
|
@ -12,6 +12,7 @@
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
ref="pageTable"
|
||||
@emitFun="handleEmitFun">
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
@ -58,9 +59,12 @@ const switchBtn = {
|
||||
name: 'SwitchBtn',
|
||||
props: ['injectData'],
|
||||
data() {
|
||||
return {
|
||||
active: +this.injectData[this.injectData.prop] == 1 ? true : false,
|
||||
};
|
||||
return {};
|
||||
},
|
||||
computed: {
|
||||
active() {
|
||||
return +this.injectData[this.injectData.prop] == 1 ? true : false;
|
||||
},
|
||||
},
|
||||
methods: {},
|
||||
render: function (h) {
|
||||
@ -72,8 +76,6 @@ const switchBtn = {
|
||||
},
|
||||
on: {
|
||||
change: (newVal) => {
|
||||
this.active = !this.active;
|
||||
console.log('changed emit', newVal);
|
||||
this.$emit('emitData', {
|
||||
action: 'update-collect',
|
||||
payload: {
|
||||
@ -95,6 +97,7 @@ export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
tableKey: Math.random(),
|
||||
searchBarKeys: ['name', 'plcTableName'],
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:equipment-plc:update')
|
||||
@ -118,17 +121,16 @@ export default {
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'code', label: '编码', align: 'center' },
|
||||
{ prop: 'plcTableName', label: '关联表名', align: 'center' },
|
||||
{ prop: 'name', label: '标识名称', align: 'center' },
|
||||
{ prop: 'enName', label: '英文名称', align: 'center' },
|
||||
{ prop: 'code', label: '编码' },
|
||||
{ prop: 'plcTableName', label: '关联表名' },
|
||||
{ prop: 'name', label: '标识名称' },
|
||||
{ prop: 'enName', label: '英文名称' },
|
||||
{
|
||||
prop: 'collection',
|
||||
label: '是否采集',
|
||||
align: 'center',
|
||||
subcomponent: switchBtn,
|
||||
},
|
||||
{ prop: 'description', label: '描述', align: 'center' },
|
||||
{ prop: 'description', label: '描述' },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
@ -185,6 +187,7 @@ export default {
|
||||
label: '编码',
|
||||
prop: 'code',
|
||||
url: '/base/equipment-group/getCode',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
[
|
||||
@ -192,7 +195,7 @@ export default {
|
||||
input: true,
|
||||
label: '标识',
|
||||
prop: 'name',
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// bind: {
|
||||
// disabled: true, // some condition, like detail mode...
|
||||
// }
|
||||
@ -246,7 +249,7 @@ export default {
|
||||
handleEmitFun({ action, payload }) {
|
||||
switch (action) {
|
||||
case 'update-collect':
|
||||
this.reset();
|
||||
this.reset();
|
||||
const tempForm = {};
|
||||
Object.keys(this.form).forEach((key) => {
|
||||
tempForm[key] = payload[key];
|
||||
@ -267,6 +270,7 @@ export default {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
// this.tableKey = Math.random(); // method 1
|
||||
});
|
||||
},
|
||||
/** 取消按钮 */
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -61,7 +62,7 @@ export default {
|
||||
components: {},
|
||||
data() {
|
||||
return {
|
||||
searchBarKeys: ['name', 'plcTableName'],
|
||||
searchBarKeys: ['equipmentId', 'plcId'],
|
||||
// tableBtn: [
|
||||
// this.$auth.hasPermi('base:equipment-plc:update')
|
||||
// ? {
|
||||
@ -98,18 +99,17 @@ export default {
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'productionLine', label: '产线', align: 'center' },
|
||||
{ prop: 'workshopSection', label: '工段', align: 'center' },
|
||||
{ prop: 'equipmentName', label: '设备名', align: 'center' },
|
||||
{ prop: 'equipmentCode', label: '设备编码', align: 'center' },
|
||||
{ prop: 'plcCode', label: '关联表编码', align: 'center' },
|
||||
{ prop: 'plcTableName', label: '关联表名', align: 'center' },
|
||||
{ prop: 'plcName', label: '标识名称', align: 'center' },
|
||||
{ prop: 'bindingParameters', label: '绑定参数数量', align: 'center' },
|
||||
{ prop: 'productionLine', label: '产线' },
|
||||
{ prop: 'workshopSection', label: '工段' },
|
||||
{ prop: 'equipmentName', label: '设备名' },
|
||||
{ prop: 'equipmentCode', label: '设备编码' },
|
||||
{ prop: 'plcCode', label: '关联表编码' },
|
||||
{ prop: 'plcTableName', label: '关联表名' },
|
||||
{ prop: 'plcName', label: '标识名称' },
|
||||
{ prop: 'bindingParameters', label: '绑定参数数量' },
|
||||
{
|
||||
_action: 'params-bind',
|
||||
label: '查看绑定',
|
||||
align: 'center',
|
||||
subcomponent: {
|
||||
props: ['injectData'],
|
||||
render: function (h) {
|
||||
@ -136,16 +136,18 @@ export default {
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'input',
|
||||
type: 'select',
|
||||
label: '设备名',
|
||||
placeholder: '请输入设备名',
|
||||
placeholder: '请选择设备',
|
||||
param: 'equipmentId',
|
||||
selectOptions: [],
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
label: '编码',
|
||||
placeholder: '请输入编码',
|
||||
type: 'select',
|
||||
label: 'PLC编码',
|
||||
placeholder: '请选择编码',
|
||||
param: 'plcId',
|
||||
selectOptions: [],
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
@ -179,6 +181,7 @@ export default {
|
||||
select: true,
|
||||
label: '关联表名',
|
||||
prop: 'plcId',
|
||||
labelKey: `plcTableName`,
|
||||
url: '/base/equipment-plc/listAll',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
@ -207,8 +210,44 @@ export default {
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.initSearchOptions();
|
||||
},
|
||||
methods: {
|
||||
async getEquipmentOptions() {
|
||||
const res = await this.$axios({
|
||||
url: '/base/equipment/listAll',
|
||||
method: 'get',
|
||||
});
|
||||
return res.data;
|
||||
},
|
||||
|
||||
async getPlcOptions() {
|
||||
const res = await this.$axios({
|
||||
url: '/base/equipment-plc/listAll',
|
||||
method: 'get',
|
||||
});
|
||||
return res.data;
|
||||
},
|
||||
|
||||
/** 初始化查询条件 */
|
||||
async initSearchOptions() {
|
||||
Promise.all([this.getEquipmentOptions(), this.getPlcOptions()]).then(
|
||||
([eqList, plcList]) => {
|
||||
this.searchBarFormConfig[0].selectOptions = eqList.map((item) => {
|
||||
return {
|
||||
name: item.name,
|
||||
id: item.id,
|
||||
};
|
||||
});
|
||||
this.searchBarFormConfig[1].selectOptions = plcList.map((item) => {
|
||||
return {
|
||||
name: item.name,
|
||||
id: item.id,
|
||||
};
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
/** 覆盖 handleEmitFun 的默认实现 */
|
||||
handleEmitFun({ action, payload }) {
|
||||
switch (action) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -68,29 +69,27 @@ export default {
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'plcParamName', label: '参数列名', align: 'center' },
|
||||
{ prop: 'name', label: '参数名称', align: 'center' },
|
||||
{ prop: 'plcParamName', label: '参数列名' },
|
||||
{ prop: 'name', label: '参数名称' },
|
||||
{
|
||||
prop: 'unit',
|
||||
label: '单位',
|
||||
align: 'center',
|
||||
filter: publicFormatter('unit_dict'),
|
||||
},
|
||||
{
|
||||
prop: 'collection',
|
||||
label: '是否采集',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? ['否', '是'][val] : '-'),
|
||||
},
|
||||
{ prop: 'minValue', label: '最小值', align: 'center' },
|
||||
{ prop: 'maxValue', label: '最大值', align: 'center' },
|
||||
{ prop: 'defaultValue', label: '标准值', align: 'center' },
|
||||
{ prop: 'description', label: '描述', align: 'center' },
|
||||
{ prop: 'remark', label: '备注', align: 'center' },
|
||||
{ prop: 'minValue', label: '最小值' },
|
||||
{ prop: 'maxValue', label: '最大值' },
|
||||
{ prop: 'defaultValue', label: '标准值' },
|
||||
{ prop: 'description', label: '描述' },
|
||||
{ prop: 'remark', label: '备注' },
|
||||
// {
|
||||
// _action: 'params-bind',
|
||||
// label: '查看绑定',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// subcomponent: {
|
||||
// props: ['injectData'],
|
||||
// render: function (h) {
|
||||
@ -157,7 +156,7 @@ export default {
|
||||
{
|
||||
type: 'number',
|
||||
message: '请输入正确的数字',
|
||||
trigger: 'blur',
|
||||
trigger: 'change',
|
||||
transform: (val) => Number(val),
|
||||
},
|
||||
],
|
||||
@ -167,10 +166,13 @@ export default {
|
||||
label: '最大值',
|
||||
prop: 'maxValue',
|
||||
rules: [
|
||||
{
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
type: 'number',
|
||||
message: '请输入正确的数字',
|
||||
trigger: 'blur',
|
||||
trigger: 'change',
|
||||
transform: (val) => Number(val),
|
||||
},
|
||||
],
|
||||
@ -349,8 +351,8 @@ export default {
|
||||
plcParamName: undefined,
|
||||
name: undefined,
|
||||
unit: undefined,
|
||||
minValue: undefined,
|
||||
maxValue: undefined,
|
||||
minValue: null,
|
||||
maxValue: null,
|
||||
defaultValue: undefined,
|
||||
collection: undefined,
|
||||
description: undefined,
|
||||
|
@ -16,6 +16,7 @@
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="120"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
@ -147,15 +148,14 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'name', label: '设备名称', align: 'center' },
|
||||
{ prop: 'code', label: '检测编码', align: 'center' },
|
||||
{ prop: 'equipmentType', label: '设备类型', align: 'center' },
|
||||
{ prop: 'enName', label: '英文名称', align: 'center' },
|
||||
{ prop: 'abbr', label: '缩写', align: 'center' },
|
||||
{ prop: 'name', label: '设备名称' },
|
||||
{ width: 256, prop: 'code', label: '检测编码' },
|
||||
{ prop: 'equipmentType', label: '设备类型' },
|
||||
{ prop: 'enName', label: '英文名称' },
|
||||
{ prop: 'abbr', label: '缩写' },
|
||||
{
|
||||
action: 'show-detail',
|
||||
label: '详情',
|
||||
align: 'center',
|
||||
subcomponent: {
|
||||
props: ['injectData'],
|
||||
render: function (h) {
|
||||
@ -377,8 +377,8 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'name', label: '属性名称', align: 'center' },
|
||||
{ prop: 'value', label: '属性值', align: 'center' },
|
||||
{ prop: 'name', label: '属性名称' },
|
||||
{ prop: 'value', label: '属性值' },
|
||||
],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -85,9 +86,9 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'name', label: '设备类型名称', align: 'center' },
|
||||
{ prop: 'code', label: '检测类型编码', align: 'center' },
|
||||
{ prop: 'remark', label: '备注', align: 'center' },
|
||||
{ prop: 'name', label: '设备类型名称', },
|
||||
{ prop: 'code', label: '检测类型编码', },
|
||||
{ prop: 'remark', label: '备注', },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
|
@ -6,7 +6,34 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="pie-chart" :data-eqname="value.equipmentName || 'Default'"></div>
|
||||
<div class="chart-grid-item" style="">
|
||||
<div
|
||||
class="pie-chart"
|
||||
ref="pieChart"
|
||||
:data-eqname="value.equipmentName || 'Default'"></div>
|
||||
<div class="data-view">
|
||||
<div class="data-view__item">
|
||||
<!-- <div class="data-view__item__value">111</div> -->
|
||||
<div class="data-view__item__value">{{ textData.workTime }}</div>
|
||||
<div class="data-view__item__title blue">工作时长</div>
|
||||
</div>
|
||||
<div class="data-view__item">
|
||||
<!-- <div class="data-view__item__value">22</div> -->
|
||||
<div class="data-view__item__value">{{ textData.stopTime }}</div>
|
||||
<div class="data-view__item__title green">停机时长</div>
|
||||
</div>
|
||||
<div class="data-view__item">
|
||||
<!-- <div class="data-view__item__value">10</div> -->
|
||||
<div class="data-view__item__value">{{ textData.downTime }}</div>
|
||||
<div class="data-view__item__title purple">故障时长</div>
|
||||
</div>
|
||||
<div class="data-view__item">
|
||||
<!-- <div class="data-view__item__value">100%</div> -->
|
||||
<div class="data-view__item__value">{{ textData.peEfficiency }}</div>
|
||||
<div class="data-view__item__title yellow">速度开动率</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -19,7 +46,27 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
textData: {
|
||||
workTime: '',
|
||||
downTime: '',
|
||||
stopTime: '',
|
||||
peEfficiency: '',
|
||||
},
|
||||
config: {
|
||||
title: {
|
||||
text: '产线1', //<=========
|
||||
top: '35%',
|
||||
left: '49%',
|
||||
textAlign: 'center',
|
||||
textStyle: {
|
||||
fontSize: 18,
|
||||
},
|
||||
subtext: '设备', //<=========
|
||||
subtextStyle: {
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
color: ['#3da8fd', '#8ef0ab', '#6b5cfd', '#FFC72A', 'transparent'],
|
||||
grid: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
@ -30,6 +77,7 @@ export default {
|
||||
trigger: 'item',
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
top: '0%',
|
||||
left: 'center',
|
||||
textStyle: {
|
||||
@ -39,34 +87,70 @@ export default {
|
||||
itemHeight: 10,
|
||||
},
|
||||
series: [
|
||||
// 嵌套环形图
|
||||
{
|
||||
name: this.value.equipmentName || 'Default',
|
||||
// 外环
|
||||
name: '',
|
||||
type: 'pie',
|
||||
radius: ['40%', '75%'],
|
||||
avoidLabelOverlap: false,
|
||||
radius: ['75%', '90%'],
|
||||
center: ['50%', '45%'],
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center',
|
||||
},
|
||||
data: ['workTime', 'stopTime', 'downTime'].map((v, index) => ({
|
||||
name: ['工作时长', '停机时长', '故障时长'][index],
|
||||
value: this.value[v],
|
||||
})),
|
||||
// data: [
|
||||
// { value: 1048, name: 'Search Engine' },
|
||||
// { value: 735, name: 'Direct' },
|
||||
// { value: 580, name: 'Email' },
|
||||
// { value: 484, name: 'Union Ads' },
|
||||
// { value: 300, name: 'Video Ads' },
|
||||
// ],
|
||||
data: [
|
||||
//<=========
|
||||
{ name: '工作时长', value: 1048 },
|
||||
{ name: '停机时长', value: 735 },
|
||||
{ name: '故障时长', value: 580 },
|
||||
],
|
||||
},
|
||||
{
|
||||
// 内环
|
||||
name: '',
|
||||
type: 'pie',
|
||||
center: ['50%', '45%'],
|
||||
radius: ['60%', '75%'],
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
data: [
|
||||
//<=========
|
||||
{ name: '总', value: 3000 },
|
||||
{ name: '', value: 1400 },
|
||||
],
|
||||
},
|
||||
// {
|
||||
// name: this.value.equipmentName || 'Default',
|
||||
// type: 'pie',
|
||||
// radius: ['40%', '75%'],
|
||||
// avoidLabelOverlap: false,
|
||||
// label: {
|
||||
// show: false,
|
||||
// position: 'center',
|
||||
// },
|
||||
// data: ['workTime', 'stopTime', 'downTime'].map((v, index) => ({
|
||||
// name: ['工作时长', '停机时长', '故障时长'][index],
|
||||
// value: this.value[v],
|
||||
// })),
|
||||
// // data: [
|
||||
// // { value: 1048, name: 'Search Engine' },
|
||||
// // { value: 735, name: 'Direct' },
|
||||
// // { value: 580, name: 'Email' },
|
||||
// // { value: 484, name: 'Union Ads' },
|
||||
// // { value: 300, name: 'Video Ads' },
|
||||
// // ],
|
||||
// },
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
console.log('value', this.value);
|
||||
if (!this.chart) {
|
||||
this.chart = echarts.init(this.$el);
|
||||
this.chart = echarts.init(this.$refs.pieChart);
|
||||
this.$nextTick(() => {
|
||||
this.chart.setOption(this.config);
|
||||
});
|
||||
@ -75,24 +159,120 @@ export default {
|
||||
beforeDestroy() {
|
||||
if (this.chart) this.chart.dispose();
|
||||
},
|
||||
methods: {},
|
||||
watch: {
|
||||
value: {
|
||||
handler(val) {
|
||||
this.updateConfig(val);
|
||||
if (this.chart) this.chart.setOption(this.config);
|
||||
},
|
||||
deep: true,
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
updateConfig(item) {
|
||||
const {
|
||||
lineName, // 产线
|
||||
equipmentName, // 设备
|
||||
downTime, // 故障时长(h)
|
||||
stopTime, // 停机时长(h)
|
||||
workTime, // 工作时长(h)
|
||||
peEfficiency, // 速度开动率
|
||||
timeEfficiency, // 时间开动率
|
||||
//===============//
|
||||
sectionName,
|
||||
workRate,
|
||||
stopRate,
|
||||
downRate,
|
||||
realProcSpeed,
|
||||
designProcSpeed,
|
||||
oee,
|
||||
teep,
|
||||
downCount,
|
||||
mtbf,
|
||||
mttr,
|
||||
} = item;
|
||||
this.config.title.text = lineName;
|
||||
this.config.title.subtext = equipmentName;
|
||||
this.config.series[0].data = [
|
||||
{ name: '工作时长', value: workTime },
|
||||
{ name: '停机时长', value: stopTime },
|
||||
{ name: '故障时长', value: downTime },
|
||||
];
|
||||
this.config.series[1].data = [
|
||||
{ name: '速度开动率', value: peEfficiency },
|
||||
{ name: '', value: Math.ceil(peEfficiency) - peEfficiency },
|
||||
];
|
||||
//
|
||||
this.textData = {
|
||||
workTime: +workTime.toFixed(2),
|
||||
stopTime: +stopTime.toFixed(2),
|
||||
downTime: +downTime.toFixed(2),
|
||||
peEfficiency: +peEfficiency.toFixed(2),
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.pie-chart {
|
||||
.chart-grid-item {
|
||||
padding: 12px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.pie-chart {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
padding: 12px;
|
||||
min-height: 320px;
|
||||
background: #f1f1f1;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pie-chart::before {
|
||||
content: attr(data-eqname);
|
||||
.data-view {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.data-view__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
user-select: none;
|
||||
padding: 0 6px;
|
||||
}
|
||||
|
||||
.data-view__item:not(:last-child) {
|
||||
border-right: 1px solid #f1f1f1;
|
||||
}
|
||||
|
||||
.data-view__item__value {
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
top: -16px;
|
||||
left: 0;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.data-view__item__title {
|
||||
font-size: 8px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.blue {
|
||||
color: #3da8fd;
|
||||
}
|
||||
|
||||
.green {
|
||||
color: #8ef0ab;
|
||||
}
|
||||
|
||||
.purple {
|
||||
color: #6b5cfd;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
color: #ffc72a;
|
||||
}
|
||||
</style>
|
||||
|
@ -13,46 +13,64 @@
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
class="base-table__margin"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun">
|
||||
<!-- :page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize" -->
|
||||
<!-- <method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" /> -->
|
||||
</base-table>
|
||||
<el-row>
|
||||
<el-col class="custom-tabs">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
:stretch="true"
|
||||
@tab-click="handleTabClick">
|
||||
<el-tab-pane :label="'\u2002数据列表\u2002'" name="table">
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
class="base-table__margin"
|
||||
:table-props="tableProps"
|
||||
:page="1"
|
||||
:limit="10"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'\u3000可视化\u3000'" name="graph">
|
||||
<div
|
||||
v-if="activeName == 'graph'"
|
||||
class="graph"
|
||||
style="display: flex; flex-direction: column; position: relative">
|
||||
<div class="blue-title">各设备加工数量</div>
|
||||
<div class="legend">
|
||||
<div class="legend-item">
|
||||
<span class="icon blue"></span>
|
||||
<span class="text">工作时长</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<span class="icon green"></span>
|
||||
<span class="text">停机时长</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<span class="icon purple"></span>
|
||||
<span class="text">故障时长</span>
|
||||
</div>
|
||||
<div class="legend-item">
|
||||
<span class="icon yellow"></span>
|
||||
<span class="text">速度开动率</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="graph-grid">
|
||||
<div class="bg-grid grid-line">
|
||||
<div class="grid-item" v-for="item in list.length" :key="item"></div>
|
||||
</div>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<!-- <pagination
|
||||
v-show="total > 0"
|
||||
:total="total"
|
||||
:page.sync="queryParams.pageNo"
|
||||
:limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" /> -->
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<base-dialog
|
||||
:dialogTitle="visualizationOpen ? '设备可视化' : '查看趋势'"
|
||||
:dialogVisible="open"
|
||||
:width="visualizationOpen ? '80%' : '700px'"
|
||||
@closed="closed"
|
||||
@close="cancel"
|
||||
@cancel="cancel"
|
||||
@confirm="submitForm">
|
||||
<div class="visualization" v-if="visualizationOpen">
|
||||
<pie-chart v-for="item in list" :key="item.id" :value="item" />
|
||||
</div>
|
||||
<div v-if="trendOpen">
|
||||
<h1>查看趋势</h1>
|
||||
</div>
|
||||
</base-dialog>
|
||||
<div class="bg-grid grid-charts">
|
||||
<pie-chart
|
||||
v-for="item in list"
|
||||
:key="item.id"
|
||||
:value="item" />
|
||||
<!-- <pie-chart v-for="item in 5" :key="item" :value="item" /> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -68,6 +86,7 @@ export default {
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
activeName: 'table',
|
||||
open: false,
|
||||
visualizationOpen: false,
|
||||
trendOpen: false,
|
||||
@ -86,84 +105,72 @@ export default {
|
||||
// : undefined,
|
||||
// ].filter((v) => v),
|
||||
tableProps: [
|
||||
{ prop: 'factoryName', label: '工厂', align: 'center' },
|
||||
{ prop: 'lineName', label: '产线', align: 'center' },
|
||||
{ prop: 'sectionName', label: '工段', align: 'center' },
|
||||
{ prop: 'equipmentName', label: '设备', align: 'center' },
|
||||
{ prop: 'factoryName', label: '工厂' },
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'sectionName', label: '工段' },
|
||||
{ prop: 'equipmentName', label: '设备' },
|
||||
{
|
||||
label: '有效时间',
|
||||
align: 'center',
|
||||
children: [
|
||||
{
|
||||
width: 128,
|
||||
prop: 'workTime',
|
||||
label: '工作时长',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'workRate',
|
||||
label: '百分比',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '关机时间',
|
||||
align: 'center',
|
||||
children: [
|
||||
{
|
||||
width: 128,
|
||||
prop: 'stopTime',
|
||||
label: '停机时长',
|
||||
align: 'center',
|
||||
},
|
||||
{ width: 128, prop: 'stopRate', label: '百分比', align: 'center' },
|
||||
{ width: 128, prop: 'stopRate', label: '百分比' },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '中断损失',
|
||||
align: 'center',
|
||||
children: [
|
||||
{
|
||||
width: 128,
|
||||
prop: 'downTime',
|
||||
label: '故障时长',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
|
||||
},
|
||||
{ width: 128, prop: 'downRate', label: '百分比', align: 'center' },
|
||||
{ width: 128, prop: 'downRate', label: '百分比' },
|
||||
{
|
||||
width: 128,
|
||||
prop: 'timeEfficiency',
|
||||
label: '时间开动率',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: '速度损失',
|
||||
align: 'center',
|
||||
children: [
|
||||
{
|
||||
width: 128,
|
||||
prop: 'realProcSpeed',
|
||||
label: '实际加工速度',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'designProcSpeed',
|
||||
label: '理论加工速度',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'peEfficiency',
|
||||
label: '速度开动率',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
|
||||
},
|
||||
],
|
||||
@ -171,19 +178,17 @@ export default {
|
||||
{
|
||||
prop: 'oee',
|
||||
label: 'OEE',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
|
||||
},
|
||||
{
|
||||
prop: 'teep',
|
||||
label: 'TEEP',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
|
||||
},
|
||||
// {
|
||||
// _action: 'view-trend',
|
||||
// label: '趋势',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// subcomponent: {
|
||||
// props: ['injectData'],
|
||||
// render: function (h) {
|
||||
@ -240,7 +245,7 @@ export default {
|
||||
parent: 'dateFilterType',
|
||||
// 时间段选择
|
||||
type: 'datePicker',
|
||||
label: '时间段',
|
||||
// label: '时间段',
|
||||
dateType: 'daterange',
|
||||
format: 'yyyy-MM-dd',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
@ -254,7 +259,7 @@ export default {
|
||||
parent: 'dateFilterType',
|
||||
// 日期选择
|
||||
type: 'datePicker',
|
||||
label: '日期',
|
||||
// label: '日期',
|
||||
dateType: 'date',
|
||||
placeholder: '选择日期',
|
||||
format: 'yyyy-MM-dd',
|
||||
@ -269,16 +274,16 @@ export default {
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '设备可视化',
|
||||
name: 'visualization',
|
||||
plain: true,
|
||||
color: 'success',
|
||||
},
|
||||
// {
|
||||
// type: 'separate',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '设备可视化',
|
||||
// name: 'visualization',
|
||||
// plain: true,
|
||||
// color: 'success',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: 'OEE',
|
||||
@ -364,7 +369,6 @@ export default {
|
||||
params: this.queryParams,
|
||||
});
|
||||
if (code == 0) {
|
||||
console.log('data', data);
|
||||
this.list = data;
|
||||
}
|
||||
},
|
||||
@ -407,6 +411,8 @@ export default {
|
||||
},
|
||||
|
||||
submitForm() {},
|
||||
|
||||
handleTabClick() {},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -416,4 +422,141 @@ export default {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(240px, 1fr));
|
||||
}
|
||||
|
||||
:deep(.custom-tabs) {
|
||||
.el-tabs__header {
|
||||
margin-bottom: 8px;
|
||||
display: inline-block;
|
||||
transform: translateY(-12px);
|
||||
}
|
||||
|
||||
.el-tabs__item {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
line-height: 36px !important;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.blue-title {
|
||||
position: relative;
|
||||
padding: 4px 0;
|
||||
padding-left: 12px;
|
||||
font-size: 14px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 6px;
|
||||
height: 16px;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
background: #0b58ff;
|
||||
}
|
||||
}
|
||||
|
||||
.graph-grid {
|
||||
margin-top: 8px;
|
||||
padding: 12px;
|
||||
position: relative;
|
||||
border-radius: 12px;
|
||||
border: 1px solid #ccc;
|
||||
// background: #0003;
|
||||
}
|
||||
.bg-grid {
|
||||
display: grid;
|
||||
place-content: center;
|
||||
grid-template-columns: repeat(4, minmax(280px, 1fr));
|
||||
grid-auto-columns: 280px;
|
||||
grid-auto-rows: 290px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.grid-line::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
width: calc(100% + 2px);
|
||||
height: calc(100% + 2px);
|
||||
display: inline-block;
|
||||
border: 8px solid #fff;
|
||||
}
|
||||
|
||||
.grid-charts {
|
||||
position: absolute;
|
||||
width: calc(100% - 24px);
|
||||
top: 12px;
|
||||
left: 12px;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.grid-item:not(:first-child) {
|
||||
border-left: 0;
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.legend {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 12px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.legend .legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.legend .legend-item .icon {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 1px;
|
||||
margin-right: 4px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.legend .legend-item .text {
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
.blue {
|
||||
background-color: #3da8fd;
|
||||
}
|
||||
|
||||
.green {
|
||||
background-color: #8ef0ab;
|
||||
}
|
||||
|
||||
.purple {
|
||||
background-color: #6b5cfd;
|
||||
}
|
||||
|
||||
.yellow {
|
||||
background-color: #ffc72a;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1390px) {
|
||||
.bg-grid {
|
||||
grid-template-columns: repeat(3, minmax(280px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1190px) {
|
||||
.bg-grid {
|
||||
grid-template-columns: repeat(2, minmax(280px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 640px) {
|
||||
.bg-grid {
|
||||
grid-template-columns: repeat(1, minmax(280px, 1fr));
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -50,39 +50,47 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
searchBarKeys: ['name', 'code'],
|
||||
// tableBtn: [
|
||||
// this.$auth.hasPermi('base:equipment-group:update')
|
||||
// ? {
|
||||
// type: 'edit',
|
||||
// btnName: '修改',
|
||||
// }
|
||||
// : undefined,
|
||||
// this.$auth.hasPermi('base:equipment-group:delete')
|
||||
// ? {
|
||||
// type: 'delete',
|
||||
// btnName: '删除',
|
||||
// }
|
||||
// : undefined,
|
||||
// ].filter((v) => v),
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:equipment-group:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:equipment-group:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
}
|
||||
: undefined,
|
||||
].filter((v) => v),
|
||||
tableProps: [
|
||||
{ prop: 'lineName', label: '产线', align: 'center' },
|
||||
{ prop: 'sectionName', label: '工段', align: 'center' },
|
||||
{ prop: 'equipmentName', label: '设备', align: 'center' },
|
||||
{
|
||||
width: 188,
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
},
|
||||
{
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
},
|
||||
],
|
||||
tableProps: [
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'sectionName', label: '工段' },
|
||||
{ prop: 'equipmentName', label: '设备' },
|
||||
{
|
||||
width: 240,
|
||||
prop: 'mtbf',
|
||||
label: '平均故障间隔时间[MTBF](h)',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 180,
|
||||
width: 240,
|
||||
prop: 'mttr',
|
||||
label: '平均维修时间[MTTR](h)',
|
||||
align: 'center',
|
||||
},
|
||||
{ prop: 'workTime', label: '工作时长(h)', align: 'center' },
|
||||
{ prop: 'downTime', label: '故障时长(h)', align: 'center' },
|
||||
{ prop: 'downCount', label: '故障次数', align: 'center' },
|
||||
{ width: 128, prop: 'workTime', label: '工作时长(h)' },
|
||||
{ width: 128, prop: 'downTime', label: '故障时长(h)' },
|
||||
{ prop: 'downCount', label: '故障次数' },
|
||||
],
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
@ -113,6 +121,8 @@ export default {
|
||||
],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
lineId: null,
|
||||
factoryId: null,
|
||||
recordTime: null,
|
||||
@ -162,15 +172,13 @@ export default {
|
||||
this.queryParams.recordTime = [
|
||||
moment()
|
||||
.month(btn.month - 1)
|
||||
.format('YYYY-MM')+'-01 00:00:00',
|
||||
moment()
|
||||
.month(btn.month)
|
||||
.format('YYYY-MM')+'-01 00:00:00',
|
||||
.format('YYYY-MM') + '-01 00:00:00',
|
||||
moment().month(btn.month).format('YYYY-MM') + '-01 00:00:00',
|
||||
];
|
||||
} else {
|
||||
this.queryParams.recordTime = null;
|
||||
}
|
||||
this.queryParams.lineId = btn.lineId || null;
|
||||
this.queryParams.lineId = btn.lineId || null;
|
||||
this.handleQuery();
|
||||
break;
|
||||
}
|
||||
|
@ -15,27 +15,143 @@ import * as echarts from 'echarts';
|
||||
export default {
|
||||
name: 'LineChart',
|
||||
components: {},
|
||||
props: ['config'],
|
||||
props: ['config', 'list'],
|
||||
data() {
|
||||
return {
|
||||
chart: null,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
// watch: {
|
||||
// list: {
|
||||
// handler(listdata) {
|
||||
// if (listdata && listdata.length) {
|
||||
// console.log('[linechart] list changed', listdata);
|
||||
// const option = this.handleList(listdata);
|
||||
// this.setOption(option);
|
||||
// }
|
||||
// },
|
||||
// immediate: true,
|
||||
// },
|
||||
// },
|
||||
computed: {
|
||||
option() {
|
||||
const opt = [];
|
||||
this.list.map((eq) => {
|
||||
/** [设备名, ok数量, 不ok数量] */
|
||||
opt.push([eq.equipmentName, eq.okQuantity, eq.nokQuantity]);
|
||||
});
|
||||
return {
|
||||
color: ['#288AFF', '#8EF0AB'],
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
right: 0
|
||||
},
|
||||
grid: {
|
||||
left: '1%',
|
||||
right: '1%',
|
||||
top: '8%',
|
||||
bottom: '3%',
|
||||
containLabel: true,
|
||||
},
|
||||
// xAxis: [
|
||||
// {
|
||||
// type: 'category',
|
||||
// data: ['设备1', '设备2', '设备3', '设备4', '设备5'],
|
||||
// },
|
||||
// ],
|
||||
// yAxis: [
|
||||
// {
|
||||
// type: 'value',
|
||||
// splitLine: {
|
||||
// lineStyle: {
|
||||
// color: '#0001',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// ],
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
axisTick: { show: false },
|
||||
data: opt.map((item) => item[0]),
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: '#0001',
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '合格数量',
|
||||
type: 'bar',
|
||||
barWidth: 20,
|
||||
stack: 's',
|
||||
data: opt.map((item) => item[1]),
|
||||
},
|
||||
{
|
||||
name: '不合格数量',
|
||||
type: 'bar',
|
||||
barWidth: 20,
|
||||
stack: 's',
|
||||
data: opt.map((item) => item[2]),
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
console.log('[linechart] mounted');
|
||||
this.init();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.chart) {
|
||||
this.chart.dispose();
|
||||
}
|
||||
console.log('[linechart] destroyed');
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
console.log('thsi el', this.$el);
|
||||
if (!this.chart) this.chart = echarts.init(this.$el);
|
||||
this.chart.setOption(this.config);
|
||||
console.log('[linechart] initialized', this.$el);
|
||||
this.$nextTick(() => {
|
||||
this.setOption();
|
||||
});
|
||||
},
|
||||
|
||||
setOption() {
|
||||
if (this.chart) this.chart.setOption(this.option);
|
||||
console.log('[linechart] option settled');
|
||||
},
|
||||
|
||||
// handleList(list) {
|
||||
// /** 清空数据 */
|
||||
// this.option.series[0].data.splice(0);
|
||||
// this.option.series[1].data.splice(0);
|
||||
// this.option.xAxis.data.splice(0);
|
||||
|
||||
// list.map((eq) => {
|
||||
// this.option.xAxis.data.push(eq.equipmentName);
|
||||
// this.option.series[0].data.push(eq.nokQuantity);
|
||||
// this.option.series[1].data.push(eq.okQuantity);
|
||||
// });
|
||||
|
||||
// this.setOption();
|
||||
|
||||
// // const pureList = list.map((eq) => ({
|
||||
// // name: eq.equipmentName,
|
||||
// // ok: eq.okQuantity,
|
||||
// // nok: eq.nokQuantity,
|
||||
// // }));
|
||||
// },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@ -43,7 +159,7 @@ export default {
|
||||
<style scoped lang="scss">
|
||||
.line-chart {
|
||||
padding: 0 12px;
|
||||
background: #e1e1e1;
|
||||
min-height: 320px;
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
|
@ -13,28 +13,35 @@
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
|
||||
<!-- 图形分析 dialog -->
|
||||
<!-- <base-dialog
|
||||
dialogTitle="图形视角"
|
||||
:dialogVisible="dialogVisible"
|
||||
width="60%"
|
||||
@close="dialogClose"
|
||||
@cancel="dialogClose"
|
||||
@confirm="dialogClose">
|
||||
<LineChart v-if="dialogVisible" :config="lineChartConfig" />
|
||||
</base-dialog> -->
|
||||
<el-row>
|
||||
<el-col class="custom-tabs">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
:stretch="true"
|
||||
@tab-click="handleTabClick">
|
||||
<el-tab-pane :label="'数据列表'" name="table">
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'\u3000柱状图\u3000'" name="graph">
|
||||
<div v-if="activeName == 'graph'" class="graph" style="height: 40vh; display: flex; flex-direction: column;">
|
||||
<div class="blue-title">各设备加工数量</div>
|
||||
<LineChart :list="list" />
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import LineChart from './components/lineChart.vue';
|
||||
|
||||
export default {
|
||||
@ -42,12 +49,14 @@ export default {
|
||||
components: { LineChart },
|
||||
props: {},
|
||||
data() {
|
||||
const now = new Date();
|
||||
const [y, m, d] = [now.getFullYear(), now.getMonth(), now.getDate()];
|
||||
return {
|
||||
dialogVisible: false,
|
||||
urls: {
|
||||
page: '/analysis/equipment-analysis/quality',
|
||||
},
|
||||
mode: 'table', // defaults to 'table'
|
||||
activeName: 'table', // defaults to 'table'
|
||||
searchBarFormConfig: [
|
||||
// 产品
|
||||
{
|
||||
@ -72,13 +81,30 @@ export default {
|
||||
dateType: 'daterange', // datetimerange
|
||||
// format: 'yyyy-MM-dd HH:mm:ss',
|
||||
format: 'yyyy-MM-dd',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
// valueFormat: 'timestamp',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
rangeSeparator: '-',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期',
|
||||
defaultTime: ['00:00:00', '23:59:59'],
|
||||
param: 'recordTime',
|
||||
defaultSelect: [
|
||||
new Date(y, m, d)
|
||||
.toLocaleString()
|
||||
.split('/')
|
||||
.map((item, index) => {
|
||||
if (index == 1 || index == 2) return item.padStart(2, '0');
|
||||
return item;
|
||||
})
|
||||
.join('-'),
|
||||
new Date(y, m, d, 23, 59, 59)
|
||||
.toLocaleString()
|
||||
.split('/')
|
||||
.map((item, index) => {
|
||||
if (index == 1 || index == 2) return item.padStart(2, '0');
|
||||
return item;
|
||||
})
|
||||
.join('-'),
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
@ -86,9 +112,9 @@ export default {
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
// {
|
||||
// type: 'separate',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '列表数据',
|
||||
@ -111,43 +137,36 @@ export default {
|
||||
// width: 160,
|
||||
prop: 'sectionName',
|
||||
label: '工段',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'equipmentName',
|
||||
label: '设备名称',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'products',
|
||||
label: '产品名称',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'inQuantity',
|
||||
label: '进片数量',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'outQuantity',
|
||||
label: '出片数量',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'nokQuantity',
|
||||
label: '破损/不合格数',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'passRate',
|
||||
label: '合格率',
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
lineChartConfig: {
|
||||
@ -161,14 +180,14 @@ export default {
|
||||
top: 0,
|
||||
left: 0,
|
||||
padding: 5,
|
||||
icon: 'roundRect',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
itemGap: 20,
|
||||
icon: 'roundRect',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
itemGap: 20,
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
lineHeight: 14
|
||||
},
|
||||
fontSize: 14,
|
||||
lineHeight: 14,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
@ -176,13 +195,13 @@ export default {
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '合格率',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
fontSize: 14,
|
||||
align: 'right'
|
||||
},
|
||||
nameGap: 26
|
||||
name: '合格率',
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
fontSize: 14,
|
||||
align: 'right',
|
||||
},
|
||||
nameGap: 26,
|
||||
},
|
||||
series: [
|
||||
{
|
||||
@ -229,6 +248,11 @@ export default {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
handleTabClick(tab, event) {
|
||||
// console.log('tab event', tab, event);
|
||||
// tab is el-tab vue component.
|
||||
},
|
||||
|
||||
async fillLineOptions() {
|
||||
const { data } = await this.$axios({
|
||||
url: '/base/production-line/listAll',
|
||||
@ -340,4 +364,38 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.custom-tabs) {
|
||||
.el-tabs__header {
|
||||
margin-bottom: 8px;
|
||||
display: inline-block;
|
||||
transform: translateY(-12px);
|
||||
}
|
||||
|
||||
.el-tabs__item {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
line-height: 36px !important;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.blue-title {
|
||||
position: relative;
|
||||
padding: 4px 0;
|
||||
padding-left: 12px;
|
||||
font-size: 14px;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 6px;
|
||||
height: 16px;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
background: #0b58ff;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -21,7 +21,14 @@ export default {
|
||||
chart: null,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
watch: {
|
||||
config: {
|
||||
handler(value) {
|
||||
if (value != null) this.setOption(value);
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
@ -32,9 +39,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
console.log('thsi el', this.$el);
|
||||
if (!this.chart) this.chart = echarts.init(this.$el);
|
||||
this.chart.setOption(this.config);
|
||||
this.setOption(this.config);
|
||||
},
|
||||
setOption(option) {
|
||||
if (this.chart) this.chart.setOption(option);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -6,25 +6,44 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<h1>设备产量时序图</h1>
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar
|
||||
:formConfigs="searchBarFormConfig"
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
<div
|
||||
class="production-timegraph-container"
|
||||
style="background: #f2f4f9; flex: 1">
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<div class="blue-title">生产节拍时序图</div>
|
||||
<!-- <h1>设备状态时序图</h1> -->
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar
|
||||
:formConfigs="searchBarFormConfig"
|
||||
ref="search-bar"
|
||||
:remove-blue="true"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
</el-row>
|
||||
|
||||
<div class="main-area">
|
||||
<div class="graphs" v-if="graphList.length">
|
||||
<div class="graph" v-for="(eq, index) in graphList" :key="eq.key">
|
||||
<h2 class="graph-title">{{ eq.key }}</h2>
|
||||
<LineChart
|
||||
:key="eq.key + '__linechart'"
|
||||
:config="getRealConfig(index)" />
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 24px;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<div class="blue-title">设备产量时序图</div>
|
||||
|
||||
<div class="main-area">
|
||||
<div class="graphs" v-if="graphList.length">
|
||||
<LineChart :config="templateConfig" />
|
||||
</div>
|
||||
<div class="no-data-bg" v-else></div>
|
||||
</div>
|
||||
<h2 v-else>请添加设备</h2>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<base-dialog
|
||||
@ -58,6 +77,7 @@ export default {
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
accumulators: new Map(),
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'select',
|
||||
@ -77,15 +97,16 @@ export default {
|
||||
{
|
||||
type: 'datePicker',
|
||||
label: '时间段',
|
||||
dateType: 'daterange', // datetimerange
|
||||
dateType: 'date', // datetimerange
|
||||
// format: 'yyyy-MM-dd HH:mm:ss',
|
||||
format: 'yyyy-MM-dd',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
// valueFormat: 'timestamp',
|
||||
rangeSeparator: '-',
|
||||
startPlaceholder: '开始日期',
|
||||
endPlaceholder: '结束日期',
|
||||
defaultTime: ['00:00:00', '23:59:59'],
|
||||
// rangeSeparator: '-',
|
||||
// startPlaceholder: '开始日期',
|
||||
// endPlaceholder: '结束日期',
|
||||
// defaultTime: ['00:00:00', '23:59:59'],
|
||||
placeholder: '选择日期',
|
||||
param: 'recordTime',
|
||||
},
|
||||
{
|
||||
@ -99,9 +120,9 @@ export default {
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '设备对比',
|
||||
btnName: '添加对比',
|
||||
name: 'compare',
|
||||
color: 'warning',
|
||||
color: 'primary',
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
@ -115,30 +136,47 @@ export default {
|
||||
eqList: [],
|
||||
graphList: [],
|
||||
templateConfig: {
|
||||
color: ['#283D68', '#FFB61F', '#4481FF', '#5AD8A6', '#E97466'],
|
||||
grid: {
|
||||
top: 88,
|
||||
left: 56,
|
||||
right: 56,
|
||||
bottom: 56,
|
||||
top: 48,
|
||||
left: 48,
|
||||
right: 24,
|
||||
bottom: 24,
|
||||
},
|
||||
legend: {
|
||||
top: 0,
|
||||
left: 0,
|
||||
padding: 5,
|
||||
icon: 'roundRect',
|
||||
itemWidth: 12,
|
||||
itemHeight: 12,
|
||||
right: 12,
|
||||
padding: 6,
|
||||
itemWidth: 16,
|
||||
itemHeight: 8,
|
||||
itemGap: 20,
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
lineHeight: 14,
|
||||
fontSize: 12,
|
||||
lineHeight: 12,
|
||||
color: '#0007',
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
show: true,
|
||||
trigger: 'axis',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: Array(24)
|
||||
.fill(1)
|
||||
.map((item, index) => `${index}:00`),
|
||||
boundaryGap: true,
|
||||
axisTick: {
|
||||
// show: false,
|
||||
alignWithLabel: true,
|
||||
lineStyle: {
|
||||
color: '#0003',
|
||||
},
|
||||
},
|
||||
axisLabel: {
|
||||
color: '#0007',
|
||||
},
|
||||
data: [],
|
||||
// data: Array(24)
|
||||
// .fill(1)
|
||||
// .map((item, index) => `${index}:00`),
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
@ -146,19 +184,41 @@ export default {
|
||||
nameLocation: 'end',
|
||||
nameTextStyle: {
|
||||
fontSize: 14,
|
||||
align: 'right',
|
||||
align: 'center',
|
||||
},
|
||||
nameGap: 26,
|
||||
max: function (value) {
|
||||
return value.max + Math.floor(value.max / 5);
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '产线1',
|
||||
data: Array(24)
|
||||
.fill(1)
|
||||
.map(() => Math.random() * 100),
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
},
|
||||
// {
|
||||
// name: '产线1',
|
||||
// data: Array(24)
|
||||
// .fill(1)
|
||||
// .map(() => Math.random() * 100),
|
||||
// type: 'line',
|
||||
// symbol: 'circle',
|
||||
// // smooth: true,
|
||||
// },
|
||||
// {
|
||||
// name: '产线2',
|
||||
// data: Array(24)
|
||||
// .fill(1)
|
||||
// .map(() => Math.random() * 100),
|
||||
// type: 'line',
|
||||
// symbol: 'circle',
|
||||
// // smooth: true,
|
||||
// },
|
||||
// {
|
||||
// name: '产线3',
|
||||
// data: Array(24)
|
||||
// .fill(1)
|
||||
// .map(() => Math.random() * 100),
|
||||
// type: 'line',
|
||||
// symbol: 'circle',
|
||||
// // smooth: true,
|
||||
// },
|
||||
],
|
||||
},
|
||||
};
|
||||
@ -176,7 +236,12 @@ export default {
|
||||
this.queryParams.lineId = payload.lineId || null;
|
||||
this.queryParams.sectionId = payload.sectionId || null;
|
||||
this.queryParams.equipmentId = payload.equipmentId || null;
|
||||
this.queryParams.recordTime = payload.recordTime || null;
|
||||
this.queryParams.recordTime = payload.recordTime
|
||||
? [
|
||||
payload.recordTime,
|
||||
payload.recordTime.replace('00:00:00', '23:59:59'),
|
||||
]
|
||||
: null;
|
||||
this.getList();
|
||||
break;
|
||||
case 'compare':
|
||||
@ -230,10 +295,41 @@ export default {
|
||||
// ];
|
||||
// eq2.key = 'SS2';
|
||||
// this.graphList = [eq1, eq2];
|
||||
console.log('graph list', this.graphList);
|
||||
|
||||
this.graphList.forEach(this.setSeries);
|
||||
} else {
|
||||
this.graphList = [];
|
||||
this.graphList.forEach(this.setSeries);
|
||||
}
|
||||
},
|
||||
|
||||
setSeries(eqArr) {
|
||||
if (eqArr.length == 0) {
|
||||
this.templateConfig.series = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let isInit = false;
|
||||
if (this.accumulators.has(eqArr.key) == false) {
|
||||
this.accumulators.set(eqArr.key, 0);
|
||||
isInit = true;
|
||||
}
|
||||
|
||||
let accumulator = this.accumulators.get(eqArr.key);
|
||||
if ((accumulator && !isInit) || (accumulator == 0 && isInit == false)) {
|
||||
accumulator++;
|
||||
this.accumulators.set(eqArr.key, accumulator);
|
||||
}
|
||||
|
||||
this.templateConfig.series.push({
|
||||
name: eqArr.key + (accumulator == 0 ? '' : '-' + accumulator),
|
||||
// name: Math.random(),
|
||||
type: 'line',
|
||||
symbol: 'circle',
|
||||
data: this.getEquipmentQuantity(eqArr),
|
||||
});
|
||||
},
|
||||
|
||||
/** 获得设备产量 */
|
||||
getEquipmentQuantity(equipmentArr) {
|
||||
return equipmentArr.map((item) => item.totalQuantity);
|
||||
@ -246,19 +342,6 @@ export default {
|
||||
);
|
||||
},
|
||||
|
||||
getRealConfig(index) {
|
||||
// if (!this.graphList || this.graphList.length == 0) return;
|
||||
const config = JSON.parse(JSON.stringify(this.templateConfig));
|
||||
// config.legend.data = this.graphList[index].key;
|
||||
config.series[0].name = this.graphList[index]?.key;
|
||||
// console.log("this.graphList?.[index]", this.graphList?.[index]);
|
||||
config.series[0].data = this.getEquipmentQuantity(
|
||||
this.graphList?.[index] || []
|
||||
);
|
||||
config.xAxis.data = this.getTimeinfo(this.graphList?.[index] || []);
|
||||
return config;
|
||||
},
|
||||
|
||||
/** 准备设备数据 */
|
||||
async initEquipment() {
|
||||
const { code, data } = await this.$axios({
|
||||
@ -313,18 +396,42 @@ export default {
|
||||
method: 'get',
|
||||
params: this.queryParams,
|
||||
});
|
||||
|
||||
this.queryParams.equipmentId = null; // 清空一下
|
||||
if (code == 0) {
|
||||
const newEqlist = this.objectToArray(data);
|
||||
if (!newEqlist || newEqlist.length == 0) {
|
||||
this.$message.error('该设备没有产量数据');
|
||||
return;
|
||||
}
|
||||
this.graphList.push(newEqlist[0]);
|
||||
this.graphList.push(...newEqlist);
|
||||
newEqlist.forEach(this.setSeries);
|
||||
}
|
||||
this.open = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style scoped lang="scss">
|
||||
.blue-title {
|
||||
position: relative;
|
||||
padding: 4px 0;
|
||||
padding-left: 12px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 6px;
|
||||
height: 16px;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
background: #0b58ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -6,29 +6,51 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<h1>设备状态时序图</h1>
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar
|
||||
:formConfigs="searchBarFormConfig"
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
<div class="status-timegraph-container" style="background: #f2f4f9; flex: 1">
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<div class="blue-title">生产节拍时序图</div>
|
||||
<!-- <h1>设备状态时序图</h1> -->
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar
|
||||
:formConfigs="searchBarFormConfig"
|
||||
ref="search-bar"
|
||||
:remove-blue="true"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
</el-row>
|
||||
|
||||
<div class="main-area">
|
||||
<div class="legend-row">
|
||||
<div class="legend">
|
||||
<div class="icon running"></div>
|
||||
<div>运行中</div>
|
||||
</div>
|
||||
<!-- <div class="legend">
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 32px;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="6">
|
||||
<div class="blue-title">设备状态时序图</div>
|
||||
</el-col>
|
||||
<el-col :span="18" class="legend-row">
|
||||
<div class="legend">
|
||||
<div class="icon running"></div>
|
||||
<div>运行中</div>
|
||||
</div>
|
||||
<!-- <div class="legend">
|
||||
<div class="icon waiting"></div>
|
||||
<div>待机</div>
|
||||
</div> -->
|
||||
<div class="legend">
|
||||
<div class="icon fault"></div>
|
||||
<div>故障</div>
|
||||
</div>
|
||||
<!-- <div class="legend">
|
||||
<div class="legend">
|
||||
<div class="icon fault"></div>
|
||||
<div>故障</div>
|
||||
</div>
|
||||
<!-- <div class="legend">
|
||||
<div class="icon lack"></div>
|
||||
<div>缺料</div>
|
||||
</div>
|
||||
@ -36,83 +58,51 @@
|
||||
<div class="icon full"></div>
|
||||
<div>满料</div>
|
||||
</div> -->
|
||||
<div class="legend">
|
||||
<div class="icon stop"></div>
|
||||
<div>计划停机</div>
|
||||
<div class="legend">
|
||||
<div class="icon stop"></div>
|
||||
<div>计划停机</div>
|
||||
</div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<div class="main-area">
|
||||
<div class="graphs" v-if="graphList.length">
|
||||
<div class="graph" v-for="eq in graphList" :key="eq.key">
|
||||
<h2 class="graph-title">{{ eq.key }}</h2>
|
||||
|
||||
<div class="graph-content">
|
||||
<el-popover
|
||||
trigger="hover"
|
||||
v-for="blc in eq"
|
||||
:key="blc.startTime"
|
||||
:title="
|
||||
blc.status == 0
|
||||
? '运行'
|
||||
: blc.status == 2
|
||||
? '故障'
|
||||
: '计划停机'
|
||||
"
|
||||
placement="top"
|
||||
:content="new Date(blc.startTime).toLocaleTimeString()">
|
||||
<div
|
||||
slot="reference"
|
||||
:key="blc.startTime + '__div'"
|
||||
class="graph-item-fixed tick"
|
||||
:class="{
|
||||
running: blc.status == 0,
|
||||
fault: blc.status == 2,
|
||||
stop: blc.status == 1,
|
||||
}"
|
||||
:style="{ height: '32px', width: blc.duration * 2 + 'px' }"
|
||||
:data-time="
|
||||
new Date(blc.startTime).toLocaleTimeString()
|
||||
"></div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<h2 v-else>请添加设备</h2>
|
||||
</div>
|
||||
<div class="graphs" v-if="graphList.length">
|
||||
<!-- <div class="graph">
|
||||
<h2 class="graph-title">设备1</h2>
|
||||
<div class="graph-item running tick" data-time="00:00"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item lack tick" data-time="03:00"></div>
|
||||
<div class="graph-item full tick" data-time="04:00"></div>
|
||||
<div class="graph-item waiting tick" data-time="05:00"></div>
|
||||
<div class="graph-item running tick" data-time="06:00"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item fault tick" data-time="08:00"></div>
|
||||
<div class="graph-item waiting tick" data-time="09:00"></div>
|
||||
<div class="graph-item running tick" data-time="10:00"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item lack tick" data-time="13:00"></div>
|
||||
<div class="graph-item full tick" data-time="14:00"></div>
|
||||
<div class="graph-item running tick" data-time="15:00"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item fault tick" data-time="18:00"></div>
|
||||
<div class="graph-item running tick" data-time="19:00"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item running"></div>
|
||||
<div class="graph-item stop tick" data-time="23:00"></div>
|
||||
</div> -->
|
||||
<div class="graph" v-for="eq in graphList" :key="eq.key">
|
||||
<h2 class="graph-title">{{ eq.key }}</h2>
|
||||
<div
|
||||
v-for="blc in eq"
|
||||
:key="blc.startTime"
|
||||
class="graph-item-fixed tick"
|
||||
:class="{
|
||||
running: blc.status == 0,
|
||||
fault: blc.status == 2,
|
||||
stop: blc.status == 1,
|
||||
}"
|
||||
:style="{ width: blc.duration * 2 + 'px' }"
|
||||
:data-time="new Date(blc.startTime).toLocaleTimeString()"></div>
|
||||
</div>
|
||||
<!-- <div class="graph">
|
||||
<h2 class="graph-title">设备3</h2>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
<div class="graph-item"></div>
|
||||
</div> -->
|
||||
</div>
|
||||
<h2 v-else>请添加设备</h2>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
<base-dialog
|
||||
@ -185,9 +175,9 @@ export default {
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '设备对比',
|
||||
btnName: '添加对比',
|
||||
name: 'compare',
|
||||
color: 'warning',
|
||||
color: 'primary',
|
||||
plain: true,
|
||||
},
|
||||
],
|
||||
@ -344,26 +334,52 @@ export default {
|
||||
|
||||
<style scoped lang="scss">
|
||||
.graph {
|
||||
border: 1px solid #ccc;
|
||||
padding: 12px 12px 28px 12px;
|
||||
margin: 64px 0;
|
||||
// border: 1px solid #ccc;
|
||||
// padding: 12px 12px 28px 12px;
|
||||
// margin: 64px 0;
|
||||
position: relative;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.graph-title {
|
||||
position: absolute;
|
||||
top: -64px;
|
||||
left: -1px;
|
||||
padding: 8px 18px;
|
||||
background: #ccc;
|
||||
font-size: 18px;
|
||||
// position: absolute;
|
||||
// top: -64px;
|
||||
// left: -1px;
|
||||
// padding: 8px 18px;
|
||||
padding: 0 12px;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.graph-content {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
padding: 22px 12px;
|
||||
border: 1px solid #ccc;
|
||||
border-bottom-width: 2px;
|
||||
border-top: none;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.graph-content::after,
|
||||
.graph-content::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 3px;
|
||||
height: 80%;
|
||||
background: #fff;
|
||||
right: -1px;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.graph-content::before {
|
||||
right: unset;
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.graph-item,
|
||||
.graph-item-fixed {
|
||||
height: 88px;
|
||||
// height: 88px;
|
||||
// width: 24px;
|
||||
flex: 1;
|
||||
// border: 1px solid #ccc;
|
||||
@ -405,32 +421,40 @@ export default {
|
||||
}
|
||||
|
||||
.running {
|
||||
background-color: #84f04e;
|
||||
background-color: #5ad8a6;
|
||||
// background-color: #84f04e;
|
||||
}
|
||||
|
||||
.waiting {
|
||||
background-color: #409eff;
|
||||
background-color: #5ad8a6;
|
||||
// background-color: #409eff;
|
||||
}
|
||||
|
||||
.fault {
|
||||
background-color: #ea5b5b;
|
||||
// background-color: #ea5b5b;
|
||||
background-color: #fc9c91;
|
||||
}
|
||||
|
||||
.full {
|
||||
background-color: #e6a23c;
|
||||
// background-color: #e6a23c;
|
||||
background-color: #598fff;
|
||||
}
|
||||
|
||||
.lack {
|
||||
background-color: #a69c8d;
|
||||
// background-color: #a69c8d;
|
||||
background-color: #7585a2;
|
||||
}
|
||||
|
||||
.stop {
|
||||
background-color: #000c;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.legend-row {
|
||||
margin: 12px 0;
|
||||
margin: 6px 0;
|
||||
padding-right: 12px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
> .legend:not(:last-child) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
@ -441,9 +465,32 @@ export default {
|
||||
}
|
||||
|
||||
.icon {
|
||||
width: 16px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 2px;
|
||||
margin-right: 4px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.blue-title {
|
||||
position: relative;
|
||||
padding: 4px 0;
|
||||
padding-left: 12px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 6px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
background: #0b58ff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -16,6 +16,7 @@
|
||||
<method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
:width="120"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
@ -81,13 +82,12 @@ export default {
|
||||
: undefined,
|
||||
].filter((v) => v),
|
||||
tableProps: [
|
||||
{ width: 128, prop: 'productionLine', label: '产线', align: 'center' },
|
||||
{ width: 128, prop: 'workshopSection', label: '工段', align: 'center' },
|
||||
{ width: 128, prop: 'equipment', label: '设备名称', align: 'center' },
|
||||
{ width: 128, prop: 'productionLine', label: '产线' },
|
||||
{ width: 128, prop: 'workshopSection', label: '工段' },
|
||||
{ width: 128, prop: 'equipment', label: '设备名称' },
|
||||
{
|
||||
prop: 'alarmGrade',
|
||||
label: '报警级别',
|
||||
align: 'center',
|
||||
filter: publicFormatter(this.DICT_TYPE.EQU_ALARM_LEVEL),
|
||||
},
|
||||
{
|
||||
@ -96,11 +96,11 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'alarmContent', label: '报警内容', align: 'center' },
|
||||
{ prop: 'alarmContent', label: '报警内容' },
|
||||
// {
|
||||
// _action: 'equipment-group-show-alert',
|
||||
// label: '报警',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// subcomponent: {
|
||||
// props: ['injectData'],
|
||||
// render: function (h) {
|
||||
@ -166,7 +166,7 @@ export default {
|
||||
this.getList();
|
||||
},
|
||||
methods: {
|
||||
/** 重写 basicPageMixin 里的 handleSearchBarBtnClick */
|
||||
/** 重写 basicPageMixin 里的 handleSearchBarBtnClick */
|
||||
handleSearchBarBtnClick(btn) {
|
||||
// 仅查询一种情况
|
||||
this.queryParams.createTime = btn.createTime;
|
||||
|
@ -35,7 +35,9 @@
|
||||
" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else style="margin-top: 20px; color: #c7c7c7; text-align: center;">暂无数据</div>
|
||||
<div v-else style="margin-top: 20px; color: #c7c7c7; text-align: center">
|
||||
暂无数据
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -139,19 +141,16 @@ export default {
|
||||
width: 48,
|
||||
prop: 'index',
|
||||
label: '序号',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 160,
|
||||
prop: 'time',
|
||||
label: '时间',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 200,
|
||||
prop: 'plcCode',
|
||||
label: 'PLC编码',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
const firstLineData = {
|
||||
@ -162,7 +161,6 @@ export default {
|
||||
otherList.forEach((item) => {
|
||||
props.push({
|
||||
label: item.name,
|
||||
align: 'center',
|
||||
prop: item.name,
|
||||
width: 128,
|
||||
});
|
||||
|
@ -25,7 +25,7 @@ export default {
|
||||
grid: {
|
||||
top: 64,
|
||||
left: 56,
|
||||
right: 24,
|
||||
right: 64,
|
||||
bottom: 56,
|
||||
},
|
||||
title: {
|
||||
@ -64,6 +64,10 @@ export default {
|
||||
color: '#ccc',
|
||||
},
|
||||
},
|
||||
name: '数量',
|
||||
nameTextStyle: {
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
|
@ -9,15 +9,52 @@
|
||||
<div style="flex: 1; display: flex; background: #f2f4f9">
|
||||
<div
|
||||
class="app-container"
|
||||
style="margin-right: 12px; border-radius: 8px; background: #fff">
|
||||
<!-- side bar -->
|
||||
style="
|
||||
margin-right: 12px;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
padding: 0;
|
||||
">
|
||||
<div
|
||||
class="side-bar__left"
|
||||
style="width: 240px; padding: 12px; height: 100%">
|
||||
class="factory-list__selector"
|
||||
style="margin: 12px"
|
||||
title="点击切换工厂"
|
||||
@mouseenter="factoryListOpen = true"
|
||||
@mouseleave="factoryListOpen = false">
|
||||
{{ currentFactory?.label || '工厂名称' }}
|
||||
<div class="factory-list__wrapper" :class="{ open: factoryListOpen }">
|
||||
<ul
|
||||
class="factory-list"
|
||||
v-if="sidebarContent.length"
|
||||
@click.prevent="factoryChangeHandler">
|
||||
<li
|
||||
v-for="fc in sidebarContent"
|
||||
:key="fc.id"
|
||||
:data-value="fc.id"
|
||||
class="factory-list__item"
|
||||
:class="{ 'is-current': fc.id == currentFactory?.id }">
|
||||
{{ fc.label }}
|
||||
</li>
|
||||
</ul>
|
||||
<div v-else style="color: #0008; width: 128px; text-align: center">
|
||||
- 无 -
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- side bar -->
|
||||
<div class="side-bar__left" style="width: 240px; height: 100%">
|
||||
<el-tree
|
||||
:data="sidebarContent"
|
||||
class="custom-tree-class"
|
||||
:data="currentFactory?.children"
|
||||
:props="treeProps"
|
||||
@node-click="handleSidebarItemClick" />
|
||||
:empty-text="' - 暂无数据 - '"
|
||||
icon-class="custom-icon-class"
|
||||
@node-click="handleSidebarItemClick">
|
||||
<!-- <div class="custom-tree-node" slot-scope="{ node, data }">
|
||||
<span class="icon"></span>
|
||||
<span>{{ node.label }}</span>
|
||||
</div> -->
|
||||
</el-tree>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@ -30,28 +67,45 @@
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
|
||||
<transition appear name="vvv" mode="out-in">
|
||||
<base-table
|
||||
v-if="mode == 'table'"
|
||||
:table-props="tableProps"
|
||||
:page="1"
|
||||
:limit="999"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun">
|
||||
<!-- <method-btn
|
||||
<el-row>
|
||||
<el-col class="custom-tabs">
|
||||
<el-tabs v-model="activeName" @tab-click="handleTabClick">
|
||||
<el-tab-pane :label="'\u2002数据列表\u2002'" name="table">
|
||||
<base-table
|
||||
v-if="mode == 'table'"
|
||||
:table-props="tableProps"
|
||||
:page="1"
|
||||
:limit="999"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun">
|
||||
<!-- <method-btn
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" /> -->
|
||||
</base-table>
|
||||
</base-table>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="'\u3000柱状图\u3000'" name="graph">
|
||||
<div class="graph" style="height: 56vh">
|
||||
<!-- graph -->
|
||||
<Graph v-if="list.length" :equipment-list="list" />
|
||||
<div
|
||||
v-else
|
||||
style="
|
||||
color: #c7c7c7;
|
||||
text-align: center;
|
||||
margin-top: 20px;
|
||||
">
|
||||
没有设备
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="graph" style="height: 56vh;" v-else>
|
||||
<!-- graph -->
|
||||
<Graph v-if="list.length" :equipment-list="list" />
|
||||
<div v-else style="color: #c7c7c7; text-align: center; margin-top: 20px;">没有设备</div>
|
||||
</div>
|
||||
</transition>
|
||||
<!-- <transition appear name="vvv" mode="out-in"></transition> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -66,6 +120,16 @@ export default {
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
factoryListOpen: false,
|
||||
currentFactory: null,
|
||||
factoryList: [
|
||||
{ name: '1', value: 1 },
|
||||
{ name: '2', value: 2 },
|
||||
{ name: '3', value: 3 },
|
||||
{ name: '4', value: 4 },
|
||||
{ name: '5', value: 5 },
|
||||
{ name: '6', value: 6 },
|
||||
],
|
||||
sidebarContent: [
|
||||
// {
|
||||
// id: 'fc1',
|
||||
@ -152,6 +216,7 @@ export default {
|
||||
// ],
|
||||
// },
|
||||
],
|
||||
activeName: 'table',
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'datePicker',
|
||||
@ -172,23 +237,23 @@ export default {
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '表格',
|
||||
name: 'table',
|
||||
plain: true,
|
||||
color: 'success',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '图表',
|
||||
name: 'graph',
|
||||
plain: true,
|
||||
color: 'warning',
|
||||
},
|
||||
// {
|
||||
// type: 'separate',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '表格',
|
||||
// name: 'table',
|
||||
// plain: true,
|
||||
// color: 'success',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '图表',
|
||||
// name: 'graph',
|
||||
// plain: true,
|
||||
// color: 'warning',
|
||||
// },
|
||||
// {
|
||||
// type: this.$auth.hasPermi('base:equipment-group:export') ? 'button' : '',
|
||||
// btnName: '导出',
|
||||
@ -197,11 +262,11 @@ export default {
|
||||
// },
|
||||
],
|
||||
tableProps: [
|
||||
{ prop: 'lineName', label: '产线', align: 'center' },
|
||||
{ prop: 'sectionName', label: '工段', align: 'center' },
|
||||
{ prop: 'externalCode', label: '设备编码', align: 'center' },
|
||||
{ prop: 'equipmentName', label: '设备名称', align: 'center' },
|
||||
{ prop: 'totalQuantity', label: '加工数量', align: 'center' },
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'sectionName', label: '工段' },
|
||||
{ prop: 'externalCode', label: '设备编码' },
|
||||
{ prop: 'equipmentName', label: '设备名称' },
|
||||
{ prop: 'totalQuantity', label: '加工数量' },
|
||||
],
|
||||
mode: 'table', // table | graph
|
||||
queryParams: {
|
||||
@ -230,20 +295,20 @@ export default {
|
||||
this.$set(factory, 'label', factory.name);
|
||||
this.$set(factory, 'type', '工厂');
|
||||
delete factory.name;
|
||||
factory.children = factory.lines;
|
||||
delete factory.lines;
|
||||
// factory.children = factory.lines;
|
||||
// delete factory.lines;
|
||||
factory.children?.forEach((line) => {
|
||||
this.$set(line, 'label', line.name);
|
||||
this.$set(line, 'type', '产线');
|
||||
delete line.name;
|
||||
line.children = line.sections;
|
||||
delete line.sections;
|
||||
// line.children = line.sections;
|
||||
// delete line.sections;
|
||||
line.children?.forEach((ws) => {
|
||||
this.$set(ws, 'label', ws.name);
|
||||
this.$set(ws, 'type', '工段');
|
||||
delete ws.name;
|
||||
ws.children = ws.equipments;
|
||||
delete ws.equipments;
|
||||
// ws.children = ws.equipments;
|
||||
// delete ws.equipments;
|
||||
ws.children?.forEach((eq) => {
|
||||
this.$set(eq, 'label', eq.name);
|
||||
this.$set(eq, 'type', '设备');
|
||||
@ -258,10 +323,23 @@ export default {
|
||||
const { data } = await this.$axios('/base/factory/getTree');
|
||||
this.sidebarContent = data;
|
||||
this.buildTree(data);
|
||||
console.log('tree', this.sidebarContent);
|
||||
},
|
||||
|
||||
handleTabClick(tab, event) {
|
||||
console.log('handle tab click: ', tab, event);
|
||||
},
|
||||
|
||||
factoryChangeHandler(event) {
|
||||
this.factoryListOpen = false;
|
||||
const fcId = event.target.dataset.value;
|
||||
console.log('fc id', fcId);
|
||||
this.handleSidebarItemClick({ id: fcId, type: '工厂' });
|
||||
this.currentFactory = this.sidebarContent.find((item) => item.id == fcId);
|
||||
},
|
||||
|
||||
handleSidebarItemClick({ label, id, type }) {
|
||||
console.log('lable clicked!', label, id, type);
|
||||
console.log('label clicked!', label, id, type);
|
||||
switch (type) {
|
||||
case '设备':
|
||||
this.queryParams.equipmentId = id;
|
||||
@ -317,8 +395,10 @@ export default {
|
||||
|
||||
<style scoped>
|
||||
.side-bar__left >>> .is-current {
|
||||
padding: 0;
|
||||
color: #111;
|
||||
background: #f2f4f7;
|
||||
/* background: #f2f4f7; */
|
||||
background: #E3EFFF !important;
|
||||
}
|
||||
|
||||
.vvv-enter,
|
||||
@ -338,4 +418,146 @@ export default {
|
||||
/* transform: translateY(0) scaleY(1); */
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.custom-tabs >>> .el-tabs__header {
|
||||
margin-bottom: 8px;
|
||||
display: inline-block;
|
||||
transform: translateY(-12px);
|
||||
}
|
||||
.custom-tabs >>> .el-tabs__item {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
line-height: 36px !important;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.factory-list__selector {
|
||||
position: relative;
|
||||
height: 36px;
|
||||
font-size: 16px;
|
||||
line-height: 36px;
|
||||
padding-left: 28px;
|
||||
background: url(../../../assets/images/factory-icon.png) 0 / 10% no-repeat;
|
||||
}
|
||||
|
||||
.factory-list__selector:hover {
|
||||
cursor: pointer;
|
||||
color: #0008;
|
||||
}
|
||||
|
||||
.factory-list__selector::after {
|
||||
/* content: ''; */
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 12px;
|
||||
display: inline-block;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
/* background: #5c5c5c; */
|
||||
border-color: #000;
|
||||
border-width: 4px;
|
||||
border-style: solid;
|
||||
border-top-color: transparent;
|
||||
border-right-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
.factory-list__selector:hover::after {
|
||||
/* cursor: pointer; */
|
||||
border-left-color: #0008;
|
||||
}
|
||||
|
||||
.factory-list__wrapper {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 32px 10px #0002;
|
||||
border-radius: 8px;
|
||||
top: 36px;
|
||||
left: 90px;
|
||||
/* max-width: 128px; */
|
||||
height: auto;
|
||||
width: auto;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
/* transition: all 0.3s ease-out; */
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.factory-list__wrapper.open {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.factory-list {
|
||||
color: #0008;
|
||||
max-height: 240px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.factory-list__item {
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
padding: 8px 64px 8px 16px;
|
||||
/* min-width: 64px; */
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.factory-list__item:hover,
|
||||
.factory-list__item.is-current {
|
||||
background: #e3efff;
|
||||
color: #0b58ff;
|
||||
}
|
||||
|
||||
.factory-list__item.is-current::after {
|
||||
content: '√';
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.custom-tree-class >>> .el-tree-node__content {
|
||||
height: auto !important;
|
||||
padding: 8px 12px !important;
|
||||
}
|
||||
.custom-tree-class >>> .el-tree-node__content:hover {
|
||||
background: #E3EFFF;
|
||||
}
|
||||
|
||||
.custom-tree-class >>> .el-tree-node__children .el-tree-node__content {
|
||||
padding: 8px 18px !important;
|
||||
}
|
||||
|
||||
.custom-tree-class >>> .el-tree-node__children .el-tree-node__children .el-tree-node__content {
|
||||
padding: 8px 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style>
|
||||
.custom-icon-class {
|
||||
margin-right: 8px;
|
||||
width: 20px;
|
||||
height: 24px;
|
||||
background: url('../../../assets/images/tree-icon-1.png') 100% / contain
|
||||
no-repeat;
|
||||
}
|
||||
|
||||
.custom-icon-class.el-tree-node__expand-icon.expanded {
|
||||
transform: unset;
|
||||
}
|
||||
|
||||
.el-tree-node__children .custom-icon-class {
|
||||
background: url('../../../assets/images/tree-icon-2.png') 100% / contain
|
||||
no-repeat;
|
||||
}
|
||||
|
||||
.el-tree-node__children .el-tree-node__children .custom-icon-class {
|
||||
background: unset;
|
||||
}
|
||||
</style>
|
||||
|
@ -11,14 +11,16 @@
|
||||
:formConfigs="[{ label: '设备近24小时生产记录', type: 'title' }]"
|
||||
ref="search-bar" />
|
||||
<el-skeleton v-if="initing" :rows="6" animated />
|
||||
<base-table
|
||||
v-else
|
||||
:span-method="mergeColumnHandler"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
<!-- :page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize" -->
|
||||
<div v-else :class="{ 'no-data-bg': !list || list.length == 0 }">
|
||||
<base-table
|
||||
v-if="list && list.length > 0"
|
||||
:span-method="mergeColumnHandler"
|
||||
:table-props="tableProps"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
<!-- :page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize" -->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -37,6 +39,7 @@ export default {
|
||||
list: [],
|
||||
tableProps: [],
|
||||
spanInfo: {},
|
||||
noData: true,
|
||||
};
|
||||
},
|
||||
computed: {},
|
||||
@ -51,24 +54,22 @@ export default {
|
||||
} = item;
|
||||
|
||||
const props = [
|
||||
{ prop: 'productLine', label: '产线', align: 'center' },
|
||||
{ prop: 'specification', label: '规格', align: 'center' },
|
||||
{ prop: 'equipmentName', label: '设备', align: 'center' },
|
||||
{ prop: 'totalQuantity', label: '生产总数', align: 'center' },
|
||||
{ prop: 'productLine', label: '产线' },
|
||||
{ prop: 'specification', label: '规格' },
|
||||
{ prop: 'equipmentName', label: '设备' },
|
||||
{ prop: 'totalQuantity', label: '生产总数' },
|
||||
];
|
||||
|
||||
for (const key of Object.keys(hourData).sort()) {
|
||||
const subprop = {
|
||||
label: key,
|
||||
align: 'center',
|
||||
children: [
|
||||
{ prop: key + '__in', label: '进数据', align: 'center' },
|
||||
{ prop: key + '__out', label: '出数据', align: 'center' },
|
||||
{ prop: key + '__nok', label: '报废数据', align: 'center' },
|
||||
{ prop: key + '__in', label: '进数据' },
|
||||
{ prop: key + '__out', label: '出数据' },
|
||||
{ prop: key + '__nok', label: '报废数据' },
|
||||
{
|
||||
prop: key + '__ratio',
|
||||
label: '报废率',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? val + ' %' : '-'),
|
||||
},
|
||||
],
|
||||
@ -138,6 +139,13 @@ export default {
|
||||
// console.log('recent-24', data);
|
||||
|
||||
this.initing = true;
|
||||
|
||||
if (!data || !data.length) {
|
||||
this.initing = false;
|
||||
this.noData = true;
|
||||
return;
|
||||
}
|
||||
this.noData = false;
|
||||
this.buildProps(data[0]);
|
||||
this.buildData(data);
|
||||
this.queryParams.pageSize = this.list.length;
|
||||
|
@ -18,6 +18,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -74,28 +75,24 @@ export default {
|
||||
width: 128,
|
||||
prop: 'equipmentName',
|
||||
label: '设备名称',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'equipmentCode',
|
||||
label: '设备编码',
|
||||
align: 'center',
|
||||
},
|
||||
{ width: 128, prop: 'inQuantity', label: '投入数', align: 'center' },
|
||||
{ width: 128, prop: 'outQuantity', label: '产出数', align: 'center' },
|
||||
{ width: 128, prop: 'inQuantity', label: '投入数' },
|
||||
{ width: 128, prop: 'outQuantity', label: '产出数' },
|
||||
{
|
||||
width: 128,
|
||||
prop: 'run',
|
||||
label: '是否运行',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? (val ? '是' : '否') : '-'),
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'status',
|
||||
label: '状态',
|
||||
align: 'center',
|
||||
filter: (val) =>
|
||||
val != null ? ['正常', '计划停机', '故障'][val] : '-',
|
||||
},
|
||||
@ -103,7 +100,6 @@ export default {
|
||||
width: 128,
|
||||
prop: 'error',
|
||||
label: '是否故障',
|
||||
align: 'center',
|
||||
filter: (val) => (val != null ? (val ? '是' : '否') : '-'),
|
||||
},
|
||||
{
|
||||
@ -121,7 +117,6 @@ export default {
|
||||
{
|
||||
_action: 'params-monitor',
|
||||
label: '参数监控',
|
||||
align: 'center',
|
||||
subcomponent: {
|
||||
props: ['injectData'],
|
||||
render: function (h) {
|
||||
@ -129,7 +124,7 @@ export default {
|
||||
return h(
|
||||
'el-button',
|
||||
{
|
||||
props: { type: 'text', size: 'mini' },
|
||||
props: { type: 'text' },
|
||||
on: {
|
||||
click: function () {
|
||||
console.log('inejctdata', _this.injectData);
|
||||
|
233
src/views/quality/base/qualityInspectionBoxBtn/dialogForm.vue
Normal file
233
src/views/quality/base/qualityInspectionBoxBtn/dialogForm.vue
Normal file
@ -0,0 +1,233 @@
|
||||
<!--
|
||||
filename: dialogForm.vue
|
||||
author: liubin
|
||||
date: 2023-09-11 15:55:13
|
||||
description: DialogForm for equipmentBindSection only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<el-form
|
||||
ref="form"
|
||||
:model="dataForm"
|
||||
label-width="100px"
|
||||
v-loading="formLoading">
|
||||
<el-row :gutter="20">
|
||||
<el-col>
|
||||
<el-form-item
|
||||
label="产线"
|
||||
prop="productionId"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-select
|
||||
v-model="dataForm.productionId"
|
||||
placeholder="请选择产线"
|
||||
filterable
|
||||
@change="handleProductlineChange">
|
||||
<el-option
|
||||
v-for="opt in productionLineList"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col>
|
||||
<el-form-item
|
||||
label="工段"
|
||||
prop="sectionId"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-select
|
||||
v-model="dataForm.sectionId"
|
||||
placeholder="请选择工段"
|
||||
filterable
|
||||
@change="$emit('update', dataForm)">
|
||||
<el-option
|
||||
v-for="opt in workshopSectionList"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col>
|
||||
<el-form-item
|
||||
label="按钮盒识别码"
|
||||
prop="buttonId"
|
||||
:rules="[
|
||||
{
|
||||
type: 'number',
|
||||
message: '请输入整数',
|
||||
trigger: 'blur',
|
||||
transform: (val) => Number.isInteger(Number(val)) && Number(val),
|
||||
},
|
||||
]">
|
||||
<el-input
|
||||
v-model="dataForm.buttonId"
|
||||
@change="$emit('update', dataForm)"
|
||||
placeholder="请输入整数" />
|
||||
</el-form-item>
|
||||
<!--
|
||||
<el-form-item
|
||||
label="报警编码"
|
||||
prop="code"
|
||||
:rules="[{ required: true, message: '不能为空', trigger: 'blur' }]">
|
||||
<el-select
|
||||
v-model="dataForm.code"
|
||||
placeholder="请选择产线"
|
||||
@change="handleProductlineChange">
|
||||
<el-option
|
||||
v-for="opt in productionLineList"
|
||||
:key="opt.value"
|
||||
:label="opt.label"
|
||||
:value="opt.value" />
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
</el-col>
|
||||
|
||||
<el-col>
|
||||
<el-form-item label="按钮盒模式" prop="model">
|
||||
<el-input
|
||||
v-model="dataForm.model"
|
||||
@change="$emit('update', dataForm)"
|
||||
placeholder="请输入按钮盒模式" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col>
|
||||
<el-form-item
|
||||
label="按钮值"
|
||||
prop="keyValue"
|
||||
:rules="[
|
||||
{
|
||||
type: 'number',
|
||||
message: '请输入100以内的整数',
|
||||
trigger: 'blur',
|
||||
transform: (val) =>
|
||||
Number(val) <= 100 && Number.isInteger(+val) && Number(val),
|
||||
},
|
||||
]">
|
||||
<el-input
|
||||
v-model="dataForm.keyValue"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
@change="$emit('update', dataForm)"
|
||||
placeholder="请输入按钮盒模式" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col>
|
||||
<el-form-item label="检测内容" prop="inspectionDetContent">
|
||||
<el-input
|
||||
type="textarea"
|
||||
v-model="dataForm.inspectionDetContent"
|
||||
placeholder="请输入检测内容"
|
||||
@change="$emit('update', dataForm)"></el-input>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DialogForm',
|
||||
model: {
|
||||
prop: 'dataForm',
|
||||
event: 'update',
|
||||
},
|
||||
emits: ['update'],
|
||||
components: {},
|
||||
props: {
|
||||
dataForm: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
formLoading: true,
|
||||
productionLineList: [],
|
||||
workshopSectionList: [],
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getProductionLineList();
|
||||
// this.getWorksectionList();
|
||||
// this.getCode('/base/equipment-group-alarm/getCode').then((code) => {
|
||||
// this.formLoading = false;
|
||||
// this.$emit('update', {
|
||||
// ...this.dataForm,
|
||||
// code,
|
||||
// });
|
||||
// });
|
||||
},
|
||||
watch: {
|
||||
'dataForm.productionId': {
|
||||
handler(id) {
|
||||
this.getWorksectionList(id);
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/** 模拟透传 ref */
|
||||
validate(cb) {
|
||||
return this.$refs.form.validate(cb);
|
||||
},
|
||||
resetFields(args) {
|
||||
return this.$refs.form.resetFields(args);
|
||||
},
|
||||
async getProductionLineList() {
|
||||
this.formLoading = true;
|
||||
const res = await this.$axios({
|
||||
url: '/base/production-line/listAll',
|
||||
method: 'get',
|
||||
});
|
||||
if (res.code == 0) {
|
||||
this.productionLineList = res.data.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
}
|
||||
this.formLoading = false;
|
||||
},
|
||||
|
||||
async getWorksectionList(id) {
|
||||
this.formLoading = true;
|
||||
const res = await this.$axios({
|
||||
url: '/base/workshop-section/listByParentId',
|
||||
method: 'get',
|
||||
params: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
if (res.code == 0) {
|
||||
this.workshopSectionList = res.data.map((item) => ({
|
||||
label: item.name,
|
||||
value: item.id,
|
||||
}));
|
||||
}
|
||||
this.formLoading = false;
|
||||
},
|
||||
|
||||
async handleProductlineChange(id) {
|
||||
await this.getWorksectionList(id);
|
||||
this.dataForm.sectionId = null;
|
||||
this.$emit('update', this.dataForm);
|
||||
},
|
||||
|
||||
async getCode(url) {
|
||||
const response = await this.$axios(url);
|
||||
return response.data;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.el-date-editor,
|
||||
.el-select {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
fixed="right"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
@ -38,7 +39,7 @@
|
||||
@close="cancel"
|
||||
@cancel="cancel"
|
||||
@confirm="submitForm">
|
||||
<DialogForm v-if="open" ref="form" :dataForm="form" :rows="rows" />
|
||||
<DialogForm v-if="open" ref="form" v-model="form" :rows="rows" />
|
||||
</base-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@ -54,11 +55,12 @@ import {
|
||||
} from '@/api/base/qualityInspectionBoxBtn';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import moment from 'moment';
|
||||
import DialogForm from './dialogForm.vue';
|
||||
|
||||
export default {
|
||||
name: 'QualityInspectionBoxBtn',
|
||||
mixins: [basicPageMixin],
|
||||
components: {},
|
||||
components: { DialogForm },
|
||||
data() {
|
||||
return {
|
||||
rows: [
|
||||
@ -81,6 +83,9 @@ export default {
|
||||
url: '/base/workshop-section/listAll',
|
||||
prop: 'sectionId',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
bind: {
|
||||
filterable: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
@ -91,9 +96,10 @@ export default {
|
||||
rules: [
|
||||
{
|
||||
type: 'number',
|
||||
message: '请输入数字',
|
||||
message: '请输入整数',
|
||||
trigger: 'blur',
|
||||
transform: (val) => Number(val),
|
||||
transform: (val) =>
|
||||
Number.isInteger(Number(val)) && Number(val),
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -107,9 +113,10 @@ export default {
|
||||
rules: [
|
||||
{
|
||||
type: 'number',
|
||||
message: '请输入100以内的数字',
|
||||
message: '请输入100以内的整数',
|
||||
trigger: 'blur',
|
||||
transform: (val) => Number(val) <= 100 && Number(val),
|
||||
transform: (val) =>
|
||||
Number(val) <= 100 && Number.isInteger(+val) && Number(val),
|
||||
},
|
||||
],
|
||||
bind: { type: 'number', min: 0, max: 100 },
|
||||
@ -120,7 +127,7 @@ export default {
|
||||
textarea: true,
|
||||
label: '检测内容',
|
||||
prop: 'inspectionDetContent',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
],
|
||||
@ -173,43 +180,36 @@ export default {
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'productionName',
|
||||
label: '产线',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'sectionName',
|
||||
label: '工段',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 128,
|
||||
prop: 'inspectionDetContent',
|
||||
label: '检测内容',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
width: 160,
|
||||
prop: 'buttonId',
|
||||
label: '按钮盒识别码',
|
||||
align: 'center',
|
||||
},
|
||||
// {
|
||||
// width: 256,
|
||||
// prop: 'productionId',
|
||||
// label: '按钮盒所在产线ID',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 256,
|
||||
// prop: 'sectionId',
|
||||
// label: '按钮盒所在工段ID',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
{ width: 90, prop: 'keyValue', label: '按钮值', align: 'center' },
|
||||
{ width: 128, prop: 'model', label: '按钮盒模式', align: 'center' },
|
||||
{ width: 90, prop: 'keyValue', label: '按钮值' },
|
||||
{ width: 128, prop: 'model', label: '按钮盒模式' },
|
||||
],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
@ -220,13 +220,13 @@ export default {
|
||||
// 搜索框需要的 keys, 与上面 queryParams 的除 pageNo, pageSize 之外的 key 一一对应
|
||||
searchBarKeys: ['inspectionDetContent'],
|
||||
form: {
|
||||
id: undefined,
|
||||
inspectionDetId: undefined,
|
||||
inspectionDetContent: undefined,
|
||||
productionId: undefined,
|
||||
sectionId: undefined,
|
||||
model: undefined,
|
||||
keyValue: undefined,
|
||||
id: null,
|
||||
buttonId: null,
|
||||
inspectionDetContent: null,
|
||||
productionId: null,
|
||||
sectionId: null,
|
||||
model: null,
|
||||
keyValue: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
@ -247,13 +247,13 @@ export default {
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
inspectionDetId: undefined,
|
||||
inspectionDetContent: undefined,
|
||||
productionId: undefined,
|
||||
sectionId: undefined,
|
||||
model: undefined,
|
||||
keyValue: undefined,
|
||||
id: null,
|
||||
buttonId: null,
|
||||
inspectionDetContent: null,
|
||||
productionId: null,
|
||||
sectionId: null,
|
||||
model: null,
|
||||
keyValue: null,
|
||||
};
|
||||
this.resetForm('form');
|
||||
},
|
||||
@ -300,7 +300,7 @@ export default {
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除安灯按钮16键对应编号为"' + id + '"的数据项?')
|
||||
.confirm('是否确认删除"' + row.sectionName + '"?')
|
||||
.then(function () {
|
||||
return deleteQualityInspectionBoxBtn(id);
|
||||
})
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
fixed="right"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
@ -172,10 +173,10 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'typeName', label: '类型名称', align: 'center' },
|
||||
{ prop: 'content', label: '检测内容', align: 'center' },
|
||||
{ prop: 'code', label: '检测编码', align: 'center' },
|
||||
{ prop: 'remark', label: '备注', align: 'center' },
|
||||
{ prop: 'typeName', label: '类型名称', },
|
||||
{ prop: 'content', label: '检测内容', },
|
||||
{ prop: 'code', label: '检测编码', },
|
||||
{ prop: 'remark', label: '备注', },
|
||||
],
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
@ -275,7 +276,7 @@ export default {
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除质量检测信息基础编号为"' + id + '"的数据项?')
|
||||
.confirm('是否确认删除检测信息"' + row.content + '"?')
|
||||
.then(function () {
|
||||
return deleteQualityInspectionDet(id);
|
||||
})
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
@ -106,9 +107,9 @@ export default {
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'name', label: '检测类型名称', align: 'center' },
|
||||
{ prop: 'code', label: '检测类型编码', align: 'center' },
|
||||
{ prop: 'remark', label: '备注', align: 'center' },
|
||||
{ prop: 'name', label: '检测类型名称' },
|
||||
{ prop: 'code', label: '检测类型编码' },
|
||||
{ prop: 'remark', label: '备注' },
|
||||
// {
|
||||
// label: '操作',
|
||||
// alignt: 'center',
|
||||
@ -321,7 +322,7 @@ export default {
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除质量检测类型基础编号为"' + id + '"的数据项?')
|
||||
.confirm('是否确认删除该质量检测类型?')
|
||||
.then(function () {
|
||||
return deleteQualityInspectionType(id);
|
||||
})
|
||||
|
@ -17,6 +17,7 @@
|
||||
v-if="tableBtn.length"
|
||||
slot="handleBtn"
|
||||
label="操作"
|
||||
:width="120"
|
||||
fixed="right"
|
||||
:method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
@ -68,7 +69,7 @@ export default {
|
||||
[
|
||||
{
|
||||
select: true,
|
||||
label: '检测内容ID',
|
||||
label: '检测内容',
|
||||
url: '/base/quality-inspection-det/listAll',
|
||||
prop: 'inspectionDetId',
|
||||
labelKey: 'content',
|
||||
@ -97,6 +98,9 @@ export default {
|
||||
label: '产线',
|
||||
url: '/base/production-line/listAll',
|
||||
prop: 'productionLineId',
|
||||
bind: {
|
||||
filterable: true,
|
||||
},
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
{
|
||||
@ -105,6 +109,9 @@ export default {
|
||||
url: '/base/workshop-section/listAll', // 这个 url 其实可加可不加,因为下面会更新 options
|
||||
options: [], // 这个options也可加可不加, 因为下面会更新 options
|
||||
prop: 'sectionId',
|
||||
bind: {
|
||||
filterable: true,
|
||||
},
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
@ -118,6 +125,7 @@ export default {
|
||||
datetime: true,
|
||||
label: '检测时间',
|
||||
prop: 'checkTime',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
bind: {
|
||||
format: 'yyyy-MM-dd HH:mm:ss',
|
||||
'value-format': 'timestamp',
|
||||
@ -126,15 +134,15 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
textarea: true,
|
||||
label: '检测内容',
|
||||
prop: 'inspectionDetContent',
|
||||
value: '',
|
||||
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
},
|
||||
],
|
||||
// [
|
||||
// {
|
||||
// textarea: true,
|
||||
// label: '检测内容',
|
||||
// prop: 'inspectionDetContent',
|
||||
// value: '',
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// },
|
||||
// ],
|
||||
[{ textarea: true, label: '描述', prop: 'explainText' }],
|
||||
[{ input: true, label: '备注', prop: 'remark' }],
|
||||
],
|
||||
@ -213,32 +221,27 @@ export default {
|
||||
width: 128,
|
||||
prop: 'inspectionDetContent',
|
||||
label: '检测内容',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 128,
|
||||
prop: 'lineName',
|
||||
label: '产线',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 128,
|
||||
prop: 'checkPerson',
|
||||
label: '检测人员',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'checkTime',
|
||||
label: '检测时间',
|
||||
align: 'center',
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{
|
||||
width: 90,
|
||||
prop: 'source',
|
||||
label: '来源',
|
||||
align: 'center',
|
||||
filter: (val) => ['未知', '手动', '自动'][val],
|
||||
},
|
||||
],
|
||||
@ -394,7 +397,7 @@ export default {
|
||||
handleDelete(row) {
|
||||
const id = row.id;
|
||||
this.$modal
|
||||
.confirm('是否确认删除质量检查信息记录表编号为"' + id + '"的数据项?')
|
||||
.confirm('是否确认删除"' + row.inspectionDetContent + '"?')
|
||||
.then(function () {
|
||||
return deleteQualityInspectionRecord(id);
|
||||
})
|
||||
|
@ -13,18 +13,20 @@
|
||||
<!-- <pre><code v-html="jsondemo"></code></pre> -->
|
||||
|
||||
<el-skeleton v-if="initing" :rows="6" animated />
|
||||
<base-table
|
||||
v-else
|
||||
:table-props="tableProps"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
<div v-else :class="{ 'no-data-bg': !list || list.length == 0 }">
|
||||
<base-table
|
||||
v-if="list && list.length > 0"
|
||||
:table-props="tableProps"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import response from './response.json';
|
||||
// import response from './response.json';
|
||||
import { handleNameData, handleDynamicData } from '@/utils/dynamicProps';
|
||||
// import hljs from 'highlight.js/lib/highlight';
|
||||
// import json from 'highlight.js/lib/languages/json';
|
||||
@ -43,7 +45,6 @@ export default {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
},
|
||||
// jsondemo: '',
|
||||
list: [
|
||||
// {
|
||||
// inspectionContent: '检测内容1',
|
||||
@ -56,7 +57,6 @@ export default {
|
||||
{
|
||||
prop: 'inspectionContent',
|
||||
label: '检测内容',
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
};
|
||||
@ -67,20 +67,10 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
async getList() {
|
||||
// const response = await this.$axios({
|
||||
// url: '/monitoring/record-in-one-day/get',
|
||||
// method: 'get',
|
||||
// });
|
||||
console.log(response);
|
||||
// const {
|
||||
// // data: { nameData },
|
||||
// code,
|
||||
// } = response;
|
||||
// this.jsondemo = hljs.highlight(
|
||||
// 'json',
|
||||
// JSON.stringify(response, null, 2),
|
||||
// true
|
||||
// ).value;
|
||||
const response = await this.$axios({
|
||||
url: '/monitoring/record-in-one-day/get',
|
||||
method: 'get',
|
||||
});
|
||||
const {
|
||||
data: { data: dyanmicData, nameData },
|
||||
} = response;
|
||||
|
@ -82,18 +82,22 @@ export default {
|
||||
computed: {
|
||||
config() {
|
||||
return {
|
||||
color: ['#fde19a', '#8be2b9', '#288aff', '#7164ff'],
|
||||
// title: {
|
||||
// text: '折线图',
|
||||
// },
|
||||
grid: {
|
||||
top: '24%',
|
||||
left: '3%',
|
||||
top: '12%',
|
||||
left: '2%',
|
||||
right: '5%',
|
||||
bottom: '5%',
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
data: this.legend,
|
||||
@ -107,13 +111,145 @@ export default {
|
||||
// },
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
boundaryGap: true,
|
||||
onZero: false,
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
// color: 'red'
|
||||
},
|
||||
},
|
||||
data: this.xProps,
|
||||
// data: [
|
||||
// '设备1',
|
||||
// '设备2',
|
||||
// '设备3',
|
||||
// '设备4',
|
||||
// '设备5',
|
||||
// '设备6',
|
||||
// '设备7',
|
||||
// '设备8',
|
||||
// '设备9',
|
||||
// '设备10',
|
||||
// '设备11',
|
||||
// '设备12',
|
||||
// '设备13',
|
||||
// '设备14',
|
||||
// '设备15',
|
||||
// '设备16',
|
||||
// '设备17',
|
||||
// '设备18',
|
||||
// '设备19',
|
||||
// '设备20',
|
||||
// ],
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '单位/片',
|
||||
nameTextStyle: {
|
||||
color: '#999',
|
||||
fontSize: 14,
|
||||
align: 'right',
|
||||
},
|
||||
max: function (value) {
|
||||
return value.max + Math.floor(value.max / 5);
|
||||
},
|
||||
},
|
||||
// 缩放 - 滑动
|
||||
dataZoom: {
|
||||
type: 'inside',
|
||||
},
|
||||
series: this.series,
|
||||
// series: [
|
||||
// {
|
||||
// name: '上片数',
|
||||
// type: 'bar',
|
||||
// // barWidth: 12,
|
||||
// data: [
|
||||
// 10,
|
||||
// 12,
|
||||
// 43,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// 12,
|
||||
// 8,
|
||||
// 122,
|
||||
// 0,
|
||||
// ,
|
||||
// 43,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// 12,
|
||||
// 8,
|
||||
// 122,
|
||||
// 77,
|
||||
// 99,
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// name: '下片数',
|
||||
// type: 'bar',
|
||||
// // barWidth: 12,
|
||||
// data: [
|
||||
// 10,
|
||||
// 12,
|
||||
// 43,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// 12,
|
||||
// 8,
|
||||
// 122,
|
||||
// 0,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// 12,
|
||||
// 8,
|
||||
// 122,
|
||||
// 0,
|
||||
// ,
|
||||
// 43,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// ],
|
||||
// },
|
||||
// {
|
||||
// name: '检测数',
|
||||
// type: 'bar',
|
||||
// // barWidth: 12,
|
||||
// barCategoryGap: 12,
|
||||
// data: [
|
||||
// 10,
|
||||
// 12,
|
||||
// 43,
|
||||
// 4,
|
||||
// 22,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// 12,
|
||||
// 8,
|
||||
// 122,
|
||||
// 0,
|
||||
// ,
|
||||
// 43,
|
||||
// 4,
|
||||
// 22,
|
||||
// 32,
|
||||
// 32,
|
||||
// 12,
|
||||
// 8,
|
||||
// 122,
|
||||
// 0,
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
};
|
||||
},
|
||||
},
|
||||
|
@ -7,9 +7,9 @@
|
||||
|
||||
<template>
|
||||
<!-- 列表 -->
|
||||
<!-- height="35vh" -->
|
||||
<base-table
|
||||
:table-props="tableProps"
|
||||
height="35vh"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"></base-table>
|
||||
@ -35,27 +35,22 @@ export default {
|
||||
{
|
||||
prop: 'lineName',
|
||||
label: '产线',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'sumUp',
|
||||
label: '上片总数',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'sumDown',
|
||||
label: '下片总数',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'sumCheck',
|
||||
label: '检测总数',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
prop: 'scrapRatio',
|
||||
label: '比例(%)',
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -7,14 +7,20 @@
|
||||
|
||||
<template>
|
||||
<div class="graph-page">
|
||||
<DetailGraph id="dg1" key="dg1" ref="dg1" title="数据总览">
|
||||
<!-- <DetailGraph id="dg1" key="dg1" ref="dg1" title="数据总览">
|
||||
<TotalGraph :summary-list="summaryList" />
|
||||
</DetailGraph>
|
||||
<DetailGraph id="dg2" key="dg2" ref="dg2" title="检测内容数据">
|
||||
</DetailGraph> -->
|
||||
<!-- <DetailGraph id="dg2" key="dg2" ref="dg2" title="检测内容数据">
|
||||
<LineGraph :x-props="lineData.xProps" :legend="legend" :series="series" />
|
||||
</DetailGraph>
|
||||
</DetailGraph> -->
|
||||
<!-- <DetailGraph id="dg3" key="dg3" ref="dg3" />
|
||||
<DetailGraph id="dg4" key="dg4" ref="dg4" /> -->
|
||||
<DetailGraph id="dg4" key="dg4" ref="dg4" /> -->
|
||||
<div v-if="!series || series.length == 0" style="color: #777; font-size: 16px; letter-spacing: 1px; text-align: center; padding-top: 56px; text-decoration: underline;">暂无数据</div>
|
||||
<LineGraph
|
||||
v-else
|
||||
:x-props="lineData.xProps"
|
||||
:legend="legend"
|
||||
:series="series" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -55,7 +61,8 @@ export default {
|
||||
console.log('this.list', this.lineData.list, this.lineData.xProps);
|
||||
const seriesItem = {
|
||||
name: item.inspectionContent,
|
||||
type: 'line',
|
||||
type: 'bar',
|
||||
barCategoryGap: 12,
|
||||
data: [],
|
||||
};
|
||||
|
||||
|
@ -6,33 +6,84 @@
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar
|
||||
:formConfigs="searchBarFormConfig"
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
<div class="quality-container" style="background: #f2f4f9; flex: 1">
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar
|
||||
:formConfigs="searchBarFormConfig"
|
||||
ref="search-bar"
|
||||
@headBtnClick="handleSearchBarBtnClick" />
|
||||
</el-row>
|
||||
|
||||
<transition mode="out-in" name="fade-down">
|
||||
<template v-if="mode == 'table'">
|
||||
<!-- 列表 -->
|
||||
<base-table
|
||||
v-if="mode == 'table'"
|
||||
:table-props="tableProps"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
</template>
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 12px 16px 16px;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<div class="blue-title">产线检测总览</div>
|
||||
<summaryTable :list="summaryList" />
|
||||
</el-row>
|
||||
|
||||
<GraphPage
|
||||
v-else
|
||||
:summary-list="summaryList"
|
||||
:line-data="{ list: list, xProps: dynamicProps.map((v) => v.prop) }" />
|
||||
</transition>
|
||||
<el-row
|
||||
class=""
|
||||
style="
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 12px 16px 16px;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<el-row style="display: flex; align-items: center">
|
||||
<div class="blue-title">产线检测详细</div>
|
||||
<div class="custom-tabs">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
:stretch="true"
|
||||
@tab-click="handleTabClick">
|
||||
<el-tab-pane
|
||||
:label="'\u2002数据列表\u2002'"
|
||||
name="table"></el-tab-pane>
|
||||
<el-tab-pane
|
||||
:label="'\u3000柱状图\u3000'"
|
||||
name="graph"></el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</el-row>
|
||||
|
||||
<transition mode="out-in" name="fade-down">
|
||||
<template v-if="mode == 'table'">
|
||||
<base-table
|
||||
v-if="mode == 'table'"
|
||||
:table-props="tableProps"
|
||||
:page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize"
|
||||
:table-data="list"
|
||||
@emitFun="handleEmitFun"></base-table>
|
||||
</template>
|
||||
|
||||
<GraphPage
|
||||
v-else
|
||||
:summary-list="summaryList"
|
||||
:line-data="{
|
||||
list: list,
|
||||
xProps: dynamicProps.map((v) => v.prop),
|
||||
}" />
|
||||
</transition>
|
||||
</el-row>
|
||||
|
||||
<!-- todo: 数据总览,用弹窗包裹的 table 实现 -->
|
||||
<base-dialog
|
||||
<!-- <base-dialog
|
||||
dialogTitle="数据总览"
|
||||
:dialogVisible="summaryOpen"
|
||||
width="50%"
|
||||
@ -40,7 +91,7 @@
|
||||
@cancel="handleSummaryClose"
|
||||
@confirm="handleSummaryClose">
|
||||
<summaryTable :list="summaryList" />
|
||||
</base-dialog>
|
||||
</base-dialog> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -48,13 +99,58 @@
|
||||
import GraphPage from './graphPage.vue';
|
||||
import summaryTable from './components/summaryTable.vue';
|
||||
|
||||
class DateGetter {
|
||||
constructor() {
|
||||
this.today = new Date();
|
||||
this.y = this.today.getFullYear();
|
||||
this.m = this.today.getMonth();
|
||||
this.d = this.today.getDate();
|
||||
}
|
||||
getWeekRange() {
|
||||
const weekStart = new Date(this.y, this.m, this.d - this.today.getDay());
|
||||
const weekEnd = new Date(
|
||||
this.y,
|
||||
this.m,
|
||||
this.d + (6 - this.today.getDay()),
|
||||
23,
|
||||
59,
|
||||
59
|
||||
);
|
||||
// console.log('week', [weekStart, weekEnd]);
|
||||
return [weekStart, weekEnd];
|
||||
}
|
||||
|
||||
getMonthRange() {
|
||||
const monthStart = new Date(this.y, this.m, 1);
|
||||
const monthEnd = new Date(this.y, this.m + 1, 0, 23, 59, 59);
|
||||
// console.log('month', [monthStart, monthEnd]);
|
||||
return [monthStart, monthEnd];
|
||||
}
|
||||
|
||||
getQuarterRange() {
|
||||
const quarterStart = new Date(this.y, this.m - (this.m % 3), 1);
|
||||
const quarterEnd = new Date(
|
||||
this.y,
|
||||
this.m - (this.m % 3) + 3,
|
||||
0,
|
||||
23,
|
||||
59,
|
||||
59
|
||||
);
|
||||
// console.log('quarter', [quarterStart, quarterEnd]);
|
||||
return [quarterStart, quarterEnd];
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'QualityStatistics',
|
||||
components: { GraphPage, summaryTable },
|
||||
props: {},
|
||||
data() {
|
||||
const dateGetter = new DateGetter();
|
||||
return {
|
||||
mode: 'table', // defaults to 'table'
|
||||
// mode: 'table', // defaults to 'table'
|
||||
activeName: 'table', // defaults to 'table'
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'datePicker',
|
||||
@ -70,6 +166,28 @@ export default {
|
||||
defaultSelect: [],
|
||||
defaultTime: ['00:00:00', '23:59:59'],
|
||||
param: 'timerange',
|
||||
pickerOptions: {
|
||||
shortcuts: [
|
||||
{
|
||||
text: '本周',
|
||||
onClick(picker) {
|
||||
picker.$emit('pick', dateGetter.getWeekRange());
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '本月',
|
||||
onClick(picker) {
|
||||
picker.$emit('pick', dateGetter.getMonthRange());
|
||||
},
|
||||
},
|
||||
{
|
||||
text: '本季',
|
||||
onClick(picker) {
|
||||
picker.$emit('pick', dateGetter.getQuarterRange());
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
@ -77,33 +195,33 @@ export default {
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '数据总览',
|
||||
name: 'summary',
|
||||
color: 'text',
|
||||
},
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '表格版',
|
||||
name: 'tableVersion',
|
||||
color: 'text btn-table',
|
||||
},
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '图形版',
|
||||
name: 'graphVersion',
|
||||
color: 'text btn-graph',
|
||||
},
|
||||
// {
|
||||
// type: 'separate',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '数据总览',
|
||||
// name: 'summary',
|
||||
// color: 'text',
|
||||
// },
|
||||
// {
|
||||
// type: 'separate',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '表格版',
|
||||
// name: 'tableVersion',
|
||||
// color: 'text btn-table',
|
||||
// },
|
||||
// {
|
||||
// type: 'separate',
|
||||
// },
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '图形版',
|
||||
// name: 'graphVersion',
|
||||
// color: 'text btn-graph',
|
||||
// },
|
||||
],
|
||||
// 动态的 props
|
||||
dynamicProps: [],
|
||||
@ -166,26 +284,26 @@ export default {
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
mode() {
|
||||
return this.activeName;
|
||||
},
|
||||
tableProps() {
|
||||
return [
|
||||
{
|
||||
// width: 160,
|
||||
prop: 'inspectionContent',
|
||||
label: '检测内容',
|
||||
align: 'center',
|
||||
},
|
||||
...this.dynamicProps,
|
||||
{
|
||||
// width: 128,
|
||||
prop: 'sumInput',
|
||||
label: '检测类型总数',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
// width: 128,
|
||||
prop: 'ratio',
|
||||
label: '比例',
|
||||
align: 'center',
|
||||
// subcomponent: {
|
||||
// name: 'TextOnly',
|
||||
// props: {
|
||||
@ -316,6 +434,14 @@ export default {
|
||||
};
|
||||
});
|
||||
},
|
||||
handleTabClick(tab, event) {
|
||||
const { name } = tab;
|
||||
if (name == 'graph') {
|
||||
// 展示柱状图
|
||||
} else {
|
||||
// 展示表格
|
||||
}
|
||||
},
|
||||
/** 总览关闭 */
|
||||
handleSummaryClose() {
|
||||
this.summaryOpen = false;
|
||||
@ -400,6 +526,42 @@ export default {
|
||||
.fade-down-leave {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.blue-title {
|
||||
position: relative;
|
||||
padding: 4px 0;
|
||||
padding-left: 12px;
|
||||
font-size: 14px;
|
||||
color: #606266;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 6px;
|
||||
height: 16px;
|
||||
width: 4px;
|
||||
border-radius: 1px;
|
||||
background: #0b58ff;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.custom-tabs) {
|
||||
.el-tabs__header {
|
||||
margin-left: 12px;
|
||||
margin-bottom: 8px;
|
||||
display: inline-block;
|
||||
transform: translateY(-6px);
|
||||
}
|
||||
|
||||
.el-tabs__item {
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--
|
||||
@ -407,47 +569,47 @@ export default {
|
||||
// width: 128,
|
||||
// prop: 'line1',
|
||||
// label: '产线1',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line2',
|
||||
// label: '产线2',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line3',
|
||||
// label: '产线3',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line4',
|
||||
// label: '产线4',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line5',
|
||||
// label: '产线5',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line6',
|
||||
// label: '产线6',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line7',
|
||||
// label: '产线7',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// },
|
||||
// {
|
||||
// width: 128,
|
||||
// prop: 'line8',
|
||||
// label: '产线8',
|
||||
// align: 'center',
|
||||
// ,
|
||||
// }, -->
|
||||
|
Loading…
Reference in New Issue
Block a user