From 4e44261ac4f6dcac2f15b3d30636d4b4823f6918 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期三, 27 五月 2026 13:24:38 +0800
Subject: [PATCH] 君哥 1.恢复之前工艺路线模块,删除字段计件/计时字段,工资定额修改成计划工时,新增计划执行人员。工艺绑定,工艺路线恢复。仅需删除bom。 2.对于新增订单需流转协同办公进行审批,审批完成流转生产管控-生产订单 3.新增审批管理,规范管理所有节点审批人。 4.修改菜单栏样式bug

---
 src/views/productionManagement/productionProcess/index.vue                 |   11 
 src/api/collaborativeApproval/approvalManagement.js                        |   20 
 src/assets/styles/sidebar.scss                                             |  331 +++---
 src/views/productionManagement/processRoute/processRouteItem/index.vue     |   28 
 src/assets/styles/element-ui.scss                                          |  224 ++-
 src/views/collaborativeApproval/approvalProcess/index.vue                  |  479 +++++++-
 src/views/salesManagement/salesLedger/index.vue                            |   65 -
 src/views/salesManagement/salesQuotation/index.vue                         |  196 ---
 src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue |  138 --
 src/views/productionManagement/productionProcess/Edit.vue                  |  195 --
 src/views/collaborativeApproval/approvalManagement/index.vue               |  885 ++++++++++++++++
 src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue |   40 
 src/views/procurementManagement/procurementLedger/index.vue                |   85 -
 src/views/productionManagement/productionOrder/New.vue                     |    4 
 src/views/productionManagement/processRoute/New.vue                        |   76 -
 src/layout/components/Sidebar/index.vue                                    |   45 
 src/views/productionManagement/processRoute/Edit.vue                       |  204 ++-
 src/layout/components/Sidebar/SidebarItem.vue                              |    2 
 src/views/productionManagement/productionProcess/New.vue                   |  137 -
 19 files changed, 1,877 insertions(+), 1,288 deletions(-)

diff --git a/src/api/collaborativeApproval/approvalManagement.js b/src/api/collaborativeApproval/approvalManagement.js
new file mode 100644
index 0000000..c2ce4c7
--- /dev/null
+++ b/src/api/collaborativeApproval/approvalManagement.js
@@ -0,0 +1,20 @@
+// 瀹℃壒绠$悊閰嶇疆
+import request from "@/utils/request";
+
+// 鏌ヨ瀹℃壒娴佺▼閰嶇疆鑺傜偣鍒楄〃
+export function getApproveProcessConfigNodeList(type) {
+    return request({
+        url: '/approveProcessConfigNode/list',
+        method: 'get',
+        params: { type },
+    })
+}
+
+// 鏂板瀹℃壒娴佺▼閰嶇疆鑺傜偣
+export function addApproveProcessConfigNode(data) {
+    return request({
+        url: '/approveProcessConfigNode/add',
+        method: 'post',
+        data: data,
+    })
+}
diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss
index f296f9d..0c4dcd8 100644
--- a/src/assets/styles/element-ui.scss
+++ b/src/assets/styles/element-ui.scss
@@ -1,52 +1,52 @@
-// cover some element-ui styles
-
-.el-breadcrumb__inner,
-.el-breadcrumb__inner a {
-  font-weight: 400 !important;
-}
-
-.el-upload {
-  input[type="file"] {
-    display: none !important;
-  }
-}
-
-.el-upload__input {
-  display: none;
-}
-
-.cell {
-  .el-tag {
-    margin-right: 0px;
-  }
-}
-
-.small-padding {
-  .cell {
-    padding-left: 5px;
-    padding-right: 5px;
-  }
-}
-
-.fixed-width {
-  .el-button--mini {
-    padding: 7px 10px;
-    width: 60px;
-  }
-}
-
-.status-col {
-  .cell {
-    padding: 0 10px;
-    text-align: center;
-
-    .el-tag {
-      margin-right: 0px;
-    }
-  }
-}
-
-// to fixed https://github.com/ElemeFE/element/issues/2461
+// cover some element-ui styles
+
+.el-breadcrumb__inner,
+.el-breadcrumb__inner a {
+  font-weight: 400 !important;
+}
+
+.el-upload {
+  input[type="file"] {
+    display: none !important;
+  }
+}
+
+.el-upload__input {
+  display: none;
+}
+
+.cell {
+  .el-tag {
+    margin-right: 0px;
+  }
+}
+
+.small-padding {
+  .cell {
+    padding-left: 5px;
+    padding-right: 5px;
+  }
+}
+
+.fixed-width {
+  .el-button--mini {
+    padding: 7px 10px;
+    width: 60px;
+  }
+}
+
+.status-col {
+  .cell {
+    padding: 0 10px;
+    text-align: center;
+
+    .el-tag {
+      margin-right: 0px;
+    }
+  }
+}
+
+// to fixed https://github.com/ElemeFE/element/issues/2461
 .el-dialog {
   transform: none;
   left: 0;
@@ -98,64 +98,86 @@
 .el-message-box__content {
   padding: 24px 24px 0;
 }
-.el-message-box__container {
-  justify-content: center;
-}
-.el-message-box__btns {
-  text-align: center;
-  padding: 16px;
-  display: flex;
-  flex-direction: row-reverse;
-  justify-content: center;
-  align-items: center;
-  .el-button--primary {
-    margin-right: 12px;
-  }
-}
+.el-message-box__container {
+  justify-content: center;
+}
+.el-message-box__btns {
+  text-align: center;
+  padding: 16px;
+  display: flex;
+  flex-direction: row-reverse;
+  justify-content: center;
+  align-items: center;
+  .el-button--primary {
+    margin-right: 12px;
+  }
+}
 .el-table__expanded-cell {
   padding: 0 !important;
   .el-table__header-wrapper {
     background-color: var(--surface-soft) !important;
   }
 }
-
-// refine element ui upload
-.upload-container {
-  .el-upload {
-    width: 100%;
-
-    .el-upload-dragger {
-      width: 100%;
-      height: 200px;
-    }
-  }
-}
-
-// dropdown
-.el-dropdown-menu {
-  a {
-    display: block;
-  }
-}
-
-// fix date-picker ui bug in filter-item
-.el-range-editor.el-input__inner {
-  display: inline-flex !important;
-}
-
-// to fix el-date-picker css style
-.el-range-separator {
-  box-sizing: content-box;
-}
-
-.el-menu--collapse
-  > div
-  > .el-submenu
-  > .el-submenu__title
-  .el-submenu__icon-arrow {
-  display: none;
-}
-
+
+// refine element ui upload
+.upload-container {
+  .el-upload {
+    width: 100%;
+
+    .el-upload-dragger {
+      width: 100%;
+      height: 200px;
+    }
+  }
+}
+
+// dropdown
+.el-dropdown-menu {
+  a {
+    display: block;
+  }
+}
+
+// fix date-picker ui bug in filter-item
+.el-range-editor.el-input__inner {
+  display: inline-flex !important;
+}
+
+// to fix el-date-picker css style
+.el-range-separator {
+  box-sizing: content-box;
+}
+
+.el-menu--collapse
+  > div
+  > .el-sub-menu
+  > .el-sub-menu__title
+  .el-sub-menu__icon-arrow {
+  display: none;
+}
+
+/* 纭繚鑿滃崟绠ご濮嬬粓鏄剧ず - 浣跨敤 flex 甯冨眬 */
+.el-sub-menu__title {
+  display: flex !important;
+  align-items: center !important;
+  line-height: normal !important;
+}
+
+.el-sub-menu__title .el-sub-menu__icon-arrow {
+  position: static !important;
+  display: inline-flex !important;
+  visibility: visible !important;
+  width: auto !important;
+  height: auto !important;
+  overflow: visible !important;
+  margin-left: auto !important;
+  align-self: center !important;
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+  transform: none !important;
+  top: auto !important;
+}
+
 .el-dropdown .el-dropdown-link {
   color: var(--el-color-primary) !important;
 }
diff --git a/src/assets/styles/sidebar.scss b/src/assets/styles/sidebar.scss
index be7b7a7..ff49a33 100644
--- a/src/assets/styles/sidebar.scss
+++ b/src/assets/styles/sidebar.scss
@@ -1,70 +1,69 @@
-#app {
-  .main-container {
-    min-height: 100%;
-    transition: margin-left 0.28s;
-    margin-left: $base-sidebar-width;
-    position: relative;
-    background: transparent;
-  }
-
-  .sidebarHide {
-    margin-left: 0 !important;
-  }
-
-  .sidebar-container {
-    transition: width 0.28s;
-    width: $base-sidebar-width !important;
-    height: 100%;
-    position: fixed;
-    font-size: 0px;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    z-index: 1001;
-    overflow: hidden;
-    padding: 12px 0 16px 16px;
-    background: transparent;
-    box-shadow: none;
-
-    // reset element-ui css
-    .horizontal-collapse-transition {
-      transition: 0s width ease-in-out, 0s padding-left ease-in-out,
-        0s padding-right ease-in-out;
-    }
-
-    .scrollbar-wrapper {
-      overflow-x: hidden !important;
-    }
-
-    .el-scrollbar__bar.is-vertical {
-      right: 0px;
-    }
-
-    .el-scrollbar {
-      height: 100%;
-    }
-
-    &.has-logo {
-      .el-scrollbar {
-        height: calc(100% - 72px);
-        margin-top: 10px;
-      }
-    }
-
-    .is-horizontal {
-      display: none;
-    }
-
-    a {
-      display: inline-block;
-      width: 100%;
-      overflow: hidden;
-    }
-
-    .svg-icon {
-      margin-right: 16px;
-    }
-
+#app {
+  .main-container {
+    min-height: 100%;
+    transition: margin-left 0.28s;
+    margin-left: $base-sidebar-width;
+    position: relative;
+    background: transparent;
+  }
+
+  .sidebarHide {
+    margin-left: 0 !important;
+  }
+
+  .sidebar-container {
+    transition: width 0.28s;
+    width: $base-sidebar-width !important;
+    height: 100%;
+    position: fixed;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    z-index: 1001;
+    overflow: hidden;
+    padding: 12px 0 16px 16px;
+    background: transparent;
+    box-shadow: none;
+
+    // reset element-ui css
+    .horizontal-collapse-transition {
+      transition: 0s width ease-in-out, 0s padding-left ease-in-out,
+        0s padding-right ease-in-out;
+    }
+
+    .scrollbar-wrapper {
+      overflow-x: hidden !important;
+    }
+
+    .el-scrollbar__bar.is-vertical {
+      right: 0px;
+    }
+
+    .el-scrollbar {
+      height: 100%;
+    }
+
+    &.has-logo {
+      .el-scrollbar {
+        height: calc(100% - 72px);
+        margin-top: 10px;
+      }
+    }
+
+    .is-horizontal {
+      display: none;
+    }
+
+    a {
+      display: inline-block;
+      width: 100%;
+      overflow: hidden;
+    }
+
+    .svg-icon {
+      margin-right: 16px;
+    }
+
     .el-menu {
       border: none;
       height: 100%;
@@ -75,18 +74,18 @@
       backdrop-filter: blur(18px);
       box-shadow: var(--shadow-sm);
     }
-
-    .el-menu-item,
-    .menu-title {
-      overflow: hidden !important;
-      text-overflow: ellipsis !important;
-      white-space: nowrap !important;
-    }
-
-    .el-menu-item .el-menu-tooltip__trigger {
-      display: inline-block !important;
-    }
-
+
+    .el-menu-item,
+    .menu-title {
+      overflow: hidden !important;
+      text-overflow: ellipsis !important;
+      white-space: nowrap !important;
+    }
+
+    .el-menu-item .el-menu-tooltip__trigger {
+      display: inline-block !important;
+    }
+
     // menu hover
     .submenu-title-noDropdown,
     .el-sub-menu__title {
@@ -95,17 +94,33 @@
         border-radius: 14px;
       }
     }
-    & .theme-light .is-active > .el-sub-menu__title {
-      color: var(--current-color) !important;
-    }
-
+
+    // 鎵�鏈夊瓙鑿滃崟鏍囬锛屼娇鐢� flex 甯冨眬璁╃澶村拰鏂囧瓧鍦ㄤ竴鎺�
+    .el-sub-menu__title {
+      padding-right: 10px !important;
+      display: flex !important;
+      align-items: center !important;
+      line-height: normal !important;
+    }
+
+    // 椤剁骇瀛愯彍鍗曟爣棰�
+    & > .el-menu > .el-sub-menu > .el-sub-menu__title {
+      padding-right: 10px !important;
+      display: flex !important;
+      align-items: center !important;
+      line-height: normal !important;
+    }
+    & .theme-light .is-active > .el-sub-menu__title {
+      color: var(--current-color) !important;
+    }
+
     & .nest-menu .el-sub-menu > .el-sub-menu__title,
     & .el-sub-menu .el-menu-item {
       min-width: 0 !important;
       margin: 0 12px 6px;
       width: calc(100% - 24px);
       padding-left: 8px !important;
-      padding-right: 8px !important;
+      padding-right: 24px !important;
       box-sizing: border-box;
 
       &:hover {
@@ -116,7 +131,7 @@
         border-radius: 14px;
       }
     }
-
+
     & .theme-light .nest-menu .el-sub-menu > .el-sub-menu__title,
     & .theme-light .el-sub-menu .el-menu-item {
       //background-color: transparent;
@@ -127,7 +142,7 @@
       }
     }
   }
-
+
   .hideSidebar {
     .sidebar-container {
       width: 68px !important;
@@ -138,7 +153,7 @@
     .main-container {
       margin-left: 84px;
     }
-
+
     .submenu-title-noDropdown {
       padding: 0 !important;
       position: relative;
@@ -225,60 +240,56 @@
             width: 0;
             overflow: hidden;
             visibility: hidden;
-            display: inline-block;
-          }
-          & > i {
-            height: 0;
-            width: 0;
-            overflow: hidden;
-            visibility: hidden;
-            display: inline-block;
+            display: inline-block;
+          }
+          & > i.el-sub-menu__icon-arrow {
+            display: none;
           }
         }
       }
     }
   }
-
-  .el-menu--collapse .el-menu .el-sub-menu {
-    min-width: $base-sidebar-width !important;
-  }
-
-  // mobile responsive
-  .mobile {
-    .main-container {
-      margin-left: 0px;
-    }
-
-    .sidebar-container {
-      transition: transform 0.28s;
-      width: $base-sidebar-width !important;
-    }
-
-    &.hideSidebar {
-      .sidebar-container {
-        pointer-events: none;
-        transition-duration: 0.3s;
-        transform: translate3d(-$base-sidebar-width, 0, 0);
-      }
-    }
-  }
-
-  .withoutAnimation {
-    .main-container,
-    .sidebar-container {
-      transition: none;
-    }
-  }
-}
-
-// when menu collapsed
-.el-menu--vertical {
-  & > .el-menu {
-    .svg-icon {
-      margin-right: 16px;
-    }
-  }
-
+
+  .el-menu--collapse .el-menu .el-sub-menu {
+    min-width: $base-sidebar-width !important;
+  }
+
+  // mobile responsive
+  .mobile {
+    .main-container {
+      margin-left: 0px;
+    }
+
+    .sidebar-container {
+      transition: transform 0.28s;
+      width: $base-sidebar-width !important;
+    }
+
+    &.hideSidebar {
+      .sidebar-container {
+        pointer-events: none;
+        transition-duration: 0.3s;
+        transform: translate3d(-$base-sidebar-width, 0, 0);
+      }
+    }
+  }
+
+  .withoutAnimation {
+    .main-container,
+    .sidebar-container {
+      transition: none;
+    }
+  }
+}
+
+// when menu collapsed
+.el-menu--vertical {
+  & > .el-menu {
+    .svg-icon {
+      margin-right: 16px;
+    }
+  }
+
   .nest-menu .el-sub-menu > .el-sub-menu__title,
   .el-menu-item {
     min-width: 0 !important;
@@ -297,27 +308,27 @@
       border-radius: 14px;
     }
   }
