BOM展示

This commit is contained in:
砂糖
2025-07-31 18:07:51 +08:00
parent b1f40f09e9
commit f02967ebbf
23 changed files with 262 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 科伦普WMS系统
VUE_APP_TITLE = 科伦普综合办公系统
# 开发环境配置
ENV = 'development'

View File

@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 科伦普WMS系统
VUE_APP_TITLE = 科伦普综合办公系统
# 生产环境配置
ENV = 'production'

View File

@@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 科伦普WMS系统
VUE_APP_TITLE = 科伦普综合办公系统
# 开发环境配置
ENV = 'development'

View File

@@ -17,6 +17,7 @@ export default {
this.$store.dispatch('category/getCategoryList');
this.$store.dispatch('category/getProductMap');
this.$store.dispatch('category/getRawMaterialMap');
this.$store.dispatch('category/getBomMap');
}
console.log(this.$store)
},

View File

@@ -5,6 +5,11 @@
{{ item.attrValue }}
</el-descriptions-item>
</el-descriptions>
<div v-else-if="mini">
<el-tooltip :content="bomInfo.map(item => item.attrKey + ':' + item.attrValue).join(',')" class="bom-info" placement="top">
<span>{{ bomInfo.map(item => item.attrKey).join(',') }}</span>
</el-tooltip>
</div>
<div v-else>
<el-empty description="暂无BOM信息" />
</div>
@@ -12,14 +17,23 @@
</template>
<script>
import { listBomItem } from '../../../api/wms/bomItem';
import { listBomItem } from '@/api/wms/bomItem';
import { mapState } from 'vuex';
export default {
name: 'BomInfo',
props: {
bomId: {
type: [String, Number],
required: true
required: false
},
itemType: {
type: String,
required: false
},
itemId: {
type: [String, Number],
required: false
}
},
data() {
@@ -27,15 +41,46 @@ export default {
bomInfo: []
}
},
computed: {
...mapState('category', ['bomMap', 'productMap', 'rawMaterialMap']),
},
created() {
this.getBomInfo();
},
methods: {
getBomInfo() {
listBomItem({ bomId: this.bomId }).then(res => {
this.bomInfo = res.rows;
})
const bomMap = this.$store.getters.bomMap;
console.log(bomMap)
if (!this.bomId && !this.itemType && !this.itemId) {
return;
}
let bomId = this.bomId;
if (!bomId) {
if (this.itemType === 'product') {
bomId = this.productMap[this.itemId].bomId;
} else if (this.itemType === 'raw_material') {
bomId = this.rawMaterialMap[this.itemId].bomId;
}
}
if (bomMap[bomId]) {
this.bomInfo = bomMap[bomId];
} else {
listBomItem({ bomId: bomId }).then(res => {
this.bomInfo = res.rows;
})
}
}
}
}
</script>
</script>
<style scoped>
.bom-info {
cursor: pointer;
/* 溢出隐藏显示省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100px;
}
</style>

View File

@@ -0,0 +1,83 @@
<template>
<div>
<div v-if="bomInfo.length > 0">
<el-tooltip :content="bomInfo.map(item => item.attrKey + ':' + item.attrValue).join(',')" class="bom-info" placement="top">
<span>{{ bomInfo.map(item => item.attrKey).join(',') }}</span>
</el-tooltip>
</div>
<div v-else>
-
</div>
</div>
</template>
<script>
// 如果传递了bomId直接使用bomId, 如果没有传递则根据itemType和itemId获取bomId
import { listBomItem } from '@/api/wms/bomItem';
import { mapState } from 'vuex';
export default {
name: 'BomInfo',
props: {
bomId: {
type: [String, Number],
required: false
},
itemType: {
type: String,
required: false
},
itemId: {
type: [String, Number],
required: false
}
},
data() {
return {
bomInfo: []
}
},
computed: {
...mapState('category', ['bomMap', 'productMap', 'rawMaterialMap']),
},
created() {
this.getBomInfo();
},
methods: {
getBomInfo() {
const bomMap = this.$store.getters.bomMap;
console.log(bomMap)
if (!this.bomId && !this.itemType && !this.itemId) {
return;
}
console.log(this.itemType, this.itemId)
let bomId = this.bomId;
if (!bomId) {
if (this.itemType === 'product') {
bomId = this.productMap[this.itemId].bomId;
} else if (this.itemType === 'raw_material') {
bomId = this.rawMaterialMap[this.itemId].bomId;
}
}
if (bomMap[bomId]) {
this.bomInfo = bomMap[bomId];
} else {
listBomItem({ bomId: bomId }).then(res => {
this.bomInfo = res.rows;
})
}
}
}
}
</script>
<style scoped>
.bom-info {
cursor: pointer;
/* 溢出隐藏显示省略号 */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 100px;
}
</style>

