Compare commits

...

5 Commits

Author SHA1 Message Date
lb
7249abf5b1 add BomSelector 2023-11-17 16:57:55 +08:00
lb
76f5385140 add Candidate 2023-11-17 16:05:57 +08:00
lb
bb731dfcd4 add custom tree 2023-11-17 14:56:43 +08:00
lb
d3eb9d8fbc update custom-transfer 2023-11-17 11:25:28 +08:00
lb
9a7521e691 add CustomTrasfer 2023-11-17 11:15:18 +08:00
7 changed files with 583 additions and 7 deletions

View File

@ -0,0 +1,123 @@
<!--
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="搜索"
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">
<el-col :span="8">
<div class="select-list">
<div class="sl__header" style="background: #f3f4fb; padding: 12px">
<span style="">可分配设备</span>
<span>1/24</span>
</div>
<el-checkbox-group v-model="selectedEquipments" class="sl__body">
<el-checkbox
v-for="n in 10"
:key="n"
:label="'设备' + n"
:true-label="n"
class="sl__body-item"></el-checkbox>
</el-checkbox-group>
</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>
<el-checkbox-group v-model="selectedMBom" class="sl__body">
<el-checkbox
v-for="n in 10"
:key="n"
class="sl__body-item"></el-checkbox>
</el-checkbox-group>
</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>
<el-checkbox-group v-model="selectedPBom" class="sl__body">
<el-checkbox
v-for="n in 10"
:key="n"
class="sl__body-item"></el-checkbox>
</el-checkbox-group>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'BomSelector',
components: {},
props: {},
data() {
return {
searchText: '',
selectedEquipments: [],
selectedMBom: [],
selectedPBom: [],
};
},
watch: {
selectedEquipments: {
handler(val) {
console.log(val);
},
deep: true,
},
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.bom-selector {
min-height: 200px;
}
.select-list {
}
.sl__body {
display: flex;
flex-direction: column;
gap: 6px;
padding: 6px;
> .el-checkbox {
margin: 0;
padding: 3px 6px;
border-radius: 4px;
transition: background 0.3s ease-in-out;
&:hover {
background: #0001;
}
}
}
.sl__header {
border-bottom: 1px solid #ccc;
}
</style>

View File

@ -0,0 +1,111 @@
<!--
filename: CustomBomList.vue
author: liubin
date: 2023-11-17 14:06:04
description:
-->
<template>
<div class="custom-bom-list—wrapper">
<div
class="ct__equipment-name"
@click.prevent="
() => {
$emit('open', equipment.id);
}
">
{{ equipment.name }}
</div>
<div
class="ct__bom-list"
:class="{
hidden: active && bomListLength > 0 ? false : true,
}">
<ul class="param-bom">
<li v-for="bom in equipment.paramBomList" :key="bom.name">
{{ bom.name }}
</li>
</ul>
<ul class="material-bom">
<li v-for="bom in equipment.materialBomList" :key="bom.name">
{{ bom.name }}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: 'CustomBomList',
components: {},
props: {
equipment: {
type: Object,
default: () => ({}),
},
active: {
type: Boolean,
default: false,
},
},
computed: {
bomListLength() {
return (
(this.equipment.paramBomList?.length || 0) +
(this.equipment.materialBomList?.length || 0)
);
},
},
data() {
return {
showList: false,
};
},
methods: {},
};
</script>
<style scoped lang="scss">
// .custom-bom-listwrapper {
// height: auto;
// transition: height .2s ease-in-out;
// }
.ct__equipment-name {
background: #0001;
padding: 8px;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
&:hover {
background: #0002;
}
}
.hidden {
display: none;
}
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
ul {
display: flex;
flex-direction: column;
gap: 4px;
margin-top: 4px;
}
.material-bom > li,
.param-bom > li {
padding: 4px 24px;
background: #0001;
border-radius: 4px;
}
</style>

View File

