From 01975cbdf4d8c738d9f92a8a16396d98d25147e8 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 26 一月 2026 09:06:34 +0800
Subject: [PATCH] 进销存升级 1.财务报表页面样式修改

---
 src/assets/icons/png/circleYellow@2x.png                    |    0 
 src/views/salesManagement/deliveryLedger/index.vue          |  310 +++++
 src/assets/icons/png/circleOrange@2x.png                    |    0 
 src/assets/icons/png/walletGreen@2x.png                     |    0 
 src/views/collaborativeApproval/approvalProcess/index.vue   |   24 
 src/assets/icons/png/walletOrange@2x.png                    |    0 
 src/views/salesManagement/salesLedger/index.vue             | 2132 +++++++++++++++++++++------------------
 src/assets/icons/png/circleRed@2x.png                       |    0 
 src/assets/icons/png/circleBlue@2x.png                      |    0 
 src/assets/icons/png/walletRed@2x.png                       |    0 
 src/views/salesManagement/invoiceLedger/index.vue           |   18 
 src/assets/icons/png/walletBlue@2x.png                      |    0 
 src/assets/icons/png/circleGreen@2x.png                     |    0 
 src/assets/icons/png/walletYellow@2x.png                    |    0 
 src/views/financialManagement/financialStatements/index.vue |  747 ++++++++++---
 15 files changed, 2,018 insertions(+), 1,213 deletions(-)

diff --git a/src/assets/icons/png/circleBlue@2x.png b/src/assets/icons/png/circleBlue@2x.png
new file mode 100644
index 0000000..55811dc
--- /dev/null
+++ b/src/assets/icons/png/circleBlue@2x.png
Binary files differ
diff --git a/src/assets/icons/png/circleGreen@2x.png b/src/assets/icons/png/circleGreen@2x.png
new file mode 100644
index 0000000..a1505a7
--- /dev/null
+++ b/src/assets/icons/png/circleGreen@2x.png
Binary files differ
diff --git a/src/assets/icons/png/circleOrange@2x.png b/src/assets/icons/png/circleOrange@2x.png
new file mode 100644
index 0000000..ba6807d
--- /dev/null
+++ b/src/assets/icons/png/circleOrange@2x.png
Binary files differ
diff --git a/src/assets/icons/png/circleRed@2x.png b/src/assets/icons/png/circleRed@2x.png
new file mode 100644
index 0000000..3d9a33c
--- /dev/null
+++ b/src/assets/icons/png/circleRed@2x.png
Binary files differ
diff --git a/src/assets/icons/png/circleYellow@2x.png b/src/assets/icons/png/circleYellow@2x.png
new file mode 100644
index 0000000..7b873a0
--- /dev/null
+++ b/src/assets/icons/png/circleYellow@2x.png
Binary files differ
diff --git a/src/assets/icons/png/walletBlue@2x.png b/src/assets/icons/png/walletBlue@2x.png
new file mode 100644
index 0000000..e0dc792
--- /dev/null
+++ b/src/assets/icons/png/walletBlue@2x.png
Binary files differ
diff --git a/src/assets/icons/png/walletGreen@2x.png b/src/assets/icons/png/walletGreen@2x.png
new file mode 100644
index 0000000..c68f20f
--- /dev/null
+++ b/src/assets/icons/png/walletGreen@2x.png
Binary files differ
diff --git a/src/assets/icons/png/walletOrange@2x.png b/src/assets/icons/png/walletOrange@2x.png
new file mode 100644
index 0000000..aacddc3
--- /dev/null
+++ b/src/assets/icons/png/walletOrange@2x.png
Binary files differ
diff --git a/src/assets/icons/png/walletRed@2x.png b/src/assets/icons/png/walletRed@2x.png
new file mode 100644
index 0000000..cd45c0b
--- /dev/null
+++ b/src/assets/icons/png/walletRed@2x.png
Binary files differ
diff --git a/src/assets/icons/png/walletYellow@2x.png b/src/assets/icons/png/walletYellow@2x.png
new file mode 100644
index 0000000..9d828cf
--- /dev/null
+++ b/src/assets/icons/png/walletYellow@2x.png
Binary files differ
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index 5ce951d..00e59c9 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -8,7 +8,7 @@
       <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-tab-pane label="鍙戣揣瀹℃壒" name="7"></el-tab-pane>
     </el-tabs>
     
     <div class="search_form">
@@ -35,9 +35,18 @@
         >
       </div>
       <div>
-        <el-button type="primary" @click="openForm('add')" v-if="currentApproveType !== 6">鏂板</el-button>
+        <el-button
+          type="primary"
+          @click="openForm('add')"
+          v-if="currentApproveType !== 6 && currentApproveType !== 7"
+        >鏂板</el-button>
         <el-button @click="handleOut">瀵煎嚭</el-button>
-        <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+        <el-button
+          type="danger"
+          plain
+          @click="handleDelete"
+          v-if="currentApproveType !== 7"
+        >鍒犻櫎</el-button>
       </div>
     </div>
     <div class="table_list">
@@ -205,7 +214,12 @@
         clickFun: (row) => {
           openForm("edit", row);
         },
-        disabled: (row) => currentApproveType.value === 6 || row.approveStatus == 2 || row.approveStatus == 1 || row.approveStatus == 4
+        disabled: (row) =>
+          currentApproveType.value === 6 ||
+          currentApproveType.value === 7 ||
+          row.approveStatus == 2 ||
+          row.approveStatus == 1 ||
+          row.approveStatus == 4
       },
       {
         name: "瀹℃牳",
@@ -294,7 +308,7 @@
     4: "鎶ラ攢绠$悊瀹℃壒琛�",
     5: "閲囪喘鐢宠瀹℃壒琛�",
     6: "鎶ヤ环瀹℃壒琛�",
-    7: "鍑哄簱瀹℃壒琛�",
+    7: "鍙戣揣瀹℃壒琛�",
   }
   const fileName = nameMap[type] || nameMap[0]
   proxy.download(url, {}, `${fileName}.xlsx`)
diff --git a/src/views/financialManagement/financialStatements/index.vue b/src/views/financialManagement/financialStatements/index.vue
index 88aa5d2..cf4eee5 100644
--- a/src/views/financialManagement/financialStatements/index.vue
+++ b/src/views/financialManagement/financialStatements/index.vue
@@ -28,103 +28,135 @@
     
     <main class="container mx-auto px-4 pb-10">
       <!-- 璐㈠姟鎸囨爣鍗$墖 -->
-      <div class="grid-container">
-        <!-- 鎬绘敹鍏� -->
-        <el-card class="bg1">
-          <p>鎬绘敹鍏�</p>
-          <h3>
-            楼{{ pageInfo.totalIncome }}
-          </h3>
-        </el-card>
-        
-        <!-- 鏀跺叆绗旀暟 -->
-        <el-card class="bg2">
-          <p>鏀跺叆绗旀暟</p>
-          <h3>
-            {{ pageInfo.incomeNumber }}
-          </h3>
-        </el-card>
+      <div class="stats-cards">
+        <!-- 鎬昏惀鏀� -->
+        <div class="stat-card stat-card-blue">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletBlue@2x.png" alt="鎬昏惀鏀�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬昏惀鏀�</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.totalIncome || 0) }} 鍏�</div>
+          </div>
+        </div>
         
         <!-- 鎬绘敮鍑� -->
-        <el-card class="bg3">
-          <p>鎬绘敮鍑�</p>
-          <h3>
-            楼{{ pageInfo.totalExpense }}
-          </h3>
-        </el-card>
+        <div class="stat-card stat-card-orange">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletOrange@2x.png" alt="鎬绘敮鍑�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬绘敮鍑�</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.totalExpense || 0) }} 鍏�</div>
+          </div>
+        </div>
         
-        <!-- 鏀嚭绗旀暟 -->
-        <el-card class="bg4">
-          <p>鏀嚭绗旀暟</p>
-          <h3>
-            {{ pageInfo.expenseNumber }}
-          </h3>
-        </el-card>
+        <!-- 鎬绘敹鍏ョ瑪鏁� -->
+        <div class="stat-card stat-card-green">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletGreen@2x.png" alt="鎬绘敹鍏ョ瑪鏁�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬绘敹鍏ョ瑪鏁�</div>
+            <div class="stat-value">{{ pageInfo.incomeNumber || 0 }} 绗�</div>
+          </div>
+        </div>
+        
+        <!-- 鎬绘敮鍑虹瑪鏁� -->
+        <div class="stat-card stat-card-red">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletRed@2x.png" alt="鎬绘敮鍑虹瑪鏁�" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鎬绘敮鍑虹瑪鏁�</div>
+            <div class="stat-value">{{ pageInfo.expenseNumber || 0 }} 绗�</div>
+          </div>
+        </div>
         
         <!-- 鍑�鏀跺叆 -->
-        <el-card class="bg5">
-          <p>鍑�鏀跺叆</p>
-          <h3>
-            楼{{ pageInfo.netRevenue }}
-          </h3>
+        <div class="stat-card stat-card-yellow">
+          <div class="stat-icon">
+            <img src="@/assets/icons/png/walletYellow@2x.png" alt="鍑�鏀跺叆" />
+          </div>
+          <div class="stat-content">
+            <div class="stat-label">鍑�鏀跺叆</div>
+            <div class="stat-value">{{ formatMoney(pageInfo.netRevenue || 0) }} 鍏�</div>
+          </div>
+        </div>
+      </div>
+      
+      <!-- 涓棿鍥捐〃鍖哄煙 -->
+      <div class="charts-row">
+        <!-- 宸︿晶锛氭敹鍏ユ敮鍑哄垎鏋� -->
+        <el-card class="chart-card">
+          <h2 class="section-title">鏀跺叆鏀嚭鍒嗘瀽</h2>
+          <div class="pie-chart-container">
+            <Echarts 
+              :legend="pieLegendIncomeExpense" 
+              :chartStyle="chartStylePie"
+              :series="pieSeriesIncomeExpense"
+              :tooltip="pieTooltipIncomeExpense" 
+              style="height: 320px; width: 100%;">
+            </Echarts>
+            <div class="pie-stats">
+              <div class="bar-stat-item">
+                <span class="bar-stat-label">鏀跺叆鏁伴噺</span>
+                <span class="bar-stat-value">{{ pageInfo.incomeNumber || 0 }}</span>
+              </div>
+              <div class="bar-stat-item">
+                <span class="bar-stat-label">鏀嚭鏁伴噺</span>
+                <span class="bar-stat-value">{{ pageInfo.expenseNumber || 0 }}</span>
+              </div>
+            </div>
+          </div>
+        </el-card>
+        
+        <!-- 鍙充晶锛氳椤圭泩鍒╁垎鏋� -->
+        <el-card class="chart-card">
+          <h2 class="section-title">琛岄」鐩堝埄鍒嗘瀽</h2>
+          <div class="bar-chart-header">
+            <div class="bar-stat-item">
+              <span class="bar-stat-label">褰撳墠鎬讳釜鏁�</span>
+              <span class="bar-stat-value">{{ allBarTypes.value?.length || 0 }}</span>
+            </div>
+            <div class="bar-stat-item">
+              <span class="bar-stat-label">鏀嚭閲戦</span>
+              <span class="bar-stat-value">{{ formatMoney(pageInfo.totalExpense || 0) }}</span>
+            </div>
+            <div class="bar-stat-item">
+              <span class="bar-stat-label">鏀跺叆閲戦</span>
+              <span class="bar-stat-value">{{ formatMoney(pageInfo.totalIncome || 0) }}</span>
+            </div>
+          </div>
+          <Echarts 
+            ref="barChart"
+            :chartStyle="chartStyle"
+            :grid="barGrid"
+            :legend="barLegend"
+            :series="barSeries"
+            :tooltip="barTooltip"
+            :xAxis="barXAxis"
+            :yAxis="barYAxis"
+            style="height: 300px; width: 100%;">
+          </Echarts>
         </el-card>
       </div>
       
-      <!-- 鏀跺叆缁熻鍥捐〃 -->
-      <div class="grid-layout">
-        <el-card style="margin-bottom: 20px;">
-          <h2 class="section-title">鏀跺叆缁熻(鍏�)</h2>
-          <div class="echarts">
-            <Echarts :legend="pieLegend0" :chartStyle="chartStylePie"
-										 :series="materialPieSeries0"
-										 :tooltip="pieTooltip" style="height: 260px;width: 35%;">
-                     <div class="chart-num">
-                      <span style="font-size: 22px;">鏀跺叆</span>
-                      <span style="font-size: 36px;
-    font-weight: 500;
-    font-family: 'MyCustomFont', sans-serif;">{{ pageInfo.totalIncome }}</span>
-                     </div>
-                    </Echarts>
-            <Echarts ref="chart"
-								 :chartStyle="chartStyle"
-								 :grid="grid"
-								 :legend="lineLegend"
-								 :series="lineSeries0"
-								 :tooltip="tooltip"
-								 :xAxis="xAxis0"
-								 :yAxis="yAxis0"
-								 style="height: 260px;width: 64%;"></Echarts>
-          </div>
-        </el-card>
-        
-        <!-- 鏀嚭缁熻鍥捐〃 -->
-        <el-card>
-          <h2 class="section-title">鏀嚭缁熻(鍏�)</h2>
-          <div class="echarts">
-            <Echarts ref="chart" 
-                    :legend="pieLegend1" 
-                    :chartStyle="chartStylePie"
-										 :series="materialPieSeries1"
-										 :tooltip="pieTooltip" 
-                     style="height: 260px;width: 35%;">
-                     <div class="chart-num">
-                      <span style="font-size: 22px;">鏀嚭</span>
-                      <span style="font-size: 36px;
-    font-weight: 500;
-    font-family: 'MyCustomFont', sans-serif;">{{ pageInfo.totalExpense }}</span>
-                     </div></Echarts>
-            <Echarts ref="chart"
-								 :chartStyle="chartStyle"
-								 :grid="grid"
-								 :legend="lineLegend"
-								 :series="lineSeries1"
-								 :tooltip="tooltip"
-								 :xAxis="xAxis1"
-								 :yAxis="yAxis1"
-								 style="height: 260px;width: 64%;"></Echarts>
-          </div>
-        </el-card>
-      </div>
+      <!-- 搴曢儴锛氳惀鏀惰秼鍔垮垎鏋� -->
+      <el-card class="trend-chart-card">
+        <h2 class="section-title">钀ユ敹瓒嬪娍鍒嗘瀽</h2>
+        <Echarts 
+          ref="trendChart"
+          :chartStyle="chartStyle"
+          :grid="grid"
+          :legend="trendLegend"
+          :series="trendSeries"
+          :tooltip="tooltip"
+          :xAxis="xAxis0"
+          :yAxis="trendYAxis"
+          style="height: 350px; width: 100%;">
+        </Echarts>
+      </el-card>
     </main>
   </div>
 </template>
@@ -334,6 +366,262 @@
 const pageInfo = ref({
 })
 
