Andrew Wallo 10 个月前
父节点
当前提交
f3b5ba7f0c

+ 39
- 63
app/Filament/Company/Resources/Accounting/DocumentResource.php 查看文件

@@ -103,6 +103,40 @@ class DocumentResource extends Resource
103 103
                         ])->from('md'),
104 104
                         TableRepeater::make('lineItems')
105 105
                             ->relationship()
106
+                            ->saveRelationshipsUsing(function (Document $document, array $state) {
107
+                                $document->lineItems()->delete();
108
+
109
+                                collect($state)->map(function ($lineItemData) use ($document) {
110
+                                    $lineItem = $document->lineItems()->create([
111
+                                        'offering_id' => $lineItemData['offering_id'],
112
+                                        'description' => $lineItemData['description'],
113
+                                        'quantity' => $lineItemData['quantity'],
114
+                                        'unit_price' => $lineItemData['unit_price'],
115
+                                        'tax_total' => collect($lineItemData['salesTaxes'] ?? [])->sum(function ($taxId) use ($lineItemData) {
116
+                                            $tax = Adjustment::find($taxId);
117
+
118
+                                            return $tax ? ($lineItemData['quantity'] * $lineItemData['unit_price']) * ($tax->rate / 100) : 0;
119
+                                        }),
120
+                                    ]);
121
+
122
+                                    $lineItem->taxes()->sync($lineItemData['salesTaxes'] ?? []);
123
+
124
+                                    return $lineItem;
125
+                                });
126
+
127
+                                $document->refresh();
128
+                                $subtotal = $document->lineItems()->sum('subtotal') / 100;
129
+                                $taxTotal = $document->lineItems()->sum('tax_total') / 100;
130
+                                $discountTotal = $document->lineItems()->sum('discount_total') / 100;
131
+                                $grandTotal = $subtotal + $taxTotal - $discountTotal;
132
+
133
+                                $document->updateQuietly([
134
+                                    'subtotal' => $subtotal,
135
+                                    'tax_total' => $taxTotal,
136
+                                    'discount_total' => $discountTotal,
137
+                                    'total' => $grandTotal,
138
+                                ]);
139
+                            })
106 140
                             ->headers([
107 141
                                 Header::make('Items')->width('20%'),
108 142
                                 Header::make('Description')->width('30%'),
@@ -135,8 +169,7 @@ class DocumentResource extends Resource
135 169
                                             $set('total', $total + $taxAmount);
136 170
                                         }
137 171
                                     }),
138
-                                Forms\Components\TextInput::make('description')
139
-                                    ->required(),
172
+                                Forms\Components\TextInput::make('description'),
140 173
                                 Forms\Components\TextInput::make('quantity')
141 174
                                     ->required()
142 175
                                     ->numeric()
@@ -175,68 +208,11 @@ class DocumentResource extends Resource
175 208
                                     }),
176 209
                             ]),
177 210
                         Forms\Components\Grid::make(6)
