src/views/productionManagement/productStructure/DetailNew/MaterialCard.vue
@@ -1,24 +1,31 @@ <template> <div class="material-node"> <!-- 当前节点卡片 --> <div :class="['node-card', isRoot ? 'root-card' : 'child-card']"> <div :class="['node-card', isRoot ? 'root-card' : (row.nodeType === 'semiFinished' ? 'semi-finished-card' : 'child-card')]"> <div class="node-header"> <div class="node-label"> <el-tag :type="isRoot ? '' : 'success'" size="small" effect="dark"> {{ isRoot ? '成品' : '原料' }} <el-tag :type="isRoot ? '' : (row.nodeType === 'semiFinished' ? 'warning' : 'success')" size="small" effect="dark"> {{ isRoot ? '成品' : (row.nodeType === 'semiFinished' ? '半成品' : '原料') }} </el-tag> <span class="node-title">{{ row.productName || '未选择产品' }}</span> <span v-if="row.model" class="node-sub">规格: {{ row.model }}</span> <span v-if="row.unit" class="node-sub">单位: {{ row.unit }}</span> </div> <div class="node-actions"> <el-button v-if="editable" type="primary" <template v-if="editable && (isRoot || row.nodeType === 'semiFinished')"> <el-button type="primary" text size="small" @click="handleAdd"> + 添加{{ isRoot ? '原料' : '子级原料' }} @click="handleAdd('semiFinished')"> + 添加半成品 </el-button> <el-button type="primary" text size="small" @click="handleAdd('rawMaterial')"> + 添加原料 </el-button> </template> <el-button v-if="editable" type="danger" text @@ -107,7 +114,7 @@ :editable="editable" :process-options="processOptions" @remove="(id:string) => $emit('remove', id)" @add="(id:string) => $emit('add', id)" @add="(id:string, nodeType:string) => $emit('add', id, nodeType)" @select-product="(tempId: string, data: any) => $emit('selectProduct', tempId, data)" @process-change="(row: any, v: any) => $emit('processChange', row, v)" @quantity-change="$emit('quantityChange')" @@ -131,7 +138,7 @@ const emit = defineEmits<{ remove: [tempId: string] add: [tempId: string] add: [tempId: string, nodeType: string] selectProduct: [tempId: string, data: any] processChange: [row: any, value: any] quantityChange: [] @@ -143,8 +150,8 @@ emit('selectProduct', props.row.tempId, null) } const handleAdd = () => { emit('add', props.row.tempId) const handleAdd = (nodeType: string) => { emit('add', props.row.tempId, nodeType) } </script> @@ -174,6 +181,11 @@ background-color: #f0f9eb; } .semi-finished-card { border-left: 4px solid #e6a23c; background-color: #fdf6ec; } .node-header { display: flex; align-items: center; src/views/productionManagement/productStructure/DetailNew/index.vue
@@ -31,6 +31,9 @@ <el-tag type="" size="small" effect="dark">成品</el-tag> <span style="margin:0 4px">← 最上层(产出物)</span> <el-divider direction="vertical" /> <el-tag type="warning" size="small" effect="dark">半成品</el-tag> <span style="margin:0 4px">(可继续展开)</span> <el-divider direction="vertical" /> <span style="margin:0 4px">最下层(投入物)→</span> <el-tag type="success" size="small" effect="dark">原料</el-tag> </div> @@ -47,7 +50,7 @@ :editable="dataValue.isEdit" :process-options="dataValue.processOptions" @remove="(id: string) => removeItem(id)" @add="(id: string) => addChildItem(id)" @add="(id: string, nodeType: string) => addChildItem(id, nodeType)" @select-product="(tempId: string, _data: any) => { dataValue.currentRowName = tempId; dataValue.showProductDialog = true }" @process-change="(row: any, v: any) => handleProcessChange(row, v)" @quantity-change="handleUnitQuantityChange" @@ -183,12 +186,17 @@ item.operationName = processName; }; const normalizeTreeData = (items: any[]) => { const normalizeTreeData = (items: any[], depth: number = 0) => { items.forEach((item: any) => { item.tempId = item.tempId || item.id || `${Date.now()}_${Math.random()}`; syncProcessOperationFields(item); if (depth > 0 && !item.nodeType) { item.nodeType = Array.isArray(item.children) && item.children.length > 0 ? 'semiFinished' : 'rawMaterial'; } if (Array.isArray(item.children) && item.children.length > 0) { normalizeTreeData(item.children); normalizeTreeData(item.children, depth + 1); } }); }; @@ -520,7 +528,7 @@ }); }; const newChildNode = (parentItem: any) => ({ const newChildNode = (parentItem: any, nodeType: string = 'rawMaterial') => ({ parentId: parentItem.id || "", parentTempId: parentItem.tempId || "", productName: "", @@ -534,6 +542,7 @@ unitQuantity: 1, demandedQuantity: 0, unit: "", nodeType, children: [], tempId: new Date().getTime(), }); @@ -542,12 +551,12 @@ dataValue.dataList.push(newChildNode({ id: "", tempId: "" })); }; const addChildItem = (parentTempId: string) => { const addChildItem = (parentTempId: string, nodeType: string = 'rawMaterial') => { const addToItem = (items: any[]): boolean => { for (const item of items) { if (item.tempId === parentTempId) { if (!item.children) item.children = []; item.children.push(newChildNode(item)); item.children.push(newChildNode(item, nodeType)); recalculateDemandedQuantities(); return true; }