+// 鏍煎紡鍖栭噾棰�
+const formatMoney = (value) => {
+  if (!value && value !== 0) return '0';
+  return Number(value).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
+};
+
+// 鏀跺叆鏀嚭鍒嗘瀽楗煎浘
+const pieDataIncomeExpense = computed(() => {
+  const totalIncome = Number(pageInfo.value.totalIncome) || 0;
+  const totalExpense = Number(pageInfo.value.totalExpense) || 0;
+  const total = totalIncome + totalExpense;
+  if (total === 0) {
+    return [
+      { name: '鏀跺叆', value: 0, percent: '0%' },
+      { name: '鏀嚭', value: 0, percent: '0%' }
+    ];
+  }
+  const incomePercent = ((totalIncome / total) * 100).toFixed(0);
+  const expensePercent = ((totalExpense / total) * 100).toFixed(0);
+  return [
+    { name: '鏀跺叆', value: totalIncome, percent: `${incomePercent}%` },
+    { name: '鏀嚭', value: totalExpense, percent: `${expensePercent}%` }
+  ];
+});
+
+const pieLegendIncomeExpense = computed(() => ({
+  show: false
+}));
+
+const pieTooltipIncomeExpense = reactive({
+  trigger: 'item',
+  formatter: function(params) {
+    if (!params.data) return params.name;
+    return `${params.name}鍗犳瘮 ${params.percent}%`;
+  }
+});
+
+const pieSeriesIncomeExpense = computed(() => [
+  {
+    type: 'pie',
+    radius: ['0%', '70%'],
+    center: ['50%', '50%'],
+    avoidLabelOverlap: true,
+    itemStyle: {
+      borderColor: '#fff',
+      borderWidth: 2
+    },
+    label: {
+      show: true,
+      position: 'outside',
+      formatter: function(params) {
+        return `${params.name}鍗犳瘮 ${params.percent}%`;
+      },
+      fontSize: 14,
+      color: '#333'
+    },
+    labelLine: {
+      show: true,
+      length: 15,
+      length2: 10,
+      lineStyle: {
+        color: '#333'
+      }
+    },
+    emphasis: {
+      label: {
+        show: true,
+        fontSize: 16,
+        fontWeight: 'bold'
+      }
+    },
+    data: pieDataIncomeExpense.value,
+    color: ['#1890FF', '#FACC14']
+  }
+]);
+
+// 琛岄」鐩堝埄鍒嗘瀽鏌辩姸鍥�
+const barXAxis = computed(() => {
+  return [{
+    type: 'category',
+    data: (allBarTypes.value && allBarTypes.value.length > 0) ? allBarTypes.value : ['椤圭洰1', '椤圭洰2', '椤圭洰3', '椤圭洰4', '椤圭洰5', '椤圭洰6', '椤圭洰7'],
+    axisTick: { show: true, alignWithLabel: true },
+  }];
+});
+
+const barYAxis = [{
+  type: 'value',
+  name: '鍗曚綅: 鍏�',
+  position: 'left',
+  min: 0,
+  nameTextStyle: {
+    color: '#000',
+    fontSize: 14,
+  },
+}];
+
+const barGrid = {
+  left: '3%',
+  right: '4%',
+  bottom: '3%',
+  containLabel: true
+};
+
+const barLegend = {
+  show: true,
+  top: 10,
+  right: 10,
+};
+
+// 鑾峰彇鎵�鏈夌被鍨嬪悕绉�
+const allBarTypes = computed(() => {
+  const incomeTypes = (lineSeries0.value || []).map(item => item.name || item.typeName).filter(Boolean);
+  const expenseTypes = (lineSeries1.value || []).map(item => item.name || item.typeName).filter(Boolean);
+  return [...new Set([...incomeTypes, ...expenseTypes])];
+});
+
+const barSeries = computed(() => {
+  if (allBarTypes.value.length === 0) {
+    return [
+      {
+        name: '鏀嚭',
+        type: 'bar',
+        data: [],
+        itemStyle: { color: '#1890FF' }
+      },
+      {
+        name: '鏀跺叆',
+        type: 'bar',
+        data: [],
+        itemStyle: { color: '#13C2C2' }
+      }
+    ];
+  }
+  
+  // 璁$畻姣忎釜椤圭洰鐨勬�绘敹鍏ワ紙姹囨�绘墍鏈夋湀浠斤級
+  const incomeData = allBarTypes.value.map(typeName => {
+    const incomeItem = (lineSeries0.value || []).find(item => (item.name || item.typeName) === typeName);
+    if (incomeItem && incomeItem.data && Array.isArray(incomeItem.data)) {
+      return incomeItem.data.reduce((sum, val) => sum + (Number(val) || 0), 0);
+    }
+    return 0;
+  });
+  
+  // 璁$畻姣忎釜椤圭洰鐨勬�绘敮鍑猴紙姹囨�绘墍鏈夋湀浠斤級
+  const expenseData = allBarTypes.value.map(typeName => {
+    const expenseItem = (lineSeries1.value || []).find(item => (item.name || item.typeName) === typeName);
+    if (expenseItem && expenseItem.data && Array.isArray(expenseItem.data)) {
+      return expenseItem.data.reduce((sum, val) => sum + (Number(val) || 0), 0);
+    }
+    return 0;
+  });
+  
+  return [
+    {
+      name: '鏀嚭',
+      type: 'bar',
+      data: expenseData,
+      itemStyle: { color: '#1890FF' }
+    },
+    {
+      name: '鏀跺叆',
+      type: 'bar',
+      data: incomeData,
+      itemStyle: { color: '#13C2C2' }
+    }
+  ];
+});
+
+const barTooltip = reactive({
+  trigger: 'axis',
+  axisPointer: {
+    type: 'shadow'
+  },
+  formatter: function (params) {
+    if (!params || !params.length) return '';
+    const axisLabel = params[0].axisValueLabel || params[0].axisValue || '';
+    const rows = params
+      .map(p => {
+        const colorDot = `<span style="display:inline-block;margin-right:6px;width:8px;height:8px;border-radius:50%;background:${p.color}"></span>`;
+        const value = typeof p.value === 'number' ? p.value.toFixed(2) : p.value;
+        return `${colorDot}${p.seriesName} ${value}`;
+      })
+      .join('<br/>');
+    return `<div>${axisLabel}</div><div>${rows}</div>`;
+  }
+});
+
+// 钀ユ敹瓒嬪娍鍒嗘瀽
+const trendLegend = {
+  show: true,
+  top: 10,
+  right: 10,
+};
+
+const trendYAxis = [{
+  type: 'value',
+  name: '鍗曚綅: 鍏�',
+  position: 'left',
+  min: 0,
+  nameTextStyle: {
+    color: '#000',
+    fontSize: 14,
+  },
+}];
+
+const trendSeries = computed(() => {
+  // 姹囨�绘墍鏈夋敮鍑虹被鍨嬬殑鏁版嵁
+  let expenseTrend = [];
+  if (lineSeries1.value.length > 0) {
+    const monthCount = Math.max(...lineSeries1.value.map(item => item.data?.length || 0));
+    expenseTrend = Array(monthCount).fill(0);
+    lineSeries1.value.forEach(item => {
+      if (item.data && Array.isArray(item.data)) {
+        item.data.forEach((val, index) => {
+          if (index < monthCount) {
+            expenseTrend[index] += Number(val) || 0;
+          }
+        });
+      }
+    });
+  }
+  
+  // 姹囨�绘墍鏈夋敹鍏ョ被鍨嬬殑鏁版嵁
+  let incomeTrend = [];
+  if (lineSeries0.value.length > 0) {
+    const monthCount = Math.max(...lineSeries0.value.map(item => item.data?.length || 0));
+    incomeTrend = Array(monthCount).fill(0);
+    lineSeries0.value.forEach(item => {
+      if (item.data && Array.isArray(item.data)) {
+        item.data.forEach((val, index) => {
+          if (index < monthCount) {
+            incomeTrend[index] += Number(val) || 0;
+          }
+        });
+      }
+    });
+  }
+  
+  return [
+    {
+      name: '鏀嚭',
+      type: 'line',
+      data: expenseTrend,
+      itemStyle: { color: '#1890FF' },
+      smooth: true
+    },
+    {
+      name: '鏀跺叆',
+      type: 'line',
+      data: incomeTrend,
+      itemStyle: { color: '#13C2C2' },
+      smooth: true
+    }
+  ];
+});
+
 // 鑾峰彇鏈�杩戝叚涓湀鐨勮寖鍥�
 const getLastSixMonths = () => {
   const endMonth = dayjs().format('YYYY-MM');
@@ -487,111 +775,220 @@
 :root {
   --el-color-primary: #4f46e5;
 }
-.el-card{
-  position: relative;
-  border-radius: 12px;
-  padding: 14px 10px 10px 10px;
-  box-shadow: 0 2px 8px #eee;
-  :deep(.el-card__body){
-    padding: 10px 20px !important;
-  }
-  &.bg1{
-    background: url(@/assets/icons/png/1.png) no-repeat 100% 100% !important;
-  }
-  &.bg2{
-    background: url(@/assets/icons/png/2.png) no-repeat 100% 100% !important;
-  }
-  &.bg3{
-    background: url(@/assets/icons/png/3.png) no-repeat 100% 100% !important;
-  }
-  &.bg4{
-    background: url(@/assets/icons/png/4.png) no-repeat 100% 100% !important;
-  }
-  &.bg5{
-    background: url(@/assets/icons/png/5.png) no-repeat 100% 100% !important;
-  }
-}
 
-.grid-container {
-  /* grid 瀹瑰櫒鍩虹鏍峰紡 */
+/* 缁熻鍗$墖鏍峰紡 */
+.stats-cards {
   display: grid;
-  gap: 1rem; /* gap-4 瀵瑰簲 1rem (16px) */
-  margin-bottom: 2rem; /* mb-8 瀵瑰簲 2rem (32px) */
+  grid-template-columns: repeat(5, 1fr);
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.stat-card {
+  background: #fff;
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  padding: 20px;
+  display: flex;
+  align-items: center;
+  gap: 15px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  transition: all 0.3s;
   
-  p{
-    font-size: 22px;
-    margin-top: 0px;
-    color: #fff;
-  }
-  h3{
-    font-size: 36px;
-    font-weight: 500;
-    font-family: 'MyCustomFont', sans-serif;
-    margin: 10px 0;
-    color: #fff;
+  &:hover {
+    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+    transform: translateY(-2px);
   }
   
-}
-
-/* 绉诲姩绔粯璁ゆ牱寮� (grid-cols-1) */
-.grid-container {
-  grid-template-columns: repeat(1, minmax(0, 1fr));
-}
-
-/* 灏忓睆骞曞強浠ヤ笂 (sm:grid-cols-2) */
-@media (min-width: 640px) {
-  .grid-container {
-    grid-template-columns: repeat(2, minmax(0, 1fr));
+  .stat-icon {
+    width: 48px;
+    height: 48px;
+    flex-shrink: 0;
+    
+    img {
+      width: 100%;
+      height: 100%;
+      object-fit: contain;
+    }
+  }
+  
+  .stat-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+  }
+  
+  .stat-label {
+    font-size: 14px;
+    color: #666;
+    line-height: 1.2;
+  }
+  
+  .stat-value {
+    font-size: 24px;
+    font-weight: 600;
+    color: #333;
+    line-height: 1.2;
+  }
+  
+  .stat-trend {
+    font-size: 12px;
+    line-height: 1.2;
+    
+    &.trend-up {
+      color: #f56c6c;
+    }
+    
+    &.trend-down {
+      color: #67c23a;
+    }
   }
 }
 
-/* 澶у睆骞曞強浠ヤ笂 (lg:grid-cols-5) */
-@media (min-width: 1024px) {
-  .grid-container {
-    grid-template-columns: repeat(5, minmax(0, 1fr));
+/* 鍥捐〃琛屽竷灞� */
+.charts-row {
+  display: grid;
+  grid-template-columns: 1fr 1fr;
+  gap: 20px;
+  margin-bottom: 20px;
+}
+
+.chart-card {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  
+  :deep(.el-card__body) {
+    padding: 20px !important;
   }
 }
 
-/* 鍗$墖鎮仠鏁堟灉澧炲己 */
-.el-card:hover {
-  transform: translateY(-2px);
+.trend-chart-card {
+  border: 1px solid #e4e7ed;
+  border-radius: 8px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  
+  :deep(.el-card__body) {
+    padding: 20px !important;
+  }
 }
-.echarts{
+
+/* 楗煎浘瀹瑰櫒 */
+.pie-chart-container {
+  position: relative;
+  
+  .pie-stats {
+    display: flex;
+    justify-content: space-between;
+    gap: 20px;
+    margin-top: 20px;
+    
+    .bar-stat-item {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+      gap: 8px;
+      padding: 15px;
+      background: #f5f7fa;
+      border-radius: 6px;
+      flex: 1;
+      
+      .bar-stat-label {
+        font-size: 14px;
+        color: #666;
+      }
+      
+      .bar-stat-value {
+        font-size: 18px;
+        font-weight: 600;
+        color: #333;
+      }
+    }
+  }
+}
+
+/* 鏌辩姸鍥惧ご閮ㄧ粺璁� */
+.bar-chart-header {
   display: flex;
   justify-content: space-between;
+  gap: 20px;
+  margin-bottom: 20px;
+  
+  .bar-stat-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    gap: 8px;
+    padding: 15px;
+    background: #f5f7fa;
+    border-radius: 6px;
+    flex: 1;
+    
+    .bar-stat-label {
+      font-size: 14px;
+      color: #666;
+    }
+    
+    .bar-stat-value {
+      font-size: 18px;
+      font-weight: 600;
+      color: #333;
+    }
+  }
 }
 
-/* 鍥捐〃瀹瑰櫒鏍峰紡 */
-.el-chart {
-  width: 100%;
-  height: 100%;
-}
+/* 鏍囬鏍峰紡 */
 .section-title {
-	position: relative;
-	font-size: 18px;
-	color: #333;
-	padding-left: 10px;
-	margin-bottom: 10px;
-	font-weight: 700;
+  position: relative;
+  font-size: 18px;
+  color: #333;
+  padding-left: 12px;
+  margin-bottom: 20px;
+  font-weight: 700;
+  
+  &::before {
+    position: absolute;
+    left: 0;
+    top: 2px;
+    content: '';
+    width: 4px;
+    height: 18px;
+    background-color: #002FA7;
+    border-radius: 2px;
+  }
 }
 
-.section-title::before {
-	position: absolute;
-	left: 0;
-	top: 0px;
-	content: '';
-	width: 4px;
-	height: 18px;
-	background-color: #002FA7;
-	border-radius: 2px;
+/* 鍝嶅簲寮忚璁� */
+@media (max-width: 1400px) {
+  .stats-cards {
+    grid-template-columns: repeat(3, 1fr);
+  }
 }
-.chart-num{
-  position: absolute;
-  z-index: 3;
-  top: 92px;
-  left: 92px;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
+
+@media (max-width: 1024px) {
+  .stats-cards {
+    grid-template-columns: repeat(2, 1fr);
+  }
+  
+  .charts-row {
+    grid-template-columns: 1fr;
+  }
+}
+
+@media (max-width: 640px) {
+  .stats-cards {
+    grid-template-columns: 1fr;
+  }
 }
 </style>
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index d838924..7b94a29 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -3,11 +3,15 @@
     <div class="search_form">
       <el-form :model="searchForm" :inline="true">
         <el-form-item label="閿�鍞鍗曞彿锛�">
-          <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+          <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search" style="width: 200px"
             @change="handleQuery" />
         </el-form-item>
         <el-form-item label="杞︾墝鍙凤細">
-          <el-input v-model="searchForm.shippingCarNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+          <el-input v-model="searchForm.shippingCarNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search" style="width: 200px"
+            @change="handleQuery" />
+        </el-form-item>
+        <el-form-item label="蹇�掑崟鍙凤細">
+          <el-input v-model="searchForm.expressNumber" placeholder="璇疯緭鍏�" clearable prefix-icon="Search" style="width: 200px"
             @change="handleQuery" />
         </el-form-item>
         <el-form-item>
@@ -24,13 +28,15 @@
         </div>
       </div>
       <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
-        :row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 18.5em)">
+        :row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)">
         <el-table-column align="center" type="selection" width="55" />
         <el-table-column align="center" label="搴忓彿" type="index" width="60" />
         <el-table-column label="閿�鍞鍗�" prop="salesContractNo" show-overflow-tooltip />
         <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip />
         <el-table-column label="鍙戣揣鏃堕棿" prop="shippingDate" show-overflow-tooltip />
         <el-table-column label="鍙戣揣杞︾墝鍙�" prop="shippingCarNumber" show-overflow-tooltip />
+        <el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip />
+        <el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip />
         <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
           <template #default="scope">
             <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">缂栬緫</el-button>
@@ -41,61 +47,123 @@
       <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
         :page="page.current" :limit="page.size" @pagination="paginationChange" />
     </div>
-    <FormDialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板鍙戣揣鍙拌处' : '缂栬緫鍙戣揣鍙拌处'" :width="'50%'"
-      :operation-type="operationType" @close="closeDia" @confirm="submitForm" @cancel="closeDia">
+    <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板鍙戣揣鍙拌处' : '缂栬緫鍙戣揣鍙拌处'" width="40%"
+      @close="closeDia">
       <el-form :model="form" label-width="120px" label-position="top" :rules="rules" ref="formRef">
         <el-row :gutter="30">
           <el-col :span="24">
-            <el-form-item label="閿�鍞鍗曪細" prop="salesContractNo">
-              <el-select v-model="form.salesContractNo" placeholder="璇烽�夋嫨" clearable filterable 
-                @change="handleSalesOrderChange" style="width: 100%" :disabled="operationType === 'edit'">
-                <el-option v-for="item in salesOrderOptions" :key="item.salesContractNo" 
-                  :label="item.salesContractNo" :value="item.salesContractNo">
-                  {{ item.salesContractNo + ' - ' + item.customerName }}
-                </el-option>
+            <el-form-item label="鍙戣揣绫诲瀷锛�" prop="type">
+              <el-select
+                v-model="form.type"
+                placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
+                style="width: 100%"
+                @change="handleShippingTypeChange"
+              >
+                <el-option label="璐ц溅" value="璐ц溅" />
+                <el-option label="蹇��" value="蹇��" />
               </el-select>
             </el-form-item>
           </el-col>
         </el-row>
         <el-row :gutter="30">
           <el-col :span="24">
-            <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerName">
-              <el-input v-model="form.customerName" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'edit'" />
+            <el-form-item label="鍙戣揣鏃ユ湡锛�" prop="shippingDate">
+              <el-date-picker
+                style="width: 100%"
+                v-model="form.shippingDate"
+                value-format="YYYY-MM-DD"
+                format="YYYY-MM-DD"
+                type="date"
+                placeholder="璇烽�夋嫨鍙戣揣鏃ユ湡"
+                clearable
+              />
             </el-form-item>
           </el-col>
         </el-row>
         <el-row :gutter="30">
-          <el-col :span="24">
-            <el-form-item label="鍙戣揣鏃堕棿锛�" prop="shippingDate">
-              <el-date-picker style="width: 100%" v-model="form.shippingDate" value-format="YYYY-MM-DD"
-                format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="24">
+          <el-col :span="24" v-if="form.type === '璐ц溅'">
             <el-form-item label="鍙戣揣杞︾墝鍙凤細" prop="shippingCarNumber">
-              <el-input v-model="form.shippingCarNumber" placeholder="璇疯緭鍏�" clearable />
+              <el-input
+                v-model="form.shippingCarNumber"
+                placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+          <el-col :span="24" v-else>
+            <el-form-item label="蹇�掑叕鍙革細" prop="expressCompany">
+              <el-input
+                v-model="form.expressCompany"
+                placeholder="璇疯緭鍏ュ揩閫掑叕鍙�"
+                clearable
+              />
             </el-form-item>
           </el-col>
         </el-row>
-        
+        <el-row :gutter="30" v-if="form.type === '蹇��'">
+          <el-col :span="24">
+            <el-form-item label="蹇�掑崟鍙凤細" prop="expressNumber">
+              <el-input
+                v-model="form.expressNumber"
+                placeholder="璇疯緭鍏ュ揩閫掑崟鍙�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="30">
+          <el-col :span="24">
+            <el-form-item label="鍙戣揣鍥剧墖锛�">
+              <el-upload 
+                v-model:file-list="deliveryFileList" 
+                :action="upload.url" 
+                multiple 
+                ref="deliveryFileUpload" 
+                auto-upload
+                :headers="upload.headers" 
+                :data="{ type: 9 }"
+                :before-upload="handleDeliveryBeforeUpload" 
+                :on-error="handleDeliveryUploadError"
+                :on-success="handleDeliveryUploadSuccess" 
+                :on-remove="handleDeliveryRemove"
+                list-type="picture-card"
+                :limit="9"
+                accept="image/png,image/jpeg,image/jpg"
+              >
+                <el-icon class="avatar-uploader-icon"><Plus /></el-icon>
+                <template #tip>
+                  <div class="el-upload__tip">
+                    鏀寔 jpg銆乯peg銆乸ng 鏍煎紡锛屾渶澶氫笂浼� 9 寮狅紝鍗曞紶澶у皬涓嶈秴杩� 10MB
+                  </div>
+                </template>
+              </el-upload>
+            </el-form-item>
+          </el-col>
+        </el-row>
       </el-form>
-    </FormDialog>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">纭</el-button>
+          <el-button @click="closeDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
 import pagination from "@/components/PIMTable/Pagination.vue";
-import FormDialog from '@/components/Dialog/FormDialog.vue';
 import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
 import { ElMessageBox } from "element-plus";
+import { Plus } from "@element-plus/icons-vue";
+import { getToken } from "@/utils/auth";
 import { getCurrentDate } from "@/utils/index.js";
 import {
   deliveryLedgerListPage,
   addOrUpdateDeliveryLedger,
   delDeliveryLedger,
 } from "@/api/salesManagement/deliveryLedger.js";
+import { delLedgerFile } from "@/api/salesManagement/salesLedger.js";
  
 
 const { proxy } = getCurrentInstance();
@@ -108,6 +176,16 @@
   size: 100,
 });
 const total = ref(0);
+const deliveryFileList = ref([]);
+const javaApi = proxy.javaApi;
+
+// 涓婁紶閰嶇疆
+const upload = reactive({
+  // 涓婁紶鐨勫湴鍧�
+  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+  // 璁剧疆涓婁紶鐨勮姹傚ご閮�
+  headers: { Authorization: "Bearer " + getToken() },
+});
 
 // 鐢ㄦ埛淇℃伅琛ㄥ崟寮规鏁版嵁
 const operationType = ref("");
@@ -116,19 +194,31 @@
   searchForm: {
     salesContractNo: "", // 閿�鍞鍗曞彿
     shippingCarNumber: "", // 杞︾墝鍙�
+    expressNumber: "", // 蹇�掑崟鍙�
   },
   form: {
     id: null,
     salesContractNo: "",
     customerName: "",
+    type: "璐ц溅", // 璐ц溅, 蹇��
     shippingDate: "",
     shippingCarNumber: "",
+    expressCompany: "",
+    expressNumber: "", // 蹇�掑崟鍙�
   },
   rules: {
     salesContractNo: [{ required: true, message: "璇烽�夋嫨閿�鍞鍗�", trigger: "change" }],
     customerName: [{ required: true, message: "璇疯緭鍏ュ鎴峰悕绉�", trigger: "blur" }],
+    type: [
+      { required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }
+    ],
     shippingDate: [{ required: true, message: "璇烽�夋嫨鍙戣揣鏃堕棿", trigger: "change" }],
-    shippingCarNumber: [{ required: true, message: "璇疯緭鍏ュ彂璐ц溅鐗屽彿", trigger: "blur" }],
+    shippingCarNumber: [
+      { validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" }
+    ],
+    expressCompany: [
+      { validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" }
+    ],
   },
 });
 const { form, rules } = toRefs(data);
@@ -177,22 +267,85 @@
 // 鎵撳紑寮规
 const openForm = async (type, row) => {
   operationType.value = type;
+  const baseUrl = import.meta.env.VITE_APP_BASE_API;
+  
   if (type === 'edit' && row) {
     form.value = {
       id: row.id ?? null,
       salesContractNo: row.salesContractNo ?? "",
       customerName: row.customerName ?? "",
+      type: row.type || "璐ц溅",
       shippingDate: row.shippingDate || getCurrentDate(),
       shippingCarNumber: row.shippingCarNumber ?? "",
+      expressCompany: row.expressCompany ?? "",
+      expressNumber: row.expressNumber ?? "",
     };
+    // 濡傛灉鏈夊浘鐗囷紝灏� commonFileList 杞崲涓烘枃浠跺垪琛ㄦ牸寮�
+    if (row.commonFileList && Array.isArray(row.commonFileList) && row.commonFileList.length > 0) {
+      deliveryFileList.value = row.commonFileList.map((file, index) => {
+        // 澶勭悊 URL锛氬皢 Windows 璺緞杞崲涓哄彲璁块棶鐨� URL
+        let fileUrl = file.url || '';
+        console.log('鍘熷 URL:', fileUrl);
+        
+        // 濡傛灉 URL 鏄� Windows 璺緞鏍煎紡锛堝寘鍚弽鏂滄潬锛夛紝闇�瑕佽浆鎹�
+        if (fileUrl && fileUrl.indexOf('\\') > -1) {
+          // 鏌ユ壘 uploads 鍏抽敭瀛楃殑浣嶇疆锛屼粠閭i噷寮�濮嬫彁鍙栫浉瀵硅矾寰�
+          const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads');
+          if (uploadsIndex > -1) {
+            // 浠� uploads 寮�濮嬫彁鍙栬矾寰勶紝骞跺皢鍙嶆枩鏉犳浛鎹负姝f枩鏉�
+            const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/');
+            fileUrl = '/' + relativePath;
+            console.log('杞崲鍚庣殑鐩稿璺緞:', fileUrl);
+          } else {
+            // 濡傛灉娌℃湁鎵惧埌 uploads锛屾彁鍙栨渶鍚庝竴涓洰褰曞拰鏂囦欢鍚�
+            const parts = fileUrl.split('\\');
+            const fileName = parts[parts.length - 1];
+            fileUrl = '/uploads/' + fileName;
+            console.log('鏈壘鍒� uploads锛屼娇鐢ㄦ枃浠跺悕:', fileUrl);
+          }
+        }
+        
+        // 纭繚鎵�鏈夐潪 http 寮�澶寸殑 URL 閮芥嫾鎺� baseUrl
+        if (fileUrl && !fileUrl.startsWith('http')) {
+          // 纭繚璺緞浠� / 寮�澶�
+          if (!fileUrl.startsWith('/')) {
+            fileUrl = '/' + fileUrl;
+          }
+          // 鎷兼帴 baseUrl
+          fileUrl = javaApi + fileUrl;
+          console.log('鏈�缁堟嫾鎺ョ殑 URL:', fileUrl);
+        }
+        
+        return {
+          uid: file.id || Date.now() + index,
+          name: file.name || `image_${index + 1}.jpg`,
+          url: fileUrl,
+          status: 'success',
+          response: {
+            code: 200,
+            data: {
+              tempId: file.id,
+              url: fileUrl
+            }
+          },
+          tempId: file.id // 淇濆瓨鏂囦欢ID锛岀敤浜庢彁浜ゆ椂浣跨敤
+        };
+      });
+    } else {
+      deliveryFileList.value = [];
+    }
   } else {
     form.value = {
       id: null,
       salesContractNo: "",
       customerName: "",
+      type: "璐ц溅",
       shippingDate: getCurrentDate(),
       shippingCarNumber: "",
+      expressCompany: "",
+      expressNumber: "",
     };
+    deliveryFileList.value = [];
   }
   
   dialogFormVisible.value = true;
@@ -202,10 +355,18 @@
 const submitForm = () => {
   proxy.$refs["formRef"].validate((valid) => {
     if (valid) {
+      let tempFileIds = [];
+      if (deliveryFileList.value !== null && deliveryFileList.value.length > 0) {
+        tempFileIds = deliveryFileList.value.map((item) => item.tempId);
+      }
       const payload = {
         id: form.value.id,
+        type: form.value.type,
         shippingDate: form.value.shippingDate,
-        shippingCarNumber: form.value.shippingCarNumber,
+        shippingCarNumber: form.value.type === "璐ц溅" ? form.value.shippingCarNumber : "",
+        expressCompany: form.value.type === "蹇��" ? form.value.expressCompany : "",
+        expressNumber: form.value.type === "蹇��" ? form.value.expressNumber : "",
+        tempFileIds: tempFileIds,
       };
       addOrUpdateDeliveryLedger(payload).then((res) => {
         proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
@@ -219,6 +380,7 @@
 // 鍏抽棴寮规
 const closeDia = () => {
   proxy.resetForm("formRef");
+  deliveryFileList.value = []; // 娓呯┖鏂囦欢鍒楄〃
   dialogFormVisible.value = false;
 };
 
@@ -280,6 +442,89 @@
     });
 };
 
+// 鍙戣揣绫诲瀷鏍¢獙锛氳揣杞︽椂瑕佹眰杞︾墝锛屽揩閫掓椂瑕佹眰蹇�掑叕鍙�
+const validateShippingCarNumber = (value, callback) => {
+  if (form.value.type === "璐ц溅") {
+    if (!value) return callback(new Error("璇疯緭鍏ュ彂璐ц溅鐗屽彿"));
+  }
+  callback();
+};
+const validateExpressCompany = (value, callback) => {
+  if (form.value.type === "蹇��") {
+    if (!value) return callback(new Error("璇疯緭鍏ュ揩閫掑叕鍙�"));
+  }
+  callback();
+};
+
+// 鍙戣揣鍥剧墖涓婁紶鍓嶆牎妫�
+function handleDeliveryBeforeUpload(file) {
+  // 鏍℃鏂囦欢绫诲瀷
+  const isImage = file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg';
+  if (!isImage) {
+    proxy.$modal.msgError("鍙兘涓婁紶 jpg銆乯peg銆乸ng 鏍煎紡鐨勫浘鐗�!");
+    return false;
+  }
+  // 鏍℃鏂囦欢澶у皬
+  const isLt10M = file.size / 1024 / 1024 < 10;
+  if (!isLt10M) {
+    proxy.$modal.msgError("涓婁紶鍥剧墖澶у皬涓嶈兘瓒呰繃 10MB!");
+    return false;
+  }
+  proxy.$modal.loading("姝e湪涓婁紶鍥剧墖锛岃绋嶅��...");
+  return true;
+}
+// 鍙戣揣鍥剧墖涓婁紶澶辫触
+function handleDeliveryUploadError(err) {
+  proxy.$modal.msgError("涓婁紶鍥剧墖澶辫触");
+  proxy.$modal.closeLoading();
+}
+// 鍙戣揣鍥剧墖涓婁紶鎴愬姛鍥炶皟
+function handleDeliveryUploadSuccess(res, file, uploadFiles) {
+  proxy.$modal.closeLoading();
+  if (res.code === 200) {
+    file.tempId = res.data.tempId;
+    proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+  } else {
+    proxy.$modal.msgError(res.msg);
+    proxy.$refs.deliveryFileUpload.handleRemove(file);
+  }
+}
+// 绉婚櫎鍙戣揣鍥剧墖
+function handleDeliveryRemove(file) {
+  console.log('file--', file)
+  // 濡傛灉鏄紪杈戞ā寮忎笖鏂囦欢鏈� id锛岄渶瑕佽皟鐢ㄦ帴鍙e垹闄�
+  if (operationType.value === "edit") {
+    let ids = [];
+    ids.push(file.uid);
+    delLedgerFile(ids).then((res) => {
+      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+      // 浠庢枃浠跺垪琛ㄤ腑绉婚櫎
+      const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
+      if (index > -1) {
+        deliveryFileList.value.splice(index, 1);
+      }
+    }).catch(() => {
+      proxy.$modal.msgError("鍒犻櫎澶辫触");
+    });
+  } else {
+    // 鏂板妯″紡鎴栨病鏈� id 鐨勬枃浠讹紝鐩存帴浠庡垪琛ㄤ腑绉婚櫎
+    const index = deliveryFileList.value.findIndex(item => item.uid === file.uid);
+    if (index > -1) {
+      deliveryFileList.value.splice(index, 1);
+    }
+  }
+}
+
+// 鍙戣揣绫诲瀷鍒囨崲鏃舵竻绌哄搴斿瓧娈�
+const handleShippingTypeChange = (val) => {
+  if (val === "璐ц溅") {
+    form.value.expressCompany = "";
+    form.value.expressNumber = "";
+  } else {
+    form.value.shippingCarNumber = "";
+  }
+};
+
 onMounted(() => {
   getList();
 });
@@ -295,5 +540,12 @@
   justify-content: space-between;
   margin-bottom: 10px;
 }
+
+// 闅愯棌鍥剧墖涓婁紶缁勪欢鐨勯瑙堟寜閽紙鏀惧ぇ闀滐級
+:deep(.el-upload-list--picture-card .el-upload-list__item-actions) {
+  .el-upload-list__item-preview {
+    display: none;
+  }
+}
 </style>
 
diff --git a/src/views/salesManagement/invoiceLedger/index.vue b/src/views/salesManagement/invoiceLedger/index.vue
index eec3a26..0b45dde 100644
--- a/src/views/salesManagement/invoiceLedger/index.vue
+++ b/src/views/salesManagement/invoiceLedger/index.vue
@@ -32,7 +32,6 @@
         <el-table-column align="center" label="搴忓彿" type="index" width="60" />
         <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip width="180" />
         <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip width="240" />
-<!--        <el-table-column label="椤圭洰" prop="projectName" width="320" />-->
         <el-table-column label="浜у搧澶х被" prop="productCategory" width="200" />
         <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" width="160" show-overflow-tooltip />
         <el-table-column label="鍙戠エ鍙�" prop="invoiceNo" width="200" show-overflow-tooltip />
@@ -42,17 +41,6 @@
         <el-table-column label="褰曞叆浜�" prop="invoicePerson" show-overflow-tooltip />
         <el-table-column label="褰曞叆鏃ユ湡" prop="createTime" show-overflow-tooltip :formatter="formatDate" width="180" />
         <el-table-column label="寮�绁ㄦ棩鏈�" prop="invoiceDate" show-overflow-tooltip width="120" />
-        <!-- <el-table-column label="鍙戠エ" prop="invoiceFileName" width="120" align="center" show-overflow-tooltip fixed="right">
-          <template #default="scope">
-            <el-button v-if="scope.row.invoiceFileName" text bg type="primary"
-              @click="handleFile(scope.row.commonFiles)">
-              鏌ョ湅闄勪欢
-            </el-button>
-            <el-button v-else link type="primary" @click="handleDownload(scope.row)">
-              涓婁紶
-            </el-button>
-          </template>
-        </el-table-column> -->
         <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
           <template #default="scope">
             <el-button link type="primary" size="small" @click="openForm(scope.row)">缂栬緫</el-button>
@@ -439,12 +427,6 @@
 }
 
 onMounted(() => {
-  // 璁剧疆寮�绁ㄦ棩鏈熻寖鍥撮粯璁ゅ�间负褰撳ぉ
-  const today = dayjs().format('YYYY-MM-DD');
-  searchForm.invoiceDate = [today, today];
-  // 璁剧疆鑼冨洿鏃ユ湡瀛楁鐨勮捣濮嬪拰缁撴潫鏃堕棿
-  searchForm.invoiceDateStart = today;
-  searchForm.invoiceDateEnd = today;
   getList();
 });
 </script>
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 54114f1..c813ed1 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -1,273 +1,318 @@
 <template>
-  <div class="app-container">
-    <div class="search_form">
-      <el-form :model="searchForm" :inline="true">
-        <el-form-item label="瀹㈡埛鍚嶇О锛�">
-          <el-input v-model="searchForm.customerName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
-            @change="handleQuery" />
-        </el-form-item>
-        <el-form-item label="瀹㈡埛鍚堝悓鍙凤細">
-          <el-input v-model="searchForm.customerContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
-            @change="handleQuery" />
-        </el-form-item>
-        <el-form-item label="閿�鍞悎鍚屽彿锛�">
-          <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
-            @change="handleQuery" />
-        </el-form-item>
-        <el-form-item label="椤圭洰鍚嶇О锛�">
-          <el-input v-model="searchForm.projectName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
-            @change="handleQuery" />
-        </el-form-item>
-        <el-form-item label="褰曞叆鏃ユ湡锛�">
-          <el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
-            placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
-        </el-form-item>
-        <el-form-item>
-          <el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
-        </el-form-item>
-      </el-form>
-    </div>
-    <div class="table_list">
-      <div class="actions">
-        <div></div>
-        <div>
-          <el-button type="primary" @click="openForm('add')">
-            鏂板鍙拌处
-          </el-button>
-          <el-button @click="handleOut">瀵煎嚭</el-button>
-          <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
-          <el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
-        </div>
-      </div>
-      <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
-        :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%"
-        :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)">
-        <el-table-column align="center" type="selection" width="55" />
-        <el-table-column type="expand">
-          <template #default="props">
-            <el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
-              <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-              <el-table-column label="浜у搧澶х被" prop="productCategory" />
-              <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
-              <el-table-column label="鍗曚綅" prop="unit" />
-              <el-table-column label="浜у搧鐘舵��" width="100px" align="center">
-                <template #default="scope">
-                  <el-tag v-if="scope.row.approveStatus === 0" type="info">鏈嚭搴�</el-tag>
-                  <el-tag v-if="scope.row.approveStatus === 1" type="success">宸插嚭搴�</el-tag>
-                  <el-tag v-if="scope.row.approveStatus === 2" type="warning">瀹℃牳涓�</el-tag>
-                  <el-tag v-if="scope.row.approveStatus === 3" type="success">瀹℃牳鎴愬姛</el-tag>
-                  <el-tag v-if="scope.row.approveStatus === 4" type="danger">瀹℃牳澶辫触</el-tag>
-                </template>
-              </el-table-column>
-              <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
-                <template #default="scope">
-                  <div>
-                    <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
-                    <el-tag v-else type="info">鏈彂璐�</el-tag>
-                  </div>
-                </template>
-              </el-table-column>
-              <el-table-column label="鍙戣揣鏃ユ湡" minWidth="100px" align="center">
-                <template #default="scope">
-                  <div>
-                    <div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
-                    <el-tag v-else type="info">鏈彂璐�</el-tag>
-                  </div>
-                </template>
-              </el-table-column>
-              <el-table-column label="鏁伴噺" prop="quantity" />
-              <el-table-column label="绋庣巼(%)" prop="taxRate" />
-              <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
-              <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
-              <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
-            <!--鎿嶄綔-->
-              <el-table-column Width="60px" label="鎿嶄綔" align="center">
-                <template #default="scope">
-                  <el-button :disabled="scope.row.approveStatus!==2 || scope.row.approveStatus!==5" link type="primary" size="small" @click="openDeliveryForm(scope.row)">鍙戣揣</el-button>
-                </template>
-              </el-table-column>
-            </el-table>
-          </template>
-        </el-table-column>
-        <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" width="180" show-overflow-tooltip />
-        <el-table-column label="瀹㈡埛鍚堝悓鍙�" prop="customerContractNo" width="180" show-overflow-tooltip />
-        <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" width="300" show-overflow-tooltip />
-        <el-table-column label="涓氬姟鍛�" prop="salesman" width="100" show-overflow-tooltip />
-        <el-table-column label="椤圭洰鍚嶇О" prop="projectName" width="180" show-overflow-tooltip />
-        <el-table-column label="浠樻鏂瑰紡" prop="paymentMethod" show-overflow-tooltip />
-        <el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" width="220" show-overflow-tooltip
-          :formatter="formattedNumber" />
-        <el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
-        <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
-        <el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
-        <el-table-column fixed="right" label="鎿嶄綔" min-width="100" align="center">
-          <template #default="scope">
-            <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">缂栬緫</el-button>
-<!--            <el-button link type="primary" size="small" @click="openForm('view', scope.row)">璇︽儏</el-button>-->
-            <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">闄勪欢</el-button>
-<!--            <el-button link type="primary" size="small" @click="openDeliveryForm(scope.row)">鍙戣揣</el-button>-->
-          </template>
-        </el-table-column>
-      </el-table>
-      <pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
-        :page="page.current" :limit="page.size" @pagination="paginationChange" />
-    </div>
-    <el-dialog v-model="dialogFormVisible" :title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : '缂栬緫閿�鍞彴璐﹂〉闈�'" width="70%"
-      @close="closeDia">
-      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
-              <el-input v-model="form.salesContractNo" placeholder="鑷姩鐢熸垚" clearable disabled />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="涓氬姟鍛橈細" prop="salesman">
-              <el-select v-model="form.salesman" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
-                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
-                  :value="item.nickName" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="瀹㈡埛鍚堝悓鍙凤細" prop="customerContractNo">
-              <el-input v-model="form.customerContractNo" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerId">
-              <el-select v-model="form.customerId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
-                <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
-                  {{
-                    item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
-                  }}
-                </el-option>
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
-              <el-input v-model="form.projectName" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
-            </el-form-item>
-          </el-col>
+	<div class="app-container">
+		<div class="search_form">
+			<el-form :model="searchForm" :inline="true">
+				<el-form-item label="瀹㈡埛鍚嶇О锛�">
+					<el-input v-model="searchForm.customerName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+										@change="handleQuery" />
+				</el-form-item>
+				<el-form-item label="閿�鍞悎鍚屽彿锛�">
+					<el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
+										@change="handleQuery" />
+				</el-form-item>
+				<el-form-item label="褰曞叆鏃ユ湡锛�">
+					<el-date-picker v-model="searchForm.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange"
+													placeholder="璇烽�夋嫨" clearable @change="changeDaterange" />
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery"> 鎼滅储 </el-button>
+				</el-form-item>
+			</el-form>
+		</div>
+		<div class="table_list">
+			<div class="actions">
+				<div></div>
+				<div>
+					<el-button type="primary" @click="openForm('add')">
+						鏂板鍙拌处
+					</el-button>
+					<el-button @click="handleImport">瀵煎叆</el-button>
+					<el-button @click="handleOut">瀵煎嚭</el-button>
+					<el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
+					<el-button type="primary" plain @click="handlePrint">鎵撳嵃</el-button>
+				</div>
+			</div>
+			<el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
+								:expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%"
+								:summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 21em)">
+				<el-table-column align="center" type="selection" width="55" />
+				<el-table-column type="expand">
+					<template #default="props">
+						<el-table :data="props.row.children" border show-summary :summary-method="summarizeChildrenTable">
+							<el-table-column align="center" label="搴忓彿" type="index" width="60" />
+							<el-table-column label="浜у搧澶х被" prop="productCategory" />
+							<el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+							<el-table-column label="鍗曚綅" prop="unit" />
+							<el-table-column label="鏁伴噺" prop="quantity" />
+							<el-table-column label="绋庣巼(%)" prop="taxRate" />
+							<el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
+							<el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
+							<el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
+							<el-table-column label="浜у搧鐘舵��"
+															 width="100px"
+															 align="center">
+								<template #default="scope">
+									<el-tag v-if="scope.row.approveStatus === 1"
+													type="success">鍏呰冻</el-tag>
+									<el-tag v-else
+													type="danger">涓嶈冻</el-tag>
+								</template>
+							</el-table-column>
+							<el-table-column label="鍙戣揣鐘舵��" prop="shippingStatus" width="140" align="center" show-overflow-tooltip />
+							<el-table-column label="鍙戣揣鏃ユ湡"
+															 minWidth="100px"
+															 align="center">
+								<template #default="scope">
+									<div>
+										<div v-if="scope.row.shippingDate">{{ scope.row.shippingDate }}</div>
+										<el-tag v-else
+														type="info">-</el-tag>
+									</div>
+								</template>
+							</el-table-column>
+							<el-table-column Width="60px"
+															 label="鎿嶄綔"
+															 align="center">
+								<template #default="scope">
+									<el-button
+														 link
+														 type="primary"
+														 size="small"
+														 @click="openDeliveryForm(scope.row)">鍙戣揣</el-button>
+								</template>
+							</el-table-column>
+						</el-table>
+					</template>
+				</el-table-column>
+				<el-table-column align="center" label="搴忓彿" type="index" width="60" />
+				<el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" show-overflow-tooltip />
+				<el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" show-overflow-tooltip />
+				<el-table-column label="涓氬姟鍛�" prop="salesman" width="100" show-overflow-tooltip />
+				<el-table-column label="鍚堝悓閲戦(鍏�)" prop="contractAmount" width="220" show-overflow-tooltip
+												 :formatter="formattedNumber" />
+				<el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
+				<el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
+				<el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
+				<el-table-column fixed="right" label="鎿嶄綔" width="120" align="center">
+					<template #default="scope">
+						<el-button link type="primary" size="small" @click="openForm('edit', scope.row)">缂栬緫</el-button>
+						<el-button link type="primary" size="small" @click="downLoadFile(scope.row)">闄勪欢</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			<pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
+									:page="page.current" :limit="page.size" @pagination="paginationChange" />
+		</div>
+		<FormDialog
+			v-model="dialogFormVisible"
+			:title="operationType === 'add' ? '鏂板閿�鍞彴璐﹂〉闈�' : '缂栬緫閿�鍞彴璐﹂〉闈�'"
+			:width="'70%'"
+			:operation-type="operationType"
+			@close="closeDia"
+			@confirm="submitForm"
+			@cancel="closeDia">
+			<el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+				<el-row v-if="operationType !== 'view'">
+					<el-col :span="24" style="display:flex; justify-content:flex-end; gap:10px; margin-bottom: 6px;">
+						<el-button type="primary" plain @click="openQuotationDialog">浠庡鎵归�氳繃鐨勬姤浠峰崟瀵煎叆</el-button>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="閿�鍞悎鍚屽彿锛�" prop="salesContractNo">
+							<el-input v-model="form.salesContractNo" placeholder="鑷姩鐢熸垚" clearable disabled />
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="涓氬姟鍛橈細" prop="salesman">
+							<el-select v-model="form.salesman"
+												 filterable
+												 :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
+								<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName"
+													 :value="item.nickName" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerId">
+							<el-select v-model="form.customerId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" filterable>
+								<el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
+									{{
+										item.customerName + "鈥斺��" + item.taxpayerIdentificationNumber
+									}}
+								</el-option>
+							</el-select>
+						</el-form-item>
+					</el-col>
 					<el-col :span="12">
 						<el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
 							<el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD"
 															format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" />
 						</el-form-item>
 					</el-col>
-        </el-row>
-        <el-row :gutter="30">
+				</el-row>
+				<el-row :gutter="30">
 					<el-col :span="12">
 						<el-form-item label="褰曞叆浜猴細" prop="entryPerson">
-							<el-select v-model="form.entryPerson" placeholder="璇烽�夋嫨" clearable @change="changs" disabled>
+							<el-select v-model="form.entryPerson"
+												 filterable
+												 default-first-option
+												 :reserve-keyword="false" placeholder="璇烽�夋嫨" clearable @change="changs">
 								<el-option v-for="item in userList" :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="entryDate">
-              <el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
-                type="date" placeholder="璇烽�夋嫨" clearable />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="浠樻鏂瑰紡">
-              <el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
-            <el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">娣诲姞</el-button>
-            <el-button v-if="operationType !== 'view'" plain type="danger" @click="deleteProduct" >鍒犻櫎</el-button>
-          </el-form-item>
-        </el-row>
-        <el-table :data="productData" border @selection-change="productSelected" show-summary
-          :summary-method="summarizeMainTable">
-          <el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'" />
-          <el-table-column align="center" label="搴忓彿" type="index" width="60" />
-          <el-table-column label="浜у搧澶х被" prop="productCategory" />
-          <el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
-          <el-table-column label="鍗曚綅" prop="unit" />
-          <el-table-column label="鏁伴噺" prop="quantity" />
-          <el-table-column label="绋庣巼(%)" prop="taxRate" />
-          <el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
-          <el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
-          <el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
-          <el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center" v-if="operationType !== 'view'">
-            <template #default="scope">
-              <el-button link type="primary" size="small" @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫</el-button>
-            </template>
-          </el-table-column>
-        </el-table>
-        <el-row :gutter="30">
-          <el-col :span="24">
-            <el-form-item label="澶囨敞路锛�" prop="remark">
-              <el-input v-model="form.remark" placeholder="璇疯緭鍏�" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="24">
-            <el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
-              <el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
-                :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
-                :on-success="handleUploadSuccess" :on-remove="handleRemove">
-                <el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>
-                <template #tip v-if="operationType !== 'view'">
-                  <div class="el-upload__tip">
-                    鏂囦欢鏍煎紡鏀寔
-                    doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
-                  </div>
-                </template>
-              </el-upload>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitForm">纭</el-button>
-          <el-button @click="closeDia">鍙栨秷</el-button>
-        </div>
-      </template>
-    </el-dialog>
-    <el-dialog v-model="productFormVisible" :title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'" width="40%" @close="closeProductDia">
-      <el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
-        <el-row :gutter="30">
-          <el-col :span="24">
-            <el-form-item label="浜у搧澶х被锛�" prop="productCategory">
-              <!-- <el-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable>
-                <el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
-              </el-select> -->
-              <el-tree-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable check-strictly
-                @change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="24">
-            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
-              <el-select v-model="productForm.productModelId" placeholder="璇烽�夋嫨" clearable @change="getProductModel">
-                <el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="鍗曚綅锛�" prop="unit">
-              <el-input v-model="productForm.unit" placeholder="璇疯緭鍏�" clearable />
-            </el-form-item>
-          </el-col>
+					<el-col :span="12">
+						<el-form-item label="褰曞叆鏃ユ湡锛�" prop="entryDate">
+							<el-date-picker style="width: 100%" v-model="form.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
+															type="date" placeholder="璇烽�夋嫨" clearable />
+						</el-form-item>
+					</el-col>
+				</el-row>
+				
+				<el-row>
+					<el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
+						<el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">娣诲姞</el-button>
+						<el-button v-if="operationType !== 'view'" plain type="danger" @click="deleteProduct" >鍒犻櫎</el-button>
+					</el-form-item>
+				</el-row>
+				<el-table :data="productData" border @selection-change="productSelected" show-summary
+									:summary-method="summarizeMainTable">
+					<el-table-column align="center" type="selection" width="55" v-if="operationType !== 'view'" />
+					<el-table-column align="center" label="搴忓彿" type="index" width="60" />
+					<el-table-column label="浜у搧澶х被" prop="productCategory" />
+					<el-table-column label="瑙勬牸鍨嬪彿" prop="specificationModel" />
+					<el-table-column label="鍗曚綅" prop="unit" />
+					<el-table-column label="鏁伴噺" prop="quantity" />
+					<el-table-column label="绋庣巼(%)" prop="taxRate" />
+					<el-table-column label="鍚◣鍗曚环(鍏�)" prop="taxInclusiveUnitPrice" :formatter="formattedNumber" />
+					<el-table-column label="鍚◣鎬讳环(鍏�)" prop="taxInclusiveTotalPrice" :formatter="formattedNumber" />
+					<el-table-column label="涓嶅惈绋庢�讳环(鍏�)" prop="taxExclusiveTotalPrice" :formatter="formattedNumber" />
+					<el-table-column fixed="right" label="鎿嶄綔" min-width="60" align="center" v-if="operationType !== 'view'">
+						<template #default="scope">
+							<el-button link type="primary" size="small" @click="openProductForm('edit', scope.row,scope.$index)">缂栬緫</el-button>
+						</template>
+					</el-table-column>
+				</el-table>
+				<el-row :gutter="30">
+					<el-col :span="24">
+						<el-form-item label="澶囨敞路锛�" prop="remark">
+							<el-input v-model="form.remark" placeholder="璇疯緭鍏�" clearable type="textarea" :rows="2" :disabled="operationType === 'view'" />
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="24">
+						<el-form-item label="闄勪欢鏉愭枡锛�" prop="remark">
+							<el-upload v-model:file-list="fileList" :action="upload.url" multiple ref="fileUpload" auto-upload
+												 :headers="upload.headers" :before-upload="handleBeforeUpload" :on-error="handleUploadError"
+												 :on-success="handleUploadSuccess" :on-remove="handleRemove">
+								<el-button type="primary" v-if="operationType !== 'view'">涓婁紶</el-button>
+								<template #tip v-if="operationType !== 'view'">
+									<div class="el-upload__tip">
+										鏂囦欢鏍煎紡鏀寔
+										doc锛宒ocx锛寈ls锛寈lsx锛宲pt锛宲ptx锛宲df锛宼xt锛寈ml锛宩pg锛宩peg锛宲ng锛実if锛宐mp锛宺ar锛寊ip锛�7z
+									</div>
+								</template>
+							</el-upload>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+		</FormDialog>
+		
+		<!-- 浠庢姤浠峰崟瀵煎叆锛堜粎瀹℃壒閫氳繃锛� -->
+		<el-dialog
+			v-model="quotationDialogVisible"
+			title="閫夋嫨瀹℃壒閫氳繃鐨勯攢鍞姤浠峰崟"
+			width="80%"
+			:close-on-click-modal="false"
+		>
+			<div style="margin-bottom: 12px; display:flex; gap: 12px; align-items:center;">
+				<el-input
+					v-model="quotationSearchForm.quotationNo"
+					placeholder="璇疯緭鍏ユ姤浠峰崟鍙�"
+					clearable
+					style="max-width: 260px;"
+					@change="fetchQuotationList"
+				/>
+				<el-input
+					v-model="quotationSearchForm.customer"
+					placeholder="璇疯緭鍏ュ鎴峰悕绉�"
+					clearable
+					style="max-width: 260px;"
+					@change="fetchQuotationList"
+				/>
+				<el-button type="primary" @click="fetchQuotationList">鎼滅储</el-button>
+				<el-button @click="resetQuotationSearch">閲嶇疆</el-button>
+			</div>
+			
+			<el-table
+				:data="quotationList"
+				border
+				stripe
+				v-loading="quotationLoading"
+				height="420px"
+			>
+				<el-table-column align="center" label="搴忓彿" type="index" width="60" />
+				<el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" width="180" show-overflow-tooltip />
+				<el-table-column prop="customer" label="瀹㈡埛鍚嶇О" min-width="220" show-overflow-tooltip />
+				<el-table-column prop="salesperson" label="涓氬姟鍛�" width="120" show-overflow-tooltip />
+				<el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="140" />
+				<el-table-column prop="status" label="瀹℃壒鐘舵��" width="120" align="center" />
+				<el-table-column prop="totalAmount" label="鎶ヤ环閲戦(鍏�)" width="160" align="right">
+					<template #default="scope">
+						{{ Number(scope.row.totalAmount ?? 0).toFixed(2) }}
+					</template>
+				</el-table-column>
+				<el-table-column fixed="right" label="鎿嶄綔" width="120" align="center">
+					<template #default="scope">
+						<el-button type="primary" link @click="applyQuotation(scope.row)">閫夋嫨</el-button>
+					</template>
+				</el-table-column>
+			</el-table>
+			
+			<template #footer>
+				<el-button @click="quotationDialogVisible = false">鍏抽棴</el-button>
+			</template>
+		</el-dialog>
+		<FormDialog
+			v-model="productFormVisible"
+			:title="productOperationType === 'add' ? '鏂板浜у搧' : '缂栬緫浜у搧'"
+			:width="'40%'"
+			:operation-type="productOperationType"
+			@close="closeProductDia"
+			@confirm="submitProduct"
+			@cancel="closeProductDia">
+			<el-form :model="productForm" label-width="140px" label-position="top" :rules="productRules" ref="productFormRef">
+				<el-row :gutter="30">
+					<el-col :span="24">
+						<el-form-item label="浜у搧澶х被锛�" prop="productCategory">
+							<!-- <el-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable>
+								<el-option v-for="item in userList" :key="item.nickName" :label="item.nickName" :value="item.nickName"/>
+							</el-select> -->
+							<el-tree-select v-model="productForm.productCategory" placeholder="璇烽�夋嫨" clearable check-strictly
+															@change="getModels" :data="productOptions" :render-after-expand="false" style="width: 100%" />
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="24">
+						<el-form-item label="瑙勬牸鍨嬪彿锛�" prop="productModelId">
+							<el-select v-model="productForm.productModelId" placeholder="璇烽�夋嫨" clearable @change="getProductModel" filterable>
+								<el-option v-for="item in modelOptions" :key="item.id" :label="item.model" :value="item.id" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="鍗曚綅锛�" prop="unit">
+							<el-input v-model="productForm.unit" placeholder="璇疯緭鍏�" clearable />
+						</el-form-item>
+					</el-col>
 					<el-col :span="12">
 						<el-form-item label="绋庣巼(%)锛�" prop="taxRate">
 							<el-select v-model="productForm.taxRate" placeholder="璇烽�夋嫨" clearable @change="calculateFromTaxRate">
@@ -277,15 +322,15 @@
 							</el-select>
 						</el-form-item>
 					</el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
-              <el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="鍚◣鍗曚环(鍏�)锛�" prop="taxInclusiveUnitPrice">
+							<el-input-number :step="0.01" :min="0" v-model="productForm.taxInclusiveUnitPrice" style="width: 100%"
 															 :precision="2"
 															 placeholder="璇疯緭鍏�" clearable @change="calculateFromUnitPrice" />
-            </el-form-item>
-          </el-col>
+						</el-form-item>
+					</el-col>
 					<el-col :span="12">
 						<el-form-item label="鏁伴噺锛�" prop="quantity">
 							<el-input-number  :step="0.1" :min="0" v-model="productForm.quantity" placeholder="璇疯緭鍏�" clearable
@@ -293,37 +338,31 @@
 																@change="calculateFromQuantity" style="width: 100%" />
 						</el-form-item>
 					</el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
-              <el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromTotalPrice" />
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice">
-              <el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromExclusiveTotalPrice" />
-            </el-form-item>
-          </el-col>
-        </el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
-              <el-select v-model="productForm.invoiceType" placeholder="璇烽�夋嫨" clearable>
-                <el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
-                <el-option label="澧炰笓绁�" value="澧炰笓绁�" />
-              </el-select>
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitProduct">纭</el-button>
-          <el-button @click="closeProductDia">鍙栨秷</el-button>
-        </div>
-      </template>
-    </el-dialog>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="鍚◣鎬讳环(鍏�)锛�" prop="taxInclusiveTotalPrice">
+							<el-input v-model="productForm.taxInclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromTotalPrice" />
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="涓嶅惈绋庢�讳环(鍏�)锛�" prop="taxExclusiveTotalPrice">
+							<el-input v-model="productForm.taxExclusiveTotalPrice" placeholder="璇疯緭鍏�" clearable @change="calculateFromExclusiveTotalPrice" />
+						</el-form-item>
+					</el-col>
+				</el-row>
+				<el-row :gutter="30">
+					<el-col :span="12">
+						<el-form-item label="鍙戠エ绫诲瀷锛�" prop="invoiceType">
+							<el-select v-model="productForm.invoiceType" placeholder="璇烽�夋嫨" clearable>
+								<el-option label="澧炴櫘绁�" value="澧炴櫘绁�" />
+								<el-option label="澧炰笓绁�" value="澧炰笓绁�" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
+		</FormDialog>
 		<!-- 鎵撳嵃棰勮寮圭獥 -->
 		<el-dialog
 			v-model="printPreviewVisible"
@@ -358,12 +397,15 @@
 										<span class="value">{{ formatDate(item.createTime) }}</span>
 									</div>
 									<div>
-
-										<span class="label">瀹㈡埛鍚嶇О锛�</span>
-										<span class="value">{{ item.customerName || '寮犵埍鏈�' }}</span>
+										<span class="label">鍙戣揣杞︾墝鍙凤細</span>
+										<span class="value">{{ item.shippingCarNumber }}</span>
 									</div>
 								</div>
 								<div class="info-row">
+									<div>
+										<span class="label">瀹㈡埛鍚嶇О锛�</span>
+										<span class="value">{{ item.customerName || '寮犵埍鏈�' }}</span>
+									</div>
 									<span class="label">鍗曞彿锛�</span>
 									<span class="value">{{ item.salesContractNo }}</span>
 								</div>
@@ -442,42 +484,66 @@
 		<el-dialog
 			v-model="deliveryFormVisible"
 			title="鍙戣揣淇℃伅"
-			width="40%"
+		width="40%"
 			@close="closeDeliveryDia"
 		>
 			<el-form :model="deliveryForm" label-width="120px" label-position="top" :rules="deliveryRules" ref="deliveryFormRef">
 				<el-row :gutter="30">
 					<el-col :span="24">
-						<el-form-item label="鍙戣揣鏃ユ湡锛�" prop="shippingDate">
-							<el-date-picker
+						<el-form-item label="鍙戣揣绫诲瀷锛�" prop="type">
+							<el-select
+								v-model="deliveryForm.type"
+								placeholder="璇烽�夋嫨鍙戣揣绫诲瀷"
 								style="width: 100%"
-								v-model="deliveryForm.shippingDate"
-								value-format="YYYY-MM-DD"
-								format="YYYY-MM-DD"
-								type="date"
-								placeholder="璇烽�夋嫨鍙戣揣鏃ユ湡"
-								clearable
-							/>
+							>
+								<el-option label="璐ц溅" value="璐ц溅" />
+								<el-option label="蹇��" value="蹇��" />
+							</el-select>
 						</el-form-item>
 					</el-col>
 				</el-row>
-				<el-row :gutter="30">
-					<el-col :span="24">
-						<el-form-item label="鍙戣揣杞︾墝鍙凤細" prop="shippingCarNumber">
-							<el-input
-								v-model="deliveryForm.shippingCarNumber"
-								placeholder="璇疯緭鍏ュ彂璐ц溅鐗屽彿"
-								clearable
-							/>
-						</el-form-item>
-					</el-col>
-				</el-row>
-        <el-row :gutter="30">
+
+        <!-- 瀹℃壒浜洪�夋嫨锛堜豢鍗忓悓瀹℃壒閲岀殑瀹℃壒浜鸿妭鐐归�夋嫨锛� -->
+        <el-row>
           <el-col :span="24">
-            <el-form-item label="瀹℃壒浜猴細" prop="approverId">
-              <el-select v-model="deliveryForm.approverId" placeholder="璇烽�夋嫨瀹℃壒浜�" clearable :disabled="operationType === 'view'">
-                <el-option v-for="item in userList" :key="item.userId" :label="item.nickName" :value="item.userId" />
-              </el-select>
+            <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"
+                      size="small"
+                      @click="removeApproverNode(index)"
+                      v-if="approverNodes.length > 1"
+                    >鍒犻櫎</el-button>
+                  </div>
+                </div>
+              </div>
             </el-form-item>
           </el-col>
         </el-row>
@@ -489,45 +555,7 @@
 				</div>
 			</template>
 		</el-dialog>
-    <FileListDialog ref="fileListRef" v-model="fileListDialogVisible" />
-    <!-- 瀵煎叆瀵硅瘽妗� -->
-    <el-dialog
-      :title="importUpload.title"
-      v-model="importUpload.open"
-      width="400px"
-      append-to-body
-    >
-      <el-upload
-        ref="importUploadRef"
-        :limit="1"
-        accept=".xlsx, .xls"
-        :headers="importUpload.headers"
-        :action="importUpload.url"
-        :disabled="importUpload.isUploading"
-        :before-upload="importUpload.beforeUpload"
-        :on-progress="importUpload.onProgress"
-        :on-success="importUpload.onSuccess"
-        :on-error="importUpload.onError"
-        :on-change="importUpload.onChange"
-        :auto-upload="false"
-        drag
-      >
-        <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
-        <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
-        <template #tip>
-          <div class="el-upload__tip text-center">
-            <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
-          </div>
-        </template>
-      </el-upload>
-      <template #footer>
-        <div class="dialog-footer">
-          <el-button type="primary" @click="submitImportFile" :loading="importUpload.isUploading">纭� 瀹�</el-button>
-          <el-button @click="importUpload.open = false">鍙� 娑�</el-button>
-        </div>
-      </template>
-    </el-dialog>
-  </div>
+	</div>
 </template>
 
 <script setup>
@@ -536,24 +564,27 @@
 import {onMounted, ref, getCurrentInstance} from "vue";
 import { addShippingInfo } from "@/api/salesManagement/deliveryLedger.js";
 import { ElMessageBox, ElMessage } from "element-plus";
-import { UploadFilled } from "@element-plus/icons-vue";
+import { UploadFilled, Download } from "@element-plus/icons-vue";
 import useUserStore from "@/store/modules/user";
 import { userListNoPage } from "@/api/system/user.js";
-import FileList from "./fileList.vue";
+import FileListDialog from '@/components/Dialog/FileListDialog.vue';
+import FormDialog from '@/components/Dialog/FormDialog.vue';
+import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
 import {
-  ledgerListPage,
-  productList,
-  customerList,
-  addOrUpdateSalesLedger,
-  getSalesLedgerWithProducts,
-  delLedger,
-  addOrUpdateSalesLedgerProduct,
-  delProduct,
-  delLedgerFile, getProductInventory,
+	ledgerListPage,
+	productList,
+	customerList,
+	addOrUpdateSalesLedger,
+	getSalesLedgerWithProducts,
+	delLedger,
+	addOrUpdateSalesLedgerProduct,
+	delProduct,
+	delLedgerFile, getProductInventory,
 } 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";
 
 const userStore = useUserStore();
 const { proxy } = getCurrentInstance();
@@ -567,8 +598,8 @@
 const modelOptions = ref([]);
 const tableLoading = ref(false);
 const page = reactive({
-  current: 1,
-  size: 100,
+	current: 1,
+	size: 100,
 });
 const total = ref(0);
 const fileList = ref([]);
@@ -577,39 +608,30 @@
 const operationType = ref("");
 const dialogFormVisible = ref(false);
 const data = reactive({
-  searchForm: {
-    customerName: "", // 瀹㈡埛鍚嶇О
-    customerContractNo: "", // 瀹㈡埛鍚堝悓缂栧彿
-    salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
-    projectName: "", // 椤圭洰鍚嶇О
-    entryDate: null, // 褰曞叆鏃ユ湡
-    entryDateStart: undefined,
-    entryDateEnd: undefined,
-  },
-  form: {
-    salesContractNo: "",
-    salesman: "",
-    customerContractNo: "",
-    customerId: "",
-    projectName: "",
-    entryPerson: "",
-    entryDate: "",
-    maintenanceTime: "",
-    productData: [],
-    executionDate: "",
-    paymentMethod: "",
-  },
-  rules: {
-    salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-    customerContractNo: [
-      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
-    ],
-    customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-    projectName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-    entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-    executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-  },
+	searchForm: {
+		customerName: "", // 瀹㈡埛鍚嶇О
+		salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
+		entryDate: null, // 褰曞叆鏃ユ湡
+		entryDateStart: undefined,
+		entryDateEnd: undefined,
+	},
+	form: {
+		salesContractNo: "",
+		salesman: "",
+		customerId: "",
+		entryPerson: "",
+		entryDate: "",
+		maintenanceTime: "",
+		productData: [],
+		executionDate: "",
+	},
+	rules: {
+		salesman: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+	},
 });
 const { form, rules } = toRefs(data);
 const { form: searchForm } = useFormData(data.searchForm);
@@ -618,514 +640,645 @@
 const productOperationType = ref("");
 const currentId = ref("");
 const productFormData = reactive({
-  productForm: {
-    productCategory: "",
-    specificationModel: "",
-    unit: "",
-    quantity: "",
-    taxInclusiveUnitPrice: "",
-    taxRate: "",
-    taxInclusiveTotalPrice: "",
-    taxExclusiveTotalPrice: "",
-    invoiceType: "",
-  },
-  productRules: {
-    productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+	productForm: {
+		productCategory: "",
+		specificationModel: "",
+		unit: "",
+		quantity: "",
+		taxInclusiveUnitPrice: "",
+		taxRate: "",
+		taxInclusiveTotalPrice: "",
+		taxExclusiveTotalPrice: "",
+		invoiceType: "",
+	},
+	productRules: {
+		productCategory: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
 		productModelId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-    specificationModel: [
-      { required: true, message: "璇烽�夋嫨", trigger: "change" },
-    ],
-    unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-    taxInclusiveUnitPrice: [
-      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
-    ],
-    taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-    taxInclusiveTotalPrice: [
-      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
-    ],
-    taxExclusiveTotalPrice: [
-      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
-    ],
-    invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
-  },
+		specificationModel: [
+			{ required: true, message: "璇烽�夋嫨", trigger: "change" },
+		],
+		unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		quantity: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+		taxInclusiveUnitPrice: [
+			{ required: true, message: "璇疯緭鍏�", trigger: "blur" },
+		],
+		taxRate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+		taxInclusiveTotalPrice: [
+			{ required: true, message: "璇疯緭鍏�", trigger: "blur" },
+		],
+		taxExclusiveTotalPrice: [
+			{ required: true, message: "璇疯緭鍏�", trigger: "blur" },
+		],
+		invoiceType: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+	},
 });
 const { productForm, productRules } = toRefs(productFormData);
 // 闃叉寰幆璁$畻鐨勬爣蹇�
 const isCalculating = ref(false);
 const upload = reactive({
-  // 涓婁紶鐨勫湴鍧�
-  url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
-  // 璁剧疆涓婁紶鐨勮姹傚ご閮�
-  headers: { Authorization: "Bearer " + getToken() },
+	// 涓婁紶鐨勫湴鍧�
+	url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
+	// 璁剧疆涓婁紶鐨勮姹傚ご閮�
+	headers: { Authorization: "Bearer " + getToken() },
 });
 // 鎵撳嵃鐩稿叧
 const printPreviewVisible = ref(false);
 const printData = ref([]);
+
+// 鎶ヤ环鍗曞鍏ョ浉鍏�
+const quotationDialogVisible = ref(false);
+const quotationLoading = ref(false);
+const quotationList = ref([]);
+const quotationSearchForm = reactive({
+	quotationNo: "",
+	customer: "",
+});
+const selectedQuotation = ref(null);
 
 // 鍙戣揣鐩稿叧
 const deliveryFormVisible = ref(false);
 const currentDeliveryRow = ref(null);
 const deliveryFormData = reactive({
   deliveryForm: {
-    shippingDate: "",
-    shippingCarNumber: "",
+    type: "璐ц溅", // 璐ц溅, 蹇��
   },
   deliveryRules: {
-    shippingDate: [
-      { required: true, message: "璇烽�夋嫨鍙戣揣鏃ユ湡", trigger: "change" }
-    ],
-    shippingCarNumber: [
-      { required: true, message: "璇疯緭鍏ュ彂璐ц溅鐗屽彿", trigger: "blur" }
-    ],
-    approverId:[
-      {
-        required: true,message: "",
-      }
+    type: [
+      { required: true, message: "璇烽�夋嫨鍙戣揣绫诲瀷", trigger: "change" }
     ]
   },
 });
 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);
 const importUpload = reactive({
-  title: "瀵煎叆閿�鍞彴璐�",
-  open: false,
-  url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
-  headers: { Authorization: "Bearer " + getToken() },
-  isUploading: false,
-  beforeUpload: (file) => {
-    const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
-    const isLt10M = file.size / 1024 / 1024 < 10;
-    if (!isExcel) {
-      proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
-      return false;
-    }
-    if (!isLt10M) {
-      proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
-      return false;
-    }
-    return true;
-  },
-  onChange: (file, fileList) => {
-    console.log('鏂囦欢鐘舵�佹敼鍙�', file, fileList);
-  },
-  onProgress: (event, file, fileList) => {
-    console.log('涓婁紶涓�...', event.percent);
-  },
-  onSuccess: (response, file, fileList) => {
-    console.log('涓婁紶鎴愬姛', response, file, fileList);
-    importUpload.isUploading = false;
-    if (response.code === 200) {
-      proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
-      importUpload.open = false;
-      if (importUploadRef.value) {
-        importUploadRef.value.clearFiles();
-      }
-      getList();
-    } else {
-      proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
-    }
-  },
-  onError: (error, file, fileList) => {
-    console.error('涓婁紶澶辫触', error, file, fileList);
-    importUpload.isUploading = false;
-    proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
-  },
+	title: "瀵煎叆閿�鍞彴璐�",
+	open: false,
+	url: import.meta.env.VITE_APP_BASE_API + "/sales/ledger/import",
+	headers: { Authorization: "Bearer " + getToken() },
+	isUploading: false,
+	beforeUpload: (file) => {
+		const isExcel = file.name.endsWith('.xlsx') || file.name.endsWith('.xls');
+		const isLt10M = file.size / 1024 / 1024 < 10;
+		if (!isExcel) {
+			proxy.$modal.msgError("涓婁紶鏂囦欢鍙兘鏄� xlsx/xls 鏍煎紡!");
+			return false;
+		}
+		if (!isLt10M) {
+			proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃 10MB!");
+			return false;
+		}
+		return true;
+	},
+	onChange: (file, fileList) => {
+		console.log('鏂囦欢鐘舵�佹敼鍙�', file, fileList);
+	},
+	onProgress: (event, file, fileList) => {
+		console.log('涓婁紶涓�...', event.percent);
+	},
+	onSuccess: (response, file, fileList) => {
+		console.log('涓婁紶鎴愬姛', response, file, fileList);
+		importUpload.isUploading = false;
+		if (response.code === 200) {
+			proxy.$modal.msgSuccess("瀵煎叆鎴愬姛");
+			importUpload.open = false;
+			if (importUploadRef.value) {
+				importUploadRef.value.clearFiles();
+			}
+			getList();
+		} else {
+			proxy.$modal.msgError(response.msg || "瀵煎叆澶辫触");
+		}
+	},
+	onError: (error, file, fileList) => {
+		console.error('涓婁紶澶辫触', error, file, fileList);
+		importUpload.isUploading = false;
+		proxy.$modal.msgError("瀵煎叆澶辫触锛岃閲嶈瘯");
+	},
 });
 
 const changeDaterange = (value) => {
-  if (value) {
-    searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
-    searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
-  } else {
-    searchForm.entryDateStart = undefined;
-    searchForm.entryDateEnd = undefined;
-  }
-  handleQuery();
+	if (value) {
+		searchForm.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD");
+		searchForm.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD");
+	} else {
+		searchForm.entryDateStart = undefined;
+		searchForm.entryDateEnd = undefined;
+	}
+	handleQuery();
 };
 
 // 鏌ヨ鍒楄〃
 /** 鎼滅储鎸夐挳鎿嶄綔 */
 const handleQuery = () => {
-  page.current = 1;
+	// 鍙湁鍦ㄧ偣鍑绘悳绱㈡寜閽椂鎵嶉噸缃〉鐮佸埌绗竴椤�
+	// 閬垮厤琛ㄥ崟瀛楁change浜嬩欢骞叉壈鍒嗛〉
+	if (arguments.length === 0) {
+		page.current = 1;
+	}
 	expandedRowKeys.value = [];
-  getList();
+	getList();
 };
 const paginationChange = (obj) => {
-  page.current = obj.page;
-  page.size = obj.limit;
-  getList();
+	page.current = obj.page;
+	page.size = obj.limit;
+	getList();
 };
-const getList =async () => {
-  let userLists = await userListNoPage();
-  userList.value = userLists.data;
-  tableLoading.value = true;
-  const { entryDate, ...rest } = searchForm;
-  ledgerListPage({ ...rest, ...page })
-    .then((res) => {
-      tableLoading.value = false;
-      tableData.value = res.records;
-      tableData.value.map((item) => {
-        item.children = [];
-      });
-      total.value = res.total;
-    })
-    .catch(() => {
-      tableLoading.value = false;
-    });
+const getList = () => {
+	tableLoading.value = true;
+	const { entryDate, ...rest } = searchForm;
+	// 灏嗚寖鍥存棩鏈熷瓧娈典紶閫掔粰鍚庣
+	const params = { ...rest, ...page };
+	// 绉婚櫎褰曞叆鏃ユ湡鐨勯粯璁ゅ�艰缃紝鍙繚鐣欒寖鍥存棩鏈熷瓧娈�
+	delete params.entryDate;
+	ledgerListPage(params)
+		.then((res) => {
+			tableLoading.value = false;
+			tableData.value = res.records;
+			tableData.value.map((item) => {
+				item.children = [];
+			});
+			total.value = res.total;
+		})
+		.catch(() => {
+			tableLoading.value = false;
+		});
 };
 // 鑾峰彇浜у搧澶х被tree鏁版嵁
 const getProductOptions = () => {
-  productTreeList().then((res) => {
-    productOptions.value = convertIdToValue(res);
-  });
+	// 杩斿洖 Promise锛屼究浜庡湪缂栬緫浜у搧鏃剁瓑寰呭姞杞藉畬鎴�
+	return productTreeList().then((res) => {
+		productOptions.value = convertIdToValue(res);
+		return productOptions.value;
+	});
 };
 const formattedNumber = (row, column, cellValue) => {
-  return parseFloat(cellValue).toFixed(2);
+	return parseFloat(cellValue).toFixed(2);
 };
 // 鑾峰彇tree瀛愭暟鎹�
 const getModels = (value) => {
-  productForm.value.productCategory = findNodeById(productOptions.value, value);
-  modelList({ id: value }).then((res) => {
-    modelOptions.value = res;
-  });
+	productForm.value.productCategory = findNodeById(productOptions.value, value);
+	modelList({ id: value }).then((res) => {
+		modelOptions.value = res;
+	});
 };
 const getProductModel = (value) => {
-  const index = modelOptions.value.findIndex((item) => item.id === value);
-  if (index !== -1) {
-    productForm.value.specificationModel = modelOptions.value[index].model;
-    productForm.value.unit = modelOptions.value[index].unit;
-  } else {
-    productForm.value.specificationModel = null;
-    productForm.value.unit = null;
-  }
+	const index = modelOptions.value.findIndex((item) => item.id === value);
+	if (index !== -1) {
+		productForm.value.specificationModel = modelOptions.value[index].model;
+		productForm.value.unit = modelOptions.value[index].unit;
+	} else {
+		productForm.value.specificationModel = null;
+		productForm.value.unit = null;
+	}
 };
 const findNodeById = (nodes, productId) => {
-  for (let i = 0; i < nodes.length; i++) {
-    if (nodes[i].value === productId) {
-      return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
-    }
-    if (nodes[i].children && nodes[i].children.length > 0) {
-      const foundNode = findNodeById(nodes[i].children, productId);
-      if (foundNode) {
-        return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
-      }
-    }
-  }
-  return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
+	for (let i = 0; i < nodes.length; i++) {
+		if (nodes[i].value === productId) {
+			return nodes[i].label; // 鎵惧埌鑺傜偣锛岃繑鍥炶鑺傜偣
+		}
+		if (nodes[i].children && nodes[i].children.length > 0) {
+			const foundNode = findNodeById(nodes[i].children, productId);
+			if (foundNode) {
+				return foundNode; // 鍦ㄥ瓙鑺傜偣涓壘鍒帮紝杩斿洖璇ヨ妭鐐�
+			}
+		}
+	}
+	return null; // 娌℃湁鎵惧埌鑺傜偣锛岃繑鍥瀗ull
 };
 function convertIdToValue(data) {
-  if (!data || !Array.isArray(data)) return [];
-  return data.map((item) => {
-    const { id, children, ...rest } = item;
-    const newItem = {
-      ...rest,
-      value: id, // 灏� id 鏀逛负 value
-    };
-    if (children && children.length > 0) {
-      newItem.children = convertIdToValue(children);
-    }
-
-    return newItem;
-  });
+	return data.map((item) => {
+		const { id, children, ...rest } = item;
+		const newItem = {
+			...rest,
+			value: id, // 灏� id 鏀逛负 value
+		};
+		if (children && children.length > 0) {
+			newItem.children = convertIdToValue(children);
+		}
+		
+		return newItem;
+	});
+}
+// 鏍规嵁鍚嶇О鍙嶆煡浜у搧澶х被 id锛屼究浜庝粎瀛樺悕绉版椂鐨勫弽鏄�
+function findNodeIdByLabel(nodes, label) {
+	if (!label) return null;
+	for (let i = 0; i < nodes.length; i++) {
+		const node = nodes[i];
+		if (node.label === label) return node.value;
+		if (node.children && node.children.length > 0) {
+			const found = findNodeIdByLabel(node.children, label);
+			if (found !== null && found !== undefined) return found;
+		}
+	}
+	return null;
 }
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
-  // 杩囨护鎺夊瓙鏁版嵁
-  selectedRows.value = selection.filter((item) => item.children !== undefined);
-  console.log("selection", selectedRows.value);
+	// 杩囨护鎺夊瓙鏁版嵁
+	selectedRows.value = selection.filter((item) => item.children !== undefined);
+	console.log("selection", selectedRows.value);
 };
 const productSelected = (selectedRows) => {
-  productSelectedRows.value = selectedRows;
+	productSelectedRows.value = selectedRows;
 };
 const expandedRowKeys = ref([]);
-// 灞曞紑琛岋紙濮嬬粓鍙睍寮�涓�琛岋級
-const expandChange = (row) => {
-  const rowKey = row.id;
-  const isExpanded = expandedRowKeys.value.includes(rowKey);
-
-  if (isExpanded) {
-    // 褰撳墠琛屽凡灞曞紑 -> 鏀惰捣
-    expandedRowKeys.value = [];
-    return;
-  }
-
-  // 灞曞紑褰撳墠琛屽墠锛屽厛鏀惰捣鍏跺畠琛�
-  expandedRowKeys.value = [];
-
-  try {
-    productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
-      const index = tableData.value.findIndex((item) => item.id === row.id);
-      if (index > -1) {
-        tableData.value[index].children = res.data;
-      }
-      // 鍙繚鐣欏綋鍓嶈繖涓�琛屽浜庡睍寮�鐘舵��
-      expandedRowKeys.value = [rowKey];
-    });
-  } catch (error) {
-    console.log(error);
-  }
+// 灞曞紑琛�
+const expandChange = (row, expandedRows) => {
+	if (expandedRows.length > 0) {
+		expandedRowKeys.value = [];
+		try {
+			productList({ salesLedgerId: row.id, type: 1 }).then((res) => {
+				const index = tableData.value.findIndex((item) => item.id === row.id);
+				if (index > -1) {
+					tableData.value[index].children = res.data;
+				}
+				expandedRowKeys.value.push(row.id);
+			});
+		} catch (error) {
+			console.log(error);
+		}
+	} else {
+		expandedRowKeys.value = [];
+	}
 };
 // 涓昏〃鍚堣鏂规硶
 const summarizeMainTable = (param) => {
-  return proxy.summarizeTable(param, [
-    "contractAmount",
-    "taxInclusiveTotalPrice",
-    "taxExclusiveTotalPrice",
-  ]);
+	return proxy.summarizeTable(param, [
+		"contractAmount",
+		"taxInclusiveTotalPrice",
+		"taxExclusiveTotalPrice",
+	]);
 };
 // 瀛愯〃鍚堣鏂规硶
 const summarizeChildrenTable = (param) => {
-  return proxy.summarizeTable(param, [
-    "taxInclusiveUnitPrice",
-    "taxInclusiveTotalPrice",
-    "taxExclusiveTotalPrice",
-  ]);
+	return proxy.summarizeTable(param, [
+		"taxInclusiveUnitPrice",
+		"taxInclusiveTotalPrice",
+		"taxExclusiveTotalPrice",
+	]);
 };
 // 鎵撳紑寮规
 const openForm = async (type, row) => {
-  operationType.value = type;
-  form.value = {};
-  productData.value = [];
-  customerList().then((res) => {
-    customerOption.value = res;
-  });
-  form.value.entryPerson = userStore.id;
-  if (type !== "add") {
-    currentId.value = row.id;
-    getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
-      form.value = { ...res };
-      form.value.entryPerson = Number(res.entryPerson);
-      productData.value = form.value.productData;
-      fileList.value = form.value.salesLedgerFiles;
-    });
-  }
-  // let userAll = await userStore.getInfo()
-  // userList.value.forEach(element => {
-  //   if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
-  //     form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
-  //   }
-  // });
-  form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
-  dialogFormVisible.value = true;
+	operationType.value = type;
+	form.value = {};
+	productData.value = [];
+	selectedQuotation.value = null;
+	let userLists = await userListNoPage();
+	userList.value = userLists.data;
+	customerList().then((res) => {
+		customerOption.value = res;
+	});
+	form.value.entryPerson = userStore.id;
+	if (type === "add") {
+		// 鏂板鏃惰缃綍鍏ユ棩鏈熶负褰撳ぉ
+		form.value.entryDate = getCurrentDate();
+		// 绛捐鏃ユ湡榛樿涓哄綋澶�
+		form.value.executionDate = getCurrentDate();
+	} else {
+		currentId.value = row.id;
+		getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
+			form.value = { ...res };
+			form.value.entryPerson = Number(res.entryPerson);
+			productData.value = form.value.productData;
+			fileList.value = form.value.salesLedgerFiles;
+		});
+	}
+	// let userAll = await userStore.getInfo()
+	// userList.value.forEach(element => {
+	//   if(userAll.user.nickName === element.nickName && userAll.user.userName === element.userName) {
+	//     form.value.entryPerson = userAll.user.userId // 璁剧疆榛樿涓氬姟鍛樹负褰撳墠鐢ㄦ埛
+	//   }
+	// });
+	form.value.entryDate = getCurrentDate(); // 璁剧疆榛樿褰曞叆鏃ユ湡涓哄綋鍓嶆棩鏈�
+	dialogFormVisible.value = true;
+};
+
+// 鎵撳紑鎶ヤ环鍗曢�夋嫨寮圭獥锛堜粎瀹℃壒閫氳繃锛�
+const openQuotationDialog = async () => {
+	if (operationType.value === "view") return;
+	quotationDialogVisible.value = true;
+	// 鍏堢‘淇濆鎴峰垪琛ㄥ凡鍔犺浇锛屼究浜庡悗缁洖濉� customerId
+	if (!customerOption.value || customerOption.value.length === 0) {
+		try {
+			const res = await customerList();
+			customerOption.value = res;
+		} catch (e) {
+			// ignore锛屽厑璁哥敤鎴峰悗缁墜鍔ㄩ�夋嫨瀹㈡埛
+		}
+	}
+	await fetchQuotationList();
+};
+
+const fetchQuotationList = async () => {
+	quotationLoading.value = true;
+	try {
+		const params = {
+			// 鍏煎鍚庣鍒嗛〉瀛楁锛氳繖閲屾部鐢ㄦ姤浠烽〉闈㈠凡鏈夊彲鐢ㄧ殑瀛楁鍛藉悕
+			currentPage: 1,
+			pageSize: 100,
+			...quotationSearchForm,
+			status: "閫氳繃",
+		};
+		const res = await getQuotationList(params);
+		quotationList.value = res?.data?.records || [];
+	} finally {
+		quotationLoading.value = false;
+	}
+};
+
+const resetQuotationSearch = async () => {
+	quotationSearchForm.quotationNo = "";
+	quotationSearchForm.customer = "";
+	await fetchQuotationList();
+};
+
+// 閫変腑鎶ヤ环鍗曞悗鍥炲~鍒板彴璐﹁〃鍗�
+const applyQuotation = (row) => {
+	if (!row) return;
+	selectedQuotation.value = row;
+	
+	// 涓氬姟鍛�
+	form.value.salesman = row.salesperson || "";
+	
+	// 瀹㈡埛鍚嶇О -> customerId
+	const customer = (customerOption.value || []).find((c) => c.customerName === row.customer);
+	if (customer?.id) {
+		form.value.customerId = customer.id;
+	} else {
+		// 濡傛灉鎵句笉鍒帮紝淇濈暀鍘熷�硷紙鍏佽鐢ㄦ埛鎵嬪姩閫夋嫨/涓嶆墦鏂凡鏈夎緭鍏ワ級
+		form.value.customerId = form.value.customerId || "";
+	}
+	
+	// 浜у搧淇℃伅鏄犲皠锛氭姤浠� products -> 鍙拌处 productData
+	const products = Array.isArray(row.products) ? row.products : [];
+	productData.value = products.map((p) => {
+		const quantity = Number(p.quantity ?? 0) || 0;
+		const unitPrice = Number(p.unitPrice ?? 0) || 0;
+		const taxRate = "13"; // 榛樿 13%锛屼究浜庣洿鎺ユ彁浜わ紙濡傞渶鍙湪浜у搧涓嚜琛屼慨鏀癸級
+		const taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+		const taxExclusiveTotalPrice = proxy.calculateTaxExclusiveTotalPrice(taxInclusiveTotalPrice, taxRate);
+		return {
+			// 鍙拌处瀛楁
+			productCategory: p.product || p.productName || "",
+			specificationModel: p.specification || "",
+			unit: p.unit || "",
+			quantity: quantity,
+			taxRate: taxRate,
+			taxInclusiveUnitPrice: unitPrice.toFixed(2),
+			taxInclusiveTotalPrice: taxInclusiveTotalPrice,
+			taxExclusiveTotalPrice: taxExclusiveTotalPrice,
+			invoiceType: "澧炴櫘绁�",
+		};
+	});
+	
+	quotationDialogVisible.value = false;
 };
 function changs(val) {
-  console.log(val);
+	console.log(val);
 }
 // 涓婁紶鍓嶆牎妫�
 function handleBeforeUpload(file) {
-  // 鏍℃鏂囦欢澶у皬
-  // if (file.size > 1024 * 1024 * 10) {
-  //   proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
-  //   return false;
-  // }
-  proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
-  return true;
+	// 鏍℃鏂囦欢澶у皬
+	// if (file.size > 1024 * 1024 * 10) {
+	//   proxy.$modal.msgError("涓婁紶鏂囦欢澶у皬涓嶈兘瓒呰繃10MB!");
+	//   return false;
+	// }
+	proxy.$modal.loading("姝e湪涓婁紶鏂囦欢锛岃绋嶅��...");
+	return true;
 }
 // 涓婁紶澶辫触
 function handleUploadError(err) {
-  proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
-  proxy.$modal.closeLoading();
+	proxy.$modal.msgError("涓婁紶鏂囦欢澶辫触");
+	proxy.$modal.closeLoading();
 }
 // 涓婁紶鎴愬姛鍥炶皟
 function handleUploadSuccess(res, file, uploadFiles) {
-  proxy.$modal.closeLoading();
-  if (res.code === 200) {
-    file.tempId = res.data.tempId;
-    proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
-  } else {
-    proxy.$modal.msgError(res.msg);
-    proxy.$refs.fileUpload.handleRemove(file);
-  }
+	proxy.$modal.closeLoading();
+	if (res.code === 200) {
+		file.tempId = res.data.tempId;
+		proxy.$modal.msgSuccess("涓婁紶鎴愬姛");
+	} else {
+		proxy.$modal.msgError(res.msg);
+		proxy.$refs.fileUpload.handleRemove(file);
+	}
 }
 // 绉婚櫎鏂囦欢
 function handleRemove(file) {
-  if (operationType.value === "edit") {
-    let ids = [];
-    ids.push(file.id);
-    delLedgerFile(ids).then((res) => {
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-    });
-  }
+	if (operationType.value === "edit") {
+		let ids = [];
+		ids.push(file.id);
+		delLedgerFile(ids).then((res) => {
+			proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+		});
+	}
 }
 // 鎻愪氦琛ㄥ崟
 const submitForm = () => {
-  proxy.$refs["formRef"].validate((valid) => {
-    if (valid) {
+	proxy.$refs["formRef"].validate((valid) => {
+		if (valid) {
 			console.log('productData.value--', productData.value)
-      if (productData.value !== null && productData.value.length > 0) {
-        form.value.productData = proxy.HaveJson(productData.value);
-      } else {
-        proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
-        return;
-      }
-      let tempFileIds = [];
-      if (fileList.value !== null && fileList.value.length > 0) {
-        tempFileIds = fileList.value.map((item) => item.tempId);
-      }
-      form.value.tempFileIds = tempFileIds;
-      form.value.type = 1;
-      addOrUpdateSalesLedger(form.value).then((res) => {
-        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-        closeDia();
-        getList();
-      });
-    }
-  });
+			if (productData.value !== null && productData.value.length > 0) {
+				form.value.productData = proxy.HaveJson(productData.value);
+			} else {
+				proxy.$modal.msgWarning("璇锋坊鍔犱骇鍝佷俊鎭�");
+				return;
+			}
+			let tempFileIds = [];
+			if (fileList.value !== null && fileList.value.length > 0) {
+				tempFileIds = fileList.value.map((item) => item.tempId);
+			}
+			form.value.tempFileIds = tempFileIds;
+			form.value.type = 1;
+			addOrUpdateSalesLedger(form.value).then((res) => {
+				proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+				closeDia();
+				getList();
+			});
+		}
+	});
 };
 // 鍏抽棴寮规
 const closeDia = () => {
-  proxy.resetForm("formRef");
-  dialogFormVisible.value = false;
+	proxy.resetForm("formRef");
+	dialogFormVisible.value = false;
 };
 
 const productIndex = ref(0);
 // 鎵撳紑浜у搧寮规