178
-                            ->inlineLabel()
179
-                            ->extraAttributes([
180
-                                'class' => 'text-right pr-16',
181
-                            ])
182 211
                             ->schema([
183
-                                Forms\Components\Group::make([
184
-                                    Forms\Components\Placeholder::make('subtotal')
185
-                                        ->label('Subtotal')
186
-                                        ->content(function (Forms\Get $get) {
187
-                                            $lineItems = $get('lineItems');
188
-
189
-                                            $subtotal = collect($lineItems)
190
-                                                ->sum(fn ($item) => ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0));
191
-
192
-                                            return money($subtotal, CurrencyAccessor::getDefaultCurrency(), true)->format();
193
-                                        }),
194
-                                    Forms\Components\Placeholder::make('tax_total')
195
-                                        ->label('Taxes')
196
-                                        ->content(function (Forms\Get $get) {
197
-                                            $lineItems = $get('lineItems');
198
-
199
-                                            $totalTaxes = collect($lineItems)->reduce(function ($carry, $item) {
200
-                                                $quantity = $item['quantity'] ?? 0;
201
-                                                $unitPrice = $item['unit_price'] ?? 0;
202
-                                                $salesTaxes = $item['salesTaxes'] ?? [];
203
-                                                $lineTotal = $quantity * $unitPrice;
204
-
205
-                                                $taxAmount = Adjustment::whereIn('id', $salesTaxes)
206
-                                                    ->pluck('rate')
207
-                                                    ->sum(fn ($rate) => $lineTotal * ($rate / 100));
208
-
209
-                                                return $carry + $taxAmount;
210
-                                            }, 0);
211
-
212
-                                            return money($totalTaxes, CurrencyAccessor::getDefaultCurrency(), true)->format();
213
-                                        }),
214
-                                    Forms\Components\Placeholder::make('total')
215
-                                        ->label('Total')
216
-                                        ->content(function (Forms\Get $get) {
217
-                                            $lineItems = $get('lineItems') ?? [];
218
-
219
-                                            $subtotal = collect($lineItems)
220
-                                                ->sum(fn ($item) => ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0));
221
-
222
-                                            $totalTaxes = collect($lineItems)->reduce(function ($carry, $item) {
223
-                                                $quantity = $item['quantity'] ?? 0;
224
-                                                $unitPrice = $item['unit_price'] ?? 0;
225
-                                                $salesTaxes = $item['salesTaxes'] ?? [];
226
-                                                $lineTotal = $quantity * $unitPrice;
227
-
228
-                                                $taxAmount = Adjustment::whereIn('id', $salesTaxes)
229
-                                                    ->pluck('rate')
230
-                                                    ->sum(fn ($rate) => $lineTotal * ($rate / 100));
231
-
232
-                                                return $carry + $taxAmount;
233
-                                            }, 0);
234
-
235
-                                            $grandTotal = $subtotal + $totalTaxes;
236
-
237
-                                            return money($grandTotal, CurrencyAccessor::getDefaultCurrency(), true)->format();
238
-                                        }),
239
-                                ])->columnStart(6),
212
+                                Forms\Components\ViewField::make('totals')
213
+                                    ->columnStart(5)
214
+                                    ->columnSpan(2)
215
+                                    ->view('filament.forms.components.invoice-totals'),
240 216
                             ]),
241 217
                         //                        Forms\Components\Repeater::make('lineItems')
242 218
                         //                            ->relationship()

+ 8
- 0
app/Filament/Company/Resources/Accounting/DocumentResource/Pages/EditDocument.php 查看文件

@@ -5,6 +5,7 @@ namespace App\Filament\Company\Resources\Accounting\DocumentResource\Pages;
5 5
 use App\Filament\Company\Resources\Accounting\DocumentResource;
6 6
 use Filament\Actions;
7 7
 use Filament\Resources\Pages\EditRecord;
8
+use Illuminate\Database\Eloquent\Model;
8 9
 
9 10
 class EditDocument extends EditRecord
10 11
 {
@@ -16,4 +17,11 @@ class EditDocument extends EditRecord
16 17
             Actions\DeleteAction::make(),
17 18
         ];
18 19
     }
20
+
21
+    protected function handleRecordUpdate(Model $record, array $data): Model
22
+    {
23
+        ray($data);
24
+
25
+        return parent::handleRecordUpdate($record, $data); // TODO: Change the autogenerated stub
26
+    }
19 27
 }

+ 8
- 0
app/Filament/Company/Resources/Sales/InvoiceResource/Pages/EditInvoice.php 查看文件

@@ -5,6 +5,7 @@ namespace App\Filament\Company\Resources\Sales\InvoiceResource\Pages;
5 5
 use App\Filament\Company\Resources\Sales\InvoiceResource;
6 6
 use Filament\Actions;
7 7
 use Filament\Resources\Pages\EditRecord;
8
+use Illuminate\Database\Eloquent\Model;
8 9
 
9 10
 class EditInvoice extends EditRecord
10 11
 {
@@ -16,4 +17,11 @@ class EditInvoice extends EditRecord
16 17
             Actions\DeleteAction::make(),
17 18
         ];
