Selaa lähdekoodia

Merge remote-tracking branch 'origin/master'

gogs 2 kuukautta sitten
vanhempi
sitoutus
075afb788a

+ 5 - 2
app/Exports/ResearchExpenseSummaryMultipleSheetExport.php

@@ -6,7 +6,7 @@ use Maatwebsite\Excel\Concerns\WithMultipleSheets;
 
 
 class ResearchExpenseSummaryMultipleSheetExport implements WithMultipleSheets
 class ResearchExpenseSummaryMultipleSheetExport implements WithMultipleSheets
 {
 {
-    protected $data; // 格式: ['2026' => [ 'items' => [...], 'summary' => [...] ], '2025' => [...] ]
+    protected $data;
 
 
     public function __construct(array $data)
     public function __construct(array $data)
     {
     {
@@ -17,7 +17,10 @@ class ResearchExpenseSummaryMultipleSheetExport implements WithMultipleSheets
     {
     {
         $sheets = [];
         $sheets = [];
         foreach ($this->data as $year => $payload) {
         foreach ($this->data as $year => $payload) {
-            $sheets[] = new ResearchExpenseSummarySheetExport($year, $payload);
+            // 从 payload 中提取动态表头,如果没有则给默认值
+            $dynamicHeaders = $payload['dynamic_headers'] ?? ['人员人工费用', '折旧费用'];
+
+            $sheets[] = new ResearchExpenseSummarySheetExport($year, $payload, $dynamicHeaders);
         }
         }
         return $sheets;
         return $sheets;
     }
     }

+ 119 - 80
app/Exports/ResearchExpenseSummarySheetExport.php

@@ -7,6 +7,7 @@ use Maatwebsite\Excel\Concerns\WithTitle;
 use Maatwebsite\Excel\Events\AfterSheet;
 use Maatwebsite\Excel\Events\AfterSheet;
 use PhpOffice\PhpSpreadsheet\Style\Alignment;
 use PhpOffice\PhpSpreadsheet\Style\Alignment;
 use PhpOffice\PhpSpreadsheet\Style\Border;
 use PhpOffice\PhpSpreadsheet\Style\Border;
+use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
 
 
 class ResearchExpenseSummarySheetExport implements WithEvents, WithTitle
 class ResearchExpenseSummarySheetExport implements WithEvents, WithTitle
 {
 {
@@ -14,13 +15,15 @@ class ResearchExpenseSummarySheetExport implements WithEvents, WithTitle
     protected $items;
     protected $items;
     protected $taxId;
     protected $taxId;
     protected $companyName;
     protected $companyName;
+    protected $dynamicHeaders;
 
 
-    public function __construct($year, array $payload)
+    public function __construct($year, array $payload, array $dynamicHeaders = [])
     {
     {
         $this->year = $year;
         $this->year = $year;
         $this->items = $payload['items'] ?? [];
         $this->items = $payload['items'] ?? [];
         $this->taxId = $payload['tax_id'] ?? '';
         $this->taxId = $payload['tax_id'] ?? '';
         $this->companyName = $payload['company_name'] ?? '';
         $this->companyName = $payload['company_name'] ?? '';
+        $this->dynamicHeaders = $dynamicHeaders ?: ['人员人工费用', '折旧费用'];
     }
     }
 
 
     public function title(): string { return $this->year . '年汇总表'; }
     public function title(): string { return $this->year . '年汇总表'; }
@@ -31,17 +34,35 @@ class ResearchExpenseSummarySheetExport implements WithEvents, WithTitle
             AfterSheet::class => function (AfterSheet $event) {
             AfterSheet::class => function (AfterSheet $event) {
                 $sheet = $event->sheet->getDelegate();
                 $sheet = $event->sheet->getDelegate();
 
 
-                // 1. 设置列宽 (A-Q)
-                $widths = ['A'=>12, 'B'=>40, 'C'=>10, 'D'=>12, 'E'=>18, 'F'=>12, 'G'=>12, 'H'=>12, 'I'=>12, 'J'=>12, 'K'=>15, 'L'=>12, 'M'=>12, 'N'=>12, 'O'=>12, 'P'=>12, 'Q'=>12];
-                foreach ($widths as $col => $w) { $sheet->getColumnDimension($col)->setWidth($w); }
+                // 1. 计算列索引
+                $totalDynamic = count($this->dynamicHeaders);
+                $startDetailIdx = 6; // F列
+
+                $col_E = 'E';
+                $col_6 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic);
+                $col_7_1 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic + 1);
+                $col_7_2 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic + 2);
+                $col_8_1 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic + 3);
+                $col_8_2 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic + 4);
+                $col_8_3 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic + 5);
+                $col_8_4 = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic + 6);
+
+                $highestColumn = $col_8_4;
+
+                // 2. 设置布局
+                $sheet->getColumnDimension('B')->setWidth(40);
+                $lastColNum = Coordinate::columnIndexFromString($highestColumn);
+                for ($i = 1; $i <= $lastColNum; $i++) {
+                    $col = Coordinate::stringFromColumnIndex($i);
+                    if ($col != 'B') $sheet->getColumnDimension($col)->setWidth(13);
+                }
 
 
-                // 2. 绘制表头 (去大标题样式)
-                $this->drawCorrectHeader($sheet);
+                // 3. 绘制表头
+                $this->drawDynamicHeader($sheet, $col_E, $col_6, $col_7_1, $col_8_1, $highestColumn);
 
 
-                // 3. 填充数据
+                // 4. 填充明细
                 $currentRow = 8;
                 $currentRow = 8;
-                $capRows = []; // 仅存 资本化且已完成(status=3) 的行
-                $expRows = []; // 存 费用化 的行
+                $capRows = []; $expRows = [];
 
 
                 foreach ($this->items as $item) {
                 foreach ($this->items as $item) {
                     $sheet->setCellValue("A{$currentRow}", $item['no']);
                     $sheet->setCellValue("A{$currentRow}", $item['no']);
@@ -49,84 +70,106 @@ class ResearchExpenseSummarySheetExport implements WithEvents, WithTitle
                     $sheet->setCellValue("C{$currentRow}", $item['status'] == 3 ? '已完成' : '进行中');
                     $sheet->setCellValue("C{$currentRow}", $item['status'] == 3 ? '已完成' : '进行中');
                     $sheet->setCellValue("D{$currentRow}", $item['type']);
                     $sheet->setCellValue("D{$currentRow}", $item['type']);
 
 
-                    // 原始数据
-                    $sheet->setCellValue("F{$currentRow}", $item['val1']); // 1.人工
-                    $sheet->setCellValue("G{$currentRow}", $item['val2']); // 2.投入
-                    $sheet->setCellValue("H{$currentRow}", $item['val3']); // 3.折旧
-                    $sheet->setCellValue("I{$currentRow}", $item['val4']); // 4.摊销
-                    $sheet->setCellValue("J{$currentRow}", $item['val5']); // 5.新产品
-                    $sheet->setCellValue("L{$currentRow}", $item['val7_1']); // 7.1
-                    $sheet->setCellValue("N{$currentRow}", $item['val8_1']); // 8.1
-                    $sheet->setCellValue("P{$currentRow}", $item['val8_3'] ?? 0); // 8.3
-
-                    // 【逻辑修正】明细行公式
-                    $sheet->setCellValue("K{$currentRow}", "=SUM(F{$currentRow}:J{$currentRow})"); // 6列
-                    $sheet->setCellValue("O{$currentRow}", "=N{$currentRow}*0.8"); // 8.2 = 8.1 * 80%
-                    // 明细行不限制 7.2 和 8.4,通常直接取 7.1 和 8.3
-                    $sheet->setCellValue("M{$currentRow}", "=L{$currentRow}"); // 7.2
-                    $sheet->setCellValue("Q{$currentRow}", "=P{$currentRow}"); // 8.4
-                    // E列 = 6 + 7.2 + 8.2 + 8.4
-                    $sheet->setCellValue("E{$currentRow}", "=K{$currentRow}+M{$currentRow}+O{$currentRow}+Q{$currentRow}");
-
-                    if ($item['type'] == '资本化支出' && $item['status'] == 3) {
+                    // 动态明细
+                    foreach ($this->dynamicHeaders as $idx => $header) {
+                        $col = Coordinate::stringFromColumnIndex($startDetailIdx + $idx);
+                        $sheet->setCellValue("{$col}{$currentRow}", $item['values'][$idx] ?? 0);
+                    }
+
+                    // 固定数值列
+                    $sheet->setCellValue("{$col_7_1}{$currentRow}", $item['val7_1'] ?? 0);
+                    $sheet->setCellValue("{$col_8_1}{$currentRow}", $item['val8_1'] ?? 0);
+                    $sheet->setCellValue("{$col_8_3}{$currentRow}", $item['val8_3'] ?? 0);
+
+                    // 行公式
+                    $firstDetailCol = Coordinate::stringFromColumnIndex($startDetailIdx);
+                    $lastDetailCol = Coordinate::stringFromColumnIndex($startDetailIdx + $totalDynamic - 1);
+
+                    $sheet->setCellValue("{$col_6}{$currentRow}", "=SUM({$firstDetailCol}{$currentRow}:{$lastDetailCol}{$currentRow})");
+                    $sheet->setCellValue("{$col_7_2}{$currentRow}", "={$col_7_1}{$currentRow}");
+                    $sheet->setCellValue("{$col_8_2}{$currentRow}", "={$col_8_1}{$currentRow}*0.8");
+                    $sheet->setCellValue("{$col_8_4}{$currentRow}", "={$col_8_3}{$currentRow}*0.8");
+                    $sheet->setCellValue("{$col_E}{$currentRow}", "={$col_6}{$currentRow}+{$col_7_2}{$currentRow}+{$col_8_2}{$currentRow}+{$col_8_4}{$currentRow}");
+
+                    // 严格清洗类型字符串进行归集
+                    $cleanType = preg_replace('/[\s\v\t\r\n]+/u', '', (string)$item['type']);
+                    if ($cleanType === '资本化支出' && $item['status'] == 3) {
                         $capRows[] = $currentRow;
                         $capRows[] = $currentRow;
-                    } elseif ($item['type'] == '费用化支出') {
+                    } elseif ($cleanType === '费用化支出') {
                         $expRows[] = $currentRow;
                         $expRows[] = $currentRow;
                     }
                     }
                     $currentRow++;
                     $currentRow++;
                 }
                 }
 
 
-                // 4. 合计行勾稽计算
-                $this->applySummaryLogic($sheet, $currentRow, $capRows, $expRows);
+                // 5. 应用合计逻辑
+                $this->applyDynamicSummaryLogic($sheet, $currentRow, $capRows, $expRows, $startDetailIdx, $totalDynamic, $col_E, $col_6, $col_7_1, $col_7_2, $col_8_1, $col_8_2, $col_8_3, $col_8_4);
 
 
-                // 5. 样式设置
+                // 6. 最终样式
                 $lastDataRow = $currentRow + 3;
                 $lastDataRow = $currentRow + 3;
-                $sheet->getStyle("A5:Q{$lastDataRow}")->applyFromArray(['borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]]]);
-                $sheet->getStyle("E8:Q{$lastDataRow}")->getNumberFormat()->setFormatCode('#,##0.00');
-                $sheet->getStyle("A5:Q7")->getAlignment()->setWrapText(true)->setHorizontal('center')->setVertical('center');
-
-                // 签字行
-                $sheet->setCellValue("A" . ($lastDataRow + 1), "法定代表人(签章):");
+                $sheet->getStyle("A5:{$highestColumn}{$lastDataRow}")->applyFromArray(['borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]]]);
+                $sheet->getStyle("E8:{$highestColumn}{$lastDataRow}")->getNumberFormat()->setFormatCode('#,##0.00');
+                $sheet->getStyle("A5:{$highestColumn}7")->getAlignment()->setWrapText(true)->setHorizontal('center')->setVertical('center');
             },
             },
         ];
         ];
     }
     }
 
 