-const openProductForm =async (type, row,index) => {
-  productOperationType.value = type;
-  productForm.value = {};
-  proxy.resetForm("productFormRef");
-  // 鏂板銆佺紪杈戦兘闇�鍏堝姞杞戒骇鍝佹爲锛屽惁鍒� el-tree-select 鏃犳暟鎹�
-  try {
-    await getProductOptions();
-  } catch (e) {
-    console.error("鍔犺浇浜у搧鏍戝け璐�", e);
-  }
-  if (type === "edit") {
-    productForm.value = { ...row };
-    productIndex.value = index;
-  }
-  productFormVisible.value = true;
-  getProductOptions();
+const openProductForm = async (type, row, index) => {
+	productOperationType.value = type;
+	productForm.value = {};
+	proxy.resetForm("productFormRef");
+	if (type === "edit") {
+		productForm.value = { ...row };
+		productIndex.value = index;
+		// 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
+		try {
+			const options = productOptions.value && productOptions.value.length > 0
+				? productOptions.value
+				: await getProductOptions();
+			const categoryId = findNodeIdByLabel(options, productForm.value.productCategory);
+			if (categoryId) {
+				const models = await modelList({ id: categoryId });
+				modelOptions.value = models || [];
+				// 鏍规嵁褰撳墠瑙勬牸鍨嬪彿鍚嶇О鍙嶆煡骞惰缃� productModelId锛屼究浜庝笅鎷夋鏄剧ず宸查�夊��
+				const currentModel = (modelOptions.value || []).find(
+					(m) => m.model === productForm.value.specificationModel
+				);
+				if (currentModel) {
+					productForm.value.productModelId = currentModel.id;
+				}
+			}
+		} catch (e) {
+			// 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
+			console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
+		}
+	}
+	productFormVisible.value = true;
 };
 // 鎻愪氦浜у搧琛ㄥ崟
 const submitProduct = () => {
-  proxy.$refs["productFormRef"].validate((valid) => {
-    if (valid) {
-      if (operationType.value === "edit") {
-        submitProductEdit();
-      } else {
-        if(productOperationType.value === "add"){
-          productData.value.push({ ...productForm.value });
-        }else{
-          productData.value[productIndex.value] = { ...productForm.value }
-        }
-        closeProductDia();
-      }
-    }
-  });
+	proxy.$refs["productFormRef"].validate((valid) => {
+		if (valid) {
+			if (operationType.value === "edit") {
+				submitProductEdit();
+			} else {
+				if(productOperationType.value === "add"){
+					productData.value.push({ ...productForm.value });
+				}else{
+					productData.value[productIndex.value] = { ...productForm.value }
+				}
+				closeProductDia();
+			}
+		}
+	});
 };
 const submitProductEdit = () => {
-  productForm.value.salesLedgerId = currentId.value;
-  productForm.value.type = 1
-  addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
-    proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
-    closeProductDia();
-    getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
-      productData.value = res.productData;
-    });
-  });
+	productForm.value.salesLedgerId = currentId.value;
+	productForm.value.type = 1
+	addOrUpdateSalesLedgerProduct(productForm.value).then((res) => {
+		proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+		closeProductDia();
+		getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then((res) => {
+			productData.value = res.productData;
+		});
+	});
 };
 // 鍒犻櫎浜у搧
 const deleteProduct = () => {
-  if (productSelectedRows.value.length === 0) {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
-    return;
-  }
-  if (operationType.value === "add") {
-    productSelectedRows.value.forEach((selectedRow) => {
-      const index = productData.value.findIndex(
-        (product) => product.id === selectedRow.id
-      );
-      if (index !== -1) {
-        productData.value.splice(index, 1);
-      }
-    });
-  } else {
-    let ids = [];
-    if (productSelectedRows.value.length > 0) {
-      ids = productSelectedRows.value.map((item) => item.id);
-    }
-    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
-      confirmButtonText: "纭",
-      cancelButtonText: "鍙栨秷",
-      type: "warning",
-    })
-      .then(() => {
-        delProduct(ids).then((res) => {
-          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-          closeProductDia();
-          getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
-            (res) => {
-              productData.value = res.productData;
-            }
-          );
-        });
-      })
-      .catch(() => {
-        proxy.$modal.msg("宸插彇娑�");
-      });
-  }
+	if (productSelectedRows.value.length === 0) {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+	if (operationType.value === "add") {
+		productSelectedRows.value.forEach((selectedRow) => {
+			const index = productData.value.findIndex(
+				(product) => product.id === selectedRow.id
+			);
+			if (index !== -1) {
+				productData.value.splice(index, 1);
+			}
+		});
+	} else {
+		let ids = [];
+		if (productSelectedRows.value.length > 0) {
+			ids = productSelectedRows.value.map((item) => item.id);
+		}
+		ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+			confirmButtonText: "纭",
+			cancelButtonText: "鍙栨秷",
+			type: "warning",
+		})
+			.then(() => {
+				delProduct(ids).then((res) => {
+					proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+					closeProductDia();
+					getSalesLedgerWithProducts({ id: currentId.value, type: 1 }).then(
+						(res) => {
+							productData.value = res.productData;
+						}
+					);
+				});
+			})
+			.catch(() => {
+				proxy.$modal.msg("宸插彇娑�");
+			});
+	}
 };
 // 鍏抽棴浜у搧寮规
 const closeProductDia = () => {
-  proxy.resetForm("productFormRef");
-  productFormVisible.value = false;
+	proxy.resetForm("productFormRef");
+	productFormVisible.value = false;
 };
 // 瀵煎叆
 const handleImport = () => {
-  importUpload.title = "瀵煎叆閿�鍞彴璐�";
-  importUpload.open = true;
-  if (importUploadRef.value) {
-    importUploadRef.value.clearFiles();
-  }
+	importUpload.title = "瀵煎叆閿�鍞彴璐�";
+	importUpload.open = true;
+	if (importUploadRef.value) {
+		importUploadRef.value.clearFiles();
+	}
+};
+
+// 涓嬭浇瀵煎叆妯℃澘
+const downloadTemplate = () => {
+	proxy.download("/sales/ledger/exportTemplate", {}, "閿�鍞彴璐﹀鍏ユā鏉�.xlsx");
 };
 
 // 鎻愪氦瀵煎叆鏂囦欢
 const submitImportFile = () => {
-  importUpload.isUploading = true;
-  proxy.$refs["importUploadRef"].submit();
+	importUpload.isUploading = true;
+	proxy.$refs["importUploadRef"].submit();
 };
 
 // 瀵煎嚭
 const handleOut = () => {
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
-    })
-    .catch(() => {
-      proxy.$modal.msg("宸插彇娑�");
-    });
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚鍑猴紝鏄惁纭瀵煎嚭锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			proxy.download("/sales/ledger/export", {}, "閿�鍞彴璐�.xlsx");
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
 };
 // 鍒犻櫎
 const handleDelete = () => {
-  let ids = [];
-  if (selectedRows.value.length > 0) {
-    ids = selectedRows.value.map((item) => item.id);
-  } else {
-    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
-    return;
-  }
-  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
-    confirmButtonText: "纭",
-    cancelButtonText: "鍙栨秷",
-    type: "warning",
-  })
-    .then(() => {
-      delLedger(ids).then((res) => {
-        proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
-        getList();
-      });
-    })
-    .catch(() => {
-      proxy.$modal.msg("宸插彇娑�");
-    });
+	let ids = [];
+	if (selectedRows.value.length > 0) {
+		ids = selectedRows.value.map((item) => item.id);
+	} else {
+		proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+		return;
+	}
+	ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "瀵煎嚭", {
+		confirmButtonText: "纭",
+		cancelButtonText: "鍙栨秷",
+		type: "warning",
+	})
+		.then(() => {
+			delLedger(ids).then((res) => {
+				proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+				getList();
+			});
+		})
+		.catch(() => {
+			proxy.$modal.msg("宸插彇娑�");
+		});
 };
 
 // 鎵撳嵃鍔熻兘
