From 70ed2d656562b2c26b4dfdd829324f2837dede21 Mon Sep 17 00:00:00 2001
From: 张诺 <zhang_12370@163.com>
Date: 星期一, 27 四月 2026 16:05:20 +0800
Subject: [PATCH] 阳光印刷Web: 调整重复点击绑定工艺路线 浅拷贝数据问题

---
 src/views/productionManagement/productionOrder/BindRouteDialog.vue | 1014 +++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 675 insertions(+), 339 deletions(-)

diff --git a/src/views/productionManagement/productionOrder/BindRouteDialog.vue b/src/views/productionManagement/productionOrder/BindRouteDialog.vue
index dcededa..4b72ee1 100644
--- a/src/views/productionManagement/productionOrder/BindRouteDialog.vue
+++ b/src/views/productionManagement/productionOrder/BindRouteDialog.vue
@@ -1,181 +1,219 @@
 <template>
   <FormDialog
-    v-model="visible"
-    :title="type === 'add' ? '缁戝畾宸ヨ壓璺嚎' : '缂栬緫宸ヨ壓璺嚎'"
-    width="1400px"
-    :operation-type="type"
-    :column="8"
-    @close="handleClose"
-    @confirm="handleConfirm"
-    @cancel="handleClose"
+      v-model="visible"
+      :title="type === 'add' ? '缁戝畾宸ヨ壓璺嚎' : type === 'detail' ? '鏌ョ湅宸ヨ壓璺嚎' : '缂栬緫宸ヨ壓璺嚎'"
+      width="1400px"
+      :operation-type="type"
+      :column="8"
+      @close="handleClose"
+      @confirm="handleConfirm"
+      @cancel="handleClose"
   >
-    <!-- ================= 鍩烘湰淇℃伅 ================= -->
-    <el-descriptions :column="3">
-      <el-descriptions-item label="缂栧彿" align="center" v-if="formData.productOrderList">
-        {{ formData.productOrderList.salesContractNo || "鏆傛棤鏁版嵁" }}
-      </el-descriptions-item>
+    <div :class="{ 'is-detail': isDetail }">
+      <!-- ================= 鍩烘湰淇℃伅 ================= -->
+      <el-descriptions :column="3">
+        <el-descriptions-item label="缂栧彿" align="center" v-if="formData.productOrderList">
+          {{ formData.productOrderList.salesContractNo || "鏆傛棤鏁版嵁" }}
+        </el-descriptions-item>
 
-      <el-descriptions-item label="鍒跺崟鏃ユ湡" align="center" v-if="formData.productOrderList">
-        {{ formData.productOrderList.entryDate || "鏆傛棤鏁版嵁" }}
-      </el-descriptions-item>
+        <el-descriptions-item label="鍒跺崟鏃ユ湡" align="center" v-if="formData.productOrderList">
+          {{ formData.productOrderList.entryDate || "鏆傛棤鏁版嵁" }}
+        </el-descriptions-item>
 
-      <el-descriptions-item label="浜や粯鏃ユ湡" align="center" v-if="formData.productOrderList">
-        {{ formData.productOrderList.deliveryDate || "鏆傛棤鏁版嵁" }}
-      </el-descriptions-item>
-    </el-descriptions>
+        <el-descriptions-item label="浜や粯鏃ユ湡" align="center" v-if="formData.productOrderList">
+          {{ formData.productOrderList.deliveryDate || "鏆傛棤鏁版嵁" }}
+        </el-descriptions-item>
+      </el-descriptions>
 
-    <el-descriptions border :column="4">
-      <el-descriptions-item label="濮旀墭鍗曚綅" :span="2" align="center">
-        {{formData.clientName || "--"}}
-      </el-descriptions-item>
+      <el-descriptions border :column="4">
+        <el-descriptions-item label="濮旀墭鍗曚綅" :span="2" align="center">
+          {{ formData.clientName || "--" }}
+        </el-descriptions-item>
 
