From 36b909e117c3ccc22dd266a94479e2a02335d261 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 26 三月 2026 18:03:34 +0800
Subject: [PATCH] 军泰伟业 1.生产订单新增编辑逻辑重写

---
 src/views/productionManagement/productStructure/Detail/index.vue       |    3 
 src/views/productionManagement/productionOrder/New.vue                 |  284 ++++++++++++++++++++++++++++-------
 src/views/productionManagement/productionReporting/index.vue           |   10 -
 src/views/productionManagement/workOrder/index.vue                     |    6 
 src/views/productionManagement/processRoute/processRouteItem/index.vue |  100 +----------
 src/views/productionManagement/productionOrder/index.vue               |   60 ++++++-
 src/api/productionManagement/productionOrder.js                        |    8 +
 7 files changed, 301 insertions(+), 170 deletions(-)

diff --git a/src/api/productionManagement/productionOrder.js b/src/api/productionManagement/productionOrder.js
index 6c8dbe2..3db843e 100644
--- a/src/api/productionManagement/productionOrder.js
+++ b/src/api/productionManagement/productionOrder.js
@@ -36,6 +36,14 @@
   });
 }
 
+export function startOrPause(data) {
+  return request({
+    url: "/productOrder/startOrPause",
+    method: "post",
+    data,
+  });
+}
+
 // 鐢熶骇璁㈠崟-鏂板
 export function addProductOrder(data) {
   return request({
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index 65035ec..f1d46fc 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -63,11 +63,9 @@
         <el-button 
             icon="Grid" 
             @click="toggleView"
-            style="margin-right: 10px;"
         >
           鍗$墖瑙嗗浘
         </el-button>
-        <el-button type="primary" @click="handleAdd">鏂板</el-button>
       </div>
     </div>
     <el-table
@@ -87,10 +85,6 @@
           {{ getProcessName(scope.row.processId) || '-' }}
         </template>
       </el-table-column>
-      <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="160" />
-      <el-table-column label="鍥剧焊缂栧彿" prop="model" min-width="140" />
-      <el-table-column label="瑙勬牸鍨嬪彿" prop="drawingNumber" min-width="160" />
-      <el-table-column label="鍗曚綅" prop="unit" width="100" />
       <el-table-column label="鏄惁璐ㄦ" prop="isQuality" width="100">
         <template #default="scope">
           {{scope.row.isQuality ? "鏄�" : "鍚�"}}
@@ -117,11 +111,9 @@
           <el-button 
               icon="Menu" 
               @click="toggleView"
-              style="margin-right: 10px;"
           >
             琛ㄦ牸瑙嗗浘
           </el-button>
-          <el-button type="primary" @click="handleAdd">鏂板</el-button>
         </div>
       </div>
       <div v-loading="tableLoading" class="card-container">
@@ -141,18 +133,8 @@
             <div class="card-process-name">{{ getProcessName(item.processId) || '-' }}</div>
           </div>
           
-          <!-- 浜у搧淇℃伅 -->
           <div class="card-content">
-            <div v-if="item.productName" class="product-info">
-              <div class="product-name">{{ item.productName }}</div>
-              <div class="product-model">{{ item.drawingNumber || '-' }}</div>
-              <div v-if="item.model" class="product-model">
-                {{ item.model }}
-                <!-- <span v-if="item.unit" class="product-unit">{{ item.unit }}</span> -->
-              </div>
-              <el-tag type="primary" class="product-tag" v-if="item.isQuality">璐ㄦ</el-tag>
-            </div>
-            <div v-else class="product-info empty">鏆傛棤浜у搧淇℃伅</div>
+            <el-tag type="primary" class="product-tag" v-if="item.isQuality">璐ㄦ</el-tag>
           </div>
           
           <!-- 鎿嶄綔鎸夐挳 -->
@@ -194,23 +176,6 @@
           </el-select>
         </el-form-item>
 
-        <el-form-item label="浜у搧鍚嶇О" prop="productModelId">
-          <el-button type="primary" @click="showProductSelectDialog = true">
-            {{ form.productName && form.model 
-              ? `${form.productName} - ${form.model}` 
-              : '閫夋嫨浜у搧' }}
-          </el-button>
-        </el-form-item>
-
-        <el-form-item label="鍗曚綅" prop="unit">
-          <el-input 
-              v-model="form.unit" 
-              :placeholder="form.productModelId ? '鏍规嵁閫夋嫨鐨勪骇鍝佽嚜鍔ㄥ甫鍑�' : '璇峰厛閫夋嫨浜у搧'" 
-              clearable 
-              :disabled="true" 
-          />
-        </el-form-item>
-
         <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
           <el-switch v-model="form.isQuality" :active-value="true" :inactive-value="false"/>
         </el-form-item>
@@ -237,18 +202,11 @@
       </template>
     </el-dialog>
 
-    <!-- 浜у搧閫夋嫨瀵硅瘽妗� -->
-    <ProductSelectDialog
-        v-model="showProductSelectDialog"
-        @confirm="handleProductSelect"
-        single
-    />
   </div>
 </template>
 
 <script setup>
 import { ref, computed, getCurrentInstance, onMounted, onUnmounted, nextTick } from "vue";
-import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
 import { findProcessRouteItemList, addOrUpdateProcessRouteItem, sortProcessRouteItem, batchDeleteProcessRouteItem } from "@/api/productionManagement/processRouteItem.js";
 import { findProductProcessRouteItemList, deleteRouteItem, addRouteItem, addOrUpdateProductProcessRouteItem, sortRouteItem } from "@/api/productionManagement/productProcessRoute.js";
 import { processList } from "@/api/productionManagement/productionProcess.js";
@@ -283,7 +241,6 @@
 });
 
 const processOptions = ref([]);
-const showProductSelectDialog = ref(false);
 const staffList = ref([]);
 
 const treeProps = {
@@ -307,17 +264,12 @@
   id: undefined,
   routeId: routeId.value,
   processId: undefined,
-  productModelId: undefined,
-  productName: "",
-  model: "",
-  unit: "",
   isQuality: false,
   userPower: [],
 });
 
 const rules = {
   processId: [{ required: true, message: '璇烽�夋嫨宸ュ簭', trigger: 'change' }],
-  productModelId: [{ required: true, message: '璇烽�夋嫨浜у搧', trigger: 'change' }],
 };
 
 // 鏍规嵁宸ュ簭ID鑾峰彇宸ュ簭鍚嶇О
