This commit is contained in:
2022-11-07 14:54:47 +08:00
commit 8cfe73aaef
1227 changed files with 194899 additions and 0 deletions

View File

@@ -0,0 +1,321 @@
<template>
<div id="container" ref="container" class="visual-container order-cockpit">
<el-row
class="container-title"
:style="{
height: beilv * 88 + 'px',
lineHeight: beilv * 88 + 'px',
fontSize: beilv * 30 + 'px'
}"
>
<div :style="{ paddingLeft: 645 * beilv + 'px' }">
<img src="../../../assets/img/logo.png" style="width:1.1em;position: relative;top:.4em" alt="">
合肥新能源数字工厂工单管理驾驶舱
</div>
<el-button
type="text"
class="title-button"
:style="{ right: 33 * beilv + 'px', top: 37 * beilv + 'px' }"
@click="changeFullScreen"
>
<svg-icon v-if="isFullScreen" icon-class="unFullScreenView" :style="{fontSize: 33 * beilv + 'px'}" />
<svg-icon v-else icon-class="fullScreenView" :style="{fontSize: 33 * beilv + 'px'}" />
</el-button>
</el-row>
<el-row class="container-main">
<!-- -->
<el-row :style="{ padding: '0 ' + 9 * beilv + 'px' }" :gutter="16 * beilv">
<el-col :span="10">
<base-container :beilv="beilv" :height="412" :title="'工单一览表'" :title-icon="'cockpit_1_1'">
<work-order :beilv="beilv" :order-msg="orderList" />
</base-container>
</el-col>
<el-col :span="14">
<base-container :beilv="beilv" :height="412" :title="'订单池'" :title-icon="'cockpit_1_2'">
<div class="box-padding specil-table1">
<base-table
:page="1"
:limit="12"
:show-index="false"
:beilv="beilv"
:table-config="orderPool"
:table-data="orderPoolList"
/>
</div>
</base-container>
</el-col>
</el-row>
<!-- -->
<el-row :style="{ padding: '0 ' + 9 * beilv + 'px' }">
<el-col :style="{ margin: 16 * beilv + 'px' + ' 0' }" :span="24">
<base-container :beilv="beilv" :height="520" :title="'在途/完成订单监控'" :title-icon="'cockpit_1_3'">
<div class="box-padding specil-table2">
<base-table
:page="1"
:limit="16"
:show-index="false"
:beilv="beilv"
:table-config="orderMonitiring"
:table-data="orderMonitiringList"
/>
</div>
</base-container>
</el-col>
</el-row>
</el-row>
</div>
</template>
<script>
import baseContainer from './components/baseContainer'
import workOrder from './components/workOrder.vue'
import screenfull from 'screenfull'
import BaseTable from './components/baseTable.vue'
import moment from 'moment'
import orderStatus from './components/orderStatus.vue'
const orderPool = [
{
prop: 'customerName',
label: '客户名称',
minWidth: 35.2
},
{
prop: 'orderCode',
label: '订单编号',
minWidth: 32
},
{
prop: 'productName',
label: '产品名称',
minWidth: 32
},
{
prop: 'planNum',
label: '计划加工量',
minWidth: 23.6
},
{
prop: 'planDelivery',
label: '计划交货期',
minWidth: 28.8
},
{
prop: 'status',
label: '订单状态',
subcomponent: orderStatus,
minWidth: 19
}
]
const orderMonitiring = [
{
prop: 'customerName',
label: '客户名称',
minWidth: 35.2
},
{
prop: 'orderCode',
label: '订单编号',
minWidth: 33.2
},
{
prop: 'status',
label: '订单状态',
subcomponent: orderStatus,
minWidth: 27
},
{
prop: 'completion',
label: '完成率',
minWidth: 24.8
},
{
prop: 'yield',
label: '良品率',
minWidth: 24.8
},
{
prop: 'shiftCosts',
label: '班组费用',
minWidth: 24.8
},
{
prop: 'energyCosts',
label: '能耗费用',
minWidth: 29.4
},
{
prop: 'equipmentCost',
label: '设备费用',
minWidth: 29.4
},
{
prop: 'materialCost',
label: '材料费用',
minWidth: 29.4
},
{
prop: 'totalCost',
label: '总费用',
minWidth: 31.6
}
]
export default {
name: 'Cockpit',
components: {
baseContainer,
workOrder,
BaseTable
},
data() {
return {
beilv: 1,
isFullScreen: false,
orderPool,
orderPoolList: [],
orderMonitiring,
orderMonitiringList: [],
orderList: []
}
},
watch: {
isFullScreen: function(val) {
if (val) {
this.beilv = document.body.offsetWidth / 1920
} else {
this.beilv = document.getElementById('container').offsetWidth / 1920
}
},
'sidebar.opened': function(val) {
console.log(val)
if (!this.isFullScreen) {
setTimeout(() => {
this.beilv = document.getElementById('container').offsetWidth / 1920
}, 300)
}
}
},
mounted() {
this.beilv = document.getElementById('container').offsetWidth / 1920
window.addEventListener('resize', () => {
if (this.isFullScreen) {
this.beilv = document.body.offsetWidth / 1920
} else {
this.beilv = document.getElementById('container').offsetWidth / 1920
}
})
this.getMsg()
},
methods: {
getMsg() {
this.orderList = [
{ code: 'ZGD20221024000110', state: '激活', name: '光伏玻璃2.0', line: 'A', workCode: '20221024000110', percentage: '100%' },
{ code: 'ZGD20221028000157', state: '激活', name: '光伏玻璃2.0', line: 'A', workCode: '20221028000157', percentage: '85%' },
{ code: 'ZGD20221030000142', state: '激活', name: '光伏玻璃2.0', line: 'A', workCode: '20221030000142', percentage: '72%' },
{ code: 'ZGD20221030000098', state: '激活', name: '光伏玻璃2.0', line: 'A', workCode: '20221030000098', percentage: '46%' }
]
const compList = ['SHABO沙玻', 'KIBING旗滨', '金晶玻璃', '济南金昊', '东莞佳美特', '汇中矿产', '文盛新材料', '西点化学', '开源塑胶', '奥驰商贸', '竹中科技', '程龙玻璃']
const arr = []
const temp = []
for (let i = 0; i < 20; i++) {
const obj = {}
const sj = parseInt(Math.random() * 200)
obj.customerName = compList[parseInt(Math.random() * (compList.length))]
obj.orderCode = moment().subtract(sj, 'days').format('YYYYMMDD') + '0000' + parseInt(Math.random() * 89 + 10)
obj.productName = '光伏玻璃2.0'
obj.planNum = parseInt(Math.random() * 800 + 100)
obj.planDelivery = moment().add(sj, 'days').format('YYYY-MM-DD')
obj.status = parseInt(Math.random() * 3 + 1)
arr.push(obj)
}
this.orderPoolList = arr
for (let i = 0; i < 20; i++) {
const obj = {}
const sj = parseInt(Math.random() * 200)
obj.customerName = compList[parseInt(Math.random() * (compList.length))]
obj.orderCode = moment().subtract(sj, 'days').format('YYYYMMDD') + '0000' + parseInt(Math.random() * 89 + 10)
obj.status = parseInt(Math.random() * 3 + 1)
obj.completion = obj.status === 1 ? '0.00%' : (obj.status === 3 ? '100%' : parseInt(Math.random() * 100) + '%')
obj.yield = parseInt(Math.random() * 50 + 50) + '%'
obj.shiftCosts = obj.status === 1 ? parseInt(0).toFixed(2) : parseInt(Math.random() * 800 + 100).toFixed(2)
obj.energyCosts = obj.status === 1 ? parseInt(0).toFixed(2) : parseInt(Math.random() * 800 + 100).toFixed(2)
obj.equipmentCost = obj.status === 1 ? parseInt(0).toFixed(2) : parseInt(Math.random() * 800 + 100).toFixed(2)
obj.materialCost = obj.status === 1 ? parseInt(0).toFixed(2) : parseInt(Math.random() * 800 + 100).toFixed(2)
obj.totalCost = parseInt(obj.shiftCosts + obj.energyCosts + obj.equipmentCost + obj.materialCost).toFixed(2)
temp.push(obj)
}
this.orderMonitiringList = temp
},
change() {
this.isFullScreen = screenfull.isFullscreen
},
init() {
if (screenfull.enabled) {
screenfull.on('change', this.change)
}
},
destroy() {
if (screenfull.enabled) {
screenfull.off('change', this.change)
}
},
changeFullScreen() {
if (!screenfull.enabled) {
this.$message({
message: 'you browser can not work',
type: 'warning'
})
return false
}
this.isFullScreen = !this.isFullScreen
screenfull.toggle(this.$refs.container)
}
}
}
</script>
<style lang="scss" scoped>
.visual-container {
width: 100%;
min-width: 960px;
background: url('../../../assets/img/cockpit/cockpit-back.png') no-repeat;
background-size: cover;
.container-title {
width: 100%;
background: url('../../../assets/img/cockpit/title.png') no-repeat;
background-size: 100% 100%;
color: #fff;
.title-button {
color: #00fff0;
font-size: 20px;
position: absolute;
}
}
.container-main {
padding: 16px 8px;
}
.box-padding {
padding: 0 16px;
}
}
</style>
<style lang="scss">
.order-cockpit {
.specil-table1 {
.el-table .cell {
padding-left: 25px;
padding-right: 25px;
}
.el-table--border th:first-child .cell,
.el-table--border td:first-child .cell {
padding-left: 25px;
}
}
.specil-table2 {
.el-table .cell {
padding-left: 50px;
}
.el-table--border th:first-child .cell,
.el-table--border td:first-child .cell {
padding-left: 50px;
}
}
}
</style>