-      <el-descriptions-item label="鏁伴噺" :span="1" align="center">
-        {{formData.orderQty || "--"}}
-      </el-descriptions-item>
+        <el-descriptions-item label="鏁伴噺" :span="1" align="center">
+          {{ formData.orderQty || "--" }}
+        </el-descriptions-item>
 
-      <el-descriptions-item label="鎴愬搧灏哄" :span="1" align="center">
-        {{formData.specificationModel || "--"}}
-      </el-descriptions-item>
+        <el-descriptions-item label="鎴愬搧灏哄" :span="1" align="center">
+          <el-input v-model="formData.finishedSize" placeholder="鎴愬搧灏哄" :disabled="isDetail">
+          </el-input>
+        </el-descriptions-item>
 
-      <el-descriptions-item label="浜у搧鍚嶇О" :span="2" align="center">
-        {{formData.productName || "--"}}
-      </el-descriptions-item>
+        <el-descriptions-item label="浜у搧鍚嶇О" :span="2" align="center">
+          {{ formData.productName || "--" }}
+        </el-descriptions-item>
 
-      <el-descriptions-item label="鍗曟嵁绫诲瀷" :span="2" align="center">
-        <el-checkbox-group v-model="introductionLetterList">
-          <el-checkbox label="浠嬬粛淇�" value="浠嬬粛淇�" />
-          <el-checkbox label="鍟嗘爣娉ㄥ唽涔�" value="鍟嗘爣娉ㄥ唽涔�" />
-          <el-checkbox label="濮斿嵃鍗�" value="濮斿嵃鍗�" />
-        </el-checkbox-group>
-      </el-descriptions-item>
-    </el-descriptions>
+        <el-descriptions-item label="鍗曟嵁绫诲瀷" :span="2" align="center">
+          <el-checkbox-group v-model="introductionLetterList" :disabled="isDetail">
+            <el-checkbox label="浠嬬粛淇�" value="浠嬬粛淇�"/>
+            <el-checkbox label="鍟嗘爣娉ㄥ唽" value="鍟嗘爣娉ㄥ唽"/>
+            <el-checkbox label="濮斿嵃鍗�" value="濮斿嵃鍗�"/>
+            <el-checkbox label="涔﹀彿" value="涔﹀彿"/>
+          </el-checkbox-group>
+        </el-descriptions-item>
+      </el-descriptions>
 
-    <!-- ================= 鏉愭枡琛� ================= -->
-    <div class="process-table-header">
-     <div class="section-title">鏉愭枡淇℃伅</div>
-      <el-button 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 }">
-          <el-tree-select
-            v-model="row.productId"
-            placeholder="璇烽�夋嫨"
-            clearable
-            check-strictly
-            @change="(val) => getModels(val, row)"
-            :data="productOptions"
-            :render-after-expand="false"
-            style="width: 100%"
-          />
-        </template>
-      </el-table-column>
-      <el-table-column label="瑙勬牸">
-        <template #default="{ row }">
-          <el-select
-            v-model="row.productModelId"
-            placeholder="璇烽�夋嫨瑙勬牸"
-            filterable
-            clearable
-            @change="(val) => handleMaterialModelChange(val, row)"
-          >
-            <el-option
-              v-for="item in row.modelOptions || []"
-              :key="item.id"
-              :label="item.model"
-              :value="item.id"
+      <!-- ================= 鏉愭枡琛� ================= -->
+      <div class="process-table-header">
+        <div class="section-title">鏉愭枡淇℃伅</div>
+        <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, $index }">
+            <el-tree-select
+                v-if="!isDetail"
+                v-model="row.productById"
+                placeholder="璇烽�夋嫨"
+                clearable
+                check-strictly
+                @change="(val) => getModels(val, row, $index)"
+                :data="productOptions"
+                :render-after-expand="false"
+                :disabled="isDetail"
+                style="width: 100%"
             />
