caipan_shop_admin/app/repository/SpuRepository.php

926 lines
32 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace app\repository;
use app\exception\RepositoryException;
use app\model\AccountRecord;
use app\model\mall\Category;
use app\model\mall\SpuCategoryPivot;
use app\model\mall\SpuLimitTime;
use app\model\Order;
use app\model\OrderActivity;
use app\model\OrderGroupList;
use app\model\Sku;
use app\model\sku\SpecParam;
use app\model\sku\SpecValue;
use app\model\Spu;
use app\model\SpuActivity;
use app\service\Repository;
use app\traits\spu\LimitTimeTrait;
use app\traits\spu\SkuTrait;
use Exception;
use think\Collection;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\facade\Log;
use think\Model;
/**
* Class SpuRepository
* @package app\repository
* @method self getInstance(Model $model = null) static
*/
class SpuRepository extends Repository
{
use SkuTrait;
use LimitTimeTrait;
/**
* 获取商品列表【后台使用】
*
* @param array $params
* @return array
* @throws Exception
*/
public function list(array $params = []): array
{
event('SpuCheck');
$whereMap = [];
$order = $params['order'] ?? ['sort' => 'desc', 'id' => 'desc'];
$type = $params['type'] ?? '';//type为空时 默认为商品管理 包含除积分商品外所有类型
if (!empty($type)) {
$whereMap[] = ['activity_type', '=', $type];
}
switch ($type) {
case Spu::TYPE_NORMAL:
$whereMap[] = ['is_activity', '=', Spu::COMMON_OFF];
$whereMap[] = ['is_score', '=', Spu::COMMON_OFF];
break;
case Spu::TYPE_SCORE:
$whereMap[] = ['is_activity', '=', Spu::COMMON_OFF];
$whereMap[] = ['is_score', '=', Spu::COMMON_ON];
break;
case Spu::TYPE_GROUP_MAKE:
case Spu::TYPE_GROUP_BUY:
case Spu::TYPE_LIMIT_TIME:
$whereMap[] = ['is_activity', '=', Spu::COMMON_ON];
$whereMap[] = ['is_score', '=', Spu::COMMON_OFF];
break;
default:
$whereMap[] = ['is_score', '=', Spu::COMMON_OFF];
// $whereMap[] = ['is_activity', '=', Spu::COMMON_OFF];
}
if (isset($params['saleable'])) {
$whereMap[] = ['saleable', '=', $params['saleable']];
}
if (isset($params['keyword']) && !empty($params['keyword'])) {
$whereMap[] = ['name|subtitle', 'like', '%'.$params['keyword'].'%'];
}
if (isset($params['spu_type']) && !empty($params['spu_type'])) {
$whereMap[] = ['spu_type', '=', $params['spu_type']];
}
$whereMap[] = ['deleted_at', '=', null];
$params['page'] = $params['page'] ?? 1;
$params['size'] = $params['size'] ?? 20;
$fields = $params['fields'] ?? [];
return Spu::findList($whereMap, $fields, $params['page'], $params['size'], null, $order);
}
/**
* 获取活动商品列表【后台使用】
*
* @param array $params
* @return array
* @throws Exception
*/
public function activityList(array $params = []): array
{
$whereMap = [];
$order = $params['order'] ?? ['sort' => 'desc', 'id' => 'desc'];
$type = $params['type'] ?? '';//type为空时 默认为商品管理 包含除积分商品外所有类型
if (!empty($type)) {
$whereMap[] = ['activity_type', '=', $type];
}
if (isset($params['saleable'])) {
$whereMap[] = ['saleable', '=', $params['saleable']];
}
if (isset($params['keyword']) && !empty($params['keyword'])) {
$whereMap[] = ['name|subtitle', 'like', '%'.$params['keyword'].'%'];
}
if (isset($params['spu_type']) && !empty($params['spu_type'])) {
$whereMap[] = ['spu_type', '=', $params['spu_type']];
}
$whereMap[] = ['deleted_at', '=', null];
$params['page'] = $params['page'] ?? 1;
$params['size'] = $params['size'] ?? 20;
$fields = $params['fields'] ?? [];
return SpuActivity::findList($whereMap, $fields, $params['page'], $params['size'], null, $order);
}
/**
* 前端商品列表
*
* @throws Exception
*/
public function listForFront(array $params = [], callable $callback = null, array $order = [], array $where = []): array
{
$page = $params['page'] ?? 1;
$size = $params['size'] ?? 0;
$page = (!is_numeric($page) || $page <= 0) ? 1 : $page;
$size = (!is_numeric($size) || $size <= 0) ? 10 : $size;
$size = 0;
event('SpuCheck');
$searchMap = $where;
// 商品名称模糊搜索
if (isset($params['keyword']) && !empty($params['keyword'])) {
$searchMap[] = ['name', 'like', '%'.$params['keyword'].'%'];
}
// 活动类型搜索
if (isset($params['activity']) && !empty($params['activity'])) {
$searchMap[] = ['activity_type', 'in', explode(',', $params['activity'])];
if (!in_array($params['activity'], [Spu::TYPE_NORMAL, Spu::TYPE_SCORE])) {
$searchMap[] = ['is_activity', '=', Spu::COMMON_ON];
}
}
// 价格区间开始
if (isset($params['price_from']) && is_numeric($params['price_from'])) {
$searchMap[] = ['price', '>=', $params['price_from']];
}
// 价格区间结束
if (isset($params['price_to']) && is_numeric($params['price_to'])) {
$searchMap[] = ['price', '<=', $params['price_to']];
}
$searchMap[] = ['saleable', '=', Spu::COMMON_ON];
// 是否积分
if (isset($params['is_score'])) {
$searchMap[] = ['is_score', '=', $params['is_score']];
}
// 是否热门
if (isset($params['is_hot'])) {
$searchMap[] = ['is_hot', '=', $params['is_hot']];
}
// 是否推荐到首页
if (isset($params['is_home']) && in_array($params['is_home'], [0, 1])) {
$searchMap[] = ['is_home', '=', $params['is_home']];
}
// 指定分类
if (isset($params['category_id']) && !empty($params['category_id'])) {
// 多个分类逗号分割
$spuIds = SpuCategoryPivot::whereIn('category_id', explode(',', $params['category_id']))->column('spu_id');
if ($spuIds) {
$searchMap[] = ['id', 'in', array_unique($spuIds)];
}else{
$searchMap[] = ['id', '=', 0];
}
}
$fields = $params['fields'] ?? ['id', 'name', 'price', 'original_price', 'cover', 'activity_type'];
if (empty($order)) {
$order = ['published_at' => 'desc'];
}
$list = Spu::findList($searchMap, $fields, $page, $size, $callback, $order);
$activityText = Spu::activityTextList();
$list['list'] = $list['list']->each(function ($item) use ($activityText) {
$spuSkuList = $this->spuSkuList($item->id);
$item->skuId = $spuSkuList[0]["id"] ?? 0;
$item->tag = $activityText[$item->activity_type] ?? '';
});
return $list;
}
/**
* 内容详情
*
* @param int $id
* @param int $accountId
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
* @throws Exception
*/
public function detail(int $id, int $accountId = 0): array
{
$field = [
'id', 'activity_id', 'activity_type', 'name', 'subtitle', 'price', 'original_price', 'unit','limit_num', 'cover', 'images',
'share_img', 'is_activity', 'stock', 'amount', 'multi_spec', 'content'
];
if (!$spu = $this->findById($id, $field)) {
throw new RepositoryException('数据不存在');
}
$spu = $spu->toArray();
if ($spu['is_activity'] == Spu::COMMON_ON) {
switch ($spu['activity_type']) {
case SpuLimitTime::TYPE:
$activityInfo = SpuLimitTime::findById($spu['activity_id']);
break;
default:
$activityInfo = null;
}
if (!$activityInfo) {
throw new RepositoryException('活动不存在');
}
if ($activityInfo['status'] != Spu::COMMON_ON) {
throw new RepositoryException('活动已下架');
}
$now = date('Y-m-d H:i:s');
if ($activityInfo['end_at'] < $now || $activityInfo['begin_at'] > $now) {
throw new RepositoryException('不在活动时间内');
}
$spu['name'] = $activityInfo['name'];
$spu['subtitle'] = $activityInfo['subtitle'];
$spu['begin_at'] = $activityInfo['begin_at'];
$spu['end_at'] = $activityInfo['end_at'];
}
if (isset($spu['is_score']) && $spu['is_score']) {
$spu['activity_type'] = Spu::TYPE_NORMAL;
}
$spu['activity_text'] = '';
$spu['tag'] = '';
// 活动标签
if ($spu['is_activity'] && isset($spu['activity_type'])) {
$spu['activity_text'] = Spu::activityTextList()[$spu['activity_type']] ?? '';
$spu['tag'] = Spu::activityTextList()[$spu['activity_type']] ?? '';
}
// 规格列表
$skuList = $spu['is_activity'] == Spu::COMMON_ON ? $this->spuSkuList($spu['activity_id'], $spu['activity_type'], true) : $this->spuSkuList($id);
if ($spu['is_activity'] == Spu::COMMON_ON) {
$default = $skuList->where('is_default', Spu::COMMON_ON)->first();
$spu['original_price'] = $spu['price'];
$spu['price'] = $default['price'];
}
$spu["skuId"] = $skuList[0]["id"] ?? 0;
$res['detail'] = $spu;
// $res['sku'] = $skuList;
return $res;
}
/**
* 获取商品规格列表
*
* @param int $id ID
* @param string $activityType 活动类型 normal=普通 limit_time=限时折扣
* @param bool $isActivity 是否活动
* @return Sku[]|array|Collection
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function spuSkuList(int $id, string $activityType = Spu::TYPE_NORMAL, bool $isActivity = false)
{
$skuFields = ['id', 'coding', 'title', 'stock', 'price', 'original_price', 'score', 'is_default'];
$where = [];
$where[] = ['type', '=', $activityType];
if ($isActivity) {
$where[] = ['spu_activity_id', '=', $id];
} else {
$where[] = ['spu_id', '=', $id];
}
return Sku::where($where)->field($skuFields)->select();
}
/**
* 获取商品 相关产品推荐
*
* @param int $spuId
* @param bool $isScore 是否积分商品
* @param int $page
* @param int $size
* @return mixed
* @throws Exception
*/
public function spuProduct(int $spuId, bool $isScore = false, int $page = 1, int $size = 10)
{
$params = [];
$params['is_score'] = $isScore;
$params['page'] = $page;
$params['size'] = $size;
$params['fields'] = $isScore ? Spu::scoreListFields() : Spu::spuListFields();
return $this->listForFront($params, function ($q) use ($spuId) {
return $q->where('id', '<>', $spuId)->order('published_at', 'desc');
})['list'];
}
/**
* 添加SPU商品信息
*
* @param array $data 基础信息
* @param array $sku 规格信息
* @return Model
* @throws RepositoryException
*/
public function addSpu(array $data, array $sku): Model
{
Db::startTrans();
try {
$now = date('Y-m-d H:i:s');
$data['saleable'] = $data['saleable'] ?? Spu::COMMON_ON;
$data['published_at'] = $data['published_at'] ?? $now;
$data['created_at'] = $now;
if (isset($data['init_amount']) && $data['init_amount'] > 0) {
$data['amount'] += $data['init_amount'];
}
$categoryIds = $data['category_id'] ?? '';
$categoryIds = explode(',', $categoryIds);
$multiSpec = (bool) $data['multi_spec'];
$spu = $this->create($data);
$skuData = $this->handleSku($spu['id'], $sku, [], 'normal', $multiSpec);
(new Sku())->saveAll($skuData['data']);
$spu->save([
'stock' => $skuData['stock'],
'price' => $skuData['price'],
'original_price' => $skuData['original_price'],
'score' => $skuData['score'],
'spec' => json_encode($skuData['spec'], JSON_UNESCAPED_UNICODE)
]);
// 中间表
$this->setCategory($spu->id, $categoryIds);
Db::commit();
return $spu;
} catch (RepositoryException $e) {
// 回滚事务
Db::rollback();
throw $e;
} catch (Exception $e) {
SpuRepository::log($e->getMessage(), $e);
// 回滚事务
Db::rollback();
throw new RepositoryException('商品创建失败');
}
}
/**
* 编辑商品信息
*
* @param int $id
* @param array $data 基础信息
* @param array $sku 规格信息
* @param array $originalSkuList 原始规格列表
* @throws RepositoryException
*/
public function editSpu(int $id, array $data, array $sku, array $originalSkuList)
{
Db::startTrans();
try {
$spu = $this->findById($id);
if (empty($spu)) {
throw new RepositoryException('没有相关的商品记录');
}
if (isset($data['init_amount']) && $data['init_amount'] > 0) {
$data['amount'] = $spu['amount'] - $spu['init_amount'];
$data['amount'] = $data['amount'] > 0 ? $data['amount'] : 0;
$data['amount'] += $data['init_amount'];
}
$now = date('Y-m-d H:i:s');
$data['saleable'] = $data['saleable'] ?? Spu::COMMON_ON;
$data['published_at'] = $data['published_at'] ?? $now;
$data['updated_at'] = $now;
$categoryIds = $data['category_id'] ?? '';
$categoryIds = explode(',', $categoryIds);
$multiSpec = (bool) $data['multi_spec'];
$skuData = $this->handleSku($id, $sku, array_column($originalSkuList, 'id'), 'normal', $multiSpec);
(new Sku())->saveAll($skuData['data']);
(new Sku())->where('id', 'in', $skuData['delete'])->delete();
$data['stock'] = $skuData['stock'];
$data['price'] = $skuData['price'];
$data['original_price'] = $skuData['original_price'];
$data['score'] = $skuData['score'];
$data['spec'] = json_encode($skuData['spec'], JSON_UNESCAPED_UNICODE);
$spu->save($data);
$this->setCategory($id, $categoryIds);
Db::commit();
} catch (RepositoryException $e) {
// 回滚事务
Db::rollback();
throw $e;
} catch (Exception $e) {
// 回滚事务
Db::rollback();
throw new RepositoryException('商品信息修改失败');
}
}
/**
* 删除SPU商品信息 软删除
*
* @param array $ids
* @return bool
* @throws RepositoryException
*/
public function deleteSpu(array $ids): bool
{
try {
return $this->model->whereIn('id', $ids)->save(['deleted_at' => date('Y-m-d H:i:s')]);
} catch (Exception $e) {
throw new RepositoryException('删除失败'.$e->getMessage());
}
}
/**
* 处理SKU数据
*
* @param int $id spu_id或spu_activity_id
* @param array $data
* @param array $originalSkuIds 原始skuID列表
* @param string $type normal=普通商品 limit_time=限时折扣
* @param bool $isMulti 是否多规格 默认是·
* @return array
* @throws RepositoryException
*/
public function handleSku(int $id, array $data, array $originalSkuIds = [], string $type = 'normal', bool $isMulti = true): array
{
if (empty($data)) {
throw new RepositoryException('规格不能为空');
}
$stock = 0;//总库存
$defaultNum = 0;//默认规格数量
$defaultPrice = 0;//默认规格价格
$defaultOriginalPrice = 0;//默认规格原价
$defaultScore = 0;//默认规格积分
$deleteIds = array_diff($originalSkuIds, array_column($data, 'id'));;//待删除待skuID列表
// 获取所有规格值及其相关规格
$specValueList = SpecValue::alias('sv')->leftJoin('spec_param sp', 'sv.spec_id = sp.id')
->where('sv.status', SpecValue::COMMON_ON)
->where('sp.status', SpecParam::COMMON_ON)
->field('sv.id as value_id, sv.title as value_title, sv.spec_id,sp.title as spec_title')
->order('sv.sort', 'desc')
->order('sv.id', 'asc')
->select();
$valueKvList = $isMulti ? $specValueList->column('value_title', 'value_id') : [];
$value2Spec = $isMulti ? $specValueList->column('spec_id', 'value_id') : [];
$value2SpecTitle = $isMulti ? $specValueList->column('spec_title', 'value_id') : [];
$specValueIds = [];// 该商品启用的规格值
// 验证规格
foreach ($data as $key => &$spec) {
// ID为空的表示新增 去掉id字段 saveAll时 自动识别更新或新增
if (empty($spec['id'])) {
unset($spec['id']);
}
if ($isMulti) {
$keys = explode('-', $key);
$spec['indexes'] = $key;
$spec['title'] = '';
$specText = [];
$specValueIds = array_merge($specValueIds, $keys);
foreach ($keys as $k) {
$spec['title'] .= ' '.($valueKvList[$k] ?? '');
$specText[] = [$value2SpecTitle[$k] => $valueKvList[$k]];
}
$spec['spec_text'] = json_encode($specText, JSON_UNESCAPED_UNICODE);
}
if (!isset($spec['stock']) || !isset($spec['is_default'])) {
throw new RepositoryException('规格信息不完整');
}
if (empty($spec['stock'])) {
throw new RepositoryException('请填写库存');
}
$spec['price'] = $spec['original_price'] ?? 0;
if (isset($spec['price']) && $spec['price'] < 0) {
throw new RepositoryException('规格价格必须大于等于0');
}
if (!isset($spec['price']) && !isset($spec['score'])) {
throw new RepositoryException('规格价格|积分不能为空');
}
$spec['original_price'] = $spec['original_price'] ?: $spec['price'];
if ($spec['is_default'] == 1) {
$defaultNum += 1;
$defaultPrice = $spec['price'];
$defaultOriginalPrice = $spec['original_price'];
$defaultScore = $spec['score'] ?? 0;
}
if ($type == 'normal') {
if (!isset($spec['spu_id'])) {
$spec['spu_id'] = $id;
}
} else {
if (!isset($spec['spu_activity_id'])) {
$spec['spu_activity_id'] = $id;
}
$spec['type'] = $type;
}
if (!isset($spec['coding']) || empty($spec['coding'])) {
$spec['coding'] = generateCode();
}
$stock += $spec['stock'];
}
$specInfo = [];// 该商品的启用的规格及其规格值
$specValueIds = array_unique($specValueIds);
foreach ($specValueIds as $valueId) {
$specId = $value2Spec[$valueId] ?? 0;
if ($specId > 0 && !isset($specInfo[$specId])) {
$specInfo[$specId] = [];
}
$specInfo[$specId][] = $valueId;
}
if ($defaultNum !== 1) {
throw new RepositoryException('默认规格有且仅有一个');
}
return [
'data' => $data,
'stock' => $stock,
'price' => $defaultPrice,
'original_price' => $defaultOriginalPrice,
'score' => $defaultScore,
'delete' => $deleteIds,
'spec' => $specInfo
];
}
/**
* 添加SPU活动商品信息
*
* @param string $type
* @param array $data 活动基础信息
* @param int $spuId
* @param array $sku 规格信息
* @return Model
* @throws RepositoryException
*/
public function addActivity(string $type, array $data, int $spuId, array $sku): Model
{
Db::startTrans();
try {
if (!$spu = Spu::findById($spuId)) {
throw new RepositoryException('商品不存在');
}
$insert = $spu->toArray();
unset($insert['id']);
$allowFields = [
'name', 'subtitle', 'saleable', 'price', 'original_price', 'score', 'level_id',
'is_hot', 'has_postage', 'cover', 'images', 'share_img', 'video', 'spu_type', 'content', 'views',
];
$now = date('Y-m-d H:i:s');
$insert = arrayKeysFilter($insert, $allowFields);
$insert['activity_type'] = $type;
$insert['cover'] = $data['cover'] ?: $insert['cover'];
$insert['activity_begin_at'] = $data['activity_begin_at'];
$insert['activity_end_at'] = $data['activity_end_at'];
$insert['limit_time'] = $data['limit_time'] ?? 0;
$insert['limit_num'] = $data['limit_num'] ?? 0;
$insert['group_base_num'] = $data['group_base_num'] ?? 0;
$insert['group_num'] = $data['group_num'] ?? 0;
$insert['group_time'] = $data['group_time'] ?? 0;
$insert['virtual_group'] = $data['virtual_group'] ?? 0;
$insert['open_one'] = $data['open_one'] ?? 0;
$insert['amount'] = 0;//销量设为0
$insert['spu_id'] = $spuId;
$insert['created_at'] = $now;
$insert['updated_at'] = $now;
$insert['published_at'] = $now;
$spuActivity = SpuActivity::create($insert);
$spu->save([
'activity_id' => $spuActivity['id'],
'is_activity' => Spu::COMMON_ON,
'activity_type' => $type,
]);
$skuData = $this->handleSku($spuActivity['id'], $sku, [], 'activity');
(new Sku())->saveAll($skuData['data']);
$spuActivity->save([
'stock' => $skuData['stock'],
'price' => $skuData['price'],
'original_price' => $skuData['original_price'],
'score' => $skuData['score'],
]);
Db::commit();
return $spu;
} catch (RepositoryException $e) {
// 回滚事务
Db::rollback();
throw $e;
} catch (Exception $e) {
SpuRepository::log($e->getMessage(), $e);
// 回滚事务
Db::rollback();
throw new RepositoryException('活动商品创建失败');
}
}
/**
* 编辑活动商品信息
*
* @param int $id
* @param array $data 基础信息
* @param array $sku 规格信息
* @param array $originalSkuList 原始规格列表
* @throws RepositoryException
*/
public function editActivity(int $id, array $data, array $sku, array $originalSkuList)
{
Db::startTrans();
try {
if (!$spuActivity = SpuActivity::findById($id)) {
throw new RepositoryException('没有相关的活动商品记录');
}
$now = date('Y-m-d H:i:s');
$data['updated_at'] = $now;
$skuData = $this->handleSku($id, $sku, array_column($originalSkuList, 'id'), 'activity');
(new Sku())->saveAll($skuData['data']);
(new Sku())->where('id', 'in', $skuData['delete'])->delete();
$data['stock'] = $skuData['stock'];
$data['price'] = $skuData['price'];
$data['original_price'] = $skuData['original_price'];
$data['score'] = $skuData['score'];
$spuActivity->save($data);
Db::commit();
} catch (RepositoryException $e) {
// 回滚事务
Db::rollback();
throw $e;
} catch (Exception $e) {
// 回滚事务
Db::rollback();
throw new RepositoryException('活动商品信息修改失败'.$e->getLine());
}
}
/**
* 获取活动商品的订单列表
*
* @throws Exception
*/
public function getActivityOrderList(int $activityId, string $type = Spu::TYPE_LIMIT_TIME, int $page = 1, int $size = 0): array
{
$where = [];
$where[] = ['spu_activity_id', '=', $activityId];
$where[] = ['deleted_at', '=', null];
$where[] = ['type', '=', $type];
$res = OrderActivity::findList($where, [], $page, $size, function ($q) {
return $q->with(['orderInfo', 'account']);
}, ['id' => 'desc']);
$res['list'] = $res['list']->each(function ($item) {
$item->activity_text = Spu::activityTextList()[$item->activity_type] ?? '';
$item->created_at = $item->orderInfo->created_at ?? '';
$item->phone = $item->orderInfo->phone ?? '';
$item->status = $item->orderInfo->status ?? '';
$item->status_text = Order::statusTextList()[$item->status] ?? '';
$item->nickname = $item->account->nickname ?? '';
$item->real_name = $item->account->real_name ?? '';
});
return $res;
}
/**
* 商品分类 构造xmSelect 需要的数据[xmSelect使用时需要json_encode处理]
*
* @param array $selected
* @param array $disabled
* @param bool $excludeParent 拥有下级的节点是否不可勾选 默认false
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function categoryXmSelect(array $selected = [], array $disabled = [], bool $excludeParent = false): array
{
$category = Category::order('sort', 'desc')
->field('id,pid,title')
->select()->toArray();
foreach ($category as $k => $m) {
$category[$k]['selected'] = in_array($m['id'], $selected);
$category[$k]['disabled'] = in_array($m['id'], $disabled);
}
$category = CmsRepository::getInstance()->buildMenuChild(0, $category, 'children', $excludeParent);
return CmsRepository::getInstance()->handleSelectedList($category);
}
/**
* 商品分类
*
* @param int $pid
* @param array $fields
* @return Category[]|array|Collection
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
*/
public function category(int $pid = 0, array $fields = ['id', 'title'])
{
return Category::where('pid', $pid)
->field($fields)
->order('sort', 'desc')
->order('id', 'asc')
->withAttr("cover",function ($value){
return resourceJoin($value,request()->domain());
})
->select();
}
public function categoryAll(array $fields = ['id', 'title'])
{
$list = Category::field($fields)
->order('sort', 'desc')
->order('id', 'asc')
->select()
->withAttr("cover",function ($value){
return resourceJoin($value,request()->domain());
})
->toArray();
return list_to_tree($list);
}
/**
* 设置商品分类
*
* @param int $spuId
* @param array $categoryIds
*/
public function setCategory(int $spuId, array $categoryIds)
{
SpuCategoryPivot::where('spu_id', $spuId)->delete();
if ($categoryIds) {
$insert = [];
foreach ($categoryIds as $categoryId) {
$insert[] = [
'spu_id' => $spuId,
'category_id' => $categoryId
];
}
(new SpuCategoryPivot())->insertAll($insert);
}
}
/**
* 获取商品分类ID列表
*
* @param int $spuId
* @return array
*/
public function getCategoryIdList(int $spuId): array
{
return SpuCategoryPivot::where('spu_id', $spuId)->column('category_id');
}
/**
* 获取商品规格信息
*
* @param int $spuId
* @return array
* @throws DataNotFoundException
* @throws DbException
* @throws ModelNotFoundException
* @throws RepositoryException
*/
public function getSpec(int $spuId): array
{
if (!$spu = Spu::findById($spuId)) {
throw new RepositoryException('商品不存在');
}
$res = [];
if ($spu['is_activity'] == Spu::COMMON_ON) {
$where[] = ['spu_activity_id', '=', $spu['activity_id']];
$where[] = ['type', '=', $spu['activity_type']];
} else {
$where[] = ['spu_id', '=', $spuId];
}
$fields = ['id', 'spu_id', 'indexes', 'title', 'coding', 'stock', 'price', 'original_price', 'is_default'];
$skuList = Sku::where($where)->field($fields)->select();
$res['sku_list'] = $skuList;//SKU列表
$res['sku'] = $skuList->where('is_default', Sku::COMMON_ON)->first();//默认SKU
$res['spec'] = [];//规格
if ($spu['multi_spec'] > 0) {
$spec = json_decode($spu['spec'], true);
$specIds = array_keys($spec);
$valueIds = [];
foreach (array_values($spec) as $arr) {
$valueIds = array_merge($valueIds, $arr);
}
$specList = SpecParam::whereIn('id', $specIds)->order('sort', 'desc')->order('id', 'asc')->select()->toArray();
$specValueList = SpecValue::whereIn('id', $valueIds)->order('sort', 'desc')->order('id', 'asc')->select()->toArray();
foreach ($specList as $sl) {
$arr = [];
$arr['id'] = $sl['id'];
$arr['title'] = $sl['title'];
$children = [];
foreach ($specValueList as $vl) {
if ($vl['spec_id'] == $sl['id']) {
$children[] = [
'id' => $vl['id'],
'title' => $vl['title'],
];
}
}
$arr['children'] = $children;
$res['spec'][] = $arr;
}
}
return $res;
}
/**
* [{"颜色": "红色"},{"尺寸": "L"}] 转成 ["颜色:红色","尺寸:L"]
*
* @param $specArr
* @return array
*/
public function convertSpecInfo($specArr): array
{
if (!$specArr) {
return [];
}
$arr = [];
foreach ($specArr as $s) {
$k = key($s);
$arr[] = sprintf("%s%s", $k, $s[$k] ?? '');
}
return $arr;
}
}