18 19
     }
20
+
21
+    protected function handleRecordUpdate(Model $record, array $data): Model
22
+    {
23
+        ray($data);
24
+
25
+        return parent::handleRecordUpdate($record, $data); // TODO: Change the autogenerated stub
26
+    }
19 27
 }

+ 2
- 2
app/Models/Accounting/DocumentLineItem.php 查看文件

@@ -31,7 +31,6 @@ class DocumentLineItem extends Model
31 31
         'description',
32 32
         'quantity',
33 33
         'unit_price',
34
-        'total',
35 34
         'tax_total',
36 35
         'discount_total',
37 36
         'created_by',
@@ -40,9 +39,10 @@ class DocumentLineItem extends Model
40 39
 
41 40
     protected $casts = [
42 41
         'unit_price' => MoneyCast::class,
43
-        'total' => MoneyCast::class,
42
+        'subtotal' => MoneyCast::class,
44 43
         'tax_total' => MoneyCast::class,
45 44
         'discount_total' => MoneyCast::class,
45
+        'total' => MoneyCast::class,
46 46
     ];
47 47
 
48 48
     public function document(): BelongsTo

+ 0
- 12
app/Observers/DocumentLineItemObserver.php 查看文件

@@ -22,18 +22,6 @@ class DocumentLineItemObserver
22 22
         //
23 23
     }
24 24
 
25
-    public function saving(DocumentLineItem $lineItem): void
26
-    {
27
-        // Calculate the base total (quantity * unit price)
28
-        $lineItem->total = $lineItem->quantity * $lineItem->unit_price;
29
-
30
-        // Calculate tax total (if applicable)
31
-        $lineItem->tax_total = $lineItem->taxes->sum(fn ($tax) => $lineItem->total * ($tax->rate / 100));
32
-
33
-        // Calculate discount total (if applicable)
34
-        $lineItem->discount_total = $lineItem->discounts->sum(fn ($discount) => $lineItem->total * ($discount->rate / 100));
35
-    }
36
-
37 25
     /**
38 26
      * Handle the DocumentLineItem "deleted" event.
39 27
      */

+ 10
- 20
app/Observers/DocumentObserver.php 查看文件

@@ -30,11 +30,6 @@ class DocumentObserver
30 30
         //
31 31
     }
32 32
 
33
-    public function updated(Document $document): void
34
-    {
35
-        $this->recalculateTotals($document);
36
-    }
37
-
38 33
     public function saved(Document $document): void
39 34
     {
40 35
         $this->recalculateTotals($document);
@@ -42,29 +37,24 @@ class DocumentObserver
42 37
 
43 38
     protected function recalculateTotals(Document $document): void
44 39
     {
45
-        // Sum up totals in cents
46
-        $subtotalCents = $document->lineItems()->sum('total');
47
-        $taxTotalCents = $document->lineItems()->sum('tax_total');
48
-        $discountTotalCents = $document->lineItems()->sum('discount_total');
49
-        $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents;
40
+        // Sum up values from line items
41
+        $subtotalCents = $document->lineItems()->sum('subtotal'); // Use the computed column directly
42
+        $taxTotalCents = $document->lineItems()->sum('tax_total'); // Sum from line items
43
+        $discountTotalCents = $document->lineItems()->sum('discount_total'); // Sum from line items
44
+        $grandTotalCents = $subtotalCents + $taxTotalCents - $discountTotalCents; // Calculated as before
50 45
 
51
-        $subtotal = $subtotalCents / 100; // Convert to dollars
46
+        // Convert from cents to dollars
47
+        $subtotal = $subtotalCents / 100;
52 48
         $taxTotal = $taxTotalCents / 100;
53 49
         $discountTotal = $discountTotalCents / 100;
54 50
         $grandTotal = $grandTotalCents / 100;
55 51
 
56
-        ray([
57
-            'subtotal' => $subtotal,
58
-            'tax_total' => $taxTotal,
59
-            'discount_total' => $discountTotal,
60
-            'grand_total' => $grandTotal,
61
-        ]);
62
-
52
+        // Update document totals
63 53
         $document->updateQuietly([
64
-            'subtotal' => $subtotal,
54
+            'subtotal' => $subtotal, // Use database-computed subtotal
65 55
             'tax_total' => $taxTotal,
66 56
             'discount_total' => $discountTotal,
67
-            'total' => $grandTotal,
57
+            'total' => $grandTotal, // Use calculated grand total
68 58
         ]);
69 59
     }
70 60
 

+ 7
- 0
app/Utilities/Currency/CurrencyConverter.php 查看文件

@@ -49,6 +49,13 @@ class CurrencyConverter
49 49
         return money($amount, $currency)->format();
50 50
     }