View File

@@ -13,10 +13,10 @@
append-to-body
>
<el-descriptions :column="1" border>
<el-descriptions-item label="ID">
<el-descriptions-item label="产品ID">
{{ product.productId || '--' }}
</el-descriptions-item>
<el-descriptions-item label="名称">
<el-descriptions-item label="产品名称">
{{ product.productName || '--' }}
</el-descriptions-item>
<el-descriptions-item label="产品编码">

View File

@@ -9,9 +9,9 @@
<el-dialog :visible="showDetail" @close="showDetail = false" :title="material.rawMaterialName" width="600px"
append-to-body>
<el-descriptions :column="1" border>
<el-descriptions-item label="ID">{{ material.rawMaterialId }}</el-descriptions-item>
<el-descriptions-item label="名称">{{ material.rawMaterialName }}</el-descriptions-item>
<el-descriptions-item label="描述">{{ material.rawMaterialCode }}</el-descriptions-item>
<el-descriptions-item label="原材料ID">{{ material.rawMaterialId }}</el-descriptions-item>
<el-descriptions-item label="原材料名称">{{ material.rawMaterialName }}</el-descriptions-item>
<el-descriptions-item label="原材料编码">{{ material.rawMaterialCode }}</el-descriptions-item>
</el-descriptions>
<BomInfo :bomId="material.bomId" />
</el-dialog>

View File

@@ -18,5 +18,6 @@ const getters = {
sidebarRouters:state => state.permission.sidebarRouters,
productList: state => state.category.productList,
rawMaterialList: state => state.category.rawMaterialList,
bomMap: state => state.category.bomMap
}
export default getters

View File

