[FIX] 徹底修復商品管理分頁參數洩漏與 UI 狀態不一致問題
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 59s
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:
@@ -150,7 +150,11 @@ class ProductCategoryController extends Controller
|
||||
|
||||
// 檢查是否已有商品使用此分類
|
||||
if ($category->products()->count() > 0) {
|
||||
return redirect()->back()->with('error', __('Cannot delete category that has products. Please move products first.'));
|
||||
$errorMsg = __('Cannot delete category that has products. Please move products first.');
|
||||
if (request()->ajax()) {
|
||||
return response()->json(['success' => false, 'message' => $errorMsg], 422);
|
||||
}
|
||||
return redirect()->back()->with('error', $errorMsg);
|
||||
}
|
||||
|
||||
if ($category->name_dictionary_key) {
|
||||
@@ -159,8 +163,18 @@ class ProductCategoryController extends Controller
|
||||
|
||||
$category->delete();
|
||||
|
||||
if (request()->ajax()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => __('Category deleted successfully')
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', __('Category deleted successfully'));
|
||||
} catch (\Exception $e) {
|
||||
if (request()->ajax()) {
|
||||
return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
|
||||
}
|
||||
return redirect()->back()->with('error', $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user