-          </el-select>
-        </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>
-        </template>
-      </el-table-column>
-      <el-table-column label="璁¢噺鍗曚綅">
-        <template #default="{ row }">
-          <el-input v-model="row.unit" placeholder="璁¢噺鍗曚綅" />
-        </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>
-        </template>
-      </el-table-column>
-      <el-table-column label="閲戦">
-        <template #default="{ row }">
-          <el-input v-model="row.totalAmount" placeholder="閲戦" />
-        </template>
-      </el-table-column>
-      <el-table-column label="鎿嶄綔" width="80">
-        <template #default="{ $index }">
-          <el-button type="danger" size="small" @click="removeMaterialRow($index)">鍒犻櫎</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <el-descriptions border :column="2" :span="2">
-      <el-descriptions-item
-          label="娉ㄦ剰浜嬮」"
-          :span="2"
-          align="center"
-          style="white-space: pre-line; word-break: break-all; min-height: 60px;"
+            <span v-else>{{ row.name }}</span>
+          </template>
+        </el-table-column>
+        <el-table-column>
+          <template #header>
+            <span class="required">*</span>瑙勬牸
+          </template>
+          <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"
+                  :key="item.id"
+                  :label="item.model"
+                  :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="鏁伴噺" :disabled="isDetail">
+            </el-input>
+          </template>
+        </el-table-column>
+        <el-table-column label="璁¢噺鍗曚綅">
+          <template #default="{ row }">
+            <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="鍗曚环" :disabled="isDetail">
+            </el-input>
+          </template>
+        </el-table-column>
+        <el-table-column label="閲戦">
+          <template #default="{ row }">
+            <el-input v-model="row.totalAmount" placeholder="閲戦" :disabled="isDetail"/>
+          </template>
+        </el-table-column>
+        <el-table-column v-if="!isDetail" label="鎿嶄綔" width="80">
+          <template #default="{ $index }">
+            <el-button type="danger" size="small" @click="removeMaterialRow($index)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <el-descriptions border :column="2" :span="2">
+        <el-descriptions-item
+            label="鍒囨枡鍥剧ず閫夋嫨"
+            :span="1"
+            align="center"
+            style="white-space: pre-line; word-break: break-all; min-height: 60px;"
+        >
+          <el-radio-group v-model="formData.cuttingDiagramCheckout">
+            <el-radio value="骞冲紶">骞冲紶</el-radio>
+            <el-radio value="鍗风瓛">鍗风瓛</el-radio>
+          </el-radio-group>
+        </el-descriptions-item>
+        <el-descriptions-item
+            label="鍒囨枡娉ㄦ剰浜嬮」"
+            :span="1"
+            align="center"
+            style="white-space: pre-line; word-break: break-all; min-height: 60px;"
+        >
+          <el-input
+              v-model="formData.productDescription"
+              :autosize="{ minRows: 2, maxRows: 4 }"
+              type="textarea"
+              placeholder="璇疯緭鍏ユ敞鎰忎簨椤�"
+              :disabled="isDetail"
+          />
+        </el-descriptions-item>
+      </el-descriptions>
+      <!-- ================= 鍒囨枡鍥剧ず ================= -->
+      <div class="section-title" v-if="type === 'add' || (type === 'detail' && formData.cuttingFileVo.length > 0)">
+        鍒囨枡鍥剧ず
+      </div>
+      <ActionFileUpload
+          v-if="type === 'add' || (type === 'detail' && formData.cuttingFileVo.length > 0)"
+          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'"
+          :onSuccess="onSuccess"
+          :onDownload="onDownload"
+          :onRemove="onRemove"
+          :onPreview="onPreview"
+          :onView="type!=='detail'"
+          :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
+          border
+          :column="6"
+          direction="vertical"
+          style="width: 100%"
+          class="fixed-desc"
       >
