From da004bc93d20874eee8ccd33fd3b246674a4531f Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期五, 27 三月 2026 10:54:52 +0800
Subject: [PATCH] 工艺路线绑定

---
 src/api/salesManagement/salesLedger.js                                             |   17 ++++
 src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue |   95 ++++++++++++++---------
 src/views/salesManagement/salesLedger/index.vue                                    |   98 ++++++++++++++++--------
 3 files changed, 141 insertions(+), 69 deletions(-)

diff --git a/src/api/salesManagement/salesLedger.js b/src/api/salesManagement/salesLedger.js
index 0eb54a1..7ded652 100644
--- a/src/api/salesManagement/salesLedger.js
+++ b/src/api/salesManagement/salesLedger.js
@@ -151,4 +151,21 @@
     url: `/salesLedgerProductProcess/delete/${id}`,
     method: "delete",
   });
+}
+
+// 閿�鍞彴璐�-缁戝畾宸ヨ壓璺嚎
+export function saleProcessBind(data) {
+  return request({
+    url: "/sales/ledger/saleProcessBind",
+    method: "post",
+    data,
+  });
+}
+
+// 閿�鍞彴璐�-鏌ヨ璁㈠崟宸茬粦瀹氬伐鑹鸿矾绾�
+export function getSaleProcessBindInfo(salesLedgerId) {
+  return request({
+    url: `/sales/ledger/salesProcess/${salesLedgerId}`,
+    method: "get",
+  });
 }
\ No newline at end of file
diff --git a/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue b/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
index 1dc7e25..f3c33b5 100644
--- a/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
+++ b/src/views/salesManagement/salesLedger/components/ProcessFlowConfigSelectDialog.vue
@@ -7,33 +7,37 @@
     @close="handleClose"
   >
     <el-row :gutter="20">
-      <el-col :span="10">
+      <el-col :span="24">
         <div style="font-weight: 600; margin-bottom: 8px;">閰嶇疆</div>
+        <div style="font-size: 12px; margin-bottom: 8px;">
+          <span v-if="boundRouteName" style="color: #67c23a;">宸茬粦瀹氾細{{ boundRouteName }}</span>
+          <span v-else style="color: #e6a23c;">鏈粦瀹�</span>
+        </div>
         <el-select
-          v-model="selectedConfigId"
+          v-model="selectedRouteId"
           filterable
           clearable
-          placeholder="璇烽�夋嫨宸ヨ壓璺嚎閰嶇疆"
+          placeholder="璇烽�夋嫨宸ヨ壓璺嚎"
           style="width: 100%;"
-          @change="handleConfigChange"
+          @change="handleRouteChange"
         >
           <el-option
-            v-for="cfg in configList"
-            :key="cfg.configId"
-            :label="cfg.configName"
-            :value="cfg.configId"
+            v-for="cfg in routeList"
+            :key="cfg.routeId"
+            :label="cfg.processRouteName"
+            :value="cfg.routeId"
           />
         </el-select>
 
         <el-divider style="margin: 16px 0;" />
 
         <div style="font-weight: 600; margin-bottom: 8px;">姝ラ棰勮</div>
-        <div style="font-size: 12px; color: #909399; margin-bottom: 6px;">
+        <div style="font-size: 12px; color: #909399; margin-bottom: 10px;">
           鏍规嵁鎵�閫夐厤缃睍绀烘祦绋嬪浘
         </div>
       </el-col>
 
-      <el-col :span="14">
+      <el-col :span="24">
         <div class="process-diagram">
           <div v-if="steps.length === 0" class="process-diagram-empty">鏆傛棤姝ラ</div>
           <div
@@ -48,7 +52,7 @@
             <div v-if="idx < steps.length - 1" class="process-diagram-arrow">鈫�</div>
           </div>
         </div>
-        <div v-if="selectedConfigId === null" style="margin-top: 10px; font-size: 12px; color: #909399;">
+        <div v-if="selectedRouteId === null" style="margin-top: 10px; font-size: 12px; color: #909399;">
           璇峰厛閫夋嫨涓�鏉″凡缁存姢濂界殑宸ヨ壓璺嚎
         </div>
       </el-col>
@@ -67,13 +71,16 @@
 
 <script setup>
 import { computed, getCurrentInstance, ref, watch } from "vue";
