From 23ad2619d81e9e45a7fb4715b4b850e94bd843e7 Mon Sep 17 00:00:00 2001
From: yuan <123@>
Date: 星期五, 24 四月 2026 15:29:25 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_NEW_pro' into dev_NEW_pro
---
src/views/index.vue | 2
src/views/salesManagement/deliveryLedger/index.vue | 363 +++++++------------
src/components/AttachmentUpload/image/index.vue | 2
src/views/productionManagement/processRoute/processRouteItem/index.vue | 74 ++-
src/components/ProcessParamListDialog.vue | 9
src/api/productionManagement/productionOrder.js | 6
src/api/productionManagement/productProcessRoute.js | 20
src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue | 63 --
src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue | 517 ++++++++++++++------------
src/api/productionManagement/processRouteItem.js | 8
src/api/productionManagement/processRoute.js | 4
src/main.js | 6
src/views/productionManagement/productionOrder/index.vue | 20
src/views/productionPlan/productionPlan/index.vue | 24
src/components/AttachmentPreview/image/index.vue | 4
15 files changed, 526 insertions(+), 596 deletions(-)
diff --git a/src/api/productionManagement/processRoute.js b/src/api/productionManagement/processRoute.js
index c07c6d3..a0cb6c8 100644
--- a/src/api/productionManagement/processRoute.js
+++ b/src/api/productionManagement/processRoute.js
@@ -12,7 +12,7 @@
export function add(data) {
return request({
- url: "/technologyRouting",
+ url: "/technologyRouting/addTechRoute",
method: "post",
data: data,
});
@@ -34,7 +34,7 @@
export function update(data) {
return request({
- url: "/technologyRouting",
+ url: "/technologyRouting/editTechRoute",
method: "put",
data: data,
});
diff --git a/src/api/productionManagement/processRouteItem.js b/src/api/productionManagement/processRouteItem.js
index 4c4bf53..0a9dc66 100644
--- a/src/api/productionManagement/processRouteItem.js
+++ b/src/api/productionManagement/processRouteItem.js
@@ -82,3 +82,11 @@
data: data,
});
}
+// 鎸夊伐鑹鸿矾绾垮伐搴忓悓姝ュ伐搴忓弬鏁�-鐢熶骇璁㈠崟
+export function syncProcessParamItemOrder(data) {
+ return request({
+ url: "/productionOrderRoutingOperationParam/sync",
+ method: "post",
+ data: data,
+ });
+}
diff --git a/src/api/productionManagement/productProcessRoute.js b/src/api/productionManagement/productProcessRoute.js
index 9d13c61..d75c239 100644
--- a/src/api/productionManagement/productProcessRoute.js
+++ b/src/api/productionManagement/productProcessRoute.js
@@ -4,7 +4,7 @@
// 鍒楄〃鏌ヨ
export function findProductProcessRouteItemList(query) {
return request({
- url: "/productProcessRoute/list",
+ url: "/productionOrderRouting/list",
method: "get",
params: query,
});
@@ -12,7 +12,7 @@
export function addOrUpdateProductProcessRouteItem(data) {
return request({
- url: "/productProcessRoute/updateRouteItem",
+ url: "/productionOrderRouting/updateRouteItem",
method: "post",
data: data,
});
@@ -21,7 +21,7 @@
// 鐢熶骇璁㈠崟涓嬶細鏂板宸ヨ壓璺嚎椤圭洰
export function addRouteItem(data) {
return request({
- url: "/productProcessRoute/addRouteItem",
+ url: "/productionOrderRouting/addRouteItem",
method: "post",
data,
});
@@ -30,7 +30,7 @@
// 鑾峰彇鐢熶骇璁㈠崟鍏宠仈鐨勫伐鑹鸿矾绾夸富淇℃伅
export function listMain(orderId) {
return request({
- url: "/productProcessRoute/listMain",
+ url: "/productionOrderRouting/listMain",
method: "get",
params: { orderId },
});
@@ -39,7 +39,7 @@
// 鍒犻櫎宸ヨ壓璺嚎椤圭洰锛堣矾鐢卞悗鎷兼帴 id锛�
export function deleteRouteItem(id) {
return request({
- url: `/productProcessRoute/deleteRouteItem/${id}`,
+ url: `/productionOrderRouting/deleteRouteItem/${id}`,
method: "delete",
});
}
@@ -47,7 +47,7 @@
// 鐢熶骇璁㈠崟涓嬶細鎺掑簭宸ヨ壓璺嚎椤圭洰
export function sortRouteItem(data) {
return request({
- url: "/productProcessRoute/sortRouteItem",
+ url: "/productionOrderRouting/sortRouteItem",
method: "post",
data,
});
@@ -55,7 +55,7 @@
// 鑾峰彇宸ュ簭鍙傛暟鍒楄〃-鐢熶骇璁㈠崟
export function findProcessParamListOrder(query) {
return request({
- url: `/productionOrderRouteItemParam/list`,
+ url: `/productionOrderRoutingOperationParam/list`,
method: "get",
params: query,
});
@@ -63,7 +63,7 @@
// 宸ヨ壓璺嚎鍙傛暟鏂板-鐢熶骇璁㈠崟
export function addProcessRouteItemParamOrder(data) {
return request({
- url: "/productionOrderRouteItemParam/add",
+ url: "/productionOrderRoutingOperationParam",
method: "post",
data: data,
});
@@ -71,7 +71,7 @@
// 宸ヨ壓璺嚎鍙傛暟淇敼-鐢熶骇璁㈠崟
export function editProcessRouteItemParamOrder(data) {
return request({
- url: "/productionOrderRouteItemParam/update",
+ url: "/productionOrderRoutingOperationParam",
method: "put",
data: data,
});
@@ -79,7 +79,7 @@
// 宸ヨ壓璺嚎鍙傛暟鍒犻櫎-鐢熶骇璁㈠崟
export function delProcessRouteItemParamOrder(id) {
return request({
- url: `/productionOrderRouteItemParam/delete/${id}`,
+ url: `/productionOrderRoutingOperationParam/${id}`,
method: "delete",
});
}
diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index ffcf936..e92dc83 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -30,7 +30,7 @@
// 鐢熶骇璁㈠崟-缁戝畾宸ヨ壓璺嚎
export function bindingRoute(data) {
return request({
- url: "/productOrder/bindingRoute",
+ url: "/productionOrder/bindingRoute",
method: "post",
data,
});
@@ -39,7 +39,7 @@
// 鐢熶骇璁㈠崟-鏂板
export function addProductOrder(data) {
return request({
- url: "/productionOrder",
+ url: "/productionOrder/addOrder",
method: "post",
data: data,
});
@@ -47,7 +47,7 @@
export function delProductOrder(ids) {
return request({
- url: `/productOrder/${ids}`,
+ url: `/productionOrder/delete/${ids}`,
method: "delete",
});
}
diff --git a/src/components/AttachmentPreview/image/index.vue b/src/components/AttachmentPreview/image/index.vue
index 5211fac..1c6039b 100644
--- a/src/components/AttachmentPreview/image/index.vue
+++ b/src/components/AttachmentPreview/image/index.vue
@@ -1,6 +1,6 @@
<script setup>
const props = defineProps({
- list: {
+ fileList: {
type: Array,
default: () => [],
},
@@ -15,7 +15,7 @@
})
const normalizedList = computed(() => {
- return (props.list || [])
+ return (props.fileList || [])
.filter((item) => item && item.previewURL)
.map((item, index) => ({
id: item.id ?? index,
diff --git a/src/components/AttachmentUpload/image/index.vue b/src/components/AttachmentUpload/image/index.vue
index 25bd13c..8243f9c 100644
--- a/src/components/AttachmentUpload/image/index.vue
+++ b/src/components/AttachmentUpload/image/index.vue
@@ -88,7 +88,7 @@
})
const uploadTip = computed(() => {
- return `鏀寔 ${props.fileType.join('/')}锛屽崟寮犱笉瓒呰繃 ${props.fileSize}MB`
+ return `鏀寔 ${props.fileType.join('/')}锛屽崟寮犱笉瓒呰繃 ${props.fileSize}MB锛屾渶澶氫笂浼� ${props.limit} 寮犲浘鐗嘸
})
function getItemUid(item, index) {
diff --git a/src/components/ProcessParamListDialog.vue b/src/components/ProcessParamListDialog.vue
index dffb7b5..883a94f 100644
--- a/src/components/ProcessParamListDialog.vue
+++ b/src/components/ProcessParamListDialog.vue
@@ -374,10 +374,9 @@
// 璋冪敤API鏂板鍙傛暟
if (props.pageType === "order") {
addProcessRouteItemParamOrder({
- orderId: Number(props.orderId),
- // processId: props.process.id,
- routeItemId: props.process.id,
- // routeItemId: Number(props.routeId),
+ productionOrderId: Number(props.orderId),
+ productionOrderRoutingOperationId: props.process.id,
+ technologyRoutingOperationParamId: props.process.id,
paramId: selectedParam.value.id,
standardValue: selectedParam.value.standardValue || "",
isRequired: selectedParam.value.isRequired || 0,
@@ -428,8 +427,6 @@
if (props.pageType === "order") {
editProcessRouteItemParamOrder({
id: editParamForm.value.id,
- // routeItemId: props.process.id,
- // paramId: editParamForm.value.paramId,
standardValue: editParamForm.value.standardValue || "",
isRequired: editParamForm.value.isRequired || 0,
})
diff --git a/src/main.js b/src/main.js
index 0b3f714..b80c9b6 100644
--- a/src/main.js
+++ b/src/main.js
@@ -43,11 +43,11 @@
// 瀵屾枃鏈粍浠�
import Editor from "@/components/Editor";
// 鏂囦欢涓婁紶缁勪欢
-import FileUpload from "@/components/FileUpload";
+import FileUpload from "@/components/AttachmentUpload/file";
// 鍥剧墖涓婁紶缁勪欢
-import ImageUpload from "@/components/ImageUpload";
+import ImageUpload from "@/components/AttachmentUpload/image";
// 鍥剧墖棰勮缁勪欢
-import ImagePreview from "@/components/ImagePreview";
+import ImagePreview from "@/components/AttachmentPreview/image";
// 瀛楀吀鏍囩缁勪欢
import DictTag from "@/components/DictTag";
// 琛ㄦ牸缁勪欢
diff --git a/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue b/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
index 27b4a59..66867e3 100644
--- a/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
+++ b/src/views/equipmentManagement/inspectionManagement/components/viewFiles.vue
@@ -134,40 +134,6 @@
const currentMediaIndex = ref(0);
const mediaList = ref([]); // 瀛樺偍褰撳墠瑕佹煡鐪嬬殑濯掍綋鍒楄〃锛堝惈鍥剧墖鍜岃棰戝璞★級
const mediaType = ref('image'); // image | video
-const javaApi = proxy.javaApi;
-
-// 澶勭悊 URL锛氬皢 Windows 璺緞杞崲涓哄彲璁块棶鐨� URL
-function processFileUrl(fileUrl) {
- if (!fileUrl) return '';
-
- // 濡傛灉 URL 鏄� Windows 璺緞鏍煎紡锛堝寘鍚弽鏂滄潬锛夛紝闇�瑕佽浆鎹�
- if (fileUrl && fileUrl.indexOf('\\') > -1) {
- // 鏌ユ壘 uploads 鍏抽敭瀛楃殑浣嶇疆锛屼粠閭i噷寮�濮嬫彁鍙栫浉瀵硅矾寰�
- const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads');
- if (uploadsIndex > -1) {
- // 浠� uploads 寮�濮嬫彁鍙栬矾寰勶紝骞跺皢鍙嶆枩鏉犳浛鎹负姝f枩鏉�
- const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/');
- fileUrl = '/' + relativePath;
- } else {
- // 濡傛灉娌℃湁鎵惧埌 uploads锛屾彁鍙栨渶鍚庝竴涓洰褰曞拰鏂囦欢鍚�
- const parts = fileUrl.split('\\');
- const fileName = parts[parts.length - 1];
- fileUrl = '/uploads/' + fileName;
- }
- }
-
- // 纭繚鎵�鏈夐潪 http 寮�澶寸殑 URL 閮芥嫾鎺� baseUrl
- if (fileUrl && !fileUrl.startsWith('http')) {
- // 纭繚璺緞浠� / 寮�澶�
- if (!fileUrl.startsWith('/')) {
- fileUrl = '/' + fileUrl;
- }
- // 鎷兼帴 baseUrl
- fileUrl = javaApi + fileUrl;
- }
-
- return fileUrl;
-}
// 澶勭悊姣忎竴绫绘暟鎹細鍒嗙鍥剧墖鍜岃棰�
function processItems(items) {
@@ -180,24 +146,18 @@
}
items.forEach(item => {
- if (!item || !item.url) return;
+ if (!item || !item.previewURL || !item.contentType) return;
+
// 澶勭悊鏂囦欢 URL
- const fileUrl = processFileUrl(item.url);
-
- // 鏍规嵁鏂囦欢鎵╁睍鍚嶅垽鏂槸鍥剧墖杩樻槸瑙嗛
- const urlLower = fileUrl.toLowerCase();
- if (urlLower.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/)) {
+ const fileUrl = item.previewURL;
+ const contentType = String(item.contentType).toLowerCase();
+
+ // 鏍规嵁 contentType 鍒ゆ柇鏄浘鐗囪繕鏄棰�
+ if (contentType.startsWith('image/')) {
images.push(fileUrl);
- } else if (urlLower.match(/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/)) {
+ } else if (contentType.startsWith('video/')) {
videos.push(fileUrl);
- } else if (item.contentType) {
- // 濡傛灉鏈� contentType锛屼娇鐢� contentType 鍒ゆ柇
- if (item.contentType.startsWith('image/')) {
- images.push(fileUrl);
- } else if (item.contentType.startsWith('video/')) {
- videos.push(fileUrl);
- }
}
});
@@ -207,10 +167,9 @@
// 鎵撳紑寮圭獥骞跺姞杞芥暟鎹�
const openDialog = async (row) => {
// 浣跨敤姝g‘鐨勫瓧娈靛悕锛歝ommonFileListBefore, commonFileListAfter
- // productionIssues 鍙兘涓嶅瓨鍦紝浣跨敤绌烘暟缁�
- const { images: beforeImgs, videos: beforeVids } = processItems(row.commonFileListBefore || []);
- const { images: afterImgs, videos: afterVids } = processItems(row.commonFileListAfter || []);
- const { images: issueImgs, videos: issueVids } = processItems(row.productionIssues || []);
+ const { images: beforeImgs, videos: beforeVids } = processItems(row.commonFileListBeforeVO || []);
+ const { images: afterImgs, videos: afterVids } = processItems(row.commonFileListAfterVO || []);
+ const { images: issueImgs, videos: issueVids } = processItems(row.commonFileListVO || []);
beforeProductionImgs.value = beforeImgs;
beforeProductionVideos.value = beforeVids;
diff --git a/src/views/index.vue b/src/views/index.vue
index 838182b..00d4312 100644
--- a/src/views/index.vue
+++ b/src/views/index.vue
@@ -8,7 +8,7 @@
<!-- 椤堕儴闂�欐潯 -->
<div class="welcome-banner">
<div class="welcome-title">
- <span class="welcome-user">{{ userStore.roleName || '绯荤粺绠$悊鍛�' }}</span>
+ <span class="welcome-user">{{ userStore.nickName || '绯荤粺绠$悊鍛�' }}</span>
<span> 鎮ㄥソ锛佺鎮ㄥ紑蹇冩瘡涓�澶�</span>
</div>
<div class="welcome-time">鐧诲綍浜�: {{ userStore.currentLoginTime }}</div>
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index 42fd4b2..b78caad 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -232,7 +232,7 @@
style="width: 100%">
<el-table-column type="expand">
<template #default>
- <el-form ref="form"
+ <el-form ref="bomFormRef"
:model="bomDataValue">
<el-table :data="bomDataValue.dataList"
row-key="tempId"
@@ -356,7 +356,7 @@
prop="model" />
</el-table>
<ProductSelectDialog v-if="bomDataValue.showProductDialog"
- v-model:model-value="bomDataValue.showProductDialog"
+ v-model="bomDataValue.showProductDialog"
:single="true"
@confirm="handleBomProduct" />
<!-- 鏂板/缂栬緫寮圭獥 -->
@@ -385,8 +385,8 @@
prop="productModelId">
<el-button type="primary"
@click="showProductSelectDialog = true">
- {{ form.productName && form.model
- ? `${form.productName} - ${form.model}`
+ {{ form.productName
+ ? (form.model ? `${form.productName} - ${form.model}` : form.productName)
: '閫夋嫨浜у搧' }}
</el-button>
</el-form-item>
@@ -401,13 +401,13 @@
prop="isQuality">
<el-switch v-model="form.isQuality"
:active-value="true"
- inactive-value="false" />
+ :inactive-value="false" />
</el-form-item>
<el-form-item label="鏄惁鐢熶骇"
prop="isProduction">
<el-switch v-model="form.isProduction"
:active-value="true"
- inactive-value="false" />
+ :inactive-value="false" />
</el-form-item>
</el-form>
<template #footer>
@@ -454,7 +454,10 @@
batchDeleteProcessRouteItem,
getProcessParamList,
} from "@/api/productionManagement/processRouteItem.js";
- import { syncProcessParamItem } from "@/api/productionManagement/processRouteItem.js";
+ import {
+ syncProcessParamItem,
+ syncProcessParamItemOrder,
+ } from "@/api/productionManagement/processRouteItem.js";
import {
findProductProcessRouteItemList,
deleteRouteItem,
@@ -469,6 +472,7 @@
queryList,
addBomDetail,
} from "@/api/productionManagement/productStructure.js";
+
import { useRoute } from "vue-router";
import { ElMessageBox, ElMessage } from "element-plus";
import Sortable from "sortablejs";
@@ -485,6 +489,7 @@
const dialogVisible = ref(false);
const operationType = ref("add"); // add | edit
const formRef = ref(null);
+ const bomFormRef = ref(null);
const submitLoading = ref(false);
const cardsContainer = ref(null);
const tableRef = ref(null);
@@ -542,17 +547,31 @@
type: "warning",
})
.then(() => {
- syncProcessParamItem({
- replaceExisting: true,
- technologyRoutingOperationId: currentProcess.value.id,
- }).then(res => {
- if (res.code === 200) {
- ElMessage.success("鍚屾鎴愬姛");
- refreshParamList();
- } else {
- ElMessage.error(res.msg || "鍚屾澶辫触");
- }
- });
+ if (pageType.value === "order") {
+ syncProcessParamItemOrder({
+ replaceExisting: true,
+ technologyRoutingOperationId: currentProcess.value.id,
+ }).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍚屾鎴愬姛");
+ refreshParamList();
+ } else {
+ ElMessage.error(res.msg || "鍚屾澶辫触");
+ }
+ });
+ } else {
+ syncProcessParamItem({
+ replaceExisting: true,
+ technologyRoutingOperationId: currentProcess.value.id,
+ }).then(res => {
+ if (res.code === 200) {
+ ElMessage.success("鍚屾鎴愬姛");
+ refreshParamList();
+ } else {
+ ElMessage.error(res.msg || "鍚屾澶辫触");
+ }
+ });
+ }
})
.catch(() => {});
};
@@ -670,15 +689,20 @@
// 浜у搧閫夋嫨
const handleProductSelect = products => {
+ console.log(products, "===products===");
if (products && products.length > 0) {
const product = products[0];
- form.value.productModelId = product.id;
- form.value.productName = product.productName;
- form.value.model = product.model;
- form.value.unit = product.unit || "";
+ console.log(product, "product");
+ form.value = {
+ ...form.value,
+ productModelId: product.id,
+ productName: product.productName,
+ model: product.model,
+ unit: product.unit || "",
+ };
showProductSelectDialog.value = false;
// 瑙﹀彂琛ㄥ崟楠岃瘉
- formRef.value?.validateField("productModelId");
+ // formRef.value?.validateField("productModelId");
}
};
@@ -773,6 +797,8 @@
productName: "",
model: "",
unit: "",
+ isQuality: false,
+ isProduction: false,
};
formRef.value?.resetFields();
};
@@ -788,7 +814,7 @@
currentProcess.value = row;
const query = {
technologyRoutingOperationId: row.id,
- orderId: orderId.value,
+ productionOrderId: orderId.value,
};
const apiPromise =
diff --git a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
index 9e1a852..6b040d6 100644
--- a/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
+++ b/src/views/productionManagement/productionOrder/components/MaterialLedgerDialog.vue
@@ -1,298 +1,327 @@
<template>
<div>
- <el-dialog v-model="dialogVisible" title="棰嗘枡鍙拌处" width="1200px" @close="handleClose">
+ <el-dialog v-model="dialogVisible"
+ title="棰嗘枡鍙拌处"
+ width="1200px"
+ @close="handleClose">
<div class="material-toolbar">
- <el-button type="primary" @click="handleAddMaterialRow">鏂板</el-button>
+ <el-button type="primary"
+ @click="handleAddMaterialRow">鏂板</el-button>
</div>
- <el-table v-loading="materialTableLoading" :data="materialTableData" border row-key="tempId">
- <el-table-column label="宸ュ簭鍚嶇О" min-width="180">
+ <el-table v-loading="materialTableLoading"
+ :data="materialTableData"
+ border
+ row-key="tempId">
+ <el-table-column label="宸ュ簭鍚嶇О"
+ min-width="180">
<template #default="{ row }">
<span v-if="row.bom === true">{{ row.processName || "-" }}</span>
- <el-select
- v-else
- v-model="row.processName"
- placeholder="璇烽�夋嫨宸ュ簭"
- clearable
- filterable
- style="width: 100%;"
- @change="val => handleProcessNameChange(row, val)"
- >
- <el-option v-for="item in processOptions" :key="item.id" :label="item.name" :value="item.name" />
+ <el-select v-else
+ v-model="row.processName"
+ placeholder="璇烽�夋嫨宸ュ簭"
+ clearable
+ filterable
+ style="width: 100%;"
+ @change="val => handleProcessNameChange(row, val)">
+ <el-option v-for="item in processOptions"
+ :key="item.id"
+ :label="item.name"
+ :value="item.name" />
</el-select>
</template>
</el-table-column>
- <el-table-column label="鍘熸枡鍚嶇О" min-width="160">
+ <el-table-column label="鍘熸枡鍚嶇О"
+ min-width="160">
<template #default="{ row }">
<span v-if="row.bom === true">{{ row.materialName || "-" }}</span>
- <el-button v-else type="primary" link @click="openMaterialProductSelect(row)">
+ <el-button v-else
+ type="primary"
+ link
+ @click="openMaterialProductSelect(row)">
{{ row.materialName || "閫夋嫨鍘熸枡" }}
</el-button>
</template>
</el-table-column>
- <el-table-column label="鍘熸枡鍨嬪彿" min-width="180">
+ <el-table-column label="鍘熸枡鍨嬪彿"
+ min-width="180">
<template #default="{ row }">
{{ row.materialModel || "-" }}
</template>
</el-table-column>
- <el-table-column label="闇�姹傛暟閲�" min-width="120">
+ <el-table-column label="闇�姹傛暟閲�"
+ min-width="120">
<template #default="{ row }">
<span v-if="row.bom === true">{{ row.requiredQty ?? "-" }}</span>
- <el-input-number
- v-else
- v-model="row.requiredQty"
- :min="0"
- :precision="3"
- :step="1"
- controls-position="right"
- style="width: 100%;"
- @change="val => handleRequiredQtyChange(row, val)"
- />
+ <el-input-number v-else
+ v-model="row.requiredQty"
+ :min="0"
+ :precision="3"
+ :step="1"
+ controls-position="right"
+ style="width: 100%;"
+ @change="val => handleRequiredQtyChange(row, val)" />
</template>
</el-table-column>
- <el-table-column label="璁¢噺鍗曚綅" width="120">
+ <el-table-column label="璁¢噺鍗曚綅"
+ width="120">
<template #default="{ row }">
{{ row.unit || "-" }}
</template>
</el-table-column>
- <el-table-column label="棰嗙敤鏁伴噺" min-width="120">
+ <el-table-column label="棰嗙敤鏁伴噺"
+ min-width="120">
<template #default="{ row }">
- <el-input-number
- v-model="row.pickQty"
- :min="0"
- :precision="3"
- :step="1"
- controls-position="right"
- style="width: 100%;"
- />
+ <el-input-number v-model="row.pickQty"
+ :min="0"
+ :precision="3"
+ :step="1"
+ controls-position="right"
+ style="width: 100%;" />
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔" width="90" fixed="right">
+ <el-table-column label="鎿嶄綔"
+ width="90"
+ fixed="right">
<template #default="{ $index, row }">
- <el-button v-if="row.bom !== true" type="danger" link @click="handleDeleteMaterialRow($index)">鍒犻櫎</el-button>
+ <el-button v-if="row.bom !== true"
+ type="danger"
+ link
+ @click="handleDeleteMaterialRow($index)">鍒犻櫎</el-button>
</template>
</el-table-column>
</el-table>
<template #footer>
<span class="dialog-footer">
- <el-button type="primary" :loading="materialSaving" @click="handleMaterialSave">淇濆瓨</el-button>
+ <el-button type="primary"
+ :loading="materialSaving"
+ @click="handleMaterialSave">淇濆瓨</el-button>
<el-button @click="dialogVisible = false">鍙栨秷</el-button>
</span>
</template>
</el-dialog>
-
- <ProductSelectDialog
- v-model="materialProductDialogVisible"
- @confirm="handleMaterialProductConfirm"
- single
- request-url="/stockInventory/rawMaterials"
- />
+ <ProductSelectDialog v-model="materialProductDialogVisible"
+ @confirm="handleMaterialProductConfirm"
+ single />
+ <!-- request-url="/stockInventory/rawMaterials" -->
</div>
</template>
<script setup>
-import { computed, ref, watch } from "vue";
-import { ElMessage } from "element-plus";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js";
-import {
- listMaterialPickingDetail,
- listMaterialPickingLedger,
- saveMaterialPickingLedger,
-} from "@/api/productionManagement/productionOrder.js";
+ import { computed, ref, watch } from "vue";
+ import { ElMessage } from "element-plus";
+ import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
+ import { findProductProcessRouteItemList } from "@/api/productionManagement/productProcessRoute.js";
+ import {
+ listMaterialPickingDetail,
+ listMaterialPickingLedger,
+ saveMaterialPickingLedger,
+ } from "@/api/productionManagement/productionOrder.js";
-const props = defineProps({
- modelValue: { type: Boolean, default: false },
- orderRow: { type: Object, default: null },
-});
-const emit = defineEmits(["update:modelValue", "saved"]);
-
-const dialogVisible = computed({
- get: () => props.modelValue,
- set: val => emit("update:modelValue", val),
-});
-
-const materialProductDialogVisible = ref(false);
-const materialTableLoading = ref(false);
-const materialSaving = ref(false);
-const materialTableData = ref([]);
-const processOptions = ref([]);
-const currentMaterialSelectRowIndex = ref(-1);
-let materialTempId = 0;
-
-const createMaterialRow = (row = {}) => ({
- tempId: row.id || `temp_${++materialTempId}`,
- id: row.id,
- processId: row.processId,
- productProcessId: row.productProcessId || row.processId,
- processName: row.processName || "",
- bom: row.bom === true,
- materialModelId: row.materialModelId,
- materialName: row.materialName || "",
- materialModel: row.materialModel || "",
- requiredQty: Number(row.requiredQty ?? 0),
- unit: row.unit || "",
- pickQty: Number(row.pickQty ?? row.requiredQty ?? 0),
-});
-
-const getProcessOptions = async () => {
- if (!props.orderRow?.id) return;
- const res = await findProductProcessRouteItemList({ orderId: props.orderRow.id });
- const routeList = Array.isArray(res?.data) ? res.data : res?.data?.records || [];
- const processMap = new Map();
- routeList.forEach(item => {
- const processId = item.processId;
- const processName = item.processName;
- if (!processId || !processName) return;
- const key = `${processId}_${processName}`;
- if (!processMap.has(key)) {
- processMap.set(key, {
- id: processId,
- name: processName,
- });
- }
+ const props = defineProps({
+ modelValue: { type: Boolean, default: false },
+ orderRow: { type: Object, default: null },
});
- processOptions.value = Array.from(processMap.values());
-};
+ const emit = defineEmits(["update:modelValue", "saved"]);
-const loadMaterialData = async () => {
- if (!props.orderRow?.id) return;
- materialTableLoading.value = true;
- materialTableData.value = [];
- await getProcessOptions();
- try {
- const detailRes = await listMaterialPickingDetail({ orderId: props.orderRow.id });
- const detailList = Array.isArray(detailRes?.data)
- ? detailRes.data
- : detailRes?.data?.records || [];
- if (detailList.length > 0) {
- materialTableData.value = detailList.map(item => createMaterialRow(item));
+ const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: val => emit("update:modelValue", val),
+ });
+
+ const materialProductDialogVisible = ref(false);
+ const materialTableLoading = ref(false);
+ const materialSaving = ref(false);
+ const materialTableData = ref([]);
+ const processOptions = ref([]);
+ const currentMaterialSelectRowIndex = ref(-1);
+ let materialTempId = 0;
+
+ const createMaterialRow = (row = {}) => ({
+ tempId: row.id || `temp_${++materialTempId}`,
+ id: row.id,
+ processId: row.processId,
+ productProcessId: row.productProcessId || row.processId,
+ processName: row.processName || "",
+ bom: row.bom === true,
+ materialModelId: row.materialModelId,
+ materialName: row.materialName || "",
+ materialModel: row.materialModel || "",
+ requiredQty: Number(row.requiredQty ?? 0),
+ unit: row.unit || "",
+ pickQty: Number(row.pickQty ?? row.requiredQty ?? 0),
+ });
+
+ const getProcessOptions = async () => {
+ if (!props.orderRow?.id) return;
+ const res = await findProductProcessRouteItemList({
+ orderId: props.orderRow.id,
+ });
+ const routeList = Array.isArray(res?.data)
+ ? res.data
+ : res?.data?.records || [];
+ const processMap = new Map();
+ routeList.forEach(item => {
+ const processId = item.processId;
+ const processName = item.processName;
+ if (!processId || !processName) return;
+ const key = `${processId}_${processName}`;
+ if (!processMap.has(key)) {
+ processMap.set(key, {
+ id: processId,
+ name: processName,
+ });
+ }
+ });
+ processOptions.value = Array.from(processMap.values());
+ };
+
+ const loadMaterialData = async () => {
+ if (!props.orderRow?.id) return;
+ materialTableLoading.value = true;
+ materialTableData.value = [];
+ await getProcessOptions();
+ try {
+ const detailRes = await listMaterialPickingDetail({
+ orderId: props.orderRow.id,
+ });
+ const detailList = Array.isArray(detailRes?.data)
+ ? detailRes.data
+ : detailRes?.data?.records || [];
+ if (detailList.length > 0) {
+ materialTableData.value = detailList.map(item => createMaterialRow(item));
+ return;
+ }
+ const ledgerRes = await listMaterialPickingLedger({
+ orderId: props.orderRow.id,
+ });
+ const ledgerList = Array.isArray(ledgerRes?.data)
+ ? ledgerRes.data
+ : ledgerRes?.data?.records || [];
+ materialTableData.value = ledgerList.map(item => createMaterialRow(item));
+ } finally {
+ materialTableLoading.value = false;
+ }
+ };
+
+ watch(
+ () => dialogVisible.value,
+ visible => {
+ if (visible) {
+ loadMaterialData();
+ }
+ }
+ );
+
+ const handleClose = () => {
+ materialTableData.value = [];
+ currentMaterialSelectRowIndex.value = -1;
+ };
+
+ const handleAddMaterialRow = () => {
+ materialTableData.value.push(createMaterialRow());
+ };
+
+ const handleDeleteMaterialRow = index => {
+ materialTableData.value.splice(index, 1);
+ };
+
+ const handleProcessNameChange = (row, processName) => {
+ const process = processOptions.value.find(item => item.name === processName);
+ row.productProcessId = process?.id;
+ };
+
+ const handleRequiredQtyChange = (row, val) => {
+ const required = Number(val ?? 0);
+ row.requiredQty = required;
+ if (!row.pickQty || Number(row.pickQty) === 0) {
+ row.pickQty = required;
+ }
+ };
+
+ const openMaterialProductSelect = row => {
+ currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(
+ item => item.tempId === row.tempId
+ );
+ materialProductDialogVisible.value = true;
+ };
+
+ const handleMaterialProductConfirm = products => {
+ if (!products || products.length === 0) return;
+ const index = currentMaterialSelectRowIndex.value;
+ if (index < 0 || !materialTableData.value[index]) return;
+ const product = products[0];
+ const row = materialTableData.value[index];
+ row.materialModelId =
+ product.materialModelId || product.modelId || product.id;
+ row.materialName =
+ product.materialName || product.productName || product.name || "";
+ row.materialModel = product.materialModel || product.model || "";
+ row.unit = product.unit || product.measureUnit || "";
+ currentMaterialSelectRowIndex.value = -1;
+ materialProductDialogVisible.value = false;
+ };
+
+ const validateMaterialRows = () => {
+ if (materialTableData.value.length === 0) {
+ return { valid: false, message: "璇峰厛鏂板棰嗘枡鏁版嵁" };
+ }
+ const invalidNewRow = materialTableData.value.find(
+ item => item.bom !== true && (!item.processName || !item.materialName)
+ );
+ if (invalidNewRow) {
+ return { valid: false, message: "鏂板琛岀殑宸ュ簭鍚嶇О鍜屽師鏂欏悕绉颁负蹇呭~椤�" };
+ }
+ const invalidRow = materialTableData.value.find(
+ item =>
+ !item.processName ||
+ !item.materialName ||
+ item.requiredQty === null ||
+ item.requiredQty === undefined ||
+ item.pickQty === null ||
+ item.pickQty === undefined
+ );
+ if (invalidRow) {
+ return { valid: false, message: "璇峰畬鍠勫伐搴忋�佸師鏂欏拰鏁伴噺鍚庡啀淇濆瓨" };
+ }
+ return { valid: true, message: "" };
+ };
+
+ const handleMaterialSave = async () => {
+ if (!props.orderRow?.id) return;
+ const validateResult = validateMaterialRows();
+ if (!validateResult.valid) {
+ ElMessage.warning(validateResult.message);
return;
}
- const ledgerRes = await listMaterialPickingLedger({ orderId: props.orderRow.id });
- const ledgerList = Array.isArray(ledgerRes?.data)
- ? ledgerRes.data
- : ledgerRes?.data?.records || [];
- materialTableData.value = ledgerList.map(item => createMaterialRow(item));
- } finally {
- materialTableLoading.value = false;
- }
-};
-
-watch(
- () => dialogVisible.value,
- visible => {
- if (visible) {
- loadMaterialData();
+ materialSaving.value = true;
+ try {
+ await saveMaterialPickingLedger({
+ orderId: props.orderRow.id,
+ items: materialTableData.value.map(item => ({
+ id: item.id,
+ processId: item.processName,
+ productProcessId: item.productProcessId,
+ processName: item.processName,
+ bom: item.bom === true,
+ materialModelId: item.materialModelId,
+ materialName: item.materialName,
+ materialModel: item.materialModel,
+ requiredQty: item.requiredQty,
+ unit: item.unit,
+ pickQty: item.pickQty,
+ })),
+ });
+ emit("saved");
+ dialogVisible.value = false;
+ } finally {
+ materialSaving.value = false;
}
- }
-);
-
-const handleClose = () => {
- materialTableData.value = [];
- currentMaterialSelectRowIndex.value = -1;
-};
-
-const handleAddMaterialRow = () => {
- materialTableData.value.push(createMaterialRow());
-};
-
-const handleDeleteMaterialRow = index => {
- materialTableData.value.splice(index, 1);
-};
-
-const handleProcessNameChange = (row, processName) => {
- const process = processOptions.value.find(item => item.name === processName);
- row.productProcessId = process?.id;
-};
-
-const handleRequiredQtyChange = (row, val) => {
- const required = Number(val ?? 0);
- row.requiredQty = required;
- if (!row.pickQty || Number(row.pickQty) === 0) {
- row.pickQty = required;
- }
-};
-
-const openMaterialProductSelect = row => {
- currentMaterialSelectRowIndex.value = materialTableData.value.findIndex(item => item.tempId === row.tempId);
- materialProductDialogVisible.value = true;
-};
-
-const handleMaterialProductConfirm = products => {
- if (!products || products.length === 0) return;
- const index = currentMaterialSelectRowIndex.value;
- if (index < 0 || !materialTableData.value[index]) return;
- const product = products[0];
- const row = materialTableData.value[index];
- row.materialModelId = product.materialModelId || product.modelId || product.id;
- row.materialName = product.materialName || product.productName || product.name || "";
- row.materialModel = product.materialModel || product.model || "";
- row.unit = product.unit || product.measureUnit || "";
- currentMaterialSelectRowIndex.value = -1;
- materialProductDialogVisible.value = false;
-};
-
-const validateMaterialRows = () => {
- if (materialTableData.value.length === 0) {
- return { valid: false, message: "璇峰厛鏂板棰嗘枡鏁版嵁" };
- }
- const invalidNewRow = materialTableData.value.find(
- item => item.bom !== true && (!item.processName || !item.materialName)
- );
- if (invalidNewRow) {
- return { valid: false, message: "鏂板琛岀殑宸ュ簭鍚嶇О鍜屽師鏂欏悕绉颁负蹇呭~椤�" };
- }
- const invalidRow = materialTableData.value.find(
- item =>
- !item.processName ||
- !item.materialName ||
- item.requiredQty === null ||
- item.requiredQty === undefined ||
- item.pickQty === null ||
- item.pickQty === undefined
- );
- if (invalidRow) {
- return { valid: false, message: "璇峰畬鍠勫伐搴忋�佸師鏂欏拰鏁伴噺鍚庡啀淇濆瓨" };
- }
- return { valid: true, message: "" };
-};
-
-const handleMaterialSave = async () => {
- if (!props.orderRow?.id) return;
- const validateResult = validateMaterialRows();
- if (!validateResult.valid) {
- ElMessage.warning(validateResult.message);
- return;
- }
- materialSaving.value = true;
- try {
- await saveMaterialPickingLedger({
- orderId: props.orderRow.id,
- items: materialTableData.value.map(item => ({
- id: item.id,
- processId: item.processName,
- productProcessId: item.productProcessId,
- processName: item.processName,
- bom: item.bom === true,
- materialModelId: item.materialModelId,
- materialName: item.materialName,
- materialModel: item.materialModel,
- requiredQty: item.requiredQty,
- unit: item.unit,
- pickQty: item.pickQty,
- })),
- });
- emit("saved");
- dialogVisible.value = false;
- } finally {
- materialSaving.value = false;
- }
-};
+ };
</script>
<style scoped lang="scss">
-.material-toolbar {
- margin-bottom: 12px;
- text-align: right;
-}
+ .material-toolbar {
+ margin-bottom: 12px;
+ text-align: right;
+ }
</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index a67130c..6480990 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -28,7 +28,7 @@
@change="handleQuery" />
</el-form-item>
<el-form-item label="浜у搧鍚嶇О:">
- <el-input v-model="searchForm.productCategory"
+ <el-input v-model="searchForm.productName"
placeholder="璇疯緭鍏�"
clearable
prefix-icon="Search"
@@ -36,7 +36,7 @@
@change="handleQuery" />
</el-form-item>
<el-form-item label="瑙勬牸:">
- <el-input v-model="searchForm.specificationModel"
+ <el-input v-model="searchForm.model"
placeholder="璇疯緭鍏�"
clearable
prefix-icon="Search"
@@ -269,8 +269,8 @@
customerName: "",
salesContractNo: "",
projectName: "",
- productCategory: "",
- specificationModel: "",
+ productName: "",
+ model: "",
},
});
const { searchForm } = toRefs(data);
@@ -354,7 +354,7 @@
try {
await bindingRoute({
id: bindForm.orderId,
- routeId: bindForm.routeId,
+ technologyRoutingId: bindForm.routeId,
});
proxy.$modal.msgSuccess("缁戝畾鎴愬姛");
bindRouteDialogVisible.value = false;
@@ -429,9 +429,9 @@
id: data.id,
bomId: data.bomId,
processRouteCode: data.processRouteCode || "",
- productName: data.productName || "",
- model: data.model || "",
- bomNo: data.bomNo || "",
+ productName: row.productName || "",
+ model: row.model || "",
+ bomNo: row.bomNo || "",
description: data.description || "",
orderId,
type: "order",
@@ -449,8 +449,8 @@
query: {
id: row.id,
bomNo: row.bomNo || "",
- productName: row.productCategory || "",
- productModelName: row.specificationModel || "",
+ productName: row.productName || "",
+ productModelName: row.model || "",
orderId: row.id,
type: "order",
},
diff --git a/src/views/productionPlan/productionPlan/index.vue b/src/views/productionPlan/productionPlan/index.vue
index 9768093..9b39531 100644
--- a/src/views/productionPlan/productionPlan/index.vue
+++ b/src/views/productionPlan/productionPlan/index.vue
@@ -343,7 +343,7 @@
},
{
label: "宸蹭笅鍙戞暟閲�",
- prop: "assignedQuantity",
+ prop: "quantityIssued",
width: "120px",
className: "spec-cell",
// formatData: (cell, row) => (cell ? `${cell}${row.unit || "鏂�"}` : 0),
@@ -389,16 +389,18 @@
name: "涓嬪彂",
type: "text",
showHide: row => {
- return row.status == 0;
+ return row.status != 2;
},
clickFun: row => {
mergeForm.productName = row.productName || "";
mergeForm.model = row.model || "";
- mergeForm.totalAssignedQuantity = Number(row.qtyRequired || 0);
+ mergeForm.totalAssignedQuantity =
+ Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
mergeForm.planCompleteTime = row.requiredDate || "";
mergeForm.productId = row.productId || "";
mergeForm.ids = [row.id];
- sumAssignedQuantity.value = Number(row.qtyRequired || 0);
+ sumAssignedQuantity.value =
+ Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
isShowNewModal.value = true;
},
},
@@ -618,9 +620,9 @@
};
}
summary[category].totalAssignedQuantity += Number(
- (
- Number(row.qtyRequired || 0) - Number(row.assignedQuantity || 0)
- ).toFixed(4)
+ (Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0)).toFixed(
+ 4
+ )
);
});
@@ -667,8 +669,12 @@
// 鍒ゆ柇琛屾槸鍚﹀彲閫夋嫨
const isSelectable = row => {
+ // 濡傛灉鏄凡涓嬪彂鐘舵�侊紝绂佹鍕鹃��
+ if (row.status == 2) {
+ return false;
+ }
// 璁$畻鍓╀綑鏁伴噺
- const remainingQty = (row.qtyRequired || 0) - (row.assignedQuantity || 0);
+ const remainingQty = (row.qtyRequired || 0) - (row.quantityIssued || 0);
// 濡傛灉鍓╀綑鏁伴噺灏忎簬绛変簬0锛岀姝㈤�夋嫨
if (remainingQty <= 0) {
return false;
@@ -696,7 +702,7 @@
// 璁$畻鎬诲埗閫犳暟閲� (榛樿qtyRequired鐨勫拰)
const totalAssignedQuantity = selectedRows.value.reduce((sum, row) => {
- return sum + Number(row.qtyRequired || 0);
+ return sum + Number(row.qtyRequired || 0) - Number(row.quantityIssued || 0);
}, 0);
sumAssignedQuantity.value = totalAssignedQuantity;
console.log(totalAssignedQuantity);
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index 0eb60cc..223c6e9 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -3,19 +3,22 @@
<div class="search_form">
<el-form :model="searchForm" :inline="true">
<el-form-item label="閿�鍞鍗曞彿锛�">
- <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search" style="width: 200px"
- @change="handleQuery" />
+ <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ style="width: 200px"
+ @change="handleQuery"/>
</el-form-item>
<el-form-item label="杞︾墝鍙凤細">
- <el-input v-model="searchForm.shippingCarNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search" style="width: 200px"
- @change="handleQuery" />
+ <el-input v-model="searchForm.shippingCarNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ style="width: 200px"
+ @change="handleQuery"/>
</el-form-item>
<el-form-item label="蹇�掑崟鍙凤細">
- <el-input v-model="searchForm.expressNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search" style="width: 200px"
- @change="handleQuery" />
+ <el-input v-model="searchForm.expressNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+ style="width: 200px"
+ @change="handleQuery"/>
</el-form-item>
<el-form-item>
- <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
+ <el-button type="primary" @click="handleQuery"> 鎼滅储</el-button>
</el-form-item>
</el-form>
</div>
@@ -28,18 +31,18 @@
</div>
</div>
<el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
- :row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)">
- <el-table-column align="center" type="selection" width="55" />
- <el-table-column align="center" label="搴忓彿" type="index" width="60" />
- <el-table-column label="閿�鍞鍗�" prop="salesContractNo" show-overflow-tooltip />
- <el-table-column label="鍙戣揣璁㈠崟鍙�" prop="shippingNo" show-overflow-tooltip />
- <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip />
- <el-table-column label="浜у搧鍚嶇О" prop="productName" show-overflow-tooltip />
- <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" show-overflow-tooltip />
- <el-table-column label="鍙戣揣鏃堕棿" prop="shippingDate" show-overflow-tooltip />
- <el-table-column label="鍙戣揣杞︾墝鍙�" prop="shippingCarNumber" show-overflow-tooltip />
- <el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip />
- <el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip />
+ :row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)">
+ <el-table-column align="center" type="selection" width="55"/>
+ <el-table-column align="center" label="搴忓彿" type="index" width="60"/>
+ <el-table-column label="閿�鍞鍗�" prop="salesContractNo" show-overflow-tooltip/>
+ <el-table-column label="鍙戣揣璁㈠崟鍙�" prop="shippingNo" show-overflow-tooltip/>
+ <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip/>
+ <el-table-column label="浜у搧鍚嶇О" prop="productName" show-overflow-tooltip/>
+ <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" show-overflow-tooltip/>
+ <el-table-column label="鍙戣揣鏃堕棿" prop="shippingDate" show-overflow-tooltip/>
+ <el-table-column label="鍙戣揣杞︾墝鍙�" prop="shippingCarNumber" show-overflow-tooltip/>
+ <el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip/>
+ <el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip/>
<el-table-column label="瀹℃牳鐘舵��" prop="status" align="center" width="120">
<template #default="scope">
<el-tag :type="getApprovalStatusType(scope.row.status)">
@@ -49,42 +52,46 @@
</el-table-column>
<el-table-column fixed="right" label="鎿嶄綔" width="220" align="center">
<template #default="scope">
- <el-button
- link
- type="primary"
- :disabled="!isApproved(scope.row.status)"
- @click="openForm('edit', scope.row)">琛ュ厖鍙戣揣淇℃伅</el-button>
<el-button
- link
- type="primary"
- style="color: #67C23A"
- @click="openDetail(scope.row)"
- >璇︽儏</el-button>
- <el-button
- link
- type="danger"
- :disabled="isApproving(scope.row.status)"
- @click="handleDeleteSingle(scope.row)">鍒犻櫎</el-button>
+ link
+ type="primary"
+ :disabled="!isApproved(scope.row.status)"
+ @click="openForm('edit', scope.row)">琛ュ厖鍙戣揣淇℃伅
+ </el-button>
+ <el-button
+ link
+ type="primary"
+ style="color: #67C23A"
+ @click="openDetail(scope.row)"
+ >璇︽儏
+ </el-button>
+ <el-button
+ link
+ type="danger"
+ :disabled="isApproving(scope.row.status)"
+ @click="handleDeleteSingle(scope.row)">鍒犻櫎
+ </el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
- :page="page.current" :limit="page.size" @pagination="paginationChange" />
+ :page="page.current" :limit="page.size" @pagination="paginationChange"/>
</div>
- <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板鍙戣揣鍙拌处' : '缂栬緫鍙戣揣鍙拌处'" width="40%"
- @close="closeDia">
+ <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板鍙戣揣鍙拌处' : '缂栬緫鍙戣揣鍙拌处'"
+ width="40%"
+ @close="closeDia">
<el-form :model="form" label-width="120px" label-position="top" :rules="rules" ref="formRef">
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="鍙戣揣绫诲瀷锛�" prop="type">
<el-select
- v-model="form.type"
- placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
- style="width: 100%"
- @change="handleShippingTypeChange"
+ v-model="form.type"
+ placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
+ style="width: 100%"
+ @change="handleShippingTypeChange"
>
- <el-option label="璐ц溅" value="璐ц溅" />
- <el-option label="蹇��" value="蹇��" />
+ <el-option label="璐ц溅" value="璐ц溅"/>
+ <el-option label="蹇��" value="蹇��"/>
</el-select>
</el-form-item>
</el-col>
@@ -93,13 +100,13 @@
<el-col :span="24">
<el-form-item label="鍙戣揣鏃ユ湡锛�" prop="shippingDate">
<el-date-picker
- style="width: 100%"
- v-model="form.shippingDate"
- value-format="YYYY-MM-DD"
- format="YYYY-MM-DD"
- type="date"
- placeholder="璇烽�夋嫨鍙戣揣鏃ユ湡"
- clearable
+ style="width: 100%"
+ v-model="form.shippingDate"
+ value-format="YYYY-MM-DD"
+ format="YYYY-MM-DD"
+ type="date"
+ placeholder="璇烽�夋嫨鍙戣揣鏃ユ湡"
+ clearable
/>
</el-form-item>
</el-col>
@@ -108,18 +115,18 @@
<el-col :span="24" v-if="form.type === '璐ц溅'">
<el-form-item label="鍙戣揣杞︾墝鍙凤細" prop="shippingCarNumber">
<el-input
- v-model="form.shippingCarNumber"
- placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
- clearable
+ v-model="form.shippingCarNumber"
+ placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
+ clearable
/>
</el-form-item>
</el-col>
<el-col :span="24" v-else>
<el-form-item label="蹇�掑叕鍙革細" prop="expressCompany">
<el-input
- v-model="form.expressCompany"
- placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
- clearable
+ v-model="form.expressCompany"
+ placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
+ clearable
/>
</el-form-item>
</el-col>
@@ -128,9 +135,9 @@
<el-col :span="24">
<el-form-item label="蹇�掑崟鍙凤細" prop="expressNumber">
<el-input
- v-model="form.expressNumber"
- placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
- clearable
+ v-model="form.expressNumber"
+ placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+ clearable
/>
</el-form-item>
</el-col>
@@ -138,29 +145,7 @@
<el-row :gutter="30">
<el-col :span="24">
<el-form-item label="鍙戣揣鍥剧墖锛�">
- <el-upload
- v-model:file-list="deliveryFileList"
- :action="upload.url"
- multiple
- ref="deliveryFileUpload"
- auto-upload
- :headers="upload.headers"
- :data="{ type: 9 }"
- :before-upload="handleDeliveryBeforeUpload"
- :on-error="handleDeliveryUploadError"
- :on-success="handleDeliveryUploadSuccess"
- :on-remove="handleDeliveryRemove"
- list-type="picture-card"
- :limit="9"
- accept="image/png,image/jpeg,image/jpg"
- >
- <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
- <template #tip>
- <div class="el-upload__tip">
- 鏀寔 jpg銆乯peg銆乸ng 鏍煎紡锛屾渶澶氫笂浼� 9 寮狅紝鍗曞紶澶у皬涓嶈秴杩� 10MB
- </div>
- </template>
- </el-upload>
+ <ImageUpload v-model:file-list="deliveryFileList" :limit="9"/>
</el-form-item>
</el-col>
</el-row>
@@ -189,19 +174,7 @@
<el-descriptions-item label="蹇�掑叕鍙�">{{ detailRow.expressCompany || '--' }}</el-descriptions-item>
<el-descriptions-item label="蹇�掑崟鍙�" :span="2">{{ detailRow.expressNumber || '--' }}</el-descriptions-item>
</el-descriptions>
-
- <div class="detail-images" v-if="detailImages.length">
- <div class="detail-images-title">鍙戣揣鍥剧墖</div>
- <el-image
- v-for="img in detailImages"
- :key="img.url"
- :src="img.url"
- :preview-src-list="detailImages.map(i => i.url)"
- fit="cover"
- class="detail-image"
- />
- </div>
- <div v-else class="detail-images-empty">鏆傛棤鍙戣揣鍥剧墖</div>
+ <ImagePreview :file-list="detailRow.storageBlobVOs || []" />
</div>
<template #footer>
<div class="dialog-footer">
@@ -214,20 +187,19 @@
<script setup>
import pagination from "@/components/PIMTable/Pagination.vue";
-import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
-import { ElMessageBox } from "element-plus";
-import { Plus } from "@element-plus/icons-vue";
-import { getToken } from "@/utils/auth";
-import { getCurrentDate } from "@/utils/index.js";
+import {onMounted, ref, reactive, toRefs, getCurrentInstance} from "vue";
+import {ElMessageBox} from "element-plus";
+import {getCurrentDate} from "@/utils/index.js";
import {
- deliveryLedgerListPage,
- addOrUpdateDeliveryLedger,
- delDeliveryLedger, deductStock,
+ deliveryLedgerListPage,
+ delDeliveryLedger, deductStock,
} from "@/api/salesManagement/deliveryLedger.js";
-import { delLedgerFile } from "@/api/salesManagement/salesLedger.js";
-
+import {delLedgerFile} from "@/api/salesManagement/salesLedger.js";
+import ImageUpload from "@/components/AttachmentUpload/image/index.vue";
+import ImagePreview from "@/components/AttachmentPreview/image/index.vue";
-const { proxy } = getCurrentInstance();
+
+const {proxy} = getCurrentInstance();
const tableData = ref([]);
const selectedRows = ref([]);
const tableLoading = ref(false);
@@ -238,40 +210,9 @@
});
const total = ref(0);
const deliveryFileList = ref([]);
-const javaApi = proxy.javaApi;
// 璇︽儏寮规
const detailDialogVisible = ref(false);
const detailRow = ref(null);
-const detailImages = ref([]);
-
-const normalizeFileUrl = (rawUrl = '') => {
- let fileUrl = rawUrl || '';
- // Windows 璺緞杞� URL
- if (fileUrl && fileUrl.indexOf('\\') > -1) {
- const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads');
- if (uploadsIndex > -1) {
- const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/');
- fileUrl = '/' + relativePath;
- } else {
- const parts = fileUrl.split('\\');
- const fileName = parts[parts.length - 1];
- fileUrl = '/uploads/' + fileName;
- }
- }
- if (fileUrl && !fileUrl.startsWith('http')) {
- if (!fileUrl.startsWith('/')) fileUrl = '/' + fileUrl;
- fileUrl = javaApi + fileUrl;
- }
- return fileUrl;
-};
-
-// 涓婁紶閰嶇疆
-const upload = reactive({
- // 涓婁紶鐨勫湴鍧�
- url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
- // 璁剧疆涓婁紶鐨勮姹傚ご閮�
- headers: { Authorization: "Bearer " + getToken() },
-});
// 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
const operationType = ref("");
@@ -295,24 +236,23 @@
expressNumber: "", // 蹇�掑崟鍙�
},
rules: {
- salesContractNo: [{ required: true, message: "璇烽�夋嫨閿�鍞鍗�", trigger: "change" }],
- customerName: [{ required: true, message: "璇疯緭鍏ュ鎴峰悕绉�", trigger: "blur" }],
+ salesContractNo: [{required: true, message: "璇烽�夋嫨閿�鍞鍗�", trigger: "change"}],
+ customerName: [{required: true, message: "璇疯緭鍏ュ鎴峰悕绉�", trigger: "blur"}],
type: [
- { required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }
+ {required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change"}
],
- shippingDate: [{ required: true, message: "璇烽�夋嫨鍙戣揣鏃堕棿", trigger: "change" }],
+ shippingDate: [{required: true, message: "璇烽�夋嫨鍙戣揣鏃堕棿", trigger: "change"}],
shippingCarNumber: [
- { validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" }
+ {validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur"}
],
expressCompany: [
- { validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" }
+ {validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur"}
],
},
});
-const { form, rules } = toRefs(data);
-const { searchForm } = toRefs(data);
+const {form, rules} = toRefs(data);
+const {searchForm} = toRefs(data);
-
// 鏌ヨ鍒楄〃
const handleQuery = () => {
@@ -328,15 +268,15 @@
const getList = () => {
tableLoading.value = true;
- deliveryLedgerListPage({ ...searchForm.value, ...page })
- .then((res) => {
- tableLoading.value = false;
- tableData.value = res.data.records || [];
- total.value = res.data.total || 0;
- })
- .catch(() => {
- tableLoading.value = false;
- });
+ deliveryLedgerListPage({...searchForm.value, ...page})
+ .then((res) => {
+ tableLoading.value = false;
+ tableData.value = res.data.records || [];
+ total.value = res.data.total || 0;
+ })
+ .catch(() => {
+ tableLoading.value = false;
+ });
};
// 閿�鍞鍗曞彉鍖栨椂鑷姩濉厖瀹㈡埛鍚嶇О
@@ -359,10 +299,9 @@
proxy.$modal.msgWarning("鍙湁瀹℃牳閫氳繃鐨勬暟鎹墠鍙互琛ュ厖鍙戣揣淇℃伅");
return;
}
-
+
operationType.value = type;
- const baseUrl = import.meta.env.VITE_APP_BASE_API;
-
+
if (type === 'edit' && row) {
form.value = {
id: row.id ?? null,
@@ -374,43 +313,9 @@
expressCompany: row.expressCompany ?? "",
expressNumber: row.expressNumber ?? "",
};
- // 濡傛灉鏈夊浘鐗囷紝灏� commonFileList 杞崲涓烘枃浠跺垪琛ㄦ牸寮�
- if (row.commonFileList && Array.isArray(row.commonFileList) && row.commonFileList.length > 0) {
- deliveryFileList.value = row.commonFileList.map((file, index) => {
- const fileUrl = normalizeFileUrl(file.url || '');
-
- return {
- uid: file.id || Date.now() + index,
- name: file.name || `image_${index + 1}.jpg`,
- url: fileUrl,
- status: 'success',
- response: {
- code: 200,
- data: {
- tempId: file.id,
- url: fileUrl
- }
- },
- tempId: file.id // 淇濆瓨鏂囦欢ID锛岀敤浜庢彁浜ゆ椂浣跨敤
- };
- });
- } else {
- deliveryFileList.value = [];
- }
- } else {
- form.value = {
- id: null,
- salesContractNo: "",
- customerName: "",
- type: "璐ц溅",
- shippingDate: getCurrentDate(),
- shippingCarNumber: "",
- expressCompany: "",
- expressNumber: "",
- };
- deliveryFileList.value = [];
+ deliveryFileList.value = row.storageBlobVOS || [];
}
-
+
dialogFormVisible.value = true;
};
@@ -418,25 +323,17 @@
const openDetail = (row) => {
detailRow.value = row || null;
const list = Array.isArray(row?.commonFileList) ? row.commonFileList : [];
- detailImages.value = list
- .map((f) => ({ url: normalizeFileUrl(f?.url || '') }))
- .filter((i) => !!i.url);
detailDialogVisible.value = true;
};
const closeDetail = () => {
detailDialogVisible.value = false;
detailRow.value = null;
- detailImages.value = [];
};
// 鎻愪氦琛ㄥ崟
const submitForm = () => {
proxy.$refs["formRef"].validate((valid) => {
if (valid) {
- let tempFileIds = [];
- if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) {
- tempFileIds = deliveryFileList.value.map((item) => item.tempId);
- }
const payload = {
id: form.value.id,
type: form.value.type,
@@ -444,9 +341,9 @@
shippingCarNumber: form.value.type === "璐ц溅" ? form.value.shippingCarNumber : "",
expressCompany: form.value.type === "蹇��" ? form.value.expressCompany : "",
expressNumber: form.value.type === "蹇��" ? form.value.expressNumber : "",
- tempFileIds: tempFileIds,
+ storageBlobDTOs: deliveryFileList.value || [],
};
- deductStock(payload).then((res) => {
+ deductStock(payload).then((res) => {
proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
closeDia();
getList();
@@ -469,12 +366,12 @@
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- proxy.download("/shippingInfo/export", {}, "鍙戣揣鍙拌处.xlsx");
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
+ .then(() => {
+ proxy.download("/shippingInfo/export", {}, "鍙戣揣鍙拌处.xlsx");
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
+ });
};
// 鎵归噺鍒犻櫎
@@ -483,29 +380,29 @@
proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
return;
}
-
+
// 妫�鏌ラ�変腑鐨勮鏄惁鏈�"瀹℃牳涓�"鐘舵��
const approvingRows = selectedRows.value.filter(row => isApproving(row.status));
if (approvingRows.length > 0) {
proxy.$modal.msgWarning("瀹℃牳涓殑鏁版嵁涓嶈兘鍒犻櫎");
return;
}
-
+
const ids = selectedRows.value.map((item) => item.id);
ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- delDeliveryLedger(ids).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
+ .then(() => {
+ delDeliveryLedger(ids).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
});
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
};
// 鍗曚釜鍒犻櫎
@@ -515,21 +412,21 @@
proxy.$modal.msgWarning("瀹℃牳涓殑鏁版嵁涓嶈兘鍒犻櫎");
return;
}
-
+
ElMessageBox.confirm("姝ゆ搷浣滃皢鍒犻櫎璇ヨ褰曪紝鏄惁纭锛�", "鍒犻櫎", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
type: "warning",
})
- .then(() => {
- delDeliveryLedger([row.id]).then((res) => {
- proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
- getList();
+ .then(() => {
+ delDeliveryLedger([row.id]).then((res) => {
+ proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+ getList();
+ });
+ })
+ .catch(() => {
+ proxy.$modal.msg("宸插彇娑�");
});
- })
- .catch(() => {
- proxy.$modal.msg("宸插彇娑�");
- });
};
// 鍙戣揣绫诲瀷鏍¢獙锛氳揣杞︽椂瑕佹眰杞︾墝锛屽揩閫掓椂瑕佹眰蹇�掑叕鍙�
@@ -563,11 +460,13 @@
proxy.$modal.loading("姝e湪涓婁紶鍥剧墖锛岃绋嶅��...");
return true;
}
+
// 鍙戣揣鍥剧墖涓婁紶澶辫触
function handleDeliveryUploadError(err) {
proxy.$modal.msgError("涓婁紶鍥剧墖澶辫触");
proxy.$modal.closeLoading();
}
+
// 鍙戣揣鍥剧墖涓婁紶鎴愬姛鍥炶皟
function handleDeliveryUploadSuccess(res, file, uploadFiles) {
proxy.$modal.closeLoading();
@@ -579,6 +478,7 @@
proxy.$refs.deliveryFileUpload.handleRemove(file);
}
}
+
// 绉婚櫎鍙戣揣鍥剧墖
function handleDeliveryRemove(file) {
console.log('file--', file)
@@ -727,17 +627,21 @@
display: none;
}
}
+
.detail-wrapper {
padding: 8px 0;
}
+
.detail-images {
margin-top: 16px;
}
+
.detail-images-title {
font-weight: 600;
margin-bottom: 10px;
color: #303133;
}
+
.detail-image {
width: 120px;
height: 120px;
@@ -745,6 +649,7 @@
margin-bottom: 10px;
border-radius: 6px;
}
+
.detail-images-empty {
margin-top: 16px;
color: #909399;
--
Gitblit v1.9.3