-        <el-input
-            v-model="formData.productDescription"
-            :autosize="{ minRows: 2, maxRows: 4 }"
-            type="textarea"
-            placeholder="璇疯緭鍏ユ敞鎰忎簨椤�"
-        />
-      </el-descriptions-item>
-    </el-descriptions>
-    <hr>
-    <!-- ================= 鍒囨枡鍥剧ず ================= -->
-    <div class="section-title">鍒囨枡鍥剧ず</div>
-    <ActionFileUpload
-        style="width: 50%;"
-        v-model:file-list="fileList"
-        :action="upload.url"
-        :headers="upload.headers"
-        :multiple="false"
-        :name="'files'"
-    tip-text="鏀寔鍥剧墖锛坖pg, jpeg, png锛夋牸寮�"
-    />
-    <!-- ================= 鍒囨枡淇℃伅 ================= -->
-    <el-descriptions
-      border
-      :column="6"
-      direction="vertical"
-      style="width: 100%"
-      class="fixed-desc"
-    >
-      <el-descriptions-item label="鍒囨枡灏哄" align="center">
-        <el-input v-model="formData.cutNum" placeholder="鍒囨枡灏哄" />
-      </el-descriptions-item>
-      <el-descriptions-item label="鍒囨枡鏁伴噺" align="center">
-        <el-input v-model="formData.cutSize" placeholder="鍒囨枡灏哄" />
-      </el-descriptions-item>
-      <el-descriptions-item label="涓洅鏁伴噺" align="center">
-        <el-input v-model="formData.mediumBoxQty" placeholder="涓洅鏁伴噺" />
-      </el-descriptions-item>
-      <el-descriptions-item label="灏忕洅鏁伴噺" align="center">
-        <el-input v-model="formData.smallBoxQty" placeholder="灏忕洅鏁伴噺" />
-      </el-descriptions-item>
-      <el-descriptions-item label="姝f暟" align="center">
-        <el-input v-model="formData.positiveQty" placeholder="姝f暟" />
-      </el-descriptions-item>
-      <el-descriptions-item label="鍔犳斁鏁�" align="center">
-        <el-input v-model="formData.allowanceQty" placeholder="鍔犳斁鏁�" />
-      </el-descriptions-item>
-    </el-descriptions>
+        <el-descriptions-item label="鍒囨枡灏哄" align="center">
+          <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="鍒囨枡鏁伴噺" :disabled="isDetail"/>
+        </el-descriptions-item>
+        <el-descriptions-item label="涓洅鏁伴噺" align="center">
+          <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="灏忕洅鏁伴噺" :disabled="isDetail"/>
+        </el-descriptions-item>
+        <el-descriptions-item label="姝f暟" align="center">
+          <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="鍔犳斁鏁�" :disabled="isDetail"/>
+        </el-descriptions-item>
+      </el-descriptions>
 
-    <div class="middle-sheet-table">
-      <table class="middle-sheet-table__inner">
-        <tbody>
+      <div class="middle-sheet-table">
+        <table class="middle-sheet-table__inner">
+          <tbody>
           <tr>
             <th>杞墖鐗�:</th>
             <th colspan="2">寮�寮犺壊</th>
@@ -196,168 +234,187 @@
           </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>
