|
@@ -448,6 +448,7 @@
|
|
v-model="row.materialCode"
|
|
v-model="row.materialCode"
|
|
placeholder="请输入物料编码"
|
|
placeholder="请输入物料编码"
|
|
style="width: 100%"
|
|
style="width: 100%"
|
|
|
|
+ :disabled="isMaterialDisabled(row)"
|
|
/>
|
|
/>
|
|
<span v-else>{{ row.materialCode }}</span>
|
|
<span v-else>{{ row.materialCode }}</span>
|
|
</template>
|
|
</template>
|
|
@@ -499,29 +500,18 @@
|
|
<el-table-column label="单价(CNY/元)" align="center" prop="unitPrice" :formatter="erpPriceTableColumnFormatter" width="120px">
|
|
<el-table-column label="单价(CNY/元)" align="center" prop="unitPrice" :formatter="erpPriceTableColumnFormatter" width="120px">
|
|
<template #default="{ row }">
|
|
<template #default="{ row }">
|
|
<div class="unit-price-container">
|
|
<div class="unit-price-container">
|
|
- <!--
|
|
|
|
- <el-tooltip
|
|
|
|
- v-if="row.isNew || !row.unitPrice || row.unitPrice === 0"
|
|
|
|
- effect=""
|
|
|
|
- content=""
|
|
|
|
- placement=""
|
|
|
|
- :disabled="row.unitPrice > 0"
|
|
|
|
- > -->
|
|
|
|
- <el-input-number
|
|
|
|
- v-if="row.isNew || !row.unitPrice || row.unitPrice === 0"
|
|
|
|
- v-model="row.unitPrice"
|
|
|
|
- :precision="2"
|
|
|
|
- :min="0"
|
|
|
|
- :controls="false"
|
|
|
|
- style="width: 100%"
|
|
|
|
- class="unit-price-input"
|
|
|
|
- :class="{
|
|
|
|
- 'is-required-input': (row.isNew || !row.unitPrice || row.unitPrice === 0) && row.unitPrice <= 0
|
|
|
|
- }"
|
|
|
|
- :disabled="isMaterialDisabled(row)"
|
|
|
|
- />
|
|
|
|
- <!-- </el-tooltip> -->
|
|
|
|
- <span v-else class="unit-price-text">{{ row.unitPrice }}</span>
|
|
|
|
|
|
+ <el-input-number
|
|
|
|
+ v-model="row.unitPrice"
|
|
|
|
+ :precision="2"
|
|
|
|
+ :min="0"
|
|
|
|
+ :controls="false"
|
|
|
|
+ style="width: 100%"
|
|
|
|
+ class="unit-price-input"
|
|
|
|
+ :class="{
|
|
|
|
+ 'is-required-input': row.unitPrice <= 0
|
|
|
|
+ }"
|
|
|
|
+ :disabled="isMaterialDisabled(row)"
|
|
|
|
+ />
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table-column>
|
|
@@ -1311,6 +1301,11 @@ const handleAddMaterial = () => {
|
|
}
|
|
}
|
|
|
|
|
|
message.success('已新增空白物料记录,请填写相关信息');
|
|
message.success('已新增空白物料记录,请填写相关信息');
|
|
|
|
+
|
|
|
|
+ // 新增物料后重新计算费用
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ calculateTotalCost();
|
|
|
|
+ });
|
|
};
|
|
};
|
|
|
|
|
|
const openMaterialForm = (row: any) => {
|
|
const openMaterialForm = (row: any) => {
|
|
@@ -1337,8 +1332,12 @@ const selectChoose = (selectedMaterial) => {
|
|
|
|
|
|
// 避免重复添加
|
|
// 避免重复添加
|
|
processedMaterials.forEach(newMaterial => {
|
|
processedMaterials.forEach(newMaterial => {
|
|
|
|
+ const uniqueKey = `${newMaterial.deviceId}${bomNodeId.value}`;
|
|
|
|
+ if (!bomMaterialsMap.value[uniqueKey]) {
|
|
|
|
+ bomMaterialsMap.value[uniqueKey] = [];
|
|
|
|
+ }
|
|
// 检查是否已存在相同 工厂+成本中心+库存地点+bomNodeId + materialCode 的条目
|
|
// 检查是否已存在相同 工厂+成本中心+库存地点+bomNodeId + materialCode 的条目
|
|
- const isExist = materialList.value.some(item =>
|
|
|
|
|
|
+ const isExist = bomMaterialsMap.value[uniqueKey].some(item =>
|
|
item.bomNodeId === bomNodeId.value &&
|
|
item.bomNodeId === bomNodeId.value &&
|
|
item.materialCode === newMaterial.materialCode &&
|
|
item.materialCode === newMaterial.materialCode &&
|
|
item.factoryId === newMaterial.factoryId &&
|
|
item.factoryId === newMaterial.factoryId &&
|
|
@@ -1347,9 +1346,19 @@ const selectChoose = (selectedMaterial) => {
|
|
);
|
|
);
|
|
|
|
|
|
if (!isExist) {
|
|
if (!isExist) {
|
|
- materialList.value.push(newMaterial);
|
|
|
|
|
|
+ bomMaterialsMap.value[uniqueKey].push(newMaterial);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
+
|
|
|
|
+ // 同步到当前显示的 materialList(如果当前选中了该保养项)
|
|
|
|
+ if (currentBomItem.value && currentBomItem.value.bomNodeId === bomNodeId.value) {
|
|
|
|
+ materialList.value = bomMaterialsMap.value[`${currentBomItem.value.deviceId}${bomNodeId.value}`] || [];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 选择物料后立即计算费用
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ calculateTotalCost();
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
// 计算属性:判断是否需要显示运行时间周期列
|
|
// 计算属性:判断是否需要显示运行时间周期列
|
|
@@ -1368,25 +1377,57 @@ const handleView = (row: IotMainWorkOrderBomVO) => {
|
|
|
|
|
|
// 计算保养金额
|
|
// 计算保养金额
|
|
const calculateTotalCost = () => {
|
|
const calculateTotalCost = () => {
|
|
- // 物料总金额 = ∑(单价 * 消耗数量)
|
|
|
|
- const materialTotal = materialList.value.reduce((sum, item) => {
|
|
|
|
- const price = Number(item.unitPrice) || 0
|
|
|
|
- const quantity = Number(item.quantity) || 0
|
|
|
|
- return sum + (price * quantity)
|
|
|
|
- }, 0)
|
|
|
|
|
|
+ try {
|
|
|
|
+ // 创建保养项ID到消耗规则的映射
|
|
|
|
+ const ruleMap = new Map<number, number>();
|
|
|
|
+ list.value.forEach(item => {
|
|
|
|
+ ruleMap.set(item.bomNodeId, item.rule);
|
|
|
|
+ });
|
|
|
|
|
|
- // 保养 = 物料总金额
|
|
|
|
- formData.value.cost = (materialTotal).toFixed(2)
|
|
|
|
|
|
+ // 从 bomMaterialsMap 中获取所有保养项的所有物料
|
|
|
|
+ let allMaterials = [];
|
|
|
|
+ for (const key in bomMaterialsMap.value) {
|
|
|
|
+ allMaterials = allMaterials.concat(bomMaterialsMap.value[key]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 物料总金额 = ∑(单价 * 消耗数量)
|
|
|
|
+ const materialTotal = allMaterials.reduce((sum, item) => {
|
|
|
|
+ // 获取物料所属保养项的消耗规则
|
|
|
|
+ const rule = ruleMap.get(item.bomNodeId);
|
|
|
|
+
|
|
|
|
+ // 如果保养项设置为不消耗物料(rule=1),跳过计算
|
|
|
|
+ if (rule === 1) return sum;
|
|
|
|
+
|
|
|
|
+ const price = Number(item.unitPrice) || 0
|
|
|
|
+ const quantity = Number(item.quantity) || 0
|
|
|
|
+ return sum + (price * quantity)
|
|
|
|
+ }, 0)
|
|
|
|
+
|
|
|
|
+ // 保养费用 = 物料总金额
|
|
|
|
+ formData.value.cost = (materialTotal).toFixed(2)
|
|
|
|
+
|
|
|
|
+ console.log('计算保养费用:', {
|
|
|
|
+ 物料总数: allMaterials.length,
|
|
|
|
+ 参与计算的物料数: allMaterials.filter(item => {
|
|
|
|
+ const rule = ruleMap.get(item.bomNodeId);
|
|
|
|
+ return rule !== 1; // 过滤掉不消耗物料的项
|
|
|
|
+ }).length,
|
|
|
|
+ 总金额: materialTotal
|
|
|
|
+ });
|
|
|
|
+ } catch (error) {
|
|
|
|
+ console.error('计算保养费用错误:', error);
|
|
|
|
+ formData.value.cost = '0.00';
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-// 监听物料列表变化
|
|
|
|
|
|
+// 同时监听物料列表和保养项列表变化
|
|
watch(
|
|
watch(
|
|
- () => materialList.value,
|
|
|
|
|
|
+ [() => materialList.value, () => list.value],
|
|
() => {
|
|
() => {
|
|
- calculateTotalCost()
|
|
|
|
|
|
+ calculateTotalCost();
|
|
},
|
|
},
|
|
{ deep: true }
|
|
{ deep: true }
|
|
-)
|
|
|
|
|
|
+);
|
|
|
|
|
|
const handleInput = (value, obj) => {
|
|
const handleInput = (value, obj) => {
|
|
// 1. 过滤非法字符(只允许数字和小数点)
|
|
// 1. 过滤非法字符(只允许数字和小数点)
|
|
@@ -1481,20 +1522,27 @@ const getMaterialCount = (bomNodeId: number) => {
|
|
const handleDeleteMaterialInTable = (material) => {
|
|
const handleDeleteMaterialInTable = (material) => {
|
|
// 确认删除对话框
|
|
// 确认删除对话框
|
|
message.confirm('确认删除该物料吗?', { title: '提示' }).then(() => {
|
|
message.confirm('确认删除该物料吗?', { title: '提示' }).then(() => {
|
|
- let targetBomNodeId = material.bomNodeId;
|
|
|
|
-
|
|
|
|
- // 如果没有选中保养项(显示所有物料),需要根据物料信息找到对应的bomNodeId
|
|
|
|
- if (showAllMaterials.value && !currentBomItem.value) {
|
|
|
|
- // 从物料中提取bomNodeId
|
|
|
|
- targetBomNodeId = material.bomNodeId;
|
|
|
|
- } else if (currentBomItem.value) {
|
|
|
|
- // 使用当前选中保养项的bomNodeId
|
|
|
|
- targetBomNodeId = currentBomItem.value.bomNodeId;
|
|
|
|
|
|
+ const targetBomNodeId = material.bomNodeId;
|
|
|
|
+ const uniqueKey = `${material.deviceId}${targetBomNodeId}`;
|
|
|
|
+
|
|
|
|
+ // 从 bomMaterialsMap 中删除
|
|
|
|
+ if (bomMaterialsMap.value[uniqueKey]) {
|
|
|
|
+ const mapIndex = bomMaterialsMap.value[uniqueKey].findIndex(item =>
|
|
|
|
+ (item.isNew && item.tempId === material.tempId) ||
|
|
|
|
+ (!item.isNew &&
|
|
|
|
+ item.factoryId === material.factoryId &&
|
|
|
|
+ item.costCenterId === material.costCenterId &&
|
|
|
|
+ item.storageLocationId === material.storageLocationId &&
|
|
|
|
+ item.materialCode === material.materialCode)
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ if (mapIndex !== -1) {
|
|
|
|
+ bomMaterialsMap.value[uniqueKey].splice(mapIndex, 1);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
- // 从materialList中删除
|
|
|
|
|
|
+ // 从 materialList 中删除
|
|
const index = materialList.value.findIndex(item =>
|
|
const index = materialList.value.findIndex(item =>
|
|
- // 对于新记录,使用tempId进行比较;对于已有记录,使用原有逻辑
|
|
|
|
(item.isNew && item.tempId === material.tempId) ||
|
|
(item.isNew && item.tempId === material.tempId) ||
|
|
(!item.isNew &&
|
|
(!item.isNew &&
|
|
item.bomNodeId === targetBomNodeId &&
|
|
item.bomNodeId === targetBomNodeId &&
|
|
@@ -1506,27 +1554,11 @@ const handleDeleteMaterialInTable = (material) => {
|
|
|
|
|
|
if (index !== -1) {
|
|
if (index !== -1) {
|
|
materialList.value.splice(index, 1);
|
|
materialList.value.splice(index, 1);
|
|
-
|
|
|
|
- // 同时从bomMaterialsMap中删除
|
|
|
|
- const uniqueKey = `${material.deviceId}${targetBomNodeId}`;
|
|
|
|
- if (bomMaterialsMap.value[uniqueKey]) {
|
|
|
|
- const mapIndex = bomMaterialsMap.value[uniqueKey].findIndex(item =>
|
|
|
|
- (item.isNew && item.tempId === material.tempId) ||
|
|
|
|
- (!item.isNew &&
|
|
|
|
- item.factoryId === material.factoryId &&
|
|
|
|
- item.costCenterId === material.costCenterId &&
|
|
|
|
- item.storageLocationId === material.storageLocationId &&
|
|
|
|
- item.materialCode === material.materialCode)
|
|
|
|
- );
|
|
|
|
- if (mapIndex !== -1) {
|
|
|
|
- bomMaterialsMap.value[uniqueKey].splice(mapIndex, 1);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- message.success('物料删除成功');
|
|
|
|
- } else {
|
|
|
|
- message.error('未找到要删除的物料');
|
|
|
|
}
|
|
}
|
|
|
|
+ // 删除物料后重新计算费用
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ calculateTotalCost();
|
|
|
|
+ });
|
|
}).catch(() => {
|
|
}).catch(() => {
|
|
// 用户取消删除
|
|
// 用户取消删除
|
|
});
|
|
});
|
|
@@ -2160,7 +2192,6 @@ onMounted(async () => {
|
|
projectDepartment: material.storageLocation, // storageLocation -> projectDepartment
|
|
projectDepartment: material.storageLocation, // storageLocation -> projectDepartment
|
|
totalInventoryQuantity: material.stockQuantity // stockQuantity -> totalInventoryQuantity
|
|
totalInventoryQuantity: material.stockQuantity // stockQuantity -> totalInventoryQuantity
|
|
}));
|
|
}));
|
|
-
|
|
|
|
// 存储到映射表中
|
|
// 存储到映射表中
|
|
bomMaterialsMap.value[uniqueKey] = mappedMaterials;
|
|
bomMaterialsMap.value[uniqueKey] = mappedMaterials;
|
|
}
|
|
}
|
|
@@ -2199,15 +2230,38 @@ onMounted(async () => {
|
|
// 查询当前保养工单已经关联的所有物料
|
|
// 查询当前保养工单已经关联的所有物料
|
|
const materials = await IotMainWorkOrderBomMaterialApi.getWorkOrderBomMaterials(queryParams);
|
|
const materials = await IotMainWorkOrderBomMaterialApi.getWorkOrderBomMaterials(queryParams);
|
|
materialList.value = []
|
|
materialList.value = []
|
|
- if (Array.isArray(materials)) {
|
|
|
|
- materialList.value = materials
|
|
|
|
- .map(item => ({
|
|
|
|
- ...item,
|
|
|
|
- }))
|
|
|
|
|
|
+ // 修改:如果有已关联的物料,使用接口返回的数据覆盖默认数据
|
|
|
|
+ if (Array.isArray(materials) && materials.length > 0) {
|
|
|
|
+ // materialList.value = materials;
|
|
|
|
+
|
|
|
|
+ // 同时更新 bomMaterialsMap
|
|
|
|
+ materials.forEach(material => {
|
|
|
|
+ const uniqueKey = `${material.deviceId}${material.bomNodeId}`;
|
|
|
|
+ if (!bomMaterialsMap.value[uniqueKey]) {
|
|
|
|
+ bomMaterialsMap.value[uniqueKey] = [];
|
|
|
|
+ }
|
|
|
|
+ // 避免重复添加
|
|
|
|
+ const existingIndex = bomMaterialsMap.value[uniqueKey].findIndex(item =>
|
|
|
|
+ item.materialCode === material.materialCode &&
|
|
|
|
+ item.factoryId === material.factoryId &&
|
|
|
|
+ item.costCenterId === material.costCenterId &&
|
|
|
|
+ item.storageLocationId === material.storageLocationId
|
|
|
|
+ );
|
|
|
|
+ if (existingIndex === -1) {
|
|
|
|
+ bomMaterialsMap.value[uniqueKey].push(material);
|
|
|
|
+ } else {
|
|
|
|
+ // 如果已存在,更新数据(使用接口返回的最新数据)
|
|
|
|
+ bomMaterialsMap.value[uniqueKey][existingIndex] = material;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
}
|
|
}
|
|
if (list.value.length > 0) {
|
|
if (list.value.length > 0) {
|
|
handleBomItemClick(list.value[0]);
|
|
handleBomItemClick(list.value[0]);
|
|
}
|
|
}
|
|
|
|
+ // 页面初始化完成后立即计算费用
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ calculateTotalCost();
|
|
|
|
+ });
|
|
} catch (error) {
|
|
} catch (error) {
|
|
console.error('数据加载失败:', error)
|
|
console.error('数据加载失败:', error)
|
|
message.error('数据加载失败,请重试')
|
|
message.error('数据加载失败,请重试')
|
|
@@ -2242,6 +2296,11 @@ const handleBomItemClick = (item) => {
|
|
|
|
|
|
// 更新物料列表
|
|
// 更新物料列表
|
|
materialList.value = bomMaterialsMap.value[uniqueKey] || [];
|
|
materialList.value = bomMaterialsMap.value[uniqueKey] || [];
|
|
|
|
+
|
|
|
|
+ // 切换保养项时重新计算费用
|
|
|
|
+ nextTick(() => {
|
|
|
|
+ calculateTotalCost();
|
|
|
|
+ });
|
|
}
|
|
}
|
|
|
|
|
|
// 为表格行添加点击事件处理
|
|
// 为表格行添加点击事件处理
|