This commit is contained in:
2023-01-03 09:33:30 +08:00
commit bd4d0e897b
190 changed files with 48628 additions and 0 deletions

View File

@@ -0,0 +1,57 @@
<template>
<div class="alarm-information">
<el-menu
:default-active="activeName"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="realTimeAlarm">实时报警</el-menu-item>
<el-menu-item index="historyAlarm">历史报警</el-menu-item>
</el-menu>
<section>
<router-view />
</section>
</div>
</template>
<script>
export default {
name: 'AlarmInformation',
data() {
return {
activeName: 'realTimeAlarm'
}
},
methods: {
handleSelect(name) {
this.$router.push({ name: name })
}
}
}
</script>
<style lang="scss">
.alarm-information {
.el-menu {
background-color: #f2f4f9;
}
.el-menu.el-menu--horizontal {
border-bottom: none;
width: 100%;
display: flex;
justify-content: space-between;
padding: 8px 8px;
.el-menu-item {
height: 48px;
line-height: 48px;
width: 49.4%;
border-radius: 8px;
background-color: #fff;
font-size: 16px;
color: rgba(22, 22, 22, 0.65);
text-align: center;
}
}
.el-tabs__active-bar {
display: none;
}
}
</style>

View File

@@ -0,0 +1,208 @@
<template>
<div class="main-box">
<el-row :gutter="10">
<el-col :span="4">
<div class="left-box">
<el-tree
:data="treeData"
node-key="id"
:props="defaultTime"
default-expand-all
@node-click="clickDevice"
>
</el-tree>
</div>
</el-col>
<el-col :span="20">
<div class="right-box">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<div style="clear: both">
<span>报警总时长为{{ totalTime }}分钟</span>
</div>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
/>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { tableHeight } from '@/utils/index'
import { getTreeData } from '@/api/app'
import { historyAlarmMessage } from '@/api/deviceManagement'
import { timeFormatter } from '@/utils'
import moment from 'moment'
const tableProps = [
{
prop: 'line',
label: '产线'
},
{
prop: 'unit',
label: '单元'
},
{
prop: 'equipmentName',
label: '设备名称',
minWidth: 120
},
{
prop: 'alarmCode',
label: '报警代码',
minWidth: 120
},
{
prop: 'alarmContent',
label: '报警内容',
minWidth: 150
},
{
prop: 'startTime',
filter: timeFormatter,
label: '报警开始时间',
minWidth: 160
},
{
prop: 'endTime',
filter: timeFormatter,
label: '报警结束时间',
minWidth: 160
},
{
prop: 'maintainTime',
label: '报警持续时间/秒',
width: 150
}
]
export default {
name: 'HistoryAlarm',
data() {
return {
treeData: [],
defaultTime: {
children: 'children',
label: 'name'
},
formConfig: [
{
type: 'datePicker',
label: '报警开始时间',
dateType: 'datetimerange',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-ddTHH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
defaultSelect: [],
width: 350
},
{
type: 'input',
label: '报警代码',
placeholder: '报警代码',
param: 'alarmCode'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
}
],
tableProps,
tableData: [],
tableH: tableHeight(340),
total: 0,
listQuery: {
current: 1,
size: 20
},
totalTime: ''
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(340)
})
this.getTree()
this.formConfig[0].defaultSelect = [
moment().format('yyyy-MM-DD') + 'T00:00:00',
moment().format('yyyy-MM-DD') + 'T23:59:59'
]
this.listQuery.startTime = moment().format('yyyy-MM-DD') + 'T00:00:00'
this.listQuery.endTime = moment().format('yyyy-MM-DD') + 'T23:59:59'
this.getList()
},
methods: {
getTree() {
getTreeData().then((res) => {
this.treeData = res.data
})
},
getList() {
historyAlarmMessage({ ...this.listQuery }).then((res) => {
if (res.code === 0) {
this.total = res.data.total
this.tableData = res.data.records
this.totalTime =
res.data.records.length > 0 ? res.data.records[0].totalTime : 0
}
})
},
buttonClick(val) {
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : ''
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : ''
this.listQuery.alarmCode = val.alarmCode
this.listQuery.equipmentName = ''
this.getList()
},
clickDevice(val) {
console.log(val)
if (!val.children) {
this.formConfig[0].defaultSelect = []
this.$refs.searchBarForm.resetForm()
this.listQuery.startTime = ''
this.listQuery.endTime = ''
this.listQuery.alarmCode = ''
this.listQuery.equipmentName = val.name
this.listQuery.current = 1
this.getList()
}
}
}
}
</script>
<style lang="scss" scoped>
.main-box {
width: 100%;
padding: 0px 6px 0 16px;
.left-box,
.right-box {
border-radius: 8px;
background-color: #fff;
height: calc(100vh - 204px);
}
.left-box {
overflow-y: auto;
}
.right-box {
padding: 24px;
}
}
</style>

View File

@@ -0,0 +1,125 @@
<template>
<div class="real-time-alarm">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
/>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
</div>
</template>
<script>
import { tableHeight } from '@/utils/index'
import { getTreeData } from '@/api/app'
import { nowAlarmMessage } from '@/api/deviceManagement'
import { timeFormatter } from '@/utils'
const tableProps = [
{
prop: 'line',
label: '产线',
minWidth: 120
},
{
prop: 'unit',
label: '单元'
},
{
prop: 'equipmentName',
label: '设备名称'
},
{
prop: 'alarmCode',
label: '报警代码'
},
{
prop: 'alarmContent',
label: '报警内容'
},
{
prop: 'startTime',
label: '报警开始时间',
filter: timeFormatter,
minWidth: 160
}
]
export default {
name: 'RealTimeAlarm',
data() {
return {
formConfig: [
{
type: 'cascader',
label: '产线/单元/设备',
selectOptions: [],
param: 'keyword',
cascaderProps: { checkStrictly: true, value: 'name', label: 'name' },
width: 250
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
}
],
tableProps,
tableData: [],
tableH: tableHeight(340),
total: 0,
listQuery: {
current: 1,
size: 20
}
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(340)
})
this.getTree()
this.getList()
},
methods: {
getTree() {
getTreeData().then((res) => {
this.formConfig[0].selectOptions = res.data
})
},
getList() {
nowAlarmMessage({ ...this.listQuery }).then((res) => {
if (res.code === 0) {
this.total = res.data.total
this.tableData = res.data.records
}
})
},
buttonClick(val) {
this.listQuery.line = val.keyword[0]
this.listQuery.unit = val.keyword[1]
this.listQuery.equipmentName = val.keyword[2]
this.getList()
}
}
}
</script>
<style lang="scss" scoped>
.real-time-alarm {
height: calc(100vh - 203px);
padding: 12px 16px;
margin: 0px 16px;
border-radius: 8px;
background-color: #fff;
}
</style>

View File

@@ -0,0 +1,189 @@
<template>
<div class="box">
<span class="title">xxx设备MTBR对比</span>
<div
:id="id"
style="width: 100%"
:style="{ height: chartHeight + 'px' }"
></div>
<div class="bottom-tip">
<div class="l-box">
<p class="num1">78%</p>
<span class="month1">本月</span>
</div>
<div class="r-box">
<p class="num2">78%</p>
<span class="month2">上月</span>
</div>
</div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { tableHeight } from '@/utils/index'
import resize from '@/utils/chartMixins/resize'
export default {
name: 'ContrastChart',
mixins: [resize],
props: {
id: {
type: String,
default: ''
}
},
data() {
return {
chartDom: '',
chart: '',
chartHeight: tableHeight(500) * 0.5
}
},
mounted() {
this.chartDom = document.getElementById(this.id)
this.chart = echarts.init(this.chartDom)
this.getChart()
window.addEventListener('resize', () => {
this.chartHeight = tableHeight(500) * 0.5
})
},
methods: {
getChart() {
var by1 = 80
var by2 = 20
var sy1 = 60
var sy2 = 40
var option = {
color: ['#84E9DC', '#fff', '#E7E9F0', '#E7E9F0'],
tooltip: {
show: false
},
legend: {
show: false
},
series: [
// 内圆1
{
namr: 'lastMonth',
type: 'pie',
zlevel: 2, // 层级
radius: ['45%', '60%'],
center: ['50%', '45%'],
avoidLabelOverlap: false,
silent: true,
tooltip: {
show: false
},
emphasis: {
scale: false
},
label: {
show: false
},
data: [
{
value: sy1,
name: '已完成 ' + sy1
},
{
value: sy2,
name: '未完成 ' + sy2
}
]
},
// 占比环
{
name: 'thisMonth',
type: 'pie',
radius: ['60%', '75%'],
center: ['50%', '45%'],
clockwise: true,
avoidLabelOverlap: false,
emphasis: {
scale: false
},
silent: false,
label: {
show: false
},
data: [
{
value: by1,
name: '已完成 ' + by1,
itemStyle: {
color: '#288aff'
}
},
{
value: by2,
name: '未完成 ' + by2
}
]
}
]
}
this.chart.setOption(option, true)
}
}
}
</script>
<style lang="scss" scoped>
.box {
padding: 16px;
.title::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #0b58ff;
border-radius: 1px;
margin-right: 8px;
vertical-align: middle;
}
.bottom-tip {
.l-box,
.r-box {
width: 50%;
display: inline-block;
text-align: center;
}
.l-box {
border-right: 1px solid #e8e8e8;
}
.num1,
.num2 {
font-size: 28px;
}
.num1 {
color: #3ca8ff;
}
.num2 {
color: #69e6d8;
}
.month1,
.month2 {
font-size: 16px;
color: #000;
}
.month1::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
background: #69e6d8;
border-radius: 4px;
margin-right: 8px;
vertical-align: middle;
}
.month2::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
background: #69e6d8;
border-radius: 4px;
margin-right: 8px;
vertical-align: middle;
}
}
}
</style>

View File

@@ -0,0 +1,89 @@
<template>
<div>
<div
id="main"
style="width: 100%"
:style="{ height: chartHeight + 'px' }"
></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { tableHeight } from '@/utils/index'
import resize from '@/utils/chartMixins/resize'
export default {
name: 'deviceOeeLine',
mixins: [resize],
data() {
return {
chartDom: '',
chart: '',
chartHeight: tableHeight(214) / 2 - 35
}
},
mounted() {
this.chartDom = document.getElementById('main')
this.chart = echarts.init(this.chartDom)
this.getChart()
window.addEventListener('resize', () => {
this.chartHeight = tableHeight(214) / 2 - 35
})
},
methods: {
getChart() {
var option = {
color: ['#5B8FF9', '#5AD8A6', '#5D7092', '#F6BD16'],
tooltip: {
trigger: 'axis'
},
legend: {
data: ['时间开动率', '性能开动率', '设备故障率', '综合效率'],
left: 30
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['1', '2', '3', '4', '5', '6', '7']
},
yAxis: {
type: 'value'
},
series: [
{
name: '时间开动率',
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '性能开动率',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '设备故障率',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '综合效率',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
}
]
}
option && this.chart.setOption(option)
}
}
}
</script>

View File