-      </table>
-    </div>
-<!--  class="section-title" -->
-    <!-- ================= 宸ヨ壓鍔犲伐 ================= -->
-    <div class="process-table-header">
-     <div class="section-title">宸ヨ壓鍔犲伐</div>
-      <el-button 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)"
-              >
-                <el-option
-                    v-for="item in processOptions"
-                    :key="item.id"
-                    :label="item.name"
-                    :value="item.id"
-                />
-              </el-select>
-            </template>
-          </el-table-column>
-        </template>
-      </el-table-column>
-      <el-table-column label="寮�鏁�">
-        <template #default="{ row }">
-          <el-input v-model="row.openCount" placeholder="璇疯緭鍏ュ紑鏁�" />
-        </template>
-      </el-table-column>
-      <el-table-column label="宸ヨ壓姝f暟">
-        <template #default="{ row }">
-          <el-input v-model="row.processPositive" placeholder="璇疯緭鍏ュ伐鑹烘鏁�" />
-        </template>
-      </el-table-column>
-      <el-table-column label="鍔犳斁鏁�">
-        <template #default="{ row }">
-          <el-input v-model="row.allowanceQty" placeholder="璇疯緭鍏ュ姞鏀炬暟" />
-        </template>
-      </el-table-column>
-      <el-table-column label="鏈哄彴" width="180">
-        <template #default="{ row }">
-          <el-select
-            v-model="row.deviceId"
-            placeholder="璇烽�夋嫨鏈哄彴"
-            filterable
-            clearable
-            @change="(val) => handleDeviceChange(val, row)"
-          >
-            <el-option
-              v-for="item in deviceOptions"
-              :key="item.id"
-              :label="item.deviceName"
-              :value="item.id"
+          </tbody>
+        </table>
+      </div>
+      <!--  class="section-title" -->
+      <!-- ================= 宸ヨ壓鍔犲伐 ================= -->
+      <div class="process-table-header">
+        <div class="section-title">宸ヨ壓鍔犲伐</div>
+        <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-select
+                v-model="row.processId"
+                placeholder="璇烽�夋嫨宸ュ簭"
+                @change="(val) => onProcessChange(val, row)"
+                :disabled="isDetail"
+            >
+              <el-option
+                  v-for="item in processOptions"
+                  :key="item.id"
+                  :label="item.name"
+                  :value="item.id"
+              />
+            </el-select>
+          </template>
+        </el-table-column>
+        <el-table-column label="寮�鏁�">
+          <template #default="{ row }">
+            <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="璇疯緭鍏ュ伐鑹烘鏁�" :disabled="isDetail"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="鍔犳斁鏁�">
+          <template #default="{ row }">
+            <el-input v-model="row.allowanceQty" placeholder="璇疯緭鍏ュ姞鏀炬暟" :disabled="isDetail"/>
+          </template>
+        </el-table-column>
+        <!--      <el-table-column width="180">-->
+        <!--        <template #header>-->
+        <!--          <span class="required">*</span>鏈哄彴-->
+        <!--        </template>-->
+        <!--        <template #default="{ row }">-->
+        <!--          <el-select-->
+        <!--            v-model="row.deviceId"-->
+        <!--            placeholder="璇烽�夋嫨鏈哄彴"-->
+        <!--            filterable-->
+        <!--            clearable-->
+        <!--            @change="(val) => handleDeviceChange(val, row)"-->
+        <!--            :disabled="isDetail"-->
+        <!--          >-->
+        <!--            <el-option-->
+        <!--              v-for="item in deviceOptions"-->
+        <!--              :key="item.id"-->
+        <!--              :label="item.deviceName"-->
+        <!--              :value="item.id"-->
+        <!--            />-->
+        <!--          </el-select>-->
+        <!--        </template>-->
+        <!--      </el-table-column>-->
+        <!--      <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-->
+        <!--            clearable-->
+        <!--            multiple-->
+        <!--            collapse-tags-->
+        <!--            collapse-tags-tooltip-->
+        <!--            @change="(val) => handleReportUsersChange(val, row)"-->
+        <!--            :disabled="isDetail"-->
+        <!--          >-->
+        <!--            <el-option-->
+        <!--              v-for="item in userOptions"-->
+        <!--              :key="item.userId"-->
+        <!--              :label="item.nickName"-->
+        <!--              :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="宸ヨ壓瑕佹眰">
+          <template #default="{ rowIndex }">
+            <el-input
+                v-model="formData.processRequirement"
+                type="textarea"
+                :rows="6"
+                placeholder="璇疯緭鍏ュ伐鑹鸿姹�"
+                :disabled="isDetail"
             />
-          </el-select>
-        </template>
-      </el-table-column>
-      <el-table-column label="鎶ュ伐浜�" width="220">
-        <template #default="{ row }">
-          <el-select
-            v-model="row.reportUserIds"
-            placeholder="璇烽�夋嫨鎶ュ伐浜�"
-            filterable
-            clearable
-            multiple
-            collapse-tags
-            collapse-tags-tooltip
-            @change="(val) => handleReportUsersChange(val, row)"
-          >
-            <el-option
-              v-for="item in userOptions"
-              :key="item.userId"
-              :label="item.nickName"
-              :value="item.userId"
-            />
-          </el-select>
-        </template>
-      </el-table-column>
-      <el-table-column label="宸ヨ壓瑕佹眰">
-        <template #default="{ rowIndex }">
-          <el-input
-            v-model="formData.processRequirement"
-            type="textarea"
-            :rows="6"
-            placeholder="璇疯緭鍏ュ伐鑹鸿姹�"
-          />
-        </template>
-      </el-table-column>
-      <el-table-column label="鎿嶄綔" width="80">
-        <template #default="{ $index }">
-          <el-button type="danger" size="small" @click="removeProcessRow($index)">鍒犻櫎</el-button>
-        </template>
-      </el-table-column>
-    </el-table>
+          </template>
+        </el-table-column>
+        <el-table-column v-if="!isDetail" label="鎿嶄綔" width="80">
+          <template #default="{ $index }">
+            <el-button type="danger" size="small" @click="removeProcessRow($index)">鍒犻櫎</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
 
