diff --git a/app/Http/Controllers/Admin/SiteSubscriptionController.php b/app/Http/Controllers/Admin/SiteSubscriptionController.php
index a8d6baf..2d15a06 100644
--- a/app/Http/Controllers/Admin/SiteSubscriptionController.php
+++ b/app/Http/Controllers/Admin/SiteSubscriptionController.php
@@ -226,6 +226,8 @@ class SiteSubscriptionController extends Controller
'merchant_id' => trim((string) $request->query('merchant_id', '')),
'plan_id' => trim((string) $request->query('plan_id', '')),
'expiry' => trim((string) $request->query('expiry', '')),
+ 'ends_from' => trim((string) $request->query('ends_from', '')),
+ 'ends_to' => trim((string) $request->query('ends_to', '')),
];
$query = $this->applyFilters(
@@ -474,31 +476,56 @@ class SiteSubscriptionController extends Controller
protected function applyFilters(Builder $query, array $filters): Builder
{
+ // 说明:该方法既会用于普通列表查询(无 join),也会用于「到期提醒 Top10」统计(有 join merchants/plans)。
+ // 为避免在 SQLite 下出现 "ambiguous column name",这里统一对 site_subscriptions 的字段加上表前缀。
+ $t = 'site_subscriptions';
+
return $query
- ->when($filters['status'] !== '', fn (Builder $builder) => $builder->where('status', $filters['status']))
- ->when(($filters['merchant_id'] ?? '') !== '', fn (Builder $builder) => $builder->where('merchant_id', (int) $filters['merchant_id']))
- ->when(($filters['plan_id'] ?? '') !== '', fn (Builder $builder) => $builder->where('plan_id', (int) $filters['plan_id']))
- ->when(($filters['expiry'] ?? '') !== '', function (Builder $builder) use ($filters) {
+ ->when($filters['status'] !== '', fn (Builder $builder) => $builder->where($t . '.status', $filters['status']))
+ ->when(($filters['merchant_id'] ?? '') !== '', fn (Builder $builder) => $builder->where($t . '.merchant_id', (int) $filters['merchant_id']))
+ ->when(($filters['plan_id'] ?? '') !== '', fn (Builder $builder) => $builder->where($t . '.plan_id', (int) $filters['plan_id']))
+ ->when(($filters['expiry'] ?? '') !== '', function (Builder $builder) use ($filters, $t) {
$expiry = (string) ($filters['expiry'] ?? '');
if ($expiry === 'expired') {
- $builder->whereNotNull('ends_at')->where('ends_at', '<', now());
+ $builder->whereNotNull($t . '.ends_at')->where($t . '.ends_at', '<', now());
} elseif ($expiry === 'expiring_7d') {
- $builder->whereNotNull('ends_at')
- ->where('ends_at', '>=', now())
- ->where('ends_at', '<', now()->addDays(7));
+ $builder->whereNotNull($t . '.ends_at')
+ ->where($t . '.ends_at', '>=', now())
+ ->where($t . '.ends_at', '<', now()->addDays(7));
}
})
- ->when($filters['keyword'] !== '', function (Builder $builder) use ($filters) {
+ ->when(($filters['ends_from'] ?? '') !== '' || ($filters['ends_to'] ?? '') !== '', function (Builder $builder) use ($filters, $t) {
+ // 到期时间范围筛选:用于运营按 ends_at 精确定位
+ // 容错:仅接受 YYYY-MM-DD
+ $from = trim((string) ($filters['ends_from'] ?? ''));
+ $to = trim((string) ($filters['ends_to'] ?? ''));
+
+ if ($from !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $from)) {
+ $from = '';
+ }
+ if ($to !== '' && !preg_match('/^\d{4}-\d{2}-\d{2}$/', $to)) {
+ $to = '';
+ }
+
+ if ($from !== '' && $to !== '') {
+ $builder->whereBetween($t . '.ends_at', [$from . ' 00:00:00', $to . ' 23:59:59']);
+ } elseif ($from !== '') {
+ $builder->where($t . '.ends_at', '>=', $from . ' 00:00:00');
+ } elseif ($to !== '') {
+ $builder->where($t . '.ends_at', '<=', $to . ' 23:59:59');
+ }
+ })
+ ->when($filters['keyword'] !== '', function (Builder $builder) use ($filters, $t) {
// 关键词搜索:订阅号 / 站点 / 套餐 / 计费周期
$keyword = trim((string) ($filters['keyword'] ?? ''));
if ($keyword === '') {
return;
}
- $builder->where(function (Builder $q) use ($keyword) {
- $q->where('subscription_no', 'like', '%' . $keyword . '%')
- ->orWhere('plan_name', 'like', '%' . $keyword . '%')
- ->orWhere('billing_cycle', 'like', '%' . $keyword . '%')
+ $builder->where(function (Builder $q) use ($keyword, $t) {
+ $q->where($t . '.subscription_no', 'like', '%' . $keyword . '%')
+ ->orWhere($t . '.plan_name', 'like', '%' . $keyword . '%')
+ ->orWhere($t . '.billing_cycle', 'like', '%' . $keyword . '%')
->orWhereHas('merchant', function (Builder $mq) use ($keyword) {
$mq->where('name', 'like', '%' . $keyword . '%')
->orWhere('slug', 'like', '%' . $keyword . '%');
@@ -509,7 +536,7 @@ class SiteSubscriptionController extends Controller
});
if (ctype_digit($keyword)) {
- $q->orWhere('id', (int) $keyword);
+ $q->orWhere($t . '.id', (int) $keyword);
}
});
});
diff --git a/resources/views/admin/site_subscriptions/index.blade.php b/resources/views/admin/site_subscriptions/index.blade.php
index ef10718..c991cec 100644
--- a/resources/views/admin/site_subscriptions/index.blade.php
+++ b/resources/views/admin/site_subscriptions/index.blade.php
@@ -272,6 +272,8 @@
+
+