51 51
 
52
+    public static function formatToMoney(string | float $amount, ?string $currency = null): string
53
+    {
54
+        $currency ??= CurrencyAccessor::getDefaultCurrency();
55
+
56
+        return money($amount, $currency, true)->format();
57
+    }
58
+
52 59
     public static function handleCurrencyChange(Set $set, $state): void
53 60
     {
54 61
         $currency = currency($state);

+ 47
- 0
app/View/Models/InvoiceTotalViewModel.php 查看文件

@@ -0,0 +1,47 @@
1
+<?php
2
+
3
+namespace App\View\Models;
4
+
5
+use App\Models\Accounting\Adjustment;
6
+use App\Models\Accounting\Document;
7
+use App\Utilities\Currency\CurrencyConverter;
8
+
9
+class InvoiceTotalViewModel
10
+{
11
+    public function __construct(
12
+        public ?Document $invoice,
13
+        public ?array $data = null
14
+    ) {}
15
+
16
+    public function buildViewData(): array
17
+    {
18
+        $lineItems = collect($this->data['lineItems'] ?? []);
19
+
20
+        $subtotal = $lineItems->sum(fn ($item) => ($item['quantity'] ?? 0) * ($item['unit_price'] ?? 0));
21
+
22
+        $taxTotal = $lineItems->reduce(function ($carry, $item) {
23
+            $quantity = $item['quantity'] ?? 0;
24
+            $unitPrice = $item['unit_price'] ?? 0;
25
+            $salesTaxes = $item['salesTaxes'] ?? [];
26
+            $lineTotal = $quantity * $unitPrice;
27
+
28
+            $taxAmount = Adjustment::whereIn('id', $salesTaxes)
29
+                ->pluck('rate')
30
+                ->sum(fn ($rate) => $lineTotal * ($rate / 100));
31
+
32
+            return $carry + $taxAmount;
33
+        }, 0);
34
+
35
+        $grandTotal = $subtotal + $taxTotal;
36
+
37
+        $subTotalFormatted = CurrencyConverter::formatToMoney($subtotal);
38
+        $taxTotalFormatted = CurrencyConverter::formatToMoney($taxTotal);
39
+        $grandTotalFormatted = CurrencyConverter::formatToMoney($grandTotal);
40
+
41
+        return [
42
+            'subtotal' => $subTotalFormatted,
43
+            'taxTotal' => $taxTotalFormatted,
44
+            'grandTotal' => $grandTotalFormatted,
45
+        ];
46
+    }
47
+}

+ 18
- 18
composer.lock 查看文件

@@ -497,16 +497,16 @@
497 497
         },