@@ -1359,8 +1512,8 @@
                 </tr>
               </thead>
               <tbody>
-                ${item.products && item.products.length > 0 ? 
-                  item.products.map(product => `
+                ${item.products && item.products.length > 0 ?
+			item.products.map(product => `
                     <tr>
                       <td>${product.productCategory || ''}</td>
                       <td>${product.specificationModel || ''}</td>
@@ -1369,9 +1522,9 @@
                       <td>${product.quantity || '0'}</td>
                       <td>${product.taxInclusiveTotalPrice || '0'}</td>
                     </tr>
-                  `).join('') : 
-                  '<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
-                }
+                  `).join('') :
+			'<tr><td colspan="6" style="text-align: center; color: #999;">鏆傛棤浜у搧鏁版嵁</td></tr>'
+		}
               </tbody>
               <tfoot>
                 <tr>
@@ -1454,100 +1607,91 @@
 	const seconds = String(date.getSeconds()).padStart(2, "0");
 	return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
 };
-// 鑾峰彇褰撳墠鏃ユ湡骞舵牸寮忓寲涓� YYYY-MM-DD
-function getCurrentDate() {
-  const today = new Date();
-  const year = today.getFullYear();
-  const month = String(today.getMonth() + 1).padStart(2, "0"); // 鏈堜唤浠�0寮�濮�
-  const day = String(today.getDate()).padStart(2, "0");
-  return `${year}-${month}-${day}`;
-}
-
 // 璁$畻浜у搧鎬绘暟閲�
 const getTotalQuantity = (products) => {
-  if (!products || products.length === 0) return '0';
-  const total = products.reduce((sum, product) => {
-    return sum + (parseFloat(product.quantity) || 0);
-  }, 0);
-  return total.toFixed(2);
+	if (!products || products.length === 0) return '0';
+	const total = products.reduce((sum, product) => {
+		return sum + (parseFloat(product.quantity) || 0);
+	}, 0);
+	return total.toFixed(2);
 };
 
 // 璁$畻浜у搧鎬婚噾棰�
 const getTotalAmount = (products) => {
-  if (!products || products.length === 0) return '0';
-  const total = products.reduce((sum, product) => {
-    return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
-  }, 0);
-  return total.toFixed(2);
+	if (!products || products.length === 0) return '0';
+	const total = products.reduce((sum, product) => {
+		return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+	}, 0);
+	return total.toFixed(2);
 };
 
 // 鐢ㄤ簬鎵撳嵃鐨勮绠楀嚱鏁�
 const getTotalQuantityForPrint = (products) => {
-  if (!products || products.length === 0) return '0';
-  const total = products.reduce((sum, product) => {
-    return sum + (parseFloat(product.quantity) || 0);
-  }, 0);
-  return total.toFixed(2);
+	if (!products || products.length === 0) return '0';
+	const total = products.reduce((sum, product) => {
+		return sum + (parseFloat(product.quantity) || 0);
+	}, 0);
+	return total.toFixed(2);
 };
 
 const getTotalAmountForPrint = (products) => {
-  if (!products || products.length === 0) return '0';
-  const total = products.reduce((sum, product) => {
-    return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
-  }, 0);
-  return total.toFixed(2);
+	if (!products || products.length === 0) return '0';
+	const total = products.reduce((sum, product) => {
+		return sum + (parseFloat(product.taxInclusiveTotalPrice) || 0);
+	}, 0);
+	return total.toFixed(2);
 };
 
 const mathNum = () => {
-  console.log("productForm.value", productForm.value);
-  if (!productForm.value.taxInclusiveUnitPrice) {
-    return;
-  }
-  if (!productForm.value.quantity) {
-    return;
-  }
-  // 鍚◣鎬讳环璁$畻
-  productForm.value.taxInclusiveTotalPrice =
-    proxy.calculateTaxIncludeTotalPrice(
-      productForm.value.taxInclusiveUnitPrice,
-      productForm.value.quantity
-    );
-  if (productForm.value.taxRate) {
-    // 涓嶅惈绋庢�讳环璁$畻
-    productForm.value.taxExclusiveTotalPrice =
-      proxy.calculateTaxExclusiveTotalPrice(
-        productForm.value.taxInclusiveTotalPrice,
-        productForm.value.taxRate
-      );
-  }
+	console.log("productForm.value", productForm.value);
+	if (!productForm.value.taxInclusiveUnitPrice) {
+		return;
+	}
+	if (!productForm.value.quantity) {
+		return;
+	}
+	// 鍚◣鎬讳环璁$畻
+	productForm.value.taxInclusiveTotalPrice =
+		proxy.calculateTaxIncludeTotalPrice(
+			productForm.value.taxInclusiveUnitPrice,
+			productForm.value.quantity
+		);
+	if (productForm.value.taxRate) {
+		// 涓嶅惈绋庢�讳环璁$畻
+		productForm.value.taxExclusiveTotalPrice =
+			proxy.calculateTaxExclusiveTotalPrice(
+				productForm.value.taxInclusiveTotalPrice,
+				productForm.value.taxRate
+			);
+	}
 };
 
 // 鏍规嵁鍚◣鎬讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
 const calculateFromTotalPrice = () => {
-  if (isCalculating.value) return;
-  
-  const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
-  const quantity = parseFloat(productForm.value.quantity);
-  
-  if (!totalPrice || !quantity || quantity <= 0) {
-    return;
-  }
-  
-  isCalculating.value = true;
-  
-  // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
-  productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
-  
-  // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
-  if (productForm.value.taxRate) {
-    productForm.value.taxExclusiveTotalPrice =
-      proxy.calculateTaxExclusiveTotalPrice(
-        totalPrice,
-        productForm.value.taxRate
-      );
-  }
-  
-  isCalculating.value = false;
+	if (isCalculating.value) return;
+	
+	const totalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+	const quantity = parseFloat(productForm.value.quantity);
+	
+	if (!totalPrice || !quantity || quantity <= 0) {
+		return;
+	}
+	
+	isCalculating.value = true;
+	
+	// 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+	productForm.value.taxInclusiveUnitPrice = (totalPrice / quantity).toFixed(2);
+	
+	// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+	if (productForm.value.taxRate) {
+		productForm.value.taxExclusiveTotalPrice =
+			proxy.calculateTaxExclusiveTotalPrice(
+				totalPrice,
+				productForm.value.taxRate
+			);
+	}
+	
+	isCalculating.value = false;
 };
 
 // 鏍规嵁涓嶅惈绋庢�讳环璁$畻鍚◣鍗曚环鍜屾暟閲�
