StoreActivityRepository.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2022 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +---------------------------------------------------------------------
  11. namespace app\common\repositories\store;
  12. use app\common\dao\store\StoreActivityDao;
  13. use app\common\model\store\StoreActivity;
  14. use app\common\repositories\BaseRepository;
  15. use app\common\repositories\store\product\ProductLabelRepository;
  16. use app\common\repositories\store\product\SpuRepository;
  17. use app\common\repositories\system\merchant\MerchantRepository;
  18. use app\common\repositories\system\RelevanceRepository;
  19. use crmeb\services\QrcodeService;
  20. use Exception;
  21. use think\exception\ValidateException;
  22. use think\facade\Cache;
  23. use think\facade\Db;
  24. /**
  25. * @mixin StoreActivityDao
  26. */
  27. class StoreActivityRepository extends BaseRepository
  28. {
  29. //氛围图
  30. const ACTIVITY_TYPE_ATMOSPHERE = 1;
  31. //活动边框
  32. const ACTIVITY_TYPE_BORDER = 2;
  33. //报名活动
  34. const ACTIVITY_TYPE_FORM = 4;
  35. //指定范围类型
  36. //0全部商品
  37. const TYPE_ALL = 0;
  38. //指定商品
  39. const TYPE_MUST_PRODUCT = 1;
  40. //指定分类
  41. const TYPE_MUST_CATEGORY = 2;
  42. //指定商户
  43. const TYPE_MUST_STORE = 3;
  44. //指定商品标签
  45. const TYPE_MUST_PRODUCT_LABEL = 4;
  46. //秒杀活动商品
  47. const TYPE_MUST_SECKILL_ACTIVE = 5;
  48. public $activeProductType = [1];
  49. //使用范围对应的类型
  50. public $typeData = [
  51. self::TYPE_ALL => '',
  52. self::TYPE_MUST_PRODUCT => RelevanceRepository::SCOPE_TYPE_PRODUCT,
  53. self::TYPE_MUST_CATEGORY => RelevanceRepository::SCOPE_TYPE_CATEGORY,
  54. self::TYPE_MUST_STORE => RelevanceRepository::SCOPE_TYPE_STORE,
  55. self::TYPE_MUST_PRODUCT_LABEL => RelevanceRepository::SCOPE_TYPE_PRODUCT_LABEL,
  56. self::TYPE_MUST_SECKILL_ACTIVE => '',
  57. ];
  58. /**
  59. * @var StoreActivityDao
  60. */
  61. protected $dao;
  62. /**
  63. * StoreActivityDao constructor.
  64. * @param StoreActivityDao $dao
  65. */
  66. public function __construct(StoreActivityDao $dao)
  67. {
  68. $this->dao = $dao;
  69. }
  70. /**
  71. * 获取活动范围类型
  72. *
  73. * 此方法用于根据传入的类型参数返回相应的活动范围类型。如果没有指定类型参数,
  74. * 则返回所有活动范围类型的映射数组。这个方法主要用于内部逻辑,以确定活动的范围和类型。
  75. *
  76. * @param null $type 活动的类型标识,如果为null,则返回所有类型。
  77. * @return array|mixed 如果$type有值,返回对应的活动范围类型;否则返回所有类型的整体映射。
  78. */
  79. public function getActiveScopeType($type = null)
  80. {
  81. // 定义活动范围类型的映射
  82. $data = [
  83. 1 => self::TYPE_MUST_SECKILL_ACTIVE,
  84. ];
  85. // 根据$type是否有值,返回相应的结果
  86. return $type ? $data[$type] : $data;
  87. }
  88. /**
  89. * 获取活动列表
  90. *
  91. * 根据给定的条件和分页信息,从数据库中检索活动列表。此方法主要用于处理数据的查询和分页逻辑。
  92. *
  93. * @param string $where 查询条件,用于筛选活动。这是一个SQL WHERE子句的字符串表示。
  94. * @param int $page 当前页码,用于指定要返回的页码。
  95. * @param int $limit 每页的记录数,用于指定每页返回的活动数量。
  96. * @return array 返回一个包含两个元素的数组,'count'表示活动的总数量,'list'表示当前页的活动列表。
  97. */
  98. public function getList($where, $page, $limit)
  99. {
  100. // 构建查询语句,根据$where条件搜索,并附加'time_status'字段
  101. $query = $this->dao->search($where)->append(['time_status']);
  102. // 计算满足条件的活动总数
  103. $count = $query->count();
  104. // 对查询结果进行分页,根据'sort'和'activity_id'排序,并返回当前页的活动列表
  105. $list = $query->page($page, $limit)->order('sort DESC,activity_id DESC')->select();
  106. // 初始化三个数组,分别用于存放未开始、正在进行和已结束的活动列表
  107. $noStart = []; // 未开始的活动列表
  108. $starting = []; // 正在进行的活动列表
  109. $ended = []; // 已结束的活动列表
  110. $dateTime = date('Y-m-d H:i:s');
  111. foreach($list as $item) {
  112. if($dateTime < $item['start_time']) {
  113. $noStart[] = $item;
  114. }
  115. if($dateTime > $item['start_time'] && $dateTime < $item['end_time']) {
  116. $starting[] = $item;
  117. }
  118. if($dateTime > $item['end_time']) {
  119. $ended[] = $item;
  120. }
  121. }
  122. // 将活动列表按照时间顺序重新排序(正在进行的活动在前,未开始和已结束的在后)
  123. $list = array_merge($starting, $noStart, $ended);
  124. // 将活动总数和列表一起返回
  125. return compact('count', 'list');
  126. }
  127. /**
  128. * 创建活动商品 的活动关联氛围图等
  129. * @param $data 主要信息
  130. * @param $type 商品类型
  131. * @return mixed
  132. * @author Qinii
  133. * @day 2024/4/15
  134. */
  135. public function saveByType(array $data, int $type)
  136. {
  137. $createData = [
  138. 'activity_name' => $data['activity_name'],
  139. 'start_time' => $data['start_time'],
  140. 'end_time' => $data['end_time'],
  141. 'pic' => $data['pic'],
  142. 'link_id' => $data['link_id'],
  143. 'activity_type' => $data['activity_type'],
  144. ];
  145. if (!in_array($data['activity_type'], [self::ACTIVITY_TYPE_ATMOSPHERE,self::ACTIVITY_TYPE_BORDER]))
  146. throw new ValidateException('活动类型错误');
  147. if (!in_array($type, $this->activeProductType))
  148. throw new ValidateException('请选择指定商品');
  149. if (count(array_filter($createData ?? [])) < 6)
  150. throw new ValidateException('缺少必传参数');
  151. $scope_type = $this->getActiveScopeType($type);
  152. $res = $this->getSearch(['activity_type' => $createData['activity_type']])
  153. ->where(['scope_type' => $scope_type, 'link_id' => $createData['link_id'],])->find();
  154. try {
  155. if ($res) {
  156. $this->dao->update($res->activity_id,$createData);
  157. } else {
  158. $createData['scope_type'] = $scope_type;
  159. $createData['status'] = strtotime($createData['start_time']) <= time() ? 1 : 0;
  160. $createData['sort'] = 999;
  161. $createData['is_display'] = 0;
  162. $createData['is_show'] = 1;
  163. $this->createActivity($createData);
  164. }
  165. return true;
  166. }catch (Exception $e) {
  167. throw new ValidateException($e->getMessage());
  168. }
  169. }
  170. /**
  171. * 创建活动
  172. * @param data['activity_name'] 名称
  173. * @param data['start_time'] 开始时间
  174. * @param data['end_time'] 结束时间
  175. * @param data['pic'] 活动图片
  176. * @param data['is_show'] 是否显示
  177. * @param data['status'] 是否在活动中
  178. * @param data['sort'] 排序
  179. * @param data['activity_type'] 活动类型
  180. * @param data['is_display'] 是否展示活动
  181. * @param data['link_id'] 关联ID
  182. * @param array $data
  183. * @param $extend
  184. * @param $func
  185. * @author Qinii
  186. * @day 2023/10/13
  187. */
  188. public function createActivity(array $data, $extend = null, $func = null)
  189. {
  190. $paramsData = $extend ? $this->getParams($data, $extend) : [];
  191. return Db::transaction(function () use ($data, $extend, $func, $paramsData) {
  192. $createData = $this->dao->create($data);
  193. if (isset($paramsData['ids']) && !empty($paramsData['ids']))
  194. app()->make(RelevanceRepository::class)->createMany($createData->activity_id, $paramsData['ids'], $paramsData['type']);
  195. if ($func && function_exists($func)) $this->$func($createData, $extend);
  196. });
  197. }
  198. /**
  199. * 整理关联参数
  200. * @param $data
  201. * @param $extend
  202. * @return array
  203. * @author Qinii
  204. * @day 2023/10/13
  205. */
  206. public function getParams($data, $extend)
  207. {
  208. if (!$extend) return [];
  209. $res = [];
  210. $type = '';
  211. switch ($data['scope_type']) {
  212. case self::TYPE_ALL;
  213. break;
  214. case self::TYPE_MUST_PRODUCT:
  215. if (!isset($extend['spu_ids']) || empty($extend['spu_ids']))
  216. throw new ValidateException('请选择指定商品');
  217. $res = app()->make(SpuRepository::class)->getSearch(['spu_ids' => $extend['spu_ids'], 'status' => 1])->column('spu_id');
  218. $type = RelevanceRepository::SCOPE_TYPE_PRODUCT;
  219. break;
  220. case self::TYPE_MUST_CATEGORY:
  221. if (!isset($extend['cate_ids']) || empty($extend['cate_ids']))
  222. throw new ValidateException('请选择指定商品分类');
  223. $res = app()->make(StoreCategoryRepository::class)->getSearch(['ids' => $extend['cate_ids'], 'status' => 1])->column('store_category_id');
  224. $type = RelevanceRepository::SCOPE_TYPE_CATEGORY;
  225. break;
  226. case self::TYPE_MUST_STORE:
  227. if (!isset($extend['mer_ids']) || empty($extend['mer_ids']))
  228. throw new ValidateException('请选择指定商户');
  229. $res = app()->make(MerchantRepository::class)->getSearch(['mer_ids' => $extend['mer_ids']])->column('mer_id');
  230. $type = RelevanceRepository::SCOPE_TYPE_STORE;
  231. break;
  232. case self::TYPE_MUST_PRODUCT_LABEL:
  233. if (!isset($extend['label_ids']) || empty($extend['label_ids']))
  234. throw new ValidateException('请选择指定商品标签');
  235. $res = app()->make(ProductLabelRepository::class)->getSearch(['product_label_id' => $extend['label_ids']])->column('product_label_id');
  236. $type = RelevanceRepository::SCOPE_TYPE_PRODUCT_LABEL;
  237. break;
  238. default:
  239. throw new ValidateException('缺少活动类型');
  240. break;
  241. }
  242. $ids = array_unique($res);
  243. return compact('ids', 'type');
  244. }
  245. /**
  246. * 更新活动信息,并处理相关的扩展数据。
  247. *
  248. * 本函数用于更新指定ID的活动数据,并根据传入的扩展数据进行相关的关联操作。
  249. * 如有需要,还可以执行额外的自定义函数。
  250. *
  251. * @param int $id 活动的唯一标识ID。
  252. * @param array $data 需要更新的活动数据数组。
  253. * @param mixed $extend 扩展数据,可以是数组或者null,用于更新关联数据。
  254. * @param callable|null $func 自定义函数,如果传入则会在更新完成后调用。
  255. */
  256. public function updateActivity(int $id, array $data, $extend = null, $func = null)
  257. {
  258. // 获取参数数据,包括直接传入的数据和扩展数据。
  259. $paramsData = $this->getParams($data, $extend);
  260. // 使用数据库事务来确保更新操作的原子性。
  261. Db::transaction(function () use ($id, $data, $extend, $func, $paramsData) {
  262. // 更新活动的基本信息。
  263. $createData = $this->dao->update($id, $data);
  264. // 如果有扩展参数数据,则处理关联数据。
  265. if (!empty($paramsData)) {
  266. // 清除旧的关联数据。
  267. app()->make(RelevanceRepository::class)->clear($id, $paramsData['type'], 'left_id');
  268. // 根据新的关联ID创建新的关联数据。
  269. if (isset($paramsData['ids']) && !empty($paramsData['ids'])) {
  270. app()->make(RelevanceRepository::class)->createMany($id, $paramsData['ids'], $paramsData['type']);
  271. }
  272. }
  273. // 如果传入了自定义函数,并且该函数存在,则调用它。
  274. if ($func && function_exists($func)) {
  275. $this->$func($createData, $extend);
  276. }
  277. });
  278. }
  279. /**
  280. * 详情
  281. * @param $where
  282. * @param $page
  283. * @param $limit
  284. * @return array
  285. * @author Qinii
  286. * @day 2022/9/17
  287. */
  288. public function getAdminList($where, $page, $limit, array $with = [])
  289. {
  290. $where['is_display'] = 1;
  291. $query = $this->dao->search($where, $with)->order('sort DESC,activity_id DESC');
  292. $count = $query->count();
  293. $list = $query->page($page, $limit)->select()->append(['time_status']);
  294. return compact('count', 'list');
  295. }
  296. /**
  297. * 详情
  298. * @param $id
  299. * @return array
  300. * @author Qinii
  301. * @day 2022/9/16
  302. */
  303. public function detail($id, $type = true)
  304. {
  305. $with = [];
  306. if ($type) $with[] = 'socpeData';
  307. $data = $this->dao->getSearch([$this->dao->getPk() => $id])->with($with)->append(['time_status'])->find()->toArray();
  308. if ($type) {
  309. try {
  310. $arr = array_column($data['socpeData'], 'right_id');
  311. if ($data['scope_type'] == self::TYPE_MUST_CATEGORY) {
  312. $data['cate_ids'] = $arr;
  313. } else if ($data['scope_type'] == self::TYPE_MUST_STORE) {
  314. $data['mer_ids'] = $arr;
  315. } else if ($data['scope_type'] == self::TYPE_MUST_PRODUCT_LABEL) {
  316. $data['label_ids'] = $arr;
  317. } else {
  318. $data['spu_ids'] = $arr;
  319. }
  320. } catch (Exception $e) {
  321. }
  322. unset($data['socpeData']);
  323. }
  324. return $data;
  325. }
  326. /**
  327. * 删除活动
  328. * @param $id
  329. * @return mixed
  330. * @author Qinii
  331. * @day 2022/9/17
  332. */
  333. public function deleteActivity($id)
  334. {
  335. return Db::transaction(function () use ($id) {
  336. $this->dao->delete($id);
  337. app()->make(RelevanceRepository::class)->clear($id, [RelevanceRepository::SCOPE_TYPE_PRODUCT, RelevanceRepository::SCOPE_TYPE_STORE, RelevanceRepository::SCOPE_TYPE_CATEGORY], 'left_id');
  338. Cache::tag('get_product')->clear();
  339. });
  340. }
  341. /**
  342. * 秒杀活动删除后删除边框
  343. * @param $linkId
  344. * @param $scope_type
  345. * @param $activity_type
  346. * @author Qinii
  347. * @day 2024/5/10
  348. */
  349. public function deleteSeckll(int $linkId, $activity_type = 2,$type = 1)
  350. {
  351. $scope_type = $this->getActiveScopeType($type);
  352. $argc = $this->dao->search(['activity_type' => $activity_type])
  353. ->where('link_id',$linkId)
  354. ->where('scope_type',$scope_type)
  355. ->find();
  356. if ($argc) $this->deleteActivity($argc->activity_id);
  357. return ;
  358. }
  359. /**
  360. * 获取需要的商品 或 商品列表 所需要的活动图
  361. * @param array $data
  362. * @param int $type
  363. * @return array
  364. * @author Qinii
  365. * @day 2024/4/16
  366. */
  367. public function getPic(array $data, int $type, $push_key = 'border_pic')
  368. {
  369. if (!$data) return [];
  370. $where = [
  371. 'activity_type' => $type,
  372. 'status' => 1,
  373. 'is_show' => 1,
  374. 'gt_end_time' => date('Y-m-d H:i:s', time())
  375. ];
  376. $activeData = $this->dao->getSearch($where)
  377. ->setOption('field', [])
  378. ->field('activity_id,scope_type,activity_type,pic')
  379. ->order('scope_type DESC,sort DESC,create_time DESC')->limit(10)->select()->toArray();
  380. $onList = $data;
  381. $list = $data;
  382. if ($onList) {
  383. foreach ($activeData as $active) {
  384. if (!$onList) break;
  385. switch ($active['scope_type']) {
  386. case self::TYPE_ALL:
  387. $newList = array_map(function ($item) use ($active, $push_key) {
  388. $item[$push_key] = $active['pic'];
  389. return $item;
  390. }, $list);
  391. $list = $newList;
  392. $onList = [];
  393. return $list;
  394. break;
  395. case self::TYPE_MUST_PRODUCT:
  396. $field = 'spu_id';
  397. break;
  398. case self::TYPE_MUST_CATEGORY:
  399. $field = 'cate_id';
  400. break;
  401. case self::TYPE_MUST_STORE:
  402. $field = 'mer_id';
  403. break;
  404. case self::TYPE_MUST_PRODUCT_LABEL:
  405. $field = 'sys_labels';
  406. break;
  407. case self::TYPE_MUST_SECKILL_ACTIVE:
  408. $field = 'active_id';
  409. break;
  410. }
  411. $this->activeProductAndList($list, $onList, $active, $field, $push_key);
  412. }
  413. }
  414. return $list;
  415. }
  416. /**
  417. * 根据当前的数组 , 获取所有活动是否存在符合的图片活动
  418. * @param $active
  419. * @param $field
  420. * @param $list
  421. * @param $onList
  422. * @author Qinii
  423. * @day 2024/4/16
  424. */
  425. public function activeProductAndList(&$list, &$onList,$active,$field,$push_key)
  426. {
  427. $_type = $this->typeData[$active['scope_type']];
  428. //获得所有商品的spuID
  429. $ids = array_column($onList, $field);
  430. $idss = array_unique($ids);
  431. if (count($idss) == 1 && !$idss[0]) return ;
  432. //以需求的字段为主键的数组
  433. $funList = [];
  434. if ($ids && $onList) $funList = array_combine($ids, $onList);
  435. if ($field == 'active_id') {
  436. //获取交集ID
  437. $intersectId = $ids;
  438. } else {
  439. $relevanceRepository = app()->make(RelevanceRepository::class);
  440. $params = ['type' => $_type, 'left_id' => $active['activity_id']];
  441. $rightIds = $relevanceRepository->getSearch($params)->whereIn('right_id', $ids)->select()->toArray();
  442. $rightIds = array_column($rightIds,'right_id');
  443. $intersectId = array_values(array_intersect($ids, $rightIds));
  444. }
  445. //存在交集则有符合条件的商品
  446. if (!empty($intersectId)) {
  447. $newList = array_map(function ($item) use ($intersectId, $active, $field, $push_key) {
  448. if (
  449. ($field !== 'active_id' || $item['active_id'] !== 0) &&
  450. in_array($item[$field], $intersectId) && !isset($item[$push_key])
  451. ) {
  452. $item[$push_key] = $active['pic'];
  453. }
  454. return $item;
  455. }, $list);
  456. foreach ($intersectId as $spu_id) {
  457. unset($funList[$spu_id]);
  458. }
  459. $list = $newList;
  460. $onList = array_values($funList);
  461. }
  462. }
  463. /**
  464. * 弃用
  465. * @param int $type
  466. * @param $spuId
  467. * @param $cateId
  468. * @param $merId
  469. * @param $labelId
  470. * @return array|mixed
  471. * @author Qinii
  472. * @day 2024/5/10
  473. */
  474. public function getActivityBySpu(int $type, $spuId, $cateId, $merId, $labelId)
  475. {
  476. $make = app()->make(RelevanceRepository::class);
  477. $list = $this->dao->getSearch(['activity_type' => $type, 'status' => 1, 'is_show' => 1, 'gt_end_time' => date('Y-m-d H:i:s', time())])
  478. ->setOption('field', [])
  479. ->field('activity_id,scope_type,activity_type,pic')
  480. ->order('sort DESC,create_time DESC')
  481. ->select()
  482. ->toArray();
  483. foreach ($list as $item) {
  484. switch ($item['scope_type']) {
  485. case self::TYPE_ALL:
  486. return $item;
  487. case self::TYPE_MUST_PRODUCT:
  488. $_type = RelevanceRepository::SCOPE_TYPE_PRODUCT;
  489. $right_id = $spuId ?: 0;
  490. break;
  491. case self::TYPE_MUST_CATEGORY:
  492. $_type = RelevanceRepository::SCOPE_TYPE_CATEGORY;
  493. $right_id = $cateId ?: 0;
  494. break;
  495. case self::TYPE_MUST_STORE:
  496. $_type = RelevanceRepository::SCOPE_TYPE_STORE;
  497. $right_id = $merId ?: 0;
  498. break;
  499. case self::TYPE_MUST_PRODUCT_LABEL:
  500. $_type = RelevanceRepository::SCOPE_TYPE_PRODUCT_LABEL;
  501. $right_id = $labelId ?: '';
  502. break;
  503. }
  504. if (isset($_type)) {
  505. $res = $make->checkHas($item['activity_id'], $right_id, $_type);
  506. if ($res) return $item;
  507. }
  508. }
  509. return [];
  510. }
  511. /**
  512. * 生成微信活动二维码
  513. *
  514. * 该方法用于生成与特定微信活动和用户关联的二维码。二维码的内容包含了活动的ID和用户的ID,
  515. * 用于在微信小程序中识别和引导用户参加特定活动。
  516. *
  517. * @param int $uid 用户ID,用于生成唯一标识并关联到二维码
  518. * @param StoreActivity $activity 活动对象,包含活动的相关信息,如活动ID
  519. * @return string 返回生成的微信活动二维码的路径
  520. */
  521. public function wxQrcode(int $uid, StoreActivity $activity)
  522. {
  523. // 生成二维码文件名,基于用户ID、活动ID和当前日期,确保唯一性
  524. $name = md5('wxactform_i' . $uid . $activity['activity_id'] . date('Ymd')) . '.jpg';
  525. // 构建二维码的key值,用于存储和检索
  526. $key = 'form_' . $activity['activity_id'] . '_' . $uid;
  527. // 调用二维码服务类,生成微信小程序二维码,并返回二维码的路径
  528. // 参数包括二维码文件名、二维码指向的URL、是否使用代理以及存储的key
  529. return app()->make(QrcodeService::class)->getWechatQrcodePath($name, '/pages/activity/registrate_activity/index?id=' . $activity['activity_id'] . '&spid=' . $uid, false, $key);
  530. }
  531. /**
  532. * 生成微页面二维码
  533. *
  534. * 该方法用于生成特定活动的微页面二维码,供用户扫码报名参加活动。二维码的生成基于用户的UID和活动ID,
  535. * 通过MD5加密生成唯一的名字,确保每个用户的活动二维码都是唯一的。
  536. *
  537. * @param int $uid 用户ID,用于生成唯一二维码名称的一部分。
  538. * @param StoreActivity $activity 活动对象,包含活动相关信息,如活动ID,用于生成二维码链接。
  539. * @return string 返回生成的二维码路径,供后续展示或下载使用。
  540. */
  541. public function mpQrcode(int $uid, StoreActivity $activity)
  542. {
  543. // 生成二维码文件名,包含UID、活动ID和当前日期,确保唯一性,并指定文件类型为jpg。
  544. $name = md5('mpactform_i' . $uid . $activity['activity_id'] . date('Ymd')) . '.jpg';
  545. // 调用二维码服务类,生成小程序二维码,指定二维码路径、目标页面和参数。
  546. // 这里的参数用于在打开小程序页面时传递活动ID和用户ID,用于识别和绑定用户活动关系。
  547. return app()->make(QrcodeService::class)->getRoutineQrcodePath($name, 'pages/activity/registrate_activity/index', 'id=' . $activity['activity_id'] . 'spid=' . $uid);
  548. }
  549. /**
  550. * 验证活动状态
  551. * @param StoreActivity|null $activity
  552. * @return true
  553. */
  554. public function verifyActivityStatus(?StoreActivity $activity, $isCreate = false)
  555. {
  556. if (empty($activity)) {
  557. throw new ValidateException('活动数据异常');
  558. }
  559. if (!$activity['is_show']) {
  560. throw new ValidateException('活动已被关闭');
  561. }
  562. if ($isCreate) {
  563. if ($activity['status'] == -1) {
  564. throw new ValidateException('活动已结束');
  565. }
  566. if ($activity['status'] == 0) {
  567. throw new ValidateException('活动未开始');
  568. }
  569. //如果存在结束时间,则判断当前时间是否大于结束时间
  570. $end_time = $activity['end_time'] ? (strtotime($activity['end_time']) <= time() ?: false) : false;
  571. if ($end_time)
  572. throw new ValidateException('活动已结束');
  573. //如果没有结束时间 则判断总人数
  574. if ($activity['count'] > 0 && $activity['count'] <= $activity['total'])
  575. throw new ValidateException('活动参与人数已满');
  576. }
  577. return true;
  578. }
  579. /**
  580. * 验证活动数据是否存在
  581. *
  582. * 本函数用于检查给定的用户ID和活动ID对应的活动数据是否已在系统中创建。
  583. * 主要用于确保用户参与的活动是有效的,防止非法或不存在的活动请求。
  584. *
  585. * @param int $uid 用户ID,表示参与活动的用户的身份。
  586. * @param int $activity_id 活动ID,表示用户参与的具体活动。
  587. * @return int 返回活动记录的ID,如果活动数据存在;如果不存在,则返回0或其他表示失败的值。
  588. */
  589. public function verifyActivityData(int $uid, int $activity_id)
  590. {
  591. // 实例化存储活动关联仓库类,用于后续查询活动数据。
  592. $formRelated = app()->make(StoreActivityRelatedRepository::class);
  593. // 准备查询条件,包括用户ID、活动ID和活动类型。
  594. $createData = [
  595. 'uid' => $uid,
  596. 'activity_id' => $activity_id,
  597. 'activity_type' => $formRelated::ACTIVITY_TYPE_FORM,
  598. ];
  599. // 执行查询并返回活动ID,如果活动数据存在。
  600. return $formRelated->getSearch($createData)->value('id');
  601. }
  602. }