@ -0,0 +1,127 @@
<!--
filename: CustomTransfer.vue
author: liubin
date: 2023-11-17 10:22:28
description:
-->
<template>
<div class="custom-transfer">
<CustomTransferBox
key="left"
class="left-ctb"
title="设备列表"
:candidate-list="candidateList"
:selected-list="selectedList"
@selected-list-change="handleChange" />
<div
class="btns"
style="
display: flex;
flex-direction: column;
gap: 12px;
justify-content: center;
align-items: center;
">
<el-button style="margin: 0">&gt;</el-button>
<el-button style="margin: 0" disabled>&lt;</el-button>
</div>
<CustomTransferBox
key="right"
class="right-ctb"
title="已选BOM"
:candidate-list="[]"
:selected-list="[]"
@selected-list-change="handleChange" />
</div>
</template>
<script>
import CustomTransferBox from './CustomTransferBox.vue';
export default {
name: 'CustomTransfer',
components: { CustomTransferBox },
props: ['sectionId', 'selectedBoms'],
data() {
return {
pageUrl: '',
list: [],
bomLoading: false,
queryParams: {
pageNo: 1,
pageSize: 100,
},
candidate: [],
selectedList: [],
};
},
computed: {},
methods: {
http(url, method, payload) {
return this.$axios({
url,
method,
params: method === 'get' ? payload : null,
data: method !== 'get' ? payload : null,
});
},
//
async getList() {
const res = await this.http.get(this.pageUrl, {
workshopSectionId: this.sectionId,
...this.queryParams,
});
if (res.code === 200) {
// this.list = res.data;
this.list = [
{ equipmentId: 1, equipmentName: '设备1' },
{ equipmentId: 2, equipmentName: '设备2' },
{ equipmentId: 3, equipmentName: '设备3' },
];
}
},
// bombom
async getMaterialBom(eqId) {},
async getParamBom(eqId) {},
async handleEquipmentClick(eqItem) {
this.bomLoading = true;
eqItem.children = [];
const { code: materialCode, data: materialData } =
await this.getMaterialBom(eqItem.equipmentId);
const { code: paramCode, data: paramData } = await this.getParamBom(
eqItem.equipmentId
);
if (materialCode == 0) {
eqItem.children.push(...materialData);
}
if (paramCode == 0) {
eqItem.children.push(...paramData);
}
this.bomLoading = false;
},
//
handleChange() {},
},
};
</script>
<style scoped lang="scss">
.custom-transfer {
background: '#cfc2';
display: flex;
}
.btns {
padding: 10px;
}
.left-ctb {
flex: 1;
}
.right-ctb {
flex: 1;
}
</style>

View File

@ -0,0 +1,110 @@
<!--
filename: CustomTrasferBox.vue
author: liubin
date: 2023-11-17 10:49:08
description:
-->
<template>
<div class="custom-transfer-box">
<div class="ctb-header">
<span>
{{ title }}
</span>
<span>
<b>{{ selectedList.length }}</b>
/
<b>{{ candidateList.length }}</b>
</span>
</div>
<div class="ctb-main">
<el-input
v-model="searchText"
placeholder="搜索"
style="margin-bottom: 12px; user-select: none">
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
<custom-tree :raw-data="candidateList" />
</div>
<div class="ctb-footer">
<pagination
v-show="1"
style="padding: 0"
:total="total"
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
@pagination="getList" />
</div>
</div>
</template>
<script>
import CustomTree from './CustomTree.vue';
export default {
name: 'CustomTransferBox',
components: { CustomTree },
props: {
title: {
type: String,
default: '',
},
candidateList: {
type: Array,
default: () => [],
},
selectedList: {
type: Array,
default: () => [],
},
},
data() {
return {
queryParams: {
pageNo: 1,
pageSize: 10,
},
total: 0,
searchText: '',
};
},
computed: {},
methods: {
getList() {
this.$emit('get-list', this.queryParams);
},
},
};
</script>
<style scoped lang="scss">
.custom-transfer-box {
margin: 0 8px;
flex: 1;
border: 1px solid #ccc;
border-radius: 8px;
min-height: 240px;
display: flex;
flex-direction: column;
}
.ctb-header {
min-height: 12px;
padding: 12px;
border-bottom: 1px solid #ccc;
display: flex;
justify-content: space-between;
}
.ctb-main {
flex: 1;
padding: 12px;
}
.ctb-footer {
user-select: none;
min-height: 12px;
padding: 12px;
border-top: 1px solid #ccc;
}
</style>

View File

@ -0,0 +1,53 @@
<!--
filename: CustomTree.vue
author: liubin
date: 2023-11-17 13:53:16
description:
-->
<template>
<div class="custom-tree">
<div v-for="equipment in rawData" :key="eq.id">
<CustomBomList
@open="closeOthers"
:active="activeId == eq.id"
:equipment="equipment" />
</div>
</div>
</template>
<script>
import CustomBomList from './CustomBomList.vue';
export default {
name: 'CustomTree',
components: { CustomBomList },
props: {
rawData: {
type: Array,
default: () => [],
},
},
data() {
return {
showList: false,
activeId: null,
};
},
computed: {},
methods: {
closeOthers(id) {
this.activeId = id;
},
},
};
</script>
<style scoped lang="scss">
.custom-tree {
// background: #0001;
display: flex;
flex-direction: column;
gap: 8px;
}
</style>

View File

@ -63,22 +63,23 @@
<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 />
</base-dialog>
</section>
</template>
<script>
import CustomTransfer from './CustomTransfer.vue';
import BomSelector from './BomSelector.vue';
export default {
name: 'ProcessBom',
components: {},
components: { BomSelector },
props: {
currentDet: {
type: Object,
@ -104,7 +105,7 @@ export default {
pageNo: 1,
pageSize: 10,
},
searchText: ''
searchText: '',
};
},
watch: {

View File

@ -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;
}
}