[FIX] 徹底修復商品管理分頁參數洩漏與 UI 狀態不一致問題
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 59s

1. 隔離商品列表與分類管理的搜尋參數(product_search / category_search)。
2. 隔離商品列表與分類管理的公司篩選參數(product_company_id / category_company_id)。
3. 優化分頁切換邏輯,切換 Tab 時自動清理 URL 參數,解決標籤殘留問題。
4. 修復 searchable-select 組件因屬性傳遞錯誤導致的 500 Internal Server Error。
5. 統一各分頁「公司篩選」Placeholder 為「所有公司」。
6. 完成分類管理搜尋框的多語系支援(新增 Search categories... 翻譯鍵值)。
7. 優化分頁器 (Pagination) 樣式以符合極簡奢華風規範。
This commit is contained in:
2026-04-15 16:45:13 +08:00
parent 24553d9b73
commit 1301bf1cb8
10 changed files with 670 additions and 247 deletions

View File

@@ -19,12 +19,16 @@ class ProductController extends Controller
public function index(Request $request)
{
$user = auth()->user();
$query = Product::with(['category.translations', 'translations', 'company']);
$tab = $request->input('tab', 'products');
$per_page = $request->input('per_page', 10);
// Products Query
$productQuery = Product::with(['category.translations', 'translations', 'company']);
// 搜尋
if ($request->filled('search')) {
$search = $request->search;
$query->where(function($q) use ($search) {
if ($request->filled('product_search')) {
$search = $request->product_search;
$productQuery->where(function($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('barcode', 'like', "%{$search}%")
->orWhere('spec', 'like', "%{$search}%");
@@ -33,29 +37,66 @@ class ProductController extends Controller
// 分類篩選
if ($request->filled('category_id')) {
$query->where('category_id', $request->category_id);
$productQuery->where('category_id', $request->category_id);
}
$per_page = $request->input('per_page', 10);
$companyId = $user->company_id;
if ($user->isSystemAdmin()) {
if ($request->filled('company_id')) {
$companyId = $request->company_id;
$query->where('company_id', $companyId);
if ($request->filled('product_company_id')) {
$productQuery->where('company_id', $request->product_company_id);
}
}
$products = $query->latest()->paginate($per_page)->withQueryString();
$categories = ProductCategory::with('translations')->get();
$products = $productQuery->latest()->paginate($per_page, ['*'], 'product_page')->withQueryString();
// Categories Query
$categoryQuery = ProductCategory::with(['translations', 'company']);
if ($user->isSystemAdmin() && $request->filled('category_company_id')) {
$categoryQuery->where('company_id', $request->category_company_id);
}
if ($request->filled('category_search')) {
$search = $request->category_search;
$categoryQuery->where(function($q) use ($search) {
$q->where('name', 'like', "%{$search}%");
});
}
$categories = $categoryQuery->latest()->paginate($per_page, ['*'], 'category_page')->withQueryString();
$companies = $user->isSystemAdmin() ? Company::all() : collect();
// 系統管理員在過濾特定公司時,應顯示該公司的功能開關 (如物料代碼、點數規則)
$selectedCompany = $companyId ? Company::find($companyId) : $user->company;
// Settings for Modal (use current user company or fallback)
$selectedCompanyId = $user->isSystemAdmin()
? ($request->input('product_company_id') ?: $request->input('category_company_id'))
: $user->company_id;
$selectedCompany = $selectedCompanyId ? Company::find($selectedCompanyId) : $user->company;
$companySettings = $selectedCompany ? ($selectedCompany->settings ?? []) : [];
$routeName = 'admin.data-config.products.index';
if ($request->ajax() || $request->wantsJson()) {
if ($tab === 'products') {
return response()->json([
'success' => true,
'html' => view('admin.products.partials.tab-products', [
'products' => $products,
'companySettings' => $companySettings,
'companies' => $companies,
'routeName' => $routeName
])->render()
]);
} else {
return response()->json([
'success' => true,
'html' => view('admin.products.partials.tab-categories', [
'categories' => $categories,
'companies' => $companies,
'routeName' => $routeName
])->render()
]);
}
}
return view('admin.products.index', [
'products' => $products,
'categories' => $categories,
@@ -313,8 +354,23 @@ class ProductController extends Controller
$product->save();
$status = $product->is_active ? __('Enabled') : __('Disabled');
if (request()->ajax()) {
return response()->json([
'success' => true,
'message' => __('Product status updated to :status', ['status' => $status]),
'is_active' => $product->is_active
]);
}
return redirect()->back()->with('success', __('Product status updated to :status', ['status' => $status]));
} catch (\Exception $e) {
if (request()->ajax()) {
return response()->json([
'success' => false,
'message' => $e->getMessage()
], 500);
}
return redirect()->back()->with('error', $e->getMessage());
}
}
@@ -337,8 +393,21 @@ class ProductController extends Controller
$product->delete();
if (request()->ajax()) {
return response()->json([
'success' => true,
'message' => __('Product deleted successfully')
]);
}
return redirect()->back()->with('success', __('Product deleted successfully'));
} catch (\Exception $e) {
if (request()->ajax()) {
return response()->json([
'success' => false,
'message' => $e->getMessage()
], 500);
}
return redirect()->back()->with('error', $e->getMessage());
}
}