-    private function drawCorrectHeader($sheet)
+    private function drawDynamicHeader($sheet, $col_E, $col_6, $col_7_1, $col_8_1, $highestColumn)
     {
     {
-        $sheet->mergeCells('A2:Q2');
+        $sheet->mergeCells("A2:{$highestColumn}2");
         $sheet->setCellValue('A2', '研发支出辅助账汇总表');
         $sheet->setCellValue('A2', '研发支出辅助账汇总表');
-        $sheet->getStyle('A2')->getAlignment()->setHorizontal('center');
-        $sheet->getStyle('A2')->getFont()->setSize(16)->setBold(true);
+        $sheet->getStyle('A2')->applyFromArray(['font' => ['size' => 16, 'bold' => true], 'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER]]);
+
+        // 第3行布局修复
+        $totalCols = Coordinate::columnIndexFromString($highestColumn);
+        $sheet->setCellValue('A3', '纳税人识别号(统一社会信用代码):' . $this->taxId);
+
+        $nameCol = Coordinate::stringFromColumnIndex(max(7, floor($totalCols * 0.55)));
+        $sheet->setCellValue($nameCol . '3', '纳税人名称:' . $this->companyName);
 
 
-        $sheet->setCellValue('A3', '纳税人识别号:' . $this->taxId);
-        $sheet->setCellValue('J3', '纳税人名称:' . $this->companyName);
-        $sheet->setCellValue('O3', "属期:{$this->year}年");
-        $sheet->setCellValue('Q3', '单位:元');
+        $periodCol = Coordinate::stringFromColumnIndex($totalCols - 3);
+        $sheet->setCellValue($periodCol . '3', "属期:{$this->year}年");
 
 
+        $sheet->setCellValue($highestColumn . '3', '单位:元');
+        $sheet->getStyle($highestColumn . '3')->getAlignment()->setHorizontal(Alignment::HORIZONTAL_RIGHT);
+
+        // 表头 5-7 行
         $vHeaders = ['A'=>'项目编号', 'B'=>'项目名称', 'C'=>'完成情况', 'D'=>'支出类型', 'E'=>"允许加计\n扣除金额合计"];
         $vHeaders = ['A'=>'项目编号', 'B'=>'项目名称', 'C'=>'完成情况', 'D'=>'支出类型', 'E'=>"允许加计\n扣除金额合计"];
         foreach ($vHeaders as $col => $text) {
         foreach ($vHeaders as $col => $text) {
             $sheet->mergeCells("{$col}5:{$col}7");
             $sheet->mergeCells("{$col}5:{$col}7");
             $sheet->setCellValue("{$col}5", $text);
             $sheet->setCellValue("{$col}5", $text);
         }
         }
 
 
-        $subHeaders = ['F'=>'人员人工费用', 'G'=>'直接投入费用', 'H'=>'折旧费用', 'I'=>'无形资产摊销', 'J'=>'新产品设计费等', 'K'=>'前五项 小计'];
-        foreach ($subHeaders as $col => $text) {
+        $startIdx = 6;
+        foreach ($this->dynamicHeaders as $idx => $text) {
+            $col = Coordinate::stringFromColumnIndex($startIdx + $idx);
             $sheet->mergeCells("{$col}5:{$col}6");
             $sheet->mergeCells("{$col}5:{$col}6");
             $sheet->setCellValue("{$col}5", $text);
             $sheet->setCellValue("{$col}5", $text);
+            $sheet->setCellValue("{$col}7", $idx + 1);
         }
         }
 
 
-        $sheet->mergeCells('L5:M5'); $sheet->setCellValue('L5', '其他相关费用及限额');
-        $sheet->setCellValue('L6', '其他相关费用合计'); $sheet->setCellValue('M6', "经限额调整后的\n其他相关费用");
-
-        $sheet->mergeCells('N5:Q5'); $sheet->setCellValue('N5', '委托研发费用及限额');
-        $sheet->setCellValue('N6', "委托境内机构或\n个人研发费用"); $sheet->setCellValue('O6', "允许加计扣除的\n委托境内研发费");
-        $sheet->setCellValue('P6', "委托境外机构\n进行研发活动费"); $sheet->setCellValue('Q6', "经限额调整后的\n委托境外研发费");
-
-        $nums = ['F'=>'1','G'=>'2','H'=>'3','I'=>'4','J'=>'5','K'=>'6','L'=>'7.1','M'=>'7.2','N'=>'8.1','O'=>'8.2','P'=>'8.3','Q'=>'8.4'];
-        foreach ($nums as $col => $n) { $sheet->setCellValue("{$col}7", $n); }
+        $sheet->mergeCells("{$col_6}5:{$col_6}6");
+        $sheet->setCellValue("{$col_6}5", "前" . count($this->dynamicHeaders) . "项小计");
+        $sheet->setCellValue("{$col_6}7", count($this->dynamicHeaders) + 1);
+
+        $col_7_2 = Coordinate::stringFromColumnIndex(Coordinate::columnIndexFromString($col_7_1) + 1);
+        $sheet->mergeCells("{$col_7_1}5:{$col_7_2}5");
+        $sheet->setCellValue("{$col_7_1}5", '其他相关费用及限额');
+        $sheet->setCellValue("{$col_7_1}6", '其他相关费用合计'); $sheet->setCellValue("{$col_7_1}7", '7.1');
+        $sheet->setCellValue("{$col_7_2}6", "经限额调整后的其他相关费用"); $sheet->setCellValue("{$col_7_2}7", '7.2');
+
+        $sheet->mergeCells("{$col_8_1}5:{$highestColumn}5");
+        $sheet->setCellValue("{$col_8_1}5", '委托研发费用及限额');
+        $sIdx = Coordinate::columnIndexFromString($col_8_1);
+        $subs = ['委托境内机构或个人进行研发活动所发生的费用', '允许加计扣除的委托境内机构或个人进行研发活动所发生的费用', '委托境外机构进行研发活动所发生的费用', '经限额调整后的委托境外机构进行研发活动所发生的费用'];
+        $nums = ['8.1','8.2','8.3','8.4'];
+        for($i=0;$i<4;$i++) {
+            $c = Coordinate::stringFromColumnIndex($sIdx + $i);
+            $sheet->setCellValue($c . '6', $subs[$i]);
+            $sheet->setCellValue($c . '7', $nums[$i]);
+        }
     }
     }
 
 
-    private function applySummaryLogic($sheet, $r, $capRows, $expRows)
+    private function applyDynamicSummaryLogic($sheet, $r, $capRows, $expRows, $startIdx, $dynamicCount, $col_E, $col_6, $col_7_1, $col_7_2, $col_8_1, $col_8_2, $col_8_3, $col_8_4)
     {
     {
         $r_cap = $r; $r_exp = $r + 1; $r_oth = $r + 2; $r_all = $r + 3;
         $r_cap = $r; $r_exp = $r + 1; $r_oth = $r + 2; $r_all = $r + 3;
         $labels = ['资本化金额小计', '费用化金额小计', '其中:其他事项', '全额合计'];
         $labels = ['资本化金额小计', '费用化金额小计', '其中:其他事项', '全额合计'];
@@ -135,39 +178,35 @@ class ResearchExpenseSummarySheetExport implements WithEvents, WithTitle
             $sheet->setCellValue("A" . ($r+$i), $label);
             $sheet->setCellValue("A" . ($r+$i), $label);
         }
         }
 
 
-        // 基础汇总列 (F,G,H,I,J,L,N,P)
-        $cols = ['F', 'G', 'H', 'I', 'J', 'L', 'N', 'P'];
-        foreach ($cols as $col) {
+        $allValCols = [];
+        for($i=0; $i<$dynamicCount; $i++) { $allValCols[] = Coordinate::stringFromColumnIndex($startIdx + $i); }
+        $allValCols = array_merge($allValCols, [$col_7_1, $col_8_1, $col_8_3]);
+
+        foreach ($allValCols as $col) {
             $f_cap = !empty($capRows) ? "=SUM(".implode(',', array_map(fn($row)=>"{$col}{$row}", $capRows)).")" : "0";
             $f_cap = !empty($capRows) ? "=SUM(".implode(',', array_map(fn($row)=>"{$col}{$row}", $capRows)).")" : "0";
-            $f_exp = !empty($expRows) ? "=SUM(".implode(',', array_map(fn($row)=>"{$col}{$row}", $expRows)).") + {$col}{$r_oth}" : "{$col}{$r_oth}";
+            $f_exp_base = !empty($expRows) ? "SUM(".implode(',', array_map(fn($row)=>"{$col}{$row}", $expRows)).")" : "0";
             $sheet->setCellValue("{$col}{$r_cap}", $f_cap);
             $sheet->setCellValue("{$col}{$r_cap}", $f_cap);
-            $sheet->setCellValue("{$col}{$r_exp}", $f_exp);
+            $sheet->setCellValue("{$col}{$r_exp}", "={$f_exp_base}+{$col}{$r_oth}");
             $sheet->setCellValue("{$col}{$r_all}", "={$col}{$r_cap}+{$col}{$r_exp}");
             $sheet->setCellValue("{$col}{$r_all}", "={$col}{$r_cap}+{$col}{$r_exp}");
         }
         }
 
 
-        // --- 核心勾稽逻辑修正 ---
-        foreach ([$r_cap, $r_exp, $r_all] as $row) {
-            $sheet->setCellValue("K{$row}", "=SUM(F{$row}:J{$row})"); // 6列
-            $sheet->setCellValue("O{$row}", "=N{$row}*0.8");           // 8.2列
+        $fCol = Coordinate::stringFromColumnIndex($startIdx);
+        $lCol = Coordinate::stringFromColumnIndex($startIdx + $dynamicCount - 1);
 
 
-            // 修正:7.2列 (规则六)
+        foreach ([$r_cap, $r_exp, $r_all] as $row) {
+            $sheet->setCellValue("{$col_6}{$row}", "=SUM({$fCol}{$row}:{$lCol}{$row})");
+            $sheet->setCellValue("{$col_8_2}{$row}", "={$col_8_1}{$row}*0.8");
             if ($row == $r_all) {
             if ($row == $r_all) {
-                $sheet->setCellValue("M{$row}", "=MIN(L{$row}, K{$row}*0.1/0.9)");
+                $sheet->setCellValue("{$col_7_2}{$row}", "=MIN({$col_7_1}{$row}, {$col_6}{$row}*0.1/0.9)");
             } else {
             } else {
-                $sheet->setCellValue("M{$row}", "=IF(L{$r_all}>0, (M{$r_all}/L{$r_all})*L{$row}, 0)");
+                $sheet->setCellValue("{$col_7_2}{$row}", "=IF({$col_7_1}{$r_all}>0, ({$col_7_2}{$r_all}/{$col_7_1}{$r_all})*{$col_7_1}{$row}, 0)");
             }
             }
-
-            // 修正:8.4列 (规则八:金额合计行计算公式)
             if ($row == $r_all) {
             if ($row == $r_all) {
-                // 1. 金额合计 = MIN((6列+7.2列+8.2列)*2/3, 8.3列*80%)
-                $sheet->setCellValue("Q{$row}", "=MIN((K{$row}+M{$row}+O{$row})*2/3, P{$row}*0.8)");
+                $sheet->setCellValue("{$col_8_4}{$row}", "=MIN(({$col_6}{$row}+{$col_7_2}{$row}+{$col_8_2}{$row})*2/3, {$col_8_3}{$row}*0.8)");
             } else {
             } else {
-                // 分摊逻辑
-                $sheet->setCellValue("Q{$row}", "=IF(P{$r_all}>0, (Q{$r_all}/P{$r_all})*P{$row}, 0)");
+                $sheet->setCellValue("{$col_8_4}{$row}", "=IF({$col_8_3}{$r_all}>0, ({$col_8_4}{$r_all}/{$col_8_3}{$r_all})*{$col_8_3}{$row}, 0)");
             }
             }
-
-            // 修正:E列 (规则四:E = 6+7.2+8.2+8.4)
-            $sheet->setCellValue("E{$row}", "=K{$row}+M{$row}+O{$row}+Q{$row}");
+            $sheet->setCellValue("{$col_E}{$row}", "={$col_6}{$row}+{$col_7_2}{$row}+{$col_8_2}{$row}+{$col_8_4}{$row}");
         }
         }
     }
     }
 }
 }

