526 lines
20 KiB
PHP
526 lines
20 KiB
PHP
<?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');
|
||
}
|
||
}
|