@@ -0,0 +1,103 @@
<template>
<div>
<div
id="palletLevel"
style="width: 100%"
:style="{ height: chartHeight + 'px' }"
></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { tableHeight } from '@/utils/index'
import resize from '@/utils/chartMixins/resize'
export default {
name: 'PalletLevelChart',
mixins: [resize],
props: {
chartMsg: {
type: Object,
default: () => {}
}
},
data() {
return {
chart: '',
chartHeight: tableHeight(400) * 0.5
}
},
mounted() {
this.$nextTick(() => {
this.getChart()
})
window.addEventListener('resize', () => {
this.chartHeight = tableHeight(400) * 0.5
})
},
watch: {
chartMsg: function () {
this.getChart()
}
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
getChart() {
if (
this.chart !== null &&
this.chart !== '' &&
this.chart !== undefined
) {
this.chart.dispose() // 页面多次刷新会出现警告Dom已经初始化了一个实例这是销毁实例
}
var chartDom = document.getElementById('palletLevel')
this.chart = echarts.init(chartDom)
console.log(this.chartMsg)
var lp = this.chartMsg.okNum
var jg = this.chartMsg.reprocessNum
var fp = this.chartMsg.wasteNum
const color = [
'rgba(91, 143, 249, 0.8500)',
'rgba(90, 216, 166, 0.8500)',
'rgba(246, 189, 22, 0.8500)'
]
var option = {
color: color,
legend: {
icon: 'circle',
bottom: '0',
left: 'center',
itemWidth: 10,
itemHeight: 10
},
series: {
name: 'palletLeve',
type: 'pie',
radius: ['40%', '60%'],
center: ['50%', '45%'],
data: [
{
value: lp,
name: '良品 ' + lp
},
{
value: jg,
name: '再加工品 ' + jg
},
{
value: fp,
name: '废品 ' + fp
}
]
}
}
option && this.chart.setOption(option)
}
}
}
</script>

View File

@@ -0,0 +1,99 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="1月" prop="a">
<el-input v-model="form.a" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="2月" prop="b">
<el-input v-model="form.b" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="3月" prop="c">
<el-input v-model="form.c" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="4月" prop="d">
<el-input v-model="form.d" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="5月" prop="e">
<el-input v-model="form.e" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="6月" prop="f">
<el-input v-model="form.f" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="7月" prop="g">
<el-input v-model="form.g" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="8月" prop="h">
<el-input v-model="form.h" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="9月" prop="i">
<el-input v-model="form.i" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="10月" prop="j">
<el-input v-model="form.j" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="11月" prop="k">
<el-input v-model="form.k" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="12月" prop="l">
<el-input v-model="form.l" placeholder="请输入计划产能"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
name: 'productPowerEdit',
data() {
return {
form: {
a: '',
b: '',
c: '',
d: '',
e: '',
f: '',
g: '',
h: '',
i: '',
j: '',
k: '',
l: ''
}
}
}
}
</script>

View File

@@ -0,0 +1,131 @@
<template>
<div>
<div
id="rateChart"
style="width: 100%"
:style="{ height: chartHeight + 'px' }"
></div>
</div>
</template>
<script>
import * as echarts from 'echarts'
import { tableHeight } from '@/utils/index'
import resize from '@/utils/chartMixins/resize'
export default {
name: 'RateAnalysisChart',
mixins: [resize],
data() {
return {
chartDom: '',
chart: '',
chartHeight: tableHeight(214) - 35
}
},
mounted() {
this.chartDom = document.getElementById('rateChart')
this.chart = echarts.init(this.chartDom)
this.getChart()
window.addEventListener('resize', () => {
this.chartHeight = tableHeight(214) - 35
})
},
methods: {
getChart() {
const xData = []
const yData1 = []
const yData2 = []
for (let i = 1; i <= 31; i++) {
let num = ''
num = i + ''
xData.push(num)
}
for (let i = 1; i <= 31; i++) {
let num = ''
num = parseInt(Math.random() * 23 + 1)
yData1.push(num)
}
for (let i = 1; i <= 31; i++) {
let num = ''
num = parseInt(Math.random() * 10 + 90)
yData2.push(num)
}
const color = ['#73A0FA', '#F6BE19', '#5AD8A6']
var option = {
color: color,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999'
}
}
},
legend: {
data: ['实际运行小时数', '理论运行时长', '设备利用率']
},
xAxis: [
{
type: 'category',
data: xData,
axisPointer: {
type: 'shadow'
}
}
],
yAxis: [
{
type: 'value',
name: '理论运行时长',
axisLabel: {
formatter: '{value} h'
}
},
{
type: 'value',
name: '设备利用率',
axisLabel: {
formatter: '{value} %'
}
}
],
series: [
{
name: '实际运行小时数',
type: 'bar',
tooltip: {
valueFormatter: function (value) {
return value + ' ml'
}
},
data: yData1
},
{
name: '理论运行时长',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + ' ml'
}
},
data: yData1
},
{
name: '设备利用率',
type: 'line',
yAxisIndex: 1,
tooltip: {
valueFormatter: function (value) {
return value + '%'
}
},
data: yData2
}
]
}
option && this.chart.setOption(option)
}
}
}
</script>

View File

@@ -0,0 +1,10 @@
<template>
<div>
<span>设备登记,不做</span>
</div>
</template>
<script>
export default {
name: 'DeviceRegistration'
}
</script>

View File

@@ -0,0 +1,57 @@
<template>
<div class="maintenance-management">
<el-menu
:default-active="activeName"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="plannedMaintenance">计划维护</el-menu-item>
<el-menu-item index="selfMaintenance">自主维护</el-menu-item>
</el-menu>
<section>
<router-view />
</section>
</div>
</template>
<script>
export default {
name: 'MaintenanceManagement',
data() {
return {
activeName: 'plannedMaintenance'
}
},
methods: {
handleSelect(name) {
this.$router.push({ name: name })
}
}
}
</script>
<style lang="scss">
.maintenance-management {
.el-menu {
background-color: #f2f4f9;
}
.el-menu.el-menu--horizontal {
border-bottom: none;
width: 100%;
display: flex;
justify-content: space-between;
padding: 8px 8px;
.el-menu-item {
height: 48px;
line-height: 48px;
width: 49.4%;
border-radius: 8px;
background-color: #fff;
font-size: 16px;
color: rgba(22, 22, 22, 0.65);
text-align: center;
}
}
.el-tabs__active-bar {
display: none;
}
}
</style>

View File

@@ -0,0 +1,482 @@
<template>
<div class="plan-maintenance">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
>
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="170"
label="操作"
fixed="right"
:method-list="tableBtn"
@clickBtn="handleClick"
/>
</base-table>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
<!-- 新增&未派工修改 -->
<base-dialog
:title="addAndEdit"
:dialogVisible="centervisibleAdd"
@cancel="handleCancelAdd"
@confirm="handleConfirmAdd"
:before-close="handleCancelAdd"
>
<planned-maintenance-add
ref="plannedMaintenanceAdd"
@successSubmit="successSubmitAdd"
/>
</base-dialog>
<!-- 确认&已派工的修改 -->
<base-dialog
:title="sureAndEdit"
:dialogVisible="centervisibleSure"
@cancel="handleCancelSure"
@confirm="handleConfirmSure"
:before-close="handleCancelSure"
>
<planned-maintenance-edit
ref="plannedMaintenanceEdit"
@successSubmit="successSubmitEdit"
/>
</base-dialog>
</div>
</template>
<script>
import { tableHeight } from '@/utils/index'
import PlannedMaintenanceAdd from './plannedMaintenanceAdd'
import PlannedMaintenanceEdit from './plannedMaintenanceEdit'
import statusTag from './statusTag.vue'
import { getTreeData } from '@/api/app'
import {
getMaintainManagePage,
maintainManageDispatch,
maintainManageExport,
maintainManageDelete
} from '@/api/deviceManagement'
import { timeFormatter } from '@/utils'
const tableProps = [
{
prop: 'code',
label: '维护工单号',
minWidth: 150
},
{
prop: 'status',
label: '状态',
width: 100,
subcomponent: statusTag
},
{
prop: 'remainTime',
label: '剩余时间',
minWidth: 150
},
{
prop: 'planStartTime',
label: '计划开始时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'planEndTime',
label: '计划结束时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'proLineName',
label: '产线',
minWidth: 150
},
{
prop: 'unitName',
label: '单元',
minWidth: 150
},
{
prop: 'equName',
label: '设备名称',
minWidth: 150
},
{
prop: 'sparePartName',
label: '备件名称',
width: 150
},
{
prop: 'model',
label: '备件型号',
minWidth: 150
},
{
prop: 'replaceNum',
label: '更换数量',
minWidth: 140
},
{
prop: 'maintainContent',
label: '维护内容',
minWidth: 180
},
{
prop: 'executiveStaff',
label: '执行人员',
minWidth: 140
},
{
prop: 'startTime',
label: '实际开始时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'endTime',
label: '实际结束时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'complete',
label: '完成情况',
minWidth: 140
},
{
prop: 'creatorName',
label: '创建人员',
minWidth: 150
},
{
prop: 'createTime',
label: '创建时间',
filter: timeFormatter,
minWidth: 160
}
]
const tableBtn = [
{
type: 'edit',
btnName: '编辑',
showParam: {
type: '&',
data: [
{
type: 'unequal',
name: 'status',
value: '未完成'
}
]
}
},
{
type: 'dispatch',
btnName: '派工',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'status',
value: '未派工'
}
]
}
},
{
type: 'sure',
btnName: '确认',
showParam: {
type: '&',
data: [
{
type: 'unequal',
name: 'status',
value: '已完成'
}
]
}
},
{
type: 'delete',
btnName: '删除'
}
]
export default {
name: 'plannedMaintenance',
components: { PlannedMaintenanceAdd, PlannedMaintenanceEdit },
data() {
return {
formConfig: [
{
type: 'datePicker',
label: '计划开始时间',
dateType: 'datetimerange',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-ddTHH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
width: 350
},
{
type: 'select',
label: '状态',
selectOptions: JSON.parse(localStorage.getItem('publicList'))
.maintainStatusVoList,
labelField: 'dataName',
valueField: 'dataName',
param: 'status',
defaultSelect: '',
width: 100
},
{
type: 'cascader',
label: '产线/单元/设备',
selectOptions: [],
param: 'keyword',
cascaderProps: { checkStrictly: true, value: 'name', label: 'name' },
width: 250
},
{
type: 'input',
label: '维护工单号',
placeholder: '维护工单号',
param: 'code'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: 'button',
btnName: '重置',
name: 'reset'
},
{
type: 'button',
btnName: '新增',
name: 'add',
color: 'primary',
plain: true
},
{
type: 'button',
btnName: '导出',
name: 'export',
color: 'primary',
plain: true
}
],
tableProps,
tableData: [],
tableBtn,
tableH: tableHeight(320),
total: 0,
listQuery: {
current: 1,
size: 20
},
addAndEdit: '',
centervisibleAdd: false,
sureAndEdit: '',
centervisibleSure: false
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(320)
})
this.getTree()
this.getList()
},
methods: {
getTree() {
getTreeData().then((res) => {
this.formConfig[2].selectOptions = res.data
})
},
getList() {
getMaintainManagePage({ ...this.listQuery }).then((res) => {
if (res.code === 0) {
this.total = res.data.total
this.tableData = res.data.records
}
})
},
handleClick(val) {
console.log(val)
switch (val.type) {
case 'edit':
if (val.data.status === '未派工') {
this.addAndEdit = '编辑'
this.centervisibleAdd = true
this.$nextTick(() => {
this.$refs.plannedMaintenanceAdd.init(val.data.id)
})
} else if (val.data.status === '已完成') {
this.sureAndEdit = '编辑'
this.centervisibleSure = true
this.$nextTick(() => {
let param = { id: val.data.id, type: 'edit' }
this.$refs.plannedMaintenanceEdit.init(param)
})
}
break
case 'dispatch':
this.$confirm('确认派工"' + val.data.code + '"吗?', {
type: 'warning'
})
.then(() => {
maintainManageDispatch({ id: val.data.id }).then((res) => {
console.log(res)
this.$message({
message: '派工成功',
type: 'success',
duration: 1500,
onClose: () => {}
})
this.getList()
})
})
.catch(() => {})
break
case 'sure':
this.sureAndEdit = '确认'
this.centervisibleSure = true
this.$nextTick(() => {
let param = { id: val.data.id, type: 'sure' }
this.$refs.plannedMaintenanceEdit.init(param)
})
break
default:
this.$confirm('确认删除工单"' + val.data.code + '"吗?', {
type: 'warning'
})
.then(() => {
maintainManageDelete({ id: val.data.id }).then((res) => {
console.log(res)
this.$message({
message: '工单删除成功',
type: 'success',
duration: 1500,
onClose: () => {}
})
this.listQuery.current = 1
this.getList()
})
})
.catch(() => {})
}
},
buttonClick(val) {
console.log(val)
switch (val.btnName) {
case 'search':
this.listQuery.planStartTime = val.timeVal ? val.timeVal[0] : ''
this.listQuery.planEndTime = val.timeVal ? val.timeVal[1] : ''
this.listQuery.status = val.status
this.listQuery.proLineName = val.keyword[0]
this.listQuery.unitName = val.keyword[1]
this.listQuery.equName = val.keyword[2]
this.listQuery.code = val.code
this.listQuery.current = 1
this.getList()
break
case 'reset':
this.$refs.searchBarForm.resetForm()
this.listQuery.planStartTime = ''
this.listQuery.planEndTime = ''
this.listQuery.status = ''
this.listQuery.proLineName = ''
this.listQuery.unitName = ''
this.listQuery.equName = ''
this.listQuery.code = ''
this.listQuery.current = 1
this.getList()
break
case 'add':
this.addAndEdit = '新增'
this.centervisibleAdd = true
this.$nextTick(() => {
this.$refs.plannedMaintenanceAdd.init()
})
break
default:
maintainManageExport({ ...this.listQuery }).then((response) => {
console.log(response)
let fileName = ''
const contentDisposition = response.headers['content-disposition']
if (contentDisposition) {
fileName = decodeURIComponent(
contentDisposition.slice(
contentDisposition.indexOf('filename=') + 9
)
)
}
const blob = new Blob([response.data])
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = (e) => {
const a = document.createElement('a')
a.download = fileName
a.href = e.target.result
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
})
}
},
handleCancelAdd() {
this.$refs.plannedMaintenanceAdd.formClear()
this.addAndEdit = ''
this.centervisibleAdd = false
},
handleConfirmAdd() {
this.$refs.plannedMaintenanceAdd.submitForm()
},
successSubmitAdd() {
this.handleCancelAdd()
this.getList()
},
handleCancelSure() {
this.$refs.plannedMaintenanceEdit.formClear()
this.sureAndEdit = ''
this.centervisibleSure = false
},
handleConfirmSure() {
this.$refs.plannedMaintenanceEdit.submitForm()
},
successSubmitEdit() {
this.handleCancelSure()
this.getList()
}
}
}
</script>
<style lang="scss" scoped>
.plan-maintenance {
height: calc(100vh - 203px);
padding: 12px 16px;
margin: 0px 16px;
border-radius: 8px;
background-color: #fff;
}
</style>

