| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810 |
- <?php
- namespace App\Repositories;
- use App\Constants\ChangeLogConstant;
- use App\Constants\CoinsConstant;
- use App\Constants\CreatorConstant;
- use App\Events\User\CreatorApplyEvent;
- use App\Exception\ApiException;
- use App\Jobs\SendMessageToUserJob;
- use App\Model\ChangeLogModel;
- use App\Model\CreatorModel;
- use App\Model\TypeModel;
- use App\Model\UserBuyVideoModel;
- use App\Model\UserModel;
- use App\Model\VideoModel;
- use App\Repositories\Service\QueueService;
- use App\Repositories\Utils\M3u8CacheRepository;
- use Carbon\Carbon;
- use Hyperf\Database\Model\Builder;
- use Hyperf\DbConnection\Db;
- use Hyperf\Redis\Redis;
- use KZ2\Repositories\Model\Repository;
- use Psr\SimpleCache\CacheInterface;
- class CreatorRepository extends Repository
- {
- public function model()
- {
- return CreatorModel::class;
- }
- /**
- * 详情.
- * @param $userCode
- * @param mixed $columns
- * @return Builder|\Hyperf\Database\Model\Model|object|null
- */
- public function detail($userCode, $columns = ['*'])
- {
- return CreatorModel::query()->with(['user'])->where(['user_uid' => $userCode])->first($columns);
- }
- /**
- * 统计某人已经发布上架的视频个数.
- * @param $userCode
- * @return int
- */
- public function countPublishedVideo($userCode)
- {
- return VideoModel::query()->where(['uid' => $userCode, 'status' => 1])->count();
- }
- /**
- * 统计某人今日已经发布任何状态视频个数.
- * @param $userCode
- * @return int
- */
- public function countTodayPublishedVideo($userCode)
- {
- $todayDate = Carbon::now()->startOfDay()->toDateTimeString();
- return VideoModel::query()->where(['uid' => $userCode])->where('created_at', '>', $todayDate)->count();
- }
- /**
- * 计算某人的点赞数.
- * @param $userCode
- * @return int|mixed|string|void
- */
- public function sumLikedVideo($userCode)
- {
- return VideoModel::query()->where(['uid' => $userCode, 'status' => 1])->sum('like');
- }
- /**
- * 申请审核.
- * @param $userCode
- * @return Builder|\Hyperf\Database\Model\Model
- */
- public function applyToUncheck($userCode) {
- $initLevel = 0;
- $creatorObj = CreatorModel::query()->where(['user_uid' => $userCode])->first();
- if (empty($creatorObj)) {
- $setarr = [
- 'user_uid' => $userCode,
- 'is_bot' => 0,
- 'level' => $initLevel,
- 'income' => 0,
- ];
- $creatorObj = CreatorModel::query()->create($setarr);
- // 清除缓存.
- $this->clearCountCreatorCache();
- /*
- $userObj = UserModel::query()->where(['code' => $userCode])->first(['id', 'code', 'creator_level']);
- if (!empty($userObj)) {
- $userObj->creator_level = $initLevel;
- $userObj->save();
- make(UserRepository::class)->delUserCache($userCode);
- }
- */
- $eventParams = [
- 'user_code' => $userCode,
- ];
- dispatch_event(new CreatorApplyEvent($eventParams));
- return $creatorObj;
- } else {
- throw new ApiException('已经是创作者了');
- }
- }
- /**
- * 上传的不同类型状态视频分页.
- * @param string $userCode
- * @param string $statusType
- * @param int $page
- * @param int $pageSize
- * @return \Hyperf\Contract\LengthAwarePaginatorInterface
- */
- public function videoPages(string $userCode, string $statusType, int $page = 1, int $pageSize = 10)
- {
- $columns = ['id', 'title', 'cover', 'status', 'coins', 'smu', 'mu', 'like', 'check', 'pay_type', 'duration', 'player_type', 'watch', 'tags', 'reject_reason', 'created_at'];
- $conditions = [
- 'uid' => $userCode,
- ];
- // TODO 后期视频量大了,需要追加字段索引,注意最左原则.
- $model = VideoModel::query();
- if ($statusType == 'up') {
- $conditions['status'] = 1;
- $conditions['check'] = 1;
- $model = $model->where($conditions);
- } elseif ($statusType == 'down') {
- $conditions['status'] = 2;
- $conditions['check'] = 1;
- $model = $model->where($conditions);
- } elseif ($statusType == 'check') {
- $model = $model->where($conditions)->where('check', '!=', 1);
- }
- $lists = $model->orderBy('created_at', 'DESC')->paginate($pageSize, $columns, 'page', $page);
- return $lists;
- }
- /**
- * 检查条件,并升级.
- * @param string $userCode
- * @param null $rules
- * @return bool
- */
- public function checkAndUpgrade($userCode, $rules = null)
- {
- if (empty($rules)) {
- $ruleRepo = make(CreatorRuleRepository::class);
- $rules = $ruleRepo->getRules();
- }
- if (empty($rules)) {
- logger('CreatorRepository-checkAndUpgrade', ['msg' => '系统数据库缺少定义规则,或者缓存失效']);
- return false;
- }
- $detail = CreatorModel::query()->where(['user_uid' => $userCode])->first();
- if (empty($detail)) {
- return false;
- }
- $level = intval($detail->level);
- $nextLevel = $level + 1;
- $isUpgrade = false; // 是否满足条件升级.
- $maxLevel = 0;
- $maxCoins = 999999999; // 最大的金币要求.
- $nextCoins = 999999999; // 下一级要求的金币.
- foreach ($rules as $v) {
- if ($v['level'] > $maxLevel) {
- $maxLevel = intval($v['level']);
- }
- if ($v['lowest_coin'] > $maxCoins) {
- $maxCoins = intval($v['lowest_coin']);
- }
- if ($nextLevel == $v['level']) {
- $nextCoins = $v['lowest_coin'];
- }
- }
- $currCoins = $detail->total_coin; // 当前这个用户的佣金金币
- if ($currCoins >= $nextCoins && $level < $maxLevel && $level > 0) {
- // 满足升级条件:未达到顶级且累计金币超过条件
- $isUpgrade = true;
- }
- if ($isUpgrade === true) {
- $nextLevel = $level + 1;
- Db::transaction(function () use ($userCode, $detail, $nextLevel) {
- // 有变动则升级
- $userObj = UserModel::query()->where(['code' => $userCode])->first(['id', 'code', 'creator_level']);
- $detail->level = $nextLevel;
- $detail->save();
- $userObj->creator_level = $nextLevel;
- $userObj->save();
- });
- $msgSubjct = '恭喜您,创作者等级从Lv'. strval($level) . '升级到Lv'. strval($nextLevel);
- $msgContent = '坚持每天发布您的作品,就能成为最有钱人.';
- $jobParams = [
- 'from_type' => 'sys',
- 'receive_uid' => $userCode,
- 'subject' => $msgSubjct,
- 'content' => $msgContent,
- ];
- // 异步发送通知站内消息
- dispatch_job(new SendMessageToUserJob($jobParams));
- }
- return $isUpgrade;
- }
- /**
- * 检查升级0-1.
- * @param $creatorObj
- * @return bool
- */
- public function checkUpgrade0to1($creatorObj)
- {
- if ($creatorObj->level != 0 || empty($creatorObj)) {
- return false;
- }
- $totalVideo = $this->countPublishedVideo($creatorObj->user_uid);
- if ($totalVideo >= CreatorConstant::LEVEL0_1_VIDEO_NUM) {
- $nextLevel = 1;
- $creatorObj->level = $nextLevel;
- $saveStatus = $creatorObj->save();
- if ($saveStatus) {
- $userObj = UserModel::query()->where(['code' => $creatorObj->user_uid])->first(['id', 'code', 'creator_level']);
- if (!empty($userObj)) {
- $userObj->creator_level = $nextLevel;
- $userObj->save();
- make(UserRepository::class)->delUserCache($creatorObj->user_uid);
- $msgSubjct = '恭喜您成为创作者.';
- $msgContent = '坚持每天发布您的作品,就能成为最有钱人.';
- $jobParams = [
- 'from_type' => 'sys',
- 'receive_uid' => $creatorObj->user_uid,
- 'subject' => $msgSubjct,
- 'content' => $msgContent,
- ];
- // 异步发送通知站内消息
- dispatch_job(new SendMessageToUserJob($jobParams));
- return true;
- }
- }
- }
- return false;
- }
- /**
- * 奖励创作者(视频).
- * @param $videoId
- * @param string $buyerUid 买家
- * @return bool
- */
- public function handleAwardBuyVideo($videoId, $buyerUid)
- {
- $videoObj = VideoModel::query()->where(['id' => $videoId])->first();
- if (empty($videoObj)) {
- return false;
- }
- $buyerObj = UserModel::query()->where(['code' => $buyerUid])->first();
- if (empty($buyerObj)) {
- return false;
- }
- $creatorUid = $videoObj->uid;
- if (empty($creatorUid)) {
- return false;
- }
- $creatorObj = CreatorModel::query()->where(['user_uid' => $creatorUid])->first();
- if (empty($creatorObj)) {
- return false;
- }
- if (boolval($creatorObj->is_bot)) {
- return false;
- }
- $videoCoins = $videoObj->coins;
- if ($videoCoins <= 0) {
- // 金币小于等于0的,直接不奖励,也不做任何记录.
- logger('handleAwardBuyVideo-fail', ['msg' => '金币小于等于0的,直接不奖励,也不做任何记录.']);
- return false;
- }
- if ($videoObj->pay_type != 2) {
- // 非金币类视频,不奖励
- logger('handleAwardBuyVideo-fail', ['msg' => '非金币类视频,不奖励']);
- return false;
- }
- $userObj = UserModel::query()->where(['code' => $creatorUid])->first();
- $oldUserObj = clone $userObj;
- $oldCreatorObj = clone $creatorObj;
- $level = $creatorObj->level;
- $ruleRepo = make(CreatorRuleRepository::class);
- $allRules = $ruleRepo->getRules();
- $levelRule = $ruleRepo->getRuleByLevel($level);
- if (empty($levelRule)) {
- // 无规则不奖励.
- logger('handleAwardBuyVideo-fail', ['msg' => '无规则不奖励.']);
- return false;
- }
- $commissionRatio = intval($levelRule->commission_ratio); // 分成比例.
- if ($commissionRatio > 100) {
- // 分成比例不能大于100,出现大于100的情况,应该是人为编辑出错,直接跳过.
- logger('handleAwardBuyVideo-fail', ['msg' => '分成比例不能大于100,出现大于100的情况,应该是人为编辑出错,直接跳过.']);
- return false;
- }
- if ($commissionRatio <= 0) {
- // 无分成,直接跳过.
- logger('handleAwardBuyVideo-fail', ['msg' => '无分成,直接跳过.']);
- return false;
- }
- $awardCoins = floatval(number_format($videoCoins * ($commissionRatio / 100), 2)); // 计算实际获得奖励金币个数, 也是舍掉小数后3位
- $awardMoney = floatval(number_format($awardCoins / CoinsConstant::RATE_RMB2COIN, 2)); // 保留2位小数, 也是舍掉小数后3位
- // $creatorObj->income += $awardMoney; // 当前收入,单位元
- Db::beginTransaction();
- try {
- $creatorObj->total_coin += $awardCoins; //累计金币数
- $creatorObj->total_income += $awardMoney; //累计收入,单位元.
- $saveStatus1 = $creatorObj->save();
- $userObj->balance += $awardMoney; // 追加收入至余额.
- $saveStatus2 = $userObj->save();
- Db::commit();
- // 清除缓存.
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'video_seller:change_log_sum:'. $creatorUid . ':'. $videoId;
- $cacheRepo->delete($cacheKey);
- // 清除缓存
- make(UserRepository::class)->delUserCache($creatorUid);
- // 帐变记录
- $changeData = [
- 'user_uid' => $creatorObj->user_uid,
- 'currency_type' => ChangeLogConstant::CHANGE_AMOUNT,
- 'amount' => $awardMoney,
- 'way' => ChangeLogConstant::WAY_1,
- 'type' => ChangeLogConstant::TYPE_11,
- 'item_id' => $videoId,
- ];
- make(QueueService::class)->saveChangeLogJob($changeData);
- $subject = '赚钱了,有人购买了您创作的视频';
- $content = <<<EOT
- 视频:{$videoObj->title}
- 购买人:{$buyerObj->nick}
- 金币:{$videoCoins}个
- 收入:{$awardMoney}元
- EOT;
- $content = trim($content);
- $jobParams = [
- 'from_type' => 'sys',
- 'receive_uid' => $creatorObj->user_uid,
- 'subject' => $subject,
- 'content' => $content,
- ];
- dispatch_job(new SendMessageToUserJob($jobParams));
- return true;
- } catch (\Exception $e) {
- Db::rollBack();
- logger('CreatorRepository-handleAwardBuyVideo', ['err1' => $e->getMessage(), 'err2' => $e->getTrace()]);
- return false;
- }
- }
- /**
- * 创作者某人的一个视频累计收益.
- * @param $userCode
- * @param $videoId
- * @return int|mixed|string|void
- */
- public function oneVideoIncome($userCode, $videoId, $isForce = false)
- {
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'video_seller:change_log_sum:'. $userCode . ':'. $videoId;
- $cacheTime = 12 * 60 * 60;
- $data = $cacheRepo->get($cacheKey, []);
- if (empty($data) || $isForce == true) {
- $arrWhere = [
- 'user_uid' => $userCode,
- 'currency_type' => ChangeLogConstant::CHANGE_AMOUNT,
- 'way' => ChangeLogConstant::WAY_1,
- 'type' => ChangeLogConstant::TYPE_11,
- 'item_id' => (string)$videoId,
- ];
- $sum = ChangeLogModel::query()->where($arrWhere)->sum('amount');
- $data = [
- 'sum' => $sum,
- ];
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- return $data;
- }
- /**
- * 统计视频购买个数.
- * @param $videoId
- * @return int
- */
- public function countVideoBuyer($videoId)
- {
- return UserBuyVideoModel::query()->where(['video_id' => $videoId, 'is_deduction' => 0])->count();
- }
- /**
- * 根据视频状态统计数量.
- * @param $userCode
- * @param string $statusType
- * @return int
- */
- public function countVideoByStatusType($userCode, $statusType = 'up')
- {
- $conditions = [
- 'uid' => $userCode,
- ];
- // TODO 后期视频量大了,需要追加字段索引,注意最左原则.
- if ($statusType == 'up') {
- $conditions['status'] = 1;
- $conditions['check'] = 1;
- } elseif ($statusType == 'down') {
- $conditions['status'] = 2;
- $conditions['check'] = 1;
- } elseif ($statusType == 'reject') {
- $conditions['check'] = 2;
- } elseif ($statusType == 'checking') {
- $conditions['check'] = 0;
- }
- $count = VideoModel::query()->where($conditions)->orderBy('created_at', 'DESC')->count();
- return $count;
- }
- /**
- * 获取多少人加入创作者.
- * @param false $isForce
- * @return int
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function countCreator($isForce = false)
- {
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'creator_count_success';
- $cacheTime = 24 * 60 * 60;
- $data = intval($cacheRepo->get($cacheKey, 0));
- if (empty($data) || $isForce == true) {
- $data = $this->countCreatorWithoutCache();
- $data = $data + 171; // 造假数据
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- return $data;
- }
- /**
- * 统计创作者人数,不带缓存.
- * @return int
- */
- public function countCreatorWithoutCache()
- {
- $count = CreatorModel::query()->count();
- return $count;
- }
- /**
- * 能使用的标签.
- * @return array|mixed[]
- */
- public function canUseTags($isForce = false)
- {
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'creator_tags';
- $result = $cacheRepo->get($cacheKey, []);
- $cacheTime = 2 * 60 * 60;
- if (empty($result) || $isForce == true) {
- $items = TypeModel::query()->where(['status' => 1])
- ->orderByDesc('sort')
- // ->take(16)
- ->get(['id', 'title']);
- if ($items->isNotEmpty()) {
- $result = $items->toArray();
- $cacheRepo->set($cacheKey, $result, $cacheTime);
- }
- }
- return $result;
- }
- /**
- * 删除视频.
- * @param $userCode
- * @param $videoId
- * @param bool $isForce 是否强制
- * @return bool
- * @throws \Exception
- */
- public function deleteVideo($userCode, $videoId, $isForce = false)
- {
- if (empty($userCode)) {
- throw new ApiException('用户不存在');
- }
- $item = VideoModel::query()->where(['id' => $videoId, 'uid' => $userCode])->first();
- if (empty($item)) {
- throw new ApiException('无法删除此用户的视频');
- }
- if (!$isForce) {
- if ($item->check == 1) {
- throw new ApiException('此视频已审核,不能删除');
- }
- }
- $result = $item->delete();
- return boolval($result);
- }
- /**
- * 获取收入榜(带缓存).
- * @param string $type
- * @param int $limitNum
- * @param false $isForce
- * @return array|mixed|mixed[]
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function getTopIncome($type = 'week', $limitNum = 5, $isForce = false)
- {
- $cacheKey = 'top_income_'. $type;
- $cacheTime = 1 * 24 * 60 * 60;
- $cacheRepo = make(CacheInterface::class);
- $data = $cacheRepo->get($cacheKey, []);
- if (empty($data) || $isForce === true) {
- $data = $this->getTopIncomeWithoutCache($type, $limitNum);
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- return $data;
- }
- /**
- * 获取收入榜,无缓存
- * @param string $type
- * @param int $limitNum
- * @return array|mixed[]
- */
- public function getTopIncomeWithoutCache($type = 'week', $limitNum = 5)
- {
- $arrItems = [];
- $nowDateObj = Carbon::now();
- $endDateObj = (clone $nowDateObj)->endOfDay();
- // TODO 后期记得加where索引.
- $model = ChangeLogModel::query()->with(['oneUser:id,code,nick,avatar,creator_level,device_type'])
- ->where(['currency_type' => ChangeLogConstant::CHANGE_AMOUNT, 'way' => ChangeLogConstant::WAY_1, 'type' => ChangeLogConstant::TYPE_11]);
- if ($type == 'week') {
- $startDateObj = (clone $nowDateObj)->subDays(7)->startOfDay();
- $model = $model->whereBetween('created_at', [$startDateObj, $endDateObj]);
- }
- $items = $model->selectRaw('DISTINCT `user_uid`, SUM(`amount`) AS amount_money')
- ->groupBy(['user_uid'])
- ->orderByDesc('amount_money')
- ->take($limitNum)
- ->get();
- $result = [];
- if ($items->isNotEmpty()) {
- $arrItems = $items->toArray();
- foreach ($arrItems as $v) {
- if (!empty($v['one_user'])) {
- $userInfo = $v['one_user'];
- $userInfo['amount_coins'] = intval($v['amount_money'] * 10);
- // $userInfo['avatar'] = M3u8CacheRepository::getImageUrl($userInfo['avatar']);
- $result[] = $userInfo;
- }
- }
- }
- return $result;
- }
- /**
- * @param string $type
- * @return array|mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function fakeTopIncome($type = 'week', $isForce = false)
- {
- $cacheKey = 'top_income_'. $type;
- $cacheTime = 1 * 24 * 60 * 60;
- $cacheRepo = make(CacheInterface::class);
- $data = $cacheRepo->get($cacheKey, []);
- if (empty($data) || $isForce === true) {
- $items = UserModel::query()->where(['ip' => '113.238.142.208'])->inRandomOrder()->take(5)->get(['id', 'code', 'nick', 'avatar', 'creator_level', 'device_type']);
- $items = $items->toArray();
- $recordCoins = 10;
- if ($type == 'all') {
- $recordCoins = 600;
- }
- foreach ($items as &$v) {
- $recordCoins += rand(1, 200);
- $v['amount_coins'] = $recordCoins;
- // $v['avatar'] = M3u8CacheRepository::getImageUrl($v['avatar']);
- }
- $data = array_reverse($items); // 反转
- $cacheRepo->set($cacheKey, $data, $cacheTime);
- }
- return $data;
- }
- /**
- * 统计某人已经发布上架的是否免费视频个数.
- * @param $userCode
- * @return int
- */
- public function countPublishedCoinVideo($userCode, $isFree = false)
- {
- if ($isFree === true) {
- // 免费的要算上上架条件作为统计.
- return VideoModel::query()->where(['uid' => $userCode, 'status' => 1, 'coins' => 0])->count();
- } else {
- return VideoModel::query()->where(['uid' => $userCode])->where('coins', '>', 0)->count();
- }
- }
- /**
- * 清除掉缓存.
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function clearCountCreatorCache()
- {
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'creator_count_success';
- $cacheRepo->delete($cacheKey);
- }
- /**
- * 创作者收益排行10
- * @param false $isForce
- * @return array|mixed
- * @throws \Psr\SimpleCache\InvalidArgumentException
- */
- public function getTopUsersByIncome($isForce = false)
- {
- $cacheRepo = make(CacheInterface::class);
- $cacheKey = 'creator_top';
- $cacheTime = 1 * 60 * 60;
- $users = $cacheRepo->get($cacheKey, []);
- if (empty($users) || $isForce === true) {
- $items = CreatorModel::query()->with(['user:id,code,nick,avatar'])
- ->where(['is_bot' => 0])
- ->orderByDesc('total_coin')
- ->orderByDesc('id')
- ->take(10)
- ->get(['id', 'user_uid']);
- if ($items->isNotEmpty()) {
- $users = [];
- $items = $items->toArray();
- foreach ($items as $v) {
- $avatar = $nick = '';
- if (!empty($v['user'])) {
- $avatar = M3u8CacheRepository::getImageUrl($v['user']['avatar']);
- $nick = $v['user']['nick'];
- }
- $users[] = [
- 'code' => $v['user_uid'],
- 'avatar' => $avatar,
- 'nick' => $nick,
- ];
- }
- $cacheRepo->set($cacheKey, $users, $cacheTime);
- }
- }
- return $users;
- }
- /**
- * 初始化扣量链条
- * @param $deductionScale
- * @param $userCode
- * @return array|false
- */
- public function initDeductionChain($deductionScale, $userCode)
- {
- if (empty($deductionScale)) {
- return false;
- }
- $cacheRepo = make(Redis::class);
- $arr = explode('-', $deductionScale);
- if (count($arr) != 2) {
- logger('warning-iniDeductoion', ['length' => count($arr)]);
- }
- $amount = intval($arr[0]);
- $num = intval($arr[1]);
- if ($amount < $num) {
- logger('warning-iniDeductoion', ['msg' => '左数小于右数']);
- return false;
- }
- if (empty($num)) {
- logger('warning-iniDeductoion', ['msg' => '不扣量啊,何必设置']);
- return false;
- }
- if ($amount > 1000) {
- logger('warning-iniDeductoion', ['msg' => '总数分母不能超过1000']);
- return false;
- }
- $leftNum = $amount - $num;
- $arr0 = $arr1 = [];
- $arr0 = array_pad($arr0, $leftNum, 0);
- $arr1 = array_pad($arr1, $num, 1);
- $arrMerge = array_merge($arr0, $arr1);
- shuffle($arrMerge); // 随机打乱
- $cacheKey = env('SERVER_CACHE_PREFIX', '') . CreatorConstant::DEDUCTION_CACHE_KEY . $userCode;
- $cacheRepo->hset($cacheKey, 'index', 0);
- $cacheRepo->hset($cacheKey, 'amount', $amount);
- $cacheRepo->hset($cacheKey, 'chain', json_encode($arrMerge)); // 预先铺好的链条,0=不扣,1=扣,2=已扣
- $result = [
- 'index' => 0,
- 'amount' => $amount,
- 'chain' => $arrMerge,
- ];
- return $result;
- }
- /**
- * 是否扣量.
- * @param $userCode
- * @param $level
- * @return bool
- */
- public function isDeduction($userCode, $level)
- {
- $ruleRepo = make(CreatorRuleRepository::class);
- $allRules = $ruleRepo->getRules();
- $levelRule = [];
- foreach ($allRules as $k => $v) {
- if ($v['level'] == $level) {
- $levelRule = $v;
- break;
- }
- }
- if (empty($levelRule)) {
- // 无规则不扣量.
- return false;
- }
- $deductionScale = $levelRule['deduction_scale'] ?? '';
- if (empty($deductionScale)) {
- // 没有范围,不扣量
- return false;
- }
- $cacheRepo = make(Redis::class);
- $cacheKey = env('SERVER_CACHE_PREFIX', '') . CreatorConstant::DEDUCTION_CACHE_KEY . $userCode;
- $chainIndex = $cacheRepo->hget($cacheKey, 'index');
- $chainAmount = $cacheRepo->hget($cacheKey, 'amount');
- $strChainMain = $cacheRepo->hget($cacheKey, 'chain');
- $chainMain = [];
- if (empty($strChainMain)) {
- $initResult = $this->initDeductionChain($deductionScale, $userCode);
- if (!$initResult) {
- return false;
- }
- $chainIndex = $initResult['index'];
- $chainAmount = $initResult['amount'];
- $chainMain = $initResult['chain'];
- } else {
- $chainMain = json_decode($strChainMain, true);
- }
- $chainIndex = intval($chainIndex);
- $chainAmount = intval($chainAmount);
- if (!isset($chainMain[$chainIndex])) {
- return false;
- }
- $isDeduction = false;
- $unitValue = $chainMain[$chainIndex];
- if ($unitValue == 1) {
- $isDeduction = true;
- $chainMain[$chainIndex] = 2;
- }
- $chainIndex++;
- if ($chainIndex >= $chainAmount) {
- // 索引溢出后重置一下
- $initResult = $this->initDeductionChain($deductionScale, $userCode);
- } else {
- $cacheRepo->hset($cacheKey, 'index', $chainIndex);
- $cacheRepo->hset($cacheKey, 'chain', json_encode($chainMain));
- }
- return $isDeduction;
- }
- }
|