ProductModel.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. <?php
  2. namespace App\Web\Models;
  3. use App\Models\BaseModel;
  4. use Illuminate\Support\Facades\DB;
  5. use Illuminate\Support\Facades\Log;
  6. class ProductModel extends BaseModel
  7. {
  8. /**
  9. * 状态字段
  10. */
  11. const DELETED_AT = 'status';
  12. /**
  13. * @var string
  14. */
  15. protected $table = 'product';
  16. /**
  17. * 获取产品列表
  18. * */
  19. public function getProductList($params,$fields='a.*'){
  20. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  21. $where=[];
  22. if(isset($params['status'])){
  23. $where[]=['a.status','=',$params['status']];
  24. }else{
  25. $where[]=['a.status','<',2];
  26. }
  27. if(!empty($params['lt_total_view'])){
  28. $where[]=['a.total_view','<',$params['lt_total_view']];
  29. }
  30. $query= $this->newInstance()->alias('a')->where($where);
  31. if (!empty($params['keyword'])) {
  32. $keyword = $params['keyword'];
  33. $query->where('a.title', 'like', "%" . $keyword . "%");
  34. }
  35. if(!empty($params['sort'])){
  36. if($params['sort']=='score_ascending'){
  37. $query->orderBy('score','asc');
  38. }else if($params['sort']=='score_descending'){
  39. $query->orderBy('score','desc');
  40. }else if($params['sort']=='pub_date_ascending'){
  41. $query->orderBy('pub_date','asc');
  42. }else if($params['sort']=='pub_date_descending'){
  43. $query->orderBy('pub_date','desc');
  44. }else if($params['sort']=='create_time_ascending'){
  45. $query->orderBy('create_time','asc');
  46. }else if($params['sort']=='create_time_descending'){
  47. $query->orderBy('create_time','desc');
  48. }else if($params['sort']=='update_time_ascending'){
  49. $query->orderBy('update_time','asc');
  50. }else if($params['sort']=='update_time_descending'){
  51. $query->orderBy('update_time','desc');
  52. }
  53. }else{
  54. $query->orderBy('is_top','desc')
  55. ->orderBy('sort');
  56. }
  57. $totalCount = $query->count();
  58. $list= $query->skip($skip)
  59. ->limit($pageSize)
  60. ->selectRaw($fields)
  61. ->get();
  62. if(!empty($list)){
  63. $list=$list->toArray();
  64. }else{
  65. $list=[];
  66. }
  67. $result = $this->buildPaginator($list, $skip, $page, $pageSize, $totalCount);
  68. return $result;
  69. }
  70. /**
  71. * 获取产品分类未关联的产品
  72. * */
  73. public function getUnrelatedProductByTypeIds($params){
  74. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  75. $typeId = $params['type_id'] ?? '';
  76. $keyword = $params['keyword'] ?? '';
  77. $where=[];
  78. if ($keyword) {
  79. $keyword = addslashes($keyword);
  80. $where['_string'] = "((a.`title` like '%{$keyword}%' or a.`description` like '%{$keyword}%'))";
  81. }
  82. $totalCount= $this->newInstance()->buildQuery($where) ->from($this->getTable().' as a')
  83. ->leftJoin('product_type_relation as b', function ($join)use($typeId) {
  84. $join->on('a.id', '=', 'b.product_id')
  85. ->where('b.status', '=', 0)
  86. ->where('b.type_id', '=', $typeId);
  87. })->where('a.status','<',2)->whereNull('b.id')->count();
  88. $fields='a.id,a.title,a.pub_date,a.image_url,a.description,a.status,a.update_time,a.create_time';
  89. $list= $this->newInstance()->buildQuery($where) ->from($this->getTable().' as a')
  90. ->leftJoin('product_type_relation as b', function ($join)use($typeId) {
  91. $join->on('a.id', '=', 'b.product_id')
  92. ->where('b.status', '=', 0)
  93. ->where('b.type_id', '=', $typeId);
  94. })->where('a.status','<',2)->whereNull('b.id')->skip($skip)
  95. ->limit($pageSize)
  96. ->selectRaw($fields)
  97. ->orderBy('sort')
  98. ->get();
  99. if(!empty($list)){
  100. $list=$list->toArray();
  101. }else{
  102. $list=[];
  103. }
  104. $result = $this->buildPaginator($list, $skip, $page, $pageSize, $totalCount);
  105. return $result;
  106. }
  107. /**
  108. * 后台根据类型id 获取产品列表
  109. * */
  110. public function getAdminProductData($params) {
  111. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  112. $typeId = $params['type_id'] ?? '';
  113. $where=[];
  114. $keyword='';
  115. if (!empty($params['keyword'])) {
  116. $keyword = $params['keyword'];
  117. $where[] = ['b.title', 'like', "%" . $keyword . "%"];
  118. }
  119. if(isset($params['status'])) {
  120. $where[]=['b.status','=',$params['status']];
  121. } else {
  122. $where[]=['b.status','<',2];
  123. }
  124. if(!empty($typeId)) {
  125. $where[]=['a.status','=',0];
  126. if(is_array($typeId)){
  127. $query= $this->newInstance()->alias('b')
  128. ->leftJoin('product_type_relation as a','a.product_id','=','b.id')
  129. ->leftJoin('web_seo as s', 's.id', '=', 'b.seo_id')
  130. ->where($where)
  131. ->whereIn('a.type_id',$typeId);
  132. } else {
  133. $where[]=['a.type_id','=',$typeId];
  134. $query= $this->newInstance()->alias('b')
  135. ->leftJoin('product_type_relation as a','a.product_id','=','b.id')
  136. ->leftJoin('web_seo as s', 's.id', '=', 'b.seo_id')
  137. ->where($where);
  138. }
  139. } else {
  140. $query= $this->newInstance()->alias('b')
  141. ->leftJoin('web_seo as s', 's.id', '=', 'b.seo_id')
  142. ->where($where);
  143. }
  144. $fields='b.id,b.title,b.pub_date,b.image_url,b.is_top,b.is_recommend,b.description,b.status,b.update_time,b.create_time,s.urla,s.seo_title,s.seo_keyword,s.seo_describe,s.trans_status';
  145. $list= $query->skip($skip)
  146. ->limit($pageSize)->groupBy('b.id')
  147. ->selectRaw($fields)
  148. ->orderBy('sort')->paginate($pageSize)->toArray();
  149. return $list;
  150. }
  151. public function getProductByTypeIds($params){
  152. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  153. $typeId = $params['type_id'] ?? '';
  154. $where=[];
  155. $keyword='';
  156. if (!empty($params['keyword'])) {
  157. $keyword = $params['keyword'];
  158. $where[] = ['b.title', 'like', "%" . $keyword . "%"];
  159. }
  160. if(isset($params['status'])){
  161. $where[]=['b.status','=',$params['status']];
  162. }else{
  163. $where[]=['b.status','<',2];
  164. }
  165. if(!empty($typeId)){
  166. $where[]=['a.status','=',0];
  167. if(is_array($typeId)){
  168. $query= $this->newInstance()->alias('b')
  169. ->leftJoin('product_type_relation as a','a.product_id','=','b.id')
  170. ->leftJoin('web_seo as s', 's.id', '=', 'b.seo_id')
  171. ->where($where)
  172. ->whereIn('a.type_id',$typeId);
  173. } else {
  174. $where[]=['a.type_id','=',$typeId];
  175. $query= $this->newInstance()->alias('b')
  176. ->leftJoin('product_type_relation as a','a.product_id','=','b.id')
  177. ->leftJoin('web_seo as s', 's.id', '=', 'b.seo_id')
  178. ->where($where);
  179. }
  180. } else {
  181. $query= $this->newInstance()->alias('b')
  182. ->leftJoin('web_seo as s', 's.id', '=', 'b.seo_id')
  183. ->where($where);
  184. }
  185. $fields='b.id,b.title,b.pub_date,b.image_url,b.description,b.status,b.update_time,b.create_time,s.urla,s.seo_title,s.seo_keyword,s.seo_describe';
  186. $totalCount = $query->count();
  187. $list= $query->skip($skip)
  188. ->limit($pageSize)
  189. ->groupBy('b.id')
  190. ->selectRaw($fields)
  191. ->orderBy('sort')
  192. ->get();
  193. if(!empty($list)){
  194. $list=$list->toArray();
  195. }else{
  196. $list=[];
  197. }
  198. $result = $this->buildPaginator($list, $skip, $page, $pageSize, $totalCount);
  199. return $result;
  200. }
  201. /**
  202. * 获取产品标签未关联的产品
  203. * */
  204. public function getUnrelatedProductByTagId($params) {
  205. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  206. $tagId = $params['tag_id'] ?? '';
  207. $keyword = $params['keyword'] ?? '';
  208. $excludeTagId = $params['exclude_tag_id'] ?? [];
  209. // 确保excludeTagId不包含当前tagId
  210. if (in_array($tagId, $excludeTagId)) {
  211. $excludeTagId = array_diff($excludeTagId, [$tagId]);
  212. }
  213. $where = [];
  214. if ($keyword) {
  215. $where[] = function($query) use ($keyword) {
  216. $query->where('a.title', 'like', "%{$keyword}%")
  217. ->orWhere('a.description', 'like', "%{$keyword}%");
  218. };
  219. }
  220. $fields = 'a.id,a.title,a.pub_date,a.image_url,a.description,a.status,a.update_time,a.create_time';
  221. // 子查询:查找关联了排除标签的产品ID
  222. $excludedProductIds = DB::table('product_tag_relation')
  223. ->whereIn('tag_id', $excludeTagId)
  224. ->where('status', 0)
  225. ->pluck('product_id')
  226. ->toArray();
  227. if (!empty($tagId)) {
  228. $query = $this->newInstance()->alias('a')
  229. ->leftJoin('product_tag_relation as b', 'a.id', '=', 'b.product_id')
  230. ->selectRaw($fields)
  231. ->where('b.status', '=', 0)
  232. ->where('a.status', '<', 2)
  233. ->where('b.tag_id', '=', $tagId)
  234. ->groupBy('a.id')
  235. ->whereNotIn('a.id', $excludedProductIds);
  236. } else {
  237. $query = $this->newInstance()->alias('a')
  238. ->selectRaw($fields)
  239. ->where('a.status', '<', 2)
  240. ->groupBy('a.id')
  241. ->whereNotIn('a.id', $excludedProductIds);
  242. }
  243. // 主查询:查找包含指定标签但不包含排除标签的产品
  244. if (!empty($where)) {
  245. $query->where($where);
  246. }
  247. $list = $query->paginate($pageSize, ['*'], 'page', $page)->toArray();
  248. return $list;
  249. }
  250. public function getUnrelatedProductByTagIds($params){
  251. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  252. $tagId = $params['tag_id'] ?? '';
  253. $keyword = $params['keyword'] ?? '';
  254. $excludeTagId = $params['exclude_tag_id'] ?? null; // 假设传入的过滤标签 ID 参数名
  255. $where=[];
  256. if ($keyword) {
  257. $keyword = addslashes($keyword);
  258. $where['_string'] = "((a.`title` like '%{$keyword}%' or a.`description` like '%{$keyword}%'))";
  259. }
  260. $totalCount= $this->newInstance()->buildQuery($where) ->from($this->getTable().' as a')
  261. ->leftJoin('product_tag_relation as b', function ($join)use($tagId,$excludeTagId) {
  262. $join->on('a.id', '=', 'b.product_id')
  263. ->where('b.status', '=', 0)
  264. ->where('b.tag_id', '=', $tagId)
  265. ->whereNotIn('a.tag_id', $excludeTagId);
  266. })->where('a.status','<',2)->whereNull('b.id')->count();
  267. $fields='a.id,a.title,a.pub_date,a.image_url,a.description,a.status,a.update_time,a.create_time';
  268. $list= $this->newInstance()->buildQuery($where) ->from($this->getTable().' as a')
  269. ->leftJoin('product_tag_relation as b', function ($join)use($tagId,$excludeTagId) {
  270. $join->on('a.id', '=', 'b.product_id')
  271. ->where('b.status', '=', 0)
  272. ->where('b.tag_id', '=', $tagId)
  273. ->whereNotIn('a.tag_id', $excludeTagId);
  274. })->where('a.status','<',2)->whereNull('b.id')->skip($skip)
  275. ->limit($pageSize)
  276. ->selectRaw($fields)
  277. ->orderBy('sort')
  278. ->get();
  279. if(!empty($list)){
  280. $list=$list->toArray();
  281. }else{
  282. $list=[];
  283. }
  284. $result = $this->buildPaginator($list, $skip, $page, $pageSize, $totalCount);
  285. return $result;
  286. }
  287. /**
  288. * 产品保存
  289. * @param array $data
  290. * */
  291. public function saveProductData($data){
  292. if (!empty($data['id'])) {
  293. $id = $data['id'];
  294. $this->newInstance()->where('id', $data['id'])->update($data);
  295. } else {
  296. $id = $this->newInstance()->insertGetId($data);
  297. }
  298. return $id;
  299. }
  300. /**
  301. * 检查 标签是否唯一
  302. * */
  303. public function checkNameUnique($name,$id=0){
  304. $where=[];
  305. if(!empty($id)){
  306. $where[]=['id', '<>', $id];
  307. }
  308. $where[]=['status', '<', 2];
  309. $where[]=['title', '=', trim($name)];
  310. return $this->checkFieldUnique('title',$where);
  311. }
  312. /**
  313. * 获取产品详情
  314. * @param array $params
  315. * */
  316. public function getProductInfo($params=[]){
  317. if(empty($params)){
  318. return [];
  319. }
  320. $where=[];
  321. $where[]=['status','<',2];
  322. if(!empty($params['id'])){
  323. $where['id']=$params['id'];
  324. }
  325. $info= $this->newInstance()->where($where)->first();
  326. if(!empty($info)){
  327. return $info->toArray();
  328. }else{
  329. return [];
  330. }
  331. }
  332. /**
  333. * 获取产品基本列表
  334. * */
  335. public function getPublishProductList($params,$fields='a.*'){
  336. $where=[];
  337. $where['a.status']=0;
  338. $query= $this->newInstance()->alias('a')
  339. ->leftJoin('web_seo as b', 'a.seo_id', '=', 'b.id')
  340. ->where($where);
  341. $pageSize = $this->getPageSize($params);
  342. if(!empty($params['sort'])) {
  343. $result = [];
  344. if (isset($params['sort']) && is_array($params['sort'])) {
  345. // 遍历sort数组中的每个元素
  346. foreach ($params['sort'] as $field) {
  347. // 为每个字段创建关联数组,值为1
  348. $result[$field] = 1;
  349. }
  350. $params['sort'] = $result;
  351. } else if (is_string($params['sort'])) {
  352. $params['sort'] = [$params['sort']=>1];
  353. }
  354. if(!empty($params['sort']['is_hot'])) {
  355. $query=$query->orderBy('a.total_view','desc');
  356. }
  357. if(!empty($params['sort']['is_top'])) {
  358. $query=$query->orderBy('a.is_top','desc');
  359. }
  360. if(!empty($params['sort']['is_recommend'])) {
  361. $query=$query->orderBy('a.is_recommend','desc');
  362. }
  363. if(!empty($params['sort']['pub_date'])) {
  364. $query=$query->orderBy('a.pub_date','desc');
  365. }
  366. if(!empty($params['sort']['update_time'])) {
  367. $query=$query->orderBy('a.update_time','desc');
  368. }
  369. if(!empty($params['sort']['create_time'])) {
  370. $query=$query->orderBy('a.create_time','desc');
  371. }
  372. } else {
  373. $query=$query->orderBy('a.sort');
  374. }
  375. if (!empty($params['keyword'])) {
  376. $keyword = $params['keyword'];
  377. $query=$query->where(function ($queryStr) use ($keyword) {
  378. $queryStr->where('a.title', 'like', "%" . $keyword . "%")
  379. ->orWhere('a.description', 'like', '%' . $keyword . '%');
  380. });
  381. }
  382. if(!empty($params['ids'])){
  383. $query->whereIn('a.id',$params['ids']);
  384. }
  385. if(!empty($params['is_paginate'])){
  386. $list= $query->selectRaw($fields)->paginate($pageSize)
  387. ->toArray();
  388. } else {
  389. $list= $query->limit($pageSize)->selectRaw($fields)->get();
  390. if(!empty($list)){
  391. $list=$list->toArray();
  392. }else{
  393. $list=[];
  394. }
  395. }
  396. return $list;
  397. }
  398. /**
  399. * 根据类型ids获取个类型产品
  400. * */
  401. public function getRenderListByTypeIds($typeIds,$params,$fields='a.*'){
  402. $where=[];
  403. $where['a.status']=0;
  404. $where['b.status']=0;
  405. $pageSize = $this->getPageSize($params);
  406. $sql = '';
  407. foreach ($typeIds as $item){
  408. $sqlStr= $this->newInstance()->alias('a')
  409. ->leftJoin('product_type_relation as b', 'a.id', '=', 'b.product_id')
  410. ->leftJoin('web_seo as c', 'a.seo_id', '=', 'c.id')
  411. ->where($where)
  412. ->where('b.type_id','=',DB::raw($item))
  413. ->orderBy('a.is_top','desc')
  414. ->orderBy('a.pub_date','desc')
  415. ->limit($pageSize)->selectRaw($fields);
  416. if (empty($sql)) {
  417. $sql = $sqlStr;
  418. } else {
  419. $sql->unionAll($sqlStr);
  420. }
  421. }
  422. $list=[];
  423. if(!empty($sql)){
  424. $list = $sql->get();
  425. if($list){
  426. $list=$list->toArray();
  427. }
  428. }
  429. return $list;
  430. }
  431. /**
  432. * 根据类型id获取产品
  433. * */
  434. public function getPublishProductListByTypeId($params,$fields='a.*'){
  435. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  436. $where=[];
  437. $where['a.status']=0;
  438. if(!empty($params['type_id'])){
  439. $where['b.type_id']= $params['type_id'];
  440. $where['b.status']=0;
  441. }
  442. $typeId = empty($params['type_id'])?0:$params['type_id'];
  443. $list = $this->newInstance()->alias('a')->selectRaw($fields)
  444. ->leftJoin('product_type_relation as b', 'a.id', '=', 'b.product_id')
  445. ->leftJoin('web_seo as c', 'a.seo_id', '=', 'c.id')
  446. ->where($where)
  447. ->groupBy('a.id')
  448. ->orderBy('a.is_top','desc')
  449. ->orderBy('a.pub_date','desc')
  450. ->paginate($pageSize)
  451. ->toArray();
  452. return $list;
  453. }
  454. /**
  455. * 根据标签id获取产品
  456. * */
  457. public function getPublishProductListByTagId($params,$fields='a.*'){
  458. list($pageSize, $page, $skip) = $this->getPaginatorParams($params);
  459. $where=[];
  460. $where['a.status']=0;
  461. if(!empty($params['tag_id'])){
  462. $where['b.tag_id']= $params['tag_id'];
  463. $where['b.status']=0;
  464. }
  465. $totalCount= $this->newInstance()->alias('a')
  466. ->leftJoin('product_tag_relation as b', 'a.id', '=', 'b.product_id')
  467. ->leftJoin('web_seo as c', 'a.seo_id', '=', 'c.id')
  468. ->where($where)->count();
  469. $list= $this->newInstance()->alias('a')
  470. ->leftJoin('product_tag_relation as b', 'a.id', '=', 'b.product_id')
  471. ->leftJoin('web_seo as c', 'a.seo_id', '=', 'c.id')
  472. ->where($where)
  473. ->orderBy('a.is_top','desc')
  474. ->orderBy('a.pub_date','desc')
  475. ->limit($pageSize)->selectRaw($fields)->get();
  476. if($list){
  477. $list=$list->toArray();
  478. }else{
  479. $list=[];
  480. }
  481. $result = $this->buildPaginator($list, $skip, $page, $pageSize, $totalCount);
  482. return $result;
  483. }
  484. /**
  485. * 根据类型ids获取标签产品
  486. * */
  487. public function getRenderListByTagIds($tagIds,$params,$fields='a.*'){
  488. $where=[];
  489. $where['a.status']=0;
  490. $where['b.status']=0;
  491. $pageSize = $this->getPageSize($params);
  492. $sql = '';
  493. foreach ($tagIds as $item){
  494. $sqlStr= $this->newInstance()->alias('a')
  495. ->leftJoin('product_tag_relation as b', 'a.id', '=', 'b.product_id')
  496. ->leftJoin('web_seo as c', 'a.seo_id', '=', 'c.id')
  497. ->where($where)
  498. ->where('b.tag_id','=',DB::raw($item))
  499. ->orderBy('a.is_top','desc')
  500. ->orderBy('a.pub_date','desc')
  501. ->limit($pageSize)->selectRaw($fields);
  502. if (empty($sql)) {
  503. $sql = $sqlStr;
  504. } else {
  505. $sql->unionAll($sqlStr);
  506. }
  507. }
  508. $list=[];
  509. if(!empty($sql)){
  510. $list = $sql->get();
  511. if($list){
  512. $list=$list->toArray();
  513. }
  514. }
  515. return $list;
  516. }
  517. public function updatePv($id){
  518. DB::update('update product set votes = 1');
  519. }
  520. /**
  521. * 根据id数组获取产品列表
  522. *
  523. * @param array $ids 产品 ID 数组
  524. * @return array 包含产品信息、类型和标签的数组
  525. */
  526. public function getProductByIds($ids){
  527. $list = $this->newInstance()
  528. ->alias('a')
  529. ->leftJoin('product_type_relation as b', 'a.id', '=', 'b.product_id')
  530. ->leftJoin('product_tag_relation as d', 'a.id', '=', 'd.product_id')
  531. ->whereIn('a.id', $ids)
  532. ->selectRaw("a.*, GROUP_CONCAT(b.type_id) as type_ids, GROUP_CONCAT(d.tag_id) as tag_ids")
  533. ->groupBy('a.id')
  534. ->get()
  535. ->toArray();
  536. foreach ($list as &$item) {
  537. if (isset($item['type_ids'])) {
  538. $item['type_ids'] = explode(',', $item['type_ids']);
  539. $item['type_ids'] = array_unique($item['type_ids']);
  540. }
  541. if (isset($item['tag_ids'])) {
  542. $item['tag_ids'] = explode(',', $item['tag_ids']);
  543. $item['tag_ids'] = array_unique($item['tag_ids']);
  544. }
  545. if (isset($item['spec'])) {
  546. $item['spec'] = json_decode($item['spec'], true);
  547. }
  548. }
  549. return $list;
  550. }
  551. }