|
|
@@ -16,6 +16,7 @@ use app\models\store\{
|
|
|
};
|
|
|
use app\models\user\UserSearch;
|
|
|
use think\facade\Config;
|
|
|
+use MeiliSearch\Client;
|
|
|
|
|
|
/**
|
|
|
* TODO 产品Model
|
|
|
@@ -89,6 +90,38 @@ class StoreProduct extends BaseModel
|
|
|
return self::where('is_del', 0)->where('is_show', 1)->where('mer_id', 0);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 独立搜索
|
|
|
+ *
|
|
|
+ * v1. 使用 meilisearch 作为后端
|
|
|
+ *
|
|
|
+ * @param string $keywords 搜索关键字
|
|
|
+ * @return json 直接返回搜索结果到前端
|
|
|
+ */
|
|
|
+ protected static function search_by_keywords($keywords, $uid)
|
|
|
+ {
|
|
|
+ $show_benefit = Config::get('app.show_benefit', false);
|
|
|
+
|
|
|
+ $ml = new Client(config('meilisearch.addr', '127.0.0.1'), config('meilisearch.key'));
|
|
|
+ $idx = $ml->index('products');
|
|
|
+ $hits = $idx->search($keywords)->getHits();
|
|
|
+
|
|
|
+ $list = [];
|
|
|
+ $fields = 'id,store_name,cate_id,image,price,stock,spec_type';
|
|
|
+ $fields = explode(',', $fields);
|
|
|
+ // shrink hits in-place
|
|
|
+ foreach ($hits as $hit) {
|
|
|
+ $item = [];
|
|
|
+ foreach ($fields as $field) {
|
|
|
+ $item[$field] = $hit[$field];
|
|
|
+ }
|
|
|
+ $item['sales'] = $hit['sales'] + $hit['ficti'];
|
|
|
+
|
|
|
+ $list[] = $item;
|
|
|
+ }
|
|
|
+ return self::setLevelPrice($list, $uid);
|
|
|
+ }
|
|
|
+
|
|
|
public static function getProductList($data, $uid)
|
|
|
{
|
|
|
$sId = $data['sid']; // category id
|
|
|
@@ -113,40 +146,48 @@ class StoreProduct extends BaseModel
|
|
|
});
|
|
|
}
|
|
|
if (!empty($keyword)) {
|
|
|
- $model->where('keyword|store_name', 'LIKE', htmlspecialchars("%$keyword%"));
|
|
|
UserSearch::InsertHistory($uid ?? 1, $keyword);
|
|
|
+
|
|
|
+ return self::search_by_keywords($keyword, $uid);
|
|
|
+ // $model->where('keyword|store_name', 'LIKE', htmlspecialchars("%$keyword%"));
|
|
|
+ }
|
|
|
+ if ($news != 0) {
|
|
|
+ $model->where('is_new', 1);
|
|
|
}
|
|
|
- if ($news != 0) $model->where('is_new', 1);
|
|
|
$baseOrder = '';
|
|
|
if ($priceOrder) $baseOrder = $priceOrder == 'desc' ? 'price DESC' : 'price ASC';
|
|
|
// if($salesOrder) $baseOrder = $salesOrder == 'desc' ? 'sales DESC' : 'sales ASC';//真实销量
|
|
|
if ($salesOrder) $baseOrder = $salesOrder == 'desc' ? 'sales DESC' : 'sales ASC'; //虚拟销量
|
|
|
- if ($baseOrder) $baseOrder .= ', ';
|
|
|
+ if ($baseOrder) {
|
|
|
+ $baseOrder .= ', ';
|
|
|
+ }
|
|
|
$model->order($baseOrder . 'sort DESC, add_time DESC');
|
|
|
$show_benefit = Config::get('app.show_benefit', false);
|
|
|
$fields = 'id,store_name,cate_id,image,IFNULL(sales,0) + IFNULL(ficti,0) as sales,price,stock,spec_type';
|
|
|
if ($show_benefit) {
|
|
|
$fields .= ',cost';
|
|
|
}
|
|
|
- $list = $model->page((int)$page, (int)$limit)->field($fields)->select()->each(function ($item)
|
|
|
- use ($uid, $type, $show_benefit, $sId) {
|
|
|
- if ($type) {
|
|
|
- if ($item['spec_type']) {
|
|
|
- $item['is_att'] = StoreProductAttrValueModel::where(['product_id' => $item['id'], 'type' => 0])->count() ? true : false;
|
|
|
- } else {
|
|
|
- $item['is_att'] = false;
|
|
|
+ $list = $model->page((int)$page, (int)$limit)
|
|
|
+ ->field($fields)
|
|
|
+ ->select()
|
|
|
+ ->each(function ($item) use ($uid, $type, $show_benefit, $sId) {
|
|
|
+ if ($type) {
|
|
|
+ if ($item['spec_type']) {
|
|
|
+ $item['is_att'] = StoreProductAttrValueModel::where(['product_id' => $item['id'], 'type' => 0])->count() ? true : false;
|
|
|
+ } else {
|
|
|
+ $item['is_att'] = false;
|
|
|
+ }
|
|
|
+ if ($uid) $item['cart_num'] = StoreCart::where('is_pay', 0)->where('is_del', 0)->where('is_new', 0)->where('type', 'product')->where('product_id', $item['id'])->where('uid', $uid)->value('cart_num');
|
|
|
+ else $item['cart_num'] = 0;
|
|
|
+ if (is_null($item['cart_num'])) $item['cart_num'] = 0;
|
|
|
}
|
|
|
- if ($uid) $item['cart_num'] = StoreCart::where('is_pay', 0)->where('is_del', 0)->where('is_new', 0)->where('type', 'product')->where('product_id', $item['id'])->where('uid', $uid)->value('cart_num');
|
|
|
- else $item['cart_num'] = 0;
|
|
|
- if (is_null($item['cart_num'])) $item['cart_num'] = 0;
|
|
|
- }
|
|
|
- // show benefit
|
|
|
- if ($show_benefit) {
|
|
|
- $rate = getRate($sId);
|
|
|
- $item['reputation'] = '赔付' . getReputation($item, $rate);
|
|
|
- unset($item['cost']);
|
|
|
- }
|
|
|
- });
|
|
|
+ // show benefit
|
|
|
+ if ($show_benefit) {
|
|
|
+ $rate = getRate($sId);
|
|
|
+ $item['reputation'] = '赔付' . getReputation($item, $rate);
|
|
|
+ unset($item['cost']);
|
|
|
+ }
|
|
|
+ });
|
|
|
$list = count($list) ? $list->toArray() : [];
|
|
|
if (!empty($list)) {
|
|
|
foreach ($list as $k => $v) {
|
|
|
@@ -309,20 +350,25 @@ class StoreProduct extends BaseModel
|
|
|
$discount = bcsub(1, bcdiv($discount, 100, 2), 2);
|
|
|
}
|
|
|
//如果不是数组直接执行减去会员优惠金额
|
|
|
- if (!is_array($list))
|
|
|
+ if (!is_array($list)) {
|
|
|
//不是会员原价返回
|
|
|
- if ($levelId)
|
|
|
+ if ($levelId) {
|
|
|
//如果$isSingle==true 返回优惠后的总金额,否则返回优惠的金额
|
|
|
return $isSingle ? bcsub($list, bcmul($discount, $list, 2), 2) : bcmul($discount, $list, 2);
|
|
|
- else
|
|
|
+ } else {
|
|
|
return $isSingle ? $list : 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
//当$list为数组时$isSingle==true为一维数组 ,否则为二维
|
|
|
- if ($isSingle)
|
|
|
+ if ($isSingle) {
|
|
|
$list['vip_price'] = isset($list['price']) ? bcsub($list['price'], bcmul($discount, $list['price'], 2), 2) : 0;
|
|
|
- else
|
|
|
+ } else {
|
|
|
foreach ($list as &$item) {
|
|
|
$item['vip_price'] = isset($item['price']) ? bcsub($item['price'], bcmul($discount, $item['price'], 2), 2) : 0;
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
return $list;
|
|
|
}
|
|
|
|
|
|
@@ -358,9 +404,13 @@ class StoreProduct extends BaseModel
|
|
|
foreach ($cateList as $cate) {
|
|
|
$cid[] = $cate['id'];
|
|
|
}
|
|
|
- $model = self::where('cate_id', 'IN', $cid)->where('is_show', 1)->where('is_del', 0)
|
|
|
+ $model = self::where('cate_id', 'IN', $cid)
|
|
|
+ ->where('is_show', 1)
|
|
|
+ ->where('is_del', 0)
|
|
|
->field($field)->order('sort DESC,id DESC');
|
|
|
- if ($limit) $model->limit($limit);
|
|
|
+ if ($limit) {
|
|
|
+ $model->limit($limit);
|
|
|
+ }
|
|
|
return $model->select();
|
|
|
}
|
|
|
|