-import { salesProcessFlowConfigList, salesProcessFlowConfigGetById } from "@/api/salesManagement/salesProcessFlowConfig.js";
+import { salesProcessFlowConfigList, salesProcessFlowConfigItemList } from "@/api/salesManagement/salesProcessFlowConfig.js";
 
 const emit = defineEmits(["update:visible", "confirm"]);
 
 const props = defineProps({
   visible: { type: Boolean, default: false },
-  defaultConfigId: { type: [Number, String, null], default: null },
+  // 鎵撳紑寮圭獥鏃剁殑鍥炴樉锛氳嫢涓氬姟宸茬粦瀹氬伐鑹鸿矾绾垮垯浼犲叆璇� routeId锛涘惁鍒欓粯璁ゅ睍绀哄垪琛ㄧ涓�鏉�
+  defaultRouteId: { type: [Number, String, null], default: null },
+  // 椤甸潰鎻愮ず锛氳鍗曞凡缁戝畾鐨勫伐鑹鸿矾绾垮悕绉�
+  boundRouteName: { type: String, default: "" },
 });
 
 const { proxy } = getCurrentInstance();
@@ -87,8 +94,8 @@
   },
 });
 
-const configList = ref([]);
-const selectedConfigId = ref(null);
+const routeList = ref([]);
+const selectedRouteId = ref(null);
 const steps = ref([]);
 const saving = ref(false);
 
@@ -102,26 +109,30 @@
   }));
 };
 