View File

@@ -0,0 +1,145 @@
<!--
* @Author: gtz
* @Date: 2022-01-19 15:58:17
* @LastEditors: zhp
* @LastEditTime: 2022-01-24 09:18:01
* @Description: file content
* @FilePath: \mt-bus-fe\src\views\OperationalOverview\components\baseContainer\index.vue
-->
<template>
<div class="base-container" :style="{height: height * beilv + 'px', fontSize: 12 * beilv + 'px'}">
<div class="line" />
<div class="line line-vertical" />
<div class="line line-right" />
<div class="line line-right-vertical" />
<div class="line line-bottom" />
<div class="line line-bottom-vertical" />
<div class="line line-bottom-right" />
<div class="line line-bottom-right-vertical" />
<div class="bar-item">
<div v-if="title" class="bar-title">
<span>
<svg-icon :icon-class="titleIcon" style="font-size: 1.5em; position: relative; top: .08em" />
{{ title }}
</span>
</div>
<div class="bar-content">
<slot />
</div>
</div>
</div>
</template>
<script>
export default {
name: 'BaseContainer',
props: {
title: {
type: String,
default: ''
},
titleIcon: {
type: String,
default: ''
},
height: {
type: Number,
default: 200
},
baseSize: {
type: Number,
default: 12
},
beilv: {
type: Number,
default: 1
}
},
data() {
return {
curIndex: 0
}
},
mounted() {
},
methods: {
changeTab(num) {
this.curIndex = num
this.$emit('tabSelect', num)
}
}
}
</script>
<style lang="scss" scoped>
.base-container {
color: #fff;
width: 100%;
background-color: rgba($color: #061027, $alpha: 0.15);
position: relative;
border: 2px solid;
border-image: linear-gradient(90deg, rgba(82, 255, 241, 0.6), rgba(95, 190, 249, 0), rgba(82, 255, 241, 0.6)) 2 2;
box-shadow: inset 0px 0px 20px 0px rgba(255,255,255,0.15);
.line {
position: absolute;
border-top: 4px solid #52FFF1;
width: 2em;
top: -.25em;
left: -.25em;
&-vertical {
top: calc(-5em / 12);
left: calc(-1em / 12);
transform: rotate(90deg);
transform-origin: left;
}
&-right {
top: -.25em;
right: -.25em;
left: inherit;
}
&-right-vertical {
top: calc(-5em / 12);
right: calc(-1em / 12);
left: inherit;
transform: rotate(-90deg);
transform-origin: right;
}
&-bottom {
top: inherit;
left: -.25em;
bottom: -.25em;
}
&-bottom-vertical {
top: inherit;
left: calc(-1em / 12);
bottom: calc(-5em / 12);
transform: rotate(-90deg);
transform-origin: left;
}
&-bottom-right {
top: inherit;
left: inherit;
right: -.25em;
bottom: -.25em;
}
&-bottom-right-vertical {
top: inherit;
left: inherit;
right: calc(-1em / 12);
bottom: calc(-5em / 12);
transform: rotate(90deg);
transform-origin: right;
}
}
.bar-title {
width: 100%;
color: #52FFF1;
font-size: 1.5em;
padding: .67em;
}
// .bar-content{
// padding: 1em;
// }
}
</style>

View File

@@ -0,0 +1,176 @@
<!--
* @Date: 2020-12-14 09:07:03
* @LastEditors: gtz
* @LastEditTime: 2022-06-14 11:12:39
* @FilePath: \mt-bus-fe\src\views\OperationalOverview\components\baseTable.vue
* @Description:
-->
<template>
<div class="visual-base-table-container">
<el-table
v-loading="isLoading"
:header-cell-style="{background:'rgba(79,114,136,0.29)',color:'#fff',height: 28 * beilv + 'px',lineHeight: 28 * beilv + 'px',padding: 0,fontSize: 12 * beilv + 'px'}"
:row-style="setRowStyle"
:data="renderData"
border
style="width: 100%; background: transparent"
>
<el-table-column v-if="page && limit && showIndex" prop="_pageIndex" :label="'tableHeader.index' | i18nFilter" :width="70 * beilv" align="center" />
<el-table-column
v-for="item in renderTableHeadList"
:key="item.prop"
:show-overflow-tooltip="showOverflow"
v-bind="item"
>
<template slot-scope="scope">
<component :is="item.subcomponent" v-if="item.subcomponent" :inject-data="{...scope.row, ...item}" @emitData="emitData" />
<span v-else>{{ scope.row[item.prop] | commonFilter(item.filter) }}</span>
</template>
</el-table-column>
<slot name="content" />
</el-table>
</div>
</template>
<script>
import { isObject, isString } from 'lodash'
export default {
name: 'BaseTable',
filters: {
commonFilter: (source, filterType = a => a) => {
return filterType(source)
}
},
props: {
tableData: {
type: Array,
required: true,
validator: val => val.filter(item => !isObject(item)).length === 0
},
tableConfig: {
type: Array,
required: true,
validator: val => val.filter(item => !isString(item.prop) || !isString(item.label)).length === 0
},
isLoading: {
type: Boolean,
required: false
},
page: {
type: Number,
required: false,
default: 1
},
limit: {
type: Number,
required: false,
default: 5
},
beilv: {
type: Number,
default: 1
},
showOverflow: {
type: Boolean,
default: true
},
showIndex: {
type: Boolean,
default: true
}
},
data() {
return {
tableConfigBak: [],
selectedBox: new Array(100).fill(true)
}
},
computed: {
renderData() {
if (this.tableData.length && !this.tableData[0]._pageIndex) {
this.tableData.forEach((item, index) => {
item._pageIndex = (this.page - 1) * this.limit + index + 1
})
}
return this.tableData.slice((this.page - 1) * this.limit, this.page * this.limit)
},
renderTableHeadList() {
return this.tableConfig.filter((item, index) => {
return this.selectedBox[index]
})
}
},
beforeMount() {
this.selectedBox = new Array(100).fill(true)
},
methods: {
emitData(val) {
this.$emit('emitFun', val)
},
setRowStyle(v) {
if (v.rowIndex % 2 === 0) {
return {
background: 'rgba(76,97,123,0.2)',
color: 'rgba(255,255,255,0.5)',
height: 26 * this.beilv + 'px',
lineHeight: 26 * this.beilv + 'px',
padding: 0,
fontSize: 12 * this.beilv + 'px'
}
} else {
return {
background: 'rgba(79,114,136,0.29)',
color: 'rgba(255,255,255,0.5)',
height: 26 * this.beilv + 'px',
lineHeight: 26 * this.beilv + 'px',
padding: 0,
fontSize: 12 * this.beilv + 'px'
}
}
},
setCellStyle(v) {
return {
lineHeight: 23 * this.beilv + 'px'
}
}
}
}
</script>
<style lang="scss">
@import "~@/styles/index.scss";
.visual-base-table-container {
.el-table {
border: 0;
}
.el-table::before,.el-table--border::after {
background-color: transparent;
}
.el-table th,td{
border-color: #0D1728 !important;
padding: 0;
}
.el-table tr {
background: transparent;
}
.el-table__row:hover > td {
background-color: rgba(79,114,136,0.29) !important;
}
.el-table__row--striped:hover > td {
background-color: rgba(79,114,136,0.29) !important;
}
}
.setting {
text-align: right;
padding: 15px;
.setting-box {
width: 100px;
}
i {
color: #aaa;
@extend .pointer;
}
}
</style>

View File

@@ -0,0 +1,42 @@
<template>
<div :style="{ height: 15 * beilv + 'px' }">
<span v-if="this.injectData.status === 3">
<svg-icon icon-class="green_dot" style="font-size: 14px; position: relative; top: .08em" />
已完成
</span>
<span v-if="this.injectData.status === 1">
<svg-icon icon-class="yellow_dot" style="font-size: 14px; position: relative; top: .08em" />
在途
</span>
<span v-if="this.injectData.status === 2">
<svg-icon icon-class="blue_dot" style="font-size: 14px; position: relative; top: .08em" />
已下发
</span>
</div>
</template>
<script>
export default {
name: 'OrderStatus',
props: {
injectData: {
type: Object,
default: () => ({})
}
},
data() {
return {
beilv: 1
}
},
mounted() {
this.beilv = document.getElementById('container').offsetWidth / 1920
window.addEventListener('resize', () => {
if (this.isFullScreen) {
this.beilv = document.body.offsetWidth / 1920
} else {
this.beilv = document.getElementById('container').offsetWidth / 1920
}
})
}
}
</script>

View File

@@ -0,0 +1,101 @@
<template>
<div class="order-box" :style="{ padding: '0 ' + 16 * beilv + 'px', fontSize: 14 * beilv + 'px'}">
<!-- 小块 -->
<div v-for="(item,index) in orderMsg" :key="index" :style="{ padding: 10 * beilv + 'px' + ' 20px ' + 16 * beilv + 'px' + ' 16px'}" class="box">
<p class="line1">
<span>工单编号<span class="light-color">{{ item.code }}</span></span>
<span class="fr">
状态
<span class="state">{{ item.state }}</span>
</span>
</p>
<p :style="{ paddingLeft: 15 * beilv + 'px'}">
<span>产品名称<span class="light-color">{{ item.name }}</span></span>
<span class="fr">
产线
<span class="light-color" style="margin-right: 25px">{{ item.line }}</span>
</span>
</p>
<p :style="{ paddingLeft: 15 * beilv + 'px'}">
<span>所属订单编号<span class="light-color">{{ item.workCode }}</span></span>
</p>
<div :style="{ paddingLeft: 15 * beilv + 'px'}">
<span v-if="item.percentage === '100%'" class="blue-color"> 订单进度</span>
<span v-else class="light-color">订单进度</span>
<span class="light-color fr">{{ item.percentage }}</span>
<div class="progress-box">
<div
class="progress"
:style="{height: 8 * beilv + 'px', width: item.percentage}"
/>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'WorkOrder',
props: {
orderMsg: {
type: Array,
default: () => []
},
beilv: {
type: Number,
default: 1
}
}
}
</script>
<style lang='scss' scoped>
.order-box {
display: flex;
flex-flow: row wrap;
justify-content: space-between;
.box {
width: 49.5%;
height: 49.5%;
margin-bottom: 8px;
background-image: url('../../../../assets/img/cockpit/module-back.png');
background-repeat: no-repeat;
background-size: 100% 100%;
.light-color {
opacity: 0.5;
}
.blue-color {
color: #3E6AE9;
}
.line1::before {
display: inline-block;
content: "";
width: 4px;
height: 14px;
border-radius: 2px;
margin-right: 8px;
vertical-align: middle;
background-color: #4BFFC8;
}
.state {
display: inline-block;
color: #70F97F;
padding: 2px 4px;
border-radius: 2px;
background: #366F5D;
}
}
}
.progress-box {
border-radius: 5px;
background: #1E2D45;
.progress {
text-align: right;
line-height: 18px;
border-radius: 5px;
padding-right: 5px;
margin-top: 10px;
background: linear-gradient(270deg, #47F8DC 0%, #4573FE 100%);
}
}
</style>