[FIX] 修復商品多語系儲存與讀取錯誤、新增自動語系名稱顯示、補強商品規格欄位及密碼顯示切換功能
All checks were successful
star-cloud-deploy-demo / deploy-demo (push) Successful in 47s

This commit is contained in:
2026-03-30 17:11:15 +08:00
parent 9bbfaa39e6
commit d14eda7d69
9 changed files with 167 additions and 40 deletions

View File

@@ -86,7 +86,14 @@ class ProductController extends Controller
public function edit($id)
{
$user = auth()->user();
$product = Product::with(['translations', 'company'])->findOrFail($id);
// 繞過 TenantScoped 載入翻譯,確保系統管理員能看到租戶公司的翻譯資料
$product = Product::with(['company'])->findOrFail($id);
$product->setRelation('translations',
Translation::withoutGlobalScopes()
->where('group', 'product')
->where('key', $product->name_dictionary_key)
->get()
);
$categories = ProductCategory::all();
$companies = $user->isSystemAdmin() ? Company::all() : collect();
@@ -131,10 +138,10 @@ class ProductController extends Controller
? $request->company_id
: auth()->user()->company_id;
// Store translations
// 儲存多語系翻譯(繞過 TenantScoped避免系統管理員操作租戶資料時被過濾
foreach ($request->names as $locale => $name) {
if (empty($name)) continue;
Translation::create([
Translation::withoutGlobalScopes()->create([
'group' => 'product',
'key' => $dictKey,
'locale' => $locale,
@@ -219,10 +226,10 @@ class ProductController extends Controller
$dictKey = $product->name_dictionary_key ?: \Illuminate\Support\Str::uuid()->toString();
$company_id = $product->company_id;
// Update or Create translations
// 更新或建立多語系翻譯(繞過 TenantScoped避免系統管理員操作租戶資料時被過濾
foreach ($request->names as $locale => $name) {
if (empty($name)) {
Translation::where([
Translation::withoutGlobalScopes()->where([
'group' => 'product',
'key' => $dictKey,
'locale' => $locale
@@ -230,7 +237,7 @@ class ProductController extends Controller
continue;
}
Translation::updateOrCreate(
Translation::withoutGlobalScopes()->updateOrCreate(
[
'group' => 'product',
'key' => $dictKey,
@@ -246,6 +253,7 @@ class ProductController extends Controller
$data = [
'category_id' => $request->category_id,
'name' => $request->names['zh_TW'] ?? ($product->name ?? 'Untitled'),
'name_dictionary_key' => $dictKey,
'barcode' => $request->barcode,
'spec' => $request->spec,
'manufacturer' => $request->manufacturer,
@@ -316,9 +324,9 @@ class ProductController extends Controller
try {
$product = Product::findOrFail($id);
// Delete translations associated with this product
// 刪除與此商品關聯的翻譯資料(繞過 TenantScoped
if ($product->name_dictionary_key) {
Translation::where('key', $product->name_dictionary_key)->delete();
Translation::withoutGlobalScopes()->where('key', $product->name_dictionary_key)->delete();
}
// Delete image

View File

@@ -48,6 +48,33 @@ class Product extends Model
return $this->belongsTo(ProductCategory::class, 'category_id');
}
/**
* 自動附加到 JSON/陣列輸出的屬性(供 Alpine.js 等前端使用)
*/
protected $appends = ['localized_name'];
/**
* 取得當前語系的商品名稱。
* 回退順序:當前語系 zh_TW name 欄位
*/
public function getLocalizedNameAttribute(): string
{
if ($this->relationLoaded('translations') && $this->translations->isNotEmpty()) {
$locale = app()->getLocale();
// 先找當前語系
$translation = $this->translations->firstWhere('locale', $locale);
if ($translation) {
return $translation->value;
}
// 回退至 zh_TW
$fallback = $this->translations->firstWhere('locale', 'zh_TW');
if ($fallback) {
return $fallback->value;
}
}
return $this->name ?? '';
}
/**
* Get the translations for the product name.
*/