diff --git a/modules/EcommerceFinance/Http/Controllers/AccountBills.php b/modules/EcommerceFinance/Http/Controllers/AccountBills.php index 88c0a39f..e6443489 100644 --- a/modules/EcommerceFinance/Http/Controllers/AccountBills.php +++ b/modules/EcommerceFinance/Http/Controllers/AccountBills.php @@ -176,9 +176,14 @@ class AccountBills extends Controller if (! is_array($requested)) { $requested = []; } + if ($requested !== []) { + $requested = collect($requested)->unique()->values(); + $invalid = $requested->reject(fn (string $field): bool => $available->has($field)); + abort_if($invalid->isNotEmpty(), 422, '包含不可导出的字段:' . $invalid->implode('、')); + } $columns = $requested === [] ? $available->values() - : collect($requested)->unique()->map(fn (string $field) => $available->get($field))->filter()->values(); + : $requested->map(fn (string $field) => $available->get($field))->values(); abort_if($columns->isEmpty(), 422, '至少选择一个可导出的字段。'); @@ -311,10 +316,9 @@ class AccountBills extends Controller $selected = $columns; } else { $columnsByField = $columns->keyBy('field'); - $selected = $requested - ->map(static fn (string $field) => $columnsByField->get($field)) - ->filter(static fn ($column): bool => is_array($column)) - ->values(); + $invalid = $requested->reject(static fn (string $field): bool => $columnsByField->has($field)); + abort_if($invalid->isNotEmpty(), 422, '包含不可导出的字段:' . $invalid->implode('、')); + $selected = $requested->map(static fn (string $field) => $columnsByField->get($field))->values(); abort_if($selected->isEmpty(), 422, '未选择有效的导出字段。'); } diff --git a/resources/assets/js/components/business/AccountBills.vue b/resources/assets/js/components/business/AccountBills.vue index 9d04b62a..60ae74b1 100644 --- a/resources/assets/js/components/business/AccountBills.vue +++ b/resources/assets/js/components/business/AccountBills.vue @@ -81,7 +81,9 @@ export default { data(){return{loading:false,loadError:false,sync:null,rows:[],sourceColumns:[],configuredColumns:[],columnsTitle:'',sourceGroups:[],summary:{income:0,expense:0,balance:0,count:0},total:0,currentPage:1,lastPage:1,perPage:20,filters:emptyFilters(this.billType),queryFilters:emptyFilters(this.billType),resultFilters:null,filterOptions:{shops:[],bill_items:[]},filterOptionsLoading:false,filterOptionsError:false,requestSerial:0,sort:{key:'occurred_at',dir:'desc'},exportMode:'filtered-visible'};}, computed:{ isDouyin(){return this.billType==='douyin';}, - usesStableDateControl(){return ['pinduoduo','dewu'].indexOf(this.billType)!==-1;}, + // Every account-bill tab uses the same explicit picker path. Keeping one + // control avoids browser-native date inputs appearing on older tabs. + usesStableDateControl(){return true;}, usesMirrorOptions(){return ['douyin','pinduoduo','dewu','jd-transactions','jd-wallet'].indexOf(this.billType)!==-1;}, invalidDateRange(){return Boolean(this.filters.start&&this.filters.end&&this.filters.start>this.filters.end);}, startDateConfig(){return {...dateConfig,maxDate:this.filters.end||null};}, diff --git a/tests/scripts/account-bills-filter-export.test.cjs b/tests/scripts/account-bills-filter-export.test.cjs index 8d077527..9e5adf02 100644 --- a/tests/scripts/account-bills-filter-export.test.cjs +++ b/tests/scripts/account-bills-filter-export.test.cjs @@ -122,13 +122,13 @@ test('calendar selection submits both bounds, resets pagination and preserves da assert.equal(opened, true); }); -test('authoritative pinduoduo and dewu pages enable the stable full-control date picker treatment', () => { +test('all account-bill pages enable the stable full-control date picker treatment', () => { const { instance: pinduoduo } = component(async () => response(), 'pinduoduo'); const { instance: dewu } = component(async () => response(), 'dewu'); const { instance: douyin } = component(async () => response(), 'douyin'); assert.equal(pinduoduo.usesStableDateControl, true); assert.equal(dewu.usesStableDateControl, true); - assert.equal(douyin.usesStableDateControl, false); + assert.equal(douyin.usesStableDateControl, true); assert.match(sfc.template.content, /is-stable-date/); assert.match(source, /\.tw-date\.is-stable-date \.tw-date-control/); });