-    <!-- ================= 鍖呰淇℃伅 ================= -->
-    <el-descriptions border :column="3" class="mt">
-      <el-descriptions-item label="閫佽揣鍦扮偣" align="center">
-        <el-input v-model="formData.deliveryAddress" placeholder="閫佽揣鍦扮偣" />
-      </el-descriptions-item>
+      <!-- ================= 鍖呰淇℃伅 ================= -->
+      <el-descriptions border :column="3" class="mt">
+        <el-descriptions-item label="閫佽揣鍦扮偣" align="center">
+          <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-descriptions-item>
+        <el-descriptions-item label="鑱旂郴浜�" align="center">
+          <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-descriptions-item>
+        <el-descriptions-item label="鍖呰瑕佹眰" align="center">
+          <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-descriptions-item>
+        <el-descriptions-item label="灏哄" align="center">
+          <el-input v-model="formData.postProcessSize" placeholder="灏哄" :disabled="isDetail"/>
+        </el-descriptions-item>
 
-      <el-descriptions-item label="瀹氳揣鏁伴噺" align="center">
-        {{formData.orderQty || "--"}}
-      </el-descriptions-item>
+        <el-descriptions-item label="瀹氳揣鏁伴噺" align="center">
+          {{ formData.orderQty || "--" }}
+        </el-descriptions-item>
 
-      <el-descriptions-item label="瀹炰氦鏁伴噺" :span="3" align="center">
-        <el-input v-model="formData.actualDeliveryQty" placeholder="瀹炰氦鏁伴噺" />
-      </el-descriptions-item>
-    </el-descriptions>
+        <el-descriptions-item label="瀹炰氦鏁伴噺" :span="3" align="center">
+          <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 {computed, getCurrentInstance, onMounted, reactive, ref, watch} from 'vue'
 import dayjs from 'dayjs'
 import FormDialog from '@/components/Dialog/FormDialog.vue'
 import ActionFileUpload from "@/components/Upload/ActionFileUpload.vue";
-import { list } from "@/api/productionManagement/productionProcess.js"
-import { modelList, productTreeList } from "@/api/basicData/product.js"
+import {list} from "@/api/productionManagement/productionProcess.js"
+import {modelList, productTreeList} from "@/api/basicData/product.js"
 import {getSalesLedgerWithProducts} from "@/api/salesManagement/salesLedger.js"
-import { getDeviceLedger } from "@/api/equipmentManagement/ledger.js"
-import { userListNoPageByTenantId } from "@/api/system/user.js"
-import { getToken } from "@/utils/auth";
+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,38 +436,44 @@
 })
 
 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() }
+  headers: {Authorization: 'Bearer ' + getToken()}
 })
 