@@ -1556,27 +1700,27 @@
 		proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
 		return;
 	}
-  if (isCalculating.value) return;
-  
-  const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
-  const quantity = parseFloat(productForm.value.quantity);
-  const taxRate = parseFloat(productForm.value.taxRate);
-  
-  if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
-    return;
-  }
-  
-  isCalculating.value = true;
-  
-  // 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
-  const taxRateDecimal = taxRate / 100;
-  const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
-  productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
-  
-  // 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
-  productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
-  
-  isCalculating.value = false;
+	if (isCalculating.value) return;
+	
+	const exclusiveTotalPrice = parseFloat(productForm.value.taxExclusiveTotalPrice);
+	const quantity = parseFloat(productForm.value.quantity);
+	const taxRate = parseFloat(productForm.value.taxRate);
+	
+	if (!exclusiveTotalPrice || !quantity || quantity <= 0 || !taxRate) {
+		return;
+	}
+	
+	isCalculating.value = true;
+	
+	// 鍏堣绠楀惈绋庢�讳环 = 涓嶅惈绋庢�讳环 / (1 - 绋庣巼/100)
+	const taxRateDecimal = taxRate / 100;
+	const inclusiveTotalPrice = exclusiveTotalPrice / (1 - taxRateDecimal);
+	productForm.value.taxInclusiveTotalPrice = inclusiveTotalPrice.toFixed(2);
+	
+	// 璁$畻鍚◣鍗曚环 = 鍚◣鎬讳环 / 鏁伴噺
+	productForm.value.taxInclusiveUnitPrice = (inclusiveTotalPrice / quantity).toFixed(2);
+	
+	isCalculating.value = false;
 };
 
 // 鏍规嵁鏁伴噺鍙樺寲璁$畻鎬讳环