-const fetchConfigList = async () => {
-  const res = await salesProcessFlowConfigList();
-  const list = res?.data ?? res?.records ?? res ?? [];
-  configList.value = Array.isArray(list) ? list : [];
+const normalizeRouteList = (list) => {
+  if (!Array.isArray(list)) return [];
+  return list.map((r) => ({
+    routeId: r.routeId ?? r.id ?? null,
+    processRouteName: r.processRouteName ?? r.routeName ?? r.name ?? "",
+    isDefault: Boolean(r.isDefault),
+  }));
 };
 
-const fetchConfigDetail = async (id) => {
-  if (!id) {
+const fetchRouteList = async () => {
+  // 閫夋嫨寮圭獥锛氬敖閲忎竴娆℃�ф媺鍏紝閬垮厤鍒嗛〉褰卞搷閫夋嫨浣撻獙
+  const res = await salesProcessFlowConfigList({ current: 1, size: 1000 });
+  const records = res?.records ?? res?.data?.records ?? res?.data ?? res ?? [];
+  routeList.value = normalizeRouteList(records).filter((r) => r.routeId !== null && r.routeId !== undefined && r.routeId !== "");
+};
+
+const fetchRouteSteps = async (routeId) => {
+  if (!routeId) {
     steps.value = [];
     return;
   }
-  const res = await salesProcessFlowConfigGetById(id);
-  const detail = res?.data ?? res ?? {};
-  steps.value = normalizeStepsFromApi(detail?.steps ?? []);
-};
-
-const initDefault = async () => {
-  await fetchConfigList();
-  selectedConfigId.value = props.defaultConfigId ?? null;
-  await fetchConfigDetail(selectedConfigId.value);
+  const res = await salesProcessFlowConfigItemList(routeId);
+  const raw = res?.data ?? res ?? [];
+  steps.value = normalizeStepsFromApi(raw);
 };
 
 watch(
@@ -129,7 +140,18 @@
   async (v) => {
     if (v) {
       try {
-        await initDefault();
+        await fetchRouteList();
+
+        // 鍥炴樉缁戝畾锛�
+        // 1. 鑻ヤ紶鍏� defaultRouteId锛屽垯浼樺厛浣跨敤瀹�
+        // 2. 鍚﹀垯浼樺厛閫変腑鏍囪涓洪粯璁�(isDefault=true)鐨勫伐鑹鸿矾绾�
+        // 3. 鑻ラ兘娌℃湁锛屽垯鍥為��涓虹涓�鏉�
+        const first = routeList.value?.[0] ?? null;
+        const defaultRoute =
+          routeList.value.find((r) => r.isDefault) ?? first;
+        const desired = props.defaultRouteId ?? (defaultRoute ? defaultRoute.routeId : null);
+        selectedRouteId.value = desired ?? null;
+        await fetchRouteSteps(selectedRouteId.value);
       } catch {
         proxy?.$modal?.msgError?.("鑾峰彇宸ヨ壓璺嚎閰嶇疆澶辫触");
       }
@@ -137,8 +159,8 @@
   }
 );
 
-const handleConfigChange = async () => {
-  await fetchConfigDetail(selectedConfigId.value);
+const handleRouteChange = async () => {
+  await fetchRouteSteps(selectedRouteId.value);
 };
 
 const handleClose = () => {
@@ -148,14 +170,13 @@
 
 const confirmSelect = async () => {
   if (saving.value) return;
-  if (selectedConfigId.value === null || selectedConfigId.value === undefined || selectedConfigId.value === "") {
-    proxy?.$modal?.msgWarning?.("璇烽�夋嫨宸ヨ壓璺嚎閰嶇疆");
+  if (selectedRouteId.value === null || selectedRouteId.value === undefined || selectedRouteId.value === "") {
+    proxy?.$modal?.msgWarning?.("璇烽�夋嫨宸ヨ壓璺嚎");
     return;
   }
   saving.value = true;
   try {
-    emit("confirm", selectedConfigId.value);
-    handleClose();
+    emit("confirm", selectedRouteId.value);
   } catch (e) {
     proxy?.$modal?.msgError?.("纭澶辫触锛岃绋嶅悗閲嶈瘯");
   } finally {
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index b9a0e84..dd209c7 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -31,6 +31,8 @@
         </div>
         <ProcessFlowConfigSelectDialog
           v-model:visible="processFlowSelectDialogVisible"
+          :default-route-id="processFlowSelectDefaultRouteId"
+          :bound-route-name="processFlowSelectBoundRouteName"
           @confirm="handleProcessFlowSelectConfirm"
         />
         <div>
@@ -992,12 +994,14 @@
 	delLedgerFile,
 	getProductInventory,
 	salesLedgerProductProcessList,
+	saleProcessBind,
+	getSaleProcessBindInfo,
 } from "@/api/salesManagement/salesLedger.js";
 import { modelList, productTreeList } from "@/api/basicData/product.js";
 import useFormData from "@/hooks/useFormData.js";
 import dayjs from "dayjs";
 import { getCurrentDate } from "@/utils/index.js";
-import { salesLedgerProductSetProcessFlowConfig } from "@/api/salesManagement/salesProcessFlowConfig.js";
+// import { salesLedgerProductSetProcessFlowConfig } from "@/api/salesManagement/salesProcessFlowConfig.js";
 
 const userStore = useUserStore();
 const { proxy } = getCurrentInstance();
@@ -1020,6 +1024,9 @@
 // 宸ヨ壓璺嚎閰嶇疆閫夋嫨寮圭獥锛堢粦瀹氬埌鍙拌处浜у搧锛�
 const processFlowSelectDialogVisible = ref(false);
 const processFlowSelectLedgerRow = ref(null);
+const processFlowSelectDefaultRouteId = ref(null);
+const processFlowSelectBoundRouteId = ref(null);
+const processFlowSelectBoundRouteName = ref("");
 
 // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
 const operationType = ref("");
@@ -1420,52 +1427,79 @@
 };
 
 // 鎵撳紑鈥滃伐鑹鸿矾绾块厤缃�濋�夋嫨寮圭獥锛堝繀椤绘樉寮忛�夋嫨锛�
-const openProcessFlowSelect = (ledgerRow) => {
+const openProcessFlowSelect = async (ledgerRow) => {
 	if (!ledgerRow) return;
 	if (!ledgerRow.isEdit) return;
+
 	processFlowSelectLedgerRow.value = ledgerRow;
+	processFlowSelectDefaultRouteId.value = null;
+	processFlowSelectBoundRouteId.value = null;
+	processFlowSelectBoundRouteName.value = "";
+
+	try {
+		const res = await getSaleProcessBindInfo(ledgerRow.id);
+		const info = res?.data ?? res ?? {};
+		const boundId =
+			info?.processRouteId ??
+			info?.routeId ??
+			info?.id ??
+			null;
+		const boundName =
+			info?.processRouteName ??
+			info?.routeName ??
+			info?.name ??
+			"";
+		processFlowSelectBoundRouteId.value = boundId;
+		processFlowSelectBoundRouteName.value = boundName;
+		processFlowSelectDefaultRouteId.value = boundId;
+	} catch (e) {
+		// 鏌ヨ澶辫触鏃舵寜鏈粦瀹氬鐞嗭紝涓嶉樆濉炲脊绐�
+		processFlowSelectBoundRouteId.value = null;
+		processFlowSelectBoundRouteName.value = "";
+		processFlowSelectDefaultRouteId.value = null;
+	}
+
 	processFlowSelectDialogVisible.value = true;
 };
 
-// 灏嗛厤缃簲鐢ㄥ埌鍙拌处涓嬬殑鎵�鏈夋湭鍙戣揣浜у搧
-const handleProcessFlowSelectConfirm = async (configId) => {
+// 缁戝畾宸ヨ壓璺嚎鍒板綋鍓嶅彴璐︽暟鎹�
+const handleProcessFlowSelectConfirm = async (routeId) => {
 	const ledgerRow = processFlowSelectLedgerRow.value;
 	if (!ledgerRow?.id) return;
 
-	const finalConfigId = configId ?? null;
-	if (!finalConfigId) return;
+	const finalRouteId = routeId ?? null;
+	if (!finalRouteId) return;
 
-	proxy?.$modal?.loading?.("姝e湪搴旂敤宸ヨ壓璺嚎閰嶇疆锛岃绋嶅��...");
-	try {
-		const res = await productList({ salesLedgerId: ledgerRow.id, type: 1 });
-		const products = res?.data ?? res?.records ?? res ?? [];
-		if (!Array.isArray(products) || products.length === 0) {
-			proxy?.$modal?.msgWarning?.("璇ュ彴璐︿笅娌℃湁浜у搧鏁版嵁");
+	const oldRouteId = processFlowSelectBoundRouteId.value;
+	if (oldRouteId !== null && oldRouteId !== undefined && oldRouteId !== "" && String(oldRouteId) !== String(finalRouteId)) {
+		try {
+			await ElMessageBox.confirm(
+				"璇ヨ鍗曞凡缁戝畾宸ヨ壓璺嚎锛屾槸鍚︾‘瀹氭洿鎹紵",
+				"鎻愮ず",
+				{
+					confirmButtonText: "纭畾",
+					cancelButtonText: "鍙栨秷",
+					type: "warning",
+				}
+			);
+		} catch {
 			return;
 		}
+	}
 
-		for (const product of products) {
-			// 宸插彂璐�/瀹℃牳閫氳繃涓嶅彲缂栬緫锛岃烦杩�
-			if (isProductShipped(product)) continue;
-			await salesLedgerProductSetProcessFlowConfig({
-				salesLedgerProductId: product.id,
-				processFlowConfigId: finalConfigId,
-			});
-		}
+	proxy?.$modal?.loading?.("姝e湪缁戝畾宸ヨ壓璺嚎锛岃绋嶅��...");
+	try {
+		await saleProcessBind({
+			salesLedgerId: ledgerRow.id,
+			processRouteId: finalRouteId,
+		});
 
-		proxy?.$modal?.msgSuccess?.("宸ヨ壓璺嚎閰嶇疆搴旂敤鎴愬姛");
-
-		// 鑻ュ綋鍓嶈宸插睍寮�锛屽埛鏂板叾瀛愪骇鍝佸垪琛�
-		if (expandedRowKeys.value.includes(ledgerRow.id)) {
-			const childRes = await productList({ salesLedgerId: ledgerRow.id, type: 1 });
-			const children = childRes?.data ?? childRes?.records ?? childRes ?? [];
-			const index = tableData.value.findIndex((item) => item.id === ledgerRow.id);
-			if (index > -1) {
-				tableData.value[index].children = children;
-			}
-		}
+		proxy?.$modal?.msgSuccess?.("宸ヨ壓璺嚎缁戝畾鎴愬姛");
+		processFlowSelectDialogVisible.value = false;
+		// 缁戝畾鍚庡埛鏂板垪琛紝纭繚鎿嶄綔鍒楀啀娆$偣鍑昏兘鍥炴樉缁戝畾
+		await getList();
 	} catch (e) {
-		proxy?.$modal?.msgError?.("搴旂敤澶辫触锛岃绋嶅悗閲嶈瘯");
+		proxy?.$modal?.msgError?.("缁戝畾澶辫触锛岃绋嶅悗閲嶈瘯");
 	} finally {
 		proxy?.$modal?.closeLoading?.();
 	}

--
Gitblit v1.9.3