Authdoctor.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. <?php
  2. namespace app\common\library;
  3. use app\common\model\Doctor;
  4. use fast\Random;
  5. use think\Config;
  6. use think\Db;
  7. use think\Exception;
  8. use think\Hook;
  9. use think\Request;
  10. use think\Validate;
  11. class Authdoctor
  12. {
  13. protected static $instance = null;
  14. protected $_error = '';
  15. protected $_logined = false;
  16. protected $_user = null;
  17. protected $_token = '';
  18. //Token默认有效时长
  19. protected $keeptime = 2592000;
  20. protected $requestUri = '';
  21. protected $rules = [];
  22. //默认配置
  23. protected $config = [];
  24. protected $options = [];
  25. protected $allowFields = [
  26. 'id', 'ruletype', 'nickname', 'avatar', 'gender','mobile',
  27. 'realname',
  28. 'idcard',
  29. 'idcard_z_image',
  30. 'idcard_f_image',
  31. 'idcard_status',
  32. 'doctor_image',
  33. 'doctor_status',
  34. 'english_status',
  35. 'keshi_id',
  36. 'hospital',
  37. 'goodat',
  38. 'level_id',
  39. 'info',
  40. 'job_status'
  41. ];
  42. public function __construct($options = [])
  43. {
  44. if ($config = Config::get('doctor')) {
  45. $this->config = array_merge($this->config, $config);
  46. }
  47. $this->options = array_merge($this->config, $options);
  48. }
  49. /**
  50. *
  51. * @param array $options 参数
  52. * @return Auth
  53. */
  54. public static function instance($options = [])
  55. {
  56. if (is_null(self::$instance)) {
  57. self::$instance = new static($options);
  58. }
  59. return self::$instance;
  60. }
  61. /**
  62. * 生成不重复的随机数字字母组合
  63. */
  64. function getUinqueNo($length = 8, $nos = [])
  65. {
  66. $newid = Random::build("alnum", $length);
  67. if (in_array($newid, $nos)) {
  68. $newid = $this->getUinqueNo($length, $nos);
  69. }
  70. return $newid;
  71. }
  72. /**
  73. * 获取User模型
  74. * @return User
  75. */
  76. public function getUser()
  77. {
  78. return $this->_user;
  79. }
  80. /**
  81. * 兼容调用user模型的属性
  82. *
  83. * @param string $name
  84. * @return mixed
  85. */
  86. public function __get($name)
  87. {
  88. return $this->_user ? $this->_user->$name : null;
  89. }
  90. /**
  91. * 兼容调用user模型的属性
  92. */
  93. public function __isset($name)
  94. {
  95. return isset($this->_user) ? isset($this->_user->$name) : false;
  96. }
  97. /**
  98. * 根据Token初始化
  99. *
  100. * @param string $token Token
  101. * @return boolean
  102. */
  103. public function init($token)
  104. {
  105. if ($this->_logined) {
  106. return true;
  107. }
  108. if ($this->_error) {
  109. return false;
  110. }
  111. $data = Tokendoctor::get($token);
  112. if (!$data) {
  113. return false;
  114. }
  115. $user_id = intval($data['user_id']);
  116. if ($user_id > 0) {
  117. $user = Doctor::get($user_id);
  118. if (!$user) {
  119. $this->setError('Account not exist');
  120. return false;
  121. }
  122. if ($user->status != 1) {
  123. $this->setError('Account is locked');
  124. return false;
  125. }
  126. $this->_user = $user;
  127. $this->_logined = true;
  128. $this->_token = $token;
  129. //初始化成功的事件
  130. // Hook::listen("company_init_successed", $this->_user);
  131. return true;
  132. } else {
  133. $this->setError('You are not logged in');
  134. return false;
  135. }
  136. }
  137. /**
  138. * 注册用户
  139. *
  140. * @param string $username 用户名
  141. * @param string $password 密码
  142. * @param string $email 邮箱
  143. * @param string $mobile 手机号
  144. * @param array $extend 扩展参数
  145. * @return boolean
  146. */
  147. public function register($username, $password, $email = '', $mobile = '', $extend = [])
  148. {
  149. // 检测用户名、昵称、邮箱、手机号是否存在
  150. /*if (User::getByUsername($username)) {
  151. $this->setError('Username already exist');
  152. return false;
  153. }
  154. if (User::getByNickname($username)) {
  155. $this->setError('Nickname already exist');
  156. return false;
  157. }
  158. if ($email && User::getByEmail($email)) {
  159. $this->setError('Email already exist');
  160. return false;
  161. }*/
  162. if(empty($mobile)){
  163. $this->setError('手机号必填');
  164. return false;
  165. }
  166. if ($mobile && Doctor::getByMobile($mobile)) {
  167. $this->setError('Mobile already exist');
  168. return false;
  169. }
  170. $ip = request()->ip();
  171. $time = time();
  172. $data = [
  173. // 'username' => $username,
  174. // 'password' => $password,
  175. // 'email' => $email,
  176. 'mobile' => $mobile,
  177. // 'level' => 1,
  178. // 'score' => 0,
  179. 'avatar' => config('site.doctor_default_avatar'),
  180. ];
  181. $params = array_merge($data, [
  182. // 'nickname' => preg_match("/^1[3-9]{1}\d{9}$/", $username) ? substr_replace($username, '****', 3, 4) : $username,
  183. 'nickname' => get_rand_nick_name(),
  184. // 'salt' => Random::alnum(),
  185. // 'jointime' => $time,
  186. // 'joinip' => $ip,
  187. // 'logintime' => $time,
  188. // 'loginip' => $ip,
  189. // 'prevtime' => $time,
  190. 'status' => 1
  191. ]);
  192. // $params['password'] = $this->getEncryptPassword($password, $params['salt']);
  193. $params = array_merge($params, $extend);
  194. //账号注册时需要开启事务,避免出现垃圾数据
  195. Db::startTrans();
  196. try {
  197. $user = Doctor::create($params, true);
  198. $this->_user = Doctor::get($user->id);
  199. /*$this->_user->username = 'd' . (10000 + $user->id);
  200. $this->_user->save();*/
  201. //设置Token
  202. $this->_token = Random::uuid();
  203. Tokendoctor::set($this->_token, $user->id, $this->keeptime);
  204. //设置登录状态
  205. $this->_logined = true;
  206. //注册钱包
  207. $wallet_id = Db::name('doctor_wallet')->insertGetId(['doctor_id'=>$user->id]);
  208. if(!$wallet_id){
  209. $this->setError('注册用户失败');
  210. Db::rollback();
  211. return false;
  212. }
  213. //注册info
  214. $info_id = Db::name('doctor_info')->insertGetId(['doctor_id'=>$user->id]);
  215. if(!$info_id){
  216. $this->setError('注册用户失败');
  217. Db::rollback();
  218. return false;
  219. }
  220. //[环信]注册用户。忽略失败
  221. /*$easemob = new Easemob();
  222. $rs = $easemob->user_create('doctor'.$user->id);
  223. if($rs === false){
  224. $this->setError('注册用户失败');
  225. Db::rollback();
  226. return false;
  227. }*/
  228. //腾讯im注册用户
  229. $tenim = new Tenim();
  230. $rs = $tenim->register('doctor'.$user->id,$params['nickname'],'');
  231. if($rs !== true){
  232. $this->setError($rs);
  233. Db::rollback();
  234. return false;
  235. }
  236. //注册成功的事件
  237. Db::commit();
  238. } catch (Exception $e) {
  239. $this->setError($e->getMessage());
  240. Db::rollback();
  241. return false;
  242. }
  243. return true;
  244. }
  245. /**
  246. * 用户登录
  247. *
  248. * @param string $account 账号,用户名、邮箱、手机号
  249. * @param string $password 密码
  250. * @return boolean
  251. */
  252. /*public function login($account, $password)
  253. {
  254. $field = 'mobile';
  255. $user = Doctor::get([$field => $account]);
  256. if (!$user) {
  257. $this->setError('Account is incorrect');
  258. return false;
  259. }
  260. if ($user->status != 1) {
  261. $this->setError('Account is locked');
  262. return false;
  263. }
  264. if ($user->password != $this->getEncryptPassword($password, $user->salt)) {
  265. $this->setError('Password is incorrect');
  266. return false;
  267. }
  268. //直接登录员工
  269. return $this->direct($user->id);
  270. }*/
  271. /**
  272. * 退出
  273. *
  274. * @return boolean
  275. */
  276. public function logout()
  277. {
  278. if (!$this->_logined) {
  279. $this->setError('You are not logged in');
  280. return false;
  281. }
  282. //设置登录标识
  283. $this->_logined = false;
  284. //删除Token
  285. Tokendoctor::delete($this->_token);
  286. //退出成功的事件
  287. Hook::listen("user_logout_successed", $this->_user);
  288. return true;
  289. }
  290. /**
  291. * 修改密码
  292. * @param string $newpassword 新密码
  293. * @param string $oldpassword 旧密码
  294. * @param bool $ignoreoldpassword 忽略旧密码
  295. * @return boolean
  296. */
  297. public function changepwd($newpassword, $oldpassword = '', $ignoreoldpassword = false)
  298. {
  299. if (!$this->_logined) {
  300. $this->setError('You are not logged in');
  301. return false;
  302. }
  303. //判断旧密码是否正确
  304. if ($this->_user->password == $this->getEncryptPassword($oldpassword, $this->_user->salt) || $ignoreoldpassword) {
  305. Db::startTrans();
  306. try {
  307. $salt = Random::alnum();
  308. $newpassword = $this->getEncryptPassword($newpassword, $salt);
  309. $this->_user->save(['loginfailure' => 0, 'password' => $newpassword, 'salt' => $salt]);
  310. Token::delete($this->_token);
  311. //修改密码成功的事件
  312. Hook::listen("user_changepwd_successed", $this->_user);
  313. Db::commit();
  314. } catch (Exception $e) {
  315. Db::rollback();
  316. $this->setError($e->getMessage());
  317. return false;
  318. }
  319. return true;
  320. } else {
  321. $this->setError('Password is incorrect');
  322. return false;
  323. }
  324. }
  325. /**
  326. * 直接登录账号
  327. * @param int $user_id
  328. * @return boolean
  329. */
  330. public function direct($user_id)
  331. {
  332. $user = Doctor::get($user_id);
  333. if ($user) {
  334. Db::startTrans();
  335. try {
  336. $ip = request()->ip();
  337. $time = time();
  338. //判断连续登录和最大连续登录
  339. /*if ($user->logintime < \fast\Date::unixtime('day')) {
  340. $user->successions = $user->logintime < \fast\Date::unixtime('day', -1) ? 1 : $user->successions + 1;
  341. $user->maxsuccessions = max($user->successions, $user->maxsuccessions);
  342. }*/
  343. // $user->prevtime = $user->logintime;
  344. //记录本次登录的IP和时间
  345. // $user->loginip = $ip;
  346. // $user->logintime = $time;
  347. //重置登录失败次数
  348. // $user->loginfailure = 0;
  349. // $user->save();
  350. $this->_user = $user;
  351. $this->_token = Random::uuid();
  352. Tokendoctor::set($this->_token, $user->id, $this->keeptime);
  353. $this->_logined = true;
  354. //登录成功的事件
  355. Hook::listen("user_login_successed", $this->_user);
  356. Db::commit();
  357. } catch (Exception $e) {
  358. Db::rollback();
  359. $this->setError($e->getMessage());
  360. return false;
  361. }
  362. return true;
  363. } else {
  364. return false;
  365. }
  366. }
  367. /**
  368. * 判断是否登录
  369. * @return boolean
  370. */
  371. public function isLogin()
  372. {
  373. if ($this->_logined) {
  374. return true;
  375. }
  376. return false;
  377. }
  378. /**
  379. * 获取当前Token
  380. * @return string
  381. */
  382. public function getToken()
  383. {
  384. return $this->_token;
  385. }
  386. public function getUserinfo_simple(){
  387. $userinfo = Tokendoctor::get($this->_token);
  388. //是否完成用户资料
  389. $data = $this->_user->toArray();
  390. if(empty($data['idcard'])){
  391. $userinfo['finish_profile'] = 0;
  392. }else{
  393. $userinfo['finish_profile'] = 1;
  394. }
  395. return $userinfo;
  396. }
  397. /**
  398. * 获取会员基本信息
  399. */
  400. public function getUserinfo()
  401. {
  402. $data = $this->_user->toArray();
  403. $allowFields = $this->getAllowFields();
  404. $userinfo = array_intersect_key($data, array_flip($allowFields));
  405. $userinfo = array_merge($userinfo, Tokendoctor::get($this->_token));
  406. //追加
  407. $userinfo['avatar'] = one_domain_image($userinfo['avatar']);
  408. $userinfo['keshi_name'] = Db::name('keshi')->where('id',$userinfo['keshi_id'])->value('name');
  409. $userinfo['level_name'] = Db::name('doctor_level')->where('id',$userinfo['level_id'])->value('name');
  410. //info
  411. $userinfo['doctor_info'] = Db::name('doctor_info')->where('doctor_id',$this->id)->find();
  412. $userinfo['wallet'] = Db::name('doctor_wallet')->where('doctor_id',$this->id)->find();
  413. //是否完成用户资料
  414. if(empty($data['idcard'])){
  415. $userinfo['finish_profile'] = 0;
  416. }else{
  417. $userinfo['finish_profile'] = 1;
  418. }
  419. //待接图文订单
  420. $where = [
  421. 'doctor_id'=>$this->id,
  422. 'ordertype'=>1,
  423. 'status'=>10,
  424. ];
  425. $userinfo['wenzhen_text_noaccept_num'] = Db::name('wenzhen_order')->where($where)->count();
  426. //待接视频订单
  427. $where = [
  428. 'doctor_id'=>$this->id,
  429. 'ordertype'=>2,
  430. 'status'=>10,
  431. 'video_model'=>1,
  432. ];
  433. $userinfo['wenzhen_video_noaccept_num'] = Db::name('wenzhen_order')->where($where)->count();
  434. //待接订单
  435. $userinfo['wenzhen_noaccept_num'] = $userinfo['wenzhen_text_noaccept_num'] + $userinfo['wenzhen_video_noaccept_num'];
  436. return $userinfo;
  437. }
  438. /**
  439. * 获取当前请求的URI
  440. * @return string
  441. */
  442. public function getRequestUri()
  443. {
  444. return $this->requestUri;
  445. }
  446. /**
  447. * 设置当前请求的URI
  448. * @param string $uri
  449. */
  450. public function setRequestUri($uri)
  451. {
  452. $this->requestUri = $uri;
  453. }
  454. /**
  455. * 获取允许输出的字段
  456. * @return array
  457. */
  458. public function getAllowFields()
  459. {
  460. return $this->allowFields;
  461. }
  462. /**
  463. * 设置允许输出的字段
  464. * @param array $fields
  465. */
  466. public function setAllowFields($fields)
  467. {
  468. $this->allowFields = $fields;
  469. }
  470. /**
  471. * 获取密码加密后的字符串
  472. * @param string $password 密码
  473. * @param string $salt 密码盐
  474. * @return string
  475. */
  476. public function getEncryptPassword($password, $salt = '')
  477. {
  478. return md5(md5($password) . $salt);
  479. }
  480. /**
  481. * 检测当前控制器和方法是否匹配传递的数组
  482. *
  483. * @param array $arr 需要验证权限的数组
  484. * @return boolean
  485. */
  486. public function match($arr = [])
  487. {
  488. $request = Request::instance();
  489. $arr = is_array($arr) ? $arr : explode(',', $arr);
  490. if (!$arr) {
  491. return false;
  492. }
  493. $arr = array_map('strtolower', $arr);
  494. // 是否存在
  495. if (in_array(strtolower($request->action()), $arr) || in_array('*', $arr)) {
  496. return true;
  497. }
  498. // 没找到匹配
  499. return false;
  500. }
  501. /**
  502. * 设置会话有效时间
  503. * @param int $keeptime 默认为永久
  504. */
  505. public function keeptime($keeptime = 0)
  506. {
  507. $this->keeptime = $keeptime;
  508. }
  509. /**
  510. * 渲染用户数据
  511. * @param array $datalist 二维数组
  512. * @param mixed $fields 加载的字段列表
  513. * @param string $fieldkey 渲染的字段
  514. * @param string $renderkey 结果字段
  515. * @return array
  516. */
  517. /*public function render(&$datalist, $fields = [], $fieldkey = 'user_id', $renderkey = 'userinfo')
  518. {
  519. $fields = !$fields ? ['id', 'nickname', 'level', 'avatar'] : (is_array($fields) ? $fields : explode(',', $fields));
  520. $ids = [];
  521. foreach ($datalist as $k => $v) {
  522. if (!isset($v[$fieldkey])) {
  523. continue;
  524. }
  525. $ids[] = $v[$fieldkey];
  526. }
  527. $list = [];
  528. if ($ids) {
  529. if (!in_array('id', $fields)) {
  530. $fields[] = 'id';
  531. }
  532. $ids = array_unique($ids);
  533. $selectlist = User::where('id', 'in', $ids)->column($fields);
  534. foreach ($selectlist as $k => $v) {
  535. $list[$v['id']] = $v;
  536. }
  537. }
  538. foreach ($datalist as $k => &$v) {
  539. $v[$renderkey] = isset($list[$v[$fieldkey]]) ? $list[$v[$fieldkey]] : null;
  540. }
  541. unset($v);
  542. return $datalist;
  543. }*/
  544. /**
  545. * 设置错误信息
  546. *
  547. * @param string $error 错误信息
  548. * @return Auth
  549. */
  550. public function setError($error)
  551. {
  552. $this->_error = $error;
  553. return $this;
  554. }
  555. /**
  556. * 获取错误信息
  557. * @return string
  558. */
  559. public function getError()
  560. {
  561. return $this->_error ? __($this->_error) : '';
  562. }
  563. }