View File

@@ -0,0 +1,245 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="维护工单号" prop="code">
<el-input
v-model="form.code"
placeholder="维护工单号"
:disabled="isEdit"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划开始时间" prop="planStartTime">
<el-date-picker
v-model="form.planStartTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="计划开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计划结束时间" prop="planEndTime">
<el-date-picker
v-model="form.planEndTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="计划结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" prop="equipmentId">
<el-cascader
v-model="form.equipmentId"
:options="cascaderOptions"
:props="{ value: 'id', label: 'name' }"
style="width: 100%"
@change="selectEq"
></el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="备件名称" prop="sparePartName">
<el-select
v-model="form.sparePartName"
placeholder="备件名称"
@change="selectModel"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsList"
:key="i"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件型号" prop="sparePartModel">
<el-select
v-model="form.sparePartModel"
placeholder="备件型号"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsSpecList"
:key="i"
:label="item.model"
:value="item.model"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="维护内容" prop="maintainContent">
<el-input
v-model="form.maintainContent"
placeholder="维护内容"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { getModelList, getNameList } from '@/api/basicConfig'
import {
getMaintainManage,
maintainManageAdd,
maintainManageUUnDistribute
} from '@/api/deviceManagement'
import moment from 'moment'
import { getTreeData } from '@/api/app'
export default {
name: 'SparePartsAdd',
data() {
return {
form: {
id: '',
code: '',
planStartTime: '',
planEndTime: '',
proLineId: '',
equipmentId: '',
sparePartName: '',
sparePartModel: '',
maintainContent: ''
},
cascaderOptions: [],
rules: {
code: [
{ required: true, message: '请输入维护工单号', trigger: 'blur' }
],
planStartTime: [
{ required: true, message: '请选择计划开始时间', trigger: 'change' }
],
planEndTime: [
{ required: true, message: '请选择计划结束时间', trigger: 'change' }
],
equipmentId: [
{ required: true, message: '请选择设备名称', trigger: 'change' }
],
sparePartName: [
{ required: true, message: '请选择备件名称', trigger: 'change' }
],
sparePartModel: [
{ required: true, message: '请选择备件型号', trigger: 'change' }
]
},
sparePartsList: [],
sparePartsSpecList: [],
isEdit: false
}
},
mounted() {},
methods: {
init(id) {
this.getTree()
this.getNameList()
if (id) {
this.form.id = id
this.isEdit = true
getMaintainManage({ id: id }).then((res) => {
console.log(res)
this.form.code = res.data.code
this.form.planStartTime = res.data.planStartTime
this.form.planEndTime = res.data.planEndTime
this.form.equipmentId = res.data.equipmentId
this.form.proLineId = res.data.proLineId
this.form.sparePartName = res.data.sparePartName
this.selectModel(this.form.sparePartName, 'noClear')
this.form.sparePartModel = res.data.model
this.form.maintainContent = res.data.maintainContent
})
} else {
this.form.planStartTime = moment().format('yyyy-MM-DDTHH:mm:ss')
this.form.planEndTime = moment()
.add(2, 'days')
.format('yyyy-MM-DDTHH:mm:ss')
this.form.id = ''
this.isEdit = false
}
},
getTree() {
getTreeData().then((res) => {
this.cascaderOptions = res.data
})
},
selectEq(val) {
this.form.equipmentId = val[2]
this.form.proLineId = val[0]
},
getNameList() {
getNameList().then((res) => {
console.log(res)
this.sparePartsList = res.data
this.sparePartsSpecList = []
})
},
selectModel(val, param) {
getModelList({
name: val
}).then((res) => {
console.log(res)
this.sparePartsSpecList = res.data
if (param !== 'noClear') {
this.form.sparePartModel = ''
}
})
},
submitForm() {
this.$refs['form'].validate((valid) => {
console.log(this.form)
if (valid) {
if (this.isEdit) {
maintainManageUUnDistribute({ ...this.form }).then((res) => {
if (res.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
}
})
} else {
maintainManageAdd({ ...this.form }).then((res) => {
if (res.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
}
})
}
} else {
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.sparePartsList = []
this.sparePartsSpecList = []
}
}
}
</script>

View File

@@ -0,0 +1,328 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="维护工单号" prop="code">
<el-input
v-model="form.code"
placeholder="维护工单号"
disabled
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划开始时间" prop="planStartTime">
<el-date-picker
v-model="form.planStartTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="计划开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="计划结束时间" prop="planEndTime">
<el-date-picker
v-model="form.planEndTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="计划结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" prop="equipmentId">
<el-cascader
v-model="form.equipmentId"
:options="cascaderOptions"
:props="{ value: 'id', label: 'name' }"
@change="selectEq"
style="width: 100%"
></el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="备件名称" prop="sparePartName">
<el-select
v-model="form.sparePartName"
placeholder="备件名称"
@change="selectModel"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsList"
:key="i"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件型号" prop="sparePartModel">
<el-select
v-model="form.sparePartModel"
placeholder="备件型号"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsSpecList"
:key="i"
:label="item.model"
:value="item.model"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="维护内容" prop="maintainContent">
<el-input
v-model="form.maintainContent"
placeholder="维护内容"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="更换数量" prop="replaceNum">
<el-input-number
v-model="form.replaceNum"
:min="0"
:max="99999999"
label="更换数量"
style="width: 100%"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="执行人员" prop="executeStaff">
<el-input
v-model="form.executeStaff"
placeholder="执行人员"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="实际开始时间" prop="startTime">
<el-date-picker
v-model="form.startTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="实际开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实际结束时间" prop="endTime">
<el-date-picker
v-model="form.endTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="实际结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="完成情况" prop="complete">
<el-input v-model="form.complete" placeholder="完成情况"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { getModelList, getNameList } from '@/api/basicConfig'
import {
getMaintainManage,
maintainManageConfirm,
maintainManageUCompleted
} from '@/api/deviceManagement'
import { getTreeData } from '@/api/app'
import moment from 'moment'
export default {
name: 'PlannedMaintenanceEdit',
data() {
return {
form: {
id: '',
code: '',
planStartTime: '',
planEndTime: '',
equipmentId: '',
proLineId: '',
sparePartName: '',
sparePartModel: '',
maintainContent: '',
replaceNum: null,
executeStaff: '',
startTime: '',
endTime: '',
complete: ''
},
cascaderOptions: [],
rules: {
code: [
{ required: true, message: '请输入维护工单号', trigger: 'blur' }
],
planStartTime: [
{ required: true, message: '请选择计划开始时间', trigger: 'change' }
],
planEndTime: [
{ required: true, message: '请选择计划结束时间', trigger: 'change' }
],
equipmentId: [
{ required: true, message: '请选择设备名称', trigger: 'change' }
],
sparePartName: [
{ required: true, message: '请选择备件名称', trigger: 'change' }
],
model: [
{ required: true, message: '请选择备件型号', trigger: 'change' }
],
replaceNum: [
{ required: true, message: '请输入更换数量', trigger: 'blur' }
],
executeStaff: [
{ required: true, message: '请输入执行人员', trigger: 'blur' }
],
startTime: [
{ required: true, message: '请选择实际开始时间', trigger: 'change' }
],
endTime: [
{ required: true, message: '请选择实际结束时间', trigger: 'change' }
]
},
productionLineList: JSON.parse(localStorage.getItem('publicList'))
.proLineVoList,
sparePartsList: [],
sparePartsSpecList: [],
isSure: false
}
},
methods: {
init(val) {
this.getNameList()
this.getTree()
this.form.id = val.id
if (val.type === 'edit') {
this.isSure = false
getMaintainManage({ id: val.id }).then((res) => {
this.form.code = res.data.code
this.form.planStartTime = res.data.planStartTime
this.form.planEndTime = res.data.planEndTime
this.form.equipmentId = res.data.equipmentId
this.form.proLineId = res.data.proLineId
this.form.sparePartName = res.data.sparePartName
this.selectModel(this.form.sparePartName, 'noClear')
this.form.sparePartModel = res.data.model
this.form.maintainContent = res.data.maintainContent
this.form.replaceNum = res.data.replaceNum
this.form.executeStaff = res.data.executeStaff
this.form.startTime = res.data.startTime
this.form.endTime = res.data.endTime
this.form.complete = res.data.complete
})
} else {
this.isSure = true
getMaintainManage({ id: val.id }).then((res) => {
this.form.code = res.data.code
this.form.planStartTime = res.data.planStartTime
this.form.planEndTime = res.data.planEndTime
this.form.equipmentId = res.data.equipmentId
this.form.proLineId = res.data.proLineId
this.form.sparePartName = res.data.sparePartName
this.form.sparePartModel = res.data.model
this.form.executeStaff = res.data.executeStaff
this.form.replaceNum = res.data.replaceNum
this.form.maintainContent = res.data.maintainContent
this.form.complete = res.data.complete
})
this.form.startTime = moment().format('yyyy-MM-DDTHH:mm:ss')
this.form.endTime = moment().format('yyyy-MM-DDTHH:mm:ss')
}
},
getTree() {
getTreeData().then((res) => {
this.cascaderOptions = res.data
})
},
selectEq(val) {
this.form.equipmentId = val[2]
this.form.proLineId = val[0]
},
getNameList() {
getNameList().then((res) => {
this.sparePartsList = res.data
})
},
selectModel(val, param) {
getModelList({
name: val
}).then((res) => {
this.sparePartsSpecList = res.data
if (param !== 'noClear') {
this.form.sparePartModel = ''
}
})
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.isSure) {
maintainManageConfirm({ ...this.form }).then(() => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
})
} else {
maintainManageUCompleted({ ...this.form }).then(() => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
})
}
} else {
console.log('error submit!!')
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.form.proLineId = ''
this.form.id = ''
this.sparePartsList = []
this.sparePartsSpecList = []
}
}
}
</script>

