zx/app/common/repositories/store/StoreActivityRepository.php

526 lines
20 KiB
PHP
Raw Permalink Normal View History

2024-07-02 15:32:59 +08:00
<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +---------------------------------------------------------------------
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');
}
}