Compare commits
1 Commits
main
...
feature/qi
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e6797a0b9 |
@ -1801,7 +1801,11 @@ class Pages extends Controller
|
||||
|
||||
$limit = min(max((int) setting('default.list_limit', 25), 10), 100);
|
||||
$page = max((int) $request->query('page', 1), 1);
|
||||
$hasFilters = collect($filters)->contains(static fn (string $value): bool => $value !== '');
|
||||
$hasFilters = $filters['date_from'] !== ''
|
||||
|| $filters['date_to'] !== ''
|
||||
|| $filters['shop_names'] !== []
|
||||
|| $filters['labels'] !== []
|
||||
|| $filters['keyword'] !== '';
|
||||
// 无筛选时复用缓存总数,避免每次翻页都在 233 万行上重跑 COUNT(*)。
|
||||
$total = $hasFilters
|
||||
? (clone $query)->count()
|
||||
@ -1826,19 +1830,39 @@ class Pages extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
/** @return array<string,string> */
|
||||
/** @return array{date_from:string,date_to:string,shop_names:list<string>,labels:list<string>,keyword:string} */
|
||||
private function jstOrderLabelFilters(Request $request): array
|
||||
{
|
||||
return [
|
||||
'date_from' => $this->dateFilter($request->query('date_from')),
|
||||
'date_to' => $this->dateFilter($request->query('date_to')),
|
||||
'shop_name' => mb_substr(trim((string) $request->query('shop_name')), 0, 191),
|
||||
'label' => mb_substr(trim((string) $request->query('label')), 0, 191),
|
||||
'shop_names' => $this->filterValues($request->query('shop_name'), 191),
|
||||
'labels' => $this->filterValues($request->query('label'), 191),
|
||||
'keyword' => mb_substr(trim((string) $request->query('keyword')), 0, 100),
|
||||
];
|
||||
}
|
||||
|
||||
/** @param array<string,string> $filters */
|
||||
/**
|
||||
* 多选筛选值归一化:兼容旧的单值参数(?shop_name=A)与新的数组参数(?shop_name[]=A&shop_name[]=B)。
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
private function filterValues(mixed $raw, int $maxLength, int $limit = 500): array
|
||||
{
|
||||
$list = is_array($raw) ? $raw : [$raw];
|
||||
$values = [];
|
||||
|
||||
foreach ($list as $value) {
|
||||
$value = mb_substr(trim((string) $value), 0, $maxLength);
|
||||
if ($value !== '' && ! in_array($value, $values, true)) {
|
||||
$values[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return array_slice($values, 0, $limit);
|
||||
}
|
||||
|
||||
/** @param array{date_from:string,date_to:string,shop_names:list<string>,labels:list<string>,keyword:string} $filters */
|
||||
private function jstOrderLabelQuery(array $filters): \Illuminate\Database\Eloquent\Builder
|
||||
{
|
||||
$query = \App\Models\Business\JstOrderLabel::query()->where('company_id', company_id());
|
||||
@ -1849,11 +1873,16 @@ class Pages extends Controller
|
||||
if ($filters['date_to'] !== '') {
|
||||
$query->where('ordered_at', '<', date('Y-m-d', strtotime($filters['date_to'] . ' +1 day')) . ' 00:00:00');
|
||||
}
|
||||
if ($filters['shop_name'] !== '') {
|
||||
$query->where('shop_name', $filters['shop_name']);
|
||||
if ($filters['shop_names'] !== []) {
|
||||
$query->whereIn('shop_name', $filters['shop_names']);
|
||||
}
|
||||
if ($filters['label'] !== '') {
|
||||
$query->where('label', 'like', '%' . str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $filters['label']) . '%');
|
||||
if ($filters['labels'] !== []) {
|
||||
// 多选标签按「任一命中」过滤,保持与单值时一致的包含匹配语义
|
||||
$query->where(function ($sub) use ($filters): void {
|
||||
foreach ($filters['labels'] as $label) {
|
||||
$sub->orWhere('label', 'like', '%' . str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $label) . '%');
|
||||
}
|
||||
});
|
||||
}
|
||||
if ($filters['keyword'] !== '') {
|
||||
$query->where('order_no', 'like', '%' . str_replace(['\\', '%', '_'], ['\\\\', '\\%', '\\_'], $filters['keyword']) . '%');
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
<div class="upstream-data-page upstream-data-page--spaced" data-jst-order-labels="true">
|
||||
@include('business.pages.partials.upstream-data-styles')
|
||||
@include('business.pages.partials.multi-select')
|
||||
|
||||
<style>
|
||||
.jst-order-labels-table {
|
||||
@ -75,23 +76,25 @@
|
||||
<button class="jst-order-labels-clear" type="button" data-jst-labels-clear="jst-label-date-to" title="清除结束日期" aria-label="清除结束日期">×</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="upstream-data-field">
|
||||
<label for="jst-label-shop">店铺名称</label>
|
||||
<select id="jst-label-shop" name="shop_name">
|
||||
<option value="">全部店铺</option>
|
||||
@foreach ($filterOptions['shops'] as $shop)
|
||||
<option value="{{ $shop }}" @selected(($filters['shop_name'] ?? '') === $shop)>{{ $shop }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="upstream-data-field cw-ms" id="jst-label-shop" data-name="shop_name" data-initial='@json($filters['shop_names'] ?? [])'>
|
||||
<span>店铺名称</span>
|
||||
<span class="cw-ms__box">
|
||||
<button type="button" class="cw-ms__btn" data-role="btn" aria-expanded="false">
|
||||
<span class="cw-ms__label">全部店铺</span><span class="cw-ms__caret">▾</span>
|
||||
</button>
|
||||
<span class="cw-ms__panel" data-role="panel" hidden></span>
|
||||
<span class="cw-ms__values" data-role="values"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="upstream-data-field">
|
||||
<label for="jst-label-label">标签</label>
|
||||
<select id="jst-label-label" name="label">
|
||||
<option value="">全部标签</option>
|
||||
@foreach ($filterOptions['labels'] as $label)
|
||||
<option value="{{ $label }}" @selected(($filters['label'] ?? '') === $label)>{{ $label }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<div class="upstream-data-field cw-ms" id="jst-label-label" data-name="label" data-initial='@json($filters['labels'] ?? [])'>
|
||||
<span>标签</span>
|
||||
<span class="cw-ms__box">
|
||||
<button type="button" class="cw-ms__btn" data-role="btn" aria-expanded="false">
|
||||
<span class="cw-ms__label">全部标签</span><span class="cw-ms__caret">▾</span>
|
||||
</button>
|
||||
<span class="cw-ms__panel" data-role="panel" hidden></span>
|
||||
<span class="cw-ms__values" data-role="values"></span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="upstream-data-field">
|
||||
<label for="jst-label-keyword">线上订单号</label>
|
||||
@ -209,5 +212,18 @@
|
||||
form.submit();
|
||||
});
|
||||
});
|
||||
|
||||
if (window.CaiWuMultiSelect) {
|
||||
window.CaiWuMultiSelect.create(document.getElementById('jst-label-shop'), {
|
||||
options: @json($filterOptions['shops'] ?? []),
|
||||
searchable: true,
|
||||
searchPlaceholder: '打字找店铺',
|
||||
});
|
||||
window.CaiWuMultiSelect.create(document.getElementById('jst-label-label'), {
|
||||
options: @json($filterOptions['labels'] ?? []),
|
||||
searchable: true,
|
||||
searchPlaceholder: '打字找标签',
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user