User.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. <?php
  2. /**
  3. * raingad IM [ThinkPHP6]
  4. * @author xiekunyu <raingad@foxmail.com>
  5. */
  6. namespace app\enterprise\model;
  7. use GatewayClient\Gateway;
  8. use app\BaseModel;
  9. use think\facade\Db;
  10. use think\model\concern\SoftDelete;
  11. use app\manage\model\Config;
  12. use thans\jwt\facade\JWTAuth;
  13. use app\admin\model\Sign;
  14. use app\admin\model\KefuWork;
  15. use app\admin\model\KefuTime;
  16. use app\admin\model\Department;
  17. class User extends BaseModel
  18. {
  19. use SoftDelete;
  20. protected $pk = "user_id";
  21. public static $defaultField = 'user_id,realname,realname as displayName,account,avatar,name_py,email,last_login_ip,service_status,cs_uid,timeout_type,remark,language_code,role,last_login_time,offline_time';
  22. protected $json = ['setting'];
  23. protected $jsonAssoc = true;
  24. // 系统人员或者其他静态人员
  25. public static function staticUser(){
  26. return [
  27. 'adminNotice'=>[
  28. 'id'=>'admin_notice',
  29. 'displayName'=>lang('system.notice'),
  30. 'avatar'=>getMainHost().'/static/common/img/notice.png',
  31. 'name_py'=>'xitongtongzhi',
  32. ],
  33. 'fileTransfer'=>[
  34. 'id'=>-1,
  35. 'displayName'=>lang('system.favor'),
  36. 'avatar'=>getMainHost().'/static/common/img/file_transfer.png',
  37. 'name_py'=>'wodeshoucang',
  38. ]
  39. ];
  40. }
  41. public function getUid()
  42. {
  43. return self::$uid;
  44. }
  45. //查询用户信息
  46. public static function getUserInfo($map=[])
  47. {
  48. if(!$map){
  49. return self::$userInfo;
  50. }
  51. $data = self::where($map)->find();
  52. if ($data) {
  53. $data = $data->toArray();
  54. }
  55. return $data;
  56. }
  57. /**
  58. * 刷新用户token 之前token将被拉黑
  59. * 修改用户数据后 调用该方法 并返回前台更新token
  60. * @param array $info 用户信息
  61. * @param string $terminal 客户端标识
  62. * @return string
  63. * @throws \think\db\exception\DataNotFoundException
  64. * @throws \think\db\exception\DbException
  65. * @throws \think\db\exception\ModelNotFoundException
  66. */
  67. public static function refreshToken($info,$terminal)
  68. {
  69. $info = str_encipher(json_encode($info),true, config('app.aes_token_key'));
  70. $authToken = 'bearer '.JWTAuth::builder(['info' => $info, 'terminal' => $terminal]);
  71. return $authToken;
  72. }
  73. // 获取所有用户列表
  74. public static function getAllUser($map, $user_ids = [],$user_id,$group_id = 0)
  75. {
  76. $field = self::$defaultField;
  77. $list=[];
  78. if($group_id){
  79. $groupUser=GroupUser::where([['group_id','=',$group_id],['role','<>',1],['status','=',1]])->column('user_id');
  80. if($groupUser){
  81. $list=User::where([['user_id','in',$groupUser]])->field($field)->select()->toArray();
  82. }
  83. }else{
  84. $config=Config::getSystemInfo();
  85. // 如果是社区模式,就只查询自己的好友,如果是企业模式,就查询所有用户
  86. if($config['sysInfo']['runMode']==1){
  87. $list = self::where($map)->field($field)->select()->toArray();
  88. }else{
  89. $friendList = Friend::getFriend(['create_user' => $user_id,'status'=>1]);
  90. $userList = array_keys($friendList);
  91. $list = self::where($map)->where('user_id', 'in', $userList)->field($field)->select()->toArray();
  92. }
  93. }
  94. foreach ($list as $k => $v) {
  95. $list[$k]['disabled'] = false;
  96. $list[$k]['avatar'] = avatarUrl($v['avatar'], $v['realname'], $v['user_id']);
  97. if ($user_ids) {
  98. if (in_array($v['user_id'], $user_ids)) {
  99. $list[$k]['disabled'] = true;
  100. }
  101. }
  102. }
  103. return $list;
  104. }
  105. //查询用户列表
  106. public static function getUserList($userInfo, $map, $user_id, $field = "", $role = 0)
  107. {
  108. if (!$field) {
  109. $field = self::$defaultField;
  110. }
  111. $config=Config::getSystemInfo();
  112. // 如果是社区模式,就只查询自己的好友,如果是企业模式,就查询所有用户
  113. if($config['sysInfo']['runMode']==1){
  114. $friendList = Friend::getFriend(['create_user' => $user_id]);
  115. if ($role > 0) {
  116. $list = self::where($map)->whereOr('cs_uid', 0)->field($field)->select();
  117. } else {
  118. $list = self::where($map)->field($field)->select();
  119. }
  120. }else{
  121. $userList = [];
  122. // 将专属客服设置为好友
  123. $csUid=$userInfo['cs_uid'] ?? 0;
  124. if($csUid){
  125. $userList[]=$csUid;
  126. }
  127. // 如果是管理员,就查询整个部门的客服好友
  128. if ($userInfo['role'] > 0) {
  129. $friendList = Friend::getFriend(['create_user' => $user_id,'status'=>1]);//管理员自己的好友
  130. $userList = array_merge($userList, array_keys($friendList));
  131. $admin_id = $userInfo['uid'];
  132. $department_cs_uids = Department::getDepartmentCsUids($admin_id);//整个部门的用户
  133. $department_cs_uids[] = $user_id;
  134. $cus=self::whereIn('cs_uid',$department_cs_uids)->column('user_id');
  135. if($cus){
  136. $userList=array_merge($userList,$cus);
  137. }
  138. }
  139. $userList = array_unique($userList);
  140. $map[] = ['user_id','in',$userList];
  141. $list = self::where($map)->whereOr(function ($query) use ($role) {
  142. if ($role > 0) {
  143. $query->where('role', 0)->where('service_status', 0)->where('is_online', 1);
  144. }
  145. })->field($field)->select();
  146. }
  147. $list_chart = chartSort($list, 'realname', false, 'index');
  148. // 查询未读消息
  149. $unread = Db::name('message')
  150. ->field('from_user,count(msg_id) as unread')
  151. ->where([['to_user', '=', $user_id], ['is_read', '=', 0], ['is_group', '=', 0]])
  152. ->group('from_user')
  153. ->select();
  154. // 查询最近的联系人
  155. $map1 = [['to_user', '=', $user_id], ['is_last', '=', 1], ['is_group', '=', 0]];
  156. $map2 = [['from_user', '=', $user_id], ['is_last', '=', 1], ['is_group', '=', 0]];
  157. $msgField = 'from_user,to_user,content as lastContent,create_time as lastSendTime,chat_identify,type,del_user';
  158. $lasMsgList = Db::name('message')
  159. ->field($msgField)
  160. ->whereOr([$map1, $map2])
  161. ->order('create_time desc')
  162. ->select();
  163. // 查询群聊
  164. $group = Group::getMyGroup(['gu.user_id' => $user_id, 'gu.status' => 1]);
  165. if ($group) {
  166. $group = $group->toArray();
  167. $group_ids = arrayToString($group, 'group_id');
  168. $getGroupLastMsg = Db::name('message')->field($msgField)->where([['to_user', 'in', $group_ids], ['is_group', '=', 1], ['is_last', '=', 1]])->select();
  169. $getAtMsg=Db::name('message')->field($msgField)->where([['to_user', 'in', $group_ids], ['is_group', '=', 1]])->whereFindInSet('at',$user_id)->select();
  170. // halt($getAtMsg);
  171. foreach ($group as $k => $v) {
  172. $setting = $v['setting'] ? json_decode($v['setting'], true) : ['manage' => 0, 'invite' => 1, 'nospeak' => 0];
  173. $group_id = 'group-' . $v['group_id'];
  174. $group[$k]['id'] = $group_id;
  175. $group[$k]['account'] = $group_id;
  176. $group[$k]['avatar'] = avatarUrl($v['avatar'], $v['displayName'], $v['group_id'], 120,1);
  177. $group[$k]['name_py'] = $v['name_py'];
  178. $group[$k]['owner_id'] = $v['owner_id'];
  179. $group[$k]['role'] = $v['role'];
  180. $group[$k]['is_group'] = 1;
  181. $group[$k]['setting'] = $setting;
  182. $group[$k]['index'] = "[2]群聊";
  183. $group[$k]['realname'] = $v['displayName'] . " [群聊]";
  184. $group[$k]['is_notice'] = $v['is_notice'];
  185. $group[$k]['is_top'] = $v['is_top'];
  186. $group[$k]['is_online'] = 1;
  187. $group[$k]['is_at'] = 0;
  188. if ($getGroupLastMsg) {
  189. foreach ($getGroupLastMsg as $key=>$val) {
  190. if ($val['to_user'] == $v['group_id']) {
  191. $group[$k]['type'] =$val['type'];
  192. $group[$k]['lastContent'] = str_encipher($val['lastContent'],false);
  193. $group[$k]['lastSendTime'] = $val['lastSendTime'] * 1000;
  194. // 已经赋值了删除掉提升下次循环的性能
  195. unset($getGroupLastMsg[$key]);
  196. break;
  197. }
  198. }
  199. }
  200. if($getAtMsg){
  201. foreach ($getAtMsg as $key=> $val) {
  202. if ($val['to_user'] == $v['group_id']) {
  203. ++$group[$k]['is_at'];
  204. // 已经赋值了删除掉提升下次循环的性能
  205. unset($getAtMsg[$key]);
  206. }
  207. }
  208. }
  209. }
  210. }
  211. try{
  212. Gateway::$registerAddress = config('gateway.registerAddress');
  213. $onlineList=Gateway::getAllUidList();
  214. }catch(\Exception $e){
  215. $onlineList=[];
  216. }
  217. $isRegion=$config['sysInfo']['ipregion'] ?? 0;
  218. $auto_cs_uid = getAutoCsUid();//获取机器人ID
  219. foreach ($list_chart as $k => $v) {
  220. $last_login_time = $v['last_login_time'];
  221. $is_auto = $v['role'] == 0 && $v['cs_uid'] == $auto_cs_uid ? 1 : 0; //挂在机器人名下的用户
  222. if ($is_auto == 1 && $last_login_time > 0 && $last_login_time < time() - 7*24*60*60) {
  223. unset($list_chart[$k]);//过滤一周前的用户
  224. continue;
  225. }
  226. $lastSendTime = $list_chart[$k]['lastSendTime'];
  227. // 是否有消息通知或者置顶聊天
  228. $friend = isset($friendList[$v['user_id']]) ? $friendList[$v['user_id']] : [];
  229. $list_chart[$k]['id'] = $v['user_id'];
  230. $list_chart[$k]['displayName'] = ($friend['nickname'] ?? '') ? : $v['realname'];
  231. $list_chart[$k]['name_py'] = $v['name_py'];
  232. $list_chart[$k]['avatar'] = avatarUrl($v['avatar'], $v['realname'], $v['user_id'], 120);
  233. $list_chart[$k]['lastContent'] = '';
  234. $list_chart[$k]['unread'] = 0;
  235. $list_chart[$k]['lastSendTime'] = $lastSendTime * 1000;
  236. $list_chart[$k]['offline_time'] = $v['offline_time'] ? date('Y-m-d H:i:s', $v['offline_time']) : '';
  237. $list_chart[$k]['is_group'] = 0;
  238. $list_chart[$k]['setting'] = [];
  239. $list_chart[$k]['is_at'] = 0;
  240. $list_chart[$k]['last_login_ip'] = '';
  241. $list_chart[$k]['location'] ="";
  242. $list_chart[$k]['cs_uid'] = $v['cs_uid'];
  243. $list_chart[$k]['is_auto'] = $is_auto;
  244. $list_chart[$k]['role'] = $v['role'];
  245. $list_chart[$k]['service_status'] = $v['service_status'];
  246. $list_chart[$k]['language_code'] = $v['language_code'];
  247. if($isRegion){
  248. $list_chart[$k]['last_login_ip'] = $v['last_login_ip'];
  249. $list_chart[$k]['location'] =$v['last_login_ip'] ? implode(" ", \Ip::find($v['last_login_ip'])) : "未知";
  250. }
  251. $is_online=0;
  252. if($v['is_online'] == 0 && isset($onlineList[$v['user_id']])){
  253. $is_online=1;
  254. }
  255. $list_chart[$k]['is_online'] = $is_online;
  256. $is_top = 0;
  257. $is_notice = 1;
  258. if ($friend) {
  259. $is_top = $friend['is_top'];
  260. $is_notice = $friend['is_notice'];
  261. }
  262. $list_chart[$k]['is_top'] = $is_top;
  263. $list_chart[$k]['is_notice'] = $is_notice;
  264. if ($unread) {
  265. foreach ($unread as $val) {
  266. if ($val['from_user'] == $v['user_id']) {
  267. $list_chart[$k]['unread'] = $val['unread'];
  268. break;
  269. }
  270. }
  271. }
  272. if ($lasMsgList) {
  273. foreach ($lasMsgList as $val) {
  274. if ($val['from_user'] == $v['user_id'] || $val['to_user'] == $v['user_id']) {
  275. $content = str_encipher($val['lastContent'],false);
  276. // 屏蔽已删除的消息
  277. if ($val['del_user']) {
  278. $delUser = explode(',', $val['del_user']);
  279. if (in_array($user_id, $delUser)) {
  280. $content = "";
  281. }
  282. }
  283. $list_chart[$k]['type'] = $val['type'];
  284. $list_chart[$k]['lastContent'] = $content;
  285. $list_chart[$k]['lastSendTime'] = $val['lastSendTime'] * 1000;
  286. break;
  287. }
  288. }
  289. }
  290. //离线后,取最近一条消息
  291. if ($is_auto && $lastSendTime == 0) {
  292. $map = [['chat_identify', '=', $auto_cs_uid.'-'.$v['user_id']],['is_last', '=', 1], ['is_group', '=', 0]];
  293. $lastMessage = Db::name('message')
  294. ->field($msgField)
  295. ->where($map)
  296. ->order('create_time desc')
  297. ->find();
  298. if ($lastMessage) {
  299. $list_chart[$k]['type'] = $lastMessage['type'];
  300. $list_chart[$k]['lastContent'] = $lastMessage['lastContent'];
  301. $list_chart[$k]['lastSendTime'] = $lastMessage['lastSendTime'] * 1000;
  302. }
  303. }
  304. }
  305. // 合并群聊和联系人
  306. $data = array_merge($list_chart, $group);
  307. // 合并助手消息和聊天消息
  308. $helper=self::otherChat($user_id);
  309. $data=array_merge($data,$helper);
  310. return $data;
  311. }
  312. //查询用户列表
  313. public static function getChatList($user_id, $field = "")
  314. {
  315. if (!$field) {
  316. $field = self::$defaultField;
  317. }
  318. $list_chart=[];
  319. $config=Config::getSystemInfo();
  320. // 查询未读消息
  321. $unread = Db::name('message')
  322. ->field('from_user,count(msg_id) as unread')
  323. ->where([['to_user', '=', $user_id], ['is_read', '=', 0], ['is_group', '=', 0]])
  324. ->group('from_user')
  325. ->select();
  326. $unread = self::matchListKey($unread,'from_user');
  327. // 查询最近的联系人
  328. $map1 = [['to_user', '=', $user_id], ['is_last', '=', 1], ['is_group', '=', 0]];
  329. $map2 = [['from_user', '=', $user_id], ['is_last', '=', 1], ['is_group', '=', 0]];
  330. $msgField = 'from_user,to_user,content as lastContent,create_time as lastSendTime,chat_identify,type,del_user';
  331. $lasMsgList = Db::name('message')
  332. ->field($msgField)
  333. ->whereOr([$map1, $map2])
  334. ->order('create_time desc')
  335. ->select();
  336. if($lasMsgList){
  337. $list=self::matchChatUser($lasMsgList, $user_id);
  338. $list_chart=$list['list'];
  339. $lasMsgList=$list['lastMsg'];
  340. }
  341. // 查询群聊
  342. $group = Group::getMyGroup(['gu.user_id' => $user_id, 'gu.status' => 1]);
  343. $groupList=[];
  344. if ($group) {
  345. $group = $group->toArray();
  346. $group_ids = arrayToString($group, 'group_id');
  347. $getGroupLastMsg = Db::name('message')->field($msgField)->where([['to_user', 'in', $group_ids], ['is_group', '=', 1], ['is_last', '=', 1]])->select();
  348. $getAtMsg=Db::name('message')->field('to_user,count(msg_id) as count')->where([['to_user', 'in', $group_ids], ['is_group', '=', 1]])->whereFindInSet('at',$user_id)->group('to_user')->select();
  349. $getGroupLastMsg=self::matchListKey($getGroupLastMsg,'to_user');
  350. $getAtMsg=self::matchListKey($getAtMsg,'to_user');
  351. $groupList=self::recombileGroupList($group,$getGroupLastMsg,$getAtMsg,false,$user_id);
  352. }
  353. try{
  354. Gateway::$registerAddress = config('gateway.registerAddress');
  355. $onlineList=Gateway::getAllUidList();
  356. }catch(\Exception $e){
  357. $onlineList=[];
  358. }
  359. $isRegion=$config['sysInfo']['ipregion'] ?? 0;
  360. $friendList = Friend::getFriend(['create_user' => $user_id,'status'=>1]);
  361. $list_chart=self::recombineUserList($list_chart,$isRegion,$friendList,$unread,$lasMsgList,$onlineList,$user_id);
  362. // 合并群聊和联系人
  363. $data = array_merge($list_chart, $groupList);
  364. // 合并助手消息和聊天消息
  365. $helper=self::otherChat($user_id);
  366. $data=array_merge($data,$helper);
  367. return $data;
  368. }
  369. // 获取好友列表
  370. public static function getFriendList($map,$user_id,$field='')
  371. {
  372. if (!$field) {
  373. $field = self::$defaultField;
  374. }
  375. $config=Config::getSystemInfo();
  376. // 如果是社区模式,就只查询自己的好友,如果是企业模式,就查询所有用户
  377. if($config['sysInfo']['runMode']==1){
  378. $friendList = Friend::getFriend(['create_user' => $user_id]);
  379. $list = self::where($map)->field($field)->select();
  380. }else{
  381. $friendList = Friend::getFriend(['create_user' => $user_id,'status'=>1]);
  382. $userList = array_keys($friendList);
  383. // 将专属客服设置为好友,6.2+已废弃,客服改为双向好友关系
  384. // $csUid=request()->userInfo['cs_uid'] ?? 0;
  385. // if($csUid){
  386. // $userList[]=$csUid;
  387. // }
  388. // 如果我有客服权限,就查询客服的好友
  389. // $cus=self::where(['cs_uid'=>$user_id])->column('user_id');
  390. // if($cus){
  391. // $userList=array_merge($userList,$cus);
  392. // }
  393. // $userList = array_unique($userList);
  394. $list = self::where($map)->where('user_id', 'in', $userList)->field($field)->select();
  395. }
  396. $list_chart=self::recombineUserList($list,$config['sysInfo']['ipregion'] ?? 0,$friendList);
  397. $list=chartSort($list_chart, 'displayName', false, 'index');
  398. // 合并助手消息和聊天消息
  399. $helper=self::otherChat($user_id);
  400. return array_merge($list,$helper);
  401. }
  402. // 获取好友列表
  403. public static function getGroupList($user_id)
  404. {
  405. // 查询群聊
  406. $group = Group::getMyGroup(['gu.user_id' => $user_id, 'gu.status' => 1]);
  407. $groupList=[];
  408. if ($group) {
  409. $group = $group->toArray();
  410. $groupList=self::recombileGroupList($group,[],[],true);
  411. }
  412. return $groupList;
  413. }
  414. //重新组成标准的群聊数据
  415. protected static function recombileGroupList($group,$getGroupLastMsg=[],$getAtMsg=[],$is_all=false,$user_id=0){
  416. $groupList=[];
  417. foreach ($group as $k => $v) {
  418. $val=$v;
  419. $group_id = 'group-' . $v['group_id'];
  420. if($user_id){
  421. $delChat=ChatDelog::getCache($user_id);
  422. $delChat = $delChat['groupList'] ?? [];
  423. if(in_array($group_id,$delChat)){
  424. continue;
  425. }
  426. }
  427. $groupVal=$getGroupLastMsg[$v['group_id']] ?? [];
  428. if($groupVal){
  429. $val['type'] =$groupVal['type'];
  430. $val['lastContent'] = str_encipher($groupVal['lastContent'],false);
  431. $val['lastSendTime'] = $groupVal['lastSendTime'] * 1000;
  432. }else{
  433. if(!$is_all){
  434. continue;
  435. }
  436. }
  437. $setting = $v['setting'] ? json_decode($v['setting'], true) : ['manage' => 0, 'invite' => 1, 'nospeak' => 0, 'profile' => 0, 'history' => 0];
  438. $val['id'] = $group_id;
  439. $val['account'] = $group_id;
  440. $val['avatar'] = avatarUrl($v['avatar'], $v['displayName'], $v['group_id'], 120,1);
  441. $val['name_py'] = $v['name_py'];
  442. $val['owner_id'] = $v['owner_id'];
  443. $val['role'] = $v['role'];
  444. $val['is_group'] = 1;
  445. $val['setting'] = $setting;
  446. $val['index'] = "[2]群聊";
  447. $val['realname'] = $v['displayName'] . " [群聊]";
  448. $val['is_notice'] = $v['is_notice'];
  449. $val['is_top'] = $v['is_top'];
  450. $val['is_online'] = 1;
  451. $val['is_at'] = 0;
  452. $atMsgVal=$getAtMsg[$v['group_id']] ?? [];
  453. if($atMsgVal){
  454. $val['is_at'] =$atMsgVal['count'];
  455. }
  456. $groupList[]=$val;
  457. }
  458. return $groupList;
  459. }
  460. // 重新组成标准的好友数据
  461. protected static function recombineUserList($list_chart,$isRegion,$friendList,$unread=[],$lasMsgList=[],$onlineList=[],$user_id=0){
  462. $isRegion=$config['sysInfo']['ipregion'] ?? 0;
  463. if($list_chart){
  464. foreach ($list_chart as $k => $v) {
  465. if($user_id){
  466. // 过滤已删除的聊天
  467. $delChat=ChatDelog::getCache($user_id);
  468. $delChat = $delChat['userList'] ?? [];
  469. if(in_array($v['user_id'],$delChat)){
  470. continue;
  471. }
  472. }
  473. // 是否有消息通知或者置顶聊天
  474. $friend = $friendList[$v['user_id']] ?? [];
  475. $list_chart[$k]['id'] = $v['user_id'];
  476. $list_chart[$k]['displayName'] = ($friend['nickname'] ?? '') ? : $v['realname'];
  477. $list_chart[$k]['name_py'] = $v['name_py'];
  478. $list_chart[$k]['avatar'] = avatarUrl($v['avatar'], $v['realname'], $v['user_id'], 120);
  479. $list_chart[$k]['lastContent'] = '';
  480. $list_chart[$k]['unread'] = 0;
  481. $list_chart[$k]['lastSendTime'] = time() * 1000;
  482. $list_chart[$k]['is_group'] = 0;
  483. $list_chart[$k]['setting'] = [];
  484. $list_chart[$k]['is_at'] = 0;
  485. $list_chart[$k]['last_login_ip'] = '';
  486. $list_chart[$k]['location'] ="";
  487. if($isRegion){
  488. $list_chart[$k]['last_login_ip'] = $v['last_login_ip'];
  489. $list_chart[$k]['location'] =$v['last_login_ip'] ? implode(" ", \Ip::find($v['last_login_ip'])) : "未知";
  490. }
  491. $list_chart[$k]['is_online'] = ($onlineList[$v['user_id']] ?? 0) ? 1 : 0;
  492. $is_top = 0;
  493. $is_notice = 1;
  494. if ($friend) {
  495. $is_top = $friend['is_top'];
  496. $is_notice = $friend['is_notice'];
  497. }
  498. $list_chart[$k]['is_top'] = $is_top;
  499. $list_chart[$k]['is_notice'] = $is_notice;
  500. $unrreadVal=$unread[$v['user_id']] ?? [];
  501. $list_chart[$k]['unread'] = $unrreadVal['unread'] ?? 0;
  502. $list_chart[$k]['type'] = 'text';
  503. $lastMsgVal=$lasMsgList[$v['user_id']] ?? [];
  504. if($lastMsgVal){
  505. $content = str_encipher($lastMsgVal['lastContent'],false);
  506. $list_chart[$k]['type'] = $lastMsgVal['type'];
  507. $list_chart[$k]['lastContent'] = $content;
  508. $list_chart[$k]['lastSendTime'] = $lastMsgVal['lastSendTime'] * 1000;
  509. }
  510. }
  511. }
  512. return $list_chart;
  513. }
  514. // 获取机器人聊天消息
  515. public static function otherChat($uid){
  516. return [];
  517. $staticList=self::staticUser();
  518. $adminNotice=$staticList['adminNotice'];
  519. $fileTransfer=$staticList['fileTransfer'];
  520. $count=Message::where(['chat_identify'=>$adminNotice['id']])->count();
  521. $createTime=Message::where(['chat_identify'=>$adminNotice['id']])->order('id desc')->value('create_time');
  522. $sendTime=0;
  523. if($createTime){
  524. $sendTime=is_string($createTime) ? strtotime($createTime) : $createTime;
  525. }
  526. $chat_identify=chat_identify($uid,$fileTransfer['id']);
  527. $fileLast=Message::where(['is_last'=>1,'chat_identify'=>$chat_identify])->find();
  528. $fileSendTime=$fileLast['create_time'] ?? '';
  529. $content =$fileLast['content'] ?? '';
  530. $friend=Friend::where(['create_user'=>$uid,'friend_user_id'=>$fileTransfer['id']])->find();
  531. $notice=[
  532. [
  533. 'id'=>$adminNotice['id'],
  534. 'user_id'=>$adminNotice['id'],
  535. 'displayName'=>$adminNotice['displayName'],
  536. 'realname'=>$adminNotice['displayName'],
  537. 'name_py'=>$adminNotice['name_py'],
  538. 'avatar'=>$adminNotice['avatar'],
  539. 'lastContent'=>$sendTime ? lang('system.announce',['num'=>$count]) :'',
  540. 'unread'=>0,
  541. 'lastSendTime'=>$sendTime * 1000,
  542. 'is_group'=>2,
  543. 'setting'=>[],
  544. 'type'=>'text',
  545. 'is_top'=>0,
  546. 'is_notice'=>1,
  547. 'is_online'=>0,
  548. 'index'=>"",
  549. ],
  550. [
  551. 'id'=>$fileTransfer['id'],
  552. 'user_id'=>$fileTransfer['id'],
  553. 'displayName'=>$fileTransfer['displayName'],
  554. 'realname'=>$fileTransfer['displayName'],
  555. 'name_py'=>$fileTransfer['name_py'],
  556. 'avatar'=>$fileTransfer['avatar'],
  557. 'lastContent'=> str_encipher($content,false) ?: lang('system.transFile'),
  558. 'unread'=>0,
  559. 'lastSendTime'=>((is_string($fileSendTime) ? strtotime($fileSendTime) : $fileSendTime) * 1000) ?: time() * 1000,
  560. 'is_group'=>3,
  561. 'setting'=>[],
  562. 'type'=>$fileLast['type'] ?? 'text',
  563. 'is_top'=>$friend['is_top'] ?? 0,
  564. 'is_notice'=>$friend['is_notice'] ?? 1,
  565. 'is_online'=>0,
  566. 'index'=>"",
  567. ],
  568. ];
  569. return $notice;
  570. }
  571. public static function getList($map)
  572. {
  573. return self::field(self::$defaultField)->where($map)->select();
  574. }
  575. // 匹配用户列表信息(返回用户信息)
  576. public static function matchUser($data, $many = false, $field = 'user_id', $cs = 80)
  577. {
  578. if ($many) {
  579. $idr = arrayToString($data, $field, false);
  580. } else {
  581. $idr = [];
  582. if (is_array($field)) {
  583. foreach ($field as $v) {
  584. $idr[] = $data[$v];
  585. }
  586. } else {
  587. $idr = [$data[$field]];
  588. }
  589. }
  590. $key = array_search(0, $idr);
  591. if ($key) {
  592. array_splice($idr, $key, 1);
  593. }
  594. $userList = self::where([['user_id', 'in', $idr]])->field(self::$defaultField)->select()->toArray();
  595. $friend = Friend::where([['friend_user_id', 'in', $idr],['create_user','=',self::$uid]])->field('friend_user_id,nickname')->select()->toArray();
  596. $list = [];
  597. foreach ($userList as $v) {
  598. $v['avatar'] = avatarUrl($v['avatar'], $v['realname'], $v['user_id'], $cs);
  599. $v['id'] = $v['user_id'];
  600. if($friend){
  601. foreach($friend as $key=>$val){
  602. if($val['friend_user_id']==$v['user_id']){
  603. $v['realname']=$val['nickname'] ? : $v['displayName'];
  604. break;
  605. }
  606. }
  607. }
  608. $list[$v['user_id']] = $v;
  609. }
  610. return $list;
  611. }
  612. // 匹配联系人列表
  613. public static function matchChatUser($data,$user_id)
  614. {
  615. $idr=[];
  616. $lastMsg=[];
  617. foreach($data as $k=>$v){
  618. $idr[]=$v['from_user'];
  619. $idr[]=$v['to_user'];
  620. if($v['from_user']==$user_id){
  621. $lastMsg[$v['to_user']]=$v;
  622. continue;
  623. }
  624. if($v['to_user']==$user_id){
  625. $lastMsg[$v['from_user']]=$v;
  626. continue;
  627. }
  628. }
  629. $key = array_search(0, $idr);
  630. if ($key) {
  631. array_splice($idr, $key, 1);
  632. }
  633. $idr = array_diff($idr, [$user_id]);
  634. $list = self::where([['user_id', 'in', $idr]])->field(self::$defaultField)->select()->toArray();
  635. return [
  636. 'list'=>$list,
  637. 'lastMsg'=>$lastMsg
  638. ];
  639. }
  640. // 匹配用户列表信息(返回data)
  641. public static function matchAllUser($data, $many = false, $field = 'user_id', $key = "userInfo", $cs = 80)
  642. {
  643. if ($many) {
  644. $idr = arrayToString($data, $field);
  645. $userList = self::getList([['user_id', 'in', $idr]]);
  646. $userList=self::matchListKey($userList,'user_id');
  647. foreach ($data as $k => $v) {
  648. $vv=$userList[$v[$field]] ?? [];
  649. if($vv){
  650. $data[$k][$key] = [
  651. 'id' => $vv['user_id'],
  652. 'displayName' => $vv['realname'],
  653. 'account' => $vv['account'],
  654. 'name_py' => $vv['name_py'],
  655. 'avatar' => avatarUrl($vv['avatar'], $vv['realname'], $vv['user_id'], $cs),
  656. ];
  657. }else{
  658. $data[$k][$key]=[];
  659. }
  660. }
  661. } else {
  662. $user = self::getUserInfo(['user_id' => $data[$field]]);
  663. $data[$key] = [
  664. 'id' => $user['user_id'],
  665. 'displayName' => $user['realname'],
  666. 'account' => $user['account'],
  667. 'name_py' => $user['name_py'],
  668. 'avatar' => avatarUrl($user['avatar'], $user['realname'], $user['user_id']),
  669. ];
  670. }
  671. return $data;
  672. }
  673. // 将id转换成联系人信息
  674. public function setContact($id,$is_group=0,$type='text',$content='',$contactInfo=null){
  675. $data=[
  676. 'id'=>$id,
  677. 'lastContent'=>$content,
  678. 'unread'=>0,
  679. 'lastSendTime'=> time() * 1000,
  680. 'is_group'=>$is_group,
  681. 'is_top'=>0,
  682. 'is_notice'=>1,
  683. 'is_top'=>0,
  684. 'is_at'=>0,
  685. 'setting'=>[],
  686. 'type'=>$type,
  687. 'location'=>'',
  688. ];
  689. if($is_group==0){
  690. $user=$contactInfo ?: User::where('user_id',$id)->find();
  691. if(!$user){
  692. $this->error=lang('user.exist');
  693. return false;
  694. }
  695. $user->avatar=avatarUrl($user->avatar,$user->realname,$user->user_id,120);
  696. // 查询好友关系
  697. $friend= self::$userInfo ? Friend::where(['friend_user_id'=>$id,'create_user'=>self::$userInfo['user_id']])->find() : [];
  698. $data['displayName'] = ($friend['nickname'] ?? '') ? : $user['realname'];
  699. $data['avatar'] = avatarUrl($user['avatar'], $user['realname'], $user['user_id'], 120);
  700. $data['location'] =$user['last_login_ip'] ? implode(" ", \Ip::find($user['last_login_ip'])) : "未知";
  701. $data['name_py'] = $user['name_py'];
  702. }else{
  703. $group_id=is_numeric($id) ? $id : (explode('-',$id)[1] ?? 0);
  704. $group=$contactInfo ?: Group::where(['group_id'=>$group_id])->find();
  705. if(!$group){
  706. $this->error=lang('group.exist');
  707. return false;
  708. }
  709. $data['id'] = 'group-'.$group_id;
  710. $data['displayName'] = $group['name'];
  711. $data['avatar'] = avatarUrl($group['avatar'], $group['name'], $group['group_id'], 120,1);
  712. $data['name_py'] = $group['name_py'];
  713. $data['setting'] = $group['setting'];
  714. $data['role'] = 3;
  715. }
  716. $data['index'] =getFirstChart($data['displayName']);
  717. return $data;
  718. }
  719. // 验证账号的合法性
  720. public function checkAccount(&$data){
  721. $user_id=$data['user_id'] ?? 0;
  722. if($user_id){
  723. $user=self::find($data['user_id']);
  724. if(!$user){
  725. $this->error='账户不存在';
  726. return false;
  727. }
  728. if($user->user_id==1 && self::$uid!=1){
  729. $this->error='超管账户只有自己才能修改';
  730. return false;
  731. }
  732. $other=self::where([['account','=',$data['account']],['user_id','<>',$data['user_id']]])->find();
  733. if($other){
  734. $this->error='账户已存在';
  735. return false;
  736. }
  737. }else{
  738. $user=self::where('account',$data['account'])->find();
  739. if($user){
  740. $this->error='账户已存在';
  741. return false;
  742. }
  743. }
  744. $config=Config::getSystemInfo();
  745. $regauth=$config['sysInfo']['regauth'] ?? 0;
  746. $acType=\utils\Regular::check_account($data['account']);
  747. switch($regauth){
  748. case 1:
  749. if($acType!=1){
  750. $this->error='当前系统只允许账号为手机号!';
  751. return false;
  752. }
  753. break;
  754. case 2:
  755. if($acType!=2){
  756. $this->error='当前系统只允许账号为邮箱!';
  757. return false;
  758. }
  759. break;
  760. case 3:
  761. // 验证账号是否为手机号或者邮箱
  762. if(!$acType){
  763. $this->error='账户必须为手机号或者邮箱';
  764. return false;
  765. }
  766. break;
  767. default:
  768. break;
  769. }
  770. $data['is_auth'] =$regauth ? 1 : 0;
  771. $email=$data['email'] ?? '';
  772. if($data['is_auth'] && $acType==2 && !$email){
  773. $data['email'] =$data['account'];
  774. }
  775. return true;
  776. }
  777. //设置用户在线状态
  778. public static function setOnline($user_id, $is_online)
  779. {
  780. $user = self::where('user_id',$user_id)->find();
  781. if (!$user) {
  782. return false;
  783. }
  784. //离线
  785. if ($is_online == 0 && $user->role == 3) {
  786. //结束今日的签到
  787. $sign = Sign::where('admin_id', $user->uid)->where('created_at', '>=', date('Y-m-d'))->order('id', 'desc')->find();
  788. if ($sign && $sign->time == 0) {
  789. $sign->time = time() - strtotime($sign->created_at);
  790. $sign->updated_at = date('Y-m-d H:i:s');
  791. $sign->save();
  792. }
  793. //结束客服在线时间
  794. KefuTime::endData($user->uid, 2);
  795. //结束客服接线时间
  796. KefuTime::endData($user->uid, 3, $user->cs_uid);
  797. //结束客服服务时间
  798. KefuTime::endData($user->uid, 4);
  799. }
  800. //上线
  801. if ($user->is_online == 0 && $is_online != 0 && $user->role == 3) {
  802. //添加客服上线次数
  803. KefuWork::addNum($user->uid, 'online_num');
  804. //通知客服签到
  805. wsSendMsg($user->user_id,'sign',['is_sign'=>1]);
  806. }
  807. //忙碌
  808. if ($user->is_online != 2 && $is_online == 2 && $user->role == 3) {
  809. //更新客服忙碌次数
  810. KefuWork::addNum($user->uid, 'busy_num');
  811. }
  812. if ($user->is_online == 2 && $is_online != 2 && $user->role == 3) {
  813. //结束客服忙碌时间
  814. KefuTime::endData($user->uid, 1);
  815. }
  816. $update_data = [
  817. 'is_online' => $is_online,
  818. ];
  819. if ($is_online == 0) {
  820. $update_data['offline_time'] = time();
  821. } else {
  822. $update_data['is_finished'] = 0;
  823. }
  824. return self::where('user_id', $user_id)->update($update_data);
  825. }
  826. public static function isOnline($user_id = null)
  827. {
  828. return $user_id ? Gateway::isUidOnline($user_id) : 0;
  829. }
  830. }