<?php /** * AbstractService.class.php * * Service 层基类 * @author: daijun */ namespace Common\Service; use Common\Common\Helper; use Common\Common\Msg; use Common\Common\Tag; use Common\Common\User; use Common\Model\PacketModel; use Common\Model\PacketrecordModel; use Common\Model\RightModel; abstract class AbstractService extends \Com\Service { // 默认页码 const DEFAULT_PAGE = 1; // 默认每页条数 const DEFAULT_LIMIT = 10; // 活动状态:草稿 const ACTIVITY_DRAFT = 0; // 活动状态:发布 const ACTIVITY_PUBLISH = 1; // 活动状态:终止 const ACTIVITY_STOP = 2; // 积分规则:默认策略 const INTEGRAL_ACTION_TYPE_DEFAULT = 1; // 积分规则:不使用策略 const INTEGRAL_ACTION_TYPE_NO = 2; // 积分规则:使用自定义策略 const INTEGRAL_ACTION_TYPE_MY = 3; // 开启红包 const RED_OPEN = 1; // 未开启红包 const RED_CLOSE = 0; // 活动隐藏 const OPEN_ACTIVITY_HIDE = 1; // 关闭隐藏 const CLOSE_ACTIVITY_HIDE = 0; /** * 推消息类型 */ // 管理员成功发布活动 const MSG_ACTIVITY_PUBLISH = 1; // 帖子发布提醒审核人 const MSG_CHECK_COMMENT_REMAIND_FOR_ADMIN = 2; // 帖子发布提醒发帖人 const MSG_CHECK_COMMENT_REMAIND_FOR_USER = 3; // 帖子被回复 const MSG_COMMENT_REPLY = 4; // 帖子审核通过 const MSG_COMMENT_CHECK_SUCCESS = 5; // 帖子审核驳回 const MSG_COMMENT_CHECK_FAIL = 6; // 获得随机红包提醒 const MSG_GET_RANDOM_REDPACKET = 7; // 提醒领取随机红包 const MSG_REMAIND_RECEIVE_RANDOM_REDPACKET = 8; // 获得补发随机红包提醒 const MSG_GET_REPEAT_RANDOM_REDPACKET = 9; // 获得定向红包提醒 const MSG_GET_VIP_REDPACKET = 10; // 提醒领取定向红包 const MSG_REMAIND_RECEIVE_VIP_REDPACKET = 11; // 获得补发定向红包提醒 const MSG_GET_REPEAT_VIP_REDPACKET = 12; // 未参与提醒消息 const MSG_REMAIND_NO_JOIN_USERS = 13; // 自动审核通过消息 const MSG_COMMENT_AUTOCHECK_SUCCESS = 14; // 自动审核被驳回消息 const MSG_COMMENT_AUTOCHECK_FAIL = 15; // 发送消息给有权限的审核人员 const MSG_ACTIVITY_PUBLISH_CHECK_USER = 16; // 发消息给有权限查看的人员 const MSG_ACTIVITY_LOOK_COMMENT = 17; // 消息ID类型为活动 const MSG_TYPE_ACTIVITY = 1; // 消息ID类型为评论 const MSG_TYPE_COMMENT = 2; // 消息ID类型为红包 const MSG_TYPE_REDPACKET = 3; // 审核消息类型 const MSG_CHECK_TYPE_ACTIVITY = 4; // 可以进行删除操作 const IS_DEL_OK = 1; // 不可以进行删除 const IS_DEL_NO = 0; // 已点赞 const IS_LIKE_OK = 1; // 未点赞 const IS_LIKE_NO = 0; // 删除评论类型 const DEL_COMMENT_TYPE = 1; // 删除回复类型 const DEL_REPLY_TYPE = 2; // 活动点赞类型 const LIKE_ACTIVITY_TYPE = 1; // 评论点赞类型 const LIKE_COMMENT_TYPE = 2; // 回复点赞类型 const LIKE_REPLY_TYPE = 3; // 分享权限 const RIGHT_TYPE_ACTIVITY = 0; // 审核权限 const RIGHT_TYPE_CHECK = 1; // 上传图片个数最大值 const IMAGES_MAX_COUNT = 9; // 权限:全公司 const IS_ALL = 1; // 开启分享审核 const OPEN_CHECK = 1; // 关闭分享审核 const CLOSE_CHECK = 0; // 审核状态:待审核 const CHECK_ING = 0; // 审核状态:已通过 const CHECK_OK = 1; // 审核状态:已驳回 const CHECK_NO = 2; // 开启红包 const OPEN_RED = 1; // 关闭红包 const CLOSE_RED = 0; // 随机比例红包 const RED_PACKET_RAND = 1; // 定向红包 const RED_PACKET_VIP = 4; // 红包状态:(已补发) const PACKET_STATUS_REPEAT = 3; // 红包状态:(领取失败) const PACKET_STATUS_FAIL = 2; // 红包状态:(领取成功) const PACKET_STATUS_SUCCESS = 1; // 红包状态:(待领取) const PACKET_STATUS_WAIT = 0; // 构造方法 public function __construct() { parent::__construct(); } /** * 即时消息通知方法 【发消息统一写这里,方便维护】 * * @param $params -通知参数 * + uids -用户uid数组 * + memID -用户uid * + dp_ids -部门id数组 * + dpID -部门id * + tag_ids -标签id数组 * + tagID -标签id * + comment_id -帖子id * + ac_id -活动id * + rid -红包记录id * @param $msg_type -通知文案类型 * * @return bool */ public function send_msg($params, $msg_type) { // 获取应用名称 $application_name = cfg('APPLICATION_NAME'); // 去除中文空格 $search = [" ", " ", "\n", "\r", "\t", ' ']; $replace = ["", "", "", "", "", ""]; $content = str_replace($search, $replace, strip_tags($params['content'])); // 本方法根据类型区分拼接不同的文案 switch ($msg_type) { case self::MSG_ACTIVITY_PUBLISH: // 活动发布时 $data = [ 'title' => '【' . $application_name . '】有新的活动,快来参与吧', 'description' => '标题:' . $params['subject'] . "\r\n活动时间:" . rgmdate((string)$params['begin_time'], 'Y-m-d H:i') . '~' . ($params['end_time'] ? rgmdate((string)$params['end_time'], 'Y-m-d H:i') : '无') . "\r\n活动描述:" . $this->cutstr($content, 0, 20), 'picUrl' => '', 'type' => self::MSG_TYPE_ACTIVITY, // 活动类型 ]; break; case self::MSG_ACTIVITY_PUBLISH_CHECK_USER: // 推送消息告知用户被设置为审核人员 $data = [ 'title' => '【' . $application_name . '】您已被设置成活动审核负责人,请关注审核消息', 'description' => '标题:' . $params['subject'] . "\r\n活动时间:" . rgmdate((string)$params['begin_time'], 'Y-m-d H:i') . '~' . ($params['end_time'] ? rgmdate((string)$params['end_time'], 'Y-m-d H:i') : '无') . "\r\n活动描述:" . $this->cutstr($content, 0, 20), 'picUrl' => '', 'type' => self::MSG_TYPE_ACTIVITY, // 审核人消息类型 ]; break; case self::MSG_ACTIVITY_LOOK_COMMENT: // 发消息给有权限查看的人员 $data = [ 'title' => '【' . $application_name . '】' . $this->cutstr($params['subject'], 0, 10) . '下有一条新的回帖,快来查看吧', 'description' => '活动标题:' . $params['subject'] . "\r\n回帖人:" . $params['username'] . "\r\n回帖内容:" . $this->cutstr($content, 0, 30), 'picUrl' => '', 'type' => self::MSG_TYPE_ACTIVITY, // 帖子类型 ]; break; case self::MSG_CHECK_COMMENT_REMAIND_FOR_ADMIN: // 审核消息—负责人 $data = [ 'title' => '【' . $application_name . '】您负责的活动有新的帖子需要审核', 'description' => '标题:' . $params['subject'] . "\r\n回帖人:" . $params['username'] . "\r\n回帖内容:" . $this->cutstr($content, 0, 30), 'picUrl' => '', 'type' => self::MSG_CHECK_TYPE_ACTIVITY, // 帖子类型 ]; break; case self::MSG_CHECK_COMMENT_REMAIND_FOR_USER: // 审核消息—发起者 $data = [ 'title' => '【' . $application_name . '】您已成功发帖,请耐心等待审核', 'description' => '标题:' . $params['subject'] . "\r\n回帖时间:" . rgmdate((string)$params['created'], 'Y-m-d H:i') . "\r\n回帖内容:" . $this->cutstr($content, 0, 30), 'picUrl' => '', 'type' => self::MSG_TYPE_COMMENT, // 帖子类型 ]; break; case self::MSG_COMMENT_REPLY: // 评论消息(帖子被回复) $data = [ 'title' => '【' . $application_name . '】您的帖子有了新的评论,快来瞧瞧吧', 'description' => '标题:' . $params['subject'] . "\r\n评论人:" . $params['username'] . "\r\n评论内容:" . $this->cutstr($content, 0, 30), 'picUrl' => '', 'type' => self::MSG_TYPE_COMMENT, // 帖子类型 ]; break; case self::MSG_COMMENT_CHECK_SUCCESS: // 帖子审核通过 $data = [ 'title' => '【' . $application_name . '】恭喜您,您的帖子已通过审核,现已正式发布', 'description' => '标题:' . $params['subject'] . "\r\n回帖时间:" . rgmdate((string)$params['created'], 'Y-m-d H:i') . "\r\n审核人:" . $params['username'] . "\r\n审核时间:" . rgmdate((string)$params['check_time'], 'Y-m-d H:i'), 'picUrl' => '', 'type' => self::MSG_TYPE_COMMENT, // 帖子类型 ]; break; case self::MSG_COMMENT_CHECK_FAIL: // 帖子审核驳回 if (!empty($params['reason'])) { $description = '标题:' . $params['subject'] . "\r\n回帖时间:" . rgmdate((string)$params['created'], 'Y-m-d H:i') . "\r\n审核人:" . $params['username'] . "\r\n审核时间:" . rgmdate((string)$params['check_time'], 'Y-m-d H:i') . "\r\n驳回原因:" . $this->cutstr($params['reason'], 0, 20); } else { $description = '标题:' . $params['subject'] . "\r\n回帖时间:" . rgmdate((string)$params['created'], 'Y-m-d H:i') . "\r\n审核人:" . $params['username'] . "\r\n审核时间:" . rgmdate((string)$params['check_time'], 'Y-m-d H:i'); } $data = [ 'title' => '【' . $application_name . '】抱歉,您的帖子未通过审核', 'description' => $description, 'picUrl' => '', 'type' => self::MSG_TYPE_COMMENT, // 帖子类型 ]; break; case self::MSG_GET_RANDOM_REDPACKET: // 获得随机红包 $data = [ 'title' => '【' . $application_name . '】恭喜您,获得一个随机红包,请点击领取', 'description' => '活动标题:' . $params['subject'] . "\r\n发放时间:" . rgmdate((string)$params['give_time'], 'Y-m-d H:i'), 'picUrl' => '', 'type' => self::MSG_TYPE_REDPACKET, // 红包类型 ]; break; case self::MSG_REMAIND_RECEIVE_RANDOM_REDPACKET: // 提醒领取随机红包 $data = [ 'title' => '【' . $application_name . '】您有一个随机红包未领取,请点击领取', 'description' => '活动标题:' . $params['subject'] . "\r\n发放时间:" . rgmdate((string)$params['give_time'], 'Y-m-d H:i'), 'picUrl' => '', 'type' => self::MSG_TYPE_REDPACKET, // 红包类型 ]; break; case self::MSG_GET_REPEAT_RANDOM_REDPACKET: // 获得补发随机红包 $data = [ 'title' => '【' . $application_name . '】恭喜您,获得一个补发随机红包,请点击领取', 'description' => '活动标题:' . $params['subject'] . "\r\n发放时间:" . rgmdate((string)$params['give_time'], 'Y-m-d H:i'), 'picUrl' => '', 'type' => self::MSG_TYPE_REDPACKET, // 红包类型 ]; break; case self::MSG_GET_VIP_REDPACKET: // 获得定向红包提醒 $data = [ 'title' => '【' . $application_name . '】恭喜您,获得一个定向红包,请点击领取', 'description' => '活动标题:' . $params['subject'] . "\r\n发放时间:" . rgmdate((string)$params['give_time'], 'Y-m-d H:i') . "\r\n红包金额:" . sprintf('%.2f', $params['rand_money'] / 100) . '元', 'picUrl' => '', 'type' => self::MSG_TYPE_REDPACKET, // 红包类型 ]; break; case self::MSG_REMAIND_RECEIVE_VIP_REDPACKET: // 提醒领取定向红包 $data = [ 'title' => '【' . $application_name . '】您一个定向红包未领取,请点击领取', 'description' => '活动标题:' . $params['subject'] . "\r\n发放时间:" . rgmdate((string)$params['give_time'], 'Y-m-d H:i') . "\r\n红包金额:" . sprintf('%.2f', $params['rand_money'] / 100) . '元', 'picUrl' => '', 'type' => self::MSG_TYPE_REDPACKET, // 红包类型 ]; break; case self::MSG_GET_REPEAT_VIP_REDPACKET: // 获得补发定向红包 $data = [ 'title' => '【' . $application_name . '】恭喜您,获得一个补发定向红包,请点击领取', 'description' => '活动标题:' . $params['subject'] . "\r\n发放时间:" . rgmdate((string)$params['give_time'], 'Y-m-d H:i') . "\r\n红包金额:" . sprintf('%.2f', $params['rand_money'] / 100) . '元', 'picUrl' => '', 'type' => self::MSG_TYPE_REDPACKET, // 红包类型 ]; break; case self::MSG_REMAIND_NO_JOIN_USERS: // 活动发布时 $data = [ 'title' => '【' . $application_name . '】您有一个活动尚未参与', 'description' => '标题:' . $params['subject'] . "\r\n活动时间:" . rgmdate((string)$params['begin_time'], 'Y-m-d H:i') . '~' . ($params['end_time'] ? rgmdate((string)$params['end_time'], 'Y-m-d H:i') : '无') . "\r\n活动描述:" . $this->cutstr($content, 0, 20), 'picUrl' => '', 'type' => self::MSG_TYPE_ACTIVITY, // 活动类型 ]; break; case self::MSG_COMMENT_AUTOCHECK_SUCCESS: // 帖子自动审核通过 $data = [ 'title' => '【' . $application_name . '】恭喜您,您的帖子已通过审核,现已正式发布', 'description' => '标题:' . $params['subject'] . "\r\n回帖时间:" . rgmdate((string)$params['created'], 'Y-m-d H:i') . "\r\n审核人:系统自动审核" . "\r\n审核时间:" . rgmdate((string)$params['check_time'], 'Y-m-d H:i'), 'picUrl' => '', 'type' => self::MSG_TYPE_COMMENT, // 帖子类型 ]; break; case self::MSG_COMMENT_AUTOCHECK_FAIL: // 帖子自动审核驳回 $description = '标题:' . $params['subject'] . "\r\n回帖时间:" . rgmdate((string)$params['created'], 'Y-m-d H:i') . "\r\n审核人:系统自动审核" . "\r\n审核时间:" . rgmdate((string)$params['check_time'], 'Y-m-d H:i') . "\r\n驳回原因:" . $this->cutstr($params['reason'], 0, 20); $data = [ 'title' => '【' . $application_name . '】抱歉,您的帖子未通过审核', 'description' => $description, 'picUrl' => '', 'type' => self::MSG_TYPE_COMMENT, // 帖子类型 ]; break; default: return true; } $this->send($params, $data); return true; } /** * 发送消息 * * @param $params -通知参数 * + is_all -全公司 * + uids -用户uid数组 * + memID -用户uid * + dp_ids -部门id数组 * + dpID -部门id * @param array $condition 消息参数 * + title -标题 * + description -内容 * + picUrl -图片URL * + type -数据类型(1:活动 2:帖子,3:红包) * * @return bool */ private function send($params = [], $condition = []) { // 发送消息接收人 $msgUser = !empty($params['uids']) ? $params['uids'] : []; $toUser = isset($params['is_all']) && !empty($params['is_all']) ? '@all' : $msgUser; // 发送消息部门 $toParty = !empty($params['dp_ids']) ? $params['dp_ids'] : []; $articles = [ [ 'title' => $condition['title'], 'description' => $condition['description'], 'url' => oaUrl('Frontend/Index/Msg/Index', [ 'type' => $condition['type'], 'ac_id' => intval($params['ac_id']), 'comment_id' => intval($params['comment_id']), 'rid' => intval($params['rid']) ] ), 'picUrl' => '', ], ]; $msgServ = &Msg::instance(); // 根据部门ID查询其下的所有用户UID(兼容发送对象超过1000人的情况) if (!empty($toParty) && $toUser != '@all') { $params = [ 'dpIdList' => $toParty, // 跟UC确认可以传部门的数组 'departmentChildrenFlag' => Helper::USER_DEPARTMENTCHILDRENFLAG_TRUE, // 按部门条件查询时,表示部门递归查询人员 ]; // 部门下的用户UID获取 $toPartUser = User::instance()->listAllBasic($params); $toUser = array_merge($toUser, (array)array_column($toPartUser, 'memUid')); } // 发消息给指定人员 if ($toUser != '@all') { // 去除用户UID数组 空值和重复值 $toUser = is_array($toUser) ? array_unique(array_filter($toUser)) : [$toUser]; $uid_groups = array_chunk($toUser, Msg::USER_MAX_COUNT); foreach ($uid_groups as $uid_group) { $msgServ->sendNews($uid_group, null, null, $articles); } } else { // 发送给全公司 $msgServ->sendNews($toUser, null, null, $articles); } return true; } /** * 转换时间格式 * 时间显示规则:1小时内显示XX分钟前,1天以内的显示XX个小时前,1~7天显示XX天前,超过7天显示具体年-月-日 时-分 * * @param string $time 当前时间戳 * * @return bool */ public function get_time($time = '') { // 获取剩余秒数 $way = NOW_TIME - ($time / 1000); // 一分钟之内 if ($way < 60) { return '刚刚'; } // 如果是一小时之内 if ($way < 3600) { return intval($way / 60) . '分钟前'; } // 如果是一天之内 if ($way < 86400) { return intval($way / 3600) . '小时前'; } // 如果是一周之内 if ($way < 604800) { return intval($way / 86400) . '天前'; } return rgmdate(strval($time), 'Y-m-d H:i'); } /** * 评论和回复获取图片信息 * * @param array $data * * @return array */ public function get_image_list($data = []) { // 初始化图片数组 $images = []; $image_ids = explode(',', $data); foreach ($image_ids as $_atId) { $images[] = [ 'atId' => $_atId, 'imgUrl' => imgUrlReal($_atId), ]; } return $images; } /** * 获取已删除用户信息 * * @param array &$user_list 用户列表 * @param array $uids 全部用户UID * * @return bool */ public function user_list(&$user_list = [], $uids = []) { // 获取未删除的用户UID $_uids = array_column($user_list, 'memUid'); // 获取被删除的用户UID $un_uid = array_diff($uids, $_uids); // 实例化 $user = User::instance(); // 遍历数据 foreach ($un_uid as $v) { // 如果UID不为空 if (!empty($v)) { $user_list[] = $user->getByUid($v); } } return true; } /** * 字符串截取,支持中文和其他编码 * static * access public * * @param string $str 需要转换的字符串 * @param int $start 开始位置 * @param string $length 截取长度 * @param string $charset 编码格式 * @param bool|string $suffix 截断显示字符 * * @return string */ public function cutstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true) { if (function_exists("mb_substr")) { $slice = mb_substr($str, $start, $length, $charset); } elseif (function_exists('iconv_substr')) { $slice = iconv_substr($str, $start, $length, $charset); if (false === $slice) { $slice = ''; } } else { $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/"; $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/"; $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/"; $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/"; preg_match_all($re[$charset], $str, $match); $slice = join("", array_slice($match[0], $start, $length)); } if (get_str_len($str) > $length && $slice) { $slice = $slice . '...'; } return $suffix ? $slice : $slice; } /** * 替换字符串中的/r/n为回车 * * @param string $str 字符串 * * @return string */ public function enter($str = '') { $str = trim($str); //清除字符串两边的空格 $replace = ["\r\n", "\n", "\r", "↵", "↵"]; return trim(str_replace($replace, "<br/>", $str)); //返回字符串 } /** * 根据规则生成随机比例红包记录 * * @param int $ac_id 活动id * @param int $pid 红包id * @param array $rule_list 红包规则 * + red_proportion 比例 * + red_proportion_money 金额(元) * @param int $red_base_num 红包基数(默认100) * * @return bool */ public function create_packet_record($ac_id = 0, $pid = 0, $rule_list = [], $red_base_num = 100) { // 实例化红包记录表Model $records_model = new PacketrecordModel(); // 红包记录初始化 $red_list = []; // 判断红包基数是否被100整除 if (($red_base_num % 100) != 0) { E('_ERR_RED_BASE_NUM'); } // 管理后台设置红包规则,红包基数代码中没有做上限设置验证,故需在此判断 if ($red_base_num > 5000) { // 产品需求:如果红包基数大于5000,则每次生成5000 $red_base_num = 5000; } foreach ($rule_list as $v) { // 计算当前规则比例的红包个数 $red_total = intval($red_base_num) * (intval($v['red_proportion']) / 100); for ($i = 0; $i < $red_total; $i++) { // 组装红包记录数据 $red_list[] = [ 'pid' => $pid, // 红包id 'p_type' => self::RED_PACKET_RAND, // 随机比例红包 'ac_id' => $ac_id, // 活动id 'cid' => 0, // 回帖id 'rand_money' => $v['red_proportion_money'] * 100 // 金额(单位:分) ]; } } // 打乱数组 shuffle($red_list); // 将红包记录入库 $total = $records_model->insert_all($red_list); // 删除大数组 unset($red_list); return empty($total) ? false : true; } /** * 获取红包订单号 * * @param int $type 红包类型(1:随机比例红包,2:定向红包,3.补发红包) * @param int $rid 红包记录id * * @return string */ public function get_order_sn($type = 1, $rid = 0) { if (1 == $type) { $str = 'N'; // 随机比例红包 } elseif (2 == $type) { $str = 'V'; // 定向红包 } else { $str = 'R'; // 补发红包 } if (empty($rid)) { $rid = rand(100, 999); } return $str . rgmdate(strval(MILLI_TIME), 'ymd') . sprintf("%08d", $rid); } /** * 推消息时给用户分配红包【只适用正常发放,不包含补发】 * * @param array $data * + int $ac_id 活动id * + int $p_type 红包类型(1.随机比例红包,2.拼手气红包,3:普通红包,4:定向红包) * + string $uid 用户id * + string $comment_id 分享id * + int $price 红包金额(定向红包此项为必填,单位:元) * + string $send_uname 红包发放人姓名 * + string $send_phone 红包发放人电话 * * @return array 红包记录 id 以及发放时间 * + int rid 红包记录 ID * + int give_time 发放红包时间(毫秒时间戳) */ public function get_red_record($data = []) { // 实例化红包记录表 $records_model = new PacketrecordModel(); // 实例化红包配置表 $packet_model = new PacketModel(); // 红包记录表自增 id 初始化 $rid = 0; // 发放时间 $give_time = MILLI_TIME; // 定向红包 if (self::RED_PACKET_VIP == $data['p_type']) { // 红包金额 $price = $data['price']; if (intval($price) < 1 || intval($price) > 2000) { // 红包金额设置不正确 E('_ERR_RED_PRICE'); } $user = User::instance()->getByUid($data['uid']); $record_arr = [ 'pid' => 0, // 红包id 'p_type' => $data['p_type'], // 红包类型 'ac_id' => $data['ac_id'], // 活动id 'rand_money' => $data['price'] * 100, // 红包金额(单位:分) 'packet_status' => self::PACKET_STATUS_WAIT, // 待领取 'give_time' => $give_time // 发放时间 ]; $rid_new = (int)$records_model->insert($record_arr); // 组装更新数据,主要是为了更新订单id以及与用户的关联关系 $update_arr = [ 'cid' => $data['comment_id'], // 回帖id 'order_sn' => $this->get_order_sn(2, $rid_new), // 生成订单号 'send_uname' => $data['send_uname'], // 发放人姓名 'send_phone' => $data['send_phone'], // 发放人电话 'uid' => $data['uid'], // 领取人uid 'username' => $user['memUsername'], // 领取人姓名 ]; // 更新订单记录数据 if ($records_model->update($rid_new, $update_arr)) { $rid = $rid_new; } } elseif (self::RED_PACKET_RAND == $data['p_type']) { // 随机红包 // 查询红包规则:每人最大领取数量 $packet_conds = [ 'ac_id' => $data['ac_id'], ]; $packet_info = $packet_model->get_by_conds($packet_conds); // 如果设置了最多领取次数 if (!empty($packet_info['max_total'])) { $record_conds = [ 'uid' => $data['uid'], 'parent_rid' => 0, // parent_rid=0的是主红包 'ac_id' => $data['ac_id'], // 当前活动 'p_type' => self::RED_PACKET_RAND // 随机比例类型 ]; // 查询该用户此次活动领取次数 $receive_count = $records_model->count_by_conds($record_conds); // 超过红包领取限制,结束程序 if ($receive_count >= $packet_info['max_total']) { return []; } } // 给用户分配红包记录 $rid = $this->match_packet_record($data, $packet_info, $give_time); } return ['rid' => $rid, 'give_time' => $give_time]; } /** * 递归给用户分配红包 * * @param array $data 回帖数据 * @param array $packet_info 红包配置数据 * @param int $give_time 发放时间 * @param int $step 递归次数 * * @return int 红包记录ID */ public function match_packet_record($data = [], $packet_info = [], $give_time = 0, $step = 0) { // 当前递归次数 $step++; $rid = 0; // 初始化红包记录ID if ($step > 5) { // 最多递归5次还没分配到,直接放弃 return 0; } // 实例化红包记录表 $records_model = new PacketrecordModel(); // 组织查询未分配红包记录条件 $record_conds = [ 'ac_id' => $data['ac_id'], // 活动id 'packet_status' => self::PACKET_STATUS_WAIT, // 待领取 'cid' => 0 // 回帖ID为0表示未分配 ]; // 获取【未分配】的红包数据 $record = $records_model->get_by_conds($record_conds); if (empty($record)) { // 没有【未分配】的红包记录了,需要按照红包配置再次生成 if (empty($packet_info)) { // 活动的红包配置未找到,抛错 E('_ERR_REPEAT_DATA'); } // 按规则生成红包 $this->create_packet_record($data['ac_id'], $packet_info['id'], unserialize($packet_info['red_content']), $packet_info['red_base_num']); // 获取【未分配】的红包数据 $record = $records_model->get_by_conds($record_conds); } if (!empty($record)) { // 有【未分配】的红包记录 if (!isset($data['username'])) { // 从UC查询发帖人姓名 username(兼容传入参数中不含发帖人 username 的情况) $user = User::instance()->getByUid($data['uid']); $data['username'] = $user['memUsername']; } $update_data = [ 'order_sn' => $this->get_order_sn(1, $record['rid']), 'uid' => $data['uid'], 'username' => $data['username'], // 发帖人 'cid' => $data['comment_id'], // 回帖 ID 'packet_status' => self::PACKET_STATUS_WAIT, // 待领取 'give_time' => $give_time // 发放时间 ]; // 更新红包记录 if ($records_model->update_by_conds(['rid' => $record['rid'], 'cid' => 0], $update_data)) { // 如果执行成功,则该记录匹配给当前用户 $rid = $record['rid']; } } if (empty($rid)) { // 如果没匹配到红包记录或者分配到红包记录,但是已被人抢占,则重新分配 $this->match_packet_record($data, $packet_info, $give_time, $step); } else { return $rid; } } /** * 数组分页 * * @param $data array 需分页的数组 * @param $page int 页码 * @param $limit int 每页数量 * * @return array */ public function get_page_data($data, $page, $limit) { $list = []; //计算每次分页的开始位置 $start_limt = ($page - 1) * $limit; $list = array_slice($data, $start_limt, $limit); return $list; } /** * 获取活动未参与人数 * * @param array $params 过滤条件 * @param array $join_list 已参与列表 * * @return array */ public function count_unjoin($params, $join_list) { // 获取权限内总人数 $right_m = new RightModel(); $right_conds = [ 'ac_id' => $params['ac_id'], ]; $right_list = $right_m->list_by_conds($right_conds); // 实例化User $user_s = new User(); if (!empty($right_list)) { // 获取权限数组 $uid = array_values(array_filter(array_column($right_list, 'uid'))); $dp_id = array_values(array_filter(array_column($right_list, 'dp_id'))); $job_id = array_values(array_filter(array_column($right_list, 'job_id'))); $role_id = array_values(array_filter(array_column($right_list, 'role_id'))); $tag_id = array_values(array_filter(array_column($right_list, 'tag_id'))); // 查询用户信息,多次查询UC,合并去重 $tag_list = []; if (!empty($tag_id)) { $tag_s = new Tag(); $tag_list = $tag_s->listUserByTagId($tag_id, 1, 1000); $tag_dp_id = array_filter(array_column($tag_list['list'], 'dpId')); $tag_uid = array_filter(array_column($tag_list['list'], 'memUid')); } $uid_list = []; $uid_list = $tag_uid ? array_merge($tag_uid, $uid) : $uid; $dp_id = !empty($tag_dp_id) ? array_merge($tag_dp_id, $dp_id) : $dp_id; if (!empty($dp_id)) { $dp_list = $user_s->listAll([ 'dpIdList' => $dp_id, 'departmentChildrenFlag' => 1, 'resultFields' => ['memUid'], ]); } $job_list = []; if (!empty($job_id)) { $job_list = $user_s->listAll([ 'jobIdList' => $job_id, 'resultFields' => ['memUid'], ]); } $role_list = []; if (!empty($role_id)) { $role_list = $user_s->listAll([ 'roleIdList' => $role_id, 'resultFields' => ['memUid'], ]); } $user_list = array_merge((array)$dp_list, (array)$job_list, (array)$role_list); } else { // 权限表不存在权限信息,为全公司,直接listAll $result_user = $user_s->listBasicByConds([], 1, 1); $res_list = $user_s->listBasicByConds([], 1, $result_user['total']); $user_list = $res_list['list']; } $user_uids = array_column($user_list, 'memUid'); $user_uids = array_unique(array_merge((array)$user_uids, (array)$uid_list)); // 剔除已参与的人员 $join_uids = array_column($join_list, 'memId'); // 接口wiki原因,memId,不是memID,不是memUid,不是uid $unjoin_uids = array_diff($user_uids, $join_uids); return [ 'unjoin_uids' => $unjoin_uids, // 未参与的uid数组 'unjoin_num' => count($unjoin_uids), // 未参与人数 ]; } }