@@ -1585,30 +1729,30 @@
 		proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
 		return;
 	}
-  if (isCalculating.value) return;
-  
-  const quantity = parseFloat(productForm.value.quantity);
-  const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-  
-  if (!quantity || quantity <= 0 || !unitPrice) {
-    return;
-  }
-  
-  isCalculating.value = true;
-  
-  // 璁$畻鍚◣鎬讳环
-  productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-  
-  // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
-  if (productForm.value.taxRate) {
-    productForm.value.taxExclusiveTotalPrice =
-      proxy.calculateTaxExclusiveTotalPrice(
-        productForm.value.taxInclusiveTotalPrice,
-        productForm.value.taxRate
-      );
-  }
-  
-  isCalculating.value = false;
+	if (isCalculating.value) return;
+	
+	const quantity = parseFloat(productForm.value.quantity);
+	const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+	
+	if (!quantity || quantity <= 0 || !unitPrice) {
+		return;
+	}
+	
+	isCalculating.value = true;
+	
+	// 璁$畻鍚◣鎬讳环
+	productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+	
+	// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+	if (productForm.value.taxRate) {
+		productForm.value.taxExclusiveTotalPrice =
+			proxy.calculateTaxExclusiveTotalPrice(
+				productForm.value.taxInclusiveTotalPrice,
+				productForm.value.taxRate
+			);
+	}
+	
+	isCalculating.value = false;
 };
 
 // 鏍规嵁鍚◣鍗曚环鍙樺寲璁$畻鎬讳环