+const showCuttingFile = computed(() => {
+  return props.type === 'detail' && Array.isArray(formData.cuttingFileVo) && formData.cuttingFileVo.length > 0
+})
+
+const filePreviewRef = ref()
 const formData = reactive({
-  productOrderList:null,
+  productOrderList: null,
   salesLedgerId: null,
   productOrderId: null,
   printOrderTime: dayjs().format('YYYY-MM-DD HH:mm:ss'),
-  fileList:[],
+  cuttingFileVo: [],
   finishTime: "",
   no: "",
   productName: "",
   productDescription: "",
+  cuttingDiagramCheckout: "",
   clientName: "",
   finishedSize: "",
   cutNum: "",
-  cutSize:"",
+  cutSize: "",
   mediumBoxQty: "",
   smallBoxQty: "",
   positiveQty: "",
@@ -429,7 +492,6 @@
   ],
   processContent: [
     {
-      id: "1",
       processId: "",
       processName: "",
       mediumBoxQty: "",
@@ -437,15 +499,20 @@
       openCount: "",
       processPositive: "",
       allowanceQty: "",
-      deviceId: "",
-      deviceName: "",
-      reportUserIds: [],
-      reportWorkerList: []
+      deviceId: "0",
+      deviceName: "0",
+      reportUserIds: [{
+        userId: "0",
+        userName: "0"
+      }],
+      reportWorkerList: [{
+        userId: "0",
+        userName: "0"
+      }],
     }
   ],
   materialInfo: [
     {
-      id: "1",
       productId: "",
       name: "",
       productModelId: "",
@@ -470,19 +537,163 @@
   technicalDept: "",
   warehouseDept: "",
   productModelId: "",
-  specificationModel:"",
+  specificationModel: "",
 })
+
+const getUploadFileUrl = (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: "",
+  cuttingDiagramCheckout: "骞冲紶",
+  clientName: "",
+  finishedSize: "",
+  cutNum: "",
+  cutSize: "",
+  mediumBoxQty: "",
+  smallBoxQty: "",
+  positiveQty: "",
+  allowanceQty: "",
+  introductionLetter: "",
+  plateMaking: [
+    {
+      designProductionFee: "",
+      impositionFee: "",
+      filmOutputFee: "",
+      proofingFee: "",
+      doctorBladePlateFee: "",
+      hotEmbossingPlateFee: "",
+      subtotalFee: ""
+    }
+  ],
+  processContent: [
+    {
+      processId: "",
+      processName: "",
+      mediumBoxQty: "",
+      smallBoxQty: "",
+      openCount: "",
+      processPositive: "",
+      allowanceQty: "",
+      deviceId: "0",
+      deviceName: "0",
+      reportUserIds: [{
+        userId: "0",
+        userName: "0"
+      }],
+      reportWorkerList: [{
+        userId: "0",
+        userName: "0"
+      }],
+    }
+  ],
+  materialInfo: [
+    {
+      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) => {
+  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) => {
+  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 +706,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,34 +736,38 @@
   if (source.productOrderId === undefined && source.id !== undefined) {
     formData.productOrderId = source.id
   }
+
+  introductionLetterList.value = String(formData.introductionLetter || "")
+      .split(",")
+      .map(s => s.trim())
+      .filter(Boolean)
 }
 
 // 鑾峰彇閿�鍞鍗�
 const getProductOrder = () => {
-  if(!formData.salesLedgerId) return
+  if (!formData.salesLedgerId) return
   getSalesLedgerWithProducts({
     type: "1",
     id: formData.salesLedgerId
   }).then(res => {
-    if(res){
+    if (res) {
       formData.productOrderList = res
     }
-    console.log(formData)
   })
 
 }
 
 watch(() => props.orderData, (val) => {
   mergeRowDataToForm(val)
-}, { immediate: true, deep: true })
+}, {immediate: true, deep: true})
 
 watch(
-  () => props.rowData,
-  (val) => {
-    mergeRowDataToForm(val)
-    getProductOrder()
-  },
-  { immediate: true, deep: true }
+    () => props.rowData,
+    (val) => {
+      mergeRowDataToForm(val)
+      getProductOrder()
+    },
+    {immediate: true, deep: true}
 )
 
 const getProcessList = () => {
@@ -547,7 +775,6 @@
     processOptions.value = res.data
   })
 }
-
 
 
 const getDeviceList = () => {
@@ -593,11 +820,9 @@
 }
 
 const handleProcessChange = (val, row) => {
-  console.log(row)
   const process = processOptions.value.find(item => item.id === val)
   if (process) {
     row.processName = process.name
-    console.log(process)
     if (process.deviceId) {
       row.deviceId = process.deviceId || ""
       row.deviceName = process.deviceName || ""
@@ -621,24 +846,40 @@
   }))
 }
 