-
-  // the scroll bar appears when the sub-menu is too long
-  > .el-menu--popup {
-    max-height: 100vh;
-    overflow-y: auto;
-    padding: 8px;
-    border-radius: 18px;
-    border: 1px solid var(--surface-border);
-    box-shadow: var(--shadow-md);
-
-    &::-webkit-scrollbar-track-piece {
-      background: #dfe7e1;
-    }
-
-    &::-webkit-scrollbar {
-      width: 6px;
-    }
-
-    &::-webkit-scrollbar-thumb {
-      background: #9aa79e;
-      border-radius: 20px;
-    }
-  }
-}
+
+  // the scroll bar appears when the sub-menu is too long
+  > .el-menu--popup {
+    max-height: 100vh;
+    overflow-y: auto;
+    padding: 8px;
+    border-radius: 18px;
+    border: 1px solid var(--surface-border);
+    box-shadow: var(--shadow-md);
+
+    &::-webkit-scrollbar-track-piece {
+      background: #dfe7e1;
+    }
+
+    &::-webkit-scrollbar {
+      width: 6px;
+    }
+
+    &::-webkit-scrollbar-thumb {
+      background: #9aa79e;
+      border-radius: 20px;
+    }
+  }
+}
diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue
index f395d95..955a8d4 100644
--- a/src/layout/components/Sidebar/SidebarItem.vue
+++ b/src/layout/components/Sidebar/SidebarItem.vue
@@ -9,7 +9,7 @@
       </app-link>
     </template>
 
-    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)" teleported>
+    <el-sub-menu v-else ref="subMenu" :index="resolvePath(item.path)">
       <template v-if="item.meta" #title>
         <svg-icon :icon-class="item.meta && item.meta.icon" />
         <span class="menu-title" :title="hasTitle(item.meta.title)">{{ item.meta.title }}</span>
diff --git a/src/layout/components/Sidebar/index.vue b/src/layout/components/Sidebar/index.vue
index 83d3026..fd73024 100644
--- a/src/layout/components/Sidebar/index.vue
+++ b/src/layout/components/Sidebar/index.vue
@@ -99,6 +99,10 @@
 
     .el-sub-menu__title {
       color: v-bind(getMenuTextColor);
+      padding-right: 10px !important;
+      display: flex !important;
+      align-items: center !important;
+      line-height: normal !important;
     }
 
     :deep(.el-sub-menu.is-active > .el-sub-menu__title) {
@@ -111,8 +115,10 @@
       padding-left: 10px !important;
       padding-right: 10px !important;
       box-sizing: border-box;
-      overflow: hidden;
       background-clip: padding-box;
+      display: flex !important;
+      align-items: center !important;
+      line-height: normal !important;
     }
 
     :deep(.el-menu-item.is-active) {
@@ -137,6 +143,43 @@
     :deep(.el-menu-item:hover) {
       border-radius: 14px;
     }
+
+    /* 纭繚瀛愯彍鍗曠澶存樉绀� - 浣跨敤 flex 甯冨眬璁╃澶村拰鏂囧瓧鍦ㄤ竴鎺� */
+    :deep(.el-sub-menu .el-sub-menu__title) {
+      display: flex !important;
+      align-items: center !important;
+      justify-content: flex-start !important;
+      line-height: normal !important;
+    }
+
+    :deep(.el-sub-menu .el-sub-menu__title .el-sub-menu__icon-arrow) {
+      position: static !important;
+      display: inline-flex !important;
+      visibility: visible !important;
+      width: auto !important;
+      height: auto !important;
+      overflow: visible !important;
+      margin-left: auto !important;
+      margin-right: 0 !important;
+      order: 999 !important;
+      align-self: center !important;
+      margin-top: 0 !important;
+      margin-bottom: 0 !important;
+      transform: none !important;
+      top: auto !important;
+    }
+
+    /* 纭繚涓�绾ц彍鍗曠澶存樉绀� */
+    :deep(> .el-menu > .el-sub-menu > .el-sub-menu__title .el-sub-menu__icon-arrow) {
+      display: inline-flex !important;
+      visibility: visible !important;
+    }
+
+    /* 纭繚浜岀骇鑿滃崟绠ご鏄剧ず */
+    :deep(.nest-menu .el-sub-menu > .el-sub-menu__title .el-sub-menu__icon-arrow) {
+      display: inline-flex !important;
+      visibility: visible !important;
+    }
   }
 }
 </style>