@@ -1617,30 +1761,30 @@
 		proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
 		return;
 	}
-  if (isCalculating.value) return;
-  
-  const quantity = parseFloat(productForm.value.quantity);
-  const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
-  
-  if (!quantity || quantity <= 0 || !unitPrice) {
-    return;
-  }
-  
-  isCalculating.value = true;
-  
-  // 璁$畻鍚◣鎬讳环
-  productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
-  
-  // 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
-  if (productForm.value.taxRate) {
-    productForm.value.taxExclusiveTotalPrice =
-      proxy.calculateTaxExclusiveTotalPrice(
-        productForm.value.taxInclusiveTotalPrice,
-        productForm.value.taxRate
-      );
-  }
-  
-  isCalculating.value = false;
+	if (isCalculating.value) return;
+	
+	const quantity = parseFloat(productForm.value.quantity);
+	const unitPrice = parseFloat(productForm.value.taxInclusiveUnitPrice);
+	
+	if (!quantity || quantity <= 0 || !unitPrice) {
+		return;
+	}
+	
+	isCalculating.value = true;
+	
+	// 璁$畻鍚◣鎬讳环
+	productForm.value.taxInclusiveTotalPrice = (unitPrice * quantity).toFixed(2);
+	
+	// 濡傛灉鏈夌◣鐜囷紝璁$畻涓嶅惈绋庢�讳环
+	if (productForm.value.taxRate) {
+		productForm.value.taxExclusiveTotalPrice =
+			proxy.calculateTaxExclusiveTotalPrice(
+				productForm.value.taxInclusiveTotalPrice,
+				productForm.value.taxRate
+			);
+	}
+	
+	isCalculating.value = false;
 };
 
 // 鏍规嵁绋庣巼鍙樺寲璁$畻涓嶅惈绋庢�讳环
