Member.php 103 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428
  1. <?php
  2. namespace app\weixin\model;
  3. use app\weixin\service\PRedis;
  4. use think\Db;
  5. use think\Model;
  6. class Member extends Model
  7. {
  8. protected $table = 'sg_user';
  9. /**
  10. * 注册用户
  11. * @param $params 注册参数
  12. * @return int|string
  13. */
  14. public static function regMember($params)
  15. {
  16. $mobile = isset($params['mobile']) ? trim($params['mobile']) : '';
  17. $userPass = isset($params['password']) ? trim($params['password']) : '';
  18. $payPass = isset($params['pay_password']) ? trim($params['pay_password']) : '';
  19. if ($mobile && Member::where(['user_login' => $mobile])->value('id')) {
  20. return 2001;
  21. }
  22. $userName = $mobile ? $mobile : makeUserName();
  23. $userPass = $userPass ? cmf_password($userPass) : cmf_password('123456');
  24. $payPass = $payPass ? cmf_password($payPass) : $userPass;
  25. $wxInfo = isset($params['wxInfo']) ? $params['wxInfo'] : [];
  26. $openid = isset($wxInfo['openid']) ? trim($wxInfo['openid']) : '';
  27. $headimgurl = isset($wxInfo['headimgurl']) ? trim($wxInfo['headimgurl']) : '';
  28. $nickname = isset($wxInfo['nickname']) ? trim($wxInfo['nickname']) : $userName;
  29. if (empty($openid)) {
  30. return false;
  31. }
  32. $data = [
  33. 'user_type' => 2,
  34. 'sex' => isset($params['sex']) ? intval($params['sex']) : 0,
  35. 'openid' => $openid,
  36. 'parent_id' => isset($params['parent_id']) ? intval($params['parent_id']) : 0,
  37. 'user_nickname' => isset($params['user_nickname']) ? trim($params['user_nickname']) : $nickname,
  38. 'avatar' => isset($params['avatar']) ? trim($params['avatar']) : $headimgurl,
  39. 'user_login' => $userName,
  40. 'user_pass' => $userPass,
  41. 'pay_password' => $payPass,
  42. 'is_follow' => isset($wxInfo['subscribe']) ? intval($wxInfo['subscribe']) : 0,
  43. 'last_login_ip' => get_client_ip(),
  44. 'last_login_time' => time(),
  45. 'create_time' => time(),
  46. ];
  47. if ($mobile) {
  48. $data['mobile'] = $mobile;
  49. }
  50. $userId = Member::where(['openid' => $openid])
  51. ->where('user_status', '>=', 0)
  52. ->value('id');
  53. PRedis::set('test:' . $openid, $data, 600);
  54. if (!$userId) {
  55. $userId = Member::insertGetId($data);
  56. return ['userId' => $userId, 'type' => 2];
  57. } else {
  58. $data = [
  59. 'last_login_ip' => get_client_ip(),
  60. 'updated_at' => date('Y-m-d H:i:s'),
  61. ];
  62. Member::where(['openid' => $openid])
  63. ->where('user_status', '>=', 0)
  64. ->update($data);
  65. return false;
  66. }
  67. }
  68. /**
  69. * 用户登录
  70. * @param $params
  71. * @return array|int|null|\PDOStatement|string|Model
  72. * @throws \think\Exception
  73. * @throws \think\db\exception\DataNotFoundException
  74. * @throws \think\db\exception\ModelNotFoundException
  75. * @throws \think\exception\DbException
  76. * @throws \think\exception\PDOException
  77. */
  78. public static function login($params)
  79. {
  80. $userName = isset($params['mobile']) ? trim($params['mobile']) : '';
  81. $password = isset($params['password']) ? trim($params['password']) : '';
  82. $field = 'id,user_login,sex,user_nickname,avatar,openid,user_pass,user_type,score,balance,user_status';
  83. $userInfo = Member::where(['user_login' => $userName])->field($field)->find();
  84. $userPass = isset($userInfo['user_pass']) ? $userInfo['user_pass'] : '';
  85. $userStatus = isset($userInfo['user_status']) ? intval($userInfo['user_status']) : 0;
  86. if (empty($userInfo)) {
  87. return 2100;
  88. }
  89. $userInfo = $userInfo->toArray();
  90. if (!cmf_compare_password($password, $userPass)) {
  91. return 2101;
  92. }
  93. if ($userStatus != 1) {
  94. return 2102;
  95. }
  96. // 更新登录数据
  97. $updateData = [
  98. 'updated_at' => date('Y-m-d H:i:s'),
  99. 'last_login_ip' => get_client_ip(),
  100. 'last_login_time' => time(),
  101. ];
  102. $curOpenId = session('openid');
  103. $openid = isset($userInfo['openid']) ? trim($userInfo['openid']) : '';
  104. if ($curOpenId) {
  105. $checkId = Member::where(['openid' => $curOpenId])->value('id');
  106. if ((empty($checkId) && empty($openid)) || ($checkId && $checkId == $userInfo['id'])) {
  107. $wxInfo = session('wxInfo');
  108. $headimgurl = isset($wxInfo['headimgurl']) ? trim($wxInfo['headimgurl']) : '';
  109. $nickname = isset($wxInfo['nickname']) ? trim($wxInfo['nickname']) : $userName;
  110. $sex = isset($wxInfo['sex']) ? intval($wxInfo['sex']) : 0;
  111. if (empty($openid)) {
  112. $updateData['openid'] = $curOpenId;
  113. }
  114. if ($headimgurl && $userInfo['avatar'] != $headimgurl) {
  115. $updateData['avatar'] = $headimgurl;
  116. }
  117. if ($nickname && $userInfo['user_nickname'] != $nickname) {
  118. $updateData['user_nickname'] = $nickname;
  119. }
  120. if ($sex && $userInfo['sex'] != $sex) {
  121. $updateData['sex'] = $sex;
  122. }
  123. }
  124. }
  125. Member::where(['user_login' => $userName])->update($updateData);
  126. unset($userInfo['user_pass']);
  127. $userInfo = array_merge($userInfo, $updateData);
  128. session('userInfo', $userInfo);
  129. return $userInfo;
  130. }
  131. /**
  132. * 获取会员信息
  133. * @param $where 条件
  134. * @param string $field 字段
  135. * @return array|false|\PDOStatement|string|Model
  136. */
  137. public static function getInfo($where, $field = "")
  138. {
  139. $field = $field ? $field : 'id,openid,user_nickname,user_type,agent_type,agent_status,avatar,user_login,collect_expire,lat,lng,address,real_name,redheart,is_reg_profile,mobile,balance,user_status,wechat_account as wechat_code,is_heart,vip_auth,vip_expire,is_follow,freezing_choose';
  140. $info = self::where($where)->field($field)->order('user_status desc,id desc')->find();
  141. return $info ? $info->toArray() : [];
  142. }
  143. /**
  144. * 获取用户主页信息
  145. * @param $userId 用户ID
  146. * @param string $field 字段
  147. * @return array
  148. */
  149. public static function getHomeInfo($userId, $field = '', $type = 0)
  150. {
  151. $where = ['m.id' => $userId, 'm.user_status' => 1, 'm.user_type' => 2];
  152. $defaultField = 'm.id,m.user_nickname,m.avatar,m.mobile,m.sex,m.birthday,m.is_heart,m.real_name,m.agent_type,m.agent_status,up.age,up.height,up.weight,up.company,up.occupation,up.property,up.graduate,up.education,up.province,up.salary,up.city,up.district,up.home_province,up.home_city,up.home_district,up.introduce,up.family,up.hobby,up.purpose,up.cause,up.expect,up.show_company,up.show_graduate,up.married,up.tags,up.isinfo,up.photolist';
  153. if ($type == 3 || $type == 4) {
  154. $defaultField = 'm.id,m.user_nickname,m.avatar,m.mobile,m.sex,m.is_heart,m.birthday,m.real_name,up.age,up.height,up.weight,up.company,up.occupation,up.property,up.graduate,up.education,up.photolist,up.salary,up.province,up.city,up.district,up.home_province,up.home_city,up.home_district,up.introduce,up.brief,up.family,up.hobby,up.purpose,up.cause,up.expect,up.show_company,up.show_graduate,up.married,up.isinfo,m.vip_auth,m.vip_expire,up.education_check,up.education_type,up.position_type,up.position_check,up.idcard_check,up.introduce_img,up.family_img,up.hobby_img,up.purpose_img,up.tags,up.cause_img,up.expect_img';
  155. } else if ($type == 2) {
  156. $defaultField = 'm.id,m.user_nickname,m.wechat_account,m.mobile,m.sex,m.birthday,m.real_name,up.age,up.height,up.weight,up.company,up.occupation,up.property,up.graduate,m.is_heart,up.education,up.province,up.salary,up.city,up.district,up.home_province,up.home_city,up.home_district,up.married,up.wechat_code,up.qq,up.education_check,up.position_check,up.idcard_check';
  157. }
  158. $field = $field ? $field : $defaultField;
  159. $info = Member::alias('m')
  160. ->join('user_profile up', 'up.userid=m.id', 'left')
  161. ->field($field)
  162. ->where($where)
  163. ->where('user_status', '>=', 0)
  164. ->find();
  165. if ($info) {
  166. if (isset($info['avatar'])) {
  167. $info['avatar'] = cmf_get_image_preview_url($info['avatar']);
  168. }
  169. if (isset($info['brief'])) {
  170. $info['brief'] = htmlspecialchars_decode($info['brief']);
  171. }
  172. if (isset($info['sex'])) {
  173. $sexs = ['', '男', '女'];
  174. $sex = isset($info['sex']) ? $info['sex'] : 0;
  175. $info['sex_txt'] = isset($sexs[$sex]) ? $sexs[$sex] : '';
  176. }
  177. $info['albums'] = [];
  178. $photolist = isset($info['photolist']) ? $info['photolist'] : '';
  179. $photolist = $photolist ? explode(',', $photolist) : [];
  180. if ($photolist) {
  181. $albums = [];
  182. foreach ($photolist as $k => $val) {
  183. $albums[] = cmf_get_image_preview_url($val);
  184. }
  185. $info['albums'] = $albums;
  186. }
  187. if (isset($info['birthday'])) {
  188. $birthday = isset($info['birthday']) ? $info['birthday'] : 0;
  189. $info['birthday_txt'] = $birthday ? date('Y年m月d日', $birthday) : '';
  190. $info['birthday_code'] = $birthday ? date('Y-m-d', $birthday) : '';
  191. $info['birthday_day'] = $birthday ? date('y年', $birthday) : '';
  192. $year = $birthday ? date('Y', $birthday) : 0;
  193. if ($year) {
  194. $info['age'] = date('Y') - $year;
  195. $info['year'] = $year;
  196. }
  197. $month = date('m-d', $birthday);
  198. $info['start'] = getStart($month);
  199. }
  200. $info['height_txt'] = '';
  201. if (isset($info['height'])) {
  202. $height = isset($info['height']) ? intval($info['height']) : 0;
  203. $info['height'] = intval($height);
  204. $info['height_txt'] = $height ? intval($info['height']) . 'CM' : '无';
  205. }
  206. $info['weight_txt'] = '';
  207. if (isset($info['weight'])) {
  208. $weight = isset($info['weight']) ? intval($info['weight']) : 0;
  209. $info['weight'] = intval($weight);
  210. $info['weight_txt'] = $weight ? intval($info['weight']) . 'KG' : '无';
  211. }
  212. // 学历
  213. $info['education_txt'] = '';
  214. if (isset($info['education'])) {
  215. $educations = config('weixin.educations');
  216. $edu = isset($info['education']) ? $info['education'] : 0;
  217. $info['education_txt'] = isset($educations[$edu]) ? $educations[$edu] : '无';
  218. }
  219. // 资产
  220. $info['property_txt'] = '暂无';
  221. $property = isset($info['property']) ? $info['property'] : 0;
  222. if (isset($info['property'])) {
  223. $propertys = config('weixin.propertys');
  224. $info['property'] = $property;
  225. $info['property_txt'] = $property && isset($propertys[$property]) ? $propertys[$property] : '暂无';
  226. }
  227. // 地址
  228. $item['now_address'] = '';
  229. if (isset($info['province'])) {
  230. $province = isset($info['province']) ? trim($info['province']) : '';
  231. $city = isset($info['city']) ? trim($info['city']) : '';
  232. $info['now_address'] = trim($province . ' ' . $city);
  233. if ($type == 2) {
  234. $district = isset($info['district']) ? trim($info['district']) : '';
  235. $info['now_address'] = $info['now_address'] . ' ' . $district;
  236. }
  237. }
  238. $item['home_address'] = '';
  239. if (isset($info['home_province'])) {
  240. $homeProvince = isset($info['home_province']) ? trim($info['home_province']) : '';
  241. $homeCity = isset($info['home_city']) ? trim($info['home_city']) : '';
  242. $info['home_address'] = trim($homeProvince . ' ' . $homeCity);
  243. if ($type == 2) {
  244. $homeDistrict = isset($info['home_district']) ? trim($info['home_district']) : '';
  245. $info['home_address'] = $info['home_address'] . ' ' . $homeDistrict;
  246. }
  247. }
  248. // 格式化婚姻状况
  249. $item['married_txt'] = '';
  250. if (isset($info['married'])) {
  251. $marrieds = config('weixin.marrieds');
  252. $married = $info['married'] ? intval($info['married']) : 0;
  253. $info['married_txt'] = $married > 0 && isset($marrieds[$married - 1]) ? $marrieds[$married - 1] : '无';
  254. }
  255. // 隐藏手机号
  256. if ($type > 0 && isset($info['mobile'])) {
  257. /*if($type==2){
  258. $info['mobile_txt'] = $info['mobile'];
  259. }*/
  260. $info['mobile'] = $info['mobile'] ? formatStr($info['mobile']) : '';
  261. }
  262. if ($type == 4) {
  263. $info['introduce'] = isset($info['introduce']) ? str_replace("\n", "<br/>", $info['introduce']) : '';
  264. $info['family'] = isset($info['family']) ? str_replace(["\n", "\s"], ["<br/>", "&nbsp;"], $info['family']) : '';
  265. $info['hobby'] = isset($info['hobby']) ? str_replace(["\n", "\s"], ["<br/>", "&nbsp;"], $info['hobby']) : '';
  266. $info['purpose'] = isset($info['purpose']) ? str_replace(["\n", "\s"], ["<br/>", "&nbsp;"], $info['purpose']) : '';
  267. $info['cause'] = isset($info['cause']) ? str_replace(["\n", "\s"], ["<br/>", "&nbsp;"], $info['cause']) : '';
  268. $info['expect'] = isset($info['expect']) ? str_replace(["\n", "\s"], ["<br/>", "&nbsp;"], $info['expect']) : '';
  269. // VIP
  270. $vipAuth = isset($info['vip_auth']) ? intval($info['vip_auth']) : 0;
  271. $vipExpire = isset($info['vip_expire']) ? intval($info['vip_expire']) : 0;
  272. if ($vipAuth && $vipExpire >= time()) {
  273. $info['vip_auth'] = 1;
  274. $info['vip_expire'] = date('Y-m-d', $info['vip_expire']);
  275. } else {
  276. $info['vip_auth'] = 0;
  277. $info['vip_expire'] = '';
  278. }
  279. }
  280. if($type == 1){
  281. $accountConfig = $siteInfo = cmf_get_option('account_config');
  282. $logoutPay = isset($accountConfig['logout_pay']) ? floatval($accountConfig['logout_pay']) : 0;
  283. $memberInfo['logout_pay'] = $logoutPay > 0 ? $logoutPay : 1;
  284. }
  285. // 个性标签
  286. if (isset($info['tags'])) {
  287. $info['tags'] = $info['tags'] ? explode(',', $info['tags']) : [];
  288. }
  289. if ($type == 3 || $type == 4) {
  290. if (isset($info['introduce_img'])) {
  291. $info['introduce_img_preview'] = $info['introduce_img'] ? cmf_get_image_preview_url($info['introduce_img']) : '';
  292. }
  293. if (isset($info['family_img'])) {
  294. $info['family_img_preview'] = $info['family_img'] ? cmf_get_image_preview_url($info['family_img']) : '';
  295. }
  296. if (isset($info['hobby_img'])) {
  297. $info['hobby_img_preview'] = $info['hobby_img'] ? cmf_get_image_preview_url($info['hobby_img']) : '';
  298. }
  299. if (isset($info['purpose_img'])) {
  300. $info['purpose_img_preview'] = $info['purpose_img'] ? cmf_get_image_preview_url($info['purpose_img']) : '';
  301. }
  302. if (isset($info['cause_img'])) {
  303. $info['cause_img_preview'] = $info['cause_img'] ? cmf_get_image_preview_url($info['cause_img']) : '';
  304. }
  305. if (isset($info['expect_img'])) {
  306. $info['expect_img_preview'] = $info['expect_img'] ? cmf_get_image_preview_url($info['expect_img']) : '';
  307. }
  308. }
  309. }
  310. return $info ? $info->toArray() : [];
  311. }
  312. /**
  313. * 记录访问记录
  314. * @param $userId
  315. * @param $accessUid
  316. * @return false|int|string
  317. * @throws \think\Exception
  318. * @throws \think\db\exception\DataNotFoundException
  319. * @throws \think\db\exception\ModelNotFoundException
  320. * @throws \think\exception\DbException
  321. * @throws \think\exception\PDOException
  322. */
  323. public static function makeUserAccess($userId, $accessUid)
  324. {
  325. if (($userId == $accessUid) || empty($userId) || empty($accessUid)) {
  326. return false;
  327. }
  328. $lockCacheKey = "caches:access:{$userId}_{$accessUid}";
  329. if (PRedis::get($lockCacheKey)) {
  330. return false;
  331. }
  332. $checkData = UserAccess::where(['user_id' => $userId, 'access_uid' => $accessUid, 'status' => 1])
  333. ->field('id,created_at,status')
  334. ->find();
  335. $checkData = $checkData ? $checkData->toArray() : [];
  336. $timeAt = isset($checkData['created_at']) ? $checkData['created_at'] : '';
  337. if ($checkData && $timeAt && $timeAt >= date('Y-m-d H:i:s', time() - rand(10, 20))) {
  338. PRedis::set($lockCacheKey, $checkData, rand(10, 20));
  339. return false;
  340. }
  341. $data = ['user_id' => $userId, 'access_uid' => $accessUid, 'created_at' => date('Y-m-d H:i:s')];
  342. if (empty($checkData)) {
  343. return UserAccess::insertGetId($data);
  344. } else {
  345. return UserAccess::where(['user_id' => $userId, 'access_uid' => $accessUid])->update(['created_at' => date('Y-m-d H:i:s')]);
  346. }
  347. }
  348. /**
  349. * 获取用户访问记录
  350. * @param $userId 被访问用户
  351. * @param $pageSize
  352. * @return array
  353. */
  354. public static function getUserAccess($userId, $pageSize)
  355. {
  356. $dataList = UserAccess::alias('ua')
  357. ->join('user u', 'u.id=ua.user_id', 'left')
  358. ->join('user au', 'au.id=ua.access_uid', 'left')
  359. ->join('user_profile up', 'up.userid=ua.access_uid', 'left')
  360. ->field('ua.id,ua.user_id,ua.access_uid,ua.created_at,ua.is_lock,ua.status,au.avatar,au.user_nickname,au.user_login,au.birthday,u.birthday as my_birthday,au.sex,up.city')
  361. ->where(['ua.user_id' => $userId, 'ua.status' => 1, 'au.user_status' => 1])
  362. ->order('ua.created_at desc,ua.id desc')
  363. ->paginate($pageSize)
  364. ->each(function ($item, $key) {
  365. $birthday = $item['birthday'];
  366. $myBirthday = $item['my_birthday'];
  367. $month = date('m-d', $birthday);
  368. $myMonth = date('m-d', $myBirthday);
  369. $start = getStart($month);
  370. $mstart = getStart($myMonth);
  371. $item['birtyday'] = $month;
  372. $item['my_birtyday'] = $myMonth;
  373. $item['start'] = $start == $mstart ? '同是' . $start : $start;
  374. $item['mstart'] = $mstart;
  375. $year = date('y年', $birthday);
  376. $item['year'] = $year;
  377. $item['city'] = str_replace('市', '', $item['city']);
  378. $item['created_at_text'] = format_time(strtotime($item['created_at']));
  379. $nickname = $item['user_nickname'] ? $item['user_nickname'] : $item['user_login'];
  380. $item['user_nickname'] = $item['is_lock'] ? formatName($nickname) : $nickname;
  381. });
  382. $dataList = $dataList ? $dataList->toArray() : ['data' => []];
  383. // 获取今日访问
  384. $dataList['todayCount'] = UserAccess::where(['user_id' => $userId, 'status' => 1])
  385. ->where('created_at', 'like', "%" . date('Y-m-d') . "%")
  386. ->count('id');
  387. return $dataList;
  388. }
  389. /**
  390. * 获取访问用户数
  391. * @param $userId
  392. * @return float|int|string
  393. */
  394. public static function getAccessCount($userId){
  395. return UserAccess::where(['user_id' => $userId, 'status' => 1])
  396. ->count('id');
  397. }
  398. /**
  399. * 获取推荐会员数量
  400. * @param $userId
  401. * @return float|string
  402. */
  403. public static function getInviteCount($userId)
  404. {
  405. return Member::where(['parent_id' => $userId, 'user_type' => 2, 'user_status' => 1])->count('id');
  406. }
  407. /**
  408. * 验证获取验证用户信息
  409. * @param $account
  410. * @return array|bool
  411. * @throws \think\db\exception\DataNotFoundException
  412. * @throws \think\db\exception\ModelNotFoundException
  413. * @throws \think\exception\DbException
  414. */
  415. public static function checkUserInfo($account)
  416. {
  417. $cacheKey = "cache:users:check_{$account}";
  418. $info = PRedis::get($cacheKey);
  419. if ($info) {
  420. return $info;
  421. }
  422. $field = 'id,openid,user_type,agent_type,agent_status,user_status,freezing_choose,is_reg_profile';
  423. $info = self::where(['openid|id' => $account, 'user_type' => 2])->field($field)->order('user_status desc,id desc')->find();
  424. $info = $info ? $info->toArray() : [];
  425. if ($info) {
  426. PRedis::set($cacheKey, $info, 5);
  427. }
  428. return $info;
  429. }
  430. /**
  431. * 获取邀请的分销用户信息
  432. * @param $userId 当前用户ID
  433. * @param string $field 返回字段,连表u-当前用户,uu连表用户
  434. * @return array
  435. * @throws \think\db\exception\DataNotFoundException
  436. * @throws \think\db\exception\ModelNotFoundException
  437. * @throws \think\exception\DbException
  438. */
  439. public static function getInviteInfo($userId, $field = '')
  440. {
  441. $field = $field ? $field : 'u.id,uu.id as invite_id,uu.openid,uu.parent_id';
  442. $info = Member::alias('u')
  443. ->leftJoin('user uu', 'uu.id=u.parent_id')
  444. ->where(['u.id' => $userId, 'uu.user_type' => 2, 'uu.agent_type' => 1, 'uu.agent_status' => 1])
  445. ->field($field)
  446. ->find();
  447. return $info ? $info->toArray() : [];
  448. }
  449. /**
  450. * 充值记录
  451. * @param $params
  452. * @param int $pageSize
  453. * @return mixed
  454. */
  455. public static function getRechargeLog($params, $pageSize = 15)
  456. {
  457. $where = [];
  458. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  459. if ($userId) {
  460. $where['user_id'] = $userId;
  461. }
  462. $cwhere = $where;
  463. $cwhere['is_read'] = 2;
  464. $count = db('user_recharge_log')
  465. ->where($cwhere)
  466. ->where('status', 'gt', 0)
  467. ->count('id');
  468. if ($count) {
  469. db('user_recharge_log')
  470. ->where($cwhere)
  471. ->where('status', 'gt', 0)
  472. ->update(['is_read' => 1, 'updated_at' => date('Y-m-d H:i:s')]);
  473. }
  474. $dataList = db('user_recharge_log')
  475. ->where($where)
  476. ->field('id,type,order_sn,pay_type,money,pay_money,balance,remark,created_at,status')
  477. ->where('status', 'gt', 0)
  478. ->order("created_at desc")
  479. ->paginate($pageSize)
  480. ->each(function ($item, $k) {
  481. $item['format_time'] = date('Y年m月d日 H点i分', strtotime($item['created_at']));
  482. $item['money'] = in_array($item['type'], [1, 4, 5]) ? intval($item['money']) : $item['money'];
  483. return $item;
  484. });
  485. return $dataList ? $dataList->toArray() : [];
  486. }
  487. /**
  488. * 充值记录数
  489. * @param $userId
  490. * @param int $type
  491. * @return mixed
  492. */
  493. public static function getRechargeCount($userId, $type = 0)
  494. {
  495. $where = ['user_id' => $userId, 'is_read' => 2];
  496. if ($type) {
  497. $where['type'] = $type;
  498. }
  499. return db('user_recharge_log')
  500. ->where($where)
  501. ->where('status', 'gt', 0)
  502. ->count('id');
  503. }
  504. /**
  505. * 推荐用户
  506. * @param $params 参数
  507. * @param $page 分页
  508. * @param $pageSize 分页大小
  509. * @param string $field 字段
  510. * @return array|null|\PDOStatement|string|Model
  511. */
  512. public static function getRecommendList($params, $pageSize, $field = '')
  513. {
  514. $page = input('page', 1);
  515. $cacheKey = "cache:recommends:index_" . $page . '_:' . md5(json_encode($params) . $pageSize . $field);
  516. $dataList = PRedis::get($cacheKey);
  517. if ($dataList) {
  518. return $dataList;
  519. }
  520. $where = ['m.is_tuijian' => 1, 'is_heart' => 1, 'm.is_reg_profile' => 1, 'm.user_status' => 1, 'm.user_type' => 2];
  521. // 匹配当前用户信息:性别
  522. $sex = 0;
  523. $userId = isset($params['user_id']) ? intval($params['user_id']) : 0;
  524. if ($userId) {
  525. $sex = Member::where(['id' => $userId])->value('sex');
  526. if ($sex > 0) {
  527. $sex = $sex == 1 ? 2 : 1;
  528. }
  529. }
  530. $field = $field ? $field : 'm.id,m.user_nickname,m.real_name,m.lat,m.lng,m.address,m.birthday,m.avatar,m.create_time,m.sex,up.graduate,up.education,up.height,up.weight,up.company,up.occupation,up.province,up.city,up.show_graduate,m.vip_auth,m.is_heart,m.vip_expire,up.show_company,up.idcard_check,up.education_check,up.position_check,up.province,up.home_city,up.photolist,up.introduce';
  531. // 距离
  532. $info = Member::where(['id' => $userId])->field('lat,lng')->find();
  533. $lat = isset($params['lat']) ? $params['lat'] : 0.00;
  534. $lng = isset($params['lng']) ? $params['lng'] : 0.00;
  535. $lat = $lat ? $lat : (isset($info['lat']) ? $info['lat'] : 0);
  536. $lng = $lng ? $lng : (isset($info['lng']) ? $info['lng'] : 0);
  537. if ($lat && $lng) {
  538. $field .= ",ROUND(
  539. 6378.138 * 2 * ASIN(
  540. SQRT(
  541. POW(
  542. SIN(
  543. (
  544. {$lat} * PI() / 180 - m.`lat` * PI() / 180
  545. ) / 2
  546. ),
  547. 2
  548. ) + COS({$lat} * PI() / 180) * COS(m.`lat` * PI() / 180) * POW(
  549. SIN(
  550. (
  551. {$lng} * PI() / 180 - m.`lng` * PI() / 180
  552. ) / 2
  553. ),
  554. 2
  555. )
  556. )
  557. ) * 1000
  558. ) AS distance";
  559. }
  560. $dataList = Member::alias('m')
  561. ->join('user_profile up', 'up.userid=m.id', 'left')
  562. ->field($field)
  563. ->where($where)
  564. ->where(function ($query) use ($sex, $params) {
  565. // 性别
  566. if ($sex > 0) {
  567. $query->where('m.sex', 'in', [0, $sex]);
  568. }
  569. // 年龄
  570. $age = isset($params['age']) ? trim($params['age']) : '';
  571. if ($age) {
  572. $ages = explode('~', $age);
  573. $age1 = isset($ages[0]) ? intval($ages[0]) : 0;
  574. $age2 = isset($ages[1]) ? intval($ages[1]) : 0;
  575. if ($age2) {
  576. $query->where('up.age', '>=', $age1)->where('up.age', '<=', $age2);
  577. } else if ($age1) {
  578. $query->where('up.age', '>=', $age1);
  579. }
  580. }
  581. // 身高
  582. $height = isset($params['height']) ? trim($params['height']) : '';
  583. if ($height) {
  584. $heights = explode('~', $height);
  585. $height1 = isset($heights[0]) ? intval($heights[0]) : 0;
  586. $height2 = isset($heights[1]) ? intval($heights[1]) : 0;
  587. if ($height2) {
  588. $query->where('up.height', '>=', $height1)->where('up.height', '<=', $height2);
  589. } else if ($height1) {
  590. $query->where('up.height', '>=', $height1);
  591. }
  592. }
  593. // 学历
  594. $education = isset($params['education']) ? intval($params['education']) : 0;
  595. if ($education > 0) {
  596. $op = $education == 3 ? '>=' : '=';
  597. $query->where('up.education', $op, $education);
  598. }
  599. // 婚姻状况
  600. $married = isset($params['married']) ? intval($params['married']) : 0;
  601. if ($married > 0) {
  602. $query->where('up.married', '=', $married);
  603. }
  604. return $query;
  605. })
  606. ->where('m.id', '>', 0)
  607. ->where('m.id', 'not in', $userId)
  608. ->order('m.tuijian_time desc,m.id')
  609. ->paginate($pageSize)
  610. ->each(function ($item, $k) {
  611. $item['avatar'] = isset($item['avatar']) ? cmf_get_image_preview_url($item['avatar']) : '';
  612. $birthday = isset($item['birthday']) ? $item['birthday'] : 0;
  613. $item['birthday_txt'] = $birthday ? date('Y年m月d日', $birthday) : '';
  614. $item['birthday_day'] = $birthday ? date('y年', $birthday) : '';
  615. $height = isset($item['height']) ? intval($item['height']) : 0;
  616. $item['height_txt'] = $height ? intval($item['height']) . 'CM' : '';
  617. $weight = isset($item['weight']) ? intval($item['weight']) : 0;
  618. $item['weight_txt'] = $weight ? intval($item['weight']) . 'KG' : '';
  619. // VIP
  620. $vipAuth = isset($item['vip_auth']) ? intval($item['vip_auth']) : 0;
  621. $vipExpire = isset($item['vip_expire']) ? intval($item['vip_expire']) : 0;
  622. if ($vipAuth && $vipExpire >= time()) {
  623. $item['vip_auth'] = 1;
  624. $item['vip_expire'] = date('Y-m-d', $item['vip_expire']);
  625. } else {
  626. $item['vip_auth'] = 0;
  627. $item['vip_expire'] = '';
  628. }
  629. // 学历
  630. $educations = config('weixin.educations');
  631. $edu = isset($item['education']) ? $item['education'] : 0;
  632. $item['education_txt'] = $edu && isset($educations[$edu]) ? $educations[$edu] : '';
  633. // 地址
  634. $province = isset($item['province']) ? trim($item['province']) : '';
  635. $city = isset($item['city']) ? trim($item['city']) : '';
  636. $homeProvince = isset($item['home_province']) ? trim($item['home_province']) : '';
  637. $homeCity = isset($item['home_city']) ? trim($item['home_city']) : '';
  638. $item['now_address'] = trim($province . ' ' . $city);
  639. $item['home_address'] = trim($homeProvince . ' ' . $homeCity);
  640. $albums = [];
  641. $photolist = isset($item['photolist']) ? $item['photolist'] : '';
  642. $photolist = $photolist ? explode(',', $photolist) : [];
  643. if ($photolist) {
  644. foreach ($photolist as $k => $val) {
  645. $albums[] = cmf_get_image_preview_url($val);
  646. }
  647. }
  648. $item['pic_count'] = count($albums);
  649. // 坐标距离
  650. $item['distance'] = isset($item['distance']) ? $item['distance'] : '';
  651. if ($item['lat'] <= 0 || $item['lng'] <= 0) {
  652. $item['distance'] = '';
  653. } else {
  654. $item['distance'] = $item['distance'] >= 1000 ? round($item['distance'] / 1000, 2) . 'km' : ($item['distance'] ? $item['distance'] . 'm' : '');
  655. }
  656. // 地址
  657. $address = isset($item['address']) ? $item['address'] : '';
  658. $addressData = $address ? explode(',', $address) : [];
  659. $item['district'] = isset($addressData[2]) ? $addressData[2] : '';
  660. return $item;
  661. });
  662. $dataList = $dataList ? $dataList->toArray() : [];
  663. //PRedis::set('recommends:query:' . $userId, Db::name('user')->getLastSql(), 600);
  664. PRedis::set($cacheKey, $dataList, 10);
  665. return $dataList;
  666. }
  667. /**
  668. * 怦然心动推荐用户
  669. * @param $userId 当前用户
  670. * @param string $field 字段
  671. * @return array|null|\PDOStatement|string|Model
  672. */
  673. public static function getHeartList($userId, $field = '', $refresh = false)
  674. {
  675. // 获取已经推荐的有效数据
  676. $updated = false;
  677. $dataList = [];
  678. $cacheKey = "hearts:recommend:" . $userId;
  679. $recommendIds = PRedis::get($cacheKey);
  680. $where = ['m.is_heart' => 1, 'm.is_reg_profile' => 1, 'm.user_status' => 1, 'm.user_type' => 2];
  681. $heartAt = Member::where(['id' => $userId])->value('heart_recommend_at');
  682. $heartAt = $heartAt ? date('Y-m-d', strtotime($heartAt)) : '';
  683. $ids = [];
  684. if (!PRedis::exists($cacheKey) || $refresh) {
  685. // 验证今天是否推荐过
  686. /*$heartAt = Member::where(['id' => $userId])->value('heart_recommend_at');
  687. $heartAt = $heartAt ? date('Y-m-d', strtotime($heartAt)) : '';
  688. if ($heartAt == date('Y-m-d')) {
  689. return true;
  690. }*/
  691. // 获取推荐的人数设置
  692. $updated = true;
  693. $siteInfo = $siteInfo = cmf_get_site_info();
  694. $ageGap = isset($siteInfo['age_gap']) ? intval($siteInfo['age_gap']) : 0;
  695. $ageGap = $ageGap ? $ageGap : 0;
  696. $recommendNum = isset($siteInfo['recommend_num']) ? intval($siteInfo['recommend_num']) : 0;
  697. $recommendNum = $recommendNum ? $recommendNum : 1;
  698. // 用户性别
  699. $memberInfo = Member::getHomeInfo($userId, 'm.sex,up.age,up.city,m.vip_auth,m.vip_expire,up.home_province');
  700. $sex = isset($memberInfo['sex']) ? intval($memberInfo['sex']) : 0;
  701. if ($sex > 0) {
  702. $sex = $sex == 1 ? 2 : 1;
  703. }
  704. // 调整VIP推荐人数
  705. $isVip = false;
  706. $vipRecommendNum = isset($siteInfo['vip_recommend_num']) ? intval($siteInfo['vip_recommend_num']) : 0;
  707. $vipAuth = isset($memberInfo['vip_auth']) ? intval($memberInfo['vip_auth']) : 0;
  708. $vipExpire = isset($memberInfo['vip_expire']) ? intval($memberInfo['vip_expire']) : 0;
  709. if ($vipAuth && $vipExpire >= time() && $vipRecommendNum > 0) {
  710. $isVip = true;
  711. $recommendNum = $vipRecommendNum;
  712. }
  713. $conditions = Member::getMemberConditions($userId);
  714. //var_dump($conditions);
  715. $hasMatchData = Predis::get("hearts:hasMeatch:{$userId}");
  716. $ids = isset($hasMatchData['ids']) ? $hasMatchData['ids'] : '';
  717. $ids = $ids ? explode(',', $ids) : [];
  718. $hasExpire = isset($hasMatchData['expire']) ? $hasMatchData['expire'] : 0;
  719. if (time() > $hasExpire || !$isVip) {
  720. $ids = [];
  721. }
  722. // vip会员只推荐身份认证的
  723. if ($isVip) {
  724. $where['up.idcard_check'] = 2;
  725. }
  726. $recommendIds = Member::alias('m')
  727. ->join('user_profile up', 'up.userid=m.id', 'left')
  728. ->where($where)
  729. ->where(function ($query) use ($sex) {
  730. return $query->where('m.sex', 'in', [0, $sex]);
  731. })
  732. ->where(function ($query) use ($ids) {
  733. // 过滤一星期内已经推荐过的
  734. if ($ids) {
  735. return $query->where('m.id', 'not in', $ids);
  736. } else {
  737. return $query->where('m.id', '>', 0);
  738. }
  739. })
  740. ->where(function ($query) use ($conditions, $memberInfo, $ageGap) {
  741. $querys = $query;
  742. // 年龄
  743. $year = isset($conditions['year']) ? trim($conditions['year']) : '';
  744. if ($year) {
  745. $year = explode('~', $year);
  746. $data1 = isset($year[0]) ? intval($year[0]) : 0;
  747. $data2 = isset($year[1]) ? intval($year[1]) : 0;
  748. if ($data2) {
  749. $data1 = $data1 ? strtotime($data1 . '-01-01') : 0;
  750. $data2 = $data2 ? strtotime(($data2 + 1) . '-01-01') : 0;
  751. $querys = $querys->where('m.birthday', '>=', $data1 . '')->where('m.birthday', '<=', $data2);
  752. } else if ($data1) {
  753. $data1 = $data1 ? strtotime($data1 . '-01-01') : 0;
  754. $querys = $querys->where('m.birthday', '>=', $data1);
  755. }
  756. }
  757. // 身高
  758. $height = isset($conditions['height']) ? trim($conditions['height']) : '';
  759. if ($height) {
  760. $height = explode('~', $height);
  761. $data1 = isset($height[0]) ? intval($height[0]) : 0;
  762. $data2 = isset($height[1]) ? intval($height[1]) : 0;
  763. if ($data2) {
  764. $querys = $querys->where('up.height', '>=', $data1)->where('up.height', '<=', $data2);
  765. } else if ($data1) {
  766. $querys = $querys->where('up.height', '>=', $data1);
  767. }
  768. }
  769. // 体重
  770. $weight = isset($conditions['weight']) ? intval($conditions['weight']) : 0;
  771. if ($weight) {
  772. $dataArr = config('weixin.weights');
  773. $datas = isset($dataArr[$weight]) ? $dataArr[$weight] : [];
  774. $data1 = isset($datas['value1']) ? $datas['value1'] : 0;
  775. $data2 = isset($datas['value2']) ? $datas['value2'] : 0;
  776. if ($data2) {
  777. $querys = $querys->where('up.weight', '>=', $data1)->where('up.weight', '<=', $data2);
  778. } else if ($data1) {
  779. $querys = $querys->where('up.weight', '>=', $data1);
  780. }
  781. }
  782. // 收入
  783. $salary = isset($conditions['salary']) ? intval($conditions['salary']) : 0;
  784. if ($salary) {
  785. $dataArr = config('weixin.salarys');
  786. $datas = isset($dataArr[$salary]) ? $dataArr[$salary] : [];
  787. $data1 = isset($datas['value']) ? $datas['value'] : 0;
  788. $data2 = isset($datas['value2']) ? $datas['value2'] : 0;
  789. if ($data2) {
  790. $querys = $querys->where('up.salary', '>=', $data1)->where('up.salary', '<=', $data2);
  791. } else if ($data1) {
  792. $querys = $querys->where('up.salary', '=', $data1);
  793. }
  794. }
  795. // 所在城市
  796. $city = isset($memberInfo['city']) ? trim($memberInfo['city']) : '';
  797. $cityValue = isset($conditions['city']) ? trim($conditions['city']) : '';
  798. if ($cityValue > 0 && $city) {
  799. $querys = $querys->where('up.city', '=', $city);
  800. }
  801. // 家乡省市:是否同省
  802. $homeProvince = isset($memberInfo['home_province']) ? trim($memberInfo['home_province']) : '';
  803. $homeProvinceValue = isset($conditions['home_province']) ? trim($conditions['home_province']) : '';
  804. if ($homeProvinceValue > 0 && $homeProvince) {
  805. $querys = $querys->where('up.home_province', '=', $homeProvince);
  806. }
  807. // 学历
  808. $education = isset($conditions['education']) ? intval($conditions['education']) : 0;
  809. if ($education > 0) {
  810. // 硕士及以上或按学历匹配
  811. $op = $education == 3 ? '>=' : '=';
  812. $querys = $querys->where('up.education', $op, $education);
  813. }
  814. // 婚姻状态
  815. $married = isset($conditions['married']) ? intval($conditions['married']) : 0;
  816. if ($married > 0) {
  817. $querys = $querys->where('up.married', '>=', $married);
  818. }
  819. return $querys;
  820. })
  821. ->orderRaw('rand()')
  822. ->limit($recommendNum)
  823. ->column('m.id');
  824. PRedis::set('hearts:query:' . $userId, ['where' => $where, 'ids' => $ids, 'query' => Member::getLastSql()], 24 * 3600);
  825. if (empty($recommendIds)) {
  826. $recommendIds = Member::alias('m')
  827. ->join('user_profile up', 'up.userid=m.id', 'left')
  828. ->where($where)
  829. ->where(function ($query) use ($sex) {
  830. return $query->where('m.sex', 'in', [0, $sex]);
  831. })
  832. ->where(function ($query) use ($ids) {
  833. // 过滤一星期内已经推荐过的
  834. if ($ids) {
  835. return $query->where('m.id', 'not in', $ids);
  836. } else {
  837. return $query->where('m.id', '>', 0);
  838. }
  839. })
  840. ->where(function ($query) use ($conditions, $memberInfo, $ageGap) {
  841. $querys = $query;
  842. // 年龄
  843. $year = isset($conditions['year']) ? trim($conditions['year']) : '';
  844. if ($year) {
  845. $year = explode('~', $year);
  846. $data1 = isset($year[0]) ? intval($year[0]) : 0;
  847. $data2 = isset($year[1]) ? intval($year[1]) : 0;
  848. if ($data2) {
  849. $data1 = $data1 ? strtotime($data1 . '-01-01') : 0;
  850. $data2 = $data2 ? strtotime(($data2 + 1) . '-01-01') : 0;
  851. $querys = $querys->where('m.birthday', '>=', $data1 . '')->where('m.birthday', '<=', $data2);
  852. } else if ($data1) {
  853. $data1 = $data1 ? strtotime($data1 . '-01-01') : 0;
  854. $querys = $querys->where('m.birthday', '>=', $data1);
  855. }
  856. }
  857. // 身高
  858. $height = isset($conditions['height']) ? trim($conditions['height']) : '';
  859. if ($height) {
  860. $height = explode('~', $height);
  861. $data1 = isset($height[0]) ? intval($height[0]) : 0;
  862. $data2 = isset($height[1]) ? intval($height[1]) : 0;
  863. if ($data2) {
  864. $querys = $querys->where('up.height', '>=', $data1)->where('up.height', '<=', $data2);
  865. } else if ($data1) {
  866. $querys = $querys->where('up.height', '>=', $data1);
  867. }
  868. }
  869. // 收入
  870. $salary = isset($conditions['salary']) ? intval($conditions['salary']) : 0;
  871. if ($height <= 0 && $salary) {
  872. $dataArr = config('weixin.salarys');
  873. $datas = isset($dataArr[$salary]) ? $dataArr[$salary] : [];
  874. $data1 = isset($datas['value']) ? $datas['value'] : 0;
  875. $data2 = isset($datas['value2']) ? $datas['value2'] : 0;
  876. if ($data2) {
  877. $querys = $querys->where('up.salary', '>=', $data1)->where('up.salary', '<=', $data2);
  878. } else if ($data1) {
  879. $querys = $querys->where('up.salary', '=', $data1);
  880. }
  881. }
  882. // 所在城市
  883. $city = isset($memberInfo['city']) ? trim($memberInfo['city']) : '';
  884. $cityValue = isset($conditions['city']) ? trim($conditions['city']) : '';
  885. if ($cityValue > 0 && $city) {
  886. $querys = $querys->where('up.city', '=', $city);
  887. }
  888. // 婚姻状态
  889. $married = isset($conditions['married']) ? intval($conditions['married']) : 0;
  890. if ($married > 0) {
  891. $querys = $querys->where('up.married', '>=', $married);
  892. }
  893. // 学历
  894. $education = isset($conditions['education']) ? intval($conditions['education']) : 0;
  895. if ($education > 0) {
  896. if ($married > 0 && $education == 3) {
  897. $querys = $querys->where('up.education', '>=', 1);
  898. } else if ($married <= 0) {
  899. // 硕士及以上或按学历匹配
  900. $op = $education == 3 ? '>=' : '=';
  901. $querys = $querys->where('up.education', $op, $education);
  902. }
  903. }
  904. return $querys;
  905. })
  906. ->orderRaw('rand()')
  907. ->limit($recommendNum)
  908. ->column('m.id');
  909. }
  910. if ($recommendIds) {
  911. // 更新推荐日期
  912. Member::where(['id' => $userId])->update(['heart_recommend_at' => date('Y-m-d H:i:s')]);
  913. }
  914. $expire = isset($siteInfo['recommend_expire']) ? intval($siteInfo['recommend_expire']) : 0;
  915. $expire = $expire ? $expire : 24;
  916. if ($recommendIds) {
  917. PRedis::set($cacheKey, $recommendIds, $expire * 3600);
  918. }
  919. }
  920. // 获取数据
  921. if ($recommendIds) {
  922. $field = $field ? $field : 'm.id,m.user_nickname,m.real_name,m.birthday,m.lat,m.lng,m.address,m.avatar,m.create_time,m.sex,m.vip_auth,m.vip_expire,up.graduate,up.education,up.height,up.weight,up.company,up.occupation,up.province,up.city,up.show_graduate,up.show_company,up.home_province,up.home_city,up.photolist,up.introduce,up.idcard_check,up.education_check,up.position_check,up.introduce';
  923. // 距离
  924. $info = Member::where(['id' => $userId])->field('lat,lng')->find();
  925. $lat = input('lat', 0.00);
  926. $lng = input('lng', 0.00);
  927. $lat = $lat ? $lat : (isset($info['lat']) ? $info['lat'] : 0);
  928. $lng = $lng ? $lng : (isset($info['lng']) ? $info['lng'] : 0);
  929. if ($lat && $lng) {
  930. $field .= ",ROUND(
  931. 6378.138 * 2 * ASIN(
  932. SQRT(
  933. POW(
  934. SIN(
  935. (
  936. {$lat} * PI() / 180 - m.`lat` * PI() / 180
  937. ) / 2
  938. ),
  939. 2
  940. ) + COS({$lat} * PI() / 180) * COS(m.`lat` * PI() / 180) * POW(
  941. SIN(
  942. (
  943. {$lng} * PI() / 180 - m.`lng` * PI() / 180
  944. ) / 2
  945. ),
  946. 2
  947. )
  948. )
  949. ) * 1000
  950. ) AS distance";
  951. }
  952. $dataList = Member::alias('m')
  953. ->join('user_profile up', 'up.userid=m.id', 'left')
  954. ->where('m.id', 'in', implode(',', $recommendIds))
  955. ->where(['m.is_heart' => 1, 'm.user_type' => 2, 'm.user_status' => 1])
  956. ->field($field)
  957. ->orderField('m.id', $recommendIds)
  958. ->paginate(count($recommendIds))
  959. ->each(function ($item, $k) {
  960. $item['avatar'] = isset($item['avatar']) ? cmf_get_image_preview_url($item['avatar']) : '';
  961. $birthday = isset($item['birthday']) ? $item['birthday'] : 0;
  962. $item['birthday_txt'] = $birthday ? date('Y年m月d日', $birthday) : '';
  963. $item['birthday_day'] = $birthday ? date('y年', $birthday) : '';
  964. $height = isset($item['height']) ? intval($item['height']) : 0;
  965. $item['height_txt'] = $height ? intval($item['height']) . 'CM' : '';
  966. $weight = isset($item['weight']) ? intval($item['weight']) : 0;
  967. $item['weight_txt'] = $weight ? intval($item['weight']) . 'KG' : '';
  968. // VIP
  969. $vipAuth = isset($item['vip_auth']) ? intval($item['vip_auth']) : 0;
  970. $vipExpire = isset($item['vip_expire']) ? intval($item['vip_expire']) : 0;
  971. if ($vipAuth && $vipExpire >= time()) {
  972. $item['vip_auth'] = 1;
  973. $item['vip_expire'] = date('Y-m-d', $item['vip_expire']);
  974. } else {
  975. $item['vip_auth'] = 0;
  976. $item['vip_expire'] = '';
  977. }
  978. // 学历
  979. $educations = config('weixin.educations');
  980. $edu = isset($item['education']) ? $item['education'] : 0;
  981. $item['education_txt'] = $edu && isset($educations[$edu]) ? $educations[$edu] : '';
  982. // 地址
  983. $province = isset($item['province']) ? trim($item['province']) : '';
  984. $city = isset($item['city']) ? trim($item['city']) : '';
  985. $homeProvince = isset($item['home_province']) ? trim($item['home_province']) : '';
  986. $homeCity = isset($item['home_city']) ? trim($item['home_city']) : '';
  987. $item['now_address'] = trim($province . ' ' . $city);
  988. $item['home_address'] = trim($homeProvince . ' ' . $homeCity);
  989. $albums = [];
  990. $photolist = isset($item['photolist']) ? $item['photolist'] : '';
  991. $photolist = $photolist ? explode(',', $photolist) : [];
  992. if ($photolist) {
  993. foreach ($photolist as $k => $val) {
  994. $albums[] = cmf_get_image_preview_url($val);
  995. }
  996. }
  997. $item['pic_count'] = count($albums);
  998. // 坐标距离
  999. $item['distance'] = isset($item['distance']) ? $item['distance'] : '';
  1000. if ($item['lat'] <= 0 || $item['lng'] <= 0) {
  1001. $item['distance'] = '';
  1002. } else {
  1003. $item['distance'] = $item['distance'] >= 1000 ? round($item['distance'] / 1000, 2) . 'km' : ($item['distance'] ? $item['distance'] . 'm' : '');
  1004. }
  1005. // 地址
  1006. $address = isset($item['address']) ? $item['address'] : '';
  1007. $addressData = $address ? explode(',', $address) : [];
  1008. $item['district'] = isset($addressData[2]) ? $addressData[2] : '';
  1009. return $item;
  1010. });
  1011. // 过滤重复
  1012. if ($updated && $recommendIds) {
  1013. if ($ids) {
  1014. $newIds = array_merge($ids, $recommendIds);
  1015. Predis::set("hearts:hasMeatch:{$userId}", ['ids' => implode(',', $newIds), 'expire' => $hasExpire], 3 * 24 * 3600);
  1016. } else {
  1017. Predis::set("hearts:hasMeatch:{$userId}", ['ids' => implode(',', $recommendIds), 'expire' => time() + 3 * 24 * 3600], 3 * 24 * 3600);
  1018. }
  1019. }
  1020. PRedis::set('hearts:results:' . $userId . '_' . date('Ymd'), ['datalist' => $dataList, 'sql' => Member::getLastSql()], 3 * 3600 * 24);
  1021. $dataList = $dataList ? $dataList->toArray() : [];
  1022. }
  1023. return $dataList;
  1024. }
  1025. /**
  1026. * 获取用户匹配条件
  1027. * @param $userId 当前用户
  1028. * @return array|mixed
  1029. */
  1030. public static function getMemberConditions($userId)
  1031. {
  1032. $conditions = db('user_conditions')->where(['user_id' => $userId])->value('conditions');
  1033. $conditions = $conditions ? json_decode($conditions, true) : [];
  1034. return $conditions;
  1035. }
  1036. /**
  1037. * 设置用户推荐条件,怦然心动条件
  1038. * @param $userId 当前用户ID
  1039. * @param $params 条件参数:age、height、weight、city、home_province、education、salary
  1040. * @return int|string
  1041. */
  1042. public static function setMemberConditions($userId, $params)
  1043. {
  1044. // 条件数据
  1045. $condition = [
  1046. 'age' => isset($params['age']) ? intval($params['age']) : 0,
  1047. 'height' => isset($params['height']) ? trim($params['height']) : '',
  1048. 'weight' => isset($params['weight']) ? intval($params['weight']) : 0,
  1049. 'city' => isset($params['city']) ? intval($params['city']) : 0,
  1050. // 'home_province' => isset($params['home_province']) ? intval($params['home_province']) : 0,
  1051. 'education' => isset($params['education']) ? intval($params['education']) : 0,
  1052. 'salary' => isset($params['salary']) ? intval($params['salary']) : 0,
  1053. 'married' => isset($params['married']) ? intval($params['married']) : 0,
  1054. 'year' => isset($params['year']) ? trim($params['year']) : '',
  1055. ];
  1056. $data = [
  1057. 'user_id' => $userId,
  1058. 'conditions' => json_encode($condition, 256),
  1059. 'updated_at' => date('Y-m-d H:i:s'),
  1060. 'status' => 1,
  1061. ];
  1062. // 验证并添加或保存
  1063. $check = db('user_conditions')->where(['user_id' => $userId])->value('id');
  1064. if ($check) {
  1065. $res = db('user_conditions')->where(['user_id' => $userId])->update($data);
  1066. } else {
  1067. $res = db('user_conditions')->insertGetId($data);
  1068. }
  1069. return $res;
  1070. }
  1071. /**
  1072. * 用户关注
  1073. * @param $userId 当前用户
  1074. * @param $collectUid 关注的用户
  1075. * @param int $opType
  1076. * @return int
  1077. */
  1078. public static function collect($userId, $collectUid, $opType = 1)
  1079. {
  1080. if ($userId == $collectUid) {
  1081. return 2114;
  1082. }
  1083. if (!Member::where(['id' => $collectUid])->value('id')) {
  1084. return 2104;
  1085. }
  1086. // 验证性别
  1087. $contactSex = Member::where(['id' => $collectUid])->value('sex');
  1088. $sex = Member::where(['id' => $userId])->value('sex');
  1089. if (!$sex || ($sex == $contactSex)) {
  1090. return 2135;
  1091. }
  1092. // 验证数据
  1093. $collectData = UserCollect::where(['user_id' => $userId, 'source_id' => $collectUid, 'type' => 1])
  1094. ->field('id,status')
  1095. ->find();
  1096. // 关注
  1097. $collectId = isset($collectData['id']) ? $collectData['id'] : 0;
  1098. $status = isset($collectData['status']) ? $collectData['status'] : 0;
  1099. if ($opType == 1) {
  1100. if ($collectId && $status == 1) {
  1101. return 2105;
  1102. }
  1103. // 若收藏时间已失效更新时间
  1104. $collectExpire = Member::where(['id' => $userId])->value('collect_expire');
  1105. if ($collectExpire - time() <= 0) {
  1106. $siteInfo = $siteInfo = cmf_get_site_info();
  1107. $collectTime = isset($siteInfo['collect_time']) ? intval($siteInfo['collect_time']) : 0;
  1108. $collectTime = $collectTime ? $collectTime : 6;
  1109. Member::saveData(['id' => $userId], ['collect_expire' => time() + $collectTime * 3600]);
  1110. $memberInfo = Member::where(['id' => $userId])->field('collect_expire,vip_auth,vip_expire')->find();
  1111. $vipAuth = isset($memberInfo['vip_auth']) ? intval($memberInfo['vip_auth']) : 0;
  1112. $vipExpire = isset($memberInfo['vip_expire']) ? $memberInfo['vip_expire'] : 0;
  1113. if (!$vipAuth || $vipExpire < time()) {
  1114. UserCollect::where(['user_id' => $userId])
  1115. ->update(['status' => 2, 'updated_at' => date('Y-m-d H:i:s')]);
  1116. }
  1117. }
  1118. $data = [
  1119. 'user_id' => $userId,
  1120. 'source_id' => $collectUid,
  1121. 'type' => 1,
  1122. 'created_at' => date('Y-m-d H:i:s'),
  1123. 'status' => 1,
  1124. ];
  1125. if ($collectId) {
  1126. if (!UserCollect::where(['user_id' => $userId, 'id' => $collectId])
  1127. ->update(['status' => 1, 'updated_at' => date('Y-m-d H:i:s')])) {
  1128. return 2107;
  1129. }
  1130. } else {
  1131. if (!UserCollect::insertGetId($data)) {
  1132. return 2107;
  1133. }
  1134. }
  1135. // 操作日志
  1136. UserLog::saveLog(['user_id' => $userId, 'type' => 4, 'content' => "收藏用户:{$collectUid}"]);
  1137. // 通知
  1138. $openid = Member::where(['id' => $collectUid])->value('openid');
  1139. $memberInfo = Member::where(['id' => $userId])->field('openid,sex,user_nickname')->find();
  1140. $nickname = isset($memberInfo['user_nickname']) ? $memberInfo['user_nickname'] : '未公开';
  1141. $sex = isset($memberInfo['sex']) ? $memberInfo['sex'] : 0;
  1142. $sex = $sex == 1 ? '帅哥' : '美女';
  1143. $dateTime = date('Y.m.d H:i');
  1144. if ($openid) {
  1145. $params = [
  1146. 'title' => "有个{$sex}查看了你的名片并且关注了你\n\n关注时间:\t{$dateTime}",
  1147. // 'title' => "有一位{$sex}申请加您的微信并给您留言了!\n\n申请时间:\t{$dateTime}\n\n收到留言:\t{$remark}",
  1148. 'remark' => "点击查看(如果不想再收到该类型消息,可本公众号回复“隐身设置”进入链接设置为隐身)",
  1149. 'type' => 'contact',
  1150. 'keywords' => [
  1151. 'keyword1' => [
  1152. 'value' => $nickname . '(昵称)',
  1153. 'color' => '#173177',
  1154. ],
  1155. 'keyword2' => [
  1156. 'value' => '隐私信息不显示',
  1157. 'color' => '#173177',
  1158. ],
  1159. 'keyword3' => [
  1160. 'value' => '消息提醒',
  1161. 'color' => '#173177',
  1162. ],
  1163. ],
  1164. 'url' => url("/weixin/member/collect?type=2", [], '', true),
  1165. ];
  1166. PRedis::set('messages:collect:' . $userId . '_' . $collectUid . '_' . $openid, ['data' => $data, 'params' => $params], 600);
  1167. Wechat::sendTplMsg($openid, $params, false);
  1168. }
  1169. return true;
  1170. } // 取消关注
  1171. else if ($opType == 2) {
  1172. if (!$collectId) {
  1173. return 1003;
  1174. }
  1175. if ($status != 1) {
  1176. return 2115;
  1177. }
  1178. if (!UserCollect::where(['user_id' => $userId, 'source_id' => $collectUid, 'type' => 1])
  1179. ->update(['status' => 2, 'updated_at' => date('Y-m-d H:i:s')])) {
  1180. return 2109;
  1181. }
  1182. // 操作日志
  1183. UserLog::saveLog(['user_id' => $userId, 'type' => 4, 'content' => "取消收藏用户:{$collectUid}"]);
  1184. return true;
  1185. }
  1186. return 1009;
  1187. }
  1188. /**
  1189. * 保存信息
  1190. * @param $where
  1191. * @param $data
  1192. * @return int|string
  1193. */
  1194. public static function saveData($where, $data)
  1195. {
  1196. $data['updated_at'] = date('Y-m-d H:i:s');
  1197. return Member::where($where)->update($data);
  1198. }
  1199. /**
  1200. * 想认识处理
  1201. * @param $userId 用户ID
  1202. * @param $contactUid 认识用户ID
  1203. * @return array|int
  1204. */
  1205. public static function contactUser($userId, $contactUid, $remark = '')
  1206. {
  1207. if ($userId == $contactUid) {
  1208. return 2133;
  1209. }
  1210. $contactInfo = Member::where(['id' => $contactUid, 'user_type' => 2, 'user_status' => 1])
  1211. ->field('id,openid,user_nickname,sex,real_name,is_reg_profile')
  1212. ->find();
  1213. $memberInfo = Member::where(['id' => $userId, 'user_type' => 2, 'user_status' => 1])
  1214. ->field('id,openid,user_nickname,real_name,sex,is_reg_profile,redheart,vip_auth,vip_expire')
  1215. ->find();
  1216. if (empty($contactInfo) || empty($memberInfo)) {
  1217. return false;
  1218. }
  1219. // 性别验证
  1220. $contactSex = isset($contactInfo['sex']) ? intval($contactInfo['sex']) : 0;
  1221. $sex = isset($memberInfo['sex']) ? intval($memberInfo['sex']) : 0;
  1222. if (!$sex || ($sex == $contactSex)) {
  1223. return 2134;
  1224. }
  1225. // 完善资料
  1226. $isRegProfile = isset($memberInfo['is_reg_profile']) ? $memberInfo['is_reg_profile'] : 0;
  1227. if ($isRegProfile != 1) {
  1228. return 2103;
  1229. }
  1230. // 验证是否已认识
  1231. $contactData = UserContactLog::where(['user_id' => $userId, 'contact_uid' => $contactUid])
  1232. ->where('status', 'in', [1, 2, 3])
  1233. ->field('id,status')
  1234. ->find();
  1235. $checkId = isset($contactData['id']) ? $contactData['id'] : 0;
  1236. $status = isset($contactData['status']) ? $contactData['status'] : 0;
  1237. if ($checkId && $status != 4) {
  1238. return $status == 1 ? 2117 : 2118;
  1239. }
  1240. //
  1241. Db::startTrans();
  1242. // 扣除爱心账户
  1243. $accountConfig = cmf_get_option('account_config');
  1244. $contactPay = isset($accountConfig['contact_pay']) ? intval($accountConfig['contact_pay']) : 0;
  1245. $contactPay = $contactPay ? $contactPay : 1;
  1246. // 会员不需要收录费
  1247. $vipAuth = isset($memberInfo['vip_auth']) ? intval($memberInfo['vip_auth']) : 0;
  1248. $vipExpire = isset($memberInfo['vip_expire']) ? intval($memberInfo['vip_expire']) : 0;
  1249. $contactPay = $vipAuth && $vipExpire >= time() ? 0 : $contactPay;
  1250. if ($contactPay > 0) {
  1251. $redheart = isset($memberInfo['redheart']) ? intval($memberInfo['redheart']) : 0;
  1252. if ($redheart < $contactPay) {
  1253. Db::rollback();
  1254. return 2121;
  1255. }
  1256. $newRedheart = max(0, ($redheart - $contactPay));
  1257. $memberData = ['redheart' => $newRedheart, 'updated_at' => date('Y-m-d H:i:s')];
  1258. if (!Member::where(['id' => $userId])->update($memberData)) {
  1259. Db::rollback();
  1260. return false;
  1261. }
  1262. // 账户明细
  1263. $cNickname = isset($contactInfo['user_nickname']) ? $contactInfo['user_nickname'] : '';
  1264. $accountData = [
  1265. 'user_id' => $userId,
  1266. 'type' => 2,
  1267. 'account_type' => 1,
  1268. 'change_type' => 2,
  1269. 'money' => $contactPay,
  1270. 'balance' => $redheart,
  1271. 'remark' => "认识【{$cNickname}】请求成功,扣除{$contactPay}个爱心",
  1272. 'created_at' => date('Y-m-d H:i:s'),
  1273. 'status' => 2,
  1274. ];
  1275. PRedis::set('accounts:contact:' . $contactUid . '_' . $userId, $accountData, 600);
  1276. if (!AccountLog::insertGetId($accountData)) {
  1277. Db::rollback();
  1278. return false;
  1279. }
  1280. }
  1281. $data = [
  1282. 'user_id' => $userId,
  1283. 'contact_uid' => $contactUid,
  1284. 'cost_redheart' => $contactPay,
  1285. 'remark' => $remark,
  1286. 'created_at' => date('Y-m-d H:i:s'),
  1287. 'status' => 1,
  1288. ];
  1289. $cid = UserContactLog::insertGetId($data);
  1290. if (!$cid) {
  1291. Db::rollback();
  1292. return false;
  1293. }
  1294. Db::commit();
  1295. if ($cid) {
  1296. // 模板消息
  1297. $openid = isset($contactInfo['openid']) ? $contactInfo['openid'] : '';
  1298. $nickname = isset($memberInfo['user_nickname']) ? $memberInfo['user_nickname'] : '';
  1299. $cNickname = isset($contactInfo['user_nickname']) ? $contactInfo['user_nickname'] : '';
  1300. $sex = isset($memberInfo['sex']) ? $memberInfo['sex'] : 1;
  1301. $sex = $sex == 1 ? '男生' : '女生';
  1302. $dateTime = date('Y.m.d H:i');
  1303. if ($openid) {
  1304. $remark = $remark ? $remark : '无';
  1305. $params = [
  1306. 'title' => "对方留言:{$remark}",
  1307. // 'title' => "有一位{$sex}申请加您的微信并给您留言了!\n\n申请时间:\t{$dateTime}\n\n收到留言:\t{$remark}",
  1308. 'remark' => "点击查看(如果不想再收到该类型消息,可本公众号回复“隐身设置”进入链接设置为隐身)",
  1309. 'type' => 'contact',
  1310. 'keywords' => [
  1311. 'keyword1' => [
  1312. 'value' => $nickname . '(昵称)',
  1313. 'color' => '#173177',
  1314. ],
  1315. 'keyword2' => [
  1316. 'value' => '隐私信息不显示',
  1317. 'color' => '#173177',
  1318. ],
  1319. 'keyword3' => [
  1320. 'value' => '待处理',
  1321. 'color' => '#173177',
  1322. ],
  1323. ],
  1324. 'url' => url("/weixin/member/home?id={$userId}&cid={$cid}", [], '', true),
  1325. ];
  1326. PRedis::set('messages:contact:' . $openid, ['data' => $data, 'params' => $params], 600);
  1327. Wechat::sendTplMsg($openid, $params, false);
  1328. }
  1329. // 操作日志
  1330. UserLog::saveLog(['user_id' => $userId, 'type' => 4, 'content' => "申请用户{$cNickname}微信"]);
  1331. return ['id' => $cid];
  1332. } else {
  1333. return 2119;
  1334. }
  1335. }
  1336. /**
  1337. * @param $userId
  1338. * @param $cid
  1339. * @return bool|int
  1340. */
  1341. public static function contactConfirm($userId, $cid, $checkStatus)
  1342. {
  1343. // 验证是否
  1344. $contactData = UserContactLog::where(['id' => $cid, 'contact_uid' => $userId])
  1345. ->field('id,user_id,cost_redheart,is_read,status')
  1346. ->find();
  1347. $checkId = isset($contactData['id']) ? $contactData['id'] : 0;
  1348. $status = isset($contactData['status']) ? $contactData['status'] : 0;
  1349. $contactUid = isset($contactData['user_id']) ? $contactData['user_id'] : 0;
  1350. $isRead = isset($contactData['is_read']) ? $contactData['is_read'] : 0; // 是否已读
  1351. if ($checkId && $status != 1 && $checkStatus != 5) {
  1352. return 2120;
  1353. }
  1354. if (empty($contactUid)) {
  1355. return 2111;
  1356. }
  1357. // 撤回操作
  1358. if ($checkStatus == 5) {
  1359. UserContactLog::where(['id' => $cid])->update(['status' => 1, 'updated_at' => date('Y-m-d H:i:s')]);
  1360. return 2139;
  1361. }
  1362. // 更新记录数据
  1363. Db::startTrans();
  1364. $updateData = ['status' => $checkStatus, 'updated_at' => date('Y-m-d H:i:s')];
  1365. if (!UserContactLog::where(['id' => $cid])->update($updateData)) {
  1366. Db::rollback();
  1367. return 2032;
  1368. }
  1369. // 当前用户信息
  1370. $field = 'm.user_nickname,m.real_name,m.openid,up.wechat_code,up.qq';
  1371. $memberInfo = Member::getHomeInfo($userId, $field);
  1372. $nickname = isset($memberInfo['user_nickname']) ? $memberInfo['user_nickname'] : '';
  1373. $field = 'm.redheart,m.user_nickname,m.real_name,m.openid,up.wechat_code,up.qq';
  1374. $contactUserInfo = Member::getHomeInfo($contactUid, $field);
  1375. $cOpenid = isset($contactUserInfo['openid']) ? $contactUserInfo['openid'] : '';
  1376. $cNickname = isset($contactUserInfo['user_nickname']) ? $contactUserInfo['user_nickname'] : '';
  1377. $redheart = isset($contactUserInfo['redheart']) ? intval($contactUserInfo['redheart']) : 0;
  1378. $contactPay = isset($contactData['cost_redheart']) ? intval($contactData['cost_redheart']) : 0;
  1379. // 已读或拒绝退款扣除的爱心
  1380. $accountConfig = cmf_get_option('account_config');
  1381. $applyRefundPay = isset($accountConfig['apply_refund_pay']) ? intval($accountConfig['apply_refund_pay']) : 0;
  1382. if ($isRead || $checkStatus == 3) {
  1383. $applyRefundPay = $applyRefundPay ? $applyRefundPay : 0;
  1384. $refundHeart = $contactPay > $applyRefundPay ? intval($contactPay - $applyRefundPay) : 0;
  1385. } else {
  1386. $refundHeart = $contactPay;
  1387. $applyRefundPay = 0;
  1388. }
  1389. // 审核失败退还扣除的爱心
  1390. if ($contactPay > 0 && ($checkStatus == 3 || $checkStatus == 4)) {
  1391. $newRedheart = max(0, ($redheart + $refundHeart));
  1392. $memberData = ['redheart' => $newRedheart, 'updated_at' => date('Y-m-d H:i:s')];
  1393. if (!Member::where(['id' => $contactUid])->update($memberData)) {
  1394. Db::rollback();
  1395. return 2031;
  1396. }
  1397. // 账户明细
  1398. $accountData = [
  1399. 'user_id' => $contactUid,
  1400. 'type' => 3,
  1401. 'account_type' => 1,
  1402. 'change_type' => 1,
  1403. 'money' => $refundHeart,
  1404. 'balance' => $redheart,
  1405. 'remark' => "认识【{$nickname}】" . ($checkStatus == 3 ? '审核失败' : '审核超时') . ",退还{$refundHeart}个爱心,扣除{$applyRefundPay}个爱心",
  1406. 'created_at' => date('Y-m-d H:i:s'),
  1407. 'status' => 2,
  1408. ];
  1409. PRedis::set('accounts:contact:' . $contactUid . '_' . $userId, $accountData, 600);
  1410. if (!AccountLog::insertGetId($accountData)) {
  1411. Db::rollback();
  1412. return false;
  1413. }
  1414. }
  1415. Db::commit();
  1416. // 发送模板信息
  1417. /*if($openid){
  1418. $cWechatCode = isset($contactUserInfo['wechat_code'])? trim($contactUserInfo['wechat_code']) : '';
  1419. $cqq = isset($contactUserInfo['qq'])? trim($contactUserInfo['qq']) : '';
  1420. $cWechatCode = $cWechatCode? $cWechatCode : '无';
  1421. $cqq = $cqq? $cqq : '无';
  1422. $params = [
  1423. 'title' => "【{$cRealname}】想认识您的请求已确认\n\n对方微信号:\t{$cWechatCode}\n\n对方QQ:\t{$cqq}",
  1424. 'remark' => "感谢您的使用,点击详情查看对方信息",
  1425. 'type' => 'contact',
  1426. 'keywords' => [
  1427. 'keyword1' => [
  1428. 'value' => '已确认',
  1429. 'color' => '#173177',
  1430. ],
  1431. 'keyword2' => [
  1432. 'value' => date('Y年m月d日 H点i分s秒'),
  1433. 'color' => '#173177',
  1434. ],
  1435. 'keyword3' => [
  1436. 'value' => "来自【{$cNickname}】,姓名:【{$cRealname}】的认识申请已经确认通过,请及时添加对方联系方式",
  1437. 'color' => '#173177',
  1438. ],
  1439. ],
  1440. 'url' => url("/weixin/member/home?id={$contactUid}&cid=$cid", '', '', true),
  1441. ];
  1442. PRedis::set('messages:contactConfirm_' . $userId.'_'.$contactUid, ['data' => $contactData, 'params' => $params], 600);
  1443. Wechat::sendTplMsg($openid, $params);
  1444. }*/
  1445. // 通知对方模板信息
  1446. if ($cOpenid) {
  1447. $wechatCode = isset($memberInfo['wechat_code']) ? trim($memberInfo['wechat_code']) : '';
  1448. $qq = isset($memberInfo['qq']) ? trim($memberInfo['qq']) : '';
  1449. $wechatCode = $wechatCode ? $wechatCode : '无';
  1450. $qq = $qq ? $qq : '无';
  1451. $dateTime = date('Y.m.d H:i');
  1452. if ($checkStatus == 2) {
  1453. $params = [
  1454. 'title' => "你喜欢的人也喜欢你啦\n\n对方姓名:\t{$nickname}(昵称)\n\n对方微信号: \t{$wechatCode}\n\n申请时间:\t{$dateTime}",
  1455. 'remark' => "脱单需主动,交友需谨慎!",
  1456. 'type' => 'contact_confirm',
  1457. 'keywords' => [
  1458. 'keyword1' => [
  1459. 'value' => '状态通知',
  1460. 'color' => '#173177',
  1461. ],
  1462. 'keyword2' => [
  1463. 'value' => '已接受',
  1464. 'color' => '#173177',
  1465. ],
  1466. ],
  1467. 'url' => url("/weixin/member/home?id={$userId}&cid={$cid}", '', '', true),
  1468. ];
  1469. } else if ($checkStatus == 3) {
  1470. // 是否扣除爱心
  1471. $remark = $applyRefundPay ? "扣除{$applyRefundPay}颗后已经原路退回" : "已经全部原路退回";
  1472. $params = [
  1473. 'title' => "Soory!亲亲!{$nickname}拒绝了您的加微信申请,您支付的爱心{$remark}。别灰心哦,您一定会遇到更好的另一半~\n\n申请时间:\t{$dateTime}",
  1474. 'remark' => "天涯何处无芳草,去看看其他的异性吧!",
  1475. 'type' => 'contact_confirm',
  1476. 'keywords' => [
  1477. 'keyword1' => [
  1478. 'value' => '状态通知',
  1479. 'color' => '#173177',
  1480. ],
  1481. 'keyword2' => [
  1482. 'value' => '已拒绝',
  1483. 'color' => '#173177',
  1484. ],
  1485. ],
  1486. 'url' => url("/weixin/match/index", '', '', true),
  1487. ];
  1488. } else {
  1489. // 是否已读
  1490. $remark = $isRead && $applyRefundPay ? "扣除{$applyRefundPay}颗后已经原路退回" : "已经全部原路退回";
  1491. $params = [
  1492. 'title' => "您好亲亲,非常抱歉{$nickname}未及时反馈而导致申请超时,您被扣除的爱心{$remark}。您还可以请客服帮您牵线增加成功率哦~\n\n申请时间:\t{$dateTime}",
  1493. 'remark' => "当你有勇气主动时,其实已经打败了那些看似优秀的人,遇见不易让客服牵线试试吧!",
  1494. 'type' => 'contact_confirm',
  1495. 'keywords' => [
  1496. 'keyword1' => [
  1497. 'value' => '状态通知',
  1498. 'color' => '#173177',
  1499. ],
  1500. 'keyword2' => [
  1501. 'value' => '过期失效',
  1502. 'color' => '#173177',
  1503. ],
  1504. ],
  1505. 'url' => url("/weixin/match/index", '', '', true),
  1506. ];
  1507. }
  1508. // 操作日志
  1509. if ($checkStatus == 2 || $checkStatus == 3) {
  1510. $content = $checkStatus == 2 ? "通过用户{$cNickname}微信申请" : "拒绝用户{$cNickname}微信申请";
  1511. UserLog::saveLog(['user_id' => $userId, 'type' => 4, 'content' => $content]);
  1512. }
  1513. PRedis::set('messages:contactConfirm:' . $contactUid . '_' . $userId, ['openid' => $cOpenid, 'data' => $contactData, 'params' => $params], 600);
  1514. Wechat::sendTplMsg($cOpenid, $params);
  1515. }
  1516. return ['id' => $cid];
  1517. }
  1518. /**
  1519. * 用户页面访问统计
  1520. * @param $userId 访问用户
  1521. * @param string $type 访问类型
  1522. * @param int $targetUid 目标用户
  1523. */
  1524. public static function visitCount($userId, $type = 'login', $targetUid = 0, $expire = 1)
  1525. {
  1526. $cacheKey = 'counts:users:' . date('Ymd') . '_' . $type;
  1527. $cacheTempKey = 'counts:usersTemp:' . $userId . '_' . $type . '_' . date('Ymd');
  1528. $checkUser = Member::where(['user_type' => 2, 'id' => $userId])
  1529. ->value('id');
  1530. if ($checkUser && $userId && !PRedis::get($cacheTempKey)) {
  1531. PRedis::set($cacheTempKey, ['userId' => $userId, 'type' => $type, 'target' => $targetUid], $expire * 3600);
  1532. $types = ['login' => '登录', 'match' => '访问单身推荐', 'heart' => '访问怦然心动', 'center' => '访问用户中心', 'home' => "访问用户[{$targetUid}]信息", 'activity' => '浏览活动列表', 'book' => '想要报名'];
  1533. $title = isset($types[$type]) ? $types[$type] : '访问平台';
  1534. if ($type != 'profile') {
  1535. UserLog::saveLog(['user_id' => $userId, 'type' => 4, 'content' => "【{$userId}】用户{$title}"]);
  1536. }
  1537. if (!PRedis::get($cacheKey)) {
  1538. PRedis::set($cacheKey, 1, 2 * 24 * 3600);
  1539. } else {
  1540. PRedis::inc($cacheKey, 1);
  1541. }
  1542. }
  1543. }
  1544. /**
  1545. * 获取匹配用户数据列表
  1546. * @param $matchUids
  1547. * @return array|bool
  1548. * @throws \think\db\exception\DataNotFoundException
  1549. * @throws \think\db\exception\ModelNotFoundException
  1550. * @throws \think\exception\DbException
  1551. */
  1552. public static function getMatchList($matchUids, $activityId = 0)
  1553. {
  1554. if (empty($matchUids)) {
  1555. return false;
  1556. }
  1557. $field = 'm.id,m.user_nickname,m.avatar,m.mobile,m.sex,m.birthday,m.is_heart,m.real_name,up.age,up.height,up.weight,up.company,up.occupation,up.property,up.graduate,up.education,up.province,up.salary,up.city,up.district,up.home_province,up.home_city,up.home_district,up.introduce,up.family,up.hobby,up.purpose,up.cause,up.expect,up.show_company,up.show_graduate,up.married,up.tags,up.isinfo,m.vip_auth,m.vip_expire,up.education_check,up.position_check,up.idcard_check';
  1558. $dataList = Member::alias('m')
  1559. ->leftJoin('user_profile up', 'up.userid=m.id')
  1560. ->where('m.id', 'in', $matchUids)
  1561. ->field($field)
  1562. ->select()
  1563. ->each(function ($item) use ($activityId) {
  1564. if ($activityId) {
  1565. $item['book_no'] = Books::where(['uid' => $item['id'], 'aid' => $activityId, 'status' => 3])->value('book_num');
  1566. }
  1567. Member::formatUser($item);
  1568. });
  1569. return $dataList ? $dataList->toArray() : [];
  1570. }
  1571. /**
  1572. * 格式化用户信息
  1573. * @param $item 数据
  1574. * @param $type
  1575. */
  1576. private static function formatUser(&$item, $type = 0)
  1577. {
  1578. if (isset($item['avatar'])) {
  1579. $item['avatar'] = cmf_get_image_preview_url($item['avatar']);
  1580. }
  1581. if (isset($item['brief'])) {
  1582. $item['brief'] = htmlspecialchars_decode($item['brief']);
  1583. }
  1584. if (isset($item['sex'])) {
  1585. $sexs = ['', '男', '女'];
  1586. $sex = isset($item['sex']) ? $item['sex'] : 0;
  1587. $item['sex_txt'] = isset($sexs[$sex]) ? $sexs[$sex] : '';
  1588. }
  1589. $item['albums'] = [];
  1590. $photolist = isset($item['photolist']) ? $item['photolist'] : '';
  1591. $photolist = $photolist ? explode(',', $photolist) : [];
  1592. if ($photolist) {
  1593. $albums = [];
  1594. foreach ($photolist as $k => $val) {
  1595. $albums[] = cmf_get_image_preview_url($val);
  1596. }
  1597. $item['albums'] = $albums;
  1598. }
  1599. if (isset($item['birthday'])) {
  1600. $birthday = isset($item['birthday']) ? $item['birthday'] : 0;
  1601. $item['birthday_txt'] = $birthday ? date('Y年m月d日', $birthday) : '';
  1602. $item['birthday_code'] = $birthday ? date('Y-m-d', $birthday) : '';
  1603. $item['birthday_day'] = $birthday ? date('y年', $birthday) : '';
  1604. }
  1605. $item['height_txt'] = '';
  1606. if (isset($item['height'])) {
  1607. $height = isset($item['height']) ? intval($item['height']) : 0;
  1608. $item['height'] = intval($height);
  1609. $item['height_txt'] = $height ? intval($item['height']) . 'CM' : '无';
  1610. }
  1611. $item['weight_txt'] = '';
  1612. if (isset($item['weight'])) {
  1613. $weight = isset($item['weight']) ? intval($item['weight']) : 0;
  1614. $item['weight'] = intval($weight);
  1615. $item['weight_txt'] = $weight ? intval($item['weight']) . 'KG' : '无';
  1616. }
  1617. // 学历
  1618. $item['education_txt'] = '';
  1619. if (isset($item['education'])) {
  1620. $educations = config('weixin.educations');
  1621. $edu = isset($item['education']) ? $item['education'] : 0;
  1622. $item['education_txt'] = isset($educations[$edu]) ? $educations[$edu] : '无';
  1623. }
  1624. // 资产
  1625. $item['property_txt'] = '暂无';
  1626. $property = isset($item['property']) ? $item['property'] : 0;
  1627. if (isset($item['property'])) {
  1628. $propertys = config('weixin.propertys');
  1629. $item['property'] = $property;
  1630. $item['property_txt'] = $property && isset($propertys[$property]) ? $propertys[$property] : '暂无';
  1631. }
  1632. // 地址
  1633. $item['now_address'] = '';
  1634. if (isset($item['province'])) {
  1635. $province = isset($item['province']) ? trim($item['province']) : '';
  1636. $city = isset($item['city']) ? trim($item['city']) : '';
  1637. $item['now_address'] = trim($province . ' ' . $city);
  1638. }
  1639. $item['home_address'] = '';
  1640. if (isset($item['home_province'])) {
  1641. $homeProvince = isset($item['home_province']) ? trim($item['home_province']) : '';
  1642. $homeCity = isset($item['home_city']) ? trim($item['home_city']) : '';
  1643. $item['home_address'] = trim($homeProvince . ' ' . $homeCity);
  1644. }
  1645. // 格式化婚姻状况
  1646. $item['married_txt'] = '';
  1647. if (isset($item['married'])) {
  1648. $marrieds = config('weixin.marrieds');
  1649. $married = $item['married'] ? intval($item['married']) : 0;
  1650. $item['married_txt'] = $married > 0 && isset($marrieds[$married - 1]) ? $marrieds[$married - 1] : '无';
  1651. }
  1652. }
  1653. /**
  1654. * 获取收到或发出消息数量
  1655. * @param $userId
  1656. * @param array $params
  1657. * @return float|int|string
  1658. */
  1659. public static function getMessageTotal($userId, $params = [])
  1660. {
  1661. $type = isset($params['type']) ? intval($params['type']) : 1;
  1662. // 我收到的
  1663. if ($type == 1) {
  1664. $where = ['uc.contact_uid' => $userId];
  1665. $joinWhere = 'u.id=uc.user_id';
  1666. } else {
  1667. $where = ['uc.user_id' => $userId];
  1668. $joinWhere = 'u.id=uc.contact_uid';
  1669. }
  1670. $status = isset($params['status']) ? intval($params['status']) : 1;
  1671. return UserContactLog::alias('uc')
  1672. ->join('user u', $joinWhere, 'left')
  1673. ->where($where)
  1674. ->where('u.id', '>', 0)
  1675. ->where(function ($query) use ($status) {
  1676. if ($status == 1) {
  1677. $query->where('uc.status', '>', 1);
  1678. } else {
  1679. $query->where('uc.status', 1);
  1680. }
  1681. })
  1682. ->count('uc.id');
  1683. }
  1684. /**
  1685. * 获取用户申请消息列表
  1686. * @param $params
  1687. * @param $pageSize
  1688. * @param string $field
  1689. * @return $this
  1690. */
  1691. public static function getMessageList($userId, $params = [], $pageSize = 20, $field = '')
  1692. {
  1693. // 验证有效时间,会员不限制
  1694. $type = isset($params['type']) ? intval($params['type']) : 1;
  1695. // 我收到的
  1696. if ($type == 1) {
  1697. $where = ['uc.contact_uid' => $userId];
  1698. $joinWhere = 'u.id=uc.user_id';
  1699. } else {
  1700. $where = ['uc.user_id' => $userId];
  1701. $joinWhere = 'u.id=uc.contact_uid';
  1702. }
  1703. $status = isset($params['status']) ? intval($params['status']) : 1;
  1704. $siteInfo = cmf_get_site_info();
  1705. $expire = isset($siteInfo['contact_time']) ? intval($siteInfo['contact_time']) : 0;
  1706. $expire = $expire ? $expire : 1;
  1707. $field = $field ? $field : 'uc.id,uc.user_id,uc.contact_uid,uc.created_at,uc.remark,uc.updated_at,uc.is_read,uc.status,u.id as uid,u.user_login,u.real_name,u.user_nickname,u.avatar,u.sex,u.birthday,mp.graduate,mp.education,mp.height,mp.weight,mp.show_graduate,mp.show_company,mp.company,mp.occupation,mp.province,mp.city,mp.home_province,mp.home_city';
  1708. $dataList = UserContactLog::alias('uc')
  1709. ->join('user u', $joinWhere, 'left')
  1710. ->join('user_profile mp', 'mp.userid=u.id', 'left')
  1711. ->where($where)
  1712. ->where('u.id', '>', 0)
  1713. ->where(function ($query) use ($status) {
  1714. if ($status == 1) {
  1715. $query->where('uc.status', 1);
  1716. } else {
  1717. $query->where('uc.status', '>', 1);
  1718. }
  1719. })
  1720. ->field($field)
  1721. ->order('uc.status asc,uc.created_at desc')
  1722. ->paginate($pageSize)
  1723. ->each(function ($item, $k) use ($expire) {
  1724. $expire = $expire ? $expire * 86400 : 0;
  1725. $status = isset($item['status']) ? intval($item['status']) : 0;
  1726. $item['avatar'] = isset($item['avatar']) ? cmf_get_image_preview_url($item['avatar']) : '';
  1727. $rtime = $item['created_at'] ? strtotime($item['created_at']) : 0;
  1728. $rtime = $rtime > time() - $expire ? $rtime - (time() - $expire) : 0;
  1729. $item['rtime'] = $rtime;
  1730. $rtime = $rtime > 23 * 3600 ? ceil($rtime / 86400) . '天' : ($rtime > 3600 ? ceil($rtime / 3600) . '小时' : ($rtime > 60 ? ceil($rtime / 60) . '分钟' : ''));
  1731. if ($status == 1) {
  1732. if ($rtime) {
  1733. $item['time'] = '<em class="red">' . $rtime . '后</em> 自动拒绝';
  1734. } else {
  1735. $item['time'] = '待处理';
  1736. }
  1737. } else {
  1738. $item['time'] = $status == 2 ? '已通过' : ($status == 3 ? '已拒绝' : '待处理');
  1739. if ($status == 4) {
  1740. $info['time'] = '过期自动处理';
  1741. }
  1742. }
  1743. Member::formatUser($item);
  1744. return $item;
  1745. });
  1746. $dataList = $dataList ? $dataList->toArray() : ['total' => 0];
  1747. $dataList['total1'] = Member::getMessageTotal($userId, $params);
  1748. return $dataList;
  1749. }
  1750. /**
  1751. * 获取用户申请消息列表
  1752. * @param $params
  1753. * @param $pageSize
  1754. * @param string $field
  1755. * @return $this
  1756. */
  1757. public static function getMessageInfo($id, $userId = 0, $field = '')
  1758. {
  1759. $siteInfo = cmf_get_site_info();
  1760. $expire = isset($siteInfo['contact_time']) ? intval($siteInfo['contact_time']) : 0;
  1761. $expire = $expire ? $expire : 1;
  1762. $type = 1;
  1763. $joinWhere = 'u.id=uc.user_id';
  1764. $data = UserContactLog::where(['id' => $id])->field('user_id,contact_uid')->find();
  1765. if ($userId && isset($data['user_id']) && $data['user_id'] == $userId) {
  1766. $joinWhere = 'u.id=uc.contact_uid';
  1767. $type = 2;
  1768. }
  1769. $field = $field ? $field : 'uc.id,uc.user_id,uc.contact_uid,uc.created_at,uc.remark,uc.updated_at,uc.is_read,uc.status,u.id as uid,u.user_login,u.real_name,u.user_nickname,u.avatar,u.sex,u.birthday,mp.wechat_code,mp.graduate,mp.education,mp.height,mp.weight,mp.show_graduate,mp.show_company,mp.company,mp.occupation,mp.province,mp.city,mp.home_province,mp.home_city,mp.education_check,mp.position_check,mp.idcard_check';
  1770. $info = UserContactLog::alias('uc')
  1771. ->join('user u', $joinWhere, 'left')
  1772. ->join('user_profile mp', 'mp.userid=u.id', 'left')
  1773. ->where(['uc.id' => $id])
  1774. ->where('u.id', '>', 0)
  1775. ->field($field)
  1776. ->find();
  1777. $info = $info ? $info->toArray() : [];
  1778. if ($info) {
  1779. $info['type'] = $type;
  1780. $expire = $expire ? $expire * 86400 : 0;
  1781. $status = isset($info['status']) ? intval($info['status']) : 0;
  1782. $info['avatar'] = isset($info['avatar']) ? cmf_get_image_preview_url($info['avatar']) : '';
  1783. $rtime = $info['created_at'] ? strtotime($info['created_at']) : 0;
  1784. $rtime = $rtime > time() - $expire ? $rtime - (time() - $expire) : 0;
  1785. $info['rtime'] = $rtime;
  1786. $rtime = $rtime > 23 * 3600 ? ceil($rtime / 86400) . '天' : ($rtime > 3600 ? ceil($rtime / 3600) . '小时' : ($rtime > 60 ? ceil($rtime / 60) . '分钟' : ''));
  1787. if ($status == 1) {
  1788. if ($rtime) {
  1789. $info['time'] = '<em class="red">' . $rtime . '后</em> 自动拒绝';
  1790. } else {
  1791. $info['time'] = '待处理';
  1792. }
  1793. } else {
  1794. $info['time'] = $status == 2 ? '已通过' : ($status == 3 ? '已拒绝' : '待处理');
  1795. if ($status == 4) {
  1796. $info['time'] = '过期自动处理';
  1797. }
  1798. }
  1799. Member::formatUser($info);
  1800. }
  1801. return $info;
  1802. }
  1803. /**
  1804. * 余额明细
  1805. * @param $params
  1806. * @param int $pageSize
  1807. * @return mixed
  1808. */
  1809. public static function getBalanceLog($params, $pageSize = 15)
  1810. {
  1811. $where = [];
  1812. $userId = isset($params['user_id']) ? $params['user_id'] : 0;
  1813. if ($userId) {
  1814. $where['b.user_id'] = $userId;
  1815. }
  1816. $changeType = isset($params['change_type']) ? $params['change_type'] : 0;
  1817. if ($changeType) {
  1818. $where['b.change_type'] = $changeType;
  1819. }
  1820. $type = isset($params['type']) ? $params['type'] : 0;
  1821. $model = db('user_balance_log')->alias('b')
  1822. ->leftJoin('user u', 'u.id=b.source_uid')
  1823. ->where($where)
  1824. ->where(function ($query) use ($type) {
  1825. if ($type == 'income') {
  1826. $query->where('b.type', '>', 1);
  1827. } else if ($type) {
  1828. $type = is_array($type) ? $type : [$type];
  1829. $query->whereIn('b.type', $type);
  1830. }
  1831. });
  1832. $types = config('weixin.incomeTypes');
  1833. $dataList = $model->field('b.id,b.type,b.order_sn,b.change as money,b.change_type,b.balance,b.remark,b.description,b.create_time,status,u.user_nickname')
  1834. ->where('b.status', 'lt', 4)
  1835. ->order("b.create_time desc")
  1836. ->paginate($pageSize)
  1837. ->each(function ($item, $k) use ($types) {
  1838. $item['format_time'] = $item['create_time'] ? date('Y年m月d日 H点i分', $item['create_time']) : '';
  1839. $item['money'] = floatval($item['money']);
  1840. $type = isset($item['type']) ? $item['type'] : 0;
  1841. $item['typeName'] = isset($types[$type]) ? $types[$type] : '';
  1842. return $item;
  1843. });
  1844. $dataList = $dataList ? $dataList->toArray() : [];
  1845. if ($dataList) {
  1846. $total = $model->where('b.status', '=', 2)->sum('b.change');
  1847. $dataList['total_money'] = moneyFormat($total);
  1848. $total = db('user_balance_log')->alias('b')
  1849. ->leftJoin('user u', 'u.id=b.source_uid')
  1850. ->where($where)
  1851. ->where(function ($query) use ($type) {
  1852. if ($type == 'income') {
  1853. $query->where('b.type', '>', 1);
  1854. } else if ($type) {
  1855. $type = is_array($type) ? $type : [$type];
  1856. $query->whereIn('b.type', $type);
  1857. }
  1858. })
  1859. ->where('b.status', '=', 1)
  1860. ->order("b.create_time desc")
  1861. ->sum('b.change');
  1862. $dataList['nopay_money'] = moneyFormat($total);
  1863. }
  1864. return $dataList;
  1865. }
  1866. /**
  1867. * 邀请扽团队成员或会员列表
  1868. * @param $params 参数
  1869. * @param $type 类型:1-团队成员,2-邀请的会员
  1870. * @param int $pageSize
  1871. * @return mixed
  1872. */
  1873. public static function getInviteList($inviteId, $type = 1, $pageSize = 15)
  1874. {
  1875. $where = ['user_type' => 2, 'user_status' => 1];
  1876. if ($inviteId) {
  1877. $where['parent_id'] = $inviteId;
  1878. }
  1879. if ($type == 1) {
  1880. $where['agent_type'] = 1;
  1881. $orderBy = "agent_create_time desc";
  1882. } else {
  1883. $where['agent_type'] = 0;
  1884. $orderBy = "create_time desc";
  1885. }
  1886. $model = Member::where($where)
  1887. ->where(function ($query) use ($type) {
  1888. if ($type == 1) {
  1889. $query->where('agent_status', '<', 4);
  1890. } else {
  1891. $query->whereIn('user_status', [0, 1, 2]);
  1892. }
  1893. });
  1894. $field = 'id,openid,user_nickname,sex,user_type,agent_type,agent_status,agent_create_time,create_time,avatar,is_reg_profile,user_status,is_heart,vip_auth,vip_expire,is_follow';
  1895. $dataList = $model->field($field)
  1896. ->order($orderBy)
  1897. ->paginate($pageSize)
  1898. ->each(function ($item, $k) use ($type, $inviteId) {
  1899. $item['avatar'] = $item['avatar'] ? cmf_get_image_preview_url($item['avatar']) : '';
  1900. if ($type == 1) {
  1901. $item['format_time'] = $item['agent_create_time'] ? date('Y-m-d H:i', $item['agent_create_time']) : '';
  1902. $item['invite_num'] = Member::getInviteCounts(['parent_id' => $item['id']], 2);
  1903. $item['invite_market_num'] = Member::getInviteCounts(['parent_id' => $item['id']], 1);
  1904. $item['invite_sum'] = Member::getBalanceCount($inviteId, $item['id']);
  1905. } else {
  1906. // VIP
  1907. $vipAuth = isset($item['vip_auth']) ? intval($item['vip_auth']) : 0;
  1908. $vipExpire = isset($item['vip_expire']) ? intval($item['vip_expire']) : 0;
  1909. if ($vipAuth && $vipExpire >= time()) {
  1910. $item['vip_auth'] = 1;
  1911. $item['vip_expire'] = date('Y-m-d', $item['vip_expire']);
  1912. } else {
  1913. $item['vip_auth'] = 0;
  1914. $item['vip_expire'] = '';
  1915. }
  1916. $item['format_time'] = $item['create_time'] ? date('Y-m-d H:i', $item['create_time']) : '';
  1917. $item['invite_sum'] = Member::getBalanceCount($inviteId, $item['id'], 2);
  1918. }
  1919. $item['avatar'] = $item['avatar'] ? cmf_get_image_preview_url($item['avatar']) : '';
  1920. return $item;
  1921. });
  1922. $dataList = $dataList ? $dataList->toArray() : [];
  1923. if ($dataList) {
  1924. $counts = [];
  1925. if ($type == 1) {
  1926. $counts['invite_num'] = Member::getInviteCounts(['parent_id' => $inviteId], 1);
  1927. $total = Member::getBalanceCount($inviteId);
  1928. $counts['invite_sum'] = moneyFormat($total);
  1929. } else {
  1930. $counts['invite_sex_1'] = Member::getInviteCounts(['parent_id' => $inviteId, 'sex' => 1], 2);
  1931. $counts['invite_sex_2'] = Member::getInviteCounts(['parent_id' => $inviteId, 'sex' => 2], 2);
  1932. $counts['invite_vip'] = Member::getInviteCounts(['parent_id' => $inviteId, 'vip_auth' => 1], 2);
  1933. $total = Member::getBalanceCount($inviteId, 0, 2);
  1934. $counts['invite_sum'] = moneyFormat($total);
  1935. }
  1936. $dataList['counts'] = $counts;
  1937. }
  1938. return $dataList;
  1939. }
  1940. /**
  1941. * 统计邀请的会员或团队成员
  1942. * @param $params
  1943. * @param int $type
  1944. * @return float|int|string
  1945. */
  1946. public static function getInviteCounts($params, $type = 1)
  1947. {
  1948. $where = ['user_type' => 2, 'user_status' => 1];
  1949. $inviteId = isset($params['parent_id']) ? $params['parent_id'] : 0;
  1950. if ($inviteId) {
  1951. $where['parent_id'] = $inviteId;
  1952. }
  1953. if ($type == 1) {
  1954. $where['agent_type'] = 1;
  1955. } else {
  1956. $where['agent_type'] = 0;
  1957. }
  1958. $sex = isset($params['sex']) ? $params['sex'] : 0;
  1959. if ($sex) {
  1960. $where['sex'] = $sex;
  1961. }
  1962. $sex = isset($params['sex']) ? $params['sex'] : 0;
  1963. if ($sex) {
  1964. $where['sex'] = $sex;
  1965. }
  1966. $count = Member::where($where)
  1967. ->where(function ($query) use ($type) {
  1968. if ($type == 1) {
  1969. $query->where('agent_status', '<', 4);
  1970. } else {
  1971. $query->whereIn('user_status', [0, 1, 2]);
  1972. }
  1973. })
  1974. ->where(function ($query) use ($params) {
  1975. $sex = isset($params['sex']) ? $params['sex'] : 0;
  1976. if ($sex) {
  1977. $query->where('sex', '=', $sex);
  1978. }
  1979. $vipAuth = isset($params['vip_auth']) ? $params['vip_auth'] : 0;
  1980. if ($vipAuth) {
  1981. $query->where('vip_auth', '=', $vipAuth)->where('vip_expire', '>=', time());
  1982. }
  1983. })
  1984. ->count('id');
  1985. return intval($count);
  1986. }
  1987. /**
  1988. * 统计收益金额
  1989. * @param $userId 所属用户
  1990. * @param int $sourceUid 来源用户
  1991. * @param int $type 类型:0-收益分成,
  1992. * @return float
  1993. */
  1994. public static function getBalanceCount($userId, $sourceUid = 0, $userType = 1, $profitType = 0)
  1995. {
  1996. $where = ['b.user_id' => $userId, 'b.status' => 2, 'u.user_type' => 2];
  1997. if ($sourceUid) {
  1998. $where['b.source_uid'] = $sourceUid;
  1999. }
  2000. if ($userType == 1) {
  2001. $where['u.agent_type'] = 1;
  2002. } else {
  2003. $where['u.agent_type'] = 0;
  2004. }
  2005. if ($profitType) {
  2006. $where['b.type'] = $profitType;
  2007. }
  2008. //var_dump($where);
  2009. $sum = UserBalanceLog::alias('b')
  2010. ->leftJoin('user u', 'u.id=b.source_uid')
  2011. ->where($where)
  2012. ->where('b.type', '>', 1)
  2013. ->where('b.type', '<', 30)
  2014. ->sum('b.pay_money');
  2015. return moneyFormat($sum);
  2016. }
  2017. /**
  2018. * 投诉拉黑用户列表
  2019. * @param int $type 类型
  2020. * @param int $pageSize 分页大小
  2021. * @return array|bool|\think\Paginator
  2022. * @throws \think\exception\DbException
  2023. */
  2024. public static function getComplainList($type, $pageSize = 30)
  2025. {
  2026. $page = input('page', 1);
  2027. $cacheKey = "cache:complainList:p_{$type}_{$page}_{$pageSize}";
  2028. $dataList = PRedis::get($cacheKey);
  2029. if ($dataList) {
  2030. return $dataList;
  2031. }
  2032. $complainTypes = config('weixin.complainTypes');
  2033. $dataList = Complain::alias('c')
  2034. ->leftJoin('user u', 'u.id=c.c_uid')
  2035. ->field('c.id,u.id as uid,u.real_name,u.user_nickname,u.avatar,u.mobile,c.type,c.remark,c.status')
  2036. ->where(['c.status' => 2])
  2037. ->where('u.id', '>', 0)
  2038. ->where(function ($query) use ($type) {
  2039. if ($type == 2) {
  2040. $query->where('c.created_time', '>=', time() - 3 * 24 * 3600);
  2041. }
  2042. })
  2043. ->order('c.created_time desc')
  2044. ->paginate($pageSize)
  2045. ->each(function ($item, $k) use ($complainTypes) {
  2046. $item['wechat_code'] = UserProfile::where(['userid' => $item['uid']])->value('wechat_code');
  2047. $item['wechat_code'] = $item['wechat_code'] ? formatName($item['wechat_code']) : '';
  2048. $item['avatar'] = $item['avatar'] ? cmf_get_image_preview_url($item['avatar']) : '';
  2049. $type = isset($item['type']) ? $item['type'] : 8;
  2050. $item['type_name'] = isset($complainTypes[$type]) ? $complainTypes[$type] : '其他';
  2051. $item['remark_count'] = $item['remark'] ? mb_strlen($item['remark'], 'utf-8') : 0;
  2052. $item['remark_sub'] = $item['remark_count'] > 30 ? substr($item['remark'], 0, 30) : $item['remark'];
  2053. });
  2054. if ($dataList) {
  2055. PRedis::set($cacheKey, $dataList, 10);
  2056. }
  2057. return $dataList;
  2058. }
  2059. /**
  2060. * 解锁用户访问信息
  2061. * @param $uid 当前用户
  2062. * @param $cuid 被解锁用户
  2063. * @return array|int
  2064. * @throws \think\Exception
  2065. * @throws \think\db\exception\DataNotFoundException
  2066. * @throws \think\db\exception\ModelNotFoundException
  2067. * @throws \think\exception\DbException
  2068. * @throws \think\exception\PDOException
  2069. */
  2070. public static function catchUnlock($uid, $cuid){
  2071. // 验证用户信息
  2072. $memberInfo = Member::where(['id'=> $uid,'user_status'=> 1])->field('id,user_nickname,redheart,openid')->find();
  2073. if(!$memberInfo){
  2074. return 2102;
  2075. }
  2076. $accessMemberInfo = Member::where(['id'=> $cuid,'user_status'=> 1])->field('id,user_nickname,redheart,openid')->find();
  2077. if(!$accessMemberInfo){
  2078. return 8305;
  2079. }
  2080. // 验证访问信息
  2081. $accessInfo = UserAccess::where(['user_id'=> $uid,'access_uid'=> $cuid,'status'=> 1])->find();
  2082. if(!$accessInfo){
  2083. return 1003;
  2084. }
  2085. if($accessInfo->is_lock == 1){
  2086. return 8304;
  2087. }
  2088. // 验证账户
  2089. $accountConfig = cmf_get_option('account_config');
  2090. $lockAccessPay = isset($accountConfig['lock_access_pay']) ? intval($accountConfig['lock_access_pay']) : 0;
  2091. if($lockAccessPay<=0){
  2092. UserAccess::where(['user_id'=> $uid,'access_uid'=> $cuid,'status'=> 1])->update(['is_lock'=> 1]);
  2093. return ['id'=> $accessInfo->id];
  2094. }
  2095. // 付费解锁
  2096. if($memberInfo->redheart < $lockAccessPay){
  2097. return 2137;
  2098. }
  2099. // 更新
  2100. Db::startTrans();
  2101. if(!UserAccess::where(['user_id'=> $uid,'access_uid'=> $cuid,'status'=> 1])->update(['is_lock'=> 1])){
  2102. Db::rollback();
  2103. return 2032;
  2104. }
  2105. // 扣除账户
  2106. $redheart = $memberInfo->redheart;
  2107. if(!Member::where(['id'=> $uid,'user_status'=> 1])->setDec('redheart',$lockAccessPay)){
  2108. Db::rollback();
  2109. return 2031;
  2110. }
  2111. // 账户明细
  2112. $data = [
  2113. 'user_id'=> $uid,
  2114. 'type'=> 2,
  2115. 'account_type'=> 1,
  2116. 'change_type'=> 2,
  2117. 'money'=> $lockAccessPay,
  2118. 'balance'=> $redheart,
  2119. 'remark'=> '解锁用户【'.$accessMemberInfo->user_nickname.'】访问信息支付'.$lockAccessPay.'颗爱心',
  2120. 'created_at'=> date('Y-m-d H:i:s'),
  2121. 'status'=> 2
  2122. ];
  2123. if(!AccountLog::insertGetId($data)){
  2124. Db::rollback();
  2125. return 8306;
  2126. }
  2127. Db::commit();
  2128. return ['id'=> $accessInfo->id];
  2129. }
  2130. /**
  2131. * 更新身份认证信息
  2132. * @param $userId
  2133. * @param $realname
  2134. * @param $idcard
  2135. * @return bool
  2136. */
  2137. public static function updateAuth($userId, $realname, $idcard){
  2138. Db::startTrans();
  2139. if (!Member::saveData(['id' => $userId], ['real_name' => $realname])) {
  2140. Db::rollback();
  2141. return false;
  2142. }
  2143. // 在线验证是否通过
  2144. $profileData = [
  2145. 'idcard'=> $idcard,
  2146. 'idcard_online_check'=> 1,
  2147. ];
  2148. if (UserProfile::checkProfile($userId)) {
  2149. $profileData['updated_at'] = date('Y-m-d H:i:s');
  2150. $res = UserProfile::saveData(['userid' => $userId], $profileData);
  2151. } else {
  2152. $res = UserProfile::insertGetId($profileData);
  2153. }
  2154. if (!$res) {
  2155. Db::rollback();
  2156. return false;
  2157. }
  2158. // 操作日志
  2159. UserLog::saveLog(['user_id' => $userId, 'type' => 1, 'content' => '提交身份证认证']);
  2160. Db::commit();
  2161. return true;
  2162. }
  2163. }