498 498
         {
499 499
             "name": "aws/aws-sdk-php",
500
-            "version": "3.330.0",
500
+            "version": "3.330.1",
501 501
             "source": {
502 502
                 "type": "git",
503 503
                 "url": "https://github.com/aws/aws-sdk-php.git",
504
-                "reference": "dd1b65a4329f91d5e282a92fab2be7bdf6e2adea"
504
+                "reference": "136749f15d1dbff07064ef5ba1c2f08b96cf78ff"
505 505
             },
506 506
             "dist": {
507 507
                 "type": "zip",
508
-                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/dd1b65a4329f91d5e282a92fab2be7bdf6e2adea",
509
-                "reference": "dd1b65a4329f91d5e282a92fab2be7bdf6e2adea",
508
+                "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/136749f15d1dbff07064ef5ba1c2f08b96cf78ff",
509
+                "reference": "136749f15d1dbff07064ef5ba1c2f08b96cf78ff",
510 510
                 "shasum": ""
511 511
             },
512 512
             "require": {
@@ -589,9 +589,9 @@
589 589
             "support": {
590 590
                 "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
591 591
                 "issues": "https://github.com/aws/aws-sdk-php/issues",
592
-                "source": "https://github.com/aws/aws-sdk-php/tree/3.330.0"
592
+                "source": "https://github.com/aws/aws-sdk-php/tree/3.330.1"
593 593
             },
594
-            "time": "2024-11-22T19:10:26+00:00"
594
+            "time": "2024-11-25T19:20:00+00:00"
595 595
         },
596 596
         {
597 597
             "name": "aws/aws-sdk-php-laravel",
@@ -5060,16 +5060,16 @@
5060 5060
         },
5061 5061
         {
5062 5062
             "name": "openspout/openspout",
5063
-            "version": "v4.26.0",
5063
+            "version": "v4.27.0",
5064 5064
             "source": {
5065 5065
                 "type": "git",
5066 5066
                 "url": "https://github.com/openspout/openspout.git",
5067
-                "reference": "a49b947c0c109f4fd112f9b5c6d6cb3e6baf8b50"
5067
+                "reference": "1841a6047b4d23d1d353821b8a03f8d599a94143"
5068 5068
             },
5069 5069
             "dist": {
5070 5070
                 "type": "zip",
5071
-                "url": "https://api.github.com/repos/openspout/openspout/zipball/a49b947c0c109f4fd112f9b5c6d6cb3e6baf8b50",
5072
-                "reference": "a49b947c0c109f4fd112f9b5c6d6cb3e6baf8b50",
5071
+                "url": "https://api.github.com/repos/openspout/openspout/zipball/1841a6047b4d23d1d353821b8a03f8d599a94143",
5072
+                "reference": "1841a6047b4d23d1d353821b8a03f8d599a94143",
5073 5073
                 "shasum": ""
5074 5074
             },
5075 5075
             "require": {
@@ -5083,13 +5083,13 @@
5083 5083
             },
5084 5084
             "require-dev": {
5085 5085
                 "ext-zlib": "*",
5086
-                "friendsofphp/php-cs-fixer": "^3.64.0",
5087
-                "infection/infection": "^0.29.6",
5086
+                "friendsofphp/php-cs-fixer": "^3.65.0",
5087
+                "infection/infection": "^0.29.8",
5088 5088
                 "phpbench/phpbench": "^1.3.1",
5089
-                "phpstan/phpstan": "^1.12.4",
5090
-                "phpstan/phpstan-phpunit": "^1.4.0",
5091
-                "phpstan/phpstan-strict-rules": "^1.6.1",
5092
-                "phpunit/phpunit": "^11.3.6"
5089
+                "phpstan/phpstan": "^2.0.2",
5090
+                "phpstan/phpstan-phpunit": "^2.0.1",
5091
+                "phpstan/phpstan-strict-rules": "^2",
5092
+                "phpunit/phpunit": "^11.4.3"
5093 5093
             },
5094 5094
             "suggest": {
5095 5095
                 "ext-iconv": "To handle non UTF-8 CSV files (if \"php-mbstring\" is not already installed or is too limited)",
@@ -5137,7 +5137,7 @@
5137 5137
             ],
5138 5138
             "support": {
5139 5139
                 "issues": "https://github.com/openspout/openspout/issues",
5140
-                "source": "https://github.com/openspout/openspout/tree/v4.26.0"
5140
+                "source": "https://github.com/openspout/openspout/tree/v4.27.0"
5141 5141
             },
5142 5142
             "funding": [
5143 5143
                 {
@@ -5149,7 +5149,7 @@
5149 5149
                     "type": "github"
5150 5150
                 }
5151 5151
             ],
5152
-            "time": "2024-09-24T14:04:43+00:00"
5152
+            "time": "2024-11-25T10:23:43+00:00"
5153 5153
         },
5154 5154
         {
5155 5155
             "name": "paragonie/constant_time_encoding",

+ 2
- 1
database/migrations/2024_11_13_220301_create_document_line_items_table.php 查看文件

@@ -19,7 +19,8 @@ return new class extends Migration
19 19
             $table->string('description')->nullable();
20 20
             $table->integer('quantity')->default(1);
21 21
             $table->integer('unit_price')->default(0);
22
-            $table->integer('total')->default(0);
22
+            $table->integer('subtotal')->storedAs('quantity * unit_price');
23
+            $table->integer('total')->storedAs('(quantity * unit_price) + tax_total - discount_total');
23 24
             $table->integer('tax_total')->default(0);
24 25
             $table->integer('discount_total')->default(0);
25 26
             $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();

+ 6
- 6
package-lock.json 查看文件

@@ -928,9 +928,9 @@
928 928
             }
929 929
         },