View File

@@ -0,0 +1,331 @@
<template>
<div class="self-maintenance">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
>
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="80"
label="操作"
fixed="right"
:method-list="tableBtn"
@clickBtn="handleClick"
/>
</base-table>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
<!-- 新增 -->
<base-dialog
:title="addAndEdit"
:dialogVisible="centervisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
>
<self-maintenance-add
ref="selfMaintenanceAdd"
@successSubmit="successSubmit"
/>
</base-dialog>
</div>
</template>
<script>
import { tableHeight } from '@/utils/index'
import SelfMaintenanceAdd from './selfMaintenanceAdd.vue'
import {
getAutoMaintainPage,
autoMaintainExport,
autoMaintainDelete
} from '@/api/deviceManagement'
import { getTreeData } from '@/api/app'
import { timeFormatter } from '@/utils'
const tableProps = [
{
prop: 'code',
label: '维护工单号',
minWidth: 150
},
{
prop: 'proLineName',
label: '产线',
minWidth: 120
},
{
prop: 'unitName',
label: '单元',
minWidth: 150
},
{
prop: 'equName',
label: '设备名称',
minWidth: 150
},
{
prop: 'maintainStaff',
label: '维护人员',
minWidth: 140
},
{
prop: 'sparePartName',
label: '备件名称',
minWidth: 150
},
{
prop: 'model',
label: '备件型号',
minWidth: 150
},
{
prop: 'replaceNum',
label: '更换数量',
minWidth: 140
},
{
prop: 'complete',
label: '完成情况',
minWidth: 140
},
{
prop: 'startTime',
label: '开始时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'endTime',
label: '结束时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'creatorName',
label: '登记人',
minWidth: 140
},
{
prop: 'createTime',
label: '登记时间',
filter: timeFormatter,
minWidth: 160
}
]
const tableBtn = [
{
type: 'edit',
btnName: '编辑'
},
{
type: 'delete',
btnName: '删除'
}
]
export default {
name: 'selfMaintenance',
components: { SelfMaintenanceAdd },
data() {
return {
formConfig: [
{
type: 'datePicker',
label: '开始时间',
dateType: 'datetimerange',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-ddTHH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
width: 350
},
{
type: 'cascader',
label: '产线/单元/设备',
selectOptions: [],
param: 'keyword',
cascaderProps: { checkStrictly: true, value: 'name', label: 'name' },
width: 250
},
{
type: 'input',
label: '维护工单号',
placeholder: '维护工单号',
param: 'code'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: 'button',
btnName: '重置',
name: 'reset'
},
{
type: 'button',
btnName: '新增',
name: 'add',
color: 'primary',
plain: true
},
{
type: 'button',
btnName: '导出',
name: 'export',
color: 'primary',
plain: true
}
],
tableProps,
tableData: [],
tableBtn,
tableH: tableHeight(320),
total: 0,
listQuery: {
current: 1,
size: 20
},
addAndEdit: '',
centervisible: false
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(320)
})
this.getTree()
this.getList()
},
methods: {
getTree() {
getTreeData().then((res) => {
this.formConfig[1].selectOptions = res.data
})
},
getList() {
getAutoMaintainPage({ ...this.listQuery }).then((res) => {
if (res.code === 0) {
this.total = res.data.total
this.tableData = res.data.records
}
})
},
handleClick(val) {
if (val.type === 'edit') {
this.addAndEdit = '编辑'
this.centervisible = true
this.$nextTick(() => {
this.$refs.selfMaintenanceAdd.init(val.data.id)
})
} else {
this.$confirm('确认删除工单号"' + val.data.code + '"吗?', {
type: 'warning'
})
.then(() => {
autoMaintainDelete({ id: val.data.id }).then((res) => {
console.log(res)
this.$message({
message: '工单删除成功',
type: 'success',
duration: 1500,
onClose: () => {}
})
this.listQuery.current = 1
this.getList()
})
})
.catch(() => {})
}
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : ''
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : ''
this.listQuery.proLineName = val.keyword[0]
this.listQuery.unitName = val.keyword[1]
this.listQuery.equName = val.keyword[2]
this.listQuery.code = val.code
this.getList()
break
case 'reset':
this.$refs.searchBarForm.resetForm()
this.listQuery.startTime = ''
this.listQuery.endTime = ''
this.listQuery.proLineName = ''
this.listQuery.unitName = ''
this.listQuery.equName = ''
this.listQuery.code = ''
this.getList()
break
case 'add':
this.addAndEdit = '新增'
this.centervisible = true
this.$nextTick(() => {
this.$refs.selfMaintenanceAdd.init()
})
break
default:
autoMaintainExport({ ...this.listQuery }).then((response) => {
let fileName = ''
const contentDisposition = response.headers['content-disposition']
if (contentDisposition) {
fileName = decodeURIComponent(
contentDisposition.slice(
contentDisposition.indexOf('filename=') + 9
)
)
}
const blob = new Blob([response.data])
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = (e) => {
const a = document.createElement('a')
a.download = fileName
a.href = e.target.result
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
})
}
},
handleCancel() {
this.$refs.selfMaintenanceAdd.formClear()
this.addAndEdit = ''
this.centervisible = false
},
handleConfirm() {
this.$refs.selfMaintenanceAdd.submitForm()
},
successSubmit() {
this.handleCancel()
this.getList()
}
}
}
</script>
<style lang="scss" scoped>
.self-maintenance {
height: calc(100vh - 203px);
padding: 12px 16px;
margin: 0px 16px;
border-radius: 8px;
background-color: #fff;
}
</style>

View File

@@ -0,0 +1,262 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="维护工单号" prop="code">
<el-input
v-model="form.code"
placeholder="维护工单号"
:disabled="isEdit"
></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" prop="equipmentId">
<el-cascader
v-model="form.equipmentId"
:options="cascaderOptions"
:props="{ value: 'id', label: 'name' }"
@change="selectEq"
style="width: 100%"
></el-cascader>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="备件名称" prop="sparePartName">
<el-select
v-model="form.sparePartName"
placeholder="备件名称"
@change="selectModel"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsList"
:key="i"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件型号" prop="sparePartModel">
<el-select
v-model="form.sparePartModel"
placeholder="备件型号"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsSpecList"
:key="i"
:label="item.model"
:value="item.model"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="更换数量" prop="replaceNum">
<el-input-number
v-model="form.replaceNum"
:min="0"
:max="10"
label="更换数量"
style="width: 100%"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="维护人员" prop="maintainStaff">
<el-input
v-model="form.maintainStaff"
placeholder="维护人员"
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="实际开始时间" prop="startTime">
<el-date-picker
v-model="form.startTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="实际开始时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="实际结束时间" prop="endTime">
<el-date-picker
v-model="form.endTime"
type="datetime"
format="yyyy-MM-dd HH:mm:ss"
value-format="yyyy-MM-ddTHH:mm:ss"
placeholder="实际结束时间"
style="width: 100%"
>
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="完成情况" prop="complete">
<el-input v-model="form.complete" placeholder="完成情况"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import defaultSettings from '@/settings'
import { getTreeData } from '@/api/app'
import { getModelList, getNameList } from '@/api/basicConfig'
import moment from 'moment'
import {
getMaintainManage,
autoMaintainAdd,
autoMaintainUpdate
} from '@/api/deviceManagement'
export default {
name: 'SelfMaintenanceAdd',
data() {
return {
form: {
id: '',
code: '',
equipmentId: '',
sparePartName: '',
sparePartModel: '',
replaceNum: null,
maintainStaff: '',
startTime: '',
endTime: '',
complete: ''
},
cascaderOptions: [],
rules: {
code: [
{ required: true, message: '请输入维护工单号', trigger: 'blur' }
],
equipmentId: [
{ required: true, message: '请选择设备名称', trigger: 'change' }
],
sparePartName: [
{ required: true, message: '请选择备件名称', trigger: 'change' }
],
sparePartModel: [
{ required: true, message: '请选择备件型号', trigger: 'change' }
],
replaceNum: [
{ required: true, message: '请输入更换数量', trigger: 'blur' }
],
maintainStaff: [
{ required: true, message: '请输入执行人员', trigger: 'blur' }
],
startTime: [
{ required: true, message: '请选择实际开始时间', trigger: 'change' }
],
endTime: [
{ required: true, message: '请选择实际结束时间', trigger: 'change' }
]
},
productionLineList: defaultSettings.productionLineList,
sparePartsTypeList: defaultSettings.sparePartsTypeList,
sparePartsList: [],
sparePartsSpecList: [],
isEdit: false
}
},
methods: {
init(id) {
this.getTree()
this.getNameList()
if (id) {
this.form.id = id
this.isEdit = true
getMaintainManage({ id }).then((res) => {
this.form.code = res.data.code
this.form.equipmentId = res.data.equipmentId
this.form.proLineId = res.data.proLineId
this.form.sparePartName = res.data.sparePartName
this.form.sparePartModel = res.data.model
this.form.replaceNum = res.data.replaceNum
this.form.maintainStaff = res.data.maintainStaff
this.form.startTime = res.data.startTime
this.form.endTime = res.data.endTime
this.form.complete = res.data.complete
})
} else {
this.form.startTime = moment().format('yyyy-MM-DDTHH:mm:ss')
this.form.endTime = moment().format('yyyy-MM-DDTHH:mm:ss')
this.isEdit = false
this.form.id = ''
}
},
getTree() {
getTreeData().then((res) => {
this.cascaderOptions = res.data
})
},
selectEq(val) {
this.form.equipmentId = val[2]
this.form.proLineId = val[0]
},
getNameList() {
getNameList().then((res) => {
this.sparePartsList = res.data
})
},
selectModel(val) {
getModelList({
name: val
}).then((res) => {
this.sparePartsSpecList = res.data
this.form.sparePartModel = ''
})
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.isEdit) {
autoMaintainUpdate({ ...this.form }).then(() => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
})
} else {
autoMaintainAdd({ ...this.form }).then(() => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
})
}
} else {
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.sparePartsList = []
this.sparePartsSpecList = []
this.form.proLineId = ''
this.form.id = ''
}
}
}
</script>

