<?php /** * Service 层基类 * AbstractService.class.php * @copyright: vchangyi.com */ namespace Common\Service; use Common\Common\Cache; use Common\Common\Department; use Common\Common\User; use Common\Common\Msg; use Common\Model\CommonModel; use Common\Model\EducationModel; use Common\Model\RightModel; abstract class AbstractService extends \Com\Service { // 每页数量 const PAGE_LIMIT_DEFAULT = 10; // 默认页码 const PAGE_DEFAULT = 1; // 考试默认图片 const DEFAULT_TRAIN_COVER = '/admincp/imgs/client/app/components/my-app/train-new/train-add/train-default-pic.jpg'; // 全公司 const IS_ALL = 1; // 非全公司 const NOT_IS_ALL = 0; // 查询人员状态:已关注 const USER_STATUS_FOLLOW = 1; // 发消息类型:培训通知 const MSG_EDUCATION_PUBLISH = 1; // 发消息类型:培训提醒 const MSG_EDUCATION_REMIND = 2; // 发消息类型:培训报名通知 const MSG_EDUCATION_SIGN = 3; // 发消息提醒:审核通知 const MSG_CHECK_STATUS = 4; // 发消息提醒:发放勋章 const MSG_GIVE_MEDAL = 5; // 构造方法 public function __construct() { parent::__construct(); } /** * 即时消息通知方法 【发消息统一写这里,方便维护】 * * @param $params -通知参数 * + uids -用户uid数组 * + memID -用户uid * + dp_ids -部门id数组 * + dpID -部门id * + tag_ids -标签id数组 * + tagID -标签id * + ed_id -培训ID * + description -摘要 * + img_id -封面图片ID * + name -培训名称 * + address -培训地址 * + msg -提前终止原因 * + content -提醒内容 * + begin_time -开始时间 * + end_time -结束时间 * + check_status -审核状态 * @param $type -通知文案类型 * * @return bool */ public function send_msg($params, $type) { // 获取运营管理icon对应的应用名称 $recommender_m = new CommonModel('CommonRecommender', 'oa_'); $icon_conditons = [ 'app_dir' => 'Train', 'type' => 2 ]; $recommender = $recommender_m->get_by_conds($icon_conditons); $appName = $recommender['title']; // 本方法根据类型区分拼接不通的文案 switch ($type) { case self::MSG_EDUCATION_PUBLISH: $data = [ 'title' => '【' . $appName . '】' . $params['name'], 'description' => rgmdate((string)$params['begin_time'], 'Y-m-d H:i') . '-' . rgmdate((string)$params['end_time'], 'Y-m-d H:i') . "\r\n" . $params['address'], 'picUrl' => $this->format_cover($params['img_id']), ]; break; case self::MSG_EDUCATION_REMIND: $data = [ 'title' => '【' . $appName . '】消息提醒', 'description' => '培训名称:' . $this->cutstr($params['name'], 0, 20) . "\r\n通知内容:" . $this->cutstr($params['content'], 0, 80) . "\r\n通知时间:" . rgmdate(strval(MILLI_TIME), 'Y-m-d'), ]; break; case self::MSG_CHECK_STATUS: $data = [ 'title' => '【' . $appName . '】报名审核', 'description' => '培训名称:' . $this->cutstr($params['name'], 0, 20) . "\r\n审核状态:" . $params['check_status'] . "\r\n通知内容:" . $this->cutstr($params['content'], 0, 80) . "\r\n审核时间:" . rgmdate(strval(MILLI_TIME), 'Y-m-d'), ]; break; case self::MSG_EDUCATION_SIGN: $data = [ 'title' => '【' . $appName . '】报名支付', 'description' => '培训名称:' . $this->cutstr($params['name'], 0, 20) . "\r\n支付状态:" . $params['pay_status'] . "\r\n支付时间:" . rgmdate((string)$params['pay_time'], 'Y-m-d H:i'), ]; break; case self::MSG_GIVE_MEDAL: $app_name = cfg('APPLICATION_NAME', null, ''); $data = [ 'title' => '【' . $appName . '】培训激励', 'description' => '消息名称:恭喜您,获得【' . $params['name'] . '】勋章' . "\r\n获取渠道:{$app_name}-" . $params['ed_name'] . "\r\n获取时间:" . rgmdate(strval(MILLI_TIME), 'Y-m-d H:i'), ]; break; default: return true; } $this->send($params, $data); return true; } /** * 发送消息 * * @param $params -通知参数 * + uids -用户uid数组 * + memID -用户uid * + dp_ids -部门id数组 * + dpID -部门id * + tag_ids -标签id数组 * + tagID -标签id * + ed_id -培训ID * + my_medal -勋章消息标识 * @param array $condition 消息参数 * + title -标题 * + description -内容 * + picUrl -图片URL * * @return bool */ private function send($params = [], $condition = []) { // 发送消息接收人 $toUser = array_unique(array_filter(array_column($params['uids'], 'memID'))); if (empty($toUser)) { $toUser = $params['uids']; } $msgUser = implode('|', $toUser); // 发送消息部门 $toParty = array_unique(array_filter(array_column($params['dp_ids'], 'dpID'))); if (empty($toParty)) { $toParty = $params['dp_ids']; } // 发送消息标签 $toTag = array_unique(array_filter(array_column($params['tag_ids'], 'tagID'))); if (empty($toTag)) { $toTag = $params['tag_ids']; } // 非勋章消息 $my_medal = 0; // 勋章消息 if ($params['my_medal']) { $my_medal = $params['my_medal']; } // 实例化发消息SDK $sdk_msg = Msg::instance(); $msg['toUser'] = !empty($msgUser) ? $msgUser : ''; // 接收人 $msg['toParty'] = !empty($toParty) ? implode('|', $toParty) : ''; $msg['toTag'] = !empty($toTag) ? implode('|', $toTag) : ''; $msg['articles'] = [ [ 'title' => $condition['title'], 'description' => $condition['description'], 'url' => oaUrl('Frontend/Index/Msg/Index', [ 'ed_id' => $params['ed_id'], 'my_medal' => $my_medal ] ), 'picUrl' => $condition['picUrl'], ], ]; $sdk_msg->sendNews($msg['toUser'], $msg['toParty'], $msg['toTag'], $msg['articles']); return true; } /** * 获取用户信息列表 * * @param array * * @return array */ public function get_all_user_by_cache($uids = []) { // 用户信息初始化 $user = &User::instance(); $cache = &Cache::instance(); $user_list = []; // 防止缓存不存在时出错 try { $user_list = $cache->get('Common.Train_User_List'); } catch (\Think\Exception $e) { \Think\Log::record($e); } catch (\Exception $e) { \Think\Log::record($e); } $user_res = $user->listBasicByConds(['memSubscribeStatus' => self::USER_STATUS_FOLLOW], 1, 1); // 如果缓存不存在 if (empty($user_list) || (count($user_list) != $user_res['total'])) { $users = $user->listAll(); $user_list = []; foreach ($users as $v) { if ($v['memSubscribeStatus'] != self::USER_STATUS_FOLLOW) { // 过滤未关注的用户 continue; } $arr = [ 'memUid' => $v['memUid'], 'memUserid' => $v['memUserid'], 'memMobile' => $v['memMobile'], 'memEmail' => $v['memEmail'], 'memActive' => $v['memActive'], 'memUsername' => $v['memUsername'], 'memFace' => $v['memFace'], 'memSubscribeStatus' => $v['memSubscribeStatus'], 'memJob' => $v['memJob'], 'memRole' => $v['memRole'], 'dpName' => $v['dpName'] ]; $user_list[$v['memUid']] = $arr; } if (!empty($user_list)) { // 实例化缓存 $cache->set('Common.Train_User_List', $user_list); } } if (empty($uids)) { return $user_list; } $user_info_list = []; foreach ($user_list as $k => $v) { if (in_array($k, $uids)) { $user_info_list[$k] = $v; } } // 获取缓存中不存在的用户信息 $all_uids = array_filter(array_column($user_list, 'memUid')); $no_uids = array_diff($uids, $all_uids); // 获取缓存中不存在的或者已被删除的用户信息 foreach ($no_uids as $_v) { $users_info = $user->getByUid($_v); $arr = []; $arr['memUid'] = $users_info['memUid']; $arr['memUserid'] = $users_info['memUserid']; $arr['memMobile'] = $users_info['memMobile']; $arr['memEmail'] = $users_info['memEmail']; $arr['memActive'] = $users_info['memActive']; $arr['memUsername'] = $users_info['memUsername']; $arr['memFace'] = $users_info['memFace']; $arr['memSubscribeStatus'] = $users_info['memSubscribeStatus']; $arr['memJob'] = $users_info['memJob']; $arr['memRole'] = $users_info['memRole']; $arr['dpName'] = $users_info['dpName']; $user_info_list[$arr['memUid']] = $arr; } return $user_info_list; } /** * 根据部门ID集合,角色ID,岗位ID获取人员ID集合 * * @author daijun * * @param array $dp_ids 部门ID集合 * @param String $role_id 角色ID * @param String $job_id 岗位ID * @param String $memUsername 用户名 * * @return array */ public function list_uids_by_dp_job_role($dp_ids = [], $role_id = '', $job_id = '', $memUsername = '') { $User = new User(); // 部门查询 $uids = []; if ($dp_ids) { $department = new Department(); $dpIDs = array_unique($dp_ids); sort($dpIDs); // 查询子部门 $department_data = $department->list_childrens_by_cdid($dpIDs, true); // 搜索当前部门 $department_data = array_merge($dpIDs, $department_data); $department_data = array_unique($department_data); // 升序 sort($department_data); // 查询部门所有用户 $user_list = $User->listAll( [ 'dpIdList' => $department_data, 'memSubscribeStatus' => self::USER_STATUS_FOLLOW ]); $dpid_uid = array_column($user_list, 'memUid'); $uids = $dpid_uid; } // 角色查询 if ($role_id) { $role_ids = [$role_id]; $user_list = $User->listAll( [ 'roleIdList' => $role_ids, 'memSubscribeStatus' => self::USER_STATUS_FOLLOW ]); $role_uid = array_column($user_list, 'memUid'); if ($dp_ids) { $uids = array_intersect($uids, $role_uid); } else { $uids = $role_uid; } } // 岗位查询 if ($job_id) { $job_ids = [$job_id]; $user_list = $User->listAll( [ 'jobIdList' => $job_ids, 'memSubscribeStatus' => self::USER_STATUS_FOLLOW ]); $job_uid = array_column($user_list, 'memUid'); if ($dp_ids || $role_id) { $uids = array_intersect($uids, $job_uid); } else { $uids = $job_uid; } } // 按照名称搜索 if ($memUsername) { $user_list = $User->listAll( [ 'memUsername' => $memUsername, 'memSubscribeStatus' => self::USER_STATUS_FOLLOW ]); $user_uid = array_column($user_list, 'memUid'); if (!empty($uids)) { $uids = array_intersect($uids, $user_uid); } else { $uids = $user_uid; } } return $uids; } /** * 字符串截取,支持中文和其他编码 * * access public * * @param string $str 需要转换的字符串 * @param int $start 开始位置 * @param int $length 截取长度 * @param string $charset 编码格式 * @param bool $suffix 截断显示字符 * * @return string */ public function cutstr($str, $start, $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 $slice; } /** * 格式化培训的封面图片地址 * * @param string $cover_id 封面 ID * * @return string 封面 URL */ public function format_cover($cover_id) { // 初始化默认图片地址 $cover_url = cfg('PROTOCAL') . $_SERVER['HTTP_HOST'] . self::DEFAULT_TRAIN_COVER . '?time=' . time(); if (!empty($cover_id)) { $cover_url = imgUrlReal($cover_id); } return $cover_url; } /** * 替换字符串中的/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 string $ed_id 培训ID */ public function recommender($ed_id = '') { $edu_serv = new EducationModel(); // 获取培训数据 $education = $edu_serv->get($ed_id); // 开启首页推荐 if (EducationService::RECOMMEND_INDEX_TRUE == $education['ed_is_recommend']) { $url = rpcUrl('/Public/Rpc/Recommender/ArticleUpdate'); $rpc_params = [ 'app' => 'train', 'dataCategoryId' => '', 'dataId' => $ed_id, 'title' => $education['ed_name'], 'summary' => $education['ed_introductions'], 'attachId' => $education['ed_cover_id'], 'pic' => !empty($education['ed_cover_id']) ? imgUrlReal($education['ed_cover_id']) : '', 'url' => 'Train/Frontend/Index/Msg?&ed_id=' . $ed_id, ]; $right_serv = new RightModel(); // 获取权限表数据 $right_all = $right_serv->get_by_conds([ 'obj_type' => 1, // 权限类型为全公司 'ed_id' => $ed_id ]); // 是否推荐给全公司 if (empty($right_all)) { $right_user_list = $this->_d->list_by_conds(['ed_id' => $ed_id]); $uids = array_unique(array_filter(array_column($right_user_list, 'ru_uid'))); if (!empty($uids)) { sort($uids); // 获取权限数据 $rpc_params['right']['users'] = $uids; \Com\Rpc::phprpc($url)->invoke('Index', $rpc_params); } } else { $rpc_params['right'] = []; \Com\Rpc::phprpc($url)->invoke('Index', $rpc_params); } } } }