yudao-dev/src/views/produce/workOrder/detail.vue
2024-12-27 15:38:14 +08:00

774 lines
18 KiB
Vue

<!--
* @Author: zwq
* @Date: 2021-11-18 14:16:25
* @LastEditors: zwq
* @LastEditTime: 2024-12-27 15:34:28
* @Description:
-->
<template>
<div
class="status-timegraph-container"
style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
<el-row
v-show="workOrderButton.length !== 0"
class=""
style="margin-bottom: 4px; border-radius: 8px">
<workOrderNav
:id-list="workOrderButton"
@getWorkOrderId="getId"></workOrderNav>
</el-row>
<el-row
class=""
style="
height: 1px;
flex: 0.3;
margin-bottom: 12px;
background: #fff;
padding: 16px;
border-radius: 8px;
display: flex;
flex-direction: column;
">
<div class="content">
<div>
<h1 class="orderTitle">工单编码:{{ dataForm.code }}</h1>
<el-button
type="primary"
plain
style="position: absolute; right: 16px; top: 5px"
v-show="workOrderButton.length === 0"
@click="goWorkOrderList()">
<svg-icon icon-class="return" />
返回
</el-button>
</div>
<small-title style="margin: 16px 0" size="sm" :no-padding="true">
基本信息
</small-title>
<div class="formContent">
<el-row :gutter="20">
<el-col :span="4">
<p class="title">工单名称</p>
<p class="text">{{ dataForm.name }}</p>
</el-col>
<el-col :span="4">
<p class="title">工单来源</p>
<p class="text">
{{
dataForm.triggerOrigin === 1
? 'MES-手动'
: dataForm.triggerOrigin === 2
? 'MES-订单下发'
: dataForm.triggerOrigin === 3
? 'ERP'
: ''
}}
</p>
</el-col>
<el-col :span="4">
<p class="title">所属订单</p>
<p
class="text"
style="
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
"
:title="orderList.map((item) => item.orderName).join(', ')">
{{ orderList.map((item) => item.orderName).join(', ') }}
</p>
</el-col>
<el-col :span="4">
<p class="title">产品名称</p>
<p class="text">{{ dataForm.productName }}</p>
</el-col>
<el-col :span="4">
<p class="title">规 格</p>
<p class="text">{{ dataForm.specifications }}</p>
</el-col>
<el-col :span="4">
<p class="title">计划生产数量</p>
<p class="text">{{ dataForm.planQuantity }}</p>
</el-col>
<el-col :span="4">
<p class="title">预计用时(小时)</p>
<p class="text">{{ dataForm.remainingTime }}</p>
</el-col>
<el-col :span="4">
<p class="title">计划投入数量</p>
<p class="text">{{ dataForm.planAssignQuantity }}</p>
</el-col>
<el-col :span="4">
<p class="title">优先级</p>
<p class="text">{{ fitlerP(dataForm.priority) }}</p>
</el-col>
<el-col :span="4">
<p class="title">负责人</p>
<p class="text">{{ dataForm.workers }}</p>
</el-col>
<el-col :span="4">
<p class="title">关联产线</p>
<p class="text">
<span
v-for="(item, index) in dataForm.productLineIds"
:key="index"
style="margin-right: 10px">
{{ item.lineName }}
</span>
</p>
</el-col>
<el-col :span="4">
<p class="title">物料计算方式</p>
<p class="text">
{{
dataForm.materialMethod === 1
? '产品基础'
: dataForm.materialMethod === 2
? '工艺扩展'
: ''
}}
</p>
</el-col>
<el-col :span="4">
<p class="title">关联工艺</p>
<p class="text">
<span
v-for="(item, index) in dataForm.productLineIds"
:key="index"
style="margin-right: 10px">
{{ item.processFlowName }}
</span>
</p>
</el-col>
</el-row>
</div>
</div>
</el-row>
<el-row
class=""
style="
height: 1px;
flex: 1;
margin-bottom: 12px;
padding: 16px;
background: #fff;
border-radius: 8px;
display: flex;
flex-direction: column;
">
<el-tabs v-model="activeName" @tab-click="switchTab">
<el-tab-pane label="生产信息" name="produce">
<div class="formContent">
<el-row :gutter="20">
<el-col :span="4">
<p class="title">工单创建时间</p>
<p class="text">{{ parseTime(dataForm.createTime) }}</p>
</el-col>
<el-col :span="4">
<p class="title">计划开始时间</p>
<p class="text">{{ parseTime(dataForm.planStartTime) }}</p>
</el-col>
<el-col :span="4">
<p class="title">计划完成时间</p>
<p class="text">{{ parseTime(dataForm.planFinishTime) }}</p>
</el-col>
<el-col :span="4">
<p class="title">预计结束时间</p>
<p class="text">{{ parseTime(dataForm.expectedFinishTime) }}</p>
</el-col>
<el-col :span="4">
<p class="title">实际开始时间</p>
<p class="text">{{ parseTime(dataForm.startProduceTime) }}</p>
</el-col>
<el-col :span="4">
<p class="title">实际完成时间</p>
<p class="text">{{ parseTime(dataForm.finishProduceTime) }}</p>
</el-col>
<el-col :span="4">
<p class="title">工单状态</p>
<p class="text">{{ fitlerS(dataForm.status) }}</p>
</el-col>
<el-col :span="4">
<p class="title">实际投入数量</p>
<p class="text">{{ dataForm.assignQuantity }}</p>
</el-col>
<el-col :span="4">
<p class="title">实际生产数量</p>
<p class="text">{{ dataForm.actualQuantity }}</p>
</el-col>
<el-col :span="4">
<p class="title">废片数量</p>
<p class="text">{{ dataForm.nokQuantity }}</p>
</el-col>
<el-col :span="4">
<p class="title">检测瑕疵数</p>
<p class="text">{{ dataForm.unpassCheckNum }}</p>
</el-col>
</el-row>
</div>
</el-tab-pane>
<el-tab-pane label="订单信息" name="order">
<base-table
:max-height="tableH"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="orderList">
<method-btn
v-if="!isdetail"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
</el-tab-pane>
<el-tab-pane label="预计用料" name="material">
<base-table
:max-height="tableH"
:table-props="tableProps1"
:page="listQuery1.pageNo"
:limit="listQuery1.pageSize"
:table-data="materialList" />
</el-tab-pane>
<el-tab-pane label="质量信息" name="quality">
<span style="font-size: 14px;">该工单未通过检测数合计:{{ allSumScrap }}</span>
<base-table
:max-height="tableH"
:table-props="tablePropsQuality"
:table-data="qualityList"
:page="1"
:limit="10" />
</el-tab-pane>
<el-tab-pane label="能源信息" name="energy">
<div class="toggleTabBox">
<div
:class="{ active: activeModule === 'dataList' }"
@click="toggleTab('dataList')">
数据列表
</div>
<div
:class="{ active: activeModule === 'barChart' }"
@click="toggleTab('barChart')">
柱状图
</div>
</div>
<div>
<div v-show="activeModule === 'dataList'">
<!-- 表格 -->
<base-table
:max-height="tableH"
:table-props="tablePropsEnergy"
:page="listQueryEnergy.pageNo"
:limit="listQueryEnergy.pageSize"
:table-data="energyList" />
</div>
<!-- 图形 -->
<div v-show="activeModule === 'barChart'">
<bar-chart ref="orderEnergyChart" :chartData="chartData" />
</div>
</div>
</el-tab-pane>
</el-tabs>
</el-row>
<!-- 对话框(添加 / 修改) -->
<!-- <base-dialog dialogTitle="添加设备" :dialogVisible="open" width="500px" @close="open = false" @cancel="open = false"
@confirm="submitForm">
<el-select v-if="open" style="width: 100%" filterable clearable v-model="queryParams.equipmentId"
placeholder="请选择一个设备">
<el-option v-for="eq in eqList" :key="eq.id" :value="eq.id" :label="eq.name"></el-option>
</el-select>
</base-dialog> -->
</div>
</template>
<script>
// import basicAdd from '../../core/mixins/basic-add';
import {
getCoreWO,
getMaterialBomPage,
getConOrderList,
getCoreWOListById,
getMaterialCostWorkOrder,
} from '@/api/base/coreWorkOrder';
import tableHeightMixin from '@/mixins/tableHeightMixin';
import { getOrderEnergyData } from '@/api/monitoring/orderEnergy';
// import { orderList } from "@/api/base/orderManage";
import { getStatisticalDataPage } from '@/api/monitoring/statisticalData';
import { getProcessFlowList } from '@/api/base/orderManage';
import SmallTitle from './SmallTitle';
import { publicFormatter } from '@/utils/dict';
import { parseTime } from '@/utils/ruoyi';
import workOrderNav from './workOrderNav.vue';
import BarChart from './barChart';
const tableBtn = [
{
type: 'edit',
btnName: '编辑',
},
{
type: 'delete',
btnName: '删除',
},
];
const tableProps = [
{
prop: 'orderName',
label: '订单名称',
},
{
prop: 'orderCode',
label: '订单编码',
},
{
prop: 'planAssignmentQuantity',
label: '计划分配数量',
},
{
prop: 'actualAssignmentQuantity',
label: '实际分配数量',
},
];
const tableProps1 = [
{
prop: 'materialName',
label: '物料名称',
},
{
prop: 'unit',
label: '单位',
filter: publicFormatter('unit_dict'),
},
{
prop: 'remainingNum',
label: '剩余生产预计消耗',
},
];
const tablePropsEnergy = [
{
prop: 'objName',
label: '对象名称',
},
{
prop: 'objCode',
label: '对象编码',
// filter: publicFormatter('unit_dict')
},
{
prop: 'energyType',
label: '能源类型',
// filter: publicFormatter('unit_dict')
},
{
prop: 'startNum',
label: '工单开始值',
// filter: publicFormatter('unit_dict')
},
{
prop: 'endNum',
label: '工单结束值/当前值',
},
{
prop: 'useNum',
label: '使用量',
},
];
export default {
mixins: [tableHeightMixin],
components: { SmallTitle, workOrderNav, BarChart },
computed: {
tablePropsQuality() {
return [
// {
// // width: 128,
// prop: 'workOrderName',
// label: '工单名称',
// },
// {
// // width: 128,
// prop: 'productionName',
// label: '产品',
// },
{
// width: 160,
prop: 'inspectionContent',
label: '检测内容',
},
...this.dynamicProps,
{
// width: 128,
prop: 'sumScrap',
label: '未通过检测总数',
},
{
// width: 128,
prop: 'scrapRatio',
label: '比例(%)',
// subcomponent: {
// name: 'TextOnly',
// props: {
// injectData: {
// type: Object,
// default: () => ({}),
// },
// },
// data() {
// return {
// text: '比例',
// };
// },
// methods: {
// handleEmit(payload) {
// console.log('handleEmit', payload);
// },
// },
// render(h) {
// return h('el-button', { props: { type: 'text' } }, this.text);
// },
// },
},
];
},
},
data() {
return {
tableBtn,
tableProps,
heightNum: 236,
tablePropsEnergy,
tableProps1,
activeModule: 'dataList',
workOrderId: undefined,
addOrUpdateVisible: false,
urlOptions: {
infoURL: getCoreWO,
},
allSumScrap: 0,
listQuery: {
pageSize: 10,
pageNo: 1,
total: 0,
},
listQueryEnergy: {
pageSize: 10,
pageNo: 1,
total: 0,
},
activeName: 'produce',
listQuery1: {
pageSize: 10,
pageNo: 1,
total: 0,
},
dataForm: {},
orderList: [],
materialList: [],
energyList: [],
qualityList: [],
chartData: [],
dynamicProps: [],
// orderArray: [],
visible: false,
isdetail: false,
workOrderButton: [],
processFlowList: [],
};
},
watch: {
workOrderId(newValue, oldValue) {
this.activeName = 'produce';
this.init(newValue);
this.dataForm.id = newValue;
},
},
created() {
this.getDict();
},
mounted() {
if (
this.$route.query.woIdString &&
this.$route.query.woIdString !== 'undefined'
) {
const idList = this.$route.query.woIdString.split(',');
console.log(idList);
getCoreWOListById(idList).then((res) => {
this.workOrderButton = res.data.map((work) => {
return {
id: work.id,
name: work.name,
};
});
console.log('this.workOrderButton======', this.workOrderButton);
this.init(this.workOrderButton[0].id, true);
});
} else {
this.init(this.$route.query.id, true);
}
},
methods: {
goWorkOrderList() {
this.$router.go(-1);
},
getId(val) {
this.workOrderId = val;
},
async switchTab(val) {
if (this.activeName === 'order') {
getConOrderList({
workOrderId: this.dataForm.id,
}).then((response) => {
this.orderList = response.data;
// this.listQuery.total = response.data.total;
});
} else if (this.activeName === 'material') {
getMaterialCostWorkOrder({
id: this.dataForm.id,
}).then((response) => {
this.materialList = response.data;
// this.listQuery.total = response.data.total;
});
} else if (this.activeName === 'energy') {
getOrderEnergyData({
workOrderId: this.dataForm.id,
}).then((response) => {
this.energyList = response.data;
this.chartData = response.data;
// this.listQuery.total = response.data.total;
});
} else if (this.activeName === 'quality') {
this.allSumScrap = 0
const {
data: { data, otherList, otherMap, nameData },
} = await getStatisticalDataPage({
workOrderId:this.dataForm.id
});
// console.log(this.queryParams);
this.dynamicProps = this.filterNameData(nameData);
this.qualityList = this.filterData(data);
}
},
getDict() {
// 工艺
getProcessFlowList().then((res) => {
this.processFlowList = res.data || [];
});
},
filterNameData(nameData) {
const ndSet = new Set();
nameData.forEach((nd) => {
ndSet.add(nd.name);
});
return Array.from(ndSet.values())
.sort()
.map((name) => ({
prop: name,
label: name,
}));
},
filterData(data) {
return data.map((item) => {
const { data: innerData } = item;
const keyValuePairs = {};
innerData.map((d) => {
keyValuePairs[d.dynamicName] = d.dynamicValue;
});
this.allSumScrap +=item.sumScrap
return {
inspectionContent: item.inspectionContent,
...keyValuePairs,
sumScrap: item.sumScrap,
productionName: item.productionName,
workOrderId: item.workOrderId,
workOrderName: item.workOrderName,
scrapRatio: item.scrapRatio,
};
});
},
fitlerP(val) {
if (val) {
if (val === 1) {
return '低';
} else if (val === 2) {
return '正常';
} else {
return '高';
}
}
},
fitlerS(val) {
if (val) {
if (val === 1) {
return '等待';
} else if (val === 2) {
return '激活';
} else if (val === 3) {
return '暂停';
} else if (val === 4) {
return '完成';
} else {
return '作废';
}
}
},
initData() {
this.orderList.splice(0);
this.materialList.splice(0);
},
handleClick(raw) {
if (raw.type === 'delete') {
this.$confirm(
`确定对${
raw.data.attrName
? '[名称=' + raw.data.attrName + ']'
: '[序号=' + raw.data._pageIndex + ']'
}进行删除操作?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteCoreProductAttr(raw.data.id).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getList();
},
});
});
})
.catch(() => {});
} else {
this.addNew(raw.data.id);
}
},
toggleTab(val) {
this.activeModule = val;
if (this.activeModule === 'barChart') {
this.$nextTick((res) => {
this.$refs.orderEnergyChart.getChart();
});
}
},
getList() {
// 获取订单列表
// 获取预使用原料列表
// if (this.dataForm.planProductId) {
// getMaterialBomPage({
// productId: this.dataForm.planProductId,
// }).then((response) => {
// this.materialList = response.data;
// // this.listQuery.total = response.data.length;
// });
// }
// 获取订单相关信息
getConOrderList({
workOrderId: this.dataForm.id,
}).then((response) => {
this.orderList = response.data;
// this.listQuery.total = response.data.total;
});
},
init(id, isdetail) {
this.initData();
this.isdetail = isdetail || false;
this.dataForm.id = id || undefined;
this.visible = true;
this.$nextTick(() => {
if (this.dataForm.id) {
// 获取工单详情
this.urlOptions.infoURL(id).then((response) => {
this.dataForm = response.data;
// 工艺名称
if (this.dataForm.productLineIds.length>0) {
console.log(this.processFlowList)
this.dataForm.productLineIds.forEach(item=>{
this.processFlowList.filter(item1 => {
if (item1.id === item.processId) {
item.processFlowName = item1.name
}
});
})
}
// 获取订单列表和用料列表
this.getList();
});
} else {
if (this.urlOptions.isGetCode) {
this.getCode();
}
}
});
},
goEdit() {
this.isdetail = false;
},
// 新增 / 修改
addNew(id) {
this.addOrUpdateVisible = true;
this.$nextTick(() => {
this.$refs.addOrUpdate.init(id);
});
},
},
};
</script>
<style lang="scss" scoped>
.orderTitle {
font-size: 16px;
font-weight: bold;
}
.formContent {
font-size: 14px;
.title {
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
margin: 0px;
}
.text {
height: 20px;
color: rgba(102, 102, 102, 0.75);
margin: 10px 0px;
}
}
.action_btn {
float: right;
margin: 5px 15px;
font-size: 14px;
}
.add {
color: #0b58ff;
}
.container {
/* background-color: #fff; */
border-radius: 8px;
padding: 16px 16px 0 16px;
margin: 8px 0 8px 0px;
}
.toggleTabBox {
display: inline-block;
div {
display: inline-block;
padding: 0 8px 4px;
color: rgba(102, 102, 102, 0.5);
border-bottom: 2px solid rgba(242, 244, 249, 1);
cursor: pointer;
}
.active {
color: rgba(0, 0, 0, 0.85);
border-bottom-color: #0b58ff;
}
}
</style>