refactor(bom): 重构BOM管理功能优化物料选择和订单维护流程

- 注释掉废弃的自动同步BOM接口定义
- 将物料编码输入框改为下拉选择支持模糊搜索
- 实现选择物料后自动填充物料名称、类别和工厂编号
- 新增PDA订单维护卡片支持按物料关键字查询工单
- 为工单信息页面添加物料选择器组件和相关校验规则
- 重构参数追溯页面为设备参数分析中心包含异常、趋势和切换三大模块
- 在物料信息页面增加导入功能支持Excel批量导入物料数据
- 统一工单维护权限检查并优化批量操作按钮布局
master
zangch@mesnac.com 2 weeks ago
parent bd059b7e7c
commit 28423e07f0

@ -11,8 +11,13 @@ export function listFactory(query) {
// 查询工厂下拉框列表 // 查询工厂下拉框列表
export function findFactoryList(query) { export function findFactoryList(query) {
return listAllFactory(query)
}
// 查询工厂全量列表(不分页)
export function listAllFactory(query) {
return request({ return request({
url: '/base/factory/findFactoryList', url: '/base/factory/all',
method: 'get', method: 'get',
params: query params: query
}) })

@ -9,6 +9,15 @@ export function listMaterialInfo(query) {
}) })
} }
// 查询全部物料信息列表
export function listAllMaterialInfo(query) {
return request({
url: '/base/materialInfo/all',
method: 'get',
params: query
})
}
// 查询物料信息详细 // 查询物料信息详细
export function getMaterialInfo(objId) { export function getMaterialInfo(objId) {
return request({ return request({

@ -44,7 +44,6 @@ export function releaseOrderPlan(data) {
}) })
} }
// 删除工单信息 // 删除工单信息
export function delOrderInfo(objId) { export function delOrderInfo(objId) {
return request({ return request({
@ -139,3 +138,21 @@ export function batchCompleteProduction(data) {
data: data data: data
}) })
} }
// PDA按物料关键字查询订单
export function listPdaOrdersByMaterial(keyword) {
return request({
url: '/dms/mobile/order/listByMaterial',
method: 'get',
params: { keyword }
})
}
// PDA维护订单状态与数量
export function updatePdaOrderStatusAndQty(data) {
return request({
url: '/dms/mobile/order/updateStatusAndQty',
method: 'post',
data: data
})
}

@ -10,14 +10,15 @@ export function listBaseBomInfo(query) {
} }
// 自动同步生产BOM // 自动同步生产BOM
export function addAutomaticSynchronizationBOM(query) { // 当前业务已经改为全部手动维护树形BOM这里注释掉历史同步接口定义避免前端继续调用。
return request({ // export function addAutomaticSynchronizationBOM(query) {
url: '/production/baseBomInfo/addAutomaticSynchronizationBOM', // return request({
method: 'get', // url: '/production/baseBomInfo/addAutomaticSynchronizationBOM',
params: query, // method: 'get',
timeout: 60000 // params: query,
}) // timeout: 60000
} // })
// }
// 查询生产BOM列表 // 查询生产BOM列表
export function listTreeBaseBomInfo(query) { export function listTreeBaseBomInfo(query) {
return request({ return request({

@ -128,6 +128,16 @@
v-hasPermi="['base:materialInfo:export']" v-hasPermi="['base:materialInfo:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<el-col :span="1.5">
<el-button
type="info"
plain
icon="el-icon-upload2"
size="mini"
@click="handleImport"
v-hasPermi="['base:materialInfo:add']"
>导入</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row> </el-row>
@ -305,6 +315,47 @@
<el-button @click="cancel"> </el-button> <el-button @click="cancel"> </el-button>
</div> </div>
</el-dialog> </el-dialog>
<el-dialog :title="upload.title" :visible.sync="upload.open" width="420px" append-to-body>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:data="{ plantCode: upload.plantCode }"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:on-error="handleFileError"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<div class="el-upload__tip" slot="tip">
<el-checkbox v-model="upload.updateSupport"></el-checkbox>
</div>
<div style="margin-top: 8px;">
<el-select v-model="upload.plantCode" placeholder="请选择所属工厂" size="mini" style="width: 220px;">
<el-option
v-for="item in factoryList"
:key="item.factoryCode"
:label="item.factoryName"
:value="item.factoryCode"
></el-option>
</el-select>
</div>
<div style="margin-top: 8px;">仅允许导入xlsxlsx格式文件</div>
<el-link type="primary" :underline="false" style="font-size:12px;vertical-align: baseline;" @click="importTemplate"></el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
@ -312,6 +363,7 @@
import { listMaterialInfo, getMaterialInfo, delMaterialInfo, addMaterialInfo, updateMaterialInfo } from "@/api/base/materialInfo"; import { listMaterialInfo, getMaterialInfo, delMaterialInfo, addMaterialInfo, updateMaterialInfo } from "@/api/base/materialInfo";
import { findFactoryList } from "@/api/base/factory"; import { findFactoryList } from "@/api/base/factory";
import { findProductLineList } from "@/api/base/productLine"; import { findProductLineList } from "@/api/base/productLine";
import { getToken } from "@/utils/auth";
export default { export default {
name: "MaterialInfo", name: "MaterialInfo",
@ -389,12 +441,26 @@ export default {
factoryList: [], factoryList: [],
// 线 // 线
productLineList: [], productLineList: [],
//
upload: {
open: false,
title: "",
isUploading: false,
updateSupport: false,
plantCode: null,
headers: { Authorization: "Bearer " + getToken() },
url: process.env.VUE_APP_BASE_API + "/base/materialInfo/importData"
}
}; };
}, },
created() { created() {
this.getList(); this.getList();
findFactoryList().then(response => { findFactoryList().then(response => {
this.factoryList = response.data; this.factoryList = response.data;
if (!this.upload.plantCode && this.factoryList.length > 0) {
const defaultFactory = this.factoryList.find(item => item.factoryCode === '2010') || this.factoryList[0];
this.upload.plantCode = defaultFactory.factoryCode;
}
}); });
findProductLineList().then(response => { findProductLineList().then(response => {
this.productLineList = response.data; this.productLineList = response.data;
@ -507,6 +573,46 @@ export default {
this.download('base/materialInfo/export', { this.download('base/materialInfo/export', {
...this.queryParams ...this.queryParams
}, `materialInfo_${new Date().getTime()}.xlsx`) }, `materialInfo_${new Date().getTime()}.xlsx`)
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "物料导入";
this.upload.open = true;
},
/** 下载模板 */
importTemplate() {
this.download('base/materialInfo/importTemplate', {}, `materialInfo_template_${new Date().getTime()}.xlsx`)
},
//
handleFileUploadProgress() {
this.upload.isUploading = true;
},
//
handleFileSuccess(response) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
if (response.code === 200) {
this.$alert("<div style='overflow:auto;overflow-x:hidden;max-height:70vh;padding:10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
this.getList();
} else {
this.$modal.msgError(response.msg || "导入失败");
}
},
//
handleFileError() {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$modal.msgError("文件上传失败,请重试");
},
//
submitFileForm() {
if (!this.upload.plantCode) {
this.$modal.msgWarning("请选择所属工厂");
return;
}
this.$refs.upload.submit();
} }
} }
}; };

@ -131,13 +131,26 @@
<el-input v-model="form.bomCode" placeholder="请输入BOM编号" /> <el-input v-model="form.bomCode" placeholder="请输入BOM编号" />
</el-form-item> </el-form-item>
<el-form-item label="物料编码" prop="materialCode"> <el-form-item label="物料编码" prop="materialCode">
<el-input v-model="form.materialCode" placeholder="请输入物料编码" /> <el-select
v-model="form.materialCode"
filterable
clearable
placeholder="请选择物料编码"
@change="handleMaterialChange"
>
<el-option
v-for="item in materialOptions"
:key="item.materialCode"
:label="item.materialCode + ' / ' + item.materialName"
:value="item.materialCode"
/>
</el-select>
</el-form-item> </el-form-item>
<el-form-item label="物料名称" prop="materialName"> <el-form-item label="物料名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入物料名称" /> <el-input v-model="form.materialName" placeholder="请选择物料后自动带出" disabled />
</el-form-item> </el-form-item>
<el-form-item label="物料类别" prop="materialType"> <el-form-item label="物料类别" prop="materialType">
<el-select v-model="form.materialType" placeholder="请选择物料类别"> <el-select v-model="form.materialType" placeholder="请选择物料类别" disabled>
<el-option <el-option
v-for="dict in dict.type.material_type" v-for="dict in dict.type.material_type"
:key="dict.value" :key="dict.value"
@ -150,7 +163,7 @@
<el-input v-model="form.standardAmount" placeholder="请输入标准数量" /> <el-input v-model="form.standardAmount" placeholder="请输入标准数量" />
</el-form-item> </el-form-item>
<el-form-item label="工厂编号" prop="factoryCode"> <el-form-item label="工厂编号" prop="factoryCode">
<el-input v-model="form.factoryCode" placeholder="请输入工厂编号" /> <el-input v-model="form.factoryCode" placeholder="请选择物料后自动带出" disabled />
</el-form-item> </el-form-item>
<el-form-item label="排序" prop="sort"> <el-form-item label="排序" prop="sort">
<el-input v-model="form.sort" placeholder="请输入排序" /> <el-input v-model="form.sort" placeholder="请输入排序" />
@ -187,6 +200,7 @@ import {
updateOrderBomInfo, updateOrderBomInfo,
findOrderBomList findOrderBomList
} from '@/api/base/orderBomInfo' } from '@/api/base/orderBomInfo'
import { listAllMaterialInfo } from '@/api/base/materialInfo'
import Treeselect from "@riophae/vue-treeselect"; import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css"; import "@riophae/vue-treeselect/dist/vue-treeselect.css";
@ -206,6 +220,8 @@ export default {
orderBomInfoList: [], orderBomInfoList: [],
// BOM // BOM
orderBomInfoOptions: [], orderBomInfoOptions: [],
//
materialOptions: [],
// //
title: "", title: "",
// //
@ -242,7 +258,7 @@ export default {
}, },
created() { created() {
this.queryParams.ancestors = this.$route.params && this.$route.params.materialCode; this.queryParams.ancestors = this.$route.params && this.$route.params.materialCode;
console.log( this.queryParams.ancestors) this.loadMaterialOptions();
this.getList(); this.getList();
}, },
methods: { methods: {
@ -274,6 +290,30 @@ export default {
this.orderBomInfoOptions.push(data); this.orderBomInfoOptions.push(data);
}); });
}, },
/** 加载全部物料下拉数据 */
loadMaterialOptions() {
listAllMaterialInfo({ isFlag: 0 }).then(response => {
this.materialOptions = response.data || [];
});
},
/** 选择物料后自动回填展示字段 */
handleMaterialChange(materialCode) {
const selectedMaterial = this.materialOptions.find(item => item.materialCode === materialCode);
if (!selectedMaterial) {
this.form.materialName = null;
this.form.materialType = null;
this.form.factoryCode = null;
return;
}
//
this.form.materialName = selectedMaterial.materialName;
this.form.materialType = selectedMaterial.materialSubclass;
this.form.factoryCode = selectedMaterial.plantCode;
if (!this.form.bomCode) {
// BOMBOM
this.form.bomCode = selectedMaterial.materialCode;
}
},
// //
cancel() { cancel() {
this.open = false; this.open = false;
@ -345,6 +385,7 @@ export default {
} }
getOrderBomInfo(row.objId).then(response => { getOrderBomInfo(row.objId).then(response => {
this.form = response.data; this.form = response.data;
this.handleMaterialChange(this.form.materialCode);
this.open = true; this.open = true;
this.title = "修改订单BOM"; this.title = "修改订单BOM";
}); });

@ -1,7 +1,7 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<!-- 搜索表单 --> <!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" class="search-form"> <el-form ref="queryForm" :model="queryParams" size="small" :inline="true" class="search-form">
<el-form-item label="设备编号" prop="deviceCode"> <el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter.native="handleQuery" /> <el-input v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter.native="handleQuery" />
</el-form-item> </el-form-item>
@ -19,39 +19,96 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-card class="maintenance-card" shadow="never">
<div slot="header">
<span>PDA订单维护</span>
</div>
<!--
该区域用于模拟/承接PDA订单维护链路
1. 先按物料关键字查询候选订单
2. 再从下拉框中明确选中一条工单
3. 最后只维护执行状态与完工数量避免一次表单承载过多业务字段
-->
<el-form :model="pdaMaintainForm" size="small" :inline="true" label-width="80px">
<el-form-item label="物料关键字">
<el-input
v-model="pdaMaintainForm.materialKeyword"
placeholder="请输入物料编码或名称"
clearable
style="width: 220px"
@keyup.enter.native="handlePdaOrderSearch"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" :loading="pdaOrderLoading" @click="handlePdaOrderSearch"></el-button>
</el-form-item>
<el-form-item label="订单选择">
<el-select
v-model="pdaMaintainForm.objId"
placeholder="请先查询再选择订单"
filterable
clearable
style="width: 360px"
@change="handlePdaOrderChange"
>
<el-option
v-for="item in pdaOrderOptions"
:key="item.objId"
:label="buildPdaOrderOptionLabel(item)"
:value="item.objId"
/>
</el-select>
</el-form-item>
<el-form-item label="执行状态">
<el-select v-model="pdaMaintainForm.executionStatus" placeholder="请选择执行状态" clearable style="width: 140px">
<el-option label="待执行" value="PENDING" />
<el-option label="运行中" value="RUNNING" />
<el-option label="已完成" value="COMPLETED" />
<el-option label="已暂停" value="PAUSED" />
</el-select>
</el-form-item>
<el-form-item label="完工数量">
<el-input-number v-model="pdaMaintainForm.actualCompleteQty" :min="0" :precision="0" style="width: 140px" />
</el-form-item>
<el-form-item>
<el-button type="success" icon="el-icon-check" size="mini" :loading="pdaMaintainSubmitting" @click="submitPdaOrderMaintain"></el-button>
</el-form-item>
</el-form>
</el-card>
<!-- 批量操作按钮 --> <!-- 批量操作按钮 -->
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
v-hasPermi="['base:orderInfo:edit']"
type="primary" type="primary"
plain plain
icon="el-icon-video-play" icon="el-icon-video-play"
size="mini" size="mini"
:disabled="multiple" :disabled="multiple"
@click="handleBatchStart" @click="handleBatchStart"
v-hasPermi="['base:orderInfo:edit']"
>批量开始生产</el-button> >批量开始生产</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
v-hasPermi="['base:orderInfo:edit']"
type="warning" type="warning"
plain plain
icon="el-icon-edit" icon="el-icon-edit"
size="mini" size="mini"
:disabled="multiple" :disabled="multiple"
@click="handleBatchUpdateQty" @click="handleBatchUpdateQty"
v-hasPermi="['base:orderInfo:edit']"
>批量更新数量</el-button> >批量更新数量</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <el-col :span="1.5">
<el-button <el-button
v-hasPermi="['base:orderInfo:edit']"
type="success" type="success"
plain plain
icon="el-icon-check" icon="el-icon-check"
size="mini" size="mini"
:disabled="multiple" :disabled="multiple"
@click="handleBatchComplete" @click="handleBatchComplete"
v-hasPermi="['base:orderInfo:edit']"
>批量完工提报</el-button> >批量完工提报</el-button>
</el-col> </el-col>
</el-row> </el-row>
@ -263,15 +320,18 @@
</template> </template>
<script> <script>
import { listOrderInfo, startProduction, completeProduction, updateQuantity, batchStartProduction, batchUpdateQuantity, batchCompleteProduction } from "@/api/base/orderInfo"; import { listOrderInfo, startProduction, completeProduction, updateQuantity, batchStartProduction, batchUpdateQuantity, batchCompleteProduction, listPdaOrdersByMaterial, updatePdaOrderStatusAndQty } from '@/api/base/orderInfo'
export default { export default {
name: "OrderExecution", name: 'OrderExecution',
data() { data() {
return { return {
loading: false, loading: false,
total: 0, total: 0,
orderList: [], orderList: [],
pdaOrderOptions: [],
pdaOrderLoading: false,
pdaMaintainSubmitting: false,
selectedIds: [], selectedIds: [],
multiple: true, multiple: true,
queryParams: { queryParams: {
@ -315,68 +375,138 @@ export default {
completeQty: 0, completeQty: 0,
defectQty: 0 defectQty: 0
}, },
detailOrder: {} detailOrder: {},
}; pdaMaintainForm: {
materialKeyword: '',
objId: null,
orderCode: '',
executionStatus: 'PENDING',
actualCompleteQty: 0
}
}
}, },
created() { created() {
this.getList(); this.getList()
}, },
methods: { methods: {
getList() { getList() {
this.loading = true; this.loading = true
listOrderInfo(this.queryParams) listOrderInfo(this.queryParams)
.then(response => { .then(response => {
const data = response && response.data ? response.data : response; const data = response && response.data ? response.data : response
if (Array.isArray(data)) { if (Array.isArray(data)) {
this.orderList = data; this.orderList = data
this.total = data.length; this.total = data.length
} else { } else {
this.orderList = (data && data.rows) ? data.rows : []; this.orderList = (data && data.rows) ? data.rows : []
this.total = (data && data.total) ? data.total : this.orderList.length; this.total = (data && data.total) ? data.total : this.orderList.length
} }
}) })
.catch(() => { .catch(() => {
this.orderList = []; this.orderList = []
this.total = 0; this.total = 0
}) })
.finally(() => { .finally(() => {
this.loading = false; this.loading = false
}); })
}, },
handleQuery() { handleQuery() {
this.queryParams.pageNum = 1; this.queryParams.pageNum = 1
this.getList(); this.getList()
}, },
resetQuery() { resetQuery() {
this.resetForm("queryForm"); this.resetForm('queryForm')
this.handleQuery(); this.handleQuery()
}, },
getStatusType(status) { getStatusType(status) {
const map = { 'RUNNING': 'warning', 'COMPLETED': 'success', 'PAUSED': 'info', 'PENDING': '' }; const map = { 'RUNNING': 'warning', 'COMPLETED': 'success', 'PAUSED': 'info', 'PENDING': '' }
return map[status] || ''; return map[status] || ''
}, },
getStatusText(status) { getStatusText(status) {
const map = { 'RUNNING': '运行中', 'COMPLETED': '已完成', 'PAUSED': '已暂停', 'PENDING': '待执行' }; const map = { 'RUNNING': '运行中', 'COMPLETED': '已完成', 'PAUSED': '已暂停', 'PENDING': '待执行' }
return map[status] || '待执行'; return map[status] || '待执行'
},
buildPdaOrderOptionLabel(row) {
//
return `${row.materialName || '-'} / ${row.orderCode || '-'} / 当前状态:${this.getStatusText(row.executionStatus)}`
},
handlePdaOrderSearch() {
const keyword = this.pdaMaintainForm.materialKeyword && this.pdaMaintainForm.materialKeyword.trim()
if (!keyword) {
this.$modal.msgWarning('请输入物料关键字')
return
}
this.pdaOrderLoading = true
listPdaOrdersByMaterial(keyword).then(response => {
const data = response && response.data ? response.data : response
this.pdaOrderOptions = Array.isArray(data) ? data : []
if (!this.pdaOrderOptions.length) {
this.$modal.msgWarning('未查询到关联工单')
this.pdaMaintainForm.objId = null
this.pdaMaintainForm.orderCode = ''
return
}
if (!this.pdaMaintainForm.objId && this.pdaOrderOptions.length === 1) {
// PDA
this.handlePdaOrderChange(this.pdaOrderOptions[0].objId)
}
}).finally(() => {
this.pdaOrderLoading = false
})
},
handlePdaOrderChange(objId) {
const current = this.pdaOrderOptions.find(item => item.objId === objId)
if (!current) {
this.pdaMaintainForm.orderCode = ''
return
}
//
this.pdaMaintainForm.orderCode = current.orderCode
this.pdaMaintainForm.executionStatus = current.executionStatus || 'PENDING'
this.pdaMaintainForm.actualCompleteQty = current.actualCompleteQty != null ? current.actualCompleteQty : (current.completeAmount || 0)
},
submitPdaOrderMaintain() {
if (!this.pdaMaintainForm.objId) {
this.$modal.msgWarning('请选择订单')
return
}
if (!this.pdaMaintainForm.executionStatus) {
this.$modal.msgWarning('请选择执行状态')
return
}
this.pdaMaintainSubmitting = true
updatePdaOrderStatusAndQty({
objId: this.pdaMaintainForm.objId,
orderCode: this.pdaMaintainForm.orderCode,
executionStatus: this.pdaMaintainForm.executionStatus,
actualCompleteQty: this.pdaMaintainForm.actualCompleteQty
}).then(() => {
//
this.$modal.msgSuccess('订单维护成功')
this.getList()
this.handlePdaOrderSearch()
}).finally(() => {
this.pdaMaintainSubmitting = false
})
}, },
handleStart(row) { handleStart(row) {
this.startForm = { this.startForm = {
orderCode: row.orderCode, orderCode: row.orderCode,
materialName: row.materialName, materialName: row.materialName,
operator: this.$store.state.user.name || '' operator: this.$store.state.user.name || ''
}; }
this.startDialogVisible = true; this.startDialogVisible = true
}, },
confirmStart() { confirmStart() {
if (!this.startForm.operator) { if (!this.startForm.operator) {
this.$modal.msgWarning("请输入操作员"); this.$modal.msgWarning('请输入操作员')
return; return
} }
startProduction(this.startForm.orderCode, this.startForm.operator).then(response => { startProduction(this.startForm.orderCode, this.startForm.operator).then(response => {
this.$modal.msgSuccess("开始生产成功"); this.$modal.msgSuccess('开始生产成功')
this.startDialogVisible = false; this.startDialogVisible = false
this.getList(); this.getList()
}); })
}, },
handleUpdateQty(row) { handleUpdateQty(row) {
this.updateForm = { this.updateForm = {
@ -384,15 +514,15 @@ export default {
planQty: row.orderAmount, planQty: row.orderAmount,
completeQty: row.actualCompleteQty || 0, completeQty: row.actualCompleteQty || 0,
defectQty: row.actualDefectQty || 0 defectQty: row.actualDefectQty || 0
}; }
this.updateQtyDialogVisible = true; this.updateQtyDialogVisible = true
}, },
confirmUpdateQty() { confirmUpdateQty() {
updateQuantity(this.updateForm.orderCode, this.updateForm.completeQty, this.updateForm.defectQty).then(response => { updateQuantity(this.updateForm.orderCode, this.updateForm.completeQty, this.updateForm.defectQty).then(response => {
this.$modal.msgSuccess("更新数量成功"); this.$modal.msgSuccess('更新数量成功')
this.updateQtyDialogVisible = false; this.updateQtyDialogVisible = false
this.getList(); this.getList()
}); })
}, },
handleComplete(row) { handleComplete(row) {
this.completeForm = { this.completeForm = {
@ -400,84 +530,84 @@ export default {
planQty: row.orderAmount, planQty: row.orderAmount,
completeQty: row.actualCompleteQty || 0, completeQty: row.actualCompleteQty || 0,
defectQty: row.actualDefectQty || 0 defectQty: row.actualDefectQty || 0
}; }
this.completeDialogVisible = true; this.completeDialogVisible = true
}, },
confirmComplete() { confirmComplete() {
this.$modal.confirm('确认完工提报?完工后工单状态将变为已完成').then(() => { this.$modal.confirm('确认完工提报?完工后工单状态将变为已完成').then(() => {
completeProduction(this.completeForm.orderCode, this.completeForm.completeQty, this.completeForm.defectQty).then(response => { completeProduction(this.completeForm.orderCode, this.completeForm.completeQty, this.completeForm.defectQty).then(response => {
this.$modal.msgSuccess("完工提报成功"); this.$modal.msgSuccess('完工提报成功')
this.completeDialogVisible = false; this.completeDialogVisible = false
this.getList(); this.getList()
}); })
}); })
}, },
handleDetail(row) { handleDetail(row) {
this.detailOrder = row; this.detailOrder = row
this.detailDialogVisible = true; this.detailDialogVisible = true
}, },
handleSelectionChange(selection) { handleSelectionChange(selection) {
this.selectedIds = selection.map(item => item.objId); this.selectedIds = selection.map(item => item.objId)
this.multiple = !selection.length; this.multiple = !selection.length
}, },
handleBatchStart() { handleBatchStart() {
if (this.selectedIds.length === 0) { if (this.selectedIds.length === 0) {
this.$modal.msgWarning("请至少选择一条工单"); this.$modal.msgWarning('请至少选择一条工单')
return; return
} }
this.batchStartForm = { this.batchStartForm = {
operator: this.$store.state.user.name || '' operator: this.$store.state.user.name || ''
}; }
this.batchStartDialogVisible = true; this.batchStartDialogVisible = true
}, },
confirmBatchStart() { confirmBatchStart() {
if (!this.batchStartForm.operator) { if (!this.batchStartForm.operator) {
this.$modal.msgWarning("请输入操作员"); this.$modal.msgWarning('请输入操作员')
return; return
} }
const data = { const data = {
objIds: this.selectedIds, objIds: this.selectedIds,
operator: this.batchStartForm.operator operator: this.batchStartForm.operator
}; }
batchStartProduction(data).then(response => { batchStartProduction(data).then(response => {
this.$modal.msgSuccess("批量开始生产成功"); this.$modal.msgSuccess('批量开始生产成功')
this.batchStartDialogVisible = false; this.batchStartDialogVisible = false
this.getList(); this.getList()
}); })
}, },
handleBatchUpdateQty() { handleBatchUpdateQty() {
if (this.selectedIds.length === 0) { if (this.selectedIds.length === 0) {
this.$modal.msgWarning("请至少选择一条工单"); this.$modal.msgWarning('请至少选择一条工单')
return; return
} }
this.batchUpdateForm = { this.batchUpdateForm = {
completeQty: 0, completeQty: 0,
defectQty: 0 defectQty: 0
}; }
this.batchUpdateQtyDialogVisible = true; this.batchUpdateQtyDialogVisible = true
}, },
confirmBatchUpdateQty() { confirmBatchUpdateQty() {
const data = { const data = {
objIds: this.selectedIds, objIds: this.selectedIds,
completeQty: this.batchUpdateForm.completeQty, completeQty: this.batchUpdateForm.completeQty,
defectQty: this.batchUpdateForm.defectQty defectQty: this.batchUpdateForm.defectQty
}; }
batchUpdateQuantity(data).then(response => { batchUpdateQuantity(data).then(response => {
this.$modal.msgSuccess("批量更新数量成功"); this.$modal.msgSuccess('批量更新数量成功')
this.batchUpdateQtyDialogVisible = false; this.batchUpdateQtyDialogVisible = false
this.getList(); this.getList()
}); })
}, },
handleBatchComplete() { handleBatchComplete() {
if (this.selectedIds.length === 0) { if (this.selectedIds.length === 0) {
this.$modal.msgWarning("请至少选择一条工单"); this.$modal.msgWarning('请至少选择一条工单')
return; return
} }
this.batchCompleteForm = { this.batchCompleteForm = {
completeQty: 0, completeQty: 0,
defectQty: 0 defectQty: 0
}; }
this.batchCompleteDialogVisible = true; this.batchCompleteDialogVisible = true
}, },
confirmBatchComplete() { confirmBatchComplete() {
this.$modal.confirm('确认批量完工提报?完工后工单状态将变为已完成').then(() => { this.$modal.confirm('确认批量完工提报?完工后工单状态将变为已完成').then(() => {
@ -485,20 +615,24 @@ export default {
objIds: this.selectedIds, objIds: this.selectedIds,
completeQty: this.batchCompleteForm.completeQty, completeQty: this.batchCompleteForm.completeQty,
defectQty: this.batchCompleteForm.defectQty defectQty: this.batchCompleteForm.defectQty
}; }
batchCompleteProduction(data).then(response => { batchCompleteProduction(data).then(response => {
this.$modal.msgSuccess("批量完工提报成功"); this.$modal.msgSuccess('批量完工提报成功')
this.batchCompleteDialogVisible = false; this.batchCompleteDialogVisible = false
this.getList(); this.getList()
}); })
}); })
} }
} }
}; }
</script> </script>
<style scoped> <style scoped>
.search-form { .search-form {
margin-bottom: 15px; margin-bottom: 15px;
} }
.maintenance-card {
margin-bottom: 15px;
}
</style> </style>

@ -249,7 +249,7 @@
/> />
<!-- 添加或修改工单信息对话框 --> <!-- 添加或修改工单信息对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body> <el-dialog :title="title" :visible.sync="open" width="620px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="120px"> <el-form ref="form" :model="form" :rules="rules" label-width="120px">
<el-form-item label="SAP计划编号" prop="orderCode"> <el-form-item label="SAP计划编号" prop="orderCode">
<el-input v-model="form.orderCode" placeholder="请输入SAP计划编号"/> <el-input v-model="form.orderCode" placeholder="请输入SAP计划编号"/>
@ -271,14 +271,16 @@
<el-input v-model="form.saleOrderLineNumber" placeholder="请输入销售订单行号"/> <el-input v-model="form.saleOrderLineNumber" placeholder="请输入销售订单行号"/>
</el-form-item> </el-form-item>
<el-form-item label="物料编码" prop="materialCode"> <el-form-item label="物料编码" prop="materialCode">
<el-input v-model="form.materialCode" placeholder="请输入物料编码"/> <el-input v-model="form.materialCode" placeholder="请选择物料编码" readonly>
<el-button slot="append" icon="el-icon-search" @click="openMaterialSelector"></el-button>
</el-input>
</el-form-item> </el-form-item>
<el-form-item label="物料名称" prop="materialName"> <el-form-item label="物料名称" prop="materialName">
<el-input v-model="form.materialName" placeholder="请输入物料名称"/> <el-input v-model="form.materialName" placeholder="请选择物料名称" readonly/>
</el-form-item>
<el-form-item label="物料组" prop="matkl">
<el-input v-model="form.matkl" placeholder="选择物料后自动带出" readonly/>
</el-form-item> </el-form-item>
<!-- <el-form-item label="物料组" prop="matkl">-->
<!-- <el-input v-model="form.matkl" placeholder="请输入物料组"/>-->
<!-- </el-form-item>-->
<el-form-item label="订单计划数量" prop="orderAmount"> <el-form-item label="订单计划数量" prop="orderAmount">
<el-input v-model="form.orderAmount" placeholder="请输入订单计划数量"/> <el-input v-model="form.orderAmount" placeholder="请输入订单计划数量"/>
</el-form-item> </el-form-item>
@ -370,6 +372,12 @@
</div> </div>
</el-dialog> </el-dialog>
<material-selector
:visible.sync="materialSelector.open"
:selected-material-code="form.materialCode"
@confirm="handleMaterialSelected"
/>
</div> </div>
</template> </template>
@ -384,9 +392,13 @@ import {
} from '@/api/base/orderInfo' } from '@/api/base/orderInfo'
import { findProductLineList } from '@/api/base/productLine' import { findProductLineList } from '@/api/base/productLine'
import { addSAPCalendar } from '@/api/production/calendarInfo' import { addSAPCalendar } from '@/api/production/calendarInfo'
import MaterialSelector from '@/components/MaterialSelector'
export default { export default {
name: 'OrderInfo', name: 'OrderInfo',
components: {
MaterialSelector
},
dicts: ['order_status', 'order_type', 'is_flag', 'is_release'], dicts: ['order_status', 'order_type', 'is_flag', 'is_release'],
data() { data() {
return { return {
@ -441,7 +453,20 @@ export default {
// //
form: {}, form: {},
// //
rules: {}, rules: {
orderCode: [
{ required: true, message: 'SAP计划编号不能为空', trigger: 'blur' }
],
workCenterCode: [
{ required: true, message: '请选择工作中心', trigger: 'change' }
],
materialCode: [
{ required: true, message: '请选择物料', trigger: 'change' }
],
orderAmount: [
{ required: true, message: '请输入订单计划数量', trigger: 'blur' }
]
},
columns: [ columns: [
{ key: 0, label: `主键标识`, visible: false }, { key: 0, label: `主键标识`, visible: false },
{ key: 1, label: `SAP计划编号`, visible: true }, { key: 1, label: `SAP计划编号`, visible: true },
@ -467,7 +492,10 @@ export default {
{ key: 21, label: `工作中心编号`, visible: true } { key: 21, label: `工作中心编号`, visible: true }
], ],
// 线 // 线
productLineList: [] productLineList: [],
materialSelector: {
open: false
}
} }
}, },
created() { created() {
@ -569,6 +597,17 @@ export default {
this.title = '修改工单信息' this.title = '修改工单信息'
}) })
}, },
openMaterialSelector() {
this.materialSelector.open = true
},
handleMaterialSelected(material) {
this.form.materialCode = material.materialCode
this.form.materialName = material.materialName
this.form.matkl = material.materialMatkl
if (this.$refs.form) {
this.$refs.form.clearValidate(['materialCode'])
}
},
/** 修改按钮操作 */ /** 修改按钮操作 */
ReplaceProductionLine(row) { ReplaceProductionLine(row) {
this.reset() this.reset()

@ -1,318 +1,89 @@
<template> <template>
<div class="app-container"> <div class="app-container trace-analysis-page">
<!-- 返回导航栏 -->
<div class="breadcrumb-nav"> <div class="breadcrumb-nav">
<el-page-header @back="goBack" content="参数追溯"> <el-page-header content="参数分析与追溯" @back="goBack">
<template slot="title"> <template slot="title">
<span style="cursor: pointer;" @click="goBack"></span> <span style="cursor: pointer;" @click="goBack"></span>
</template> </template>
</el-page-header> </el-page-header>
</div> </div>
<!-- 搜索表单 --> <el-card shadow="never" class="trace-card">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" class="search-form"> <div slot="header" class="trace-card-header">
<el-form-item label="设备" prop="deviceCode"> <span>设备参数分析中心</span>
<el-select v-model="queryParams.deviceCode" placeholder="请选择设备" clearable filterable style="width: 200px;"> <span class="trace-card-tip">围绕异常趋势和切换三类业务场景统一分析</span>
<el-option </div>
v-for="item in deviceList"
:key="item.deviceCode"
:label="item.deviceName || item.deviceCode"
:value="item.deviceCode"
>
<span style="float: left">{{ item.deviceName || item.deviceCode }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.deviceCode }}</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="参数" prop="paramCode">
<el-select v-model="queryParams.paramCode" placeholder="请选择参数(可选)" clearable filterable style="width: 200px;">
<el-option
v-for="item in paramList"
:key="item.paramCode"
:label="item.paramName || item.paramCode"
:value="item.paramCode"
/>
</el-select>
</el-form-item>
<el-form-item label="时间范围" prop="dateRange">
<el-date-picker
v-model="dateRange"
type="datetimerange"
range-separator="至"
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="yyyy-MM-dd HH:mm:ss"
:default-time="['00:00:00', '23:59:59']"
style="width: 360px;"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery"></el-button>
<el-button icon="el-icon-refresh" @click="resetQuery"></el-button>
<el-button type="warning" icon="el-icon-download" @click="handleExport" :loading="exportLoading">导出</el-button>
<el-button type="success" icon="el-icon-s-data" @click="handleSPC" :disabled="!queryParams.paramCode">SPC分析</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 --> <el-tabs v-model="activeTab" @tab-click="handleTabClick">
<el-table v-loading="loading" :data="traceList" border stripe> <el-tab-pane label="参数异常报表" name="anomaly">
<el-table-column label="设备编号" prop="deviceCode" width="120" /> <anomaly-report
<el-table-column label="参数编号" prop="paramCode" width="100" /> ref="anomalyReport"
<el-table-column label="参数名称" prop="paramName" min-width="180" show-overflow-tooltip /> :device-list="deviceList"
<el-table-column label="参数值" prop="paramValue" width="120" align="center"> :default-device-code="defaultDeviceCode"
<template slot-scope="scope">
<span class="param-value">{{ scope.row.paramValue }}</span>
</template>
</el-table-column>
<el-table-column label="采集时间" prop="collectTime" width="180">
<template slot-scope="scope">
{{ parseTime(scope.row.collectTime) }}
</template>
</el-table-column>
<el-table-column label="记录时间" prop="recordTime" width="180">
<template slot-scope="scope">
{{ parseTime(scope.row.recordTime) }}
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/> />
</el-tab-pane>
<!-- SPC分析对话框 --> <el-tab-pane label="参数趋势/SPC报表" name="spc">
<el-dialog title="SPC分析" :visible.sync="spcDialogVisible" width="800px" append-to-body> <spc-report
<div v-loading="spcLoading" class="spc-content"> ref="spcReport"
<div v-if="spcData" class="spc-result"> :device-list="deviceList"
<div class="spc-header"> :default-device-code="defaultDeviceCode"
<div class="spc-info"> />
<span><b>设备:</b> {{ spcData.deviceCode }}</span> </el-tab-pane>
<span><b>参数:</b> {{ spcData.paramName }}</span> <el-tab-pane label="模具/物料/产品切换追溯" name="switch">
<span><b>样本数:</b> {{ spcData.sampleSize }}</span> <switch-trace-report
</div> ref="switchTraceReport"
</div> :device-list="deviceList"
<el-divider /> :default-device-code="defaultDeviceCode"
<el-row :gutter="20"> />
<el-col :span="8"> </el-tab-pane>
<el-card shadow="hover" class="spc-card"> </el-tabs>
<div slot="header">统计指标</div>
<div class="spc-stat">
<div class="stat-item"><span class="label">均值 (X̄)</span><span class="value">{{ spcData.mean }}</span></div>
<div class="stat-item"><span class="label">标准差 (σ)</span><span class="value">{{ spcData.stdDev }}</span></div>
</div>
</el-card> </el-card>
</el-col>
<el-col :span="8">
<el-card shadow="hover" class="spc-card">
<div slot="header">控制限</div>
<div class="spc-stat">
<div class="stat-item"><span class="label">UCL (上控制限)</span><span class="value ucl">{{ spcData.ucl }}</span></div>
<div class="stat-item"><span class="label">CL (中心线)</span><span class="value">{{ spcData.cl }}</span></div>
<div class="stat-item"><span class="label">LCL (下控制限)</span><span class="value lcl">{{ spcData.lcl }}</span></div>
</div>
</el-card>
</el-col>
<el-col :span="8">
<el-card shadow="hover" class="spc-card">
<div slot="header">过程能力</div>
<div class="spc-stat">
<div class="stat-item"><span class="label">CPK</span><span :class="['value', 'cpk', getCPKClass(spcData.cpk)]">{{ spcData.cpk }}</span></div>
<div class="stat-item"><span class="label">USL (上规格限)</span><span class="value">{{ spcData.usl }}</span></div>
<div class="stat-item"><span class="label">LSL (下规格限)</span><span class="value">{{ spcData.lsl }}</span></div>
</div>
</el-card>
</el-col>
</el-row>
<el-divider />
<div class="cpk-legend">
<span class="legend-item cpk-good">CPK 1.33: 优秀</span>
<span class="legend-item cpk-ok">1.0 CPK < 1.33: 合格</span>
<span class="legend-item cpk-bad">CPK < 1.0: 需改进</span>
</div>
</div>
<div v-else class="no-data">
<i class="el-icon-warning-outline"></i>
<span>暂无SPC数据请确保查询条件正确</span>
</div>
</div>
<div slot="footer">
<el-button @click="spcDialogVisible = false">关闭</el-button>
</div>
</el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { getTraceList, getSPCData, getLatestVal } from "@/api/baseDeviceParamVal/val"; import { getDeviceLedgerList } from '@/api/base/deviceLedger'
import { getDeviceLedgerList } from "@/api/base/deviceLedger"; import AnomalyReport from './AnomalyReport.vue'
import SpcReport from './SpcReport.vue'
import SwitchTraceReport from './SwitchTrace.vue'
export default { export default {
name: "DeviceParamValTrace", name: 'DeviceParamTraceIndex',
components: {
AnomalyReport,
SpcReport,
SwitchTraceReport
},
data() { data() {
return { return {
loading: false, activeTab: 'anomaly',
exportLoading: false,
spcLoading: false,
spcDialogVisible: false,
total: 0,
traceList: [],
deviceList: [], deviceList: [],
paramList: [], defaultDeviceCode: ''
dateRange: [],
spcData: null,
queryParams: {
pageNum: 1,
pageSize: 20,
deviceCode: '',
paramCode: '',
startTime: '',
endTime: ''
} }
};
}, },
created() { created() {
this.loadDeviceList(); this.defaultDeviceCode = this.$route.query.deviceCode || ''
// this.loadDeviceList()
if (this.$route.query.deviceCode) {
this.queryParams.deviceCode = this.$route.query.deviceCode;
this.loadParamList(this.queryParams.deviceCode);
}
// 1
const now = new Date();
const oneHourAgo = new Date(now.getTime() - 60 * 60 * 1000);
this.dateRange = [this.formatDate(oneHourAgo), this.formatDate(now)];
},
watch: {
'queryParams.deviceCode'(val) {
if (val) {
this.loadParamList(val);
} else {
this.paramList = [];
this.queryParams.paramCode = '';
}
}
}, },
methods: { methods: {
formatDate(date) {
const y = date.getFullYear();
const m = (date.getMonth() + 1).toString().padStart(2, '0');
const d = date.getDate().toString().padStart(2, '0');
const h = date.getHours().toString().padStart(2, '0');
const i = date.getMinutes().toString().padStart(2, '0');
const s = date.getSeconds().toString().padStart(2, '0');
return `${y}-${m}-${d} ${h}:${i}:${s}`;
},
goBack() { goBack() {
this.$router.push('/device/Monitor/val'); this.$router.push('/device/Monitor/val')
}, },
loadDeviceList() { loadDeviceList() {
getDeviceLedgerList().then(response => { getDeviceLedgerList().then(response => {
this.deviceList = response.data || response.rows || []; this.deviceList = response.data || response.rows || []
}); })
}, },
loadParamList(deviceCode) { handleTabClick() {
getLatestVal({ deviceCode }).then(response => { // resizeECharts
const rows = response.data || response.rows || []; this.$nextTick(() => {
// if (this.activeTab === 'spc' && this.$refs.spcReport) {
const paramMap = {}; this.$refs.spcReport.handleTabActivated()
rows.forEach(item => {
if (!paramMap[item.paramCode]) {
paramMap[item.paramCode] = { paramCode: item.paramCode, paramName: item.paramName };
} }
}); })
this.paramList = Object.values(paramMap);
});
},
getList() {
if (!this.queryParams.deviceCode) {
this.$message.warning('请选择设备');
return;
}
if (!this.dateRange || this.dateRange.length !== 2) {
this.$message.warning('请选择时间范围');
return;
}
this.queryParams.startTime = this.dateRange[0];
this.queryParams.endTime = this.dateRange[1];
this.loading = true;
getTraceList(this.queryParams).then(response => {
this.traceList = response.rows || [];
this.total = response.total || 0;
this.loading = false;
}).catch(() => {
this.loading = false;
});
},
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
resetQuery() {
this.dateRange = [];
this.queryParams = {
pageNum: 1,
pageSize: 20,
deviceCode: '',
paramCode: '',
startTime: '',
endTime: ''
};
this.traceList = [];
this.total = 0;
},
handleExport() {
if (!this.queryParams.deviceCode || !this.dateRange || this.dateRange.length !== 2) {
this.$message.warning('请先设置查询条件');
return;
}
this.exportLoading = true;
const params = {
deviceCode: this.queryParams.deviceCode,
paramCode: this.queryParams.paramCode,
startTime: this.dateRange[0],
endTime: this.dateRange[1]
};
this.download('/baseDeviceParamVal/val/trace/export', params, `参数追溯_${new Date().getTime()}.xlsx`);
setTimeout(() => { this.exportLoading = false; }, 1000);
},
handleSPC() {
if (!this.queryParams.deviceCode || !this.queryParams.paramCode) {
this.$message.warning('请选择设备和参数');
return;
}
if (!this.dateRange || this.dateRange.length !== 2) {
this.$message.warning('请选择时间范围');
return;
}
this.spcDialogVisible = true;
this.spcLoading = true;
this.spcData = null;
getSPCData({
deviceCode: this.queryParams.deviceCode,
paramCode: this.queryParams.paramCode,
startTime: this.dateRange[0],
endTime: this.dateRange[1]
}).then(response => {
this.spcData = response.data;
this.spcLoading = false;
}).catch(() => {
this.spcLoading = false;
});
},
getCPKClass(cpk) {
if (cpk >= 1.33) return 'cpk-good';
if (cpk >= 1.0) return 'cpk-ok';
return 'cpk-bad';
} }
} }
}; }
</script> </script>
<style scoped> <style scoped>
@ -323,133 +94,21 @@ export default {
border-radius: 4px; border-radius: 4px;
} }
.search-form { .trace-card {
padding: 16px;
background: #fff;
border-radius: 4px; border-radius: 4px;
margin-bottom: 16px;
} }
.param-value { .trace-card-header {
font-weight: 600;
color: #1890ff;
}
.spc-content {
min-height: 200px;
}
.spc-header {
margin-bottom: 16px;
}
.spc-info {
display: flex;
gap: 24px;
font-size: 14px;
}
.spc-info b {
color: #666;
margin-right: 4px;
}
.spc-card {
height: 180px;
}
.spc-card .el-card__header {
padding: 10px 16px;
font-weight: 600;
background: #fafafa;
}
.spc-stat {
padding: 8px 0;
}
.stat-item {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 8px 0; font-size: 15px;
border-bottom: 1px solid #f0f0f0;
}
.stat-item:last-child {
border-bottom: none;
}
.stat-item .label {
color: #666;
font-size: 13px;
}
.stat-item .value {
font-weight: 600; font-weight: 600;
font-size: 16px;
color: #333;
} }
.stat-item .value.ucl { .trace-card-tip {
color: #f56c6c; font-size: 13px;
} color: #909399;
font-weight: 400;
.stat-item .value.lcl {
color: #67c23a;
}
.stat-item .value.cpk-good {
color: #67c23a;
}
.stat-item .value.cpk-ok {
color: #e6a23c;
}
.stat-item .value.cpk-bad {
color: #f56c6c;
}
.cpk-legend {
display: flex;
justify-content: center;
gap: 24px;
margin-top: 16px;
}
.legend-item {
padding: 4px 12px;
border-radius: 4px;
font-size: 12px;
}
.legend-item.cpk-good {
background: #f0f9eb;
color: #67c23a;
}
.legend-item.cpk-ok {
background: #fdf6ec;
color: #e6a23c;
}
.legend-item.cpk-bad {
background: #fef0f0;
color: #f56c6c;
}
.no-data {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 60px 20px;
color: #999;
}
.no-data i {
font-size: 48px;
margin-bottom: 12px;
} }
</style> </style>

@ -331,6 +331,7 @@ export default {
createTime: null, createTime: null,
updateBy: null, updateBy: null,
updateTime: null, updateTime: null,
productIds: [],
baseStationProjectList: [], baseStationProjectList: [],
}; };
this.resetForm("form"); this.resetForm("form");
@ -385,15 +386,16 @@ export default {
submitForm() { submitForm() {
this.$refs["form"].validate(valid => { this.$refs["form"].validate(valid => {
if (valid) { if (valid) {
const checkedProjectIds = this.getMenuAllCheckedKeys();
// null
this.form.productIds = Array.isArray(checkedProjectIds) ? checkedProjectIds : [];
if (this.form.maintStationId != null) { if (this.form.maintStationId != null) {
this.form.productIds = this.getMenuAllCheckedKeys();
updateStation(this.form).then(response => { updateStation(this.form).then(response => {
this.$modal.msgSuccess("修改成功"); this.$modal.msgSuccess("修改成功");
this.open = false; this.open = false;
this.getList(); this.getList();
}); });
} else { } else {
this.form.productIds = this.getMenuAllCheckedKeys();
addStation(this.form).then(response => { addStation(this.form).then(response => {
this.$modal.msgSuccess("新增成功"); this.$modal.msgSuccess("新增成功");
this.open = false; this.open = false;

@ -129,7 +129,6 @@
<el-table-column type="selection" width="55" align="center" /> <el-table-column type="selection" width="55" align="center" />
<!-- <el-table-column label="主键标识" align="center" prop="maintInstanceId" />--> <!-- <el-table-column label="主键标识" align="center" prop="maintInstanceId" />-->
<!-- <el-table-column label="保养计划ID,关联dms_plan_maint的plan_maint_id" align="center" prop="planMaintId" />--> <!-- <el-table-column label="保养计划ID,关联dms_plan_maint的plan_maint_id" align="center" prop="planMaintId" />-->
<!-- <el-table-column label="工单流程ID关联wf_process的wf_process_id" align="center" prop="wfProcessId" />-->
<el-table-column label="保养单号" align="center" prop="billsMaintCode" /> <el-table-column label="保养单号" align="center" prop="billsMaintCode" />
<el-table-column label="计划保养时间" align="center" prop="planBeginTime" width="180"> <el-table-column label="计划保养时间" align="center" prop="planBeginTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
@ -289,7 +288,6 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
planMaintId: null, planMaintId: null,
wfProcessId: null,
billsMaintCode: null, billsMaintCode: null,
planBeginTime: null, planBeginTime: null,
realBeginTime: null, realBeginTime: null,
@ -303,9 +301,6 @@ export default {
form: {}, form: {},
// //
rules: { rules: {
wfProcessId: [
{ required: true, message: "工单流程ID关联wf_process的wf_process_id不能为空", trigger: "blur" }
],
billsMaintCode: [ billsMaintCode: [
{ required: true, message: "保养单号不能为空", trigger: "blur" } { required: true, message: "保养单号不能为空", trigger: "blur" }
], ],
@ -359,7 +354,6 @@ export default {
this.form = { this.form = {
maintInstanceId: null, maintInstanceId: null,
planMaintId: null, planMaintId: null,
wfProcessId: null,
billsMaintCode: null, billsMaintCode: null,
planBeginTime: null, planBeginTime: null,
realBeginTime: null, realBeginTime: null,
@ -419,8 +413,6 @@ export default {
this.getList(); this.getList();
}); });
} else { } else {
this.form.wfProcessId = 103;
addDmsBillsMaintInstance(this.form).then(response => { addDmsBillsMaintInstance(this.form).then(response => {
this.$modal.msgSuccess("新增成功"); this.$modal.msgSuccess("新增成功");
this.open = false; this.open = false;

@ -8,11 +8,6 @@
<el-input v-model="this.dmsBillsMaintInstanceList[0].billsMaintCode" disabled /> <el-input v-model="this.dmsBillsMaintInstanceList[0].billsMaintCode" disabled />
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="8" :offset="2">-->
<!-- <el-form-item label="当前流程" >-->
<!-- <el-input v-model="this.dmsBillsMaintInstanceList[0].wfProcessId" disabled />-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="8" :offset="2"> <el-col :span="8" :offset="2">
<el-form-item label="工单状态" > <el-form-item label="工单状态" >
<el-input v-model="this.billsStatusCheck" disabled /> <el-input v-model="this.billsStatusCheck" disabled />
@ -257,7 +252,6 @@ export default {
pageNum: 1, pageNum: 1,
pageSize: 10, pageSize: 10,
maintInstanceId: null, maintInstanceId: null,
processActivityId: null,
maintLevel: null, maintLevel: null,
maintGroup: null, maintGroup: null,
maintSupervisor: null, maintSupervisor: null,
@ -381,7 +375,6 @@ export default {
this.form = { this.form = {
instanceActivityId: null, instanceActivityId: null,
maintInstanceId: null, maintInstanceId: null,
processActivityId: null,
maintLevel: null, maintLevel: null,
maintGroup: null, maintGroup: null,
maintSupervisor: null, maintSupervisor: null,

@ -76,15 +76,15 @@
v-hasPermi="['production:baseBomInfo:export']" v-hasPermi="['production:baseBomInfo:export']"
>导出</el-button> >导出</el-button>
</el-col> </el-col>
<el-col :span="1.5"> <!-- <el-col :span="1.5">-->
<el-button <!-- <el-button-->
type="primary" <!-- type="primary"-->
plain <!-- plain-->
icon="el-icon-plus" <!-- icon="el-icon-plus"-->
size="mini" <!-- size="mini"-->
@click="AutomaticSynchronizationBOM" <!-- @click="AutomaticSynchronizationBOM"-->
>自动同步生产BOM</el-button> <!-- >自动同步生产BOM</el-button>-->
</el-col> <!-- </el-col>-->
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row> </el-row>
@ -231,8 +231,8 @@ import {
getBaseBomInfo, getBaseBomInfo,
delBaseBomInfo, delBaseBomInfo,
addBaseBomInfo, addBaseBomInfo,
updateBaseBomInfo, updateBaseBomInfo
addAutomaticSynchronizationBOM // addAutomaticSynchronizationBOM
} from '@/api/production/baseBomInfo' } from '@/api/production/baseBomInfo'
import {findFactoryList} from "@//api/base/factory"; import {findFactoryList} from "@//api/base/factory";
import addBom from '@//views/base/orderBomInfo/addBom.vue'; import addBom from '@//views/base/orderBomInfo/addBom.vue';
@ -425,12 +425,13 @@ export default {
} }
}); });
}, },
AutomaticSynchronizationBOM(){ // AutomaticSynchronizationBOM(){
addAutomaticSynchronizationBOM(this.form).then(response => { // // BOM
this.$modal.msgSuccess('同步成功') // addAutomaticSynchronizationBOM(this.form).then(response => {
this.getList() // this.$modal.msgSuccess('')
}) // this.getList()
}, // })
// },
/** 删除按钮操作 */ /** 删除按钮操作 */
handleDelete(row) { handleDelete(row) {
const objIds = row.objId || this.ids; const objIds = row.objId || this.ids;

Loading…
Cancel
Save