View File

@@ -0,0 +1,44 @@
<template>
<div>
<el-tag size="medium" :type="tagType" v-if="injectData.status">{{
injectData.status
}}</el-tag>
</div>
</template>
<script>
export default {
name: 'statusTag',
props: {
injectData: {
type: Object,
default: () => ({})
}
},
data() {
return {
tagType: ''
}
},
mounted() {
this.init()
},
methods: {
init() {
if (this.injectData.status === '未派工') {
this.tagType = 'info'
} else if (this.injectData.status === '未完成') {
this.tagType = 'warning'
} else {
this.tagType = 'success'
}
}
},
watch: {
injectData(newVal, oldVal) {
if (oldVal.status !== newVal.status) {
this.init()
}
}
}
}
</script>

View File

@@ -0,0 +1,59 @@
<template>
<div class="performance-analysis">
<el-menu
:default-active="activeName"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="devicePage">设备OEE</el-menu-item>
<el-menu-item index="utilizationRateAnalysis">利用率分析</el-menu-item>
<el-menu-item index="mtbrf">MTBR-F</el-menu-item>
<el-menu-item index="analysisOfPallet">托盘指标分析</el-menu-item>
</el-menu>
<section>
<router-view />
</section>
</div>
</template>
<script>
export default {
name: 'performanceAnalysis',
data() {
return {
activeName: 'devicePage'
}
},
methods: {
handleSelect(name) {
this.$router.push({ name: name })
}
}
}
</script>
<style lang="scss">
.performance-analysis {
.el-menu {
background-color: #f2f4f9;
}
.el-menu.el-menu--horizontal {
border-bottom: none;
width: 100%;
display: flex;
justify-content: space-between;
padding: 8px 8px;
.el-menu-item {
height: 48px;
line-height: 48px;
width: 24.5%;
border-radius: 8px;
background-color: #fff;
font-size: 16px;
color: rgba(22, 22, 22, 0.65);
text-align: center;
}
}
.el-tabs__active-bar {
display: none;
}
}
</style>

View File

@@ -0,0 +1,279 @@
<template>
<div>
<el-row :gutter="10" class="main-box">
<el-col :span="18">
<div class="left-box">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<base-table
ref="palletTable1"
id="palletTable"
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
highlight-current-row
@current-change="selectPallet"
/>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
</div>
</el-col>
<el-col :span="6">
<div class="right-box">
<el-row>
<el-col class="rigth-top">
<span class="title">托盘对应产品等级数据</span>
<base-table
:table-props="tableProps2"
:table-data="tableData2"
:max-height="tableH2"
/>
</el-col>
</el-row>
<el-row>
<el-col class="right-bottom">
<span class="title">托盘对应产品等级分析</span>
<pallet-level-chart :chartMsg="chartMsg" />
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { tableHeight } from '@/utils/index'
import palletLevelChart from './../components/palletLevelChart.vue'
import {
palletIndicatorAnalysisPage,
palletIndicatorAnalysisType
} from '@/api/deviceManagement'
import { timeFormatter } from '@/utils'
const tableProps = [
{
prop: 'proLineName',
label: '产线',
minWidth: 80
},
{
prop: 'code',
label: '工单编号',
minWidth: 120
},
{
prop: 'glassId',
label: '玻璃ID',
minWidth: 120
},
{
prop: 'rackId',
label: '成品架ID',
minWidth: 120
},
{
prop: 'loadTime',
label: '产品上片时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'unloadTime',
label: '产品下片时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'grade',
label: '玻璃等级',
minWidth: 80
},
{
prop: 'palletId',
label: '面磨托盘ID',
minWidth: 120
},
{
prop: 'glassLength',
label: '玻璃长度'
},
{
prop: 'glassWidth',
label: '玻璃宽度'
},
{
prop: 'glassHeight',
label: '玻璃厚度'
}
]
const tableProps2 = [
{
prop: 'productType',
label: '产品分类'
},
{
prop: 'num',
label: '数量'
},
{
prop: 'percentage',
label: '占比'
}
]
export default {
name: 'analysisOfPallet',
components: { palletLevelChart },
data() {
return {
formConfig: [
{
type: 'input',
label: '托盘ID',
placeholder: '托盘ID',
param: 'palletId'
},
{
type: 'datePicker',
label: '产品上片时间',
dateType: 'datetime',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
placeholder: '产品上片时间',
param: 'testTime',
width: 200
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
}
],
listQuery: {
current: 1,
size: 20
},
total: 0,
tableProps,
tableData: [],
tableH: tableHeight(330),
listQuery2: {
current: 1,
size: 500
},
tableProps2,
tableData2: [],
tableH2: tableHeight(360) / 2,
chartMsg: {}
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(330)
this.tableH2 = tableHeight(360) / 2
})
this.getList()
},
methods: {
getList() {
palletIndicatorAnalysisPage({ ...this.listQuery }).then((res) => {
this.tableData = res.data.records
this.total = res.data.total
this.setCurrent()
let palletId = this.tableData[0].palletId
this.getLevel(palletId)
})
},
setCurrent() {
let _this = this
setTimeout(function () {
_this.$refs.palletTable1.setCurrent('palletTable', 0)
}, 500)
},
getLevel() {
// 需要修改ID
palletIndicatorAnalysisType({ id: 1 }).then((res) => {
this.tableData2 = []
if (res.code === 0) {
const data = res.data
this.chartMsg = data
console.log(this.chartMsg)
let obj = {}
obj.productType = '良品'
obj.num = data.okNum
obj.percentage = data.okPercentage
this.tableData2.push(obj)
let obj2 = {}
obj2.productType = '待再加工'
obj2.num = data.reprocessNum
obj2.percentage = data.rePercentage
this.tableData2.push(obj2)
let obj3 = {}
obj3.productType = '废品'
obj3.num = data.wasteNum
obj3.percentage = data.noPercentage
this.tableData2.push(obj3)
}
})
},
buttonClick(val) {
if (val.btnName === 'search') {
this.listQuery.palletId = val.palletId
this.getList()
}
},
selectPallet(newVal) {
let palletId = newVal.palletId
this.getLevel(palletId)
}
}
}
</script>
<style lang="scss" scoped>
.main-box {
width: 100%;
padding: 0px 6px 0 16px;
.left-box {
height: calc(100vh - 204px);
padding: 16px;
border-radius: 8px;
background-color: #fff;
}
.rigth-top {
background-color: #fff;
margin-bottom: 10px;
height: calc((100vh - 214px) / 2);
border-radius: 8px;
padding: 16px;
}
.right-bottom {
background-color: #fff;
height: calc((100vh - 214px) / 2);
border-radius: 8px;
padding: 16px;
}
.title {
display: inline-block;
margin-right: 8px;
margin-bottom: 22px;
}
.title::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #0b58ff;
border-radius: 1px;
margin-right: 8px;
vertical-align: middle;
}
}
</style>

View File

@@ -0,0 +1,304 @@
<template>
<div>
<el-row :gutter="10" class="main-box">
<el-col :span="4">
<div class="left-box">
<el-tree
:data="treeData"
node-key="id"
:props="defaultTime"
default-expand-all
@node-click="clickDevice"
>
</el-tree>
</div>
</el-col>
<el-col :span="20">
<el-row :gutter="10">
<el-col :span="24">
<el-row :gutter="10">
<el-col :span="18">
<div class="top-left">
<div>
<span class="title">月份选择</span>
<el-date-picker
v-model="chooseMonth"
type="month"
placeholder="默认选择本月"
size="small"
>
</el-date-picker>
<el-button
type="primary"
size="small"
style="margin-left: 24px"
>查询</el-button
>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:page-width="50"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
/>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="top-right">
<div>
<span class="title">xx单元计划产能</span>
<svg-icon
icon-class="device_edit"
class="icon-style"
@click="editPower"
/>
</div>
<el-row>
<el-col :span="12">
<base-table
:table-props="tableProps2"
:table-data="tableData2"
:max-height="tableH"
/>
</el-col>
<el-col :span="12">
<base-table
:table-props="tableProps2"
:table-data="tableData3"
:max-height="tableH"
/>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</el-col>
</el-row>
<el-row :gutter="10">
<el-col :span="24">
<div class="right-bottom">
<device-oee-line />
</div>
</el-col>
</el-row>
</el-col>
</el-row>
<!-- 编辑 -->
<base-dialog
title="产能维护"
:dialogVisible="centervisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
>
<product-power-edit ref="product-power" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template>
<script>
import { getTreeData } from '@/api/app'
import { tableHeight } from '@/utils/index'
import {
performanceAnalysisGet,
performanceAnalysisPlan
} from '@/api/deviceManagement'
import productPowerEdit from './../components/productPowerEdit.vue'
import deviceOeeLine from './../components/deviceOeeLine.vue'
const tableProps = [
{
prop: 'startTime',
label: '时间',
minWidth: 90
},
{
prop: 'endTime',
label: '开动时长(h)',
minWidth: 100
},
{
prop: 'inputNum',
label: '负荷时长(h)',
minWidth: 100
},
{
prop: 'outputNum7',
label: '实际产能',
minWidth: 90
},
{
prop: 'lossesNum6',
label: '设计产能',
minWidth: 90
},
{
prop: 'lossesNum5',
label: '时间开动率',
minWidth: 100
},
{
prop: 'lossesNum4',
label: '性能开动率',
minWidth: 100
},
{
prop: 'lossesNum3',
label: '综合效率OEE',
minWidth: 110
},
{
prop: 'lossesNum2',
label: '故障时长',
minWidth: 90
},
{
prop: 'lossesNum1',
label: '设备故障率',
minWidth: 100
}
]
const tableProps2 = [
{
prop: 'startTime',
label: '月份',
width: 50
},
{
prop: 'endTime',
label: '设计产能',
minWidth: 80
}
]
export default {
name: 'deviceOEEPage',
data() {
return {
treeData: [],
defaultTime: {
children: 'children',
label: 'name'
},
chooseMonth: '',
listQuery: {
current: 1,
size: 500
},
tableProps,
tableData: [],
tableH: tableHeight(214) / 2 - 75,
tableProps2,
tableData2: [],
tableData3: [],
centervisible: false
}
},
components: { productPowerEdit, deviceOeeLine },
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(214) / 2 - 75
})
this.getTree()
this.getList()
for (let i = 0; i < 30; i++) {
let obj = {}
obj.startTime = i
this.tableData.push(obj)
}
let arr = []
for (let i = 1; i < 13; i++) {
let obj = {}
obj.endTime = i
arr.push(obj)
}
this.tableData2 = arr.slice(0, 6)
this.tableData3 = arr.slice(6, 12)
},
methods: {
getTree() {
getTreeData().then((res) => {
this.treeData = res.data
})
},
getList() {
// 获取设备OEE
performanceAnalysisGet({ ...this.listQuery }).then((res) => {
console.log(res)
})
},
getPlan() {
// 获取计划产能
performanceAnalysisPlan({ name: '精切磨边', year: '2022' }).then(
(res) => {
console.log(res)
}
)
},
clickDevice(val) {
console.log(val)
if (!val.children) {
console.log(val.children)
}
},
editPower() {
this.centervisible = true
},
handleCancel() {
this.centervisible = false
},
handleConfirm() {
this.centervisible = false
},
successSubmit() {}
}
}
</script>
<style lang="scss" scoped>
.main-box {
width: 100%;
padding: 0px 6px 0 16px;
.left-box,
.top-left,
.top-right,
.right-bottom {
padding: 16px 10px 0;
border-radius: 8px;
background-color: #fff;
}
.left-box {
overflow-y: auto;
height: calc(100vh - 204px);
}
.top-left,
.top-right,
.right-bottom {
height: calc((100vh - 214px) / 2);
}
.top-right,
.top-left {
.title {
display: inline-block;
margin-right: 8px;
margin-bottom: 22px;
}
.title::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #0b58ff;
border-radius: 1px;
margin-right: 8px;
vertical-align: middle;
}
.icon-style {
font-size: 14px;
margin-left: 18px;
cursor: pointer;
}
}
.right-bottom {
margin-top: 10px;
}
}
</style>