diff --git a/src/views/collaborativeApproval/approvalManagement/index.vue b/src/views/collaborativeApproval/approvalManagement/index.vue
new file mode 100644
index 0000000..aaf3a43
--- /dev/null
+++ b/src/views/collaborativeApproval/approvalManagement/index.vue
@@ -0,0 +1,885 @@
+<template>
+  <div class="app-container">
+    <!-- 椤甸潰鏍囬 -->
+    <div class="page-header">
+      <div class="header-title">
+        <el-icon class="title-icon"><Setting /></el-icon>
+        <span>瀹℃壒娴佺▼閰嶇疆</span>
+      </div>
+      <div class="header-desc">涓轰笉鍚屽鎵圭被鍨嬮厤缃鎵规祦绋嬪拰瀹℃壒浜�</div>
+    </div>
+
+    <!-- 瀹℃壒绫诲瀷鍒囨崲 - 绱у噾鏍囩寮� -->
+    <div class="type-tabs">
+      <div
+        v-for="type in approveTypes"
+        :key="type.value"
+        class="type-tab"
+        :class="{ active: activeTab === type.value }"
+        @click="activeTab = type.value; handleTabChange()"
+      >
+        <el-icon :size="14" :style="{ color: activeTab === type.value ? type.color : '#909399' }">
+          <component :is="type.icon" />
+        </el-icon>
+        <span class="tab-name">{{ type.label }}</span>
+      </div>
+    </div>
+
+    <!-- 涓昏鍐呭鍖哄煙 -->
+    <el-card class="config-card" shadow="hover" v-loading="loading">
+      <template #header>
+        <div class="card-header">
+          <div class="header-left">
+            <div class="type-icon" :style="{ backgroundColor: getTypeColor(currentApproveType) }">
+              <el-icon :size="20" color="#fff"><component :is="getTypeIcon(currentApproveType)" /></el-icon>
+            </div>
+            <div class="header-info">
+              <span class="type-name">{{ currentApproveTypeName }}</span>
+              <el-tag :type="approverList.length > 0 ? 'success' : 'warning'" size="small" effect="light">
+                {{ approverList.length > 0 ? `宸查厤缃� ${approverList.length} 涓鎵逛汉` : '鏈厤缃鎵逛汉' }}
+              </el-tag>
+            </div>
+          </div>
+          <div class="header-actions" v-if="approverList.length > 0">
+            <el-button @click="handleReset" size="default">
+              <el-icon><RefreshLeft /></el-icon>
+              閲嶇疆
+            </el-button>
+            <el-button type="primary" @click="handleSave" :loading="saveLoading" size="default">
+              <el-icon><Check /></el-icon>
+              淇濆瓨閰嶇疆
+            </el-button>
+          </div>
+        </div>
+      </template>
+
+      <!-- 瀹℃壒娴佺▼灞曠ず -->
+      <div class="flow-wrapper" v-if="approverList.length > 0">
+        <div class="flow-container">
+          <div
+            v-for="(item, index) in approverList"
+            :key="index"
+            class="flow-item"
+          >
+            <!-- 瀹℃壒鑺傜偣鍗$墖 -->
+            <div class="node-card" :class="{ 'empty': !item.approverId }">
+              <!-- 椤堕儴搴忓彿鍜岀骇鍒� -->
+              <div class="node-badge">{{ index + 1 }}</div>
+              
+              <!-- 澶村儚鍖哄煙 -->
+              <div class="node-avatar-section">
+                <div 
+                  class="node-avatar" 
+                  :class="{ 'has-user': item.approverId }"
+                  :style="item.approverId ? { backgroundColor: getAvatarColor(item.approverName) } : {}"
+                >
+                  <span v-if="item.approverId">{{ item.approverName.charAt(0) }}</span>
+                  <el-icon v-else :size="24"><User /></el-icon>
+                </div>
+                <div class="node-level">{{ getLevelText(index) }}</div>
+              </div>
+
+              <!-- 閫夋嫨鍖哄煙 -->
+              <div class="node-select-section">
+                <el-select
+                  v-model="item.approverId"
+                  placeholder="閫夋嫨瀹℃壒浜�"
+                  filterable
+                  size="default"
+                  @change="(val) => handleApproverChange(val, item)"
+                >
+                  <el-option
+                    v-for="user in userList"
+                    :key="user.userId"
+                    :label="user.nickName"
+                    :value="user.userId"
+                  />
+                </el-select>
+              </div>
+
+              <!-- 鎿嶄綔鎸夐挳 -->
+              <div class="node-actions">
+                <el-button
+                  type="primary"
+                  circle
+                  :disabled="index === 0"
+                  @click="moveLeft(index)"
+                  size="small"
+                  class="action-btn"
+                  title="鍓嶇Щ"
+                >
+                  <el-icon><ArrowLeft /></el-icon>
+                </el-button>
+                <el-button
+                  type="primary"
+                  circle
+                  :disabled="index === approverList.length - 1"
+                  @click="moveRight(index)"
+                  size="small"
+                  class="action-btn"
+                  title="鍚庣Щ"
+                >
+                  <el-icon><ArrowRight /></el-icon>
+                </el-button>
+                <el-button
+                  type="danger"
+                  circle
+                  @click="handleDelete(index)"
+                  size="small"
+                  class="action-btn"
+                >
+                  <el-icon><Delete /></el-icon>
+                </el-button>
+              </div>
+            </div>
+
+            <!-- 杩炴帴绠ご -->
+            <div class="arrow-connector" v-if="index < approverList.length - 1">
+              <div class="arrow-line"></div>
+              <el-icon class="arrow-icon"><ArrowRight /></el-icon>
+            </div>
+          </div>
+
+          <!-- 鏂板鑺傜偣鎸夐挳 - 鏀惧湪娴佺▼鏈�鍚� -->
+          <div class="add-node-item">
+            <div class="arrow-connector" v-if="approverList.length > 0">
+              <div class="arrow-line"></div>
+              <el-icon class="arrow-icon"><ArrowRight /></el-icon>
+            </div>
+            <div class="add-node-card" @click="handleAdd">
+              <div class="add-icon-wrapper">
+                <el-icon :size="28"><Plus /></el-icon>
+              </div>
+              <span class="add-text">鏂板瀹℃壒浜�</span>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <!-- 绌虹姸鎬� -->
+      <div class="empty-state" v-else>
+        <div class="empty-content">
+          <div class="empty-icon-wrapper">
+            <el-icon :size="48" color="#c0c4cc"><User /></el-icon>
+          </div>
+          <div class="empty-text">鏆傛棤瀹℃壒浜洪厤缃�</div>
+          <div class="empty-subtext">鐐瑰嚮涓嬫柟鎸夐挳娣诲姞绗竴涓鎵逛汉</div>
+          <el-button type="primary" size="large" @click="handleAdd" class="empty-add-btn">
+            <el-icon><Plus /></el-icon>
+            鏂板瀹℃壒浜�
+          </el-button>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 搴曢儴鎻愮ず -->
+    <div class="bottom-tips">
+      <el-icon><InfoFilled /></el-icon>
+      <span>鎻愮ず锛氭瘡涓祦绋嬭嚦灏戦厤缃竴涓鎵逛汉锛屽鎵规寜椤哄簭娴佽浆锛屽彲閫氳繃绠ご璋冩暣椤哄簭</span>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, computed, onMounted } from 'vue';
+import { ElMessage, ElMessageBox } from 'element-plus';
+import {
+  Plus, ArrowLeft, Delete, Check, RefreshLeft, Setting,
+  Suitcase, Calendar, Location, Money, ShoppingCart, DocumentChecked,
+  Van, ArrowRight, User, InfoFilled, Sell
+} from '@element-plus/icons-vue';
+import { getApproveProcessConfigNodeList, addApproveProcessConfigNode } from '@/api/collaborativeApproval/approvalManagement';
+import { userListNoPage } from '@/api/system/user';
+
+// 褰撳墠閫変腑鐨勬爣绛鹃〉
+const activeTab = ref('1');
+
+// 瀹℃壒绫诲瀷閰嶇疆鏁扮粍
+const approveTypes = [
+  { value: '1', label: '鍏嚭绠$悊', icon: 'Suitcase', color: '#409EFF' },
+  { value: '2', label: '璇峰亣绠$悊', icon: 'Calendar', color: '#67C23A' },
+  { value: '3', label: '鍑哄樊绠$悊', icon: 'Location', color: '#E6A23C' },
+  { value: '4', label: '鎶ラ攢绠$悊', icon: 'Money', color: '#F56C6C' },
+  { value: '5', label: '閲囪喘瀹℃壒', icon: 'ShoppingCart', color: '#909399' },
+  { value: '6', label: '鎶ヤ环瀹℃壒', icon: 'DocumentChecked', color: '#9B59B6' },
+  { value: '7', label: '鍙戣揣瀹℃壒', icon: 'Van', color: '#1ABC9C' },
+  { value: '10', label: '閿�鍞鎵�', icon: 'Sell', color: '#FF6B6B' },
+];
+
+// 瀹℃壒绫诲瀷鍚嶇О鏄犲皠
+const approveTypeNameMap = {
+  1: '鍏嚭绠$悊',
+  2: '璇峰亣绠$悊',
+  3: '鍑哄樊绠$悊',
+  4: '鎶ラ攢绠$悊',
+  5: '閲囪喘瀹℃壒',
+  6: '鎶ヤ环瀹℃壒',
+  7: '鍙戣揣瀹℃壒',
+  10: '閿�鍞鎵�',
+};
+
+// 瀹℃壒绫诲瀷鍥炬爣鏄犲皠
+const typeIconMap = {
+  1: 'Suitcase',
+  2: 'Calendar',
+  3: 'Location',
+  4: 'Money',
+  5: 'ShoppingCart',
+  6: 'DocumentChecked',
+  7: 'Van',
+  10: 'Sell',
+};
+
+// 瀹℃壒绫诲瀷棰滆壊鏄犲皠
+const typeColorMap = {
+  1: '#409EFF',
+  2: '#67C23A',
+  3: '#E6A23C',
+  4: '#F56C6C',
+  5: '#909399',
+  6: '#9B59B6',
+  7: '#1ABC9C',
+  10: '#FF6B6B',
+};
+
+// 澶村儚棰滆壊姹�
+const avatarColors = ['#409EFF', '#67C23A', '#E6A23C', '#F56C6C', '#9B59B6', '#1ABC9C', '#FF6B6B', '#4ECDC4'];
+
+// 褰撳墠瀹℃壒绫诲瀷鍚嶇О
+const currentApproveTypeName = computed(() => {
+  return approveTypeNameMap[activeTab.value] || '鏈煡绫诲瀷';
+});
+
+// 褰撳墠瀹℃壒绫诲瀷
+const currentApproveType = computed(() => {
+  return Number(activeTab.value);
+});
+
+// 鑾峰彇绫诲瀷鍥炬爣
+const getTypeIcon = (type) => typeIconMap[type] || 'Setting';
+
+// 鑾峰彇绫诲瀷棰滆壊
+const getTypeColor = (type) => typeColorMap[type] || '#409EFF';
+
+// 鑾峰彇澶村儚棰滆壊
+const getAvatarColor = (name) => {
+  if (!name) return '#C0C4CC';
+  let hash = 0;
+  for (let i = 0; i < name.length; i++) {
+    hash = name.charCodeAt(i) + ((hash << 5) - hash);
+  }
+  return avatarColors[Math.abs(hash) % avatarColors.length];
+};
+
+// 鑾峰彇绾у埆鏂囨湰
+const getLevelText = (index) => {
+  const texts = ['绗竴绾�', '绗簩绾�', '绗笁绾�', '绗洓绾�', '绗簲绾�', '绗叚绾�', '绗竷绾�', '绗叓绾�'];
+  return texts[index] || `绗�${index + 1}绾;
+};
+
+// 瀹℃壒浜哄垪琛紙鐪熷疄鎺ュ彛锛�
+const userList = ref([]);
+
+// 瀹℃壒浜哄垪琛�
+const approverList = ref([]);
+
+// 鍘熷鏁版嵁锛岀敤浜庨噸缃�
+const originalList = ref([]);
+
+// 鍔犺浇鐘舵��
+const loading = ref(false);
+const saveLoading = ref(false);
+
+// 鏍囩椤靛垏鎹㈠鐞�
+const handleTabChange = () => {
+  loadData();
+};
+
+// 鍔犺浇瀹℃壒閰嶇疆鏁版嵁锛堟ā鎷燂級
+const loadData = async () => {
+  loading.value = true;
+  try {
+    const res = await getApproveProcessConfigNodeList(currentApproveType.value);
+    const source = Array.isArray(res?.data)
+      ? res.data
+      : Array.isArray(res?.rows)
+        ? res.rows
+        : Array.isArray(res?.data?.records)
+          ? res.data.records
+          : [];
+    const data = source.map((item, index) => ({
+      ...item,
+      sortOrder: item.nodeOrder ?? item.sortOrder ?? index + 1,
+    }));
+    approverList.value = data.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
+    originalList.value = JSON.parse(JSON.stringify(approverList.value));
+  } catch (error) {
+    approverList.value = [];
+    originalList.value = [];
+    ElMessage.error('鍔犺浇瀹℃壒閰嶇疆澶辫触');
+  } finally {
+    loading.value = false;
+  }
+};
+
+const loadUserList = async () => {
+  try {
+    const res = await userListNoPage();
+    userList.value = Array.isArray(res?.data) ? res.data : [];
+  } catch (error) {
+    userList.value = [];
+    ElMessage.error('鍔犺浇浜哄憳鍒楄〃澶辫触');
+  }
+};
+
+// 瀹℃壒浜洪�夋嫨鍙樺寲
+const handleApproverChange = (userId, row) => {
+  const user = userList.value.find((u) => u.userId === userId);
+  if (user) {
+    row.approverName = user.nickName;
+  }
+};
+
+// 鏂板瀹℃壒浜�
+const handleAdd = () => {
+  const newOrder = approverList.value.length + 1;
+  approverList.value.push({
+    id: null,
+    approveType: currentApproveType.value,
+    approverId: null,
+    approverName: '',
+    sortOrder: newOrder,
+  });
+};
+
+// 鍒犻櫎瀹℃壒浜�
+const handleDelete = (index) => {
+  ElMessageBox.confirm('纭畾鍒犻櫎璇ュ鎵逛汉鍚楋紵', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning',
+  })
+    .then(() => {
+      approverList.value.splice(index, 1);
+      approverList.value.forEach((item, idx) => {
+        item.sortOrder = idx + 1;
+      });
+      ElMessage.success('鍒犻櫎鎴愬姛');
+    })
+    .catch(() => {});
+};
+
+// 鍓嶇Щ
+const moveLeft = (index) => {
+  if (index === 0) return;
+  const temp = approverList.value[index];
+  approverList.value[index] = approverList.value[index - 1];
+  approverList.value[index - 1] = temp;
+  approverList.value[index].sortOrder = index + 1;
+  approverList.value[index - 1].sortOrder = index;
+};
+
+// 鍚庣Щ
+const moveRight = (index) => {
+  if (index === approverList.value.length - 1) return;
+  const temp = approverList.value[index];
+  approverList.value[index] = approverList.value[index + 1];
+  approverList.value[index + 1] = temp;
+  approverList.value[index].sortOrder = index + 1;
+  approverList.value[index + 1].sortOrder = index + 2;
+};
+
+// 淇濆瓨閰嶇疆
+const handleSave = async () => {
+  if (approverList.value.length === 0) {
+    ElMessage.warning('璇疯嚦灏戦厤缃竴涓鎵逛汉');
+    return;
+  }
+
+  const hasEmptyApprover = approverList.value.some((item) => !item.approverId);
+  if (hasEmptyApprover) {
+    ElMessage.warning('璇烽�夋嫨鎵�鏈夊鎵逛汉');
+    return;
+  }
+
+  const approverIds = approverList.value.map((item) => item.approverId);
+  const uniqueIds = [...new Set(approverIds)];
+  if (uniqueIds.length !== approverIds.length) {
+    ElMessage.warning('瀹℃壒浜轰笉鑳介噸澶�');
+    return;
+  }
+
+  saveLoading.value = true;
+  try {
+    const payload = approverList.value.map((item, index) => ({
+      approveType: currentApproveType.value,
+      nodeOrder: index + 1,
+      approverId: item.approverId,
+      approverName: item.approverName,
+    }));
+    await addApproveProcessConfigNode(payload);
+    ElMessage.success('淇濆瓨鎴愬姛');
+    await loadData();
+  } catch (error) {
+    ElMessage.error('淇濆瓨澶辫触');
+  } finally {
+    saveLoading.value = false;
+  }
+};
+
+// 閲嶇疆
+const handleReset = () => {
+  if (originalList.value.length === 0) {
+    approverList.value = [];
+    return;
+  }
+  ElMessageBox.confirm('纭畾瑕侀噸缃綋鍓嶉厤缃悧锛熸湭淇濆瓨鐨勬洿鏀瑰皢涓㈠け銆�', '鎻愮ず', {
+    confirmButtonText: '纭畾',
+    cancelButtonText: '鍙栨秷',
+    type: 'warning',
+  })
+    .then(() => {
+      approverList.value = JSON.parse(JSON.stringify(originalList.value));
+      ElMessage.success('宸查噸缃�');
+    })
+    .catch(() => {});
+};
+
+onMounted(async () => {
+  await loadUserList();
+  await loadData();
+});
+</script>
+
+<style scoped>
+.page-header {
+  margin-bottom: 20px;
+}
+
+.header-title {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+  font-size: 20px;
+  font-weight: 600;
+  color: var(--el-text-color-primary, #303133);
+  margin-bottom: 6px;
+}
+
+.title-icon {
+  font-size: 24px;
+  color: var(--el-color-primary, #409EFF);
+}
+
+.header-desc {
+  font-size: 13px;
+  color: var(--el-text-color-secondary, #909399);
+  margin-left: 34px;
+}
+
+/* 瀹℃壒绫诲瀷鍒囨崲 - 绱у噾鏍囩寮� */
+.type-tabs {
+  display: flex;
+  gap: 4px;
+  margin-bottom: 16px;
+  padding: 4px;
+  background: var(--el-fill-color-light, #f5f7fa);
+  border-radius: 8px;
+  overflow-x: auto;
+}
+
+.type-tab {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  padding: 8px 14px;
+  border-radius: 6px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+  white-space: nowrap;
+  font-size: 13px;
+  color: var(--el-text-color-regular, #606266);
+}
+
+.type-tab:hover {
+  background: var(--el-color-primary-light-9, rgba(64, 158, 255, 0.1));
+  color: var(--el-color-primary, #409EFF);
+}
+
+.type-tab.active {
+  background: var(--el-bg-color, #fff);
+  color: var(--el-color-primary, #409EFF);
+  font-weight: 600;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+}
+
+.tab-name {
+  font-size: 13px;
+}
+
+.tab-count {
+  min-width: 16px;
+  height: 16px;
+  padding: 0 5px;
+  background: var(--el-color-success, #67C23A);
+  color: #fff;
+  border-radius: 8px;
+  font-size: 11px;
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.config-card {
+  margin-bottom: 16px;
+  border-radius: 12px;
+}
+
+:deep(.el-card__header) {
+  padding: 16px 20px;
+  border-bottom: 1px solid var(--el-border-color-light, #ebeef5);
+}
+
+.card-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.header-left {
+  display: flex;
+  align-items: center;
+  gap: 14px;
+}
+
+.type-icon {
+  width: 44px;
+  height: 44px;
+  border-radius: 10px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.header-info {
+  display: flex;
+  flex-direction: column;
+  gap: 6px;
+}
+
+.type-name {
+  font-size: 16px;
+  font-weight: 600;
+  color: var(--el-text-color-primary, #303133);
+}
+
+.header-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.flow-wrapper {
+  overflow-x: auto;
+  padding: 8px 4px;
+}
+
+.flow-container {
+  display: flex;
+  align-items: center;
+  gap: 0;
+  min-width: min-content;
+}
+
+.flow-item {
+  display: flex;
+  align-items: center;
+}
+
+.node-card {
+  width: 200px;
+  background: var(--el-bg-color, #fff);
+  border: 2px solid var(--el-border-color, #e4e7ed);
+  border-radius: 12px;
+  padding: 16px;
+  position: relative;
+  transition: all 0.3s ease;
+  flex-shrink: 0;
+}
+
+.node-card:hover {
+  border-color: var(--el-color-primary, #409EFF);
+  box-shadow: 0 4px 16px rgba(64, 158, 255, 0.15);
+  transform: translateY(-2px);
+}
+
+.node-card.empty {
+  border-style: dashed;
+  border-color: var(--el-border-color, #c0c4cc);
+  background: var(--el-fill-color-light, #fafbfc);
+}
+
+.node-card.empty:hover {
+  border-color: var(--el-color-primary, #409EFF);
+  background: var(--el-fill-color-light, #f5f7fa);
+}
+
+.node-badge {
+  position: absolute;
+  top: -10px;
+  left: 16px;
+  width: 24px;
+  height: 24px;
+  background: var(--el-color-primary, #409EFF);
+  color: #fff;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  font-size: 13px;
+  font-weight: 700;
+  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.4);
+}
+
+.node-avatar-section {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  margin-bottom: 12px;
+  margin-top: 4px;
+}
+
+.node-avatar {
+  width: 56px;
+  height: 56px;
+  border-radius: 50%;
+  background: var(--el-fill-color, #f0f2f5);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 8px;
+  color: var(--el-text-color-placeholder, #c0c4cc);
+  transition: all 0.3s ease;
+}
+
+.node-avatar.has-user {
+  color: #fff;
+  font-size: 22px;
+  font-weight: 600;
+  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
+}
+
+.node-level {
+  font-size: 12px;
+  color: var(--el-text-color-secondary, #909399);
+  font-weight: 500;
+}
+
+.node-select-section {
+  margin-bottom: 12px;
+}
+
+.node-select-section :deep(.el-select) {
+  width: 100%;
+}
+
+.node-actions {
+  display: flex;
+  justify-content: center;
+  gap: 8px;
+  padding-top: 12px;
+  border-top: 1px solid var(--el-border-color-light, #ebeef5);
+}
+
+.action-btn {
+  transition: all 0.2s;
+}
+
+.action-btn:hover:not(:disabled) {
+  transform: scale(1.1);
+}
+
+.arrow-connector {
+  display: flex;
+  align-items: center;
+  width: 50px;
+  position: relative;
+}
+
+.arrow-line {
+  flex: 1;
+  height: 2px;
+  background: var(--el-border-color, #c0c4cc);
+}
+
+.arrow-icon {
+  color: var(--el-text-color-placeholder, #c0c4cc);
+  font-size: 14px;
+  margin-left: -2px;
+}
+
+/* 鏂板鑺傜偣鏍峰紡 */
+.add-node-item {
+  display: flex;
+  align-items: center;
+}
+
+.add-node-card {
+  width: 140px;
+  height: 200px;
+  border: 2px dashed var(--el-border-color, #c0c4cc);
+  border-radius: 12px;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 12px;
+  cursor: pointer;
+  transition: all 0.3s ease;
+  background: var(--el-fill-color-light, #fafbfc);
+  flex-shrink: 0;
+  margin-left: 0;
+}
+
+.add-node-card:hover {
+  border-color: var(--el-color-primary, #409EFF);
+  background: var(--el-color-primary-light-9, #f0f7ff);
+  transform: translateY(-2px);
+  box-shadow: 0 4px 16px rgba(64, 158, 255, 0.15);
+}
+
+.add-icon-wrapper {
+  width: 48px;
+  height: 48px;
+  border-radius: 50%;
+  background: var(--el-color-primary, #409EFF);
+  color: #fff;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
+  transition: all 0.3s ease;
+}
+
+.add-node-card:hover .add-icon-wrapper {
+  transform: scale(1.1);
+  box-shadow: 0 6px 16px rgba(64, 158, 255, 0.4);
+}
+
+.add-text {
+  font-size: 14px;
+  color: var(--el-text-color-regular, #606266);
+  font-weight: 500;
+}
+
+.add-node-card:hover .add-text {
+  color: var(--el-color-primary, #409EFF);
+}
+
+/* 绌虹姸鎬� */
+.empty-state {
+  padding: 50px 20px;
+}
+
+.empty-content {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 16px;
+}
+
+.empty-icon-wrapper {
+  width: 80px;
+  height: 80px;
+  border-radius: 50%;
+  background: var(--el-fill-color-light, #f5f7fa);
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-bottom: 8px;
+}
+
+.empty-text {
+  font-size: 16px;
+  font-weight: 600;
+  color: var(--el-text-color-regular, #606266);
+}
+
+.empty-subtext {
+  font-size: 13px;
+  color: var(--el-text-color-secondary, #909399);
+}
+
+.empty-add-btn {
+  margin-top: 8px;
+  padding: 12px 28px;
+}
+
+/* 搴曢儴鎻愮ず */
+.bottom-tips {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  gap: 8px;
+  padding: 12px 20px;
+  background: var(--el-fill-color-light, #f5f7fa);
+  border-radius: 8px;
+  color: var(--el-text-color-regular, #606266);
+  font-size: 13px;
+}
+
+.bottom-tips .el-icon {
+  color: var(--el-color-primary, #409EFF);
+  font-size: 16px;
+}
+
+@media (max-width: 768px) {
+  .type-tabs {
+    padding: 3px;
+  }
+
+  .type-tab {
+    padding: 6px 10px;
+    font-size: 12px;
+  }
+
+  .tab-name {
+    font-size: 12px;
+  }
+
+  .flow-container {
+    flex-wrap: wrap;
+    justify-content: center;
+  }
+
+  .arrow-connector {
+    width: 100%;
+    height: 30px;
+    flex-direction: row;
+    justify-content: center;
+  }
+
+  .arrow-line {
+    width: 2px;
+    height: 30px;
+  }
+
+  .arrow-icon {
+    right: auto;
+    top: auto;
+    bottom: -5px;
+    transform: rotate(90deg);
+  }
+
+  .add-node-item {
+    width: 100%;
+    justify-content: center;
+    margin-top: 10px;
+  }
+
+  .add-node-item .arrow-connector {
+    display: none;
+  }
+}
+</style>
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index 20a4ee6..1269621 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -39,39 +39,6 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
-				<!-- 瀹℃壒浜洪�夋嫨锛堝姩鎬佽妭鐐癸級 -->
-				<el-row :gutter="30">
-					<el-col :span="12">
-						<el-form-item label="鐢宠浜猴細" prop="approveUser">
-							<el-select
-								v-model="form.approveUser"
-								placeholder="閫夋嫨浜哄憳"
-								disabled
-							>
-								<el-option
-									v-for="user in userList"
-									:key="user.userId"
-									:label="user.nickName"
-									:value="user.userId"
-								/>
-							</el-select>
-						</el-form-item>
-					</el-col>
-					<el-col :span="12">
-						<el-form-item label="鐢宠鏃ユ湡锛�" prop="approveTime">
-							<el-date-picker
-								v-model="form.approveTime"
-								type="date"
-								placeholder="璇烽�夋嫨鏃ユ湡"
-								value-format="YYYY-MM-DD"
-								format="YYYY-MM-DD"
-								clearable
-								style="width: 100%"
-								disabled
-							/>
-						</el-form-item>
-					</el-col>
-				</el-row>
 			</el-form>
 
       <!-- 鎶ヤ环瀹℃壒锛氬睍绀烘姤浠疯鎯咃紙澶嶇敤閿�鍞姤浠�"鏌ョ湅璇︽儏瀵硅瘽妗�"鍐呭缁撴瀯锛� -->
@@ -228,7 +195,6 @@
 	updateApproveNode
 } from "@/api/collaborativeApproval/approvalProcess.js";
 import useUserStore from "@/store/modules/user.js";
-import {userListNoPageByTenantId} from "@/api/system/user.js";
 import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
 import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
 import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
@@ -248,7 +214,6 @@
 const formRef = ref(null);
 const userStore = useUserStore()
 const productOptions = ref([]);
-const userList = ref([])
 const quotationLoading = ref(false)
 const currentQuotation = ref({})
 const purchaseLoading = ref(false)
@@ -258,9 +223,7 @@
 
 const data = reactive({
 	form: {
-		approveTime: "",
 		approveId: "",
-		approveUser: "",
 		approveDeptId: "",
 		approveReason: "",
 		checkResult: "",
@@ -295,9 +258,6 @@
   dialogFormVisible.value = true;
   currentQuotation.value = {}
   currentPurchase.value = {}
-	userListNoPageByTenantId().then((res) => {
-		userList.value = res.data;
-	});
 	form.value = {...row}
 	// 绔嬪嵆娓呴櫎琛ㄥ崟楠岃瘉鐘舵�侊紙鍥犱负瀛楁鏄痙isabled鐨勶紝涓嶉渶瑕侀獙璇侊級
 	nextTick(() => {
diff --git a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
index 998fa33..8328ee6 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -97,82 +97,7 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <!-- 瀹℃壒浜洪�夋嫨锛堝姩鎬佽妭鐐癸級 -->
-        <el-row>
-          <el-col :span="24">
-            <el-form-item>
-              <template #label>
-                <span>瀹℃壒浜洪�夋嫨锛�</span>
-                <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">鏂板鑺傜偣</el-button>
-              </template>
-              <div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
-                <div
-                  v-for="(node, index) in approverNodes"
-                  :key="node.id"
-                  style="margin-right: 30px; text-align: center; margin-bottom: 10px;"
-                >
-                  <div>
-                    <span>瀹℃壒浜�</span>
-                    鈫�
-                  </div>
-                  <el-select
-                    v-model="node.userId"
-                    placeholder="閫夋嫨浜哄憳"
-                    style="width: 120px; margin-bottom: 8px;"
-                  >
-                    <el-option
-                      v-for="user in userList"
-                      :key="user.userId"
-                      :label="user.nickName"
-                      :value="user.userId"
-                    />
-                  </el-select>
-                  <div>
-                    <el-button
-                      type="danger"
-                      size="small"
-                      @click="removeApproverNode(index)"
-                      v-if="approverNodes.length > 1"
-                    >鍒犻櫎</el-button>
-                  </div>
-                </div>
-              </div>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="鐢宠浜猴細" prop="approveUser">
-							<el-select
-								v-model="form.approveUser"
-								placeholder="閫夋嫨浜哄憳"
-                filterable
-                default-first-option
-                :reserve-keyword="false"
-							>
-								<el-option
-									v-for="user in userList"
-									:key="user.userId"
-									:label="user.nickName"
-									:value="user.userId"
-								/>
-							</el-select>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="鐢宠鏃ユ湡锛�" prop="approveTime">
-              <el-date-picker
-                  v-model="form.approveTime"
-                  type="date"
-                  placeholder="璇烽�夋嫨鏃ユ湡"
-                  value-format="YYYY-MM-DD"
-                  format="YYYY-MM-DD"
-                  clearable
-                  style="width: 100%"
-              />
-            </el-form-item>
-          </el-col>
-        </el-row>
+
         <el-row :gutter="30">
           <el-col :span="24">
             <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
@@ -211,13 +136,10 @@
 import {
   delLedgerFile,
 } from "@/api/salesManagement/salesLedger.js";
-import {userListNoPageByTenantId} from "@/api/system/user.js";
 import { getToken } from "@/utils/auth";
 const { proxy } = getCurrentInstance()
 const emit = defineEmits(['close'])
 import useUserStore from "@/store/modules/user";
-import { getCurrentDate } from "@/utils/index.js";
-import log from "@/views/monitor/job/log.vue";
 const userStore = useUserStore();
 
 const dialogFormVisible = ref(false);
@@ -231,24 +153,19 @@
 });
 const data = reactive({
   form: {
-    approveTime: "",
     approveId: "",
-    approveUser: "",
-		approveDeptId: "",
+    approveDeptId: "",
     approveDeptName: "",
     approveReason: "",
     checkResult: "",
     tempFileIds: [],
-    approverList: [], // 鏂板瀛楁锛屽瓨鍌ㄦ墍鏈夎妭鐐圭殑瀹℃壒浜篿d
     startDate: "", // 璇峰亣寮�濮嬫椂闂�
     endDate: "", // 璇峰亣缁撴潫鏃堕棿
     price: null, // 鎶ラ攢閲戦
     location: "" // 鍑哄樊鍦扮偣
   },
   rules: {
-    approveTime: [{ required: false, message: "璇疯緭鍏�", trigger: "change" },],
     approveId: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
-    approveUser: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
     approveDeptName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     approveReason: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
     checkResult: [{ required: false, message: "璇疯緭鍏�", trigger: "blur" }],
@@ -268,18 +185,7 @@
   }
 })
 
-// 瀹℃壒浜鸿妭鐐圭浉鍏�
-const approverNodes = ref([
-  { id: 1, userId: null }
-])
-let nextApproverId = 2
-const userList = ref([])
-function addApproverNode() {
-  approverNodes.value.push({ id: nextApproverId++, userId: null })
-}
-function removeApproverNode(index) {
-  approverNodes.value.splice(index, 1)
-}
+
 // 澶勭悊閮ㄩ棬閫夋嫨鍙樺寲
 const handleDeptChange = (deptId) => {
   if (deptId) {
@@ -295,39 +201,19 @@
 const openDialog = (type, row) => {
   operationType.value = type;
   dialogFormVisible.value = true;
-	userListNoPageByTenantId().then((res) => {
-    userList.value = res.data;
-  });
-	form.value = {}
-	approverNodes.value = [
-		{ id: 1, userId: null }
-	]
-  form.value.approveUser = userStore.id;
-  form.value.approveTime = getCurrentDate();
-  
+  form.value = {}
+
   // 鑾峰彇褰撳墠鐢ㄦ埛淇℃伅骞惰缃儴闂↖D
   form.value.approveDeptId = userStore.currentDeptId
-  
+
   // 鍔犺浇閮ㄩ棬閫夐」锛屽苟鍦ㄥ姞杞藉畬鎴愬悗璁剧疆閮ㄩ棬鍚嶇О
   getProductOptions();
   if (operationType.value === 'edit') {
     fileList.value = row.commonFileList
     form.value.tempFileIds = fileList.value.map(file => file.id)
-		currentApproveStatus.value = row.approveStatus
+    currentApproveStatus.value = row.approveStatus
     approveProcessGetInfo({id: row.approveId,approveReason: '1'}).then(res => {
-			form.value = {...res.data}
-      // 鍙嶆樉瀹℃壒浜�
-      if (res.data && res.data.approveUserIds) {
-        const userIds = res.data.approveUserIds.split(',')
-        approverNodes.value = userIds.map((userId, idx) => ({
-          id: idx + 1, 
-          userId: parseInt(userId.trim())
-        }))
-        nextApproverId = userIds.length + 1
-      } else {
-        approverNodes.value = [{ id: 1, userId: null }]
-        nextApproverId = 2
-      }
+      form.value = {...res.data}
     })
   }
 }
@@ -362,15 +248,7 @@
 }
 // 鎻愪氦浜у搧琛ㄥ崟
 const submitForm = () => {
-  // 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿d
-  form.value.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
   form.value.approveType = props.approveType
-  // 瀹℃壒浜哄繀濉牎楠�
-  const hasEmptyApprover = approverNodes.value.some(node => !node.userId)
-  if (hasEmptyApprover) {
-    proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒")
-    return
-  }
   // 褰� approveType 涓� 2 鏃讹紝鏍¢獙璇峰亣鏃堕棿
   if (props.approveType == 2) {
     if (!form.value.startDate) {
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index 33bde47..deaf6db 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -1,67 +1,129 @@
 <template>
   <div class="app-container">
-    <!-- 鏍囩椤靛垏鎹笉鍚岀殑瀹℃壒绫诲瀷 -->
-    <el-tabs v-model="activeTab" @tab-change="handleTabChange" class="approval-tabs">
-      <el-tab-pane label="鍏嚭绠$悊" name="1"></el-tab-pane>
-      <el-tab-pane label="璇峰亣绠$悊" name="2"></el-tab-pane>
-      <el-tab-pane label="鍑哄樊绠$悊" name="3"></el-tab-pane>
-      <el-tab-pane label="鎶ラ攢绠$悊" name="4"></el-tab-pane>
-      <el-tab-pane label="閲囪喘瀹℃壒" name="5"></el-tab-pane>
-      <el-tab-pane label="鎶ヤ环瀹℃壒" name="6"></el-tab-pane>
-      <el-tab-pane label="鍙戣揣瀹℃壒" name="7"></el-tab-pane>
-    </el-tabs>
-    
-    <div class="search_form">
-      <div>
-        <span class="search_title">娴佺▼缂栧彿锛�</span>
-        <el-input
-            v-model="searchForm.approveId"
-            style="width: 240px"
-            placeholder="璇疯緭鍏ユ祦绋嬬紪鍙锋悳绱�"
-            @change="handleQuery"
-            clearable
-            :prefix-icon="Search"
-        />
-        <span class="search_title ml10">瀹℃壒鐘舵�侊細</span>
-				<el-select v-model="searchForm.approveStatus" clearable @change="handleQuery" style="width: 240px">
-					<el-option label="寰呭鏍�" :value="0" />
-					<el-option label="瀹℃牳涓�" :value="1" />
-					<el-option label="瀹℃牳瀹屾垚" :value="2" />
-					<el-option label="瀹℃牳鏈�氳繃" :value="3" />
-					<el-option label="宸查噸鏂版彁浜�" :value="4" />
-				</el-select>
-        <el-button type="primary" @click="handleQuery" style="margin-left: 10px"
-        >鎼滅储</el-button
-        >
-      </div>
-      <div>
-        <el-button
-          type="primary"
-          @click="openForm('add')"
-          v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7"
-        >鏂板</el-button>
-        <el-button @click="handleOut">瀵煎嚭</el-button>
-        <el-button
-          type="danger"
-          plain
-          @click="handleDelete"
-          v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7"
-        >鍒犻櫎</el-button>
+    <!-- 瀹℃壒绫诲瀷鍒囨崲 - 绱у噾鏍囩寮� -->
+    <div class="type-tabs">
+      <div
+        v-for="type in approveTypes"
+        :key="type.value"
+        class="type-tab"
+        :class="{ active: activeTab === type.value }"
+        @click="activeTab = type.value; handleTabChange()"
+      >
+        <el-icon :size="14" :style="{ color: activeTab === type.value ? type.color : '#909399' }">
+          <component :is="type.icon" />
+        </el-icon>
+        <span class="tab-name">{{ type.label }}</span>
       </div>
     </div>
-    <div class="table_list">
+
+    <!-- 鎼滅储鍜屾搷浣滃尯鍩� -->
+    <el-card class="search-card" shadow="never">
+      <div class="search-content">
+        <div class="search-filters">
+          <div class="filter-item">
+            <span class="filter-label">娴佺▼缂栧彿</span>
+            <el-input
+              v-model="searchForm.approveId"
+              placeholder="璇疯緭鍏ユ祦绋嬬紪鍙�"
+              clearable
+              :prefix-icon="Search"
+              @keyup.enter="handleQuery"
+              class="search-input"
+            />
+          </div>
+          <div class="filter-item">
+            <span class="filter-label">瀹℃壒鐘舵��</span>
+            <el-select 
+              v-model="searchForm.approveStatus" 
+              clearable 
+              @change="handleQuery"
+              placeholder="璇烽�夋嫨鐘舵��"
+              class="search-select"
+            >
+              <el-option label="寰呭鏍�" :value="0">
+                <el-tag size="small" type="warning">寰呭鏍�</el-tag>
+              </el-option>
+              <el-option label="瀹℃牳涓�" :value="1">
+                <el-tag size="small" type="primary">瀹℃牳涓�</el-tag>
+              </el-option>
+              <el-option label="瀹℃牳瀹屾垚" :value="2">
+                <el-tag size="small" type="success">瀹℃牳瀹屾垚</el-tag>
+              </el-option>
+              <el-option label="瀹℃牳鏈�氳繃" :value="3">
+                <el-tag size="small" type="danger">瀹℃牳鏈�氳繃</el-tag>
+              </el-option>
+              <el-option label="宸查噸鏂版彁浜�" :value="4">
+                <el-tag size="small" type="info">宸查噸鏂版彁浜�</el-tag>
+              </el-option>
+            </el-select>
+          </div>
+          <el-button type="primary" @click="handleQuery" class="search-btn">
+            <el-icon><Search /></el-icon>
+            鎼滅储
+          </el-button>
+          <el-button @click="resetQuery" class="reset-btn">
+            <el-icon><RefreshRight /></el-icon>
+            閲嶇疆
+          </el-button>
+        </div>
+        <div class="search-actions">
+          <el-button
+            type="primary"
+            @click="openForm('add')"
+            v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7 && currentApproveType !== 10"
+            class="action-btn primary"
+          >
+            <el-icon><Plus /></el-icon>
+            鏂板
+          </el-button>
+          <el-button @click="handleOut" class="action-btn">
+            <el-icon><Download /></el-icon>
+            瀵煎嚭
+          </el-button>
+          <el-button
+            type="danger"
+            plain
+            @click="handleDelete"
+            v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7 && currentApproveType !== 10"
+            class="action-btn danger"
+          >
+            <el-icon><Delete /></el-icon>
+            鍒犻櫎
+          </el-button>
+        </div>
+      </div>
+    </el-card>
+
+    <!-- 鏁版嵁琛ㄦ牸 -->
+    <el-card class="table-card" shadow="never" v-loading="tableLoading">
+      <template #header>
+        <div class="table-header">
+          <div class="table-title">
+            <div class="type-tag" :style="{ backgroundColor: currentTypeInfo.color }">
+              <el-icon color="#fff" :size="16"><component :is="currentTypeInfo.icon" /></el-icon>
+            </div>
+            <span>{{ currentTypeInfo.label }}鍒楄〃</span>
+            <el-tag type="info" size="small" effect="plain" class="count-tag">
+              鍏� {{ page.total }} 鏉�
+            </el-tag>
+          </div>
+        </div>
+      </template>
       <PIMTable
-          rowKey="id"
-          :column="tableColumnCopy"
-          :tableData="tableData"
-          :page="page"
-          :isSelection="true"
-          @selection-change="handleSelectionChange"
-          :tableLoading="tableLoading"
-          @pagination="pagination"
-          :total="page.total"
+        rowKey="id"
+        :column="tableColumnCopy"
+        :tableData="tableData"
+        :page="page"
+        :isSelection="true"
+        @selection-change="handleSelectionChange"
+        :tableLoading="tableLoading"
+        @pagination="pagination"
+        :total="page.total"
+        class="custom-table"
       ></PIMTable>
-    </div>
+    </el-card>
+
+    <!-- 寮圭獥缁勪欢 -->
     <info-form-dia ref="infoFormDia" @close="handleQuery" :approveType="currentApproveType"></info-form-dia>
     <approval-dia ref="approvalDia" @close="handleQuery" :approveType="currentApproveType"></approval-dia>
     <FileList ref="fileListRef" />
@@ -70,7 +132,7 @@
 
 <script setup>
 import FileList from "./fileList.vue";
-import { Search } from "@element-plus/icons-vue";
+import { Search, Plus, Delete, Download, RefreshRight, DocumentChecked } from "@element-plus/icons-vue";
 import {onMounted, ref, computed, reactive, toRefs, nextTick, getCurrentInstance} from "vue";
 import {ElMessageBox} from "element-plus";
 import { useRoute } from 'vue-router';
@@ -85,13 +147,38 @@
 // 褰撳墠閫変腑鐨勬爣绛鹃〉锛岄粯璁や负鍏嚭绠$悊
 const activeTab = ref('1');
 
+// 鍚勭被鍨嬫暟閲忕粺璁�
+const typeCounts = ref({});
+
+// 瀹℃壒绫诲瀷閰嶇疆
+const approveTypes = [
+  { value: '1', label: '鍏嚭绠$悊', icon: 'Suitcase', color: '#409EFF' },
+  { value: '2', label: '璇峰亣绠$悊', icon: 'Calendar', color: '#67C23A' },
+  { value: '3', label: '鍑哄樊绠$悊', icon: 'Location', color: '#E6A23C' },
+  { value: '4', label: '鎶ラ攢绠$悊', icon: 'Money', color: '#F56C6C' },
+  { value: '5', label: '閲囪喘瀹℃壒', icon: 'ShoppingCart', color: '#909399' },
+  { value: '6', label: '鎶ヤ环瀹℃壒', icon: 'DocumentChecked', color: '#9B59B6' },
+  { value: '7', label: '鍙戣揣瀹℃壒', icon: 'Van', color: '#1ABC9C' },
+  { value: '10', label: '閿�鍞鎵�', icon: 'Sell', color: '#FF6B6B' },
+];
+
+// 褰撳墠瀹℃壒绫诲瀷淇℃伅
+const currentTypeInfo = computed(() => {
+  return approveTypes.find(t => t.value === activeTab.value) || approveTypes[0];
+});
+
+// 鑾峰彇绫诲瀷鏁伴噺
+const getTypeCount = (value) => {
+  return typeCounts.value[value] || 0;
+};
+
 // 褰撳墠瀹℃壒绫诲瀷锛屾牴鎹�変腑鐨勬爣绛鹃〉璁$畻
 const currentApproveType = computed(() => {
   return Number(activeTab.value);
 });
 
 // 鏍囩椤靛垏鎹㈠鐞�
-const handleTabChange = (tabName) => {
+const handleTabChange = () => {
   // 鍒囨崲鏍囩椤垫椂閲嶇疆鎼滅储鏉′欢鍜屽垎椤碉紝骞堕噸鏂板姞杞芥暟鎹�
   searchForm.value.approveId = '';
   searchForm.value.approveStatus = '';
@@ -102,11 +189,18 @@
 
 const data = reactive({
   searchForm: {
-		approveId: "",
-		approveStatus: "",
+    approveId: "",
+    approveStatus: "",
   },
 });
 const { searchForm } = toRefs(data);
+
+// 閲嶇疆鎼滅储
+const resetQuery = () => {
+  searchForm.value.approveId = '';
+  searchForm.value.approveStatus = '';
+  handleQuery();
+};
 
 // 鍔ㄦ�佽〃鏍煎垪閰嶇疆锛屾牴鎹鎵圭被鍨嬬敓鎴愬垪
 const tableColumnCopy = computed(() => {
@@ -114,6 +208,7 @@
   const isReimburseType = currentApproveType.value === 4; // 鎶ラ攢绠$悊
   const isQuotationType = currentApproveType.value === 6; // 鎶ヤ环瀹℃壒
   const isPurchaseType = currentApproveType.value === 5; // 閲囪喘瀹℃壒
+  const isSalesType = currentApproveType.value === 10; // 閿�鍞鎵�
   
   // 鍩虹鍒楅厤缃�
   const baseColumns = [
@@ -212,6 +307,7 @@
         currentApproveType.value === 5 ||
         currentApproveType.value === 6 ||
         currentApproveType.value === 7 ||
+        currentApproveType.value === 10 ||
         row.approveStatus == 2 ||
         row.approveStatus == 1 ||
         row.approveStatus == 4
@@ -238,7 +334,7 @@
     },
   ];
 
-  // 鎶ヤ环瀹℃壒锛堢被鍨� 6锛変笉灞曠ず鈥滈檮浠垛�濇搷浣�
+  // 鎶ヤ环瀹℃壒锛堢被鍨� 6锛変笉灞曠ず"闄勪欢"鎿嶄綔
   if (!isQuotationType) {
     actionOperations.push({
       name: "闄勪欢",
@@ -294,6 +390,8 @@
     tableLoading.value = false;
     tableData.value = res.data.records
     page.total = res.data.total;
+    // 鏇存柊褰撳墠绫诲瀷鏁伴噺
+    typeCounts.value[activeTab.value] = res.data.total;
   }).catch(err => {
     tableLoading.value = false;
   })
@@ -310,6 +408,7 @@
     5: "/approveProcess/exportFive",
     6: "/approveProcess/exportSix",
     7: "/approveProcess/exportSeven",
+    10: "/approveProcess/exportTen",
   }
   const url = urlMap[type] || urlMap[0]
   const nameMap = {
@@ -321,6 +420,7 @@
     5: "閲囪喘鐢宠瀹℃壒琛�",
     6: "鎶ヤ环瀹℃壒琛�",
     7: "鍙戣揣瀹℃壒琛�",
+    10: "閿�鍞鎵硅〃",
   }
   const fileName = nameMap[type] || nameMap[0]
   proxy.download(url, {}, `${fileName}.xlsx`)
@@ -388,7 +488,256 @@
 </script>
 
 <style scoped>
-.approval-tabs {
-  margin-bottom: 10px;
+.page-header {
+  margin-bottom: 20px;
+}
+
+.header-title {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+}
+
+.title-icon {
+  font-size: 28px;
+  color: var(--el-color-primary, #409EFF);
+}
+
+.header-text {
+  display: flex;
+  flex-direction: column;
+  gap: 4px;
+}
+
+.main-title {
+  font-size: 20px;
+  font-weight: 600;
+  color: var(--el-text-color-primary, #303133);
+}
+
+.sub-title {
+  font-size: 13px;
+  color: var(--el-text-color-secondary, #909399);
+}
+
+/* 瀹℃壒绫诲瀷鍒囨崲 - 绱у噾鏍囩寮� */
+.type-tabs {
+  display: flex;
+  gap: 4px;
+  margin-bottom: 16px;
+  padding: 4px;
+  background: var(--el-fill-color-light, #f5f7fa);
+  border-radius: 8px;
+  overflow-x: auto;
+}
+
+.type-tab {
+  display: flex;
+  align-items: center;
+  gap: 6px;
+  padding: 8px 14px;
+  border-radius: 6px;
+  cursor: pointer;
+  transition: all 0.2s ease;
+  white-space: nowrap;
+  font-size: 13px;
+  color: var(--el-text-color-regular, #606266);
+}
+
+.type-tab:hover {
+  background: var(--el-color-primary-light-9, rgba(64, 158, 255, 0.1));
+  color: var(--el-color-primary, #409EFF);
+}
+
+.type-tab.active {
+  background: var(--el-bg-color, #fff);
+  color: var(--el-color-primary, #409EFF);
+  font-weight: 600;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+}
+
+.tab-name {
+  font-size: 13px;
+}
+
+.tab-count {
+  min-width: 16px;
+  height: 16px;
+  padding: 0 5px;
+  background: var(--el-color-success, #67C23A);
+  color: #fff;
+  border-radius: 8px;
+  font-size: 11px;
+  font-weight: 600;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+/* 鎼滅储鍗$墖 */
+.search-card {
+  margin-bottom: 16px;
+  border-radius: 12px;
+}
+
+:deep(.el-card__body) {
+  padding: 20px;
+}
+
+.search-content {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-wrap: wrap;
+  gap: 16px;
+}
+
+.search-filters {
+  display: flex;
+  align-items: center;
+  gap: 16px;
+  flex-wrap: wrap;
+}
+
+.filter-item {
+  display: flex;
+  align-items: center;
+  gap: 8px;
+}
+
+.filter-label {
+  font-size: 14px;
+  color: var(--el-text-color-regular, #606266);
+  font-weight: 500;
+  white-space: nowrap;
+}
+
+.search-input,
+.search-select {
+  width: 200px;
+}
+
+.search-btn {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.reset-btn {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.search-actions {
+  display: flex;
+  gap: 10px;
+}
+
+.action-btn {
+  display: flex;
+  align-items: center;
+  gap: 4px;
+}
+
+.action-btn.primary {
+  background: var(--el-color-primary, #409EFF);
+  border: none;
+}
+
+.action-btn.danger {
+  transition: all 0.3s;
+}
+
+.action-btn.danger:hover {
+  background: #f56c6c;
+  color: #fff;
+}
+
+/* 琛ㄦ牸鍗$墖 */
+.table-card {
+  border-radius: 12px;
+}
+
+:deep(.el-card__header) {
+  padding: 16px 20px;
+  border-bottom: 1px solid var(--el-border-color-light, #ebeef5);
+}
+
+.table-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+
+.table-title {
+  display: flex;
+  align-items: center;
+  gap: 12px;
+  font-size: 16px;
+  font-weight: 600;
+  color: var(--el-text-color-primary, #303133);
+}
+
+.type-tag {
+  width: 32px;
+  height: 32px;
+  border-radius: 8px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+}
+
+.count-tag {
+  margin-left: 8px;
+}
+
+.custom-table {
+  margin-top: 8px;
+}
+
+/* 鍝嶅簲寮� */
+@media (max-width: 1200px) {
+  .search-content {
+    flex-direction: column;
+    align-items: stretch;
+  }
+
+  .search-filters {
+    justify-content: flex-start;
+  }
+
+  .search-actions {
+    justify-content: flex-end;
+  }
+}
+
+@media (max-width: 768px) {
+  .type-tabs {
+    padding: 3px;
+  }
+
+  .type-tab {
+    padding: 6px 10px;
+    font-size: 12px;
+  }
+
+  .tab-name {
+    font-size: 12px;
+  }
+
+  .search-filters {
+    flex-direction: column;
+    align-items: stretch;
+  }
+
+  .filter-item {
+    width: 100%;
+  }
+
+  .search-input,
+  .search-select {
+    width: 100%;
+  }
 }
 </style>
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 8a293fc..8e06d8b 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -298,50 +298,6 @@
             </el-form-item>
           </el-col>
         </el-row>
-        <el-row :gutter="30">
-          <el-col :span="24">
-            <el-form-item>
-              <template #label>
-                <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;">
-                  <span>瀹℃壒浜洪�夋嫨锛�</span>
-                  <el-button type="primary" size="small" @click="addApproverNode" icon="Plus">鏂板鑺傜偣</el-button>
-                </div>
-              </template>
-              <div class="approver-nodes-container">
-                <div
-                  v-for="(node, index) in approverNodes"
-                  :key="node.id"
-                  class="approver-node-item"
-                >
-                  <div class="approver-node-header">
-                    <span class="approver-node-label">瀹℃壒鑺傜偣 {{ index + 1 }}</span>
-                    <el-button
-                      v-if="approverNodes.length > 1"
-                      type="danger"
-                      size="small"
-                      text
-                      @click="removeApproverNode(index)"
-                      icon="Delete"
-                    >鍒犻櫎</el-button>
-                  </div>
-                  <el-select
-                    v-model="node.userId"
-                    placeholder="璇烽�夋嫨瀹℃壒浜�"
-                    filterable
-                    style="width: 100%;"
-                  >
-                    <el-option
-                      v-for="user in userList"
-                      :key="user.userId"
-                      :label="user.nickName"
-                      :value="user.userId"
-                    />
-                  </el-select>
-                </div>
-              </div>
-            </el-form-item>
-          </el-col>
-        </el-row>
         <el-row>
           <el-form-item label="浜у搧淇℃伅锛�"
                         prop="entryDate">
@@ -760,16 +716,6 @@
 
   const userStore = useUserStore();
 
-  // 瀹℃壒浜鸿妭鐐癸紙浠块攢鍞彴璐﹀彂璐у鎵逛汉锛�
-  const approverNodes = ref([{ id: 1, userId: null }]);
-  let nextApproverId = 2;
-  const addApproverNode = () => {
-    approverNodes.value.push({ id: nextApproverId++, userId: null });
-  };
-  const removeApproverNode = (index) => {
-    approverNodes.value.splice(index, 1);
-  };
-
   // 璁㈠崟瀹℃壒鐘舵�佹樉绀烘枃鏈�
   const approvalStatusText = {
     1: "寰呭鏍�",
@@ -1121,19 +1067,12 @@
     }
 
     try {
-      // 鑾峰彇瀹℃壒浜篒D瀛楃涓�
-      const approveUserIds = approverNodes.value
-        .filter(node => node.userId)
-        .map(node => node.userId)
-        .join(",");
-      
       let params = {
         productData: proxy.HaveJson(productData.value),
         supplierId: form.value.supplierId,
         paymentMethod: form.value.paymentMethod,
         recorderId: form.value.recorderId,
         projectName: form.value.projectName,
-        approveUserIds: approveUserIds,
         templateName: templateName.value.trim(),
       };
       console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value);
@@ -1284,9 +1223,6 @@
     templateName.value = "";
     filterInputValue.value = "";
     isTemplateNameDuplicate.value = false;
-    // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
-    approverNodes.value = [{ id: 1, userId: null }];
-    nextApproverId = 2;
     try {
       // 骞惰鍔犺浇鍩虹鏁版嵁
       const [userRes, salesRes, supplierRes] = await Promise.all([
@@ -1325,15 +1261,6 @@
           form.value = { ...purchaseRes };
           productData.value = purchaseRes.productData || [];
           fileList.value = purchaseRes.salesLedgerFiles || [];
-          // 濡傛灉缂栬緫鏃舵湁瀹℃壒浜猴紝瑙f瀽瀹℃壒浜篒D瀛楃涓插苟璁剧疆鍒拌妭鐐逛腑
-          if (purchaseRes.approveUserIds) {
-            const approverIds = purchaseRes.approveUserIds.split(",");
-            approverNodes.value = approverIds.map((id, index) => ({
-              id: index + 1,
-              userId: Number(id)
-            }));
-            nextApproverId = approverIds.length + 1;
-          }
         } catch (error) {
           console.error("鍔犺浇閲囪喘鍙拌处鏁版嵁澶辫触:", error);
           proxy.$modal.msgError("鍔犺浇鏁版嵁澶辫触");
@@ -1402,14 +1329,6 @@
   const submitForm = () => {
     proxy.$refs["formRef"].validate(valid => {
       if (valid) {
-        // 瀹℃壒浜哄繀濉牎楠岋紙鎵�鏈夎妭鐐归兘瑕侀�変汉锛�
-        const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
-        if (hasEmptyApprover) {
-          proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
-          return;
-        }
-        const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
-        
         if (productData.value.length > 0) {
           // 鏂板鏃讹紝闇�瑕佷粠姣忎釜浜у搧瀵硅薄涓垹闄� id 瀛楁
           let processedProductData = productData.value;
@@ -1430,7 +1349,6 @@
         }
         form.value.tempFileIds = tempFileIds;
         form.value.type = 2;
-        form.value.approveUserIds = approveUserIds;
 
         // 濡傛灉salesLedgerId涓虹┖锛屽垯涓嶄紶閫抯alesContractNo
         if (!form.value.salesLedgerId) {
@@ -1454,9 +1372,6 @@
   // 鍏抽棴寮规
   const closeDia = () => {
     proxy.resetForm("formRef");
-    // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
-    approverNodes.value = [{ id: 1, userId: null }];
-    nextApproverId = 2;
     dialogFormVisible.value = false;
   };
   // 鎵撳紑浜у搧寮规
diff --git a/src/views/productionManagement/processRoute/Edit.vue b/src/views/productionManagement/processRoute/Edit.vue
index 0c0fe0f..f84719b 100644
--- a/src/views/productionManagement/processRoute/Edit.vue
+++ b/src/views/productionManagement/processRoute/Edit.vue
@@ -3,7 +3,7 @@
     <el-dialog
         v-model="isShow"
         title="缂栬緫宸ヨ壓璺嚎"
-        width="400"
+        width="800"
         @close="closeModal"
     >
       <el-form label-width="140px" :model="formState" label-position="top" ref="formRef">
@@ -25,35 +25,54 @@
           </el-button>
         </el-form-item>
 
-        <el-form-item
-            label="BOM"
-            prop="bomId"
-            :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨BOM',
-                trigger: 'change',
-              }
-            ]"
-        >
-          <el-select
-              v-model="formState.bomId"
-              placeholder="璇烽�夋嫨BOM"
-              clearable
-              :disabled="!formState.productModelId || bomOptions.length === 0"
-              style="width: 100%"
-          >
-            <el-option
-                v-for="item in bomOptions"
-                :key="item.id"
-                :label="item.bomNo || `BOM-${item.id}`"
-                :value="item.id"
-            />
-          </el-select>
-        </el-form-item>
-
         <el-form-item label="澶囨敞" prop="description">
           <el-input v-model="formState.description" type="textarea" />
+        </el-form-item>
+
+        <!-- 宸ュ簭閰嶇疆 -->
+        <el-form-item label="宸ュ簭閰嶇疆" required>
+          <el-table :data="formState.processRouteItemList" border size="small" style="width: 100%">
+            <el-table-column label="閮ㄤ欢" min-width="200">
+              <template #default="{ row }">
+                <el-select
+                    v-model="row.processId"
+                    placeholder="璇烽�夋嫨閮ㄤ欢"
+                    clearable
+                    filterable
+                    style="width: 100%"
+                >
+                  <el-option
+                      v-for="process in processOptions"
+                      :key="process.id"
+                      :label="formatProcessOptionLabel(process)"
+                      :value="process.id"
+                  />
+                </el-select>
+              </template>
+            </el-table-column>
+            <el-table-column label="璐ㄦ" width="80" align="center">
+              <template #default="{ row }">
+                <el-switch v-model="row.isQuality" :active-value="true" inactive-value="false"/>
+              </template>
+            </el-table-column>
+            <el-table-column label="澶囨敞" min-width="150">
+              <template #default="{ row }">
+                <el-input v-model="row.remark" placeholder="璇疯緭鍏ュ娉�" size="small"/>
+              </template>
+            </el-table-column>
+            <el-table-column label="鎿嶄綔" width="60" align="center">
+              <template #default="{ $index }">
+                <el-button type="danger" link size="small" @click="removeProcessItem($index)">
+                  <el-icon><Delete /></el-icon>
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+          <div style="margin-top: 8px;">
+            <el-button type="primary" link size="small" @click="addProcessItem">
+              <el-icon><Plus /></el-icon> 娣诲姞宸ュ簭
+            </el-button>
+          </div>
         </el-form-item>
       </el-form>
       
@@ -76,7 +95,7 @@
 <script setup>
 import {ref, computed, getCurrentInstance, onMounted, nextTick, watch} from "vue";
 import {update} from "@/api/productionManagement/processRoute.js";
-import {getByModel} from "@/api/productionManagement/productBom.js";
+import {processList} from "@/api/productionManagement/productionProcess.js";
 import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
 
 const props = defineProps({
@@ -99,8 +118,8 @@
   productModelId: undefined,
   productName: "",
   productModelName: "",
-  bomId: undefined,
   description: '',
+  processRouteItemList: [],
 });
 
 const isShow = computed({
@@ -113,9 +132,49 @@
 });
 
 const showProductSelectDialog = ref(false);
-const bomOptions = ref([]);
+const processOptions = ref([]);
 
 let { proxy } = getCurrentInstance()
+
+// 鑾峰彇宸ュ簭鍒楄〃
+const getProcessOptions = async () => {
+  try {
+    const res = await processList();
+    processOptions.value = res.data || [];
+  } catch (error) {
+    console.error("鑾峰彇宸ュ簭鍒楄〃澶辫触", error);
+    processOptions.value = [];
+  }
+};
+
+// 鏍煎紡鍖栧伐搴忛�夐」鏍囩
+const formatProcessOptionLabel = (process) => {
+  if (!process) return '';
+  const typeMap = {
+    1: '鍔犲伐',
+    2: '鍒澘鍐疯姱鍒朵綔',
+    3: '绠¤矾缁勫',
+    4: '缃愪綋杩炴帴鍙婅皟璇�',
+    5: '娴嬭瘯鎵撳帇',
+    6: '鍏朵粬',
+  };
+  const typeText = typeMap[process.type] || '';
+  return `${process.name} ${process.no ? '(' + process.no + ')' : ''} ${typeText ? '[' + typeText + ']' : ''}`;
+};
+
+// 娣诲姞宸ュ簭
+const addProcessItem = () => {
+  formState.value.processRouteItemList.push({
+    processId: undefined,
+    isQuality: false,
+    remark: '',
+  });
+};
+
+// 绉婚櫎宸ュ簭
+const removeProcessItem = (index) => {
+  formState.value.processRouteItemList.splice(index, 1);
+};
 
 const closeModal = () => {
   isShow.value = false;
@@ -131,90 +190,42 @@
       productName: props.record.productName || "",
       // 娉ㄦ剰锛歳ecord涓殑瀛楁鏄痬odel锛岄渶瑕佹槧灏勫埌productModelName
       productModelName: props.record.model || props.record.productModelName || "",
-      bomId: props.record.bomId,
       description: props.record.description || '',
+      processRouteItemList: props.record.processRouteItemList || [],
     };
-    // 濡傛灉鏈変骇鍝佸瀷鍙稩D锛屽姞杞紹OM鍒楄〃
-    if (props.record.productModelId) {
-      loadBomList(props.record.productModelId);
-    }
   }
 }
-
-// 鍔犺浇BOM鍒楄〃
-const loadBomList = async (productModelId) => {
-  if (!productModelId) {
-    bomOptions.value = [];
-    return;
-  }
-  try {
-    const res = await getByModel(productModelId);
-    // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
-    let bomList = [];
-    if (Array.isArray(res)) {
-      bomList = res;
-    } else if (res && res.data) {
-      bomList = Array.isArray(res.data) ? res.data : [res.data];
-    } else if (res && typeof res === 'object') {
-      bomList = [res];
-    }
-    bomOptions.value = bomList;
-  } catch (error) {
-    console.error("鍔犺浇BOM鍒楄〃澶辫触锛�", error);
-    bomOptions.value = [];
-  }
-};
 
 // 浜у搧閫夋嫨澶勭悊
 const handleProductSelect = async (products) => {
   if (products && products.length > 0) {
     const product = products[0];
-    // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
-    try {
-      const res = await getByModel(product.id);
-      // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
-      let bomList = [];
-      if (Array.isArray(res)) {
-        bomList = res;
-      } else if (res && res.data) {
-        bomList = Array.isArray(res.data) ? res.data : [res.data];
-      } else if (res && typeof res === 'object') {
-        bomList = [res];
-      }
-      
-      if (bomList.length > 0) {
-        formState.value.productModelId = product.id;
-        formState.value.productName = product.productName;
-        formState.value.productModelName = product.model;
-        // 濡傛灉褰撳墠閫夋嫨鐨凚OM涓嶅湪鏂板垪琛ㄤ腑锛屽垯閲嶇疆BOM閫夋嫨
-        const currentBomExists = bomList.some(bom => bom.id === formState.value.bomId);
-        if (!currentBomExists) {
-          formState.value.bomId = undefined;
-        }
-        bomOptions.value = bomList;
-        showProductSelectDialog.value = false;
-        // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
-        proxy.$refs["formRef"]?.validateField('productModelId');
-      } else {
-        proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
-      }
-    } catch (error) {
-      // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
-      proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
-    }
+    formState.value.productModelId = product.id;
+    formState.value.productName = product.productName;
+    formState.value.productModelName = product.model;
+    showProductSelectDialog.value = false;
+    // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+    proxy.$refs["formRef"]?.validateField('productModelId');
   }
 };
 
 const handleSubmit = () => {
   proxy.$refs["formRef"].validate(valid => {
     if (valid) {
-      // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
+      // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝�
       if (!formState.value.productModelId) {
         proxy.$modal.msgError("璇烽�夋嫨浜у搧");
         return;
       }
-      if (!formState.value.bomId) {
-        proxy.$modal.msgError("璇烽�夋嫨BOM");
+      // 楠岃瘉鏄惁閰嶇疆浜嗗伐搴�
+      if (!formState.value.processRouteItemList || formState.value.processRouteItemList.length === 0) {
+        proxy.$modal.msgError("璇疯嚦灏戦厤缃竴涓伐搴�");
+        return;
+      }
+      // 楠岃瘉鎵�鏈夊伐搴忔槸鍚﹂�夋嫨浜嗛儴浠�
+      const invalidItem = formState.value.processRouteItemList.find(item => !item.processId);
+      if (invalidItem) {
+        proxy.$modal.msgError("璇烽�夋嫨鎵�鏈夊伐搴忕殑閮ㄤ欢");
         return;
       }
       update(formState.value).then(res => {
@@ -245,6 +256,7 @@
 }, { immediate: true });
 
 onMounted(() => {
+  getProcessOptions();
   if (props.visible && props.record) {
     setFormData();
   }
diff --git a/src/views/productionManagement/processRoute/New.vue b/src/views/productionManagement/processRoute/New.vue
index 62c6873..f9893a1 100644
--- a/src/views/productionManagement/processRoute/New.vue
+++ b/src/views/productionManagement/processRoute/New.vue
@@ -25,33 +25,6 @@
           </el-button>
         </el-form-item>
 
-        <el-form-item
-            label="BOM"
-            prop="bomId"
-            :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨BOM',
-                trigger: 'change',
-              }
-            ]"
-        >
-          <el-select
-              v-model="formState.bomId"
-              placeholder="璇烽�夋嫨BOM"
-              clearable
-              :disabled="!formState.productModelId || bomOptions.length === 0"
-              style="width: 100%"
-          >
-            <el-option
-                v-for="item in bomOptions"
-                :key="item.id"
-                :label="item.bomNo || `BOM-${item.id}`"
-                :value="item.id"
-            />
-          </el-select>
-        </el-form-item>
-
         <el-form-item label="澶囨敞" prop="description">
           <el-input v-model="formState.description" type="textarea" />
         </el-form-item>
@@ -76,7 +49,6 @@
 <script setup>
 import {ref, computed, getCurrentInstance} from "vue";
 import {add} from "@/api/productionManagement/processRoute.js";
-import {getByModel} from "@/api/productionManagement/productBom.js";
 import ProductSelectDialog from "@/views/basicData/product/ProductSelectDialog.vue";
 
 const props = defineProps({
@@ -94,7 +66,6 @@
   productModelId: undefined,
   productName: "",
   productModelName: "",
-  bomId: undefined,
   description: '',
 });
 
@@ -108,7 +79,6 @@
 });
 
 const showProductSelectDialog = ref(false);
-const bomOptions = ref([]);
 
 let { proxy } = getCurrentInstance()
 
@@ -119,10 +89,8 @@
     productModelId: undefined,
     productName: "",
     productModelName: "",
-    bomId: undefined,
     description: '',
   };
-  bomOptions.value = [];
   isShow.value = false;
 };
 
@@ -130,48 +98,21 @@
 const handleProductSelect = async (products) => {
   if (products && products.length > 0) {
     const product = products[0];
-    // 鍏堟煡璇OM鍒楄〃锛堝繀閫夛級
-    try {
-      const res = await getByModel(product.id);
-      // 澶勭悊杩斿洖鐨凚OM鏁版嵁锛氬彲鑳芥槸鏁扮粍銆佸璞℃垨鍖呭惈data瀛楁
-      let bomList = [];
-      if (Array.isArray(res)) {
-        bomList = res;
-      } else if (res && res.data) {
-        bomList = Array.isArray(res.data) ? res.data : [res.data];
-      } else if (res && typeof res === 'object') {
-        bomList = [res];
-      }
-      
-      if (bomList.length > 0) {
-        formState.value.productModelId = product.id;
-        formState.value.productName = product.productName;
-        formState.value.productModelName = product.model;
-        formState.value.bomId = undefined; // 閲嶇疆BOM閫夋嫨
-        bomOptions.value = bomList;
-        showProductSelectDialog.value = false;
-        // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
-        proxy.$refs["formRef"]?.validateField('productModelId');
-      } else {
-        proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
-      }
-    } catch (error) {
-      // 濡傛灉鎺ュ彛杩斿洖404鎴栧叾浠栭敊璇紝璇存槑娌℃湁BOM
-      proxy.$modal.msgError("璇ヤ骇鍝佹病鏈塀OM锛岃鍏堝垱寤築OM");
-    }
+    formState.value.productModelId = product.id;
+    formState.value.productName = product.productName;
+    formState.value.productModelName = product.model;
+    showProductSelectDialog.value = false;
+    // 瑙﹀彂琛ㄥ崟楠岃瘉鏇存柊
+    proxy.$refs["formRef"]?.validateField('productModelId');
   }
 };
 
 const handleSubmit = () => {
   proxy.$refs["formRef"].validate(valid => {
     if (valid) {
-      // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝佸拰BOM
+      // 楠岃瘉鏄惁閫夋嫨浜嗕骇鍝�
       if (!formState.value.productModelId) {
         proxy.$modal.msgError("璇烽�夋嫨浜у搧");
-        return;
-      }
-      if (!formState.value.bomId) {
-        proxy.$modal.msgError("璇烽�夋嫨BOM");
         return;
       }
       add(formState.value).then(res => {
@@ -185,10 +126,11 @@
   })
 };
 
-
 defineExpose({
   closeModal,
   handleSubmit,
   isShow,
 });
 </script>
+
+
diff --git a/src/views/productionManagement/processRoute/processRouteItem/index.vue b/src/views/productionManagement/processRoute/processRouteItem/index.vue
index c2c24b4..398403a 100644
--- a/src/views/productionManagement/processRoute/processRouteItem/index.vue
+++ b/src/views/productionManagement/processRoute/processRouteItem/index.vue
@@ -50,7 +50,7 @@
     
     <!-- 琛ㄦ牸瑙嗗浘 -->
     <div v-if="viewMode === 'table'" class="section-header">
-      <div class="section-title">浜у搧閮ㄤ欢鍒楄〃</div>
+      <div class="section-title">宸ュ簭鍒楄〃</div>
       <div class="section-actions">
         <el-button 
             icon="Grid" 
@@ -74,14 +74,9 @@
         class="lims-table"
     >
       <el-table-column align="center" label="搴忓彿" width="60" type="index" />
-      <el-table-column label="浜у搧鍚嶇О" prop="name" min-width="140" show-overflow-tooltip>
+      <el-table-column label="閮ㄤ欢鍚嶇О" prop="name" min-width="140" show-overflow-tooltip>
         <template #default="scope">
           {{ getProcessField(scope.row, 'name') }}
-        </template>
-      </el-table-column>
-      <el-table-column label="浜у搧瑙勬牸" prop="productModel" min-width="120" show-overflow-tooltip>
-        <template #default="scope">
-          {{ getProcessField(scope.row, 'productModel') }}
         </template>
       </el-table-column>
       <el-table-column label="閮ㄤ欢缂栧彿" prop="no" width="120" show-overflow-tooltip>
@@ -92,6 +87,16 @@
       <el-table-column label="閮ㄤ欢绫诲瀷" prop="typeText" width="120" show-overflow-tooltip>
         <template #default="scope">
           {{ getProcessTypeText(getProcessRaw(scope.row)?.type) || '-' }}
+        </template>
+      </el-table-column>
+      <el-table-column label="浜у搧鍚嶇О" prop="productName" min-width="140" show-overflow-tooltip>
+        <template #default="scope">
+          {{ scope.row.productName || getProcessField(scope.row, 'productName') }}
+        </template>
+      </el-table-column>
+      <el-table-column label="浜у搧瑙勬牸" prop="productModel" min-width="120" show-overflow-tooltip>
+        <template #default="scope">
+          {{ scope.row.model || getProcessField(scope.row, 'productModel') }}
         </template>
       </el-table-column>
       <el-table-column label="璁″垝宸ユ椂(灏忔椂)" prop="salaryQuota" width="130" align="center">
@@ -130,7 +135,7 @@
     <!-- 鍗$墖瑙嗗浘 -->
     <template v-else>
       <div class="section-header">
-        <div class="section-title">宸ヨ壓璺嚎椤圭洰鍒楄〃</div>
+        <div class="section-title">宸ュ簭鍒楄〃</div>
         <div class="section-actions">
           <el-button 
               icon="Menu" 
@@ -162,7 +167,8 @@
           <!-- 涓庡伐搴忎富琛ㄤ竴鑷寸殑绠�瑕佷俊鎭� -->
           <div class="card-content">
             <div class="product-info">
-              <div class="product-name">{{ getProcessField(item, 'productModel') }}</div>
+              <div class="product-name">{{ item.productName || getProcessField(item, 'productName') }}</div>
+              <div class="product-model">{{ item.model || getProcessField(item, 'productModel') }}</div>
               <div v-if="getProcessRaw(item)?.no" class="product-model">缂栧彿 {{ getProcessRaw(item)?.no }}</div>
               <div v-if="getProcessTypeText(getProcessRaw(item)?.type)" class="product-model">
                 {{ getProcessTypeText(getProcessRaw(item)?.type) }}
@@ -184,7 +190,7 @@
     <!-- 鏂板/缂栬緫寮圭獥锛堝竷灞�銆佸瓧娈典笌宸ュ簭/閮ㄤ欢椤� New銆丒dit 涓�鑷达紱鎻愪氦鍙傛暟浠嶄负鍘熸帴鍙e瓧娈碉級 -->
     <el-dialog
         v-model="dialogVisible"
-        :title="operationType === 'add' ? '鏂板宸ヨ壓璺嚎椤圭洰' : '缂栬緫宸ヨ壓璺嚎椤圭洰'"
+        :title="operationType === 'add' ? '鏂板宸ュ簭' : '缂栬緫宸ュ簭'"
         width="760"
         @close="closeDialog"
     >
@@ -322,7 +328,7 @@
 const submitLoading = ref(false);
 const cardsContainer = ref(null);
 const tableRef = ref(null);
-const viewMode = ref('table'); // table | card
+const viewMode = ref('card'); // table | card
 const routeInfo = ref({
   processRouteCode: '',
   productName: '',
diff --git a/src/views/productionManagement/productionOrder/New.vue b/src/views/productionManagement/productionOrder/New.vue
index c6b1a2c..656d017 100644
--- a/src/views/productionManagement/productionOrder/New.vue
+++ b/src/views/productionManagement/productionOrder/New.vue
@@ -37,7 +37,7 @@
           <el-input v-model="formState.unit"  disabled />
         </el-form-item>
 
-        <!-- <el-form-item label="宸ヨ壓璺嚎">
+        <el-form-item label="宸ヨ壓璺嚎">
           <el-select v-model="formState.routeId"
                      placeholder="璇烽�夋嫨宸ヨ壓璺嚎"
                      style="width: 100%;"
@@ -47,7 +47,7 @@
                        :label="`${item.processRouteCode || ''}`"
                        :value="item.id" />
           </el-select>
-        </el-form-item> -->
+        </el-form-item>
 
         <el-form-item
             label="闇�姹傛暟閲�"
diff --git a/src/views/productionManagement/productionProcess/Edit.vue b/src/views/productionManagement/productionProcess/Edit.vue
index b3ccddc..38a6665 100644
--- a/src/views/productionManagement/productionProcess/Edit.vue
+++ b/src/views/productionManagement/productionProcess/Edit.vue
@@ -10,53 +10,21 @@
         <el-row :gutter="16">
           <el-col :span="12">
             <el-form-item
-            label="浜у搧鍚嶇О锛�"
-            prop="productId"
+            label="閮ㄤ欢鍚嶇О"
+            prop="name"
             :rules="[
                 {
                 required: true,
-                message: '璇烽�夋嫨浜у搧鍚嶇О',
-              },
-            ]">
-              <el-tree-select
-            v-model="formState.productId"
-            placeholder="璇烽�夋嫨浜у搧鍚嶇О"
-            clearable
-            filterable
-            check-strictly
-            :data="productCategoryOptions"
-            :render-after-expand="false"
-            style="width: 100%"
-            @change="handleProductChange"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item
-            label="浜у搧瑙勬牸锛�"
-            prop="productModelId"
-            :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨浜у搧瑙勬牸',
-              },
-            ]">
-              <el-select v-model="formState.productModelId"
-                     placeholder="璇烽�夋嫨浜у搧瑙勬牸"
-                     clearable
-                     filterable
-                     :disabled="!formState.productId"
-                     style="width: 100%">
-                <el-option v-for="item in modelOptions"
-                       :key="item.id"
-                       :label="item.model"
-                       :value="item.id" />
-              </el-select>
+                message: '璇疯緭鍏ラ儴浠跺悕绉�',
+              }
+            ]"
+            >
+              <el-input v-model="formState.name" placeholder="璇疯緭鍏ラ儴浠跺悕绉�" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="閮ㄤ欢缂栧彿" prop="no">
-              <el-input v-model="formState.no"  />
+              <el-input v-model="formState.no" placeholder="璇疯緭鍏ラ儴浠剁紪鍙�" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -111,6 +79,25 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
+            <el-form-item label="璁″垝鎵ц浜哄憳" prop="executorId">
+              <el-select
+            v-model="formState.executorId"
+            placeholder="璇烽�夋嫨璁″垝鎵ц浜哄憳"
+            clearable
+            filterable
+            style="width: 100%"
+            @change="handleExecutorChange"
+              >
+                <el-option
+              v-for="item in plannerOptions"
+              :key="item.userId"
+              :label="item.nickName"
+              :value="item.userId"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
             <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
               <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
             </el-form-item>
@@ -135,7 +122,6 @@
 <script setup>
 import { ref, computed, getCurrentInstance, watch, onMounted } from "vue";
 import {update} from "@/api/productionManagement/productionProcess.js";
-import { modelListPage, productTreeList } from "@/api/basicData/product";
 import { userListNoPageByTenantId } from "@/api/system/user.js";
 
 const props = defineProps({
@@ -156,18 +142,16 @@
 const formState = ref({
   id: props.record.id,
   name: props.record.name,
-  productId: props.record.productId,
-  productModelId: props.record.productModelId,
   type: props.record.type,
   no: props.record.no,
   remark: props.record.remark,
   salaryQuota: props.record.salaryQuota,
   plannerId: props.record.plannerId,
   plannerName: props.record.plannerName,
+  executorId: props.record.executorId,
+  executorName: props.record.executorName,
   isQuality: props.record.isQuality,
 });
-const productCategoryOptions = ref([]);
-const modelOptions = ref([]);
 const plannerOptions = ref([]);
 
 const isShow = computed({
@@ -185,14 +169,14 @@
     formState.value = {
       id: newRecord.id,
       name: newRecord.name || '',
-      productId: newRecord.productId,
-      productModelId: getRecordProductModelId(newRecord),
-      no: newRecord.no || '',
       type: newRecord.type,
+      no: newRecord.no || '',
       remark: newRecord.remark || '',
       salaryQuota: newRecord.salaryQuota || '',
       plannerId: newRecord.plannerId,
       plannerName: newRecord.plannerName || '',
+      executorId: newRecord.executorId,
+      executorName: newRecord.executorName || '',
       isQuality: props.record.isQuality,
     };
   }
@@ -204,17 +188,16 @@
     formState.value = {
       id: props.record.id,
       name: props.record.name || '',
-      productId: props.record.productId,
-      productModelId: getRecordProductModelId(props.record),
-      no: props.record.no || '',
       type: props.record.type,
+      no: props.record.no || '',
       remark: props.record.remark || '',
       salaryQuota: props.record.salaryQuota || '',
       plannerId: props.record.plannerId,
       plannerName: props.record.plannerName || '',
+      executorId: props.record.executorId,
+      executorName: props.record.executorName || '',
       isQuality: props.record.isQuality,
     };
-    getModelOptions(formState.value.productId);
   }
 });
 
@@ -231,105 +214,6 @@
     return;
   }
   callback();
-};
-
-const convertProductTree = list => {
-  return (list || []).map(item => {
-    const children = convertProductTree(item.children || item.childList || []);
-    return {
-      ...item,
-      value: item.id,
-      label: item.name || item.label,
-      children,
-      disabled: children.length > 0,
-    };
-  });
-};
-
-const findNodeById = (nodes, targetId) => {
-  for (const node of nodes || []) {
-    if (String(node.value) === String(targetId)) {
-      return node;
-    }
-    if (node.children && node.children.length > 0) {
-      const found = findNodeById(node.children, targetId);
-      if (found) return found;
-    }
-  }
-  return null;
-};
-
-const findNodeIdByLabel = (nodes, targetLabel) => {
-  for (const node of nodes || []) {
-    if (node.label === targetLabel) {
-      return node.value;
-    }
-    if (node.children && node.children.length > 0) {
-      const found = findNodeIdByLabel(node.children, targetLabel);
-      if (found !== null && found !== undefined) return found;
-    }
-  }
-  return undefined;
-};
-
-function findModelIdByName(models, modelName) {
-  if (!modelName) {
-    return undefined;
-  }
-  const matched = (models || []).find(item => String(item.model) === String(modelName));
-  return matched?.id;
-}
-
-function getRecordProductModelId(record) {
-  if (!record) {
-    return undefined;
-  }
-  return record.productModelId ?? record.modelId ?? record.specificationModelId ?? undefined;
-}
-
-function syncProductModelIdFromModelName() {
-  if (formState.value.productModelId || modelOptions.value.length === 0) {
-    return;
-  }
-  const modelName = props.record?.productModel || props.record?.model || props.record?.specificationModel || "";
-  const matchedId = findModelIdByName(modelOptions.value, modelName);
-  if (matchedId !== undefined) {
-    formState.value.productModelId = matchedId;
-  }
-}
-
-const getProductCategoryOptions = async () => {
-  try {
-    const res = await productTreeList();
-    const list = Array.isArray(res) ? res : res?.data || [];
-    productCategoryOptions.value = convertProductTree(list);
-    if (!formState.value.productId && formState.value.name) {
-      formState.value.productId = findNodeIdByLabel(productCategoryOptions.value, formState.value.name);
-    }
-    await getModelOptions(formState.value.productId);
-    syncProductModelIdFromModelName();
-  } catch (e) {
-    productCategoryOptions.value = [];
-  }
-};
-
-const getModelOptions = async productId => {
-  if (!productId) {
-    modelOptions.value = [];
-    return;
-  }
-  try {
-    const res = await modelListPage({
-      id: productId,
-      current: 1,
-      size: 999,
-    });
-    const records = res?.records || res?.data?.records || [];
-    modelOptions.value = records;
-    syncProductModelIdFromModelName();
-  } catch (e) {
-    modelOptions.value = [];
-  }
 };
 
 const getPlannerOptions = async () => {
@@ -350,11 +234,9 @@
   formState.value.plannerName = selectedUser?.nickName || '';
 };
 
-const handleProductChange = async value => {
-  const selectedNode = findNodeById(productCategoryOptions.value, value);
-  formState.value.name = selectedNode?.label || '';
-  formState.value.productModelId = undefined;
-  await getModelOptions(value);
+const handleExecutorChange = value => {
+  const selectedUser = plannerOptions.value.find(item => String(item.userId) === String(value));
+  formState.value.executorName = selectedUser?.nickName || '';
 };
 
 const closeModal = () => {
@@ -376,7 +258,6 @@
 };
 
 onMounted(() => {
-  getProductCategoryOptions();
   getPlannerOptions();
 });
 
diff --git a/src/views/productionManagement/productionProcess/New.vue b/src/views/productionManagement/productionProcess/New.vue
index 250e229..8b57f23 100644
--- a/src/views/productionManagement/productionProcess/New.vue
+++ b/src/views/productionManagement/productionProcess/New.vue
@@ -10,53 +10,21 @@
         <el-row :gutter="16">
           <el-col :span="12">
             <el-form-item
-            label="浜у搧鍚嶇О锛�"
-            prop="productId"
+            label="閮ㄤ欢鍚嶇О"
+            prop="name"
             :rules="[
                 {
                 required: true,
-                message: '璇烽�夋嫨浜у搧鍚嶇О',
-              },
-            ]">
-              <el-tree-select
-            v-model="formState.productId"
-            placeholder="璇烽�夋嫨浜у搧鍚嶇О"
-            clearable
-            filterable
-            check-strictly
-            :data="productCategoryOptions"
-            :render-after-expand="false"
-            style="width: 100%"
-            @change="handleProductChange"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item
-            label="浜у搧瑙勬牸锛�"
-            prop="productModelId"
-            :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨浜у搧瑙勬牸',
-              },
-            ]">
-              <el-select v-model="formState.productModelId"
-                     placeholder="璇烽�夋嫨浜у搧瑙勬牸"
-                     clearable
-                     filterable
-                     :disabled="!formState.productId"
-                     style="width: 100%">
-                <el-option v-for="item in modelOptions"
-                       :key="item.id"
-                       :label="item.model"
-                       :value="item.id" />
-              </el-select>
+                message: '璇疯緭鍏ラ儴浠跺悕绉�',
+              }
+            ]"
+            >
+              <el-input v-model="formState.name" placeholder="璇疯緭鍏ラ儴浠跺悕绉�" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
             <el-form-item label="閮ㄤ欢缂栧彿" prop="no">
-              <el-input v-model="formState.no"  />
+              <el-input v-model="formState.no" placeholder="璇疯緭鍏ラ儴浠剁紪鍙�" />
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -113,6 +81,25 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
+            <el-form-item label="璁″垝鎵ц浜哄憳" prop="executorId">
+              <el-select
+            v-model="formState.executorId"
+            placeholder="璇烽�夋嫨璁″垝鎵ц浜哄憳"
+            clearable
+            filterable
+            style="width: 100%"
+            @change="handleExecutorChange"
+              >
+                <el-option
+              v-for="item in plannerOptions"
+              :key="item.userId"
+              :label="item.nickName"
+              :value="item.userId"
+                />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
             <el-form-item label="鏄惁璐ㄦ" prop="isQuality">
               <el-switch v-model="formState.isQuality" :active-value="true" inactive-value="false"/>
             </el-form-item>
@@ -137,7 +124,6 @@
 <script setup>
 import { ref, computed, getCurrentInstance, onMounted } from "vue";
 import {add} from "@/api/productionManagement/productionProcess.js";
-import { modelListPage, productTreeList } from "@/api/basicData/product";
 import { userListNoPageByTenantId } from "@/api/system/user.js";
 
 const props = defineProps({
@@ -152,17 +138,15 @@
 // 鍝嶅簲寮忔暟鎹紙鏇夸唬閫夐」寮忕殑 data锛�
 const formState = ref({
   name: '',
-  productId: undefined,
-  productModelId: undefined,
   type: undefined,
   remark: '',
   salaryQuota:  '',
   plannerId: undefined,
   plannerName: '',
+  executorId: undefined,
+  executorName: '',
   isQuality: false,
 });
-const productCategoryOptions = ref([]);
-const modelOptions = ref([]);
 const plannerOptions = ref([]);
 
 const isShow = computed({
@@ -189,60 +173,6 @@
   callback();
 };
 
-const convertProductTree = list => {
-  return (list || []).map(item => {
-    const children = convertProductTree(item.children || item.childList || []);
-    return {
-      ...item,
-      value: item.id,
-      label: item.name || item.label,
-      children,
-      disabled: children.length > 0,
-    };
-  });
-};
-
-const findNodeById = (nodes, targetId) => {
-  for (const node of nodes || []) {
-    if (String(node.value) === String(targetId)) {
-      return node;
-    }
-    if (node.children && node.children.length > 0) {
-      const found = findNodeById(node.children, targetId);
-      if (found) return found;
-    }
-  }
-  return null;
-};
-
-const getProductCategoryOptions = async () => {
-  try {
-    const res = await productTreeList();
-    const list = Array.isArray(res) ? res : res?.data || [];
-    productCategoryOptions.value = convertProductTree(list);
-  } catch (e) {
-    productCategoryOptions.value = [];
-  }
-};
-
-const getModelOptions = async productId => {
-  if (!productId) {
-    modelOptions.value = [];
-    return;
-  }
-  try {
-    const res = await modelListPage({
-      id: productId,
-      current: 1,
-      size: 999,
-    });
-    const records = res?.records || res?.data?.records || [];
-    modelOptions.value = records;
-  } catch (e) {
-    modelOptions.value = [];
-  }
-};
-
 const getPlannerOptions = async () => {
   try {
     const res = await userListNoPageByTenantId();
@@ -257,11 +187,9 @@
   formState.value.plannerName = selectedUser?.nickName || '';
 };
 
-const handleProductChange = async value => {
-  const selectedNode = findNodeById(productCategoryOptions.value, value);
-  formState.value.name = selectedNode?.label || '';
-  formState.value.productModelId = undefined;
-  await getModelOptions(value);
+const handleExecutorChange = value => {
+  const selectedUser = plannerOptions.value.find(item => String(item.userId) === String(value));
+  formState.value.executorName = selectedUser?.nickName || '';
 };
 
 const closeModal = () => {
@@ -283,7 +211,6 @@
 };
 
 onMounted(() => {
-  getProductCategoryOptions();
   getPlannerOptions();
 });
 
diff --git a/src/views/productionManagement/productionProcess/index.vue b/src/views/productionManagement/productionProcess/index.vue
index 92530e5..e4347e3 100644
--- a/src/views/productionManagement/productionProcess/index.vue
+++ b/src/views/productionManagement/productionProcess/index.vue
@@ -115,14 +115,9 @@
   });
   const { searchForm } = toRefs(data);
   const tableColumn = ref([
-
     {
-      label: "浜у搧鍚嶇О",
+      label: "閮ㄤ欢鍚嶇О",
       prop: "name",
-    },
-    {
-      label: "浜у搧瑙勬牸",
-      prop: "productModel",
     },
     {
       label: "閮ㄤ欢缂栧彿",
@@ -141,6 +136,10 @@
       prop: "plannerName",
     },
     {
+      label: "璁″垝鎵ц浜哄憳",
+      prop: "executorName",
+    },
+    {
       label: "鏄惁璐ㄦ",
       prop: "isQuality",
       formatData: (params) => {
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index fa191a0..930b0e8 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -595,50 +595,6 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
-
-        <!-- 瀹℃壒浜洪�夋嫨锛堜豢鍗忓悓瀹℃壒閲岀殑瀹℃壒浜鸿妭鐐归�夋嫨锛� -->
-        <el-row>
-          <el-col :span="24">
-            <el-form-item>
-              <template #label>
-                <span>瀹℃壒浜洪�夋嫨锛�</span>
-                <el-button type="primary" @click="addApproverNode" style="margin-left: 8px;">鏂板鑺傜偣</el-button>
-              </template>
-              <div style="display: flex; align-items: flex-end; flex-wrap: wrap;">
-                <div
-                  v-for="(node, index) in approverNodes"
-                  :key="node.id"
-                  style="margin-right: 20px; text-align: center; margin-bottom: 10px;"
-                >
-                  <div>
-                    <span>瀹℃壒浜�</span>
-                    鈫�
-                  </div>
-                  <el-select
-                    v-model="node.userId"
-                    placeholder="閫夋嫨浜哄憳"
-                    filterable
-                    style="width: 140px; margin-bottom: 8px;"
-                  >
-                    <el-option
-                      v-for="user in userList"
-                      :key="user.userId"
-                      :label="user.nickName"
-                      :value="user.userId"
-                    />
-                  </el-select>
-                  <div>
-                    <el-button
-                      type="danger"
-                      @click="removeApproverNode(index)"
-                      v-if="approverNodes.length > 1"
-                    >鍒犻櫎</el-button>
-                  </div>
-                </div>
-              </div>
-            </el-form-item>
-          </el-col>
-        </el-row>
 			</el-form>
 			<template #footer>
 				<div class="dialog-footer">
@@ -809,16 +765,6 @@
   },
 });
 const { deliveryForm, deliveryRules } = toRefs(deliveryFormData);
-
-// 鍙戣揣瀹℃壒浜鸿妭鐐癸紙浠垮崗鍚屽鎵� infoFormDia.vue锛�
-const approverNodes = ref([{ id: 1, userId: null }]);
-let nextApproverId = 2;
-const addApproverNode = () => {
-  approverNodes.value.push({ id: nextApproverId++, userId: null });
-};
-const removeApproverNode = (index) => {
-  approverNodes.value.splice(index, 1);
-};
 
 // 瀵煎叆鐩稿叧
 const importUploadRef = ref(null);
@@ -2115,9 +2061,6 @@
   deliveryForm.value = {
     type: "璐ц溅",
   };
-  // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
-  approverNodes.value = [{ id: 1, userId: null }];
-  nextApproverId = 2;
 	deliveryFormVisible.value = true;
 };
 
@@ -2125,13 +2068,6 @@
 const submitDelivery = () => {
   proxy.$refs["deliveryFormRef"].validate((valid) => {
     if (valid) {
-      // 瀹℃壒浜哄繀濉牎楠岋紙鎵�鏈夎妭鐐归兘瑕侀�変汉锛�
-      const hasEmptyApprover = approverNodes.value.some(node => !node.userId);
-      if (hasEmptyApprover) {
-        proxy.$modal.msgError("璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒");
-        return;
-      }
-      const approveUserIds = approverNodes.value.map(node => node.userId).join(",");
       // 淇濆瓨褰撳墠灞曞紑鐨勮ID锛屼互渚垮彂璐у悗閲嶆柊鍔犺浇瀛愯〃鏍兼暟鎹�
       const currentExpandedKeys = [...expandedRowKeys.value];
       const salesLedgerId = currentDeliveryRow.value.salesLedgerId;
@@ -2139,7 +2075,6 @@
         salesLedgerId: salesLedgerId,
         salesLedgerProductId: currentDeliveryRow.value.id,
         type: deliveryForm.value.type,
-				approveUserIds,
       })
         .then(() => {
           proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
index 2a094a8..be59964 100644
--- a/src/views/salesManagement/salesQuotation/index.vue
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -173,69 +173,6 @@
             </div>
           </el-card>
 
-          <!-- 瀹℃壒浜轰俊鎭� -->
-          <el-card class="form-card" shadow="hover">
-            <template #header>
-              <div class="card-header-wrapper">
-                <el-icon class="card-icon">
-                  <UserFilled/>
-                </el-icon>
-                <span class="card-title">瀹℃壒浜洪�夋嫨</span>
-                <el-button type="primary" size="small" @click="addApproverNode" class="header-btn">
-                  <el-icon>
-                    <Plus/>
-                  </el-icon>
-                  鏂板鑺傜偣
-                </el-button>
-              </div>
-            </template>
-            <div class="form-content">
-              <el-row>
-                <el-col :span="24">
-                  <el-form-item>
-                    <div class="approver-nodes-container">
-                      <div
-                          v-for="(node, index) in approverNodes"
-                          :key="node.id"
-                          class="approver-node-item"
-                      >
-                        <div class="approver-node-label">
-                          <span class="node-step">{{ index + 1 }}</span>
-                          <span class="node-text">瀹℃壒浜�</span>
-                          <el-icon class="arrow-icon">
-                            <ArrowRight/>
-                          </el-icon>
-                        </div>
-                        <el-select
-                            v-model="node.userId"
-                            placeholder="閫夋嫨浜哄憳"
-                            class="approver-select"
-                            clearable
-                        >
-                          <el-option
-                              v-for="user in userList"
-                              :key="user.userId"
-                              :label="user.nickName"
-                              :value="user.userId"
-                          />
-                        </el-select>
-                        <el-button
-                            type="danger"
-                            size="small"
-                            :icon="Delete"
-                            @click="removeApproverNode(index)"
-                            v-if="approverNodes.length > 1"
-                            class="remove-btn"
-                        >鍒犻櫎
-                        </el-button>
-                      </div>
-                    </div>
-                  </el-form-item>
-                </el-col>
-              </el-row>
-            </div>
-          </el-card>
-
           <!-- 浜у搧淇℃伅 -->
           <el-card class="form-card" shadow="hover">
             <template #header>
@@ -345,68 +282,6 @@
     <FormDialog v-model="importDialogVisible" title="瀵煎叆鎶ヤ环鍗�" width="85%" :close-on-click-modal="false"
                 @close="importDialogVisible = false" @confirm="handleImportSubmit"
                 @cancel="importDialogVisible = false">
-      <!-- 瀹℃壒浜轰俊鎭� -->
-      <el-card class="form-card" shadow="hover">
-        <template #header>
-          <div class="card-header-wrapper">
-            <el-icon class="card-icon">
-              <UserFilled/>
-            </el-icon>
-            <span class="card-title">瀹℃壒浜洪�夋嫨</span>
-            <el-button type="primary" size="small" @click="addImportApproverNode" class="header-btn">
-              <el-icon>
-                <Plus/>
-              </el-icon>
-              鏂板鑺傜偣
-            </el-button>
-          </div>
-        </template>
-        <div class="form-content">
-          <el-row>
-            <el-col :span="24">
-              <el-form-item>
-                <div class="approver-nodes-container">
-                  <div
-                      v-for="(node, index) in importApproverNodes"
-                      :key="node.id"
-                      class="approver-node-item"
-                  >
-                    <div class="approver-node-label">
-                      <span class="node-step">{{ index + 1 }}</span>
-                      <span class="node-text">瀹℃壒浜�</span>
-                      <el-icon class="arrow-icon">
-                        <ArrowRight/>
-                      </el-icon>
-                    </div>
-                    <el-select
-                        v-model="node.userId"
-                        placeholder="閫夋嫨浜哄憳"
-                        class="approver-select"
-                        clearable
-                    >
-                      <el-option
-                          v-for="user in userList"
-                          :key="user.userId"
-                          :label="user.nickName"
-                          :value="user.userId"
-                      />
-                    </el-select>
-                    <el-button
-                        type="danger"
-                        size="small"
-                        :icon="Delete"
-                        @click="removeImportApproverNode(index)"
-                        v-if="importApproverNodes.length > 1"
-                        class="remove-btn"
-                    >鍒犻櫎
-                    </el-button>
-                  </div>
-                </div>
-              </el-form-item>
-            </el-col>
-          </el-row>
-        </div>
-      </el-card>
       <el-card class="form-card" shadow="hover">
         <template #header>
           <div class="card-header-wrapper">
@@ -546,10 +421,6 @@
 const importDialogVisible = ref(false)
 const viewDialogVisible = ref(false)
 const importFileList = ref([])
-const importApproverNodes = ref([
-  {id: 1, userId: null}
-])
-let nextImportApproverId = 2
 
 const fileUpload = ref(null)
 
@@ -599,36 +470,11 @@
 const userList = ref([]);
 const customerOption = ref([]);
 
-// 瀹℃壒浜鸿妭鐐圭浉鍏�
-const approverNodes = ref([
-  {id: 1, userId: null}
-])
-let nextApproverId = 2
-
 const isEdit = ref(false)
 const showDetail = ref(false)
 const editId = ref(null)
 const currentQuotation = ref({})
 const formRef = ref()
-
-// 娣诲姞瀹℃壒浜鸿妭鐐�
-function addApproverNode() {
-  approverNodes.value.push({id: nextApproverId++, userId: null})
-}
-
-// 鍒犻櫎瀹℃壒浜鸿妭鐐�
-function removeApproverNode(index) {
-  approverNodes.value.splice(index, 1)
-}
-
-// 瀵煎叆寮圭獥瀹℃壒浜鸿妭鐐圭浉鍏�
-function addImportApproverNode() {
-  importApproverNodes.value.push({id: nextImportApproverId++, userId: null})
-}
-
-function removeImportApproverNode(index) {
-  importApproverNodes.value.splice(index, 1)
-}
 
 function triggerRemoveImportFile(file) {
   const index = importFileList.value.indexOf(file)
@@ -643,12 +489,6 @@
     return
   }
 
-  const hasEmptyApprover = importApproverNodes.value.some(node => !node.userId)
-  if (hasEmptyApprover) {
-    ElMessage.error('璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒')
-    return
-  }
-
   const selectedFile = importFileList.value[0]
   const rawFile = selectedFile?.raw || selectedFile
   if (!validateImportFile(rawFile)) {
@@ -657,10 +497,6 @@
 
   const formData = new FormData()
   formData.append('file', rawFile)
-
-  // 瀹℃牳浜� IDs锛屼互閫楀彿鍒嗗壊
-  const approveUserIds = importApproverNodes.value.map(node => node.userId).join(',')
-  formData.append('approveUserIdsJson', approveUserIds)
 
   loading.value = true
   try {
@@ -767,10 +603,6 @@
 const handleImport = async () => {
   importFileList.value = []
 
-  // 鉁� 娓呯┖鈥滃鍏ョ敤鈥濈殑瀹℃壒浜�
-  importApproverNodes.value = [{id: 1, userId: null}]
-  nextImportApproverId = 2
-
   let userLists = await userListNoPage();
   importDialogVisible.value = true
 
@@ -785,9 +617,6 @@
   dialogTitle.value = '鏂板鎶ヤ环'
   isEdit.value = false
   resetForm()
-  // 閲嶇疆瀹℃壒浜鸿妭鐐�
-  approverNodes.value = [{id: 1, userId: null}]
-  nextApproverId = 2
   dialogVisible.value = true
   let userLists = await userListNoPage();
   // 鍙鍒堕渶瑕佺殑瀛楁锛岄伩鍏嶅皢缁勪欢寮曠敤鏀惧叆鍝嶅簲寮忓璞�
@@ -992,19 +821,6 @@
   form.discountAmount = row.discountAmount || 0
   form.totalAmount = row.totalAmount || 0
 
-  // 鍙嶆樉瀹℃壒浜�
-  if (row.approveUserIds) {
-    const userIds = row.approveUserIds.split(',')
-    approverNodes.value = userIds.map((userId, idx) => ({
-      id: idx + 1,
-      userId: parseInt(userId.trim())
-    }))
-    nextApproverId = userIds.length + 1
-  } else {
-    approverNodes.value = [{id: 1, userId: null}]
-    nextApproverId = 2
-  }
-
   // 鍔犺浇鐢ㄦ埛鍒楄〃
   let userLists = await userListNoPage();
   userList.value = (userLists.data || []).map(item => ({
@@ -1103,16 +919,6 @@
         return
       }
 
-      // 瀹℃壒浜哄繀濉牎楠�
-      const hasEmptyApprover = approverNodes.value.some(node => !node.userId)
-      if (hasEmptyApprover) {
-        ElMessage.error('璇蜂负鎵�鏈夊鎵硅妭鐐归�夋嫨瀹℃壒浜猴紒')
-        return
-      }
-
-      // 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿d
-      form.approveUserIds = approverNodes.value.map(node => node.userId).join(',')
-
       // 璁$畻鎵�鏈変骇鍝佺殑鍗曚环鎬诲拰
       form.totalAmount = form.products.reduce((sum, product) => {
         const price = Number(product.unitPrice) || 0
@@ -1177,8 +983,6 @@
         validDate: item.validDate || '',
         paymentMethod: item.paymentMethod || '',
         status: item.status || '鑽夌',
-        // 瀹℃壒浜猴紙鐢ㄤ簬缂栬緫鏃跺弽鏄撅級
-        approveUserIds: item.approveUserIds || '',
         remark: item.remark || '',
         products: item.products ? item.products.map(product => ({
           productId: product.productId || '',

--
Gitblit v1.9.3