1.缺失信息提交

This commit is contained in:
2025-05-07 12:18:08 +08:00
parent 4da5dc858a
commit 62532ca66a
4 changed files with 729 additions and 0 deletions

View File

@ -0,0 +1,90 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\api\controller;
use app\api\logic\GoodsLogic;
class GoodsController extends BaseApiController
{
public array $notNeedLogin = ['getgoodsdetail', 'getgoodslist','getbestlist','gethostlist','getsearchpage'];
/**
* note 商品列表
* create_time 2020/10/20 11:12
*/
public function getGoodsList(){
$get = $this->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('清理失败','');
}
}

View File

@ -0,0 +1,401 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\api\logic;
use app\api\model\Goods;
use app\common\model\Distribution;
use app\common\model\DistributionGoods;
use app\common\model\DistributionLevel;
use app\common\model\Footprint;
use app\common\model\goods\GoodsBrand;
use app\common\model\TeamActivity;
use app\common\model\TeamFound;
use app\common\model\TeamGoodsItem;
use app\common\server\ConfigServer;
use app\common\server\UrlServer;
use think\facade\Db;
use think\facade\Hook;
class GoodsLogic{
//商品列表
public static function getGoodsList($user_id,$get,$page,$size){
$where = [];
$order = [];
$where[] = ['status','=',1];
$where[] = ['del','=',0];
$goods = new Goods();
//品牌筛选
if(isset($get['brand_id']) && $get['brand_id']) {
$where[] = ['brand_id', '=', $get['brand_id']];
}
//分类筛选
if(isset($get['category_id']) && $get['category_id']){
$where[] = ['first_category_id|second_category_id|third_category_id','=',$get['category_id']];
}
//关键词搜索
if(isset($get['keyword']) && $get['keyword']){
// 优先查品牌 然后再查询商品
$band_ids = GoodsBrand::where('is_show', 1)->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
];
}
}

225
app/api/model/Goods.php Normal file
View File

@ -0,0 +1,225 @@
<?php
// +----------------------------------------------------------------------
// | likeshop开源商城系统
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | gitee下载https://gitee.com/likeshop_gitee
// | github下载https://github.com/likeshop-github
// | 访问官网https://www.likeshop.cn
// | 访问社区https://home.likeshop.cn
// | 访问手册http://doc.likeshop.cn
// | 微信公众号likeshop技术社区
// | likeshop系列产品在gitee、github等公开渠道开源版本可免费商用未经许可不能去除前后端官方版权标识
// | likeshop系列产品收费版本务必购买商业授权购买去版权授权后方可去除前后端官方版权标识
// | 禁止对系统程序代码以任何目的,任何形式的再发布
// | likeshop团队版权所有并拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeshop.cn.team
// +----------------------------------------------------------------------
namespace app\api\model;
use app\common\model\DistributionGoods;
use app\common\service\ConfigServer;
use app\common\service\UrlServer;
use think\facade\Db;
use think\Model;
class Goods extends Model{
//商品图片
public function getImageAttr($value,$data){
if($value){
return UrlServer::getFileUrl($value);
}
return $value;
}
//商品视频
public function getVideoAttr($value,$data){
if($value){
return UrlServer::getFileUrl($value);
}
return $value;
}
//商品详情
public function getContentAttr($value,$data){
$preg = '/(<img .*?src=")[^https|^http](.*?)(".*?>)/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);
}
}
}
}

View File

@ -0,0 +1,13 @@
<?php
namespace app\common\model\goods;
use think\Model;
use think\model\concern\SoftDelete;
class GoodsBrand extends Model
{
use SoftDelete;
protected $defaultSoftDelete = 0;
protected $deleteTime = 'del';
}