// +--------------------------------------------------------------------- namespace app\common\repositories\store; use app\common\dao\store\StoreActivityDao; use app\common\model\store\StoreActivity; use app\common\repositories\BaseRepository; use app\common\repositories\store\product\ProductLabelRepository; use app\common\repositories\store\product\SpuRepository; use app\common\repositories\system\merchant\MerchantRepository; use app\common\repositories\system\RelevanceRepository; use crmeb\services\QrcodeService; use Exception; use think\exception\ValidateException; use think\facade\Cache; use think\facade\Db; /** * @mixin StoreActivityDao */ class StoreActivityRepository extends BaseRepository { //氛围图 const ACTIVITY_TYPE_ATMOSPHERE = 1; //活动边框 const ACTIVITY_TYPE_BORDER = 2; //报名活动 const ACTIVITY_TYPE_FORM = 4; //指定范围类型 //0全部商品 const TYPE_ALL = 0; //指定商品 const TYPE_MUST_PRODUCT = 1; //指定分类 const TYPE_MUST_CATEGORY = 2; //指定商户 const TYPE_MUST_STORE = 3; //指定商品标签 const TYPE_MUST_PRODUCT_LABEL = 4; //秒杀活动商品 const TYPE_MUST_SECKILL_ACTIVE = 5; public $activeProductType = [1]; //使用范围对应的类型 public $typeData = [ self::TYPE_ALL => '', self::TYPE_MUST_PRODUCT => RelevanceRepository::SCOPE_TYPE_PRODUCT, self::TYPE_MUST_CATEGORY => RelevanceRepository::SCOPE_TYPE_CATEGORY, self::TYPE_MUST_STORE => RelevanceRepository::SCOPE_TYPE_STORE, self::TYPE_MUST_PRODUCT_LABEL => RelevanceRepository::SCOPE_TYPE_PRODUCT_LABEL, self::TYPE_MUST_SECKILL_ACTIVE => '', ]; /** * @var StoreActivityDao */ protected $dao; /** * StoreActivityDao constructor. * @param StoreActivityDao $dao */ public function __construct(StoreActivityDao $dao) { $this->dao = $dao; } public function getActiveScopeType($type = null) { $data = [ 1 => self::TYPE_MUST_SECKILL_ACTIVE, ]; return $type ? $data[$type] : $data; } public function getList($where, $page, $limit) { $query = $this->dao->search($where)->append(['time_status']); $count = $query->count(); $list = $query->page($page, $limit)->order('sort DESC,activity_id DESC')->select(); return compact('count', 'list'); } /** * 创建活动商品 的活动关联氛围图等 * @param $data 主要信息 * @param $type 商品类型 * @return mixed * @author Qinii * @day 2024/4/15 */ public function saveByType(array $data, int $type) { $createData = [ 'activity_name' => $data['activity_name'], 'start_time' => $data['start_time'], 'end_time' => $data['end_time'], 'pic' => $data['pic'], 'link_id' => $data['link_id'], 'activity_type' => $data['activity_type'], ]; if (!in_array($data['activity_type'], [self::ACTIVITY_TYPE_ATMOSPHERE,self::ACTIVITY_TYPE_BORDER])) throw new ValidateException('活动类型错误'); if (!in_array($type, $this->activeProductType)) throw new ValidateException('请选择指定商品'); if (count(array_filter($createData ?? [])) < 6) throw new ValidateException('缺少必传参数'); $scope_type = $this->getActiveScopeType($type); $res = $this->getSearch(['activity_type' => $createData['activity_type']]) ->where(['scope_type' => $scope_type, 'link_id' => $createData['link_id'],])->find(); try { if ($res) { $this->dao->update($res->activity_id,$createData); } else { $createData['scope_type'] = $scope_type; $createData['status'] = strtotime($createData['start_time']) <= time() ? 1 : 0; $createData['sort'] = 999; $createData['is_display'] = 0; $createData['is_show'] = 1; $this->createActivity($createData); } return true; }catch (Exception $e) { throw new ValidateException($e->getMessage()); } } /** * 创建活动 * @param data['activity_name'] 名称 * @param data['start_time'] 开始时间 * @param data['end_time'] 结束时间 * @param data['pic'] 活动图片 * @param data['is_show'] 是否显示 * @param data['status'] 是否在活动中 * @param data['sort'] 排序 * @param data['activity_type'] 活动类型 * @param data['is_display'] 是否展示活动 * @param data['link_id'] 关联ID * @param array $data * @param $extend * @param $func * @author Qinii * @day 2023/10/13 */ public function createActivity(array $data, $extend = null, $func = null) { $paramsData = $extend ? $this->getParams($data, $extend) : []; return Db::transaction(function () use ($data, $extend, $func, $paramsData) { $createData = $this->dao->create($data); if (isset($paramsData['ids']) && !empty($paramsData['ids'])) app()->make(RelevanceRepository::class)->createMany($createData->activity_id, $paramsData['ids'], $paramsData['type']); if ($func && function_exists($func)) $this->$func($createData, $extend); }); } /** * 整理关联参数 * @param $data * @param $extend * @return array * @author Qinii * @day 2023/10/13 */ public function getParams($data, $extend) { if (!$extend) return []; $res = []; $type = ''; switch ($data['scope_type']) { case self::TYPE_ALL; break; case self::TYPE_MUST_PRODUCT: if (!isset($extend['spu_ids']) || empty($extend['spu_ids'])) throw new ValidateException('请选择指定商品'); $res = app()->make(SpuRepository::class)->getSearch(['spu_ids' => $extend['spu_ids'], 'status' => 1])->column('spu_id'); $type = RelevanceRepository::SCOPE_TYPE_PRODUCT; break; case self::TYPE_MUST_CATEGORY: if (!isset($extend['cate_ids']) || empty($extend['cate_ids'])) throw new ValidateException('请选择指定商品分类'); $res = app()->make(StoreCategoryRepository::class)->getSearch(['ids' => $extend['cate_ids'], 'status' => 1])->column('store_category_id'); $type = RelevanceRepository::SCOPE_TYPE_CATEGORY; break; case self::TYPE_MUST_STORE: if (!isset($extend['mer_ids']) || empty($extend['mer_ids'])) throw new ValidateException('请选择指定商户'); $res = app()->make(MerchantRepository::class)->getSearch(['mer_ids' => $extend['mer_ids']])->column('mer_id'); $type = RelevanceRepository::SCOPE_TYPE_STORE; break; case self::TYPE_MUST_PRODUCT_LABEL: if (!isset($extend['label_ids']) || empty($extend['label_ids'])) throw new ValidateException('请选择指定商品标签'); $res = app()->make(ProductLabelRepository::class)->getSearch(['product_label_id' => $extend['label_ids']])->column('product_label_id'); $type = RelevanceRepository::SCOPE_TYPE_PRODUCT_LABEL; break; default: throw new ValidateException('缺少活动类型'); break; } $ids = array_unique($res); return compact('ids', 'type'); } public function updateActivity(int $id, array $data, $extend = null, $func = null) { $paramsData = $this->getParams($data, $extend); Db::transaction(function () use ($id, $data, $extend, $func, $paramsData) { $createData = $this->dao->update($id, $data); if (!empty($paramsData)) { app()->make(RelevanceRepository::class)->clear($id, $paramsData['type'], 'left_id'); if (isset($paramsData['ids']) && !empty($paramsData['ids'])) app()->make(RelevanceRepository::class)->createMany($id, $paramsData['ids'], $paramsData['type']); } if ($func && function_exists($func)) $this->$func($createData, $extend); }); } /** * TODO 详情 * @param $where * @param $page * @param $limit * @return array * @author Qinii * @day 2022/9/17 */ public function getAdminList($where, $page, $limit, array $with = []) { $where['is_display'] = 1; $query = $this->dao->search($where, $with)->order('sort DESC,activity_id DESC'); $count = $query->count(); $list = $query->page($page, $limit)->select()->append(['time_status']); return compact('count', 'list'); } /** * TODO 详情 * @param $id * @return array * @author Qinii * @day 2022/9/16 */ public function detail($id, $type = true) { $with = []; if ($type) $with[] = 'socpeData'; $data = $this->dao->getSearch([$this->dao->getPk() => $id])->with($with)->append(['time_status'])->find()->toArray(); if ($type) { try { $arr = array_column($data['socpeData'], 'right_id'); if ($data['scope_type'] == self::TYPE_MUST_CATEGORY) { $data['cate_ids'] = $arr; } else if ($data['scope_type'] == self::TYPE_MUST_STORE) { $data['mer_ids'] = $arr; } else if ($data['scope_type'] == self::TYPE_MUST_PRODUCT_LABEL) { $data['label_ids'] = $arr; } else { $data['spu_ids'] = $arr; } } catch (Exception $e) { } unset($data['socpeData']); } return $data; } /** * TODO 删除活动 * @param $id * @return mixed * @author Qinii * @day 2022/9/17 */ public function deleteActivity($id) { return Db::transaction(function () use ($id) { $this->dao->delete($id); app()->make(RelevanceRepository::class)->clear($id, [RelevanceRepository::SCOPE_TYPE_PRODUCT, RelevanceRepository::SCOPE_TYPE_STORE, RelevanceRepository::SCOPE_TYPE_CATEGORY], 'left_id'); Cache::tag('get_product')->clear(); }); } /** * 秒杀活动删除后删除边框 * @param $linkId * @param $scope_type * @param $activity_type * @author Qinii * @day 2024/5/10 */ public function deleteSeckll(int $linkId, $activity_type = 2,$type = 1) { $scope_type = $this->getActiveScopeType($type); $argc = $this->dao->search(['activity_type' => $activity_type]) ->where('link_id',$linkId) ->where('scope_type',$scope_type) ->find(); if ($argc) $this->deleteActivity($argc->activity_id); return ; } /** * 获取需要的商品 或 商品列表 所需要的活动图 * @param array $data * @param int $type * @return array * @author Qinii * @day 2024/4/16 */ public function getPic(array $data, int $type, $push_key = 'border_pic') { if (!$data) return []; $where = [ 'activity_type' => $type, 'status' => 1, 'is_show' => 1, 'gt_end_time' => date('Y-m-d H:i:s', time()) ]; $activeData = $this->dao->getSearch($where) ->setOption('field', []) ->field('activity_id,scope_type,activity_type,pic') ->order('scope_type DESC,sort DESC,create_time DESC')->limit(10)->select(); $onList = $data; $list = $data; if ($onList) { foreach ($activeData as $active) { if (!$onList) break; switch ($active['scope_type']) { case self::TYPE_ALL: $newList = array_map(function ($item) use ($active, $push_key) { $item[$push_key] = $active['pic']; return $item; }, $list); $list = $newList; $onList = []; return $list; break; case self::TYPE_MUST_PRODUCT: $field = 'spu_id'; break; case self::TYPE_MUST_CATEGORY: $field = 'cate_id'; break; case self::TYPE_MUST_STORE: $field = 'mer_id'; break; case self::TYPE_MUST_PRODUCT_LABEL: $field = 'sys_labels'; break; case self::TYPE_MUST_SECKILL_ACTIVE: $field = 'active_id'; break; } $this->activeProductAndList($list, $onList, $active, $field, $push_key); } } return $list; } /** * 根据当前的数组 , 获取所有活动是否存在符合的图片活动 * @param $active * @param $field * @param $list * @param $onList * @author Qinii * @day 2024/4/16 */ public function activeProductAndList(&$list, &$onList,$active,$field,$push_key) { $_type = $this->typeData[$active['scope_type']]; //获得所有商品的spuID $ids = array_column($onList, $field); $idss = array_unique($ids); if (count($idss) == 1 && !$idss[0]) return ; //以需求的字段为主键的数组 $funList = []; if ($ids && $onList) $funList = array_combine($ids, $onList); if ($field == 'active_id') { //获取交集ID $intersectId = $ids; } else { $relevanceRepository = app()->make(RelevanceRepository::class); $params = ['type' => $_type, 'left_id' => $active['activity_id']]; $rightIds = $relevanceRepository->getSearch($params)->whereIn('right_id', $ids)->select()->toArray(); $rightIds = array_column($rightIds,'right_id'); $intersectId = array_values(array_intersect($ids, $rightIds)); } //存在交集则有符合条件的商品 if (!empty($intersectId)) { $newList = array_map(function ($item) use ($intersectId, $active, $field, $push_key) { if ( ($field !== 'active_id' || $item['active_id'] !== 0) && in_array($item[$field], $intersectId) && !isset($item[$push_key]) ) { $item[$push_key] = $active['pic']; } return $item; }, $list); foreach ($intersectId as $spu_id) { unset($funList[$spu_id]); } $list = $newList; $onList = array_values($funList); } } /** * 弃用 * @param int $type * @param $spuId * @param $cateId * @param $merId * @param $labelId * @return array|mixed * @author Qinii * @day 2024/5/10 */ public function getActivityBySpu(int $type, $spuId, $cateId, $merId, $labelId) { $make = app()->make(RelevanceRepository::class); $list = $this->dao->getSearch(['activity_type' => $type, 'status' => 1, 'is_show' => 1, 'gt_end_time' => date('Y-m-d H:i:s', time())]) ->setOption('field', []) ->field('activity_id,scope_type,activity_type,pic') ->order('sort DESC,create_time DESC') ->select() ->toArray(); foreach ($list as $item) { switch ($item['scope_type']) { case self::TYPE_ALL: return $item; case self::TYPE_MUST_PRODUCT: $_type = RelevanceRepository::SCOPE_TYPE_PRODUCT; $right_id = $spuId ?: 0; break; case self::TYPE_MUST_CATEGORY: $_type = RelevanceRepository::SCOPE_TYPE_CATEGORY; $right_id = $cateId ?: 0; break; case self::TYPE_MUST_STORE: $_type = RelevanceRepository::SCOPE_TYPE_STORE; $right_id = $merId ?: 0; break; case self::TYPE_MUST_PRODUCT_LABEL: $_type = RelevanceRepository::SCOPE_TYPE_PRODUCT_LABEL; $right_id = $labelId ?: ''; break; } if (isset($_type)) { $res = $make->checkHas($item['activity_id'], $right_id, $_type); if ($res) return $item; } } return []; } public function wxQrcode(int $uid, StoreActivity $activity) { $name = md5('wxactform_i' . $uid . $activity['activity_id'] . date('Ymd')) . '.jpg'; $key = 'form_' . $activity['activity_id'] . '_' . $uid; return app()->make(QrcodeService::class)->getWechatQrcodePath($name, '/pages/activity/registrate_activity/index?id=' . $activity['activity_id'] . '&spid=' . $uid, false, $key); } public function mpQrcode(int $uid, StoreActivity $activity) { $name = md5('mpactform_i' . $uid . $activity['activity_id'] . date('Ymd')) . '.jpg'; return app()->make(QrcodeService::class)->getRoutineQrcodePath($name, 'pages/activity/registrate_activity/index', 'id=' . $activity['activity_id'] . 'spid=' . $uid); } /** * 验证活动状态 * @param StoreActivity|null $activity * @return true */ public function verifyActivityStatus(?StoreActivity $activity, $isCreate = false) { if (empty($activity)) { throw new ValidateException('活动数据异常'); } if (!$activity['is_show']) { throw new ValidateException('活动已被关闭'); } if ($isCreate) { if ($activity['status'] == -1) { throw new ValidateException('活动已结束'); } if ($activity['status'] == 0) { throw new ValidateException('活动未开始'); } //如果存在结束时间,则判断当前时间是否大于结束时间 $end_time = $activity['end_time'] ? (strtotime($activity['end_time']) <= time() ?: false) : false; if ($end_time) throw new ValidateException('活动已结束'); //如果没有结束时间 则判断总人数 if ($activity['count'] > 0 && $activity['count'] <= $activity['total']) throw new ValidateException('活动参与人数已满'); } return true; } public function verifyActivityData(int $uid, int $activity_id) { $formRelated = app()->make(StoreActivityRelatedRepository::class); $createData = [ 'uid' => $uid, 'activity_id' => $activity_id, 'activity_type' => $formRelated::ACTIVITY_TYPE_FORM, ]; return $formRelated->getSearch($createData)->value('id'); } }