View File

@@ -0,0 +1,223 @@
<template>
<div>
<el-row :gutter="10" class="main-box">
<el-col :span="4">
<div class="left-box">
<el-tree
:data="treeData"
node-key="id"
:props="defaultTime"
default-expand-all
@node-click="clickDevice"
>
</el-tree>
</div>
</el-col>
<el-col :span="14">
<div class="middle-box">
<el-row>
<el-col class="middle-top">
<div>
<div class="choose-box">
<el-radio-group v-model="selectDimension" size="small">
<el-radio-button label="year"></el-radio-button>
<el-radio-button label="month"></el-radio-button>
<el-radio-button label="week"></el-radio-button>
</el-radio-group>
</div>
<div class="search-box">
<span>发生时间 </span>
<el-date-picker
v-model="chooseDate"
type="date"
placeholder="请选择"
size="small"
>
</el-date-picker>
<el-button
type="primary"
size="small"
style="margin-left: 24px"
>查询</el-button
>
</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col class="middle-bottom">
<span class="title">xxxx设备 故障信息</span>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:page-width="50"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
/>
</el-col>
</el-row>
</div>
</el-col>
<el-col :span="6">
<div class="right-box">
<el-row>
<el-col class="right-top">
<contrast-chart1 :id="'chart1'" />
</el-col>
</el-row>
<el-row>
<el-col class="right-bottom">
<contrast-chart2 :id="'chart2'" />
</el-col>
</el-row>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { getTreeData } from '@/api/app'
import { tableHeight } from '@/utils/index'
import contrastChart1 from './../components/contrastChart.vue'
import contrastChart2 from './../components/contrastChart.vue'
const tableProps = [
{
prop: 'startState',
label: '前状态'
},
{
prop: 'endState',
label: '后状态'
},
{
prop: 'occurrenceTime',
label: '发生时间'
},
{
prop: 'ChangeTime',
label: '变化时间'
}
]
export default {
name: 'mtbrfPage',
components: {
contrastChart1,
contrastChart2
},
data() {
return {
treeData: [],
defaultTime: {
children: 'children',
label: 'name'
},
listQuery: {
current: 1,
size: 500
},
chooseDate: '',
tableProps,
tableData: [],
tableH: tableHeight(350),
selectDimension: 'year'
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(350)
})
this.getTree()
this.getList()
},
methods: {
getTree() {
getTreeData().then((res) => {
this.treeData = res.data
})
},
clickDevice(val) {
console.log(val)
if (!val.children) {
console.log(val.children)
}
},
getList() {
let arr = []
for (let i = 0; i < 30; i++) {
let obj = {}
obj.startState = i + '2112'
arr.push(obj)
}
this.tableData = arr
}
}
}
</script>
<style lang="scss" scoped>
.main-box {
width: 100%;
padding: 0px 6px 0 16px;
.left-box {
overflow-y: auto;
height: calc(100vh - 204px);
padding: 16px 10px 0;
}
.left-box,
.middle-top,
.middle-bottom,
.right-top,
.right-bottom {
border-radius: 8px;
background-color: #fff;
}
.middle-top {
height: 60px;
margin-bottom: 8px;
padding: 16px;
.choose-box {
display: inline-block;
margin-right: 10px;
}
.search-box {
display: inline-block;
vertical-align: bottom;
}
}
.middle-bottom {
height: calc(100vh - 272px);
}
.right-top {
height: calc((100vh - 212px) * 0.5);
margin-bottom: 8px;
}
.right-bottom {
height: calc((100vh - 212px) * 0.5);
}
.title {
display: inline-block;
margin-right: 8px;
margin-bottom: 22px;
}
.title::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #0b58ff;
border-radius: 1px;
margin-right: 8px;
vertical-align: middle;
}
}
</style>
<style lang="scss">
.middle-top {
.el-radio-button__inner {
background-color: #f2f4f9;
}
}
.middle-bottom {
padding: 16px;
}
</style>

View File

@@ -0,0 +1,101 @@
<template>
<div>
<el-row :gutter="10" class="main-box">
<el-col :span="4">
<div class="left-box">
<el-tree
:data="treeData"
node-key="id"
:props="defaultTime"
default-expand-all
@node-click="clickDevice"
>
</el-tree>
</div>
</el-col>
<el-col :span="20">
<div class="right-box">
<div>
<span class="title">月份选择</span>
<el-date-picker
v-model="chooseMonth"
type="month"
placeholder="默认选择本月"
size="small"
>
</el-date-picker>
<el-button type="primary" size="small" style="margin-left: 24px"
>查询</el-button
>
</div>
<rate-analysis-chart></rate-analysis-chart>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { getTreeData } from '@/api/app'
import rateAnalysisChart from './../components/rateAnalysisChart.vue'
export default {
name: 'utilizationRateAnalysis',
data() {
return {
treeData: [],
defaultTime: {
children: 'children',
label: 'name'
},
chooseMonth: ''
}
},
components: {
rateAnalysisChart
},
mounted() {
this.getTree()
},
methods: {
getTree() {
getTreeData().then((res) => {
this.treeData = res.data
})
},
clickDevice(val) {
console.log(val)
if (!val.children) {
console.log(val.children)
}
}
}
}
</script>
<style lang="scss" scoped>
.main-box {
width: 100%;
padding: 0px 6px 0 16px;
.left-box,
.right-box {
overflow-y: auto;
height: calc(100vh - 204px);
padding: 16px 10px 0;
border-radius: 8px;
background-color: #fff;
}
.title {
display: inline-block;
margin-right: 8px;
margin-bottom: 22px;
}
.title::before {
content: '';
display: inline-block;
width: 4px;
height: 16px;
background: #0b58ff;
border-radius: 1px;
margin-right: 8px;
vertical-align: middle;
}
}
</style>

View File

@@ -0,0 +1,57 @@
<template>
<div class="spare-parts-box">
<el-menu
:default-active="activeName"
mode="horizontal"
@select="handleSelect"
>
<el-menu-item index="sparePartsStock">备件库存</el-menu-item>
<el-menu-item index="sparePartsRecord">备件记录</el-menu-item>
</el-menu>
<section>
<router-view />
</section>
</div>
</template>
<script>
export default {
name: 'SpareParts',
data() {
return {
activeName: 'sparePartsStock'
}
},
methods: {
handleSelect(name) {
this.$router.push({ name: name })
}
}
}
</script>
<style lang="scss">
.spare-parts-box {
.el-menu {
background-color: #f2f4f9;
}
.el-menu.el-menu--horizontal {
border-bottom: none;
width: 100%;
display: flex;
justify-content: space-between;
padding: 8px 8px;
.el-menu-item {
height: 48px;
line-height: 48px;
width: 49.4%;
border-radius: 8px;
background-color: #fff;
font-size: 16px;
color: rgba(22, 22, 22, 0.65);
text-align: center;
}
}
.el-tabs__active-bar {
display: none;
}
}
</style>

View File

@@ -0,0 +1,54 @@
<template>
<el-popover placement="right" width="500" trigger="click">
<el-table :data="tableData">
<el-table-column prop="batchCode" label="批次编码" width="160">
</el-table-column>
<el-table-column prop="supplier" label="供应商" width="220">
</el-table-column>
<el-table-column prop="num" label="当前库存"> </el-table-column>
</el-table>
<el-button
slot="reference"
type="text"
class="tableInnerButton"
@click="showInnerTable(injectData.id)"
>详情</el-button
>
</el-popover>
</template>
<script>
import { getSparePartStockDetail } from '@/api/deviceManagement'
export default {
name: 'InnerTable',
props: {
injectData: {
type: Object,
default: () => ({})
},
itemProp: {
type: String
}
},
data() {
return {
list: this.injectData,
tableData: []
}
},
methods: {
showInnerTable(id) {
console.log(id)
getSparePartStockDetail({ id: id }).then((res) => {
if (res.code === 0) {
this.tableData = res.data
}
})
}
}
}
</script>
<style lang="scss">
.tableInnerButton {
padding: 0;
}
</style>

View File

