123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- <?php
- // +----------------------------------------------------------------------
- // | Niucloud-admin 企业快速开发的saas管理平台
- // +----------------------------------------------------------------------
- // | 官方网址:https://www.niucloud.com
- // +----------------------------------------------------------------------
- // | niucloud团队 版权所有 开源版本可自由商用
- // +----------------------------------------------------------------------
- // | Author: Niucloud Team
- // +----------------------------------------------------------------------
- namespace app\service\api\member;
- use app\job\member\MemberGiftGrantJob;
- use app\model\member\MemberSign;
- use app\service\core\member\CoreMemberService;
- use app\service\core\sys\CoreConfigService;
- use core\base\BaseApiService;
- use core\exception\CommonException;
- use think\db\exception\DbException;
- use think\facade\Db;
- use DateInterval;
- use DateTime;
- use DatePeriod;
- /**
- * 会员签到服务层
- * Class BaseService
- * @package app\service
- */
- class MemberSignService extends BaseApiService
- {
- public function __construct()
- {
- parent::__construct();
- $this->model = new MemberSign();
- }
- /**
- * 会员签到记录
- * @param array $where
- * @return array
- */
- public function getPage(array $where = [])
- {
- $where['member_id'] = $this->member_id;
- $where['site_id'] = $this->site_id;
- $field = 'sign_id, site_id, member_id, days, day_award, continue_award, continue_tag, create_time, is_sign';
- $search_model = $this->model->where($where)->field($field)->append(['is_sign_name'])->order('create_time desc');
- return $this->pageQuery($search_model);
- }
- /**
- * 会员签到详情
- * @param int $sign_id
- * @return array
- */
- public function getInfo(int $sign_id)
- {
- $field = 'sign_id, site_id, member_id, days, day_award, continue_award, continue_tag, create_time, is_sign';
- return $this->model->where([['sign_id', '=', $sign_id], ['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->field($field)->append(['is_sign_name'])->findOrEmpty()->toArray();
- }
- /**
- * 签到
- * @return array
- */
- public function sign()
- {
- $sign_config = $this->getSign();
- if (!$sign_config['is_use']) throw new CommonException('SIGN_NOT_USE');
- if (empty($sign_config['sign_period']) || empty($sign_config['day_award'])) throw new CommonException('SIGN_NOT_SET');
- $sign_period = $sign_config['sign_period'];//签到周期
- $today = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->whereDay('create_time')->findOrEmpty()->toArray();
- if (!empty($today)) throw new CommonException('SIGNED_TODAY');
- Db::startTrans();
- try {
- $yesterday = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->whereDay('create_time', 'yesterday')->findOrEmpty()->toArray();
- if ($yesterday) {
- $days = $yesterday['days'];
- $days++;
- if ($days > $sign_period) { //连签天数大于签到周期,连签天数重置为1
- $days = 1;
- $data['start_time'] = time();
- }
- if (!empty($sign_config['continue_award'])) {
- $continue_signs = array_column($sign_config['continue_award'], 'continue_sign');
- //获取连签奖励最大天数
- $max_continue_sign = max($continue_signs);
- if ($max_continue_sign < $sign_period && $days > $max_continue_sign) { //连签奖励最大天数 小于 签到周期 并且 连签天数 大于 连签奖励最大天数 连签天数重置为1
- $days = 1;
- }
- }
- } else { //断签,连签天数重置为1
- $days = 1;
- $data['start_time'] = time();
- }
- $awards = []; //奖励数组
- $continue_text = ''; //连签提示
- //添加签到记录
- $data['site_id'] = $this->site_id;
- $data['member_id'] = $this->member_id;
- $data['days'] = $days;
- $data['day_award'] = $sign_config['day_award'];
- $data['is_sign'] = 1;
- $data['create_time'] = time();
- $res = $this->model->create($data);
- if ($res) {
- //日签奖励发放
- MemberGiftGrantJob::dispatch([
- 'site_id' => $this->site_id,
- 'member_id' => $this->member_id,
- 'gift' => $sign_config['day_award'],
- 'param' => [
- 'from_type' => 'day_sign_award',
- 'memo' => '日签奖励'
- ]
- ]);
- $awards['day_award'] = $sign_config['day_award'];
- //签到成功后判断连签天数是否满足连签奖励发放条件
- if (!empty($sign_config['continue_award'])) {
- foreach ($sign_config['continue_award'] as $key => $value) {
- $continue_sign = intval($value['continue_sign']);//连续签到天数要求
- //如果连签天数满足配置条件,发放连签奖励
- if ($res->days == $continue_sign) {
- $gifts = $value;
- unset($gifts['continue_sign'], $gifts['continue_tag'], $gifts['receive_limit'], $gifts['receive_num']);
- $continue_data['continue_award'] = $value;
- $continue_data['continue_tag'] = $value['continue_tag'];//连签奖励标识
- if ($value['receive_limit'] == 2) {//receive_limit (1.不限制 2.每人限领 receive_num 次)
- //周期开始时间
- $period_start_time = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id], ['days', '=', 1], ['start_time', '>', 0]])->order('sign_id desc')->field('start_time')->limit(1)->value('start_time');
- //周期结束时间
- $period_end_time = strtotime("+$sign_period day", $period_start_time);
- //查询领取次数
- $receive_count = $this->model
- ->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id], ['continue_tag', '=', $value['continue_tag']]])
- ->whereBetweenTime('create_time', $period_start_time, $period_end_time)->count('sign_id');
- if ($receive_count < $value['receive_num']) {
- //连签奖励发放
- MemberGiftGrantJob::dispatch([
- 'site_id' => $this->site_id,
- 'member_id' => $this->member_id,
- 'gift' => $gifts,
- 'param' => [
- 'from_type' => 'continue_sign_award',
- 'memo' => '连签奖励'
- ]
- ]);
- $awards['continue_award'] = $gifts;
- $continue_text = get_lang('CONTINUE_SIGN').$res->days.get_lang('DAYS');
- //更新连签发放记录
- $this->model->where([['sign_id', '=', $res->sign_id]])->update($continue_data);
- }
- } else { //不限制
- //连签奖励发放
- MemberGiftGrantJob::dispatch([
- 'site_id' => $this->site_id,
- 'member_id' => $this->member_id,
- 'gift' => $gifts,
- 'param' => [
- 'from_type' => 'continue_sign_award',
- 'memo' => '连签奖励'
- ]
- ]);
- $awards['continue_award'] = $gifts;
- $continue_text = get_lang('CONTINUE_SIGN').$res->days.get_lang('DAYS');
- //更新连签发放记录
- $this->model->where([['sign_id', '=', $res->sign_id]])->update($continue_data);
- }
- }
- }
- }
- }
- Db::commit();
- $awards_total = $this->getTotalAward($awards);
- $result['title'] = get_lang('SIGN_SUCCESS');
- $result['info'] = $continue_text.get_lang('GET_AWARD');
- $result['awards'] = $awards_total;
- if ($awards_total) {
- return $result;
- } else {
- return [
- 'title' => '',
- 'info' => '',
- 'awards' => [],
- ];
- }
- } catch (DbException $e) {
- Db::rollback();
- throw new CommonException($e->getMessage());
- }
- }
- /**
- * 获取月签到数据
- * @param int $year
- * @param int $month
- * @return array
- */
- public function getSignInfo(int $year, int $month)
- {
- $data = [];
- $info = $this->getSign();
- if ($info['is_use'] == 1) {//判断签到是否开启
- $model_result = $this->model->field('create_time')->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->whereMonth('create_time', $year . '-' . sprintf("%02d", $month))->select();
- $days = [];
- foreach ($model_result as $key => $value) {
- $day = date('d', strtotime($value['create_time']));
- array_push($days, $day);
- }
- $data['days'] = $days;
- if (!empty($info['sign_period']) && !empty($info['continue_award'])) {//判断签到周期和连签奖励是否设置
- $sign_period = $info['sign_period'];//签到周期
- $continue_signs = array_column($info['continue_award'], 'continue_sign');
- //获取连签奖励最大天数
- $max_continue_sign = max($continue_signs);
- //周期开始时间
- $period_start_time = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id], ['days', '=', 1], ['start_time', '>', 0]])->order('sign_id desc')->field('start_time')->limit(1)->value('start_time');
- if (!empty($period_start_time)) {
- //周期结束时间
- $period_end_time = strtotime("+$sign_period day", $period_start_time);
- //获取两个时间戳之间的天数组
- $days_array = $this->getDaysArray($period_start_time, $period_end_time);
- foreach ($days_array as $key => $value) {
- $day = $key + 1;
- foreach ($info['continue_award'] as $k => $v) {
- if ($v['receive_limit'] == 1) {//不限制次数奖励添加
- $period_num = intdiv($sign_period, $max_continue_sign);//周期内可循环轮次
- for ($i = 0; $i < $period_num; $i++) {
- if ($max_continue_sign * $i + $v['continue_sign'] == $day) {
- $data['period'][$key]['award'] = true;
- }
- }
- } else {//限制次数奖励添加
- for ($i = 0; $i < $v['receive_num']; $i++) {
- if ($max_continue_sign * $i + $v['continue_sign'] == $day) {
- $data['period'][$key]['award'] = true;
- }
- }
- }
- }
- $data['period'][$key]['day'] = $value;
- }
- } else {
- $data['period'] = [];
- }
- } else {
- $data['period'] = [];
- }
- }
- return $data;
- }
- /**
- * 获取日签到奖励
- * @param int $year
- * @param int $month
- * @param int $day
- * @return array
- */
- public function getDayAward(int $year, int $month, int $day)
- {
- $max_continue_sign = 1;//连签奖励最大天数
- $continue_sign_day = 0;//连签奖励天数
- $time = $year.'-'.sprintf("%02d", $month).'-'.sprintf("%02d", $day);
- $info = $this->getSign();
- if (!$info['is_use']) throw new CommonException('SIGN_NOT_USE');
- if (empty($info['sign_period']) || empty($info['day_award'])) throw new CommonException('SIGN_NOT_SET');
- $sign_period = $info['sign_period'];//签到周期
- if (!empty($info['continue_award'])) {
- $continue_signs = array_column($info['continue_award'], 'continue_sign');
- //获取连签奖励最大天数
- $max_continue_sign = max($continue_signs);
- }
- //周期开始时间
- $period_start_time = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id], ['days', '=', 1], ['start_time', '>', 0]])->order('sign_id desc')->field('start_time')->limit(1)->value('start_time');
- //周期结束时间
- $period_end_time = strtotime("+$sign_period day", $period_start_time);
- //获取两个时间戳之间的天数组
- $days_array = $this->getDaysArray($period_start_time, $period_end_time);
- $award = [];//当日奖励
- //判断查询日期是否在签到周期内
- if (in_array($time, $days_array)) {
- $counter = 0;//计数器
- foreach ($days_array as $key => $value) {
- $counter++;
- if ($value == $time) {
- $continue_sign_day = $counter;
- $award['day_award'] = $info['day_award'];
- if (!empty($info['continue_award'])) {
- $days = $key + 1;
- foreach ($info['continue_award'] as $k => $v) {
- $gift = $v;
- unset($gift['continue_sign'], $gift['continue_tag'], $gift['receive_limit'], $gift['receive_num']);
- if ($v['receive_limit'] == 1) {//不限制次数奖励添加
- $period_num = intdiv($sign_period, $max_continue_sign);//周期内可循环轮次
- for ($i = 0; $i < $period_num; $i++) {
- if ($max_continue_sign * $i + $v['continue_sign'] == $days) {
- $award['continue_award'] = $gift;
- }
- }
- } else {//限制次数奖励添加
- for ($i = 0; $i < $v['receive_num']; $i++) {
- if ($max_continue_sign * $i + $v['continue_sign'] == $days) {
- $award['continue_award'] = $gift;
- }
- }
- }
- }
- }
- }
- if (!empty($info['continue_award'])) {
- if ($counter % $max_continue_sign == 0) {
- $counter = 0;
- }
- } else {
- if ($counter % $sign_period == 0) {
- $counter = 0;
- }
- }
- }
- } else {
- $day_result = $this->model->field('create_time')->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->whereDay('create_time', $time)->findOrEmpty()->toArray();
- if (!empty($day_result)) {
- $award['day_award'] = $day_result['day_award'];
- $continue_award = $day_result['continue_award'];
- if (!empty($continue_award)) {
- unset($continue_award['continue_sign'], $continue_award['continue_tag'], $continue_award['receive_limit'], $continue_award['receive_num']);
- $award['continue_award'] = $continue_award;
- }
- }
- }
- $awards_total = $this->getTotalAward($award);
- $continue_text = $continue_sign_day > 0 ? get_lang('CONTINUE_SIGN').$continue_sign_day.get_lang('DAYS') : '';
- $result['title'] = get_lang('SIGN_AWARD');
- $result['info'] = $continue_text.get_lang('WILL_GET_AWARD');
- $result['awards'] = $awards_total;
- if ($awards_total) {
- return $result;
- } else {
- return [
- 'title' => '',
- 'info' => '',
- 'awards' => [],
- ];
- }
- }
- /**
- * 获取合并奖励数据
- * @param $awards
- * @return array|null
- */
- private function getTotalAward($awards)
- {
- $total_point = 0;
- $total_balance = 0;
- $coupon_id = [];
- $coupon_list = [];
- $is_use_point_day = false;
- $is_use_point_continue = false;
- $is_use_balance_day = false;
- $is_use_balance_continue = false;
- $is_use_coupon_day = false;
- $is_use_coupon_continue = false;
- if (!empty($awards['day_award']['point'])) {
- if ($awards['day_award']['point']['is_use'] == 1) {
- $is_use_point_day = true;
- $total_point += intval($awards['day_award']['point']['num']);
- }
- }
- if (!empty($awards['day_award']['balance'])) {
- if ($awards['day_award']['balance']['is_use'] == 1) {
- $is_use_balance_day = true;
- $total_balance += floatval($awards['day_award']['balance']['money']);
- }
- }
- if (!empty($awards['day_award']['shop_coupon'])) {
- if ($awards['day_award']['shop_coupon']['is_use'] == 1) {
- $is_use_coupon_day = true;
- $coupon_id = array_merge($coupon_id, $awards['day_award']['shop_coupon']['coupon_id']);
- $coupon_list = $this->getArrayMerge($coupon_list, $awards['day_award']['shop_coupon']['coupon_list']);
- }
- }
- if (!empty($awards['continue_award'])) {
- if (!empty($awards['continue_award']['point'])) {
- if ($awards['continue_award']['point']['is_use'] == 1) {
- $is_use_point_continue = true;
- $total_point += intval($awards['continue_award']['point']['num']);
- }
- }
- if (!empty($awards['continue_award']['balance'])) {
- if ($awards['continue_award']['balance']['is_use'] == 1) {
- $is_use_balance_continue = true;
- $total_balance += floatval($awards['continue_award']['balance']['money']);
- }
- }
- if (!empty($awards['continue_award']['shop_coupon'])) {
- if ($awards['continue_award']['shop_coupon']['is_use'] == 1) {
- $is_use_coupon_continue = true;
- $coupon_id = array_merge($coupon_id, $awards['continue_award']['shop_coupon']['coupon_id']);
- $coupon_list = $this->getArrayMerge($coupon_list, $awards['continue_award']['shop_coupon']['coupon_list']);
- }
- }
- }
- $coupon_id = array_unique($coupon_id);
- $is_use_point = ($is_use_point_day || $is_use_point_continue) ? 1 : 0;
- $is_use_balance = ($is_use_balance_day || $is_use_balance_continue) ? 1 : 0;
- $is_use_coupon = ($is_use_coupon_day || $is_use_coupon_continue) ? 1 : 0;
- //相同奖励合并
- $awards_total = [
- 'point' => [
- 'is_use' => $is_use_point,
- 'num' => $total_point,
- ],
- 'balance' => [
- 'is_use' => $is_use_balance,
- 'money' => $total_balance,
- ],
- 'shop_coupon' => [
- 'is_use' => $is_use_coupon,
- 'coupon_id' => $coupon_id,
- 'coupon_list' => $coupon_list,
- ]
- ];
- return (new CoreMemberService())->getGiftContent($this->site_id, $awards_total, 'member_sign');
- }
- /**
- * 获取用户签到设置
- * @return array
- */
- public function getSignConfig()
- {
- $info = $this->getSign();
- $today = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->whereDay('create_time')->findOrEmpty()->toArray();
- $yesterday = $this->model->where([['site_id', '=', $this->site_id], ['member_id', '=', $this->member_id]])->whereDay('create_time', 'yesterday')->findOrEmpty()->toArray();
- if (!empty($info['day_award'])) {
- $day_award = (new CoreMemberService())->getGiftContent($this->site_id, $info['day_award'],'member_sign');
- $info['day_award'] = $day_award;
- }
- if (!empty($info['continue_award'])) {
- foreach ($info['continue_award'] as $key => $value) {
- $gift = $value;
- unset($gift['continue_sign'], $gift['continue_tag'], $gift['receive_limit'], $gift['receive_num']);
- $gift_content = (new CoreMemberService())->getGiftContent($this->site_id, $gift, 'member_sign_continue');
- $gift_count = 0;
- $content_text = '';
- $content_icon = '';
- foreach ($gift_content as $vv) {
- if ($vv['is_use'] == 1) {
- foreach ($vv['content'] as $v) {
- $content_text = $content_text . ($gift_count == 0 ? '' : '+') . $v['text'];
- $content_icon = $v['icon'];
- $gift_count++;
- }
- }
- }
- if ($gift_count > 1) {
- $continue_award['gift'] = ['total' => ['text' => $content_text, 'icon' => '/static/resource/images/member/sign/pack01.png']];
- } else if($gift_count == 1) {
- $continue_award['gift'] = ['total' => ['text' => $content_text, 'icon' => $content_icon]];
- } else {
- $continue_award['gift'] = [];
- }
- $continue_award['continue_sign'] = $value['continue_sign'];
- $info['continue_award'][$key] = $continue_award;
- }
- }
- $info['is_sign'] = empty($today) ? false : true;//是否签到
- if (empty($today)) {
- $info['days'] = empty($yesterday) ? 0 : $yesterday['days'];//连签天数
- } else {
- $info['days'] = $today['days'];//连签天数
- }
- return $info;
- }
- /**
- * 获取站点签到设置
- */
- public function getSign()
- {
- $info = ( new CoreConfigService() )->getConfig($this->request->defaultSiteId(), 'SIGN_CONFIG');
- if (empty($info)) {
- $info = [];
- $info[ 'value' ] = [
- 'is_use' => 0,
- 'sign_period' => '',
- 'day_award' => '',
- 'continue_award' => [],
- 'rule_explain' => ''
- ];
- }
- return $info[ 'value' ];
- }
- /**
- * 获取两个时间戳之间的天数组
- * @param $start_timestamp
- * @param $end_timestamp
- * @return array
- */
- private function getDaysArray($start_timestamp, $end_timestamp) {
- $start = new DateTime("@$start_timestamp"); // 使用时间戳创建DateTime对象
- $end = new DateTime("@$end_timestamp"); // 同上
- $interval = new DateInterval('P1D'); // 每天的周期
- $period = new DatePeriod($start, $interval, $end); // 创建周期范围
- $days_array = [];
- foreach ($period as $day) {
- $days_array[] = $day->format('Y-m-d'); // 格式化日期并添加到数组
- }
- return $days_array;
- }
- /**
- * 合并数据,如果键值相等其值相加
- * @param $desc
- * @param $json_wares
- * @return array|false
- */
- private static function getArrayMerge($desc, $json_wares)
- {
- if (is_array($desc) && is_array($json_wares)) {
- $arrayMerge = array();
- foreach ($json_wares as $key=>$value) {
- if (array_key_exists($key, $desc)) {
- $arrayMerge[$key] = $value + $desc[$key];
- unset($desc[$key]);
- } else {
- $arrayMerge[$key] = $value;
- }
- }
- return $arrayMerge+$desc;
- } else {
- return false;
- }
- }
- }
|