middleware('auth'); $this->middleware('company.identify'); } public function import(Request $request, string $summaryPage): RedirectResponse { $this->authorizePage($summaryPage); $this->store->title($summaryPage); $request->validate([ 'import' => ['required', 'file', 'mimes:xlsx,xls,csv', 'max:10240'], ]); try { $result = $this->store->import( $request->file('import'), (int) (company_id() ?: 1), $summaryPage, user_id() ? (int) user_id() : null, ); } catch (RuntimeException $exception) { report($exception); return $this->redirectToPage($summaryPage)->with('error', '汇总数据保存失败,请稍后重试。'); } return $this->redirectToPage($summaryPage)->with( 'success', "导入完成:{$result['rows']} 条数据,{$result['columns']} 个字段。", ); } public function template(string $summaryPage): BinaryFileResponse { $this->authorizePage($summaryPage); abort_unless($summaryPage === 'freight-difference', 404); $path = resource_path('templates/courier-payables/freight-difference-import-template.xlsx'); abort_unless(is_file($path), 404); $response = response()->download($path, 'freight_difference_import_template.xlsx', [ 'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'Cache-Control' => 'private, no-store', ]); return $response->setContentDisposition( 'attachment', '运费差导入模板.xlsx', 'freight_difference_import_template.xlsx', ); } public function export(string $summaryPage): StreamedResponse|RedirectResponse { $this->authorizePage($summaryPage); $title = $this->store->title($summaryPage); try { $snapshot = $this->store->snapshot((int) (company_id() ?: 1), $summaryPage); } catch (RuntimeException) { return $this->redirectToPage($summaryPage)->with('error', '汇总数据暂时无法读取,请重新导入后再试。'); } if ($snapshot === null) { return $this->redirectToPage($summaryPage)->with('error', '当前没有可导出的汇总数据。'); } return response()->streamDownload(function () use ($snapshot): void { $csv = fopen('php://output', 'w'); if ($csv === false) { throw new RuntimeException('无法创建汇总数据导出流。'); } fputs($csv, chr(0xEF) . chr(0xBB) . chr(0xBF)); fputcsv($csv, array_map([$this, 'csvText'], $snapshot['headers'])); foreach ($snapshot['rows'] as $row) { fputcsv($csv, array_map([$this, 'csvText'], $row)); } fclose($csv); }, $title . '_' . now()->format('Ymd_His') . '.csv', [ 'Content-Type' => 'text/csv; charset=UTF-8', 'Cache-Control' => 'private, no-store', ]); } private function redirectToPage(string $summaryPage): RedirectResponse { return redirect()->route('business.pages.show', [ 'section' => 'courier-payables', 'page' => $summaryPage, ]); } private function authorizePage(string $summaryPage): void { $section = collect(SidebarPermissions::navigationFor(user())) ->firstWhere('slug', 'courier-payables'); $pages = collect($section['pages'] ?? [])->flatMap(static fn (array $page): array => [ $page, ...($page['children'] ?? []), ]); abort_unless($pages->contains('slug', $summaryPage), 403, '当前账号没有该页面权限。'); } private function csvText(mixed $value): string { $value = (string) $value; if (preg_match('/^[+-]?(?:(?:\d{1,3}(?:,\d{3})+|\d+)(?:\.\d+)?|\.\d+)%?$/u', $value) === 1) { return $value; } return preg_match('/^[=+\-@\t\r]/u', $value) === 1 ? "\t" . $value : $value; } }