930 930
         "node_modules/axios": {
931
-            "version": "1.7.7",
932
-            "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
933
-            "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
931
+            "version": "1.7.8",
932
+            "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz",
933
+            "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==",
934 934
             "dev": true,
935 935
             "license": "MIT",
936 936
             "dependencies": {
@@ -1187,9 +1187,9 @@
1187 1187
             "license": "MIT"
1188 1188
         },
1189 1189
         "node_modules/electron-to-chromium": {
1190
-            "version": "1.5.64",
1191
-            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.64.tgz",
1192
-            "integrity": "sha512-IXEuxU+5ClW2IGEYFC2T7szbyVgehupCWQe5GNh+H065CD6U6IFN0s4KeAMFGNmQolRU4IV7zGBWSYMmZ8uuqQ==",
1190
+            "version": "1.5.65",
1191
+            "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz",
1192
+            "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==",
1193 1193
             "dev": true,
1194 1194
             "license": "ISC"
1195 1195
         },

+ 1
- 0
resources/css/filament/company/tailwind.config.js 查看文件

@@ -5,6 +5,7 @@ export default {
5 5
     content: [
6 6
         './app/Filament/Company/**/*.php',
7 7
         './resources/views/filament/company/**/*.blade.php',
8
+        './resources/views/filament/forms/**/*.blade.php',
8 9
         './resources/views/livewire/company/**/*.blade.php',
9 10
         './resources/views/components/**/*.blade.php',
10 11
         './vendor/filament/**/*.blade.php',

+ 30
- 0
resources/views/filament/forms/components/invoice-totals.blade.php 查看文件

@@ -0,0 +1,30 @@
1
+@use('App\Utilities\Currency\CurrencyAccessor')
2
+
3
+@php
4
+    $data = $this->form->getRawState();
5
+    $viewModel = new \App\View\Models\InvoiceTotalViewModel($this->record, $data);
6
+    extract($viewModel->buildViewData(), \EXTR_SKIP);
7
+@endphp
8
+
9
+<div class="totals-summary w-full pr-14">
10
+    <table class="w-full text-right table-fixed">
11
+        <tbody>
12
+            <tr>
13
+                <td class="w-2/3 text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Subtotal:</td>
14
+                <td class="w-1/3 text-sm pl-4 py-2 leading-6">{{ $subtotal }}</td>
15
+            </tr>
16
+            <tr>
17
+                <td class="w-2/3 text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Taxes:</td>
18
+                <td class="w-1/3 text-sm pl-4 py-2 leading-6">{{ $taxTotal }}</td>
19
+            </tr>
20
+            <tr class="font-semibold">
21
+                <td class="w-2/3 text-sm px-4 py-2 font-medium leading-6 text-gray-950 dark:text-white">Total:</td>
22
+                <td class="w-1/3 text-sm pl-4 py-2 leading-6">{{ $grandTotal }}</td>
23
+            </tr>
24
+        </tbody>
25
+    </table>
26
+</div>
27
+
28
+
29
+
30
+

正在加载...
取消
保存