14 changed files with 1514 additions and 12 deletions
			
			
		- 
					59app/AdminSupplier/Actions/Grid/ExportToExcelButton.php
 - 
					59app/AdminSupplier/Actions/Grid/ImportFromExcelButton.php
 - 
					21app/AdminSupplier/Controllers/ProductController.php
 - 
					18app/AdminSupplier/Extensions/ProductToExcelExporter.php
 - 
					52app/AdminSupplier/Forms/ExcelImport.php
 - 
					100app/Exports/ProductExport.php
 - 
					176app/Imports/ProductImport.php
 - 
					63app/Imports/ProductSpecImport.php
 - 
					45app/Jobs/ExportProductToExcel.php
 - 
					63app/Jobs/ImportProductFromExcel.php
 - 
					4composer.json
 - 
					520composer.lock
 - 
					328config/excel.php
 - 
					14tests/Feature/ExampleTest.php
 
@ -0,0 +1,59 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\AdminSupplier\Actions\Grid; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Jobs\ExportProductToExcel; | 
			
		||||
 | 
				use Dcat\Admin\Grid\Tools\AbstractTool; | 
			
		||||
 | 
				use Dcat\Admin\Traits\HasPermissions; | 
			
		||||
 | 
				use Illuminate\Contracts\Auth\Authenticatable; | 
			
		||||
 | 
				use Illuminate\Database\Eloquent\Model; | 
			
		||||
 | 
				use Illuminate\Http\Request; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ExportToExcelButton extends AbstractTool | 
			
		||||
 | 
				{ | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @return string | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
					protected $title = '导入所有产品到excel'; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function html() | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$this->appendHtmlAttribute('class', 'btn btn-primary btn-outline'); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						return <<<HTML | 
			
		||||
 | 
				<button {$this->formatHtmlAttributes()}>{$this->title()}</button> | 
			
		||||
 | 
				HTML; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function handle(Request $request) | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						ExportProductToExcel::dispatch(\Admin::user()->id); | 
			
		||||
 | 
						return $this->response()->success('导出成功,稍后到导出列表下载'); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
					 * @return string|array|void | 
			
		||||
 | 
					 */ | 
			
		||||
 | 
					public function confirm() | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						// return ['Confirm?', 'contents'];
 | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @param Model|Authenticatable|HasPermissions|null $user | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return bool | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    protected function authorize($user): bool | 
			
		||||
 | 
				    { | 
			
		||||
 | 
				        return true; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @return array | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    protected function parameters() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
				        return []; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,59 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\AdminSupplier\Actions\Grid; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use Dcat\Admin\Grid\Tools\AbstractTool; | 
			
		||||
 | 
				use Dcat\Admin\Traits\HasPermissions; | 
			
		||||
 | 
				use Illuminate\Contracts\Auth\Authenticatable; | 
			
		||||
 | 
				use Illuminate\Database\Eloquent\Model; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ImportFromExcelButton extends AbstractTool | 
			
		||||
 | 
				{ | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @return string | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
					protected $title = '从Excel导入'; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function html() | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$this->appendHtmlAttribute('class', 'btn btn-primary btn-outline'); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						return <<<HTML | 
			
		||||
 | 
				<a {$this->formatHtmlAttributes()}>{$this->title()}</a> | 
			
		||||
 | 
				HTML; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @return string|void | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    protected function href() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						return admin_url('product/import'); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
					 * @return string|array|void | 
			
		||||
 | 
					 */ | 
			
		||||
 | 
					public function confirm() | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						// return ['Confirm?', 'contents'];
 | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @param Model|Authenticatable|HasPermissions|null $user | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return bool | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    protected function authorize($user): bool | 
			
		||||
 | 
				    { | 
			
		||||
 | 
				        return true; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * @return array | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    protected function parameters() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
				        return []; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,18 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\AdminSupplier\Extensions; | 
			
		||||
 | 
				use App\Exports\ProductExport; | 
			
		||||
 | 
				use Dcat\Admin\Admin; | 
			
		||||
 | 
				use Dcat\Admin\Grid\Exporters\AbstractExporter; | 
			
		||||
 | 
				use Maatwebsite\Excel\Facades\Excel; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				/** | 
			
		||||
 | 
				 * Excel导出功能 | 
			
		||||
 | 
				 */ | 
			
		||||
 | 
				class ProductToExcelExporter extends AbstractExporter | 
			
		||||
 | 
				{ | 
			
		||||
 | 
					public function export() | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						return Excel::download(new ProductExport(Admin::user()->id), '导出产品-' . date('Y-m-d H:i:s') . '.xlsx')->send(); | 
			
		||||
 | 
					} | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,52 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\AdminSupplier\Forms; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Jobs\ImportProductFromExcel; | 
			
		||||
 | 
				use Dcat\Admin\Widgets\Form; | 
			
		||||
 | 
				use Illuminate\Support\Facades\Storage; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ExcelImport extends Form | 
			
		||||
 | 
				{ | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * Handle the form request. | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @param array $input | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return mixed | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    public function handle(array $input) | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						foreach ($input['zip_file'] as $zip_file) { | 
			
		||||
 | 
							/*# 使用md5_file来重命名文件,保证唯一
 | 
			
		||||
 | 
							$to_path = str_replace(basename($zip_file), '', $zip_file); | 
			
		||||
 | 
							$to_path .= md5_file(Storage::disk('public')->path($zip_file)) . '.zip'; | 
			
		||||
 | 
							Storage::disk('public')->move($zip_file, $to_path);*/ | 
			
		||||
 | 
							ImportProductFromExcel::dispatch(\Admin::user()->id, Storage::disk('public')->path($zip_file)); | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        return $this->response()->success('操作成功,导入产品可能需要几分钟,请勿重复导入,请耐心等待')->refresh(); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * Build a form here. | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    public function form() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
				        $this->multipleFile('zip_file', 'ZIP文件') | 
			
		||||
 | 
							->help('注意:请上传zip文件,上传文件大小不能超过' . ini_get('upload_max_filesize') . | 
			
		||||
 | 
								'。<a href="' . Storage::disk('public')->url('import.zip') . '" target="_blank">文件导入模板</a>') | 
			
		||||
 | 
							->accept('zip') | 
			
		||||
 | 
							->uniqueName()->autoUpload()->required(); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * The data of the form. | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return array | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    public function default() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
				        return []; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,100 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\Exports; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Common\ProductStatus; | 
			
		||||
 | 
				use App\Models\Product; | 
			
		||||
 | 
				use Maatwebsite\Excel\Concerns\FromQuery; | 
			
		||||
 | 
				use Maatwebsite\Excel\Concerns\WithColumnFormatting; | 
			
		||||
 | 
				use Maatwebsite\Excel\Concerns\WithHeadings; | 
			
		||||
 | 
				use PhpOffice\PhpSpreadsheet\Style\NumberFormat; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ProductExport implements FromQuery, WithHeadings, WithColumnFormatting | 
			
		||||
 | 
				{ | 
			
		||||
 | 
					private int $supplier_id; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function __construct(int $supplier_id) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$this->supplier_id = $supplier_id; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function query() | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						return Product::with('category:id,name')->where('supplier_id', $this->supplier_id); | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function prepareRows($rows) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						return $rows->transform(function ($row) { | 
			
		||||
 | 
							return [ | 
			
		||||
 | 
								'id' => $row->id, | 
			
		||||
 | 
								'status' => ProductStatus::array()[$row->status] ?? '', | 
			
		||||
 | 
								'category_name' => $row->category?->name ?? '', | 
			
		||||
 | 
								'title' => $row->title, | 
			
		||||
 | 
								'price' => $row->price, | 
			
		||||
 | 
								'original_price' => $row->original_price, | 
			
		||||
 | 
								'stock' => $row->stock, | 
			
		||||
 | 
								'know' => $row->know, | 
			
		||||
 | 
								'content' => $row->content, | 
			
		||||
 | 
								'verify_mobile' => $row->verify_mobile, | 
			
		||||
 | 
								'diy_form_id' => $row->diy_form_id, | 
			
		||||
 | 
								'出发地' => $row->extends['field_0_departure_place'] ?? '', | 
			
		||||
 | 
								'出发地经度' => $row->extends['field_0_departure_place_longitude'] ?? '', | 
			
		||||
 | 
								'出发地纬度' => $row->extends['field_0_departure_place_latitude'] ?? '', | 
			
		||||
 | 
								'目的地' => $row->extends['field_0_destination'] ?? '', | 
			
		||||
 | 
								'目的地经度' => $row->extends['field_0_destination_longitude'] ?? '', | 
			
		||||
 | 
								'目的地纬度' => $row->extends['field_0_destination_latitude'] ?? '', | 
			
		||||
 | 
								'行程起始时间' => $row->extends['field_0_date?->start'] ?? '', | 
			
		||||
 | 
								'行程结束时间' => $row->extends['field_0_date?->end'] ?? '', | 
			
		||||
 | 
								'酒店名' => $row->extends['field_1_name'] ?? '', | 
			
		||||
 | 
								'酒店地址' => $row->extends['field_1_address'] ?? '', | 
			
		||||
 | 
								'酒店经度' => $row->extends['field_1_longitude'] ?? '', | 
			
		||||
 | 
								'酒店纬度' => $row->extends['field_1_latitude'] ?? '', | 
			
		||||
 | 
								'景区名' => $row->extends['field_2_name'] ?? '', | 
			
		||||
 | 
								'景区地址' => $row->extends['field_2_address'] ?? '', | 
			
		||||
 | 
								'景区经度' => $row->extends['field_2_longitude'] ?? '', | 
			
		||||
 | 
								'景区纬度' => $row->extends['field_2_latitude'] ?? '', | 
			
		||||
 | 
								'餐厅名' => $row->extends['field_3_name'] ?? '', | 
			
		||||
 | 
								'餐厅地址' => $row->extends['field_3_address'] ?? '', | 
			
		||||
 | 
								'餐厅经度' => $row->extends['field_3_longitude'] ?? '', | 
			
		||||
 | 
								'餐厅纬度' => $row->extends['field_3_latitude'] ?? '', | 
			
		||||
 | 
								'交通地址' => $row->extends['field_4_address'] ?? '', | 
			
		||||
 | 
								'交通经度' => $row->extends['field_4_longitude'] ?? '', | 
			
		||||
 | 
								'交通纬度' => $row->extends['field_4_latitude'] ?? '', | 
			
		||||
 | 
								'购物地址' => $row->extends['field_5_address'] ?? '', | 
			
		||||
 | 
								'购物经度' => $row->extends['field_5_longitude'] ?? '', | 
			
		||||
 | 
								'购物纬度' => $row->extends['field_5_latitude'] ?? '', | 
			
		||||
 | 
							]; | 
			
		||||
 | 
						}); | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function map($row): array | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						return [ | 
			
		||||
 | 
							$row->id, | 
			
		||||
 | 
							$row->category->name, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						]; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function headings(): array | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						return [ | 
			
		||||
 | 
							'ID', '状态', '分类', '产品标题', '销售价', '市场价', '库存', '旅客须知', '产品详情', '核销手机号', '信息收集表单ID', | 
			
		||||
 | 
							'出发地', '出发地经度', '出发地纬度', '目的地', '目的地经度', '目的地纬度', '行程起始时间', '行程结束时间', | 
			
		||||
 | 
							'酒店名', '酒店地址', '酒店经度', '酒店纬度', | 
			
		||||
 | 
							'景区名', '景区地址', '景区经度', '景区纬度', | 
			
		||||
 | 
							'餐厅名', '餐厅地址', '餐厅经度', '餐厅纬度', | 
			
		||||
 | 
							'交通地址', '交通经度', '交通纬度', | 
			
		||||
 | 
							'购物地址', '购物经度', '购物纬度', | 
			
		||||
 | 
						]; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function columnFormats(): array | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						for ($i = 65; $i <= 90; $i++) { | 
			
		||||
 | 
							$format[chr($i)] = NumberFormat::FORMAT_TEXT; | 
			
		||||
 | 
						} | 
			
		||||
 | 
						return $format; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,176 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\Imports; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Models\Category; | 
			
		||||
 | 
				use App\Models\Product; | 
			
		||||
 | 
				use Illuminate\Support\Collection; | 
			
		||||
 | 
				use Illuminate\Support\Facades\Storage; | 
			
		||||
 | 
				use Maatwebsite\Excel\Concerns\ToCollection; | 
			
		||||
 | 
				use Maatwebsite\Excel\Facades\Excel; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ProductImport implements ToCollection | 
			
		||||
 | 
				{ | 
			
		||||
 | 
					private int $supplier_id; | 
			
		||||
 | 
					private string $extract_path; | 
			
		||||
 | 
					private array $keys = []; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function __construct(int $supplier_id, $extract_path) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$this->supplier_id = $supplier_id; | 
			
		||||
 | 
						$this->extract_path = $extract_path; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function collection(Collection $collection) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						if ($collection->isEmpty()) { | 
			
		||||
 | 
							return; | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						//校验数组count()是否正确
 | 
			
		||||
 | 
						if (count($collection[0]) < 35) { | 
			
		||||
 | 
							throw new \Exception('Excel产品信息格式不正确'); | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$this->keys = array_flip($collection[0]->toArray()); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						//去除第一行的标题
 | 
			
		||||
 | 
						unset($collection[0]); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						//$collection
 | 
			
		||||
 | 
						$this->createData($collection); | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					private function createData($rows) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$keys = $this->keys; | 
			
		||||
 | 
						foreach ($rows as $product_index => $row) { | 
			
		||||
 | 
							$category = Category::where(['agent_id' => 0, 'name' => trim($row[$keys['分类']])])->first(); | 
			
		||||
 | 
							if (!$category) continue; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							$insert_data = [ | 
			
		||||
 | 
								'supplier_id' => $this->supplier_id, | 
			
		||||
 | 
								'category_id' => $category->id, | 
			
		||||
 | 
								'type' => $category->publish_type, | 
			
		||||
 | 
								'title' => $row[$keys['产品标题']] ?? '', | 
			
		||||
 | 
								'price' => $row[$keys['销售价']] ?? 0, | 
			
		||||
 | 
								'original_price' => $row[$keys['市场价']] ?? 0, | 
			
		||||
 | 
								'stock' => $row[$keys['库存']] ?? 0, | 
			
		||||
 | 
								'know' => $row[$keys['旅客须知']] ?? '', | 
			
		||||
 | 
								'content' => $row[$keys['产品详情']] ?? '', | 
			
		||||
 | 
								'verify_mobile' => $row[$keys['核销手机号']] ?? '', | 
			
		||||
 | 
								'diy_form_id' => $row[$keys['信息收集表单ID']] ?? '', | 
			
		||||
 | 
								'pictures' => $this->get_pictures($product_index), | 
			
		||||
 | 
							]; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							# 扩展字段
 | 
			
		||||
 | 
							$insert_data['extends'] = $this->get_extends($category->publish_type, $row); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							if ($category->publish_type == 0) { | 
			
		||||
 | 
								$insert_data['longitude'] = $insert_data['extends']['field_0_departure_place_longitude'] ?? 0; | 
			
		||||
 | 
								$insert_data['latitude'] = $insert_data['extends']['field_0_departure_place_latitude'] ?? 0; | 
			
		||||
 | 
								$insert_data['address'] = $insert_data['extends']['field_0_departure_place'] ?? ''; | 
			
		||||
 | 
							} else { | 
			
		||||
 | 
								$insert_data['longitude'] = $insert_data['extends']['field_'.$category->publish_type.'_longitude'] ?? 0; | 
			
		||||
 | 
								$insert_data['latitude'] = $insert_data['extends']['field_'.$category->publish_type.'_latitude'] ?? 0; | 
			
		||||
 | 
								$insert_data['address'] = $insert_data['extends']['field_'.$category->publish_type.'_address'] ?? ''; | 
			
		||||
 | 
							} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							$product = Product::create($insert_data); | 
			
		||||
 | 
							if ($product->id) { | 
			
		||||
 | 
								$this->insert_spec($product_index, $product->id); | 
			
		||||
 | 
							} | 
			
		||||
 | 
						} | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					# 插入规格
 | 
			
		||||
 | 
					private function insert_spec($product_index, $product_id) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$spec_file = $this->extract_path . "/产品规格{$product_index}.xlsx"; | 
			
		||||
 | 
						if (file_exists($spec_file)) { | 
			
		||||
 | 
							Excel::import(new ProductSpecImport($product_id), $spec_file); | 
			
		||||
 | 
						} | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					# 遍历图片文件,并移动到storage/app/public/supplier/import目录下
 | 
			
		||||
 | 
					private function get_pictures($product_index): array | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$storage_disk = Storage::disk('public'); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$http_path = 'supplier/import/' . $this->supplier_id . '/' . date('Y-m'); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						if (!$storage_disk->exists($http_path)) { | 
			
		||||
 | 
							$storage_disk->makeDirectory($http_path); //Storage的makeDirectory才能递归创建
 | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$image_path = $this->extract_path . "/产品主图/$product_index"; | 
			
		||||
 | 
						chdir($image_path); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$pictures = []; | 
			
		||||
 | 
						foreach (glob('*') as $file) { | 
			
		||||
 | 
							$ext = strtolower(pathinfo($file)['extension']); | 
			
		||||
 | 
							if (!in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp', 'tiff', 'jfif'])) { | 
			
		||||
 | 
								continue; | 
			
		||||
 | 
							} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							$filename = '/' . md5_file($file) . '.' . $ext; | 
			
		||||
 | 
							$move_file = realpath($file); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							# Storage::move只适用于storage/app目录下的文件,且是相对路径
 | 
			
		||||
 | 
							if (rename($move_file, $storage_disk->path($http_path . $filename))) { | 
			
		||||
 | 
								$pictures[] = $http_path . $filename; | 
			
		||||
 | 
							} | 
			
		||||
 | 
						} | 
			
		||||
 | 
						return $pictures; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					# 获取扩展字段
 | 
			
		||||
 | 
					private function get_extends(int $publish_type, $row): array | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$keys = $this->keys; | 
			
		||||
 | 
						return match ($publish_type) { | 
			
		||||
 | 
							0 => [ | 
			
		||||
 | 
								'field_0_departure_place' => $row[$keys['出发地']] ?? '', | 
			
		||||
 | 
								'field_0_departure_place_longitude' => $row[$keys['出发地经度']] ?? 0, | 
			
		||||
 | 
								'field_0_departure_place_latitude' => $row[$keys['出发地纬度']] ?? 0, | 
			
		||||
 | 
								'field_0_destination' => $row[$keys['目的地']] ?? '', | 
			
		||||
 | 
								'field_0_destination_longitude' => $row[$keys['目的地经度']] ?? 0, | 
			
		||||
 | 
								'field_0_destination_latitude' => $row[$keys['目的地纬度']] ?? 0, | 
			
		||||
 | 
								'field_0_date' => [ | 
			
		||||
 | 
									# Excel日期是从1900-01-01起,PHP日期是1970-01-01起,所以要减去25569天数得到正确日期
 | 
			
		||||
 | 
									'start' => !empty($row[$keys['行程起始时间']]) ? date('Y-m-d', strtotime('+ ' . ($row[$keys['行程起始时间']] - 25569) . 'day', 0)) : '', | 
			
		||||
 | 
									'end' => !empty($row[$keys['行程结束时间']]) ? date('Y-m-d', strtotime('+ ' . ($row[$keys['行程结束时间']] - 25569) . 'day', 0)) : '', | 
			
		||||
 | 
								], | 
			
		||||
 | 
							], | 
			
		||||
 | 
							1 => [ | 
			
		||||
 | 
								'field_1_name' => $row[$keys['酒店名']] ?? '', | 
			
		||||
 | 
								'field_1_address' => $row[$keys['酒店地址']] ?? '', | 
			
		||||
 | 
								'field_1_longitude' => $row[$keys['酒店经度']] ?? 0, | 
			
		||||
 | 
								'field_1_latitude' => $row[$keys['酒店纬度']] ?? 0, | 
			
		||||
 | 
							], | 
			
		||||
 | 
							2 => [ | 
			
		||||
 | 
								'field_2_name' => $row[$keys['景区名']] ?? '', | 
			
		||||
 | 
								'field_2_address' => $row[$keys['景区地址']] ?? '', | 
			
		||||
 | 
								'field_2_longitude' => $row[$keys['景区经度']] ?? 0, | 
			
		||||
 | 
								'field_2_latitude' => $row[$keys['景区纬度']] ?? 0, | 
			
		||||
 | 
							], | 
			
		||||
 | 
							3 => [ | 
			
		||||
 | 
								'field_3_name' => $row[$keys['餐厅名']] ?? '', | 
			
		||||
 | 
								'field_3_address' => $row[$keys['餐厅地址']] ?? '', | 
			
		||||
 | 
								'field_3_longitude' => $row[$keys['餐厅经度']] ?? 0, | 
			
		||||
 | 
								'field_3_latitude' => $row[$keys['餐厅纬度']] ?? 0, | 
			
		||||
 | 
							], | 
			
		||||
 | 
							4 => [ | 
			
		||||
 | 
								'field_4_address' => $row[$keys['交通地址']] ?? '', | 
			
		||||
 | 
								'field_4_longitude' => $row[$keys['交通经度']] ?? 0, | 
			
		||||
 | 
								'field_4_latitude' => $row[$keys['交通纬度']] ?? 0, | 
			
		||||
 | 
							], | 
			
		||||
 | 
							5 => [ | 
			
		||||
 | 
								'field_5_address' => $row[$keys['购物地址']] ?? '', | 
			
		||||
 | 
								'field_5_longitude' => $row[$keys['购物经度']] ?? 0, | 
			
		||||
 | 
								'field_5_latitude' => $row[$keys['购物纬度']] ?? 0, | 
			
		||||
 | 
							], | 
			
		||||
 | 
							default => [], | 
			
		||||
 | 
						}; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,63 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\Imports; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Models\ProductSpec; | 
			
		||||
 | 
				use Illuminate\Support\Collection; | 
			
		||||
 | 
				use Illuminate\Support\Facades\DB; | 
			
		||||
 | 
				use Maatwebsite\Excel\Concerns\ToCollection; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ProductSpecImport implements ToCollection | 
			
		||||
 | 
				{ | 
			
		||||
 | 
					private int $product_id; | 
			
		||||
 | 
					private array $keys; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function __construct(int $product_id) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$this->product_id = $product_id; | 
			
		||||
 | 
					} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					public function collection(Collection $collection) | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						if ($collection->isEmpty()) { | 
			
		||||
 | 
							return; | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						//校验数组count()是否正确
 | 
			
		||||
 | 
						if (count($collection[0]) < 6) { | 
			
		||||
 | 
							throw new \Exception('Excel产品规格格式不正确'); | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$this->keys = array_flip($collection[0]->toArray()); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						//去除第一行的标题
 | 
			
		||||
 | 
						unset($collection[0]); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$this->createData($collection); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					private function createData($rows) | 
			
		||||
 | 
					{ | 
			
		||||
 | 
						$keys = $this->keys; | 
			
		||||
 | 
						DB::beginTransaction(); | 
			
		||||
 | 
						foreach ($rows as $row) { | 
			
		||||
 | 
							# Excel日期是从1900-01-01起的天数,PHP日期是1970-01-01起,所以要减去25569天数得到正确日期
 | 
			
		||||
 | 
							$row[$keys['日期']] = date('Y-m-d', strtotime('+ ' . ($row[$keys['日期']] - 25569) . 'day', 0)); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
							ProductSpec::updateOrCreate([ | 
			
		||||
 | 
								'product_id' => $this->product_id, | 
			
		||||
 | 
								'name' => $row[$keys['规格名称']], | 
			
		||||
 | 
								'date' => $row[$keys['日期']], | 
			
		||||
 | 
							], [ | 
			
		||||
 | 
								'product_id' => $this->product_id, | 
			
		||||
 | 
								'name' => $row[$keys['规格名称']], | 
			
		||||
 | 
								'date' => $row[$keys['日期']], | 
			
		||||
 | 
								'stock' => $row[$keys['库存']], | 
			
		||||
 | 
								'original_price' => $row[$keys['市场价']], | 
			
		||||
 | 
								'price' => $row[$keys['销售价']], | 
			
		||||
 | 
								'cost_price' => $row[$keys['成本价']], | 
			
		||||
 | 
							]); | 
			
		||||
 | 
						} | 
			
		||||
 | 
						DB::commit(); | 
			
		||||
 | 
					} | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,45 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\Jobs; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Exports\ProductExport; | 
			
		||||
 | 
				use App\Models\ProductExportLog; | 
			
		||||
 | 
				use Illuminate\Bus\Queueable; | 
			
		||||
 | 
				use Illuminate\Contracts\Queue\ShouldBeUnique; | 
			
		||||
 | 
				use Illuminate\Contracts\Queue\ShouldQueue; | 
			
		||||
 | 
				use Illuminate\Foundation\Bus\Dispatchable; | 
			
		||||
 | 
				use Illuminate\Queue\InteractsWithQueue; | 
			
		||||
 | 
				use Illuminate\Queue\SerializesModels; | 
			
		||||
 | 
				use Maatwebsite\Excel\Facades\Excel; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ExportProductToExcel implements ShouldQueue | 
			
		||||
 | 
				{ | 
			
		||||
 | 
				    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					private int $supplier_id; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * Create a new job instance. | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return void | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    public function __construct(int $supplier_id) | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						$this->supplier_id = $supplier_id; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * Execute the job. | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return void | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    public function handle() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						$filePath = "supplier/export/{$this->supplier_id}/" . date('Y-m') . "/导出产品-" . date('Y-m-d_H-i-s') . '.xlsx'; | 
			
		||||
 | 
						Excel::store(new ProductExport($this->supplier_id), $filePath, 'public'); | 
			
		||||
 | 
						ProductExportLog::create([ | 
			
		||||
 | 
							'supplier_id' => $this->supplier_id, | 
			
		||||
 | 
							'filename' => $filePath, | 
			
		||||
 | 
						]); | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,63 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				namespace App\Jobs; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use App\Imports\ProductImport; | 
			
		||||
 | 
				use Exception; | 
			
		||||
 | 
				use Illuminate\Bus\Queueable; | 
			
		||||
 | 
				use Illuminate\Contracts\Queue\ShouldBeUnique; | 
			
		||||
 | 
				use Illuminate\Contracts\Queue\ShouldQueue; | 
			
		||||
 | 
				use Illuminate\Foundation\Bus\Dispatchable; | 
			
		||||
 | 
				use Illuminate\Queue\InteractsWithQueue; | 
			
		||||
 | 
				use Illuminate\Queue\SerializesModels; | 
			
		||||
 | 
				use Illuminate\Support\Facades\Storage; | 
			
		||||
 | 
				use Maatwebsite\Excel\Facades\Excel; | 
			
		||||
 | 
				use ZipArchive; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				class ImportProductFromExcel implements ShouldQueue | 
			
		||||
 | 
				{ | 
			
		||||
 | 
				    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					private int $supplier_id; | 
			
		||||
 | 
					private string $zip_file; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /** | 
			
		||||
 | 
				     * Create a new job instance. | 
			
		||||
 | 
				     * | 
			
		||||
 | 
				     * @return void | 
			
		||||
 | 
				     */ | 
			
		||||
 | 
				    public function __construct(int $supplier_id, string $zip_file) | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						$this->supplier_id = $supplier_id; | 
			
		||||
 | 
						$this->zip_file = $zip_file; | 
			
		||||
 | 
				    } | 
			
		||||
 | 
				
 | 
			
		||||
 | 
					/** | 
			
		||||
 | 
					 * Execute the job. | 
			
		||||
 | 
					 * | 
			
		||||
 | 
					 * @return void | 
			
		||||
 | 
					 * @throws Exception | 
			
		||||
 | 
					 */ | 
			
		||||
 | 
				    public function handle() | 
			
		||||
 | 
				    { | 
			
		||||
 | 
						if (!$this->supplier_id) { | 
			
		||||
 | 
							throw new Exception('未指定要导入的供应商'); | 
			
		||||
 | 
						} else if (!$this->zip_file) { | 
			
		||||
 | 
							throw new Exception('未指定要导入的zip文件'); | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$extract_path = Storage::path('excel/extract/' . basename($this->zip_file, '.zip')); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						$zip = new ZipArchive; | 
			
		||||
 | 
						if ($zip->open($this->zip_file) === TRUE && $zip->extractTo($extract_path)) { | 
			
		||||
 | 
							$zip->close(); | 
			
		||||
 | 
						} else { | 
			
		||||
 | 
							throw new Exception("解压文件 {$this->zip_file} 失败!"); | 
			
		||||
 | 
						} | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						# 解压后删除压缩文件
 | 
			
		||||
 | 
						unlink($this->zip_file); | 
			
		||||
 | 
				
 | 
			
		||||
 | 
						Excel::import(new ProductImport($this->supplier_id, $extract_path), $extract_path . '/产品.xlsx'); | 
			
		||||
 | 
					} | 
			
		||||
 | 
				} | 
			
		||||
@ -0,0 +1,328 @@ | 
			
		|||||
 | 
				<?php | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				use Maatwebsite\Excel\Excel; | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				return [ | 
			
		||||
 | 
				    'exports' => [ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Chunk size | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When using FromQuery, the query is automatically chunked. | 
			
		||||
 | 
				        | Here you can specify how big the chunk should be. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'chunk_size'             => 1000, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Pre-calculate formulas during export | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'pre_calculate_formulas' => false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Enable strict null comparison | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When enabling strict null comparison empty cells ('') will | 
			
		||||
 | 
				        | be added to the sheet. | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'strict_null_comparison' => false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | CSV Settings | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Configure e.g. delimiter, enclosure and line ending for CSV exports. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'csv'                    => [ | 
			
		||||
 | 
				            'delimiter'              => ',', | 
			
		||||
 | 
				            'enclosure'              => '"', | 
			
		||||
 | 
				            'line_ending'            => PHP_EOL, | 
			
		||||
 | 
				            'use_bom'                => false, | 
			
		||||
 | 
				            'include_separator_line' => false, | 
			
		||||
 | 
				            'excel_compatibility'    => false, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Worksheet properties | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Configure e.g. default title, creator, subject,... | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'properties'             => [ | 
			
		||||
 | 
				            'creator'        => '', | 
			
		||||
 | 
				            'lastModifiedBy' => '', | 
			
		||||
 | 
				            'title'          => '', | 
			
		||||
 | 
				            'description'    => '', | 
			
		||||
 | 
				            'subject'        => '', | 
			
		||||
 | 
				            'keywords'       => '', | 
			
		||||
 | 
				            'category'       => '', | 
			
		||||
 | 
				            'manager'        => '', | 
			
		||||
 | 
				            'company'        => '', | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    'imports'            => [ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Read Only | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When dealing with imports, you might only be interested in the | 
			
		||||
 | 
				        | data that the sheet exists. By default we ignore all styles, | 
			
		||||
 | 
				        | however if you want to do some logic based on style data | 
			
		||||
 | 
				        | you can enable it by setting read_only to false. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'read_only' => true, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Ignore Empty | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When dealing with imports, you might be interested in ignoring | 
			
		||||
 | 
				        | rows that have null values or empty strings. By default rows | 
			
		||||
 | 
				        | containing empty strings or empty values are not ignored but can be | 
			
		||||
 | 
				        | ignored by enabling the setting ignore_empty to true. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'ignore_empty' => false, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Heading Row Formatter | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Configure the heading row formatter. | 
			
		||||
 | 
				        | Available options: none|slug|custom | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'heading_row' => [ | 
			
		||||
 | 
				            'formatter' => 'slug', | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | CSV Settings | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Configure e.g. delimiter, enclosure and line ending for CSV imports. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'csv'         => [ | 
			
		||||
 | 
				            'delimiter'        => ',', | 
			
		||||
 | 
				            'enclosure'        => '"', | 
			
		||||
 | 
				            'escape_character' => '\\', | 
			
		||||
 | 
				            'contiguous'       => false, | 
			
		||||
 | 
				            'input_encoding'   => 'UTF-8', | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Worksheet properties | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Configure e.g. default title, creator, subject,... | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'properties'  => [ | 
			
		||||
 | 
				            'creator'        => '', | 
			
		||||
 | 
				            'lastModifiedBy' => '', | 
			
		||||
 | 
				            'title'          => '', | 
			
		||||
 | 
				            'description'    => '', | 
			
		||||
 | 
				            'subject'        => '', | 
			
		||||
 | 
				            'keywords'       => '', | 
			
		||||
 | 
				            'category'       => '', | 
			
		||||
 | 
				            'manager'        => '', | 
			
		||||
 | 
				            'company'        => '', | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /* | 
			
		||||
 | 
				    |-------------------------------------------------------------------------- | 
			
		||||
 | 
				    | Extension detector | 
			
		||||
 | 
				    |-------------------------------------------------------------------------- | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | Configure here which writer/reader type should be used when the package | 
			
		||||
 | 
				    | needs to guess the correct type based on the extension alone. | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    */ | 
			
		||||
 | 
				    'extension_detector' => [ | 
			
		||||
 | 
				        'xlsx'     => Excel::XLSX, | 
			
		||||
 | 
				        'xlsm'     => Excel::XLSX, | 
			
		||||
 | 
				        'xltx'     => Excel::XLSX, | 
			
		||||
 | 
				        'xltm'     => Excel::XLSX, | 
			
		||||
 | 
				        'xls'      => Excel::XLS, | 
			
		||||
 | 
				        'xlt'      => Excel::XLS, | 
			
		||||
 | 
				        'ods'      => Excel::ODS, | 
			
		||||
 | 
				        'ots'      => Excel::ODS, | 
			
		||||
 | 
				        'slk'      => Excel::SLK, | 
			
		||||
 | 
				        'xml'      => Excel::XML, | 
			
		||||
 | 
				        'gnumeric' => Excel::GNUMERIC, | 
			
		||||
 | 
				        'htm'      => Excel::HTML, | 
			
		||||
 | 
				        'html'     => Excel::HTML, | 
			
		||||
 | 
				        'csv'      => Excel::CSV, | 
			
		||||
 | 
				        'tsv'      => Excel::TSV, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | PDF Extension | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Configure here which Pdf driver should be used by default. | 
			
		||||
 | 
				        | Available options: Excel::MPDF | Excel::TCPDF | Excel::DOMPDF | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'pdf'      => Excel::DOMPDF, | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /* | 
			
		||||
 | 
				    |-------------------------------------------------------------------------- | 
			
		||||
 | 
				    | Value Binder | 
			
		||||
 | 
				    |-------------------------------------------------------------------------- | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | PhpSpreadsheet offers a way to hook into the process of a value being | 
			
		||||
 | 
				    | written to a cell. In there some assumptions are made on how the | 
			
		||||
 | 
				    | value should be formatted. If you want to change those defaults, | 
			
		||||
 | 
				    | you can implement your own default value binder. | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | Possible value binders: | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | [x] Maatwebsite\Excel\DefaultValueBinder::class | 
			
		||||
 | 
				    | [x] PhpOffice\PhpSpreadsheet\Cell\StringValueBinder::class | 
			
		||||
 | 
				    | [x] PhpOffice\PhpSpreadsheet\Cell\AdvancedValueBinder::class | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    */ | 
			
		||||
 | 
				    'value_binder' => [ | 
			
		||||
 | 
				        'default' => Maatwebsite\Excel\DefaultValueBinder::class, | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    'cache' => [ | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Default cell caching driver | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | By default PhpSpreadsheet keeps all cell values in memory, however when | 
			
		||||
 | 
				        | dealing with large files, this might result into memory issues. If you | 
			
		||||
 | 
				        | want to mitigate that, you can configure a cell caching driver here. | 
			
		||||
 | 
				        | When using the illuminate driver, it will store each value in a the | 
			
		||||
 | 
				        | cache store. This can slow down the process, because it needs to | 
			
		||||
 | 
				        | store each value. You can use the "batch" store if you want to | 
			
		||||
 | 
				        | only persist to the store when the memory limit is reached. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | Drivers: memory|illuminate|batch | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'driver'     => 'memory', | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Batch memory caching | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When dealing with the "batch" caching driver, it will only | 
			
		||||
 | 
				        | persist to the store when the memory limit is reached. | 
			
		||||
 | 
				        | Here you can tweak the memory limit to your liking. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'batch'     => [ | 
			
		||||
 | 
				            'memory_limit' => 60000, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Illuminate cache | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When using the "illuminate" caching driver, it will automatically use | 
			
		||||
 | 
				        | your default cache store. However if you prefer to have the cell | 
			
		||||
 | 
				        | cache on a separate store, you can configure the store name here. | 
			
		||||
 | 
				        | You can use any store defined in your cache config. When leaving | 
			
		||||
 | 
				        | at "null" it will use the default store. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'illuminate' => [ | 
			
		||||
 | 
				            'store' => null, | 
			
		||||
 | 
				        ], | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    /* | 
			
		||||
 | 
				    |-------------------------------------------------------------------------- | 
			
		||||
 | 
				    | Transaction Handler | 
			
		||||
 | 
				    |-------------------------------------------------------------------------- | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | By default the import is wrapped in a transaction. This is useful | 
			
		||||
 | 
				    | for when an import may fail and you want to retry it. With the | 
			
		||||
 | 
				    | transactions, the previous import gets rolled-back. | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | You can disable the transaction handler by setting this to null. | 
			
		||||
 | 
				    | Or you can choose a custom made transaction handler here. | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    | Supported handlers: null|db | 
			
		||||
 | 
				    | | 
			
		||||
 | 
				    */ | 
			
		||||
 | 
				    'transactions' => [ | 
			
		||||
 | 
				        'handler' => 'db', | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				    'temporary_files' => [ | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Local Temporary Path | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When exporting and importing files, we use a temporary file, before | 
			
		||||
 | 
				        | storing reading or downloading. Here you can customize that path. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'local_path'          => storage_path('framework/cache/laravel-excel'), | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Remote Temporary Disk | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When dealing with a multi server setup with queues in which you | 
			
		||||
 | 
				        | cannot rely on having a shared local temporary path, you might | 
			
		||||
 | 
				        | want to store the temporary file on a shared disk. During the | 
			
		||||
 | 
				        | queue executing, we'll retrieve the temporary file from that | 
			
		||||
 | 
				        | location instead. When left to null, it will always use | 
			
		||||
 | 
				        | the local path. This setting only has effect when using | 
			
		||||
 | 
				        | in conjunction with queued imports and exports. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'remote_disk'         => null, | 
			
		||||
 | 
				        'remote_prefix'       => null, | 
			
		||||
 | 
				
 | 
			
		||||
 | 
				        /* | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | Force Resync | 
			
		||||
 | 
				        |-------------------------------------------------------------------------- | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        | When dealing with a multi server setup as above, it's possible | 
			
		||||
 | 
				        | for the clean up that occurs after entire queue has been run to only | 
			
		||||
 | 
				        | cleanup the server that the last AfterImportJob runs on. The rest of the server | 
			
		||||
 | 
				        | would still have the local temporary file stored on it. In this case your | 
			
		||||
 | 
				        | local storage limits can be exceeded and future imports won't be processed. | 
			
		||||
 | 
				        | To mitigate this you can set this config value to be true, so that after every | 
			
		||||
 | 
				        | queued chunk is processed the local temporary file is deleted on the server that | 
			
		||||
 | 
				        | processed it. | 
			
		||||
 | 
				        | | 
			
		||||
 | 
				        */ | 
			
		||||
 | 
				        'force_resync_remote' => null, | 
			
		||||
 | 
				    ], | 
			
		||||
 | 
				]; | 
			
		||||
						Write
						Preview
					
					
					Loading…
					
					Cancel
						Save
					
		Reference in new issue