From 5b76649a97e92e3f02cdbb71e871443524fd0348 Mon Sep 17 00:00:00 2001
From: zhangwencui <1064582902@qq.com>
Date: 星期二, 27 一月 2026 14:12:04 +0800
Subject: [PATCH] 销售台账增加发货列表和发货功能

---
 src/api/salesManagement/salesLedger.js                   |   10 
 src/pages.json                                           |   14 
 src/pages/sales/salesAccount/goOut.vue                   |  657 +++++++++++++++++++
 src/pages/sales/salesAccount/index.vue                   |  386 +++++-----
 src/pages/sales/salesAccount/out.vue                     |  407 +++++++++++
 src/pages/procurementManagement/paymentLedger/detail.vue |  517 +++++++-------
 6 files changed, 1,555 insertions(+), 436 deletions(-)

diff --git a/src/api/salesManagement/salesLedger.js b/src/api/salesManagement/salesLedger.js
index a6125f3..3297637 100644
--- a/src/api/salesManagement/salesLedger.js
+++ b/src/api/salesManagement/salesLedger.js
@@ -125,3 +125,13 @@
     params: query
   })
 }
+
+
+// 鏂板鍙戣揣淇℃伅
+export function addShippingInfo(data) {
+  return request({
+    url: "/shippingInfo/add",
+    method: "post",
+    data,
+  });
+}
diff --git a/src/pages.json b/src/pages.json
index 09bebad..e93e39d 100644
--- a/src/pages.json
+++ b/src/pages.json
@@ -58,6 +58,20 @@
       }
     },
     {
+      "path": "pages/sales/salesAccount/out",
+      "style": {
+        "navigationBarTitleText": "鍙戣揣鐘舵��",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/sales/salesAccount/goOut",
+      "style": {
+        "navigationBarTitleText": "鍙戣揣",
+        "navigationStyle": "custom"
+      }
+    },
+    {
       "path": "pages/sales/salesAccount/detail",
       "style": {
         "navigationBarTitleText": "淇敼鍙拌处",
diff --git a/src/pages/procurementManagement/paymentLedger/detail.vue b/src/pages/procurementManagement/paymentLedger/detail.vue
index 915ee5d..00ccf8b 100644
--- a/src/pages/procurementManagement/paymentLedger/detail.vue
+++ b/src/pages/procurementManagement/paymentLedger/detail.vue
@@ -1,294 +1,305 @@
 <template>
-	<view class="receipt-payment-detail">
-		<!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
-		<PageHeader title="渚涘簲鍟嗗線鏉ヨ鎯�" @back="goBack" />
-		
-		<!-- 缁熻淇℃伅 -->
-		<view class="summary-info" v-if="tableData.length > 0">
-			<view class="summary-item">
-				<text class="summary-label">鎬昏褰曟暟</text>
-				<text class="summary-value">{{ tableData.length }}</text>
-			</view>
-			<view class="summary-item">
-				<text class="summary-label">寮�绁ㄦ�婚噾棰�</text>
-				<text class="summary-value">{{ formatAmount(invoiceTotal) }}</text>
-			</view>
-			<view class="summary-item">
-				<text class="summary-label">鍥炴鎬婚噾棰�</text>
-				<text class="summary-value highlight">{{ formatAmount(receiptTotal) }}</text>
-			</view>
-			<view class="summary-item">
-				<text class="summary-label">搴旀敹鎬婚噾棰�</text>
-				<text class="summary-value danger">{{ formatAmount(unReceiptTotal) }}</text>
-			</view>
-		</view>
-		
-		<!-- 鍥炴璁板綍鏄庣粏鍒楄〃 -->
-		<view class="detail-list" v-if="tableData.length > 0">
-			<view v-for="(item, index) in tableData" :key="index" class="detail-item">
-				<view class="item-header">
-					<view class="item-left">
-						<view class="record-icon">
-							<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
-						</view>
-						<text class="item-index">{{ index + 1 }}</text>
-					</view>
-					<view class="item-date">{{ item.happenTime }}</view>
-				</view>
-				<up-divider></up-divider>
-				<view class="item-details">
-					<view class="detail-row">
-						<text class="detail-label">鍙戠エ閲戦(鍏�)</text>
-						<text class="detail-value">{{ formatAmount(item.invoiceAmount) }}</text>
-					</view>
-					<view class="detail-row">
-						<text class="detail-label">浠樻閲戦(鍏�)</text>
-						<text class="detail-value highlight">{{ formatAmount(item.currentPaymentAmount) }}</text>
-					</view>
-					<view class="detail-row">
-						<text class="detail-label">搴斾粯閲戦(鍏�)</text>
-						<text class="detail-value danger">{{ formatAmount(item.payableAmount) }}</text>
-					</view>
-				</view>
-			</view>
-		</view>
-		<view v-else class="no-data">
-			<text>鏆傛棤鍥炴璁板綍</text>
-		</view>
-	</view>
+  <view class="receipt-payment-detail">
+    <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+    <PageHeader title="渚涘簲鍟嗗線鏉ヨ鎯�"
+                @back="goBack" />
+    <!-- 缁熻淇℃伅 -->
+    <view class="summary-info"
+          v-if="tableData.length > 0">
+      <view class="summary-item">
+        <text class="summary-label">鎬昏褰曟暟</text>
+        <text class="summary-value">{{ tableData.length }}</text>
+      </view>
+      <view class="summary-item">
+        <text class="summary-label">寮�绁ㄦ�婚噾棰�</text>
+        <text class="summary-value">{{ formatAmount(invoiceTotal) }}</text>
+      </view>
+      <view class="summary-item">
+        <text class="summary-label">鍥炴鎬婚噾棰�</text>
+        <text class="summary-value highlight">{{ formatAmount(receiptTotal) }}</text>
+      </view>
+      <view class="summary-item">
+        <text class="summary-label">搴旀敹鎬婚噾棰�</text>
+        <text class="summary-value danger">{{ formatAmount(unReceiptTotal) }}</text>
+      </view>
+    </view>
+    <!-- 鍥炴璁板綍鏄庣粏鍒楄〃 -->
+    <view class="detail-list"
+          v-if="tableData.length > 0">
+      <view v-for="(item, index) in tableData"
+            :key="index"
+            class="detail-item">
+        <view class="item-header">
+          <view class="item-left">
+            <view class="record-icon">
+              <up-icon name="file-text"
+                       size="16"
+                       color="#ffffff"></up-icon>
+            </view>
+            <text class="item-index">{{ index + 1 }}</text>
+          </view>
+          <view class="item-date">{{ item.happenTime }}</view>
+        </view>
+        <up-divider></up-divider>
+        <view class="item-details">
+          <view class="detail-row">
+            <text class="detail-label">鍙戠エ閲戦(鍏�)</text>
+            <text class="detail-value">{{ formatAmount(item.invoiceAmount) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">浠樻閲戦(鍏�)</text>
+            <text class="detail-value highlight">{{ formatAmount(item.currentPaymentAmount) }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">搴斾粯閲戦(鍏�)</text>
+            <text class="detail-value danger">{{ formatAmount(item.payableAmount) }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view v-else
+          class="no-data">
+      <text>鏆傛棤鍥炴璁板綍</text>
+    </view>
+  </view>
 </template>
 
 <script setup>
-import { ref, computed, onMounted } from 'vue';
-import { onShow } from '@dcloudio/uni-app';
-import {paymentLedgerList, paymentRecordList} from "@/api/procurementManagement/paymentLedger";
+  import { ref, computed, onMounted } from "vue";
+  import { onShow } from "@dcloudio/uni-app";
+  import {
+    paymentLedgerList,
+    paymentRecordList,
+  } from "@/api/procurementManagement/paymentLedger";
 
-// 瀹㈡埛淇℃伅
-const supplierId = ref('');
+  // 瀹㈡埛淇℃伅
+  const supplierId = ref("");
 
-// 琛ㄦ牸鏁版嵁
-const tableData = ref([]);
+  // 琛ㄦ牸鏁版嵁
+  const tableData = ref([]);
 
-const invoiceTotal = computed(() => {
-	return tableData.value.reduce((sum, item) => {
-		return sum + (parseFloat(item.invoiceAmount) || 0);
-	}, 0);
-});
+  const invoiceTotal = computed(() => {
+    return tableData.value.reduce((sum, item) => {
+      return sum + (parseFloat(item.invoiceAmount) || 0);
+    }, 0);
+  });
 
-const receiptTotal = computed(() => {
-	return tableData.value.reduce((sum, item) => {
-		return sum + (parseFloat(item.receiptAmount) || 0);
-	}, 0);
-});
+  const receiptTotal = computed(() => {
+    return tableData.value.reduce((sum, item) => {
+      return sum + (parseFloat(item.receiptAmount) || 0);
+    }, 0);
+  });
 
-const unReceiptTotal = computed(() => {
-	return tableData.value.reduce((sum, item) => {
-		return sum + (parseFloat(item.unReceiptAmount) || 0);
-	}, 0);
-});
+  const unReceiptTotal = computed(() => {
+    return tableData.value.reduce((sum, item) => {
+      return sum + (parseFloat(item.unReceiptAmount) || 0);
+    }, 0);
+  });
 
-// 杩斿洖涓婁竴椤�
-const goBack = () => {
-	uni.removeStorageSync('supplierId')
-	uni.navigateBack();
-};
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.removeStorageSync("supplierId");
+    uni.navigateBack();
+  };
 
-// 鑾峰彇椤甸潰鍙傛暟
-const getPageParams = () => {
-	// 浠庢湰鍦板瓨鍌ㄨ幏鍙栦緵搴斿晢ID
-	const storedSupplierId = uni.getStorageSync('supplierId');
-	if (storedSupplierId) {
-		supplierId.value = storedSupplierId;
-	}
-};
+  // 鑾峰彇椤甸潰鍙傛暟
+  const getPageParams = () => {
+    // 浠庢湰鍦板瓨鍌ㄨ幏鍙栦緵搴斿晢ID
+    const storedSupplierId = uni.getStorageSync("supplierId");
+    if (storedSupplierId) {
+      supplierId.value = storedSupplierId;
+    }
+  };
 
-// 鏌ヨ鍒楄〃
-const getList = () => {
-	if (!supplierId.value) {
-		uni.showToast({
-			title: '瀹㈡埛淇℃伅缂哄け',
-			icon: 'error'
-		});
-		return;
-	}
-	showLoadingToast('鍔犺浇涓�...')
-	paymentRecordList(supplierId.value).then((res) => {
-		tableData.value = res.data;
-		closeToast()
-	}).catch(() => {
-		closeToast()
-		uni.showToast({
-			title: '鏌ヨ澶辫触',
-			icon: 'error'
-		});
-	});
-};
+  // 鏌ヨ鍒楄〃
+  const getList = () => {
+    if (!supplierId.value) {
+      uni.showToast({
+        title: "瀹㈡埛淇℃伅缂哄け",
+        icon: "error",
+      });
+      return;
+    }
+    showLoadingToast("鍔犺浇涓�...");
+    paymentRecordList(supplierId.value)
+      .then(res => {
+        tableData.value = res.data;
+        closeToast();
+      })
+      .catch(() => {
+        closeToast();
+        uni.showToast({
+          title: "鏌ヨ澶辫触",
+          icon: "error",
+        });
+      });
+  };
 
-// 鏍煎紡鍖栭噾棰�
-const formatAmount = (amount) => {
-	return amount ? parseFloat(amount).toFixed(2) : '0.00';
-};
+  // 鏍煎紡鍖栭噾棰�
+  const formatAmount = amount => {
+    return amount ? parseFloat(amount).toFixed(2) : "0.00";
+  };
 
-// 鏄剧ず鍔犺浇鎻愮ず
-const showLoadingToast = (message) => {
-	uni.showLoading({
-		title: message,
-		mask: true
-	});
-};
+  // 鏄剧ず鍔犺浇鎻愮ず
+  const showLoadingToast = message => {
+    uni.showLoading({
+      title: message,
+      mask: true,
+    });
+  };
 
-// 鍏抽棴鎻愮ず
-const closeToast = () => {
-	uni.hideLoading();
-};
+  // 鍏抽棴鎻愮ず
+  const closeToast = () => {
+    uni.hideLoading();
+  };
 
-onMounted(() => {
-	// 椤甸潰鍔犺浇鏃惰幏鍙栧弬鏁板苟鍒锋柊鍒楄〃
-	getPageParams();
-	getList();
-});
+  onMounted(() => {
+    // 椤甸潰鍔犺浇鏃惰幏鍙栧弬鏁板苟鍒锋柊鍒楄〃
+    getPageParams();
+    getList();
+  });
 </script>
 
 <style scoped lang="scss">
-.receipt-payment-detail {
-	min-height: 100vh;
-	background: #f8f9fa;
-	position: relative;
-}
+  .receipt-payment-detail {
+    min-height: 100vh;
+    background: #f8f9fa;
+    position: relative;
+  }
 
-.u-divider {
-	margin: 0 !important;
-}
+  .u-divider {
+    margin: 0 !important;
+  }
 
-.summary-info {
-	background: #ffffff;
-	margin: 20px 20px 0 20px;
-	border-radius: 12px;
-	padding: 16px;
-	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
-}
+  .summary-info {
+    background: #ffffff;
+    margin: 20px 20px 0 20px;
+    border-radius: 12px;
+    padding: 16px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+  }
 
-.summary-item {
-	display: flex;
-	justify-content: space-between;
-	align-items: center;
-	margin-bottom: 8px;
-	
-	&:last-child {
-		margin-bottom: 0;
-	}
-}
+  .summary-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 8px;
 
-.summary-label {
-	font-size: 14px;
-	color: #666;
-}
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
 
-.summary-value {
-	font-size: 14px;
-	color: #333;
-	font-weight: 500;
-}
+  .summary-label {
+    font-size: 14px;
+    color: #666;
+  }
 
-.summary-value.highlight {
-	color: #2979ff;
-	font-weight: 600;
-}
+  .summary-value {
+    font-size: 14px;
+    color: #333;
+    font-weight: 500;
+  }
 
-.summary-value.danger {
-	color: #ff4757;
-	font-weight: 600;
-}
+  .summary-value.highlight {
+    color: #2979ff;
+    font-weight: 600;
+  }
 
-.detail-list {
-	padding: 20px;
-}
+  .summary-value.danger {
+    color: #ff4757;
+    font-weight: 600;
+  }
 
-.detail-item {
-	background: #ffffff;
-	border-radius: 12px;
-	margin-bottom: 16px;
-	overflow: hidden;
-	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
-	padding: 0 16px;
-}
+  .detail-list {
+    padding: 20px;
+  }
 
-.item-header {
-	padding: 10px 0;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-}
+  .detail-item {
+    background: #ffffff;
+    border-radius: 12px;
+    margin-bottom: 16px;
+    overflow: hidden;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+    padding: 0 16px;
+  }
 
-.item-left {
-	display: flex;
-	align-items: center;
-	gap: 8px;
-}
+  .item-header {
+    padding: 10px 0;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
 
-.record-icon {
-	width: 24px;
-	height: 24px;
-	background: #2979ff;
-	border-radius: 4px;
-	display: flex;
-	align-items: center;
-	justify-content: center;
-}
+  .item-left {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
 
-.item-index {
-	font-size: 14px;
-	color: #333;
-	font-weight: 500;
-}
+  .record-icon {
+    width: 24px;
+    height: 24px;
+    background: #2979ff;
+    border-radius: 4px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
 
-.item-date {
-	font-size: 12px;
-	color: #666;
-}
+  .item-index {
+    font-size: 14px;
+    color: #333;
+    font-weight: 500;
+  }
 
-.item-details {
-	padding: 16px 0;
-}
+  .item-date {
+    font-size: 12px;
+    color: #666;
+  }
 
-.detail-row {
-	display: flex;
-	align-items: flex-end;
-	justify-content: space-between;
-	margin-bottom: 8px;
-	
-	&:last-child {
-		margin-bottom: 0;
-	}
-}
+  .item-details {
+    padding: 16px 0;
+  }
 
-.detail-label {
-	font-size: 12px;
-	color: #777777;
-	min-width: 60px;
-}
+  .detail-row {
+    display: flex;
+    align-items: flex-end;
+    justify-content: space-between;
+    margin-bottom: 8px;
 
-.detail-value {
-	font-size: 12px;
-	color: #000000;
-	text-align: right;
-	flex: 1;
-	margin-left: 16px;
-}
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
 
-.detail-value.highlight {
-	color: #2979ff;
-	font-weight: 500;
-}
+  .detail-label {
+    font-size: 12px;
+    color: #777777;
+    min-width: 60px;
+  }
 
-.detail-value.danger {
-	color: #ff4757;
-	font-weight: 500;
-}
+  .detail-value {
+    font-size: 12px;
+    color: #000000;
+    text-align: right;
+    flex: 1;
+    margin-left: 16px;
+  }
 
-.no-data {
-	padding: 40px 0;
-	text-align: center;
-	color: #999;
-}
+  .detail-value.highlight {
+    color: #2979ff;
+    font-weight: 500;
+  }
+
+  .detail-value.danger {
+    color: #ff4757;
+    font-weight: 500;
+  }
+
+  .no-data {
+    padding: 40px 0;
+    text-align: center;
+    color: #999;
+  }
 </style>
diff --git a/src/pages/sales/salesAccount/goOut.vue b/src/pages/sales/salesAccount/goOut.vue
new file mode 100644
index 0000000..9980e5f
--- /dev/null
+++ b/src/pages/sales/salesAccount/goOut.vue
@@ -0,0 +1,657 @@
+<template>
+  <view class="account-detail">
+    <PageHeader title="鍙戣揣"
+                @back="goBack" />
+    <!-- 琛ㄥ崟鍖哄煙 -->
+    <u-form ref="formRef"
+            @submit="submitForm"
+            :rules="rules"
+            :model="form"
+            label-width="140rpx">
+      <u-form-item prop="typeValue"
+                   label="鍙戣揣绫诲瀷"
+                   required>
+        <u-input v-model="typeValue"
+                 readonly
+                 placeholder="璇烽�夋嫨鍙戣揣鏂瑰紡"
+                 @click="showPicker = true" />
+        <template #right>
+          <up-icon name="arrow-right"
+                   @click="showPicker = true"></up-icon>
+        </template>
+      </u-form-item>
+    </u-form>
+    <!-- 閫夋嫨鍣ㄥ脊绐� -->
+    <up-action-sheet :show="showPicker"
+                     :actions="productOptions"
+                     title="鍙戣揣鏂瑰紡"
+                     @select="onConfirm"
+                     @close="showPicker = false" />
+    <!-- 瀹℃牳娴佺▼鍖哄煙 -->
+    <view class="approval-process">
+      <view class="approval-header">
+        <text class="approval-title">瀹℃牳娴佺▼</text>
+        <text class="approval-desc">姣忎釜姝ラ鍙兘閫夋嫨涓�涓鎵逛汉</text>
+      </view>
+      <view class="approval-steps">
+        <view v-for="(step, stepIndex) in approverNodes"
+              :key="stepIndex"
+              class="approval-step">
+          <view class="step-dot"></view>
+          <view class="step-title">
+            <text>瀹℃壒浜�</text>
+          </view>
+          <view class="approver-container">
+            <view v-if="step.nickName"
+                  class="approver-item">
+              <view class="approver-avatar">
+                <text class="avatar-text">{{ step.nickName.charAt(0) }}</text>
+                <view class="status-dot"></view>
+              </view>
+              <view class="approver-info">
+                <text class="approver-name">{{ step.nickName }}</text>
+              </view>
+              <view class="delete-approver-btn"
+                    @click="removeApprover(stepIndex)">脳</view>
+            </view>
+            <view v-else
+                  class="add-approver-btn"
+                  @click="addApprover(stepIndex)">
+              <view class="add-circle">+</view>
+              <text class="add-label">閫夋嫨瀹℃壒浜�</text>
+            </view>
+          </view>
+          <view class="step-line"
+                v-if="stepIndex < approverNodes.length - 1"></view>
+          <view class="delete-step-btn"
+                v-if="approverNodes.length > 1"
+                @click="removeApprovalStep(stepIndex)">鍒犻櫎鑺傜偣</view>
+        </view>
+      </view>
+      <view class="add-step-btn">
+        <u-button icon="plus"
+                  plain
+                  type="primary"
+                  style="width: 100%"
+                  @click="addApprovalStep">鏂板鑺傜偣</u-button>
+      </view>
+    </view>
+    <!-- 搴曢儴鎸夐挳 -->
+    <view class="footer-btns">
+      <u-button class="cancel-btn"
+                @click="goBack">鍙栨秷</u-button>
+      <u-button class="save-btn"
+                @click="submitForm">鍙戣揣</u-button>
+    </view>
+  </view>
+</template>
+
+<script setup>
+  import { ref, onMounted, onUnmounted, reactive, toRefs } from "vue";
+  import PageHeader from "@/components/PageHeader.vue";
+  import { addShippingInfo } from "@/api/salesManagement/salesLedger";
+  const showToast = message => {
+    uni.showToast({
+      title: message,
+      icon: "none",
+    });
+  };
+  import { userListNoPageByTenantId } from "@/api/system/user";
+
+  const data = reactive({
+    form: {
+      approveTime: "",
+      approveId: "",
+      approveUser: "",
+      approveUserName: "",
+      approveDeptName: "",
+      approveDeptId: "",
+      approveReason: "",
+      checkResult: "",
+      tempFileIds: [],
+      approverList: [], // 鏂板瀛楁锛屽瓨鍌ㄦ墍鏈夎妭鐐圭殑瀹℃壒浜篿d
+      startDate: "",
+      endDate: "",
+      location: "",
+      price: "",
+    },
+    rules: {
+      typeValue: [{ required: false, message: "璇烽�夋嫨", trigger: "change" }],
+    },
+  });
+  const { form, rules } = toRefs(data);
+  const showPicker = ref(false);
+  const productOptions = ref([
+    {
+      value: "璐ц溅",
+      name: "璐ц溅",
+    },
+    {
+      value: "蹇��",
+      name: "蹇��",
+    },
+  ]);
+  const operationType = ref("");
+  const currentApproveStatus = ref("");
+  const approverNodes = ref([]);
+  const userList = ref([]);
+  const formRef = ref(null);
+  const approveType = ref(0);
+  const goOutData = ref({});
+  onMounted(async () => {
+    try {
+      userListNoPageByTenantId().then(res => {
+        userList.value = res.data;
+      });
+      // 浠庢湰鍦板瓨鍌ㄨ幏鍙栧彂璐ц鎯�
+      goOutData.value = JSON.parse(uni.getStorageSync("goOutData"));
+      console.log(goOutData.value, "goOutData.value");
+
+      // 鍒濆鍖栧鎵规祦绋嬭妭鐐癸紝榛樿涓�涓妭鐐�
+      approverNodes.value = [{ id: 1, userId: null }];
+
+      // 鐩戝惉鑱旂郴浜洪�夋嫨浜嬩欢
+      uni.$on("selectContact", handleSelectContact);
+    } catch (error) {
+      console.error("鑾峰彇澶辫触:", error);
+    }
+  });
+
+  onUnmounted(() => {
+    // 绉婚櫎浜嬩欢鐩戝惉
+    uni.$off("selectContact", handleSelectContact);
+  });
+  const typeValue = ref("璐ц溅");
+  const onConfirm = item => {
+    // 璁剧疆閫変腑鐨勯儴闂�
+    typeValue.value = item.name;
+    showPicker.value = false;
+  };
+
+  const goBack = () => {
+    // 娓呴櫎鏈湴瀛樺偍鐨勬暟鎹�
+    uni.removeStorageSync("operationType");
+    uni.removeStorageSync("invoiceLedgerEditRow");
+    uni.removeStorageSync("approveType");
+    uni.navigateBack();
+  };
+
+  const submitForm = () => {
+    // 妫�鏌ユ瘡涓鎵规楠ゆ槸鍚﹂兘鏈夊鎵逛汉
+    const hasEmptyStep = approverNodes.value.some(step => !step.nickName);
+    if (hasEmptyStep) {
+      showToast("璇蜂负姣忎釜瀹℃壒姝ラ閫夋嫨瀹℃壒浜�");
+      return;
+    }
+    formRef.value
+      .validate()
+      .then(valid => {
+        if (valid) {
+          // 琛ㄥ崟鏍¢獙閫氳繃锛屽彲浠ユ彁浜ゆ暟鎹�
+          // 鏀堕泦鎵�鏈夎妭鐐圭殑瀹℃壒浜篿d
+          console.log("approverNodes---", approverNodes.value);
+          const approveUserIds = approverNodes.value
+            .map(node => node.userId)
+            .join(",");
+          const params = {
+            salesLedgerId: goOutData.value.salesLedgerId,
+            salesLedgerProductId: goOutData.value.id,
+            type: typeValue.value,
+            approveUserIds,
+          };
+          console.log(params, "params");
+
+          addShippingInfo(params).then(res => {
+            showToast("鍙戣揣鎴愬姛");
+            setTimeout(() => {
+              goBack();
+            }, 500);
+          });
+        }
+      })
+      .catch(error => {
+        console.error("琛ㄥ崟鏍¢獙澶辫触:", error);
+        // 灏濊瘯鑾峰彇鍏蜂綋鐨勯敊璇瓧娈�
+        if (error && error.errors) {
+          const firstError = error.errors[0];
+          if (firstError) {
+            uni.showToast({
+              title: firstError.message || "琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ュ繀濉」",
+              icon: "none",
+            });
+            return;
+          }
+        }
+        // 鏄剧ず閫氱敤閿欒淇℃伅
+        uni.showToast({
+          title: "琛ㄥ崟鏍¢獙澶辫触锛岃妫�鏌ュ繀濉」",
+          icon: "none",
+        });
+      });
+  };
+
+  // 澶勭悊鑱旂郴浜洪�夋嫨缁撴灉
+  const handleSelectContact = data => {
+    const { stepIndex, contact } = data;
+    // 灏嗛�変腑鐨勮仈绯讳汉璁剧疆涓哄搴斿鎵规楠ょ殑瀹℃壒浜�
+    approverNodes.value[stepIndex].userId = contact.userId;
+    approverNodes.value[stepIndex].nickName = contact.nickName;
+  };
+
+  const addApprover = stepIndex => {
+    // 璺宠浆鍒拌仈绯讳汉閫夋嫨椤甸潰
+    uni.setStorageSync("stepIndex", stepIndex);
+    uni.navigateTo({
+      url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect",
+    });
+  };
+
+  const addApprovalStep = () => {
+    // 娣诲姞鏂扮殑瀹℃壒姝ラ
+    approverNodes.value.push({ userId: null, nickName: null });
+  };
+
+  const removeApprover = stepIndex => {
+    // 绉婚櫎瀹℃壒浜�
+    approverNodes.value[stepIndex].userId = null;
+    approverNodes.value[stepIndex].nickName = null;
+  };
+
+  const removeApprovalStep = stepIndex => {
+    // 纭繚鑷冲皯淇濈暀涓�涓鎵规楠�
+    if (approverNodes.value.length > 1) {
+      approverNodes.value.splice(stepIndex, 1);
+    } else {
+      uni.showToast({
+        title: "鑷冲皯闇�瑕佷竴涓鎵规楠�",
+        icon: "none",
+      });
+    }
+  };
+</script>
+
+<style scoped lang="scss">
+  @import "@/static/scss/form-common.scss";
+
+  .approval-process {
+    background: #fff;
+    margin: 16px;
+    border-radius: 16px;
+    padding: 16px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+  }
+
+  .approval-header {
+    margin-bottom: 16px;
+  }
+
+  .approval-title {
+    font-size: 16px;
+    font-weight: 600;
+    color: #333;
+    display: block;
+    margin-bottom: 4px;
+  }
+
+  .approval-desc {
+    font-size: 12px;
+    color: #999;
+  }
+
+  /* 鏍峰紡澧炲己涓衡�滅畝娲佸皬鍦嗗湀椋庢牸鈥� */
+  .approval-steps {
+    padding-left: 22px;
+    position: relative;
+
+    &::before {
+      content: "";
+      position: absolute;
+      left: 11px;
+      top: 40px;
+      bottom: 40px;
+      width: 2px;
+      background: linear-gradient(
+        to bottom,
+        #e6f7ff 0%,
+        #bae7ff 50%,
+        #91d5ff 100%
+      );
+      border-radius: 1px;
+    }
+  }
+
+  .approval-step {
+    position: relative;
+    margin-bottom: 24px;
+
+    &::before {
+      content: "";
+      position: absolute;
+      left: -18px;
+      top: 14px; // 浠� 8px 璋冩暣涓� 14px锛屼笌鏂囧瓧涓績瀵归綈
+      width: 12px;
+      height: 12px;
+      background: #fff;
+      border: 3px solid #006cfb;
+      border-radius: 50%;
+      z-index: 2;
+      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    }
+  }
+
+  .step-title {
+    top: 12px;
+    margin-bottom: 12px;
+    position: relative;
+    margin-left: 6px;
+  }
+
+  .step-title text {
+    font-size: 14px;
+    color: #666;
+    background: #f0f0f0;
+    padding: 4px 12px;
+    border-radius: 12px;
+    position: relative;
+    line-height: 1.4; // 纭繚鏂囧瓧琛岄珮涓�鑷�
+  }
+
+  .approver-item {
+    display: flex;
+    align-items: center;
+    background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+    border-radius: 16px;
+    padding: 16px;
+    gap: 12px;
+    position: relative;
+    border: 1px solid #e6f7ff;
+    box-shadow: 0 4px 12px rgba(0, 108, 251, 0.08);
+    transition: all 0.3s ease;
+  }
+
+  .approver-avatar {
+    width: 48px;
+    height: 48px;
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    position: relative;
+    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
+  }
+
+  .avatar-text {
+    color: #fff;
+    font-size: 18px;
+    font-weight: 600;
+    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
+  }
+
+  .approver-info {
+    flex: 1;
+    position: relative;
+  }
+
+  .approver-name {
+    display: block;
+    font-size: 16px;
+    color: #333;
+    font-weight: 500;
+    position: relative;
+  }
+
+  .approver-dept {
+    font-size: 12px;
+    color: #999;
+    background: rgba(0, 108, 251, 0.05);
+    padding: 2px 8px;
+    border-radius: 8px;
+    display: inline-block;
+    position: relative;
+
+    &::before {
+      content: "";
+      position: absolute;
+      left: 4px;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 2px;
+      height: 2px;
+      background: #006cfb;
+      border-radius: 50%;
+    }
+  }
+
+  .delete-approver-btn {
+    font-size: 16px;
+    color: #ff4d4f;
+    background: linear-gradient(
+      135deg,
+      rgba(255, 77, 79, 0.1) 0%,
+      rgba(255, 77, 79, 0.05) 100%
+    );
+    width: 28px;
+    height: 28px;
+    border-radius: 50%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    transition: all 0.3s ease;
+    position: relative;
+  }
+
+  .add-approver-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    background: linear-gradient(135deg, #f0f8ff 0%, #e6f7ff 100%);
+    border: 2px dashed #006cfb;
+    border-radius: 16px;
+    padding: 20px;
+    color: #006cfb;
+    font-size: 14px;
+    position: relative;
+    transition: all 0.3s ease;
+
+    &::before {
+      content: "";
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate(-50%, -50%);
+      width: 32px;
+      height: 32px;
+      border: 2px solid #006cfb;
+      border-radius: 50%;
+      opacity: 0;
+      transition: all 0.3s ease;
+    }
+  }
+
+  .delete-step-btn {
+    color: #ff4d4f;
+    font-size: 12px;
+    background: linear-gradient(
+      135deg,
+      rgba(255, 77, 79, 0.1) 0%,
+      rgba(255, 77, 79, 0.05) 100%
+    );
+    padding: 6px 12px;
+    border-radius: 12px;
+    display: inline-block;
+    position: relative;
+    transition: all 0.3s ease;
+
+    &::before {
+      content: "";
+      position: absolute;
+      left: 6px;
+      top: 50%;
+      transform: translateY(-50%);
+      width: 4px;
+      height: 4px;
+      background: #ff4d4f;
+      border-radius: 50%;
+    }
+  }
+
+  .step-line {
+    display: none; // 闅愯棌鍘熸潵鐨勭嚎鏉★紝浣跨敤浼厓绱犱唬鏇�
+  }
+
+  .add-step-btn {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+  .footer-btns {
+    position: fixed;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: #fff;
+    display: flex;
+    justify-content: space-around;
+    align-items: center;
+    padding: 0.75rem 0;
+    box-shadow: 0 -0.125rem 0.5rem rgba(0, 0, 0, 0.05);
+    z-index: 1000;
+  }
+
+  .cancel-btn {
+    font-weight: 400;
+    font-size: 1rem;
+    color: #ffffff;
+    width: 6.375rem;
+    background: #c7c9cc;
+    box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2);
+    border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
+  }
+
+  .save-btn {
+    font-weight: 400;
+    font-size: 1rem;
+    color: #ffffff;
+    width: 14rem;
+    background: linear-gradient(140deg, #00baff 0%, #006cfb 100%);
+    box-shadow: 0 0.25rem 0.625rem 0 rgba(3, 88, 185, 0.2);
+    border-radius: 2.5rem 2.5rem 2.5rem 2.5rem;
+  }
+
+  // 鍔ㄧ敾瀹氫箟
+  @keyframes pulse {
+    0% {
+      transform: scale(1);
+      opacity: 1;
+    }
+    50% {
+      transform: scale(1.2);
+      opacity: 0.7;
+    }
+    100% {
+      transform: scale(1);
+      opacity: 1;
+    }
+  }
+
+  @keyframes rotate {
+    0% {
+      transform: rotate(0deg);
+    }
+    100% {
+      transform: rotate(360deg);
+    }
+  }
+
+  @keyframes ripple {
+    0% {
+      transform: translate(-50%, -50%) scale(0.8);
+      opacity: 1;
+    }
+    100% {
+      transform: translate(-50%, -50%) scale(1.6);
+      opacity: 0;
+    }
+  }
+
+  /* 濡傛灉宸叉湁 .step-line锛岃繖閲屾洿绮惧噯瀹氫綅鍒板乏渚т笌灏忓渾鐐瑰榻� */
+  .step-line {
+    position: absolute;
+    left: 4px;
+    top: 48px;
+    width: 2px;
+    height: calc(100% - 48px);
+    background: #e5e7eb;
+  }
+
+  .approver-container {
+    display: flex;
+    align-items: center;
+    background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
+    border-radius: 16px;
+    gap: 12px;
+    padding: 10px 0;
+    background: transparent;
+    border: none;
+    box-shadow: none;
+  }
+
+  .approver-item {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+    padding: 8px 10px;
+    background: transparent;
+    border: none;
+    box-shadow: none;
+    border-radius: 0;
+  }
+
+  .approver-avatar {
+    position: relative;
+    width: 40px;
+    height: 40px;
+    border-radius: 50%;
+    background: #f3f4f6;
+    border: 2px solid #e5e7eb;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    animation: none; /* 绂佺敤鏃嬭浆绛夊姩鐢伙紝鍥炲綊绠�娲� */
+  }
+
+  .avatar-text {
+    font-size: 14px;
+    color: #374151;
+    font-weight: 600;
+  }
+
+  .add-approver-btn {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    background: transparent;
+    border: none;
+    box-shadow: none;
+    padding: 0;
+  }
+
+  .add-approver-btn .add-circle {
+    width: 40px;
+    height: 40px;
+    border: 2px dashed #a0aec0;
+    border-radius: 50%;
+    color: #6b7280;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 22px;
+    line-height: 1;
+  }
+
+  .add-approver-btn .add-label {
+    color: #3b82f6;
+    font-size: 14px;
+  }
+</style>
\ No newline at end of file
diff --git a/src/pages/sales/salesAccount/index.vue b/src/pages/sales/salesAccount/index.vue
index acc8783..d6a8646 100644
--- a/src/pages/sales/salesAccount/index.vue
+++ b/src/pages/sales/salesAccount/index.vue
@@ -1,196 +1,216 @@
 <template>
-	<view class="sales-account">
-		<!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
-		<PageHeader title="閿�鍞彴璐�" @back="goBack" />
-		
-		<!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
-		<view class="search-section">
-			<view class="search-bar">
-				<view class="search-input">
-					<up-input
-						class="search-text"
-						placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿鎼滅储"
-						v-model="salesContractNo"
-						@change="getList"
-						clearable
-					/>
-				</view>
-				<view class="filter-button" @click="getList">
-					<up-icon name="search" size="24" color="#999"></up-icon>
-				</view>
-			</view>
-		</view>
-		
-		<!-- 閿�鍞彴璐︾�戝竷娴� -->
-		<view class="ledger-list" v-if="ledgerList.length > 0">
-			<view v-for="(item, index) in ledgerList" :key="index">
-				<view class="ledger-item" @click="handleInfo('edit', item)">
-					<view class="item-header">
-						<view class="item-left">
-							<view class="document-icon">
-								<up-icon name="file-text" size="16" color="#ffffff"></up-icon>
-							</view>
-							<text class="item-id">{{ item.salesContractNo }}</text>
-						</view>
-						<!--							<view class="item-tag">-->
-						<!--								<text class="tag-text">{{ item.recorder }}</text>-->
-						<!--							</view>-->
-					</view>
-					<up-divider></up-divider>
-					
-					<view class="item-details">
-						<view class="detail-row">
-							<text class="detail-label">瀹㈡埛鍚嶇О</text>
-							<text class="detail-value">{{ item.customerName }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">瀹㈡埛鍚堝悓鍙�</text>
-							<text class="detail-value">{{ item.customerContractNo }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">涓氬姟鍛�</text>
-							<text class="detail-value">{{ item.salesman }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">椤圭洰鍚嶇О</text>
-							<text class="detail-value">{{ item.projectName }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">浠樻鏂瑰紡</text>
-							<text class="detail-value">{{ item.paymentMethod }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">鍚堝悓閲戦(鍏�)</text>
-							<text class="detail-value highlight">{{ item.contractAmount }}</text>
-						</view>
-						<view class="detail-row">
-							<text class="detail-label">绛捐鏃ユ湡</text>
-							<text class="detail-value">{{ item.executionDate }}</text>
-						</view>
-						<up-divider></up-divider>
-						<view class="detail-info">
-							<view class="detail-row">
-								<text class="detail-label">褰曞叆浜�</text>
-								<text class="detail-value">{{ item.entryPersonName }}</text>
-							</view>
-							<view class="detail-row">
-								<text class="detail-label">褰曞叆鏃ユ湡</text>
-								<text class="detail-value">{{ item.entryDate }}</text>
-							</view>
-						</view>
-					</view>
-				</view>
-			</view>
-		</view>
-		<view v-else class="no-data">
-			<text>鏆傛棤閿�鍞彴璐︽暟鎹�</text>
-		</view>
-		
-		<!-- 娴姩鎿嶄綔鎸夐挳 -->
-		<view class="fab-button" @click="handleInfo('add')">
-			<up-icon name="plus" size="24" color="#ffffff"></up-icon>
-		</view>
-	</view>
+  <view class="sales-account">
+    <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+    <PageHeader title="閿�鍞彴璐�"
+                @back="goBack" />
+    <!-- 鎼滅储鍜岀瓫閫夊尯鍩� -->
+    <view class="search-section">
+      <view class="search-bar">
+        <view class="search-input">
+          <up-input class="search-text"
+                    placeholder="璇疯緭鍏ラ攢鍞悎鍚屽彿鎼滅储"
+                    v-model="salesContractNo"
+                    @change="getList"
+                    clearable />
+        </view>
+        <view class="filter-button"
+              @click="getList">
+          <up-icon name="search"
+                   size="24"
+                   color="#999"></up-icon>
+        </view>
+      </view>
+    </view>
+    <!-- 閿�鍞彴璐︾�戝竷娴� -->
+    <view class="ledger-list"
+          v-if="ledgerList.length > 0">
+      <view v-for="(item, index) in ledgerList"
+            :key="index">
+        <view class="ledger-item"
+              @click="handleInfo('edit', item)">
+          <view class="item-header">
+            <view class="item-left">
+              <view class="document-icon">
+                <up-icon name="file-text"
+                         size="16"
+                         color="#ffffff"></up-icon>
+              </view>
+              <text class="item-id">{{ item.salesContractNo }}</text>
+            </view>
+            <!--							<view class="item-tag">-->
+            <!--								<text class="tag-text">{{ item.recorder }}</text>-->
+            <!--							</view>-->
+          </view>
+          <up-divider></up-divider>
+          <view class="item-details">
+            <view class="detail-row">
+              <text class="detail-label">瀹㈡埛鍚嶇О</text>
+              <text class="detail-value">{{ item.customerName }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">瀹㈡埛鍚堝悓鍙�</text>
+              <text class="detail-value">{{ item.customerContractNo }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">涓氬姟鍛�</text>
+              <text class="detail-value">{{ item.salesman }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">椤圭洰鍚嶇О</text>
+              <text class="detail-value">{{ item.projectName }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">浠樻鏂瑰紡</text>
+              <text class="detail-value">{{ item.paymentMethod }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">鍚堝悓閲戦(鍏�)</text>
+              <text class="detail-value highlight">{{ item.contractAmount }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">绛捐鏃ユ湡</text>
+              <text class="detail-value">{{ item.executionDate }}</text>
+            </view>
+            <up-divider></up-divider>
+            <view class="detail-info">
+              <view class="detail-row">
+                <text class="detail-label">褰曞叆浜�</text>
+                <text class="detail-value">{{ item.entryPersonName }}</text>
+              </view>
+              <view class="detail-row">
+                <text class="detail-label">褰曞叆鏃ユ湡</text>
+                <text class="detail-value">{{ item.entryDate }}</text>
+              </view>
+            </view>
+            <up-divider></up-divider>
+            <u-button class="detail-button"
+                      size="small"
+                      type="primary"
+                      @click="openOut(item)">
+              鍙戣揣鐘舵��
+            </u-button>
+          </view>
+        </view>
+      </view>
+    </view>
+    <view v-else
+          class="no-data">
+      <text>鏆傛棤閿�鍞彴璐︽暟鎹�</text>
+    </view>
+    <!-- 娴姩鎿嶄綔鎸夐挳 -->
+    <view class="fab-button"
+          @click="handleInfo('add')">
+      <up-icon name="plus"
+               size="24"
+               color="#ffffff"></up-icon>
+    </view>
+  </view>
 </template>
 
 <script setup>
-import { ref } from 'vue';
-import { onShow } from '@dcloudio/uni-app';
-import {ledgerListPage} from "@/api/salesManagement/salesLedger";
-import useUserStore from "@/store/modules/user";
-import PageHeader from "@/components/PageHeader.vue";
-const userStore = useUserStore()
-const showLoadingToast = (message) => {
-	uni.showLoading({
-		title: message,
-		mask: true
-	})
-}
-const closeToast = () => {
-	uni.hideLoading()
-}
+  import { ref } from "vue";
+  import { onShow } from "@dcloudio/uni-app";
+  import { ledgerListPage } from "@/api/salesManagement/salesLedger";
+  import useUserStore from "@/store/modules/user";
+  import PageHeader from "@/components/PageHeader.vue";
+  const userStore = useUserStore();
+  const showLoadingToast = message => {
+    uni.showLoading({
+      title: message,
+      mask: true,
+    });
+  };
+  const closeToast = () => {
+    uni.hideLoading();
+  };
 
-// 鎼滅储鍏抽敭璇�
-const salesContractNo = ref('');
+  // 鎼滅储鍏抽敭璇�
+  const salesContractNo = ref("");
 
-// 閿�鍞彴璐︽暟鎹�
-const ledgerList = ref([]);
+  // 閿�鍞彴璐︽暟鎹�
+  const ledgerList = ref([]);
 
-// 杩斿洖涓婁竴椤�
-const goBack = () => {
-	uni.navigateBack();
-};
-// 鏌ヨ鍒楄〃
-const getList = () => {
-	showLoadingToast('鍔犺浇涓�...')
-	const page = {
-		current: -1,
-		size: -1
-	}
-	ledgerListPage({...page, salesContractNo: salesContractNo.value}).then((res) => {
-		console.log('閿�鍞彴璐�----', res);
-		ledgerList.value = res.records;
-		closeToast()
-	}).catch(() => {
-		closeToast()
-	});
-};
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.navigateBack();
+  };
+  // 鏌ヨ鍒楄〃
+  const getList = () => {
+    showLoadingToast("鍔犺浇涓�...");
+    const page = {
+      current: -1,
+      size: -1,
+    };
+    ledgerListPage({ ...page, salesContractNo: salesContractNo.value })
+      .then(res => {
+        console.log("閿�鍞彴璐�----", res);
+        ledgerList.value = res.records;
+        closeToast();
+      })
+      .catch(() => {
+        closeToast();
+      });
+  };
+  const openOut = item => {
+    uni.setStorageSync("outData", JSON.stringify(item));
+    uni.navigateTo({
+      url: "/pages/sales/salesAccount/out",
+    });
+  };
+  // 澶勭悊鍙拌处淇℃伅鎿嶄綔锛堟煡鐪�/缂栬緫/鏂板锛�
+  const handleInfo = (type, row) => {
+    try {
+      // 璁剧疆鎿嶄綔绫诲瀷
+      uni.setStorageSync("operationType", type);
 
-// 澶勭悊鍙拌处淇℃伅鎿嶄綔锛堟煡鐪�/缂栬緫/鏂板锛�
-const handleInfo = (type, row) => {
-	try {
-		// 璁剧疆鎿嶄綔绫诲瀷
-		uni.setStorageSync('operationType', type);
-		
-		// 濡傛灉鏄煡鐪嬫垨缂栬緫鎿嶄綔
-		if (type !== 'add') {
-			// 楠岃瘉琛屾暟鎹槸鍚﹀瓨鍦�
-			if (!row) {
-				uni.showToast({
-					title: '鏁版嵁涓嶅瓨鍦�',
-					icon: 'error'
-				});
-				return;
-			}
-			
-			// 妫�鏌ユ潈闄愶細鍙湁褰曞叆浜烘墠鑳界紪杈�
-			if (row.entryPerson != userStore.id) {
-				// 闈炲綍鍏ヤ汉璺宠浆鍒板彧璇昏鎯呴〉闈�
-				uni.setStorageSync('editData', JSON.stringify(row));
-				uni.navigateTo({
-					url: '/pages/sales/salesAccount/view'
-				});
-				return;
-			}
-			
-			// 褰曞叆浜虹紪杈戯細瀛樺偍鏁版嵁骞惰烦杞埌缂栬緫椤甸潰
-			uni.setStorageSync('editData', JSON.stringify(row));
-			uni.navigateTo({
-				url: '/pages/sales/salesAccount/detail'
-			});
-			return;
-		}
-		
-		// 鏂板鎿嶄綔锛氱洿鎺ヨ烦杞埌缂栬緫椤甸潰
-		uni.navigateTo({
-			url: '/pages/sales/salesAccount/detail'
-		});
-		
-	} catch (error) {
-		console.error('澶勭悊鍙拌处淇℃伅鎿嶄綔澶辫触:', error);
-		uni.showToast({
-			title: '鎿嶄綔澶辫触锛岃閲嶈瘯',
-			icon: 'error'
-		});
-	}
-};
+      // 濡傛灉鏄煡鐪嬫垨缂栬緫鎿嶄綔
+      if (type !== "add") {
+        // 楠岃瘉琛屾暟鎹槸鍚﹀瓨鍦�
+        if (!row) {
+          uni.showToast({
+            title: "鏁版嵁涓嶅瓨鍦�",
+            icon: "error",
+          });
+          return;
+        }
 
-onShow(() => {
-	// 椤甸潰鏄剧ず鏃跺埛鏂板垪琛�
-	getList();
-});
+        // 妫�鏌ユ潈闄愶細鍙湁褰曞叆浜烘墠鑳界紪杈�
+        if (row.entryPerson != userStore.id) {
+          // 闈炲綍鍏ヤ汉璺宠浆鍒板彧璇昏鎯呴〉闈�
+          uni.setStorageSync("editData", JSON.stringify(row));
+          uni.navigateTo({
+            url: "/pages/sales/salesAccount/view",
+          });
+          return;
+        }
+
+        // 褰曞叆浜虹紪杈戯細瀛樺偍鏁版嵁骞惰烦杞埌缂栬緫椤甸潰
+        uni.setStorageSync("editData", JSON.stringify(row));
+        uni.navigateTo({
+          url: "/pages/sales/salesAccount/detail",
+        });
+        return;
+      }
+
+      // 鏂板鎿嶄綔锛氱洿鎺ヨ烦杞埌缂栬緫椤甸潰
+      uni.navigateTo({
+        url: "/pages/sales/salesAccount/detail",
+      });
+    } catch (error) {
+      console.error("澶勭悊鍙拌处淇℃伅鎿嶄綔澶辫触:", error);
+      uni.showToast({
+        title: "鎿嶄綔澶辫触锛岃閲嶈瘯",
+        icon: "error",
+      });
+    }
+  };
+
+  onShow(() => {
+    // 椤甸潰鏄剧ず鏃跺埛鏂板垪琛�
+    getList();
+  });
 </script>
 
 <style scoped lang="scss">
-@import '@/styles/sales-common.scss';
+  @import "@/styles/sales-common.scss";
 </style>
diff --git a/src/pages/sales/salesAccount/out.vue b/src/pages/sales/salesAccount/out.vue
new file mode 100644
index 0000000..d4fc5be
--- /dev/null
+++ b/src/pages/sales/salesAccount/out.vue
@@ -0,0 +1,407 @@
+<template>
+  <view class="receipt-payment-detail">
+    <!-- 浣跨敤閫氱敤椤甸潰澶撮儴缁勪欢 -->
+    <PageHeader title="鍙戣揣鐘舵��"
+                @back="goBack" />
+    <!-- 缁熻淇℃伅 -->
+    <view class="summary-info">
+      <view class="summary-item">
+        <text class="summary-label">瀹㈡埛鍚嶇О</text>
+        <text class="summary-value">{{ outData.customerName }}</text>
+      </view>
+      <view class="summary-item">
+        <text class="summary-label">鍚堝悓閲戦</text>
+        <text class="summary-value">{{ outData.contractAmount }}</text>
+      </view>
+      <view class="summary-item">
+        <text class="summary-label">绛捐鏃ユ湡</text>
+        <text class="summary-value">{{ outData.executionDate }}</text>
+      </view>
+    </view>
+    <!-- 鍥炴璁板綍鏄庣粏鍒楄〃 -->
+    <view class="detail-list"
+          v-if="tableData.length > 0">
+      <view v-for="(item, index) in tableData"
+            :key="index"
+            class="detail-item">
+        <view class="item-header">
+          <view class="item-left">
+            <view class="record-icon">
+              <up-icon name="file-text"
+                       size="16"
+                       color="#ffffff"></up-icon>
+            </view>
+            <text class="item-index">{{ item.productCategory }}</text>
+          </view>
+        </view>
+        <up-divider></up-divider>
+        <view class="item-details">
+          <view class="detail-row">
+            <text class="detail-label">浜у搧澶х被</text>
+            <text class="detail-value">{{ item.productCategory }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">瑙勬牸鍨嬪彿</text>
+            <text class="detail-value">{{ item.specificationModel }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍗曚綅</text>
+            <text class="detail-value">{{ item.unit }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">浜у搧鐘舵��</text>
+            <text v-if="item.approveStatus === 1"
+                  class="detail-value highlight">鍏呰冻</text>
+            <text v-else
+                  class="detail-value danger">涓嶈冻</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍙戣揣鐘舵��</text>
+            <u-tag size="mini"
+                   :type="getShippingStatusType(item)">{{ getShippingStatusText(item) }}</u-tag>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">蹇�掑叕鍙�</text>
+            <text class="detail-value">{{ item.expressCompany }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">蹇�掑崟鍙�</text>
+            <text class="detail-value">{{ item.expressNumber }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍙戣揣杞︾墝</text>
+            <u-tag size="mini"
+                   v-if="item.shippingCarNumber"
+                   type="success">{{ item.shippingCarNumber }}</u-tag>
+            <u-tag v-else
+                   size="mini"
+                   type="info">-</u-tag>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍙戣揣鏃ユ湡</text>
+            <text class="detail-value">{{ item.shippingDate || '-' }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鏁伴噺</text>
+            <text class="detail-value">{{ item.quantity }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">绋庣巼锛�%锛�</text>
+            <text class="detail-value">{{ item.taxRate }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍚◣鍗曚环锛堝厓锛�</text>
+            <text class="detail-value">{{ item.taxInclusiveUnitPrice }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">鍚◣鎬讳环锛堝厓锛�</text>
+            <text class="detail-value">{{ item.taxInclusiveTotalPrice }}</text>
+          </view>
+          <view class="detail-row">
+            <text class="detail-label">涓嶅惈绋庢�讳环锛堝厓锛�</text>
+            <text class="detail-value">{{ item.taxExclusiveTotalPrice }}</text>
+          </view>
+          <up-divider></up-divider>
+          <u-button class="detail-button"
+                    size="small"
+                    type="primary"
+                    :disabled="!canShip(item)"
+                    @click="goout(item)">
+            鍙戣揣
+          </u-button>
+        </view>
+      </view>
+    </view>
+    <view v-else
+          class="no-data">
+      <text>鏆傛棤鍥炴璁板綍</text>
+    </view>
+  </view>
+</template>
+
+<script setup>
+  import { ref, computed, onMounted } from "vue";
+  import { productList } from "@/api/salesManagement/salesLedger";
+
+  // 瀹㈡埛淇℃伅
+  const supplierId = ref("");
+
+  // 琛ㄦ牸鏁版嵁
+  const tableData = ref([]);
+
+  // 杩斿洖涓婁竴椤�
+  const goBack = () => {
+    uni.removeStorageSync("supplierId");
+    uni.navigateBack();
+  };
+  const getShippingStatusType = row => {
+    // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
+    if (row.shippingDate || row.shippingCarNumber) {
+      return "success";
+    }
+
+    // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+    const status = row.shippingStatus;
+
+    // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
+    if (status === null || status === undefined || status === "") {
+      return "info";
+    }
+
+    // 鐘舵�佹槸瀛楃涓�
+    const statusStr = String(status).trim();
+    const typeTextMap = {
+      寰呭彂璐�: "info",
+      寰呭鏍�: "info",
+      瀹℃牳涓�: "warning",
+      瀹℃牳鎷掔粷: "danger",
+      瀹℃牳閫氳繃: "success",
+      宸插彂璐�: "success",
+    };
+    return typeTextMap[statusStr] || "info";
+  };
+  const getShippingStatusText = row => {
+    // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
+    if (row.shippingDate || row.shippingCarNumber) {
+      return "宸插彂璐�";
+    }
+
+    // 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+    const status = row.shippingStatus;
+
+    // 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
+    if (status === null || status === undefined || status === "") {
+      return "寰呭彂璐�";
+    }
+
+    // 鐘舵�佹槸瀛楃涓�
+    const statusStr = String(status).trim();
+    const statusTextMap = {
+      寰呭彂璐�: "寰呭彂璐�",
+      寰呭鏍�: "寰呭鏍�",
+      瀹℃牳涓�: "瀹℃牳涓�",
+      瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
+      瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
+      宸插彂璐�: "宸插彂璐�",
+    };
+    return statusTextMap[statusStr] || "寰呭彂璐�";
+  };
+  // 鑾峰彇椤甸潰鍙傛暟
+  const getPageParams = () => {
+    // 浠庢湰鍦板瓨鍌ㄨ幏鍙栦緵搴斿晢ID
+    const storedSupplierId = uni.getStorageSync("supplierId");
+    if (storedSupplierId) {
+      supplierId.value = storedSupplierId;
+    }
+  };
+  const goout = item => {
+    uni.setStorageSync("goOutData", JSON.stringify(item));
+    uni.navigateTo({
+      url: "/pages/sales/salesAccount/goOut",
+    });
+  };
+
+  // 鏌ヨ鍒楄〃
+  const getList = () => {
+    showLoadingToast("鍔犺浇涓�...");
+    productList({
+      salesLedgerId: outData.value.id,
+      type: 1,
+    })
+      .then(res => {
+        tableData.value = res.data;
+        closeToast();
+      })
+      .catch(() => {
+        closeToast();
+        uni.showToast({
+          title: "鏌ヨ澶辫触",
+          icon: "error",
+        });
+      });
+  };
+  const canShip = row => {
+    // 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
+    if (row.approveStatus !== 1) {
+      return false;
+    }
+
+    // 鑾峰彇鍙戣揣鐘舵��
+    const shippingStatus = row.shippingStatus;
+
+    // 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
+    if (row.shippingDate || row.shippingCarNumber) {
+      return false;
+    }
+
+    // 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
+    const statusStr = shippingStatus ? String(shippingStatus).trim() : "";
+    return statusStr === "寰呭彂璐�" || statusStr === "瀹℃牳鎷掔粷";
+  };
+
+  // 鏄剧ず鍔犺浇鎻愮ず
+  const showLoadingToast = message => {
+    uni.showLoading({
+      title: message,
+      mask: true,
+    });
+  };
+
+  // 鍏抽棴鎻愮ず
+  const closeToast = () => {
+    uni.hideLoading();
+  };
+  const outData = ref({});
+
+  onMounted(() => {
+    // 椤甸潰鍔犺浇鏃惰幏鍙栧弬鏁板苟鍒锋柊鍒楄〃
+    getPageParams();
+    // 浠庢湰鍦板瓨鍌ㄨ幏鍙栧彂璐х姸鎬佹暟鎹�
+    outData.value = JSON.parse(uni.getStorageSync("outData"));
+    getList();
+  });
+</script>
+
+<style scoped lang="scss">
+  .receipt-payment-detail {
+    min-height: 100vh;
+    background: #f8f9fa;
+    position: relative;
+  }
+
+  .u-divider {
+    margin: 0 !important;
+  }
+
+  .summary-info {
+    background: #ffffff;
+    margin: 20px 20px 0 20px;
+    border-radius: 12px;
+    padding: 16px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+  }
+
+  .summary-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 8px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
+  .summary-label {
+    font-size: 14px;
+    color: #666;
+  }
+
+  .summary-value {
+    font-size: 14px;
+    color: #333;
+    font-weight: 500;
+  }
+
+  .summary-value.highlight {
+    color: #2979ff;
+    font-weight: 600;
+  }
+
+  .summary-value.danger {
+    color: #ff4757;
+    font-weight: 600;
+  }
+
+  .detail-list {
+    padding: 20px;
+  }
+
+  .detail-item {
+    background: #ffffff;
+    border-radius: 12px;
+    margin-bottom: 16px;
+    overflow: hidden;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
+    padding: 0 16px;
+  }
+
+  .item-header {
+    padding: 10px 0;
+    display: flex;
+    align-items: center;
+    justify-content: space-between;
+  }
+
+  .item-left {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
+
+  .record-icon {
+    width: 24px;
+    height: 24px;
+    background: #2979ff;
+    border-radius: 4px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .item-index {
+    font-size: 14px;
+    color: #333;
+    font-weight: 500;
+  }
+
+  .item-date {
+    font-size: 12px;
+    color: #666;
+  }
+
+  .item-details {
+    padding: 16px 0;
+  }
+
+  .detail-row {
+    display: flex;
+    align-items: flex-end;
+    justify-content: space-between;
+    margin-bottom: 8px;
+
+    &:last-child {
+      margin-bottom: 0;
+    }
+  }
+
+  .detail-label {
+    font-size: 12px;
+    color: #777777;
+    min-width: 60px;
+  }
+
+  .detail-value {
+    font-size: 12px;
+    color: #000000;
+    text-align: right;
+    flex: 1;
+    margin-left: 16px;
+  }
+
+  .detail-value.highlight {
+    color: #2979ff;
+    font-weight: 500;
+  }
+
+  .detail-value.danger {
+    color: #ff4757;
+    font-weight: 500;
+  }
+
+  .no-data {
+    padding: 40px 0;
+    text-align: center;
+    color: #999;
+  }
+</style>

--
Gitblit v1.9.3