|
|
|
|
<template>
|
|
|
|
|
<basic-container>
|
|
|
|
|
<!-- <el-tabs v-model="activeName" @tab-click="handleClick">
|
|
|
|
|
<el-tab-pane label="部件-子件" name="1"></el-tab-pane>
|
|
|
|
|
<el-tab-pane label="部件-模具" name="2"></el-tab-pane>
|
|
|
|
|
<el-tab-pane label="模具-子件" name="3"></el-tab-pane>
|
|
|
|
|
</el-tabs> -->
|
|
|
|
|
<!-- <pieceChildQuery v-if="activeName=='1'"></pieceChildQuery>
|
|
|
|
|
<sinterMoldNew v-if="activeName=='2'"></sinterMoldNew>
|
|
|
|
|
<moldChild v-if="activeName=='3'"></moldChild> -->
|
|
|
|
|
<el-form :model="form" label-width="60" label-position="left">
|
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="部件号:">
|
|
|
|
|
<el-input v-model="form.bujian" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="6">
|
|
|
|
|
<el-form-item label="子件号:">
|
|
|
|
|
<el-input v-model="form.zijian" />
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<div style="float: right">
|
|
|
|
|
<el-button type="primary" icon="search" @click="searchFn()">查询</el-button>
|
|
|
|
|
<el-button icon="refreshLeft" @click="resetFn()">重置</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
</el-form>
|
|
|
|
|
|
|
|
|
|
<div class="form-box">
|
|
|
|
|
<div v-if="isComponentOpen">
|
|
|
|
|
<div v-if="dataTree.length > 0" class="form-bom" ref="lineChart"></div>
|
|
|
|
|
<el-empty v-else description="数据为空"></el-empty>
|
|
|
|
|
</div>
|
|
|
|
|
<div v-if="isSubOpen">
|
|
|
|
|
<avue-crud
|
|
|
|
|
:option="option"
|
|
|
|
|
:table-loading="loading"
|
|
|
|
|
:data="data"
|
|
|
|
|
v-model="form"
|
|
|
|
|
v-model:page="page"
|
|
|
|
|
ref="crud"
|
|
|
|
|
@row-del="rowDel"
|
|
|
|
|
@search-change="searchChange"
|
|
|
|
|
@search-reset="searchReset"
|
|
|
|
|
@selection-change="selectionChange"
|
|
|
|
|
@current-change="currentChange"
|
|
|
|
|
@size-change="sizeChange"
|
|
|
|
|
@refresh-change="refreshChange"
|
|
|
|
|
@on-load="onLoad"
|
|
|
|
|
>
|
|
|
|
|
<template #bpartCode="scope">
|
|
|
|
|
<el-button type="text" @click="linkToPartTree(scope.row)">{{
|
|
|
|
|
scope.row.bpartCode
|
|
|
|
|
}}</el-button>
|
|
|
|
|
</template>
|
|
|
|
|
</avue-crud>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</basic-container>
|
|
|
|
|
</template>
|
|
|
|
|
<script>
|
|
|
|
|
// import pieceChildQuery from './components/pieceChildQuery.vue'
|
|
|
|
|
// import sinterMoldNew from './components/sinterMoldNew.vue'
|
|
|
|
|
// import moldChild from './components/moldChild.vue'
|
|
|
|
|
import { getSinteringPart, getDsPartTree } from '@/api/processManagement/sinTerBOM';
|
|
|
|
|
export default {
|
|
|
|
|
components: {
|
|
|
|
|
// pieceChildQuery,
|
|
|
|
|
// sinterMoldNew,
|
|
|
|
|
// moldChild
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
activeName: '1',
|
|
|
|
|
form: {
|
|
|
|
|
bujian: '',
|
|
|
|
|
zijian: '',
|
|
|
|
|
},
|
|
|
|
|
option: {
|
|
|
|
|
height: 'auto',
|
|
|
|
|
calcHeight: 32,
|
|
|
|
|
tip: false,
|
|
|
|
|
simplePage: true,
|
|
|
|
|
searchShow: true,
|
|
|
|
|
searchMenuSpan: 6,
|
|
|
|
|
searchIcon: true,
|
|
|
|
|
searchIndex: 3,
|
|
|
|
|
tree: false,
|
|
|
|
|
border: true,
|
|
|
|
|
index: true,
|
|
|
|
|
selection: false,
|
|
|
|
|
viewBtn: false,
|
|
|
|
|
delBtn: false,
|
|
|
|
|
addBtn: false,
|
|
|
|
|
editBtn: false,
|
|
|
|
|
editBtnText: '修改',
|
|
|
|
|
addBtnIcon: ' ',
|
|
|
|
|
viewBtnIcon: ' ',
|
|
|
|
|
delBtnIcon: ' ',
|
|
|
|
|
editBtnIcon: ' ',
|
|
|
|
|
viewBtnText: '详情',
|
|
|
|
|
labelWidth: 120,
|
|
|
|
|
menuWidth: 100,
|
|
|
|
|
dialogWidth: 640,
|
|
|
|
|
dialogClickModal: false,
|
|
|
|
|
searchEnter: true,
|
|
|
|
|
excelBtn: false,
|
|
|
|
|
filterBtn: true,
|
|
|
|
|
searchShowBtn: false,
|
|
|
|
|
columnSort: true,
|
|
|
|
|
excelBtn: true,
|
|
|
|
|
columnSort: true,
|
|
|
|
|
showOverflowTooltip: true,
|
|
|
|
|
gridBtn: false,
|
|
|
|
|
searchLabelPosition: 'left',
|
|
|
|
|
searchGutter: 24,
|
|
|
|
|
searchSpan: 6,
|
|
|
|
|
menuAlign: 'left',
|
|
|
|
|
gridBtn: false,
|
|
|
|
|
searchMenuPosition: 'right',
|
|
|
|
|
addBtnIcon: ' ',
|
|
|
|
|
viewBtnIcon: ' ',
|
|
|
|
|
delBtnIcon: ' ',
|
|
|
|
|
editBtnIcon: ' ',
|
|
|
|
|
header: false,
|
|
|
|
|
menu: false,
|
|
|
|
|
align: 'center',
|
|
|
|
|
column: [
|
|
|
|
|
{
|
|
|
|
|
label: '部件号',
|
|
|
|
|
prop: 'bpartCode',
|
|
|
|
|
sortable: true,
|
|
|
|
|
filter: true,
|
|
|
|
|
span: 24,
|
|
|
|
|
search: false,
|
|
|
|
|
headerAlign: 'center',
|
|
|
|
|
align: 'center',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '子件号',
|
|
|
|
|
prop: 'zpartCode',
|
|
|
|
|
sortable: true,
|
|
|
|
|
filter: true,
|
|
|
|
|
span: 24,
|
|
|
|
|
search: false,
|
|
|
|
|
headerAlign: 'center',
|
|
|
|
|
align: 'center',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: '子件名称',
|
|
|
|
|
prop: 'zpartName',
|
|
|
|
|
sortable: true,
|
|
|
|
|
filter: true,
|
|
|
|
|
span: 24,
|
|
|
|
|
search: false,
|
|
|
|
|
headerAlign: 'center',
|
|
|
|
|
align: 'center',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
isSubOpen: false,
|
|
|
|
|
isComponentOpen: false,
|
|
|
|
|
data: [],
|
|
|
|
|
dataTree: [],
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
methods: {
|
|
|
|
|
// 点击子件中的部件号 跳转到部件树
|
|
|
|
|
linkToPartTree(row) {
|
|
|
|
|
this.isComponentOpen = true;
|
|
|
|
|
this.isSubOpen = false;
|
|
|
|
|
getDsPartTree({ partCode: row.bpartCode, zPartCode: '' }).then(res => {
|
|
|
|
|
let resData = res.data.data;
|
|
|
|
|
let arr = JSON.parse(JSON.stringify(resData).replace(/partName/g, 'name'));
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.createBarChart(arr);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
searchFn() {
|
|
|
|
|
if (this.form.zijian != '') {
|
|
|
|
|
this.isComponentOpen = false;
|
|
|
|
|
this.isSubOpen = true;
|
|
|
|
|
getSinteringPart({ bPartCode: this.form.bujian, zPartCode: this.form.zijian }).then(res => {
|
|
|
|
|
this.data = res.data.data;
|
|
|
|
|
});
|
|
|
|
|
} else if (this.form.bujian != '') {
|
|
|
|
|
this.isComponentOpen = true;
|
|
|
|
|
this.isSubOpen = false;
|
|
|
|
|
getDsPartTree({ partCode: this.form.bujian, zPartCode: this.form.zijian }).then(res => {
|
|
|
|
|
let resData = res.data.data;
|
|
|
|
|
this.dataTree = res.data.data;
|
|
|
|
|
let arr = JSON.parse(JSON.stringify(resData).replace(/partName/g, 'name'));
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
this.createBarChart(arr);
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (this.form.zijian == '' && this.form.bujian == '') {
|
|
|
|
|
this.isSubOpen = false;
|
|
|
|
|
this.isComponentOpen = false;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// 获取子件列表
|
|
|
|
|
|
|
|
|
|
resetFn() {
|
|
|
|
|
this.form.zijian = '';
|
|
|
|
|
this.form.bujian = '';
|
|
|
|
|
this.isSubOpen = false;
|
|
|
|
|
this.isComponentOpen = false;
|
|
|
|
|
},
|
|
|
|
|
getTextWidth(text, fontSize = 14) {
|
|
|
|
|
// 中文字符宽度≈fontSize,英文字符≈fontSize/2,加额外内边距
|
|
|
|
|
const cnChar = text.replace(/[a-zA-Z0-9]/g, '').length;
|
|
|
|
|
const enChar = text.length - cnChar;
|
|
|
|
|
return cnChar * fontSize + enChar * (fontSize / 2) + 20; // +20 内边距
|
|
|
|
|
},
|
|
|
|
|
// 图表
|
|
|
|
|
createBarChart(value) {
|
|
|
|
|
const mapBoxEchart = this.$echarts.init(this.$refs.lineChart);
|
|
|
|
|
const option = {
|
|
|
|
|
series: [
|
|
|
|
|
{
|
|
|
|
|
roam: true,
|
|
|
|
|
type: 'tree',
|
|
|
|
|
data: value || [],
|
|
|
|
|
top: '20%',
|
|
|
|
|
left: '7%',
|
|
|
|
|
bottom: '20%',
|
|
|
|
|
right: '20%',
|
|
|
|
|
expandAndCollapse: false,
|
|
|
|
|
animationDuration: 550,
|
|
|
|
|
animationDurationUpdate: 750,
|
|
|
|
|
orient: 'vertical',
|
|
|
|
|
symbol: 'roundRect',
|
|
|
|
|
itemStyle: {
|
|
|
|
|
color: '#284c89',
|
|
|
|
|
borderWidth: 2,
|
|
|
|
|
borderColor: '#fff',
|
|
|
|
|
borderRadius: 4, // 圆角半径,值越大圆角越明显
|
|
|
|
|
paddingLeft: 10,
|
|
|
|
|
},
|
|
|
|
|
// 动态计算节点大小:宽度=最长文本宽度,高度=行数*行高+内边距
|
|
|
|
|
symbolSize: (val, params) => {
|
|
|
|
|
// 容错:params为空/无name时给默认值
|
|
|
|
|
const nodeName = params?.name || '未知节点';
|
|
|
|
|
const childCount = params?.children?.length || 0;
|
|
|
|
|
const childText = `${childCount}个子件`;
|
|
|
|
|
const nodeQuota = nodeData?.quota !== undefined ? nodeData.quota : '';
|
|
|
|
|
|
|
|
|
|
// 计算文本宽度
|
|
|
|
|
const textWidth = Math.max(nodeName.length * 12, childText.length * 12) + 30;
|
|
|
|
|
// 动态计算行数
|
|
|
|
|
let lineCount = 2; // 默认 2 行(partCode + name)
|
|
|
|
|
if (nodeQuota !== '' && nodeQuota !== null) {
|
|
|
|
|
lineCount = 3; // 有 quota 时 3 行
|
|
|
|
|
}
|
|
|
|
|
// 计算高度:每行 20px + 上下内边距 20px
|
|
|
|
|
const height = lineCount * 20 + 10;
|
|
|
|
|
return [Math.max(textWidth, 100), height]; // 高度设为60px(适配两行文本)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
label: {
|
|
|
|
|
position: 'inside',
|
|
|
|
|
show: true,
|
|
|
|
|
align: 'center',
|
|
|
|
|
verticalAlign: 'middle',
|
|
|
|
|
fontSize: 12,
|
|
|
|
|
lineHeight: 20,
|
|
|
|
|
color: '#fff',
|
|
|
|
|
formatter: params => {
|
|
|
|
|
const childText = params.data.quota >= 0 ? `${params.data.quota}个` : '';
|
|
|
|
|
// 去掉模板字符串缩进,用\n换行,避免多余空白
|
|
|
|
|
return `${params.data.partCode}\n${params.name}${
|
|
|
|
|
childText ? '\n' + childText : ''
|
|
|
|
|
}`;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
};
|
|
|
|
|
// 使用制定的配置项和数据显示图表
|
|
|
|
|
mapBoxEchart.setOption(option, true);
|
|
|
|
|
// // 窗口大小改变时,重新渲染图表
|
|
|
|
|
window.addEventListener(
|
|
|
|
|
'resize',
|
|
|
|
|
function () {
|
|
|
|
|
mapBoxEchart.resize();
|
|
|
|
|
},
|
|
|
|
|
200
|
|
|
|
|
);
|
|
|
|
|
// 4. 核心:监听点击事件,实现label跳转
|
|
|
|
|
mapBoxEchart.on('click', params => {
|
|
|
|
|
// 过滤条件:仅点击节点(label/text)时触发,排除连接线等
|
|
|
|
|
if (params.componentType === 'series' && params.seriesType === 'tree' && params.data) {
|
|
|
|
|
window.open(`${params.data.docLink}`, '_blank');
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.form-box {
|
|
|
|
|
// height: 700px;
|
|
|
|
|
height: calc(100vh - 60px - 40px - 10px - 90px - 31px);
|
|
|
|
|
}
|
|
|
|
|
.form-bom {
|
|
|
|
|
height: calc(100vh - 60px - 40px - 10px - 90px - 31px);
|
|
|
|
|
width: '100%';
|
|
|
|
|
background: #f0f2f5;
|
|
|
|
|
}
|
|
|
|
|
</style>
|