From ea2d2f9ca1f21064e7378d06ccd1b9a770bccfd8 Mon Sep 17 00:00:00 2001 From: WuYongJie <549727955@qq.com> Date: Thu, 24 Sep 2026 00:00:26 +0800 Subject: [PATCH] feat: improve business directory filters and export --- app/Business/UpstreamBusinessInformation.php | 49 ++- app/Utilities/SidebarPermissions.php | 25 +- config/business_navigation.php | 22 + .../BusinessInformationMirrorRepository.php | 143 +++++- .../StoreAccountMirrorRepository.php | 41 +- .../pages/partials/directory-table.blade.php | 406 +++++++++++++++++- .../pages/partials/prototype-page.blade.php | 4 + .../components/layouts/admin/menu.blade.php | 1 + tests/Feature/Business/ManagementCrudTest.php | 27 +- ...usinessInformationMirrorRepositoryTest.php | 24 ++ .../StoreAccountMirrorRepositoryTest.php | 5 +- .../UpstreamBusinessInformationTest.php | 2 +- 12 files changed, 722 insertions(+), 27 deletions(-) diff --git a/app/Business/UpstreamBusinessInformation.php b/app/Business/UpstreamBusinessInformation.php index 24039b72..e5da4d50 100644 --- a/app/Business/UpstreamBusinessInformation.php +++ b/app/Business/UpstreamBusinessInformation.php @@ -88,10 +88,12 @@ class UpstreamBusinessInformation private function companyPage(int $page, int $perPage): array { + $filters = $this->pageFilters('company-management', 'basic-information'); return $this->page( 'company-information.read', $page, $perPage, + $filters, fn () => $this->snapshot('company-information.read', [ 'page' => $page, 'perPage' => $perPage, @@ -133,10 +135,12 @@ SQL); private function storePage(int $page, int $perPage): array { + $filters = $this->pageFilters('store-management', 'basic-information'); return $this->page( 'store-information.read', $page, $perPage, + $filters, fn () => $this->snapshot('store-information.read', [ 'page' => $page, 'perPage' => $perPage, @@ -157,7 +161,11 @@ SQL); private function storeAccountPage(int $page, int $perPage): array { try { - return ($this->storeAccounts ?? app(StoreAccountMirrorRepository::class))->paginate($page, $perPage); + return ($this->storeAccounts ?? app(StoreAccountMirrorRepository::class))->paginate( + $page, + $perPage, + $this->pageFilters('store-management', 'store-accounts'), + ); } catch (\RuntimeException $exception) { report($exception); throw new ServiceUnavailableHttpException(null, '店铺账号共享镜像尚未完成首次同步。'); @@ -469,10 +477,12 @@ SQL); private function trademarkPage(int $page, int $perPage): array { + $filters = $this->pageFilters('trademark-management', 'information'); return $this->page( 'trademark-information.read', $page, $perPage, + $filters, fn () => $this->snapshot('trademark-information.read', [ 'page' => $page, 'perPage' => $perPage, @@ -509,10 +519,14 @@ SQL); ]; } - private function page(string $scope, int $page, int $perPage, callable $resolver): array + private function page(string $scope, int $page, int $perPage, array $filters, callable $resolver): array { if ($this->mirror->ready($scope)) { - return $this->normalize($scope, $this->mirror->paginate($scope, $page, $perPage)); + return $this->normalize($scope, $this->mirror->paginate($scope, $page, $perPage, $filters)); + } + + if ($filters !== []) { + throw new ServiceUnavailableHttpException(null, '当前数据源暂不支持所选条件查询,请检查共享业务镜像状态。'); } if ((app(\App\Utilities\SystemDatabaseConfiguration::class)->current()['mode'] ?? '') === 'bootstrap' @@ -527,6 +541,34 @@ SQL); }); } + /** @return array */ + private function pageFilters(string $section, string $page): array + { + $fields = collect(config('business_navigation')) + ->firstWhere('slug', $section)['pages'] ?? []; + $pageConfig = collect($fields)->flatMap(fn (array $item) => [$item, ...($item['children'] ?? [])])->firstWhere('slug', $page); + $allowed = collect($pageConfig['directory']['fields'] ?? []) + ->reject(fn (array $field) => ($field['kind'] ?? '') === 'secret' && ($field['name'] ?? '') !== 'withdrawal_account') + ->pluck('name')->all(); + if ($section === 'company-management' && $page === 'basic-information') { + $allowed = array_values(array_unique([...$allowed, 'company_type', 'related_people'])); + } + $filters = []; + foreach ($allowed as $name) { + foreach ([$name, $name . '_from', $name . '_to'] as $key) { + $value = trim((string) request($key, '')); + if ($value !== '') $filters[$key] = mb_substr($value, 0, 191); + } + } + $sort = trim((string) request('sort', '')); + if (in_array($sort, $allowed, true)) { + $filters['_sort'] = $sort; + $filters['_direction'] = request('direction') === 'desc' ? 'desc' : 'asc'; + } + + return $filters; + } + /** @param array{data: array>, total: int} $payload */ private function normalize(string $scope, array $payload): array { @@ -548,6 +590,7 @@ SQL); $row = $this->toUtf8($row); $row['establishment_date'] = $this->date($row['establishment_date'] ?? null); $row['subscribed_at'] = $this->date($row['subscribed_at'] ?? null); + $row['city'] = RegisteredAddressCity::parse($row['registered_address'] ?? null); $row['company_status'] = match ((string) ($row['company_status'] ?? '')) { '0' => '正常', '1' => '已注销', diff --git a/app/Utilities/SidebarPermissions.php b/app/Utilities/SidebarPermissions.php index 9c9a0eb2..f721d1a3 100644 --- a/app/Utilities/SidebarPermissions.php +++ b/app/Utilities/SidebarPermissions.php @@ -76,7 +76,7 @@ class SidebarPermissions return $navigation; } - return array_values(array_filter(array_map(function (array $section) use ($allowed) { + $navigation = array_values(array_filter(array_map(function (array $section) use ($allowed) { $sectionKey = $section['slug']; if (in_array($sectionKey, $allowed, true)) { @@ -118,6 +118,29 @@ class SidebarPermissions return null; }, $navigation))); + + // 新增的公司成本安排与主体经营报表共用公司经营报表权限。 + // 对已经保存过精确权限的账号兼容旧配置,避免新增页面被旧权限集合隐藏。 + foreach ($navigation as &$section) { + if (($section['slug'] ?? null) !== 'company-management') { + continue; + } + + $hasSubjectReport = collect($section['pages'] ?? [])->contains('slug', 'subject-operating-report'); + $hasCostArrangement = collect($section['pages'] ?? [])->contains('slug', 'company-cost-arrangement'); + + if ($hasSubjectReport && ! $hasCostArrangement) { + $costPage = collect(BusinessNavigation::all()) + ->firstWhere('slug', 'company-management')['pages'] ?? []; + $costPage = collect($costPage)->firstWhere('slug', 'company-cost-arrangement'); + if ($costPage) { + $section['pages'][] = $costPage; + } + } + } + unset($section); + + return $navigation; } public static function allKeys(): array diff --git a/config/business_navigation.php b/config/business_navigation.php index f1d57ed8..e05aaa85 100644 --- a/config/business_navigation.php +++ b/config/business_navigation.php @@ -26,6 +26,28 @@ $navigation = [ ], ], ], + [ + 'slug' => 'company-cost-arrangement', + 'title' => '公司成本安排', + 'directory' => [ + 'icon' => 'account_balance_wallet', + 'status' => '报表待定义', + 'description' => '按公司主体查看当月收入、成本缺口及成本费用安排。', + 'empty' => '公司成本安排尚未同步数据。', + 'fields' => [ + ['name' => 'company', 'label' => '公司'], + ['name' => 'company_type', 'label' => '公司类型'], + ['name' => 'invoice_type', 'label' => '发票类型'], + ['name' => 'current_month_income_forecast', 'label' => '当月收入预测', 'kind' => 'number'], + ['name' => 'historical_cost_gap', 'label' => '往期成本缺口', 'kind' => 'number'], + ['name' => 'supplier_cost_arrangement', 'label' => '供应商成本安排', 'kind' => 'number'], + ['name' => 'courier_cost_arrangement', 'label' => '快递成本安排', 'kind' => 'number'], + ['name' => 'current_month_tax_forecast', 'label' => '当月税金预测', 'kind' => 'number'], + ['name' => 'labor_cost_forecast', 'label' => '人工成本预测', 'kind' => 'number'], + ['name' => 'other_expense_forecast', 'label' => '其他费用预测', 'kind' => 'number'], + ], + ], + ], [ 'slug' => 'basic-information', 'title' => '公司基础信息', diff --git a/modules/EcommerceFinance/Repositories/BusinessInformationMirrorRepository.php b/modules/EcommerceFinance/Repositories/BusinessInformationMirrorRepository.php index 0700039e..8902d8c6 100644 --- a/modules/EcommerceFinance/Repositories/BusinessInformationMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/BusinessInformationMirrorRepository.php @@ -31,7 +31,7 @@ class BusinessInformationMirrorRepository } /** @return array{data: array>, total: int} */ - public function paginate(string $scope, int $page, int $perPage): array + public function paginate(string $scope, int $page, int $perPage, array $filters = []): array { if (! $this->ready($scope)) { throw new RuntimeException('business_mirror_dataset_not_ready'); @@ -41,9 +41,9 @@ class BusinessInformationMirrorRepository $perPage = min(max($perPage, 1), 100); return match ($scope) { - 'company-information.read' => $this->companies($page, $perPage), - 'store-information.read' => $this->stores($page, $perPage), - 'trademark-information.read' => $this->trademarks($page, $perPage), + 'company-information.read' => $this->companies($page, $perPage, $filters), + 'store-information.read' => $this->stores($page, $perPage, $filters), + 'trademark-information.read' => $this->trademarks($page, $perPage, $filters), default => throw new InvalidArgumentException('未知的业务资料镜像范围:' . $scope), }; } @@ -162,7 +162,7 @@ SQL) } /** @return array{data: array>, total: int} */ - private function companies(int $page, int $perPage): array + private function companies(int $page, int $perPage, array $filters): array { $query = $this->connection->table('ops_fys_company_info') ->selectRaw(<<<'SQL' @@ -184,13 +184,77 @@ taxCategoryAndType AS taxpayer_category, NULL AS shareholders SQL); - return $this->page($query, $page, $perPage, 'Id'); + $this->applyFieldFilters($query, $filters, [ + 'unified_social_credit_code' => 'unifiedSocialCreditCode', 'company_name' => 'businessLicenseName', + 'establishment_date' => 'IncorporationDate', + 'registered_at' => 'IncorporationDate', + 'legal_representative' => 'legalRepresentative', 'registered_address' => 'registeredAddress', + 'city' => 'registeredAddress', + 'business_scope' => 'businessScope', 'subscribed_at' => 'registeredCapitalVaildTime', + 'financial_officer' => 'financialManager', + 'billing_officer' => 'financialManager', + 'supervisor' => 'supervisor', + ], ['subscribed_capital' => 'registeredCapital'], [ + 'company_type' => 'businessLicenseType', + 'taxpayer_type' => 'taxCategoryAndType', + 'taxpayer_category' => 'taxCategoryAndType', + ]); + $companyStatus = trim((string) ($filters['company_status'] ?? '')); + if ($companyStatus !== '') { + $statusCode = ['正常' => '0', '已注销' => '1'][$companyStatus] ?? $companyStatus; + $query->where('companyStatus', '=', $statusCode); + } + $relatedPeople = mb_substr(trim((string) ($filters['related_people'] ?? '')), 0, 191); + if ($relatedPeople !== '') { + $like = '%' . addcslashes($relatedPeople, '%_\\') . '%'; + $query->where(function ($query) use ($like): void { + $query->where('legalRepresentative', 'like', $like) + ->orWhere('supervisor', 'like', $like) + ->orWhere('financialManager', 'like', $like); + }); + } + return $this->page($query, $page, $perPage, 'Id', $filters, [ + 'unified_social_credit_code' => 'unifiedSocialCreditCode', 'company_name' => 'businessLicenseName', + 'taxpayer_type' => 'taxCategoryAndType', 'company_status' => 'companyStatus', + 'subscribed_capital' => 'registeredCapital', 'registered_at' => 'IncorporationDate', + 'legal_representative' => 'legalRepresentative', 'supervisor' => 'supervisor', + 'billing_officer' => 'financialManager', 'registered_address' => 'registeredAddress', + 'city' => 'registeredAddress', 'business_scope' => 'businessScope', + 'basic_deposit_account' => 'accountSerialNumber', 'subscribed_at' => 'registeredCapitalVaildTime', + ]); } /** @return array{data: array>, total: int} */ - private function stores(int $page, int $perPage): array + private function stores(int $page, int $perPage, array $filters): array { - return $this->page($this->storeQuery(), $page, $perPage, 's.Id'); + $query = $this->storeQuery(); + $this->applyFieldFilters($query, $filters, [ + 'store_id' => 's.sotreId', 'store_name' => 's.erpShopName', 'store_entity' => 'c.businessLicenseName', + 'trademark' => 't.trademarkName', 'trademark_number' => 's.trademarkNumber', + 'business_department' => 's.responsibleDepartment', 'store_manager' => 's.shopHead', + 'department_manager' => 's.customerDeptManager', 'opened_at' => 's.openTime', 'renewed_at' => 's.renewalTime', + ], [], ['platform' => 's.platform']); + $storeStatus = trim((string) ($filters['store_status'] ?? '')); + if ($storeStatus !== '') { + $statusCode = ['正常' => '0', '关闭中' => '3', '已关闭' => '6'][$storeStatus] ?? $storeStatus; + $query->where('s.shopState', '=', $statusCode); + } + $withdrawalAccount = trim((string) ($filters['withdrawal_account'] ?? '')); + if ($withdrawalAccount === '已配置') { + $query->whereNotNull('s.shopBankAccount')->where('s.shopBankAccount', '<>', ''); + } elseif ($withdrawalAccount === '未配置') { + $query->where(function ($query): void { + $query->whereNull('s.shopBankAccount')->orWhere('s.shopBankAccount', '=', ''); + }); + } + return $this->page($query, $page, $perPage, 's.Id', $filters, [ + 'platform' => 's.platform', 'store_id' => 's.sotreId', 'store_name' => 's.erpShopName', + 'store_entity' => 'c.businessLicenseName', 'store_status' => 's.shopState', + 'trademark' => 't.trademarkName', 'trademark_number' => 's.trademarkNumber', + 'business_department' => 's.responsibleDepartment', 'store_manager' => 's.shopHead', + 'department_manager' => 's.customerDeptManager', 'opened_at' => 's.openTime', + 'renewed_at' => 's.renewalTime', 'withdrawal_account' => 's.shopBankAccount', + ]); } private function storeQuery() @@ -245,7 +309,7 @@ SQL); } /** @return array{data: array>, total: int} */ - private function trademarks(int $page, int $perPage): array + private function trademarks(int $page, int $perPage, array $filters): array { $query = $this->connection->table('ops_fys_trademark_info') ->where('isDelete', 0) @@ -264,14 +328,69 @@ custodyDepartment AS custody_department, remark AS notes SQL); - return $this->page($query, $page, $perPage, 'Id'); + $this->applyFieldFilters($query, $filters, [ + 'trademark_number' => 'trademarkNumber', 'trademark_name' => 'trademarkName', + 'registration_date' => 'registrationDate', + 'expiry_date' => 'termOfValidity', 'international_classification' => 'internationalClassification', + 'approved_goods' => 'approvedCommodities', 'final_holder' => 'transferenceUser', + 'registered_address' => 'registrationAddress', 'custody_department' => 'custodyDepartment', + ]); + $status = trim((string) ($filters['trademark_status'] ?? '')); + if ($status !== '') { + $statusCode = ['未启用' => '0', '有效' => '1'][$status] ?? $status; + $query->where('trademarkStatus', '=', $statusCode); + } + return $this->page($query, $page, $perPage, 'Id', $filters, [ + 'trademark_name' => 'trademarkName', 'trademark_number' => 'trademarkNumber', + 'trademark_status' => 'trademarkStatus', 'registration_date' => 'registrationDate', + 'expiry_date' => 'termOfValidity', 'international_classification' => 'internationalClassification', + 'approved_goods' => 'approvedCommodities', 'final_holder' => 'transferenceUser', + 'registered_address' => 'registrationAddress', 'custody_department' => 'custodyDepartment', + ]); + } + + /** @param array $textColumns @param array $exactColumns @param array $enumColumns */ + private function applyFieldFilters($query, array $filters, array $textColumns, array $exactColumns = [], array $enumColumns = []): void + { + foreach ($textColumns as $key => $column) { + $value = mb_substr(trim((string) ($filters[$key] ?? '')), 0, 191); + if ($value !== '') { + $query->where($column, 'like', '%' . addcslashes($value, '%_\\') . '%'); + } + } + foreach ($exactColumns as $key => $column) { + $value = trim((string) ($filters[$key] ?? '')); + if ($value !== '') { + $query->where($column, '=', $value); + } + } + foreach ($enumColumns as $key => $column) { + $value = trim((string) ($filters[$key] ?? '')); + if ($value !== '') { + $query->where($column, '=', $value); + } + } + foreach (['opened_at' => 's.openTime', 'renewed_at' => 's.renewalTime', 'registration_date' => 'registrationDate', 'expiry_date' => 'termOfValidity'] as $key => $column) { + if (! array_key_exists($key, $textColumns)) continue; + foreach (['_from' => '>=', '_to' => '<='] as $suffix => $operator) { + $date = trim((string) ($filters[$key . $suffix] ?? '')); + if (preg_match('/^\\d{4}-\\d{2}-\\d{2}$/D', $date)) $query->where($column, $operator, $date); + } + } } /** @return array{data: array>, total: int} */ - private function page($query, int $page, int $perPage, string $orderColumn): array + private function page($query, int $page, int $perPage, string $orderColumn, array $filters = [], array $sortColumns = []): array { $total = (clone $query)->count(); - $rows = $query->orderByDesc($orderColumn) + $sortColumn = $sortColumns[$filters['_sort'] ?? ''] ?? null; + $direction = ($filters['_direction'] ?? 'asc') === 'desc' ? 'desc' : 'asc'; + if ($sortColumn !== null) { + $query->orderBy($sortColumn, $direction)->orderByDesc($orderColumn); + } else { + $query->orderByDesc($orderColumn); + } + $rows = $query ->forPage($page, $perPage) ->get() ->map(static fn (object $row): array => (array) $row) diff --git a/modules/EcommerceFinance/Repositories/StoreAccountMirrorRepository.php b/modules/EcommerceFinance/Repositories/StoreAccountMirrorRepository.php index 91ed7d7f..5880ccb0 100644 --- a/modules/EcommerceFinance/Repositories/StoreAccountMirrorRepository.php +++ b/modules/EcommerceFinance/Repositories/StoreAccountMirrorRepository.php @@ -15,7 +15,7 @@ class StoreAccountMirrorRepository ) {} /** @return array{data:array>,total:int} */ - public function paginate(int $page, int $perPage): array + public function paginate(int $page, int $perPage, array $filters = []): array { $dataset = $this->datasets->get(self::DATASET); if (! $this->mirror->ready($dataset)) { @@ -25,9 +25,46 @@ class StoreAccountMirrorRepository $page = max($page, 1); $perPage = min(max($perPage, 1), 100); $query = $this->mirror->connection()->table($dataset->targetTable()); + $columns = [ + 'store_name' => 'storeName', 'operation_owner' => 'operationOwner', + 'operation_department_head' => 'operationDepartmentHead', 'operation_director' => 'operationDirector', + 'profit_center' => 'profitCenter', 'account' => 'account', 'bound_phone' => 'boundPhone', + 'verification_contact' => 'verificationContact', 'account_group_name' => 'accountGroupName', + ]; + foreach ($columns as $key => $column) { + $value = mb_substr(trim((string) ($filters[$key] ?? '')), 0, 191); + if ($value !== '') $query->where($column, 'like', '%' . addcslashes($value, '%_\\') . '%'); + } + $accountType = trim((string) ($filters['account_type'] ?? '')); + if ($accountType !== '') $query->where('accountType', '=', $accountType === '主账号' ? 'MAIN' : ($accountType === '子账号' ? 'SUB' : $accountType)); + $passwordState = trim((string) ($filters['password_configured'] ?? '')); + if (in_array($passwordState, ['已设置', '未设置', '状态未同步'], true)) { + if ($passwordState === '状态未同步') $query->whereNull('passwordConfigured'); + else $query->where('passwordConfigured', $passwordState === '已设置'); + } + foreach (['created_at' => 'createdAt', 'updated_at' => 'updatedAt'] as $key => $column) { + foreach (['_from' => '>=', '_to' => '<='] as $suffix => $operator) { + $date = trim((string) ($filters[$key . $suffix] ?? '')); + if (preg_match('/^\d{4}-\d{2}-\d{2}$/D', $date)) $query->whereDate($column, $operator, $date); + } + } $total = (clone $query)->count(); + $sortColumns = [ + 'store_name' => 'storeName', 'operation_owner' => 'operationOwner', + 'operation_department_head' => 'operationDepartmentHead', 'operation_director' => 'operationDirector', + 'profit_center' => 'profitCenter', 'account_type' => 'accountType', 'account' => 'account', + 'password_configured' => 'passwordConfigured', 'bound_phone' => 'boundPhone', + 'verification_contact' => 'verificationContact', 'account_group_name' => 'accountGroupName', + 'created_at' => 'createdAt', 'updated_at' => 'updatedAt', + ]; + $sortColumn = $sortColumns[$filters['_sort'] ?? ''] ?? null; + $direction = ($filters['_direction'] ?? 'asc') === 'desc' ? 'desc' : 'asc'; + if ($sortColumn !== null) { + $query->orderBy($sortColumn, $direction)->orderByDesc('id'); + } else { + $query->orderByDesc('id'); + } $rows = $query - ->orderByDesc('id') ->forPage($page, $perPage) ->get() ->map(fn (object $row): array => [ diff --git a/resources/views/business/pages/partials/directory-table.blade.php b/resources/views/business/pages/partials/directory-table.blade.php index eaa1c021..abb0c618 100644 --- a/resources/views/business/pages/partials/directory-table.blade.php +++ b/resources/views/business/pages/partials/directory-table.blade.php @@ -23,6 +23,19 @@ $directoryCurrentPage = $directoryIsPaginated ? $directoryRows->currentPage() : 1; $directoryLastPage = $directoryIsPaginated ? $directoryRows->lastPage() : 1; $directoryPerPage = $directoryIsPaginated ? $directoryRows->perPage() : 0; + $directoryPageKey = ($section['slug'] ?? '') . '/' . ($page['slug'] ?? ''); + $directoryUsesFieldQuery = in_array($directoryPageKey, [ + 'company-management/basic-information', + 'store-management/basic-information', + 'trademark-management/information', + 'store-management/store-accounts', + ], true); + $directoryQueryPageDescriptions = [ + 'company-management/basic-information' => '公司主体、状态和登记资料的查询与导出', + 'store-management/basic-information' => '店铺主体、平台和经营资料的查询与导出', + 'trademark-management/information' => '商标主体、状态和登记资料的查询与导出', + 'store-management/store-accounts' => '店铺账号资料的查询与安全状态导出', + ]; @endphp
+ @if ($directoryUsesFieldQuery) +
+
+ {{ $page['title'] ?? $section['title'] }} +

{{ $directoryQueryPageDescriptions[$directoryPageKey] ?? '基础资料的查询与导出' }}

+
+ {{ $directory['status'] ?? '尚未同步' }} +
+ @if (!empty($upstreamError)) + + @endif + @else
@@ -400,8 +530,140 @@ {{ $directory['empty'] ?? '数据尚未同步,当前只展示已确认的字段结构。' }}
@endif + @endif @if (!empty($directoryFields)) + @php + $directoryQueryFields = $directoryPageKey === 'company-management/basic-information' + ? [ + ['name' => 'unified_social_credit_code', 'label' => '统一社会信用代码', 'placeholder' => '输入完整或部分代码'], + ['name' => 'company_name', 'label' => '公司名称', 'placeholder' => '输入公司名称关键词'], + ['name' => 'taxpayer_type', 'label' => '纳税人类型'], + ['name' => 'company_status', 'label' => '公司状态'], + ['name' => 'legal_representative', 'label' => '法人', 'placeholder' => '按姓名查询'], + ['name' => 'city', 'label' => '城市', 'placeholder' => '城市较多,使用搜索'], + ['name' => 'related_people', 'label' => '相关人员', 'placeholder' => '输入人员姓名,模糊匹配'], + ['name' => 'company_type', 'label' => '公司类型'], + ] + : $directoryFields; + $directoryExcludedQueryFields = match ($directoryPageKey) { + 'store-management/basic-information' => ['opened_at', 'renewed_at'], + 'trademark-management/information' => ['registration_date', 'expiry_date'], + default => [], + }; + if (!empty($directoryExcludedQueryFields)) { + $directoryQueryFields = collect($directoryQueryFields) + ->reject(fn (array $field): bool => in_array( + $field['name'], + $directoryExcludedQueryFields, + true, + )) + ->values() + ->all(); + } + $directorySelectFields = match (($section['slug'] ?? '') . '/' . ($page['slug'] ?? '')) { + 'company-management/basic-information' => ['taxpayer_type', 'company_status', 'company_type'], + 'store-management/basic-information' => ['platform', 'store_status', 'withdrawal_account'], + 'trademark-management/information' => ['trademark_status'], + 'store-management/store-accounts' => ['account_type', 'password_configured'], + default => [], + }; + $directoryColumnNames = collect($directoryFields)->pluck('name')->all(); + $requestedDirectoryColumns = array_values(array_intersect( + array_filter(explode(',', (string) request('columns', ''))), + $directoryColumnNames, + )); + $visibleDirectoryColumns = request()->has('columns') ? $requestedDirectoryColumns : $directoryColumnNames; + $directoryQueryFormId = 'directory-query-form-' . ($page['slug'] ?? 'page'); + @endphp + @if ($directoryUsesFieldQuery) +
+
+ 查询条件 + 类型较少的字段直接选择,内容较多的字段支持关键词搜索 +
+
+ @if (request()->has('columns')) + + @endif + @foreach ($directoryQueryFields as $field) + @php $kind = $field['kind'] ?? 'text'; @endphp + @continue($kind === 'secret' && $field['name'] !== 'withdrawal_account') + @continue(($page['slug'] ?? '') === 'store-accounts' && in_array($field['name'], [ + 'account', + 'password_configured', + 'bound_phone', + 'verification_contact', + 'account_group_name', + 'created_at', + 'updated_at', + ], true)) + + @endforeach +
+
+ 勾选字段 +
+ 勾选需要显示的表头,可重复调整。 + @foreach ($directoryFields as $field) + + @endforeach +
+
+ + +
+ 导出 Excel +
+ 默认全选,可取消不需要导出的表头。 + @foreach ($directoryFields as $field) + + @endforeach + +
+
+
+
+ @endif @if (($page['slug'] ?? '') === 'store-report')
@php @@ -484,6 +746,7 @@
@endif + @if (!in_array(($section['slug'] ?? '') . '/' . ($page['slug'] ?? ''), ['company-management/basic-information', 'store-management/basic-information', 'trademark-management/information', 'store-management/store-accounts'], true))
@@ -508,13 +771,28 @@
+ @endif
- +
@foreach ($directoryFields as $field) - + @endforeach @@ -544,7 +822,7 @@ $display = in_array($value, [true, 1, '1', '是', '✔'], true) ? '是' : '否'; } @endphp -
#{{ $field['label'] }} + @if ($directoryUsesFieldQuery) + @php + $isSorted = request('sort') === $field['name']; + $direction = $isSorted ? request('direction', 'asc') : null; + $nextDirection = $isSorted && $direction === 'asc' ? 'desc' : 'asc'; + @endphp + + {{ $field['label'] }} + + + @else + {{ $field['label'] }} + @endif +
+ @if (($page['slug'] ?? '') === 'store-accounts' && $field['name'] === 'password_configured') {{ filled($display) ? $display : '—' }} @if ($value === false) @@ -620,6 +898,126 @@