@@ -0,0 +1,206 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="产线" prop="proLineId">
<el-select
v-model="form.proLineId"
placeholder="产线"
style="width: 100%"
>
<el-option
v-for="item in productionLineList"
:key="item.dataCode"
:label="item.dataName"
:value="item.dataCode"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件类别" prop="type">
<el-select
v-model="form.type"
placeholder="备件类别"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsTypeList"
:key="i"
:label="item.dataName"
:value="item.dataName"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="备件名称" prop="sparePartName">
<el-select
v-model="form.sparePartName"
placeholder="备件名称"
@change="selectModel"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsList"
:key="i"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件型号" prop="model">
<el-select
v-model="form.model"
placeholder="备件型号"
style="width: 100%"
>
<el-option
v-for="(item, i) in sparePartsSpecList"
:key="i"
:label="item.model"
:value="item.model"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="批次编码" prop="batchCode">
<el-input v-model="form.batchCode" placeholder="批次编码"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="入库数量" prop="inNum">
<el-input-number
v-model="form.inNum"
:min="0"
:max="9999999999"
style="width: 100%"
></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="供应商" prop="supplier">
<el-input v-model="form.supplier" placeholder="供应商"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="库位" prop="stockPosition">
<el-input v-model="form.stockPosition" placeholder="库位"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="备注"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { getModelList, getNameList } from '@/api/basicConfig'
import { sparePartStockInStock } from '@/api/deviceManagement'
export default {
name: 'SparePartsAdd',
data() {
return {
form: {
proLineId: '',
type: '',
sparePartName: '',
model: '',
batchCode: '',
inNum: '',
supplier: '',
stockPosition: '',
remark: ''
},
rules: {
proLineId: [
{ required: true, message: '请选择产线', trigger: 'change' }
],
type: [
{ required: true, message: '请选择备件类型', trigger: 'change' }
],
sparePartName: [
{ required: true, message: '请选择备件名称', trigger: 'change' }
],
model: [
{ required: true, message: '请选择备件型号', trigger: 'change' }
],
batchCode: [
{ required: true, message: '请输入批次编码', trigger: 'blur' }
],
inNum: [{ required: true, message: '请输入入库数量', trigger: 'blur' }],
stockPosition: [
{ required: true, message: '请输入库位', trigger: 'blur' }
],
planStartTime: [
{ required: true, message: '请选择计划开始时间', trigger: 'change' }
],
planEndTime: [
{ required: true, message: '请选择计划结束时间', trigger: 'change' }
]
},
productionLineList: JSON.parse(localStorage.getItem('publicList'))
.proLineVoList,
sparePartsTypeList: JSON.parse(localStorage.getItem('publicList'))
.sparePartsTypeList,
sparePartsList: [],
sparePartsSpecList: []
}
},
methods: {
init() {
this.getNameList()
},
getNameList() {
getNameList().then((res) => {
this.sparePartsList = res.data
this.sparePartsSpecList = []
})
},
selectModel(val) {
getModelList({
name: val
}).then((res) => {
this.sparePartsSpecList = res.data
this.form.model = ''
})
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
sparePartStockInStock({ ...this.form }).then((res) => {
if (res.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
}
})
} else {
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.sparePartsList = []
this.sparePartsSpecList = []
}
}
}
</script>

View File

@@ -0,0 +1,218 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="产线1" prop="proLineId">
<el-select
v-model="form.proLineId"
placeholder="产线"
style="width: 100%"
disabled
>
<el-option
v-for="item in productionLineList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件类别" prop="sparePartType">
<el-select
v-model="form.sparePartType"
placeholder="备件类别"
style="width: 100%"
disabled
>
<el-option
v-for="(item, i) in sparePartsTypeList"
:key="i"
:label="item.dataName"
:value="item.dataName"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="备件名称" prop="sparePartName">
<el-select
v-model="form.sparePartName"
placeholder="备件名称"
@change="selectModel"
style="width: 100%"
disabled
>
<el-option
v-for="(item, i) in sparePartsList"
:key="i"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件型号" prop="model">
<el-select
v-model="form.model"
placeholder="备件型号"
style="width: 100%"
disabled
>
<el-option
v-for="(item, i) in sparePartsSpecList"
:key="i"
:label="item.model"
:value="item.model"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="库位" prop="stockPosition">
<el-input v-model="form.stockPosition" placeholder="库位"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="最低安全库存" prop="minNum">
<el-input-number
v-model="form.minNum"
:min="0"
:max="999999999"
style="width: 100%"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最高安全库存" prop="maxNum">
<el-input-number
v-model="form.maxNum"
:min="0"
:max="9999999999"
style="width: 100%"
></el-input-number>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="备注"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { getModelList, getNameList } from '@/api/basicConfig'
import { sparePartStockUpdate, getSparePartStock } from '@/api/deviceManagement'
export default {
name: 'SparePartsEdit',
data() {
return {
form: {
id: '',
proLineId: '',
sparePartType: '',
sparePartName: '',
model: '',
supplier: '',
stockPosition: '',
remark: ''
},
rules: {
proLineId: [
{ required: true, message: '请选择产线', trigger: 'change' }
],
sparePartType: [
{ required: true, message: '请选择备件类型', trigger: 'change' }
],
sparePartName: [
{ required: true, message: '请选择备件名称', trigger: 'change' }
],
model: [
{ required: true, message: '请选择备件型号', trigger: 'change' }
],
stockPosition: [
{ required: true, message: '请输入库位', trigger: 'blur' }
]
},
productionLineList: JSON.parse(localStorage.getItem('publicList'))
.proLineVoList,
sparePartsTypeList: JSON.parse(localStorage.getItem('publicList'))
.sparePartsTypeList,
sparePartsList: [],
sparePartsSpecList: [{ id: 1, name: '1mm' }]
}
},
methods: {
init(id) {
if (id) {
this.form.id = id
getSparePartStock({ id }).then((res) => {
console.log(res)
this.form.proLineId = res.data.proLineId
this.form.sparePartType = res.data.sparePartType
this.form.sparePartName = res.data.sparePartName
this.form.model = res.data.model
this.form.maxNum = res.data.maxNum
this.form.minNum = res.data.minNum
this.form.stockPosition = res.data.stockPosition
this.form.remark = res.data.remark
})
}
},
getNameList() {
getNameList().then((res) => {
this.sparePartsList = res.data
this.sparePartsSpecList = []
})
},
selectModel(val) {
getModelList({
name: val
}).then((res) => {
this.sparePartsSpecList = res.data
this.form.model = ''
})
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
sparePartStockUpdate({
id: this.form.id,
maxNum: this.form.maxNum,
minNum: this.form.minNum,
remark: this.form.remark,
stockPosition: this.form.stockPosition
}).then((res) => {
if (res.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
}
})
} else {
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.sparePartsList = []
this.sparePartsSpecList = []
}
}
}
</script>

View File

@@ -0,0 +1,261 @@
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="产线" prop="proLineId">
<el-select
v-model="form.proLineId"
placeholder="产线"
style="width: 100%"
disabled
>
<el-option
v-for="item in productionLineList"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件类别" prop="sparePartType">
<el-select
v-model="form.sparePartType"
placeholder="备件类别"
style="width: 100%"
disabled
>
<el-option
v-for="(item, i) in sparePartsTypeList"
:key="i"
:label="item.dataName"
:value="item.dataName"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="备件名称" prop="sparePartName">
<el-select
v-model="form.sparePartName"
placeholder="备件名称"
@change="selectModel"
style="width: 100%"
disabled
>
<el-option
v-for="(item, i) in sparePartsList"
:key="i"
:label="item.name"
:value="item.name"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备件型号" prop="model">
<el-select
v-model="form.model"
placeholder="备件型号"
style="width: 100%"
disabled
>
<el-option
v-for="(item, i) in sparePartsSpecList"
:key="i"
:label="item.model"
:value="item.model"
></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="批次编码" prop="batchCode">
<el-select
v-model="form.batchCode"
placeholder="批次编码"
style="width: 100%"
@change="batchChange"
>
<el-option
v-for="(item, i) in batchCodeList"
:key="i"
:label="item.batchCode"
:value="item.batchCode"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="供应商" prop="supplier">
<el-input
v-model="form.supplier"
placeholder="供应商"
disabled
></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="出库数量" prop="outNum">
<el-input-number
v-model="form.outNum"
:min="0"
:max="999999999"
style="width: 100%"
></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="领用人" prop="recipient">
<el-input v-model="form.recipient" placeholder="领用人"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="备注"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { getModelList, getNameList } from '@/api/basicConfig'
import {
sparePartStockOutStock,
getBatchList,
getSparePartStock
} from '@/api/deviceManagement'
export default {
name: 'SparePartsOut',
data() {
return {
form: {
id: '',
proLineId: '',
sparePartType: '',
sparePartName: '',
model: '',
batchCode: '',
supplier: '',
outNum: '',
recipient: '',
remark: ''
},
rules: {
proLineId: [
{ required: true, message: '请选择产线', trigger: 'change' }
],
sparePartType: [
{ required: true, message: '请选择备件类型', trigger: 'change' }
],
sparePartName: [
{ required: true, message: '请选择备件名称', trigger: 'change' }
],
model: [
{ required: true, message: '请选择备件型号', trigger: 'change' }
],
batchCode: [
{ required: true, message: '请选择批次编码', trigger: 'change' }
],
outNum: [
{ required: true, message: '请输入出库数量', trigger: 'blur' }
],
recipient: [
{ required: true, message: '请输入领用人', trigger: 'blur' }
]
},
productionLineList: JSON.parse(localStorage.getItem('publicList'))
.proLineVoList,
sparePartsTypeList: JSON.parse(localStorage.getItem('publicList'))
.sparePartsTypeList,
sparePartsList: [],
sparePartsSpecList: [],
batchCodeList: []
}
},
methods: {
init(id) {
if (id) {
this.form.id = id
this.getBatchList(id)
getSparePartStock({ id }).then((res) => {
this.form.proLineId = res.data.proLineId
this.form.sparePartType = res.data.sparePartType
this.form.sparePartName = res.data.sparePartName
this.form.model = res.data.model
this.form.maxNum = res.data.maxNum
this.form.minNum = res.data.minNum
this.form.stockPosition = res.data.stockPosition
this.form.remark = res.data.remark
})
}
},
getBatchList(id) {
getBatchList({ id }).then((res) => {
this.batchCodeList = res.data
})
},
getNameList() {
getNameList().then((res) => {
this.sparePartsList = res.data
this.sparePartsSpecList = []
})
},
selectModel(val) {
getModelList({
name: val
}).then((res) => {
this.sparePartsSpecList = res.data
this.form.model = ''
})
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
sparePartStockOutStock({
id: this.form.id,
batchCode: this.form.batchCode,
outNum: this.form.outNum,
recipient: this.form.recipient,
remark: this.form.remark
}).then((res) => {
if (res.code === 0) {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500
})
this.$emit('successSubmit')
}
})
} else {
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.sparePartsList = []
this.sparePartsSpecList = []
this.batchCodeList = []
},
batchChange(val) {
this.batchCodeList &&
this.batchCodeList.map((item) => {
if (item.batchCode === val) {
this.form.supplier = item.supplier
}
})
}
}
}
</script>

View File

