Reviewed-on: http://git.picaiba.com/mt-fe-group/yudao-dev/pulls/97pull/106/head
@@ -12,12 +12,12 @@ ENV = 'development' | |||
VUE_APP_TITLE = MES系统 | |||
# 芋道管理系统/开发环境 | |||
VUE_APP_BASE_API = 'http://100.64.0.26:48082' | |||
# VUE_APP_BASE_API = 'http://100.64.0.26:48082' | |||
# VUE_APP_BASE_API = 'http://192.168.0.33:48082' | |||
# VUE_APP_BASE_API = 'http://192.168.4.173:48080' | |||
# VUE_APP_BASE_API = 'http://192.168.2.173:48080' | |||
# VUE_APP_BASE_API = 'http://192.168.1.49:48080' | |||
# VUE_APP_BASE_API = 'http://192.168.1.8:48080' | |||
VUE_APP_BASE_API = 'http://192.168.1.8:48082' | |||
# VUE_APP_BASE_API = 'http://192.168.4.159:48080' | |||
# VUE_APP_BASE_API = 'http://192.168.1.56:48080' | |||
# VUE_APP_BASE_API = 'http://192.168.4.159:48080' | |||
@@ -0,0 +1,114 @@ | |||
<!-- | |||
filename: BomSelection.vue | |||
author: liubin | |||
date: 2023-11-20 13:23:36 | |||
description: | |||
--> | |||
<template> | |||
<div class="bom-selection"> | |||
<el-checkbox | |||
v-for="item in list__inner" | |||
:key="item.id + randomKey" | |||
:label="item.name" | |||
:disabled="item.disabled" | |||
:checked="item.id === selected" | |||
@change="(e) => handleChange(item, e)" | |||
class="sl__body-item"></el-checkbox> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: 'BomSelection', | |||
components: {}, | |||
// model: { | |||
// prop: 'selected', | |||
// event: 'update', | |||
// }, | |||
props: { | |||
currentSelect: { | |||
type: String, | |||
default: null, | |||
}, | |||
list: { | |||
type: Array, | |||
default: () => [], | |||
}, | |||
equipmentId: { | |||
type: String, | |||
default: '', | |||
}, | |||
}, | |||
data() { | |||
return { | |||
list__inner: [], | |||
selected: null, | |||
randomKey: Math.random(), | |||
}; | |||
}, | |||
watch: { | |||
list: { | |||
handler(val) { | |||
if (val) { | |||
this.list__inner = val.map((item) => ({ ...item, disabled: false })); | |||
} | |||
}, | |||
deep: true, | |||
immediate: true, | |||
}, | |||
currentSelect: { | |||
handler(val) { | |||
this.selected = val; | |||
this.randomKey = Math.random(); | |||
}, | |||
immediate: true, | |||
}, | |||
}, | |||
methods: { | |||
handleChange(bomItem, selected) { | |||
this.list__inner = this.list__inner.map((item) => ({ | |||
...item, | |||
disabled: selected ? item.id !== bomItem.id : false, | |||
})); | |||
if (selected) this.selected = null; | |||
else this.clearSelected(); | |||
this.$emit('change', this.equipmentId, bomItem.id, selected); | |||
this.$nextTick(() => { | |||
this.$forceUpdate(); | |||
}); | |||
}, | |||
clearSelected() { | |||
console.log('clearSelected'); | |||
this.selected = null; | |||
this.randomKey = Math.random(); | |||
// this.$emit('update', null); | |||
// this.$nextTick(() => { | |||
// this.$forceUpdate(); | |||
// }); | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.bom-selection { | |||
display: flex; | |||
flex-direction: column; | |||
gap: 6px; | |||
padding: 6px; | |||
} | |||
.sl__body-item { | |||
margin: 0; | |||
padding: 3px 6px; | |||
border-radius: 4px; | |||
transition: background 0.3s ease-in-out; | |||
&:hover { | |||
background: #0001; | |||
} | |||
} | |||
</style> |
@@ -0,0 +1,264 @@ | |||
<!-- | |||
filename: BomSelector.vue | |||
author: liubin | |||
date: 2023-11-17 16:23:28 | |||
description: | |||
--> | |||
<template> | |||
<div class="bom-selector"> | |||
<el-row> | |||
<el-col :span="8"> | |||
<el-input | |||
v-model="searchText" | |||
placeholder="搜索" | |||
clearable | |||
style="margin-bottom: 12px; user-select: none"> | |||
<i slot="prefix" class="el-input__icon el-icon-search"></i> | |||
</el-input> | |||
</el-col> | |||
</el-row> | |||
<el-row style="border: 1px solid #ccc; display: flex"> | |||
<el-col :span="8"> | |||
<div class="select-list"> | |||
<div class="sl__header" style="background: #f3f4fb; padding: 12px"> | |||
<span style="">可分配设备</span> | |||
<span> | |||
{{ selectedEquipments.length }}/{{ filteredBomList.length }} | |||
</span> | |||
</div> | |||
<div class="sl__body"> | |||
<div | |||
class="sl__body-item" | |||
v-for="eq in filteredBomList" | |||
:key="eq.id + refreshKey"> | |||
<el-checkbox | |||
:key="refreshKey" | |||
:checked="selectedEquipments.includes(eq.id)" | |||
@change="(e) => handleEquipmentChange(eq, e)" | |||
class=""></el-checkbox> | |||
<span | |||
:key="'label' + refreshKey" | |||
@click.stop="() => handleLoadDom(eq)"> | |||
{{ eq.name }} | |||
</span> | |||
</div> | |||
</div> | |||
</div> | |||
</el-col> | |||
<el-col :span="8" style="border-left: 1px solid #ccc"> | |||
<div class="select-list"> | |||
<div class="sl__header" style="background: #f3f4fb; padding: 12px"> | |||
<span style="">物料BOM</span> | |||
</div> | |||
<BomSelection | |||
ref="materialsBomList" | |||
:key="materialsBomList.equipmentId + 'materialsBomList'" | |||
:list="materialsBomList" | |||
:equipment-id="materialsBomList.equipmentId" | |||
:current-select="currentSelectedMaterialBomId" | |||
@change="handleMaterialBomChange" /> | |||
</div> | |||
</el-col> | |||
<el-col :span="8" style="border-left: 1px solid #ccc"> | |||
<div class="select-list"> | |||
<div class="sl__header" style="background: #f3f4fb; padding: 12px"> | |||
<span style="">参数BOM</span> | |||
</div> | |||
<BomSelection | |||
ref="valuesBomList" | |||
:key="valuesBomList.equipmentId + 'valuesBomList'" | |||
:list="valuesBomList" | |||
:equipment-id="valuesBomList.equipmentId" | |||
:current-select="currentSelectedValueBomId" | |||
@change="handleValueBomChange" /> | |||
</div> | |||
</el-col> | |||
</el-row> | |||
</div> | |||
</template> | |||
; | |||
<script> | |||
import BomSelection from './BomSelection.vue'; | |||
export default { | |||
name: 'BomSelector', | |||
components: { BomSelection }, | |||
model: { | |||
prop: 'value', | |||
event: 'update', | |||
}, | |||
props: { | |||
bomList: { | |||
type: Array, | |||
default: () => [], | |||
}, | |||
value: { | |||
type: Array, | |||
default: () => [], | |||
}, | |||
}, | |||
data() { | |||
return { | |||
searchText: '', | |||
selectedEquipments: [], | |||
selected: [], | |||
materialsBomList: [], | |||
valuesBomList: [], | |||
refreshKey: Math.random(), | |||
currentSelectedMaterialBomId: null, | |||
currentSelectedValueBomId: null, | |||
}; | |||
}, | |||
watch: { | |||
value: { | |||
handler(val) { | |||
console.log('value', val); | |||
if (val) { | |||
this.selectedEquipments = val.map((item) => item.equipmentId); | |||
this.selected = val; | |||
} | |||
}, | |||
deep: true, | |||
immediate: true, | |||
}, | |||
}, | |||
computed: { | |||
filteredBomList() { | |||
return this.bomList.filter((item) => { | |||
return item.name.includes(this.searchText); | |||
}); | |||
}, | |||
}, | |||
methods: { | |||
commit() { | |||
this.$emit('update', this.selected); | |||
}, | |||
handleLoadDom(eq) { | |||
// 只显示 dom 列表 | |||
this.currentEquipment = eq.id; | |||
this.materialsBomList = eq.materialsBom; | |||
this.valuesBomList = eq.valuesBom; | |||
// 回复选中的bom信息 | |||
if (this.selectedEquipments.includes(eq.id)) { | |||
const selectedItem = this.selected.find( | |||
(item) => item.equipmentId == eq.id | |||
); | |||
this.currentSelectedMaterialBomId = | |||
selectedItem.equMaterialBomId ?? null; | |||
this.currentSelectedValueBomId = selectedItem.equValueBomId ?? null; | |||
} | |||
}, | |||
handleEquipmentChange(eq, selected) { | |||
this.currentEquipment = eq.id; | |||
this.materialsBomList = eq.materialsBom; | |||
this.valuesBomList = eq.valuesBom; | |||
if (selected) { | |||
this.selectedEquipments.push(eq.id); | |||
this.selected.push({ | |||
equipmentId: eq.id, | |||
equValueBomId: null, | |||
equMaterialBomId: null, | |||
}); | |||
// this.$emit('update', this.selected); | |||
} else { | |||
// 清空选择状态 | |||
this.selectedEquipments = this.selectedEquipments.filter( | |||
(id) => id !== eq.id | |||
); | |||
// this.$refs.materialsBomList.clearSelected(); | |||
// this.$refs.valuesBomList.clearSelected(); | |||
this.currentSelectedMaterialBomId = null; | |||
this.currentSelectedValueBomId = null; | |||
this.selected = this.selected.filter( | |||
(item) => item.equipmentId !== eq.id | |||
); | |||
// this.$emit('update', this.selected); | |||
} | |||
}, | |||
handleMaterialBomChange(equipmentId, bomId, selected) { | |||
const selectedItem = this.selected.find( | |||
(item) => item.equipmentId == equipmentId | |||
); | |||
if (selected && !selectedItem) { | |||
// 如果没找到这个 | |||
this.selectedEquipments.push(equipmentId); | |||
this.selected.push({ | |||
equipmentId, | |||
equValueBomId: null, | |||
equMaterialBomId: bomId, | |||
}); | |||
// 强制更新'设备'一栏 | |||
this.refreshKey = Math.random(); | |||
// this.$emit('update', this.selected); | |||
return; | |||
} | |||
selectedItem && (selectedItem.equMaterialBomId = selected ? bomId : null); | |||
this.currentSelectedMaterialBomId = selected ? bomId : null; | |||
// this.$emit('update', this.selected); | |||
}, | |||
handleValueBomChange(equipmentId, bomId, selected) { | |||
const selectedItem = this.selected.find( | |||
(item) => item.equipmentId == equipmentId | |||
); | |||
if (selected && !selectedItem) { | |||
// 如果没找到这个 | |||
this.selectedEquipments.push(equipmentId); | |||
this.selected.push({ | |||
equipmentId, | |||
equValueBomId: bomId, | |||
equMaterialBomId: null, | |||
}); | |||
this.refreshKey = Math.random(); | |||
// this.$emit('update', this.selected); | |||
return; | |||
} | |||
selectedItem && (selectedItem.equValueBomId = selected ? bomId : null); | |||
this.currentSelectedValueBomId = selected ? bomId : null; | |||
// this.$emit('update', this.selected); | |||
}, | |||
}, | |||
}; | |||
</script> | |||
<style scoped lang="scss"> | |||
.bom-selector { | |||
min-height: 200px; | |||
} | |||
.sl__body { | |||
display: flex; | |||
flex-direction: column; | |||
gap: 6px; | |||
padding: 6px; | |||
} | |||
.sl__body-item { | |||
margin: 0; | |||
padding: 3px 6px; | |||
border-radius: 4px; | |||
cursor: pointer; | |||
transition: background 0.3s ease-in-out; | |||
display: flex; | |||
align-items: center; | |||
gap: 8px; | |||
> span { | |||
flex: 1; | |||
} | |||
&:hover { | |||
background: #0001; | |||
} | |||
} | |||
.sl__header { | |||
border-bottom: 1px solid #ccc; | |||
} | |||
</style> |
@@ -31,6 +31,9 @@ | |||
icon="el-icon-search" | |||
placeholder="搜索" | |||
v-model="searchText" | |||
:disabled="currentDet == null" | |||
@change="handleSearchTextChange" | |||
clearable | |||
style="margin-left: 20px"> | |||
<i slot="prefix" class="el-input__icon el-icon-search"></i> | |||
</el-input> | |||
@@ -63,22 +66,27 @@ | |||
<base-dialog | |||
dialogTitle="选择设备" | |||
:dialogVisible="open" | |||
width="45%" | |||
@close="cancel" | |||
@cancel="cancel" | |||
@confirm="submitForm"> | |||
<el-transfer v-model="choosedEquipments" :data="eqList"> | |||
<!-- <span slot-scope="{ option }"> | |||
{{ option.key }} - {{ option.label }} | |||
</span> --> | |||
</el-transfer> | |||
<!-- <CustomTransfer /> --> | |||
<BomSelector | |||
ref="bomSelector" | |||
v-if="open" | |||
:bom-list="bomList" | |||
:value="selectedBoms" | |||
@update="selectedBoms = $event" /> | |||
</base-dialog> | |||
</section> | |||
</template> | |||
<script> | |||
import BomSelector from './BomSelector.vue'; | |||
export default { | |||
name: 'ProcessBom', | |||
components: {}, | |||
components: { BomSelector }, | |||
props: { | |||
currentDet: { | |||
type: Object, | |||
@@ -89,11 +97,12 @@ export default { | |||
return { | |||
open: false, | |||
eqList: [], | |||
bomList: [], | |||
finalList: [], | |||
choosedEquipments: [], | |||
searchBarFormConfig: [{ label: '工序下设备' }], | |||
tableProps: [ | |||
{ prop: 'equipmentId', label: '设备名称' }, | |||
{ prop: 'equName', label: '设备名称' }, | |||
{ prop: 'materialName', label: '物料BOM' }, | |||
{ prop: 'valueName', label: '参数BOM' }, | |||
], | |||
@@ -103,13 +112,17 @@ export default { | |||
queryParams: { | |||
pageNo: 1, | |||
pageSize: 10, | |||
equipmentName: '', | |||
}, | |||
searchText: '' | |||
searchText: '', | |||
selectedBoms: [], | |||
timer: null, | |||
}; | |||
}, | |||
watch: { | |||
currentDet: { | |||
handler(val) { | |||
console.log('currentDet', val); | |||
if (val != null) { | |||
this.getList(val); | |||
} else { | |||
@@ -121,51 +134,21 @@ export default { | |||
}, | |||
}, | |||
methods: { | |||
renderFn(h, option) { | |||
console.log(option); | |||
return <span>1</span>; | |||
}, | |||
async getEqList() { | |||
console.log('currentDet', this.currentDet); | |||
const { sectionId } = this.currentDet; | |||
const { code, data } = await this.http( | |||
'base/core-equipment-bind-section/page', | |||
'get', | |||
{ workshopSectionId: sectionId, pageNo: 1, pageSize: 100 } | |||
); | |||
if (code == 0) { | |||
console.log('workshopSectionId', data); | |||
// 模拟数据 | |||
this.eqList = [ | |||
{ equipmentId: 1, equipmentName: '设备1' }, | |||
{ equipmentId: 2, equipmentName: '设备2' }, | |||
{ equipmentId: 3, equipmentName: '设备3' }, | |||
{ equipmentId: 4, equipmentName: '设备4' }, | |||
{ equipmentId: 5, equipmentName: '设备5' }, | |||
{ equipmentId: 6, equipmentName: '设备6' }, | |||
]; // ].map((item) => ({ label: item.equipmentName, key: item.equipmentId })); | |||
handleEmitFun() {}, | |||
// 获取参数bom和物料bom | |||
// 需调用参数bom接口和 物料bom接口 | |||
this.finalList = this.eqList.map((item) => { | |||
item.sub = []; | |||
// key: equipmentId-参数bomId | |||
item.sub.push({ | |||
key: item.equipmentId + '-' + '101', | |||
label: '参数bom1', | |||
}); | |||
item.sub.push({ | |||
key: item.equipmentId + '-' + '201', | |||
label: '物料bom1', | |||
}); | |||
handleTableBtnClick() {}, | |||
return item; | |||
handleSearchTextChange(val) { | |||
if (this.timer) clearTimeout(this.timer); | |||
this.timer = setTimeout(() => { | |||
console.log('geting list.......'); | |||
this.queryParams.equipmentName = val; | |||
this.$nextTick(() => { | |||
this.getList(this.currentDet); | |||
}); | |||
} | |||
}, 300); | |||
}, | |||
handleEmitFun() {}, | |||
handleTableBtnClick() {}, | |||
put(payload) { | |||
return this.http(this.updateUrl, 'put', payload); | |||
}, | |||
@@ -186,8 +169,41 @@ export default { | |||
data: method !== 'get' ? payload : null, | |||
}); | |||
}, | |||
submitForm() {}, | |||
async getList({ detId, detName, detDesc, flowId, sectionName } = {}) { | |||
submitForm() { | |||
// 现将子组件的修改提交更新至本组件 | |||
this.$refs.bomSelector.commit(); | |||
// 再提交至后端 | |||
this.$nextTick(async () => { | |||
console.log('selectedBoms', this.selectedBoms); | |||
if (this.selectedBoms.length) { | |||
const { code, data } = await this.http( | |||
'/extend/process-flow-det-equipment/createList', | |||
'post', | |||
this.selectedBoms.map((item) => ({ | |||
...item, | |||
flowDetId: this.currentDet.detId, | |||
})) | |||
); | |||
if (code == 0) { | |||
this.$message.success('操作成功'); | |||
this.getList(this.currentDet); | |||
this.cancel(); | |||
} else { | |||
this.$message.error('操作失败'); | |||
} | |||
} else { | |||
this.$message.info('请选择设备'); | |||
} | |||
}); | |||
}, | |||
async getList({ | |||
detId, | |||
detName, | |||
detDesc, | |||
flowId, | |||
sectionName, | |||
sectionId, | |||
} = {}) { | |||
console.log('get list', detId, detName, flowId); | |||
const { data, code } = await this.http( | |||
'/extend/process-flow-det-equipment/page', | |||
@@ -201,10 +217,38 @@ export default { | |||
this.list.splice(0); | |||
this.total = 0; | |||
} | |||
// 获取设备及bom列表 | |||
this.http('/extend/process-flow-det/getEquipmentDetBySectionId', 'post', { | |||
sectionId, | |||
flowDetId: detId, | |||
}).then(({ code, data }) => { | |||
if (code == 0) { | |||
this.bomList = data.map((eq) => { | |||
eq.materialsBom = eq.materialsBom || []; | |||
eq.valuesBom = eq.valuesBom || []; | |||
// 设置选中状态 | |||
eq.materialsBom.chosen = eq.materialsBomChoseId ?? null; | |||
eq.valuesBom.chosen = eq.valuesBomChoseId ?? null; | |||
if (eq.equChose || eq.materialsBom.chosen || eq.valuesBom.chosen) { | |||
this.selectedBoms.push({ | |||
equipmentId: eq.id, | |||
equMaterialBomId: eq.materialsBom.chosen, | |||
equValueBomId: eq.valuesBom.chosen, | |||
}); | |||
} | |||
// 设置设备id | |||
eq.materialsBom.equipmentId = eq.id; | |||
eq.valuesBom.equipmentId = eq.id; | |||
return eq; | |||
}); | |||
} else { | |||
this.bomList.splice(0); | |||
} | |||
}); | |||
}, | |||
async handleAddEquipment() { | |||
this.open = true; | |||
await this.getEqList(); | |||
}, | |||
cancel() { | |||
this.open = false; | |||
@@ -0,0 +1,51 @@ | |||
export class Candidate { | |||
constructor(id, name, paramBomList, materialBomList) { | |||
this.equipmentId = id; | |||
this.equipmentName = name; | |||
this.children = []; | |||
this.totalBom = paramBomList.length + materialBomList.length; | |||
this.selected = false; | |||
paramBomList.forEach((pb) => { | |||
this.children.push({ | |||
id: pb.id, | |||
name: pb.name, | |||
type: 'param', | |||
selected: false, | |||
}); | |||
}); | |||
materialBomList.forEach((mb) => { | |||
this.children.push({ | |||
id: mb.id, | |||
name: mb.name, | |||
type: 'material', | |||
selected: false, | |||
}); | |||
}); | |||
} | |||
get selected() { | |||
return this.children.filter((child) => child.selected).length; | |||
} | |||
get paramBom() { | |||
return this.children.filter((child) => child.type === 'param'); | |||
} | |||
get materialBom() { | |||
return this.children.filter((child) => child.type === 'material'); | |||
} | |||
} | |||
export class CandidateList { | |||
constructor() { | |||
this.value = []; | |||
} | |||
addCandidate(candidate) { | |||
this.value.push(candidate); | |||
} | |||
get selected() { | |||
return this.list.filter((candidate) => candidate.selected).length; | |||
} | |||
} |