@@ -395,10 +347,6 @@
     id: row.id,
     routeId: routeId.value,
     processId: row.processId,
-    productModelId: row.productModelId,
-    productName: row.productName || "",
-    model: row.model || "",
-    unit: row.unit || "",
     isQuality: row.isQuality,
     userPower: userPowerIds,
   };
@@ -447,20 +395,6 @@
     .catch(() => {});
 };
 
-// 浜у搧閫夋嫨
-const handleProductSelect = (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 || "";
-    showProductSelectDialog.value = false;
-    // 瑙﹀彂琛ㄥ崟楠岃瘉
-    formRef.value?.validateField('productModelId');
-  }
-};
-
 // 鎻愪氦
 const handleSubmit = () => {
   formRef.value.validate((valid) => {
@@ -480,7 +414,6 @@
               productOrderId: orderId.value,
               productRouteId: routeId.value,
               processId: form.value.processId,
-              productModelId: form.value.productModelId,
               isQuality: form.value.isQuality,
               userPower: userPowerNames.join(','),
               dragSort,
@@ -488,7 +421,6 @@
           : addOrUpdateProcessRouteItem({
               routeId: routeId.value,
               processId: form.value.processId,
-              productModelId: form.value.productModelId,
               isQuality: form.value.isQuality,
               userPower: userPowerNames.join(','),
               dragSort,
@@ -514,14 +446,12 @@
           ? addOrUpdateProductProcessRouteItem({
               id: form.value.id,
               processId: form.value.processId,
-              productModelId: form.value.productModelId,
               isQuality: form.value.isQuality,
               userPower: userPowerNames.join(','),
             })
           : addOrUpdateProcessRouteItem({
               routeId: routeId.value,
               processId: form.value.processId,
-              productModelId: form.value.productModelId,
               id: form.value.id,
               isQuality: form.value.isQuality,
               userPower: userPowerNames.join(','),
@@ -550,10 +480,8 @@
     id: undefined,
     routeId: routeId.value,
     processId: undefined,
-    productModelId: undefined,
-    productName: "",
-    model: "",
-    unit: "",
+    isQuality: false,
+    userPower: [],
   };
   formRef.value?.resetFields();
 };
@@ -800,20 +728,20 @@
 
 .process-card {
   flex-shrink: 0;
-  width: 220px;
+  width: 160px;
   background: #fff;
+  border: 1px solid #e4e7ed;
   border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
   padding: 16px;
   display: flex;
   flex-direction: column;
   cursor: move;
-  transition: all 0.3s;
+  transition: all 0.2s;
 }
 
 .process-card:hover {
-  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
-  transform: translateY(-2px);
+  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
 }
 
 .card-header {
@@ -822,20 +750,20 @@
 }
 
 .card-number {
-  width: 36px;
-  height: 36px;
-  line-height: 36px;
+  width: 28px;
+  height: 28px;
+  line-height: 28px;
   border-radius: 50%;
   background: #409eff;
   color: #fff;
   font-weight: bold;
-  font-size: 16px;
+  font-size: 13px;
   margin: 0 auto 8px;
 }
 
 .card-process-name {
   font-size: 14px;
-  color: #333;
+  color: #303133;
   font-weight: 500;
   word-break: break-all;
 }
@@ -843,7 +771,7 @@
 .card-content {
   flex: 1;
   margin-bottom: 12px;
-  min-height: 60px;
+  min-height: 40px;
   display: flex;
   align-items: center;
   justify-content: center;
diff --git a/src/views/productionManagement/productStructure/Detail/index.vue b/src/views/productionManagement/productStructure/Detail/index.vue
index 7807a6d..c98b941 100644
--- a/src/views/productionManagement/productStructure/Detail/index.vue
+++ b/src/views/productionManagement/productStructure/Detail/index.vue
@@ -144,7 +144,8 @@
           </el-form>
         </template>
       </el-table-column>
-      <el-table-column label="BOM缂栧彿"
+      <el-table-column v-if="!isOrderPage"
+                       label="BOM缂栧彿"
                        prop="bomNo" />
       <el-table-column label="浜у搧鍚嶇О"
                        prop="productName" />
diff --git a/src/views/productionManagement/productionOrder/New.vue b/src/views/productionManagement/productionOrder/New.vue
index 329473a..51e5404 100644
--- a/src/views/productionManagement/productionOrder/New.vue
+++ b/src/views/productionManagement/productionOrder/New.vue
@@ -28,8 +28,8 @@
               </el-form-item>
             </el-col>
             <el-col :span="12">
-              <el-form-item label="鍥剧焊缂栧彿" prop="productModelName">
-                <el-input v-model="formState.productModelName" disabled />
+              <el-form-item label="鍥剧焊缂栧彿" prop="model">
+                <el-input v-model="formState.model" disabled />
               </el-form-item>
             </el-col>
           </el-row>
@@ -61,18 +61,22 @@
             <el-col :span="12">
               <el-form-item label="鍥剧焊涓婁紶">
                 <el-upload
-                    action="#"
-                    :auto-upload="false"
-                    :on-change="handleFileChange"
-                    :file-list="fileList"
+                    v-model:file-list="fileList"
+                    :action="upload.url"
+                    :headers="upload.headers"
+                    :data="upload.data"
+                    :on-success="handleDrawingUploadSuccess"
+                    :on-remove="handleDrawingRemove"
+                    :before-upload="handleDrawingBeforeUpload"
                     :limit="5"
-                    class="upload-inline"
+                    accept=".pdf,.jpg,.jpeg,.png,.dwg"
+                    list-type="picture-card"
                 >
-                  <el-button type="primary" plain size="small">
-                    <el-icon><Upload /></el-icon> 閫夋嫨鏂囦欢
-                  </el-button>
+                  <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
                   <template #tip>
-                    <div class="el-upload__tip">鏀寔jpg/png/pdf锛屽崟涓笉瓒呰繃10MB</div>
+                    <div class="el-upload__tip">
+                      鏀寔 pdf銆乯pg銆乯peg銆乸ng銆乨wg 鏍煎紡锛屽ぇ灏忎笉瓒呰繃 10MB
+                    </div>
                   </template>
                 </el-upload>
               </el-form-item>
@@ -94,11 +98,26 @@
           @confirm="handleMaterialProductSelect"
       />
 
-      <!-- 鐢熶骇浠诲姟 -->
+      <!-- BOM閫夋嫨寮圭獥 -->
+      <el-dialog
+          v-model="showBomDialog"
+          title="閫夋嫨BOM"
+          width="500"
+          append-to-body
+      >
+        <el-table :data="bomList" border size="small" @row-click="handleBomSelect" highlight-current-row style="margin-bottom: 10px;">
+          <el-table-column type="index" label="搴忓彿" width="60" />
+          <el-table-column label="BOM缂栧彿" prop="bomNo" min-width="120" />
+          <el-table-column label="鐗堟湰" prop="version" min-width="80" />
+          <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="100" />
+        </el-table>
+      </el-dialog>
+
+      <!-- 宸ュ簭 -->
       <div class="section-card">
         <div class="section-header">
           <span class="section-icon">馃敡</span>
-          <span class="section-title-text">鐢熶骇浠诲姟</span>
+          <span class="section-title-text">宸ュ簭</span>
           <el-button type="primary" size="small" @click="addProductionTask" class="add-btn">
             <el-icon><Plus /></el-icon> 娣诲姞浠诲姟
           </el-button>
@@ -115,10 +134,10 @@
               @change="(val) => handleProcessChange(val, row)"
             >
               <el-option
-                v-for="item in processOptions"
+                v-for="item in processRouteItemsOptions"
                 :key="item.id"
-                :label="item.name"
-                :value="item.id"
+                :label="item.processName"
+                :value="item.processId"
               />
             </el-select>
           </template>
@@ -185,7 +204,7 @@
         </el-table-column>
       </el-table>
       <div v-if="processRouteItems.length === 0" class="empty-tip">
-        <el-empty description="鏆傛棤鐢熶骇浠诲姟锛岀偣鍑讳笂鏂规寜閽坊鍔�" :image-size="60" />
+        <el-empty description="鏆傛棤宸ュ簭锛岀偣鍑讳笂鏂规寜閽坊鍔�" :image-size="60" />
       </div>
         </div>
       </div>
@@ -202,6 +221,8 @@
         <div class="table-container">
           <el-table :data="productStructureRecords" border size="small" class="compact-table">
             <el-table-column type="index" label="搴忓彿" width="50" align="center" />
+            <el-table-column label="鍥剧焊缂栧彿" prop="model" min-width="120" />
+            <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="120" />
             <el-table-column label="鍗曚綅浜у嚭闇�瑕佹暟閲�" min-width="140">
               <template #default="{ row }">
                 <el-input-number v-model="row.unitQuantity" :min="0" :precision="2" size="small" style="width: 100%" />
@@ -215,11 +236,6 @@
             <el-table-column label="鍗曚綅" min-width="80">
               <template #default="{ row }">
                 <el-input v-model="row.unit" placeholder="璇疯緭鍏�" size="small" />
-              </template>
-            </el-table-column>
-            <el-table-column label="bomId" min-width="100">
-              <template #default="{ row }">
-                <el-input-number v-model="row.bomId" :min="0" size="small" style="width: 100%" />
               </template>
             </el-table-column>
             <el-table-column label="鎿嶄綔" width="80" fixed="right" align="center">
@@ -247,12 +263,15 @@
 </template>
 
 <script setup>
-import {ref, computed, getCurrentInstance} from "vue";
+import {ref, computed, getCurrentInstance, watch} from "vue";
 import { Plus, Delete, Upload } from '@element-plus/icons-vue';
 import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
-import {addProductOrder, listProcessRoute} from "@/api/productionManagement/productionOrder.js";
-import {list as listProcess} from "@/api/productionManagement/productionProcess.js";
+import {addProductOrder} from "@/api/productionManagement/productionOrder.js";
 import {listDeptUserTree} from "@/api/basicData/productProcess.js";
+import {findProcessRouteItemList} from "@/api/productionManagement/processRouteItem.js";
+import {listPage as listProductBom} from "@/api/productionManagement/productBom.js";
+import {listByBomIdIsParent} from "@/api/productionManagement/productStructure.js";
+import { getToken } from "@/utils/auth.js";
 
 const props = defineProps({
   visible: {
@@ -275,11 +294,13 @@
   productModelId: undefined,
   routeId: undefined,
   productName: "",
-  productModelName: "",
+  model: "",
   unit: "",
   drawingNumber: "",
   quantity: 0,
   deliveryDate: "",
+  tempFileIds: [],
+  salesLedgerFiles: [],
 });
 
 // 宸ュ簭璺嚎鏄庣粏鍒楄〃
@@ -288,14 +309,17 @@
  // 鐗╂枡娓呭崟鍒楄〃
  const productStructureRecords = ref([]);
 
-// 宸ュ簭鍒楄〃
-const processOptions = ref([]);
-
 // 鐢ㄦ埛鍒楄〃
 const userOptions = ref([]);
 
 // 鏂囦欢鍒楄〃
 const fileList = ref([]);
+
+const upload = reactive({
+  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+  headers: { Authorization: "Bearer " + getToken() },
+  data: { type: 14 },
+});
 
 const isShow = computed({
   get() {
@@ -308,13 +332,6 @@
 
 const showProductSelectDialog = ref(false);
 const showMaterialProductDialog = ref(false);
-
-// 鑾峰彇宸ュ簭鍒楄〃
-const fetchProcessOptions = () => {
-  listProcess().then(res => {
-    processOptions.value = res.data || [];
-  });
-};
 
 // 鑾峰彇鐢ㄦ埛鍒楄〃
 const fetchUserOptions = () => {
@@ -341,7 +358,6 @@
 };
 
 // 缁勪欢鎸傝浇鏃惰幏鍙栨暟鎹�
-fetchProcessOptions();
 fetchUserOptions();
 
 let { proxy } = getCurrentInstance()
@@ -354,10 +370,12 @@
     routeId: undefined,
     productName: "",
     drawingNumber: "",
-    productModelName: "",
+    model: "",
     unit: "",
     quantity: 0,
     deliveryDate: "",
+    tempFileIds: [],
+    salesLedgerFiles: [],
   };
   // 閲嶇疆宸ュ簭璺嚎鏄庣粏鍜岀墿鏂欐竻鍗�
   processRouteItems.value = [];
@@ -373,35 +391,108 @@
     formState.value.productId = product.productId;
     formState.value.productName = product.productName;
     formState.value.drawingNumber = product.drawingNumber;
-    formState.value.productModelName = product.model;
+    formState.value.model = product.model;
     formState.value.productModelId = product.id;
     formState.value.unit = product.unit;
+    formState.value.routeId = product.routeId;
     showProductSelectDialog.value = false;
-    fetchRouteOptions( product.id);
+    
+    // 1. 閫氳繃浜у搧鑷甫鐨剅outeId鑾峰彇宸ュ簭鍒楄〃
+    if (product.routeId) {
+      fetchProcessRouteItems(product.routeId);
+    }
+    
+    // 2. 閫氳繃浜у搧id鏌ヨBOM鍒楄〃
+    fetchBomList(product.id);
+    
     // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
     proxy.$refs["formRef"]?.validateField('productModelId');
   }
 };
 
-const routeOptions = ref([]);
-const bindRouteLoading = ref(false);
-const fetchRouteOptions = (productModelId) => {
-  formState.value.routeId = undefined;
-  routeOptions.value = []
-  bindRouteLoading.value = true;
-  listProcessRoute({ productModelId: productModelId }).then(res => {
-    routeOptions.value = res.data || [];
-  }).finally(() => {
-    bindRouteLoading.value = false;
-  })
-}
+// 宸ヨ壓璺嚎宸ュ簭鍒楄〃
+const processRouteItemsOptions = ref([]);
+
+const fetchProcessRouteItems = (routeId) => {
+  processRouteItemsOptions.value = [];
+  findProcessRouteItemList({ routeId: routeId }).then(res => {
+    const items = res.data || [];
+    processRouteItemsOptions.value = items;
+    
+    // 鑷姩娣诲姞宸ュ簭
+    processRouteItems.value = items.map(item => ({
+      processId: item.processId,
+      processName: item.processName,
+      productModelId: item.productModelId,
+      userPower: item.userPower ? item.userPower.split(',') : [],
+      planStartTime: "",
+      planEndTime: "",
+      planNum: 1,
+      isQuality: item.isQuality || false,
+    }));
+  });
+};
+
+// BOM鍒楄〃寮圭獥鐩稿叧
+const showBomDialog = ref(false);
+const bomList = ref([]);
+const currentProductId = ref(null);
+
+const fetchBomList = (productModelId) => {
+  currentProductId.value = productModelId;
+  listProductBom({ productModelId: productModelId }).then(res => {
+    const bomData = res.data?.records || [];
+    if (bomData.length === 1) {
+      // 鍙湁涓�涓狟OM锛岀洿鎺ユ煡璇㈢墿鏂欐竻鍗�
+      fetchMaterialList(bomData[0].id);
+    } else if (bomData.length > 1) {
+      // 澶氫釜BOM锛屽脊鍑洪�夋嫨妗�
+      bomList.value = bomData;
+      showBomDialog.value = true;
+    }
+  });
+};
+
+const handleBomSelect = (bom) => {
+  showBomDialog.value = false;
+  fetchMaterialList(bom.id);
+};
+
+const fetchMaterialList = (bomId) => {
+  listByBomIdIsParent(bomId).then(res => {
+    const materials = res.data || [];
+    const demandQty = formState.value.quantity || 1;
+    productStructureRecords.value = materials.map(item => ({
+      parentId: item.parentId,
+      productModelId: item.productModelId,
+      model: item.model || '',
+      productName: item.productName || '',
+      productOrderId: undefined,
+      processId: undefined,
+      unitQuantity: item.unitQuantity || 1,
+      demandedQuantity: (item.unitQuantity || 1) * demandQty,
+      unit: item.unit || '',
+      bomId: item.bomId,
+    }));
+  });
+};
+
+// 鐩戝惉闇�姹傛暟閲忓彉鍖栵紝閲嶆柊璁$畻鐗╂枡闇�姹傛暟閲�
+watch(() => formState.value.quantity, (newQty) => {
+  if (productStructureRecords.value.length > 0 && newQty) {
+    productStructureRecords.value = productStructureRecords.value.map(item => ({
+      ...item,
+      demandedQuantity: (item.unitQuantity || 1) * newQty
+    }));
+  }
+});
 
 // 宸ュ簭閫夋嫨鍙樺寲澶勭悊
 const handleProcessChange = (processId, row) => {
-  const selectedProcess = processOptions.value.find(item => item.id === processId);
+  const selectedProcess = processRouteItemsOptions.value.find(item => item.processId === processId);
   if (selectedProcess) {
-    row.processName = selectedProcess.name;
-    row.processNo = selectedProcess.no;
+    row.processName = selectedProcess.processName;
+    row.productModelId = selectedProcess.productModelId;
     row.isQuality = selectedProcess.isQuality || false;
     // userPower鏄�楀彿鍒嗛殧鐨勭敤鎴峰悕锛岃浆鎹负鏁扮粍
     if (selectedProcess.userPower) {
@@ -412,8 +503,16 @@
   }
 };
 
-// 娣诲姞鐢熶骇浠诲姟
+// 娣诲姞宸ュ簭
 const addProductionTask = () => {
+  if (!formState.value.productModelId) {
+    proxy.$modal.msgWarning("璇峰厛閫夋嫨浜у搧");
+    return;
+  }
+  if (processRouteItemsOptions.value.length === 0) {
+    proxy.$modal.msgWarning("璇峰厛閫夋嫨浜у搧浠ヨ幏鍙栧伐搴忓垪琛�");
+    return;
+  }
   processRouteItems.value.push({
     processId: undefined,
     processName: "",
@@ -446,6 +545,8 @@
         parentId: undefined,
         productOrderId: undefined,
         processId: undefined,
+        model: product.model || '',
+        productName: product.productName || '',
         unitQuantity: 1,
         demandedQuantity: 1,
         unit: product.unit,
@@ -461,9 +562,47 @@
   productStructureRecords.value.splice(index, 1);
 };
 
-// 鏂囦欢涓婁紶鍙樻洿
-const handleFileChange = (file, files) => {
-  fileList.value = files;
+const handleDrawingBeforeUpload = (file) => {
+  const isAllowed = [
+    'application/pdf',
+    'image/jpeg',
+    'image/jpg',
+    'image/png',
+    'application/dwg'
+  ].includes(file.type) || file.name.endsWith('.dwg');
+  const isLt10M = file.size / 1024 / 1024 < 10;
+  
+  if (!isAllowed) {
+    proxy.$modal.msgError("鍙兘涓婁紶 pdf銆乯pg銆乯peg銆乸ng銆乨wg 鏍煎紡鐨勬枃浠讹紒");
+    return false;
+  }
+  if (!isLt10M) {
+    proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB锛�");
+    return false;
+  }
+  return true;
+};
+
+const handleDrawingUploadSuccess = (response, file, fileList) => {
+  console.log('涓婁紶鎴愬姛鍝嶅簲', response);
+  console.log('response.data', response.data);
+  if (response.code === 200) {
+    formState.value.tempFileIds = [response.data?.tempId];
+    formState.value.salesLedgerFiles = [{
+      tempId: response.data?.tempId,
+      originalName: response.data?.originalName || file.name,
+      tempPath: response.data?.tempPath,
+      type: response.data?.type || 14
+    }];
+    proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+  } else {
+    proxy.$modal.msgError(response.msg || "涓婁紶澶辫触");
+  }
+};
+
+const handleDrawingRemove = (file) => {
+  formState.value.tempFileIds = [];
+  formState.value.salesLedgerFiles = [];
 };
 
 const handleSubmit = () => {
@@ -490,7 +629,7 @@
         ...formState.value,
         processRouteItems: processedProcessRouteItems,
         productStructureRecords: productStructureRecords.value,
-        files: fileList.value,
+        files: formState.value.salesLedgerFiles,
       };
 
       addProductOrder(submitData).then(res => {
@@ -583,6 +722,31 @@
   padding: 20px 0;
 }
 
+.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 148px;
+  height: 148px;
+  text-align: center;
+  line-height: 148px;
+}
+
+:deep(.el-upload--picture-card) {
+  width: 148px;
+  height: 148px;
+}
+
+:deep(.el-upload-list__item) {
+  width: 148px;
+  height: 148px;
+}
+
+:deep(.el-upload__tip) {
+  font-size: 12px;
+  color: #909399;
+  margin-top: 8px;
+}
+
 .upload-inline :deep(.el-upload) {
   display: inline-flex;
 }
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index a376df1..8ba6699 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -83,7 +83,7 @@
     productOrderListPage,
     listProcessRoute,
     bindingRoute,
-    listProcessBom, delProductOrder,
+    listProcessBom, delProductOrder, startOrPause,
   } from "@/api/productionManagement/productionOrder.js";
   import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js";
   import {fileDel} from "@/api/financialManagement/revenueManagement.js";
@@ -158,8 +158,24 @@
       label: "鎿嶄綔",
       align: "center",
       fixed: "right",
-      width: 200,
+      width: 240,
       operation: [
+        {
+          name: "寮�濮�",
+          type: "text",
+          showHide: row => row.status === '寰呯敓浜�',
+          clickFun: row => {
+            handleStartOrPause(row);
+          },
+        },
+        {
+          name: "鏆傚仠",
+          type: "text",
+          showHide: row => row.status === '鐢熶骇涓�',
+          clickFun: row => {
+            handleStartOrPause(row);
+          },
+        },
         {
           name: "宸ヨ壓璺嚎",
           type: "text",
@@ -176,7 +192,7 @@
           },
         },
         {
-          name: "浜у搧缁撴瀯",
+          name: "鐗╂枡娓呭崟",
           type: "text",
           clickFun: row => {
             showProductStructure(row);
@@ -225,6 +241,8 @@
     if (row.isFh) return '';
 
     const diff = row.deliveryDaysDiff;
+    if (diff === undefined || diff === null || diff === '' || diff < 0) return '';
+    
     if (diff === 15) {
       return 'yellow';
     } else if (diff === 10) {
@@ -331,11 +349,12 @@
     const orderId = row.id;
     try {
       const res = await getOrderProcessRouteMain(orderId);
-      const data = res.data || {};
-      if (!data || !data.id) {
+      const dataList = res.data || [];
+      if (!dataList || dataList.length === 0 || !dataList[0].id) {
         proxy.$modal.msgWarning("鏈壘鍒板叧鑱旂殑宸ヨ壓璺嚎");
         return;
       }
+      const data = dataList[0];
       router.push({
         path: "/productionManagement/processRouteItem",
         query: {
@@ -356,12 +375,37 @@
     }
   };
 
-  const showProductStructure = row => {
+  const handleStartOrPause = async (row) => {
+    const operation = row.status === '寰呯敓浜�' ? 1 : 2;
+    const operationText = operation === 1 ? "寮�濮�" : "鏆傚仠";
+    try {
+      await startOrPause({ id: row.id, operation });
+      proxy.$modal.msgSuccess(`${operationText}鎴愬姛`);
+      getList();
+    } catch (e) {
+      console.error(`${operationText}澶辫触锛歚, e);
+      proxy.$modal.msgError(`${operationText}澶辫触`);
+    }
+  };
+
+  const showProductStructure = async row => {
+    let bomNo = row.bomNo || "";
+    if (!bomNo && row.id) {
+      try {
+        const res = await getOrderProcessRouteMain(row.id);
+        const dataList = res.data || [];
+        if (dataList && dataList.length > 0 && dataList[0].bomNo) {
+          bomNo = dataList[0].bomNo;
+        }
+      } catch (e) {
+        console.error("鑾峰彇BOM缂栧彿澶辫触锛�", e);
+      }
+    }
     router.push({
       path: "/productionManagement/productStructureDetail",
       query: {
         id: row.id,
-        bomNo: row.bomNo || "",
+        bomNo: bomNo,
         drawingNumber: row.drawingNumber || "",
         productName: row.productCategory || "",
         productModelName: row.specificationModel || "",
@@ -434,7 +478,7 @@
 }
 
 :deep(.red) {
-  background-color: #f80202;
+  background-color: #FFCCCC;
 }
 
 :deep(.purple){
diff --git a/src/views/productionManagement/productionReporting/index.vue b/src/views/productionManagement/productionReporting/index.vue
index 4e28304..f596301 100644
--- a/src/views/productionManagement/productionReporting/index.vue
+++ b/src/views/productionManagement/productionReporting/index.vue
@@ -168,11 +168,6 @@
       width: 120,
     },
     {
-      label: "閿�鍞悎鍚屽彿",
-      prop: "salesContractNo",
-      width: 120,
-    },
-    {
       label: "浜у搧鍚嶇О",
       prop: "productName",
       width: 120,
@@ -181,11 +176,6 @@
       label: "浜у搧鍥剧焊缂栧彿",
       prop: "productModelName",
       width: 160,
-    },
-    {
-      label: "浜у搧瑙勬牸鍨嬪彿",
-      prop: "drawingNumber",
-      width: 120,
     },
     {
       label: "浜у嚭鏁伴噺",
diff --git a/src/views/productionManagement/workOrder/index.vue b/src/views/productionManagement/workOrder/index.vue
index f27b39c..1911e65 100644
--- a/src/views/productionManagement/workOrder/index.vue
+++ b/src/views/productionManagement/workOrder/index.vue
@@ -255,10 +255,6 @@
       prop: "model"
     },
     {
-      label: "瑙勬牸鍨嬪彿",
-      prop: "drawingNumber",
-    },
-    {
       label: "鍗曚綅",
       prop: "unit",
     },
@@ -333,7 +329,7 @@
           clickFun: row => {
             showReportDialog(row);
           },
-          disabled: row => row.planQuantity <= 0,
+          disabled: row => row.status === 1 || row.status === 3 || row.planQuantity <= 0,
         },
       ],
     },

--
Gitblit v1.9.3