@@ -0,0 +1,270 @@
<template>
<div class="spare-parts-record">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
/>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
</div>
</template>
<script>
import { tableHeight } from '@/utils/index'
import { getRecordPage, exportHis } from '@/api/deviceManagement'
import { timeFormatter, publicFormatter } from '@/utils'
import moment from 'moment'
const tableProps = [
{
prop: 'type',
label: '类型',
filter: publicFormatter('materialVoList'),
minWidth: 120
},
{
prop: 'proLineName',
label: '产线',
minWidth: 120
},
{
prop: 'sparePartType',
label: '备件类别',
minWidth: 150
},
{
prop: 'sparePartName',
label: '备件名称',
minWidth: 150
},
{
prop: 'model',
label: '备件型号',
minWidth: 150
},
{
prop: 'num',
label: '数量/个',
minWidth: 150
},
{
prop: 'batchCode',
label: '批次编码',
minWidth: 140
},
{
prop: 'supplier',
label: '供应商',
minWidth: 140
},
{
prop: 'stockPosition',
label: '库位',
minWidth: 140
},
{
prop: 'recipient',
label: '领取人',
minWidth: 140
},
{
prop: 'creatorName',
label: '登记人',
minWidth: 140
},
{
prop: 'createTime',
label: '登记时间',
filter: timeFormatter,
minWidth: 160
},
{
prop: 'remark',
label: '备注',
minWidth: 150
}
]
export default {
name: 'SparePartsRecord',
data() {
return {
activeName: 'stock',
formConfig: [
{
type: 'datePicker',
label: '登记时间',
dateType: 'datetimerange',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'yyyy-MM-ddTHH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
defaultSelect: [],
width: 350
},
{
type: 'select',
label: '类型',
selectOptions: JSON.parse(localStorage.getItem('publicList'))
.materialVoList,
labelField: 'dataName',
valueField: 'dataCode',
param: 'stockType',
defaultSelect: '',
width: 100
},
{
type: 'select',
label: '产线',
selectOptions: JSON.parse(localStorage.getItem('publicList'))
.proLineVoList,
param: 'proLineId',
labelField: 'dataName',
valueField: 'dataCode',
defaultSelect: '',
width: 100
},
{
type: 'select',
label: '备件类别',
selectOptions: JSON.parse(localStorage.getItem('publicList'))
.sparePartsTypeList,
param: 'type',
labelField: 'dataName',
valueField: 'dataName',
defaultSelect: '',
width: 150
},
{
type: 'input',
label: '备件名称',
placeholder: '备件名称',
param: 'sparePartName'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: 'button',
btnName: '重置',
name: 'reset'
},
{
type: 'button',
btnName: '导出',
name: 'export',
color: 'primary',
plain: true
}
],
tableProps,
tableData: [],
tableH: tableHeight(320),
total: 0,
listQuery: {
current: 1,
size: 20
}
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(320)
})
this.formConfig[0].defaultSelect = [
moment().format('yyyy-MM-DD') + 'T00:00:00',
moment().format('yyyy-MM-DD') + 'T23:59:59'
]
this.listQuery.startTime = moment().format('yyyy-MM-DD') + 'T00:00:00'
this.listQuery.endTime = moment().format('yyyy-MM-DD') + 'T23:59:59'
this.getList()
},
methods: {
getList() {
getRecordPage({ ...this.listQuery }).then((res) => {
if (res.code === 0) {
this.total = res.data.total
this.tableData = res.data.records
}
})
},
buttonClick(val) {
console.log(val)
if (val.btnName === 'search') {
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : ''
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : ''
this.listQuery.stockType = val.stockType
this.listQuery.proLineId = val.proLineId
this.listQuery.type = val.type
this.listQuery.sparePartName = val.sparePartName
this.listQuery.current = 1
this.getList()
} else if (val.btnName === 'reset') {
this.$refs.searchBarForm.resetForm()
this.formConfig[0].defaultSelect = []
this.listQuery.startTime = ''
this.listQuery.endTime = ''
this.listQuery.stockType = ''
this.listQuery.proLineId = ''
this.listQuery.type = ''
this.listQuery.sparePartName = ''
this.listQuery.current = 1
this.getList()
} else if (val.btnName === 'export') {
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : ''
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : ''
this.listQuery.stockType = val.stockType
this.listQuery.proLineId = val.proLineId
this.listQuery.type = val.type
this.listQuery.sparePartName = val.sparePartName
exportHis({ ...this.listQuery }).then((res) => {
console.log(res)
let fileName = ''
const contentDisposition = res.headers['content-disposition']
if (contentDisposition) {
fileName = decodeURIComponent(
contentDisposition.slice(
contentDisposition.indexOf('filename=') + 9
)
)
}
const blob = new Blob([res.data])
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = (e) => {
const a = document.createElement('a')
a.download = fileName
a.href = e.target.result
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
})
}
}
}
}
</script>
<style lang="scss" scoped>
.spare-parts-record {
height: calc(100vh - 203px);
padding: 12px 16px;
margin: 0px 16px;
border-radius: 8px;
background-color: #fff;
}
</style>

View File

@@ -0,0 +1,356 @@
<template>
<div class="spare-parts-stock">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<base-table
:page="listQuery.current"
:limit="listQuery.size"
:table-props="tableProps"
:table-data="tableData"
:max-height="tableH"
:row-class-name="tableRowClassName"
>
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
fixed="right"
:method-list="tableBtn"
@clickBtn="handleClick"
/>
</base-table>
<pagination
:page.sync="listQuery.current"
:limit.sync="listQuery.size"
:total="total"
@pagination="getList()"
/>
<!-- 入库 -->
<base-dialog
title="入库"
:dialogVisible="centervisibleIn"
@cancel="handleCancelIn"
@confirm="handleConfirmIn"
:before-close="handleCancelIn"
>
<spare-parts-add ref="sparePartsAdd" @successSubmit="successSubmitIn" />
</base-dialog>
<!-- 编辑 -->
<base-dialog
title="编辑"
:dialogVisible="centervisibleEdit"
@cancel="handleCancelEdit"
@confirm="handleConfirmEdit"
:before-close="handleCancelEdit"
>
<spare-parts-edit
ref="sparePartsEdit"
@successSubmit="successSubmitEdit"
/>
</base-dialog>
<!-- 出库 -->
<base-dialog
title="出库"
:dialogVisible="centervisibleOut"
@cancel="handleCancelOut"
@confirm="handleConfirmOut"
:before-close="handleCancelOut"
>
<spare-parts-out ref="sparePartsOut" @successSubmit="successSubmitOut" />
</base-dialog>
</div>
</template>
<script>
import SparePartsAdd from './sparePartsAdd.vue'
import SparePartsEdit from './sparePartsEdit'
import SparePartsOut from './sparePartsOut'
import InnerTable from './InnerTable'
import { tableHeight } from '@/utils/index'
import {
getSparePartStockPage,
sparePartStockExport
} from '@/api/deviceManagement'
const tableProps = [
{
prop: 'proLineName',
label: '产线',
minWidth: 120
},
{
prop: 'sparePartType',
label: '备件类别',
minWidth: 150
},
{
prop: 'sparePartName',
label: '备件名称',
minWidth: 150
},
{
prop: 'model',
label: '备件型号',
minWidth: 150
},
{
prop: 'num',
label: '库存数量/个',
sortable: true,
minWidth: 150
},
{
prop: 'inventoryDetails',
label: '库存详情',
minWidth: 100,
subcomponent: InnerTable
},
{
prop: 'minNum',
label: '最低安全库存',
width: 150
},
{
prop: 'maxNum',
label: '最高安全库存',
width: 150
},
{
prop: 'stockPosition',
label: '库位',
minWidth: 140
},
{
prop: 'remark',
label: '备注',
minWidth: 150
}
]
const tableBtn = [
{
type: 'edit',
btnName: '编辑'
},
{
type: 'output',
btnName: '出库'
}
]
export default {
name: 'SparePartsStock',
components: { SparePartsAdd, SparePartsEdit, SparePartsOut },
data() {
return {
formConfig: [
{
type: 'select',
label: '产线',
selectOptions: JSON.parse(localStorage.getItem('publicList'))
.proLineVoList,
param: 'proLineId',
labelField: 'dataName',
valueField: 'dataCode',
defaultSelect: '',
width: 150
},
{
type: 'select',
label: '备件类别',
selectOptions: JSON.parse(localStorage.getItem('publicList'))
.sparePartsTypeList,
param: 'type',
labelField: 'dataName',
valueField: 'dataName',
defaultSelect: '',
width: 150
},
{
type: 'input',
label: '备件名称',
placeholder: '备件名称',
param: 'sparePartName'
},
{
type: 'input',
label: '备件型号',
placeholder: '备件型号',
param: 'model'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: 'button',
btnName: '重置',
name: 'reset'
},
{
type: 'button',
btnName: '入库',
name: 'add',
color: 'primary',
plain: true
},
{
type: 'button',
btnName: '导出',
name: 'export',
color: 'primary',
plain: true
}
],
tableProps,
tableData: [],
tableBtn,
tableH: tableHeight(320),
total: 0,
listQuery: {
current: 1,
size: 20
},
centervisibleIn: false,
centervisibleEdit: false,
centervisibleOut: false
}
},
mounted() {
window.addEventListener('resize', () => {
this.tableH = tableHeight(320)
})
this.getList()
},
methods: {
getList() {
getSparePartStockPage({ ...this.listQuery }).then((res) => {
console.log(res)
if (res.code === 0) {
this.total = res.data.total
this.tableData = res.data.records
}
})
},
handleClick(val) {
console.log(val)
if (val.type === 'edit') {
this.centervisibleEdit = true
this.$nextTick(() => {
this.$refs.sparePartsEdit.init(val.data.id)
})
} else if (val.type === 'output') {
this.centervisibleOut = true
this.$nextTick(() => {
this.$refs.sparePartsOut.init(val.data.id)
})
}
},
buttonClick(val) {
console.log(val)
switch (val.btnName) {
case 'search':
this.listQuery.proLineId = val.proLineId
this.listQuery.type = val.type
this.listQuery.sparePartName = val.sparePartName
this.listQuery.model = val.model
this.listQuery.current = 1
this.getList()
break
case 'reset':
this.$refs.searchBarForm.resetForm()
this.listQuery.proLineId = ''
this.listQuery.type = ''
this.listQuery.sparePartName = ''
this.listQuery.model = ''
this.listQuery.current = 1
this.getList()
break
case 'add':
this.centervisibleIn = true
this.$nextTick(() => {
this.$refs.sparePartsAdd.init()
})
break
default:
this.listQuery.proLineId = val.proLineId
this.listQuery.type = val.type
this.listQuery.sparePartName = val.sparePartName
this.listQuery.model = val.model
sparePartStockExport({ ...this.listQuery }).then((res) => {
let fileName = ''
const contentDisposition = res.headers['content-disposition']
if (contentDisposition) {
fileName = decodeURIComponent(
contentDisposition.slice(
contentDisposition.indexOf('filename=') + 9
)
)
}
const blob = new Blob([res.data])
const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = (e) => {
const a = document.createElement('a')
a.download = fileName
a.href = e.target.result
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
}
})
}
},
tableRowClassName({ row }) {
if (row.flag && row.flag > 0) {
return 'danger-row'
}
return ''
},
handleCancelIn() {
this.$refs.sparePartsAdd.formClear()
this.centervisibleIn = false
},
handleConfirmIn() {
this.$refs.sparePartsAdd.submitForm()
},
successSubmitIn() {
this.handleCancelIn()
this.getList()
},
handleCancelEdit() {
this.$refs.sparePartsEdit.formClear()
this.centervisibleEdit = false
},
handleConfirmEdit() {
this.$refs.sparePartsEdit.submitForm()
},
successSubmitEdit() {
this.handleCancelEdit()
this.getList()
},
handleCancelOut() {
this.$refs.sparePartsOut.formClear()
this.centervisibleOut = false
},
handleConfirmOut() {
this.$refs.sparePartsOut.submitForm()
},
successSubmitOut() {
this.handleCancelOut()
this.getList()
}
}
}
</script>
<style lang="scss" scoped>
.spare-parts-stock {
height: calc(100vh - 203px);
padding: 12px 16px;
margin: 0px 16px;
border-radius: 8px;
background-color: #fff;
}
</style>

View File

@@ -0,0 +1,10 @@
<template>
<div>
<span>载具管理,暂时不做</span>
</div>
</template>
<script>
export default {
name: 'VehicleManagement'
}
</script>