From 0ede6469f1507b81dd827efc36590cfd9773ebde Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期四, 21 五月 2026 09:36:41 +0800
Subject: [PATCH] 生产订单增加附件的查看
---
src/views/productionManagement/processRoute/processRouteItem/index.vue | 304 +++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 275 insertions(+), 29 deletions(-)
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index fd1a6a8..3c52410 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -47,16 +47,45 @@
<span class="info-value">{{ routeInfo.quantity || '-' }}</span>
</div>
</div>
- <div class="info-item full-width"
- v-if="routeInfo.description">
+ <div class="info-item">
<div class="info-label-wrapper">
- <span class="info-label">鎻忚堪</span>
+ <span class="info-label">澶囨敞</span>
</div>
<div class="info-value-wrapper">
<span class="info-value">{{ routeInfo.description }}</span>
</div>
</div>
</div>
+ </el-card>
+ <!-- 闄勪欢妯″潡 -->
+ <div v-if="pageType === 'order'"
+ class="section-header">
+ <div class="section-title">闄勪欢</div>
+ </div>
+ <el-card v-if="pageType === 'order'"
+ class="attachment-card"
+ shadow="hover"
+ style="margin-top: 10px; margin-bottom: 20px;">
+ <el-table :data="attachmentTableData"
+ border
+ class="attachment-table">
+ <el-table-column label="闄勪欢鍚嶇О"
+ prop="originalFilename"
+ show-overflow-tooltip />
+ <el-table-column fixed="right"
+ label="鎿嶄綔"
+ width="200"
+ align="center">
+ <template #default="scope">
+ <el-button link
+ type="primary"
+ size="small"
+ @click="downloadAttachmentFile(scope.row.downloadURL)">
+ 涓嬭浇
+ </el-button>
+ </template>
+ </el-table-column>
+ </el-table>
</el-card>
<!-- 琛ㄦ牸瑙嗗浘 -->
<div v-if="viewMode === 'table'"
@@ -68,7 +97,8 @@
style="margin-right: 10px;">
鍗$墖瑙嗗浘
</el-button>
- <el-button type="primary"
+ <el-button v-if="editable"
+ type="primary"
@click="handleAdd">鏂板</el-button>
</div>
</div>
@@ -110,6 +140,13 @@
<el-table-column label="鍗曚綅"
prop="unit"
width="100" />
+ <el-table-column label="璁¤垂绫诲瀷"
+ prop="type"
+ width="100">
+ <template #default="scope">
+ {{scope.row.type==0 ? "璁℃椂" : "璁′欢"}}
+ </template>
+ </el-table-column>
<el-table-column label="鏄惁璐ㄦ"
prop="isQuality"
width="100">
@@ -133,12 +170,12 @@
link
size="small"
@click="handleEdit(scope.row)"
- :disabled="scope.row.isComplete">缂栬緫</el-button>
+ :disabled="scope.row.isComplete || !editable">缂栬緫</el-button>
<el-button type="danger"
link
size="small"
@click="handleDelete(scope.row)"
- :disabled="scope.row.isComplete">鍒犻櫎</el-button>
+ :disabled="scope.row.isComplete || !editable">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
@@ -152,7 +189,8 @@
style="margin-right: 10px;">
琛ㄦ牸瑙嗗浘
</el-button>
- <el-button type="primary"
+ <el-button v-if="editable"
+ type="primary"
@click="handleAdd">鏂板</el-button>
</div>
</div>
@@ -179,12 +217,16 @@
{{ item.model }}
<!-- <span v-if="item.unit" class="product-unit">{{ item.unit }}</span> -->
</div>
+ <el-tag class="product-tag"
+ :type="item.type == 1 ? 'primary' : 'success'"
+ style="margin-left: 8px;">{{ item.type==0?'璁℃椂':'璁′欢' }}</el-tag>
<el-tag type="primary"
class="product-tag"
+ style="margin-left: 8px;"
v-if="item.isQuality">璐ㄦ</el-tag>
<el-tag type="primary"
class="product-tag"
- :style="item.isQuality?'margin-left:8px':''"
+ style="margin-left: 8px;"
v-if="item.isProduction">鐢熶骇</el-tag>
</div>
<div v-else
@@ -196,7 +238,7 @@
link
size="small"
@click="handleEdit(item)"
- :disabled="item.isComplete">缂栬緫</el-button>
+ :disabled="item.isComplete || !editable">缂栬緫</el-button>
<el-button type="info"
link
size="small"
@@ -205,7 +247,7 @@
link
size="small"
@click="handleDelete(item)"
- :disabled="item.isComplete">鍒犻櫎</el-button>
+ :disabled="item.isComplete || !editable">鍒犻櫎</el-button>
</div>
</div>
</div>
@@ -216,7 +258,7 @@
style="margin-top: 20px;">
<div class="section-title">BOM 缁撴瀯</div>
<div class="section-actions"
- v-if="pageType === 'order'">
+ v-if="pageType === 'order' && editable">
<el-button v-if="!bomDataValue.isEdit"
type="primary"
@click="bomDataValue.isEdit = true">
@@ -302,7 +344,7 @@
:step="1"
controls-position="right"
style="width: 100%"
- @change="handleUnitQuantityChange(row)"
+ @change="handleUnitQuantityChange"
:disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)" />
</el-form-item>
</template>
@@ -320,7 +362,7 @@
:step="1"
controls-position="right"
style="width: 100%"
- :disabled="!bomDataValue.isEdit || bomDataValue.dataList.some(item => (item).tempId === row.tempId)" />
+ :disabled="true" />
</el-form-item>
</template>
</el-table-column>
@@ -369,6 +411,18 @@
v-model="bomDataValue.showProductDialog"
:single="true"
@confirm="handleBomProduct" />
+ <!-- 涓婁紶缁勪欢寮圭獥 -->
+ <el-dialog v-model="uploadDialogVisible"
+ title="涓婁紶闄勪欢"
+ width="50%"
+ @close="closeAttachmentUpload">
+ <AttachmentUpload v-model:file-list="newFileList" />
+ <template #footer>
+ <el-button @click="saveAttachmentUpload"
+ type="primary">淇濆瓨</el-button>
+ <el-button @click="closeAttachmentUpload">鍏抽棴</el-button>
+ </template>
+ </el-dialog>
<!-- 鏂板/缂栬緫寮圭獥 -->
<el-dialog v-model="dialogVisible"
:title="operationType === 'add' ? '鏂板宸ヨ壓璺嚎椤圭洰' : '缂栬緫宸ヨ壓璺嚎椤圭洰'"
@@ -422,6 +476,13 @@
v-else>
<span>{{ form.unit }}</span>
</el-form-item>
+ <el-form-item label="璁¤垂绫诲瀷"
+ prop="type">
+ <el-radio-group v-model="form.type">
+ <el-radio :label="0">璁℃椂</el-radio>
+ <el-radio :label="1">璁′欢</el-radio>
+ </el-radio-group>
+ </el-form-item>
<el-form-item label="鏄惁璐ㄦ"
prop="isQuality">
<el-switch v-model="form.isQuality"
@@ -447,7 +508,6 @@
@confirm="handleProductSelect"
single />
<!-- 鍙傛暟鍒楄〃瀵硅瘽妗� -->
- <!-- :editable="!routeInfo.status" -->
<ProcessParamListDialog v-model="showParamListDialog"
:title="`${currentProcess ? (currentProcess.processName || currentProcess.technologyOperationName || currentProcess.operationName) : ''} - 鍙傛暟鍒楄〃`"
:route-id="routeId"
@@ -455,6 +515,7 @@
:process="currentProcess"
:page-type="pageType"
:param-list="paramList"
+ :editable="editable"
@getsyncProcessParamItem="getsyncProcessParamItem"
@refresh="refreshParamList" />
</div>
@@ -498,6 +559,12 @@
queryList2,
add2,
} from "@/api/productionManagement/productStructure.js";
+ import AttachmentUpload from "@/components/AttachmentUpload/file/index.vue";
+ import {
+ attachmentList,
+ deleteAttachment,
+ createAttachment,
+ } from "@/api/basicData/storageAttachment.js";
import { useRoute } from "vue-router";
import { ElMessageBox, ElMessage } from "element-plus";
@@ -509,6 +576,8 @@
const routeId = computed(() => route.query.id);
const orderId = computed(() => route.query.orderId);
const pageType = computed(() => route.query.type);
+ const editable = computed(() => route.query.editable !== "false");
+ const technologyRoutingId = computed(() => route.query.technologyRoutingId);
const tableLoading = ref(false);
const tableData = ref([]);
@@ -527,7 +596,66 @@
bomNo: "",
description: "",
quantity: 0,
+ technologyRoutingId: "",
});
+
+ // 闄勪欢鐩稿叧
+ const attachmentTableData = ref([]);
+ const uploadDialogVisible = ref(false);
+ const newFileList = ref([]);
+
+ const getAttachmentList = () => {
+ if (!technologyRoutingId.value) return;
+ attachmentList({
+ recordType: "technology_routing",
+ recordId: technologyRoutingId.value,
+ }).then(res => {
+ attachmentTableData.value = (res && res.data) || [];
+ });
+ };
+
+ const handleUploadAttachment = () => {
+ uploadDialogVisible.value = true;
+ };
+
+ const saveAttachmentUpload = async () => {
+ if (newFileList.value.length > 0) {
+ createAttachment({
+ application: "file",
+ recordType: "technology_routing",
+ recordId: technologyRoutingId.value,
+ storageBlobDTOs: [...newFileList.value, ...attachmentTableData.value],
+ })
+ .then(res => {
+ if (res && res.code === 200) {
+ proxy?.$modal?.msgSuccess("涓婁紶鎴愬姛");
+ newFileList.value = [];
+ getAttachmentList();
+ }
+ })
+ .finally(() => {
+ uploadDialogVisible.value = false;
+ });
+ }
+ };
+
+ const closeAttachmentUpload = () => {
+ newFileList.value = [];
+ uploadDialogVisible.value = false;
+ };
+
+ const handleDeleteAttachment = async row => {
+ deleteAttachment([row.storageAttachmentId]).then(res => {
+ if (res && res.code === 200) {
+ proxy?.$modal?.msgSuccess("鍒犻櫎鎴愬姛");
+ getAttachmentList();
+ }
+ });
+ };
+
+ const downloadAttachmentFile = url => {
+ window.open(url, "_blank");
+ };
const processOptions = ref([]);
const showProductSelectDialog = ref(false);
@@ -555,6 +683,7 @@
model: "",
unit: "",
isQuality: false,
+ type: 0,
isProduction: false,
});
@@ -658,6 +787,7 @@
bomId: route.query.bomId || "",
description: route.query.description || "",
quantity: route.query.quantity || 0,
+ technologyRoutingId: route.query.technologyRoutingId || "",
status: !(route.query.status == 1 || route.query.status === "false"),
};
bomTableData.value[0].productName = routeInfo.value.productName;
@@ -684,6 +814,7 @@
model: row.model || "",
unit: row.unit || "",
isQuality: row.isQuality,
+ type: row.type || 0,
isProduction: row.isProduction,
};
dialogVisible.value = true;
@@ -755,6 +886,7 @@
operationName: getProcessName(form.value.technologyOperationId),
productModelId: form.value.productModelId,
isQuality: form.value.isQuality,
+ type: form.value.type,
isProduction: form.value.isProduction,
dragSort,
})
@@ -763,6 +895,7 @@
technologyOperationId: form.value.technologyOperationId,
productModelId: form.value.productModelId,
isQuality: form.value.isQuality,
+ type: form.value.type,
isProduction: form.value.isProduction,
dragSort,
});
@@ -790,6 +923,7 @@
operationName: getProcessName(form.value.technologyOperationId),
productModelId: form.value.productModelId,
isQuality: form.value.isQuality,
+ type: form.value.type,
isProduction: form.value.isProduction,
})
: addOrUpdateProcessRouteItem1({
@@ -798,6 +932,7 @@
productModelId: form.value.productModelId,
id: form.value.id,
isQuality: form.value.isQuality,
+ type: form.value.type,
isProduction: form.value.isProduction,
});
@@ -829,6 +964,7 @@
model: "",
unit: "",
isQuality: false,
+ type: 0,
isProduction: false,
};
formRef.value?.resetFields();
@@ -878,6 +1014,7 @@
// 鍒濆鍖栨嫋鎷芥帓搴�
const initSortable = () => {
destroySortable();
+ if (!editable.value) return;
if (viewMode.value === "table") {
// 琛ㄦ牸瑙嗗浘鐨勬嫋鎷芥帓搴�
@@ -1060,18 +1197,97 @@
}
});
};
+
+ const toQuantityNumber = value => {
+ const numberValue = Number(value);
+ if (!Number.isFinite(numberValue)) {
+ return 0;
+ }
+ return Number(numberValue.toFixed(2));
+ };
+
+ const syncDemandedQuantityTree = (items, parentDemandedQuantity = null) => {
+ items.forEach(item => {
+ if (parentDemandedQuantity !== null) {
+ item.demandedQuantity = toQuantityNumber(
+ parentDemandedQuantity * toQuantityNumber(item.unitQuantity)
+ );
+ }
+
+ if (Array.isArray(item.children) && item.children.length > 0) {
+ syncDemandedQuantityTree(
+ item.children,
+ toQuantityNumber(item.demandedQuantity)
+ );
+ }
+ });
+ };
+
+ const recalculateDemandedQuantities = () => {
+ if (pageType.value !== "order") {
+ return;
+ }
+
+ const rootDemandedQuantity = routeInfo.value.quantity;
+ if (
+ rootDemandedQuantity === undefined ||
+ rootDemandedQuantity === null ||
+ rootDemandedQuantity === ""
+ ) {
+ syncDemandedQuantityTree(bomDataValue.value.dataList);
+ return;
+ }
+
+ syncDemandedQuantityTree(
+ bomDataValue.value.dataList,
+ toQuantityNumber(rootDemandedQuantity)
+ );
+ };
+
const processChange = value => {
processOptions.value.forEach(item => {
if (item.id == value) {
form.value.isQuality = item.isQuality;
+ form.value.type = item.type || 0;
form.value.isProduction = item.isProduction;
}
});
};
+ const findSiblings = (items, tempId) => {
+ if (!items || items.length === 0) return null;
+ // 妫�鏌ュ綋鍓嶅眰绾�
+ if (items.some(item => item.tempId === tempId)) {
+ return items;
+ }
+ // 閫掑綊鏌ユ壘瀛愮骇
+ for (const item of items) {
+ if (item.children && item.children.length > 0) {
+ const result = findSiblings(item.children, tempId);
+ if (result) return result;
+ }
+ }
+ return null;
+ };
+
const handleBomProcessChange = (row, value) => {
row.processId = value || "";
syncProcessOperationFields(row);
+
+ // 妫�鏌ュ悓涓�灞傜骇鏄惁宸茬粡鏈夊叾浠栦笉鍚岀殑宸ュ簭琚�変腑
+ const siblings = findSiblings(bomDataValue.value.dataList, row.tempId);
+ if (siblings && value) {
+ const hasDifferentProcess = siblings.some(sibling => {
+ return (
+ sibling.tempId !== row.tempId &&
+ sibling.processId &&
+ sibling.processId !== value
+ );
+ });
+ if (hasDifferentProcess) {
+ ElMessage.warning("鍚屼竴灞傜骇宸插瓨鍦ㄤ笉鍚岀殑宸ュ簭锛岃鍏堢粺涓�宸ュ簭鍚庡啀杩涜淇敼");
+ }
+ }
};
const openBomDialog = tempId => {
@@ -1087,6 +1303,7 @@
);
bomDataValue.value.dataList = data || [];
normalizeTreeData(bomDataValue.value.dataList);
+ recalculateDemandedQuantities();
} catch (err) {
console.error("鑾峰彇BOM鏁版嵁澶辫触锛�", err);
}
@@ -1182,10 +1399,8 @@
});
};
- const handleUnitQuantityChange = row => {
- if (routeInfo.value.quantity && routeInfo.value.quantity !== 0) {
- row.demandedQuantity = (row.unitQuantity || 0) * routeInfo.value.quantity;
- }
+ const handleUnitQuantityChange = () => {
+ recalculateDemandedQuantities();
};
const addchildItem = (item, tempId) => {
@@ -1206,14 +1421,12 @@
"",
operationName: "",
unitQuantity: 1,
- demandedQuantity:
- routeInfo.value.quantity && routeInfo.value.quantity !== 0
- ? 1 * routeInfo.value.quantity
- : 0,
+ demandedQuantity: 0,
children: [],
unit: "",
tempId: new Date().getTime(),
});
+ recalculateDemandedQuantities();
return true;
}
if (item.children && item.children.length > 0) {
@@ -1245,14 +1458,12 @@
"",
operationName: "",
unitQuantity: 1,
- demandedQuantity:
- routeInfo.value.quantity && routeInfo.value.quantity !== 0
- ? 1 * routeInfo.value.quantity
- : 0,
+ demandedQuantity: 0,
unit: "",
children: [],
tempId: new Date().getTime(),
});
+ recalculateDemandedQuantities();
return;
}
addchildItem(item, tempId);
@@ -1292,9 +1503,36 @@
}
};
+ // 鏍¢獙鍚屼竴灞傜骇鐨勫伐搴忔槸鍚︿竴鑷�
+ const validateProcessConsistency = items => {
+ if (!items || items.length === 0) return;
+
+ // 妫�鏌ュ綋鍓嶅眰绾�
+ const processes = items
+ .filter(item => item.processId)
+ .map(item => item.processId);
+ if (processes.length > 1) {
+ const uniqueProcesses = [...new Set(processes)];
+ if (uniqueProcesses.length > 1) {
+ ElMessage.error("鍚屼竴灞傜骇鐨勫伐搴忓繀椤讳竴鑷�");
+ isValid = false;
+ return;
+ }
+ }
+
+ // 閫掑綊妫�鏌ュ瓙绾�
+ items.forEach(item => {
+ if (item.children && item.children.length > 0) {
+ validateProcessConsistency(item.children);
+ }
+ });
+ };
+
bomDataValue.value.dataList.forEach(item => {
validateItem(item, true);
});
+
+ validateProcessConsistency(bomDataValue.value.dataList);
return isValid;
};
@@ -1320,6 +1558,7 @@
console.log(bomDataValue.value.dataList, "bomDataValue.value.dataList");
normalizeTreeData(bomDataValue.value.dataList);
+ recalculateDemandedQuantities();
const valid = validateAllBom();
if (valid) {
@@ -1331,7 +1570,7 @@
.then(() => {
ElMessage.success("BOM淇濆瓨鎴愬姛");
bomDataValue.value.isEdit = false;
- fetchBomData();
+ refreshCurrentPage();
})
.catch(() => {
ElMessage.error("BOM淇濆瓨澶辫触");
@@ -1344,11 +1583,18 @@
}
};
- onMounted(() => {
+ const refreshCurrentPage = () => {
getRouteInfo();
getList();
getProcessList();
fetchBomData();
+ if (pageType.value === "order") {
+ getAttachmentList();
+ }
+ };
+
+ onMounted(() => {
+ refreshCurrentPage();
});
onUnmounted(() => {
@@ -1615,4 +1861,4 @@
line-height: 1.5;
word-break: break-all;
}
-</style>
+</style>
\ No newline at end of file
--
Gitblit v1.9.3