From 62532ca66ae14b945038e00287c2ca200fd4ca22 Mon Sep 17 00:00:00 2001 From: xucong <850806214@qq.com> Date: Wed, 7 May 2025 12:18:08 +0800 Subject: [PATCH] =?UTF-8?q?1.=E7=BC=BA=E5=A4=B1=E4=BF=A1=E6=81=AF=E6=8F=90?= =?UTF-8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/controller/GoodsController.php | 90 ++++++ app/api/logic/GoodsLogic.php | 401 +++++++++++++++++++++++++ app/api/model/Goods.php | 225 ++++++++++++++ app/common/model/goods/GoodsBrand.php | 13 + 4 files changed, 729 insertions(+) create mode 100644 app/api/controller/GoodsController.php create mode 100644 app/api/logic/GoodsLogic.php create mode 100644 app/api/model/Goods.php create mode 100644 app/common/model/goods/GoodsBrand.php diff --git a/app/api/controller/GoodsController.php b/app/api/controller/GoodsController.php new file mode 100644 index 0000000..8b4f891 --- /dev/null +++ b/app/api/controller/GoodsController.php @@ -0,0 +1,90 @@ +request->get(); + $goods_list = GoodsLogic::getGoodsList($this->user_id, $get, $this->page_no, $this->page_size); + $this->success('获取成功',$goods_list); + + } + + + /** + * note 商品详情 + * create_time 2020/10/20 11:12 + */ + public function getGoodsDetail(){ + $id = $this->request->get('id'); + $goods = GoodsLogic::getGoodsDetail($this->user_id,$id); + if($goods){ + $this->_success('获取成功',$goods); + } + $this->_error('商品不存在',[],0,0); + } + + /** + * note 首页好物优选 + * create_time 2020/10/21 19:04 + */ + public function getBestList() { + $goods_list = GoodsLogic::getBestList($this->page_no, $this->page_size); + $this->_success('获取成功', $goods_list); + + } + /** + * note 热销商品 + * create_time 2020/11/17 9:52 + */ + public function getHostList(){ + $goods_list = GoodsLogic::getHostList($this->page_no, $this->page_size); + $this->_success('获取成功', $goods_list); + } + + + /** + * note 获取搜索页数据 + * create_time 2020/10/22 16:01 + */ + public function getSearchPage(){ + $limit = $this->request->get('limit ',10); + $list = GoodsLogic::getSearchPage($this->user_id,$limit); + $this->_success('',$list); + } + /** + * note 清空搜索记录 + * create_time 2020/12/18 10:26 + */ + public function clearSearch(){ + $result = GoodsLogic::clearSearch($this->user_id); + if($result){ + $this->_success('清理成功',''); + } + $this->_error('清理失败',''); + + } +} \ No newline at end of file diff --git a/app/api/logic/GoodsLogic.php b/app/api/logic/GoodsLogic.php new file mode 100644 index 0000000..c33ebb0 --- /dev/null +++ b/app/api/logic/GoodsLogic.php @@ -0,0 +1,401 @@ +where('name', 'like', "%{$get['keyword']}%")->column('id'); + if ($band_ids) { + $where[] = function ($query) use($band_ids, $get) { + $query->where('brand_id', 'in', $band_ids)->whereOr('name', 'like', "%{$get['keyword']}%"); + }; + } else { + $where[] = [ 'name', 'like', "%{$get['keyword']}%" ]; + } + + //记录关键词 + if($user_id){ + self::recordKeyWord(trim($get['keyword']),$user_id); + } + + } + //销量排序 + if(isset($get['sales_sum']) && $get['sales_sum']){ + $order['sales_sum'] = $get['sales_sum']; + } + //价格排序 + if(isset($get['price']) && $get['price']){ + $order['min_price'] = $get['price']; + } + + $order['sort'] = 'desc'; + $order['id'] = 'desc'; + + $goods_count = $goods + ->where($where) + ->count(); + + $goods_list = $goods + ->where($where) + ->page($page,$size) + ->order($order) + ->field('id,name,image,min_price as price,market_price,sales_sum+virtual_sales_sum as sales_sum,sort') + ->select(); + + $more = is_more($goods_count,$page,$size); //是否有下一页 + + $data = [ + 'list' => $goods_list, + 'page_no' => $page, + 'page_size' => $size, + 'count' => $goods_count, + 'more' => $more + ]; + return $data; + + } + + //记录搜索关键词 + public static function recordKeyWord($keyword,$user_id){ + $record = Db::name('search_record')->where(['user_id'=>$user_id,'keyword'=>$keyword,'del'=>0])->find(); + + if($record){ + return Db::name('search_record')->where(['id'=>$record['id']])->update(['count'=>Db::raw('count+1'),'update_time'=>time()]); + } + return Db::name('search_record')->insert(['user_id'=>$user_id,'keyword'=>$keyword]); + } + //商品详情 + public static function getGoodsDetail($user_id,$id){ + + $goods = Goods::get(['id'=>$id,'status'=>1],['goods_image','goods_item']); + if(empty($goods)){ + return []; + } + + //点击量 + $goods->click_count = $goods->click_count + 1; + $goods->save(); + $goods->sales_sum += $goods->virtual_sales_sum; + $goods->is_collect = 0; + $goods->member_price = 0; + $goods->append(['order_give_integral', 'commission_price']); + + //检查商品是否整在参加活动,如果正在参加活动替换商品的价格为活动价 + $goods = self::checkActivity($goods); + if($user_id) { + //是否收藏 + $collect = Db::name('goods_collect')->where(['user_id'=>$user_id,'goods_id'=>$id])->find(); + $goods->is_collect= $collect ? 1 : 0; + + //会员折扣 + $member_discount = Db::name('user_level l') + ->join('user u', 'u.level = l.id') + ->where(['u.id' => $user_id]) + ->value('discount'); + $price_array = []; + //处理会员折扣价格 + if ($goods->is_member > 0 && $member_discount > 0) { + //会员价格 + foreach ($goods->goods_item as $item => $value){ + $goods->goods_item[$item]['member_price'] = 0; + if($member_discount){ + $member_price = round($value['price'] * $member_discount / 10,2); + $goods->goods_item[$item]['member_price'] = $member_price; + $price_array[] = $member_price; + } + } + $price_array && $goods->member_price = min($price_array); + } + //多规格,按最高的价格计算积分 + if($price_array && 2 === $goods->give_integral_type){ + $price = $price_array ? max($price_array) : $goods->max_price; + $goods->order_give_integral = intval($price * $goods->give_integral / 100); + } + } + //猜你喜欢 + $goods->Like(); + //商品规格 + $goods->GoodsSpec(); + $goods->append(['comment'])->hidden(['Spec','GoodsSpecValue']) + ->visible(['id','name','image','video','stock','remark','content','sales_sum','poster', + 'click_count','min_price','max_price','market_price','is_collect','goods_spec','goods_image', + 'goods_item','activity','member_price','is_express','is_selffetch','market_price']); + + $market_price_array = array_column($goods->goods_item->toarray(),'market_price'); + $goods->market_price = max($market_price_array); + $price_array = array_column($goods->goods_item->toarray(),'price'); + $goods->min_price = min($price_array); + $goods->max_price = max($price_array); + + $goods->poster = !empty($goods->poster) ? UrlServer::getFileUrl($goods->poster) : ''; + // 商品虚拟浏览量 + $goods->click_count += $goods->virtual_click; + //判断是否开启了拼团 + if ($goods['is_team']) { + $resTeam = self::getTeam($goods); + // 如果活动没结束,则返回拼团数据, 否则把商品是否已开团状态改为,不是开团商品 + if ($resTeam !== 100 and is_array($resTeam)) { + $goods['activity'] = $resTeam; + } else { + $goods['is_team'] = 0; + } + } + // 预估佣金 + $goods = $goods->toArray(); + $goods['distribution'] = self::getDistribution($id, $user_id); + + // 钩子-记录足迹(浏览商品) + Hook::listen('footprint', [ + 'type' => Footprint::browse_goods, + 'user_id' => $user_id, + 'foreign_id' => $id //商品ID + ]); + + + Db::name('goods_click')->insert([ + 'user_id' => $user_id, + 'goods_id' => $id, + 'create_time' => time(), + ]); + + return $goods; + + + + } + //好物优选 + public static function getBestList($page,$size){ + $goods = new Goods(); + $goods_count = $goods + ->where(['del'=>0,'status'=>1,'is_best'=>1]) + ->count(); + + $goods_list = $goods + ->where(['del'=>0,'status'=>1,'is_best'=>1]) + ->field('id,name,image,min_price as price,market_price') + ->order('sort desc,id desc') + ->page($page,$size) + ->select(); + + $more = is_more($goods_count,$page,$size); //是否有下一页 + + $data = [ + 'list' => $goods_list, + 'page_no' => $page, + 'page_size' => $size, + 'count' => $goods_count, + 'more' => $more + ]; + return $data; + } + + //热门推荐 + public static function getHostList($page,$size){ + $goods = new Goods(); + $goods_count = $goods + ->where(['del'=>0,'status'=>1]) + ->count(); + + $goods_list = $goods + ->where(['del'=>0,'status'=>1]) + ->field('id,name,image,min_price as price,market_price,sales_sum+virtual_sales_sum as sales_sum,click_count,sort') + ->order('sales_sum desc,click_count desc, sort desc') + ->page($page,$size) + ->select(); + + $more = is_more($goods_count,$page,$size); //是否有下一页 + + $data = [ + 'list' => $goods_list, + 'page_no' => $page, + 'page_size' => $size, + 'count' => $goods_count, + 'more' => $more + ]; + return $data; + } + + //搜索记录 + public static function getSearchPage($user_id,$limit){ + $history_list = Db::name('search_record') + ->where(['user_id'=>$user_id,'del'=>0]) + ->limit($limit) + ->order('id desc') + ->column('keyword'); + $hot_lists = ConfigServer::get('hot_search','hot_keyword',[]); + return[ + 'history_lists' => $history_list, + 'hot_lists' => $hot_lists, + ]; + } + + //检查商品是否正在参加活动 + public static function checkActivity($goods){ + $goods['activity'] = []; + $seckill = SeckillLogic::getSeckillGoods(); + if($seckill['seckill_goods']){ + $seckill_goods_ids = array_column($seckill['seckill_goods'],'goods_id'); + if($seckill['seckill_goods'] && in_array($goods['id'],$seckill_goods_ids)){ + $goods['activity'] = [ + 'type' => 1, + 'info' => $seckill['seckill'], + ]; + foreach ($goods['goods_item'] as &$item){ + if(isset($seckill['seckill_goods'][$item['id']])){ + + $item['price'] = $seckill['seckill_goods'][$item['id']]['price']; + } + } + } + + } + return $goods; + + } + + //清空搜索记录 + public static function clearSearch($user_id){ + return Db::name('search_record') + ->where(['user_id'=>$user_id]) + ->update(['del'=>1,'update_time'=>time()]); + + } + + // 获取拼团内容 + private static function getTeam($goods) + { + // 查询拼团活动信息 + $teamActivityModel = new TeamActivity(); + $team = $teamActivityModel->field(true) + ->where(['del'=>0, 'status'=>1, 'goods_id'=>$goods['id']])->find(); + + // 判断是否已到活动时间 (为真则活动结束) + if ($team['end_time'] <= time()) { + Goods::where(['id'=>$goods['id']])->update([ 'is_team' => 0 ]); + return 10; + } + + // 查询规格信息 + $teamGoodsItem = new TeamGoodsItem(); + $team_item = $teamGoodsItem->field(true) + ->where('team_id', '=', $team['team_id']) + ->where('goods_id','=', $team['goods_id'])->select(); + + $team_spec_price = []; + foreach ($team_item as $item) { + $team_spec_price[intval($item['item_id'])] = $item['team_price']; + } + // 重置商品规格价格 为 拼团活动规格的价格 + $goods_item = $goods['goods_item']; + foreach ($goods_item as &$item) { + $item['team_price'] = $team_spec_price[$item['id']]; + } + $goods['goods_item'] = $goods_item; + + unset($team['status']); + unset($team['del']); + unset($team['create_time']); + + // 获取该商品正在开的团,但是还不够人的团 + $teamFoundModel = new TeamFound(); + $team_found = $teamFoundModel->field('id,team_id,found_time,found_end_time, + nickname,avatar,join,need') + ->where('team_id', '=', $team['team_id']) + ->where('status', '=', 0) + ->where('found_end_time', '>', time()) + ->limit(10) + ->select()->toArray(); + + return ['type'=>2, 'team'=>$team, 'team_found'=>$team_found]; + } + + /** + * 计算最高可得预估佣金 + * @param $goodsId + * @param $userId + * @return array + */ + public static function getDistribution($goodsId, $userId) + { + $earnings = 0; + $goods = \app\common\model\Goods::findOrEmpty($goodsId)->toArray(); + $distributionGoods = DistributionGoods::where('goods_id', $goodsId)->select()->toArray(); + if(!empty($distributionGoods) && $distributionGoods[0]['is_distribution'] && $distributionGoods[0]['rule'] == 2) { + foreach($distributionGoods as $item) { + $earnings = max($earnings, round($goods['max_price'] * $item['first_ratio'] / 100, 2)); + $earnings = max($earnings, round($goods['max_price'] * $item['second_ratio'] / 100, 2)); + } + } + if(!empty($distributionGoods) && $distributionGoods[0]['is_distribution'] && $distributionGoods[0]['rule'] == 1) { + $levels = DistributionLevel::select()->toArray(); + foreach($levels as $item) { + $earnings = max($earnings, round($goods['max_price'] * $item['first_ratio'] / 100, 2)); + $earnings = max($earnings, round($goods['max_price'] * $item['second_ratio'] / 100, 2)); + } + } + + // 详情页是否显示佣金 + $isShow = ConfigServer::get('distribution', 'is_show_earnings', 0); + if ($isShow) { + // 详情页佣金可见用户 0-全部用户 1-分销商 + $scope = ConfigServer::get('distribution', 'show_earnings_scope', 0); + $user = Distribution::where(['user_id' => $userId])->findOrEmpty()->toArray(); + if ($scope && empty($user['is_distribution'])) { + $isShow = 0; + } + } + + return [ + 'is_show' => $isShow, + 'earnings' => $earnings + ]; + } +} \ No newline at end of file diff --git a/app/api/model/Goods.php b/app/api/model/Goods.php new file mode 100644 index 0000000..f0dc827 --- /dev/null +++ b/app/api/model/Goods.php @@ -0,0 +1,225 @@ +)/is'; + $local_url = UrlServer::getFileUrl('/'); + return preg_replace($preg, "\${1}$local_url\${2}\${3}",$value); + } + //商品库存 + public function getStockAttr($value,$data){ + if($data['is_show_stock']){ + return $value; + } + return true; + } + //商品轮播图 + public function GoodsImage(){ + return $this->hasMany('GoodsImage','goods_id','id')->field('goods_id,uri'); + } + public function Spec() + { + return $this->hasMany('GoodsSpec', 'goods_id', 'id'); + } + public function GoodsItem(){ + return $this->hasMany('GoodsItem', 'goods_id', 'id')->field('id,goods_id,image,spec_value_ids,spec_value_str,market_price,price,stock'); + } + public function GoodsSpecValue(){ + + return $this->hasMany('GoodsSpecValue','goods_id','id'); + } + + public function GoodsSpec() + { + $spec = $this->Spec->toArray(); + $spec_value = $this->GoodsSpecValue; + $spec = array_column($spec,null,'id'); + $goods_item = $this->getAttr('goods_item'); + + //将商品价格替换成商品规格价 +// $this->setAttr('price',$goods_item[0]['price']); +// $this->setAttr('market_price',$goods_item[0]['market_price']); + + //拼接规格 + foreach ($spec_value as $item){ + if(isset($spec[$item['spec_id']])){ + $spec[$item['spec_id']]['spec_value'][]= $item; + } + } + $this->setAttr('goods_spec',array_values($spec)); + //规格图片为空则替换商品主图 + foreach ($goods_item as $item_key => $item_value){ + if(empty($item_value['image'])){ + $goods_item[$item_key]['image'] = $this->getAttr('image'); + } + } + $this->setAttr('goods_item',$goods_item); + } + + public function Like(){ + $goods = new self(); + $like_list = $goods->where(['del'=>0,'is_like'=>1,'status'=>1])->field('id,name,image,min_price as price,market_price')->orderRaw('rand()')->limit(5)->select(); + + $this->setAttr('like',$like_list); + } + + //下单赠送积分 + public function getOrderGiveIntegralAttr($value,$data) + { + $data['give_integral'] = empty($data['give_integral']) ? 0 : $data['give_integral']; + if (1 === $data['give_integral_type']) { + return intval($data['give_integral']); + } + return intval($data['max_price'] * $data['give_integral'] / 100); + } + + public function getCommentAttr($value,$data){ + $comment = []; + $goods_comment = Db::name('goods_comment g') + ->leftjoin('user u','g.user_id = u.id') + ->where(['goods_id'=>$data['id'],'g.del'=>0,'g.status'=>1]) + ->order('g.id desc') + ->field('g.id,user_id,item_id,comment,g.create_time,nickname,avatar,virtual_data') + ->find(); + + if($goods_comment){ + // 虚拟评论 + if (empty($goods_comment['user_id']) && !empty($goods_comment['virtual_data'])) { + $virtual_data = json_decode($goods_comment['virtual_data'], JSON_UNESCAPED_UNICODE); + $goods_comment['avatar'] = $virtual_data['avatar'] ?? ''; + $goods_comment['nickname'] = $virtual_data['nickname'] ?? ''; + $goods_comment['create_time'] = $virtual_data['comment_time'] ?? time(); + } + + //好评人数 + $goods_count = Db::name('goods_comment') + ->where(['goods_id'=>$data['id'],'del'=>0]) + ->where('goods_comment','>',3) + ->count(); + //总评论人数 + $comment_count = Db::name('goods_comment') + ->where(['goods_id'=>$data['id'],'del'=>0]) + ->count(); + //评论图片 + $comment_image = Db::name('goods_comment_image')->where(['goods_comment_id'=>$goods_comment])->column('uri'); + + $comment = $goods_comment; + $comment['goods_rate'] = round(($goods_count/$comment_count)*100, 2).'%'; + $comment['avatar'] = UrlServer::getFileUrl($comment['avatar']); + $comment['spec_value_str'] = ''; + $comment['create_time'] = date('Y-m-d H:i:s',$comment['create_time']); + foreach ($comment_image as &$image_item){ + $image_item = UrlServer::getFileUrl($image_item); + } + $comment['image'] = $comment_image; + foreach ($this->goods_item as $item){ + if($item['id'] == $comment['item_id']){ + $comment['spec_value_str'] = $item['spec_value_str']; + } + } + if(empty($comment['comment'])){ + $comment['comment'] = '此用户没有填写评论'; + } + } + return $comment; + } + + + //详情页显示佣金金额 + public function getCommissionPriceAttr($value, $data) + { + $open_distribution = ConfigServer::get('distribution', 'is_open', 1); + $show_commission = ConfigServer::get('distribution', 'show_commission', 0); + $first_ratio = empty($data['first_ratio']) ? 0 : $data['first_ratio']; + + if ($open_distribution && $show_commission && $data['is_commission'] && $first_ratio > 0) { + $money = round($first_ratio * $data['max_price'] / 100, 2); + if ($money > 0) { + return $money; + } + } + return 0; + } + + /** + * @notes 商品是否参与分销 + * @param $value + * @return string + * @author Tab + */ + public function getDistributionFlagAttr($value) + { + $data = DistributionGoods::where('goods_id', $value)->findOrEmpty()->toArray(); + if (!empty($data) && $data['is_distribution'] == 1) { + return true; + } + return false; + } + + /** + * @notes 分销状态搜索器 + * @param $query + * @param $value + * @param $data + * @author Tab + */ + public function searchIsDistributionAttr($query, $value, $data) + { + // 不参与分销 + if (isset($data['is_distribution']) && $data['is_distribution'] == '0') { + // 先找出参与分销的商品id + $ids = DistributionGoods::where('is_distribution', 1)->column('goods_id'); + if (!empty($ids)) { + // 在搜索条件中将它们排除掉 + $query->where('id', 'not in', $ids); + } + } + // 参与分销 + if (isset($data['is_distribution']) && $data['is_distribution'] == '1') { + // 先找出参与分销的商品id + $ids = DistributionGoods::where('is_distribution', 1)->column('goods_id'); + if (!empty($ids)) { + // 在搜索条件中使用它们来进行过滤 + $query->where('id', 'in', $ids); + } + } + } +} \ No newline at end of file diff --git a/app/common/model/goods/GoodsBrand.php b/app/common/model/goods/GoodsBrand.php new file mode 100644 index 0000000..49ec24f --- /dev/null +++ b/app/common/model/goods/GoodsBrand.php @@ -0,0 +1,13 @@ +