智慧教务系统 PHP-NiuCloud框架开发
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

565 lines
25 KiB

<?php
// +----------------------------------------------------------------------
// | Niucloud-admin 企业快速开发的多应用管理平台
// +----------------------------------------------------------------------
// | 官方网址: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;
$field = 'sign_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, member_id, days, day_award, continue_award, continue_tag, create_time, is_sign';
return $this->model->where([['sign_id', '=', $sign_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([['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([['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['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([
'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([['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([['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([
'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([
'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([['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([['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([['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([['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;
$coupon_check_data = array_filter(event('CouponCheck', ['is_use_coupon' => $is_use_coupon, 'coupon_id' => $coupon_id, 'coupon_list' => $coupon_list]))[0] ?? [];
if (empty($coupon_check_data)) {
$is_use_coupon = false;
$coupon_check_data = [
'coupon_id' => [],
'coupon_list' => []
];
}
$is_use_coupon = empty($coupon_check_data['coupon_id']) ? false : $is_use_coupon;
//相同奖励合并
$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_check_data['coupon_id'],
'coupon_list' => $coupon_check_data['coupon_list'],
]
];
return (new CoreMemberService())->getGiftContent($awards_total, 'member_sign');
}
/**
* 获取用户签到设置
* @return array
*/
public function getSignConfig()
{
$info = $this->getSign();
$today = $this->model->where([['member_id', '=', $this->member_id]])->whereDay('create_time')->findOrEmpty()->toArray();
$yesterday = $this->model->where([['member_id', '=', $this->member_id]])->whereDay('create_time', 'yesterday')->findOrEmpty()->toArray();
if (!empty($info['day_award'])) {
$day_award = (new CoreMemberService())->getGiftContent($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($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('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;
}
}
}