SpecService.php 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. <?php
  2. namespace App\Modules\Admin\Services;
  3. use App\Base\BaseService;
  4. use App\Exceptions\ClientException;
  5. use App\Models\Goods\Spec;
  6. use App\Models\Goods\SpecAttr;
  7. use Illuminate\Database\Eloquent\Builder;
  8. use Illuminate\Support\Arr;
  9. use Illuminate\Support\Facades\DB;
  10. use Nerd\CartesianProduct\CartesianProduct;
  11. class SpecService extends BaseService
  12. {
  13. public function paginate($params)
  14. {
  15. $p = Spec::query()->when($params['name'], function (Builder $query) use ($params) {
  16. return $query->where("name", 'like', "%{$params['name']}%");
  17. })->orderByDesc("id")->paginate($params['page_size']);
  18. return [
  19. "total" => $p->total(),
  20. "page_total" => $p->lastPage(),
  21. "list" => array_map(function (Spec $u) {
  22. return $u->format(Spec::FORMAT_ATTR);
  23. }, $p->items()),
  24. ];
  25. }
  26. public function specStore($params)
  27. {
  28. $id = $params['id'] ?? 0;
  29. if ($id) {
  30. $spec = Spec::find($id);
  31. } else {
  32. $spec = new Spec();
  33. }
  34. $spec->name = Arr::get($params, 'name');
  35. $spec->en_name = Arr::get($params, 'en_name');
  36. $spec->index_weight = Arr::get($params, 'index_weight');
  37. $spec->category_weight = Arr::get($params, 'category_weight');
  38. $spec->search_weight = Arr::get($params, 'search_weight');
  39. $spec->is_custom = (int)Arr::get($params, 'is_custom');
  40. DB::transaction(function () use ($params, $spec) {
  41. $spec->save();
  42. $attr = Arr::get($params, "attr", []);
  43. $holdIdArr = Arr::pluck($attr, "id");
  44. SpecAttr::query()->where("spec_id", $spec->id)->whereNotIn("id", $holdIdArr)->delete();
  45. foreach ($attr as $k => $v) {
  46. $id = Arr::get($v, "id");
  47. if ($id) {
  48. $m = SpecAttr::whereSpecId($spec->id)->find($id);
  49. if (is_null($m)) {
  50. logger()->error("无法保存这个属性值:" . $v['name'] ?? "");
  51. throw new ClientException("无法保存这个属性值:" . $v['name'] ?? "");
  52. }
  53. } else {
  54. $m = new SpecAttr();
  55. }
  56. $m->spec_id = $spec->id;
  57. $m->name = $v['name'] ?? "";
  58. $m->save();
  59. }
  60. });
  61. return true;
  62. }
  63. public function specInfo($data)
  64. {
  65. $id = $data['id'];
  66. $spec = Spec::findOrFail($id);
  67. return $spec->format(Spec::FORMAT_ATTR);
  68. }
  69. public function specDelete($data)
  70. {
  71. $id = $data['id'] ?? 0;
  72. // @TODO kphcdr 判断是否有商品还在使用这个规则,否则无法删除
  73. $spec = Spec::find($id);
  74. if ($spec) {
  75. SpecAttr::where("spec_id", $spec->id)->delete();
  76. $spec->delete();
  77. }
  78. return true;
  79. }
  80. /**
  81. * 生成笛卡尔积表格
  82. *
  83. * @param array $specIdArr
  84. */
  85. public function cartesian(array $specIdArr)
  86. {
  87. $specS = Spec::with("attrs")->whereIn("id", $specIdArr)->where("is_custom", 0)->get();
  88. if ($specS->isEmpty()) {
  89. return [];
  90. }
  91. $attrS = collect();
  92. $cartesianProduct = new CartesianProduct();
  93. foreach ($specS as $spec) {
  94. /** @var Spec $spec */
  95. $cartesianProduct->appendSet($spec->attrs->pluck("name")->toArray());
  96. $attrS = $attrS->merge($spec->attrs);
  97. }
  98. $cartesian = $cartesianProduct->compute();
  99. foreach ($cartesian as $c) {
  100. if (is_array($c)) {
  101. $specAttr = array_map(function ($cname) use ($attrS) {
  102. /** @var SpecAttr $attr */
  103. $attr = $attrS->where("name", $cname)->first();
  104. return [
  105. "id" => $attr->id,
  106. "name" => $cname,
  107. "spec_name" => optional($attr->spec)->name,
  108. ];
  109. }, $c);
  110. } else {
  111. /** @var SpecAttr $attr */
  112. $attr = $attrS->where("name", $c)->first();
  113. $specAttr = [[
  114. "id" => $attr->id,
  115. "name" => $c,
  116. "spec_name" => optional($attr->spec)->name,
  117. ]];
  118. }
  119. $return[] = [
  120. "id" => 0,
  121. "sn" => "",
  122. "url_3d" => "",
  123. "is_use" => 1,
  124. "spec_attr" => $specAttr,
  125. ];
  126. }
  127. return $return;
  128. }
  129. }