common.php 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999
  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. // 应用公共文件
  12. use app\common\repositories\system\config\ConfigValueRepository;
  13. use app\common\repositories\system\groupData\GroupDataRepository;
  14. use crmeb\services\UploadService;
  15. use Swoole\Lock;
  16. use think\db\BaseQuery;
  17. if (!function_exists('go')) {
  18. function go(): bool
  19. {
  20. return \Swoole\Coroutine::create(...func_get_args());
  21. }
  22. }
  23. if (!function_exists('isDebug')) {
  24. function isDebug(): bool
  25. {
  26. return !!env('APP_DEBUG');
  27. }
  28. }
  29. if (!function_exists('formToData')) {
  30. function formToData($form): array
  31. {
  32. $rule = $form->formRule();
  33. $action = $form->getAction();
  34. $method = $form->getMethod();
  35. $title = $form->getTitle();
  36. $config = (object)$form->formConfig();
  37. return compact('rule', 'action', 'method', 'title', 'config');
  38. }
  39. }
  40. if (!function_exists('getDistance')) {
  41. function getDistance($lat1, $lng1, $lat2, $lng2)
  42. {
  43. //将角度转为狐度
  44. $radLat1 = deg2rad($lat1);//deg2rad()函数将角度转换为弧度
  45. $radLat2 = deg2rad($lat2);
  46. $radLng1 = deg2rad($lng1);
  47. $radLng2 = deg2rad($lng2);
  48. $a = $radLat1 - $radLat2;
  49. $b = $radLng1 - $radLng2;
  50. $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * 6371;
  51. return round($s, 1);
  52. }
  53. }
  54. /**
  55. * 无线级分类处理
  56. *
  57. * @param array $data 数据源
  58. * @param string $idName 主键
  59. * @param string $fieldName 父级字段
  60. * @param string $childrenKey 子级字段名
  61. * @return array
  62. * @author 张先生
  63. * @date 2020-03-27
  64. */
  65. if (!function_exists('formatCategory')) {
  66. function formatCategory(array $data, string $idName = "id", string $fieldName = 'pid', $childrenKey = 'children')
  67. {
  68. $items = [];
  69. foreach ($data as $item) {
  70. $items[$item[$idName]] = $item;
  71. }
  72. $result = array();
  73. foreach ($items as $item) {
  74. if (isset($items[$item[$fieldName]])) {
  75. $items[$item[$fieldName]][$childrenKey][] = &$items[$item[$idName]];
  76. } else if($item[$fieldName] == 0){
  77. $result[] = &$items[$item[$idName]];
  78. }
  79. }
  80. return $result;
  81. }
  82. }
  83. if (!function_exists('formatTreeList')) {
  84. function formatTreeList(&$options, $name, $pidName = 'pid', $pid = 0, $level = 0, &$data = []): array
  85. {
  86. $_options = $options;
  87. foreach ($_options as $k => $option) {
  88. if ($option[$pidName] == $pid) {
  89. $data[] = ['value' => $k, 'label' => str_repeat('|---', $level + 1) . $option[$name]];
  90. unset($options[$k]);
  91. formatTreeList($options, $name, $pidName, $k, $level + 1, $data);
  92. }
  93. }
  94. return $data;
  95. }
  96. }
  97. if (!function_exists('formatTree')) {
  98. function formatTree(&$options, $name, $pidName = 'pid', $pid = 0, $level = 0, $data = []): array
  99. {
  100. $_options = $options;
  101. foreach ($_options as $k => $option) {
  102. if ($option[$pidName] == $pid) {
  103. $value = ['id' => $k, 'title' => $option[$name]];
  104. unset($options[$k]);
  105. $value['children'] = formatTree($options, $name, $pidName, $k, $level + 1);
  106. $data[] = $value;
  107. }
  108. }
  109. return $data;
  110. }
  111. }
  112. if (!function_exists('formatCascaderData')) {
  113. function formatCascaderData(&$options, $name, $baseLevel = 0, $pidName = 'pid', $pid = 0, $level = 0, $data = []): array
  114. {
  115. $_options = $options;
  116. foreach ($_options as $k => $option) {
  117. if ($option[$pidName] == $pid) {
  118. $value = ['value' => $k, 'label' => $option[$name]];
  119. unset($options[$k]);
  120. $value['children'] = formatCascaderData($options, $name, $baseLevel, $pidName, $k, $level + 1);
  121. if (!count($value['children'])) unset($value['children']);
  122. $data[] = $value;
  123. }
  124. }
  125. return $data;
  126. }
  127. }
  128. /**
  129. * @function toMap 数组重新组装
  130. * @param array $data 数据
  131. * @param string $field key
  132. * @param string $value value default null
  133. * @return array
  134. * @author 张先生
  135. * @date 2020-04-01
  136. */
  137. if (!function_exists('toMap')) {
  138. function toMap(array $data, $field = 'id', $value = '')
  139. {
  140. $result = array();
  141. if (empty($data)) {
  142. return $result;
  143. }
  144. //开始处理数据
  145. foreach ($data as $item) {
  146. $val = $item;
  147. if (!empty($value)) {
  148. $val = $item[$value];
  149. }
  150. $result[$item[$field]] = $val;
  151. }
  152. return $result;
  153. }
  154. }
  155. /**
  156. * @function getUniqueListByArray 从数组中获取某个字段的值,重新拼装成新的一维数组
  157. * @param array $data 数据
  158. * @param string $field key
  159. * @return array
  160. * @author 张先生
  161. * @date 2020-04-01
  162. */
  163. if (!function_exists('getUniqueListByArray')) {
  164. function getUniqueListByArray(array $data, $field = 'id')
  165. {
  166. return array_unique(array_values(array_column($data, $field)));
  167. }
  168. }
  169. if (!function_exists('isPhone')) {
  170. function isPhone($test)
  171. {
  172. return !preg_match("/^1[3456789]{1}\d{9}$/", $test);
  173. }
  174. }
  175. if (!function_exists('getMonth')) {
  176. /**
  177. * 获取本季度 time
  178. * @param int|string $time
  179. * @param $ceil
  180. * @return array
  181. */
  182. function getMonth($time = '', $ceil = 0)
  183. {
  184. if ($ceil != 0)
  185. $season = ceil(date('n') / 3) - $ceil;
  186. else
  187. $season = ceil(date('n') / 3);
  188. $firstday = date('Y-m-01', mktime(0, 0, 0, ($season - 1) * 3 + 1, 1, date('Y')));
  189. $lastday = date('Y-m-t', mktime(0, 0, 0, $season * 3, 1, date('Y')));
  190. return array($firstday, $lastday);
  191. }
  192. }
  193. if (!function_exists('getModelTime')) {
  194. /**
  195. * @param BaseQuery $model
  196. * @param string $section
  197. * @param string $prefix
  198. * @param string $field
  199. * @return mixed
  200. * @author xaboy
  201. * @day 2020-04-29
  202. */
  203. function getModelTime(BaseQuery $model, string $section, $prefix = 'create_time', $field = '-')
  204. {
  205. if (!isset($section)) return $model;
  206. switch ($section) {
  207. case 'today':
  208. $model->whereBetween($prefix, [date('Y-m-d H:i:s', strtotime('today')), date('Y-m-d H:i:s', strtotime('tomorrow -1second'))]);
  209. break;
  210. case 'week':
  211. $model->whereBetween($prefix, [date('Y-m-d H:i:s', strtotime('this week 00:00:00')), date('Y-m-d H:i:s', strtotime('next week 00:00:00 -1second'))]);
  212. break;
  213. case 'month':
  214. $model->whereBetween($prefix, [date('Y-m-d H:i:s', strtotime('first Day of this month 00:00:00')), date('Y-m-d H:i:s', strtotime('first Day of next month 00:00:00 -1second'))]);
  215. break;
  216. case 'year':
  217. $model->whereBetween($prefix, [date('Y-m-d H:i:s', strtotime('this year 1/1')), date('Y-m-d H:i:s', strtotime('next year 1/1 -1second'))]);
  218. break;
  219. case 'yesterday':
  220. $model->whereBetween($prefix, [date('Y-m-d H:i:s', strtotime('yesterday')), date('Y-m-d H:i:s', strtotime('today -1second'))]);
  221. break;
  222. case 'quarter':
  223. list($startTime, $endTime) = getMonth();
  224. $model = $model->where($prefix, '>', $startTime);
  225. $model = $model->where($prefix, '<', $endTime);
  226. break;
  227. case 'lately7':
  228. $model = $model->where($prefix, 'between', [date('Y-m-d', strtotime("-7 day")), date('Y-m-d H:i:s')]);
  229. break;
  230. case 'lately30':
  231. $model = $model->where($prefix, 'between', [date('Y-m-d', strtotime("-30 day")), date('Y-m-d H:i:s')]);
  232. break;
  233. default:
  234. if (strstr($section, $field) !== false) {
  235. list($startTime, $endTime) = explode($field, $section);
  236. if (strlen($startTime) == 4) {
  237. $model->whereBetweenTime($prefix, date('Y-m-d H:i:s', strtotime($section)), date('Y-m-d H:i:s', strtotime($section . ' +1day -1second')));
  238. } else {
  239. if ($startTime == $endTime) {
  240. $model = $model->whereBetweenTime($prefix, date('Y-m-d 0:0:0', strtotime($startTime)), date('Y-m-d 23:59:59', strtotime($endTime)));
  241. } else {
  242. $model = $model->whereBetweenTime($prefix, date('Y-m-d H:i:s', strtotime($startTime)), date('Y-m-d H:i:s', strtotime($endTime . ' +1day -1second')));
  243. }
  244. }
  245. }
  246. break;
  247. }
  248. return $model;
  249. }
  250. }
  251. if (!function_exists('systemConfig')) {
  252. /**
  253. * 获取系统配置
  254. *
  255. * @param string|string[] $key
  256. * @return mixed
  257. * @author xaboy
  258. * @day 2020-05-08
  259. */
  260. function systemConfig($key)
  261. {
  262. return merchantConfig(0, $key);
  263. }
  264. }
  265. if (!function_exists('getDatesBetweenTwoDays')) {
  266. function getDatesBetweenTwoDays($startDate, $endDate)
  267. {
  268. $dates = [];
  269. if (strtotime($startDate) > strtotime($endDate)) {
  270. //如果开始日期大于结束日期,直接return 防止下面的循环出现死循环
  271. return $dates;
  272. } elseif ($startDate == $endDate) {
  273. //开始日期与结束日期是同一天时
  274. array_push($dates, date('m-d', strtotime($startDate)));
  275. return $dates;
  276. } else {
  277. array_push($dates, date('m-d', strtotime($startDate)));
  278. $currentDate = $startDate;
  279. do {
  280. $nextDate = date('Y-m-d', strtotime($currentDate . ' +1 days'));
  281. array_push($dates, date('m-d', strtotime($currentDate . ' +1 days')));
  282. $currentDate = $nextDate;
  283. } while ($endDate != $currentDate);
  284. return $dates;
  285. }
  286. }
  287. }
  288. if (!function_exists('getStartModelTime')) {
  289. function getStartModelTime(string $section)
  290. {
  291. switch ($section) {
  292. case 'today':
  293. case 'yesterday':
  294. return date('Y-m-d', strtotime($section));
  295. case 'week':
  296. return date('Y-m-d', strtotime('this week'));
  297. case 'month':
  298. return date('Y-m-d', strtotime('first Day of this month'));
  299. case 'year':
  300. return date('Y-m-d', strtotime('this year 1/1'));
  301. case 'quarter':
  302. list($startTime, $endTime) = getMonth();
  303. return $startTime;
  304. case 'lately7':
  305. return date('Y-m-d', strtotime("-7 day"));
  306. case 'lately30':
  307. return date('Y-m-d', strtotime("-30 day"));
  308. default:
  309. if (strstr($section, '-') !== false) {
  310. list($startTime, $endTime) = explode('-', $section);
  311. return date('Y-m-d H:i:s', strtotime($startTime));
  312. }
  313. return date('Y-m-d H:i:s');
  314. }
  315. }
  316. }
  317. if (!function_exists('merchantConfig')) {
  318. /**
  319. * 获取商户配置
  320. *
  321. * @param int $merId
  322. * @param string|string[] $key
  323. * @return mixed
  324. * @author xaboy
  325. * @day 2020-05-08
  326. */
  327. function merchantConfig(int $merId, $key)
  328. {
  329. $request = request();
  330. $make = app()->make(ConfigValueRepository::class);
  331. if (is_array($key)) {
  332. $_key = [];
  333. $cacheData = [];
  334. foreach ($key as $v) {
  335. if ($request->hasCache($merId, $v)) {
  336. $cacheData[$v] = $request->getCache($merId, $v);
  337. } else {
  338. $_key[] = $v;
  339. }
  340. }
  341. if (!count($_key)) return $cacheData;
  342. $data = $make->more($_key, $merId);
  343. $request->setCache($merId, $data);
  344. $data += $cacheData;
  345. } else {
  346. if ($request->hasCache($merId, $key)) {
  347. $data = $request->getCache($merId, $key);
  348. } else {
  349. $data = $make->get($key, $merId);
  350. $request->setCache($merId, $key, $data);
  351. }
  352. }
  353. return $data;
  354. }
  355. }
  356. if (!function_exists('systemGroupData')) {
  357. /**
  358. * 获取总后台组合数据配置
  359. *
  360. * @param string $key
  361. * @param int|null $page
  362. * @param int|null $limit
  363. * @return array
  364. * @author xaboy
  365. * @day 2020/5/27
  366. */
  367. function systemGroupData(string $key, ?int $page = null, ?int $limit = 10)
  368. {
  369. $make = app()->make(GroupDataRepository::class);
  370. return $make->groupData($key, 0, $page, $limit);
  371. }
  372. }
  373. if (!function_exists('merchantGroupData')) {
  374. /**
  375. * 获取商户后台组合数据配置
  376. *
  377. * @param int $merId
  378. * @param string $key
  379. * @param int|null $page
  380. * @param int|null $limit
  381. * @return array
  382. * @author xaboy
  383. * @day 2020/5/27
  384. */
  385. function merchantGroupData(int $merId, string $key, ?int $page = null, ?int $limit = 10)
  386. {
  387. $make = app()->make(GroupDataRepository::class);
  388. return $make->groupData($key, $merId, $page, $limit);
  389. }
  390. }
  391. if (!function_exists('filter_emoji')) {
  392. // 过滤掉emoji表情
  393. function filter_emoji($str)
  394. {
  395. $str = preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换
  396. '/./u',
  397. function (array $match) {
  398. return strlen($match[0]) >= 4 ? '' : $match[0];
  399. },
  400. $str);
  401. return $str;
  402. }
  403. }
  404. if (!function_exists('setHttpType')) {
  405. /**
  406. * TODO 修改 https 和 http 移动到common
  407. * @param $url $url 域名
  408. * @param int $type 0 返回https 1 返回 http
  409. * @return string
  410. */
  411. function setHttpType($url, $type = 0)
  412. {
  413. $domainTop = substr($url, 0, 5);
  414. if ($type) {
  415. if ($domainTop == 'https') $url = 'http' . substr($url, 5, strlen($url));
  416. } else {
  417. if ($domainTop != 'https') $url = 'https:' . substr($url, 5, strlen($url));
  418. }
  419. return $url;
  420. }
  421. }
  422. if (!function_exists('remoteImage')) {
  423. /**
  424. * TODO 获取小程序二维码是否生成
  425. * @param $url
  426. * @return array
  427. */
  428. function remoteImage($url)
  429. {
  430. $curl = curl_init();
  431. curl_setopt($curl, CURLOPT_URL, $url);
  432. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  433. $result = curl_exec($curl);
  434. $result = json_decode($result, true);
  435. if (is_array($result)) return ['status' => false, 'msg' => $result['errcode'] . '---' . $result['errmsg']];
  436. return ['status' => true];
  437. }
  438. }
  439. if (!function_exists('image_to_base64')) {
  440. /**
  441. * 获取图片转为base64
  442. * @param string $avatar
  443. * @return bool|string
  444. */
  445. function image_to_base64($avatar = '', $timeout = 9)
  446. {
  447. try {
  448. $url = parse_url($avatar);
  449. $url = $url['host'];
  450. $header = [
  451. 'User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:45.0) Gecko/20100101 Firefox/45.0',
  452. 'Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
  453. 'Accept-Encoding: gzip, deflate, br',
  454. 'accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
  455. 'Host:' . $url
  456. ];
  457. $dir = pathinfo($url);
  458. $host = $dir['dirname'];
  459. $refer = $host . '/';
  460. $curl = curl_init();
  461. curl_setopt($curl, CURLOPT_REFERER, $refer);
  462. curl_setopt($curl, CURLOPT_URL, $avatar);
  463. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  464. curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  465. curl_setopt($curl, CURLOPT_ENCODING, 'gzip');
  466. curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $timeout);
  467. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  468. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  469. $data = curl_exec($curl);
  470. $code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
  471. curl_close($curl);
  472. if ($code == 200) {
  473. return "data:image/jpeg;base64," . base64_encode($data);
  474. } else {
  475. return false;
  476. }
  477. } catch (Exception $e) {
  478. return false;
  479. }
  480. }
  481. }
  482. if (!function_exists('put_image')) {
  483. /**
  484. * 获取图片转为base64
  485. * @param string $avatar
  486. * @return bool|string
  487. */
  488. function put_image($url, $filename = '')
  489. {
  490. if ($url == '') {
  491. return false;
  492. }
  493. try {
  494. if ($filename == '') {
  495. $ext = pathinfo($url);
  496. if ($ext['extension'] != "jpg" && $ext['extension'] != "png" && $ext['extension'] != "jpeg") {
  497. return false;
  498. }
  499. $filename = time() . "." . $ext['extension'];
  500. }
  501. //文件保存路径
  502. ob_start();
  503. readfile($url);
  504. $img = ob_get_contents();
  505. ob_end_clean();
  506. $path = 'public/uploads/qrcode';
  507. $fp2 = fopen($path . '/' . $filename, 'a');
  508. fwrite($fp2, $img);
  509. fclose($fp2);
  510. return $path . '/' . $filename;
  511. } catch (Exception $e) {
  512. return false;
  513. }
  514. }
  515. }
  516. if (!function_exists('path_to_url')) {
  517. /**
  518. * 路径转url路径
  519. * @param $path
  520. * @return string
  521. */
  522. function path_to_url($path)
  523. {
  524. return trim(str_replace(DIRECTORY_SEPARATOR, '/', $path), '.');
  525. }
  526. }
  527. if (!function_exists('tidy_url')) {
  528. /**
  529. * 路径转url路径
  530. * @param $url
  531. * @param int $http
  532. * @param string $site
  533. * @return string
  534. */
  535. function tidy_url($url, $http = null, $site = null)
  536. {
  537. if (!$site) {
  538. $site = systemConfig('site_url');
  539. }
  540. $url = path_to_url($url);
  541. if (strpos($url, 'http') === false)
  542. $url = rtrim($site, '/') . '/' . ltrim($url, '/');
  543. if (is_null($http)) {
  544. $http = (parse_url($site)['scheme'] ?? '') == 'https' ? 0 : 1;
  545. }
  546. $url = set_http_type($url, $http);
  547. return $url;
  548. }
  549. }
  550. if (!function_exists('curl_file_exist')) {
  551. /**
  552. * CURL 检测远程文件是否在
  553. * @param $url
  554. * @return bool
  555. */
  556. function curl_file_exist($url)
  557. {
  558. $ch = curl_init();
  559. try {
  560. curl_setopt($ch, CURLOPT_URL, $url);
  561. curl_setopt($ch, CURLOPT_HEADER, 1);
  562. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  563. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
  564. $contents = curl_exec($ch);
  565. if (preg_match("/404/", $contents)) return false;
  566. if (preg_match("/403/", $contents)) return false;
  567. return true;
  568. } catch (Exception $e) {
  569. return false;
  570. }
  571. }
  572. }
  573. if (!function_exists('set_http_type')) {
  574. /**
  575. * 修改 https 和 http
  576. * @param $url $url 域名
  577. * @param int $type 0 返回https 1 返回 http
  578. * @return string
  579. */
  580. function set_http_type($url, $type = 0)
  581. {
  582. $domainTop = substr($url, 0, 5);
  583. if ($type) {
  584. if ($domainTop == 'https') $url = 'http' . substr($url, 5, strlen($url));
  585. } else {
  586. if ($domainTop != 'https') $url = 'https:' . substr($url, 5, strlen($url));
  587. }
  588. return $url;
  589. }
  590. }
  591. if (!function_exists('setSharePoster')) {
  592. /**
  593. * TODO 生成分享二维码图片
  594. * @param array $config
  595. * @param $path
  596. * @return array|bool|string
  597. * @throws Exception
  598. */
  599. function setSharePoster($config, $path)
  600. {
  601. $imageDefault = array(
  602. 'left' => 0,
  603. 'top' => 0,
  604. 'right' => 0,
  605. 'bottom' => 0,
  606. 'width' => 100,
  607. 'height' => 100,
  608. 'opacity' => 100
  609. );
  610. $textDefault = array(
  611. 'text' => '',
  612. 'left' => 0,
  613. 'top' => 0,
  614. 'fontSize' => 32, //字号
  615. 'fontColor' => '255,255,255', //字体颜色
  616. 'angle' => 0,
  617. );
  618. $background = $config['background'];//海报最底层得背景
  619. if (substr($background, 0, 1) === '/') {
  620. $background = substr($background, 1);
  621. }
  622. $backgroundInfo = getimagesize($background);
  623. $background = imagecreatefromstring(file_get_contents($background));
  624. $backgroundWidth = $backgroundInfo[0]; //背景宽度
  625. $backgroundHeight = $backgroundInfo[1]; //背景高度
  626. $imageRes = imageCreatetruecolor($backgroundWidth, $backgroundHeight);
  627. $color = imagecolorallocate($imageRes, 0, 0, 0);
  628. imagefill($imageRes, 0, 0, $color);
  629. imagecopyresampled($imageRes, $background, 0, 0, 0, 0, imagesx($background), imagesy($background), imagesx($background), imagesy($background));
  630. if (!empty($config['image'])) {
  631. foreach ($config['image'] as $key => $val) {
  632. $val = array_merge($imageDefault, $val);
  633. $info = getimagesize($val['url']);
  634. $function = 'imagecreatefrom' . image_type_to_extension($info[2], false);
  635. if ($val['stream']) {
  636. $info = getimagesizefromstring($val['url']);
  637. $function = 'imagecreatefromstring';
  638. }
  639. $res = $function($val['url']);
  640. $resWidth = $info[0];
  641. $resHeight = $info[1];
  642. $canvas = imagecreatetruecolor($val['width'], $val['height']);
  643. imagefill($canvas, 0, 0, $color);
  644. imagecopyresampled($canvas, $res, 0, 0, 0, 0, $val['width'], $val['height'], $resWidth, $resHeight);
  645. $val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) - $val['width'] : $val['left'];
  646. $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) - $val['height'] : $val['top'];
  647. imagecopymerge($imageRes, $canvas, $val['left'], $val['top'], $val['right'], $val['bottom'], $val['width'], $val['height'], $val['opacity']);//左,上,右,下,宽度,高度,透明度
  648. }
  649. }
  650. if (isset($config['text']) && !empty($config['text'])) {
  651. foreach ($config['text'] as $key => $val) {
  652. $val = array_merge($textDefault, $val);
  653. list($R, $G, $B) = explode(',', $val['fontColor']);
  654. $fontColor = imagecolorallocate($imageRes, $R, $G, $B);
  655. $val['left'] = $val['left'] < 0 ? $backgroundWidth - abs($val['left']) : $val['left'];
  656. $val['top'] = $val['top'] < 0 ? $backgroundHeight - abs($val['top']) : $val['top'];
  657. imagettftext($imageRes, $val['fontSize'], $val['angle'], $val['left'], $val['top'], $fontColor, $val['fontPath'], $val['text']);
  658. }
  659. }
  660. ob_start();
  661. imagejpeg($imageRes);
  662. imagedestroy($imageRes);
  663. $res = ob_get_contents();
  664. ob_end_clean();
  665. $key = substr(md5(rand(0, 9999)), 0, 5) . date('YmdHis') . rand(0, 999999) . '.jpg';
  666. $uploadType = (int)systemConfig('upload_type') ?: 1;
  667. $upload = UploadService::create($uploadType);
  668. $res = $upload->to($path)->validate()->stream($res, $key);
  669. if ($res === false) {
  670. return $upload->getError();
  671. } else {
  672. $info = $upload->getUploadInfo();
  673. $info['image_type'] = $uploadType;
  674. return $info;
  675. }
  676. }
  677. }
  678. if (!function_exists('getTimes')) {
  679. function getTimes()
  680. {
  681. $dates = [];
  682. for ($i = 0; $i <= 24; $i++) {
  683. for ($j = 0; $j < 60; $j++) {
  684. $dates[] = sprintf('%02.d', $i) . ':' . sprintf('%02.d', $j);
  685. }
  686. }
  687. return $dates;
  688. }
  689. }
  690. if (!function_exists('monday')) {
  691. /**
  692. * 获取周一
  693. *
  694. * @param null $time
  695. * @return false|string
  696. * @author xaboy
  697. * @day 2020/6/22
  698. */
  699. function monday($time = null)
  700. {
  701. return date('Y-m-d', strtotime('Sunday -6 day', $time ?: time()));
  702. }
  703. }
  704. if (!function_exists('orderLock')) {
  705. /**
  706. * @param string $name
  707. * @return Lock
  708. * @author xaboy
  709. * @day 2020/8/25
  710. */
  711. function makeLock($name = 'default'): Lock
  712. {
  713. return $GLOBALS['_swoole_order_lock'][$name];
  714. }
  715. }
  716. if (!function_exists('get_crmeb_version')) {
  717. /**
  718. * 获取CRMEB系统版本号
  719. * @param string $default
  720. * @return string
  721. */
  722. function get_crmeb_version($default = 'v1.0.0')
  723. {
  724. try {
  725. $version = parse_ini_file(app()->getRootPath() . '.version');
  726. return $version['version'] ?? $default;
  727. } catch (Throwable $e) {
  728. return $default;
  729. }
  730. }
  731. }
  732. if (!function_exists('update_crmeb_compiled')) {
  733. /**
  734. * 获取CRMEB系统版本号
  735. * @param string $default
  736. * @return string
  737. */
  738. function update_crmeb_compiled($default = 'v1.0.0')
  739. {
  740. $compiled = [
  741. '7.1' => 'compiled71',
  742. '7.2' => 'compiled72',
  743. '7.3' => 'compiled73',
  744. ];
  745. $phpv = @phpversion();
  746. $phpvs = substr($phpv, 0, 3);
  747. $key = $compiled[$phpvs] ?? '';
  748. if (!$key)
  749. return false;
  750. $root = app()->getRootPath();
  751. $compiledPath = $root . 'install/compiled';
  752. $file = $root . 'install/compiled/' . $key . '.zip';
  753. $toPath = $root . 'crmeb/basic';
  754. $toConfigPath = $root . 'config/crmeb.php';
  755. try {
  756. if (is_file($file)) {
  757. $zip = new ZipArchive();
  758. if ($zip->open($file) === true) {
  759. $zip->extractTo($compiledPath . '/');
  760. $zip->close();
  761. }
  762. if (is_dir($compiledPath . '/basic')) {
  763. if (is_dir($toPath) || mkdir($toPath, 0777) || is_dir($toPath)) {
  764. foreach (glob($compiledPath . '/basic/*') as $item) {
  765. @rename($item, $toPath . '/' . pathinfo($item, PATHINFO_BASENAME));
  766. }
  767. }
  768. @rmdir($compiledPath . '/basic');
  769. }
  770. if (is_file($compiledPath . '/crmeb.php')) {
  771. @rename($compiledPath . '/crmeb.php', $toConfigPath);
  772. }
  773. }
  774. } catch (\Exception $exception) {
  775. return false;
  776. }
  777. return true;
  778. }
  779. }
  780. if (!function_exists('attr_format')) {
  781. /**
  782. * 格式化属性
  783. * @param $arr
  784. * @return array
  785. */
  786. function attr_format($arr)
  787. {
  788. $data = [];
  789. $res = [];
  790. $count = count($arr);
  791. if ($count > 1) {
  792. for ($i = 0; $i < $count - 1; $i++) {
  793. if ($i == 0) $data = $arr[$i]['detail'];
  794. //替代变量1
  795. $rep1 = [];
  796. foreach ($data as $v) {
  797. foreach ($arr[$i + 1]['detail'] as $g) {
  798. //替代变量2
  799. $rep2 = ($i != 0 ? '' : $arr[$i]['value'] . '_$_') . $v . '-$-' . $arr[$i + 1]['value'] . '_$_' . $g;
  800. $tmp[] = $rep2;
  801. if ($i == $count - 2) {
  802. foreach (explode('-$-', $rep2) as $k => $h) {
  803. //替代变量3
  804. $rep3 = explode('_$_', $h);
  805. //替代变量4
  806. $rep4['detail'][$rep3[0]] = isset($rep3[1]) ? $rep3[1] : '';
  807. }
  808. if($count == count($rep4['detail']))
  809. $res[] = $rep4;
  810. }
  811. }
  812. }
  813. $data = isset($tmp) ? $tmp : [];
  814. }
  815. } else {
  816. $dataArr = [];
  817. foreach ($arr as $k => $v) {
  818. foreach ($v['detail'] as $kk => $vv) {
  819. $dataArr[$kk] = $v['value'] . '_' . $vv;
  820. $res[$kk]['detail'][$v['value']] = $vv;
  821. }
  822. }
  823. $data[] = implode('-', $dataArr);
  824. }
  825. return [$data, $res];
  826. }
  827. }
  828. if (!function_exists('not_empty_check')) {
  829. /**
  830. * 非空验证
  831. * @param $param
  832. * @return bool
  833. */
  834. function not_empty_check($param)
  835. {
  836. if (is_array($param)) {
  837. return !(count($param) <= 0);
  838. } else {
  839. if ($param == '') {
  840. return false;
  841. }
  842. if ($param == null) {
  843. return false;
  844. }
  845. return true;
  846. }
  847. }
  848. }
  849. if (!function_exists('mobile_check')) {
  850. /**
  851. * 电话验证
  852. * @param $param
  853. * @return bool
  854. */
  855. function mobile_check($param)
  856. {
  857. if (!preg_match("/^1[3456789]\d{9}$/", $param)) {
  858. return false;
  859. } else {
  860. return true;
  861. }
  862. }
  863. }
  864. if (!function_exists('do_request')) {
  865. /**
  866. * CURL 请求接口
  867. * @param string $url 请求地址
  868. * @param array $data 请求参数
  869. * @param array $header 请求头
  870. * @param bool $post true:post请求 false:get请求
  871. * @param bool $json post请求时 请求数据打包方式是否为json
  872. * @param int $format 数据打包为json格式时打包的格式值 来自json_encode
  873. * @param bool $form post请求时 请求数据是否为表单 同时为false时为http提交 优先级高于json
  874. * @return bool|false|string
  875. */
  876. function do_request($url, $data, $header = null, $post = true, $json = false, $format = 0, $form = false)
  877. {
  878. $curl = curl_init();
  879. curl_setopt($curl, CURLOPT_URL, $url);
  880. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  881. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  882. if ($post) {
  883. curl_setopt($curl, CURLOPT_POST, 1);
  884. if (!$json && !$form) {
  885. curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($data));
  886. } else if ($json && !$form) {
  887. curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data, $format));
  888. } else {
  889. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  890. }
  891. }
  892. curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
  893. if ($header) {
  894. curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
  895. curl_setopt($curl, CURLOPT_HEADER, 0);
  896. }
  897. $result = curl_exec($curl);
  898. if (curl_errno($curl)) {
  899. return json_encode(['status' => curl_errno($curl), 'msg' => '请求失败']);
  900. }
  901. curl_close($curl);
  902. return $result;
  903. }
  904. }
  905. if (!function_exists('get_distance')) {
  906. function get_distance($lat1, $lng1, $lat2, $lng2)
  907. {
  908. $EARTH_RADIUS = 6378137;
  909. $radLat1 = rad($lat1);
  910. $radLat2 = rad($lat2);
  911. $a = $radLat1 - $radLat2;
  912. $b = rad($lng1) - rad($lng2);
  913. $s = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2)));
  914. $s = $s * $EARTH_RADIUS;
  915. $s = round($s * 10000) / 10000;
  916. return $s;
  917. }
  918. }
  919. if (!function_exists('rad')) {
  920. function rad($d)
  921. {
  922. return $d * M_PI / 180.0;
  923. }
  924. }
  925. if (!function_exists('file_debug')) {
  926. /**
  927. * @param $file
  928. * @param $title
  929. * @param $data
  930. * @param int $step
  931. * @return void
  932. */
  933. function file_debug($file, $title, $data, $step = 0)
  934. {
  935. file_put_contents($file, "【" . date('Y-m-d H:i:s') . "】{$title}:" . ($step > 0 ? ('(step' . $step . ')') : '') . json_encode($data) . PHP_EOL, FILE_APPEND);
  936. }
  937. }