新增设备总览透光率产线产品监控等
This commit is contained in:
309
src/views/quality/dpdda/defectAnalysis.vue
Normal file
309
src/views/quality/dpdda/defectAnalysis.vue
Normal file
@@ -0,0 +1,309 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<base-table :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-data="list"
|
||||
@emitFun="handleEmitFun">
|
||||
<!-- <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" :method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" /> -->
|
||||
</base-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
|
||||
import {
|
||||
getPdList,
|
||||
} from '@/api/core/monitoring/auto';
|
||||
import { getFactoryPage } from '@/api/core/base/factory';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import { getDefectAnalysis } from '@/api/monitoring/defectSummary';
|
||||
import * as XLSX from 'xlsx'
|
||||
import FileSaver from 'file-saver'
|
||||
export default {
|
||||
name: 'QualityInspectionType',
|
||||
mixins: [basicPageMixin],
|
||||
data() {
|
||||
return {
|
||||
// tableBtn: [
|
||||
// this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||
// ? {
|
||||
// type: 'edit',
|
||||
// btnName: '修改',
|
||||
// }
|
||||
// : undefined,
|
||||
// this.$auth.hasPermi('base:quality-inspection-type:delete')
|
||||
// ? {
|
||||
// type: 'delete',
|
||||
// btnName: '删除',
|
||||
// }
|
||||
// : undefined,
|
||||
// ].filter((v) => v),
|
||||
tableProps: [
|
||||
// {
|
||||
// prop: 'createTime',
|
||||
// label: '添加时间',
|
||||
// fixed: true,
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'factoryName', label: '工厂' },
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'remark', label: '玻璃编号' },
|
||||
{
|
||||
prop: 'checkTime',
|
||||
label: '检测时间',
|
||||
fixed: true,
|
||||
width: 180,
|
||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
},
|
||||
{ prop: 'checkNum', label: '缺陷数' },
|
||||
{
|
||||
prop: 'glassGrade',
|
||||
label: '等级',
|
||||
filter: (val) => val === 0 ? '合格' : val === 1 ? '提示' : val === 2 ? '返修' : val === 3 ? '报废' : ''
|
||||
},
|
||||
{ prop: 'reason', label: '判等原因' },
|
||||
{ prop: 'specifications', label: '规格' },
|
||||
|
||||
|
||||
// {
|
||||
// label: '操作',
|
||||
// alignt: 'center',
|
||||
// subcomponent: {
|
||||
// render: function (h) {
|
||||
// return h('div', null, [
|
||||
// h(
|
||||
// 'el-button',
|
||||
// {
|
||||
// props: {
|
||||
// icon: 'el-icon-edit',
|
||||
// size: 'mini',
|
||||
// type: 'text',
|
||||
// },
|
||||
// },
|
||||
// ' 修改'
|
||||
// ),
|
||||
// h(
|
||||
// 'el-button',
|
||||
// {
|
||||
// props: {
|
||||
// icon: 'el-icon-edit',
|
||||
// size: 'mini',
|
||||
// type: 'text',
|
||||
// },
|
||||
// },
|
||||
// ' 修改'
|
||||
// ),
|
||||
// ]);
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
],
|
||||
//
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'select',
|
||||
label: '工厂',
|
||||
selectOptions: [],
|
||||
param: 'factoryId',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
label: '产线',
|
||||
selectOptions: [],
|
||||
param: 'lineId',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
label: '缺陷数>',
|
||||
// selectOptions: [],
|
||||
param: 'checkNum',
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
label: '时间范围',
|
||||
dateType: 'datetimerange',
|
||||
format: 'yyyy-MM-dd HH:mm:ss',
|
||||
// valueFormat: 'timestamp',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
rangeSeparator: '-',
|
||||
startPlaceholder: '开始时间',
|
||||
endPlaceholder: '结束时间',
|
||||
param: 'timeVal',
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '查询',
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '重置',
|
||||
// name: 'reset',
|
||||
// },
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
// {
|
||||
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||
// ? 'button'
|
||||
// : '',
|
||||
// btnName: '新增',
|
||||
// name: 'add',
|
||||
// plain: true,
|
||||
// color: 'success',
|
||||
// },
|
||||
{
|
||||
type: this.$auth.hasPermi('base:quality-inspection-type:export')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '导出',
|
||||
name: 'export',
|
||||
color: 'warning',
|
||||
},
|
||||
],
|
||||
// 表单配置
|
||||
// formRows: [
|
||||
// [
|
||||
// {
|
||||
// input: true,
|
||||
// label: '检测类型名称',
|
||||
// prop: 'name',
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// // bind: {
|
||||
// // disabled: true, // some condition, like detail mode...
|
||||
// // }
|
||||
// },
|
||||
// ],
|
||||
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||
// ],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
lineId: undefined,
|
||||
factoryId: undefined,
|
||||
checkNum: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
};
|
||||
},
|
||||
// watch: {
|
||||
// form: {
|
||||
// handler: (val) => {
|
||||
// console.log('form changed', val);
|
||||
// },
|
||||
// deep: true
|
||||
// },
|
||||
// },
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDict()
|
||||
},
|
||||
methods: {
|
||||
getDict() {
|
||||
getPdList().then(res => {
|
||||
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||
});
|
||||
|
||||
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||
});
|
||||
},
|
||||
/** base table related */
|
||||
handleTableBtnClick({ data, type }) {
|
||||
switch (type) {
|
||||
case 'edit':
|
||||
this.handleUpdate(data);
|
||||
break;
|
||||
case 'delete':
|
||||
this.handleDelete(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
/** search bar related */
|
||||
handleSearchBarBtnClick(btn) {
|
||||
// const keys = ['name'];
|
||||
switch (btn.btnName) {
|
||||
case 'search':
|
||||
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||
this.queryParams.checkNum = btn.checkNum ? btn.checkNum : undefined
|
||||
|
||||
|
||||
// keys.forEach((key) => {
|
||||
// this.queryParams[key] = btn[key] || null;
|
||||
// });
|
||||
this.getList();
|
||||
break;
|
||||
case 'add':
|
||||
this.handleAdd();
|
||||
break;
|
||||
case 'export':
|
||||
this.handleExport();
|
||||
break;
|
||||
// case 'reset':
|
||||
// this.$refs['search-bar'].resetForm();
|
||||
// this.resetQuery();
|
||||
// break;
|
||||
}
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getDefectAnalysis(this.queryParams).then((response) => {
|
||||
this.list = response.data.list;
|
||||
this.total = response.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||
const fix = tables.querySelector('.el-table__fixed')
|
||||
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||
if (fix) {
|
||||
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||
}
|
||||
if (fixRight) {
|
||||
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||
}
|
||||
let exportTable = XLSX.utils.table_to_book(tables)
|
||||
|
||||
var exportTableOut = XLSX.write(exportTable, {
|
||||
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||
})
|
||||
// sheetjs.xlsx为导出表格的标题名称
|
||||
try {
|
||||
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||
type: 'application/octet-stream'
|
||||
}),'缺陷分析.xlsx')
|
||||
} catch (e) {
|
||||
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||
}
|
||||
return exportTableOut
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
560
src/views/quality/dpdda/defectSummary.vue
Normal file
560
src/views/quality/dpdda/defectSummary.vue
Normal file
@@ -0,0 +1,560 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<base-table :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-data="list"
|
||||
@emitFun="handleEmitFun">
|
||||
<method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" :method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" />
|
||||
</base-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
<div v-if="chartData" class="charts-container">
|
||||
<div v-for="(lineData, lineName) in chartData" :key="lineName" class="chart-wrapper">
|
||||
<div class="blue-block"></div>
|
||||
<h3 class="chart-title">{{ lineName }}</h3>
|
||||
<div :id="`chart-${lineName}`" class="chart" style="width: 100%; height: 300px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<defect-summary-det ref="defectSummaryDetRef" v-if="defectVis" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
|
||||
import {
|
||||
getPdList,
|
||||
} from '@/api/core/monitoring/auto';
|
||||
import { getFactoryPage } from '@/api/core/base/factory';
|
||||
import { getDefectSummaryTable, getDefectSummaryChart } from '@/api/monitoring/defectSummary';
|
||||
import * as echarts from 'echarts';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import defectSummaryDet from './defectSummaryDet.vue'
|
||||
export default {
|
||||
name: 'QualityInspectionType',
|
||||
mixins: [basicPageMixin],
|
||||
components: {
|
||||
defectSummaryDet
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||
? {
|
||||
type: 'detail',
|
||||
btnName: '缺陷详情',
|
||||
}
|
||||
: undefined,
|
||||
// this.$auth.hasPermi('base:quality-inspection-type:delete')
|
||||
// ? {
|
||||
// type: 'delete',
|
||||
// btnName: '删除',
|
||||
// }
|
||||
// : undefined,
|
||||
].filter((v) => v),
|
||||
tableProps: [
|
||||
// {
|
||||
// prop: 'createTime',
|
||||
// label: '添加时间',
|
||||
// fixed: true,
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'factoryName', label: '工厂' },
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'glassNum', label: '玻璃总数' },
|
||||
{
|
||||
prop: 'okNum',
|
||||
label: '合格品数',
|
||||
},
|
||||
{ prop: 'okRate', label: '合格百分比' },
|
||||
{ prop: 'repairNum', label: '返修品数' },
|
||||
{ prop: 'repairRate', label: '返修百分比' },
|
||||
{ prop: 'ngNum', label: '废片数' },
|
||||
{ prop: 'ngRate', label: '废片百分比' },
|
||||
{ prop: 'oneNgNum', label: '1类缺陷玻璃数量' },
|
||||
{ prop: 'twoNgNum', label: '2类缺陷玻璃数量' },
|
||||
{ prop: 'threeNgNum', label: '3类缺陷玻璃数量' },
|
||||
|
||||
|
||||
|
||||
|
||||
// {
|
||||
// label: '操作',
|
||||
// alignt: 'center',
|
||||
// subcomponent: {
|
||||
// render: function (h) {
|
||||
// return h('div', null, [
|
||||
// h(
|
||||
// 'el-button',
|
||||
// {
|
||||
// props: {
|
||||
// icon: 'el-icon-edit',
|
||||
// size: 'mini',
|
||||
// type: 'text',
|
||||
// },
|
||||
// },
|
||||
// ' 修改'
|
||||
// ),
|
||||
// h(
|
||||
// 'el-button',
|
||||
// {
|
||||
// props: {
|
||||
// icon: 'el-icon-edit',
|
||||
// size: 'mini',
|
||||
// type: 'text',
|
||||
// },
|
||||
// },
|
||||
// ' 修改'
|
||||
// ),
|
||||
// ]);
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
],
|
||||
//
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'select',
|
||||
label: '工厂',
|
||||
selectOptions: [],
|
||||
param: 'factoryId',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
label: '产线',
|
||||
selectOptions: [],
|
||||
multiple: true,
|
||||
param: 'lineId',
|
||||
},
|
||||
// {
|
||||
// type: 'input',
|
||||
// label: '缺陷数>',
|
||||
// // selectOptions: [],
|
||||
// param: 'number',
|
||||
// },
|
||||
{
|
||||
type: 'datePicker',
|
||||
label: '时间范围',
|
||||
dateType: 'datetimerange',
|
||||
format: 'yyyy-MM-dd HH:mm:ss',
|
||||
// valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
valueFormat: 'timestamp',
|
||||
defaultTime: ['00:00:00', '23:59:59'],
|
||||
rangeSeparator: '-',
|
||||
startPlaceholder: '开始时间',
|
||||
endPlaceholder: '结束时间',
|
||||
param: 'timeVal',
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '查询',
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '重置',
|
||||
// name: 'reset',
|
||||
// },
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
// {
|
||||
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||
// ? 'button'
|
||||
// : '',
|
||||
// btnName: '新增',
|
||||
// name: 'add',
|
||||
// plain: true,
|
||||
// color: 'success',
|
||||
// },
|
||||
{
|
||||
type: this.$auth.hasPermi('base:quality-inspection-type:export')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '导出',
|
||||
name: 'export',
|
||||
color: 'warning',
|
||||
},
|
||||
],
|
||||
// 表单配置
|
||||
// formRows: [
|
||||
// [
|
||||
// {
|
||||
// input: true,
|
||||
// label: '检测类型名称',
|
||||
// prop: 'name',
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// // bind: {
|
||||
// // disabled: true, // some condition, like detail mode...
|
||||
// // }
|
||||
// },
|
||||
// ],
|
||||
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||
// ],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
chartData: {},
|
||||
charts: {},
|
||||
defectVis:false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
lineId: undefined,
|
||||
factoryId: undefined,
|
||||
checkNum: undefined,
|
||||
startTime: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
};
|
||||
},
|
||||
// watch: {
|
||||
// form: {
|
||||
// handler: (val) => {
|
||||
// console.log('form changed', val);
|
||||
// },
|
||||
// deep: true
|
||||
// },
|
||||
// },
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDict()
|
||||
},
|
||||
methods: {
|
||||
getDict() {
|
||||
getPdList().then(res => {
|
||||
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||
});
|
||||
|
||||
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||
});
|
||||
},
|
||||
/** base table related */
|
||||
handleTableBtnClick({ data, type }) {
|
||||
switch (type) {
|
||||
case 'detail':
|
||||
this.defectVis = true
|
||||
this.$nextTick(() => {
|
||||
this.$refs.defectSummaryDetRef.init({
|
||||
factoryId:data.factoryId,
|
||||
lineId: [data.lineId],
|
||||
factoryName: data.factoryName,
|
||||
lineName: data.lineName,
|
||||
startTime: this.queryParams.startTime,
|
||||
endTime: this.queryParams.endTime,
|
||||
|
||||
})
|
||||
})
|
||||
break;
|
||||
case 'delete':
|
||||
this.handleDelete(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
// 销毁所有 ECharts 实例
|
||||
Object.values(this.charts).forEach(chart => {
|
||||
if (chart && chart.dispose) {
|
||||
chart.dispose();
|
||||
}
|
||||
});
|
||||
this.charts = {};
|
||||
},
|
||||
/**
|
||||
* 初始化单个图表
|
||||
* @param {string} lineName - 产线名称
|
||||
* @param {Array} lineData - 该产线的原始数据
|
||||
*/
|
||||
initSingleChart(lineName, lineData) {
|
||||
// 如果已有实例,先销毁
|
||||
if (this.charts[lineName]) {
|
||||
this.charts[lineName].dispose();
|
||||
}
|
||||
|
||||
const chartDom = document.getElementById(`chart-${lineName}`);
|
||||
if (!chartDom || !lineData || lineData.length === 0) {
|
||||
console.warn(`图表容器 chart-${lineName} 未找到或数据为空`);
|
||||
return;
|
||||
}
|
||||
|
||||
const myChart = echarts.init(chartDom);
|
||||
|
||||
// --- 动态处理数据逻辑 ---
|
||||
const startTime = this.queryParams.startTime;
|
||||
const endTime = this.queryParams.endTime;
|
||||
|
||||
if (!startTime || !endTime) {
|
||||
console.error("起始时间或结束时间为空,无法计算时间差。");
|
||||
return;
|
||||
}
|
||||
|
||||
const durationDays = (endTime - startTime) / (1000 * 60 * 60 * 24);
|
||||
const isHourly = durationDays < 7;
|
||||
|
||||
// 使用Map来保证顺序,并能存储聚合后的数据和原始显示标签
|
||||
const aggregatedMap = new Map();
|
||||
|
||||
lineData.forEach(item => {
|
||||
let groupKey; // 用于分组的键
|
||||
let displayLabel; // 用于显示的标签
|
||||
|
||||
if (isHourly) {
|
||||
// --- 方法一:使用字符串分割 ---
|
||||
const timePart = item.timePoint.split('T')[1];
|
||||
groupKey = timePart ? timePart : item.timePoint; // 安全处理
|
||||
|
||||
displayLabel = item.timePoint.replace('T', ' ');
|
||||
} else {
|
||||
// 按天聚合:分组键和显示标签都到天
|
||||
groupKey = item.timePoint.split('T')[0];
|
||||
displayLabel = groupKey;
|
||||
}
|
||||
|
||||
if (!aggregatedMap.has(groupKey)) {
|
||||
aggregatedMap.set(groupKey, {
|
||||
displayLabel: displayLabel,
|
||||
okNum: 0,
|
||||
repairNum: 0,
|
||||
ngNum: 0
|
||||
});
|
||||
}
|
||||
|
||||
const aggregatedItem = aggregatedMap.get(groupKey);
|
||||
aggregatedItem.okNum += item.okNum || 0;
|
||||
aggregatedItem.repairNum += item.repairNum || 0;
|
||||
aggregatedItem.ngNum += item.ngNum || 0;
|
||||
});
|
||||
|
||||
// 准备 ECharts 所需的数据格式
|
||||
const xAxisData = [];
|
||||
const okNumData = [];
|
||||
const repairNumData = [];
|
||||
const ngNumData = [];
|
||||
|
||||
aggregatedMap.forEach(item => {
|
||||
xAxisData.push(item.displayLabel);
|
||||
okNumData.push(item.okNum);
|
||||
repairNumData.push(item.repairNum);
|
||||
ngNumData.push(item.ngNum);
|
||||
});
|
||||
|
||||
// --- ECharts 配置项 ---
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: { type: 'cross' },
|
||||
},
|
||||
legend: {
|
||||
data: ['合格品数', '返修品数', '废片数'],
|
||||
itemHeight: 2,
|
||||
itemWidth: 20,
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '20%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: xAxisData,
|
||||
axisLabel: {
|
||||
rotate: 45,
|
||||
interval: 0, // 强制显示所有标签
|
||||
formatter: function (value) {
|
||||
if (isHourly) {
|
||||
// 从 "2025-10-30 00:00" 中提取 "00:00" 进行显示
|
||||
return value.split(' ')[1];
|
||||
} else {
|
||||
// 天级别,显示 "MM-DD"
|
||||
const dateParts = value.split('-');
|
||||
return `${dateParts[1]}-${dateParts[2]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '合格品数',
|
||||
type: 'line',
|
||||
showSymbol: false,
|
||||
data: okNumData,
|
||||
itemStyle: { color: 'rgba(40, 138, 255, 1)' },
|
||||
},
|
||||
{
|
||||
name: '返修品数',
|
||||
type: 'line',
|
||||
showSymbol: false,
|
||||
data: repairNumData,
|
||||
itemStyle: { color: 'rgba(115, 222, 147, 1)' },
|
||||
},
|
||||
{
|
||||
name: '废片数',
|
||||
type: 'line',
|
||||
showSymbol: false,
|
||||
data: ngNumData,
|
||||
itemStyle: { color: 'rgba(255, 206, 106, 1)' },
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
this.charts[lineName] = myChart;
|
||||
|
||||
// 监听容器大小变化
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
myChart.resize();
|
||||
});
|
||||
resizeObserver.observe(chartDom);
|
||||
myChart._resizeObserver = resizeObserver;
|
||||
},
|
||||
|
||||
/**
|
||||
* 根据获取到的 chartData 更新所有图表
|
||||
*/
|
||||
updateAllCharts() {
|
||||
if (!this.chartData) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用 nextTick 确保 v-for 生成的 DOM 已存在
|
||||
this.$nextTick(() => {
|
||||
const lineNames = Object.keys(this.chartData);
|
||||
lineNames.forEach(lineName => {
|
||||
this.initSingleChart(lineName, this.chartData[lineName]);
|
||||
});
|
||||
});
|
||||
},
|
||||
/** search bar related */
|
||||
handleSearchBarBtnClick(btn) {
|
||||
switch (btn.btnName) {
|
||||
case 'search':
|
||||
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||
this.getList();
|
||||
break;
|
||||
case 'add':
|
||||
this.handleAdd();
|
||||
break;
|
||||
case 'export':
|
||||
this.handleExport();
|
||||
break;
|
||||
// case 'reset':
|
||||
// this.$refs['search-bar'].resetForm();
|
||||
// this.resetQuery();
|
||||
// break;
|
||||
}
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getDefectSummaryTable(this.queryParams).then((response) => {
|
||||
this.list = response.data;
|
||||
// this.total = response.data.total;
|
||||
this.loading = false;
|
||||
})
|
||||
getDefectSummaryChart(this.queryParams).then((res) => {
|
||||
console.log('res.data', res.data);
|
||||
|
||||
this.chartData = res.data || {};
|
||||
// 手动调用更新图表的方法
|
||||
this.updateAllCharts();
|
||||
// // this.total = response.data.total;
|
||||
// this.loading = false;
|
||||
})
|
||||
},
|
||||
/** 表单重置 */
|
||||
reset() {
|
||||
this.form = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
code: undefined,
|
||||
remark: undefined,
|
||||
};
|
||||
this.resetForm('form');
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||
const fix = tables.querySelector('.el-table__fixed')
|
||||
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||
if (fix) {
|
||||
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||
}
|
||||
if (fixRight) {
|
||||
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||
}
|
||||
let exportTable = XLSX.utils.table_to_book(tables)
|
||||
|
||||
var exportTableOut = XLSX.write(exportTable, {
|
||||
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||
})
|
||||
// sheetjs.xlsx为导出表格的标题名称
|
||||
try {
|
||||
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||
type: 'application/octet-stream'
|
||||
}), '缺陷汇总.xlsx')
|
||||
} catch (e) {
|
||||
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||
}
|
||||
return exportTableOut
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.charts-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.chart-wrapper {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
margin-top: 10px;
|
||||
/* 最小宽度,防止缩得太小 */
|
||||
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px; */
|
||||
/* padding: 10px; */
|
||||
}
|
||||
|
||||
.blue-block {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
width: 4px;
|
||||
height: 16px;
|
||||
background-color: #0B58FF;
|
||||
border-radius: 1px;
|
||||
margin-right: 8px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.chart-title {
|
||||
text-align: left;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
224
src/views/quality/dpdda/defectSummaryDet.vue
Normal file
224
src/views/quality/dpdda/defectSummaryDet.vue
Normal file
@@ -0,0 +1,224 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-drawer title="详情" :visible.sync="visible" size="70%" @close='closeD'>
|
||||
<div class="box">
|
||||
<!-- 顶部信息展示区域 -->
|
||||
<div class="info-header">
|
||||
<div class="info-item">
|
||||
<span class="label">工厂:</span>
|
||||
<span class="value">{{ factoryName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">产线:</span>
|
||||
<span class="value">{{ lineName }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="label">时间范围:</span>
|
||||
<span class="value">{{ timeRange }}</span>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<el-button type="primary" @click="handleExport">导出</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 表格 -->
|
||||
<base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps"
|
||||
:table-data="tableData" :span-method="spanMethod" :max-height="tableH">
|
||||
</base-table>
|
||||
</div>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import * as XLSX from 'xlsx';
|
||||
import { getDefectSummaryDet } from '@/api/monitoring/defectSummary';
|
||||
// import { publicFormatter } from '@/utils/dict'
|
||||
|
||||
const tableProps = [
|
||||
{ prop: 'defectLevel', label: '缺陷等级' },
|
||||
{ prop: 'defectName', label: '缺陷类型' },
|
||||
{ prop: 'defectNum', label: '玻璃数量' }
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'EnergyStatisticsDet',
|
||||
props: {},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
tableProps,
|
||||
tableData: [],
|
||||
tableBtn: [],
|
||||
tableH: this.tableHeight(115),
|
||||
total: 0,
|
||||
queryParams: { pageNo: 1, pageSize: 30 },
|
||||
factoryName: '',
|
||||
lineName: '',
|
||||
timeRange: '',
|
||||
name: '',
|
||||
energyType: '',
|
||||
energyTypeId: '',
|
||||
addOrEditTitle: "",
|
||||
centervisible: false,
|
||||
collectionList: [
|
||||
{ value: 0, label: '否' },
|
||||
{ value: 1, label: '是' }
|
||||
],
|
||||
showBtn: true,
|
||||
selectedList: []
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.addEventListener('resize', () => {
|
||||
this.tableH = this.tableHeight(115)
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
spanMethod({ row, column, rowIndex, columnIndex }) {
|
||||
const fields = ['defectLevel']
|
||||
const cellValue = row[column.property]
|
||||
if (cellValue && fields.includes(column.property)) {
|
||||
const prevRow = this.tableData[rowIndex - 1]
|
||||
let nextRow = this.tableData[rowIndex + 1]
|
||||
if (prevRow && prevRow[column.property] === cellValue) {
|
||||
return { rowspan: 0, colspan: 0 }
|
||||
} else {
|
||||
let countRowspan = 1
|
||||
while (nextRow && nextRow[column.property] === cellValue) {
|
||||
nextRow = this.tableData[++countRowspan + rowIndex]
|
||||
}
|
||||
if (countRowspan > 1) {
|
||||
return { rowspan: countRowspan, colspan: 1 }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
init(data) {
|
||||
this.visible = true;
|
||||
this.factoryName = data.factoryName || '未知工厂';
|
||||
this.lineName = data.lineName || '未知产线';
|
||||
|
||||
if (data.startTime && data.endTime) {
|
||||
const start = moment(data.startTime).format('yyyy-MM-DD HH:mm:ss');
|
||||
const end = moment(data.endTime).format('yyyy-MM-DD HH:mm:ss');
|
||||
this.timeRange = `${start} - ${end}`;
|
||||
} else {
|
||||
this.timeRange = '';
|
||||
}
|
||||
|
||||
this.queryParams.factoryId = data.factoryId;
|
||||
this.queryParams.lineId = data.lineId;
|
||||
this.queryParams.startTime = data.startTime;
|
||||
this.queryParams.endTime = data.endTime;
|
||||
|
||||
this.getList();
|
||||
},
|
||||
|
||||
getList() {
|
||||
getDefectSummaryDet({ ...this.queryParams }).then((res) => {
|
||||
this.tableData = res.data || [];
|
||||
})
|
||||
},
|
||||
|
||||
closeD() {
|
||||
this.$emit('closeDrawer');
|
||||
},
|
||||
|
||||
closeDet() {
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// --- 重写的导出方法 ---
|
||||
// --- 修改后的导出方法 ---
|
||||
handleExport() {
|
||||
console.log("开始执行导出...");
|
||||
this.$modal.confirm('确定要导出表格数据吗?').then(() => {
|
||||
console.log("用户确认导出");
|
||||
|
||||
// 1. 准备数据
|
||||
console.log("tableProps:", this.tableProps);
|
||||
console.log("tableData:", this.tableData);
|
||||
|
||||
// 1.1 准备表头 (新增了 '工厂', '产线', '时间范围')
|
||||
const headers = ['工厂', '产线', '时间范围', ...this.tableProps.map(prop => prop.label)];
|
||||
console.log("生成的表头:", headers);
|
||||
|
||||
// 1.2 准备表格数据
|
||||
const exportData = [];
|
||||
this.tableData.forEach((row) => {
|
||||
const newRow = [];
|
||||
// 先添加顶部信息列
|
||||
newRow.push(this.factoryName);
|
||||
newRow.push(this.lineName);
|
||||
newRow.push(this.timeRange);
|
||||
|
||||
// 再添加表格数据列
|
||||
this.tableProps.forEach((prop) => {
|
||||
// 直接填入所有数据,不再对 defectLevel 进行合并判断
|
||||
newRow.push(row[prop.prop] !== undefined ? row[prop.prop] : '');
|
||||
});
|
||||
exportData.push(newRow);
|
||||
});
|
||||
console.log("处理后的数据:", exportData);
|
||||
|
||||
// 2. 创建工作簿和工作表
|
||||
try {
|
||||
const worksheet = XLSX.utils.aoa_to_sheet([headers, ...exportData]);
|
||||
console.log("工作表创建成功");
|
||||
const workbook = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(workbook, worksheet, '缺陷详情数据');
|
||||
console.log("工作簿创建成功");
|
||||
|
||||
// 3. 触发下载
|
||||
const fileName = `${this.factoryName}-${this.lineName}-缺陷汇总详情-${moment().format('YYYYMMDDHHmmss')}.xlsx`;
|
||||
console.log("准备下载文件:", fileName);
|
||||
XLSX.writeFile(workbook, fileName);
|
||||
console.log("下载触发成功");
|
||||
} catch (error) {
|
||||
console.error("生成Excel文件时出错:", error);
|
||||
this.$modal.msgError('导出失败,生成文件时出错!');
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log("用户取消导出或发生错误:", error);
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
padding: 0 32px;
|
||||
}
|
||||
|
||||
.info-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-around;
|
||||
padding: 16px 0;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
margin-bottom: 16px;
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 32px;
|
||||
font-size: 16px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
.label {
|
||||
color: #606266;
|
||||
margin-right: 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.value {
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
416
src/views/quality/dpdda/sectionDefect.vue
Normal file
416
src/views/quality/dpdda/sectionDefect.vue
Normal file
@@ -0,0 +1,416 @@
|
||||
<template>
|
||||
<div style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
|
||||
<el-row class="" style="
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 0;
|
||||
border-radius: 8px;
|
||||
">
|
||||
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
|
||||
<base-table :max-height="tableH" :table-props="tableProps" :page="queryParams.pageNo"
|
||||
:limit="queryParams.pageSize" :table-data="list" @emitFun="handleEmitFun" />
|
||||
</el-row>
|
||||
<!-- 搜索工作栏 -->
|
||||
|
||||
<!-- 用一个 div 包裹表格和图表,并使用 flex 布局 -->
|
||||
<el-row class="" style="
|
||||
height: 1px;
|
||||
flex: 1;
|
||||
margin-bottom: 12px;
|
||||
background: #fff;
|
||||
padding: 16px 16px 32px;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<div id="chart" style="width: 100%; height: 300px;"></div>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getPdList,
|
||||
} from '@/api/core/monitoring/auto';
|
||||
import { getFactoryPage } from '@/api/core/base/factory';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import { getSectionDefect } from '@/api/monitoring/defectSummary';
|
||||
import * as echarts from 'echarts';
|
||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||
export default {
|
||||
name: 'QualityInspectionType',
|
||||
mixins: [basicPageMixin, tableHeightMixin],
|
||||
data() {
|
||||
return {
|
||||
tableBtn: [
|
||||
this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||
? {
|
||||
type: 'edit',
|
||||
btnName: '修改',
|
||||
}
|
||||
: undefined,
|
||||
this.$auth.hasPermi('base:quality-inspection-type:delete')
|
||||
? {
|
||||
type: 'delete',
|
||||
btnName: '删除',
|
||||
}
|
||||
: undefined,
|
||||
].filter((v) => v),
|
||||
tableProps: [
|
||||
// {
|
||||
// prop: 'createTime',
|
||||
// label: '添加时间',
|
||||
// fixed: true,
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'factoryName', label: '工厂' },
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'checkCount', label: '检测片数' },
|
||||
{
|
||||
prop: 'ngCount',
|
||||
label: '不良合计',
|
||||
},
|
||||
{
|
||||
prop: 'ngRate',
|
||||
label: '不良率',
|
||||
},
|
||||
{ prop: 'originalNgCount', label: '原片不良' },
|
||||
{ prop: 'edgeNgCount', label: '磨边不良' },
|
||||
{ prop: 'silkNgCount', label: '丝印不良' },
|
||||
{ prop: 'drillNgCount', label: '打孔不良' },
|
||||
{ prop: 'coatingNgCount', label: '镀膜不良' },
|
||||
{ prop: 'packNgCount', label: '钢包不良' },
|
||||
|
||||
|
||||
|
||||
// {
|
||||
// label: '操作',
|
||||
// alignt: 'center',
|
||||
// subcomponent: {
|
||||
// render: function (h) {
|
||||
// return h('div', null, [
|
||||
// h(
|
||||
// 'el-button',
|
||||
// {
|
||||
// props: {
|
||||
// icon: 'el-icon-edit',
|
||||
// size: 'mini',
|
||||
// type: 'text',
|
||||
// },
|
||||
// },
|
||||
// ' 修改'
|
||||
// ),
|
||||
// h(
|
||||
// 'el-button',
|
||||
// {
|
||||
// props: {
|
||||
// icon: 'el-icon-edit',
|
||||
// size: 'mini',
|
||||
// type: 'text',
|
||||
// },
|
||||
// },
|
||||
// ' 修改'
|
||||
// ),
|
||||
// ]);
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
],
|
||||
//
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'select',
|
||||
label: '工厂',
|
||||
selectOptions: [],
|
||||
param: 'factoryId',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
label: '产线',
|
||||
selectOptions: [],
|
||||
multiple: true,
|
||||
param: 'lineId',
|
||||
},
|
||||
// {
|
||||
// type: 'input',
|
||||
// label: '缺陷数>',
|
||||
// // selectOptions: [],
|
||||
// param: 'number',
|
||||
// },
|
||||
{
|
||||
type: 'datePicker',
|
||||
label: '时间范围',
|
||||
dateType: 'datetimerange',
|
||||
format: 'yyyy-MM-dd HH:mm:ss',
|
||||
valueFormat: 'timestamp',
|
||||
rangeSeparator: '-',
|
||||
startPlaceholder: '开始时间',
|
||||
endPlaceholder: '结束时间',
|
||||
param: 'timeVal',
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '查询',
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '重置',
|
||||
// name: 'reset',
|
||||
// },
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
// {
|
||||
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||
// ? 'button'
|
||||
// : '',
|
||||
// btnName: '新增',
|
||||
// name: 'add',
|
||||
// plain: true,
|
||||
// color: 'success',
|
||||
// },
|
||||
{
|
||||
type: this.$auth.hasPermi('base:quality-inspection-type:export')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '导出',
|
||||
name: 'export',
|
||||
color: 'warning',
|
||||
},
|
||||
],
|
||||
// 表单配置
|
||||
// formRows: [
|
||||
// [
|
||||
// {
|
||||
// input: true,
|
||||
// label: '检测类型名称',
|
||||
// prop: 'name',
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// // bind: {
|
||||
// // disabled: true, // some condition, like detail mode...
|
||||
// // }
|
||||
// },
|
||||
// ],
|
||||
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||
// ],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
lineId: undefined,
|
||||
factoryId: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
};
|
||||
},
|
||||
// watch: {
|
||||
// form: {
|
||||
// handler: (val) => {
|
||||
// console.log('form changed', val);
|
||||
// },
|
||||
// deep: true
|
||||
// },
|
||||
// },
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDict()
|
||||
},
|
||||
methods: {
|
||||
getDict() {
|
||||
getPdList().then(res => {
|
||||
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||
});
|
||||
|
||||
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||
});
|
||||
},
|
||||
/** base table related */
|
||||
handleTableBtnClick({ data, type }) {
|
||||
switch (type) {
|
||||
case 'edit':
|
||||
this.handleUpdate(data);
|
||||
break;
|
||||
case 'delete':
|
||||
this.handleDelete(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
/** search bar related */
|
||||
handleSearchBarBtnClick(btn) {
|
||||
switch (btn.btnName) {
|
||||
case 'search':
|
||||
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||
this.getList();
|
||||
break;
|
||||
case 'add':
|
||||
this.handleAdd();
|
||||
break;
|
||||
case 'export':
|
||||
this.handleExport();
|
||||
break;
|
||||
case 'reset':
|
||||
this.$refs['search-bar'].resetForm();
|
||||
this.resetQuery();
|
||||
break;
|
||||
}
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getSectionDefect(this.queryParams).then((response) => {
|
||||
this.list = response.data;
|
||||
// 定义颜色数组,与你提供的顺序一致
|
||||
const colors = [
|
||||
'rgba(99, 189, 255, 1)',
|
||||
'rgba(113, 100, 255, 1)',
|
||||
'rgba(255, 104, 96, 1)',
|
||||
'rgba(255, 151, 71, 1)',
|
||||
'rgba(176, 235, 66, 1)',
|
||||
'rgba(214, 128, 255, 1)',
|
||||
'rgba(0, 67, 210, 1)'
|
||||
];
|
||||
|
||||
const series = response.data.map((item, index) => {
|
||||
// 为每个系列分配颜色,index 从 0 开始,依次对应 colors 数组
|
||||
const color = colors[index % colors.length]; // 使用取模确保不越界
|
||||
|
||||
return {
|
||||
name: item.lineName,
|
||||
type: 'bar',
|
||||
stack: 'Ad',
|
||||
barWidth: '20',
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
itemStyle: {
|
||||
color: color // 指定当前系列的颜色
|
||||
},
|
||||
data: [
|
||||
item.originalNgCount,
|
||||
item.edgeNgCount,
|
||||
item.silkNgCount,
|
||||
item.drillNgCount,
|
||||
item.coatingNgCount,
|
||||
item.packNgCount
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
this.loading = false;
|
||||
this.getChart(series);
|
||||
});
|
||||
},
|
||||
getChart(series) {
|
||||
var chartDom = document.getElementById('chart');
|
||||
var myChart = echarts.init(chartDom);
|
||||
var option;
|
||||
option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: 30,
|
||||
top: 20,
|
||||
right: 30,
|
||||
bottom:20
|
||||
},
|
||||
legend: {},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
data: ['原片不良', '磨边不良', '丝印不良', '打孔不良', '镀膜不良', ' 钢包不良']
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value'
|
||||
}
|
||||
],
|
||||
series: series
|
||||
};
|
||||
|
||||
option && myChart.setOption(option);
|
||||
},
|
||||
/** 导出按钮操作 */
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||
const fix = tables.querySelector('.el-table__fixed')
|
||||
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||
if (fix) {
|
||||
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||
}
|
||||
if (fixRight) {
|
||||
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||
}
|
||||
let exportTable = XLSX.utils.table_to_book(tables)
|
||||
|
||||
var exportTableOut = XLSX.write(exportTable, {
|
||||
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||
})
|
||||
// sheetjs.xlsx为导出表格的标题名称
|
||||
try {
|
||||
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||
type: 'application/octet-stream'
|
||||
}), '工段不良.xlsx')
|
||||
} catch (e) {
|
||||
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||
}
|
||||
return exportTableOut
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
/* 添加 scoped 以避免样式污染 */
|
||||
.app-container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* 垂直排列 */
|
||||
gap: 20px;
|
||||
}
|
||||
.table-container,
|
||||
.chart-container {
|
||||
flex: 1;
|
||||
/* 让两个容器平分父容器的空间 */
|
||||
min-height: 300px;
|
||||
/* 设置最小高度,防止内容过少时变形 */
|
||||
border: 1px solid #ebeef5;
|
||||
/* 添加一个边框,方便看清分隔 */
|
||||
border-radius: 4px;
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* 确保图表容器的父元素也有高度,ECharts 才能正确渲染 */
|
||||
.chart-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
</style>
|
||||
305
src/views/quality/transmittanceTesting.vue
Normal file
305
src/views/quality/transmittanceTesting.vue
Normal file
@@ -0,0 +1,305 @@
|
||||
<template>
|
||||
<div class="app-container">
|
||||
<!-- 搜索工作栏 -->
|
||||
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
|
||||
|
||||
<!-- 列表 -->
|
||||
<base-table :max-height="tableH" :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize"
|
||||
:table-data="list" @emitFun="handleEmitFun">
|
||||
<!-- <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" :method-list="tableBtn"
|
||||
@clickBtn="handleTableBtnClick" /> -->
|
||||
</base-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<!-- 对话框(添加 / 修改) -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment';
|
||||
import { getPdList,} from '@/api/core/monitoring/auto';
|
||||
import { getFactoryPage } from '@/api/core/base/factory';
|
||||
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||
import { getTranslucentPage, exportTranslucent } from '@/api/monitoring/defectSummary';
|
||||
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||
export default {
|
||||
name: 'QualityInspectionType',
|
||||
mixins: [basicPageMixin, tableHeightMixin],
|
||||
data() {
|
||||
return {
|
||||
// tableBtn: [
|
||||
// this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||
// ? {
|
||||
// type: 'edit',
|
||||
// btnName: '修改',
|
||||
// }
|
||||
// : undefined,
|
||||
// this.$auth.hasPermi('base:quality-inspection-type:delete')
|
||||
// ? {
|
||||
// type: 'delete',
|
||||
// btnName: '删除',
|
||||
// }
|
||||
// : undefined,
|
||||
// ].filter((v) => v),
|
||||
tableProps: [
|
||||
// {
|
||||
// prop: 'createTime',
|
||||
// label: '添加时间',
|
||||
// fixed: true,
|
||||
// width: 180,
|
||||
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||
// },
|
||||
{ prop: 'factoryName', label: '工厂' },
|
||||
{ prop: 'lineName', label: '产线' },
|
||||
{ prop: 'timeVal', label: '时间段' },
|
||||
{ prop: 'totalNum', label: '玻璃总数' },
|
||||
{ prop: 'goodNum', label: '一等品数量' },
|
||||
{ prop: 'passNum', label: '二等品数量' },
|
||||
{ prop: 'scrapNum', label: '废片数' },
|
||||
{ prop: 'passRate', label: '合格率' },
|
||||
],
|
||||
//
|
||||
searchBarFormConfig: [
|
||||
{
|
||||
type: 'select',
|
||||
label: '工厂',
|
||||
selectOptions: [],
|
||||
param: 'factoryId',
|
||||
},
|
||||
{
|
||||
type: 'select',
|
||||
label: '产线',
|
||||
selectOptions: [],
|
||||
param: 'lineId',
|
||||
},
|
||||
{
|
||||
type: 'datePicker',
|
||||
label: '时间范围',
|
||||
dateType: 'datetimerange',
|
||||
format: 'yyyy-MM-dd HH:mm:ss',
|
||||
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||
rangeSeparator: '-',
|
||||
startPlaceholder: '开始时间',
|
||||
endPlaceholder: '结束时间',
|
||||
param: 'timeVal',
|
||||
width: 350
|
||||
},
|
||||
{
|
||||
type: 'button',
|
||||
btnName: '查询',
|
||||
name: 'search',
|
||||
color: 'primary',
|
||||
},
|
||||
// {
|
||||
// type: 'button',
|
||||
// btnName: '重置',
|
||||
// name: 'reset',
|
||||
// },
|
||||
{
|
||||
type: 'separate',
|
||||
},
|
||||
// {
|
||||
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||
// ? 'button'
|
||||
// : '',
|
||||
// btnName: '新增',
|
||||
// name: 'add',
|
||||
// plain: true,
|
||||
// color: 'success',
|
||||
// },
|
||||
{
|
||||
type: this.$auth.hasPermi('monitoring:translucent:export')
|
||||
? 'button'
|
||||
: '',
|
||||
btnName: '导出',
|
||||
name: 'export',
|
||||
color: 'warning',
|
||||
},
|
||||
],
|
||||
// 表单配置
|
||||
// formRows: [
|
||||
// [
|
||||
// {
|
||||
// input: true,
|
||||
// label: '检测类型名称',
|
||||
// prop: 'name',
|
||||
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||
// // bind: {
|
||||
// // disabled: true, // some condition, like detail mode...
|
||||
// // }
|
||||
// },
|
||||
// ],
|
||||
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||
// ],
|
||||
// 是否显示弹出层
|
||||
open: false,
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
lineId: undefined,
|
||||
factoryId: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
},
|
||||
// 表单参数
|
||||
form: {},
|
||||
};
|
||||
},
|
||||
// watch: {
|
||||
// form: {
|
||||
// handler: (val) => {
|
||||
// console.log('form changed', val);
|
||||
// },
|
||||
// deep: true
|
||||
// },
|
||||
// },
|
||||
created() {
|
||||
this.getList();
|
||||
this.getDict()
|
||||
},
|
||||
methods: {
|
||||
getDict() {
|
||||
getPdList().then(res => {
|
||||
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||
});
|
||||
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||
});
|
||||
},
|
||||
/** base table related */
|
||||
handleTableBtnClick({ data, type }) {
|
||||
switch (type) {
|
||||
case 'edit':
|
||||
this.handleUpdate(data);
|
||||
break;
|
||||
case 'delete':
|
||||
this.handleDelete(data);
|
||||
break;
|
||||
}
|
||||
},
|
||||
/** search bar related */
|
||||
handleSearchBarBtnClick(btn) {
|
||||
console.log('btn',btn);
|
||||
|
||||
// const keys = ['name'];
|
||||
switch (btn.btnName) {
|
||||
case 'search':
|
||||
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||
// keys.forEach((key) => {
|
||||
// this.queryParams[key] = btn[key] || null;
|
||||
// });
|
||||
this.getList();
|
||||
break;
|
||||
case 'add':
|
||||
this.handleAdd();
|
||||
break;
|
||||
case 'export':
|
||||
this.handleExport();
|
||||
break;
|
||||
case 'reset':
|
||||
this.$refs['search-bar'].resetForm();
|
||||
this.resetQuery();
|
||||
break;
|
||||
}
|
||||
},
|
||||
/** 查询列表 */
|
||||
getList() {
|
||||
this.loading = true;
|
||||
// 执行查询
|
||||
getTranslucentPage(this.queryParams).then((res) => {
|
||||
this.list = res.data.list ? res.data.list.map((item) => {
|
||||
const startTime = item.startTime ? moment(item.startTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
||||
const endTime = item.endTime ? moment(item.endTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
||||
|
||||
// 拼接开始时间和结束时间,中间用“至”连接
|
||||
const timeVal = startTime && endTime ? `${startTime} 至 ${endTime}` : '';
|
||||
|
||||
return {
|
||||
...item,
|
||||
timeVal: timeVal
|
||||
};
|
||||
}) :[]
|
||||
this.total = res.data.total;
|
||||
this.loading = false;
|
||||
});
|
||||
},
|
||||
/** 表单重置 */
|
||||
// reset() {
|
||||
// this.form = {
|
||||
// id: undefined,
|
||||
// name: undefined,
|
||||
// code: undefined,
|
||||
// remark: undefined,
|
||||
// };
|
||||
// this.resetForm('form');
|
||||
// },
|
||||
/** 新增按钮操作 */
|
||||
// handleAdd() {
|
||||
// this.reset();
|
||||
// this.open = true;
|
||||
// this.title = '添加质量检测类型基础';
|
||||
// },
|
||||
/** 修改按钮操作 */
|
||||
// handleUpdate(row) {
|
||||
// this.reset();
|
||||
// const id = row.id;
|
||||
// getQualityInspectionType(id).then((response) => {
|
||||
// this.form = response.data;
|
||||
// this.open = true;
|
||||
// this.title = '修改质量检测类型基础';
|
||||
// });
|
||||
// },
|
||||
/** 提交按钮 */
|
||||
// submitForm() {
|
||||
// // console.log('this.$refs.form', this.$refs.form);
|
||||
// // return;
|
||||
// this.$refs['form'].validate((valid) => {
|
||||
// if (!valid) {
|
||||
// return;
|
||||
// }
|
||||
// console.log('final form', JSON.stringify(this.form));
|
||||
// // 修改的提交
|
||||
// if (this.form.id != null) {
|
||||
// updateQualityInspectionType(this.form).then((response) => {
|
||||
// this.$modal.msgSuccess('修改成功');
|
||||
// this.open = false;
|
||||
// this.getList();
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// // 添加的提交
|
||||
// createQualityInspectionType(this.form).then((response) => {
|
||||
// this.$modal.msgSuccess('新增成功');
|
||||
// this.open = false;
|
||||
// this.getList();
|
||||
// });
|
||||
// });
|
||||
// },
|
||||
handleExport() {
|
||||
// 处理查询参数
|
||||
let params = { ...this.queryParams };
|
||||
// params.pageNo = undefined;
|
||||
// params.pageSize = undefined;
|
||||
this.$modal
|
||||
.confirm('是否确认导出透光率检测?')
|
||||
.then(() => {
|
||||
this.exportLoading = true;
|
||||
return exportTranslucent(params);
|
||||
})
|
||||
.then((response) => {
|
||||
this.$download.excel(response, '透光率检测.xls');
|
||||
this.exportLoading = false;
|
||||
})
|
||||
.catch(() => { });
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
Reference in New Issue
Block a user