yudao-dev/src/views/equipment/analysis/quality/index.vue
2023-11-11 20:49:31 +08:00

412 lines
8.2 KiB
Vue

<!--
filename: index.vue
author: liubin
date: 2023-09-04 09:34:52
description: 设备质量分析
-->
<template>
<div class="app-container">
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
@headBtnClick="handleSearchBarBtnClick" />
<el-row>
<el-col class="custom-tabs">
<el-tabs
v-model="activeName"
:stretch="true"
@tab-click="handleTabClick">
<el-tab-pane :label="'数据列表'" name="table">
<!-- 列表 -->
<base-table
:table-props="tableProps"
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-data="list"
@emitFun="handleEmitFun"></base-table>
</el-tab-pane>
<el-tab-pane :label="'\u3000柱状图\u3000'" name="graph">
<div
v-if="activeName == 'graph'"
class="graph"
style="height: 40vh; display: flex; flex-direction: column">
<div class="blue-title">各设备加工数量</div>
<LineChart v-if="list && list.length" :list="list" />
<div v-else class="no-data-bg"></div>
</div>
</el-tab-pane>
</el-tabs>
</el-col>
</el-row>
</div>
</template>
<script>
import moment from 'moment';
import LineChart from './components/lineChart.vue';
export default {
name: 'QualityAnalysis',
components: { LineChart },
props: {},
data() {
const now = new Date();
const [y, m, d] = [now.getFullYear(), now.getMonth(), now.getDate()];
return {
dialogVisible: false,
urls: {
page: '/analysis/equipment-analysis/quality',
},
activeName: 'table', // defaults to 'table'
searchBarFormConfig: [
// 产品
{
__index: 'product',
type: 'select',
label: '产品',
placeholder: '请选择产品',
param: 'productId',
},
// 产线
{
__index: 'line',
type: 'select',
label: '产线',
placeholder: '请选择产线',
param: 'lineId',
},
// 时间段
{
type: 'datePicker',
label: '时间段',
dateType: 'daterange', // datetimerange
// format: 'yyyy-MM-dd HH:mm:ss',
format: 'yyyy-MM-dd',
// valueFormat: 'timestamp',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',
defaultTime: ['00:00:00', '23:59:59'],
param: 'recordTime',
defaultSelect: [
new Date(y, m, d)
.toLocaleString()
.split('/')
.map((item, index) => {
if (index == 1 || index == 2) return item.padStart(2, '0');
return item;
})
.join('-'),
new Date(y, m, d, 23, 59, 59)
.toLocaleString()
.split('/')
.map((item, index) => {
if (index == 1 || index == 2) return item.padStart(2, '0');
return item;
})
.join('-'),
],
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
// {
// type: 'separate',
// },
// {
// type: 'button',
// btnName: '列表数据',
// name: 'tableVersion',
// color: 'text btn-table',
// },
// {
// type: 'separate',
// },
// {
// type: 'button',
// btnName: '图形分析',
// name: 'graphVersion',
// color: 'text btn-graph',
// },
],
// 动态的 props
tableProps: [
{
// width: 160,
prop: 'sectionName',
label: '工段',
},
{
// width: 160,
prop: 'equipmentName',
label: '设备名称',
},
{
// width: 160,
prop: 'products',
label: '产品名称',
},
{
// width: 160,
prop: 'inQuantity',
label: '进片数量',
},
{
// width: 160,
prop: 'outQuantity',
label: '出片数量',
},
{
// width: 160,
prop: 'nokQuantity',
label: '破损/不合格数',
},
{
// width: 160,
prop: 'passRate',
label: '合格率',
},
],
lineChartConfig: {
grid: {
top: 88,
left: 56,
right: 56,
bottom: 56,
},
legend: {
top: 0,
left: 0,
padding: 5,
icon: 'roundRect',
itemWidth: 12,
itemHeight: 12,
itemGap: 20,
textStyle: {
fontSize: 14,
lineHeight: 14,
},
},
xAxis: {
type: 'category',
data: ['设备1', '设备2', '设备3', '设备4', '设备5'],
},
yAxis: {
type: 'value',
name: '合格率',
nameLocation: 'end',
nameTextStyle: {
fontSize: 14,
align: 'right',
},
nameGap: 26,
},
series: [
{
name: '产线1',
data: [150, 230, 224, 218, 135],
type: 'line',
smooth: true,
},
{
name: '产线2',
data: [111, 224, 42, 11, 24],
type: 'line',
smooth: true,
},
{
name: '产线3',
data: [218, 112, 331, 44, 99],
type: 'line',
smooth: true,
},
{
name: '产线4',
data: [3, 221, 42, 553, 311],
type: 'line',
smooth: true,
},
],
},
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
lineId: null,
productId: null,
recordTime: [],
},
list: [],
};
},
computed: {},
created() {
this.fillLineOptions();
this.fillProductOptions();
},
mounted() {
this.$refs['search-bar'].headBtnClick('search');
},
methods: {
handleTabClick(tab, event) {
// console.log('tab event', tab, event);
// tab is el-tab vue component.
},
async fillLineOptions() {
const { data } = await this.$axios({
url: '/base/core-production-line/listAll',
method: 'get',
});
const cfg = this.searchBarFormConfig.find(
(item) => item.__index == 'line'
);
this.$set(
cfg,
'selectOptions',
data.map((item) => ({
id: item.id,
name: item.name,
}))
);
},
async fillProductOptions() {
const { data } = await this.$axios({
url: '/base/core-product/listAll',
method: 'get',
});
const cfg = this.searchBarFormConfig.find(
(item) => item.__index == 'product'
);
this.$set(
cfg,
'selectOptions',
data.map((item) => ({
id: item.id,
name: item.name,
}))
);
},
async getList() {
const { data } = await this.$axios({
url: '/analysis/equipment-analysis/quality',
method: 'get',
params: {
lineId: this.queryParams.lineId || null,
productId: this.queryParams.productId || null,
recordTime: this.queryParams.recordTime || null,
},
});
this.list = data.map((item) => ({
...item,
products: item.products?.join(','),
}));
},
handleSearchBarBtnClick(btn) {
// debugger;
switch (btn.btnName) {
case 'search':
this.queryParams.lineId = btn.lineId;
this.queryParams.productId = btn.productId;
this.queryParams.recordTime = btn.recordTime
? btn.recordTime.map((time) =>
moment(new Date(time)).format('YYYY-MM-DD HH:mm:ss')
)
: null;
this.$nextTick(() => {
this.getList();
});
break;
case 'tableVersion':
this.dialogClose();
break;
case 'graphVersion':
this.dialogShow();
break;
}
},
handleEmitFun({ action, payload }) {},
dialogShow() {
this.dialogVisible = true;
},
dialogClose() {
this.dialogVisible = false;
},
},
};
</script>
<style scoped lang="scss">
:deep(.searchBar) {
.el-button.btn-table {
color: rgb(0, 130, 130);
border: 1px solid rgb(0, 130, 130);
padding: 8px 10px;
border: 1px solid rgb(0, 130, 130);
padding: 8px 10px;
&:hover {
border-color: #fff;
color: #fff;
background: rgb(0, 130, 130);
}
}
.el-button.btn-graph {
color: rgb(130, 0, 130);
border: 1px solid rgb(130, 0, 130);
padding: 8px 10px;
&:hover {
border-color: #fff;
color: #fff;
background: rgb(130, 0, 130);
}
}
}
:deep(.custom-tabs) {
.el-tabs__header {
margin-bottom: 8px;
display: inline-block;
transform: translateY(-12px);
}
.el-tabs__item {
padding-left: 0 !important;
padding-right: 0 !important;
line-height: 36px !important;
height: 36px;
}
}
.blue-title {
position: relative;
padding: 4px 0;
padding-left: 12px;
font-size: 14px;
&::before {
content: '';
position: absolute;
left: 0;
top: 6px;
height: 16px;
width: 4px;
border-radius: 1px;
background: #0b58ff;
}
}
</style>