From ea6ad9ddc3d5b33897e93276282245f7023836ff Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 28 八月 2025 17:45:28 +0800
Subject: [PATCH] 大数据市场分析

---
 src/views/invoiceCollaboration/components/BatchDownloadDialog.vue |  704 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 704 insertions(+), 0 deletions(-)

diff --git a/src/views/invoiceCollaboration/components/BatchDownloadDialog.vue b/src/views/invoiceCollaboration/components/BatchDownloadDialog.vue
new file mode 100644
index 0000000..18e40a0
--- /dev/null
+++ b/src/views/invoiceCollaboration/components/BatchDownloadDialog.vue
@@ -0,0 +1,704 @@
+<template>
+  <el-dialog
+    :model-value="dialogVisible"
+    @update:model-value="$emit('update:dialogVisible', $event)"
+    title="鎵归噺涓嬭浇鍙戠エ"
+    width="800px"
+    :close-on-click-modal="false"
+    :close-on-press-escape="false"
+  >
+    <div class="batch-download-container">
+      <!-- 鍙戠エ鍒楄〃淇℃伅 -->
+      <el-card class="invoice-list" shadow="never">
+        <template #header>
+          <div class="card-header">
+            <span>寰呬笅杞藉彂绁ㄥ垪琛�</span>
+            <el-tag type="info" size="small" style="margin-left: 10px">
+              鍏� {{ invoices.length }} 寮犲彂绁�
+            </el-tag>
+          </div>
+        </template>
+        
+        <el-table :data="invoices" style="width: 100%" max-height="300">
+          <el-table-column prop="invoiceNo" label="鍙戠エ鍙风爜" width="120" />
+          <el-table-column prop="buyerName" label="璐拱鏂�" width="150" />
+          <el-table-column prop="amount" label="閲戦" width="100">
+            <template #default="scope">
+              楼{{ scope.row.amount.toFixed(2) }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="status" label="鐘舵��" width="100">
+            <template #default="scope">
+              <el-tag :type="getStatusType(scope.row.status)" size="small">
+                {{ getStatusText(scope.row.status) }}
+              </el-tag>
+            </template>
+          </el-table-column>
+        </el-table>
+      </el-card>
+
+      <!-- 涓嬭浇閫夐」 -->
+      <el-card class="download-options" shadow="never">
+        <template #header>
+          <div class="card-header">涓嬭浇閫夐」</div>
+        </template>
+        
+        <el-form :model="downloadOptions" label-width="120px">
+                     <!-- 鏂囦欢鏍煎紡 -->
+           <el-form-item label="鏂囦欢鏍煎紡">
+             <el-radio-group v-model="downloadOptions.format">
+               <el-radio label="html">HTML鏍煎紡</el-radio>
+               <el-radio label="excel">Excel鏍煎紡</el-radio>
+               <el-radio label="zip">ZIP鍘嬬缉鍖�</el-radio>
+             </el-radio-group>
+           </el-form-item>
+
+          <!-- 涓嬭浇鍐呭 -->
+          <el-form-item label="涓嬭浇鍐呭">
+            <el-checkbox-group v-model="downloadOptions.content">
+              <el-checkbox label="invoice">鍙戠エ姝f湰</el-checkbox>
+              <el-checkbox label="details">鏄庣粏娓呭崟</el-checkbox>
+              <el-checkbox label="summary">姹囨�绘姤琛�</el-checkbox>
+            </el-checkbox-group>
+          </el-form-item>
+
+          <!-- 鏂囦欢鍛藉悕 -->
+          <el-form-item label="鏂囦欢鍛藉悕">
+            <el-select v-model="downloadOptions.naming" style="width: 100%">
+              <el-option label="鍙戠エ鍙风爜_璐拱鏂瑰悕绉�" value="invoice_buyer" />
+              <el-option label="鍙戠エ鍙风爜_鏃ユ湡" value="invoice_date" />
+              <el-option label="璐拱鏂瑰悕绉癬鏃ユ湡" value="buyer_date" />
+              <el-option label="鑷畾涔夊墠缂�" value="custom" />
+            </el-select>
+          </el-form-item>
+
+          <!-- 鑷畾涔夊墠缂� -->
+          <el-form-item v-if="downloadOptions.naming === 'custom'" label="鑷畾涔夊墠缂�">
+            <el-input v-model="downloadOptions.customPrefix" placeholder="璇疯緭鍏ユ枃浠跺墠缂�" />
+          </el-form-item>
+
+          <!-- 鍘嬬缉閫夐」 -->
+          <el-form-item label="鍘嬬缉閫夐」">
+            <el-checkbox v-model="downloadOptions.compress">鍚敤鍘嬬缉</el-checkbox>
+            <el-checkbox v-model="downloadOptions.password">璁剧疆瑙e帇瀵嗙爜</el-checkbox>
+          </el-form-item>
+
+          <!-- 瑙e帇瀵嗙爜 -->
+          <el-form-item v-if="downloadOptions.password" label="瑙e帇瀵嗙爜">
+            <el-input v-model="downloadOptions.extractPassword" placeholder="璇疯緭鍏ヨВ鍘嬪瘑鐮�" />
+          </el-form-item>
+        </el-form>
+      </el-card>
+
+      <!-- 涓嬭浇杩涘害 -->
+      <el-card v-if="downloading" class="download-progress" shadow="never">
+        <template #header>
+          <div class="card-header">涓嬭浇杩涘害</div>
+        </template>
+        
+        <div class="progress-content">
+          <el-progress 
+            :percentage="downloadProgress" 
+            :status="downloadProgress === 100 ? 'success' : ''"
+            :stroke-width="20"
+          />
+          <div class="progress-text">
+            {{ downloadProgress === 100 ? '涓嬭浇瀹屾垚' : `姝e湪涓嬭浇... ${downloadProgress}%` }}
+          </div>
+          <div class="progress-detail">
+            {{ downloadProgress === 100 ? '鎵�鏈夊彂绁ㄤ笅杞藉畬鎴�' : `宸蹭笅杞� ${downloadedCount} 寮狅紝鍓╀綑 ${invoices.length - downloadedCount} 寮燻 }}
+          </div>
+        </div>
+      </el-card>
+    </div>
+
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="handleClose" :disabled="downloading">鍙栨秷</el-button>
+        <el-button 
+          type="primary" 
+          @click="handleBatchDownload" 
+          :loading="downloading"
+          :disabled="!canDownload"
+        >
+          {{ downloading ? '涓嬭浇涓�...' : '寮�濮嬩笅杞�' }}
+        </el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+import { ref, computed, watch } from 'vue';
+import { ElMessage } from 'element-plus';
+
+// 瀹氫箟props
+const props = defineProps({
+  dialogVisible: {
+    type: Boolean,
+    default: false
+  },
+  invoices: {
+    type: Array,
+    default: () => []
+  }
+});
+
+// 瀹氫箟emits
+const emit = defineEmits(['update:dialogVisible', 'success']);
+
+// 鍝嶅簲寮忔暟鎹�
+const downloading = ref(false);
+const downloadProgress = ref(0);
+const downloadedCount = ref(0);
+const downloadOptions = ref({
+  format: 'pdf',
+  content: ['invoice'],
+  naming: 'invoice_buyer',
+  customPrefix: '',
+  compress: true,
+  password: false,
+  extractPassword: ''
+});
+
+// 璁$畻灞炴��
+const canDownload = computed(() => {
+  return props.invoices.length > 0 && !downloading.value;
+});
+
+// 鐩戝惉鍣�
+watch(() => props.invoices, () => {
+  // 閲嶇疆涓嬭浇鐘舵��
+  downloading.value = false;
+  downloadProgress.value = 0;
+  downloadedCount.value = 0;
+}, { immediate: true });
+
+// 鑾峰彇鐘舵�佺被鍨�
+const getStatusType = (status) => {
+  const statusMap = {
+    'issued': 'success',
+    'pending': 'warning',
+    'cancelled': 'danger'
+  };
+  return statusMap[status] || 'info';
+};
+
+// 鑾峰彇鐘舵�佹枃鏈�
+const getStatusText = (status) => {
+  const statusMap = {
+    'issued': '宸插紑绁�',
+    'pending': '寰呭紑绁�',
+    'cancelled': '宸蹭綔搴�'
+  };
+  return statusMap[status] || '鏈煡';
+};
+
+// 鍏抽棴瀵硅瘽妗�
+const handleClose = () => {
+  if (!downloading.value) {
+    emit('update:dialogVisible', false);
+  }
+};
+
+// 鎵归噺涓嬭浇
+const handleBatchDownload = async () => {
+  if (downloading.value) return;
+  
+  try {
+    downloading.value = true;
+    downloadProgress.value = 0;
+    downloadedCount.value = 0;
+    
+    // 鎵归噺涓嬭浇杩囩▼
+    if (downloadOptions.format === 'zip') {
+      // ZIP鏍煎紡锛氱敓鎴愬崟涓帇缂╁寘
+      await generateZIPFile();
+      downloadProgress.value = 100;
+      downloadedCount.value = props.invoices.length;
+    } else {
+      // 鍏朵粬鏍煎紡锛氶�愪釜涓嬭浇鏂囦欢
+      const totalInvoices = props.invoices.length;
+      const progressStep = 100 / totalInvoices;
+      
+      for (let i = 0; i < totalInvoices; i++) {
+        // 鐢熸垚鍗曚釜鍙戠エ鏂囦欢
+        await generateInvoiceFile(props.invoices[i], i);
+        
+        downloadedCount.value++;
+        downloadProgress.value = Math.round((i + 1) * progressStep);
+        
+        // 鐭殏寤惰繜锛岄伩鍏嶆祻瑙堝櫒闃诲
+        await new Promise(resolve => setTimeout(resolve, 200));
+      }
+      
+      // 鐢熸垚姹囨�绘枃浠�
+      if (downloadOptions.content.includes('summary')) {
+        await generateSummaryFile();
+      }
+    }
+    
+    // 涓嬭浇瀹屾垚
+    ElMessage.success(`鎴愬姛涓嬭浇 ${totalInvoices} 寮犲彂绁╜);
+    emit('success');
+    
+  } catch (error) {
+    console.error('鎵归噺涓嬭浇澶辫触:', error);
+    ElMessage.error("鎵归噺涓嬭浇澶辫触锛岃閲嶈瘯");
+    downloading.value = false;
+    downloadProgress.value = 0;
+    downloadedCount.value = 0;
+  }
+};
+
+// 鐢熸垚鍗曚釜鍙戠エ鏂囦欢
+const generateInvoiceFile = async (invoice, index) => {
+  try {
+    let fileContent, fileName, mimeType;
+    
+         if (downloadOptions.format === 'html') {
+       fileContent = generateHTMLContent(invoice);
+       fileName = `${getFileName(invoice, index)}.html`;
+       mimeType = 'text/html';
+     } else if (downloadOptions.content.includes('details')) {
+       fileContent = generateExcelContent(invoice);
+       fileName = `${getFileName(invoice, index)}.csv`;
+       mimeType = 'text/csv';
+     } else if (downloadOptions.format === 'excel') {
+      fileContent = generateExcelContent(invoice);
+      fileName = `${getFileName(invoice, index)}.csv`;
+      mimeType = 'text/csv';
+    } else if (downloadOptions.format === 'zip') {
+      // ZIP鏍煎紡闇�瑕佺壒娈婂鐞嗭紝杩欓噷鍏堣烦杩�
+      return;
+    }
+
+    // 鍒涘缓Blob瀵硅薄
+    const blob = new Blob([fileContent], { type: mimeType });
+    
+    // 鍒涘缓涓嬭浇閾炬帴
+    const url = window.URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = fileName;
+    
+    // 瑙﹀彂涓嬭浇
+    document.body.appendChild(link);
+    link.click();
+    
+    // 娓呯悊
+    document.body.removeChild(link);
+    window.URL.revokeObjectURL(url);
+    
+  } catch (error) {
+    console.error(`鐢熸垚鍙戠エ鏂囦欢澶辫触: ${invoice.invoiceNo}`, error);
+  }
+};
+
+// 鐢熸垚ZIP鍘嬬缉鍖�
+const generateZIPFile = async () => {
+  try {
+    // 鍔ㄦ�佸鍏SZip搴�
+    const JSZip = await import('jszip');
+    const zip = new JSZip.default();
+    
+    // 娣诲姞鍙戠エ鏂囦欢鍒癦IP
+    props.invoices.forEach((invoice, index) => {
+      let fileContent, fileName;
+      
+             if (downloadOptions.content.includes('invoice')) {
+         if (downloadOptions.content.includes('details')) {
+           fileContent = generateExcelContent(invoice);
+           fileName = `${getFileName(invoice, index)}.csv`;
+         } else {
+           fileContent = generateHTMLContent(invoice);
+           fileName = `${getFileName(invoice, index)}.html`;
+         }
+         zip.file(fileName, fileContent);
+       }
+    });
+    
+    // 娣诲姞姹囨�绘枃浠�
+    if (downloadOptions.content.includes('summary')) {
+      const summaryContent = generateSummaryContent();
+      zip.file('鍙戠エ姹囨��.csv', summaryContent);
+    }
+    
+    // 鐢熸垚ZIP鏂囦欢
+    const zipBlob = await zip.generateAsync({ 
+      type: 'blob',
+      compression: downloadOptions.compress ? 'DEFLATE' : 'STORE'
+    });
+    
+    // 涓嬭浇ZIP鏂囦欢
+    const fileName = `鍙戠エ鎵归噺涓嬭浇_${new Date().toISOString().split('T')[0]}.zip`;
+    const url = window.URL.createObjectURL(zipBlob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = fileName;
+    
+    document.body.appendChild(link);
+    link.click();
+    
+    document.body.removeChild(link);
+    window.URL.revokeObjectURL(url);
+    
+  } catch (error) {
+    console.error('鐢熸垚ZIP鏂囦欢澶辫触:', error);
+    ElMessage.error('ZIP鏂囦欢鐢熸垚澶辫触锛岃妫�鏌ユ槸鍚﹀畨瑁呬簡jszip搴�');
+  }
+};
+
+// 鐢熸垚姹囨�绘枃浠�
+const generateSummaryFile = async () => {
+  try {
+    const summaryContent = generateSummaryContent();
+    const fileName = `鍙戠エ姹囨�籣${new Date().toISOString().split('T')[0]}.csv`;
+    
+    const blob = new Blob([summaryContent], { type: 'text/csv;charset=utf-8;' });
+    const url = window.URL.createObjectURL(blob);
+    const link = document.createElement('a');
+    link.href = url;
+    link.download = fileName;
+    
+    document.body.appendChild(link);
+    link.click();
+    
+    document.body.removeChild(link);
+    window.URL.revokeObjectURL(url);
+    
+  } catch (error) {
+    console.error('鐢熸垚姹囨�绘枃浠跺け璐�:', error);
+  }
+};
+
+// 鑾峰彇鏂囦欢鍚�
+const getFileName = (invoice, index) => {
+  let fileName = '';
+  
+  if (downloadOptions.naming === 'invoice_buyer') {
+    fileName = `${invoice.invoiceNo}_${invoice.buyerName}`;
+  } else if (downloadOptions.naming === 'invoice_date') {
+    fileName = `${invoice.invoiceNo}_${invoice.invoiceDate}`;
+  } else if (downloadOptions.naming === 'buyer_date') {
+    fileName = `${invoice.buyerName}_${invoice.invoiceDate}`;
+  } else if (downloadOptions.naming === 'custom') {
+    fileName = `${downloadOptions.customPrefix || '鍙戠エ'}_${index + 1}`;
+  }
+  
+  // 娓呯悊鏂囦欢鍚嶄腑鐨勭壒娈婂瓧绗�
+  return fileName.replace(/[<>:"/\\|?*]/g, '_');
+};
+
+// 鐢熸垚HTML鍐呭
+const generateHTMLContent = (invoice) => {
+  const content = `<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>鍙戠エ淇℃伅 - ${invoice.invoiceNo || 'N/A'}</title>
+    <style>
+        body {
+            font-family: 'Microsoft YaHei', Arial, sans-serif;
+            margin: 0;
+            padding: 20px;
+            background-color: #f5f5f5;
+        }
+        .invoice-container {
+            max-width: 800px;
+            margin: 0 auto;
+            background: white;
+            border-radius: 8px;
+            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+            overflow: hidden;
+        }
+        .invoice-header {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            color: white;
+            padding: 30px;
+            text-align: center;
+        }
+        .invoice-header h1 {
+            margin: 0;
+            font-size: 28px;
+            font-weight: 300;
+        }
+        .invoice-header .subtitle {
+            margin-top: 10px;
+            opacity: 0.9;
+            font-size: 16px;
+        }
+        .invoice-content {
+            padding: 30px;
+        }
+        .info-section {
+            margin-bottom: 25px;
+        }
+        .info-section h3 {
+            color: #333;
+            border-bottom: 2px solid #667eea;
+            padding-bottom: 8px;
+            margin-bottom: 15px;
+        }
+        .info-grid {
+            display: grid;
+            grid-template-columns: 1fr 1fr;
+            gap: 15px;
+        }
+        .info-item {
+            display: flex;
+            align-items: center;
+            padding: 12px;
+            background: #f8f9fa;
+            border-radius: 6px;
+            border-left: 4px solid #667eea;
+        }
+        .info-label {
+            font-weight: bold;
+            color: #555;
+            min-width: 100px;
+        }
+        .info-value {
+            color: #333;
+            margin-left: 10px;
+        }
+        .amount-section {
+            background: #f8f9fa;
+            padding: 20px;
+            border-radius: 8px;
+            margin-top: 20px;
+        }
+        .amount-grid {
+            display: grid;
+            grid-template-columns: repeat(3, 1fr);
+            gap: 20px;
+        }
+        .amount-item {
+            text-align: center;
+            padding: 15px;
+            background: white;
+            border-radius: 6px;
+            box-shadow: 0 1px 3px rgba(0,0,0,0.1);
+        }
+        .amount-label {
+            font-size: 14px;
+            color: #666;
+            margin-bottom: 8px;
+        }
+        .amount-value {
+            font-size: 24px;
+            font-weight: bold;
+            color: #667eea;
+        }
+        .footer {
+            text-align: center;
+            padding: 20px;
+            color: #666;
+            border-top: 1px solid #eee;
+            margin-top: 20px;
+        }
+        @media print {
+            body { background: white; }
+            .invoice-container { box-shadow: none; }
+        }
+    </style>
+</head>
+<body>
+    <div class="invoice-container">
+        <div class="invoice-header">
+            <h1>鍙戠エ淇℃伅</h1>
+            <div class="subtitle">Invoice Information</div>
+        </div>
+        
+        <div class="invoice-content">
+            <div class="info-section">
+                <h3>鍩烘湰淇℃伅</h3>
+                <div class="info-grid">
+                    <div class="info-item">
+                        <span class="info-label">鍙戠エ鍙风爜:</span>
+                        <span class="info-value">${invoice.invoiceNo || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">鍙戠エ浠g爜:</span>
+                        <span class="info-value">${invoice.invoiceCode || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">寮�绁ㄦ棩鏈�:</span>
+                        <span class="info-value">${invoice.invoiceDate || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">鐘舵��:</span>
+                        <span class="info-value">${getStatusText(invoice.status)}</span>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="info-section">
+                <h3>璐拱鏂逛俊鎭�</h3>
+                <div class="info-grid">
+                    <div class="info-item">
+                        <span class="info-label">璐拱鏂瑰悕绉�:</span>
+                        <span class="info-value">${invoice.buyerName || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">璐拱鏂圭◣鍙�:</span>
+                        <span class="info-value">${invoice.buyerTaxNo || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">璐拱鏂瑰湴鍧�:</span>
+                        <span class="info-value">${invoice.buyerAddress || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">閾惰璐︽埛:</span>
+                        <span class="info-value">${invoice.buyerBankAccount || 'N/A'}</span>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="info-section">
+                <h3>閿�鍞柟淇℃伅</h3>
+                <div class="info-grid">
+                    <div class="info-item">
+                        <span class="info-label">閿�鍞柟鍚嶇О:</span>
+                        <span class="info-value">${invoice.sellerName || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">閿�鍞柟绋庡彿:</span>
+                        <span class="info-value">${invoice.sellerTaxNo || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">閿�鍞柟鍦板潃:</span>
+                        <span class="info-value">${invoice.sellerAddress || 'N/A'}</span>
+                    </div>
+                    <div class="info-item">
+                        <span class="info-label">閾惰璐︽埛:</span>
+                        <span class="info-value">${invoice.sellerBankAccount || 'N/A'}</span>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="amount-section">
+                <h3>閲戦淇℃伅</h3>
+                <div class="amount-grid">
+                    <div class="amount-item">
+                        <div class="amount-label">閲戦</div>
+                        <div class="amount-value">楼${(invoice.amount || 0).toFixed(2)}</div>
+                    </div>
+                    <div class="info-item">
+                        <div class="amount-label">绋庨</div>
+                        <div class="amount-value">楼${(invoice.taxAmount || 0).toFixed(2)}</div>
+                    </div>
+                    <div class="amount-item">
+                        <div class="amount-label">浠风◣鍚堣</div>
+                        <div class="amount-value">楼${(invoice.totalAmount || 0).toFixed(2)}</div>
+                    </div>
+                </div>
+            </div>
+            
+            <div class="footer">
+                <p>鐢熸垚鏃堕棿: ${new Date().toLocaleString()}</p>
+                <p>姝ゆ枃浠剁敱绯荤粺鑷姩鐢熸垚</p>
+            </div>
+        </div>
+    </div>
+</body>
+</html>`;
+  
+  return content;
+};
+
+// 鐢熸垚Excel鍐呭
+const generateExcelContent = (invoice) => {
+  const content = `鍙戠エ淇℃伅
+鍙戠エ鍙风爜,${invoice.invoiceNo || 'N/A'}
+鍙戠エ浠g爜,${invoice.invoiceCode || 'N/A'}
+寮�绁ㄦ棩鏈�,${invoice.invoiceDate || 'N/A'}
+璐拱鏂瑰悕绉�,${invoice.buyerName || 'N/A'}
+閿�鍞柟鍚嶇О,${invoice.sellerName || 'N/A'}
+閲戦,${(invoice.amount || 0).toFixed(2)}
+绋庨,${(invoice.taxAmount || 0).toFixed(2)}
+浠风◣鍚堣,${(invoice.totalAmount || 0).toFixed(2)}
+鐘舵��,${getStatusText(invoice.status)}
+鍒涘缓鏃堕棿,${invoice.createTime || 'N/A'}`;
+  return content;
+};
+
+// 鐢熸垚姹囨�诲唴瀹�
+const generateSummaryContent = () => {
+  let content = '鍙戠エ姹囨�绘姤琛╘n';
+  content += '鍙戠エ鍙风爜,鍙戠エ浠g爜,寮�绁ㄦ棩鏈�,璐拱鏂瑰悕绉�,閿�鍞柟鍚嶇О,閲戦,绋庨,浠风◣鍚堣,鐘舵��,鍒涘缓鏃堕棿\n';
+  
+  props.invoices.forEach(invoice => {
+    content += `${invoice.invoiceNo || 'N/A'},${invoice.invoiceCode || 'N/A'},${invoice.invoiceDate || 'N/A'},${invoice.buyerName || 'N/A'},${invoice.sellerName || 'N/A'},${(invoice.amount || 0).toFixed(2)},${(invoice.taxAmount || 0).toFixed(2)},${(invoice.totalAmount || 0).toFixed(2)},${getStatusText(invoice.status)},${invoice.createTime || 'N/A'}\n`;
+  });
+  
+  // 娣诲姞鍚堣琛�
+  const totalAmount = props.invoices.reduce((sum, item) => sum + (item.amount || 0), 0);
+  const totalTaxAmount = props.invoices.reduce((sum, item) => sum + (item.taxAmount || 0), 0);
+  const totalSum = props.invoices.reduce((sum, item) => sum + (item.totalAmount || 0), 0);
+  
+  content += `鍚堣,,,,,${totalAmount.toFixed(2)},${totalTaxAmount.toFixed(2)},${totalSum.toFixed(2)},,`;
+  
+  return content;
+};
+</script>
+
+<style scoped>
+.batch-download-container {
+  padding: 0;
+}
+
+.invoice-list,
+.download-options,
+.download-progress {
+  margin-bottom: 20px;
+}
+
+.invoice-list:last-child,
+.download-options:last-child,
+.download-progress:last-child {
+  margin-bottom: 0;
+}
+
+.card-header {
+  font-weight: bold;
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+}
+
+.progress-content {
+  padding: 20px 0;
+  text-align: center;
+}
+
+.progress-text {
+  margin-top: 15px;
+  font-size: 16px;
+  font-weight: bold;
+  color: #409eff;
+}
+
+.progress-detail {
+  margin-top: 10px;
+  color: #606266;
+  font-size: 14px;
+}
+
+.dialog-footer {
+  text-align: right;
+}
+
+.el-radio-group {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+
+.el-checkbox-group {
+  display: flex;
+  flex-direction: column;
+  gap: 10px;
+}
+</style>

--
Gitblit v1.9.3