BaseServices.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\services;
  12. use crmeb\utils\JwtAuth;
  13. use think\facade\Db;
  14. use think\facade\Config;
  15. use think\facade\Route as Url;
  16. /**
  17. * Class BaseServices
  18. * @package app\services
  19. */
  20. abstract class BaseServices
  21. {
  22. /**
  23. * 模型注入
  24. * @var object
  25. */
  26. protected $dao;
  27. /**
  28. * 获取分页配置
  29. * @param bool $isPage
  30. * @param bool $isRelieve
  31. * @return int[]
  32. */
  33. public function getPageValue(bool $isPage = true, bool $isRelieve = true)
  34. {
  35. $page = $limit = 0;
  36. if ($isPage) {
  37. $page = app()->request->param(Config::get('database.page.pageKey', 'page') . '/d', 0);
  38. $limit = app()->request->param(Config::get('database.page.limitKey', 'limit') . '/d', 0);
  39. }
  40. $limitMax = Config::get('database.page.limitMax');
  41. $defaultLimit = Config::get('database.page.defaultLimit', 10);
  42. if ($limit > $limitMax && $isRelieve) {
  43. $limit = $limitMax;
  44. }
  45. return [(int)$page, (int)$limit, (int)$defaultLimit];
  46. }
  47. /**
  48. * 数据库事务操作
  49. * @param callable $closure
  50. * @return mixed
  51. */
  52. public function transaction(callable $closure, bool $isTran = true)
  53. {
  54. return $isTran ? Db::transaction($closure) : $closure();
  55. }
  56. /**
  57. * 创建token
  58. * @param int $id
  59. * @param $type
  60. * @return array
  61. */
  62. public function createToken(int $id, $type, string $pwd = '')
  63. {
  64. /** @var JwtAuth $jwtAuth */
  65. $jwtAuth = app()->make(JwtAuth::class);
  66. return $jwtAuth->createToken($id, $type, ['auth' => md5($pwd)]);
  67. }
  68. /**
  69. * 获取路由地址
  70. * @param string $path
  71. * @param array $params
  72. * @param bool $suffix
  73. * @param bool $isDomain
  74. * @return string
  75. */
  76. public function url(string $path, array $params = [], bool $suffix = false, bool $isDomain = false)
  77. {
  78. return Url::buildUrl($path, $params)->suffix($suffix)->domain($isDomain)->build();
  79. }
  80. /**
  81. * 密码hash加密
  82. * @param string $password
  83. * @return false|string|null
  84. */
  85. public function passwordHash(string $password)
  86. {
  87. return password_hash($password, PASSWORD_BCRYPT);
  88. }
  89. /**
  90. * 格式化时间
  91. * @param $time
  92. * @param bool $is_time_key
  93. * @return array
  94. */
  95. public function timeHandle($time, bool $is_time_key = false)
  96. {
  97. switch ($time) {
  98. case 'today':
  99. $start = date('Y-m-d 00:00:00');
  100. $end = date('Y-m-d 23:59:59');
  101. break;
  102. case 'yesterday':
  103. $start = date('Y-m-d 00:00:00', strtotime("-1 day"));
  104. $end = date('Y-m-d 23:59:59', strtotime("-1 day"));
  105. break;
  106. case 'sevenday':
  107. $start = date('Y-m-d 00:00:00', strtotime('-6 day'));
  108. $end = date('Y-m-d 23:59:59');
  109. break;
  110. case 'thirtyday':
  111. $start = date('Y-m-d 00:00:00', strtotime('-29 day'));
  112. $end = date('Y-m-d 23:59:59');
  113. break;
  114. case 'last month':
  115. $start = date('Y-m-01 00:00:00', strtotime('first Day of last month 00:00:00'));
  116. $end = date("Y-m-d 23:59:59", strtotime('first Day of this month 00:00:00 -1second'));
  117. break;
  118. case 'month':
  119. $start = date('Y-m-01 00:00:00');
  120. $end = date('Y-m-d 23:59:59', mktime(23, 59, 59, date('m'), date('t'), date('Y')));
  121. break;
  122. case 'year':
  123. $start = date('Y-01-01 00:00:00');
  124. $end = date('Y-12-31 23:59:59');
  125. break;
  126. default:
  127. $start = date("Y/m/d", strtotime("-30 days", time()));
  128. $end = date("Y/m/d", time());
  129. if (strstr($time, '-') !== false) {
  130. [$start_r, $end_r] = explode('-', $time);
  131. if ($start_r || $end_r) {
  132. $start = $start_r;
  133. $end = $end_r;
  134. $end_time = strtotime($end_r);
  135. //没选具体时分秒 加上86400
  136. if ($end_time == strtotime(date('Y/m/d', $end_time))) {
  137. $end = date('Y/m/d H:i:s', $end_time + 86399);
  138. }
  139. }
  140. }
  141. break;
  142. }
  143. $start = $start ? strtotime($start) : 0;
  144. $end = $end ? strtotime($end) : 0;
  145. if ($is_time_key) {
  146. $dayCount = ceil(($end - $start) / 86400);
  147. $s_start = $start;
  148. $timeKey = [];
  149. if ($dayCount == 1) {
  150. $timeType = 'hour';
  151. $timeKey = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
  152. } elseif ($dayCount <= 31) {
  153. $timeType = 'day';
  154. for ($i = 0; $i < $dayCount; $i++) {
  155. $timeKey[] = date('Y-m-d', $s_start);
  156. $s_start = strtotime("+1 day", $s_start);
  157. }
  158. } elseif ($dayCount <= 92) {
  159. $timeType = 'weekly';
  160. for ($i = 0; $i < $dayCount; $i = $i + 7) {
  161. $timeKey[] = '第' . date('W', $s_start) . '周';
  162. $s_start = strtotime("+1 week", $s_start);
  163. }
  164. } else {
  165. $timeType = 'year';
  166. while ($s_start <= $end) {
  167. $timeKey[] = date('Y-m', $s_start);
  168. $s_start = strtotime("+1 month", $s_start);
  169. }
  170. }
  171. return [$start, $end, $timeType, $timeKey];
  172. }
  173. return [$start, $end];
  174. }
  175. /**
  176. * 计算环比增长率
  177. * @param $nowValue
  178. * @param $lastValue
  179. * @return float|int|string
  180. */
  181. public function countRate($nowValue, $lastValue)
  182. {
  183. if ($lastValue == 0 && $nowValue == 0) return 0;
  184. if ($lastValue == 0) return round(bcmul(bcdiv($nowValue, 1, 4), 100, 2), 2);
  185. if ($nowValue == 0) return -round(bcmul(bcdiv($lastValue, 1, 4), 100, 2), 2);
  186. return bcmul(bcdiv((bcsub($nowValue, $lastValue, 2)), $lastValue, 4), 100, 2);
  187. }
  188. /**
  189. * tree处理 分类、标签数据(这一类数据)
  190. * @param array $cate
  191. * @param array $label
  192. * @return array
  193. */
  194. public function get_tree_children(array $cate, array $label)
  195. {
  196. if ($cate) {
  197. foreach ($cate as $key => $value) {
  198. if ($label) {
  199. foreach ($label as $k => $item) {
  200. if ($value['id'] == $item['label_cate']) {
  201. $cate[$key]['children'][] = $item;
  202. unset($label[$k]);
  203. }
  204. }
  205. } else {
  206. $cate[$key]['children'] = [];
  207. }
  208. }
  209. }
  210. return $cate;
  211. }
  212. /**
  213. * ip转城市
  214. * @param $ip
  215. * @return array|string|string[]|null
  216. */
  217. public function convertIp($ip)
  218. {
  219. try {
  220. $ip1num = 0;
  221. $ip2num = 0;
  222. $ipAddr1 = "";
  223. $ipAddr2 = "";
  224. $dat_path = public_path() . 'statics/ip.dat';
  225. if (!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $ip)) {
  226. return '';
  227. }
  228. if (!$fd = @fopen($dat_path, 'rb')) {
  229. return '';
  230. }
  231. $ip = explode('.', $ip);
  232. $ipNum = $ip[0] * 16777216 + $ip[1] * 65536 + $ip[2] * 256 + $ip[3];
  233. $DataBegin = fread($fd, 4);
  234. $DataEnd = fread($fd, 4);
  235. $ipbegin = implode('', unpack('L', $DataBegin));
  236. if ($ipbegin < 0) $ipbegin += pow(2, 32);
  237. $ipend = implode('', unpack('L', $DataEnd));
  238. if ($ipend < 0) $ipend += pow(2, 32);
  239. $ipAllNum = ($ipend - $ipbegin) / 7 + 1;
  240. $BeginNum = 0;
  241. $EndNum = $ipAllNum;
  242. while ($ip1num > $ipNum || $ip2num < $ipNum) {
  243. $Middle = intval(($EndNum + $BeginNum) / 2);
  244. fseek($fd, $ipbegin + 7 * $Middle);
  245. $ipData1 = fread($fd, 4);
  246. if (strlen($ipData1) < 4) {
  247. fclose($fd);
  248. return '';
  249. }
  250. $ip1num = implode('', unpack('L', $ipData1));
  251. if ($ip1num < 0) $ip1num += pow(2, 32);
  252. if ($ip1num > $ipNum) {
  253. $EndNum = $Middle;
  254. continue;
  255. }
  256. $DataSeek = fread($fd, 3);
  257. if (strlen($DataSeek) < 3) {
  258. fclose($fd);
  259. return '';
  260. }
  261. $DataSeek = implode('', unpack('L', $DataSeek . chr(0)));
  262. fseek($fd, $DataSeek);
  263. $ipData2 = fread($fd, 4);
  264. if (strlen($ipData2) < 4) {
  265. fclose($fd);
  266. return '';
  267. }
  268. $ip2num = implode('', unpack('L', $ipData2));
  269. if ($ip2num < 0) $ip2num += pow(2, 32);
  270. if ($ip2num < $ipNum) {
  271. if ($Middle == $BeginNum) {
  272. fclose($fd);
  273. return '';
  274. }
  275. $BeginNum = $Middle;
  276. }
  277. }
  278. $ipFlag = fread($fd, 1);
  279. if ($ipFlag == chr(1)) {
  280. $ipSeek = fread($fd, 3);
  281. if (strlen($ipSeek) < 3) {
  282. fclose($fd);
  283. return '';
  284. }
  285. $ipSeek = implode('', unpack('L', $ipSeek . chr(0)));
  286. fseek($fd, $ipSeek);
  287. $ipFlag = fread($fd, 1);
  288. }
  289. if ($ipFlag == chr(2)) {
  290. $AddrSeek = fread($fd, 3);
  291. if (strlen($AddrSeek) < 3) {
  292. fclose($fd);
  293. return '';
  294. }
  295. $ipFlag = fread($fd, 1);
  296. if ($ipFlag == chr(2)) {
  297. $AddrSeek2 = fread($fd, 3);
  298. if (strlen($AddrSeek2) < 3) {
  299. fclose($fd);
  300. return '';
  301. }
  302. $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
  303. fseek($fd, $AddrSeek2);
  304. } else {
  305. fseek($fd, -1, SEEK_CUR);
  306. }
  307. while (($char = fread($fd, 1)) != chr(0))
  308. $ipAddr2 .= $char;
  309. $AddrSeek = implode('', unpack('L', $AddrSeek . chr(0)));
  310. fseek($fd, $AddrSeek);
  311. while (($char = fread($fd, 1)) != chr(0))
  312. $ipAddr1 .= $char;
  313. } else {
  314. fseek($fd, -1, SEEK_CUR);
  315. while (($char = fread($fd, 1)) != chr(0))
  316. $ipAddr1 .= $char;
  317. $ipFlag = fread($fd, 1);
  318. if ($ipFlag == chr(2)) {
  319. $AddrSeek2 = fread($fd, 3);
  320. if (strlen($AddrSeek2) < 3) {
  321. fclose($fd);
  322. return '';
  323. }
  324. $AddrSeek2 = implode('', unpack('L', $AddrSeek2 . chr(0)));
  325. fseek($fd, $AddrSeek2);
  326. } else {
  327. fseek($fd, -1, SEEK_CUR);
  328. }
  329. while (($char = fread($fd, 1)) != chr(0)) {
  330. $ipAddr2 .= $char;
  331. }
  332. }
  333. fclose($fd);
  334. if (preg_match('/http/i', $ipAddr2)) {
  335. $ipAddr2 = '';
  336. }
  337. $ipaddr = $ipAddr1;
  338. $ipaddr = preg_replace('/CZ88.NET/is', '', $ipaddr);
  339. $ipaddr = preg_replace('/^s*/is', '', $ipaddr);
  340. $ipaddr = preg_replace('/s*$/is', '', $ipaddr);
  341. if (preg_match('/http/i', $ipaddr) || $ipaddr == '') {
  342. $ipaddr = '';
  343. }
  344. return $this->strToUtf8($ipaddr);
  345. } catch (\Throwable $e) {
  346. return '';
  347. }
  348. }
  349. /**
  350. * 文字格式转utf8
  351. * @param $str
  352. * @return array|false|string|string[]|null
  353. */
  354. public function strToUtf8($str)
  355. {
  356. $encode = mb_detect_encoding($str, array("ASCII", 'UTF-8', "GB2312", "GBK", 'BIG5'));
  357. if ($encode == 'UTF-8') {
  358. return $str;
  359. } else {
  360. return mb_convert_encoding($str, 'UTF-8', $encode);
  361. }
  362. }
  363. /**
  364. * 处理城市数据
  365. * @param $address
  366. * @return array
  367. */
  368. public function addressHandle($address)
  369. {
  370. if ($address) {
  371. try {
  372. preg_match('/(.*?(省|自治区|北京市|天津市|上海市|重庆市|澳门特别行政区|香港特别行政区))/', $address, $matches);
  373. if (count($matches) > 1) {
  374. $province = $matches[count($matches) - 2];
  375. $address = preg_replace('/(.*?(省|自治区|北京市|天津市|上海市|重庆市|澳门特别行政区|香港特别行政区))/', '', $address, 1);
  376. }
  377. preg_match('/(.*?(市|自治州|地区|区划|县))/', $address, $matches);
  378. if (count($matches) > 1) {
  379. $city = $matches[count($matches) - 2];
  380. $address = str_replace($city, '', $address);
  381. }
  382. preg_match('/(.*?(区|县|镇|乡|街道))/', $address, $matches);
  383. if (count($matches) > 1) {
  384. $area = $matches[count($matches) - 2];
  385. $address = str_replace($area, '', $address);
  386. }
  387. } catch (\Throwable $e) {
  388. }
  389. }
  390. return [
  391. 'province' => $province ?? '',
  392. 'city' => $city ?? '',
  393. 'district' => $area ?? '',
  394. "address" => $address
  395. ];
  396. }
  397. /**
  398. * @param $name
  399. * @param $arguments
  400. * @return mixed
  401. */
  402. public function __call($name, $arguments)
  403. {
  404. return call_user_func_array([$this->dao, $name], $arguments);
  405. }
  406. }