@@ -1,13 +1,15 @@
import { listCategory } from '@/api/wms/category';
import { listProduct } from '@/api/wms/product';
import { listRawMaterial } from '@/api/wms/rawMaterial';
import { listBomItem } from '@/api/wms/bomItem';
const state = {
categoryList: [],
productMap: {},
rawMaterialMap: {},
productList: [],
rawMaterialList: []
rawMaterialList: [],
bomMap: {}
};
const mutations = {
@@ -25,6 +27,9 @@ const mutations = {
},
SET_RAW_MATERIAL_LIST(state, list) {
state.rawMaterialList = list;
},
SET_BOM_MAP(state, map) {
state.bomMap = map;
}
};
@@ -33,7 +38,7 @@ const actions = {
if (state.categoryList.length > 0) {
return Promise.resolve(state.categoryList);
}
return listCategory().then(res => {
return listCategory({ pageNum: 1, pageSize: 10000 }).then(res => {
commit('SET_CATEGORY_LIST', res.rows || []);
return res.rows || [];
});
@@ -42,7 +47,7 @@ const actions = {
if (Object.keys(state.productMap).length > 0) {
return Promise.resolve(state.productMap);
}
return listProduct().then(res => {
return listProduct({ pageNum: 1, pageSize: 10000 }).then(res => {
const map = {};
res.rows.forEach(item => {
map[item.productId] = item;
@@ -56,7 +61,7 @@ const actions = {
if (Object.keys(state.rawMaterialMap).length > 0) {
return Promise.resolve(state.rawMaterialMap);
}
return listRawMaterial().then(res => {
return listRawMaterial({ pageNum: 1, pageSize: 10000 }).then(res => {
const map = {};
res.rows.forEach(item => {
map[item.rawMaterialId] = item;
@@ -65,6 +70,23 @@ const actions = {
commit('SET_RAW_MATERIAL_LIST', res.rows || []);
return map;
});
},
getBomMap({ state, commit }) {
if (Object.keys(state.bomMap).length > 0) {
return Promise.resolve(state.bomMap);
}
return listBomItem({ pageNum: 1, pageSize: 10000 }).then(res => {
console.log('bomItem', res)
const map = {};
res.rows.forEach(item => {
if (!map[item.bomId]) {
map[item.bomId] = [];
}
map[item.bomId].push(item);
});
commit('SET_BOM_MAP', map);
return map;
})
}
};
export default {

View File

@@ -1,7 +1,7 @@
<template>
<div class="login">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
<h3 class="title">科伦普WMS系统</h3>
<h3 class="title">科伦普综合办公系统</h3>
<el-form-item prop="username">
<el-input
v-model="loginForm.username"
@@ -144,6 +144,7 @@ export default {
this.$store.dispatch('category/getCategoryList');
this.$store.dispatch('category/getProductMap');
this.$store.dispatch('category/getRawMaterialMap');
this.$store.dispatch('category/getBomMap');
this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
}).catch(() => {
this.loading = false;

View File

@@ -68,6 +68,11 @@
</ProductInfo>
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template slot-scope="scope">
<BomInfoMini item-type="product" :item-id="scope.row.productId" />
</template>
</el-table-column>
<el-table-column label="产品数量" align="center" prop="quantity" />
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="备注" align="center" prop="remark" />
@@ -132,6 +137,7 @@ import { getOrder } from "@/api/wms/order";
import ProductSelect from '@/components/KLPService/ProductSelect';
import { EOrderStatus } from "@/utils/enums";
import { ProductInfo } from '@/components/KLPService';
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: "OrderDetailPanel",
@@ -144,7 +150,8 @@ export default {
},
components: {
ProductSelect,
ProductInfo
ProductInfo,
BomInfoMini
},
data() {
return {

View File

@@ -17,8 +17,8 @@
<el-form-item label="库位" class="form-item">
<WarehouseSelect v-model="defaultForm.warehouseId" />
</el-form-item>
<el-form-item label="主码" class="form-item">
<el-select v-model="defaultForm.stockIoId" placeholder="请选择主码" clearable class="form-input">
<el-form-item label="挂载单据" class="form-item">
<el-select v-model="defaultForm.stockIoId" placeholder="请选择挂载单据" clearable class="form-input">
<el-option
v-for="item in masterList"
:key="item.stockIoId"
@@ -61,9 +61,9 @@
<WarehouseSelect v-model="scope.row.warehouseId" />
</template>
</el-table-column>
<el-table-column prop="stockIoId" label="主码" align="center">
<el-table-column prop="stockIoId" label="挂载单据" align="center">
<template #default="scope">
<el-select v-model="scope.row.stockIoId" placeholder="请选择主码" clearable class="table-select">
<el-select v-model="scope.row.stockIoId" placeholder="请选择挂载单据" clearable class="table-select">
<el-option
v-for="item in masterList"
:key="item.stockIoId"
@@ -173,7 +173,7 @@ export default {
},
fetchMaster() {
listStockIo({ pageSize: 9999, pageNum: 1 }).then(res => {
console.log(res, '获取主码');
console.log(res, '获取挂载单据');
this.masterList = res.rows;
});
},

View File

@@ -128,6 +128,11 @@
<dict-tag :options="dict.type.common_swicth" :value="scope.row.isEnabled"/>
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template slot-scope="scope">
<BomInfoMini :bomId="scope.row.bomId" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
@@ -260,6 +265,7 @@ import CategorySelect from '@/components/KLPService/CategorySelect';
import CategoryRenderer from '@/components/KLPService/Renderer/CategoryRenderer.vue';
import UserSelect from '@/components/KLPService/UserSelect';
import BomPanel from '../bom/components/BomPanel.vue';
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: "Product",
@@ -267,7 +273,8 @@ export default {
CategorySelect,
CategoryRenderer,
UserSelect,
BomPanel
BomPanel,
BomInfoMini
},
dicts: ['common_swicth'],
data() {

View File

@@ -32,6 +32,11 @@
<RawMaterialSelect v-model="scope.row.rawMaterialId" placeholder="请选择原材料" />
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template #default="scope">
<BomInfoMini item-type="raw_material" :item-id="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" />
<el-table-column prop="onTheWay" label="在途" />
<el-table-column prop="inventory" label="在库" />
@@ -65,10 +70,11 @@ import { createPurchasePlan } from '@/api/wms/purchasePlan'
import { listRawMaterial } from '@/api/wms/rawMaterial'
import UserSelect from '@/components/KLPService/UserSelect'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: 'CreatePurchasePanel',
components: { UserSelect, RawMaterialSelect },
components: { UserSelect, RawMaterialSelect, BomInfoMini },
props: {
orderId: {
type: [String, Number],

View File

@@ -24,6 +24,13 @@ export default {
loading: false
}
},
watch: {
orderId: {
handler(newVal) {
this.handleRecommend()
}
}
},
mounted() {
if (!this.showButton) {
this.handleRecommend();

View File

@@ -15,8 +15,8 @@
<script>
import RecommendPurchasePanel from './RecommendPurchasePanel.vue'
import CreatePurchasePanel from './CreatePurchasePanel.vue'
import { updatePurchasePlan } from '@/api/wms/purchasePlan'
import { EOrderStatus } from '@/api/wms/order'
import { updateOrder } from '@/api/wms/order'
import { EOrderStatus } from '@/utils/enums'
export default {
name: 'PurchasePlanClac',
@@ -32,18 +32,22 @@ export default {
},
data() {
return {
recommendData: {}
recommendData: {},
EOrderStatus: EOrderStatus
}
},
methods: {
onRecommend(data) {
console.log('获取推荐数据', data)
this.recommendData = data
},
onConfirm(submitData) {
updatePurchasePlan({
console.log('calc层', submitData)
updateOrder({
orderId: this.orderId,
orderStatus: EOrderStatus.PRODUCTIONING,
orderStatus: this.EOrderStatus.PRODUCTIONING,
}).then(response => {
console.log("状态变更成功")
this.$emit('confirm', submitData)
})

View File

@@ -65,6 +65,11 @@
</RawMaterialInfo>
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template slot-scope="scope">
<BomInfoMini item-type="raw_material" :item-id="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column label="负责人" align="center" prop="owner" />
<el-table-column label="计划采购数量" align="center" prop="quantity" />
<el-table-column label="单位" align="center" prop="unit" />
@@ -180,6 +185,7 @@ import StockInDialog from "./stockin.vue";
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect';
import UserSelect from '@/components/KLPService/UserSelect'
import { RawMaterialInfo } from '@/components/KLPService';
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: "PurchasePlanDetail",
@@ -187,7 +193,8 @@ export default {
StockInDialog,
RawMaterialSelect,
UserSelect,
RawMaterialInfo
RawMaterialInfo,
BomInfoMini
},
props: {
planId: {

View File

@@ -64,6 +64,11 @@
style="width: 100%"
>
<el-table-column label="原材料" align="center" prop="rawMaterialName" />
<el-table-column label="BOM" align="center">
<template slot-scope="scope">
<BomInfoMini item-type="raw_material" :item-id="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column label="计划数量" align="center" prop="planQuantity" />
<el-table-column label="入库数量" align="center" prop="quantity">
<template slot-scope="scope">
@@ -121,11 +126,13 @@ import { updatePurchasePlanDetail } from "@/api/wms/purchasePlanDetail";
import { getRawMaterial } from "@/api/wms/rawMaterial";
import { EPurchaseDetailStatus } from "@/utils/enums";
import WarehouseSelect from "@/components/KLPService/WarehouseSelect";
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: "StockInDialog",
components: {
WarehouseSelect
WarehouseSelect,
BomInfoMini
},
props: {
visible: {

View File

@@ -26,6 +26,11 @@
<RawMaterialInfo :materialId="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template #default="scope">
<BomInfoMini item-type="raw_material" :item-id="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" align="center" />
<el-table-column prop="onTheWay" label="在途" align="center" />
<el-table-column prop="inventory" label="在库" align="center" />
@@ -65,6 +70,11 @@
<RawMaterialInfo :materialId="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template #default="scope">
<BomInfoMini item-type="raw_material" :item-id="scope.row.rawMaterialId" />
</template>
</el-table-column>
<el-table-column prop="unit" label="单位" />
<el-table-column prop="onTheWay" label="在途" />
<el-table-column prop="inventory" label="在库" />
@@ -100,11 +110,11 @@ import { listRawMaterial, listRawMaterialWithDemand } from '@/api/wms/rawMateria
import UserSelect from '@/components/KLPService/UserSelect'
import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect'
import RawMaterialInfo from '@/components/KLPService/Renderer/RawMaterialInfo.vue'
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: 'CreatePurchasePanel',
components: { UserSelect, RawMaterialSelect, RawMaterialInfo },
components: { UserSelect, RawMaterialSelect, RawMaterialInfo, BomInfoMini },
props: {
orderId: {
type: [String, Number],

View File

@@ -117,7 +117,7 @@
<el-table-column label="原材料名称" align="center" prop="rawMaterialName" />
<el-table-column label="计量单位" align="center" prop="unit" />
<el-table-column label="钢种/牌号" align="center" prop="steelGrade" />
<el-table-column label="目标冷轧牌号" align="center" prop="targetColdGrade" />
<!-- <el-table-column label="目标冷轧牌号" align="center" prop="targetColdGrade" />
<el-table-column label="基础材质分类" align="center">
<template slot-scope="scope">
<CategoryRenderer :category-id="scope.row.baseMaterialId" />
@@ -132,6 +132,11 @@
<template slot-scope="scope">
<dict-tag :options="dict.type.common_swicth" :value="scope.row.isEnabled"/>
</template>
</el-table-column> -->
<el-table-column label="BOM" align="center">
<template slot-scope="scope">
<BomInfoMini :bomId="scope.row.bomId" />
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
@@ -292,13 +297,15 @@ import { listRawMaterial, getRawMaterial, delRawMaterial, addRawMaterial, update
import CategorySelect from "@/components/KLPService/CategorySelect/index.vue";
import CategoryRenderer from '@/components/KLPService/Renderer/CategoryRenderer.vue';
import BomPanel from '@/views/wms/bom/components/BomPanel.vue';
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: "RawMaterial",
components: {
CategorySelect,
CategoryRenderer,
BomPanel
BomPanel,
BomInfoMini
},
dicts: ['common_swicth'],
data() {

View File

@@ -87,6 +87,11 @@
<span v-else>{{ scope.row.itemId }}</span>
</template>
</el-table-column>
<el-table-column label="BOM" align="center">
<template slot-scope="scope">
<BomInfoMini :item-type="scope.row.itemType" :item-id="scope.row.itemId" />
</template>
</el-table-column>
<el-table-column label="数量" align="center" prop="quantity" />
<el-table-column label="单位" align="center" prop="unit" />
<el-table-column label="批次号" align="center" prop="batchNo" />
@@ -236,6 +241,7 @@ import RawMaterialSelect from '@/components/KLPService/RawMaterialSelect';
import ProductSelect from '@/components/KLPService/ProductSelect';
import { ITEM_TYPE } from '@/utils/enums';
import {RawMaterialInfo, ProductInfo} from "@/components/KLPService";
import BomInfoMini from '@/components/KLPService/Renderer/BomInfoMini.vue';
export default {
name: "StockIoDetailPanel",
@@ -244,7 +250,8 @@ export default {
RawMaterialSelect,
ProductSelect,
RawMaterialInfo,
ProductInfo
ProductInfo,
BomInfoMini
},
dicts: ['stock_item_type'],
props: {

View File

@@ -7,7 +7,7 @@ function resolve(dir) {
const CompressionPlugin = require('compression-webpack-plugin')
const name = process.env.VUE_APP_TITLE || '科伦普WMS系统' // 网页标题
const name = process.env.VUE_APP_TITLE || '科伦普综合办公系统' // 网页标题
const port = process.env.port || process.env.npm_config_port || 80 // 端口