From 5cfebd7e46c0c53f79b5fb4a917e926194ab4398 Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期五, 24 四月 2026 14:19:14 +0800
Subject: [PATCH] feat(生产订单): 完善绑定工艺路线弹窗功能及文件预览组件
---
src/views/productionManagement/productionOrder/BindRouteDialog.vue | 381 ++++++++++++++++++++++++++++++++++++-----
src/views/productionManagement/productionOrder/index.vue | 28 ++-
src/components/Upload/ActionFileUpload.vue | 68 +++++++
src/components/filePreview/index.vue | 9
src/views/collaborativeApproval/knowledgeBase/index.vue | 2
5 files changed, 420 insertions(+), 68 deletions(-)
diff --git a/src/components/Upload/ActionFileUpload.vue b/src/components/Upload/ActionFileUpload.vue
index 2d20b60..8a929e0 100644
--- a/src/components/Upload/ActionFileUpload.vue
+++ b/src/components/Upload/ActionFileUpload.vue
@@ -7,14 +7,17 @@
ref="fileUploadRef"
:auto-upload="autoUpload"
:headers="headers"
+ :limit="limit"
+ :disabled="disabled"
:before-upload="handleBeforeUpload"
+ :on-exceed="handleExceed"
:on-error="handleUploadError"
:on-success="handleUploadSuccess"
:on-remove="handleRemove"
:on-preview="handlePreview"
:show-file-list="showFileList"
>
- <el-button type="primary">{{ buttonText }}</el-button>
+ <el-button v-if="!disabled" type="primary">{{ buttonText }}</el-button>
<template #file="{ file }">
<div style="display:flex; align-items:center; gap: 10px; width: 100%;">
<span style="flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">
@@ -23,7 +26,7 @@
<div style="display:flex; align-items:center; gap: 6px;">
<el-button link type="success" :icon="Download" @click="handleDownload(file)" />
<el-button link type="primary" :icon="View" @click="handlePreview(file)" />
- <el-button link type="danger" :icon="Delete" @click="triggerRemoveFile(file)" />
+ <el-button link type="danger" :icon="Delete" @click="triggerRemoveFile(file)" v-if="onView" />
</div>
</div>
</template>
@@ -60,6 +63,14 @@
type: Boolean,
default: true,
},
+ limit: {
+ type: Number,
+ default: undefined,
+ },
+ replaceOnExceed: {
+ type: Boolean,
+ default: false,
+ },
autoUpload: {
type: Boolean,
default: true,
@@ -67,6 +78,10 @@
showFileList: {
type: Boolean,
default: true,
+ },
+ disabled: {
+ type: Boolean,
+ default: false,
},
buttonText: {
type: String,
@@ -100,6 +115,10 @@
type: Function,
default: null,
},
+ onView: {
+ type: Boolean,
+ default: true,
+ },
});
const emit = defineEmits([
@@ -118,8 +137,27 @@
set: (val) => emit("update:fileList", val),
});
+const resolveUrl = (url) => {
+ const u = String(url || "");
+ if (!u) return "";
+ if (/^(https?:)?\/\//i.test(u)) return u;
+ if (/^(blob:|data:)/i.test(u)) return u;
+ const baseUrl = import.meta.env.VITE_APP_BASE_API || "";
+ if (!baseUrl) return u;
+ if (u.startsWith("/")) return baseUrl + u;
+ return baseUrl + "/" + u;
+};
+
const getFileUrl = (file) => {
- return file?.url || file?.response?.data?.tempPath || file?.response?.data?.url || "";
+ const respData = file?.response?.data;
+ const rawUrl =
+ file?.url ||
+ (Array.isArray(respData) ? respData?.[0]?.fileUrl : undefined) ||
+ respData?.fileUrl ||
+ respData?.tempPath ||
+ respData?.url ||
+ "";
+ return resolveUrl(rawUrl);
};
const triggerRemoveFile = (file) => {
@@ -138,7 +176,31 @@
emit("error", ...args);
};
+const handleExceed = (files) => {
+ if (!props.replaceOnExceed) return;
+ if (props.limit !== 1) return;
+ const file = files?.[0];
+ if (!file) return;
+ fileUploadRef.value?.clearFiles?.();
+ innerFileList.value = [];
+ fileUploadRef.value?.handleStart?.(file);
+ if (props.autoUpload) {
+ fileUploadRef.value?.submit?.();
+ }
+};
+
const handleUploadSuccess = (...args) => {
+ const [response, uploadFile, uploadFiles] = args;
+ if (uploadFile && !uploadFile.url) {
+ const rawUrl = response?.data?.tempPath || response?.data?.url || response?.url || "";
+ const resolvedUrl = resolveUrl(rawUrl);
+ if (resolvedUrl) {
+ uploadFile.url = resolvedUrl;
+ }
+ }
+ if (props.limit === 1 && Array.isArray(uploadFiles) && uploadFiles.length) {
+ innerFileList.value = [uploadFiles[uploadFiles.length - 1]];
+ }
props.onSuccess?.(...args);
emit("success", ...args);
};
diff --git a/src/components/filePreview/index.vue b/src/components/filePreview/index.vue
index cda5b56..82cee78 100644
--- a/src/components/filePreview/index.vue
+++ b/src/components/filePreview/index.vue
@@ -88,7 +88,6 @@
});
const isPdf = computed(() => {
- console.log(fileUrl.value)
return /\.pdf$/i.test(fileUrl.value);
});
@@ -167,6 +166,11 @@
fileUrl.value = window.location.protocol+'//'+window.location.host+ url;
dialogVisible.value = true;
};
+
+const openUrl = (url) => {
+ fileUrl.value = url;
+ dialogVisible.value = true;
+}
const handleClose = () => {
dialogVisible.value = false;
};
@@ -183,7 +187,8 @@
// 鏆撮湶open鏂规硶渚涘閮ㄨ皟鐢�
defineExpose({
- open
+ open,
+ openUrl
})
</script>
diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index ff8da1b..1104880 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -767,6 +767,7 @@
// 鏂囦欢棰勮/涓嬭浇
const handleDownload = (file) => {
+ console.log(file)
const url = getUploadFileUrl(file)
if (!url) return
proxy?.$modal?.loading?.("姝e湪涓嬭浇鏂囦欢锛岃绋嶅��...")
@@ -775,6 +776,7 @@
}
function handlePreview(file) {
+ console.log(file)
const url = getUploadFileUrl(file)
if (!url) return
filePreviewRef.value?.open?.(url)
diff --git a/src/views/productionManagement/productionOrder/BindRouteDialog.vue b/src/views/productionManagement/productionOrder/BindRouteDialog.vue
index dcededa..484b950 100644
--- a/src/views/productionManagement/productionOrder/BindRouteDialog.vue
+++ b/src/views/productionManagement/productionOrder/BindRouteDialog.vue
@@ -1,7 +1,7 @@
<template>
<FormDialog
v-model="visible"
- :title="type === 'add' ? '缁戝畾宸ヨ壓璺嚎' : '缂栬緫宸ヨ壓璺嚎'"
+ :title="type === 'add' ? '缁戝畾宸ヨ壓璺嚎' : type === 'detail' ? '鏌ョ湅宸ヨ壓璺嚎' : '缂栬緫宸ヨ壓璺嚎'"
width="1400px"
:operation-type="type"
:column="8"
@@ -9,6 +9,7 @@
@confirm="handleConfirm"
@cancel="handleClose"
>
+ <div :class="{ 'is-detail': isDetail }">
<!-- ================= 鍩烘湰淇℃伅 ================= -->
<el-descriptions :column="3">
<el-descriptions-item label="缂栧彿" align="center" v-if="formData.productOrderList">
@@ -34,7 +35,7 @@
</el-descriptions-item>
<el-descriptions-item label="鎴愬搧灏哄" :span="1" align="center">
- {{formData.specificationModel || "--"}}
+ {{formData.finishedSize || "--"}}
</el-descriptions-item>
<el-descriptions-item label="浜у搧鍚嶇О" :span="2" align="center">
@@ -42,7 +43,7 @@
</el-descriptions-item>
<el-descriptions-item label="鍗曟嵁绫诲瀷" :span="2" align="center">
- <el-checkbox-group v-model="introductionLetterList">
+ <el-checkbox-group v-model="introductionLetterList" :disabled="isDetail">
<el-checkbox label="浠嬬粛淇�" value="浠嬬粛淇�" />
<el-checkbox label="鍟嗘爣娉ㄥ唽涔�" value="鍟嗘爣娉ㄥ唽涔�" />
<el-checkbox label="濮斿嵃鍗�" value="濮斿嵃鍗�" />
@@ -53,12 +54,13 @@
<!-- ================= 鏉愭枡琛� ================= -->
<div class="process-table-header">
<div class="section-title">鏉愭枡淇℃伅</div>
- <el-button type="primary" size="small" @click="addMaterialRow">鏂板涓�琛�</el-button>
+ <el-button v-if="!isDetail" type="primary" size="small" @click="addMaterialRow">鏂板涓�琛�</el-button>
</div>
<el-table border :data="formData.materialInfo" style="width: 100%">
<el-table-column label="鏉愭枡鍚嶇О">
- <template #default="{ row }">
+ <template #default="{ row }" >
<el-tree-select
+ v-if="!isDetail"
v-model="row.productId"
placeholder="璇烽�夋嫨"
clearable
@@ -66,18 +68,22 @@
@change="(val) => getModels(val, row)"
:data="productOptions"
:render-after-expand="false"
+ :disabled="isDetail"
style="width: 100%"
/>
- </template>
+ <span v-else>{{ row.name }}</span>
+ </template>
</el-table-column>
<el-table-column label="瑙勬牸">
<template #default="{ row }">
<el-select
+ v-if="!isDetail"
v-model="row.productModelId"
placeholder="璇烽�夋嫨瑙勬牸"
filterable
clearable
@change="(val) => handleMaterialModelChange(val, row)"
+ :disabled="isDetail"
>
<el-option
v-for="item in row.modelOptions || []"
@@ -86,33 +92,32 @@
:value="item.id"
/>
</el-select>
+ <span v-else>{{ row.model }}</span>
</template>
</el-table-column>
<el-table-column label="鏁伴噺">
<template #default="{ row }">
- <el-input v-model="row.num" placeholder="鏁伴噺">
- <template #append>{{ row.numSuffix }}</template>
+ <el-input v-model="row.num" placeholder="鏁伴噺" :disabled="isDetail">
</el-input>
</template>
</el-table-column>
<el-table-column label="璁¢噺鍗曚綅">
<template #default="{ row }">
- <el-input v-model="row.unit" placeholder="璁¢噺鍗曚綅" />
+ <el-input v-model="row.unit" placeholder="璁¢噺鍗曚綅" :disabled="isDetail" />
</template>
</el-table-column>
<el-table-column label="鍗曚环">
<template #default="{ row }">
- <el-input v-model="row.price" placeholder="鍗曚环">
- <template #append>{{ row.unitSuffix }}</template>
+ <el-input v-model="row.price" placeholder="鍗曚环" :disabled="isDetail">
</el-input>
</template>
</el-table-column>
<el-table-column label="閲戦">
<template #default="{ row }">
- <el-input v-model="row.totalAmount" placeholder="閲戦" />
+ <el-input v-model="row.totalAmount" placeholder="閲戦" :disabled="isDetail" />
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔" width="80">
+ <el-table-column v-if="!isDetail" label="鎿嶄綔" width="80">
<template #default="{ $index }">
<el-button type="danger" size="small" @click="removeMaterialRow($index)">鍒犻櫎</el-button>
</template>
@@ -130,20 +135,34 @@
:autosize="{ minRows: 2, maxRows: 4 }"
type="textarea"
placeholder="璇疯緭鍏ユ敞鎰忎簨椤�"
+ :disabled="isDetail"
/>
</el-descriptions-item>
</el-descriptions>
- <hr>
<!-- ================= 鍒囨枡鍥剧ず ================= -->
<div class="section-title">鍒囨枡鍥剧ず</div>
<ActionFileUpload
- style="width: 50%;"
- v-model:file-list="fileList"
+ style="width: 50%;float: left;"
+ v-model:file-list="formData.cuttingFileVo"
:action="upload.url"
:headers="upload.headers"
:multiple="false"
+ :limit="1"
+ :replaceOnExceed="true"
+ :disabled="isDetail"
:name="'files'"
- tip-text="鏀寔鍥剧墖锛坖pg, jpeg, png锛夋牸寮�"
+ :onSuccess="onSuccess"
+ :onDownload="onDownload"
+ :onRemove="onRemove"
+ :onPreview="onPreview"
+ :onView="type === 'detail' ? false : true"
+ :tip-text="type === 'detail' ? '' : '鏀寔鍥剧墖锛坖pg, jpeg, png锛夋牸寮�'"
+ />
+ <el-image
+ v-if="formData.cuttingFileVo.length > 0"
+ style="width: 100px; height: 100px"
+ :src="resolveFileUrl(getUploadFileUrl(formData.cuttingFileVo[0]))"
+ fit="cover"
/>
<!-- ================= 鍒囨枡淇℃伅 ================= -->
<el-descriptions
@@ -154,22 +173,22 @@
class="fixed-desc"
>
<el-descriptions-item label="鍒囨枡灏哄" align="center">
- <el-input v-model="formData.cutNum" placeholder="鍒囨枡灏哄" />
+ <el-input v-model="formData.cutNum" placeholder="鍒囨枡灏哄" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="鍒囨枡鏁伴噺" align="center">
- <el-input v-model="formData.cutSize" placeholder="鍒囨枡灏哄" />
+ <el-input v-model="formData.cutSize" placeholder="鍒囨枡灏哄" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="涓洅鏁伴噺" align="center">
- <el-input v-model="formData.mediumBoxQty" placeholder="涓洅鏁伴噺" />
+ <el-input v-model="formData.mediumBoxQty" placeholder="涓洅鏁伴噺" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="灏忕洅鏁伴噺" align="center">
- <el-input v-model="formData.smallBoxQty" placeholder="灏忕洅鏁伴噺" />
+ <el-input v-model="formData.smallBoxQty" placeholder="灏忕洅鏁伴噺" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="姝f暟" align="center">
- <el-input v-model="formData.positiveQty" placeholder="姝f暟" />
+ <el-input v-model="formData.positiveQty" placeholder="姝f暟" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="鍔犳斁鏁�" align="center">
- <el-input v-model="formData.allowanceQty" placeholder="鍔犳斁鏁�" />
+ <el-input v-model="formData.allowanceQty" placeholder="鍔犳斁鏁�" :disabled="isDetail" />
</el-descriptions-item>
</el-descriptions>
@@ -196,25 +215,25 @@
</tr>
<tr v-for="(plate, index) in formData.plateMaking" :key="index">
<td>
- <el-input v-model="plate.designProductionFee" placeholder="璇疯緭鍏ヨ璁″埗浣滆垂" />
+ <el-input v-model="plate.designProductionFee" placeholder="璇疯緭鍏ヨ璁″埗浣滆垂" :disabled="isDetail" />
</td>
<td>
- <el-input v-model="plate.impositionFee" placeholder="璇疯緭鍏ユ嫾鐗堣垂" />
+ <el-input v-model="plate.impositionFee" placeholder="璇疯緭鍏ユ嫾鐗堣垂" :disabled="isDetail" />
</td>
<td>
- <el-input v-model="plate.filmOutputFee" placeholder="璇疯緭鍏ュ嚭鐗囪垂" />
+ <el-input v-model="plate.filmOutputFee" placeholder="璇疯緭鍏ュ嚭鐗囪垂" :disabled="isDetail" />
</td>
<td>
- <el-input v-model="plate.proofingFee" placeholder="璇疯緭鍏ユ墦鏍疯垂" />
+ <el-input v-model="plate.proofingFee" placeholder="璇疯緭鍏ユ墦鏍疯垂" :disabled="isDetail" />
</td>
<td>
- <el-input v-model="plate.doctorBladePlateFee" placeholder="璇疯緭鍏ュ埆鍒�鐗堣垂" />
+ <el-input v-model="plate.doctorBladePlateFee" placeholder="璇疯緭鍏ュ埆鍒�鐗堣垂" :disabled="isDetail" />
</td>
<td>
- <el-input v-model="plate.hotEmbossingPlateFee" placeholder="璇疯緭鍏ョ儷/鍑哥増璐�" />
+ <el-input v-model="plate.hotEmbossingPlateFee" placeholder="璇疯緭鍏ョ儷/鍑哥増璐�" :disabled="isDetail" />
</td>
<td>
- <el-input v-model="plate.subtotalFee" placeholder="璇疯緭鍏ュ皬璁�" />
+ <el-input v-model="plate.subtotalFee" placeholder="璇疯緭鍏ュ皬璁�" :disabled="isDetail" />
</td>
</tr>
</tbody>
@@ -224,17 +243,16 @@
<!-- ================= 宸ヨ壓鍔犲伐 ================= -->
<div class="process-table-header">
<div class="section-title">宸ヨ壓鍔犲伐</div>
- <el-button type="primary" size="small" @click="addProcessRow">鏂板涓�琛�</el-button>
+ <el-button v-if="!isDetail" type="primary" size="small" @click="addProcessRow">鏂板涓�琛�</el-button>
</div>
<el-table border :data="formData.processContent" style="width: 100%" :span-method="objectSpanMethod">
- <el-table-column label="宸ュ簭" width="140">
- <template #default="{ row }">
<el-table-column label="宸ュ簭" width="140">
<template #default="{ row }">
<el-select
v-model="row.processId"
placeholder="璇烽�夋嫨宸ュ簭"
@change="(val) => onProcessChange(val, row)"
+ :disabled="isDetail"
>
<el-option
v-for="item in processOptions"
@@ -245,24 +263,25 @@
</el-select>
</template>
</el-table-column>
- </template>
- </el-table-column>
<el-table-column label="寮�鏁�">
<template #default="{ row }">
- <el-input v-model="row.openCount" placeholder="璇疯緭鍏ュ紑鏁�" />
+ <el-input v-model="row.openCount" placeholder="璇疯緭鍏ュ紑鏁�" :disabled="isDetail" />
</template>
</el-table-column>
<el-table-column label="宸ヨ壓姝f暟">
<template #default="{ row }">
- <el-input v-model="row.processPositive" placeholder="璇疯緭鍏ュ伐鑹烘鏁�" />
+ <el-input v-model="row.processPositive" placeholder="璇疯緭鍏ュ伐鑹烘鏁�" :disabled="isDetail" />
</template>
</el-table-column>
<el-table-column label="鍔犳斁鏁�">
<template #default="{ row }">
- <el-input v-model="row.allowanceQty" placeholder="璇疯緭鍏ュ姞鏀炬暟" />
+ <el-input v-model="row.allowanceQty" placeholder="璇疯緭鍏ュ姞鏀炬暟" :disabled="isDetail" />
</template>
</el-table-column>
- <el-table-column label="鏈哄彴" width="180">
+ <el-table-column width="180">
+ <template #header>
+ <span class="required">*</span>鏈哄彴
+ </template>
<template #default="{ row }">
<el-select
v-model="row.deviceId"
@@ -270,6 +289,7 @@
filterable
clearable
@change="(val) => handleDeviceChange(val, row)"
+ :disabled="isDetail"
>
<el-option
v-for="item in deviceOptions"
@@ -280,9 +300,13 @@
</el-select>
</template>
</el-table-column>
- <el-table-column label="鎶ュ伐浜�" width="220">
+ <el-table-column width="220">
+ <template #header>
+ <span class="required">*</span>鎶ュ伐浜�
+ </template>
<template #default="{ row }">
<el-select
+ v-if="!isDetail"
v-model="row.reportUserIds"
placeholder="璇烽�夋嫨鎶ュ伐浜�"
filterable
@@ -291,6 +315,7 @@
collapse-tags
collapse-tags-tooltip
@change="(val) => handleReportUsersChange(val, row)"
+ :disabled="isDetail"
>
<el-option
v-for="item in userOptions"
@@ -299,6 +324,14 @@
:value="item.userId"
/>
</el-select>
+ <el-tag
+ v-else
+ v-for="item in row.reportWorkerList"
+
+ :key="item.id"
+ >
+ {{ item.userName }}
+ </el-tag>
</template>
</el-table-column>
<el-table-column label="宸ヨ壓瑕佹眰">
@@ -308,10 +341,11 @@
type="textarea"
:rows="6"
placeholder="璇疯緭鍏ュ伐鑹鸿姹�"
+ :disabled="isDetail"
/>
</template>
</el-table-column>
- <el-table-column label="鎿嶄綔" width="80">
+ <el-table-column v-if="!isDetail" label="鎿嶄綔" width="80">
<template #default="{ $index }">
<el-button type="danger" size="small" @click="removeProcessRow($index)">鍒犻櫎</el-button>
</template>
@@ -321,19 +355,19 @@
<!-- ================= 鍖呰淇℃伅 ================= -->
<el-descriptions border :column="3" class="mt">
<el-descriptions-item label="閫佽揣鍦扮偣" align="center">
- <el-input v-model="formData.deliveryAddress" placeholder="閫佽揣鍦扮偣" />
+ <el-input v-model="formData.deliveryAddress" placeholder="閫佽揣鍦扮偣" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="鑱旂郴浜�" align="center">
- <el-input v-model="formData.contactName" placeholder="鑱旂郴浜�" />
+ <el-input v-model="formData.contactName" placeholder="鑱旂郴浜�" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="鍖呰瑕佹眰" align="center">
- <el-input v-model="formData.packagingRequirement" placeholder="鍖呰瑕佹眰" />
+ <el-input v-model="formData.packagingRequirement" placeholder="鍖呰瑕佹眰" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="灏哄" align="center">
- <el-input v-model="formData.postProcessSize" placeholder="灏哄" />
+ <el-input v-model="formData.postProcessSize" placeholder="灏哄" :disabled="isDetail" />
</el-descriptions-item>
<el-descriptions-item label="瀹氳揣鏁伴噺" align="center">
@@ -341,14 +375,16 @@
</el-descriptions-item>
<el-descriptions-item label="瀹炰氦鏁伴噺" :span="3" align="center">
- <el-input v-model="formData.actualDeliveryQty" placeholder="瀹炰氦鏁伴噺" />
+ <el-input v-model="formData.actualDeliveryQty" placeholder="瀹炰氦鏁伴噺" :disabled="isDetail" />
</el-descriptions-item>
</el-descriptions>
+ </div>
</FormDialog>
+ <filePreview ref="filePreviewRef" />
</template>
<script setup>
-import { ref, reactive, computed, onMounted, watch } from 'vue'
+import { ref, reactive, computed, onMounted, watch, getCurrentInstance } from 'vue'
import dayjs from 'dayjs'
import FormDialog from '@/components/Dialog/FormDialog.vue'
import ActionFileUpload from "@/components/Upload/ActionFileUpload.vue";
@@ -358,6 +394,8 @@
import { getDeviceLedger } from "@/api/equipmentManagement/ledger.js"
import { userListNoPageByTenantId } from "@/api/system/user.js"
import { getToken } from "@/utils/auth";
+import filePreview from '@/components/filePreview/index.vue'
+import { ElMessage } from "element-plus";
const props = defineProps({
modelValue: {
@@ -379,30 +417,31 @@
})
const emit = defineEmits(['update:modelValue', 'confirm'])
+const { proxy } = getCurrentInstance()
const visible = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
+const isDetail = computed(() => props.type === 'detail')
const processOptions = ref([])
const deviceOptions = ref([])
const userOptions = ref([])
-const reportWorkerList = ref([])
const productOptions = ref([])
const introductionLetterList = ref([])
-const fileList = ref([])
const upload = reactive({
url: import.meta.env.VITE_APP_BASE_API + '/basic/customer-follow/upload',
headers: { Authorization: 'Bearer ' + getToken() }
})
+const filePreviewRef = ref()
const formData = reactive({
productOrderList:null,
salesLedgerId: null,
productOrderId: null,
printOrderTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
- fileList:[],
+ cuttingFileVo:[],
finishTime: "",
no: "",
productName: "",
@@ -473,16 +512,158 @@
specificationModel:"",
})
+const getUploadFileUrl = (file) => {
+ console.log("file", file)
+ const response = file?.response
+ const data = response?.data
+ if (Array.isArray(data) && data.length) {
+ return data[0]?.fileUrl || data[0]?.url || data[0]?.tempPath || ""
+ }
+
+ return file?.url || file?.fileUrl || data?.tempPath || data?.url || data?.fileUrl || ""
+}
+
// 鐩戝惉 checkbox group 鍙樺寲骞跺悓姝ュ埌 introductionLetter 瀛楃涓�
watch(introductionLetterList, (val) => {
formData.introductionLetter = val.join(',')
})
const onProcessChange = (processId, row) => {
- const selected = processOptions.find(item => item.id === processId)
+ const selected = processOptions.value.find(item => item.id === processId)
row.processName = selected?.name || ''
}
const cloneDeep = (val) => JSON.parse(JSON.stringify(val))
+const createDefaultFormData = () => ({
+ productOrderList: null,
+ salesLedgerId: null,
+ productOrderId: null,
+ printOrderTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
+ cuttingFileVo: [],
+ finishTime: "",
+ no: "",
+ productName: "",
+ productDescription: "",
+ clientName: "",
+ finishedSize: "",
+ cutNum: "",
+ cutSize: "",
+ mediumBoxQty: "",
+ smallBoxQty: "",
+ positiveQty: "",
+ allowanceQty: "",
+ introductionLetter: "",
+ plateMaking: [
+ {
+ designProductionFee: "",
+ impositionFee: "",
+ filmOutputFee: "",
+ proofingFee: "",
+ doctorBladePlateFee: "",
+ hotEmbossingPlateFee: "",
+ subtotalFee: ""
+ }
+ ],
+ processContent: [
+ {
+ id: "1",
+ processId: "",
+ processName: "",
+ mediumBoxQty: "",
+ smallBoxQty: "",
+ openCount: "",
+ processPositive: "",
+ allowanceQty: "",
+ deviceId: "",
+ deviceName: "",
+ reportUserIds: [],
+ reportWorkerList: []
+ }
+ ],
+ materialInfo: [
+ {
+ id: "1",
+ productId: "",
+ name: "",
+ productModelId: "",
+ model: "",
+ modelOptions: [],
+ num: "",
+ numSuffix: "寮�",
+ unitSuffix: "鍏�/kg",
+ unit: "",
+ price: "",
+ totalAmount: ""
+ }
+ ],
+ processRequirement: "",
+ deliveryAddress: "",
+ contactName: "",
+ packagingRequirement: "",
+ postProcessSize: "",
+ orderQty: "",
+ actualDeliveryQty: "",
+ productionDept: "",
+ technicalDept: "",
+ warehouseDept: "",
+ productModelId: "",
+ specificationModel: "",
+ cuttingFileId:""
+})
+
+const resetForm = () => {
+ const next = createDefaultFormData()
+ Object.keys(next).forEach((key) => {
+ formData[key] = Array.isArray(next[key]) ? cloneDeep(next[key]) : next[key]
+ })
+ introductionLetterList.value = []
+}
+
+const onSuccess = (response, uploadFile, uploadFiles) => {
+ const data = response?.data
+
+ if (uploadFile && !uploadFile.url) {
+ uploadFile.url = (Array.isArray(data) ? data?.[0]?.fileUrl : data?.fileUrl) || data?.tempPath || data?.url || response?.url || ""
+ }
+ if (Array.isArray(uploadFiles) && uploadFiles.length) {
+ formData.cuttingFileVo = [uploadFiles[uploadFiles.length - 1]]
+ formData.cuttingFileId = data?.[0]?.id || ""
+ }
+}
+
+const JavaApi = computed(() => proxy?.javaApi || "")
+
+const onRemove = (file) => {
+ formData.cuttingFileVo = []
+ formData.cuttingFileId = ""
+}
+
+const resolveFileUrl = (rawUrl) => {
+ console.log("rawUrl", rawUrl)
+ const u = String(rawUrl || "")
+ if (!u) return ""
+ if (/^(https?:)?\/\//i.test(u)) return u
+ if (/^(blob:|data:)/i.test(u)) return u
+ const base = String(JavaApi.value || "").replace(/\/+$/, "")
+ if (!base) return u
+ if (u.startsWith("/")) return base + u
+ return base + "/" + u
+}
+
+// 鏂囦欢棰勮/涓嬭浇
+const onDownload = (file) => {
+ console.log(file)
+ const url = resolveFileUrl(getUploadFileUrl(file))
+ if (!url) return
+ proxy?.$modal?.loading?.("姝e湪涓嬭浇鏂囦欢锛岃绋嶅��...")
+ proxy.$download.name(url);
+ proxy?.$modal?.closeLoading?.()
+}
+
+const onPreview = (file) => {
+ const url = resolveFileUrl(getUploadFileUrl(file))
+ if (!url) return
+ filePreviewRef.value?.openUrl?.(url);
+}
const mergeRowDataToForm = (source) => {
@@ -495,6 +676,19 @@
formData[key] = Array.isArray(source[key]) ? cloneDeep(source[key]) : source[key]
}
})
+
+ if (formData.cuttingFileVo && !Array.isArray(formData.cuttingFileVo)) {
+ formData.cuttingFileVo = [formData.cuttingFileVo]
+ }
+ if (Array.isArray(formData.cuttingFileVo)) {
+ formData.cuttingFileVo = formData.cuttingFileVo
+ .filter(Boolean)
+ .map((f) => ({
+ ...f,
+ name: f?.name || f?.fileName || "",
+ url: f?.url || f?.fileUrl || "",
+ }))
+ }
// 鍏煎 index.vue 閲屽父鐢ㄥ瓧娈靛悕涓庡脊绐楀瓧娈靛悕涓嶄竴鑷寸殑鎯呭喌
if (source.productName === undefined && source.productCategory !== undefined) {
@@ -512,6 +706,11 @@
if (source.productOrderId === undefined && source.id !== undefined) {
formData.productOrderId = source.id
}
+
+ introductionLetterList.value = String(formData.introductionLetter || "")
+ .split(",")
+ .map(s => s.trim())
+ .filter(Boolean)
}
// 鑾峰彇閿�鍞鍗�
@@ -704,7 +903,30 @@
}
const handleConfirm = () => {
- emit('confirm', JSON.parse(JSON.stringify(formData)))
+ if (isDetail.value) {
+ return
+ }
+ const rows = Array.isArray(formData.processContent) ? formData.processContent : []
+ for (let i = 0; i < rows.length; i++) {
+ const row = rows[i] || {}
+ if (!row.deviceId) {
+ ElMessage.warning(`宸ヨ壓鍔犲伐绗�${i + 1}琛岋細鏈哄彴蹇呭~`)
+ return
+ }
+ if (!Array.isArray(row.reportUserIds) || row.reportUserIds.length === 0) {
+ ElMessage.warning(`宸ヨ壓鍔犲伐绗�${i + 1}琛岋細鎶ュ伐浜哄繀濉玚)
+ return
+ }
+ }
+ const payload = cloneDeep(formData)
+ delete payload.productOrderList
+ if (Array.isArray(payload.materialInfo)) {
+ payload.materialInfo = payload.materialInfo.map((item) => {
+ const { modelOptions, ...rest } = item || {}
+ return rest
+ })
+ }
+ emit('confirm', payload)
}
onMounted(() => {
@@ -714,7 +936,8 @@
getMaterialProductOptions()
})
defineExpose({
- getProductOrder
+ getProductOrder,
+ resetForm
})
</script>
@@ -784,7 +1007,59 @@
.mt {
margin-top: 20px;
}
+:deep(.required) {
+ color: #f56c6c;
+}
:deep(.el-textarea__inner){
box-shadow: none;
}
+
+.is-detail {
+ :deep(.el-input__wrapper) {
+ box-shadow: none !important;
+ background-color: transparent !important;
+ }
+
+ :deep(.el-input__inner) {
+ color: var(--el-text-color-regular) !important;
+ -webkit-text-fill-color: var(--el-text-color-regular) !important;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ :deep(.el-input-group__append),
+ :deep(.el-input-group__prepend) {
+ background-color: transparent !important;
+ box-shadow: none !important;
+ color: var(--el-text-color-regular) !important;
+ }
+
+ :deep(.el-select__wrapper) {
+ box-shadow: none !important;
+ background-color: transparent !important;
+ }
+
+ :deep(.el-select__selected-item) {
+ color: var(--el-text-color-regular) !important;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+ :deep(.el-select__caret) {
+ display: none;
+ }
+
+ :deep(.el-textarea__inner) {
+ box-shadow: none !important;
+ background-color: transparent !important;
+ color: var(--el-text-color-regular) !important;
+ -webkit-text-fill-color: var(--el-text-color-regular) !important;
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ }
+}
</style>
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 15e7cba..d2cf5f1 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -110,7 +110,13 @@
const handleBindRouteSubmit =async (data)=>{
const res = await saveProductionProductInput(data)
- console.log(res)
+ if(res.code === 200){
+ proxy.$modal.msgSuccess("缁戝畾鎴愬姛");
+ bindRouteDialogVisible.value = false
+ handleQuery()
+ }else{
+ proxy.$modal.msgError(res.msg || "缁戝畾澶辫触")
+ }
}
@@ -279,18 +285,20 @@
const openBindRouteDialog = async (row,type) => {
bindForm.orderId = row.id;
bindForm.routeId = null;
- bindRouteDialogVisible.value = true;
routeOptions.value = [];
bindRouteLoading.value = true;
- if(type === "view") {
- bindDialogType.value = "view"
- let res = await viewGetByProductWordId(row.id)
- console.log(res)
- }
- BindRouteDialogRef.value?.getProductOrder()
-
try {
- rowData.value = row;
+ BindRouteDialogRef.value?.resetForm?.()
+ if (type === "view") {
+ bindDialogType.value = "detail"
+ const res = await viewGetByProductWordId(row.id)
+ rowData.value = res?.data || res
+ } else {
+ bindDialogType.value = "add"
+ rowData.value = row
+ rowData.value.finishedSize = row.specificationModel
+ }
+ bindRouteDialogVisible.value = true;
} catch (e) {
console.error("鑾峰彇宸ヨ壓璺嚎鍒楄〃澶辫触锛�", e);
proxy.$modal.msgError("鑾峰彇宸ヨ壓璺嚎鍒楄〃澶辫触");
--
Gitblit v1.9.3