@@ -1649,25 +1793,25 @@
 		proxy.$modal.msgWarning("璇峰厛閫夋嫨绋庣巼");
 		return;
 	}
-  if (isCalculating.value) return;
-  
-  const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
-  const taxRate = parseFloat(productForm.value.taxRate);
-  
-  if (!inclusiveTotalPrice || !taxRate) {
-    return;
-  }
-  
-  isCalculating.value = true;
-  
-  // 璁$畻涓嶅惈绋庢�讳环
-  productForm.value.taxExclusiveTotalPrice =
-    proxy.calculateTaxExclusiveTotalPrice(
-      inclusiveTotalPrice,
-      taxRate
-    );
-  
-  isCalculating.value = false;
+	if (isCalculating.value) return;
+	
+	const inclusiveTotalPrice = parseFloat(productForm.value.taxInclusiveTotalPrice);
+	const taxRate = parseFloat(productForm.value.taxRate);
+	
+	if (!inclusiveTotalPrice || !taxRate) {
+		return;
+	}
+	
+	isCalculating.value = true;
+	
+	// 璁$畻涓嶅惈绋庢�讳环
+	productForm.value.taxExclusiveTotalPrice =
+		proxy.calculateTaxExclusiveTotalPrice(
+			inclusiveTotalPrice,
+			taxRate
+		);
+	
+	isCalculating.value = false;
 };
 /**
  * 涓嬭浇鏂囦欢
@@ -1675,42 +1819,50 @@
  * @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
  */
 const fileListRef = ref(null)
+const fileListDialogVisible = ref(false)
 const downLoadFile = (row) => {
-  getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
-    fileListRef.value.open(res.salesLedgerFiles)
-  });
+	getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
+		if (fileListRef.value) {
+			fileListRef.value.open(res.salesLedgerFiles)
+			fileListDialogVisible.value = true
+		}
+	});
 }
 
 // 鎵撳紑鍙戣揣寮规
 const openDeliveryForm = (row) => {
-  currentDeliveryRow.value = row;
+	currentDeliveryRow.value = row;
   deliveryForm.value = {
-    shippingDate: "", // 绉婚櫎榛樿鍊艰缃�
-    shippingCarNumber: "",
+    type: "璐ц溅",
   };
-  deliveryFormVisible.value = true;
+  // 閲嶇疆瀹℃壒浜鸿妭鐐癸紙榛樿涓�涓┖鑺傜偣锛�
+  approverNodes.value = [{ id: 1, userId: null }];
+  nextApproverId = 2;
+	deliveryFormVisible.value = true;
 };
 
 // 鎻愪氦鍙戣揣琛ㄥ崟
 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(",");
       addShippingInfo({
-        approverId:deliveryForm.value.approverId,
         salesLedgerId: currentDeliveryRow.value.salesLedgerId,
         salesLedgerProductId: currentDeliveryRow.value.id,
-        shippingDate: deliveryForm.value.shippingDate,
-        shippingCarNumber: deliveryForm.value.shippingCarNumber,
+        type: deliveryForm.value.type,
+				approveUserIds,
       })
         .then(() => {
           proxy.$modal.msgSuccess("鍙戣揣鎴愬姛");
           closeDeliveryDia();
           getList();
-          expandedRowKeys.value = [];
         })
-        .catch(() => {
-          proxy.$modal.msgError("鍙戣揣澶辫触锛岃閲嶈瘯");
-        });
     }
   });
 };
@@ -1721,25 +1873,33 @@
   deliveryFormVisible.value = false;
   currentDeliveryRow.value = null;
 };
-
+const currentFactoryName = ref("");
+const getCurrentFactoryName = async () => {
+	let res = await userStore.getInfo();
+	currentFactoryName.value = res.user.currentFactoryName;
+};
 onMounted(() => {
 	getList();
+	userListNoPage().then(res => {
+		userList.value = res.data;
+	})
+	getCurrentFactoryName();
 });
 </script>
 
 <style scoped lang="scss">
 .ml-10 {
-  margin-left: 10px;
+	margin-left: 10px;
 }
 
 .table_list {
-  margin-top: unset;
+	margin-top: unset;
 }
 
 .actions {
-  display: flex;
-  justify-content: space-between;
-  margin-bottom: 10px;
+	display: flex;
+	justify-content: space-between;
+	margin-bottom: 10px;
 }
 .print-preview-dialog {
 	.el-dialog__body {

--
Gitblit v1.9.3