-const getModels = (val, row) => {
+const getModels = async (val, row, index) => {
+  const targetRow = formData.materialInfo[index]
   row.productId = val || ""
+  row.productById = val || ""
   row.name = val ? findProductLabelById(productOptions.value, val) : ""
+
   row.productModelId = ""
   row.model = ""
   row.unit = ""
   row.modelOptions = []
-  if (!val) {
-    return
+
+  if (!val) return
+
+  const res = await modelList({id: val})
+  formData.materialInfo[index] = {
+    ...targetRow,
+    modelOptions: Array.isArray(res) ? res :
+        Array.isArray(res?.data) ? res.data :
+            Array.isArray(res?.rows) ? res.rows :
+                Array.isArray(res?.data?.records) ? res.data.records :
+                    []
   }
-  modelList({ id: val }).then(res => {
-    row.modelOptions = Array.isArray(res) ? res : Array.isArray(res?.data) ? res.data : []
-  })
+  // row.modelOptions = Array.isArray(res) ? res :
+  //     Array.isArray(res?.data) ? res.data :
+  //         Array.isArray(res?.rows) ? res.rows :
+  //             Array.isArray(res?.data?.records) ? res.data.records :
+  //                 []
+
 }
 
 const handleMaterialModelChange = (val, row) => {
   const currentModel = (row.modelOptions || []).find(item => item.id === val)
   row.productModelId = val || ""
+  row.productId = currentModel?.id || ""
   row.model = currentModel?.model || ""
   row.unit = currentModel?.unit || ""
 }
@@ -667,16 +908,21 @@
 
 const addProcessRow = () => {
   formData.processContent.push({
-    id: Date.now().toString(),
     processId: "",
     processName: "",
     openCount: "",
     processPositive: "",
     allowanceQty: "",
-    deviceId: "",
-    deviceName: "",
-    reportUserIds: [],
-    reportWorkerList: []
+    deviceId: "0",
+    deviceName: "0",
+    reportUserIds: [{
+      userId: "0",
+      userName: "0"
+    }],
+    reportWorkerList: [{
+      userId: "0",
+      userName: "0"
+    }],
   })
 }
 
@@ -684,7 +930,7 @@
   formData.processContent.splice(index, 1)
 }
 
-const objectSpanMethod = ({ column, rowIndex }) => {
+const objectSpanMethod = ({column, rowIndex}) => {
   if (column.label === "宸ヨ壓瑕佹眰") {
     if (rowIndex === 0) {
       return {
@@ -704,7 +950,39 @@
 }
 
 const handleConfirm = () => {
-  emit('confirm', JSON.parse(JSON.stringify(formData)))
+  if (isDetail.value) {
+    return
+  }
+  const materialRows = Array.isArray(formData.materialInfo) ? formData.materialInfo : []
+  for (let i = 0; i < materialRows.length; i++) {
+    const row = materialRows[i] || {}
+    if (!row.productId) {
+      ElMessage.warning(`鏉愭枡淇℃伅绗�${i + 1}琛岋細	瑙勬牸蹇呭~`)
+      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 +992,8 @@
   getMaterialProductOptions()
 })
 defineExpose({
-  getProductOrder
+  getProductOrder,
+  resetForm
 })
 </script>
 
@@ -729,10 +1008,12 @@
 
 .fixed-desc {
   margin-top: 20px;
+
   :deep(.el-descriptions__table) {
     table-layout: fixed;
     width: 100%;
   }
+
   :deep(.el-descriptions__cell) {
     width: 25%;
     word-break: break-word;
@@ -775,6 +1056,7 @@
   display: flex;
   justify-content: space-between;
   align-items: center;
+
   span {
     font-size: 16px;
     font-weight: bold;
@@ -784,7 +1066,61 @@
 .mt {
   margin-top: 20px;
 }
-:deep(.el-textarea__inner){
+
+: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>

--
Gitblit v1.9.3