+ 80 - 13
app/Service/ExportFileService.php

@@ -720,22 +720,89 @@ class ExportFileService extends Service
         return [true, $filename];
         return [true, $filename];
     }
     }
 
 
-    /**
-     * 辅助方法:计算合计行
-     */
-    private function calculateTotalRow(array $data, int $dynamicCount)
+    // 研发支出辅助帐汇总表
+    public function exportFormalSummary(array $data, $user)
     {
     {
-        $totalColumnCount = 8 + $dynamicCount + 2;
-        $totals = array_fill(0, $totalColumnCount, 0);
-        $totals[0] = '合计';
-        $totals[1] = $totals[2] = $totals[3] = '';
-
-        foreach ($data as $row) {
-            for ($i = 4; $i < $totalColumnCount; $i++) {
-                $totals[$i] += (float)($row[$i] ?? 0);
+        $service = new StatisticService();
+        // 1. 调用业务逻辑获取原始数据
+        list($status, $result) = $service->employeeAttendanceMonthStatistic($data, $user);
+        if (!$status) return [false, $result];
+
+        $rawList = $result['list'] ?? [];
+        $feeTypes = $result['fee_type_list'] ?? [];
+
+        // 2. 构造动态表头名称
+        $dynamicHeaderTitles = array_column($feeTypes, 'title');
+        $dynamicHeaders = array_merge(['人员人工费用', '折旧费用'], $dynamicHeaderTitles);
+
+        $items = [];
+        foreach ($rawList as $v) {
+            $rowValues = [];
+            // A. 填充基础固定两项:人工和折旧
+            $rowValues[] = (float)($v['employee_salary'] ?? 0);
+            $rowValues[] = (float)($v['device_depreciation'] ?? 0);
+
+            // B. 初始化累加变量
+            $val7_1 = 0; // 其他相关费用合计 (所有 total_amount 之和)
+            $val8_1 = 0; // 委托境内合计 (所有 entrust1_amount 之和)
+            $val8_3 = 0; // 委托境外合计 (所有 entrust2_amount 之和)
+
+            // 将当前项目的 fee_list 转为集合以便按 ID 快速查找
+            $currentProjectFees = collect($v['fee_list'] ?? [])->keyBy('id');
+
+            // 遍历所有可能的费用类型,确保 values 数组长度与表头一致
+            foreach ($feeTypes as $type) {
+                $feeData = $currentProjectFees->get($type['id']);
+                $amount = (float)($feeData['total_amount'] ?? 0);
+
+                // 填充到动态科目列
+                $rowValues[] = $amount;
+
+                // --- 费用归集逻辑修正 ---
+                // 1. 累加其他相关费用合计 (7.1)
+                $val7_1 += $amount;
+
+                // 2. 累加委托费用 (8.1 和 8.3)
+                $val8_1 += (float)($feeData['entrust1_amount'] ?? 0);
+                $val8_3 += (float)($feeData['entrust2_amount'] ?? 0);
             }
             }
+
+            $items[] = [
+                'no'     => $v['code'] ?? '',
+                'name'   => $v['title'] ?? '',
+                'status' => (($v['state'] ?? '') == "完结" ? 3 : 2),
+                'type'   => $v['expense_type'] ?? '费用化支出',
+                'values' => $rowValues,
+                'val7_1' => $val7_1, // 修正:此处为 total_amount 累加之和
+                'val8_1' => $val8_1, // 修正:此处为 entrust1_amount 累加之和
+                'val8_3' => $val8_3, // 修正:此处为 entrust2_amount 累加之和
+            ];
         }
         }
-        return $totals;
+
+        // 年份获取逻辑
+        $timeSource = $data['month_start'] ?? ($data['month_end'] ?? 'now');
+        $year = is_numeric($timeSource) ? date('Y', $timeSource) : date('Y', strtotime($timeSource));
+
+        // 3. 组织多 Sheet 格式数据
+        $monthsData = [
+            $year => [
+                'tax_id'          => $user->tax_id ?? '***********',
+                'company_name'    => Depart::where('id', $user['top_depart_id'])->value('title'),
+                'items'           => $items,
+                'dynamic_headers' => $dynamicHeaders
+            ]
+        ];
+
+        // 4. 执行 Excel 存储
+        $file_name = "研发支出辅助账汇总表_" . date("YmdHis") . "_" . rand(1000, 9999);
+        $filename = $file_name . '.xlsx';
+
+        Excel::store(
+            new \App\Exports\ResearchExpenseSummaryMultipleSheetExport($monthsData),
+            "public/export/{$filename}"
+        );
+
+        return [true, $filename];
     }
     }
 
 
     public function saveExportData($data, $headers, $type = 'default',$file_name = ''){
     public function saveExportData($data, $headers, $type = 'default',$file_name = ''){